commit - e19660d59fd85e4dc844d77fee9eb5837f3e3be5
commit + 63035f9f4ff2f4ea5b7361830edad916a30e37cd
blob - 20222ee6b0aa62833a8c69e650cb151f963aafc9
blob + 74fbaf41f1e493e85741b0ef0c24782c6c023472
--- got/got.1
+++ got/got.1
.Nm
work tree, use the repository path associated with this work tree.
.El
-.It Cm diff Oo Fl C Ar number Oc Oo Fl r Ar repository-path Oc Oo Fl s Oc Op Ar object1 Ar object2 | Ar path
+.It Cm diff Oo Fl C Ar number Oc Oo Fl r Ar repository-path Oc Oo Fl s Oc Oo Fl w Oc Op Ar object1 Ar object2 | Ar path
When invoked within a work tree with less than two arguments, display
uncommitted changes in the work tree.
If a
This option is only valid when
.Cm got diff
is invoked in a work tree.
+.It Fl w
+Ignore whitespace-only changes.
.El
.It Cm di
Short alias for
blob - 13dea80561dab55f3899f8130a265eb49dc72ebd
blob + 0c7661cb83bd74a19bc65dabb5d4ecf110143c1b
--- got/got.c
+++ got/got.c
static const struct got_error *
diff_blobs(struct got_object_id *blob_id1, struct got_object_id *blob_id2,
- const char *path, int diff_context, struct got_repository *repo)
+ const char *path, int diff_context, int ignore_whitespace,
+ struct got_repository *repo)
{
const struct got_error *err = NULL;
struct got_blob_object *blob1 = NULL, *blob2 = NULL;
while (path[0] == '/')
path++;
err = got_diff_blob(blob1, blob2, path, path, diff_context,
- stdout);
+ ignore_whitespace, stdout);
done:
if (blob1)
got_object_blob_close(blob1);
static const struct got_error *
diff_trees(struct got_object_id *tree_id1, struct got_object_id *tree_id2,
- const char *path, int diff_context, struct got_repository *repo)
+ const char *path, int diff_context, int ignore_whitespace,
+ struct got_repository *repo)
{
const struct got_error *err = NULL;
struct got_tree_object *tree1 = NULL, *tree2 = NULL;
goto done;
arg.diff_context = diff_context;
+ arg.ignore_whitespace = ignore_whitespace;
arg.outfile = stdout;
while (path[0] == '/')
path++;
switch (obj_type) {
case GOT_OBJ_TYPE_BLOB:
err = diff_blobs(obj_id1, obj_id2, path, diff_context,
- repo);
+ 0, repo);
break;
case GOT_OBJ_TYPE_TREE:
err = diff_trees(obj_id1, obj_id2, path, diff_context,
- repo);
+ 0, repo);
break;
default:
err = got_error(GOT_ERR_OBJ_TYPE);
if (err)
goto done;
printf("diff %s %s\n", id_str1 ? id_str1 : "/dev/null", id_str2);
- err = diff_trees(obj_id1, obj_id2, "", diff_context, repo);
+ err = diff_trees(obj_id1, obj_id2, "", diff_context, 0, repo);
}
done:
usage_diff(void)
{
fprintf(stderr, "usage: %s diff [-C number] [-r repository-path] [-s] "
- "[object1 object2 | path]\n", getprogname());
+ "[-w] [object1 object2 | path]\n", getprogname());
exit(1);
}
const char *id_str;
int header_shown;
int diff_staged;
+ int ignore_whitespace;
};
static const struct got_error *
return got_error(GOT_ERR_FILE_STATUS);
}
return got_diff_objects_as_blobs(blob_id, staged_blob_id,
- label1, label2, a->diff_context, a->repo, stdout);
+ label1, label2, a->diff_context, a->ignore_whitespace,
+ a->repo, stdout);
}
if (staged_status == GOT_STATUS_ADD ||
sb.st_size = 0;
err = got_diff_blob_file(blob1, label1, f2, sb.st_size, path,
- a->diff_context, stdout);
+ a->diff_context, a->ignore_whitespace, stdout);
done:
if (blob1)
got_object_blob_close(blob1);
const char *id_str1 = NULL, *id_str2 = NULL;
char *label1 = NULL, *label2 = NULL;
int type1, type2;
- int diff_context = 3, diff_staged = 0, ch;
+ int diff_context = 3, diff_staged = 0, ignore_whitespace = 0, ch;
const char *errstr;
char *path = NULL;
err(1, "pledge");
#endif
- while ((ch = getopt(argc, argv, "C:r:s")) != -1) {
+ while ((ch = getopt(argc, argv, "C:r:sw")) != -1) {
switch (ch) {
case 'C':
diff_context = strtonum(optarg, 1, INT_MAX, &errstr);
break;
case 's':
diff_staged = 1;
+ break;
+ case 'w':
+ ignore_whitespace = 1;
break;
default:
usage_diff();
arg.id_str = id_str;
arg.header_shown = 0;
arg.diff_staged = diff_staged;
+ arg.ignore_whitespace = ignore_whitespace;
error = got_pathlist_append(&paths, path, NULL);
if (error)
switch (type1) {
case GOT_OBJ_TYPE_BLOB:
error = got_diff_objects_as_blobs(id1, id2, NULL, NULL,
- diff_context, repo, stdout);
+ diff_context, ignore_whitespace, repo, stdout);
break;
case GOT_OBJ_TYPE_TREE:
error = got_diff_objects_as_trees(id1, id2, "", "",
- diff_context, repo, stdout);
+ diff_context, ignore_whitespace, repo, stdout);
break;
case GOT_OBJ_TYPE_COMMIT:
printf("diff %s %s\n", label1, label2);
error = got_diff_objects_as_commits(id1, id2, diff_context,
- repo, stdout);
+ ignore_whitespace, repo, stdout);
break;
default:
error = got_error(GOT_ERR_OBJ_TYPE);
blob - 927863bea9c15cfb8336083f49201f2c717f2c89
blob + 2cbdb362bbc46817c1d3e664247b978b73e7f02c
--- include/got_diff.h
+++ include/got_diff.h
* be provided which will be used to identify each blob in the diff output.
* If a label is NULL, use the blob's SHA1 checksum instead.
* The number of context lines to show in the diff must be specified as well.
+ * Whitespace differences may optionally be ignored.
*/
const struct got_error *got_diff_blob(struct got_blob_object *,
- struct got_blob_object *, const char *, const char *, int, FILE *);
+ struct got_blob_object *, const char *, const char *, int, int, FILE *);
/*
* Compute the differences between a blob and a file and write unified diff
* well as a const char * diff header label which identifies the file.
* An optional const char * diff header label for the blob may be provided, too.
* The number of context lines to show in the diff must be specified as well.
+ * Whitespace differences may optionally be ignored.
*/
const struct got_error *got_diff_blob_file(struct got_blob_object *,
- const char *, FILE *, size_t, const char *, int, FILE *);
+ const char *, FILE *, size_t, const char *, int, int, FILE *);
/*
* A callback function invoked to handle the differences between two blobs
struct got_diff_blob_output_unidiff_arg {
FILE *outfile; /* Unidiff text will be written here. */
int diff_context; /* Sets the number of context lines. */
+ int ignore_whitespace; /* Ignore whitespace differences. */
};
const struct got_error *got_diff_blob_output_unidiff(void *,
struct got_blob_object *, struct got_blob_object *,
* Write unified diff text to the provided output FILE.
*/
const struct got_error *got_diff_objects_as_blobs(struct got_object_id *,
- struct got_object_id *, const char *, const char *, int,
+ struct got_object_id *, const char *, const char *, int, int,
struct got_repository *, FILE *);
/*
* Write unified diff text to the provided output FILE.
*/
const struct got_error *got_diff_objects_as_trees(struct got_object_id *,
- struct got_object_id *, char *, char *, int, struct got_repository *, FILE *);
+ struct got_object_id *, char *, char *, int, int,
+ struct got_repository *, FILE *);
/*
* Diff two objects, assuming both objects are commits.
* Write unified diff text to the provided output FILE.
*/
const struct got_error *got_diff_objects_as_commits(struct got_object_id *,
- struct got_object_id *, int, struct got_repository *, FILE *);
+ struct got_object_id *, int, int, struct got_repository *, FILE *);
#define GOT_DIFF_MAX_CONTEXT 64
blob - e269983fad8691f00210e955a6383796011dcfc7
blob + c100c664ee6266b7d278ba0176da2648da0f1053
--- lib/diff.c
+++ lib/diff.c
static const struct got_error *
diff_blobs(struct got_blob_object *blob1, struct got_blob_object *blob2,
- const char *label1, const char *label2, int diff_context, FILE *outfile,
- struct got_diff_changes *changes)
+ const char *label1, const char *label2, int diff_context,
+ int ignore_whitespace, FILE *outfile, struct got_diff_changes *changes)
{
struct got_diff_state ds;
struct got_diff_args args;
args.label[1] = label2 ? label2 : idstr2;
args.diff_context = diff_context;
flags |= D_PROTOTYPE;
+ if (ignore_whitespace)
+ flags |= D_IGNOREBLANKS;
if (outfile) {
fprintf(outfile, "blob - %s\n", idstr1);
struct got_diff_blob_output_unidiff_arg *a = arg;
return diff_blobs(blob1, blob2, label1, label2, a->diff_context,
- a->outfile, NULL);
+ a->ignore_whitespace, a->outfile, NULL);
}
const struct got_error *
got_diff_blob(struct got_blob_object *blob1, struct got_blob_object *blob2,
- const char *label1, const char *label2, int diff_context, FILE *outfile)
+ const char *label1, const char *label2, int diff_context,
+ int ignore_whitespace, FILE *outfile)
{
- return diff_blobs(blob1, blob2, label1, label2, diff_context, outfile,
- NULL);
+ return diff_blobs(blob1, blob2, label1, label2, diff_context,
+ ignore_whitespace, outfile, NULL);
}
static const struct got_error *
static const struct got_error *
diff_blob_file(struct got_diff_changes **changes,
struct got_blob_object *blob1, const char *label1, FILE *f2, size_t size2,
- const char *label2, int diff_context, FILE *outfile)
+ const char *label2, int diff_context, int ignore_whitespace, FILE *outfile)
{
struct got_diff_state ds;
struct got_diff_args args;
args.label[1] = label2;
args.diff_context = diff_context;
flags |= D_PROTOTYPE;
+ if (ignore_whitespace)
+ flags |= D_IGNOREBLANKS;
if (outfile) {
fprintf(outfile, "blob - %s\n", label1 ? label1 : idstr1);
const struct got_error *
got_diff_blob_file(struct got_blob_object *blob1, const char *label1,
FILE *f2, size_t size2, const char *label2, int diff_context,
- FILE *outfile)
+ int ignore_whitespace, FILE *outfile)
{
return diff_blob_file(NULL, blob1, label1, f2, size2, label2,
- diff_context, outfile);
+ diff_context, ignore_whitespace, outfile);
}
const struct got_error *
struct got_blob_object *blob1, FILE *f2, size_t size2)
{
return diff_blob_file(changes, blob1, NULL, f2, size2, NULL,
- 0, NULL);
+ 0, 0, NULL);
}
const struct got_error *
if (err)
return err;
- err = diff_blobs(blob1, blob2, NULL, NULL, 3, NULL, *changes);
+ err = diff_blobs(blob1, blob2, NULL, NULL, 3, 0, NULL, *changes);
if (err) {
got_diff_free_changes(*changes);
*changes = NULL;
const struct got_error *
got_diff_objects_as_blobs(struct got_object_id *id1, struct got_object_id *id2,
const char *label1, const char *label2, int diff_context,
- struct got_repository *repo, FILE *outfile)
+ int ignore_whitespace, struct got_repository *repo, FILE *outfile)
{
const struct got_error *err;
struct got_blob_object *blob1 = NULL, *blob2 = NULL;
goto done;
}
err = got_diff_blob(blob1, blob2, label1, label2, diff_context,
- outfile);
+ ignore_whitespace, outfile);
done:
if (blob1)
got_object_blob_close(blob1);
const struct got_error *
got_diff_objects_as_trees(struct got_object_id *id1, struct got_object_id *id2,
- char *label1, char *label2, int diff_context, struct got_repository *repo,
- FILE *outfile)
+ char *label1, char *label2, int diff_context, int ignore_whitespace,
+ struct got_repository *repo, FILE *outfile)
{
const struct got_error *err;
struct got_tree_object *tree1 = NULL, *tree2 = NULL;
goto done;
}
arg.diff_context = diff_context;
+ arg.ignore_whitespace = ignore_whitespace;
arg.outfile = outfile;
err = got_diff_tree(tree1, tree2, label1, label2, repo,
got_diff_blob_output_unidiff, &arg, 1);
const struct got_error *
got_diff_objects_as_commits(struct got_object_id *id1,
- struct got_object_id *id2, int diff_context,
+ struct got_object_id *id2, int diff_context, int ignore_whitespace,
struct got_repository *repo, FILE *outfile)
{
const struct got_error *err;
err = got_diff_objects_as_trees(
commit1 ? got_object_commit_get_tree_id(commit1) : NULL,
- got_object_commit_get_tree_id(commit2), "", "", diff_context, repo,
- outfile);
+ got_object_commit_get_tree_id(commit2), "", "", diff_context,
+ ignore_whitespace, repo, outfile);
done:
if (commit1)
got_object_commit_close(commit1);
blob - 455469c47cd574f5fca1a82ebd6b9e3e680dc5e8 (mode 755)
blob + d5083e047e683d5211b8352a65aeb41fea0facb2 (mode 744)
--- regress/cmdline/diff.sh
+++ regress/cmdline/diff.sh
test_done "$testroot" "$ret"
}
+function test_diff_ignore_whitespace {
+ local testroot=`test_init diff_ignore_whitespace`
+ 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
+
+ echo "alpha " > $testroot/wt/alpha
+
+ (cd $testroot/wt && got diff -w > $testroot/stdout)
+
+ echo "diff $commit_id0 $testroot/wt" > $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -c $commit_id0 -i | grep 'alpha$' | \
+ cut -d' ' -f 1 >> $testroot/stdout.expected
+ echo 'file + alpha' >> $testroot/stdout.expected
+
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
run_test test_diff_basic
run_test test_diff_shows_conflict
run_test test_diff_tag
+run_test test_diff_ignore_whitespace
blob - 9c5b076048da355aa22fb10fbd74a357c2146375
blob + aad8017a1963e96977883c2dadfcef0fce8eac58
--- tog/tog.c
+++ tog/tog.c
switch (obj_type) {
case GOT_OBJ_TYPE_BLOB:
err = got_diff_objects_as_blobs(s->id1, s->id2, NULL, NULL,
- s->diff_context, s->repo, f);
+ s->diff_context, 0, s->repo, f);
break;
case GOT_OBJ_TYPE_TREE:
err = got_diff_objects_as_trees(s->id1, s->id2, "", "",
- s->diff_context, s->repo, f);
+ s->diff_context, 0, s->repo, f);
break;
case GOT_OBJ_TYPE_COMMIT: {
const struct got_object_id_queue *parent_ids;
got_object_commit_close(commit2);
err = got_diff_objects_as_commits(s->id1, s->id2,
- s->diff_context, s->repo, f);
+ s->diff_context, 0, s->repo, f);
break;
}
default: