isomorphic-git 1.40.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 +61 -28
- package/index.js +61 -28
- package/index.umd.min.js +1 -1
- package/index.umd.min.js.map +1 -1
- package/managers/index.cjs +59 -26
- package/managers/index.js +59 -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
|
@@ -1644,6 +1644,23 @@ class InvalidOidError extends BaseError {
|
|
|
1644
1644
|
/** @type {'InvalidOidError'} */
|
|
1645
1645
|
InvalidOidError.code = 'InvalidOidError';
|
|
1646
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
|
+
|
|
1647
1664
|
class NoRefspecError extends BaseError {
|
|
1648
1665
|
/**
|
|
1649
1666
|
* @param {string} remote
|
|
@@ -1846,6 +1863,16 @@ const refpaths = ref => [
|
|
|
1846
1863
|
// @see https://git-scm.com/docs/gitrepository-layout
|
|
1847
1864
|
const GIT_FILES = ['config', 'description', 'index', 'shallow', 'commondir'];
|
|
1848
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
|
+
|
|
1849
1876
|
let lock$1;
|
|
1850
1877
|
|
|
1851
1878
|
async function acquireLock(ref, callback) {
|
|
@@ -1900,6 +1927,31 @@ class GitRefManager {
|
|
|
1900
1927
|
}
|
|
1901
1928
|
const refspec = GitRefSpecSet.from(refspecs);
|
|
1902
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
|
+
}
|
|
1903
1955
|
// Delete all current tags if the pruneTags argument is true.
|
|
1904
1956
|
if (pruneTags) {
|
|
1905
1957
|
const tags = await GitRefManager.listRefs({
|
|
@@ -1927,18 +1979,12 @@ class GitRefManager {
|
|
|
1927
1979
|
}
|
|
1928
1980
|
}
|
|
1929
1981
|
// Combine refs and symrefs giving symrefs priority
|
|
1930
|
-
const refTranslations = refspec.translate([...refs.keys()]);
|
|
1931
1982
|
for (const [serverRef, translatedRef] of refTranslations) {
|
|
1932
1983
|
const value = refs.get(serverRef);
|
|
1933
1984
|
actualRefsToWrite.set(translatedRef, value);
|
|
1934
1985
|
}
|
|
1935
|
-
const
|
|
1936
|
-
|
|
1937
|
-
const value = symrefs.get(serverRef);
|
|
1938
|
-
const symtarget = refspec.translateOne(value);
|
|
1939
|
-
if (symtarget) {
|
|
1940
|
-
actualRefsToWrite.set(translatedRef, `ref: ${symtarget}`);
|
|
1941
|
-
}
|
|
1986
|
+
for (const [translatedRef, value] of symrefTranslations) {
|
|
1987
|
+
actualRefsToWrite.set(translatedRef, value);
|
|
1942
1988
|
}
|
|
1943
1989
|
// If `prune` argument is true, clear out the existing local refspec roots
|
|
1944
1990
|
const pruned = [];
|
|
@@ -1997,6 +2043,7 @@ class GitRefManager {
|
|
|
1997
2043
|
// TODO: make this less crude?
|
|
1998
2044
|
static async writeRef({ fs, gitdir, ref, value }) {
|
|
1999
2045
|
// Validate input
|
|
2046
|
+
assertWritableRef(ref);
|
|
2000
2047
|
if (!value.match(/[0-9a-f]{40}/)) {
|
|
2001
2048
|
throw new InvalidOidError(value)
|
|
2002
2049
|
}
|
|
@@ -2016,6 +2063,7 @@ class GitRefManager {
|
|
|
2016
2063
|
* @returns {Promise<void>}
|
|
2017
2064
|
*/
|
|
2018
2065
|
static async writeSymbolicRef({ fs, gitdir, ref, value }) {
|
|
2066
|
+
assertWritableRef(ref);
|
|
2019
2067
|
await acquireLock(ref, async () =>
|
|
2020
2068
|
fs.write(join(gitdir, ref), 'ref: ' + `${value.trim()}\n`, 'utf8')
|
|
2021
2069
|
);
|
|
@@ -2044,6 +2092,8 @@ class GitRefManager {
|
|
|
2044
2092
|
* @returns {Promise<void>}
|
|
2045
2093
|
*/
|
|
2046
2094
|
static async deleteRefs({ fs, gitdir, refs }) {
|
|
2095
|
+
// Validate input
|
|
2096
|
+
refs.forEach(assertWritableRef);
|
|
2047
2097
|
// Delete regular ref
|
|
2048
2098
|
await Promise.all(refs.map(ref => fs.rm(join(gitdir, ref))));
|
|
2049
2099
|
// Delete any packed ref
|
|
@@ -2167,7 +2217,7 @@ class GitRefManager {
|
|
|
2167
2217
|
// We need to alternate between the file system and the packed-refs
|
|
2168
2218
|
const packedMap = await GitRefManager.packedRefs({ fs, gitdir });
|
|
2169
2219
|
// Look in all the proper paths, in this order
|
|
2170
|
-
const allpaths = refpaths(ref);
|
|
2220
|
+
const allpaths = refpaths(ref).filter(p => !GIT_FILES.includes(p)); // exclude git system files (#709)
|
|
2171
2221
|
for (const ref of allpaths) {
|
|
2172
2222
|
const refExists = await acquireLock(ref, async () =>
|
|
2173
2223
|
fs.exists(`${gitdir}/${ref}`)
|
|
@@ -4518,23 +4568,6 @@ async function _writeCommit({ fs, gitdir, commit }) {
|
|
|
4518
4568
|
return oid
|
|
4519
4569
|
}
|
|
4520
4570
|
|
|
4521
|
-
class InvalidRefNameError extends BaseError {
|
|
4522
|
-
/**
|
|
4523
|
-
* @param {string} ref
|
|
4524
|
-
* @param {string} suggestion
|
|
4525
|
-
* @param {boolean} canForce
|
|
4526
|
-
*/
|
|
4527
|
-
constructor(ref, suggestion) {
|
|
4528
|
-
super(
|
|
4529
|
-
`"${ref}" would be an invalid git reference. (Hint: a valid alternative would be "${suggestion}".)`
|
|
4530
|
-
);
|
|
4531
|
-
this.code = this.name = InvalidRefNameError.code;
|
|
4532
|
-
this.data = { ref, suggestion };
|
|
4533
|
-
}
|
|
4534
|
-
}
|
|
4535
|
-
/** @type {'InvalidRefNameError'} */
|
|
4536
|
-
InvalidRefNameError.code = 'InvalidRefNameError';
|
|
4537
|
-
|
|
4538
4571
|
class MissingNameError extends BaseError {
|
|
4539
4572
|
/**
|
|
4540
4573
|
* @param {'author'|'committer'|'tagger'} role
|
package/managers/index.js
CHANGED
|
@@ -1637,6 +1637,23 @@ class InvalidOidError extends BaseError {
|
|
|
1637
1637
|
/** @type {'InvalidOidError'} */
|
|
1638
1638
|
InvalidOidError.code = 'InvalidOidError';
|
|
1639
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
|
+
|
|
1640
1657
|
class NoRefspecError extends BaseError {
|
|
1641
1658
|
/**
|
|
1642
1659
|
* @param {string} remote
|
|
@@ -1839,6 +1856,16 @@ const refpaths = ref => [
|
|
|
1839
1856
|
// @see https://git-scm.com/docs/gitrepository-layout
|
|
1840
1857
|
const GIT_FILES = ['config', 'description', 'index', 'shallow', 'commondir'];
|
|
1841
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
|
+
|
|
1842
1869
|
let lock$1;
|
|
1843
1870
|
|
|
1844
1871
|
async function acquireLock(ref, callback) {
|
|
@@ -1893,6 +1920,31 @@ class GitRefManager {
|
|
|
1893
1920
|
}
|
|
1894
1921
|
const refspec = GitRefSpecSet.from(refspecs);
|
|
1895
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
|
+
}
|
|
1896
1948
|
// Delete all current tags if the pruneTags argument is true.
|
|
1897
1949
|
if (pruneTags) {
|
|
1898
1950
|
const tags = await GitRefManager.listRefs({
|
|
@@ -1920,18 +1972,12 @@ class GitRefManager {
|
|
|
1920
1972
|
}
|
|
1921
1973
|
}
|
|
1922
1974
|
// Combine refs and symrefs giving symrefs priority
|
|
1923
|
-
const refTranslations = refspec.translate([...refs.keys()]);
|
|
1924
1975
|
for (const [serverRef, translatedRef] of refTranslations) {
|
|
1925
1976
|
const value = refs.get(serverRef);
|
|
1926
1977
|
actualRefsToWrite.set(translatedRef, value);
|
|
1927
1978
|
}
|
|
1928
|
-
const
|
|
1929
|
-
|
|
1930
|
-
const value = symrefs.get(serverRef);
|
|
1931
|
-
const symtarget = refspec.translateOne(value);
|
|
1932
|
-
if (symtarget) {
|
|
1933
|
-
actualRefsToWrite.set(translatedRef, `ref: ${symtarget}`);
|
|
1934
|
-
}
|
|
1979
|
+
for (const [translatedRef, value] of symrefTranslations) {
|
|
1980
|
+
actualRefsToWrite.set(translatedRef, value);
|
|
1935
1981
|
}
|
|
1936
1982
|
// If `prune` argument is true, clear out the existing local refspec roots
|
|
1937
1983
|
const pruned = [];
|
|
@@ -1990,6 +2036,7 @@ class GitRefManager {
|
|
|
1990
2036
|
// TODO: make this less crude?
|
|
1991
2037
|
static async writeRef({ fs, gitdir, ref, value }) {
|
|
1992
2038
|
// Validate input
|
|
2039
|
+
assertWritableRef(ref);
|
|
1993
2040
|
if (!value.match(/[0-9a-f]{40}/)) {
|
|
1994
2041
|
throw new InvalidOidError(value)
|
|
1995
2042
|
}
|
|
@@ -2009,6 +2056,7 @@ class GitRefManager {
|
|
|
2009
2056
|
* @returns {Promise<void>}
|
|
2010
2057
|
*/
|
|
2011
2058
|
static async writeSymbolicRef({ fs, gitdir, ref, value }) {
|
|
2059
|
+
assertWritableRef(ref);
|
|
2012
2060
|
await acquireLock(ref, async () =>
|
|
2013
2061
|
fs.write(join(gitdir, ref), 'ref: ' + `${value.trim()}\n`, 'utf8')
|
|
2014
2062
|
);
|
|
@@ -2037,6 +2085,8 @@ class GitRefManager {
|
|
|
2037
2085
|
* @returns {Promise<void>}
|
|
2038
2086
|
*/
|
|
2039
2087
|
static async deleteRefs({ fs, gitdir, refs }) {
|
|
2088
|
+
// Validate input
|
|
2089
|
+
refs.forEach(assertWritableRef);
|
|
2040
2090
|
// Delete regular ref
|
|
2041
2091
|
await Promise.all(refs.map(ref => fs.rm(join(gitdir, ref))));
|
|
2042
2092
|
// Delete any packed ref
|
|
@@ -2160,7 +2210,7 @@ class GitRefManager {
|
|
|
2160
2210
|
// We need to alternate between the file system and the packed-refs
|
|
2161
2211
|
const packedMap = await GitRefManager.packedRefs({ fs, gitdir });
|
|
2162
2212
|
// Look in all the proper paths, in this order
|
|
2163
|
-
const allpaths = refpaths(ref);
|
|
2213
|
+
const allpaths = refpaths(ref).filter(p => !GIT_FILES.includes(p)); // exclude git system files (#709)
|
|
2164
2214
|
for (const ref of allpaths) {
|
|
2165
2215
|
const refExists = await acquireLock(ref, async () =>
|
|
2166
2216
|
fs.exists(`${gitdir}/${ref}`)
|
|
@@ -4505,23 +4555,6 @@ async function _writeCommit({ fs, gitdir, commit }) {
|
|
|
4505
4555
|
return oid
|
|
4506
4556
|
}
|
|
4507
4557
|
|
|
4508
|
-
class InvalidRefNameError extends BaseError {
|
|
4509
|
-
/**
|
|
4510
|
-
* @param {string} ref
|
|
4511
|
-
* @param {string} suggestion
|
|
4512
|
-
* @param {boolean} canForce
|
|
4513
|
-
*/
|
|
4514
|
-
constructor(ref, suggestion) {
|
|
4515
|
-
super(
|
|
4516
|
-
`"${ref}" would be an invalid git reference. (Hint: a valid alternative would be "${suggestion}".)`
|
|
4517
|
-
);
|
|
4518
|
-
this.code = this.name = InvalidRefNameError.code;
|
|
4519
|
-
this.data = { ref, suggestion };
|
|
4520
|
-
}
|
|
4521
|
-
}
|
|
4522
|
-
/** @type {'InvalidRefNameError'} */
|
|
4523
|
-
InvalidRefNameError.code = 'InvalidRefNameError';
|
|
4524
|
-
|
|
4525
4558
|
class MissingNameError extends BaseError {
|
|
4526
4559
|
/**
|
|
4527
4560
|
* @param {'author'|'committer'|'tagger'} role
|