69 "Candidate cacheFile={$this->cacheFile} for {$repoDir}"
71 if ( $usePrecomputed &&
72 $this->cacheFile !==
null &&
73 is_readable( $this->cacheFile )
75 $this->cache = FormatJson::decode(
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}\"" );
384 file_put_contents( $this->cacheFile, FormatJson::encode( $this->cache ) );
419 if ( self::$viewers ===
false ) {
421 Hooks::run(
'GitViewers', [ &self::$viewers ] );
$wgGitRepositoryViewers
Map GIT repository URLs to viewer URLs to provide links in Special:Version.
$wgGitInfoCacheDirectory
Directory where GitInfo will look for pre-computed cache files.
$wgGitBin
Fully specified path to git binary.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
static repo()
Get the singleton for the repo at $IP.
getHead()
Get the HEAD of the repo (without any opening "ref: ")
static getCacheFilePath( $repoDir)
Compute the path to the cache file for a given directory.
static array false $viewers
Map of repo URLs to viewer URLs.
$cacheFile
Path to JSON cache file for pre-computed git information.
$basedir
Location of the .git directory.
getRemoteUrl()
Get the URL of the remote origin.
getHeadCommitDate()
Get the commit date of HEAD entry of the git code repository.
precomputeValues()
Precompute and cache git information.
$cache
Cached git information.
cacheIsComplete()
Check to see if the current cache is fully populated.
static $repo
Singleton for the repo at $IP.
$repoDir
Location of the repository.
getHeadViewUrl()
Get an URL to a web viewer link to the HEAD revision.
__construct( $repoDir, $usePrecomputed=true)
static isSHA1( $str)
Check if a string looks like a hex encoded SHA1 hash.
getHeadSHA1()
Get the SHA1 for the current HEAD of the repo.
getCurrentBranch()
Get the name of the current branch, or HEAD if not found.
static getViewers()
Gets the list of repository viewers.