From 73da2a3c8d0a43b81c419f9ebcb986d3fdf7366e Mon Sep 17 00:00:00 2001 From: JGZYES Date: Wed, 2 Sep 2026 21:33:06 +0800 Subject: [PATCH] =?UTF-8?q?web:=20git.php=20=E2=80=94=20GitHub-style=20bro?= =?UTF-8?q?wser=20of=20a=20LOCAL=20stored=20PMM=20repo=20copy=20(repo/),?= =?UTF-8?q?=20one-click=20clone/pull,=20cross-platform=20git=20format=20qu?= =?UTF-8?q?oting;=20source.php=20redirects=20to=20git.php?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + web/_common.php | 2 +- web/git.php | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ web/index.php | 4 +- web/source.php | 158 +------------------------------------------ 5 files changed, 179 insertions(+), 159 deletions(-) create mode 100644 web/git.php diff --git a/.gitignore b/.gitignore index 8bb2cfa..fe9c0e3 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ # source browser cache clone web/.src/ +web/repo/ diff --git a/web/_common.php b/web/_common.php index f1b42d7..95bcda5 100644 --- a/web/_common.php +++ b/web/_common.php @@ -13,7 +13,7 @@ function pmm_nav_links(string $active): string { 'install' => ['install.php', '安装'], 'download' => ['download.php', '下载'], 'status' => ['servers.php', '服务状态'], - 'source' => ['source.php', '源码'], + 'source' => ['git.php', '源码'], ]; $html = ''; foreach ($items as $key => [$href, $label]) { diff --git a/web/git.php b/web/git.php new file mode 100644 index 0000000..277bbcd --- /dev/null +++ b/web/git.php @@ -0,0 +1,173 @@ +&1'; + $out = (string)@shell_exec($cmd); + echo is_dir($REPO_DIR . '/.git') ? 'OK' : '克隆失败:' . substr($out, 0, 200); + } 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; +} + +$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 仓库(git clone),页面即自动变为 GitHub 风格源码浏览。可用下面命令:

    +
    git clone --depth 1  
    +
    + + +
    +
    + +
    + +
    + + + · +
    +
    + +
    + 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 58087a4..a73996f 100644 --- a/web/index.php +++ b/web/index.php @@ -95,10 +95,10 @@ pmm_header('home', '跨平台 C 语言包管理器'); 服务状态 深圳 / 香港镜像的实时探测与详细信息 - + </> 源码 - GitHub 风格浏览 PMM 源码(克隆本仓库) + GitHub 风格浏览 PMM 源码(本地仓库副本) diff --git a/web/source.php b/web/source.php index b689e3a..4c49b82 100644 --- a/web/source.php +++ b/web/source.php @@ -1,157 +1,3 @@ &1'; - @shell_exec($cmd); - if (is_dir($ROOT . '/.git')) $git_ok = true; -} - -function sh(string $c): string { return trim((string)@shell_exec($c)); } -function git_path(string $rel): string { - global $ROOT; - $full = realpath($ROOT . '/' . $rel); - if (!$full) return ''; - if (strpos(str_replace('\\', '/', $full), str_replace('\\', '/', realpath($ROOT))) !== 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'; -} -/* Lightweight markdown -> HTML (code fences, headings, lists, links, bold, hr). */ -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; -} - -/* --- git meta --- */ -$branch = $git_ok ? sh("git -C " . escapeshellarg($ROOT) . " rev-parse --abbrev-ref HEAD 2>/dev/null") : ''; -$last = $git_ok ? sh('git -C ' . escapeshellarg($ROOT) . ' 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) . '' : - '提示:正在初始化 Git 仓库(首次访问会 git clone),若失败请检查服务器 git/网络。'; ?>
    -
    - -
    -
    - -
    - - -
    - - - · -
    - -
    - -无法克隆仓库(服务端缺少 git 或网络受限)。可手动把源码放到 web/.src/ 目录。
    '; - pmm_footer(); exit; -} - -$rel = $_GET['path'] ?? ''; -$rel = str_replace(['../', '..\\', "\0"], '', $rel); -$rel = ltrim($rel, '/'); -$abs = git_path($rel); -if (!$abs) { $abs = realpath($ROOT); $rel = ''; } - -$is_file = is_file($abs); -$parts = $rel === '' ? [] : explode('/', $rel); -?> -
    - . - ' . esc($p) . ''; } ?> -
    - - -
    - bytes
    -
    - - - - - - [true, $d], $dirs), array_map(fn($f) => [false, $f], $files)); - foreach ($rows as [$isD, $name]): - $sub = $rel === '' ? $name : "$rel/$name"; - $href = $isD ? 'source.php?path=' . urlencode($sub) : 'source.php?path=' . urlencode($sub); - $commit = ''; - if ($git_ok) { $commit = sh('git -C ' . escapeshellarg($ROOT) . ' log -1 --format=%h|%an|%ad --date=short -- ' . escapeshellarg($sub) . ' 2>/dev/null'); } - [$ch, $ca, $cd] = array_pad(explode('|', $commit, 3), 3, ''); - ?> - - - - - - - - -
    名称提交时间大小
    - - - -
    - - -
    README
    - - - - - - +/* Source browsing now lives in git.php (local stored repo copy). */ +header('Location: git.php'); exit;