Beispiel #1
0
func (r *Repository) getParents(revSpec vcs.CommitID) ([]vcs.CommitID, error) {
	var parents []vcs.CommitID

	cmd := exec.Command("hg", "parents", "-r", string(revSpec), "--template",
		`{node}\x00{author|person}\x00{author|email}\x00{date|rfc3339date}\x00{desc}\x00{p1node}\x00{p2node}\x00`)
	cmd.Dir = r.Dir
	out, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("exec `hg parents` failed: %s. Output was:\n\n%s", err, out)
	}

	const partsPerCommit = 7 // number of \x00-separated fields per commit
	allParts := bytes.Split(out, []byte{'\x00'})
	numCommits := len(allParts) / partsPerCommit
	for i := 0; i < numCommits; i++ {
		parts := allParts[partsPerCommit*i : partsPerCommit*(i+1)]

		if p1 := parts[0]; len(p1) > 0 && !bytes.Equal(p1, hgNullParentNodeID) {
			parents = append(parents, vcs.CommitID(p1))
		}
		if p2 := parts[5]; len(p2) > 0 && !bytes.Equal(p2, hgNullParentNodeID) {
			parents = append(parents, vcs.CommitID(p2))
		}
		if p3 := parts[6]; len(p3) > 0 && !bytes.Equal(p3, hgNullParentNodeID) {
			parents = append(parents, vcs.CommitID(p3))
		}
	}

	return parents, nil
}
Beispiel #2
0
func (r *Repository) makeCommit(rec *hg_revlog.Rec) (*vcs.Commit, error) {
	fb := hg_revlog.NewFileBuilder()
	ce, err := hg_changelog.BuildEntry(rec, fb)
	if err != nil {
		return nil, err
	}

	addr, err := mail.ParseAddress(ce.Committer)
	if err != nil {
		// This occurs when the commit author specifier is
		// malformed. Fall back to just using the whole committer
		// string as the name.
		addr = &mail.Address{
			Name:    ce.Committer,
			Address: "",
		}
	}

	var parents []vcs.CommitID
	if !rec.IsStartOfBranch() {
		if p := rec.Parent(); p != nil {
			parents = append(parents, vcs.CommitID(hex.EncodeToString(rec.Parent().Id())))
		}
		if rec.Parent2Present() {
			parents = append(parents, vcs.CommitID(hex.EncodeToString(rec.Parent2().Id())))
		}
	}

	return &vcs.Commit{
		ID:      vcs.CommitID(ce.Id),
		Author:  vcs.Signature{addr.Name, addr.Address, pbtypes.NewTimestamp(ce.Date)},
		Message: ce.Comment,
		Parents: parents,
	}, nil
}
Beispiel #3
0
func (h *Handler) serveRepoMergeBase(w http.ResponseWriter, r *http.Request) error {
	v := mux.Vars(r)

	repo, repoPath, done, err := h.getRepo(r)
	if err != nil {
		return err
	}
	defer done()

	if repo, ok := repo.(vcs.Merger); ok {
		a, b := vcs.CommitID(v["CommitIDA"]), vcs.CommitID(v["CommitIDB"])

		mb, err := repo.MergeBase(a, b)
		if err != nil {
			return err
		}

		var statusCode int
		if commitIDIsCanon(string(a)) && commitIDIsCanon(string(b)) {
			setLongCache(w)
			statusCode = http.StatusMovedPermanently
		} else {
			setShortCache(w)
			statusCode = http.StatusFound
		}
		http.Redirect(w, r, h.router.URLToRepoCommit(repoPath, mb).String(), statusCode)
		return nil
	}

	return &httpError{http.StatusNotImplemented, fmt.Errorf("Merger not yet implemented by %T", repo)}
}
Beispiel #4
0
func TestServeRepoCrossRepoDiff(t *testing.T) {
	setupHandlerTest()
	defer teardownHandlerTest()

	baseRepoPath := "a.b/c"
	headRepoPath := "x.y/z"
	mockHeadRepo := vcs_testing.MockRepository{}
	opt := vcs.DiffOptions{}

	rm := &mockCrossRepoDiff{
		t:        t,
		base:     vcs.CommitID(strings.Repeat("a", 40)),
		headRepo: mockHeadRepo,
		head:     vcs.CommitID(strings.Repeat("b", 40)),
		opt:      opt,
		diff:     &vcs.Diff{Raw: "diff"},
	}
	sm := &mockService{
		t: t,
		open: func(repoPath string) (interface{}, error) {
			switch repoPath {
			case baseRepoPath:
				return rm, nil
			case headRepoPath:
				return mockHeadRepo, nil
			default:
				panic("unexpected repo clone: " + repoPath)
			}
		},
	}
	testHandler.Service = sm

	resp, err := http.Get(server.URL + testHandler.router.URLToRepoCrossRepoDiff(baseRepoPath, rm.base, headRepoPath, rm.head, &opt).String())
	if err != nil && !isIgnoredRedirectErr(err) {
		t.Fatal(err)
	}
	defer resp.Body.Close()

	if !rm.called {
		t.Errorf("!called")
	}

	var diff *vcs.Diff
	if err := json.NewDecoder(resp.Body).Decode(&diff); err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(diff, rm.diff) {
		t.Errorf("got crossRepoDiff %+v, want %+v", diff, rm.diff)
	}
}
Beispiel #5
0
// ResolveRevision returns the revision that the given revision
// specifier resolves to, or a non-nil error if there is no such
// revision.
func (r *Repository) ResolveRevision(spec string) (vcs.CommitID, error) {
	// TODO: git rev-parse supports a horde of complex syntaxes, it will be a fair bit more work to support all of them.
	// e.g. "master@{yesterday}", "master~3", and various text/path/tree traversal search.

	if len(spec) == 40 {
		commit, err := r.repo.GetCommit(spec)
		if err == nil {
			return vcs.CommitID(commit.Id.String()), nil
		}
	}

	ci, err := r.ResolveBranch(spec)
	if err == nil {
		return ci, nil
	}
	ci, err = r.ResolveTag(spec)
	if err == nil {
		return ci, nil
	}
	// Do an extra lookup just in case it's a complex syntax we don't support
	// TODO: Remove fallback usage: ResolveRevision
	ci, err = r.Repository.ResolveRevision(spec)
	if err == nil {
		return ci, nil
	}
	return ci, vcs.ErrRevisionNotFound
}
Beispiel #6
0
func (r *Repository) Tags() ([]*vcs.Tag, error) {
	r.editLock.RLock()
	defer r.editLock.RUnlock()

	refs, err := r.u.NewReferenceIterator()
	if err != nil {
		return nil, err
	}

	var ts []*vcs.Tag
	for {
		ref, err := refs.Next()
		if isErrIterOver(err) {
			break
		}
		if err != nil {
			return nil, err
		}
		if ref.IsTag() {
			ts = append(ts, &vcs.Tag{Name: ref.Shorthand(), CommitID: vcs.CommitID(ref.Target().String())})
		}
	}

	sort.Sort(vcs.Tags(ts))
	return ts, nil
}
Beispiel #7
0
func (r *Repository) Branches(opt vcs.BranchesOptions) ([]*vcs.Branch, error) {
	if opt.ContainsCommit != "" {
		return nil, fmt.Errorf("vcs.BranchesOptions.ContainsCommit option not implemented")
	}

	r.editLock.RLock()
	defer r.editLock.RUnlock()

	refs, err := r.u.NewReferenceIterator()
	if err != nil {
		return nil, err
	}

	var bs []*vcs.Branch
	for {
		ref, err := refs.Next()
		if isErrIterOver(err) {
			break
		}
		if err != nil {
			return nil, err
		}
		if ref.IsBranch() {
			bs = append(bs, &vcs.Branch{Name: ref.Shorthand(), Head: vcs.CommitID(ref.Target().String())})
		}
	}

	sort.Sort(vcs.Branches(bs))
	return bs, nil
}
Beispiel #8
0
func TestRepository_ResolveRevision(t *testing.T) {
	setup()
	defer teardown()

	repoPath := "a.b/c"
	repo_, _ := vcsclient.Repository(repoPath)
	repo := repo_.(*repository)

	want := vcs.CommitID("abcd")

	var called bool
	mux.HandleFunc(urlPath(t, RouteRepoRevision, repo, map[string]string{"RepoPath": repoPath, "RevSpec": "myrevspec"}), func(w http.ResponseWriter, r *http.Request) {
		called = true
		testMethod(t, r, "GET")

		http.Redirect(w, r, urlPath(t, RouteRepoCommit, repo, map[string]string{"CommitID": "abcd"}), http.StatusFound)
	})

	commitID, err := repo.ResolveRevision("myrevspec")
	if err != nil {
		t.Errorf("Repository.ResolveRevision returned error: %v", err)
	}

	if !called {
		t.Fatal("!called")
	}

	if commitID != want {
		t.Errorf("Repository.ResolveRevision returned %+v, want %+v", commitID, want)
	}
}
Beispiel #9
0
func TestRepository_CrossRepoMergeBase(t *testing.T) {
	setup()
	defer teardown()

	repoPath := "a.b/c"
	repo_, _ := vcsclient.Repository(repoPath)
	repo := repo_.(*repository)

	want := vcs.CommitID("abcd")

	var called bool
	mux.HandleFunc(urlPath(t, RouteRepoCrossRepoMergeBase, repo, map[string]string{"RepoPath": repoPath, "CommitIDA": "a", "BRepoPath": "x.com/y", "CommitIDB": "b"}), func(w http.ResponseWriter, r *http.Request) {
		called = true
		testMethod(t, r, "GET")

		http.Redirect(w, r, urlPath(t, RouteRepoCommit, repo, map[string]string{"CommitID": "abcd"}), http.StatusFound)
	})

	bRepoPath := "x.com/y"
	bRepo, _ := vcsclient.Repository(bRepoPath)

	commitID, err := repo.CrossRepoMergeBase("a", bRepo, "b")
	if err != nil {
		t.Errorf("Repository.CrossRepoMergeBase returned error: %v", err)
	}

	if !called {
		t.Fatal("!called")
	}

	if commitID != want {
		t.Errorf("Repository.CrossRepoMergeBase returned %+v, want %+v", commitID, want)
	}
}
Beispiel #10
0
func (fs *filesystem) submoduleInfo(path string, e *git.TreeEntry) (*util.FileInfo, error) {
	// TODO: Cache submodules?
	subs, err := e.Tree().GetSubmodules()
	if err != nil {
		return nil, err
	}
	var found *git.Submodule
	for _, sub := range subs {
		if sub.Path == path {
			found = sub
			break
		}
	}

	if found == nil {
		return nil, fmt.Errorf("submodule not found: %s", path)
	}

	return &util.FileInfo{
		Name_: e.Name(),
		Mode_: vcs.ModeSubmodule,
		Sys_: vcs.SubmoduleInfo{
			URL:      found.URL,
			CommitID: vcs.CommitID(e.Id.String()),
		},
	}, nil
}
Beispiel #11
0
func (fs *gitFSLibGit2) makeFileInfo(path string, e *git2go.TreeEntry) (*util.FileInfo, error) {
	switch e.Type {
	case git2go.ObjectBlob:
		return fs.fileInfo(e)
	case git2go.ObjectTree:
		return fs.dirInfo(e), nil
	case git2go.ObjectCommit:
		submod, err := fs.repo.Submodules.Lookup(path)
		if err != nil {
			return nil, err
		}

		// TODO(sqs): add (*Submodule).Free to git2go and defer submod.Free()
		// below when that method has been added.
		//
		// defer submod.Free()

		return &util.FileInfo{
			Name_: e.Name,
			Mode_: vcs.ModeSubmodule,
			Sys_: vcs.SubmoduleInfo{
				URL:      submod.Url(),
				CommitID: vcs.CommitID(e.Id.String()),
			},
		}, nil
	}

	return nil, fmt.Errorf("unexpected object type %v while making file info (expected blob, tree, or commit)", e.Type)
}
Beispiel #12
0
func (r *Repository) makeCommit(c *git2go.Commit) *vcs.Commit {
	var parents []vcs.CommitID
	if pc := c.ParentCount(); pc > 0 {
		parents = make([]vcs.CommitID, pc)
		for i := 0; i < int(pc); i++ {
			parents[i] = vcs.CommitID(c.ParentId(uint(i)).String())
		}
	}

	au, cm := c.Author(), c.Committer()
	return &vcs.Commit{
		ID:        vcs.CommitID(c.Id().String()),
		Author:    vcs.Signature{au.Name, au.Email, pbtypes.NewTimestamp(au.When)},
		Committer: &vcs.Signature{cm.Name, cm.Email, pbtypes.NewTimestamp(cm.When)},
		Message:   strings.TrimSuffix(c.Message(), "\n"),
		Parents:   parents,
	}
}
Beispiel #13
0
func TestServeRepoTreeEntry_File(t *testing.T) {
	setupHandlerTest()
	defer teardownHandlerTest()

	commitID := vcs.CommitID(strings.Repeat("a", 40))

	repoPath := "a.b/c"
	rm := &mockFileSystem{
		t:  t,
		at: commitID,
		fs: mapFS(map[string]string{"myfile": "mydata"}),
	}
	sm := &mockServiceForExistingRepo{
		t:        t,
		repoPath: repoPath,
		repo:     rm,
	}
	testHandler.Service = sm

	resp, err := http.Get(server.URL + testHandler.router.URLToRepoTreeEntry(repoPath, commitID, "myfile").String())
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	if got, want := resp.StatusCode, http.StatusOK; got != want {
		t.Errorf("got status code %d, want %d", got, want)
	}

	if !sm.opened {
		t.Errorf("!opened")
	}
	if !rm.called {
		t.Errorf("!called")
	}

	var e *vcsclient.TreeEntry
	if err := json.NewDecoder(resp.Body).Decode(&e); err != nil {
		t.Fatal(err)
	}

	wantEntry := &vcsclient.TreeEntry{
		Name:     "myfile",
		Type:     vcsclient.FileEntry,
		Size:     6,
		ModTime:  pbtypes.NewTimestamp(time.Time{}),
		Contents: []byte("mydata"),
	}

	if !reflect.DeepEqual(e, wantEntry) {
		t.Errorf("got tree entry %+v, want %+v", e, wantEntry)
	}

	// used canonical commit ID, so should be long-cached
	if cc := resp.Header.Get("cache-control"); cc != longCacheControl {
		t.Errorf("got cache-control %q, want %q", cc, longCacheControl)
	}
}
Beispiel #14
0
// ResolveBranch returns the branch with the given name, or
// ErrBranchNotFound if no such branch exists.
func (r *Repository) ResolveBranch(name string) (vcs.CommitID, error) {
	id, err := r.repo.GetCommitIdOfBranch(name)
	if _, ok := err.(git.RefNotFound); ok {
		return "", vcs.ErrBranchNotFound
	} else if err != nil {
		// Unexpected error
		return "", err
	}
	return vcs.CommitID(id), nil
}
Beispiel #15
0
func TestServeRepoDiff(t *testing.T) {
	setupHandlerTest()
	defer teardownHandlerTest()

	repoPath := "a.b/c"
	opt := vcs.DiffOptions{}

	rm := &mockDiff{
		t:    t,
		base: vcs.CommitID(strings.Repeat("a", 40)),
		head: vcs.CommitID(strings.Repeat("b", 40)),
		opt:  opt,
		diff: &vcs.Diff{Raw: "diff"},
	}
	sm := &mockServiceForExistingRepo{
		t:        t,
		repoPath: repoPath,
		repo:     rm,
	}
	testHandler.Service = sm

	resp, err := http.Get(server.URL + testHandler.router.URLToRepoDiff(repoPath, rm.base, rm.head, &opt).String())
	if err != nil && !isIgnoredRedirectErr(err) {
		t.Fatal(err)
	}
	defer resp.Body.Close()

	if !sm.opened {
		t.Errorf("!opened")
	}
	if !rm.called {
		t.Errorf("!called")
	}

	var diff *vcs.Diff
	if err := json.NewDecoder(resp.Body).Decode(&diff); err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(diff, rm.diff) {
		t.Errorf("got diff %+v, want %+v", diff, rm.diff)
	}
}
Beispiel #16
0
func (r *Repository) Tags() ([]*vcs.Tag, error) {
	ts := make([]*vcs.Tag, len(r.allTags.IdByName))
	i := 0
	for name, id := range r.allTags.IdByName {
		ts[i] = &vcs.Tag{Name: name, CommitID: vcs.CommitID(id)}
		i++
	}
	sort.Sort(vcs.Tags(ts))
	return ts, nil
}
Beispiel #17
0
// checkCommitID returns whether the commit ID is canonical (i.e., the
// full 40-character commit ID), and an error (if any).
func checkCommitID(commitID string) (vcs.CommitID, bool, error) {
	if commitID == "" {
		return "", false, &httpError{http.StatusBadRequest, errors.New("CommitID is empty")}
	}

	if !isLowercaseHex(commitID) {
		return "", false, &httpError{http.StatusBadRequest, errors.New("CommitID must be lowercase hex")}
	}

	return vcs.CommitID(commitID), commitIDIsCanon(commitID), nil
}
Beispiel #18
0
func (r *Repository) MergeBase(a, b vcs.CommitID) (vcs.CommitID, error) {
	r.editLock.RLock()
	defer r.editLock.RUnlock()

	cmd := exec.Command("git", "merge-base", "--", string(a), string(b))
	cmd.Dir = r.Dir
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("exec %v failed: %s. Output was:\n\n%s", cmd.Args, err, out)
	}
	return vcs.CommitID(bytes.TrimSpace(out)), nil
}
Beispiel #19
0
func (h *Handler) serveRepoDiff(w http.ResponseWriter, r *http.Request) error {
	v := mux.Vars(r)

	repo, _, done, err := h.getRepo(r)
	if err != nil {
		return err
	}
	defer done()

	var opt vcs.DiffOptions
	if err := schemaDecoder.Decode(&opt, r.URL.Query()); err != nil {
		return err
	}

	if repo, ok := repo.(vcs.Differ); ok {
		diff, err := repo.Diff(vcs.CommitID(v["Base"]), vcs.CommitID(v["Head"]), &opt)
		if err != nil {
			return err
		}

		_, baseCanon, err := checkCommitID(v["Base"])
		if err != nil {
			return err
		}
		_, headCanon, err := checkCommitID(v["Head"])
		if err != nil {
			return err
		}
		if baseCanon && headCanon {
			setLongCache(w)
		} else {
			setShortCache(w)
		}

		return writeJSON(w, diff)
	}

	return &httpError{http.StatusNotImplemented, fmt.Errorf("Diff not yet implemented for %T", repo)}
}
Beispiel #20
0
func (r *Repository) ResolveBranch(name string) (vcs.CommitID, error) {
	r.editLock.RLock()
	defer r.editLock.RUnlock()

	b, err := r.u.LookupBranch(name, git2go.BranchLocal)
	if err != nil {
		if err.Error() == fmt.Sprintf("Cannot locate local branch '%s'", name) {
			return "", vcs.ErrBranchNotFound
		}
		return "", err
	}
	return vcs.CommitID(b.Target().String()), nil
}
Beispiel #21
0
func (r *Repository) ResolveRevision(spec string) (vcs.CommitID, error) {
	cmd := exec.Command("hg", "identify", "--debug", "-i", "--rev="+spec)
	cmd.Dir = r.Dir
	out, err := cmd.CombinedOutput()
	if err != nil {
		out = bytes.TrimSpace(out)
		if isUnknownRevisionError(string(out), spec) {
			return "", vcs.ErrRevisionNotFound
		}
		return "", fmt.Errorf("exec `hg identify` failed: %s. Output was:\n\n%s", err, out)
	}
	return vcs.CommitID(bytes.TrimSpace(out)), nil
}
Beispiel #22
0
func (r *repository) parseCommitIDInURL(urlStr string) (vcs.CommitID, error) {
	url, err := url.Parse(urlStr)
	if err != nil {
		return "", err
	}

	var info muxpkg.RouteMatch
	match := (*muxpkg.Router)(router).Match(&http.Request{Method: "GET", URL: url}, &info)
	if !match || info.Vars["CommitID"] == "" {
		return "", errors.New("failed to determine CommitID from URL")
	}

	return vcs.CommitID(info.Vars["CommitID"]), nil
}
Beispiel #23
0
func (r *Repository) ResolveRevision(spec string) (vcs.CommitID, error) {
	r.editLock.RLock()
	defer r.editLock.RUnlock()

	o, err := r.u.RevparseSingle(spec)
	if err != nil {
		if err.Error() == fmt.Sprintf("Revspec '%s' not found.", spec) {
			return "", vcs.ErrRevisionNotFound
		}
		return "", err
	}
	defer o.Free()
	return vcs.CommitID(o.Id().String()), nil
}
Beispiel #24
0
func (r *Repository) Branches(opt vcs.BranchesOptions) ([]*vcs.Branch, error) {
	if opt.ContainsCommit != "" {
		return nil, fmt.Errorf("vcs.BranchesOptions.ContainsCommit option not implemented")
	}

	bs := make([]*vcs.Branch, len(r.branchHeads.IdByName))
	i := 0
	for name, id := range r.branchHeads.IdByName {
		bs[i] = &vcs.Branch{Name: name, Head: vcs.CommitID(id)}
		i++
	}
	sort.Sort(vcs.Branches(bs))
	return bs, nil
}
Beispiel #25
0
func (r *Repository) Branches(opt vcs.BranchesOptions) ([]*vcs.Branch, error) {
	r.editLock.RLock()
	defer r.editLock.RUnlock()

	f := make(branchFilter)
	if opt.MergedInto != "" {
		b, err := r.branches("--merged", opt.MergedInto)
		if err != nil {
			return nil, err
		}
		f.add(b)
	}
	if opt.ContainsCommit != "" {
		b, err := r.branches("--contains=" + opt.ContainsCommit)
		if err != nil {
			return nil, err
		}
		f.add(b)
	}

	refs, err := r.showRef("--heads")
	if err != nil {
		return nil, err
	}

	var branches []*vcs.Branch
	for _, ref := range refs {
		name := strings.TrimPrefix(ref[1], "refs/heads/")
		id := vcs.CommitID(ref[0])
		if !f.allows(name) {
			continue
		}

		branch := &vcs.Branch{Name: name, Head: id}
		if opt.IncludeCommit {
			branch.Commit, err = r.getCommit(id)
			if err != nil {
				return nil, err
			}
		}
		if opt.BehindAheadBranch != "" {
			branch.Counts, err = r.branchesBehindAhead(name, opt.BehindAheadBranch)
			if err != nil {
				return nil, err
			}
		}
		branches = append(branches, branch)
	}
	return branches, nil
}
Beispiel #26
0
func (r *Repository) Tags() ([]*vcs.Tag, error) {
	refs, err := r.execAndParseCols("tags")
	if err != nil {
		return nil, err
	}

	tags := make([]*vcs.Tag, len(refs))
	for i, ref := range refs {
		tags[i] = &vcs.Tag{
			Name:     ref[1],
			CommitID: vcs.CommitID(ref[0]),
		}
	}
	return tags, nil
}
Beispiel #27
0
// mergeBaseHoldingEditLock performs a merge-base. Callers must hold
// the r.editLock (either as a reader or writer).
func (r *Repository) mergeBaseHoldingEditLock(a, b vcs.CommitID) (vcs.CommitID, error) {
	ao, err := git2go.NewOid(string(a))
	if err != nil {
		return "", err
	}
	bo, err := git2go.NewOid(string(b))
	if err != nil {
		return "", err
	}
	mb, err := r.u.MergeBase(ao, bo)
	if err != nil {
		return "", err
	}
	return vcs.CommitID(mb.String()), nil
}
Beispiel #28
0
// Convert a git.Commit to a vcs.Commit
func (r *Repository) vcsCommit(commit *git.Commit) *vcs.Commit {
	var committer *vcs.Signature
	if commit.Committer != nil {
		committer = &vcs.Signature{
			Name:  commit.Committer.Name,
			Email: commit.Committer.Email,
			Date:  pbtypes.NewTimestamp(commit.Committer.When),
		}
	}

	n := commit.ParentCount()
	parentIds := commit.ParentIds()
	parents := make([]vcs.CommitID, 0, len(parentIds))
	for _, id := range parentIds {
		parents = append(parents, vcs.CommitID(id.String()))
	}
	if n == 0 {
		// Required to make reflect.DeepEqual tests pass. :/
		parents = nil
	}

	var author vcs.Signature
	if commit.Author != nil {
		author.Name = commit.Author.Name
		author.Email = commit.Author.Email
		author.Date = pbtypes.NewTimestamp(commit.Author.When)
	}

	return &vcs.Commit{
		ID:        vcs.CommitID(commit.Id.String()),
		Author:    author,
		Committer: committer,
		Message:   strings.TrimSuffix(commit.Message(), "\n"),
		Parents:   parents,
	}
}
Beispiel #29
0
func (r *Repository) ResolveRevision(spec string) (vcs.CommitID, error) {
	if id, err := r.ResolveBranch(spec); err == nil {
		return id, nil
	}
	if id, err := r.ResolveTag(spec); err == nil {
		return id, nil
	}

	rec, err := r.parseRevisionSpec(spec).Lookup(r.cl)
	if err != nil {
		if err == hg_revlog.ErrRevNotFound || err == hex.ErrLength {
			return "", vcs.ErrRevisionNotFound
		}
		return "", err
	}
	return vcs.CommitID(hex.EncodeToString(rec.Id())), nil
}
Beispiel #30
0
// Tags returns a list of all tags in the repository.
func (r *Repository) Tags() ([]*vcs.Tag, error) {
	names, err := r.repo.GetTags()
	if err != nil {
		return nil, err
	}

	tags := make([]*vcs.Tag, 0, len(names))
	for _, name := range names {
		id, err := r.ResolveTag(name)
		if err != nil {
			return nil, err
		}
		tags = append(tags, &vcs.Tag{Name: name, CommitID: vcs.CommitID(id)})
	}

	return tags, nil
}