Skip to content

Commit 92a952a

Browse files
authored
add support to list commits of branch and merge (#24)
* add support to list commits of branch and merge * added new method to repo pool * use correct name
1 parent 8824def commit 92a952a

File tree

4 files changed

+327
-12
lines changed

4 files changed

+327
-12
lines changed

pkg/mirror/repo_pool.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,30 @@ func (rp *RepoPool) Clone(ctx context.Context, remote, dst, branch, pathspec str
202202
}
203203
return repo.Clone(ctx, dst, branch, pathspec, rmGitDir)
204204
}
205+
206+
// MergeCommits is wrapper around repositories MergeCommits method
207+
func (rp *RepoPool) MergeCommits(ctx context.Context, remote, mergeCommitHash string) ([]CommitInfo, error) {
208+
repo, err := rp.Repository(remote)
209+
if err != nil {
210+
return nil, err
211+
}
212+
return repo.MergeCommits(ctx, mergeCommitHash)
213+
}
214+
215+
// BranchCommits is wrapper around repositories BranchCommits method
216+
func (rp *RepoPool) BranchCommits(ctx context.Context, remote, branch string) ([]CommitInfo, error) {
217+
repo, err := rp.Repository(remote)
218+
if err != nil {
219+
return nil, err
220+
}
221+
return repo.BranchCommits(ctx, branch)
222+
}
223+
224+
// ListCommitsWithChangedFiles is wrapper around repositories ListCommitsWithChangedFiles method
225+
func (rp *RepoPool) ListCommitsWithChangedFiles(ctx context.Context, remote, ref1, ref2 string) ([]CommitInfo, error) {
226+
repo, err := rp.Repository(remote)
227+
if err != nil {
228+
return nil, err
229+
}
230+
return repo.ListCommitsWithChangedFiles(ctx, ref1, ref2)
231+
}

pkg/mirror/repository.go

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,10 @@ func (r *Repository) LogMsg(ctx context.Context, ref, path string) (string, erro
188188

189189
// Subject returns commit subject of given commit hash
190190
func (r *Repository) Subject(ctx context.Context, hash string) (string, error) {
191-
if err := r.ObjectExists(ctx, hash); err != nil {
192-
return "", err
193-
}
194-
195191
r.lock.RLock()
196192
defer r.lock.RUnlock()
197193

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

206202
// ChangedFiles returns path of the changed files for given commit hash
207203
func (r *Repository) ChangedFiles(ctx context.Context, hash string) ([]string, error) {
208-
if err := r.ObjectExists(ctx, hash); err != nil {
204+
r.lock.RLock()
205+
defer r.lock.RUnlock()
206+
207+
args := []string{"show", `--name-only`, `--pretty=format:`, hash}
208+
msg, err := runGitCommand(ctx, r.log, r.envs, r.dir, args...)
209+
if err != nil {
209210
return nil, err
210211
}
212+
return strings.Split(msg, "\n"), nil
213+
}
214+
215+
type CommitInfo struct {
216+
Hash string
217+
ChangedFiles []string
218+
}
219+
220+
// MergeCommits lists commits from the mergeCommitHash but not from the first
221+
// parent of mergeCommitHash (mergeCommitHash^) in chronological order. (latest to oldest)
222+
func (r *Repository) MergeCommits(ctx context.Context, mergeCommitHash string) ([]CommitInfo, error) {
223+
return r.ListCommitsWithChangedFiles(ctx, mergeCommitHash+"^", mergeCommitHash)
224+
}
225+
226+
// BranchCommits lists commits from the tip of the branch but not from the HEAD
227+
// of the repository in chronological order. (latest to oldest)
228+
func (r *Repository) BranchCommits(ctx context.Context, branch string) ([]CommitInfo, error) {
229+
return r.ListCommitsWithChangedFiles(ctx, "HEAD", branch)
230+
}
211231

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

215-
args := []string{"show", `--name-only`, `--pretty=format:`, hash}
239+
args := []string{"log", `--name-only`, `--pretty=format:%H`, ref1 + ".." + ref2}
216240
msg, err := runGitCommand(ctx, r.log, r.envs, r.dir, args...)
217241
if err != nil {
218242
return nil, err
219243
}
220-
return strings.Split(msg, "\n"), nil
244+
return ParseCommitWithChangedFilesList(msg), nil
245+
}
246+
247+
// ParseCommitWithChangedFilesList will parse following output of 'show/log'
248+
// command with `--name-only`, `--pretty=format:%H` flags
249+
//
250+
// 72ea9c9de6963e97ac472d9ea996e384c6923cca
251+
//
252+
// 80e11d114dd3aa135c18573402a8e688599c69e0
253+
// one/readme.yaml
254+
// one/hello.tf
255+
// two/readme.yaml
256+
func ParseCommitWithChangedFilesList(output string) []CommitInfo {
257+
commitCount := 0
258+
Commits := []CommitInfo{}
259+
260+
for _, line := range strings.Split(output, "\n") {
261+
line = strings.TrimSpace(line)
262+
if line == "" {
263+
continue
264+
}
265+
if IsFullCommitHash(line) {
266+
Commits = append(Commits, CommitInfo{Hash: line})
267+
commitCount += 1
268+
continue
269+
}
270+
// if line is not commit or empty then its assumed to be changed file name
271+
// also this file change belongs to the last commit
272+
if commitCount > 0 {
273+
Commits[commitCount-1].ChangedFiles = append(Commits[commitCount-1].ChangedFiles, line)
274+
}
275+
}
276+
277+
return Commits
221278
}
222279

223280
// ObjectExists returns error is given object is not valid or if it doesn't exists

pkg/mirror/repository_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,64 @@ func TestRepo_AddWorktreeLink(t *testing.T) {
166166
t.Errorf("Repo.AddWorktreeLink() worktreelinks mismatch (-want +got):\n%s", diff)
167167
}
168168
}
169+
170+
func TestParseCommitWithChangedFilesList(t *testing.T) {
171+
tests := []struct {
172+
name string
173+
output string
174+
want []CommitInfo
175+
}{
176+
{
177+
"empty",
178+
`
179+
180+
`,
181+
[]CommitInfo{},
182+
},
183+
{
184+
"only_commit",
185+
`267fc66a734de9e4de57d9d20c83566a69cd703c
186+
`,
187+
[]CommitInfo{{Hash: "267fc66a734de9e4de57d9d20c83566a69cd703c"}},
188+
},
189+
{
190+
"no_changed_files",
191+
`
192+
267fc66a734de9e4de57d9d20c83566a69cd703c
193+
194+
195+
`,
196+
[]CommitInfo{{Hash: "267fc66a734de9e4de57d9d20c83566a69cd703c"}},
197+
},
198+
{
199+
"multiple_commits",
200+
`267fc66a734de9e4de57d9d20c83566a69cd703c
201+
1f68b80bc259e067fdb3dc4bb82cdbd43645e392
202+
one/hello.tf
203+
204+
72ea9c9de6963e97ac472d9ea996e384c6923cca
205+
readme
206+
207+
80e11d114dd3aa135c18573402a8e688599c69e0
208+
one/readme
209+
one/hello.tf
210+
two/readme
211+
212+
`,
213+
[]CommitInfo{
214+
{Hash: "267fc66a734de9e4de57d9d20c83566a69cd703c"},
215+
{Hash: "1f68b80bc259e067fdb3dc4bb82cdbd43645e392", ChangedFiles: []string{"one/hello.tf"}},
216+
{Hash: "72ea9c9de6963e97ac472d9ea996e384c6923cca", ChangedFiles: []string{"readme"}},
217+
{Hash: "80e11d114dd3aa135c18573402a8e688599c69e0", ChangedFiles: []string{"one/readme", "one/hello.tf", "two/readme"}},
218+
},
219+
},
220+
}
221+
for _, tt := range tests {
222+
t.Run(tt.name, func(t *testing.T) {
223+
got := ParseCommitWithChangedFilesList(tt.output)
224+
if diff := cmp.Diff(tt.want, got); diff != "" {
225+
t.Errorf("ParseCommitWithChangedFilesList() output mismatch (-want +got):\n%s", diff)
226+
}
227+
})
228+
}
229+
}

0 commit comments

Comments
 (0)