Added some missing test files to MANIFEST.in (reported by Peter Santoro).
[zeroinstall.git] / 0alias
blob923a3b695c6509dd9a778ee2bbab253f4a0fe7bf
1 #!/usr/bin/env python
2 import os, sys
3 from optparse import OptionParser
5 from zeroinstall.injector import reader, model, basedir
6 from zeroinstall import support, alias, helpers
8 def export(name, value):
9 """Try to guess the command to set an environment variable."""
10 shell = os.environ.get('SHELL', '?')
11 if 'csh' in shell:
12 return "setenv %s %s" % (name, value)
13 return "export %s=%s" % (name, value)
15 for first_path in os.environ['PATH'].split(':'):
16 if os.path.realpath(first_path).startswith(basedir.xdg_cache_home):
17 pass # print "Skipping cache", first_path
18 elif not os.access(first_path, os.W_OK):
19 pass # print "No access", first_path
20 else:
21 break
22 else:
23 print >>sys.stderr, ("No writable non-cache directory in $PATH, which currently contains:\n\n%s\n"
24 "To create a directory for your scripts, use these commands:\n"
25 "$ mkdir ~/bin\n"
26 "$ %s" % ('\n'.join(os.environ['PATH'].split(':')), export('PATH', '$HOME/bin:$PATH')))
27 sys.exit(1)
29 parser = OptionParser(usage="usage: %%prog [options] alias [interface [command]]\n\n"
30 "Creates a script in the first usable directory in $PATH\n"
31 "(%s) to run 'interface'.\n"
32 "If no interface is given, edits the policy for an existing alias.\n"
33 "For interfaces providing more than one command, the desired command\n"
34 "may also be given." % first_path)
35 parser.add_option("-m", "--manpage", help="show the manual page for an existing alias", action='store_true')
36 parser.add_option("-r", "--resolve", help="show the URI for an alias", action='store_true')
37 parser.add_option("-V", "--version", help="display version information", action='store_true')
38 parser.disable_interspersed_args()
40 (options, args) = parser.parse_args()
42 if options.version:
43 import zeroinstall
44 print "0alias (zero-install) " + zeroinstall.version
45 print "Copyright (C) 2007 Thomas Leonard"
46 print "This program comes with ABSOLUTELY NO WARRANTY,"
47 print "to the extent permitted by law."
48 print "You may redistribute copies of this program"
49 print "under the terms of the GNU Lesser General Public License."
50 print "For more information about these matters, see the file named COPYING."
51 sys.exit(0)
53 if options.manpage:
54 if len(args) != 1:
55 os.execlp('man', 'man', *args)
56 sys.exit(1)
58 if len(args) < 1 or len(args) > 3:
59 parser.print_help()
60 sys.exit(1)
61 alias_prog, interface_uri, main = (list(args) + [None, None])[:3]
63 if options.resolve or options.manpage:
64 if interface_uri is not None:
65 parser.print_help()
66 sys.exit(1)
68 if interface_uri is None:
69 try:
70 if not os.path.isabs(alias_prog):
71 full_path = support.find_in_path(alias_prog)
72 if not full_path:
73 raise alias.NotAnAliasScript("Not found in $PATH: " + alias_prog)
74 else:
75 full_path = alias_prog
77 interface_uri, main = alias.parse_script(full_path)
78 except alias.NotAnAliasScript, ex:
79 if options.manpage:
80 os.execlp('man', 'man', *args)
81 print >>sys.stderr, str(ex)
82 sys.exit(1)
84 interface_uri = model.canonical_iface_uri(interface_uri)
86 if options.resolve:
87 print interface_uri
88 sys.exit(0)
90 if options.manpage:
91 sels = helpers.ensure_cached(interface_uri)
92 if not sels:
93 # Cancelled by user
94 sys.exit(1)
96 selected_impl = sels.selections[interface_uri]
97 if selected_impl.id.startswith('/'):
98 impl_path = selected_impl.id
99 else:
100 from zeroinstall.injector.iface_cache import iface_cache
101 impl_path = iface_cache.stores.lookup(selected_impl.id)
103 if main is None:
104 main = selected_impl.main
105 if main is None:
106 print >>sys.stderr, "No main program for interface '%s'" % interface_uri
107 sys.exit(1)
109 # TODO: the feed should say where the man-page is, but for now we'll just search
110 # the whole implementation for one
112 prog_name = os.path.basename(main)
113 alias_name = os.path.basename(args[0])
115 assert impl_path
116 manpages = []
117 for root, dirs, files in os.walk(impl_path):
118 for f in files:
119 if f.endswith('.gz'):
120 manpage_file = f[:-3]
121 else:
122 manpage_file = f
123 if manpage_file.endswith('.1') or \
124 manpage_file.endswith('.6') or \
125 manpage_file.endswith('.8'):
126 manpage_prog = manpage_file[:-2]
127 if manpage_prog == prog_name or manpage_prog == alias_name:
128 os.execlp('man', 'man', os.path.join(root, f))
129 sys.exit(1)
130 else:
131 manpages.append((root, f))
133 print "No matching manpage was found for '%s' (%s)" % (alias_name, interface_uri)
134 if manpages:
135 print "These non-matching man-pages were found, however:"
136 for root, file in manpages:
137 print os.path.join(root, file)
138 sys.exit(1)
140 if len(args) == 1:
141 os.execlp('0launch', '0launch', '-gd', '--', interface_uri)
142 sys.exit(1)
144 try:
145 interface = model.Interface(interface_uri)
146 if not reader.update_from_cache(interface):
147 print >>sys.stderr, "Interface '%s' not currently in cache. Fetching..." % interface_uri
148 if os.spawnlp(os.P_WAIT, '0launch', '0launch', '-d', interface_uri):
149 raise model.SafeException("0launch failed")
150 if not reader.update_from_cache(interface):
151 raise model.SafeException("Interface still not in cache. Aborting.")
153 script = os.path.join(first_path, alias_prog)
154 if os.path.exists(script):
155 raise model.SafeException("File '%s' already exists. Delete it first." % script)
156 sys.exit(1)
157 except model.SafeException, ex:
158 print >>sys.stderr, ex
159 sys.exit(1)
161 wrapper = file(script, 'w')
162 alias.write_script(wrapper, interface_uri, main)
164 # Make new script executable
165 os.chmod(script, 0111 | os.fstat(wrapper.fileno()).st_mode)
166 wrapper.close()
168 print "Created script '%s'." % script
169 print "To edit policy: 0alias %s" % alias_prog
170 print "(note: some shells require you to type 'rehash' now)"