From 517e9f0d5a00f9e94d149119b106c6f93eeb87b5 Mon Sep 17 00:00:00 2001 From: Felipe Santos Date: Thu, 7 Apr 2022 12:54:22 -0300 Subject: [PATCH] Adds support for vanilla Gerrit And separates the existing Gerrit provider to a new GoogleSource one. Closes #1953 --- README.md | 16 ++++++------ package.json | 1 + patches/tr46.js | 4 ++- src/config.ts | 1 + src/env/node/git/localGitProvider.ts | 3 ++- src/git/remotes/factory.ts | 11 +++++++- src/git/remotes/gerrit.ts | 30 +++++++++++++++++----- src/git/remotes/google-source.ts | 28 ++++++++++++++++++++ .../8-hosting-service-integrations.md | 2 +- 9 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 src/git/remotes/google-source.ts diff --git a/README.md b/README.md index 311d6bf..a62370d 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Here are just some of the **features** that GitLens provides, - [status](#quick-status-access- 'Jump to Quick Status Access') — current branch and working tree status - a user-friendly [**interactive rebase editor**](#interactive-rebase-editor- 'Jump to the Interactive Rebase Editor') to easily configure an interactive rebase session - [**terminal links**](#terminal-links- 'Jump to Terminal Links') — `ctrl+click` on autolinks in the integrated terminal to quickly jump to more details for commits, branches, tags, and more -- rich [**remote provider integrations**](#remote-provider-integrations- 'Jump to Remote Provider Integrations') — GitHub, GitLab, Gitea, Gerrit, Bitbucket, Azure DevOps +- rich [**remote provider integrations**](#remote-provider-integrations- 'Jump to Remote Provider Integrations') — GitHub, GitLab, Gitea, Gerrit, GoogleSource, Bitbucket, Azure DevOps - issue and pull request auto-linking - rich hover information provided for linked issues and pull requests (GitHub only) - associates pull requests with branches and commits (GitHub only) @@ -186,7 +186,7 @@ Worktrees allow you to easily work on different branches of a repository simulta

- Adds a **details hover** annotation to the current line to show more commit details ([optional](#hover-settings- 'Jump to the Hover settings'), on by default) - - Provides **automatic issue linking** to Bitbucket, Gerrit, Gitea, GitHub, GitLab, and Azure DevOps in commit messages + - Provides **automatic issue linking** to Bitbucket, Gerrit, GoogleSource, Gitea, GitHub, GitLab, and Azure DevOps in commit messages - Provides a **quick-access command bar** with _Open Changes_, _Blame Previous Revision_, _Open on Remote_, _Invite to Live Share_ (if available), and _Show More Actions_ command buttons - Click the commit SHA to execute the _Show Commit_ command @@ -215,7 +215,7 @@ Worktrees allow you to easily work on different branches of a repository simulta

- Adds a **details hover** annotation to each line while annotating to show more commit details ([optional](#hover-settings- 'Jump to the Hover settings'), on by default) - - Provides **automatic issue linking** to Bitbucket, Gerrit, Gitea, GitHub, GitLab, and Azure DevOps in commit messages + - Provides **automatic issue linking** to Bitbucket, Gerrit, GoogleSource, Gitea, GitHub, GitLab, and Azure DevOps in commit messages - Provides a **quick-access command bar** with _Open Changes_, _Blame Previous Revision_, _Open on Remote_, _Invite to Live Share_ (if available), and _Show More Actions_ command buttons - Click the commit SHA to execute the _Show Commit_ command @@ -614,7 +614,7 @@ The _Search & Compare_ view lists pinnable (saved) results for searching commit ## Remote Provider Integrations [#](#remote-provider-integrations- 'Remote Provider Integrations') -GitLens provides rich integrations with many remote providers, including GitHub, GitHub Enterprise, GitLab, Gitea, Gerrit, Bitbucket, Bitbucket Server, and Azure DevOps. You can also define [custom remote providers](#remote-provider-integration-settings- 'Jump to the Remote Provider Integration settings') or [remote providers with custom domains](#remote-provider-integration-settings- 'Jump to the Remote Provider Integration settings') as well. +GitLens provides rich integrations with many remote providers, including GitHub, GitHub Enterprise, GitLab, Gitea, Gerrit, GoogleSource, Bitbucket, Bitbucket Server, and Azure DevOps. You can also define [custom remote providers](#remote-provider-integration-settings- 'Jump to the Remote Provider Integration settings') or [remote providers with custom domains](#remote-provider-integration-settings- 'Jump to the Remote Provider Integration settings') as well. Basic integrations provide issue and pull request auto-linking, while richer integrations (e.g. GitHub) can provide rich hover information provided for auto-linked issues and pull requests, associate pull requests with branches and commits, and provide avatars. @@ -996,10 +996,10 @@ See also [View Settings](#view-settings- 'Jump to the View settings') ## Remote Provider Integration Settings [#](#remote-provider-integration-settings- 'Remote Provider Integration Settings') -| Name | Description | -| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `gitlens.integrations.enabled` | Specifies whether to enable rich integrations with any supported remote services | -| `gitlens.remotes` | Specifies custom remote services to be matched with Git remotes to detect custom domains for built-in remote services or provide support for custom remote services

Supported Types (e.g. `"type": "GitHub"`):Example:
`"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "GitHub" }]`

Example:
`"gitlens.remotes": [{ "regex": "ssh:\/\/(my\.company\.com):1234\/git\/(.+)", "type": "GitHub" }]`

Example:
`"gitlens.remotes": [{`
    `"domain": "git.corporate-url.com",`
    `"type": "Custom",`
    `"name": "My Company",`
    `"protocol": "https",`
    `"urls": {`
        `"repository": "https://git.corporate-url.com/${repo}",`
        `"branches": "https://git.corporate-url.com/${repo}/branches",`
        `"branch": "https://git.corporate-url.com/${repo}/commits/${branch}",`
        `"commit": "https://git.corporate-url.com/${repo}/commit/${id}",`
        `"file": "https://git.corporate-url.com/${repo}?path=${file}${line}",`
        `"fileInBranch": "https://git.corporate-url.com/${repo}/blob/${branch}/${file}${line}",`
        `"fileInCommit": "https://git.corporate-url.com/${repo}/blob/${id}/${file}${line}",`
        `"fileLine": "#L${line}",`
        `"fileRange": "#L${start}-L${end}"`
        `}`
    `}]`

Example:
`"gitlens.remotes": [{`
    `"regex": "ssh:\\/\\/(my\\.company\\.com):1234\\/git\\/(.+)",`
    `"type": "Custom",`
    `"name": "My Company",`
    `"protocol": "https",`
    `"urls": {`
        `"repository": "https://my.company.com/projects/${repoBase}/repos/${repoPath}",`
        `"branches": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/branches",`
        `"branch": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/commits/${branch}",`
        `"commit": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/commit/${id}",`
        `"file": "https://my.company.com/projects/${repoBase}/repos/${repoPath}?path=${file}${line}",`
        `"fileInBranch": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/blob/${branch}/${file}${line}",`
        `"fileInCommit": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/blob/${id}/${file}${line}",`
        `"fileLine": "#L${line}",`
        `"fileRange": "#L${start}-L${end}"`
        `}`
    `}]` | +| Name | Description | +| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `gitlens.integrations.enabled` | Specifies whether to enable rich integrations with any supported remote services | +| `gitlens.remotes` | Specifies custom remote services to be matched with Git remotes to detect custom domains for built-in remote services or provide support for custom remote services

Supported Types (e.g. `"type": "GitHub"`):Example:
`"gitlens.remotes": [{ "domain": "git.corporate-url.com", "type": "GitHub" }]`

Example:
`"gitlens.remotes": [{ "regex": "ssh:\/\/(my\.company\.com):1234\/git\/(.+)", "type": "GitHub" }]`

Example:
`"gitlens.remotes": [{`
    `"domain": "git.corporate-url.com",`
    `"type": "Custom",`
    `"name": "My Company",`
    `"protocol": "https",`
    `"urls": {`
        `"repository": "https://git.corporate-url.com/${repo}",`
        `"branches": "https://git.corporate-url.com/${repo}/branches",`
        `"branch": "https://git.corporate-url.com/${repo}/commits/${branch}",`
        `"commit": "https://git.corporate-url.com/${repo}/commit/${id}",`
        `"file": "https://git.corporate-url.com/${repo}?path=${file}${line}",`
        `"fileInBranch": "https://git.corporate-url.com/${repo}/blob/${branch}/${file}${line}",`
        `"fileInCommit": "https://git.corporate-url.com/${repo}/blob/${id}/${file}${line}",`
        `"fileLine": "#L${line}",`
        `"fileRange": "#L${start}-L${end}"`
        `}`
    `}]`

Example:
`"gitlens.remotes": [{`
    `"regex": "ssh:\\/\\/(my\\.company\\.com):1234\\/git\\/(.+)",`
    `"type": "Custom",`
    `"name": "My Company",`
    `"protocol": "https",`
    `"urls": {`
        `"repository": "https://my.company.com/projects/${repoBase}/repos/${repoPath}",`
        `"branches": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/branches",`
        `"branch": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/commits/${branch}",`
        `"commit": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/commit/${id}",`
        `"file": "https://my.company.com/projects/${repoBase}/repos/${repoPath}?path=${file}${line}",`
        `"fileInBranch": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/blob/${branch}/${file}${line}",`
        `"fileInCommit": "https://my.company.com/projects/${repoBase}/repos/${repoPath}/blob/${id}/${file}${line}",`
        `"fileLine": "#L${line}",`
        `"fileRange": "#L${start}-L${end}"`
        `}`
    `}]` | ## Date & Time Settings [#](#date--time-settings- 'Date & Time Settings') diff --git a/package.json b/package.json index e3111ee..5d3a470 100644 --- a/package.json +++ b/package.json @@ -2267,6 +2267,7 @@ "Bitbucket", "BitbucketServer", "Gerrit", + "GoogleSource", "Gitea", "GitHub", "GitLab" diff --git a/patches/tr46.js b/patches/tr46.js index f3efff4..4f4f639 100644 --- a/patches/tr46.js +++ b/patches/tr46.js @@ -1,2 +1,4 @@ -function toASCII(d) { return d; } +function toASCII(d) { + return d; +} module.exports = { toASCII }; diff --git a/src/config.ts b/src/config.ts index cc60506..e1d80ea 100644 --- a/src/config.ts +++ b/src/config.ts @@ -234,6 +234,7 @@ export const enum CustomRemoteType { BitbucketServer = 'BitbucketServer', Custom = 'Custom', Gerrit = 'Gerrit', + GoogleSource = 'GoogleSource', Gitea = 'Gitea', GitHub = 'GitHub', GitLab = 'GitLab', diff --git a/src/env/node/git/localGitProvider.ts b/src/env/node/git/localGitProvider.ts index bbe4089..9515646 100644 --- a/src/env/node/git/localGitProvider.ts +++ b/src/env/node/git/localGitProvider.ts @@ -450,7 +450,8 @@ export class LocalGitProvider implements GitProvider, Disposable { case 'bitbucket': case 'azure-devops': case 'gitea': - case 'gerrit': { + case 'gerrit': + case 'google-source': { const url = remote.provider.url({ type: RemoteResourceType.Repo }); if (url == null) return RepositoryVisibility.Private; diff --git a/src/git/remotes/factory.ts b/src/git/remotes/factory.ts index 5dd16f8..b3e2368 100644 --- a/src/git/remotes/factory.ts +++ b/src/git/remotes/factory.ts @@ -8,6 +8,7 @@ import { GerritRemote } from './gerrit'; import { GiteaRemote } from './gitea'; import { GitHubRemote } from './github'; import { GitLabRemote } from './gitlab'; +import { GoogleSourceRemote } from './google-source'; import { RemoteProvider } from './provider'; // export { RemoteProvider, RichRemoteProvider }; @@ -60,9 +61,14 @@ const builtInProviders: RemoteProviders = [ }, { custom: false, - matcher: /\bgooglesource\.com$/i, + matcher: /\bgerrithub\.io$/i, creator: (domain: string, path: string) => new GerritRemote(domain, path), }, + { + custom: false, + matcher: /\bgooglesource\.com$/i, + creator: (domain: string, path: string) => new GoogleSourceRemote(domain, path), + }, ]; export class RemoteProviderFactory { @@ -143,6 +149,9 @@ export class RemoteProviderFactory { new CustomRemote(domain, path, cfg.urls!, cfg.protocol, cfg.name); case CustomRemoteType.Gerrit: return (domain: string, path: string) => new GerritRemote(domain, path, cfg.protocol, cfg.name, true); + case CustomRemoteType.GoogleSource: + return (domain: string, path: string) => + new GoogleSourceRemote(domain, path, cfg.protocol, cfg.name, true); case CustomRemoteType.Gitea: return (domain: string, path: string) => new GiteaRemote(domain, path, cfg.protocol, cfg.name, true); case CustomRemoteType.GitHub: diff --git a/src/git/remotes/gerrit.ts b/src/git/remotes/gerrit.ts index cc32612..f1a101e 100644 --- a/src/git/remotes/gerrit.ts +++ b/src/git/remotes/gerrit.ts @@ -9,7 +9,26 @@ const fileRegex = /^\/([^/]+)\/\+(.+)$/i; const rangeRegex = /^(\d+)$/; export class GerritRemote extends RemoteProvider { - constructor(domain: string, path: string, protocol?: string, name?: string, custom: boolean = false) { + constructor( + domain: string, + path: string, + protocol?: string, + name?: string, + custom: boolean = false, + trimPath: boolean = true, + ) { + /* + * Git remote URLs differs when cloned by HTTPS with or without authentication. + * An anonymous clone looks like: + * $ git clone "https://review.gerrithub.io/jenkinsci/gerrit-code-review-plugin" + * An authenticated clone looks like: + * $ git clone "https://felipecrs@review.gerrithub.io/a/jenkinsci/gerrit-code-review-plugin" + * Where username may be omitted, but the "a/" prefix is always present. + */ + if (trimPath && protocol !== 'ssh') { + path = path.replace(/^a\//, ''); + } + super(domain, path, protocol, name, custom); } @@ -40,13 +59,12 @@ export class GerritRemote extends RemoteProvider { return this.formatName('Gerrit'); } - private get reviewDomain(): string { - const [subdomain, secondLevelDomain, topLevelDomain] = this.domain.split('.'); - return [`${subdomain}-review`, secondLevelDomain, topLevelDomain].join('.'); + protected override get baseUrl(): string { + return `${this.protocol}://${this.domain}/plugins/gitiles/${this.path}`; } - private get baseReviewUrl(): string { - return `${this.protocol}://${this.reviewDomain}`; + protected get baseReviewUrl(): string { + return `${this.protocol}://${this.domain}`; } async getLocalInfoFromRemoteUri( diff --git a/src/git/remotes/google-source.ts b/src/git/remotes/google-source.ts new file mode 100644 index 0000000..06dc763 --- /dev/null +++ b/src/git/remotes/google-source.ts @@ -0,0 +1,28 @@ +import { GerritRemote } from './gerrit'; + +export class GoogleSourceRemote extends GerritRemote { + constructor(domain: string, path: string, protocol?: string, name?: string, custom: boolean = false) { + super(domain, path, protocol, name, custom, false); + } + + override get id() { + return 'google-source'; + } + + override get name() { + return this.formatName('Google Source'); + } + + protected override get baseUrl(): string { + return `${this.protocol}://${this.domain}/${this.path}`; + } + + private get reviewDomain(): string { + const [subdomain, secondLevelDomain, topLevelDomain] = this.domain.split('.'); + return [`${subdomain}-review`, secondLevelDomain, topLevelDomain].join('.'); + } + + protected override get baseReviewUrl(): string { + return `${this.protocol}://${this.reviewDomain}`; + } +} diff --git a/walkthroughs/getting-started/8-hosting-service-integrations.md b/walkthroughs/getting-started/8-hosting-service-integrations.md index c53211b..617db1d 100644 --- a/walkthroughs/getting-started/8-hosting-service-integrations.md +++ b/walkthroughs/getting-started/8-hosting-service-integrations.md @@ -4,6 +4,6 @@ Hosting service integrations

-GitLens provides rich integrations with many remote providers, including GitHub, GitHub Enterprise, GitLab, Gitea, Gerrit, Bitbucket, Bitbucket Server, Azure DevOps and custom servers. +GitLens provides rich integrations with many remote providers, including GitHub, GitHub Enterprise, GitLab, Gitea, Gerrit, Google Source, Bitbucket, Bitbucket Server, Azure DevOps and custom servers. All Git host integrations provide issue and pull request auto-linking, while advanced integrations (e.g. GitHub) provide more detailed hover information, plus the ability to associate pull requests with branches/commits, and avatars.