github.com/stffabi/git-lfs@v2.3.5-0.20180214015214-8eeaa8d88902+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/tools" 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 fileSize is given as a non-negative (>= 0) integer, that value is used 20 // with preference to os.Stat(fileName).Size(). If it is given as negative, the 21 // value from the `stat(1)` call will be used instead. 22 // 23 // If the object read from "from" is _already_ a clean pointer, then it will be 24 // written out verbatim to "to", without trying to make it a pointer again. 25 func clean(gf *lfs.GitFilter, to io.Writer, from io.Reader, fileName string, fileSize int64) (*lfs.Pointer, error) { 26 var cb tools.CopyCallback 27 var file *os.File 28 29 if len(fileName) > 0 { 30 stat, err := os.Stat(fileName) 31 if err == nil && stat != nil { 32 if fileSize < 0 { 33 fileSize = stat.Size() 34 } 35 36 localCb, localFile, err := gf.CopyCallbackFile("clean", fileName, 1, 1) 37 if err != nil { 38 Error(err.Error()) 39 } else { 40 cb = localCb 41 file = localFile 42 } 43 } 44 } 45 46 cleaned, err := gf.Clean(from, fileName, fileSize, cb) 47 if file != nil { 48 file.Close() 49 } 50 51 if cleaned != nil { 52 defer cleaned.Teardown() 53 } 54 55 if errors.IsCleanPointerError(err) { 56 // If the contents read from the working directory was _already_ 57 // a pointer, we'll get a `CleanPointerError`, with the context 58 // containing the bytes that we should write back out to Git. 59 60 _, err = to.Write(errors.GetContext(err, "bytes").([]byte)) 61 return nil, err 62 } 63 64 if err != nil { 65 ExitWithError(errors.Wrap(err, "Error cleaning LFS object")) 66 } 67 68 tmpfile := cleaned.Filename 69 mediafile, err := gf.ObjectPath(cleaned.Oid) 70 if err != nil { 71 Panic(err, "Unable to get local media path.") 72 } 73 74 if stat, _ := os.Stat(mediafile); stat != nil { 75 if stat.Size() != cleaned.Size && len(cleaned.Pointer.Extensions) == 0 { 76 Exit("Files don't match:\n%s\n%s", mediafile, tmpfile) 77 } 78 Debug("%s exists", mediafile) 79 } else { 80 if err := os.Rename(tmpfile, mediafile); err != nil { 81 Panic(err, "Unable to move %s to %s\n", tmpfile, mediafile) 82 } 83 84 Debug("Writing %s", mediafile) 85 } 86 87 _, err = lfs.EncodePointer(to, cleaned.Pointer) 88 return cleaned.Pointer, err 89 } 90 91 func cleanCommand(cmd *cobra.Command, args []string) { 92 requireStdin("This command should be run by the Git 'clean' filter") 93 installHooks(false) 94 95 var fileName string 96 if len(args) > 0 { 97 fileName = args[0] 98 } 99 100 gitfilter := lfs.NewGitFilter(cfg) 101 ptr, err := clean(gitfilter, os.Stdout, os.Stdin, fileName, -1) 102 if err != nil { 103 Error(err.Error()) 104 } 105 106 if ptr != nil && possiblyMalformedObjectSize(ptr.Size) { 107 Error("Possibly malformed conversion on Windows, see `git lfs help smudge` for more details.") 108 } 109 } 110 111 func init() { 112 RegisterCommand("clean", cleanCommand, nil) 113 }