Skip to content

Commit 262f6ff

Browse files
jayreeisomorphic-git-bot
authored andcommitted
fix: fix statusMatrix with win32 linebreaks (#1907)
* fix: local test-abortMerge * chore: website updates * fix: fix statusMatrix with win32 linebreaks * chore: replace buffer
1 parent f1d4874 commit 262f6ff

File tree

5 files changed

+110
-64
lines changed

5 files changed

+110
-64
lines changed

js/isomorphic-git/index.cjs

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -907,18 +907,18 @@ class GitIndex {
907907
}
908908
}
909909

910-
function compareStats(entry, stats) {
910+
function compareStats(entry, stats, filemode = true, trustino = true) {
911911
// Comparison based on the description in Paragraph 4 of
912912
// https://www.kernel.org/pub/software/scm/git/docs/technical/racy-git.txt
913913
const e = normalizeStats(entry);
914914
const s = normalizeStats(stats);
915915
const staleness =
916-
e.mode !== s.mode ||
916+
(filemode && e.mode !== s.mode) ||
917917
e.mtimeSeconds !== s.mtimeSeconds ||
918918
e.ctimeSeconds !== s.ctimeSeconds ||
919919
e.uid !== s.uid ||
920920
e.gid !== s.gid ||
921-
e.ino !== s.ino ||
921+
(trustino && e.ino !== s.ino) ||
922922
e.size !== s.size;
923923
return staleness
924924
}
@@ -1623,26 +1623,28 @@ class GitConfig {
16231623
constructor(text) {
16241624
let section = null;
16251625
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+
}
16421643

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+
: [];
16461648
}
16471649

16481650
static from(text) {
@@ -4175,17 +4177,22 @@ class GitWalkerFs {
41754177

41764178
async content(entry) {
41774179
if (entry._content === false) {
4178-
const { fs, dir } = this;
4180+
const { fs, dir, gitdir } = this;
41794181
if ((await entry.type()) === 'tree') {
41804182
entry._content = undefined;
41814183
} else {
4182-
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+
});
41834190
// workaround for a BrowserFS edge case
41844191
entry._actualSize = content.length;
41854192
if (entry._stat && entry._stat.size === -1) {
41864193
entry._stat.size = entry._actualSize;
41874194
}
4188-
entry._content = new Uint8Array(content);
4195+
entry._content = new TextEncoder().encode(content);
41894196
}
41904197
}
41914198
return entry._content
@@ -4201,7 +4208,10 @@ class GitWalkerFs {
42014208
) {
42024209
const stage = index.entriesMap.get(entry._fullpath);
42034210
const stats = await entry.stat();
4204-
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)) {
42054215
const content = await entry.content();
42064216
if (content === undefined) {
42074217
oid = undefined;
@@ -4215,8 +4225,8 @@ class GitWalkerFs {
42154225
if (
42164226
stage &&
42174227
oid === stage.oid &&
4218-
stats.mode === stage.mode &&
4219-
compareStats(stats, stage)
4228+
(!filemode || stats.mode === stage.mode) &&
4229+
compareStats(stats, stage, filemode, trustino)
42204230
) {
42214231
index.insert({
42224232
filepath: entry._fullpath,
@@ -4553,6 +4563,9 @@ class FileSystem {
45534563
async read(filepath, options = {}) {
45544564
try {
45554565
let buffer = await this._readFile(filepath, options);
4566+
if (typeof buffer === 'string' && options.autocrlf) {
4567+
buffer = buffer.replace(/\r\n/g, '\n');
4568+
}
45564569
// Convert plain ArrayBuffers to Buffers
45574570
if (typeof buffer !== 'string') {
45584571
buffer = Buffer.from(buffer);
@@ -5083,11 +5096,21 @@ async function addToIndex({
50835096
}
50845097
}
50855098
} else {
5099+
const config = await GitConfigManager.get({ fs, gitdir });
5100+
const autocrlf = (await config.get('core.autocrlf')) || false;
50865101
const object = stats.isSymbolicLink()
50875102
? await fs.readlink(join(dir, currentFilepath)).then(posixifyPathBuffer)
5088-
: await fs.read(join(dir, currentFilepath));
5103+
: await fs.read(join(dir, currentFilepath), {
5104+
encoding: 'utf8',
5105+
autocrlf,
5106+
});
50895107
if (object === null) throw new NotFoundError(currentFilepath)
5090-
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+
});
50915114
index.insert({ filepath: currentFilepath, stats, oid });
50925115
}
50935116
});

js/isomorphic-git/index.js

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -901,18 +901,18 @@ class GitIndex {
901901
}
902902
}
903903

904-
function compareStats(entry, stats) {
904+
function compareStats(entry, stats, filemode = true, trustino = true) {
905905
// Comparison based on the description in Paragraph 4 of
906906
// https://www.kernel.org/pub/software/scm/git/docs/technical/racy-git.txt
907907
const e = normalizeStats(entry);
908908
const s = normalizeStats(stats);
909909
const staleness =
910-
e.mode !== s.mode ||
910+
(filemode && e.mode !== s.mode) ||
911911
e.mtimeSeconds !== s.mtimeSeconds ||
912912
e.ctimeSeconds !== s.ctimeSeconds ||
913913
e.uid !== s.uid ||
914914
e.gid !== s.gid ||
915-
e.ino !== s.ino ||
915+
(trustino && e.ino !== s.ino) ||
916916
e.size !== s.size;
917917
return staleness
918918
}
@@ -1617,26 +1617,28 @@ class GitConfig {
16171617
constructor(text) {
16181618
let section = null;
16191619
let subsection = null;
1620-
this.parsedConfig = text.split('\n').map(line => {
1621-
let name = null;
1622-
let value = null;
1623-
1624-
const trimmedLine = line.trim();
1625-
const extractedSection = extractSectionLine(trimmedLine);
1626-
const isSection = extractedSection != null;
1627-
if (isSection) {
1628-
;[section, subsection] = extractedSection;
1629-
} else {
1630-
const extractedVariable = extractVariableLine(trimmedLine);
1631-
const isVariable = extractedVariable != null;
1632-
if (isVariable) {
1633-
;[name, value] = extractedVariable;
1634-
}
1635-
}
1620+
this.parsedConfig = text
1621+
? text.split('\n').map(line => {
1622+
let name = null;
1623+
let value = null;
1624+
1625+
const trimmedLine = line.trim();
1626+
const extractedSection = extractSectionLine(trimmedLine);
1627+
const isSection = extractedSection != null;
1628+
if (isSection) {
1629+
;[section, subsection] = extractedSection;
1630+
} else {
1631+
const extractedVariable = extractVariableLine(trimmedLine);
1632+
const isVariable = extractedVariable != null;
1633+
if (isVariable) {
1634+
;[name, value] = extractedVariable;
1635+
}
1636+
}
16361637

1637-
const path = getPath(section, subsection, name);
1638-
return { line, isSection, section, subsection, name, value, path }
1639-
});
1638+
const path = getPath(section, subsection, name);
1639+
return { line, isSection, section, subsection, name, value, path }
1640+
})
1641+
: [];
16401642
}
16411643

16421644
static from(text) {
@@ -4169,17 +4171,22 @@ class GitWalkerFs {
41694171

41704172
async content(entry) {
41714173
if (entry._content === false) {
4172-
const { fs, dir } = this;
4174+
const { fs, dir, gitdir } = this;
41734175
if ((await entry.type()) === 'tree') {
41744176
entry._content = undefined;
41754177
} else {
4176-
const content = await fs.read(`${dir}/${entry._fullpath}`);
4178+
const config = await GitConfigManager.get({ fs, gitdir });
4179+
const autocrlf = (await config.get('core.autocrlf')) || false;
4180+
const content = await fs.read(`${dir}/${entry._fullpath}`, {
4181+
encoding: 'utf8',
4182+
autocrlf,
4183+
});
41774184
// workaround for a BrowserFS edge case
41784185
entry._actualSize = content.length;
41794186
if (entry._stat && entry._stat.size === -1) {
41804187
entry._stat.size = entry._actualSize;
41814188
}
4182-
entry._content = new Uint8Array(content);
4189+
entry._content = new TextEncoder().encode(content);
41834190
}
41844191
}
41854192
return entry._content
@@ -4195,7 +4202,10 @@ class GitWalkerFs {
41954202
) {
41964203
const stage = index.entriesMap.get(entry._fullpath);
41974204
const stats = await entry.stat();
4198-
if (!stage || compareStats(stats, stage)) {
4205+
const config = await GitConfigManager.get({ fs, gitdir });
4206+
const filemode = await config.get('core.filemode');
4207+
const trustino = !(process.platform === 'win32');
4208+
if (!stage || compareStats(stats, stage, filemode, trustino)) {
41994209
const content = await entry.content();
42004210
if (content === undefined) {
42014211
oid = undefined;
@@ -4209,8 +4219,8 @@ class GitWalkerFs {
42094219
if (
42104220
stage &&
42114221
oid === stage.oid &&
4212-
stats.mode === stage.mode &&
4213-
compareStats(stats, stage)
4222+
(!filemode || stats.mode === stage.mode) &&
4223+
compareStats(stats, stage, filemode, trustino)
42144224
) {
42154225
index.insert({
42164226
filepath: entry._fullpath,
@@ -4547,6 +4557,9 @@ class FileSystem {
45474557
async read(filepath, options = {}) {
45484558
try {
45494559
let buffer = await this._readFile(filepath, options);
4560+
if (typeof buffer === 'string' && options.autocrlf) {
4561+
buffer = buffer.replace(/\r\n/g, '\n');
4562+
}
45504563
// Convert plain ArrayBuffers to Buffers
45514564
if (typeof buffer !== 'string') {
45524565
buffer = Buffer.from(buffer);
@@ -5077,11 +5090,21 @@ async function addToIndex({
50775090
}
50785091
}
50795092
} else {
5093+
const config = await GitConfigManager.get({ fs, gitdir });
5094+
const autocrlf = (await config.get('core.autocrlf')) || false;
50805095
const object = stats.isSymbolicLink()
50815096
? await fs.readlink(join(dir, currentFilepath)).then(posixifyPathBuffer)
5082-
: await fs.read(join(dir, currentFilepath));
5097+
: await fs.read(join(dir, currentFilepath), {
5098+
encoding: 'utf8',
5099+
autocrlf,
5100+
});
50835101
if (object === null) throw new NotFoundError(currentFilepath)
5084-
const oid = await _writeObject({ fs, gitdir, type: 'blob', object });
5102+
const oid = await _writeObject({
5103+
fs,
5104+
gitdir,
5105+
type: 'blob',
5106+
object: new TextEncoder().encode(object),
5107+
});
50855108
index.insert({ filepath: currentFilepath, stats, oid });
50865109
}
50875110
});

0 commit comments

Comments
 (0)