Browse Source

Fixes branch commit quickpick nav

main
Eric Amodio 5 years ago
parent
commit
d2b87f98c6
11 changed files with 179 additions and 281 deletions
  1. +5
    -7
      src/commands/showQuickCommitDetails.ts
  2. +5
    -0
      src/git/git.ts
  3. +31
    -44
      src/git/gitService.ts
  4. +0
    -6
      src/git/models/blameCommit.ts
  5. +12
    -36
      src/git/models/commit.ts
  6. +6
    -13
      src/git/models/logCommit.ts
  7. +4
    -31
      src/git/models/stashCommit.ts
  8. +1
    -1
      src/git/parsers/logParser.ts
  9. +5
    -5
      src/quickpicks/commitFileQuickPick.ts
  10. +108
    -136
      src/quickpicks/commitQuickPick.ts
  11. +2
    -2
      src/system/iterable.ts

+ 5
- 7
src/commands/showQuickCommitDetails.ts View File

@ -156,13 +156,11 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand {
[args.commit.toGitUri(), args] [args.commit.toGitUri(), args]
); );
const pick = await CommitQuickPick.show(
args.commit as GitLogCommit,
uri,
args.goBackCommand,
currentCommand,
args.repoLog
);
const pick = await new CommitQuickPick(repoPath).show(args.commit as GitLogCommit, uri, {
currentCommand: currentCommand,
goBackCommand: args.goBackCommand,
repoLog: args.repoLog
});
if (pick === undefined) return undefined; if (pick === undefined) return undefined;
if (!(pick instanceof CommitWithFileStatusQuickPickItem)) return pick.execute(); if (!(pick instanceof CommitWithFileStatusQuickPickItem)) return pick.execute();

+ 5
- 0
src/git/git.ts View File

@ -204,6 +204,7 @@ export class Git {
static deletedOrMissingSha = '0000000000000000000000000000000000000000-'; static deletedOrMissingSha = '0000000000000000000000000000000000000000-';
static shaLikeRegex = /(^[0-9a-f]{40}([\^@~:]\S*)?$)|(^[0]{40}(:|-)$)/; static shaLikeRegex = /(^[0-9a-f]{40}([\^@~:]\S*)?$)|(^[0]{40}(:|-)$)/;
static shaRegex = /(^[0-9a-f]{40}$)|(^[0]{40}(:|-)$)/; static shaRegex = /(^[0-9a-f]{40}$)|(^[0]{40}(:|-)$)/;
static shaParentRegex = /^[0-9a-f]{40}\^[0-3]?$/;
static shaShortenRegex = /^(.*?)([\^@~:].*)?$/; static shaShortenRegex = /^(.*?)([\^@~:].*)?$/;
static stagedUncommittedRegex = /^[0]{40}([\^@~]\S*)?:$/; static stagedUncommittedRegex = /^[0]{40}([\^@~]\S*)?:$/;
static stagedUncommittedSha = '0000000000000000000000000000000000000000:'; static stagedUncommittedSha = '0000000000000000000000000000000000000000:';
@ -242,6 +243,10 @@ export class Git {
return Git.shaLikeRegex.test(ref); return Git.shaLikeRegex.test(ref);
} }
static isShaParent(ref: string) {
return Git.shaParentRegex.test(ref);
}
static isStagedUncommitted(ref: string | undefined): boolean { static isStagedUncommitted(ref: string | undefined): boolean {
return ref ? Git.stagedUncommittedRegex.test(ref) : false; return ref ? Git.stagedUncommittedRegex.test(ref) : false;
} }

+ 31
- 44
src/git/gitService.ts View File

@ -139,6 +139,18 @@ export class GitService implements Disposable {
this._disposable && this._disposable.dispose(); this._disposable && this._disposable.dispose();
} }
@log()
static async initialize(): Promise<void> {
// Try to use the same git as the built-in vscode git extension
let gitPath;
const gitApi = await GitService.getBuiltInGitApi();
if (gitApi !== undefined) {
gitPath = gitApi.git.path;
}
await Git.setOrFindGitPath(gitPath || workspace.getConfiguration('git').get<string>('path'));
}
get useCaching() { get useCaching() {
return Container.config.advanced.caching.enabled; return Container.config.advanced.caching.enabled;
} }
@ -2386,23 +2398,17 @@ export class GitService implements Disposable {
return Git.stash_push(repoPath, pathspecs, message); return Git.stash_push(repoPath, pathspecs, message);
} }
static getEncoding(repoPath: string, fileName: string): string;
static getEncoding(uri: Uri): string;
static getEncoding(repoPathOrUri: string | Uri, fileName?: string): string {
const uri = typeof repoPathOrUri === 'string' ? GitUri.resolveToUri(fileName!, repoPathOrUri) : repoPathOrUri;
return Git.getEncoding(workspace.getConfiguration('files', uri).get<string>('encoding'));
static compareGitVersion(version: string) {
return Versions.compare(Versions.fromString(this.getGitVersion()), Versions.fromString(version));
} }
@log()
static async initialize(): Promise<void> {
// Try to use the same git as the built-in vscode git extension
let gitPath;
const gitApi = await GitService.getBuiltInGitApi();
if (gitApi !== undefined) {
gitPath = gitApi.git.path;
static ensureGitVersion(version: string, feature: string): void {
const gitVersion = this.getGitVersion();
if (Versions.compare(Versions.fromString(gitVersion), Versions.fromString(version)) === -1) {
throw new Error(
`${feature} requires a newer version of Git (>= ${version}) than is currently installed (${gitVersion}). Please install a more recent version of Git to use this GitLens feature.`
);
} }
await Git.setOrFindGitPath(gitPath || workspace.getConfiguration('git').get<string>('path'));
} }
@log() @log()
@ -2420,25 +2426,19 @@ export class GitService implements Disposable {
return undefined; return undefined;
} }
static getGitPath(): string {
return Git.getGitPath();
}
static getGitVersion(): string {
return Git.getGitVersion();
}
static isShaLike(ref: string): boolean {
return Git.isShaLike(ref);
static getEncoding(repoPath: string, fileName: string): string;
static getEncoding(uri: Uri): string;
static getEncoding(repoPathOrUri: string | Uri, fileName?: string): string {
const uri = typeof repoPathOrUri === 'string' ? GitUri.resolveToUri(fileName!, repoPathOrUri) : repoPathOrUri;
return Git.getEncoding(workspace.getConfiguration('files', uri).get<string>('encoding'));
} }
static isStagedUncommitted(ref: string | undefined): boolean {
return Git.isStagedUncommitted(ref);
}
static isUncommitted(ref: string | undefined): boolean {
return Git.isUncommitted(ref);
}
static getGitPath = Git.getGitPath;
static getGitVersion = Git.getGitVersion;
static isShaLike = Git.isShaLike;
static isShaParent = Git.isShaParent;
static isStagedUncommitted = Git.isStagedUncommitted;
static isUncommitted = Git.isUncommitted;
static shortenSha( static shortenSha(
ref: string | undefined, ref: string | undefined,
@ -2453,17 +2453,4 @@ export class GitService implements Disposable {
return Git.isShaLike(ref) || Git.isStagedUncommitted(ref) ? Git.shortenSha(ref, strings) : ref; return Git.isShaLike(ref) || Git.isStagedUncommitted(ref) ? Git.shortenSha(ref, strings) : ref;
} }
static compareGitVersion(version: string) {
return Versions.compare(Versions.fromString(this.getGitVersion()), Versions.fromString(version));
}
static ensureGitVersion(version: string, feature: string): void {
const gitVersion = this.getGitVersion();
if (Versions.compare(Versions.fromString(gitVersion), Versions.fromString(version)) === -1) {
throw new Error(
`${feature} requires a newer version of Git (>= ${version}) than is currently installed (${gitVersion}). Please install a more recent version of Git to use this GitLens feature.`
);
}
}
} }

+ 0
- 6
src/git/models/blameCommit.ts View File

@ -32,12 +32,6 @@ export class GitBlameCommit extends GitCommit {
); );
} }
get previousFileSha(): string {
if (this._resolvedPreviousFileSha !== undefined) return this._resolvedPreviousFileSha;
return `${this.sha}^`;
}
with(changes: { with(changes: {
sha?: string; sha?: string;
fileName?: string; fileName?: string;

+ 12
- 36
src/git/models/commit.ts View File

@ -42,21 +42,8 @@ export const CommitFormatting = {
}; };
export abstract class GitCommit { export abstract class GitCommit {
readonly type: GitCommitType;
readonly originalFileName: string | undefined;
previousFileName: string | undefined;
protected readonly _fileName: string;
protected _previousSha: string | undefined;
private _authorDateFormatter: Dates.DateFormatter | undefined;
private _committerDateFormatter: Dates.DateFormatter | undefined;
private _isStagedUncommitted: boolean | undefined;
private _isUncommitted: boolean | undefined;
private _shortSha: string | undefined;
constructor( constructor(
type: GitCommitType,
public readonly type: GitCommitType,
public readonly repoPath: string, public readonly repoPath: string,
public readonly sha: string, public readonly sha: string,
public readonly author: string, public readonly author: string,
@ -65,17 +52,14 @@ export abstract class GitCommit {
public readonly committerDate: Date, public readonly committerDate: Date,
public readonly message: string, public readonly message: string,
fileName: string, fileName: string,
originalFileName?: string,
previousSha?: string,
previousFileName?: string
public readonly originalFileName: string | undefined,
public previousSha: string | undefined,
public previousFileName: string | undefined
) { ) {
this.type = type;
this._fileName = fileName || ''; this._fileName = fileName || '';
this.originalFileName = originalFileName;
this._previousSha = previousSha;
this.previousFileName = previousFileName;
} }
private readonly _fileName: string;
get fileName() { get fileName() {
// If we aren't a single-file commit, return an empty file name (makes it default to the repoPath) // If we aren't a single-file commit, return an empty file name (makes it default to the repoPath)
return this.isFile ? this._fileName : ''; return this.isFile ? this._fileName : '';
@ -91,6 +75,7 @@ export abstract class GitCommit {
: this.formatDateFromNow(); : this.formatDateFromNow();
} }
private _shortSha: string | undefined;
get shortSha() { get shortSha() {
if (this._shortSha === undefined) { if (this._shortSha === undefined) {
this._shortSha = Git.shortenSha(this.sha); this._shortSha = Git.shortenSha(this.sha);
@ -110,6 +95,7 @@ export abstract class GitCommit {
return this.type === GitCommitType.Stash || this.type === GitCommitType.StashFile; return this.type === GitCommitType.Stash || this.type === GitCommitType.StashFile;
} }
private _isStagedUncommitted: boolean | undefined;
get isStagedUncommitted(): boolean { get isStagedUncommitted(): boolean {
if (this._isStagedUncommitted === undefined) { if (this._isStagedUncommitted === undefined) {
this._isStagedUncommitted = Git.isStagedUncommitted(this.sha); this._isStagedUncommitted = Git.isStagedUncommitted(this.sha);
@ -117,6 +103,7 @@ export abstract class GitCommit {
return this._isStagedUncommitted; return this._isStagedUncommitted;
} }
private _isUncommitted: boolean | undefined;
get isUncommitted(): boolean { get isUncommitted(): boolean {
if (this._isUncommitted === undefined) { if (this._isUncommitted === undefined) {
this._isUncommitted = Git.isUncommitted(this.sha); this._isUncommitted = Git.isUncommitted(this.sha);
@ -124,21 +111,8 @@ export abstract class GitCommit {
return this._isUncommitted; return this._isUncommitted;
} }
abstract get previousFileSha(): string;
protected _resolvedPreviousFileSha: string | undefined;
get previousFileShortSha(): string {
return Git.shortenSha(this.previousFileSha)!;
}
get previousSha(): string | undefined {
return this._previousSha;
}
set previousSha(value: string | undefined) {
if (value === this._previousSha) return;
this._previousSha = value;
this._resolvedPreviousFileSha = undefined;
get previousFileSha(): string {
return `${this.sha}^`;
} }
get previousShortSha() { get previousShortSha() {
@ -162,6 +136,7 @@ export abstract class GitCommit {
return this._workingUriPromise; return this._workingUriPromise;
} }
private _authorDateFormatter: Dates.DateFormatter | undefined;
private get authorDateFormatter(): Dates.DateFormatter { private get authorDateFormatter(): Dates.DateFormatter {
if (this._authorDateFormatter === undefined) { if (this._authorDateFormatter === undefined) {
this._authorDateFormatter = Dates.toFormatter(this.authorDate); this._authorDateFormatter = Dates.toFormatter(this.authorDate);
@ -169,6 +144,7 @@ export abstract class GitCommit {
return this._authorDateFormatter; return this._authorDateFormatter;
} }
private _committerDateFormatter: Dates.DateFormatter | undefined;
private get committerDateFormatter(): Dates.DateFormatter { private get committerDateFormatter(): Dates.DateFormatter {
if (this._committerDateFormatter === undefined) { if (this._committerDateFormatter === undefined) {
this._committerDateFormatter = Dates.toFormatter(this.committerDate); this._committerDateFormatter = Dates.toFormatter(this.committerDate);

+ 6
- 13
src/git/models/logCommit.ts View File

@ -2,7 +2,6 @@
import * as paths from 'path'; import * as paths from 'path';
import { Uri } from 'vscode'; import { Uri } from 'vscode';
import { Strings } from '../../system'; import { Strings } from '../../system';
import { Git } from '../git';
import { GitUri } from '../gitUri'; import { GitUri } from '../gitUri';
import { GitCommit, GitCommitType } from './commit'; import { GitCommit, GitCommitType } from './commit';
import { GitFile, GitFileStatus } from './file'; import { GitFile, GitFileStatus } from './file';
@ -22,10 +21,10 @@ export class GitLogCommit extends GitCommit {
message: string, message: string,
fileName: string, fileName: string,
public readonly files: GitFile[], public readonly files: GitFile[],
public readonly status: GitFileStatus | undefined,
originalFileName: string | undefined,
previousSha: string | undefined,
previousFileName: string | undefined,
public readonly status?: GitFileStatus | undefined,
originalFileName?: string | undefined,
previousSha?: string | undefined,
previousFileName?: string | undefined,
public readonly parentShas?: string[] public readonly parentShas?: string[]
) { ) {
super( super(
@ -39,7 +38,7 @@ export class GitLogCommit extends GitCommit {
message, message,
fileName, fileName,
originalFileName, originalFileName,
previousSha,
previousSha || `${sha}^`,
previousFileName previousFileName
); );
} }
@ -48,18 +47,12 @@ export class GitLogCommit extends GitCommit {
return this.parentShas && this.parentShas.length > 1; return this.parentShas && this.parentShas.length > 1;
} }
get nextShortSha() {
return this.nextSha && Git.shortenSha(this.nextSha);
}
get nextUri(): Uri { get nextUri(): Uri {
return this.nextFileName ? GitUri.resolveToUri(this.nextFileName, this.repoPath) : this.uri; return this.nextFileName ? GitUri.resolveToUri(this.nextFileName, this.repoPath) : this.uri;
} }
get previousFileSha(): string { get previousFileSha(): string {
if (this._resolvedPreviousFileSha !== undefined) return this._resolvedPreviousFileSha;
return this.isFile && this.previousSha ? this.previousSha : `${this.sha}^`;
return this.isFile ? this.previousSha! : `${this.sha}^`;
} }
private _diff?: { private _diff?: {

+ 4
- 31
src/git/models/stashCommit.ts View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import { GitCommitType } from './commit'; import { GitCommitType } from './commit';
import { GitFile, GitFileStatus } from './file';
import { GitFile } from './file';
import { GitLogCommit } from './logCommit'; import { GitLogCommit } from './logCommit';
export class GitStashCommit extends GitLogCommit { export class GitStashCommit extends GitLogCommit {
@ -17,28 +17,9 @@ export class GitStashCommit extends GitLogCommit {
committedDate: Date, committedDate: Date,
message: string, message: string,
fileName: string, fileName: string,
files: GitFile[],
status?: GitFileStatus | undefined,
originalFileName?: string | undefined,
previousSha?: string | undefined,
previousFileName?: string | undefined
files: GitFile[]
) { ) {
super(
type,
repoPath,
sha,
'You',
undefined,
authorDate,
committedDate,
message,
fileName,
files,
status,
originalFileName,
previousSha === undefined ? `${sha}^` : previousSha,
previousFileName
);
super(type, repoPath, sha, 'You', undefined, authorDate, committedDate, message, fileName, files);
} }
get shortSha() { get shortSha() {
@ -52,10 +33,6 @@ export class GitStashCommit extends GitLogCommit {
authorDate?: Date; authorDate?: Date;
committedDate?: Date; committedDate?: Date;
message?: string; message?: string;
originalFileName?: string | null;
previousFileName?: string | null;
previousSha?: string | null;
status?: GitFileStatus;
files?: GitFile[] | null; files?: GitFile[] | null;
}): GitLogCommit { }): GitLogCommit {
return new GitStashCommit( return new GitStashCommit(
@ -67,11 +44,7 @@ export class GitStashCommit extends GitLogCommit {
changes.committedDate || this.committerDate, changes.committedDate || this.committerDate,
changes.message || this.message, changes.message || this.message,
changes.fileName || this.fileName, changes.fileName || this.fileName,
this.getChangedValue(changes.files, this.files) || [],
changes.status || this.status,
this.getChangedValue(changes.originalFileName, this.originalFileName),
this.getChangedValue(changes.previousSha, this.previousSha),
this.getChangedValue(changes.previousFileName, this.previousFileName)
this.getChangedValue(changes.files, this.files) || []
); );
} }
} }

+ 1
- 1
src/git/parsers/logParser.ts View File

@ -354,7 +354,7 @@ export class GitLogParser {
entry.files || [], entry.files || [],
entry.status, entry.status,
originalFileName, originalFileName,
`${entry.ref!}^`,
type === GitCommitType.Branch ? entry.parentShas![0] : undefined,
undefined, undefined,
entry.parentShas! entry.parentShas!
); );

+ 5
- 5
src/quickpicks/commitFileQuickPick.ts View File

@ -14,7 +14,7 @@ import {
} from '../commands'; } from '../commands';
import { GlyphChars } from '../constants'; import { GlyphChars } from '../constants';
import { Container } from '../container'; import { Container } from '../container';
import { GitLog, GitLogCommit, GitUri, RemoteResourceType } from '../git/gitService';
import { GitLog, GitLogCommit, GitService, GitUri, RemoteResourceType } from '../git/gitService';
import { KeyCommand, KeyNoopCommand } from '../keyboard'; import { KeyCommand, KeyNoopCommand } from '../keyboard';
import { Strings } from '../system'; import { Strings } from '../system';
import { import {
@ -115,7 +115,7 @@ export class CommitFileQuickPick {
items.push(new ApplyCommitFileChangesCommandQuickPickItem(commit)); items.push(new ApplyCommitFileChangesCommandQuickPickItem(commit));
} }
if (commit.previousFileShortSha) {
if (commit.previousFileSha) {
const commandArgs: DiffWithPreviousCommandArgs = { const commandArgs: DiffWithPreviousCommandArgs = {
commit: commit commit: commit
}; };
@ -123,9 +123,9 @@ export class CommitFileQuickPick {
new CommandQuickPickItem( new CommandQuickPickItem(
{ {
label: '$(git-compare) Open Changes', label: '$(git-compare) Open Changes',
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${
commit.previousFileShortSha
} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}`
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${GitService.shortenSha(
commit.previousFileSha
)} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}`
}, },
Commands.DiffWithPrevious, Commands.DiffWithPrevious,
[commit.uri, commandArgs] [commit.uri, commandArgs]

+ 108
- 136
src/quickpicks/commitQuickPick.ts View File

@ -18,11 +18,12 @@ import {
GitFileStatus, GitFileStatus,
GitLog, GitLog,
GitLogCommit, GitLogCommit,
GitService,
GitStashCommit, GitStashCommit,
GitUri, GitUri,
RemoteResourceType RemoteResourceType
} from '../git/gitService'; } from '../git/gitService';
import { KeyCommand, KeyNoopCommand, Keys } from '../keyboard';
import { KeyNoopCommand, Keys } from '../keyboard';
import { Arrays, Iterables, Strings } from '../system'; import { Arrays, Iterables, Strings } from '../system';
import { import {
CommandQuickPickItem, CommandQuickPickItem,
@ -106,14 +107,105 @@ export class OpenCommitFileRevisionsCommandQuickPickItem extends OpenFilesComman
} }
} }
export interface CommitQuickPickOptions {
currentCommand?: CommandQuickPickItem;
goBackCommand?: CommandQuickPickItem;
repoLog?: GitLog;
}
export class CommitQuickPick { export class CommitQuickPick {
static async show(
constructor(public readonly repoPath: string | undefined) {}
async show(
commit: GitLogCommit, commit: GitLogCommit,
uri: Uri, uri: Uri,
goBackCommand?: CommandQuickPickItem,
currentCommand?: CommandQuickPickItem,
repoLog?: GitLog
options: CommitQuickPickOptions = {}
): Promise<CommitWithFileStatusQuickPickItem | CommandQuickPickItem | undefined> { ): Promise<CommitWithFileStatusQuickPickItem | CommandQuickPickItem | undefined> {
let previousCommand: (() => Promise<KeyCommandQuickPickItem | typeof KeyNoopCommand>) | undefined = undefined;
let nextCommand: (() => Promise<KeyCommandQuickPickItem | typeof KeyNoopCommand>) | undefined = undefined;
if (!commit.isStash) {
previousCommand = async () => {
const previousRef =
commit.previousSha === undefined || GitService.isShaParent(commit.previousSha)
? await Container.git.resolveReference(commit.repoPath, commit.previousSha || `${commit.sha}`)
: commit.previousSha;
if (previousRef === undefined) return KeyNoopCommand;
const previousCommandArgs: ShowQuickCommitDetailsCommandArgs = {
repoLog: options.repoLog,
sha: previousRef,
goBackCommand: options.goBackCommand
};
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
Uri.file(commit.repoPath),
previousCommandArgs
]);
};
nextCommand = async () => {
let log = options.repoLog;
let c = log && log.commits.get(commit.sha);
// If we can't find the commit or the next commit isn't available (since it isn't trustworthy)
if (c === undefined || c.nextSha === undefined) {
log = undefined;
c = undefined;
// Try to find the next commit
const nextLog = await Container.git.getLog(commit.repoPath, {
maxCount: 1,
reverse: true,
ref: commit.sha
});
const next = nextLog && Iterables.first(nextLog.commits.values());
if (next !== undefined && next.sha !== commit.sha) {
c = commit;
c.nextSha = next.sha;
}
}
if (c === undefined || c.nextSha === undefined) return KeyNoopCommand;
const nextCommandArgs: ShowQuickCommitDetailsCommandArgs = {
repoLog: log,
sha: c.nextSha,
goBackCommand: options.goBackCommand
};
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
Uri.file(commit.repoPath),
nextCommandArgs
]);
};
}
const scope = await Container.keyboard.beginScope({
left: options.goBackCommand,
',': previousCommand,
'.': nextCommand
});
const pick = await window.showQuickPick(this.getItems(commit, uri, options), {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: `${commit.shortSha} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${
commit.author ? `${commit.author}, ` : ''
}${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getShortMessage()}`,
ignoreFocusOut: getQuickPickIgnoreFocusOut(),
onDidSelectItem: (item: QuickPickItem) => {
void scope.setKeyCommand('right', item);
if (typeof item.onDidSelect === 'function') {
item.onDidSelect();
}
}
});
await scope.dispose();
return pick;
}
private async getItems(commit: GitLogCommit, uri: Uri, options: CommitQuickPickOptions = {}) {
const items: (CommitWithFileStatusQuickPickItem | CommandQuickPickItem)[] = commit.files.map( const items: (CommitWithFileStatusQuickPickItem | CommandQuickPickItem)[] = commit.files.map(
fs => new CommitWithFileStatusQuickPickItem(commit, fs) fs => new CommitWithFileStatusQuickPickItem(commit, fs)
); );
@ -127,7 +219,7 @@ export class CommitQuickPick {
confirm: true, confirm: true,
deleteAfter: false, deleteAfter: false,
stashItem: commit as GitStashCommit, stashItem: commit as GitStashCommit,
goBackCommand: currentCommand
goBackCommand: options.currentCommand
}; };
items.splice( items.splice(
index++, index++,
@ -145,7 +237,7 @@ export class CommitQuickPick {
const stashDeleteCommmandArgs: StashDeleteCommandArgs = { const stashDeleteCommmandArgs: StashDeleteCommandArgs = {
confirm: true, confirm: true,
stashItem: commit as GitStashCommit, stashItem: commit as GitStashCommit,
goBackCommand: currentCommand
goBackCommand: options.currentCommand
}; };
items.splice( items.splice(
index++, index++,
@ -176,7 +268,7 @@ export class CommitQuickPick {
type: RemoteResourceType.Commit, type: RemoteResourceType.Commit,
sha: commit.sha sha: commit.sha
}, },
currentCommand
options.currentCommand
) )
); );
} }
@ -195,9 +287,9 @@ export class CommitQuickPick {
new CommandQuickPickItem( new CommandQuickPickItem(
{ {
label: '$(git-compare) Open Directory Compare with Previous Revision', label: '$(git-compare) Open Directory Compare with Previous Revision',
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.previousFileShortSha} ${
GlyphChars.Space
} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}`
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${GitService.shortenSha(
commit.previousFileSha
)} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}`
}, },
Commands.DiffDirectory, Commands.DiffDirectory,
[commit.uri, diffDirectoryCommmandArgs] [commit.uri, diffDirectoryCommmandArgs]
@ -259,9 +351,9 @@ export class CommitQuickPick {
const commitDetailsCommandArgs: ShowQuickCommitDetailsCommandArgs = { const commitDetailsCommandArgs: ShowQuickCommitDetailsCommandArgs = {
commit: commit, commit: commit,
repoLog: repoLog,
repoLog: options.repoLog,
sha: commit.sha, sha: commit.sha,
goBackCommand: goBackCommand
goBackCommand: options.goBackCommand
}; };
items.splice( items.splice(
index++, index++,
@ -276,130 +368,10 @@ export class CommitQuickPick {
) )
); );
if (goBackCommand) {
items.splice(0, 0, goBackCommand);
if (options.goBackCommand) {
items.splice(0, 0, options.goBackCommand);
} }
let previousCommand: KeyCommand | (() => Promise<KeyCommand>) | undefined = undefined;
let nextCommand: KeyCommand | (() => Promise<KeyCommand>) | undefined = undefined;
if (!stash) {
// If we have the full history, we are good
if (repoLog !== undefined && !repoLog.truncated && repoLog.sha === undefined) {
const previousCommandArgs: ShowQuickCommitDetailsCommandArgs = {
repoLog: repoLog,
sha: commit.previousSha,
goBackCommand: goBackCommand
};
previousCommand =
commit.previousSha === undefined
? undefined
: new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
commit.previousUri,
previousCommandArgs
]);
const nextCommandArgs: ShowQuickCommitDetailsCommandArgs = {
repoLog: repoLog,
sha: commit.nextSha,
goBackCommand: goBackCommand
};
nextCommand =
commit.nextSha === undefined
? undefined
: new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
commit.nextUri,
nextCommandArgs
]);
}
else {
previousCommand = async () => {
let log = repoLog;
let c = log && log.commits.get(commit.sha);
// If we can't find the commit or the previous commit isn't available (since it isn't trustworthy)
if (c === undefined || c.previousSha === undefined) {
log = await Container.git.getLog(commit.repoPath, {
maxCount: Container.config.advanced.maxListItems,
ref: commit.sha
});
c = log && log.commits.get(commit.sha);
if (c) {
// Copy over next info, since it is trustworthy at this point
c.nextSha = commit.nextSha;
}
}
if (c === undefined || c.previousSha === undefined) return KeyNoopCommand;
const previousCommandArgs: ShowQuickCommitDetailsCommandArgs = {
repoLog: log,
sha: c.previousSha,
goBackCommand: goBackCommand
};
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [
c.previousUri,
previousCommandArgs
]);
};
nextCommand = async () => {
let log = repoLog;
let c = log && log.commits.get(commit.sha);
// If we can't find the commit or the next commit isn't available (since it isn't trustworthy)
if (c === undefined || c.nextSha === undefined) {
log = undefined;
c = undefined;
// Try to find the next commit
const nextLog = await Container.git.getLog(commit.repoPath, {
maxCount: 1,
reverse: true,
ref: commit.sha
});
const next = nextLog && Iterables.first(nextLog.commits.values());
if (next !== undefined && next.sha !== commit.sha) {
c = commit;
c.nextSha = next.sha;
}
}
if (c === undefined || c.nextSha === undefined) return KeyNoopCommand;
const nextCommandArgs: ShowQuickCommitDetailsCommandArgs = {
repoLog: log,
sha: c.nextSha,
goBackCommand: goBackCommand
};
return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [c.nextUri, nextCommandArgs]);
};
}
}
const scope = await Container.keyboard.beginScope({
left: goBackCommand,
',': previousCommand,
'.': nextCommand
});
const pick = await window.showQuickPick(items, {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: `${commit.shortSha} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${
commit.author ? `${commit.author}, ` : ''
}${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getShortMessage()}`,
ignoreFocusOut: getQuickPickIgnoreFocusOut(),
onDidSelectItem: (item: QuickPickItem) => {
void scope.setKeyCommand('right', item);
if (typeof item.onDidSelect === 'function') {
item.onDidSelect();
}
}
});
await scope.dispose();
return pick;
return items;
} }
} }

+ 2
- 2
src/system/iterable.ts View File

@ -112,8 +112,8 @@ export namespace Iterables {
return value; return value;
} }
export function last<T>(source: Iterable<T>): T | null {
let item: T | null = null;
export function last<T>(source: Iterable<T>): T | undefined {
let item: T | undefined;
for (item of source) { for (item of source) {
/* noop */ /* noop */
} }

Loading…
Cancel
Save