commit 24f136e0f955e179395f9d081b45fbea32f02325 from: Stefan Sperling via: Thomas Adam date: Sat Nov 20 22:47:47 2021 UTC preverse binary files during updates and merges commit - 1ea7ccc6f361b1b07c3f3c301b033ea50b17cf54 commit + 24f136e0f955e179395f9d081b45fbea32f02325 blob - 63f4fa74abf23dd8211a43333dd555ccf57acd6d blob + c3199cc5662e657eb2b2bc0279e30f8a26837ed8 --- include/got_error.h +++ include/got_error.h @@ -163,6 +163,7 @@ #define GOT_ERR_MERGE_COMMIT_OUT_OF_DATE 143 #define GOT_ERR_MERGE_BUSY 144 #define GOT_ERR_MERGE_PATH 145 +#define GOT_ERR_FILE_BINARY 146 static const struct got_error { int code; @@ -339,6 +340,7 @@ static const struct got_error { "work tree and must be continued or aborted first" }, { GOT_ERR_MERGE_PATH, "cannot merge branch which contains " "changes outside of this work tree's path prefix" }, + { GOT_ERR_FILE_BINARY, "found a binary file instead of text" }, }; /* blob - 83a6b8e3a481fb9bcce5cdacd3e06b5295a7bfeb blob + b331de0ba24a050f33d26768b66e98fe04a3500d --- lib/diff3.c +++ lib/diff3.c @@ -222,9 +222,19 @@ diffreg(BUF **d, const char *path1, const char *path2, if (err) goto done; - err = got_diffreg(&diffreg_result, f1, f2, diff_algo, 0, 1); + err = got_diffreg(&diffreg_result, f1, f2, diff_algo, 0, 0); if (err) goto done; + + if (diffreg_result) { + struct diff_result *diff_result = diffreg_result->result; + int atomizer_flags = (diff_result->left->atomizer_flags | + diff_result->right->atomizer_flags); + if ((atomizer_flags & DIFF_ATOMIZER_FOUND_BINARY_DATA)) { + err = got_error(GOT_ERR_FILE_BINARY); + goto done; + } + } err = got_diffreg_output(NULL, NULL, diffreg_result, 1, 1, "", "", GOT_DIFF_OUTPUT_EDSCRIPT, 0, outfile); blob - f9980ca34fe6e0e1c431bd61173a4af6fed70df8 blob + 5ff80e7c12f60902a2ac09403e9f24c9b77cc98e --- lib/worktree.c +++ lib/worktree.c @@ -472,6 +472,159 @@ check_files_equal(int *same, FILE *f1, FILE *f2) return got_ferror(f2, GOT_ERR_IO); return check_file_contents_equal(same, f1, f2); +} + +static const struct got_error * +copy_file_to_fd(off_t *outsize, FILE *f, int outfd) +{ + uint8_t fbuf[65536]; + size_t flen; + ssize_t outlen; + + *outsize = 0; + + if (fseek(f, 0L, SEEK_SET) == -1) + return got_ferror(f, GOT_ERR_IO); + + for (;;) { + flen = fread(fbuf, 1, sizeof(fbuf), f); + if (flen == 0) { + if (ferror(f)) + return got_error_from_errno("fread"); + if (feof(f)) + break; + } + outlen = write(outfd, fbuf, flen); + if (outlen == -1) + return got_error_from_errno("write"); + if (outlen != flen) + return got_error(GOT_ERR_IO); + *outsize += outlen; + } + + return NULL; +} + +static const struct got_error * +merge_binary_file(int *overlapcnt, int merged_fd, + FILE *f_deriv, FILE *f_orig, FILE *f_deriv2, + const char *label_deriv, const char *label_orig, const char *label_deriv2, + const char *ondisk_path) +{ + const struct got_error *err = NULL; + int same_content, changed_deriv, changed_deriv2; + int fd_orig = -1, fd_deriv = -1, fd_deriv2 = -1; + off_t size_orig = 0, size_deriv = 0, size_deriv2 = 0; + char *path_orig = NULL, *path_deriv = NULL, *path_deriv2 = NULL; + char *base_path_orig = NULL, *base_path_deriv = NULL; + char *base_path_deriv2 = NULL; + + *overlapcnt = 0; + + err = check_files_equal(&same_content, f_deriv, f_deriv2); + if (err) + return err; + + if (same_content) + return copy_file_to_fd(&size_deriv, f_deriv, merged_fd); + + err = check_files_equal(&same_content, f_deriv, f_orig); + if (err) + return err; + changed_deriv = !same_content; + err = check_files_equal(&same_content, f_deriv2, f_orig); + if (err) + return err; + changed_deriv2 = !same_content; + + if (changed_deriv && changed_deriv2) { + *overlapcnt = 1; + if (asprintf(&base_path_orig, "%s-orig", ondisk_path) == -1) { + err = got_error_from_errno("asprintf"); + goto done; + } + if (asprintf(&base_path_deriv, "%s-1", ondisk_path) == -1) { + err = got_error_from_errno("asprintf"); + goto done; + } + if (asprintf(&base_path_deriv2, "%s-2", ondisk_path) == -1) { + err = got_error_from_errno("asprintf"); + goto done; + } + err = got_opentemp_named_fd(&path_orig, &fd_orig, + base_path_orig); + if (err) + goto done; + err = got_opentemp_named_fd(&path_deriv, &fd_deriv, + base_path_deriv); + if (err) + goto done; + err = got_opentemp_named_fd(&path_deriv2, &fd_deriv2, + base_path_deriv2); + if (err) + goto done; + err = copy_file_to_fd(&size_orig, f_orig, fd_orig); + if (err) + goto done; + err = copy_file_to_fd(&size_deriv, f_deriv, fd_deriv); + if (err) + goto done; + err = copy_file_to_fd(&size_deriv2, f_deriv2, fd_deriv2); + if (err) + goto done; + if (dprintf(merged_fd, "Binary files differ and cannot be " + "merged automatically:\n") < 0) { + err = got_error_from_errno("dprintf"); + goto done; + } + if (dprintf(merged_fd, "%s%s%s\nfile %s\n", + GOT_DIFF_CONFLICT_MARKER_BEGIN, + label_deriv ? " " : "", + label_deriv ? label_deriv : "", + path_deriv) < 0) { + err = got_error_from_errno("dprintf"); + goto done; + } + if (size_orig > 0) { + if (dprintf(merged_fd, "%s%s%s\nfile %s\n", + GOT_DIFF_CONFLICT_MARKER_ORIG, + label_orig ? " " : "", + label_orig ? label_orig : "", + path_orig) < 0) { + err = got_error_from_errno("dprintf"); + goto done; + } + } + if (dprintf(merged_fd, "%s\nfile %s\n%s%s%s\n", + GOT_DIFF_CONFLICT_MARKER_SEP, + path_deriv2, + GOT_DIFF_CONFLICT_MARKER_END, + label_deriv2 ? " " : "", + label_deriv2 ? label_deriv2 : "") < 0) { + err = got_error_from_errno("dprintf"); + goto done; + } + } else if (changed_deriv) + err = copy_file_to_fd(&size_deriv, f_deriv, merged_fd); + else if (changed_deriv2) + err = copy_file_to_fd(&size_deriv2, f_deriv2, merged_fd); +done: + if (size_orig == 0 && path_orig && unlink(path_orig) == -1 && + err == NULL) + err = got_error_from_errno2("unlink", path_orig); + if (fd_orig != -1 && close(fd_orig) == -1 && err == NULL) + err = got_error_from_errno2("close", path_orig); + if (fd_deriv != -1 && close(fd_deriv) == -1 && err == NULL) + err = got_error_from_errno2("close", path_deriv); + if (fd_deriv2 != -1 && close(fd_deriv2) == -1 && err == NULL) + err = got_error_from_errno2("close", path_deriv2); + free(path_orig); + free(path_deriv); + free(path_deriv2); + free(base_path_orig); + free(base_path_deriv); + free(base_path_deriv2); + return err; } /* @@ -513,8 +666,15 @@ merge_file(int *local_changes_subsumed, struct got_wor err = got_merge_diff3(&overlapcnt, merged_fd, f_deriv, f_orig, f_deriv2, label_deriv, label_orig, label_deriv2, diff_algo); - if (err) - goto done; + if (err) { + if (err->code != GOT_ERR_FILE_BINARY) + goto done; + err = merge_binary_file(&overlapcnt, merged_fd, f_deriv, + f_orig, f_deriv2, label_deriv, label_orig, label_deriv2, + ondisk_path); + if (err) + goto done; + } err = (*progress_cb)(progress_arg, overlapcnt > 0 ? GOT_STATUS_CONFLICT : GOT_STATUS_MERGE, path); blob - bc0e291705739106b854b8c5ee70abde8acb3b11 blob + cbb7c12856b31d06f88b3a9e169bb1eb0d762373 --- regress/cmdline/cherrypick.sh +++ regress/cmdline/cherrypick.sh @@ -1460,6 +1460,233 @@ test_cherrypick_dot_on_a_line_by_itself() { diff -u $testroot/content.expected $testroot/content fi test_done "$testroot" "$ret" +} + +test_cherrypick_binary_file() { + local testroot=`test_init cherrypick_binary_file` + local commit_id0=`git_show_head $testroot/repo` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/ls $testroot/wt/foo + chmod 755 $testroot/wt/foo + (cd $testroot/wt && got add foo >/dev/null) + (cd $testroot/wt && got commit -m 'add binary file' > /dev/null) + local commit_id1=`git_show_head $testroot/repo` + + cp /bin/cat $testroot/wt/foo + chmod 755 $testroot/wt/foo + (cd $testroot/wt && got commit -m 'change binary file' > /dev/null) + local commit_id2=`git_show_head $testroot/repo` + + cp /bin/cp $testroot/wt/foo + chmod 755 $testroot/wt/foo + (cd $testroot/wt && got commit -m 'change binary file' > /dev/null) + local commit_id3=`git_show_head $testroot/repo` + + (cd $testroot/wt && got rm foo >/dev/null) + (cd $testroot/wt && got commit -m 'remove binary file' > /dev/null) + local commit_id4=`git_show_head $testroot/repo` + + # backdate the work tree to make it usable for cherry-picking + (cd $testroot/wt && got up -c $commit_id0 > /dev/null) + + # cherry-pick addition of a binary file + (cd $testroot/wt && got cy $commit_id1 > $testroot/stdout) + + echo "A foo" > $testroot/stdout.expected + echo "Merged commit $commit_id1" >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/ls $testroot/content.expected + chmod 755 $testroot/content.expected + cp $testroot/wt/foo $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # cherry-pick modification of a binary file + (cd $testroot/wt && got cy $commit_id2 > $testroot/stdout) + + echo "G foo" > $testroot/stdout.expected + echo "Merged commit $commit_id2" >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/cat $testroot/content.expected + chmod 755 $testroot/content.expected + cp $testroot/wt/foo $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # cherry-pick conflicting addition of a binary file + (cd $testroot/wt && got cy $commit_id1 > $testroot/stdout) + + echo "C foo" > $testroot/stdout.expected + echo "Merged commit $commit_id1" >> $testroot/stdout.expected + echo "Files with new merge conflicts: 1" >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "Binary files differ and cannot be merged automatically:" \ + > $testroot/content.expected + echo "<<<<<<< merged change: commit $commit_id1" \ + >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-1-* >> $testroot/content.expected + echo '=======' >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-2-* >> $testroot/content.expected + echo '>>>>>>>' >> $testroot/content.expected + cp $testroot/wt/foo $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # revert local changes to allow further testing + (cd $testroot/wt && got revert -R . >/dev/null) + + (cd $testroot/wt && got status > $testroot/stdout) + echo '? foo' > $testroot/stdout.expected + echo -n '? ' >> $testroot/stdout.expected + (cd $testroot/wt && ls foo-1-* >> $testroot/stdout.expected) + echo -n '? ' >> $testroot/stdout.expected + (cd $testroot/wt && ls foo-2-* >> $testroot/stdout.expected) + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + # tidy up + rm $testroot/wt/foo $testroot/wt/foo-1-* $testroot/wt/foo-2-* + (cd $testroot/wt && got up -c $commit_id1 > /dev/null) + + # cherry-pick conflicting modification of a binary file + (cd $testroot/wt && got cy $commit_id3 > $testroot/stdout) + + echo "C foo" > $testroot/stdout.expected + echo "Merged commit $commit_id3" >> $testroot/stdout.expected + echo "Files with new merge conflicts: 1" >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "Binary files differ and cannot be merged automatically:" \ + > $testroot/content.expected + echo '<<<<<<<' >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-1-* >> $testroot/content.expected + echo "||||||| 3-way merge base: commit $commit_id2" \ + >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-orig-* >> $testroot/content.expected + echo '=======' >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-2-* >> $testroot/content.expected + echo ">>>>>>> merged change: commit $commit_id3" \ + >> $testroot/content.expected + cp $testroot/wt/foo $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/ls $testroot/content.expected + chmod 755 $testroot/content.expected + cat $testroot/wt/foo-1-* > $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/cp $testroot/content.expected + chmod 755 $testroot/content.expected + cat $testroot/wt/foo-2-* > $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # revert local changes to allow further testing + (cd $testroot/wt && got revert -R . > /dev/null) + rm $testroot/wt/foo-1-* + rm $testroot/wt/foo-2-* + (cd $testroot/wt && got up -c $commit_id3 > /dev/null) + + # cherry-pick deletion of a binary file + (cd $testroot/wt && got cy $commit_id4 > $testroot/stdout) + + echo "D foo" > $testroot/stdout.expected + echo "Merged commit $commit_id4" >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + if [ -e $testroot/wt/foo ]; then + echo "removed file foo still exists on disk" >&2 + test_done "$testroot" "1" + return 1 + fi + test_done "$testroot" "0" } test_parseargs "$@" @@ -1478,3 +1705,4 @@ run_test test_cherrypick_conflict_no_eol2 run_test test_cherrypick_unrelated_changes run_test test_cherrypick_same_branch run_test test_cherrypick_dot_on_a_line_by_itself +run_test test_cherrypick_binary_file blob - 5d6ef1de516952ff8423025457c87352fb8ed55e blob + 5de6e8cfdcc437961bf4810e7405115e6e685f68 --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -2741,6 +2741,267 @@ test_update_quiet() { diff -u $testroot/content.expected $testroot/content fi test_done "$testroot" "$ret" +} + +test_update_binary_file() { + local testroot=`test_init update_binary_file` + local commit_id0=`git_show_head $testroot/repo` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/ls $testroot/wt/foo + chmod 755 $testroot/wt/foo + (cd $testroot/wt && got add foo >/dev/null) + (cd $testroot/wt && got commit -m 'add binary file' > /dev/null) + local commit_id1=`git_show_head $testroot/repo` + + cp /bin/cat $testroot/wt/foo + chmod 755 $testroot/wt/foo + (cd $testroot/wt && got commit -m 'change binary file' > /dev/null) + local commit_id2=`git_show_head $testroot/repo` + + cp /bin/cp $testroot/wt/foo + chmod 755 $testroot/wt/foo + (cd $testroot/wt && got commit -m 'change binary file' > /dev/null) + local commit_id3=`git_show_head $testroot/repo` + + (cd $testroot/wt && got rm foo >/dev/null) + (cd $testroot/wt && got commit -m 'remove binary file' > /dev/null) + local commit_id4=`git_show_head $testroot/repo` + + # backdate the work tree to make it usable for updating + (cd $testroot/wt && got up -c $commit_id0 > /dev/null) + + # update which adds a binary file + (cd $testroot/wt && got up -c $commit_id1 > $testroot/stdout) + + echo "A foo" > $testroot/stdout.expected + echo -n "Updated to refs/heads/master: $commit_id1" \ + >> $testroot/stdout.expected + echo >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/ls $testroot/content.expected + chmod 755 $testroot/content.expected + cat $testroot/wt/foo > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # update which adds a conflicting binary file + (cd $testroot/wt && got up -c $commit_id0 > /dev/null) + cp /bin/cat $testroot/wt/foo + chmod 755 $testroot/wt/foo + (cd $testroot/wt && got add foo > /dev/null) + (cd $testroot/wt && got up -c $commit_id1 > $testroot/stdout) + + echo "C foo" > $testroot/stdout.expected + echo "Updated to refs/heads/master: $commit_id1" \ + >> $testroot/stdout.expected + echo "Files with new merge conflicts: 1" >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "Binary files differ and cannot be merged automatically:" \ + > $testroot/content.expected + echo "<<<<<<< merged change: commit $commit_id1" \ + >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-1-* >> $testroot/content.expected + echo '=======' >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-2-* >> $testroot/content.expected + echo ">>>>>>>" >> $testroot/content.expected + cat $testroot/wt/foo > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/ls $testroot/content.expected + chmod 755 $testroot/content.expected + cat $testroot/wt/foo-1-* > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/cat $testroot/content.expected + chmod 755 $testroot/content.expected + cat $testroot/wt/foo-2-* > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # tidy up + (cd $testroot/wt && got revert -R . >/dev/null) + rm $testroot/wt/foo-1-* $testroot/wt/foo-2-* + (cd $testroot/wt && got up -c $commit_id1 > /dev/null) + + # update which changes a binary file + (cd $testroot/wt && got up -c $commit_id2 > $testroot/stdout) + + echo "U foo" > $testroot/stdout.expected + echo -n "Updated to refs/heads/master: $commit_id2" \ + >> $testroot/stdout.expected + echo >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/cat $testroot/content.expected + chmod 755 $testroot/content.expected + cat $testroot/wt/foo > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # update which changes a locally modified binary file + cp /bin/ls $testroot/wt/foo + chmod 755 $testroot/wt/foo + (cd $testroot/wt && got up -c $commit_id3 > $testroot/stdout) + + echo "C foo" > $testroot/stdout.expected + echo -n "Updated to refs/heads/master: $commit_id3" \ + >> $testroot/stdout.expected + echo >> $testroot/stdout.expected + echo "Files with new merge conflicts: 1" >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "Binary files differ and cannot be merged automatically:" \ + > $testroot/content.expected + echo "<<<<<<< merged change: commit $commit_id3" \ + >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-1-* >> $testroot/content.expected + echo "||||||| 3-way merge base: commit $commit_id2" \ + >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-orig-* >> $testroot/content.expected + echo '=======' >> $testroot/content.expected + echo -n "file " >> $testroot/content.expected + ls $testroot/wt/foo-2-* >> $testroot/content.expected + echo ">>>>>>>" >> $testroot/content.expected + cat $testroot/wt/foo > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/cp $testroot/content.expected + chmod 755 $testroot/content.expected + cp $testroot/wt/foo-1-* $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + cp /bin/ls $testroot/content.expected + chmod 755 $testroot/content.expected + cp $testroot/wt/foo-2-* $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/wt && got status > $testroot/stdout) + echo 'C foo' > $testroot/stdout.expected + echo -n '? ' >> $testroot/stdout.expected + (cd $testroot/wt && ls foo-1-* >> $testroot/stdout.expected) + echo -n '? ' >> $testroot/stdout.expected + (cd $testroot/wt && ls foo-2-* >> $testroot/stdout.expected) + echo -n '? ' >> $testroot/stdout.expected + (cd $testroot/wt && ls foo-orig-* >> $testroot/stdout.expected) + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + # tidy up + (cd $testroot/wt && got revert -R . > /dev/null) + rm $testroot/wt/foo-orig-* $testroot/wt/foo-1-* $testroot/wt/foo-2-* + + # update which deletes a binary file + (cd $testroot/wt && got up -c $commit_id4 > $testroot/stdout) + echo "D foo" > $testroot/stdout.expected + echo -n "Updated to refs/heads/master: $commit_id4" \ + >> $testroot/stdout.expected + echo >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + fi + + if [ -e $testroot/wt/foo ]; then + echo "removed file foo still exists on disk" >&2 + test_done "$testroot" "1" + return 1 + fi + test_done "$testroot" "0" } test_parseargs "$@" @@ -2786,3 +3047,4 @@ run_test test_update_single_file run_test test_update_file_skipped_due_to_conflict run_test test_update_file_skipped_due_to_obstruction run_test test_update_quiet +run_test test_update_binary_file