-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add helper function Dirent.FollowSymlink() #36
base: master
Are you sure you want to change the base?
Conversation
Add Dirent.FollowSymlink()
Add Dirent.Path() ; Use Dirent.path in Dirent.FollowSymlink()
…nt.IsSymlink() == false
Update Dirent.FollowSymlink() to return the original Dirent when Dire…
Update all direct struct initializations for &Dirent{} with path
Can you provide a mini file system example that led you down the path of adding this functionality? There is nothing in the new Callback: func(osPathname string, de *godirwalk.Dirent) error {
// resolve any symlinks we encounter to their linked filepath
if de.IsSymlink() {
resolvedPath, err := filepath.EvalSymlinks(osPathname)
if err != nil {
return nil, err
}
absPath, err := filepath.Abs(resolvedPath)
if err != nil {
return nil, err
}
de, err = NewDirent(absPath)
if err != nil {
return nil, err
}
}
log.WithFields(log.Fields{
"path": path,
"IsRegular": de.IsRegular(),
"IsDir": de.IsDir(),
"IsSymlink": de.IsSymlink(),
}).Info("")
return nil
}, Or implemented as a function in a given program. func NewDirentByFollowingSymlinks(osPathname string, de *godirwalk.Dirent) (*godirwalk.Dirent, error) {
resolvedPath, err := filepath.EvalSymlinks(osPathname)
if err != nil {
return nil, err
}
absPath, err := filepath.Abs(resolvedPath)
if err != nil {
return nil, err
}
return NewDirent(absPath)
} Then in the Callback, you could call this function: Callback: func(osPathname string, de *godirwalk.Dirent) error {
// resolve any symlinks we encounter to their linked filepath
if de.IsSymlink() {
var err error
de, err = NewDirentByFollowingSymlinks(osPathname, de)
if err != nil {
return nil, err
}
}
log.WithFields(log.Fields{
"path": path,
"IsRegular": de.IsRegular(),
"IsDir": de.IsDir(),
"IsSymlink": de.IsSymlink(),
}).Info("")
return nil
}, I have two primary and two minor concerns with adding this into godirwalk right now. My first concern is expanding the API without my clearly understanding the benefit of doing so, especially in light of the two alternate solutions I have provided above. My second concern flows from the first. If we added My third concern is minor, but storing the entire pathname in each Finally my final concern is some of the API calling semantics of the proposed |
Thanks for the review. I'll address the minor concerns first about memory and relative path:
Why should we add this feature at all? The use case that led me to this library is being able to walk filepaths in golang with the ability to interact with symlinks. This library is the most full featured and user friendly, and I think this additional API fits with godirwalk's calling card of "interacts with symlinks". Edit: I also originally thought that I could write an internal function that extends this api only in my one project, but I want to share this ability with the world and share in the user friendly functionality. Just knowing that a path is a symlink is great, because now we can interact with it, and being able to directly interact with symlinks as a first class citizen of this library is a cherry on top in my opinion. And that's why I sought to add this feature to godirwalk. Clarification:
What do you mean by this where someone would only want to visit the symlink on the resolved path? In my understanding symlinks (as they're soft links) represent a relative path to another path on the system that must have an absolute representation. These symlinks could be relative to another relative path to the originating path used in the call to |
Added a helper function for handling symlinks to Dirent. This function can be used as follows:
This is useful because without following the symlink via filepath.EvalSymlinks() and creating a new Dirent, then the original Dirent on some systems will return de.IsSymlink() // true and de.IsDir() // false and de.IsRegular() // false, which can cause accidental mistakes. By using de.FollowSymlink() you can then be confident that de.IsDir() and de.IsRegular() will now return stat information about the followed symlink.
This PR also includes adding
Dirent.Path()
andDirent.path
to support absolute paths when following the symlink.Note: There exists a subtle flaw in that you can't reassign and initialize a variable in the same := or = in golang, so instead these must be separated out. :/ The other option is to pre-declare both variables such as var err error or adding it to the function proto.