diff --git a/pykat/testing/test.py b/pykat/testing/test.py
index 152b9b92d6c7ead15e582ccefd0204509d5fb036..b3fc95c8a0549603ab513b98bcdd8728e01d24e9 100644
--- a/pykat/testing/test.py
+++ b/pykat/testing/test.py
@@ -29,14 +29,15 @@ class DiffException(Exception):
 		self.outfile = outfile
 
 def runcmd(args):
-	p = sub.Popen(args, stdout=sub.PIPE, stderr=sub.PIPE)
-	out, err = p.communicate()
-
-	if p.returncode != 0:
-		print err
-		raise RunException(p.returncode, args, err, out)
+    p = sub.Popen(args, stdout=sub.PIPE, stderr=sub.PIPE)
+    out, err = p.communicate()
+    
+    if p.returncode != 0:
+        print "STDERR: " + err
+        print "STDOUT: " + out
+        raise RunException(p.returncode, args, err, out)
 
-	return [out,err]
+    return [out,err]
 
 class FinesseTestProcess(Thread):
     
@@ -51,13 +52,18 @@ class FinesseTestProcess(Thread):
     diff_rel_eps = 1e-13
     running_kat = ""
     running_suite = ""
+    cancelling = False
     
-    def __init__(self, TEST_DIR, BASE_DIR, git_commit, 
+    def __init__(self, TEST_DIR, BASE_DIR, test_commit, 
                  run_fast=False, suites=[], test_id="0",
                  git_bin="",emails="", nobuild=True,*args, **kqwargs):
                  
         Thread.__init__(self)
-        self.git_commit = git_commit
+        self.git_commit = test_commit
+        
+        if test_commit is None:
+            raise Exception("A git commit ID must be provided for the test")
+        
         self.queue_time = datetime.now()
         self.test_id = test_id
         self.TEST_DIR = TEST_DIR
@@ -102,7 +108,11 @@ class FinesseTestProcess(Thread):
             self.suites.extend(suites)
 
         self.GIT_BIN = git_bin
-                
+    
+    def cancelCheck(self):
+        if self.cancelling:
+            raise SystemExit()
+    
     def percent_done(self):
         if self.total_kats == 0:
             return 0.0
@@ -126,29 +136,44 @@ class FinesseTestProcess(Thread):
             
         self.built = False
 
-        print type(self.nobuild), self.nobuild
-        
-        if not os.path.exists("build"):
-            os.mkdir("build")
-            
+        BUILD_PATH = os.path.join(self.BASE_DIR, "build")
+                    
         # Firstly we need to build the latest version of finesse
-        if os.path.isdir("build") and not self.nobuild:
-            print "deleting build dir..."
-            shutil.rmtree("build")
+        if not self.nobuild:
+            print "deleting build dir..." + BUILD_PATH
+            if os.path.exists(BUILD_PATH):
+                shutil.rmtree(BUILD_PATH)
 
             print "Checking out finesse base..."
-            utils.git(["clone","git://gitmaster.atlas.aei.uni-hannover.de/finesse/base.git","build"])
+            utils.git(["clone","git://gitmaster.atlas.aei.uni-hannover.de/finesse/base.git",BUILD_PATH])
 
-            os.chdir("build")
-            print "Checking out and building develop version of finesse..."
+            os.chdir(BUILD_PATH)
+            print "Checking out and building develop version of finesse " + self.git_commit
+            
+            SRC_PATH = os.path.join(BUILD_PATH,"src")
             
             if sys.platform == "win32":
-                runcmd(["bash","./finesse.sh","--checkout","develop"])
+                runcmd(["bash","./finesse.sh","--checkout"])
+                self.cancelCheck()
+                
+                os.chdir(SRC_PATH)
+                utils.git(["checkout",self.git_commit])
+                self.cancelCheck()
+                
+                os.chdir(BUILD_PATH)
                 runcmd(["bash","./finesse.sh","--build"])
+                self.cancelCheck()
             else:
-                EXE = ""
                 runcmd(["./finesse.sh","--checkout","develop"])
+                self.cancelCheck()
+                
+                os.chdir(SRC_PATH)
+                utils.git(["checkout",self.git_commit])
+                self.cancelCheck()
+                
+                os.chdir(BUILD_PATH)
                 runcmd(["./finesse.sh","--build"])
+                self.cancelCheck()
                 
             os.chdir(self.BASE_DIR)
             
@@ -156,7 +181,7 @@ class FinesseTestProcess(Thread):
         
         # check if kat runs
         if not os.path.exists(FINESSE_EXE):
-            raise Exception("Kat file was not found")
+            raise Exception("Kat file was not found in " + FINESSE_EXE)
         
         self.built = True
         
@@ -172,14 +197,18 @@ class FinesseTestProcess(Thread):
         
         os.environ["KATINI"] = os.path.join(self.TEST_DIR,"kat.ini")
         
+        self.cancelCheck()
         # Clean up and pull latest test repository
         print "Cleaning test repository..."
         os.chdir(self.TEST_DIR)
         utils.git(["clean","-xdf"])
+        self.cancelCheck()
         utils.git(["reset","--hard"])
+        self.cancelCheck()
         print "Pulling latest test..."
         utils.git(["pull"])
-
+        self.cancelCheck()
+    
         # Define storage structures for generating report later
         kat_run_exceptions = {}
         output_differences = {}
@@ -201,8 +230,9 @@ class FinesseTestProcess(Thread):
                 if files.endswith(".kat"):
                     self.total_kats += 1
                     print self.total_kats
-
+        
         for suite in self.suites:
+            self.cancelCheck()
             print "Running suite: " + suite + "..."
             kats = []
             os.chdir(os.path.join(self.TEST_DIR,"kat_test",suite))
@@ -217,6 +247,7 @@ class FinesseTestProcess(Thread):
             self.running_suite = suite
             
             for kat in kats:
+                self.cancelCheck()
                 self.running_kat = kat
                 
                 print self.get_progress()
@@ -237,6 +268,8 @@ class FinesseTestProcess(Thread):
                     finally:
                         self.done_kats += 1
 
+        self.cancelCheck()
+        
         for suite in self.suites:
             if len(kat_run_exceptions[suite].keys()) > 0:
                 print "Could not run the following kats:\n" + "\n".join(kat_run_exceptions.keys()) + " in " + suite
@@ -246,6 +279,7 @@ class FinesseTestProcess(Thread):
         
         # Now we have generated the output files compare them to the references
         for suite in self.suites:
+            self.cancelCheck()
             print "Diffing suite: " + suite + "..."
 
             outs = []
@@ -259,7 +293,9 @@ class FinesseTestProcess(Thread):
 
             if not os.path.exists(REF_DIR):
                 raise Exception("Suite reference directory doesn't exist: " + REF_DIR)
+                
             for out in outs:
+                self.cancelCheck()
                 #print "Diffing " + out
                 ref_file = os.path.join(REF_DIR,out)
                 
@@ -295,6 +331,8 @@ class FinesseTestProcess(Thread):
         reportname = today.strftime('%d%m%y')
         print "Writing report to " + reportname
 
+        self.cancelCheck()
+        
         f = open(reportname,'w')
         f.write("Python Nightly Test\n")
         f.write(today.strftime('%A, %d. %B %Y %I:%M%p') + "\n")
@@ -326,6 +364,8 @@ class FinesseTestProcess(Thread):
 
         f.close()
         
+        self.cancelCheck()
+        
         if self.emails:
             
             if isError:
diff --git a/pykat/testing/utils.py b/pykat/testing/utils.py
index 2e1c6a95b676418ad139ee9777a452db87ac2612..007585ba12ee50b9204fb563f671f8835ec49a96 100644
--- a/pykat/testing/utils.py
+++ b/pykat/testing/utils.py
@@ -19,11 +19,16 @@ def git(args):
     else:
         cmd = GIT_BIN + " " + args
         
+    print cmd
+    
+    print os.getcwd()
+    
     p = sub.Popen(cmd, stdout=sub.PIPE, stderr=sub.PIPE)
     out, err = p.communicate()
-
+        
     if p.returncode != 0:
-        print err
+        print "STDERR: " + err
+        print "STDOUT: " + err
         raise RunException(p.returncode, args, err, out)
 
     return [out, err]
diff --git a/pykat/testing/web/templates/finesse_test.html b/pykat/testing/web/templates/finesse_test.html
index c02fd0b81a78eda58324ec407e7c5ed0e1a5f3f3..faf5d89273edcda2e9155ca654735b3c87f2c2fa 100644
--- a/pykat/testing/web/templates/finesse_test.html
+++ b/pykat/testing/web/templates/finesse_test.html
@@ -15,6 +15,7 @@
                 Test status: <span id="txtStatus"></span>
                 <div id="current_test_progress" style="width:500px;"></div>
                 <input type="button" value="Refresh" id="btnGetProgress"/>
+                <input type="button" value="Cancel" id="btnCancelCurrent"/>
             </div>
             
             <div class="queued_tests">
@@ -37,10 +38,14 @@
             <div class="new_test">
             <h2>Start new test</h2>
             
+            <select id="branch_list" style="width: 100px;">
+                <option text="develop" value="develop"/>
+            </select>
+            
             <select id="commit_list" style="width: 300px;">
             </select>
             
-            <input type="button" value="Refresh log entries" id="btnGetLogs"/>
+            <input type="button" value="Refresh" id="btnGetLogs"/>
             
             <input type="button" value="Start new FINESSSE test" id="btnStartTest"/>
             </div>
@@ -52,7 +57,7 @@
         <script type="text/JavaScript">
                         
             $(document).ready(function(){
-                updateLogEntries();
+                updateBranches();
                 
                 window.setInterval(function(){                
                     updateQueuedTests();
@@ -70,6 +75,12 @@
             });
             
             $("#btnGetLogs").click(function(){
+                $("#branch_list").empty();
+                updateBranches();
+            });
+            
+            $("#branch_list").change(function(){
+                $("#commit_list").empty();
                 updateLogEntries();
             });
             
@@ -81,6 +92,7 @@
                 updateProgress();
             });
             
+            
             function updateProgress(){
                 $.ajax({
                   type: "POST",
@@ -88,14 +100,28 @@
                   url: "/finesse/get_test_progress",
                   success: function (data) {
                     
-                    if(data.running){
+                    if(data.cancelling){
+                        $('#btnCancelCurrent').attr("disabled", true);
                         $('#txtGitVersion').text(data.version);
-                        $('#txtStatus').text(data.status);
+                        $('#txtStatus').text("CANCELLING AT NEXT CHANCE - " + data.status);
                         $( "#current_test_progress" ).progressbar({ value: data.percent });
                     } else {
-                        $('#txtGitVersion').text("N/A");
-                        $('#txtStatus').text("No test running");
-                        $( "#current_test_progress" ).progressbar({ value: false });
+                        if(data.running){
+                            $('#txtGitVersion').text(data.version);
+                            $('#txtStatus').text(data.status);
+                            $("#current_test_progress").progressbar({ value: data.percent });
+                            $('#btnCancelCurrent').attr("disabled", false);
+                            $('#btnCancelCurrent').unbind('click');
+                            $('#btnCancelCurrent').click(function(){
+                                $('#btnCancelCurrent').attr("disabled", true);
+                                cancelTest(data.id);
+                            });
+                        } else {
+                            $('#btnCancelCurrent').attr("disabled", true);
+                            $('#txtGitVersion').text("N/A");
+                            $('#txtStatus').text("No test running");
+                            $( "#current_test_progress" ).progressbar({ value: false });
+                        }
                     }
                   },
                   error: function(jqXHR, textStatus, err){
@@ -105,6 +131,20 @@
                 });
             }
             
+            function cancelTest(id){
+                $.ajax({
+                  type: "POST",
+                  contentType: "application/json; charset=utf-8",
+                  url: "/finesse/cancel_test_" + id,
+                  success: function () {
+                  },
+                  error: function(jqXHR, textStatus, err){
+                    console.log('error: ' + err);
+                  },
+                  dataType: "json"
+                });
+            }
+            
             function startNewTest(){
                 
                 list = $("#commit_list");
@@ -160,7 +200,7 @@
                             rows += '<td>'+ tests[i].id + '</td>';
                             rows += '<td>'+ tests[i].queue_time +'</td>';
                             rows += '<td>'+ tests[i].git_commit +'</td>';
-                            rows += '<td>';
+                            rows += '<td><input type="button" value="Cancel" onclick="cancelTest(' + tests[i].id + ');"'+ +'</td>';
                             rows += '</tr>';
                             
                             tbl.append(rows);
@@ -176,21 +216,48 @@
                 });
             }
             
+            function updateBranches(){
+                $("#btnStartTest").attr("disabled", true);
+                blist = $("#branch_list");
+
+                $.ajax({
+                  type: "POST",
+                  contentType: "application/json; charset=utf-8",
+                  url: "/finesse/get_branches",
+                  success: function (data) {
+                    
+                    branches = data.branches;
+                    blist.empty();
+                    
+                    for(var i=0; i<branches.length; i++){
+                        blist.append($('<option>', { value: branches[i], text: branches[i]}));
+                    }
+                    
+                    updateLogEntries();
+                  },
+                  error: function(jqXHR, textStatus, err){
+                    console.log('error: ' + err);
+                  },
+                  dataType: "json"
+                });
+            }
+            
             function updateLogEntries(){
+                $("#btnStartTest").attr("disabled", true);
                 list = $("#commit_list");
-
-                list.empty();
                 
                 $.ajax({
                   type: "POST",
                   contentType: "application/json; charset=utf-8",
-                  url: "/finesse/get_50_logs",
+                  url: "/finesse/get_50_" + $("#branch_list").val() + "_logs",
                   success: function (data) {
                     logs = data.logs;
+                    list.empty();
                     
                     for(var i=0; i<logs.length; i++){
                         list.append($('<option>', { value: logs[i].commit, text: logs[i].commit + " - " + logs[i].message}));
                     }
+                    $("#btnStartTest").attr("disabled", false);
                   },
                   error: function(jqXHR, textStatus, err){
                     console.log('error: ' + err);
diff --git a/pykat/testing/web/web_interface.py b/pykat/testing/web/web_interface.py
index 7b1148bf31e98fba1639630ba1f561dd00acfb70..20a9052de017d2b6610561e83f9245c762f862d9 100644
--- a/pykat/testing/web/web_interface.py
+++ b/pykat/testing/web/web_interface.py
@@ -68,9 +68,47 @@ class FinesseProcessWatcher(Thread):
             current_test = None
         
         schedule_lock.release()
-        
-
 
+@app.route('/finesse/cancel_test_<id>', methods=["POST"])
+def finesse_cancel_test(id):
+    print id
+    
+    if int(id) >= 0:
+        id = int(id)
+        print "Cancelling " + str(id)
+        
+        try:
+            # get lock here so that watcher doesn't interfere
+            # with removing/starting new tests
+            schedule_lock.acquire()
+            
+            print current_test
+            
+            if current_test is not None:
+                print "cid " + str(current_test.test_id)
+                if current_test.test_id == id:
+                    current_test.cancelling = True
+                    print "Cancelling Current Test"
+                    return str(id)
+        
+            ix = 0
+            remove = -1;
+            
+            for t in scheduled_tests:
+                if t.test_id == id:
+                    remove = ix
+                    break
+                ix += 1
+             
+            if remove > -1:
+                print "Cancelled queued test"
+                scheduled_tests.pop(remove)
+                return str(id)
+            
+            print "Nothing cancelled"
+            return "0"
+        finally:
+            schedule_lock.release()     
 
 @app.route('/')
 def home_page():
@@ -105,7 +143,7 @@ def finesse_start_test():
                                       TEST_RUN_PATH,
                                       git_commit, 
                                       run_fast=False, suites=[], test_id=test_id,
-                                      emails="", nobuild=True)
+                                      emails="", nobuild=False)
         
         # check if anything is running and if it
         # isn't start this test off
@@ -148,21 +186,46 @@ def finesse_get_test_progress():
     
             return jsonify(running=False)
         else:
-    
+            test_id = current_test.test_id
+            cancelling = current_test.cancelling
             percent_done = current_test.percent_done()
             status = current_test.get_progress()
             version = current_test.get_version()
-            return jsonify(running=True, percent=percent_done, status=status, version=version)    
+            return jsonify(cancelling=cancelling, running=True, id=test_id, percent=percent_done, status=status, version=version)    
             
     finally:
         schedule_lock.release()
     
+@app.route('/finesse/get_branches', methods=["POST"])
+def finesse_get_branches():
+    os.chdir(os.path.join(app.instance_path,"finesse_src"))
+        
+    try:
+        [out,err] = utils.git("branch -a")
+    except Exception as ex:
+        print "git branch error : " + str(ex)
     
-@app.route('/finesse/get_<count>_logs', methods=['POST'])
-def finesse_get_log(count):
-    [out,err] = utils.git("--git-dir ./finesse_src/.git pull")
+    branches = list()
+    
+    for b in out.split("\n"):
+        vals = b.split("/")
+        if len(vals) >= 3:
+            branches.append(vals[2].split(" ")[0])
+
+    return jsonify(branches=branches)
+    
+@app.route('/finesse/get_<count>_<branch>_logs', methods=['POST'])
+def finesse_get_log(count,branch):
+    os.chdir(os.path.join(app.instance_path,"finesse_src"))
+        
+    print "!!!!", count, branch
+    try:
+        [out,err] = utils.git("checkout " + branch)
+        [out,err] = utils.git("pull")
+    except Exception as ex:
+        print "git pull error : " + str(ex)
     
-    [out,err] = utils.git("--git-dir ./finesse_src/.git log --max-count={0} --pretty=oneline".format(count))
+    [out,err] = utils.git("log --max-count={0} --pretty=oneline".format(count))
     
     log_entries = out.split("\n")
     
@@ -182,4 +245,5 @@ def finesse_get_log(count):
             
     
     return jsonify(logs=log2send)
-                       
\ No newline at end of file
+                     
+                
\ No newline at end of file
diff --git a/pykat/testing/web_server.py b/pykat/testing/web_server.py
index d5fd15660915e767778f745e08f1d6b2f0f1abb9..2d57324e4843c8c4c342c9b58db892ae5e294f4f 100644
--- a/pykat/testing/web_server.py
+++ b/pykat/testing/web_server.py
@@ -3,7 +3,7 @@ import sys
 from flask import Flask
 from pykat.testing import utils
 
-def start(instance_path,port=5000, debug=True):
+def start(instance_path,port=5000, debug=False):
     global app
     
     print "starting web server..."
@@ -31,8 +31,9 @@ def start(instance_path,port=5000, debug=True):
         print "finesse src folder didn't exist, cloning now..."
         utils.git("clone git://gitmaster.atlas.aei.uni-hannover.de/finesse/src.git finesse_src")
     else:
+        os.chdir(os.path.join(app.instance_path,"finesse_src"))
         # get the latest version for logs etc.
-        utils.git("--git-dir ./finesse_src/.git pull")
+        utils.git("pull")
         
     # need local copy of test
     if not os.path.exists("./finesse_test"):