The loop that feeds git update-index MUST NOT panic

This commit is contained in:
rubyist 2015-08-07 15:35:43 -04:00
parent 711f483767
commit e9092641a9

@ -68,6 +68,7 @@ func checkoutFromFetchChan(include []string, exclude []string, in chan *lfs.Wrap
// Launch git update-index // Launch git update-index
c := make(chan *lfs.WrappedPointer) c := make(chan *lfs.WrappedPointer)
var wait sync.WaitGroup var wait sync.WaitGroup
wait.Add(1) wait.Add(1)
@ -142,7 +143,19 @@ func checkoutAll() {
// Populate the working copy with the real content of objects where the file is // Populate the working copy with the real content of objects where the file is
// either missing, or contains a matching pointer placeholder, from a list of pointers. // either missing, or contains a matching pointer placeholder, from a list of pointers.
// If the file exists but has other content it is left alone // If the file exists but has other content it is left alone
// Callers of this function MUST NOT Panic or otherwise exit the process
// without waiting for this function to shut down. If the process exits while
// update-index is in the middle of processing a file the git index can be left
// in a locked state.
func checkoutWithChan(in <-chan *lfs.WrappedPointer) { func checkoutWithChan(in <-chan *lfs.WrappedPointer) {
// 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")
}
// Fire up the update-index command // Fire up the update-index command
cmd := exec.Command("git", "update-index", "-q", "--refresh", "--stdin") cmd := exec.Command("git", "update-index", "-q", "--refresh", "--stdin")
updateIdxStdin, err := cmd.StdinPipe() updateIdxStdin, err := cmd.StdinPipe()
@ -154,13 +167,10 @@ func checkoutWithChan(in <-chan *lfs.WrappedPointer) {
Panic(err, "Could not update the index") Panic(err, "Could not update the index")
} }
// Get a converter from repo-relative to cwd-relative // From this point on, git update-index is running. Code in this loop MUST
// Since writing data & calling git update-index must be relative to cwd // NOT Panic() or otherwise cause the process to exit. If the process exits
repopathchan := make(chan string, 1) // while update-index is in the middle of updating, the index can remain in a
cwdpathchan, err := lfs.ConvertRepoFilesRelativeToCwd(repopathchan) // locked state.
if err != nil {
Panic(err, "Could not convert file paths")
}
// As files come in, write them to the wd and update the index // As files come in, write them to the wd and update the index
for pointer := range in { for pointer := range in {
@ -172,24 +182,27 @@ func checkoutWithChan(in <-chan *lfs.WrappedPointer) {
// File has non-pointer content, leave it alone // File has non-pointer content, leave it alone
continue continue
} }
Panic(err, "Problem accessing %v", pointer.Name) LoggedError(err, "Problem accessing %v", pointer.Name)
continue
} }
if filepointer != nil && filepointer.Oid != pointer.Oid { if filepointer != nil && filepointer.Oid != pointer.Oid {
// User has probably manually reset a file to another commit // User has probably manually reset a file to another commit
// while leaving it a pointer; don't mess with this // while leaving it a pointer; don't mess with this
continue continue
} }
// OK now we can (over)write the file content
repopathchan <- pointer.Name repopathchan <- pointer.Name
cwdfilepath := <-cwdpathchan cwdfilepath := <-cwdpathchan
// smudge but set auto-download to false
err = lfs.PointerSmudgeToFile(cwdfilepath, pointer.Pointer, false, nil) err = lfs.PointerSmudgeToFile(cwdfilepath, pointer.Pointer, false, nil)
if err != nil { if err != nil {
if err == lfs.DownloadDeclinedError { if err == lfs.DownloadDeclinedError {
// acceptable error, data not local (fetch not run or include/exclude) // acceptable error, data not local (fetch not run or include/exclude)
LoggedError(err, "Skipped checkout for %v, content not local. Use fetch to download.", pointer.Name) LoggedError(err, "Skipped checkout for %v, content not local. Use fetch to download.", pointer.Name)
} else { } else {
Panic(err, "Could not checkout file") LoggedError(err, "Could not checkout file")
continue
} }
} }
@ -201,5 +214,4 @@ func checkoutWithChan(in <-chan *lfs.WrappedPointer) {
if err := cmd.Wait(); err != nil { if err := cmd.Wait(); err != nil {
Panic(err, "Error updating the git index") Panic(err, "Error updating the git index")
} }
} }