Fix a bunch of issues related to checkout in non-root directories
Have to convert file paths to/from cwd-relative and root-relative: 1. cwd->root for include filter arguments (user is in cwd, ls-tree is rooted) 2. root->cwd when writing files & update-index since both are relative to cwd not root like results
This commit is contained in:
parent
1ac8ed6840
commit
760c7d75e1
@ -21,7 +21,19 @@ var (
|
||||
func checkoutCommand(cmd *cobra.Command, args []string) {
|
||||
|
||||
// Parameters are filters
|
||||
checkoutWithIncludeExclude(args, nil)
|
||||
// firstly convert any pathspecs to the root of the repo, in case this is being executed in a sub-folder
|
||||
var rootedpaths = make([]string, len(args))
|
||||
inchan := make(chan string, 1)
|
||||
outchan, err := lfs.ConvertCwdFilesRelativeToRepo(inchan)
|
||||
if err != nil {
|
||||
Panic(err, "Could not checkout")
|
||||
}
|
||||
for _, arg := range args {
|
||||
inchan <- arg
|
||||
rootedpaths = append(rootedpaths, <-outchan)
|
||||
}
|
||||
close(inchan)
|
||||
checkoutWithIncludeExclude(rootedpaths, nil)
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -78,6 +90,14 @@ func checkoutWithChan(in <-chan *lfs.WrappedPointer) {
|
||||
Panic(err, "Could not update the index")
|
||||
}
|
||||
|
||||
// Get a converter from repo-relative to cwd-relative
|
||||
// Since writing data & calling git update-index must be relative to cwd
|
||||
repopathchan := make(chan string, 1)
|
||||
cwdpathchan, err := lfs.ConvertRepoFilesRelativeToCwd(repopathchan)
|
||||
if err != nil {
|
||||
Panic(err, "Could not convert file paths")
|
||||
}
|
||||
|
||||
// As files come in, write them to the wd and update the index
|
||||
for pointer := range in {
|
||||
|
||||
@ -96,13 +116,16 @@ func checkoutWithChan(in <-chan *lfs.WrappedPointer) {
|
||||
continue
|
||||
}
|
||||
// OK now we can (over)write the file content
|
||||
err = lfs.PointerSmudgeToFile(pointer.Name, pointer.Pointer, nil)
|
||||
repopathchan <- pointer.Name
|
||||
cwdfilepath := <-cwdpathchan
|
||||
err = lfs.PointerSmudgeToFile(cwdfilepath, pointer.Pointer, nil)
|
||||
if err != nil {
|
||||
Panic(err, "Could not checkout file")
|
||||
}
|
||||
|
||||
updateIdxStdin.Write([]byte(pointer.Name + "\n"))
|
||||
updateIdxStdin.Write([]byte(cwdfilepath + "\n"))
|
||||
}
|
||||
close(repopathchan)
|
||||
|
||||
updateIdxStdin.Close()
|
||||
if err := cmd.Wait(); err != nil {
|
||||
|
72
lfs/util.go
72
lfs/util.go
@ -173,6 +173,78 @@ func GetPlatform() Platform {
|
||||
return currentPlatform
|
||||
}
|
||||
|
||||
// Convert filenames expressed relative to the root of the repo relative to the
|
||||
// current working dir. Useful when needing to calling git with results from a rooted command,
|
||||
// but the user is in a subdir of their repo
|
||||
// Pass in a channel which you will fill with relative files & receive a channel which will get results
|
||||
func ConvertRepoFilesRelativeToCwd(repochan <-chan string) (<-chan string, error) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to get working dir: %v", err)
|
||||
}
|
||||
|
||||
// Early-out if working dir is root dir, same result
|
||||
passthrough := false
|
||||
if LocalWorkingDir == wd {
|
||||
passthrough = true
|
||||
}
|
||||
|
||||
outchan := make(chan string, 1)
|
||||
|
||||
go func() {
|
||||
for f := range repochan {
|
||||
if passthrough {
|
||||
outchan <- f
|
||||
continue
|
||||
}
|
||||
abs := filepath.Join(LocalWorkingDir, f)
|
||||
rel, err := filepath.Rel(wd, abs)
|
||||
if err != nil {
|
||||
// Use absolute file instead
|
||||
outchan <- abs
|
||||
} else {
|
||||
outchan <- rel
|
||||
}
|
||||
}
|
||||
close(outchan)
|
||||
}()
|
||||
|
||||
return outchan, nil
|
||||
}
|
||||
|
||||
// Convert filenames expressed relative to the current directory to be
|
||||
// relative to the repo root. Useful when calling git with arguments that requires them
|
||||
// to be rooted but the user is in a subdir of their repo & expects to use relative args
|
||||
// Pass in a channel which you will fill with relative files & receive a channel which will get results
|
||||
func ConvertCwdFilesRelativeToRepo(cwdchan <-chan string) (<-chan string, error) {
|
||||
curdir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not retrieve current directory: %v", err)
|
||||
}
|
||||
outchan := make(chan string, 1)
|
||||
go func() {
|
||||
for p := range cwdchan {
|
||||
var abs string
|
||||
if filepath.IsAbs(p) {
|
||||
abs = p
|
||||
} else {
|
||||
abs = filepath.Join(curdir, p)
|
||||
}
|
||||
reltoroot, err := filepath.Rel(LocalWorkingDir, abs)
|
||||
if err != nil {
|
||||
// Can't do this, use absolute as best fallback
|
||||
outchan <- abs
|
||||
} else {
|
||||
outchan <- reltoroot
|
||||
}
|
||||
}
|
||||
close(outchan)
|
||||
}()
|
||||
|
||||
return outchan, nil
|
||||
|
||||
}
|
||||
|
||||
// Are we running on Windows? Need to handle some extra path shenanigans
|
||||
func IsWindows() bool {
|
||||
return GetPlatform() == PlatformWindows
|
||||
|
Loading…
Reference in New Issue
Block a user