From 7947a0551e724bf55e0f35f71b8df64d3c6c7c93 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Wed, 2 Feb 2022 23:27:52 -0500 Subject: [PATCH] Implements getting commit on branches for GitHub Consolidates into a single method call --- .vscode/queries.github-graphql-nb | 2 +- src/commands/quickCommand.steps.ts | 13 +++- src/env/node/git/localGitProvider.ts | 19 +++-- src/git/gitProvider.ts | 9 ++- src/git/gitProviderService.ts | 26 +++---- src/premium/github/github.ts | 133 ++++++++++++++++++++++++++++++++ src/premium/github/githubGitProvider.ts | 28 ++++++- src/views/branchesView.ts | 6 +- src/views/commitsView.ts | 8 +- src/views/remotesView.ts | 6 +- src/views/repositoriesView.ts | 12 ++- 11 files changed, 220 insertions(+), 42 deletions(-) diff --git a/.vscode/queries.github-graphql-nb b/.vscode/queries.github-graphql-nb index 5d04e1c..dc4caab 100644 --- a/.vscode/queries.github-graphql-nb +++ b/.vscode/queries.github-graphql-nb @@ -1 +1 @@ -{"cells":[{"code":"### Get Default Branch & Tip","kind":"markdown"},{"code":"query getDefaultBranchAndTip(\n\t$owner: String!\n\t$repo: String!\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tdefaultBranchRef {\n\t\t\tname\n\t\t\ttarget { oid }\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Get Branches","kind":"markdown"},{"code":"query getBranches(\n\t$owner: String!\n\t$repo: String!\n\t$branchQuery: String\n\t$cursor: String\n\t$limit: Int = 100\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\trefs(query: $branchQuery, refPrefix: \"refs/heads/\", first: $limit, after: $cursor, orderBy: { field: TAG_COMMIT_DATE, direction: DESC }) {\n\t\t\tpageInfo {\n\t\t\t\tendCursor\n\t\t\t\thasNextPage\n\t\t\t}\n\t\t\tnodes {\n\t\t\t\tname\n\t\t\t\ttarget {\n\t\t\t\t\toid\n\t\t\t\t\tcommitUrl\n\t\t\t\t\t...on Commit {\n\t\t\t\t\t\tauthoredDate\n\t\t\t\t\t\tcommittedDate\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Get Blame","kind":"markdown"},{"code":"query getBlame(\n\t$owner: String!\n\t$repo: String!\n\t$ref: GitObjectID!\n\t$path: String!\n) {\n\tviewer { name }\n\trepository(owner: $owner, name: $repo) {\n\t\tobject(oid: $ref) {\n\t\t\t...on Commit {\n\t\t\t\tblame(path: $path) {\n\t\t\t\t\tranges {\n\t\t\t\t\t\tstartingLine\n\t\t\t\t\t\tendingLine\n\t\t\t\t\t\tage\n\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\tparents(first: 3) { nodes { oid } }\n\t\t\t\t\t\t\tmessage\n\t\t\t\t\t\t\tauthor {\n\t\t\t\t\t\t\t\tavatarUrl\n\t\t\t\t\t\t\t\tdate\n\t\t\t\t\t\t\t\temail\n\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcommitter { date }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"54f28933055124d6ba3808a787f6947c929f9db0\",\n\t\"path\": \"src/keyboard.ts\"\n}","kind":"code"},{"code":"### Get Commit for File","kind":"markdown"},{"code":"query getCommitForFile(\n\t$owner: String!\n\t$repo: String!\n\t$ref: String!\n\t$path: String!\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tref(qualifiedName: $ref) {\n\t\t\ttarget {\n\t\t\t\t... on Commit {\n\t\t\t\t\thistory(first: 1, path: $path) {\n\t\t\t\t\t\tnodes {\n\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\tparents(first: 3) { nodes { oid } }\n\t\t\t\t\t\t\tmessage\n\t\t\t\t\t\t\tadditions\n\t\t\t\t\t\t\tchangedFiles\n\t\t\t\t\t\t\tdeletions\n\t\t\t\t\t\t\tauthor {\n\t\t\t\t\t\t\t\tdate\n\t\t\t\t\t\t\t\temail\n\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcommitter { date }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"refs/heads/main\",\n\t\"path\": \"src/extension.ts\"\n}","kind":"code"},{"code":"### Get Current User","kind":"markdown"},{"code":"query getCurrentUser(\n\t$owner: String!\n\t$repo: String!\n) {\n\tviewer { name }\n\trepository(name: $repo owner: $owner) {\n\t\tviewerPermission\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Get Commit","kind":"markdown"},{"code":"query getCommit(\n\t$owner: String!\n\t$repo: String!\n\t$ref: GitObjectID!\n) {\n\trepository(name: $repo owner: $owner) {\n\t\tobject(oid: $ref) {\n\t\t\t...on Commit {\n\t\t\t\toid\n\t\t\t\tparents(first: 3) { nodes { oid } }\n\t\t\t\tmessage\n\t\t\t\tadditions\n\t\t\t\tchangedFiles\n\t\t\t\tdeletions\n\t\t\t\tauthor {\n\t\t\t\t\tdate\n\t\t\t\t\temail\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tcommitter { date }\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"54f28933055124d6ba3808a787f6947c929f9db0\"\n}","kind":"code"},{"code":"### Get Commits","kind":"markdown"},{"code":"query getCommits(\n\t$owner: String!\n\t$repo: String!\n\t$ref: GitObjectID!\n) {\n\trepository(name: $repo owner: $owner) {\n\t\tobject(oid: $ref) {\n\t\t\t...on Commit {\n\t\t\t\toid\n\t\t\t\tparents(first: 3) { nodes { oid } }\n\t\t\t\tmessage\n\t\t\t\tadditions\n\t\t\t\tchangedFiles\n\t\t\t\tdeletions\n\t\t\t\tauthor {\n\t\t\t\t\tdate\n\t\t\t\t\temail\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tcommitter { date }\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"54f28933055124d6ba3808a787f6947c929f9db0\"\n}","kind":"code"},{"code":"### Get Tags","kind":"markdown"},{"code":"query getTags(\n\t$owner: String!\n\t$repo: String!\n\t$tagQuery: String\n\t$cursor: String\n\t$limit: Int = 100\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\trefs(query: $tagQuery, refPrefix: \"refs/tags/\", first: $limit, after: $cursor, orderBy: { field: TAG_COMMIT_DATE, direction: DESC }) {\n\t\t\tpageInfo {\n\t\t\t\tendCursor\n\t\t\t\thasNextPage\n\t\t\t}\n\t\t\tnodes {\n\t\t\t\tname\n\t\t\t\ttarget {\n\t\t\t\t\toid\n\t\t\t\t\tcommitUrl\n\t\t\t\t\t...on Commit {\n\t\t\t\t\t\tauthoredDate\n\t\t\t\t\t\tcommittedDate\n\t\t\t\t\t\tmessage\n\t\t\t\t\t}\n\t\t\t\t\t...on Tag {\n\t\t\t\t\t\tmessage\n\t\t\t\t\t\ttagger { date }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Get Contributors","kind":"markdown"},{"code":"query getContributors(\n\t$owner: String!\n\t$repo: String!\n\t$cursor: String\n\t$limit: Int = 100\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tcollaborators(affiliation: ALL, first: $limit, after: $cursor) {\n\t\t\tpageInfo {\n\t\t\t\tendCursor\n\t\t\t\thasNextPage\n\t\t\t}\n\t\t\tnodes {\n\t\t\t\tname\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Resolve reference","kind":"markdown"},{"code":"query resolveReference(\n\t$owner: String!\n\t$repo: String!\n\t$ref: String!\n\t$path: String!\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tobject(expression: $ref) {\n\t\t\t... on Commit {\n\t\t\t\thistory(first: 1, path: $path) {\n\t\t\t\t\tnodes { oid }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"d790e9db047769de079f6838c3578f3a47bf5930^\",\n\t\"path\": \"CODE_OF_CONDUCT.md\"\n}","kind":"code"}]} \ No newline at end of file +{"cells":[{"code":"### Get Default Branch & Tip","kind":"markdown"},{"code":"query getDefaultBranchAndTip(\n\t$owner: String!\n\t$repo: String!\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tdefaultBranchRef {\n\t\t\tname\n\t\t\ttarget { oid }\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Get Branches","kind":"markdown"},{"code":"query getBranches(\n\t$owner: String!\n\t$repo: String!\n\t$branchQuery: String\n\t$cursor: String\n\t$limit: Int = 100\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\trefs(query: $branchQuery, refPrefix: \"refs/heads/\", first: $limit, after: $cursor, orderBy: { field: TAG_COMMIT_DATE, direction: DESC }) {\n\t\t\tpageInfo {\n\t\t\t\tendCursor\n\t\t\t\thasNextPage\n\t\t\t}\n\t\t\tnodes {\n\t\t\t\tname\n\t\t\t\ttarget {\n\t\t\t\t\toid\n\t\t\t\t\tcommitUrl\n\t\t\t\t\t...on Commit {\n\t\t\t\t\t\tauthoredDate\n\t\t\t\t\t\tcommittedDate\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Get Blame","kind":"markdown"},{"code":"query getBlame(\n\t$owner: String!\n\t$repo: String!\n\t$ref: GitObjectID!\n\t$path: String!\n) {\n\tviewer { name }\n\trepository(owner: $owner, name: $repo) {\n\t\tobject(oid: $ref) {\n\t\t\t...on Commit {\n\t\t\t\tblame(path: $path) {\n\t\t\t\t\tranges {\n\t\t\t\t\t\tstartingLine\n\t\t\t\t\t\tendingLine\n\t\t\t\t\t\tage\n\t\t\t\t\t\tcommit {\n\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\tparents(first: 3) { nodes { oid } }\n\t\t\t\t\t\t\tmessage\n\t\t\t\t\t\t\tauthor {\n\t\t\t\t\t\t\t\tavatarUrl\n\t\t\t\t\t\t\t\tdate\n\t\t\t\t\t\t\t\temail\n\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcommitter { date }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"54f28933055124d6ba3808a787f6947c929f9db0\",\n\t\"path\": \"src/keyboard.ts\"\n}","kind":"code"},{"code":"### Get Commit for File","kind":"markdown"},{"code":"query getCommitForFile(\n\t$owner: String!\n\t$repo: String!\n\t$ref: String!\n\t$path: String!\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tref(qualifiedName: $ref) {\n\t\t\ttarget {\n\t\t\t\t... on Commit {\n\t\t\t\t\thistory(first: 1, path: $path) {\n\t\t\t\t\t\tnodes {\n\t\t\t\t\t\t\toid\n\t\t\t\t\t\t\tparents(first: 3) { nodes { oid } }\n\t\t\t\t\t\t\tmessage\n\t\t\t\t\t\t\tadditions\n\t\t\t\t\t\t\tchangedFiles\n\t\t\t\t\t\t\tdeletions\n\t\t\t\t\t\t\tauthor {\n\t\t\t\t\t\t\t\tdate\n\t\t\t\t\t\t\t\temail\n\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcommitter { date }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"refs/heads/main\",\n\t\"path\": \"src/extension.ts\"\n}","kind":"code"},{"code":"### Get Current User","kind":"markdown"},{"code":"query getCurrentUser(\n\t$owner: String!\n\t$repo: String!\n) {\n\tviewer { name }\n\trepository(name: $repo owner: $owner) {\n\t\tviewerPermission\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Get Commit","kind":"markdown"},{"code":"query getCommit(\n\t$owner: String!\n\t$repo: String!\n\t$ref: GitObjectID!\n) {\n\trepository(name: $repo owner: $owner) {\n\t\tobject(oid: $ref) {\n\t\t\t...on Commit {\n\t\t\t\toid\n\t\t\t\tparents(first: 3) { nodes { oid } }\n\t\t\t\tmessage\n\t\t\t\tadditions\n\t\t\t\tchangedFiles\n\t\t\t\tdeletions\n\t\t\t\tauthor {\n\t\t\t\t\tdate\n\t\t\t\t\temail\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tcommitter { date }\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"54f28933055124d6ba3808a787f6947c929f9db0\"\n}","kind":"code"},{"code":"### Get Commits","kind":"markdown"},{"code":"query getCommits(\n\t$owner: String!\n\t$repo: String!\n\t$ref: GitObjectID!\n) {\n\trepository(name: $repo owner: $owner) {\n\t\tobject(oid: $ref) {\n\t\t\t...on Commit {\n\t\t\t\toid\n\t\t\t\tparents(first: 3) { nodes { oid } }\n\t\t\t\tmessage\n\t\t\t\tadditions\n\t\t\t\tchangedFiles\n\t\t\t\tdeletions\n\t\t\t\tauthor {\n\t\t\t\t\tdate\n\t\t\t\t\temail\n\t\t\t\t\tname\n\t\t\t\t}\n\t\t\t\tcommitter { date }\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"54f28933055124d6ba3808a787f6947c929f9db0\"\n}","kind":"code"},{"code":"### Get Tags","kind":"markdown"},{"code":"query getTags(\n\t$owner: String!\n\t$repo: String!\n\t$tagQuery: String\n\t$cursor: String\n\t$limit: Int = 100\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\trefs(query: $tagQuery, refPrefix: \"refs/tags/\", first: $limit, after: $cursor, orderBy: { field: TAG_COMMIT_DATE, direction: DESC }) {\n\t\t\tpageInfo {\n\t\t\t\tendCursor\n\t\t\t\thasNextPage\n\t\t\t}\n\t\t\tnodes {\n\t\t\t\tname\n\t\t\t\ttarget {\n\t\t\t\t\toid\n\t\t\t\t\tcommitUrl\n\t\t\t\t\t...on Commit {\n\t\t\t\t\t\tauthoredDate\n\t\t\t\t\t\tcommittedDate\n\t\t\t\t\t\tmessage\n\t\t\t\t\t}\n\t\t\t\t\t...on Tag {\n\t\t\t\t\t\tmessage\n\t\t\t\t\t\ttagger { date }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Get Contributors","kind":"markdown"},{"code":"query getContributors(\n\t$owner: String!\n\t$repo: String!\n\t$cursor: String\n\t$limit: Int = 100\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tcollaborators(affiliation: ALL, first: $limit, after: $cursor) {\n\t\t\tpageInfo {\n\t\t\t\tendCursor\n\t\t\t\thasNextPage\n\t\t\t}\n\t\t\tnodes {\n\t\t\t\tname\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\"\n}","kind":"code"},{"code":"### Resolve reference","kind":"markdown"},{"code":"query resolveReference(\n\t$owner: String!\n\t$repo: String!\n\t$ref: String!\n\t$path: String!\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tobject(expression: $ref) {\n\t\t\t... on Commit {\n\t\t\t\thistory(first: 1, path: $path) {\n\t\t\t\t\tnodes { oid }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"d790e9db047769de079f6838c3578f3a47bf5930^\",\n\t\"path\": \"CODE_OF_CONDUCT.md\"\n}","kind":"code"},{"code":"### Get branches that contain commit","kind":"markdown"},{"code":"query getCommitBranches(\n\t$owner: String!\n\t$repo: String!\n\t$since: GitTimestamp!\n\t$until: GitTimestamp!\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\trefs(first: 20, refPrefix: \"refs/heads/\", orderBy: { field: TAG_COMMIT_DATE, direction: DESC }) {\n\t\t\tnodes {\n\t\t\t\tname\n\t\t\t\ttarget {\n\t\t\t\t\t... on Commit {\n\t\t\t\t\t\thistory(first: 3, since: $since until: $until) {\n\t\t\t\t\t\t\tnodes { oid }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"since\": \"2022-01-06T01:07:46-04:00\",\n\t\"until\": \"2022-01-06T01:07:46-05:00\"\n}","kind":"code"},{"code":"query getCommitBranch(\n\t$owner: String!\n\t$repo: String!\n\t$ref: String!\n\t$since: GitTimestamp!\n\t$until: GitTimestamp!\n) {\n\trepository(owner: $owner, name: $repo) {\n\t\tref(qualifiedName: $ref) {\n\t\t\ttarget {\n\t\t\t\t... on Commit {\n\t\t\t\t\thistory(first: 3, since: $since until: $until) {\n\t\t\t\t\t\tnodes { oid }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvariables {\n\t\"owner\": \"eamodio\",\n\t\"repo\": \"vscode-gitlens\",\n\t\"ref\": \"refs/heads/main\",\n\t\"since\": \"2022-01-06T01:07:46-04:00\",\n\t\"until\": \"2022-01-06T01:07:46-05:00\"\n}","kind":"code"}]} \ No newline at end of file diff --git a/src/commands/quickCommand.steps.ts b/src/commands/quickCommand.steps.ts index 47e58da..e046c6c 100644 --- a/src/commands/quickCommand.steps.ts +++ b/src/commands/quickCommand.steps.ts @@ -1475,10 +1475,15 @@ async function getShowCommitOrStashStepItems< new SearchForCommitQuickPickItem(state.reference), ); - if ( - branch != null && - (await Container.instance.git.branchContainsCommit(state.repo.path, branch.name, state.reference.ref)) - ) { + const branches = + branch != null + ? await Container.instance.git.getCommitBranches(state.repo.path, state.reference.ref, { + branch: branch.name, + commitDate: GitCommit.is(state.reference) ? state.reference.committer.date : undefined, + }) + : undefined; + + if (branches?.length) { items.push( new GitCommandQuickPickItem('Revert Commit...', { command: 'revert', diff --git a/src/env/node/git/localGitProvider.ts b/src/env/node/git/localGitProvider.ts index 95b7ee4..6966578 100644 --- a/src/env/node/git/localGitProvider.ts +++ b/src/env/node/git/localGitProvider.ts @@ -709,13 +709,6 @@ export class LocalGitProvider implements GitProvider, Disposable { } @log() - async branchContainsCommit(repoPath: string, name: string, ref: string): Promise { - let data = await this.git.branch__containsOrPointsAt(repoPath, ref, { mode: 'contains', name: name }); - data = data?.trim(); - return Boolean(data); - } - - @log() async checkout( repoPath: string, ref: string, @@ -1368,8 +1361,18 @@ export class LocalGitProvider implements GitProvider, Disposable { async getCommitBranches( repoPath: string, ref: string, - options?: { mode?: 'contains' | 'pointsAt'; remotes?: boolean }, + options?: { branch?: string; commitDate?: Date; mode?: 'contains' | 'pointsAt'; remotes?: boolean }, ): Promise { + if (options?.branch) { + const data = await this.git.branch__containsOrPointsAt(repoPath, ref, { + mode: 'contains', + name: options.branch, + }); + if (!data) return []; + + return [data?.trim()]; + } + const data = await this.git.branch__containsOrPointsAt(repoPath, ref, options); if (!data) return []; diff --git a/src/git/gitProvider.ts b/src/git/gitProvider.ts index 34f79f5..46b0630 100644 --- a/src/git/gitProvider.ts +++ b/src/git/gitProvider.ts @@ -105,7 +105,6 @@ export interface GitProvider extends Disposable { addRemote(repoPath: string, name: string, url: string): Promise; pruneRemote(repoPath: string, remoteName: string): Promise; applyChangesToWorkingFile(uri: GitUri, ref1?: string, ref2?: string): Promise; - branchContainsCommit(repoPath: string, name: string, ref: string): Promise; checkout( repoPath: string, ref: string, @@ -178,7 +177,13 @@ export interface GitProvider extends Disposable { getCommitBranches( repoPath: string, ref: string, - options?: { mode?: 'contains' | 'pointsAt' | undefined; remotes?: boolean | undefined }, + options?: { + branch?: string | undefined; + commitDate?: Date | undefined; + mode?: 'contains' | 'pointsAt' | undefined; + name?: string | undefined; + remotes?: boolean | undefined; + }, ): Promise; getCommitCount(repoPath: string, ref: string): Promise; getCommitForFile( diff --git a/src/git/gitProviderService.ts b/src/git/gitProviderService.ts index 755c54a..784ad4f 100644 --- a/src/git/gitProviderService.ts +++ b/src/git/gitProviderService.ts @@ -712,12 +712,6 @@ export class GitProviderService implements Disposable { } @log() - async branchContainsCommit(repoPath: string | Uri, name: string, ref: string): Promise { - const { provider, path } = this.getProvider(repoPath); - return provider.branchContainsCommit(path, name, ref); - } - - @log() async checkout( repoPath: string, ref: string, @@ -846,6 +840,15 @@ export class GitProviderService implements Disposable { ); } + @log({ args: { 1: refs => refs.join(',') } }) + getAheadBehindCommitCount( + repoPath: string | Uri, + refs: string[], + ): Promise<{ ahead: number; behind: number } | undefined> { + const { provider, path } = this.getProvider(repoPath); + return provider.getAheadBehindCommitCount(path, refs); + } + @log() /** * Returns the blame of a file @@ -1046,21 +1049,12 @@ export class GitProviderService implements Disposable { getCommitBranches( repoPath: string | Uri, ref: string, - options?: { mode?: 'contains' | 'pointsAt'; remotes?: boolean }, + options?: { branch?: string; commitDate?: Date; mode?: 'contains' | 'pointsAt'; remotes?: boolean }, ): Promise { const { provider, path } = this.getProvider(repoPath); return provider.getCommitBranches(path, ref, options); } - @log({ args: { 1: refs => refs.join(',') } }) - getAheadBehindCommitCount( - repoPath: string | Uri, - refs: string[], - ): Promise<{ ahead: number; behind: number } | undefined> { - const { provider, path } = this.getProvider(repoPath); - return provider.getAheadBehindCommitCount(path, refs); - } - @log() getCommitCount(repoPath: string | Uri, ref: string): Promise { const { provider, path } = this.getProvider(repoPath); diff --git a/src/premium/github/github.ts b/src/premium/github/github.ts index f496b1b..520beeb 100644 --- a/src/premium/github/github.ts +++ b/src/premium/github/github.ts @@ -698,6 +698,139 @@ export class GitHubApi { return { ...(commit ?? results.values[0]), viewer: results.viewer }; } + @debug({ args: { 0: '' } }) + async getCommitBranches( + token: string, + owner: string, + repo: string, + ref: string, + date: Date, + branch?: string, + ): Promise { + const cc = Logger.getCorrelationContext(); + + if (branch) { + interface QueryResult { + repository: { + ref: { + target: { + history: { + nodes: { oid: string }[]; + }; + }; + }; + }; + } + try { + const query = `query getCommitBranch( + $owner: String! + $repo: String! + $ref: String! + $since: GitTimestamp! + $until: GitTimestamp! +) { + repository(owner: $owner, name: $repo) { + ref(qualifiedName: $ref) { + target { + ... on Commit { + history(first: 3, since: $since until: $until) { + nodes { oid } + } + } + } + } + } +}`; + const rsp = await this.graphql(token, query, { + owner: owner, + repo: repo, + ref: `refs/heads/${branch}`, + since: date.toISOString(), + until: date.toISOString(), + }); + + const nodes = rsp?.repository?.ref.target.history.nodes; + if (nodes == null) return []; + + const branches = []; + + for (const commit of nodes) { + if (commit.oid === ref) { + branches.push(branch); + break; + } + } + + return branches; + } catch (ex) { + return this.handleRequestError(ex, cc, []); + } + } + + interface QueryResult { + repository: { + refs: { + nodes: { + name: string; + target: { + history: { + nodes: { oid: string }[]; + }; + }; + }[]; + }; + }; + } + + try { + const query = `query getCommitBranches( + $owner: String! + $repo: String! + $since: GitTimestamp! + $until: GitTimestamp! +) { + repository(owner: $owner, name: $repo) { + refs(first: 20, refPrefix: "refs/heads/", orderBy: { field: TAG_COMMIT_DATE, direction: DESC }) { + nodes { + name + target { + ... on Commit { + history(first: 3, since: $since until: $until) { + nodes { oid } + } + } + } + } + } + } +}`; + const rsp = await this.graphql(token, query, { + owner: owner, + repo: repo, + since: date.toISOString(), + until: date.toISOString(), + }); + + const nodes = rsp?.repository?.refs?.nodes; + if (nodes == null) return []; + + const branches = []; + + for (const branch of nodes) { + for (const commit of branch.target.history.nodes) { + if (commit.oid === ref) { + branches.push(branch.name); + break; + } + } + } + + return branches; + } catch (ex) { + return this.handleRequestError(ex, cc, []); + } + } + @debug({ args: { 0: '' } }) async getCommits( token: string, diff --git a/src/premium/github/githubGitProvider.ts b/src/premium/github/githubGitProvider.ts index f92d2a8..9798454 100644 --- a/src/premium/github/githubGitProvider.ts +++ b/src/premium/github/githubGitProvider.ts @@ -740,11 +740,31 @@ export class GitHubGitProvider implements GitProvider, Disposable { @log() async getCommitBranches( - _repoPath: string, - _ref: string, - _options?: { mode?: 'contains' | 'pointsAt'; remotes?: boolean }, + repoPath: string, + ref: string, + options?: { branch?: string; commitDate?: Date; mode?: 'contains' | 'pointsAt'; remotes?: boolean }, ): Promise { - return []; + if (repoPath == null || options?.commitDate == null) return []; + + const cc = Logger.getCorrelationContext(); + + try { + const { metadata, github, session } = await this.ensureRepositoryContext(repoPath); + + const branches = await github.getCommitBranches( + session?.accessToken, + metadata.repo.owner, + metadata.repo.name, + ref, + options?.commitDate, + options?.branch, + ); + return branches; + } catch (ex) { + Logger.error(ex, cc); + debugger; + return []; + } } @log() diff --git a/src/views/branchesView.ts b/src/views/branchesView.ts index 00f4582..7a7d855 100644 --- a/src/views/branchesView.ts +++ b/src/views/branchesView.ts @@ -240,7 +240,11 @@ export class BranchesView extends ViewBase const repoNodeId = RepositoryNode.getId(commit.repoPath); // Get all the branches the commit is on - const branches = await this.container.git.getCommitBranches(commit.repoPath, commit.ref); + const branches = await this.container.git.getCommitBranches( + commit.repoPath, + commit.ref, + GitCommit.is(commit) ? { commitDate: commit.committer.date } : undefined, + ); if (branches.length === 0) return undefined; return this.findNode((n: any) => n.commit?.ref === commit.ref, { diff --git a/src/views/commitsView.ts b/src/views/commitsView.ts index 79f0733..85dc2b8 100644 --- a/src/views/commitsView.ts +++ b/src/views/commitsView.ts @@ -288,9 +288,11 @@ export class CommitsView extends ViewBase { if (branch == null) return undefined; // Check if the commit exists on the current branch - if (!(await this.container.git.branchContainsCommit(commit.repoPath, branch.name, commit.ref))) { - return undefined; - } + const branches = await Container.instance.git.getCommitBranches(commit.repoPath, commit.ref, { + branch: branch.name, + commitDate: GitCommit.is(commit) ? commit.committer.date : undefined, + }); + if (!branches.length) return undefined; return this.findNode((n: any) => n.commit?.ref === commit.ref, { allowPaging: true, diff --git a/src/views/remotesView.ts b/src/views/remotesView.ts index 5d7916d..c090121 100644 --- a/src/views/remotesView.ts +++ b/src/views/remotesView.ts @@ -231,7 +231,11 @@ export class RemotesView extends ViewBase { const repoNodeId = RepositoryNode.getId(commit.repoPath); // Get all the remote branches the commit is on - const branches = await this.container.git.getCommitBranches(commit.repoPath, commit.ref, { remotes: true }); + const branches = await this.container.git.getCommitBranches( + commit.repoPath, + commit.ref, + GitCommit.is(commit) ? { commitDate: commit.committer.date, remotes: true } : { remotes: true }, + ); if (branches.length === 0) return undefined; const remotes = branches.map(b => b.split('/', 1)[0]); diff --git a/src/views/repositoriesView.ts b/src/views/repositoriesView.ts index f7e4774..7f58e6c 100644 --- a/src/views/repositoriesView.ts +++ b/src/views/repositoriesView.ts @@ -330,7 +330,11 @@ export class RepositoriesView extends ViewBase n.commit !== undefined && n.commit.ref === commit.ref, { allowPaging: true, @@ -361,7 +365,11 @@ export class RepositoriesView extends ViewBase b.split('/', 1)[0]);