[Buildbot-devel] [PATCH v2 10/12] Allow patches to be submitted	through the web interface. 	If and only if user authentication is used to allow force/stop
	builds, users can also attach a patch to the `force build' request.
	* buildbot/sourcestamp.py (SourceStamp.__init__): Enhance the
	documentation.
	(make_force_build_form): Add fields to upload a patch and specify a
	patch-level.
	* buildbot/status/web/builder.py (StatusResourceBuilder.force):
	Handle the new fields of the form to allow patches for authenticated
	users.

Signed-off-by: Benoit Sigoure 
---
 buildbot/sourcestamp.py        |    3 ++-
 buildbot/status/web/base.py    |   17 +++++++++++++++--
 buildbot/status/web/builder.py |   30 ++++++++++++++++++++++++------
 3 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/buildbot/sourcestamp.py b/buildbot/sourcestamp.py
index 69d3c30..a388014 100644
--- a/buildbot/sourcestamp.py
+++ b/buildbot/sourcestamp.py
@@ -12,7 +12,8 @@ class SourceStamp(util.ComparableMixin):
        None, build the HEAD revision from the given branch.
      - (revision=REV, patchspec=(LEVEL, DIFF), changes=None): checkout REV,
        then apply a patch to the source, with C{patch -pPATCHLEVEL 
+    if useLoginPassword:
+        form_type = ' method="post" enctype="multipart/form-data"'
+        form_attach = (make_row("Build with a patch?",
+                                '')
+                       + make_row("Patch level:",
+                                  ''))
+    else:
+        form_attach = ""
+        form_type = ""
+
+    data = """
To force a build, fill out the following fields and
-      click the `Force Build' button""" % forceURL
+      click the `Force Build' button
+    """ % (forceURL, form_type)
     return (data
       + make_name_login_password_form(useLoginPassword)
       + make_row("Reason for build:",
@@ -97,6 +109,7 @@ def make_force_build_form(forceURL, useLoginPassword):
                  '')
       + make_row("Revision to build:",
                  '')
+      + form_attach
       + '\\n')
 
 colormap = {
diff --git a/buildbot/status/web/builder.py b/buildbot/status/web/builder.py
index e028c9d..900a33f 100644
--- a/buildbot/status/web/builder.py
+++ b/buildbot/status/web/builder.py
@@ -128,12 +128,26 @@ class StatusResourceBuilder(HtmlResource, OneLineMixin):
         reason = req.args.get("comments", [""])[0]
         branch = req.args.get("branch", [""])[0]
         revision = req.args.get("revision", [""])[0]
+        patch = req.args.get("patch", [""])[0]
+        if patch:
+            patch_level = req.args.get("plevel", ["1"])[0]
+            try:
+                patch_level = int(patch_level)
+            except ValueError:
+                # TODO: tell the web user that their request was invalid
+                return Redirect("..")
+            patch = (patch_level, patch)
+            has_patch = "yes"
+        else:
+            has_patch = "no"
+            patch = None
 
-        r = "The web-page 'force build' button was pressed by '%s': %s\\n" \\
-            % (name, reason)
-        log.msg("web forcebuild of builder '%s', branch='%s', revision='%s'"
-                "by user '%s'" % (self.builder_status.getName(), branch,
-                                  revision, name))
+        r = "The web-page 'force build' button was pressed by '%s': %s" \\
+            "(patch: %s)\\n" % (name, reason, has_patch)
+        log.msg("web forcebuild of builder '%s', branch='%s', "
+                "revision='%s', by user '%s' (patch: %s)" \\
+                % (self.builder_status.getName(), branch, revision, name,
+                   has_patch))
 
         if not self.builder_control:
             # TODO: tell the web user that their request was denied
@@ -144,6 +158,10 @@ class StatusResourceBuilder(HtmlResource, OneLineMixin):
             if not self.authUser(req):
                 # TODO: tell the web user that their request was denied
                 return Redirect("..")
+        else:
+            if patch:
+                log.msg("user is not authenticated: discarding the patch")
+            patch = None
 
         # keep weird stuff out of the branch and revision strings. TODO:
         # centralize this somewhere.
@@ -164,7 +182,7 @@ class StatusResourceBuilder(HtmlResource, OneLineMixin):
         # buildbot.changes.changes.Change instance which doesn't really fit
         # this use case (it requires a list of changed files which is tedious
         # to compute at this stage)
-        s = SourceStamp(branch=branch, revision=revision)
+        s = SourceStamp(branch=branch, revision=revision, patch=patch)
         req = BuildRequest(r, s, self.builder_status.getName())
         try:
             self.builder_control.requestBuildSoon(req)
-- 
1.5.3.5.756.gc887a


