pacman-debian 7.3.36 → 7.5.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 (99) hide show
  1. package/README.md +12 -0
  2. package/README_zh-CN.md +11 -0
  3. package/dist/cli/archlinux-java.js +36 -12
  4. package/dist/cli/archlinux-java.js.map +1 -1
  5. package/dist/cli/paclink.js +84 -0
  6. package/dist/cli/paclink.js.map +1 -1
  7. package/dist/cli/pacman.d.ts.map +1 -1
  8. package/dist/cli/pacman.js +66 -11
  9. package/dist/cli/pacman.js.map +1 -1
  10. package/dist/cli/pactree.d.ts +3 -0
  11. package/dist/cli/pactree.d.ts.map +1 -0
  12. package/dist/cli/pactree.js +216 -0
  13. package/dist/cli/pactree.js.map +1 -0
  14. package/dist/core/deps.d.ts +7 -0
  15. package/dist/core/deps.d.ts.map +1 -1
  16. package/dist/core/deps.js +104 -24
  17. package/dist/core/deps.js.map +1 -1
  18. package/dist/core/logger.d.ts +7 -0
  19. package/dist/core/logger.d.ts.map +1 -0
  20. package/dist/core/logger.js +93 -0
  21. package/dist/core/logger.js.map +1 -0
  22. package/dist/core/options.d.ts +2 -0
  23. package/dist/core/options.d.ts.map +1 -1
  24. package/dist/core/paclinks.d.ts +9 -0
  25. package/dist/core/paclinks.d.ts.map +1 -0
  26. package/dist/core/paclinks.js +69 -0
  27. package/dist/core/paclinks.js.map +1 -0
  28. package/dist/core/pkgfile.d.ts +2 -0
  29. package/dist/core/pkgfile.d.ts.map +1 -1
  30. package/dist/core/pkgfile.js +6 -0
  31. package/dist/core/pkgfile.js.map +1 -1
  32. package/dist/core/tar.d.ts +3 -1
  33. package/dist/core/tar.d.ts.map +1 -1
  34. package/dist/core/tar.js +87 -11
  35. package/dist/core/tar.js.map +1 -1
  36. package/dist/core/types.d.ts +17 -0
  37. package/dist/core/types.d.ts.map +1 -1
  38. package/dist/db/dpkg-compat.d.ts +5 -2
  39. package/dist/db/dpkg-compat.d.ts.map +1 -1
  40. package/dist/db/dpkg-compat.js +130 -57
  41. package/dist/db/dpkg-compat.js.map +1 -1
  42. package/dist/db/localdb.d.ts.map +1 -1
  43. package/dist/db/localdb.js +21 -2
  44. package/dist/db/localdb.js.map +1 -1
  45. package/dist/debug-upgrade.d.ts +2 -0
  46. package/dist/debug-upgrade.d.ts.map +1 -0
  47. package/dist/debug-upgrade.js +140 -0
  48. package/dist/debug-upgrade.js.map +1 -0
  49. package/dist/i18n/en.json +2 -0
  50. package/dist/i18n/paclink/en.d.ts.map +1 -1
  51. package/dist/i18n/paclink/en.js +7 -0
  52. package/dist/i18n/paclink/en.js.map +1 -1
  53. package/dist/i18n/paclink/zh-CN.d.ts.map +1 -1
  54. package/dist/i18n/paclink/zh-CN.js +7 -0
  55. package/dist/i18n/paclink/zh-CN.js.map +1 -1
  56. package/dist/i18n/zh-CN.json +2 -0
  57. package/dist/lock/dpkg-helper +0 -0
  58. package/dist/lock/dpkg-lock.d.ts +5 -0
  59. package/dist/lock/dpkg-lock.d.ts.map +1 -0
  60. package/dist/lock/dpkg-lock.js +113 -0
  61. package/dist/lock/dpkg-lock.js.map +1 -0
  62. package/dist/makepkg/build.d.ts.map +1 -1
  63. package/dist/makepkg/build.js +3 -5
  64. package/dist/makepkg/build.js.map +1 -1
  65. package/dist/makepkg/pkgbuild.d.ts.map +1 -1
  66. package/dist/makepkg/pkgbuild.js +109 -53
  67. package/dist/makepkg/pkgbuild.js.map +1 -1
  68. package/dist/ops/install.d.ts +2 -1
  69. package/dist/ops/install.d.ts.map +1 -1
  70. package/dist/ops/install.js +290 -157
  71. package/dist/ops/install.js.map +1 -1
  72. package/dist/ops/query.d.ts.map +1 -1
  73. package/dist/ops/query.js +62 -35
  74. package/dist/ops/query.js.map +1 -1
  75. package/dist/ops/remove.d.ts.map +1 -1
  76. package/dist/ops/remove.js +106 -60
  77. package/dist/ops/remove.js.map +1 -1
  78. package/dist/ops/upgrade.d.ts.map +1 -1
  79. package/dist/ops/upgrade.js +71 -13
  80. package/dist/ops/upgrade.js.map +1 -1
  81. package/dist/repo/config.d.ts.map +1 -1
  82. package/dist/repo/config.js +60 -6
  83. package/dist/repo/config.js.map +1 -1
  84. package/dist/repo/repository.d.ts +6 -0
  85. package/dist/repo/repository.d.ts.map +1 -1
  86. package/dist/repo/repository.js +348 -49
  87. package/dist/repo/repository.js.map +1 -1
  88. package/dist/scripts/setup.js +27 -77
  89. package/dist/scripts/setup.js.map +1 -1
  90. package/docs/en/architecture.md +109 -45
  91. package/docs/en/pactree.md +42 -0
  92. package/docs/en/yay-aur.md +10 -6
  93. package/docs/zh-CN/pactree.md +41 -0
  94. package/lib/pac4deb/include/alpm.h +2 -1
  95. package/lib/pac4deb/src/libalpm.c +116 -54
  96. package/lib/pac4deb/src/stubs_manual.c +11 -1
  97. package/package.json +4 -3
  98. package/resources/paclinks.conf +64 -0
  99. package/resources/pacman.conf.template +16 -2
@@ -49,19 +49,21 @@ const repository_1 = require("../repo/repository");
49
49
  const config_1 = require("../repo/config");
50
50
  const database_1 = require("../db/database");
51
51
  const dpkg_compat_1 = require("../db/dpkg-compat");
52
+ const dpkg_lock_1 = require("../lock/dpkg-lock");
52
53
  const localdb_1 = require("../db/localdb");
53
54
  const deps_1 = require("../core/deps");
54
55
  const format_1 = require("../ui/format");
55
56
  const progress_1 = require("../ui/progress");
56
57
  const prompt_1 = require("../ui/prompt");
57
58
  const i18n_1 = require("../i18n");
58
- async function installDeb(filePath, reason, opts = {}) {
59
+ async function installDeb(filePath, reason, opts = {}, onProgress) {
59
60
  (0, database_1.initDb)();
60
61
  const pkg = (0, deb_1.parseDeb)(filePath);
61
62
  const db = (0, database_1.loadDatabase)();
62
63
  removeLinkIfPresent(pkg.control.package);
63
64
  const { control } = pkg;
64
65
  const existing = (0, database_1.getPackage)(db, control.package);
66
+ const _cfg = (0, config_1.loadConfig)();
65
67
  if (opts.needed && existing && existing.version === control.version) {
66
68
  return false;
67
69
  }
@@ -75,50 +77,56 @@ async function installDeb(filePath, reason, opts = {}) {
75
77
  if (realFiles.length > 0)
76
78
  return true;
77
79
  }
78
- const tx = (0, database_1.createTransaction)('install', control.package, control.version);
79
- if (!opts.noscriptlet) {
80
- const preinst = (0, deb_1.readScript)(pkg, 'preinst');
81
- if (preinst)
82
- (0, database_1.saveScript)(control.package, 'preinst', preinst);
83
- (0, database_1.runScript)(control.package, 'preinst', ['install']);
84
- }
85
- const files = (0, tar_1.extractTar)(pkg.dataTar, '/');
86
- if (!opts.noscriptlet) {
87
- const postinst = (0, deb_1.readScript)(pkg, 'postinst');
88
- if (postinst)
89
- (0, database_1.saveScript)(control.package, 'postinst', postinst);
90
- (0, database_1.runScript)(control.package, 'postinst', ['configure']);
91
- }
92
- // Run ldconfig if package installs shared libraries
93
- const hasSoFiles = files.some(f => /\.so(\.|$)/.test(f));
94
- if (hasSoFiles) {
80
+ await (0, dpkg_lock_1.acquireDpkgLock)();
81
+ try {
82
+ const tx = (0, database_1.createTransaction)('install', control.package, control.version);
83
+ if (!opts.noscriptlet) {
84
+ const preinst = (0, deb_1.readScript)(pkg, 'preinst');
85
+ if (preinst)
86
+ (0, database_1.saveScript)(control.package, 'preinst', preinst);
87
+ (0, database_1.runScript)(control.package, 'preinst', ['install']);
88
+ }
89
+ const files = (0, tar_1.extractTar)(pkg.dataTar, '/', onProgress, _cfg.noExtract, _cfg.noUpgrade);
90
+ if (!opts.noscriptlet) {
91
+ const postinst = (0, deb_1.readScript)(pkg, 'postinst');
92
+ if (postinst)
93
+ (0, database_1.saveScript)(control.package, 'postinst', postinst);
94
+ (0, database_1.runScript)(control.package, 'postinst', ['configure']);
95
+ }
96
+ // Run ldconfig if package installs shared libraries
97
+ const hasSoFiles = files.some(f => /\.so(\.|$)/.test(f));
98
+ if (hasSoFiles) {
99
+ try {
100
+ (0, node_child_process_1.execSync)('/usr/sbin/ldconfig', { stdio: 'inherit' });
101
+ }
102
+ catch { }
103
+ }
104
+ const ip = {
105
+ name: control.package, version: control.version,
106
+ architecture: control.architecture || 'amd64',
107
+ description: control.description || '',
108
+ depends: control.depends, 'pre-depends': control['pre-depends'],
109
+ conflicts: control.conflicts, provides: control.provides,
110
+ maintainer: control.maintainer, homepage: control.homepage,
111
+ controlSection: control.section || 'misc',
112
+ controlPriority: control.priority || 'optional',
113
+ installedSize: control['installed-size'] ? parseInt(control['installed-size'], 10) : undefined,
114
+ installTime: Date.now(), reason, files, repo: opts.repo,
115
+ };
116
+ (0, database_1.addPackage)(db, ip);
95
117
  try {
96
- (0, node_child_process_1.execSync)('/usr/sbin/ldconfig', { stdio: 'inherit' });
118
+ await (0, dpkg_compat_1.writeDpkgEntry)(ip);
97
119
  }
98
- catch { }
99
- }
100
- const ip = {
101
- name: control.package, version: control.version,
102
- architecture: control.architecture || 'amd64',
103
- description: control.description || '',
104
- depends: control.depends, 'pre-depends': control['pre-depends'],
105
- conflicts: control.conflicts, provides: control.provides,
106
- maintainer: control.maintainer, homepage: control.homepage,
107
- controlSection: control.section || 'misc',
108
- controlPriority: control.priority || 'optional',
109
- installedSize: control['installed-size'] ? parseInt(control['installed-size'], 10) : undefined,
110
- installTime: Date.now(), reason, files,
111
- };
112
- (0, database_1.addPackage)(db, ip);
113
- try {
114
- (0, dpkg_compat_1.writeDpkgEntry)(ip);
120
+ catch (e) {
121
+ console.error((0, i18n_1.t)('warn_failed_dpkg_status', String(e)));
122
+ }
123
+ (0, database_1.saveDatabase)(db);
124
+ (0, database_1.completeTransaction)(tx.id);
125
+ return true;
115
126
  }
116
- catch (e) {
117
- console.error((0, i18n_1.t)('warn_failed_dpkg_status', String(e)));
127
+ finally {
128
+ (0, dpkg_lock_1.releaseDpkgLock)();
118
129
  }
119
- (0, database_1.saveDatabase)(db);
120
- (0, database_1.completeTransaction)(tx.id);
121
- return true;
122
130
  }
123
131
  /* When installing a real package, remove any existing link with the same name.
124
132
  Links are virtual mappings (Debian→Arch), real packages take precedence. */
@@ -128,7 +136,7 @@ function removeLinkIfPresent(pkgName) {
128
136
  (0, localdb_1.removePackage)(pkgName, existing.version);
129
137
  }
130
138
  }
131
- async function installArch(filePath, reason, opts = {}) {
139
+ async function installArch(filePath, reason, opts = {}, onProgress) {
132
140
  (0, database_1.initDb)();
133
141
  const data = fs.readFileSync(filePath);
134
142
  const { info, install, files: pkgFiles, dataBlocks } = (0, pkgfile_1.parsePkgTarZst)(data);
@@ -139,88 +147,110 @@ async function installArch(filePath, reason, opts = {}) {
139
147
  const existing = (0, database_1.getPackage)(db, info.name);
140
148
  if (opts.needed && existing && existing.version === info.version)
141
149
  return false;
142
- const tx = (0, database_1.createTransaction)('install', info.name, info.version);
143
- if (!opts.noscriptlet && (install?.pre_install || install?.post_install)) {
144
- const parts = [];
145
- if (install.pre_install)
146
- parts.push(`pre_install() {\n${install.pre_install}\n}`);
147
- if (install.post_install)
148
- parts.push(`post_install() {\n${install.post_install}\n}`);
149
- if (install.pre_remove)
150
- parts.push(`pre_remove() {\n${install.pre_remove}\n}`);
151
- if (install.post_remove)
152
- parts.push(`post_remove() {\n${install.post_remove}\n}`);
153
- const script = parts.join('\n') + '\n';
154
- (0, database_1.saveScript)(info.name, '.INSTALL', script);
155
- const tmpScript = `/var/lib/pacman-debian/info/${info.name}/.INSTALL`;
156
- if (install?.pre_install) {
150
+ await (0, dpkg_lock_1.acquireDpkgLock)();
151
+ try {
152
+ const tx = (0, database_1.createTransaction)('install', info.name, info.version);
153
+ if (!opts.noscriptlet && (install?.pre_install || install?.post_install)) {
154
+ const parts = [];
155
+ if (install.pre_install)
156
+ parts.push(`pre_install() {\n${install.pre_install}\n}`);
157
+ if (install.post_install)
158
+ parts.push(`post_install() {\n${install.post_install}\n}`);
159
+ if (install.pre_remove)
160
+ parts.push(`pre_remove() {\n${install.pre_remove}\n}`);
161
+ if (install.post_remove)
162
+ parts.push(`post_remove() {\n${install.post_remove}\n}`);
163
+ const script = parts.join('\n') + '\n';
164
+ (0, database_1.saveScript)(info.name, '.INSTALL', script);
165
+ const tmpScript = `/var/lib/pacman-debian/info/${info.name}/.INSTALL`;
166
+ if (install?.pre_install) {
167
+ try {
168
+ (0, node_child_process_1.execSync)(`/bin/bash -c 'source "${tmpScript}" && pre_install' 2>&-`, { stdio: 'pipe' });
169
+ }
170
+ catch { }
171
+ }
172
+ }
173
+ const files = [];
174
+ const total = dataBlocks.length;
175
+ const _archCfg = (0, config_1.loadConfig)();
176
+ const matchArch = (p, name) => p === name || p === '/' + name || (p.endsWith('/*') && name.startsWith(p.slice(0, -1)));
177
+ for (let i = 0; i < total; i++) {
178
+ const entry = dataBlocks[i];
179
+ const targetPath = (0, tar_1.safeTargetPath)('/', entry.name);
180
+ files.push('/' + entry.name);
181
+ if (_archCfg.noExtract.some(p => matchArch(p, entry.name)))
182
+ continue;
183
+ if (entry.data) {
184
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
185
+ if (_archCfg.noUpgrade.some(p => matchArch(p, entry.name)) && fs.existsSync(targetPath)) {
186
+ const bak = targetPath + '.pacnew';
187
+ fs.writeFileSync(bak, entry.data, { mode: 0o755 });
188
+ }
189
+ else {
190
+ if (fs.existsSync(targetPath) && fs.lstatSync(targetPath).isSymbolicLink())
191
+ fs.unlinkSync(targetPath);
192
+ fs.writeFileSync(targetPath, entry.data, { mode: 0o755 });
193
+ }
194
+ }
195
+ onProgress?.(i + 1, total, entry.name);
196
+ }
197
+ if (!opts.noscriptlet && install?.post_install) {
198
+ const tmpScript = `/var/lib/pacman-debian/info/${info.name}/.INSTALL`;
199
+ if (!fs.existsSync(tmpScript)) {
200
+ (0, database_1.saveScript)(info.name, '.INSTALL', `post_install() {\n${install.post_install}\n}\n`);
201
+ }
157
202
  try {
158
- (0, node_child_process_1.execSync)(`/bin/bash -c 'source "${tmpScript}" && pre_install' 2>&-`, { stdio: 'pipe' });
203
+ (0, node_child_process_1.execSync)(`/bin/bash -c 'source "${tmpScript}" && post_install' 2>&-`, { stdio: 'pipe' });
159
204
  }
160
205
  catch { }
161
206
  }
162
- }
163
- const files = [];
164
- for (const entry of dataBlocks) {
165
- const targetPath = path.resolve('/', entry.name);
166
- if (!targetPath.startsWith('/'))
167
- continue;
168
- files.push('/' + entry.name);
169
- if (entry.data) {
170
- fs.mkdirSync(path.dirname(targetPath), { recursive: true });
171
- fs.writeFileSync(targetPath, entry.data, { mode: 0o755 });
172
- }
173
- }
174
- if (!opts.noscriptlet && install?.post_install) {
175
- const tmpScript = `/var/lib/pacman-debian/info/${info.name}/.INSTALL`;
176
- if (!fs.existsSync(tmpScript)) {
177
- (0, database_1.saveScript)(info.name, '.INSTALL', `post_install() {\n${install.post_install}\n}\n`);
207
+ // Run ldconfig if package installs shared libraries
208
+ const hasSoFiles = files.some(f => /\.so(\.|$)/.test(f));
209
+ if (hasSoFiles) {
210
+ try {
211
+ (0, node_child_process_1.execSync)('/usr/sbin/ldconfig', { stdio: 'inherit' });
212
+ }
213
+ catch { }
178
214
  }
215
+ const ip = {
216
+ name: info.name, version: info.version,
217
+ architecture: info.arch || 'any',
218
+ description: info.description || '',
219
+ depends: (info.depends || []).join(', '),
220
+ conflicts: (info.conflicts || []).join(', '),
221
+ provides: (info.provides || []).join(', '),
222
+ maintainer: info.packager,
223
+ homepage: info.url,
224
+ license: (info.license || []).join(', '), pkgbase: info.base, buildDate: info.buildDate,
225
+ controlSection: 'misc', controlPriority: 'optional',
226
+ installedSize: info.installedSize ?? (info.size ? Math.ceil(info.size / 1024) : undefined),
227
+ installTime: Date.now(), reason, files, repoType: 'arch',
228
+ repo: opts.repo,
229
+ };
230
+ (0, database_1.addPackage)(db, ip);
179
231
  try {
180
- (0, node_child_process_1.execSync)(`/bin/bash -c 'source "${tmpScript}" && post_install' 2>&-`, { stdio: 'pipe' });
232
+ await (0, dpkg_compat_1.writeDpkgEntry)(ip);
181
233
  }
182
- catch { }
183
- }
184
- // Run ldconfig if package installs shared libraries
185
- const hasSoFiles = files.some(f => /\.so(\.|$)/.test(f));
186
- if (hasSoFiles) {
187
- try {
188
- (0, node_child_process_1.execSync)('/usr/sbin/ldconfig', { stdio: 'inherit' });
234
+ catch (e) {
235
+ console.error((0, i18n_1.t)('warn_failed_dpkg_status', String(e)));
189
236
  }
190
- catch { }
191
- }
192
- const ip = {
193
- name: info.name, version: info.version,
194
- architecture: info.arch || 'any',
195
- description: info.description || '',
196
- depends: (info.depends || []).join(', '),
197
- conflicts: (info.conflicts || []).join(', '),
198
- provides: (info.provides || []).join(', '),
199
- homepage: info.url,
200
- controlSection: 'unknown', controlPriority: 'optional',
201
- installedSize: info.installedSize,
202
- installTime: Date.now(), reason, files, repoType: 'arch',
203
- };
204
- (0, database_1.addPackage)(db, ip);
205
- try {
206
- (0, dpkg_compat_1.writeDpkgEntry)(ip);
237
+ (0, database_1.saveDatabase)(db);
238
+ (0, database_1.completeTransaction)(tx.id);
239
+ return true;
207
240
  }
208
- catch (e) {
209
- console.error((0, i18n_1.t)('warn_failed_dpkg_status', String(e)));
241
+ finally {
242
+ (0, dpkg_lock_1.releaseDpkgLock)();
210
243
  }
211
- (0, database_1.saveDatabase)(db);
212
- (0, database_1.completeTransaction)(tx.id);
213
- return true;
214
244
  }
215
- async function installPkgFile(filePath, reason, opts = {}) {
245
+ async function installPkgFile(filePath, reason, opts = {}, onProgress) {
216
246
  if (opts.print) {
217
247
  console.log((0, i18n_1.t)('would_install', path.basename(filePath)));
218
248
  return true;
219
249
  }
220
250
  if (filePath.endsWith('.pkg.tar.zst') || filePath.endsWith('.pkg.tar.xz') || filePath.endsWith('.pkg.tar.gz')) {
221
- return installArch(filePath, reason, opts);
251
+ return installArch(filePath, reason, opts, onProgress);
222
252
  }
223
- return installDeb(filePath, reason, opts);
253
+ return installDeb(filePath, reason, opts, onProgress);
224
254
  }
225
255
  function parseFtpUrl(url) {
226
256
  const rest = url.slice(6);
@@ -383,42 +413,70 @@ async function installPkg(target, opts = {}) {
383
413
  return false;
384
414
  }
385
415
  const cols = process.stdout.columns || 80;
386
- const barLen = Math.max(Math.floor((cols - 30) * 0.35), 8);
387
- const barDone = '#'.repeat(barLen);
416
+ const barLen = Math.max(cols - 50, 8);
417
+ const drawBar = (pct) => {
418
+ const filled = Math.round((pct / 100) * barLen);
419
+ return `[${'#'.repeat(filled)}${'-'.repeat(barLen - filled)}] ${String(pct).padStart(3)}%`;
420
+ };
388
421
  console.log((0, i18n_1.t)('packages_single', fname) + '\n');
389
422
  if (!await (0, prompt_1.confirm)((0, i18n_1.t)('confirm_proceed')))
390
- return false;
423
+ return true;
391
424
  if (opts.print) {
392
425
  console.log((0, i18n_1.t)('would_install', fname));
393
426
  return true;
394
427
  }
395
- process.stdout.write((0, i18n_1.t)('progress_loading_data', '1', '1', barDone) + '\n');
396
- process.stdout.write((0, i18n_1.t)('progress_installing_single', '1', '1', fname, barDone) + '\n');
397
- const result = await installPkgFile(localPath, 'explicit', opts);
398
- if (isUrl)
399
- try {
400
- fs.unlinkSync(localPath);
401
- }
402
- catch { }
403
- return result;
428
+ process.stdout.write(`(1/1) ${(0, i18n_1.t)('progress_loading_files_msg')} ${drawBar(0)}`);
429
+ let lastName = '';
430
+ try {
431
+ const result = await installPkgFile(localPath, 'explicit', opts, (current, total, name) => {
432
+ const pct = total > 0 ? Math.round(current / total * 100) : 100;
433
+ lastName = name;
434
+ process.stdout.write(`\r\x1b[K(1/1) ${(0, i18n_1.t)('progress_loading_files_msg')} ${name} ${drawBar(pct)}`);
435
+ });
436
+ process.stdout.write(`\r\x1b[K(1/1) installing ${fname} ${drawBar(100)}\n`);
437
+ if (isUrl)
438
+ try {
439
+ fs.unlinkSync(localPath);
440
+ }
441
+ catch { }
442
+ return result;
443
+ }
444
+ catch (error) {
445
+ process.stdout.write(`\r\x1b[K`);
446
+ console.error(`error: failed to install ${fname}${lastName ? ` near ${lastName}` : ''}: ${error.message}`);
447
+ if (isUrl)
448
+ try {
449
+ fs.unlinkSync(localPath);
450
+ }
451
+ catch { }
452
+ return false;
453
+ }
404
454
  }
405
455
  async function installPackages(targets, opts = {}) {
406
456
  (0, database_1.initDb)();
407
- // Validate targets exist
457
+ // Validate targets exist (support repo/pkgname syntax)
408
458
  const targetPkgs = [];
409
459
  for (const target of targets) {
410
- const rp = (0, repository_1.findInRepo)(target);
460
+ const sl = target.indexOf('/');
461
+ const repo = sl > 0 ? target.slice(0, sl) : undefined;
462
+ const requested = sl > 0 ? target.slice(sl + 1) : target;
463
+ const eq = requested.indexOf('=');
464
+ const name = eq >= 0 ? requested.slice(0, eq) : requested;
465
+ const version = eq >= 0 ? requested.slice(eq + 1) : undefined;
466
+ const rp = version ? (0, repository_1.findInRepoVersioned)(name, version, repo)
467
+ : (repo ? (0, repository_1.findInRepoScoped)(repo, name) : (0, repository_1.findInRepo)(name));
468
+ const displayName = target;
411
469
  if (!rp) {
412
470
  const cacheDir = '/var/cache/pacman-debian/packages';
413
471
  if (!fs.existsSync(cacheDir) || fs.readdirSync(cacheDir).length === 0) {
414
472
  console.error((0, i18n_1.t)('error_db_not_synced'));
415
- return 0;
473
+ throw new Error('package database is not synchronized');
416
474
  }
417
- console.error((0, i18n_1.t)('error_not_found', target));
418
- continue;
475
+ console.error((0, i18n_1.t)('error_not_found', displayName));
476
+ throw new Error(`target not found: ${displayName}`);
419
477
  }
420
- if (opts.needed && (0, dpkg_compat_1.dpkgHasPackage)(target)) {
421
- console.log((0, i18n_1.t)('pkg_up_to_date', target));
478
+ if (opts.needed && (0, dpkg_compat_1.dpkgHasPackage)(name)) {
479
+ console.log((0, i18n_1.t)('pkg_up_to_date', name));
422
480
  continue;
423
481
  }
424
482
  targetPkgs.push(rp);
@@ -427,15 +485,39 @@ async function installPackages(targets, opts = {}) {
427
485
  return 0;
428
486
  // Resolve dependencies
429
487
  console.log((0, i18n_1.t)('resolving_deps'));
430
- const { install: depResults, errors: depErrors } = (0, deps_1.resolveDeps)(targets);
488
+ const preferredRepos = new Map();
489
+ if (!(0, config_1.loadConfig)().notFindDepsFromCurrentRepo) {
490
+ for (const target of targets) {
491
+ const slash = target.indexOf('/');
492
+ const requested = slash > 0 ? target.slice(slash + 1) : target;
493
+ const eq = requested.indexOf('=');
494
+ const name = eq >= 0 ? requested.slice(0, eq) : requested;
495
+ if (slash > 0)
496
+ preferredRepos.set(name, [target.slice(0, slash)]);
497
+ }
498
+ }
499
+ const depTargets = targets.map(target => {
500
+ const slash = target.indexOf('/');
501
+ const prefix = slash > 0 ? target.slice(0, slash + 1) : '';
502
+ const requested = slash > 0 ? target.slice(slash + 1) : target;
503
+ const eq = requested.indexOf('=');
504
+ return prefix + (eq >= 0 ? requested.slice(0, eq) : requested);
505
+ });
506
+ const { install: depResults, errors: depErrors } = (0, deps_1.resolveDeps)(depTargets, { preferredRepos });
431
507
  for (const err of depErrors)
432
508
  console.error((0, i18n_1.t)('warn_prefix', err));
433
- if (depErrors.length > 0 && depResults.length === 0)
434
- return 0;
509
+ if (depErrors.length > 0)
510
+ throw new Error('dependency resolution failed');
435
511
  // Dedupe: deps first, then targets (Arch pacman convention)
436
512
  const allPkgs = [];
437
513
  const seen = new Set();
514
+ const targetNames = new Set(targetPkgs.map(p => p.package));
438
515
  for (const dr of depResults) {
516
+ // The explicit target below is authoritative, including an exact
517
+ // `name=version` request; do not let an unversioned dependency lookup
518
+ // replace it with the first repository match.
519
+ if (targetNames.has(dr.pkg.package))
520
+ continue;
439
521
  if (seen.has(dr.pkg.package))
440
522
  continue;
441
523
  seen.add(dr.pkg.package);
@@ -456,11 +538,29 @@ async function installPackages(targets, opts = {}) {
456
538
  if (conflicts.length > 0) {
457
539
  console.error('');
458
540
  console.error((0, i18n_1.t)('error_unresolvable_conflicts'));
459
- return 0;
541
+ throw new Error('unresolvable package conflicts detected');
460
542
  }
461
543
  const totalSize = allPkgs.reduce((s, p) => s + (p.size || 0), 0);
462
544
  const totalInst = allPkgs.reduce((s, p) => s + ((p.installedSize || 0) * 1024), 0);
463
- console.log((0, i18n_1.t)('packages_multi', String(allPkgs.length), allPkgs.map(p => p.package).join(' ')) + '\n');
545
+ const _cfg = (0, config_1.loadConfig)();
546
+ if (_cfg.verbosePkgLists) {
547
+ const cols = process.stdout.columns || 80;
548
+ const nameW = Math.max(20, Math.floor(cols * 0.3));
549
+ const verW = Math.max(16, Math.floor(cols * 0.2));
550
+ const repoW = Math.max(10, Math.floor(cols * 0.15));
551
+ console.log((0, i18n_1.t)('packages_multi', String(allPkgs.length), ''));
552
+ console.log(` ${'Name'.padEnd(nameW)} ${'Version'.padEnd(verW)} ${'Repo'.padEnd(repoW)} Size`);
553
+ console.log(` ${'─'.repeat(nameW)} ${'─'.repeat(verW)} ${'─'.repeat(repoW)} ${'─'.repeat(8)}`);
554
+ for (const p of allPkgs) {
555
+ const name = p.package.length > nameW ? p.package.slice(0, nameW - 3) + '...' : p.package;
556
+ const ver = (p.version || '').length > verW ? (p.version || '').slice(0, verW - 3) + '...' : (p.version || '');
557
+ console.log(` ${name.padEnd(nameW)} ${ver.padEnd(verW)} ${p.repo.padEnd(repoW)} ${(0, format_1.formatBytes)(p.size || 0).padStart(8)}`);
558
+ }
559
+ }
560
+ else {
561
+ console.log((0, i18n_1.t)('packages_multi', String(allPkgs.length), allPkgs.map(p => p.package).join(' ')));
562
+ }
563
+ console.log('');
464
564
  console.log((0, i18n_1.t)('total_download_size', (0, format_1.formatBytes)(totalSize).padStart(9)));
465
565
  console.log((0, i18n_1.t)('total_installed_size', (0, format_1.formatBytes)(totalInst).padStart(9)));
466
566
  console.log('');
@@ -471,11 +571,13 @@ async function installPackages(targets, opts = {}) {
471
571
  console.log((0, i18n_1.t)('would_install', `${p.package}-${p.version}`));
472
572
  return allPkgs.length;
473
573
  }
574
+ // ---- Transaction start ----
575
+ console.log((0, i18n_1.t)('processing_changes'));
474
576
  // ---- Download phase ----
475
577
  const total = allPkgs.length;
476
578
  const cols = process.stdout.columns || 80;
477
579
  const parallelN = (0, config_1.loadConfig)().parallelDownloads || 1;
478
- console.log((0, i18n_1.t)('downloading_packages'));
580
+ console.log((0, i18n_1.t)('retrieving_packages'));
479
581
  const downloaded = [];
480
582
  const startTime = Date.now();
481
583
  /** Render a right-aligned progress bar line. leftText precedes `[`, rightText follows `]`. */
@@ -487,7 +589,11 @@ async function installPackages(targets, opts = {}) {
487
589
  return line;
488
590
  };
489
591
  const nameWidth = Math.max(25, Math.floor(cols * 0.35));
592
+ let dlIdx = 0;
490
593
  const downloadOne = async (p) => {
594
+ const idx = ++dlIdx;
595
+ const digits = String(total).length;
596
+ const prefix = `(${String(idx).padStart(digits)}/${String(total).padEnd(digits)})`;
491
597
  const pkgLabel = `${p.package}-${p.version}-${p.architecture || 'any'}`;
492
598
  const displayName = pkgLabel.length > nameWidth ? pkgLabel.slice(0, nameWidth - 3) + '...' : pkgLabel;
493
599
  let finalRate = 0, prevTime = Date.now(), prevBytes = 0, smoothRate = 0;
@@ -504,11 +610,11 @@ async function installPackages(targets, opts = {}) {
504
610
  const eta = smoothRate > 0 && tot > 0 ? (tot - rec) / smoothRate : 0;
505
611
  const etaS = (0, progress_1.formatETA)(eta);
506
612
  const pct = tot > 0 ? Math.round(rec / tot * 100) : 0;
507
- const line = barLine(` ${displayName.padEnd(nameWidth)} ${dl.val.padStart(6)} ${dl.unit.padEnd(3)} ${rateStr} ${etaS} [`, `] ${String(pct).padStart(3)}%`, pct);
613
+ const line = barLine(` ${prefix} ${displayName.padEnd(nameWidth)} ${dl.val.padStart(6)} ${dl.unit.padEnd(3)} ${rateStr} ${etaS} [`, `] ${String(pct).padStart(3)}%`, pct);
508
614
  process.stdout.write(`\r${line}`);
509
615
  });
510
616
  const finalSize = (0, progress_1.humanSize)(p.size || 0, 1);
511
- const compLine = barLine(` ${displayName.padEnd(nameWidth)} ${finalSize.val.padStart(6)} ${finalSize.unit.padEnd(3)} ${(0, progress_1.formatRate)(finalRate)} ${'00:00'} [`, `] 100%`, 100);
617
+ const compLine = barLine(` ${prefix} ${displayName.padEnd(nameWidth)} ${finalSize.val.padStart(6)} ${finalSize.unit.padEnd(3)} ${(0, progress_1.formatRate)(finalRate)} ${'00:00'} [`, `] 100%`, 100);
512
618
  process.stdout.write(`\r${compLine}\n`);
513
619
  return { pkg: p, path: localPath, rate: finalRate };
514
620
  };
@@ -522,7 +628,12 @@ async function installPackages(targets, opts = {}) {
522
628
  }
523
629
  };
524
630
  const workers = Array.from({ length: Math.min(parallelN, total) }, () => doBatch());
525
- await Promise.all(workers);
631
+ try {
632
+ await Promise.all(workers);
633
+ }
634
+ catch (error) {
635
+ throw new Error(`package download failed: ${error.message}`);
636
+ }
526
637
  // 汇总行
527
638
  const totalSz = allPkgs.reduce((s, p) => s + (p.size || 0), 0);
528
639
  const elapsed = (Date.now() - startTime) / 1000;
@@ -533,7 +644,10 @@ async function installPackages(targets, opts = {}) {
533
644
  const totalLine = barLine(` ${totalLabel.padEnd(nameWidth)} ${totalSizeStr.val.padStart(6)} ${totalSizeStr.unit.padEnd(3)} ${totalRateStr} ${'00:00'} [`, `] 100%`, 100);
534
645
  process.stdout.write(totalLine + '\n');
535
646
  // ---- Pre-install checks (after download, matching real pacman order) ----
536
- const prefixStr = `(${String(total)}/${String(total)}) `;
647
+ const totalChk = downloaded.length;
648
+ const digitsChk = String(totalChk).length;
649
+ let chkIdx = 0;
650
+ const prefixChk = () => `(${String(++chkIdx).padStart(digitsChk)}/${String(totalChk).padEnd(digitsChk)})`;
537
651
  const checkMessages = [
538
652
  (0, i18n_1.t)('progress_checking_keys_msg'),
539
653
  (0, i18n_1.t)('progress_checking_integrity_msg'),
@@ -541,10 +655,11 @@ async function installPackages(targets, opts = {}) {
541
655
  (0, i18n_1.t)('progress_checking_conflicts_msg'),
542
656
  (0, i18n_1.t)('progress_checking_space_msg'),
543
657
  ];
544
- const maxMsgTw = Math.max(...checkMessages.map(m => (0, progress_1.terminalWidth)(m)));
658
+ const maxChkMsgTw = Math.max(...checkMessages.map(m => (0, progress_1.terminalWidth)(m)));
545
659
  const fmtCheck = (msg) => {
546
- const pad = maxMsgTw - (0, progress_1.terminalWidth)(msg);
547
- const line = barLine(`${prefixStr}${msg}${' '.repeat(pad)} [`, `] 100%`, 100);
660
+ const p = prefixChk();
661
+ const pad = maxChkMsgTw - (0, progress_1.terminalWidth)(msg);
662
+ const line = barLine(` ${p} ${msg}${' '.repeat(pad)} [`, `] 100%`, 100);
548
663
  process.stdout.write(line + '\n');
549
664
  };
550
665
  // 1. Keys check
@@ -564,8 +679,9 @@ async function installPackages(targets, opts = {}) {
564
679
  // 3. Load files — validate package archive format
565
680
  for (const { pkg: p, path: fp } of downloaded) {
566
681
  try {
567
- if (fp.endsWith('.deb'))
568
- (0, node_child_process_1.execSync)(`dpkg-deb --info "${fp}" 2>/dev/null`, { encoding: 'utf8', timeout: 5000 });
682
+ if (fp.endsWith('.deb')) {
683
+ (0, deb_1.parseDeb)(fp);
684
+ }
569
685
  else
570
686
  (0, node_child_process_1.execSync)(`tar -t --zstd -f "${fp}" 2>/dev/null | head -1`, { encoding: 'utf8', timeout: 5000 });
571
687
  }
@@ -575,30 +691,47 @@ async function installPackages(targets, opts = {}) {
575
691
  }
576
692
  }
577
693
  fmtCheck((0, i18n_1.t)('progress_loading_files_msg'));
694
+ if (!integrityOk)
695
+ throw new Error('package integrity check failed');
578
696
  // 4. File conflict check
579
697
  fmtCheck((0, i18n_1.t)('progress_checking_conflicts_msg'));
580
698
  // 5. Available space check
581
- try {
582
- const df = (0, node_child_process_1.execSync)('df -k /', { encoding: 'utf8', timeout: 5000 });
583
- const match = df.trim().split('\n').pop()?.match(/\s(\d+)\s+(\d+)\s+(\d+)/);
584
- if (match) {
585
- const availKb = parseInt(match[3], 10);
586
- const needKb = Math.ceil((allPkgs.reduce((s, p) => s + ((p.installedSize || 0) * 1024), 0)) / 1024);
587
- if (availKb < needKb) {
588
- console.error(`\n ERROR: not enough disk space (need ${needKb} KiB, have ${availKb} KiB)`);
589
- return 0;
699
+ const cfg = (0, config_1.loadConfig)();
700
+ if (cfg.checkSpace) {
701
+ try {
702
+ const dfPath = cfg.rootDir === '/' ? '/' : cfg.rootDir;
703
+ const df = (0, node_child_process_1.execSync)(`df -k "${dfPath}"`, { encoding: 'utf8', timeout: 5000 });
704
+ const match = df.trim().split('\n').pop()?.match(/\s(\d+)\s+(\d+)\s+(\d+)/);
705
+ if (match) {
706
+ const availKb = parseInt(match[3], 10);
707
+ const needKb = allPkgs.reduce((s, p) => s + ((p.installedSize || 0)), 0);
708
+ if (availKb < needKb) {
709
+ console.error(`\n error: not enough disk space (need ${(needKb / 1024).toFixed(1)} MiB, have ${(availKb / 1024).toFixed(1)} MiB)`);
710
+ throw new Error('not enough disk space');
711
+ }
590
712
  }
591
713
  }
714
+ catch (error) {
715
+ if (error.message === 'not enough disk space')
716
+ throw error;
717
+ }
592
718
  }
593
- catch { }
594
719
  fmtCheck((0, i18n_1.t)('progress_checking_space_msg'));
595
- // Install phase (serial for safety)
596
- for (const { pkg: p, path: localPath } of downloaded) {
597
- const isExplicit = targetPkgs.some(r => r.package === p.package);
598
- await installPkgFile(localPath, isExplicit ? (opts.asdeps ? 'dependency' : 'explicit') : 'dependency', opts);
720
+ // Hold dpkg locks for the complete system-modifying transaction.
721
+ await (0, dpkg_lock_1.acquireDpkgLock)();
722
+ try {
723
+ for (const { pkg: p, path: localPath } of downloaded) {
724
+ const isExplicit = targetPkgs.some(r => r.package === p.package);
725
+ const ok = await installPkgFile(localPath, isExplicit ? (opts.asdeps ? 'dependency' : 'explicit') : 'dependency', { ...opts, repo: p.repo });
726
+ if (!ok)
727
+ throw new Error(`failed to install ${p.package}`);
728
+ }
729
+ // Post-transaction hooks
730
+ process.stdout.write((0, i18n_1.t)('running_hooks') + '\n');
731
+ }
732
+ finally {
733
+ (0, dpkg_lock_1.releaseDpkgLock)();
599
734
  }
600
- // Post-transaction hooks
601
- process.stdout.write((0, i18n_1.t)('running_hooks') + '\n');
602
735
  return total;
603
736
  }
604
737
  //# sourceMappingURL=install.js.map