Skip to content

Commit 84ba8fb

Browse files
eamodioianhattendorf
authored andcommitted
Optimizes commit signature detection
- Adds a lightweight method to check for commit signatures - Adds short ttl caching to signature check results - Adopts the lightweight check in hovers and views
1 parent 2e08459 commit 84ba8fb

File tree

6 files changed

+48
-13
lines changed

6 files changed

+48
-13
lines changed

src/env/node/git/sub-providers/commits.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,12 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
13091309

13101310
try {
13111311
const result = await this.git.exec(
1312-
{ cwd: repoPath, errors: 'ignore', configs: gitConfigsLog },
1312+
{
1313+
cwd: repoPath,
1314+
errors: 'ignore',
1315+
caching: { cache: this.cache.gitResults, options: { accessTTL: 60 * 1000 } },
1316+
configs: gitConfigsLog,
1317+
},
13131318
'log',
13141319
`--format=${signatureFormat}`,
13151320
'-1',
@@ -1324,6 +1329,28 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
13241329
return undefined;
13251330
}
13261331
}
1332+
1333+
@log()
1334+
async isCommitSigned(repoPath: string, sha: string): Promise<boolean> {
1335+
const scope = getLogScope();
1336+
1337+
try {
1338+
const result = await this.git.exec(
1339+
{
1340+
cwd: repoPath,
1341+
errors: 'ignore',
1342+
caching: { cache: this.cache.gitResults, options: { accessTTL: 60 * 1000 } },
1343+
},
1344+
'cat-file',
1345+
'commit',
1346+
sha,
1347+
);
1348+
return /^gpgsig(-sha256)? /m.test(result.stdout);
1349+
} catch (ex) {
1350+
Logger.error(ex, scope);
1351+
return false;
1352+
}
1353+
}
13271354
}
13281355

13291356
function createCommit(

src/git/gitProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,8 @@ export interface GitCommitsSubProvider {
391391
rev: string,
392392
cancellation?: CancellationToken,
393393
): Promise<GitCommitReachability | undefined>;
394-
395394
getCommitSignature?(repoPath: string, sha: string): Promise<CommitSignature | undefined>;
395+
isCommitSigned?(repoPath: string, sha: string): Promise<boolean>;
396396
}
397397

398398
export interface GitOperationsSubProvider {

src/git/models/commit.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export class GitCommit implements GitRevisionReference {
5959
private _stashUntrackedFilesLoaded = false;
6060
private _recomputeStats = false;
6161
private _signature: CommitSignature | undefined | null;
62+
private _signed: boolean | undefined;
6263

6364
readonly lines: GitCommitLine[];
6465
readonly ref: string;
@@ -601,6 +602,15 @@ export class GitCommit implements GitRevisionReference {
601602
return this._signature ?? undefined;
602603
}
603604

605+
async isSigned(): Promise<boolean> {
606+
if (this.isUncommitted) return false;
607+
if (this._signed != null) return this._signed;
608+
609+
this._signed =
610+
(await this.container.git.getRepositoryService(this.repoPath).commits.isCommitSigned?.(this.sha)) ?? false;
611+
return this._signed;
612+
}
613+
604614
async getCommitForFile(file: string | GitFile, staged?: boolean): Promise<GitCommit | undefined> {
605615
const path = typeof file === 'string' ? this.container.git.getRelativePath(file, this.repoPath) : file.path;
606616
const foundFile = await this.findFile(path, staged);

src/hovers/hovers.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ export async function detailsMessage(
251251
presenceResult,
252252
previousLineComparisonUrisResult,
253253
_fullDetailsResult,
254-
signatureResult,
254+
signedResult,
255255
] = await Promise.allSettled([
256256
enhancedAutolinks
257257
? pauseOnCancelOrTimeoutMapTuplePromise(
@@ -278,9 +278,7 @@ export async function detailsMessage(
278278
? commit.getPreviousComparisonUrisForRange(editorLineToDiffRange(editorLine), uri.sha)
279279
: undefined,
280280
commit.message == null ? commit.ensureFullDetails() : undefined,
281-
showSignature
282-
? pauseOnCancelOrTimeout(commit.getSignature(), options?.cancellation, options?.timeout)
283-
: undefined,
281+
showSignature ? commit.isSigned() : undefined,
284282
]);
285283

286284
if (options?.cancellation?.isCancellationRequested) return undefined;
@@ -289,7 +287,7 @@ export async function detailsMessage(
289287
const pr = getSettledValue(prResult);
290288
const presence = getSettledValue(presenceResult);
291289
const previousLineComparisonUris = getSettledValue(previousLineComparisonUrisResult);
292-
const signature = getSettledValue(signatureResult);
290+
const signed = getSettledValue(signedResult);
293291

294292
const details = await CommitFormatter.fromTemplateAsync(
295293
options.format,
@@ -308,7 +306,7 @@ export async function detailsMessage(
308306
previousLineComparisonUris: previousLineComparisonUris,
309307
outputFormat: 'markdown',
310308
remotes: remotes,
311-
signed: signature?.value != null,
309+
signed: signed,
312310
},
313311
);
314312

src/views/nodes/commitNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ export class CommitNode extends ViewRefNode<'commit', ViewsWithCommits | FileHis
275275
allowFilteredFiles: this._options.allowFilteredFiles,
276276
include: { stats: true },
277277
}),
278-
showSignature ? pauseOnCancelOrTimeout(this.commit.getSignature(), cancellation) : undefined,
278+
showSignature ? pauseOnCancelOrTimeout(this.commit.isSigned(), cancellation) : undefined,
279279
]);
280280

281281
if (cancellation.isCancellationRequested) return undefined;

src/webviews/plus/graph/graphWebview.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,17 +1025,17 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
10251025
CommitFormatter.has(template, 'signature');
10261026

10271027
const svc = this.container.git.getRepositoryService(commit.repoPath);
1028-
const [remotesResult, _, signatureResult] = await Promise.allSettled([
1028+
const [remotesResult, _, signedResult] = await Promise.allSettled([
10291029
svc.remotes.getBestRemotesWithProviders(),
10301030
commit.ensureFullDetails({ include: { stats: true } }),
1031-
showSignature ? pauseOnCancelOrTimeout(commit.getSignature(), cancellation) : undefined,
1031+
showSignature ? commit.isSigned() : undefined,
10321032
]);
10331033

10341034
if (cancellation.isCancellationRequested) throw new CancellationError();
10351035

10361036
const remotes = getSettledValue(remotesResult, []);
10371037
const [remote] = remotes;
1038-
const signature = getSettledValue(signatureResult);
1038+
const signed = getSettledValue(signedResult);
10391039

10401040
let enrichedAutolinks;
10411041
let pr;
@@ -1070,7 +1070,7 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
10701070
pullRequest: pr,
10711071
outputFormat: 'markdown',
10721072
remotes: remotes,
1073-
signed: signature?.value != null,
1073+
signed: signed,
10741074
// unpublished: this.unpublished,
10751075
},
10761076
);

0 commit comments

Comments
 (0)