Skip to content

Commit

Permalink
add support to list commits of branch and merge (#24)
Browse files Browse the repository at this point in the history
* add support to list commits of branch and merge

* added new method to repo pool

* use correct name
  • Loading branch information
asiyani authored Oct 11, 2024
1 parent 8824def commit 92a952a
Show file tree
Hide file tree
Showing 4 changed files with 327 additions and 12 deletions.
27 changes: 27 additions & 0 deletions pkg/mirror/repo_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,30 @@ func (rp *RepoPool) Clone(ctx context.Context, remote, dst, branch, pathspec str
}
return repo.Clone(ctx, dst, branch, pathspec, rmGitDir)
}

// MergeCommits is wrapper around repositories MergeCommits method
func (rp *RepoPool) MergeCommits(ctx context.Context, remote, mergeCommitHash string) ([]CommitInfo, error) {
repo, err := rp.Repository(remote)
if err != nil {
return nil, err
}
return repo.MergeCommits(ctx, mergeCommitHash)
}

// BranchCommits is wrapper around repositories BranchCommits method
func (rp *RepoPool) BranchCommits(ctx context.Context, remote, branch string) ([]CommitInfo, error) {
repo, err := rp.Repository(remote)
if err != nil {
return nil, err
}
return repo.BranchCommits(ctx, branch)
}

// ListCommitsWithChangedFiles is wrapper around repositories ListCommitsWithChangedFiles method
func (rp *RepoPool) ListCommitsWithChangedFiles(ctx context.Context, remote, ref1, ref2 string) ([]CommitInfo, error) {
repo, err := rp.Repository(remote)
if err != nil {
return nil, err
}
return repo.ListCommitsWithChangedFiles(ctx, ref1, ref2)
}
73 changes: 65 additions & 8 deletions pkg/mirror/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,10 @@ func (r *Repository) LogMsg(ctx context.Context, ref, path string) (string, erro

// Subject returns commit subject of given commit hash
func (r *Repository) Subject(ctx context.Context, hash string) (string, error) {
if err := r.ObjectExists(ctx, hash); err != nil {
return "", err
}

r.lock.RLock()
defer r.lock.RUnlock()

args := []string{"show", `--no-patch`, `--format='%s'`, hash}
args := []string{"show", `--no-patch`, `--format=%s`, hash}
msg, err := runGitCommand(ctx, r.log, r.envs, r.dir, args...)
if err != nil {
return "", err
Expand All @@ -205,19 +201,80 @@ func (r *Repository) Subject(ctx context.Context, hash string) (string, error) {

// ChangedFiles returns path of the changed files for given commit hash
func (r *Repository) ChangedFiles(ctx context.Context, hash string) ([]string, error) {
if err := r.ObjectExists(ctx, hash); err != nil {
r.lock.RLock()
defer r.lock.RUnlock()

args := []string{"show", `--name-only`, `--pretty=format:`, hash}
msg, err := runGitCommand(ctx, r.log, r.envs, r.dir, args...)
if err != nil {
return nil, err
}
return strings.Split(msg, "\n"), nil
}

type CommitInfo struct {
Hash string
ChangedFiles []string
}

// MergeCommits lists commits from the mergeCommitHash but not from the first
// parent of mergeCommitHash (mergeCommitHash^) in chronological order. (latest to oldest)
func (r *Repository) MergeCommits(ctx context.Context, mergeCommitHash string) ([]CommitInfo, error) {
return r.ListCommitsWithChangedFiles(ctx, mergeCommitHash+"^", mergeCommitHash)
}

// BranchCommits lists commits from the tip of the branch but not from the HEAD
// of the repository in chronological order. (latest to oldest)
func (r *Repository) BranchCommits(ctx context.Context, branch string) ([]CommitInfo, error) {
return r.ListCommitsWithChangedFiles(ctx, "HEAD", branch)
}

// ListCommitsWithChangedFiles returns path of the changed files for given commit hash
// list all the commits and files which are reachable from 'ref2', but not from 'ref1'
// The output is given in reverse chronological order.
func (r *Repository) ListCommitsWithChangedFiles(ctx context.Context, ref1, ref2 string) ([]CommitInfo, error) {
r.lock.RLock()
defer r.lock.RUnlock()

args := []string{"show", `--name-only`, `--pretty=format:`, hash}
args := []string{"log", `--name-only`, `--pretty=format:%H`, ref1 + ".." + ref2}
msg, err := runGitCommand(ctx, r.log, r.envs, r.dir, args...)
if err != nil {
return nil, err
}
return strings.Split(msg, "\n"), nil
return ParseCommitWithChangedFilesList(msg), nil
}

// ParseCommitWithChangedFilesList will parse following output of 'show/log'
// command with `--name-only`, `--pretty=format:%H` flags
//
// 72ea9c9de6963e97ac472d9ea996e384c6923cca
//
// 80e11d114dd3aa135c18573402a8e688599c69e0
// one/readme.yaml
// one/hello.tf
// two/readme.yaml
func ParseCommitWithChangedFilesList(output string) []CommitInfo {
commitCount := 0
Commits := []CommitInfo{}

for _, line := range strings.Split(output, "\n") {
line = strings.TrimSpace(line)
if line == "" {
continue
}
if IsFullCommitHash(line) {
Commits = append(Commits, CommitInfo{Hash: line})
commitCount += 1
continue
}
// if line is not commit or empty then its assumed to be changed file name
// also this file change belongs to the last commit
if commitCount > 0 {
Commits[commitCount-1].ChangedFiles = append(Commits[commitCount-1].ChangedFiles, line)
}
}

return Commits
}

// ObjectExists returns error is given object is not valid or if it doesn't exists
Expand Down
61 changes: 61 additions & 0 deletions pkg/mirror/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,64 @@ func TestRepo_AddWorktreeLink(t *testing.T) {
t.Errorf("Repo.AddWorktreeLink() worktreelinks mismatch (-want +got):\n%s", diff)
}
}

func TestParseCommitWithChangedFilesList(t *testing.T) {
tests := []struct {
name string
output string
want []CommitInfo
}{
{
"empty",
`
`,
[]CommitInfo{},
},
{
"only_commit",
`267fc66a734de9e4de57d9d20c83566a69cd703c
`,
[]CommitInfo{{Hash: "267fc66a734de9e4de57d9d20c83566a69cd703c"}},
},
{
"no_changed_files",
`
267fc66a734de9e4de57d9d20c83566a69cd703c
`,
[]CommitInfo{{Hash: "267fc66a734de9e4de57d9d20c83566a69cd703c"}},
},
{
"multiple_commits",
`267fc66a734de9e4de57d9d20c83566a69cd703c
1f68b80bc259e067fdb3dc4bb82cdbd43645e392
one/hello.tf
72ea9c9de6963e97ac472d9ea996e384c6923cca
readme
80e11d114dd3aa135c18573402a8e688599c69e0
one/readme
one/hello.tf
two/readme
`,
[]CommitInfo{
{Hash: "267fc66a734de9e4de57d9d20c83566a69cd703c"},
{Hash: "1f68b80bc259e067fdb3dc4bb82cdbd43645e392", ChangedFiles: []string{"one/hello.tf"}},
{Hash: "72ea9c9de6963e97ac472d9ea996e384c6923cca", ChangedFiles: []string{"readme"}},
{Hash: "80e11d114dd3aa135c18573402a8e688599c69e0", ChangedFiles: []string{"one/readme", "one/hello.tf", "two/readme"}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ParseCommitWithChangedFilesList(tt.output)
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("ParseCommitWithChangedFilesList() output mismatch (-want +got):\n%s", diff)
}
})
}
}
Loading

0 comments on commit 92a952a

Please sign in to comment.