mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
fix(git): recognize colored stale lease rejections (#36041)
This commit is contained in:
@@ -13,6 +13,39 @@ afterEach(() => {
|
||||
})
|
||||
|
||||
describe('normalizeGitErrorMessage', () => {
|
||||
it.each([
|
||||
' ! [rejected] main -> main (stale info)',
|
||||
'\t!\t[rejected] main -> main (stale info)\t',
|
||||
' \x1b[31m! [rejected] main -> main (stale info)\x1b[m',
|
||||
'\x1b[31m ! [rejected] main -> main (stale info)\x1b[0m'
|
||||
])('preserves stale lease rejection details: %s', (rejection) => {
|
||||
for (const newline of ['\n', '\r\n']) {
|
||||
const output = [
|
||||
'Command failed: git push https://user:secret@example.com/repo.git',
|
||||
rejection,
|
||||
"error: failed to push some refs to 'https://token@example.com/repo.git'"
|
||||
].join(newline)
|
||||
|
||||
expect(normalizeGitErrorMessage(new Error(output), 'push')).toBe(
|
||||
output.replace('user:secret@', '').replace('token@', '')
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('does not classify a rejection marker on a separate line as a stale lease rejection', () => {
|
||||
const tail = "error: failed to push some refs to 'origin'"
|
||||
const error = new Error(`Command failed: git push\n !\n [rejected] main (stale info)\n${tail}`)
|
||||
|
||||
expect(normalizeGitErrorMessage(error, 'push')).toBe(tail)
|
||||
})
|
||||
|
||||
it('handles push errors containing many blank lines', () => {
|
||||
const tail = "error: failed to push some refs to 'origin'"
|
||||
const error = new Error(`Command failed: git push\n${'\n'.repeat(64_000)}${tail}`)
|
||||
|
||||
expect(normalizeGitErrorMessage(error, 'push')).toBe(tail)
|
||||
})
|
||||
|
||||
it.each(['remote: stale info', 'hook: stale info'])(
|
||||
'does not classify unrelated output as a lease rejection: %s',
|
||||
(output) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { stripAnsiEscapeSequences } from './ansi-escape-sequences'
|
||||
import { isPushHookFailure } from './source-control-push-failure'
|
||||
|
||||
// Why: strip `user:password@` on any scheme, but a lone `user@` only on HTTP(S) — SSH's git@host user-info is required, so stripping breaks the URL.
|
||||
@@ -6,7 +7,7 @@ const HTTPS_TOKEN_URL_PATTERN = /(https?:\/\/)[^\s/@:]+@/gi
|
||||
const SUBMODULE_PUSH_FAILURE_PATTERN = /Unable to push submodule ['"](.+?)['"]/i
|
||||
const SUBMODULE_PUSH_FAILURE_SENTINEL_PATTERN =
|
||||
/failed to push all needed submodules|Unable to push submodule/i
|
||||
const STALE_LEASE_REJECTION_PATTERN = /^\s*!\s+\[rejected\][^\r\n]*\(stale info\)\s*$/m
|
||||
const STALE_LEASE_REJECTION_PATTERN = /^[ \t]*![ \t]+\[rejected\][^\r\n]*\(stale info\)[ \t]*$/m
|
||||
const SUBMODULE_REMOTE_CHANGED_PATTERN =
|
||||
/non-fast-forward|fetch first|updates were rejected|remote contains work that you do not have/i
|
||||
const NORMALIZED_SUBMODULE_PUSH_FAILURE_PATTERN =
|
||||
@@ -166,7 +167,10 @@ export function normalizeGitErrorMessage(error: unknown, operation?: GitRemoteOp
|
||||
return 'Push rejected: remote has newer commits (non-fast-forward). Please pull or sync first.'
|
||||
}
|
||||
|
||||
if (operation === 'push' && (STALE_LEASE_REJECTION_PATTERN.test(raw) || isPushHookFailure(raw))) {
|
||||
if (
|
||||
operation === 'push' &&
|
||||
(STALE_LEASE_REJECTION_PATTERN.test(stripAnsiEscapeSequences(raw)) || isPushHookFailure(raw))
|
||||
) {
|
||||
// Lease rejection and pre-push hook details precede Git's generic "failed to push some refs" tail line.
|
||||
return raw.trim()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user