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

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"regexp"
    10  	"strings"
    11  
    12  	. "github.com/atlassian/git-lob/Godeps/_workspace/src/github.com/onsi/ginkgo"
    13  	. "github.com/atlassian/git-lob/Godeps/_workspace/src/github.com/onsi/gomega"
    14  	. "github.com/atlassian/git-lob/core"
    15  )
    16  
    17  // This test file is about running git commands with git filters configured
    18  // In order to do this, we have to actually run 'go build' to produce a git-lob
    19  // binary, and configure filters & .gitattributes in a repo to do it
    20  var _ = Describe("Integration", func() {
    21  
    22  	BeforeEach(func() {
    23  		// This singular BeforeEach will just perform the build
    24  		outp, err := exec.Command("go", "build").CombinedOutput()
    25  		if err != nil {
    26  			Fail(fmt.Sprintf("Failed to call 'go build': %v\n%v", err.Error(), string(outp)))
    27  		}
    28  	})
    29  
    30  	var gitlobbinarypath string
    31  	// Function to create a git repo configured with git-lob filters for integration testing
    32  	createConfiguredRepoFunc := func(root string) {
    33  		CreateGitRepoForTest(root)
    34  		ioutil.WriteFile(filepath.Join(root, ".gitattributes"),
    35  			[]byte(`*.png filter=testlob -crlf
    36  *.jpg filter=testlob -crlf
    37  *.zip filter=testlob -crlf
    38  *.tiff filter=testlob -crlf
    39  *.tga filter=testlob -crlf
    40  *.dds filter=testlob -crlf
    41  *.bmp filter=testlob -crlf
    42  *.mov filter=testlob -crlf`), 0644)
    43  		f, err := os.OpenFile(filepath.Join(root, ".git", "config"), os.O_APPEND|os.O_RDWR|os.O_CREATE, 0644)
    44  		if err != nil {
    45  			Fail(fmt.Sprintf("Can't write gitconfig: %v", err.Error()))
    46  		}
    47  		// Here we have to assume that go test is running in the root source folder
    48  		cwd, _ := os.Getwd()
    49  		gitlobbinarypath = filepath.Join(cwd, "git-lob")
    50  		// For windows we need to convert \ to / since Git doesn't allow backslashes
    51  		gitlobbinarypath = strings.Replace(gitlobbinarypath, "\\", "/", -1)
    52  		f.WriteString(fmt.Sprintf(`
    53  [filter "testlob"]
    54    clean = "%v filter-clean %%f"
    55    smudge = "%v filter-smudge %%f"
    56  `, gitlobbinarypath, gitlobbinarypath))
    57  		f.Close()
    58  	}
    59  
    60  	Context("Integration tests", func() {
    61  		// All actual tests nested here
    62  		root := filepath.Join(os.TempDir(), "IntegrationTest")
    63  		var oldwd string
    64  		filespercommit := [][]string{
    65  			[]string{
    66  				"img1.png", "img2.jpg",
    67  				filepath.Join("movies", "movie1.mov"),
    68  				filepath.Join("movies", "movie2.mov"),
    69  				filepath.Join("other", "files", "windows.bmp"),
    70  			},
    71  			[]string{
    72  				"img3.tga", "img4.tiff", "img5.png",
    73  				filepath.Join("movies", "movie3.mov"),
    74  				filepath.Join("movies", "movie4.mov"),
    75  				filepath.Join("other", "files", "windows7.bmp"),
    76  			},
    77  			[]string{
    78  				"img6.jpg",
    79  				filepath.Join("other", "files", "windows10.bmp"),
    80  			},
    81  		}
    82  		sizeForFile := func(filename string, i int) int64 {
    83  			// not actually that big, we're not doing size tests here
    84  			if strings.HasSuffix(filename, ".mov") {
    85  				return int64(i%3*1000 + 2000)
    86  			} else {
    87  				return int64(i%3*100 + 300)
    88  			}
    89  		}
    90  		checkExistsAndRightSize := func(fileset int) {
    91  			files := filespercommit[fileset]
    92  			for i, file := range files {
    93  				sz := sizeForFile(file, i)
    94  				stat, err := os.Stat(file)
    95  				Expect(err).To(BeNil(), fmt.Sprintf("%v should exist", file))
    96  				Expect(stat.Size()).To(BeEquivalentTo(sz), fmt.Sprintf("%v should be correct size", file))
    97  			}
    98  		}
    99  		checkExistsAndIsPlaceholder := func(fileset int) {
   100  			files := filespercommit[fileset]
   101  			for _, file := range files {
   102  				stat, err := os.Stat(file)
   103  				Expect(err).To(BeNil(), fmt.Sprintf("%v should exist", file))
   104  				Expect(stat.Size()).To(BeEquivalentTo(SHALineLen), fmt.Sprintf("%v should be correct size", file))
   105  			}
   106  		}
   107  		checkNotExists := func(fileset int) {
   108  			files := filespercommit[fileset]
   109  			for _, file := range files {
   110  				_, err := os.Stat(file)
   111  				Expect(err).ToNot(BeNil(), fmt.Sprintf("%v should not exist", file))
   112  			}
   113  		}
   114  		checkGitStatusNotModified := func() {
   115  			outp, err := exec.Command("git", "status", "--porcelain", "-uno").CombinedOutput()
   116  			Expect(outp).To(HaveLen(0), "Should be no modified files")
   117  			Expect(err).To(BeNil(), "git status should succeed")
   118  		}
   119  		moveAsideLOBs := func(shas []string) {
   120  			for _, sha := range shas {
   121  				meta := GetLocalLOBMetaPath(sha)
   122  				err := os.Rename(meta, meta+"_bak")
   123  				Expect(err).To(BeNil(), fmt.Sprintf("Rename should succeed for %v", meta))
   124  				// Assuming only one chunk for this test
   125  				chunk := GetLocalLOBChunkPath(sha, 0)
   126  				err = os.Rename(chunk, chunk+"_bak")
   127  				Expect(err).To(BeNil(), fmt.Sprintf("Rename should succeed for %v", chunk))
   128  			}
   129  
   130  		}
   131  		restoreLOBs := func(shas []string) {
   132  			for _, sha := range shas {
   133  				meta := GetLocalLOBMetaPath(sha)
   134  				err := os.Rename(meta+"_bak", meta)
   135  				Expect(err).To(BeNil(), fmt.Sprintf("Rename should succeed for %v", meta))
   136  				// Assuming only one chunk for this test
   137  				chunk := GetLocalLOBChunkPath(sha, 0)
   138  				err = os.Rename(chunk+"_bak", chunk)
   139  				Expect(err).To(BeNil(), fmt.Sprintf("Rename should succeed for %v", chunk))
   140  			}
   141  
   142  		}
   143  
   144  		BeforeEach(func() {
   145  			createConfiguredRepoFunc(root)
   146  			oldwd, _ = os.Getwd()
   147  			os.Chdir(root)
   148  		})
   149  		AfterEach(func() {
   150  			os.Chdir(oldwd)
   151  			err := ForceRemoveAll(root)
   152  			if err != nil {
   153  				Fail(err.Error())
   154  			}
   155  		})
   156  
   157  		It("Git filters work", func() {
   158  
   159  			diffregex := regexp.MustCompile("(?m)git-lob: ([A-Fa-f0-9]{40})")
   160  			// Create commits
   161  			for ci, commitfiles := range filespercommit {
   162  				for i, file := range commitfiles {
   163  					err := os.MkdirAll(filepath.Dir(file), 0755)
   164  					Expect(err).To(BeNil(), "Shouldn't fail creating dir")
   165  					sz := sizeForFile(file, i)
   166  					// Create real content
   167  					CreateRandomFileForTest(sz, file)
   168  					// git add, will write placeholder & store via filter (or should)
   169  					err = exec.Command("git", "add", file).Run()
   170  					Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail in git add for %v", file))
   171  
   172  					// Check content of index & that binaries created
   173  
   174  					diffout, err := exec.Command("git", "diff", "--cached", file).CombinedOutput()
   175  					Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail in git diff for %v", file))
   176  					match := diffregex.FindStringSubmatch(string(diffout))
   177  					Expect(match).ToNot(BeNil(), fmt.Sprintf("Should find git-lob ref in diff for %v", file))
   178  					Expect(match).To(HaveLen(2), "Should be 2 matches")
   179  					sha := match[1]
   180  
   181  					// confirm that the file is stored correctly
   182  					err = CheckLOBFilesForSHA(sha, GetLocalLOBRoot(), false)
   183  					Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail checking storage for %v", file))
   184  				}
   185  				// Commit & tag
   186  				err := exec.Command("git", "commit", "-m", fmt.Sprintf("Commit %d", ci)).Run()
   187  				Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail commit %d", ci))
   188  				err = exec.Command("git", "tag", "-a", "-m", "Nothing", fmt.Sprintf("Tag%d", ci)).Run()
   189  				Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail tagging %d", ci))
   190  
   191  				checkGitStatusNotModified()
   192  			}
   193  
   194  			// Now check out a few times to make sure working copy changes appropriately
   195  			err := exec.Command("git", "checkout", "Tag0").Run()
   196  			Expect(err).To(BeNil(), "Shouldn't fail to checkout")
   197  			checkExistsAndRightSize(0)
   198  			checkNotExists(1)
   199  			checkNotExists(2)
   200  			checkGitStatusNotModified()
   201  
   202  			err = exec.Command("git", "checkout", "Tag1").Run()
   203  			Expect(err).To(BeNil(), "Shouldn't fail to checkout")
   204  			checkExistsAndRightSize(0)
   205  			checkExistsAndRightSize(1)
   206  			checkNotExists(2)
   207  			checkGitStatusNotModified()
   208  
   209  			err = exec.Command("git", "checkout", "Tag2").Run()
   210  			Expect(err).To(BeNil(), "Shouldn't fail to checkout")
   211  			checkExistsAndRightSize(0)
   212  			checkExistsAndRightSize(1)
   213  			checkExistsAndRightSize(2)
   214  			checkGitStatusNotModified()
   215  
   216  		})
   217  
   218  		It("leaves files unmodified when placeholders present and after checkout", func() {
   219  			diffregex := regexp.MustCompile("(?m)git-lob: ([A-Fa-f0-9]{40})")
   220  			var shaspercommit [][]string
   221  			// Create commits
   222  			for ci, commitfiles := range filespercommit {
   223  				var shas []string
   224  				for i, file := range commitfiles {
   225  					err := os.MkdirAll(filepath.Dir(file), 0755)
   226  					Expect(err).To(BeNil(), "Shouldn't fail creating dir")
   227  					sz := sizeForFile(file, i)
   228  					// Create real content
   229  					CreateRandomFileForTest(sz, file)
   230  					// git add, will write placeholder & store via filter (or should)
   231  					err = exec.Command("git", "add", file).Run()
   232  					Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail in git add for %v", file))
   233  
   234  					// Get SHA
   235  					diffout, err := exec.Command("git", "diff", "--cached", file).CombinedOutput()
   236  					Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail in git diff for %v", file))
   237  					match := diffregex.FindStringSubmatch(string(diffout))
   238  					Expect(match).ToNot(BeNil(), fmt.Sprintf("Should find git-lob ref in diff for %v", file))
   239  					Expect(match).To(HaveLen(2), "Should be 2 matches")
   240  					sha := match[1]
   241  
   242  					shas = append(shas, sha)
   243  				}
   244  				// Commit & tag
   245  				err := exec.Command("git", "commit", "-m", fmt.Sprintf("Commit %d", ci)).Run()
   246  				Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail commit %d", ci))
   247  				err = exec.Command("git", "tag", "-a", "-m", "Nothing", fmt.Sprintf("Tag%d", ci)).Run()
   248  				Expect(err).To(BeNil(), fmt.Sprintf("Shouldn't fail tagging %d", ci))
   249  
   250  				shaspercommit = append(shaspercommit, shas)
   251  			}
   252  
   253  			// check out Tag0, thus deleting everything in Tag1/2
   254  			err := exec.Command("git", "checkout", "Tag0").Run()
   255  			Expect(err).To(BeNil(), "Shouldn't fail to checkout")
   256  			checkNotExists(1)
   257  			checkNotExists(2)
   258  			checkGitStatusNotModified()
   259  
   260  			// Now move aside storage for files in Tag1/2 so that they will be missing
   261  			// when we try to check them out
   262  			moveAsideLOBs(shaspercommit[1])
   263  			moveAsideLOBs(shaspercommit[2])
   264  			err = exec.Command("git", "checkout", "Tag2").Run()
   265  			Expect(err).To(BeNil(), "Shouldn't fail to checkout")
   266  			checkExistsAndIsPlaceholder(1)
   267  			checkExistsAndIsPlaceholder(2)
   268  
   269  			// now restore data for 1
   270  			restoreLOBs(shaspercommit[1])
   271  			// Now git-lob checkout - note we call direct not via "git lob" so we don't assume this test version is
   272  			// on the path (it probably isn't). We ignore errors because Tag2 files are still missing so will return non-zero
   273  			exec.Command(gitlobbinarypath, "checkout").Run()
   274  			checkExistsAndRightSize(1)
   275  			checkExistsAndIsPlaceholder(2)
   276  			checkGitStatusNotModified()
   277  
   278  			// now restore data for 2
   279  			restoreLOBs(shaspercommit[2])
   280  			// Now git-lob checkout - note we call direct not via "git lob" so we don't assume this test version is
   281  			// on the path (it probably isn't). Should be no errors this time since complete data
   282  			err = exec.Command(gitlobbinarypath, "checkout").Run()
   283  			Expect(err).To(BeNil(), "Shouldn't fail to git-lob checkout")
   284  			checkExistsAndRightSize(1)
   285  			checkExistsAndRightSize(2)
   286  			checkGitStatusNotModified()
   287  
   288  		})
   289  
   290  	})
   291  })