commit 6d054bb9e38d22dc37c9141e75db6b8b9cd7ca9b from: Mark Jamsek via: Thomas Adam date: Fri Sep 23 07:52:52 2022 UTC show file mode for new added files in work tree diffs Make work tree diffs of local changes on disk display the file mode of new added files like other versions of `got diff` currently do. ok stsp@ commit - 790ca73c1011a3aedd266ed382a84bd9a5094816 commit + 6d054bb9e38d22dc37c9141e75db6b8b9cd7ca9b blob - 0ef1bde429a115ad0f96ae4adcaedfd38f7704f0 blob + aa4a411ffcd6b1548c7dd705448a655602514913 --- got/got.c +++ got/got.c @@ -4717,7 +4717,9 @@ print_diff(void *arg, unsigned char status, unsigned c char *abspath = NULL, *label1 = NULL; struct stat sb; off_t size1 = 0; - int f2_exists = 1; + int f2_exists = 0; + + memset(&sb, 0, sizeof(sb)); if (a->diff_staged) { if (staged_status != GOT_STATUS_MODIFY && @@ -4850,8 +4852,8 @@ print_diff(void *arg, unsigned char status, unsigned c goto done; } } - if (fstat(fd, &sb) == -1) { - err = got_error_from_errno2("fstat", abspath); + if (fstatat(fd, abspath, &sb, AT_SYMLINK_NOFOLLOW) == -1) { + err = got_error_from_errno2("fstatat", abspath); goto done; } f2 = fdopen(fd, "r"); @@ -4860,9 +4862,7 @@ print_diff(void *arg, unsigned char status, unsigned c goto done; } fd = -1; - } else { - sb.st_size = 0; - f2_exists = 0; + f2_exists = 1; } if (blob1) { @@ -4873,8 +4873,8 @@ print_diff(void *arg, unsigned char status, unsigned c } err = got_diff_blob_file(blob1, a->f1, size1, label1, f2 ? f2 : a->f2, - f2_exists, sb.st_size, path, GOT_DIFF_ALGORITHM_PATIENCE, - a->diff_context, a->ignore_whitespace, a->force_text_diff, stdout); + f2_exists, &sb, path, GOT_DIFF_ALGORITHM_PATIENCE, a->diff_context, + a->ignore_whitespace, a->force_text_diff, stdout); done: if (fd1 != -1 && close(fd1) == -1 && err == NULL) err = got_error_from_errno("close"); blob - bc4bc871ee90bf32c4fd2bd3b2b452f29d5822a0 blob + 26617c2f087a790bbb5f19d32d57f83246fcb532 --- include/got_diff.h +++ include/got_diff.h @@ -74,7 +74,7 @@ const struct got_error *got_diff_blob(struct got_diff_ * Whitespace differences may optionally be ignored. */ const struct got_error *got_diff_blob_file(struct got_blob_object *, FILE *, - off_t, const char *, FILE *, int, size_t, const char *, + off_t, const char *, FILE *, int, struct stat *, const char *, enum got_diff_algorithm, int, int, int, FILE *); /* blob - 1174cfde7a73bb0a1bb62e32a59759f03e7c66eb blob + 4e77651dc35e2405f41d383a4af005829a48743e --- lib/diff.c +++ lib/diff.c @@ -222,7 +222,7 @@ got_diff_blob(struct got_diff_line **lines, size_t*nli static const struct got_error * diff_blob_file(struct got_diffreg_result **resultp, struct got_blob_object *blob1, FILE *f1, off_t size1, const char *label1, - FILE *f2, int f2_exists, size_t size2, const char *label2, + FILE *f2, int f2_exists, struct stat *sb2, const char *label2, enum got_diff_algorithm diff_algo, int diff_context, int ignore_whitespace, int force_text_diff, FILE *outfile) { @@ -240,9 +240,22 @@ diff_blob_file(struct got_diffreg_result **resultp, idstr1 = "/dev/null"; if (outfile) { + char *mode = NULL; + + /* display file mode for new added files only */ + if (f2_exists && blob1 == NULL) { + int mmask = (S_IRWXU | S_IRWXG | S_IRWXO); + + if (S_ISLNK(sb2->st_mode)) + mmask = S_IFLNK; + if (asprintf(&mode, " (mode %o)", + sb2->st_mode & mmask) == -1) + return got_error_from_errno("asprintf"); + } fprintf(outfile, "blob - %s\n", label1 ? label1 : idstr1); - fprintf(outfile, "file + %s\n", - f2_exists ? label2 : "/dev/null"); + fprintf(outfile, "file + %s%s\n", + f2_exists ? label2 : "/dev/null", mode ? mode : ""); + free(mode); } err = got_diffreg(&result, f1, f2, diff_algo, ignore_whitespace, @@ -273,13 +286,13 @@ done: const struct got_error * got_diff_blob_file(struct got_blob_object *blob1, FILE *f1, off_t size1, - const char *label1, FILE *f2, int f2_exists, size_t size2, + const char *label1, FILE *f2, int f2_exists, struct stat *sb2, const char *label2, enum got_diff_algorithm diff_algo, int diff_context, int ignore_whitespace, int force_text_diff, FILE *outfile) { return diff_blob_file(NULL, blob1, f1, size1, label1, f2, f2_exists, - size2, label2, diff_algo, diff_context, ignore_whitespace, - force_text_diff, outfile ); + sb2, label2, diff_algo, diff_context, ignore_whitespace, + force_text_diff, outfile); } static const struct got_error * blob - 2f96f78243ecc7610927ef5df3b037cb40f8b7d2 blob + 2629b8eb5ac5bf6ef386a08e8ee437b27ef5fd41 --- libexec/got-read-patch/got-read-patch.c +++ libexec/got-read-patch/got-read-patch.c @@ -231,7 +231,8 @@ find_diff(int *done, int *next, FILE *fp, int git, con } else if (!strncmp(line, "+++ ", 4)) { free(new); err = filename(line+4, &new); - } else if (!strncmp(line, "blob + ", 7)) { + } else if (!strncmp(line, "blob + ", 7) || + !strncmp(line, "file + ", 7)) { xbit = filexbit(line); } else if (!git && !strncmp(line, "blob - ", 7)) { free(blob); blob - b9d15eb9d66bfe79b16eb3334fd9628431af7f0d blob + 84e63ab3e0ed94eb29e2fcdd5b9e529332c4f093 --- regress/cmdline/diff.sh +++ regress/cmdline/diff.sh @@ -54,7 +54,7 @@ test_diff_basic() { echo '@@ -1 +0,0 @@' >> $testroot/stdout.expected echo '-beta' >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + new' >> $testroot/stdout.expected + echo 'file + new (mode 644)' >> $testroot/stdout.expected echo '--- /dev/null' >> $testroot/stdout.expected echo '+++ new' >> $testroot/stdout.expected echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected @@ -148,7 +148,7 @@ test_diff_basic() { echo '-zeta' >> $testroot/stdout.expected echo '+modified zeta' >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + new' >> $testroot/stdout.expected + echo 'file + new (mode 644)' >> $testroot/stdout.expected echo '--- /dev/null' >> $testroot/stdout.expected echo '+++ new' >> $testroot/stdout.expected echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected @@ -269,13 +269,13 @@ test_diff_basic() { echo "commit - $head_rev" >> $testroot/stdout.expected echo "path + $testroot/wt" >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + master' >> $testroot/stdout.expected + echo 'file + master (mode 644)' >> $testroot/stdout.expected echo '--- /dev/null' >> $testroot/stdout.expected echo '+++ master' >> $testroot/stdout.expected echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected echo '+master' >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + new' >> $testroot/stdout.expected + echo 'file + new (mode 644)' >> $testroot/stdout.expected echo '--- /dev/null' >> $testroot/stdout.expected echo '+++ new' >> $testroot/stdout.expected echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected @@ -311,7 +311,7 @@ test_diff_basic() { echo "commit - $head_rev" >> $testroot/stdout.expected echo "path + $testroot/wt" >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + new' >> $testroot/stdout.expected + echo 'file + new (mode 644)' >> $testroot/stdout.expected echo '--- /dev/null' >> $testroot/stdout.expected echo '+++ new' >> $testroot/stdout.expected echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected @@ -365,7 +365,7 @@ test_diff_basic() { echo "commit - $head_rev" >> $testroot/stdout.expected echo "path + $testroot/wt" >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + new' >> $testroot/stdout.expected + echo 'file + new (mode 644)' >> $testroot/stdout.expected echo '--- /dev/null' >> $testroot/stdout.expected echo '+++ new' >> $testroot/stdout.expected echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected @@ -798,7 +798,7 @@ test_diff_symlinks_in_work_tree() { echo '-nonexistent' >> $testroot/stdout.expected echo '\ No newline at end of file' >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + zeta.link' >> $testroot/stdout.expected + echo 'file + zeta.link (mode 120000)' >> $testroot/stdout.expected echo '--- /dev/null' >> $testroot/stdout.expected echo '+++ zeta.link' >> $testroot/stdout.expected echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected @@ -950,7 +950,7 @@ test_diff_binary_files() { echo "commit - $head_rev" >> $testroot/stdout.expected echo "path + $testroot/wt" >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + foo' >> $testroot/stdout.expected + echo 'file + foo (mode 644)' >> $testroot/stdout.expected echo "Binary files /dev/null and foo differ" \ >> $testroot/stdout.expected @@ -967,7 +967,7 @@ test_diff_binary_files() { echo "commit - $head_rev" >> $testroot/stdout.expected echo "path + $testroot/wt" >> $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected - echo 'file + foo' >> $testroot/stdout.expected + echo 'file + foo (mode 644)' >> $testroot/stdout.expected echo '--- /dev/null' >> $testroot/stdout.expected echo '+++ foo' >> $testroot/stdout.expected echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected @@ -1317,11 +1317,58 @@ test_diff_crlf() { @@ -1 +1 @@ -test +test 2 +EOF + + 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_worktree_newfile_xbit() { + local testroot=`test_init diff_worktree_newfile_xbit` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret=$? + if [ $ret -ne 0 ]; then + test_done "$testroot" $ret + return 1 + fi + + echo xfile > $testroot/wt/xfile + chmod +x $testroot/wt/xfile + (cd $testroot/wt && got add xfile) > /dev/null + ret=$? + if [ $ret -ne 0 ]; then + test_done "$testroot" $ret + return 1 + fi + (cd $testroot/wt && got diff) > $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + test_done "$testroot" $ret + return 1 + fi + + local commit_id=`git_show_head $testroot/repo` + cat < $testroot/stdout.expected +diff $testroot/wt +commit - $commit_id +path + $testroot/wt +blob - /dev/null +file + xfile (mode 755) +--- /dev/null ++++ xfile +@@ -0,0 +1 @@ ++xfile EOF cmp -s $testroot/stdout.expected $testroot/stdout ret=$? if [ $ret -ne 0 ]; then + echo "failed to record mode 755" diff -u $testroot/stdout.expected $testroot/stdout fi test_done "$testroot" $ret @@ -1340,3 +1387,4 @@ run_test test_diff_binary_files run_test test_diff_commits run_test test_diff_ignored_file run_test test_diff_crlf +run_test test_diff_worktree_newfile_xbit