(stream, { service })
| 4 | import { parseCapabilitiesV2 } from '../wire/parseCapabilitiesV2.js' |
| 5 | |
| 6 | export async function parseRefsAdResponse(stream, { service }) { |
| 7 | const capabilities = new Set() |
| 8 | const refs = new Map() |
| 9 | const symrefs = new Map() |
| 10 | |
| 11 | // There is probably a better way to do this, but for now |
| 12 | // let's just throw the result parser inline here. |
| 13 | const read = GitPktLine.streamReader(stream) |
| 14 | let lineOne = await read() |
| 15 | // skip past any flushes |
| 16 | while (lineOne === null) lineOne = await read() |
| 17 | |
| 18 | if (lineOne === true) throw new EmptyServerResponseError() |
| 19 | |
| 20 | // Handle protocol v2 responses (Bitbucket Server doesn't include a `# service=` line) |
| 21 | if (lineOne.includes('version 2')) { |
| 22 | return parseCapabilitiesV2(read) |
| 23 | } |
| 24 | |
| 25 | // Clients MUST ignore an LF at the end of the line. |
| 26 | if (lineOne.toString('utf8').replace(/\n$/, '') !== `# service=${service}`) { |
| 27 | throw new ParseError(`# service=${service}\\n`, lineOne.toString('utf8')) |
| 28 | } |
| 29 | let lineTwo = await read() |
| 30 | // skip past any flushes |
| 31 | while (lineTwo === null) lineTwo = await read() |
| 32 | // In the edge case of a brand new repo, zero refs (and zero capabilities) |
| 33 | // are returned. |
| 34 | if (lineTwo === true) return { capabilities, refs, symrefs } |
| 35 | lineTwo = lineTwo.toString('utf8') |
| 36 | |
| 37 | // Handle protocol v2 responses |
| 38 | if (lineTwo.includes('version 2')) { |
| 39 | return parseCapabilitiesV2(read) |
| 40 | } |
| 41 | |
| 42 | const [firstRef, capabilitiesLine] = splitAndAssert(lineTwo, '\x00', '\\x00') |
| 43 | capabilitiesLine.split(' ').map(x => capabilities.add(x)) |
| 44 | // see no-refs in https://git-scm.com/docs/pack-protocol#_reference_discovery (since git 2.41.0) |
| 45 | if (firstRef !== '0000000000000000000000000000000000000000 capabilities^{}') { |
| 46 | const [ref, name] = splitAndAssert(firstRef, ' ', ' ') |
| 47 | refs.set(name, ref) |
| 48 | while (true) { |
| 49 | const line = await read() |
| 50 | if (line === true) break |
| 51 | if (line !== null) { |
| 52 | const [ref, name] = splitAndAssert(line.toString('utf8'), ' ', ' ') |
| 53 | refs.set(name, ref) |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | // Symrefs are thrown into the "capabilities" unfortunately. |
| 58 | for (const cap of capabilities) { |
| 59 | if (cap.startsWith('symref=')) { |
| 60 | const m = cap.match(/symref=([^:]+):(.*)/) |
| 61 | if (m.length === 3) { |
| 62 | symrefs.set(m[1], m[2]) |
| 63 | } |
no test coverage detected
searching dependent graphs…