Ver a proveniência

Closes #1257 - Adds commit ordering option

Co-authored-by: Shashank-Shastri <shashank.m.shastri@gmail.com>
Co-authored-by: Eric Amodio <eamodio@gmail.com>
main
Eric Amodio há 3 anos
ascendente
cometimento
ecbf4cdfcb
5 ficheiros alterados com 170 adições e 32 eliminações
  1. +1
    -0
      README.md
  2. +21
    -0
      package.json
  3. +1
    -0
      src/config.ts
  4. +80
    -13
      src/git/git.ts
  5. +67
    -19
      src/git/gitService.ts

+ 1
- 0
README.md Ver ficheiro

@ -1005,6 +1005,7 @@ See also [View Settings](#view-settings- 'Jump to the View settings')
| `gitlens.advanced.blame.delayAfterEdit` | Specifies the time (in milliseconds) to wait before re-blaming an unsaved document after an edit. Use 0 to specify an infinite wait |
| `gitlens.advanced.blame.sizeThresholdAfterEdit` | Specifies the maximum document size (in lines) allowed to be re-blamed after an edit while still unsaved. Use 0 to specify no maximum |
| `gitlens.advanced.caching.enabled` | Specifies whether git output will be cached &mdash; changing the default is not recommended |
| `gitlens.advanced.commitOrdering` | Specifies the order by which commits will be shown. If unspecified, commits will be shown in reverse chronological order<br /><br />`date` - shows commits in reverse chronological order of the commit timestamp<br />`author-date` - shows commits in reverse chronological order of the author timestamp<br />`topo` - shows commits in reverse chronological order of the commit timestamp, but avoids intermixing multiple lines of history |
| `gitlens.advanced.externalDiffTool` | Specifies an optional external diff tool to use when comparing files. Must be a configured [Git difftool](https://git-scm.com/docs/git-config#Documentation/git-config.txt-difftool). |
| `gitlens.advanced.externalDirectoryDiffTool` | Specifies an optional external diff tool to use when comparing directories. Must be a configured [Git difftool](https://git-scm.com/docs/git-config#Documentation/git-config.txt-difftool). |
| `gitlens.advanced.fileHistoryFollowsRenames` | Specifies whether file histories will follow renames -- will affect how merge commits are shown in histories |

+ 21
- 0
package.json Ver ficheiro

@ -2520,6 +2520,27 @@
"markdownDescription": "Specifies whether git output will be cached — changing the default is not recommended",
"scope": "window"
},
"gitlens.advanced.commitOrdering": {
"type": [
"string",
"null"
],
"default": null,
"enum": [
null,
"date",
"author-date",
"topo"
],
"enumDescriptions": [
"Shows commits in reverse chronological order",
"Shows commits in reverse chronological order of the commit timestamp",
"Shows commits in reverse chronological order of the author timestamp",
"Shows commits in reverse chronological order of the commit timestamp, but avoids intermixing multiple lines of history"
],
"markdownDescription": "Specifies the order by which commits will be shown. If unspecified, commits will be shown in reverse chronological order",
"scope": "window"
},
"gitlens.advanced.externalDiffTool": {
"type": [
"string",

+ 1
- 0
src/config.ts Ver ficheiro

@ -308,6 +308,7 @@ export interface AdvancedConfig {
caching: {
enabled: boolean;
};
commitOrdering: string | null;
externalDiffTool: string | null;
externalDirectoryDiffTool: string | null;
fileHistoryFollowsRenames: boolean;

+ 80
- 13
src/git/git.ts Ver ficheiro

@ -745,6 +745,7 @@ export namespace Git {
format = 'default',
limit,
merges,
ordering,
reverse,
similarityThreshold,
since,
@ -753,6 +754,7 @@ export namespace Git {
format?: 'refs' | 'default';
limit?: number;
merges?: boolean;
ordering?: string | null;
reverse?: boolean;
similarityThreshold?: number | null;
since?: string;
@ -770,6 +772,10 @@ export namespace Git {
params.push('--name-status');
}
if (ordering) {
params.push(`--${ordering}-order`);
}
if (limit && !reverse) {
params.push(`-n${limit + 1}`);
}
@ -812,6 +818,7 @@ export namespace Git {
firstParent = false,
format = 'default',
limit,
ordering,
renames = true,
reverse = false,
since,
@ -824,6 +831,7 @@ export namespace Git {
firstParent?: boolean;
format?: 'refs' | 'simple' | 'default';
limit?: number;
ordering?: string | null;
renames?: boolean;
reverse?: boolean;
since?: string;
@ -839,6 +847,10 @@ export namespace Git {
`--format=${format === 'default' ? GitLogParser.defaultFormat : GitLogParser.simpleFormat}`,
];
if (ordering) {
params.push(`--${ordering}-order`);
}
if (limit && !reverse) {
params.push(`-n${limit + 1}`);
}
@ -903,7 +915,11 @@ export namespace Git {
export async function log__file_recent(
repoPath: string,
fileName: string,
{ ref, similarityThreshold }: { ref?: string; similarityThreshold?: number | null } = {},
{
ordering,
ref,
similarityThreshold,
}: { ordering?: string | null; ref?: string; similarityThreshold?: number | null } = {},
) {
const params = [
'log',
@ -912,6 +928,10 @@ export namespace Git {
'--format=%H',
];
if (ordering) {
params.push(`--${ordering}-order`);
}
if (ref) {
params.push(ref);
}
@ -925,8 +945,19 @@ export namespace Git {
return data.length === 0 ? undefined : data.trim();
}
export async function log__find_object(repoPath: string, objectId: string, ref: string, file?: string) {
export async function log__find_object(
repoPath: string,
objectId: string,
ref: string,
ordering: string | null,
file?: string,
) {
const params = ['log', '-n1', '--no-renames', '--format=%H', `--find-object=${objectId}`, ref];
if (ordering) {
params.push(`--${ordering}-order`);
}
if (file) {
params.push('--', file);
}
@ -938,32 +969,47 @@ export namespace Git {
return data.length === 0 ? undefined : data.trim();
}
export async function log__recent(repoPath: string) {
export async function log__recent(repoPath: string, ordering?: string | null) {
const params = ['log', '-n1', '--format=%H'];
if (ordering) {
params.push(`--${ordering}-order`);
}
const data = await git<string>(
{ cwd: repoPath, configs: ['-c', 'log.showSignature=false'], errors: GitErrorHandling.Ignore },
'log',
'-n1',
'--format=%H',
...params,
'--',
);
return data.length === 0 ? undefined : data.trim();
}
export async function log__recent_committerdate(repoPath: string) {
export async function log__recent_committerdate(repoPath: string, ordering?: string | null) {
const params = ['log', '-n1', '--format=%ct'];
if (ordering) {
params.push(`--${ordering}-order`);
}
const data = await git<string>(
{ cwd: repoPath, configs: ['-c', 'log.showSignature=false'], errors: GitErrorHandling.Ignore },
'log',
'-n1',
'--format=%ct',
...params,
'--',
);
return data.length === 0 ? undefined : data.trim();
}
export function log__search(
repoPath: string,
search: string[] = emptyArray,
{ limit, skip, useShow }: { limit?: number; skip?: number; useShow?: boolean } = {},
{
limit,
ordering,
skip,
useShow,
}: { limit?: number; ordering?: string | null; skip?: number; useShow?: boolean } = {},
) {
const params = [
useShow ? 'show' : 'log',
@ -971,13 +1017,19 @@ export namespace Git {
`--format=${GitLogParser.defaultFormat}`,
'--use-mailmap',
];
if (limit && !useShow) {
params.push(`-n${limit + 1}`);
}
if (skip && !useShow) {
params.push(`--skip=${skip}`);
}
if (ordering && !useShow) {
params.push(`--${ordering}-order`);
}
return git<string>(
{ cwd: repoPath, configs: useShow ? undefined : ['-c', 'log.showSignature=false'] },
...params,
@ -1038,18 +1090,32 @@ export namespace Git {
export function reflog(
repoPath: string,
{ all, branch, limit, skip }: { all?: boolean; branch?: string; limit?: number; skip?: number } = {},
{
all,
branch,
limit,
ordering,
skip,
}: { all?: boolean; branch?: string; limit?: number; ordering?: string | null; skip?: number } = {},
): Promise<string> {
const params = ['log', '--walk-reflogs', `--format=${GitReflogParser.defaultFormat}`, '--date=iso8601'];
if (ordering) {
params.push(`--${ordering}-order`);
}
if (all) {
params.push('--all');
}
if (limit) {
params.push(`-n${limit}`);
}
if (skip) {
params.push(`--skip=${skip}`);
}
if (branch) {
params.push(branch);
}
@ -1122,6 +1188,7 @@ export namespace Git {
export async function rev_parse__currentBranch(
repoPath: string,
ordering: string | null,
): Promise<[string, string | undefined] | undefined> {
try {
const data = await git<string>(
@ -1164,7 +1231,7 @@ export namespace Git {
}
if (GitWarnings.headNotABranch.test(msg)) {
const sha = await log__recent(repoPath);
const sha = await log__recent(repoPath, ordering);
if (sha === undefined) return undefined;
return [`(HEAD detached at ${GitRevision.shorten(sha)})`, sha];

+ 67
- 19
src/git/gitService.ts Ver ficheiro

@ -1215,14 +1215,14 @@ export class GitService implements Disposable {
let [branch] = await this.getBranches(repoPath, { filter: b => b.current });
if (branch != null) return branch;
const data = await Git.rev_parse__currentBranch(repoPath);
const data = await Git.rev_parse__currentBranch(repoPath, Container.config.advanced.commitOrdering);
if (data == null) return undefined;
const [name, tracking] = data[0].split('\n');
if (GitBranch.isDetached(name)) {
const [rebaseStatus, committerDate] = await Promise.all([
this.getRebaseStatus(repoPath),
Git.log__recent_committerdate(repoPath),
Git.log__recent_committerdate(repoPath, Container.config.advanced.commitOrdering),
]);
branch = new GitBranch(
@ -1300,12 +1300,12 @@ export class GitService implements Disposable {
if (data == null || data.length === 0) {
let current;
const data = await Git.rev_parse__currentBranch(repoPath);
const data = await Git.rev_parse__currentBranch(repoPath, Container.config.advanced.commitOrdering);
if (data != null) {
const [name, tracking] = data[0].split('\n');
const [rebaseStatus, committerDate] = await Promise.all([
GitBranch.isDetached(name) ? this.getRebaseStatus(repoPath) : undefined,
Git.log__recent_committerdate(repoPath),
Git.log__recent_committerdate(repoPath, Container.config.advanced.commitOrdering),
]);
current = new GitBranch(
@ -1498,6 +1498,7 @@ export class GitService implements Disposable {
async getOldestUnpushedRefForFile(repoPath: string, fileName: string): Promise<string | undefined> {
const data = await Git.log__file(repoPath, fileName, '@{push}..', {
format: 'refs',
ordering: Container.config.advanced.commitOrdering,
renames: true,
});
if (data == null || data.length === 0) return undefined;
@ -1876,6 +1877,7 @@ export class GitService implements Disposable {
authors?: string[];
limit?: number;
merges?: boolean;
ordering?: string | null;
ref?: string;
reverse?: boolean;
since?: string;
@ -1888,6 +1890,7 @@ export class GitService implements Disposable {
authors: options.authors,
limit: limit,
merges: options.merges == null ? true : options.merges,
ordering: options.ordering ?? Container.config.advanced.commitOrdering,
reverse: options.reverse,
similarityThreshold: Container.config.advanced.similarityThreshold,
since: options.since,
@ -1928,6 +1931,7 @@ export class GitService implements Disposable {
authors?: string[];
limit?: number;
merges?: boolean;
ordering?: string | null;
ref?: string;
reverse?: boolean;
since?: string;
@ -1944,6 +1948,7 @@ export class GitService implements Disposable {
reverse: options.reverse,
similarityThreshold: Container.config.advanced.similarityThreshold,
since: options.since,
ordering: options.ordering ?? Container.config.advanced.commitOrdering,
});
const commits = GitLogParser.parseRefsOnly(data);
return new Set(commits);
@ -1954,7 +1959,14 @@ export class GitService implements Disposable {
private getLogMoreFn(
log: GitLog,
options: { authors?: string[]; limit?: number; merges?: boolean; ref?: string; reverse?: boolean },
options: {
authors?: string[];
limit?: number;
merges?: boolean;
ordering?: string | null;
ref?: string;
reverse?: boolean;
},
): (limit: number | { until: string } | undefined) => Promise<GitLog> {
return async (limit: number | { until: string } | undefined) => {
const moreUntil = limit != null && typeof limit === 'object' ? limit.until : undefined;
@ -2021,7 +2033,7 @@ export class GitService implements Disposable {
async getLogForSearch(
repoPath: string,
search: SearchPattern,
options: { limit?: number; skip?: number } = {},
options: { limit?: number; ordering?: string | null; skip?: number } = {},
): Promise<GitLog | undefined> {
search = { matchAll: false, matchCase: false, matchRegex: true, ...search };
@ -2098,7 +2110,12 @@ export class GitService implements Disposable {
args.push(...files);
}
const data = await Git.log__search(repoPath, args, { ...options, limit: limit, useShow: useShow });
const data = await Git.log__search(repoPath, args, {
ordering: Container.config.advanced.commitOrdering,
...options,
limit: limit,
useShow: useShow,
});
const log = GitLogParser.parse(
data,
GitCommitType.Log,
@ -2128,7 +2145,7 @@ export class GitService implements Disposable {
private getLogForSearchMoreFn(
log: GitLog,
search: SearchPattern,
options: { limit?: number },
options: { limit?: number; ordering?: string | null },
): (limit: number | undefined) => Promise<GitLog> {
return async (limit: number | undefined) => {
limit = limit ?? Container.config.advanced.maxSearchItems ?? 0;
@ -2180,6 +2197,7 @@ export class GitService implements Disposable {
options: {
all?: boolean;
limit?: number;
ordering?: string | null;
range?: Range;
ref?: string;
renames?: boolean;
@ -2330,6 +2348,7 @@ export class GitService implements Disposable {
}: {
all?: boolean;
limit?: number;
ordering?: string | null;
range?: Range;
ref?: string;
renames?: boolean;
@ -2354,6 +2373,7 @@ export class GitService implements Disposable {
}
const data = await Git.log__file(root, file, ref, {
ordering: Container.config.advanced.commitOrdering,
...options,
firstParent: options.renames,
startLine: range == null ? undefined : range.start.line + 1,
@ -2404,7 +2424,15 @@ export class GitService implements Disposable {
private getLogForFileMoreFn(
log: GitLog,
fileName: string,
options: { all?: boolean; limit?: number; range?: Range; ref?: string; renames?: boolean; reverse?: boolean },
options: {
all?: boolean;
limit?: number;
ordering?: string | null;
range?: Range;
ref?: string;
renames?: boolean;
reverse?: boolean;
},
): (limit: number | { until: string } | undefined) => Promise<GitLog> {
return async (limit: number | { until: string } | undefined) => {
const moreUntil = limit != null && typeof limit === 'object' ? limit.until : undefined;
@ -2669,10 +2697,11 @@ export class GitService implements Disposable {
const fileName = GitUri.relativeTo(uri, repoPath);
let data = await Git.log__file(repoPath, fileName, ref, {
filters: filters,
format: 'simple',
limit: skip + 1,
// startLine: editorLine != null ? editorLine + 1 : undefined,
ordering: Container.config.advanced.commitOrdering,
reverse: true,
format: 'simple',
// startLine: editorLine != null ? editorLine + 1 : undefined,
});
if (data == null || data.length === 0) return undefined;
@ -2681,9 +2710,10 @@ export class GitService implements Disposable {
if (status === 'D') {
data = await Git.log__file(repoPath, '.', nextRef, {
filters: ['R', 'C'],
format: 'simple',
limit: 1,
ordering: Container.config.advanced.commitOrdering,
// startLine: editorLine != null ? editorLine + 1 : undefined
format: 'simple',
});
if (data == null || data.length === 0) {
return GitUri.fromFile(file ?? fileName, repoPath, nextRef);
@ -2918,9 +2948,10 @@ export class GitService implements Disposable {
let data;
try {
data = await Git.log__file(repoPath, fileName, ref, {
limit: skip + 2,
firstParent: firstParent,
format: 'simple',
limit: skip + 2,
ordering: Container.config.advanced.commitOrdering,
startLine: editorLine != null ? editorLine + 1 : undefined,
});
} catch (ex) {
@ -2934,7 +2965,9 @@ export class GitService implements Disposable {
}
}
ref = await Git.log__file_recent(repoPath, fileName);
ref = await Git.log__file_recent(repoPath, fileName, {
ordering: Container.config.advanced.commitOrdering,
});
return GitUri.fromFile(fileName, repoPath, ref ?? GitRevision.deletedOrMissing);
}
@ -3056,14 +3089,21 @@ export class GitService implements Disposable {
@log()
async getIncomingActivity(
repoPath: string,
{ limit, ...options }: { all?: boolean; branch?: string; limit?: number; skip?: number } = {},
{
limit,
...options
}: { all?: boolean; branch?: string; limit?: number; ordering?: string | null; skip?: number } = {},
): Promise<GitReflog | undefined> {
const cc = Logger.getCorrelationContext();
limit = limit ?? Container.config.advanced.maxListItems ?? 0;
try {
// Pass a much larger limit to reflog, because we aggregate the data and we won't know how many lines we'll need
const data = await Git.reflog(repoPath, { ...options, limit: limit * 100 });
const data = await Git.reflog(repoPath, {
ordering: Container.config.advanced.commitOrdering,
...options,
limit: limit * 100,
});
if (data == null) return undefined;
const reflog = GitReflogParser.parse(data, repoPath, reflogCommands, limit, limit * 100);
@ -3080,7 +3120,7 @@ export class GitService implements Disposable {
private getReflogMoreFn(
reflog: GitReflog,
options: { all?: boolean; branch?: string; limit?: number; skip?: number },
options: { all?: boolean; branch?: string; limit?: number; ordering?: string | null; skip?: number },
): (limit: number) => Promise<GitReflog> {
return async (limit: number | undefined) => {
limit = limit ?? Container.config.advanced.maxSearchItems ?? 0;
@ -3721,6 +3761,7 @@ export class GitService implements Disposable {
// TODO: Add caching
// Get the most recent commit for this file name
ref = await Git.log__file_recent(repoPath, fileName, {
ordering: Container.config.advanced.commitOrdering,
similarityThreshold: Container.config.advanced.similarityThreshold,
});
if (ref == null) return undefined;
@ -3728,8 +3769,9 @@ export class GitService implements Disposable {
// Now check if that commit had any renames
data = await Git.log__file(repoPath, '.', ref, {
filters: ['R', 'C', 'D'],
limit: 1,
format: 'simple',
limit: 1,
ordering: Container.config.advanced.commitOrdering,
});
if (data == null || data.length === 0) break;
@ -4012,7 +4054,13 @@ export class GitService implements Disposable {
const blob = await Git.rev_parse__verify(repoPath, ref, fileName);
if (blob == null) return GitRevision.deletedOrMissing;
let promise: Promise<string | void | undefined> = Git.log__find_object(repoPath, blob, ref, fileName);
let promise: Promise<string | void | undefined> = Git.log__find_object(
repoPath,
blob,
ref,
Container.config.advanced.commitOrdering,
fileName,
);
if (options?.timeout != null) {
promise = Promise.race([promise, Functions.wait(options.timeout)]);
}

Carregando…
Cancelar
Guardar