Files
vscode-gitlens/src/git/gitEnrichment.ts
Eric Amodio 73bbbc1d5f Adds compare with branch command
Adds branches quick pick
2017-03-18 02:01:25 -04:00

240 lines
5.9 KiB
TypeScript

'use strict';
import { Uri } from 'vscode';
import { Git } from './git';
import * as path from 'path';
export interface IGitEnricher<T> {
enrich(data: string, ...args: any[]): T;
}
export interface IGitBlame {
repoPath: string;
authors: Map<string, IGitAuthor>;
commits: Map<string, GitCommit>;
lines: IGitCommitLine[];
}
export interface IGitBlameLine {
author: IGitAuthor;
commit: GitCommit;
line: IGitCommitLine;
}
export interface IGitBlameLines extends IGitBlame {
allLines: IGitCommitLine[];
}
export interface IGitBlameCommitLines {
author: IGitAuthor;
commit: GitCommit;
lines: IGitCommitLine[];
}
export interface IGitAuthor {
name: string;
lineCount: number;
}
interface IGitCommit {
repoPath: string;
sha: string;
fileName: string;
author: string;
date: Date;
message: string;
lines: IGitCommitLine[];
originalFileName?: string;
previousSha?: string;
previousFileName?: string;
readonly isUncommitted: boolean;
previousUri: Uri;
uri: Uri;
}
export class GitCommit implements IGitCommit {
lines: IGitCommitLine[];
originalFileName?: string;
previousSha?: string;
previousFileName?: string;
private _isUncommitted: boolean | undefined;
constructor(
public repoPath: string,
public sha: string,
public fileName: string,
public author: string,
public date: Date,
public message: string,
lines?: IGitCommitLine[],
originalFileName?: string,
previousSha?: string,
previousFileName?: string
) {
this.fileName = this.fileName.replace(/, ?$/, '');
this.lines = lines || [];
this.originalFileName = originalFileName;
this.previousSha = previousSha;
this.previousFileName = previousFileName;
}
get shortSha() {
return this.sha.substring(0, 8);
}
get isUncommitted(): boolean {
if (this._isUncommitted === undefined) {
this._isUncommitted = Git.isUncommitted(this.sha);
}
return this._isUncommitted;
}
get previousShortSha() {
return this.previousSha && this.previousSha.substring(0, 8);
}
get previousUri(): Uri {
return this.previousFileName ? Uri.file(path.resolve(this.repoPath, this.previousFileName)) : this.uri;
}
get uri(): Uri {
return Uri.file(path.resolve(this.repoPath, this.originalFileName || this.fileName));
}
getFormattedPath(separator: string = ' \u00a0\u2022\u00a0 '): string {
const directory = path.dirname(this.fileName);
return (!directory || directory === '.')
? path.basename(this.fileName)
: `${path.basename(this.fileName)}${separator}${directory}`;
}
}
export type GitLogType = 'file' | 'repo';
export class GitLogCommit extends GitCommit {
fileNames: string;
fileStatuses: { status: GitFileStatus, fileName: string }[];
nextSha?: string;
nextFileName?: string;
status: GitFileStatus;
constructor(
public type: GitLogType,
repoPath: string,
sha: string,
fileName: string,
author: string,
date: Date,
message: string,
status?: GitFileStatus,
fileStatuses?: { status: GitFileStatus, fileName: string }[],
lines?: IGitCommitLine[],
originalFileName?: string,
previousSha?: string,
previousFileName?: string
) {
super(repoPath, sha, fileName, author, date, message, lines, originalFileName, previousSha, previousFileName);
this.status = status;
this.fileNames = this.fileName;
if (fileStatuses) {
this.fileStatuses = fileStatuses.filter(_ => !!_.fileName);
this.fileName = this.fileStatuses[0].fileName;
}
else {
this.fileStatuses = [{ status: status, fileName: fileName }];
}
}
get nextShortSha() {
return this.nextSha && this.nextSha.substring(0, 8);
}
get nextUri(): Uri {
return this.nextFileName ? Uri.file(path.resolve(this.repoPath, this.nextFileName)) : this.uri;
}
}
export interface IGitCommitLine {
sha: string;
previousSha?: string;
line: number;
originalLine: number;
code?: string;
}
export interface IGitLog {
repoPath: string;
authors: Map<string, IGitAuthor>;
commits: Map<string, GitLogCommit>;
maxCount: number | undefined;
truncated: boolean;
}
export declare type GitFileStatus = '?' | 'A' | 'C' | 'D' | 'M' | 'R' | 'U';
export class GitFileStatusItem {
staged: boolean;
status: GitFileStatus;
fileName: string;
constructor(public repoPath: string, status: string) {
this.fileName = status.substring(3);
this.parseStatus(status);
}
private parseStatus(status: string) {
const indexStatus = status[0].trim();
const workTreeStatus = status[1].trim();
this.staged = !!indexStatus;
this.status = (indexStatus || workTreeStatus || 'U') as GitFileStatus;
}
}
const statusOcticonsMap = {
'?': '$(diff-ignored)',
A: '$(diff-added)',
C: '$(diff-added)',
D: '$(diff-removed)',
M: '$(diff-modified)',
R: '$(diff-renamed)',
U: '$(question)'
};
export function getGitStatusIcon(status: GitFileStatus, missing: string = '\u00a0\u00a0\u00a0\u00a0'): string {
return statusOcticonsMap[status] || missing;
}
export class GitBranch {
current: boolean;
name: string;
remote: boolean;
constructor(branch: string) {
branch = branch.trim();
if (branch.startsWith('* ')) {
branch = branch.substring(2);
this.current = true;
}
if (branch.startsWith('remotes/')) {
branch = branch.substring(8);
this.remote = true;
}
const index = branch.indexOf(' ');
if (index !== -1) {
branch = branch.substring(0, index);
}
this.name = branch;
}
}