Skip to content
This repository has been archived by the owner on Apr 26, 2021. It is now read-only.

Commit

Permalink
Merge branch 'master' of github.com:tsuru/gandalf
Browse files Browse the repository at this point in the history
Conflicts:
	repository/mocks.go
  • Loading branch information
guilhermef committed Jul 2, 2014
2 parents 1c831f2 + 833c128 commit 7b87bb1
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 14 deletions.
32 changes: 31 additions & 1 deletion api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func HealthCheck(w http.ResponseWriter, r *http.Request) {

func GetFileContents(w http.ResponseWriter, r *http.Request) {
repo := r.URL.Query().Get(":name")
path := r.URL.Query().Get(":path")
path := r.URL.Query().Get("path")
ref := r.URL.Query().Get("ref")
if ref == "" {
ref = "master"
Expand Down Expand Up @@ -303,3 +303,33 @@ func GetArchive(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Expires", "Mon, 26 Jul 1997 05:00:00 GMT")
w.Write(contents)
}

func GetTree(w http.ResponseWriter, r *http.Request) {
repo := r.URL.Query().Get(":name")
path := r.URL.Query().Get("path")
ref := r.URL.Query().Get("ref")
if ref == "" {
ref = "master"
}
if path == "" {
path = "."
}
if repo == "" {
err := fmt.Errorf("Error when trying to obtain tree for path %s on ref %s of repository %s (repository is required).", path, ref, repo)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
tree, err := repository.GetTree(repo, ref, path)
if err != nil {
err := fmt.Errorf("Error when trying to obtain tree for path %s on ref %s of repository %s (%s).", path, ref, repo, err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
b, err := json.Marshal(tree)
if err != nil {
err := fmt.Errorf("Error when trying to obtain tree for path %s on ref %s of repository %s (%s).", path, ref, repo, err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
w.Write(b)
}
138 changes: 133 additions & 5 deletions api/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ func (s *S) TestHealthcheck(c *gocheck.C) {
}

func (s *S) TestGetFileContents(c *gocheck.C) {
url := "/repository/repo/contents/README.txt?:name=repo&:path=README.txt"
url := "/repository/repo/contents?:name=repo&path=README.txt"
expected := "result"
repository.Retriever = &repository.MockContentRetriever{
ResultContents: []byte(expected),
Expand All @@ -699,7 +699,7 @@ func (s *S) TestGetFileContents(c *gocheck.C) {
}

func (s *S) TestGetFileContentsWithoutExtension(c *gocheck.C) {
url := "/repository/repo/contents/README?:name=repo&:path=README"
url := "/repository/repo/contents?:name=repo&path=README"
expected := "result"
repository.Retriever = &repository.MockContentRetriever{
ResultContents: []byte(expected),
Expand All @@ -718,7 +718,7 @@ func (s *S) TestGetFileContentsWithoutExtension(c *gocheck.C) {
}

func (s *S) TestGetFileContentsWithRef(c *gocheck.C) {
url := "/repository/repo/contents/README?:name=repo&:path=README.txt&ref=other"
url := "/repository/repo/contents?:name=repo&path=README.txt&ref=other"
expected := "result"
mockRetriever := repository.MockContentRetriever{
ResultContents: []byte(expected),
Expand All @@ -739,7 +739,7 @@ func (s *S) TestGetFileContentsWithRef(c *gocheck.C) {
}

func (s *S) TestGetFileContentsWhenCommandFails(c *gocheck.C) {
url := "/repository/repo/contents/README?:name=repo&:path=README.txt&ref=other"
url := "/repository/repo/contents?:name=repo&path=README.txt&ref=other"
outputError := fmt.Errorf("command error")
repository.Retriever = &repository.MockContentRetriever{
OutputError: outputError,
Expand All @@ -756,7 +756,7 @@ func (s *S) TestGetFileContentsWhenCommandFails(c *gocheck.C) {
}

func (s *S) TestGetFileContentsWhenNoRepository(c *gocheck.C) {
url := "/repository//contents/README?:name=&:path=README.txt&ref=other"
url := "/repository//contents?:name=&path=README.txt&ref=other"
request, err := http.NewRequest("GET", url, nil)
c.Assert(err, gocheck.IsNil)
recorder := httptest.NewRecorder()
Expand Down Expand Up @@ -843,3 +843,131 @@ func (s *S) TestGetArchive(c *gocheck.C) {
c.Assert(recorder.Header()["Pragma"][0], gocheck.Equals, "private")
c.Assert(recorder.Header()["Expires"][0], gocheck.Equals, "Mon, 26 Jul 1997 05:00:00 GMT")
}

func (s *S) TestGetTreeWithDefaultValues(c *gocheck.C) {
url := "/repository/repo/tree?:name=repo"
tree := make([]map[string]string, 1)
tree[0] = make(map[string]string)
tree[0]["permission"] = "333"
tree[0]["filetype"] = "blob"
tree[0]["hash"] = "123456"
tree[0]["path"] = "filename.txt"
tree[0]["rawPath"] = "raw/filename.txt"
mockRetriever := repository.MockContentRetriever{
Tree: tree,
}
repository.Retriever = &mockRetriever
defer func() {
repository.Retriever = nil
}()
request, err := http.NewRequest("GET", url, nil)
c.Assert(err, gocheck.IsNil)
recorder := httptest.NewRecorder()
GetTree(recorder, request)
c.Assert(recorder.Code, gocheck.Equals, http.StatusOK)
var obj []map[string]string
json.Unmarshal(recorder.Body.Bytes(), &obj)
c.Assert(len(obj), gocheck.Equals, 1)
c.Assert(obj[0]["permission"], gocheck.Equals, tree[0]["permission"])
c.Assert(obj[0]["filetype"], gocheck.Equals, tree[0]["filetype"])
c.Assert(obj[0]["hash"], gocheck.Equals, tree[0]["hash"])
c.Assert(obj[0]["path"], gocheck.Equals, tree[0]["path"])
c.Assert(obj[0]["rawPath"], gocheck.Equals, tree[0]["rawPath"])
c.Assert(mockRetriever.LastRef, gocheck.Equals, "master")
c.Assert(mockRetriever.LastPath, gocheck.Equals, ".")
}

func (s *S) TestGetTreeWithSpecificPath(c *gocheck.C) {
url := "/repository/repo/tree?:name=repo&path=/test"
tree := make([]map[string]string, 1)
tree[0] = make(map[string]string)
tree[0]["permission"] = "333"
tree[0]["filetype"] = "blob"
tree[0]["hash"] = "123456"
tree[0]["path"] = "/test/filename.txt"
tree[0]["rawPath"] = "/test/raw/filename.txt"
mockRetriever := repository.MockContentRetriever{
Tree: tree,
}
repository.Retriever = &mockRetriever
defer func() {
repository.Retriever = nil
}()
request, err := http.NewRequest("GET", url, nil)
c.Assert(err, gocheck.IsNil)
recorder := httptest.NewRecorder()
GetTree(recorder, request)
c.Assert(recorder.Code, gocheck.Equals, http.StatusOK)
var obj []map[string]string
json.Unmarshal(recorder.Body.Bytes(), &obj)
c.Assert(len(obj), gocheck.Equals, 1)
c.Assert(obj[0]["permission"], gocheck.Equals, tree[0]["permission"])
c.Assert(obj[0]["filetype"], gocheck.Equals, tree[0]["filetype"])
c.Assert(obj[0]["hash"], gocheck.Equals, tree[0]["hash"])
c.Assert(obj[0]["path"], gocheck.Equals, tree[0]["path"])
c.Assert(obj[0]["rawPath"], gocheck.Equals, tree[0]["rawPath"])
c.Assert(mockRetriever.LastRef, gocheck.Equals, "master")
c.Assert(mockRetriever.LastPath, gocheck.Equals, "/test")
}

func (s *S) TestGetTreeWithSpecificRef(c *gocheck.C) {
url := "/repository/repo/tree?:name=repo&path=/test&ref=1.1.1"
tree := make([]map[string]string, 1)
tree[0] = make(map[string]string)
tree[0]["permission"] = "333"
tree[0]["filetype"] = "blob"
tree[0]["hash"] = "123456"
tree[0]["path"] = "/test/filename.txt"
tree[0]["rawPath"] = "/test/raw/filename.txt"
mockRetriever := repository.MockContentRetriever{
Tree: tree,
}
repository.Retriever = &mockRetriever
defer func() {
repository.Retriever = nil
}()
request, err := http.NewRequest("GET", url, nil)
c.Assert(err, gocheck.IsNil)
recorder := httptest.NewRecorder()
GetTree(recorder, request)
c.Assert(recorder.Code, gocheck.Equals, http.StatusOK)
var obj []map[string]string
json.Unmarshal(recorder.Body.Bytes(), &obj)
c.Assert(len(obj), gocheck.Equals, 1)
c.Assert(obj[0]["permission"], gocheck.Equals, tree[0]["permission"])
c.Assert(obj[0]["filetype"], gocheck.Equals, tree[0]["filetype"])
c.Assert(obj[0]["hash"], gocheck.Equals, tree[0]["hash"])
c.Assert(obj[0]["path"], gocheck.Equals, tree[0]["path"])
c.Assert(obj[0]["rawPath"], gocheck.Equals, tree[0]["rawPath"])
c.Assert(mockRetriever.LastRef, gocheck.Equals, "1.1.1")
c.Assert(mockRetriever.LastPath, gocheck.Equals, "/test")
}

func (s *S) TestGetTreeWhenNoRepo(c *gocheck.C) {
url := "/repository//tree?:name="
request, err := http.NewRequest("GET", url, nil)
c.Assert(err, gocheck.IsNil)
recorder := httptest.NewRecorder()
GetTree(recorder, request)
c.Assert(recorder.Code, gocheck.Equals, http.StatusBadRequest)
expected := "Error when trying to obtain tree for path . on ref master of repository (repository is required).\n"
c.Assert(recorder.Body.String(), gocheck.Equals, expected)
}

func (s *S) TestGetTreeWhenCommandFails(c *gocheck.C) {
url := "/repository/repo/tree/?:name=repo&ref=master&path=/test"
expected := fmt.Errorf("output error")
mockRetriever := repository.MockContentRetriever{
OutputError: expected,
}
repository.Retriever = &mockRetriever
defer func() {
repository.Retriever = nil
}()
request, err := http.NewRequest("GET", url, nil)
c.Assert(err, gocheck.IsNil)
recorder := httptest.NewRecorder()
GetTree(recorder, request)
c.Assert(recorder.Code, gocheck.Equals, http.StatusBadRequest)
c.Assert(recorder.Body.String(), gocheck.Equals, "Error when trying to obtain tree for path /test on ref master of repository repo (output error).\n")
}
52 changes: 51 additions & 1 deletion docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Get file contents
Returns the contents for a `path` in the specified `repository` with the given `ref` (commit, tag or branch).

* Method: GET
* URI: /repository/`:name`/contents/`:path`?ref=:ref
* URI: /repository/`:name`/contents?ref=:ref&path=:path
* Format: binary

Where:
Expand All @@ -65,6 +65,50 @@ Where:
* `:path` is the file path in the repository file system;
* `:ref` is the repository ref (commit, tag or branch). **This is optional**. If not passed this is assumed to be "master".

Example URLs (http://gandalf-server omitted for clarity)::

$ curl /repository/myrepository/contents?ref=0.1.0&path=/some/path/in/the/repo.txt
$ curl /repository/myrepository/contents?path=/some/path/in/the/repo.txt # gets master

Get tree
--------

Returns a list of all the files under a `path` in the specified `repository` with the given `ref` (commit, tag or branch).

* Method: GET
* URI: /repository/`:name`/tree?ref=:ref&path=:path
* Format: JSON

Where:

* `:name` is the name of the repository;
* `:path` is the file path in the repository file system. **This is optional**. If not passed this is assumed to be ".";
* `:ref` is the repository ref (commit, tag or branch). **This is optional**. If not passed this is assumed to be "master".

Example result::

[{
filetype: "blob",
hash: "6767b5de5943632e47cb6f8bf5b2147bc0be5cf8",
path: ".gitignore",
permission: "100644",
rawPath: ".gitignore"
}, {
filetype: "blob",
hash: "fbd8b6db62282a8402a4fc5503e9a886b4fb8b4b",
path: ".travis.yml",
permission: "100644",
rawPath: ".travis.yml"
}]

`rawPath` contains exactly the value returned from git (with escaped characters, quotes, etc), while `path` is somewhat cleaner (spaces removed, quotes removed from the left and right).

Example URLs (http://gandalf-server omitted for clarity)::

$ curl /repository/myrepository/tree # gets master and root path(.)
$ curl /repository/myrepository/tree?ref=0.1.0 # gets 0.1.0 tag and root path(.)
$ curl /repository/myrepository/tree?ref=0.1.0&path=/myrepository # gets 0.1.0 tag and files under /myrepository

Get archive
-----------

Expand All @@ -79,3 +123,9 @@ Where:
* `:name` is the name of the repository;
* `:ref` is the repository ref (commit, tag or branch);
* `:format` is the format to return the archive. This can be zip, tar or tar.gz.

Example URLs (http://gandalf-server omitted for clarity)::

$ curl /repository/myrepository/archive/master.zip # gets master and zip format
$ curl /repository/myrepository/archive/master.tar.gz # gets master and tar.gz format
$ curl /repository/myrepository/archive/0.1.0.zip # gets 0.1.0 tag and zip format
28 changes: 22 additions & 6 deletions repository/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (
type MockContentRetriever struct {
LastFormat ArchiveFormat
LastRef string
LastPath string
ResultContents []byte
Tree []map[string]string
LookPathError error
OutputError error
}
Expand Down Expand Up @@ -54,13 +56,13 @@ func CreateTestRepository(tmp_path string, repo string, file string, content str
if err != nil {
return cleanup, err
}
out, err := exec.Command("mkdir", "-p", testPath).Output()
_, err = exec.Command("mkdir", "-p", testPath).Output()
if err != nil {
return cleanup, err
}
cmd := exec.Command(gitPath, "init")
cmd.Dir = testPath
out, err = cmd.Output()
_, err = cmd.Output()
if err != nil {
return cleanup, err
}
Expand All @@ -70,24 +72,38 @@ func CreateTestRepository(tmp_path string, repo string, file string, content str
}
cmd = exec.Command(gitPath, "add", file)
cmd.Dir = testPath
out, err = cmd.Output()
_, err = cmd.Output()
if err != nil {
return cleanup, err
}
cmd = exec.Command(gitPath, "config", "user.email", "much@email.com")
cmd.Dir = testPath
out, err = cmd.Output()
_, err = cmd.Output()
if err != nil {
return cleanup, err
}
cmd = exec.Command(gitPath, "config", "user.name", "doge")
cmd.Dir = testPath
out, err = cmd.Output()
_, err = cmd.Output()
if err != nil {
return cleanup, err
}
cmd = exec.Command(gitPath, "commit", "-m", content)
cmd.Dir = testPath
out, err = cmd.Output()
_, err = cmd.Output()
return cleanup, err
}

func (r *MockContentRetriever) GetTree(repo, ref, path string) ([]map[string]string, error) {
if r.LookPathError != nil {
return nil, r.LookPathError
}

if r.OutputError != nil {
return nil, r.OutputError
}

r.LastRef = ref
r.LastPath = path
return r.Tree, nil
}

0 comments on commit 7b87bb1

Please sign in to comment.