Skip to content

Instantly share code, notes, and snippets.

@fumikito
Last active September 1, 2015 05:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fumikito/2f644fb9b47c6438c872 to your computer and use it in GitHub Desktop.
Save fumikito/2f644fb9b47c6438c872 to your computer and use it in GitHub Desktop.
Archive files between 2 commits on Git repository
#!/usr/bin/env php
<?php
if( isset( $argv[1] ) && preg_match('/(-{1,2})?help$/', $argv[1] ) ) {
echo <<<'TXT'
/**
* Archive git diff file between specified commit
*
* git_diff ./archive 29879823c HEAD
*
* Enter above, diff between HEAD and 29879823c will be arvhived to `./archive`.
*
* [How to install]
*
*
* @param string $path Output folder's path.
* @param string $hash Target commit's hash.
* @param string $from_hash Origin commit's hash. HEAD if not specified.
*/
TXT;
exit;
}
/**
* Echo
*
* @param string $string
* @param int $lf Number of line feed
*/
function e($string, $lf = 1){
echo $string.implode('', array_map(function($var){
return PHP_EOL;
}, range(0, max(1, $lf) - 1)));
}
/**
* Die
*
* @param $string
*/
function d($sring){
echo $sring.PHP_EOL;
exit;
}
//
// Start processing
//
//
echo <<<TXT
< This is an Git diff tool! >
---------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
TXT;
foreach( [
1 => 'Target path is not specified.',
2 => 'Target commit is not specified.',
] as $index => $msg){
if( !isset($argv[$index]) ){
d('[ERROR] '.$msg);
}
}
$from = isset($argv[3]) ? $argv[3] : 'HEAD';
$to = $argv[2];
$out = $argv[1];
$cur_dir = getcwd();
$summary = <<<'TXT'
=======================
From : %s
To : %s
Target Directory : %s
Current DIrectory: %s
=======================
TXT;
e(sprintf($summary, $from, $to, $out, $cur_dir), 2);
$cmd = escapeshellcmd(sprintf('git diff --name-only %s %s', escapeshellarg($from), escapeshellarg($to)));
$result = exec($cmd, $output);
// 確認
$deleted = [];
$updated = [];
array_map(function($line) use ($cur_dir, &$updated, &$deleted){
$path = $cur_dir.DIRECTORY_SEPARATOR.trim($line);
if( file_exists($path) ){
$updated[] = $line;
}else{
$deleted[] = $line;
}
}, $output);
$summary = <<<'TXT'
[Updated]
%s
==============
[Deleted]
%s
==============
TXT;
e(sprintf($summary, implode(PHP_EOL, $updated), implode(PHP_EOL, $deleted)));
echo 'Are you sure to archive these files? [y/n]';
while($f = fgets(STDIN)){
if( false !== array_search(strtolower(trim($f)), ['y', 'yes']) ){
e('Now archiving...');
break;
}else{
d('Abort!');
}
}
// Create directory
if( !is_dir($out) ){
if( !mkdir($out, 0755, true) ){
d(sprintf('[ERROR] Failed to create %s!', $out));
}
}elseif( !is_writable($out) ){
d(sprintf('[ERROR] %s is not writable!', $out));
}
foreach( $updated as $file ){
$path = $cur_dir.DIRECTORY_SEPARATOR.$file;
if( file_exists($path) ){
$target = rtrim($out, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file;
$dir = dirname($target);
if( !is_dir($dir) ){
mkdir($dir, 0755, true);
}
copy($path, $target);
echo '.';
}
}
echo PHP_EOL;
e(sprintf('[SUCCCESS] Archived on %s!', $out));
exit;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment