diff --git a/src/git/gitUri.ts b/src/git/gitUri.ts index 327f0cf..c37e2e3 100644 --- a/src/git/gitUri.ts +++ b/src/git/gitUri.ts @@ -23,7 +23,7 @@ export class GitUri extends Uri { this.offset = 0; if (uri.scheme === DocumentSchemes.Git) { - const data = GitProvider.fromGitUri(uri); + const data = GitProvider.fromGitContentUri(uri); base._fsPath = data.originalFileName || data.fileName; this.offset = (data.decoration && data.decoration.split('\n').length) || 0; @@ -72,10 +72,10 @@ export interface IGitCommitInfo { } export interface IGitUriData { - repoPath: string; + sha: string; fileName: string; + repoPath: string; originalFileName?: string; - sha: string; - index: number; + index?: number; decoration?: string; } \ No newline at end of file diff --git a/src/gitContentProvider.ts b/src/gitContentProvider.ts index 91f7010..838b79f 100644 --- a/src/gitContentProvider.ts +++ b/src/gitContentProvider.ts @@ -12,7 +12,7 @@ export default class GitContentProvider implements TextDocumentContentProvider { constructor(context: ExtensionContext, private git: GitProvider) { } async provideTextDocumentContent(uri: Uri): Promise { - const data = GitProvider.fromGitUri(uri); + const data = GitProvider.fromGitContentUri(uri); const fileName = data.originalFileName || data.fileName; try { let text = await this.git.getVersionedFileText(fileName, data.repoPath, data.sha) as string; diff --git a/src/gitProvider.ts b/src/gitProvider.ts index 6a042fb..a6552ea 100644 --- a/src/gitProvider.ts +++ b/src/gitProvider.ts @@ -450,7 +450,7 @@ export default class GitProvider extends Disposable { if (c.isUncommitted) return; const decoration = `\u2937 ${c.author}, ${moment(c.date).format('MMMM Do, YYYY h:MMa')}`; - const uri = GitProvider.toGitUri(c, i + 1, commitCount, c.originalFileName, decoration); + const uri = GitProvider.toReferenceGitContentUri(c, i + 1, commitCount, c.originalFileName, decoration); locations.push(new Location(uri, new Position(0, 0))); if (c.sha === selectedSha) { locations.push(new Location(uri, new Position(line + 1, 0))); @@ -550,7 +550,7 @@ export default class GitProvider extends Disposable { if (c.isUncommitted) return; const decoration = `\u2937 ${c.author}, ${moment(c.date).format('MMMM Do, YYYY h:MMa')}`; - const uri = GitProvider.toGitUri(c, i + 1, commitCount, c.originalFileName, decoration); + const uri = GitProvider.toReferenceGitContentUri(c, i + 1, commitCount, c.originalFileName, decoration); locations.push(new Location(uri, new Position(0, 0))); if (c.sha === selectedSha) { locations.push(new Location(uri, new Position(line + 1, 0))); @@ -614,20 +614,41 @@ export default class GitProvider extends Disposable { return Git.isUncommitted(sha); } - static fromGitUri(uri: Uri): IGitUriData { + static fromGitContentUri(uri: Uri): IGitUriData { if (uri.scheme !== DocumentSchemes.Git) throw new Error(`fromGitUri(uri=${uri}) invalid scheme`); - return GitProvider._fromGitUri(uri); + return GitProvider._fromGitContentUri(uri); } - private static _fromGitUri(uri: Uri): T { + private static _fromGitContentUri(uri: Uri): T { return JSON.parse(uri.query) as T; } - static toGitUri(commit: GitCommit, index: number, commitCount: number, originalFileName?: string, decoration?: string) { - return GitProvider._toGitUri(commit, DocumentSchemes.Git, commitCount, GitProvider._toGitUriData(commit, index, originalFileName, decoration)); + static toGitContentUri(sha: string, fileName: string, repoPath: string, originalFileName: string): Uri; + static toGitContentUri(commit: GitCommit): Uri; + static toGitContentUri(shaOrcommit: string | GitCommit, fileName?: string, repoPath?: string, originalFileName?: string): Uri { + let data: IGitUriData; + if (typeof shaOrcommit === 'string') { + data = GitProvider._toGitUriData({ + sha: shaOrcommit, + fileName: fileName, + repoPath: repoPath, + originalFileName: originalFileName + }); + } + else { + data = GitProvider._toGitUriData(shaOrcommit, undefined, shaOrcommit.originalFileName); + fileName = shaOrcommit.fileName; + } + + const extension = path.extname(fileName); + return Uri.parse(`${DocumentSchemes.Git}:${path.basename(fileName, extension)}:${data.sha}${extension}?${JSON.stringify(data)}`); + } + + static toReferenceGitContentUri(commit: GitCommit, index: number, commitCount: number, originalFileName?: string, decoration?: string): Uri { + return GitProvider._toReferenceGitContentUri(commit, DocumentSchemes.Git, commitCount, GitProvider._toGitUriData(commit, index, originalFileName, decoration)); } - private static _toGitUri(commit: GitCommit, scheme: DocumentSchemes, commitCount: number, data: IGitUriData) { + private static _toReferenceGitContentUri(commit: GitCommit, scheme: DocumentSchemes, commitCount: number, data: IGitUriData) { const pad = (n: number) => ('0000000' + n).slice(-('' + commitCount).length); const ext = path.extname(data.fileName); const uriPath = `${path.relative(commit.repoPath, data.fileName.slice(0, -ext.length))}/${commit.sha}${ext}`; @@ -641,11 +662,11 @@ export default class GitProvider extends Disposable { return Uri.parse(`${scheme}:${pad(data.index)} \u2022 ${encodeURIComponent(message)} \u2022 ${moment(commit.date).format('MMM D, YYYY hh:MMa')} \u2022 ${encodeURIComponent(uriPath)}?${JSON.stringify(data)}`); } - private static _toGitUriData(commit: GitCommit, index: number, originalFileName?: string, decoration?: string): T { - const fileName = Git.normalizePath(path.join(commit.repoPath, commit.fileName)); + private static _toGitUriData(commit: IGitUriData, index?: number, originalFileName?: string, decoration?: string): T { + const fileName = Git.normalizePath(path.resolve(commit.repoPath, commit.fileName)); const data = { repoPath: commit.repoPath, fileName: fileName, sha: commit.sha, index: index } as T; if (originalFileName) { - data.originalFileName = Git.normalizePath(path.join(commit.repoPath, originalFileName)); + data.originalFileName = Git.normalizePath(path.resolve(commit.repoPath, originalFileName)); } if (decoration) { data.decoration = decoration; diff --git a/src/quickPicks.ts b/src/quickPicks.ts index 368b697..f07d8f9 100644 --- a/src/quickPicks.ts +++ b/src/quickPicks.ts @@ -1,7 +1,7 @@ 'use strict'; export { CommandQuickPickItem, OpenFileCommandQuickPickItem, OpenFilesCommandQuickPickItem } from './quickPicks/quickPicks'; export { CommitQuickPickItem, CommitWithFileStatusQuickPickItem } from './quickPicks/gitQuickPicks'; -export { OpenCommitFileCommandQuickPickItem, OpenCommitFilesCommandQuickPickItem, CommitDetailsQuickPick, CommitFileDetailsQuickPick } from './quickPicks/commitDetails'; +export { OpenCommitFileCommandQuickPickItem, OpenCommitWorkingTreeFileCommandQuickPickItem, OpenCommitFilesCommandQuickPickItem, OpenCommitWorkingTreeFilesCommandQuickPickItem, CommitDetailsQuickPick, CommitFileDetailsQuickPick } from './quickPicks/commitDetails'; export { FileHistoryQuickPick } from './quickPicks/fileHistory'; export { RepoHistoryQuickPick } from './quickPicks/repoHistory'; export { OpenStatusFileCommandQuickPickItem, OpenStatusFilesCommandQuickPickItem, RepoStatusQuickPick } from './quickPicks/repoStatus'; diff --git a/src/quickPicks/commitDetails.ts b/src/quickPicks/commitDetails.ts index e0fcbbb..0935c28 100644 --- a/src/quickPicks/commitDetails.ts +++ b/src/quickPicks/commitDetails.ts @@ -13,9 +13,20 @@ export { CommandQuickPickItem, CommitWithFileStatusQuickPickItem }; export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { constructor(commit: GitCommit, item?: QuickPickItem) { + const uri = GitProvider.toGitContentUri(commit); + super(uri, item || { + label: `$(file-symlink-file) Open File`, + description: `\u00a0 \u2014 \u00a0\u00a0 as of \u00a0 $(git-commit) \u00a0 ${commit.sha} \u00a0\u2022\u00a0 ${commit.getFormattedPath()}` + }); + } +} + +export class OpenCommitWorkingTreeFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { + + constructor(commit: GitCommit, item?: QuickPickItem) { const uri = Uri.file(path.resolve(commit.repoPath, commit.fileName)); super(uri, item || { - label: `$(file-symlink-file) Open Working Tree File`, + label: `$(file-symlink-file) Open Working File`, description: `\u00a0 \u2014 \u00a0\u00a0 ${commit.getFormattedPath()}` }); } @@ -25,11 +36,24 @@ export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPi constructor(commit: GitLogCommit, item?: QuickPickItem) { const repoPath = commit.repoPath; + const uris = commit.fileStatuses.map(_ => GitProvider.toGitContentUri(commit.sha, _.fileName, repoPath, commit.originalFileName)); + super(uris, item || { + label: `$(file-symlink-file) Open Files`, + description: `\u00a0 \u2014 \u00a0\u00a0 as of \u00a0 $(git-commit) \u00a0 ${commit.sha}` + //detail: `Opens all of the changed files in $(git-commit) ${commit.sha}` + }); + } +} + +export class OpenCommitWorkingTreeFilesCommandQuickPickItem extends OpenFilesCommandQuickPickItem { + + constructor(commit: GitLogCommit, versioned: boolean = false, item?: QuickPickItem) { + const repoPath = commit.repoPath; const uris = commit.fileStatuses.map(_ => Uri.file(path.resolve(repoPath, _.fileName))); super(uris, item || { - label: `$(file-symlink-file) Open Working Tree Files`, - description: undefined, - detail: `Opens all of the files in commit $(git-commit) ${commit.sha}` + label: `$(file-symlink-file) Open Working Files`, + description: undefined + //detail: `Opens all of the changed file in the working tree` }); } } @@ -49,7 +73,8 @@ export class CommitDetailsQuickPick { description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.message}` }, Commands.CopyMessageToClipboard, [uri, commit.sha, commit.message])); - items.splice(2, 0, new OpenCommitFilesCommandQuickPickItem(commit)); + items.splice(2, 0, new OpenCommitWorkingTreeFilesCommandQuickPickItem(commit)); + items.splice(3, 0, new OpenCommitFilesCommandQuickPickItem(commit)); if (goBackCommand) { items.splice(0, 0, goBackCommand); @@ -117,6 +142,7 @@ export class CommitFileDetailsQuickPick { description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.message}` }, Commands.CopyMessageToClipboard, [uri, commit.sha, commit.message])); + items.push(new OpenCommitWorkingTreeFileCommandQuickPickItem(commit)); items.push(new OpenCommitFileCommandQuickPickItem(commit)); if (options.showFileHistory) {