Advertisement
puggan

git_branch_compare

Mar 21st, 2017
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 5.08 KB | None | 0 0
  1. #!/usr/bin/env php
  2. <?php
  3.  
  4.     $wd = getcwd();
  5.  
  6.     $git_dir = shell_exec('git rev-parse --show-toplevel');
  7.  
  8.     if(!$git_dir) {
  9.         fprintf(STDERR, "Not inside a git path");
  10.         exit(1);
  11.     }
  12.  
  13.     $git_wd = substr($wd, strlen($git_dir));
  14.  
  15.     [$arguments, $flags] = parse_arguments(array_slice($argv, 1));
  16.  
  17.     $branches = [];
  18.  
  19.     if(count($arguments) == 1)
  20.     {
  21.         $branches['HEAD'] = hash_branch('HEAD', $flags);
  22.     }
  23.  
  24.     foreach($arguments as $branch_name)
  25.     {
  26.         if(!isset($branches[$branch_name]))
  27.         {
  28.             $branches[$branch_name] = hash_branch($branch_name, $flags);
  29.         }
  30.     }
  31.  
  32.     $patch_index = [];
  33.     foreach($branches as $branch_name => $branch_commits)
  34.     {
  35.         foreach($branch_commits as $commit)
  36.         {
  37.             if(empty($commit['patch_hash'])) continue;
  38.             $patch_index[$commit['patch_hash']][$commit['commit_hash']] = $commit['branches'];
  39.         }
  40.     }
  41.  
  42.     $branch_compare_count = count($branches);
  43.  
  44.     foreach($patch_index as $patch_hash => $patch_commits)
  45.     {
  46.         $patch_branches = [];
  47.         foreach($patch_commits as $commit_branches)
  48.         {
  49.             foreach($commit_branches as $branch_name)
  50.             {
  51.                 $patch_branches[$branch_name] = $branch_name;
  52.             }
  53.         }
  54.  
  55.         $patch_branch_count = count($patch_branches);
  56.         $first_commit = array_keys($patch_commits)[0];
  57.         $first_branch = $patch_commits[$first_commit][0];
  58.         $short_commit = substr($first_commit, 0, 7);
  59.  
  60.         if($patch_branch_count == $branch_compare_count)
  61.         {
  62.             if(count($patch_commits) > 1)
  63.             {
  64.                 echo "{$short_commit} (ALL:cherry) {$branches[$first_branch][$first_commit]['title']}\n";
  65.  
  66.             }
  67.             else
  68.             {
  69.                 echo "{$short_commit} (ALL:same) {$branches[$first_branch][$first_commit]['title']}\n";
  70.             }
  71.         }
  72.         else
  73.         {
  74.             echo "{$short_commit} (" . implode(', ', $patch_branches) . ") {$branches[$first_branch][$first_commit]['title']}\n";
  75.         }
  76.     }
  77.  
  78.     exit(0);
  79.  
  80.     function hash_branch($branch_name, $flags)
  81.     {
  82.         static $hashes = [];
  83.  
  84.         $cmd = 'git log --format="format:%H %s" ';
  85.         if(!empty($flags['-c']))
  86.         {
  87.             $cmd .= ' -' . ((int) $flags['-c'][0]) . ' ';
  88.         }
  89.         if($branch_name)
  90.         {
  91.             $cmd .= escapeshellarg($branch_name);
  92.         }
  93.  
  94.         $error = 0;
  95.         $output = [];
  96.         exec($cmd, $output, $error);
  97.         if($error)
  98.         {
  99.             return FALSE;
  100.         }
  101.  
  102.         $branch_hases = [];
  103.  
  104.         foreach($output as $row)
  105.         {
  106.             [$commit_hash, $commit_title] = explode(' ', $row, 2);
  107.  
  108.             if(!isset($hashes[$commit_hash]))
  109.             {
  110.                 $hashes[$commit_hash] = load_commit($commit_hash, $commit_title, $flags);
  111.             }
  112.  
  113.             $hashes[$commit_hash]['branches'][] = $branch_name;
  114.             $branch_hases[$commit_hash] = &$hashes[$commit_hash];
  115.         }
  116.  
  117.         return $branch_hases;
  118.     }
  119.  
  120.     function load_commit($commit_hash, $commit_title, $flags)
  121.     {
  122.         $commit = ['commit_hash' => $commit_hash, 'title' => $commit_title, 'patch_hash' => NULL, 'branches' => []];
  123.         $cmd = 'git show --format=format:%H ' . escapeshellarg($commit_hash);
  124.         $error = 0;
  125.         $output = [];
  126.         exec($cmd, $output, $error);
  127.         if($error)
  128.         {
  129.             return FALSE;
  130.         }
  131.  
  132.         $compare_commit_hash = trim(array_shift($output));
  133.  
  134.         if($compare_commit_hash != $commit_hash)
  135.         {
  136.             return FALSE;
  137.         }
  138.  
  139.         $hash_data = array();
  140.         $include_file = TRUE;
  141.         foreach($output as $row)
  142.         {
  143.             if(substr($row, 0, 5) == 'diff ')
  144.             {
  145.                 if($flags AND isset($flags['-x']))
  146.                 {
  147.                     $match = FALSE;
  148.                     $row_parts = explode(' ', $row, 3);
  149.                     foreach($flags['-x'] as $path)
  150.                     {
  151.                         $path = trim($path);
  152.                         if(substr($path, 0, 1) == '/')
  153.                         {
  154.                             $path = substr($path, 1);
  155.                         }
  156.                         if(substr($path, -1) == '*')
  157.                         {
  158.                             $path = substr($path, 0, -1);
  159.                         }
  160.                         else if(substr($path, -1) != '/')
  161.                         {
  162.                             $path .= ' ';
  163.                         }
  164.                         if($row_parts[1] == '--git')
  165.                         {
  166.                             if(substr($row, 0, 13 + strlen($path)) == "diff --git a/{$path}")
  167.                             {
  168.                                 $match = TRUE;
  169.                                 break;
  170.                             }
  171.                         }
  172.                         else if($row_parts[1] == '--cc')
  173.                         {
  174.                             if(substr($row, 0, 10 + strlen($path)) == "diff --cc {$path}")
  175.                             {
  176.                                 $match = TRUE;
  177.                                 break;
  178.                             }
  179.                         }
  180.                     }
  181.                     if($match)
  182.                     {
  183.                         $include_file = FALSE;
  184.                         continue;
  185.                     }
  186.                 }
  187.  
  188.                 $include_file = TRUE;
  189.                 $hash_data[] = $row;
  190.                 continue;
  191.             }
  192.  
  193.             if(!$include_file)
  194.             {
  195.                 continue;
  196.             }
  197.  
  198.             if(substr($row, 0, 6) == 'index ')
  199.             {
  200.                 continue;
  201.             }
  202.  
  203.             if(substr($row, 0, 3) == '@@ ')
  204.             {
  205.                 $hash_data[] = '@@';
  206.                 continue;
  207.             }
  208.  
  209.             $hash_data[] = $row;
  210.         }
  211.  
  212.         if($hash_data)
  213.         {
  214.             $commit['patch_hash'] = sha1(implode(PHP_EOL, $hash_data));
  215.         }
  216.  
  217.         return $commit;
  218.     }
  219.  
  220.     function parse_arguments($raw_arguments)
  221.     {
  222.         $arguments = array();
  223.         $flags = array();
  224.  
  225.         while($raw_arguments)
  226.         {
  227.             $current_arguemnt = array_shift($raw_arguments);
  228.             if(substr($current_arguemnt, 0, 1) != '-')
  229.             {
  230.                 $arguments[] = $current_arguemnt;
  231.                 continue;
  232.             }
  233.  
  234.             if($current_arguemnt == '--')
  235.             {
  236.                 while($current_arguemnt = array_shift($raw_arguments))
  237.                 {
  238.                     $arguments[] = $current_arguemnt;
  239.                 }
  240.                 break;
  241.             }
  242.  
  243.             $next_argument = array_shift($raw_arguments);
  244.             $flags[$current_arguemnt][] = $next_argument;
  245.         }
  246.  
  247.         return array($arguments, $flags);
  248.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement