Also insert trees into cache if they came from a Git repository.
If Git repositories are on spinning storage, the trees are relatively
expensive to construct.
Change-Id: I49680a5b254f0f2b0c0190e439c512ce2625a3fb
diff --git a/fs/manifestfs.go b/fs/manifestfs.go
index 2450c02..b5b6ebc 100644
--- a/fs/manifestfs.go
+++ b/fs/manifestfs.go
@@ -231,6 +231,7 @@
}
tree, err := c.Tree.Get(revID)
+ cached := (err == nil && tree != nil)
if err != nil {
if repo := c.Git.OpenLocal(p.CloneURL); repo != nil {
defer repo.Free()
@@ -242,10 +243,11 @@
repoService := service.NewRepoService(p.Name)
tree, err = repoService.GetTree(p.Revision, "", true)
- if err == nil {
- if err := c.Tree.Add(revID, tree); err != nil {
- log.Printf("treeCache.Add: %v", err)
- }
+ }
+
+ if !cached && tree != nil && err == nil {
+ if err := c.Tree.Add(revID, tree); err != nil {
+ log.Printf("treeCache.Add: %v", err)
}
}
diff --git a/fs/manifestfs_test.go b/fs/manifestfs_test.go
index 05c1ca9..2f3aa86 100644
--- a/fs/manifestfs_test.go
+++ b/fs/manifestfs_test.go
@@ -18,9 +18,11 @@
"fmt"
"io/ioutil"
"os"
+ "os/exec"
"path/filepath"
"reflect"
"sort"
+ "strings"
"syscall"
"testing"
"time"
@@ -30,6 +32,8 @@
"github.com/google/slothfs/manifest"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
+
+ git "github.com/libgit2/git2go"
)
func newManifestTestFixture(mf *manifest.Manifest) (*testFixture, error) {
@@ -53,6 +57,82 @@
return fix, nil
}
+func TestManifestFSGitRepoSeedsTreeCache(t *testing.T) {
+ fix, err := newTestFixture()
+ if err != nil {
+ t.Fatal("newTestFixture", err)
+ }
+ defer fix.cleanup()
+
+ // Add a git repo.
+ cmd := exec.Command("/bin/sh", "-c",
+ strings.Join([]string{
+ "mkdir -p localhost/platform/build/kati.git",
+ "cd localhost/platform/build/kati.git",
+ "git init",
+ "touch file",
+ "git add file",
+ "git commit -m msg -a",
+ "git show --no-patch --pretty=format:'%H' HEAD | head",
+ }, " && "))
+ cmd.Dir = filepath.Join(fix.dir, "cache", "git")
+
+ headSHA1 := ""
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Fatalf("create repo: %v, out: %s", err, string(out))
+ } else {
+ lines := strings.Split(string(out), "\n")
+ headSHA1 = lines[len(lines)-1]
+ }
+
+ p := testManifest.Project[0]
+ p.CloneURL = "file:///localhost/platform/build/kati"
+ p.Revision = headSHA1
+
+ mf := *testManifest
+ mf.Project = nil
+ mf.Project = append(mf.Project, p)
+
+ opts := ManifestOptions{
+ Manifest: &mf,
+ }
+
+ fs, err := NewManifestFS(fix.service, fix.cache, opts)
+ if err != nil {
+ t.Fatal("NewManifestFS", err)
+ }
+ if err := fix.mount(fs); err != nil {
+ t.Fatal("mount", err)
+ }
+
+ headID, err := git.NewOid(headSHA1)
+ if err != nil {
+ t.Fatal("NewOid(%q): %v", headSHA1, err)
+ }
+
+ tree, err := fix.cache.Tree.Get(headID)
+ if err != nil {
+ t.Fatalf("treeCache.Get(%s): %v", headSHA1, err)
+ }
+
+ newInt := func(n int) *int { return &n }
+ tree.ID = ""
+ want := &gitiles.Tree{
+ Entries: []gitiles.TreeEntry{
+ {
+ Name: "file",
+ Mode: 0100644,
+ Type: "blob",
+ ID: "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+ Size: newInt(0),
+ },
+ },
+ }
+ if !reflect.DeepEqual(tree, want) {
+ t.Errorf("got cached tree %v, want %v", tree, want)
+ }
+}
+
func TestManifestFSCloneOption(t *testing.T) {
mf := *testManifest
for i := range mf.Project {
diff --git a/gitiles/types.go b/gitiles/types.go
index 0b9a593..56a3da5 100644
--- a/gitiles/types.go
+++ b/gitiles/types.go
@@ -14,7 +14,10 @@
package gitiles
-import "fmt"
+import (
+ "bytes"
+ "fmt"
+)
// Project describes a repository
type Project struct {
@@ -103,3 +106,14 @@
ID string
Entries []TreeEntry
}
+
+func (t *Tree) String() string {
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "tree %s {\n", t.ID)
+ for _, e := range t.Entries {
+ fmt.Fprintf(&buf, " %s\n", e.String())
+ }
+ fmt.Fprintf(&buf, "}\n")
+ return buf.String()
+
+}