diff --git a/src/Liip/RMT/Action/BaseAction.php b/src/Liip/RMT/Action/BaseAction.php
index 502cb41c..f110e103 100644
--- a/src/Liip/RMT/Action/BaseAction.php
+++ b/src/Liip/RMT/Action/BaseAction.php
@@ -27,6 +27,14 @@ public function __construct($options = array())
*/
abstract public function execute();
+ /**
+ * Rollback the effect of this action
+ */
+ public function rollback()
+ {
+ // assume there is nothing to do by default
+ }
+
/**
* Return the name of the action as it will be display to the user
*
diff --git a/src/Liip/RMT/Action/VcsCommitAction.php b/src/Liip/RMT/Action/VcsCommitAction.php
index a74bb414..07288e9c 100644
--- a/src/Liip/RMT/Action/VcsCommitAction.php
+++ b/src/Liip/RMT/Action/VcsCommitAction.php
@@ -38,9 +38,19 @@ public function execute()
return;
}
- $vcs->saveWorkingCopy(
- str_replace('%version%', Context::getParam('new-version'), $this->options['commit-message'])
- );
+ $vcs->saveWorkingCopy($this->getCommitMessage(Context::getParam('new-version')));
+ $this->confirmSuccess();
+ }
+
+ public function rollback()
+ {
+ $version = Context::get('version-persister')->getCurrentVersion();
+ Context::get('vcs')->revertLastCommit($this->getCommitMessage($version));
$this->confirmSuccess();
}
+
+ protected function getCommitMessage($version)
+ {
+ return str_replace('%version%', $version, $this->options['commit-message']);
+ }
}
diff --git a/src/Liip/RMT/Action/VcsTagAction.php b/src/Liip/RMT/Action/VcsTagAction.php
index ecff5aa5..2f07977c 100644
--- a/src/Liip/RMT/Action/VcsTagAction.php
+++ b/src/Liip/RMT/Action/VcsTagAction.php
@@ -27,4 +27,12 @@ public function execute()
);
$this->confirmSuccess();
}
+
+ public function rollback()
+ {
+ $tag = Context::get('version-persister')->getCurrentVersionTag();
+ Context::get('vcs')->deleteTag($tag);
+ $this->confirmSuccess();
+ }
+
}
diff --git a/src/Liip/RMT/Application.php b/src/Liip/RMT/Application.php
index 9491d17f..272a94a7 100644
--- a/src/Liip/RMT/Application.php
+++ b/src/Liip/RMT/Application.php
@@ -18,6 +18,7 @@
use Liip\RMT\Command\CurrentCommand;
use Liip\RMT\Command\ConfigCommand;
use Liip\RMT\Command\InitCommand;
+use Liip\RMT\Command\RollbackCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application as BaseApplication;
@@ -50,6 +51,7 @@ public function __construct()
// Add command that require the config file
if (file_exists($this->getConfigFilePath())) {
$this->add(new ReleaseCommand());
+ $this->add(new RollbackCommand());
$this->add(new CurrentCommand());
$this->add(new ChangesCommand());
$this->add(new ConfigCommand());
diff --git a/src/Liip/RMT/Command/RollbackCommand.php b/src/Liip/RMT/Command/RollbackCommand.php
new file mode 100644
index 00000000..7fd562ab
--- /dev/null
+++ b/src/Liip/RMT/Command/RollbackCommand.php
@@ -0,0 +1,60 @@
+setName('rollback');
+ $this->setDescription('Rollback the last release if there was no change since.');
+ $this->setHelp('The rollback should be used to cancel a previously done release.');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ if (count(Context::get('vcs')->getLocalModifications()) > 0) {
+ Context::get('output')->writeln('Local modifications found. Aborting.');
+ return;
+ }
+
+ $tag = Context::get('version-persister')->getCurrentVersionTag();
+ $modifications = Context::get('vcs')->getAllModificationsSince($tag, false, false);
+ if (count($modifications) > 0) {
+ Context::get('output')->writeln('There were commits since the last release. Aborting.');
+ return;
+ }
+
+ $this->rollbackActionListIfExist('post-release-actions');
+ $this->rollbackActionListIfExist('pre-release-actions');
+ }
+
+ protected function rollbackActionListIfExist($name)
+ {
+ $actions = Context::getInstance()->getList($name);
+ $actions = array_reverse($actions);
+ foreach ($actions as $num => $action) {
+ $this->getOutput()->write(++$num.') '.$action->getTitle().' : ');
+ $action->rollback();
+ }
+ }
+}
diff --git a/src/Liip/RMT/VCS/Git.php b/src/Liip/RMT/VCS/Git.php
index 4c35efb0..5111b318 100644
--- a/src/Liip/RMT/VCS/Git.php
+++ b/src/Liip/RMT/VCS/Git.php
@@ -50,6 +50,11 @@ public function createTag($tagName)
return $this->executeGitCommand("tag $tagName");
}
+ public function deleteTag($tagName)
+ {
+ return $this->executeGitCommand("tag -d $tagName");
+ }
+
public function publishTag($tagName, $remote = null)
{
$remote = $remote == null ? 'origin' : $remote;
@@ -68,6 +73,18 @@ public function saveWorkingCopy($commitMsg = '')
$this->executeGitCommand("commit -m \"$commitMsg\"");
}
+ public function revertLastCommit($commitMsg = null)
+ {
+ if (! is_null($commitMsg)) {
+ $msg = $this->executeGitCommand('log -1 --pretty=%B');
+ if (count($msg) != 1 || $msg[0] !== $commitMsg) {
+ return;
+ }
+ }
+
+ $this->executeGitCommand('reset --hard HEAD~1');
+ }
+
public function getCurrentBranch()
{
$branches = $this->executeGitCommand('branch');
diff --git a/src/Liip/RMT/VCS/Hg.php b/src/Liip/RMT/VCS/Hg.php
index 1fa713fc..f0277f38 100644
--- a/src/Liip/RMT/VCS/Hg.php
+++ b/src/Liip/RMT/VCS/Hg.php
@@ -58,6 +58,11 @@ public function createTag($tagName)
return $this->executeHgCommand("tag $tagName");
}
+ public function deleteTag($tagName)
+ {
+ return $this->executeHgCommand("tag --remove $tagName");
+ }
+
public function publishTag($tagName, $remote = null)
{
// nothing to do, tags are published with other changes
@@ -75,6 +80,17 @@ public function saveWorkingCopy($commitMsg = '')
$this->executeHgCommand("commit -m \"$commitMsg\"");
}
+ public function revertLastCommit($commitMsg = null)
+ {
+ if (! is_null($commitMsg)) {
+ $msg = $this->executeHgCommand('log -l 1 -T "{desc}"');
+ if (count($msg) != 1 || $msg[0] !== $commitMsg) {
+ return;
+ }
+ }
+
+ $this->executeHgCommand('reset --hard HEAD~1'); }
+
public function getCurrentBranch()
{
$data = $this->executeHgCommand('branch');
diff --git a/src/Liip/RMT/VCS/VCSInterface.php b/src/Liip/RMT/VCS/VCSInterface.php
index a6a858e1..d1bdb93c 100644
--- a/src/Liip/RMT/VCS/VCSInterface.php
+++ b/src/Liip/RMT/VCS/VCSInterface.php
@@ -32,6 +32,13 @@ public function getTags();
*/
public function createTag($tagName);
+ /**
+ * Delete a tag
+ *
+ * @param string $tagName
+ */
+ public function deleteTag($tagName);
+
/**
* Publish a new created tag
*
@@ -78,6 +85,14 @@ public function getLocalModifications();
*/
public function saveWorkingCopy($commitMsg = '');
+ /**
+ * Revert the last commit. If a message is given, only revert
+ * if the commit message matches.
+ *
+ * @param string|null $commitMsg
+ */
+ public function revertLastCommit($commitMsg = null);
+
/**
* Publish local modification
*