Commit a5c16f3cfb92f1129ef13124fc70147480141d69

Russell Belfer 2013-11-01T10:18:03

Add git_diff_options_init helper Sometimes the static initializer for git_diff_options cannot be used and since setting them to all zeroes doesn't actually work quite right, this adds a new helper for that situation. This also adds an explicit new value to the submodule settings options to be used when those enums need static initialization.

diff --git a/include/git2/diff.h b/include/git2/diff.h
index ac2d4b1..a16f86a 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -352,10 +352,10 @@ typedef struct {
 
 	/* options controlling which files are in the diff */
 
-	git_submodule_ignore_t ignore_submodules; /** << submodule ignore rule */
-	git_strarray pathspec;     /**< defaults to include all paths */
+	git_submodule_ignore_t ignore_submodules; /**< submodule ignore rule */
+	git_strarray       pathspec;     /**< defaults to include all paths */
 	git_diff_notify_cb notify_cb;
-	void *notify_payload;
+	void              *notify_payload;
 
 	/* options controlling how to diff text is generated */
 
@@ -367,9 +367,14 @@ typedef struct {
 	const char *new_prefix;       /**< defaults to "b" */
 } git_diff_options;
 
+/* The current version of the diff options structure */
 #define GIT_DIFF_OPTIONS_VERSION 1
+
+/* Stack initializer for diff options.  Alternatively use
+ * `git_diff_options_init` programmatic initialization.
+ */
 #define GIT_DIFF_OPTIONS_INIT \
-	{GIT_DIFF_OPTIONS_VERSION, 0, 0, {NULL,0}, NULL, NULL, 3}
+	{GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_DEFAULT, {NULL,0}, NULL, NULL, 3}
 
 /**
  * When iterating over a diff, callback that will be made per file.
@@ -738,6 +743,23 @@ GIT_EXTERN(int) git_diff_find_similar(
 	git_diff *diff,
 	const git_diff_find_options *options);
 
+/**
+ * Initialize diff options structure
+ *
+ * In most cases, you can probably just use `GIT_DIFF_OPTIONS_INIT` to
+ * initialize the diff options structure, but in some cases that is not
+ * going to work.  You can call this function instead.  Note that you
+ * must pass both a pointer to the structure to be initialized and the
+ * `GIT_DIFF_OPTIONS_VERSION` value from the header you compiled with.
+ *
+ * @param options Pointer to git_diff_options memory to be initialized
+ * @param version Should be `GIT_DIFF_OPTIONS_VERSION`
+ * @return 0 on success, negative on failure (such as unsupported version)
+ */
+GIT_EXTERN(int) git_diff_options_init(
+	git_diff_options *options,
+	unsigned int version);
+
 /**@}*/
 
 
diff --git a/include/git2/types.h b/include/git2/types.h
index 2d18d38..71d5374 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -268,13 +268,18 @@ typedef struct git_submodule git_submodule;
  *   superproject into the current checkout out branch of the submodule.
  * - GIT_SUBMODULE_UPDATE_NONE: do not update this submodule even when
  *   the commit in the superproject is updated.
+ * - GIT_SUBMODULE_UPDATE_DEFAULT: not used except as static initializer
+ *   when we don't want any particular update rule to be specified.
  */
 typedef enum {
-	GIT_SUBMODULE_UPDATE_RESET = -1,
+	GIT_SUBMODULE_UPDATE_RESET    = -1,
+
 	GIT_SUBMODULE_UPDATE_CHECKOUT = 1,
-	GIT_SUBMODULE_UPDATE_REBASE = 2,
-	GIT_SUBMODULE_UPDATE_MERGE = 3,
-	GIT_SUBMODULE_UPDATE_NONE = 4
+	GIT_SUBMODULE_UPDATE_REBASE   = 2,
+	GIT_SUBMODULE_UPDATE_MERGE    = 3,
+	GIT_SUBMODULE_UPDATE_NONE     = 4,
+
+	GIT_SUBMODULE_UPDATE_DEFAULT  = 0
 } git_submodule_update_t;
 
 /**
@@ -301,13 +306,18 @@ typedef enum {
  *   only considering changes if the HEAD of submodule has moved from the
  *   value in the superproject.
  * - GIT_SUBMODULE_IGNORE_ALL: never check if the submodule is dirty
+ * - GIT_SUBMODULE_IGNORE_DEFAULT: not used except as static initializer
+ *   when we don't want any particular ignore rule to be specified.
  */
 typedef enum {
-	GIT_SUBMODULE_IGNORE_RESET = -1,    /* reset to on-disk value */
-	GIT_SUBMODULE_IGNORE_NONE = 1,      /* any change or untracked == dirty */
-	GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /* dirty if tracked files change */
-	GIT_SUBMODULE_IGNORE_DIRTY = 3,     /* only dirty if HEAD moved */
-	GIT_SUBMODULE_IGNORE_ALL = 4        /* never dirty */
+	GIT_SUBMODULE_IGNORE_RESET     = -1, /* reset to on-disk value */
+
+	GIT_SUBMODULE_IGNORE_NONE      = 1,  /* any change or untracked == dirty */
+	GIT_SUBMODULE_IGNORE_UNTRACKED = 2,  /* dirty if tracked files change */
+	GIT_SUBMODULE_IGNORE_DIRTY     = 3,  /* only dirty if HEAD moved */
+	GIT_SUBMODULE_IGNORE_ALL       = 4,  /* never dirty */
+
+	GIT_SUBMODULE_IGNORE_DEFAULT   = 0
 } git_submodule_ignore_t;
 
 /** @} */
diff --git a/src/diff.c b/src/diff.c
index 5c89b6e..d94fb2c 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1311,6 +1311,19 @@ int git_diff_tree_to_workdir_with_index(
 	return error;
 }
 
+int git_diff_options_init(git_diff_options *options, unsigned int version)
+{
+	git_diff_options template = GIT_DIFF_OPTIONS_INIT;
+
+	if (version != template.version) {
+		giterr_set(GITERR_INVALID,
+			"Invalid version %d for git_diff_options", (int)version);
+		return -1;
+	}
+
+	memcpy(options, &template, sizeof(*options));
+	return 0;
+}
 
 size_t git_diff_num_deltas(const git_diff *diff)
 {
diff --git a/tests-clar/diff/blob.c b/tests-clar/diff/blob.c
index b51bc0f..93f2071 100644
--- a/tests-clar/diff/blob.c
+++ b/tests-clar/diff/blob.c
@@ -26,9 +26,8 @@ void test_diff_blob__initialize(void)
 
 	g_repo = cl_git_sandbox_init("attr");
 
-	GIT_INIT_STRUCTURE(&opts, GIT_DIFF_OPTIONS_VERSION);
+	cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION));
 	opts.context_lines = 1;
-	opts.interhunk_lines = 0;
 
 	memset(&expected, 0, sizeof(expected));
 
diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c
index ca2daf5..582174b 100644
--- a/tests-clar/diff/tree.c
+++ b/tests-clar/diff/tree.c
@@ -9,9 +9,7 @@ static diff_expects expect;
 
 void test_diff_tree__initialize(void)
 {
-	GIT_INIT_STRUCTURE(&opts, GIT_DIFF_OPTIONS_VERSION);
-	/* The default context lines is set by _INIT which we can't use here */
-	opts.context_lines = 3;
+	cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION));
 
 	memset(&expect, 0, sizeof(expect));
 
@@ -91,7 +89,8 @@ void test_diff_tree__0(void)
 }
 
 #define DIFF_OPTS(FLAGS, CTXT) \
-	{GIT_DIFF_OPTIONS_VERSION, (FLAGS), 0, {NULL,0}, NULL, NULL, (CTXT), 1}
+	{GIT_DIFF_OPTIONS_VERSION, (FLAGS), GIT_SUBMODULE_IGNORE_DEFAULT, \
+	{NULL,0}, NULL, NULL, (CTXT), 1}
 
 void test_diff_tree__options(void)
 {