github.com/atlassian/git-lob@v0.0.0-20150806085256-2386a5ed291a/core/missing_test.go (about)

     1  package core
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	. "github.com/atlassian/git-lob/Godeps/_workspace/src/github.com/onsi/ginkgo"
     9  	. "github.com/atlassian/git-lob/Godeps/_workspace/src/github.com/onsi/gomega"
    10  	. "github.com/atlassian/git-lob/util"
    11  )
    12  
    13  var _ = Describe("Missing", func() {
    14  
    15  	root := filepath.Join(os.TempDir(), "MissingTest")
    16  	var oldwd string
    17  	var setupInputs []*TestCommitSetupInput
    18  	var setupOutputs []*CommitLOBRef
    19  
    20  	BeforeEach(func() {
    21  		oldwd, _ = os.Getwd()
    22  		CreateGitRepoForTest(root)
    23  		os.Chdir(root)
    24  
    25  		setupInputs = []*TestCommitSetupInput{
    26  			&TestCommitSetupInput{ // 0
    27  				Files:          []string{"file1.bin", "file2.bin"},
    28  				CommitterName:  "Barry",
    29  				CommitterEmail: "baz@foo.com",
    30  			},
    31  			&TestCommitSetupInput{ // 1
    32  				Files:          []string{filepath.Join("fld", "file3.bin"), filepath.Join("fld", "file4.bin")},
    33  				CommitterName:  "Nigel",
    34  				CommitterEmail: "nig@foo.com",
    35  			},
    36  			&TestCommitSetupInput{ // 2
    37  				Files:          []string{"file1.bin"},
    38  				CommitterName:  "Nigel",
    39  				CommitterEmail: "nig@foo.com",
    40  			},
    41  			&TestCommitSetupInput{ // 3
    42  				Files:          []string{filepath.Join("fld", "large", "large1.bin")},
    43  				FileSizes:      []int64{ChunkSize + 30},
    44  				CommitterName:  "Barry",
    45  				CommitterEmail: "baz@foo.com",
    46  			},
    47  			&TestCommitSetupInput{ // 4
    48  				Files:          []string{filepath.Join("fld", "file5.bin")},
    49  				CommitterName:  "Barry",
    50  				CommitterEmail: "baz@foo.com",
    51  			},
    52  			&TestCommitSetupInput{ // 5
    53  				Files:          []string{"file4.bin", "file5.bin"},
    54  				CommitterName:  "Barry",
    55  				CommitterEmail: "baz@foo.com",
    56  			},
    57  		}
    58  
    59  		setupOutputs = SetupRepoForTest(setupInputs)
    60  
    61  		// At this point all files are placeholders, because that's how SetupRepoForTest works (to avoid filters)
    62  		// Checkout all files before we break things
    63  		Expect(Checkout(nil, false, func(t ProgressCallbackType, filelob *FileLOB, err error) {})).To(BeNil())
    64  		// Now make some of these files placeholders
    65  		// Case 1. placeholder for missing data (small file and missing chunk) - blamed
    66  		// ./file1.bin
    67  		Expect(ioutil.WriteFile(setupInputs[2].Files[0], []byte(getLOBPlaceholderContent(setupOutputs[2].LobSHAs[0])), 0644)).To(BeNil())
    68  		Expect(ForceRemove(GetLocalLOBMetaPath(setupOutputs[2].LobSHAs[0]))).To(BeNil())     // remove meta
    69  		Expect(ForceRemove(GetLocalLOBChunkPath(setupOutputs[2].LobSHAs[0], 0))).To(BeNil()) // remove chunk 1
    70  		// ./fld/large/large1.bin
    71  		Expect(ioutil.WriteFile(setupInputs[3].Files[0], []byte(getLOBPlaceholderContent(setupOutputs[3].LobSHAs[0])), 0644)).To(BeNil())
    72  		Expect(ForceRemove(GetLocalLOBChunkPath(setupOutputs[3].LobSHAs[0], 1))).To(BeNil()) // remove chunk 2 (partial)
    73  
    74  		// Case 2. placeholder for corrupt data
    75  		// for this one we just mess up the metadata
    76  		// ./fld/file4.bin
    77  		Expect(ioutil.WriteFile(setupInputs[1].Files[1], []byte(getLOBPlaceholderContent(setupOutputs[1].LobSHAs[1])), 0644)).To(BeNil())
    78  		Expect(ioutil.WriteFile(GetLocalLOBMetaPath(setupOutputs[1].LobSHAs[1]), []byte("{ garbage }"), 0644)).To(BeNil()) // corrupt meta
    79  
    80  		// Case 3. placeholder locally modified (random SHA)
    81  		// ./file4.bin
    82  		Expect(ioutil.WriteFile(setupInputs[5].Files[0], []byte(getLOBPlaceholderContent("1111111111111111111111111111111111111111")), 0644)).To(BeNil())
    83  
    84  		// Case 4. placeholder with data available
    85  		// ./file5.bin
    86  		Expect(ioutil.WriteFile(setupInputs[5].Files[1], []byte(getLOBPlaceholderContent(setupOutputs[5].LobSHAs[1])), 0644)).To(BeNil())
    87  
    88  	})
    89  	AfterEach(func() {
    90  		os.Chdir(oldwd)
    91  		err := ForceRemoveAll(root)
    92  		if err != nil {
    93  			Fail(err.Error())
    94  		}
    95  	})
    96  
    97  	It("Checks missing correctly", func() {
    98  		var responses []*MissingCallbackData
    99  		callback := func(data *MissingCallbackData) (quit bool) {
   100  			if data.Type != MissingWorking {
   101  				responses = append(responses, data)
   102  			}
   103  			return false
   104  		}
   105  		Missing(false, nil, callback)
   106  		Expect(responses).To(HaveLen(5), "Should be 5 callbacks")
   107  		// Doing a direct comparison with commit summaries is unusable when it fails because time.Time spits out
   108  		// so much output it floods everything. So pick out specifics to test for
   109  		findResponseForPath := func(path string) *MissingCallbackData {
   110  			for _, resp := range responses {
   111  				if resp.Path == path {
   112  					return resp
   113  				}
   114  			}
   115  			return nil
   116  		}
   117  		// Case 1a
   118  		r := findResponseForPath(setupInputs[2].Files[0])
   119  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[2].Files[0])
   120  		Expect(r.Type).To(BeEquivalentTo(MissingBlamed), "Should be blamed")
   121  		Expect(r.CommitSummary).ToNot(BeNil(), "Should have commit details")
   122  		Expect(r.CommitSummary.SHA).To(Equal(setupOutputs[2].Commit), "Should blame correct commit")
   123  		Expect(r.CommitSummary.CommitterName).To(Equal("Nigel"), "Should blame correct person")
   124  		Expect(r.CommitSummary.CommitterEmail).To(Equal("nig@foo.com"), "Should blame correct person")
   125  		// Case 1b
   126  		r = findResponseForPath(setupInputs[3].Files[0])
   127  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[3].Files[0])
   128  		Expect(r.Type).To(BeEquivalentTo(MissingBlamed), "Should be blamed")
   129  		Expect(r.CommitSummary).ToNot(BeNil(), "Should have commit details")
   130  		Expect(r.CommitSummary.SHA).To(Equal(setupOutputs[3].Commit), "Should blame correct commit")
   131  		Expect(r.CommitSummary.CommitterName).To(Equal("Barry"), "Should blame correct person")
   132  		Expect(r.CommitSummary.CommitterEmail).To(Equal("baz@foo.com"), "Should blame correct person")
   133  		// Case 2
   134  		r = findResponseForPath(setupInputs[1].Files[1])
   135  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[1].Files[1])
   136  		Expect(r.Type).To(BeEquivalentTo(MissingCorrupt), "Should be corrupt")
   137  		// Case 3
   138  		r = findResponseForPath(setupInputs[5].Files[0])
   139  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[5].Files[0])
   140  		Expect(r.Type).To(BeEquivalentTo(MissingModified), "Should be locally modified")
   141  		// Case 4
   142  		r = findResponseForPath(setupInputs[5].Files[1])
   143  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[5].Files[1])
   144  		Expect(r.Type).To(BeEquivalentTo(MissingAvailable), "Should be a placeholder but available")
   145  
   146  		content, err := ioutil.ReadFile(setupInputs[5].Files[1])
   147  		Expect(err).To(BeNil(), "Should be ok to read placeholder")
   148  		Expect(string(content)).To(Equal(getLOBPlaceholderContent(setupOutputs[5].LobSHAs[1])), "Available file should still be a placeholder")
   149  
   150  		// Now do the same again but checkout=true
   151  		responses = nil
   152  		Missing(true, nil, callback)
   153  		Expect(responses).To(HaveLen(5), "Should be 5 callbacks")
   154  		// Case 1a
   155  		r = findResponseForPath(setupInputs[2].Files[0])
   156  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[2].Files[0])
   157  		Expect(r.Type).To(BeEquivalentTo(MissingBlamed), "Should be blamed")
   158  		Expect(r.CommitSummary).ToNot(BeNil(), "Should have commit details")
   159  		Expect(r.CommitSummary.SHA).To(Equal(setupOutputs[2].Commit), "Should blame correct commit")
   160  		Expect(r.CommitSummary.CommitterName).To(Equal("Nigel"), "Should blame correct person")
   161  		Expect(r.CommitSummary.CommitterEmail).To(Equal("nig@foo.com"), "Should blame correct person")
   162  		// Case 1b
   163  		r = findResponseForPath(setupInputs[3].Files[0])
   164  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[3].Files[0])
   165  		Expect(r.Type).To(BeEquivalentTo(MissingBlamed), "Should be blamed")
   166  		Expect(r.CommitSummary).ToNot(BeNil(), "Should have commit details")
   167  		Expect(r.CommitSummary.SHA).To(Equal(setupOutputs[3].Commit), "Should blame correct commit")
   168  		Expect(r.CommitSummary.CommitterName).To(Equal("Barry"), "Should blame correct person")
   169  		Expect(r.CommitSummary.CommitterEmail).To(Equal("baz@foo.com"), "Should blame correct person")
   170  		// Case 2
   171  		r = findResponseForPath(setupInputs[1].Files[1])
   172  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[1].Files[1])
   173  		Expect(r.Type).To(BeEquivalentTo(MissingCorrupt), "Should be corrupt")
   174  		// Case 3
   175  		r = findResponseForPath(setupInputs[5].Files[0])
   176  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[5].Files[0])
   177  		Expect(r.Type).To(BeEquivalentTo(MissingModified), "Should be locally modified")
   178  		// Case 4
   179  		r = findResponseForPath(setupInputs[5].Files[1])
   180  		Expect(r).ToNot(BeNil(), "Should find response for"+setupInputs[5].Files[1])
   181  		Expect(r.Type).To(BeEquivalentTo(MissingFixed), "Available file should have been fixed")
   182  
   183  		stat, err := os.Stat(setupInputs[5].Files[1])
   184  		Expect(err).To(BeNil(), "Should be ok to read placeholder")
   185  		Expect(stat.Size()).ToNot(BeEquivalentTo(SHALineLen), "Available file should have been replaced with real data")
   186  
   187  		// Now test using path matching
   188  		var filenames []string
   189  		nameCallback := func(data *MissingCallbackData) (quit bool) {
   190  			if data.Type != MissingWorking {
   191  				filenames = append(filenames, data.Path)
   192  			}
   193  			return false
   194  		}
   195  		Missing(false, []string{"fld"}, nameCallback)
   196  		Expect(filenames).To(ConsistOf([]string{
   197  			filepath.Join("fld", "large", "large1.bin"),
   198  			filepath.Join("fld", "file4.bin")}), "Should have correct filtered responses")
   199  
   200  		// Now test using path matching - wildcard
   201  		filenames = nil
   202  		Missing(false, []string{"file*"}, nameCallback)
   203  		// file5.bin has already been fixed, and shouldn't match anything in subdirs
   204  		Expect(filenames).To(ConsistOf([]string{
   205  			"file1.bin", "file4.bin"}), "Should have correct filtered responses")
   206  
   207  		// Now test using path matching - wildcard with folder
   208  		filenames = nil
   209  		Missing(false, []string{"*/*.bin"}, nameCallback)
   210  		// only 1 level down
   211  		Expect(filenames).To(ConsistOf([]string{
   212  			filepath.Join("fld", "file4.bin")}), "Should have correct filtered responses")
   213  		//Now multiple matches
   214  		filenames = nil
   215  		Missing(false, []string{"fld", "file*.bin"}, nameCallback)
   216  		// This should match everything
   217  		Expect(filenames).To(ConsistOf([]string{
   218  			filepath.Join("fld", "large", "large1.bin"),
   219  			filepath.Join("fld", "file4.bin"),
   220  			"file1.bin", "file4.bin",
   221  		}), "Should have correct filtered responses")
   222  	})
   223  
   224  })