diff --git a/repository/repository.go b/repository/repository.go index 6548e27..0ab8c14 100644 --- a/repository/repository.go +++ b/repository/repository.go @@ -15,6 +15,7 @@ import ( "io/ioutil" "labix.org/v2/mgo" "labix.org/v2/mgo/bson" + "os" "os/exec" "regexp" "strings" @@ -28,6 +29,18 @@ type Repository struct { IsPublic bool } +// exists returns whether the given file or directory exists or not +func exists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + // MarshalJSON marshals the Repository in json format. func (r *Repository) MarshalJSON() ([]byte, error) { data := map[string]interface{}{ @@ -248,6 +261,10 @@ func (*GitContentRetriever) GetContents(repo, ref, path string) ([]byte, error) return nil, fmt.Errorf("Error when trying to obtain file %s on ref %s of repository %s (%s).", path, ref, repo, err) } cwd := barePath(repo) + repoExists, err := exists(cwd) + if err != nil || !repoExists { + return nil, fmt.Errorf("Error when trying to obtain file %s on ref %s of repository %s (Repository does not exist).", path, ref, repo) + } cmd := exec.Command(gitPath, "show", fmt.Sprintf("%s:%s", ref, path)) cmd.Dir = cwd out, err := cmd.Output() @@ -273,6 +290,10 @@ func (*GitContentRetriever) GetArchive(repo, ref string, format ArchiveFormat) ( } prefix := fmt.Sprintf("--prefix=%s-%s/", repo, ref) cwd := barePath(repo) + repoExists, err := exists(cwd) + if err != nil || !repoExists { + return nil, fmt.Errorf("Error when trying to obtain archive for ref %s of repository %s (Repository does not exist).", ref, repo) + } cmd := exec.Command(gitPath, "archive", ref, prefix, archiveFormat) cmd.Dir = cwd out, err := cmd.Output() @@ -285,9 +306,13 @@ func (*GitContentRetriever) GetArchive(repo, ref string, format ArchiveFormat) ( func (*GitContentRetriever) GetTree(repo, ref, path string) ([]map[string]string, error) { gitPath, err := exec.LookPath("git") if err != nil { - return nil, fmt.Errorf("Error when trying to obtain file %s on ref %s of repository %s (%s).", path, ref, repo, err) + return nil, fmt.Errorf("Error when trying to obtain tree %s on ref %s of repository %s (%s).", path, ref, repo, err) } cwd := barePath(repo) + repoExists, err := exists(cwd) + if err != nil || !repoExists { + return nil, fmt.Errorf("Error when trying to obtain tree %s on ref %s of repository %s (Repository does not exist).", path, ref, repo) + } cmd := exec.Command(gitPath, "ls-tree", "-r", ref, path) cmd.Dir = cwd out, err := cmd.Output() diff --git a/repository/repository_test.go b/repository/repository_test.go index 639ef07..b276562 100644 --- a/repository/repository_test.go +++ b/repository/repository_test.go @@ -5,6 +5,9 @@ package repository import ( + "archive/tar" + "archive/zip" + "bytes" "encoding/json" "fmt" "github.com/tsuru/commandmocker" @@ -12,6 +15,8 @@ import ( "github.com/tsuru/gandalf/db" "github.com/tsuru/gandalf/fs" fstesting "github.com/tsuru/tsuru/fs/testing" + "io" + "io/ioutil" "labix.org/v2/mgo/bson" "launchpad.net/gocheck" "path" @@ -618,3 +623,115 @@ func (s *S) TestGetTreeIntegrationWithFileNameWithSpace(c *gocheck.C) { c.Assert(tree[0]["path"], gocheck.Equals, "much/much README") c.Assert(tree[0]["rawPath"], gocheck.Equals, "much/much README") } + +func (s *S) TestGetArchiveIntegrationWhenZip(c *gocheck.C) { + expected := make(map[string]string) + expected["gandalf-test-repo-master/README"] = "much WOW" + oldBare := bare + bare = "/tmp" + repo := "gandalf-test-repo" + file := "README" + content := "much WOW" + cleanUp, errCreate := CreateTestRepository(bare, repo, file, content) + defer func() { + cleanUp() + bare = oldBare + }() + c.Assert(errCreate, gocheck.IsNil) + zipContents, err := GetArchive(repo, "master", Zip) + reader := bytes.NewReader(zipContents) + zipReader, err := zip.NewReader(reader, int64(len(zipContents))) + c.Assert(err, gocheck.IsNil) + for _, f := range zipReader.File { + //fmt.Printf("Contents of %s:\n", f.Name) + rc, err := f.Open() + c.Assert(err, gocheck.IsNil) + defer rc.Close() + contents, err := ioutil.ReadAll(rc) + c.Assert(err, gocheck.IsNil) + c.Assert(string(contents), gocheck.Equals, expected[f.Name]) + } +} + +func (s *S) TestGetArchiveIntegrationWhenTar(c *gocheck.C) { + expected := make(map[string]string) + expected["gandalf-test-repo-master/README"] = "much WOW" + oldBare := bare + bare = "/tmp" + repo := "gandalf-test-repo" + file := "README" + content := "much WOW" + cleanUp, errCreate := CreateTestRepository(bare, repo, file, content) + defer func() { + cleanUp() + bare = oldBare + }() + c.Assert(errCreate, gocheck.IsNil) + tarContents, err := GetArchive(repo, "master", Tar) + c.Assert(err, gocheck.IsNil) + reader := bytes.NewReader(tarContents) + tarReader := tar.NewReader(reader) + c.Assert(err, gocheck.IsNil) + for { + hdr, err := tarReader.Next() + if err == io.EOF { + // end of tar archive + break + } + c.Assert(err, gocheck.IsNil) + path := hdr.Name + _, ok := expected[path] + if !ok { + continue + } + buffer := new(bytes.Buffer) + _, err = io.Copy(buffer, tarReader) + c.Assert(err, gocheck.IsNil) + c.Assert(buffer.String(), gocheck.Equals, expected[path]) + } +} + +func (s *S) TestGetArchiveIntegrationWhenInvalidFormat(c *gocheck.C) { + expected := make(map[string]string) + expected["gandalf-test-repo-master/README"] = "much WOW" + oldBare := bare + bare = "/tmp" + repo := "gandalf-test-repo" + file := "README" + content := "much WOW" + cleanUp, errCreate := CreateTestRepository(bare, repo, file, content) + defer func() { + cleanUp() + bare = oldBare + }() + c.Assert(errCreate, gocheck.IsNil) + zipContents, err := GetArchive(repo, "master", 99) + reader := bytes.NewReader(zipContents) + zipReader, err := zip.NewReader(reader, int64(len(zipContents))) + c.Assert(err, gocheck.IsNil) + for _, f := range zipReader.File { + //fmt.Printf("Contents of %s:\n", f.Name) + rc, err := f.Open() + c.Assert(err, gocheck.IsNil) + defer rc.Close() + contents, err := ioutil.ReadAll(rc) + c.Assert(err, gocheck.IsNil) + c.Assert(string(contents), gocheck.Equals, expected[f.Name]) + } +} + +func (s *S) TestGetArchiveIntegrationWhenInvalidRepo(c *gocheck.C) { + oldBare := bare + bare = "/tmp" + repo := "gandalf-test-repo" + file := "README" + content := "much WOW" + cleanUp, errCreate := CreateTestRepository(bare, repo, file, content) + defer func() { + cleanUp() + bare = oldBare + }() + c.Assert(errCreate, gocheck.IsNil) + _, err := GetArchive("invalid-repo", "master", Zip) + c.Assert(err.Error(), gocheck.Equals, "Error when trying to obtain archive for ref master of repository invalid-repo (Repository does not exist).") +}