--- /dev/null
+#include "chainedtask.h"
+
+using namespace std;
+
+ChainedTask::ChainedTask(Task *t):
+ current(0),
+ final_status(RUNNING)
+{
+ add_task(t);
+}
+
+ChainedTask::~ChainedTask()
+{
+ for(vector<Task *>::iterator i=tasks.begin(); i!=tasks.end(); ++i)
+ delete *i;
+}
+
+void ChainedTask::add_task(Task *t)
+{
+ tasks.push_back(t);
+}
+
+string ChainedTask::get_command() const
+{
+ string cmd;
+ for(vector<Task *>::const_iterator i=tasks.begin(); i!=tasks.end(); ++i)
+ {
+ if(i!=tasks.begin())
+ cmd += '\n';
+ cmd += (*i)->get_command();
+ }
+ return cmd;
+}
+
+void ChainedTask::start()
+{
+ prepare();
+
+ current = 0;
+ tasks[current]->start();
+}
+
+Task::Status ChainedTask::check()
+{
+ while(current<tasks.size() && !process(tasks[current]->check())) ;
+
+ return final_status;
+}
+
+Task::Status ChainedTask::wait()
+{
+ while(current<tasks.size() && !process(tasks[current]->wait())) ;
+
+ return final_status;
+}
+
+bool ChainedTask::process(Status sub_status)
+{
+ if(sub_status==SUCCESS && current+1<tasks.size())
+ {
+ // The task succeeded and there's more to run
+ ++current;
+ tasks[current]->start();
+ return true;
+ }
+
+ if(sub_status!=RUNNING)
+ {
+ // The task is not running anymore and either failed or was the last one
+ current = tasks.size();
+ final_status = sub_status;
+ }
+
+ return false;
+}
--- /dev/null
+#ifndef CHAINEDTASK_H_
+#define CHAINEDTASK_H_
+
+#include <vector>
+#include "task.h"
+
+/**
+Runs multiple tasks as one unit, one after the other. Execution of the chain
+will stop if any of the component tasks terminates with an error.
+*/
+class ChainedTask: public Task
+{
+private:
+ std::vector<Task *> tasks;
+ unsigned current;
+ Status final_status;
+
+public:
+ ChainedTask(Task *);
+ ~ChainedTask();
+
+ void add_task(Task *);
+
+ virtual std::string get_command() const;
+ virtual void start();
+ virtual Status check();
+ virtual Status wait();
+private:
+ bool process(Status);
+};
+
+#endif