MCPcopy Create free account
hub / github.com/coder/envbox / SameDirSymlinks

Function SameDirSymlinks

xunix/gpu.go:204–268  ·  view source on GitHub ↗

SameDirSymlinks returns all links in the same directory as `target` that point to target, either indirectly or directly. Only symlinks in the same directory as `target` are considered.

(afs FS, target string)

Source from the content-addressed store, hash-verified

202// point to target, either indirectly or directly. Only symlinks in the same
203// directory as `target` are considered.
204func SameDirSymlinks(afs FS, target string) ([]string, error) {
205 // Get the list of files in the directory of the target.
206 fis, err := afero.ReadDir(afs, filepath.Dir(target))
207 if err != nil {
208 return nil, xerrors.Errorf("read dir %q: %w", filepath.Dir(target), err)
209 }
210
211 // Do an initial pass to map all symlinks to their destinations.
212 allLinks := make(map[string]string)
213 for _, fi := range fis {
214 // Ignore non-symlinks.
215 if fi.Mode()&os.ModeSymlink == 0 {
216 continue
217 }
218
219 absPath := filepath.Join(filepath.Dir(target), fi.Name())
220 link, err := afs.Readlink(filepath.Join(filepath.Dir(target), fi.Name()))
221 if err != nil {
222 return nil, xerrors.Errorf("readlink %q: %w", fi.Name(), err)
223 }
224
225 if !filepath.IsAbs(link) {
226 link = filepath.Join(filepath.Dir(target), link)
227 }
228 allLinks[absPath] = link
229 }
230
231 // Now we can start checking for symlinks that point to the target.
232 var (
233 found = make([]string, 0)
234 // Set an arbitrary upper limit to prevent infinite loops.
235 maxIterations = 10
236 )
237 for range maxIterations {
238 var foundThisTime bool
239 for linkName, linkDest := range allLinks {
240 // Ignore symlinks that point outside of target's directory.
241 if filepath.Dir(linkName) != filepath.Dir(target) {
242 continue
243 }
244
245 // If the symlink points to the target, add it to the list.
246 if linkDest == target {
247 if !slices.Contains(found, linkName) {
248 found = append(found, linkName)
249 foundThisTime = true
250 }
251 }
252
253 // If the symlink points to another symlink that we already determined
254 // points to the target, add it to the list.
255 if slices.Contains(found, linkDest) {
256 if !slices.Contains(found, linkName) {
257 found = append(found, linkName)
258 foundThisTime = true
259 }
260 }
261 }

Callers 2

Test_SameDirSymlinksFunction · 0.92
GPUsFunction · 0.85

Calls 2

ErrorfMethod · 0.65
ReadlinkMethod · 0.65

Tested by 1

Test_SameDirSymlinksFunction · 0.74