Commit 510f1bac6b94ce19459498ae78f87fc4f4552305

Russell Belfer 2012-08-30T16:39:05

Fix comments and a minor bug This adds better header comments and also fixes a bug in one of simple APIs that tells the number of lines in the current hunk.

diff --git a/include/git2/diff.h b/include/git2/diff.h
index 7ac6994..d145506 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -327,28 +327,118 @@ GIT_EXTERN(int) git_diff_merge(
 /**@{*/
 
 /**
+ * Iterate over a diff list issuing callbacks.
+ *
+ * This will iterate through all of the files described in a diff.  You
+ * should provide a file callback to learn about each file.
+ *
+ * The "hunk" and "line" callbacks are optional, and the text diff of the
+ * files will only be calculated if they are not NULL.  Of course, these
+ * callbacks will not be invoked for binary files on the diff list or for
+ * files whose only changed is a file mode change.
+ *
+ * Returning a non-zero value from any of the callbacks will terminate
+ * the iteration and cause this return `GIT_EUSER`.
+ *
+ * @param diff A git_diff_list generated by one of the above functions.
+ * @param cb_data Reference pointer that will be passed to your callbacks.
+ * @param file_cb Callback function to make per file in the diff.
+ * @param hunk_cb Optional callback to make per hunk of text diff.  This
+ *                callback is called to describe a range of lines in the
+ *                diff.  It will not be issued for binary files.
+ * @param line_cb Optional callback to make per line of diff text.  This
+ *                same callback will be made for context lines, added, and
+ *                removed lines, and even for a deleted trailing newline.
+ * @return 0 on success, GIT_EUSER on non-zero callback, or error code
+ */
+GIT_EXTERN(int) git_diff_foreach(
+	git_diff_list *diff,
+	void *cb_data,
+	git_diff_file_fn file_cb,
+	git_diff_hunk_fn hunk_cb,
+	git_diff_data_fn line_cb);
+
+/**
  * Create a diff iterator object that can be used to traverse a diff.
+ *
+ * This iterator can be used instead of `git_diff_foreach` in situations
+ * where callback functions are awkward to use.  Because of the way that
+ * diffs are calculated internally, using an iterator will use somewhat
+ * more memory than `git_diff_foreach` would.
+ *
+ * @param iterator Output parameter of newly created iterator.
+ * @param diff Diff over which you wish to iterate.
+ * @return 0 on success, < 0 on error
  */
 GIT_EXTERN(int) git_diff_iterator_new(
 	git_diff_iterator **iterator,
 	git_diff_list *diff);
 
-GIT_EXTERN(void) git_diff_iterator_free(git_diff_iterator *iter);
+/**
+ * Release the iterator object.
+ *
+ * Call this when you are done using the iterator.
+ *
+ * @param iterator The diff iterator to be freed.
+ */
+GIT_EXTERN(void) git_diff_iterator_free(git_diff_iterator *iterator);
 
 /**
  * Return the number of files in the diff.
+ *
+ * Note that there is an uncommon scenario where this number might be too
+ * high -- if a file in the working directory has been "touched" on disk but
+ * the contents were then reverted, it might have been added to the
+ * `git_diff_list` as a MODIFIED file along with a note that the status
+ * needs to be confirmed when the file contents are loaded into memory.  In
+ * that case, when the file is loaded, we will check the contents and might
+ * switch it back to UNMODIFIED.  The loading of the file is deferred until
+ * as late as possible.  As a result, this might return a value what was too
+ * high in those circumstances.
+ *
+ * This is true of `git_diff_foreach` as well, but the only implication
+ * there is that the `progress` value would not advance evenly.
+ *
+ * @param iterator The iterator object
+ * @return The maximum number of files to be iterated over
  */
 GIT_EXTERN(int) git_diff_iterator_num_files(git_diff_iterator *iterator);
 
+/**
+ * Return the number of hunks in the current file
+ *
+ * This will return the number of diff hunks in the current file.  If the
+ * diff has not been performed yet, this may result in loading the file and
+ * performing the diff.
+ *
+ * @param iterator The iterator object
+ * @return The number of hunks in the current file or <0 on loading failure
+ */
 GIT_EXTERN(int) git_diff_iterator_num_hunks_in_file(git_diff_iterator *iterator);
 
+/**
+ * Return the number of lines in the hunk currently being examined.
+ *
+ * This will return the number of lines in the current hunk.  If the diff
+ * has not been performed yet, this may result in loading the file and
+ * performing the diff.
+ *
+ * @param iterator The iterator object
+ * @return The number of lines in the current hunk (context, added, and
+ *         removed all added together) or <0 on loading failure
+ */
 GIT_EXTERN(int) git_diff_iterator_num_lines_in_hunk(git_diff_iterator *iterator);
 
 /**
  * Return the delta information for the next file in the diff.
  *
  * This will return a pointer to the next git_diff_delta` to be processed or
- * NULL if the iterator is at the end of the diff, then advance.
+ * NULL if the iterator is at the end of the diff, then advance.  This
+ * returns the value `GIT_ITEROVER` after processing the last file.
+ *
+ * @param delta Output parameter for the next delta object
+ * @param iterator The iterator object
+ * @return 0 on success, GIT_ITEROVER when done, other value < 0 on error
  */
 GIT_EXTERN(int) git_diff_iterator_next_file(
 	git_diff_delta **delta,
@@ -364,6 +454,10 @@ GIT_EXTERN(int) git_diff_iterator_next_file(
  * actual text diff will be computed (it cannot be computed incrementally)
  * so the first call for a new file is expensive (at least in relative
  * terms - in reality, it is still pretty darn fast).
+ *
+ * @param iterator The iterator object
+ * @return 0 on success, GIT_ITEROVER when done with current file, other
+ *         value < 0 on error
  */
 GIT_EXTERN(int) git_diff_iterator_next_hunk(
 	git_diff_range **range,
@@ -373,6 +467,10 @@ GIT_EXTERN(int) git_diff_iterator_next_hunk(
 
 /**
  * Return the next line of the current hunk of diffs.
+ *
+ * @param iterator The iterator object
+ * @return 0 on success, GIT_ITEROVER when done with current hunk, other
+ *         value < 0 on error
  */
 GIT_EXTERN(int) git_diff_iterator_next_line(
 	char *line_origin, /**< GIT_DIFF_LINE_... value from above */
@@ -381,38 +479,6 @@ GIT_EXTERN(int) git_diff_iterator_next_line(
 	git_diff_iterator *iterator);
 
 /**
- * Iterate over a diff list issuing callbacks.
- *
- * This will iterate through all of the files described in a diff.  You
- * should provide a file callback to learn about each file.
- *
- * The "hunk" and "line" callbacks are optional, and the text diff of the
- * files will only be calculated if they are not NULL.  Of course, these
- * callbacks will not be invoked for binary files on the diff list or for
- * files whose only changed is a file mode change.
- *
- * Returning a non-zero value from any of the callbacks will terminate
- * the iteration and cause this return `GIT_EUSER`.
- *
- * @param diff A git_diff_list generated by one of the above functions.
- * @param cb_data Reference pointer that will be passed to your callbacks.
- * @param file_cb Callback function to make per file in the diff.
- * @param hunk_cb Optional callback to make per hunk of text diff.  This
- *                callback is called to describe a range of lines in the
- *                diff.  It will not be issued for binary files.
- * @param line_cb Optional callback to make per line of diff text.  This
- *                same callback will be made for context lines, added, and
- *                removed lines, and even for a deleted trailing newline.
- * @return 0 on success, GIT_EUSER on non-zero callback, or error code
- */
-GIT_EXTERN(int) git_diff_foreach(
-	git_diff_list *diff,
-	void *cb_data,
-	git_diff_file_fn file_cb,
-	git_diff_hunk_fn hunk_cb,
-	git_diff_data_fn line_cb);
-
-/**
  * Iterate over a diff generating text output like "git diff --name-status".
  *
  * Returning a non-zero value from the callbacks will terminate the
diff --git a/src/diff_output.c b/src/diff_output.c
index 6992174..d715f9e 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -1023,7 +1023,6 @@ struct git_diff_iterator {
 	diffiter_hunk *hunk_curr;
 	char hunk_header[128];
 	git_pool lines;
-	size_t   line_count;
 	diffiter_line *line_curr;
 };
 
@@ -1096,7 +1095,6 @@ static int diffiter_line_cb(
 	line->len = content_len;
 
 	info->last_hunk->line_count++;
-	iter->line_count++;
 
 	if (info->last_hunk->line_head == NULL)
 		info->last_hunk->line_head = line;
@@ -1136,7 +1134,6 @@ static void diffiter_do_unload_file(git_diff_iterator *iter)
 	iter->ctxt.delta = NULL;
 	iter->hunk_head = NULL;
 	iter->hunk_count = 0;
-	iter->line_count = 0;
 }
 
 int git_diff_iterator_new(
@@ -1202,7 +1199,9 @@ int git_diff_iterator_num_hunks_in_file(git_diff_iterator *iter)
 int git_diff_iterator_num_lines_in_hunk(git_diff_iterator *iter)
 {
 	int error = diffiter_do_diff_file(iter);
-	return (error != 0) ? error : (int)iter->line_count;
+	if (!error && iter->hunk_curr)
+		error = iter->hunk_curr->line_count;
+	return error;
 }
 
 int git_diff_iterator_next_file(