diff options
author | Alejandro Rodríguez <alejorro70@gmail.com> | 2016-12-23 03:12:39 +0300 |
---|---|---|
committer | Alejandro Rodríguez <alejorro70@gmail.com> | 2016-12-23 03:12:39 +0300 |
commit | e554214aaa8ab3c5186c817781d8c83428f60f0c (patch) | |
tree | efe661f0ca5ab4220f5ef0d5c341c78517b0da50 | |
parent | 577ed944fadf424e28e08f83e5f6784d8ea57d98 (diff) |
Add function to cache calls to git-upload-pack and git-receive-packinfo-refs
-rw-r--r-- | caching/refs.go | 82 | ||||
-rw-r--r-- | caching/resf_test.go | 23 |
2 files changed, 97 insertions, 8 deletions
diff --git a/caching/refs.go b/caching/refs.go index dd0d6fa3a..252ecea66 100644 --- a/caching/refs.go +++ b/caching/refs.go @@ -1,7 +1,12 @@ package caching import ( + "bytes" + "fmt" + "io" + "io/ioutil" "os" + "os/exec" "path" "syscall" @@ -11,8 +16,7 @@ import ( type RefsCache struct { repositoryPath string cacheDir string - uploadCachePath string - receiveCachePath string + cachePaths map[string]string lockFd int } @@ -43,8 +47,10 @@ func NewRefsCache(repositoryPath string) *RefsCache { repositoryPath: repositoryPath, cacheDir: cacheDir, lockFd: lockFd, - uploadCachePath: path.Join(cacheDir, "upload-pack"), - receiveCachePath: path.Join(cacheDir, "receive-pack"), + cachePaths: map[string]string { + "upload-pack": path.Join(cacheDir, "upload-pack"), + "receive-pack": path.Join(cacheDir, "receive-pack"), + }, } } @@ -68,6 +74,18 @@ func (r *RefsCache) Unlock() { } } +func (r *RefsCache) GetLockUuid() string { + var buf [4096]byte + + syscall.Seek(r.lockFd, 0, 0) // Rewind to the start of the file + n, err := syscall.Read(r.lockFd, buf[:]) + if err != nil { + panic(err) + } + + return string(buf[:n]) +} + func (r *RefsCache) InvalidateCache() { r.Lock() defer r.Unlock() @@ -79,6 +97,58 @@ func (r *RefsCache) InvalidateCache() { syscall.Write(r.lockFd, []byte(newUuid.String())) // Remove cache files - os.Remove(r.uploadCachePath) - os.Remove(r.receiveCachePath) + for _, cachePath := range r.cachePaths { + os.Remove(cachePath) + } +} + +func (r *RefsCache) ExecuteToFile(command string, f *os.File) { + var out bytes.Buffer + cmd := exec.Command("git", command, "--stateless-rpc", "--advertise-refs", r.repositoryPath) + cmd.Stdout = &out + + err := cmd.Run() + if err != nil { + panic(err) + } + + // Print to Stdout + out.WriteTo(os.Stdout) + + // Print to file + _, err = f.Write(out.Bytes()) + if err != nil { + panic(err) + } +} + +func (r *RefsCache) Cache(command string) error { + if command != "upload-pack" && command != "receive-pack" { + return fmt.Errorf("Invalid command") + } + + r.Lock() + defer r.Unlock() + + currentUuid := r.GetLockUuid() + fmt.Printf(path.Join(os.TempDir(), "command_output")) + tempFile, err := ioutil.TempFile(os.TempDir(), "command_output") + if err != nil { + panic(err) + } + defer tempFile.Close() + + r.ExecuteToFile(command, tempFile) + + if newUuid := r.GetLockUuid(); currentUuid == newUuid { + cacheFile, err := os.Create(r.cachePaths[command]) + if err != nil { + panic(err) + } + defer cacheFile.Close() + tempFile.Seek(0, 0) // Reset tempFile to the start of the file + io.Copy(cacheFile, tempFile) + } + + return nil } diff --git a/caching/resf_test.go b/caching/resf_test.go index 565d63860..ca3ab580b 100644 --- a/caching/resf_test.go +++ b/caching/resf_test.go @@ -3,6 +3,7 @@ package caching import ( "io/ioutil" "os" + "os/exec" "path" "syscall" "testing" @@ -36,10 +37,28 @@ func TestInvalidateCache(t *testing.T) { t.Error("Expected InvalidateCache to rewrite lock") } - if _, err := os.Stat(r.uploadCachePath); !os.IsNotExist(err) { + if _, err := os.Stat(r.cachePaths["upload-pack"]); !os.IsNotExist(err) { t.Error("Expected InvalidateCache to remove upload-pack cache") } - if _, err := os.Stat(r.receiveCachePath); !os.IsNotExist(err) { + if _, err := os.Stat(r.cachePaths["receive-pack"]); !os.IsNotExist(err) { t.Error("Expected InvalidateCache to remove receive-pack cache") } } + +func TestCache(t *testing.T) { + source := "https://gitlab.com/gitlab-org/gitlab-test.git" + repoDir := path.Join(tmpDir, "gitlab-test") + exec.Command("git", "clone", "--bare", source, repoDir).Run() + r := NewRefsCache(repoDir) + defer os.RemoveAll(tmpDir) + + if err := r.Cache("non-existing-command"); err.Error() != "Invalid command" { + t.Error("Expected Cache to fail with \"Invalid command\"") + } + + r.Cache("upload-pack") + + if _, err := os.Stat(r.cachePaths["upload-pack"]); os.IsNotExist(err) { + t.Error("Expected Cache to create upload-pack cache") + } +} |