You are here

function _git_deploy_get_upstream in Git Deploy 6.2

Same name and namespace in other branches
  1. 8.2 git_deploy.module \_git_deploy_get_upstream()
  2. 6 git_deploy.module \_git_deploy_get_upstream()
  3. 7.2 git_deploy.module \_git_deploy_get_upstream()
  4. 7 git_deploy.module \_git_deploy_get_upstream()

Gets upstream info.

Parameters

string $git: Git formatted for command line.

string[] $patterns: List of patterns for matching branch names, without trailing ".x". Must not include repository name. Also used to check for release tags.

Return value

string[] Array with the following keys, if found:

  • branch: Best matching remote branch.
  • remote: Remote repository containing best matching branch.
  • tag: Release tag from last common commit in matching branch.
  • datestamp: Unix timestamp of last common commit.
1 call to _git_deploy_get_upstream()
git_deploy_system_info_alter in ./git_deploy.module
Implements hook_system_info_alter().

File

./git_deploy.module, line 187
Adds project, version and date information to projects checked out with Git.

Code

function _git_deploy_get_upstream($git, array $patterns = array(
  '*',
)) {
  $upstream = array(
    'synced' => FALSE,
  );

  // Check that there are remote repositories.
  exec("{$git} remote 2> " . GIT_DEPLOY_ERROR_DUMP, $remotes);
  if (!empty($remotes)) {

    // Get most recent tag.
    $tag = exec("{$git} describe --tags --abbrev=0 --match " . implode(' --match ', substr_replace($patterns, '.*', array_map('strlen', $patterns))) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);

    // Get current commit.
    $last_base = $head = exec("{$git} log -1 --pretty=format:%H 2> " . GIT_DEPLOY_ERROR_DUMP);

    // Get tracked upstream branch.
    $remote = exec("{$git} rev-parse --abbrev-ref @{upstream} 2> " . GIT_DEPLOY_ERROR_DUMP);
    if ($remote !== '' && preg_match('/^.+\\/(?:' . implode('|', str_replace(array(
      '.',
      '*',
    ), array(
      '\\.',
      '\\d+',
    ), $patterns)) . ')\\.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 " . escapeshellarg($remote) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
      if (!empty($tag)) {

        // See if most recent tag is in our branch.
        exec("{$git} describe --tags --contains " . escapeshellarg($last_base) . ' --match ' . escapeshellarg($tag) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP, $output, $status);
      }
      if (empty($tag) || $status !== 0) {

        // Compare with last remote commit for update status.
        $upstream['synced'] = $last_base == exec("{$git} log -1 --pretty=format:%H " . escapeshellarg($remote) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
      }
      else {
        $upstream['tag'] = $tag;
      }
    }
    else {

      // If local does not track an upstream branch, find best matching remote.
      if (in_array('origin', $remotes)) {

        // If origin exists, don't check any other remote repositories.
        $upstream['remote'] = 'origin';
      }
      elseif ($remote !== '') {

        // If we are tracking a remote repository, don't check any other remote
        // repositories.
        list(, $upstream['remote']) = array_reverse(explode('/', $remote));
      }
      if (isset($upstream['remote'])) {
        $branch_patterns = substr_replace($patterns, "{$upstream['remote']}/", 0, 0);
      }
      else {
        $upstream['remote'] = current($remotes);
        $branch_patterns = substr_replace($patterns, '*/', 0, 0);
      }
      if (!empty($tag)) {

        // See if we are on a tag.
        exec("{$git} describe --tags --exact-match --match " . escapeshellarg($tag) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP, $output, $status);
      }

      // If we are not on a tag, find the best matching remote branch.
      if (empty($tag) || $status !== 0) {

        // Append ".x" to the branch patterns.
        $branch_patterns = substr_replace($branch_patterns, '.x', array_map('strlen', $branch_patterns));

        // Enclose branch patterns in quotes and join together.
        $branch_pattern = implode(' ', array_map('escapeshellarg', $branch_patterns));

        // List matching branches by version in descending order.
        exec("{$git} branch -r --list {$branch_pattern} master 2> " . GIT_DEPLOY_ERROR_DUMP, $branches);
        if (!empty($branches)) {
          usort($branches, 'version_compare');
          foreach (array_reverse(array_map('trim', $branches)) as $branch) {
            $tip = exec("{$git} log -1 --pretty=format:%H " . escapeshellarg($branch) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
            if ($tip == $head) {

              // If remote branch matches local branch, it is the best match.
              list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $branch));
              $last_base = $tip;

              // Local history contains last remote commit.
              $upstream['synced'] = TRUE;
              break;
            }
            if (isset($upstream['branch'])) {

              // Replace branch tip with last common commit.
              $tip = exec("{$git} merge-base HEAD " . escapeshellarg($tip) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);
              if ($tip != $last_base) {

                // See if this branch is older than last branch.
                exec("{$git} merge-base --is-ancestor " . escapeshellarg($tip) . ' ' . escapeshellarg($last_base) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP, $output, $status);
              }
              if ($tip == $last_base || $status === 0) {

                // Last remote branch was more recent. For performance, stop
                // looking.
                break;
              }

              // This remote branch is more recent.
              list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $branch));
              $last_base = $tip;
            }
            else {

              // Find most recent common commit.
              list($upstream['branch'], $upstream['remote']) = array_reverse(explode('/', $branch));
              $last_base = exec("{$git} merge-base HEAD " . escapeshellarg($tip) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP);

              // Check for latest commit in local history.
              $upstream['synced'] = $last_base == $tip;
            }
          }
          if (!empty($tag)) {

            // See if most recent tag is in our branch.
            exec("{$git} describe --tags --contains " . escapeshellarg($last_base) . ' --match ' . escapeshellarg($tag) . ' 2> ' . GIT_DEPLOY_ERROR_DUMP, $output, $status);
            if ($status === 0) {
              $upstream['tag'] = $tag;
            }
          }
        }
      }
      else {
        $upstream['tag'] = $tag;
      }
    }

    // Find the timestamp for the current commit.
    $upstream['datestamp'] = exec("{$git} log -1 --pretty=format:%at " . escapeshellarg($last_base) . " 2> " . GIT_DEPLOY_ERROR_DUMP);
  }
  return $upstream;
}