-
Notifications
You must be signed in to change notification settings - Fork 499
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
Improve Windows support. #381
Conversation
zb140
commented
Jul 2, 2019
- Fix handling of paths and permissions to work on Windows
- Make sure all tests are passing
lib/chezmoi/fsmutator_windows.go
Outdated
"github.com/twpayne/go-vfs/vfst" | ||
) | ||
|
||
func (a *FSMutator) getCorrectedPath(file string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if there's a better way to deal with the fact that during the tests a path will get passed in that needs to have the test sandbox dir prepended to it. This feels like a hack but it's probably better than pushing IsPrivate up into go-vfs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the right way to handle this is for go-vfs
to include a function that returns the path to the file on the underlying filesystem. twpayne/go-vfs#40
This is really impressive work @zb140 :) I'll only have time to review it fully at the weekend, but there a few changes that I would like to see:
|
@@ -369,8 +364,9 @@ func getDefaultData(fs vfs.FS) (map[string]interface{}, error) { | |||
group, err := user.LookupGroupId(currentUser.Gid) | |||
if err == nil { | |||
data["group"] = group.Name | |||
} else if cgoEnabled { | |||
// Only return an error if CGO is enabled. | |||
} else if cgoEnabled && runtime.GOOS != "windows" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed nearly all of the uses of runtime.GOOS
that I added. I left this one in because I really think it makes more sense to just add this boolean check rather than try to refactor this into separate files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, makes sense.
Thanks! It's quite a big change, so I definitely understand it'll take a while to review. In addition to removing the usages of Next I revisited the idea discussed in #23 to override I'm not sure right now how best to proceed. If you have any thoughts or suggestions, I'd love to hear them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks really good.
I think that with twpayne/go-vfs#40 you can make IsPrivate
a top-level function in lib/chezmoi
.
Instead of using the _other
suffix for non-Windows systems, please use _posix
instead. This just requires renaming a few files.
This PR is probably a couple of commits away from being merged :)
@@ -369,8 +364,9 @@ func getDefaultData(fs vfs.FS) (map[string]interface{}, error) { | |||
group, err := user.LookupGroupId(currentUser.Gid) | |||
if err == nil { | |||
data["group"] = group.Name | |||
} else if cgoEnabled { | |||
// Only return an error if CGO is enabled. | |||
} else if cgoEnabled && runtime.GOOS != "windows" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, makes sense.
lib/chezmoi/fsmutator_windows.go
Outdated
"github.com/twpayne/go-vfs/vfst" | ||
) | ||
|
||
func (a *FSMutator) getCorrectedPath(file string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the right way to handle this is for go-vfs
to include a function that returns the path to the file on the underlying filesystem. twpayne/go-vfs#40
|
||
// WriteFile implements Mutator.WriteFile. | ||
func (a *FSMutator) WriteFile(name string, data []byte, perm os.FileMode, currData []byte) error { | ||
// Special case: if writing to the real filesystem, use github.com/google/renameio |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After a private chat with @stapelberg last week (author of github.com/google/renameio
) I understood that atomic file replacement is not possible on Windows, so we can remove the use of renameio
here. I've asked for confirmation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. I've left it in for now but once he confirms I'll go ahead and remove it.
lib/chezmoi/script.go
Outdated
@@ -121,10 +121,14 @@ func (s *Script) Apply(fs vfs.FS, mutator Mutator, applyOptions *ApplyOptions) e | |||
} | |||
|
|||
// Write the temporary script file. | |||
f, err := ioutil.TempFile("", filepath.Base(s.targetName)) | |||
pathBase := filepath.Base(s.targetName) | |||
pathBase = strings.Replace(pathBase, "#", "*", 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment explaining why this replacement is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out I massively overcomplicated this, which I realized once I started explaining the replacement. My only defense is that some of this code was written pretty late at night 😉
(For the record, the point of doing this was to preserve the file extension, which Windows uses to decide if it knows how to execute a file or not. Because of that, TempFile
's randomness couldn't just go on the end of the name, which is the default, so I needed a *
to indicate where it should go. But *
is not a legal character in a Windows filename, thus the indirection. Of course, the much simpler solution is... just put it on the front of whatever the real filename is.)
…ks. Some other stuff works, but some is still broken
… failure is due to absolute vs relative paths in one of the dump tests.
* that will return the absolute path of $PWD, which is almost certainly not the right thing to do
…o add back some code that got lost in the merge.
* Make sure to close the persistent store before trying to delete the directory it lives in. (Aside from causing the tests to fail, surprisingly this also causes them to take a very long time to run *before* they fail) * The ability to run a script on Windows is mainly controlled by the file extension, so all the script names must end with `.bat`.
…s disabled on Windows for now. Also, build tags for `noupgrade.go` should be ORed rather than ANDed.
creating a constant to compare against, but that doesn't seem like it really solves any problems, nor does it appear to be common practice in other projects.
…build tags instead.
…w things to better match conventions.
… vfs.Stater but the Windows one can't.
* Newlines on Windows have a CR before them, which `prompt` didn't allow for.
I think I've addressed everything you mentioned (except removing |
… tests. Also, for tests that launch Powershell, do so in NonInteractive mode.
…emporary script file names.
Brilliant! Thank you so much! I've merged this, will do a quick round of minor clean-ups, and tag a new version. |