1717995ceb56610cd6e00d4ec9b443d2cbe291c6
[yaffs-website] / web / modules / contrib / hacked / src / hackedProjectWebDevDownloader.php
1 <?php
2
3 namespace Drupal\hacked;
4
5 use Exception;
6
7 /**
8  * Downloads a development snapshot of a project using Git.
9  */
10 class hackedProjectWebDevDownloader extends hackedProjectWebDownloader {
11
12   /**
13    * Get download information for the dev release.
14    *
15    * @return array
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.
20    */
21   function download_link() {
22     $info = array();
23     $project = &$this->project->project_info;
24
25     // Get the branch we're on.
26     $release = strtok($project['existing_version'],'-') . '-' . $project['existing_major'] . '.x-dev';
27     $branch = $project['releases'][$release]['tag'];
28
29     // Assign some information depending on the project type.
30     if ($project['project_type'] == 'core') {
31       // Special handling for core.
32       $info['module'] = 'drupal';
33     }
34     else {
35       // Contrib.
36       $info['module'] = $project['name'];
37     }
38
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'];
43
44     // Return it.
45     return $info;
46   }
47
48   /**
49    * Download the version of the project to compare.
50    *
51    * @return boolean
52    *   TRUE if the download was successful; FALSE otherwise.
53    */
54   function download() {
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'];
62
63     // Return the path if the project version has already been downloaded to
64     // the cache.
65     if (file_exists($destination)) {
66       return $destination;
67     }
68
69     // Clone the project repository and check out the appropriate branch.
70     try {
71       $this->git_clone($giturl, $destination, $branch);
72     }
73     catch (Exception $e) {
74       \Drupal::logger('hacked')->error($e->getMessage()->render());
75       return FALSE;
76     }
77
78     // Attempt to checkout the last commit before timestamp on the local version.
79     try {
80       $this->git_checkout($destination, $branch, $timestamp);
81     }
82     catch (Exception $e) {
83       \Drupal::logger('hacked')->error($e->getMessage()->render());
84       return FALSE;
85     }
86
87     return TRUE;
88   }
89
90   /**
91    * Clones a git repository in a temporary directory.
92    *
93    * @param $giturl
94    *   URL of the project.
95    * @param $path
96    *   The location in which to place the checkout.
97    * @param $branch
98    *   The branch to check out.
99    * @throws Exception on failure.
100    */
101   function git_clone($giturl, $path, $branch) {
102
103     // Get the Git command and location information.
104     $git_cmd = $this->git_get_command();
105     $dirname = dirname($path);
106     $basename = basename($path);
107
108     // Prepare the download location.
109     file_prepare_directory($dirname, FILE_CREATE_DIRECTORY);
110     file_prepare_directory($path, FILE_CREATE_DIRECTORY);
111
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);
114
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(),
119         '%path' => $path,
120         '%branch' => $branch,
121       ]));
122     }
123   }
124
125   /**
126    * Checks out the last Git commit prior to the project's timestamp.
127    *
128    * @param $path
129    *   The path of the Git repository where the checkout should happen.
130    * @param $branch
131    *   The desired branch within the repository containing the commit.
132    * @param $timestamp
133    *   The UNIX timestamp for the downloaded project.
134    * @throws Exception on failure.
135    */
136   function git_checkout($path, $branch, $timestamp) {
137
138     // Fetch the Git command.
139     $git_cmd = $this->git_get_command();
140
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);
144
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,
150       ]));
151     }
152   }
153
154   /**
155    * Helper function to return the command to run git on the command line.
156    *
157    * @return string
158    *   The command with which to run Git.
159    */
160   function git_get_command() {
161     $command = \Drupal::config('hacked.settings')->get('git_cmd');
162     return is_null($command) ? 'git' : $command;
163   }
164
165   /**
166    * Returns the final destination of the unpacked project.
167    *
168    * @return string
169    *   The unpacked project's path.
170    */
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();
175   }
176 }