@push.rocks/smartlinuxrepo 0.0.0-stage → 1.0.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.
- package/.smartconfig.json +65 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/alpine/apkindex.d.ts +39 -0
- package/dist_ts/alpine/apkindex.js +211 -0
- package/dist_ts/alpine/pkginfo.d.ts +45 -0
- package/dist_ts/alpine/pkginfo.js +159 -0
- package/dist_ts/alpine/reader.d.ts +20 -0
- package/dist_ts/alpine/reader.js +89 -0
- package/dist_ts/arch/builder.d.ts +41 -0
- package/dist_ts/arch/builder.js +234 -0
- package/dist_ts/arch/reader.d.ts +16 -0
- package/dist_ts/arch/reader.js +271 -0
- package/dist_ts/arch/signer.d.ts +21 -0
- package/dist_ts/arch/signer.js +66 -0
- package/dist_ts/arch/vercmp.d.ts +12 -0
- package/dist_ts/arch/vercmp.js +170 -0
- package/dist_ts/debian/control.d.ts +22 -0
- package/dist_ts/debian/control.js +137 -0
- package/dist_ts/debian/gostring.d.ts +26 -0
- package/dist_ts/debian/gostring.js +145 -0
- package/dist_ts/debian/indexbuilder.d.ts +47 -0
- package/dist_ts/debian/indexbuilder.js +299 -0
- package/dist_ts/debian/mailaddress.d.ts +12 -0
- package/dist_ts/debian/mailaddress.js +736 -0
- package/dist_ts/debian/reader.d.ts +30 -0
- package/dist_ts/debian/reader.js +110 -0
- package/dist_ts/index.d.ts +23 -0
- package/dist_ts/index.js +18 -0
- package/dist_ts/plugins.d.ts +8 -0
- package/dist_ts/plugins.js +11 -0
- package/dist_ts/readers/ar.d.ts +31 -0
- package/dist_ts/readers/ar.js +87 -0
- package/dist_ts/readers/bytes.d.ts +58 -0
- package/dist_ts/readers/bytes.js +147 -0
- package/dist_ts/readers/bytesource.d.ts +40 -0
- package/dist_ts/readers/bytesource.js +154 -0
- package/dist_ts/readers/decompress.d.ts +43 -0
- package/dist_ts/readers/decompress.js +269 -0
- package/dist_ts/readers/gzipmember.d.ts +32 -0
- package/dist_ts/readers/gzipmember.js +176 -0
- package/dist_ts/readers/tar.d.ts +85 -0
- package/dist_ts/readers/tar.js +731 -0
- package/dist_ts/readers/text.d.ts +16 -0
- package/dist_ts/readers/text.js +96 -0
- package/dist_ts/rpm/builder.d.ts +28 -0
- package/dist_ts/rpm/builder.js +208 -0
- package/dist_ts/rpm/header.d.ts +138 -0
- package/dist_ts/rpm/header.js +546 -0
- package/dist_ts/rpm/reader.d.ts +20 -0
- package/dist_ts/rpm/reader.js +306 -0
- package/dist_ts/rpm/repoconfig.d.ts +15 -0
- package/dist_ts/rpm/repoconfig.js +38 -0
- package/dist_ts/rpm/repodata.d.ts +44 -0
- package/dist_ts/rpm/repodata.js +148 -0
- package/dist_ts/rpm/sign.d.ts +30 -0
- package/dist_ts/rpm/sign.js +183 -0
- package/dist_ts/rpm/updates.d.ts +38 -0
- package/dist_ts/rpm/updates.js +265 -0
- package/dist_ts/rpm/xml.d.ts +18 -0
- package/dist_ts/rpm/xml.js +90 -0
- package/dist_ts/shared/architecture.d.ts +8 -0
- package/dist_ts/shared/architecture.js +17 -0
- package/dist_ts/shared/errors.d.ts +38 -0
- package/dist_ts/shared/errors.js +22 -0
- package/dist_ts/shared/gopath.d.ts +13 -0
- package/dist_ts/shared/gopath.js +53 -0
- package/dist_ts/shared/gostrings.d.ts +14 -0
- package/dist_ts/shared/gostrings.js +29 -0
- package/dist_ts/shared/limits.d.ts +47 -0
- package/dist_ts/shared/limits.js +57 -0
- package/dist_ts/shared/types.d.ts +213 -0
- package/dist_ts/shared/types.js +13 -0
- package/dist_ts/shared/url.d.ts +18 -0
- package/dist_ts/shared/url.js +371 -0
- package/dist_ts/shared/validation.d.ts +21 -0
- package/dist_ts/shared/validation.js +58 -0
- package/dist_ts/signing/keys.d.ts +36 -0
- package/dist_ts/signing/keys.js +89 -0
- package/dist_ts/signing/openpgpframing.d.ts +33 -0
- package/dist_ts/signing/openpgpframing.js +93 -0
- package/dist_ts/signing/signers.d.ts +63 -0
- package/dist_ts/signing/signers.js +248 -0
- package/dist_ts/writers/gotar.d.ts +43 -0
- package/dist_ts/writers/gotar.js +218 -0
- package/license.md +19 -0
- package/package.json +56 -3
- package/readme.md +176 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/alpine/apkindex.ts +241 -0
- package/ts/alpine/pkginfo.ts +183 -0
- package/ts/alpine/reader.ts +96 -0
- package/ts/arch/builder.ts +283 -0
- package/ts/arch/reader.ts +307 -0
- package/ts/arch/signer.ts +70 -0
- package/ts/arch/vercmp.ts +188 -0
- package/ts/debian/control.ts +150 -0
- package/ts/debian/gostring.ts +150 -0
- package/ts/debian/indexbuilder.ts +355 -0
- package/ts/debian/mailaddress.ts +754 -0
- package/ts/debian/reader.ts +126 -0
- package/ts/index.ts +46 -0
- package/ts/plugins.ts +13 -0
- package/ts/readers/ar.ts +102 -0
- package/ts/readers/bytes.ts +182 -0
- package/ts/readers/bytesource.ts +164 -0
- package/ts/readers/decompress.ts +332 -0
- package/ts/readers/gzipmember.ts +209 -0
- package/ts/readers/tar.ts +835 -0
- package/ts/readers/text.ts +91 -0
- package/ts/rpm/builder.ts +253 -0
- package/ts/rpm/header.ts +628 -0
- package/ts/rpm/reader.ts +317 -0
- package/ts/rpm/repoconfig.ts +45 -0
- package/ts/rpm/repodata.ts +219 -0
- package/ts/rpm/sign.ts +200 -0
- package/ts/rpm/updates.ts +314 -0
- package/ts/rpm/xml.ts +101 -0
- package/ts/shared/architecture.ts +16 -0
- package/ts/shared/errors.ts +78 -0
- package/ts/shared/gopath.ts +54 -0
- package/ts/shared/gostrings.ts +31 -0
- package/ts/shared/limits.ts +93 -0
- package/ts/shared/types.ts +251 -0
- package/ts/shared/url.ts +387 -0
- package/ts/shared/validation.ts +71 -0
- package/ts/signing/keys.ts +110 -0
- package/ts/signing/openpgpframing.ts +115 -0
- package/ts/signing/signers.ts +315 -0
- package/ts/writers/gotar.ts +256 -0
- package/README.md +0 -3
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { LinuxRepoError, limitExceeded } from '../shared/errors.js';
|
|
2
|
+
import { goPathBase, goPathClean } from '../shared/gopath.js';
|
|
3
|
+
import { resolveLinuxPackageLimits } from '../shared/limits.js';
|
|
4
|
+
import { isValidUrl } from '../shared/url.js';
|
|
5
|
+
import { readUpTo, skipToEnd } from '../readers/bytes.js';
|
|
6
|
+
import { PackageByteSource } from '../readers/bytesource.js';
|
|
7
|
+
import { withDecompressingReader } from '../readers/decompress.js';
|
|
8
|
+
import { readTarEntryData, TarReader } from '../readers/tar.js';
|
|
9
|
+
import { decodeGoUtf8 } from '../readers/text.js';
|
|
10
|
+
import { goParseInt64, goTrimSpace } from '../shared/gostrings.js';
|
|
11
|
+
/** Gitea `namePattern` (`modules/packages/arch/metadata.go:47`). */
|
|
12
|
+
export const ARCH_NAME_PATTERN = /^[a-zA-Z0-9@._+-]+$/;
|
|
13
|
+
/** Gitea `versionPattern` (`metadata.go:49`); Go's `\d` and `\w` are ASCII, as in a JS RegExp without `u`. */
|
|
14
|
+
export const ARCH_VERSION_PATTERN = /^(?:\d:)?[\w.+~]+(?:-[-\w.+~]+)?$/;
|
|
15
|
+
const MAGIC_BYTES = 10;
|
|
16
|
+
const GO_C_ISDIR = 0o40000;
|
|
17
|
+
/**
|
|
18
|
+
* Reads an Arch package (`.pkg.tar.zst`, `.xz` or `.gz`, chosen by magic as
|
|
19
|
+
* Gitea 28.2.0 does) into a record: `.PKGINFO` metadata and the file list,
|
|
20
|
+
* derived exactly as Gitea's `arch.ParsePackage`, plus the size and digests of
|
|
21
|
+
* the whole file. The whole payload is decompressed (bounded by
|
|
22
|
+
* `maxPayloadBytes`) because the file list needs every tar entry, and to the
|
|
23
|
+
* end of the compressed stream, so a cut or corrupt container is refused
|
|
24
|
+
* even where it lies past the tar end marker (Go stops reading there).
|
|
25
|
+
*/
|
|
26
|
+
export async function readArchPackage(sourceArg, limitsArg) {
|
|
27
|
+
const limits = resolveLinuxPackageLimits(limitsArg);
|
|
28
|
+
const source = new PackageByteSource(sourceArg, limits.maxPackageBytes);
|
|
29
|
+
const magic = await readUpTo(source, MAGIC_BYTES);
|
|
30
|
+
source.unread(magic);
|
|
31
|
+
const container = detectContainer(magic);
|
|
32
|
+
if (container === null) {
|
|
33
|
+
throw new LinuxRepoError('unsupported-compression', 'not a zst, xz or gz compressed Arch package', {
|
|
34
|
+
field: 'compression',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const walked = await withDecompressingReader(source, container.decoder, { maxOutputBytes: limits.maxPayloadBytes, outputLimit: 'maxPayloadBytes' }, async (payloadArg) => {
|
|
38
|
+
const result = await walkPayload(new TarReader(payloadArg, { maxEntries: limits.maxEntries, maxHeaderBytes: limits.maxHeaderBytes }), limits);
|
|
39
|
+
// Go stops at the tar end marker; the codec decodes the rest of the
|
|
40
|
+
// stream as well, so a package cut or corrupted after the marker fails
|
|
41
|
+
// loudly instead of being stored and signed
|
|
42
|
+
await skipToEnd(payloadArg);
|
|
43
|
+
return result;
|
|
44
|
+
});
|
|
45
|
+
if (walked.info === null) {
|
|
46
|
+
throw new LinuxRepoError('missing-field', '.PKGINFO file is missing', { field: '.PKGINFO' });
|
|
47
|
+
}
|
|
48
|
+
await source.drain();
|
|
49
|
+
const info = walked.info;
|
|
50
|
+
return {
|
|
51
|
+
format: 'arch',
|
|
52
|
+
name: info.name,
|
|
53
|
+
version: info.version,
|
|
54
|
+
architecture: info.architecture,
|
|
55
|
+
fileName: `${info.name}-${info.version}-${info.architecture}.pkg.tar.${container.extension}`,
|
|
56
|
+
digests: source.digests(),
|
|
57
|
+
metadata: {
|
|
58
|
+
compression: container.extension,
|
|
59
|
+
...info.metadata,
|
|
60
|
+
files: walked.files,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function detectContainer(magicArg) {
|
|
65
|
+
const startsWith = (bytesArg) => bytesArg.every((byte, index) => magicArg[index] === byte);
|
|
66
|
+
if (startsWith([0x28, 0xb5, 0x2f, 0xfd])) {
|
|
67
|
+
return { extension: 'zst', decoder: 'zstd' };
|
|
68
|
+
}
|
|
69
|
+
if (startsWith([0xfd, 0x37, 0x7a, 0x58, 0x5a])) {
|
|
70
|
+
return { extension: 'xz', decoder: 'xz' };
|
|
71
|
+
}
|
|
72
|
+
if (startsWith([0x1f, 0x8b])) {
|
|
73
|
+
return { extension: 'gz', decoder: 'gzip' };
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Gitea's tar walk (`metadata.go:135-163`): regular entries only; a regular
|
|
79
|
+
* entry whose base name is `.PKGINFO` is parsed (a later one replaces an
|
|
80
|
+
* earlier one); every other regular entry whose base name does not start with
|
|
81
|
+
* `.` and whose name holds no CR or LF joins the file list, in archive order.
|
|
82
|
+
*/
|
|
83
|
+
async function walkPayload(tarArg, limitsArg) {
|
|
84
|
+
let info = null;
|
|
85
|
+
const files = [];
|
|
86
|
+
let fileBytes = 0;
|
|
87
|
+
for (;;) {
|
|
88
|
+
const entry = await tarArg.next();
|
|
89
|
+
if (entry === null) {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
if (entry.typeflag !== '0') {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const base = fileInfoName(entry);
|
|
96
|
+
if (base === '.PKGINFO') {
|
|
97
|
+
const data = await readTarEntryData(entry, limitsArg.maxDecompressedMetadataBytes, 'maxDecompressedMetadataBytes');
|
|
98
|
+
info = parsePackageInfo(data, limitsArg);
|
|
99
|
+
}
|
|
100
|
+
else if (!base.startsWith('.')) {
|
|
101
|
+
if (/[\n\r]/.test(entry.name)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
// Gitea's BoundedFileList: entry count and total name bytes
|
|
105
|
+
const nameBytes = Buffer.byteLength(entry.name, 'utf8');
|
|
106
|
+
if (files.length >= limitsArg.maxEntries) {
|
|
107
|
+
throw limitExceeded('maxEntries', limitsArg.maxEntries, 'Arch file list');
|
|
108
|
+
}
|
|
109
|
+
if (fileBytes + nameBytes > limitsArg.maxFileListBytes) {
|
|
110
|
+
throw limitExceeded('maxFileListBytes', limitsArg.maxFileListBytes, 'Arch file list');
|
|
111
|
+
}
|
|
112
|
+
fileBytes += nameBytes;
|
|
113
|
+
files.push(entry.name);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return { info, files };
|
|
117
|
+
}
|
|
118
|
+
/** Go `tar.Header.FileInfo().Name()` for a regular entry: `path.Base`, after `path.Clean` when the mode marks a directory. */
|
|
119
|
+
function fileInfoName(entryArg) {
|
|
120
|
+
const typeBits = (Number(BigInt.asUintN(32, entryArg.mode)) & ~0o7777) >>> 0;
|
|
121
|
+
if (typeBits === GO_C_ISDIR) {
|
|
122
|
+
return goPathBase(goPathClean(entryArg.name));
|
|
123
|
+
}
|
|
124
|
+
return goPathBase(entryArg.name);
|
|
125
|
+
}
|
|
126
|
+
const MULTI_VALUE_KEYS = {
|
|
127
|
+
license: 'licenses',
|
|
128
|
+
provides: 'provides',
|
|
129
|
+
depend: 'depends',
|
|
130
|
+
replaces: 'replaces',
|
|
131
|
+
optdepend: 'optDepends',
|
|
132
|
+
makedepend: 'makeDepends',
|
|
133
|
+
checkdepend: 'checkDepends',
|
|
134
|
+
conflict: 'conflicts',
|
|
135
|
+
backup: 'backup',
|
|
136
|
+
group: 'groups',
|
|
137
|
+
xdata: 'xdata',
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Gitea's `ParsePackageInfo` (`metadata.go:178-267`): lines as Go's
|
|
141
|
+
* `bufio.ScanLines` splits them (a trailing CR dropped), `#` lines and lines
|
|
142
|
+
* without `=` skipped, key and value `strings.TrimSpace`d, single values last
|
|
143
|
+
* one wins, `builddate` and `size` parsed as int64 (an unparsable value
|
|
144
|
+
* refuses the package), then the name, version and architecture checks and
|
|
145
|
+
* the URL check. Lines are bounded by `maxHeaderBytes` (Gitea: 64 KiB) and
|
|
146
|
+
* each multi-valued key by `maxEntries`.
|
|
147
|
+
*/
|
|
148
|
+
function parsePackageInfo(dataArg, limitsArg) {
|
|
149
|
+
const info = {
|
|
150
|
+
name: '',
|
|
151
|
+
version: '',
|
|
152
|
+
architecture: '',
|
|
153
|
+
metadata: {
|
|
154
|
+
base: '',
|
|
155
|
+
description: '',
|
|
156
|
+
projectUrl: '',
|
|
157
|
+
licenses: [],
|
|
158
|
+
installedSize: 0,
|
|
159
|
+
buildDate: 0,
|
|
160
|
+
packager: '',
|
|
161
|
+
groups: [],
|
|
162
|
+
provides: [],
|
|
163
|
+
replaces: [],
|
|
164
|
+
depends: [],
|
|
165
|
+
optDepends: [],
|
|
166
|
+
makeDepends: [],
|
|
167
|
+
checkDepends: [],
|
|
168
|
+
conflicts: [],
|
|
169
|
+
xdata: [],
|
|
170
|
+
backup: [],
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
for (const rawLine of splitLines(dataArg, limitsArg.maxHeaderBytes)) {
|
|
174
|
+
const line = decodeGoUtf8(rawLine);
|
|
175
|
+
if (line.startsWith('#')) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const equals = line.indexOf('=');
|
|
179
|
+
if (equals < 0) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
const key = goTrimSpace(line.slice(0, equals));
|
|
183
|
+
const value = goTrimSpace(line.slice(equals + 1));
|
|
184
|
+
switch (key) {
|
|
185
|
+
case 'pkgname':
|
|
186
|
+
info.name = value;
|
|
187
|
+
break;
|
|
188
|
+
case 'pkgbase':
|
|
189
|
+
info.metadata.base = value;
|
|
190
|
+
break;
|
|
191
|
+
case 'pkgver':
|
|
192
|
+
info.version = value;
|
|
193
|
+
break;
|
|
194
|
+
case 'pkgdesc':
|
|
195
|
+
info.metadata.description = value;
|
|
196
|
+
break;
|
|
197
|
+
case 'url':
|
|
198
|
+
info.metadata.projectUrl = value;
|
|
199
|
+
break;
|
|
200
|
+
case 'packager':
|
|
201
|
+
info.metadata.packager = value;
|
|
202
|
+
break;
|
|
203
|
+
case 'arch':
|
|
204
|
+
info.architecture = value;
|
|
205
|
+
break;
|
|
206
|
+
case 'builddate':
|
|
207
|
+
info.metadata.buildDate = parseInteger(value, 'builddate');
|
|
208
|
+
break;
|
|
209
|
+
case 'size':
|
|
210
|
+
info.metadata.installedSize = parseInteger(value, 'size');
|
|
211
|
+
break;
|
|
212
|
+
default:
|
|
213
|
+
if (Object.hasOwn(MULTI_VALUE_KEYS, key)) {
|
|
214
|
+
const list = info.metadata[MULTI_VALUE_KEYS[key]];
|
|
215
|
+
if (list.length >= limitsArg.maxEntries) {
|
|
216
|
+
throw limitExceeded('maxEntries', limitsArg.maxEntries, `.PKGINFO ${key} values`);
|
|
217
|
+
}
|
|
218
|
+
list.push(value);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (!ARCH_NAME_PATTERN.test(info.name)) {
|
|
223
|
+
throw new LinuxRepoError('invalid-field', 'package name is invalid', { field: 'pkgname' });
|
|
224
|
+
}
|
|
225
|
+
if (!ARCH_VERSION_PATTERN.test(info.version)) {
|
|
226
|
+
throw new LinuxRepoError('invalid-field', 'package version is invalid', { field: 'pkgver' });
|
|
227
|
+
}
|
|
228
|
+
if (info.architecture === '') {
|
|
229
|
+
throw new LinuxRepoError('invalid-field', 'package architecture is invalid', { field: 'arch' });
|
|
230
|
+
}
|
|
231
|
+
if (!isValidUrl(info.metadata.projectUrl)) {
|
|
232
|
+
info.metadata.projectUrl = '';
|
|
233
|
+
}
|
|
234
|
+
return info;
|
|
235
|
+
}
|
|
236
|
+
/** int64 as Go parses it; values outside the safe integer range cannot live in a JSON record. */
|
|
237
|
+
function parseInteger(valueArg, fieldArg) {
|
|
238
|
+
const value = goParseInt64(valueArg);
|
|
239
|
+
if (value === null) {
|
|
240
|
+
throw new LinuxRepoError('invalid-field', `.PKGINFO ${fieldArg} is not an integer`, { field: fieldArg });
|
|
241
|
+
}
|
|
242
|
+
if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < BigInt(Number.MIN_SAFE_INTEGER)) {
|
|
243
|
+
throw new LinuxRepoError('invalid-field', `.PKGINFO ${fieldArg} is outside the safe integer range`, {
|
|
244
|
+
field: fieldArg,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return Number(value);
|
|
248
|
+
}
|
|
249
|
+
/** Go `bufio.ScanLines`: split at LF, drop one trailing CR, keep a final unterminated line when non-empty. */
|
|
250
|
+
function splitLines(dataArg, maxLineBytesArg) {
|
|
251
|
+
const lines = [];
|
|
252
|
+
let start = 0;
|
|
253
|
+
while (start < dataArg.length) {
|
|
254
|
+
let end = dataArg.indexOf(0x0a, start);
|
|
255
|
+
const terminated = end >= 0;
|
|
256
|
+
if (!terminated) {
|
|
257
|
+
end = dataArg.length;
|
|
258
|
+
}
|
|
259
|
+
if (end - start > maxLineBytesArg) {
|
|
260
|
+
throw limitExceeded('maxHeaderBytes', maxLineBytesArg, '.PKGINFO line');
|
|
261
|
+
}
|
|
262
|
+
let line = dataArg.subarray(start, end);
|
|
263
|
+
if (line.length > 0 && line[line.length - 1] === 0x0d) {
|
|
264
|
+
line = line.subarray(0, line.length - 1);
|
|
265
|
+
}
|
|
266
|
+
lines.push(line);
|
|
267
|
+
start = terminated ? end + 1 : end;
|
|
268
|
+
}
|
|
269
|
+
return lines;
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVhZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvYXJjaC9yZWFkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzlELE9BQU8sRUFBRSx5QkFBeUIsRUFBNEIsTUFBTSxxQkFBcUIsQ0FBQztBQUUxRixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsdUJBQXVCLEVBQTBCLE1BQU0sMEJBQTBCLENBQUM7QUFDM0YsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFNBQVMsRUFBa0IsTUFBTSxtQkFBbUIsQ0FBQztBQUNoRixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVuRSxvRUFBb0U7QUFDcEUsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcscUJBQXFCLENBQUM7QUFDdkQsOEdBQThHO0FBQzlHLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLG1DQUFtQyxDQUFDO0FBRXhFLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQztBQUN2QixNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUM7QUFTM0I7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGVBQWUsQ0FDbkMsU0FBb0MsRUFDcEMsU0FBd0M7SUFFeEMsTUFBTSxNQUFNLEdBQUcseUJBQXlCLENBQUMsU0FBUyxDQUFDLENBQUM7SUFD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
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ILinuxPackageLimits } from '../shared/limits.js';
|
|
2
|
+
import type { IOpenPgpSigner } from '../signing/signers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Signs an Arch package at upload time, as Gitea 28.2.0 signs every upload
|
|
5
|
+
* (`routers/api/packages/arch/arch.go:83`, `openpgp.DetachSign`): returns the
|
|
6
|
+
* `.sig` file, one binary detached signature packet over the package bytes.
|
|
7
|
+
* The package streams to the signer once, counted against `maxPackageBytes`
|
|
8
|
+
* of `limits` (pass the limits the package was read with); the codec keeps no
|
|
9
|
+
* copy, but the built-in OpenPGP signer still holds it in memory: openpgp.js
|
|
10
|
+
* buffers the whole document when detach-signing a stream.
|
|
11
|
+
* A failure of the package stream (the limit, or the caller's source error
|
|
12
|
+
* unchanged) wins over whatever the signer made of it. Pass the result as the index
|
|
13
|
+
* entry's `packageSignature`. Imported packages keep their stored signature
|
|
14
|
+
* and are never re-signed.
|
|
15
|
+
*/
|
|
16
|
+
export declare function signArchPackage(inputArg: {
|
|
17
|
+
source: AsyncIterable<Uint8Array>;
|
|
18
|
+
signer: IOpenPgpSigner;
|
|
19
|
+
timestamp: Date;
|
|
20
|
+
limits?: Partial<ILinuxPackageLimits>;
|
|
21
|
+
}): Promise<Uint8Array>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { LinuxRepoError } from '../shared/errors.js';
|
|
2
|
+
import { resolveLinuxPackageLimits } from '../shared/limits.js';
|
|
3
|
+
import { assertTimestamp } from '../shared/validation.js';
|
|
4
|
+
import { READ_CHUNK_BYTES } from '../readers/bytes.js';
|
|
5
|
+
import { PackageByteSource } from '../readers/bytesource.js';
|
|
6
|
+
import { createDetachedBinarySignature } from '../signing/openpgpframing.js';
|
|
7
|
+
/**
|
|
8
|
+
* Signs an Arch package at upload time, as Gitea 28.2.0 signs every upload
|
|
9
|
+
* (`routers/api/packages/arch/arch.go:83`, `openpgp.DetachSign`): returns the
|
|
10
|
+
* `.sig` file, one binary detached signature packet over the package bytes.
|
|
11
|
+
* The package streams to the signer once, counted against `maxPackageBytes`
|
|
12
|
+
* of `limits` (pass the limits the package was read with); the codec keeps no
|
|
13
|
+
* copy, but the built-in OpenPGP signer still holds it in memory: openpgp.js
|
|
14
|
+
* buffers the whole document when detach-signing a stream.
|
|
15
|
+
* A failure of the package stream (the limit, or the caller's source error
|
|
16
|
+
* unchanged) wins over whatever the signer made of it. Pass the result as the index
|
|
17
|
+
* entry's `packageSignature`. Imported packages keep their stored signature
|
|
18
|
+
* and are never re-signed.
|
|
19
|
+
*/
|
|
20
|
+
export async function signArchPackage(inputArg) {
|
|
21
|
+
if (inputArg === null || typeof inputArg !== 'object') {
|
|
22
|
+
throw new LinuxRepoError('invalid-input', 'input must be an object', { field: 'input' });
|
|
23
|
+
}
|
|
24
|
+
assertTimestamp(inputArg.timestamp);
|
|
25
|
+
if (inputArg.signer === null || typeof inputArg.signer !== 'object' || typeof inputArg.signer.signBinary !== 'function') {
|
|
26
|
+
throw new LinuxRepoError('invalid-input', 'signer must be an IOpenPgpSigner', { field: 'signer' });
|
|
27
|
+
}
|
|
28
|
+
const limits = resolveLinuxPackageLimits(inputArg.limits);
|
|
29
|
+
const source = new PackageByteSource(inputArg.source, limits.maxPackageBytes);
|
|
30
|
+
let ended = false;
|
|
31
|
+
let failure;
|
|
32
|
+
const chunks = async function* () {
|
|
33
|
+
for (;;) {
|
|
34
|
+
let chunk;
|
|
35
|
+
try {
|
|
36
|
+
chunk = await source.read(READ_CHUNK_BYTES);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
failure = { error };
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
if (chunk === null) {
|
|
43
|
+
ended = true;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
yield chunk;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
let packet;
|
|
50
|
+
try {
|
|
51
|
+
packet = await createDetachedBinarySignature({ data: chunks(), signer: inputArg.signer, timestamp: inputArg.timestamp });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw failure !== undefined ? failure.error : error;
|
|
55
|
+
}
|
|
56
|
+
if (failure !== undefined) {
|
|
57
|
+
throw failure.error;
|
|
58
|
+
}
|
|
59
|
+
if (!ended) {
|
|
60
|
+
throw new LinuxRepoError('signing-failed', 'the signer returned before reading the whole package', {
|
|
61
|
+
field: 'signer',
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return packet;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvYXJjaC9zaWduZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3JELE9BQU8sRUFBRSx5QkFBeUIsRUFBNEIsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDN0QsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFHN0U7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsUUFLckM7SUFDQyxJQUFJLFFBQVEsS0FBSyxJQUFJLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDdEQsTUFBTSxJQUFJLGNBQWMsQ0FBQyxlQUFlLEVBQUUseUJBQXlCLEVBQUUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUMzRixDQUFDO0lBQ0QsZUFBZSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNwQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssSUFBSSxJQUFJLE9BQU8sUUFBUSxDQUFDLE1BQU0sS0FBSyxRQUFRLElBQUksT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFDLFVBQVUsS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUN4SCxNQUFNLElBQUksY0FBYyxDQUFDLGVBQWUsRUFBRSxrQ0FBa0MsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ3JHLENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyx5QkFBeUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM5RSxJQUFJLEtBQUssR0FBRyxLQUFLLENBQUM7SUFDbEIsSUFBSSxPQUF1QyxDQUFDO0lBQzVDLE1BQU0sTUFBTSxHQUFHLEtBQUssU0FBUyxDQUFDO1FBQzVCLFNBQVMsQ0FBQztZQUNSLElBQUksS0FBd0IsQ0FBQztZQUM3QixJQUFJLENBQUM7Z0JBQ0gsS0FBSyxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQzlDLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLE9BQU8sR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDO2dCQUNwQixNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFDRCxJQUFJLEtBQUssS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDbkIsS0FBSyxHQUFHLElBQUksQ0FBQztnQkFDYixPQUFPO1lBQ1QsQ0FBQztZQUNELE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUMsQ0FBQztJQUNGLElBQUksTUFBa0IsQ0FBQztJQUN2QixJQUFJLENBQUM7UUFDSCxNQUFNLEdBQUcsTUFBTSw2QkFBNkIsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDM0gsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLE9BQU8sS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUN0RCxDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDMUIsTUFBTSxPQUFPLENBQUMsS0FBSyxDQUFDO0lBQ3RCLENBQUM7SUFDRCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDWCxNQUFNLElBQUksY0FBYyxDQUFDLGdCQUFnQixFQUFFLHNEQUFzRCxFQUFFO1lBQ2pHLEtBQUssRUFBRSxRQUFRO1NBQ2hCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIn0=
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pacman's version comparison: libalpm `alpm_pkg_vercmp` with `parseEVR` and
|
|
3
|
+
* `rpmvercmp` (`lib/libalpm/version.c`, read from pacman 6.0.2 and checked
|
|
4
|
+
* against pacman's `vercmp` tool in the Docker gate). Gitea 28.2.0 uses a
|
|
5
|
+
* simplified comparator (`services/packages/arch/vercmp.go`) that splits on
|
|
6
|
+
* `.` only and can pick what pacman sees as a downgrade; the codec follows
|
|
7
|
+
* alpm. Characters are classified as in the C locale.
|
|
8
|
+
*
|
|
9
|
+
* Returns 1 when `a` is newer, -1 when `b` is newer, 0 when pacman treats
|
|
10
|
+
* them as the same version.
|
|
11
|
+
*/
|
|
12
|
+
export declare function compareArchVersions(aArg: string, bArg: string): -1 | 0 | 1;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pacman's version comparison: libalpm `alpm_pkg_vercmp` with `parseEVR` and
|
|
3
|
+
* `rpmvercmp` (`lib/libalpm/version.c`, read from pacman 6.0.2 and checked
|
|
4
|
+
* against pacman's `vercmp` tool in the Docker gate). Gitea 28.2.0 uses a
|
|
5
|
+
* simplified comparator (`services/packages/arch/vercmp.go`) that splits on
|
|
6
|
+
* `.` only and can pick what pacman sees as a downgrade; the codec follows
|
|
7
|
+
* alpm. Characters are classified as in the C locale.
|
|
8
|
+
*
|
|
9
|
+
* Returns 1 when `a` is newer, -1 when `b` is newer, 0 when pacman treats
|
|
10
|
+
* them as the same version.
|
|
11
|
+
*/
|
|
12
|
+
export function compareArchVersions(aArg, bArg) {
|
|
13
|
+
if (aArg === bArg) {
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
const a = parseEvr(toBytes(aArg));
|
|
17
|
+
const b = parseEvr(toBytes(bArg));
|
|
18
|
+
let result = rpmvercmp(a.epoch, b.epoch);
|
|
19
|
+
if (result === 0) {
|
|
20
|
+
result = rpmvercmp(a.version, b.version);
|
|
21
|
+
if (result === 0 && a.release !== null && b.release !== null) {
|
|
22
|
+
result = rpmvercmp(a.release, b.release);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
const ZERO = Uint8Array.of(0x30);
|
|
28
|
+
function toBytes(valueArg) {
|
|
29
|
+
const bytes = new TextEncoder().encode(valueArg);
|
|
30
|
+
// a C string ends at the first NUL
|
|
31
|
+
const nul = bytes.indexOf(0);
|
|
32
|
+
return nul < 0 ? bytes : bytes.subarray(0, nul);
|
|
33
|
+
}
|
|
34
|
+
/** `parseEVR`: `[epoch:]version[-release]`; the release starts after the last `-`. */
|
|
35
|
+
function parseEvr(evrArg) {
|
|
36
|
+
let s = 0;
|
|
37
|
+
while (s < evrArg.length && isDigit(evrArg[s])) {
|
|
38
|
+
s++;
|
|
39
|
+
}
|
|
40
|
+
// strrchr(s, '-') searches from the epoch terminator on
|
|
41
|
+
let dash = -1;
|
|
42
|
+
for (let i = evrArg.length - 1; i >= s; i--) {
|
|
43
|
+
if (evrArg[i] === 0x2d) {
|
|
44
|
+
dash = i;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
let epoch;
|
|
49
|
+
let versionStart;
|
|
50
|
+
if (s < evrArg.length && evrArg[s] === 0x3a) {
|
|
51
|
+
epoch = s === 0 ? ZERO : evrArg.subarray(0, s);
|
|
52
|
+
versionStart = s + 1;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
epoch = ZERO;
|
|
56
|
+
versionStart = 0;
|
|
57
|
+
}
|
|
58
|
+
if (dash >= 0) {
|
|
59
|
+
return { epoch, version: evrArg.subarray(versionStart, dash), release: evrArg.subarray(dash + 1) };
|
|
60
|
+
}
|
|
61
|
+
return { epoch, version: evrArg.subarray(versionStart), release: null };
|
|
62
|
+
}
|
|
63
|
+
/** `rpmvercmp` over two C strings. */
|
|
64
|
+
function rpmvercmp(aArg, bArg) {
|
|
65
|
+
if (compareBytes(aArg, 0, aArg.length, bArg, 0, bArg.length) === 0) {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
const at = (bytesArg, indexArg) => (indexArg < bytesArg.length ? bytesArg[indexArg] : 0);
|
|
69
|
+
let one = 0;
|
|
70
|
+
let two = 0;
|
|
71
|
+
let ptr1 = 0;
|
|
72
|
+
let ptr2 = 0;
|
|
73
|
+
while (at(aArg, one) !== 0 && at(bArg, two) !== 0) {
|
|
74
|
+
while (at(aArg, one) !== 0 && !isAlnum(at(aArg, one))) {
|
|
75
|
+
one++;
|
|
76
|
+
}
|
|
77
|
+
while (at(bArg, two) !== 0 && !isAlnum(at(bArg, two))) {
|
|
78
|
+
two++;
|
|
79
|
+
}
|
|
80
|
+
if (!(at(aArg, one) !== 0 && at(bArg, two) !== 0)) {
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
// separator runs of different length decide
|
|
84
|
+
if (one - ptr1 !== two - ptr2) {
|
|
85
|
+
return one - ptr1 < two - ptr2 ? -1 : 1;
|
|
86
|
+
}
|
|
87
|
+
ptr1 = one;
|
|
88
|
+
ptr2 = two;
|
|
89
|
+
let isNum;
|
|
90
|
+
if (isDigit(at(aArg, ptr1))) {
|
|
91
|
+
while (at(aArg, ptr1) !== 0 && isDigit(at(aArg, ptr1))) {
|
|
92
|
+
ptr1++;
|
|
93
|
+
}
|
|
94
|
+
while (at(bArg, ptr2) !== 0 && isDigit(at(bArg, ptr2))) {
|
|
95
|
+
ptr2++;
|
|
96
|
+
}
|
|
97
|
+
isNum = true;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
while (at(aArg, ptr1) !== 0 && isAlpha(at(aArg, ptr1))) {
|
|
101
|
+
ptr1++;
|
|
102
|
+
}
|
|
103
|
+
while (at(bArg, ptr2) !== 0 && isAlpha(at(bArg, ptr2))) {
|
|
104
|
+
ptr2++;
|
|
105
|
+
}
|
|
106
|
+
isNum = false;
|
|
107
|
+
}
|
|
108
|
+
if (one === ptr1) {
|
|
109
|
+
return -1;
|
|
110
|
+
}
|
|
111
|
+
// numeric segments are newer than alpha segments
|
|
112
|
+
if (two === ptr2) {
|
|
113
|
+
return isNum ? 1 : -1;
|
|
114
|
+
}
|
|
115
|
+
let segment1 = one;
|
|
116
|
+
let segment2 = two;
|
|
117
|
+
if (isNum) {
|
|
118
|
+
while (at(aArg, segment1) === 0x30 && segment1 < ptr1) {
|
|
119
|
+
segment1++;
|
|
120
|
+
}
|
|
121
|
+
while (at(bArg, segment2) === 0x30 && segment2 < ptr2) {
|
|
122
|
+
segment2++;
|
|
123
|
+
}
|
|
124
|
+
if (ptr1 - segment1 > ptr2 - segment2) {
|
|
125
|
+
return 1;
|
|
126
|
+
}
|
|
127
|
+
if (ptr2 - segment2 > ptr1 - segment1) {
|
|
128
|
+
return -1;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const rc = compareBytes(aArg, segment1, ptr1, bArg, segment2, ptr2);
|
|
132
|
+
if (rc !== 0) {
|
|
133
|
+
return rc;
|
|
134
|
+
}
|
|
135
|
+
one = ptr1;
|
|
136
|
+
two = ptr2;
|
|
137
|
+
}
|
|
138
|
+
if (at(aArg, one) === 0 && at(bArg, two) === 0) {
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
// a remaining alpha string never beats an empty one
|
|
142
|
+
if ((at(aArg, one) === 0 && !isAlpha(at(bArg, two))) || isAlpha(at(aArg, one))) {
|
|
143
|
+
return -1;
|
|
144
|
+
}
|
|
145
|
+
return 1;
|
|
146
|
+
}
|
|
147
|
+
/** `strcmp` over two byte ranges. */
|
|
148
|
+
function compareBytes(aArg, aStartArg, aEndArg, bArg, bStartArg, bEndArg) {
|
|
149
|
+
const length = Math.min(aEndArg - aStartArg, bEndArg - bStartArg);
|
|
150
|
+
for (let i = 0; i < length; i++) {
|
|
151
|
+
const x = aArg[aStartArg + i];
|
|
152
|
+
const y = bArg[bStartArg + i];
|
|
153
|
+
if (x !== y) {
|
|
154
|
+
return x < y ? -1 : 1;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const aLength = aEndArg - aStartArg;
|
|
158
|
+
const bLength = bEndArg - bStartArg;
|
|
159
|
+
return aLength === bLength ? 0 : aLength < bLength ? -1 : 1;
|
|
160
|
+
}
|
|
161
|
+
function isDigit(byteArg) {
|
|
162
|
+
return byteArg >= 0x30 && byteArg <= 0x39;
|
|
163
|
+
}
|
|
164
|
+
function isAlpha(byteArg) {
|
|
165
|
+
return (byteArg >= 0x41 && byteArg <= 0x5a) || (byteArg >= 0x61 && byteArg <= 0x7a);
|
|
166
|
+
}
|
|
167
|
+
function isAlnum(byteArg) {
|
|
168
|
+
return isDigit(byteArg) || isAlpha(byteArg);
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyY21wLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvYXJjaC92ZXJjbXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxJQUFZLEVBQUUsSUFBWTtJQUM1RCxJQUFJLElBQUksS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUNsQixPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7SUFDRCxNQUFNLENBQUMsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbEMsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLElBQUksTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN6QyxJQUFJLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNqQixNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pDLElBQUksTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxLQUFLLElBQUksSUFBSSxDQUFDLENBQUMsT0FBTyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzdELE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0MsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBUUQsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUVqQyxTQUFTLE9BQU8sQ0FBQyxRQUFnQjtJQUMvQixNQUFNLEtBQUssR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENB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TyxDQUFDLENBQUMsQ0FBQztJQUNaLENBQUM7SUFDRCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFRCxxQ0FBcUM7QUFDckMsU0FBUyxZQUFZLENBQ25CLElBQWdCLEVBQ2hCLFNBQWlCLEVBQ2pCLE9BQWUsRUFDZixJQUFnQixFQUNoQixTQUFpQixFQUNqQixPQUFlO0lBRWYsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsU0FBUyxFQUFFLE9BQU8sR0FBRyxTQUFTLENBQUMsQ0FBQztJQUNsRSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDaEMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5QixNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ1osT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLENBQUM7SUFDSCxDQUFDO0lBQ0QsTUFBTSxPQUFPLEdBQUcsT0FBTyxHQUFHLFNBQVMsQ0FBQztJQUNwQyxNQUFNLE9BQU8sR0FBRyxPQUFPLEdBQUcsU0FBUyxDQUFDO0lBQ3BDLE9BQU8sT0FBTyxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzlELENBQUM7QUFFRCxTQUFTLE9BQU8sQ0FBQyxPQUFlO0lBQzlCLE9BQU8sT0FBTyxJQUFJLElBQUksSUFBSSxPQUFPLElBQUksSUFBSSxDQUFDO0FBQzVDLENBQUM7QUFFRCxTQUFTLE9BQU8sQ0FBQyxPQUFlO0lBQzlCLE9BQU8sQ0FBQyxPQUFPLElBQUksSUFBSSxJQUFJLE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxJQUFJLElBQUksT0FBTyxJQUFJLElBQUksQ0FBQyxDQUFDO0FBQ3RGLENBQUM7QUFFRCxTQUFTLE9BQU8sQ0FBQyxPQUFlO0lBQzlCLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUM5QyxDQUFDIn0=
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IDebianPackageMetadata } from '../shared/types.js';
|
|
2
|
+
/** Gitea's distribution and component rule (`metadata.go:67`, applied at upload). */
|
|
3
|
+
export declare const DEBIAN_SYMBOL_PATTERN: RegExp;
|
|
4
|
+
export interface IDebianControl {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
architecture: string;
|
|
8
|
+
metadata: IDebianPackageMetadata;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A port of Gitea 28.2.0 `ParseControlFile` (`metadata.go:165-265`) over the
|
|
12
|
+
* bytes of the `control` entry. Lines are split as `bufio.ScanLines` does
|
|
13
|
+
* (`\n`, one trailing `\r` dropped); the first blank line after content ends
|
|
14
|
+
* the stanza. Every derived value is Gitea's: the raw stanza trimmed, the
|
|
15
|
+
* Maintainer name through `net/mail`, the Homepage only when Gitea's URL
|
|
16
|
+
* check accepts it, the Description with its continuation lines appended
|
|
17
|
+
* verbatim, and the Depends text split on `,` (`['']` when there is none).
|
|
18
|
+
*
|
|
19
|
+
* Gitea's scanner refuses lines over 64 KiB; the codec accepts lines up to
|
|
20
|
+
* `maxLineBytes` (`maxHeaderBytes`), which is at least that.
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseDebianControlFile(bytesArg: Uint8Array, maxLineBytesArg: number): IDebianControl;
|