pacman-debian 7.2.0 → 7.3.1
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/README.md +22 -2
- package/README_zh-CN.md +89 -19
- package/dist/cli/paclink.d.ts.map +1 -0
- package/dist/cli/paclink.js +261 -0
- package/dist/cli/paclink.js.map +1 -0
- package/dist/cli/pacman.d.ts.map +1 -1
- package/dist/cli/pacman.js +64 -38
- package/dist/cli/pacman.js.map +1 -1
- package/dist/core/compress.d.ts.map +1 -1
- package/dist/core/compress.js +29 -0
- package/dist/core/compress.js.map +1 -1
- package/dist/core/deps.d.ts.map +1 -1
- package/dist/core/deps.js +133 -68
- package/dist/core/deps.js.map +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/database.js +3 -1
- package/dist/db/database.js.map +1 -1
- package/dist/db/localdb.d.ts.map +1 -1
- package/dist/db/localdb.js +73 -4
- package/dist/db/localdb.js.map +1 -1
- package/dist/i18n/en.json +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +52 -6
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/paclink/en.d.ts.map +1 -0
- package/dist/i18n/paclink/en.js +62 -0
- package/dist/i18n/paclink/en.js.map +1 -0
- package/dist/i18n/paclink/zh-CN.d.ts.map +1 -0
- package/dist/i18n/paclink/zh-CN.js +62 -0
- package/dist/i18n/paclink/zh-CN.js.map +1 -0
- package/dist/i18n/setup/en.d.ts.map +1 -0
- package/dist/i18n/setup/en.js +49 -0
- package/dist/i18n/setup/en.js.map +1 -0
- package/dist/i18n/setup/zh-CN.d.ts.map +1 -0
- package/dist/i18n/setup/zh-CN.js +49 -0
- package/dist/i18n/setup/zh-CN.js.map +1 -0
- package/dist/i18n/zh-CN.json +6 -0
- package/dist/ops/install.d.ts.map +1 -1
- package/dist/ops/install.js +238 -45
- package/dist/ops/install.js.map +1 -1
- package/dist/ops/query.d.ts.map +1 -1
- package/dist/ops/query.js +25 -9
- package/dist/ops/query.js.map +1 -1
- package/dist/ops/remove.d.ts.map +1 -1
- package/dist/ops/remove.js +213 -42
- package/dist/ops/remove.js.map +1 -1
- package/dist/ops/upgrade.d.ts.map +1 -1
- package/dist/ops/upgrade.js +13 -15
- package/dist/ops/upgrade.js.map +1 -1
- package/dist/repo/repository.d.ts.map +1 -1
- package/dist/repo/repository.js +246 -90
- package/dist/repo/repository.js.map +1 -1
- package/dist/scripts/setup.js +119 -116
- package/dist/scripts/setup.js.map +1 -1
- package/package.json +18 -7
- package/README.zh.md +0 -388
- package/dist/ar.d.ts +0 -8
- package/dist/cli/pacman.d.ts +0 -2
- package/dist/compress.d.ts +0 -2
- package/dist/config.d.ts +0 -3
- package/dist/control.d.ts +0 -2
- package/dist/core/ar.d.ts +0 -7
- package/dist/core/compress.d.ts +0 -2
- package/dist/core/control.d.ts +0 -2
- package/dist/core/deb.d.ts +0 -4
- package/dist/core/deps.d.ts +0 -25
- package/dist/core/options.d.ts +0 -19
- package/dist/core/pkgfile.d.ts +0 -35
- package/dist/core/tar.d.ts +0 -13
- package/dist/core/types.d.ts +0 -83
- package/dist/database.d.ts +0 -20
- package/dist/db/database.d.ts +0 -17
- package/dist/db/dpkg-compat.d.ts +0 -19
- package/dist/db/localdb.d.ts +0 -9
- package/dist/db/sqlite.d.ts +0 -20
- package/dist/deb.d.ts +0 -5
- package/dist/dpkg-compat.d.ts +0 -18
- package/dist/i18n/index.d.ts +0 -3
- package/dist/index.d.ts +0 -3
- package/dist/install.d.ts +0 -2
- package/dist/makepkg/build.d.ts +0 -19
- package/dist/makepkg/index.d.ts +0 -3
- package/dist/makepkg/pkgbuild.d.ts +0 -36
- package/dist/ops/install.d.ts +0 -5
- package/dist/ops/query.d.ts +0 -9
- package/dist/ops/remove.d.ts +0 -3
- package/dist/ops/upgrade.d.ts +0 -4
- package/dist/pacman.d.ts +0 -2
- package/dist/query.d.ts +0 -5
- package/dist/remove.d.ts +0 -2
- package/dist/repo/config.d.ts +0 -3
- package/dist/repo/repository.d.ts +0 -10
- package/dist/repository.d.ts +0 -10
- package/dist/scripts/pacman-conf.d.ts +0 -3
- package/dist/scripts/setup.d.ts +0 -3
- package/dist/tar.d.ts +0 -17
- package/dist/types.d.ts +0 -80
- package/dist/ui/colors.d.ts +0 -13
- package/dist/ui/format.d.ts +0 -3
- package/dist/ui/progress.d.ts +0 -8
- package/dist/ui/prompt.d.ts +0 -4
- package/lib/pac4deb/Makefile +0 -26
- package/lib/pac4deb/README.md +0 -47
- package/lib/pac4deb/include/alpm.h +0 -166
- package/lib/pac4deb/include/alpm_list.h +0 -42
- package/lib/pac4deb/libalpm.so +0 -0
- package/lib/pac4deb/src/alpm_list.c +0 -102
- package/lib/pac4deb/src/genstubs.sh +0 -51
- package/lib/pac4deb/src/genstubs2.sh +0 -72
- package/lib/pac4deb/src/genstubs3.sh +0 -43
- package/lib/pac4deb/src/libalpm.c +0 -537
- package/lib/pac4deb/src/stubs_manual.c +0 -198
- package/lib/pac4deb/stubs.c +0 -6
- package/lib/pac4deb/update_header.sh +0 -15
- package/src/cli/pacman.ts +0 -308
- package/src/core/ar.ts +0 -54
- package/src/core/compress.ts +0 -27
- package/src/core/control.ts +0 -22
- package/src/core/deb.ts +0 -47
- package/src/core/deps.ts +0 -260
- package/src/core/options.ts +0 -20
- package/src/core/pkgfile.ts +0 -146
- package/src/core/tar.ts +0 -101
- package/src/core/types.ts +0 -89
- package/src/db/database.ts +0 -102
- package/src/db/dpkg-compat.ts +0 -129
- package/src/db/localdb.ts +0 -181
- package/src/i18n/en.json +0 -114
- package/src/i18n/index.ts +0 -32
- package/src/i18n/zh-CN.json +0 -114
- package/src/index.ts +0 -7
- package/src/makepkg/build.ts +0 -351
- package/src/makepkg/index.ts +0 -87
- package/src/makepkg/pkgbuild.ts +0 -146
- package/src/ops/install.ts +0 -260
- package/src/ops/query.ts +0 -117
- package/src/ops/remove.ts +0 -77
- package/src/ops/upgrade.ts +0 -87
- package/src/repo/config.ts +0 -96
- package/src/repo/repository.ts +0 -520
- package/src/scripts/pacman-conf.ts +0 -68
- package/src/scripts/setup.ts +0 -261
- package/src/ui/colors.ts +0 -40
- package/src/ui/format.ts +0 -9
- package/src/ui/progress.ts +0 -26
- package/src/ui/prompt.ts +0 -21
- package/tsconfig.json +0 -19
package/src/index.ts
DELETED
package/src/makepkg/build.ts
DELETED
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import * as crypto from 'node:crypto';
|
|
4
|
-
import * as os from 'node:os';
|
|
5
|
-
import { execSync } from 'node:child_process';
|
|
6
|
-
import { parsePkgbuild, pkgFilename, printSrcinfo } from './pkgbuild';
|
|
7
|
-
import type { PkgbuildInfo } from './pkgbuild';
|
|
8
|
-
|
|
9
|
-
export interface BuildOptions {
|
|
10
|
-
install?: boolean;
|
|
11
|
-
clean?: boolean;
|
|
12
|
-
skipExtract?: boolean;
|
|
13
|
-
skipBuild?: boolean;
|
|
14
|
-
skipPackage?: boolean;
|
|
15
|
-
skipChecksum?: boolean;
|
|
16
|
-
nodeps?: boolean;
|
|
17
|
-
syncdeps?: boolean;
|
|
18
|
-
rmdeps?: boolean;
|
|
19
|
-
force?: boolean;
|
|
20
|
-
log?: boolean;
|
|
21
|
-
ignoreArch?: boolean;
|
|
22
|
-
pkgbuild?: string;
|
|
23
|
-
printsrcinfo?: boolean;
|
|
24
|
-
geninteg?: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function ensureDir(d: string) { if (!fs.existsSync(d)) fs.mkdirSync(d, { recursive: true }); }
|
|
28
|
-
|
|
29
|
-
function verifyChecksum(filePath: string, expected: string, algorithm: string): boolean {
|
|
30
|
-
if (!expected || expected === 'SKIP' || expected === 'skip') return true;
|
|
31
|
-
const hash = crypto.createHash(algorithm).update(fs.readFileSync(filePath)).digest('hex');
|
|
32
|
-
return hash === expected.toLowerCase();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function getSourceFilename(url: string): string {
|
|
36
|
-
const s = url.split('::')[1] || url;
|
|
37
|
-
return path.basename(s.split('?')[0].split('#')[0]);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function getSourceURL(url: string): string {
|
|
41
|
-
const parts = url.split('::');
|
|
42
|
-
return parts.length > 1 ? parts[1] : parts[0];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function downloadSource(url: string, destDir: string): string {
|
|
46
|
-
const filename = getSourceFilename(url);
|
|
47
|
-
const dest = path.join(destDir, filename);
|
|
48
|
-
if (fs.existsSync(dest)) return dest;
|
|
49
|
-
const realUrl = getSourceURL(url);
|
|
50
|
-
console.log(` downloading ${filename}...`);
|
|
51
|
-
try { execSync(`curl -fsSL -o "${dest}" "${realUrl}"`, { stdio: 'pipe', timeout: 120000 }); }
|
|
52
|
-
catch { execSync(`wget -q -O "${dest}" "${realUrl}"`, { stdio: 'pipe', timeout: 120000 }); }
|
|
53
|
-
return dest;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function extractSource(filePath: string, destDir: string): void {
|
|
57
|
-
const name = path.basename(filePath);
|
|
58
|
-
if (name.endsWith('.tar.gz') || name.endsWith('.tgz')) execSync(`tar -xzf "${filePath}" -C "${destDir}"`, { stdio: 'pipe' });
|
|
59
|
-
else if (name.endsWith('.tar.xz')) execSync(`tar -xJf "${filePath}" -C "${destDir}"`, { stdio: 'pipe' });
|
|
60
|
-
else if (name.endsWith('.tar.bz2')) execSync(`tar -xjf "${filePath}" -C "${destDir}"`, { stdio: 'pipe' });
|
|
61
|
-
else if (name.endsWith('.tar.zst')) execSync(`tar --zstd -xf "${filePath}" -C "${destDir}"`, { stdio: 'pipe' });
|
|
62
|
-
else if (name.endsWith('.zip')) execSync(`unzip -q -o "${filePath}" -d "${destDir}"`, { stdio: 'pipe' });
|
|
63
|
-
else if (name.endsWith('.gz')) execSync(`gunzip -c "${filePath}" > "${destDir}/${name.replace(/\.gz$/, '')}"`, { stdio: 'pipe' });
|
|
64
|
-
else if (name.endsWith('.xz')) execSync(`xz -dc "${filePath}" > "${destDir}/${name.replace(/\.xz$/, '')}"`, { stdio: 'pipe' });
|
|
65
|
-
else fs.copyFileSync(filePath, path.join(destDir, name));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function getDirSize(dir: string): number {
|
|
69
|
-
let total = 0;
|
|
70
|
-
try {
|
|
71
|
-
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
72
|
-
const fp = path.join(dir, e.name);
|
|
73
|
-
if (e.isFile()) total += fs.statSync(fp).size;
|
|
74
|
-
else if (e.isDirectory()) total += getDirSize(fp);
|
|
75
|
-
}
|
|
76
|
-
} catch {}
|
|
77
|
-
return total;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function installDep(dep: string): void {
|
|
81
|
-
const name = dep.split(/[<>=]/)[0].trim();
|
|
82
|
-
try {
|
|
83
|
-
// Prefer our own pacman, fallback to apt
|
|
84
|
-
execSync(`pacman -S --noconfirm --needed "${name}" 2>/dev/null`, { stdio: 'pipe', timeout: 60000 });
|
|
85
|
-
} catch {
|
|
86
|
-
try { execSync(`apt-get install -y "${name}" 2>/dev/null`, { stdio: 'pipe', timeout: 60000 }); } catch {}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export async function buildPkgbuild(options: BuildOptions): Promise<string> {
|
|
91
|
-
const pkgbuildPath = path.resolve(options.pkgbuild || 'PKGBUILD');
|
|
92
|
-
const workDir = path.dirname(pkgbuildPath);
|
|
93
|
-
|
|
94
|
-
if (options.printsrcinfo) {
|
|
95
|
-
const info = parsePkgbuild(pkgbuildPath, options.ignoreArch);
|
|
96
|
-
process.stdout.write(printSrcinfo(info));
|
|
97
|
-
return '';
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (options.geninteg) {
|
|
101
|
-
const info = parsePkgbuild(pkgbuildPath, options.ignoreArch);
|
|
102
|
-
for (let i = 0; i < info.source.length; i++) {
|
|
103
|
-
const src = getSourceFilename(info.source[i]);
|
|
104
|
-
console.log(` generating checksum for ${src}...`);
|
|
105
|
-
}
|
|
106
|
-
console.log(' (run with sources downloaded)');
|
|
107
|
-
return '';
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const logDir = path.join(workDir, 'src');
|
|
111
|
-
const logFile = options.log ? path.join(workDir, `${path.basename(workDir)}.log`) : undefined;
|
|
112
|
-
|
|
113
|
-
console.log(`==> Building ${path.basename(workDir)}`);
|
|
114
|
-
const info = parsePkgbuild(pkgbuildPath, options.ignoreArch);
|
|
115
|
-
|
|
116
|
-
const fullVersion = [info.pkgver, info.pkgrel].filter(Boolean).join('-');
|
|
117
|
-
console.log(` -> package: ${info.pkgname}-${fullVersion}`);
|
|
118
|
-
|
|
119
|
-
// Determine effective architecture (match system from PKGBUILD's arch list)
|
|
120
|
-
const archMap: Record<string, string> = { arm64: 'aarch64', arm: 'armv7h', x86: 'i686', x64: 'x86_64' };
|
|
121
|
-
const systemArch = archMap[process.arch] || process.arch;
|
|
122
|
-
const effectiveArch = info.arch.find(a => a === systemArch || a === 'any') || info.arch[0] || 'any';
|
|
123
|
-
if (effectiveArch !== systemArch && !info.arch.includes('any')) {
|
|
124
|
-
console.log(` warning: system arch ${systemArch} not in PKGBUILD arch list, using ${effectiveArch}`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const srcdir = path.join(workDir, 'src', `${info.pkgname}-${info.pkgver}`);
|
|
128
|
-
const pkgdir = path.join(workDir, 'pkg', `${info.pkgname}-${info.pkgver}`);
|
|
129
|
-
const outDir = workDir;
|
|
130
|
-
|
|
131
|
-
ensureDir(srcdir);
|
|
132
|
-
ensureDir(pkgdir);
|
|
133
|
-
ensureDir(outDir);
|
|
134
|
-
|
|
135
|
-
if (options.clean) {
|
|
136
|
-
if (fs.existsSync(srcdir)) fs.rmSync(srcdir, { recursive: true });
|
|
137
|
-
if (fs.existsSync(pkgdir)) fs.rmSync(pkgdir, { recursive: true });
|
|
138
|
-
ensureDir(srcdir);
|
|
139
|
-
ensureDir(pkgdir);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// --- syncdeps ---
|
|
143
|
-
if (options.syncdeps && !options.nodeps) {
|
|
144
|
-
const allDeps = [...new Set([...info.makedepends, ...info.checkdepends, ...info.depends])];
|
|
145
|
-
if (allDeps.length > 0) {
|
|
146
|
-
console.log(' :: Installing missing dependencies...');
|
|
147
|
-
for (const d of allDeps) {
|
|
148
|
-
const name = d.split(/[<>=]/)[0].trim();
|
|
149
|
-
process.stdout.write(` installing ${name}...`);
|
|
150
|
-
installDep(d);
|
|
151
|
-
process.stdout.write(' done\n');
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// --- Download sources ---
|
|
157
|
-
const sourceFiles: string[] = [];
|
|
158
|
-
if (info.source.length > 0) {
|
|
159
|
-
console.log(' :: Downloading sources...');
|
|
160
|
-
for (const src of info.source) {
|
|
161
|
-
const filename = getSourceFilename(src);
|
|
162
|
-
const srcUrl = getSourceURL(src);
|
|
163
|
-
if (srcUrl.startsWith('http://') || srcUrl.startsWith('https://') || srcUrl.startsWith('ftp://')) {
|
|
164
|
-
const file = downloadSource(src, srcdir);
|
|
165
|
-
sourceFiles.push(file);
|
|
166
|
-
console.log(` ${filename}... done`);
|
|
167
|
-
} else if (fs.existsSync(path.join(workDir, src))) {
|
|
168
|
-
const file = path.join(workDir, src);
|
|
169
|
-
const dest = path.join(srcdir, filename);
|
|
170
|
-
fs.cpSync(file, dest, { recursive: true, force: true });
|
|
171
|
-
sourceFiles.push(dest);
|
|
172
|
-
console.log(` ${filename}... found in workspace`);
|
|
173
|
-
} else {
|
|
174
|
-
console.log(` ${filename}... not found`);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// --- Verify checksums ---
|
|
180
|
-
if (!options.skipChecksum && !options.nodeps && info.source.length > 0) {
|
|
181
|
-
const hasSha = info.sha256sums.length === info.source.length && info.sha256sums.some(s => s && s !== 'SKIP');
|
|
182
|
-
const hasMd5 = info.md5sums.length === info.source.length && info.md5sums.some(s => s && s !== 'SKIP');
|
|
183
|
-
if (hasSha || hasMd5) {
|
|
184
|
-
console.log(' :: Verifying source file checksums...');
|
|
185
|
-
for (let i = 0; i < info.source.length; i++) {
|
|
186
|
-
const filename = getSourceFilename(info.source[i]);
|
|
187
|
-
const file = sourceFiles[i];
|
|
188
|
-
if (!file || !fs.existsSync(file)) continue;
|
|
189
|
-
if (hasSha) {
|
|
190
|
-
if (verifyChecksum(file, info.sha256sums[i], 'sha256')) {
|
|
191
|
-
console.log(` ${filename} ... Passed`);
|
|
192
|
-
} else {
|
|
193
|
-
throw new Error(`sha256sum mismatch for ${filename}`);
|
|
194
|
-
}
|
|
195
|
-
} else if (hasMd5) {
|
|
196
|
-
if (verifyChecksum(file, info.md5sums[i], 'md5')) {
|
|
197
|
-
console.log(` ${filename} ... Passed`);
|
|
198
|
-
} else {
|
|
199
|
-
throw new Error(`md5sum mismatch for ${filename}`);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// --- Extract sources ---
|
|
207
|
-
if (!options.skipExtract) {
|
|
208
|
-
const noextract = new Set(info.noextract);
|
|
209
|
-
const toExtract = sourceFiles.filter(f => !noextract.has(path.basename(f)));
|
|
210
|
-
if (toExtract.length > 0) {
|
|
211
|
-
console.log(' :: Extracting sources...');
|
|
212
|
-
for (const file of toExtract) {
|
|
213
|
-
try {
|
|
214
|
-
extractSource(file, srcdir);
|
|
215
|
-
console.log(` ${path.basename(file)}... done`);
|
|
216
|
-
} catch (e: any) {
|
|
217
|
-
console.error(` warning: failed to extract ${path.basename(file)}: ${e.message}`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// --- Build script ---
|
|
224
|
-
const buildScript = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'makepkg-')), `${info.pkgname}.sh`);
|
|
225
|
-
try {
|
|
226
|
-
const scriptLines: string[] = [
|
|
227
|
-
'#!/bin/bash',
|
|
228
|
-
'set -e',
|
|
229
|
-
`export srcdir="${srcdir}"`,
|
|
230
|
-
`export pkgdir="${pkgdir}"`,
|
|
231
|
-
`export pkgname="${info.pkgname}"`,
|
|
232
|
-
`export pkgver="${info.pkgver}"`,
|
|
233
|
-
`export pkgrel="${info.pkgrel}"`,
|
|
234
|
-
`export CARCH="${info.arch[0] || 'aarch64'}"`,
|
|
235
|
-
'cd "$srcdir"',
|
|
236
|
-
'',
|
|
237
|
-
];
|
|
238
|
-
|
|
239
|
-
// prepare()
|
|
240
|
-
if (info.prepareFn && !options.skipBuild) {
|
|
241
|
-
console.log(' :: Preparing...');
|
|
242
|
-
scriptLines.push(info.prepareFn);
|
|
243
|
-
scriptLines.push('prepare');
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// build()
|
|
247
|
-
if (info.buildFn && !options.skipBuild) {
|
|
248
|
-
console.log(' :: Building...');
|
|
249
|
-
scriptLines.push(info.buildFn);
|
|
250
|
-
scriptLines.push('build');
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// check()
|
|
254
|
-
if (info.checkFn && !options.skipBuild) {
|
|
255
|
-
console.log(' :: Checking...');
|
|
256
|
-
scriptLines.push(info.checkFn);
|
|
257
|
-
scriptLines.push('check');
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// package()
|
|
261
|
-
if (info.packageFn && !options.skipPackage) {
|
|
262
|
-
console.log(' :: Packaging...');
|
|
263
|
-
scriptLines.push(info.packageFn);
|
|
264
|
-
scriptLines.push('package');
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const hasWork = scriptLines.length > 7;
|
|
268
|
-
if (!hasWork && !options.skipPackage) {
|
|
269
|
-
throw new Error('PKGBUILD has no build(), prepare(), check(), or package() function');
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (hasWork) {
|
|
273
|
-
fs.writeFileSync(buildScript, scriptLines.join('\n'), { mode: 0o755 });
|
|
274
|
-
const logArg = logFile ? ` 2>&1 | tee "${logFile}"` : '';
|
|
275
|
-
try {
|
|
276
|
-
const cmd = `/bin/bash "${buildScript}"${logArg}`;
|
|
277
|
-
execSync(cmd, { stdio: 'inherit', timeout: 600000, cwd: srcdir });
|
|
278
|
-
} catch (e: any) {
|
|
279
|
-
throw new Error(`build failed: ${e.message}`);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
} finally {
|
|
283
|
-
try { fs.unlinkSync(buildScript); } catch {}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// --- Create .pkg.tar.zst ---
|
|
287
|
-
if (!options.skipPackage) {
|
|
288
|
-
const outFile = path.join(outDir, pkgFilename(info, effectiveArch));
|
|
289
|
-
|
|
290
|
-
if (!options.force && fs.existsSync(outFile)) {
|
|
291
|
-
throw new Error(`${path.basename(outFile)} already exists (use -f to overwrite)`);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const pkgContents = fs.readdirSync(pkgdir);
|
|
295
|
-
if (pkgContents.length === 0) throw new Error('package() produced no files in $pkgdir');
|
|
296
|
-
|
|
297
|
-
// Build .PKGINFO
|
|
298
|
-
const pkginfoLines = [
|
|
299
|
-
'# generated by pacman-debian makepkg',
|
|
300
|
-
`pkgname = ${info.pkgname}`,
|
|
301
|
-
`pkgver = ${info.pkgver}-${info.pkgrel}`,
|
|
302
|
-
`pkgdesc = ${info.pkgdesc || '(none)'}`,
|
|
303
|
-
`url = ${info.url || ''}`,
|
|
304
|
-
`builddate = ${Math.floor(Date.now() / 1000)}`,
|
|
305
|
-
`packager = pacman-debian`,
|
|
306
|
-
`size = ${getDirSize(pkgdir)}`,
|
|
307
|
-
`arch = ${effectiveArch}`,
|
|
308
|
-
...info.license.map(l => `license = ${l}`),
|
|
309
|
-
...info.depends.map(d => `depend = ${d}`),
|
|
310
|
-
...info.provides.map(p => `provides = ${p}`),
|
|
311
|
-
...info.conflicts.map(c => `conflict = ${c}`),
|
|
312
|
-
];
|
|
313
|
-
fs.writeFileSync(path.join(pkgdir, '.PKGINFO'), pkginfoLines.join('\n') + '\n');
|
|
314
|
-
|
|
315
|
-
// Copy install script if present
|
|
316
|
-
if (info.install && fs.existsSync(path.join(workDir, info.install))) {
|
|
317
|
-
fs.copyFileSync(path.join(workDir, info.install), path.join(pkgdir, '.INSTALL'));
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Create .pkg.tar.zst
|
|
321
|
-
execSync(`tar --zstd -cf "${outFile}" -C "${pkgdir}" .`, { stdio: 'pipe', timeout: 120000 });
|
|
322
|
-
|
|
323
|
-
const stat = fs.statSync(outFile);
|
|
324
|
-
const sizeKb = (stat.size / 1024).toFixed(0);
|
|
325
|
-
console.log(` ==> Created package: ${path.basename(outFile)} (${sizeKb} KiB)`);
|
|
326
|
-
|
|
327
|
-
// Install
|
|
328
|
-
if (options.install) {
|
|
329
|
-
if (process.getuid && process.getuid() !== 0) {
|
|
330
|
-
console.log(` ==> Install with: sudo pacman -U ${path.basename(outFile)}`);
|
|
331
|
-
} else {
|
|
332
|
-
console.log(' :: Installing package...');
|
|
333
|
-
const { installPkgFile } = await import('../ops/install');
|
|
334
|
-
await installPkgFile(outFile, 'explicit');
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Remove build deps
|
|
339
|
-
if (options.rmdeps && options.syncdeps) {
|
|
340
|
-
const allDeps = [...new Set([...info.makedepends, ...info.checkdepends])];
|
|
341
|
-
for (const d of allDeps) {
|
|
342
|
-
const name = d.split(/[<>=]/)[0].trim();
|
|
343
|
-
try { execSync(`pacman -R --noconfirm "${name}" 2>/dev/null`, { stdio: 'pipe' }); } catch {}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
return outFile;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
return '';
|
|
351
|
-
}
|
package/src/makepkg/index.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { buildPkgbuild } from './build';
|
|
3
|
-
|
|
4
|
-
function help(): void {
|
|
5
|
-
console.log(`makepkg (pacman-debian) - build packages from PKGBUILD
|
|
6
|
-
|
|
7
|
-
usage: makepkg [options]
|
|
8
|
-
|
|
9
|
-
options:
|
|
10
|
-
-i, --install Install package after build
|
|
11
|
-
-s, --syncdeps Install missing dependencies
|
|
12
|
-
-r, --rmdeps Remove dependencies after build (use with -s)
|
|
13
|
-
-c, --clean Clean build files before building
|
|
14
|
-
-f, --force Overwrite existing package
|
|
15
|
-
-o, --nobuild Download and extract only
|
|
16
|
-
-e, --noextract Skip extraction (use existing src dir)
|
|
17
|
-
-d, --nodeps Skip all dependency checks
|
|
18
|
-
-L, --log Log build output to file
|
|
19
|
-
-A, --ignorearch Ignore architecture mismatch
|
|
20
|
-
-p, --pkgbuild Use an alternate build script (default: PKGBUILD)
|
|
21
|
-
--printsrcinfo Print .SRCINFO and exit
|
|
22
|
-
--geninteg Generate integrity checksums
|
|
23
|
-
--nocheck Skip check() function
|
|
24
|
-
--noprepare Skip prepare() function
|
|
25
|
-
-h, --help Show this help
|
|
26
|
-
`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function main(): Promise<void> {
|
|
30
|
-
const args = process.argv.slice(2);
|
|
31
|
-
|
|
32
|
-
if (args.includes('-h') || args.includes('--help')) { help(); return; }
|
|
33
|
-
|
|
34
|
-
const has = (short: string, long: string) => args.includes(short) || args.includes(long);
|
|
35
|
-
|
|
36
|
-
const options: any = {
|
|
37
|
-
install: has('-i', '--install'),
|
|
38
|
-
syncdeps: has('-s', '--syncdeps'),
|
|
39
|
-
rmdeps: has('-r', '--rmdeps'),
|
|
40
|
-
clean: has('-c', '--clean'),
|
|
41
|
-
force: has('-f', '--force'),
|
|
42
|
-
skipBuild: has('-o', '--nobuild'),
|
|
43
|
-
skipExtract: has('-e', '--noextract'),
|
|
44
|
-
skipPackage: has('-o', '--nobuild'),
|
|
45
|
-
nodeps: has('-d', '--nodeps'),
|
|
46
|
-
log: has('-L', '--log'),
|
|
47
|
-
ignoreArch: has('-A', '--ignorearch'),
|
|
48
|
-
printsrcinfo: has('', '--printsrcinfo'),
|
|
49
|
-
geninteg: has('', '--geninteg'),
|
|
50
|
-
nocheck: has('', '--nocheck'),
|
|
51
|
-
noprepare: has('', '--noprepare'),
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// --nocheck sets skipBuild to skip check, but still run build
|
|
55
|
-
// --noprepare sets skipBuild to skip prepare, but still run build
|
|
56
|
-
|
|
57
|
-
const pkgbuildIdx = args.indexOf('-p');
|
|
58
|
-
if (pkgbuildIdx !== -1 && args[pkgbuildIdx + 1]) options.pkgbuild = args[pkgbuildIdx + 1];
|
|
59
|
-
else {
|
|
60
|
-
const idx = args.indexOf('--pkgbuild');
|
|
61
|
-
if (idx !== -1 && args[idx + 1]) options.pkgbuild = args[idx + 1];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (options.printsrcinfo || options.geninteg) {
|
|
65
|
-
await buildPkgbuild(options);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if ((options.install || options.syncdeps) && !options.skipPackage &&
|
|
70
|
-
process.getuid && process.getuid() !== 0) {
|
|
71
|
-
// Build as user, then print install instructions
|
|
72
|
-
console.log(':: Building package...');
|
|
73
|
-
await buildPkgbuild({ ...options, install: false, syncdeps: false });
|
|
74
|
-
console.log('');
|
|
75
|
-
console.log(' To install the package, run:');
|
|
76
|
-
console.log(` sudo pacman -U *.pkg.tar.zst`);
|
|
77
|
-
console.log('');
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
await buildPkgbuild(options);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
main().catch(e => {
|
|
85
|
-
console.error(`error: ${e.message}`);
|
|
86
|
-
process.exit(1);
|
|
87
|
-
});
|
package/src/makepkg/pkgbuild.ts
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import * as path from 'node:path';
|
|
4
|
-
|
|
5
|
-
export interface PkgbuildInfo {
|
|
6
|
-
pkgbase?: string;
|
|
7
|
-
pkgname: string;
|
|
8
|
-
pkgver: string;
|
|
9
|
-
pkgrel: string;
|
|
10
|
-
epoch?: string;
|
|
11
|
-
pkgdesc: string;
|
|
12
|
-
arch: string[];
|
|
13
|
-
url?: string;
|
|
14
|
-
license: string[];
|
|
15
|
-
groups: string[];
|
|
16
|
-
depends: string[];
|
|
17
|
-
makedepends: string[];
|
|
18
|
-
optdepends: string[];
|
|
19
|
-
checkdepends: string[];
|
|
20
|
-
provides: string[];
|
|
21
|
-
conflicts: string[];
|
|
22
|
-
replaces: string[];
|
|
23
|
-
source: string[];
|
|
24
|
-
noextract: string[];
|
|
25
|
-
sha256sums: string[];
|
|
26
|
-
md5sums: string[];
|
|
27
|
-
validpgpkeys: string[];
|
|
28
|
-
install?: string;
|
|
29
|
-
options: string[];
|
|
30
|
-
backup: string[];
|
|
31
|
-
buildFn: string;
|
|
32
|
-
packageFn: string;
|
|
33
|
-
prepareFn: string;
|
|
34
|
-
checkFn: string;
|
|
35
|
-
validArch: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function bashGet(v: string, p: string): string {
|
|
39
|
-
try {
|
|
40
|
-
return execSync(
|
|
41
|
-
`bash -c 'source "${p}" 2>/dev/null; printf "%s" "${'$'}{${v}}" 2>/dev/null'`,
|
|
42
|
-
{ encoding: 'utf8', timeout: 10000 }
|
|
43
|
-
).trim();
|
|
44
|
-
} catch { return ''; }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function bashGetArray(v: string, p: string): string[] {
|
|
48
|
-
try {
|
|
49
|
-
const out = execSync(
|
|
50
|
-
`bash -c 'source "${p}" 2>/dev/null; for i in "${'$'}{${v}[@]}"; do echo "$i"; done' 2>/dev/null`,
|
|
51
|
-
{ encoding: 'utf8', timeout: 10000 }
|
|
52
|
-
).trim();
|
|
53
|
-
return out ? out.split('\n').filter(Boolean) : [];
|
|
54
|
-
} catch { return []; }
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function bashGetFn(f: string, p: string): string {
|
|
58
|
-
try {
|
|
59
|
-
return execSync(
|
|
60
|
-
`bash -c 'source "${p}" 2>/dev/null; declare -f ${f} 2>/dev/null'`,
|
|
61
|
-
{ encoding: 'utf8', timeout: 10000 }
|
|
62
|
-
).trim();
|
|
63
|
-
} catch { return ''; }
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function parsePkgbuild(pkgbuildPath: string, ignoreArch = false): PkgbuildInfo {
|
|
67
|
-
if (!fs.existsSync(pkgbuildPath)) throw new Error(`PKGBUILD not found: ${pkgbuildPath}`);
|
|
68
|
-
const absPath = path.resolve(pkgbuildPath);
|
|
69
|
-
|
|
70
|
-
const arch = bashGetArray('arch', absPath);
|
|
71
|
-
const systemArch = process.arch === 'arm64' ? 'aarch64' : process.arch;
|
|
72
|
-
const validArch = ignoreArch || arch.length === 0 || arch.includes('any') || arch.includes(systemArch);
|
|
73
|
-
|
|
74
|
-
const info: PkgbuildInfo = {
|
|
75
|
-
pkgbase: bashGet('pkgbase', absPath) || undefined,
|
|
76
|
-
pkgname: bashGet('pkgname', absPath),
|
|
77
|
-
pkgver: bashGet('pkgver', absPath),
|
|
78
|
-
pkgrel: bashGet('pkgrel', absPath),
|
|
79
|
-
epoch: bashGet('epoch', absPath) || undefined,
|
|
80
|
-
pkgdesc: bashGet('pkgdesc', absPath) || '',
|
|
81
|
-
arch,
|
|
82
|
-
url: bashGet('url', absPath) || undefined,
|
|
83
|
-
license: bashGetArray('license', absPath),
|
|
84
|
-
groups: bashGetArray('groups', absPath),
|
|
85
|
-
depends: bashGetArray('depends', absPath),
|
|
86
|
-
makedepends: bashGetArray('makedepends', absPath),
|
|
87
|
-
optdepends: bashGetArray('optdepends', absPath),
|
|
88
|
-
checkdepends: bashGetArray('checkdepends', absPath),
|
|
89
|
-
provides: bashGetArray('provides', absPath),
|
|
90
|
-
conflicts: bashGetArray('conflicts', absPath),
|
|
91
|
-
replaces: bashGetArray('replaces', absPath),
|
|
92
|
-
source: bashGetArray('source', absPath),
|
|
93
|
-
noextract: bashGetArray('noextract', absPath),
|
|
94
|
-
sha256sums: bashGetArray('sha256sums', absPath),
|
|
95
|
-
md5sums: bashGetArray('md5sums', absPath),
|
|
96
|
-
validpgpkeys: bashGetArray('validpgpkeys', absPath),
|
|
97
|
-
install: bashGet('install', absPath) || undefined,
|
|
98
|
-
options: bashGetArray('options', absPath),
|
|
99
|
-
backup: bashGetArray('backup', absPath),
|
|
100
|
-
buildFn: bashGetFn('build', absPath),
|
|
101
|
-
packageFn: bashGetFn('package', absPath),
|
|
102
|
-
prepareFn: bashGetFn('prepare', absPath),
|
|
103
|
-
checkFn: bashGetFn('check', absPath),
|
|
104
|
-
validArch,
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
if (!info.pkgname) throw new Error('PKGBUILD missing pkgname');
|
|
108
|
-
if (!info.pkgver) throw new Error('PKGBUILD missing pkgver');
|
|
109
|
-
if (!info.validArch) throw new Error(`PKGBUILD does not support architecture: ${systemArch} (${arch.join(', ')})`);
|
|
110
|
-
|
|
111
|
-
return info;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function pkgFilename(info: PkgbuildInfo, archOverride?: string): string {
|
|
115
|
-
return `${info.pkgname}-${info.pkgver}-${info.pkgrel}-${archOverride || info.arch[0] || 'any'}.pkg.tar.zst`;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export function printSrcinfo(info: PkgbuildInfo): string {
|
|
119
|
-
const lines: string[] = [
|
|
120
|
-
`pkgbase = ${info.pkgbase || info.pkgname}`,
|
|
121
|
-
`pkgname = ${info.pkgname}`,
|
|
122
|
-
`pkgver = ${info.pkgver}`,
|
|
123
|
-
`pkgrel = ${info.pkgrel}`,
|
|
124
|
-
];
|
|
125
|
-
if (info.epoch) lines.push(`epoch = ${info.epoch}`);
|
|
126
|
-
lines.push(`pkgdesc = ${info.pkgdesc}`);
|
|
127
|
-
for (const a of info.arch) lines.push(`arch = ${a}`);
|
|
128
|
-
if (info.url) lines.push(`url = ${info.url}`);
|
|
129
|
-
for (const l of info.license) lines.push(`license = ${l}`);
|
|
130
|
-
for (const g of info.groups) lines.push(`group = ${g}`);
|
|
131
|
-
for (const d of info.depends) lines.push(`depend = ${d}`);
|
|
132
|
-
for (const d of info.makedepends) lines.push(`makedepend = ${d}`);
|
|
133
|
-
for (const d of info.optdepends) lines.push(`optdepend = ${d}`);
|
|
134
|
-
for (const d of info.checkdepends) lines.push(`checkdepend = ${d}`);
|
|
135
|
-
for (const p of info.provides) lines.push(`provides = ${p}`);
|
|
136
|
-
for (const c of info.conflicts) lines.push(`conflict = ${c}`);
|
|
137
|
-
for (const r of info.replaces) lines.push(`replaces = ${r}`);
|
|
138
|
-
for (const s of info.source) lines.push(`source = ${s}`);
|
|
139
|
-
for (const s of info.noextract) lines.push(`noextract = ${s}`);
|
|
140
|
-
for (const s of info.sha256sums) lines.push(`sha256sums = ${s}`);
|
|
141
|
-
for (const s of info.md5sums) lines.push(`md5sums = ${s}`);
|
|
142
|
-
if (info.install) lines.push(`install = ${info.install}`);
|
|
143
|
-
for (const o of info.options) lines.push(`options = ${o}`);
|
|
144
|
-
for (const b of info.backup) lines.push(`backup = ${b}`);
|
|
145
|
-
return lines.join('\n') + '\n';
|
|
146
|
-
}
|