MediaWiki  master
makeRepo.php
Go to the documentation of this file.
1 <?php
2 
4 
5 require __DIR__ . '/../Maintenance.php';
6 
7 class HHVMMakeRepo extends Maintenance {
8  function __construct() {
9  parent::__construct();
10  $this->addDescription( 'Compile PHP sources for this MediaWiki instance, ' .
11  'and generate an HHVM bytecode file to be used with HHVM\'s ' .
12  'RepoAuthoritative mode. The MediaWiki core installation path and ' .
13  'all registered extensions are automatically searched for the file ' .
14  'extensions *.php, *.inc, *.php5 and *.phtml.' );
15  $this->addOption( 'output', 'Output filename', true, true, 'o' );
16  $this->addOption( 'input-dir', 'Add an input directory. ' .
17  'This can be specified multiple times.', false, true, 'd', true );
18  $this->addOption( 'exclude-dir', 'Directory to exclude. ' .
19  'This can be specified multiple times.', false, true, false, true );
20  $this->addOption( 'extension', 'Extra file extension', false, true, false, true );
21  $this->addOption( 'hhvm', 'Location of HHVM binary', false, true );
22  $this->addOption( 'base-dir', 'The root of all source files. ' .
23  'This must match hhvm.server.source_root in the server\'s configuration file. ' .
24  'By default, the MW core install path will be used.',
25  false, true );
26  $this->addOption( 'verbose', 'Log level 0-3', false, true, 'v' );
27  }
28 
29  private static function startsWith( $subject, $search ) {
30  return substr( $subject, 0, strlen( $search ) === $search );
31  }
32 
33  function execute() {
34  global $wgExtensionCredits, $IP;
35 
36  $dirs = [ $IP ];
37 
38  foreach ( $wgExtensionCredits as $type => $extensions ) {
39  foreach ( $extensions as $extension ) {
40  if ( isset( $extension['path'] )
41  && !self::startsWith( $extension['path'], $IP )
42  ) {
43  $dirs[] = dirname( $extension['path'] );
44  }
45  }
46  }
47 
48  $dirs = array_merge( $dirs, $this->getOption( 'input-dir', [] ) );
49  $fileExts =
50  [
51  'php' => true,
52  'inc' => true,
53  'php5' => true,
54  'phtml' => true
55  ] +
56  array_flip( $this->getOption( 'extension', [] ) );
57 
58  $dirs = array_unique( $dirs );
59 
60  $baseDir = $this->getOption( 'base-dir', $IP );
61  $excludeDirs = array_map( 'realpath', $this->getOption( 'exclude-dir', [] ) );
62 
63  if ( $baseDir !== '' && substr( $baseDir, -1 ) !== '/' ) {
64  $baseDir .= '/';
65  }
66 
67  $unfilteredFiles = [ "$IP/LocalSettings.php" ];
68  foreach ( $dirs as $dir ) {
69  $this->appendDir( $unfilteredFiles, $dir );
70  }
71 
72  $files = [];
73  foreach ( $unfilteredFiles as $file ) {
74  $dotPos = strrpos( $file, '.' );
75  $slashPos = strrpos( $file, '/' );
76  if ( $dotPos === false || $slashPos === false || $dotPos < $slashPos ) {
77  continue;
78  }
79  $extension = substr( $file, $dotPos + 1 );
80  if ( !isset( $fileExts[$extension] ) ) {
81  continue;
82  }
83  $canonical = realpath( $file );
84  foreach ( $excludeDirs as $excluded ) {
85  if ( self::startsWith( $canonical, $excluded ) ) {
86  continue 2;
87  }
88  }
89  if ( self::startsWith( $file, $baseDir ) ) {
90  $file = substr( $file, strlen( $baseDir ) );
91  }
92  $files[] = $file;
93  }
94 
95  $files = array_unique( $files );
96 
97  print "Found " . count( $files ) . " files in " .
98  count( $dirs ) . " directories\n";
99 
100  $tmpDir = wfTempDir() . '/mw-make-repo' . mt_rand( 0, 1 << 31 );
101  if ( !mkdir( $tmpDir ) ) {
102  $this->fatalError( 'Unable to create temporary directory' );
103  }
104  file_put_contents( "$tmpDir/file-list", implode( "\n", $files ) );
105 
106  $hhvm = $this->getOption( 'hhvm', 'hhvm' );
107  $verbose = $this->getOption( 'verbose', 3 );
108  $cmd = Shell::escape(
109  $hhvm,
110  '--hphp',
111  '--target', 'hhbc',
112  '--format', 'binary',
113  '--force', '1',
114  '--keep-tempdir', '1',
115  '--log', $verbose,
116  '-v', 'AllVolatile=true',
117  '--input-dir', $baseDir,
118  '--input-list', "$tmpDir/file-list",
119  '--output-dir', $tmpDir );
120  print "$cmd\n";
121  passthru( $cmd, $ret );
122  if ( $ret ) {
123  $this->cleanupTemp( $tmpDir );
124  $this->fatalError( "Error: HHVM returned error code $ret" );
125  }
126  if ( !rename( "$tmpDir/hhvm.hhbc", $this->getOption( 'output' ) ) ) {
127  $this->cleanupTemp( $tmpDir );
128  $this->fatalError( "Error: unable to rename output file" );
129  }
130  $this->cleanupTemp( $tmpDir );
131  return 0;
132  }
133 
134  private function cleanupTemp( $tmpDir ) {
135  if ( file_exists( "$tmpDir/hhvm.hhbc" ) ) {
136  unlink( "$tmpDir/hhvm.hhbc" );
137  }
138  if ( file_exists( "$tmpDir/Stats.js" ) ) {
139  unlink( "$tmpDir/Stats.js" );
140  }
141 
142  unlink( "$tmpDir/file-list" );
143  rmdir( $tmpDir );
144  }
145 
146  private function appendDir( &$files, $dir ) {
147  $iter = new RecursiveIteratorIterator(
148  new RecursiveDirectoryIterator(
149  $dir,
150  FilesystemIterator::UNIX_PATHS
151  ),
152  RecursiveIteratorIterator::LEAVES_ONLY
153  );
155  foreach ( $iter as $file => $fileInfo ) {
156  if ( $fileInfo->isFile() ) {
157  $files[] = $file;
158  }
159  }
160  }
161 }
162 
163 $maintClass = HHVMMakeRepo::class;
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
$wgExtensionCredits
An array of information about installed extensions keyed by their type.
const RUN_MAINTENANCE_IF_MAIN
Definition: Maintenance.php:39
appendDir(&$files, $dir)
Definition: makeRepo.php:146
$IP
Definition: WebStart.php:41
getOption( $name, $default=null)
Get an option, or return the default.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:82
cleanupTemp( $tmpDir)
Definition: makeRepo.php:134
wfTempDir()
Tries to get the system directory for temporary files.
$maintClass
Definition: makeRepo.php:163
addDescription( $text)
Set the description text.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
return true
Definition: router.php:82
static startsWith( $subject, $search)
Definition: makeRepo.php:29