2 from zeroinstall
import SafeException
3 from xml
.dom
import minidom
4 from optparse
import OptionParser
7 from logging
import info
, debug
8 import edit
, validator
, create
12 parser
= OptionParser(usage
="usage: %prog [options] interface")
13 parser
.add_option("--add-version", help="add a new implementation", action
='store', metavar
='VERSION')
14 parser
.add_option("--archive-url", help="add archive at this URL", action
='store', metavar
='URL')
15 parser
.add_option("--archive-file", help="local copy of archive-url", action
='store', metavar
='FILE')
16 parser
.add_option("--archive-extract", help="subdirectory of archive to extract", action
='store', metavar
='DIR')
17 parser
.add_option("-c", "--create", help="create file if nonexistant", action
='store_true')
18 parser
.add_option("-d", "--add-digest", help="add extra digests", action
='store', metavar
='ALG')
19 parser
.add_option("-e", "--edit", help="edit with $EDITOR", action
='store_true')
20 parser
.add_option("-g", "--gpgsign", help="add a GPG signature block", action
='store_true')
21 parser
.add_option("-k", "--key", help="key to use for signing")
22 parser
.add_option("-l", "--local", help="create feed from local interface")
23 parser
.add_option("--manifest-algorithm", help="select algorithm for manifests", action
='append', metavar
='ALG')
24 parser
.add_option("--set-interface-uri", help="set interface URI", action
='store', metavar
='URI')
25 parser
.add_option("--set-id", help="set implementation ID", action
='store', metavar
='DIGEST')
26 parser
.add_option("--set-main", help="set main executable", action
='store', metavar
='EXEC')
27 parser
.add_option("--set-arch", help="set architecture", action
='store', metavar
='ARCH')
28 parser
.add_option("--set-released", help="set release date", action
='store', metavar
='DATE')
29 parser
.add_option("--set-stability", help="set stability", action
='store', metavar
='STABILITY')
30 parser
.add_option("--set-version", help="set version number", action
='store', metavar
='VERSION')
31 parser
.add_option("-s", "--stable", help="mark testing version stable", action
='store_true')
32 parser
.add_option("-x", "--xmlsign", help="add an XML signature block", action
='store_true')
33 parser
.add_option("-u", "--unsign", help="remove any signature", action
='store_true')
34 parser
.add_option("-v", "--verbose", help="more verbose output", action
='count')
35 parser
.add_option("-V", "--version", help="display version information", action
='store_true')
37 (options
, args
) = parser
.parse_args()
39 force_save
= options
.create
42 print "0publish (zero-install) " + version
43 print "Copyright (C) 2005-2007 Thomas Leonard"
44 print "This program comes with ABSOLUTELY NO WARRANTY,"
45 print "to the extent permitted by law."
46 print "You may redistribute copies of this program"
47 print "under the terms of the GNU General Public License."
48 print "For more information about these matters, see the file named COPYING."
53 logger
= logging
.getLogger()
54 if options
.verbose
== 1:
55 logger
.setLevel(logging
.INFO
)
57 logger
.setLevel(logging
.DEBUG
)
66 ans
= raw_input(q
+ " [Y/N] ").lower()
67 if ans
in ('y', 'yes'): return True
68 if ans
in ('n', 'no'): return False
71 # Load or create the starting data...
73 if os
.path
.exists(interface
):
74 contents
= file(interface
).read()
75 data
, sign_fn
, key
= signing
.check_signature(interface
)
77 if os
.path
.exists(options
.local
):
78 data
= create
.create_from_local(options
.local
)
79 sign_fn
= signing
.sign_unsigned
84 raise Exception("File '%s' does not exist." % options
.local
)
86 if options
.create
or confirm("Interface file '%s' does not exist. Create it?" % interface
):
87 data
= create
.create(interface
)
88 sign_fn
= signing
.sign_unsigned
90 options
.edit
= not options
.create
94 debug("Original data: %s", data
)
95 info("Original signing method: %s", sign_fn
.__name
__)
96 info("Original key: %s", key
)
102 if sign_fn
is signing
.sign_unsigned
and options
.key
:
103 sign_fn
= signing
.sign_xml
106 # Validate the input...
108 validator
.check(data
, warnings
= False) # Don't warn on load AND save!
110 except validator
.InvalidInterface
, ex
:
111 print "Invalid interface: " + str(ex
)
114 ans
= raw_input("Interface is invalid. (E)dit or (A)bort?").lower()
115 if ans
in ('e', 'edit'):
116 data
= edit
.edit(data
)
117 options
.edit
= False # Don't edit twice
119 if ans
in ('a', 'abort'): sys
.exit(1)
123 sign_fn
= signing
.sign_xml
125 sign_fn
= signing
.sign_unsigned
127 sign_fn
= signing
.sign_plain
129 print "Changing key from '%s' to '%s'" % (key
, options
.key
)
131 if options
.set_interface_uri
:
133 data
= release
.set_interface_uri(data
, options
.set_interface_uri
)
134 if options
.add_version
:
136 data
= release
.add_version(data
, options
.add_version
)
137 if options
.set_id
or options
.set_version
or options
.set_released
or \
138 options
.set_stability
or options
.set_arch
or options
.set_main
:
140 data
= release
.make_release(data
, options
.set_id
,
141 options
.set_version
, options
.set_released
, options
.set_stability
,
142 options
.set_main
, options
.set_arch
)
145 data
= stable
.mark_stable(data
)
146 if options
.archive_url
:
148 algs
= options
.manifest_algorithm
152 if hasattr(hashlib
, 'sha256'):
153 algs
.append('sha256')
154 data
= archive
.add_archive(data
, options
.archive_url
, options
.archive_file
, options
.archive_extract
, algs
)
155 elif options
.archive_file
or options
.archive_extract
:
156 raise Exception('Must use --archive-uri option')
159 data
= merge
.merge(data
, options
.local
)
160 if options
.add_digest
:
162 data
= digest
.add_digests(data
, alg
= options
.add_digest
)
164 data
= edit
.edit(data
)
167 # Validate the result...
169 validator
.check(data
)
171 except validator
.InvalidInterface
, ex
:
172 print "Invalid interface: " + str(ex
)
175 ans
= raw_input("Interface is invalid. (E)dit or (A)bort?").lower()
176 if ans
in ('e', 'edit'):
177 data
= edit
.edit(data
)
179 if ans
in ('a', 'abort'): sys
.exit(1)
181 if (old_data
== data
and sign_fn
== old_sign_fn
and key
== old_key
) and not force_save
:
182 print "Interface unchanged. Not writing."
186 doc
= minidom
.parseString(data
)
187 data
= create
.xml_header
+ doc
.documentElement
.toxml()
190 if not data
.endswith('\n'): data
+= '\n'
191 sign_fn(interface
, data
, key
)
193 info("Wrote '%s'", interface
)
195 if sign_fn
!= signing
.sign_unsigned
:
196 # Read it back in to find out what key we signed it with
197 # and ensure that the key has been exported
198 contents
= file(interface
).read()
199 saved_data
, saved_sign_fn
, saved_key
= signing
.check_signature(interface
)
200 assert saved_data
== data
201 assert saved_sign_fn
== sign_fn
202 signing
.export_key(os
.path
.dirname(interface
), saved_key
)
203 except KeyboardInterrupt, ex
:
204 print >>sys
.stderr
, "Aborted at user's request"
206 except SafeException
, ex
:
207 if options
.verbose
: raise
208 print >>sys
.stderr
, ex