source: trunk/moap/command/doap.py @ 171

Revision 171, 10.0 KB checked in by thomas, 6 years ago (diff)
  • moap/command/doap.py (Freshmeat.do): Don't use Default as the branch if the moap version specifies it.
Line 
1# -*- Mode: Python -*-
2# vi:si:et:sw=4:sts=4:ts=4
3
4import os
5import sys
6import urllib
7import tarfile
8
9from moap.util import util, mail
10from moap.doap import doap
11import bug
12
13
14def urlgrab(url, filename):
15    opener = urllib.URLopener()
16    try:
17        (t, h) = opener.retrieve(url, filename)
18    except IOError, e:
19        if len(e.args) == 4:
20            # http error masquerading as IO error
21            if e.args[0] != 'http error':
22                raise e
23            code = e.args[1]
24            if code == 404:
25                print "URL %s not found" % url
26                raise e
27            else:
28                raise e
29
30
31class Freshmeat(util.LogCommand):
32    summary = "submit to Freshmeat"
33    description = """This command submits a release to Freshmeat.
34Login details are taken from $HOME/.netrc.  Add a section for a machine named
35"freshmeat" with login and password settings.
36"""
37
38    def handleOptions(self, options):
39        self.options = options
40
41    def do(self, args):
42        self.debug('submitting to freshmeat')
43        d = self.parentCommand.doap
44
45        if not self.parentCommand.version:
46            sys.stderr.write('Please specify a version to submit with -v.\n')
47            return 3
48
49        # FIXME: add hide-from-front-page
50        project = d.getProject()
51
52        from moap.publish import freshmeat
53        fm = freshmeat.Session()
54        try:
55            fm.login()
56        except freshmeat.SessionException, e:
57            sys.stderr.write('Could not login to Freshmeat: %s\n' %
58                e.message)
59            return 3
60           
61
62        release = project.getRelease(self.parentCommand.version)
63        if not release:
64            sys.stderr.write('No revision %s found.\n' % 
65                self.parentCommand.version)
66            return 3
67
68        # FIXME: fm.fetch_release() seems to lie to me when I use it
69        # on gstreamer
70
71        # branches on Freshmeat are called "Default" by default
72        branch = release.version.branch or "Default"
73        # submit
74        # FIXME: how do we get changes and release_focus ?
75        args = {
76            'project_name':        project.shortname,
77            'branch_name':         branch,
78            'version':             release.version.revision,
79            'changes':             "Unknown",
80            'release_focus':       4,
81            'hide_from_frontpage': 'N',
82        }
83
84        for uri in release.version.file_release:
85            mapping = {
86                '.tar.gz':  'tgz',
87                '.tgz':     'tgz',
88                '.tar.bz2': 'bz2',
89                '.rpm':     'rpm',
90            }
91            for ext in mapping.keys():
92                if uri.endswith(ext):
93                    key = 'url_%s' % mapping[ext]
94                    self.stdout.write("- %s: %s\n" % (key, uri))
95                    args[key] = uri
96
97        self.stdout.write(
98            "Submitting release of %s %s on branch %s\n" % (
99                project.name, self.parentCommand.version, branch))
100        try:
101            fm.publish_release(**args)
102        except freshmeat.SessionError, e:
103            if e.code == 40:
104                self.stderr.write("ERROR: denied releasing %r\n" %
105                    self.parentCommand.version)
106            elif e.code == 51:
107                self.stderr.write(
108                    "Freshmeat already knows about this version\n")
109            elif e.code == 81:
110                self.stderr.write("Freshmeat does not know the project %s\n" %
111                    project.shortname)
112            else:
113                self.stderr.write("ERROR: %r\n" % e)
114
115class Mail(util.LogCommand):
116    summary = "send release announcement through mail"
117    usage = "mail [mail-options] [TO]..."
118    description = """Send out release announcement mail.
119The To: addresses can be specified as arguments to the mail command."""
120
121    def addOptions(self):
122        self.parser.add_option('-f', '--from',
123            action="store", dest="fromm",
124            help="address to send from")
125        self.parser.add_option('-n', '--dry-run',
126            action="store_true", dest="dry_run",
127            help="show the mail that would have been sent")
128        self.parser.add_option('-R', '--release-notes',
129            action="store", dest="release_notes",
130            help="release notes to use (otherwise looked up in tarball)")
131
132    def handleOptions(self, options):
133        self.options = options
134
135    def do(self, args):
136        d = self.parentCommand.doap
137
138        if not self.parentCommand.version:
139            sys.stderr.write('Please specify a version to submit with -v.\n')
140            return 3
141
142        version = self.parentCommand.version
143
144        if not self.options.fromm:
145            sys.stderr.write('Please specify a From: address with -f.\n')
146            return 3
147
148        if len(args) < 1:
149            sys.stderr.write('Please specify one or more To: addresses.\n')
150            return 3
151        to = args
152           
153        project = d.getProject()
154
155        release = project.getRelease(version)
156        if not release:
157            sys.stderr.write('No revision %s found.\n' % version)
158            return 3
159
160        # get a list of release files
161        keep = []
162        extensions = ['.tar.gz', '.tgz', '.tar.bz2']
163        for uri in release.version.file_release:
164            for ext in extensions:
165                if uri.endswith(ext):
166                    keep.append(uri)
167
168        self.debug('Release files: %r' % keep)
169
170        # now that we have a list of candidates, check if any of them
171        # exists in the current directory
172        found = False
173        for uri in keep:
174            filename = os.path.basename(uri)
175            if os.path.exists(filename):
176                sys.stdout.write("Found release %s in current directory.\n" %
177                    filename)
178                found = True
179                break
180
181        # if we don't have a local archive, try and get a uri one
182        if not found:
183            for uri in keep:
184                if uri.startswith('http') or uri.startswith('ftp:'):
185                    filename = os.path.basename(uri)
186                    sys.stdout.write('Downloading %s ... ' % uri)
187                    sys.stdout.flush()
188                    urlgrab(uri, filename)
189                    sys.stdout.write('done.\n')
190
191                    sys.stdout.write(
192                        "Downloaded %s in current dir\n" % filename)
193                    found = True
194                    break
195
196        if not found:
197            self.stderr.write("ERROR: no file found\n")
198            return 1
199
200        # filename now is the path to a tar/bz2
201        self.debug('Found %s' % filename)
202
203        # Find the release notes
204        RELEASE = None
205        if self.options.release_notes:
206            RELEASE = open(self.options.release_notes).read()
207        else:
208            tar_archive = tarfile.open(mode="r", name=filename)
209            for tarinfo in tar_archive:
210                if tarinfo.name.endswith('RELEASE'):
211                    RELEASE = tar_archive.extractfile(tarinfo).read()
212            tar_archive.close()
213
214        # now send out the mail with the release notes attached
215        d = {
216            'projectName': project.name,
217            'version':     version,
218            'releaseName': release.version.name
219        }
220        subject = "RELEASE: %(projectName)s %(version)s '%(releaseName)s'" % d
221        content = "This mail announces the release of "
222        content += "%(projectName)s %(version)s '%(releaseName)s'.\n\n" % d
223        content += "%s\n" % project.description
224        if project.homepage:
225            content += "For more information, see %s\n" % project.homepage
226        if project.bug_database:
227            content += "To file bugs, go to %s\n" % project.bug_database
228
229        message = mail.Message(subject, to, self.options.fromm)
230        message.setContent(content)
231
232        if RELEASE:
233            message.addAttachment('RELEASE', 'text/plain', RELEASE)
234
235        if self.options.dry_run:
236            self.stdout.write(message.get())
237        else:
238            self.stdout.write('Sending release announcement ... ')
239            message.send()
240            self.stdout.write('sent.\n')
241
242        return 0
243
244class Show(util.LogCommand):
245    description = "Show project information"
246
247    def do(self, args):
248        __pychecker__ = 'no-argsused'
249        d = self.parentCommand.doap
250        project = d.getProject()
251
252        self.stdout.write("DOAP file:         %s\n" % d.path)
253        self.stdout.write("project:           %s\n" % project.name)
254        if project.shortdesc:
255            self.stdout.write("short description: %s\n" % project.shortdesc)
256        if project.created:
257            self.stdout.write("created:           %s\n" % project.created)
258        if project.homepage:
259            self.stdout.write("homepage:          %s\n" % project.homepage)
260        if project.bug_database:
261            self.stdout.write("bug database:      %s\n" % project.bug_database)
262        if project.download_page:
263            self.stdout.write("download page:     %s\n" % project.download_page)
264        if not project.release:
265            self.stdout.write("                   No releases made.\n")
266        else:
267            v = project.release[0].version
268            self.stdout.write(
269                "Latest release:    version %s '%s' on branch %s.\n" % (
270                    v.revision, v.name, v.branch))
271
272class Doap(util.LogCommand):
273    """
274    @ivar doap: the L{doap.Doap} object.
275    """
276
277    usage = "doap [doap-options] %command"
278    description = "read and act on DOAP file"
279    subCommandClasses = [Freshmeat, Mail, Show, bug.Bug]
280
281    doap = None
282
283    def addOptions(self):
284        self.parser.add_option('-f', '--file',
285            action="store", dest="file",
286            help=".doap file to act on")
287        self.parser.add_option('-v', '--version',
288            action="store", dest="version",
289            help="version to submit")
290
291
292    def handleOptions(self, options):
293        self.path = None
294        if options.file: self.path = options.file
295        self.version = options.version
296
297        try:
298            d = doap.findDoapFile(self.path)
299        except doap.DoapException, e:
300            sys.stdout.write(e.args[0])
301            return 3
302        self.doap = d
303
304
Note: See TracBrowser for help on using the repository browser.