~ubuntu-branches/debian/sid/git-cola/sid

« back to all changes in this revision

Viewing changes to cola/git.py

  • Committer: Bazaar Package Importer
  • Author(s): Iulian Udrea
  • Date: 2010-06-15 19:17:53 UTC
  • mfrom: (1.3.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20100615191753-v538sje6miaikuqm
Tags: 1.4.2.3-1
 
* New upstream version.
* debian/control: single line synopsis: gui -> GUI.  Closes: #585947.
* Bump Standards-Version to 3.9.1 (no changes required).

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
import os
9
9
import sys
10
10
import errno
 
11
import commands
11
12
import subprocess
12
13
import threading
13
14
 
15
16
from cola import core
16
17
from cola import errors
17
18
from cola import signals
 
19
from cola.decorators import memoize
18
20
 
19
21
cmdlock = threading.Lock()
20
22
 
21
23
 
 
24
@memoize
 
25
def instance():
 
26
    """Return the GitCola singleton"""
 
27
    return GitCola()
 
28
 
 
29
 
22
30
def dashify(string):
23
31
    return string.replace('_', '-')
24
32
 
37
45
if sys.platform == 'win32':
38
46
    extra = {'shell': True}
39
47
 
 
48
 
40
49
class Git(object):
41
50
    """
42
51
    The Git class manages communication with the Git binary
152
161
                print "%s -> %d" % (command, status)
153
162
 
154
163
        if GIT_COLA_TRACE:
155
 
            msg = 'trace: %s' % ' '.join(map(shell_quote, command))
 
164
            msg = 'trace: %s' % ' '.join(map(commands.mkarg, command))
156
165
            cola.notifier().broadcast(signals.log_cmd, status, msg)
157
166
 
158
167
        # Allow access to the command's status code
235
244
    return cmd_arg.replace('^', '^^')
236
245
 
237
246
 
238
 
def shell_quote(*strings):
239
 
    """
240
 
    Quote strings so that they can be suitably martialled
241
 
    off to the shell.  This method supports POSIX sh syntax.
242
 
    This is crucial to properly handle command line arguments
243
 
    with spaces, quotes, double-quotes, etc. on darwin/win32...
244
 
    """
245
 
 
246
 
    regex = re.compile('[^\w!%+,\-./:@^]')
247
 
    quote_regex = re.compile("((?:'\\''){2,})")
248
 
 
249
 
    ret = []
250
 
    for s in strings:
251
 
        if not s:
252
 
            continue
253
 
 
254
 
        if '\x00' in s:
255
 
            raise ValueError('No way to quote strings '
256
 
                             'containing null(\\000) bytes')
257
 
 
258
 
        # = does need quoting else in command position it's a
259
 
        # program-local environment setting
260
 
        match = regex.search(s)
261
 
        if match and '=' not in s:
262
 
            # ' -> '\''
263
 
            s = s.replace("'", "'\\''")
264
 
 
265
 
            # make multiple ' in a row look simpler
266
 
            # '\'''\'''\'' -> '"'''"'
267
 
            quote_match = quote_regex.match(s)
268
 
            if quote_match:
269
 
                quotes = match.group(1)
270
 
                s.replace(quotes, ("'" *(len(quotes)/4)) + "\"'")
271
 
 
272
 
            s = "'%s'" % s
273
 
            if s.startswith("''"):
274
 
                s = s[2:]
275
 
 
276
 
            if s.endswith("''"):
277
 
                s = s[:-2]
278
 
        ret.append(s)
279
 
    return ' '.join(ret)
 
247
class GitCola(Git):
 
248
    """
 
249
    Subclass Git to provide search-for-git-dir
 
250
 
 
251
    """
 
252
    def __init__(self):
 
253
        Git.__init__(self)
 
254
        self.load_worktree(os.getcwd())
 
255
 
 
256
    def load_worktree(self, path):
 
257
        self._git_dir = path
 
258
        self._worktree = None
 
259
        self.worktree()
 
260
 
 
261
    def worktree(self):
 
262
        if self._worktree:
 
263
            return self._worktree
 
264
        self.git_dir()
 
265
        if self._git_dir:
 
266
            curdir = self._git_dir
 
267
        else:
 
268
            curdir = os.getcwd()
 
269
 
 
270
        if self._is_git_dir(os.path.join(curdir, '.git')):
 
271
            return curdir
 
272
 
 
273
        # Handle bare repositories
 
274
        if (len(os.path.basename(curdir)) > 4
 
275
                and curdir.endswith('.git')):
 
276
            return curdir
 
277
        if 'GIT_WORK_TREE' in os.environ:
 
278
            self._worktree = os.getenv('GIT_WORK_TREE')
 
279
        if not self._worktree or not os.path.isdir(self._worktree):
 
280
            if self._git_dir:
 
281
                gitparent = os.path.join(os.path.abspath(self._git_dir), '..')
 
282
                self._worktree = os.path.abspath(gitparent)
 
283
                self.set_cwd(self._worktree)
 
284
        return self._worktree
 
285
 
 
286
    def is_valid(self):
 
287
        return self._git_dir and self._is_git_dir(self._git_dir)
 
288
 
 
289
    def git_path(self, *paths):
 
290
        return os.path.join(self.git_dir(), *paths)
 
291
 
 
292
    def git_dir(self):
 
293
        if self.is_valid():
 
294
            return self._git_dir
 
295
        if 'GIT_DIR' in os.environ:
 
296
            self._git_dir = os.getenv('GIT_DIR')
 
297
        if self._git_dir:
 
298
            curpath = os.path.abspath(self._git_dir)
 
299
        else:
 
300
            curpath = os.path.abspath(os.getcwd())
 
301
        # Search for a .git directory
 
302
        while curpath:
 
303
            if self._is_git_dir(curpath):
 
304
                self._git_dir = curpath
 
305
                break
 
306
            gitpath = os.path.join(curpath, '.git')
 
307
            if self._is_git_dir(gitpath):
 
308
                self._git_dir = gitpath
 
309
                break
 
310
            curpath, dummy = os.path.split(curpath)
 
311
            if not dummy:
 
312
                break
 
313
        return self._git_dir
 
314
 
 
315
    def _is_git_dir(self, d):
 
316
        """From git's setup.c:is_git_directory()."""
 
317
        if (os.path.isdir(d)
 
318
                and os.path.isdir(os.path.join(d, 'objects'))
 
319
                and os.path.isdir(os.path.join(d, 'refs'))):
 
320
            headref = os.path.join(d, 'HEAD')
 
321
            return (os.path.isfile(headref)
 
322
                    or (os.path.islink(headref)
 
323
                    and os.readlink(headref).startswith('refs')))
 
324
        return False