Skip to content

Commit

Permalink
fix: fix statusMatrix with win32 linebreaks (#1907)
Browse files Browse the repository at this point in the history
* fix: local test-abortMerge

* chore: website updates

* fix: fix statusMatrix with win32 linebreaks

* chore: replace buffer
  • Loading branch information
jayree committed May 3, 2024
1 parent 545c8f1 commit 2d0c021
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 34 deletions.
8 changes: 4 additions & 4 deletions __tests__/test-abortMerge.js
Expand Up @@ -173,8 +173,8 @@ describe('abortMerge', () => {
fs,
dir,
gitdir,
ours: 'A',
theirs: 'B',
ours: 'c',
theirs: 'd',
abortOnConflict: false,
author: {
name: 'Mr. Test',
Expand All @@ -195,9 +195,9 @@ describe('abortMerge', () => {
await fs.write(`${dir}/b/b`, 'new text for file b')
await fs.write(`${dir}/c/c`, 'new text for file c')

await abortMerge({ fs, dir, gitdir, commit: 'A' })
await abortMerge({ fs, dir, gitdir, commit: 'c' })

const trees = [TREE({ ref: 'A' }), WORKDIR(), STAGE()]
const trees = [TREE({ ref: 'c' }), WORKDIR(), STAGE()]
await walk({
fs,
dir,
Expand Down
15 changes: 13 additions & 2 deletions src/api/add.js
Expand Up @@ -3,6 +3,7 @@ import '../typedefs.js'

import { MultipleGitError } from '../errors/MultipleGitError'
import { NotFoundError } from '../errors/NotFoundError.js'
import { GitConfigManager } from '../managers/GitConfigManager.js'
import { GitIgnoreManager } from '../managers/GitIgnoreManager.js'
import { GitIndexManager } from '../managers/GitIndexManager.js'
import { FileSystem } from '../models/FileSystem.js'
Expand Down Expand Up @@ -117,11 +118,21 @@ async function addToIndex({
}
}
} else {
const config = await GitConfigManager.get({ fs, gitdir })
const autocrlf = (await config.get('core.autocrlf')) || false
const object = stats.isSymbolicLink()
? await fs.readlink(join(dir, currentFilepath)).then(posixifyPathBuffer)
: await fs.read(join(dir, currentFilepath))
: await fs.read(join(dir, currentFilepath), {
encoding: 'utf8',
autocrlf,
})
if (object === null) throw new NotFoundError(currentFilepath)
const oid = await _writeObject({ fs, gitdir, type: 'blob', object })
const oid = await _writeObject({
fs,
gitdir,
type: 'blob',
object: new TextEncoder().encode(object),
})
index.insert({ filepath: currentFilepath, stats, oid })
}
})
Expand Down
3 changes: 3 additions & 0 deletions src/models/FileSystem.js
Expand Up @@ -101,6 +101,9 @@ export class FileSystem {
async read(filepath, options = {}) {
try {
let buffer = await this._readFile(filepath, options)
if (typeof buffer === 'string' && options.autocrlf) {
buffer = buffer.replace(/\r\n/g, '\n')
}
// Convert plain ArrayBuffers to Buffers
if (typeof buffer !== 'string') {
buffer = Buffer.from(buffer)
Expand Down
38 changes: 20 additions & 18 deletions src/models/GitConfig.js
Expand Up @@ -139,26 +139,28 @@ export class GitConfig {
constructor(text) {
let section = null
let subsection = null
this.parsedConfig = text.split('\n').map(line => {
let name = null
let value = null
this.parsedConfig = text
? text.split('\n').map(line => {
let name = null
let value = null

const trimmedLine = line.trim()
const extractedSection = extractSectionLine(trimmedLine)
const isSection = extractedSection != null
if (isSection) {
;[section, subsection] = extractedSection
} else {
const extractedVariable = extractVariableLine(trimmedLine)
const isVariable = extractedVariable != null
if (isVariable) {
;[name, value] = extractedVariable
}
}
const trimmedLine = line.trim()
const extractedSection = extractSectionLine(trimmedLine)
const isSection = extractedSection != null
if (isSection) {
;[section, subsection] = extractedSection
} else {
const extractedVariable = extractVariableLine(trimmedLine)
const isVariable = extractedVariable != null
if (isVariable) {
;[name, value] = extractedVariable
}
}

const path = getPath(section, subsection, name)
return { line, isSection, section, subsection, name, value, path }
})
const path = getPath(section, subsection, name)
return { line, isSection, section, subsection, name, value, path }
})
: []
}

static from(text) {
Expand Down
21 changes: 15 additions & 6 deletions src/models/GitWalkerFs.js
@@ -1,3 +1,4 @@
import { GitConfigManager } from '../managers/GitConfigManager.js'
import { GitIndexManager } from '../managers/GitIndexManager.js'
import { compareStats } from '../utils/compareStats.js'
import { join } from '../utils/join'
Expand Down Expand Up @@ -94,17 +95,22 @@ export class GitWalkerFs {

async content(entry) {
if (entry._content === false) {
const { fs, dir } = this
const { fs, dir, gitdir } = this
if ((await entry.type()) === 'tree') {
entry._content = undefined
} else {
const content = await fs.read(`${dir}/${entry._fullpath}`)
const config = await GitConfigManager.get({ fs, gitdir })
const autocrlf = (await config.get('core.autocrlf')) || false
const content = await fs.read(`${dir}/${entry._fullpath}`, {
encoding: 'utf8',
autocrlf,
})
// workaround for a BrowserFS edge case
entry._actualSize = content.length
if (entry._stat && entry._stat.size === -1) {
entry._stat.size = entry._actualSize
}
entry._content = new Uint8Array(content)
entry._content = new TextEncoder().encode(content)
}
}
return entry._content
Expand All @@ -120,7 +126,10 @@ export class GitWalkerFs {
) {
const stage = index.entriesMap.get(entry._fullpath)
const stats = await entry.stat()
if (!stage || compareStats(stats, stage)) {
const config = await GitConfigManager.get({ fs, gitdir })
const filemode = await config.get('core.filemode')
const trustino = !(process.platform === 'win32')
if (!stage || compareStats(stats, stage, filemode, trustino)) {
const content = await entry.content()
if (content === undefined) {
oid = undefined
Expand All @@ -134,8 +143,8 @@ export class GitWalkerFs {
if (
stage &&
oid === stage.oid &&
stats.mode === stage.mode &&
compareStats(stats, stage)
(!filemode || stats.mode === stage.mode) &&
compareStats(stats, stage, filemode, trustino)
) {
index.insert({
filepath: entry._fullpath,
Expand Down
6 changes: 3 additions & 3 deletions src/utils/compareStats.js
@@ -1,17 +1,17 @@
import { normalizeStats } from './normalizeStats.js'

export function compareStats(entry, stats) {
export function compareStats(entry, stats, filemode = true, trustino = true) {
// Comparison based on the description in Paragraph 4 of
// https://www.kernel.org/pub/software/scm/git/docs/technical/racy-git.txt
const e = normalizeStats(entry)
const s = normalizeStats(stats)
const staleness =
e.mode !== s.mode ||
(filemode && e.mode !== s.mode) ||
e.mtimeSeconds !== s.mtimeSeconds ||
e.ctimeSeconds !== s.ctimeSeconds ||
e.uid !== s.uid ||
e.gid !== s.gid ||
e.ino !== s.ino ||
(trustino && e.ino !== s.ino) ||
e.size !== s.size
return staleness
}
2 changes: 1 addition & 1 deletion website/versioned_docs/version-1.x/annotatedTag.md
Expand Up @@ -21,7 +21,7 @@ Create an annotated tag.
| tagger.email | string | Default is `user.email` config. |
| tagger.timestamp | number = Math.floor(Date.now()/1000) | Set the tagger timestamp field. This is the integer number of seconds since the Unix epoch (1970-01-01 00:00:00). |
| tagger.timezoneOffset | number | Set the tagger timezone offset field. This is the difference, in minutes, from the current timezone to UTC. Default is `(new Date()).getTimezoneOffset()`. |
| gpgsig | string | The gpgsig attached to the tag object. (Mutually exclusive with the `signingKey` option.) |
| gpgsig | string | The gpgsig attached to the tag object. (Mutually exclusive with the `signingKey` option.) |
| signingKey | string | Sign the tag object using this private PGP key. (Mutually exclusive with the `gpgsig` option.) |
| force | boolean = false | Instead of throwing an error if a tag named `ref` already exists, overwrite the existing tag. Note that this option does not modify the original tag object itself. |
| cache | object | a [cache](cache.md) object |
Expand Down
2 changes: 2 additions & 0 deletions website/versioned_docs/version-1.x/statusMatrix.md
Expand Up @@ -66,6 +66,8 @@ representing the HEAD status, WORKDIR status, and STAGE status of the entry.
["g.txt", 1, 2, 3], // modified, staged, with unstaged changes
["h.txt", 1, 0, 1], // deleted, unstaged
["i.txt", 1, 0, 0], // deleted, staged
["j.txt", 1, 2, 0], // deleted, staged, with unstaged-modified changes (new file of the same name)
["k.txt", 1, 1, 0], // deleted, staged, with unstaged changes (new file of the same name)
]
```

Expand Down

0 comments on commit 2d0c021

Please sign in to comment.