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 * as FSE from 'fs-extra'
import { getCommits, git, IGitExecutionOptions } from '.' import { getCommits, revRange } from '.'
import { CommitOneLine } from '../../models/commit' import { Commit, CommitOneLine } from '../../models/commit'
import { Repository } from '../../models/repository' 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 squashOnto - commit to squash the `squash` commits onto
* @param previousCommit - sha of commit before all commits in squash operation * @param previousCommit - sha of commit before all commits in squash operation
* @param commitSummary - summary of new commit made by squash * @param commitSummary - summary of new commit made by squash
@ -16,72 +17,54 @@ import { Repository } from '../../models/repository'
*/ */
export async function squash( export async function squash(
repository: Repository, repository: Repository,
squash: ReadonlyArray<CommitOneLine>, toSquash: ReadonlyArray<CommitOneLine>,
squashOnto: CommitOneLine, squashOnto: CommitOneLine,
logIndex: number, lastRetainedCommitRef: string,
commitSummary: string, commitSummary: string,
commitDescription: string commitDescription: string
): Promise<ReadonlyArray<string>> { ): Promise<RebaseResult> {
const options: IGitExecutionOptions = { const commits: Commit[] = [
env: { ...(await getCommits(repository, revRange(lastRetainedCommitRef, 'HEAD'))),
// if we don't provide editor, we can't detect git errors ]
// GIT_EDITOR: ':',
},
}
// get commits from log to cherry pick let todoOutput = ''
/* commits.forEach(c => {
const commits = await getCommits( 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, repository,
'HEAD~' + logIndex + 1, todoPath,
logIndex + 1 lastRetainedCommitRef,
)
*/
//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,
'squash', 'squash',
options `cat "${messagePath}" >`
// TODO: add progress
) )
return [] FSE.remove(todoPath)
FSE.remove(messagePath)
// parse todo return result
// build new todo
// save todo
//return true
} }

View file

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