27 use Wikimedia\AtEase\AtEase;
76 "Candidate cacheFile={$this->cacheFile} for {$repoDir}"
78 if ( $usePrecomputed &&
79 $this->cacheFile !==
null &&
80 is_readable( $this->cacheFile )
83 file_get_contents( $this->cacheFile ),
86 wfDebugLog(
'gitinfo',
"Loaded git data from cache for {$repoDir}" );
90 wfDebugLog(
'gitinfo',
"Cache incomplete for {$repoDir}" );
91 $this->basedir =
$repoDir . DIRECTORY_SEPARATOR .
'.git';
92 if ( is_readable( $this->basedir ) && !is_dir( $this->basedir ) ) {
93 $GITfile = file_get_contents( $this->basedir );
94 if ( strlen( $GITfile ) > 8 &&
95 substr( $GITfile, 0, 8 ) ===
'gitdir: '
97 $path = rtrim( substr( $GITfile, 8 ),
"\r\n" );
98 if (
$path[0] ===
'/' || substr(
$path, 1, 1 ) ===
':' ) {
100 $this->basedir =
$path;
123 $realIP = realpath(
$IP );
125 if ( $repoName ===
false ) {
129 if ( strpos( $repoName, $realIP ) === 0 ) {
131 $repoName = substr( $repoName, strlen( $realIP ) );
135 $repoName = strtr( $repoName, DIRECTORY_SEPARATOR,
'-' );
136 $fileName =
'info' . $repoName .
'.json';
137 $cachePath =
"{$wgGitInfoCacheDirectory}/{$fileName}";
138 if ( is_readable( $cachePath ) ) {
143 return "$repoDir/gitinfo.json";
151 public static function repo() {
152 if ( self::$repo ===
null ) {
154 self::$repo =
new self(
$IP );
166 return (
bool)preg_match(
'/^[0-9A-F]{40}$/i', $str );
175 if ( !isset( $this->cache[
'head'] ) ) {
176 $headFile =
"{$this->basedir}/HEAD";
179 if ( is_readable( $headFile ) ) {
180 $head = file_get_contents( $headFile );
182 if ( preg_match(
"/ref: (.*)/", $head, $m ) ) {
183 $head = rtrim( $m[1] );
185 $head = rtrim( $head );
188 $this->cache[
'head'] = $head;
190 return $this->cache[
'head'];
199 if ( !isset( $this->cache[
'headSHA1'] ) ) {
204 if ( self::isSHA1( $head ) ) {
208 $refFile =
"{$this->basedir}/{$head}";
209 $packedRefs =
"{$this->basedir}/packed-refs";
210 $headRegex = preg_quote( $head,
'/' );
211 if ( is_readable( $refFile ) ) {
212 $sha1 = rtrim( file_get_contents( $refFile ) );
213 } elseif ( is_readable( $packedRefs ) &&
214 preg_match(
"/^([0-9A-Fa-f]{40}) $headRegex$/m", file_get_contents( $packedRefs ),
$matches )
219 $this->cache[
'headSHA1'] = $sha1;
221 return $this->cache[
'headSHA1'];
233 if ( !isset( $this->cache[
'headCommitDate'] ) ) {
237 $isFile = AtEase::quietCall(
'is_file',
$wgGitBin );
240 !Shell::isDisabled() &&
247 '--format=format:%ct',
250 $gitDir = realpath( $this->basedir );
251 $result = Shell::command( $cmd )
252 ->environment( [
'GIT_DIR' => $gitDir ] )
253 ->restrict( Shell::RESTRICT_DEFAULT | Shell::NO_NETWORK )
254 ->whitelistPaths( [ $gitDir, $this->repoDir ] )
257 if ( $result->getExitCode() === 0 ) {
258 $date = (int)$result->getStdout();
261 $this->cache[
'headCommitDate'] = $date;
263 return $this->cache[
'headCommitDate'];
272 if ( !isset( $this->cache[
'branch'] ) ) {
275 preg_match(
"#^refs/heads/(.*)$#", $branch, $m )
279 $this->cache[
'branch'] = $branch;
281 return $this->cache[
'branch'];
291 if ( $url ===
false ) {
294 foreach ( self::getViewers() as
$repo => $viewer ) {
295 $pattern =
'#^' .
$repo .
'$#';
296 if ( preg_match( $pattern, $url,
$matches ) ) {
297 $viewerUrl = preg_replace( $pattern, $viewer, $url );
300 '%h' => substr( $headSHA1, 0, 7 ),
305 return strtr( $viewerUrl, $replacements );
316 if ( !isset( $this->cache[
'remoteURL'] ) ) {
317 $config =
"{$this->basedir}/config";
319 if ( is_readable( $config ) ) {
320 Wikimedia\suppressWarnings();
321 $configArray = parse_ini_file( $config,
true );
322 Wikimedia\restoreWarnings();
326 if ( isset( $configArray[
'remote origin'] ) ) {
327 $remote = $configArray[
'remote origin'];
328 } elseif ( is_array( $configArray ) ) {
329 foreach ( $configArray as $sectionName => $sectionConf ) {
330 if ( substr( $sectionName, 0, 6 ) ==
'remote' ) {
331 $remote = $sectionConf;
336 if ( $remote !==
false && isset( $remote[
'url'] ) ) {
337 $url = $remote[
'url'];
340 $this->cache[
'remoteURL'] = $url;
342 return $this->cache[
'remoteURL'];
355 return isset( $this->cache[
'head'] ) &&
356 isset( $this->cache[
'headSHA1'] ) &&
357 isset( $this->cache[
'headCommitDate'] ) &&
358 isset( $this->cache[
'branch'] ) &&
359 isset( $this->cache[
'remoteURL'] );
372 if ( $this->cacheFile !==
null ) {
382 "Failed to compute GitInfo for \"{$this->basedir}\""
387 $cacheDir = dirname( $this->cacheFile );
388 if ( !file_exists( $cacheDir ) &&
391 throw new MWException(
"Unable to create GitInfo cache \"{$cacheDir}\"" );
429 if ( self::$viewers ===
false ) {