-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f2ff40d
commit ed20113
Showing
1 changed file
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
#!/usr/bin/php | ||
<?php | ||
|
||
/* | ||
Manipulates version of bcc. | ||
*/ | ||
|
||
define( 'PROJECT_DIR', dirname( __DIR__ ) ); | ||
define( 'SRC_DIR', PROJECT_DIR . '/src' ); | ||
define( 'BUILD_DIR', PROJECT_DIR . '/build' ); | ||
define( 'VERSION_FILE', BUILD_DIR . '/version.c' ); | ||
define( 'RELEASE_VERSION_FILE', SRC_DIR . '/version.c' ); | ||
define( 'EXIT_SUCCESS', 0 ); | ||
define( 'EXIT_FAILURE', 1 ); | ||
|
||
class task { | ||
public $script_path; | ||
public $command; | ||
public $major_number; | ||
public $minor_number; | ||
public $patch_number; | ||
// Number of compilations since the last release (public) version. | ||
public $build_number; | ||
public $commit; | ||
|
||
private function __construct( $argv ) { | ||
$this->script_path = $argv[ 0 ]; | ||
$this->command = ''; | ||
$this->major_number = 0; | ||
$this->minor_number = 0; | ||
$this->patch_number = 0; | ||
$this->build_number = 0; | ||
$this->commit = ''; | ||
} | ||
|
||
private function read_command() { | ||
$options = getopt( '', array( | ||
'help', | ||
'show', | ||
'bump-major', | ||
'bump-minor', | ||
'bump-patch', | ||
'bump-build', | ||
'reset', | ||
) ); | ||
if ( count( $options ) > 0 ) { | ||
$this->command = key( $options ); | ||
} | ||
} | ||
|
||
private function execute_command() { | ||
switch ( $this->command ) { | ||
case 'help': | ||
$this->handle_help(); | ||
break; | ||
case 'show': | ||
$this->handle_show(); | ||
break; | ||
case 'bump-major': | ||
$this->handle_bump_major(); | ||
break; | ||
case 'bump-minor': | ||
$this->handle_bump_minor(); | ||
break; | ||
case 'bump-patch': | ||
$this->handle_bump_patch(); | ||
break; | ||
case 'bump-build': | ||
$this->handle_bump_build(); | ||
break; | ||
case 'reset': | ||
$this->handle_reset(); | ||
break; | ||
case '': | ||
$this->handle_empty(); | ||
break; | ||
default: | ||
$this->show_err( | ||
"unhandled command: " . $this->command ); | ||
$this->bail(); | ||
} | ||
} | ||
|
||
private function handle_help() { | ||
$this->show_help(); | ||
} | ||
|
||
private function show_help() { | ||
printf( | ||
"Usage: %s [option]\n" . | ||
"Options:\n" . | ||
" --help Show this help information\n" . | ||
" --show Show current version\n" . | ||
" --bump-major Bump major number of version\n" . | ||
" --bump-minor Bump minor number of version\n" . | ||
" --bump-patch Bump patch number of version\n" . | ||
" --bump-build Bump build number of version\n" . | ||
" --reset Set version back to the initial version\n", | ||
$this->script_path ); | ||
} | ||
|
||
private function handle_show() { | ||
$this->load_version(); | ||
printf( "%s\n", $this->encode_version() ); | ||
} | ||
|
||
private function load_version() { | ||
$contents = @file_get_contents( VERSION_FILE ); | ||
if ( $contents === false ) { | ||
$this->show_err(); | ||
$this->bail(); | ||
} | ||
$matches = array(); | ||
$result = preg_match( '/const char\* c_version = "([^"]+)";$/', | ||
$contents, $matches ); | ||
if ( $result !== 1 ) { | ||
$this->show_err( 'version file (' . VERSION_FILE . | ||
') of incorrect format' ); | ||
$this->bail(); | ||
} | ||
$this->decode_version( $matches[ 1 ] ); | ||
} | ||
|
||
private function save_version( $release_version = false ) { | ||
$version = $this->encode_version(); | ||
$this->write_version_file( VERSION_FILE, $version ); | ||
if ( $release_version ) { | ||
$this->write_version_file( RELEASE_VERSION_FILE, $version ); | ||
} | ||
} | ||
|
||
private function write_version_file( $file, $version ) { | ||
$written = @file_put_contents( $file, sprintf( | ||
"// NOTE: This file is automatically generated by this script: \n" . | ||
"// %s\n" . | ||
"const char* c_version = \"%s\";\n", __FILE__, $version ) ); | ||
if ( $written === false ) { | ||
$this->show_err(); | ||
$this->bail(); | ||
} | ||
} | ||
|
||
private function encode_version() { | ||
$version = sprintf( '%d.%d.%d', | ||
$this->major_number, | ||
$this->minor_number, | ||
$this->patch_number ); | ||
if ( $this->is_development_version() ) { | ||
$version = sprintf( '%s+%s.%d', | ||
$version, | ||
$this->get_latest_commit_hash(), | ||
$this->build_number ); | ||
} | ||
return $version; | ||
} | ||
|
||
private function is_development_version() { | ||
// A nonzero build number indicates a development version. | ||
return ( $this->build_number > 0 ); | ||
} | ||
|
||
private function decode_version( $version ) { | ||
$matches = array(); | ||
$result = preg_match( | ||
'/^([0-9]+)\.([0-9]+)\.([0-9]+)(\+([a-z0-9]+)\.([0-9]+))?$/', | ||
$version, $matches ); | ||
if ( $result !== 1 ) { | ||
$this->show_err( "version string of incorrect format" ); | ||
$this->bail(); | ||
} | ||
$this->major_number = ( int ) $matches[ 1 ]; | ||
$this->minor_number = ( int ) $matches[ 2 ]; | ||
$this->patch_number = ( int ) $matches[ 3 ]; | ||
if ( count( $matches ) == 7 ) { | ||
$this->commit = $matches[ 5 ]; | ||
$this->build_number = ( int ) $matches[ 6 ]; | ||
} | ||
} | ||
|
||
private function get_latest_commit_hash() { | ||
$code = 1; | ||
$lines = array(); | ||
exec( 'git --no-pager log -n 1 --pretty="%H"', $lines, $code ); | ||
if ( ! ( $code == 0 && count( $lines ) == 1 ) ) { | ||
$this->showErr( 'could not get hash of latest commit' ); | ||
$this->bail(); | ||
} | ||
return $lines[ 0 ]; | ||
} | ||
|
||
private function handle_bump_major() { | ||
$this->load_version(); | ||
++$this->major_number; | ||
$this->minor_number = 0; | ||
$this->patch_number = 0; | ||
$this->build_number = 0; | ||
$this->save_version( true ); | ||
} | ||
|
||
private function handle_bump_minor() { | ||
$this->load_version(); | ||
++$this->minor_number; | ||
$this->patch_number = 0; | ||
$this->build_number = 0; | ||
$this->save_version( true ); | ||
} | ||
|
||
private function handle_bump_patch() { | ||
$this->load_version(); | ||
++$this->patch_number; | ||
$this->build_number = 0; | ||
$this->save_version( true ); | ||
} | ||
|
||
private function handle_bump_build() { | ||
$this->load_version(); | ||
++$this->build_number; | ||
$this->save_version(); | ||
} | ||
|
||
private function handle_reset() { | ||
$this->save_version( true ); | ||
} | ||
|
||
private function handle_empty() { | ||
$this->show_help(); | ||
$this->bail(); | ||
} | ||
|
||
private function show_err( $msg = '' ) { | ||
$prefix = sprintf( '%s', basename( $this->script_path ) ); | ||
if ( $msg == '' ) { | ||
$err = error_get_last(); | ||
if ( $err !== null ) { | ||
$prefix = sprintf( '%s:%d', $prefix, $err[ 'line' ] ); | ||
$msg = $err[ 'message' ]; | ||
} | ||
} | ||
printf( "%s: error: %s\n", $prefix, $msg ); | ||
} | ||
|
||
private function bail() { | ||
throw new Exception(); | ||
} | ||
|
||
public static function run( $argv ) { | ||
try { | ||
$task = new task( $argv ); | ||
$task->read_command(); | ||
$task->execute_command(); | ||
exit( EXIT_SUCCESS ); | ||
} | ||
catch ( Exception $e ) { | ||
exit( EXIT_FAILURE ); | ||
} | ||
} | ||
}; | ||
|
||
task::run( $argv ); |