git_drupalorg.inc

  1. 8.0.x commands/pm/package_handler/git_drupalorg.inc
  2. 6.x commands/pm/package_handler/git_drupalorg.inc
  3. 7.x commands/pm/package_handler/git_drupalorg.inc
  4. 4.x commands/pm/package_handler/git_drupalorg.inc
  5. 5.x commands/pm/package_handler/git_drupalorg.inc
  6. master commands/pm/package_handler/git_drupalorg.inc

Drush PM drupal.org Git extension.

Functions

Namesort descending Description
drush_pm_git_drupalorg_compute_rebuild_version Helper function to compute the rebulid version string for a project.
package_handler_download_project Download a project.
package_handler_post_download Post download action.
package_handler_update_project Update a project (so far, only modules are supported).
package_handler_validate Validate this package handler can run.

File

commands/pm/package_handler/git_drupalorg.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Drush PM drupal.org Git extension.
  5. */
  6. /**
  7. * Validate this package handler can run.
  8. */
  9. function package_handler_validate() {
  10. // Check git command exists. Disable possible output.
  11. $debug = drush_get_context('DRUSH_DEBUG');
  12. drush_set_context('DRUSH_DEBUG', FALSE);
  13. // We need to check for a git executable and then make sure version is >=1.7
  14. // (avoid drush_shell_exec because we want to run this even in --simulated mode.)
  15. $success = exec('git --version', $git);
  16. $git_version_array = explode(" ", $git[0]);
  17. $git_version = $git_version_array[2];
  18. drush_set_context('DRUSH_DEBUG', $debug);
  19. if (!$success) {
  20. return drush_set_error('DRUSH_SHELL_COMMAND_NOT_FOUND', dt('git executable not found.'));
  21. } elseif ($git_version < '1.7') {
  22. return drush_set_error('GIT_VERSION_UNSUPPORTED', dt('Your git version !git_version is not supported; please upgrade to git 1.7 or later.', array('!git_version' => $git_version)));
  23. }
  24. // Check git_deploy is enabled. Only for bootstrapped sites.
  25. if (drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_FULL) {
  26. if (!drush_get_option('gitinfofile') && !module_exists('git_deploy')) {
  27. drush_log(dt('git package handler needs git_deploy module enabled to work properly.'), 'warning');
  28. }
  29. }
  30. return TRUE;
  31. }
  32. /**
  33. * Download a project.
  34. *
  35. * @param $request
  36. * The project array with name, base and full (final) paths.
  37. * @param $release
  38. * The release details array from drupal.org.
  39. */
  40. function package_handler_download_project(&$request, $release) {
  41. if ($username = drush_get_option('gitusername')) {
  42. // Uses SSH, which enables pushing changes back to git.drupal.org.
  43. $repository = $username . '@git.drupal.org:project/' . $request['name'] . '.git';
  44. }
  45. else {
  46. $repository = 'git://git.drupal.org/project/' . $request['name'] . '.git';
  47. }
  48. $request['repository'] = $repository;
  49. $tag = $release['tag'];
  50. // If the --cache option was given, create a new git reference cache of the
  51. // remote repository, or update the existing cache to fetch recent changes.
  52. if (drush_get_option('cache') && ($cachedir = drush_directory_cache())) {
  53. $gitcache = $cachedir . '/git';
  54. $projectcache = $gitcache . '/' . $request['name'] . '.git';
  55. drush_mkdir($gitcache);
  56. // Setup a new cache, if we don't have this project yet.
  57. if (!file_exists($projectcache)) {
  58. // --mirror works similar to --bare, but retrieves all tags, local
  59. // branches, remote branches, and any other refs (notes, stashes, etc).
  60. // @see http://stackoverflow.com/questions/3959924
  61. $command = 'git clone --mirror';
  62. if (drush_get_context('DRUSH_VERBOSE')) {
  63. $command .= ' --verbose --progress';
  64. }
  65. $command .= ' %s %s';
  66. drush_shell_cd_and_exec($gitcache, $command, $repository, $request['name'] . '.git');
  67. }
  68. // If we already have this project, update it to speed up subsequent clones.
  69. else {
  70. // A --mirror clone is fully synchronized with `git remote update` instead
  71. // of `git fetch --all`.
  72. // @see http://stackoverflow.com/questions/6150188
  73. drush_shell_cd_and_exec($projectcache, 'git remote update');
  74. }
  75. $gitcache = $projectcache;
  76. }
  77. // Clone the repo into its appropriate target location.
  78. $command = 'git clone';
  79. $command .= ' ' . drush_get_option('gitcloneparams');
  80. if (drush_get_option('cache')) {
  81. $command .= ' --reference ' . drush_escapeshellarg($gitcache);
  82. }
  83. if (drush_get_context('DRUSH_VERBOSE')) {
  84. $command .= ' --verbose --progress';
  85. }
  86. $command .= ' ' . drush_escapeshellarg($repository);
  87. $command .= ' ' . drush_escapeshellarg($request['full_project_path']);
  88. if (!drush_shell_exec($command)) {
  89. return drush_set_error('DRUSH_PM_GIT_CHECKOUT_PROBLEMS', dt('Unable to clone project !name from git.drupal.org.', array('!name' => $request['name'])));
  90. }
  91. // Check if the 'tag' from the release feed is a tag or a branch.
  92. // If the tag exists, git will return it
  93. if (!drush_shell_cd_and_exec($request['full_project_path'], 'git tag -l ' . drush_escapeshellarg($tag))) {
  94. return drush_set_error('DRUSH_PM_GIT_CHECKOUT_PROBLEMS', dt('Unable to clone project !name from git.drupal.org.', array('!name' => $request['name'])));
  95. }
  96. $output = drush_shell_exec_output();
  97. if (isset($output[0]) && ($output[0] == $tag)) {
  98. // If we want a tag, simply checkout it. The checkout will end up in
  99. // "detached head" state.
  100. $command = 'git checkout ' . drush_get_option('gitcheckoutparams');
  101. $command .= ' ' . drush_escapeshellarg($tag);
  102. if (!drush_shell_cd_and_exec($request['full_project_path'], $command)) {
  103. return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to retrieve ' . $request['name'] . ' from git.drupal.org.');
  104. }
  105. }
  106. else {
  107. // Else, we want to checkout a branch.
  108. // First check if we are not already in the correct branch.
  109. if (!drush_shell_cd_and_exec($request['full_project_path'], 'git symbolic-ref HEAD')) {
  110. return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to retrieve ' . $request['name'] . ' from git.drupal.org.');
  111. }
  112. $output = drush_shell_exec_output();
  113. $current_branch = preg_replace('@^refs/heads/@', '', $output[0]);
  114. // If we are not on the correct branch already, switch to the correct one.
  115. if ($current_branch != $tag) {
  116. $command = 'git checkout';
  117. $command .= ' ' . drush_get_option('gitcheckoutparams');
  118. $command .= ' --track ' . drush_escapeshellarg('origin/' . $tag) . ' -b ' . drush_escapeshellarg($tag);
  119. if (!drush_shell_cd_and_exec($request['full_project_path'], $command)) {
  120. return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to retrieve ' . $request['name'] . ' from git.drupal.org.');
  121. }
  122. }
  123. }
  124. return TRUE;
  125. }
  126. /**
  127. * Update a project (so far, only modules are supported).
  128. *
  129. * @param $request
  130. * The project array with name, base and full (final) paths.
  131. * @param $release
  132. * The release details array from drupal.org.
  133. */
  134. function package_handler_update_project($request, $release) {
  135. drush_log('Updating project ' . $request['name'] . ' ...');
  136. $commands = array();
  137. if ($release['version_extra'] == 'dev') {
  138. // Update the branch of the development repository.
  139. $commands[] = 'git pull';
  140. $commands[] = drush_get_option('gitpullparams');
  141. }
  142. else {
  143. // Use a stable repository.
  144. $commands[] = 'git fetch';
  145. $commands[] = drush_get_option('gitfetchparams');
  146. $commands[] = ';';
  147. $commands[] = 'git checkout';
  148. $commands[] = drush_get_option('gitcheckoutparams');
  149. $commands[] = $release['version'];
  150. }
  151. if (!drush_shell_cd_and_exec($request['full_project_path'], implode(' ', $commands))) {
  152. return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to update ' . $request['name'] . ' from git.drupal.org.');
  153. }
  154. return TRUE;
  155. }
  156. /**
  157. * Post download action.
  158. *
  159. * This action take place once the project is placed in its final location.
  160. *
  161. * Here we add the project as a git submodule.
  162. */
  163. function package_handler_post_download($project, $release) {
  164. if (drush_get_option('gitsubmodule', FALSE)) {
  165. // Obtain the superproject path, then add as submodule.
  166. if (drush_shell_cd_and_exec(dirname($project['full_project_path']), 'git rev-parse --show-toplevel')) {
  167. $output = drush_shell_exec_output();
  168. $superproject = $output[0];
  169. // Add the downloaded project as a submodule of its git superproject.
  170. $command = array();
  171. $command[] = 'git submodule add';
  172. $command[] = drush_get_option('gitsubmoduleaddparams');
  173. $command[] = $project['repository'];
  174. // We need the submodule relative path.
  175. $command[] = substr(realpath($project['full_project_path']), strlen(realpath($superproject)) + 1);
  176. if (!drush_shell_cd_and_exec($superproject, implode(' ', $command))) {
  177. return drush_set_error('DRUSH_PM_GIT_CHECKOUT_PROBLEMS', dt('Unable to add !name as a git submodule of !super.', array('!name' => $project['name'], '!super' => $superproject)));
  178. }
  179. }
  180. else {
  181. return drush_set_error('DRUSH_PM_GIT_SUBMODULE_PROBLEMS', dt('Unable to create !project as a git submodule: !dir is not in a Git repository.', array('!project' => $project['name'], '!dir' => dirname($project['full_project_path']))));
  182. }
  183. }
  184. if (drush_get_option('gitinfofile', FALSE)) {
  185. $matches = array();
  186. if (preg_match('/^(.+).x-dev$/', $release['version'], $matches)) {
  187. $full_version = drush_pm_git_drupalorg_compute_rebuild_version($project['project_install_location'], $matches[1]);
  188. }
  189. else {
  190. $full_version = $release['version'];
  191. }
  192. drush_pm_inject_info_file_metadata($project['project_install_location'], $project['name'], $full_version);
  193. }
  194. }
  195. /**
  196. * Helper function to compute the rebulid version string for a project.
  197. *
  198. * This does some magic in Git to find the latest release tag along
  199. * the branch we're packaging from, count the number of commits since
  200. * then, and use that to construct this fancy alternate version string
  201. * which is useful for the version-specific dependency support in Drupal
  202. * 7 and higher.
  203. *
  204. * NOTE: A similar function lives in git_deploy and in the drupal.org
  205. * packaging script (see DrupalorgProjectPackageRelease.class.php inside
  206. * drupalorg/drupalorg_project/plugins/release_packager). Any changes to the
  207. * actual logic in here should probably be reflected in the other places.
  208. *
  209. * @param string $project_dir
  210. * The full path to the root directory of the project to operate on.
  211. * @param string $branch
  212. * The branch that we're using for -dev. This should only include the
  213. * core version, the dash, and the branch's major version (eg. '7.x-2').
  214. *
  215. * @return string
  216. * The full 'rebuild version string' in the given Git checkout.
  217. */
  218. function drush_pm_git_drupalorg_compute_rebuild_version($project_dir, $branch) {
  219. $rebuild_version = '';
  220. $branch_preg = preg_quote($branch);
  221. if (drush_shell_cd_and_exec($project_dir, 'git describe --tags')) {
  222. $shell_output = drush_shell_exec_output();
  223. $last_tag = $shell_output[0];
  224. // Make sure the tag starts as Drupal formatted (for eg.
  225. // 7.x-1.0-alpha1) and if we are on a proper branch (ie. not master)
  226. // then it's on that branch.
  227. if (preg_match('/^(?<drupalversion>' . $branch_preg . '\.\d+(?:-[^-]+)?)(?<gitextra>-(?<numberofcommits>\d+-)g[0-9a-f]{7})?$/', $last_tag, $matches)) {
  228. // If we found additional git metadata (in particular, number of commits)
  229. // then use that info to build the version string.
  230. if (isset($matches['gitextra'])) {
  231. $rebuild_version = $matches['drupalversion'] . '+' . $matches['numberofcommits'] . 'dev';
  232. }
  233. // Otherwise, the branch tip is pointing to the same commit as the
  234. // last tag on the branch, in which case we use the prior tag and
  235. // add '+0-dev' to indicate we're still on a -dev branch.
  236. else {
  237. $rebuild_version = $last_tag . '+0-dev';
  238. }
  239. }
  240. }
  241. return $rebuild_version;
  242. }