MediaWiki  REL1_23
GitInfo.php
Go to the documentation of this file.
00001 <?php
00026 class GitInfo {
00027 
00031     protected static $repo = null;
00032 
00036     protected $basedir;
00037 
00041     private static $viewers = false;
00042 
00046     public function __construct( $dir ) {
00047         $this->basedir = $dir . DIRECTORY_SEPARATOR . '.git';
00048         if ( is_readable( $this->basedir ) && !is_dir( $this->basedir ) ) {
00049             $GITfile = file_get_contents( $this->basedir );
00050             if ( strlen( $GITfile ) > 8 && substr( $GITfile, 0, 8 ) === 'gitdir: ' ) {
00051                 $path = rtrim( substr( $GITfile, 8 ), "\r\n" );
00052                 $isAbsolute = $path[0] === '/' || substr( $path, 1, 1 ) === ':';
00053                 $this->basedir = $isAbsolute ? $path : $dir . DIRECTORY_SEPARATOR . $path;
00054             }
00055         }
00056     }
00057 
00062     public static function repo() {
00063         global $IP;
00064         if ( is_null( self::$repo ) ) {
00065             self::$repo = new self( $IP );
00066         }
00067         return self::$repo;
00068     }
00069 
00076     public static function isSHA1( $str ) {
00077         return !!preg_match( '/^[0-9A-F]{40}$/i', $str );
00078     }
00079 
00084     public function getHead() {
00085         $headFile = "{$this->basedir}/HEAD";
00086 
00087         if ( !is_readable( $headFile ) ) {
00088             return false;
00089         }
00090 
00091         $head = file_get_contents( $headFile );
00092 
00093         if ( preg_match( "/ref: (.*)/", $head, $m ) ) {
00094             return rtrim( $m[1] );
00095         } else {
00096             return rtrim( $head );
00097         }
00098     }
00099 
00104     public function getHeadSHA1() {
00105         $head = $this->getHead();
00106 
00107         // If detached HEAD may be a SHA1
00108         if ( self::isSHA1( $head ) ) {
00109             return $head;
00110         }
00111 
00112         // If not a SHA1 it may be a ref:
00113         $refFile = "{$this->basedir}/{$head}";
00114         if ( !is_readable( $refFile ) ) {
00115             return false;
00116         }
00117 
00118         $sha1 = rtrim( file_get_contents( $refFile ) );
00119 
00120         return $sha1;
00121     }
00122 
00129     public function getHeadCommitDate() {
00130         global $wgGitBin;
00131 
00132         if ( !is_file( $wgGitBin ) || !is_executable( $wgGitBin ) ) {
00133             return false;
00134         }
00135 
00136         $environment = array( "GIT_DIR" => $this->basedir );
00137         $cmd = wfEscapeShellArg( $wgGitBin ) . " show -s --format=format:%ct HEAD";
00138         $retc = false;
00139         $commitDate = wfShellExec( $cmd, $retc, $environment );
00140 
00141         if ( $retc !== 0 ) {
00142             return false;
00143         } else {
00144             return (int)$commitDate;
00145         }
00146     }
00147 
00152     public function getCurrentBranch() {
00153         $head = $this->getHead();
00154         if ( $head && preg_match( "#^refs/heads/(.*)$#", $head, $m ) ) {
00155             return $m[1];
00156         } else {
00157             return $head;
00158         }
00159     }
00160 
00166     public function getHeadViewUrl() {
00167         $config = "{$this->basedir}/config";
00168         if ( !is_readable( $config ) ) {
00169             return false;
00170         }
00171 
00172         wfSuppressWarnings();
00173         $configArray = parse_ini_file( $config, true );
00174         wfRestoreWarnings();
00175         $remote = false;
00176 
00177         // Use the "origin" remote repo if available or any other repo if not.
00178         if ( isset( $configArray['remote origin'] ) ) {
00179             $remote = $configArray['remote origin'];
00180         } elseif ( is_array( $configArray ) ) {
00181             foreach ( $configArray as $sectionName => $sectionConf ) {
00182                 if ( substr( $sectionName, 0, 6 ) == 'remote' ) {
00183                     $remote = $sectionConf;
00184                 }
00185             }
00186         }
00187 
00188         if ( $remote === false || !isset( $remote['url'] ) ) {
00189             return false;
00190         }
00191 
00192         $url = $remote['url'];
00193         if ( substr( $url, -4 ) !== '.git' ) {
00194             $url .= '.git';
00195         }
00196         foreach ( self::getViewers() as $repo => $viewer ) {
00197             $pattern = '#^' . $repo . '$#';
00198             if ( preg_match( $pattern, $url, $matches ) ) {
00199                 $viewerUrl = preg_replace( $pattern, $viewer, $url );
00200                 $headSHA1 = $this->getHeadSHA1();
00201                 $replacements = array(
00202                     '%h' => substr( $headSHA1, 0, 7 ),
00203                     '%H' => $headSHA1,
00204                     '%r' => urlencode( $matches[1] ),
00205                 );
00206                 return strtr( $viewerUrl, $replacements );
00207             }
00208         }
00209         return false;
00210     }
00211 
00216     public static function headSHA1() {
00217         return self::repo()->getHeadSHA1();
00218     }
00219 
00224     public static function currentBranch() {
00225         return self::repo()->getCurrentBranch();
00226     }
00227 
00232     public static function headViewUrl() {
00233         return self::repo()->getHeadViewUrl();
00234     }
00235 
00240     protected static function getViewers() {
00241         global $wgGitRepositoryViewers;
00242 
00243         if ( self::$viewers === false ) {
00244             self::$viewers = $wgGitRepositoryViewers;
00245             wfRunHooks( 'GitViewers', array( &self::$viewers ) );
00246         }
00247 
00248         return self::$viewers;
00249     }
00250 }