Save requirements (e.g. --not-before) with apps
[zeroinstall.git] / zeroinstall / cmd / update.py
blob40877c0ade63dd7f9a9371fe8d45ad846d39919d
1 """
2 The B{0install download} command-line interface.
3 """
5 # Copyright (C) 2011, Thomas Leonard
6 # See the README file for details, or visit http://0install.net.
8 from __future__ import print_function
10 import sys
12 from zeroinstall import SafeException, _
13 from zeroinstall.injector import model, requirements
14 from zeroinstall.cmd import UsageError, select
16 syntax = "URI"
18 add_options = select.add_generic_select_options
20 def handle(config, options, args):
21 if len(args) != 1:
22 raise UsageError()
24 assert not options.offline
26 old_gui = options.gui
28 app = config.app_mgr.lookup_app(args[0], missing_ok = True)
29 if app is not None:
30 old_sels = app.get_selections()
31 old_selections = old_sels.selections
32 iface_uri = old_sels.interface
33 r = app.get_requirements()
34 r.parse_update_options(options)
35 else:
36 iface_uri = model.canonical_iface_uri(args[0])
38 r = requirements.Requirements(iface_uri)
39 r.parse_options(options)
41 # Select once in offline console mode to get the old values
42 options.offline = True
43 options.gui = False
44 options.refresh = False
46 try:
47 old_sels = select.get_selections_for(r, config, options,
48 select_only = True, download_only = False, test_callback = None)
49 except SafeException:
50 old_selections = {}
51 else:
52 if old_sels is None:
53 old_selections = {}
54 else:
55 old_selections = old_sels.selections
57 # Download in online mode to get the new values
58 config.network_use = model.network_full
59 options.offline = False
60 options.gui = old_gui
61 options.refresh = True
63 sels = select.get_selections_for(r, config, options,
64 select_only = False, download_only = True, test_callback = None)
65 if not sels:
66 sys.exit(1) # Aborted by user
68 root_feed = config.iface_cache.get_feed(iface_uri)
69 if root_feed:
70 target = root_feed.get_replaced_by()
71 if target is not None:
72 print(_("Warning: interface {old} has been replaced by {new}".format(old = iface_uri, new = target)))
74 changes = False
76 for iface, old_sel in old_selections.iteritems():
77 new_sel = sels.selections.get(iface, None)
78 if new_sel is None:
79 print(_("No longer used: %s") % iface)
80 changes = True
81 elif old_sel.version != new_sel.version:
82 print(_("%s: %s -> %s") % (iface, old_sel.version, new_sel.version))
83 changes = True
85 for iface, new_sel in sels.selections.iteritems():
86 if iface not in old_selections:
87 print(_("%s: new -> %s") % (iface, new_sel.version))
88 changes = True
90 root_sel = sels[iface_uri]
91 root_iface = config.iface_cache.get_interface(iface_uri)
92 latest = max((impl.version, impl) for impl in root_iface.implementations.values())[1]
93 if latest.version > model.parse_version(sels[iface_uri].version):
94 print(_("A later version ({name} {latest}) exists but was not selected. Using {version} instead.").format(
95 latest = latest.get_version(),
96 name = root_iface.get_name(),
97 version = root_sel.version))
98 if not config.help_with_testing and latest.get_stability() < model.stable:
99 print(_('To select "testing" versions, use:\n0install config help_with_testing True'))
100 elif not changes:
101 from zeroinstall.support import xmltools
103 # No obvious changes, but check for more subtle updates.
104 if xmltools.nodes_equal(sels.toDOM(), old_sels.toDOM()):
105 print(_("No updates found. Continuing with version {version}.").format(version = root_sel.version))
106 else:
107 changes = True
108 print(_("Updates to metadata found, but no change to version ({version}).").format(version = root_sel.version))
110 if app is not None:
111 if changes:
112 app.set_selections(sels)
113 app.set_requirements(r)