From 838ea434f18bd21db2e3325a5cd70787953e5659 Mon Sep 17 00:00:00 2001 From: chhsia0 Date: Tue, 1 Oct 2019 13:14:01 -0700 Subject: [PATCH] Added `CompareChanges` function to `GitService`. CompareChanges returns the changeset between two commits. If the source commit is not an ancestor of the target commit, it is up to the driver to return a 2-way or 3-way diff changeset. --- scm/driver/bitbucket/git.go | 8 + scm/driver/bitbucket/git_test.go | 26 ++ scm/driver/gitea/git.go | 4 + scm/driver/github/git.go | 11 + scm/driver/github/git_test.go | 30 ++ scm/driver/github/testdata/compare.json | 260 ++++++++++++++++++ .../github/testdata/compare.json.golden | 8 + scm/driver/gitlab/git.go | 11 + scm/driver/gitlab/git_test.go | 32 +++ scm/driver/gitlab/testdata/compare.json | 48 ++++ .../gitlab/testdata/compare.json.golden | 8 + scm/driver/gogs/git.go | 4 + scm/driver/stash/git.go | 12 + scm/driver/stash/git_test.go | 28 ++ scm/driver/stash/testdata/compare.json | 126 +++++++++ scm/driver/stash/testdata/compare.json.golden | 26 ++ scm/git.go | 8 +- 17 files changed, 649 insertions(+), 1 deletion(-) create mode 100644 scm/driver/github/testdata/compare.json create mode 100644 scm/driver/github/testdata/compare.json.golden create mode 100644 scm/driver/gitlab/testdata/compare.json create mode 100644 scm/driver/gitlab/testdata/compare.json.golden create mode 100644 scm/driver/stash/testdata/compare.json create mode 100644 scm/driver/stash/testdata/compare.json.golden diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index c825bcfdc..79b6cae29 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -69,6 +69,14 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm return convertDiffstats(out), res, err } +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + path := fmt.Sprintf("2.0/repositories/%s/diffstat/%s..%s?%s", repo, source, target, encodeListOptions(opts)) + out := new(diffstats) + res, err := s.client.do(ctx, "GET", path, nil, &out) + copyPagination(out.pagination, res) + return convertDiffstats(out), res, err +} + type branch struct { Type string `json:"type"` Name string `json:"name"` diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 277bb4808..7a15e8a83 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -204,3 +204,29 @@ func TestGitListChanges(t *testing.T) { t.Log(diff) } } +func TestGitCompareChanges(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories/atlassian/atlaskit/diffstat/dec26e0fe887167743c2b7e36531dedfeb6cd478..425863f9dbe56d70c8dcdbf2e4e0805e85591fcc"). + MatchParam("page", "1"). + MatchParam("pagelen", "30"). + Reply(200). + Type("application/json"). + File("testdata/diffstat.json") + + client, _ := New("https://api.bitbucket.org") + got, _, err := client.Git.CompareChanges(context.Background(), "atlassian/atlaskit", "dec26e0fe887167743c2b7e36531dedfeb6cd478", "425863f9dbe56d70c8dcdbf2e4e0805e85591fcc", scm.ListOptions{Page: 1, Size: 30}) + if err != nil { + t.Error(err) + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/diffstat.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index f16c58576..c6cfaa12a 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -53,6 +53,10 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li return nil, nil, scm.ErrNotSupported } +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/scm/driver/github/git.go b/scm/driver/github/git.go index 9a41e562e..fb07733ec 100644 --- a/scm/driver/github/git.go +++ b/scm/driver/github/git.go @@ -62,6 +62,13 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li return convertChangeList(out.Files), res, err } +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/compare/%s...%s", repo, source, target) + out := new(compare) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertChangeList(out.Files), res, err +} + type branch struct { Name string `json:"name"` Commit commit `json:"commit"` @@ -95,6 +102,10 @@ type commit struct { Files []*file `json:"files"` } +type compare struct { + Files []*file `json:"files"` +} + func convertCommitList(from []*commit) []*scm.Commit { to := []*scm.Commit{} for _, v := range from { diff --git a/scm/driver/github/git_test.go b/scm/driver/github/git_test.go index 712fe034b..4bc40050b 100644 --- a/scm/driver/github/git_test.go +++ b/scm/driver/github/git_test.go @@ -216,3 +216,33 @@ func TestGitListChanges(t *testing.T) { t.Run("Request", testRequest(res)) t.Run("Rate", testRate(res)) } + +func TestGitCompareChanges(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/repos/octocat/hello-world/compare/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e...7fd1a60b01f91b314f59955a4e4d4e80d8edf11d"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/compare.json") + + client := NewDefault() + got, res, err := client.Git.CompareChanges(context.Background(), "octocat/hello-world", "553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/compare.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} diff --git a/scm/driver/github/testdata/compare.json b/scm/driver/github/testdata/compare.json new file mode 100644 index 000000000..0b400f801 --- /dev/null +++ b/scm/driver/github/testdata/compare.json @@ -0,0 +1,260 @@ +{ + "url": "https://api.github.com/repos/octocat/Hello-World/compare/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e...7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", + "html_url": "https://github.com/octocat/Hello-World/compare/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e...7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", + "permalink_url": "https://github.com/octocat/Hello-World/compare/octocat:553c207...octocat:7fd1a60", + "diff_url": "https://github.com/octocat/Hello-World/compare/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e...7fd1a60b01f91b314f59955a4e4d4e80d8edf11d.diff", + "patch_url": "https://github.com/octocat/Hello-World/compare/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e...7fd1a60b01f91b314f59955a4e4d4e80d8edf11d.patch", + "base_commit": { + "sha": "553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "node_id": "MDY6Q29tbWl0MTI5NjI2OTo1NTNjMjA3N2YwZWRjM2Q1ZGM1ZDE3MjYyZjZhYTQ5OGU2OWQ2Zjhl", + "commit": { + "author": { + "name": "cameronmcefee", + "email": "cameron@github.com", + "date": "2011-01-26T19:06:08Z" + }, + "committer": { + "name": "cameronmcefee", + "email": "cameron@github.com", + "date": "2011-01-26T19:06:08Z" + }, + "message": "first commit", + "tree": { + "sha": "fcf4a9bba6857422971d67147517eb5edfdbf48d", + "url": "https://api.github.com/repos/octocat/Hello-World/git/trees/fcf4a9bba6857422971d67147517eb5edfdbf48d" + }, + "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "comment_count": 51, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null + } + }, + "url": "https://api.github.com/repos/octocat/Hello-World/commits/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "html_url": "https://github.com/octocat/Hello-World/commit/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e/comments", + "author": null, + "committer": null, + "parents": [] + }, + "merge_base_commit": { + "sha": "553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "node_id": "MDY6Q29tbWl0MTI5NjI2OTo1NTNjMjA3N2YwZWRjM2Q1ZGM1ZDE3MjYyZjZhYTQ5OGU2OWQ2Zjhl", + "commit": { + "author": { + "name": "cameronmcefee", + "email": "cameron@github.com", + "date": "2011-01-26T19:06:08Z" + }, + "committer": { + "name": "cameronmcefee", + "email": "cameron@github.com", + "date": "2011-01-26T19:06:08Z" + }, + "message": "first commit", + "tree": { + "sha": "fcf4a9bba6857422971d67147517eb5edfdbf48d", + "url": "https://api.github.com/repos/octocat/Hello-World/git/trees/fcf4a9bba6857422971d67147517eb5edfdbf48d" + }, + "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "comment_count": 51, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null + } + }, + "url": "https://api.github.com/repos/octocat/Hello-World/commits/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "html_url": "https://github.com/octocat/Hello-World/commit/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e/comments", + "author": null, + "committer": null, + "parents": [] + }, + "status": "ahead", + "ahead_by": 2, + "behind_by": 0, + "total_commits": 2, + "commits": [ + { + "sha": "762941318ee16e59dabbacb1b4049eec22f0d303", + "node_id": "MDY6Q29tbWl0MTI5NjI2OTo3NjI5NDEzMThlZTE2ZTU5ZGFiYmFjYjFiNDA0OWVlYzIyZjBkMzAz", + "commit": { + "author": { + "name": "Johnneylee Jack Rollins", + "email": "johnneylee.rollins@gmail.com", + "date": "2011-09-14T04:42:41Z" + }, + "committer": { + "name": "Johnneylee Jack Rollins", + "email": "johnneylee.rollins@gmail.com", + "date": "2011-09-14T04:42:41Z" + }, + "message": "New line at end of file. --Signed off by Spaceghost", + "tree": { + "sha": "b4eecafa9be2f2006ce1b709d6857b07069b4608", + "url": "https://api.github.com/repos/octocat/Hello-World/git/trees/b4eecafa9be2f2006ce1b709d6857b07069b4608" + }, + "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/762941318ee16e59dabbacb1b4049eec22f0d303", + "comment_count": 213, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null + } + }, + "url": "https://api.github.com/repos/octocat/Hello-World/commits/762941318ee16e59dabbacb1b4049eec22f0d303", + "html_url": "https://github.com/octocat/Hello-World/commit/762941318ee16e59dabbacb1b4049eec22f0d303", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/762941318ee16e59dabbacb1b4049eec22f0d303/comments", + "author": { + "login": "Spaceghost", + "id": 251370, + "node_id": "MDQ6VXNlcjI1MTM3MA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/251370?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Spaceghost", + "html_url": "https://github.com/Spaceghost", + "followers_url": "https://api.github.com/users/Spaceghost/followers", + "following_url": "https://api.github.com/users/Spaceghost/following{/other_user}", + "gists_url": "https://api.github.com/users/Spaceghost/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Spaceghost/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Spaceghost/subscriptions", + "organizations_url": "https://api.github.com/users/Spaceghost/orgs", + "repos_url": "https://api.github.com/users/Spaceghost/repos", + "events_url": "https://api.github.com/users/Spaceghost/events{/privacy}", + "received_events_url": "https://api.github.com/users/Spaceghost/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "Spaceghost", + "id": 251370, + "node_id": "MDQ6VXNlcjI1MTM3MA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/251370?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Spaceghost", + "html_url": "https://github.com/Spaceghost", + "followers_url": "https://api.github.com/users/Spaceghost/followers", + "following_url": "https://api.github.com/users/Spaceghost/following{/other_user}", + "gists_url": "https://api.github.com/users/Spaceghost/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Spaceghost/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Spaceghost/subscriptions", + "organizations_url": "https://api.github.com/users/Spaceghost/orgs", + "repos_url": "https://api.github.com/users/Spaceghost/repos", + "events_url": "https://api.github.com/users/Spaceghost/events{/privacy}", + "received_events_url": "https://api.github.com/users/Spaceghost/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "url": "https://api.github.com/repos/octocat/Hello-World/commits/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "html_url": "https://github.com/octocat/Hello-World/commit/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e" + } + ] + }, + { + "sha": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", + "node_id": "MDY6Q29tbWl0MTI5NjI2OTo3ZmQxYTYwYjAxZjkxYjMxNGY1OTk1NWE0ZTRkNGU4MGQ4ZWRmMTFk", + "commit": { + "author": { + "name": "The Octocat", + "email": "octocat@nowhere.com", + "date": "2012-03-06T23:06:50Z" + }, + "committer": { + "name": "The Octocat", + "email": "octocat@nowhere.com", + "date": "2012-03-06T23:06:50Z" + }, + "message": "Merge pull request #6 from Spaceghost/patch-1\n\nNew line at end of file.", + "tree": { + "sha": "b4eecafa9be2f2006ce1b709d6857b07069b4608", + "url": "https://api.github.com/repos/octocat/Hello-World/git/trees/b4eecafa9be2f2006ce1b709d6857b07069b4608" + }, + "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", + "comment_count": 61, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null + } + }, + "url": "https://api.github.com/repos/octocat/Hello-World/commits/7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", + "html_url": "https://github.com/octocat/Hello-World/commit/7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/7fd1a60b01f91b314f59955a4e4d4e80d8edf11d/comments", + "author": { + "login": "octocat", + "id": 583231, + "node_id": "MDQ6VXNlcjU4MzIzMQ==", + "avatar_url": "https://avatars3.githubusercontent.com/u/583231?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "octocat", + "id": 583231, + "node_id": "MDQ6VXNlcjU4MzIzMQ==", + "avatar_url": "https://avatars3.githubusercontent.com/u/583231?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "url": "https://api.github.com/repos/octocat/Hello-World/commits/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e", + "html_url": "https://github.com/octocat/Hello-World/commit/553c2077f0edc3d5dc5d17262f6aa498e69d6f8e" + }, + { + "sha": "762941318ee16e59dabbacb1b4049eec22f0d303", + "url": "https://api.github.com/repos/octocat/Hello-World/commits/762941318ee16e59dabbacb1b4049eec22f0d303", + "html_url": "https://github.com/octocat/Hello-World/commit/762941318ee16e59dabbacb1b4049eec22f0d303" + } + ] + } + ], + "files": [ + { + "sha": "980a0d5f19a64b4b30a87d4206aade58726b60e3", + "filename": "README", + "status": "modified", + "additions": 1, + "deletions": 1, + "changes": 2, + "blob_url": "https://github.com/octocat/Hello-World/blob/7fd1a60b01f91b314f59955a4e4d4e80d8edf11d/README", + "raw_url": "https://github.com/octocat/Hello-World/raw/7fd1a60b01f91b314f59955a4e4d4e80d8edf11d/README", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/README?ref=7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", + "patch": "@@ -1 +1 @@\n-Hello World!\n\\ No newline at end of file\n+Hello World!" + } + ] +} diff --git a/scm/driver/github/testdata/compare.json.golden b/scm/driver/github/testdata/compare.json.golden new file mode 100644 index 000000000..f502bc0db --- /dev/null +++ b/scm/driver/github/testdata/compare.json.golden @@ -0,0 +1,8 @@ +[ + { + "Path": "README", + "Added": false, + "Renamed": false, + "Deleted": false + } +] diff --git a/scm/driver/gitlab/git.go b/scm/driver/gitlab/git.go index 3ff1fa4f5..7b7e78d09 100644 --- a/scm/driver/gitlab/git.go +++ b/scm/driver/gitlab/git.go @@ -65,6 +65,13 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm return convertChangeList(out), res, err } +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/repository/compare?from=%s&to=%s", encode(repo), source, target) + out := new(compare) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertChangeList(out.Diffs), res, err +} + type branch struct { Name string `json:"name"` Commit struct { @@ -85,6 +92,10 @@ type commit struct { Created time.Time `json:"created_at"` } +type compare struct { + Diffs []*change `json:"diffs"` +} + func convertCommitList(from []*commit) []*scm.Commit { to := []*scm.Commit{} for _, v := range from { diff --git a/scm/driver/gitlab/git_test.go b/scm/driver/gitlab/git_test.go index 31e9fcdaa..dab63658b 100644 --- a/scm/driver/gitlab/git_test.go +++ b/scm/driver/gitlab/git_test.go @@ -242,3 +242,35 @@ func TestGitListChanges(t *testing.T) { t.Run("Request", testRequest(res)) t.Run("Rate", testRate(res)) } + +func TestGitCompareChanges(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Get("/api/v4/projects/diaspora/diaspora/repository/compare"). + MatchParam("from", "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"). + MatchParam("to", "6104942438c14ec7bd21c6cd5bd995272b3faff6"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/compare.json") + + client := NewDefault() + got, res, err := client.Git.CompareChanges(context.Background(), "diaspora/diaspora", "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba", "6104942438c14ec7bd21c6cd5bd995272b3faff6", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/compare.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} diff --git a/scm/driver/gitlab/testdata/compare.json b/scm/driver/gitlab/testdata/compare.json new file mode 100644 index 000000000..4494fe83b --- /dev/null +++ b/scm/driver/gitlab/testdata/compare.json @@ -0,0 +1,48 @@ +{ + "commit": { + "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", + "short_id": "6104942438c", + "title": "Sanitize for network graph", + "author_name": "randx", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committer_name": "Dmitriy", + "committer_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2012-06-28T03:44:20-07:00", + "message": "Sanitize for network graph", + "committed_date": "2012-06-28T03:44:20-07:00", + "authored_date": "2012-06-28T03:44:20-07:00", + "parent_ids": [ + "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" + ] + }, + "commits": [ + { + "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", + "short_id": "6104942438c", + "title": "Sanitize for network graph", + "author_name": "randx", + "author_email": "dmitriy.zaporozhets@gmail.com", + "committer_name": "Dmitriy", + "committer_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2012-06-28T03:44:20-07:00", + "message": "Sanitize for network graph", + "committed_date": "2012-06-28T03:44:20-07:00", + "authored_date": "2012-06-28T03:44:20-07:00", + "parent_ids": [ + "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" + ] + } + ], + "diffs": [ + { + "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files", + "new_path": "doc/update/5.4-to-6.0.md", + "old_path": "doc/update/5.4-to-6.0.md", + "a_mode": null, + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false + } + ] +} diff --git a/scm/driver/gitlab/testdata/compare.json.golden b/scm/driver/gitlab/testdata/compare.json.golden new file mode 100644 index 000000000..fc86cb189 --- /dev/null +++ b/scm/driver/gitlab/testdata/compare.json.golden @@ -0,0 +1,8 @@ +[ + { + "Path": "doc/update/5.4-to-6.0.md", + "Added": true, + "Renamed": false, + "Deleted": false + } +] \ No newline at end of file diff --git a/scm/driver/gogs/git.go b/scm/driver/gogs/git.go index 45075bcb3..3956547de 100644 --- a/scm/driver/gogs/git.go +++ b/scm/driver/gogs/git.go @@ -53,6 +53,10 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li return nil, nil, scm.ErrNotSupported } +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go index b43e126bd..b07e9087e 100644 --- a/scm/driver/stash/git.go +++ b/scm/driver/stash/git.go @@ -99,6 +99,18 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm return convertDiffstats(out), res, err } +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/compare/changes?from=%s&to=%s&%s", namespace, name, source, target, encodeListOptions(opts)) + out := new(diffstats) + res, err := s.client.do(ctx, "GET", path, nil, &out) + if !out.pagination.LastPage.Bool { + res.Page.First = 1 + res.Page.Next = opts.Page + 1 + } + return convertDiffstats(out), res, err +} + type branch struct { ID string `json:"id"` DisplayID string `json:"displayId"` diff --git a/scm/driver/stash/git_test.go b/scm/driver/stash/git_test.go index 095abeda7..9d8209327 100644 --- a/scm/driver/stash/git_test.go +++ b/scm/driver/stash/git_test.go @@ -182,3 +182,31 @@ func TestGitListChanges(t *testing.T) { t.Log(diff) } } + +func TestGitCompareChanges(t *testing.T) { + defer gock.Off() + + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/my-repo/compare/changes"). + MatchParam("from", "4f4b0ef1714a5b6cafdaf2f53c7f5f5b38fb9348"). + MatchParam("to", "131cb13f4aed12e725177bc4b7c28db67839bf9f"). + MatchParam("limit", "30"). + Reply(200). + Type("application/json"). + File("testdata/compare.json") + + client, _ := New("http://example.com:7990") + got, _, err := client.Git.CompareChanges(context.Background(), "PRJ/my-repo", "4f4b0ef1714a5b6cafdaf2f53c7f5f5b38fb9348", "131cb13f4aed12e725177bc4b7c28db67839bf9f", scm.ListOptions{Page: 1, Size: 30}) + if err != nil { + t.Error(err) + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/compare.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/stash/testdata/compare.json b/scm/driver/stash/testdata/compare.json new file mode 100644 index 000000000..e94519b3b --- /dev/null +++ b/scm/driver/stash/testdata/compare.json @@ -0,0 +1,126 @@ +{ + "values": [ + { + "contentId": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "fromContentId": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "path": { + "components": [ + ".gitignore" + ], + "parent": "", + "name": ".gitignore", + "extension": "gitignore", + "toString": ".gitignore" + }, + "percentUnchanged": -1, + "type": "DELETE", + "nodeType": "FILE", + "srcExecutable": false, + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/commits/131cb13f4aed12e725177bc4b7c28db67839bf9f#.gitignore" + } + ] + }, + "properties": { + "gitChangeType": "DELETE" + } + }, + { + "contentId": "f1df0de7c4a94b7d83bd4864154e48e8b7f4d2cb", + "fromContentId": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "path": { + "components": [ + "COPYING" + ], + "parent": "", + "name": "COPYING", + "toString": "COPYING" + }, + "executable": false, + "percentUnchanged": -1, + "type": "MODIFY", + "nodeType": "FILE", + "srcExecutable": false, + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/commits/131cb13f4aed12e725177bc4b7c28db67839bf9f#COPYING" + } + ] + }, + "properties": { + "gitChangeType": "MODIFY" + } + }, + { + "contentId": "e427984d4a2c1904681f2e2ee5980f37640d353f", + "fromContentId": "e427984d4a2c1904681f2e2ee5980f37640d353f", + "path": { + "components": [ + "README.md" + ], + "parent": "", + "name": "README.md", + "extension": "md", + "toString": "README.md" + }, + "executable": false, + "percentUnchanged": 100, + "type": "MOVE", + "nodeType": "FILE", + "srcPath": { + "components": [ + "README" + ], + "parent": "", + "name": "README", + "toString": "README" + }, + "srcExecutable": false, + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/commits/131cb13f4aed12e725177bc4b7c28db67839bf9f#README.md" + } + ] + }, + "properties": { + "gitChangeType": "RENAME" + } + }, + { + "contentId": "002a5c740c7d288d40d490a43aae9297488a2433", + "fromContentId": "0000000000000000000000000000000000000000", + "path": { + "components": [ + "main.go" + ], + "parent": "", + "name": "main.go", + "extension": "go", + "toString": "main.go" + }, + "executable": false, + "percentUnchanged": -1, + "type": "ADD", + "nodeType": "FILE", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/commits/131cb13f4aed12e725177bc4b7c28db67839bf9f#main.go" + } + ] + }, + "properties": { + "gitChangeType": "ADD" + } + } + ], + "size": 4, + "isLastPage": true, + "start": 0, + "limit": 25, + "nextPageStart": null +} diff --git a/scm/driver/stash/testdata/compare.json.golden b/scm/driver/stash/testdata/compare.json.golden new file mode 100644 index 000000000..de482d945 --- /dev/null +++ b/scm/driver/stash/testdata/compare.json.golden @@ -0,0 +1,26 @@ +[ + { + "Path": ".gitignore", + "Added": false, + "Renamed": false, + "Deleted": true + }, + { + "Path": "COPYING", + "Added": false, + "Renamed": false, + "Deleted": false + }, + { + "Path": "README.md", + "Added": false, + "Renamed": true, + "Deleted": false + }, + { + "Path": "main.go", + "Added": true, + "Renamed": false, + "Deleted": false + } +] \ No newline at end of file diff --git a/scm/git.go b/scm/git.go index f4b20f7ab..a5bda8e1c 100644 --- a/scm/git.go +++ b/scm/git.go @@ -66,10 +66,16 @@ type ( // ListCommits returns a list of git commits. ListCommits(ctx context.Context, repo string, opts CommitListOptions) ([]*Commit, *Response, error) - // ListChanges returns the changeset between two commits. + // ListChanges returns the changeset of a commit. ListChanges(ctx context.Context, repo, ref string, opts ListOptions) ([]*Change, *Response, error) // ListTags returns a list of git tags. ListTags(ctx context.Context, repo string, opts ListOptions) ([]*Reference, *Response, error) + + // CompareChanges returns the changeset between two + // commits. If the source commit is not an ancestor + // of the target commit, it is up to the driver to + // return a 2-way or 3-way diff changeset. + CompareChanges(ctx context.Context, repo, source, target string, opts ListOptions) ([]*Change, *Response, error) } )