diff --git a/.gitignore-revs b/.git-blame-ignore-revs similarity index 100% rename from .gitignore-revs rename to .git-blame-ignore-revs diff --git a/.vscode/settings.json b/.vscode/settings.json index b292f7d..5afced1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -38,7 +38,6 @@ "query": "state:open repo:${owner}/${repository} sort:updated-desc" } ], - "gitlens.advanced.blame.customArguments": ["--ignore-revs-file", ".gitignore-revs"], "[html][javascript][json][jsonc][markdown][scss][svg][typescript][typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index a8b7adb..e5f3c47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - Adds an experimental _Generate Commit Message (Experimental)_ command to use OpenAI to generate a commit message for staged changes — currently only available in the pre-release edition - Adds a _Open Git Worktree..._ command to jump directly to opening a worktree in the _Git Command Palette_ +- Adds auto-detection for `.git-blame-ignore-revs` files and excludes the commits listed within from the blame annotations ### Fixed diff --git a/src/env/node/git/git.ts b/src/env/node/git/git.ts index 56bb689..1a2a91b 100644 --- a/src/env/node/git/git.ts +++ b/src/env/node/git/git.ts @@ -294,17 +294,31 @@ export class Git { return proc; } - private gitLocator!: () => Promise; + private _gitLocation: GitLocation | undefined; + private _gitLocationPromise: Promise | undefined; + private async getLocation(): Promise { + if (this._gitLocation == null) { + if (this._gitLocationPromise == null) { + this._gitLocationPromise = this._gitLocator(); + } + this._gitLocation = await this._gitLocationPromise; + } + return this._gitLocation; + } + + private _gitLocator!: () => Promise; setLocator(locator: () => Promise): void { - this.gitLocator = locator; + this._gitLocator = locator; + this._gitLocationPromise = undefined; + this._gitLocation = undefined; } async path(): Promise { - return (await this.gitLocator()).path; + return (await this.getLocation()).path; } async version(): Promise { - return (await this.gitLocator()).version; + return (await this.getLocation()).version; } async isAtLeastVersion(minimum: string): Promise { @@ -312,6 +326,12 @@ export class Git { return result !== -1; } + maybeIsAtLeastVersion(minimum: string): boolean | undefined { + return this._gitLocation != null + ? compare(fromString(this._gitLocation.version), fromString(minimum)) !== -1 + : undefined; + } + // Git commands add(repoPath: string | undefined, pathspec: string) { @@ -346,38 +366,48 @@ export class Git { } if (options.args != null) { params.push(...options.args); + } - const index = params.indexOf('--ignore-revs-file'); - if (index !== -1) { - // Ensure the version of Git supports the --ignore-revs-file flag, otherwise the blame will fail - let supported = await this.isAtLeastVersion('2.23'); - if (supported) { - let ignoreRevsFile = params[index + 1]; - if (!isAbsolute(ignoreRevsFile)) { - ignoreRevsFile = joinPaths(repoPath ?? '', ignoreRevsFile); - } + // Ensure the version of Git supports the --ignore-revs-file flag, otherwise the blame will fail + let supportsIgnoreRevsFile = this.maybeIsAtLeastVersion('2.23'); + if (supportsIgnoreRevsFile === undefined) { + supportsIgnoreRevsFile = await this.isAtLeastVersion('2.23'); + } - const exists = this.ignoreRevsFileMap.get(ignoreRevsFile); - if (exists !== undefined) { - supported = exists; - } else { - // Ensure the specified --ignore-revs-file exists, otherwise the blame will fail - try { - supported = await fsExists(ignoreRevsFile); - } catch { - supported = false; - } + const ignoreRevsIndex = params.indexOf('--ignore-revs-file'); - this.ignoreRevsFileMap.set(ignoreRevsFile, supported); - } + if (supportsIgnoreRevsFile) { + let ignoreRevsFile; + if (ignoreRevsIndex !== -1) { + ignoreRevsFile = params[ignoreRevsIndex + 1]; + if (!isAbsolute(ignoreRevsFile)) { + ignoreRevsFile = joinPaths(root, ignoreRevsFile); } + } else { + ignoreRevsFile = joinPaths(root, '.git-blame-ignore-revs'); + } - if (!supported) { - params.splice(index, 2); + const exists = this.ignoreRevsFileMap.get(ignoreRevsFile); + if (exists !== undefined) { + supportsIgnoreRevsFile = exists; + } else { + // Ensure the specified --ignore-revs-file exists, otherwise the blame will fail + try { + supportsIgnoreRevsFile = await fsExists(ignoreRevsFile); + } catch { + supportsIgnoreRevsFile = false; } + + this.ignoreRevsFileMap.set(ignoreRevsFile, supportsIgnoreRevsFile); } } + if (!supportsIgnoreRevsFile && ignoreRevsIndex !== -1) { + params.splice(ignoreRevsIndex, 2); + } else if (supportsIgnoreRevsFile && ignoreRevsIndex === -1) { + params.push('--ignore-revs-file', '.git-blame-ignore-revs'); + } + let stdin; if (ref) { if (isUncommittedStaged(ref)) {