{"thread":{"id":"38234","subject":"mangled file names in git checkout-index --temp output when run in repo subdirectory","startedAt":"2014-12-23T16:36:53Z","lastAt":"2014-12-23T23:27:18Z","messageCount":2,"participants":["Russ Cox","Eric Sunshine"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"254014","messageId":"CAA8EjDRsw6o8T1sS=rpSt_+KaKt9QnONCmF23yHDdKhgKHcdww@mail.gmail.com","threadId":"38234","inReplyTo":null,"subject":"mangled file names in git checkout-index --temp output when run in repo subdirectory","fromName":"Russ Cox","fromEmail":"rsc@golang.org","sentAt":"2014-12-23T16:36:53Z","receivedAt":"2014-12-23T16:36:53Z","isPatch":false,"sender":{"key":"rsc@golang.org","avatar":null},"body":"I am using git checkout-index --temp to obtain copies of files from\nthe index, but it does not always print valid file names unless run\nfrom the repository root.\n\ngit checkout-index --temp prints names of files in the index\ninterpreted relative to the current directory below the repository\nroot.\n\nIf you have a git repo in /tmp/gitbug, you are in /tmp/gitbug/dir1,\nand you run git checkout-index --temp /tmp/gitbug/dir1/file1, the file\nlisting prints just \"file1\". So far so good.\n\nHowever, this file name shortening appears to assume that all file\nnames being printed will be within the subtree rooted at the current\ndirectory, and it just skips over the first N characters in the name,\nwhere N is the length of the current directory name relative to the\nrepo root (in the above example, N = len(\"dir1/\") = 5).\n\nThat is, if you have a git repo in /tmp/gitbug, you are in\n/tmp/gitbug/dir1, and you run git checkout-index --temp\n/tmp/gitbug/longdir2/file2, the file listing prints \"ir2/file2\", not\n\"../longdir2/file2\". If you arrange things just right you can get \"\"\nas the file name. I've never seen arbitrary binary garbage, so\n(without inspecting the source code) it does appear that something is\nkeeping the printed string pointer within the original string, even in\nthe case when N > the length of the string being printed.\n\nI have seen this in a few different versions of Git. I just downloaded\nand built Git 2.2.1 from sources and confirmed that it has the buggy\nbehavior. Below is a shell script demonstrating the bug and an\nannotated transcript of the execution of the script on my system.\n\nThe workaround seems to be that, until the bug is fixed, git\ncheckout-index must be run in the repository root.\n\nThanks.\nRuss\n\n% cat /tmp/gitbugdemo\n#!/bin/bash\n\ngit=${1:-git}\nset -e\nrm -rf /tmp/gitbug\nmkdir /tmp/gitbug\ncd /tmp/gitbug\n$git init .\nmkdir dir1 longdir2 veryveryverylongdir3\necho hello world >dir1/file1\necho hello world >longdir2/file2\necho hello world >veryveryverylongdir3/file3\nfiles=\"/tmp/gitbug/dir1/file1 /tmp/gitbug/longdir2/file2\n/tmp/gitbug/veryveryverylongdir3/file3\"\nrelfiles=$(echo $files | sed 's;/tmp/gitbug/;../;g')\nrootfiles=$(echo $relfiles | sed 's;\\.\\./;;g')\nset -x\n$git version\ncd /tmp/gitbug\n$git add .\n$git checkout-index --temp $files\n$git checkout-index --temp $rootfiles\ncd /tmp/gitbug/dir1\n$git checkout-index --temp $files\n$git checkout-index --temp $relfiles\ncd /tmp/gitbug/longdir2\n$git checkout-index --temp $files\n$git checkout-index --temp $relfiles\ncd /tmp/gitbug/veryveryverylongdir3\n$git checkout-index --temp $files\n$git checkout-index --temp $relfiles\n%\n\n% /tmp/gitbugdemo git2.2.1\nwarning: templates not found /usr/local/share/git-core/templates\nInitialized empty Git repository in /private/tmp/gitbug/.git/\n+ git2.2.1 version\ngit version 2.2.1\n+ cd /tmp/gitbug\n+ git2.2.1 add .\n\n### In root directory, all is well.\n+ git2.2.1 checkout-index --temp /tmp/gitbug/dir1/file1\n/tmp/gitbug/longdir2/file2 /tmp/gitbug/veryveryverylongdir3/file3\n.merge_file_TRqU2e dir1/file1\n.merge_file_7uajP4 longdir2/file2\n.merge_file_L4OD1U veryveryverylongdir3/file3\n+ git2.2.1 checkout-index --temp dir1/file1 longdir2/file2\nveryveryverylongdir3/file3\n.merge_file_77EMra dir1/file1\n.merge_file_DpKgMu longdir2/file2\n.merge_file_w8yfxA veryveryverylongdir3/file3\n\n### In dir1/, loses first 5 chars of file paths outside current directory.\n### Both absolute and relative command-line arguments trigger bug.\n+ cd /tmp/gitbug/dir1\n+ git2.2.1 checkout-index --temp /tmp/gitbug/dir1/file1\n/tmp/gitbug/longdir2/file2 /tmp/gitbug/veryveryverylongdir3/file3\n.merge_file_2SwQmt file1\n.merge_file_g0rOvr ir2/file2\n.merge_file_3uDW54 eryverylongdir3/file3\n+ git2.2.1 checkout-index --temp ../dir1/file1 ../longdir2/file2\n../veryveryverylongdir3/file3\n.merge_file_BwUlNt file1\n.merge_file_gQji59 ir2/file2\n.merge_file_hNNjc9 eryverylongdir3/file3\n\n### In longdir2/, loses first 9 chars of file paths outside current directory.\n### Both absolute and relative command-line arguments trigger bug.\n+ cd /tmp/gitbug/longdir2\n+ git2.2.1 checkout-index --temp /tmp/gitbug/dir1/file1\n/tmp/gitbug/longdir2/file2 /tmp/gitbug/veryveryverylongdir3/file3\n.merge_file_ljy0oC 1\n.merge_file_ANLgpx file2\n.merge_file_1lDbMp erylongdir3/file3\n+ git2.2.1 checkout-index --temp ../dir1/file1 ../longdir2/file2\n../veryveryverylongdir3/file3\n.merge_file_ugqOsC 1\n.merge_file_reoXBo file2\n.merge_file_p4tQn9 erylongdir3/file3\n\n### In veryveryverylongdir3/, inconsistent truncation of file paths\noutside current directory.\n### Absolute command-line arguments trigger bug but relative ones do not (!).\n+ cd /tmp/gitbug/veryveryverylongdir3\n+ git2.2.1 checkout-index --temp /tmp/gitbug/dir1/file1\n/tmp/gitbug/longdir2/file2 /tmp/gitbug/veryveryverylongdir3/file3\n.merge_file_VvT0uT 1\n.merge_file_UfAT1x file2\n.merge_file_Fon1Ex file3\n+ git2.2.1 checkout-index --temp ../dir1/file1 ../longdir2/file2\n../veryveryverylongdir3/file3\n.merge_file_YDHkDe ../dir1/file1\n.merge_file_F7M27m ../longdir2/file2\n.merge_file_ZkkXnQ file3\n%\n"},{"id":"254055","messageId":"CAPig+cQ4Bb=bUKeKuBp-ykorBV+mSuztvzh=AA5CDNPFLVQw5Q@mail.gmail.com","threadId":"38234","inReplyTo":"CAA8EjDRsw6o8T1sS=rpSt_+KaKt9QnONCmF23yHDdKhgKHcdww@mail.gmail.com","subject":"Re: mangled file names in git checkout-index --temp output when run in repo subdirectory","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2014-12-23T23:27:18Z","receivedAt":"2014-12-23T23:27:18Z","isPatch":false,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Dec 23, 2014 at 11:36 AM, Russ Cox <rsc@golang.org> wrote:\n> I am using git checkout-index --temp to obtain copies of files from\n> the index, but it does not always print valid file names unless run\n> from the repository root.\n>\n> git checkout-index --temp prints names of files in the index\n> interpreted relative to the current directory below the repository\n> root.\n>\n> If you have a git repo in /tmp/gitbug, you are in /tmp/gitbug/dir1,\n> and you run git checkout-index --temp /tmp/gitbug/dir1/file1, the file\n> listing prints just \"file1\". So far so good.\n>\n> However, this file name shortening appears to assume that all file\n> names being printed will be within the subtree rooted at the current\n> directory, and it just skips over the first N characters in the name,\n> where N is the length of the current directory name relative to the\n> repo root (in the above example, N = len(\"dir1/\") = 5).\n\nIndeed, although the \"checkout\" functionality of checkout-index\nproperly handles relative paths above the current directory, the code\nwhich prints them doesn't. I'm working up a patch.\n"}]}