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  }