diff options
Diffstat (limited to 'modules/git')
-rw-r--r-- | modules/git/blob.go | 2 | ||||
-rw-r--r-- | modules/git/commit.go | 14 | ||||
-rw-r--r-- | modules/git/commit_archive.go | 2 | ||||
-rw-r--r-- | modules/git/error.go | 22 | ||||
-rw-r--r-- | modules/git/repo.go | 3 | ||||
-rw-r--r-- | modules/git/repo_branch.go | 13 | ||||
-rw-r--r-- | modules/git/repo_commit.go | 8 | ||||
-rw-r--r-- | modules/git/repo_pull.go | 52 | ||||
-rw-r--r-- | modules/git/repo_tag.go | 4 | ||||
-rw-r--r-- | modules/git/sha1.go | 2 | ||||
-rw-r--r-- | modules/git/signature.go | 16 | ||||
-rw-r--r-- | modules/git/signature_test.go | 20 | ||||
-rw-r--r-- | modules/git/submodule.go | 3 | ||||
-rw-r--r-- | modules/git/tag.go | 2 | ||||
-rw-r--r-- | modules/git/tree.go | 39 | ||||
-rw-r--r-- | modules/git/tree_blob.go | 2 | ||||
-rw-r--r-- | modules/git/tree_entry.go | 4 | ||||
-rw-r--r-- | modules/git/utils.go | 5 |
18 files changed, 161 insertions, 52 deletions
diff --git a/modules/git/blob.go b/modules/git/blob.go index 3ce462a3..bdf0cae4 100644 --- a/modules/git/blob.go +++ b/modules/git/blob.go @@ -18,7 +18,7 @@ type Blob struct { } func (b *Blob) Data() (io.Reader, error) { - stdout, stderr, err := com.ExecCmdDirBytes(b.repo.Path, "git", "show", b.Id.String()) + stdout, stderr, err := com.ExecCmdDirBytes(b.repo.Path, "git", "show", b.ID.String()) if err != nil { return nil, errors.New(string(stderr)) } diff --git a/modules/git/commit.go b/modules/git/commit.go index da0ab644..674a0b85 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -14,7 +14,7 @@ import ( // Commit represents a git commit. type Commit struct { Tree - Id sha1 // The id of this commit object + ID sha1 // The id of this commit object Author *Signature Committer *Signature CommitMessage string @@ -35,7 +35,7 @@ func (c *Commit) Summary() string { // Return oid of the parent number n (0-based index). Return nil if no such parent exists. func (c *Commit) ParentId(n int) (id sha1, err error) { if n >= len(c.parents) { - err = IdNotExist + err = IDNotExist return } return c.parents[n], nil @@ -61,7 +61,7 @@ func (c *Commit) ParentCount() int { } func (c *Commit) CommitsBefore() (*list.List, error) { - return c.repo.getCommitsBefore(c.Id) + return c.repo.getCommitsBefore(c.ID) } func (c *Commit) CommitsBeforeUntil(commitId string) (*list.List, error) { @@ -73,19 +73,19 @@ func (c *Commit) CommitsBeforeUntil(commitId string) (*list.List, error) { } func (c *Commit) CommitsCount() (int, error) { - return c.repo.commitsCount(c.Id) + return c.repo.commitsCount(c.ID) } func (c *Commit) SearchCommits(keyword string) (*list.List, error) { - return c.repo.searchCommits(c.Id, keyword) + return c.repo.searchCommits(c.ID, keyword) } func (c *Commit) CommitsByRange(page int) (*list.List, error) { - return c.repo.commitsByRange(c.Id, page) + return c.repo.commitsByRange(c.ID, page) } func (c *Commit) GetCommitOfRelPath(relPath string) (*Commit, error) { - return c.repo.getCommitOfRelPath(c.Id, relPath) + return c.repo.getCommitOfRelPath(c.ID, relPath) } func (c *Commit) GetSubModule(entryname string) (*SubModule, error) { diff --git a/modules/git/commit_archive.go b/modules/git/commit_archive.go index 23b4b058..8bb6b129 100644 --- a/modules/git/commit_archive.go +++ b/modules/git/commit_archive.go @@ -28,7 +28,7 @@ func (c *Commit) CreateArchive(path string, archiveType ArchiveType) error { return fmt.Errorf("unknown format: %v", archiveType) } - _, stderr, err := com.ExecCmdDir(c.repo.Path, "git", "archive", "--format="+format, "-o", path, c.Id.String()) + _, stderr, err := com.ExecCmdDir(c.repo.Path, "git", "archive", "--format="+format, "-o", path, c.ID.String()) if err != nil { return fmt.Errorf("%s", stderr) } diff --git a/modules/git/error.go b/modules/git/error.go new file mode 100644 index 00000000..c86c56e5 --- /dev/null +++ b/modules/git/error.go @@ -0,0 +1,22 @@ +// Copyright 2015 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package git + +import ( + "fmt" +) + +type ErrUnsupportedVersion struct { + Required string +} + +func IsErrUnsupportedVersion(err error) bool { + _, ok := err.(ErrUnsupportedVersion) + return ok +} + +func (err ErrUnsupportedVersion) Error() string { + return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required) +} diff --git a/modules/git/repo.go b/modules/git/repo.go index 14ac39a3..39fad97d 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -5,6 +5,7 @@ package git import ( + "errors" "path/filepath" ) @@ -21,6 +22,8 @@ func OpenRepository(repoPath string) (*Repository, error) { repoPath, err := filepath.Abs(repoPath) if err != nil { return nil, err + } else if !isDir(repoPath) { + return nil, errors.New("no such file or directory") } return &Repository{Path: repoPath}, nil diff --git a/modules/git/repo_branch.go b/modules/git/repo_branch.go index a4e06053..86c4f538 100644 --- a/modules/git/repo_branch.go +++ b/modules/git/repo_branch.go @@ -35,3 +35,16 @@ func (repo *Repository) GetBranches() ([]string, error) { } return branches, nil } + +// SetDefaultBranch sets default branch of repository. +func (repo *Repository) SetDefaultBranch(branchName string) error { + if gitVer.LessThan(MustParseVersion("1.7.10")) { + return ErrUnsupportedVersion{"1.7.10"} + } + + _, stderr, err := com.ExecCmdDir(repo.Path, "git", "symbolic-ref", "HEAD", "refs/heads/"+branchName) + if err != nil { + return concatenateError(err, stderr) + } + return nil +} diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index e8ac2dfc..28633058 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -70,7 +70,7 @@ l: if err != nil { return nil, err } - commit.Tree.Id = id + commit.Tree.ID = id case "parent": // A commit can have one or more parents oid, err := NewIdFromString(string(line[spacepos+1:])) @@ -121,7 +121,7 @@ func (repo *Repository) getCommit(id sha1) (*Commit, error) { return nil, err } commit.repo = repo - commit.Id = id + commit.ID = id repo.commitCache[id] = commit return commit, nil @@ -211,7 +211,7 @@ func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List var err error cur := last for { - if cur.Id.Equal(before.Id) { + if cur.ID.Equal(before.ID) { break } l.PushBack(cur) @@ -240,7 +240,7 @@ func (repo *Repository) commitsBefore(lock *sync.Mutex, l *list.List, parent *li for { if in == nil { break - } else if in.Value.(*Commit).Id.Equal(commit.Id) { + } else if in.Value.(*Commit).ID.Equal(commit.ID) { return nil } else { if in.Next() == nil { diff --git a/modules/git/repo_pull.go b/modules/git/repo_pull.go index a9cc33a1..f9ea7100 100644 --- a/modules/git/repo_pull.go +++ b/modules/git/repo_pull.go @@ -20,31 +20,55 @@ type PullRequestInfo struct { NumFiles int } +// GetMergeBase checks and returns merge base of two branches. +func (repo *Repository) GetMergeBase(remoteBranch, headBranch string) (string, error) { + // Get merge base commit. + stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "merge-base", remoteBranch, headBranch) + if err != nil { + return "", fmt.Errorf("get merge base: %v", concatenateError(err, stderr)) + } + return strings.TrimSpace(stdout), nil +} + +// AddRemote adds a remote to repository. +func (repo *Repository) AddRemote(name, path string) error { + _, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "add", "-f", name, path) + if err != nil { + return fmt.Errorf("add remote(%s - %s): %v", name, path, concatenateError(err, stderr)) + } + return nil +} + +// RemoveRemote removes a remote from repository. +func (repo *Repository) RemoveRemote(name string) error { + _, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "remove", name) + if err != nil { + return fmt.Errorf("remove remote(%s): %v", name, concatenateError(err, stderr)) + } + return nil +} + // GetPullRequestInfo generates and returns pull request information // between base and head branches of repositories. -func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (*PullRequestInfo, error) { +func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (_ *PullRequestInfo, err error) { // Add a temporary remote. tmpRemote := com.ToStr(time.Now().UnixNano()) - _, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "add", "-f", tmpRemote, basePath) - if err != nil { - return nil, fmt.Errorf("add base as remote: %v", concatenateError(err, stderr)) + if err = repo.AddRemote(tmpRemote, basePath); err != nil { + return nil, fmt.Errorf("AddRemote: %v", err) } defer func() { - com.ExecCmdDir(repo.Path, "git", "remote", "remove", tmpRemote) + repo.RemoveRemote(tmpRemote) }() - prInfo := new(PullRequestInfo) - - var stdout string remoteBranch := "remotes/" + tmpRemote + "/" + baseBranch - // Get merge base commit. - stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "merge-base", remoteBranch, headBranch) + + prInfo := new(PullRequestInfo) + prInfo.MergeBase, err = repo.GetMergeBase(remoteBranch, headBranch) if err != nil { - return nil, fmt.Errorf("get merge base: %v", concatenateError(err, stderr)) + return nil, fmt.Errorf("GetMergeBase: %v", err) } - prInfo.MergeBase = strings.TrimSpace(stdout) - stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "log", prInfo.MergeBase+"..."+headBranch, prettyLogFormat) + stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "log", prInfo.MergeBase+"..."+headBranch, prettyLogFormat) if err != nil { return nil, fmt.Errorf("list diff logs: %v", concatenateError(err, stderr)) } @@ -65,7 +89,7 @@ func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch stri // GetPatch generates and returns patch data between given branches. func (repo *Repository) GetPatch(mergeBase, headBranch string) ([]byte, error) { - stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "diff", "-p", mergeBase, headBranch) + stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "diff", "-p", "--binary", mergeBase, headBranch) if err != nil { return nil, concatenateError(err, string(stderr)) } diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index 8f37d31a..a1f81649 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -69,7 +69,7 @@ func (repo *Repository) getTag(id sha1) (*Tag, error) { // Tag is a commit. if ObjectType(tp) == COMMIT { tag := &Tag{ - Id: id, + ID: id, Object: id, Type: string(COMMIT), repo: repo, @@ -89,7 +89,7 @@ func (repo *Repository) getTag(id sha1) (*Tag, error) { return nil, err } - tag.Id = id + tag.ID = id tag.repo = repo repo.tagCache[id] = tag diff --git a/modules/git/sha1.go b/modules/git/sha1.go index 5c57e89b..f286f35a 100644 --- a/modules/git/sha1.go +++ b/modules/git/sha1.go @@ -12,7 +12,7 @@ import ( ) var ( - IdNotExist = errors.New("sha1 id not exist") + IDNotExist = errors.New("sha1 ID does not exist") ) type sha1 [20]byte diff --git a/modules/git/signature.go b/modules/git/signature.go index b77f7a44..6cd92943 100644 --- a/modules/git/signature.go +++ b/modules/git/signature.go @@ -26,23 +26,23 @@ type Signature struct { // FIXME: include timezone for timestamp! func newSignatureFromCommitline(line []byte) (_ *Signature, err error) { sig := new(Signature) - emailstart := bytes.IndexByte(line, '<') - sig.Name = string(line[:emailstart-1]) - emailstop := bytes.IndexByte(line, '>') - sig.Email = string(line[emailstart+1 : emailstop]) + emailStart := bytes.IndexByte(line, '<') + sig.Name = string(line[:emailStart-1]) + emailEnd := bytes.IndexByte(line, '>') + sig.Email = string(line[emailStart+1 : emailEnd]) // Check date format. - firstChar := line[emailstop+2] + firstChar := line[emailEnd+2] if firstChar >= 48 && firstChar <= 57 { - timestop := bytes.IndexByte(line[emailstop+2:], ' ') - timestring := string(line[emailstop+2 : emailstop+2+timestop]) + timestop := bytes.IndexByte(line[emailEnd+2:], ' ') + timestring := string(line[emailEnd+2 : emailEnd+2+timestop]) seconds, err := strconv.ParseInt(timestring, 10, 64) if err != nil { return nil, err } sig.When = time.Unix(seconds, 0) } else { - sig.When, err = time.Parse("Mon Jan _2 15:04:05 2006 -0700", string(line[emailstop+2:])) + sig.When, err = time.Parse("Mon Jan _2 15:04:05 2006 -0700", string(line[emailEnd+2:])) if err != nil { return nil, err } diff --git a/modules/git/signature_test.go b/modules/git/signature_test.go new file mode 100644 index 00000000..a84f9b3d --- /dev/null +++ b/modules/git/signature_test.go @@ -0,0 +1,20 @@ +// Copyright 2015 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package git + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func Test_newSignatureFromCommitline(t *testing.T) { + Convey("Parse signature from commit line", t, func() { + line := "Intern <intern@macbook-intern.(none)> 1445412825 +0200" + sig, err := newSignatureFromCommitline([]byte(line)) + So(err, ShouldBeNil) + So(sig, ShouldNotBeNil) + }) +} diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 0b8efc26..10680c24 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -6,6 +6,7 @@ package git import ( "strings" + "github.com/gogits/gogs/modules/setting" ) @@ -53,7 +54,7 @@ func (sf *SubModuleFile) RefUrl() string { j := strings.LastIndex(url, ":") if i > -1 && j > -1 { // fix problem with reverse proxy works only with local server - if strings.Contains(setting.AppUrl,url[i+1:j]) { + if strings.Contains(setting.AppUrl, url[i+1:j]) { return setting.AppUrl + url[j+1:] } else { return "http://" + url[i+1:j] + "/" + url[j+1:] diff --git a/modules/git/tag.go b/modules/git/tag.go index 7fbbcb1c..8010aa9d 100644 --- a/modules/git/tag.go +++ b/modules/git/tag.go @@ -11,7 +11,7 @@ import ( // Tag represents a Git tag. type Tag struct { Name string - Id sha1 + ID sha1 repo *Repository Object sha1 // The id of this commit object Type string diff --git a/modules/git/tree.go b/modules/git/tree.go index 27539f06..1a561cf5 100644 --- a/modules/git/tree.go +++ b/modules/git/tree.go @@ -18,7 +18,7 @@ var ( // A tree is a flat directory listing. type Tree struct { - Id sha1 + ID sha1 repo *Repository // parent tree @@ -28,6 +28,27 @@ type Tree struct { entriesParsed bool } +var escapeChar = []byte("\\") + +func UnescapeChars(in []byte) []byte { + if bytes.Index(in, escapeChar) == -1 { + return in + } + + endIdx := len(in) - 1 + isEscape := false + out := make([]byte, 0, endIdx+1) + for i := range in { + if in[i] == '\\' && !isEscape { + isEscape = true + continue + } + isEscape = false + out = append(out, in[i]) + } + return out +} + // Parse tree information from the (uncompressed) raw // data from the tree object. func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) { @@ -66,16 +87,16 @@ func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) { if err != nil { return nil, err } - entry.Id = id + entry.ID = id pos += step + 1 // Skip half of sha1. step = bytes.IndexByte(data[pos:], '\n') - entry.name = string(data[pos : pos+step]) // In case entry name is surrounded by double quotes(it happens only in git-shell). - if entry.name[0] == '"' { - entry.name = string(data[pos+1 : pos+step-1]) - entry.name = strings.Replace(entry.name, `\"`, `"`, -1) + if data[pos] == '"' { + entry.name = string(UnescapeChars(data[pos+1 : pos+step-1])) + } else { + entry.name = string(data[pos : pos+step]) } pos += step + 1 @@ -100,7 +121,7 @@ func (t *Tree) SubTree(rpath string) (*Tree, error) { return nil, err } - g, err = t.repo.getTree(te.Id) + g, err = t.repo.getTree(te.ID) if err != nil { return nil, err } @@ -117,7 +138,7 @@ func (t *Tree) ListEntries(relpath string) (Entries, error) { t.entriesParsed = true stdout, stderr, err := com.ExecCmdDirBytes(t.repo.Path, - "git", "ls-tree", t.Id.String()) + "git", "ls-tree", t.ID.String()) if err != nil { if strings.Contains(err.Error(), "exit status 128") { return nil, errors.New(strings.TrimSpace(string(stderr))) @@ -130,7 +151,7 @@ func (t *Tree) ListEntries(relpath string) (Entries, error) { func NewTree(repo *Repository, id sha1) *Tree { tree := new(Tree) - tree.Id = id + tree.ID = id tree.repo = repo return tree } diff --git a/modules/git/tree_blob.go b/modules/git/tree_blob.go index f996aba3..44c5d0c8 100644 --- a/modules/git/tree_blob.go +++ b/modules/git/tree_blob.go @@ -13,7 +13,7 @@ import ( func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) { if len(relpath) == 0 { return &TreeEntry{ - Id: t.Id, + ID: t.ID, Type: TREE, mode: ModeTree, }, nil diff --git a/modules/git/tree_entry.go b/modules/git/tree_entry.go index e403e93e..18250257 100644 --- a/modules/git/tree_entry.go +++ b/modules/git/tree_entry.go @@ -24,7 +24,7 @@ const ( ) type TreeEntry struct { - Id sha1 + ID sha1 Type ObjectType mode EntryMode @@ -51,7 +51,7 @@ func (te *TreeEntry) Size() int64 { return te.size } - stdout, _, err := com.ExecCmdDir(te.ptree.repo.Path, "git", "cat-file", "-s", te.Id.String()) + stdout, _, err := com.ExecCmdDir(te.ptree.repo.Path, "git", "cat-file", "-s", te.ID.String()) if err != nil { return 0 } diff --git a/modules/git/utils.go b/modules/git/utils.go index 78792aaf..d2d0c19e 100644 --- a/modules/git/utils.go +++ b/modules/git/utils.go @@ -35,6 +35,11 @@ func parsePrettyFormatLog(repo *Repository, logByts []byte) (*list.List, error) } func RefEndName(refStr string) string { + if strings.HasPrefix(refStr, "refs/heads/") { + // trim the "refs/heads/" + return refStr[len("refs/heads/"):] + } + index := strings.LastIndex(refStr, "/") if index != -1 { return refStr[index+1:] |