git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v6 00/16] New remote-hg helper:w
@ 2012-11-04  2:13 Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 01/16] Add new remote-hg transport helper Felipe Contreras
                   ` (15 more replies)
  0 siblings, 16 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Hi,

Only a few updates, and has been moved to contrib/remote-helpers
(git-remote-bzr is on the way).

This remote-hg has advantages other tools don't have:

 * Uses transport-helper (git clone hg::path)
 * The code is small
 * The code is simple
 * No external dependencies (other than mercurial)
 * It's easy to install (put into your path)
 * Has extensive tests (for real)
 * Active development
 * Has compatibility with hg-git
 * The required patches are available
 * No changes necesary to git core
 * Support for bookmarks
 * Support for tags

One important alternative is the one written by Sverre Rabbelier that is
now maintained and distributed in msysgit. A list of issues with that
approach (not exhaustive):

 * Doesn't work on newer versions of mercurial
 * There are multiple versions, each with different issues
 * Don't pass a single of this remote-hg's tests

To use it add it to your $PATH (e.g. ~/bin).

 % git clone hd:///full/path/or/url/to/hg/repo

To run the tests:

 % make -C contrib/remote-helpers test

The only caveat is that you need 'python' in your $PATH.

Changes since v5:

 * Move to contrib/remote-helpers
 * Reorganize tests
 * Fix update of bookmarks
 * Fix for older versions of python
 * Performance improvements
 * Improve default branch/bookmark handling
 * Add fixes test-lib
 * Cleanups

Changes since v4:

Felipe Contreras (16):
  Add new remote-hg transport helper
  remote-hg: add support for pushing
  remote-hg: add support for remote pushing
  remote-hg: add support to push URLs
  remote-hg: make sure the encoding is correct
  remote-hg: match hg merge behavior
  remote-hg: add support for hg-git compat mode
  remote-hg: add compat for hg-git author fixes
  remote-hg: fake bookmark when there's none
  remote-hg: add basic tests
  test-lib: avoid full path to store test results
  remote-hg: add bidirectional tests
  remote-hg: add tests to compare with hg-git
  remote-hg: add extra author test
  remote-hg: add option to not track branches
  remote-hg: the author email can be null

 contrib/remote-helpers/Makefile          |  13 +
 contrib/remote-helpers/git-remote-hg     | 785 +++++++++++++++++++++++++++++++
 contrib/remote-helpers/test-hg-bidi.sh   | 243 ++++++++++
 contrib/remote-helpers/test-hg-hg-git.sh | 466 ++++++++++++++++++
 contrib/remote-helpers/test-hg.sh        | 112 +++++
 t/test-lib.sh                            |   3 +-
 6 files changed, 1621 insertions(+), 1 deletion(-)
 create mode 100644 contrib/remote-helpers/Makefile
 create mode 100755 contrib/remote-helpers/git-remote-hg
 create mode 100755 contrib/remote-helpers/test-hg-bidi.sh
 create mode 100755 contrib/remote-helpers/test-hg-hg-git.sh
 create mode 100755 contrib/remote-helpers/test-hg.sh

-- 
1.8.0

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v6 01/16] Add new remote-hg transport helper
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 02/16] remote-hg: add support for pushing Felipe Contreras
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 391 +++++++++++++++++++++++++++++++++++
 1 file changed, 391 insertions(+)
 create mode 100755 contrib/remote-helpers/git-remote-hg

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
new file mode 100755
index 0000000..e37e278
--- /dev/null
+++ b/contrib/remote-helpers/git-remote-hg
@@ -0,0 +1,391 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+# Inspired by Rocco Rutte's hg-fast-export
+
+# Just copy to your ~/bin, or anywhere in your $PATH.
+# Then you can clone with:
+# git clone hg::/path/to/mercurial/repo/
+
+from mercurial import hg, ui, bookmarks
+
+import re
+import sys
+import os
+import json
+
+NAME_RE = re.compile('^([^<>]+)')
+AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+
+def die(msg, *args):
+    sys.stderr.write('ERROR: %s\n' % (msg % args))
+    sys.exit(1)
+
+def warn(msg, *args):
+    sys.stderr.write('WARNING: %s\n' % (msg % args))
+
+def gitmode(flags):
+    return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
+
+def gittz(tz):
+    return '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
+
+class Marks:
+
+    def __init__(self, path):
+        self.path = path
+        self.tips = {}
+        self.marks = {}
+        self.last_mark = 0
+
+        self.load()
+
+    def load(self):
+        if not os.path.exists(self.path):
+            return
+
+        tmp = json.load(open(self.path))
+
+        self.tips = tmp['tips']
+        self.marks = tmp['marks']
+        self.last_mark = tmp['last-mark']
+
+    def dict(self):
+        return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
+
+    def store(self):
+        json.dump(self.dict(), open(self.path, 'w'))
+
+    def __str__(self):
+        return str(self.dict())
+
+    def from_rev(self, rev):
+        return self.marks[str(rev)]
+
+    def get_mark(self, rev):
+        self.last_mark += 1
+        self.marks[str(rev)] = self.last_mark
+        return self.last_mark
+
+    def is_marked(self, rev):
+        return self.marks.has_key(str(rev))
+
+    def get_tip(self, branch):
+        return self.tips.get(branch, 0)
+
+    def set_tip(self, branch, tip):
+        self.tips[branch] = tip
+
+class Parser:
+
+    def __init__(self, repo):
+        self.repo = repo
+        self.line = self.get_line()
+
+    def get_line(self):
+        return sys.stdin.readline().strip()
+
+    def __getitem__(self, i):
+        return self.line.split()[i]
+
+    def check(self, word):
+        return self.line.startswith(word)
+
+    def each_block(self, separator):
+        while self.line != separator:
+            yield self.line
+            self.line = self.get_line()
+
+    def __iter__(self):
+        return self.each_block('')
+
+    def next(self):
+        self.line = self.get_line()
+        if self.line == 'done':
+            self.line = None
+
+def export_file(fc):
+    d = fc.data()
+    print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
+    print "data %d" % len(d)
+    print d
+
+def get_filechanges(repo, ctx, parent):
+    modified = set()
+    added = set()
+    removed = set()
+
+    cur = ctx.manifest()
+    prev = repo[parent].manifest().copy()
+
+    for fn in cur:
+        if fn in prev:
+            if (cur.flags(fn) != prev.flags(fn) or cur[fn] != prev[fn]):
+                modified.add(fn)
+            del prev[fn]
+        else:
+            added.add(fn)
+    removed |= set(prev.keys())
+
+    return added | modified, removed
+
+def fixup_user(user):
+    user = user.replace('"', '')
+    name = mail = None
+    m = AUTHOR_RE.match(user)
+    if m:
+        name = m.group(1)
+        mail = m.group(2).strip()
+    else:
+        m = NAME_RE.match(user)
+        if m:
+            name = m.group(1).strip()
+
+    if not name:
+        name = 'Unknown'
+    if not mail:
+        mail = 'unknown'
+
+    return '%s <%s>' % (name, mail)
+
+def get_repo(url, alias):
+    global dirname
+
+    myui = ui.ui()
+    myui.setconfig('ui', 'interactive', 'off')
+
+    if hg.islocal(url):
+        repo = hg.repository(myui, url)
+    else:
+        local_path = os.path.join(dirname, 'clone')
+        if not os.path.exists(local_path):
+            peer, dstpeer = hg.clone(myui, {}, url, local_path, update=False, pull=True)
+            repo = dstpeer.local()
+        else:
+            repo = hg.repository(myui, local_path)
+            peer = hg.peer(myui, {}, url)
+            repo.pull(peer, heads=None, force=True)
+
+    return repo
+
+def rev_to_mark(rev):
+    global marks
+    return marks.from_rev(rev)
+
+def export_ref(repo, name, kind, head):
+    global prefix, marks
+
+    ename = '%s/%s' % (kind, name)
+    tip = marks.get_tip(ename)
+
+    # mercurial takes too much time checking this
+    if tip and tip == head.rev():
+        # nothing to do
+        return
+    revs = repo.revs('%u:%u' % (tip, head))
+    count = 0
+
+    revs = [rev for rev in revs if not marks.is_marked(rev)]
+
+    for rev in revs:
+
+        c = repo[rev]
+        (manifest, user, (time, tz), files, desc, extra) = repo.changelog.read(c.node())
+        rev_branch = extra['branch']
+
+        author = "%s %d %s" % (fixup_user(user), time, gittz(tz))
+        if 'committer' in extra:
+            user, time, tz = extra['committer'].rsplit(' ', 2)
+            committer = "%s %s %s" % (user, time, gittz(int(tz)))
+        else:
+            committer = author
+
+        parents = [p for p in repo.changelog.parentrevs(rev) if p >= 0]
+
+        if len(parents) == 0:
+            modified = c.manifest().keys()
+            removed = []
+        else:
+            modified, removed = get_filechanges(repo, c, parents[0])
+
+        if len(parents) == 0 and rev:
+            print 'reset %s/%s' % (prefix, ename)
+
+        print "commit %s/%s" % (prefix, ename)
+        print "mark :%d" % (marks.get_mark(rev))
+        print "author %s" % (author)
+        print "committer %s" % (committer)
+        print "data %d" % (len(desc))
+        print desc
+
+        if len(parents) > 0:
+            print "from :%s" % (rev_to_mark(parents[0]))
+            if len(parents) > 1:
+                print "merge :%s" % (rev_to_mark(parents[1]))
+
+        for f in modified:
+            export_file(c.filectx(f))
+        for f in removed:
+            print "D %s" % (f)
+        print
+
+        count += 1
+        if (count % 100 == 0):
+            print "progress revision %d '%s' (%d/%d)" % (rev, name, count, len(revs))
+            print "#############################################################"
+
+    # make sure the ref is updated
+    print "reset %s/%s" % (prefix, ename)
+    print "from :%u" % rev_to_mark(rev)
+    print
+
+    marks.set_tip(ename, rev)
+
+def export_tag(repo, tag):
+    export_ref(repo, tag, 'tags', repo[tag])
+
+def export_bookmark(repo, bmark):
+    head = bmarks[bmark]
+    export_ref(repo, bmark, 'bookmarks', head)
+
+def export_branch(repo, branch):
+    tip = get_branch_tip(repo, branch)
+    head = repo[tip]
+    export_ref(repo, branch, 'branches', head)
+
+def export_head(repo):
+    global g_head
+    export_ref(repo, g_head[0], 'bookmarks', g_head[1])
+
+def do_capabilities(parser):
+    global prefix, dirname
+
+    print "import"
+    print "refspec refs/heads/branches/*:%s/branches/*" % prefix
+    print "refspec refs/heads/*:%s/bookmarks/*" % prefix
+    print "refspec refs/tags/*:%s/tags/*" % prefix
+    print
+
+def get_branch_tip(repo, branch):
+    global branches
+
+    heads = branches.get(branch, None)
+    if not heads:
+        return None
+
+    # verify there's only one head
+    if (len(heads) > 1):
+        warn("Branch '%s' has more than one head, consider merging" % branch)
+        # older versions of mercurial don't have this
+        if hasattr(repo, "branchtip"):
+            return repo.branchtip(branch)
+
+    return heads[0]
+
+def list_head(repo, cur):
+    global g_head
+
+    head = bookmarks.readcurrent(repo)
+    if not head:
+        return
+    node = repo[head]
+    print "@refs/heads/%s HEAD" % head
+    g_head = (head, node)
+
+def do_list(parser):
+    global branches, bmarks
+
+    repo = parser.repo
+    for branch in repo.branchmap():
+        heads = repo.branchheads(branch)
+        if len(heads):
+            branches[branch] = heads
+
+    for bmark, node in bookmarks.listbookmarks(repo).iteritems():
+        bmarks[bmark] = repo[node]
+
+    cur = repo.dirstate.branch()
+
+    list_head(repo, cur)
+    for branch in branches:
+        print "? refs/heads/branches/%s" % branch
+    for bmark in bmarks:
+        print "? refs/heads/%s" % bmark
+
+    for tag, node in repo.tagslist():
+        if tag == 'tip':
+            continue
+        print "? refs/tags/%s" % tag
+
+    print
+
+def do_import(parser):
+    repo = parser.repo
+
+    path = os.path.join(dirname, 'marks-git')
+
+    print "feature done"
+    if os.path.exists(path):
+        print "feature import-marks=%s" % path
+    print "feature export-marks=%s" % path
+    sys.stdout.flush()
+
+    # lets get all the import lines
+    while parser.check('import'):
+        ref = parser[1]
+
+        if (ref == 'HEAD'):
+            export_head(repo)
+        elif ref.startswith('refs/heads/branches/'):
+            branch = ref[len('refs/heads/branches/'):]
+            export_branch(repo, branch)
+        elif ref.startswith('refs/heads/'):
+            bmark = ref[len('refs/heads/'):]
+            export_bookmark(repo, bmark)
+        elif ref.startswith('refs/tags/'):
+            tag = ref[len('refs/tags/'):]
+            export_tag(repo, tag)
+
+        parser.next()
+
+    print 'done'
+
+def main(args):
+    global prefix, dirname, marks, branches, bmarks
+
+    alias = args[1]
+    url = args[2]
+
+    gitdir = os.environ['GIT_DIR']
+    dirname = os.path.join(gitdir, 'hg', alias)
+    branches = {}
+    bmarks = {}
+
+    repo = get_repo(url, alias)
+    prefix = 'refs/hg/%s' % alias
+
+    if not os.path.exists(dirname):
+        os.makedirs(dirname)
+
+    marks_path = os.path.join(dirname, 'marks-hg')
+    marks = Marks(marks_path)
+
+    parser = Parser(repo)
+    for line in parser:
+        if parser.check('capabilities'):
+            do_capabilities(parser)
+        elif parser.check('list'):
+            do_list(parser)
+        elif parser.check('import'):
+            do_import(parser)
+        elif parser.check('export'):
+            do_export(parser)
+        else:
+            die('unhandled command: %s' % line)
+        sys.stdout.flush()
+
+    marks.store()
+
+sys.exit(main(sys.argv))
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 02/16] remote-hg: add support for pushing
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 01/16] Add new remote-hg transport helper Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 03/16] remote-hg: add support for remote pushing Felipe Contreras
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 217 ++++++++++++++++++++++++++++++++++-
 1 file changed, 215 insertions(+), 2 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index e37e278..fcceede 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -9,7 +9,7 @@
 # Then you can clone with:
 # git clone hg::/path/to/mercurial/repo/
 
-from mercurial import hg, ui, bookmarks
+from mercurial import hg, ui, bookmarks, context
 
 import re
 import sys
@@ -18,6 +18,7 @@ import json
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.+)> (\d+) ([+-]\d+)')
 
 def die(msg, *args):
     sys.stderr.write('ERROR: %s\n' % (msg % args))
@@ -32,12 +33,17 @@ def gitmode(flags):
 def gittz(tz):
     return '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
 
+def hgmode(mode):
+    m = { '0100755': 'x', '0120000': 'l' }
+    return m.get(mode, '')
+
 class Marks:
 
     def __init__(self, path):
         self.path = path
         self.tips = {}
         self.marks = {}
+        self.rev_marks = {}
         self.last_mark = 0
 
         self.load()
@@ -52,6 +58,9 @@ class Marks:
         self.marks = tmp['marks']
         self.last_mark = tmp['last-mark']
 
+        for rev, mark in self.marks.iteritems():
+            self.rev_marks[mark] = int(rev)
+
     def dict(self):
         return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
 
@@ -64,11 +73,19 @@ class Marks:
     def from_rev(self, rev):
         return self.marks[str(rev)]
 
+    def to_rev(self, mark):
+        return self.rev_marks[mark]
+
     def get_mark(self, rev):
         self.last_mark += 1
         self.marks[str(rev)] = self.last_mark
         return self.last_mark
 
+    def new_mark(self, rev, mark):
+        self.marks[str(rev)] = mark
+        self.rev_marks[mark] = rev
+        self.last_mark = mark
+
     def is_marked(self, rev):
         return self.marks.has_key(str(rev))
 
@@ -106,6 +123,35 @@ class Parser:
         if self.line == 'done':
             self.line = None
 
+    def get_mark(self):
+        i = self.line.index(':') + 1
+        return int(self.line[i:])
+
+    def get_data(self):
+        if not self.check('data'):
+            return None
+        i = self.line.index(' ') + 1
+        size = int(self.line[i:])
+        return sys.stdin.read(size)
+
+    def get_author(self):
+        m = RAW_AUTHOR_RE.match(self.line)
+        if not m:
+            return None
+        _, name, email, date, tz = m.groups()
+
+        if email != 'unknown':
+            if name:
+                user = '%s <%s>' % (name, email)
+            else:
+                user = '<%s>' % (email)
+        else:
+            user = name
+
+        tz = int(tz)
+        tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
+        return (user, int(date), -tz)
+
 def export_file(fc):
     d = fc.data()
     print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
@@ -174,6 +220,10 @@ def rev_to_mark(rev):
     global marks
     return marks.from_rev(rev)
 
+def mark_to_rev(mark):
+    global marks
+    return marks.to_rev(mark)
+
 def export_ref(repo, name, kind, head):
     global prefix, marks
 
@@ -263,9 +313,17 @@ def do_capabilities(parser):
     global prefix, dirname
 
     print "import"
+    print "export"
     print "refspec refs/heads/branches/*:%s/branches/*" % prefix
     print "refspec refs/heads/*:%s/bookmarks/*" % prefix
     print "refspec refs/tags/*:%s/tags/*" % prefix
+
+    path = os.path.join(dirname, 'marks-git')
+
+    if os.path.exists(path):
+        print "*import-marks %s" % path
+    print "*export-marks %s" % path
+
     print
 
 def get_branch_tip(repo, branch):
@@ -352,8 +410,161 @@ def do_import(parser):
 
     print 'done'
 
+def parse_blob(parser):
+    global blob_marks
+
+    parser.next()
+    mark = parser.get_mark()
+    parser.next()
+    data = parser.get_data()
+    blob_marks[mark] = data
+    parser.next()
+    return
+
+def parse_commit(parser):
+    global marks, blob_marks, bmarks, parsed_refs
+
+    from_mark = merge_mark = None
+
+    ref = parser[1]
+    parser.next()
+
+    commit_mark = parser.get_mark()
+    parser.next()
+    author = parser.get_author()
+    parser.next()
+    committer = parser.get_author()
+    parser.next()
+    data = parser.get_data()
+    parser.next()
+    if parser.check('from'):
+        from_mark = parser.get_mark()
+        parser.next()
+    if parser.check('merge'):
+        merge_mark = parser.get_mark()
+        parser.next()
+        if parser.check('merge'):
+            die('octopus merges are not supported yet')
+
+    files = {}
+
+    for line in parser:
+        if parser.check('M'):
+            t, m, mark_ref, path = line.split(' ')
+            mark = int(mark_ref[1:])
+            f = { 'mode' : hgmode(m), 'data' : blob_marks[mark] }
+        elif parser.check('D'):
+            t, path = line.split(' ')
+            f = { 'deleted' : True }
+        else:
+            die('Unknown file command: %s' % line)
+        files[path] = f
+
+    def getfilectx(repo, memctx, f):
+        of = files[f]
+        if 'deleted' in of:
+            raise IOError
+        is_exec = of['mode'] == 'x'
+        is_link = of['mode'] == 'l'
+        return context.memfilectx(f, of['data'], is_link, is_exec, None)
+
+    repo = parser.repo
+
+    user, date, tz = author
+    extra = {}
+
+    if committer != author:
+        extra['committer'] = "%s %u %u" % committer
+
+    if from_mark:
+        p1 = repo.changelog.node(mark_to_rev(from_mark))
+    else:
+        p1 = '\0' * 20
+
+    if merge_mark:
+        p2 = repo.changelog.node(mark_to_rev(merge_mark))
+    else:
+        p2 = '\0' * 20
+
+    ctx = context.memctx(repo, (p1, p2), data,
+            files.keys(), getfilectx,
+            user, (date, tz), extra)
+
+    node = repo.commitctx(ctx)
+
+    rev = repo[node].rev()
+
+    parsed_refs[ref] = node
+
+    marks.new_mark(rev, commit_mark)
+
+def parse_reset(parser):
+    ref = parser[1]
+    parser.next()
+    # ugh
+    if parser.check('commit'):
+        parse_commit(parser)
+        return
+    if not parser.check('from'):
+        return
+    from_mark = parser.get_mark()
+    parser.next()
+
+    node = parser.repo.changelog.node(mark_to_rev(from_mark))
+    parsed_refs[ref] = node
+
+def parse_tag(parser):
+    name = parser[1]
+    parser.next()
+    from_mark = parser.get_mark()
+    parser.next()
+    tagger = parser.get_author()
+    parser.next()
+    data = parser.get_data()
+    parser.next()
+
+    # nothing to do
+
+def do_export(parser):
+    global parsed_refs, bmarks
+
+    parser.next()
+
+    for line in parser.each_block('done'):
+        if parser.check('blob'):
+            parse_blob(parser)
+        elif parser.check('commit'):
+            parse_commit(parser)
+        elif parser.check('reset'):
+            parse_reset(parser)
+        elif parser.check('tag'):
+            parse_tag(parser)
+        elif parser.check('feature'):
+            pass
+        else:
+            die('unhandled export command: %s' % line)
+
+    for ref, node in parsed_refs.iteritems():
+        if ref.startswith('refs/heads/branches'):
+            pass
+        elif ref.startswith('refs/heads/'):
+            bmark = ref[len('refs/heads/'):]
+            if bmark in bmarks:
+                old = bmarks[bmark].hex()
+            else:
+                old = ''
+            if not bookmarks.pushbookmark(parser.repo, bmark, old, node):
+                continue
+        elif ref.startswith('refs/tags/'):
+            tag = ref[len('refs/tags/'):]
+            parser.repo.tag([tag], node, None, True, None, {})
+        print "ok %s" % ref
+
+    print
+
 def main(args):
-    global prefix, dirname, marks, branches, bmarks
+    global prefix, dirname, branches, bmarks
+    global marks, blob_marks, parsed_refs
 
     alias = args[1]
     url = args[2]
@@ -362,6 +573,8 @@ def main(args):
     dirname = os.path.join(gitdir, 'hg', alias)
     branches = {}
     bmarks = {}
+    blob_marks = {}
+    parsed_refs = {}
 
     repo = get_repo(url, alias)
     prefix = 'refs/hg/%s' % alias
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 03/16] remote-hg: add support for remote pushing
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 01/16] Add new remote-hg transport helper Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 02/16] remote-hg: add support for pushing Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 04/16] remote-hg: add support to push URLs Felipe Contreras
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index fcceede..45629e0 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -197,7 +197,7 @@ def fixup_user(user):
     return '%s <%s>' % (name, mail)
 
 def get_repo(url, alias):
-    global dirname
+    global dirname, peer
 
     myui = ui.ui()
     myui.setconfig('ui', 'interactive', 'off')
@@ -526,7 +526,7 @@ def parse_tag(parser):
     # nothing to do
 
 def do_export(parser):
-    global parsed_refs, bmarks
+    global parsed_refs, bmarks, peer
 
     parser.next()
 
@@ -562,12 +562,17 @@ def do_export(parser):
 
     print
 
+    if peer:
+        parser.repo.push(peer, force=False)
+
 def main(args):
     global prefix, dirname, branches, bmarks
     global marks, blob_marks, parsed_refs
+    global peer
 
     alias = args[1]
     url = args[2]
+    peer = None
 
     gitdir = os.environ['GIT_DIR']
     dirname = os.path.join(gitdir, 'hg', alias)
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 04/16] remote-hg: add support to push URLs
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (2 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 03/16] remote-hg: add support for remote pushing Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 05/16] remote-hg: make sure the encoding is correct Felipe Contreras
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 45629e0..a5023c9 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -9,12 +9,13 @@
 # Then you can clone with:
 # git clone hg::/path/to/mercurial/repo/
 
-from mercurial import hg, ui, bookmarks, context
+from mercurial import hg, ui, bookmarks, context, util
 
 import re
 import sys
 import os
 import json
+import shutil
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
@@ -574,6 +575,12 @@ def main(args):
     url = args[2]
     peer = None
 
+    if alias[4:] == url:
+        is_tmp = True
+        alias = util.sha1(alias).hexdigest()
+    else:
+        is_tmp = False
+
     gitdir = os.environ['GIT_DIR']
     dirname = os.path.join(gitdir, 'hg', alias)
     branches = {}
@@ -604,6 +611,9 @@ def main(args):
             die('unhandled command: %s' % line)
         sys.stdout.flush()
 
-    marks.store()
+    if not is_tmp:
+        marks.store()
+    else:
+        shutil.rmtree(dirname)
 
 sys.exit(main(sys.argv))
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 05/16] remote-hg: make sure the encoding is correct
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (3 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 04/16] remote-hg: add support to push URLs Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 06/16] remote-hg: match hg merge behavior Felipe Contreras
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Independently of the environment.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index a5023c9..503a9fc 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -9,7 +9,7 @@
 # Then you can clone with:
 # git clone hg::/path/to/mercurial/repo/
 
-from mercurial import hg, ui, bookmarks, context, util
+from mercurial import hg, ui, bookmarks, context, util, encoding
 
 import re
 import sys
@@ -391,6 +391,9 @@ def do_import(parser):
     print "feature export-marks=%s" % path
     sys.stdout.flush()
 
+    tmp = encoding.encoding
+    encoding.encoding = 'utf-8'
+
     # lets get all the import lines
     while parser.check('import'):
         ref = parser[1]
@@ -409,6 +412,8 @@ def do_import(parser):
 
         parser.next()
 
+    encoding.encoding = tmp
+
     print 'done'
 
 def parse_blob(parser):
@@ -491,8 +496,13 @@ def parse_commit(parser):
             files.keys(), getfilectx,
             user, (date, tz), extra)
 
+    tmp = encoding.encoding
+    encoding.encoding = 'utf-8'
+
     node = repo.commitctx(ctx)
 
+    encoding.encoding = tmp
+
     rev = repo[node].rev()
 
     parsed_refs[ref] = node
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 06/16] remote-hg: match hg merge behavior
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (4 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 05/16] remote-hg: make sure the encoding is correct Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 07/16] remote-hg: add support for hg-git compat mode Felipe Contreras
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 503a9fc..247b7cb 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -427,6 +427,14 @@ def parse_blob(parser):
     parser.next()
     return
 
+def get_merge_files(repo, p1, p2, files):
+    for e in repo[p1].files():
+        if e not in files:
+            if e not in repo[p1].manifest():
+                continue
+            f = { 'ctx' : repo[p1][e] }
+            files[e] = f
+
 def parse_commit(parser):
     global marks, blob_marks, bmarks, parsed_refs
 
@@ -470,6 +478,8 @@ def parse_commit(parser):
         of = files[f]
         if 'deleted' in of:
             raise IOError
+        if 'ctx' in of:
+            return of['ctx']
         is_exec = of['mode'] == 'x'
         is_link = of['mode'] == 'l'
         return context.memfilectx(f, of['data'], is_link, is_exec, None)
@@ -492,6 +502,13 @@ def parse_commit(parser):
     else:
         p2 = '\0' * 20
 
+    #
+    # If files changed from any of the parents, hg wants to know, but in git if
+    # nothing changed from the first parent, nothing changed.
+    #
+    if merge_mark:
+        get_merge_files(repo, p1, p2, files)
+
     ctx = context.memctx(repo, (p1, p2), data,
             files.keys(), getfilectx,
             user, (date, tz), extra)
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 07/16] remote-hg: add support for hg-git compat mode
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (5 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 06/16] remote-hg: match hg merge behavior Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-28 20:23   ` W. Trevor King
  2012-11-04  2:13 ` [PATCH v6 08/16] remote-hg: add compat for hg-git author fixes Felipe Contreras
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 89 +++++++++++++++++++++++++++++++++---
 1 file changed, 83 insertions(+), 6 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 247b7cb..d585756 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -16,6 +16,22 @@ import sys
 import os
 import json
 import shutil
+import subprocess
+
+#
+# If you want to switch to hg-git compatibility mode:
+# git config --global remote-hg.hg-git-compat true
+#
+# git:
+# Sensible defaults for git.
+# hg bookmarks are exported as git branches, hg branches are prefixed
+# with 'branches/'.
+#
+# hg:
+# Emulate hg-git.
+# Only hg bookmarks are exported as git branches.
+# Commits are modified to preserve hg information and allow biridectionality.
+#
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
@@ -226,7 +242,7 @@ def mark_to_rev(mark):
     return marks.to_rev(mark)
 
 def export_ref(repo, name, kind, head):
-    global prefix, marks
+    global prefix, marks, mode
 
     ename = '%s/%s' % (kind, name)
     tip = marks.get_tip(ename)
@@ -261,6 +277,33 @@ def export_ref(repo, name, kind, head):
         else:
             modified, removed = get_filechanges(repo, c, parents[0])
 
+        if mode == 'hg':
+            extra_msg = ''
+
+            if rev_branch != 'default':
+                extra_msg += 'branch : %s\n' % rev_branch
+
+            renames = []
+            for f in c.files():
+                if f not in c.manifest():
+                    continue
+                rename = c.filectx(f).renamed()
+                if rename:
+                    renames.append((rename[0], f))
+
+            for e in renames:
+                extra_msg += "rename : %s => %s\n" % e
+
+            for key, value in extra.iteritems():
+                if key in ('author', 'committer', 'encoding', 'message', 'branch', 'hg-git'):
+                    continue
+                else:
+                    extra_msg += "extra : %s : %s\n" % (key, urllib.quote(value))
+
+            desc += '\n'
+            if extra_msg:
+                desc += '\n--HG--\n' + extra_msg
+
         if len(parents) == 0 and rev:
             print 'reset %s/%s' % (prefix, ename)
 
@@ -354,7 +397,7 @@ def list_head(repo, cur):
     g_head = (head, node)
 
 def do_list(parser):
-    global branches, bmarks
+    global branches, bmarks, mode
 
     repo = parser.repo
     for branch in repo.branchmap():
@@ -368,8 +411,11 @@ def do_list(parser):
     cur = repo.dirstate.branch()
 
     list_head(repo, cur)
-    for branch in branches:
-        print "? refs/heads/branches/%s" % branch
+
+    if mode != 'hg':
+        for branch in branches:
+            print "? refs/heads/branches/%s" % branch
+
     for bmark in bmarks:
         print "? refs/heads/%s" % bmark
 
@@ -437,6 +483,7 @@ def get_merge_files(repo, p1, p2, files):
 
 def parse_commit(parser):
     global marks, blob_marks, bmarks, parsed_refs
+    global mode
 
     from_mark = merge_mark = None
 
@@ -482,7 +529,9 @@ def parse_commit(parser):
             return of['ctx']
         is_exec = of['mode'] == 'x'
         is_link = of['mode'] == 'l'
-        return context.memfilectx(f, of['data'], is_link, is_exec, None)
+        rename = of.get('rename', None)
+        return context.memfilectx(f, of['data'],
+                is_link, is_exec, rename)
 
     repo = parser.repo
 
@@ -509,6 +558,21 @@ def parse_commit(parser):
     if merge_mark:
         get_merge_files(repo, p1, p2, files)
 
+    if mode == 'hg':
+        i = data.find('\n--HG--\n')
+        if i >= 0:
+            tmp = data[i + len('\n--HG--\n'):].strip()
+            for k, v in [e.split(' : ') for e in tmp.split('\n')]:
+                if k == 'rename':
+                    old, new = v.split(' => ', 1)
+                    files[new]['rename'] = old
+                elif k == 'branch':
+                    extra[k] = v
+                elif k == 'extra':
+                    ek, ev = v.split(' : ', 1)
+                    extra[ek] = urllib.unquote(ev)
+            data = data[:i]
+
     ctx = context.memctx(repo, (p1, p2), data,
             files.keys(), getfilectx,
             user, (date, tz), extra)
@@ -596,12 +660,25 @@ def do_export(parser):
 def main(args):
     global prefix, dirname, branches, bmarks
     global marks, blob_marks, parsed_refs
-    global peer
+    global peer, mode
 
     alias = args[1]
     url = args[2]
     peer = None
 
+    cmd = ['git', 'config', '--get', 'remote-hg.hg-git-compat']
+    hg_git_compat = False
+    try:
+        if subprocess.check_output(cmd) == 'true\n':
+            hg_git_compat = True
+    except subprocess.CalledProcessError:
+        pass
+
+    if hg_git_compat:
+        mode = 'hg'
+    else:
+        mode = 'git'
+
     if alias[4:] == url:
         is_tmp = True
         alias = util.sha1(alias).hexdigest()
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 08/16] remote-hg: add compat for hg-git author fixes
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (6 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 07/16] remote-hg: add support for hg-git compat mode Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 09/16] remote-hg: fake bookmark when there's none Felipe Contreras
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 59 ++++++++++++++++++++++++++++++++----
 1 file changed, 53 insertions(+), 6 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index d585756..9db4b7e 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -17,6 +17,7 @@ import os
 import json
 import shutil
 import subprocess
+import urllib
 
 #
 # If you want to switch to hg-git compatibility mode:
@@ -35,6 +36,7 @@ import subprocess
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+AUTHOR_HG_RE = re.compile('^(.*?) ?<(.+?)(?:>(.+)?)?$')
 RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.+)> (\d+) ([+-]\d+)')
 
 def die(msg, *args):
@@ -152,12 +154,20 @@ class Parser:
         return sys.stdin.read(size)
 
     def get_author(self):
+        global bad_mail
+
+        ex = None
         m = RAW_AUTHOR_RE.match(self.line)
         if not m:
             return None
         _, name, email, date, tz = m.groups()
+        if name and 'ext:' in name:
+            m = re.match('^(.+?) ext:\((.+)\)$', name)
+            if m:
+                name = m.group(1)
+                ex = urllib.unquote(m.group(2))
 
-        if email != 'unknown':
+        if email != bad_mail:
             if name:
                 user = '%s <%s>' % (name, email)
             else:
@@ -165,6 +175,9 @@ class Parser:
         else:
             user = name
 
+        if ex:
+            user += ex
+
         tz = int(tz)
         tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
         return (user, int(date), -tz)
@@ -194,9 +207,9 @@ def get_filechanges(repo, ctx, parent):
 
     return added | modified, removed
 
-def fixup_user(user):
-    user = user.replace('"', '')
+def fixup_user_git(user):
     name = mail = None
+    user = user.replace('"', '')
     m = AUTHOR_RE.match(user)
     if m:
         name = m.group(1)
@@ -205,11 +218,41 @@ def fixup_user(user):
         m = NAME_RE.match(user)
         if m:
             name = m.group(1).strip()
+    return (name, mail)
+
+def fixup_user_hg(user):
+    def sanitize(name):
+        # stole this from hg-git
+        return re.sub('[<>\n]', '?', name.lstrip('< ').rstrip('> '))
+
+    m = AUTHOR_HG_RE.match(user)
+    if m:
+        name = sanitize(m.group(1))
+        mail = sanitize(m.group(2))
+        ex = m.group(3)
+        if ex:
+            name += ' ext:(' + urllib.quote(ex) + ')'
+    else:
+        name = sanitize(user)
+        if '@' in user:
+            mail = name
+        else:
+            mail = None
+
+    return (name, mail)
+
+def fixup_user(user):
+    global mode, bad_mail
+
+    if mode == 'git':
+        name, mail = fixup_user_git(user)
+    else:
+        name, mail = fixup_user_hg(user)
 
     if not name:
-        name = 'Unknown'
+        name = bad_name
     if not mail:
-        mail = 'unknown'
+        mail = bad_mail
 
     return '%s <%s>' % (name, mail)
 
@@ -660,7 +703,7 @@ def do_export(parser):
 def main(args):
     global prefix, dirname, branches, bmarks
     global marks, blob_marks, parsed_refs
-    global peer, mode
+    global peer, mode, bad_mail, bad_name
 
     alias = args[1]
     url = args[2]
@@ -676,8 +719,12 @@ def main(args):
 
     if hg_git_compat:
         mode = 'hg'
+        bad_mail = 'none@none'
+        bad_name = ''
     else:
         mode = 'git'
+        bad_mail = 'unknown'
+        bad_name = 'Unknown'
 
     if alias[4:] == url:
         is_tmp = True
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 09/16] remote-hg: fake bookmark when there's none
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (7 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 08/16] remote-hg: add compat for hg-git author fixes Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 10/16] remote-hg: add basic tests Felipe Contreras
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Or at least no current bookmark.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 9db4b7e..dbe309a 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -26,7 +26,7 @@ import urllib
 # git:
 # Sensible defaults for git.
 # hg bookmarks are exported as git branches, hg branches are prefixed
-# with 'branches/'.
+# with 'branches/', HEAD is a special case.
 #
 # hg:
 # Emulate hg-git.
@@ -430,12 +430,21 @@ def get_branch_tip(repo, branch):
     return heads[0]
 
 def list_head(repo, cur):
-    global g_head
+    global g_head, bmarks
 
     head = bookmarks.readcurrent(repo)
-    if not head:
-        return
-    node = repo[head]
+    if head:
+        node = repo[head]
+    else:
+        # fake bookmark from current branch
+        head = cur
+        node = repo['.']
+        if not node:
+            return
+        if head == 'default':
+            head = 'master'
+        bmarks[head] = node
+
     print "@refs/heads/%s HEAD" % head
     g_head = (head, node)
 
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 10/16] remote-hg: add basic tests
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (8 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 09/16] remote-hg: fake bookmark when there's none Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 11/16] test-lib: avoid full path to store test results Felipe Contreras
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/Makefile   |  13 +++++
 contrib/remote-helpers/test-hg.sh | 112 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 125 insertions(+)
 create mode 100644 contrib/remote-helpers/Makefile
 create mode 100755 contrib/remote-helpers/test-hg.sh

diff --git a/contrib/remote-helpers/Makefile b/contrib/remote-helpers/Makefile
new file mode 100644
index 0000000..9a76575
--- /dev/null
+++ b/contrib/remote-helpers/Makefile
@@ -0,0 +1,13 @@
+TESTS := $(wildcard test*.sh)
+
+export T := $(addprefix $(CURDIR)/,$(TESTS))
+export MAKE := $(MAKE) -e
+export PATH := $(CURDIR):$(PATH)
+
+test:
+	$(MAKE) -C ../../t $@
+
+$(TESTS):
+	$(MAKE) -C ../../t $(CURDIR)/$@
+
+.PHONY: $(TESTS)
diff --git a/contrib/remote-helpers/test-hg.sh b/contrib/remote-helpers/test-hg.sh
new file mode 100755
index 0000000..40e6e3c
--- /dev/null
+++ b/contrib/remote-helpers/test-hg.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+# Base commands from hg-git tests:
+# https://bitbucket.org/durin42/hg-git/src
+#
+
+test_description='Test remote-hg'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+	skip_all='skipping remote-hg tests; python not available'
+	test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import mercurial'; then
+	skip_all='skipping remote-hg tests; mercurial not available'
+	test_done
+fi
+
+check () {
+	(cd $1 &&
+	git log --format='%s' -1 &&
+	git symbolic-ref HEAD) > actual &&
+	(echo $2 &&
+	echo "refs/heads/$3") > expected &&
+	test_cmp expected actual
+}
+
+test_expect_success 'cloning' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  hg init hgrepo &&
+  cd hgrepo &&
+  echo zero > content &&
+  hg add content &&
+  hg commit -m zero
+  ) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  check gitrepo zero master
+'
+
+test_expect_success 'cloning with branches' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  cd hgrepo &&
+  hg branch next &&
+  echo next > content &&
+  hg commit -m next
+  ) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  check gitrepo next next &&
+
+  (cd hgrepo && hg checkout default) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo2 &&
+  check gitrepo2 zero master
+'
+
+test_expect_success 'cloning with bookmarks' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  cd hgrepo &&
+  hg bookmark feature-a &&
+  echo feature-a > content &&
+  hg commit -m feature-a
+  ) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  check gitrepo feature-a feature-a
+'
+
+test_expect_success 'cloning with detached head' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  cd hgrepo &&
+  hg update -r 0
+  ) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  check gitrepo zero master
+'
+
+test_expect_success 'update bookmark' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  cd hgrepo &&
+  hg bookmark devel
+  ) &&
+
+  (
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  cd gitrepo &&
+  git checkout devel &&
+  echo devel > content &&
+  git commit -a -m devel &&
+  git push
+  ) &&
+
+  hg -R hgrepo bookmarks | grep "devel\s\+3:"
+'
+
+test_done
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 11/16] test-lib: avoid full path to store test results
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (9 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 10/16] remote-hg: add basic tests Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 12/16] remote-hg: add bidirectional tests Felipe Contreras
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

No reason to use the full path in case this is used externally.

Otherwise we might get errors such as:

./test-lib.sh: line 394: /home/bob/dev/git/t/test-results//home/bob/dev/git/contrib/remote-hg/test-2894.counts: No such file or directory

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 t/test-lib.sh | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/t/test-lib.sh b/t/test-lib.sh
index 514282c..5a3d665 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -389,7 +389,8 @@ test_done () {
 	then
 		test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
 		mkdir -p "$test_results_dir"
-		test_results_path="$test_results_dir/${0%.sh}-$$.counts"
+		base=${0##*/}
+		test_results_path="$test_results_dir/${base%.sh}-$$.counts"
 
 		cat >>"$test_results_path" <<-EOF
 		total $test_count
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 12/16] remote-hg: add bidirectional tests
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (10 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 11/16] test-lib: avoid full path to store test results Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 13/16] remote-hg: add tests to compare with hg-git Felipe Contreras
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Base commands from hg-git tests:
https://bitbucket.org/durin42/hg-git/src

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/test-hg-bidi.sh | 243 +++++++++++++++++++++++++++++++++
 1 file changed, 243 insertions(+)
 create mode 100755 contrib/remote-helpers/test-hg-bidi.sh

diff --git a/contrib/remote-helpers/test-hg-bidi.sh b/contrib/remote-helpers/test-hg-bidi.sh
new file mode 100755
index 0000000..a94eb28
--- /dev/null
+++ b/contrib/remote-helpers/test-hg-bidi.sh
@@ -0,0 +1,243 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+# Base commands from hg-git tests:
+# https://bitbucket.org/durin42/hg-git/src
+#
+
+test_description='Test biridectionality of remote-hg'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+	skip_all='skipping remote-hg tests; python not available'
+	test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import mercurial'; then
+	skip_all='skipping remote-hg tests; mercurial not available'
+	test_done
+fi
+
+# clone to a git repo
+git_clone () {
+	hg -R $1 bookmark -f -r tip master &&
+	git clone -q "hg::$PWD/$1" $2
+}
+
+# clone to an hg repo
+hg_clone () {
+	(
+	hg init $2 &&
+	cd $1 &&
+	git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
+	) &&
+
+	(cd $2 && hg -q update)
+}
+
+# push an hg repo
+hg_push () {
+	(
+	cd $2
+	old=$(git symbolic-ref --short HEAD)
+	git checkout -q -b tmp &&
+	git fetch -q "hg::$PWD/../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
+	git checkout -q $old &&
+	git branch -q -D tmp 2> /dev/null || true
+	)
+}
+
+hg_log () {
+	hg -R $1 log --graph --debug | grep -v 'tag: *default/'
+}
+
+setup () {
+	(
+	echo "[ui]"
+	echo "username = A U Thor <author@example.com>"
+	echo "[defaults]"
+	echo "backout = -d \"0 0\""
+	echo "commit = -d \"0 0\""
+	echo "debugrawcommit = -d \"0 0\""
+	echo "tag = -d \"0 0\""
+	) >> "$HOME"/.hgrc &&
+	git config --global remote-hg.hg-git-compat true
+
+	export HGEDITOR=/usr/bin/true
+
+	export GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
+	export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+}
+
+setup
+
+test_expect_success 'encoding' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	git init -q gitrepo &&
+	cd gitrepo &&
+
+	echo alpha > alpha &&
+	git add alpha &&
+	git commit -m "add älphà" &&
+
+	export GIT_AUTHOR_NAME="tést èncödîng" &&
+	echo beta > beta &&
+	git add beta &&
+	git commit -m "add beta" &&
+
+	echo gamma > gamma &&
+	git add gamma &&
+	git commit -m "add gämmâ" &&
+
+	: TODO git config i18n.commitencoding latin-1 &&
+	echo delta > delta &&
+	git add delta &&
+	git commit -m "add déltà"
+	) &&
+
+	hg_clone gitrepo hgrepo &&
+	git_clone hgrepo gitrepo2 &&
+	hg_clone gitrepo2 hgrepo2 &&
+
+	HGENCODING=utf-8 hg_log hgrepo > expected &&
+	HGENCODING=utf-8 hg_log hgrepo2 > actual &&
+
+	test_cmp expected actual
+'
+
+test_expect_success 'file removal' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	git init -q gitrepo &&
+	cd gitrepo &&
+	echo alpha > alpha &&
+	git add alpha &&
+	git commit -m "add alpha" &&
+	echo beta > beta &&
+	git add beta &&
+	git commit -m "add beta"
+	mkdir foo &&
+	echo blah > foo/bar &&
+	git add foo &&
+	git commit -m "add foo" &&
+	git rm alpha &&
+	git commit -m "remove alpha" &&
+	git rm foo/bar &&
+	git commit -m "remove foo/bar"
+	) &&
+
+	hg_clone gitrepo hgrepo &&
+	git_clone hgrepo gitrepo2 &&
+	hg_clone gitrepo2 hgrepo2 &&
+
+	hg_log hgrepo > expected &&
+	hg_log hgrepo2 > actual &&
+
+	test_cmp expected actual
+'
+
+test_expect_success 'git tags' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	git init -q gitrepo &&
+	cd gitrepo &&
+	git config receive.denyCurrentBranch ignore &&
+	echo alpha > alpha &&
+	git add alpha &&
+	git commit -m "add alpha" &&
+	git tag alpha &&
+
+	echo beta > beta &&
+	git add beta &&
+	git commit -m "add beta" &&
+	git tag -a -m "added tag beta" beta
+	) &&
+
+	hg_clone gitrepo hgrepo &&
+	git_clone hgrepo gitrepo2 &&
+	hg_clone gitrepo2 hgrepo2 &&
+
+	hg_log hgrepo > expected &&
+	hg_log hgrepo2 > actual &&
+
+	test_cmp expected actual
+'
+
+test_expect_success 'hg branch' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	git init -q gitrepo &&
+	cd gitrepo &&
+
+	echo alpha > alpha &&
+	git add alpha &&
+	git commit -q -m "add alpha" &&
+	git checkout -q -b not-master
+	) &&
+
+	(
+	hg_clone gitrepo hgrepo &&
+
+	cd hgrepo &&
+	hg -q co master &&
+	hg mv alpha beta &&
+	hg -q commit -m "rename alpha to beta" &&
+	hg branch gamma | grep -v "permanent and global" &&
+	hg -q commit -m "started branch gamma"
+	) &&
+
+	hg_push hgrepo gitrepo &&
+	hg_clone gitrepo hgrepo2 &&
+
+	: TODO, avoid "master" bookmark &&
+	(cd hgrepo2 && hg checkout gamma) &&
+
+	hg_log hgrepo > expected &&
+	hg_log hgrepo2 > actual &&
+
+	test_cmp expected actual
+'
+
+test_expect_success 'hg tags' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	git init -q gitrepo &&
+	cd gitrepo &&
+
+	echo alpha > alpha &&
+	git add alpha &&
+	git commit -m "add alpha" &&
+	git checkout -q -b not-master
+	) &&
+
+	(
+	hg_clone gitrepo hgrepo &&
+
+	cd hgrepo &&
+	hg co master &&
+	hg tag alpha
+	) &&
+
+	hg_push hgrepo gitrepo &&
+	hg_clone gitrepo hgrepo2 &&
+
+	hg_log hgrepo > expected &&
+	hg_log hgrepo2 > actual &&
+
+	test_cmp expected actual
+'
+
+test_done
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 13/16] remote-hg: add tests to compare with hg-git
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (11 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 12/16] remote-hg: add bidirectional tests Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 14/16] remote-hg: add extra author test Felipe Contreras
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

The base commands come from the tests of the hg-git project.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/test-hg-hg-git.sh | 462 +++++++++++++++++++++++++++++++
 1 file changed, 462 insertions(+)
 create mode 100755 contrib/remote-helpers/test-hg-hg-git.sh

diff --git a/contrib/remote-helpers/test-hg-hg-git.sh b/contrib/remote-helpers/test-hg-hg-git.sh
new file mode 100755
index 0000000..e07bba5
--- /dev/null
+++ b/contrib/remote-helpers/test-hg-hg-git.sh
@@ -0,0 +1,462 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+# Base commands from hg-git tests:
+# https://bitbucket.org/durin42/hg-git/src
+#
+
+test_description='Test remote-hg output compared to hg-git'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+	skip_all='skipping remote-hg tests; python not available'
+	test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import mercurial'; then
+	skip_all='skipping remote-hg tests; mercurial not available'
+	test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import hggit'; then
+	skip_all='skipping remote-hg tests; hg-git not available'
+	test_done
+fi
+
+# clone to a git repo with git
+git_clone_git () {
+	hg -R $1 bookmark -f -r tip master &&
+	git clone -q "hg::$PWD/$1" $2
+}
+
+# clone to an hg repo with git
+hg_clone_git () {
+	(
+	hg init $2 &&
+	cd $1 &&
+	git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
+	) &&
+
+	(cd $2 && hg -q update)
+}
+
+# clone to a git repo with hg
+git_clone_hg () {
+	(
+	git init -q $2 &&
+	cd $1 &&
+	hg bookmark -f -r tip master &&
+	hg -q push -r master ../$2 || true
+	)
+}
+
+# clone to an hg repo with hg
+hg_clone_hg () {
+	hg -q clone $1 $2
+}
+
+# push an hg repo with git
+hg_push_git () {
+	(
+	cd $2
+	old=$(git symbolic-ref --short HEAD)
+	git checkout -q -b tmp &&
+	git fetch -q "hg::$PWD/../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
+	git checkout -q $old &&
+	git branch -q -D tmp 2> /dev/null || true
+	)
+}
+
+# push an hg git repo with hg
+hg_push_hg () {
+	(
+	cd $1 &&
+	hg -q push ../$2 || true
+	)
+}
+
+hg_log () {
+	hg -R $1 log --graph --debug | grep -v 'tag: *default/'
+}
+
+git_log () {
+	git --git-dir=$1/.git fast-export --branches
+}
+
+setup () {
+	(
+	echo "[ui]"
+	echo "username = A U Thor <author@example.com>"
+	echo "[defaults]"
+	echo "backout = -d \"0 0\""
+	echo "commit = -d \"0 0\""
+	echo "debugrawcommit = -d \"0 0\""
+	echo "tag = -d \"0 0\""
+	echo "[extensions]"
+	echo "hgext.bookmarks ="
+	echo "hggit ="
+	) >> "$HOME"/.hgrc &&
+	git config --global receive.denycurrentbranch warn
+	git config --global remote-hg.hg-git-compat true
+
+	export HGEDITOR=/usr/bin/true
+
+	export GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
+	export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+}
+
+setup
+
+test_expect_success 'merge conflict 1' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	hg init hgrepo1 &&
+	cd hgrepo1 &&
+	echo A > afile &&
+	hg add afile &&
+	hg ci -m "origin" &&
+
+	echo B > afile &&
+	hg ci -m "A->B" &&
+
+	hg up -r0 &&
+	echo C > afile &&
+	hg ci -m "A->C" &&
+
+	hg merge -r1 || true &&
+	echo C > afile &&
+	hg resolve -m afile &&
+	hg ci -m "merge to C"
+	) &&
+
+	for x in hg git; do
+		git_clone_$x hgrepo1 gitrepo-$x &&
+		hg_clone_$x gitrepo-$x hgrepo2-$x &&
+		hg_log hgrepo2-$x > hg-log-$x &&
+		git_log gitrepo-$x > git-log-$x
+	done &&
+
+	test_cmp hg-log-hg hg-log-git &&
+	test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'merge conflict 2' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	hg init hgrepo1 &&
+	cd hgrepo1 &&
+	echo A > afile &&
+	hg add afile &&
+	hg ci -m "origin" &&
+
+	echo B > afile &&
+	hg ci -m "A->B" &&
+
+	hg up -r0 &&
+	echo C > afile &&
+	hg ci -m "A->C" &&
+
+	hg merge -r1 || true &&
+	echo B > afile &&
+	hg resolve -m afile &&
+	hg ci -m "merge to B"
+	) &&
+
+	for x in hg git; do
+		git_clone_$x hgrepo1 gitrepo-$x &&
+		hg_clone_$x gitrepo-$x hgrepo2-$x &&
+		hg_log hgrepo2-$x > hg-log-$x &&
+		git_log gitrepo-$x > git-log-$x
+	done &&
+
+	test_cmp hg-log-hg hg-log-git &&
+	test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'converged merge' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	hg init hgrepo1 &&
+	cd hgrepo1 &&
+	echo A > afile &&
+	hg add afile &&
+	hg ci -m "origin" &&
+
+	echo B > afile &&
+	hg ci -m "A->B" &&
+
+	echo C > afile &&
+	hg ci -m "B->C" &&
+
+	hg up -r0 &&
+	echo C > afile &&
+	hg ci -m "A->C" &&
+
+	hg merge -r2 || true &&
+	hg ci -m "merge"
+	) &&
+
+	for x in hg git; do
+		git_clone_$x hgrepo1 gitrepo-$x &&
+		hg_clone_$x gitrepo-$x hgrepo2-$x &&
+		hg_log hgrepo2-$x > hg-log-$x &&
+		git_log gitrepo-$x > git-log-$x
+	done &&
+
+	test_cmp hg-log-hg hg-log-git &&
+	test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'encoding' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	git init -q gitrepo &&
+	cd gitrepo &&
+
+	echo alpha > alpha &&
+	git add alpha &&
+	git commit -m "add älphà" &&
+
+	export GIT_AUTHOR_NAME="tést èncödîng" &&
+	echo beta > beta &&
+	git add beta &&
+	git commit -m "add beta" &&
+
+	echo gamma > gamma &&
+	git add gamma &&
+	git commit -m "add gämmâ" &&
+
+	: TODO git config i18n.commitencoding latin-1 &&
+	echo delta > delta &&
+	git add delta &&
+	git commit -m "add déltà"
+	) &&
+
+	for x in hg git; do
+		hg_clone_$x gitrepo hgrepo-$x &&
+		git_clone_$x hgrepo-$x gitrepo2-$x &&
+
+		HGENCODING=utf-8 hg_log hgrepo-$x > hg-log-$x &&
+		git_log gitrepo2-$x > git-log-$x
+	done &&
+
+	test_cmp hg-log-hg hg-log-git &&
+	test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'file removal' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	git init -q gitrepo &&
+	cd gitrepo &&
+	echo alpha > alpha &&
+	git add alpha &&
+	git commit -m "add alpha" &&
+	echo beta > beta &&
+	git add beta &&
+	git commit -m "add beta"
+	mkdir foo &&
+	echo blah > foo/bar &&
+	git add foo &&
+	git commit -m "add foo" &&
+	git rm alpha &&
+	git commit -m "remove alpha" &&
+	git rm foo/bar &&
+	git commit -m "remove foo/bar"
+	) &&
+
+	for x in hg git; do
+		(
+		hg_clone_$x gitrepo hgrepo-$x &&
+		cd hgrepo-$x &&
+		hg_log . &&
+		hg manifest -r 3 &&
+		hg manifest
+		) > output-$x &&
+
+		git_clone_$x hgrepo-$x gitrepo2-$x &&
+		git_log gitrepo2-$x > log-$x
+	done &&
+
+	test_cmp output-hg output-git &&
+	test_cmp log-hg log-git
+'
+
+test_expect_success 'git tags' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	(
+	git init -q gitrepo &&
+	cd gitrepo &&
+	git config receive.denyCurrentBranch ignore &&
+	echo alpha > alpha &&
+	git add alpha &&
+	git commit -m "add alpha" &&
+	git tag alpha &&
+
+	echo beta > beta &&
+	git add beta &&
+	git commit -m "add beta" &&
+	git tag -a -m "added tag beta" beta
+	) &&
+
+	for x in hg git; do
+		hg_clone_$x gitrepo hgrepo-$x &&
+		hg_log hgrepo-$x > log-$x
+	done &&
+
+	test_cmp log-hg log-git
+'
+
+test_expect_success 'hg author' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	for x in hg git; do
+		(
+		git init -q gitrepo-$x &&
+		cd gitrepo-$x &&
+
+		echo alpha > alpha &&
+		git add alpha &&
+		git commit -m "add alpha" &&
+		git checkout -q -b not-master
+		) &&
+
+		(
+		hg_clone_$x gitrepo-$x hgrepo-$x &&
+		cd hgrepo-$x &&
+
+		hg co master &&
+		echo beta > beta &&
+		hg add beta &&
+		hg commit -u "test" -m "add beta" &&
+
+		echo gamma >> beta &&
+		hg commit -u "test <test@example.com> (comment)" -m "modify beta" &&
+
+		echo gamma > gamma &&
+		hg add gamma &&
+		hg commit -u "<test@example.com>" -m "add gamma" &&
+
+		echo delta > delta &&
+		hg add delta &&
+		hg commit -u "name<test@example.com>" -m "add delta" &&
+
+		echo epsilon > epsilon &&
+		hg add epsilon &&
+		hg commit -u "name <test@example.com" -m "add epsilon" &&
+
+		echo zeta > zeta &&
+		hg add zeta &&
+		hg commit -u " test " -m "add zeta" &&
+
+		echo eta > eta &&
+		hg add eta &&
+		hg commit -u "test < test@example.com >" -m "add eta" &&
+
+		echo theta > theta &&
+		hg add theta &&
+		hg commit -u "test >test@example.com>" -m "add theta"
+		) &&
+
+		hg_push_$x hgrepo-$x gitrepo-$x &&
+		hg_clone_$x gitrepo-$x hgrepo2-$x &&
+
+		hg_log hgrepo2-$x > hg-log-$x &&
+		git_log gitrepo-$x > git-log-$x
+	done &&
+
+	test_cmp git-log-hg git-log-git &&
+
+	test_cmp hg-log-hg hg-log-git &&
+	test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'hg branch' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	for x in hg git; do
+		(
+		git init -q gitrepo-$x &&
+		cd gitrepo-$x &&
+
+		echo alpha > alpha &&
+		git add alpha &&
+		git commit -q -m "add alpha" &&
+		git checkout -q -b not-master
+		) &&
+
+		(
+		hg_clone_$x gitrepo-$x hgrepo-$x &&
+
+		cd hgrepo-$x &&
+		hg -q co master &&
+		hg mv alpha beta &&
+		hg -q commit -m "rename alpha to beta" &&
+		hg branch gamma | grep -v "permanent and global" &&
+		hg -q commit -m "started branch gamma"
+		) &&
+
+		hg_push_$x hgrepo-$x gitrepo-$x &&
+		hg_clone_$x gitrepo-$x hgrepo2-$x &&
+
+		hg_log hgrepo2-$x > hg-log-$x &&
+		git_log gitrepo-$x > git-log-$x
+	done &&
+
+	test_cmp hg-log-hg hg-log-git &&
+	test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'hg tags' '
+	mkdir -p tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	for x in hg git; do
+		(
+		git init -q gitrepo-$x &&
+		cd gitrepo-$x &&
+
+		echo alpha > alpha &&
+		git add alpha &&
+		git commit -m "add alpha" &&
+		git checkout -q -b not-master
+		) &&
+
+		(
+		hg_clone_$x gitrepo-$x hgrepo-$x &&
+
+		cd hgrepo-$x &&
+		hg co master &&
+		hg tag alpha
+		) &&
+
+		hg_push_$x hgrepo-$x gitrepo-$x &&
+		hg_clone_$x gitrepo-$x hgrepo2-$x &&
+
+		(
+		git --git-dir=gitrepo-$x/.git tag -l &&
+		hg_log hgrepo2-$x &&
+		cat hgrepo2-$x/.hgtags
+		) > output-$x
+	done &&
+
+	test_cmp output-hg output-git
+'
+
+test_done
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 14/16] remote-hg: add extra author test
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (12 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 13/16] remote-hg: add tests to compare with hg-git Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 15/16] remote-hg: add option to not track branches Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 16/16] remote-hg: the author email can be null Felipe Contreras
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

For hg.hg.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/test-hg-hg-git.sh | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/contrib/remote-helpers/test-hg-hg-git.sh b/contrib/remote-helpers/test-hg-hg-git.sh
index e07bba5..3e76d9f 100755
--- a/contrib/remote-helpers/test-hg-hg-git.sh
+++ b/contrib/remote-helpers/test-hg-hg-git.sh
@@ -370,7 +370,11 @@ test_expect_success 'hg author' '
 
 		echo theta > theta &&
 		hg add theta &&
-		hg commit -u "test >test@example.com>" -m "add theta"
+		hg commit -u "test >test@example.com>" -m "add theta" &&
+
+		echo iota > iota &&
+		hg add iota &&
+		hg commit -u "test <test <at> example <dot> com>" -m "add iota"
 		) &&
 
 		hg_push_$x hgrepo-$x gitrepo-$x &&
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 15/16] remote-hg: add option to not track branches
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (13 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 14/16] remote-hg: add extra author test Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  2012-11-04  2:13 ` [PATCH v6 16/16] remote-hg: the author email can be null Felipe Contreras
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Some people prefer it this way.

 % git config --global remote-hg.track-branches false

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index dbe309a..a9ae844 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -449,14 +449,9 @@ def list_head(repo, cur):
     g_head = (head, node)
 
 def do_list(parser):
-    global branches, bmarks, mode
+    global branches, bmarks, mode, track_branches
 
     repo = parser.repo
-    for branch in repo.branchmap():
-        heads = repo.branchheads(branch)
-        if len(heads):
-            branches[branch] = heads
-
     for bmark, node in bookmarks.listbookmarks(repo).iteritems():
         bmarks[bmark] = repo[node]
 
@@ -464,7 +459,12 @@ def do_list(parser):
 
     list_head(repo, cur)
 
-    if mode != 'hg':
+    if track_branches:
+        for branch in repo.branchmap():
+            heads = repo.branchheads(branch)
+            if len(heads):
+                branches[branch] = heads
+
         for branch in branches:
             print "? refs/heads/branches/%s" % branch
 
@@ -713,16 +713,22 @@ def main(args):
     global prefix, dirname, branches, bmarks
     global marks, blob_marks, parsed_refs
     global peer, mode, bad_mail, bad_name
+    global track_branches
 
     alias = args[1]
     url = args[2]
     peer = None
 
-    cmd = ['git', 'config', '--get', 'remote-hg.hg-git-compat']
     hg_git_compat = False
+    track_branches = True
     try:
+        cmd = ['git', 'config', '--get', 'remote-hg.hg-git-compat']
         if subprocess.check_output(cmd) == 'true\n':
             hg_git_compat = True
+            track_branches = False
+        cmd = ['git', 'config', '--get', 'remote-hg.track-branches']
+        if subprocess.check_output(cmd) == 'false\n':
+            track_branches = False
     except subprocess.CalledProcessError:
         pass
 
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v6 16/16] remote-hg: the author email can be null
  2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
                   ` (14 preceding siblings ...)
  2012-11-04  2:13 ` [PATCH v6 15/16] remote-hg: add option to not track branches Felipe Contreras
@ 2012-11-04  2:13 ` Felipe Contreras
  15 siblings, 0 replies; 22+ messages in thread
From: Felipe Contreras @ 2012-11-04  2:13 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Sverre Rabbelier, Johannes Schindelin,
	Ilari Liusvaara, Daniel Barkalow, Michael J Gruber,
	Felipe Contreras

Like 'Foo <>'.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/remote-helpers/git-remote-hg | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index a9ae844..7929eec 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -35,9 +35,9 @@ import urllib
 #
 
 NAME_RE = re.compile('^([^<>]+)')
-AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
-AUTHOR_HG_RE = re.compile('^(.*?) ?<(.+?)(?:>(.+)?)?$')
-RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.+)> (\d+) ([+-]\d+)')
+AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]*)>$')
+AUTHOR_HG_RE = re.compile('^(.*?) ?<(.*?)(?:>(.+)?)?$')
+RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.*)> (\d+) ([+-]\d+)')
 
 def die(msg, *args):
     sys.stderr.write('ERROR: %s\n' % (msg % args))
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v6 07/16] remote-hg: add support for hg-git compat mode
  2012-11-04  2:13 ` [PATCH v6 07/16] remote-hg: add support for hg-git compat mode Felipe Contreras
@ 2012-11-28 20:23   ` W. Trevor King
  2013-01-08 15:47     ` [PATCH] remote-hg: Fix biridectionality -> bidirectionality typos W. Trevor King
  0 siblings, 1 reply; 22+ messages in thread
From: W. Trevor King @ 2012-11-28 20:23 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: git, Junio C Hamano, Jeff King, Sverre Rabbelier,
	Johannes Schindelin, Ilari Liusvaara, Daniel Barkalow,
	Michael J Gruber

I'm not sure if this is the most recent patch iteration for this
feature, but I just saw this typo in `pu`.

On Sun, Nov 04, 2012 at 03:13:29AM +0100, Felipe Contreras wrote:
> +# Commits are modified to preserve hg information and allow biridectionality.
                                                               ^^^^^^^^
s/biridectionality/bidirectionality/

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] remote-hg: Fix biridectionality -> bidirectionality typos
  2012-11-28 20:23   ` W. Trevor King
@ 2013-01-08 15:47     ` W. Trevor King
  2013-01-08 17:32       ` Junio C Hamano
  0 siblings, 1 reply; 22+ messages in thread
From: W. Trevor King @ 2013-01-08 15:47 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: git, Junio C Hamano, Jeff King, Sverre Rabbelier,
	Johannes Schindelin, Ilari Liusvaara, Daniel Barkalow,
	Michael J Gruber

[-- Attachment #1: Type: text/plain, Size: 1850 bytes --]

Signed-off-by: W. Trevor King <wking@tremily.us>
---

I was looking for one of my older messages to the Git list, and I
found this, which seems to have fallen through the cracks:

On Wed, Nov 28, 2012 at 03:23:20PM -0500, W. Trevor King wrote:
> I'm not sure if this is the most recent patch iteration for this
> feature, but I just saw this typo in `pu`.
> 
> On Sun, Nov 04, 2012 at 03:13:29AM +0100, Felipe Contreras wrote:
> > +# Commits are modified to preserve hg information and allow biridectionality.
>                                                                ^^^^^^^^
> s/biridectionality/bidirectionality/

This fixes that instance (which has since landed in master) and
another similar typo.

 contrib/remote-helpers/git-remote-hg   | 2 +-
 contrib/remote-helpers/test-hg-bidi.sh | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 016cdad..c700600 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -31,7 +31,7 @@ import urllib
 # hg:
 # Emulate hg-git.
 # Only hg bookmarks are exported as git branches.
-# Commits are modified to preserve hg information and allow biridectionality.
+# Commits are modified to preserve hg information and allow bidirectionality.
 #
 
 NAME_RE = re.compile('^([^<>]+)')
diff --git a/contrib/remote-helpers/test-hg-bidi.sh b/contrib/remote-helpers/test-hg-bidi.sh
index a94eb28..1d61982 100755
--- a/contrib/remote-helpers/test-hg-bidi.sh
+++ b/contrib/remote-helpers/test-hg-bidi.sh
@@ -6,7 +6,7 @@
 # https://bitbucket.org/durin42/hg-git/src
 #
 
-test_description='Test biridectionality of remote-hg'
+test_description='Test bidirectionality of remote-hg'
 
 . ./test-lib.sh
 
-- 
1.8.1.151.g32238ae

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH] remote-hg: Fix biridectionality -> bidirectionality typos
  2013-01-08 15:47     ` [PATCH] remote-hg: Fix biridectionality -> bidirectionality typos W. Trevor King
@ 2013-01-08 17:32       ` Junio C Hamano
  2013-01-08 17:50         ` W. Trevor King
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2013-01-08 17:32 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Felipe Contreras, git, Jeff King, Sverre Rabbelier,
	Johannes Schindelin, Ilari Liusvaara, Daniel Barkalow,
	Michael J Gruber

"W. Trevor King" <wking@tremily.us> writes:

> Signed-off-by: W. Trevor King <wking@tremily.us>
> ---
>
> I was looking for one of my older messages to the Git list, and I
> found this, which seems to have fallen through the cracks:

Thanks; didn't Documentation/SubmittingPatches ask you not to do PGP
multipart but send patches in plain text?

> On Wed, Nov 28, 2012 at 03:23:20PM -0500, W. Trevor King wrote:
>> I'm not sure if this is the most recent patch iteration for this
>> feature, but I just saw this typo in `pu`.
>> 
>> On Sun, Nov 04, 2012 at 03:13:29AM +0100, Felipe Contreras wrote:
>> > +# Commits are modified to preserve hg information and allow biridectionality.
>>                                                                ^^^^^^^^
>> s/biridectionality/bidirectionality/
>
> This fixes that instance (which has since landed in master) and
> another similar typo.
>
>  contrib/remote-helpers/git-remote-hg   | 2 +-
>  contrib/remote-helpers/test-hg-bidi.sh | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
> index 016cdad..c700600 100755
> --- a/contrib/remote-helpers/git-remote-hg
> +++ b/contrib/remote-helpers/git-remote-hg
> @@ -31,7 +31,7 @@ import urllib
>  # hg:
>  # Emulate hg-git.
>  # Only hg bookmarks are exported as git branches.
> -# Commits are modified to preserve hg information and allow biridectionality.
> +# Commits are modified to preserve hg information and allow bidirectionality.
>  #
>  
>  NAME_RE = re.compile('^([^<>]+)')
> diff --git a/contrib/remote-helpers/test-hg-bidi.sh b/contrib/remote-helpers/test-hg-bidi.sh
> index a94eb28..1d61982 100755
> --- a/contrib/remote-helpers/test-hg-bidi.sh
> +++ b/contrib/remote-helpers/test-hg-bidi.sh
> @@ -6,7 +6,7 @@
>  # https://bitbucket.org/durin42/hg-git/src
>  #
>  
> -test_description='Test biridectionality of remote-hg'
> +test_description='Test bidirectionality of remote-hg'
>  
>  . ./test-lib.sh

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] remote-hg: Fix biridectionality -> bidirectionality typos
  2013-01-08 17:32       ` Junio C Hamano
@ 2013-01-08 17:50         ` W. Trevor King
  2013-01-08 18:10           ` Junio C Hamano
  0 siblings, 1 reply; 22+ messages in thread
From: W. Trevor King @ 2013-01-08 17:50 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Felipe Contreras, git, Jeff King, Sverre Rabbelier,
	Johannes Schindelin, Ilari Liusvaara, Daniel Barkalow,
	Michael J Gruber

[-- Attachment #1: Type: text/plain, Size: 253 bytes --]

On Tue, Jan 08, 2013 at 09:32:07AM -0800, Junio C Hamano wrote:
> Thanks; didn't Documentation/SubmittingPatches ask you not to do PGP
> multipart but send patches in plain text?

Gah.  I need to tell myself to reread that every time I send a patch
:p.

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] remote-hg: Fix biridectionality -> bidirectionality typos
  2013-01-08 17:50         ` W. Trevor King
@ 2013-01-08 18:10           ` Junio C Hamano
  0 siblings, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2013-01-08 18:10 UTC (permalink / raw)
  To: W. Trevor King
  Cc: Felipe Contreras, git, Jeff King, Sverre Rabbelier,
	Johannes Schindelin, Ilari Liusvaara, Daniel Barkalow,
	Michael J Gruber

"W. Trevor King" <wking@tremily.us> writes:

> On Tue, Jan 08, 2013 at 09:32:07AM -0800, Junio C Hamano wrote:
>> Thanks; didn't Documentation/SubmittingPatches ask you not to do PGP
>> multipart but send patches in plain text?
>
> Gah.  I need to tell myself to reread that every time I send a patch
> :p.

No need to worry; thanks for a patch---applied to 'maint'.

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2013-01-08 18:10 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-04  2:13 [PATCH v6 00/16] New remote-hg helper:w Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 01/16] Add new remote-hg transport helper Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 02/16] remote-hg: add support for pushing Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 03/16] remote-hg: add support for remote pushing Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 04/16] remote-hg: add support to push URLs Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 05/16] remote-hg: make sure the encoding is correct Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 06/16] remote-hg: match hg merge behavior Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 07/16] remote-hg: add support for hg-git compat mode Felipe Contreras
2012-11-28 20:23   ` W. Trevor King
2013-01-08 15:47     ` [PATCH] remote-hg: Fix biridectionality -> bidirectionality typos W. Trevor King
2013-01-08 17:32       ` Junio C Hamano
2013-01-08 17:50         ` W. Trevor King
2013-01-08 18:10           ` Junio C Hamano
2012-11-04  2:13 ` [PATCH v6 08/16] remote-hg: add compat for hg-git author fixes Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 09/16] remote-hg: fake bookmark when there's none Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 10/16] remote-hg: add basic tests Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 11/16] test-lib: avoid full path to store test results Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 12/16] remote-hg: add bidirectional tests Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 13/16] remote-hg: add tests to compare with hg-git Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 14/16] remote-hg: add extra author test Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 15/16] remote-hg: add option to not track branches Felipe Contreras
2012-11-04  2:13 ` [PATCH v6 16/16] remote-hg: the author email can be null Felipe Contreras

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).