58 public function __construct( $repoDir, $usePrecomputed =
true ) {
61 "Computed cacheFile={$this->cacheFile} for {$repoDir}"
63 if ( $usePrecomputed &&
64 $this->cacheFile !==
null &&
65 is_readable( $this->cacheFile )
68 file_get_contents( $this->cacheFile ),
71 wfDebugLog(
'gitinfo',
"Loaded git data from cache for {$repoDir}" );
75 wfDebugLog(
'gitinfo',
"Cache incomplete for {$repoDir}" );
76 $this->basedir = $repoDir . DIRECTORY_SEPARATOR .
'.git';
77 if ( is_readable( $this->basedir ) && !is_dir( $this->basedir ) ) {
78 $GITfile = file_get_contents( $this->basedir );
79 if ( strlen( $GITfile ) > 8 &&
80 substr( $GITfile, 0, 8 ) ===
'gitdir: '
82 $path = rtrim( substr( $GITfile, 8 ),
"\r\n" );
83 if (
$path[0] ===
'/' || substr(
$path, 1, 1 ) ===
':' ) {
85 $this->basedir =
$path;
87 $this->basedir = $repoDir . DIRECTORY_SEPARATOR .
$path;
108 $realIP = realpath(
$IP );
109 $repoName = realpath( $repoDir );
110 if ( $repoName ===
false ) {
112 $repoName = $repoDir;
114 if ( strpos( $repoName, $realIP ) === 0 ) {
116 $repoName = substr( $repoName, strlen( $realIP ) );
120 $repoName = strtr( $repoName, DIRECTORY_SEPARATOR,
'-' );
121 $fileName =
'info' . $repoName .
'.json';
122 $cachePath =
"{$wgGitInfoCacheDirectory}/{$fileName}";
123 if ( is_readable( $cachePath ) ) {
128 return "$repoDir/gitinfo.json";
136 public static function repo() {
137 if ( is_null( self::$repo ) ) {
139 self::$repo =
new self(
$IP );
151 return !!preg_match(
'/^[0-9A-F]{40}$/i', $str );
160 if ( !isset( $this->
cache[
'head'] ) ) {
161 $headFile =
"{$this->basedir}/HEAD";
164 if ( is_readable( $headFile ) ) {
165 $head = file_get_contents( $headFile );
167 if ( preg_match(
"/ref: (.*)/", $head, $m ) ) {
168 $head = rtrim( $m[1] );
170 $head = rtrim( $head );
173 $this->
cache[
'head'] = $head;
175 return $this->
cache[
'head'];
184 if ( !isset( $this->
cache[
'headSHA1'] ) ) {
189 if ( self::isSHA1( $head ) ) {
193 $refFile =
"{$this->basedir}/{$head}";
194 if ( is_readable( $refFile ) ) {
195 $sha1 = rtrim( file_get_contents( $refFile ) );
198 $this->
cache[
'headSHA1'] = $sha1;
200 return $this->
cache[
'headSHA1'];
212 if ( !isset( $this->
cache[
'headCommitDate'] ) ) {
220 " show -s --format=format:%ct HEAD";
222 $commitDate =
wfShellExec( $cmd, $retc, $environment );
224 $date = (int)$commitDate;
227 $this->
cache[
'headCommitDate'] = $date;
229 return $this->
cache[
'headCommitDate'];
238 if ( !isset( $this->
cache[
'branch'] ) ) {
241 preg_match(
"#^refs/heads/(.*)$#", $branch, $m )
245 $this->
cache[
'branch'] = $branch;
247 return $this->
cache[
'branch'];
257 if ( $url ===
false ) {
260 foreach ( self::getViewers()
as $repo => $viewer ) {
261 $pattern =
'#^' .
$repo .
'$#';
262 if ( preg_match( $pattern, $url,
$matches ) ) {
263 $viewerUrl = preg_replace( $pattern, $viewer, $url );
266 '%h' => substr( $headSHA1, 0, 7 ),
271 return strtr( $viewerUrl, $replacements );
282 if ( !isset( $this->
cache[
'remoteURL'] ) ) {
283 $config =
"{$this->basedir}/config";
285 if ( is_readable( $config ) ) {
286 MediaWiki\suppressWarnings();
287 $configArray = parse_ini_file( $config,
true );
288 MediaWiki\restoreWarnings();
292 if ( isset( $configArray[
'remote origin'] ) ) {
293 $remote = $configArray[
'remote origin'];
294 } elseif ( is_array( $configArray ) ) {
295 foreach ( $configArray
as $sectionName => $sectionConf ) {
296 if ( substr( $sectionName, 0, 6 ) ==
'remote' ) {
297 $remote = $sectionConf;
302 if ( $remote !==
false && isset( $remote[
'url'] ) ) {
303 $url = $remote[
'url'];
306 $this->
cache[
'remoteURL'] = $url;
308 return $this->
cache[
'remoteURL'];
321 return isset( $this->
cache[
'head'] ) &&
322 isset( $this->
cache[
'headSHA1'] ) &&
323 isset( $this->
cache[
'headCommitDate'] ) &&
324 isset( $this->
cache[
'branch'] ) &&
325 isset( $this->
cache[
'remoteURL'] );
338 if ( $this->cacheFile !==
null ) {
348 "Failed to compute GitInfo for \"{$this->basedir}\""
353 $cacheDir = dirname( $this->cacheFile );
354 if ( !file_exists( $cacheDir ) &&
357 throw new MWException(
"Unable to create GitInfo cache \"{$cacheDir}\"" );
395 if ( self::$viewers ===
false ) {
397 Hooks::run(
'GitViewers', [ &self::$viewers ] );