1/*---------------------------------------------------------------------------------------------
2 *  Copyright (c) Microsoft Corporation. All rights reserved.
3 *  Licensed under the MIT License. See License.txt in the project root for license information.
4 *--------------------------------------------------------------------------------------------*/
5
6import { Uri, Event, Disposable, ProviderResult } from 'vscode';
7export { ProviderResult } from 'vscode';
8
9export interface Git {
10	readonly path: string;
11}
12
13export interface InputBox {
14	value: string;
15}
16
17export const enum ForcePushMode {
18	Force,
19	ForceWithLease
20}
21
22export const enum RefType {
23	Head,
24	RemoteHead,
25	Tag
26}
27
28export interface Ref {
29	readonly type: RefType;
30	readonly name?: string;
31	readonly commit?: string;
32	readonly remote?: string;
33}
34
35export interface UpstreamRef {
36	readonly remote: string;
37	readonly name: string;
38}
39
40export interface Branch extends Ref {
41	readonly upstream?: UpstreamRef;
42	readonly ahead?: number;
43	readonly behind?: number;
44}
45
46export interface Commit {
47	readonly hash: string;
48	readonly message: string;
49	readonly parents: string[];
50	readonly authorDate?: Date;
51	readonly authorName?: string;
52	readonly authorEmail?: string;
53	readonly commitDate?: Date;
54}
55
56export interface Submodule {
57	readonly name: string;
58	readonly path: string;
59	readonly url: string;
60}
61
62export interface Remote {
63	readonly name: string;
64	readonly fetchUrl?: string;
65	readonly pushUrl?: string;
66	readonly isReadOnly: boolean;
67}
68
69export const enum Status {
70	INDEX_MODIFIED,
71	INDEX_ADDED,
72	INDEX_DELETED,
73	INDEX_RENAMED,
74	INDEX_COPIED,
75
76	MODIFIED,
77	DELETED,
78	UNTRACKED,
79	IGNORED,
80	INTENT_TO_ADD,
81
82	ADDED_BY_US,
83	ADDED_BY_THEM,
84	DELETED_BY_US,
85	DELETED_BY_THEM,
86	BOTH_ADDED,
87	BOTH_DELETED,
88	BOTH_MODIFIED
89}
90
91export interface Change {
92
93	/**
94	 * Returns either `originalUri` or `renameUri`, depending
95	 * on whether this change is a rename change. When
96	 * in doubt always use `uri` over the other two alternatives.
97	 */
98	readonly uri: Uri;
99	readonly originalUri: Uri;
100	readonly renameUri: Uri | undefined;
101	readonly status: Status;
102}
103
104export interface RepositoryState {
105	readonly HEAD: Branch | undefined;
106	readonly refs: Ref[];
107	readonly remotes: Remote[];
108	readonly submodules: Submodule[];
109	readonly rebaseCommit: Commit | undefined;
110
111	readonly mergeChanges: Change[];
112	readonly indexChanges: Change[];
113	readonly workingTreeChanges: Change[];
114
115	readonly onDidChange: Event<void>;
116}
117
118export interface RepositoryUIState {
119	readonly selected: boolean;
120	readonly onDidChange: Event<void>;
121}
122
123/**
124 * Log options.
125 */
126export interface LogOptions {
127	/** Max number of log entries to retrieve. If not specified, the default is 32. */
128	readonly maxEntries?: number;
129	readonly path?: string;
130}
131
132export interface CommitOptions {
133	all?: boolean | 'tracked';
134	amend?: boolean;
135	signoff?: boolean;
136	signCommit?: boolean;
137	empty?: boolean;
138	noVerify?: boolean;
139	requireUserConfig?: boolean;
140}
141
142export interface FetchOptions {
143	remote?: string;
144	ref?: string;
145	all?: boolean;
146	prune?: boolean;
147	depth?: number;
148}
149
150export interface BranchQuery {
151	readonly remote?: boolean;
152	readonly pattern?: string;
153	readonly count?: number;
154	readonly contains?: string;
155}
156
157export interface Repository {
158
159	readonly rootUri: Uri;
160	readonly inputBox: InputBox;
161	readonly state: RepositoryState;
162	readonly ui: RepositoryUIState;
163
164	getConfigs(): Promise<{ key: string; value: string; }[]>;
165	getConfig(key: string): Promise<string>;
166	setConfig(key: string, value: string): Promise<string>;
167	getGlobalConfig(key: string): Promise<string>;
168
169	getObjectDetails(treeish: string, path: string): Promise<{ mode: string, object: string, size: number }>;
170	detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }>;
171	buffer(ref: string, path: string): Promise<Buffer>;
172	show(ref: string, path: string): Promise<string>;
173	getCommit(ref: string): Promise<Commit>;
174
175	clean(paths: string[]): Promise<void>;
176
177	apply(patch: string, reverse?: boolean): Promise<void>;
178	diff(cached?: boolean): Promise<string>;
179	diffWithHEAD(): Promise<Change[]>;
180	diffWithHEAD(path: string): Promise<string>;
181	diffWith(ref: string): Promise<Change[]>;
182	diffWith(ref: string, path: string): Promise<string>;
183	diffIndexWithHEAD(): Promise<Change[]>;
184	diffIndexWithHEAD(path: string): Promise<string>;
185	diffIndexWith(ref: string): Promise<Change[]>;
186	diffIndexWith(ref: string, path: string): Promise<string>;
187	diffBlobs(object1: string, object2: string): Promise<string>;
188	diffBetween(ref1: string, ref2: string): Promise<Change[]>;
189	diffBetween(ref1: string, ref2: string, path: string): Promise<string>;
190
191	hashObject(data: string): Promise<string>;
192
193	createBranch(name: string, checkout: boolean, ref?: string): Promise<void>;
194	deleteBranch(name: string, force?: boolean): Promise<void>;
195	getBranch(name: string): Promise<Branch>;
196	getBranches(query: BranchQuery): Promise<Ref[]>;
197	setBranchUpstream(name: string, upstream: string): Promise<void>;
198
199	getMergeBase(ref1: string, ref2: string): Promise<string>;
200
201	status(): Promise<void>;
202	checkout(treeish: string): Promise<void>;
203
204	addRemote(name: string, url: string): Promise<void>;
205	removeRemote(name: string): Promise<void>;
206	renameRemote(name: string, newName: string): Promise<void>;
207
208	fetch(options?: FetchOptions): Promise<void>;
209	fetch(remote?: string, ref?: string, depth?: number): Promise<void>;
210	pull(unshallow?: boolean): Promise<void>;
211	push(remoteName?: string, branchName?: string, setUpstream?: boolean, force?: ForcePushMode): Promise<void>;
212
213	blame(path: string): Promise<string>;
214	log(options?: LogOptions): Promise<Commit[]>;
215
216	commit(message: string, opts?: CommitOptions): Promise<void>;
217}
218
219export interface RemoteSource {
220	readonly name: string;
221	readonly description?: string;
222	readonly url: string | string[];
223}
224
225export interface RemoteSourceProvider {
226	readonly name: string;
227	readonly icon?: string; // codicon name
228	readonly supportsQuery?: boolean;
229	getRemoteSources(query?: string): ProviderResult<RemoteSource[]>;
230	getBranches?(url: string): ProviderResult<string[]>;
231	publishRepository?(repository: Repository): Promise<void>;
232}
233
234export interface Credentials {
235	readonly username: string;
236	readonly password: string;
237}
238
239export interface CredentialsProvider {
240	getCredentials(host: Uri): ProviderResult<Credentials>;
241}
242
243export interface PushErrorHandler {
244	handlePushError(repository: Repository, remote: Remote, refspec: string, error: Error & { gitErrorCode: GitErrorCodes }): Promise<boolean>;
245}
246
247export type APIState = 'uninitialized' | 'initialized';
248
249export interface PublishEvent {
250	repository: Repository;
251	branch?: string;
252}
253
254export interface API {
255	readonly state: APIState;
256	readonly onDidChangeState: Event<APIState>;
257	readonly onDidPublish: Event<PublishEvent>;
258	readonly git: Git;
259	readonly repositories: Repository[];
260	readonly onDidOpenRepository: Event<Repository>;
261	readonly onDidCloseRepository: Event<Repository>;
262
263	toGitUri(uri: Uri, ref: string): Uri;
264	getRepository(uri: Uri): Repository | null;
265	init(root: Uri): Promise<Repository | null>;
266	openRepository(root: Uri): Promise<Repository | null>
267
268	registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
269	registerCredentialsProvider(provider: CredentialsProvider): Disposable;
270	registerPushErrorHandler(handler: PushErrorHandler): Disposable;
271}
272
273export interface GitExtension {
274
275	readonly enabled: boolean;
276	readonly onDidChangeEnablement: Event<boolean>;
277
278	/**
279	 * Returns a specific API version.
280	 *
281	 * Throws error if git extension is disabled. You can listed to the
282	 * [GitExtension.onDidChangeEnablement](#GitExtension.onDidChangeEnablement) event
283	 * to know when the extension becomes enabled/disabled.
284	 *
285	 * @param version Version number.
286	 * @returns API instance
287	 */
288	getAPI(version: 1): API;
289}
290
291export const enum GitErrorCodes {
292	BadConfigFile = 'BadConfigFile',
293	AuthenticationFailed = 'AuthenticationFailed',
294	NoUserNameConfigured = 'NoUserNameConfigured',
295	NoUserEmailConfigured = 'NoUserEmailConfigured',
296	NoRemoteRepositorySpecified = 'NoRemoteRepositorySpecified',
297	NotAGitRepository = 'NotAGitRepository',
298	NotAtRepositoryRoot = 'NotAtRepositoryRoot',
299	Conflict = 'Conflict',
300	StashConflict = 'StashConflict',
301	UnmergedChanges = 'UnmergedChanges',
302	PushRejected = 'PushRejected',
303	RemoteConnectionError = 'RemoteConnectionError',
304	DirtyWorkTree = 'DirtyWorkTree',
305	CantOpenResource = 'CantOpenResource',
306	GitNotFound = 'GitNotFound',
307	CantCreatePipe = 'CantCreatePipe',
308	PermissionDenied = 'PermissionDenied',
309	CantAccessRemote = 'CantAccessRemote',
310	RepositoryNotFound = 'RepositoryNotFound',
311	RepositoryIsLocked = 'RepositoryIsLocked',
312	BranchNotFullyMerged = 'BranchNotFullyMerged',
313	NoRemoteReference = 'NoRemoteReference',
314	InvalidBranchName = 'InvalidBranchName',
315	BranchAlreadyExists = 'BranchAlreadyExists',
316	NoLocalChanges = 'NoLocalChanges',
317	NoStashFound = 'NoStashFound',
318	LocalChangesOverwritten = 'LocalChangesOverwritten',
319	NoUpstreamBranch = 'NoUpstreamBranch',
320	IsInSubmodule = 'IsInSubmodule',
321	WrongCase = 'WrongCase',
322	CantLockRef = 'CantLockRef',
323	CantRebaseMultipleBranches = 'CantRebaseMultipleBranches',
324	PatchDoesNotApply = 'PatchDoesNotApply',
325	NoPathFound = 'NoPathFound',
326	UnknownPath = 'UnknownPath',
327}
328