From 7a51946eda8262d1bd9505b62b0bd1b17290e7b4 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Sun, 19 Mar 2017 01:16:19 -0400 Subject: [PATCH] Adds working filename detection method Adds get current branch method Fixes diff with working tree when file was renamed Fixes various quick pick commands when file was renamed Adds branch support to ShowQuickRepoHistory Adds branch info to repo quick pick placeholder Adds Show Branch History to commit limited branch history quick pick Adds Show File History to commit limited file history quick pick Removes conditional display of commit details on commit file details quick pick Removes conditional display of show file history on commit file details quick pick Fixed #30 - Diff with Working Tree fails from repo/commit quickpick list if file was renamed (and the commit was before the rename) --- src/commands/diffWithWorking.ts | 4 ++- src/commands/showQuickCommitDetails.ts | 7 ++++ src/commands/showQuickCommitFileDetails.ts | 18 +++++----- src/commands/showQuickFileHistory.ts | 7 ++-- src/commands/showQuickRepoHistory.ts | 24 +++++++------ src/gitService.ts | 58 +++++++++++++++++++++--------- src/quickPicks/commitDetails.ts | 2 +- src/quickPicks/commitFileDetails.ts | 42 +++++++++++----------- src/quickPicks/fileHistory.ts | 43 ++++++++++++++++------ src/quickPicks/repoHistory.ts | 43 ++++++++++++++++------ 10 files changed, 163 insertions(+), 85 deletions(-) diff --git a/src/commands/diffWithWorking.ts b/src/commands/diffWithWorking.ts index 66e5579..84e3ff0 100644 --- a/src/commands/diffWithWorking.ts +++ b/src/commands/diffWithWorking.ts @@ -40,9 +40,11 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand { const gitUri = await GitUri.fromUri(uri, this.git); + const workingFileName = await this.git.findWorkingFileName(gitUri.repoPath, gitUri.fsPath); + try { const compare = await this.git.getVersionedFile(commit.repoPath, commit.uri.fsPath, commit.sha); - await commands.executeCommand(BuiltInCommands.Diff, Uri.file(compare), gitUri.fileUri(), `${path.basename(commit.uri.fsPath)} (${commit.shortSha}) ↔ ${path.basename(gitUri.fsPath)}`); + await commands.executeCommand(BuiltInCommands.Diff, Uri.file(compare), Uri.file(path.resolve(gitUri.repoPath, workingFileName)), `${path.basename(commit.uri.fsPath)} (${commit.shortSha}) ↔ ${path.basename(workingFileName)}`); return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: line, at: 'center' }); } catch (ex) { diff --git a/src/commands/showQuickCommitDetails.ts b/src/commands/showQuickCommitDetails.ts index 97bb2e6..7336658 100644 --- a/src/commands/showQuickCommitDetails.ts +++ b/src/commands/showQuickCommitDetails.ts @@ -4,6 +4,7 @@ import { ActiveEditorCommand, Commands } from './commands'; import { GitCommit, GitLogCommit, GitService, GitUri, IGitLog } from '../gitService'; import { Logger } from '../logger'; import { CommandQuickPickItem, CommitDetailsQuickPick, CommitWithFileStatusQuickPickItem } from '../quickPicks'; +import * as path from 'path'; export class ShowQuickCommitDetailsCommand extends ActiveEditorCommand { @@ -20,6 +21,7 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCommand { const gitUri = await GitUri.fromUri(uri, this.git); let repoPath = gitUri.repoPath; + let workingFileName = path.relative(repoPath, gitUri.fsPath); if (!sha) { if (!editor) return undefined; @@ -33,6 +35,7 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCommand { sha = blame.commit.isUncommitted ? blame.commit.previousSha : blame.commit.sha; repoPath = blame.commit.repoPath; + workingFileName = blame.commit.fileName; commit = blame.commit; } @@ -60,6 +63,10 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCommand { } } + if (!commit.workingFileName) { + commit.workingFileName = workingFileName; + } + if (!goBackCommand) { // Create a command to get back to the branch history goBackCommand = new CommandQuickPickItem({ diff --git a/src/commands/showQuickCommitFileDetails.ts b/src/commands/showQuickCommitFileDetails.ts index 427b64c..b14ed07 100644 --- a/src/commands/showQuickCommitFileDetails.ts +++ b/src/commands/showQuickCommitFileDetails.ts @@ -12,12 +12,14 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCommand { super(Commands.ShowQuickCommitFileDetails); } - async execute(editor: TextEditor, uri?: Uri, sha?: string, commit?: GitCommit | GitLogCommit, goBackCommand?: CommandQuickPickItem, options: { showFileHistory?: boolean } = { showFileHistory: true }, fileLog?: IGitLog) { + async execute(editor: TextEditor, uri?: Uri, sha?: string, commit?: GitCommit | GitLogCommit, goBackCommand?: CommandQuickPickItem, fileLog?: IGitLog) { if (!(uri instanceof Uri)) { if (!editor || !editor.document) return undefined; uri = editor.document.uri; } + let workingFileName = commit && commit.workingFileName; + if (!sha) { if (!editor) return undefined; @@ -33,6 +35,7 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCommand { sha = blame.commit.isUncommitted ? blame.commit.previousSha : blame.commit.sha; commit = blame.commit; + workingFileName = path.relative(commit.repoPath, gitUri.fsPath); } catch (ex) { Logger.error('[GitLens.ShowQuickCommitFileDetailsCommand]', `getBlameForLine(${blameline})`, ex); @@ -51,7 +54,7 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCommand { } if (!fileLog) { - const log = await this.git.getLogForFile(undefined, uri.fsPath, sha, undefined, 2); + const log = await this.git.getLogForFile(undefined, commit ? commit.uri.fsPath : uri.fsPath, sha, undefined, 2); if (!log) return window.showWarningMessage(`Unable to show commit file details`); commit = log.commits.get(sha); @@ -59,9 +62,8 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCommand { } // Attempt to the most recent commit -- so that we can find the real working filename if there was a rename - const workingCommit = await this.git.findMostRecentCommitForFile(commit.uri.fsPath, commit.sha); - // TODO: Leave this at undefined until findMostRecentCommitForFile actually works - const workingFileName = !workingCommit ? commit.fileName : undefined; + commit.workingFileName = workingFileName; + commit.workingFileName = await this.git.findWorkingFileName(commit); const shortSha = sha.substring(0, 8); @@ -73,13 +75,13 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCommand { }, Commands.ShowQuickCommitDetails, [new GitUri(commit.uri, commit), sha, commit]); } - const pick = await CommitFileDetailsQuickPick.show(this.git, commit as GitLogCommit, workingFileName, uri, goBackCommand, + const pick = await CommitFileDetailsQuickPick.show(this.git, commit as GitLogCommit, uri, goBackCommand, // Create a command to get back to where we are right now new CommandQuickPickItem({ label: `go back \u21A9`, description: `\u00a0 \u2014 \u00a0\u00a0 to details of \u00a0$(file-text) ${path.basename(commit.fileName)} in \u00a0$(git-commit) ${shortSha}` - }, Commands.ShowQuickCommitFileDetails, [new GitUri(commit.uri, commit), sha, commit, goBackCommand, options]), - { showFileHistory: options.showFileHistory }, fileLog); + }, Commands.ShowQuickCommitFileDetails, [new GitUri(commit.uri, commit), sha, commit, goBackCommand]), + fileLog); if (!pick) return undefined; diff --git a/src/commands/showQuickFileHistory.ts b/src/commands/showQuickFileHistory.ts index f62ad85..ac9f7d0 100644 --- a/src/commands/showQuickFileHistory.ts +++ b/src/commands/showQuickFileHistory.ts @@ -34,7 +34,7 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCommand { if (progressCancellation.token.isCancellationRequested) return undefined; - const pick = await FileHistoryQuickPick.show(log, gitUri, progressCancellation, goBackCommand, nextPageCommand); + const pick = await FileHistoryQuickPick.show(this.git, log, gitUri, progressCancellation, goBackCommand, nextPageCommand); if (!pick) return undefined; if (pick instanceof CommandQuickPickItem) { @@ -44,9 +44,8 @@ export class ShowQuickFileHistoryCommand extends ActiveEditorCommand { return commands.executeCommand(Commands.ShowQuickCommitFileDetails, new GitUri(pick.commit.uri, pick.commit), pick.commit.sha, pick.commit, new CommandQuickPickItem({ label: `go back \u21A9`, - description: `\u00a0 \u2014 \u00a0\u00a0 to history of \u00a0$(file-text) ${path.basename(pick.commit.fileName)}` - }, Commands.ShowQuickFileHistory, [uri, undefined, maxCount, goBackCommand, log]), - { showFileHistory: false }, + description: `\u00a0 \u2014 \u00a0\u00a0 to history of \u00a0$(file-text) ${path.basename(pick.commit.fileName)}${gitUri.sha ? ` from \u00a0$(git-commit) ${gitUri.shortSha}` : ''}` + }, Commands.ShowQuickFileHistory, [uri, range, maxCount, goBackCommand, log]), log); } catch (ex) { diff --git a/src/commands/showQuickRepoHistory.ts b/src/commands/showQuickRepoHistory.ts index 8e92525..ff631fe 100644 --- a/src/commands/showQuickRepoHistory.ts +++ b/src/commands/showQuickRepoHistory.ts @@ -11,7 +11,7 @@ export class ShowQuickRepoHistoryCommand extends ActiveEditorCommand { super(Commands.ShowQuickRepoHistory); } - async execute(editor: TextEditor, uri?: Uri, maxCount?: number, goBackCommand?: CommandQuickPickItem, log?: IGitLog, nextPageCommand?: CommandQuickPickItem) { + async execute(editor: TextEditor, uri?: Uri, branch?: string, maxCount?: number, goBackCommand?: CommandQuickPickItem, log?: IGitLog, nextPageCommand?: CommandQuickPickItem) { if (!(uri instanceof Uri)) { uri = editor && editor.document && editor.document.uri; } @@ -22,21 +22,23 @@ export class ShowQuickRepoHistoryCommand extends ActiveEditorCommand { maxCount = this.git.config.advanced.maxQuickHistory; } - const progressCancellation = RepoHistoryQuickPick.showProgress(); + branch = branch || (await this.git.getBranch(this.git.repoPath)).name; + + const progressCancellation = RepoHistoryQuickPick.showProgress(branch); try { - if (!log) { - const repoPath = (gitUri && gitUri.repoPath) || await this.git.getRepoPathFromUri(uri, this.repoPath); - if (!repoPath) return window.showWarningMessage(`Unable to show repository history`); + const repoPath = (gitUri && gitUri.repoPath) || await this.git.getRepoPathFromUri(uri, this.repoPath); + if (!repoPath) return window.showWarningMessage(`Unable to show history`); - if (progressCancellation.token.isCancellationRequested) return undefined; + if (progressCancellation.token.isCancellationRequested) return undefined; - log = await this.git.getLogForRepo(repoPath, (gitUri && gitUri.sha), maxCount); - if (!log) return window.showWarningMessage(`Unable to show repository history`); + if (!log) { + log = await this.git.getLogForRepo(repoPath, (gitUri && gitUri.sha) || branch, maxCount); + if (!log) return window.showWarningMessage(`Unable to show history`); } if (progressCancellation.token.isCancellationRequested) return undefined; - const pick = await RepoHistoryQuickPick.show(log, gitUri, progressCancellation, goBackCommand, nextPageCommand); + const pick = await RepoHistoryQuickPick.show(log, gitUri, branch, progressCancellation, goBackCommand, nextPageCommand); if (!pick) return undefined; if (pick instanceof CommandQuickPickItem) { @@ -46,8 +48,8 @@ export class ShowQuickRepoHistoryCommand extends ActiveEditorCommand { return commands.executeCommand(Commands.ShowQuickCommitDetails, new GitUri(pick.commit.uri, pick.commit), pick.commit.sha, pick.commit, new CommandQuickPickItem({ label: `go back \u21A9`, - description: `\u00a0 \u2014 \u00a0\u00a0 to branch history` - }, Commands.ShowQuickRepoHistory, [uri, maxCount, goBackCommand, log]), + description: `\u00a0 \u2014 \u00a0\u00a0 to \u00a0$(git-branch) ${branch} history` + }, Commands.ShowQuickRepoHistory, [uri, branch, maxCount, goBackCommand, log]), log); } catch (ex) { diff --git a/src/gitService.ts b/src/gitService.ts index e9cd4a2..02b20ed 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -225,28 +225,44 @@ export class GitService extends Disposable { } } - async findMostRecentCommitForFile(fileName: string, sha?: string): Promise { - const exists = await new Promise((resolve, reject) => fs.exists(fileName, e => resolve(e))); - if (exists) return null; + async findWorkingFileName(commit: GitCommit): Promise; + async findWorkingFileName(repoPath: string, fileName: string): Promise + async findWorkingFileName(commitOrRepoPath: GitCommit | string, fileName?: string): Promise { + let repoPath: string; + if (typeof commitOrRepoPath === 'string') { + repoPath = commitOrRepoPath; + [fileName] = Git.splitPath(fileName, repoPath); + } + else { + const c = commitOrRepoPath; + repoPath = c.repoPath; + if (c.workingFileName && await this._fileExists(repoPath, c.workingFileName)) return c.workingFileName; + fileName = c.fileName; + } - return undefined; + while (true) { + if (await this._fileExists(repoPath, fileName)) return fileName; - // TODO: Get this to work -- for some reason a reverse log won't return the renamed file - // Not sure how else to figure this out + // Get the most recent commit for this file name + let log = await this.getLogForFile(repoPath, fileName, undefined, undefined, 1); + if (!log) return undefined; - // let log: IGitLog; - // let commit: GitCommit; - // while (true) { - // // Go backward from the current commit to head to find the latest filename - // log = await this.getLogForFile(undefined, fileName, sha, undefined, undefined, true); - // if (!log) break; + let c = Iterables.first(log.commits.values()); - // commit = Iterables.first(log.commits.values()); - // sha = commit.sha; - // fileName = commit.fileName; - // } + // Get the full commit (so we can see if there are any matching renames in the file statuses) + log = await this.getLogForRepo(repoPath, c.sha, 1); + if (!log) return undefined; - // return commit; + c = Iterables.first(log.commits.values()); + const status = c.fileStatuses.find(_ => _.originalFileName === fileName); + if (!status) return undefined; + + fileName = status.fileName; + } + } + + private async _fileExists(repoPath: string, fileName: string): Promise { + return await new Promise((resolve, reject) => fs.exists(path.resolve(repoPath, fileName), e => resolve(e))); } public getBlameability(fileName: string): boolean { @@ -441,6 +457,14 @@ export class GitService extends Disposable { return locations; } + async getBranch(repoPath: string): Promise { + Logger.log(`getBranch('${repoPath}')`); + + const data = await Git.branch(repoPath, false); + const branches = data.split('\n').filter(_ => !!_).map(_ => new GitBranch(_)); + return branches.find(_ => _.current); + } + async getBranches(repoPath: string): Promise { Logger.log(`getBranches('${repoPath}')`); diff --git a/src/quickPicks/commitDetails.ts b/src/quickPicks/commitDetails.ts index 019a511..97592c2 100644 --- a/src/quickPicks/commitDetails.ts +++ b/src/quickPicks/commitDetails.ts @@ -130,7 +130,7 @@ export class CommitDetailsQuickPick { const pick = await window.showQuickPick(items, { matchOnDescription: true, matchOnDetail: true, - placeHolder: `${commit.shortSha} \u2022 ${commit.author}, ${moment(commit.date).fromNow()} \u2022 ${commit.message}`, + placeHolder: `${commit.shortSha} \u00a0\u2022\u00a0 ${commit.author}, ${moment(commit.date).fromNow()} \u00a0\u2022\u00a0 ${commit.message}`, ignoreFocusOut: getQuickPickIgnoreFocusOut(), onDidSelectItem: (item: QuickPickItem) => { scope.setKeyCommand('right', item); diff --git a/src/quickPicks/commitFileDetails.ts b/src/quickPicks/commitFileDetails.ts index 76a0789..3c8606d 100644 --- a/src/quickPicks/commitFileDetails.ts +++ b/src/quickPicks/commitFileDetails.ts @@ -31,10 +31,10 @@ export class OpenCommitWorkingTreeFileCommandQuickPickItem extends OpenFileComma export class CommitFileDetailsQuickPick { - static async show(git: GitService, commit: GitLogCommit, workingFileName: string, uri: Uri, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem, options: { showFileHistory?: boolean } = {}, fileLog?: IGitLog): Promise { + static async show(git: GitService, commit: GitLogCommit, uri: Uri, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem, fileLog?: IGitLog): Promise { const items: CommandQuickPickItem[] = []; - const workingName = (workingFileName && path.basename(workingFileName)) || path.basename(commit.fileName); + const workingName = (commit.workingFileName && path.basename(commit.workingFileName)) || path.basename(commit.fileName); const isUncommitted = commit.isUncommitted; if (isUncommitted) { @@ -45,12 +45,10 @@ export class CommitFileDetailsQuickPick { commit = Iterables.first(log.commits.values()); } - if (!options.showFileHistory) { - items.push(new CommandQuickPickItem({ - label: `$(git-commit) Show Commit Details`, - description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.shortSha}` - }, Commands.ShowQuickCommitDetails, [new GitUri(commit.uri, commit), commit.sha, commit, currentCommand])); - } + items.push(new CommandQuickPickItem({ + label: `$(git-commit) Show Commit Details`, + description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.shortSha}` + }, Commands.ShowQuickCommitDetails, [new GitUri(commit.uri, commit), commit.sha, commit, currentCommand])); if (commit.previousSha) { items.push(new CommandQuickPickItem({ @@ -59,10 +57,12 @@ export class CommitFileDetailsQuickPick { }, Commands.DiffWithPrevious, [commit.uri, commit])); } - items.push(new CommandQuickPickItem({ - label: `$(git-compare) Compare with Working Tree`, - description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.shortSha} \u00a0 $(git-compare) \u00a0 $(file-text) ${workingName}` - }, Commands.DiffWithWorking, [uri, commit])); + if (commit.workingFileName) { + items.push(new CommandQuickPickItem({ + label: `$(git-compare) Compare with Working Tree`, + description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.shortSha} \u00a0 $(git-compare) \u00a0 $(file-text) ${workingName}` + }, Commands.DiffWithWorking, [Uri.file(path.resolve(commit.repoPath, commit.workingFileName)), commit])); + } items.push(new CommandQuickPickItem({ label: `$(clippy) Copy Commit Sha to Clipboard`, @@ -77,16 +77,16 @@ export class CommitFileDetailsQuickPick { items.push(new OpenCommitFileCommandQuickPickItem(commit)); items.push(new OpenCommitWorkingTreeFileCommandQuickPickItem(commit)); - if (workingFileName && options.showFileHistory) { + if (commit.workingFileName) { items.push(new CommandQuickPickItem({ label: `$(history) Show File History`, description: `\u00a0 \u2014 \u00a0\u00a0 of ${path.basename(commit.fileName)}` - }, Commands.ShowQuickFileHistory, [commit.uri, undefined, undefined, currentCommand, fileLog])); + }, Commands.ShowQuickFileHistory, [Uri.file(path.resolve(commit.repoPath, commit.workingFileName)), undefined, undefined, currentCommand, fileLog])); } items.push(new CommandQuickPickItem({ - label: `$(history) Show ${workingFileName && options.showFileHistory ? 'Previous ' : ''}File History`, - description: `\u00a0 \u2014 \u00a0\u00a0 of ${path.basename(commit.fileName)} \u00a0\u2022\u00a0 starting from \u00a0$(git-commit) ${commit.shortSha}` + label: `$(history) Show ${commit.workingFileName ? 'Previous ' : ''}File History`, + description: `\u00a0 \u2014 \u00a0\u00a0 of ${path.basename(commit.fileName)} \u00a0\u2022\u00a0 from \u00a0$(git-commit) ${commit.shortSha}` }, Commands.ShowQuickFileHistory, [new GitUri(commit.uri, commit), undefined, undefined, currentCommand])); if (goBackCommand) { @@ -97,8 +97,8 @@ export class CommitFileDetailsQuickPick { let nextCommand: CommandQuickPickItem | (() => Promise); // If we have the full history, we are good if (fileLog && !fileLog.truncated) { - previousCommand = commit.previousSha && new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [commit.previousUri, commit.previousSha, undefined, goBackCommand, options, fileLog]); - nextCommand = commit.nextSha && new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [commit.nextUri, commit.nextSha, undefined, goBackCommand, options, fileLog]); + previousCommand = commit.previousSha && new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [commit.previousUri, commit.previousSha, undefined, goBackCommand, fileLog]); + nextCommand = commit.nextSha && new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [commit.nextUri, commit.nextSha, undefined, goBackCommand, fileLog]); } else { previousCommand = async () => { @@ -117,7 +117,7 @@ export class CommitFileDetailsQuickPick { } } if (!c) return KeyNoopCommand; - return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [c.previousUri, c.previousSha, undefined, goBackCommand, options, log]); + return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [c.previousUri, c.previousSha, undefined, goBackCommand, log]); }; nextCommand = async () => { @@ -139,7 +139,7 @@ export class CommitFileDetailsQuickPick { } } if (!c) return KeyNoopCommand; - return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [c.nextUri, c.nextSha, undefined, goBackCommand, options, log]); + return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [c.nextUri, c.nextSha, undefined, goBackCommand, log]); }; } @@ -151,7 +151,7 @@ export class CommitFileDetailsQuickPick { const pick = await window.showQuickPick(items, { matchOnDescription: true, - placeHolder: `${commit.getFormattedPath()} \u2022 ${isUncommitted ? 'Uncommitted \u21E8 ' : '' }${commit.shortSha} \u2022 ${commit.author}, ${moment(commit.date).fromNow()} \u2022 ${commit.message}`, + placeHolder: `${commit.getFormattedPath()} \u00a0\u2022\u00a0 ${isUncommitted ? 'Uncommitted \u21E8 ' : '' }${commit.shortSha} \u00a0\u2022\u00a0 ${commit.author}, ${moment(commit.date).fromNow()} \u00a0\u2022\u00a0 ${commit.message}`, ignoreFocusOut: getQuickPickIgnoreFocusOut(), onDidSelectItem: (item: QuickPickItem) => { scope.setKeyCommand('right', item); diff --git a/src/quickPicks/fileHistory.ts b/src/quickPicks/fileHistory.ts index 9bdbe65..7602dda 100644 --- a/src/quickPicks/fileHistory.ts +++ b/src/quickPicks/fileHistory.ts @@ -2,7 +2,7 @@ import { Iterables } from '../system'; import { CancellationTokenSource, QuickPickOptions, Uri, window } from 'vscode'; import { Commands, Keyboard, KeyNoopCommand } from '../commands'; -import { GitUri, IGitLog } from '../gitService'; +import { GitService, GitUri, IGitLog } from '../gitService'; import { CommitQuickPickItem } from './gitQuickPicks'; import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './quickPicks'; import * as path from 'path'; @@ -10,7 +10,7 @@ import * as path from 'path'; export class FileHistoryQuickPick { static showProgress(uri: GitUri) { - return showQuickPickProgress(`${uri.getFormattedPath()}${uri.sha ? ` \u00a0\u2022\u00a0 ${uri.sha.substring(0, 8)}` : ''}`, + return showQuickPickProgress(`${uri.getFormattedPath()}${uri.sha ? ` \u00a0\u2022\u00a0 ${uri.shortSha}` : ''}`, { left: KeyNoopCommand, ',': KeyNoopCommand, @@ -18,18 +18,38 @@ export class FileHistoryQuickPick { }); } - static async show(log: IGitLog, uri: GitUri, progressCancellation: CancellationTokenSource, goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem): Promise { + static async show(git: GitService, log: IGitLog, uri: GitUri, progressCancellation: CancellationTokenSource, goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem): Promise { const items = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))) as (CommitQuickPickItem | CommandQuickPickItem)[]; let previousPageCommand: CommandQuickPickItem; let index = 0; if (log.truncated || uri.sha) { - index++; - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(sync) Show All Commits`, - description: `\u00a0 \u2014 \u00a0\u00a0 this may take a while` - }, Commands.ShowQuickFileHistory, [Uri.file(uri.fsPath), undefined, 0, goBackCommand])); + if (log.truncated) { + index++; + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(sync) Show All Commits`, + description: `\u00a0 \u2014 \u00a0\u00a0 this may take a while` + }, Commands.ShowQuickFileHistory, [Uri.file(uri.fsPath), undefined, 0, goBackCommand])); + } + else { + const workingFileName = await git.findWorkingFileName(log.repoPath, path.relative(log.repoPath, uri.fsPath)); + if (workingFileName) { + index++; + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(history) Show File History`, + description: `\u00a0 \u2014 \u00a0\u00a0 of ${path.basename(workingFileName)}` + }, Commands.ShowQuickFileHistory, [ + Uri.file(path.resolve(log.repoPath, workingFileName)), + undefined, + undefined, + new CommandQuickPickItem({ + label: `go back \u21A9`, + description: `\u00a0 \u2014 \u00a0\u00a0 to history of \u00a0$(file-text) ${path.basename(uri.fsPath)}${uri.sha ? ` from \u00a0$(git-commit) ${uri.shortSha}` : ''}` + }, Commands.ShowQuickFileHistory, [uri, log.range, log.maxCount, goBackCommand, log]) + ])); + } + } if (nextPageCommand) { index++; @@ -63,10 +83,11 @@ export class FileHistoryQuickPick { [ undefined, undefined, + undefined, new CommandQuickPickItem({ label: `go back \u21A9`, - description: `\u00a0 \u2014 \u00a0\u00a0 to history of \u00a0$(file-text) ${path.basename(uri.fsPath)}` - }, Commands.ShowQuickFileHistory, [uri, undefined, log.maxCount, undefined, log]) + description: `\u00a0 \u2014 \u00a0\u00a0 to history of \u00a0$(file-text) ${path.basename(uri.fsPath)}${uri.sha ? ` from \u00a0$(git-commit) ${uri.shortSha}` : ''}` + }, Commands.ShowQuickFileHistory, [uri, log.range, log.maxCount, undefined, log]) ])); } @@ -89,7 +110,7 @@ export class FileHistoryQuickPick { const pick = await window.showQuickPick(items, { matchOnDescription: true, matchOnDetail: true, - placeHolder: `${commit.getFormattedPath()}${uri.sha ? ` \u00a0\u2022\u00a0 ${uri.sha.substring(0, 8)}` : ''}`, + placeHolder: `${commit.getFormattedPath()}${uri.sha ? ` \u00a0\u2022\u00a0 ${uri.shortSha}` : ''}`, ignoreFocusOut: getQuickPickIgnoreFocusOut() // onDidSelectItem: (item: QuickPickItem) => { // scope.setKeyCommand('right', item); diff --git a/src/quickPicks/repoHistory.ts b/src/quickPicks/repoHistory.ts index 21a6ca1..fbb6bbe 100644 --- a/src/quickPicks/repoHistory.ts +++ b/src/quickPicks/repoHistory.ts @@ -8,8 +8,8 @@ import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress export class RepoHistoryQuickPick { - static showProgress() { - return showQuickPickProgress('Repository history \u2014 search by commit message, filename, or sha', + static showProgress(branch: string) { + return showQuickPickProgress(`${branch} history \u2014 search by commit message, filename, or sha`, { left: KeyNoopCommand, ',': KeyNoopCommand, @@ -17,16 +17,37 @@ export class RepoHistoryQuickPick { }); } - static async show(log: IGitLog, uri: GitUri, progressCancellation: CancellationTokenSource, goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem): Promise { + static async show(log: IGitLog, uri: GitUri, branch: string, progressCancellation: CancellationTokenSource, goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem): Promise { const items = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c, ` \u2014 ${c.fileNames}`))) as (CommitQuickPickItem | CommandQuickPickItem)[]; let previousPageCommand: CommandQuickPickItem; - if (log.truncated || (uri && uri.sha)) { - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(sync) Show All Commits`, - description: `\u00a0 \u2014 \u00a0\u00a0 this may take a while` - }, Commands.ShowQuickRepoHistory, [uri && Uri.file(uri.fsPath), 0, goBackCommand])); + if ((log.truncated || (uri && uri.sha))) { + if (log.truncated) { + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(sync) Show All Commits`, + description: `\u00a0 \u2014 \u00a0\u00a0 this may take a while` + }, Commands.ShowQuickRepoHistory, [ + new GitUri(Uri.file(log.repoPath), { fileName: '', repoPath: log.repoPath }), + branch, + 0, + goBackCommand + ])); + } + else { + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(history) Show Branch History`, + description: `\u00a0 \u2014 \u00a0\u00a0 shows \u00a0$(git-branch) ${branch} history` + }, Commands.ShowQuickRepoHistory, [ + new GitUri(Uri.file(log.repoPath), { fileName: '', repoPath: log.repoPath }), + branch, + undefined, + new CommandQuickPickItem({ + label: `go back \u21A9`, + description: `\u00a0 \u2014 \u00a0\u00a0 to \u00a0$(git-branch) ${branch} history` + }, Commands.ShowQuickRepoHistory, [uri, branch, log.maxCount, goBackCommand, log]) + ])); + } if (nextPageCommand) { items.splice(0, 0, nextPageCommand); @@ -36,14 +57,14 @@ export class RepoHistoryQuickPick { const npc = new CommandQuickPickItem({ label: `$(arrow-right) Show Next Commits`, description: `\u00a0 \u2014 \u00a0\u00a0 shows ${log.maxCount} newer commits` - }, Commands.ShowQuickRepoHistory, [uri, log.maxCount, goBackCommand, undefined, nextPageCommand]); + }, Commands.ShowQuickRepoHistory, [uri, branch, log.maxCount, goBackCommand, undefined, nextPageCommand]); const last = Iterables.last(log.commits.values()); previousPageCommand = new CommandQuickPickItem({ label: `$(arrow-left) Show Previous Commits`, description: `\u00a0 \u2014 \u00a0\u00a0 shows ${log.maxCount} older commits` - }, Commands.ShowQuickRepoHistory, [new GitUri(uri ? uri : last.uri, last), log.maxCount, goBackCommand, undefined, npc]); + }, Commands.ShowQuickRepoHistory, [new GitUri(uri ? uri : last.uri, last), branch, log.maxCount, goBackCommand, undefined, npc]); items.splice(0, 0, previousPageCommand); } @@ -66,7 +87,7 @@ export class RepoHistoryQuickPick { const pick = await window.showQuickPick(items, { matchOnDescription: true, matchOnDetail: true, - placeHolder: `Branch history \u2014 search by commit message, filename, or sha`, + placeHolder: `${branch} history \u2014 search by commit message, filename, or sha`, ignoreFocusOut: getQuickPickIgnoreFocusOut() // onDidSelectItem: (item: QuickPickItem) => { // scope.setKeyCommand('right', item);