diff --git a/git_deploy.module b/git_deploy.module index 61f66ee..731a5bd 100644 --- a/git_deploy.module +++ b/git_deploy.module @@ -21,32 +21,22 @@ define('GIT_DEPLOY_ERROR_DUMP', file_exists('/dev/null') ? '/dev/null' : 'nul'); function git_deploy_system_info_alter(array &$info, Extension $file, $type) { static $projects = []; if ($file->origin == 'core' || empty($info['version'])) { - $directory = $file->getPath(); - // Verify that this project was installed with Git. - while ($directory && !file_exists("$directory/.git")) { - $directory = substr($directory, 0, strrpos($directory, '/')); - } - $git_dir = (empty($directory) ? '' : "$directory/") . '.git'; - // For core, finish verifying that it was installed with Git. - if (!empty($directory) || $file->origin == 'core' && file_exists($git_dir)) { - // Only check Git once per project. - $directory = $file->origin == 'core' ? 'core' : $directory; + // Make sure Git operates in the right directory. + chdir($file->getPath()); + // Verify that we are in a Git repository. + $directory = exec('git rev-parse --show-toplevel 2> ' . GIT_DEPLOY_ERROR_DUMP); + if (!empty($directory)) { + // Only check Git once per repository. if (!isset($projects[$directory])) { $projects[$directory] = []; - // Make sure Git operates in the right directory. - $git = "git --git-dir $git_dir"; // Get upstream info. list($core) = explode('.', $info['core']); - $upstream = _git_deploy_get_upstream($git, $file->origin == 'core' ? "$core*" : "$info[core]-*"); + $upstream = _git_deploy_get_upstream($file->origin == 'core' ? "$core*" : "$info[core]-*"); // Find the project name based on fetch URL. if (isset($upstream['remote'])) { - $fetch_url = exec("$git config --get remote.$upstream[remote].url 2> " . GIT_DEPLOY_ERROR_DUMP); + $fetch_url = exec("git config --get remote.$upstream[remote].url 2> " . GIT_DEPLOY_ERROR_DUMP); if (!empty($fetch_url)) { - $project_name = substr($fetch_url, strrpos($fetch_url, '/') + 1); - if (substr($project_name, -4) == '.git') { - $project_name = substr($project_name, 0, -4); - } - $projects[$directory]['project'] = $project_name; + $projects[$directory]['project'] = basename($fetch_url, '.git'); } } // Set version from tag. @@ -64,14 +54,16 @@ function git_deploy_system_info_alter(array &$info, Extension $file, $type) { } $info = $projects[$directory] + $info; } + // Switch back to Drupal root folder. + chdir(DRUPAL_ROOT); } } /** * Gets upstream info. * - * @param string $git - * Git formatted for command line. + * This function must be run from within a Git repository. + * * @param string $pattern * Pattern for matching branch names, without trailing ".x". Must not include * remote. Also used to check for release tags. @@ -83,49 +75,49 @@ function git_deploy_system_info_alter(array &$info, Extension $file, $type) { * - tag: Release tag from last common commit in matching branch. * - datestamp: Unix timestamp of last common commit. */ -function _git_deploy_get_upstream($git, $pattern = '*') { +function _git_deploy_get_upstream($pattern = '*') { $upstream = []; // Get tracked upstream branch. - $remote = exec("$git rev-parse --abbrev-ref @{upstream} 2> " . GIT_DEPLOY_ERROR_DUMP); + $remote = exec('git rev-parse --abbrev-ref @{upstream} 2> ' . GIT_DEPLOY_ERROR_DUMP); if (fnmatch("*/$pattern.x", $remote)) { // Set remote. list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $remote)); // Find last common commit in both local and upstream. - $last_base = exec("$git merge-base HEAD $remote 2> " . GIT_DEPLOY_ERROR_DUMP); + $last_base = exec("git merge-base HEAD $remote 2> " . GIT_DEPLOY_ERROR_DUMP); // Get time of last common commit. - $upstream['datestamp'] = exec("$git log -1 --pretty=format:%at $last_base 2> " . GIT_DEPLOY_ERROR_DUMP); + $upstream['datestamp'] = exec("git log -1 --pretty=format:%at $last_base 2> " . GIT_DEPLOY_ERROR_DUMP); } else { // If local does not track an upstream branch, find best matching remote // branch. - exec("$git remote 2> " . GIT_DEPLOY_ERROR_DUMP, $remotes); + exec('git remote 2> ' . GIT_DEPLOY_ERROR_DUMP, $remotes); if (!empty($remotes)) { // Only consider the origin remote, if it exists. $branch_pattern = in_array('origin', $remotes) ? "origin/$pattern.x" : "*/$pattern.x"; // List matching branches in descending order. - exec("$git branch -r --sort=-refname --list --format='%(refname:short)' $branch_pattern 2> " . GIT_DEPLOY_ERROR_DUMP, $branches); + exec("git branch -r --sort=-refname --list --format='%(refname:short)' $branch_pattern 2> " . GIT_DEPLOY_ERROR_DUMP, $branches); if (!empty($branches)) { $remote = array_shift($branches); // Find last common commit in both local and upstream. - $last_base = exec("$git merge-base HEAD $remote 2> " . GIT_DEPLOY_ERROR_DUMP); + $last_base = exec("git merge-base HEAD $remote 2> " . GIT_DEPLOY_ERROR_DUMP); if (!empty($branches)) { // There's no reason to check other branches for a more recent common // commit if they do not contain the base commit, so filter the branch // list. - exec("$git branch -r --sort=-refname --contains $last_base --no-contains $remote --format='%(refname:short)' $branch_pattern 2> " . GIT_DEPLOY_ERROR_DUMP, $branches); + exec("git branch -r --sort=-refname --contains $last_base --no-contains $remote --format='%(refname:short)' $branch_pattern 2> " . GIT_DEPLOY_ERROR_DUMP, $branches); while (!empty($branches)) { $branch = array_shift($branches); // Find last common commit in both local and upstream. - $base = exec("$git merge-base HEAD $branch 2> " . GIT_DEPLOY_ERROR_DUMP); + $base = exec("git merge-base HEAD $branch 2> " . GIT_DEPLOY_ERROR_DUMP); // Count commits since last base commit. - $difference = exec("$git rev-list --count $base ^$last_base 2> " . GIT_DEPLOY_ERROR_DUMP); + $difference = exec("git rev-list --count $base ^$last_base 2> " . GIT_DEPLOY_ERROR_DUMP); // If base contains new commits, it is a better match. if (!empty($difference)) { $remote = $branch; $last_base = $base; if (!empty($branches)) { // Filter the branch list. - exec("$git branch -r --sort=-refname --contains $last_base --no-contains $remote --format='%(refname:short)' $branch_pattern 2> " . GIT_DEPLOY_ERROR_DUMP, $branches); + exec("git branch -r --sort=-refname --contains $last_base --no-contains $remote --format='%(refname:short)' $branch_pattern 2> " . GIT_DEPLOY_ERROR_DUMP, $branches); } } } @@ -133,13 +125,13 @@ function _git_deploy_get_upstream($git, $pattern = '*') { // Set remote. list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $remote)); // Check for latest release tag from last common commit. - exec("$git tag --points-at $last_base $pattern.* 2> " . GIT_DEPLOY_ERROR_DUMP, $tags); + exec("git tag --points-at $last_base $pattern.* 2> " . GIT_DEPLOY_ERROR_DUMP, $tags); if (!empty($tags)) { usort($tags, 'version_compare'); $upstream['tag'] = end($tags); } // Get time of last common commit. - $upstream['datestamp'] = exec("$git log -1 --pretty=format:%at $last_base 2> " . GIT_DEPLOY_ERROR_DUMP); + $upstream['datestamp'] = exec("git log -1 --pretty=format:%at $last_base 2> " . GIT_DEPLOY_ERROR_DUMP); } } } @@ -153,23 +145,20 @@ function git_deploy_update_status_alter(&$projects) { foreach ($projects as $project => &$project_info) { // Override the update status on dev branches. if ($project_info['install_type'] == 'dev' && in_array($project_info['status'], [UpdateManagerInterface::NOT_SECURE, UpdateManagerInterface::NOT_CURRENT])) { - $directory = drupal_get_path(preg_replace('/-disabled$/', '', $project_info['project_type']), key($project_info['includes'])); - // Verify that this project was installed with Git. - while ($directory && !file_exists("$directory/.git")) { - $directory = substr($directory, 0, strrpos($directory, '/')); - } - $git_dir = (empty($directory) ? '' : "$directory/") . '.git'; - if (!empty($directory) || $project_info['project_type'] == 'core' && file_exists($git_dir)) { + // Make sure Git operates in the right directory. + chdir(drupal_get_path(preg_replace('/-disabled$/', '', $project_info['project_type']), key($project_info['includes']))); + // Verify that we are in a Git repository. + $directory = exec('git rev-parse --show-toplevel 2> ' . GIT_DEPLOY_ERROR_DUMP); + if (!empty($directory)) { $version = $project_info['existing_version']; if (isset($project_info['releases'][$version])) { $release = $project_info['releases'][$version]; if (isset($release['tag'])) { - $git = "git --git-dir $git_dir"; // Fetch latest commit from origin. - exec("$git fetch origin 2> " . GIT_DEPLOY_ERROR_DUMP); - $last_commit = exec("$git log -1 --pretty=format:%H origin/$release[tag] 2> " . GIT_DEPLOY_ERROR_DUMP); + exec('git fetch origin 2> ' . GIT_DEPLOY_ERROR_DUMP); + $last_commit = exec("git log -1 --pretty=format:%H origin/$release[tag] 2> " . GIT_DEPLOY_ERROR_DUMP); // See if local branch contains latest commit. - exec("$git merge-base --is-ancestor $last_commit HEAD 2> " . GIT_DEPLOY_ERROR_DUMP, $output, $return_val); + exec("git merge-base --is-ancestor $last_commit HEAD 2> " . GIT_DEPLOY_ERROR_DUMP, $output, $return_val); // We still need to compare commit time to release time because this // repository may have been cloned from a copy of the upstream // repository. Allow a 12 hour time difference between release and @@ -183,4 +172,6 @@ function git_deploy_update_status_alter(&$projects) { } } } + // Switch back to Drupal root folder. + chdir(DRUPAL_ROOT); }