From 9a12a6256efa7da4b4245d0f2b7df6f3b84edabd Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 18 Sep 2012 15:13:07 -0700 Subject: [PATCH] New take on iterating over diff content Allow diff deltas to be accessed by index and make patch generation explicit with hunk and line access by index as well. --- include/git2/diff.h | 243 ++++++++++++++++++-------------------------- 1 file changed, 100 insertions(+), 143 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index 05825c50d..2a5cdacc0 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -98,9 +98,6 @@ enum { GIT_DIFF_FILE_FREE_PATH = (1 << 1), GIT_DIFF_FILE_BINARY = (1 << 2), GIT_DIFF_FILE_NOT_BINARY = (1 << 3), - GIT_DIFF_FILE_FREE_DATA = (1 << 4), - GIT_DIFF_FILE_UNMAP_DATA = (1 << 5), - GIT_DIFF_FILE_NO_DATA = (1 << 6), }; /** @@ -220,9 +217,13 @@ typedef int (*git_diff_data_fn)( size_t content_len); /** - * The diff iterator object is used to scan a diff list. + * The diff patch is used to store all the text diffs for a delta. + * + * You can easily loop over the content of patches and get information about + * them. */ -typedef struct git_diff_iterator git_diff_iterator; +typedef struct git_diff_patch git_diff_patch; + /** @name Diff List Generator Functions * @@ -349,7 +350,7 @@ GIT_EXTERN(int) git_diff_merge( /**@{*/ /** - * Iterate over a diff list issuing callbacks. + * Loop over all deltas in 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. @@ -380,137 +381,6 @@ GIT_EXTERN(int) git_diff_foreach( 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); - -/** - * 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 progress value for traversing the diff. - * - * This returns a value between 0.0 and 1.0 that represents the progress - * through the diff iterator. The value is monotonically increasing and - * will advance gradually as you progress through the iteration. - * - * @param iterator The diff iterator - * @return Value between 0.0 and 1.0 - */ -GIT_EXTERN(float) git_diff_iterator_progress(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. 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, - git_diff_iterator *iterator); - -/** - * Return the hunk information for the next hunk in the current file. - * - * It is recommended that you not call this if the file is a binary - * file, but it is allowed to do so. - * - * The `header` text output will contain the standard hunk header that - * would appear in diff output. The header string will be NUL terminated. - * - * WARNING! Call this function for the first time on a file is when the - * 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 range Output pointer to range of lines covered by the hunk; - * This range object is owned by the library and should not be freed. - * @param header Output pointer to the text of the hunk header - * This string is owned by the library and should not be freed. - * @param header_len Output pointer to store the length of the header text - * @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, - const char **header, - size_t *header_len, - git_diff_iterator *iterator); - -/** - * Return the next line of the current hunk of diffs. - * - * The `line_origin` output will tell you what type of line this is - * (e.g. was it added or removed or is it just context for the diff). - * - * The `content` will be a pointer to the file data that goes in the - * line. IT WILL NOT BE NUL TERMINATED. You have to use the `content_len` - * value and only process that many bytes of data from the content string. - * - * @param line_origin Output pointer to store a GIT_DIFF_LINE value for this - * next chunk of data. The value is a single character, not a buffer. - * @param content Output pointer to store the content of the diff; this - * string is owned by the library and should not be freed. - * @param content_len Output pointer to store the length of the content. - * @param iterator The iterator object - * @return 0 on success, GIT_ITEROVER when done with current line, other - * value < 0 on error - */ -GIT_EXTERN(int) git_diff_iterator_next_line( - char *line_origin, /**< GIT_DIFF_LINE_... value from above */ - const char **content, - size_t *content_len, - git_diff_iterator *iterator); - /** * Iterate over a diff generating text output like "git diff --name-status". * @@ -552,17 +422,104 @@ GIT_EXTERN(int) git_diff_print_patch( /** * Query how many diff records are there in a diff list. * - * You can optionally pass in a `git_delta_t` value if you want a count - * of just entries that match that delta type, or pass -1 for all delta - * records. + * @param diff A git_diff_list generated by one of the above functions + * @return Count of number of deltas in the list + */ +GIT_EXTERN(size_t) git_diff_entrycount(git_diff_list *diff); + +/** + * Query how many diff deltas are there in a diff list filtered by type. + * + * This works just like `git_diff_entrycount()` with an extra parameter + * that is a `git_delta_t` and returns just the count of how many deltas + * match that particular type. * * @param diff A git_diff_list generated by one of the above functions - * @param delta_t A git_delta_t value to filter the count, or -1 for all records + * @param type A git_delta_t value to filter the count * @return Count of number of deltas matching delta_t type */ -GIT_EXTERN(int) git_diff_entrycount( +GIT_EXTERN(size_t) git_diff_entrycount_of_type( git_diff_list *diff, - int delta_t); + git_delta_t type); + +/** + * Return the diff delta and patch for an entry in the diff list. + * + * The `git_diff_patch` is a newly created object contains the text diffs + * for the delta. You have to call `git_diff_patch_free()` when you are + * done with it. You can use the patch object to loop over all the hunks + * and lines in the diff of the one delta. + * + * For a binary file, no `git_diff_patch` will be created, the output will + * be set to NULL, and the `binary` flag will be set true in the + * `git_diff_delta` structure. + * + * The `git_diff_delta` pointer points to internal data and you do not have + * to release it when you are done with it. It will go away when the + * `git_diff_list` and `git_diff_patch` go away. + * + * It is okay to pass NULL for either of the output parameters; if you pass + * NULL for the `git_diff_patch`, then the text diff will not be calculated. + * + * @param patch Output parameter for the delta patch object + * @param delta Output parameter for the delta object + * @param diff Diff list object + * @param idx Index into diff list + * @return 0 on success, other value < 0 on error + */ +GIT_EXTERN(int) git_diff_get_patch( + git_diff_patch **patch, + const git_diff_delta **delta, + git_diff_list *diff, + size_t idx); + +/** + * Free a git_diff_patch object. + */ +GIT_EXTERN(void) git_diff_patch_free( + git_diff_patch *patch); + +/** + * Get the delta associated with a patch + */ +GIT_EXTERN(void) git_diff_patch_get_delta( + const git_diff_delta **delta, + git_diff_patch *patch); + +/** + * Get the number of hunks in a patch + */ +GIT_EXTERN(size_t) git_diff_patch_hunks( + git_diff_patch *patch); + +/** + * Get the information about a hunk in a patch + */ +GIT_EXTERN(int) git_diff_patch_get_hunk( + const git_diff_range **range, + const char **header, + size_t *header_len, + size_t *lines_in_hunk, + git_diff_patch *patch, + size_t hunk); + +/** + * Get the number of lines in a hunk + */ +GIT_EXTERN(size_t) git_diff_patch_lines_in_hunk( + git_diff_patch *patch, + size_t hunk); + +/** + * Get a line in a hunk of a patch + */ +GIT_EXTERN(int) git_diff_patch_get_line_in_hunk( + char *line_origin, + const char **content, + size_t *content_len, + git_diff_patch *patch, + size_t hunk, + size_t line_of_hunk); /**@}*/