Skip to content

Commit

Permalink
Adds support for .git-blame-ignore-rev files
Browse files Browse the repository at this point in the history
  • Loading branch information
eamodio committed Mar 10, 2023
1 parent 189cc64 commit ea78a75
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 28 deletions.
File renamed without changes.
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
84 changes: 57 additions & 27 deletions src/env/node/git/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,24 +294,44 @@ export class Git {
return proc;
}

private gitLocator!: () => Promise<GitLocation>;
private _gitLocation: GitLocation | undefined;
private _gitLocationPromise: Promise<GitLocation> | undefined;
private async getLocation(): Promise<GitLocation> {
if (this._gitLocation == null) {
if (this._gitLocationPromise == null) {
this._gitLocationPromise = this._gitLocator();
}
this._gitLocation = await this._gitLocationPromise;
}
return this._gitLocation;
}

private _gitLocator!: () => Promise<GitLocation>;
setLocator(locator: () => Promise<GitLocation>): void {
this.gitLocator = locator;
this._gitLocator = locator;
this._gitLocationPromise = undefined;
this._gitLocation = undefined;
}

async path(): Promise<string> {
return (await this.gitLocator()).path;
return (await this.getLocation()).path;
}

async version(): Promise<string> {
return (await this.gitLocator()).version;
return (await this.getLocation()).version;
}

async isAtLeastVersion(minimum: string): Promise<boolean> {
const result = compare(fromString(await this.version()), fromString(minimum));
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) {
Expand Down Expand Up @@ -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)) {
Expand Down

0 comments on commit ea78a75

Please sign in to comment.