{"thread":{"id":"16269","subject":"importing mercurial patch","startedAt":"2008-11-11T10:58:33Z","lastAt":"2008-11-11T23:36:19Z","messageCount":6,"participants":["Ondrej Certik","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"95449","messageId":"85b5c3130811110258h53d389co97a3c33e10667ae8@mail.gmail.com","threadId":"16269","inReplyTo":null,"subject":"importing mercurial patch","fromName":"Ondrej Certik","fromEmail":"ondrej@certik.cz","sentAt":"2008-11-11T10:58:33Z","receivedAt":"2008-11-11T10:58:33Z","isPatch":false,"sender":{"key":"ondrej@certik.cz","avatar":"https://gravatar.com/avatar/106d05822138a98292e09d1580dbe8f27e05faecd87f13d5d58d889d0687771c?d=mp&s=160"},"body":"Hi,\n\nI'd like git to be able to import mercurial-exported patches. This\nshort Python program does it:\n\n\n-------------------------------------\n#! /usr/bin/python\n\nimport os\nimport sys\nimport re\nimport tempfile\n\ndef run(cmd):\n    print cmd\n    os.system(cmd)\n\npatch = sys.argv[1]\np = open(patch).read()\nauthor = re.search(\"# User (.+)\", p).groups()[0]\np = p.split(\"\\n\")\nwhile not p[0].startswith(\"# Parent\"):\n    del p[0]\ni = 1\nwhile not p[i].startswith(\"diff -r \"):\n    i += 1\ncommit_message = \"\\n\".join(p[1:i])\n_, filename = tempfile.mkstemp()\nf = open(filename, \"w\")\nf.write(commit_message)\nf.close()\n\nrun(\"git apply %s\" % patch)\nrun(\"git ci -a --author='%s' -F %s\" % (author, filename) )\n---------------------\n\n\nHow should this be implemented in git? Should I try to extend\n\"git-am.sh\" to handle it?\n\nFor better imagination, this is how the patch looks like:\n\nhttp://paste.debian.net/21210/\n\nThanks for any feedback,\nOndrej\n"},{"id":"95450","messageId":"85b5c3130811110259x5d659f7ah74e7774773bdcc58@mail.gmail.com","threadId":"16269","inReplyTo":"85b5c3130811110258h53d389co97a3c33e10667ae8@mail.gmail.com","subject":"Re: importing mercurial patch","fromName":"Ondrej Certik","fromEmail":"ondrej@certik.cz","sentAt":"2008-11-11T10:59:43Z","receivedAt":"2008-11-11T10:59:43Z","isPatch":false,"sender":{"key":"ondrej@certik.cz","avatar":"https://gravatar.com/avatar/106d05822138a98292e09d1580dbe8f27e05faecd87f13d5d58d889d0687771c?d=mp&s=160"},"body":"On Tue, Nov 11, 2008 at 11:58 AM, Ondrej Certik <ondrej@certik.cz> wrote:\n> Hi,\n>\n> I'd like git to be able to import mercurial-exported patches. This\n> short Python program does it:\n>\n>\n> -------------------------------------\n> #! /usr/bin/python\n>\n> import os\n> import sys\n> import re\n> import tempfile\n>\n> def run(cmd):\n>    print cmd\n>    os.system(cmd)\n>\n> patch = sys.argv[1]\n> p = open(patch).read()\n> author = re.search(\"# User (.+)\", p).groups()[0]\n> p = p.split(\"\\n\")\n> while not p[0].startswith(\"# Parent\"):\n>    del p[0]\n> i = 1\n> while not p[i].startswith(\"diff -r \"):\n>    i += 1\n> commit_message = \"\\n\".join(p[1:i])\n> _, filename = tempfile.mkstemp()\n> f = open(filename, \"w\")\n> f.write(commit_message)\n> f.close()\n>\n> run(\"git apply %s\" % patch)\n> run(\"git ci -a --author='%s' -F %s\" % (author, filename) )\n> ---------------------\n>\n>\n> How should this be implemented in git? Should I try to extend\n> \"git-am.sh\" to handle it?\n\nJust to make it clear --- I will of course use sh or C with git, I\nonly used Python above because that's the language I know the best.\n\nOndrej\n"},{"id":"95455","messageId":"alpine.DEB.1.00.0811111258260.30769@pacific.mpi-cbg.de","threadId":"16269","inReplyTo":"85b5c3130811110258h53d389co97a3c33e10667ae8@mail.gmail.com","subject":"Re: importing mercurial patch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-11-11T12:00:49Z","receivedAt":"2008-11-11T12:00:49Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 11 Nov 2008, Ondrej Certik wrote:\n\n> I'd like git to be able to import mercurial-exported patches.\n\nHave you seen\n\n\thttp://repo.or.cz/w/fast-export.git/\n\n?\n\nI had many problems with it, so many that I started to write my own \nhg-fast-export together with Dirkjan Ochtman, a very nice Mercurial guy \n(actually, he started writing it, and I tried to fix it, but it still does \nnot work due to merge mishandling).\n\nBut then I saw that finally, they started work on it again.  It is \nsomewhat sloppy, having a large part in Python and a large part in shell, \nwhich could have been avoided, but at least it works.\n\nCiao,\nDscho\n"},{"id":"95456","messageId":"85b5c3130811110418l11be8084sf0f47a1095755747@mail.gmail.com","threadId":"16269","inReplyTo":"alpine.DEB.1.00.0811111258260.30769@pacific.mpi-cbg.de","subject":"Re: importing mercurial patch","fromName":"Ondrej Certik","fromEmail":"ondrej@certik.cz","sentAt":"2008-11-11T12:18:37Z","receivedAt":"2008-11-11T12:18:37Z","isPatch":false,"sender":{"key":"ondrej@certik.cz","avatar":"https://gravatar.com/avatar/106d05822138a98292e09d1580dbe8f27e05faecd87f13d5d58d889d0687771c?d=mp&s=160"},"body":"On Tue, Nov 11, 2008 at 1:00 PM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n> On Tue, 11 Nov 2008, Ondrej Certik wrote:\n>\n>> I'd like git to be able to import mercurial-exported patches.\n>\n> Have you seen\n>\n>        http://repo.or.cz/w/fast-export.git/\n>\n> ?\n>\n> I had many problems with it, so many that I started to write my own\n> hg-fast-export together with Dirkjan Ochtman, a very nice Mercurial guy\n> (actually, he started writing it, and I tried to fix it, but it still does\n> not work due to merge mishandling).\n>\n> But then I saw that finally, they started work on it again.  It is\n> somewhat sloppy, having a large part in Python and a large part in shell,\n> which could have been avoided, but at least it works.\n\nYes, I use fast-export to convert from hg to git on the fly. But as I\nunderstood it, you need to have the whole repository converted. So if\nsomeone sends the patch in the mercurial format, I just want to apply\nit to git, instead of applying it to hg first and then converting.\nWell, you are right, that this is definitely one way of doing it.\n\nBut imho if git supported mercurial patches, life would be a lot easier.\n\nOndrej\n"},{"id":"95459","messageId":"alpine.DEB.1.00.0811111454330.30769@pacific.mpi-cbg.de","threadId":"16269","inReplyTo":"85b5c3130811110418l11be8084sf0f47a1095755747@mail.gmail.com","subject":"Re: importing mercurial patch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-11-11T14:41:30Z","receivedAt":"2008-11-11T14:41:30Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 11 Nov 2008, Ondrej Certik wrote:\n\n> But imho if git supported mercurial patches, life would be a lot easier.\n\nMine would not be.\n\nBTW I had to be online (which is not always the case when I read email) to \naccess the pastebin, which made it more of a hassle to look at it than I \ndeem necessary.  Besides, it is bad because in 3 days, that pastie will be \ngone.  Not nice.\n\nSo here is it, for the pleasure of others:\n\n\t# HG changeset patch\n\t# User Vinzent Steinberg <vinzent.steinberg@gmail.com>\n\t# Date 1226338168 -3600\n\t# Node ID 23efeaf89f7089d94307526ec0536eb6f4382213\n\t# Parent  dab6435e04fd083d66bbfa897cbe15ab9660b9e6\n\t<commit subject>\n\n\t<commit body>\n\n\tdiff -r <commit name> -r <commit name> <filename>\n\t--- a/<filename> <date>\n\t--- b/<filename> <date>\n\t@@ <line range pair> @@\n\t...\n\nSo what I suggest is that you familiarize yourself with \nbuiltin-mailsplit.c.  Basically you'd need to enhance the is_from_line() \nfunction to check this:\n\n\tconst char *hg_patch_preamble = \"# HG changeset patch\\n\";\n\n\tif (len >= strlen(hg_patch_preamble) && !memcmp(line, \n\t\t\thg_patch_preamble, strlen(hg_patch_preamble))\n\t\treturn 1;\n\nThen you need to familiarize yourself with builtin-mailinfo.c.  In \nfunction mailinfo(), you'd need to work on this:\n\n        /* process the email header */\n        while (read_one_header_line(&line, fin))\n                check_header(&line, p_hdr_data, 1);\n\nI'd suggest to make the function read_one_header_line() into a \nhandle_one_header_line(), and replace the while loop with this:\n\n\tif (!strbuf_getline(&line, fin)) {\n\t\tif (!strcmp(line.buf, \"# HG changeset patch\\n\"))\n\t\t\twhile (handle_one_hg_header_line(&line, \n\t\t\t\t\tp_hdr_data, fin))\n\t\t\t\tstrbuf_getline(&line, fin);\n\t\telse\n\t\t\twhile (handle_one_header_line(&line, fin)) {\n\t\t\t\tcheck_header(&line, p_hdr_data, 1);\n\t\t\t\tstrbuf_getline(&line, fin);\n\t\t\t}\n\t}\n\nImplementing handle_one_hg_header_line() should be a breeze:\n\n\tstatic int handle_one_hg_header_line(struct strbuf *line,\n\t\t\tstruct strbuf *hdr_data[], FILE *in)\n\t{\n\t\tif (line.buf[0] != '#') {\n\t\t\tstrbuf_addbuf(hdr_data[1], line);\n\t\t\treturn 0; /* no more headers */\n\t\t}\n\n\t\tif (!prefixcmp(line.buf, \"# User \"))\n\t\t\tstrbuf_addstr(hdr_data[0], line.buf + 7);\n\t\telse if (!prefixcmp(line.buf, \"# Date \"))\n\t\t\tstrbuf_addstr(hdr_data[2], line.buf + 7);\n\t\treturn 1;\n\t}\n\nOkay, this is all utterly untested, and you probably need to trim the \nnewlines from the lines first, and maybe you need to replace the \nhdr_data[] entries instead of adding to them, but now you have a starting \npoint.\n\nHth,\nDscho\n"},{"id":"95506","messageId":"85b5c3130811111536q774ad33fk76da59cf90c264df@mail.gmail.com","threadId":"16269","inReplyTo":"alpine.DEB.1.00.0811111454330.30769@pacific.mpi-cbg.de","subject":"Re: importing mercurial patch","fromName":"Ondrej Certik","fromEmail":"ondrej@certik.cz","sentAt":"2008-11-11T23:36:19Z","receivedAt":"2008-11-11T23:36:19Z","isPatch":false,"sender":{"key":"ondrej@certik.cz","avatar":"https://gravatar.com/avatar/106d05822138a98292e09d1580dbe8f27e05faecd87f13d5d58d889d0687771c?d=mp&s=160"},"body":"Hi Johannes!\n\nOn Tue, Nov 11, 2008 at 3:41 PM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n> On Tue, 11 Nov 2008, Ondrej Certik wrote:\n>\n>> But imho if git supported mercurial patches, life would be a lot easier.\n>\n> Mine would not be.\n\nBecause you don't use Mercurial, or is there also some other reason?\n\n> BTW I had to be online (which is not always the case when I read email) to\n> access the pastebin, which made it more of a hassle to look at it than I\n> deem necessary.  Besides, it is bad because in 3 days, that pastie will be\n> gone.  Not nice.\n\nYou are right, sorry about that.\n\n>\n> So here is it, for the pleasure of others:\n>\n>        # HG changeset patch\n>        # User Vinzent Steinberg <vinzent.steinberg@gmail.com>\n>        # Date 1226338168 -3600\n>        # Node ID 23efeaf89f7089d94307526ec0536eb6f4382213\n>        # Parent  dab6435e04fd083d66bbfa897cbe15ab9660b9e6\n>        <commit subject>\n>\n>        <commit body>\n>\n>        diff -r <commit name> -r <commit name> <filename>\n>        --- a/<filename> <date>\n>        --- b/<filename> <date>\n>        @@ <line range pair> @@\n>        ...\n>\n> So what I suggest is that you familiarize yourself with\n> builtin-mailsplit.c.  Basically you'd need to enhance the is_from_line()\n> function to check this:\n>\n>        const char *hg_patch_preamble = \"# HG changeset patch\\n\";\n>\n>        if (len >= strlen(hg_patch_preamble) && !memcmp(line,\n>                        hg_patch_preamble, strlen(hg_patch_preamble))\n>                return 1;\n>\n> Then you need to familiarize yourself with builtin-mailinfo.c.  In\n> function mailinfo(), you'd need to work on this:\n>\n>        /* process the email header */\n>        while (read_one_header_line(&line, fin))\n>                check_header(&line, p_hdr_data, 1);\n>\n> I'd suggest to make the function read_one_header_line() into a\n> handle_one_header_line(), and replace the while loop with this:\n>\n>        if (!strbuf_getline(&line, fin)) {\n>                if (!strcmp(line.buf, \"# HG changeset patch\\n\"))\n>                        while (handle_one_hg_header_line(&line,\n>                                        p_hdr_data, fin))\n>                                strbuf_getline(&line, fin);\n>                else\n>                        while (handle_one_header_line(&line, fin)) {\n>                                check_header(&line, p_hdr_data, 1);\n>                                strbuf_getline(&line, fin);\n>                        }\n>        }\n>\n> Implementing handle_one_hg_header_line() should be a breeze:\n>\n>        static int handle_one_hg_header_line(struct strbuf *line,\n>                        struct strbuf *hdr_data[], FILE *in)\n>        {\n>                if (line.buf[0] != '#') {\n>                        strbuf_addbuf(hdr_data[1], line);\n>                        return 0; /* no more headers */\n>                }\n>\n>                if (!prefixcmp(line.buf, \"# User \"))\n>                        strbuf_addstr(hdr_data[0], line.buf + 7);\n>                else if (!prefixcmp(line.buf, \"# Date \"))\n>                        strbuf_addstr(hdr_data[2], line.buf + 7);\n>                return 1;\n>        }\n>\n> Okay, this is all utterly untested, and you probably need to trim the\n> newlines from the lines first, and maybe you need to replace the\n> hdr_data[] entries instead of adding to them, but now you have a starting\n> point.\n\nThanks a lot for the detailed help, I'll give it a shot and report\nback in couple days, hopefully with a working patch. :)\n\nOndrej\n"}]}