add git-remote-hg
[git/srabbelier.git] / git-remote-hg.py
blobf05ed2cd26e2b29900cb570f9fbab3e4ebaa5a03
1 #!/usr/bin/env python
3 import sys
4 import os
5 sys.path.insert(0, os.getenv("GITPYTHONLIB","."))
7 from git_remote_helpers.util import die, debug, warn
8 from git_remote_helpers.hg.hg import GitHg
9 from git_remote_helpers.hg.export import GitExporter
10 from git_remote_helpers.hg.non_local import NonLocalHg
12 def get_repo(alias, url):
13 """Returns a hg.repository object initialized for usage.
14 """
16 try:
17 from mercurial import hg, ui
18 except ImportError:
19 die("Mercurial python libraries not installed")
21 ui = ui.ui()
22 source, revs = hg.parseurl(ui.expandpath(url), ['tip'])
23 repo = hg.repository(ui, source)
25 prefix = 'refs/hg/%s/' % alias
26 debug("prefix: '%s'", prefix)
28 repo.hg = hg
29 repo.gitdir = ""
30 repo.alias = alias
31 repo.prefix = prefix
32 repo.revs = revs
34 repo.git_hg = GitHg(warn)
35 exporter = GitExporter(repo.git_hg, repo, 'hg.marks', 'git.marks', prefix)
36 non_local = NonLocalHg(repo, alias)
38 repo.exporter = exporter
39 repo.non_local = non_local
41 return repo
44 def local_repo(repo, path):
45 """Returns a hg.repository object initalized for usage.
46 """
48 local = repo.hg.repository(repo.ui, path)
50 local.git_hg = repo.git_hg
51 local.non_local = None
52 local.hg = repo.hg
53 local.gitdir = repo.gitdir
54 local.alias = repo.alias
55 local.prefix = repo.prefix
56 local.revs = repo.revs
57 local.exporter = GitExporter(repo.git_hg, local, 'hg.marks', 'git.marks', repo.prefix)
59 return local
62 def do_capabilities(repo, args):
63 """Prints the supported capabilities.
64 """
66 print "import"
67 print "gitdir"
68 print "refspec refs/heads/*:%s*" % repo.prefix
70 print # end capabilities
73 def do_list(repo, args):
74 """Lists all known references.
75 """
77 for ref in repo.revs:
78 debug("? refs/heads/%s", ref)
79 print "? refs/heads/%s" % ref
81 debug("@refs/heads/tip HEAD")
82 print "@refs/heads/tip HEAD"
84 print # end list
87 def get_branch(ref):
88 if not ref.startswith("refs/heads/"):
89 die("Ref should start with 'refs/heads/'")
91 splitref = ref.split('/')
93 if len(splitref) != 3:
94 die("Cannot parse ref, need 3 slashes")
96 branch = splitref[2]
98 return branch
101 def update_local_repo(repo):
105 if repo.local():
106 return repo
108 path = repo.non_local.clone(repo.gitdir)
109 repo.non_local.update(repo.gitdir)
110 repo = local_repo(repo, path)
111 return repo
114 def do_import(repo, args):
118 if len(args) != 1:
119 die("Import needs exactly one ref")
121 if not repo.gitdir:
122 die("Need gitdir to import")
124 if args[0] == 'HEAD':
125 branch = 'tip'
126 else:
127 branch = get_branch(args[0])
129 repo = update_local_repo(repo)
130 repo.exporter.setup(True, repo.gitdir, True, True)
132 repo.exporter.export_repo()
133 repo.exporter.export_branch('tip', 'tip')
135 repo.exporter.write_marks(repo.gitdir)
137 def do_gitdir(repo, args):
141 if not args:
142 die("gitdir needs an argument")
144 repo.gitdir = ' '.join(args)
147 COMMANDS = {
148 'capabilities': do_capabilities,
149 'list': do_list,
150 'import': do_import,
151 'gitdir': do_gitdir,
155 def sanitize(value):
156 if value.startswith('hg::'):
157 value = value[4:]
159 return value
162 def read_one_line(repo):
163 line = sys.stdin.readline()
165 cmdline = line.strip().split()
167 if not cmdline:
168 return False # Blank line means we're about to quit
170 cmd = cmdline.pop(0)
171 debug("Got command '%s' with args '%s'", cmd, ' '.join(cmdline))
173 if cmd not in COMMANDS:
174 die("Unknown command, %s", cmd)
176 func = COMMANDS[cmd]
177 func(repo, cmdline)
178 sys.stdout.flush()
180 return True
183 def main(args):
184 if len(args) != 3:
185 die("Expecting exactly three arguments.")
186 sys.exit(1)
188 if os.getenv("GIT_DEBUG_HG"):
189 import git_remote_helpers.util
190 git_remote_helpers.util.DEBUG = True
192 alias = sanitize(args[1])
193 url = sanitize(args[2])
195 if not alias.isalnum():
196 warn("non-alnum alias '%s'", alias)
197 alias = "tmp"
199 args[1] = alias
200 args[2] = url
202 repo = get_repo(alias, url)
204 debug("Got arguments %s", args[1:])
206 more = True
208 while (more):
209 more = read_one_line(repo)
211 if __name__ == '__main__':
212 sys.exit(main(sys.argv))