@push.rocks/smartlinuxrepo 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.smartconfig.json +64 -0
  2. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  3. package/dist_ts/00_commitinfo_data.js +9 -0
  4. package/dist_ts/alpine/apkindex.d.ts +39 -0
  5. package/dist_ts/alpine/apkindex.js +211 -0
  6. package/dist_ts/alpine/pkginfo.d.ts +45 -0
  7. package/dist_ts/alpine/pkginfo.js +159 -0
  8. package/dist_ts/alpine/reader.d.ts +20 -0
  9. package/dist_ts/alpine/reader.js +89 -0
  10. package/dist_ts/arch/builder.d.ts +41 -0
  11. package/dist_ts/arch/builder.js +234 -0
  12. package/dist_ts/arch/reader.d.ts +16 -0
  13. package/dist_ts/arch/reader.js +271 -0
  14. package/dist_ts/arch/signer.d.ts +21 -0
  15. package/dist_ts/arch/signer.js +66 -0
  16. package/dist_ts/arch/vercmp.d.ts +12 -0
  17. package/dist_ts/arch/vercmp.js +170 -0
  18. package/dist_ts/debian/control.d.ts +22 -0
  19. package/dist_ts/debian/control.js +137 -0
  20. package/dist_ts/debian/gostring.d.ts +26 -0
  21. package/dist_ts/debian/gostring.js +145 -0
  22. package/dist_ts/debian/indexbuilder.d.ts +47 -0
  23. package/dist_ts/debian/indexbuilder.js +299 -0
  24. package/dist_ts/debian/mailaddress.d.ts +12 -0
  25. package/dist_ts/debian/mailaddress.js +736 -0
  26. package/dist_ts/debian/reader.d.ts +30 -0
  27. package/dist_ts/debian/reader.js +110 -0
  28. package/dist_ts/index.d.ts +23 -0
  29. package/dist_ts/index.js +18 -0
  30. package/dist_ts/plugins.d.ts +8 -0
  31. package/dist_ts/plugins.js +11 -0
  32. package/dist_ts/readers/ar.d.ts +31 -0
  33. package/dist_ts/readers/ar.js +87 -0
  34. package/dist_ts/readers/bytes.d.ts +58 -0
  35. package/dist_ts/readers/bytes.js +147 -0
  36. package/dist_ts/readers/bytesource.d.ts +40 -0
  37. package/dist_ts/readers/bytesource.js +154 -0
  38. package/dist_ts/readers/decompress.d.ts +43 -0
  39. package/dist_ts/readers/decompress.js +269 -0
  40. package/dist_ts/readers/gzipmember.d.ts +32 -0
  41. package/dist_ts/readers/gzipmember.js +176 -0
  42. package/dist_ts/readers/tar.d.ts +85 -0
  43. package/dist_ts/readers/tar.js +731 -0
  44. package/dist_ts/readers/text.d.ts +16 -0
  45. package/dist_ts/readers/text.js +96 -0
  46. package/dist_ts/rpm/builder.d.ts +28 -0
  47. package/dist_ts/rpm/builder.js +208 -0
  48. package/dist_ts/rpm/header.d.ts +138 -0
  49. package/dist_ts/rpm/header.js +546 -0
  50. package/dist_ts/rpm/reader.d.ts +20 -0
  51. package/dist_ts/rpm/reader.js +306 -0
  52. package/dist_ts/rpm/repoconfig.d.ts +15 -0
  53. package/dist_ts/rpm/repoconfig.js +38 -0
  54. package/dist_ts/rpm/repodata.d.ts +44 -0
  55. package/dist_ts/rpm/repodata.js +148 -0
  56. package/dist_ts/rpm/sign.d.ts +30 -0
  57. package/dist_ts/rpm/sign.js +183 -0
  58. package/dist_ts/rpm/updates.d.ts +38 -0
  59. package/dist_ts/rpm/updates.js +265 -0
  60. package/dist_ts/rpm/xml.d.ts +18 -0
  61. package/dist_ts/rpm/xml.js +90 -0
  62. package/dist_ts/shared/architecture.d.ts +8 -0
  63. package/dist_ts/shared/architecture.js +17 -0
  64. package/dist_ts/shared/errors.d.ts +38 -0
  65. package/dist_ts/shared/errors.js +22 -0
  66. package/dist_ts/shared/gopath.d.ts +13 -0
  67. package/dist_ts/shared/gopath.js +53 -0
  68. package/dist_ts/shared/gostrings.d.ts +14 -0
  69. package/dist_ts/shared/gostrings.js +29 -0
  70. package/dist_ts/shared/limits.d.ts +47 -0
  71. package/dist_ts/shared/limits.js +57 -0
  72. package/dist_ts/shared/types.d.ts +213 -0
  73. package/dist_ts/shared/types.js +13 -0
  74. package/dist_ts/shared/url.d.ts +18 -0
  75. package/dist_ts/shared/url.js +371 -0
  76. package/dist_ts/shared/validation.d.ts +21 -0
  77. package/dist_ts/shared/validation.js +58 -0
  78. package/dist_ts/signing/keys.d.ts +36 -0
  79. package/dist_ts/signing/keys.js +89 -0
  80. package/dist_ts/signing/openpgpframing.d.ts +33 -0
  81. package/dist_ts/signing/openpgpframing.js +93 -0
  82. package/dist_ts/signing/signers.d.ts +63 -0
  83. package/dist_ts/signing/signers.js +248 -0
  84. package/dist_ts/writers/gotar.d.ts +43 -0
  85. package/dist_ts/writers/gotar.js +218 -0
  86. package/license.md +19 -0
  87. package/package.json +56 -3
  88. package/readme.md +176 -0
  89. package/ts/00_commitinfo_data.ts +8 -0
  90. package/ts/alpine/apkindex.ts +241 -0
  91. package/ts/alpine/pkginfo.ts +183 -0
  92. package/ts/alpine/reader.ts +96 -0
  93. package/ts/arch/builder.ts +283 -0
  94. package/ts/arch/reader.ts +307 -0
  95. package/ts/arch/signer.ts +70 -0
  96. package/ts/arch/vercmp.ts +188 -0
  97. package/ts/debian/control.ts +150 -0
  98. package/ts/debian/gostring.ts +150 -0
  99. package/ts/debian/indexbuilder.ts +355 -0
  100. package/ts/debian/mailaddress.ts +754 -0
  101. package/ts/debian/reader.ts +126 -0
  102. package/ts/index.ts +46 -0
  103. package/ts/plugins.ts +13 -0
  104. package/ts/readers/ar.ts +102 -0
  105. package/ts/readers/bytes.ts +182 -0
  106. package/ts/readers/bytesource.ts +164 -0
  107. package/ts/readers/decompress.ts +332 -0
  108. package/ts/readers/gzipmember.ts +209 -0
  109. package/ts/readers/tar.ts +835 -0
  110. package/ts/readers/text.ts +91 -0
  111. package/ts/rpm/builder.ts +253 -0
  112. package/ts/rpm/header.ts +628 -0
  113. package/ts/rpm/reader.ts +317 -0
  114. package/ts/rpm/repoconfig.ts +45 -0
  115. package/ts/rpm/repodata.ts +219 -0
  116. package/ts/rpm/sign.ts +200 -0
  117. package/ts/rpm/updates.ts +314 -0
  118. package/ts/rpm/xml.ts +101 -0
  119. package/ts/shared/architecture.ts +16 -0
  120. package/ts/shared/errors.ts +78 -0
  121. package/ts/shared/gopath.ts +54 -0
  122. package/ts/shared/gostrings.ts +31 -0
  123. package/ts/shared/limits.ts +93 -0
  124. package/ts/shared/types.ts +251 -0
  125. package/ts/shared/url.ts +387 -0
  126. package/ts/shared/validation.ts +71 -0
  127. package/ts/signing/keys.ts +110 -0
  128. package/ts/signing/openpgpframing.ts +115 -0
  129. package/ts/signing/signers.ts +315 -0
  130. package/ts/writers/gotar.ts +256 -0
  131. package/README.md +0 -3
@@ -0,0 +1,89 @@
1
+ import { LinuxRepoError, truncated } from '../shared/errors.js';
2
+ import { resolveLinuxPackageLimits } from '../shared/limits.js';
3
+ import { BufferReader, readUpTo } from '../readers/bytes.js';
4
+ import { PackageByteSource } from '../readers/bytesource.js';
5
+ import { readGzipMember } from '../readers/gzipmember.js';
6
+ import { readTarEntryData, TarReader } from '../readers/tar.js';
7
+ import { parseAlpinePackageInfo } from './pkginfo.js';
8
+ const PKGINFO = '.PKGINFO';
9
+ /**
10
+ * Reads an apk v2 package (concatenated gzip members: usually the signature,
11
+ * the control segment holding `.PKGINFO`, and the data) into a record, as
12
+ * Gitea 28.2.0's `ParsePackage` does (`modules/packages/alpine/metadata.go:77-134`):
13
+ * - gzip members are read one at a time; the first member whose tar holds an
14
+ * entry named exactly `.PKGINFO` is the control segment. Unsigned packages
15
+ * (no signature member) are accepted;
16
+ * - `digests.controlSha1` is the SHA-1 of exactly that member's bytes (the
17
+ * APKINDEX `C:` value is `Q1` plus its base64);
18
+ * - the rest of the input is hashed, never decompressed;
19
+ * - the record's `fileName` is Gitea's `{name}-{version}.apk`.
20
+ *
21
+ * Each member read before the control segment is buffered and bounded by
22
+ * `maxMetadataBytes` (member bytes) and `maxDecompressedMetadataBytes` (its
23
+ * tar). An apk v3 (ADB) package is `unsupported-package-format`, as Gitea
24
+ * refuses it too. On failure the reader stops pulling and returns no record.
25
+ */
26
+ export async function readAlpinePackage(sourceArg, limitsArg) {
27
+ const limits = resolveLinuxPackageLimits(limitsArg);
28
+ const input = new PackageByteSource(sourceArg, limits.maxPackageBytes);
29
+ const head = await readUpTo(input, 3);
30
+ if (head.length === 0) {
31
+ throw truncated('apk package');
32
+ }
33
+ if (head.length === 3 && head[0] === 0x41 && head[1] === 0x44 && head[2] === 0x42) {
34
+ throw new LinuxRepoError('unsupported-package-format', 'apk v3 (ADB) packages are not supported', {
35
+ field: 'apk package',
36
+ });
37
+ }
38
+ input.unread(head);
39
+ for (;;) {
40
+ const member = await readGzipMember(input, {
41
+ maxMemberBytes: limits.maxMetadataBytes,
42
+ memberLimit: 'maxMetadataBytes',
43
+ maxOutputBytes: limits.maxDecompressedMetadataBytes,
44
+ outputLimit: 'maxDecompressedMetadataBytes',
45
+ maxHeaderBytes: limits.maxHeaderBytes,
46
+ });
47
+ if (member === null) {
48
+ throw new LinuxRepoError('missing-field', 'the package has no .PKGINFO', { field: PKGINFO });
49
+ }
50
+ const tar = new TarReader(new BufferReader(member.output), {
51
+ maxEntries: limits.maxEntries,
52
+ maxHeaderBytes: limits.maxHeaderBytes,
53
+ });
54
+ for (let entry = await tar.next(); entry !== null; entry = await tar.next()) {
55
+ if (entry.name !== PKGINFO) {
56
+ continue;
57
+ }
58
+ // Gitea stops at the first .PKGINFO and ignores the rest of the member's tar
59
+ const pkginfo = await readTarEntryData(entry, limits.maxDecompressedMetadataBytes, 'maxDecompressedMetadataBytes');
60
+ const info = parseAlpinePackageInfo(pkginfo, limits);
61
+ await input.drain();
62
+ const digests = input.digests();
63
+ return {
64
+ format: 'alpine',
65
+ name: info.name,
66
+ version: info.version,
67
+ architecture: info.architecture,
68
+ fileName: `${info.name}-${info.version}.apk`,
69
+ digests: { ...digests, controlSha1: member.memberSha1 },
70
+ metadata: {
71
+ description: info.description,
72
+ license: info.license,
73
+ projectUrl: info.projectUrl,
74
+ maintainer: info.maintainer,
75
+ packager: info.packager,
76
+ buildDate: info.buildDate,
77
+ installedSize: info.installedSize,
78
+ origin: info.origin,
79
+ commit: info.commit,
80
+ installIf: info.installIf,
81
+ provides: info.provides,
82
+ dependencies: info.dependencies,
83
+ providerPriority: info.providerPriority,
84
+ },
85
+ };
86
+ }
87
+ }
88
+ }
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVhZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvYWxwaW5lL3JlYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSx5QkFBeUIsRUFBNEIsTUFBTSxxQkFBcUIsQ0FBQztBQUUxRixPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzdELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDaEUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXRELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQztBQUUzQjs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsaUJBQWlCLENBQ3JDLFNBQW9DLEVBQ3BDLFNBQXdDO0lBRXhDLE1BQU0sTUFBTSxHQUFHLHlCQUF5QixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3BELE1BQU0sS0FBSyxHQUFHLElBQUksaUJBQWlCLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUV2RSxNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3RCLE1BQU0sU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsS0FB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
@@ -0,0 +1,41 @@
1
+ import type { IArchPackageRecord, ILinuxIndexFile } from '../shared/types.js';
2
+ import { type IOpenPgpSigner } from '../signing/signers.js';
3
+ /** One package of an Arch repository index. */
4
+ export interface IArchIndexEntry {
5
+ record: IArchPackageRecord;
6
+ /**
7
+ * The package's detached signature (the `.sig` file's bytes) as stored at
8
+ * upload time; written as `%PGPSIG%`. Without it the entry has no
9
+ * `%PGPSIG%` and pacman fetches `<file>.sig`. The builder never signs a package.
10
+ */
11
+ packageSignature?: Uint8Array;
12
+ }
13
+ /**
14
+ * Builds the Arch index files of one repository: for every architecture that
15
+ * has packages, the gzip tar `packages.db` and its detached signature, as
16
+ * Gitea 28.2.0 `buildPackagesIndex` builds them.
17
+ *
18
+ * - `any` packages also go into every other architecture's index.
19
+ * - Each index lists one version per package (Gitea's identity: the
20
+ * lower-cased name), the newest by pacman's version comparison; versions
21
+ * that compare equal are ordered by architecture (the index's own before
22
+ * `any`), then bytewise by version and file name, so input order never decides.
23
+ * - Entries are written sorted bytewise by `<name>-<version>`, each as
24
+ * `<name>-<version>/files` then `<name>-<version>/desc`.
25
+ * - Only the index is signed (binary detached signature over the gzip bytes).
26
+ *
27
+ * Paths are `<repository>/<architecture>/packages.db` and `packages.db.sig`
28
+ * (no repository prefix when `repository` is `''`), without aliases: the
29
+ * request names Gitea maps onto them (`<repo>.db`, `.files`, the `any`
30
+ * fallback) are the consumer's route, documented in the readme.
31
+ */
32
+ export declare function buildArchIndex(inputArg: {
33
+ repository: string;
34
+ entries: IArchIndexEntry[];
35
+ signer: IOpenPgpSigner;
36
+ timestamp: Date;
37
+ }): Promise<ILinuxIndexFile[]>;
38
+ /** The `desc` member of one entry (`repository.go:353-379`). */
39
+ export declare function renderArchDesc(entryArg: IArchIndexEntry): string;
40
+ /** The `files` member of one entry (`repository.go:346-350`). */
41
+ export declare function renderArchFiles(recordArg: IArchPackageRecord): string;
@@ -0,0 +1,234 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { isIndexableArchitecture } from '../shared/architecture.js';
3
+ import { LinuxRepoError } from '../shared/errors.js';
4
+ import { assertBytes, assertSegmentName, assertTimestamp, hasControlCharacter } from '../shared/validation.js';
5
+ import { createDetachedBinarySignature } from '../signing/openpgpframing.js';
6
+ import { singleChunk } from '../signing/signers.js';
7
+ import { writeGoTar } from '../writers/gotar.js';
8
+ import { ARCH_NAME_PATTERN, ARCH_VERSION_PATTERN } from './reader.js';
9
+ import { compareArchVersions } from './vercmp.js';
10
+ /** Gitea's stored name of the index archive (`services/packages/arch/repository.go:37`). */
11
+ const INDEX_ARCHIVE_NAME = 'packages.db';
12
+ const ANY_ARCHITECTURE = 'any';
13
+ /** `int64(os.ModePerm)` (`repository.go:393`). */
14
+ const ENTRY_MODE = 0o777;
15
+ /**
16
+ * Builds the Arch index files of one repository: for every architecture that
17
+ * has packages, the gzip tar `packages.db` and its detached signature, as
18
+ * Gitea 28.2.0 `buildPackagesIndex` builds them.
19
+ *
20
+ * - `any` packages also go into every other architecture's index.
21
+ * - Each index lists one version per package (Gitea's identity: the
22
+ * lower-cased name), the newest by pacman's version comparison; versions
23
+ * that compare equal are ordered by architecture (the index's own before
24
+ * `any`), then bytewise by version and file name, so input order never decides.
25
+ * - Entries are written sorted bytewise by `<name>-<version>`, each as
26
+ * `<name>-<version>/files` then `<name>-<version>/desc`.
27
+ * - Only the index is signed (binary detached signature over the gzip bytes).
28
+ *
29
+ * Paths are `<repository>/<architecture>/packages.db` and `packages.db.sig`
30
+ * (no repository prefix when `repository` is `''`), without aliases: the
31
+ * request names Gitea maps onto them (`<repo>.db`, `.files`, the `any`
32
+ * fallback) are the consumer's route, documented in the readme.
33
+ */
34
+ export async function buildArchIndex(inputArg) {
35
+ if (inputArg === null || typeof inputArg !== 'object') {
36
+ throw new LinuxRepoError('invalid-input', 'input must be an object', { field: 'input' });
37
+ }
38
+ assertRepository(inputArg.repository);
39
+ assertTimestamp(inputArg.timestamp);
40
+ if (inputArg.signer === null || typeof inputArg.signer !== 'object' || typeof inputArg.signer.signBinary !== 'function') {
41
+ throw new LinuxRepoError('invalid-input', 'signer must be an IOpenPgpSigner', { field: 'signer' });
42
+ }
43
+ if (!Array.isArray(inputArg.entries)) {
44
+ throw new LinuxRepoError('invalid-input', 'entries must be an array', { field: 'entries' });
45
+ }
46
+ const fileNames = new Set();
47
+ for (const entry of inputArg.entries) {
48
+ assertEntry(entry);
49
+ if (fileNames.has(entry.record.fileName)) {
50
+ throw new LinuxRepoError('invalid-input', `duplicate package file ${entry.record.fileName}`, {
51
+ field: 'entries',
52
+ value: entry.record.fileName,
53
+ });
54
+ }
55
+ fileNames.add(entry.record.fileName);
56
+ }
57
+ if (inputArg.entries.length === 0) {
58
+ return [];
59
+ }
60
+ const architectures = [...new Set(inputArg.entries.map((entry) => entry.record.architecture))].sort(compareText);
61
+ const files = [];
62
+ for (const architecture of architectures) {
63
+ const candidates = inputArg.entries.filter((entry) => entry.record.architecture === architecture ||
64
+ (architecture !== ANY_ARCHITECTURE && entry.record.architecture === ANY_ARCHITECTURE));
65
+ const selected = selectLatest(candidates, architecture);
66
+ const tarFiles = selected.flatMap((entry) => {
67
+ const directory = `${entry.record.name}-${entry.record.version}`;
68
+ return [
69
+ { name: `${directory}/files`, mode: ENTRY_MODE, data: encodeText(renderArchFiles(entry.record)) },
70
+ { name: `${directory}/desc`, mode: ENTRY_MODE, data: encodeText(renderArchDesc(entry)) },
71
+ ];
72
+ });
73
+ const archive = toUint8Array(plugins.zlib.gzipSync(writeGoTar(tarFiles)));
74
+ const signature = await createDetachedBinarySignature({
75
+ data: singleChunk(archive),
76
+ signer: inputArg.signer,
77
+ timestamp: inputArg.timestamp,
78
+ });
79
+ const directory = inputArg.repository === '' ? architecture : `${inputArg.repository}/${architecture}`;
80
+ files.push(indexFile(`${directory}/${INDEX_ARCHIVE_NAME}`, archive, 'application/gzip'), indexFile(`${directory}/${INDEX_ARCHIVE_NAME}.sig`, signature, 'application/pgp-signature'));
81
+ }
82
+ return files.sort((a, b) => compareText(a.path, b.path));
83
+ }
84
+ /** The `desc` member of one entry (`repository.go:353-379`). */
85
+ export function renderArchDesc(entryArg) {
86
+ const record = entryArg.record;
87
+ const metadata = record.metadata;
88
+ const signature = entryArg.packageSignature === undefined ? '' : toBuffer(entryArg.packageSignature).toString('base64');
89
+ return renderFields([
90
+ ['FILENAME', record.fileName],
91
+ ['MD5SUM', record.digests.md5],
92
+ ['SHA256SUM', record.digests.sha256],
93
+ ['PGPSIG', signature],
94
+ ['CSIZE', String(record.digests.size)],
95
+ ['ISIZE', String(metadata.installedSize)],
96
+ ['NAME', record.name],
97
+ ['BASE', metadata.base],
98
+ ['ARCH', record.architecture],
99
+ ['VERSION', record.version],
100
+ ['DESC', metadata.description],
101
+ ['URL', metadata.projectUrl],
102
+ ['LICENSE', joinFields(metadata.licenses)],
103
+ ['GROUPS', joinFields(metadata.groups)],
104
+ ['BUILDDATE', String(metadata.buildDate)],
105
+ ['PACKAGER', metadata.packager],
106
+ ['PROVIDES', joinFields(metadata.provides)],
107
+ ['REPLACES', joinFields(metadata.replaces)],
108
+ ['CONFLICTS', joinFields(metadata.conflicts)],
109
+ ['DEPENDS', joinFields(metadata.depends)],
110
+ ['OPTDEPENDS', joinFields(metadata.optDepends)],
111
+ ['MAKEDEPENDS', joinFields(metadata.makeDepends)],
112
+ ['CHECKDEPENDS', joinFields(metadata.checkDepends)],
113
+ ]);
114
+ }
115
+ /** The `files` member of one entry (`repository.go:346-350`). */
116
+ export function renderArchFiles(recordArg) {
117
+ return renderFields([['FILES', joinFields(recordArg.metadata.files)]]);
118
+ }
119
+ /** `writeFields`: `%KEY%\nvalue\n\n` per non-empty value. */
120
+ function renderFields(fieldsArg) {
121
+ let text = '';
122
+ for (const [key, value] of fieldsArg) {
123
+ if (value !== '') {
124
+ text += `%${key}%\n${value}\n\n`;
125
+ }
126
+ }
127
+ return text;
128
+ }
129
+ /** `joinFields`: LF-joined, dropping values that contain CR or LF (they would forge index lines). */
130
+ function joinFields(valuesArg) {
131
+ return valuesArg.filter((value) => !/[\n\r]/.test(value)).join('\n');
132
+ }
133
+ function selectLatest(entriesArg, architectureArg) {
134
+ const latest = new Map();
135
+ for (const entry of entriesArg) {
136
+ const key = entry.record.name.toLowerCase();
137
+ const current = latest.get(key);
138
+ if (current === undefined || isPreferred(entry, current, architectureArg)) {
139
+ latest.set(key, entry);
140
+ }
141
+ }
142
+ return [...latest.values()].sort((a, b) => compareText(`${a.record.name}-${a.record.version}`, `${b.record.name}-${b.record.version}`));
143
+ }
144
+ /** True when `candidateArg` wins over `currentArg`: newer by alpm, then the tie order. */
145
+ function isPreferred(candidateArg, currentArg, architectureArg) {
146
+ const byVersion = compareArchVersions(candidateArg.record.version, currentArg.record.version);
147
+ if (byVersion !== 0) {
148
+ return byVersion > 0;
149
+ }
150
+ const ownArchitecture = (entryArg) => (entryArg.record.architecture === architectureArg ? 0 : 1);
151
+ const byArchitecture = ownArchitecture(candidateArg) - ownArchitecture(currentArg);
152
+ if (byArchitecture !== 0) {
153
+ return byArchitecture < 0;
154
+ }
155
+ const byVersionText = compareText(candidateArg.record.version, currentArg.record.version);
156
+ if (byVersionText !== 0) {
157
+ return byVersionText < 0;
158
+ }
159
+ return compareText(candidateArg.record.fileName, currentArg.record.fileName) < 0;
160
+ }
161
+ function indexFile(pathArg, bytesArg, mediaTypeArg) {
162
+ return {
163
+ path: pathArg,
164
+ bytes: bytesArg,
165
+ sha256: plugins.crypto.createHash('sha256').update(bytesArg).digest('hex'),
166
+ mediaType: mediaTypeArg,
167
+ stage: 'pointer',
168
+ aliases: [],
169
+ };
170
+ }
171
+ /** `''`, or `/`-separated segments that are non-empty, not `.` or `..`, and free of control characters. */
172
+ function assertRepository(valueArg) {
173
+ if (typeof valueArg !== 'string') {
174
+ throw new LinuxRepoError('invalid-input', 'repository must be a string', { field: 'repository' });
175
+ }
176
+ if (valueArg === '') {
177
+ return;
178
+ }
179
+ for (const segment of valueArg.split('/')) {
180
+ if (segment === '' || segment === '.' || segment === '..' || hasControlCharacter(segment)) {
181
+ throw new LinuxRepoError('invalid-input', 'repository segments must be non-empty, not "." or "..", and free of control characters', { field: 'repository' });
182
+ }
183
+ }
184
+ }
185
+ /**
186
+ * The record values that become index paths and lines must be what the
187
+ * reader produces: Gitea's name and version patterns, an indexable
188
+ * architecture, a file name that is one path segment.
189
+ */
190
+ function assertEntry(entryArg) {
191
+ if (entryArg === null || typeof entryArg !== 'object') {
192
+ throw new LinuxRepoError('invalid-input', 'each entry must be an object', { field: 'entries' });
193
+ }
194
+ const entry = entryArg;
195
+ const record = entry.record;
196
+ if (record === null || typeof record !== 'object' || record.format !== 'arch') {
197
+ throw new LinuxRepoError('invalid-input', 'each entry needs an Arch package record', { field: 'entries' });
198
+ }
199
+ if (typeof record.fileName !== 'string') {
200
+ throw new LinuxRepoError('invalid-input', 'record.fileName must be a string', { field: 'record.fileName' });
201
+ }
202
+ if (typeof record.name !== 'string' || !ARCH_NAME_PATTERN.test(record.name)) {
203
+ throw new LinuxRepoError('invalid-input', `package ${record.fileName} has an invalid name`, {
204
+ field: 'record.name',
205
+ value: record.fileName,
206
+ });
207
+ }
208
+ if (typeof record.version !== 'string' || !ARCH_VERSION_PATTERN.test(record.version)) {
209
+ throw new LinuxRepoError('invalid-input', `package ${record.fileName} has an invalid version`, {
210
+ field: 'record.version',
211
+ value: record.fileName,
212
+ });
213
+ }
214
+ if (!isIndexableArchitecture(record.architecture)) {
215
+ throw new LinuxRepoError('invalid-input', `package ${record.fileName} has an architecture that cannot name an index path`, { field: 'record.architecture', value: record.fileName });
216
+ }
217
+ assertSegmentName(record.fileName, 'record.fileName');
218
+ if (entry.packageSignature !== undefined) {
219
+ assertBytes(entry.packageSignature, 'packageSignature');
220
+ }
221
+ }
222
+ function compareText(aArg, bArg) {
223
+ return Buffer.compare(Buffer.from(aArg, 'utf8'), Buffer.from(bArg, 'utf8'));
224
+ }
225
+ function encodeText(textArg) {
226
+ return new TextEncoder().encode(textArg);
227
+ }
228
+ function toBuffer(bytesArg) {
229
+ return Buffer.from(bytesArg.buffer, bytesArg.byteOffset, bytesArg.byteLength);
230
+ }
231
+ function toUint8Array(bufferArg) {
232
+ return new Uint8Array(bufferArg.buffer, bufferArg.byteOffset, bufferArg.byteLength);
233
+ }
234
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2FyY2gvYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFckQsT0FBTyxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMvRyxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM3RSxPQUFPLEVBQUUsV0FBVyxFQUF1QixNQUFNLHVCQUF1QixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDdEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBYWxELDRGQUE0RjtBQUM1RixNQUFNLGtCQUFrQixHQUFHLGFBQWEsQ0FBQztBQUN6QyxNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQztBQUMvQixrREFBa0Q7QUFDbEQsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDO0FBRXpCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FBQyxRQUtwQztJQUNDLElBQUksUUFBUSxLQUFLLElBQUksSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUN0RCxNQUFNLElBQUksY0FBYyxDQUFDLGVBQWUsRUFBRSx5QkFBeUIsRUFBRSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFDRCxnQkFBZ0Is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
@@ -0,0 +1,16 @@
1
+ import { type ILinuxPackageLimits } from '../shared/limits.js';
2
+ import type { IArchPackageRecord } from '../shared/types.js';
3
+ /** Gitea `namePattern` (`modules/packages/arch/metadata.go:47`). */
4
+ export declare const ARCH_NAME_PATTERN: RegExp;
5
+ /** Gitea `versionPattern` (`metadata.go:49`); Go's `\d` and `\w` are ASCII, as in a JS RegExp without `u`. */
6
+ export declare const ARCH_VERSION_PATTERN: RegExp;
7
+ /**
8
+ * Reads an Arch package (`.pkg.tar.zst`, `.xz` or `.gz`, chosen by magic as
9
+ * Gitea 28.2.0 does) into a record: `.PKGINFO` metadata and the file list,
10
+ * derived exactly as Gitea's `arch.ParsePackage`, plus the size and digests of
11
+ * the whole file. The whole payload is decompressed (bounded by
12
+ * `maxPayloadBytes`) because the file list needs every tar entry, and to the
13
+ * end of the compressed stream, so a cut or corrupt container is refused
14
+ * even where it lies past the tar end marker (Go stops reading there).
15
+ */
16
+ export declare function readArchPackage(sourceArg: AsyncIterable<Uint8Array>, limitsArg?: Partial<ILinuxPackageLimits>): Promise<IArchPackageRecord>;