From 52a549e85bd6ee9f0cd26061b580fb2eaca662f6 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Sun, 16 Sep 2018 03:21:52 -0400 Subject: [PATCH] Renames/reworks git models for files and statuses --- src/commands/diffWithBranch.ts | 6 +- src/commands/externalDiff.ts | 2 +- src/git/formatters/statusFormatter.ts | 43 +++++++---- src/git/gitService.ts | 11 +-- src/git/gitUri.ts | 42 +++++------ src/git/models/file.ts | 98 ++++++++++++++++++++++++ src/git/models/logCommit.ts | 44 +++++------ src/git/models/models.ts | 1 + src/git/models/stashCommit.ts | 14 ++-- src/git/models/status.ts | 126 ++++--------------------------- src/git/parsers/diffParser.ts | 35 ++++----- src/git/parsers/logParser.ts | 28 +++---- src/git/parsers/stashParser.ts | 20 ++--- src/git/parsers/statusParser.ts | 6 +- src/quickpicks/commitQuickPick.ts | 28 ++++--- src/quickpicks/repoStatusQuickPick.ts | 32 ++++---- src/views/explorerCommands.ts | 10 +-- src/views/nodes/commitFileNode.ts | 19 +++-- src/views/nodes/commitNode.ts | 2 +- src/views/nodes/fileHistoryNode.ts | 8 +- src/views/nodes/lineHistoryNode.ts | 16 ++-- src/views/nodes/resultsFilesNode.ts | 4 +- src/views/nodes/stashFileNode.ts | 6 +- src/views/nodes/stashNode.ts | 10 +-- src/views/nodes/statusFileCommitsNode.ts | 27 +++---- src/views/nodes/statusFileNode.ts | 22 ++---- src/views/nodes/statusFilesNode.ts | 50 ++++++------ 27 files changed, 350 insertions(+), 360 deletions(-) create mode 100644 src/git/models/file.ts diff --git a/src/commands/diffWithBranch.ts b/src/commands/diffWithBranch.ts index fe05795..e68b62a 100644 --- a/src/commands/diffWithBranch.ts +++ b/src/commands/diffWithBranch.ts @@ -60,10 +60,10 @@ export class DiffWithBranchCommand extends ActiveEditorCommand { let renamedTitle: string | undefined; // Check to see if this file has been renamed - const statuses = await Container.git.getDiffStatus(gitUri.repoPath, 'HEAD', ref, { filter: 'R' }); - if (statuses !== undefined) { + const files = await Container.git.getDiffStatus(gitUri.repoPath, 'HEAD', ref, { filter: 'R' }); + if (files !== undefined) { const fileName = Strings.normalizePath(path.relative(gitUri.repoPath, gitUri.fsPath)); - const rename = statuses.find(s => s.fileName === fileName); + const rename = files.find(s => s.fileName === fileName); if (rename !== undefined && rename.originalFileName !== undefined) { renamedUri = Uri.file(path.join(gitUri.repoPath, rename.originalFileName)); renamedTitle = `${path.basename(rename.originalFileName)} (${ref})`; diff --git a/src/commands/externalDiff.ts b/src/commands/externalDiff.ts index 1c19666..ae66803 100644 --- a/src/commands/externalDiff.ts +++ b/src/commands/externalDiff.ts @@ -122,7 +122,7 @@ export class ExternalDiffCommand extends Command { args.files.push(new ExternalDiffFile(file.uri, true)); } - if (file.workTreeStatus === 'M') { + if (file.workingTreeStatus === 'M') { args.files.push(new ExternalDiffFile(file.uri, false)); } } diff --git a/src/git/formatters/statusFormatter.ts b/src/git/formatters/statusFormatter.ts index e5017d3..db98bbe 100644 --- a/src/git/formatters/statusFormatter.ts +++ b/src/git/formatters/statusFormatter.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import { GlyphChars } from '../../constants'; import { Strings } from '../../system'; -import { GitStatusFile, IGitStatusFile, IGitStatusFileWithCommit } from '../models/status'; +import { GitFile, GitFileWithCommit } from '../models/file'; import { Formatter, IFormatOptions } from './formatter'; export interface IStatusFormatOptions extends IFormatOptions { @@ -18,9 +18,9 @@ export interface IStatusFormatOptions extends IFormatOptions { }; } -export class StatusFileFormatter extends Formatter { +export class StatusFileFormatter extends Formatter { get directory() { - const directory = GitStatusFile.getFormattedDirectory(this._item, false, this._options.relativePath); + const directory = GitFile.getFormattedDirectory(this._item, false, this._options.relativePath); return this._padOrTruncate(directory, this._options.tokenOptions!.directory); } @@ -30,40 +30,51 @@ export class StatusFileFormatter extends Formatter f.originalFileName === fileName); - if (status === undefined) return undefined; + const file = c.files.find(f => f.originalFileName === fileName); + if (file === undefined) return undefined; - return status.fileName; + return file.fileName; } async findWorkingFileName(commit: GitCommit): Promise<[string | undefined, string | undefined]>; @@ -1088,7 +1089,7 @@ export class GitService implements Disposable { ref1?: string, ref2?: string, options: { filter?: string } = {} - ): Promise { + ): Promise { Logger.log(`getDiffStatus('${repoPath}', '${ref1}', '${ref2}', ${options.filter})`); try { diff --git a/src/git/gitUri.ts b/src/git/gitUri.ts index f665235..618bdca 100644 --- a/src/git/gitUri.ts +++ b/src/git/gitUri.ts @@ -4,7 +4,7 @@ import { Uri } from 'vscode'; import { UriComparer } from '../comparers'; import { DocumentSchemes, GlyphChars } from '../constants'; import { Container } from '../container'; -import { GitCommit, GitService, IGitStatusFile } from '../git/gitService'; +import { GitCommit, GitFile, GitService } from '../git/gitService'; import { Strings } from '../system'; export interface GitCommitish { @@ -167,9 +167,9 @@ export class GitUri extends ((Uri as any) as UriEx) { }); } - static fromFileStatus(status: IGitStatusFile, repoPath: string, sha?: string, original: boolean = false): GitUri { - const uri = Uri.file(path.resolve(repoPath, (original && status.originalFileName) || status.fileName)); - return sha === undefined ? new GitUri(uri, repoPath) : new GitUri(uri, { repoPath: repoPath, sha: sha }); + static fromFile(file: GitFile, repoPath: string, ref?: string, original: boolean = false): GitUri { + const uri = Uri.file(path.resolve(repoPath, (original && file.originalFileName) || file.fileName)); + return ref === undefined ? new GitUri(uri, repoPath) : new GitUri(uri, { repoPath: repoPath, sha: ref }); } static fromRepoPath(repoPath: string, ref?: string) { @@ -280,40 +280,36 @@ export class GitUri extends ((Uri as any) as UriEx) { } static toRevisionUri(uri: GitUri): Uri; - static toRevisionUri(sha: string, fileName: string, repoPath: string): Uri; - static toRevisionUri(sha: string, status: IGitStatusFile, repoPath: string): Uri; - static toRevisionUri( - uriOrSha: string | GitUri, - fileNameOrStatus?: string | IGitStatusFile, - repoPath?: string - ): Uri { + static toRevisionUri(ref: string, fileName: string, repoPath: string): Uri; + static toRevisionUri(ref: string, file: GitFile, repoPath: string): Uri; + static toRevisionUri(uriOrRef: string | GitUri, fileNameOrFile?: string | GitFile, repoPath?: string): Uri { let fileName: string; - let sha: string | undefined; + let ref: string | undefined; let shortSha: string | undefined; - if (typeof uriOrSha === 'string') { - if (typeof fileNameOrStatus === 'string') { - fileName = fileNameOrStatus; + if (typeof uriOrRef === 'string') { + if (typeof fileNameOrFile === 'string') { + fileName = fileNameOrFile; } else { - fileName = path.resolve(repoPath!, fileNameOrStatus!.fileName); + fileName = path.resolve(repoPath!, fileNameOrFile!.fileName); } - sha = uriOrSha; - shortSha = GitService.shortenSha(sha); + ref = uriOrRef; + shortSha = GitService.shortenSha(ref); } else { - fileName = uriOrSha.fsPath!; - repoPath = uriOrSha.repoPath!; - sha = uriOrSha.sha; - shortSha = uriOrSha.shortSha; + fileName = uriOrRef.fsPath!; + repoPath = uriOrRef.repoPath!; + ref = uriOrRef.sha; + shortSha = uriOrRef.shortSha; } repoPath = Strings.normalizePath(repoPath!); const repoName = path.basename(repoPath); const data: IUriRevisionData = { path: Strings.normalizePath(fileName, { addLeadingSlash: true }), - ref: sha, + ref: ref, repoPath: repoPath }; diff --git a/src/git/models/file.ts b/src/git/models/file.ts new file mode 100644 index 0000000..ac111e2 --- /dev/null +++ b/src/git/models/file.ts @@ -0,0 +1,98 @@ +'use strict'; +import { GlyphChars } from '../../constants'; +import { Strings } from '../../system'; +import { GitUri } from '../gitUri'; +import { GitLogCommit } from './logCommit'; + +export declare type GitFileStatus = '!' | '?' | 'A' | 'C' | 'D' | 'M' | 'R' | 'T' | 'U' | 'X' | 'B'; + +export interface GitFile { + status: GitFileStatus; + readonly repoPath: string; + readonly indexStatus: GitFileStatus | undefined; + readonly workingTreeStatus: GitFileStatus | undefined; + readonly fileName: string; + readonly originalFileName?: string; +} + +export interface GitFileWithCommit extends GitFile { + readonly commit: GitLogCommit; +} + +export namespace GitFile { + export function getFormattedDirectory( + file: GitFile, + includeOriginal: boolean = false, + relativeTo?: string + ): string { + const directory = GitUri.getDirectory(file.fileName, relativeTo); + return includeOriginal && file.status === 'R' && file.originalFileName + ? `${directory} ${Strings.pad(GlyphChars.ArrowLeft, 1, 1)} ${file.originalFileName}` + : directory; + } + + export function getFormattedPath( + file: GitFile, + options: { relativeTo?: string; separator?: string; suffix?: string } = {} + ): string { + return GitUri.getFormattedPath(file.fileName, options); + } + + export function getRelativePath(file: GitFile, relativeTo?: string): string { + return GitUri.getRelativePath(file.fileName, relativeTo); + } + + const statusIconsMap = { + '!': 'icon-status-ignored.svg', + '?': 'icon-status-untracked.svg', + A: 'icon-status-added.svg', + C: 'icon-status-copied.svg', + D: 'icon-status-deleted.svg', + M: 'icon-status-modified.svg', + R: 'icon-status-renamed.svg', + T: 'icon-status-modified.svg', + U: 'icon-status-conflict.svg', + X: 'icon-status-unknown.svg', + B: 'icon-status-unknown.svg' + }; + + export function getStatusIcon(status: GitFileStatus): string { + return statusIconsMap[status] || statusIconsMap['X']; + } + + const statusOcticonsMap = { + '!': '$(diff-ignored)', + '?': '$(diff-added)', + A: '$(diff-added)', + C: '$(diff-added)', + D: '$(diff-removed)', + M: '$(diff-modified)', + R: '$(diff-renamed)', + T: '$(diff-modified)', + U: '$(alert)', + X: '$(question)', + B: '$(question)' + }; + + export function getStatusOcticon(status: GitFileStatus, missing: string = GlyphChars.Space.repeat(4)): string { + return statusOcticonsMap[status] || missing; + } + + const statusTextMap = { + '!': 'Ignored', + '?': 'Untracked', + A: 'Added', + C: 'Copied', + D: 'Deleted', + M: 'Modified', + R: 'Renamed', + T: 'Modified', + U: 'Conflict', + X: 'Unknown', + B: 'Unknown' + }; + + export function getStatusText(status: GitFileStatus): string { + return statusTextMap[status] || statusTextMap['X']; + } +} diff --git a/src/git/models/logCommit.ts b/src/git/models/logCommit.ts index c728283..a3c1016 100644 --- a/src/git/models/logCommit.ts +++ b/src/git/models/logCommit.ts @@ -4,7 +4,7 @@ import { Uri } from 'vscode'; import { Strings } from '../../system'; import { Git } from '../git'; import { GitCommit, GitCommitType } from './commit'; -import { GitStatusFileStatus, IGitStatusFile } from './status'; +import { GitFile, GitFileStatus } from './file'; export class GitLogCommit extends GitCommit { nextSha?: string; @@ -19,8 +19,8 @@ export class GitLogCommit extends GitCommit { date: Date, message: string, fileName: string, - public readonly fileStatuses: IGitStatusFile[], - public readonly status: GitStatusFileStatus | undefined, + public readonly files: GitFile[], + public readonly status: GitFileStatus | undefined, originalFileName: string | undefined, previousSha: string | undefined, previousFileName: string | undefined, @@ -73,8 +73,8 @@ export class GitLogCommit extends GitCommit { changed: 0 }; - if (this.fileStatuses.length !== 0) { - for (const f of this.fileStatuses) { + if (this.files.length !== 0) { + for (const f of this.files) { switch (f.status) { case 'A': case '?': @@ -128,21 +128,21 @@ export class GitLogCommit extends GitCommit { } toFileCommit(fileName: string): GitLogCommit | undefined; - toFileCommit(status: IGitStatusFile): GitLogCommit; - toFileCommit(fileNameOrStatus: string | IGitStatusFile): GitLogCommit | undefined { - let status: IGitStatusFile | undefined; - if (typeof fileNameOrStatus === 'string') { - const fileName = Strings.normalizePath(path.relative(this.repoPath, fileNameOrStatus)); - status = this.fileStatuses.find(f => f.fileName === fileName); - if (status === undefined) return undefined; + toFileCommit(file: GitFile): GitLogCommit; + toFileCommit(fileNameOrFile: string | GitFile): GitLogCommit | undefined { + let file: GitFile | undefined; + if (typeof fileNameOrFile === 'string') { + const fileName = Strings.normalizePath(path.relative(this.repoPath, fileNameOrFile)); + file = this.files.find(f => f.fileName === fileName); + if (file === undefined) return undefined; } else { - status = fileNameOrStatus; + file = fileNameOrFile; } let sha; // If this is a stash commit with an untracked file - if (this.type === GitCommitType.Stash && status.status === '?') { + if (this.type === GitCommitType.Stash && file.status === '?') { sha = `${this.sha}^3`; } @@ -152,12 +152,12 @@ export class GitLogCommit extends GitCommit { return this.with({ type: this.isStash ? GitCommitType.StashFile : GitCommitType.File, sha: sha, - fileName: status.fileName, - originalFileName: status.originalFileName, + fileName: file.fileName, + originalFileName: file.originalFileName, previousSha: previousSha, - previousFileName: status.originalFileName || status.fileName, - status: status.status, - fileStatuses: [status] + previousFileName: file.originalFileName || file.fileName, + status: file.status, + files: [file] }); } @@ -172,8 +172,8 @@ export class GitLogCommit extends GitCommit { originalFileName?: string | null; previousFileName?: string | null; previousSha?: string | null; - status?: GitStatusFileStatus; - fileStatuses?: IGitStatusFile[] | null; + status?: GitFileStatus; + files?: GitFile[] | null; }): GitLogCommit { return new GitLogCommit( changes.type || this.type, @@ -184,7 +184,7 @@ export class GitLogCommit extends GitCommit { changes.date || this.date, changes.message || this.message, changes.fileName || this.fileName, - this.getChangedValue(changes.fileStatuses, this.fileStatuses) || [], + this.getChangedValue(changes.files, this.files) || [], changes.status || this.status, this.getChangedValue(changes.originalFileName, this.originalFileName), this.getChangedValue(changes.previousSha, this.previousSha), diff --git a/src/git/models/models.ts b/src/git/models/models.ts index 638e1ac..6eaa582 100644 --- a/src/git/models/models.ts +++ b/src/git/models/models.ts @@ -5,6 +5,7 @@ export * from './blameCommit'; export * from './branch'; export * from './commit'; export * from './diff'; +export * from './file'; export * from './log'; export * from './logCommit'; export * from './remote'; diff --git a/src/git/models/stashCommit.ts b/src/git/models/stashCommit.ts index 907cd6a..ce396a4 100644 --- a/src/git/models/stashCommit.ts +++ b/src/git/models/stashCommit.ts @@ -1,7 +1,7 @@ 'use strict'; import { GitCommitType } from './commit'; +import { GitFile, GitFileStatus } from './file'; import { GitLogCommit } from './logCommit'; -import { GitStatusFileStatus, IGitStatusFile } from './status'; export class GitStashCommit extends GitLogCommit { constructor( @@ -12,8 +12,8 @@ export class GitStashCommit extends GitLogCommit { date: Date, message: string, fileName: string, - fileStatuses: IGitStatusFile[], - status?: GitStatusFileStatus | undefined, + files: GitFile[], + status?: GitFileStatus | undefined, originalFileName?: string | undefined, previousSha?: string | undefined, previousFileName?: string | undefined @@ -27,7 +27,7 @@ export class GitStashCommit extends GitLogCommit { date, message, fileName, - fileStatuses, + files, status, originalFileName, previousSha === undefined ? `${sha}^` : previousSha, @@ -48,8 +48,8 @@ export class GitStashCommit extends GitLogCommit { originalFileName?: string | null; previousFileName?: string | null; previousSha?: string | null; - status?: GitStatusFileStatus; - fileStatuses?: IGitStatusFile[] | null; + status?: GitFileStatus; + files?: GitFile[] | null; }): GitLogCommit { return new GitStashCommit( changes.type || this.type, @@ -59,7 +59,7 @@ export class GitStashCommit extends GitLogCommit { changes.date || this.date, changes.message || this.message, changes.fileName || this.fileName, - this.getChangedValue(changes.fileStatuses, this.fileStatuses) || [], + this.getChangedValue(changes.files, this.files) || [], changes.status || this.status, this.getChangedValue(changes.originalFileName, this.originalFileName), this.getChangedValue(changes.previousSha, this.previousSha), diff --git a/src/git/models/status.ts b/src/git/models/status.ts index 83ac4b2..cda17ad 100644 --- a/src/git/models/status.ts +++ b/src/git/models/status.ts @@ -3,9 +3,8 @@ import * as path from 'path'; import { Uri } from 'vscode'; import { GlyphChars } from '../../constants'; import { Strings } from '../../system'; -import { GitUri } from '../gitUri'; import { GitBranch } from './branch'; -import { GitLogCommit } from './logCommit'; +import { GitFile, GitFileStatus } from './file'; export interface GitStatusUpstreamState { ahead: number; @@ -136,32 +135,17 @@ export class GitStatus { } } -export declare type GitStatusFileStatus = '!' | '?' | 'A' | 'C' | 'D' | 'M' | 'R' | 'T' | 'U' | 'X' | 'B'; - -export interface IGitStatusFile { - status: GitStatusFileStatus; - readonly repoPath: string; - readonly indexStatus: GitStatusFileStatus; - readonly workTreeStatus: GitStatusFileStatus; - readonly fileName: string; - readonly originalFileName?: string; -} - -export interface IGitStatusFileWithCommit extends IGitStatusFile { - readonly commit: GitLogCommit; -} - -export class GitStatusFile implements IGitStatusFile { +export class GitStatusFile implements GitFile { constructor( public readonly repoPath: string, - public readonly indexStatus: GitStatusFileStatus, - public readonly workTreeStatus: GitStatusFileStatus, + public readonly indexStatus: GitFileStatus | undefined, + public readonly workingTreeStatus: GitFileStatus | undefined, public readonly fileName: string, public readonly originalFileName?: string ) {} - get status(): GitStatusFileStatus { - return (this.indexStatus || this.workTreeStatus || '?') as GitStatusFileStatus; + get status(): GitFileStatus { + return (this.indexStatus || this.workingTreeStatus || '?') as GitFileStatus; } get staged() { @@ -173,31 +157,31 @@ export class GitStatusFile implements IGitStatusFile { } getFormattedDirectory(includeOriginal: boolean = false): string { - return GitStatusFile.getFormattedDirectory(this, includeOriginal); + return GitFile.getFormattedDirectory(this, includeOriginal); } getFormattedPath(options: { relativeTo?: string; separator?: string; suffix?: string } = {}): string { - return GitStatusFile.getFormattedPath(this, options); + return GitFile.getFormattedPath(this, options); } getOcticon() { - return getGitStatusOcticon(this.status); + return GitFile.getStatusOcticon(this.status); } - getStatusText(status: IGitStatusFile): string { - return GitStatusFile.getStatusText(this.status); + getStatusText(file: GitFile): string { + return GitFile.getStatusText(this.status); } with(changes: { - indexStatus?: GitStatusFileStatus | null; - workTreeStatus?: GitStatusFileStatus | null; + indexStatus?: GitFileStatus | null; + workTreeStatus?: GitFileStatus | null; fileName?: string; originalFileName?: string | null; }): GitStatusFile { return new GitStatusFile( this.repoPath, - this.getChangedValue(changes.indexStatus, this.indexStatus) as GitStatusFileStatus, - this.getChangedValue(changes.workTreeStatus, this.workTreeStatus) as GitStatusFileStatus, + this.getChangedValue(changes.indexStatus, this.indexStatus) as GitFileStatus, + this.getChangedValue(changes.workTreeStatus, this.workingTreeStatus) as GitFileStatus, changes.fileName || this.fileName, this.getChangedValue(changes.originalFileName, this.originalFileName) ); @@ -207,84 +191,4 @@ export class GitStatusFile implements IGitStatusFile { if (change === undefined) return original; return change !== null ? change : undefined; } - - static getFormattedDirectory( - status: IGitStatusFile, - includeOriginal: boolean = false, - relativeTo?: string - ): string { - const directory = GitUri.getDirectory(status.fileName, relativeTo); - return includeOriginal && status.status === 'R' && status.originalFileName - ? `${directory} ${Strings.pad(GlyphChars.ArrowLeft, 1, 1)} ${status.originalFileName}` - : directory; - } - - static getFormattedPath( - status: IGitStatusFile, - options: { relativeTo?: string; separator?: string; suffix?: string } = {} - ): string { - return GitUri.getFormattedPath(status.fileName, options); - } - - static getRelativePath(status: IGitStatusFile, relativeTo?: string): string { - return GitUri.getRelativePath(status.fileName, relativeTo); - } - - static getStatusText(status: GitStatusFileStatus): string { - return getGitStatusText(status); - } -} - -const statusOcticonsMap = { - '!': '$(diff-ignored)', - '?': '$(diff-added)', - A: '$(diff-added)', - C: '$(diff-added)', - D: '$(diff-removed)', - M: '$(diff-modified)', - R: '$(diff-renamed)', - T: '$(diff-modified)', - U: '$(alert)', - X: '$(question)', - B: '$(question)' -}; - -export function getGitStatusOcticon(status: GitStatusFileStatus, missing: string = GlyphChars.Space.repeat(4)): string { - return statusOcticonsMap[status] || missing; -} - -const statusIconsMap = { - '!': 'icon-status-ignored.svg', - '?': 'icon-status-untracked.svg', - A: 'icon-status-added.svg', - C: 'icon-status-copied.svg', - D: 'icon-status-deleted.svg', - M: 'icon-status-modified.svg', - R: 'icon-status-renamed.svg', - T: 'icon-status-modified.svg', - U: 'icon-status-conflict.svg', - X: 'icon-status-unknown.svg', - B: 'icon-status-unknown.svg' -}; - -export function getGitStatusIcon(status: GitStatusFileStatus): string { - return statusIconsMap[status] || statusIconsMap['X']; -} - -const statusTextMap = { - '!': 'ignored', - '?': 'untracked', - A: 'added', - C: 'copied', - D: 'deleted', - M: 'modified', - R: 'renamed', - T: 'modified', - U: 'conflict', - X: 'unknown', - B: 'unknown' -}; - -export function getGitStatusText(status: GitStatusFileStatus): string { - return statusTextMap[status] || statusTextMap['X']; } diff --git a/src/git/parsers/diffParser.ts b/src/git/parsers/diffParser.ts index 87eaafb..1f91f32 100644 --- a/src/git/parsers/diffParser.ts +++ b/src/git/parsers/diffParser.ts @@ -6,8 +6,8 @@ import { GitDiffChunkLine, GitDiffLine, GitDiffShortStat, - GitStatusFile, - GitStatusParser + GitFile, + GitFileStatus } from './../git'; const nameStatusDiffRegex = /^(.*?)\t(.*?)(?:\t(.*?))?$/gm; @@ -137,32 +137,33 @@ export class GitDiffParser { return chunkLines; } - static parseNameStatus(data: string, repoPath: string): GitStatusFile[] | undefined { + static parseNameStatus(data: string, repoPath: string): GitFile[] | undefined { if (!data) return undefined; - const statuses: GitStatusFile[] = []; + const files: GitFile[] = []; let match: RegExpExecArray | null = null; do { match = nameStatusDiffRegex.exec(data); if (match == null) break; - statuses.push( - GitStatusParser.parseStatusFile( - repoPath, - // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 - (' ' + match[1]).substr(1), - // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 - (' ' + match[2]).substr(1), - // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 - match[3] === undefined ? undefined : (' ' + match[3]).substr(1) - ) - ); + // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 + const status = (' ' + match[1]).substr(1); + files.push({ + repoPath, + status: (status[0] !== '.' ? status[0].trim() : '?') as GitFileStatus, + indexStatus: undefined, + workingTreeStatus: undefined, + // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 + fileName: (' ' + match[2]).substr(1), + // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 + originalFileName: match[3] === undefined ? undefined : (' ' + match[3]).substr(1) + } as GitFile); } while (match != null); - if (!statuses.length) return undefined; + if (!files.length) return undefined; - return statuses; + return files; } static parseShortStat(data: string): GitDiffShortStat | undefined { diff --git a/src/git/parsers/logParser.ts b/src/git/parsers/logParser.ts index 5544eac..4867289 100644 --- a/src/git/parsers/logParser.ts +++ b/src/git/parsers/logParser.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import { Range } from 'vscode'; import { Arrays, Strings } from '../../system'; -import { Git, GitAuthor, GitCommitType, GitLog, GitLogCommit, GitStatusFileStatus, IGitStatusFile } from './../git'; +import { Git, GitAuthor, GitCommitType, GitFile, GitFileStatus, GitLog, GitLogCommit } from './../git'; interface LogEntry { ref?: string; @@ -15,9 +15,9 @@ interface LogEntry { fileName?: string; originalFileName?: string; - fileStatuses?: IGitStatusFile[]; + files?: GitFile[]; - status?: GitStatusFileStatus; + status?: GitFileStatus; summary?: string; } @@ -140,17 +140,17 @@ export class GitLogParser { if (type === GitCommitType.Branch) { const status = { - status: line[0] as GitStatusFileStatus, + status: line[0] as GitFileStatus, fileName: line.substring(1), originalFileName: undefined - } as IGitStatusFile; + } as GitFile; this.parseFileName(status); if (status.fileName) { - if (entry.fileStatuses === undefined) { - entry.fileStatuses = []; + if (entry.files === undefined) { + entry.files = []; } - entry.fileStatuses.push(status); + entry.files.push(status); } } else if (line.startsWith('diff')) { @@ -174,15 +174,15 @@ export class GitLogParser { break; } else { - entry.status = line[0] as GitStatusFileStatus; + entry.status = line[0] as GitFileStatus; entry.fileName = line.substring(1); this.parseFileName(entry); } } - if (entry.fileStatuses !== undefined) { + if (entry.files !== undefined) { entry.fileName = Arrays.filterMap( - entry.fileStatuses, + entry.files, f => (!!f.fileName ? f.fileName : undefined) ).join(', '); } @@ -268,12 +268,12 @@ export class GitLogParser { const originalFileName = relativeFileName !== entry.fileName ? entry.fileName : undefined; if (type === GitCommitType.File) { - entry.fileStatuses = [ + entry.files = [ { status: entry.status, fileName: relativeFileName, originalFileName: originalFileName - } as IGitStatusFile + } as GitFile ]; } @@ -286,7 +286,7 @@ export class GitLogParser { new Date((entry.date! as any) * 1000), entry.summary === undefined ? '' : entry.summary, relativeFileName, - entry.fileStatuses || [], + entry.files || [], entry.status, originalFileName, undefined, diff --git a/src/git/parsers/stashParser.ts b/src/git/parsers/stashParser.ts index 7f1b9f6..5c4777a 100644 --- a/src/git/parsers/stashParser.ts +++ b/src/git/parsers/stashParser.ts @@ -1,13 +1,13 @@ 'use strict'; import { Arrays, Strings } from '../../system'; -import { GitCommitType, GitLogParser, GitStash, GitStashCommit, GitStatusFileStatus, IGitStatusFile } from './../git'; +import { GitCommitType, GitFile, GitFileStatus, GitLogParser, GitStash, GitStashCommit } from './../git'; // import { Logger } from './logger'; interface StashEntry { ref?: string; date?: string; fileNames?: string; - fileStatuses?: IGitStatusFile[]; + files?: GitFile[]; summary?: string; stashName?: string; } @@ -94,23 +94,23 @@ export class GitStashParser { if (line.startsWith('warning:')) continue; const status = { - status: line[0] as GitStatusFileStatus, + status: line[0] as GitFileStatus, fileName: line.substring(1), originalFileName: undefined - } as IGitStatusFile; + } as GitFile; GitLogParser.parseFileName(status); if (status.fileName) { - if (entry.fileStatuses === undefined) { - entry.fileStatuses = []; + if (entry.files === undefined) { + entry.files = []; } - entry.fileStatuses.push(status); + entry.files.push(status); } } - if (entry.fileStatuses !== undefined) { + if (entry.files !== undefined) { entry.fileNames = Arrays.filterMap( - entry.fileStatuses, + entry.files, f => (!!f.fileName ? f.fileName : undefined) ).join(', '); } @@ -142,7 +142,7 @@ export class GitStashParser { new Date((entry.date! as any) * 1000), entry.summary === undefined ? '' : entry.summary, entry.fileNames!, - entry.fileStatuses || [] + entry.files || [] ); } diff --git a/src/git/parsers/statusParser.ts b/src/git/parsers/statusParser.ts index c96c74e..9a20dc5 100644 --- a/src/git/parsers/statusParser.ts +++ b/src/git/parsers/statusParser.ts @@ -1,6 +1,6 @@ 'use strict'; import { Strings } from '../../system'; -import { GitStatus, GitStatusFile, GitStatusFileStatus } from './../git'; +import { GitFileStatus, GitStatus, GitStatusFile } from './../git'; const aheadStatusV1Regex = /(?:ahead ([0-9]+))/; const behindStatusV1Regex = /(?:behind ([0-9]+))/; @@ -138,8 +138,8 @@ export class GitStatusParser { return new GitStatusFile( repoPath, - indexStatus as GitStatusFileStatus, - workTreeStatus as GitStatusFileStatus, + indexStatus as GitFileStatus | undefined, + workTreeStatus as GitFileStatus | undefined, fileName, originalFileName ); diff --git a/src/quickpicks/commitQuickPick.ts b/src/quickpicks/commitQuickPick.ts index 300811d..0749ca4 100644 --- a/src/quickpicks/commitQuickPick.ts +++ b/src/quickpicks/commitQuickPick.ts @@ -14,14 +14,12 @@ import { import { GlyphChars } from '../constants'; import { Container } from '../container'; import { - getGitStatusOcticon, + GitFile, + GitFileStatus, GitLog, GitLogCommit, GitStashCommit, - GitStatusFile, - GitStatusFileStatus, GitUri, - IGitStatusFile, RemoteResource } from '../git/gitService'; import { KeyCommand, KeyNoopCommand, Keys } from '../keyboard'; @@ -38,21 +36,21 @@ import { import { OpenRemotesCommandQuickPickItem } from './remotesQuickPick'; export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickItem { - readonly status: GitStatusFileStatus; + readonly status: GitFileStatus; readonly commit: GitLogCommit; - constructor(commit: GitLogCommit, status: IGitStatusFile) { - const octicon = getGitStatusOcticon(status.status); - const description = GitStatusFile.getFormattedDirectory(status, true); + constructor(commit: GitLogCommit, file: GitFile) { + const octicon = GitFile.getStatusOcticon(file.status); + const description = GitFile.getFormattedDirectory(file, true); - super(GitUri.toRevisionUri(commit.sha, status, commit.repoPath), { - label: `${Strings.pad(octicon, 4, 2)} ${path.basename(status.fileName)}`, + super(GitUri.toRevisionUri(commit.sha, file, commit.repoPath), { + label: `${Strings.pad(octicon, 4, 2)} ${path.basename(file.fileName)}`, description: description }); - this.commit = commit.toFileCommit(status); - this.status = status.status; + this.commit = commit.toFileCommit(file); + this.status = file.status; } get sha(): string { @@ -75,7 +73,7 @@ export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickI export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPickItem { constructor(commit: GitLogCommit, versioned: boolean = false, item?: QuickPickItem) { const repoPath = commit.repoPath; - const uris = Arrays.filterMap(commit.fileStatuses, f => GitUri.fromFileStatus(f, repoPath)); + const uris = Arrays.filterMap(commit.files, f => GitUri.fromFile(f, repoPath)); super( uris, @@ -90,7 +88,7 @@ export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPi export class OpenCommitFileRevisionsCommandQuickPickItem extends OpenFilesCommandQuickPickItem { constructor(commit: GitLogCommit, item?: QuickPickItem) { - const uris = Arrays.filterMap(commit.fileStatuses, f => + const uris = Arrays.filterMap(commit.files, f => GitUri.toRevisionUri(f.status === 'D' ? commit.previousFileSha : commit.sha, f, commit.repoPath) ); @@ -117,7 +115,7 @@ export class CommitQuickPick { ): Promise { await commit.resolvePreviousFileSha(); - const items: (CommitWithFileStatusQuickPickItem | CommandQuickPickItem)[] = commit.fileStatuses.map( + const items: (CommitWithFileStatusQuickPickItem | CommandQuickPickItem)[] = commit.files.map( fs => new CommitWithFileStatusQuickPickItem(commit, fs) ); diff --git a/src/quickpicks/repoStatusQuickPick.ts b/src/quickpicks/repoStatusQuickPick.ts index 1aeb1e2..aa37146 100644 --- a/src/quickpicks/repoStatusQuickPick.ts +++ b/src/quickpicks/repoStatusQuickPick.ts @@ -13,11 +13,11 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitCommitType, + GitFileStatus, GitLogCommit, GitService, GitStatus, GitStatusFile, - GitStatusFileStatus, GitUri } from '../git/gitService'; import { Keys } from '../keyboard'; @@ -33,7 +33,7 @@ export class OpenStatusFileCommandQuickPickItem extends OpenFileCommandQuickPick public readonly status: GitStatusFile; private readonly commit: GitLogCommit; - constructor(status: GitStatusFile, realIndexStatus?: GitStatusFileStatus, item?: QuickPickItem) { + constructor(status: GitStatusFile, realIndexStatus?: GitFileStatus, item?: QuickPickItem) { const octicon = status.getOcticon(); const description = status.getFormattedDirectory(true); @@ -87,24 +87,20 @@ export class OpenStatusFileCommandQuickPickItem extends OpenFileCommandQuickPick } onDidPressKey(key: Keys): Promise<{} | undefined> { - return commands.executeCommand( - Commands.DiffWithPrevious, - GitUri.fromFileStatus(this.status, this.status.repoPath), - { - commit: this.commit, - line: 0, - showOptions: { - preserveFocus: true, - preview: false - } as TextDocumentShowOptions - } as DiffWithPreviousCommandArgs - ) as Promise<{} | undefined>; + return commands.executeCommand(Commands.DiffWithPrevious, GitUri.fromFile(this.status, this.status.repoPath), { + commit: this.commit, + line: 0, + showOptions: { + preserveFocus: true, + preview: false + } as TextDocumentShowOptions + } as DiffWithPreviousCommandArgs) as Promise<{} | undefined>; } } export class OpenStatusFilesCommandQuickPickItem extends CommandQuickPickItem { - constructor(statuses: GitStatusFile[], item?: QuickPickItem) { - const uris = statuses.map(f => f.uri); + constructor(files: GitStatusFile[], item?: QuickPickItem) { + const uris = files.map(f => f.uri); super( item || { @@ -166,7 +162,7 @@ export class RepoStatusQuickPick { break; } - switch (f.workTreeStatus) { + switch (f.workingTreeStatus) { case 'A': case '?': unstagedAdds++; @@ -208,7 +204,7 @@ export class RepoStatusQuickPick { > { const items = [ ...Iterables.flatMap(status.files, s => { - if (s.workTreeStatus !== undefined && s.indexStatus !== undefined) { + if (s.workingTreeStatus !== undefined && s.indexStatus !== undefined) { return [ new OpenStatusFileCommandQuickPickItem(s.with({ indexStatus: null }), s.indexStatus), new OpenStatusFileCommandQuickPickItem(s.with({ workTreeStatus: null })) diff --git a/src/views/explorerCommands.ts b/src/views/explorerCommands.ts index c57c7bd..8942a36 100644 --- a/src/views/explorerCommands.ts +++ b/src/views/explorerCommands.ts @@ -281,7 +281,7 @@ export class ExplorerCommands implements Disposable { options: TextDocumentShowOptions = { preserveFocus: false, preview: false } ) { const repoPath = node.commit.repoPath; - const uris = node.commit.fileStatuses.map(s => GitUri.fromFileStatus(s, repoPath)); + const uris = node.commit.files.map(s => GitUri.fromFile(s, repoPath)); for (const uri of uris) { await this.openDiffWith( @@ -303,8 +303,8 @@ export class ExplorerCommands implements Disposable { ) { const repoPath = node.commit.repoPath; const uris = Arrays.filterMap( - node.commit.fileStatuses, - f => (f.status !== 'D' ? GitUri.fromFileStatus(f, repoPath) : undefined) + node.commit.files, + f => (f.status !== 'D' ? GitUri.fromFile(f, repoPath) : undefined) ); for (const uri of uris) { @@ -317,7 +317,7 @@ export class ExplorerCommands implements Disposable { options: TextDocumentShowOptions = { preserveFocus: false, preview: false } ) { const repoPath = node.commit.repoPath; - const uris = Arrays.filterMap(node.commit.fileStatuses, f => GitUri.fromFileStatus(f, repoPath)); + const uris = Arrays.filterMap(node.commit.files, f => GitUri.fromFile(f, repoPath)); for (const uri of uris) { await openEditor(uri, options); @@ -328,7 +328,7 @@ export class ExplorerCommands implements Disposable { node: CommitNode | StashNode, options: TextDocumentShowOptions = { preserveFocus: false, preview: false } ) { - const uris = Arrays.filterMap(node.commit.fileStatuses, f => + const uris = Arrays.filterMap(node.commit.files, f => GitUri.toRevisionUri( f.status === 'D' ? node.commit.previousFileSha : node.commit.sha, f, diff --git a/src/views/nodes/commitFileNode.ts b/src/views/nodes/commitFileNode.ts index ddf3423..f021f0e 100644 --- a/src/views/nodes/commitFileNode.ts +++ b/src/views/nodes/commitFileNode.ts @@ -6,11 +6,10 @@ import { GlyphChars } from '../../constants'; import { Container } from '../../container'; import { CommitFormatter, - getGitStatusIcon, + GitFile, GitLogCommit, GitUri, ICommitFormatOptions, - IGitStatusFile, IStatusFormatOptions, StatusFileFormatter } from '../../git/gitService'; @@ -32,14 +31,14 @@ export class CommitFileNode extends ExplorerRefNode { readonly priority: boolean = false; constructor( - public readonly status: IGitStatusFile, + public readonly file: GitFile, public commit: GitLogCommit, parent: ExplorerNode, public readonly explorer: Explorer, private readonly _displayAs: CommitFileNodeDisplayAs, private readonly _selection?: Selection ) { - super(GitUri.fromFileStatus(status, commit.repoPath, commit.sha), parent); + super(GitUri.fromFile(file, commit.repoPath, commit.sha), parent); } get ref(): string { @@ -53,9 +52,9 @@ export class CommitFileNode extends ExplorerRefNode { async getTreeItem(): Promise { if (!this.commit.isFile) { // See if we can get the commit directly from the multi-file commit - const commit = this.commit.toFileCommit(this.status); + const commit = this.commit.toFileCommit(this.file); if (commit === undefined) { - const log = await Container.git.getLogForFile(this.repoPath, this.status.fileName, { + const log = await Container.git.getLogForFile(this.repoPath, this.file.fileName, { maxCount: 2, ref: this.commit.sha }); @@ -79,7 +78,7 @@ export class CommitFileNode extends ExplorerRefNode { }; } else if ((this._displayAs & CommitFileNodeDisplayAs.StatusIcon) === CommitFileNodeDisplayAs.StatusIcon) { - const icon = getGitStatusIcon(this.status.status); + const icon = GitFile.getStatusIcon(this.file.status); item.iconPath = { dark: Container.context.asAbsolutePath(path.join('images', 'dark', icon)), light: Container.context.asAbsolutePath(path.join('images', 'light', icon)) @@ -115,7 +114,7 @@ export class CommitFileNode extends ExplorerRefNode { truncateMessageAtNewLine: true, dateFormat: Container.config.defaultDateFormat } as ICommitFormatOptions) - : StatusFileFormatter.fromTemplate(this.getCommitFileTemplate(), this.status, { + : StatusFileFormatter.fromTemplate(this.getCommitFileTemplate(), this.file, { relativePath: this.relativePath } as IStatusFormatOptions); } @@ -151,7 +150,7 @@ export class CommitFileNode extends ExplorerRefNode { ); } else { - this._tooltip = StatusFileFormatter.fromTemplate('${file}\n${directory}/\n\n${status}', this.status); + this._tooltip = StatusFileFormatter.fromTemplate('${file}\n${directory}/\n\n${status}', this.file); } } return this._tooltip; @@ -170,7 +169,7 @@ export class CommitFileNode extends ExplorerRefNode { title: 'Compare File with Previous Revision', command: Commands.DiffWithPrevious, arguments: [ - GitUri.fromFileStatus(this.status, this.commit.repoPath), + GitUri.fromFile(this.file, this.commit.repoPath), { commit: this.commit, line: this._selection !== undefined ? this._selection.active.line : 0, diff --git a/src/views/nodes/commitNode.ts b/src/views/nodes/commitNode.ts index 41c4f00..d8faf7e 100644 --- a/src/views/nodes/commitNode.ts +++ b/src/views/nodes/commitNode.ts @@ -31,7 +31,7 @@ export class CommitNode extends ExplorerRefNode { const commit = this.commit; let children: FileExplorerNode[] = [ ...Iterables.map( - commit.fileStatuses, + commit.files, s => new CommitFileNode(s, commit.toFileCommit(s), this, this.explorer, CommitFileNodeDisplayAs.File) ) ]; diff --git a/src/views/nodes/fileHistoryNode.ts b/src/views/nodes/fileHistoryNode.ts index f539d70..878586e 100644 --- a/src/views/nodes/fileHistoryNode.ts +++ b/src/views/nodes/fileHistoryNode.ts @@ -30,15 +30,15 @@ export class FileHistoryNode extends SubscribeableExplorerNode new CommitFileNode(c.fileStatuses[0], c, this, this.explorer, displayAs) + c => new CommitFileNode(c.files[0], c, this, this.explorer, displayAs) ) ); } diff --git a/src/views/nodes/lineHistoryNode.ts b/src/views/nodes/lineHistoryNode.ts index a2a8386..6e3758a 100644 --- a/src/views/nodes/lineHistoryNode.ts +++ b/src/views/nodes/lineHistoryNode.ts @@ -1,7 +1,7 @@ 'use strict'; import { Disposable, Selection, TreeItem, TreeItemCollapsibleState } from 'vscode'; import { Container } from '../../container'; -import { GitCommitType, GitLogCommit, IGitStatusFile } from '../../git/git'; +import { GitCommitType, GitFile, GitLogCommit } from '../../git/git'; import { GitService, GitUri, @@ -41,7 +41,7 @@ export class LineHistoryNode extends SubscribeableExplorerNode new CommitFileNode(c.fileStatuses[0], c, this, this.explorer, displayAs, this.selection) + c => new CommitFileNode(c.files[0], c, this, this.explorer, displayAs, this.selection) ) ); } @@ -51,13 +51,13 @@ export class LineHistoryNode extends SubscribeableExplorerNode { - const statuses = (this.commit as GitStashCommit).fileStatuses; + const files = (this.commit as GitStashCommit).files; // Check for any untracked files -- since git doesn't return them via `git stash list` :( const log = await Container.git.getLog(this.commit.repoPath, { @@ -34,14 +34,14 @@ export class StashNode extends ExplorerRefNode { }); if (log !== undefined) { const commit = Iterables.first(log.commits.values()); - if (commit !== undefined && commit.fileStatuses.length !== 0) { + if (commit !== undefined && commit.files.length !== 0) { // Since these files are untracked -- make them look that way - commit.fileStatuses.forEach(s => (s.status = '?')); - statuses.splice(statuses.length, 0, ...commit.fileStatuses); + commit.files.forEach(s => (s.status = '?')); + files.splice(files.length, 0, ...commit.files); } } - const children = statuses.map(s => new StashFileNode(s, this.commit.toFileCommit(s), this, this.explorer)); + const children = files.map(s => new StashFileNode(s, this.commit.toFileCommit(s), this, this.explorer)); children.sort((a, b) => a.label!.localeCompare(b.label!)); return children; } diff --git a/src/views/nodes/statusFileCommitsNode.ts b/src/views/nodes/statusFileCommitsNode.ts index 804e885..411d6b3 100644 --- a/src/views/nodes/statusFileCommitsNode.ts +++ b/src/views/nodes/statusFileCommitsNode.ts @@ -2,13 +2,11 @@ import * as path from 'path'; import { Command, TreeItem, TreeItemCollapsibleState } from 'vscode'; import { Commands, DiffWithPreviousCommandArgs } from '../../commands'; -import { Container } from '../../container'; import { - getGitStatusIcon, + GitFile, + GitFileWithCommit, GitLogCommit, GitUri, - IGitStatusFile, - IGitStatusFileWithCommit, IStatusFormatOptions, StatusFileFormatter } from '../../git/gitService'; @@ -20,19 +18,19 @@ import { ExplorerNode, ResourceType } from './explorerNode'; export class StatusFileCommitsNode extends ExplorerNode { constructor( public readonly repoPath: string, - public readonly status: IGitStatusFile, + public readonly file: GitFile, public readonly commits: GitLogCommit[], parent: ExplorerNode, public readonly explorer: Explorer ) { - super(GitUri.fromFileStatus(status, repoPath, 'HEAD'), parent); + super(GitUri.fromFile(file, repoPath, 'HEAD'), parent); } async getChildren(): Promise { return this.commits.map( c => new CommitFileNode( - this.status, + this.file, c, this, this.explorer, @@ -53,14 +51,12 @@ export class StatusFileCommitsNode extends ExplorerNode { if (this.commit.isStagedUncommitted) { item.tooltip = StatusFileFormatter.fromTemplate( - '${status} in index\n\n${file}\n${directory}/', - this.status + this.file ); } else { item.tooltip = StatusFileFormatter.fromTemplate( - '${status} in working tree\n\n${file}\n${directory}/', - this.status + this.file ); } item.command = this.getCommand(); @@ -68,8 +64,7 @@ export class StatusFileCommitsNode extends ExplorerNode { else { item.contextValue = ResourceType.StatusFileCommits; item.tooltip = StatusFileFormatter.fromTemplate( - `\${status} in ${this.getChangedIn()}\n\n\${file}\n\${directory}/`, - this.status + this.file ); } @@ -102,9 +97,9 @@ export class StatusFileCommitsNode extends ExplorerNode { this._label = StatusFileFormatter.fromTemplate( this.explorer.config.statusFileFormat, { - ...this.status, + ...this.file, commit: this.commit - } as IGitStatusFileWithCommit, + } as GitFileWithCommit, { relativePath: this.relativePath } as IStatusFormatOptions @@ -163,7 +158,7 @@ export class StatusFileCommitsNode extends ExplorerNode { title: 'Compare File with Previous Revision', command: Commands.DiffWithPrevious, arguments: [ - GitUri.fromFileStatus(this.status, this.repoPath), + GitUri.fromFile(this.file, this.repoPath), { commit: this.commit, line: 0, diff --git a/src/views/nodes/statusFileNode.ts b/src/views/nodes/statusFileNode.ts index d5a9eba..2684a3d 100644 --- a/src/views/nodes/statusFileNode.ts +++ b/src/views/nodes/statusFileNode.ts @@ -3,26 +3,20 @@ import * as path from 'path'; import { Command, TreeItem, TreeItemCollapsibleState } from 'vscode'; import { Commands, DiffWithCommandArgs } from '../../commands'; import { Container } from '../../container'; -import { - getGitStatusIcon, - GitStatusFile, - GitUri, - IStatusFormatOptions, - StatusFileFormatter -} from '../../git/gitService'; +import { GitFile, GitStatusFile, GitUri, IStatusFormatOptions, StatusFileFormatter } from '../../git/gitService'; import { Explorer } from '../explorer'; import { ExplorerNode, ResourceType } from './explorerNode'; export class StatusFileNode extends ExplorerNode { constructor( public readonly repoPath: string, - private readonly _status: GitStatusFile, + private readonly _file: GitStatusFile, private readonly _ref1: string, private readonly _ref2: string, parent: ExplorerNode, public readonly explorer: Explorer ) { - super(GitUri.fromFileStatus(_status, repoPath, _ref1 ? _ref1 : _ref2 ? _ref2 : undefined), parent); + super(GitUri.fromFile(_file, repoPath, _ref1 ? _ref1 : _ref2 ? _ref2 : undefined), parent); } getChildren(): ExplorerNode[] { @@ -32,9 +26,9 @@ export class StatusFileNode extends ExplorerNode { getTreeItem(): TreeItem { const item = new TreeItem(this.label, TreeItemCollapsibleState.None); item.contextValue = ResourceType.StatusFile; - item.tooltip = StatusFileFormatter.fromTemplate('${file}\n${directory}/\n\n${status}', this._status); + item.tooltip = StatusFileFormatter.fromTemplate('${file}\n${directory}/\n\n${status}', this._file); - const statusIcon = getGitStatusIcon(this._status.status); + const statusIcon = GitFile.getStatusIcon(this._file.status); item.iconPath = { dark: Container.context.asAbsolutePath(path.join('images', 'dark', statusIcon)), light: Container.context.asAbsolutePath(path.join('images', 'light', statusIcon)) @@ -55,7 +49,7 @@ export class StatusFileNode extends ExplorerNode { private _label: string | undefined; get label() { if (this._label === undefined) { - this._label = StatusFileFormatter.fromTemplate(this.explorer.config.statusFileFormat, this._status, { + this._label = StatusFileFormatter.fromTemplate(this.explorer.config.statusFileFormat, this._file, { relativePath: this.relativePath } as IStatusFormatOptions); } @@ -89,8 +83,8 @@ export class StatusFileNode extends ExplorerNode { rhs: { sha: this._ref2, uri: - this._status.status === 'R' - ? GitUri.fromFileStatus(this._status, this.uri.repoPath!, this._ref2, true) + this._file.status === 'R' + ? GitUri.fromFile(this._file, this.uri.repoPath!, this._ref2, true) : this.uri }, repoPath: this.uri.repoPath!, diff --git a/src/views/nodes/statusFilesNode.ts b/src/views/nodes/statusFilesNode.ts index bf85a5c..b43a43d 100644 --- a/src/views/nodes/statusFilesNode.ts +++ b/src/views/nodes/statusFilesNode.ts @@ -6,12 +6,12 @@ import { Container } from '../../container'; import { GitStatusFile } from '../../git/git'; import { GitCommitType, + GitFileWithCommit, GitLog, GitLogCommit, GitService, GitStatus, - GitUri, - IGitStatusFileWithCommit + GitUri } from '../../git/gitService'; import { Arrays, Iterables, Objects, Strings } from '../../system'; import { RepositoriesExplorer } from '../repositoriesExplorer'; @@ -37,7 +37,7 @@ export class StatusFilesNode extends ExplorerNode { } async getChildren(): Promise { - let statuses: IGitStatusFileWithCommit[] = []; + let files: GitFileWithCommit[] = []; const repoPath = this.repoPath; @@ -45,20 +45,20 @@ export class StatusFilesNode extends ExplorerNode { if (this.range !== undefined) { log = await Container.git.getLog(repoPath, { maxCount: 0, ref: this.range }); if (log !== undefined) { - statuses = [ + files = [ ...Iterables.flatMap(log.commits.values(), c => - c.fileStatuses.map(s => ({ ...s, commit: c } as IGitStatusFileWithCommit)) + c.files.map(s => ({ ...s, commit: c } as GitFileWithCommit)) ) ]; } } if (this.status.files.length !== 0 && this.includeWorkingTree) { - statuses.splice( + files.splice( 0, 0, ...Iterables.flatMap(this.status.files, s => { - if (s.workTreeStatus !== undefined && s.indexStatus !== undefined) { + if (s.workingTreeStatus !== undefined && s.indexStatus !== undefined) { // Decrements the date to guarantee this entry will be sorted after the previous entry (most recent first) const older = new Date(); older.setMilliseconds(older.getMilliseconds() - 1); @@ -78,18 +78,18 @@ export class StatusFilesNode extends ExplorerNode { ); } - statuses.sort((a, b) => b.commit.date.getTime() - a.commit.date.getTime()); + files.sort((a, b) => b.commit.date.getTime() - a.commit.date.getTime()); - const groups = Arrays.groupBy(statuses, s => s.fileName); + const groups = Arrays.groupBy(files, s => s.fileName); let children: FileExplorerNode[] = [ ...Iterables.map( Objects.values(groups), - statuses => + files => new StatusFileCommitsNode( repoPath, - statuses[statuses.length - 1], - statuses.map(s => s.commit), + files[files.length - 1], + files.map(s => s.commit), this, this.explorer ) @@ -156,28 +156,28 @@ export class StatusFilesNode extends ExplorerNode { return this.explorer.config.includeWorkingTree; } - private toStatusFile(s: GitStatusFile, ref: string, previousRef: string, date?: Date): IGitStatusFileWithCommit { + private toStatusFile(file: GitStatusFile, ref: string, previousRef: string, date?: Date): GitFileWithCommit { return { - status: s.status, - repoPath: s.repoPath, - indexStatus: s.indexStatus, - workTreeStatus: s.workTreeStatus, - fileName: s.fileName, - originalFileName: s.originalFileName, + status: file.status, + repoPath: file.repoPath, + indexStatus: file.indexStatus, + workingTreeStatus: file.workingTreeStatus, + fileName: file.fileName, + originalFileName: file.originalFileName, commit: new GitLogCommit( GitCommitType.File, - s.repoPath, + file.repoPath, ref, 'You', undefined, date || new Date(), '', - s.fileName, - [s], - s.status, - s.originalFileName, + file.fileName, + [file], + file.status, + file.originalFileName, previousRef, - s.fileName + file.fileName ) }; }