Skip to content

Commit 37124c3

Browse files
authored
feat: impl git index features (#21)
1 parent a5110dd commit 37124c3

File tree

5 files changed

+842
-19
lines changed

5 files changed

+842
-19
lines changed

index.d.ts

Lines changed: 263 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,101 @@
66
* napi does not support union types when converting rust enum types to TypeScript.
77
* This feature will be provided starting from v3, so create a custom TypeScript until the v3 stable releases.
88
*/
9-
9+
export interface IndexEntry {
10+
ctime: Date
11+
mtime: Date
12+
dev: number
13+
ino: number
14+
mode: number
15+
uid: number
16+
gid: number
17+
fileSize: number
18+
id: string
19+
flags: number
20+
flagsExtended: number
21+
/**
22+
* The path of this index entry as a byte vector. Regardless of the
23+
* current platform, the directory separator is an ASCII forward slash
24+
* (`0x2F`). There are no terminating or internal NUL characters, and no
25+
* trailing slashes. Most of the time, paths will be valid utf-8 — but
26+
* not always. For more information on the path storage format, see
27+
* [these git docs][git-index-docs]. Note that libgit2 will take care of
28+
* handling the prefix compression mentioned there.
29+
*
30+
* [git-index-docs]: https://github.com/git/git/blob/a08a83db2bf27f015bec9a435f6d73e223c21c5e/Documentation/technical/index-format.txt#L107-L124
31+
*/
32+
path: Buffer
33+
}
34+
export interface IndexOnMatchCallbackArgs {
35+
/** The path of entry. */
36+
path: string
37+
/** The patchspec that matched it. */
38+
pathspec: string
39+
}
40+
export interface IndexAddAllOptions {
41+
/**
42+
* Files that are ignored will be skipped (unlike `addPath`). If a file is
43+
* already tracked in the index, then it will be updated even if it is
44+
* ignored. Pass the `force` flag to skip the checking of ignore rules.
45+
*/
46+
force?: boolean
47+
/**
48+
* The `pathspecs` are a list of file names or shell glob patterns that
49+
* will matched against files in the repository's working directory. Each
50+
* file that matches will be added to the index (either updating an
51+
* existing entry or adding a new entry). You can disable glob expansion
52+
* and force exact matching with the `disablePathspecMatch` flag.
53+
*/
54+
disablePathspecMatch?: boolean
55+
/**
56+
* To emulate `git add -A` and generate an error if the pathspec contains
57+
* the exact path of an ignored file (when not using `force`), add the
58+
* `checkPathspec` flag. This checks that each entry in `pathspecs`
59+
* that is an exact match to a filename on disk is either not ignored or
60+
* already in the index. If this check fails, the function will return
61+
* an error.
62+
*/
63+
checkPathspec?: boolean
64+
/**
65+
* If you provide a callback function, it will be invoked on each matching
66+
* item in the working directory immediately before it is added to /
67+
* updated in the index. Returning zero will add the item to the index,
68+
* greater than zero will skip the item, and less than zero will abort the
69+
* scan an return an error to the caller.
70+
*/
71+
onMatch?: (args: IndexOnMatchCallbackArgs) => number
72+
}
73+
export type IndexStage =
74+
/** Match any index stage. */
75+
| 'Any'
76+
/** A normal staged file in the index. (default) */
77+
| 'Normal'
78+
/** The ancestor side of a conflict. */
79+
| 'Ancestor'
80+
/** The "ours" side of a conflict. */
81+
| 'Ours'
82+
/** The "theirs" side of a conflict. */
83+
| 'Theirs';
84+
export interface IndexRemoveOptions {
85+
stage?: IndexStage
86+
}
87+
export interface IndexRemoveAllOptions {
88+
/**
89+
* If you provide a callback function, it will be invoked on each matching
90+
* item in the index immediately before it is removed. Return 0 to remove
91+
* the item, > 0 to skip the item, and < 0 to abort the scan.
92+
*/
93+
onMatch?: (args: IndexOnMatchCallbackArgs) => number
94+
}
95+
export interface IndexUpdateAllOptions {
96+
/**
97+
* If you provide a callback function, it will be invoked on each matching
98+
* item in the index immediately before it is updated (either refreshed or
99+
* removed depending on working directory state). Return 0 to proceed with
100+
* updating the item, > 0 to skip the item, and < 0 to abort the scan.
101+
*/
102+
onMatch?: (args: IndexOnMatchCallbackArgs) => number
103+
}
10104
/**
11105
* Ensure the reference name is well-formed.
12106
*
@@ -29,7 +123,7 @@
29123
export declare function isReferenceNameValid(refname: string): boolean
30124
/** An enumeration of all possible kinds of references. */
31125
export type ReferenceType =
32-
/** A reference which points at an object id. */
126+
/** A reference which points at an object id. */
33127
| 'Direct'
34128
/** A reference which points at another reference. */
35129
| 'Symbolic';
@@ -123,8 +217,8 @@ export interface RenameReferenceOptions {
123217
* If the force flag is not enabled, and there's already a reference with
124218
* the given name, the renaming will fail.
125219
*/
126-
force?: boolean
127-
logMessage?: string
220+
force?: boolean;
221+
logMessage?: string;
128222
}
129223
export type Direction =
130224
| 'Fetch'
@@ -136,7 +230,7 @@ export interface RefspecObject {
136230
force: boolean;
137231
}
138232
export type Credential =
139-
/** Create a "default" credential usable for Negotiate mechanisms like NTLM or Kerberos authentication. */
233+
/** Create a "default" credential usable for Negotiate mechanisms like NTLM or Kerberos authentication. */
140234
| { type: 'Default' }
141235
/**
142236
* Create a new ssh key credential object used for querying an ssh-agent.
@@ -156,24 +250,24 @@ export interface ProxyOptions {
156250
*
157251
* Note that this will override `url` specified before.
158252
*/
159-
auto?: boolean
253+
auto?: boolean;
160254
/**
161255
* Specify the exact URL of the proxy to use.
162256
*
163257
* Note that this will override `auto` specified before.
164258
*/
165-
url?: string
259+
url?: string;
166260
}
167261
export type FetchPrune =
168-
/** Use the setting from the configuration */
262+
/** Use the setting from the configuration */
169263
| 'Unspecified'
170264
/** Force pruning on */
171265
| 'On'
172266
/** Force pruning off */
173267
| 'Off';
174268
/** Automatic tag following options. */
175269
export type AutotagOption =
176-
/** Use the setting from the remote's configuration */
270+
/** Use the setting from the remote's configuration */
177271
| 'Unspecified'
178272
/** Ask the server for tags pointing to objects we're already downloading */
179273
| 'Auto'
@@ -189,7 +283,7 @@ export type AutotagOption =
189283
* (`/info/refs`), but not subsequent requests.
190284
*/
191285
export type RemoteRedirect =
192-
/** Do not follow any off-site redirects at any stage of the fetch or push. */
286+
/** Do not follow any off-site redirects at any stage of the fetch or push. */
193287
| 'None'
194288
/**
195289
* Allow off-site redirects only upon the initial request. This is the
@@ -335,11 +429,11 @@ export declare function revparseModeContains(source: number, target: number): bo
335429
/** A revspec represents a range of revisions within a repository. */
336430
export interface Revspec {
337431
/** Access the `from` range of this revspec. */
338-
from?: string
432+
from?: string;
339433
/** Access the `to` range of this revspec. */
340-
to?: string
434+
to?: string;
341435
/** Returns the intent of the revspec. */
342-
mode: number
436+
mode: number;
343437
}
344438
/**
345439
* A Signature is used to indicate authorship of various actions throughout the
@@ -349,17 +443,17 @@ export interface Revspec {
349443
*/
350444
export interface Signature {
351445
/** Name on the signature. */
352-
name: string
446+
name: string;
353447
/** Email on the signature. */
354-
email: string
448+
email: string;
355449
/** Time in seconds, from epoch */
356-
timestamp: number
450+
timestamp: number;
357451
}
358452
export interface CreateSignatureOptions {
359453
/** Time in seconds, from epoch */
360-
timestamp: number
454+
timestamp: number;
361455
/** Timezone offset, in minutes */
362-
offset?: number
456+
offset?: number;
363457
}
364458
/** Create a new action signature. */
365459
export declare function createSignature(name: string, email: string, options?: CreateSignatureOptions | undefined | null): Signature
@@ -421,6 +515,145 @@ export declare class Commit {
421515
*/
422516
time(): Date
423517
}
518+
/**
519+
* A structure to represent a git [index][1]
520+
*
521+
* [1]: http://git-scm.com/book/en/Git-Internals-Git-Objects
522+
*/
523+
export declare class Index {
524+
/**
525+
* Get index on-disk version.
526+
*
527+
* Valid return values are 2, 3, or 4. If 3 is returned, an index
528+
* with version 2 may be written instead, if the extension data in
529+
* version 3 is not necessary.
530+
*/
531+
version(): number
532+
/**
533+
* Set index on-disk version.
534+
*
535+
* Valid values are 2, 3, or 4. If 2 is given, git_index_write may
536+
* write an index with version 3 instead, if necessary to accurately
537+
* represent the index.
538+
*/
539+
setVersion(version: number): void
540+
/** Get one of the entries in the index by its path. */
541+
getByPath(path: string, stage?: IndexStage | undefined | null): IndexEntry | null
542+
/**
543+
* Add or update an index entry from a file on disk
544+
*
545+
* The file path must be relative to the repository's working folder and
546+
* must be readable.
547+
*
548+
* This method will fail in bare index instances.
549+
*
550+
* This forces the file to be added to the index, not looking at gitignore
551+
* rules.
552+
*
553+
* If this file currently is the result of a merge conflict, this file will
554+
* no longer be marked as conflicting. The data about the conflict will be
555+
* moved to the "resolve undo" (REUC) section.
556+
*/
557+
addPath(path: string): void
558+
/**
559+
* Add or update index entries matching files in the working directory.
560+
*
561+
* This method will fail in bare index instances.
562+
*
563+
* The `pathspecs` are a list of file names or shell glob patterns that
564+
* will matched against files in the repository's working directory. Each
565+
* file that matches will be added to the index (either updating an
566+
* existing entry or adding a new entry).
567+
*
568+
* @example
569+
*
570+
* Emulate `git add *`:
571+
*
572+
* ```ts
573+
* import { openRepository } from 'es-git';
574+
*
575+
* const repo = await openRepository('.');
576+
* const index = repo.index();
577+
* index.addAll(['*']);
578+
* index.write();
579+
* ```
580+
*/
581+
addAll(pathspecs: Array<string>, options?: IndexAddAllOptions | undefined | null): void
582+
/**
583+
* Update the contents of an existing index object in memory by reading
584+
* from the hard disk.
585+
*
586+
* If force is true, this performs a "hard" read that discards in-memory
587+
* changes and always reloads the on-disk index data. If there is no
588+
* on-disk version, the index will be cleared.
589+
*
590+
* If force is false, this does a "soft" read that reloads the index data
591+
* from disk only if it has changed since the last time it was loaded.
592+
* Purely in-memory index data will be untouched. Be aware: if there are
593+
* changes on disk, unwritten in-memory changes are discarded.
594+
*/
595+
read(force?: boolean | undefined | null): void
596+
/**
597+
* Write the index as a tree.
598+
*
599+
* This method will scan the index and write a representation of its
600+
* current state back to disk; it recursively creates tree objects for each
601+
* of the subtrees stored in the index, but only returns the OID of the
602+
* root tree. This is the OID that can be used e.g. to create a commit.
603+
*
604+
* The index instance cannot be bare, and needs to be associated to an
605+
* existing repository.
606+
*
607+
* The index must not contain any file in conflict.
608+
*/
609+
writeTree(): string
610+
/**
611+
* Remove an index entry corresponding to a file on disk.
612+
*
613+
* The file path must be relative to the repository's working folder. It
614+
* may exist.
615+
*
616+
* If this file currently is the result of a merge conflict, this file will
617+
* no longer be marked as conflicting. The data about the conflict will be
618+
* moved to the "resolve undo" (REUC) section.
619+
*/
620+
removePath(path: string, options?: IndexRemoveOptions | undefined | null): void
621+
/** Remove all matching index entries. */
622+
removeAll(pathspecs: Array<string>, options?: IndexRemoveAllOptions | undefined | null): void
623+
/**
624+
* Update all index entries to match the working directory
625+
*
626+
* This method will fail in bare index instances.
627+
*
628+
* This scans the existing index entries and synchronizes them with the
629+
* working directory, deleting them if the corresponding working directory
630+
* file no longer exists otherwise updating the information (including
631+
* adding the latest version of file to the ODB if needed).
632+
*/
633+
updateAll(pathspecs: Array<string>, options?: IndexUpdateAllOptions | undefined | null): void
634+
/** Get the count of entries currently in the index */
635+
count(): number
636+
/** Return `true` is there is no entry in the index */
637+
isEmpty(): boolean
638+
/**
639+
* Get the full path to the index file on disk.
640+
*
641+
* Returns `None` if this is an in-memory index.
642+
*/
643+
path(): string | null
644+
/**
645+
* Does this index have conflicts?
646+
*
647+
* Returns `true` if the index contains conflicts, `false` if it does not.
648+
*/
649+
hasConflicts(): boolean
650+
/** Get an iterator over the entries in this index. */
651+
entries(): IndexEntries
652+
}
653+
/** An iterator over the entries in an index */
654+
export declare class IndexEntries {
655+
[Symbol.iterator](): Iterator<IndexEntry, void, void>
656+
}
424657
/**
425658
* A structure representing a [remote][1] of a git repository.
426659
*
@@ -489,6 +722,18 @@ export declare class Repository {
489722
findCommit(oid: string): Commit | null
490723
/** Lookup a reference to one of the commits in a repository. */
491724
getCommit(oid: string): Commit
725+
/**
726+
* Get the Index file for this repository.
727+
*
728+
* If a custom index has not been set, the default index for the repository
729+
* will be returned (the one located in .git/index).
730+
*
731+
* **Caution**: If the [`git2::Repository`] of this index is dropped, then this
732+
* [`git2::Index`] will become detached, and most methods on it will fail. See
733+
* [`git2::Index::open`]. Be sure the repository has a binding such as a local
734+
* variable to keep it alive at least as long as the index.
735+
*/
736+
index(): Index
492737
/**
493738
* Lookup a reference to one of the objects in a repository.
494739
*

index.js

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)