Browse Source

Fixes #34 - Open file should open the selected version of the file

Renames current Open File command to  Open Working File
Renames current Open Files command to  Open Working Files
Adds new Open File command to open the commit version of the file
Adds new Open Files command to open the commit version of the files
main
Eric Amodio 7 years ago
parent
commit
74845f979b
5 changed files with 69 additions and 22 deletions
  1. +4
    -4
      src/git/gitUri.ts
  2. +1
    -1
      src/gitContentProvider.ts
  3. +32
    -11
      src/gitProvider.ts
  4. +1
    -1
      src/quickPicks.ts
  5. +31
    -5
      src/quickPicks/commitDetails.ts

+ 4
- 4
src/git/gitUri.ts View File

@ -23,7 +23,7 @@ export class GitUri extends Uri {
this.offset = 0; this.offset = 0;
if (uri.scheme === DocumentSchemes.Git) { if (uri.scheme === DocumentSchemes.Git) {
const data = GitProvider.fromGitUri(uri);
const data = GitProvider.fromGitContentUri(uri);
base._fsPath = data.originalFileName || data.fileName; base._fsPath = data.originalFileName || data.fileName;
this.offset = (data.decoration && data.decoration.split('\n').length) || 0; this.offset = (data.decoration && data.decoration.split('\n').length) || 0;
@ -72,10 +72,10 @@ export interface IGitCommitInfo {
} }
export interface IGitUriData { export interface IGitUriData {
repoPath: string;
sha: string;
fileName: string; fileName: string;
repoPath: string;
originalFileName?: string; originalFileName?: string;
sha: string;
index: number;
index?: number;
decoration?: string; decoration?: string;
} }

+ 1
- 1
src/gitContentProvider.ts View File

@ -12,7 +12,7 @@ export default class GitContentProvider implements TextDocumentContentProvider {
constructor(context: ExtensionContext, private git: GitProvider) { } constructor(context: ExtensionContext, private git: GitProvider) { }
async provideTextDocumentContent(uri: Uri): Promise<string> { async provideTextDocumentContent(uri: Uri): Promise<string> {
const data = GitProvider.fromGitUri(uri);
const data = GitProvider.fromGitContentUri(uri);
const fileName = data.originalFileName || data.fileName; const fileName = data.originalFileName || data.fileName;
try { try {
let text = await this.git.getVersionedFileText(fileName, data.repoPath, data.sha) as string; let text = await this.git.getVersionedFileText(fileName, data.repoPath, data.sha) as string;

+ 32
- 11
src/gitProvider.ts View File

@ -450,7 +450,7 @@ export default class GitProvider extends Disposable {
if (c.isUncommitted) return; if (c.isUncommitted) return;
const decoration = `\u2937 ${c.author}, ${moment(c.date).format('MMMM Do, YYYY h:MMa')}`; 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))); locations.push(new Location(uri, new Position(0, 0)));
if (c.sha === selectedSha) { if (c.sha === selectedSha) {
locations.push(new Location(uri, new Position(line + 1, 0))); locations.push(new Location(uri, new Position(line + 1, 0)));
@ -550,7 +550,7 @@ export default class GitProvider extends Disposable {
if (c.isUncommitted) return; if (c.isUncommitted) return;
const decoration = `\u2937 ${c.author}, ${moment(c.date).format('MMMM Do, YYYY h:MMa')}`; 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))); locations.push(new Location(uri, new Position(0, 0)));
if (c.sha === selectedSha) { if (c.sha === selectedSha) {
locations.push(new Location(uri, new Position(line + 1, 0))); locations.push(new Location(uri, new Position(line + 1, 0)));
@ -614,20 +614,41 @@ export default class GitProvider extends Disposable {
return Git.isUncommitted(sha); 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`); if (uri.scheme !== DocumentSchemes.Git) throw new Error(`fromGitUri(uri=${uri}) invalid scheme`);
return GitProvider._fromGitUri<IGitUriData>(uri);
return GitProvider._fromGitContentUri<IGitUriData>(uri);
} }
private static _fromGitUri<T extends IGitUriData>(uri: Uri): T {
private static _fromGitContentUri<T extends IGitUriData>(uri: Uri): T {
return JSON.parse(uri.query) as 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 pad = (n: number) => ('0000000' + n).slice(-('' + commitCount).length);
const ext = path.extname(data.fileName); const ext = path.extname(data.fileName);
const uriPath = `${path.relative(commit.repoPath, data.fileName.slice(0, -ext.length))}/${commit.sha}${ext}`; 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)}`); 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<T extends IGitUriData>(commit: GitCommit, index: number, originalFileName?: string, decoration?: string): T {
const fileName = Git.normalizePath(path.join(commit.repoPath, commit.fileName));
private static _toGitUriData<T extends IGitUriData>(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; const data = { repoPath: commit.repoPath, fileName: fileName, sha: commit.sha, index: index } as T;
if (originalFileName) { if (originalFileName) {
data.originalFileName = Git.normalizePath(path.join(commit.repoPath, originalFileName));
data.originalFileName = Git.normalizePath(path.resolve(commit.repoPath, originalFileName));
} }
if (decoration) { if (decoration) {
data.decoration = decoration; data.decoration = decoration;

+ 1
- 1
src/quickPicks.ts View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
export { CommandQuickPickItem, OpenFileCommandQuickPickItem, OpenFilesCommandQuickPickItem } from './quickPicks/quickPicks'; export { CommandQuickPickItem, OpenFileCommandQuickPickItem, OpenFilesCommandQuickPickItem } from './quickPicks/quickPicks';
export { CommitQuickPickItem, CommitWithFileStatusQuickPickItem } from './quickPicks/gitQuickPicks'; 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 { FileHistoryQuickPick } from './quickPicks/fileHistory';
export { RepoHistoryQuickPick } from './quickPicks/repoHistory'; export { RepoHistoryQuickPick } from './quickPicks/repoHistory';
export { OpenStatusFileCommandQuickPickItem, OpenStatusFilesCommandQuickPickItem, RepoStatusQuickPick } from './quickPicks/repoStatus'; export { OpenStatusFileCommandQuickPickItem, OpenStatusFilesCommandQuickPickItem, RepoStatusQuickPick } from './quickPicks/repoStatus';

+ 31
- 5
src/quickPicks/commitDetails.ts View File

@ -13,9 +13,20 @@ export { CommandQuickPickItem, CommitWithFileStatusQuickPickItem };
export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPickItem {
constructor(commit: GitCommit, item?: QuickPickItem) { 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)); const uri = Uri.file(path.resolve(commit.repoPath, commit.fileName));
super(uri, item || { 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()}` description: `\u00a0 \u2014 \u00a0\u00a0 ${commit.getFormattedPath()}`
}); });
} }
@ -25,11 +36,24 @@ export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPi
constructor(commit: GitLogCommit, item?: QuickPickItem) { constructor(commit: GitLogCommit, item?: QuickPickItem) {
const repoPath = commit.repoPath; 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))); const uris = commit.fileStatuses.map(_ => Uri.file(path.resolve(repoPath, _.fileName)));
super(uris, item || { 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}` description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.message}`
}, Commands.CopyMessageToClipboard, [uri, commit.sha, 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) { if (goBackCommand) {
items.splice(0, 0, goBackCommand); items.splice(0, 0, goBackCommand);
@ -117,6 +142,7 @@ export class CommitFileDetailsQuickPick {
description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.message}` description: `\u00a0 \u2014 \u00a0\u00a0 $(git-commit) ${commit.message}`
}, Commands.CopyMessageToClipboard, [uri, commit.sha, commit.message])); }, Commands.CopyMessageToClipboard, [uri, commit.sha, commit.message]));
items.push(new OpenCommitWorkingTreeFileCommandQuickPickItem(commit));
items.push(new OpenCommitFileCommandQuickPickItem(commit)); items.push(new OpenCommitFileCommandQuickPickItem(commit));
if (options.showFileHistory) { if (options.showFileHistory) {

Loading…
Cancel
Save