Skip to content

Commit

Permalink
feat: replace List Branches API with List matching references API (
Browse files Browse the repository at this point in the history
  • Loading branch information
conwnet authored Feb 22, 2021
1 parent 9ab8562 commit c4886ef
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 72 deletions.
36 changes: 16 additions & 20 deletions extensions/github1s/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,34 +101,30 @@ export const validateToken = (token: string) => {
});
};

export const getGithubBranches = (owner: string, repo: string) => {
// the [List Branches](https://docs.github.com/en/rest/reference/repos#list-branches) API
// only returned max to 100 branches for per request
// [List matching references](https://docs.github.com/en/rest/reference/git#list-matching-references)
// can returned all branches for a request, and there is an issue for this API
// https://github.com/github/docs/issues/3863
export const getGithubBranchRefs = (owner: string, repo: string) => {
return fetch(
`https://api.github.com/repos/${owner}/${repo}/branches?per_page=100`
`https://api.github.com/repos/${owner}/${repo}/git/matching-refs/heads`
)
.then((branches) => {
// TODO: only no more than 200 branches are supported
if (branches.length === 100) {
return fetch(
`https://api.github.com/repos/${owner}/${repo}/branches?per_page=100&page=2`
).then((otherBranches) => [...branches, ...otherBranches]);
}
return branches;
.then((branchRefs) => {
// the field in branchRef will looks like `refs/heads/<branch>`, we add a name field here
return branchRefs.map((item) => ({ ...item, name: item.ref.slice(11) }));
})
.catch(handleRequestError);
};

export const getGithubTags = (owner: string, repo: string) => {
// It's similar to `getGithubBranchRefs`
export const getGithubTagRefs = (owner: string, repo: string) => {
return fetch(
`https://api.github.com/repos/${owner}/${repo}/tags?per_page=100`
`https://api.github.com/repos/${owner}/${repo}/git/matching-refs/tags`
)
.then((tags) => {
// TODO: only no more than 200 tags are supported
if (tags.length === 100) {
return fetch(
`https://api.github.com/repos/${owner}/${repo}/tags?per_page=100&page=2`
).then((otherTags) => [...tags, ...otherTags]);
}
return tags;
.then((tagRefs) => {
// the field in tagRef will looks like `refs/tags/<tag>`, we add a name field here
return tagRefs.map((item) => ({ ...item, name: item.ref.slice(10) }));
})
.catch(handleRequestError);
};
Expand Down
8 changes: 4 additions & 4 deletions extensions/github1s/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import * as vscode from 'vscode';
import {
getExtensionContext,
getRepositoryBranches,
getRepositoryTags,
getRepositoryBranchRefs,
getRepositoryTagRefs,
getCurrentRef,
getCurrentAuthority,
changeCurrentRef,
Expand Down Expand Up @@ -115,7 +115,7 @@ export const commandGetCurrentAuthority = (): Promise<string> =>
getCurrentAuthority();

export const commandSwitchBranch = () => {
return Promise.all([getRepositoryBranches(), getCurrentRef()]).then(
return Promise.all([getRepositoryBranchRefs(), getCurrentRef()]).then(
([repositoryBranches, currentRef]) =>
vscode.window
.showQuickPick(
Expand All @@ -136,7 +136,7 @@ export const commandSwitchBranch = () => {
};

export const commandSwitchTag = () => {
return Promise.all([getRepositoryTags(), getCurrentRef()]).then(
return Promise.all([getRepositoryTagRefs(), getCurrentRef()]).then(
([repositoryBranches, currentRef]) =>
vscode.window
.showQuickPick(
Expand Down
80 changes: 34 additions & 46 deletions extensions/github1s/src/util/git-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,25 @@

import * as vscode from 'vscode';
import { reuseable } from './func';
import { getGithubBranches, getGithubTags } from '../api';
import { getGithubBranchRefs, getGithubTagRefs } from '../api';

export interface RepositoryBranch {
export interface RepositoryRef {
name: string;
commit: {
sha: string;
url: string;
};
protected?: boolean;
}

export interface RepositoryTag {
name: string;
commit: {
ref: string;
node_id: string;
url: string;
object: {
sha: string;
type: string;
url: string;
};
zipball_url: string;
tarball_url: string;
node_id: string;
}

let currentOwner = '';
let currentRepo = '';
let currentRef = '';
let repositoryBranches: RepositoryBranch[] = null;
let repositoryTags: RepositoryTag[] = null;
let repositoryBranchRefs: RepositoryRef[] = null;
let repositoryTagRefs: RepositoryRef[] = null;

// get current browser uri, update `currentOwner` and `currentRepo`
const getBrowserUri = (): Promise<vscode.Uri> => {
Expand All @@ -48,54 +40,48 @@ const getBrowserUri = (): Promise<vscode.Uri> => {
});
};

const getRepositoryBranchesFromUri = reuseable(
(
uri: vscode.Uri,
forceUpdate: boolean = false
): Promise<RepositoryBranch[]> => {
const getRepositoryBranchRefsFromUri = reuseable(
(uri: vscode.Uri, forceUpdate: boolean = false): Promise<RepositoryRef[]> => {
// use the cached branches if already fetched and not forceUpdate
if (repositoryBranches && repositoryBranches.length && !forceUpdate) {
return Promise.resolve(repositoryBranches);
if (repositoryBranchRefs && repositoryBranchRefs.length && !forceUpdate) {
return Promise.resolve(repositoryBranchRefs);
}
const [owner = 'conwnet', repo = 'github1s'] = uri.path
.split('/')
.filter(Boolean);
return getGithubBranches(owner, repo).then(
(githubBranches) => (repositoryBranches = githubBranches)
return getGithubBranchRefs(owner, repo).then(
(branchRefs: RepositoryRef[]) => (repositoryBranchRefs = branchRefs)
);
}
);

export const getRepositoryBranches = reuseable(
(forceUpdate: boolean = false): Promise<RepositoryBranch[]> => {
export const getRepositoryBranchRefs = reuseable(
(forceUpdate: boolean = false): Promise<RepositoryRef[]> => {
return getBrowserUri().then((uri) =>
getRepositoryBranchesFromUri(uri, forceUpdate)
getRepositoryBranchRefsFromUri(uri, forceUpdate)
);
}
);

const getRepositoryTagsFromUri = reuseable(
(
uri: vscode.Uri,
forceUpdate: boolean = false
): Promise<RepositoryBranch[]> => {
const getRepositoryTagRefsFromUri = reuseable(
(uri: vscode.Uri, forceUpdate: boolean = false): Promise<RepositoryRef[]> => {
// use the cached tags if already fetched and not forceUpdate
if (repositoryTags && repositoryTags.length && !forceUpdate) {
return Promise.resolve(repositoryTags);
if (repositoryTagRefs && repositoryTagRefs.length && !forceUpdate) {
return Promise.resolve(repositoryTagRefs);
}
const [owner = 'conwnet', repo = 'github1s'] = uri.path
.split('/')
.filter(Boolean);
return getGithubTags(owner, repo).then(
(githubTags) => (repositoryTags = githubTags)
return getGithubTagRefs(owner, repo).then(
(tagRefs: RepositoryRef[]) => (repositoryTagRefs = tagRefs)
);
}
);

export const getRepositoryTags = reuseable(
(forceUpdate: boolean = false): Promise<RepositoryBranch[]> => {
export const getRepositoryTagRefs = reuseable(
(forceUpdate: boolean = false): Promise<RepositoryRef[]> => {
return getBrowserUri().then((uri) =>
getRepositoryTagsFromUri(uri, forceUpdate)
getRepositoryTagRefsFromUri(uri, forceUpdate)
);
}
);
Expand Down Expand Up @@ -136,12 +122,14 @@ const getCurrentRefFromUri = reuseable(
return Promise.resolve('HEAD');
}

const branchNamesPromise: Promise<string[]> = getRepositoryBranchesFromUri(
uri
).then((branches) => branches.map((item) => item.name));
const tagNamesPromise: Promise<string[]> = getRepositoryTagsFromUri(
const branchNamesPromise: Promise<
string[]
> = getRepositoryBranchRefsFromUri(uri).then((branchRefs) =>
branchRefs.map((item) => item.name)
);
const tagNamesPromise: Promise<string[]> = getRepositoryTagRefsFromUri(
uri
).then((tags) => tags.map((item) => item.name));
).then((tagRefs) => tagRefs.map((item) => item.name));

return branchNamesPromise.then((branchNames: string[]) => {
// try to find current ref from repo branches, we needn't wait to tags request ready if can find it here
Expand Down
4 changes: 2 additions & 2 deletions extensions/github1s/src/util/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export {
export {
getCurrentRef,
getCurrentAuthority,
getRepositoryBranches,
getRepositoryTags,
getRepositoryBranchRefs,
getRepositoryTagRefs,
changeCurrentRef,
} from './git-ref';
export { parseGitmodules, parseSubmoduleUrl } from './submodule';
Expand Down

1 comment on commit c4886ef

@vercel
Copy link

@vercel vercel bot commented on c4886ef Feb 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.