]> git.proxmox.com Git - libgit2.git/blobdiff - include/git2/diff.h
New upstream version 1.4.3+dfsg.1
[libgit2.git] / include / git2 / diff.h
index 0abbc7f06f85badcc0e553fd18a1c7a353dded85..3839f0033ce7fcc563d60cf078c412ce3af0790d 100644 (file)
 /**
  * @file git2/diff.h
  * @brief Git tree and file differencing routines.
- *
- * Overview
- * --------
- *
- * Calculating diffs is generally done in two phases: building a list of
- * diffs then traversing it.  This makes is easier to share logic across
- * the various types of diffs (tree vs tree, workdir vs index, etc.), and
- * also allows you to insert optional diff post-processing phases,
- * such as rename detection, in between the steps.  When you are done with
- * a diff object, it must be freed.
- *
- * Terminology
- * -----------
- *
- * To understand the diff APIs, you should know the following terms:
- *
- * - A `diff` represents the cumulative list of differences between two
- *   snapshots of a repository (possibly filtered by a set of file name
- *   patterns).  This is the `git_diff` object.
- *
- * - A `delta` is a file pair with an old and new revision.  The old version
- *   may be absent if the file was just created and the new version may be
- *   absent if the file was deleted.  A diff is mostly just a list of deltas.
- *
- * - A `binary` file / delta is a file (or pair) for which no text diffs
- *   should be generated.  A diff can contain delta entries that are
- *   binary, but no diff content will be output for those files.  There is
- *   a base heuristic for binary detection and you can further tune the
- *   behavior with git attributes or diff flags and option settings.
- *
- * - A `hunk` is a span of modified lines in a delta along with some stable
- *   surrounding context.  You can configure the amount of context and other
- *   properties of how hunks are generated.  Each hunk also comes with a
- *   header that described where it starts and ends in both the old and new
- *   versions in the delta.
- *
- * - A `line` is a range of characters inside a hunk.  It could be a context
- *   line (i.e. in both old and new versions), an added line (i.e. only in
- *   the new version), or a removed line (i.e. only in the old version).
- *   Unfortunately, we don't know anything about the encoding of data in the
- *   file being diffed, so we cannot tell you much about the line content.
- *   Line data will not be NUL-byte terminated, however, because it will be
- *   just a span of bytes inside the larger file.
- *
  * @ingroup Git
  * @{
  */
@@ -129,8 +85,12 @@ typedef enum {
         */
        GIT_DIFF_INCLUDE_CASECHANGE = (1u << 11),
 
-       /** If the pathspec is set in the diff options, this flags means to
-        *  apply it as an exact match instead of as an fnmatch pattern.
+       /** If the pathspec is set in the diff options, this flags indicates
+        *  that the paths will be treated as literal paths instead of
+        *  fnmatch patterns.  Each path in the list must either be a full
+        *  path to a file or a directory.  (A trailing slash indicates that
+        *  the path will _only_ match a directory).  If a directory is
+        *  specified, all children will be included.
         */
        GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1u << 12),
 
@@ -159,7 +119,7 @@ typedef enum {
 
        /** Include unreadable files in the diff */
        GIT_DIFF_INCLUDE_UNREADABLE = (1u << 16),
-       
+
        /** Include unreadable files in the diff */
        GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 17),
 
@@ -167,6 +127,15 @@ typedef enum {
         * Options controlling how output will be generated
         */
 
+       /** Use a heuristic that takes indentation and whitespace into account
+        * which generally can produce better diffs when dealing with ambiguous
+        * diff hunks.
+        */
+       GIT_DIFF_INDENT_HEURISTIC = (1u << 18),
+
+       /** Ignore blank lines */
+       GIT_DIFF_IGNORE_BLANK_LINES = (1u << 19),
+
        /** Treat all files as text, disabling binary attributes & detection */
        GIT_DIFF_FORCE_TEXT = (1u << 20),
        /** Treat all files as binary, disabling text diffs */
@@ -196,21 +165,33 @@ typedef enum {
        /** Use the "patience diff" algorithm */
        GIT_DIFF_PATIENCE = (1u << 28),
        /** Take extra time to find minimal diff */
-       GIT_DIFF_MINIMAL = (1 << 29),
+       GIT_DIFF_MINIMAL = (1u << 29),
 
        /** Include the necessary deflate / delta information so that `git-apply`
         *  can apply given diff information to binary files.
         */
-       GIT_DIFF_SHOW_BINARY = (1 << 30),
+       GIT_DIFF_SHOW_BINARY = (1u << 30)
 } git_diff_option_t;
 
 /**
  * The diff object that contains all individual file deltas.
  *
+ * A `diff` represents the cumulative list of differences between two
+ * snapshots of a repository (possibly filtered by a set of file name
+ * patterns).
+ *
+ * Calculating diffs is generally done in two phases: building a list of
+ * diffs then traversing it. This makes is easier to share logic across
+ * the various types of diffs (tree vs tree, workdir vs index, etc.), and
+ * also allows you to insert optional diff post-processing phases,
+ * such as rename detection, in between the steps. When you are done with
+ * a diff object, it must be freed.
+ *
  * This is an opaque structure which will be allocated by one of the diff
- * generator functions below (such as `git_diff_tree_to_tree`).  You are
+ * generator functions below (such as `git_diff_tree_to_tree`). You are
  * responsible for releasing the object memory when done, using the
  * `git_diff_free()` function.
+ *
  */
 typedef struct git_diff git_diff;
 
@@ -227,6 +208,7 @@ typedef enum {
        GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */
        GIT_DIFF_FLAG_VALID_ID   = (1u << 2), /**< `id` value is known correct */
        GIT_DIFF_FLAG_EXISTS     = (1u << 3), /**< file exists at this side of the delta */
+       GIT_DIFF_FLAG_VALID_SIZE = (1u << 4)  /**< file size value is known correct */
 } git_diff_flag_t;
 
 /**
@@ -250,7 +232,7 @@ typedef enum {
        GIT_DELTA_UNTRACKED = 7,   /**< entry is untracked item in workdir */
        GIT_DELTA_TYPECHANGE = 8,  /**< type of entry changed between old and new */
        GIT_DELTA_UNREADABLE = 9,  /**< entry is unreadable */
-       GIT_DELTA_CONFLICTED = 10, /**< entry in the index is conflicted */
+       GIT_DELTA_CONFLICTED = 10  /**< entry in the index is conflicted */
 } git_delta_t;
 
 /**
@@ -259,32 +241,53 @@ typedef enum {
  * Although this is called a "file", it could represent a file, a symbolic
  * link, a submodule commit id, or even a tree (although that only if you
  * are tracking type changes or ignored/untracked directories).
- *
- * The `oid` is the `git_oid` of the item.  If the entry represents an
- * absent side of a diff (e.g. the `old_file` of a `GIT_DELTA_ADDED` delta),
- * then the oid will be zeroes.
- *
- * `path` is the NUL-terminated path to the entry relative to the working
- * directory of the repository.
- *
- * `size` is the size of the entry in bytes.
- *
- * `flags` is a combination of the `git_diff_flag_t` types
- *
- * `mode` is, roughly, the stat() `st_mode` value for the item.  This will
- * be restricted to one of the `git_filemode_t` values.
  */
 typedef struct {
-       git_oid     id;
-       const char *path;
-       git_off_t   size;
-       uint32_t    flags;
-       uint16_t    mode;
+       /**
+        * The `git_oid` of the item.  If the entry represents an
+        * absent side of a diff (e.g. the `old_file` of a `GIT_DELTA_ADDED` delta),
+        * then the oid will be zeroes.
+        */
+       git_oid            id;
+
+       /**
+        * The NUL-terminated path to the entry relative to the working
+        * directory of the repository.
+        */
+       const char        *path;
+
+       /**
+        * The size of the entry in bytes.
+        */
+       git_object_size_t  size;
+
+       /**
+        * A combination of the `git_diff_flag_t` types
+        */
+       uint32_t           flags;
+
+       /**
+        * Roughly, the stat() `st_mode` value for the item.  This will
+        * be restricted to one of the `git_filemode_t` values.
+        */
+       uint16_t           mode;
+
+       /**
+        * Represents the known length of the `id` field, when
+        * converted to a hex string.  It is generally `GIT_OID_HEXSZ`, unless this
+        * delta was created from reading a patch file, in which case it may be
+        * abbreviated to something reasonable, like 7 characters.
+        */
+       uint16_t           id_abbrev;
 } git_diff_file;
 
 /**
  * Description of changes to one entry.
  *
+ * A `delta` is a file pair with an old and new revision.  The old version
+ * may be absent if the file was just created and the new version may be
+ * absent if the file was deleted.  A diff is mostly just a list of deltas.
+ *
  * When iterating over a diff, this will be passed to most callbacks and
  * you can use the contents to understand exactly what has changed.
  *
@@ -330,7 +333,7 @@ typedef struct {
 /**
  * Diff notification callback function.
  *
- * The callback will be called for each file, just before the `git_delta_t`
+ * The callback will be called for each file, just before the `git_diff_delta`
  * gets inserted into the diff.
  *
  * When the callback:
@@ -340,12 +343,28 @@ typedef struct {
  * - returns 0, the delta is inserted into the diff, and the diff process
  *             continues.
  */
-typedef int (*git_diff_notify_cb)(
+typedef int GIT_CALLBACK(git_diff_notify_cb)(
        const git_diff *diff_so_far,
        const git_diff_delta *delta_to_add,
        const char *matched_pathspec,
        void *payload);
 
+/**
+ * Diff progress callback.
+ *
+ * Called before each file comparison.
+ *
+ * @param diff_so_far The diff being generated.
+ * @param old_path The path to the old file or NULL.
+ * @param new_path The path to the new file or NULL.
+ * @return Non-zero to abort the diff.
+ */
+typedef int GIT_CALLBACK(git_diff_progress_cb)(
+       const git_diff *diff_so_far,
+       const char *old_path,
+       const char *new_path,
+       void *payload);
+
 /**
  * Structure describing options about how the diff should be executed.
  *
@@ -353,43 +372,79 @@ typedef int (*git_diff_notify_cb)(
  * values.  Similarly, passing NULL for the options structure will
  * give the defaults.  The default values are marked below.
  *
- * - `flags` is a combination of the `git_diff_option_t` values above
- * - `context_lines` is the number of unchanged lines that define the
- *    boundary of a hunk (and to display before and after)
- * - `interhunk_lines` is the maximum number of unchanged lines between
- *    hunk boundaries before the hunks will be merged into a one.
- * - `old_prefix` is the virtual "directory" to prefix to old file names
- *   in hunk headers (default "a")
- * - `new_prefix` is the virtual "directory" to prefix to new file names
- *   in hunk headers (default "b")
- * - `pathspec` is an array of paths / fnmatch patterns to constrain diff
- * - `max_size` is a file size (in bytes) above which a blob will be marked
- *   as binary automatically; pass a negative value to disable.
- * - `notify_cb` is an optional callback function, notifying the consumer of
- *   which files are being examined as the diff is generated
- * - `notify_payload` is the payload data to pass to the `notify_cb` function
- * - `ignore_submodules` overrides the submodule ignore setting for all
- *   submodules in the diff.
  */
 typedef struct {
        unsigned int version;      /**< version for the struct */
-       uint32_t flags;            /**< defaults to GIT_DIFF_NORMAL */
+
+       /**
+        * A combination of `git_diff_option_t` values above.
+        * Defaults to GIT_DIFF_NORMAL
+        */
+       uint32_t flags;
 
        /* 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_diff_notify_cb notify_cb;
-       void              *notify_payload;
+       /** Overrides the submodule ignore setting for all submodules in the diff. */
+       git_submodule_ignore_t ignore_submodules;
+
+       /**
+        * An array of paths / fnmatch patterns to constrain diff.
+        * All paths are included by default.
+        */
+       git_strarray       pathspec;
+
+       /**
+        * An optional callback function, notifying the consumer of changes to
+        * the diff as new deltas are added.
+        */
+       git_diff_notify_cb   notify_cb;
+
+       /**
+        * An optional callback function, notifying the consumer of which files
+        * are being examined as the diff is generated.
+        */
+       git_diff_progress_cb progress_cb;
+
+       /** The payload to pass to the callback functions. */
+       void                *payload;
 
        /* options controlling how to diff text is generated */
 
-       uint32_t    context_lines;    /**< defaults to 3 */
-       uint32_t    interhunk_lines;  /**< defaults to 0 */
-       uint16_t    id_abbrev;       /**< default 'core.abbrev' or 7 if unset */
-       git_off_t   max_size;         /**< defaults to 512MB */
-       const char *old_prefix;       /**< defaults to "a" */
-       const char *new_prefix;       /**< defaults to "b" */
+       /**
+        * The number of unchanged lines that define the boundary of a hunk
+        * (and to display before and after). Defaults to 3.
+        */
+       uint32_t    context_lines;
+       /**
+        * The maximum number of unchanged lines between hunk boundaries before
+        * the hunks will be merged into one. Defaults to 0.
+        */
+       uint32_t    interhunk_lines;
+
+       /**
+        * The abbreviation length to use when formatting object ids.
+        * Defaults to the value of 'core.abbrev' from the config, or 7 if unset.
+        */
+       uint16_t    id_abbrev;
+
+       /**
+        * A size (in bytes) above which a blob will be marked as binary
+        * automatically; pass a negative value to disable.
+        * Defaults to 512MB.
+        */
+       git_off_t   max_size;
+
+       /**
+        * The virtual "directory" prefix for old file names in hunk headers.
+        * Default is "a".
+        */
+       const char *old_prefix;
+
+       /**
+        * The virtual "directory" prefix for new file names in hunk headers.
+        * Defaults to "b".
+        */
+       const char *new_prefix;
 } git_diff_options;
 
 /* The current version of the diff options structure */
@@ -399,17 +454,19 @@ typedef struct {
  * `git_diff_options_init` programmatic initialization.
  */
 #define GIT_DIFF_OPTIONS_INIT \
-       {GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_UNSPECIFIED, {NULL,0}, NULL, NULL, 3}
+       {GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_UNSPECIFIED, {NULL,0}, NULL, NULL, NULL, 3}
 
 /**
- * Initializes a `git_diff_options` with default values. Equivalent to
- * creating an instance with GIT_DIFF_OPTIONS_INIT.
+ * Initialize git_diff_options structure
+ *
+ * Initializes a `git_diff_options` with default values. Equivalent to creating
+ * an instance with GIT_DIFF_OPTIONS_INIT.
  *
- * @param opts The `git_diff_options` struct to initialize
- * @param version Version of struct; pass `GIT_DIFF_OPTIONS_VERSION`
+ * @param opts The `git_diff_options` struct to initialize.
+ * @param version The struct version; pass `GIT_DIFF_OPTIONS_VERSION`.
  * @return Zero on success; -1 on failure.
  */
-GIT_EXTERN(int) git_diff_init_options(
+GIT_EXTERN(int) git_diff_options_init(
        git_diff_options *opts,
        unsigned int version);
 
@@ -420,11 +477,13 @@ GIT_EXTERN(int) git_diff_init_options(
  * @param progress Goes from 0 to 1 over the diff
  * @param payload User-specified pointer from foreach function
  */
-typedef int (*git_diff_file_cb)(
+typedef int GIT_CALLBACK(git_diff_file_cb)(
        const git_diff_delta *delta,
        float progress,
        void *payload);
 
+#define GIT_DIFF_HUNK_HEADER_SIZE      128
+
 /**
  * When producing a binary diff, the binary data returned will be
  * either the deflated full ("literal") contents of the file, or
@@ -439,7 +498,7 @@ typedef enum {
        GIT_DIFF_BINARY_LITERAL,
 
        /** The binary data is the delta from one side to the other. */
-       GIT_DIFF_BINARY_DELTA,
+       GIT_DIFF_BINARY_DELTA
 } git_diff_binary_t;
 
 /** The contents of one of the files in a binary diff. */
@@ -457,23 +516,46 @@ typedef struct {
        size_t inflatedlen;
 } git_diff_binary_file;
 
-/** Structure describing the binary contents of a diff. */
+/**
+ * Structure describing the binary contents of a diff.
+ *
+ * A `binary` file / delta is a file (or pair) for which no text diffs
+ * should be generated. A diff can contain delta entries that are
+ * binary, but no diff content will be output for those files. There is
+ * a base heuristic for binary detection and you can further tune the
+ * behavior with git attributes or diff flags and option settings.
+ */
 typedef struct {
+       /**
+        * Whether there is data in this binary structure or not.
+        *
+        * If this is `1`, then this was produced and included binary content.
+        * If this is `0` then this was generated knowing only that a binary
+        * file changed but without providing the data, probably from a patch
+        * that said `Binary files a/file.txt and b/file.txt differ`.
+        */
+       unsigned int contains_data;
        git_diff_binary_file old_file; /**< The contents of the old file. */
        git_diff_binary_file new_file; /**< The contents of the new file. */
 } git_diff_binary;
 
 /**
-* When iterating over a diff, callback that will be made for
-* binary content within the diff.
-*/
-typedef int(*git_diff_binary_cb)(
+ * When iterating over a diff, callback that will be made for
+ * binary content within the diff.
+ */
+typedef int GIT_CALLBACK(git_diff_binary_cb)(
        const git_diff_delta *delta,
        const git_diff_binary *binary,
        void *payload);
 
 /**
  * Structure describing a hunk of a diff.
+ *
+ * A `hunk` is a span of modified lines in a delta along with some stable
+ * surrounding context. You can configure the amount of context and other
+ * properties of how hunks are generated. Each hunk also comes with a
+ * header that described where it starts and ends in both the old and new
+ * versions in the delta.
  */
 typedef struct {
        int    old_start;     /**< Starting line number in old_file */
@@ -481,13 +563,13 @@ typedef struct {
        int    new_start;     /**< Starting line number in new_file */
        int    new_lines;     /**< Number of lines in new_file */
        size_t header_len;    /**< Number of bytes in header text */
-       char   header[128];   /**< Header text, NUL-byte terminated */
+       char   header[GIT_DIFF_HUNK_HEADER_SIZE];   /**< Header text, NUL-byte terminated */
 } git_diff_hunk;
 
 /**
  * When iterating over a diff, callback that will be made per hunk.
  */
-typedef int (*git_diff_hunk_cb)(
+typedef int GIT_CALLBACK(git_diff_hunk_cb)(
        const git_diff_delta *delta,
        const git_diff_hunk *hunk,
        void *payload);
@@ -521,6 +603,14 @@ typedef enum {
 
 /**
  * Structure describing a line (or data span) of a diff.
+ *
+ * A `line` is a range of characters inside a hunk.  It could be a context
+ * line (i.e. in both old and new versions), an added line (i.e. only in
+ * the new version), or a removed line (i.e. only in the old version).
+ * Unfortunately, we don't know anything about the encoding of data in the
+ * file being diffed, so we cannot tell you much about the line content.
+ * Line data will not be NUL-byte terminated, however, because it will be
+ * just a span of bytes inside the larger file.
  */
 typedef struct {
        char   origin;       /**< A git_diff_line_t value */
@@ -540,7 +630,7 @@ typedef struct {
  * of text.  This uses some extra GIT_DIFF_LINE_... constants for output
  * of lines of file and hunk headers.
  */
-typedef int (*git_diff_line_cb)(
+typedef int GIT_CALLBACK(git_diff_line_cb)(
        const git_diff_delta *delta, /**< delta that contains this data */
        const git_diff_hunk *hunk,   /**< hunk containing this data */
        const git_diff_line *line,   /**< line data */
@@ -617,21 +707,21 @@ typedef enum {
         * GIT_DIFF_INCLUDE_UNMODIFIED flag.  If you do not want UNMODIFIED
         * records in the final result, pass this flag to have them removed.
         */
-       GIT_DIFF_FIND_REMOVE_UNMODIFIED = (1u << 16),
+       GIT_DIFF_FIND_REMOVE_UNMODIFIED = (1u << 16)
 } git_diff_find_t;
 
 /**
  * Pluggable similarity metric
  */
 typedef struct {
-       int (*file_signature)(
+       int GIT_CALLBACK(file_signature)(
                void **out, const git_diff_file *file,
                const char *fullpath, void *payload);
-       int (*buffer_signature)(
+       int GIT_CALLBACK(buffer_signature)(
                void **out, const git_diff_file *file,
                const char *buf, size_t buflen, void *payload);
-       void (*free_signature)(void *sig, void *payload);
-       int (*similarity)(int *score, void *siga, void *sigb, void *payload);
+       void GIT_CALLBACK(free_signature)(void *sig, void *payload);
+       int GIT_CALLBACK(similarity)(int *score, void *siga, void *sigb, void *payload);
        void *payload;
 } git_diff_similarity_metric;
 
@@ -639,21 +729,6 @@ typedef struct {
  * Control behavior of rename and copy detection
  *
  * These options mostly mimic parameters that can be passed to git-diff.
- *
- * - `rename_threshold` is the same as the -M option with a value
- * - `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
- * - `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
- * hashes of ranges of data in the file.  The default metric is a pretty
- * good similarity approximation that should work fairly well for both text
- * and binary data, and is pretty fast with fixed memory overhead.
  */
 typedef struct {
        unsigned int version;
@@ -665,21 +740,49 @@ typedef struct {
         */
        uint32_t flags;
 
-       /** Similarity to consider a file renamed (default 50) */
+       /**
+        * Threshold above which similar files will be considered renames.
+        * This is equivalent to the -M option. Defaults to 50.
+        */
        uint16_t rename_threshold;
-       /** Similarity of modified to be eligible rename source (default 50) */
+
+       /**
+        * Threshold below which similar files will be eligible to be a rename source.
+        * This is equivalent to the first part of the -B option. Defaults to 50.
+        */
        uint16_t rename_from_rewrite_threshold;
-       /** Similarity to consider a file a copy (default 50) */
+
+       /**
+        * Threshold above which similar files will be considered copies.
+        * This is equivalent to the -C option. Defaults to 50.
+        */
        uint16_t copy_threshold;
-       /** Similarity to split modify into delete/add pair (default 60) */
+
+       /**
+        * Threshold below which similar files will be split into a delete/add pair.
+        * This is equivalent to the last part of the -B option. Defaults to 60.
+        */
        uint16_t break_rewrite_threshold;
 
-       /** Maximum similarity sources to examine for a file (somewhat like
-        *  git-diff's `-l` option or `diff.renameLimit` config) (default 200)
+       /**
+        * Maximum number of matches to consider for a particular file.
+        *
+        * This is a little different from the `-l` option from Git because we
+        * will still process up to this many matches before abandoning the search.
+        * Defaults to 1000.
         */
        size_t rename_limit;
 
-       /** Pluggable similarity metric; pass NULL to use internal metric */
+       /**
+        * The `metric` option allows you to plug in a custom similarity metric.
+        *
+        * Set it to NULL to use the default internal metric.
+        *
+        * The default metric is based on sampling hashes of ranges of data in
+        * the file, which is a pretty good similarity approximation that should
+        * work fairly well for both text and binary data while still being
+        * pretty fast with a fixed memory overhead.
+        */
        git_diff_similarity_metric *metric;
 } git_diff_find_options;
 
@@ -687,14 +790,16 @@ typedef struct {
 #define GIT_DIFF_FIND_OPTIONS_INIT {GIT_DIFF_FIND_OPTIONS_VERSION}
 
 /**
- * Initializes a `git_diff_find_options` with default values. Equivalent to
- * creating an instance with GIT_DIFF_FIND_OPTIONS_INIT.
+ * Initialize git_diff_find_options structure
  *
- * @param opts The `git_diff_find_options` struct to initialize
- * @param version Version of struct; pass `GIT_DIFF_FIND_OPTIONS_VERSION`
+ * Initializes a `git_diff_find_options` with default values. Equivalent to creating
+ * an instance with GIT_DIFF_FIND_OPTIONS_INIT.
+ *
+ * @param opts The `git_diff_find_options` struct to initialize.
+ * @param version The struct version; pass `GIT_DIFF_FIND_OPTIONS_VERSION`.
  * @return Zero on success; -1 on failure.
  */
-GIT_EXTERN(int) git_diff_find_init_options(
+GIT_EXTERN(int) git_diff_find_options_init(
        git_diff_find_options *opts,
        unsigned int version);
 
@@ -727,13 +832,14 @@ GIT_EXTERN(void) git_diff_free(git_diff *diff);
  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
  * @param new_tree A git_tree object to diff to, or NULL for empty tree.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_tree_to_tree(
        git_diff **diff,
        git_repository *repo,
        git_tree *old_tree,
        git_tree *new_tree,
-       const git_diff_options *opts); /**< can be NULL for defaults */
+       const git_diff_options *opts);
 
 /**
  * Create a diff between a tree and repository index.
@@ -753,13 +859,14 @@ GIT_EXTERN(int) git_diff_tree_to_tree(
  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
  * @param index The index to diff with; repo index used if NULL.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_tree_to_index(
        git_diff **diff,
        git_repository *repo,
        git_tree *old_tree,
        git_index *index,
-       const git_diff_options *opts); /**< can be NULL for defaults */
+       const git_diff_options *opts);
 
 /**
  * Create a diff between the repository index and the workdir directory.
@@ -780,12 +887,13 @@ GIT_EXTERN(int) git_diff_tree_to_index(
  * @param repo The repository.
  * @param index The index to diff from; repo index used if NULL.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_index_to_workdir(
        git_diff **diff,
        git_repository *repo,
        git_index *index,
-       const git_diff_options *opts); /**< can be NULL for defaults */
+       const git_diff_options *opts);
 
 /**
  * Create a diff between a tree and the working directory.
@@ -809,12 +917,13 @@ GIT_EXTERN(int) git_diff_index_to_workdir(
  * @param repo The repository containing the tree.
  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_tree_to_workdir(
        git_diff **diff,
        git_repository *repo,
        git_tree *old_tree,
-       const git_diff_options *opts); /**< can be NULL for defaults */
+       const git_diff_options *opts);
 
 /**
  * Create a diff between a tree and the working directory using index data
@@ -828,12 +937,13 @@ GIT_EXTERN(int) git_diff_tree_to_workdir(
  * @param repo The repository containing the tree.
  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_tree_to_workdir_with_index(
        git_diff **diff,
        git_repository *repo,
        git_tree *old_tree,
-       const git_diff_options *opts); /**< can be NULL for defaults */
+       const git_diff_options *opts);
 
 /**
  * Create a diff with the difference between two index objects.
@@ -846,13 +956,14 @@ GIT_EXTERN(int) git_diff_tree_to_workdir_with_index(
  * @param old_index A git_index object to diff from.
  * @param new_index A git_index object to diff to.
  * @param opts Structure with options to influence diff or NULL for defaults.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_index_to_index(
        git_diff **diff,
        git_repository *repo,
        git_index *old_index,
        git_index *new_index,
-       const git_diff_options *opts); /**< can be NULL for defaults */
+       const git_diff_options *opts);
 
 /**
  * Merge one diff into another.
@@ -866,6 +977,7 @@ GIT_EXTERN(int) git_diff_index_to_index(
  *
  * @param onto Diff to merge into.
  * @param from Diff to merge.
+ * @return 0 or an error code.
  */
 GIT_EXTERN(int) git_diff_merge(
        git_diff *onto,
@@ -908,7 +1020,7 @@ GIT_EXTERN(size_t) git_diff_num_deltas(const git_diff *diff);
 /**
  * Query how many diff deltas are there in a diff filtered by type.
  *
- * This works just like `git_diff_entrycount()` with an extra parameter
+ * This works just like `git_diff_num_deltas()` with an extra parameter
  * that is a `git_delta_t` and returns just the count of how many deltas
  * match that particular type.
  *
@@ -1003,6 +1115,7 @@ typedef enum {
        GIT_DIFF_FORMAT_RAW          = 3u, /**< like git diff --raw */
        GIT_DIFF_FORMAT_NAME_ONLY    = 4u, /**< like git diff --name-only */
        GIT_DIFF_FORMAT_NAME_STATUS  = 5u, /**< like git diff --name-status */
+       GIT_DIFF_FORMAT_PATCH_ID     = 6u  /**< git diff as used by git patch-id */
 } git_diff_format_t;
 
 /**
@@ -1023,6 +1136,21 @@ GIT_EXTERN(int) git_diff_print(
        git_diff_line_cb print_cb,
        void *payload);
 
+/**
+ * Produce the complete formatted text output from a diff into a
+ * buffer.
+ *
+ * @param out A pointer to a user-allocated git_buf that will
+ *            contain the diff text
+ * @param diff A git_diff generated by one of the above functions.
+ * @param format A git_diff_format_t value to pick the text format.
+ * @return 0 on success or error code
+ */
+GIT_EXTERN(int) git_diff_to_buf(
+       git_buf *out,
+       git_diff *diff,
+       git_diff_format_t format);
+
 /**@}*/
 
 
@@ -1143,6 +1271,30 @@ GIT_EXTERN(int) git_diff_buffers(
        git_diff_line_cb line_cb,
        void *payload);
 
+/**
+ * Read the contents of a git patch file into a `git_diff` object.
+ *
+ * The diff object produced is similar to the one that would be
+ * produced if you actually produced it computationally by comparing
+ * two trees, however there may be subtle differences.  For example,
+ * a patch file likely contains abbreviated object IDs, so the
+ * object IDs in a `git_diff_delta` produced by this function will
+ * also be abbreviated.
+ *
+ * This function will only read patch files created by a git
+ * implementation, it will not read unified diffs produced by
+ * the `diff` program, nor any other types of patch files.
+ *
+ * @param out A pointer to a git_diff pointer that will be allocated.
+ * @param content The contents of a patch file
+ * @param content_len The length of the patch file contents
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_diff_from_buffer(
+       git_diff **out,
+       const char *content,
+       size_t content_len);
+
 /**
  * This is an opaque structure which is allocated by `git_diff_get_stats`.
  * You are responsible for releasing the object memory when done, using the
@@ -1167,13 +1319,13 @@ typedef enum {
        GIT_DIFF_STATS_NUMBER = (1u << 2),
 
        /** Extended header information such as creations, renames and mode changes, equivalent of `--summary` */
-       GIT_DIFF_STATS_INCLUDE_SUMMARY = (1u << 3),
+       GIT_DIFF_STATS_INCLUDE_SUMMARY = (1u << 3)
 } git_diff_stats_format_t;
 
 /**
- * Accumlate diff statistics for all patches.
+ * Accumulate diff statistics for all patches.
  *
- * @param out Structure containg the diff statistics.
+ * @param out Structure containing the diff statistics.
  * @param diff A git_diff generated by one of the above functions.
  * @return 0 on success; non-zero on error
  */
@@ -1232,92 +1384,53 @@ GIT_EXTERN(int) git_diff_stats_to_buf(
 GIT_EXTERN(void) git_diff_stats_free(git_diff_stats *stats);
 
 /**
- * Formatting options for diff e-mail generation
- */
-typedef enum {
-       /** Normal patch, the default */
-       GIT_DIFF_FORMAT_EMAIL_NONE = 0,
-
-       /** Don't insert "[PATCH]" in the subject header*/
-       GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0),
-
-} git_diff_format_email_flags_t;
-
-/**
- * Options for controlling the formatting of the generated e-mail.
+ * Patch ID options structure
+ *
+ * Initialize with `GIT_PATCHID_OPTIONS_INIT`. Alternatively, you can
+ * use `git_diff_patchid_options_init`.
+ *
  */
-typedef struct {
+typedef struct git_diff_patchid_options {
        unsigned int version;
+} git_diff_patchid_options;
 
-       git_diff_format_email_flags_t flags;
-
-       /** This patch number */
-       size_t patch_no;
-
-       /** Total number of patches in this series */
-       size_t total_patches;
-
-       /** id to use for the commit */
-       const git_oid *id;
-
-       /** Summary of the change */
-       const char *summary;
-
-       /** Author of the change */
-       const git_signature *author;
-} git_diff_format_email_options;
-
-#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1
-#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL}
-
-/**
- * Create an e-mail ready patch from a diff.
- *
- * @param out buffer to store the e-mail patch in
- * @param diff containing the commit
- * @param opts structure with options to influence content and formatting.
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_diff_format_email(
-       git_buf *out,
-       git_diff *diff,
-       const git_diff_format_email_options *opts);
+#define GIT_DIFF_PATCHID_OPTIONS_VERSION 1
+#define GIT_DIFF_PATCHID_OPTIONS_INIT { GIT_DIFF_PATCHID_OPTIONS_VERSION }
 
 /**
- * Create an e-mail ready patch for a commit.
+ * Initialize git_diff_patchid_options structure
  *
- * Does not support creating patches for merge commits (yet).
+ * Initializes a `git_diff_patchid_options` with default values. Equivalent to
+ * creating an instance with `GIT_DIFF_PATCHID_OPTIONS_INIT`.
  *
- * @param out buffer to store the e-mail patch in
- * @param repo containing the commit
- * @param commit pointer to up commit
- * @param patch_no patch number of the commit
- * @param total_patches total number of patches in the patch set
- * @param flags determines the formatting of the e-mail
- * @param diff_opts structure with options to influence diff or NULL for defaults.
- * @return 0 or an error code
+ * @param opts The `git_diff_patchid_options` struct to initialize.
+ * @param version The struct version; pass `GIT_DIFF_PATCHID_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
  */
-GIT_EXTERN(int) git_diff_commit_as_email(
-       git_buf *out,
-       git_repository *repo,
-       git_commit *commit,
-       size_t patch_no,
-       size_t total_patches,
-       git_diff_format_email_flags_t flags,
-       const git_diff_options *diff_opts);
+GIT_EXTERN(int) git_diff_patchid_options_init(
+       git_diff_patchid_options *opts,
+       unsigned int version);
 
 /**
- * Initializes a `git_diff_format_email_options` with default values.
- *
- * Equivalent to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
- *
- * @param opts The `git_diff_format_email_options` struct to initialize
- * @param version Version of struct; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`
- * @return Zero on success; -1 on failure.
+ * Calculate the patch ID for the given patch.
+ *
+ * Calculate a stable patch ID for the given patch by summing the
+ * hash of the file diffs, ignoring whitespace and line numbers.
+ * This can be used to derive whether two diffs are the same with
+ * a high probability.
+ *
+ * Currently, this function only calculates stable patch IDs, as
+ * defined in git-patch-id(1), and should in fact generate the
+ * same IDs as the upstream git project does.
+ *
+ * @param out Pointer where the calculated patch ID should be stored
+ * @param diff The diff to calculate the ID for
+ * @param opts Options for how to calculate the patch ID. This is
+ *  intended for future changes, as currently no options are
+ *  available.
+ * @return 0 on success, an error code otherwise.
  */
-GIT_EXTERN(int) git_diff_format_email_init_options(
-       git_diff_format_email_options *opts,
-       unsigned int version);
+GIT_EXTERN(int) git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opts);
 
 GIT_END_DECL