{"thread":{"id":"32073","subject":"[PATCH v3 0/7] New remote-bzr remote helper","startedAt":"2012-11-11T14:19:51Z","lastAt":"2012-12-14T00:52:00Z","messageCount":26,"participants":["Felipe Contreras","Junio C Hamano"],"isPatch":true,"patchVersion":3,"patchTotal":7},"messages":[{"id":"202849","messageId":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","threadId":"32073","inReplyTo":null,"subject":"[PATCH v3 0/7] New remote-bzr remote helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-11T14:19:51Z","receivedAt":"2012-11-11T14:19:51Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Hi,\n\nThis is a re-roll of the previous series to add support to fetch and push\nspecial modes, and refactor some related code.\n\nCheers.\n\nChanges since v2:\n\n * Add support for special modes\n * Minor refactoring and cleanups\n\nChanges since v1:\n\n * Rewritten to avoid bzr-fastimport\n\nFelipe Contreras (7):\n  Add new remote-bzr transport helper\n  remote-bzr: add support for pushing\n  remote-bzr: add support for remote repositories\n  remote-bzr: update working tree\n  remote-bzr: add simple tests\n  remote-bzr: add support for fecthing special modes\n  remote-bzr: add support to push special modes\n\n contrib/remote-helpers/git-remote-bzr | 713 ++++++++++++++++++++++++++++++++++\n contrib/remote-helpers/test-bzr.sh    | 143 +++++++\n 2 files changed, 856 insertions(+)\n create mode 100755 contrib/remote-helpers/git-remote-bzr\n create mode 100755 contrib/remote-helpers/test-bzr.sh\n\n-- \n1.8.0\n"},{"id":"202851","messageId":"1352643598-8500-2-git-send-email-felipe.contreras@gmail.com","threadId":"32073","inReplyTo":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v3 1/7] Add new remote-bzr transport helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-11T14:19:52Z","receivedAt":"2012-11-11T14:19:52Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/remote-helpers/git-remote-bzr | 352 ++++++++++++++++++++++++++++++++++\n 1 file changed, 352 insertions(+)\n create mode 100755 contrib/remote-helpers/git-remote-bzr\n\ndiff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\nnew file mode 100755\nindex 0000000..b6be9d6\n--- /dev/null\n+++ b/contrib/remote-helpers/git-remote-bzr\n@@ -0,0 +1,352 @@\n+#!/usr/bin/env python\n+#\n+# Copyright (c) 2012 Felipe Contreras\n+#\n+\n+#\n+# Just copy to your ~/bin, or anywhere in your $PATH.\n+# Then you can clone with:\n+# % git clone bzr::/path/to/bzr/repo/or/url\n+#\n+# For example:\n+# % git clone bzr::$HOME/myrepo\n+# or\n+# % git clone bzr::lp:myrepo\n+#\n+\n+import sys\n+\n+import bzrlib\n+bzrlib.initialize()\n+\n+import bzrlib.plugin\n+bzrlib.plugin.load_plugins()\n+\n+import sys\n+import os\n+import json\n+import re\n+\n+NAME_RE = re.compile('^([^<>]+)')\n+AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]*)>$')\n+\n+def die(msg, *args):\n+    sys.stderr.write('ERROR: %s\\n' % (msg % args))\n+    sys.exit(1)\n+\n+def warn(msg, *args):\n+    sys.stderr.write('WARNING: %s\\n' % (msg % args))\n+\n+def gittz(tz):\n+    return '%+03d%02d' % (tz / 3600, tz % 3600 / 60)\n+\n+class Marks:\n+\n+    def __init__(self, path):\n+        self.path = path\n+        self.tips = {}\n+        self.marks = {}\n+        self.last_mark = 0\n+        self.load()\n+\n+    def load(self):\n+        if not os.path.exists(self.path):\n+            return\n+\n+        tmp = json.load(open(self.path))\n+        self.tips = tmp['tips']\n+        self.marks = tmp['marks']\n+        self.last_mark = tmp['last-mark']\n+\n+    def dict(self):\n+        return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }\n+\n+    def store(self):\n+        json.dump(self.dict(), open(self.path, 'w'))\n+\n+    def __str__(self):\n+        return str(self.dict())\n+\n+    def from_rev(self, rev):\n+        return self.marks[rev]\n+\n+    def next_mark(self):\n+        self.last_mark += 1\n+        return self.last_mark\n+\n+    def get_mark(self, rev):\n+        self.last_mark += 1\n+        self.marks[rev] = self.last_mark\n+        return self.last_mark\n+\n+    def is_marked(self, rev):\n+        return self.marks.has_key(rev)\n+\n+    def get_tip(self, branch):\n+        return self.tips.get(branch, None)\n+\n+    def set_tip(self, branch, tip):\n+        self.tips[branch] = tip\n+\n+class Parser:\n+\n+    def __init__(self, repo):\n+        self.repo = repo\n+        self.line = self.get_line()\n+\n+    def get_line(self):\n+        return sys.stdin.readline().strip()\n+\n+    def __getitem__(self, i):\n+        return self.line.split()[i]\n+\n+    def check(self, word):\n+        return self.line.startswith(word)\n+\n+    def each_block(self, separator):\n+        while self.line != separator:\n+            yield self.line\n+            self.line = self.get_line()\n+\n+    def __iter__(self):\n+        return self.each_block('')\n+\n+    def next(self):\n+        self.line = self.get_line()\n+        if self.line == 'done':\n+            self.line = None\n+\n+def rev_to_mark(rev):\n+    global marks\n+    return marks.from_rev(rev)\n+\n+def fixup_user(user):\n+    name = mail = None\n+    user = user.replace('\"', '')\n+    m = AUTHOR_RE.match(user)\n+    if m:\n+        name = m.group(1)\n+        mail = m.group(2).strip()\n+    else:\n+        m = NAME_RE.match(user)\n+        if m:\n+            name = m.group(1).strip()\n+\n+    return '%s <%s>' % (name, mail)\n+\n+def get_filechanges(cur, prev):\n+    modified = {}\n+    removed = {}\n+\n+    changes = cur.changes_from(prev)\n+\n+    for path, fid, kind in changes.added:\n+        modified[path] = fid\n+    for path, fid, kind in changes.removed:\n+        removed[path] = None\n+    for path, fid, kind, mod, _ in changes.modified:\n+        modified[path] = fid\n+    for oldpath, newpath, fid, kind, mod, _ in changes.renamed:\n+        removed[oldpath] = None\n+        modified[newpath] = fid\n+\n+    return modified, removed\n+\n+def export_files(tree, files):\n+    global marks, filenodes\n+\n+    final = []\n+    for path, fid in files.iteritems():\n+        h = tree.get_file_sha1(fid)\n+\n+        mode = '100644'\n+\n+        # is the blob already exported?\n+        if h in filenodes:\n+            mark = filenodes[h]\n+        else:\n+            d = tree.get_file_text(fid)\n+\n+            mark = marks.next_mark()\n+            filenodes[h] = mark\n+\n+            print \"blob\"\n+            print \"mark :%u\" % mark\n+            print \"data %d\" % len(d)\n+            print d\n+\n+        final.append((mode, mark, path))\n+\n+    return final\n+\n+def export_branch(branch, name):\n+    global prefix, dirname\n+\n+    ref = '%s/heads/%s' % (prefix, name)\n+    tip = marks.get_tip(name)\n+\n+    repo = branch.repository\n+    repo.lock_read()\n+    revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward')\n+    count = 0\n+\n+    revs = [revid for revid, _, _, _ in revs if not marks.is_marked(revid)]\n+\n+    for revid in revs:\n+\n+        rev = repo.get_revision(revid)\n+\n+        parents = rev.parent_ids\n+        time = rev.timestamp\n+        tz = rev.timezone\n+        committer = rev.committer.encode('utf-8')\n+        committer = \"%s %u %s\" % (fixup_user(committer), time, gittz(tz))\n+        author = committer\n+        msg = rev.message.encode('utf-8')\n+\n+        msg += '\\n'\n+\n+        if len(parents) == 0:\n+            parent = bzrlib.revision.NULL_REVISION\n+        else:\n+            parent = parents[0]\n+\n+        cur_tree = repo.revision_tree(revid)\n+        prev = repo.revision_tree(parent)\n+        modified, removed = get_filechanges(cur_tree, prev)\n+\n+        modified_final = export_files(cur_tree, modified)\n+\n+        if len(parents) == 0:\n+            print 'reset %s' % ref\n+\n+        print \"commit %s\" % ref\n+        print \"mark :%d\" % (marks.get_mark(revid))\n+        print \"author %s\" % (author)\n+        print \"committer %s\" % (committer)\n+        print \"data %d\" % (len(msg))\n+        print msg\n+\n+        for i, p in enumerate(parents):\n+            try:\n+                m = rev_to_mark(p)\n+            except KeyError:\n+                # ghost?\n+                continue\n+            if i == 0:\n+                print \"from :%s\" % m\n+            else:\n+                print \"merge :%s\" % m\n+\n+        for f in modified_final:\n+            print \"M %s :%u %s\" % f\n+        for f in removed:\n+            print \"D %s\" % (f)\n+        print\n+\n+        count += 1\n+        if (count % 100 == 0):\n+            print \"progress revision %s (%d/%d)\" % (revid, count, len(revs))\n+            print \"#############################################################\"\n+\n+    repo.unlock()\n+\n+    revid = branch.last_revision()\n+\n+    # make sure the ref is updated\n+    print \"reset %s\" % ref\n+    print \"from :%u\" % rev_to_mark(revid)\n+    print\n+\n+    marks.set_tip(name, revid)\n+\n+def export_tag(repo, name):\n+    global tags\n+    try:\n+        print \"reset refs/tags/%s\" % name\n+        print \"from :%u\" % rev_to_mark(tags[name])\n+        print\n+    except KeyError:\n+        warn(\"TODO: fetch tag '%s'\" % name)\n+\n+def do_import(parser):\n+    global dirname\n+\n+    branch = parser.repo\n+    path = os.path.join(dirname, 'marks-git')\n+\n+    print \"feature done\"\n+    if os.path.exists(path):\n+        print \"feature import-marks=%s\" % path\n+    print \"feature export-marks=%s\" % path\n+    sys.stdout.flush()\n+\n+    while parser.check('import'):\n+        ref = parser[1]\n+        if ref.startswith('refs/heads/'):\n+            name = ref[len('refs/heads/'):]\n+            export_branch(branch, name)\n+        if ref.startswith('refs/tags/'):\n+            name = ref[len('refs/tags/'):]\n+            export_tag(branch, name)\n+        parser.next()\n+\n+    print 'done'\n+\n+    sys.stdout.flush()\n+\n+def do_capabilities(parser):\n+    print \"import\"\n+    print \"refspec refs/heads/*:%s/heads/*\" % prefix\n+    print\n+\n+def do_list(parser):\n+    global tags\n+    print \"? refs/heads/%s\" % 'master'\n+    for tag, revid in parser.repo.tags.get_tag_dict().items():\n+        print \"? refs/tags/%s\" % tag\n+        tags[tag] = revid\n+    print \"@refs/heads/%s HEAD\" % 'master'\n+    print\n+\n+def get_repo(url, alias):\n+    origin = bzrlib.controldir.ControlDir.open(url)\n+    return origin.open_branch()\n+\n+def main(args):\n+    global marks, prefix, dirname\n+    global tags, filenodes\n+\n+    alias = args[1]\n+    url = args[2]\n+\n+    prefix = 'refs/bzr/%s' % alias\n+    tags = {}\n+    filenodes = {}\n+\n+    gitdir = os.environ['GIT_DIR']\n+    dirname = os.path.join(gitdir, 'bzr', alias)\n+\n+    if not os.path.exists(dirname):\n+        os.makedirs(dirname)\n+\n+    repo = get_repo(url, alias)\n+\n+    marks_path = os.path.join(dirname, 'marks-int')\n+    marks = Marks(marks_path)\n+\n+    parser = Parser(repo)\n+    for line in parser:\n+        if parser.check('capabilities'):\n+            do_capabilities(parser)\n+        elif parser.check('list'):\n+            do_list(parser)\n+        elif parser.check('import'):\n+            do_import(parser)\n+        else:\n+            die('unhandled command: %s' % line)\n+        sys.stdout.flush()\n+\n+    marks.store()\n+\n+sys.exit(main(sys.argv))\n-- \n1.8.0\n"},{"id":"202853","messageId":"1352643598-8500-3-git-send-email-felipe.contreras@gmail.com","threadId":"32073","inReplyTo":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v3 2/7] remote-bzr: add support for pushing","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-11T14:19:53Z","receivedAt":"2012-11-11T14:19:53Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/remote-helpers/git-remote-bzr | 295 ++++++++++++++++++++++++++++++++++\n 1 file changed, 295 insertions(+)\n\ndiff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\nindex b6be9d6..8366234 100755\n--- a/contrib/remote-helpers/git-remote-bzr\n+++ b/contrib/remote-helpers/git-remote-bzr\n@@ -22,13 +22,17 @@ bzrlib.initialize()\n import bzrlib.plugin\n bzrlib.plugin.load_plugins()\n \n+import bzrlib.generate_ids\n+\n import sys\n import os\n import json\n import re\n+import StringIO\n \n NAME_RE = re.compile('^([^<>]+)')\n AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]*)>$')\n+RAW_AUTHOR_RE = re.compile('^(\\w+) (.+)? <(.*)> (\\d+) ([+-]\\d+)')\n \n def die(msg, *args):\n     sys.stderr.write('ERROR: %s\\n' % (msg % args))\n@@ -46,6 +50,7 @@ class Marks:\n         self.path = path\n         self.tips = {}\n         self.marks = {}\n+        self.rev_marks = {}\n         self.last_mark = 0\n         self.load()\n \n@@ -58,6 +63,9 @@ class Marks:\n         self.marks = tmp['marks']\n         self.last_mark = tmp['last-mark']\n \n+        for rev, mark in self.marks.iteritems():\n+            self.rev_marks[mark] = rev\n+\n     def dict(self):\n         return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }\n \n@@ -70,6 +78,9 @@ class Marks:\n     def from_rev(self, rev):\n         return self.marks[rev]\n \n+    def to_rev(self, mark):\n+        return self.rev_marks[mark]\n+\n     def next_mark(self):\n         self.last_mark += 1\n         return self.last_mark\n@@ -82,6 +93,11 @@ class Marks:\n     def is_marked(self, rev):\n         return self.marks.has_key(rev)\n \n+    def new_mark(self, rev, mark):\n+        self.marks[rev] = mark\n+        self.rev_marks[mark] = rev\n+        self.last_mark = mark\n+\n     def get_tip(self, branch):\n         return self.tips.get(branch, None)\n \n@@ -116,10 +132,35 @@ class Parser:\n         if self.line == 'done':\n             self.line = None\n \n+    def get_mark(self):\n+        i = self.line.index(':') + 1\n+        return int(self.line[i:])\n+\n+    def get_data(self):\n+        if not self.check('data'):\n+            return None\n+        i = self.line.index(' ') + 1\n+        size = int(self.line[i:])\n+        return sys.stdin.read(size)\n+\n+    def get_author(self):\n+        m = RAW_AUTHOR_RE.match(self.line)\n+        if not m:\n+            return None\n+        _, name, email, date, tz = m.groups()\n+        committer = '%s <%s>' % (name, email)\n+        tz = int(tz)\n+        tz = ((tz / 100) * 3600) + ((tz % 100) * 60)\n+        return (committer, int(date), tz)\n+\n def rev_to_mark(rev):\n     global marks\n     return marks.from_rev(rev)\n \n+def mark_to_rev(mark):\n+    global marks\n+    return marks.to_rev(mark)\n+\n def fixup_user(user):\n     name = mail = None\n     user = user.replace('\"', '')\n@@ -295,9 +336,255 @@ def do_import(parser):\n \n     sys.stdout.flush()\n \n+def parse_blob(parser):\n+    global blob_marks\n+\n+    parser.next()\n+    mark = parser.get_mark()\n+    parser.next()\n+    data = parser.get_data()\n+    blob_marks[mark] = data\n+    parser.next()\n+\n+class CustomTree():\n+\n+    def __init__(self, repo, revid, parents, files):\n+        global files_cache\n+\n+        self.repo = repo\n+        self.revid = revid\n+        self.parents = parents\n+        self.updates = files\n+\n+        def copy_tree(revid):\n+            files = files_cache[revid] = {}\n+            tree = repo.repository.revision_tree(revid)\n+            repo.lock_read()\n+            try:\n+                for path, entry in tree.iter_entries_by_dir():\n+                    files[path] = entry.file_id\n+            finally:\n+                repo.unlock()\n+            return files\n+\n+        if len(parents) == 0:\n+            self.base_id = bzrlib.revision.NULL_REVISION\n+            self.base_files = {}\n+        else:\n+            self.base_id = parents[0]\n+            self.base_files = files_cache.get(self.base_id, None)\n+            if not self.base_files:\n+                self.base_files = copy_tree(self.base_id)\n+\n+        self.files = files_cache[revid] = self.base_files.copy()\n+\n+    def last_revision(self):\n+        return self.base_id\n+\n+    def iter_changes(self):\n+        changes = []\n+\n+        def get_parent(dirname, basename):\n+            parent_fid = self.base_files.get(dirname, None)\n+            if parent_fid:\n+                return parent_fid\n+            parent_fid = self.files.get(dirname, None)\n+            if parent_fid:\n+                return parent_fid\n+            if basename == '':\n+                return None\n+            d = add_entry(dirname, 'directory')\n+            return d[0]\n+\n+        def add_entry(path, kind):\n+            dirname, basename = os.path.split(path)\n+            parent_fid = get_parent(dirname, basename)\n+            fid = bzrlib.generate_ids.gen_file_id(path)\n+            change = (fid,\n+                    (None, path),\n+                    True,\n+                    (False, True),\n+                    (None, parent_fid),\n+                    (None, basename),\n+                    (None, kind),\n+                    (None, False))\n+            self.files[path] = change[0]\n+            changes.append(change)\n+            return change\n+\n+        def update_entry(path, kind):\n+            dirname, basename = os.path.split(path)\n+            fid = self.base_files[path]\n+            parent_fid = get_parent(dirname, basename)\n+            change = (fid,\n+                    (path, path),\n+                    True,\n+                    (True, True),\n+                    (None, parent_fid),\n+                    (None, basename),\n+                    (None, kind),\n+                    (None, False))\n+            self.files[path] = change[0]\n+            changes.append(change)\n+            return change\n+\n+        def remove_entry(path, kind):\n+            dirname, basename = os.path.split(path)\n+            fid = self.base_files[path]\n+            parent_fid = get_parent(dirname, basename)\n+            change = (fid,\n+                    (path, None),\n+                    True,\n+                    (True, False),\n+                    (parent_fid, None),\n+                    (None, None),\n+                    (None, None),\n+                    (None, None))\n+            del self.files[path]\n+            changes.append(change)\n+            return change\n+\n+        for path, f in self.updates.iteritems():\n+            if 'deleted' in f:\n+                remove_entry(path, 'file')\n+            elif path in self.base_files:\n+                update_entry(path, 'file')\n+            else:\n+                add_entry(path, 'file')\n+\n+        return changes\n+\n+    def get_file_with_stat(self, file_id, path=None):\n+        return (StringIO.StringIO(self.updates[path]['data']), None)\n+\n+def parse_commit(parser):\n+    global marks, blob_marks, bmarks, parsed_refs\n+    global mode\n+\n+    parents = []\n+\n+    ref = parser[1]\n+    parser.next()\n+\n+    if ref != 'refs/heads/master':\n+        die(\"bzr doesn't support multiple branches; use 'master'\")\n+\n+    commit_mark = parser.get_mark()\n+    parser.next()\n+    author = parser.get_author()\n+    parser.next()\n+    committer = parser.get_author()\n+    parser.next()\n+    data = parser.get_data()\n+    parser.next()\n+    if parser.check('from'):\n+        parents.append(parser.get_mark())\n+        parser.next()\n+    while parser.check('merge'):\n+        parents.append(parser.get_mark())\n+        parser.next()\n+\n+    files = {}\n+\n+    for line in parser:\n+        if parser.check('M'):\n+            t, m, mark_ref, path = line.split(' ', 3)\n+            mark = int(mark_ref[1:])\n+            f = { 'mode' : m, 'data' : blob_marks[mark] }\n+        elif parser.check('D'):\n+            t, path = line.split(' ')\n+            f = { 'deleted' : True }\n+        else:\n+            die('Unknown file command: %s' % line)\n+        files[path] = f\n+\n+    repo = parser.repo\n+\n+    committer, date, tz = committer\n+    parents = [str(mark_to_rev(p)) for p in parents]\n+    revid = bzrlib.generate_ids.gen_revision_id(committer, date)\n+    props = {}\n+    props['branch-nick'] = repo.nick\n+\n+    mtree = CustomTree(repo, revid, parents, files)\n+    changes = mtree.iter_changes()\n+\n+    repo.lock_write()\n+    try:\n+        builder = repo.get_commit_builder(parents, None, date, tz, committer, props, revid, False)\n+        try:\n+            list(builder.record_iter_changes(mtree, mtree.last_revision(), changes))\n+            builder.finish_inventory()\n+            builder.commit(data.decode('utf-8', 'replace'))\n+        except Exception, e:\n+            builder.abort()\n+            raise\n+    finally:\n+        repo.unlock()\n+\n+    parsed_refs[ref] = revid\n+    marks.new_mark(revid, commit_mark)\n+\n+def parse_reset(parser):\n+    global parsed_refs\n+\n+    ref = parser[1]\n+    parser.next()\n+\n+    if ref != 'refs/heads/master':\n+        die(\"bzr doesn't support multiple branches; use 'master'\")\n+\n+    # ugh\n+    if parser.check('commit'):\n+        parse_commit(parser)\n+        return\n+    if not parser.check('from'):\n+        return\n+    from_mark = parser.get_mark()\n+    parser.next()\n+\n+    parsed_refs[ref] = mark_to_rev(from_mark)\n+\n+def do_export(parser):\n+    global parsed_refs, dirname\n+\n+    parser.next()\n+\n+    for line in parser.each_block('done'):\n+        if parser.check('blob'):\n+            parse_blob(parser)\n+        elif parser.check('commit'):\n+            parse_commit(parser)\n+        elif parser.check('reset'):\n+            parse_reset(parser)\n+        elif parser.check('tag'):\n+            pass\n+        elif parser.check('feature'):\n+            pass\n+        else:\n+            die('unhandled export command: %s' % line)\n+\n+    repo = parser.repo\n+\n+    for ref, revid in parsed_refs.iteritems():\n+        if ref == 'refs/heads/master':\n+            repo.generate_revision_history(revid, marks.get_tip('master'))\n+        print \"ok %s\" % ref\n+    print\n+\n def do_capabilities(parser):\n+    global dirname\n+\n     print \"import\"\n+    print \"export\"\n     print \"refspec refs/heads/*:%s/heads/*\" % prefix\n+\n+    path = os.path.join(dirname, 'marks-git')\n+\n+    if os.path.exists(path):\n+        print \"*import-marks %s\" % path\n+    print \"*export-marks %s\" % path\n+\n     print\n \n def do_list(parser):\n@@ -316,6 +603,9 @@ def get_repo(url, alias):\n def main(args):\n     global marks, prefix, dirname\n     global tags, filenodes\n+    global blob_marks\n+    global parsed_refs\n+    global files_cache\n \n     alias = args[1]\n     url = args[2]\n@@ -323,6 +613,9 @@ def main(args):\n     prefix = 'refs/bzr/%s' % alias\n     tags = {}\n     filenodes = {}\n+    blob_marks = {}\n+    parsed_refs = {}\n+    files_cache = {}\n \n     gitdir = os.environ['GIT_DIR']\n     dirname = os.path.join(gitdir, 'bzr', alias)\n@@ -343,6 +636,8 @@ def main(args):\n             do_list(parser)\n         elif parser.check('import'):\n             do_import(parser)\n+        elif parser.check('export'):\n+            do_export(parser)\n         else:\n             die('unhandled command: %s' % line)\n         sys.stdout.flush()\n-- \n1.8.0\n"},{"id":"202850","messageId":"1352643598-8500-4-git-send-email-felipe.contreras@gmail.com","threadId":"32073","inReplyTo":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v3 3/7] remote-bzr: add support for remote repositories","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-11T14:19:54Z","receivedAt":"2012-11-11T14:19:54Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Strictly speaking bzr doesn't need any changes to interact with remote\nrepositories, but it's dead slow.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/remote-helpers/git-remote-bzr | 26 ++++++++++++++++++++++++--\n 1 file changed, 24 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\nindex 8366234..2c05f35 100755\n--- a/contrib/remote-helpers/git-remote-bzr\n+++ b/contrib/remote-helpers/git-remote-bzr\n@@ -546,7 +546,7 @@ def parse_reset(parser):\n     parsed_refs[ref] = mark_to_rev(from_mark)\n \n def do_export(parser):\n-    global parsed_refs, dirname\n+    global parsed_refs, dirname, peer\n \n     parser.next()\n \n@@ -569,6 +569,8 @@ def do_export(parser):\n     for ref, revid in parsed_refs.iteritems():\n         if ref == 'refs/heads/master':\n             repo.generate_revision_history(revid, marks.get_tip('master'))\n+            revno, revid = repo.last_revision_info()\n+            peer.import_last_revision_info_and_tags(repo, revno, revid)\n         print \"ok %s\" % ref\n     print\n \n@@ -597,8 +599,28 @@ def do_list(parser):\n     print\n \n def get_repo(url, alias):\n+    global dirname, peer\n+\n+    clone_path = os.path.join(dirname, 'clone')\n     origin = bzrlib.controldir.ControlDir.open(url)\n-    return origin.open_branch()\n+    remote_branch = origin.open_branch()\n+\n+    if os.path.exists(clone_path):\n+        # pull\n+        d = bzrlib.controldir.ControlDir.open(clone_path)\n+        branch = d.open_branch()\n+        result = branch.pull(remote_branch, [], None, False)\n+    else:\n+        # clone\n+        d = origin.sprout(clone_path, None,\n+                hardlink=True, create_tree_if_local=False,\n+                source_branch=remote_branch)\n+        branch = d.open_branch()\n+        branch.bind(remote_branch)\n+\n+    peer = remote_branch\n+\n+    return branch\n \n def main(args):\n     global marks, prefix, dirname\n-- \n1.8.0\n"},{"id":"202854","messageId":"1352643598-8500-5-git-send-email-felipe.contreras@gmail.com","threadId":"32073","inReplyTo":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v3 4/7] remote-bzr: update working tree","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-11T14:19:55Z","receivedAt":"2012-11-11T14:19:55Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/remote-helpers/git-remote-bzr | 2 ++\n 1 file changed, 2 insertions(+)\n\ndiff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\nindex 2c05f35..5b89a05 100755\n--- a/contrib/remote-helpers/git-remote-bzr\n+++ b/contrib/remote-helpers/git-remote-bzr\n@@ -571,6 +571,8 @@ def do_export(parser):\n             repo.generate_revision_history(revid, marks.get_tip('master'))\n             revno, revid = repo.last_revision_info()\n             peer.import_last_revision_info_and_tags(repo, revno, revid)\n+            wt = peer.bzrdir.open_workingtree()\n+            wt.update()\n         print \"ok %s\" % ref\n     print\n \n-- \n1.8.0\n"},{"id":"202852","messageId":"1352643598-8500-6-git-send-email-felipe.contreras@gmail.com","threadId":"32073","inReplyTo":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v3 5/7] remote-bzr: add simple tests","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-11T14:19:56Z","receivedAt":"2012-11-11T14:19:56Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/remote-helpers/test-bzr.sh | 111 +++++++++++++++++++++++++++++++++++++\n 1 file changed, 111 insertions(+)\n create mode 100755 contrib/remote-helpers/test-bzr.sh\n\ndiff --git a/contrib/remote-helpers/test-bzr.sh b/contrib/remote-helpers/test-bzr.sh\nnew file mode 100755\nindex 0000000..8594ffc\n--- /dev/null\n+++ b/contrib/remote-helpers/test-bzr.sh\n@@ -0,0 +1,111 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2012 Felipe Contreras\n+#\n+\n+test_description='Test remote-bzr'\n+\n+. ./test-lib.sh\n+\n+if ! test_have_prereq PYTHON; then\n+\tskip_all='skipping remote-bzr tests; python not available'\n+\ttest_done\n+fi\n+\n+if ! \"$PYTHON_PATH\" -c 'import bzrlib'; then\n+\tskip_all='skipping remote-bzr tests; bzr not available'\n+\ttest_done\n+fi\n+\n+cmd=<<EOF\n+import bzrlib\n+bzrlib.initialize()\n+import bzrlib.plugin\n+bzrlib.plugin.load_plugins()\n+import bzrlib.plugins.fastimport\n+EOF\n+\n+if ! \"$PYTHON_PATH\" -c \"$cmd\"; then\n+\techo \"consider setting BZR_PLUGIN_PATH=$HOME/.bazaar/plugins\" 1>&2\n+\tskip_all='skipping remote-bzr tests; bzr-fastimport not available'\n+\ttest_done\n+fi\n+\n+check () {\n+\t(cd $1 &&\n+\tgit log --format='%s' -1 &&\n+\tgit symbolic-ref HEAD) > actual &&\n+\t(echo $2 &&\n+\techo \"refs/heads/$3\") > expected &&\n+\ttest_cmp expected actual\n+}\n+\n+bzr whoami \"A U Thor <author@example.com>\"\n+\n+test_expect_success 'cloning' '\n+  (bzr init bzrrepo &&\n+  cd bzrrepo &&\n+  echo one > content &&\n+  bzr add content &&\n+  bzr commit -m one\n+  ) &&\n+\n+  git clone \"bzr::$PWD/bzrrepo\" gitrepo &&\n+  check gitrepo one master\n+'\n+\n+test_expect_success 'pulling' '\n+  (cd bzrrepo &&\n+  echo two > content &&\n+  bzr commit -m two\n+  ) &&\n+\n+  (cd gitrepo && git pull) &&\n+\n+  check gitrepo two master\n+'\n+\n+test_expect_success 'pushing' '\n+  (cd gitrepo &&\n+  echo three > content &&\n+  git commit -a -m three &&\n+  git push\n+  ) &&\n+\n+  echo three > expected &&\n+  cat bzrrepo/content > actual &&\n+  test_cmp expected actual\n+'\n+\n+test_expect_success 'roundtrip' '\n+  (cd gitrepo &&\n+  git pull &&\n+  git log --format=\"%s\" -1 origin/master > actual) &&\n+  echo three > expected &&\n+  test_cmp expected actual &&\n+\n+  (cd gitrepo && git push && git pull) &&\n+\n+  (cd bzrrepo &&\n+  echo four > content &&\n+  bzr commit -m four\n+  ) &&\n+\n+  (cd gitrepo && git pull && git push) &&\n+\n+  check gitrepo four master &&\n+\n+  (cd gitrepo &&\n+  echo five > content &&\n+  git commit -a -m five &&\n+  git push && git pull\n+  ) &&\n+\n+  (cd bzrrepo && bzr revert) &&\n+\n+  echo five > expected &&\n+  cat bzrrepo/content > actual &&\n+  test_cmp expected actual\n+'\n+\n+test_done\n-- \n1.8.0\n"},{"id":"202855","messageId":"1352643598-8500-7-git-send-email-felipe.contreras@gmail.com","threadId":"32073","inReplyTo":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v3 6/7] remote-bzr: add support for fecthing special modes","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-11T14:19:57Z","receivedAt":"2012-11-11T14:19:57Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/remote-helpers/git-remote-bzr | 38 +++++++++++++++++++++++++----------\n contrib/remote-helpers/test-bzr.sh    | 32 +++++++++++++++++++++++++++++\n 2 files changed, 59 insertions(+), 11 deletions(-)\n\ndiff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\nindex 5b89a05..2bae5d0 100755\n--- a/contrib/remote-helpers/git-remote-bzr\n+++ b/contrib/remote-helpers/git-remote-bzr\n@@ -198,23 +198,39 @@ def export_files(tree, files):\n \n     final = []\n     for path, fid in files.iteritems():\n+        kind = tree.kind(fid)\n+\n         h = tree.get_file_sha1(fid)\n \n-        mode = '100644'\n+        if kind == 'symlink':\n+            d = tree.get_symlink_target(fid)\n+            mode = '120000'\n+        elif kind == 'file':\n+\n+            if tree.is_executable(fid):\n+                mode = '100755'\n+            else:\n+                mode = '100644'\n+\n+            # is the blog already exported?\n+            if h in filenodes:\n+                mark = filenodes[h]\n+                final.append((mode, mark, path))\n+                continue\n \n-        # is the blob already exported?\n-        if h in filenodes:\n-            mark = filenodes[h]\n-        else:\n             d = tree.get_file_text(fid)\n+        elif kind == 'directory':\n+            continue\n+        else:\n+            die(\"Unhandled kind '%s' for path '%s'\" % (kind, path))\n \n-            mark = marks.next_mark()\n-            filenodes[h] = mark\n+        mark = marks.next_mark()\n+        filenodes[h] = mark\n \n-            print \"blob\"\n-            print \"mark :%u\" % mark\n-            print \"data %d\" % len(d)\n-            print d\n+        print \"blob\"\n+        print \"mark :%u\" % mark\n+        print \"data %d\" % len(d)\n+        print d\n \n         final.append((mode, mark, path))\n \ndiff --git a/contrib/remote-helpers/test-bzr.sh b/contrib/remote-helpers/test-bzr.sh\nindex 8594ffc..c92d0c6 100755\n--- a/contrib/remote-helpers/test-bzr.sh\n+++ b/contrib/remote-helpers/test-bzr.sh\n@@ -108,4 +108,36 @@ test_expect_success 'roundtrip' '\n   test_cmp expected actual\n '\n \n+cat > expected <<EOF\n+100644 blob 54f9d6da5c91d556e6b54340b1327573073030af\tcontent\n+100755 blob 68769579c3eaadbe555379b9c3538e6628bae1eb\texecutable\n+120000 blob 6b584e8ece562ebffc15d38808cd6b98fc3d97ea\tlink\n+EOF\n+\n+test_expect_success 'special modes' '\n+  (cd bzrrepo &&\n+  echo exec > executable\n+  chmod +x executable &&\n+  bzr add executable\n+  bzr commit -m exec &&\n+  ln -s content link\n+  bzr add link\n+  bzr commit -m link &&\n+  mkdir dir &&\n+  bzr add dir &&\n+  bzr commit -m dir) &&\n+\n+  (cd gitrepo &&\n+  git pull\n+  git ls-tree HEAD > ../actual) &&\n+\n+  test_cmp expected actual &&\n+\n+  (cd gitrepo &&\n+  git cat-file -p HEAD:link > ../actual) &&\n+\n+  echo -n content > expected &&\n+  test_cmp expected actual\n+'\n+\n test_done\n-- \n1.8.0\n"},{"id":"202856","messageId":"1352643598-8500-8-git-send-email-felipe.contreras@gmail.com","threadId":"32073","inReplyTo":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v3 7/7] remote-bzr: add support to push special modes","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-11T14:19:58Z","receivedAt":"2012-11-11T14:19:58Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/remote-helpers/git-remote-bzr | 60 +++++++++++++++++++++++++----------\n 1 file changed, 43 insertions(+), 17 deletions(-)\n\ndiff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\nindex 2bae5d0..f8919f4 100755\n--- a/contrib/remote-helpers/git-remote-bzr\n+++ b/contrib/remote-helpers/git-remote-bzr\n@@ -370,7 +370,7 @@ class CustomTree():\n         self.repo = repo\n         self.revid = revid\n         self.parents = parents\n-        self.updates = files\n+        self.updates = {}\n \n         def copy_tree(revid):\n             files = files_cache[revid] = {}\n@@ -394,6 +394,13 @@ class CustomTree():\n \n         self.files = files_cache[revid] = self.base_files.copy()\n \n+        for path, f in files.iteritems():\n+            fid = self.files.get(path, None)\n+            if not fid:\n+                fid = bzrlib.generate_ids.gen_file_id(path)\n+            f['path'] = path\n+            self.updates[fid] = f\n+\n     def last_revision(self):\n         return self.base_id\n \n@@ -409,13 +416,20 @@ class CustomTree():\n                 return parent_fid\n             if basename == '':\n                 return None\n-            d = add_entry(dirname, 'directory')\n-            return d[0]\n+            fid = bzrlib.generate_ids.gen_file_id(path)\n+            d = add_entry(fid, dirname, 'directory')\n+            return fid\n \n-        def add_entry(path, kind):\n+        def add_entry(fid, path, kind, mode = None):\n             dirname, basename = os.path.split(path)\n             parent_fid = get_parent(dirname, basename)\n-            fid = bzrlib.generate_ids.gen_file_id(path)\n+\n+            executable = False\n+            if mode == '100755':\n+                executable = True\n+            elif mode == '120000':\n+                kind = 'symlink'\n+\n             change = (fid,\n                     (None, path),\n                     True,\n@@ -423,15 +437,21 @@ class CustomTree():\n                     (None, parent_fid),\n                     (None, basename),\n                     (None, kind),\n-                    (None, False))\n+                    (None, executable))\n             self.files[path] = change[0]\n             changes.append(change)\n             return change\n \n-        def update_entry(path, kind):\n+        def update_entry(fid, path, kind, mode = None):\n             dirname, basename = os.path.split(path)\n-            fid = self.base_files[path]\n             parent_fid = get_parent(dirname, basename)\n+\n+            executable = False\n+            if mode == '100755':\n+                executable = True\n+            elif mode == '120000':\n+                kind = 'symlink'\n+\n             change = (fid,\n                     (path, path),\n                     True,\n@@ -439,14 +459,13 @@ class CustomTree():\n                     (None, parent_fid),\n                     (None, basename),\n                     (None, kind),\n-                    (None, False))\n+                    (None, executable))\n             self.files[path] = change[0]\n             changes.append(change)\n             return change\n \n-        def remove_entry(path, kind):\n+        def remove_entry(fid, path, kind):\n             dirname, basename = os.path.split(path)\n-            fid = self.base_files[path]\n             parent_fid = get_parent(dirname, basename)\n             change = (fid,\n                     (path, None),\n@@ -460,18 +479,25 @@ class CustomTree():\n             changes.append(change)\n             return change\n \n-        for path, f in self.updates.iteritems():\n+        for fid, f in self.updates.iteritems():\n+            path = f['path']\n+\n             if 'deleted' in f:\n-                remove_entry(path, 'file')\n-            elif path in self.base_files:\n-                update_entry(path, 'file')\n+                remove_entry(fid, path, 'file')\n+                continue\n+\n+            if path in self.base_files:\n+                update_entry(fid, path, 'file', f['mode'])\n             else:\n-                add_entry(path, 'file')\n+                add_entry(fid, path, 'file', f['mode'])\n \n         return changes\n \n     def get_file_with_stat(self, file_id, path=None):\n-        return (StringIO.StringIO(self.updates[path]['data']), None)\n+        return (StringIO.StringIO(self.updates[file_id]['data']), None)\n+\n+    def get_symlink_target(self, file_id):\n+        return self.updates[file_id]['data']\n \n def parse_commit(parser):\n     global marks, blob_marks, bmarks, parsed_refs\n-- \n1.8.0\n"},{"id":"203761","messageId":"CAMP44s2F9C4cr6v===M3AWHieaiUk1adigcU8txpZPL0wN81Ow@mail.gmail.com","threadId":"32073","inReplyTo":"1352643598-8500-1-git-send-email-felipe.contreras@gmail.com","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-24T10:21:04Z","receivedAt":"2012-11-24T10:21:04Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Sun, Nov 11, 2012 at 3:19 PM, Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n> This is a re-roll of the previous series to add support to fetch and push\n> special modes, and refactor some related code.\n\nIt seems this one got forgotten, I only see v2 in pu.\n\nCheers.\n\n-- \nFelipe Contreras\n"},{"id":"203847","messageId":"7v4nkdxawx.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"CAMP44s2F9C4cr6v===M3AWHieaiUk1adigcU8txpZPL0wN81Ow@mail.gmail.com","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-11-26T04:09:34Z","receivedAt":"2012-11-26T04:09:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n> On Sun, Nov 11, 2012 at 3:19 PM, Felipe Contreras\n> <felipe.contreras@gmail.com> wrote:\n>> This is a re-roll of the previous series to add support to fetch and push\n>> special modes, and refactor some related code.\n>\n> It seems this one got forgotten, I only see v2 in pu.\n\nOops; I think that was fell through the cracks during the maintainer\nhand-off.  As the previous one has already been cooking in 'next'\nfor a week or so, I would appreciate if you send incremental updates\nto fix or enhance what is in there.\n\nThanks.\n"},{"id":"203868","messageId":"CAMP44s1G3b3XQX+=5Ag2exdy83hULbz1m0Z6UFDrhZU2TGwBMg@mail.gmail.com","threadId":"32073","inReplyTo":"7v4nkdxawx.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-26T11:34:12Z","receivedAt":"2012-11-26T11:34:12Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Mon, Nov 26, 2012 at 5:09 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>> On Sun, Nov 11, 2012 at 3:19 PM, Felipe Contreras\n>> <felipe.contreras@gmail.com> wrote:\n>>> This is a re-roll of the previous series to add support to fetch and push\n>>> special modes, and refactor some related code.\n>>\n>> It seems this one got forgotten, I only see v2 in pu.\n>\n> Oops; I think that was fell through the cracks during the maintainer\n> hand-off.  As the previous one has already been cooking in 'next'\n> for a week or so, I would appreciate if you send incremental updates\n> to fix or enhance what is in there.\n\nYes, that's what I have planned for the next patches, as I already did\nfor remote-hg, but the changes in remote-bzr were a bit bigger.\n\n-- \nFelipe Contreras\n"},{"id":"204061","messageId":"7vehjelizc.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"CAMP44s1G3b3XQX+=5Ag2exdy83hULbz1m0Z6UFDrhZU2TGwBMg@mail.gmail.com","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-11-27T23:32:55Z","receivedAt":"2012-11-27T23:32:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n> On Mon, Nov 26, 2012 at 5:09 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>>\n>>> On Sun, Nov 11, 2012 at 3:19 PM, Felipe Contreras\n>>> <felipe.contreras@gmail.com> wrote:\n>>>> This is a re-roll of the previous series to add support to fetch and push\n>>>> special modes, and refactor some related code.\n>>>\n>>> It seems this one got forgotten, I only see v2 in pu.\n>>\n>> Oops; I think that was fell through the cracks during the maintainer\n>> hand-off.  As the previous one has already been cooking in 'next'\n>> for a week or so, I would appreciate if you send incremental updates\n>> to fix or enhance what is in there.\n>\n> Yes, that's what I have planned for the next patches, as I already did\n> for remote-hg, but the changes in remote-bzr were a bit bigger.\n\nOK.  Both fc/remote-hg and fc/remote-bzr are slated for 'master'\nsoonish, but I take the above to mean that fc/remote-hg is ready\nwhile it is better to wait for updates to fc/remote-bzr before\nmerging it.\n\nThanks.\n"},{"id":"204070","messageId":"CAMP44s0swzsg1MkQHkPUtwZi71xaad3y4uY542jYvXAf8Ha5nQ@mail.gmail.com","threadId":"32073","inReplyTo":"7vehjelizc.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-28T00:23:29Z","receivedAt":"2012-11-28T00:23:29Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Wed, Nov 28, 2012 at 12:32 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>> On Mon, Nov 26, 2012 at 5:09 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>>> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>>>\n>>>> On Sun, Nov 11, 2012 at 3:19 PM, Felipe Contreras\n>>>> <felipe.contreras@gmail.com> wrote:\n>>>>> This is a re-roll of the previous series to add support to fetch and push\n>>>>> special modes, and refactor some related code.\n>>>>\n>>>> It seems this one got forgotten, I only see v2 in pu.\n>>>\n>>> Oops; I think that was fell through the cracks during the maintainer\n>>> hand-off.  As the previous one has already been cooking in 'next'\n>>> for a week or so, I would appreciate if you send incremental updates\n>>> to fix or enhance what is in there.\n>>\n>> Yes, that's what I have planned for the next patches, as I already did\n>> for remote-hg, but the changes in remote-bzr were a bit bigger.\n>\n> OK.  Both fc/remote-hg and fc/remote-bzr are slated for 'master'\n> soonish, but I take the above to mean that fc/remote-hg is ready\n> while it is better to wait for updates to fc/remote-bzr before\n> merging it.\n\nI was waiting on both to be merged, let me see what I have pending and\nwould be nice to have before the merge.\n\n\n-- \nFelipe Contreras\n"},{"id":"204075","messageId":"CAMP44s1NrmhVaTgAs_Y_C3BXpX205L=yBigxp+k9qxz4tOEKag@mail.gmail.com","threadId":"32073","inReplyTo":"7vehjelizc.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-28T00:42:14Z","receivedAt":"2012-11-28T00:42:14Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Wed, Nov 28, 2012 at 12:32 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>> On Mon, Nov 26, 2012 at 5:09 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>>> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>>>\n>>>> On Sun, Nov 11, 2012 at 3:19 PM, Felipe Contreras\n>>>> <felipe.contreras@gmail.com> wrote:\n>>>>> This is a re-roll of the previous series to add support to fetch and push\n>>>>> special modes, and refactor some related code.\n>>>>\n>>>> It seems this one got forgotten, I only see v2 in pu.\n>>>\n>>> Oops; I think that was fell through the cracks during the maintainer\n>>> hand-off.  As the previous one has already been cooking in 'next'\n>>> for a week or so, I would appreciate if you send incremental updates\n>>> to fix or enhance what is in there.\n>>\n>> Yes, that's what I have planned for the next patches, as I already did\n>> for remote-hg, but the changes in remote-bzr were a bit bigger.\n>\n> OK.  Both fc/remote-hg and fc/remote-bzr are slated for 'master'\n> soonish, but I take the above to mean that fc/remote-hg is ready\n> while it is better to wait for updates to fc/remote-bzr before\n> merging it.\n\nPlease update remote-bzr to series version 3. The rest of the patches\nwill be on top of that version.\n\n-- \nFelipe Contreras\n"},{"id":"204092","messageId":"7vsj7ujxr2.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"CAMP44s0swzsg1MkQHkPUtwZi71xaad3y4uY542jYvXAf8Ha5nQ@mail.gmail.com","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-11-28T01:56:49Z","receivedAt":"2012-11-28T01:56:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n>> OK.  Both fc/remote-hg and fc/remote-bzr are slated for 'master'\n>> soonish, but I take the above to mean that fc/remote-hg is ready\n>> while it is better to wait for updates to fc/remote-bzr before\n>> merging it.\n>\n> I was waiting on both to be merged, let me see what I have pending and\n> would be nice to have before the merge.\n\nOK.\n\nAt this point, both have been cooking for a week or more in 'next',\nthere is no existing users, they are on the fringe so breakages in\nthem won't negatively affect anybody anyway.  So it doesn't matter\nmuch if they are merged to 'master' and then fixed up with follow up\npatches after that, or fixed up with follow up patches while they\nare in 'next', as they won't be rewound and restarted from scratch.\n"},{"id":"204103","messageId":"CAMP44s3t54zYFha_qsDrg0JDZ52q8=WTs7q0rJ9qZL8kVCVWKA@mail.gmail.com","threadId":"32073","inReplyTo":"7vsj7ujxr2.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-28T02:18:27Z","receivedAt":"2012-11-28T02:18:27Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Wed, Nov 28, 2012 at 2:56 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>>> OK.  Both fc/remote-hg and fc/remote-bzr are slated for 'master'\n>>> soonish, but I take the above to mean that fc/remote-hg is ready\n>>> while it is better to wait for updates to fc/remote-bzr before\n>>> merging it.\n>>\n>> I was waiting on both to be merged, let me see what I have pending and\n>> would be nice to have before the merge.\n>\n> OK.\n>\n> At this point, both have been cooking for a week or more in 'next',\n> there is no existing users, they are on the fringe so breakages in\n> them won't negatively affect anybody anyway.  So it doesn't matter\n> much if they are merged to 'master' and then fixed up with follow up\n> patches after that, or fixed up with follow up patches while they\n> are in 'next', as they won't be rewound and restarted from scratch.\n\nThe fixes are affecting some people, that's why I did them. Some were\nreported here in the mailing list, and some in my github's clone:\n\nhttps://github.com/felipec/git/issues?page=1&state=closed\n\nI tried to minimize the changes in the last patch series I sent, I\nhave more, but those truly can wait.\n\nCheers.\n\n-- \nFelipe Contreras\n"},{"id":"204107","messageId":"7vpq2yihaq.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"CAMP44s3t54zYFha_qsDrg0JDZ52q8=WTs7q0rJ9qZL8kVCVWKA@mail.gmail.com","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-11-28T02:37:33Z","receivedAt":"2012-11-28T02:37:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n>> At this point, both have been cooking for a week or more in 'next',\n>> there is no existing users, they are on the fringe so breakages in\n>> them won't negatively affect anybody anyway.  So it doesn't matter\n>> much if they are merged to 'master' and then fixed up with follow up\n>> patches after that, or fixed up with follow up patches while they\n>> are in 'next', as they won't be rewound and restarted from scratch.\n>\n> The fixes are affecting some people, that's why I did them. Some were\n> reported here in the mailing list, and some in my github's clone:\n>\n> https://github.com/felipec/git/issues?page=1&state=closed\n\nAre you talking about -hg or -bzr or both?\n\nIn any case, I am mostly concerned about *my* next release, whose\nrc0 will be tagged sometime this week or the next week.\n\nPeople who have been bitten by bugs from *your* tree or versions in\n'next' do not count.  When I said \"no existing users\", I was talking\nabout the end users who need rock solid stable \"releases\" because\ntagged versions are the only ones they use.\n\nIf the code of these topics is still in flux and needs constant\nfixes, probably it is a better idea to cook them longer in 'next',\nskipping the upcoming 1.8.1 release.  If we are going to go that\nroute, we can drop the v2 fc/remote-bzr and queue v3 when we rewind\nthe tip of 'next' after 1.8.1 release (by that time you may have v4\nof the series, but then we can skip v3).  Is that more preferrable\nthan rushing these topics forward before they are ready for general\naudience?\n"},{"id":"204110","messageId":"CAMP44s23FfxQG6v+dfRGWHzxpWZ5BSGpAm=8Q8Bmj04tDwmwKw@mail.gmail.com","threadId":"32073","inReplyTo":"7vpq2yihaq.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-28T03:05:46Z","receivedAt":"2012-11-28T03:05:46Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Wed, Nov 28, 2012 at 3:37 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>>> At this point, both have been cooking for a week or more in 'next',\n>>> there is no existing users, they are on the fringe so breakages in\n>>> them won't negatively affect anybody anyway.  So it doesn't matter\n>>> much if they are merged to 'master' and then fixed up with follow up\n>>> patches after that, or fixed up with follow up patches while they\n>>> are in 'next', as they won't be rewound and restarted from scratch.\n>>\n>> The fixes are affecting some people, that's why I did them. Some were\n>> reported here in the mailing list, and some in my github's clone:\n>>\n>> https://github.com/felipec/git/issues?page=1&state=closed\n>\n> Are you talking about -hg or -bzr or both?\n>\n> In any case, I am mostly concerned about *my* next release, whose\n> rc0 will be tagged sometime this week or the next week.\n>\n> People who have been bitten by bugs from *your* tree or versions in\n> 'next' do not count.  When I said \"no existing users\", I was talking\n> about the end users who need rock solid stable \"releases\" because\n> tagged versions are the only ones they use.\n\nIf users you call \"fringe\" have noticed these compatibility issues,\nchances are your \"existing users\" are going to catch them as well.\n\nThose issues were fixed right away, but I didn't sent them because I\nwanted things to settle. I didn't see that v2 landed in next until\nnow.\n\n> If the code of these topics is still in flux and needs constant\n> fixes, probably it is a better idea to cook them longer in 'next',\n> skipping the upcoming 1.8.1 release.  If we are going to go that\n> route, we can drop the v2 fc/remote-bzr and queue v3 when we rewind\n> the tip of 'next' after 1.8.1 release (by that time you may have v4\n> of the series, but then we can skip v3).  Is that more preferrable\n> than rushing these topics forward before they are ready for general\n> audience?\n\nThey are not in constant flux, that's why I haven't send any new\nre-rolls since v3, which was on November 11. I've been using v3 for\nbaseline since them, and the rest of the patches I've sent on top of\nthat.\n\nIn fact, these particular fixes were already sent on November 13 (on top of v3):\nhttp://article.gmane.org/gmane.comp.version-control.git/209558\n\nOn November 10 Jeff threatened to to merge v2 to next on the \"What's\ncooking\", and I told him I was about to sent a re-roll, he\nacknowledged the same day, and I sent the next one.\n\nSince v3 remote-bzr hasn't been on flux.\n\nNow, what you do is up to you, but I think v3 plus the two patches I\nsent on nov 13, and just resent today should be safe. That being said,\nI don't use remote-bzr really, and I don't know how many people have\nbeen using it, so I have no idea how ready it really is. If I were you\nI would just merge v3 to next, or revert v2 and merge v3, and then\napply the two patches on top. Or if you want, revert v2, wait for\n1.8.1, and then merge v3. Either way it's doubtful there will be a v4\n(if there are next patches they will be on top of v3, as they have\nbeen for quite some time now), so it's not clear what \"existing users\"\nwill gain by that.\n\nI'm confident about remote-hg though.\n\nCheers.\n\n-- \nFelipe Contreras\n"},{"id":"204137","messageId":"7vhaoai533.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"CAMP44s23FfxQG6v+dfRGWHzxpWZ5BSGpAm=8Q8Bmj04tDwmwKw@mail.gmail.com","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-11-28T07:01:20Z","receivedAt":"2012-11-28T07:01:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n>> People who have been bitten by bugs from *your* tree or versions in\n>> 'next' do not count.  When I said \"no existing users\", I was talking\n>> about the end users who need rock solid stable \"releases\" because\n>> tagged versions are the only ones they use.\n>\n> If users you call \"fringe\" have noticed these compatibility issues,\n> chances are your \"existing users\" are going to catch them as well.\n\nThere seems to be some misunderstanding.\n\nI have never called them \"fringe\"; they are \"early adopters\" who are\nexpected to be capable of \"git pull\" to pick up fixes from\nbetween-releases trees (or \"git am\" patches from the list) and\nrebuild their Git.  \n\nWe cannot expect that from the real end users (who do not exist yet,\nluckily) who only follow tagged releases.  Hitting them with bugs we\nneed to fix after the release is not \"letting them notice and\nreport\", but just \"irresponsibly hurting the end users\".  \"Letting\nthem notice and report\" is what \"early adopter\" population who run\n'next' are for.  Quality expectations between these two populations\nare quite different.\n\n> ... That being said,\n> I don't use remote-bzr really, and I don't know how many people have\n> been using it, so I have no idea how ready it really is. ...\n> ... Either way it's doubtful there will be a v4\n\nOK; thanks for clarification.  If you are not using it actively, it\nprobably is a better idea to proceed with more caution, as low rate\nof update necessity does not directly relate to maturity of the\ntool.  I'd feel better to cook it longer in 'next' to recruit early\nadopters so that we can hear positive feedbacks (or negative ones\nthat can result in fixes to whatever is still uncovered, if any).\n\nI hate reverting anything from 'next', but for the above to work\nsmoothly, it seems to me that reverting the merge of v2 and queuing\nv3 plus remainder sounds like the best course.\n\n> I'm confident about remote-hg though.\n\nMeaning unlike remote-bzr, at least you are using it more actively\n(or you know people who are), right?  I've queued the two patches\n(out of four) from you today, so we can merge it to 'master' before\n1.8.1-rc0.\n\nThanks.\n"},{"id":"204142","messageId":"CAMP44s07c55zAtNXvPwtQFeQwEQKFfq9YOhFynqguc-HpA3EMg@mail.gmail.com","threadId":"32073","inReplyTo":"7vhaoai533.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 0/7] New remote-bzr remote helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-11-28T07:42:47Z","receivedAt":"2012-11-28T07:42:47Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Wed, Nov 28, 2012 at 8:01 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>>> People who have been bitten by bugs from *your* tree or versions in\n>>> 'next' do not count.  When I said \"no existing users\", I was talking\n>>> about the end users who need rock solid stable \"releases\" because\n>>> tagged versions are the only ones they use.\n>>\n>> If users you call \"fringe\" have noticed these compatibility issues,\n>> chances are your \"existing users\" are going to catch them as well.\n>\n> There seems to be some misunderstanding.\n>\n> I have never called them \"fringe\"; they are \"early adopters\" who are\n> expected to be capable of \"git pull\" to pick up fixes from\n> between-releases trees (or \"git am\" patches from the list) and\n> rebuild their Git.\n>\n> We cannot expect that from the real end users (who do not exist yet,\n> luckily) who only follow tagged releases.  Hitting them with bugs we\n> need to fix after the release is not \"letting them notice and\n> report\", but just \"irresponsibly hurting the end users\".  \"Letting\n> them notice and report\" is what \"early adopter\" population who run\n> 'next' are for.  Quality expectations between these two populations\n> are quite different.\n\nPerhaps, but I still don't agree with the statement that the people\nbitten by those bugs don't count. If those bugs are not fixed, they\nwill bite the \"normal\" population.\n\n>> ... That being said,\n>> I don't use remote-bzr really, and I don't know how many people have\n>> been using it, so I have no idea how ready it really is. ...\n>> ... Either way it's doubtful there will be a v4\n>\n> OK; thanks for clarification.  If you are not using it actively, it\n> probably is a better idea to proceed with more caution, as low rate\n> of update necessity does not directly relate to maturity of the\n> tool.  I'd feel better to cook it longer in 'next' to recruit early\n> adopters so that we can hear positive feedbacks (or negative ones\n> that can result in fixes to whatever is still uncovered, if any).\n\nPerhaps, on the other hand it's not like any of their existing\nfunctionality will break. Chances are they will be happy to have\nanything that somehow works, even if it has bugs. In fact, the current\nremote-bzr, even if it hasn't received so much testing, is probably\nalready more stable than other tools:\n\nAs an example there is this bug:\nhttp://bugs.launchpad.net/bzr/+bug/541626\n\nWhich has been affecting users of 'bzr fast-export' for years (most of\nbzr<->git bridges use this tool), and nobody does anything about it,\neven though the developers thought the problem was in bzr itself (and\nthat it was actually fixed, despite the reports to the contrary). I\nfixed the problem and added a reliable test case to reproduce the\nissue in bzr's test suite itself, only to receive no feedback.\n\nI think there are very few users of bazaar, and if you read the source\ncode you would be happy that's the case, so I'm not sure letting it\ncook in 'next' is going to achieve much, most of them are going to see\nit only when it hits master. Most likely the few bazaar users are\naccustomed to different quality standards, and this tool doesn't even\nhave known bugs.\n\n>> I'm confident about remote-hg though.\n>\n> Meaning unlike remote-bzr, at least you are using it more actively\n> (or you know people who are), right?  I've queued the two patches\n> (out of four) from you today, so we can merge it to 'master' before\n> 1.8.1-rc0.\n\nI'm not using it actively, it seems some people are, but that's not\nwhy I'm confident; it's because of the extensive automatic testing\nthat compares the output with hg-git (which is widely used).\n\nCheers.\n\n-- \nFelipe Contreras\n"},{"id":"204170","messageId":"7vy5hlvddb.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"1352643598-8500-6-git-send-email-felipe.contreras@gmail.com","subject":"Re: [PATCH v3 5/7] remote-bzr: add simple tests","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-11-28T17:36:16Z","receivedAt":"2012-11-28T17:36:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> ---\n>  contrib/remote-helpers/test-bzr.sh | 111 +++++++++++++++++++++++++++++++++++++\n>  1 file changed, 111 insertions(+)\n>  create mode 100755 contrib/remote-helpers/test-bzr.sh\n>\n> diff --git a/contrib/remote-helpers/test-bzr.sh b/contrib/remote-helpers/test-bzr.sh\n> new file mode 100755\n> index 0000000..8594ffc\n> --- /dev/null\n> +++ b/contrib/remote-helpers/test-bzr.sh\n> @@ -0,0 +1,111 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2012 Felipe Contreras\n> +#\n> +\n> +test_description='Test remote-bzr'\n> +\n> +. ./test-lib.sh\n> +\n> +if ! test_have_prereq PYTHON; then\n> +\tskip_all='skipping remote-bzr tests; python not available'\n> +\ttest_done\n> +fi\n> +\n> +if ! \"$PYTHON_PATH\" -c 'import bzrlib'; then\n> +\tskip_all='skipping remote-bzr tests; bzr not available'\n> +\ttest_done\n> +fi\n\n> +cmd=<<EOF\n> +import bzrlib\n> +bzrlib.initialize()\n> +import bzrlib.plugin\n> +bzrlib.plugin.load_plugins()\n> +import bzrlib.plugins.fastimport\n> +EOF\n> +if ! \"$PYTHON_PATH\" -c \"$cmd\"; then\n\nI cannot see how this could have ever worked.  It could be that you\nwrote it for zsh and tested only with the version of zsh you have;\nzsh I have here does not grok it (and of course dash and bash won't).\n\nIn any case, I do not think this is a POSIX shell.  Just replace\n\"=<<EOF\" and \"EOF\" with single quote and everybody's shell should be\nable to read it.\n\n> +\techo \"consider setting BZR_PLUGIN_PATH=$HOME/.bazaar/plugins\" 1>&2\n> +\tskip_all='skipping remote-bzr tests; bzr-fastimport not available'\n> +\ttest_done\n> +fi\n> +\n> +check () {\n> +\t(cd $1 &&\n> +\tgit log --format='%s' -1 &&\n> +\tgit symbolic-ref HEAD) > actual &&\n> +\t(echo $2 &&\n> +\techo \"refs/heads/$3\") > expected &&\n\nStyle: s/> expected/>expected/;\nI won't repeat this but there are many others in this file.\n\nThanks.\n"},{"id":"204171","messageId":"7vtxs9vda3.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"1352643598-8500-5-git-send-email-felipe.contreras@gmail.com","subject":"Re: [PATCH v3 4/7] remote-bzr: update working tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-11-28T17:38:12Z","receivedAt":"2012-11-28T17:38:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n> ---\n>  contrib/remote-helpers/git-remote-bzr | 2 ++\n>  1 file changed, 2 insertions(+)\n>\n> diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\n> index 2c05f35..5b89a05 100755\n> --- a/contrib/remote-helpers/git-remote-bzr\n> +++ b/contrib/remote-helpers/git-remote-bzr\n> @@ -571,6 +571,8 @@ def do_export(parser):\n>              repo.generate_revision_history(revid, marks.get_tip('master'))\n>              revno, revid = repo.last_revision_info()\n>              peer.import_last_revision_info_and_tags(repo, revno, revid)\n> +            wt = peer.bzrdir.open_workingtree()\n> +            wt.update()\n>          print \"ok %s\" % ref\n>      print\n\nShouldn't this be squashed as part of one of the earlier patches?\nThe split between 1/7 (import first) and 2/7 (then support export)\nmakes sense, but this one looks more like \"oops, we forgot to touch\nthe working tree while updating the history in the previous steps\nand here is a fix\" to me.\n"},{"id":"204854","messageId":"CAMP44s1ZdMK+0_pP3qkZUepOvkfMaXeY2BV0MFu5YOSV=40Dcw@mail.gmail.com","threadId":"32073","inReplyTo":"7vtxs9vda3.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 4/7] remote-bzr: update working tree","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-12-13T22:08:54Z","receivedAt":"2012-12-13T22:08:54Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Wed, Nov 28, 2012 at 11:38 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n>> ---\n>>  contrib/remote-helpers/git-remote-bzr | 2 ++\n>>  1 file changed, 2 insertions(+)\n>>\n>> diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\n>> index 2c05f35..5b89a05 100755\n>> --- a/contrib/remote-helpers/git-remote-bzr\n>> +++ b/contrib/remote-helpers/git-remote-bzr\n>> @@ -571,6 +571,8 @@ def do_export(parser):\n>>              repo.generate_revision_history(revid, marks.get_tip('master'))\n>>              revno, revid = repo.last_revision_info()\n>>              peer.import_last_revision_info_and_tags(repo, revno, revid)\n>> +            wt = peer.bzrdir.open_workingtree()\n>> +            wt.update()\n>>          print \"ok %s\" % ref\n>>      print\n>\n> Shouldn't this be squashed as part of one of the earlier patches?\n> The split between 1/7 (import first) and 2/7 (then support export)\n> makes sense, but this one looks more like \"oops, we forgot to touch\n> the working tree while updating the history in the previous steps\n> and here is a fix\" to me.\n\nPerhaps. It's not really clear if we should update the working tree at\nall. A 'git push' doesn't update the working directory on the remote,\nbut a 'bzr push' does. I thought it was better to leave this\ndistinction clear, in case this becomes an issue later on.\n\nCheers.\n\n-- \nFelipe Contreras\n"},{"id":"204858","messageId":"7vobhxwm3n.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"CAMP44s1ZdMK+0_pP3qkZUepOvkfMaXeY2BV0MFu5YOSV=40Dcw@mail.gmail.com","subject":"Re: [PATCH v3 4/7] remote-bzr: update working tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-12-13T23:47:40Z","receivedAt":"2012-12-13T23:47:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n> On Wed, Nov 28, 2012 at 11:38 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>>\n>>> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n>>> ---\n>>>  contrib/remote-helpers/git-remote-bzr | 2 ++\n>>>  1 file changed, 2 insertions(+)\n>>>\n>>> diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\n>>> index 2c05f35..5b89a05 100755\n>>> --- a/contrib/remote-helpers/git-remote-bzr\n>>> +++ b/contrib/remote-helpers/git-remote-bzr\n>>> @@ -571,6 +571,8 @@ def do_export(parser):\n>>>              repo.generate_revision_history(revid, marks.get_tip('master'))\n>>>              revno, revid = repo.last_revision_info()\n>>>              peer.import_last_revision_info_and_tags(repo, revno, revid)\n>>> +            wt = peer.bzrdir.open_workingtree()\n>>> +            wt.update()\n>>>          print \"ok %s\" % ref\n>>>      print\n>>\n>> Shouldn't this be squashed as part of one of the earlier patches?\n>> The split between 1/7 (import first) and 2/7 (then support export)\n>> makes sense, but this one looks more like \"oops, we forgot to touch\n>> the working tree while updating the history in the previous steps\n>> and here is a fix\" to me.\n>\n> Perhaps. It's not really clear if we should update the working tree at\n> all. A 'git push' doesn't update the working directory on the remote,\n> but a 'bzr push' does. I thought it was better to leave this\n> distinction clear, in case this becomes an issue later on.\n\nIf you explained that in the log message, then we would have avoided\nthis exchange, and more importantly, if you had a in-code comment\nthere, it may help people who later want to add a knob to leave the\nworking tree intact.  The seed you sow now to help others, who may\nbe less skillful and knowledgeable than you are, will help the\nproject in the longer term.\n\nThanks.  I don't mind rephrasing that four lines and amend the\nlog message of what I have in 'pu', if that is what you want.\n"},{"id":"204860","messageId":"7vhanpwllh.fsf@alter.siamese.dyndns.org","threadId":"32073","inReplyTo":"7vobhxwm3n.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 4/7] remote-bzr: update working tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-12-13T23:58:34Z","receivedAt":"2012-12-13T23:58:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>> Perhaps. It's not really clear if we should update the working tree at\n>> all. A 'git push' doesn't update the working directory on the remote,\n>> but a 'bzr push' does. I thought it was better to leave this\n>> distinction clear, in case this becomes an issue later on.\n> ...\n> ...  I don't mind rephrasing that four lines and amend the\n> log message of what I have in 'pu', if that is what you want.\n\n... which may look like this.\n\n    remote-bzr: update working tree upon pushing\n    \n    A 'git push' doesn't update the working directory on the remote, but\n    a 'bzr push' does.  Teach the remote helper for bzr to update the\n    working tree on the bzr side upon pushing via the \"export\" command.\n\nLet me know if I grossly misinterpreted/misrepresented what you\nwanted to do in this patch.\n\nThanks.\n"},{"id":"204863","messageId":"CAMP44s2RrPDv=8s8bWUk7oWQ7D_P15E+-ShcFzYCjOP-ik6v6w@mail.gmail.com","threadId":"32073","inReplyTo":"7vhanpwllh.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3 4/7] remote-bzr: update working tree","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2012-12-14T00:52:00Z","receivedAt":"2012-12-14T00:52:00Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Thu, Dec 13, 2012 at 5:58 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>>> Perhaps. It's not really clear if we should update the working tree at\n>>> all. A 'git push' doesn't update the working directory on the remote,\n>>> but a 'bzr push' does. I thought it was better to leave this\n>>> distinction clear, in case this becomes an issue later on.\n>> ...\n>> ...  I don't mind rephrasing that four lines and amend the\n>> log message of what I have in 'pu', if that is what you want.\n>\n> ... which may look like this.\n>\n>     remote-bzr: update working tree upon pushing\n>\n>     A 'git push' doesn't update the working directory on the remote, but\n>     a 'bzr push' does.  Teach the remote helper for bzr to update the\n>     working tree on the bzr side upon pushing via the \"export\" command.\n>\n> Let me know if I grossly misinterpreted/misrepresented what you\n> wanted to do in this patch.\n\nLooks good to me.\n\nCheers.\n\n-- \nFelipe Contreras\n"}]}