]> git.ozlabs.org Git - patchwork/blobdiff - apps/patchwork/bin/pwclient
patchwork: new pwclient git-am action
[patchwork] / apps / patchwork / bin / pwclient
index 863c1aeb00626b4396513a34002ba869fc363106..4c47b119193b7a50b7c800e25fd1a84da111014e 100755 (executable)
@@ -79,12 +79,13 @@ class Filter:
         """Return human-readable description of the filter."""
         return str(self.d)
 
-class BasicHTTPAuthTransport(xmlrpclib.Transport):
+class BasicHTTPAuthTransport(xmlrpclib.SafeTransport):
 
-    def __init__(self, username = None, password = None):
+    def __init__(self, username = None, password = None, use_https = False):
         self.username = username
         self.password = password
-        xmlrpclib.Transport.__init__(self)
+        self.use_https = use_https
+        xmlrpclib.SafeTransport.__init__(self)
 
     def authenticated(self):
         return self.username != None and self.password != None
@@ -97,12 +98,20 @@ class BasicHTTPAuthTransport(xmlrpclib.Transport):
         auth = 'Basic ' + base64.encodestring(credentials).strip()
         connection.putheader('Authorization', auth)
 
+    def make_connection(self, host):
+        if self.use_https:
+            fn = xmlrpclib.SafeTransport.make_connection
+        else:
+            fn = xmlrpclib.Transport.make_connection
+        return fn(self, host)
+
 def usage():
     sys.stderr.write("Usage: %s <action> [options]\n\n" % \
                         (os.path.basename(sys.argv[0])))
     sys.stderr.write("Where <action> is one of:\n")
     sys.stderr.write(
 """        apply <ID>    : Apply a patch (in the current dir, using -p1)
+        git-am <ID>   : Apply a patch to current git branch using "git am"
         get <ID>      : Download a patch and save it locally
         projects      : List all projects
         states        : Show list of potential patch states
@@ -165,13 +174,14 @@ def action_list(rpc, filter, submitter_str, delegate_str):
     if submitter_str != "":
         ids = person_ids_by_name(rpc, submitter_str)
         if len(ids) == 0:
-            sys.stderr.write("Note: Nobody found matching *%s*\n", \
+            sys.stderr.write("Note: Nobody found matching *%s*\n" % \
                              submitter_str)
         else:
             for id in ids:
                 person = rpc.person_get(id)
                 print "Patches submitted by %s <%s>:" % \
-                        (person['name'], person['email'])
+                        (unicode(person['name']).encode("utf-8"), \
+                         unicode(person['email']).encode("utf-8"))
                 f = filter
                 f.add("submitter_id", id)
                 patches = rpc.patch_list(f.d)
@@ -181,7 +191,7 @@ def action_list(rpc, filter, submitter_str, delegate_str):
     if delegate_str != "":
         ids = person_ids_by_name(rpc, delegate_str)
         if len(ids) == 0:
-            sys.stderr.write("Note: Nobody found matching *%s*\n", \
+            sys.stderr.write("Note: Nobody found matching *%s*\n" % \
                              delegate_str)
         else:
             for id in ids:
@@ -234,24 +244,31 @@ def action_get(rpc, patch_id):
         sys.exit(1)
 
     try:
-        f.write(s)
+        f.write(unicode(s).encode("utf-8"))
         f.close()
         print "Saved patch to %s" % fname
     except:
         sys.stderr.write("Failed to write to %s\n" % fname)
         sys.exit(1)
 
-def action_apply(rpc, patch_id):
+def action_apply(rpc, patch_id, apply_cmd=None):
     patch = rpc.patch_get(patch_id)
     if patch == {}:
         sys.stderr.write("Error getting information on patch ID %d\n" % \
                          patch_id)
         sys.exit(1)
-    print "Applying patch #%d to current directory" % patch_id
+
+    if apply_cmd is None:
+      print "Applying patch #%d to current directory" % patch_id
+      apply_cmd = ['patch', '-p1']
+    else:
+      print "Applying patch #%d using %s" % (
+          patch_id, repr(' '.join(apply_cmd)))
+
     print "Description: %s" % patch['name']
     s = rpc.patch_get_mbox(patch_id)
     if len(s) > 0:
-        proc = subprocess.Popen(['patch', '-p1'], stdin = subprocess.PIPE)
+        proc = subprocess.Popen(apply_cmd, stdin = subprocess.PIPE)
         proc.communicate(s)
     else:
         sys.stderr.write("Error: No patch content found\n")
@@ -285,8 +302,14 @@ def action_update_patch(rpc, patch_id, state = None, commit = None):
     if not success:
         sys.stderr.write("Patch not updated\n")
 
-def patch_id_from_hash(rpc, hash):
-    patch = rpc.patch_get_by_hash(hash)
+def patch_id_from_hash(rpc, project, hash):
+    try:
+        patch = rpc.patch_get_by_project_hash(project, hash)
+    except xmlrpclib.Fault:
+        # the server may not have the newer patch_get_by_project_hash function,
+        # so fall back to hash-only.
+        patch = rpc.patch_get_by_hash(hash)
+
     if patch == {}:
         return None
 
@@ -359,9 +382,12 @@ def main():
         if config.has_option('auth', 'username') and \
                 config.has_option('auth', 'password'):
 
+            use_https = url.startswith('https')
+
             transport = BasicHTTPAuthTransport( \
                     config.get('auth', 'username'),
-                    config.get('auth', 'password'))
+                    config.get('auth', 'password'),
+                    use_https)
 
         else:
             sys.stderr.write(("The %s action requires authentication, "
@@ -382,7 +408,7 @@ def main():
 
     patch_id = None
     if hash_str:
-        patch_id = patch_id_from_hash(rpc, hash_str)
+        patch_id = patch_id_from_hash(rpc, project_str, hash_str)
         if patch_id is None:
             sys.stderr.write("No patch has the hash provided\n")
             sys.exit(1)
@@ -428,6 +454,15 @@ def main():
 
         action_apply(rpc, patch_id)
 
+    elif action == 'git-am':
+        try:
+            patch_id = patch_id or int(args[0])
+        except:
+            sys.stderr.write("Invalid patch ID given\n")
+            sys.exit(1)
+
+        action_apply(rpc, patch_id, ['git', 'am'])
+
     elif action == 'update':
         try:
             patch_id = patch_id or int(args[0])