613 lines
20 KiB
Go
613 lines
20 KiB
Go
/*
|
|
Copyright 2015 Google Inc. All rights reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package repository
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// Constants used for testing.
|
|
// We initialize our mock repo with two branches (one of which holds a pending review),
|
|
// and commit history that looks like this:
|
|
//
|
|
// Master Branch: A--B--D--E--F--J
|
|
// \ / \ \
|
|
// C \ \
|
|
// \ \
|
|
// Review Branch: G--H--I
|
|
//
|
|
// Where commits "B" and "D" represent reviews that have been submitted, and "G"
|
|
// is a pending review.
|
|
const (
|
|
TestTargetRef = "refs/heads/master"
|
|
TestReviewRef = "refs/heads/ojarjur/mychange"
|
|
TestAlternateReviewRef = "refs/review/mychange"
|
|
TestRequestsRef = "refs/notes/devtools/reviews"
|
|
TestCommentsRef = "refs/notes/devtools/discuss"
|
|
|
|
TestCommitA = "A"
|
|
TestCommitB = "B"
|
|
TestCommitC = "C"
|
|
TestCommitD = "D"
|
|
TestCommitE = "E"
|
|
TestCommitF = "F"
|
|
TestCommitG = "G"
|
|
TestCommitH = "H"
|
|
TestCommitI = "I"
|
|
TestCommitJ = "J"
|
|
|
|
TestRequestB = `{"timestamp": "0000000001", "reviewRef": "refs/heads/ojarjur/mychange", "targetRef": "refs/heads/master", "requester": "ojarjur", "reviewers": ["ojarjur"], "description": "B"}`
|
|
TestRequestD = `{"timestamp": "0000000002", "reviewRef": "refs/heads/ojarjur/mychange", "targetRef": "refs/heads/master", "requester": "ojarjur", "reviewers": ["ojarjur"], "description": "D"}`
|
|
TestRequestG = `{"timestamp": "0000000004", "reviewRef": "refs/heads/ojarjur/mychange", "targetRef": "refs/heads/master", "requester": "ojarjur", "reviewers": ["ojarjur"], "description": "G"}
|
|
|
|
{"timestamp": "0000000005", "reviewRef": "refs/heads/ojarjur/mychange", "targetRef": "refs/heads/master", "requester": "ojarjur", "reviewers": ["ojarjur"], "description": "Updated description of G"}
|
|
|
|
{"timestamp": "0000000005", "reviewRef": "refs/heads/ojarjur/mychange", "targetRef": "refs/heads/master", "requester": "ojarjur", "reviewers": ["ojarjur"], "description": "Final description of G"}`
|
|
|
|
TestDiscussB = `{"timestamp": "0000000001", "author": "ojarjur", "location": {"commit": "B"}, "resolved": true}`
|
|
TestDiscussD = `{"timestamp": "0000000003", "author": "ojarjur", "location": {"commit": "E"}, "resolved": true}`
|
|
)
|
|
|
|
type mockCommit struct {
|
|
Message string `json:"message,omitempty"`
|
|
Time string `json:"time,omitempty"`
|
|
Parents []string `json:"parents,omitempty"`
|
|
}
|
|
|
|
// mockRepoForTest defines an instance of Repo that can be used for testing.
|
|
type mockRepoForTest struct {
|
|
Head string
|
|
Refs map[string]string `json:"refs,omitempty"`
|
|
Commits map[string]mockCommit `json:"commits,omitempty"`
|
|
Notes map[string]map[string]string `json:"notes,omitempty"`
|
|
}
|
|
|
|
func (r *mockRepoForTest) createCommit(message string, time string, parents []string) (string, error) {
|
|
newCommit := mockCommit{
|
|
Message: message,
|
|
Time: time,
|
|
Parents: parents,
|
|
}
|
|
newCommitJSON, err := json.Marshal(newCommit)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
newCommitHash := fmt.Sprintf("%x", sha1.Sum([]byte(newCommitJSON)))
|
|
r.Commits[newCommitHash] = newCommit
|
|
return newCommitHash, nil
|
|
}
|
|
|
|
// NewMockRepoForTest returns a mocked-out instance of the Repo interface that has been pre-populated with test data.
|
|
func NewMockRepoForTest() Repo {
|
|
commitA := mockCommit{
|
|
Message: "First commit",
|
|
Time: "0",
|
|
Parents: nil,
|
|
}
|
|
commitB := mockCommit{
|
|
Message: "Second commit",
|
|
Time: "1",
|
|
Parents: []string{TestCommitA},
|
|
}
|
|
commitC := mockCommit{
|
|
Message: "No, I'm the second commit",
|
|
Time: "1",
|
|
Parents: []string{TestCommitA},
|
|
}
|
|
commitD := mockCommit{
|
|
Message: "Fourth commit",
|
|
Time: "2",
|
|
Parents: []string{TestCommitB, TestCommitC},
|
|
}
|
|
commitE := mockCommit{
|
|
Message: "Fifth commit",
|
|
Time: "3",
|
|
Parents: []string{TestCommitD},
|
|
}
|
|
commitF := mockCommit{
|
|
Message: "Sixth commit",
|
|
Time: "4",
|
|
Parents: []string{TestCommitE},
|
|
}
|
|
commitG := mockCommit{
|
|
Message: "No, I'm the sixth commit",
|
|
Time: "4",
|
|
Parents: []string{TestCommitE},
|
|
}
|
|
commitH := mockCommit{
|
|
Message: "Seventh commit",
|
|
Time: "5",
|
|
Parents: []string{TestCommitG, TestCommitF},
|
|
}
|
|
commitI := mockCommit{
|
|
Message: "Eighth commit",
|
|
Time: "6",
|
|
Parents: []string{TestCommitH},
|
|
}
|
|
commitJ := mockCommit{
|
|
Message: "No, I'm the eighth commit",
|
|
Time: "6",
|
|
Parents: []string{TestCommitF},
|
|
}
|
|
return &mockRepoForTest{
|
|
Head: TestTargetRef,
|
|
Refs: map[string]string{
|
|
TestTargetRef: TestCommitJ,
|
|
TestReviewRef: TestCommitI,
|
|
TestAlternateReviewRef: TestCommitI,
|
|
},
|
|
Commits: map[string]mockCommit{
|
|
TestCommitA: commitA,
|
|
TestCommitB: commitB,
|
|
TestCommitC: commitC,
|
|
TestCommitD: commitD,
|
|
TestCommitE: commitE,
|
|
TestCommitF: commitF,
|
|
TestCommitG: commitG,
|
|
TestCommitH: commitH,
|
|
TestCommitI: commitI,
|
|
TestCommitJ: commitJ,
|
|
},
|
|
Notes: map[string]map[string]string{
|
|
TestRequestsRef: map[string]string{
|
|
TestCommitB: TestRequestB,
|
|
TestCommitD: TestRequestD,
|
|
TestCommitG: TestRequestG,
|
|
},
|
|
TestCommentsRef: map[string]string{
|
|
TestCommitB: TestDiscussB,
|
|
TestCommitD: TestDiscussD,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetPath returns the path to the repo.
|
|
func (r *mockRepoForTest) GetPath() string { return "~/mockRepo/" }
|
|
|
|
// GetRepoStateHash returns a hash which embodies the entire current state of a repository.
|
|
func (r *mockRepoForTest) GetRepoStateHash() (string, error) {
|
|
repoJSON, err := json.Marshal(r)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return fmt.Sprintf("%x", sha1.Sum([]byte(repoJSON))), nil
|
|
}
|
|
|
|
// GetUserEmail returns the email address that the user has used to configure git.
|
|
func (r *mockRepoForTest) GetUserEmail() (string, error) { return "user@example.com", nil }
|
|
|
|
// GetUserSigningKey returns the key id the user has configured for
|
|
// sigining git artifacts.
|
|
func (r *mockRepoForTest) GetUserSigningKey() (string, error) {
|
|
return "gpgsig", nil
|
|
}
|
|
|
|
// GetCoreEditor returns the name of the editor that the user has used to configure git.
|
|
func (r *mockRepoForTest) GetCoreEditor() (string, error) { return "vi", nil }
|
|
|
|
// GetSubmitStrategy returns the way in which a review is submitted
|
|
func (r *mockRepoForTest) GetSubmitStrategy() (string, error) { return "merge", nil }
|
|
|
|
// HasUncommittedChanges returns true if there are local, uncommitted changes.
|
|
func (r *mockRepoForTest) HasUncommittedChanges() (bool, error) { return false, nil }
|
|
|
|
func (r *mockRepoForTest) resolveLocalRef(ref string) (string, error) {
|
|
if ref == "HEAD" {
|
|
ref = r.Head
|
|
}
|
|
if commit, ok := r.Refs[ref]; ok {
|
|
return commit, nil
|
|
}
|
|
if _, ok := r.Commits[ref]; ok {
|
|
return ref, nil
|
|
}
|
|
return "", fmt.Errorf("The ref %q does not exist", ref)
|
|
}
|
|
|
|
// VerifyCommit verifies that the supplied hash points to a known commit.
|
|
func (r *mockRepoForTest) VerifyCommit(hash string) error {
|
|
if _, ok := r.Commits[hash]; !ok {
|
|
return fmt.Errorf("The given hash %q is not a known commit", hash)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// VerifyGitRef verifies that the supplied ref points to a known commit.
|
|
func (r *mockRepoForTest) VerifyGitRef(ref string) error {
|
|
_, err := r.resolveLocalRef(ref)
|
|
return err
|
|
}
|
|
|
|
// GetHeadRef returns the ref that is the current HEAD.
|
|
func (r *mockRepoForTest) GetHeadRef() (string, error) { return r.Head, nil }
|
|
|
|
// GetCommitHash returns the hash of the commit pointed to by the given ref.
|
|
func (r *mockRepoForTest) GetCommitHash(ref string) (string, error) {
|
|
err := r.VerifyGitRef(ref)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return r.resolveLocalRef(ref)
|
|
}
|
|
|
|
// ResolveRefCommit returns the commit pointed to by the given ref, which may be a remote ref.
|
|
//
|
|
// This differs from GetCommitHash which only works on exact matches, in that it will try to
|
|
// intelligently handle the scenario of a ref not existing locally, but being known to exist
|
|
// in a remote repo.
|
|
//
|
|
// This method should be used when a command may be performed by either the reviewer or the
|
|
// reviewee, while GetCommitHash should be used when the encompassing command should only be
|
|
// performed by the reviewee.
|
|
func (r *mockRepoForTest) ResolveRefCommit(ref string) (string, error) {
|
|
if commit, err := r.resolveLocalRef(ref); err == nil {
|
|
return commit, err
|
|
}
|
|
return r.resolveLocalRef(strings.Replace(ref, "refs/heads/", "refs/remotes/origin/", 1))
|
|
}
|
|
|
|
func (r *mockRepoForTest) getCommit(ref string) (mockCommit, error) {
|
|
commit, err := r.resolveLocalRef(ref)
|
|
return r.Commits[commit], err
|
|
}
|
|
|
|
// GetCommitMessage returns the message stored in the commit pointed to by the given ref.
|
|
func (r *mockRepoForTest) GetCommitMessage(ref string) (string, error) {
|
|
commit, err := r.getCommit(ref)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return commit.Message, nil
|
|
}
|
|
|
|
// GetCommitTime returns the commit time of the commit pointed to by the given ref.
|
|
func (r *mockRepoForTest) GetCommitTime(ref string) (string, error) {
|
|
commit, err := r.getCommit(ref)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return commit.Time, nil
|
|
}
|
|
|
|
// GetLastParent returns the last parent of the given commit (as ordered by git).
|
|
func (r *mockRepoForTest) GetLastParent(ref string) (string, error) {
|
|
commit, err := r.getCommit(ref)
|
|
if len(commit.Parents) > 0 {
|
|
return commit.Parents[len(commit.Parents)-1], err
|
|
}
|
|
return "", err
|
|
}
|
|
|
|
// GetCommitDetails returns the details of a commit's metadata.
|
|
func (r *mockRepoForTest) GetCommitDetails(ref string) (*CommitDetails, error) {
|
|
commit, err := r.getCommit(ref)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var details CommitDetails
|
|
details.Author = "Test Author"
|
|
details.AuthorEmail = "author@example.com"
|
|
details.Summary = commit.Message
|
|
details.Time = commit.Time
|
|
details.Parents = commit.Parents
|
|
return &details, nil
|
|
}
|
|
|
|
// ancestors returns the breadth-first traversal of a commit's ancestors
|
|
func (r *mockRepoForTest) ancestors(commit string) ([]string, error) {
|
|
queue := []string{commit}
|
|
var ancestors []string
|
|
for queue != nil {
|
|
var nextQueue []string
|
|
for _, c := range queue {
|
|
commit, err := r.getCommit(c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
parents := commit.Parents
|
|
nextQueue = append(nextQueue, parents...)
|
|
ancestors = append(ancestors, parents...)
|
|
}
|
|
queue = nextQueue
|
|
}
|
|
return ancestors, nil
|
|
}
|
|
|
|
// IsAncestor determines if the first argument points to a commit that is an ancestor of the second.
|
|
func (r *mockRepoForTest) IsAncestor(ancestor, descendant string) (bool, error) {
|
|
var err error
|
|
ancestor, err = r.resolveLocalRef(ancestor)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
descendant, err = r.resolveLocalRef(descendant)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if ancestor == descendant {
|
|
return true, nil
|
|
}
|
|
descendantCommit, err := r.getCommit(descendant)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
for _, parent := range descendantCommit.Parents {
|
|
if t, e := r.IsAncestor(ancestor, parent); e == nil && t {
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
// MergeBase determines if the first commit that is an ancestor of the two arguments.
|
|
func (r *mockRepoForTest) MergeBase(a, b string) (string, error) {
|
|
ancestors, err := r.ancestors(a)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
for _, ancestor := range ancestors {
|
|
if t, e := r.IsAncestor(ancestor, b); e == nil && t {
|
|
return ancestor, nil
|
|
}
|
|
}
|
|
return "", nil
|
|
}
|
|
|
|
// Diff computes the diff between two given commits.
|
|
func (r *mockRepoForTest) Diff(left, right string, diffArgs ...string) (string, error) {
|
|
return fmt.Sprintf("Diff between %q and %q", left, right), nil
|
|
}
|
|
|
|
// Show returns the contents of the given file at the given commit.
|
|
func (r *mockRepoForTest) Show(commit, path string) (string, error) {
|
|
return fmt.Sprintf("%s:%s", commit, path), nil
|
|
}
|
|
|
|
// SwitchToRef changes the currently-checked-out ref.
|
|
func (r *mockRepoForTest) SwitchToRef(ref string) error {
|
|
r.Head = ref
|
|
return nil
|
|
}
|
|
|
|
// ArchiveRef adds the current commit pointed to by the 'ref' argument
|
|
// under the ref specified in the 'archive' argument.
|
|
//
|
|
// Both the 'ref' and 'archive' arguments are expected to be the fully
|
|
// qualified names of git refs (e.g. 'refs/heads/my-change' or
|
|
// 'refs/archive/devtools').
|
|
//
|
|
// If the ref pointed to by the 'archive' argument does not exist
|
|
// yet, then it will be created.
|
|
func (r *mockRepoForTest) ArchiveRef(ref, archive string) error {
|
|
commitToArchive, err := r.resolveLocalRef(ref)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var archiveParents []string
|
|
if archiveCommit, err := r.resolveLocalRef(archive); err == nil {
|
|
archiveParents = []string{archiveCommit, commitToArchive}
|
|
} else {
|
|
archiveParents = []string{commitToArchive}
|
|
}
|
|
archiveCommit, err := r.createCommit("Archiving", "Nowish", archiveParents)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.Refs[archive] = archiveCommit
|
|
return nil
|
|
}
|
|
|
|
// MergeRef merges the given ref into the current one.
|
|
//
|
|
// The ref argument is the ref to merge, and fastForward indicates that the
|
|
// current ref should only move forward, as opposed to creating a bubble merge.
|
|
func (r *mockRepoForTest) MergeRef(ref string, fastForward bool, messages ...string) error {
|
|
newCommitHash, err := r.resolveLocalRef(ref)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !fastForward {
|
|
origCommit, err := r.resolveLocalRef(r.Head)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
newCommit, err := r.getCommit(ref)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
message := strings.Join(messages, "\n\n")
|
|
time := newCommit.Time
|
|
parents := []string{origCommit, newCommitHash}
|
|
newCommitHash, err = r.createCommit(message, time, parents)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
r.Refs[r.Head] = newCommitHash
|
|
return nil
|
|
}
|
|
|
|
// MergeAndSignRef merges the given ref into the current one and signs the
|
|
// merge.
|
|
//
|
|
// The ref argument is the ref to merge, and fastForward indicates that the
|
|
// current ref should only move forward, as opposed to creating a bubble merge.
|
|
func (r *mockRepoForTest) MergeAndSignRef(ref string, fastForward bool,
|
|
messages ...string) error {
|
|
return nil
|
|
}
|
|
|
|
// RebaseRef rebases the current ref onto the given one.
|
|
func (r *mockRepoForTest) RebaseRef(ref string) error {
|
|
parentHash := r.Refs[ref]
|
|
origCommit, err := r.getCommit(r.Head)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
newCommitHash, err := r.createCommit(origCommit.Message, origCommit.Time, []string{parentHash})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if strings.HasPrefix(r.Head, "refs/heads/") {
|
|
r.Refs[r.Head] = newCommitHash
|
|
} else {
|
|
// The current head is not a branch, so updating
|
|
// it should leave us in a detached-head state.
|
|
r.Head = newCommitHash
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RebaseAndSignRef rebases the current ref onto the given one and signs the
|
|
// result.
|
|
func (r *mockRepoForTest) RebaseAndSignRef(ref string) error { return nil }
|
|
|
|
// ListCommits returns the list of commits reachable from the given ref.
|
|
//
|
|
// The generated list is in chronological order (with the oldest commit first).
|
|
//
|
|
// If the specified ref does not exist, then this method returns an empty result.
|
|
func (r *mockRepoForTest) ListCommits(ref string) []string { return nil }
|
|
|
|
// ListCommitsBetween returns the list of commits between the two given revisions.
|
|
//
|
|
// The "from" parameter is the starting point (exclusive), and the "to"
|
|
// parameter is the ending point (inclusive).
|
|
//
|
|
// The "from" commit does not need to be an ancestor of the "to" commit. If it
|
|
// is not, then the merge base of the two is used as the starting point.
|
|
// Admittedly, this makes calling these the "between" commits is a bit of a
|
|
// misnomer, but it also makes the method easier to use when you want to
|
|
// generate the list of changes in a feature branch, as it eliminates the need
|
|
// to explicitly calculate the merge base. This also makes the semantics of the
|
|
// method compatible with git's built-in "rev-list" command.
|
|
//
|
|
// The generated list is in chronological order (with the oldest commit first).
|
|
func (r *mockRepoForTest) ListCommitsBetween(from, to string) ([]string, error) {
|
|
commits := []string{to}
|
|
potentialCommits, _ := r.ancestors(to)
|
|
for _, commit := range potentialCommits {
|
|
blocked, err := r.IsAncestor(commit, from)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !blocked {
|
|
commits = append(commits, commit)
|
|
}
|
|
}
|
|
return commits, nil
|
|
}
|
|
|
|
// GetNotes reads the notes from the given ref that annotate the given revision.
|
|
func (r *mockRepoForTest) GetNotes(notesRef, revision string) []Note {
|
|
notesText := r.Notes[notesRef][revision]
|
|
var notes []Note
|
|
for _, line := range strings.Split(notesText, "\n") {
|
|
notes = append(notes, Note(line))
|
|
}
|
|
return notes
|
|
}
|
|
|
|
// GetAllNotes reads the contents of the notes under the given ref for every commit.
|
|
//
|
|
// The returned value is a mapping from commit hash to the list of notes for that commit.
|
|
//
|
|
// This is the batch version of the corresponding GetNotes(...) method.
|
|
func (r *mockRepoForTest) GetAllNotes(notesRef string) (map[string][]Note, error) {
|
|
notesMap := make(map[string][]Note)
|
|
for _, commit := range r.ListNotedRevisions(notesRef) {
|
|
notesMap[commit] = r.GetNotes(notesRef, commit)
|
|
}
|
|
return notesMap, nil
|
|
}
|
|
|
|
// AppendNote appends a note to a revision under the given ref.
|
|
func (r *mockRepoForTest) AppendNote(ref, revision string, note Note) error {
|
|
existingNotes := r.Notes[ref][revision]
|
|
newNotes := existingNotes + "\n" + string(note)
|
|
r.Notes[ref][revision] = newNotes
|
|
return nil
|
|
}
|
|
|
|
// ListNotedRevisions returns the collection of revisions that are annotated by notes in the given ref.
|
|
func (r *mockRepoForTest) ListNotedRevisions(notesRef string) []string {
|
|
var revisions []string
|
|
for revision := range r.Notes[notesRef] {
|
|
if _, ok := r.Commits[revision]; ok {
|
|
revisions = append(revisions, revision)
|
|
}
|
|
}
|
|
return revisions
|
|
}
|
|
|
|
// PushNotes pushes git notes to a remote repo.
|
|
func (r *mockRepoForTest) PushNotes(remote, notesRefPattern string) error { return nil }
|
|
|
|
// PullNotes fetches the contents of the given notes ref from a remote repo,
|
|
// and then merges them with the corresponding local notes using the
|
|
// "cat_sort_uniq" strategy.
|
|
func (r *mockRepoForTest) PullNotes(remote, notesRefPattern string) error { return nil }
|
|
|
|
// PushNotesAndArchive pushes the given notes and archive refs to a remote repo.
|
|
func (r *mockRepoForTest) PushNotesAndArchive(remote, notesRefPattern, archiveRefPattern string) error {
|
|
return nil
|
|
}
|
|
|
|
// PullNotesAndArchive fetches the contents of the notes and archives refs from
|
|
// a remote repo, and merges them with the corresponding local refs.
|
|
//
|
|
// For notes refs, we assume that every note can be automatically merged using
|
|
// the 'cat_sort_uniq' strategy (the git-appraise schemas fit that requirement),
|
|
// so we automatically merge the remote notes into the local notes.
|
|
//
|
|
// For "archive" refs, they are expected to be used solely for maintaining
|
|
// reachability of commits that are part of the history of any reviews,
|
|
// so we do not maintain any consistency with their tree objects. Instead,
|
|
// we merely ensure that their history graph includes every commit that we
|
|
// intend to keep.
|
|
func (r *mockRepoForTest) PullNotesAndArchive(remote, notesRefPattern, archiveRefPattern string) error {
|
|
return nil
|
|
}
|
|
|
|
// MergeNotes merges in the remote's state of the archives reference into
|
|
// the local repository's.
|
|
func (repo *mockRepoForTest) MergeNotes(remote, notesRefPattern string) error {
|
|
return nil
|
|
}
|
|
|
|
// MergeArchives merges in the remote's state of the archives reference into
|
|
// the local repository's.
|
|
func (repo *mockRepoForTest) MergeArchives(remote,
|
|
archiveRefPattern string) error {
|
|
return nil
|
|
}
|
|
|
|
// FetchAndReturnNewReviewHashes fetches the notes "branches" and then susses
|
|
// out the IDs (the revision the review points to) of any new reviews, then
|
|
// returns that list of IDs.
|
|
//
|
|
// This is accomplished by determining which files in the notes tree have
|
|
// changed because the _names_ of these files correspond to the revisions they
|
|
// point to.
|
|
func (repo *mockRepoForTest) FetchAndReturnNewReviewHashes(remote, notesRefPattern,
|
|
archiveRefPattern string) ([]string, error) {
|
|
return nil, nil
|
|
}
|