I am using git checkout-index --temp to obtain copies of files from
the index, but it does not always print valid file names unless run
from the repository root.

git checkout-index --temp prints names of files in the index
interpreted relative to the current directory below the repository
root.

If you have a git repo in /tmp/gitbug, you are in /tmp/gitbug/dir1,
and you run git checkout-index --temp /tmp/gitbug/dir1/file1, the file
listing prints just "file1". So far so good.

However, this file name shortening appears to assume that all file
names being printed will be within the subtree rooted at the current
directory, and it just skips over the first N characters in the name,
where N is the length of the current directory name relative to the
repo root (in the above example, N = len("dir1/") = 5).

That is, if you have a git repo in /tmp/gitbug, you are in
/tmp/gitbug/dir1, and you run git checkout-index --temp
/tmp/gitbug/longdir2/file2, the file listing prints "ir2/file2", not
"../longdir2/file2". If you arrange things just right you can get ""
as the file name. I've never seen arbitrary binary garbage, so
(without inspecting the source code) it does appear that something is
keeping the printed string pointer within the original string, even in
the case when N > the length of the string being printed.

I have seen this in a few different versions of Git. I just downloaded
and built Git 2.2.1 from sources and confirmed that it has the buggy
behavior. Below is a shell script demonstrating the bug and an
annotated transcript of the execution of the script on my system.

The workaround seems to be that, until the bug is fixed, git
checkout-index must be run in the repository root.

Thanks.
Russ

% cat /tmp/gitbugdemo
#!/bin/bash

git=${1:-git}
set -e
rm -rf /tmp/gitbug
mkdir /tmp/gitbug
cd /tmp/gitbug
$git init .
mkdir dir1 longdir2 veryveryverylongdir3
echo hello world >dir1/file1
echo hello world >longdir2/file2
echo hello world >veryveryverylongdir3/file3
files="/tmp/gitbug/dir1/file1 /tmp/gitbug/longdir2/file2
/tmp/gitbug/veryveryverylongdir3/file3"
relfiles=$(echo $files | sed 's;/tmp/gitbug/;../;g')
rootfiles=$(echo $relfiles | sed 's;\.\./;;g')
set -x
$git version
cd /tmp/gitbug
$git add .
$git checkout-index --temp $files
$git checkout-index --temp $rootfiles
cd /tmp/gitbug/dir1
$git checkout-index --temp $files
$git checkout-index --temp $relfiles
cd /tmp/gitbug/longdir2
$git checkout-index --temp $files
$git checkout-index --temp $relfiles
cd /tmp/gitbug/veryveryverylongdir3
$git checkout-index --temp $files
$git checkout-index --temp $relfiles
%

% /tmp/gitbugdemo git2.2.1
warning: templates not found /usr/local/share/git-core/templates
Initialized empty Git repository in /private/tmp/gitbug/.git/
+ git2.2.1 version
git version 2.2.1
+ cd /tmp/gitbug
+ git2.2.1 add .

### In root directory, all is well.
+ git2.2.1 checkout-index --temp /tmp/gitbug/dir1/file1
/tmp/gitbug/longdir2/file2 /tmp/gitbug/veryveryverylongdir3/file3
.merge_file_TRqU2e dir1/file1
.merge_file_7uajP4 longdir2/file2
.merge_file_L4OD1U veryveryverylongdir3/file3
+ git2.2.1 checkout-index --temp dir1/file1 longdir2/file2
veryveryverylongdir3/file3
.merge_file_77EMra dir1/file1
.merge_file_DpKgMu longdir2/file2
.merge_file_w8yfxA veryveryverylongdir3/file3

### In dir1/, loses first 5 chars of file paths outside current directory.
### Both absolute and relative command-line arguments trigger bug.
+ cd /tmp/gitbug/dir1
+ git2.2.1 checkout-index --temp /tmp/gitbug/dir1/file1
/tmp/gitbug/longdir2/file2 /tmp/gitbug/veryveryverylongdir3/file3
.merge_file_2SwQmt file1
.merge_file_g0rOvr ir2/file2
.merge_file_3uDW54 eryverylongdir3/file3
+ git2.2.1 checkout-index --temp ../dir1/file1 ../longdir2/file2
../veryveryverylongdir3/file3
.merge_file_BwUlNt file1
.merge_file_gQji59 ir2/file2
.merge_file_hNNjc9 eryverylongdir3/file3

### In longdir2/, loses first 9 chars of file paths outside current directory.
### Both absolute and relative command-line arguments trigger bug.
+ cd /tmp/gitbug/longdir2
+ git2.2.1 checkout-index --temp /tmp/gitbug/dir1/file1
/tmp/gitbug/longdir2/file2 /tmp/gitbug/veryveryverylongdir3/file3
.merge_file_ljy0oC 1
.merge_file_ANLgpx file2
.merge_file_1lDbMp erylongdir3/file3
+ git2.2.1 checkout-index --temp ../dir1/file1 ../longdir2/file2
../veryveryverylongdir3/file3
.merge_file_ugqOsC 1
.merge_file_reoXBo file2
.merge_file_p4tQn9 erylongdir3/file3

### In veryveryverylongdir3/, inconsistent truncation of file paths
outside current directory.
### Absolute command-line arguments trigger bug but relative ones do not (!).
+ cd /tmp/gitbug/veryveryverylongdir3
+ git2.2.1 checkout-index --temp /tmp/gitbug/dir1/file1
/tmp/gitbug/longdir2/file2 /tmp/gitbug/veryveryverylongdir3/file3
.merge_file_VvT0uT 1
.merge_file_UfAT1x file2
.merge_file_Fon1Ex file3
+ git2.2.1 checkout-index --temp ../dir1/file1 ../longdir2/file2
../veryveryverylongdir3/file3
.merge_file_YDHkDe ../dir1/file1
.merge_file_F7M27m ../longdir2/file2
.merge_file_ZkkXnQ file3
%
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to