Skip to content

Commit

Permalink
[feat:stash] feature complete for issue isomorphic-git#228 and issue i…
Browse files Browse the repository at this point in the history
…somorphic-git#980, also add more test cases for changes and deletion under a folder
  • Loading branch information
modesty authored and modestysn committed Apr 5, 2024
1 parent 58c61fa commit 9198b7f
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 30 deletions.
155 changes: 137 additions & 18 deletions __tests__/test-stash.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
// @ts-nocheck
/* eslint-env node, browser, jasmine */
const { stash, Errors, setConfig, add, status } = require('isomorphic-git')
const {
stash,
Errors,
setConfig,
add,
status,
commit,
} = require('isomorphic-git')

const { makeFixture } = require('./__helpers__/FixtureFS.js')

Expand Down Expand Up @@ -46,7 +53,7 @@ const stashChanges = async (fs, dir, gitdir, defalt = true, again = true) => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir })
await stash({ fs, dir, gitdir })
} catch (e) {
error = e
console.log(e.stack)
Expand Down Expand Up @@ -226,13 +233,125 @@ describe('stash apply', () => {
bStatus = await status({ fs, dir, gitdir, filepath: 'folder/d.js' })
expect(bStatus).toBe('added')
})

it('stash apply with deleted files', async () => {
const { fs, dir, gitdir } = await makeFixture('test-stash')
await addUserConfig(fs, dir, gitdir)

await fs.rm(`${dir}/a.txt`)
await fs.rm(`${dir}/b.js`)

let aStatus = await status({ fs, dir, gitdir, filepath: 'a.txt' })
expect(aStatus).toBe('*deleted')
let bStatus = await status({ fs, dir, gitdir, filepath: 'b.js' })
expect(bStatus).toBe('*deleted')

let error = null
try {
await stash({ fs, dir, gitdir, op: 'push' })

aStatus = await status({ fs, dir, gitdir, filepath: 'a.txt' })
expect(aStatus).toBe('unmodified')
bStatus = await status({ fs, dir, gitdir, filepath: 'b.js' })
expect(bStatus).toBe('unmodified')

await stash({ fs, dir, gitdir, op: 'apply' })
} catch (e) {
error = e
console.log(e.stack)
}

expect(error).toBeNull()
aStatus = await status({ fs, dir, gitdir, filepath: 'a.txt' })
expect(aStatus).toBe('*deleted')
bStatus = await status({ fs, dir, gitdir, filepath: 'b.js' })
expect(bStatus).toBe('*deleted')
})

it('stash apply with deleted files and staged changes', async () => {
const { fs, dir, gitdir } = await makeFixture('test-stash')
await addUserConfig(fs, dir, gitdir)

await fs.rm(`${dir}/a.txt`)
await fs.write(`${dir}/b.js`, 'staged changes - b')

let aStatus = await status({ fs, dir, gitdir, filepath: 'a.txt' })
expect(aStatus).toBe('*deleted')
let bStatus = await status({ fs, dir, gitdir, filepath: 'b.js' })
expect(bStatus).toBe('*modified')

await add({ fs, dir, gitdir, filepath: ['b.js'] })

bStatus = await status({ fs, dir, gitdir, filepath: 'b.js' })
expect(bStatus).toBe('modified')

let error = null
try {
await stash({ fs, dir, gitdir, op: 'push' })

aStatus = await status({ fs, dir, gitdir, filepath: 'a.txt' })
expect(aStatus).toBe('unmodified')
bStatus = await status({ fs, dir, gitdir, filepath: 'b.js' })
expect(bStatus).toBe('unmodified')

await stash({ fs, dir, gitdir, op: 'apply' })
} catch (e) {
error = e
console.log(e.stack)
}

expect(error).toBeNull()
aStatus = await status({ fs, dir, gitdir, filepath: 'a.txt' })
expect(aStatus).toBe('*deleted')
bStatus = await status({ fs, dir, gitdir, filepath: 'b.js' })
expect(bStatus).toBe('modified')
})

it('stash apply with delete folder', async () => {
const { fs, dir, gitdir } = await makeFixture('test-stash')
await addUserConfig(fs, dir, gitdir)

await fs.mkdir(`${dir}/folder`)
await fs.write(`${dir}/folder/e.js`, 'commited change - e')
await add({ fs, dir, gitdir, filepath: ['folder', 'folder/e.js'] })
await commit({
fs,
dir,
gitdir,
author: { name: 'author', email: 'author@test' },
message: 'add folder',
})

// await fs.rmdir(`${dir}/folder`)
await fs.rm(`${dir}/folder/e.js`)

let aStatus = await status({ fs, dir, gitdir, filepath: 'folder/e.js' })
expect(aStatus).toBe('*deleted')

let error = null
try {
await stash({ fs, dir, gitdir, op: 'push' })

aStatus = await status({ fs, dir, gitdir, filepath: 'folder/e.js' })
expect(aStatus).toBe('unmodified')

await stash({ fs, dir, gitdir, op: 'apply' })
} catch (e) {
error = e
console.log(e.stack)
}

expect(error).toBeNull()
aStatus = await status({ fs, dir, gitdir, filepath: 'folder/e.js' })
expect(aStatus).toBe('*deleted')
})
})

describe('stash list', () => {
it('stash list with no stash', async () => {
const { fs, dir, gitdir } = await makeFixture('test-stash')

const stashList = await stash({ fs, bare: true, dir, gitdir, op: 'list' })
const stashList = await stash({ fs, dir, gitdir, op: 'list' })
expect(stashList).toEqual([])
})

Expand All @@ -241,7 +360,7 @@ describe('stash list', () => {

await stashChanges(fs, dir, gitdir, true, false) // staged and non-unstaged changes

const stashList = await stash({ fs, bare: true, dir, gitdir, op: 'list' })
const stashList = await stash({ fs, dir, gitdir, op: 'list' })
expect(stashList.length).toBe(1)
})

Expand All @@ -251,7 +370,7 @@ describe('stash list', () => {
await stashChanges(fs, dir, gitdir, true, false) // staged and non-unstaged changes
await stashChanges(fs, dir, gitdir, true, false) // staged and non-unstaged changes

const stashList = await stash({ fs, bare: true, dir, gitdir, op: 'list' })
const stashList = await stash({ fs, dir, gitdir, op: 'list' })
expect(stashList.length).toBe(2)
})
})
Expand All @@ -262,7 +381,7 @@ describe('stash drop', () => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir, op: 'drop' })
await stash({ fs, dir, gitdir, op: 'drop' })
} catch (e) {
error = e
}
Expand All @@ -277,13 +396,13 @@ describe('stash drop', () => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir, op: 'drop' })
await stash({ fs, dir, gitdir, op: 'drop' })
} catch (e) {
error = e
}

expect(error).toBeNull()
const stashList = await stash({ fs, bare: true, dir, gitdir, op: 'list' })
const stashList = await stash({ fs, dir, gitdir, op: 'list' })
expect(stashList.length).toBe(0)
})
})
Expand All @@ -294,7 +413,7 @@ describe('stash clear', () => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir, op: 'clear' })
await stash({ fs, dir, gitdir, op: 'clear' })
} catch (e) {
error = e
}
Expand All @@ -309,13 +428,13 @@ describe('stash clear', () => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir, op: 'clear' })
await stash({ fs, dir, gitdir, op: 'clear' })
} catch (e) {
error = e
}

expect(error).toBeNull()
const stashList = await stash({ fs, bare: true, dir, gitdir, op: 'list' })
const stashList = await stash({ fs, dir, gitdir, op: 'list' })
expect(stashList.length).toBe(0)
})

Expand All @@ -327,13 +446,13 @@ describe('stash clear', () => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir, op: 'clear' })
await stash({ fs, dir, gitdir, op: 'clear' })
} catch (e) {
error = e
}

expect(error).toBeNull()
const stashList = await stash({ fs, bare: true, dir, gitdir, op: 'list' })
const stashList = await stash({ fs, dir, gitdir, op: 'list' })
expect(stashList.length).toBe(0)
})
})
Expand All @@ -344,7 +463,7 @@ describe('stash pop', () => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir, op: 'pop' })
await stash({ fs, dir, gitdir, op: 'pop' })
} catch (e) {
error = e
}
Expand All @@ -359,13 +478,13 @@ describe('stash pop', () => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir, op: 'pop' })
await stash({ fs, dir, gitdir, op: 'pop' })
} catch (e) {
error = e
}

expect(error).toBeNull()
const stashList = await stash({ fs, bare: true, dir, gitdir, op: 'list' })
const stashList = await stash({ fs, dir, gitdir, op: 'list' })
expect(stashList.length).toBe(0)
})

Expand All @@ -377,13 +496,13 @@ describe('stash pop', () => {

let error = null
try {
await stash({ fs, bare: true, dir, gitdir, op: 'pop' })
await stash({ fs, dir, gitdir, op: 'pop' })
} catch (e) {
error = e
}

expect(error).toBeNull()
const stashList = await stash({ fs, bare: true, dir, gitdir, op: 'list' })
const stashList = await stash({ fs, dir, gitdir, op: 'list' })
expect(stashList.length).toBe(1)
})
})
41 changes: 29 additions & 12 deletions src/utils/walkerToTreeEntryMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,21 @@ export async function writeTreeChanges(
const [head, stage] = child
if (isStage) {
if (stage) {
filtered.push(child)
// for deleted file in work dir, it also needs to be added on stage
if (await fs.exists(`${dir}/${stage.toString()}`)) {
filtered.push(child)
} else {
changedEntries.push([null, stage]) // record the change (deletion) while stop the iteration
}
}
} else {
if (head) {
filtered.push(child) // workdir, tracked only
// for deleted file in workdir, "stage" (workdir in our case) will be undefined
if (!stage) {
changedEntries.push([head, null]) // record the change (deletion) while stop the iteration
} else {
filtered.push(child) // workdir, tracked only
}
}
}
}
Expand Down Expand Up @@ -201,28 +211,35 @@ export async function applyTreeChanges(
) {
return
}
const type = stash ? await stash.type() : undefined
const type = stash ? await stash.type() : await parent.type()
if (type !== 'tree' && type !== 'blob') {
return
}

const currentFilepath = join(dir, filepath)

// deleted tree or blob
if (!stash && parent) {
if (type === 'tree') {
await fs.rmdir(currentFilepath)
} else if (type === 'blob') {
await fs.rm(currentFilepath)
}
return
}

const oid = await stash.oid()
if (oid === undefined) {
await fs.rm(join(dir, currentFilepath))
} else if (!parent || (await parent.oid()) !== oid) {
if (!parent || (await parent.oid()) !== oid) {
// only apply changes if changed from the parent commit or doesn't exist in the parent commit
if (type === 'tree') {
if (!(await fs.exists(currentFilepath))) {
await fs.mkdir(currentFilepath)
}
await fs.mkdir(currentFilepath)
} else {
const { blob } = await readBlob({ fs, dir, gitdir, oid })
await fs.write(currentFilepath, blob)
// await fs.chmod(currentFilepath, await stash.mode())
if (wasStaged) {
await add({ fs, dir, gitdir, filepath })
}
}
if (wasStaged) {
await add({ fs, dir, gitdir, filepath })
}
}
return {
Expand Down

0 comments on commit 9198b7f

Please sign in to comment.