mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-21 02:24:09 -07:00
add extension IDs (#11377)
This commit is contained in:
@@ -76,24 +76,30 @@ export async function cloneFromGit(
|
||||
}
|
||||
}
|
||||
|
||||
export function parseGitHubRepoForReleases(source: string): {
|
||||
export interface GithubRepoInfo {
|
||||
owner: string;
|
||||
repo: string;
|
||||
} | null {
|
||||
}
|
||||
|
||||
export function tryParseGithubUrl(source: string): GithubRepoInfo | null {
|
||||
// First step in normalizing a github ssh URI to the https form.
|
||||
if (source.startsWith('git@github.com:')) {
|
||||
source = source.replace('git@github.com:', '');
|
||||
}
|
||||
// Default to a github repo path, so `source` can be just an org/repo
|
||||
const parsedUrl = URL.parse(source, 'https://github.com');
|
||||
if (!parsedUrl) {
|
||||
throw new Error(`Invalid repo URL: ${source}`);
|
||||
}
|
||||
// The pathname should be "/owner/repo".
|
||||
const parts = parsedUrl?.pathname
|
||||
.substring(1)
|
||||
.split('/')
|
||||
// Remove the empty segments, fixes trailing slashes
|
||||
.filter((part) => part !== '');
|
||||
if (parsedUrl?.host !== 'github.com') {
|
||||
return null;
|
||||
}
|
||||
// The pathname should be "/owner/repo".
|
||||
const parts = parsedUrl?.pathname
|
||||
.split('/')
|
||||
// Remove the empty segments, fixes trailing and leading slashes
|
||||
.filter((part) => part !== '');
|
||||
|
||||
if (parts?.length !== 2) {
|
||||
throw new Error(
|
||||
`Invalid GitHub repository source: ${source}. Expected "owner/repo" or a github repo uri.`,
|
||||
@@ -102,13 +108,10 @@ export function parseGitHubRepoForReleases(source: string): {
|
||||
const owner = parts[0];
|
||||
const repo = parts[1].replace('.git', '');
|
||||
|
||||
if (owner.startsWith('git@github.com')) {
|
||||
throw new Error(
|
||||
`GitHub release-based extensions are not supported for SSH. You must use an HTTPS URI with a personal access token to download releases from private repositories. You can set your personal access token in the GITHUB_TOKEN environment variable and install the extension via SSH.`,
|
||||
);
|
||||
}
|
||||
|
||||
return { owner, repo };
|
||||
return {
|
||||
owner,
|
||||
repo,
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchReleaseFromGithub(
|
||||
@@ -217,7 +220,7 @@ export async function checkForExtensionUpdate(
|
||||
console.error(`No "source" provided for extension.`);
|
||||
return ExtensionUpdateState.ERROR;
|
||||
}
|
||||
const repoInfo = parseGitHubRepoForReleases(source);
|
||||
const repoInfo = tryParseGithubUrl(source);
|
||||
if (!repoInfo) {
|
||||
console.error(
|
||||
`Source is not a valid GitHub repository for release checks: ${source}`,
|
||||
@@ -248,39 +251,35 @@ export async function checkForExtensionUpdate(
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitHubDownloadResult {
|
||||
tagName?: string;
|
||||
type: 'git' | 'github-release';
|
||||
success: boolean;
|
||||
failureReason?:
|
||||
| 'failed to fetch release data'
|
||||
| 'no release data'
|
||||
| 'no release asset found'
|
||||
| 'failed to download asset'
|
||||
| 'failed to extract asset'
|
||||
| 'unknown';
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
export type GitHubDownloadResult =
|
||||
| {
|
||||
tagName?: string;
|
||||
type: 'git' | 'github-release';
|
||||
success: false;
|
||||
failureReason:
|
||||
| 'failed to fetch release data'
|
||||
| 'no release data'
|
||||
| 'no release asset found'
|
||||
| 'failed to download asset'
|
||||
| 'failed to extract asset'
|
||||
| 'unknown';
|
||||
errorMessage: string;
|
||||
}
|
||||
| {
|
||||
tagName?: string;
|
||||
type: 'git' | 'github-release';
|
||||
success: true;
|
||||
};
|
||||
export async function downloadFromGitHubRelease(
|
||||
installMetadata: ExtensionInstallMetadata,
|
||||
destination: string,
|
||||
githubRepoInfo: GithubRepoInfo,
|
||||
): Promise<GitHubDownloadResult> {
|
||||
const { source, ref, allowPreRelease: preRelease } = installMetadata;
|
||||
const { ref, allowPreRelease: preRelease } = installMetadata;
|
||||
const { owner, repo } = githubRepoInfo;
|
||||
let releaseData: GithubReleaseData | null = null;
|
||||
|
||||
try {
|
||||
const parts = parseGitHubRepoForReleases(source);
|
||||
if (!parts) {
|
||||
return {
|
||||
failureReason: 'no release data',
|
||||
success: false,
|
||||
type: 'github-release',
|
||||
errorMessage: `Not a github repo: ${source}`,
|
||||
};
|
||||
}
|
||||
const { owner, repo } = parts;
|
||||
|
||||
try {
|
||||
releaseData = await fetchReleaseFromGithub(owner, repo, ref, preRelease);
|
||||
if (!releaseData) {
|
||||
|
||||
Reference in New Issue
Block a user