isomorphic-git 1.25.6 → 1.25.8

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/README.md CHANGED
@@ -368,6 +368,8 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
368
368
  <td align="center"><a href="https://api.github.com/users/hisco"><img src="https://avatars.githubusercontent.com/u/39222286?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Eyal Hisco</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/issues?q=author%3Ahisco" title="Bug reports">🐛</a></td>
369
369
  <td align="center"><a href="https://github.com/scolladon"><img src="https://avatars.githubusercontent.com/u/522422?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Sebastien</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=scolladon" title="Code">💻</a></td>
370
370
  <td align="center"><a href="https://github.com/yarikoptic"><img src="https://avatars.githubusercontent.com/u/39889?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Yaroslav Halchenko</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=yarikoptic" title="Documentation">📖</a></td>
371
+ <td align="center"><a href="https://alex-v.blog/"><img src="https://avatars.githubusercontent.com/u/716334?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Alex Villarreal</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=alexvy86" title="Code">💻</a></td>
372
+ <td align="center"><a href="https://github.com/amrc-benmorrow"><img src="https://avatars.githubusercontent.com/u/120477944?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Ben Morrow</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=amrc-benmorrow" title="Code">💻</a></td>
371
373
  </tr>
372
374
  </table>
373
375
 
@@ -1,8 +1,8 @@
1
1
  [
2
2
  "Chrome Headless 79.0.3945.0 (Linux x86_64)",
3
- "Firefox 122.0 (Ubuntu 0.0.0)",
4
- "Chrome 120.0.0.0 (Android 10)",
5
- "Mobile Safari 13.0 (iOS 13.0)",
3
+ "Firefox 125.0 (Ubuntu 0.0.0)",
4
+ "Chrome 123.0.0.0 (Android 10)",
6
5
  "Edge 79.0.309.65 (Windows 10)",
6
+ "Mobile Safari 13.0 (iOS 13.0)",
7
7
  "Safari 13.1 (Mac OS 10.15.4)"
8
8
  ]
package/index.cjs CHANGED
@@ -907,18 +907,18 @@ class GitIndex {
907
907
  }
908
908
  }
909
909
 
910
- function compareStats(entry, stats) {
910
+ function compareStats(entry, stats, filemode = true, trustino = true) {
911
911
  // Comparison based on the description in Paragraph 4 of
912
912
  // https://www.kernel.org/pub/software/scm/git/docs/technical/racy-git.txt
913
913
  const e = normalizeStats(entry);
914
914
  const s = normalizeStats(stats);
915
915
  const staleness =
916
- e.mode !== s.mode ||
916
+ (filemode && e.mode !== s.mode) ||
917
917
  e.mtimeSeconds !== s.mtimeSeconds ||
918
918
  e.ctimeSeconds !== s.ctimeSeconds ||
919
919
  e.uid !== s.uid ||
920
920
  e.gid !== s.gid ||
921
- e.ino !== s.ino ||
921
+ (trustino && e.ino !== s.ino) ||
922
922
  e.size !== s.size;
923
923
  return staleness
924
924
  }
@@ -1623,26 +1623,28 @@ class GitConfig {
1623
1623
  constructor(text) {
1624
1624
  let section = null;
1625
1625
  let subsection = null;
1626
- this.parsedConfig = text.split('\n').map(line => {
1627
- let name = null;
1628
- let value = null;
1629
-
1630
- const trimmedLine = line.trim();
1631
- const extractedSection = extractSectionLine(trimmedLine);
1632
- const isSection = extractedSection != null;
1633
- if (isSection) {
1634
- ;[section, subsection] = extractedSection;
1635
- } else {
1636
- const extractedVariable = extractVariableLine(trimmedLine);
1637
- const isVariable = extractedVariable != null;
1638
- if (isVariable) {
1639
- ;[name, value] = extractedVariable;
1640
- }
1641
- }
1626
+ this.parsedConfig = text
1627
+ ? text.split('\n').map(line => {
1628
+ let name = null;
1629
+ let value = null;
1630
+
1631
+ const trimmedLine = line.trim();
1632
+ const extractedSection = extractSectionLine(trimmedLine);
1633
+ const isSection = extractedSection != null;
1634
+ if (isSection) {
1635
+ ;[section, subsection] = extractedSection;
1636
+ } else {
1637
+ const extractedVariable = extractVariableLine(trimmedLine);
1638
+ const isVariable = extractedVariable != null;
1639
+ if (isVariable) {
1640
+ ;[name, value] = extractedVariable;
1641
+ }
1642
+ }
1642
1643
 
1643
- const path = getPath(section, subsection, name);
1644
- return { line, isSection, section, subsection, name, value, path }
1645
- });
1644
+ const path = getPath(section, subsection, name);
1645
+ return { line, isSection, section, subsection, name, value, path }
1646
+ })
1647
+ : [];
1646
1648
  }
1647
1649
 
1648
1650
  static from(text) {
@@ -1796,6 +1798,13 @@ const refpaths = ref => [
1796
1798
  // @see https://git-scm.com/docs/gitrepository-layout
1797
1799
  const GIT_FILES = ['config', 'description', 'index', 'shallow', 'commondir'];
1798
1800
 
1801
+ let lock$1;
1802
+
1803
+ async function acquireLock(ref, callback) {
1804
+ if (lock$1 === undefined) lock$1 = new AsyncLock();
1805
+ return lock$1.acquire(ref, callback)
1806
+ }
1807
+
1799
1808
  class GitRefManager {
1800
1809
  static async updateRemoteRefs({
1801
1810
  fs,
@@ -1902,7 +1911,9 @@ class GitRefManager {
1902
1911
  // are .git/refs/remotes/origin/refs/remotes/remote_mirror_3059
1903
1912
  // and .git/refs/remotes/origin/refs/merge-requests
1904
1913
  for (const [key, value] of actualRefsToWrite) {
1905
- await fs.write(join(gitdir, key), `${value.trim()}\n`, 'utf8');
1914
+ await acquireLock(key, async () =>
1915
+ fs.write(join(gitdir, key), `${value.trim()}\n`, 'utf8')
1916
+ );
1906
1917
  }
1907
1918
  return { pruned }
1908
1919
  }
@@ -1913,11 +1924,15 @@ class GitRefManager {
1913
1924
  if (!value.match(/[0-9a-f]{40}/)) {
1914
1925
  throw new InvalidOidError(value)
1915
1926
  }
1916
- await fs.write(join(gitdir, ref), `${value.trim()}\n`, 'utf8');
1927
+ await acquireLock(ref, async () =>
1928
+ fs.write(join(gitdir, ref), `${value.trim()}\n`, 'utf8')
1929
+ );
1917
1930
  }
1918
1931
 
1919
1932
  static async writeSymbolicRef({ fs, gitdir, ref, value }) {
1920
- await fs.write(join(gitdir, ref), 'ref: ' + `${value.trim()}\n`, 'utf8');
1933
+ await acquireLock(ref, async () =>
1934
+ fs.write(join(gitdir, ref), 'ref: ' + `${value.trim()}\n`, 'utf8')
1935
+ );
1921
1936
  }
1922
1937
 
1923
1938
  static async deleteRef({ fs, gitdir, ref }) {
@@ -1928,7 +1943,9 @@ class GitRefManager {
1928
1943
  // Delete regular ref
1929
1944
  await Promise.all(refs.map(ref => fs.rm(join(gitdir, ref))));
1930
1945
  // Delete any packed ref
1931
- let text = await fs.read(`${gitdir}/packed-refs`, { encoding: 'utf8' });
1946
+ let text = await acquireLock('packed-refs', async () =>
1947
+ fs.read(`${gitdir}/packed-refs`, { encoding: 'utf8' })
1948
+ );
1932
1949
  const packed = GitPackedRefs.from(text);
1933
1950
  const beforeSize = packed.refs.size;
1934
1951
  for (const ref of refs) {
@@ -1938,7 +1955,9 @@ class GitRefManager {
1938
1955
  }
1939
1956
  if (packed.refs.size < beforeSize) {
1940
1957
  text = packed.toString();
1941
- await fs.write(`${gitdir}/packed-refs`, text, { encoding: 'utf8' });
1958
+ await acquireLock('packed-refs', async () =>
1959
+ fs.write(`${gitdir}/packed-refs`, text, { encoding: 'utf8' })
1960
+ );
1942
1961
  }
1943
1962
  }
1944
1963
 
@@ -1957,7 +1976,7 @@ class GitRefManager {
1957
1976
  return ref
1958
1977
  }
1959
1978
  }
1960
- let sha;
1979
+
1961
1980
  // Is it a ref pointer?
1962
1981
  if (ref.startsWith('ref: ')) {
1963
1982
  ref = ref.slice('ref: '.length);
@@ -1973,9 +1992,12 @@ class GitRefManager {
1973
1992
  const allpaths = refpaths(ref).filter(p => !GIT_FILES.includes(p)); // exclude git system files (#709)
1974
1993
 
1975
1994
  for (const ref of allpaths) {
1976
- sha =
1977
- (await fs.read(`${gitdir}/${ref}`, { encoding: 'utf8' })) ||
1978
- packedMap.get(ref);
1995
+ const sha = await acquireLock(
1996
+ ref,
1997
+ async () =>
1998
+ (await fs.read(`${gitdir}/${ref}`, { encoding: 'utf8' })) ||
1999
+ packedMap.get(ref)
2000
+ );
1979
2001
  if (sha) {
1980
2002
  return GitRefManager.resolve({ fs, gitdir, ref: sha.trim(), depth })
1981
2003
  }
@@ -2003,7 +2025,10 @@ class GitRefManager {
2003
2025
  // Look in all the proper paths, in this order
2004
2026
  const allpaths = refpaths(ref);
2005
2027
  for (const ref of allpaths) {
2006
- if (await fs.exists(`${gitdir}/${ref}`)) return ref
2028
+ const refExists = await acquireLock(ref, async () =>
2029
+ fs.exists(`${gitdir}/${ref}`)
2030
+ );
2031
+ if (refExists) return ref
2007
2032
  if (packedMap.has(ref)) return ref
2008
2033
  }
2009
2034
  // Do we give up?
@@ -2054,7 +2079,9 @@ class GitRefManager {
2054
2079
  }
2055
2080
 
2056
2081
  static async packedRefs({ fs, gitdir }) {
2057
- const text = await fs.read(`${gitdir}/packed-refs`, { encoding: 'utf8' });
2082
+ const text = await acquireLock('packed-refs', async () =>
2083
+ fs.read(`${gitdir}/packed-refs`, { encoding: 'utf8' })
2084
+ );
2058
2085
  const packed = GitPackedRefs.from(text);
2059
2086
  return packed.refs
2060
2087
  }
@@ -4150,17 +4177,22 @@ class GitWalkerFs {
4150
4177
 
4151
4178
  async content(entry) {
4152
4179
  if (entry._content === false) {
4153
- const { fs, dir } = this;
4180
+ const { fs, dir, gitdir } = this;
4154
4181
  if ((await entry.type()) === 'tree') {
4155
4182
  entry._content = undefined;
4156
4183
  } else {
4157
- const content = await fs.read(`${dir}/${entry._fullpath}`);
4184
+ const config = await GitConfigManager.get({ fs, gitdir });
4185
+ const autocrlf = (await config.get('core.autocrlf')) || false;
4186
+ const content = await fs.read(`${dir}/${entry._fullpath}`, {
4187
+ encoding: 'utf8',
4188
+ autocrlf,
4189
+ });
4158
4190
  // workaround for a BrowserFS edge case
4159
4191
  entry._actualSize = content.length;
4160
4192
  if (entry._stat && entry._stat.size === -1) {
4161
4193
  entry._stat.size = entry._actualSize;
4162
4194
  }
4163
- entry._content = new Uint8Array(content);
4195
+ entry._content = new TextEncoder().encode(content);
4164
4196
  }
4165
4197
  }
4166
4198
  return entry._content
@@ -4176,7 +4208,10 @@ class GitWalkerFs {
4176
4208
  ) {
4177
4209
  const stage = index.entriesMap.get(entry._fullpath);
4178
4210
  const stats = await entry.stat();
4179
- if (!stage || compareStats(stats, stage)) {
4211
+ const config = await GitConfigManager.get({ fs, gitdir });
4212
+ const filemode = await config.get('core.filemode');
4213
+ const trustino = !(process.platform === 'win32');
4214
+ if (!stage || compareStats(stats, stage, filemode, trustino)) {
4180
4215
  const content = await entry.content();
4181
4216
  if (content === undefined) {
4182
4217
  oid = undefined;
@@ -4190,8 +4225,8 @@ class GitWalkerFs {
4190
4225
  if (
4191
4226
  stage &&
4192
4227
  oid === stage.oid &&
4193
- stats.mode === stage.mode &&
4194
- compareStats(stats, stage)
4228
+ (!filemode || stats.mode === stage.mode) &&
4229
+ compareStats(stats, stage, filemode, trustino)
4195
4230
  ) {
4196
4231
  index.insert({
4197
4232
  filepath: entry._fullpath,
@@ -4528,6 +4563,9 @@ class FileSystem {
4528
4563
  async read(filepath, options = {}) {
4529
4564
  try {
4530
4565
  let buffer = await this._readFile(filepath, options);
4566
+ if (typeof buffer === 'string' && options.autocrlf) {
4567
+ buffer = buffer.replace(/\r\n/g, '\n');
4568
+ }
4531
4569
  // Convert plain ArrayBuffers to Buffers
4532
4570
  if (typeof buffer !== 'string') {
4533
4571
  buffer = Buffer.from(buffer);
@@ -5058,11 +5096,21 @@ async function addToIndex({
5058
5096
  }
5059
5097
  }
5060
5098
  } else {
5099
+ const config = await GitConfigManager.get({ fs, gitdir });
5100
+ const autocrlf = (await config.get('core.autocrlf')) || false;
5061
5101
  const object = stats.isSymbolicLink()
5062
5102
  ? await fs.readlink(join(dir, currentFilepath)).then(posixifyPathBuffer)
5063
- : await fs.read(join(dir, currentFilepath));
5103
+ : await fs.read(join(dir, currentFilepath), {
5104
+ encoding: 'utf8',
5105
+ autocrlf,
5106
+ });
5064
5107
  if (object === null) throw new NotFoundError(currentFilepath)
5065
- const oid = await _writeObject({ fs, gitdir, type: 'blob', object });
5108
+ const oid = await _writeObject({
5109
+ fs,
5110
+ gitdir,
5111
+ type: 'blob',
5112
+ object: new TextEncoder().encode(object),
5113
+ });
5066
5114
  index.insert({ filepath: currentFilepath, stats, oid });
5067
5115
  }
5068
5116
  });
@@ -6929,14 +6977,17 @@ async function parseRefsAdResponse(stream, { service }) {
6929
6977
 
6930
6978
  const [firstRef, capabilitiesLine] = splitAndAssert(lineTwo, '\x00', '\\x00');
6931
6979
  capabilitiesLine.split(' ').map(x => capabilities.add(x));
6932
- const [ref, name] = splitAndAssert(firstRef, ' ', ' ');
6933
- refs.set(name, ref);
6934
- while (true) {
6935
- const line = await read();
6936
- if (line === true) break
6937
- if (line !== null) {
6938
- const [ref, name] = splitAndAssert(line.toString('utf8'), ' ', ' ');
6939
- refs.set(name, ref);
6980
+ // see no-refs in https://git-scm.com/docs/pack-protocol#_reference_discovery (since git 2.41.0)
6981
+ if (firstRef !== '0000000000000000000000000000000000000000 capabilities^{}') {
6982
+ const [ref, name] = splitAndAssert(firstRef, ' ', ' ');
6983
+ refs.set(name, ref);
6984
+ while (true) {
6985
+ const line = await read();
6986
+ if (line === true) break
6987
+ if (line !== null) {
6988
+ const [ref, name] = splitAndAssert(line.toString('utf8'), ' ', ' ');
6989
+ refs.set(name, ref);
6990
+ }
6940
6991
  }
6941
6992
  }
6942
6993
  // Symrefs are thrown into the "capabilities" unfortunately.
@@ -7216,14 +7267,14 @@ class GitRemoteManager {
7216
7267
  }
7217
7268
  }
7218
7269
 
7219
- let lock$1 = null;
7270
+ let lock$2 = null;
7220
7271
 
7221
7272
  class GitShallowManager {
7222
7273
  static async read({ fs, gitdir }) {
7223
- if (lock$1 === null) lock$1 = new AsyncLock();
7274
+ if (lock$2 === null) lock$2 = new AsyncLock();
7224
7275
  const filepath = join(gitdir, 'shallow');
7225
7276
  const oids = new Set();
7226
- await lock$1.acquire(filepath, async function() {
7277
+ await lock$2.acquire(filepath, async function() {
7227
7278
  const text = await fs.read(filepath, { encoding: 'utf8' });
7228
7279
  if (text === null) return oids // no file
7229
7280
  if (text.trim() === '') return oids // empty file
@@ -7236,18 +7287,18 @@ class GitShallowManager {
7236
7287
  }
7237
7288
 
7238
7289
  static async write({ fs, gitdir, oids }) {
7239
- if (lock$1 === null) lock$1 = new AsyncLock();
7290
+ if (lock$2 === null) lock$2 = new AsyncLock();
7240
7291
  const filepath = join(gitdir, 'shallow');
7241
7292
  if (oids.size > 0) {
7242
7293
  const text = [...oids].join('\n') + '\n';
7243
- await lock$1.acquire(filepath, async function() {
7294
+ await lock$2.acquire(filepath, async function() {
7244
7295
  await fs.write(filepath, text, {
7245
7296
  encoding: 'utf8',
7246
7297
  });
7247
7298
  });
7248
7299
  } else {
7249
7300
  // No shallows
7250
- await lock$1.acquire(filepath, async function() {
7301
+ await lock$2.acquire(filepath, async function() {
7251
7302
  await fs.rm(filepath);
7252
7303
  });
7253
7304
  }
@@ -7334,8 +7385,8 @@ function filterCapabilities(server, client) {
7334
7385
 
7335
7386
  const pkg = {
7336
7387
  name: 'isomorphic-git',
7337
- version: '1.25.6',
7338
- agent: 'git/isomorphic-git@1.25.6',
7388
+ version: '1.25.8',
7389
+ agent: 'git/isomorphic-git@1.25.8',
7339
7390
  };
7340
7391
 
7341
7392
  class FIFO {
@@ -13887,6 +13938,8 @@ async function getHeadTree({ fs, cache, gitdir }) {
13887
13938
  * ["g.txt", 1, 2, 3], // modified, staged, with unstaged changes
13888
13939
  * ["h.txt", 1, 0, 1], // deleted, unstaged
13889
13940
  * ["i.txt", 1, 0, 0], // deleted, staged
13941
+ * ["j.txt", 1, 2, 0], // deleted, staged, with unstaged-modified changes (new file of the same name)
13942
+ * ["k.txt", 1, 1, 0], // deleted, staged, with unstaged changes (new file of the same name)
13890
13943
  * ]
13891
13944
  * ```
13892
13945
  *
package/index.d.ts CHANGED
@@ -3094,6 +3094,8 @@ export function status({ fs: _fs, dir, gitdir, filepath, cache, }: {
3094
3094
  * ["g.txt", 1, 2, 3], // modified, staged, with unstaged changes
3095
3095
  * ["h.txt", 1, 0, 1], // deleted, unstaged
3096
3096
  * ["i.txt", 1, 0, 0], // deleted, staged
3097
+ * ["j.txt", 1, 2, 0], // deleted, staged, with unstaged-modified changes (new file of the same name)
3098
+ * ["k.txt", 1, 1, 0], // deleted, staged, with unstaged changes (new file of the same name)
3097
3099
  * ]
3098
3100
  * ```
3099
3101
  *