diff --git a/web/_common.php b/web/_common.php index 9670e85..14bd84a 100644 --- a/web/_common.php +++ b/web/_common.php @@ -8,13 +8,8 @@ define('PMM_VERSION', '0.3.6'); function pmm_nav_links(string $active): string { $items = [ - 'home' => ['index.php', '首页'], - 'features' => ['features.php', '特性'], - 'install' => ['install.php', '安装'], - 'download' => ['download.php', '下载'], - 'status' => ['servers.php', '服务状态'], - 'translate'=> ['translate.php', '翻译'], - 'source' => ['git.php', '源码'], + 'home' => ['index.php', '首页'], + 'docs' => ['docs/index.php', '文档'], ]; $html = ''; foreach ($items as $key => [$href, $label]) { @@ -24,6 +19,21 @@ function pmm_nav_links(string $active): string { return $html; } +/* Minimal markdown renderer (self-contained). Used by the docs site. */ +function md(string $t): string { + $t = htmlspecialchars($t, ENT_QUOTES, 'UTF-8'); + $t = preg_replace('/```([a-zA-Z0-9]*)\n(.*?)```/s', "
\\2
", $t); + $t = preg_replace('/^### (.*)$/m', '

$1

', $t); + $t = preg_replace('/^## (.*)$/m', '

$1

', $t); + $t = preg_replace('/^# (.*)$/m', '

$1

', $t); + $t = preg_replace('/^[-*] (.*)$/m', '
  • $1
  • ', $t); + $t = preg_replace('/^\s*---\s*$/m', '
    ', $t); + $t = preg_replace('/\*\*(.+?)\*\*/', '$1', $t); + $t = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '$1', $t); + $t = preg_replace('/`([^`]+)`/', '$1', $t); + return $t; +} + function pmm_header(string $active, string $title): void { $t = htmlspecialchars($title, ENT_QUOTES, 'UTF-8'); echo '' . "\n" . diff --git a/web/assets/style.css b/web/assets/style.css index 5568fde..015acfa 100644 --- a/web/assets/style.css +++ b/web/assets/style.css @@ -297,3 +297,26 @@ code{font-family:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,"Co .rel-size{font-size:11.5px;color:var(--dim);font-family:ui-monospace,monospace;white-space:nowrap} .rel-dl{margin-left:auto;font-size:12px;color:var(--muted);border:1px solid var(--line);border-radius:6px;padding:3px 10px;text-decoration:none;white-space:nowrap} .rel-dl:hover{color:#fff;border-color:#fff} + +/* ---------- docs site ---------- */ +.docs-nav{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:24px;border-bottom:1px solid var(--line);padding-bottom:14px} +.docs-link{font-size:13.5px;color:var(--muted);text-decoration:none;padding:6px 14px;border:1px solid var(--line);border-radius:999px;white-space:nowrap} +.docs-link:hover{color:#fff;border-color:#fff} +.docs-link.active{color:var(--ink);background:var(--accent);border-color:var(--accent)} +.docs-body{max-width:860px;line-height:1.8;color:var(--text)} +.docs-body h1{font-size:30px;margin:0 0 18px;letter-spacing:-.5px;border-bottom:1px solid var(--line);padding-bottom:14px} +.docs-body h2{font-size:20px;margin:34px 0 12px;color:#fff} +.docs-body h3{font-size:16px;margin:26px 0 10px;color:#fff} +.docs-body p{margin:0 0 14px} +.docs-body li{margin:5px 0} +.docs-body ul,.docs-body ol{padding-left:22px;margin:0 0 14px} +.docs-body code{background:var(--panel);border:1px solid var(--line);padding:1px 6px;border-radius:5px;font-size:13px;font-family:ui-monospace,monospace;color:var(--muted)} +.docs-body pre.mdcode{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:14px 16px;overflow:auto;margin:0 0 14px} +.docs-body pre.mdcode code{background:none;border:0;padding:0;color:var(--text);font-size:13px;line-height:1.6;display:block} +.docs-body hr{border:0;border-top:1px solid var(--line);margin:22px 0} +.docs-body a{color:#fff;text-decoration:underline} +.docs-body a:hover{color:var(--accent)} +.docs-body strong{color:#fff} +.docs-body table{border-collapse:collapse;width:100%;margin:0 0 16px} +.docs-body th,.docs-body td{border:1px solid var(--line);padding:8px 12px;font-size:13px;text-align:left} +.docs-body th{background:var(--panel);color:#fff} diff --git a/web/docs/cli.md b/web/docs/cli.md new file mode 100644 index 0000000..dc8cfbf --- /dev/null +++ b/web/docs/cli.md @@ -0,0 +1,57 @@ +# 命令参考 + +## 安装 + +```bash +pmm install # 从注册表安装 +pmm install [pkg2 ...] # 装多个 +pmm install # 装本地包 +pmm install -dpkg # 强制按 deb 装 +pmm install -rpm # 强制按 rpm 装 +pmm install --git # 从 git Release 装 +pmm install --force # 强制重装 +``` + +## 卸载 / 查询 + +```bash +pmm remove +pmm list # 已安装 +pmm list --upgradable # 可升级的 +pmm search # 搜索 +pmm info # 详情 +pmm verify # sha256/sha1 +``` + +## 镜像 / 更新 + +```bash +pmm mirror list +pmm mirror add +pmm mirror use +pmm mirror remove +pmm mirror check # 探测各镜像源可达性 +pmm update # 刷新镜像索引 +pmm upgrade [--yes] # 升级所有已装包 +pmm self-update # 更新 pmm 自身 +``` + +## 配置 + +```bash +pmm setting lang -l # 列语言包 +pmm setting lang # 切换语言 +pmm setting set # 写 pmm.conf(如 mirror / proxy) +pmm setting get # 读 pmm.conf +pmm setting mirror # 设当前镜像 +pmm cache clean # 清缓存 +``` + +## 全局选项 + +```bash +--no-color # 禁用 ANSI 颜色 +-q, --quiet # 只显示错误/警告 +--verbose # 更多细节 +-p # 指定安装盘符(Windows) +``` diff --git a/web/docs/download.md b/web/docs/download.md new file mode 100644 index 0000000..9fcaf1b --- /dev/null +++ b/web/docs/download.md @@ -0,0 +1,36 @@ +# 下载 + +PMM 提供多种安装包。官网镜像站保留二进制注册表(`mirror/`),也可直接从 GitHub Release 获取。 + +## 一键安装(推荐) + +```bash +curl -sSL https://pmm.parlz.com/install.sh | bash +``` + +> 说明:`install.sh` 现在由 GitHub Release 提供;若你手动部署,可把仓库里的 `install.sh` 放到站点根目录,或直接用下方的 GitHub 链接。 + +## 各平台产物(GitHub Release) + +- [pmm-0.3.6-windows-amd64.zip](https://github.com/JGZYES/ParlzPackageManger/releases/latest) — Windows 免安装 +- [pmm_0.3.6_amd64.deb](https://github.com/JGZYES/ParlzPackageManger/releases/latest) — Debian/Ubuntu +- [pmm-0.3.6.x86_64.rpm](https://github.com/JGZYES/ParlzPackageManger/releases/latest) — CentOS/RHEL +- [pmm-0.3.6-linux-amd64.pdm](https://github.com/JGZYES/ParlzPackageManger/releases/latest) — `.pdm` 包 +- [pmm-0.3.6.apk](https://github.com/JGZYES/ParlzPackageManger/releases/latest) — Alpine +- [pmm-0.3.6.pkg.tar.zst](https://github.com/JGZYES/ParlzPackageManger/releases/latest) — Arch + +## 用 pmm 安装(从镜像注册表) + +mirror 注册表保留在 `web/mirror/`,pmm 客户端可直接安装: + +```bash +pmm install pmm==0.3.6 # 升级 pmm 自身 +pmm install nodejs # 装一个软件包 +``` + +## 镜像源 + +- **深圳(默认)**:`https://sz.pmm.parlz.com/mirror/packages` +- **香港(备份)**:`https://pmm.parlz.com/mirror/packages` + +全部历史版本的 `.pdm` 都在镜像 `mirror/packages/pmm/` 下。详见 [镜像源](index.php?page=mirror)。 diff --git a/web/docs/features.md b/web/docs/features.md new file mode 100644 index 0000000..ef740d2 --- /dev/null +++ b/web/docs/features.md @@ -0,0 +1,15 @@ +# 核心特性 + +- **apt 式多镜像源**:按优先级回退,`mirror.ini` 可配多个 registry。 +- **Git Release 安装**:直接装 GitHub / GitLab / Gitea / Forgejo 的最新 Release。 +- **`.pdm` 打包格式**:deb 风格的内置包管理器,跨平台。 +- **依赖解析**:安装时自动解析 `Depends`。 +- **并发下载 + 断点续传**:大文件分片并行、断点续传。 +- **哈希校验**:下载后 sha256 / sha1 校验,拒绝校验失败。 +- **本地包安装**:`.deb` / `.rpm` / `.apk` / `.msi` / `.zip` / `.pkg.tar.zst` 都能装。 +- **搜索与信息**:`pmm search` / `pmm info`。 +- **缓存管理**:`pmm cache clean`。 +- **彩色输出 + 语言包**:`[PMM]:[LEVEL]` 结构化输出,`.pjson` 多语言。 +- **i18n**:`pmm setting lang ` 切换语言,社区可贡献。 + +详见 [命令参考](index.php?page=cli) 与 [翻译](index.php?page=translate)。 diff --git a/web/docs/index.md b/web/docs/index.md new file mode 100644 index 0000000..7bf85af --- /dev/null +++ b/web/docs/index.md @@ -0,0 +1,34 @@ +# 快速开始 + +**PMM(ParlzPackageManager)** 是一个用 C 语言从零编写的跨平台包管理器,理念:**敲即得,装即跑**。 + +支持 Windows / Linux / macOS。像 apt 一样多镜像源,也能直接装 GitHub / GitLab / Gitea / Forgejo 的 Release。 + +## 一分钟装好 + +```bash +curl -sSL https://pmm.parlz.com/install.sh | bash +``` + +装好后: + +```bash +pmm --version # 查看版本 +pmm install nodejs # 安装一个软件包 +pmm list # 已安装的软件包 +``` + +## 常用命令一览 + +```bash +pmm install 安装 +pmm remove 卸载 +pmm search 搜索 +pmm info 详情 +pmm update 刷新镜像索引 +pmm upgrade 升级所有已装包 +pmm mirror list 查看镜像源 +pmm setting lang 切换语言包 +``` + +详见 [命令参考](index.php?page=cli)。 diff --git a/web/docs/index.php b/web/docs/index.php new file mode 100644 index 0000000..46386cf --- /dev/null +++ b/web/docs/index.php @@ -0,0 +1,43 @@ + (defaults to "index"). */ +define('PMM_SITE', 1); +require dirname(__DIR__) . '/_common.php'; + +/* doc pages: [slug, title] */ +$pages = [ + 'index' => '快速开始', + 'install' => '安装', + 'download' => '下载', + 'features' => '核心特性', + 'cli' => '命令参考', + 'mirror' => '镜像源', + 'translate' => '翻译 / 语言包', + 'source' => '源码', +]; +$page = isset($_GET['page']) ? (string)$_GET['page'] : 'index'; +if (!isset($pages[$page])) $page = 'index'; +$title = $pages[$page]; + +$mdPath = __DIR__ . '/' . $page . '.md'; +$body = ''; +if (is_file($mdPath)) { + $body = (string)file_get_contents($mdPath); + $body = str_replace("\r", "", $body); // md() regex hard-codes \n + $body = md($body); +} + +pmm_header('docs', '文档 · ' . $title); +pmm_page_open('DOCS', $title); +?> +
    +
    + +
    +
    +
    + diff --git a/web/docs/install.md b/web/docs/install.md new file mode 100644 index 0000000..dfe503d --- /dev/null +++ b/web/docs/install.md @@ -0,0 +1,49 @@ +# 安装 + +## Linux / macOS 一键 + +```bash +curl -sSL https://pmm.parlz.com/install.sh | bash +``` + +## Windows + +下载并解压 zip,将 `pmm.exe` 加入 PATH: + +```bash +# PowerShell +Invoke-WebRequest https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm-0.3.6-windows-amd64.zip -OutFile pmm.zip +Expand-Archive pmm.zip -DestinationPath pmm +# 然后将 pmm\pmm.exe 所在目录加入 PATH +``` + +## Debian / Ubuntu(.deb) + +```bash +curl -L -o pmm.deb https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm_0.3.6_amd64.deb +sudo apt install ./pmm.deb +``` + +## CentOS / RHEL(.rpm) + +```bash +curl -L -o pmm.rpm https://github.com/JGZYES/ParlzPackageManger/releases/latest/download/pmm-0.3.6-1.x86_64.rpm +sudo rpm -Uvh pmm.rpm +``` + +## 用 pmm 安装 pmm 自身 + +```bash +pmm install pmm==0.3.6 +``` + +## 装好后 + +```bash +pmm search nodejs +pmm install nodejs +pmm list +pmm remove nodejs +``` + +详见 [命令参考](index.php?page=cli) 与 [下载](index.php?page=download)。 diff --git a/web/docs/mirror.md b/web/docs/mirror.md new file mode 100644 index 0000000..3b58492 --- /dev/null +++ b/web/docs/mirror.md @@ -0,0 +1,40 @@ +# 镜像源 + +PMM 采用 apt 式多镜像源,按优先级回退。配置在 `~/.pmm/mirror.ini`。 + +## 默认镜像 + +- **深圳(默认)**:`https://sz.pmm.parlz.com/mirror/packages` +- **香港(备份)**:`https://pmm.parlz.com/mirror/packages` + +## mirror.ini 格式 + +```ini +[sz] +registry = https://sz.pmm.parlz.com/mirror/packages +priority = 1 +default = true + +[main] +registry = https://pmm.parlz.com/mirror/packages +priority = 20 +``` + +## 管理镜像 + +```bash +pmm mirror list # 列出 +pmm mirror add # 添加 +pmm mirror use # 设为当前 +pmm mirror remove # 移除 +pmm mirror check # 探测每个源的可达性/优先级 +``` + +## 服务状态 + +首页有深圳/香港双镜像的实时探测: +- 注册表 `mirror/packages/pmm.json` +- `.pdm` 下载 `mirror/packages/pmm/-linux-amd64.pdm` +- 镜像目录浏览 `mirror/` + +详见 [下载](index.php?page=download)。 diff --git a/web/docs/source.md b/web/docs/source.md new file mode 100644 index 0000000..fd5b17b --- /dev/null +++ b/web/docs/source.md @@ -0,0 +1,22 @@ +# 源码 + +PMM 是开源项目(GPL-3.0)。 + +- **GitHub 仓库**:[JGZYES/ParlzPackageManger](https://github.com/JGZYES/ParlzPackageManger) +- **GitHub Releases**:[releases](https://github.com/JGZYES/ParlzPackageManger/releases) +- **提交 Issue / PR**:[issues](https://github.com/JGZYES/ParlzPackageManger/issues) + +## 构建 + +需要 C11 编译器 + 静态链接环境: + +```bash +# Linux +gcc -O2 -Wall -static -std=c11 -o pmm \ + 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 +``` + +## 文档规范 + +界面文案、`.pjson` 语言包键名、版本 banner 等遵循 [STANDARD.md](https://github.com/JGZYES/ParlzPackageManger/blob/main/docs/STANDARD.md)。 diff --git a/web/docs/translate.md b/web/docs/translate.md new file mode 100644 index 0000000..3f6994f --- /dev/null +++ b/web/docs/translate.md @@ -0,0 +1,32 @@ +# 翻译 / 语言包 + +PMM 的界面文案由 `.pjson` 语言包驱动。默认内置 **zh-CN** 与 **en-US**,社区可以提交新的语言包或修订译文。 + +## 安装语言包 + +```bash +pmm setting lang -l # 列已有语言包 +pmm setting lang ja-JP # 安装并切换 +``` + +## 如何贡献一门语言 + +1. 从镜像下载一个语言包作模板(如 `zh-CN.pjson`)。 +2. 把键名保持不变、只改值,另存为你的语言,如 `ja-JP.pjson`、`zh-TW.pjson`。 +3. 将文件发到 **`luoriguodu@qq.com`**,或在 **GitHub 提 Issue**。 +4. 通过后进入镜像 `web/mirror/lang/`,用户即可 `pmm setting lang ` 安装。 + +## 语言包格式 + +```json +{ + "help.banner": "PMM %s (%s)", + "cmd.install": "install", + "desc.install": "根据名称安装指定软件包", + "msg.installed": "已安装 %s" +} +``` + +键命名:`<区域>.<语义>`(如 `msg.err.not-found`),占位符用 `%s` / `%d`。 + +详见 [STANDARD.md](https://github.com/JGZYES/ParlzPackageManger/blob/main/docs/STANDARD.md)。 diff --git a/web/download.php b/web/download.php deleted file mode 100644 index 2e0898f..0000000 --- a/web/download.php +++ /dev/null @@ -1,56 +0,0 @@ - - -
    -
    -

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

    - -

    Linux 也可 curl -sSL https://pmm.parlz.com/install.sh | bash.pdm 包可直接 pmm install pmm 安装。

    - -

    镜像

    -

    PMM 默认镜像(apt 式,按优先级回退),地址与 mirror.ini 一致。

    -
    -
    sz · 默认https://sz.pmm.parlz.com/mirror/packages
    -
    main · 备份https://pmm.parlz.com/mirror/packages
    -
    - -

    全部历史版本的 .pdm 都在镜像 mirror/packages/pmm/ 下。

    -
    -
    - - diff --git a/web/downloads/install.sh b/web/downloads/install.sh deleted file mode 100644 index a8d4e8c..0000000 --- a/web/downloads/install.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/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.3.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)" -# --progress-bar shows a live download progress line (tty only) -if ! curl -fL --progress-bar --max-time 300 -o "$TMP" "$URL"; then - rm -f "$TMP"; echo "pmm: 下载失败($URL)"; exit 1 -fi -echo "" -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 diff --git a/web/downloads/pmm b/web/downloads/pmm deleted file mode 100644 index f0b8b5d..0000000 Binary files a/web/downloads/pmm and /dev/null differ diff --git a/web/downloads/pmm-0.3.6-windows-amd64.zip b/web/downloads/pmm-0.3.6-windows-amd64.zip deleted file mode 100644 index ecd5406..0000000 Binary files a/web/downloads/pmm-0.3.6-windows-amd64.zip and /dev/null differ diff --git a/web/downloads/pmm-0.3.6.apk b/web/downloads/pmm-0.3.6.apk deleted file mode 100644 index 8d33fd8..0000000 Binary files a/web/downloads/pmm-0.3.6.apk and /dev/null differ diff --git a/web/downloads/pmm-0.3.6.pkg.tar.zst b/web/downloads/pmm-0.3.6.pkg.tar.zst deleted file mode 100644 index c601952..0000000 Binary files a/web/downloads/pmm-0.3.6.pkg.tar.zst and /dev/null differ diff --git a/web/downloads/pmm-0.3.6.x86_64.rpm b/web/downloads/pmm-0.3.6.x86_64.rpm deleted file mode 100644 index f40295f..0000000 Binary files a/web/downloads/pmm-0.3.6.x86_64.rpm and /dev/null differ diff --git a/web/downloads/pmm.exe b/web/downloads/pmm.exe deleted file mode 100644 index 7c3b915..0000000 Binary files a/web/downloads/pmm.exe and /dev/null differ diff --git a/web/downloads/pmm_0.3.6_amd64.deb b/web/downloads/pmm_0.3.6_amd64.deb deleted file mode 100644 index 202dee1..0000000 Binary files a/web/downloads/pmm_0.3.6_amd64.deb and /dev/null differ diff --git a/web/features.php b/web/features.php deleted file mode 100644 index 4317f20..0000000 --- a/web/features.php +++ /dev/null @@ -1,24 +0,0 @@ - - -
    -
    -
    -

    apt 式多镜像源

    支持 mirror.ini / mirror.conf,按优先级自动回退;默认自带 sz(深圳)与 main(香港)两个镜像,缺失时自动生成。

    -

    Git Release 安装

    pmm install --git repo 自动识别 GitHub / GitLab / Gitea / Forgejo 及私有部署;支持 repo@tag / -b branch 安装指定版本。

    -

    .pdm 打包格式

    pmm pack <dir> 生成含 control.tar.gz / data.tar.gz / sha256sums 的归档,思路同 .deb。

    -

    依赖解析

    pdm-control 声明 Depends:,registry 包声明 "depends": [...];安装时自动递归解析并按版本约束(==/≥/≤)安装,带防环保护。

    -

    并发下载 + 断点续传

    大文件(≥8MB)自动 4 路 Range 分片并行下载、逐片续传、拼接后校验;失败自动回退单流。进度条含已用/剩余时间与实时速度。

    -

    哈希校验

    内置 SHA-256 与 SHA-1(FIPS 180-4),下载后强校验;pmm verify <file> 随时验证任意安装包。

    -

    本地包安装

    pmm install -dpkg x.deb(Linux)、pmm install -msi x.msi(Windows),也支持 .rpm/.zip/.tar.gz/.exe/.dmg 等,直接装文件或 URL。

    -

    搜索与信息

    pmm search <关键词> 发现镜像里的包;pmm info <pkg> 查看版本与平台变体;pmm list 列出已装包。

    -

    缓存管理

    下载缓存统一放在 <base>/cachepmm cache clean 一键清空,--no-cache 强制重新下载。

    -
    -
    -
    - - diff --git a/web/git.php b/web/git.php deleted file mode 100644 index 44fd7d0..0000000 --- a/web/git.php +++ /dev/null @@ -1,366 +0,0 @@ -&1'; - $out = (string)@shell_exec($cmd); - if (is_dir($REPO_DIR . '/.git')) echo 'OK'; - else echo '克隆失败:' . substr($out, 0, 220) . "\n(请确保 PHP 对 " . $REPO_DIR . " 可写:chmod -R 775 " . $REPO_DIR . " 或其父目录;或设 PMM_SRC_DIR)"; - } else { - $out = (string)@shell_exec('git -C ' . escapeshellarg($REPO_DIR) . ' pull --depth 1 2>&1'); - echo 'OK (pull: ' . substr(trim($out), 0, 80) . ')'; - } - exit; -} - -$repo_ok = is_dir($REPO_DIR . '/.git'); - -function sh(string $c): string { return trim((string)@shell_exec($c)); } -function repo_path(string $rel): string { - global $REPO_DIR; - $base = realpath($REPO_DIR); - $full = realpath($REPO_DIR . '/' . $rel); - if (!$base || !$full) return ''; - if (strpos(str_replace('\\', '/', $full), str_replace('\\', '/', $base)) !== 0) return ''; - return $full; -} -function esc(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } -function fmt_size(int $b): string { - if ($b < 1024) return $b . ' B'; - if ($b < 1048576) return round($b / 1024, 1) . ' KB'; - return round($b / 1048576, 1) . ' MB'; -} -function md(string $t): string { - $t = htmlspecialchars($t, ENT_QUOTES, 'UTF-8'); - $t = preg_replace('/```([a-zA-Z0-9]*)\n(.*?)```/s', "
    \\2
    ", $t); - $t = preg_replace('/^### (.*)$/m', '

    $1

    ', $t); - $t = preg_replace('/^## (.*)$/m', '

    $1

    ', $t); - $t = preg_replace('/^# (.*)$/m', '

    $1

    ', $t); - $t = preg_replace('/^[-*] (.*)$/m', '
  • $1
  • ', $t); - $t = preg_replace('/^\s*---\s*$/m', '
    ', $t); - $t = preg_replace('/\*\*(.+?)\*\*/', '$1', $t); - $t = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '$1', $t); - $t = preg_replace('/`([^`]+)`/', '$1', $t); - return $t; -} -function gh_api(string $url): array { - $json = null; - if (function_exists('curl_init')) { - $ch = curl_init($url); - curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, - CURLOPT_FOLLOWLOCATION => true, CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, CURLOPT_USERAGENT => 'pmm-site']); - $r = curl_exec($ch); curl_close($ch); - if (is_string($r) && $r !== '') $json = $r; - } - if ($json === null) $json = (string)@shell_exec('curl -s --max-time 15 ' . escapeshellarg($url)); - $d = json_decode((string)$json, true); - return is_array($d) ? $d : []; -} -/* Prefer a local copy of a release asset on this server; fall back to GitHub. */ -/* Prefer a local copy of a release asset (web/releases//, web/downloads/, - * web/mirror/, web root) on this server; fall back to GitHub. */ -function local_asset(string $name, string $tag = ''): ?string { - $cands = []; - if ($tag !== '') $cands[] = __DIR__ . '/releases/' . $tag . '/' . $name; - $cands = array_merge($cands, [__DIR__ . '/downloads/' . $name, __DIR__ . '/mirror/packages/pmm/' . $name, __DIR__ . '/' . $name]); - $base = realpath(__DIR__); - foreach ($cands as $p) { - if (@is_file($p)) { - $rp = realpath($p); - if (strpos($rp, $base) !== 0) continue; - return '/' . str_replace('\\', '/', substr(str_replace('\\', '/', $rp), strlen($base) + 1)); - } - } - return null; -} -function render_releases(): void { - $rels = gh_api('https://api.github.com/repos/JGZYES/ParlzPackageManger/releases?per_page=30'); - if (!$rels) { echo '
    无法获取 Releases(网络或 API 受限)。
    '; return; } - /* left: tag list (like GitHub's folded releases) */ - echo '
    '; - /* right: release entries */ - echo '
    '; - $i = 0; - foreach ($rels as $r): - $tag = $r['tag_name'] ?? '?'; $name = $r['name'] ?? $tag; - $date = $r['published_at'] ?? ($r['created_at'] ?? ''); - $date = substr(str_replace('T', ' ', (string)$date), 0, 10); - $prere = !empty($r['prerelease']); - $assets = $r['assets'] ?? []; - $body = (string)($r['body'] ?? ''); -?> -
    > -
    -
    -

    -
    - Latest - Pre-release - -
    -
    - -
    - - - -
    - - -
    - -

    标签

    -
    -
    -
    '; -} - -$view = $_GET['view'] ?? ''; -$branch = $repo_ok ? sh("git -C " . escapeshellarg($REPO_DIR) . " rev-parse --abbrev-ref HEAD 2>/dev/null") : ''; -$last = $repo_ok ? sh('git -C ' . escapeshellarg($REPO_DIR) . " log -1 --format=\"%H|%s|%an|%ad\" --date=short 2>/dev/null") : ''; -[$lhash, $lsubj, $luser, $ldate] = array_pad(explode('|', $last, 4), 4, ''); -$lhash7 = substr($lhash, 0, 7); - -pmm_header('source', '源码浏览'); -?> - -
    -
    SOURCE
    -

    源码 浏览

    -
    - JGZYES/ParlzPackageManager · 分支 ' . esc($branch) . ' · ' . esc($REPO_DIR) - : '提示:本地依赖仓库尚未初始化,请先 git clone 或点击下方“初始化/更新”。'; ?> -
    -
    - -
    -
    - - -
    -
    初始化本地源码仓库
    -

    页面将 PMM 仓库副本存入 。若 PHP 无写权限(web 根归 root),先 - chmod -R 775 或其父目录;或用环境变量 PMM_SRC_DIR 指定持久目录。初始化命令:

    -
    git clone --depth 1  
    -
    - - -
    -
    - -
    - -
    - - - · -
    -
    - - - -

    Releases

    - - -
    - source - ' . esc($p) . ''; } ?> -
    - - -
    - bytes
    -
    - - - - - [true, $d], $dirs), array_map(fn($f) => [false, $f], $files)); - foreach ($rows as [$isD, $name]): - $sub = $rel === '' ? $name : "$rel/$name"; - $href = 'git.php?path=' . urlencode($sub); - $commit = sh('git -C ' . escapeshellarg($REPO_DIR) . " log -1 --format=\"%h|%an|%ad\" --date=short -- " . escapeshellarg($sub) . ' 2>/dev/null'); - [$ch, $ca, $cd] = array_pad(explode('|', $commit, 3), 3, ''); - ?> - - - - - - - - -
    名称提交时间大小
    -
    - -
    README
    - - - -
    -
    - - - \ No newline at end of file diff --git a/web/index.php b/web/index.php index a73996f..c1c2805 100644 --- a/web/index.php +++ b/web/index.php @@ -1,5 +1,6 @@ ParlzPackageManager (PMM)

    一个用 C 语言从零编写的跨平台包管理器。像 apt 一样多用镜像源,也能直接从 GitHub / GitLab / Gitea / Forgejo Release 装包。

    双镜像 · 深圳 / 香港 实时在线
    @@ -75,30 +76,20 @@ pmm_header('home', '跨平台 C 语言包管理器');
    diff --git a/web/install.php b/web/install.php deleted file mode 100644 index 130944f..0000000 --- a/web/install.php +++ /dev/null @@ -1,56 +0,0 @@ - - -
    -
    -

    下载对应平台二进制,一条命令搞定,完成后自动加入 PATH。

    -
    - - - -
    -
    -
    # ZIP 免安装版(解压即用,pmm.exe 在压缩包内)
    -curl -L -o pmm.zip https://pmm.parlz.com/releases/v/pmm--windows-amd64.zip
    -# 解压后把 pmm.exe 所在目录加入 PATH,然后:
    -pmm -v
    - -
    -
    -
    # 方式一:sh 一键安装(自动下载二进制 + 加 PATH)
    -curl -sSL https://pmm.parlz.com/install.sh | bash
    -
    -# 方式二:.deb 安装
    -curl -L -o pmm.deb https://pmm.parlz.com/releases/v/pmm__amd64.deb
    -sudo apt install ./pmm.deb
    -
    -# 方式三:.rpm 安装
    -curl -L -o pmm.rpm https://pmm.parlz.com/releases/v/pmm-.x86_64.rpm
    -sudo rpm -Uvh pmm.rpm
    -pmm -v
    - -
    -
    -
    # sh 一键安装
    -curl -sSL https://pmm.parlz.com/install.sh | bash
    -pmm -v
    - -
    - -

    装好之后

    -
    -
    pmm search node          # 在镜像里搜包
    -pmm install nodejs       # 安装(自动解析依赖)
    -pmm install nodejs==24.20.0   # 指定版本
    -pmm install --git owner/repo@v1.2.3   # 从 git release 安装指定 tag
    -pmm list                 # 已装列表
    -pmm remove nodejs        # 卸载
    -
    -
    -
    - - diff --git a/web/install.sh b/web/install.sh deleted file mode 100644 index a8d4e8c..0000000 --- a/web/install.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/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.3.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)" -# --progress-bar shows a live download progress line (tty only) -if ! curl -fL --progress-bar --max-time 300 -o "$TMP" "$URL"; then - rm -f "$TMP"; echo "pmm: 下载失败($URL)"; exit 1 -fi -echo "" -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 diff --git a/web/mirror/index.php b/web/mirror/index.php index 75c8532..d68d98f 100644 --- a/web/mirror/index.php +++ b/web/mirror/index.php @@ -89,7 +89,7 @@ if ($dirRel !== '') { } foreach ($dirs as $d) { $href = '?dir=' . rawurlencode($webRel === '' ? $d : $webRel . '/' . $d); - echo "
  • " . ic('folder') . "" . en($d) . "/
  • "; + echo "
  • " . ic('folder') . "" . en($d) . "/
  • "; } foreach ($files as $f) { $href = url_enc_path($webRel, $f); diff --git a/web/servers.php b/web/servers.php deleted file mode 100644 index 5437925..0000000 --- a/web/servers.php +++ /dev/null @@ -1,26 +0,0 @@ - - -
    -
    -

    实时监控 PMM 双镜像(深圳 / 香港)的注册表、下载服务与 Web 浏览三项能力,每 15 秒自动刷新。不暴露任何服务器 IP。

    - -
    - 检测中… - -
    - -
    -
    深圳
    sz.pmm.parlz.com
    https://sz.pmm.parlz.com/mirror/packages
    检测中…
    -
    香港
    pmm.parlz.com
    https://pmm.parlz.com/mirror/packages
    检测中…
    -
    - -
    -
    -
    - - diff --git a/web/source.php b/web/source.php deleted file mode 100644 index 4c49b82..0000000 --- a/web/source.php +++ /dev/null @@ -1,3 +0,0 @@ - '深圳', 'region' => 'CN · 深圳', 'host' => 'sz.pmm.parlz.com'], - ['name' => '香港', 'region' => 'HK · 香港', 'host' => 'pmm.parlz.com'], -]; - -/* Probe one URL: returns [code, ms, server, ctype]. - * Prefers the PHP curl extension (reliable CURLINFO_TOTAL_TIME for ms, and works - * where shell_exec/curl-binary are unavailable); falls back to shell curl. */ -function probe_url(string $url): array { - $code = 0; $ms = 0; $server = ''; $ctype = ''; - - /* 1) PHP curl extension */ - if (function_exists('curl_init')) { - $ch = curl_init($url); - curl_setopt_array($ch, [ - CURLOPT_RETURNTRANSFER => true, - CURLOPT_NOBODY => true, - CURLOPT_HEADER => true, - CURLOPT_CONNECTTIMEOUT => 3, - CURLOPT_TIMEOUT => 8, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, - CURLOPT_USERAGENT => 'pmm-status/1.0', - ]); - $resp = curl_exec($ch); - $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); - $ms = (int)round(((float)curl_getinfo($ch, CURLINFO_TOTAL_TIME)) * 1000.0); - $ctype = (string)curl_getinfo($ch, CURLINFO_CONTENT_TYPE); - if (preg_match('/^Server:\s*(.+)$/mi', (string)$resp, $m)) $server = trim($m[1]); - curl_close($ch); - if ($code > 0) return [$code, $ms, $server, $ctype]; - } - - /* 2) shell curl (works where the binary exists; parses -D - headers + -w marker) */ - $cmd = 'curl -k -s -o /dev/null -D - --max-time 8 ' - . '-w "__PMM_PROBE__%{http_code} %{time_total}" ' . escapeshellarg($url); - $out = (string)@shell_exec($cmd); - if ($out !== '') { - /* headers before the marker, "code ms" after it */ - $pos = strrpos($out, '__PMM_PROBE__'); - if ($pos !== false) { - $meta = trim(substr($out, $pos + strlen('__PMM_PROBE__'))); - $parts = preg_split('/\s+/', $meta); - if (isset($parts[0])) $code = (int)$parts[0]; - if (isset($parts[1])) $ms = (int)round(((float)$parts[1]) * 1000); - $head = substr($out, 0, $pos); - if (preg_match('/^Server:\s*(.+)$/mi', $head, $m)) $server = trim($m[1]); - if (preg_match('/^Content-Type:\s*(.+)$/mi', $head, $m)) $ctype = trim($m[1]); - } - } - return [$code, $ms, $server, $ctype]; -} - -function probe_check(string $url): array { - [$code, $ms, $server, $ctype] = probe_url($url); - return [ - 'ok' => ($code >= 200 && $code < 500 && $code !== 0), - 'code' => $code, - 'ms' => $ms, - 'server' => $server, - 'ctype' => $ctype, - ]; -} - -$out = []; -foreach ($servers as $s) { - $h = $s['host']; - $reg = probe_check("https://{$h}/mirror/packages/pmm.json"); - $dl = probe_check("https://{$h}/mirror/packages/pmm/" . PMM_VERSION . "-linux-amd64.pdm"); - $web = probe_check("https://{$h}/mirror/"); - $avg = 0; $n = 0; - foreach ([$reg, $dl, $web] as $c) if ($c['ok']) { $avg += $c['ms']; $n++; } - $avg = $n ? (int)round($avg / $n) : 0; - $out[] = [ - 'name' => $s['name'], - 'region' => $s['region'], - 'host' => $h, - 'online' => $reg['ok'], - 'avg_ms' => $avg, - 'checks' => [ - ['item' => '注册表 (packages API)', 'url' => "https://{$h}/mirror/packages/pmm.json", 'result' => $reg], - ['item' => '下载服务 (.pdm 分发)', 'url' => "https://{$h}/mirror/packages/pmm/" . PMM_VERSION . "-linux-amd64.pdm", 'result' => $dl], - ['item' => 'Web 目录浏览', 'url' => "https://{$h}/mirror/", 'result' => $web], - ], - 'checked_at' => gmdate('Y-m-d\TH:i:s\Z'), - ]; -} -echo json_encode($out, JSON_UNESCAPED_UNICODE); diff --git a/web/translate.php b/web/translate.php deleted file mode 100644 index 6450dd5..0000000 --- a/web/translate.php +++ /dev/null @@ -1,74 +0,0 @@ - $locale, - 'keys' => $keys, - 'file' => 'mirror/lang/' . basename($f), - 'raw' => $raw, - ]; - } -} -usort($packs, function ($a, $b) { return strcmp($a['locale'], $b['locale']); }); - -$mail = 'luoriguodu@qq.com'; -$issues = 'https://github.com/JGZYES/ParlzPackageManger/issues/new'; - -pmm_header('translate', '翻译 · Translate'); -pmm_page_open('TRANSLATE', '翻译 / Language'); -?> -
    -
    -

    PMM 的界面文案由 .pjson 语言包驱动。每门语言一个包;想新增语言或修订译文,请 - 发邮件 - 或在 GitHub 提 Issue

    - -
    - -
    暂无语言包
    - -
    - - - -
    - 查看 -
    -
    - - -
    - -
    - -

    如何贡献一门语言

    -
      -
    1. 打开任一语言(如 zh-CN)卡片 → 下载 .pjson
    2. -
    3. zh-CN 的键名保留、只改值,另存为你的语言,如 ja-JP.pjsonzh-TW.pjson
    4. -
    5. 将文件作为附件发到 ,或在 GitHub 提 Issue 粘贴内容。
    6. -
    7. 通过后即进入镜像 web/mirror/lang/,用户用 pmm setting lang <locale> 安装。
    8. -
    - -

    安装语言包:

    -
    pmm setting lang ja-JP
    -pmm setting lang -l
    -
    -
    -