Skip to content

Commit ae4bf5d

Browse files
sergeibbbd13
authored andcommitted
Track and attach parent commit timestamps to stashes in StashGitSubProvider
(#4401, #4468)
1 parent 31d87dc commit ae4bf5d

File tree

1 file changed

+59
-2
lines changed

1 file changed

+59
-2
lines changed

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

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@ import type { GitCache } from '../../../../git/cache';
55
import { GitErrorHandling } from '../../../../git/commandOptions';
66
import { StashApplyError, StashApplyErrorReason } from '../../../../git/errors';
77
import type { GitStashSubProvider } from '../../../../git/gitProvider';
8-
import type { GitStashCommit } from '../../../../git/models/commit';
8+
import type { GitStashCommit, GitStashParentInfo } from '../../../../git/models/commit';
99
import { GitCommit, GitCommitIdentity } from '../../../../git/models/commit';
1010
import { GitFileChange } from '../../../../git/models/fileChange';
1111
import type { GitFileStatus } from '../../../../git/models/fileStatus';
1212
import { GitFileWorkingTreeStatus } from '../../../../git/models/fileStatus';
1313
import { RepositoryChange } from '../../../../git/models/repository';
1414
import type { GitStash } from '../../../../git/models/stash';
1515
import type { ParsedStash } from '../../../../git/parsers/logParser';
16-
import { getStashFilesOnlyLogParser, getStashLogParser } from '../../../../git/parsers/logParser';
16+
import {
17+
getShaAndDatesLogParser,
18+
getStashFilesOnlyLogParser,
19+
getStashLogParser,
20+
} from '../../../../git/parsers/logParser';
1721
import { configuration } from '../../../../system/-webview/configuration';
1822
import { splitPath } from '../../../../system/-webview/path';
1923
import { countStringLength } from '../../../../system/array';
@@ -90,9 +94,62 @@ export class StashGitSubProvider implements GitStashSubProvider {
9094
);
9195

9296
const stashes = new Map<string, GitStashCommit>();
97+
const parentShas = new Set<string>();
9398

99+
// First pass: create stashes and collect parent SHAs
94100
for (const s of parser.parse(result.stdout)) {
95101
stashes.set(s.sha, createStash(this.container, s, repoPath));
102+
// Collect all parent SHAs for timestamp lookup
103+
if (s.parents) {
104+
for (const parentSha of s.parents.split(' ')) {
105+
if (parentSha.trim()) {
106+
parentShas.add(parentSha.trim());
107+
}
108+
}
109+
}
110+
}
111+
112+
// Second pass: fetch parent timestamps if we have any parents
113+
const parentTimestamps = new Map<string, { authorDate: number; committerDate: number }>();
114+
if (parentShas.size > 0) {
115+
try {
116+
const datesParser = getShaAndDatesLogParser();
117+
const parentResult = await this.git.exec(
118+
{
119+
cwd: repoPath,
120+
cancellation: cancellation,
121+
stdin: Array.from(parentShas).join('\n'),
122+
},
123+
'log',
124+
...datesParser.arguments,
125+
'--no-walk',
126+
'--stdin',
127+
);
128+
129+
for (const entry of datesParser.parse(parentResult.stdout)) {
130+
parentTimestamps.set(entry.sha, {
131+
authorDate: Number(entry.authorDate),
132+
committerDate: Number(entry.committerDate),
133+
});
134+
}
135+
} catch (_ex) {
136+
// If we can't get parent timestamps, continue without them
137+
// This could happen if some parent commits are not available
138+
}
139+
}
140+
141+
// Third pass: update stashes with parent timestamp information
142+
for (const sha of stashes.keys()) {
143+
const stash = stashes.get(sha);
144+
if (stash?.parents.length) {
145+
const parentsWithTimestamps: GitStashParentInfo[] = stash.parents.map(parentSha => ({
146+
sha: parentSha,
147+
authorDate: parentTimestamps.get(parentSha)?.authorDate,
148+
committerDate: parentTimestamps.get(parentSha)?.committerDate,
149+
}));
150+
// Store the parent timestamp information on the stash
151+
stashes.set(sha, stash.with({ parentTimestamps: parentsWithTimestamps }));
152+
}
96153
}
97154

98155
return { repoPath: repoPath, stashes: stashes };

0 commit comments

Comments
 (0)