Download raw body.
fix 'got update' with added + obstructed file
When 'got update' tries to add a new file to the work tree and this
file is obstructed by a directory on disk, the update fails like this:
$ got update
? new
got: new: Is a directory
$
And the work tree is not updated. The above update with error can be
run over and over and won't proceed until the directory is removed.
The problem here is simply that the update as a whole should succeed,
not stop on one such file even though there might be more files to update.
With the patch below this situation is properly detected as an obstruction
and the update succeeds:
$ got update
~ new
Updated to refs/heads/master: c1f85b4938dc4c668a88f13df2b98a520fc077cc
File paths obstructed by a non-regular file: 1
$
Regardless, the file 'new' will not be added to the work tree until the
directory is moved and 'got update' is run again.
And I am extending a corresponding test to cover this issue.
ok?
diff f365d76274ee1ae2b57225686a0733176fc4bfb2 /home/stsp/src/got
blob - f5bc677438d23ddca778382674edef04e09cb939
file + lib/worktree.c
--- lib/worktree.c
+++ lib/worktree.c
@@ -1942,8 +1942,20 @@ update_blob(struct got_worktree *worktree,
if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE)
sb.st_mode = got_fileindex_perms_to_st(ie);
} else {
- sb.st_mode = GOT_DEFAULT_FILE_MODE;
- status = GOT_STATUS_UNVERSIONED;
+ if (stat(ondisk_path, &sb) == -1) {
+ if (errno != ENOENT) {
+ err = got_error_from_errno2("stat",
+ ondisk_path);
+ goto done;
+ }
+ sb.st_mode = GOT_DEFAULT_FILE_MODE;
+ status = GOT_STATUS_UNVERSIONED;
+ } else {
+ if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))
+ status = GOT_STATUS_UNVERSIONED;
+ else
+ status = GOT_STATUS_OBSTRUCTED;
+ }
}
if (status == GOT_STATUS_OBSTRUCTED) {
blob - cae602420f097ed69b049e9fffb3fc46510d2de5
file + regress/cmdline/update.sh
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
@@ -2588,6 +2588,8 @@ test_update_file_skipped_due_to_obstruction() {
blob_id0=`get_blob_id $testroot/repo "" beta`
echo "changed beta" > $testroot/repo/beta
+ echo "new file" > $testroot/repo/new
+ (cd $testroot/repo && git add new)
git_commit $testroot/repo -m "changed beta"
local commit_id1=`git_show_head $testroot/repo`
blob_id1=`get_blob_id $testroot/repo "" beta`
@@ -2617,14 +2619,22 @@ test_update_file_skipped_due_to_obstruction() {
rm $testroot/wt/beta
mkdir -p $testroot/wt/beta/psi
+ mkdir -p $testroot/wt/new
- # update to the latest commit; this skips beta
+ # update to the latest commit; this skips beta and the new file
(cd $testroot/wt && got update > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "update failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
echo "~ beta" > $testroot/stdout.expected
+ echo "~ new" >> $testroot/stdout.expected
echo "Updated to refs/heads/master: $commit_id1" \
>> $testroot/stdout.expected
- echo "File paths obstructed by a non-regular file: 1" \
+ echo "File paths obstructed by a non-regular file: 2" \
>> $testroot/stdout.expected
cmp -s $testroot/stdout.expected $testroot/stdout
ret="$?"
@@ -2656,8 +2666,11 @@ test_update_file_skipped_due_to_obstruction() {
# updating to the latest commit should now update beta
(cd $testroot/wt && got update > $testroot/stdout)
echo "! beta" > $testroot/stdout.expected
+ echo "~ new" >> $testroot/stdout.expected
echo "Updated to refs/heads/master: $commit_id1" \
>> $testroot/stdout.expected
+ echo "File paths obstructed by a non-regular file: 1" \
+ >> $testroot/stdout.expected
cmp -s $testroot/stdout.expected $testroot/stdout
ret="$?"
if [ "$ret" != "0" ]; then
fix 'got update' with added + obstructed file