mirror your GitHub repos to tangled.org automatically
1

Configure Feed

Select the types of activity you want to include in your feed.

at main 4.7 kB View raw
1import { execFileSync } from 'node:child_process' 2import { afterEach, beforeEach, describe, expect, it } from 'vitest' 3import { RemoteRejectedError } from '../../server/utils/git-wire/errors' 4import { runSplice, runSpliceDelete } from '../../server/utils/splice' 5import { fakeGithubFetch, GitFixture, localReceivePackFactory } from '../utils/git-wire' 6 7describe('splice (end-to-end against real git binaries)', () => { 8 let fx: GitFixture 9 let realFetch: typeof globalThis.fetch 10 11 beforeEach(() => { 12 fx = new GitFixture() 13 realFetch = globalThis.fetch 14 }) 15 16 afterEach(() => { 17 globalThis.fetch = realFetch 18 fx.cleanup() 19 }) 20 21 function wireGithub(ghBare: string) { 22 globalThis.fetch = fakeGithubFetch(new Map([['owner/repo', ghBare]])) as unknown as typeof globalThis.fetch 23 } 24 25 it('mirrors a first push into an empty knot, transferring objects end to end', async () => { 26 const gh = fx.initBare('gh.git') 27 const work = fx.initWork('work') 28 const sha = fx.commit(work, 'a.txt', 'hello world') 29 fx.pushTo(work, gh, 'HEAD:refs/heads/main') 30 const knot = fx.initBare('knot.git') 31 wireGithub(gh) 32 33 const result = await runSplice(localReceivePackFactory(knot), { 34 repoFullName: 'owner/repo', 35 ref: 'refs/heads/main', 36 want: sha, 37 token: 'tok', 38 }) 39 40 expect(result).toEqual({ status: 'synced', sha }) 41 expect(fx.revParse(knot, 'refs/heads/main')).toBe(sha) 42 expect(execFileSync('git', ['cat-file', '-p', `${sha}:a.txt`], { cwd: knot, encoding: 'utf8' })).toBe('hello world') 43 }) 44 45 it('streams only the delta on a follow-up push (thin pack via knot tips as haves)', async () => { 46 const gh = fx.initBare('gh.git') 47 const work = fx.initWork('work') 48 const first = fx.commit(work, 'a.txt', 'a'.repeat(8000)) 49 fx.pushTo(work, gh, 'HEAD:refs/heads/main') 50 const knot = fx.initBare('knot.git') 51 wireGithub(gh) 52 53 await runSplice(localReceivePackFactory(knot), { repoFullName: 'owner/repo', ref: 'refs/heads/main', want: first, token: 'tok' }) 54 55 const second = fx.commit(work, 'b.txt', 'b'.repeat(8000)) 56 fx.pushTo(work, gh, 'HEAD:refs/heads/main') 57 const result = await runSplice(localReceivePackFactory(knot), { repoFullName: 'owner/repo', ref: 'refs/heads/main', want: second, token: 'tok' }) 58 59 expect(result).toEqual({ status: 'synced', sha: second }) 60 expect(fx.revParse(knot, 'refs/heads/main')).toBe(second) 61 }) 62 63 it('no-ops when the knot tip already equals want', async () => { 64 const gh = fx.initBare('gh.git') 65 const work = fx.initWork('work') 66 const sha = fx.commit(work, 'a.txt', 'hello') 67 fx.pushTo(work, gh, 'HEAD:refs/heads/main') 68 const knot = fx.initBare('knot.git') 69 wireGithub(gh) 70 71 await runSplice(localReceivePackFactory(knot), { repoFullName: 'owner/repo', ref: 'refs/heads/main', want: sha, token: 'tok' }) 72 const again = await runSplice(localReceivePackFactory(knot), { repoFullName: 'owner/repo', ref: 'refs/heads/main', want: sha, token: 'tok' }) 73 74 expect(again).toEqual({ status: 'already-synced', sha }) 75 }) 76 77 it('aborts a push that exceeds the byte cap', async () => { 78 const gh = fx.initBare('gh.git') 79 const work = fx.initWork('work') 80 const sha = fx.commit(work, 'a.txt', 'x'.repeat(20_000)) 81 fx.pushTo(work, gh, 'HEAD:refs/heads/main') 82 const knot = fx.initBare('knot.git') 83 wireGithub(gh) 84 85 const prev = process.env.NUXT_MAX_PACK_BYTES 86 process.env.NUXT_MAX_PACK_BYTES = '10' 87 try { 88 await expect( 89 runSplice(localReceivePackFactory(knot), { repoFullName: 'owner/repo', ref: 'refs/heads/main', want: sha, token: 'tok' }), 90 ).rejects.toMatchObject({ constructor: RemoteRejectedError, reason: 'too-big' }) 91 } 92 finally { 93 if (prev === undefined) delete process.env.NUXT_MAX_PACK_BYTES 94 else process.env.NUXT_MAX_PACK_BYTES = prev 95 } 96 }) 97 98 it('deletes a ref and treats an already-absent ref as success', async () => { 99 const gh = fx.initBare('gh.git') 100 const work = fx.initWork('work') 101 const sha = fx.commit(work, 'a.txt', 'hello') 102 fx.pushTo(work, gh, 'HEAD:refs/heads/main') 103 const knot = fx.initBare('knot.git') 104 wireGithub(gh) 105 106 await runSplice(localReceivePackFactory(knot), { repoFullName: 'owner/repo', ref: 'refs/heads/main', want: sha, token: 'tok' }) 107 108 expect(await runSpliceDelete(localReceivePackFactory(knot), 'refs/heads/main')).toEqual({ status: 'synced' }) 109 expect(() => fx.revParse(knot, 'refs/heads/main')).toThrow(/unknown revision|ambiguous argument|fatal/) 110 111 expect(await runSpliceDelete(localReceivePackFactory(knot), 'refs/heads/gone')).toEqual({ status: 'already-absent' }) 112 }) 113})