3 namespace Drupal\hacked;
8 * Downloads a development snapshot of a project using Git.
10 class hackedProjectWebDevDownloader extends hackedProjectWebDownloader {
13 * Get download information for the dev release.
16 * 'module' => The name of the project.
17 * 'giturl' => The upstream URL of the project.
18 * 'branch' => The development branch the snapshot was taken from.
19 * 'timestamp' => When the project was originally downloaded.
21 function download_link() {
23 $project = &$this->project->project_info;
25 // Get the branch we're on.
26 $release = strtok($project['existing_version'],'-') . '-' . $project['existing_major'] . '.x-dev';
27 $branch = $project['releases'][$release]['tag'];
29 // Assign some information depending on the project type.
30 if ($project['project_type'] == 'core') {
31 // Special handling for core.
32 $info['module'] = 'drupal';
36 $info['module'] = $project['name'];
39 // Assign all of the other information.
40 $info['giturl'] = 'https://git.drupal.org/project/' . $project['name'] . '.git';
41 $info['branch'] = $branch;
42 $info['timestamp'] = $project['datestamp'];
49 * Download the version of the project to compare.
52 * TRUE if the download was successful; FALSE otherwise.
55 // Get detailed information about the download.
56 $destination = $this->get_destination();
57 $info = $this->download_link();
58 $giturl = $info['giturl'];
59 $branch = $info['branch'];
60 $module = $info['module'];
61 $timestamp = $info['timestamp'];
63 // Return the path if the project version has already been downloaded to
65 if (file_exists($destination)) {
69 // Clone the project repository and check out the appropriate branch.
71 $this->git_clone($giturl, $destination, $branch);
73 catch (Exception $e) {
74 \Drupal::logger('hacked')->error($e->getMessage()->render());
78 // Attempt to checkout the last commit before timestamp on the local version.
80 $this->git_checkout($destination, $branch, $timestamp);
82 catch (Exception $e) {
83 \Drupal::logger('hacked')->error($e->getMessage()->render());
91 * Clones a git repository in a temporary directory.
96 * The location in which to place the checkout.
98 * The branch to check out.
99 * @throws Exception on failure.
101 function git_clone($giturl, $path, $branch) {
103 // Get the Git command and location information.
104 $git_cmd = $this->git_get_command();
105 $dirname = dirname($path);
106 $basename = basename($path);
108 // Prepare the download location.
109 file_prepare_directory($dirname, FILE_CREATE_DIRECTORY);
110 file_prepare_directory($path, FILE_CREATE_DIRECTORY);
112 // Perform the clone operation, and leave us in the appropriate branch.
113 exec("cd $dirname; $git_cmd clone --branch $branch $giturl $basename", $output_lines, $return_value);
115 // Throw an exception if it didn't work.
116 if ($return_value != 0) {
117 throw new Exception($this->t('Could not clone project %project into path %path at branch %branch.', [
118 '%project' => $this->project->title(),
120 '%branch' => $branch,
126 * Checks out the last Git commit prior to the project's timestamp.
129 * The path of the Git repository where the checkout should happen.
131 * The desired branch within the repository containing the commit.
133 * The UNIX timestamp for the downloaded project.
134 * @throws Exception on failure.
136 function git_checkout($path, $branch, $timestamp) {
138 // Fetch the Git command.
139 $git_cmd = $this->git_get_command();
141 // Point the working tree at the commit just before the timestamp.
142 // This takes us to the point in time when the local project was downloaded.
143 exec("cd $path; $git_cmd checkout $($git_cmd rev-list -n 1 --before='$timestamp' $branch)", $output_lines, $return_value);
145 // Throw an exception if it didn't work.
146 if ($return_value != 0) {
147 throw new Exception(t('Could not check out latest commit before %timestamp in Git repository %repository.', [
148 '%timestamp' => $timestamp,
149 '%repository' => $path,
155 * Helper function to return the command to run git on the command line.
158 * The command with which to run Git.
160 function git_get_command() {
161 $command = \Drupal::config('hacked.settings')->get('git_cmd');
162 return is_null($command) ? 'git' : $command;
166 * Returns the final destination of the unpacked project.
169 * The unpacked project's path.
171 function get_final_destination() {
172 // Simply return the original destination as Git's cloning already provides
173 // an unpacked project.
174 return $this->get_destination();