Browse Source

Reworks Azure DevOps remote parsing

Fixes vs-ssh domain issue
Adds better display path for ADO remotes
Adds full urls to remote tooltips
main
Eric Amodio 6 years ago
parent
commit
c4a83e7ebb
5 changed files with 55 additions and 24 deletions
  1. +5
    -3
      src/git/parsers/remoteParser.ts
  2. +33
    -17
      src/git/remotes/azure-devops.ts
  3. +4
    -1
      src/git/remotes/factory.ts
  4. +4
    -0
      src/git/remotes/provider.ts
  5. +9
    -3
      src/views/nodes/remoteNode.ts

+ 5
- 3
src/git/parsers/remoteParser.ts View File

@ -68,15 +68,17 @@ export class GitRemoteParser {
const uniqueness = `${domain}/${path}`;
let remote: GitRemote | undefined = groups[uniqueness];
if (remote === undefined) {
const provider = providerFactory(domain, path);
remote = new GitRemote(
repoPath,
uniqueness,
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
(' ' + match[1]).substr(1),
scheme,
domain,
path,
providerFactory(domain, path),
provider !== undefined ? provider.domain : domain,
provider !== undefined ? provider.path : path,
provider,
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
[{ url: url, type: (' ' + match[3]).substr(1) as GitRemoteType }]
);

+ 33
- 17
src/git/remotes/azure-devops.ts View File

@ -3,22 +3,36 @@ import { Range } from 'vscode';
import { RemoteProvider } from './provider';
const issueEnricherRegex = /(^|\s)(#([0-9]+))\b/gi;
const stripGitRegex = /\/_git\/?/i;
const sshDomainRegex = /^ssh\./i;
const gitRegex = /\/_git\/?/i;
const legacyDefaultCollectionRegex = /^DefaultCollection\//i;
const orgAndProjectRegex = /^(.*?)\/(.*?)\/(.*)/;
const sshDomainRegex = /^(ssh|vs-ssh)\./i;
const sshPathRegex = /^\/?v\d\//i;
export class AzureDevOpsRemote extends RemoteProvider {
constructor(domain: string, path: string, protocol?: string, name?: string) {
domain = domain.replace(sshDomainRegex, '');
path = path.replace(sshPathRegex, '').replace(stripGitRegex, '/');
constructor(domain: string, path: string, protocol?: string, name?: string, legacy: boolean = false) {
if (sshDomainRegex.test(domain)) {
path = path.replace(sshPathRegex, '');
domain = domain.replace(sshDomainRegex, '');
super(domain, path, protocol, name);
}
// Add in /_git/ into ssh urls
const match = orgAndProjectRegex.exec(path);
if (match != null) {
const [, org, project, rest] = match;
// Handle legacy vsts urls
if (legacy) {
domain = `${org}.${domain}`;
path = `${project}/_git/${rest}`;
}
else {
path = `${org}/${project}/_git/${rest}`;
}
}
}
get baseUrl() {
const [orgAndProject, repo] = this.splitPath();
return `https://${this.domain}/${orgAndProject}/_git/${repo}`;
super(domain, path, protocol, name);
}
get icon() {
@ -29,9 +43,17 @@ export class AzureDevOpsRemote extends RemoteProvider {
return 'Azure DevOps';
}
private _displayPath: string | undefined;
get displayPath(): string {
if (this._displayPath === undefined) {
this._displayPath = this.path.replace(gitRegex, '/').replace(legacyDefaultCollectionRegex, '');
}
return this._displayPath;
}
enrichMessage(message: string): string {
// Strip off any `_git` part from the repo url
const baseUrl = this.baseUrl.replace(stripGitRegex, '/');
const baseUrl = this.baseUrl.replace(gitRegex, '/');
// Matches #123
return message.replace(issueEnricherRegex, `$1[$2](${baseUrl}/_workitems/edit/$3 "Open Work Item $2")`);
}
@ -63,10 +85,4 @@ export class AzureDevOpsRemote extends RemoteProvider {
if (branch) return `${this.baseUrl}/?path=%2F${fileName}&version=GB${branch}&_a=contents${line}`;
return `${this.baseUrl}?path=%2F${fileName}${line}`;
}
protected splitPath(): [string, string] {
const index = this.path.lastIndexOf('/');
return [this.path.substring(0, index), this.path.substring(index + 1)];
}
}

+ 4
- 1
src/git/remotes/factory.ts View File

@ -19,7 +19,10 @@ const defaultProviders: RemoteProviders = [
[/\bdev\.azure\.com$/i, (domain: string, path: string) => new AzureDevOpsRemote(domain, path)],
[/\bbitbucket\b/i, (domain: string, path: string) => new BitbucketServerRemote(domain, path)],
[/\bgitlab\b/i, (domain: string, path: string) => new GitLabRemote(domain, path)],
[/\bvisualstudio\.com$/i, (domain: string, path: string) => new AzureDevOpsRemote(domain, path)]
[
/\bvisualstudio\.com$/i,
(domain: string, path: string) => new AzureDevOpsRemote(domain, path, undefined, undefined, true)
]
];
export class RemoteProviderFactory {

+ 4
- 0
src/git/remotes/provider.ts View File

@ -80,6 +80,10 @@ export abstract class RemoteProvider {
return 'remote';
}
get displayPath(): string {
return this.path;
}
abstract get name(): string;
protected get baseUrl() {

+ 9
- 3
src/views/nodes/remoteNode.ts View File

@ -90,7 +90,9 @@ export class RemoteNode extends ViewNode {
);
item.description = `${separator}${GlyphChars.Space} ${
this.remote.provider !== undefined ? this.remote.provider.name : this.remote.domain
} ${GlyphChars.Space}${GlyphChars.Dot}${GlyphChars.Space} ${this.remote.path}`;
} ${GlyphChars.Space}${GlyphChars.Dot}${GlyphChars.Space} ${
this.remote.provider !== undefined ? this.remote.provider.displayPath : this.remote.path
}`;
item.contextValue = ResourceType.Remote;
if (this.remote.default) {
item.contextValue += '+default';
@ -110,9 +112,13 @@ export class RemoteNode extends ViewNode {
}
item.id = this.id;
item.tooltip = `${this.remote.name}\n${this.remote.path} (${
item.tooltip = `${this.remote.name} (${
this.remote.provider !== undefined ? this.remote.provider.name : this.remote.domain
})`;
})\n${this.remote.provider !== undefined ? this.remote.provider.displayPath : this.remote.path}\n`;
for (const type of this.remote.types) {
item.tooltip += `\n${type.url} (${type.type})`;
}
return item;
}

Loading…
Cancel
Save