]> thyrsus.com Git - freecode-submit.git/commitdiff
We're getting login.
authorEric S. Raymond <esr@thyrsus.com>
Sun, 7 Dec 2003 04:34:01 +0000 (04:34 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Sun, 7 Dec 2003 04:34:01 +0000 (04:34 +0000)
freshmeat-submit

index 3027c3f707b2311db71754a8b8ca5b0f9b93038d..7bf777405b1f957b0f9ae18e75fd64b4d8e70337 100755 (executable)
@@ -1,4 +1,6 @@
 #!/usr/bin/env python
+#
+# meathook -- script transactions with the Freshmeat server
 
 import sys
 
@@ -10,7 +12,7 @@ def error(m):
 if sys.version[:6] < '2.2.0':
     error("you must upgrade to Python 2.2.0 or better to use this script.")
 
-import xmlrpclib, netrc
+import xmlrpclib, netrc, email.Parser, optparse
 
 class FreshmeatSessionException:
     def __init__(self, msg):
@@ -21,7 +23,8 @@ class FreshmeatSession:
     freshmeat_xmlrpc = "http://dev.freshmeat.net/xmlrpc/"
 
     def __init__(self, login=None, password=None, verbose=0):
-        "Initialize an XML-RPC session to Freshmeat by loggin in."
+        "Initialize an XML-RPC session to Freshmeat by logging in."
+        self.verbose = verbose
         # If user didn't supply credentials, fetch from ~/.netrc
         if not login:
             try:
@@ -39,22 +42,161 @@ class FreshmeatSession:
         # Open xml-rpc connection to Freshmeat
         self.session = xmlrpclib.Server(FreshmeatSession.freshmeat_xmlrpc,
                                      verbose=verbose)
-        # Log in to the service
-        self.sid = self.session.login(login, password)
+        # Log in to Freshmeat
+        response = self.session.login( \
+            {"username":login, "password":password})
+        self.sid = response['SID']
+        self.lifetime = response['Validity']
+        if verbose:
+            print "Session ID = %s, lifetime = %s" % (self.sid, self.lifetime)
+
+    def set_project(self, name):
+        "Set the current project."
+        if self.verbose:
+            print "About to look up project"
+        self.pid = self.session.lookup_project_id({'SID':self.sid,'name':name})
+        if self.verbose:
+            print "Project ID is:", self.pid
+        self.branch_list = self.session.fetch_branch_list(self.sid, self.pid)
+        if self.verbose:
+            print "Project branch list is:", self.branch_list
+
+    def add_release(self, release_info, branch=None):
+        "Add a new release to the current project."
+        if not branch and len(self.branch_list) == 1:
+            branch = self.branch_list.keys()[0]
+        if not branch:
+            raise FreshmeatSessionException("branch specification required")
+        self.session.add_release(self.sid, self.pid, branch, dir(release_info))
+
+    def withdraw_release(self, release):
+        pass
   
     def logout(self):
+        "End the session."
         return self.session.logout(self.sid)
 
+freshmeat_field_map = (
+    ("Project",          "p", "project"),
+    ("Branch",           "b", "project"),
+    ("Version",          "v", "version"),
+    ("Changes",          "c", "changes"),
+    ("Release-Focus",    "r", "release_focus"),
+    ("Hide",             "x", "hide_from_frontpage"),
+    ("Home-Page-URL",    "H", "url_homepage"),
+    ("Gzipped-Tar-URL",  "G", "url_tgz"),
+    ("Bzipped-Tar-URL",  "B", "url_bz2"),
+    ("Zipped-Tar-URL",   "Z", "url_zip"),
+    ("RPM-URL",                 "R", "url_rom"),
+    ("Debian-URL",      "D", "url_deb"),
+    ("OSX-URL",                 "O", "url_osx"),
+    ("BSD-Port-URL",     "P", "url_bsdport"),
+    ("Purchase-URL",     "U", "url_purchase"),
+    ("CVS-URL",                 "C", "url_cvs"),
+    ("Mailing-List-URL", "L", "url_list"),
+    ("Mirror-Site-URL",  "M", "url_mirror"),
+    ("Demo-URL",        "E", "url_demo"),
+    )
+
+class FreshmeatMetadata:
+    "Complete release information for a project/branch pair."
+    # Member names are identical to the XML-RPC structure members
+    # for an add_release request.
+    def __init__(self):
+       self.version = None             # Version string of new release
+       self.changes = None             # Changes list of new release
+        self.release_focus = None      # Release focus ID of new release
+       self.hide_from_frontpage = None # 'Y' if release is to be hidden
+       self.url_homepage = None        # Homepage
+       self.url_tgz = None             # Tar/GZ
+       self.url_bz2 = None             # Tar/BZ2
+       self.url_zip = None             # Zip
+       self.url_changelog = None       # Changelog
+       self.url_rpm = None             # RPM package
+       self.url_deb = None             # Debian package
+       self.url_osx = None             # OS X package
+       self.url_bsdport = None         # BSD Ports URL
+       self.url_purchase = None        # Purchase
+       self.url_cvs = None             # CVS tree (cvsweb)
+       self.url_list = None            # Mailing list archive
+       self.url_mirror = None          # Mirror site
+       self.url_demo = None            # Demo site
+
+    def field_to_header(hdr):
+        hdr = "-".join(map(lambda x: x.capitalize(), hdr.split("_")))
+        for (alias, shortopt, name) in field_map:
+            if hdr == name:
+                hdr = alias
+                break
+        return hdr
+
+    def __repr__(self):
+        res = ""
+        return res
+
+class FreshmeatMetadataFactory:
+    "Factory class for producing Metadata records"
+
+    def __init__(self):
+        self.message_parser = email.Parser.Parser()
+        self.argument_parser = optparse.OptionParser( \
+            usage="usage: %prog [options]")
+        for (msg_field, shortopt, rpc_field) in freshmeat_field_map:
+            self.argument_parser.add_option("-" + shortopt,
+                                            "--" + msg_field.lower(),
+                                            dest=rpc_field,
+                                            help="Set the %s field"%msg_field)
+        self.argument_parser.add_option('-n', '--no-stdin', dest='read',
+                          default=True, action='store_false',
+                          help='Suppress reading fields from stdin.')
+        self.argument_parser.add_option('-V', '--verbose', dest='verbose',
+                          default=True, action='store_false',
+                          help='Enable verbose debugging.')
+        
+    def header_to_field(self, hdr):
+        hdr = hdr.lower().replace("-", "_")
+        for (alias, shortopt, name) in freshmeat_field_map:
+            if hdr == alias.lower().replace("-", "_"):
+                hdr = name
+                break
+        return hdr
+
+    def getMetadata(self, stream):
+        "Make a Metadata object."
+        data = {}
+        (options, args) = self.argument_parser.parse_args()
+        if options.read:
+            message = self.message_parser.parse(stream)
+            for (key, value) in message.items():
+                data.update({self.header_to_field(key) : value})
+            if not 'comment' in data:
+                data['comment'] = message.get_payload() 
+        self.verbose = options.verbose
+
+        # Merge in options from the command line;
+        # they override what's on stdin.
+        data['verbose'] = False
+        for (key, value) in options.__dict__.items():
+            if key not in ('read', 'verbose') and value != None:
+                data[key] = value
+        return data
 
 if __name__ == "__main__":
+    # First, gather update data from stdin and command-line switches
+    factory = FreshmeatMetadataFactory()
+    data = factory.getMetadata(sys.stdin)
     try:
-        session = FreshmeatSession()
+        # Establish session
+        session = FreshmeatSession(data['verbose'])
+        # Connect with the appropriate project
+        session.set_project(data['project'])
     except FreshmeatSessionException, e:
         print "meathook:", e.msg
         sys.exit(1)
     except xmlrpclib.Fault, f:
-        print "meathook: %d, %s" %  (f.faultCode, f.faultString)
+        print "meathook: %d %s" %  (f.faultCode, f.faultString)
         sys.exit(1)
 
+
 # end