镜像自地址
https://github.com/JGZYES/ParlzPackageManger.git
已同步 2026-09-11 08:52:45 +08:00
install: Windows ZIP + self-extracting EXE (win_setup.c SFX), Linux .deb + install.sh; host at /downloads + /install.sh; wire packaging into CI release
这个提交包含在:
@@ -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/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/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 <<EOF
|
||||||
|
Package: pmm
|
||||||
|
Version: $VER
|
||||||
|
Section: devel
|
||||||
|
Priority: optional
|
||||||
|
Architecture: amd64
|
||||||
|
Maintainer: PMM <packages@pmm.dev>
|
||||||
|
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
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -53,7 +94,6 @@ jobs:
|
|||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
files: |
|
files: out/*
|
||||||
out/pmm${{ matrix.ext }}
|
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
name: PMM ${{ github.ref_name }}
|
name: PMM ${{ github.ref_name }}
|
||||||
|
|||||||
+5
@@ -22,3 +22,8 @@
|
|||||||
# still matches after the mirror moved to web/mirror/.
|
# still matches after the mirror moved to web/mirror/.
|
||||||
!**/mirror/packages/
|
!**/mirror/packages/
|
||||||
!**/mirror/packages/**/*.pdm
|
!**/mirror/packages/**/*.pdm
|
||||||
|
|
||||||
|
# installer downloads served at /downloads/ (committed so the site works)
|
||||||
|
!web/downloads/
|
||||||
|
!web/downloads/**/*.zip
|
||||||
|
!web/downloads/**/*.deb
|
||||||
|
|||||||
+82
@@ -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 <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
二进制文件未显示。
二进制文件未显示。
+20
-11
@@ -148,19 +148,25 @@ for ($r = 0; $r < $ROWS; $r++)
|
|||||||
<button class="tab" data-tab="macos">macOS</button>
|
<button class="tab" data-tab="macos">macOS</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="code-box" data-pane="win" data-active="1">
|
<div class="code-box" data-pane="win" data-active="1">
|
||||||
<pre><code>curl -L -o pmm.exe https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm.exe
|
<pre><code># ZIP 下载(解压即用,pmm.exe 在压缩包内)
|
||||||
pmm.exe -v</code></pre>
|
curl -L -o pmm.zip https://pmm.parlz.com/downloads/pmm-<?php echo $VERSION; ?>-windows-amd64.zip
|
||||||
|
# 解压后把 pmm.exe 所在目录加入 PATH,然后:
|
||||||
|
pmm -v</code></pre>
|
||||||
<button class="copy-btn" data-copy="win">复制</button>
|
<button class="copy-btn" data-copy="win">复制</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="code-box" data-pane="linux">
|
<div class="code-box" data-pane="linux">
|
||||||
<pre><code>curl -L -o pmm https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm
|
<pre><code># 方式一:sh 一键安装(自动下载二进制 + 加 PATH)
|
||||||
chmod +x pmm && sudo mv pmm /usr/local/bin/pmm
|
curl -sSL https://pmm.parlz.com/install.sh | bash
|
||||||
|
|
||||||
|
# 方式二:.deb 安装
|
||||||
|
curl -L -o pmm.deb https://pmm.parlz.com/downloads/pmm_<?php echo $VERSION; ?>_amd64.deb
|
||||||
|
sudo apt install ./pmm.deb
|
||||||
pmm -v</code></pre>
|
pmm -v</code></pre>
|
||||||
<button class="copy-btn" data-copy="linux">复制</button>
|
<button class="copy-btn" data-copy="linux">复制</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="code-box" data-pane="macos">
|
<div class="code-box" data-pane="macos">
|
||||||
<pre><code>curl -L -o pmm https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm
|
<pre><code># sh 一键安装
|
||||||
chmod +x pmm && sudo mv pmm /usr/local/bin/pmm
|
curl -sSL https://pmm.parlz.com/install.sh | bash
|
||||||
pmm -v</code></pre>
|
pmm -v</code></pre>
|
||||||
<button class="copy-btn" data-copy="macos">复制</button>
|
<button class="copy-btn" data-copy="macos">复制</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -172,17 +178,20 @@ pmm -v</code></pre>
|
|||||||
<h2 class="section-title">下载 <span class="accent">PMM</span></h2>
|
<h2 class="section-title">下载 <span class="accent">PMM</span></h2>
|
||||||
<p class="section-sub">可从官方镜像站或 GitHub Release 获取。镜像地址不变。</p>
|
<p class="section-sub">可从官方镜像站或 GitHub Release 获取。镜像地址不变。</p>
|
||||||
<div class="dl-grid">
|
<div class="dl-grid">
|
||||||
<a class="dl-card" href="mirror/packages/pmm/<?php echo $VERSION; ?>-windows-amd64.pdm" download>
|
<a class="dl-card" href="downloads/pmm-<?php echo $VERSION; ?>-windows-amd64.zip" download>
|
||||||
<span class="dl-os">Windows</span><span class="dl-file">pmm-<?php echo $VERSION; ?>-windows-amd64.pdm</span><span class="dl-arrow">↓</span>
|
<span class="dl-os">Windows</span><span class="dl-file">pmm-<?php echo $VERSION; ?>-windows-amd64.zip</span><span class="dl-arrow">↓</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="dl-card" href="mirror/packages/pmm/<?php echo $VERSION; ?>-linux-amd64.pdm" download>
|
<a class="dl-card" href="downloads/pmm_<?php echo $VERSION; ?>_amd64.deb" download>
|
||||||
<span class="dl-os">Linux</span><span class="dl-file">pmm-<?php echo $VERSION; ?>-linux-amd64.pdm</span><span class="dl-arrow">↓</span>
|
<span class="dl-os">Linux</span><span class="dl-file">pmm_<?php echo $VERSION; ?>_amd64.deb</span><span class="dl-arrow">↓</span>
|
||||||
|
</a>
|
||||||
|
<a class="dl-card" href="install.sh" download>
|
||||||
|
<span class="dl-os">Linux/macOS</span><span class="dl-file">install.sh · 一键安装</span><span class="dl-arrow">↓</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="dl-card" href="https://github.com/JGZYES/ParlzPackageManger/releases/latest" target="_blank" rel="noopener">
|
<a class="dl-card" href="https://github.com/JGZYES/ParlzPackageManger/releases/latest" target="_blank" rel="noopener">
|
||||||
<span class="dl-os">全部</span><span class="dl-file">GitHub Releases / 源码</span><span class="dl-arrow">↗</span>
|
<span class="dl-os">全部</span><span class="dl-file">GitHub Releases / 源码</span><span class="dl-arrow">↗</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="tips">也可用 <code>pmm install pmm</code> / <code>pmm install php</code> 直接从镜像源安装。</p>
|
<p class="tips">Linux 也可 <code>curl -sSL https://pmm.parlz.com/install.sh | bash</code>;<code>.pdm</code> 包仍可从镜像 <code>pmm install pmm</code> / <code>pmm install php</code> 安装。</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
+54
@@ -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
|
||||||
在新工单中引用
屏蔽一个用户