#!/usr/bin/env php $branch_commits) { foreach($branch_commits as $commit) { if(empty($commit['patch_hash'])) continue; $patch_index[$commit['patch_hash']][$commit['commit_hash']] = $commit['branches']; } } $branch_compare_count = count($branches); foreach($patch_index as $patch_hash => $patch_commits) { $patch_branches = []; foreach($patch_commits as $commit_branches) { foreach($commit_branches as $branch_name) { $patch_branches[$branch_name] = $branch_name; } } $patch_branch_count = count($patch_branches); $first_commit = array_keys($patch_commits)[0]; $first_branch = $patch_commits[$first_commit][0]; $short_commit = substr($first_commit, 0, 7); if($patch_branch_count == $branch_compare_count) { if(count($patch_commits) > 1) { echo "{$short_commit} (ALL:cherry) {$branches[$first_branch][$first_commit]['title']}\n"; } else { echo "{$short_commit} (ALL:same) {$branches[$first_branch][$first_commit]['title']}\n"; } } else { echo "{$short_commit} (" . implode(', ', $patch_branches) . ") {$branches[$first_branch][$first_commit]['title']}\n"; } } exit(0); function hash_branch($branch_name, $flags) { static $hashes = []; $cmd = 'git log --format="format:%H %s" '; if(!empty($flags['-c'])) { $cmd .= ' -' . ((int) $flags['-c'][0]) . ' '; } if($branch_name) { $cmd .= escapeshellarg($branch_name); } $error = 0; $output = []; exec($cmd, $output, $error); if($error) { return FALSE; } $branch_hases = []; foreach($output as $row) { [$commit_hash, $commit_title] = explode(' ', $row, 2); if(!isset($hashes[$commit_hash])) { $hashes[$commit_hash] = load_commit($commit_hash, $commit_title, $flags); } $hashes[$commit_hash]['branches'][] = $branch_name; $branch_hases[$commit_hash] = &$hashes[$commit_hash]; } return $branch_hases; } function load_commit($commit_hash, $commit_title, $flags) { $commit = ['commit_hash' => $commit_hash, 'title' => $commit_title, 'patch_hash' => NULL, 'branches' => []]; $cmd = 'git show --format=format:%H ' . escapeshellarg($commit_hash); $error = 0; $output = []; exec($cmd, $output, $error); if($error) { return FALSE; } $compare_commit_hash = trim(array_shift($output)); if($compare_commit_hash != $commit_hash) { return FALSE; } $hash_data = array(); $include_file = TRUE; foreach($output as $row) { if(substr($row, 0, 5) == 'diff ') { if($flags AND isset($flags['-x'])) { $match = FALSE; $row_parts = explode(' ', $row, 3); foreach($flags['-x'] as $path) { $path = trim($path); if(substr($path, 0, 1) == '/') { $path = substr($path, 1); } if(substr($path, -1) == '*') { $path = substr($path, 0, -1); } else if(substr($path, -1) != '/') { $path .= ' '; } if($row_parts[1] == '--git') { if(substr($row, 0, 13 + strlen($path)) == "diff --git a/{$path}") { $match = TRUE; break; } } else if($row_parts[1] == '--cc') { if(substr($row, 0, 10 + strlen($path)) == "diff --cc {$path}") { $match = TRUE; break; } } } if($match) { $include_file = FALSE; continue; } } $include_file = TRUE; $hash_data[] = $row; continue; } if(!$include_file) { continue; } if(substr($row, 0, 6) == 'index ') { continue; } if(substr($row, 0, 3) == '@@ ') { $hash_data[] = '@@'; continue; } $hash_data[] = $row; } if($hash_data) { $commit['patch_hash'] = sha1(implode(PHP_EOL, $hash_data)); } return $commit; } function parse_arguments($raw_arguments) { $arguments = array(); $flags = array(); while($raw_arguments) { $current_arguemnt = array_shift($raw_arguments); if(substr($current_arguemnt, 0, 1) != '-') { $arguments[] = $current_arguemnt; continue; } if($current_arguemnt == '--') { while($current_arguemnt = array_shift($raw_arguments)) { $arguments[] = $current_arguemnt; } break; } $next_argument = array_shift($raw_arguments); $flags[$current_arguemnt][] = $next_argument; } return array($arguments, $flags); }