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;