69 "Candidate cacheFile={$this->cacheFile} for {$repoDir}"
71 if ( $usePrecomputed &&
72 $this->cacheFile !==
null &&
73 is_readable( $this->cacheFile )
76 file_get_contents( $this->cacheFile ),
79 wfDebugLog(
'gitinfo',
"Loaded git data from cache for {$repoDir}" );
83 wfDebugLog(
'gitinfo',
"Cache incomplete for {$repoDir}" );
84 $this->basedir =
$repoDir . DIRECTORY_SEPARATOR .
'.git';
85 if ( is_readable( $this->basedir ) && !is_dir( $this->basedir ) ) {
86 $GITfile = file_get_contents( $this->basedir );
87 if ( strlen( $GITfile ) > 8 &&
88 substr( $GITfile, 0, 8 ) ===
'gitdir: '
90 $path = rtrim( substr( $GITfile, 8 ),
"\r\n" );
91 if (
$path[0] ===
'/' || substr(
$path, 1, 1 ) ===
':' ) {
93 $this->basedir =
$path;
116 $realIP = realpath(
$IP );
118 if ( $repoName ===
false ) {
122 if ( strpos( $repoName, $realIP ) === 0 ) {
124 $repoName = substr( $repoName, strlen( $realIP ) );
128 $repoName = strtr( $repoName, DIRECTORY_SEPARATOR,
'-' );
129 $fileName =
'info' . $repoName .
'.json';
130 $cachePath =
"{$wgGitInfoCacheDirectory}/{$fileName}";
131 if ( is_readable( $cachePath ) ) {
136 return "$repoDir/gitinfo.json";
144 public static function repo() {
145 if ( is_null( self::$repo ) ) {
147 self::$repo =
new self(
$IP );
159 return (
bool)preg_match(
'/^[0-9A-F]{40}$/i', $str );
168 if ( !isset( $this->cache[
'head'] ) ) {
169 $headFile =
"{$this->basedir}/HEAD";
172 if ( is_readable( $headFile ) ) {
173 $head = file_get_contents( $headFile );
175 if ( preg_match(
"/ref: (.*)/", $head, $m ) ) {
176 $head = rtrim( $m[1] );
178 $head = rtrim( $head );
181 $this->cache[
'head'] = $head;
183 return $this->cache[
'head'];
192 if ( !isset( $this->cache[
'headSHA1'] ) ) {
197 if ( self::isSHA1( $head ) ) {
201 $refFile =
"{$this->basedir}/{$head}";
202 $packedRefs =
"{$this->basedir}/packed-refs";
203 $headRegex = preg_quote( $head,
'/' );
204 if ( is_readable( $refFile ) ) {
205 $sha1 = rtrim( file_get_contents( $refFile ) );
206 } elseif ( is_readable( $packedRefs ) &&
207 preg_match(
"/^([0-9A-Fa-f]{40}) $headRegex$/m", file_get_contents( $packedRefs ),
$matches )
212 $this->cache[
'headSHA1'] = $sha1;
214 return $this->cache[
'headSHA1'];
226 if ( !isset( $this->cache[
'headCommitDate'] ) ) {
230 !Shell::isDisabled() &&
237 '--format=format:%ct',
240 $gitDir = realpath( $this->basedir );
241 $result = Shell::command( $cmd )
242 ->environment( [
'GIT_DIR' => $gitDir ] )
243 ->restrict( Shell::RESTRICT_DEFAULT | Shell::NO_NETWORK )
244 ->whitelistPaths( [ $gitDir, $this->repoDir ] )
247 if ( $result->getExitCode() === 0 ) {
248 $date = (int)$result->getStdout();
251 $this->cache[
'headCommitDate'] = $date;
253 return $this->cache[
'headCommitDate'];
262 if ( !isset( $this->cache[
'branch'] ) ) {
265 preg_match(
"#^refs/heads/(.*)$#", $branch, $m )
269 $this->cache[
'branch'] = $branch;
271 return $this->cache[
'branch'];
281 if ( $url ===
false ) {
284 foreach ( self::getViewers() as
$repo => $viewer ) {
285 $pattern =
'#^' .
$repo .
'$#';
286 if ( preg_match( $pattern, $url,
$matches ) ) {
287 $viewerUrl = preg_replace( $pattern, $viewer, $url );
290 '%h' => substr( $headSHA1, 0, 7 ),
295 return strtr( $viewerUrl, $replacements );
306 if ( !isset( $this->cache[
'remoteURL'] ) ) {
307 $config =
"{$this->basedir}/config";
309 if ( is_readable( $config ) ) {
310 Wikimedia\suppressWarnings();
311 $configArray = parse_ini_file( $config,
true );
312 Wikimedia\restoreWarnings();
316 if ( isset( $configArray[
'remote origin'] ) ) {
317 $remote = $configArray[
'remote origin'];
318 } elseif ( is_array( $configArray ) ) {
319 foreach ( $configArray as $sectionName => $sectionConf ) {
320 if ( substr( $sectionName, 0, 6 ) ==
'remote' ) {
321 $remote = $sectionConf;
326 if ( $remote !==
false && isset( $remote[
'url'] ) ) {
327 $url = $remote[
'url'];
330 $this->cache[
'remoteURL'] = $url;
332 return $this->cache[
'remoteURL'];
345 return isset( $this->cache[
'head'] ) &&
346 isset( $this->cache[
'headSHA1'] ) &&
347 isset( $this->cache[
'headCommitDate'] ) &&
348 isset( $this->cache[
'branch'] ) &&
349 isset( $this->cache[
'remoteURL'] );
362 if ( $this->cacheFile !==
null ) {
372 "Failed to compute GitInfo for \"{$this->basedir}\""
377 $cacheDir = dirname( $this->cacheFile );
378 if ( !file_exists( $cacheDir ) &&
381 throw new MWException(
"Unable to create GitInfo cache \"{$cacheDir}\"" );
419 if ( self::$viewers ===
false ) {
421 Hooks::run(
'GitViewers', [ &self::$viewers ] );