github.com/atlassian/git-lob@v0.0.0-20150806085256-2386a5ed291a/core/filter.go (about) 1 package core 2 3 import ( 4 "io" 5 "regexp" 6 7 "github.com/atlassian/git-lob/util" 8 ) 9 10 // Prefix which identifies file contents as a git-lob SHA entry 11 // Use this prefix rather than just the SHA in case by accident a file's content 12 // actually is a 40-char pattern 13 const SHAPrefix = "git-lob: " 14 const SHALen = 40 15 const SHALineLen = len(SHAPrefix) + SHALen 16 const SHALineRegexStr = "^git-lob: [A-Fa-f0-9]{40}$" 17 const SHALineMatchRegexStr = "^git-lob: ([0-9A-Fa-f]{40})$" 18 19 func getLOBPlaceholderContent(sha string) string { 20 return SHAPrefix + sha 21 } 22 23 func SmudgeFilterWithReaderWriter(in io.Reader, out io.Writer, filename string) int { 24 util.LogDebug("Running smudge filter for ", filename) 25 26 shaRegex := regexp.MustCompile(SHALineMatchRegexStr) 27 // read committed content from stdin 28 // write actual file content to stdout if a git-lob SHA 29 buf := make([]byte, SHALineLen) 30 c, err := in.Read(buf) 31 if c == SHALineLen { 32 if match := shaRegex.FindStringSubmatch(string(buf)); match != nil { 33 sha := match[1] 34 lobinfo, err := RetrieveLOB(sha, out) 35 if err == nil { 36 util.LogDebugf("Successfully smudged %v: %v in %v chunks from %v\n", filename, util.FormatSize(lobinfo.Size), lobinfo.NumChunks, sha) 37 return 0 38 } else { 39 if IsNotFoundError(err) { 40 util.LogErrorf("%v: content not available, placeholder used [%v]\n", filename, sha[:7]) 41 } else { 42 util.LogErrorf("Error obtaining %v for %v: %v\n", sha, filename, err) 43 } 44 // fall through to below which will just write the SHA line to the working copy 45 } 46 47 } 48 } 49 // Otherwise, pass through content 50 out.Write(buf[:c]) 51 _, err = io.Copy(out, in) 52 if err != nil { 53 util.LogErrorf("Error copying stdin->stdout for %v: %v\n", filename, err) 54 return 3 55 } 56 57 return 0 58 } 59 60 func CleanFilterWithReaderWriter(in io.Reader, out io.Writer, filename string) int { 61 util.LogDebug("Running clean filter for ", filename) 62 shaRegex := regexp.MustCompile(SHALineMatchRegexStr) 63 // read working copy content from stdin 64 // First check if this is an unexpanded LOB SHA (not downloaded) 65 buf := make([]byte, SHALineLen) 66 c, err := in.Read(buf) 67 if c == SHALineLen { 68 if match := shaRegex.FindStringSubmatch(string(buf)); match != nil { 69 sha := match[1] 70 util.LogDebugf("Unexpanded LOB file content at %v, not storing\n", filename) 71 // Yes, unexpanded SHA, just write 72 out.Write(buf[:c]) 73 _, err = io.Copy(out, in) 74 if err == nil { 75 util.LogDebug("Successful clean filter for ", filename) 76 return 0 77 } else { 78 util.LogErrorf("Error writing unexpanded LOB for %v/%v in clean filter: %v\n", filename, sha, err) 79 return 3 80 } 81 82 } 83 } 84 // Otherwise if we got here, this is just binary data we need to hash 85 lobinfo, err := StoreLOB(in, buf[:c]) 86 87 if err != nil { 88 util.LogErrorf("Error storing LOB from %v in clean filter: %v\n", filename, err) 89 return 4 90 } 91 92 // Write SHA code to output 93 shaLine := getLOBPlaceholderContent(lobinfo.SHA) 94 _, err = io.WriteString(out, shaLine) 95 if err != nil { 96 util.LogErrorf("Error writing LOB SHA for %v to index in clean filter: %v\n", filename, err) 97 return 5 98 } 99 100 util.LogDebug("Successful clean filter for ", filename) 101 102 return 0 103 }