镜像自地址
https://github.com/JGZYES/ParlzPackageManger.git
已同步 2026-09-11 08:52:45 +08:00
i18n: replace all user-facing strings with pmm_tr/pmm_tr_fmt
- Main/install/pdm/pmm/json user-facing messages now resolve through the .pjson language pack (pmm_tr/pmm_tr_fmt) instead of hardcoded strings. - print_help and version are standardised (PMM <ver> (<arch>)) and the help headings/descriptions/options come from the language pack. - Keep http.c download progress bar, PMM_DEBUG logs and file-writing fputs as untranslated. - zh-CN/en-US packs use %s placeholders matching the source call args. - Header files (part of the i18n feature) added; Makefile/build.bat/ci include src/i18n.c. Verified on WSL: LANG=zh-CN/en-US switches help + runtime messages between Chinese and English; compilation is clean.
这个提交包含在:
+40
-41
@@ -14,6 +14,7 @@
|
||||
#include "install.h"
|
||||
#include "pmm.h"
|
||||
#include "out.h"
|
||||
#include "i18n.h"
|
||||
#include "http.h"
|
||||
#include "json.h"
|
||||
#include "sha256.h"
|
||||
@@ -117,16 +118,15 @@ static int verify_checksums(const char *url, const char *path, const char *name)
|
||||
extract_hex(text, name, expect, sizeof(expect));
|
||||
free(text);
|
||||
if (!expect[0]) {
|
||||
pmm_warn("warning: could not parse %s checksum file\n", algos[i].ext);
|
||||
pmm_warn("%s", pmm_tr_fmt("msg.warn.parse-checksum", algos[i].ext));
|
||||
continue;
|
||||
}
|
||||
/* case-insensitive compare */
|
||||
if (strcasecmp(expect, hex) != 0) {
|
||||
pmm_error("CHECKSUM MISMATCH (%s)!\n expected: %s\n actual: %s\n",
|
||||
algos[i].ext, expect, hex);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.checksum-mismatch", algos[i].ext, expect, hex));
|
||||
return -1;
|
||||
}
|
||||
pmm_success("%s checksum OK: %s\n", algos[i].algo == 256 ? "sha256" : "sha1", hex);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.checksum-ok", algos[i].algo == 256 ? "sha256" : "sha1", hex));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -419,29 +419,29 @@ int install_file(const char *url, const char *name) {
|
||||
char **cands = mirrors_download_candidates(ml, url, &ncand);
|
||||
int ok = -1;
|
||||
for (int i = 0; i < ncand; i++) {
|
||||
pmm_info("downloading %s%s\n", cands[i],
|
||||
i < ncand - 1 ? " (mirror)" : "");
|
||||
pmm_info("%s", pmm_tr_fmt("msg.downloading", cands[i],
|
||||
i < ncand - 1 ? " (mirror)" : ""));
|
||||
if (http_download(cands[i], path) == 0) { ok = 0; break; }
|
||||
pmm_warn("download failed, trying next source...\n");
|
||||
pmm_warn("%s", pmm_tr("msg.warn.download-retry"));
|
||||
remove(path);
|
||||
}
|
||||
for (int i = 0; i < ncand; i++) free(cands[i]);
|
||||
free(cands);
|
||||
mirrors_free(ml);
|
||||
if (ok != 0) {
|
||||
pmm_error("all download sources failed: %s\n", url);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.download-failed", url));
|
||||
return -1;
|
||||
}
|
||||
pmm_success("downloaded %s\n", path);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.downloaded", path));
|
||||
|
||||
/* integrity: sha256 + sha1, verified against sidecar checksums when present */
|
||||
char hex[128];
|
||||
if (pmm_sha256_file(path, hex) == 0)
|
||||
pmm_info("sha256: %s\n", hex);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.sha256", hex));
|
||||
if (pmm_sha1_file(path, hex) == 0)
|
||||
pmm_info("sha1: %s\n", hex);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.sha1", hex));
|
||||
if (verify_checksums(url, path, name) != 0) {
|
||||
pmm_error("refusing to install: checksum verification failed\n");
|
||||
pmm_error(pmm_tr("msg.err.checksum-refuse"));
|
||||
remove(path);
|
||||
return -1;
|
||||
}
|
||||
@@ -461,10 +461,9 @@ static int install_path(const char *path, const char *name) {
|
||||
/* A bare binary (no extension) must really be a native executable for this
|
||||
* OS; otherwise refuse so the caller can fall back to the os-named asset. */
|
||||
if (strchr(bname, '.') == NULL) {
|
||||
pmm_info("verifying %s is a native %s binary...\n", bname, pmm_os_name(os));
|
||||
pmm_info("%s", pmm_tr_fmt("msg.verifying-native", bname, pmm_os_name(os)));
|
||||
if (!native_binary_ok(path, os)) {
|
||||
pmm_warn("%s is not a usable %s binary; will fall back\n",
|
||||
bname, pmm_os_name(os));
|
||||
pmm_warn("%s", pmm_tr_fmt("msg.warn.not-usable", bname, pmm_os_name(os)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -479,12 +478,12 @@ static int install_path(const char *path, const char *name) {
|
||||
/* .pdm packages are installed through the deb-like manager */
|
||||
if (has_suffix(bname, ".pdm") || has_suffix(bname, ".PDM")) {
|
||||
extern int pdm_install_file(const char *path);
|
||||
pmm_info("installing .pdm %s ...\n", bname);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.installing", bname));
|
||||
if (pdm_install_file(path) != 0) {
|
||||
pmm_error(".pdm install failed: %s\n", bname);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.failed-install", bname));
|
||||
return -1;
|
||||
}
|
||||
pmm_success("installed .pdm %s\n", bname);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.installed", bname));
|
||||
pmm_add_to_path();
|
||||
return 0;
|
||||
}
|
||||
@@ -553,7 +552,7 @@ static int install_path(const char *path, const char *name) {
|
||||
"elif command -v alien >/dev/null 2>&1; then sudo alien -i \"%s\"; "
|
||||
"else echo -e \"\\033[31m[PMM]:[ERROR]cannot unpack .rpm (need rpm/cpio)\\033[0m\" 1>&2; exit 1; fi",
|
||||
path, path, path);
|
||||
if (system(cmd) != 0) { pmm_error("rpm install failed\n"); return -1; }
|
||||
if (system(cmd) != 0) { pmm_error(pmm_tr("msg.err.failed-install")); return -1; }
|
||||
(void)dcmd; (void)ct;
|
||||
#else
|
||||
/* create the (possibly multi-level) stage dir first; pmm_cpio_unpack
|
||||
@@ -563,18 +562,18 @@ static int install_path(const char *path, const char *name) {
|
||||
char mkstag[1400];
|
||||
snprintf(mkstag, sizeof(mkstag), "mkdir -p \"%s\"", fstage);
|
||||
if (system(mkstag) != 0) {
|
||||
pmm_error("cannot create rpm stage dir: %s\n", fstage);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.rpm-stage", fstage));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* unpack into stage (no sudo needed; stage is user-writable) */
|
||||
if (pmm_cpio_unpack_cmd(fstage, dcmd) != 0) {
|
||||
pmm_error("rpm payload decompress/cpio failed (need %s)\n", dc);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.rpm-decompress", dc));
|
||||
return -1;
|
||||
}
|
||||
/* copy the unpacked payload into /, then clean up */
|
||||
if (system(cmd) != 0) {
|
||||
pmm_error("failed to copy rpm payload into /\n");
|
||||
pmm_error(pmm_tr("msg.err.rpm-copy"));
|
||||
return -1;
|
||||
}
|
||||
(void)ct;
|
||||
@@ -636,12 +635,12 @@ static int install_path(const char *path, const char *name) {
|
||||
snprintf(cmd, sizeof(cmd), "cp -f \"%s\" \"%s/\" 2>/dev/null || true", path, dest);
|
||||
}
|
||||
|
||||
pmm_info("installing %s ...\n", bname);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.installing", bname));
|
||||
if (run_cmd_quiet(cmd) != 0) {
|
||||
pmm_error("install command failed: %s\n", cmd);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.failed-install", cmd));
|
||||
return -1;
|
||||
}
|
||||
pmm_success("installed %s\n", bname);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.installed", bname));
|
||||
pmm_add_to_path();
|
||||
return 0;
|
||||
}
|
||||
@@ -649,11 +648,11 @@ static int install_path(const char *path, const char *name) {
|
||||
/* Install a local file by its extension — e.g. `pmm install -dpkg foo.deb`
|
||||
* (Linux) or `pmm install -msi foo.msi` (Windows). Returns 0 on success. */
|
||||
int install_local_file(const char *path) {
|
||||
if (!path || !*path) { pmm_error("empty file path\n"); return -1; }
|
||||
if (!path || !*path) { pmm_error(pmm_tr("msg.err.empty-path")); return -1; }
|
||||
FILE *chk = fopen(path, "rb");
|
||||
if (!chk) { pmm_error("cannot open file: %s\n", path); return -1; }
|
||||
if (!chk) { pmm_error("%s", pmm_tr_fmt("msg.err.cannot-open", path)); return -1; }
|
||||
fclose(chk);
|
||||
pmm_info("installing local file %s\n", path);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.installing-file", path));
|
||||
return install_path(path, path);
|
||||
}
|
||||
|
||||
@@ -805,7 +804,7 @@ int install_from_registry(const char *name, const char *spec, const char *mirror
|
||||
if (!seen[i] && ml->items[i].registry && *ml->items[i].registry)
|
||||
bases[nb++] = ml->items[i].registry;
|
||||
|
||||
if (nb == 0) { pmm_error("no registry mirrors\n"); mirrors_free(ml); return -1; }
|
||||
if (nb == 0) { pmm_error(pmm_tr("msg.err.no-registry-mirror")); mirrors_free(ml); return -1; }
|
||||
|
||||
/* fetch the <pkg>.json latest pointer (carries the variants list) */
|
||||
char url[2048];
|
||||
@@ -814,7 +813,7 @@ int install_from_registry(const char *name, const char *spec, const char *mirror
|
||||
char *used_base = NULL;
|
||||
for (int i = 0; i < nb; i++) {
|
||||
snprintf(url, sizeof(url), "%s/%s.json", bases[i], name);
|
||||
pmm_info("looking up %s in mirror %s\n", name, bases[i]);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.looking-up", name, bases[i]));
|
||||
body = http_get(url, &status);
|
||||
if (getenv("PMM_DEBUG")) fprintf(stderr, "[reg] %s -> body=%s status=%d\n",
|
||||
bases[i], body ? "set" : "NULL", status);
|
||||
@@ -825,14 +824,14 @@ int install_from_registry(const char *name, const char *spec, const char *mirror
|
||||
free(body); body = NULL;
|
||||
}
|
||||
if (!body) {
|
||||
pmm_error("package '%s' not found in any registry mirror\n", name);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.registry-not-found", name));
|
||||
mirrors_free(ml);
|
||||
return -1;
|
||||
}
|
||||
JsonValue *meta = json_parse(body);
|
||||
free(body);
|
||||
if (!meta || meta->type != JSON_OBJECT) {
|
||||
pmm_error("bad registry entry for '%s' (%s)\n", name, used_base);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.bad-entry", name, used_base));
|
||||
json_free(meta);
|
||||
mirrors_free(ml);
|
||||
return -1;
|
||||
@@ -870,19 +869,19 @@ int install_from_registry(const char *name, const char *spec, const char *mirror
|
||||
const char *s = json_str(v, "sha256"); free(want_sha); want_sha = s ? strdup(s) : NULL; }
|
||||
}
|
||||
if (!chosen) {
|
||||
pmm_error("no version of '%s' for os=%s arch=%s%s%s\n", name, osn, arch,
|
||||
(spec && *spec) ? " satisfying '" : "", (spec && *spec) ? spec : "");
|
||||
pmm_error("%s", pmm_tr_fmt("msg.no-version", name, osn, arch,
|
||||
(spec && *spec)) ? " satisfying '" : "", (spec && *spec) ? spec : "");
|
||||
json_free(meta); mirrors_free(ml); return -1;
|
||||
}
|
||||
pmm_info("selected %s@%s (os=%s arch=%s)\n", name, chosen, osn, arch);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.selected", name, chosen, osn, arch));
|
||||
} else {
|
||||
/* legacy single-platform entry */
|
||||
dl = json_str(meta, "url"); file = json_str(meta, "file");
|
||||
const char *s = json_str(meta, "sha256"); want_sha = s ? strdup(s) : NULL;
|
||||
pmm_info("selected %s@%s (os=%s)\n", name, json_str(meta, "version"), osn);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.selected", name, json_str(meta, "version")), osn);
|
||||
}
|
||||
if (!dl) {
|
||||
pmm_error("registry entry for '%s' has no url\n", name);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.registry-entry-no-url", name));
|
||||
json_free(meta); mirrors_free(ml); return -1;
|
||||
}
|
||||
char *url_cp = strdup(dl);
|
||||
@@ -898,12 +897,12 @@ int install_from_registry(const char *name, const char *spec, const char *mirror
|
||||
snprintf(path, sizeof(path), "%s/%s", cache, file_cp);
|
||||
if (pmm_sha256_file(path, hex) == 0) {
|
||||
if (strcasecmp(want_sha, hex) != 0) {
|
||||
pmm_error("CHECKSUM MISMATCH (%s registry entry)!\n"
|
||||
" expected: %s\n actual: %s\n", name, want_sha, hex);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.checksum-mismatch",
|
||||
" expected: %s\n actual: %s\n", name, want_sha, hex));
|
||||
remove(path);
|
||||
rc = -1;
|
||||
} else {
|
||||
pmm_success("registry sha256 OK: %s\n", hex);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.registry-ok", hex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -917,6 +916,6 @@ static int install_dep_spec(const char *depstr) {
|
||||
for (int i = 0; i < dep_seen_n; i++)
|
||||
if (strcmp(dep_seen[i], name) == 0) return 0; /* cycle / duplicate */
|
||||
if (dep_seen_n < 128) dep_seen[dep_seen_n++] = strdup(name);
|
||||
pmm_info("resolving dependency %s%s%s\n", name, spec[0] ? " " : "", spec);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.resolving-dep", name, spec[0] ? " " : "", spec));
|
||||
return install_from_registry(name, spec[0] ? spec : NULL, NULL);
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,6 +1,7 @@
|
||||
/* json.c - minimal recursive-descent JSON parser (no external deps) */
|
||||
#include "json.h"
|
||||
#include "out.h"
|
||||
#include "i18n.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -12,7 +13,7 @@ static JsonValue *parse_value(Parser *ps);
|
||||
|
||||
static JsonValue *jnew(JsonType t) {
|
||||
JsonValue *v = calloc(1, sizeof(JsonValue));
|
||||
if (!v) { pmm_error("out of memory\n"); exit(1); }
|
||||
if (!v) { pmm_error(pmm_tr("msg.err.oom")); exit(1); }
|
||||
v->type = t;
|
||||
return v;
|
||||
}
|
||||
@@ -36,7 +37,7 @@ static void jadd(JsonValue *v, char *key, JsonValue *item) {
|
||||
if (v->type == JSON_OBJECT)
|
||||
v->keys = realloc(v->keys, v->capacity * sizeof(char *));
|
||||
if (!v->items || (v->type == JSON_OBJECT && !v->keys)) {
|
||||
pmm_error("out of memory\n"); exit(1);
|
||||
pmm_error(pmm_tr("msg.err.oom")); exit(1);
|
||||
}
|
||||
}
|
||||
if (v->type == JSON_OBJECT) v->keys[v->count] = key;
|
||||
@@ -48,7 +49,7 @@ static void skip_ws(Parser *ps) {
|
||||
}
|
||||
|
||||
static void fail(const char *msg) {
|
||||
pmm_error("JSON parse error: %s\n", msg);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.json-parse", msg));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
+61
-79
@@ -209,13 +209,13 @@ static char *registry_fetch(const char *rel, int *outstatus) {
|
||||
|
||||
/* pmm search <keyword> — list registry packages matching keyword. */
|
||||
static int cmd_search(int argc, char **argv) {
|
||||
if (argc < 1) { pmm_error("usage: pmm search <keyword>\n"); return 1; }
|
||||
if (argc < 1) { pmm_error("%s", pmm_tr("msg.err.usage")); return 1; }
|
||||
int status = 0;
|
||||
char *body = registry_fetch("packages.json", &status);
|
||||
if (!body) { pmm_error("no registry index (packages.json) available\n"); return 1; }
|
||||
if (!body) { pmm_error("%s", pmm_tr("msg.err.no-registry-index")); return 1; }
|
||||
JsonValue *root = json_parse(body);
|
||||
free(body);
|
||||
if (!root || root->type != JSON_ARRAY) { pmm_error("bad registry index\n"); json_free(root); return 1; }
|
||||
if (!root || root->type != JSON_ARRAY) { pmm_error("%s", pmm_tr("msg.err.bad-registry-index")); json_free(root); return 1; }
|
||||
const char *kw = argv[0];
|
||||
int found = 0;
|
||||
for (int i = 0; i < root->count; i++) {
|
||||
@@ -225,7 +225,7 @@ static int cmd_search(int argc, char **argv) {
|
||||
if (ci_contains(name, kw)) { printf(" %s\n", name); found++; }
|
||||
}
|
||||
json_free(root);
|
||||
if (!found) pmm_info("no package matches '%s'\n", kw);
|
||||
if (!found) pmm_info("%s", pmm_tr_fmt("msg.no-match", kw));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -245,15 +245,15 @@ static int cmd_info(int argc, char **argv) {
|
||||
char rel[512]; snprintf(rel, sizeof(rel), "%s.json", pkg);
|
||||
int status = 0;
|
||||
char *body = registry_fetch(rel, &status);
|
||||
if (!body) { pmm_error("package '%s' not found in registry\n", pkg); return 1; }
|
||||
if (!body) { pmm_error("%s", pmm_tr_fmt("msg.err.not-found", pkg)); return 1; }
|
||||
JsonValue *root = json_parse(body);
|
||||
free(body);
|
||||
if (!root || root->type != JSON_OBJECT) { pmm_error("bad registry entry '%s'\n", pkg); json_free(root); return 1; }
|
||||
if (!root || root->type != JSON_OBJECT) { pmm_error("%s", pmm_tr_fmt("msg.err.bad-entry", pkg)); json_free(root); return 1; }
|
||||
const char *name = json_str(root, "name");
|
||||
const char *ver = json_str(root, "version");
|
||||
pmm_info("%s%s%s\n", name ? name : pkg, ver ? " " : "", ver ? ver : "");
|
||||
const char *desc = json_str(root, "description");
|
||||
if (desc) pmm_info("description: %s\n", desc);
|
||||
if (desc) pmm_info("%s", pmm_tr_fmt("msg.description", desc));
|
||||
JsonValue *vr = json_get(root, "variants");
|
||||
if (vr && vr->count > 0) {
|
||||
printf(" versions:\n");
|
||||
@@ -366,7 +366,7 @@ static int cmd_upgrade(int argc, char **argv) {
|
||||
|
||||
char files[128][1400];
|
||||
int nfiles = list_info_files(db, files, 128);
|
||||
if (nfiles == 0) { pmm_info("no installed packages.\n"); return 0; }
|
||||
if (nfiles == 0) { pmm_info("%s", pmm_tr("msg.no-installed")); return 0; }
|
||||
|
||||
int upgraded = 0, checked = 0;
|
||||
for (int fi = 0; fi < nfiles; fi++) {
|
||||
@@ -387,7 +387,7 @@ static int cmd_upgrade(int argc, char **argv) {
|
||||
char rel[512]; snprintf(rel, sizeof(rel), "%s.json", pkg);
|
||||
int status = 0;
|
||||
char *body = registry_fetch(rel, &status);
|
||||
if (!body) { pmm_warn("skipping %s: no registry entry\n", pkg); continue; }
|
||||
if (!body) { pmm_warn("%s", pmm_tr_fmt("msg.skipping-no-registry", pkg)); continue; }
|
||||
JsonValue *root = json_parse(body);
|
||||
free(body);
|
||||
if (!root) continue;
|
||||
@@ -418,7 +418,7 @@ static int cmd_upgrade(int argc, char **argv) {
|
||||
json_free(root);
|
||||
if (!best) continue;
|
||||
|
||||
if (cmp_version(bestbuf, curver) <= 0) { pmm_info("%s %s is up to date (latest %s)\n", pkg, curver, bestbuf); continue; }
|
||||
if (cmp_version(bestbuf, curver) <= 0) { pmm_info("%s", pmm_tr_fmt("msg.up-to-date", pkg, curver, bestbuf)); continue; }
|
||||
|
||||
pmm_info("%s: %s -> %s\n", pkg, curver, bestbuf);
|
||||
if (!yes) {
|
||||
@@ -429,13 +429,13 @@ static int cmd_upgrade(int argc, char **argv) {
|
||||
if (!(ans[0] == 'y' || ans[0] == 'Y')) continue;
|
||||
}
|
||||
if (install_from_registry(pkg, NULL, mirror.name) == 0) { upgraded++; }
|
||||
else pmm_error("failed to upgrade %s\n", pkg);
|
||||
else pmm_error("%s", pmm_tr_fmt("msg.err.failed-install", pkg));
|
||||
}
|
||||
|
||||
free(cfg.registry_url); free(cfg.mirror_name);
|
||||
free(mirror.name); free(mirror.api_base);
|
||||
if (checked == 0) pmm_info("no installed .pdm packages.\n");
|
||||
else pmm_success("upgraded %d package(s).\n", upgraded);
|
||||
if (checked == 0) pmm_info("%s", pmm_tr("msg.no-installed"));
|
||||
else pmm_success("%s", pmm_tr_fmt("msg.upgraded", upgraded));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -470,7 +470,7 @@ static int cmd_update(void) {
|
||||
pmm_error("bad registry index\n"); if (root) json_free(root); free(body); return 1;
|
||||
}
|
||||
int total = root->count, ok = 0;
|
||||
if (total == 0) { pmm_info("registry index is empty.\n"); json_free(root); free(body); return 0; }
|
||||
if (total == 0) { pmm_info("%s", pmm_tr("msg.registry-empty")); json_free(root); free(body); return 0; }
|
||||
save_registry_cache("packages.json", body);
|
||||
json_free(root);
|
||||
|
||||
@@ -491,7 +491,7 @@ static int cmd_update(void) {
|
||||
json_free(r2);
|
||||
}
|
||||
free(body);
|
||||
pmm_success("updated registry index: %d/%d packages cached.\n", ok, total);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.registry-updated", ok, total));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -500,9 +500,9 @@ static int cmd_verify(int argc, char **argv) {
|
||||
if (argc < 1) { pmm_error("usage: pmm verify <file>\n"); return 1; }
|
||||
const char *file = argv[0];
|
||||
char hex[128];
|
||||
if (pmm_sha256_file(file, hex) == 0) pmm_success("sha256 %s %s\n", hex, file);
|
||||
else { pmm_error("cannot read %s\n", file); return 1; }
|
||||
if (pmm_sha1_file(file, hex) == 0) pmm_success("sha1 %s %s\n", hex, file);
|
||||
if (pmm_sha256_file(file, hex) == 0) pmm_success("%s", pmm_tr_fmt("msg.sha256", hex, file));
|
||||
else { pmm_error("%s", pmm_tr_fmt("msg.err.cannot-read", file)); return 1; }
|
||||
if (pmm_sha1_file(file, hex) == 0) pmm_success("%s", pmm_tr_fmt("msg.sha1", hex, file));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -541,7 +541,7 @@ static void rm_tree(const char *dir) {
|
||||
static int cmd_cache_clean(void) {
|
||||
char dir[1024];
|
||||
pmm_cache_dir(dir, sizeof(dir));
|
||||
pmm_info("cleaning cache %s\n", dir);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.cleaning-cache", dir));
|
||||
rm_tree(dir);
|
||||
return 0;
|
||||
}
|
||||
@@ -564,7 +564,7 @@ static int cmd_install_git(int argc, char **argv, const char *flag) {
|
||||
if (strcmp(argv[i], "--host") == 0 && i + 1 < argc) {
|
||||
host = host_from_name(argv[++i]);
|
||||
if (host == HOST_UNKNOWN) {
|
||||
pmm_error("unknown host '%s'\n", argv[i]);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.unknown-host", argv[i]));
|
||||
return 1;
|
||||
}
|
||||
} else if ((strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--branch") == 0) && i + 1 < argc) {
|
||||
@@ -598,8 +598,7 @@ static int cmd_install_git(int argc, char **argv, const char *flag) {
|
||||
"(tried gitea/gitlab/github shapes)\n", repo);
|
||||
if (!asset) {
|
||||
if (host != HOST_AUTO)
|
||||
pmm_error("no suitable %s asset found in latest release of %s\n",
|
||||
pmm_os_name(os), repo);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.no-suitable-asset", pmm_os_name(os)), repo);
|
||||
repo_close(ctx);
|
||||
return 1;
|
||||
}
|
||||
@@ -614,7 +613,7 @@ static int cmd_install_git(int argc, char **argv, const char *flag) {
|
||||
if (sub) {
|
||||
ReleaseAsset *fb = repo_asset_matching(ctx, os, sub);
|
||||
if (fb && strcmp(fb->name, asset->name) != 0) {
|
||||
pmm_warn("retrying with %s (%s)\n", fb->name, pmm_os_name(os));
|
||||
pmm_warn("%s", pmm_tr_fmt("msg.retrying-asset", fb->name, pmm_os_name(os)));
|
||||
rc = install_file(fb->url, fb->name);
|
||||
repo_asset_free(fb);
|
||||
}
|
||||
@@ -655,7 +654,7 @@ static int cmd_mirror(int argc, char **argv) {
|
||||
* (apt-style source check). Reports priority + ok/fail for each source. */
|
||||
if (strcmp(argv[0], "check") == 0) {
|
||||
Ini *ini = ini_load(path);
|
||||
if (!ini || !ini->head) { pmm_error("no mirrors configured (use: pmm mirror add)\n"); ini_free(ini); return 1; }
|
||||
if (!ini || !ini->head) { pmm_error("%s", pmm_tr("msg.err.no-mirror")); ini_free(ini); return 1; }
|
||||
printf("checking registry mirrors...\n");
|
||||
char lastsec[512] = "";
|
||||
int reachable = 0, total = 0;
|
||||
@@ -689,10 +688,10 @@ static int cmd_mirror(int argc, char **argv) {
|
||||
}
|
||||
if (strcmp(argv[0], "add") == 0 && argc >= 3) {
|
||||
FILE *f = fopen(path, "a");
|
||||
if (!f) { pmm_error("cannot write %s\n", path); return 1; }
|
||||
if (!f) { pmm_error("%s", pmm_tr_fmt("msg.err.cannot-write", path)); return 1; }
|
||||
fprintf(f, "\n[%s]\napi = %s\n", argv[1], argv[2]);
|
||||
fclose(f);
|
||||
pmm_success("mirror '%s' added\n", argv[1]);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.mirror-added", argv[1]));
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[0], "use") == 0 && argc >= 2) {
|
||||
@@ -709,20 +708,20 @@ static int cmd_mirror(int argc, char **argv) {
|
||||
fclose(rf);
|
||||
}
|
||||
FILE *wf = fopen(cfgpath, "w");
|
||||
if (!wf) { pmm_error("cannot write %s\n", cfgpath); return 1; }
|
||||
if (!wf) { pmm_error("%s", pmm_tr_fmt("msg.err.cannot-write", cfgpath)); return 1; }
|
||||
int wrote = 0;
|
||||
for (int i = 0; i < n; i++) fputs(lines[i], wf);
|
||||
fprintf(wf, "mirror = %s\n", argv[1]);
|
||||
(void)wrote;
|
||||
fclose(wf);
|
||||
pmm_success("active mirror set to '%s'\n", argv[1]);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.mirror-active", argv[1]));
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[0], "remove") == 0 && argc >= 2) {
|
||||
Ini *ini = ini_load(path);
|
||||
if (!ini) { pmm_error("no mirror file\n"); return 1; }
|
||||
if (!ini) { pmm_error("%s", pmm_tr("msg.err.no-mirror-file")); return 1; }
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) { pmm_error("cannot write %s\n", path); ini_free(ini); return 1; }
|
||||
if (!f) { pmm_error("%s", pmm_tr_fmt("msg.err.cannot-write", path)); ini_free(ini); return 1; }
|
||||
char cursec[512] = "";
|
||||
for (IniEntry *e = ini->head; e; e = e->next) {
|
||||
if (strcmp(e->section, cursec) != 0) {
|
||||
@@ -735,48 +734,31 @@ static int cmd_mirror(int argc, char **argv) {
|
||||
}
|
||||
fclose(f);
|
||||
ini_free(ini);
|
||||
pmm_success("mirror '%s' removed\n", argv[1]);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.mirror-removed", argv[1]));
|
||||
return 0;
|
||||
}
|
||||
pmm_error("usage: pmm mirror list|add|use|remove|check ...\n");
|
||||
pmm_error("%s", pmm_tr("msg.err.usage"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_help(void) {
|
||||
printf("PMM %s (%s)\n\n", PMM_VERSION, pmm_detect_arch());
|
||||
printf("usage:\n");
|
||||
printf(" pmm install <pkg> install from registry mirrors (apt-style)\n");
|
||||
printf(" pmm install <file.pdm> install a local .pdm package\n");
|
||||
printf(" pmm install <pkg> [pkg2 ...] install several packages\n");
|
||||
printf(" pmm install <file.deb|file.msi|file.rpm|...> install a local package file\n");
|
||||
printf(" pmm install -dpkg <x.deb> install a .deb (Linux)\n");
|
||||
printf(" pmm install -msi <x.msi> install an .msi (Windows)\n");
|
||||
printf(" pmm install -rpm <x.rpm> install an .rpm (any Linux, incl. Debian/RPM)\n");
|
||||
printf(" pmm install <https://...> install a file from a URL\n");
|
||||
printf(" pmm search <keyword> list registry packages matching keyword\n");
|
||||
printf(" pmm info <package|file.pdm> registry/local package info\n");
|
||||
printf(" pmm verify <file> print sha256/sha1 of a package file\n");
|
||||
printf(" pmm pack <dir> [out.pdm] pack a folder into a .pdm\n");
|
||||
printf(" pmm list list installed packages\n");
|
||||
printf(" pmm remove <pkg> uninstall a package\n");
|
||||
printf(" pmm self-update update the pmm tool itself\n");
|
||||
printf(" pmm update refresh the registry index (apt-style)\n");
|
||||
printf(" pmm upgrade [--yes] upgrade all installed packages\n");
|
||||
printf(" pmm install --git <repo-url.git> any git host, API auto-detected\n");
|
||||
printf(" pmm install --github <owner/repo> GitHub latest release\n");
|
||||
printf(" pmm install --gitlab <owner/repo> GitLab latest release\n");
|
||||
printf(" pmm install --gitea <url/owner/repo> Gitea/Forgejo (incl. self-hosted)\n");
|
||||
printf(" [--host github|gitlab|gitea|forgejo]\n");
|
||||
printf(" pmm mirror list|add <n> <api>|use <n>|remove <n>|check\n");
|
||||
printf(" pmm list list installed files\n");
|
||||
printf(" pmm version | help\n\n");
|
||||
printf("options:\n");
|
||||
printf(" -p<drive> install under <DRIVE>:\\\\.pmm (e.g. -pd -> D:\\\\.pmm, -pc -> C:\\\\.pmm)\n");
|
||||
printf(" 第一个 -p 会被记住,后续命令无需再写;用 -pc 切回 C 盘\n");
|
||||
printf(" --no-color omit ANSI colours even on a terminal (PMM_NO_COLOR=1 too)\n");
|
||||
printf(" -q, --quiet only print errors/warnings (suppress info/success)\n");
|
||||
printf(" --verbose print extra detail\n\n");
|
||||
printf("config: <base>/pmm.json | pmm.ini | pmm.conf (base = <drive>:\\\\.pmm 或 ~/.pmm)\n");
|
||||
printf("%s\n", pmm_tr("help.usage"));
|
||||
printf(" %-32s%s\n", "pmm install <pkg> ", pmm_tr("desc.install"));
|
||||
printf(" %-32s%s\n", "pmm search <keyword> ", pmm_tr("desc.search"));
|
||||
printf(" %-32s%s\n", "pmm info <pkg|file.pdm> ", pmm_tr("desc.info"));
|
||||
printf(" %-32s%s\n", "pmm remove <pkg> ", pmm_tr("desc.remove"));
|
||||
printf(" %-32s%s\n", "pmm update ", pmm_tr("desc.update"));
|
||||
printf(" %-32s%s\n", "pmm upgrade [--yes] ", pmm_tr("desc.upgrade"));
|
||||
printf(" %-32s%s\n", "pmm mirror ... ", pmm_tr("desc.mirror"));
|
||||
printf(" %-32s%s\n", "pmm self-update ", pmm_tr("desc.self-update"));
|
||||
printf(" %-32s%s\n", "pmm version | help ", pmm_tr("desc.help"));
|
||||
printf("\n%s\n", pmm_tr("help.options"));
|
||||
printf(" %-32s%s\n", "-p<drive> ", pmm_tr("opt.p-drive"));
|
||||
printf(" %-32s%s\n", "--no-color ", pmm_tr("opt.no-color"));
|
||||
printf(" %-32s%s\n", "-q, --quiet", pmm_tr("opt.quiet"));
|
||||
printf(" %-32s%s\n", "--verbose ", pmm_tr("opt.verbose"));
|
||||
printf("\nconfig: <base>/pmm.json | pmm.ini | pmm.conf (base = <drive>:\\\\.pmm 或 ~/.pmm)\n");
|
||||
printf("mirrors: <base>/mirror.ini | mirror.conf\n");
|
||||
printf("asset mapping: windows=exe/msi/zip/7z linux=deb/rpm/appimage/tar.* macos=dmg/pkg\n");
|
||||
}
|
||||
@@ -791,7 +773,7 @@ static void mkdir_p_local(char *path) {
|
||||
/* pmm setting lang ... */
|
||||
static int cmd_setting(int argc, char **argv) {
|
||||
if (argc < 1 || strcmp(argv[0], "lang") != 0) {
|
||||
pmm_error("usage: pmm setting lang -l | <locale>\n");
|
||||
pmm_error("%s", pmm_tr("msg.err.usage"));
|
||||
return 1;
|
||||
}
|
||||
char dir[1024];
|
||||
@@ -824,16 +806,16 @@ static int cmd_setting(int argc, char **argv) {
|
||||
}
|
||||
|
||||
/* install / activate a specific locale: requires a value */
|
||||
if (argc < 2) { pmm_error("usage: pmm setting lang <locale>\n"); return 1; }
|
||||
if (argc < 2) { pmm_error("%s", pmm_tr("msg.err.usage")); return 1; }
|
||||
const char *loc = argv[1];
|
||||
if (strchr(loc, '/') || strchr(loc, '\\') || strstr(loc, "..")) { pmm_error("invalid locale: %s\n", loc); return 1; }
|
||||
if (strchr(loc, '/') || strchr(loc, '\\') || strstr(loc, "..")) { pmm_error("%s", pmm_tr_fmt("msg.err.invalid-locale", loc)); return 1; }
|
||||
|
||||
/* pick a registry base for the language pack */
|
||||
MirrorList *ml = mirrors_load();
|
||||
const char *base = NULL;
|
||||
for (int i = 0; i < ml->count; i++)
|
||||
if (ml->items[i].registry && *ml->items[i].registry) { base = ml->items[i].registry; break; }
|
||||
if (!base) { pmm_error("no registry mirror configured\n"); mirrors_free(ml); return 1; }
|
||||
if (!base) { pmm_error("%s", pmm_tr("msg.err.no-registry-mirror")); mirrors_free(ml); return 1; }
|
||||
|
||||
char url[2048];
|
||||
snprintf(url, sizeof(url), "%s/lang/%s.pjson", base, loc);
|
||||
@@ -841,7 +823,7 @@ static int cmd_setting(int argc, char **argv) {
|
||||
char out[1400];
|
||||
snprintf(out, sizeof(out), "%s/%s.pjson", langdir, loc);
|
||||
if (http_download(url, out) != 0) {
|
||||
pmm_error("failed to download language pack %s\n", loc);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.download-failed", loc));
|
||||
mirrors_free(ml); return 1;
|
||||
}
|
||||
mirrors_free(ml);
|
||||
@@ -859,14 +841,14 @@ static int cmd_setting(int argc, char **argv) {
|
||||
fclose(rf);
|
||||
}
|
||||
FILE *wf = fopen(cfgpath, "w");
|
||||
if (!wf) { pmm_error("cannot write %s\n", cfgpath); return 1; }
|
||||
if (!wf) { pmm_error("%s", pmm_tr_fmt("msg.err.cannot-write", cfgpath)); return 1; }
|
||||
for (int i = 0; i < nn; i++) fputs(lines[i], wf);
|
||||
fprintf(wf, "language = %s\n", loc);
|
||||
fclose(wf);
|
||||
|
||||
pmm_lang_set_locale(loc);
|
||||
pmm_lang_load(out);
|
||||
pmm_success("language set to '%s'\n", loc);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.lang-set", loc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -978,7 +960,7 @@ int main(int argc, char **argv) {
|
||||
if (strcmp(argv[1], "setting") == 0) return cmd_setting(argc - 2, argv + 2);
|
||||
/* pmm remove <pkg> (also used by the Windows "Uninstall" registration) */
|
||||
if (strcmp(argv[1], "remove") == 0) {
|
||||
if (argc < 3) { pmm_error("usage: pmm remove <pkg>\n"); return 1; }
|
||||
if (argc < 3) { pmm_error("%s", pmm_tr("msg.err.usage")); return 1; }
|
||||
return pdm_remove(argv[2]) == 0 ? 0 : 1;
|
||||
}
|
||||
/* pmm self-update: install the latest 'pmm' tool package (auto os+arch) */
|
||||
@@ -1060,7 +1042,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
size_t la = strlen(pkg);
|
||||
if (la > 4 && (strcmp(pkg + la - 4, ".pdm") == 0 || strcmp(pkg + la - 4, ".PDM") == 0)) {
|
||||
if (pdm_install_file(pkg) == 0) ok++; else pmm_error("failed to install %s\n", pkg);
|
||||
if (pdm_install_file(pkg) == 0) ok++; else pmm_error("%s", pmm_tr_fmt("msg.err.failed-install", pkg));
|
||||
continue;
|
||||
}
|
||||
/* direct URL install: pmm install https://.../foo.zip
|
||||
@@ -1072,14 +1054,14 @@ int main(int argc, char **argv) {
|
||||
else if (forced == 2) bn = "download.msi";
|
||||
else if (forced == 3) bn = "download.rpm";
|
||||
if (install_file(pkg, bn) == 0) ok++;
|
||||
else pmm_error("failed to install %s\n", pkg);
|
||||
else pmm_error("%s", pmm_tr_fmt("msg.err.failed-install", pkg));
|
||||
continue;
|
||||
}
|
||||
/* local file install: forced -dpkg/-msi, or an existing installer file
|
||||
* (e.g. `pmm install foo.deb` / `pmm install foo.msi`) */
|
||||
if (forced == 1 || forced == 2 || forced == 3 || has_installer_ext(pkg)) {
|
||||
if (install_local_file(pkg) == 0) ok++;
|
||||
else pmm_error("failed to install %s\n", pkg);
|
||||
else pmm_error("%s", pmm_tr_fmt("msg.err.failed-install", pkg));
|
||||
continue;
|
||||
}
|
||||
if (install_from_registry(pkg, spec[0] ? spec : NULL, mirror.name) == 0) ok++;
|
||||
@@ -1091,7 +1073,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
if (strcmp(argv[1], "pack") == 0) {
|
||||
if (argc < 3) {
|
||||
pmm_error("usage: pmm pack <dir> [output.pdm]\n");
|
||||
pmm_error("%s", pmm_tr("msg.err.usage"));
|
||||
return 1;
|
||||
}
|
||||
return pdm_pack(argv[2], argc >= 4 ? argv[3] : NULL) == 0 ? 0 : 1;
|
||||
@@ -1101,13 +1083,13 @@ int main(int argc, char **argv) {
|
||||
return cmd_search(argc - 2, argv + 2);
|
||||
if (strcmp(argv[1], "cache") == 0) {
|
||||
if (argc >= 3 && strcmp(argv[2], "clean") == 0) return cmd_cache_clean();
|
||||
pmm_error("usage: pmm cache clean\n"); return 1;
|
||||
pmm_error("%s", pmm_tr("msg.err.usage")); return 1;
|
||||
}
|
||||
if (strcmp(argv[1], "info") == 0)
|
||||
return cmd_info(argc - 2, argv + 2);
|
||||
if (strcmp(argv[1], "verify") == 0)
|
||||
return cmd_verify(argc - 2, argv + 2);
|
||||
|
||||
pmm_error("unknown command '%s' (try 'pmm help')\n", argv[1]);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.unknown-cmd", argv[1]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "pdm.h"
|
||||
#include "pmm.h"
|
||||
#include "out.h"
|
||||
#include "i18n.h"
|
||||
#include "install.h"
|
||||
#include "sha256.h"
|
||||
#include <stdio.h>
|
||||
@@ -137,13 +138,13 @@ int pdm_pack(const char *dir, const char *out) {
|
||||
snprintf(cp_, sizeof(cp_), "%s/pdm-control", dir);
|
||||
char *control = read_file(cp_, NULL);
|
||||
if (!control) {
|
||||
pmm_error("%s has no pdm-control file\n", dir);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.no-control", dir));
|
||||
return -1;
|
||||
}
|
||||
char *pkg = control_get(control, "Package");
|
||||
char *ver = control_get(control, "Version");
|
||||
if (!pkg || !*pkg) {
|
||||
pmm_error("pdm-control missing 'Package:' field\n");
|
||||
pmm_error(pmm_tr("msg.err.no-package"));
|
||||
free(control); return -1;
|
||||
}
|
||||
if (!ver || !*ver) ver = strdup("0.0.0");
|
||||
@@ -164,13 +165,13 @@ int pdm_pack(const char *dir, const char *out) {
|
||||
|
||||
/* control.tar.gz (contains pdm-control; packed from the source dir) */
|
||||
snprintf(cmd, sizeof(cmd), "tar -czf \"%s/control.tar.gz\" -C \"%s\" pdm-control", stage, dir);
|
||||
if (system(cmd) != 0) { pmm_error("tar (control) failed\n"); rmtree(stage); return -1; }
|
||||
if (system(cmd) != 0) { pmm_error(pmm_tr("msg.err.tar-control")); rmtree(stage); return -1; }
|
||||
|
||||
/* data.tar.gz (everything except pdm-control and the scratch dir) */
|
||||
snprintf(cmd, sizeof(cmd),
|
||||
"tar -czf \"%s/data.tar.gz\" -C \"%s\" --exclude pdm-control --exclude %s .",
|
||||
stage, dir, stage);
|
||||
if (system(cmd) != 0) { pmm_error("tar (data) failed\n"); rmtree(stage); return -1; }
|
||||
if (system(cmd) != 0) { pmm_error(pmm_tr("msg.err.tar-data")); rmtree(stage); return -1; }
|
||||
|
||||
/* sha256sums of the two members */
|
||||
char sums_path[1100], hex[128];
|
||||
@@ -189,9 +190,9 @@ int pdm_pack(const char *dir, const char *out) {
|
||||
snprintf(cmd, sizeof(cmd), "tar -cf \"%s\" -C \"%s\" control.tar.gz data.tar.gz sha256sums", out, stage);
|
||||
int rc = system(cmd);
|
||||
rmtree(stage);
|
||||
if (rc != 0) { pmm_error("failed to write %s\n", out); return -1; }
|
||||
if (rc != 0) { pmm_error("%s", pmm_tr_fmt("msg.err.cannot-write", out)); return -1; }
|
||||
|
||||
pmm_success("packed %s (%s %s) -> %s\n", dir, pkg, ver, out);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.packed", dir, pkg, ver, out));
|
||||
free(control); free(pkg);
|
||||
if (strcmp(ver, "0.0.0") != 0) free(ver);
|
||||
return 0;
|
||||
@@ -374,7 +375,7 @@ int pdm_info(const char *pdmfile) {
|
||||
|
||||
int pdm_install_file(const char *pdmfile) {
|
||||
if (!ends_with(pdmfile, ".pdm")) {
|
||||
pmm_error("'%s' is not a .pdm file\n", pdmfile);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.not-pdm", pdmfile));
|
||||
return -1;
|
||||
}
|
||||
char home[1024], db[1024], root[1024], cmd[2600];
|
||||
@@ -394,11 +395,11 @@ int pdm_install_file(const char *pdmfile) {
|
||||
char tmpname[1400], tmprel[] = "_pmm_install.pdm";
|
||||
snprintf(tmpname, sizeof(tmpname), "%s/_pmm_install.pdm", home);
|
||||
if (copy_file(pdmfile, tmpname) != 0) {
|
||||
pmm_error("cannot read %s\n", pdmfile);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.cannot-read", pdmfile));
|
||||
return -1;
|
||||
}
|
||||
if (chdir_save(home) != 0) { remove(tmpname); return -1; }
|
||||
if (system(NULL) == 0) { pmm_error("cannot run tar\n"); chdir_restore(); remove(tmpname); return -1; }
|
||||
if (system(NULL) == 0) { pmm_error(pmm_tr("msg.err.no-tar")); chdir_restore(); remove(tmpname); return -1; }
|
||||
|
||||
const char *stage = "installed/.stage";
|
||||
rmtree(stage);
|
||||
@@ -407,7 +408,7 @@ int pdm_install_file(const char *pdmfile) {
|
||||
/* extract members (all relative) */
|
||||
snprintf(cmd, sizeof(cmd), "tar -xf \"%s\" -C \"%s\"", tmprel, stage);
|
||||
if (system(cmd) != 0) {
|
||||
pmm_error("not a valid .pdm archive: %s\n", pdmfile);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.bad-archive", pdmfile));
|
||||
chdir_restore(); remove(tmpname); return -1;
|
||||
}
|
||||
|
||||
@@ -421,21 +422,21 @@ int pdm_install_file(const char *pdmfile) {
|
||||
char mp[1200];
|
||||
snprintf(mp, sizeof(mp), "installed/.stage/%s", fname);
|
||||
if (pmm_sha256_file(mp, hex) != 0 || strcasecmp(hex, expect) != 0) {
|
||||
pmm_error("CHECKSUM MISMATCH for %s in %s\n", fname, pdmfile);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.checksum-mismatch", fname, pdmfile));
|
||||
fclose(sf); chdir_restore(); remove(tmpname); return -1;
|
||||
}
|
||||
}
|
||||
fclose(sf);
|
||||
pmm_success("sha256 checksums OK\n");
|
||||
pmm_success(pmm_tr("msg.checksum-ok"));
|
||||
} else {
|
||||
pmm_warn("warning: no sha256sums member, skipping integrity check\n");
|
||||
pmm_warn(pmm_tr("msg.warn.no-checksum"));
|
||||
}
|
||||
|
||||
/* read control */
|
||||
snprintf(cmd, sizeof(cmd), "tar -xzOf \"%s/control.tar.gz\" pdm-control", stage);
|
||||
FILE *cf = PMM_POPEN_READ(cmd);
|
||||
if (!cf) {
|
||||
pmm_error("missing control.tar.gz in %s\n", pdmfile);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.no-control-tar", pdmfile));
|
||||
chdir_restore(); remove(tmpname); return -1;
|
||||
}
|
||||
char ctl[4096];
|
||||
@@ -448,7 +449,7 @@ int pdm_install_file(const char *pdmfile) {
|
||||
char *pkg = control_get(ctl, "Package");
|
||||
char *ver = control_get(ctl, "Version");
|
||||
if (!pkg || !*pkg) {
|
||||
pmm_error("package has no Package: field\n");
|
||||
pmm_error(pmm_tr("msg.err.no-package"));
|
||||
chdir_restore(); remove(tmpname); return -1;
|
||||
}
|
||||
|
||||
@@ -456,7 +457,7 @@ int pdm_install_file(const char *pdmfile) {
|
||||
const char *tgt = flat ? "." : "root";
|
||||
snprintf(cmd, sizeof(cmd), "tar -xzf \"%s/data.tar.gz\" -C \"%s\"", stage, tgt);
|
||||
if (system(cmd) != 0) {
|
||||
pmm_error("data extraction failed\n");
|
||||
pmm_error(pmm_tr("msg.err.extract"));
|
||||
chdir_restore(); remove(tmpname); return -1;
|
||||
}
|
||||
|
||||
@@ -487,7 +488,7 @@ int pdm_install_file(const char *pdmfile) {
|
||||
}
|
||||
PMM_PCLOSE_READ(tf);
|
||||
} else {
|
||||
pmm_warn("warning: could not record file list\n");
|
||||
pmm_warn(pmm_tr("msg.warn.no-filelist"));
|
||||
}
|
||||
fclose(dbf);
|
||||
}
|
||||
@@ -554,7 +555,7 @@ int pdm_remove(const char *name) {
|
||||
long len = 0;
|
||||
char *info = read_file(ipath, &len);
|
||||
if (!info) {
|
||||
pmm_error("package '%s' is not installed\n", name);
|
||||
pmm_error("%s", pmm_tr_fmt("msg.err.not-installed", name));
|
||||
return -1;
|
||||
}
|
||||
char *files = strstr(info, "Files:\n");
|
||||
@@ -582,7 +583,7 @@ int pdm_remove(const char *name) {
|
||||
}
|
||||
remove(ipath);
|
||||
free(info);
|
||||
pmm_success("removed %s (%d files)\n", name, n);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.removed", name, n));
|
||||
pmm_reg_uninstall_clear(name); /* drop it from Installed Apps */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* pmm.c - platform & config-dir helpers */
|
||||
#include "pmm.h"
|
||||
#include "out.h"
|
||||
#include "i18n.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -130,7 +131,7 @@ void pmm_set_install_drive(const char *letter) {
|
||||
mkdir_p(dir);
|
||||
FILE *f = fopen(state, "w");
|
||||
if (f) { fprintf(f, "%c", c); fclose(f); }
|
||||
pmm_success("install drive set to %c:\n", c);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.drive-set", c));
|
||||
}
|
||||
|
||||
void pmm_set_install_path(const char *path) {
|
||||
@@ -140,7 +141,7 @@ void pmm_set_install_path(const char *path) {
|
||||
size_t l = strlen(g_base_path);
|
||||
while (l > 1 && (g_base_path[l-1] == '/' || g_base_path[l-1] == '\\')) g_base_path[--l] = '\0';
|
||||
mkdir_p(g_base_path);
|
||||
pmm_success("install path set to %s\n", g_base_path);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.path-set", g_base_path));
|
||||
}
|
||||
int pmm_flat_mode(void) { return g_base_path[0] ? 1 : 0; }
|
||||
|
||||
@@ -408,9 +409,9 @@ void pmm_add_to_path(void) {
|
||||
if (room <= 0) break; /* no space left: stop */
|
||||
snprintf(next + l, room + 1, "%s", list[i]);
|
||||
added++;
|
||||
pmm_info("adding to PATH: %s\n", list[i]);
|
||||
pmm_info("%s", pmm_tr_fmt("msg.path-adding", list[i]));
|
||||
}
|
||||
if (!added) { pmm_info("PATH already contains PMM dirs\n"); return; }
|
||||
if (!added) { pmm_info(pmm_tr("msg.path-exists")); return; }
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
@@ -418,7 +419,7 @@ void pmm_add_to_path(void) {
|
||||
/* drive letters and ';' are fine for setx; quote the value */
|
||||
snprintf(cmd, sizeof(cmd), "setx Path \"%s\" >nul 2>&1", next);
|
||||
system(cmd);
|
||||
pmm_success("PATH updated for new shells (reopen a terminal or run: setx) (user-level)\n");
|
||||
pmm_success(pmm_tr("msg.path-updated"));
|
||||
}
|
||||
#else
|
||||
{
|
||||
@@ -433,7 +434,7 @@ void pmm_add_to_path(void) {
|
||||
fclose(f);
|
||||
}
|
||||
(void)she;
|
||||
pmm_success("updated %s (reload your shell)\n", rcp);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.path-reload", rcp));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -514,10 +515,9 @@ int pmm_reg_uninstall(const char *pkg, const char *ver, const char *pub,
|
||||
int rc = system(cmd);
|
||||
remove(ps1);
|
||||
if (rc != 0)
|
||||
pmm_warn("warning: could not register '%s' in Installed Apps\n", pkg);
|
||||
pmm_warn("%s", pmm_tr_fmt("msg.warn.no-register", pkg));
|
||||
else
|
||||
pmm_success("registered '%s' %s in Installed Apps (uninstall via pmm remove %s)\n",
|
||||
pkg, ver ? ver : "", pkg);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.registered", pkg, ver ? ver : "", pkg));
|
||||
return rc == 0 ? 0 : -1;
|
||||
#endif
|
||||
}
|
||||
@@ -532,6 +532,6 @@ void pmm_reg_uninstall_clear(const char *pkg) {
|
||||
"%%SystemRoot%%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NoProfile -Command \"Remove-Item -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s' -Recurse -Force -ErrorAction SilentlyContinue\" 2>nul",
|
||||
pkg);
|
||||
system(cmd);
|
||||
pmm_success("removed '%s' from Installed Apps\n", pkg);
|
||||
pmm_success("%s", pmm_tr_fmt("msg.removed", pkg));
|
||||
#endif
|
||||
}
|
||||
|
||||
+83
-36
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"help.banner": "PMM {ver} ({arch})",
|
||||
"help.banner": "PMM %s (%s)",
|
||||
"help.usage": "usage:",
|
||||
"help.commands": "commands:",
|
||||
"help.options": "options:",
|
||||
@@ -30,43 +30,90 @@
|
||||
"opt.no-color": "omit ANSI colours on a terminal (PMM_NO_COLOR=1 too)",
|
||||
"opt.quiet": "only print errors/warnings (suppress info/success)",
|
||||
"opt.verbose": "print extra detail",
|
||||
"msg.looking-up": "looking up {name} in mirror {mirror}",
|
||||
"msg.selected": "selected {name}@{version} (os={os} arch={arch})",
|
||||
"msg.downloading": "downloading {url}",
|
||||
"msg.downloaded": "downloaded {path}",
|
||||
"msg.sha256": "sha256: {hex}",
|
||||
"msg.sha1": "sha1: {hex}",
|
||||
"msg.installing": "installing {name} ...",
|
||||
"msg.installed": "installed {name}",
|
||||
"msg.removed": "removed {name} ({count} files)",
|
||||
"msg.checksum-ok": "{algo} checksum OK: {hex}",
|
||||
"msg.checksum-mismatch": "CHECKSUM MISMATCH ({algo})!\n expected: {expected}\n actual: {actual}",
|
||||
"msg.registry-ok": "registry sha256 OK: {hex}",
|
||||
"msg.registry-not-found": "package '{name}' not found in any registry mirror",
|
||||
"msg.no-version": "no version of '{name}' for os={os} arch={arch} satisfying '{spec}'",
|
||||
"msg.up-to-date": "{name} {cur} is up to date (latest {latest})",
|
||||
"msg.upgrading": "{name}: {cur} -> {latest}",
|
||||
"msg.upgraded": "upgraded {count} package(s).",
|
||||
"msg.looking-up": "looking up %s in mirror %s",
|
||||
"msg.selected": "selected %s@%s (os=%s arch=%s)",
|
||||
"msg.downloading": "downloading %s",
|
||||
"msg.downloaded": "downloaded %s",
|
||||
"msg.sha256": "sha256: %s",
|
||||
"msg.sha1": "sha1: %s",
|
||||
"msg.installing": "installing %s ...",
|
||||
"msg.installing-file": "installing local file %s",
|
||||
"msg.installed": "installed %s",
|
||||
"msg.removed": "removed %s (%d files)",
|
||||
"msg.packed": "packed %s (%s %s) -> %s",
|
||||
"msg.checksum-ok": "%s checksum OK: %s",
|
||||
"msg.checksum-mismatch": "CHECKSUM MISMATCH (%s)!\n expected: %s\n actual: %s",
|
||||
"msg.registry-ok": "registry sha256 OK: %s",
|
||||
"msg.registry-not-found": "package '%s' not found in any registry mirror",
|
||||
"msg.no-version": "no version of '%s' for os=%s arch=%s satisfying '%s'",
|
||||
"msg.up-to-date": "%s %s is up to date (latest %s)",
|
||||
"msg.upgrading": "%s: %s -> %s",
|
||||
"msg.upgraded": "upgraded %d package(s).",
|
||||
"msg.no-installed": "no installed packages.",
|
||||
"msg.registry-updated": "updated registry index: {ok}/{total} packages cached.",
|
||||
"msg.skipping-no-registry": "skipping {name}: no registry entry",
|
||||
"msg.err.not-found": "package '{name}' not found",
|
||||
"msg.err.usage": "usage: {usage}",
|
||||
"msg.err.unknown-cmd": "unknown command '{cmd}' (try 'pmm help')",
|
||||
"msg.err.failed-install": "failed to install {name}",
|
||||
"msg.err.failed-remove": "failed to uninstall {name}",
|
||||
"msg.registry-updated": "updated registry index: %d/%d packages cached.",
|
||||
"msg.skipping-no-registry": "skipping %s: no registry entry",
|
||||
"msg.no-match": "no package matches '%s'",
|
||||
"msg.description": "description: %s",
|
||||
"msg.cleaning-cache": "cleaning cache %s",
|
||||
"msg.drive-set": "install drive set to %c:",
|
||||
"msg.path-set": "install path set to %s",
|
||||
"msg.path-adding": "adding to PATH: %s",
|
||||
"msg.path-exists": "PATH already contains PMM dirs",
|
||||
"msg.path-updated": "PATH updated for new shells (reopen a terminal or run: setx) (user-level)",
|
||||
"msg.path-reload": "updated %s (reload your shell)",
|
||||
"msg.registered": "registered '%s' %s in Installed Apps (uninstall via pmm remove %s)",
|
||||
"msg.unregistered": "removed '%s' from Installed Apps",
|
||||
"msg.mirror-added": "mirror '%s' added",
|
||||
"msg.mirror-active": "active mirror set to '%s'",
|
||||
"msg.mirror-removed": "mirror '%s' removed",
|
||||
"msg.lang-set": "language set to '%s'",
|
||||
"msg.empty-path": "empty file path",
|
||||
"msg.verifying-native": "verifying %s is a native %s binary...",
|
||||
"msg.resolving-dep": "resolving dependency %s%s%s",
|
||||
"msg.err.usage": "usage:",
|
||||
"msg.err.not-found": "package '%s' not found",
|
||||
"msg.err.not-installed": "package '%s' is not installed",
|
||||
"msg.err.unknown-cmd": "unknown command '%s' (try 'pmm help')",
|
||||
"msg.err.failed-install": "failed to install %s",
|
||||
"msg.err.cannot-write": "cannot write %s",
|
||||
"msg.err.cannot-read": "cannot read %s",
|
||||
"msg.err.cannot-open": "cannot open file: %s",
|
||||
"msg.err.invalid-locale": "invalid language pack: %s",
|
||||
"msg.err.download-failed": "failed to download language pack %s",
|
||||
"msg.err.no-registry-mirror": "no registry mirror configured. Add to ~/.pmm/mirror.ini",
|
||||
"msg.err.cannot-write": "cannot write {path}",
|
||||
"msg.err.cannot-open": "cannot open file: {path}",
|
||||
"msg.err.empty-path": "empty file path",
|
||||
"msg.err.invalid-locale": "invalid language pack: {locale}",
|
||||
"msg.err.download-failed": "failed to download language pack {locale}",
|
||||
"msg.lang-set": "language set to '{locale}'",
|
||||
"msg.api-unreachable": "could not reach a known release API for {repo}",
|
||||
"msg.no-suitable-asset": "no suitable {os} asset found in latest release of {repo}",
|
||||
"msg.retrying-asset": "retrying with {name} ({os})",
|
||||
"msg.err.no-mirror": "no mirrors configured (use: pmm mirror add)",
|
||||
"msg.err.no-mirror-file": "no mirror file",
|
||||
"msg.err.no-registry-index": "no registry index (packages.json) available",
|
||||
"msg.err.bad-registry-index": "bad registry index",
|
||||
"msg.err.bad-entry": "bad registry entry '%s'",
|
||||
"msg.err.no-control": "%s has no pdm-control file",
|
||||
"msg.err.no-package": "pdm-control missing 'Package:' field",
|
||||
"msg.err.tar-control": "tar (control) failed",
|
||||
"msg.err.tar-data": "tar (data) failed",
|
||||
"msg.err.not-pdm": "'%s' is not a .pdm file",
|
||||
"msg.err.no-tar": "cannot run tar",
|
||||
"msg.err.bad-archive": "not a valid .pdm archive: %s",
|
||||
"msg.err.no-control-tar": "missing control.tar.gz in %s",
|
||||
"msg.err.extract": "data extraction failed",
|
||||
"msg.err.oom": "out of memory",
|
||||
"msg.err.json-parse": "JSON parse error: %s",
|
||||
"msg.err.unknown-host": "unknown host '%s'",
|
||||
"msg.err.no-suitable-asset": "no suitable %s asset found in latest release of %s",
|
||||
"msg.err.checksum-refuse": "refusing to install: checksum verification failed",
|
||||
"msg.err.registry-entry-no-url": "registry entry for '%s' has no url",
|
||||
"msg.err.rpm-stage": "cannot create rpm stage dir: %s",
|
||||
"msg.err.rpm-decompress": "rpm payload decompress/cpio failed (need %s)",
|
||||
"msg.err.rpm-copy": "failed to copy rpm payload into /",
|
||||
"msg.warn.parse-checksum": "warning: could not parse %s checksum file",
|
||||
"msg.warn.download-retry": "download failed, trying next source...",
|
||||
"msg.warn.not-usable": "%s is not a usable %s binary; will fall back",
|
||||
"msg.warn.no-checksum": "warning: no sha256sums member, skipping integrity check",
|
||||
"msg.warn.no-filelist": "warning: could not record file list",
|
||||
"msg.warn.no-register": "warning: could not register '%s' in Installed Apps",
|
||||
"msg.api-unreachable": "could not reach a known release API for %s",
|
||||
"msg.retrying-asset": "retrying with %s (%s)",
|
||||
"mirror.sources": "mirrors:",
|
||||
"mirror.checking": "checking registry mirrors...",
|
||||
"mirror.result": "result: {ok}/{total} sources reachable",
|
||||
"lang.packs-in": "language packs in {dir}:"
|
||||
"mirror.result": "result: %d/%d sources reachable",
|
||||
"lang.packs-in": "language packs in %s:"
|
||||
}
|
||||
|
||||
+83
-36
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"help.banner": "PMM {ver} ({arch})",
|
||||
"help.banner": "PMM %s (%s)",
|
||||
"help.usage": "用法:",
|
||||
"help.commands": "命令:",
|
||||
"help.options": "选项:",
|
||||
@@ -30,43 +30,90 @@
|
||||
"opt.no-color": "在终端上省略 ANSI 颜色(PMM_NO_COLOR=1 也可)",
|
||||
"opt.quiet": "只打印错误 / 警告(抑制 info / success)",
|
||||
"opt.verbose": "打印更多细节",
|
||||
"msg.looking-up": "在镜像 {mirror} 中查找 {name}",
|
||||
"msg.selected": "已选择 {name}@{version} (os={os} arch={arch})",
|
||||
"msg.downloading": "下载 {url}",
|
||||
"msg.downloaded": "已下载 {path}",
|
||||
"msg.sha256": "sha256: {hex}",
|
||||
"msg.sha1": "sha1: {hex}",
|
||||
"msg.installing": "正在安装 {name} ...",
|
||||
"msg.installed": "已安装 {name}",
|
||||
"msg.removed": "已卸载 {name} ({count} 个文件)",
|
||||
"msg.checksum-ok": "{algo} 校验 OK: {hex}",
|
||||
"msg.checksum-mismatch": "校验不匹配 ({algo})!\n 期望: {expected}\n 实际: {actual}",
|
||||
"msg.registry-ok": "注册表 sha256 OK: {hex}",
|
||||
"msg.registry-not-found": "在任一注册表镜像中找不到软件包 '{name}'",
|
||||
"msg.no-version": "没有满足 '{spec}' 的 {name} 版本 (os={os} arch={arch})",
|
||||
"msg.up-to-date": "{name} {cur} 已是最新 (最新 {latest})",
|
||||
"msg.upgrading": "{name}: {cur} -> {latest}",
|
||||
"msg.upgraded": "已升级 {count} 个软件包。",
|
||||
"msg.looking-up": "在镜像 %s 中查找 %s",
|
||||
"msg.selected": "已选择 %s@%s (os=%s arch=%s)",
|
||||
"msg.downloading": "下载 %s",
|
||||
"msg.downloaded": "已下载 %s",
|
||||
"msg.sha256": "sha256: %s",
|
||||
"msg.sha1": "sha1: %s",
|
||||
"msg.installing": "正在安装 %s ...",
|
||||
"msg.installing-file": "正在安装本地文件 %s",
|
||||
"msg.installed": "已安装 %s",
|
||||
"msg.removed": "已卸载 %s (%d 个文件)",
|
||||
"msg.packed": "已打包 %s (%s %s) -> %s",
|
||||
"msg.checksum-ok": "%s 校验 OK: %s",
|
||||
"msg.checksum-mismatch": "校验不匹配 (%s)!\n 期望: %s\n 实际: %s",
|
||||
"msg.registry-ok": "注册表 sha256 OK: %s",
|
||||
"msg.registry-not-found": "在任一注册表镜像中找不到软件包 '%s'",
|
||||
"msg.no-version": "没有满足 '%s' 的 %s 版本 (os=%s arch=%s)",
|
||||
"msg.up-to-date": "%s %s 已是最新 (最新 %s)",
|
||||
"msg.upgrading": "%s: %s -> %s",
|
||||
"msg.upgraded": "已升级 %d 个软件包。",
|
||||
"msg.no-installed": "没有已安装的软件包。",
|
||||
"msg.registry-updated": "注册表索引已更新: {ok}/{total} 个软件包已缓存。",
|
||||
"msg.skipping-no-registry": "跳过 {name}: 没有注册表条目",
|
||||
"msg.err.not-found": "找不到软件包 '{name}'",
|
||||
"msg.err.usage": "用法: {usage}",
|
||||
"msg.err.unknown-cmd": "未知命令 '{cmd}'(试试 'pmm help')",
|
||||
"msg.err.failed-install": "安装 {name} 失败",
|
||||
"msg.err.failed-remove": "卸载 {name} 失败",
|
||||
"msg.registry-updated": "注册表索引已更新: %d/%d 个软件包已缓存。",
|
||||
"msg.skipping-no-registry": "跳过 %s: 没有注册表条目",
|
||||
"msg.no-match": "没有匹配 '%s' 的软件包",
|
||||
"msg.description": "描述: %s",
|
||||
"msg.cleaning-cache": "正在清理缓存 %s",
|
||||
"msg.drive-set": "安装盘符已设为 %c:",
|
||||
"msg.path-set": "安装路径已设为 %s",
|
||||
"msg.path-adding": "正在添加到 PATH: %s",
|
||||
"msg.path-exists": "PATH 已包含 PMM 目录",
|
||||
"msg.path-updated": "PATH 已更新(新终端生效,或运行 setx)(用户级)",
|
||||
"msg.path-reload": "已更新 %s(请重新加载 shell)",
|
||||
"msg.registered": "已在已安装应用中注册 '%s' %s(通过 pmm remove %s 卸载)",
|
||||
"msg.unregistered": "已从已安装应用移除 '%s'",
|
||||
"msg.mirror-added": "镜像源 '%s' 已添加",
|
||||
"msg.mirror-active": "当前镜像源已设为 '%s'",
|
||||
"msg.mirror-removed": "镜像源 '%s' 已移除",
|
||||
"msg.lang-set": "语言已设为 '%s'",
|
||||
"msg.empty-path": "文件路径为空",
|
||||
"msg.verifying-native": "正在验证 %s 是否为可用的 %s 二进制...",
|
||||
"msg.resolving-dep": "正在解析依赖 %s%s%s",
|
||||
"msg.err.usage": "用法:",
|
||||
"msg.err.not-found": "找不到软件包 '%s'",
|
||||
"msg.err.not-installed": "软件包 '%s' 未安装",
|
||||
"msg.err.unknown-cmd": "未知命令 '%s'(试试 'pmm help')",
|
||||
"msg.err.failed-install": "安装 %s 失败",
|
||||
"msg.err.cannot-write": "无法写入 %s",
|
||||
"msg.err.cannot-read": "无法读取 %s",
|
||||
"msg.err.cannot-open": "无法打开文件: %s",
|
||||
"msg.err.invalid-locale": "无效的语言包: %s",
|
||||
"msg.err.download-failed": "下载语言包 %s 失败",
|
||||
"msg.err.no-registry-mirror": "没有配置注册表镜像。请添加到 ~/.pmm/mirror.ini",
|
||||
"msg.err.cannot-write": "无法写入 {path}",
|
||||
"msg.err.cannot-open": "无法打开文件: {path}",
|
||||
"msg.err.empty-path": "文件路径为空",
|
||||
"msg.err.invalid-locale": "无效的语言: {locale}",
|
||||
"msg.err.download-failed": "下载语言包 {locale} 失败",
|
||||
"msg.lang-set": "语言已设为 '{locale}'",
|
||||
"msg.api-unreachable": "无法访问已知的发布 API: {repo}",
|
||||
"msg.no-suitable-asset": "在最新的 {repo} 发布中没找到合适的 {os} 资源",
|
||||
"msg.retrying-asset": "改用 {name} ({os}) 重试",
|
||||
"msg.err.no-mirror": "没有配置镜像源(使用: pmm mirror add)",
|
||||
"msg.err.no-mirror-file": "没有镜像配置文件",
|
||||
"msg.err.no-registry-index": "没有可用注册表索引 (packages.json)",
|
||||
"msg.err.bad-registry-index": "注册表索引格式错误",
|
||||
"msg.err.bad-entry": "软件包 '%s' 的注册表条目错误",
|
||||
"msg.err.no-control": "没有 pdm-control 文件: %s",
|
||||
"msg.err.no-package": "pdm-control 缺少 'Package:' 字段",
|
||||
"msg.err.tar-control": "tar(control)失败",
|
||||
"msg.err.tar-data": "tar(data)失败",
|
||||
"msg.err.not-pdm": "'%s' 不是 .pdm 文件",
|
||||
"msg.err.no-tar": "无法运行 tar",
|
||||
"msg.err.bad-archive": "不是有效的 .pdm 归档: %s",
|
||||
"msg.err.no-control-tar": "缺失 control.tar.gz: %s",
|
||||
"msg.err.extract": "数据解压失败",
|
||||
"msg.err.oom": "内存不足",
|
||||
"msg.err.json-parse": "JSON 解析错误: %s",
|
||||
"msg.err.unknown-host": "未知的主机 '%s'",
|
||||
"msg.err.no-suitable-asset": "在最新发布中找不到适用于 %s 的资源 %s",
|
||||
"msg.err.checksum-refuse": "拒绝安装: 校验和验证失败",
|
||||
"msg.err.registry-entry-no-url": "软件包 '%s' 的注册表条目没有 url",
|
||||
"msg.err.rpm-stage": "无法创建 rpm 解包目录: %s",
|
||||
"msg.err.rpm-decompress": "rpm payload 解压/cpio 失败(需要 %s)",
|
||||
"msg.err.rpm-copy": "无法把 rpm payload 复制到 /",
|
||||
"msg.warn.parse-checksum": "警告: 无法解析 %s 校验文件",
|
||||
"msg.warn.download-retry": "下载失败,尝试下一个源...",
|
||||
"msg.warn.not-usable": "%s 不是可用的 %s 二进制; 将回退",
|
||||
"msg.warn.no-checksum": "警告: 没有 sha256sums 成员,跳过完整性校验",
|
||||
"msg.warn.no-filelist": "警告: 无法记录文件列表",
|
||||
"msg.warn.no-register": "警告: 无法在已安装应用中注册 '%s'",
|
||||
"msg.api-unreachable": "无法访问已知的发布 API: %s",
|
||||
"msg.retrying-asset": "改用 %s (%s) 重试",
|
||||
"mirror.sources": "镜像源:",
|
||||
"mirror.checking": "正在检查注册表镜像源...",
|
||||
"mirror.result": "结果: {ok}/{total} 个镜像源可达",
|
||||
"lang.packs-in": "{dir} 中的语言包:"
|
||||
"mirror.result": "结果: %d/%d 个镜像源可达",
|
||||
"lang.packs-in": "%s 中的语言包:"
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户