]>
Commit | Line | Data |
---|---|---|
7aeaa2fc SR |
1 | #!/usr/bin/env python |
2 | ||
3 | import hashlib | |
4 | import sys | |
5 | ||
6 | from git_remote_helpers.util import die, debug, warn | |
7 | from git_remote_helpers.git.repo import GitRepo | |
8 | from git_remote_helpers.git.exporter import GitExporter | |
9 | from git_remote_helpers.git.importer import GitImporter | |
10 | from git_remote_helpers.git.non_local import NonLocalGit | |
11 | ||
12 | def get_repo(alias, url): | |
13 | """Returns a git repository object initialized for usage. | |
14 | """ | |
15 | ||
16 | repo = GitRepo(url) | |
17 | repo.get_revs() | |
18 | repo.get_head() | |
19 | ||
20 | hasher = hashlib.sha1() | |
21 | hasher.update(repo.path) | |
22 | repo.hash = hasher.hexdigest() | |
23 | ||
24 | repo.get_base_path = lambda base: os.path.join( | |
25 | base, 'info', 'fast-import', repo.hash) | |
26 | ||
27 | prefix = 'refs/testgit/%s/' % alias | |
28 | debug("prefix: '%s'", prefix) | |
29 | ||
30 | repo.gitdir = "" | |
31 | repo.alias = alias | |
32 | repo.prefix = prefix | |
33 | ||
34 | repo.exporter = GitExporter(repo) | |
35 | repo.importer = GitImporter(repo) | |
36 | repo.non_local = NonLocalGit(repo) | |
37 | ||
38 | return repo | |
39 | ||
40 | ||
41 | def local_repo(repo, path): | |
42 | """Returns a git repository object initalized for usage. | |
43 | """ | |
44 | ||
45 | local = GitRepo(path) | |
46 | ||
47 | local.non_local = None | |
48 | local.gitdir = repo.gitdir | |
49 | local.alias = repo.alias | |
50 | local.prefix = repo.prefix | |
51 | local.hash = repo.hash | |
52 | local.get_base_path = repo.get_base_path | |
53 | local.exporter = GitExporter(local) | |
54 | local.importer = GitImporter(local) | |
55 | ||
56 | return local | |
57 | ||
58 | ||
59 | def do_capabilities(repo, args): | |
60 | """Prints the supported capabilities. | |
61 | """ | |
62 | ||
63 | print "import" | |
64 | print "export" | |
65 | print "gitdir" | |
66 | print "refspec refs/heads/*:%s*" % repo.prefix | |
67 | ||
68 | print # end capabilities | |
69 | ||
70 | ||
71 | def do_list(repo, args): | |
72 | """Lists all known references. | |
73 | ||
74 | Bug: This will always set the remote head to master for non-local | |
75 | repositories, since we have no way of determining what the remote | |
76 | head is at clone time. | |
77 | """ | |
78 | ||
79 | for ref in repo.revs: | |
80 | debug("? refs/heads/%s", ref) | |
81 | print "? refs/heads/%s" % ref | |
82 | ||
83 | if repo.head: | |
84 | debug("@refs/heads/%s HEAD" % repo.head) | |
85 | print "@refs/heads/%s HEAD" % repo.head | |
86 | else: | |
87 | debug("@refs/heads/master HEAD") | |
88 | print "@refs/heads/master HEAD" | |
89 | ||
90 | print # end list | |
91 | ||
92 | ||
93 | def update_local_repo(repo): | |
94 | """Updates (or clones) a local repo. | |
95 | """ | |
96 | ||
97 | if repo.local: | |
98 | return repo | |
99 | ||
100 | path = repo.non_local.clone(repo.gitdir) | |
101 | repo.non_local.update(repo.gitdir) | |
102 | repo = local_repo(repo, path) | |
103 | return repo | |
104 | ||
105 | ||
106 | def do_import(repo, args): | |
107 | """Exports a fast-import stream from testgit for git to import. | |
108 | """ | |
109 | ||
110 | if len(args) != 1: | |
111 | die("Import needs exactly one ref") | |
112 | ||
113 | if not repo.gitdir: | |
114 | die("Need gitdir to import") | |
115 | ||
116 | repo = update_local_repo(repo) | |
117 | repo.exporter.export_repo(repo.gitdir) | |
118 | ||
119 | ||
120 | def do_export(repo, args): | |
121 | """Imports a fast-import stream from git to testgit. | |
122 | """ | |
123 | ||
124 | if not repo.gitdir: | |
125 | die("Need gitdir to export") | |
126 | ||
127 | dirname = repo.get_base_path(repo.gitdir) | |
128 | ||
129 | if not os.path.exists(dirname): | |
130 | os.makedirs(dirname) | |
131 | ||
132 | path = os.path.join(dirname, 'testgit.marks') | |
133 | print path | |
134 | print path if os.path.exists(path) else "" | |
135 | sys.stdout.flush() | |
136 | ||
137 | update_local_repo(repo) | |
138 | repo.importer.do_import(repo.gitdir) | |
139 | repo.non_local.push(repo.gitdir) | |
140 | ||
141 | ||
142 | def do_gitdir(repo, args): | |
143 | """Stores the location of the gitdir. | |
144 | """ | |
145 | ||
146 | if not args: | |
147 | die("gitdir needs an argument") | |
148 | ||
149 | repo.gitdir = ' '.join(args) | |
150 | ||
151 | ||
152 | COMMANDS = { | |
153 | 'capabilities': do_capabilities, | |
154 | 'list': do_list, | |
155 | 'import': do_import, | |
156 | 'export': do_export, | |
157 | 'gitdir': do_gitdir, | |
158 | } | |
159 | ||
160 | ||
161 | def sanitize(value): | |
162 | """Cleans up the url. | |
163 | """ | |
164 | ||
165 | if value.startswith('testgit::'): | |
166 | value = value[9:] | |
167 | ||
168 | return value | |
169 | ||
170 | ||
171 | def read_one_line(repo): | |
172 | """Reads and processes one command. | |
173 | """ | |
174 | ||
175 | line = sys.stdin.readline() | |
176 | ||
177 | cmdline = line | |
178 | ||
179 | if not cmdline: | |
180 | warn("Unexpected EOF") | |
181 | return False | |
182 | ||
183 | cmdline = cmdline.strip().split() | |
184 | if not cmdline: | |
185 | # Blank line means we're about to quit | |
186 | return False | |
187 | ||
188 | cmd = cmdline.pop(0) | |
189 | debug("Got command '%s' with args '%s'", cmd, ' '.join(cmdline)) | |
190 | ||
191 | if cmd not in COMMANDS: | |
192 | die("Unknown command, %s", cmd) | |
193 | ||
194 | func = COMMANDS[cmd] | |
195 | func(repo, cmdline) | |
196 | sys.stdout.flush() | |
197 | ||
198 | return True | |
199 | ||
200 | ||
201 | def main(args): | |
202 | """Starts a new remote helper for the specified repository. | |
203 | """ | |
204 | ||
205 | if len(args) != 3: | |
206 | die("Expecting exactly three arguments.") | |
207 | sys.exit(1) | |
208 | ||
209 | if os.getenv("GIT_DEBUG_TESTGIT"): | |
210 | import git_remote_helpers.util | |
211 | git_remote_helpers.util.DEBUG = True | |
212 | ||
213 | alias = sanitize(args[1]) | |
214 | url = sanitize(args[2]) | |
215 | ||
216 | if not alias.isalnum(): | |
217 | warn("non-alnum alias '%s'", alias) | |
218 | alias = "tmp" | |
219 | ||
220 | args[1] = alias | |
221 | args[2] = url | |
222 | ||
223 | repo = get_repo(alias, url) | |
224 | ||
225 | debug("Got arguments %s", args[1:]) | |
226 | ||
227 | more = True | |
228 | ||
229 | while (more): | |
230 | more = read_one_line(repo) | |
231 | ||
232 | if __name__ == '__main__': | |
233 | sys.exit(main(sys.argv)) |