git: implement API

This commit is contained in:
Joao Moreno
2018-08-24 12:04:29 +02:00
parent 28d2b5d2d6
commit 103715c3cc
5 changed files with 238 additions and 17 deletions

View File

@@ -6,8 +6,8 @@
'use strict';
import { Model } from '../model';
import { Repository as BaseRepository } from '../repository';
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit } from './git';
import { Repository as BaseRepository, Resource } from '../repository';
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change } from './git';
import { Event, SourceControlInputBox, Uri } from 'vscode';
import { mapEvent } from '../util';
@@ -17,6 +17,11 @@ class ApiInputBox implements InputBox {
constructor(private _inputBox: SourceControlInputBox) { }
}
export class ApiChange implements Change {
constructor(_resource: Resource) { }
}
export class ApiRepositoryState implements RepositoryState {
get HEAD(): Branch | undefined { return this._repository.HEAD; }
@@ -25,6 +30,10 @@ export class ApiRepositoryState implements RepositoryState {
get submodules(): Submodule[] { return [...this._repository.submodules]; }
get rebaseCommit(): Commit | undefined { return this._repository.rebaseCommit; }
get mergeChanges(): Change[] { return this._repository.mergeGroup.resourceStates.map(r => new ApiChange(r)); }
get indexChanges(): Change[] { return this._repository.indexGroup.resourceStates.map(r => new ApiChange(r)); }
get workingTreeChanges(): Change[] { return this._repository.workingTreeGroup.resourceStates.map(r => new ApiChange(r)); }
readonly onDidChange: Event<void> = this._repository.onDidRunGitStatus;
constructor(private _repository: BaseRepository) { }
@@ -38,9 +47,101 @@ export class ApiRepository implements Repository {
constructor(private _repository: BaseRepository) { }
getConfigs(): Promise<{ key: string; value: string; }[]> {
return this._repository.getConfigs();
}
getConfig(key: string): Promise<string> {
return this._repository.getConfig(key);
}
setConfig(key: string, value: string): Promise<string> {
return this._repository.setConfig(key, value);
}
show(ref: string, path: string): Promise<string> {
return this._repository.show(ref, path);
}
getCommit(ref: string): Promise<Commit> {
return this._repository.getCommit(ref);
}
getObjectDetails(treeish: string, path: string): Promise<{ mode: string; object: string; size: number; }> {
return this._repository.getObjectDetails(treeish, path);
}
diffWithHEAD(path: string): Promise<string> {
return this._repository.diffWithHEAD(path);
}
diffWith(ref: string, path: string): Promise<string> {
return this._repository.diffWith(ref, path);
}
diffIndexWithHEAD(path: string): Promise<string> {
return this._repository.diffIndexWithHEAD(path);
}
diffIndexWith(ref: string, path: string): Promise<string> {
return this._repository.diffIndexWith(ref, path);
}
diffBlobs(object1: string, object2: string): Promise<string> {
return this._repository.diffBlobs(object1, object2);
}
diffBetween(ref1: string, ref2: string, path: string): Promise<string> {
return this._repository.diffBetween(ref1, ref2, path);
}
hashObject(data: string): Promise<string> {
return this._repository.hashObject(data);
}
createBranch(name: string, checkout: boolean, ref?: string | undefined): Promise<void> {
return this._repository.branch(name, checkout, ref);
}
deleteBranch(name: string): Promise<void> {
return this._repository.deleteBranch(name);
}
getBranch(name: string): Promise<Branch> {
return this._repository.getBranch(name);
}
setBranchUpstream(name: string, upstream: string): Promise<void> {
return this._repository.setBranchUpstream(name, upstream);
}
getMergeBase(ref1: string, ref2: string): Promise<string> {
throw new Error('Method not implemented.');
}
status(): Promise<void> {
return this._repository.status();
}
checkout(treeish: string): Promise<void> {
return this._repository.checkout(treeish);
}
addRemote(name: string, url: string): Promise<void> {
return this._repository.addRemote(name, url);
}
removeRemote(name: string): Promise<void> {
return this._repository.removeRemote(name);
}
fetch(remote?: string | undefined, ref?: string | undefined): Promise<void> {
return this._repository.fetch(remote, ref);
}
pull(): Promise<void> {
return this._repository.pull();
}
}
export class ApiGit implements Git {

View File

@@ -74,21 +74,15 @@ export interface RepositoryState {
readonly onDidChange: Event<void>;
}
export const enum ConfigScope {
System,
Global,
Local
}
export interface Repository {
readonly rootUri: Uri;
readonly inputBox: InputBox;
readonly state: RepositoryState;
getConfigs(scope: ConfigScope): Promise<{ key: string; value: string; }[]>;
getConfig(scope: ConfigScope, key: string): Promise<string>;
setConfig(scope: ConfigScope, key: string, value: string): Promise<string>;
getConfigs(): Promise<{ key: string; value: string; }[]>;
getConfig(key: string): Promise<string>;
setConfig(key: string, value: string): Promise<string>;
show(ref: string, path: string): Promise<string>;
getCommit(ref: string): Promise<Commit>;

View File

@@ -92,7 +92,11 @@ export class GitContentProvider {
return '';
}
return await repository.diff(path, ref === 'index');
if (ref === 'index') {
return await repository.diffIndexWithHEAD(path);
} else {
return await repository.diffWithHEAD(path);
}
}
const repository = this.model.getRepository(uri);

View File

@@ -682,7 +682,7 @@ export class Repository {
return this.git.spawn(args, options);
}
async config(scope: string, key: string, value: any, options: SpawnOptions): Promise<string> {
async config(scope: string, key: string, value: any = null, options: SpawnOptions = {}): Promise<string> {
const args = ['config'];
if (scope) {
@@ -699,6 +699,24 @@ export class Repository {
return result.stdout;
}
async getConfigs(scope: string): Promise<{ key: string; value: string; }[]> {
const args = ['config'];
if (scope) {
args.push('--' + scope);
}
args.push('-l');
const result = await this.run(args);
const lines = result.stdout.trim().split(/\r|\r\n|\n/);
return lines.map(entry => {
const equalsIndex = entry.indexOf('=');
return { key: entry.substr(0, equalsIndex), value: entry.substr(equalsIndex + 1) };
});
}
async bufferString(object: string, encoding: string = 'utf8', autoGuessEncoding = false): Promise<string> {
const stdout = await this.buffer(object);
@@ -837,6 +855,36 @@ export class Repository {
return result.stdout;
}
async diffWithHEAD(path: string): Promise<string> {
const args = ['diff', '--', path];
const result = await this.run(args);
return result.stdout;
}
async diffWith(ref: string, path: string): Promise<string> {
const args = ['diff', ref, '--', path];
const result = await this.run(args);
return result.stdout;
}
async diffIndexWithHEAD(path: string): Promise<string> {
const args = ['diff', '--cached', '--', path];
const result = await this.run(args);
return result.stdout;
}
async diffIndexWith(ref: string, path: string): Promise<string> {
const args = ['diff', '--cached', ref, '--', path];
const result = await this.run(args);
return result.stdout;
}
async diffBlobs(object1: string, object2: string): Promise<string> {
const args = ['diff', object1, object2];
const result = await this.run(args);
return result.stdout;
}
async diffBetween(ref1: string, ref2: string, path: string): Promise<string> {
const args = ['diff', `${ref1}...${ref2}`, '--', path];
const result = await this.run(args);
@@ -851,6 +899,13 @@ export class Repository {
return result.stdout.trim();
}
async hashObject(data: string): Promise<string> {
const args = ['hash-object', '-w', '--stdin'];
const result = await this.run(args, { input: data });
return result.stdout.trim();
}
async add(paths: string[]): Promise<void> {
const args = ['add', '-A', '--'];
@@ -1098,6 +1153,11 @@ export class Repository {
await this.run(args);
}
async removeRemote(name: string): Promise<void> {
const args = ['remote', 'rm', name];
await this.run(args);
}
async fetch(remote?: string, ref?: string): Promise<void> {
const args = ['fetch'];

View File

@@ -6,7 +6,7 @@
'use strict';
import { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType } from 'vscode';
import { Repository as BaseRepository, Commit, GitErrorCodes, Stash, GitError, Submodule, DiffOptions } from './git';
import { Repository as BaseRepository, Commit, GitErrorCodes, Stash, GitError, Submodule } from './git';
import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent } from './util';
import { memoize, throttle, debounce } from './decorators';
import { toGitUri } from './uri';
@@ -277,14 +277,20 @@ export class Resource implements SourceControlResourceState {
export enum Operation {
Status = 'Status',
Config = 'Config',
Diff = 'Diff',
MergeBase = 'MergeBase',
Add = 'Add',
RevertFiles = 'RevertFiles',
Commit = 'Commit',
Clean = 'Clean',
Branch = 'Branch',
GetBranch = 'GetBranch',
SetBranchUpstream = 'SetBranchUpstream',
HashObject = 'HashObject',
Checkout = 'Checkout',
Reset = 'Reset',
Remote = 'Remote',
Fetch = 'Fetch',
Pull = 'Pull',
Push = 'Push',
@@ -650,13 +656,53 @@ export class Repository implements Disposable {
}
}
getConfigs(): Promise<{ key: string; value: string; }[]> {
return this.run(Operation.Config, () => this.repository.getConfigs('local'));
}
getConfig(key: string): Promise<string> {
return this.run(Operation.Config, () => this.repository.config('local', key));
}
setConfig(key: string, value: string): Promise<string> {
return this.run(Operation.Config, () => this.repository.config('local', key, value));
}
@throttle
async status(): Promise<void> {
await this.run(Operation.Status);
}
diff(path: string, cached = false): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diff(path, cached));
diffWithHEAD(path: string): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diffWithHEAD(path));
}
diffWith(ref: string, path: string): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diffWith(ref, path));
}
diffIndexWithHEAD(path: string): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diffIndexWithHEAD(path));
}
diffIndexWith(ref: string, path: string): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diffIndexWith(ref, path));
}
diffBlobs(object1: string, object2: string): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diffBlobs(object1, object2));
}
diffBetween(ref1: string, ref2: string, path: string): Promise<string> {
return this.run(Operation.Diff, () => this.repository.diffBetween(ref1, ref2, path));
}
getMergeBase(ref1: string, ref2: string): Promise<string> {
return this.run(Operation.MergeBase, () => this.repository.getMergeBase(ref1, ref2));
}
async hashObject(data: string): Promise<string> {
return this.run(Operation.HashObject, () => this.repository.hashObject(data));
}
async add(resources: Uri[]): Promise<void> {
@@ -758,6 +804,14 @@ export class Repository implements Disposable {
await this.run(Operation.RenameBranch, () => this.repository.renameBranch(name));
}
async getBranch(name: string): Promise<Branch> {
return await this.run(Operation.GetBranch, () => this.repository.getBranch(name));
}
async setBranchUpstream(name: string, upstream: string): Promise<void> {
await this.run(Operation.SetBranchUpstream, () => this.repository.setBranchUpstream(name, upstream));
}
async merge(ref: string): Promise<void> {
await this.run(Operation.Merge, () => this.repository.merge(ref));
}
@@ -782,6 +836,14 @@ export class Repository implements Disposable {
await this.run(Operation.DeleteRef, () => this.repository.deleteRef(ref));
}
async addRemote(name: string, url: string): Promise<void> {
await this.run(Operation.Remote, () => this.repository.addRemote(name, url));
}
async removeRemote(name: string): Promise<void> {
await this.run(Operation.Remote, () => this.repository.removeRemote(name));
}
@throttle
async fetchDefault(): Promise<void> {
await this.run(Operation.Fetch, () => this.repository.fetch());
@@ -805,7 +867,7 @@ export class Repository implements Disposable {
}
@throttle
async pull(head: Branch | undefined): Promise<void> {
async pull(head?: Branch): Promise<void> {
let remote: string | undefined;
let branch: string | undefined;