Skip to content

Commit 0700c9e

Browse files
committed
git: contributable add remote
1 parent b514c4a commit 0700c9e

2 files changed

Lines changed: 63 additions & 27 deletions

File tree

extensions/git/package.nls.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"command.pushToForce": "Push to... (Force)",
5656
"command.pushFollowTags": "Push (Follow Tags)",
5757
"command.pushFollowTagsForce": "Push (Follow Tags, Force)",
58-
"command.addRemote": "Add Remote",
58+
"command.addRemote": "Add Remote...",
5959
"command.removeRemote": "Remove Remote",
6060
"command.sync": "Sync",
6161
"command.syncRebase": "Sync (Rebase)",

extensions/git/src/commands.ts

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,11 @@ function createCheckoutItems(repository: Repository): CheckoutItem[] {
217217
return [...heads, ...tags, ...remoteHeads];
218218
}
219219

220+
function sanitizeRemoteName(name: string) {
221+
name = name.trim();
222+
return name && name.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, '-');
223+
}
224+
220225
class TagItem implements QuickPickItem {
221226
get label(): string { return this.ref.name ?? ''; }
222227
get description(): string { return this.ref.commit?.substr(0, 8) ?? ''; }
@@ -529,7 +534,7 @@ export class CommandCenter {
529534
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('clonefrom', "Clone from {0}", provider.name), alwaysShow: true, provider }));
530535

531536
quickpick.placeholder = providers.length === 0
532-
? localize('provide url', "Provide repository URL.")
537+
? localize('provide url', "Provide repository URL")
533538
: localize('provide url or pick', "Provide repository URL or pick a repository source.");
534539

535540
const updatePicks = (value?: string) => {
@@ -2119,48 +2124,79 @@ export class CommandCenter {
21192124

21202125
@command('git.addRemote', { repository: true })
21212126
async addRemote(repository: Repository): Promise<string | undefined> {
2122-
const remotes = repository.remotes;
2123-
2124-
const sanitize = (name: string) => {
2125-
name = name.trim();
2126-
return name && name.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$|\[|\]$/g, '-');
2127+
const quickpick = window.createQuickPick<(QuickPickItem & { provider?: RemoteSourceProvider, url?: string })>();
2128+
quickpick.ignoreFocusOut = true;
2129+
2130+
const providers = this.model.getRemoteProviders()
2131+
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('addfrom', "Add remote from {0}", provider.name), alwaysShow: true, provider }));
2132+
2133+
quickpick.placeholder = providers.length === 0
2134+
? localize('provide url', "Provide repository URL")
2135+
: localize('provide url or pick', "Provide repository URL or pick a repository source.");
2136+
2137+
const updatePicks = (value?: string) => {
2138+
if (value) {
2139+
quickpick.items = [{
2140+
label: localize('addFrom', "Add remote from URL"),
2141+
description: value,
2142+
alwaysShow: true,
2143+
url: value
2144+
},
2145+
...providers];
2146+
} else {
2147+
quickpick.items = providers;
2148+
}
21272149
};
21282150

2151+
quickpick.onDidChangeValue(updatePicks);
2152+
updatePicks();
2153+
2154+
const result = await getQuickPickResult(quickpick);
2155+
let url: string | undefined;
2156+
2157+
if (result) {
2158+
if (result.url) {
2159+
url = result.url;
2160+
} else if (result.provider) {
2161+
const quickpick = new RemoteSourceProviderQuickPick(result.provider);
2162+
const remote = await quickpick.pick();
2163+
2164+
if (remote) {
2165+
if (typeof remote.url === 'string') {
2166+
url = remote.url;
2167+
} else if (remote.url.length > 0) {
2168+
url = await window.showQuickPick(remote.url, { ignoreFocusOut: true, placeHolder: localize('pick url', "Choose a URL to clone from.") });
2169+
}
2170+
}
2171+
}
2172+
}
2173+
2174+
if (!url) {
2175+
return;
2176+
}
2177+
21292178
const resultName = await window.showInputBox({
21302179
placeHolder: localize('remote name', "Remote name"),
21312180
prompt: localize('provide remote name', "Please provide a remote name"),
21322181
ignoreFocusOut: true,
21332182
validateInput: (name: string) => {
2134-
if (sanitize(name)) {
2135-
return null;
2183+
if (!sanitizeRemoteName(name)) {
2184+
return localize('remote name format invalid', "Remote name format invalid");
2185+
} else if (repository.remotes.find(r => r.name === name)) {
2186+
return localize('remote already exists', "Remote '{0}' already exists.", name);
21362187
}
2137-
return localize('remote name format invalid', "Remote name format invalid");
2188+
2189+
return null;
21382190
}
21392191
});
21402192

2141-
const name = sanitize(resultName || '');
2193+
const name = sanitizeRemoteName(resultName || '');
21422194

21432195
if (!name) {
21442196
return;
21452197
}
21462198

2147-
if (remotes.find(r => r.name === name)) {
2148-
window.showErrorMessage(localize('remote already exists', "Remote '{0}' already exists.", name));
2149-
return;
2150-
}
2151-
2152-
const url = await window.showInputBox({
2153-
placeHolder: localize('remote url', "Remote URL"),
2154-
prompt: localize('provide remote URL', "Enter URL for remote \"{0}\"", name),
2155-
ignoreFocusOut: true
2156-
});
2157-
2158-
if (!url) {
2159-
return;
2160-
}
2161-
21622199
await repository.addRemote(name, url);
2163-
21642200
return name;
21652201
}
21662202

0 commit comments

Comments
 (0)