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("", "--select-version", help="select version to use in --set-* commands", action
='store', metavar
='VERSION')
33 parser
.add_option("-x", "--xmlsign", help="add an XML signature block", action
='store_true')
34 parser
.add_option("-u", "--unsign", help="remove any signature", action
='store_true')
35 parser
.add_option("-v", "--verbose", help="more verbose output", action
='count')
36 parser
.add_option("-V", "--version", help="display version information", action
='store_true')
38 (options
, args
) = parser
.parse_args()
40 force_save
= options
.create
43 print "0publish (zero-install) " + version
44 print "Copyright (C) 2005-2010 Thomas Leonard"
45 print "This program comes with ABSOLUTELY NO WARRANTY,"
46 print "to the extent permitted by law."
47 print "You may redistribute copies of this program"
48 print "under the terms of the GNU General Public License."
49 print "For more information about these matters, see the file named COPYING."
54 logger
= logging
.getLogger()
55 if options
.verbose
== 1:
56 logger
.setLevel(logging
.INFO
)
58 logger
.setLevel(logging
.DEBUG
)
67 ans
= raw_input(q
+ " [Y/N] ").lower()
68 if ans
in ('y', 'yes'): return True
69 if ans
in ('n', 'no'): return False
72 # Load or create the starting data...
74 if os
.path
.exists(interface
):
75 contents
= file(interface
).read()
76 data
, sign_fn
, key
= signing
.check_signature(interface
)
78 if os
.path
.exists(options
.local
):
79 data
= create
.create_from_local(options
.local
)
80 sign_fn
= signing
.sign_unsigned
85 raise Exception("File '%s' does not exist." % options
.local
)
87 if options
.create
or confirm("Interface file '%s' does not exist. Create it?" % interface
):
88 data
= create
.create(interface
)
89 sign_fn
= signing
.sign_unsigned
91 options
.edit
= not options
.create
95 debug("Original data: %s", data
)
96 info("Original signing method: %s", sign_fn
.__name
__)
97 info("Original key: %s", key
)
100 old_sign_fn
= sign_fn
103 if sign_fn
is signing
.sign_unsigned
and options
.key
:
104 sign_fn
= signing
.sign_xml
107 # Validate the input...
109 validator
.check(data
, warnings
= False) # Don't warn on load AND save!
111 except validator
.InvalidInterface
, ex
:
112 print "Invalid interface: " + str(ex
)
115 ans
= raw_input("Interface is invalid. (E)dit or (A)bort?").lower()
116 if ans
in ('e', 'edit'):
117 data
= edit
.edit(data
)
118 options
.edit
= False # Don't edit twice
120 if ans
in ('a', 'abort'): sys
.exit(1)
124 sign_fn
= signing
.sign_xml
126 sign_fn
= signing
.sign_unsigned
128 sign_fn
= signing
.sign_plain
130 print "Changing key from '%s' to '%s'" % (key
, options
.key
)
132 if options
.set_interface_uri
:
134 data
= release
.set_interface_uri(data
, options
.set_interface_uri
)
135 if options
.add_version
:
137 data
= release
.add_version(data
, options
.add_version
)
138 if options
.set_id
or options
.set_version
or options
.set_released
or \
139 options
.set_stability
or options
.set_arch
or options
.set_main
:
141 data
= release
.set_attributes(data
, options
.select_version
,
143 version
= options
.set_version
,
144 released
= options
.set_released
,
145 stability
= options
.set_stability
,
146 main
= options
.set_main
,
147 arch
= options
.set_arch
)
149 assert not options
.select_version
, "Use --set-stability=stable --select-version=... instead"
151 data
= stable
.mark_stable(data
)
152 if options
.archive_url
:
154 algs
= options
.manifest_algorithm
158 if hasattr(hashlib
, 'sha256'):
159 algs
.append('sha256')
160 data
= archive
.add_archive(data
, options
.archive_url
, options
.archive_file
, options
.archive_extract
, algs
)
161 elif options
.archive_file
or options
.archive_extract
:
162 raise Exception('Must use --archive-uri option')
165 data
= merge
.merge(data
, options
.local
)
166 if options
.add_digest
:
168 data
= digest
.add_digests(data
, alg
= options
.add_digest
)
170 data
= edit
.edit(data
)
173 # Validate the result...
175 validator
.check(data
)
177 except validator
.InvalidInterface
, ex
:
178 print "Invalid interface: " + str(ex
)
181 ans
= raw_input("Interface is invalid. (E)dit or (A)bort?").lower()
182 if ans
in ('e', 'edit'):
183 data
= edit
.edit(data
)
185 if ans
in ('a', 'abort'): sys
.exit(1)
187 if (old_data
== data
and sign_fn
== old_sign_fn
and key
== old_key
) and not force_save
:
188 print "Interface unchanged. Not writing."
192 doc
= minidom
.parseString(data
)
193 data
= create
.xml_header
+ doc
.documentElement
.toxml()
196 if not data
.endswith('\n'): data
+= '\n'
197 sign_fn(interface
, data
, key
)
199 info("Wrote '%s'", interface
)
201 if sign_fn
!= signing
.sign_unsigned
:
202 # Read it back in to find out what key we signed it with
203 # and ensure that the key has been exported
204 contents
= file(interface
).read()
205 saved_data
, saved_sign_fn
, saved_key
= signing
.check_signature(interface
)
206 assert saved_data
== data
207 assert saved_sign_fn
== sign_fn
208 signing
.export_key(os
.path
.dirname(interface
), saved_key
)
209 except KeyboardInterrupt, ex
:
210 print >>sys
.stderr
, "Aborted at user's request"
212 except SafeException
, ex
:
213 if options
.verbose
: raise
214 print >>sys
.stderr
, ex