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; |
12
|
|
|
|
13
|
|
|
|
14
|
|
|
use ConsoleHelpers\ConsoleKit\Exception\CommandException; |
15
|
|
|
use ConsoleHelpers\SVNBuddy\Repository\Connector\Connector; |
16
|
|
|
use ConsoleHelpers\SVNBuddy\Repository\WorkingCopyConflictTracker; |
17
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
18
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
19
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
20
|
|
|
|
21
|
|
|
class RevertCommand extends AbstractCommand implements IAggregatorAwareCommand |
22
|
|
|
{ |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Working copy conflict tracker. |
26
|
|
|
* |
27
|
|
|
* @var WorkingCopyConflictTracker |
28
|
|
|
*/ |
29
|
|
|
private $_workingCopyConflictTracker; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Prepare dependencies. |
33
|
|
|
* |
34
|
|
|
* @return void |
35
|
|
|
*/ |
36
|
|
|
protected function prepareDependencies() |
37
|
|
|
{ |
38
|
|
|
parent::prepareDependencies(); |
39
|
|
|
|
40
|
|
|
$container = $this->getContainer(); |
41
|
|
|
|
42
|
|
|
$this->_workingCopyConflictTracker = $container['working_copy_conflict_tracker']; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* {@inheritdoc} |
47
|
|
|
*/ |
48
|
|
|
protected function configure() |
49
|
|
|
{ |
50
|
|
|
$this |
51
|
|
|
->setName('revert') |
52
|
|
|
->setDescription('Restore pristine working copy file (undo most local edits)') |
53
|
|
|
->addArgument( |
54
|
|
|
'path', |
55
|
|
|
InputArgument::OPTIONAL, |
56
|
|
|
'Working copy path', |
57
|
|
|
'.' |
58
|
|
|
); |
59
|
|
|
|
60
|
|
|
parent::configure(); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* {@inheritdoc} |
65
|
|
|
*/ |
66
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
67
|
|
|
{ |
68
|
|
|
$wc_path = $this->getWorkingCopyPath(); |
69
|
|
|
|
70
|
|
|
// Collect added path before "svn revert" because then they won't be shown as added by "svn status". |
71
|
|
|
$added_paths = $this->getAddedPaths(); |
72
|
|
|
|
73
|
|
|
$this->io->writeln('Reverting local changes in working copy ... '); |
74
|
|
|
$command = $this->repositoryConnector->getCommand( |
75
|
|
|
'revert', |
76
|
|
|
array('--depth', 'infinity', $wc_path) |
77
|
|
|
); |
78
|
|
|
$command->runLive(array( |
79
|
|
|
$wc_path => '.', |
80
|
|
|
)); |
81
|
|
|
|
82
|
|
|
$this->deletePaths($added_paths); |
83
|
|
|
|
84
|
|
|
$recorded_conflicts = $this->_workingCopyConflictTracker->getRecordedConflicts($wc_path); |
85
|
|
|
|
86
|
|
|
if ( $recorded_conflicts ) { |
|
|
|
|
87
|
|
|
$this->io->writeln(array( |
88
|
|
|
'', |
89
|
|
|
'Reverted Recorded Conflicts (' . count($recorded_conflicts) . ' paths):', |
90
|
|
|
)); |
91
|
|
|
|
92
|
|
|
foreach ( $recorded_conflicts as $conflicted_path ) { |
93
|
|
|
$this->io->writeln(' * ' . $conflicted_path); |
94
|
|
|
} |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
$this->_workingCopyConflictTracker->erase($wc_path); |
98
|
|
|
$this->io->writeln('<info>Done</info>'); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Returns added paths. |
103
|
|
|
* |
104
|
|
|
* @return array |
105
|
|
|
*/ |
106
|
|
|
protected function getAddedPaths() |
107
|
|
|
{ |
108
|
|
|
$wc_path = $this->getWorkingCopyPath(); |
109
|
|
|
|
110
|
|
|
$added_paths = array(); |
111
|
|
|
$status = $this->repositoryConnector->getWorkingCopyStatus($wc_path); |
112
|
|
|
|
113
|
|
|
foreach ( $status as $status_path => $status_path_data ) { |
114
|
|
|
if ( $status_path_data['item'] === Connector::STATUS_ADDED ) { |
115
|
|
|
$added_paths[] = $status_path; |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
return $added_paths; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Deletes given paths in the working copy. |
124
|
|
|
* |
125
|
|
|
* @param array $paths Paths. |
126
|
|
|
* |
127
|
|
|
* @return void |
128
|
|
|
* @throws CommandException When one of the paths can't be deleted. |
129
|
|
|
*/ |
130
|
|
|
protected function deletePaths(array $paths) |
131
|
|
|
{ |
132
|
|
|
if ( !$paths ) { |
|
|
|
|
133
|
|
|
return; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
// When folder with files is added delete files first and then folder. |
137
|
|
|
rsort($paths); |
138
|
|
|
$wc_path = $this->getWorkingCopyPath(); |
139
|
|
|
|
140
|
|
|
foreach ( $paths as $path ) { |
141
|
|
|
$absolute_path = $wc_path . '/' . $path; |
142
|
|
|
|
143
|
|
|
// At some point "svn revert" was improved to do this (maybe after SVN 1.6). |
144
|
|
|
if ( !file_exists($absolute_path) ) { |
145
|
|
|
continue; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
$deleted = is_dir($absolute_path) ? rmdir($absolute_path) : unlink($absolute_path); |
149
|
|
|
|
150
|
|
|
if ( $deleted ) { |
151
|
|
|
$this->io->writeln('Reverted \'' . str_replace($wc_path, '.', $absolute_path) . '\''); |
152
|
|
|
} |
153
|
|
|
else { |
154
|
|
|
throw new CommandException('Unable to delete "' . $path . '".'); |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Returns option names, that makes sense to use in aggregation mode. |
161
|
|
|
* |
162
|
|
|
* @return array |
163
|
|
|
*/ |
164
|
|
|
public function getAggregatedOptions() |
165
|
|
|
{ |
166
|
|
|
return array(); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
} |
170
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.