首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 封裝 SVN 操作類:基於命令列的版本控制自動化實戰

     編輯:PHP 相關知識

設計目標

  • 封裝 svn CLI 指令,提供 OOP 介面
  • 統一錯誤處理與日誌記錄
  • 支援 CI/CD 流水線自動化佈署

核心類別結構

workDir = realpath($workDir);
    }

    /** 統一執行入口 */
    private function exec(string $cmd): array {
        $full = self::BIN . ' ' . self::AUTH . ' ' . $cmd . ' 2>&1';
        $out = [];
        $code = 0;
        exec("cd {$this->workDir} && {$full}", $out, $code);
        $this->lastOutput = $out;
        $this->lastCode   = $code;
        return [$out, $code];
    }

    /** 解析輸出判斷成功 */
    private function assertSuccess(array $out, int $code, string $keyword): bool {
        if ($code !== 0) return false;
        return implode("\n", $out) !== '' && stripos(implode("\n", $out), $keyword) !== false;
    }

    // ---------- 公開 API ----------
    public function ls(string $url): array { /* ... */ }
    public function copy(string $src, string $dst, string $msg): bool { /* ... */ }
    public function delete(string $url, string $msg): bool { /* ... */ }
    public function move(string $src, string $dst, string $msg): bool { /* ... */ }
    public function mkdir(string $url, string $msg): bool { /* ... */ }
    public function diff(string $url1, string $url2): string { /* ... */ }
    public function checkout(string $url, string $dest): bool { /* ... */ }
    public function update(string $dest): array { /* 回傳 [rev, changedFiles] */ }
    public function merge(string $target, string $source, int $revFrom, int $revTo): bool { /* ... */ }
    public function commit(string $path, string $msg): bool { /* ... */ }
    public function status(string $path): array { /* ... */ }
    public function hasConflict(string $path): bool { /* ... */ }
    public function log(string $url, int $limit = 10): array { /* ... */ }
    public function info(string $url): array { /* 回傳 [rev, url, author, date] */ }
    public function getHeadRevision(string $wc): int { /* ... */ }
    public function getFileFirstVersion(string $url): int { /* ... */ }
    public function getChangedFiles(int $revFrom, int $revTo): array { /* ... */ }
    public function getChangedInfo(int $revFrom, int $revTo): string { /* ... */ }
    public function getFileContent(string $url, int $rev): string { /* ... */ }
}

關鍵方法實現片段

更新並取得版本號

public function update(string $dest): array {
    [$out, $code] = $this->exec("up {$dest}");
    if ($code !== 0) throw new RuntimeException("SVN up failed: " . implode("\n", $out));
    
    $rev = 0;
    foreach ($out as $line) {
        if (preg_match('/Updated to revision (\d+)/', $line, $m)) {
            $rev = (int)$m[1];
            break;
        }
    }
    return [$rev, $out];
}

檢測衝突

public function hasConflict(string $path): bool {
    [$out] = $this->exec("st {$path}");
    foreach ($out as $line) {
        if (str_starts_with(trim($line), 'C') || str_starts_with(trim($line), '!')) {
            return true; // Conflict 或 Missing
        }
    }
    return false;
}

取得檔案指定版本內容

public function getFileContent(string $url, int $rev): string {
    [$out, $code] = $this->exec("cat -r {$rev} {$url}");
    if ($code !== 0) throw new RuntimeException("SVN cat failed");
    return implode("\n", $out);
}

實戰應用場景

  1. 自動化發布:Jenkins/GitLab CI 階段 svn copy trunk tags/1.2.3 -m "Release 1.2.3"
  2. 程式碼審查輔助:MR 建立時自動 svn diff 產出變更報表
  3. 熱修復回滾:svn merge -r HEAD:12345 . 快速還原特定版本

最佳實踐與坑點

  • 權限隔離:專用 SVN 帳號(robot),僅授予必要路徑讀寫權限。
  • 非互動模式:--non-interactive --no-auth-cache 避免提示阻塞 CI。
  • 工作目錄乾淨:操作前先 svn status 確認無本地修改,否則 update/merge 易產生衝突。
  • 編碼一致:確保伺服器、資料庫、PHP 檔案皆為 UTF-8,避免中文檔名亂碼。
  • 超時控制:大型倉庫 checkout/update 可能超過 PHP max_execution_time,建議 CLI 模式執行並設 set_time_limit(0)。

擴展方向

  • 引入 symfony/process 替代 exec(),獲得即時輸出流、信號處理、跨平台相容。
  • 實作 SvnRepository 介面,支援 svn://、https://、file:// 多協議。
  • 整合 Webhook 觸發自動同步至鏡像倉庫。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved