Squashing with interactive rebase one test

This commit is contained in:
Becca 2021-04-28 13:52:22 -04:00
parent 18e298ae6b
commit a28b7503d7
2 changed files with 60 additions and 91 deletions

View file

@ -1,13 +1,14 @@
import * as Path from 'path'
import * as FSE from 'fs-extra'
import { getCommits, git, IGitExecutionOptions } from '.'
import { CommitOneLine } from '../../models/commit'
import { getCommits, revRange } from '.'
import { Commit, CommitOneLine } from '../../models/commit'
import { Repository } from '../../models/repository'
import { getTempFilePath } from '../file-system'
import { rebaseInteractive, RebaseResult } from './rebase'
/**
* Initiates an interactive rebase and squashes provided commits
* Squashes provided commits by calling interactive rebase
*
* @param squash - commits to squash onto another commit
* @param toSquash - commits to squash onto another commit
* @param squashOnto - commit to squash the `squash` commits onto
* @param previousCommit - sha of commit before all commits in squash operation
* @param commitSummary - summary of new commit made by squash
@ -16,72 +17,54 @@ import { Repository } from '../../models/repository'
*/
export async function squash(
repository: Repository,
squash: ReadonlyArray<CommitOneLine>,
toSquash: ReadonlyArray<CommitOneLine>,
squashOnto: CommitOneLine,
logIndex: number,
lastRetainedCommitRef: string,
commitSummary: string,
commitDescription: string
): Promise<ReadonlyArray<string>> {
const options: IGitExecutionOptions = {
env: {
// if we don't provide editor, we can't detect git errors
// GIT_EDITOR: ':',
},
}
): Promise<RebaseResult> {
const commits: Commit[] = [
...(await getCommits(repository, revRange(lastRetainedCommitRef, 'HEAD'))),
]
// get commits from log to cherry pick
/*
const commits = await getCommits(
let todoOutput = ''
commits.forEach(c => {
if (toSquash.map(sq => sq.sha).includes(c.sha)) {
return
}
if (c.sha === squashOnto.sha) {
todoOutput += `pick ${c.sha} ${c.summary}\n`
toSquash.forEach(async sq => {
todoOutput += `squash ${sq.sha} ${sq.summary}\n`
})
return
}
todoOutput += `pick ${c.sha} ${c.summary}\n`
})
const todoPath = await getTempFilePath('squashTodo')
await FSE.writeFile(todoPath, todoOutput)
const messagePath = await getTempFilePath('squashCommitMessage')
const message =
commitDescription !== ''
? `${commitSummary}\n\n${commitDescription}`
: commitSummary
await FSE.writeFile(messagePath, message)
const result = await rebaseInteractive(
repository,
'HEAD~' + logIndex + 1,
logIndex + 1
)
*/
//return commits.map(c => c.shortSha)
// current branch name
// const currentBranch = git current branch...
// Create a temporary branch from the head before the earliest squash commit
// - const tempBranch = git checkout head~x -b temp branch... pick a branch name that doesn't exist..
// loop through log
// if commit === SquashOnto
// - cherry pick -n squash onto
// - loop through ToSquash -> cherry pick -n (may have conflicts/Progress?)
// - commit -m commitsummary and commitDescription
// if commit in squashOnto
// - continue loop
// else
// - cherry pick regular
// This loop process could be aborted at anytime.. if so delete temp branch, check out current branch
// check out current branch
// git hard reset --> HEAD~logIndex+1
// git rebase tempBranch ... this should not have conflicts since the branches base history should be the same..
// Start interactive rebase
await git(
[
'rebase',
'-c',
'"sequence.editor=sed -i /123456/d"',
'-i',
'HEAD~'logIndex+1,
],
repository.path,
todoPath,
lastRetainedCommitRef,
'squash',
options
`cat "${messagePath}" >`
// TODO: add progress
)
return []
FSE.remove(todoPath)
FSE.remove(messagePath)
// parse todo
// build new todo
// save todo
//return true
return result
}

View file

@ -1,10 +1,9 @@
import * as Path from 'path'
import * as FSE from 'fs-extra'
import { getCommit, getCommits, git } from '../../../src/lib/git'
import { getCommit, getCommits, RebaseResult } from '../../../src/lib/git'
import { CommitOneLine } from '../../../src/models/commit'
import { Repository } from '../../../src/models/repository'
import { setupEmptyRepositoryDefaultMain } from '../../helpers/repositories'
import { makeCommit } from '../../helpers/repository-scaffolding'
import { squash } from '../../../src/lib/git/squash'
describe('git/cherry-pick', () => {
let repository: Repository
@ -17,36 +16,23 @@ describe('git/cherry-pick', () => {
it('squashes one commit onto the next (non-conflicting)', async () => {
const firstCommit = await makeSquashCommit(repository, 'first')
const firstShortSha = firstCommit.sha.slice(0, 7)
const secondCommit = await makeSquashCommit(repository, 'second')
const secondShortSha = secondCommit.sha.slice(0, 7)
const thirdCommit = await makeSquashCommit(repository, 'third')
const thirdShortSha = thirdCommit.sha.slice(0, 7)
const path = Path.join(repository.path, 'test')
await FSE.writeFile(
Path.join(repository.path, 'test'),
`pick ${firstShortSha} 1\nsquash ${secondShortSha} 2\nsquash ${thirdShortSha} 3\n`
const result = await squash(
repository,
[secondCommit],
firstCommit,
initialCommit.sha,
'Test Summary',
'Test Body'
)
await git(
[
'-c',
`sequence.editor=cat "${path}" >`,
'rebase',
'-i',
initialCommit.sha,
],
repository.path,
'squash',
{
env: {
GIT_EDITOR: ':',
},
}
)
expect(result).toBe(RebaseResult.CompletedWithoutError)
const log = await getCommits(repository, 'HEAD', 5)
const squashed = log[0]
expect(squashed.summary).toBe('Test Summary')
expect(squashed.body).toBe('Test Body\n')
expect(log.length).toBe(2)
})
})