/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 dulwich/dulwich/repo.py

  • Committer: John Arbash Meinel
  • Date: 2006-09-05 13:57:30 UTC
  • mto: This revision was merged to the branch mainline in revision 1990.
  • Revision ID: john@arbash-meinel.com-20060905135730-d51221405aa03eb2
Create an osutils helper function for modifying the environment

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# repo.py -- For dealing wih git repositories.
2
 
# Copyright (C) 2007 James Westby <jw+debian@jameswestby.net>
3
 
# Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
4
 
5
 
# This program is free software; you can redistribute it and/or
6
 
# modify it under the terms of the GNU General Public License
7
 
# as published by the Free Software Foundation; version 2
8
 
# of the License.
9
 
10
 
# This program is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
# GNU General Public License for more details.
14
 
15
 
# You should have received a copy of the GNU General Public License
16
 
# along with this program; if not, write to the Free Software
17
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 
# MA  02110-1301, USA.
19
 
 
20
 
import os
21
 
 
22
 
from commit import Commit
23
 
from errors import MissingCommitError
24
 
from objects import (ShaFile,
25
 
                     Commit,
26
 
                     Tree,
27
 
                     Blob,
28
 
                     )
29
 
from pack import load_packs
30
 
 
31
 
OBJECTDIR = 'objects'
32
 
PACKDIR = 'pack'
33
 
SYMREF = 'ref: '
34
 
 
35
 
 
36
 
class Tag(object):
37
 
 
38
 
    def __init__(self, name, ref):
39
 
        self.name = name
40
 
        self.ref = ref
41
 
 
42
 
 
43
 
class Repo(object):
44
 
 
45
 
  ref_locs = ['', 'refs', 'refs/tags', 'refs/heads', 'refs/remotes']
46
 
 
47
 
  def __init__(self, root):
48
 
    controldir = os.path.join(root, ".git")
49
 
    if os.path.exists(os.path.join(controldir, "objects")):
50
 
      self.bare = False
51
 
      self._basedir = controldir
52
 
    else:
53
 
      self.bare = True
54
 
      self._basedir = root
55
 
    self.path = controldir
56
 
    self.tags = [Tag(name, ref) for name, ref in self.get_tags().items()]
57
 
    self._packs = None
58
 
 
59
 
  def basedir(self):
60
 
    return self._basedir
61
 
 
62
 
  def object_dir(self):
63
 
    return os.path.join(self.basedir(), OBJECTDIR)
64
 
 
65
 
  def pack_dir(self):
66
 
    return os.path.join(self.object_dir(), PACKDIR)
67
 
 
68
 
  def _get_packs(self):
69
 
    if self._packs is None:
70
 
        self._packs = list(load_packs(self.pack_dir()))
71
 
    return self._packs
72
 
 
73
 
  def _get_ref(self, file):
74
 
    f = open(file, 'rb')
75
 
    try:
76
 
      contents = f.read()
77
 
      if contents.startswith(SYMREF):
78
 
        ref = contents[len(SYMREF):]
79
 
        if ref[-1] == '\n':
80
 
          ref = ref[:-1]
81
 
        return self.ref(ref)
82
 
      assert len(contents) == 41, 'Invalid ref'
83
 
      return contents[:-1]
84
 
    finally:
85
 
      f.close()
86
 
 
87
 
  def ref(self, name):
88
 
    for dir in self.ref_locs:
89
 
      file = os.path.join(self.basedir(), dir, name)
90
 
      if os.path.exists(file):
91
 
        return self._get_ref(file)
92
 
 
93
 
  def get_tags(self):
94
 
    ret = {}
95
 
    for root, dirs, files in os.walk(os.path.join(self.basedir(), 'refs', 'tags')):
96
 
      for name in files:
97
 
        ret[name] = self._get_ref(os.path.join(root, name))
98
 
    return ret
99
 
 
100
 
  def heads(self):
101
 
    ret = {}
102
 
    for root, dirs, files in os.walk(os.path.join(self.basedir(), 'refs', 'heads')):
103
 
      for name in files:
104
 
        ret[name] = self._get_ref(os.path.join(root, name))
105
 
    return ret
106
 
 
107
 
  def head(self):
108
 
    return self.ref('HEAD')
109
 
 
110
 
  def _get_object(self, sha, cls):
111
 
    assert len(sha) == 40, "Incorrect length sha: %s" % str(sha)
112
 
    dir = sha[:2]
113
 
    file = sha[2:]
114
 
    # Check from object dir
115
 
    path = os.path.join(self.object_dir(), dir, file)
116
 
    if os.path.exists(path):
117
 
      return cls.from_file(path)
118
 
    # Check from packs
119
 
    for pack in self._get_packs():
120
 
        if sha in pack:
121
 
            return pack[sha]
122
 
    # Should this raise instead?
123
 
    return None
124
 
 
125
 
  def get_object(self, sha):
126
 
    return self._get_object(sha, ShaFile)
127
 
 
128
 
  def commit(self, sha):
129
 
    return self._get_object(sha, Commit)
130
 
 
131
 
  def get_tree(self, sha):
132
 
    return self._get_object(sha, Tree)
133
 
 
134
 
  def get_blob(self, sha):
135
 
    return self._get_object(sha, Blob)
136
 
 
137
 
  def revision_history(self, head):
138
 
    """Returns a list of the commits reachable from head.
139
 
 
140
 
    Returns a list of commit objects. the first of which will be the commit
141
 
    of head, then following theat will be the parents.
142
 
 
143
 
    Raises NotCommitError if any no commits are referenced, including if the
144
 
    head parameter isn't the sha of a commit.
145
 
 
146
 
    XXX: work out how to handle merges.
147
 
    """
148
 
    # We build the list backwards, as parents are more likely to be older
149
 
    # than children
150
 
    pending_commits = [head]
151
 
    history = []
152
 
    while pending_commits != []:
153
 
      head = pending_commits.pop(0)
154
 
      commit = self.commit(head)
155
 
      if commit is None:
156
 
        raise MissingCommitError(head)
157
 
      if commit in history:
158
 
        continue
159
 
      i = 0
160
 
      for known_commit in history:
161
 
        if known_commit.commit_time() > commit.commit_time():
162
 
          break
163
 
        i += 1
164
 
      history.insert(i, commit)
165
 
      parents = commit.parents()
166
 
      pending_commits += parents
167
 
    history.reverse()
168
 
    return history
169
 
 
170
 
  @classmethod
171
 
  def init_bare(cls, path, mkdir=True):
172
 
      for d in [["objects"], 
173
 
                ["objects", "info"], 
174
 
                ["objects", "pack"],
175
 
                ["branches"],
176
 
                ["refs"],
177
 
                ["refs", "tags"],
178
 
                ["refs", "heads"],
179
 
                ["hooks"],
180
 
                ["info"]]:
181
 
          os.mkdir(os.path.join(path, *d))
182
 
      open(os.path.join(path, 'HEAD'), 'w').write("ref: refs/heads/master\n")
183
 
      open(os.path.join(path, 'description'), 'w').write("Unnamed repository")
184
 
      open(os.path.join(path, 'info', 'excludes'), 'w').write("")
185
 
 
186
 
  create = init_bare
187