I wrote a little package called cdup that walks a directory and each of its ancestors looking for a file/dir. This is useful e.g. to find the root of a git dir (look for .git) or a Go module (look for go.mod).
I aimed to write it using fs.FS and use os.DirFS as a bridge to the OS filesystem as needed, perhaps inside a wrapper function.
I may just be holding it wrong, but I encountered a few surprising bumps.
A typical invocation is cdup.Find(pwd, ".git"). The obvious but wrong translation of this is cdup.FindIn(os.DirFS("/"), pwd, ".git").
What is the correct root path to pass to os.DirFS on Windows? filepath.VolumeName seems like the right API to use. (I think?)
Then we must convert pwd to a relative path using filepath.Rel. On Windows, we also need to call filepath.ToSlash.
So I believe that the correct code is something like:
root := "/"
if vol := filepath.VolumeName(dir); vol != "" {
root = vol
}
rel := filepath.Rel(root, dir)
rel = filepath.ToSlash(rel)
cdup.FindIn(os.DirFS(root), rel, ".git")
This is a surprising amount of non-obvious work for what seems like it should be a trivial bridge between fs.FS and the OS filesystem.
I'm not sure exactly what the fix should be here. Docs/examples? New package filepath API to get the OS fs root for a path? New package os API to construct a root filesystem (and expose the root for use with filepath.Rel)?
I wrote a little package called cdup that walks a directory and each of its ancestors looking for a file/dir. This is useful e.g. to find the root of a git dir (look for
.git) or a Go module (look forgo.mod).I aimed to write it using
fs.FSand useos.DirFSas a bridge to the OS filesystem as needed, perhaps inside a wrapper function.I may just be holding it wrong, but I encountered a few surprising bumps.
A typical invocation is
cdup.Find(pwd, ".git"). The obvious but wrong translation of this iscdup.FindIn(os.DirFS("/"), pwd, ".git").What is the correct root path to pass to
os.DirFSon Windows?filepath.VolumeNameseems like the right API to use. (I think?)Then we must convert
pwdto a relative path usingfilepath.Rel. On Windows, we also need to callfilepath.ToSlash.So I believe that the correct code is something like:
This is a surprising amount of non-obvious work for what seems like it should be a trivial bridge between fs.FS and the OS filesystem.
I'm not sure exactly what the fix should be here. Docs/examples? New package filepath API to get the OS fs root for a path? New package os API to construct a root filesystem (and expose the root for use with filepath.Rel)?