Completed
Push — master ( 1ce881...81451d )
by Alexander
03:11
created

PharCreateCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 23
ccs 0
cts 18
cp 0
rs 9.0856
cc 1
eloc 17
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * This file is part of the SVN-Buddy library.
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 *
7
 * @copyright Alexander Obuhovich <[email protected]>
8
 * @link      https://github.com/console-helpers/svn-buddy
9
 */
10
11
namespace ConsoleHelpers\SVNBuddy\Command\Dev;
12
13
14
use ConsoleHelpers\ConsoleKit\Exception\CommandException;
15
use ConsoleHelpers\SVNBuddy\Command\AbstractCommand;
16
use ConsoleHelpers\SVNBuddy\Updater\Stability;
17
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
18
use Symfony\Component\Console\Input\InputInterface;
19
use Symfony\Component\Console\Input\InputOption;
20
use Symfony\Component\Console\Output\OutputInterface;
21
use Symfony\Component\Process\ProcessBuilder;
22
23
class PharCreateCommand extends AbstractCommand
24
{
25
26
	/**
27
	 * Root folder of the project.
28
	 *
29
	 * @var string
30
	 */
31
	private $_projectRootFolder;
32
33
	/**
34
	 * {@inheritdoc}
35
	 */
36
	protected function configure()
37
	{
38
		$this
39
			->setName('dev:phar-create')
40
			->setDescription(
41
				'Creates PHAR for new release'
42
			)
43
			->addOption(
44
				'build-dir',
45
				null,
46
				InputOption::VALUE_REQUIRED,
47
				'Directory, where build results would be stored',
48
				'build'
49
			)
50
			->addOption(
51
				'stability',
52
				's',
53
				InputOption::VALUE_REQUIRED,
54
				'Stability of the build (<comment>stable</comment>, <comment>snapshot</comment>, <comment>preview</comment>)'
55
			);
56
57
		parent::configure();
58
	}
59
60
	/**
61
	 * Prepare dependencies.
62
	 *
63
	 * @return void
64
	 */
65
	protected function prepareDependencies()
66
	{
67
		parent::prepareDependencies();
68
69
		$container = $this->getContainer();
70
71
		$this->_projectRootFolder = $container['project_root_folder'];
72
	}
73
74
	/**
75
	 * Return possible values for the named option
76
	 *
77
	 * @param string            $optionName Option name.
78
	 * @param CompletionContext $context    Completion context.
79
	 *
80
	 * @return array
81
	 */
82
	public function completeOptionValues($optionName, CompletionContext $context)
83
	{
84
		$ret = parent::completeOptionValues($optionName, $context);
85
86
		if ( $optionName === 'stability' ) {
87
			return $this->_getStabilities();
88
		}
89
90
		return $ret;
91
	}
92
93
	/**
94
	 * {@inheritdoc}
95
	 *
96
	 * @throws \RuntimeException When unknown stability was specified.
97
	 */
98
	protected function execute(InputInterface $input, OutputInterface $output)
99
	{
100
		$stability = $this->_getStability();
101
102
		if ( $stability && !in_array($stability, $this->_getStabilities()) ) {
103
			throw new \RuntimeException('The "' . $stability . '" is unknown.');
104
		}
105
106
		$version = $this->_getVersion();
107
		$build_dir = realpath($this->io->getOption('build-dir'));
108
109
		$this->io->write('1. removing dev dependencies ... ');
110
		$this->_shellCommand(
111
			'composer',
112
			array(
113
				'install',
114
				'--no-interaction',
115
				'--no-dev',
116
			),
117
			$this->_projectRootFolder
118
		);
119
		$this->io->writeln('done');
120
121
		$this->io->write('2. creating phar file ... ');
122
		$box_config = json_decode(file_get_contents($this->_projectRootFolder . '/box.json.dist'), true);
123
124
		$phar_file = $build_dir . '/' . basename($box_config['output']);
125
		$signature_file = $phar_file . '.sig';
126
127
		$box_config['replacements'] = array('git-version' => $version);
128
		$box_config['output'] = $phar_file;
129
130
		file_put_contents(
131
			$this->_projectRootFolder . '/box.json',
132
			json_encode($box_config, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0)
133
		);
134
135
		$box_cli = trim($this->_shellCommand('which', array('box')));
136
		$this->_shellCommand('php', array('-d', 'phar.readonly=0', $box_cli, 'build'), $this->_projectRootFolder);
137
		$this->io->writeln('done');
138
139
		$this->io->write('3. calculating phar signature ... ');
140
		file_put_contents(
141
			$signature_file,
142
			$this->_shellCommand('sha1sum', array(basename($phar_file)), dirname($phar_file))
143
		);
144
		$this->io->writeln('done');
145
146
		$this->io->write('4. restoring dev dependencies ... ');
147
		$this->_shellCommand(
148
			'composer',
149
			array(
150
				'install',
151
				'--no-interaction',
152
			),
153
			$this->_projectRootFolder
154
		);
155
		$this->io->writeln('done');
156
157
		$this->io->writeln('Phar for <info>' . $version . '</info> version created.');
158
	}
159
160
	/**
161
	 * Returns stability.
162
	 *
163
	 * @return string|null
164
	 */
165
	private function _getStability()
166
	{
167
		return $this->io->getOption('stability');
168
	}
169
170
	/**
171
	 * Returns all stabilities.
172
	 *
173
	 * @return array
174
	 */
175
	private function _getStabilities()
176
	{
177
		return array(Stability::PREVIEW, Stability::SNAPSHOT, Stability::STABLE);
178
	}
179
180
	/**
181
	 * Returns version.
182
	 *
183
	 * @return string
184
	 * @throws CommandException When "stable" stability was used with non-stable version.
185
	 */
186
	private function _getVersion()
187
	{
188
		$stability = $this->_getStability();
189
		$git_version = $this->_getGitVersion();
190
		$is_unstable = preg_match('/^.*-[\d]+-g.{7}$/', $git_version);
191
192
		if ( !$stability ) {
193
			$stability = $is_unstable ? Stability::PREVIEW : Stability::STABLE;
194
		}
195
196
		if ( $is_unstable && $stability === Stability::STABLE ) {
197
			throw new CommandException('The "' . $git_version . '" version can\'t be used with "stable" stability.');
198
		}
199
200
		return $stability . ':' . $git_version;
201
	}
202
203
	/**
204
	 * Returns same version as Box does for "git-version" replacement.
205
	 *
206
	 * @return string
207
	 */
208
	private function _getGitVersion()
209
	{
210
		return trim($this->_shellCommand(
211
			'git',
212
			array('describe', 'HEAD', '--tags'),
213
			$this->_projectRootFolder
214
		));
215
	}
216
217
	/**
218
	 * Runs command.
219
	 *
220
	 * @param string      $command           Command.
221
	 * @param array       $arguments         Arguments.
222
	 * @param string|null $working_directory Working directory.
223
	 *
224
	 * @return string
225
	 */
226
	private function _shellCommand($command, array $arguments = array(), $working_directory = null)
227
	{
228
		$final_arguments = array_merge(array($command), $arguments);
229
230
		$process = ProcessBuilder::create($final_arguments)
231
			->setWorkingDirectory($working_directory)
232
			->getProcess();
233
234
		return $process->mustRun()->getOutput();
235
	}
236
237
}
238