Skip to content
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

Rename files in cache too if they exist #3480

Closed

Conversation

darthShadow
Copy link
Member

@darthShadow darthShadow commented Aug 26, 2019

What is the purpose of this change?

Files in cache should be renamed too along with renames on the remote

Was the change discussed in an issue or in the forum before?

#2907

Checklist

  • I have read the contribution guidelines.
  • I have added tests for all changes in this PR if appropriate.
  • I have added documentation for the changes if appropriate.
  • All commit messages are in house style.
  • I'm done, this Pull Request is ready for review :-)

@darthShadow
Copy link
Member Author

darthShadow commented Aug 26, 2019

I still need to handle cases where the file is moved into or out of a directory. Done.

vfs/cache.go Show resolved Hide resolved
vfs/cache.go Show resolved Hide resolved
Copy link
Member

@ncw ncw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great thing to do - thanks for tackling this.

I put some notes inline.

I think we should try to write a test for this, then we'll be sure it works properly on all OSes - what do you think?

vfs/cache.go Outdated
return true
}
}
if err = os.Link(osOldPath, osNewPath); err == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use os.Rename always? Isn't it equivalent to Link+Remove?

os.Link doesn't work on all windows fileystems (eg FAT)

os.Rename may have troubles renaming over an existing file on Windows.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not much of difference either way. Didn't try it on windows, if it doesn't work there, I will just remove the section that tries to link.

As for rename, what do you think would be better? Remove the existing destination or do nothing and print an error log?

@@ -270,12 +270,63 @@ func (c *cache) exists(name string) bool {
if err != nil {
return false
}
if fi.IsDir() {
// checks for non-regular files (e.g. directories, symlinks, devices, etc.)
if !fi.Mode().IsRegular() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

vfs/cache.go Outdated
return false
}
return true
}

// renames the file in cache
func (c *cache) rename(name string, newName string) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be more go style to return an annotated error, than a boolean here I think...

vfs/cache.go Outdated
}
if !sfi.Mode().IsRegular() {
// cannot copy non-regular files (e.g., directories, symlinks, devices, etc.)
fs.Errorf("rename: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... so instead of fs.Errorf(...); return false

do

return errors.Errorf("rename: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String()))

vfs/cache.go Outdated
dfi, err := os.Stat(osNewPath)
if err != nil {
if !os.IsNotExist(err) {
fs.Errorf(name, "rename: Failed to stat destination: %v", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and likewise wrap the errors when you have them so this should be

return errors.Wrap(err, "rename: Failed to stat destination")

vfs/file.go Outdated

// Rename in the cache too if it exists
if f.d.vfs.Opt.CacheMode >= CacheModeWrites && f.d.vfs.cache.exists(f.Path()) {
if ok := f.d.vfs.cache.rename(f.Path(), newPath); !ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then this should be something like

err = f.d.vfs.cache.rename(f.Path(), newPath)
if err != nil {
    fs.Infof(f.Path(), "File.Rename failed in Cache: %v", err)
}

vfs/cache.go Outdated
osNewPath := c.toOSPath(newName)
sfi, err := os.Stat(osOldPath)
if err != nil {
return false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return errors.Wrap(err, "rename: source file")

fs.Errorf("rename: non-regular destination file: %s (%q)", dfi.Name(), dfi.Mode().String())
return false
}
if os.SameFile(sfi, dfi) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How likely do you think os.SameFile is to return true here? I'm struggling to see how it might happen

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thought it better to be safe than have an issue afterwards in case it ever happens. This avoids silent failures from rename in case both the source & destination point to the same file via links.

Source: https://forum.golangbridge.org/t/os-rename-and-hard-link-overwrite/7838

@darthShadow
Copy link
Member Author

Thanks for the review. As for the tests, I may need some help with that. Haven't written any tests before 😅

@ncw
Copy link
Member

ncw commented Aug 26, 2019

Thanks for the review. As for the tests, I may need some help with that. Haven't written any tests before

Take a look in the cache_test.go file there is a fair amount of machinery in there. You'd write a test for the rename function in there.

It would be good if we could also adjust the rename file test to check the correct things are happening in the cache but that might be a bit trickier.

func TestDirRename(t *testing.T) {

@ncw
Copy link
Member

ncw commented Sep 2, 2019

How are you doing with this? Need help finishing it off?

@darthShadow
Copy link
Member Author

Need to get some time together to finish off the tests. Will be updating it by the weekend at the latest.

@ncw
Copy link
Member

ncw commented Sep 3, 2019

Need to get some time together to finish off the tests. Will be updating it by the weekend at the latest.

Great :-) Let me know if you need any help.

Signed-off-by: Anagh Kumar Baranwal <6824881+darthShadow@users.noreply.github.com>
Signed-off-by: Anagh Kumar Baranwal <6824881+darthShadow@users.noreply.github.com>
@darthShadow
Copy link
Member Author

@ncw Sorry for the delay, but doesn't look like I will have any time in the next 2-3 months to write any tests and finish this. I have just pushed the latest changeset that I had started on and hope that you or someone else can use that and finish this PR.

@ncw
Copy link
Member

ncw commented Oct 26, 2019

@ncw Sorry for the delay, but doesn't look like I will have any time in the next 2-3 months to write any tests and finish this. I have just pushed the latest changeset that I had started on and hope that you or someone else can use that and finish this PR.

That is no problem. I'll try to get this merged one way or another in 1.51

@bdutro do you fancy finishing this off?

@bdutro
Copy link
Contributor

bdutro commented Oct 28, 2019

@ncw, sure. How should I add my changes? It seems like the proper way is to do a pull request against @darthShadow's branch, which would then get added to this pull request when it's merged.

Edit: Also, does this just need a test added, or do we need to fix the test failures as well?

@ncw
Copy link
Member

ncw commented Oct 29, 2019

@ncw, sure. How should I add my changes? It seems like the proper way is to do a pull request against @darthShadow's branch, which would then get added to this pull request when it's merged.

I would pull the current changes into a local branch, add your commits there then make a new pull request I think.

Edit: Also, does this just need a test added, or do we need to fix the test failures as well?

Both I think.

@ncw
Copy link
Member

ncw commented Nov 10, 2019

This is now merged in #3688 - thank you @darthShadow for the initial work and @bdutro for finishing it off.

@ncw ncw closed this Nov 10, 2019
@darthShadow darthShadow deleted the fix-2907-vfs-cache-rename branch October 13, 2020 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants