Browse Source

Implements getting commit on branches for GitHub

Consolidates into a single method call
main
Eric Amodio 2 years ago
parent
commit
7947a0551e
11 changed files with 220 additions and 42 deletions
  1. +1
    -1
      .vscode/queries.github-graphql-nb
  2. +9
    -4
      src/commands/quickCommand.steps.ts
  3. +11
    -8
      src/env/node/git/localGitProvider.ts
  4. +7
    -2
      src/git/gitProvider.ts
  5. +10
    -16
      src/git/gitProviderService.ts
  6. +133
    -0
      src/premium/github/github.ts
  7. +24
    -4
      src/premium/github/githubGitProvider.ts
  8. +5
    -1
      src/views/branchesView.ts
  9. +5
    -3
      src/views/commitsView.ts
  10. +5
    -1
      src/views/remotesView.ts
  11. +10
    -2
      src/views/repositoriesView.ts

+ 1
- 1
.vscode/queries.github-graphql-nb
File diff suppressed because it is too large
View File


+ 9
- 4
src/commands/quickCommand.steps.ts View File

@ -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',

+ 11
- 8
src/env/node/git/localGitProvider.ts View File

@ -709,13 +709,6 @@ export class LocalGitProvider implements GitProvider, Disposable {
}
@log()
async branchContainsCommit(repoPath: string, name: string, ref: string): Promise<boolean> {
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<string[]> {
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 [];

+ 7
- 2
src/git/gitProvider.ts View File

@ -105,7 +105,6 @@ export interface GitProvider extends Disposable {
addRemote(repoPath: string, name: string, url: string): Promise<void>;
pruneRemote(repoPath: string, remoteName: string): Promise<void>;
applyChangesToWorkingFile(uri: GitUri, ref1?: string, ref2?: string): Promise<void>;
branchContainsCommit(repoPath: string, name: string, ref: string): Promise<boolean>;
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<string[]>;
getCommitCount(repoPath: string, ref: string): Promise<number | undefined>;
getCommitForFile(

+ 10
- 16
src/git/gitProviderService.ts View File

@ -712,12 +712,6 @@ export class GitProviderService implements Disposable {
}
@log()
async branchContainsCommit(repoPath: string | Uri, name: string, ref: string): Promise<boolean> {
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<GitProviderService['getAheadBehindCommitCount']>({ 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<string[]> {
const { provider, path } = this.getProvider(repoPath);
return provider.getCommitBranches(path, ref, options);
}
@log<GitProviderService['getAheadBehindCommitCount']>({ 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<number | undefined> {
const { provider, path } = this.getProvider(repoPath);

+ 133
- 0
src/premium/github/github.ts View File

@ -698,6 +698,139 @@ export class GitHubApi {
return { ...(commit ?? results.values[0]), viewer: results.viewer };
}
@debug<GitHubApi['getCommitBranches']>({ args: { 0: '<token>' } })
async getCommitBranches(
token: string,
owner: string,
repo: string,
ref: string,
date: Date,
branch?: string,
): Promise<string[]> {
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<QueryResult>(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<string[]>(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<QueryResult>(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<string[]>(ex, cc, []);
}
}
@debug<GitHubApi['getCommits']>({ args: { 0: '<token>' } })
async getCommits(
token: string,

+ 24
- 4
src/premium/github/githubGitProvider.ts View File

@ -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<string[]> {
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()

+ 5
- 1
src/views/branchesView.ts View File

@ -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, {

+ 5
- 3
src/views/commitsView.ts View File

@ -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,

+ 5
- 1
src/views/remotesView.ts View File

@ -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]);

+ 10
- 2
src/views/repositoriesView.ts View File

@ -330,7 +330,11 @@ export class RepositoriesView extends ViewBase
const repoNodeId = RepositoryNode.getId(commit.repoPath);
// Get all the branches the commit is on
let branches = await this.container.git.getCommitBranches(commit.repoPath, commit.ref);
let branches = await this.container.git.getCommitBranches(
commit.repoPath,
commit.ref,
GitCommit.is(commit) ? { commitDate: commit.committer.date } : undefined,
);
if (branches.length !== 0) {
return this.findNode((n: any) => n.commit !== undefined && n.commit.ref === commit.ref, {
allowPaging: true,
@ -361,7 +365,11 @@ export class RepositoriesView extends ViewBase
}
// If we didn't find the commit on any local branches, check remote branches
branches = await this.container.git.getCommitBranches(commit.repoPath, commit.ref, { remotes: true });
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]);

Loading…
Cancel
Save