[SCM] Samba Shared Repository - branch master updated

Jelmer Vernooij jelmer at samba.org
Sat Oct 2 14:13:48 MDT 2010


The branch, master has been updated
       via  20c6512 land: Implement --fail-immediately directly in Python, provide subunit file.
       via  72119de subunithelper: Make filter options optional.
       via  d7edb40 format-subunit: Split out summary file writing.
       via  4ece674 selftest: Move plain text formatter to subunithelper.
       via  8354518 land: Add separate treestagebuilder for subunit.
       via  b965a65 land: Cherry-pick tridges changes to autobuild.
       via  4190bd4 land: Move stage building into a separate class so we can have subclasses (e.g. subunit-specific).
       via  554289c land: Only pass shell=True if necessary.
       via  d03ff1c land: Add --fail-slowly option.
       via  9169044 Several smaller cleanups, use python coding style.
       via  7f01677 land: Avoid running things in a shell where not necessary.
       via  56ad550 land-remote: Checkout repository first.
       via  ff5fdb6 land-remote: Use --repository option.
       via  8ce24a9 land: Add --repository option.
       via  3c85d03 land: Move more functionality onto builder.
       via  74be4a2 land: Avoid more uses of chdir().
       via  6f6bfb3 Split land.py back out of autobuild.py, so I can change it without risking to break the autobuild system.
      from  13756d0 s3: Attempt to fix bug 7665

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 20c65121a7debe0ec2b7a316b6d36f97edf0264b
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sat Oct 2 20:32:16 2010 +0200

    land: Implement --fail-immediately directly in Python, provide subunit file.

commit 72119de02b61f567781ecaab7cfe5f48ac15113a
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sat Oct 2 18:41:14 2010 +0200

    subunithelper: Make filter options optional.

commit d7edb40fca382ec822a7b17e4b47ecabb43e99d6
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sat Oct 2 18:40:44 2010 +0200

    format-subunit: Split out summary file writing.

commit 4ece674a99ff6c2ca0b6af435d2fcd488fb67d09
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sat Oct 2 17:02:02 2010 +0200

    selftest: Move plain text formatter to subunithelper.

commit 8354518c9630269dd0fe3953e9c49a43b9119e6b
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sat Oct 2 13:26:36 2010 +0200

    land: Add separate treestagebuilder for subunit.

commit b965a65e03817a4481306c6332fc88548ad9dea4
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sat Oct 2 13:17:25 2010 +0200

    land: Cherry-pick tridges changes to autobuild.

commit 4190bd4e3463091d239acb521f7ba1cad04e8af7
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sat Oct 2 13:13:37 2010 +0200

    land: Move stage building into a separate class so we can have subclasses (e.g. subunit-specific).

commit 554289c261995e67e168a388f49d0861d75ce1a4
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sat Oct 2 02:59:21 2010 +0200

    land: Only pass shell=True if necessary.

commit d03ff1c9daf71fc1a9ddffde63744d809f4705f5
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 22:10:13 2010 +0200

    land: Add --fail-slowly option.

commit 916904443d6df7f9bd7502f31f1f7734e845a48a
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 21:55:10 2010 +0200

    Several smaller cleanups, use python coding style.

commit 7f0167770c1be1b0cb7a2ab8c657feac86c9b74d
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 21:43:20 2010 +0200

    land: Avoid running things in a shell where not necessary.

commit 56ad550a92c9c0c65da52861e43ed7595131d0ef
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 19:24:20 2010 +0200

    land-remote: Checkout repository first.

commit ff5fdb65f54f2e2efd865112f579989e96d848cf
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 21:35:35 2010 +0200

    land-remote: Use --repository option.

commit 8ce24a9187f7f93cb3557696034c94fc8be161f1
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 21:34:31 2010 +0200

    land: Add --repository option.

commit 3c85d031d37eb55c32dd3f9f600795ea51a4b935
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 19:03:18 2010 +0200

    land: Move more functionality onto builder.

commit 74be4a2abfb0be83bacce04dcc531968dc31c4b9
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 18:52:10 2010 +0200

    land: Avoid more uses of chdir().

commit 6f6bfb3f2039ce6ba3bd4c1ee1440becc2c6e104
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Fri Oct 1 21:28:32 2010 +0200

    Split land.py back out of autobuild.py, so I can change it without
    risking to break the autobuild system.

-----------------------------------------------------------------------

Summary of changes:
 script/{autobuild-remote.py => land-remote.py} |   12 +-
 script/{autobuild.py => land.py}               |  326 +++++++++++++++++-------
 selftest/format-subunit                        |  221 +---------------
 selftest/subunithelper.py                      |  208 +++++++++++++++-
 4 files changed, 465 insertions(+), 302 deletions(-)
 rename script/{autobuild-remote.py => land-remote.py} (83%)
 copy script/{autobuild.py => land.py} (58%)


Changeset truncated at 500 lines:

diff --git a/script/autobuild-remote.py b/script/land-remote.py
similarity index 83%
rename from script/autobuild-remote.py
rename to script/land-remote.py
index 4abc874..cb0d7da 100755
--- a/script/autobuild-remote.py
+++ b/script/land-remote.py
@@ -12,14 +12,17 @@ parser.add_option("--remote-repo", help="Location of remote repository (default:
 parser.add_option("--host", help="Host to land on (SSH connection string)", type=str, default="sn-devel-104.sn.samba.org")
 parser.add_option("--foreground", help="Don't daemonize", action="store_true", default=False)
 parser.add_option("--email", help="Email address to send build/test output to", type=str, default=None, metavar="EMAIL")
+parser.add_option("--always-email", help="always send email, even on success", action="store_true")
 parser.add_option("--rebase-master", help="rebase on master before testing", default=False, action='store_true')
 parser.add_option("--rebase", help="rebase on the given tree before testing", default=None, type='str')
 parser.add_option("--passcmd", help="command to run on success", default=None)
 parser.add_option("--tail", help="show output while running", default=False, action="store_true")
 parser.add_option("--keeplogs", help="keep logs", default=False, action="store_true")
 parser.add_option("--nocleanup", help="don't remove test tree", default=False, action="store_true")
-parser.add_option("", "--fix-whitespace", help="fix whitespace on rebase",
+parser.add_option("--fix-whitespace", help="fix whitespace on rebase",
                   default=False, action="store_true")
+parser.add_option("--fail-slowly", help="continue running tests even after one has already failed",
+                  action="store_true")
 
 (opts, args) = parser.parse_args()
 
@@ -35,6 +38,7 @@ if not opts.remote_repo:
         sys.exit(1)
     remote_repo = stdout.rstrip()
     print "Remote tempdir: %s" % remote_repo
+    # Bootstrap, git.samba.org is close to sn-devel
     remote_args = ["git", "clone", "git://git.samba.org/samba.git", remote_repo]
     #remote_args = ["git", "init", remote_repo]
     print "%s$ %s" % (opts.host, " ".join(remote_args))
@@ -43,12 +47,14 @@ else:
     remote_repo = opts.remote_repo
 
 print "Pushing local branch"
-args = ["git", "push", "--force", "git+ssh://%s/%s" % (opts.host, remote_repo), "HEAD:HEAD"]
+args = ["git", "push", "--force", "git+ssh://%s/%s" % (opts.host, remote_repo), "HEAD:land"]
 print "$ " + " ".join(args)
 subprocess.check_call(args)
-remote_args = ["cd", remote_repo, "&&", "python", "./script/autobuild.py"]
+remote_args = ["cd", remote_repo, ";", "git", "checkout", "land", ";", "python", "./script/land.py", "--repository=%s" % remote_repo]
 if opts.email:
     remote_args.append("--email=%s" % opts.email)
+if opts.always_email:
+    remote_args.append("--always-email")
 if not opts.foreground:
     remote_args.append("--daemon")
 if opts.nocleanup:
diff --git a/script/autobuild.py b/script/land.py
similarity index 58%
copy from script/autobuild.py
copy to script/land.py
index a0c2d9f..8f17c7c 100755
--- a/script/autobuild.py
+++ b/script/land.py
@@ -1,12 +1,20 @@
 #!/usr/bin/env python
 # run tests on all Samba subprojects and push to a git tree on success
 # Copyright Andrew Tridgell 2010
+# Copyright Jelmer Vernooij 2010
 # released under GNU GPL v3 or later
 
-from subprocess import call, check_call,Popen, PIPE
+import fcntl
+from subprocess import call, check_call, Popen, PIPE
 import os, tarfile, sys, time
 from optparse import OptionParser
 import smtplib
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../selftest"))
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/testtools"))
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/subunit/python"))
+import subunit
+import testtools
+import subunithelper
 from email.mime.text import MIMEText
 
 samba_master = os.getenv('SAMBA_MASTER', 'git://git.samba.org/samba.git')
@@ -22,12 +30,12 @@ tasks = {
                   ("make basics", "make basics", "text/plain"),
                   ("make", "make -j 4 everything", "text/plain"), # don't use too many processes
                   ("install", "make install", "text/plain"),
-                  ("test", "TDB_NO_FSYNC=1 make test FAIL_IMMEDIATELY=1", "text/plain") ],
+                  ("test", "TDB_NO_FSYNC=1 make subunit-test", "text/x-subunit") ],
 
     "source4" : [ ("configure", "./configure.developer ${PREFIX}", "text/plain"),
                   ("make", "make -j", "text/plain"),
                   ("install", "make install", "text/plain"),
-                  ("test", "TDB_NO_FSYNC=1 make test FAIL_IMMEDIATELY=1", "text/plain") ],
+                  ("test", "TDB_NO_FSYNC=1 make subunit-test", "text/x-subunit") ],
 
     "source4/lib/ldb" : [ ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
                           ("make", "make -j", "text/plain"),
@@ -44,7 +52,7 @@ tasks = {
                      ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
                      ("make", "make -j", "text/plain"),
                      ("install", "make install", "text/plain"),
-                     ("test", "make test", "text/plain"), ],
+                     ("test", "make test", "text/x-subunit"), ],
 
     "lib/replace" : [ ("autogen", "./autogen-waf.sh", "text/plain"),
                       ("configure", "./configure --enable-developer -C ${PREFIX}", "text/plain"),
@@ -71,71 +79,218 @@ retry_task = [ ( "retry",
                 done
                ''' % samba_master, "test/plain" ) ]
 
-def run_cmd(cmd, dir=".", show=None, output=False, checkfail=True):
+
+def run_cmd(cmd, dir=None, show=None, output=False, checkfail=True, shell=False):
     if show is None:
         show = options.verbose
     if show:
         print("Running: '%s' in '%s'" % (cmd, dir))
     if output:
-        return Popen([cmd], shell=True, stdout=PIPE, cwd=dir).communicate()[0]
+        return Popen(cmd, stdout=PIPE, cwd=dir, shell=shell).communicate()[0]
     elif checkfail:
-        return check_call(cmd, shell=True, cwd=dir)
+        return check_call(cmd, cwd=dir, shell=shell)
     else:
-        return call(cmd, shell=True, cwd=dir)
+        return call(cmd, cwd=dir, shell=shell)
 
 
-class builder(object):
-    '''handle build of one directory'''
+class TreeStageBuilder(object):
+    """Handle building of a particular stage for a tree.
+    """
 
-    def __init__(self, name, sequence):
+    def __init__(self, tree, name, command, fail_quickly=False):
+        self.tree = tree
         self.name = name
-
-        if name in ['pass', 'fail', 'retry']:
-            self.dir = "."
+        self.command = command
+        self.fail_quickly = fail_quickly
+        self.status = None
+        self.stdin = open(os.devnull, 'r')
+
+    def start(self):
+        raise NotImplementedError(self.start)
+
+    def poll(self):
+        self.status = self.proc.poll()
+        return self.status
+
+    def kill(self):
+        if self.proc is not None:
+            try:
+                run_cmd(["killbysubdir", self.tree.sdir], checkfail=False)
+            except OSError:
+                # killbysubdir doesn't exist ?
+                pass
+            self.proc.terminate()
+            self.proc.wait()
+            self.proc = None
+
+    @property
+    def failure_reason(self):
+        return "failed '%s' with status %d" % (self.cmd, self.status)
+
+    @property
+    def failed(self):
+        return (os.WIFSIGNALED(self.status) or os.WEXITSTATUS(self.status) != 0)
+
+
+class PlainTreeStageBuilder(TreeStageBuilder):
+
+    def start(self):
+        print '%s: [%s] Running %s' % (self.name, self.name, self.command)
+        self.proc = Popen(self.command, shell=True, cwd=self.tree.dir,
+                          stdout=self.tree.stdout, stderr=self.tree.stderr,
+                          stdin=self.stdin)
+
+
+class AbortingTestResult(subunithelper.TestsuiteEnabledTestResult):
+
+    def __init__(self, stage):
+        super(AbortingTestResult, self).__init__()
+        self.stage = stage
+
+    def addError(self, test, details=None):
+        self.stage.proc.terminate()
+
+    def addFailure(self, test, details=None):
+        self.stage.proc.terminate()
+
+
+class SubunitTreeStageBuilder(TreeStageBuilder):
+
+    def __init__(self, tree, name, command, fail_quickly=False):
+        super(SubunitTreeStageBuilder, self).__init__(tree, name, command,
+                fail_quickly)
+        self.failed_tests = []
+        self.subunit_path = os.path.join(gitroot,
+            "%s.%s.subunit" % (self.tree.tag, self.name))
+        self.tree.logfiles.append(
+            (self.subunit_path, os.path.basename(self.subunit_path)))
+        self.subunit = open(self.subunit_path, 'w')
+
+        formatter = subunithelper.PlainFormatter(False, True, {})
+        clients = [formatter, subunit.TestProtocolClient(self.subunit)]
+        if fail_quickly:
+            clients.append(AbortingTestResult(self))
+        self.subunit_server = subunit.TestProtocolServer(
+            testtools.MultiTestResult(*clients),
+            self.subunit)
+        self.buffered = ""
+
+    def start(self):
+        print '%s: [%s] Running' % (self.tree.name, self.name)
+        self.proc = Popen(self.command, shell=True, cwd=self.tree.dir,
+            stdout=PIPE, stderr=self.tree.stderr, stdin=self.stdin)
+        fd = self.proc.stdout.fileno()
+        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
+        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
+
+    def poll(self):
+        try:
+            data = self.proc.stdout.read()
+        except IOError:
+            return None
         else:
-            self.dir = self.name
+            self.tree.stdout.write(data)
+            self.buffered += data
+            buffered = ""
+            for l in self.buffered.splitlines(True):
+                if l[-1] == "\n":
+                    self.subunit_server.lineReceived(l)
+                else:
+                    buffered += l
+            self.buffered = buffered
+            self.status = self.proc.poll()
+            if self.status is not None:
+                self.subunit.close()
+                import pdb; pdb.set_trace()
+            return self.status
+
+
+class TreeBuilder(object):
+    '''handle build of one directory'''
+
+    def __init__(self, name, sequence, fail_quickly=False):
+        self.name = name
+        self.fail_quickly = fail_quickly
 
         self.tag = self.name.replace('/', '_')
         self.sequence = sequence
         self.next = 0
-        self.stdout_path = "%s/%s.stdout" % (gitroot, self.tag)
-        self.stderr_path = "%s/%s.stderr" % (gitroot, self.tag)
+        self.stdout_path = os.path.join(gitroot, "%s.stdout" % (self.tag, ))
+        self.stderr_path = os.path.join(gitroot, "%s.stderr" % (self.tag, ))
+        self.logfiles = [(self.stdout_path, os.path.basename(self.stdout_path)),
+                         (self.stderr_path, os.path.basename(self.stderr_path))]
         if options.verbose:
             print("stdout for %s in %s" % (self.name, self.stdout_path))
             print("stderr for %s in %s" % (self.name, self.stderr_path))
-        run_cmd("rm -f %s %s" % (self.stdout_path, self.stderr_path))
+        if os.path.exists(self.stdout_path):
+            os.unlink(self.stdout_path)
+        if os.path.exists(self.stderr_path):
+            os.unlink(self.stderr_path)
         self.stdout = open(self.stdout_path, 'w')
         self.stderr = open(self.stderr_path, 'w')
-        self.stdin  = open("/dev/null", 'r')
-        self.sdir = "%s/%s" % (testbase, self.tag)
-        self.prefix = "%s/prefix/%s" % (testbase, self.tag)
-        run_cmd("rm -rf %s" % self.sdir)
+        self.sdir = os.path.join(testbase, self.tag)
+        if name in ['pass', 'fail', 'retry']:
+            self.dir = self.sdir
+        else:
+            self.dir = os.path.join(self.sdir, self.name)
+        self.prefix = os.path.join(testbase, "prefix", self.tag)
+        run_cmd(["rm", "-rf", self.sdir])
         cleanup_list.append(self.sdir)
         cleanup_list.append(self.prefix)
         os.makedirs(self.sdir)
-        run_cmd("rm -rf %s" % self.sdir)
-        run_cmd("git clone --shared %s %s" % (gitroot, self.sdir))
+        run_cmd(["rm",  "-rf", self.sdir])
+        run_cmd(["git", "clone", "--shared", gitroot, self.sdir])
         self.start_next()
 
     def start_next(self):
         if self.next == len(self.sequence):
             print '%s: Completed OK' % self.name
             self.done = True
+            self.stdout.close()
+            self.stderr.close()
             return
-        (self.stage, self.cmd, self.output_mime_type) = self.sequence[self.next]
-        self.cmd = self.cmd.replace("${PREFIX}", "--prefix=%s" % self.prefix)
-#        if self.output_mime_type == "text/x-subunit":
-#            self.cmd += " | %s --immediate" % (os.path.join(os.path.dirname(__file__), "selftest/format-subunit"))
-        print '%s: [%s] Running %s' % (self.name, self.stage, self.cmd)
-        cwd = os.getcwd()
-        os.chdir("%s/%s" % (self.sdir, self.dir))
-        self.proc = Popen(self.cmd, shell=True,
-                          stdout=self.stdout, stderr=self.stderr, stdin=self.stdin)
-        os.chdir(cwd)
+        (stage_name, cmd, output_mime_type) = self.sequence[self.next]
+        cmd = cmd.replace("${PREFIX}", "--prefix=%s" % self.prefix)
+        if output_mime_type == "text/plain":
+            self.stage = PlainTreeStageBuilder(self, stage_name, cmd,
+                self.fail_quickly)
+        elif output_mime_type == "text/x-subunit":
+            self.stage = SubunitTreeStageBuilder(self, stage_name, cmd,
+                self.fail_quickly)
+        else:
+            raise Exception("Unknown output mime type %s" % output_mime_type)
+        self.stage.start()
         self.next += 1
 
+    def remove_logs(self):
+        for path, name in self.logfiles:
+            os.unlink(path)
+
+    @property
+    def status(self):
+        return self.stage.status
+
+    def poll(self):
+        return self.stage.poll()
+
+    def kill(self):
+        if self.stage is not None:
+            self.stage.kill()
+            self.stage = None
+
+    @property
+    def failed(self):
+        if self.stage is None:
+            return False
+        return self.stage.failed
+
+    @property
+    def failure_reason(self):
+        return "%s: [%s] %s" % (self.name, self.stage.name,
+            self.stage.failure_reason)
 
-class buildlist(object):
+
+class BuildList(object):
     '''handle build of multiple directories'''
 
     def __init__(self, tasklist, tasknames):
@@ -150,10 +305,11 @@ class buildlist(object):
         if tasknames == []:
             tasknames = tasklist
         for n in tasknames:
-            b = builder(n, tasks[n])
+            b = TreeBuilder(n, tasks[n], not options.fail_slowly)
             self.tlist.append(b)
         if options.retry:
-            self.retry = builder('retry', retry_task)
+            self.retry = TreeBuilder('retry', retry_task,
+                not options.fail_slowly)
             self.need_retry = False
 
     def kill_kids(self):
@@ -166,23 +322,18 @@ class buildlist(object):
             self.retry.proc.wait()
             self.retry = None
         for b in self.tlist:
-            if b.proc is not None:
-                run_cmd("killbysubdir %s > /dev/null 2>&1" % b.sdir, checkfail=False)
-                b.proc.terminate()
-                b.proc.wait()
-                b.proc = None
+            b.kill()
 
     def wait_one(self):
         while True:
             none_running = True
             for b in self.tlist:
-                if b.proc is None:
+                if b.stage is None:
                     continue
                 none_running = False
-                b.status = b.proc.poll()
-                if b.status is None:
+                if b.poll() is None:
                     continue
-                b.proc = None
+                b.stage = None
                 return b
             if options.retry:
                 ret = self.retry.proc.poll()
@@ -203,9 +354,9 @@ class buildlist(object):
                 return (0, None, None, None, "retry")
             if b is None:
                 break
-            if os.WIFSIGNALED(b.status) or os.WEXITSTATUS(b.status) != 0:
+            if b.failed:
                 self.kill_kids()
-                return (b.status, b.name, b.stage, b.tag, "%s: [%s] failed '%s' with status %d" % (b.name, b.stage, b.cmd, b.status))
+                return (b.status, b.name, b.stage, b.tag, b.failure_reason)
             b.start_next()
         self.kill_kids()
         return (0, None, None, None, "All OK")
@@ -213,22 +364,19 @@ class buildlist(object):
     def tarlogs(self, fname):
         tar = tarfile.open(fname, "w:gz")
         for b in self.tlist:
-            tar.add(b.stdout_path, arcname="%s.stdout" % b.tag)
-            tar.add(b.stderr_path, arcname="%s.stderr" % b.tag)
-        tar.add("autobuild.log")
+            for (path, name) in b.logfiles:
+                tar.add(path, arcname=name)
+        if os.path.exists("autobuild.log"):
+            tar.add("autobuild.log")
         tar.close()
 
     def remove_logs(self):
         for b in self.tlist:
-            os.unlink(b.stdout_path)
-            os.unlink(b.stderr_path)
+            b.remove_logs()
 
     def start_tail(self):
-        cwd = os.getcwd()
         cmd = "tail -f *.stdout *.stderr"
-        os.chdir(gitroot)
-        self.tail_proc = Popen(cmd, shell=True)
-        os.chdir(cwd)
+        self.tail_proc = Popen(cmd, shell=True, cwd=gitroot)
 
 
 def cleanup():
@@ -236,12 +384,11 @@ def cleanup():
         return
     print("Cleaning up ....")
     for d in cleanup_list:
-        run_cmd("rm -rf %s" % d)
+        run_cmd(["rm", "-rf", d])
 
 
-def find_git_root():
+def find_git_root(p):
     '''get to the top of the git repo'''
-    p=os.getcwd()
     while p != '/':
         if os.path.isdir(os.path.join(p, ".git")):
             return p
@@ -275,13 +422,13 @@ def daemonize(logfile):
 
 def rebase_tree(url):
     print("Rebasing on %s" % url)
-    run_cmd("git remote add -t master master %s" % url, show=True, dir=test_master)
-    run_cmd("git fetch master", show=True, dir=test_master)
+    run_cmd(["git", "remote", "add", "-t", "master", "master", url], show=True, dir=test_master)
+    run_cmd(["git", "fetch", "master"], show=True, dir=test_master)
     if options.fix_whitespace:
-        run_cmd("git rebase --whitespace=fix master/master", show=True, dir=test_master)
+        run_cmd(["git", "rebase", "--whitespace=fix", "master/master"], show=True, dir=test_master)
     else:
-        run_cmd("git rebase master/master", show=True, dir=test_master)
-    diff = run_cmd("git --no-pager diff HEAD master/master", dir=test_master, output=True)
+        run_cmd(["git", "rebase", "master/master"], show=True, dir=test_master)
+    diff = run_cmd(["git", "--no-pager", "diff", "HEAD", "master/master"], dir=test_master, output=True)
     if diff == '':
         print("No differences between HEAD and master/master - exiting")
         sys.exit(0)
@@ -289,15 +436,16 @@ def rebase_tree(url):
 def push_to(url):
     print("Pushing to %s" % url)
     if options.mark:
-        run_cmd("EDITOR=script/commit_mark.sh git commit --amend -c HEAD", dir=test_master)
+        run_cmd("EDITOR=script/commit_mark.sh git commit --amend -c HEAD", dir=test_master, shell=True)
         # the notes method doesn't work yet, as metze hasn't allowed refs/notes/* in master
         # run_cmd("EDITOR=script/commit_mark.sh git notes edit HEAD", dir=test_master)
-    run_cmd("git remote add -t master pushto %s" % url, show=True, dir=test_master)
-    run_cmd("git push pushto +HEAD:master", show=True, dir=test_master)
+    run_cmd(["git", "remote", "add", "-t", "master", "pushto", url], show=True, dir=test_master)
+    run_cmd(["git", "push", "pushto", "+HEAD:master"], show=True, dir=test_master)
 
 def_testbase = os.getenv("AUTOBUILD_TESTBASE", "/memdisk/%s" % os.getenv('USER'))
 
 parser = OptionParser()
+parser.add_option("", "--repository", help="repository to run tests for", default=None, type=str)
 parser.add_option("", "--tail", help="show output while running", default=False, action="store_true")
 parser.add_option("", "--keeplogs", help="keep logs", default=False, action="store_true")
 parser.add_option("", "--nocleanup", help="don't remove test tree", default=False, action="store_true")
@@ -326,6 +474,8 @@ parser.add_option("", "--always-email", help="always send email, even on success
                   action="store_true")
 parser.add_option("", "--daemon", help="daemonize after initial setup",
                   action="store_true")
+parser.add_option("", "--fail-slowly", help="continue running tests even after one has already failed",
+                  action="store_true")
 
 
 def email_failure(status, failed_task, failed_stage, failed_tag, errstr):


-- 
Samba Shared Repository


More information about the samba-cvs mailing list