isomorphic-git 1.39.0 → 1.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +115 -29
- package/index.d.cts +8 -1
- package/index.d.ts +8 -1
- package/index.js +115 -29
- package/index.umd.min.d.ts +8 -1
- package/index.umd.min.js +1 -1
- package/index.umd.min.js.map +1 -1
- package/managers/index.cjs +60 -26
- package/managers/index.d.cts +4 -0
- package/managers/index.d.ts +4 -0
- package/managers/index.js +60 -26
- package/managers/index.umd.min.js +1 -1
- package/managers/index.umd.min.js.map +1 -1
- package/package.json +1 -1
package/managers/index.cjs
CHANGED
|
@@ -63,6 +63,7 @@ var crypto$1 = require('crypto');
|
|
|
63
63
|
* @property {string} message Commit message
|
|
64
64
|
* @property {string} tree SHA-1 object id of corresponding file tree
|
|
65
65
|
* @property {string[]} parent an array of zero or more SHA-1 object ids
|
|
66
|
+
* @property {Array.<Array.<string|null>>} [changes] Changed files as `[newOid, oldOid, filepath]`; present when `log` is called with `includeChanges: true`.
|
|
66
67
|
* @property {Object} author
|
|
67
68
|
* @property {string} author.name The author's name
|
|
68
69
|
* @property {string} author.email The author's email
|
|
@@ -1643,6 +1644,23 @@ class InvalidOidError extends BaseError {
|
|
|
1643
1644
|
/** @type {'InvalidOidError'} */
|
|
1644
1645
|
InvalidOidError.code = 'InvalidOidError';
|
|
1645
1646
|
|
|
1647
|
+
class InvalidRefNameError extends BaseError {
|
|
1648
|
+
/**
|
|
1649
|
+
* @param {string} ref
|
|
1650
|
+
* @param {string} suggestion
|
|
1651
|
+
* @param {boolean} canForce
|
|
1652
|
+
*/
|
|
1653
|
+
constructor(ref, suggestion) {
|
|
1654
|
+
super(
|
|
1655
|
+
`"${ref}" would be an invalid git reference. (Hint: a valid alternative would be "${suggestion}".)`
|
|
1656
|
+
);
|
|
1657
|
+
this.code = this.name = InvalidRefNameError.code;
|
|
1658
|
+
this.data = { ref, suggestion };
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
/** @type {'InvalidRefNameError'} */
|
|
1662
|
+
InvalidRefNameError.code = 'InvalidRefNameError';
|
|
1663
|
+
|
|
1646
1664
|
class NoRefspecError extends BaseError {
|
|
1647
1665
|
/**
|
|
1648
1666
|
* @param {string} remote
|
|
@@ -1845,6 +1863,16 @@ const refpaths = ref => [
|
|
|
1845
1863
|
// @see https://git-scm.com/docs/gitrepository-layout
|
|
1846
1864
|
const GIT_FILES = ['config', 'description', 'index', 'shallow', 'commondir'];
|
|
1847
1865
|
|
|
1866
|
+
// These names are legal one-level ref names, so nothing upstream of here
|
|
1867
|
+
// rejects them, and writing to one lands on the repository file itself.
|
|
1868
|
+
// Canonical git refuses too: `git update-ref index <oid>` fails with
|
|
1869
|
+
// "cannot lock ref 'index': reference broken" and leaves the file alone.
|
|
1870
|
+
function assertWritableRef(ref) {
|
|
1871
|
+
if (GIT_FILES.includes(ref)) {
|
|
1872
|
+
throw new InvalidRefNameError(ref, `refs/heads/${ref}`)
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1848
1876
|
let lock$1;
|
|
1849
1877
|
|
|
1850
1878
|
async function acquireLock(ref, callback) {
|
|
@@ -1899,6 +1927,31 @@ class GitRefManager {
|
|
|
1899
1927
|
}
|
|
1900
1928
|
const refspec = GitRefSpecSet.from(refspecs);
|
|
1901
1929
|
const actualRefsToWrite = new Map();
|
|
1930
|
+
// Work out every destination this call will write, before touching the
|
|
1931
|
+
// repository. Translating is pure, so it can happen up here; the writes
|
|
1932
|
+
// themselves stay at the end of the function.
|
|
1933
|
+
const refTranslations = refspec.translate([...refs.keys()]);
|
|
1934
|
+
const symrefTranslations = [];
|
|
1935
|
+
for (const [serverRef, translatedRef] of refspec.translate([
|
|
1936
|
+
...symrefs.keys(),
|
|
1937
|
+
])) {
|
|
1938
|
+
const symtarget = refspec.translateOne(symrefs.get(serverRef));
|
|
1939
|
+
if (symtarget) {
|
|
1940
|
+
symrefTranslations.push([translatedRef, `ref: ${symtarget}`]);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
// The local side of a refspec is whatever `remote.<name>.fetch` says, so a
|
|
1944
|
+
// config like `+refs/heads/main:index` lands a write on `.git/index`.
|
|
1945
|
+
// Refuse it here rather than at the write loop: `pruneTags` and `prune`
|
|
1946
|
+
// delete refs in between, so a later throw leaves the repository pruned
|
|
1947
|
+
// and not updated. The tags added below are always `refs/tags/...`, which
|
|
1948
|
+
// is never a system file, so nothing is missed by checking this early.
|
|
1949
|
+
for (const [, translatedRef] of refTranslations) {
|
|
1950
|
+
assertWritableRef(translatedRef);
|
|
1951
|
+
}
|
|
1952
|
+
for (const [translatedRef] of symrefTranslations) {
|
|
1953
|
+
assertWritableRef(translatedRef);
|
|
1954
|
+
}
|
|
1902
1955
|
// Delete all current tags if the pruneTags argument is true.
|
|
1903
1956
|
if (pruneTags) {
|
|
1904
1957
|
const tags = await GitRefManager.listRefs({
|
|
@@ -1926,18 +1979,12 @@ class GitRefManager {
|
|
|
1926
1979
|
}
|
|
1927
1980
|
}
|
|
1928
1981
|
// Combine refs and symrefs giving symrefs priority
|
|
1929
|
-
const refTranslations = refspec.translate([...refs.keys()]);
|
|
1930
1982
|
for (const [serverRef, translatedRef] of refTranslations) {
|
|
1931
1983
|
const value = refs.get(serverRef);
|
|
1932
1984
|
actualRefsToWrite.set(translatedRef, value);
|
|
1933
1985
|
}
|
|
1934
|
-
const
|
|
1935
|
-
|
|
1936
|
-
const value = symrefs.get(serverRef);
|
|
1937
|
-
const symtarget = refspec.translateOne(value);
|
|
1938
|
-
if (symtarget) {
|
|
1939
|
-
actualRefsToWrite.set(translatedRef, `ref: ${symtarget}`);
|
|
1940
|
-
}
|
|
1986
|
+
for (const [translatedRef, value] of symrefTranslations) {
|
|
1987
|
+
actualRefsToWrite.set(translatedRef, value);
|
|
1941
1988
|
}
|
|
1942
1989
|
// If `prune` argument is true, clear out the existing local refspec roots
|
|
1943
1990
|
const pruned = [];
|
|
@@ -1996,6 +2043,7 @@ class GitRefManager {
|
|
|
1996
2043
|
// TODO: make this less crude?
|
|
1997
2044
|
static async writeRef({ fs, gitdir, ref, value }) {
|
|
1998
2045
|
// Validate input
|
|
2046
|
+
assertWritableRef(ref);
|
|
1999
2047
|
if (!value.match(/[0-9a-f]{40}/)) {
|
|
2000
2048
|
throw new InvalidOidError(value)
|
|
2001
2049
|
}
|
|
@@ -2015,6 +2063,7 @@ class GitRefManager {
|
|
|
2015
2063
|
* @returns {Promise<void>}
|
|
2016
2064
|
*/
|
|
2017
2065
|
static async writeSymbolicRef({ fs, gitdir, ref, value }) {
|
|
2066
|
+
assertWritableRef(ref);
|
|
2018
2067
|
await acquireLock(ref, async () =>
|
|
2019
2068
|
fs.write(join(gitdir, ref), 'ref: ' + `${value.trim()}\n`, 'utf8')
|
|
2020
2069
|
);
|
|
@@ -2043,6 +2092,8 @@ class GitRefManager {
|
|
|
2043
2092
|
* @returns {Promise<void>}
|
|
2044
2093
|
*/
|
|
2045
2094
|
static async deleteRefs({ fs, gitdir, refs }) {
|
|
2095
|
+
// Validate input
|
|
2096
|
+
refs.forEach(assertWritableRef);
|
|
2046
2097
|
// Delete regular ref
|
|
2047
2098
|
await Promise.all(refs.map(ref => fs.rm(join(gitdir, ref))));
|
|
2048
2099
|
// Delete any packed ref
|
|
@@ -2166,7 +2217,7 @@ class GitRefManager {
|
|
|
2166
2217
|
// We need to alternate between the file system and the packed-refs
|
|
2167
2218
|
const packedMap = await GitRefManager.packedRefs({ fs, gitdir });
|
|
2168
2219
|
// Look in all the proper paths, in this order
|
|
2169
|
-
const allpaths = refpaths(ref);
|
|
2220
|
+
const allpaths = refpaths(ref).filter(p => !GIT_FILES.includes(p)); // exclude git system files (#709)
|
|
2170
2221
|
for (const ref of allpaths) {
|
|
2171
2222
|
const refExists = await acquireLock(ref, async () =>
|
|
2172
2223
|
fs.exists(`${gitdir}/${ref}`)
|
|
@@ -4517,23 +4568,6 @@ async function _writeCommit({ fs, gitdir, commit }) {
|
|
|
4517
4568
|
return oid
|
|
4518
4569
|
}
|
|
4519
4570
|
|
|
4520
|
-
class InvalidRefNameError extends BaseError {
|
|
4521
|
-
/**
|
|
4522
|
-
* @param {string} ref
|
|
4523
|
-
* @param {string} suggestion
|
|
4524
|
-
* @param {boolean} canForce
|
|
4525
|
-
*/
|
|
4526
|
-
constructor(ref, suggestion) {
|
|
4527
|
-
super(
|
|
4528
|
-
`"${ref}" would be an invalid git reference. (Hint: a valid alternative would be "${suggestion}".)`
|
|
4529
|
-
);
|
|
4530
|
-
this.code = this.name = InvalidRefNameError.code;
|
|
4531
|
-
this.data = { ref, suggestion };
|
|
4532
|
-
}
|
|
4533
|
-
}
|
|
4534
|
-
/** @type {'InvalidRefNameError'} */
|
|
4535
|
-
InvalidRefNameError.code = 'InvalidRefNameError';
|
|
4536
|
-
|
|
4537
4571
|
class MissingNameError extends BaseError {
|
|
4538
4572
|
/**
|
|
4539
4573
|
* @param {'author'|'committer'|'tagger'} role
|
package/managers/index.d.cts
CHANGED
|
@@ -103,6 +103,10 @@ export type CommitObject = {
|
|
|
103
103
|
* an array of zero or more SHA-1 object ids
|
|
104
104
|
*/
|
|
105
105
|
parent: string[];
|
|
106
|
+
/**
|
|
107
|
+
* Changed files as `[newOid, oldOid, filepath]`; present when `log` is called with `includeChanges: true`.
|
|
108
|
+
*/
|
|
109
|
+
changes?: (string | null)[][] | undefined;
|
|
106
110
|
author: {
|
|
107
111
|
name: string;
|
|
108
112
|
email: string;
|
package/managers/index.d.ts
CHANGED
|
@@ -102,6 +102,10 @@ export type CommitObject = {
|
|
|
102
102
|
* an array of zero or more SHA-1 object ids
|
|
103
103
|
*/
|
|
104
104
|
parent: string[];
|
|
105
|
+
/**
|
|
106
|
+
* Changed files as `[newOid, oldOid, filepath]`; present when `log` is called with `includeChanges: true`.
|
|
107
|
+
*/
|
|
108
|
+
changes?: (string | null)[][] | undefined;
|
|
105
109
|
author: {
|
|
106
110
|
name: string;
|
|
107
111
|
email: string;
|
package/managers/index.js
CHANGED
|
@@ -56,6 +56,7 @@ import pako from 'pako';
|
|
|
56
56
|
* @property {string} message Commit message
|
|
57
57
|
* @property {string} tree SHA-1 object id of corresponding file tree
|
|
58
58
|
* @property {string[]} parent an array of zero or more SHA-1 object ids
|
|
59
|
+
* @property {Array.<Array.<string|null>>} [changes] Changed files as `[newOid, oldOid, filepath]`; present when `log` is called with `includeChanges: true`.
|
|
59
60
|
* @property {Object} author
|
|
60
61
|
* @property {string} author.name The author's name
|
|
61
62
|
* @property {string} author.email The author's email
|
|
@@ -1636,6 +1637,23 @@ class InvalidOidError extends BaseError {
|
|
|
1636
1637
|
/** @type {'InvalidOidError'} */
|
|
1637
1638
|
InvalidOidError.code = 'InvalidOidError';
|
|
1638
1639
|
|
|
1640
|
+
class InvalidRefNameError extends BaseError {
|
|
1641
|
+
/**
|
|
1642
|
+
* @param {string} ref
|
|
1643
|
+
* @param {string} suggestion
|
|
1644
|
+
* @param {boolean} canForce
|
|
1645
|
+
*/
|
|
1646
|
+
constructor(ref, suggestion) {
|
|
1647
|
+
super(
|
|
1648
|
+
`"${ref}" would be an invalid git reference. (Hint: a valid alternative would be "${suggestion}".)`
|
|
1649
|
+
);
|
|
1650
|
+
this.code = this.name = InvalidRefNameError.code;
|
|
1651
|
+
this.data = { ref, suggestion };
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
/** @type {'InvalidRefNameError'} */
|
|
1655
|
+
InvalidRefNameError.code = 'InvalidRefNameError';
|
|
1656
|
+
|
|
1639
1657
|
class NoRefspecError extends BaseError {
|
|
1640
1658
|
/**
|
|
1641
1659
|
* @param {string} remote
|
|
@@ -1838,6 +1856,16 @@ const refpaths = ref => [
|
|
|
1838
1856
|
// @see https://git-scm.com/docs/gitrepository-layout
|
|
1839
1857
|
const GIT_FILES = ['config', 'description', 'index', 'shallow', 'commondir'];
|
|
1840
1858
|
|
|
1859
|
+
// These names are legal one-level ref names, so nothing upstream of here
|
|
1860
|
+
// rejects them, and writing to one lands on the repository file itself.
|
|
1861
|
+
// Canonical git refuses too: `git update-ref index <oid>` fails with
|
|
1862
|
+
// "cannot lock ref 'index': reference broken" and leaves the file alone.
|
|
1863
|
+
function assertWritableRef(ref) {
|
|
1864
|
+
if (GIT_FILES.includes(ref)) {
|
|
1865
|
+
throw new InvalidRefNameError(ref, `refs/heads/${ref}`)
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1841
1869
|
let lock$1;
|
|
1842
1870
|
|
|
1843
1871
|
async function acquireLock(ref, callback) {
|
|
@@ -1892,6 +1920,31 @@ class GitRefManager {
|
|
|
1892
1920
|
}
|
|
1893
1921
|
const refspec = GitRefSpecSet.from(refspecs);
|
|
1894
1922
|
const actualRefsToWrite = new Map();
|
|
1923
|
+
// Work out every destination this call will write, before touching the
|
|
1924
|
+
// repository. Translating is pure, so it can happen up here; the writes
|
|
1925
|
+
// themselves stay at the end of the function.
|
|
1926
|
+
const refTranslations = refspec.translate([...refs.keys()]);
|
|
1927
|
+
const symrefTranslations = [];
|
|
1928
|
+
for (const [serverRef, translatedRef] of refspec.translate([
|
|
1929
|
+
...symrefs.keys(),
|
|
1930
|
+
])) {
|
|
1931
|
+
const symtarget = refspec.translateOne(symrefs.get(serverRef));
|
|
1932
|
+
if (symtarget) {
|
|
1933
|
+
symrefTranslations.push([translatedRef, `ref: ${symtarget}`]);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
// The local side of a refspec is whatever `remote.<name>.fetch` says, so a
|
|
1937
|
+
// config like `+refs/heads/main:index` lands a write on `.git/index`.
|
|
1938
|
+
// Refuse it here rather than at the write loop: `pruneTags` and `prune`
|
|
1939
|
+
// delete refs in between, so a later throw leaves the repository pruned
|
|
1940
|
+
// and not updated. The tags added below are always `refs/tags/...`, which
|
|
1941
|
+
// is never a system file, so nothing is missed by checking this early.
|
|
1942
|
+
for (const [, translatedRef] of refTranslations) {
|
|
1943
|
+
assertWritableRef(translatedRef);
|
|
1944
|
+
}
|
|
1945
|
+
for (const [translatedRef] of symrefTranslations) {
|
|
1946
|
+
assertWritableRef(translatedRef);
|
|
1947
|
+
}
|
|
1895
1948
|
// Delete all current tags if the pruneTags argument is true.
|
|
1896
1949
|
if (pruneTags) {
|
|
1897
1950
|
const tags = await GitRefManager.listRefs({
|
|
@@ -1919,18 +1972,12 @@ class GitRefManager {
|
|
|
1919
1972
|
}
|
|
1920
1973
|
}
|
|
1921
1974
|
// Combine refs and symrefs giving symrefs priority
|
|
1922
|
-
const refTranslations = refspec.translate([...refs.keys()]);
|
|
1923
1975
|
for (const [serverRef, translatedRef] of refTranslations) {
|
|
1924
1976
|
const value = refs.get(serverRef);
|
|
1925
1977
|
actualRefsToWrite.set(translatedRef, value);
|
|
1926
1978
|
}
|
|
1927
|
-
const
|
|
1928
|
-
|
|
1929
|
-
const value = symrefs.get(serverRef);
|
|
1930
|
-
const symtarget = refspec.translateOne(value);
|
|
1931
|
-
if (symtarget) {
|
|
1932
|
-
actualRefsToWrite.set(translatedRef, `ref: ${symtarget}`);
|
|
1933
|
-
}
|
|
1979
|
+
for (const [translatedRef, value] of symrefTranslations) {
|
|
1980
|
+
actualRefsToWrite.set(translatedRef, value);
|
|
1934
1981
|
}
|
|
1935
1982
|
// If `prune` argument is true, clear out the existing local refspec roots
|
|
1936
1983
|
const pruned = [];
|
|
@@ -1989,6 +2036,7 @@ class GitRefManager {
|
|
|
1989
2036
|
// TODO: make this less crude?
|
|
1990
2037
|
static async writeRef({ fs, gitdir, ref, value }) {
|
|
1991
2038
|
// Validate input
|
|
2039
|
+
assertWritableRef(ref);
|
|
1992
2040
|
if (!value.match(/[0-9a-f]{40}/)) {
|
|
1993
2041
|
throw new InvalidOidError(value)
|
|
1994
2042
|
}
|
|
@@ -2008,6 +2056,7 @@ class GitRefManager {
|
|
|
2008
2056
|
* @returns {Promise<void>}
|
|
2009
2057
|
*/
|
|
2010
2058
|
static async writeSymbolicRef({ fs, gitdir, ref, value }) {
|
|
2059
|
+
assertWritableRef(ref);
|
|
2011
2060
|
await acquireLock(ref, async () =>
|
|
2012
2061
|
fs.write(join(gitdir, ref), 'ref: ' + `${value.trim()}\n`, 'utf8')
|
|
2013
2062
|
);
|
|
@@ -2036,6 +2085,8 @@ class GitRefManager {
|
|
|
2036
2085
|
* @returns {Promise<void>}
|
|
2037
2086
|
*/
|
|
2038
2087
|
static async deleteRefs({ fs, gitdir, refs }) {
|
|
2088
|
+
// Validate input
|
|
2089
|
+
refs.forEach(assertWritableRef);
|
|
2039
2090
|
// Delete regular ref
|
|
2040
2091
|
await Promise.all(refs.map(ref => fs.rm(join(gitdir, ref))));
|
|
2041
2092
|
// Delete any packed ref
|
|
@@ -2159,7 +2210,7 @@ class GitRefManager {
|
|
|
2159
2210
|
// We need to alternate between the file system and the packed-refs
|
|
2160
2211
|
const packedMap = await GitRefManager.packedRefs({ fs, gitdir });
|
|
2161
2212
|
// Look in all the proper paths, in this order
|
|
2162
|
-
const allpaths = refpaths(ref);
|
|
2213
|
+
const allpaths = refpaths(ref).filter(p => !GIT_FILES.includes(p)); // exclude git system files (#709)
|
|
2163
2214
|
for (const ref of allpaths) {
|
|
2164
2215
|
const refExists = await acquireLock(ref, async () =>
|
|
2165
2216
|
fs.exists(`${gitdir}/${ref}`)
|
|
@@ -4504,23 +4555,6 @@ async function _writeCommit({ fs, gitdir, commit }) {
|
|
|
4504
4555
|
return oid
|
|
4505
4556
|
}
|
|
4506
4557
|
|
|
4507
|
-
class InvalidRefNameError extends BaseError {
|
|
4508
|
-
/**
|
|
4509
|
-
* @param {string} ref
|
|
4510
|
-
* @param {string} suggestion
|
|
4511
|
-
* @param {boolean} canForce
|
|
4512
|
-
*/
|
|
4513
|
-
constructor(ref, suggestion) {
|
|
4514
|
-
super(
|
|
4515
|
-
`"${ref}" would be an invalid git reference. (Hint: a valid alternative would be "${suggestion}".)`
|
|
4516
|
-
);
|
|
4517
|
-
this.code = this.name = InvalidRefNameError.code;
|
|
4518
|
-
this.data = { ref, suggestion };
|
|
4519
|
-
}
|
|
4520
|
-
}
|
|
4521
|
-
/** @type {'InvalidRefNameError'} */
|
|
4522
|
-
InvalidRefNameError.code = 'InvalidRefNameError';
|
|
4523
|
-
|
|
4524
4558
|
class MissingNameError extends BaseError {
|
|
4525
4559
|
/**
|
|
4526
4560
|
* @param {'author'|'committer'|'tagger'} role
|