镜像自地址
https://github.com/JGZYES/ParlzPackageManger.git
已同步 2026-09-11 05:42:44 +08:00
fix: pmm self install/upgrade now takes effect immediately
- pdm_install_file: when the 'pmm' package is installed, copy the freshly built binary over the currently-running pmm path (e.g. /usr/local/bin/pmm) and clear the shell command hash, so 'pmm -v' reflects the new version without a manual 'hash -r'. Falls back to a hint when the target dir is not writable (non-root). - pmm_add_to_path: prepend PMM dirs on Windows instead of appending, so ~/.pmm/root takes priority over /usr/local/bin (matches Linux .bashrc). - release.yml: add -D_GNU_SOURCE so newer gcc exposes strdup/popen/realpath (fixes implicit-declaration build errors). - CHANGELOG/0.3.7.md
这个提交包含在:
@@ -53,7 +53,7 @@ jobs:
|
||||
mkdir -p out
|
||||
VER=${{ github.ref_type == 'tag' && github.ref_name || (github.event.inputs.version != '' && github.event.inputs.version || 'dev') }}
|
||||
VER=${VER#v}
|
||||
${{ matrix.cc }} -O2 -Wall -static -std=c11 -D_FORTIFY_SOURCE=0 -U_FORTIFY_SOURCE -DPMM_VERSION=\"$VER\" -o out/${{ matrix.bin }} \
|
||||
${{ matrix.cc }} -O2 -Wall -static -std=c11 -D_GNU_SOURCE -D_FORTIFY_SOURCE=0 -U_FORTIFY_SOURCE -DPMM_VERSION=\"$VER\" -o out/${{ matrix.bin }} \
|
||||
src/main.c src/json.c src/ini.c src/pmm.c src/http.c src/repo.c src/install.c \
|
||||
src/sha256.c src/sha1.c src/mirrors.c src/pdm.c src/out.c src/i18n.c
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# PMM v0.3.7
|
||||
|
||||
## 修复
|
||||
- **安装/升级 `pmm` 自身后「不生效」**:之前新二进制只装进 `~/.pmm/root`,从不覆盖当前正在运行的 pmm 路径,
|
||||
导致 apt 装的 `/usr/local/bin/pmm` 一直挡在前面、或升级后需 `hash -r` 才生效。现在安装 `pmm` 包时会把新二进制
|
||||
**同步覆盖到当前运行的 pmm 路径**(如 `/usr/local/bin/pmm`)并自动执行 `hash -r`,`pmm -v` 立即显示新版本。
|
||||
- Windows 上 `pmm_add_to_path` 由 **append** 改为 **prepend**:PMM 目录排在 PATH 前面,避免被 `/usr/local/bin`
|
||||
等系统目录覆盖(与 Linux 的 `~/.bashrc` 行为一致)。
|
||||
- 构建命令增加 `-D_GNU_SOURCE`,修复新版 gcc 下 `strdup`/`popen`/`realpath` 的隐式声明编译错误。
|
||||
|
||||
## 说明
|
||||
- 若运行用户无权限覆盖 `/usr/local/bin/pmm`(非 root),会打印黄色提示:新版本位于
|
||||
`~/.pmm/root/usr/local/bin/pmm`,请将其加入 PATH 并在当前 shell 运行 `hash -r`。
|
||||
+1
@@ -55,6 +55,7 @@ static const char *kBuiltinZh =
|
||||
"\"msg.checksum-ok\":\"%s 校验 OK: %s\",\"msg.checksum-mismatch\":\"校验不匹配 (%s)!\","
|
||||
"\"msg.resolving-dep\":\"正在解析依赖 %s\",\"msg.registry-ok\":\"注册表 sha256 OK: %s\","
|
||||
"\"msg.path-exists\":\"PATH 已包含 PMM 目录\",\"msg.err.registry-not-found\":\"找不到软件包 '%s'\","
|
||||
"\"msg.pmm-self-replaced\":\"pmm 已更新到 %s\",\"msg.pmm-self-hint\":\"无法覆盖 %s(需 root/管理员);新版本在 %s。请将其加入 PATH 并在当前 shell 运行 hash -r\","
|
||||
"\"msg.err.usage\":\"用法\",\"msg.err.unknown-cmd\":\"未知命令 '%s' (试试 'pmm help')\","
|
||||
"\"msg.err.download-failed\":\"下载语言包 %s 失败\",\"msg.err.invalid-locale\":\"无效语言 %s\","
|
||||
"\"msg.err.not-found\":\"找不到软件包 '%s'\",\"msg.err.failed-install\":\"安装 %s 失败\","
|
||||
|
||||
@@ -393,6 +393,51 @@ static void restore_aside(const char *target) {
|
||||
rename(old, target);
|
||||
}
|
||||
|
||||
/* Locate the freshly-installed pmm binary under `root`. Fills `out` with the
|
||||
* full path and returns 0 on success, 1 if it couldn't be found. */
|
||||
static int find_pmm_binary(const char *root, char *out, size_t outsz) {
|
||||
#ifdef _WIN32
|
||||
const char *names[] = { "pmm.exe", "pmm" };
|
||||
#else
|
||||
const char *names[] = { "pmm" };
|
||||
#endif
|
||||
const char *dirms[] = { "/bin", "/usr/local/bin", "/", NULL };
|
||||
for (int d = 0; dirms[d]; d++) {
|
||||
for (size_t k = 0; k < sizeof(names) / sizeof(names[0]); k++) {
|
||||
snprintf(out, outsz, "%s%s/%s", root, dirms[d], names[k]);
|
||||
struct stat st;
|
||||
if (stat(out, &st) == 0 && S_ISREG(st.st_mode)) return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* After installing/upgrading the `pmm` tool itself, make the newly installed
|
||||
* binary take effect immediately: copy it over the currently-running pmm
|
||||
* (so an apt/system /usr/local/bin/pmm is replaced) and clear the shell's
|
||||
* command hash so `pmm -v` reflects the new version without `hash -r`. */
|
||||
static void pmm_sync_self(const char *newbin) {
|
||||
const char *self = pmm_self_path();
|
||||
if (!self || !*self) return;
|
||||
if (path_eq_ci(newbin, self)) return; /* already the running image */
|
||||
int moved = move_self_aside(self);
|
||||
if (copy_file(newbin, self) != 0) {
|
||||
if (moved) restore_aside(self); /* put the old image back */
|
||||
pmm_warn("%s", pmm_tr_fmt("msg.pmm-self-hint", self, newbin, newbin));
|
||||
return;
|
||||
}
|
||||
if (moved) {
|
||||
char old[1500];
|
||||
snprintf(old, sizeof(old), "%s.old", self);
|
||||
remove(old); /* drop the old image */
|
||||
}
|
||||
pmm_success("%s", pmm_tr_fmt("msg.pmm-self-replaced", self));
|
||||
#ifndef _WIN32
|
||||
{ char cx[1600]; snprintf(cx, sizeof(cx), "chmod +x \"%s\" 2>/dev/null || true", self); system(cx); }
|
||||
system("hash -r 2>/dev/null || true");
|
||||
#endif
|
||||
}
|
||||
|
||||
int pdm_info(const char *pdmfile) {
|
||||
pmm_info("%s\n", base_name(pdmfile));
|
||||
/* Copy into the pm dir + chdir, then use relative names (works with both
|
||||
@@ -576,6 +621,15 @@ int pdm_install_file(const char *pdmfile) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we just installed/upgraded the pmm tool itself, make the new binary
|
||||
* take effect immediately: replace the running image and clear the hash.
|
||||
* (Otherwise an apt/system /usr/local/bin/pmm keeps shadowing it.) */
|
||||
if (pkg && strcmp(pkg, "pmm") == 0) {
|
||||
char nb[1400];
|
||||
if (find_pmm_binary(root, nb, sizeof(nb)) == 0)
|
||||
pmm_sync_self(nb);
|
||||
}
|
||||
|
||||
free(pkg); if (ver) free(ver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -393,26 +393,30 @@ void pmm_add_to_path(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* append missing dirs (bounds-safe: never let size_t underflow) */
|
||||
char next[17000] = "";
|
||||
snprintf(next, sizeof(next), "%s", cur);
|
||||
/* prepend any missing PMM dirs so they take priority over /usr/local/bin
|
||||
* (an apt/system install could otherwise shadow a pmm-managed binary). */
|
||||
char prefix[17000] = "";
|
||||
size_t plen = 0;
|
||||
int added = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!list[i][0]) continue;
|
||||
if (path_has(next, list[i], ';') || path_has(next, list[i], ':')) continue;
|
||||
size_t l = strlen(next);
|
||||
/* ensure a separator between entries */
|
||||
if (l && next[l-1] != ';' && next[l-1] != ':' && l + 1 < sizeof(next)) {
|
||||
next[l] = ';'; next[l+1] = '\0'; l++;
|
||||
}
|
||||
size_t room = sizeof(next) - l - 1;
|
||||
if (path_has(cur, list[i], ';') || path_has(cur, list[i], ':')
|
||||
|| path_has(prefix, list[i], ';') || path_has(prefix, list[i], ':')) continue;
|
||||
if (plen) { if (plen + 1 < sizeof(prefix)) prefix[plen++] = ';'; }
|
||||
size_t room = sizeof(prefix) - plen - 1;
|
||||
if (room <= 0) break; /* no space left: stop */
|
||||
snprintf(next + l, room + 1, "%s", list[i]);
|
||||
snprintf(prefix + plen, room + 1, "%s", list[i]);
|
||||
plen += strlen(list[i]);
|
||||
added++;
|
||||
pmm_info("%s", pmm_tr_fmt("msg.path-adding", list[i]));
|
||||
}
|
||||
if (!added) { pmm_info(pmm_tr("msg.path-exists")); return; }
|
||||
|
||||
/* final value: PMM dirs (prefix) then the existing startup PATH (cur).
|
||||
* Only Windows persists it (setx); Linux prepends via .bashrc below. */
|
||||
char next[17000] = "";
|
||||
snprintf(next, sizeof(next), "%s;%s", prefix, cur);
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
char cmd[17001];
|
||||
|
||||
在新工单中引用
屏蔽一个用户