1 # Copyright (c) 2008 David Aguilar
2 """This module provides miscellaneous utility functions."""
14 from cStringIO
import StringIO
18 from cola
import resources
19 from cola
.git
import shell_quote
21 KNOWN_FILE_MIME_TYPES
= {
24 'python': 'script.png',
26 'shell': 'script.png',
28 'octet': 'binary.png',
31 KNOWN_FILE_EXTENSION
= {
32 '.java': 'script.png',
33 '.groovy': 'script.png',
41 def add_parents(path_entry_set
):
42 """Iterate over each item in the set and add its parent directories."""
43 for path
in list(path_entry_set
):
45 path
= path
.replace('//', '/')
46 if path
not in path_entry_set
:
47 path_entry_set
.add(path
)
49 parent_dir
= dirname(path
)
50 while parent_dir
and parent_dir
not in path_entry_set
:
51 path_entry_set
.add(parent_dir
)
52 parent_dir
= dirname(parent_dir
)
58 Run arguments as a command and return output.
60 >>> run_cmd(["echo", "hello", "world"])
64 return git
.Git
.execute(command
)
67 def qm_for_locale(locale
):
68 """Returns the .qm file for a particular $LANG values."""
69 regex
= re
.compile(r
'([^\.])+\..*$')
70 match
= regex
.match(locale
)
72 locale
= match
.group(1)
73 return resources
.qm(locale
.split('_')[0])
76 def ident_file_type(filename
):
77 """Returns an icon based on the contents of filename."""
78 if os
.path
.exists(filename
):
79 filemimetype
= mimetypes
.guess_type(filename
)
80 if filemimetype
[0] != None:
81 for filetype
, iconname
in KNOWN_FILE_MIME_TYPES
.iteritems():
82 if filetype
in filemimetype
[0].lower():
84 filename
= filename
.lower()
85 for fileext
, iconname
in KNOWN_FILE_EXTENSION
.iteritems():
86 if filename
.endswith(fileext
):
91 # Fallback for modified files of an unknown type
95 def file_icon(filename
):
97 Returns the full path to an icon file corresponding to
100 return resources
.icon(ident_file_type(filename
))
104 """Launches a command in the background."""
105 args
= tuple([core
.encode(a
) for a
in args
])
106 if os
.name
in ('nt', 'dos'):
107 for path
in os
.environ
['PATH'].split(os
.pathsep
):
108 filenames
= (os
.path
.join(path
, args
[0]),
109 os
.path
.join(path
, args
[0]) + ".exe")
110 for filename
in filenames
:
111 if os
.path
.exists(filename
):
113 return os
.spawnv(os
.P_NOWAIT
, filename
, args
)
116 raise IOError('cannot find executable: %s' % args
[0])
118 argv
= map(shell_quote
, args
)
119 return os
.system(' '.join(argv
) + '&')
123 """Subtracts list b from list a and returns the resulting list."""
124 # conceptually, c = a - b
133 def grep(pattern
, items
, squash
=True):
134 """Greps a list for items that match a pattern and return a list of
135 matching items. If only one item matches, return just that item.
137 isdict
= type(items
) is dict
138 if pattern
in __grep_cache
:
139 regex
= __grep_cache
[pattern
]
141 regex
= __grep_cache
[pattern
] = re
.compile(pattern
)
145 match
= regex
.match(item
)
148 groups
= match
.groups()
150 subitems
= match
.group(0)
155 subitems
= list(groups
)
157 matchdict
[item
] = items
[item
]
159 matched
.append(subitems
)
164 if squash
and len(matched
) == 1:
172 An os.path.basename() implementation that always uses '/'
174 Avoid os.path.basename because git's output always
175 uses '/' regardless of platform.
178 return path
.rsplit('/', 1)[-1]
183 An os.path.dirname() implementation that always uses '/'
185 Avoid os.path.dirname because git's output always
186 uses '/' regardless of platform.
190 path
= path
.replace('//', '/')
191 path_dirname
= path
.rsplit('/', 1)[0]
192 if path_dirname
== path
:
194 return path
.rsplit('/', 1)[0]
198 """Slurps a filepath into a string."""
200 slushy
= core
.read_nointr(fh
)
202 return core
.decode(slushy
)
205 def write(path
, contents
):
206 """Writes a string to a file."""
208 core
.write_nointr(fh
, core
.encode(contents
))
211 def strip_prefix(prefix
, string
):
212 """Return string, without the prefix. Blow up if string doesn't
213 start with prefix."""
214 assert string
.startswith(prefix
)
215 return string
[len(prefix
):]
218 """Removes shell metacharacters from a string."""
219 for c
in """ \t!@#$%^&*()\\;,<>"'[]{}~|""":
220 s
= s
.replace(c
, '_')
224 """Is this a linux machine?"""
227 return platform
.system() == 'Linux'
229 if e
.errno
== errno
.EINTR
:
235 return os
.path
.exists('/usr/bin/apt-get')
239 """Return True on OSX."""
242 p
= platform
.platform()
245 if e
.errno
== errno
.EINTR
:
249 return 'macintosh' in p
or 'darwin' in p
253 """Is it windows or mac? (e.g. is running git-mergetool non-trivial?)"""
258 return platform
.system() == 'Windows'
260 if e
.errno
== errno
.EINTR
:
266 """Return a cheap md5 hexdigest for a path."""
267 contents
= slurp(path
)
268 md5
= hashlib
.new('md5')
270 return md5
.hexdigest()
273 def quote_repopath(repopath
):
274 """Quote a path for nt/dos only."""
275 if os
.name
in ('nt', 'dos'):
276 repopath
= '"%s"' % repopath