3 from optparse
import OptionParser
5 from zeroinstall
.injector
import reader
, model
6 from zeroinstall
import support
, alias
, helpers
7 from zeroinstall
.support
import basedir
9 def export(name
, value
):
10 """Try to guess the command to set an environment variable."""
11 shell
= os
.environ
.get('SHELL', '?')
13 return "setenv %s %s" % (name
, value
)
14 return "export %s=%s" % (name
, value
)
17 """Find the first writable path in : separated list."""
19 if os
.path
.realpath(path
).startswith(basedir
.xdg_cache_home
):
20 pass # print "Skipping cache", first_path
21 elif not os
.access(path
, os
.W_OK
):
22 pass # print "No access", first_path
30 # Do this here so we can include it in the help message.
31 # But, don't abort if there isn't one because we might
32 # be doing something else (e.g. --manpage)
33 first_path
= find_path(os
.environ
['PATH'].split(':'))
35 parser
= OptionParser(usage
="usage: %%prog [options] alias [interface [command]]\n\n"
36 "Creates a script in the first usable directory in $PATH\n"
37 "(%s) to run 'interface' unless overridden by --dir.\n"
38 "If no interface is given, edits the policy for an existing alias.\n"
39 "For interfaces providing more than one command, the desired command\n"
40 "may also be given." % first_path
)
41 parser
.add_option("-m", "--manpage", help="show the manual page for an existing alias", action
='store_true')
42 parser
.add_option("-r", "--resolve", help="show the URI for an alias", action
='store_true')
43 parser
.add_option("-V", "--version", help="display version information", action
='store_true')
44 parser
.add_option("-d", "--dir", help="install in DIR", dest
="user_path", metavar
="DIR")
45 parser
.disable_interspersed_args()
47 (options
, args
) = parser
.parse_args()
51 print "0alias (zero-install) " + zeroinstall
.version
52 print "Copyright (C) 2007 Thomas Leonard"
53 print "This program comes with ABSOLUTELY NO WARRANTY,"
54 print "to the extent permitted by law."
55 print "You may redistribute copies of this program"
56 print "under the terms of the GNU Lesser General Public License."
57 print "For more information about these matters, see the file named COPYING."
62 os
.execlp('man', 'man', *args
)
65 if len(args
) < 1 or len(args
) > 3:
68 alias_prog
, interface_uri
, main
= (list(args
) + [None, None])[:3]
70 if options
.resolve
or options
.manpage
:
71 if interface_uri
is not None:
76 first_path
= options
.user_path
77 if not os
.path
.isdir(first_path
):
78 print >>sys
.stderr
, "Directory '%s' does not exist." % first_path
81 if interface_uri
is None:
83 if not os
.path
.isabs(alias_prog
):
84 full_path
= support
.find_in_path(alias_prog
)
86 raise alias
.NotAnAliasScript("Not found in $PATH: " + alias_prog
)
88 full_path
= alias_prog
90 interface_uri
, main
= alias
.parse_script(full_path
)
91 except alias
.NotAnAliasScript
, ex
:
93 os
.execlp('man', 'man', *args
)
94 print >>sys
.stderr
, str(ex
)
97 interface_uri
= model
.canonical_iface_uri(interface_uri
)
104 sels
= helpers
.ensure_cached(interface_uri
)
109 selected_impl
= sels
.selections
[interface_uri
]
110 if selected_impl
.id.startswith('/'):
111 impl_path
= selected_impl
.id
113 from zeroinstall
.injector
.iface_cache
import iface_cache
114 impl_path
= iface_cache
.stores
.lookup(selected_impl
.id)
117 main
= selected_impl
.main
119 print >>sys
.stderr
, "No main program for interface '%s'" % interface_uri
122 # TODO: the feed should say where the man-page is, but for now we'll just search
123 # the whole implementation for one
125 prog_name
= os
.path
.basename(main
)
126 alias_name
= os
.path
.basename(args
[0])
130 for root
, dirs
, files
in os
.walk(impl_path
):
132 if f
.endswith('.gz'):
133 manpage_file
= f
[:-3]
136 if manpage_file
.endswith('.1') or \
137 manpage_file
.endswith('.6') or \
138 manpage_file
.endswith('.8'):
139 manpage_prog
= manpage_file
[:-2]
140 if manpage_prog
== prog_name
or manpage_prog
== alias_name
:
141 os
.execlp('man', 'man', os
.path
.join(root
, f
))
144 manpages
.append((root
, f
))
146 print "No matching manpage was found for '%s' (%s)" % (alias_name
, interface_uri
)
148 print "These non-matching man-pages were found, however:"
149 for root
, file in manpages
:
150 print os
.path
.join(root
, file)
153 if first_path
is None:
154 print >>sys
.stderr
, ("No writable non-cache directory in $PATH, which currently contains:\n\n%s\n\n"
155 "To create a directory for your scripts, use these commands:\n"
158 "or specify a writable path with --path"
159 % ('\n'.join(os
.environ
['PATH'].split(':')), export('PATH', '$HOME/bin:$PATH')))
163 os
.execlp('0launch', '0launch', '-gd', '--', interface_uri
)
167 interface
= model
.Interface(interface_uri
)
168 if not reader
.update_from_cache(interface
):
169 print >>sys
.stderr
, "Interface '%s' not currently in cache. Fetching..." % interface_uri
170 if os
.spawnlp(os
.P_WAIT
, '0launch', '0launch', '-d', interface_uri
):
171 raise model
.SafeException("0launch failed")
172 if not reader
.update_from_cache(interface
):
173 raise model
.SafeException("Interface still not in cache. Aborting.")
175 script
= os
.path
.join(first_path
, alias_prog
)
176 if os
.path
.exists(script
):
177 raise model
.SafeException("File '%s' already exists. Delete it first." % script
)
179 except model
.SafeException
, ex
:
180 print >>sys
.stderr
, ex
183 wrapper
= file(script
, 'w')
184 alias
.write_script(wrapper
, interface_uri
, main
)
186 # Make new script executable
187 os
.chmod(script
, 0111 | os
.fstat(wrapper
.fileno()).st_mode
)
190 print "Created script '%s'." % script
191 print "To edit policy: 0alias %s" % alias_prog
192 print "(note: some shells require you to type 'rehash' now)"