Revert "Merge branch 'jc/graduate-remote-hg-bzr' (early part)"

Instead of showing a warning and working as before, fail and show the message and force immediate upgrade from their upstream repositories when these tools are run, per request from their primary author. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed May 20, 2014 at 14:18 UTC b2c851a8e67da752d8a5dbde5a9dae6e3428a4c9
11 files changed +87 -4360
Documentation/RelNotes/2.0.0.txt
+7
@@ -55,6 +55,9 @@ UI, Workflows & Features
55 * The "multi-mail" post-receive hook (in contrib/) has been updated
56 to a more recent version from the upstream.
57
58 + * The "remote-hg/bzr" remote-helper interfaces (in contrib/) are
59 + now maintained separately as a third-party plug-in.
60 +
61 * "git gc --aggressive" learned "--depth" option and
62 "gc.aggressiveDepth" configuration variable to allow use of a less
63 insane depth than the built-in default value of 250.
@@ -88,6 +91,10 @@ UI, Workflows & Features
91 * "git grep" learned to behave in a way similar to native grep when
92 "-h" (no header) and "-c" (count) options are given.
93
94 + * "git push" via transport-helper interface has been updated to
95 + allow forced ref updates in a way similar to the natively
96 + supported transports.
97 +
98 * The "simple" mode is the default for "git push".
99
100 * "git add -u" and "git add -A", when run without any pathspec, is a
contrib/remote-helpers/Makefile deleted
-14
@@ -1,14 +0,0 @@
1 -TESTS := $(wildcard test*.sh)
2 -
3 -export T := $(addprefix $(CURDIR)/,$(TESTS))
4 -export MAKE := $(MAKE) -e
5 -export PATH := $(CURDIR):$(PATH)
6 -export TEST_LINT := test-lint-executable test-lint-shell-syntax
7 -
8 -test:
9 - $(MAKE) -C ../../t $@
10 -
11 -$(TESTS):
12 - $(MAKE) -C ../../t $(CURDIR)/$@
13 -
14 -.PHONY: $(TESTS)
contrib/remote-helpers/README
+1 -5
@@ -1,6 +1,6 @@
1 The remote-helper bridges to access data stored in Mercurial and
2 Bazaar are maintained outside the git.git tree in the repositories
3 -of its primary author:
3 +of their primary author:
4
5 https://github.com/felipec/git-remote-hg (for Mercurial)
6 https://github.com/felipec/git-remote-bzr (for Bazaar)
@@ -13,7 +13,3 @@ repositories, e.g.:
13 $ wget -O $HOME/bin/git-remote-bzr \
14 https://raw.github.com/felipec/git-remote-bzr/master/git-remote-bzr
15 $ chmod +x $HOME/bin/git-remote-hg $HOME/bin/git-remote-bzr
16 -
17 -As a convenience, copies of the last-bundled version of these two
18 -remote-helper bridges are still kept here, but they may become
19 -stale over time.
contrib/remote-helpers/git-remote-bzr
+6 -979
@@ -1,986 +1,13 @@
1 #!/usr/bin/env python
2 -#
3 -# Copyright (c) 2012 Felipe Contreras
4 -#
5 -
6 -#
7 -# Just copy to your ~/bin, or anywhere in your $PATH.
8 -# Then you can clone with:
9 -# % git clone bzr::/path/to/bzr/repo/or/url
10 -#
11 -# For example:
12 -# % git clone bzr::$HOME/myrepo
13 -# or
14 -# % git clone bzr::lp:myrepo
15 -#
16 -# If you want to specify which branches you want to track (per repo):
17 -# % git config remote.origin.bzr-branches 'trunk, devel, test'
18 -#
19 -# Where 'origin' is the name of the repository you want to specify the
20 -# branches.
21 -#
22 -
23 -import sys
24 -
25 -import bzrlib
26 -if hasattr(bzrlib, "initialize"):
27 - bzrlib.initialize()
28 -
29 -import bzrlib.plugin
30 -bzrlib.plugin.load_plugins()
31 -
32 -import bzrlib.generate_ids
33 -import bzrlib.transport
34 -import bzrlib.errors
35 -import bzrlib.ui
36 -import bzrlib.urlutils
37 -import bzrlib.branch
2
3 import sys
40 -import os
41 -import json
42 -import re
43 -import StringIO
44 -import atexit, shutil, hashlib, urlparse, subprocess
4
5 sys.stderr.write('WARNING: git-remote-bzr is now maintained independently.\n')
6 sys.stderr.write('WARNING: For more information visit https://github.com/felipec/git-remote-bzr\n')
7
49 -NAME_RE = re.compile('^([^<>]+)')
50 -AUTHOR_RE = re.compile('^([^<>]+?)? ?[<>]([^<>]*)(?:$|>)')
51 -EMAIL_RE = re.compile(r'([^ \t<>]+@[^ \t<>]+)')
52 -RAW_AUTHOR_RE = re.compile('^(\w+) (.+)? <(.*)> (\d+) ([+-]\d+)')
53 -
54 -def die(msg, *args):
55 - sys.stderr.write('ERROR: %s\n' % (msg % args))
56 - sys.exit(1)
57 -
58 -def warn(msg, *args):
59 - sys.stderr.write('WARNING: %s\n' % (msg % args))
60 -
61 -def gittz(tz):
62 - return '%+03d%02d' % (tz / 3600, tz % 3600 / 60)
63 -
64 -def get_config(config):
65 - cmd = ['git', 'config', '--get', config]
66 - process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
67 - output, _ = process.communicate()
68 - return output
69 -
70 -class Marks:
71 -
72 - def __init__(self, path):
73 - self.path = path
74 - self.tips = {}
75 - self.marks = {}
76 - self.rev_marks = {}
77 - self.last_mark = 0
78 - self.load()
79 -
80 - def load(self):
81 - if not os.path.exists(self.path):
82 - return
83 -
84 - tmp = json.load(open(self.path))
85 - self.tips = tmp['tips']
86 - self.marks = tmp['marks']
87 - self.last_mark = tmp['last-mark']
88 -
89 - for rev, mark in self.marks.iteritems():
90 - self.rev_marks[mark] = rev
91 -
92 - def dict(self):
93 - return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
94 -
95 - def store(self):
96 - json.dump(self.dict(), open(self.path, 'w'))
97 -
98 - def __str__(self):
99 - return str(self.dict())
100 -
101 - def from_rev(self, rev):
102 - return self.marks[rev]
103 -
104 - def to_rev(self, mark):
105 - return str(self.rev_marks[mark])
106 -
107 - def next_mark(self):
108 - self.last_mark += 1
109 - return self.last_mark
110 -
111 - def get_mark(self, rev):
112 - self.last_mark += 1
113 - self.marks[rev] = self.last_mark
114 - return self.last_mark
115 -
116 - def is_marked(self, rev):
117 - return rev in self.marks
118 -
119 - def new_mark(self, rev, mark):
120 - self.marks[rev] = mark
121 - self.rev_marks[mark] = rev
122 - self.last_mark = mark
123 -
124 - def get_tip(self, branch):
125 - try:
126 - return str(self.tips[branch])
127 - except KeyError:
128 - return None
129 -
130 - def set_tip(self, branch, tip):
131 - self.tips[branch] = tip
132 -
133 -class Parser:
134 -
135 - def __init__(self, repo):
136 - self.repo = repo
137 - self.line = self.get_line()
138 -
139 - def get_line(self):
140 - return sys.stdin.readline().strip()
141 -
142 - def __getitem__(self, i):
143 - return self.line.split()[i]
144 -
145 - def check(self, word):
146 - return self.line.startswith(word)
147 -
148 - def each_block(self, separator):
149 - while self.line != separator:
150 - yield self.line
151 - self.line = self.get_line()
152 -
153 - def __iter__(self):
154 - return self.each_block('')
155 -
156 - def next(self):
157 - self.line = self.get_line()
158 - if self.line == 'done':
159 - self.line = None
160 -
161 - def get_mark(self):
162 - i = self.line.index(':') + 1
163 - return int(self.line[i:])
164 -
165 - def get_data(self):
166 - if not self.check('data'):
167 - return None
168 - i = self.line.index(' ') + 1
169 - size = int(self.line[i:])
170 - return sys.stdin.read(size)
171 -
172 - def get_author(self):
173 - m = RAW_AUTHOR_RE.match(self.line)
174 - if not m:
175 - return None
176 - _, name, email, date, tz = m.groups()
177 - name = name.decode('utf-8')
178 - committer = '%s <%s>' % (name, email)
179 - tz = int(tz)
180 - tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
181 - return (committer, int(date), tz)
182 -
183 -def rev_to_mark(rev):
184 - return marks.from_rev(rev)
185 -
186 -def mark_to_rev(mark):
187 - return marks.to_rev(mark)
188 -
189 -def fixup_user(user):
190 - name = mail = None
191 - user = user.replace('"', '')
192 - m = AUTHOR_RE.match(user)
193 - if m:
194 - name = m.group(1)
195 - mail = m.group(2).strip()
196 - else:
197 - m = EMAIL_RE.match(user)
198 - if m:
199 - mail = m.group(1)
200 - else:
201 - m = NAME_RE.match(user)
202 - if m:
203 - name = m.group(1).strip()
204 -
205 - if not name:
206 - name = 'unknown'
207 - if not mail:
208 - mail = 'Unknown'
209 -
210 - return '%s <%s>' % (name, mail)
211 -
212 -def get_filechanges(cur, prev):
213 - modified = {}
214 - removed = {}
215 -
216 - changes = cur.changes_from(prev)
217 -
218 - def u(s):
219 - return s.encode('utf-8')
220 -
221 - for path, fid, kind in changes.added:
222 - modified[u(path)] = fid
223 - for path, fid, kind in changes.removed:
224 - removed[u(path)] = None
225 - for path, fid, kind, mod, _ in changes.modified:
226 - modified[u(path)] = fid
227 - for oldpath, newpath, fid, kind, mod, _ in changes.renamed:
228 - removed[u(oldpath)] = None
229 - if kind == 'directory':
230 - lst = cur.list_files(from_dir=newpath, recursive=True)
231 - for path, file_class, kind, fid, entry in lst:
232 - if kind != 'directory':
233 - modified[u(newpath + '/' + path)] = fid
234 - else:
235 - modified[u(newpath)] = fid
236 -
237 - return modified, removed
238 -
239 -def export_files(tree, files):
240 - final = []
241 - for path, fid in files.iteritems():
242 - kind = tree.kind(fid)
243 -
244 - h = tree.get_file_sha1(fid)
245 -
246 - if kind == 'symlink':
247 - d = tree.get_symlink_target(fid)
248 - mode = '120000'
249 - elif kind == 'file':
250 -
251 - if tree.is_executable(fid):
252 - mode = '100755'
253 - else:
254 - mode = '100644'
255 -
256 - # is the blob already exported?
257 - if h in filenodes:
258 - mark = filenodes[h]
259 - final.append((mode, mark, path))
260 - continue
261 -
262 - d = tree.get_file_text(fid)
263 - elif kind == 'directory':
264 - continue
265 - else:
266 - die("Unhandled kind '%s' for path '%s'" % (kind, path))
267 -
268 - mark = marks.next_mark()
269 - filenodes[h] = mark
270 -
271 - print "blob"
272 - print "mark :%u" % mark
273 - print "data %d" % len(d)
274 - print d
275 -
276 - final.append((mode, mark, path))
277 -
278 - return final
279 -
280 -def export_branch(repo, name):
281 - ref = '%s/heads/%s' % (prefix, name)
282 - tip = marks.get_tip(name)
283 -
284 - branch = get_remote_branch(name)
285 - repo = branch.repository
286 -
287 - branch.lock_read()
288 - revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward')
289 - try:
290 - tip_revno = branch.revision_id_to_revno(tip)
291 - last_revno, _ = branch.last_revision_info()
292 - total = last_revno - tip_revno
293 - except bzrlib.errors.NoSuchRevision:
294 - tip_revno = 0
295 - total = 0
296 -
297 - for revid, _, seq, _ in revs:
298 -
299 - if marks.is_marked(revid):
300 - continue
301 -
302 - rev = repo.get_revision(revid)
303 - revno = seq[0]
304 -
305 - parents = rev.parent_ids
306 - time = rev.timestamp
307 - tz = rev.timezone
308 - committer = rev.committer.encode('utf-8')
309 - committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz))
310 - authors = rev.get_apparent_authors()
311 - if authors:
312 - author = authors[0].encode('utf-8')
313 - author = "%s %u %s" % (fixup_user(author), time, gittz(tz))
314 - else:
315 - author = committer
316 - msg = rev.message.encode('utf-8')
317 -
318 - msg += '\n'
319 -
320 - if len(parents) == 0:
321 - parent = bzrlib.revision.NULL_REVISION
322 - else:
323 - parent = parents[0]
324 -
325 - cur_tree = repo.revision_tree(revid)
326 - prev = repo.revision_tree(parent)
327 - modified, removed = get_filechanges(cur_tree, prev)
328 -
329 - modified_final = export_files(cur_tree, modified)
330 -
331 - if len(parents) == 0:
332 - print 'reset %s' % ref
333 -
334 - print "commit %s" % ref
335 - print "mark :%d" % (marks.get_mark(revid))
336 - print "author %s" % (author)
337 - print "committer %s" % (committer)
338 - print "data %d" % (len(msg))
339 - print msg
340 -
341 - for i, p in enumerate(parents):
342 - try:
343 - m = rev_to_mark(p)
344 - except KeyError:
345 - # ghost?
346 - continue
347 - if i == 0:
348 - print "from :%s" % m
349 - else:
350 - print "merge :%s" % m
351 -
352 - for f in removed:
353 - print "D %s" % (f,)
354 - for f in modified_final:
355 - print "M %s :%u %s" % f
356 - print
357 -
358 - if len(seq) > 1:
359 - # let's skip branch revisions from the progress report
360 - continue
361 -
362 - progress = (revno - tip_revno)
363 - if (progress % 100 == 0):
364 - if total:
365 - print "progress revision %d '%s' (%d/%d)" % (revno, name, progress, total)
366 - else:
367 - print "progress revision %d '%s' (%d)" % (revno, name, progress)
368 -
369 - branch.unlock()
370 -
371 - revid = branch.last_revision()
372 -
373 - # make sure the ref is updated
374 - print "reset %s" % ref
375 - print "from :%u" % rev_to_mark(revid)
376 - print
377 -
378 - marks.set_tip(name, revid)
379 -
380 -def export_tag(repo, name):
381 - ref = '%s/tags/%s' % (prefix, name)
382 - print "reset %s" % ref
383 - print "from :%u" % rev_to_mark(tags[name])
384 - print
385 -
386 -def do_import(parser):
387 - repo = parser.repo
388 - path = os.path.join(dirname, 'marks-git')
389 -
390 - print "feature done"
391 - if os.path.exists(path):
392 - print "feature import-marks=%s" % path
393 - print "feature export-marks=%s" % path
394 - print "feature force"
395 - sys.stdout.flush()
396 -
397 - while parser.check('import'):
398 - ref = parser[1]
399 - if ref.startswith('refs/heads/'):
400 - name = ref[len('refs/heads/'):]
401 - export_branch(repo, name)
402 - if ref.startswith('refs/tags/'):
403 - name = ref[len('refs/tags/'):]
404 - export_tag(repo, name)
405 - parser.next()
406 -
407 - print 'done'
408 -
409 - sys.stdout.flush()
410 -
411 -def parse_blob(parser):
412 - parser.next()
413 - mark = parser.get_mark()
414 - parser.next()
415 - data = parser.get_data()
416 - blob_marks[mark] = data
417 - parser.next()
418 -
419 -class CustomTree():
420 -
421 - def __init__(self, branch, revid, parents, files):
422 - self.updates = {}
423 - self.branch = branch
424 -
425 - def copy_tree(revid):
426 - files = files_cache[revid] = {}
427 - branch.lock_read()
428 - tree = branch.repository.revision_tree(revid)
429 - try:
430 - for path, entry in tree.iter_entries_by_dir():
431 - files[path] = [entry.file_id, None]
432 - finally:
433 - branch.unlock()
434 - return files
435 -
436 - if len(parents) == 0:
437 - self.base_id = bzrlib.revision.NULL_REVISION
438 - self.base_files = {}
439 - else:
440 - self.base_id = parents[0]
441 - self.base_files = files_cache.get(self.base_id, None)
442 - if not self.base_files:
443 - self.base_files = copy_tree(self.base_id)
444 -
445 - self.files = files_cache[revid] = self.base_files.copy()
446 - self.rev_files = {}
447 -
448 - for path, data in self.files.iteritems():
449 - fid, mark = data
450 - self.rev_files[fid] = [path, mark]
451 -
452 - for path, f in files.iteritems():
453 - fid, mark = self.files.get(path, [None, None])
454 - if not fid:
455 - fid = bzrlib.generate_ids.gen_file_id(path)
456 - f['path'] = path
457 - self.rev_files[fid] = [path, mark]
458 - self.updates[fid] = f
459 -
460 - def last_revision(self):
461 - return self.base_id
462 -
463 - def iter_changes(self):
464 - changes = []
465 -
466 - def get_parent(dirname, basename):
467 - parent_fid, mark = self.base_files.get(dirname, [None, None])
468 - if parent_fid:
469 - return parent_fid
470 - parent_fid, mark = self.files.get(dirname, [None, None])
471 - if parent_fid:
472 - return parent_fid
473 - if basename == '':
474 - return None
475 - fid = bzrlib.generate_ids.gen_file_id(path)
476 - add_entry(fid, dirname, 'directory')
477 - return fid
478 -
479 - def add_entry(fid, path, kind, mode=None):
480 - dirname, basename = os.path.split(path)
481 - parent_fid = get_parent(dirname, basename)
482 -
483 - executable = False
484 - if mode == '100755':
485 - executable = True
486 - elif mode == '120000':
487 - kind = 'symlink'
488 -
489 - change = (fid,
490 - (None, path),
491 - True,
492 - (False, True),
493 - (None, parent_fid),
494 - (None, basename),
495 - (None, kind),
496 - (None, executable))
497 - self.files[path] = [change[0], None]
498 - changes.append(change)
499 -
500 - def update_entry(fid, path, kind, mode=None):
501 - dirname, basename = os.path.split(path)
502 - parent_fid = get_parent(dirname, basename)
503 -
504 - executable = False
505 - if mode == '100755':
506 - executable = True
507 - elif mode == '120000':
508 - kind = 'symlink'
509 -
510 - change = (fid,
511 - (path, path),
512 - True,
513 - (True, True),
514 - (None, parent_fid),
515 - (None, basename),
516 - (None, kind),
517 - (None, executable))
518 - self.files[path] = [change[0], None]
519 - changes.append(change)
520 -
521 - def remove_entry(fid, path, kind):
522 - dirname, basename = os.path.split(path)
523 - parent_fid = get_parent(dirname, basename)
524 - change = (fid,
525 - (path, None),
526 - True,
527 - (True, False),
528 - (parent_fid, None),
529 - (None, None),
530 - (None, None),
531 - (None, None))
532 - del self.files[path]
533 - changes.append(change)
534 -
535 - for fid, f in self.updates.iteritems():
536 - path = f['path']
537 -
538 - if 'deleted' in f:
539 - remove_entry(fid, path, 'file')
540 - continue
541 -
542 - if path in self.base_files:
543 - update_entry(fid, path, 'file', f['mode'])
544 - else:
545 - add_entry(fid, path, 'file', f['mode'])
546 -
547 - self.files[path][1] = f['mark']
548 - self.rev_files[fid][1] = f['mark']
549 -
550 - return changes
551 -
552 - def get_content(self, file_id):
553 - path, mark = self.rev_files[file_id]
554 - if mark:
555 - return blob_marks[mark]
556 -
557 - # last resort
558 - tree = self.branch.repository.revision_tree(self.base_id)
559 - return tree.get_file_text(file_id)
560 -
561 - def get_file_with_stat(self, file_id, path=None):
562 - content = self.get_content(file_id)
563 - return (StringIO.StringIO(content), None)
564 -
565 - def get_symlink_target(self, file_id):
566 - return self.get_content(file_id)
567 -
568 - def id2path(self, file_id):
569 - path, mark = self.rev_files[file_id]
570 - return path
571 -
572 -def c_style_unescape(string):
573 - if string[0] == string[-1] == '"':
574 - return string.decode('string-escape')[1:-1]
575 - return string
576 -
577 -def parse_commit(parser):
578 - parents = []
579 -
580 - ref = parser[1]
581 - parser.next()
582 -
583 - if ref.startswith('refs/heads/'):
584 - name = ref[len('refs/heads/'):]
585 - branch = get_remote_branch(name)
586 - else:
587 - die('unknown ref')
588 -
589 - commit_mark = parser.get_mark()
590 - parser.next()
591 - author = parser.get_author()
592 - parser.next()
593 - committer = parser.get_author()
594 - parser.next()
595 - data = parser.get_data()
596 - parser.next()
597 - if parser.check('from'):
598 - parents.append(parser.get_mark())
599 - parser.next()
600 - while parser.check('merge'):
601 - parents.append(parser.get_mark())
602 - parser.next()
603 -
604 - # fast-export adds an extra newline
605 - if data[-1] == '\n':
606 - data = data[:-1]
607 -
608 - files = {}
609 -
610 - for line in parser:
611 - if parser.check('M'):
612 - t, m, mark_ref, path = line.split(' ', 3)
613 - mark = int(mark_ref[1:])
614 - f = { 'mode' : m, 'mark' : mark }
615 - elif parser.check('D'):
616 - t, path = line.split(' ', 1)
617 - f = { 'deleted' : True }
618 - else:
619 - die('Unknown file command: %s' % line)
620 - path = c_style_unescape(path).decode('utf-8')
621 - files[path] = f
622 -
623 - committer, date, tz = committer
624 - author, _, _ = author
625 - parents = [mark_to_rev(p) for p in parents]
626 - revid = bzrlib.generate_ids.gen_revision_id(committer, date)
627 - props = {}
628 - props['branch-nick'] = branch.nick
629 - props['authors'] = author
630 -
631 - mtree = CustomTree(branch, revid, parents, files)
632 - changes = mtree.iter_changes()
633 -
634 - branch.lock_write()
635 - try:
636 - builder = branch.get_commit_builder(parents, None, date, tz, committer, props, revid)
637 - try:
638 - list(builder.record_iter_changes(mtree, mtree.last_revision(), changes))
639 - builder.finish_inventory()
640 - builder.commit(data.decode('utf-8', 'replace'))
641 - except Exception, e:
642 - builder.abort()
643 - raise
644 - finally:
645 - branch.unlock()
646 -
647 - parsed_refs[ref] = revid
648 - marks.new_mark(revid, commit_mark)
649 -
650 -def parse_reset(parser):
651 - ref = parser[1]
652 - parser.next()
653 -
654 - # ugh
655 - if parser.check('commit'):
656 - parse_commit(parser)
657 - return
658 - if not parser.check('from'):
659 - return
660 - from_mark = parser.get_mark()
661 - parser.next()
662 -
663 - parsed_refs[ref] = mark_to_rev(from_mark)
664 -
665 -def do_export(parser):
666 - parser.next()
667 -
668 - for line in parser.each_block('done'):
669 - if parser.check('blob'):
670 - parse_blob(parser)
671 - elif parser.check('commit'):
672 - parse_commit(parser)
673 - elif parser.check('reset'):
674 - parse_reset(parser)
675 - elif parser.check('tag'):
676 - pass
677 - elif parser.check('feature'):
678 - pass
679 - else:
680 - die('unhandled export command: %s' % line)
681 -
682 - for ref, revid in parsed_refs.iteritems():
683 - if ref.startswith('refs/heads/'):
684 - name = ref[len('refs/heads/'):]
685 - branch = get_remote_branch(name)
686 - branch.generate_revision_history(revid, marks.get_tip(name))
687 -
688 - if name in peers:
689 - peer = bzrlib.branch.Branch.open(peers[name],
690 - possible_transports=transports)
691 - try:
692 - peer.bzrdir.push_branch(branch, revision_id=revid,
693 - overwrite=force)
694 - except bzrlib.errors.DivergedBranches:
695 - print "error %s non-fast forward" % ref
696 - continue
697 -
698 - try:
699 - wt = branch.bzrdir.open_workingtree()
700 - wt.update()
701 - except bzrlib.errors.NoWorkingTree:
702 - pass
703 - elif ref.startswith('refs/tags/'):
704 - # TODO: implement tag push
705 - print "error %s pushing tags not supported" % ref
706 - continue
707 - else:
708 - # transport-helper/fast-export bugs
709 - continue
710 -
711 - print "ok %s" % ref
712 -
713 - print
714 -
715 -def do_capabilities(parser):
716 - print "import"
717 - print "export"
718 - print "refspec refs/heads/*:%s/heads/*" % prefix
719 - print "refspec refs/tags/*:%s/tags/*" % prefix
720 -
721 - path = os.path.join(dirname, 'marks-git')
722 -
723 - if os.path.exists(path):
724 - print "*import-marks %s" % path
725 - print "*export-marks %s" % path
726 -
727 - print "option"
728 - print
729 -
730 -class InvalidOptionValue(Exception):
731 - pass
732 -
733 -def get_bool_option(val):
734 - if val == 'true':
735 - return True
736 - elif val == 'false':
737 - return False
738 - else:
739 - raise InvalidOptionValue()
740 -
741 -def do_option(parser):
742 - global force
743 - opt, val = parser[1:3]
744 - try:
745 - if opt == 'force':
746 - force = get_bool_option(val)
747 - print 'ok'
748 - else:
749 - print 'unsupported'
750 - except InvalidOptionValue:
751 - print "error '%s' is not a valid value for option '%s'" % (val, opt)
752 -
753 -def ref_is_valid(name):
754 - return not True in [c in name for c in '~^: \\']
755 -
756 -def do_list(parser):
757 - master_branch = None
758 -
759 - for name in branches:
760 - if not master_branch:
761 - master_branch = name
762 - print "? refs/heads/%s" % name
763 -
764 - branch = get_remote_branch(master_branch)
765 - branch.lock_read()
766 - for tag, revid in branch.tags.get_tag_dict().items():
767 - try:
768 - branch.revision_id_to_dotted_revno(revid)
769 - except bzrlib.errors.NoSuchRevision:
770 - continue
771 - if not ref_is_valid(tag):
772 - continue
773 - print "? refs/tags/%s" % tag
774 - tags[tag] = revid
775 - branch.unlock()
776 -
777 - print "@refs/heads/%s HEAD" % master_branch
778 - print
779 -
780 -def clone(path, remote_branch):
781 - try:
782 - bdir = bzrlib.bzrdir.BzrDir.create(path, possible_transports=transports)
783 - except bzrlib.errors.AlreadyControlDirError:
784 - bdir = bzrlib.bzrdir.BzrDir.open(path, possible_transports=transports)
785 - repo = bdir.find_repository()
786 - repo.fetch(remote_branch.repository)
787 - return remote_branch.sprout(bdir, repository=repo)
788 -
789 -def get_remote_branch(name):
790 - remote_branch = bzrlib.branch.Branch.open(branches[name],
791 - possible_transports=transports)
792 - if isinstance(remote_branch.bzrdir.root_transport, bzrlib.transport.local.LocalTransport):
793 - return remote_branch
794 -
795 - branch_path = os.path.join(dirname, 'clone', name)
796 -
797 - try:
798 - branch = bzrlib.branch.Branch.open(branch_path,
799 - possible_transports=transports)
800 - except bzrlib.errors.NotBranchError:
801 - # clone
802 - branch = clone(branch_path, remote_branch)
803 - else:
804 - # pull
805 - try:
806 - branch.pull(remote_branch, overwrite=True)
807 - except bzrlib.errors.DivergedBranches:
808 - # use remote branch for now
809 - return remote_branch
810 -
811 - return branch
812 -
813 -def find_branches(repo):
814 - transport = repo.bzrdir.root_transport
815 -
816 - for fn in transport.iter_files_recursive():
817 - if not fn.endswith('.bzr/branch-format'):
818 - continue
819 -
820 - name = subdir = fn[:-len('/.bzr/branch-format')]
821 - name = name if name != '' else 'master'
822 - name = name.replace('/', '+')
823 -
824 - try:
825 - cur = transport.clone(subdir)
826 - branch = bzrlib.branch.Branch.open_from_transport(cur)
827 - except bzrlib.errors.NotBranchError:
828 - continue
829 - else:
830 - yield name, branch.base
831 -
832 -def get_repo(url, alias):
833 - normal_url = bzrlib.urlutils.normalize_url(url)
834 - origin = bzrlib.bzrdir.BzrDir.open(url, possible_transports=transports)
835 - is_local = isinstance(origin.transport, bzrlib.transport.local.LocalTransport)
836 -
837 - shared_path = os.path.join(gitdir, 'bzr')
838 - try:
839 - shared_dir = bzrlib.bzrdir.BzrDir.open(shared_path,
840 - possible_transports=transports)
841 - except bzrlib.errors.NotBranchError:
842 - shared_dir = bzrlib.bzrdir.BzrDir.create(shared_path,
843 - possible_transports=transports)
844 - try:
845 - shared_repo = shared_dir.open_repository()
846 - except bzrlib.errors.NoRepositoryPresent:
847 - shared_repo = shared_dir.create_repository(shared=True)
848 -
849 - if not is_local:
850 - clone_path = os.path.join(dirname, 'clone')
851 - if not os.path.exists(clone_path):
852 - os.mkdir(clone_path)
853 - else:
854 - # check and remove old organization
855 - try:
856 - bdir = bzrlib.bzrdir.BzrDir.open(clone_path,
857 - possible_transports=transports)
858 - bdir.destroy_repository()
859 - except bzrlib.errors.NotBranchError:
860 - pass
861 - except bzrlib.errors.NoRepositoryPresent:
862 - pass
863 -
864 - wanted = get_config('remote.%s.bzr-branches' % alias).rstrip().split(', ')
865 - # stupid python
866 - wanted = [e for e in wanted if e]
867 - if not wanted:
868 - wanted = get_config('remote-bzr.branches').rstrip().split(', ')
869 - # stupid python
870 - wanted = [e for e in wanted if e]
871 -
872 - if not wanted:
873 - try:
874 - repo = origin.open_repository()
875 - if not repo.bzrdir.root_transport.listable():
876 - # this repository is not usable for us
877 - raise bzrlib.errors.NoRepositoryPresent(repo.bzrdir)
878 - except bzrlib.errors.NoRepositoryPresent:
879 - wanted = ['master']
880 -
881 - if wanted:
882 - def list_wanted(url, wanted):
883 - for name in wanted:
884 - subdir = name if name != 'master' else ''
885 - yield name, bzrlib.urlutils.join(url, subdir)
886 -
887 - branch_list = list_wanted(url, wanted)
888 - else:
889 - branch_list = find_branches(repo)
890 -
891 - for name, url in branch_list:
892 - if not is_local:
893 - peers[name] = url
894 - branches[name] = url
895 -
896 - return origin
897 -
898 -def fix_path(alias, orig_url):
899 - url = urlparse.urlparse(orig_url, 'file')
900 - if url.scheme != 'file' or os.path.isabs(url.path):
901 - return
902 - abs_url = urlparse.urljoin("%s/" % os.getcwd(), orig_url)
903 - cmd = ['git', 'config', 'remote.%s.url' % alias, "bzr::%s" % abs_url]
904 - subprocess.call(cmd)
905 -
906 -def main(args):
907 - global marks, prefix, gitdir, dirname
908 - global tags, filenodes
909 - global blob_marks
910 - global parsed_refs
911 - global files_cache
912 - global is_tmp
913 - global branches, peers
914 - global transports
915 - global force
916 -
917 - marks = None
918 - is_tmp = False
919 - gitdir = os.environ.get('GIT_DIR', None)
920 -
921 - if len(args) < 3:
922 - die('Not enough arguments.')
923 -
924 - if not gitdir:
925 - die('GIT_DIR not set')
926 -
927 - alias = args[1]
928 - url = args[2]
929 -
930 - tags = {}
931 - filenodes = {}
932 - blob_marks = {}
933 - parsed_refs = {}
934 - files_cache = {}
935 - branches = {}
936 - peers = {}
937 - transports = []
938 - force = False
939 -
940 - if alias[5:] == url:
941 - is_tmp = True
942 - alias = hashlib.sha1(alias).hexdigest()
943 -
944 - prefix = 'refs/bzr/%s' % alias
945 - dirname = os.path.join(gitdir, 'bzr', alias)
946 -
947 - if not is_tmp:
948 - fix_path(alias, url)
949 -
950 - if not os.path.exists(dirname):
951 - os.makedirs(dirname)
952 -
953 - if hasattr(bzrlib.ui.ui_factory, 'be_quiet'):
954 - bzrlib.ui.ui_factory.be_quiet(True)
955 -
956 - repo = get_repo(url, alias)
957 -
958 - marks_path = os.path.join(dirname, 'marks-int')
959 - marks = Marks(marks_path)
960 -
961 - parser = Parser(repo)
962 - for line in parser:
963 - if parser.check('capabilities'):
964 - do_capabilities(parser)
965 - elif parser.check('list'):
966 - do_list(parser)
967 - elif parser.check('import'):
968 - do_import(parser)
969 - elif parser.check('export'):
970 - do_export(parser)
971 - elif parser.check('option'):
972 - do_option(parser)
973 - else:
974 - die('unhandled command: %s' % line)
975 - sys.stdout.flush()
976 -
977 -def bye():
978 - if not marks:
979 - return
980 - if not is_tmp:
981 - marks.store()
982 - else:
983 - shutil.rmtree(dirname)
984 -
985 -atexit.register(bye)
986 -sys.exit(main(sys.argv))
8 +sys.stderr.write('''WARNING:
9 +WARNING: You can pick a directory on your $PATH and download it, e.g.:
10 +WARNING: $ wget -O $HOME/bin/git-remote-bzr \\
11 +WARNING: https://raw.github.com/felipec/git-remote-bzr/master/git-remote-bzr
12 +WARNING: $ chmod +x $HOME/bin/git-remote-bzr
13 +''')
contrib/remote-helpers/git-remote-hg
+6 -1254
@@ -1,1261 +1,13 @@
1 #!/usr/bin/env python
2 -#
3 -# Copyright (c) 2012 Felipe Contreras
4 -#
2
6 -# Inspired by Rocco Rutte's hg-fast-export
7 -
8 -# Just copy to your ~/bin, or anywhere in your $PATH.
9 -# Then you can clone with:
10 -# git clone hg::/path/to/mercurial/repo/
11 -#
12 -# For remote repositories a local clone is stored in
13 -# "$GIT_DIR/hg/origin/clone/.hg/".
14 -
15 -from mercurial import hg, ui, bookmarks, context, encoding, node, error, extensions, discovery, util
16 -
17 -import re
3 import sys
19 -import os
20 -import json
21 -import shutil
22 -import subprocess
23 -import urllib
24 -import atexit
25 -import urlparse, hashlib
26 -import time as ptime
4
5 sys.stderr.write('WARNING: git-remote-hg is now maintained independently.\n')
6 sys.stderr.write('WARNING: For more information visit https://github.com/felipec/git-remote-hg\n')
7
31 -#
32 -# If you want to see Mercurial revisions as Git commit notes:
33 -# git config core.notesRef refs/notes/hg
34 -#
35 -# If you are not in hg-git-compat mode and want to disable the tracking of
36 -# named branches:
37 -# git config --global remote-hg.track-branches false
38 -#
39 -# If you want the equivalent of hg's clone/pull--insecure option:
40 -# git config --global remote-hg.insecure true
41 -#
42 -# If you want to switch to hg-git compatibility mode:
43 -# git config --global remote-hg.hg-git-compat true
44 -#
45 -# git:
46 -# Sensible defaults for git.
47 -# hg bookmarks are exported as git branches, hg branches are prefixed
48 -# with 'branches/', HEAD is a special case.
49 -#
50 -# hg:
51 -# Emulate hg-git.
52 -# Only hg bookmarks are exported as git branches.
53 -# Commits are modified to preserve hg information and allow bidirectionality.
54 -#
55 -
56 -NAME_RE = re.compile('^([^<>]+)')
57 -AUTHOR_RE = re.compile('^([^<>]+?)? ?[<>]([^<>]*)(?:$|>)')
58 -EMAIL_RE = re.compile(r'([^ \t<>]+@[^ \t<>]+)')
59 -AUTHOR_HG_RE = re.compile('^(.*?) ?<(.*?)(?:>(.+)?)?$')
60 -RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.*)> (\d+) ([+-]\d+)')
61 -
62 -VERSION = 2
63 -
64 -def die(msg, *args):
65 - sys.stderr.write('ERROR: %s\n' % (msg % args))
66 - sys.exit(1)
67 -
68 -def warn(msg, *args):
69 - sys.stderr.write('WARNING: %s\n' % (msg % args))
70 -
71 -def gitmode(flags):
72 - return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
73 -
74 -def gittz(tz):
75 - return '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
76 -
77 -def hgmode(mode):
78 - m = { '100755': 'x', '120000': 'l' }
79 - return m.get(mode, '')
80 -
81 -def hghex(n):
82 - return node.hex(n)
83 -
84 -def hgbin(n):
85 - return node.bin(n)
86 -
87 -def hgref(ref):
88 - return ref.replace('___', ' ')
89 -
90 -def gitref(ref):
91 - return ref.replace(' ', '___')
92 -
93 -def check_version(*check):
94 - if not hg_version:
95 - return True
96 - return hg_version >= check
97 -
98 -def get_config(config):
99 - cmd = ['git', 'config', '--get', config]
100 - process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
101 - output, _ = process.communicate()
102 - return output
103 -
104 -def get_config_bool(config, default=False):
105 - value = get_config(config).rstrip('\n')
106 - if value == "true":
107 - return True
108 - elif value == "false":
109 - return False
110 - else:
111 - return default
112 -
113 -class Marks:
114 -
115 - def __init__(self, path, repo):
116 - self.path = path
117 - self.repo = repo
118 - self.clear()
119 - self.load()
120 -
121 - if self.version < VERSION:
122 - if self.version == 1:
123 - self.upgrade_one()
124 -
125 - # upgraded?
126 - if self.version < VERSION:
127 - self.clear()
128 - self.version = VERSION
129 -
130 - def clear(self):
131 - self.tips = {}
132 - self.marks = {}
133 - self.rev_marks = {}
134 - self.last_mark = 0
135 - self.version = 0
136 - self.last_note = 0
137 -
138 - def load(self):
139 - if not os.path.exists(self.path):
140 - return
141 -
142 - tmp = json.load(open(self.path))
143 -
144 - self.tips = tmp['tips']
145 - self.marks = tmp['marks']
146 - self.last_mark = tmp['last-mark']
147 - self.version = tmp.get('version', 1)
148 - self.last_note = tmp.get('last-note', 0)
149 -
150 - for rev, mark in self.marks.iteritems():
151 - self.rev_marks[mark] = rev
152 -
153 - def upgrade_one(self):
154 - def get_id(rev):
155 - return hghex(self.repo.changelog.node(int(rev)))
156 - self.tips = dict((name, get_id(rev)) for name, rev in self.tips.iteritems())
157 - self.marks = dict((get_id(rev), mark) for rev, mark in self.marks.iteritems())
158 - self.rev_marks = dict((mark, get_id(rev)) for mark, rev in self.rev_marks.iteritems())
159 - self.version = 2
160 -
161 - def dict(self):
162 - return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark, 'version' : self.version, 'last-note' : self.last_note }
163 -
164 - def store(self):
165 - json.dump(self.dict(), open(self.path, 'w'))
166 -
167 - def __str__(self):
168 - return str(self.dict())
169 -
170 - def from_rev(self, rev):
171 - return self.marks[rev]
172 -
173 - def to_rev(self, mark):
174 - return str(self.rev_marks[mark])
175 -
176 - def next_mark(self):
177 - self.last_mark += 1
178 - return self.last_mark
179 -
180 - def get_mark(self, rev):
181 - self.last_mark += 1
182 - self.marks[rev] = self.last_mark
183 - return self.last_mark
184 -
185 - def new_mark(self, rev, mark):
186 - self.marks[rev] = mark
187 - self.rev_marks[mark] = rev
188 - self.last_mark = mark
189 -
190 - def is_marked(self, rev):
191 - return rev in self.marks
192 -
193 - def get_tip(self, branch):
194 - return str(self.tips[branch])
195 -
196 - def set_tip(self, branch, tip):
197 - self.tips[branch] = tip
198 -
199 -class Parser:
200 -
201 - def __init__(self, repo):
202 - self.repo = repo
203 - self.line = self.get_line()
204 -
205 - def get_line(self):
206 - return sys.stdin.readline().strip()
207 -
208 - def __getitem__(self, i):
209 - return self.line.split()[i]
210 -
211 - def check(self, word):
212 - return self.line.startswith(word)
213 -
214 - def each_block(self, separator):
215 - while self.line != separator:
216 - yield self.line
217 - self.line = self.get_line()
218 -
219 - def __iter__(self):
220 - return self.each_block('')
221 -
222 - def next(self):
223 - self.line = self.get_line()
224 - if self.line == 'done':
225 - self.line = None
226 -
227 - def get_mark(self):
228 - i = self.line.index(':') + 1
229 - return int(self.line[i:])
230 -
231 - def get_data(self):
232 - if not self.check('data'):
233 - return None
234 - i = self.line.index(' ') + 1
235 - size = int(self.line[i:])
236 - return sys.stdin.read(size)
237 -
238 - def get_author(self):
239 - ex = None
240 - m = RAW_AUTHOR_RE.match(self.line)
241 - if not m:
242 - return None
243 - _, name, email, date, tz = m.groups()
244 - if name and 'ext:' in name:
245 - m = re.match('^(.+?) ext:\((.+)\)$', name)
246 - if m:
247 - name = m.group(1)
248 - ex = urllib.unquote(m.group(2))
249 -
250 - if email != bad_mail:
251 - if name:
252 - user = '%s <%s>' % (name, email)
253 - else:
254 - user = '<%s>' % (email)
255 - else:
256 - user = name
257 -
258 - if ex:
259 - user += ex
260 -
261 - tz = int(tz)
262 - tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
263 - return (user, int(date), -tz)
264 -
265 -def fix_file_path(path):
266 - path = os.path.normpath(path)
267 - if not os.path.isabs(path):
268 - return path
269 - return os.path.relpath(path, '/')
270 -
271 -def export_files(files):
272 - final = []
273 - for f in files:
274 - fid = node.hex(f.filenode())
275 -
276 - if fid in filenodes:
277 - mark = filenodes[fid]
278 - else:
279 - mark = marks.next_mark()
280 - filenodes[fid] = mark
281 - d = f.data()
282 -
283 - print "blob"
284 - print "mark :%u" % mark
285 - print "data %d" % len(d)
286 - print d
287 -
288 - path = fix_file_path(f.path())
289 - final.append((gitmode(f.flags()), mark, path))
290 -
291 - return final
292 -
293 -def get_filechanges(repo, ctx, parent):
294 - modified = set()
295 - added = set()
296 - removed = set()
297 -
298 - # load earliest manifest first for caching reasons
299 - prev = parent.manifest().copy()
300 - cur = ctx.manifest()
301 -
302 - for fn in cur:
303 - if fn in prev:
304 - if (cur.flags(fn) != prev.flags(fn) or cur[fn] != prev[fn]):
305 - modified.add(fn)
306 - del prev[fn]
307 - else:
308 - added.add(fn)
309 - removed |= set(prev.keys())
310 -
311 - return added | modified, removed
312 -
313 -def fixup_user_git(user):
314 - name = mail = None
315 - user = user.replace('"', '')
316 - m = AUTHOR_RE.match(user)
317 - if m:
318 - name = m.group(1)
319 - mail = m.group(2).strip()
320 - else:
321 - m = EMAIL_RE.match(user)
322 - if m:
323 - mail = m.group(1)
324 - else:
325 - m = NAME_RE.match(user)
326 - if m:
327 - name = m.group(1).strip()
328 - return (name, mail)
329 -
330 -def fixup_user_hg(user):
331 - def sanitize(name):
332 - # stole this from hg-git
333 - return re.sub('[<>\n]', '?', name.lstrip('< ').rstrip('> '))
334 -
335 - m = AUTHOR_HG_RE.match(user)
336 - if m:
337 - name = sanitize(m.group(1))
338 - mail = sanitize(m.group(2))
339 - ex = m.group(3)
340 - if ex:
341 - name += ' ext:(' + urllib.quote(ex) + ')'
342 - else:
343 - name = sanitize(user)
344 - if '@' in user:
345 - mail = name
346 - else:
347 - mail = None
348 -
349 - return (name, mail)
350 -
351 -def fixup_user(user):
352 - if mode == 'git':
353 - name, mail = fixup_user_git(user)
354 - else:
355 - name, mail = fixup_user_hg(user)
356 -
357 - if not name:
358 - name = bad_name
359 - if not mail:
360 - mail = bad_mail
361 -
362 - return '%s <%s>' % (name, mail)
363 -
364 -def updatebookmarks(repo, peer):
365 - remotemarks = peer.listkeys('bookmarks')
366 - localmarks = repo._bookmarks
367 -
368 - if not remotemarks:
369 - return
370 -
371 - for k, v in remotemarks.iteritems():
372 - localmarks[k] = hgbin(v)
373 -
374 - if hasattr(localmarks, 'write'):
375 - localmarks.write()
376 - else:
377 - bookmarks.write(repo)
378 -
379 -def get_repo(url, alias):
380 - global peer
381 -
382 - myui = ui.ui()
383 - myui.setconfig('ui', 'interactive', 'off')
384 - myui.fout = sys.stderr
385 -
386 - if get_config_bool('remote-hg.insecure'):
387 - myui.setconfig('web', 'cacerts', '')
388 -
389 - extensions.loadall(myui)
390 -
391 - if hg.islocal(url) and not os.environ.get('GIT_REMOTE_HG_TEST_REMOTE'):
392 - repo = hg.repository(myui, url)
393 - if not os.path.exists(dirname):
394 - os.makedirs(dirname)
395 - else:
396 - shared_path = os.path.join(gitdir, 'hg')
397 -
398 - # check and upgrade old organization
399 - hg_path = os.path.join(shared_path, '.hg')
400 - if os.path.exists(shared_path) and not os.path.exists(hg_path):
401 - repos = os.listdir(shared_path)
402 - for x in repos:
403 - local_hg = os.path.join(shared_path, x, 'clone', '.hg')
404 - if not os.path.exists(local_hg):
405 - continue
406 - if not os.path.exists(hg_path):
407 - shutil.move(local_hg, hg_path)
408 - shutil.rmtree(os.path.join(shared_path, x, 'clone'))
409 -
410 - # setup shared repo (if not there)
411 - try:
412 - hg.peer(myui, {}, shared_path, create=True)
413 - except error.RepoError:
414 - pass
415 -
416 - if not os.path.exists(dirname):
417 - os.makedirs(dirname)
418 -
419 - local_path = os.path.join(dirname, 'clone')
420 - if not os.path.exists(local_path):
421 - hg.share(myui, shared_path, local_path, update=False)
422 - else:
423 - # make sure the shared path is always up-to-date
424 - util.writefile(os.path.join(local_path, '.hg', 'sharedpath'), hg_path)
425 -
426 - repo = hg.repository(myui, local_path)
427 - try:
428 - peer = hg.peer(myui, {}, url)
429 - except:
430 - die('Repository error')
431 - repo.pull(peer, heads=None, force=True)
432 -
433 - updatebookmarks(repo, peer)
434 -
435 - return repo
436 -
437 -def rev_to_mark(rev):
438 - return marks.from_rev(rev.hex())
439 -
440 -def mark_to_rev(mark):
441 - return marks.to_rev(mark)
442 -
443 -def export_ref(repo, name, kind, head):
444 - ename = '%s/%s' % (kind, name)
445 - try:
446 - tip = marks.get_tip(ename)
447 - tip = repo[tip].rev()
448 - except:
449 - tip = 0
450 -
451 - revs = xrange(tip, head.rev() + 1)
452 - total = len(revs)
453 -
454 - for rev in revs:
455 -
456 - c = repo[rev]
457 - node = c.node()
458 -
459 - if marks.is_marked(c.hex()):
460 - continue
461 -
462 - (manifest, user, (time, tz), files, desc, extra) = repo.changelog.read(node)
463 - rev_branch = extra['branch']
464 -
465 - author = "%s %d %s" % (fixup_user(user), time, gittz(tz))
466 - if 'committer' in extra:
467 - user, time, tz = extra['committer'].rsplit(' ', 2)
468 - committer = "%s %s %s" % (user, time, gittz(int(tz)))
469 - else:
470 - committer = author
471 -
472 - parents = [repo[p] for p in repo.changelog.parentrevs(rev) if p >= 0]
473 -
474 - if len(parents) == 0:
475 - modified = c.manifest().keys()
476 - removed = []
477 - else:
478 - modified, removed = get_filechanges(repo, c, parents[0])
479 -
480 - desc += '\n'
481 -
482 - if mode == 'hg':
483 - extra_msg = ''
484 -
485 - if rev_branch != 'default':
486 - extra_msg += 'branch : %s\n' % rev_branch
487 -
488 - renames = []
489 - for f in c.files():
490 - if f not in c.manifest():
491 - continue
492 - rename = c.filectx(f).renamed()
493 - if rename:
494 - renames.append((rename[0], f))
495 -
496 - for e in renames:
497 - extra_msg += "rename : %s => %s\n" % e
498 -
499 - for key, value in extra.iteritems():
500 - if key in ('author', 'committer', 'encoding', 'message', 'branch', 'hg-git'):
501 - continue
502 - else:
503 - extra_msg += "extra : %s : %s\n" % (key, urllib.quote(value))
504 -
505 - if extra_msg:
506 - desc += '\n--HG--\n' + extra_msg
507 -
508 - if len(parents) == 0 and rev:
509 - print 'reset %s/%s' % (prefix, ename)
510 -
511 - modified_final = export_files(c.filectx(f) for f in modified)
512 -
513 - print "commit %s/%s" % (prefix, ename)
514 - print "mark :%d" % (marks.get_mark(c.hex()))
515 - print "author %s" % (author)
516 - print "committer %s" % (committer)
517 - print "data %d" % (len(desc))
518 - print desc
519 -
520 - if len(parents) > 0:
521 - print "from :%s" % (rev_to_mark(parents[0]))
522 - if len(parents) > 1:
523 - print "merge :%s" % (rev_to_mark(parents[1]))
524 -
525 - for f in removed:
526 - print "D %s" % (fix_file_path(f))
527 - for f in modified_final:
528 - print "M %s :%u %s" % f
529 - print
530 -
531 - progress = (rev - tip)
532 - if (progress % 100 == 0):
533 - print "progress revision %d '%s' (%d/%d)" % (rev, name, progress, total)
534 -
535 - # make sure the ref is updated
536 - print "reset %s/%s" % (prefix, ename)
537 - print "from :%u" % rev_to_mark(head)
538 - print
539 -
540 - pending_revs = set(revs) - notes
541 - if pending_revs:
542 - note_mark = marks.next_mark()
543 - ref = "refs/notes/hg"
544 -
545 - print "commit %s" % ref
546 - print "mark :%d" % (note_mark)
547 - print "committer remote-hg <> %d %s" % (ptime.time(), gittz(ptime.timezone))
548 - desc = "Notes for %s\n" % (name)
549 - print "data %d" % (len(desc))
550 - print desc
551 - if marks.last_note:
552 - print "from :%u" % marks.last_note
553 -
554 - for rev in pending_revs:
555 - notes.add(rev)
556 - c = repo[rev]
557 - print "N inline :%u" % rev_to_mark(c)
558 - msg = c.hex()
559 - print "data %d" % (len(msg))
560 - print msg
561 - print
562 -
563 - marks.last_note = note_mark
564 -
565 - marks.set_tip(ename, head.hex())
566 -
567 -def export_tag(repo, tag):
568 - export_ref(repo, tag, 'tags', repo[hgref(tag)])
569 -
570 -def export_bookmark(repo, bmark):
571 - head = bmarks[hgref(bmark)]
572 - export_ref(repo, bmark, 'bookmarks', head)
573 -
574 -def export_branch(repo, branch):
575 - tip = get_branch_tip(repo, branch)
576 - head = repo[tip]
577 - export_ref(repo, branch, 'branches', head)
578 -
579 -def export_head(repo):
580 - export_ref(repo, g_head[0], 'bookmarks', g_head[1])
581 -
582 -def do_capabilities(parser):
583 - print "import"
584 - print "export"
585 - print "refspec refs/heads/branches/*:%s/branches/*" % prefix
586 - print "refspec refs/heads/*:%s/bookmarks/*" % prefix
587 - print "refspec refs/tags/*:%s/tags/*" % prefix
588 -
589 - path = os.path.join(dirname, 'marks-git')
590 -
591 - if os.path.exists(path):
592 - print "*import-marks %s" % path
593 - print "*export-marks %s" % path
594 - print "option"
595 -
596 - print
597 -
598 -def branch_tip(branch):
599 - return branches[branch][-1]
600 -
601 -def get_branch_tip(repo, branch):
602 - heads = branches.get(hgref(branch), None)
603 - if not heads:
604 - return None
605 -
606 - # verify there's only one head
607 - if (len(heads) > 1):
608 - warn("Branch '%s' has more than one head, consider merging" % branch)
609 - return branch_tip(hgref(branch))
610 -
611 - return heads[0]
612 -
613 -def list_head(repo, cur):
614 - global g_head, fake_bmark
615 -
616 - if 'default' not in branches:
617 - # empty repo
618 - return
619 -
620 - node = repo[branch_tip('default')]
621 - head = 'master' if not 'master' in bmarks else 'default'
622 - fake_bmark = head
623 - bmarks[head] = node
624 -
625 - head = gitref(head)
626 - print "@refs/heads/%s HEAD" % head
627 - g_head = (head, node)
628 -
629 -def do_list(parser):
630 - repo = parser.repo
631 - for bmark, node in bookmarks.listbookmarks(repo).iteritems():
632 - bmarks[bmark] = repo[node]
633 -
634 - cur = repo.dirstate.branch()
635 - orig = peer if peer else repo
636 -
637 - for branch, heads in orig.branchmap().iteritems():
638 - # only open heads
639 - heads = [h for h in heads if 'close' not in repo.changelog.read(h)[5]]
640 - if heads:
641 - branches[branch] = heads
642 -
643 - list_head(repo, cur)
644 -
645 - if track_branches:
646 - for branch in branches:
647 - print "? refs/heads/branches/%s" % gitref(branch)
648 -
649 - for bmark in bmarks:
650 - if bmarks[bmark].hex() == '0000000000000000000000000000000000000000':
651 - warn("Ignoring invalid bookmark '%s'", bmark)
652 - else:
653 - print "? refs/heads/%s" % gitref(bmark)
654 -
655 - for tag, node in repo.tagslist():
656 - if tag == 'tip':
657 - continue
658 - print "? refs/tags/%s" % gitref(tag)
659 -
660 - print
661 -
662 -def do_import(parser):
663 - repo = parser.repo
664 -
665 - path = os.path.join(dirname, 'marks-git')
666 -
667 - print "feature done"
668 - if os.path.exists(path):
669 - print "feature import-marks=%s" % path
670 - print "feature export-marks=%s" % path
671 - print "feature force"
672 - sys.stdout.flush()
673 -
674 - tmp = encoding.encoding
675 - encoding.encoding = 'utf-8'
676 -
677 - # lets get all the import lines
678 - while parser.check('import'):
679 - ref = parser[1]
680 -
681 - if (ref == 'HEAD'):
682 - export_head(repo)
683 - elif ref.startswith('refs/heads/branches/'):
684 - branch = ref[len('refs/heads/branches/'):]
685 - export_branch(repo, branch)
686 - elif ref.startswith('refs/heads/'):
687 - bmark = ref[len('refs/heads/'):]
688 - export_bookmark(repo, bmark)
689 - elif ref.startswith('refs/tags/'):
690 - tag = ref[len('refs/tags/'):]
691 - export_tag(repo, tag)
692 -
693 - parser.next()
694 -
695 - encoding.encoding = tmp
696 -
697 - print 'done'
698 -
699 -def parse_blob(parser):
700 - parser.next()
701 - mark = parser.get_mark()
702 - parser.next()
703 - data = parser.get_data()
704 - blob_marks[mark] = data
705 - parser.next()
706 -
707 -def get_merge_files(repo, p1, p2, files):
708 - for e in repo[p1].files():
709 - if e not in files:
710 - if e not in repo[p1].manifest():
711 - continue
712 - f = { 'ctx' : repo[p1][e] }
713 - files[e] = f
714 -
715 -def c_style_unescape(string):
716 - if string[0] == string[-1] == '"':
717 - return string.decode('string-escape')[1:-1]
718 - return string
719 -
720 -def parse_commit(parser):
721 - from_mark = merge_mark = None
722 -
723 - ref = parser[1]
724 - parser.next()
725 -
726 - commit_mark = parser.get_mark()
727 - parser.next()
728 - author = parser.get_author()
729 - parser.next()
730 - committer = parser.get_author()
731 - parser.next()
732 - data = parser.get_data()
733 - parser.next()
734 - if parser.check('from'):
735 - from_mark = parser.get_mark()
736 - parser.next()
737 - if parser.check('merge'):
738 - merge_mark = parser.get_mark()
739 - parser.next()
740 - if parser.check('merge'):
741 - die('octopus merges are not supported yet')
742 -
743 - # fast-export adds an extra newline
744 - if data[-1] == '\n':
745 - data = data[:-1]
746 -
747 - files = {}
748 -
749 - for line in parser:
750 - if parser.check('M'):
751 - t, m, mark_ref, path = line.split(' ', 3)
752 - mark = int(mark_ref[1:])
753 - f = { 'mode' : hgmode(m), 'data' : blob_marks[mark] }
754 - elif parser.check('D'):
755 - t, path = line.split(' ', 1)
756 - f = { 'deleted' : True }
757 - else:
758 - die('Unknown file command: %s' % line)
759 - path = c_style_unescape(path)
760 - files[path] = f
761 -
762 - # only export the commits if we are on an internal proxy repo
763 - if dry_run and not peer:
764 - parsed_refs[ref] = None
765 - return
766 -
767 - def getfilectx(repo, memctx, f):
768 - of = files[f]
769 - if 'deleted' in of:
770 - raise IOError
771 - if 'ctx' in of:
772 - return of['ctx']
773 - is_exec = of['mode'] == 'x'
774 - is_link = of['mode'] == 'l'
775 - rename = of.get('rename', None)
776 - return context.memfilectx(f, of['data'],
777 - is_link, is_exec, rename)
778 -
779 - repo = parser.repo
780 -
781 - user, date, tz = author
782 - extra = {}
783 -
784 - if committer != author:
785 - extra['committer'] = "%s %u %u" % committer
786 -
787 - if from_mark:
788 - p1 = mark_to_rev(from_mark)
789 - else:
790 - p1 = '0' * 40
791 -
792 - if merge_mark:
793 - p2 = mark_to_rev(merge_mark)
794 - else:
795 - p2 = '0' * 40
796 -
797 - #
798 - # If files changed from any of the parents, hg wants to know, but in git if
799 - # nothing changed from the first parent, nothing changed.
800 - #
801 - if merge_mark:
802 - get_merge_files(repo, p1, p2, files)
803 -
804 - # Check if the ref is supposed to be a named branch
805 - if ref.startswith('refs/heads/branches/'):
806 - branch = ref[len('refs/heads/branches/'):]
807 - extra['branch'] = hgref(branch)
808 -
809 - if mode == 'hg':
810 - i = data.find('\n--HG--\n')
811 - if i >= 0:
812 - tmp = data[i + len('\n--HG--\n'):].strip()
813 - for k, v in [e.split(' : ', 1) for e in tmp.split('\n')]:
814 - if k == 'rename':
815 - old, new = v.split(' => ', 1)
816 - files[new]['rename'] = old
817 - elif k == 'branch':
818 - extra[k] = v
819 - elif k == 'extra':
820 - ek, ev = v.split(' : ', 1)
821 - extra[ek] = urllib.unquote(ev)
822 - data = data[:i]
823 -
824 - ctx = context.memctx(repo, (p1, p2), data,
825 - files.keys(), getfilectx,
826 - user, (date, tz), extra)
827 -
828 - tmp = encoding.encoding
829 - encoding.encoding = 'utf-8'
830 -
831 - node = hghex(repo.commitctx(ctx))
832 -
833 - encoding.encoding = tmp
834 -
835 - parsed_refs[ref] = node
836 - marks.new_mark(node, commit_mark)
837 -
838 -def parse_reset(parser):
839 - ref = parser[1]
840 - parser.next()
841 - # ugh
842 - if parser.check('commit'):
843 - parse_commit(parser)
844 - return
845 - if not parser.check('from'):
846 - return
847 - from_mark = parser.get_mark()
848 - parser.next()
849 -
850 - try:
851 - rev = mark_to_rev(from_mark)
852 - except KeyError:
853 - rev = None
854 - parsed_refs[ref] = rev
855 -
856 -def parse_tag(parser):
857 - name = parser[1]
858 - parser.next()
859 - from_mark = parser.get_mark()
860 - parser.next()
861 - tagger = parser.get_author()
862 - parser.next()
863 - data = parser.get_data()
864 - parser.next()
865 -
866 - parsed_tags[name] = (tagger, data)
867 -
868 -def write_tag(repo, tag, node, msg, author):
869 - branch = repo[node].branch()
870 - tip = branch_tip(branch)
871 - tip = repo[tip]
872 -
873 - def getfilectx(repo, memctx, f):
874 - try:
875 - fctx = tip.filectx(f)
876 - data = fctx.data()
877 - except error.ManifestLookupError:
878 - data = ""
879 - content = data + "%s %s\n" % (node, tag)
880 - return context.memfilectx(f, content, False, False, None)
881 -
882 - p1 = tip.hex()
883 - p2 = '0' * 40
884 - if author:
885 - user, date, tz = author
886 - date_tz = (date, tz)
887 - else:
888 - cmd = ['git', 'var', 'GIT_COMMITTER_IDENT']
889 - process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
890 - output, _ = process.communicate()
891 - m = re.match('^.* <.*>', output)
892 - if m:
893 - user = m.group(0)
894 - else:
895 - user = repo.ui.username()
896 - date_tz = None
897 -
898 - ctx = context.memctx(repo, (p1, p2), msg,
899 - ['.hgtags'], getfilectx,
900 - user, date_tz, {'branch' : branch})
901 -
902 - tmp = encoding.encoding
903 - encoding.encoding = 'utf-8'
904 -
905 - tagnode = repo.commitctx(ctx)
906 -
907 - encoding.encoding = tmp
908 -
909 - return (tagnode, branch)
910 -
911 -def checkheads_bmark(repo, ref, ctx):
912 - bmark = ref[len('refs/heads/'):]
913 - if not bmark in bmarks:
914 - # new bmark
915 - return True
916 -
917 - ctx_old = bmarks[bmark]
918 - ctx_new = ctx
919 - if not repo.changelog.descendant(ctx_old.rev(), ctx_new.rev()):
920 - if force_push:
921 - print "ok %s forced update" % ref
922 - else:
923 - print "error %s non-fast forward" % ref
924 - return False
925 -
926 - return True
927 -
928 -def checkheads(repo, remote, p_revs):
929 -
930 - remotemap = remote.branchmap()
931 - if not remotemap:
932 - # empty repo
933 - return True
934 -
935 - new = {}
936 - ret = True
937 -
938 - for node, ref in p_revs.iteritems():
939 - ctx = repo[node]
940 - branch = ctx.branch()
941 - if not branch in remotemap:
942 - # new branch
943 - continue
944 - if not ref.startswith('refs/heads/branches'):
945 - if ref.startswith('refs/heads/'):
946 - if not checkheads_bmark(repo, ref, ctx):
947 - ret = False
948 -
949 - # only check branches
950 - continue
951 - new.setdefault(branch, []).append(ctx.rev())
952 -
953 - for branch, heads in new.iteritems():
954 - old = [repo.changelog.rev(x) for x in remotemap[branch]]
955 - for rev in heads:
956 - if check_version(2, 3):
957 - ancestors = repo.changelog.ancestors([rev], stoprev=min(old))
958 - else:
959 - ancestors = repo.changelog.ancestors(rev)
960 - found = False
961 -
962 - for x in old:
963 - if x in ancestors:
964 - found = True
965 - break
966 -
967 - if found:
968 - continue
969 -
970 - node = repo.changelog.node(rev)
971 - ref = p_revs[node]
972 - if force_push:
973 - print "ok %s forced update" % ref
974 - else:
975 - print "error %s non-fast forward" % ref
976 - ret = False
977 -
978 - return ret
979 -
980 -def push_unsafe(repo, remote, parsed_refs, p_revs):
981 -
982 - force = force_push
983 -
984 - fci = discovery.findcommonincoming
985 - commoninc = fci(repo, remote, force=force)
986 - common, _, remoteheads = commoninc
987 -
988 - if not checkheads(repo, remote, p_revs):
989 - return None
990 -
991 - cg = repo.getbundle('push', heads=list(p_revs), common=common)
992 -
993 - unbundle = remote.capable('unbundle')
994 - if unbundle:
995 - if force:
996 - remoteheads = ['force']
997 - return remote.unbundle(cg, remoteheads, 'push')
998 - else:
999 - return remote.addchangegroup(cg, 'push', repo.url())
1000 -
1001 -def push(repo, remote, parsed_refs, p_revs):
1002 - if hasattr(remote, 'canpush') and not remote.canpush():
1003 - print "error cannot push"
1004 -
1005 - if not p_revs:
1006 - # nothing to push
1007 - return
1008 -
1009 - lock = None
1010 - unbundle = remote.capable('unbundle')
1011 - if not unbundle:
1012 - lock = remote.lock()
1013 - try:
1014 - ret = push_unsafe(repo, remote, parsed_refs, p_revs)
1015 - finally:
1016 - if lock is not None:
1017 - lock.release()
1018 -
1019 - return ret
1020 -
1021 -def check_tip(ref, kind, name, heads):
1022 - try:
1023 - ename = '%s/%s' % (kind, name)
1024 - tip = marks.get_tip(ename)
1025 - except KeyError:
1026 - return True
1027 - else:
1028 - return tip in heads
1029 -
1030 -def do_export(parser):
1031 - p_bmarks = []
1032 - p_revs = {}
1033 -
1034 - parser.next()
1035 -
1036 - for line in parser.each_block('done'):
1037 - if parser.check('blob'):
1038 - parse_blob(parser)
1039 - elif parser.check('commit'):
1040 - parse_commit(parser)
1041 - elif parser.check('reset'):
1042 - parse_reset(parser)
1043 - elif parser.check('tag'):
1044 - parse_tag(parser)
1045 - elif parser.check('feature'):
1046 - pass
1047 - else:
1048 - die('unhandled export command: %s' % line)
1049 -
1050 - need_fetch = False
1051 -
1052 - for ref, node in parsed_refs.iteritems():
1053 - bnode = hgbin(node) if node else None
1054 - if ref.startswith('refs/heads/branches'):
1055 - branch = ref[len('refs/heads/branches/'):]
1056 - if branch in branches and bnode in branches[branch]:
1057 - # up to date
1058 - continue
1059 -
1060 - if peer:
1061 - remotemap = peer.branchmap()
1062 - if remotemap and branch in remotemap:
1063 - heads = [hghex(e) for e in remotemap[branch]]
1064 - if not check_tip(ref, 'branches', branch, heads):
1065 - print "error %s fetch first" % ref
1066 - need_fetch = True
1067 - continue
1068 -
1069 - p_revs[bnode] = ref
1070 - print "ok %s" % ref
1071 - elif ref.startswith('refs/heads/'):
1072 - bmark = ref[len('refs/heads/'):]
1073 - new = node
1074 - old = bmarks[bmark].hex() if bmark in bmarks else ''
1075 -
1076 - if old == new:
1077 - continue
1078 -
1079 - print "ok %s" % ref
1080 - if bmark != fake_bmark and \
1081 - not (bmark == 'master' and bmark not in parser.repo._bookmarks):
1082 - p_bmarks.append((ref, bmark, old, new))
1083 -
1084 - if peer:
1085 - remote_old = peer.listkeys('bookmarks').get(bmark)
1086 - if remote_old:
1087 - if not check_tip(ref, 'bookmarks', bmark, remote_old):
1088 - print "error %s fetch first" % ref
1089 - need_fetch = True
1090 - continue
1091 -
1092 - p_revs[bnode] = ref
1093 - elif ref.startswith('refs/tags/'):
1094 - if dry_run:
1095 - print "ok %s" % ref
1096 - continue
1097 - tag = ref[len('refs/tags/'):]
1098 - tag = hgref(tag)
1099 - author, msg = parsed_tags.get(tag, (None, None))
1100 - if mode == 'git':
1101 - if not msg:
1102 - msg = 'Added tag %s for changeset %s' % (tag, node[:12])
1103 - tagnode, branch = write_tag(parser.repo, tag, node, msg, author)
1104 - p_revs[tagnode] = 'refs/heads/branches/' + gitref(branch)
1105 - else:
1106 - fp = parser.repo.opener('localtags', 'a')
1107 - fp.write('%s %s\n' % (node, tag))
1108 - fp.close()
1109 - p_revs[bnode] = ref
1110 - print "ok %s" % ref
1111 - else:
1112 - # transport-helper/fast-export bugs
1113 - continue
1114 -
1115 - if need_fetch:
1116 - print
1117 - return
1118 -
1119 - if dry_run:
1120 - if peer and not force_push:
1121 - checkheads(parser.repo, peer, p_revs)
1122 - print
1123 - return
1124 -
1125 - if peer:
1126 - if not push(parser.repo, peer, parsed_refs, p_revs):
1127 - # do not update bookmarks
1128 - print
1129 - return
1130 -
1131 - # update remote bookmarks
1132 - remote_bmarks = peer.listkeys('bookmarks')
1133 - for ref, bmark, old, new in p_bmarks:
1134 - if force_push:
1135 - old = remote_bmarks.get(bmark, '')
1136 - if not peer.pushkey('bookmarks', bmark, old, new):
1137 - print "error %s" % ref
1138 - else:
1139 - # update local bookmarks
1140 - for ref, bmark, old, new in p_bmarks:
1141 - if not bookmarks.pushbookmark(parser.repo, bmark, old, new):
1142 - print "error %s" % ref
1143 -
1144 - print
1145 -
1146 -def do_option(parser):
1147 - global dry_run, force_push
1148 - _, key, value = parser.line.split(' ')
1149 - if key == 'dry-run':
1150 - dry_run = (value == 'true')
1151 - print 'ok'
1152 - elif key == 'force':
1153 - force_push = (value == 'true')
1154 - print 'ok'
1155 - else:
1156 - print 'unsupported'
1157 -
1158 -def fix_path(alias, repo, orig_url):
1159 - url = urlparse.urlparse(orig_url, 'file')
1160 - if url.scheme != 'file' or os.path.isabs(os.path.expanduser(url.path)):
1161 - return
1162 - abs_url = urlparse.urljoin("%s/" % os.getcwd(), orig_url)
1163 - cmd = ['git', 'config', 'remote.%s.url' % alias, "hg::%s" % abs_url]
1164 - subprocess.call(cmd)
1165 -
1166 -def main(args):
1167 - global prefix, gitdir, dirname, branches, bmarks
1168 - global marks, blob_marks, parsed_refs
1169 - global peer, mode, bad_mail, bad_name
1170 - global track_branches, force_push, is_tmp
1171 - global parsed_tags
1172 - global filenodes
1173 - global fake_bmark, hg_version
1174 - global dry_run
1175 - global notes, alias
1176 -
1177 - marks = None
1178 - is_tmp = False
1179 - gitdir = os.environ.get('GIT_DIR', None)
1180 -
1181 - if len(args) < 3:
1182 - die('Not enough arguments.')
1183 -
1184 - if not gitdir:
1185 - die('GIT_DIR not set')
1186 -
1187 - alias = args[1]
1188 - url = args[2]
1189 - peer = None
1190 -
1191 - hg_git_compat = get_config_bool('remote-hg.hg-git-compat')
1192 - track_branches = get_config_bool('remote-hg.track-branches', True)
1193 - force_push = False
1194 -
1195 - if hg_git_compat:
1196 - mode = 'hg'
1197 - bad_mail = 'none@none'
1198 - bad_name = ''
1199 - else:
1200 - mode = 'git'
1201 - bad_mail = 'unknown'
1202 - bad_name = 'Unknown'
1203 -
1204 - if alias[4:] == url:
1205 - is_tmp = True
1206 - alias = hashlib.sha1(alias).hexdigest()
1207 -
1208 - dirname = os.path.join(gitdir, 'hg', alias)
1209 - branches = {}
1210 - bmarks = {}
1211 - blob_marks = {}
1212 - parsed_refs = {}
1213 - parsed_tags = {}
1214 - filenodes = {}
1215 - fake_bmark = None
1216 - try:
1217 - hg_version = tuple(int(e) for e in util.version().split('.'))
1218 - except:
1219 - hg_version = None
1220 - dry_run = False
1221 - notes = set()
1222 -
1223 - repo = get_repo(url, alias)
1224 - prefix = 'refs/hg/%s' % alias
1225 -
1226 - if not is_tmp:
1227 - fix_path(alias, peer or repo, url)
1228 -
1229 - marks_path = os.path.join(dirname, 'marks-hg')
1230 - marks = Marks(marks_path, repo)
1231 -
1232 - if sys.platform == 'win32':
1233 - import msvcrt
1234 - msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
1235 -
1236 - parser = Parser(repo)
1237 - for line in parser:
1238 - if parser.check('capabilities'):
1239 - do_capabilities(parser)
1240 - elif parser.check('list'):
1241 - do_list(parser)
1242 - elif parser.check('import'):
1243 - do_import(parser)
1244 - elif parser.check('export'):
1245 - do_export(parser)
1246 - elif parser.check('option'):
1247 - do_option(parser)
1248 - else:
1249 - die('unhandled command: %s' % line)
1250 - sys.stdout.flush()
1251 -
1252 -def bye():
1253 - if not marks:
1254 - return
1255 - if not is_tmp:
1256 - marks.store()
1257 - else:
1258 - shutil.rmtree(dirname)
1259 -
1260 -atexit.register(bye)
1261 -sys.exit(main(sys.argv))
8 +sys.stderr.write('''WARNING:
9 +WARNING: You can pick a directory on your $PATH and download it, e.g.:
10 +WARNING: $ wget -O $HOME/bin/git-remote-hg \\
11 +WARNING: https://raw.github.com/felipec/git-remote-hg/master/git-remote-hg
12 +WARNING: $ chmod +x $HOME/bin/git-remote-hg
13 +''')
contrib/remote-helpers/test-bzr.sh deleted
-438
@@ -1,438 +0,0 @@
1 -#!/bin/sh
2 -#
3 -# Copyright (c) 2012 Felipe Contreras
4 -#
5 -
6 -test_description='Test remote-bzr'
7 -
8 -test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=${0%/*}/../../t
9 -. "$TEST_DIRECTORY"/test-lib.sh
10 -
11 -if ! test_have_prereq PYTHON
12 -then
13 - skip_all='skipping remote-bzr tests; python not available'
14 - test_done
15 -fi
16 -
17 -if ! python -c 'import bzrlib'
18 -then
19 - skip_all='skipping remote-bzr tests; bzr not available'
20 - test_done
21 -fi
22 -
23 -check () {
24 - echo $3 >expected &&
25 - git --git-dir=$1/.git log --format='%s' -1 $2 >actual
26 - test_cmp expected actual
27 -}
28 -
29 -bzr whoami "A U Thor <author@example.com>"
30 -
31 -test_expect_success 'cloning' '
32 - (
33 - bzr init bzrrepo &&
34 - cd bzrrepo &&
35 - echo one >content &&
36 - bzr add content &&
37 - bzr commit -m one
38 - ) &&
39 -
40 - git clone "bzr::bzrrepo" gitrepo &&
41 - check gitrepo HEAD one
42 -'
43 -
44 -test_expect_success 'pulling' '
45 - (
46 - cd bzrrepo &&
47 - echo two >content &&
48 - bzr commit -m two
49 - ) &&
50 -
51 - (cd gitrepo && git pull) &&
52 -
53 - check gitrepo HEAD two
54 -'
55 -
56 -test_expect_success 'pushing' '
57 - (
58 - cd gitrepo &&
59 - echo three >content &&
60 - git commit -a -m three &&
61 - git push
62 - ) &&
63 -
64 - echo three >expected &&
65 - cat bzrrepo/content >actual &&
66 - test_cmp expected actual
67 -'
68 -
69 -test_expect_success 'forced pushing' '
70 - (
71 - cd gitrepo &&
72 - echo three-new >content &&
73 - git commit -a --amend -m three-new &&
74 - git push -f
75 - ) &&
76 -
77 - (
78 - cd bzrrepo &&
79 - # the forced update overwrites the bzr branch but not the bzr
80 - # working directory (it tries to merge instead)
81 - bzr revert
82 - ) &&
83 -
84 - echo three-new >expected &&
85 - cat bzrrepo/content >actual &&
86 - test_cmp expected actual
87 -'
88 -
89 -test_expect_success 'roundtrip' '
90 - (
91 - cd gitrepo &&
92 - git pull &&
93 - git log --format="%s" -1 origin/master >actual
94 - ) &&
95 - echo three-new >expected &&
96 - test_cmp expected actual &&
97 -
98 - (cd gitrepo && git push && git pull) &&
99 -
100 - (
101 - cd bzrrepo &&
102 - echo four >content &&
103 - bzr commit -m four
104 - ) &&
105 -
106 - (cd gitrepo && git pull && git push) &&
107 -
108 - check gitrepo HEAD four &&
109 -
110 - (
111 - cd gitrepo &&
112 - echo five >content &&
113 - git commit -a -m five &&
114 - git push && git pull
115 - ) &&
116 -
117 - (cd bzrrepo && bzr revert) &&
118 -
119 - echo five >expected &&
120 - cat bzrrepo/content >actual &&
121 - test_cmp expected actual
122 -'
123 -
124 -cat >expected <<\EOF
125 -100644 blob 54f9d6da5c91d556e6b54340b1327573073030af content
126 -100755 blob 68769579c3eaadbe555379b9c3538e6628bae1eb executable
127 -120000 blob 6b584e8ece562ebffc15d38808cd6b98fc3d97ea link
128 -EOF
129 -
130 -test_expect_success 'special modes' '
131 - (
132 - cd bzrrepo &&
133 - echo exec >executable
134 - chmod +x executable &&
135 - bzr add executable
136 - bzr commit -m exec &&
137 - ln -s content link
138 - bzr add link
139 - bzr commit -m link &&
140 - mkdir dir &&
141 - bzr add dir &&
142 - bzr commit -m dir
143 - ) &&
144 -
145 - (
146 - cd gitrepo &&
147 - git pull
148 - git ls-tree HEAD >../actual
149 - ) &&
150 -
151 - test_cmp expected actual &&
152 -
153 - (
154 - cd gitrepo &&
155 - git cat-file -p HEAD:link >../actual
156 - ) &&
157 -
158 - printf content >expected &&
159 - test_cmp expected actual
160 -'
161 -
162 -cat >expected <<\EOF
163 -100644 blob 54f9d6da5c91d556e6b54340b1327573073030af content
164 -100755 blob 68769579c3eaadbe555379b9c3538e6628bae1eb executable
165 -120000 blob 6b584e8ece562ebffc15d38808cd6b98fc3d97ea link
166 -040000 tree 35c0caa46693cef62247ac89a680f0c5ce32b37b movedir-new
167 -EOF
168 -
169 -test_expect_success 'moving directory' '
170 - (
171 - cd bzrrepo &&
172 - mkdir movedir &&
173 - echo one >movedir/one &&
174 - echo two >movedir/two &&
175 - bzr add movedir &&
176 - bzr commit -m movedir &&
177 - bzr mv movedir movedir-new &&
178 - bzr commit -m movedir-new
179 - ) &&
180 -
181 - (
182 - cd gitrepo &&
183 - git pull &&
184 - git ls-tree HEAD >../actual
185 - ) &&
186 -
187 - test_cmp expected actual
188 -'
189 -
190 -test_expect_success 'different authors' '
191 - (
192 - cd bzrrepo &&
193 - echo john >>content &&
194 - bzr commit -m john \
195 - --author "Jane Rey <jrey@example.com>" \
196 - --author "John Doe <jdoe@example.com>"
197 - ) &&
198 -
199 - (
200 - cd gitrepo &&
201 - git pull &&
202 - git show --format="%an <%ae>, %cn <%ce>" --quiet >../actual
203 - ) &&
204 -
205 - echo "Jane Rey <jrey@example.com>, A U Thor <author@example.com>" >expected &&
206 - test_cmp expected actual
207 -'
208 -
209 -# cleanup previous stuff
210 -rm -rf bzrrepo gitrepo
211 -
212 -test_expect_success 'fetch utf-8 filenames' '
213 - test_when_finished "rm -rf bzrrepo gitrepo && LC_ALL=C" &&
214 -
215 - LC_ALL=en_US.UTF-8
216 - export LC_ALL
217 -
218 - (
219 - bzr init bzrrepo &&
220 - cd bzrrepo &&
221 -
222 - echo test >>"ærø" &&
223 - bzr add "ærø" &&
224 - echo test >>"ø~?" &&
225 - bzr add "ø~?" &&
226 - bzr commit -m add-utf-8 &&
227 - echo test >>"ærø" &&
228 - bzr commit -m test-utf-8 &&
229 - bzr rm "ø~?" &&
230 - bzr mv "ærø" "ø~?" &&
231 - bzr commit -m bzr-mv-utf-8
232 - ) &&
233 -
234 - (
235 - git clone "bzr::bzrrepo" gitrepo &&
236 - cd gitrepo &&
237 - git -c core.quotepath=false ls-files >../actual
238 - ) &&
239 - echo "ø~?" >expected &&
240 - test_cmp expected actual
241 -'
242 -
243 -test_expect_success 'push utf-8 filenames' '
244 - test_when_finished "rm -rf bzrrepo gitrepo && LC_ALL=C" &&
245 -
246 - mkdir -p tmp && cd tmp &&
247 -
248 - LC_ALL=en_US.UTF-8
249 - export LC_ALL
250 -
251 - (
252 - bzr init bzrrepo &&
253 - cd bzrrepo &&
254 -
255 - echo one >>content &&
256 - bzr add content &&
257 - bzr commit -m one
258 - ) &&
259 -
260 - (
261 - git clone "bzr::bzrrepo" gitrepo &&
262 - cd gitrepo &&
263 -
264 - echo test >>"ærø" &&
265 - git add "ærø" &&
266 - git commit -m utf-8 &&
267 -
268 - git push
269 - ) &&
270 -
271 - (cd bzrrepo && bzr ls >../actual) &&
272 - printf "content\nærø\n" >expected &&
273 - test_cmp expected actual
274 -'
275 -
276 -test_expect_success 'pushing a merge' '
277 - test_when_finished "rm -rf bzrrepo gitrepo" &&
278 -
279 - (
280 - bzr init bzrrepo &&
281 - cd bzrrepo &&
282 - echo one >content &&
283 - bzr add content &&
284 - bzr commit -m one
285 - ) &&
286 -
287 - git clone "bzr::bzrrepo" gitrepo &&
288 -
289 - (
290 - cd bzrrepo &&
291 - echo two >content &&
292 - bzr commit -m two
293 - ) &&
294 -
295 - (
296 - cd gitrepo &&
297 - echo three >content &&
298 - git commit -a -m three &&
299 - git fetch &&
300 - git merge origin/master || true &&
301 - echo three >content &&
302 - git commit -a --no-edit &&
303 - git push
304 - ) &&
305 -
306 - echo three >expected &&
307 - cat bzrrepo/content >actual &&
308 - test_cmp expected actual
309 -'
310 -
311 -cat >expected <<\EOF
312 -origin/HEAD
313 -origin/branch
314 -origin/trunk
315 -EOF
316 -
317 -test_expect_success 'proper bzr repo' '
318 - test_when_finished "rm -rf bzrrepo gitrepo" &&
319 -
320 - bzr init-repo bzrrepo &&
321 -
322 - (
323 - bzr init bzrrepo/trunk &&
324 - cd bzrrepo/trunk &&
325 - echo one >>content &&
326 - bzr add content &&
327 - bzr commit -m one
328 - ) &&
329 -
330 - (
331 - bzr branch bzrrepo/trunk bzrrepo/branch &&
332 - cd bzrrepo/branch &&
333 - echo two >>content &&
334 - bzr commit -m one
335 - ) &&
336 -
337 - (
338 - git clone "bzr::bzrrepo" gitrepo &&
339 - cd gitrepo &&
340 - git for-each-ref --format "%(refname:short)" refs/remotes/origin >../actual
341 - ) &&
342 -
343 - test_cmp expected actual
344 -'
345 -
346 -test_expect_success 'strip' '
347 - test_when_finished "rm -rf bzrrepo gitrepo" &&
348 -
349 - (
350 - bzr init bzrrepo &&
351 - cd bzrrepo &&
352 -
353 - echo one >>content &&
354 - bzr add content &&
355 - bzr commit -m one &&
356 -
357 - echo two >>content &&
358 - bzr commit -m two
359 - ) &&
360 -
361 - git clone "bzr::bzrrepo" gitrepo &&
362 -
363 - (
364 - cd bzrrepo &&
365 - bzr uncommit --force &&
366 -
367 - echo three >>content &&
368 - bzr commit -m three &&
369 -
370 - echo four >>content &&
371 - bzr commit -m four &&
372 - bzr log --line | sed -e "s/^[0-9][0-9]*: //" >../expected
373 - ) &&
374 -
375 - (
376 - cd gitrepo &&
377 - git fetch &&
378 - git log --format="%an %ad %s" --date=short origin/master >../actual
379 - ) &&
380 -
381 - test_cmp expected actual
382 -'
383 -
384 -test_expect_success 'export utf-8 authors' '
385 - test_when_finished "rm -rf bzrrepo gitrepo && LC_ALL=C && GIT_COMMITTER_NAME=\"C O Mitter\""
386 -
387 - LC_ALL=en_US.UTF-8
388 - export LC_ALL
389 -
390 - GIT_COMMITTER_NAME="Grégoire"
391 - export GIT_COMMITTER_NAME
392 -
393 - bzr init bzrrepo &&
394 -
395 - (
396 - git init gitrepo &&
397 - cd gitrepo &&
398 - echo greg >>content &&
399 - git add content &&
400 - git commit -m one &&
401 - git remote add bzr "bzr::../bzrrepo" &&
402 - git push bzr master
403 - ) &&
404 -
405 - (
406 - cd bzrrepo &&
407 - bzr log | grep "^committer: " >../actual
408 - ) &&
409 -
410 - echo "committer: Grégoire <committer@example.com>" >expected &&
411 - test_cmp expected actual
412 -'
413 -
414 -test_expect_success 'push different author' '
415 - test_when_finished "rm -rf bzrrepo gitrepo" &&
416 -
417 - bzr init bzrrepo &&
418 -
419 - (
420 - git init gitrepo &&
421 - cd gitrepo &&
422 - echo john >> content &&
423 - git add content &&
424 - git commit -m john --author "John Doe <jdoe@example.com>" &&
425 - git remote add bzr "bzr::../bzrrepo" &&
426 - git push bzr master
427 - ) &&
428 -
429 - (
430 - cd bzrrepo &&
431 - bzr log | grep "^author: " > ../actual
432 - ) &&
433 -
434 - echo "author: John Doe <jdoe@example.com>" > expected &&
435 - test_cmp expected actual
436 -'
437 -
438 -test_done
contrib/remote-helpers/test-hg-bidi.sh deleted
-243
@@ -1,243 +0,0 @@
1 -#!/bin/sh
2 -#
3 -# Copyright (c) 2012 Felipe Contreras
4 -#
5 -# Base commands from hg-git tests:
6 -# https://bitbucket.org/durin42/hg-git/src
7 -#
8 -
9 -test_description='Test bidirectionality of remote-hg'
10 -
11 -test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=${0%/*}/../../t
12 -. "$TEST_DIRECTORY"/test-lib.sh
13 -
14 -if ! test_have_prereq PYTHON
15 -then
16 - skip_all='skipping remote-hg tests; python not available'
17 - test_done
18 -fi
19 -
20 -if ! python -c 'import mercurial'
21 -then
22 - skip_all='skipping remote-hg tests; mercurial not available'
23 - test_done
24 -fi
25 -
26 -# clone to a git repo
27 -git_clone () {
28 - git clone -q "hg::$1" $2
29 -}
30 -
31 -# clone to an hg repo
32 -hg_clone () {
33 - (
34 - hg init $2 &&
35 - cd $1 &&
36 - git push -q "hg::../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
37 - ) &&
38 -
39 - (cd $2 && hg -q update)
40 -}
41 -
42 -# push an hg repo
43 -hg_push () {
44 - (
45 - cd $2
46 - git checkout -q -b tmp &&
47 - git fetch -q "hg::../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
48 - git checkout -q @{-1} &&
49 - git branch -q -D tmp 2>/dev/null || true
50 - )
51 -}
52 -
53 -hg_log () {
54 - hg -R $1 log --graph --debug
55 -}
56 -
57 -setup () {
58 - (
59 - echo "[ui]"
60 - echo "username = A U Thor <author@example.com>"
61 - echo "[defaults]"
62 - echo "backout = -d \"0 0\""
63 - echo "commit = -d \"0 0\""
64 - echo "debugrawcommit = -d \"0 0\""
65 - echo "tag = -d \"0 0\""
66 - echo "[extensions]"
67 - echo "graphlog ="
68 - ) >>"$HOME"/.hgrc &&
69 - git config --global remote-hg.hg-git-compat true
70 - git config --global remote-hg.track-branches true
71 -
72 - HGEDITOR=/usr/bin/true
73 - GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
74 - GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
75 - export HGEDITOR GIT_AUTHOR_DATE GIT_COMMITTER_DATE
76 -}
77 -
78 -setup
79 -
80 -test_expect_success 'encoding' '
81 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
82 -
83 - (
84 - git init -q gitrepo &&
85 - cd gitrepo &&
86 -
87 - echo alpha >alpha &&
88 - git add alpha &&
89 - git commit -m "add älphà" &&
90 -
91 - GIT_AUTHOR_NAME="tést èncödîng" &&
92 - export GIT_AUTHOR_NAME &&
93 - echo beta >beta &&
94 - git add beta &&
95 - git commit -m "add beta" &&
96 -
97 - echo gamma >gamma &&
98 - git add gamma &&
99 - git commit -m "add gämmâ" &&
100 -
101 - : TODO git config i18n.commitencoding latin-1 &&
102 - echo delta >delta &&
103 - git add delta &&
104 - git commit -m "add déltà"
105 - ) &&
106 -
107 - hg_clone gitrepo hgrepo &&
108 - git_clone hgrepo gitrepo2 &&
109 - hg_clone gitrepo2 hgrepo2 &&
110 -
111 - HGENCODING=utf-8 hg_log hgrepo >expected &&
112 - HGENCODING=utf-8 hg_log hgrepo2 >actual &&
113 -
114 - test_cmp expected actual
115 -'
116 -
117 -test_expect_success 'file removal' '
118 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
119 -
120 - (
121 - git init -q gitrepo &&
122 - cd gitrepo &&
123 - echo alpha >alpha &&
124 - git add alpha &&
125 - git commit -m "add alpha" &&
126 - echo beta >beta &&
127 - git add beta &&
128 - git commit -m "add beta"
129 - mkdir foo &&
130 - echo blah >foo/bar &&
131 - git add foo &&
132 - git commit -m "add foo" &&
133 - git rm alpha &&
134 - git commit -m "remove alpha" &&
135 - git rm foo/bar &&
136 - git commit -m "remove foo/bar"
137 - ) &&
138 -
139 - hg_clone gitrepo hgrepo &&
140 - git_clone hgrepo gitrepo2 &&
141 - hg_clone gitrepo2 hgrepo2 &&
142 -
143 - hg_log hgrepo >expected &&
144 - hg_log hgrepo2 >actual &&
145 -
146 - test_cmp expected actual
147 -'
148 -
149 -test_expect_success 'git tags' '
150 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
151 -
152 - (
153 - git init -q gitrepo &&
154 - cd gitrepo &&
155 - git config receive.denyCurrentBranch ignore &&
156 - echo alpha >alpha &&
157 - git add alpha &&
158 - git commit -m "add alpha" &&
159 - git tag alpha &&
160 -
161 - echo beta >beta &&
162 - git add beta &&
163 - git commit -m "add beta" &&
164 - git tag -a -m "added tag beta" beta
165 - ) &&
166 -
167 - hg_clone gitrepo hgrepo &&
168 - git_clone hgrepo gitrepo2 &&
169 - hg_clone gitrepo2 hgrepo2 &&
170 -
171 - hg_log hgrepo >expected &&
172 - hg_log hgrepo2 >actual &&
173 -
174 - test_cmp expected actual
175 -'
176 -
177 -test_expect_success 'hg branch' '
178 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
179 -
180 - (
181 - git init -q gitrepo &&
182 - cd gitrepo &&
183 -
184 - echo alpha >alpha &&
185 - git add alpha &&
186 - git commit -q -m "add alpha" &&
187 - git checkout -q -b not-master
188 - ) &&
189 -
190 - (
191 - hg_clone gitrepo hgrepo &&
192 -
193 - cd hgrepo &&
194 - hg -q co default &&
195 - hg mv alpha beta &&
196 - hg -q commit -m "rename alpha to beta" &&
197 - hg branch gamma | grep -v "permanent and global" &&
198 - hg -q commit -m "started branch gamma"
199 - ) &&
200 -
201 - hg_push hgrepo gitrepo &&
202 - hg_clone gitrepo hgrepo2 &&
203 -
204 - : Back to the common revision &&
205 - (cd hgrepo && hg checkout default) &&
206 -
207 - hg_log hgrepo >expected &&
208 - hg_log hgrepo2 >actual &&
209 -
210 - test_cmp expected actual
211 -'
212 -
213 -test_expect_success 'hg tags' '
214 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
215 -
216 - (
217 - git init -q gitrepo &&
218 - cd gitrepo &&
219 -
220 - echo alpha >alpha &&
221 - git add alpha &&
222 - git commit -m "add alpha" &&
223 - git checkout -q -b not-master
224 - ) &&
225 -
226 - (
227 - hg_clone gitrepo hgrepo &&
228 -
229 - cd hgrepo &&
230 - hg co default &&
231 - hg tag alpha
232 - ) &&
233 -
234 - hg_push hgrepo gitrepo &&
235 - hg_clone gitrepo hgrepo2 &&
236 -
237 - hg_log hgrepo >expected &&
238 - hg_log hgrepo2 >actual &&
239 -
240 - test_cmp expected actual
241 -'
242 -
243 -test_done
contrib/remote-helpers/test-hg-hg-git.sh deleted
-542
@@ -1,542 +0,0 @@
1 -#!/bin/sh
2 -#
3 -# Copyright (c) 2012 Felipe Contreras
4 -#
5 -# Base commands from hg-git tests:
6 -# https://bitbucket.org/durin42/hg-git/src
7 -#
8 -
9 -test_description='Test remote-hg output compared to hg-git'
10 -
11 -test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=${0%/*}/../../t
12 -. "$TEST_DIRECTORY"/test-lib.sh
13 -
14 -if ! test_have_prereq PYTHON
15 -then
16 - skip_all='skipping remote-hg tests; python not available'
17 - test_done
18 -fi
19 -
20 -if ! python -c 'import mercurial'
21 -then
22 - skip_all='skipping remote-hg tests; mercurial not available'
23 - test_done
24 -fi
25 -
26 -if ! python -c 'import hggit'
27 -then
28 - skip_all='skipping remote-hg tests; hg-git not available'
29 - test_done
30 -fi
31 -
32 -# clone to a git repo with git
33 -git_clone_git () {
34 - git clone -q "hg::$1" $2 &&
35 - (cd $2 && git checkout master && git branch -D default)
36 -}
37 -
38 -# clone to an hg repo with git
39 -hg_clone_git () {
40 - (
41 - hg init $2 &&
42 - hg -R $2 bookmark -i master &&
43 - cd $1 &&
44 - git push -q "hg::../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
45 - ) &&
46 -
47 - (cd $2 && hg -q update)
48 -}
49 -
50 -# clone to a git repo with hg
51 -git_clone_hg () {
52 - (
53 - git init -q $2 &&
54 - cd $1 &&
55 - hg bookmark -i -f -r tip master &&
56 - hg -q push -r master ../$2 || true
57 - )
58 -}
59 -
60 -# clone to an hg repo with hg
61 -hg_clone_hg () {
62 - hg -q clone $1 $2
63 -}
64 -
65 -# push an hg repo with git
66 -hg_push_git () {
67 - (
68 - cd $2
69 - git checkout -q -b tmp &&
70 - git fetch -q "hg::../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
71 - git branch -D default &&
72 - git checkout -q @{-1} &&
73 - git branch -q -D tmp 2>/dev/null || true
74 - )
75 -}
76 -
77 -# push an hg git repo with hg
78 -hg_push_hg () {
79 - (
80 - cd $1 &&
81 - hg -q push ../$2 || true
82 - )
83 -}
84 -
85 -hg_log () {
86 - hg -R $1 log --graph --debug >log &&
87 - grep -v 'tag: *default/' log
88 -}
89 -
90 -git_log () {
91 - git --git-dir=$1/.git fast-export --branches
92 -}
93 -
94 -setup () {
95 - (
96 - echo "[ui]"
97 - echo "username = A U Thor <author@example.com>"
98 - echo "[defaults]"
99 - echo "backout = -d \"0 0\""
100 - echo "commit = -d \"0 0\""
101 - echo "debugrawcommit = -d \"0 0\""
102 - echo "tag = -d \"0 0\""
103 - echo "[extensions]"
104 - echo "hgext.bookmarks ="
105 - echo "hggit ="
106 - echo "graphlog ="
107 - ) >>"$HOME"/.hgrc &&
108 - git config --global receive.denycurrentbranch warn
109 - git config --global remote-hg.hg-git-compat true
110 - git config --global remote-hg.track-branches false
111 -
112 - HGEDITOR=true
113 - HGMERGE=true
114 -
115 - GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
116 - GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
117 - export HGEDITOR HGMERGE GIT_AUTHOR_DATE GIT_COMMITTER_DATE
118 -}
119 -
120 -setup
121 -
122 -test_expect_success 'executable bit' '
123 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
124 -
125 - (
126 - git init -q gitrepo &&
127 - cd gitrepo &&
128 - echo alpha >alpha &&
129 - chmod 0644 alpha &&
130 - git add alpha &&
131 - git commit -m "add alpha" &&
132 - chmod 0755 alpha &&
133 - git add alpha &&
134 - git commit -m "set executable bit" &&
135 - chmod 0644 alpha &&
136 - git add alpha &&
137 - git commit -m "clear executable bit"
138 - ) &&
139 -
140 - for x in hg git
141 - do
142 - (
143 - hg_clone_$x gitrepo hgrepo-$x &&
144 - cd hgrepo-$x &&
145 - hg_log . &&
146 - hg manifest -r 1 -v &&
147 - hg manifest -v
148 - ) >"output-$x" &&
149 -
150 - git_clone_$x hgrepo-$x gitrepo2-$x &&
151 - git_log gitrepo2-$x >"log-$x"
152 - done &&
153 -
154 - test_cmp output-hg output-git &&
155 - test_cmp log-hg log-git
156 -'
157 -
158 -test_expect_success 'symlink' '
159 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
160 -
161 - (
162 - git init -q gitrepo &&
163 - cd gitrepo &&
164 - echo alpha >alpha &&
165 - git add alpha &&
166 - git commit -m "add alpha" &&
167 - ln -s alpha beta &&
168 - git add beta &&
169 - git commit -m "add beta"
170 - ) &&
171 -
172 - for x in hg git
173 - do
174 - (
175 - hg_clone_$x gitrepo hgrepo-$x &&
176 - cd hgrepo-$x &&
177 - hg_log . &&
178 - hg manifest -v
179 - ) >"output-$x" &&
180 -
181 - git_clone_$x hgrepo-$x gitrepo2-$x &&
182 - git_log gitrepo2-$x >"log-$x"
183 - done &&
184 -
185 - test_cmp output-hg output-git &&
186 - test_cmp log-hg log-git
187 -'
188 -
189 -test_expect_success 'merge conflict 1' '
190 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
191 -
192 - (
193 - hg init hgrepo1 &&
194 - cd hgrepo1 &&
195 - echo A >afile &&
196 - hg add afile &&
197 - hg ci -m "origin" &&
198 -
199 - echo B >afile &&
200 - hg ci -m "A->B" &&
201 -
202 - hg up -r0 &&
203 - echo C >afile &&
204 - hg ci -m "A->C" &&
205 -
206 - hg merge -r1 &&
207 - echo C >afile &&
208 - hg resolve -m afile &&
209 - hg ci -m "merge to C"
210 - ) &&
211 -
212 - for x in hg git
213 - do
214 - git_clone_$x hgrepo1 gitrepo-$x &&
215 - hg_clone_$x gitrepo-$x hgrepo2-$x &&
216 - hg_log hgrepo2-$x >"hg-log-$x" &&
217 - git_log gitrepo-$x >"git-log-$x"
218 - done &&
219 -
220 - test_cmp hg-log-hg hg-log-git &&
221 - test_cmp git-log-hg git-log-git
222 -'
223 -
224 -test_expect_success 'merge conflict 2' '
225 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
226 -
227 - (
228 - hg init hgrepo1 &&
229 - cd hgrepo1 &&
230 - echo A >afile &&
231 - hg add afile &&
232 - hg ci -m "origin" &&
233 -
234 - echo B >afile &&
235 - hg ci -m "A->B" &&
236 -
237 - hg up -r0 &&
238 - echo C >afile &&
239 - hg ci -m "A->C" &&
240 -
241 - hg merge -r1 || true &&
242 - echo B >afile &&
243 - hg resolve -m afile &&
244 - hg ci -m "merge to B"
245 - ) &&
246 -
247 - for x in hg git
248 - do
249 - git_clone_$x hgrepo1 gitrepo-$x &&
250 - hg_clone_$x gitrepo-$x hgrepo2-$x &&
251 - hg_log hgrepo2-$x >"hg-log-$x" &&
252 - git_log gitrepo-$x >"git-log-$x"
253 - done &&
254 -
255 - test_cmp hg-log-hg hg-log-git &&
256 - test_cmp git-log-hg git-log-git
257 -'
258 -
259 -test_expect_success 'converged merge' '
260 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
261 -
262 - (
263 - hg init hgrepo1 &&
264 - cd hgrepo1 &&
265 - echo A >afile &&
266 - hg add afile &&
267 - hg ci -m "origin" &&
268 -
269 - echo B >afile &&
270 - hg ci -m "A->B" &&
271 -
272 - echo C >afile &&
273 - hg ci -m "B->C" &&
274 -
275 - hg up -r0 &&
276 - echo C >afile &&
277 - hg ci -m "A->C" &&
278 -
279 - hg merge -r2 || true &&
280 - hg ci -m "merge"
281 - ) &&
282 -
283 - for x in hg git
284 - do
285 - git_clone_$x hgrepo1 gitrepo-$x &&
286 - hg_clone_$x gitrepo-$x hgrepo2-$x &&
287 - hg_log hgrepo2-$x >"hg-log-$x" &&
288 - git_log gitrepo-$x >"git-log-$x"
289 - done &&
290 -
291 - test_cmp hg-log-hg hg-log-git &&
292 - test_cmp git-log-hg git-log-git
293 -'
294 -
295 -test_expect_success 'encoding' '
296 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
297 -
298 - (
299 - git init -q gitrepo &&
300 - cd gitrepo &&
301 -
302 - echo alpha >alpha &&
303 - git add alpha &&
304 - git commit -m "add älphà" &&
305 -
306 - GIT_AUTHOR_NAME="tést èncödîng" &&
307 - export GIT_AUTHOR_NAME &&
308 - echo beta >beta &&
309 - git add beta &&
310 - git commit -m "add beta" &&
311 -
312 - echo gamma >gamma &&
313 - git add gamma &&
314 - git commit -m "add gämmâ" &&
315 -
316 - : TODO git config i18n.commitencoding latin-1 &&
317 - echo delta >delta &&
318 - git add delta &&
319 - git commit -m "add déltà"
320 - ) &&
321 -
322 - for x in hg git
323 - do
324 - hg_clone_$x gitrepo hgrepo-$x &&
325 - git_clone_$x hgrepo-$x gitrepo2-$x &&
326 -
327 - HGENCODING=utf-8 hg_log hgrepo-$x >"hg-log-$x" &&
328 - git_log gitrepo2-$x >"git-log-$x"
329 - done &&
330 -
331 - test_cmp hg-log-hg hg-log-git &&
332 - test_cmp git-log-hg git-log-git
333 -'
334 -
335 -test_expect_success 'file removal' '
336 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
337 -
338 - (
339 - git init -q gitrepo &&
340 - cd gitrepo &&
341 - echo alpha >alpha &&
342 - git add alpha &&
343 - git commit -m "add alpha" &&
344 - echo beta >beta &&
345 - git add beta &&
346 - git commit -m "add beta"
347 - mkdir foo &&
348 - echo blah >foo/bar &&
349 - git add foo &&
350 - git commit -m "add foo" &&
351 - git rm alpha &&
352 - git commit -m "remove alpha" &&
353 - git rm foo/bar &&
354 - git commit -m "remove foo/bar"
355 - ) &&
356 -
357 - for x in hg git
358 - do
359 - (
360 - hg_clone_$x gitrepo hgrepo-$x &&
361 - cd hgrepo-$x &&
362 - hg_log . &&
363 - hg manifest -r 3 &&
364 - hg manifest
365 - ) >"output-$x" &&
366 -
367 - git_clone_$x hgrepo-$x gitrepo2-$x &&
368 - git_log gitrepo2-$x >"log-$x"
369 - done &&
370 -
371 - test_cmp output-hg output-git &&
372 - test_cmp log-hg log-git
373 -'
374 -
375 -test_expect_success 'git tags' '
376 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
377 -
378 - (
379 - git init -q gitrepo &&
380 - cd gitrepo &&
381 - git config receive.denyCurrentBranch ignore &&
382 - echo alpha >alpha &&
383 - git add alpha &&
384 - git commit -m "add alpha" &&
385 - git tag alpha &&
386 -
387 - echo beta >beta &&
388 - git add beta &&
389 - git commit -m "add beta" &&
390 - git tag -a -m "added tag beta" beta
391 - ) &&
392 -
393 - for x in hg git
394 - do
395 - hg_clone_$x gitrepo hgrepo-$x &&
396 - hg_log hgrepo-$x >"log-$x"
397 - done &&
398 -
399 - test_cmp log-hg log-git
400 -'
401 -
402 -test_expect_success 'hg author' '
403 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
404 -
405 - for x in hg git
406 - do
407 - (
408 - git init -q gitrepo-$x &&
409 - cd gitrepo-$x &&
410 -
411 - echo alpha >alpha &&
412 - git add alpha &&
413 - git commit -m "add alpha" &&
414 - git checkout -q -b not-master
415 - ) &&
416 -
417 - (
418 - hg_clone_$x gitrepo-$x hgrepo-$x &&
419 - cd hgrepo-$x &&
420 -
421 - hg co master &&
422 - echo beta >beta &&
423 - hg add beta &&
424 - hg commit -u "test" -m "add beta" &&
425 -
426 - echo gamma >>beta &&
427 - hg commit -u "test <test@example.com> (comment)" -m "modify beta" &&
428 -
429 - echo gamma >gamma &&
430 - hg add gamma &&
431 - hg commit -u "<test@example.com>" -m "add gamma" &&
432 -
433 - echo delta >delta &&
434 - hg add delta &&
435 - hg commit -u "name<test@example.com>" -m "add delta" &&
436 -
437 - echo epsilon >epsilon &&
438 - hg add epsilon &&
439 - hg commit -u "name <test@example.com" -m "add epsilon" &&
440 -
441 - echo zeta >zeta &&
442 - hg add zeta &&
443 - hg commit -u " test " -m "add zeta" &&
444 -
445 - echo eta >eta &&
446 - hg add eta &&
447 - hg commit -u "test < test@example.com >" -m "add eta" &&
448 -
449 - echo theta >theta &&
450 - hg add theta &&
451 - hg commit -u "test >test@example.com>" -m "add theta" &&
452 -
453 - echo iota >iota &&
454 - hg add iota &&
455 - hg commit -u "test <test <at> example <dot> com>" -m "add iota"
456 - ) &&
457 -
458 - hg_push_$x hgrepo-$x gitrepo-$x &&
459 - hg_clone_$x gitrepo-$x hgrepo2-$x &&
460 -
461 - hg_log hgrepo2-$x >"hg-log-$x" &&
462 - git_log gitrepo-$x >"git-log-$x"
463 - done &&
464 -
465 - test_cmp hg-log-hg hg-log-git &&
466 - test_cmp git-log-hg git-log-git
467 -'
468 -
469 -test_expect_success 'hg branch' '
470 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
471 -
472 - for x in hg git
473 - do
474 - (
475 - git init -q gitrepo-$x &&
476 - cd gitrepo-$x &&
477 -
478 - echo alpha >alpha &&
479 - git add alpha &&
480 - git commit -q -m "add alpha" &&
481 - git checkout -q -b not-master
482 - ) &&
483 -
484 - (
485 - hg_clone_$x gitrepo-$x hgrepo-$x &&
486 -
487 - cd hgrepo-$x &&
488 - hg -q co master &&
489 - hg mv alpha beta &&
490 - hg -q commit -m "rename alpha to beta" &&
491 - hg branch gamma | grep -v "permanent and global" &&
492 - hg -q commit -m "started branch gamma"
493 - ) &&
494 -
495 - hg_push_$x hgrepo-$x gitrepo-$x &&
496 - hg_clone_$x gitrepo-$x hgrepo2-$x &&
497 -
498 - hg_log hgrepo2-$x >"hg-log-$x" &&
499 - git_log gitrepo-$x >"git-log-$x"
500 - done &&
501 -
502 - test_cmp hg-log-hg hg-log-git &&
503 - test_cmp git-log-hg git-log-git
504 -'
505 -
506 -test_expect_success 'hg tags' '
507 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
508 -
509 - for x in hg git
510 - do
511 - (
512 - git init -q gitrepo-$x &&
513 - cd gitrepo-$x &&
514 -
515 - echo alpha >alpha &&
516 - git add alpha &&
517 - git commit -m "add alpha" &&
518 - git checkout -q -b not-master
519 - ) &&
520 -
521 - (
522 - hg_clone_$x gitrepo-$x hgrepo-$x &&
523 -
524 - cd hgrepo-$x &&
525 - hg co master &&
526 - hg tag alpha
527 - ) &&
528 -
529 - hg_push_$x hgrepo-$x gitrepo-$x &&
530 - hg_clone_$x gitrepo-$x hgrepo2-$x &&
531 -
532 - (
533 - git --git-dir=gitrepo-$x/.git tag -l &&
534 - hg_log hgrepo2-$x &&
535 - cat hgrepo2-$x/.hgtags
536 - ) >"output-$x"
537 - done &&
538 -
539 - test_cmp output-hg output-git
540 -'
541 -
542 -test_done
contrib/remote-helpers/test-hg.sh deleted
-848
@@ -1,848 +0,0 @@
1 -#!/bin/sh
2 -#
3 -# Copyright (c) 2012 Felipe Contreras
4 -#
5 -# Base commands from hg-git tests:
6 -# https://bitbucket.org/durin42/hg-git/src
7 -#
8 -
9 -test_description='Test remote-hg'
10 -
11 -test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=${0%/*}/../../t
12 -. "$TEST_DIRECTORY"/test-lib.sh
13 -
14 -if ! test_have_prereq PYTHON
15 -then
16 - skip_all='skipping remote-hg tests; python not available'
17 - test_done
18 -fi
19 -
20 -if ! python -c 'import mercurial'
21 -then
22 - skip_all='skipping remote-hg tests; mercurial not available'
23 - test_done
24 -fi
25 -
26 -check () {
27 - echo $3 >expected &&
28 - git --git-dir=$1/.git log --format='%s' -1 $2 >actual
29 - test_cmp expected actual
30 -}
31 -
32 -check_branch () {
33 - if test -n "$3"
34 - then
35 - echo $3 >expected &&
36 - hg -R $1 log -r $2 --template '{desc}\n' >actual &&
37 - test_cmp expected actual
38 - else
39 - hg -R $1 branches >out &&
40 - ! grep $2 out
41 - fi
42 -}
43 -
44 -check_bookmark () {
45 - if test -n "$3"
46 - then
47 - echo $3 >expected &&
48 - hg -R $1 log -r "bookmark('$2')" --template '{desc}\n' >actual &&
49 - test_cmp expected actual
50 - else
51 - hg -R $1 bookmarks >out &&
52 - ! grep $2 out
53 - fi
54 -}
55 -
56 -check_push () {
57 - expected_ret=$1 ret=0 ref_ret=0
58 -
59 - shift
60 - git push origin "$@" 2>error
61 - ret=$?
62 - cat error
63 -
64 - while IFS=':' read branch kind
65 - do
66 - case "$kind" in
67 - 'new')
68 - grep "^ \* \[new branch\] *${branch} -> ${branch}$" error || ref_ret=1
69 - ;;
70 - 'non-fast-forward')
71 - grep "^ ! \[rejected\] *${branch} -> ${branch} (non-fast-forward)$" error || ref_ret=1
72 - ;;
73 - 'fetch-first')
74 - grep "^ ! \[rejected\] *${branch} -> ${branch} (fetch first)$" error || ref_ret=1
75 - ;;
76 - 'forced-update')
77 - grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *${branch} -> ${branch} (forced update)$" error || ref_ret=1
78 - ;;
79 - '')
80 - grep "^ [a-f0-9]*\.\.[a-f0-9]* *${branch} -> ${branch}$" error || ref_ret=1
81 - ;;
82 - esac
83 - test $ref_ret -ne 0 && echo "match for '$branch' failed" && break
84 - done
85 -
86 - if test $expected_ret -ne $ret || test $ref_ret -ne 0
87 - then
88 - return 1
89 - fi
90 -
91 - return 0
92 -}
93 -
94 -setup () {
95 - (
96 - echo "[ui]"
97 - echo "username = H G Wells <wells@example.com>"
98 - echo "[extensions]"
99 - echo "mq ="
100 - ) >>"$HOME"/.hgrc &&
101 -
102 - GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230" &&
103 - GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" &&
104 - export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
105 -}
106 -
107 -setup
108 -
109 -test_expect_success 'cloning' '
110 - test_when_finished "rm -rf gitrepo*" &&
111 -
112 - (
113 - hg init hgrepo &&
114 - cd hgrepo &&
115 - echo zero >content &&
116 - hg add content &&
117 - hg commit -m zero
118 - ) &&
119 -
120 - git clone "hg::hgrepo" gitrepo &&
121 - check gitrepo HEAD zero
122 -'
123 -
124 -test_expect_success 'cloning with branches' '
125 - test_when_finished "rm -rf gitrepo*" &&
126 -
127 - (
128 - cd hgrepo &&
129 - hg branch next &&
130 - echo next >content &&
131 - hg commit -m next
132 - ) &&
133 -
134 - git clone "hg::hgrepo" gitrepo &&
135 - check gitrepo origin/branches/next next
136 -'
137 -
138 -test_expect_success 'cloning with bookmarks' '
139 - test_when_finished "rm -rf gitrepo*" &&
140 -
141 - (
142 - cd hgrepo &&
143 - hg checkout default &&
144 - hg bookmark feature-a &&
145 - echo feature-a >content &&
146 - hg commit -m feature-a
147 - ) &&
148 -
149 - git clone "hg::hgrepo" gitrepo &&
150 - check gitrepo origin/feature-a feature-a
151 -'
152 -
153 -test_expect_success 'update bookmark' '
154 - test_when_finished "rm -rf gitrepo*" &&
155 -
156 - (
157 - cd hgrepo &&
158 - hg bookmark devel
159 - ) &&
160 -
161 - (
162 - git clone "hg::hgrepo" gitrepo &&
163 - cd gitrepo &&
164 - git checkout --quiet devel &&
165 - echo devel >content &&
166 - git commit -a -m devel &&
167 - git push --quiet
168 - ) &&
169 -
170 - check_bookmark hgrepo devel devel
171 -'
172 -
173 -test_expect_success 'new bookmark' '
174 - test_when_finished "rm -rf gitrepo*" &&
175 -
176 - (
177 - git clone "hg::hgrepo" gitrepo &&
178 - cd gitrepo &&
179 - git checkout --quiet -b feature-b &&
180 - echo feature-b >content &&
181 - git commit -a -m feature-b &&
182 - git push --quiet origin feature-b
183 - ) &&
184 -
185 - check_bookmark hgrepo feature-b feature-b
186 -'
187 -
188 -# cleanup previous stuff
189 -rm -rf hgrepo
190 -
191 -author_test () {
192 - echo $1 >>content &&
193 - hg commit -u "$2" -m "add $1" &&
194 - echo "$3" >>../expected
195 -}
196 -
197 -test_expect_success 'authors' '
198 - test_when_finished "rm -rf hgrepo gitrepo" &&
199 -
200 - (
201 - hg init hgrepo &&
202 - cd hgrepo &&
203 -
204 - touch content &&
205 - hg add content &&
206 -
207 - >../expected &&
208 - author_test alpha "" "H G Wells <wells@example.com>" &&
209 - author_test beta "beta" "beta <unknown>" &&
210 - author_test gamma "gamma <test@example.com> (comment)" "gamma <test@example.com>" &&
211 - author_test delta "<delta@example.com>" "Unknown <delta@example.com>" &&
212 - author_test epsilon "epsilon<test@example.com>" "epsilon <test@example.com>" &&
213 - author_test zeta "zeta <test@example.com" "zeta <test@example.com>" &&
214 - author_test eta " eta " "eta <unknown>" &&
215 - author_test theta "theta < test@example.com >" "theta <test@example.com>" &&
216 - author_test iota "iota >test@example.com>" "iota <test@example.com>" &&
217 - author_test kappa "kappa < test <at> example <dot> com>" "kappa <unknown>" &&
218 - author_test lambda "lambda@example.com" "Unknown <lambda@example.com>" &&
219 - author_test mu "mu.mu@example.com" "Unknown <mu.mu@example.com>"
220 - ) &&
221 -
222 - git clone "hg::hgrepo" gitrepo &&
223 - git --git-dir=gitrepo/.git log --reverse --format="%an <%ae>" >actual &&
224 -
225 - test_cmp expected actual
226 -'
227 -
228 -test_expect_success 'strip' '
229 - test_when_finished "rm -rf hgrepo gitrepo" &&
230 -
231 - (
232 - hg init hgrepo &&
233 - cd hgrepo &&
234 -
235 - echo one >>content &&
236 - hg add content &&
237 - hg commit -m one &&
238 -
239 - echo two >>content &&
240 - hg commit -m two
241 - ) &&
242 -
243 - git clone "hg::hgrepo" gitrepo &&
244 -
245 - (
246 - cd hgrepo &&
247 - hg strip 1 &&
248 -
249 - echo three >>content &&
250 - hg commit -m three &&
251 -
252 - echo four >>content &&
253 - hg commit -m four
254 - ) &&
255 -
256 - (
257 - cd gitrepo &&
258 - git fetch &&
259 - git log --format="%s" origin/master >../actual
260 - ) &&
261 -
262 - hg -R hgrepo log --template "{desc}\n" >expected &&
263 - test_cmp actual expected
264 -'
265 -
266 -test_expect_success 'remote push with master bookmark' '
267 - test_when_finished "rm -rf hgrepo gitrepo*" &&
268 -
269 - (
270 - hg init hgrepo &&
271 - cd hgrepo &&
272 - echo zero >content &&
273 - hg add content &&
274 - hg commit -m zero &&
275 - hg bookmark master &&
276 - echo one >content &&
277 - hg commit -m one
278 - ) &&
279 -
280 - (
281 - git clone "hg::hgrepo" gitrepo &&
282 - cd gitrepo &&
283 - echo two >content &&
284 - git commit -a -m two &&
285 - git push
286 - ) &&
287 -
288 - check_branch hgrepo default two
289 -'
290 -
291 -cat >expected <<\EOF
292 -changeset: 0:6e2126489d3d
293 -tag: tip
294 -user: A U Thor <author@example.com>
295 -date: Mon Jan 01 00:00:00 2007 +0230
296 -summary: one
297 -
298 -EOF
299 -
300 -test_expect_success 'remote push from master branch' '
301 - test_when_finished "rm -rf hgrepo gitrepo*" &&
302 -
303 - hg init hgrepo &&
304 -
305 - (
306 - git init gitrepo &&
307 - cd gitrepo &&
308 - git remote add origin "hg::../hgrepo" &&
309 - echo one >content &&
310 - git add content &&
311 - git commit -a -m one &&
312 - git push origin master
313 - ) &&
314 -
315 - hg -R hgrepo log >actual &&
316 - cat actual &&
317 - test_cmp expected actual &&
318 -
319 - check_branch hgrepo default one
320 -'
321 -
322 -GIT_REMOTE_HG_TEST_REMOTE=1
323 -export GIT_REMOTE_HG_TEST_REMOTE
324 -
325 -test_expect_success 'remote cloning' '
326 - test_when_finished "rm -rf gitrepo*" &&
327 -
328 - (
329 - hg init hgrepo &&
330 - cd hgrepo &&
331 - echo zero >content &&
332 - hg add content &&
333 - hg commit -m zero
334 - ) &&
335 -
336 - git clone "hg::hgrepo" gitrepo &&
337 - check gitrepo HEAD zero
338 -'
339 -
340 -test_expect_success 'moving remote clone' '
341 - test_when_finished "rm -rf gitrepo*" &&
342 -
343 - (
344 - git clone "hg::hgrepo" gitrepo &&
345 - mv gitrepo gitrepo2 &&
346 - cd gitrepo2 &&
347 - git fetch
348 - )
349 -'
350 -
351 -test_expect_success 'remote update bookmark' '
352 - test_when_finished "rm -rf gitrepo*" &&
353 -
354 - (
355 - cd hgrepo &&
356 - hg bookmark devel
357 - ) &&
358 -
359 - (
360 - git clone "hg::hgrepo" gitrepo &&
361 - cd gitrepo &&
362 - git checkout --quiet devel &&
363 - echo devel >content &&
364 - git commit -a -m devel &&
365 - git push --quiet
366 - ) &&
367 -
368 - check_bookmark hgrepo devel devel
369 -'
370 -
371 -test_expect_success 'remote new bookmark' '
372 - test_when_finished "rm -rf gitrepo*" &&
373 -
374 - (
375 - git clone "hg::hgrepo" gitrepo &&
376 - cd gitrepo &&
377 - git checkout --quiet -b feature-b &&
378 - echo feature-b >content &&
379 - git commit -a -m feature-b &&
380 - git push --quiet origin feature-b
381 - ) &&
382 -
383 - check_bookmark hgrepo feature-b feature-b
384 -'
385 -
386 -test_expect_success 'remote push diverged' '
387 - test_when_finished "rm -rf gitrepo*" &&
388 -
389 - git clone "hg::hgrepo" gitrepo &&
390 -
391 - (
392 - cd hgrepo &&
393 - hg checkout default &&
394 - echo bump >content &&
395 - hg commit -m bump
396 - ) &&
397 -
398 - (
399 - cd gitrepo &&
400 - echo diverge >content &&
401 - git commit -a -m diverged &&
402 - check_push 1 <<-\EOF
403 - master:non-fast-forward
404 - EOF
405 - ) &&
406 -
407 - check_branch hgrepo default bump
408 -'
409 -
410 -test_expect_success 'remote update bookmark diverge' '
411 - test_when_finished "rm -rf gitrepo*" &&
412 -
413 - (
414 - cd hgrepo &&
415 - hg checkout tip^ &&
416 - hg bookmark diverge
417 - ) &&
418 -
419 - git clone "hg::hgrepo" gitrepo &&
420 -
421 - (
422 - cd hgrepo &&
423 - echo "bump bookmark" >content &&
424 - hg commit -m "bump bookmark"
425 - ) &&
426 -
427 - (
428 - cd gitrepo &&
429 - git checkout --quiet diverge &&
430 - echo diverge >content &&
431 - git commit -a -m diverge &&
432 - check_push 1 <<-\EOF
433 - diverge:fetch-first
434 - EOF
435 - ) &&
436 -
437 - check_bookmark hgrepo diverge "bump bookmark"
438 -'
439 -
440 -test_expect_success 'remote new bookmark multiple branch head' '
441 - test_when_finished "rm -rf gitrepo*" &&
442 -
443 - (
444 - git clone "hg::hgrepo" gitrepo &&
445 - cd gitrepo &&
446 - git checkout --quiet -b feature-c HEAD^ &&
447 - echo feature-c >content &&
448 - git commit -a -m feature-c &&
449 - git push --quiet origin feature-c
450 - ) &&
451 -
452 - check_bookmark hgrepo feature-c feature-c
453 -'
454 -
455 -# cleanup previous stuff
456 -rm -rf hgrepo
457 -
458 -test_expect_success 'fetch special filenames' '
459 - test_when_finished "rm -rf hgrepo gitrepo && LC_ALL=C" &&
460 -
461 - LC_ALL=en_US.UTF-8
462 - export LC_ALL
463 -
464 - (
465 - hg init hgrepo &&
466 - cd hgrepo &&
467 -
468 - echo test >> "æ rø" &&
469 - hg add "æ rø" &&
470 - echo test >> "ø~?" &&
471 - hg add "ø~?" &&
472 - hg commit -m add-utf-8 &&
473 - echo test >> "æ rø" &&
474 - hg commit -m test-utf-8 &&
475 - hg rm "ø~?" &&
476 - hg mv "æ rø" "ø~?" &&
477 - hg commit -m hg-mv-utf-8
478 - ) &&
479 -
480 - (
481 - git clone "hg::hgrepo" gitrepo &&
482 - cd gitrepo &&
483 - git -c core.quotepath=false ls-files > ../actual
484 - ) &&
485 - echo "ø~?" > expected &&
486 - test_cmp expected actual
487 -'
488 -
489 -test_expect_success 'push special filenames' '
490 - test_when_finished "rm -rf hgrepo gitrepo && LC_ALL=C" &&
491 -
492 - mkdir -p tmp && cd tmp &&
493 -
494 - LC_ALL=en_US.UTF-8
495 - export LC_ALL
496 -
497 - (
498 - hg init hgrepo &&
499 - cd hgrepo &&
500 -
501 - echo one >> content &&
502 - hg add content &&
503 - hg commit -m one
504 - ) &&
505 -
506 - (
507 - git clone "hg::hgrepo" gitrepo &&
508 - cd gitrepo &&
509 -
510 - echo test >> "æ rø" &&
511 - git add "æ rø" &&
512 - git commit -m utf-8 &&
513 -
514 - git push
515 - ) &&
516 -
517 - (cd hgrepo &&
518 - hg update &&
519 - hg manifest > ../actual
520 - ) &&
521 -
522 - printf "content\næ rø\n" > expected &&
523 - test_cmp expected actual
524 -'
525 -
526 -setup_big_push () {
527 - (
528 - hg init hgrepo &&
529 - cd hgrepo &&
530 - echo zero >content &&
531 - hg add content &&
532 - hg commit -m zero &&
533 - hg bookmark bad_bmark1 &&
534 - echo one >content &&
535 - hg commit -m one &&
536 - hg bookmark bad_bmark2 &&
537 - hg bookmark good_bmark &&
538 - hg bookmark -i good_bmark &&
539 - hg -q branch good_branch &&
540 - echo "good branch" >content &&
541 - hg commit -m "good branch" &&
542 - hg -q branch bad_branch &&
543 - echo "bad branch" >content &&
544 - hg commit -m "bad branch"
545 - ) &&
546 -
547 - git clone "hg::hgrepo" gitrepo &&
548 -
549 - (
550 - cd gitrepo &&
551 - echo two >content &&
552 - git commit -q -a -m two &&
553 -
554 - git checkout -q good_bmark &&
555 - echo three >content &&
556 - git commit -q -a -m three &&
557 -
558 - git checkout -q bad_bmark1 &&
559 - git reset --hard HEAD^ &&
560 - echo four >content &&
561 - git commit -q -a -m four &&
562 -
563 - git checkout -q bad_bmark2 &&
564 - git reset --hard HEAD^ &&
565 - echo five >content &&
566 - git commit -q -a -m five &&
567 -
568 - git checkout -q -b new_bmark master &&
569 - echo six >content &&
570 - git commit -q -a -m six &&
571 -
572 - git checkout -q branches/good_branch &&
573 - echo seven >content &&
574 - git commit -q -a -m seven &&
575 - echo eight >content &&
576 - git commit -q -a -m eight &&
577 -
578 - git checkout -q branches/bad_branch &&
579 - git reset --hard HEAD^ &&
580 - echo nine >content &&
581 - git commit -q -a -m nine &&
582 -
583 - git checkout -q -b branches/new_branch master &&
584 - echo ten >content &&
585 - git commit -q -a -m ten
586 - )
587 -}
588 -
589 -test_expect_success 'remote big push' '
590 - test_when_finished "rm -rf hgrepo gitrepo*" &&
591 -
592 - setup_big_push
593 -
594 - (
595 - cd gitrepo &&
596 -
597 - check_push 1 --all <<-\EOF
598 - master
599 - good_bmark
600 - branches/good_branch
601 - new_bmark:new
602 - branches/new_branch:new
603 - bad_bmark1:non-fast-forward
604 - bad_bmark2:non-fast-forward
605 - branches/bad_branch:non-fast-forward
606 - EOF
607 - ) &&
608 -
609 - check_branch hgrepo default one &&
610 - check_branch hgrepo good_branch "good branch" &&
611 - check_branch hgrepo bad_branch "bad branch" &&
612 - check_branch hgrepo new_branch '' &&
613 - check_bookmark hgrepo good_bmark one &&
614 - check_bookmark hgrepo bad_bmark1 one &&
615 - check_bookmark hgrepo bad_bmark2 one &&
616 - check_bookmark hgrepo new_bmark ''
617 -'
618 -
619 -test_expect_success 'remote big push fetch first' '
620 - test_when_finished "rm -rf hgrepo gitrepo*" &&
621 -
622 - (
623 - hg init hgrepo &&
624 - cd hgrepo &&
625 - echo zero >content &&
626 - hg add content &&
627 - hg commit -m zero &&
628 - hg bookmark bad_bmark &&
629 - hg bookmark good_bmark &&
630 - hg bookmark -i good_bmark &&
631 - hg -q branch good_branch &&
632 - echo "good branch" >content &&
633 - hg commit -m "good branch" &&
634 - hg -q branch bad_branch &&
635 - echo "bad branch" >content &&
636 - hg commit -m "bad branch"
637 - ) &&
638 -
639 - git clone "hg::hgrepo" gitrepo &&
640 -
641 - (
642 - cd hgrepo &&
643 - hg bookmark -f bad_bmark &&
644 - echo update_bmark >content &&
645 - hg commit -m "update bmark"
646 - ) &&
647 -
648 - (
649 - cd gitrepo &&
650 - echo two >content &&
651 - git commit -q -a -m two &&
652 -
653 - git checkout -q good_bmark &&
654 - echo three >content &&
655 - git commit -q -a -m three &&
656 -
657 - git checkout -q bad_bmark &&
658 - echo four >content &&
659 - git commit -q -a -m four &&
660 -
661 - git checkout -q branches/bad_branch &&
662 - echo five >content &&
663 - git commit -q -a -m five &&
664 -
665 - check_push 1 --all <<-\EOF &&
666 - master
667 - good_bmark
668 - bad_bmark:fetch-first
669 - branches/bad_branch:festch-first
670 - EOF
671 -
672 - git fetch &&
673 -
674 - check_push 1 --all <<-\EOF
675 - master
676 - good_bmark
677 - bad_bmark:non-fast-forward
678 - branches/bad_branch:non-fast-forward
679 - EOF
680 - )
681 -'
682 -
683 -test_expect_success 'remote big push force' '
684 - test_when_finished "rm -rf hgrepo gitrepo*" &&
685 -
686 - setup_big_push
687 -
688 - (
689 - cd gitrepo &&
690 -
691 - check_push 0 --force --all <<-\EOF
692 - master
693 - good_bmark
694 - branches/good_branch
695 - new_bmark:new
696 - branches/new_branch:new
697 - bad_bmark1:forced-update
698 - bad_bmark2:forced-update
699 - branches/bad_branch:forced-update
700 - EOF
701 - ) &&
702 -
703 - check_branch hgrepo default six &&
704 - check_branch hgrepo good_branch eight &&
705 - check_branch hgrepo bad_branch nine &&
706 - check_branch hgrepo new_branch ten &&
707 - check_bookmark hgrepo good_bmark three &&
708 - check_bookmark hgrepo bad_bmark1 four &&
709 - check_bookmark hgrepo bad_bmark2 five &&
710 - check_bookmark hgrepo new_bmark six
711 -'
712 -
713 -test_expect_success 'remote big push dry-run' '
714 - test_when_finished "rm -rf hgrepo gitrepo*" &&
715 -
716 - setup_big_push
717 -
718 - (
719 - cd gitrepo &&
720 -
721 - check_push 1 --dry-run --all <<-\EOF &&
722 - master
723 - good_bmark
724 - branches/good_branch
725 - new_bmark:new
726 - branches/new_branch:new
727 - bad_bmark1:non-fast-forward
728 - bad_bmark2:non-fast-forward
729 - branches/bad_branch:non-fast-forward
730 - EOF
731 -
732 - check_push 0 --dry-run master good_bmark new_bmark branches/good_branch branches/new_branch <<-\EOF
733 - master
734 - good_bmark
735 - branches/good_branch
736 - new_bmark:new
737 - branches/new_branch:new
738 - EOF
739 - ) &&
740 -
741 - check_branch hgrepo default one &&
742 - check_branch hgrepo good_branch "good branch" &&
743 - check_branch hgrepo bad_branch "bad branch" &&
744 - check_branch hgrepo new_branch '' &&
745 - check_bookmark hgrepo good_bmark one &&
746 - check_bookmark hgrepo bad_bmark1 one &&
747 - check_bookmark hgrepo bad_bmark2 one &&
748 - check_bookmark hgrepo new_bmark ''
749 -'
750 -
751 -test_expect_success 'remote double failed push' '
752 - test_when_finished "rm -rf hgrepo gitrepo*" &&
753 -
754 - (
755 - hg init hgrepo &&
756 - cd hgrepo &&
757 - echo zero >content &&
758 - hg add content &&
759 - hg commit -m zero &&
760 - echo one >content &&
761 - hg commit -m one
762 - ) &&
763 -
764 - (
765 - git clone "hg::hgrepo" gitrepo &&
766 - cd gitrepo &&
767 - git reset --hard HEAD^ &&
768 - echo two >content &&
769 - git commit -a -m two &&
770 - test_expect_code 1 git push &&
771 - test_expect_code 1 git push
772 - )
773 -'
774 -
775 -test_expect_success 'clone remote with master null bookmark, then push to the bookmark' '
776 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
777 -
778 - hg init hgrepo &&
779 - (
780 - cd hgrepo &&
781 - echo a >a &&
782 - hg add a &&
783 - hg commit -m a &&
784 - hg bookmark -r null master
785 - ) &&
786 -
787 - git clone "hg::hgrepo" gitrepo &&
788 - check gitrepo HEAD a &&
789 - (
790 - cd gitrepo &&
791 - git checkout --quiet -b master &&
792 - echo b >b &&
793 - git add b &&
794 - git commit -m b &&
795 - git push origin master
796 - )
797 -'
798 -
799 -test_expect_success 'clone remote with default null bookmark, then push to the bookmark' '
800 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
801 -
802 - hg init hgrepo &&
803 - (
804 - cd hgrepo &&
805 - echo a >a &&
806 - hg add a &&
807 - hg commit -m a &&
808 - hg bookmark -r null -f default
809 - ) &&
810 -
811 - git clone "hg::hgrepo" gitrepo &&
812 - check gitrepo HEAD a &&
813 - (
814 - cd gitrepo &&
815 - git checkout --quiet -b default &&
816 - echo b >b &&
817 - git add b &&
818 - git commit -m b &&
819 - git push origin default
820 - )
821 -'
822 -
823 -test_expect_success 'clone remote with generic null bookmark, then push to the bookmark' '
824 - test_when_finished "rm -rf gitrepo* hgrepo*" &&
825 -
826 - hg init hgrepo &&
827 - (
828 - cd hgrepo &&
829 - echo a >a &&
830 - hg add a &&
831 - hg commit -m a &&
832 - hg bookmark -r null bmark
833 - ) &&
834 -
835 - git clone "hg::hgrepo" gitrepo &&
836 - check gitrepo HEAD a &&
837 - (
838 - cd gitrepo &&
839 - git checkout --quiet -b bmark &&
840 - git remote -v &&
841 - echo b >b &&
842 - git add b &&
843 - git commit -m b &&
844 - git push origin bmark
845 - )
846 -'
847 -
848 -test_done
t/t5801-remote-helpers.sh
+23 -8
@@ -212,19 +212,30 @@ test_expect_success 'push update refs failure' '
212 echo "update fail" >>file &&
213 git commit -a -m "update fail" &&
214 git rev-parse --verify testgit/origin/heads/update >expect &&
215 - GIT_REMOTE_TESTGIT_PUSH_ERROR="non-fast forward" &&
216 - export GIT_REMOTE_TESTGIT_PUSH_ERROR &&
217 - test_expect_code 1 git push origin update &&
215 + test_expect_code 1 env GIT_REMOTE_TESTGIT_FAILURE="non-fast forward" \
216 + git push origin update &&
217 git rev-parse --verify testgit/origin/heads/update >actual &&
218 test_cmp expect actual
219 )
220 '
221
222 +clean_mark () {
223 + cut -f 2 -d ' ' "$1" |
224 + git cat-file --batch-check |
225 + grep commit |
226 + sort >$(basename "$1")
227 +}
228 +
229 +cmp_marks () {
230 + test_when_finished "rm -rf git.marks testgit.marks" &&
231 + clean_mark ".git/testgit/$1/git.marks" &&
232 + clean_mark ".git/testgit/$1/testgit.marks" &&
233 + test_cmp git.marks testgit.marks
234 +}
235 +
236 test_expect_success 'proper failure checks for fetching' '
224 - (GIT_REMOTE_TESTGIT_FAILURE=1 &&
225 - export GIT_REMOTE_TESTGIT_FAILURE &&
226 - cd local &&
227 - test_must_fail git fetch 2> error &&
237 + (cd local &&
238 + test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git fetch 2>error &&
239 cat error &&
240 grep -q "Error while running fast-import" error
241 )
@@ -232,7 +243,11 @@ test_expect_success 'proper failure checks for fetching' '
243
244 test_expect_success 'proper failure checks for pushing' '
245 (cd local &&
235 - test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git push --all
246 + git checkout -b crash master &&
247 + echo crash >>file &&
248 + git commit -a -m crash &&
249 + test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git push --all &&
250 + cmp_marks origin
251 )
252 '
253
transport-helper.c
+44 -29
@@ -58,7 +58,7 @@ static int recvline_fh(FILE *helper, struct strbuf *buffer, const char *name)
58 if (strbuf_getline(buffer, helper, '\n') == EOF) {
59 if (debug)
60 fprintf(stderr, "Debug: Remote helper quit.\n");
61 - exit(128);
61 + return 1;
62 }
63
64 if (debug)
@@ -71,12 +71,6 @@ static int recvline(struct helper_data *helper, struct strbuf *buffer)
71 return recvline_fh(helper->out, buffer, helper->name);
72 }
73
74 -static void xchgline(struct helper_data *helper, struct strbuf *buffer)
75 -{
76 - sendline(helper, buffer);
77 - recvline(helper, buffer);
78 -}
79 -
74 static void write_constant(int fd, const char *str)
75 {
76 if (debug)
@@ -163,7 +157,8 @@ static struct child_process *get_helper(struct transport *transport)
157 while (1) {
158 const char *capname;
159 int mandatory = 0;
166 - recvline(data, &buf);
160 + if (recvline(data, &buf))
161 + exit(128);
162
163 if (!*buf.buf)
164 break;
@@ -200,15 +195,9 @@ static struct child_process *get_helper(struct transport *transport)
195 } else if (!strcmp(capname, "signed-tags")) {
196 data->signed_tags = 1;
197 } else if (starts_with(capname, "export-marks ")) {
203 - struct strbuf arg = STRBUF_INIT;
204 - strbuf_addstr(&arg, "--export-marks=");
205 - strbuf_addstr(&arg, capname + strlen("export-marks "));
206 - data->export_marks = strbuf_detach(&arg, NULL);
198 + data->export_marks = xstrdup(capname + strlen("export-marks "));
199 } else if (starts_with(capname, "import-marks")) {
208 - struct strbuf arg = STRBUF_INIT;
209 - strbuf_addstr(&arg, "--import-marks=");
210 - strbuf_addstr(&arg, capname + strlen("import-marks "));
211 - data->import_marks = strbuf_detach(&arg, NULL);
200 + data->import_marks = xstrdup(capname + strlen("import-marks "));
201 } else if (starts_with(capname, "no-private-update")) {
202 data->no_private_update = 1;
203 } else if (mandatory) {
@@ -307,7 +296,9 @@ static int set_helper_option(struct transport *transport,
296 quote_c_style(value, &buf, NULL, 0);
297 strbuf_addch(&buf, '\n');
298
310 - xchgline(data, &buf);
299 + sendline(data, &buf);
300 + if (recvline(data, &buf))
301 + exit(128);
302
303 if (!strcmp(buf.buf, "ok"))
304 ret = 0;
@@ -379,7 +370,8 @@ static int fetch_with_fetch(struct transport *transport,
370 sendline(data, &buf);
371
372 while (1) {
382 - recvline(data, &buf);
373 + if (recvline(data, &buf))
374 + exit(128);
375
376 if (starts_with(buf.buf, "lock ")) {
377 const char *name = buf.buf + 5;
@@ -430,6 +422,8 @@ static int get_exporter(struct transport *transport,
422 struct helper_data *data = transport->data;
423 struct child_process *helper = get_helper(transport);
424 int argc = 0, i;
425 + struct strbuf tmp = STRBUF_INIT;
426 +
427 memset(fastexport, 0, sizeof(*fastexport));
428
429 /* we need to duplicate helper->in because we want to use it after
@@ -440,10 +434,14 @@ static int get_exporter(struct transport *transport,
434 fastexport->argv[argc++] = "--use-done-feature";
435 fastexport->argv[argc++] = data->signed_tags ?
436 "--signed-tags=verbatim" : "--signed-tags=warn-strip";
443 - if (data->export_marks)
444 - fastexport->argv[argc++] = data->export_marks;
445 - if (data->import_marks)
446 - fastexport->argv[argc++] = data->import_marks;
437 + if (data->export_marks) {
438 + strbuf_addf(&tmp, "--export-marks=%s.tmp", data->export_marks);
439 + fastexport->argv[argc++] = strbuf_detach(&tmp, NULL);
440 + }
441 + if (data->import_marks) {
442 + strbuf_addf(&tmp, "--import-marks=%s", data->import_marks);
443 + fastexport->argv[argc++] = strbuf_detach(&tmp, NULL);
444 + }
445
446 for (i = 0; i < revlist_args->nr; i++)
447 fastexport->argv[argc++] = revlist_args->items[i].string;
@@ -563,7 +561,9 @@ static int process_connect_service(struct transport *transport,
561 goto exit;
562
563 sendline(data, &cmdbuf);
566 - recvline_fh(input, &cmdbuf, name);
564 + if (recvline_fh(input, &cmdbuf, name))
565 + exit(128);
566 +
567 if (!strcmp(cmdbuf.buf, "")) {
568 data->no_disconnect_req = 1;
569 if (debug)
@@ -739,16 +739,22 @@ static int push_update_ref_status(struct strbuf *buf,
739 return !(status == REF_STATUS_OK);
740 }
741
742 -static void push_update_refs_status(struct helper_data *data,
742 +static int push_update_refs_status(struct helper_data *data,
743 struct ref *remote_refs,
744 int flags)
745 {
746 struct strbuf buf = STRBUF_INIT;
747 struct ref *ref = remote_refs;
748 + int ret = 0;
749 +
750 for (;;) {
751 char *private;
752
751 - recvline(data, &buf);
753 + if (recvline(data, &buf)) {
754 + ret = 1;
755 + break;
756 + }
757 +
758 if (!buf.len)
759 break;
760
@@ -766,6 +772,7 @@ static void push_update_refs_status(struct helper_data *data,
772 free(private);
773 }
774 strbuf_release(&buf);
775 + return ret;
776 }
777
778 static int push_refs_with_push(struct transport *transport,
@@ -846,8 +853,7 @@ static int push_refs_with_push(struct transport *transport,
853 sendline(data, &buf);
854 strbuf_release(&buf);
855
849 - push_update_refs_status(data, remote_refs, flags);
850 - return 0;
856 + return push_update_refs_status(data, remote_refs, flags);
857 }
858
859 static int push_refs_with_export(struct transport *transport,
@@ -905,7 +911,15 @@ static int push_refs_with_export(struct transport *transport,
911
912 if (finish_command(&exporter))
913 die("Error while running fast-export");
908 - push_update_refs_status(data, remote_refs, flags);
914 + if (push_update_refs_status(data, remote_refs, flags))
915 + return 1;
916 +
917 + if (data->export_marks) {
918 + strbuf_addf(&buf, "%s.tmp", data->export_marks);
919 + rename(buf.buf, data->export_marks);
920 + strbuf_release(&buf);
921 + }
922 +
923 return 0;
924 }
925
@@ -974,7 +988,8 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
988
989 while (1) {
990 char *eov, *eon;
977 - recvline(data, &buf);
991 + if (recvline(data, &buf))
992 + exit(128);
993
994 if (!*buf.buf)
995 break;