21
19
"""A GIT branch and repository format implementation for bzr."""
27
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "dulwich"))
29
from bzrlib import bzrdir
30
from bzrlib.foreign import ForeignVcs, VcsMappingRegistry, foreign_vcs_registry
31
from bzrlib.plugins.git.dir import LocalGitBzrDirFormat, RemoteGitBzrDirFormat
32
from bzrlib.transport import register_lazy_transport
33
from bzrlib.commands import Command, register_command
34
from bzrlib.option import Option
36
bzrdir.format_registry.register(
37
'git', LocalGitBzrDirFormat,
38
help='GIT repository.',
39
native=False, experimental=True,
22
from StringIO import StringIO
25
import stgit.git as git
42
bzrdir.BzrDirFormat.register_control_format(LocalGitBzrDirFormat)
43
bzrdir.BzrDirFormat.register_control_format(RemoteGitBzrDirFormat)
45
register_lazy_transport("git://", 'bzrlib.plugins.git.remote',
49
class ForeignGit(ForeignVcs):
53
git_mapping_registry = VcsMappingRegistry()
54
git_mapping_registry.register_lazy('git-experimental', "bzrlib.plugins.git.mapping",
55
"BzrGitMappingExperimental")
56
foreign_vcs_registry.register("git", ForeignGit(git_mapping_registry),
57
"Stupid content tracker")
60
class cmd_git_serve(Command):
61
"""Provide access to a Bazaar branch using the git protocol.
63
This command is experimental and doesn't do much yet.
67
help='serve contents of directory',
71
def run(self, directory=None):
72
from dulwich.server import TCPGitServer
73
from bzrlib.plugins.git.server import BzrBackend
74
from bzrlib.trace import warning
77
warning("server support in bzr-git is experimental.")
80
directory = os.getcwd()
82
backend = BzrBackend(directory)
84
server = TCPGitServer(backend, 'localhost')
85
server.serve_forever()
87
register_command(cmd_git_serve)
90
class cmd_git_import(Command):
91
"""Import all branches from a git repository.
95
takes_args = ["src_location", "dest_location"]
97
def run(self, src_location, dest_location):
98
from bzrlib.bzrdir import BzrDir, format_registry
99
from bzrlib.errors import NoRepositoryPresent, NotBranchError
100
from bzrlib.repository import Repository
101
source_repo = Repository.open(src_location)
102
format = format_registry.make_bzrdir('rich-root-pack')
104
target_bzrdir = BzrDir.open(dest_location)
105
except NotBranchError:
106
target_bzrdir = BzrDir.create(dest_location, format=format)
108
target_repo = target_bzrdir.open_repository()
109
except NoRepositoryPresent:
110
target_repo = target_bzrdir.create_repository(shared=True)
112
target_repo.fetch(source_repo)
113
for name, ref in source_repo._git.heads().iteritems():
114
head_loc = os.path.join(dest_location, name)
116
head_bzrdir = BzrDir.open(head_loc)
117
except NotBranchError:
118
head_bzrdir = BzrDir.create(head_loc, format=format)
120
head_branch = head_bzrdir.open_branch()
121
except NotBranchError:
122
head_branch = head_bzrdir.create_branch()
123
head_branch.generate_revision_history(source_repo.get_mapping().revision_id_foreign_to_bzr(ref))
126
register_command(cmd_git_import)
35
from bzrlib.decorators import *
38
import bzrlib.errors as errors
39
import bzrlib.repository
40
from bzrlib.revision import Revision
43
class GitInventory(object):
45
def __init__(self, revision_id):
47
self.root = GitEntry('', 'directory', revision_id)
48
self.entries[''] = self.root
50
def __getitem__(self, key):
51
return self.entries[key]
53
def iter_entries(self):
54
return iter(sorted(self.entries.items()))
56
def iter_entries_by_dir(self):
57
return self.iter_entries()
60
return len(self.entries)
63
class GitEntry(object):
65
def __init__(self, path, kind, revision, text_sha1=None, executable=False,
70
self.executable = executable
71
self.name = osutils.basename(path)
75
self.parent_id = osutils.dirname(path)
76
self.revision = revision
77
self.symlink_target = None
78
self.text_sha1 = text_sha1
82
return "GitEntry(%r, %r, %r, %r)" % (self.path, self.kind,
83
self.revision, self.parent_id)
86
class GitModel(object):
87
"""API that follows GIT model closely"""
89
def __init__(self, git_dir):
90
self.git_dir = git_dir
92
def git_command(self, command, args):
93
args = ' '.join("'%s'" % arg for arg in args)
94
return 'git --git-dir=%s %s %s' % (self.git_dir, command, args)
96
def git_lines(self, command, args):
97
return stgit.git._output_lines(self.git_command(command, args))
99
def git_line(self, command, args):
100
return stgit.git._output_one_line(self.git_command(command, args))
102
def cat_file(self, type, object_id, pretty=False):
108
args.append(object_id)
109
return self.git_lines('cat-file', args)
111
def rev_list(self, heads, max_count=None, header=False):
113
if max_count is not None:
114
args.append('--max-count=%d' % max_count)
115
if header is not False:
116
args.append('--header')
121
return self.git_lines('rev-list', args)
123
def rev_parse(self, git_id):
124
args = ['--verify', git_id]
125
return self.git_line('rev-parse', args)
128
return self.rev_parse('HEAD')
130
def ancestor_lines(self, revisions):
132
for line in self.rev_list(revisions, header=True):
133
if line.startswith('\x00'):
135
revision_lines = [line[1:].decode('latin-1')]
137
revision_lines.append(line.decode('latin-1'))
138
assert revision_lines == ['']
140
def get_inventory(self, tree_id):
141
for line in self.cat_file('tree', tree_id, True):
142
sections = line.split(' ', 2)
143
obj_id, name = sections[2].split('\t', 1)
144
name = name.rstrip('\n')
145
if name.startswith('"'):
146
name = name[1:-1].decode('string_escape').decode('utf-8')
147
yield (sections[0], sections[1], obj_id, name)
150
class cmd_test_git(commands.Command):
153
from bzrlib.tests import selftest
129
155
def test_suite():
130
156
from bzrlib.plugins.git import tests
131
157
return tests.test_suite()