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