github.com/psexton/git-lfs@v2.1.1-0.20170517224304-289a18b2bc53+incompatible/commands/command_clean.go (about) 1 package commands 2 3 import ( 4 "io" 5 "os" 6 7 "github.com/git-lfs/git-lfs/errors" 8 "github.com/git-lfs/git-lfs/lfs" 9 "github.com/git-lfs/git-lfs/progress" 10 "github.com/spf13/cobra" 11 ) 12 13 // clean cleans an object read from the given `io.Reader`, "from", and writes 14 // out a corresponding pointer to the `io.Writer`, "to". If there were any 15 // errors encountered along the way, they will be returned immediately if the 16 // error is non-fatal, otherwise they will halt using the built in 17 // `commands.Panic`. 18 // 19 // If the object read from "from" is _already_ a clean pointer, then it will be 20 // written out verbatim to "to", without trying to make it a pointer again. 21 func clean(to io.Writer, from io.Reader, fileName string) error { 22 var cb progress.CopyCallback 23 var file *os.File 24 var fileSize int64 25 26 if len(fileName) > 0 { 27 stat, err := os.Stat(fileName) 28 if err == nil && stat != nil { 29 fileSize = stat.Size() 30 31 localCb, localFile, err := lfs.CopyCallbackFile("clean", fileName, 1, 1) 32 if err != nil { 33 Error(err.Error()) 34 } else { 35 cb = localCb 36 file = localFile 37 } 38 } 39 } 40 41 cleaned, err := lfs.PointerClean(from, fileName, fileSize, cb) 42 if file != nil { 43 file.Close() 44 } 45 46 if cleaned != nil { 47 defer cleaned.Teardown() 48 } 49 50 if errors.IsCleanPointerError(err) { 51 // If the contents read from the working directory was _already_ 52 // a pointer, we'll get a `CleanPointerError`, with the context 53 // containing the bytes that we should write back out to Git. 54 55 _, err = to.Write(errors.GetContext(err, "bytes").([]byte)) 56 return err 57 } 58 59 if err != nil { 60 ExitWithError(errors.Wrap(err, "Error cleaning LFS object")) 61 } 62 63 tmpfile := cleaned.Filename 64 mediafile, err := lfs.LocalMediaPath(cleaned.Oid) 65 if err != nil { 66 Panic(err, "Unable to get local media path.") 67 } 68 69 if stat, _ := os.Stat(mediafile); stat != nil { 70 if stat.Size() != cleaned.Size && len(cleaned.Pointer.Extensions) == 0 { 71 Exit("Files don't match:\n%s\n%s", mediafile, tmpfile) 72 } 73 Debug("%s exists", mediafile) 74 } else { 75 if err := os.Rename(tmpfile, mediafile); err != nil { 76 Panic(err, "Unable to move %s to %s\n", tmpfile, mediafile) 77 } 78 79 Debug("Writing %s", mediafile) 80 } 81 82 _, err = lfs.EncodePointer(to, cleaned.Pointer) 83 return err 84 } 85 86 func cleanCommand(cmd *cobra.Command, args []string) { 87 requireStdin("This command should be run by the Git 'clean' filter") 88 lfs.InstallHooks(false) 89 90 var fileName string 91 if len(args) > 0 { 92 fileName = args[0] 93 } 94 95 if err := clean(os.Stdout, os.Stdin, fileName); err != nil { 96 Error(err.Error()) 97 } 98 } 99 100 func init() { 101 RegisterCommand("clean", cleanCommand, nil) 102 }