Subversion Repositories php_utils

Rev

Rev 84 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * PHP svn functions
  5.  * Copyright 2021 - 2023 Daniel Marschall, ViaThinkSoft
  6.  * Revision 2023-09-15
  7.  *
  8.  * Licensed under the Apache License, Version 2.0 (the "License");
  9.  * you may not use this file except in compliance with the License.
  10.  * You may obtain a copy of the License at
  11.  *
  12.  *     http://www.apache.org/licenses/LICENSE-2.0
  13.  *
  14.  * Unless required by applicable law or agreed to in writing, software
  15.  * distributed under the License is distributed on an "AS IS" BASIS,
  16.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17.  * See the License for the specific language governing permissions and
  18.  * limitations under the License.
  19.  */
  20.  
  21. function get_svn_revision($dir='') {
  22.         if (!empty($dir)) $dir .= '/';
  23.         if (!is_dir($dir)) return false;
  24.         if (is_dir($dir.'/.svn')) $dir .= '/.svn/';
  25.  
  26.         // Try to find out the SVN version using the shell
  27.         $output = @shell_exec('svnversion '.escapeshellarg($dir).' 2>&1');
  28.         $match = array();
  29.         if (preg_match('/\d+/', $output, $match)) {
  30.                 return ($cachedVersion = $match[0]);
  31.         }
  32.  
  33.         $output = @shell_exec('svn info '.escapeshellarg($dir).' 2>&1');
  34.         if (preg_match('/Revision:\s*(\d+)/m', $output, $match)) { // do not translate
  35.                 return ($cachedVersion = $match[1]);
  36.         }
  37.  
  38.         // If that failed, try to get the version via access of the database files
  39.         if (class_exists('SQLite3')) {
  40.                 try {
  41.                         $db = new SQLite3($dir.'.svn/wc.db');
  42.                         $results = $db->query('SELECT MIN(revision) AS rev FROM NODES_BASE');
  43.                         while ($row = $results->fetchArray()) {
  44.                                 return ($cachedVersion = $row['rev']);
  45.                         }
  46.                         $db->close();
  47.                         $db = null;
  48.                 } catch (Exception $e) {
  49.                 }
  50.         }
  51.         if (class_exists('PDO')) {
  52.                 try {
  53.                         $pdo = new PDO('sqlite:'.$dir.'.svn/wc.db');
  54.                         $res = $pdo->query('SELECT MIN(revision) AS rev FROM NODES_BASE');
  55.                         $row = $res->fetch();
  56.                         if ($row !== false) {
  57.                                 return ($cachedVersion = $row['rev']);
  58.                         }
  59.                         $pdo = null;
  60.                 } catch (Exception $e) {
  61.                 }
  62.         }
  63.  
  64.         // We couldn't get the revision info
  65.         // Try parsing the binary file. It is a bit risky though...
  66.         return get_svn_revision_without_sqlite3($dir);
  67. }
  68.  
  69. // Note: get_svn_revision_without_sqlite3() can be very unstable, so it is highly recommended to install php-sqlite in order to parse the file correctly.
  70. function get_svn_revision_without_sqlite3($svn_path, $base='trunk') {
  71.         if (!empty($svn_path)) $svn_path .= '/';
  72.         if (!is_dir($svn_path)) return false;
  73.         if (!is_dir($svn_path.'/.svn')) $svn_path .= '/../';
  74.  
  75.         $fil = file_get_contents($svn_path.'/.svn/wc.db');
  76.         preg_match_all('@('.preg_quote($base,'@').'/[a-z0-9!"#$%&\'()*+,.\/:;<=>?\@\[\] ^_`{|}~-]+)(..)normal(file|dir)@', $fil, $m, PREG_SET_ORDER);
  77.  
  78.         $files = array();
  79.         foreach ($m as list($dummy, $fil, $revision, $type)) {
  80.                 $val = hexdec(bin2hex($revision));
  81.  
  82.                 $tmp = explode("$base/", $fil);
  83.                 $fil = end($tmp);
  84.  
  85.                 // TODO: Problem: We don't know if it was checked out as / or checked out as /trunk/, or something else!
  86.                 if (!file_exists($svn_path."/$base/$fil") && !file_exists($svn_path."/$fil")) continue; // deleted files (deleted rows?!) might be still in the binary
  87.  
  88.                 if (!isset($files[$fil])) $files[$fil] = -1;
  89.                 if ($files[$fil] < $val) $files[$fil] = $val;
  90.         }
  91.         $arr = array_values($files);
  92.  
  93.         /*
  94.         foreach ($files as $name => $val) {
  95.                 if ($val != 1228) echo "DEBUG Unexpected: $val / $fil\n";
  96.         }
  97.         */
  98.  
  99.         if (count($files) == 0) return 1; // should not happen
  100.         $num = count($arr);
  101.         $middleVal = floor(($num - 1) / 2);
  102.         if ($num % 2) {
  103.                 $median = $arr[$middleVal];
  104.         } else {
  105.                 $lowMid = $arr[$middleVal];
  106.                 $highMid = $arr[$middleVal + 1];
  107.                 $median = (($lowMid + $highMid) / 2);
  108.         }
  109.  
  110.         return $median;
  111. }
  112.