/** * The main function of the hook. * * Expects the following arguments: * * - $argv[1] - The path of the configuration file, xgit-config.php. * - $argv[2] - The name of the ref being stored. * - $argv[3] - The old object name stored in the ref. * - $argv[4] - The new objectname to be stored in the ref. * * @param argc * The number of arguments on the command line. * * @param argv * Array of the arguments. */ function xgit_init($argc, $argv) { $this_file = array_shift($argv); // argv[0] if ($argc != 5) { xgit_help($this_file, STDERR); exit(VERSIONCONTROL_GIT_ERROR_WRONG_ARGC); } $config_file = array_shift($argv); // argv[1] $ref = array_shift($argv); // argv[2] $old_obj = array_shift($argv); // argv[3] $new_obj = array_shift($argv); // argv[4] // Load the configuration file and bootstrap Drupal. if (!file_exists($config_file)) { fwrite(STDERR, t('Error: failed to load configuration file.') . "\n"); exit(VERSIONCONTROL_GIT_ERROR_NO_CONFIG); } include_once $config_file; global $xgit; // Admins and other privileged users don't need to go through any checks. if (!in_array($xgit['uid'], $xgit['allowed_users'])) { // Do a full Drupal bootstrap. xgit_bootstrap(); $ref_type = xgit_ref_type($ref); if ($ref_type === FALSE) { fwrite(STDERR, "Given reference '{$ref}' is invalid.\n\n"); exit(VERSIONCONTROL_GIT_ERROR_INVALID_REF); } try { _xgit_assert_type(array($new_obj => array('commit', 'tag', 'empty'), $old_obj => array('commit', 'tag', 'empty'))); } catch (Exception $e) { fwrite(STDERR, $e->getMessage()); exit(VERSIONCONTROL_GIT_ERROR_INVALID_OBJ); } // Debugging help if ($GLOBALS['xgit_debug']) { $commits = xgit_get_commits($old_obj, $new_obj); $commits = implode(' ', $commits); fwrite(STDERR, 'DEBUG COMMITS:' . $commits . "\n"); } $label = xgit_label_for($ref, $old_obj, $new_obj); foreach (xgit_get_commits($old_obj, $new_obj) as $commit) { $access = xgit_check_commit_access($commit, $label); // Fail and print out error messages if commit access has been denied. if (!$access) { fwrite(STDERR, implode("\n\n", versioncontrol_get_access_errors()) . "\n\n"); exit(VERSIONCONTROL_GIT_ERROR_NO_ACCESS); } } } // Everything succeeded. Allow operation to complete. exit(0); }
/** * Gets either an array of branches which are "fully contained by" the given * commit or those branches which are not contained by the given commit. This is * useful for figuring out which commits are not already contained by a * different branch, since * * git rev-list <commit> --not <unmerged_branches> * * will return the commits which are parents of $commit and are not reachable * from any other branch. This list can then be used to figure out which commits * are introduced by a newly created branch. * * @param $commit * The commit for which to find the merged branches. * * @param $merged * Whether to get merged or unmerged branches. If TRUE, returns the merged * branches; FALSE gets the unmerged branches. * * @param $include_remote * Whether or not to include remote tracking branches in the search. Is FALSE * by default. */ function _xgit_get_merged_branches($commit, $merged = TRUE, $include_remote = FALSE) { global $xgit; _xgit_assert_type(array($commit => 'commit')); if (!isset($xgit['objects'][$commit]['unmerged'])) { $remote_spec = $include_remote ? '-a' : ''; $merged_spec = $merged ? '--merged' : '--no-merged'; $command = 'git --git-dir="%s" branch %s --no-color %s %s'; $command = sprintf($command, $xgit['git_dir'], $remote_spec, $merged_spec, escapeshellarg($commit)); $result = shell_exec($command); $branches = preg_split("/\n/", $result, -1, PREG_SPLIT_NO_EMPTY); // There is a chance that $result may contain a '*' if there is a HEAD and it // is included in the output. $branches = preg_replace('/^([\\* ] )?/', '', $branches); $xgit['objects'][$commit]['unmerged'] = $branches; } return $xgit['objects'][$commit]['unmerged']; }