github.com/bazelbuild/remote-apis-sdks@v0.0.0-20240425170053-8a36686a6350/go/pkg/symlinkopts/opts.go (about) 1 // Package symlinkopts provides an efficient interface to create unambiguous symlink options. 2 package symlinkopts 3 4 import ( 5 "fmt" 6 "strings" 7 ) 8 9 // Options represents a set of options for handling symlinks. The zero value is equivalent to skipping all symlinks. 10 type Options struct { 11 preserve bool 12 noDangling bool 13 includeTarget bool 14 resolve bool 15 resolveExternal bool 16 } 17 18 // String returns a string representation of the options. 19 // 20 // The string has at most five letters: 21 // 22 // P for Preserve 23 // N for No Dangling 24 // I for Include Target 25 // R for Replace 26 // E for Replace External 27 func (o Options) String() string { 28 var b strings.Builder 29 if o.preserve { 30 fmt.Fprint(&b, "P") 31 } 32 if o.noDangling { 33 fmt.Fprint(&b, "N") 34 } 35 if o.includeTarget { 36 fmt.Fprint(&b, "I") 37 } 38 if o.resolve { 39 fmt.Fprint(&b, "R") 40 } 41 if o.resolveExternal { 42 fmt.Fprint(&b, "E") 43 } 44 return b.String() 45 } 46 47 // Preserve returns true if the options include the corresponding property. 48 func (o Options) Preserve() bool { 49 return o.preserve 50 } 51 52 // NoDangling returns true if the options include the corresponding property. 53 func (o Options) NoDangling() bool { 54 return o.noDangling 55 } 56 57 // IncludeTarget returns true if the options include the corresponding property. 58 func (o Options) IncludeTarget() bool { 59 return o.includeTarget 60 } 61 62 // Resolve returns true if the options include the corresponding property. 63 func (o Options) Resolve() bool { 64 return o.resolve 65 } 66 67 // ResolveExternal returns true if the options include the corresponding property. 68 func (o Options) ResolveExternal() bool { 69 return o.resolveExternal 70 } 71 72 // Skip returns true if the options indicate that symlinks should be skipped. 73 func (o Options) Skip() bool { 74 return !o.preserve && !o.noDangling && !o.includeTarget && !o.resolve && !o.resolveExternal 75 } 76 77 // ResolveAlways return the correct set of options to always resolve symlinks. 78 // 79 // This implies that symlinks are followed and no dangling symlinks are allowed. 80 // Every symlink will be replaced by its target. For example, if foo/bar was a symlink 81 // to the regular file baz, then foo/bar will become a regular file with the content of baz. 82 func ResolveAlways() Options { 83 return Options{ 84 resolve: true, 85 resolveExternal: true, 86 includeTarget: true, 87 noDangling: true, 88 } 89 } 90 91 // ResolveExternalOnly returns the correct set of options to only resolve symlinks 92 // if the target is outside the root directory. Otherwise, the symlink is preserved. 93 // 94 // This implies that all symlinks are followed, therefore, no dangling links are allowed. 95 // Otherwise, it's not possible to guarantee that all required files are under the root. 96 // Targets of non-external symlinks are not included. 97 func ResolveExternalOnly() Options { 98 return Options{ 99 preserve: true, 100 resolveExternal: true, 101 noDangling: true, 102 } 103 } 104 105 // ResolveExternalOnlyWithTarget is like ResolveExternalOnly but targets of non-external symlinks are included. 106 func ResolveExternalOnlyWithTarget() Options { 107 return Options{ 108 preserve: true, 109 resolveExternal: true, 110 includeTarget: true, 111 noDangling: true, 112 } 113 } 114 115 // PreserveWithTarget returns the correct set of options to preserve all symlinks and include the targets. 116 // 117 // This implies that dangling links are not allowed. 118 func PreserveWithTarget() Options { 119 return Options{ 120 preserve: true, 121 includeTarget: true, 122 noDangling: true, 123 } 124 } 125 126 // PreserveNoDangling returns the correct set of options to preserve all symlinks without targets. 127 // 128 // Targets need to be explicitly included. 129 // Dangling links are not allowed. 130 func PreserveNoDangling() Options { 131 return Options{ 132 preserve: true, 133 noDangling: true, 134 } 135 } 136 137 // PreserveAllowDangling returns the correct set of options to preserve all symlinks without targets. 138 // 139 // Targets need to be explicitly included. 140 // Dangling links are allowed. 141 func PreserveAllowDangling() Options { 142 return Options{preserve: true} 143 } 144 145 // Skip is the zero value for Options which is equivalent to skipping all symlinks (as if they did not exist). 146 func Skip() Options { 147 return Options{} 148 }