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>
 
 
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
 
 
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.
 
 
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,
 
 
22
from commit import Commit
 
 
23
from errors import MissingCommitError
 
 
24
from objects import (ShaFile,
 
 
36
    def __init__(self, name, ref):
 
 
38
        self.commit = Commit(ref)
 
 
43
  ref_locs = ['', 'refs', 'refs/tags', 'refs/heads', 'refs/remotes']
 
 
45
  def __init__(self, root):
 
 
46
    controldir = os.path.join(root, ".git")
 
 
47
    if os.path.exists(os.path.join(controldir, "objects")):
 
 
49
      self._basedir = controldir
 
 
53
    self.path = controldir
 
 
54
    self.tags = [Tag(name, ref) for name, ref in self.get_tags().items()]
 
 
60
    return os.path.join(self.basedir(), objectdir)
 
 
62
  def _get_ref(self, file):
 
 
66
      if contents.startswith(symref):
 
 
67
        ref = contents[len(symref):]
 
 
71
      assert len(contents) == 41, 'Invalid ref'
 
 
77
    for dir in self.ref_locs:
 
 
78
      file = os.path.join(self.basedir(), dir, name)
 
 
79
      if os.path.exists(file):
 
 
80
        return self._get_ref(file)
 
 
84
    for name in os.listdir(os.path.join(self.basedir(), 'refs', 'tags')):
 
 
85
      ret[name] = self._get_ref(os.path.join(self.basedir(), 'refs', 'tags', name))
 
 
90
    for name in os.listdir(os.path.join(self.basedir(), 'refs', 'heads')):
 
 
91
      ret[name] = self._get_ref(os.path.join(self.basedir(), 'refs', 'heads', name))
 
 
95
    return self.ref('HEAD')
 
 
97
  def _get_object(self, sha, cls):
 
 
98
    assert len(sha) == 40, "Incorrect length sha: %s" % str(sha)
 
 
101
    path = os.path.join(self.object_dir(), dir, file)
 
 
102
    if not os.path.exists(path):
 
 
103
      # Should this raise instead?
 
 
105
    return cls.from_file(path)
 
 
107
  def get_object(self, sha):
 
 
108
    return self._get_object(sha, ShaFile)
 
 
110
  def commit(self, sha):
 
 
111
    return self._get_object(sha, Commit)
 
 
113
  def get_tree(self, sha):
 
 
114
    return self._get_object(sha, Tree)
 
 
116
  def get_blob(self, sha):
 
 
117
    return self._get_object(sha, Blob)
 
 
119
  def revision_history(self, head):
 
 
120
    """Returns a list of the commits reachable from head.
 
 
122
    Returns a list of commit objects. the first of which will be the commit
 
 
123
    of head, then following theat will be the parents.
 
 
125
    Raises NotCommitError if any no commits are referenced, including if the
 
 
126
    head parameter isn't the sha of a commit.
 
 
128
    XXX: work out how to handle merges.
 
 
130
    # We build the list backwards, as parents are more likely to be older
 
 
132
    pending_commits = [head]
 
 
134
    while pending_commits != []:
 
 
135
      head = pending_commits.pop(0)
 
 
136
      commit = self.commit(head)
 
 
138
        raise MissingCommitError(head)
 
 
139
      if commit in history:
 
 
142
      for known_commit in history:
 
 
143
        if known_commit.commit_time() > commit.commit_time():
 
 
146
      history.insert(i, commit)
 
 
147
      parents = commit.parents()
 
 
148
      pending_commits += parents
 
 
153
  def init_bare(cls, path, mkdir=True):
 
 
154
      for d in [["objects"], 
 
 
163
          os.mkdir(os.path.join(path, *d))
 
 
164
      open(os.path.join(path, 'HEAD'), 'w').write("ref: refs/heads/master\n")
 
 
165
      open(os.path.join(path, 'description'), 'w').write("Unnamed repository")
 
 
166
      open(os.path.join(path, 'info', 'excludes'), 'w').write("")