diff --git a/dist/Logger.d.mts b/dist/Logger.d.mts index 5364a25..18279a8 100644 --- a/dist/Logger.d.mts +++ b/dist/Logger.d.mts @@ -3,5 +3,7 @@ * * SPDX-License-Identifier: GPL-3.0-only OR GPL-2.0-only */ -declare const Logger: Console; -export { Logger, }; +import { Logger as PinoLogger } from 'pino'; +declare let Logger: PinoLogger; +declare function setLogger(logger: PinoLogger): void; +export { Logger, setLogger, }; diff --git a/dist/Logger.mjs b/dist/Logger.mjs index b92fb71..bb3d133 100644 --- a/dist/Logger.mjs +++ b/dist/Logger.mjs @@ -3,24 +3,11 @@ * * SPDX-License-Identifier: GPL-3.0-only OR GPL-2.0-only */ -// import { Logger as TsLogger } from 'tslog' -// Define the enum for log levels -// enum LogLevel { -// Silly = 0, -// Trace = 1, -// Debug = 2, -// Info = 3, -// Warn = 4, -// Error = 5, -// Fatal = 6 -// } -// Create the logger instance using the enum -// const Logger = new TsLogger({ -// name: '@foo/bar', -// minLevel: process.env['RUNNER_DEBUG'] === '1' ? LogLevel.Silly : LogLevel.Fatal -// }) -const Logger = console; -export { Logger, -// LogLevel, - }; +import { pino } from 'pino'; +let Logger = pino({ level: 'silent' }); +function setLogger(logger) { + Logger = logger; +} +// const Logger = console +export { Logger, setLogger, }; //# sourceMappingURL=Logger.mjs.map \ No newline at end of file diff --git a/dist/Logger.mjs.map b/dist/Logger.mjs.map index 47e7a07..7054cd7 100644 --- a/dist/Logger.mjs.map +++ b/dist/Logger.mjs.map @@ -1 +1 @@ -{"version":3,"file":"Logger.mjs","sourceRoot":"","sources":["../src/Logger.mts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,6CAA6C;AAE7C,iCAAiC;AACjC,kBAAkB;AAClB,eAAe;AACf,eAAe;AACf,eAAe;AACf,cAAc;AACd,cAAc;AACd,eAAe;AACf,cAAc;AACd,IAAI;AAEJ,4CAA4C;AAC5C,iCAAiC;AACjC,uBAAuB;AACvB,qFAAqF;AACrF,KAAK;AAEL,MAAM,MAAM,GAAG,OAAO,CAAA;AAEtB,OAAO,EACL,MAAM;AACN,YAAY;EACb,CAAA"} \ No newline at end of file +{"version":3,"file":"Logger.mjs","sourceRoot":"","sources":["../src/Logger.mts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAwB,MAAM,MAAM,CAAA;AAEjD,IAAI,MAAM,GAAG,IAAI,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAC,CAAC,CAAA;AAEpC,SAAS,SAAS,CAAC,MAAkB;IACnC,MAAM,GAAG,MAAM,CAAA;AACjB,CAAC;AAED,yBAAyB;AAEzB,OAAO,EACL,MAAM,EACN,SAAS,GACV,CAAA"} \ No newline at end of file diff --git a/dist/main.mjs b/dist/main.mjs index a6dcd19..6eba8c8 100644 --- a/dist/main.mjs +++ b/dist/main.mjs @@ -6,18 +6,43 @@ import { GitCommandManager, } from './GitCommandManager.mjs'; import { GitLsRemoteParser, } from './GitLsRemoteParser.mjs'; import { GitLsRemoteOutputCmp, } from './GitLsRemoteOutputCmp.mjs'; -// import { -// Logger as libLogger, -// LogLevel, -// } from './Logger.mjs' +import { setLogger as setGitRemoteRefsLogger, } from './Logger.mjs'; import { GitRemoteRefMap, } from './GitRemoteRefMap.mjs'; // import { Logger as TsLogger } from 'tslog' -// if (require.main === module) { +import { pino } from 'pino'; +import { PinoPretty } from 'pino-pretty'; (async () => { // libLogger.settings.minLevel = LogLevel.Silly // const logger = new TsLogger({name: "main", minLevel: LogLevel.Silly}) - const logger = console; - // Logger.logLevel = 'silly' + // const logger = console + const startTime = performance.now(); + const levelEmojis = { + trace: '🔍', + debug: '🐛', + info: 'ℹī¸', + warn: '⚠ī¸', + error: '❌', + fatal: '💀' + }; + const pretty = PinoPretty({ + colorize: true, + ignore: [ + 'pid', + 'hostname', + 'module', + ].join(), + // @ts-expect-error The custom prettifier extras, currently define only `colors`, not eg. `label` etc. + customPrettifiers: { + time: () => `+${((performance.now() - startTime) / 1000).toFixed(3)}s`, + // @ts-expect-error Throws an erro for some reason + level: (_logLevel, _k, _l, { label }) => levelEmojis[label.toLowerCase()] || '❓', + } + }); + const logger = pino({ + level: 'trace', + }, pretty); + const childLogger = logger.child({ module: '@foo/bar' }); + setGitRemoteRefsLogger(childLogger); const git = new GitCommandManager(); await git.init(); const parser = new GitLsRemoteParser(); @@ -64,5 +89,4 @@ import { GitRemoteRefMap, } from './GitRemoteRefMap.mjs'; const fooOneOutput = { remote: 'foo-one-remote', refMap: new GitRemoteRefMap([{ refname: 'foo', oid: ''.padStart(40, '1') }]) }; await runSmokeTest('OID_MISMATCH', fooZeroOutput, fooOneOutput); })(); -// } //# sourceMappingURL=main.mjs.map \ No newline at end of file diff --git a/dist/main.mjs.map b/dist/main.mjs.map index 55cd58b..0dd4463 100644 --- a/dist/main.mjs.map +++ b/dist/main.mjs.map @@ -1 +1 @@ -{"version":3,"file":"main.mjs","sourceRoot":"","sources":["../src/main.mts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"main.mjs","sourceRoot":"","sources":["../src/main.mts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/new/git-remote-refs-main.ts b/new/git-remote-refs-main.ts new file mode 100644 index 0000000..77fe5aa --- /dev/null +++ b/new/git-remote-refs-main.ts @@ -0,0 +1,24 @@ +import { GitRemoteRefs } from './git-remote-refs'; + +async function main() { + const repoUrl1 = 'https://git.launchpad.net/beautifulsoup'; + const repoUrl2 = 'https://github.com/facsimiles/beautifulsoup.git'; + + try { + const diff = await GitRemoteRefs.compare(repoUrl1, repoUrl2); + + + if ( diff ) { + console.log('Detailed comparison:'); + console.log('In-sync refs:', diff.inSyncRefs); + console.log('Out-of-sync refs:', diff.outOfSyncRefs); + console.log('Missing refs:', diff.missingRefs); + } else { + console.log('Repositories are in sync'); + } + } catch (error) { + console.error('Error:', error); + } +} + +main(); diff --git a/new/git-remote-refs.ts b/new/git-remote-refs.ts new file mode 100644 index 0000000..588a555 --- /dev/null +++ b/new/git-remote-refs.ts @@ -0,0 +1,198 @@ +// git-remote-refs.ts + +// Utility types +type Hex = string; + +type GitRef = { + name: string; + oid: Hex; + symref?: string; +}; + +type ComparisonResult = { + inSync: boolean; + inSyncRefs: GitRef[]; + outOfSyncRefs: { ref: GitRef; otherOid: Hex }[]; + missingRefs: { repo: 'A' | 'B'; ref: GitRef }[]; +}; + +// Constants +const PACKET_DELIM = '0001'; +const PACKET_FLUSH = '0000'; +const GIT_HASH_ALGO = 'sha1'; +const HEX_PACKET_LENGTH = 4; + +// Regular expressions for strict parsing +const OID_REGEX = /^[0-9a-f]{40}([0-9a-f]{24})?$/i; +const REF_NAME_REGEX = /^[^\s]+$/; + +class GitRemoteRefs { + private static userAgent = 'GitRemoteRefs/1.0'; + private static textEncoder = new TextEncoder(); + private static textDecoder = new TextDecoder(); + + private static readonly lsRefsRequest: Uint8Array = GitRemoteRefs.createLsRefsRequest(); + + private static encodePacket(data: string): Uint8Array { + const packetContent = `${data}\n`; + const length = packetContent.length + HEX_PACKET_LENGTH; + const packet = `${length.toString(16).padStart(HEX_PACKET_LENGTH, '0')}${packetContent}`; + return GitRemoteRefs.textEncoder.encode(packet); + } + + private static createLsRefsRequest(): Uint8Array { + const packets: Uint8Array[] = [ + GitRemoteRefs.encodePacket(`command=ls-refs`), + GitRemoteRefs.encodePacket(`agent=${GitRemoteRefs.userAgent}`), + GitRemoteRefs.encodePacket(`object-format=${GIT_HASH_ALGO}`), + GitRemoteRefs.textEncoder.encode(PACKET_DELIM), + GitRemoteRefs.encodePacket('peel'), + GitRemoteRefs.encodePacket('symrefs'), + GitRemoteRefs.encodePacket('unborn'), + GitRemoteRefs.textEncoder.encode(PACKET_FLUSH) + ]; + + return GitRemoteRefs.concatUint8Arrays(packets); + } + + private static concatUint8Arrays(arrays: Uint8Array[]): Uint8Array { + const totalLength = arrays.reduce((acc, arr) => acc + arr.length, 0); + const result = new Uint8Array(totalLength); + let offset = 0; + for (const arr of arrays) { + result.set(arr, offset); + offset += arr.length; + } + return result; + } + + private static async* packetParser(reader: ReadableStreamDefaultReader): AsyncGenerator { + let buffer = new Uint8Array(0); + + while (true) { + if (buffer.length < HEX_PACKET_LENGTH) { + const { value, done } = await reader.read(); + if (done) break; + buffer = GitRemoteRefs.concatUint8Arrays([buffer, value]); + continue; + } + + const packetLength = parseInt(GitRemoteRefs.textDecoder.decode(buffer.slice(0, HEX_PACKET_LENGTH)), 16); + + if (packetLength === 0) { + yield PACKET_FLUSH; + buffer = buffer.slice(HEX_PACKET_LENGTH); + continue; + } + + if (packetLength === 1) { + yield PACKET_DELIM; + buffer = buffer.slice(HEX_PACKET_LENGTH); + continue; + } + + if (buffer.length < packetLength) { + const { value, done } = await reader.read(); + if (done) break; + buffer = GitRemoteRefs.concatUint8Arrays([buffer, value]); + continue; + } + + const packetContent = GitRemoteRefs.textDecoder.decode(buffer.slice(HEX_PACKET_LENGTH, packetLength)); + yield packetContent.trim(); + buffer = buffer.slice(packetLength); + } + } + + private static parseRef(line: string): GitRef | null { + const [oid, name, ...rest] = line.split(' '); + if (!oid || !name || !OID_REGEX.test(oid) || !REF_NAME_REGEX.test(name)) return null; + + const ref: GitRef = { name, oid }; + rest.forEach(part => { + if (part.startsWith('symref-target:')) { + ref.symref = part.split(':')[1]; + } + }); + + return ref; + } + + private static async sendLsRefsCommand(repoUrl: string): Promise { + const url = new URL(repoUrl); + url.pathname = `${url.pathname}/git-upload-pack`; + + const response = await fetch(url.toString(), { + method: 'POST', + headers: { + 'Content-Type': 'application/x-git-upload-pack-request', + 'Git-Protocol': 'version=2', + }, + body: GitRemoteRefs.lsRefsRequest, + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const reader = response.body!.getReader(); + const refs: GitRef[] = []; + + for await (const packet of GitRemoteRefs.packetParser(reader)) { + if (packet === PACKET_FLUSH) break; + const ref = GitRemoteRefs.parseRef(packet); + if (ref) refs.push(ref); + } + + return refs; + } + + public static async lsRefs(repoUrl: string): Promise { + return GitRemoteRefs.sendLsRefsCommand(repoUrl); + } + + private static compareRefs(refsA: GitRef[], refsB: GitRef[]): ComparisonResult { + console.log({refsA, refsB}) + const refMapA = new Map(refsA.map(ref => [ref.name, ref])); + const refMapB = new Map(refsB.map(ref => [ref.name, ref])); + + const inSyncRefs: GitRef[] = []; + const outOfSyncRefs: { ref: GitRef, otherOid: Hex }[] = []; + const missingRefs: { repo: 'A' | 'B', ref: GitRef }[] = []; + + for (const [name, refA] of refMapA) { + const refB = refMapB.get(name); + if (refB) { + if (refA.oid === refB.oid) { + inSyncRefs.push(refA); + } else { + outOfSyncRefs.push({ ref: refA, otherOid: refB.oid }); + } + refMapB.delete(name); + } else { + missingRefs.push({ repo: 'B', ref: refA }); + } + } + + for (const refB of refMapB.values()) { + missingRefs.push({ repo: 'A', ref: refB }); + } + + const inSync = outOfSyncRefs.length === 0 && missingRefs.length === 0; + + return { inSync, inSyncRefs, outOfSyncRefs, missingRefs }; + } + + public static async compare(repoUrlA: string, repoUrlB: string): Promise { + const [refsA, refsB] = await Promise.all([ + GitRemoteRefs.lsRefs(repoUrlA), + GitRemoteRefs.lsRefs(repoUrlB) + ]); + + const comparison = GitRemoteRefs.compareRefs(refsA, refsB); + + return comparison.inSync ? null : comparison; + } +} + +export { GitRemoteRefs, GitRef, ComparisonResult }; diff --git a/package-lock.json b/package-lock.json index ca56cc7..d01da56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,16 @@ "name": "@rindeal/git-remote-refs-cmp", "version": "0.3.0", "license": "GPL-3.0-only OR GPL-2.0-only", + "dependencies": { + "pino": "^9.4.0" + }, "devDependencies": { "@eslint/js": "^9.9.1", "@tsconfig/node20": "^20.1.4", "@types/jest": "^29.5.12", "@types/node": "^22.5.4", "eslint": "^9.9.1", + "pino-pretty": "^11.2.2", "ts-jest": "^29.2.5", "typescript": "^5.0.0", "typescript-eslint": "^8.4.0" @@ -1631,6 +1635,17 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -1734,6 +1749,14 @@ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -1856,6 +1879,25 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1933,6 +1975,29 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -2022,9 +2087,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz", - "integrity": "sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", "dev": true, "peer": true }, @@ -2079,6 +2144,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2128,6 +2199,15 @@ "node": ">= 8" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -2237,6 +2317,15 @@ "dev": true, "peer": true }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2429,6 +2518,22 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -2479,6 +2584,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "dev": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2525,6 +2636,20 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -2788,6 +2913,12 @@ "node": ">= 0.4" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -2805,6 +2936,25 @@ "node": ">=10.17.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3672,6 +3822,15 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3922,6 +4081,15 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3971,12 +4139,19 @@ "node": ">=8" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "peer": true, "dependencies": { "wrappy": "1" } @@ -4138,6 +4313,66 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pino": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.4.0.tgz", + "integrity": "sha512-nbkQb5+9YPhQRz/BeQmrWpEknAaqjpAqRK8NwJpmrX/JHu7JuZC5G1CeAwJDJfGes4h+YihC6in3Q2nGb+Y09w==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", + "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", + "dev": true, + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -4252,6 +4487,19 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-warning": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.0.tgz", + "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -4266,6 +4514,16 @@ "node": ">= 6" } }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4312,12 +4570,40 @@ } ] }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, + "node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4421,6 +4707,39 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "dev": true + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4475,6 +4794,14 @@ "node": ">=8" } }, + "node_modules/sonic-boom": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.1.0.tgz", + "integrity": "sha512-NGipjjRicyJJ03rPiZCJYjwlsuP2d1/5QUviozRXC7S3WdVWNK5e3Ojieb9CCyfhq2UC+3+SRd9nG3I2lPRvUw==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4496,6 +4823,14 @@ "source-map": "^0.6.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4524,6 +4859,14 @@ "node": ">=8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -4643,6 +4986,14 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -4932,8 +5283,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/write-file-atomic": { "version": "4.0.2", diff --git a/package.json b/package.json index 2e8c875..280032d 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,12 @@ "@types/jest": "^29.5.12", "@types/node": "^22.5.4", "eslint": "^9.9.1", + "pino-pretty": "^11.2.2", "ts-jest": "^29.2.5", "typescript": "^5.0.0", "typescript-eslint": "^8.4.0" + }, + "dependencies": { + "pino": "^9.4.0" } } diff --git a/src/Logger.mts b/src/Logger.mts index 181ae33..4df6aae 100644 --- a/src/Logger.mts +++ b/src/Logger.mts @@ -4,28 +4,17 @@ * SPDX-License-Identifier: GPL-3.0-only OR GPL-2.0-only */ -// import { Logger as TsLogger } from 'tslog' +import { pino, Logger as PinoLogger } from 'pino' -// Define the enum for log levels -// enum LogLevel { -// Silly = 0, -// Trace = 1, -// Debug = 2, -// Info = 3, -// Warn = 4, -// Error = 5, -// Fatal = 6 -// } +let Logger = pino({level: 'silent'}) -// Create the logger instance using the enum -// const Logger = new TsLogger({ -// name: '@foo/bar', -// minLevel: process.env['RUNNER_DEBUG'] === '1' ? LogLevel.Silly : LogLevel.Fatal -// }) +function setLogger(logger: PinoLogger) { + Logger = logger +} -const Logger = console +// const Logger = console export { Logger, - // LogLevel, + setLogger, } diff --git a/src/main.mts b/src/main.mts index 6586fa6..1a3e64d 100644 --- a/src/main.mts +++ b/src/main.mts @@ -16,41 +16,82 @@ import { import { GitLsRemoteOutput, } from './GitLsRemoteOutput.mjs' -// import { - // Logger as libLogger, - // LogLevel, -// } from './Logger.mjs' +import { + setLogger as setGitRemoteRefsLogger, +} from './Logger.mjs' import { GitRemoteRefMap, } from './GitRemoteRefMap.mjs' // import { Logger as TsLogger } from 'tslog' +import { pino } from 'pino' +import { PinoPretty } from 'pino-pretty' + +(async () => { + // libLogger.settings.minLevel = LogLevel.Silly + // const logger = new TsLogger({name: "main", minLevel: LogLevel.Silly}) + // const logger = console + const startTime = performance.now() + const levelEmojis = { + trace: '🔍', + debug: '🐛', + info: 'ℹī¸', + warn: '⚠ī¸', + error: '❌', + fatal: '💀' + } -// if (require.main === module) { - (async () => { - // libLogger.settings.minLevel = LogLevel.Silly - // const logger = new TsLogger({name: "main", minLevel: LogLevel.Silly}) - const logger = console - // Logger.logLevel = 'silly' + const pretty = PinoPretty({ + colorize: true, + ignore: [ + 'pid', + 'hostname', + 'module', + ].join(), + // @ts-expect-error The custom prettifier extras, currently define only `colors`, not eg. `label` etc. + customPrettifiers: { + time: () => `+${((performance.now() - startTime) / 1000).toFixed(3)}s`, + + // @ts-expect-error Throws an erro for some reason + level: (_logLevel, _k, _l, { label }) => levelEmojis[label.toLowerCase()] || '❓', + } + }) + const logger = pino({ + level: 'trace', + }, pretty) + const childLogger = logger.child({module: '@foo/bar'}) + setGitRemoteRefsLogger(childLogger) - const git = new GitCommandManager() - await git.init() - const parser = new GitLsRemoteParser() - const lsRemoteCmp = new GitLsRemoteOutputCmp() + const git = new GitCommandManager() + await git.init() + const parser = new GitLsRemoteParser() + const lsRemoteCmp = new GitLsRemoteOutputCmp() - // Smoke test real mirrored repository, should not differ + // Smoke test real mirrored repository, should not differ - const sourceRemote = 'https://git.launchpad.net/beautifulsoup' - const targetRemote = 'https://github.com/facsimiles/beautifulsoup.git' + const sourceRemote = 'https://git.launchpad.net/beautifulsoup' + const targetRemote = 'https://github.com/facsimiles/beautifulsoup.git' - const [source, target] = await Promise.all( - [sourceRemote, targetRemote].map(async (remote) => - parser.parse(await git.lsRemote({ remote }), remote) - ) + const [source, target] = await Promise.all( + [sourceRemote, targetRemote].map(async (remote) => + parser.parse(await git.lsRemote({ remote }), remote) ) + ) - const diff = await lsRemoteCmp.compare(source, target) + const diff = await lsRemoteCmp.compare(source, target) + if (diff) { + logger.info('The repositories differ:') + logger.info(diff) + logger.info(diff.type.toString()) + } else { + logger.info('The repositories are exact clones.') + } + + const runSmokeTest = async (testName: string, output1: GitLsRemoteOutput, output2: GitLsRemoteOutput) => { + logger.debug(''.padStart(79, '-')) + logger.warn(`Smoke test: ${testName}`) + const diff = await lsRemoteCmp.compare(output1, output2) if (diff) { logger.info('The repositories differ:') logger.info(diff) @@ -58,37 +99,24 @@ import { } else { logger.info('The repositories are exact clones.') } + } - const runSmokeTest = async (testName: string, output1: GitLsRemoteOutput, output2: GitLsRemoteOutput) => { - logger.debug(''.padStart(79, '-')) - logger.warn(`Smoke test: ${testName}`) - const diff = await lsRemoteCmp.compare(output1, output2) - if (diff) { - logger.info('The repositories differ:') - logger.info(diff) - logger.info(diff.type.toString()) - } else { - logger.info('The repositories are exact clones.') - } - } - - // REF_COUNT_MISMATCH - const oneRefOutput: GitLsRemoteOutput = { remote: 'one-ref-remote', refMap: new GitRemoteRefMap([{ refname: 'one', oid: ''.padStart(40, '0') }]) } - const twoRefOutput: GitLsRemoteOutput = { remote: 'two-ref-remote', refMap: new GitRemoteRefMap([{ refname: 'one', oid: ''.padStart(40, '0') }, { refname: 'two', oid: ''.padStart(40, '0') }]) } - await runSmokeTest('REF_COUNT_MISMATCH', oneRefOutput, twoRefOutput) + // REF_COUNT_MISMATCH + const oneRefOutput: GitLsRemoteOutput = { remote: 'one-ref-remote', refMap: new GitRemoteRefMap([{ refname: 'one', oid: ''.padStart(40, '0') }]) } + const twoRefOutput: GitLsRemoteOutput = { remote: 'two-ref-remote', refMap: new GitRemoteRefMap([{ refname: 'one', oid: ''.padStart(40, '0') }, { refname: 'two', oid: ''.padStart(40, '0') }]) } + await runSmokeTest('REF_COUNT_MISMATCH', oneRefOutput, twoRefOutput) - // ZERO_REFS - const emptyOutput: GitLsRemoteOutput = { remote: 'empty-remote', refMap: new GitRemoteRefMap() } - await runSmokeTest('ZERO_REFS', emptyOutput, emptyOutput) + // ZERO_REFS + const emptyOutput: GitLsRemoteOutput = { remote: 'empty-remote', refMap: new GitRemoteRefMap() } + await runSmokeTest('ZERO_REFS', emptyOutput, emptyOutput) - // REF_NOT_FOUND - const fooOutput: GitLsRemoteOutput = { remote: 'foo-remote', refMap: new GitRemoteRefMap([{ refname: 'foo', oid: ''.padStart(40, '0') }]) } - const barOutput: GitLsRemoteOutput = { remote: 'bar-remote', refMap: new GitRemoteRefMap([{ refname: 'bar', oid: ''.padStart(40, '0') }]) } - await runSmokeTest('REF_NOT_FOUND', fooOutput, barOutput) + // REF_NOT_FOUND + const fooOutput: GitLsRemoteOutput = { remote: 'foo-remote', refMap: new GitRemoteRefMap([{ refname: 'foo', oid: ''.padStart(40, '0') }]) } + const barOutput: GitLsRemoteOutput = { remote: 'bar-remote', refMap: new GitRemoteRefMap([{ refname: 'bar', oid: ''.padStart(40, '0') }]) } + await runSmokeTest('REF_NOT_FOUND', fooOutput, barOutput) - // OID_MISMATCH - const fooZeroOutput: GitLsRemoteOutput = { remote: 'foo-zero-remote', refMap: new GitRemoteRefMap([{ refname: 'foo', oid: ''.padStart(40, '0') }]) } - const fooOneOutput: GitLsRemoteOutput = { remote: 'foo-one-remote', refMap: new GitRemoteRefMap([{ refname: 'foo', oid: ''.padStart(40, '1') }]) } - await runSmokeTest('OID_MISMATCH', fooZeroOutput, fooOneOutput) - })() -// } + // OID_MISMATCH + const fooZeroOutput: GitLsRemoteOutput = { remote: 'foo-zero-remote', refMap: new GitRemoteRefMap([{ refname: 'foo', oid: ''.padStart(40, '0') }]) } + const fooOneOutput: GitLsRemoteOutput = { remote: 'foo-one-remote', refMap: new GitRemoteRefMap([{ refname: 'foo', oid: ''.padStart(40, '1') }]) } + await runSmokeTest('OID_MISMATCH', fooZeroOutput, fooOneOutput) +})()