diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 12fb9b1..3efdf72 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,6 +42,47 @@ jobs: 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 + - name: Package installers + run: | + sudo apt-get update >/dev/null 2>&1 + sudo apt-get install -y zip dpkg-dev xxd >/dev/null 2>&1 || true + VER=${{ github.ref_type == 'tag' && github.ref_name || 'dev' }} + VER=${VER#v} + + # -- install.sh helper (uploaded to the release, also served at /install.sh) + cp web/install.sh out/install.sh + + # -- Windows: ZIP + self-extracting installer (embeds pmm.exe) + if [ -f out/pmm.exe ]; then + ( cd out && zip -q "pmm-${VER}-windows-amd64.zip" pmm.exe ) + xxd -i -n pmm_payload out/pmm.exe > payload.h + x86_64-w64-mingw32-gcc -O2 -I . -DPMM_SETUP_VER=\"$VER\" \ + -o "out/pmm-setup-${VER}.exe" src/win_setup.c -luser32 -ladvapi32 + rm -f payload.h + fi + + # -- Linux: .deb + if [ -f out/pmm ]; then + rm -rf pkg && mkdir -p pkg/DEBIAN pkg/usr/local/bin + cp out/pmm pkg/usr/local/bin/pmm + cat > pkg/DEBIAN/control < +Installed-Size: $(du -k pkg/usr/local/bin/pmm | cut -f1) +Description: ParlzPackageManager (PMM) - cross-platform C package manager + A cross-platform (Windows/Linux/macOS) package manager written in C, with + apt-style multi-mirror (mirror.ini), git release installs, .pdm packages + and SHA-256/SHA-1 verification. +EOF + ( cd pkg/usr/local/bin && md5sum pmm > ../DEBIAN/md5sums ) + dpkg-deb --build --root-owner-group pkg "out/pmm_${VER}_amd64.deb" + rm -rf pkg + fi + - name: Upload artifact uses: actions/upload-artifact@v4 with: @@ -53,7 +94,6 @@ jobs: if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v2 with: - files: | - out/pmm${{ matrix.ext }} + files: out/* generate_release_notes: true name: PMM ${{ github.ref_name }} diff --git a/.gitignore b/.gitignore index e2e66cd..24a7179 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,8 @@ # still matches after the mirror moved to web/mirror/. !**/mirror/packages/ !**/mirror/packages/**/*.pdm + +# installer downloads served at /downloads/ (committed so the site works) +!web/downloads/ +!web/downloads/**/*.zip +!web/downloads/**/*.deb diff --git a/src/win_setup.c b/src/win_setup.c new file mode 100644 index 0000000..c1d3642 --- /dev/null +++ b/src/win_setup.c @@ -0,0 +1,82 @@ +/* win_setup.c — minimal self-extracting installer for pmm.exe (built by CI). + * + * The pmm.exe payload is embedded as pmm_payload[] / pmm_payload_len (a header + * generated from `xxd -i out/pmm.exe`, with the symbols renamed at build time). + * On run it writes pmm.exe to %LOCALAPPDATA%\PMM\bin and adds that dir to PATH. + * + * Build (cross, on the ubuntu runner): + * x86_64-w64-mingw32-gcc -O2 -o out/pmm-setup.exe src/win_setup.c \ + * -I. -luser32 -ladvapi32 -lopengl32 (payload.h on include path) + */ +#include +#include +#include +#include "payload.h" + +/* Add `dir` to HKCU\Environment\Path if not already present (user-level PATH, + * no admin needed — mirrors a lightweight, .NET-style install). */ +static void add_to_path(const char *dir) { + HKEY key; + char cur[32768]; DWORD sz = sizeof(cur); DWORD type = REG_SZ; + const char *needle = dir; + + if (RegOpenKeyExA(HKEY_CURRENT_USER, "Environment", 0, KEY_READ, &key) == ERROR_SUCCESS) { + DWORD t = 0; + if (RegQueryValueExA(key, "Path", 0, &t, (BYTE *)cur, &sz) != ERROR_SUCCESS) { + cur[0] = 0; sz = 0; t = REG_SZ; + } + RegCloseKey(key); + } else { + cur[0] = 0; sz = 0; + } + if (strstr(cur, needle)) return; /* already there */ + + char bump[1] = ";"; + char next[65536]; + if (sz == 0 || cur[0] == 0) bump[0] = 0; + /* normalize sep: if entry exists and doesn't end with ';', add one */ + _snprintf(next, sizeof(next), "%s%s%s", cur, (cur[0] && cur[strlen(cur)-1]!=';' ? ";" : bump), dir); + + if (RegOpenKeyExA(HKEY_CURRENT_USER, "Environment", 0, KEY_SET_VALUE, &key) != ERROR_SUCCESS) + return; + RegSetValueExA(key, "Path", 0, REG_EXPAND_SZ, (const BYTE *)next, (DWORD)strlen(next) + 1); + RegCloseKey(key); + /* broadcast so new shells pick it up */ + SendMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, + (LPARAM)"Environment", SMTO_ABORTIFHUNG, 5000, NULL); +} + +static void make_dirs(const char *path) { + char tmp[4096]; + _snprintf(tmp, sizeof(tmp), "%s", path); + for (char *p = tmp + 1; *p; p++) + if (*p == '\\') { *p = 0; CreateDirectoryA(tmp, NULL); *p = '\\'; } + CreateDirectoryA(tmp, NULL); +} + +int main(void) { + char dir[MAX_PATH]; + DWORD n = GetEnvironmentVariableA("LOCALAPPDATA", dir, sizeof(dir)); + if (n == 0 || n >= sizeof(dir)) { + GetModuleFileNameA(NULL, dir, sizeof(dir)); + char *s = strrchr(dir, '\\'); if (s) *s = 0; + _snprintf(dir + strlen(dir), sizeof(dir) - strlen(dir), "\\PMM\\bin"); + } else { + _snprintf(dir + strlen(dir), sizeof(dir) - strlen(dir), "\\PMM\\bin"); + } + make_dirs(dir); + + char dest[MAX_PATH]; + _snprintf(dest, sizeof(dest), "%s\\pmm.exe", dir); + FILE *f = fopen(dest, "wb"); + if (!f) { printf("PMM: cannot write %s\n", dest); return 1; } + if (fwrite(pmm_payload, 1, pmm_payload_len, f) != pmm_payload_len) { + fclose(f); printf("PMM: write failed\n"); return 1; + } + fclose(f); + + add_to_path(dir); + printf("PMM %s installed to %s\n", PMM_SETUP_VER, dest); + printf("PATH updated. Open a NEW terminal and run: pmm -v\n"); + return 0; +} diff --git a/web/downloads/pmm-0.2.6-windows-amd64.zip b/web/downloads/pmm-0.2.6-windows-amd64.zip new file mode 100644 index 0000000..b6d53fa Binary files /dev/null and b/web/downloads/pmm-0.2.6-windows-amd64.zip differ diff --git a/web/downloads/pmm_0.2.6_amd64.deb b/web/downloads/pmm_0.2.6_amd64.deb new file mode 100644 index 0000000..2ed72cb Binary files /dev/null and b/web/downloads/pmm_0.2.6_amd64.deb differ diff --git a/web/index.php b/web/index.php index da490cc..fb8979e 100644 --- a/web/index.php +++ b/web/index.php @@ -148,19 +148,25 @@ for ($r = 0; $r < $ROWS; $r++)
-
curl -L -o pmm.exe https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm.exe
-pmm.exe -v
+
# ZIP 下载(解压即用,pmm.exe 在压缩包内)
+curl -L -o pmm.zip https://pmm.parlz.com/downloads/pmm--windows-amd64.zip
+# 解压后把 pmm.exe 所在目录加入 PATH,然后:
+pmm -v
-
curl -L -o pmm https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm
-chmod +x pmm && sudo mv pmm /usr/local/bin/pmm
+      
# 方式一:sh 一键安装(自动下载二进制 + 加 PATH)
+curl -sSL https://pmm.parlz.com/install.sh | bash
+
+# 方式二:.deb 安装
+curl -L -o pmm.deb https://pmm.parlz.com/downloads/pmm__amd64.deb
+sudo apt install ./pmm.deb
 pmm -v
-
curl -L -o pmm https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm
-chmod +x pmm && sudo mv pmm /usr/local/bin/pmm
+      
# sh 一键安装
+curl -sSL https://pmm.parlz.com/install.sh | bash
 pmm -v
@@ -172,17 +178,20 @@ pmm -v

下载 PMM

可从官方镜像站或 GitHub Release 获取。镜像地址不变。

-

也可用 pmm install pmm / pmm install php 直接从镜像源安装。

+

Linux 也可 curl -sSL https://pmm.parlz.com/install.sh | bash.pdm 包仍可从镜像 pmm install pmm / pmm install php 安装。

diff --git a/web/install.sh b/web/install.sh new file mode 100644 index 0000000..2e4bac4 --- /dev/null +++ b/web/install.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# ParlzPackageManager (PMM) — Linux/macOS one-line installer. +# +# 用法: +# curl -sSL -o install.sh https://pmm.parlz.com/install.sh && bash install.sh +# 或:curl -sSL https://pmm.parlz.com/install.sh | bash +# +# 下载官方 release 二进制并安装到 /usr/local/bin/pmm(root)或 ~/.local/bin/pmm。 +set -e +VER="0.2.6" +REPO="JGZYES/ParlzPackageManger" + +# ---- 检测平台 ---- +OS="$(uname -s)"; ARCH="$(uname -m)" +case "$OS" in + Linux) os=linux ;; + Darwin) os=macos ;; + *) echo "pmm: 不支持的平台 $OS"; exit 1 ;; +esac +case "$ARCH" in + x86_64|amd64) arch=amd64 ;; + aarch64|arm64) arch=arm64 ;; + *) echo "pmm: 不支持的架构 $ARCH"; exit 1 ;; +esac + +# ---- 下载 pmm(release 资产名为 pmm)---- +URL="https://github.com/$REPO/releases/download/v$VER/pmm" +if [ "$arch" != "amd64" ]; then + echo "pmm: 注意:官方发布目前只提供 amd64 资产,$os/$arch 可能 404" +fi +echo "pmm: 下载 v$VER ($os/$arch) ..." +TMP="$(mktemp)" +if ! curl -fsSL --max-time 120 -o "$TMP" "$URL"; then + rm -f "$TMP"; echo "pmm: 下载失败($URL)"; exit 1 +fi +chmod +x "$TMP" + +# ---- 安装 ---- +if [ "$(id -u)" = "0" ]; then + DEST="/usr/local/bin/pmm" +else + DEST="${HOME}/.local/bin/pmm" +fi +mkdir -p "$(dirname "$DEST")" +cp "$TMP" "$DEST" && chmod +x "$DEST" && rm -f "$TMP" + +# ---- PATH 提示 ---- +case ":$PATH:" in + *":$(dirname "$DEST"):"*) ;; + *) echo "pmm: 请将 $(dirname "$DEST") 加入 PATH(或重新登录 shell)" ;; +esac + +echo "pmm: 安装完成 -> $DEST" +"$DEST" -v 2>/dev/null || true