29 use Wikimedia\AtEase\AtEase;
78 "Candidate cacheFile={$this->cacheFile} for {$repoDir}"
80 if ( $usePrecomputed &&
81 $this->cacheFile !==
null &&
82 is_readable( $this->cacheFile )
85 file_get_contents( $this->cacheFile ),
88 wfDebugLog(
'gitinfo',
"Loaded git data from cache for {$repoDir}" );
92 wfDebugLog(
'gitinfo',
"Cache incomplete for {$repoDir}" );
93 $this->basedir =
$repoDir . DIRECTORY_SEPARATOR .
'.git';
94 if ( is_readable( $this->basedir ) && !is_dir( $this->basedir ) ) {
95 $GITfile = file_get_contents( $this->basedir );
96 if ( strlen( $GITfile ) > 8 &&
97 substr( $GITfile, 0, 8 ) ===
'gitdir: '
99 $path = rtrim( substr( $GITfile, 8 ),
"\r\n" );
100 if (
$path[0] ===
'/' || substr(
$path, 1, 1 ) ===
':' ) {
102 $this->basedir =
$path;
120 $config = MediaWikiServices::getInstance()->getMainConfig();
121 $gitInfoCacheDirectory = $config->get( MainConfigNames::GitInfoCacheDirectory );
122 if ( $gitInfoCacheDirectory ===
false ) {
123 $gitInfoCacheDirectory = $config->get( MainConfigNames::CacheDirectory ) .
'/gitinfo';
125 $baseDir = $config->get( MainConfigNames::BaseDirectory );
126 if ( $gitInfoCacheDirectory ) {
129 $realIP = realpath( $baseDir );
131 if ( $repoName ===
false ) {
135 if ( strpos( $repoName, $realIP ) === 0 ) {
137 $repoName = substr( $repoName, strlen( $realIP ) );
141 $repoName = strtr( $repoName, DIRECTORY_SEPARATOR,
'-' );
142 $fileName =
'info' . $repoName .
'.json';
143 $cachePath =
"{$gitInfoCacheDirectory}/{$fileName}";
144 if ( is_readable( $cachePath ) ) {
149 return "$repoDir/gitinfo.json";
157 public static function repo() {
158 if ( self::$repo ===
null ) {
159 self::$repo =
new self( MW_INSTALL_PATH );
171 return (
bool)preg_match(
'/^[0-9A-F]{40}$/i', $str );
180 if ( !isset( $this->cache[
'head'] ) ) {
181 $headFile =
"{$this->basedir}/HEAD";
184 if ( is_readable( $headFile ) ) {
185 $head = file_get_contents( $headFile );
187 if ( preg_match(
"/ref: (.*)/", $head, $m ) ) {
188 $head = rtrim( $m[1] );
190 $head = rtrim( $head );
193 $this->cache[
'head'] = $head;
195 return $this->cache[
'head'];
204 if ( !isset( $this->cache[
'headSHA1'] ) ) {
209 if ( self::isSHA1( $head ) ) {
213 $refFile =
"{$this->basedir}/{$head}";
214 $packedRefs =
"{$this->basedir}/packed-refs";
215 $headRegex = preg_quote( $head,
'/' );
216 if ( is_readable( $refFile ) ) {
217 $sha1 = rtrim( file_get_contents( $refFile ) );
218 } elseif ( is_readable( $packedRefs ) &&
219 preg_match(
"/^([0-9A-Fa-f]{40}) $headRegex$/m", file_get_contents( $packedRefs ),
$matches )
224 $this->cache[
'headSHA1'] = $sha1;
226 return $this->cache[
'headSHA1'];
236 $gitBin = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::GitBin );
238 if ( !isset( $this->cache[
'headCommitDate'] ) ) {
242 $isFile = AtEase::quietCall(
'is_file', $gitBin );
244 is_executable( $gitBin ) &&
245 !Shell::isDisabled() &&
252 '--format=format:%ct',
255 $gitDir = realpath( $this->basedir );
256 $result = Shell::command( $cmd )
257 ->environment( [
'GIT_DIR' => $gitDir ] )
258 ->restrict( Shell::RESTRICT_DEFAULT | Shell::NO_NETWORK )
259 ->whitelistPaths( [ $gitDir, $this->repoDir ] )
262 if ( $result->getExitCode() === 0 ) {
263 $date = (int)$result->getStdout();
266 $this->cache[
'headCommitDate'] = $date;
268 return $this->cache[
'headCommitDate'];
277 if ( !isset( $this->cache[
'branch'] ) ) {
280 preg_match(
"#^refs/heads/(.*)$#", $branch, $m )
284 $this->cache[
'branch'] = $branch;
286 return $this->cache[
'branch'];
296 if ( $url ===
false ) {
299 foreach ( self::getViewers() as
$repo => $viewer ) {
300 $pattern =
'#^' .
$repo .
'$#';
301 if ( preg_match( $pattern, $url,
$matches ) ) {
302 $viewerUrl = preg_replace( $pattern, $viewer, $url );
305 '%h' => substr( $headSHA1, 0, 7 ),
310 return strtr( $viewerUrl, $replacements );
321 if ( !isset( $this->cache[
'remoteURL'] ) ) {
322 $config =
"{$this->basedir}/config";
324 if ( is_readable( $config ) ) {
325 AtEase::suppressWarnings();
326 $configArray = parse_ini_file( $config,
true );
327 AtEase::restoreWarnings();
331 if ( isset( $configArray[
'remote origin'] ) ) {
332 $remote = $configArray[
'remote origin'];
333 } elseif ( is_array( $configArray ) ) {
334 foreach ( $configArray as $sectionName => $sectionConf ) {
335 if ( substr( $sectionName, 0, 6 ) ==
'remote' ) {
336 $remote = $sectionConf;
341 if ( $remote !==
false && isset( $remote[
'url'] ) ) {
342 $url = $remote[
'url'];
345 $this->cache[
'remoteURL'] = $url;
347 return $this->cache[
'remoteURL'];
360 return isset( $this->cache[
'head'] ) &&
361 isset( $this->cache[
'headSHA1'] ) &&
362 isset( $this->cache[
'headCommitDate'] ) &&
363 isset( $this->cache[
'branch'] ) &&
364 isset( $this->cache[
'remoteURL'] );
377 if ( $this->cacheFile !==
null ) {
387 "Failed to compute GitInfo for \"{$this->basedir}\""
392 $cacheDir = dirname( $this->cacheFile );
393 if ( !file_exists( $cacheDir ) &&
396 throw new MWException(
"Unable to create GitInfo cache \"{$cacheDir}\"" );
432 $gitRepositoryViewers = MediaWikiServices::getInstance()->getMainConfig()
433 ->get( MainConfigNames::GitRepositoryViewers );
435 if ( self::$viewers ===
false ) {
436 self::$viewers = $gitRepositoryViewers;
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 MW_INSTALL_PATH.
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.
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
A class containing constants representing the names of configuration variables.