/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to model.py

  • Committer: Robert Collins
  • Date: 2010-05-06 07:48:22 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506074822-0bsgf2j4h8jx0xkk
Added ``bzrlib.tests.matchers`` as a place to put matchers, along with
our first in-tree matcher. See the module docstring for details.
(Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
"""The model for interacting with the git process, etc."""
18
 
 
19
 
import os
20
 
import subprocess
21
 
 
22
 
from bzrlib.plugins.git import errors
23
 
 
24
 
 
25
 
class GitModel(object):
26
 
    """API that follows GIT model closely"""
27
 
 
28
 
    def __init__(self, git_dir):
29
 
        self.git_dir = git_dir
30
 
 
31
 
    def git_command(self, command, args):
32
 
        return ['git', command] + args
33
 
 
34
 
    def git_lines(self, command, args):
35
 
        cmd = self.git_command(command, args)
36
 
        env = os.environ.copy()
37
 
        env['GIT_DIR'] = self.git_dir
38
 
        p = subprocess.Popen(cmd,
39
 
                             stdout=subprocess.PIPE,
40
 
                             stderr=subprocess.PIPE,
41
 
                             env=env)
42
 
        lines = p.stdout.readlines()
43
 
        if p.wait() != 0:
44
 
            raise errors.GitCommandError(cmd, p.returncode,
45
 
                                         p.stderr.read().strip())
46
 
        return lines
47
 
 
48
 
    def git_line(self, command, args):
49
 
        lines = self.git_lines(command, args)
50
 
        return lines[0]
51
 
 
52
 
    def cat_file(self, type, object_id, pretty=False):
53
 
        args = []
54
 
        if pretty:
55
 
            args.append('-p')
56
 
        else:
57
 
            args.append(type)
58
 
        args.append(object_id)
59
 
        return self.git_lines('cat-file', args)
60
 
 
61
 
    def rev_list(self, heads, max_count=None, header=False, parents=False,
62
 
                 topo_order=False, paths=None):
63
 
        args = []
64
 
        if max_count is not None:
65
 
            args.append('--max-count=%d' % max_count)
66
 
        if header:
67
 
            args.append('--header')
68
 
        if parents:
69
 
            args.append('--parents')
70
 
        if topo_order:
71
 
            args.append('--topo-order')
72
 
        if heads is None:
73
 
            args.append('--all')
74
 
        else:
75
 
            args.extend(heads)
76
 
        if paths is not None:
77
 
            args.append('--')
78
 
            args.extend(paths)
79
 
        return self.git_lines('rev-list', args)
80
 
 
81
 
    def rev_parse(self, git_id):
82
 
        args = ['--verify', git_id]
83
 
        return self.git_line('rev-parse', args).strip()
84
 
 
85
 
    def get_head(self):
86
 
        try:
87
 
            return self.rev_parse('HEAD')
88
 
        except errors.GitCommandError, e:
89
 
            # Most likely, this is a null branch, so treat it as such
90
 
            if e.stderr == 'fatal: Needed a single revision':
91
 
                return None
92
 
            raise
93
 
 
94
 
    def get_revision_graph(self, revisions):
95
 
        ancestors = {}
96
 
        for line in self.rev_list(revisions, parents=True):
97
 
            entries = line.split()
98
 
            ancestors[entries[0]] = entries[1:]
99
 
        return ancestors
100
 
 
101
 
    def get_ancestry(self, revisions):
102
 
        args = ['--topo-order', '--reverse'] + revisions
103
 
        return [line[:-1] for line in self.git_lines('rev-list', args)]
104
 
 
105
 
    def ancestor_lines(self, revisions):
106
 
        revision_lines = []
107
 
        for line in self.rev_list(revisions, header=True):
108
 
            if line.startswith('\x00'):
109
 
                yield revision_lines
110
 
                revision_lines = [line[1:].decode('latin-1')]
111
 
            else:
112
 
                revision_lines.append(line.decode('latin-1'))
113
 
        assert revision_lines == ['']
114
 
 
115
 
    def get_inventory(self, tree_id):
116
 
        for line in self.git_lines('ls-tree', ['-r', '-t', tree_id]):
117
 
            # Ideally, we would use -z so we would not have to handle escaped
118
 
            # file names. But then we could not use readlines() to split the
119
 
            # data as it is read.
120
 
            permissions, type, hash_and_path = line.split(' ', 2)
121
 
            hash, name = hash_and_path.split('\t', 1)
122
 
            name = name[:-1] # strip trailing newline
123
 
            if name.startswith('"'):
124
 
                name = name[1:-1].decode('string_escape')
125
 
            name = name.decode('utf-8')
126
 
            yield permissions, type, hash, name