{"thread":{"id":"2798","subject":"[PATCH] merge-recursive: leave unmerged entries in the index.","startedAt":"2005-12-11T06:26:30Z","lastAt":"2005-12-11T09:42:38Z","messageCount":3,"participants":["Junio C Hamano","Fredrik Kuivinen"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"13474","messageId":"7vek4ktai1.fsf@assigned-by-dhcp.cox.net","threadId":"2798","inReplyTo":null,"subject":"[PATCH] merge-recursive: leave unmerged entries in the index.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-11T06:26:30Z","receivedAt":"2005-12-11T06:26:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This does two things.\n\n - When one branch renamed and the other branch did not, the\n   resulting half-merged file in the working tree used to swap\n   branches around and showed as if renaming side was \"ours\".\n   This was confusing and inconsistent (even though the conflict\n   markers were marked with branch names, it was not a good\n   enough excuse).  This changes the order of arguments to\n   mergeFile in such a case to make sure we always see \"our\"\n   change between <<< and ===, and \"their\" change between ===\n   and >>>.\n\n - When both branches renamed to the same path, and when one\n   branch renamed and the other branch did not, we attempt\n   mergeFile.  When this automerge conflicted, we used to\n   collapse the index.  Now we use update-index --index-info\n   to inject higher stage entries to leave the index in unmerged\n   state for these two cases.\n\nWhat this still does _not_ do is to inject unmerged state into\nthe index when the structural changes conflict.  I have not\nthought things through what to do in each case yet, but the\ncases this commit cover are the most common ones, so this would\nbe a good start.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n * Aside from minor cleanups both in usage strings and\n   documentation, many of which might still remain, I consider\n   this the last remaining bit before we can go 1.0, and\n   comments and corrections are very much appreciated.\n\n git-merge-recursive.py |   54 +++++++++++++++++++++++++++++++++++++++++-------\n 1 files changed, 46 insertions(+), 8 deletions(-)\n\ne5c23ede9ccc6ddd5f2cf13154f977bb1b687051\ndiff --git a/git-merge-recursive.py b/git-merge-recursive.py\nindex b7fb096..767b13c 100755\n--- a/git-merge-recursive.py\n+++ b/git-merge-recursive.py\n@@ -280,6 +280,22 @@ def updateFileExt(sha, mode, path, updat\n         runProgram(['git-update-index', '--add', '--cacheinfo',\n                     '0%o' % mode, sha, path])\n \n+def setIndexStages(path,\n+                   oSHA1, oMode,\n+                   aSHA1, aMode,\n+                   bSHA1, bMode):\n+    prog = ['git-update-index', '-z', '--index-info']\n+    proc = subprocess.Popen(prog, stdin=subprocess.PIPE)\n+    pipe = proc.stdin\n+    # Clear stages first.\n+    pipe.write(\"0 \" + (\"0\" * 40) + \"\\t\" + path + \"\\0\")\n+    # Set stages\n+    pipe.write(\"%o %s %d\\t%s\\0\" % (oMode, oSHA1, 1, path))\n+    pipe.write(\"%o %s %d\\t%s\\0\" % (aMode, aSHA1, 2, path))\n+    pipe.write(\"%o %s %d\\t%s\\0\" % (bMode, bSHA1, 3, path))\n+    pipe.close()\n+    proc.wait()\n+\n def removeFile(clean, path):\n     updateCache = cacheOnly or clean\n     updateWd = not cacheOnly\n@@ -590,6 +606,8 @@ def processRenames(renamesA, renamesB, b\n                 else:\n                     dstName2 = ren1.dstName\n \n+                # NEEDSWORK: place dstNameA at stage 2 and dstNameB at stage 3\n+                # What about other stages???\n                 updateFile(False, ren1.dstSha, ren1.dstMode, dstName1)\n                 updateFile(False, ren2.dstSha, ren2.dstMode, dstName2)\n             else:\n@@ -611,8 +629,11 @@ def processRenames(renamesA, renamesB, b\n                     cleanMerge = False\n \n                     if not cacheOnly:\n-                        updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName,\n-                                      updateCache=True, updateWd=False)\n+                        setIndexStages(ren1.dstName,\n+                                       ren1.srcSha, ren1.srcMode,\n+                                       ren1.dstSha, ren1.dstMode,\n+                                       ren2.dstSha, ren2.dstMode)\n+\n                 updateFile(clean, resSha, resMode, ren1.dstName)\n         else:\n             # Renamed in 1, maybe changed in 2\n@@ -672,11 +693,24 @@ def processRenames(renamesA, renamesB, b\n                 tryMerge = True\n \n             if tryMerge:\n+\n+                oName, oSHA1, oMode = ren1.srcName, ren1.srcSha, ren1.srcMode\n+                aName, bName = ren1.dstName, ren1.srcName\n+                aSHA1, bSHA1 = ren1.dstSha, srcShaOtherBranch\n+                aMode, bMode = ren1.dstMode, srcModeOtherBranch\n+                aBranch, bBranch = branchName1, branchName2\n+\n+                if renamesA != renames1:\n+                    aName, bName = bName, aName\n+                    aSHA1, bSHA1 = bSHA1, aSHA1\n+                    aMode, bMode = bMode, aMode\n+                    aBranch, bBranch = bBranch, aBranch\n+\n                 [resSha, resMode, clean, merge] = \\\n-                         mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode,\n-                                   ren1.dstName, ren1.dstSha, ren1.dstMode,\n-                                   ren1.srcName, srcShaOtherBranch, srcModeOtherBranch,\n-                                   branchName1, branchName2)\n+                         mergeFile(oName, oSHA1, oMode,\n+                                   aName, aSHA1, aMode,\n+                                   bName, bSHA1, bMode,\n+                                   aBranch, bBranch);\n \n                 if merge or not clean:\n                     output('Renaming', fmtRename(ren1.srcName, ren1.dstName))\n@@ -690,8 +724,12 @@ def processRenames(renamesA, renamesB, b\n                     cleanMerge = False\n \n                     if not cacheOnly:\n-                        updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName,\n-                                      updateCache=True, updateWd=False)\n+                        # Stuff stage1/2/3\n+                        setIndexStages(ren1.dstName,\n+                                       oSHA1, oMode,\n+                                       aSHA1, aMode,\n+                                       bSHA1, bMode)\n+\n                 updateFile(clean, resSha, resMode, ren1.dstName)\n \n     return cleanMerge\n-- \n0.99.9.GIT\n"},{"id":"13481","messageId":"20051211092531.GA4919@c165.ib.student.liu.se","threadId":"2798","inReplyTo":"7vek4ktai1.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] merge-recursive: leave unmerged entries in the index.","fromName":"Fredrik Kuivinen","fromEmail":"freku045@student.liu.se","sentAt":"2005-12-11T09:25:31Z","receivedAt":"2005-12-11T09:25:31Z","isPatch":true,"sender":{"key":"frekui@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13770967?v=4"},"body":"On Sat, Dec 10, 2005 at 10:26:30PM -0800, Junio C Hamano wrote:\n> This does two things.\n> \n>  - When one branch renamed and the other branch did not, the\n>    resulting half-merged file in the working tree used to swap\n>    branches around and showed as if renaming side was \"ours\".\n>    This was confusing and inconsistent (even though the conflict\n>    markers were marked with branch names, it was not a good\n>    enough excuse).  This changes the order of arguments to\n>    mergeFile in such a case to make sure we always see \"our\"\n>    change between <<< and ===, and \"their\" change between ===\n>    and >>>.\n> \n>  - When both branches renamed to the same path, and when one\n>    branch renamed and the other branch did not, we attempt\n>    mergeFile.  When this automerge conflicted, we used to\n>    collapse the index.  Now we use update-index --index-info\n>    to inject higher stage entries to leave the index in unmerged\n>    state for these two cases.\n> \n> What this still does _not_ do is to inject unmerged state into\n> the index when the structural changes conflict.  I have not\n> thought things through what to do in each case yet, but the\n> cases this commit cover are the most common ones, so this would\n> be a good start.\n> \n\nGood work! I have one comment, see below.\n\n> e5c23ede9ccc6ddd5f2cf13154f977bb1b687051\n> diff --git a/git-merge-recursive.py b/git-merge-recursive.py\n> index b7fb096..767b13c 100755\n> --- a/git-merge-recursive.py\n> +++ b/git-merge-recursive.py\n> @@ -280,6 +280,22 @@ def updateFileExt(sha, mode, path, updat\n>          runProgram(['git-update-index', '--add', '--cacheinfo',\n>                      '0%o' % mode, sha, path])\n>  \n> +def setIndexStages(path,\n> +                   oSHA1, oMode,\n> +                   aSHA1, aMode,\n> +                   bSHA1, bMode):\n> +    prog = ['git-update-index', '-z', '--index-info']\n> +    proc = subprocess.Popen(prog, stdin=subprocess.PIPE)\n> +    pipe = proc.stdin\n> +    # Clear stages first.\n> +    pipe.write(\"0 \" + (\"0\" * 40) + \"\\t\" + path + \"\\0\")\n> +    # Set stages\n> +    pipe.write(\"%o %s %d\\t%s\\0\" % (oMode, oSHA1, 1, path))\n> +    pipe.write(\"%o %s %d\\t%s\\0\" % (aMode, aSHA1, 2, path))\n> +    pipe.write(\"%o %s %d\\t%s\\0\" % (bMode, bSHA1, 3, path))\n> +    pipe.close()\n> +    proc.wait()\n> +\n\nIt might be cleaner to use\n\nrunProgram(['git-update-index', '-z', '--index-info'],\n           input=\"0 \" + (\"0\" * 40) + \"\\t\" + path + \"\\0\" + \\\n                 \"%o %s %d\\t%s\\0\" % (oMode, oSHA1, 1, path) + \\\n                 \"%o %s %d\\t%s\\0\" % (aMode, aSHA1, 2, path) + \\\n                 \"%o %s %d\\t%s\\0\" % (bMode, bSHA1, 3, path))\n\nhere instead. With this code we will get an exception if\ngit-update-index exits with an error code. It is also consistent with\nthe rest of the code.\n\n- Fredrik\n"},{"id":"13483","messageId":"7v64pwnf5d.fsf@assigned-by-dhcp.cox.net","threadId":"2798","inReplyTo":"20051211092531.GA4919@c165.ib.student.liu.se","subject":"Re: [PATCH] merge-recursive: leave unmerged entries in the index.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-11T09:42:38Z","receivedAt":"2005-12-11T09:42:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Fredrik Kuivinen <freku045@student.liu.se> writes:\n\n> It might be cleaner to use\n>\n> runProgram(['git-update-index', '-z', '--index-info'],\n>            input=\"0 \" + (\"0\" * 40) + \"\\t\" + path + \"\\0\" + \\\n>                  \"%o %s %d\\t%s\\0\" % (oMode, oSHA1, 1, path) + \\\n>                  \"%o %s %d\\t%s\\0\" % (aMode, aSHA1, 2, path) + \\\n>                  \"%o %s %d\\t%s\\0\" % (bMode, bSHA1, 3, path))\n>\n> here instead. With this code we will get an exception if\n> git-update-index exits with an error code. It is also consistent with\n> the rest of the code.\n\nThanks.  I did not know how to feed the string through\nrunProgram (well, I did not look close enough).\n"}]}