commit - 6f59b577b065bf3d4ea7715e91c9ffe910ca3a36
commit + 870ddae51fc1a153927d6bcaf1324ae00d6b4af4
blob - 10dd64ab2adb789373fe5e625fb09f592f6ccd70
blob + 1724c65c05bba46e05b9ad4ee3bbfce7ad7b72fd
--- lib/diff.c
+++ lib/diff.c
}
static const struct got_error *
-diff_kind_mismatch(struct got_object_id *id1, struct got_object_id *id2,
+diff_kind_mismatch(struct got_tree_entry *te1, struct got_tree_entry *te2,
+ FILE *f1, FILE *f2, int fd1, int fd2,
const char *label1, const char *label2, struct got_repository *repo,
- got_diff_blob_cb cb, void *cb_arg)
+ got_diff_blob_cb cb, void *cb_arg, int diff_content)
{
- /* XXX TODO */
+ const struct got_error *err = NULL;
+
+ /*
+ * Handle files changing into directories and vice-versa.
+ * Disregard edge cases with FIFOs, device nodes, etc for now.
+ */
+ if (!S_ISDIR(te1->mode) && S_ISDIR(te2->mode)) {
+ if (S_ISREG(te1->mode)) {
+ if (diff_content) {
+ err = diff_deleted_blob(&te1->id, f1, fd1,
+ f2, label1, te1->mode, repo, cb, cb_arg);
+ } else {
+ err = cb(cb_arg, NULL, NULL, NULL, NULL,
+ &te1->id, NULL, label1, NULL,
+ te1->mode, 0, repo);
+ }
+ if (err)
+ return err;
+ }
+ return diff_added_tree(&te2->id, f1, f2, fd2, label2,
+ repo, cb, cb_arg, diff_content);
+ } else if (S_ISDIR(te1->mode) && !S_ISDIR(te2->mode)) {
+ err = diff_deleted_tree(&te1->id, f1, fd1, f2,
+ label1, repo, cb, cb_arg, diff_content);
+ if (err)
+ return err;
+ if (S_ISREG(te2->mode)) {
+ if (diff_content) {
+ err = diff_added_blob(&te2->id, f1, f2, fd2,
+ label2, te2->mode, repo, cb, cb_arg);
+ } else {
+ err = cb(cb_arg, NULL, NULL, NULL, NULL, NULL,
+ &te2->id, NULL, label2, 0, te2->mode, repo);
+ }
+ if (err)
+ return err;
+ }
+ }
+
return NULL;
}
if (id_match)
return NULL;
- return diff_kind_mismatch(&te1->id, &te2->id, label1, label2, repo,
- cb, cb_arg);
+ return diff_kind_mismatch(te1, te2, f1, f2, fd1, fd2,
+ label1, label2, repo, cb, cb_arg, diff_content);
}
static const struct got_error *
blob - 7e0eedeb0291727fa2b2651ff4c8911df3aaf27b
blob + 53c5d1f6202fffc4bed181b63da76e86641ad5e9
--- regress/cmdline/common.sh
+++ regress/cmdline/common.sh
(cd $repo && git rm -q "$@")
}
+git_rmdir()
+{
+ local repo="$1"
+ shift
+ (cd $repo && git rm -q -r "$@")
+}
+
git_show_head()
{
local repo="$1"
blob - fe9c943bc19d1b0b6905788633041f88ae69282b
blob + 74c5c3277048c41e7d957d274e2fd708fbd7e022
--- regress/cmdline/diff.sh
+++ regress/cmdline/diff.sh
test_diff_file_to_dir() {
local testroot=`test_init diff_file_to_dir`
local commit_id0=`git_show_head $testroot/repo`
+ local alpha_blobid=`get_blob_id $testroot/repo "" alpha`
got checkout $testroot/repo $testroot/wt > /dev/null
ret=$?
(cd $testroot/repo && git add alpha/eta)
git_commit $testroot/repo -m "changed alpha into directory"
local commit_id1=`git_show_head $testroot/repo`
+ local alpha_eta_blobid=`get_blob_id $testroot/repo alpha eta`
- echo "diff $commit_id0 $commit_id1" > $testroot/stdout.expected
- echo "commit - $commit_id0" >> $testroot/stdout.expected
- echo "commit + $commit_id1" >> $testroot/stdout.expected
+ cat <<EOF >$testroot/stdout.expected
+diff $commit_id0 $commit_id1
+commit - $commit_id0
+commit + $commit_id1
+blob - $alpha_blobid (mode 644)
+blob + /dev/null
+--- alpha
++++ /dev/null
+@@ -1 +0,0 @@
+-alpha
+blob - /dev/null
+blob + $alpha_eta_blobid (mode 644)
+--- /dev/null
++++ alpha/eta
+@@ -0,0 +1 @@
++eta
+EOF
got diff -r $testroot/repo $commit_id0 $commit_id1 > $testroot/stdout
- # Diff should not be empty
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
cmp -s $testroot/stdout.expected $testroot/stdout
ret=$?
- if [ $ret -eq 0 ]; then
- ret="xfail file to directory"
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ local author_time=`git_show_author_time $testroot/repo`
+ d=`date -u -r $author_time +"%a %b %e %X %Y UTC"`
+ cat <<EOF >$testroot/stdout.expected
+-----------------------------------------------
+commit $commit_id1 (master)
+from: $GOT_AUTHOR
+date: $d
+
+ changed alpha into directory
+
+ D alpha
+ A alpha/eta
+
+EOF
+
+ got log -P -r $testroot/repo -l1 -c $commit_id1 > $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
fi
+
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
test_done "$testroot" "$ret"
}
+test_diff_dir_to_file() {
+ local testroot=`test_init diff_file_to_dir`
+ local commit_id0=`git_show_head $testroot/repo`
+ local epsilon_zeta_blobid=`get_blob_id $testroot/repo epsilon zeta`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ git_rmdir $testroot/repo epsilon
+ echo epsilon > $testroot/repo/epsilon
+ (cd $testroot/repo && git add epsilon)
+ git_commit $testroot/repo -m "changed epsilon into file"
+ local commit_id1=`git_show_head $testroot/repo`
+ local epsilon_blobid=`get_blob_id $testroot/repo "" epsilon`
+
+ cat <<EOF >$testroot/stdout.expected
+diff $commit_id0 $commit_id1
+commit - $commit_id0
+commit + $commit_id1
+blob - $epsilon_zeta_blobid (mode 644)
+blob + /dev/null
+--- epsilon/zeta
++++ /dev/null
+@@ -1 +0,0 @@
+-zeta
+blob - /dev/null
+blob + $epsilon_blobid (mode 644)
+--- /dev/null
++++ epsilon
+@@ -0,0 +1 @@
++epsilon
+EOF
+ got diff -r $testroot/repo $commit_id0 $commit_id1 > $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ local author_time=`git_show_author_time $testroot/repo`
+ d=`date -u -r $author_time +"%a %b %e %X %Y UTC"`
+ cat <<EOF >$testroot/stdout.expected
+-----------------------------------------------
+commit $commit_id1 (master)
+from: $GOT_AUTHOR
+date: $d
+
+ changed epsilon into file
+
+ D epsilon/zeta
+ A epsilon
+
+EOF
+
+ got log -P -r $testroot/repo -l1 -c $commit_id1 > $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
test_parseargs "$@"
run_test test_diff_basic
run_test test_diff_shows_conflict
run_test test_diff_commit_diffstat
run_test test_diff_worktree_diffstat
run_test test_diff_file_to_dir
+run_test test_diff_dir_to_file