summaryrefslogtreecommitdiff
path: root/include/git2
diff options
context:
space:
mode:
authorVicent Martí <vicent@github.com>2013-05-24 01:13:48 -0700
committerVicent Martí <vicent@github.com>2013-05-24 01:13:48 -0700
commit30caf0cf2942412981b7662e50a2e9242afa2cce (patch)
treecbfb8e0a543dbce5f11230dad85e8309bf90037c /include/git2
parent87a56fe015d263e592242157fa6c88badf46fa18 (diff)
parent49f70f2c370e649c3a0970b6aadd6f5cdf4f2701 (diff)
downloadlibgit2-30caf0cf2942412981b7662e50a2e9242afa2cce.tar.gz
Merge pull request #1595 from arrbee/even-more-rename-fixes
Even more rename detection fixes
Diffstat (limited to 'include/git2')
-rw-r--r--include/git2/diff.h70
-rw-r--r--include/git2/oid.h21
2 files changed, 73 insertions, 18 deletions
diff --git a/include/git2/diff.h b/include/git2/diff.h
index 1feddd7a2..0d4875b43 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -243,6 +243,19 @@ typedef struct {
* `NOT_BINARY` flag set to avoid examining file contents if you do not pass
* in hunk and/or line callbacks to the diff foreach iteration function. It
* will just use the git attributes for those files.
+ *
+ * The similarity score is zero unless you call `git_diff_find_similar()`
+ * which does a similarity analysis of files in the diff. Use that
+ * function to do rename and copy detection, and to split heavily modified
+ * files in add/delete pairs. After that call, deltas with a status of
+ * GIT_DELTA_RENAMED or GIT_DELTA_COPIED will have a similarity score
+ * between 0 and 100 indicating how similar the old and new sides are.
+ *
+ * If you ask `git_diff_find_similar` to find heavily modified files to
+ * break, but to not *actually* break the records, then GIT_DELTA_MODIFIED
+ * records may have a non-zero similarity score if the self-similarity is
+ * below the split threshold. To display this value like core Git, invert
+ * the score (a la `printf("M%03d", 100 - delta->similarity)`).
*/
typedef struct {
git_diff_file old_file;
@@ -408,18 +421,28 @@ typedef enum {
/** consider unmodified as copy sources? (`--find-copies-harder`) */
GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED = (1 << 3),
- /** split large rewrites into delete/add pairs (`--break-rewrites=/M`) */
- GIT_DIFF_FIND_AND_BREAK_REWRITES = (1 << 4),
+ /** mark large rewrites for split (`--break-rewrites=/M`) */
+ GIT_DIFF_FIND_REWRITES = (1 << 4),
+ /** actually split large rewrites into delete/add pairs */
+ GIT_DIFF_BREAK_REWRITES = (1 << 5),
+ /** mark rewrites for split and break into delete/add pairs */
+ GIT_DIFF_FIND_AND_BREAK_REWRITES =
+ (GIT_DIFF_FIND_REWRITES | GIT_DIFF_BREAK_REWRITES),
+
+ /** find renames/copies for untracked items in working directory */
+ GIT_DIFF_FIND_FOR_UNTRACKED = (1 << 6),
/** turn on all finding features */
- GIT_DIFF_FIND_ALL = (0x1f),
+ GIT_DIFF_FIND_ALL = (0x0ff),
/** measure similarity ignoring leading whitespace (default) */
GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE = 0,
/** measure similarity ignoring all whitespace */
- GIT_DIFF_FIND_IGNORE_WHITESPACE = (1 << 6),
+ GIT_DIFF_FIND_IGNORE_WHITESPACE = (1 << 12),
/** measure similarity including all data */
- GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE = (1 << 7),
+ GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE = (1 << 13),
+ /** measure similarity only by comparing SHAs (fast and cheap) */
+ GIT_DIFF_FIND_EXACT_MATCH_ONLY = (1 << 14),
} git_diff_find_t;
/**
@@ -446,7 +469,10 @@ typedef struct {
* - `copy_threshold` is the same as the -C option with a value
* - `rename_from_rewrite_threshold` matches the top of the -B option
* - `break_rewrite_threshold` matches the bottom of the -B option
- * - `target_limit` matches the -l option
+ * - `rename_limit` is the maximum number of matches to consider for
+ * a particular file. This is a little different from the `-l` option
+ * to regular Git because we will still process up to this many matches
+ * before abandoning the search.
*
* The `metric` option allows you to plug in a custom similarity metric.
* Set it to NULL for the default internal metric which is based on sampling
@@ -458,21 +484,21 @@ typedef struct {
unsigned int version;
/** Combination of git_diff_find_t values (default FIND_RENAMES) */
- unsigned int flags;
+ uint32_t flags;
/** Similarity to consider a file renamed (default 50) */
- unsigned int rename_threshold;
+ uint16_t rename_threshold;
/** Similarity of modified to be eligible rename source (default 50) */
- unsigned int rename_from_rewrite_threshold;
+ uint16_t rename_from_rewrite_threshold;
/** Similarity to consider a file a copy (default 50) */
- unsigned int copy_threshold;
+ uint16_t copy_threshold;
/** Similarity to split modify into delete/add pair (default 60) */
- unsigned int break_rewrite_threshold;
+ uint16_t break_rewrite_threshold;
- /** Maximum similarity sources to examine (a la diff's `-l` option or
- * the `diff.renameLimit` config) (default 200)
+ /** Maximum similarity sources to examine for a file (somewhat like
+ * git-diff's `-l` option or `diff.renameLimit` config) (default 200)
*/
- unsigned int target_limit;
+ size_t rename_limit;
/** Pluggable similarity metric; pass NULL to use internal metric */
git_diff_similarity_metric *metric;
@@ -689,6 +715,22 @@ GIT_EXTERN(int) git_diff_print_compact(
void *payload);
/**
+ * Iterate over a diff generating text output like "git diff --raw".
+ *
+ * Returning a non-zero value from 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 print_cb Callback to make per line of diff text.
+ * @param payload Reference pointer that will be passed to your callback.
+ * @return 0 on success, GIT_EUSER on non-zero callback, or error code
+ */
+GIT_EXTERN(int) git_diff_print_raw(
+ git_diff_list *diff,
+ git_diff_data_cb print_cb,
+ void *payload);
+
+/**
* Look up the single character abbreviation for a delta status code.
*
* When you call `git_diff_print_compact` it prints single letter codes into
diff --git a/include/git2/oid.h b/include/git2/oid.h
index b20bb221a..018cead4a 100644
--- a/include/git2/oid.h
+++ b/include/git2/oid.h
@@ -90,6 +90,17 @@ GIT_EXTERN(void) git_oid_fromraw(git_oid *out, const unsigned char *raw);
GIT_EXTERN(void) git_oid_fmt(char *out, const git_oid *id);
/**
+ * Format a git_oid into a partial hex string.
+ *
+ * @param out output hex string; you say how many bytes to write.
+ * If the number of bytes is > GIT_OID_HEXSZ, extra bytes
+ * will be zeroed; if not, a '\0' terminator is NOT added.
+ * @param n number of characters to write into out string
+ * @param oid oid structure to format.
+ */
+GIT_EXTERN(void) git_oid_nfmt(char *out, size_t n, const git_oid *id);
+
+/**
* Format a git_oid into a loose-object path string.
*
* The resulting string is "aa/...", where "aa" is the first two
@@ -117,10 +128,12 @@ GIT_EXTERN(char *) git_oid_allocfmt(const git_oid *id);
* Format a git_oid into a buffer as a hex format c-string.
*
* If the buffer is smaller than GIT_OID_HEXSZ+1, then the resulting
- * oid c-string will be truncated to n-1 characters. If there are
- * any input parameter errors (out == NULL, n == 0, oid == NULL),
- * then a pointer to an empty string is returned, so that the return
- * value can always be printed.
+ * oid c-string will be truncated to n-1 characters (but will still be
+ * NUL-byte terminated).
+ *
+ * If there are any input parameter errors (out == NULL, n == 0, oid ==
+ * NULL), then a pointer to an empty string is returned, so that the
+ * return value can always be printed.
*
* @param out the buffer into which the oid string is output.
* @param n the size of the out buffer.