Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:59:37

0001 /*
0002  * Copyright (C) the libgit2 contributors. All rights reserved.
0003  *
0004  * This file is part of libgit2, distributed under the GNU GPL v2 with
0005  * a Linking Exception. For full terms see the included COPYING file.
0006  */
0007 #ifndef INCLUDE_git_diff_h__
0008 #define INCLUDE_git_diff_h__
0009 
0010 #include "common.h"
0011 #include "types.h"
0012 #include "oid.h"
0013 #include "tree.h"
0014 #include "refs.h"
0015 
0016 /**
0017  * @file git2/diff.h
0018  * @brief Git tree and file differencing routines.
0019  * @ingroup Git
0020  * @{
0021  */
0022 GIT_BEGIN_DECL
0023 
0024 /**
0025  * Flags for diff options.  A combination of these flags can be passed
0026  * in via the `flags` value in the `git_diff_options`.
0027  */
0028 typedef enum {
0029     /** Normal diff, the default */
0030     GIT_DIFF_NORMAL = 0,
0031 
0032     /*
0033      * Options controlling which files will be in the diff
0034      */
0035 
0036     /** Reverse the sides of the diff */
0037     GIT_DIFF_REVERSE = (1u << 0),
0038 
0039     /** Include ignored files in the diff */
0040     GIT_DIFF_INCLUDE_IGNORED = (1u << 1),
0041 
0042     /** Even with GIT_DIFF_INCLUDE_IGNORED, an entire ignored directory
0043      *  will be marked with only a single entry in the diff; this flag
0044      *  adds all files under the directory as IGNORED entries, too.
0045      */
0046     GIT_DIFF_RECURSE_IGNORED_DIRS = (1u << 2),
0047 
0048     /** Include untracked files in the diff */
0049     GIT_DIFF_INCLUDE_UNTRACKED = (1u << 3),
0050 
0051     /** Even with GIT_DIFF_INCLUDE_UNTRACKED, an entire untracked
0052      *  directory will be marked with only a single entry in the diff
0053      *  (a la what core Git does in `git status`); this flag adds *all*
0054      *  files under untracked directories as UNTRACKED entries, too.
0055      */
0056     GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1u << 4),
0057 
0058     /** Include unmodified files in the diff */
0059     GIT_DIFF_INCLUDE_UNMODIFIED = (1u << 5),
0060 
0061     /** Normally, a type change between files will be converted into a
0062      *  DELETED record for the old and an ADDED record for the new; this
0063      *  options enabled the generation of TYPECHANGE delta records.
0064      */
0065     GIT_DIFF_INCLUDE_TYPECHANGE = (1u << 6),
0066 
0067     /** Even with GIT_DIFF_INCLUDE_TYPECHANGE, blob->tree changes still
0068      *  generally show as a DELETED blob.  This flag tries to correctly
0069      *  label blob->tree transitions as TYPECHANGE records with new_file's
0070      *  mode set to tree.  Note: the tree SHA will not be available.
0071      */
0072     GIT_DIFF_INCLUDE_TYPECHANGE_TREES = (1u << 7),
0073 
0074     /** Ignore file mode changes */
0075     GIT_DIFF_IGNORE_FILEMODE = (1u << 8),
0076 
0077     /** Treat all submodules as unmodified */
0078     GIT_DIFF_IGNORE_SUBMODULES = (1u << 9),
0079 
0080     /** Use case insensitive filename comparisons */
0081     GIT_DIFF_IGNORE_CASE = (1u << 10),
0082 
0083     /** May be combined with `GIT_DIFF_IGNORE_CASE` to specify that a file
0084      *  that has changed case will be returned as an add/delete pair.
0085      */
0086     GIT_DIFF_INCLUDE_CASECHANGE = (1u << 11),
0087 
0088     /** If the pathspec is set in the diff options, this flags indicates
0089      *  that the paths will be treated as literal paths instead of
0090      *  fnmatch patterns.  Each path in the list must either be a full
0091      *  path to a file or a directory.  (A trailing slash indicates that
0092      *  the path will _only_ match a directory).  If a directory is
0093      *  specified, all children will be included.
0094      */
0095     GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1u << 12),
0096 
0097     /** Disable updating of the `binary` flag in delta records.  This is
0098      *  useful when iterating over a diff if you don't need hunk and data
0099      *  callbacks and want to avoid having to load file completely.
0100      */
0101     GIT_DIFF_SKIP_BINARY_CHECK = (1u << 13),
0102 
0103     /** When diff finds an untracked directory, to match the behavior of
0104      *  core Git, it scans the contents for IGNORED and UNTRACKED files.
0105      *  If *all* contents are IGNORED, then the directory is IGNORED; if
0106      *  any contents are not IGNORED, then the directory is UNTRACKED.
0107      *  This is extra work that may not matter in many cases.  This flag
0108      *  turns off that scan and immediately labels an untracked directory
0109      *  as UNTRACKED (changing the behavior to not match core Git).
0110      */
0111     GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = (1u << 14),
0112 
0113     /** When diff finds a file in the working directory with stat
0114      * information different from the index, but the OID ends up being the
0115      * same, write the correct stat information into the index.  Note:
0116      * without this flag, diff will always leave the index untouched.
0117      */
0118     GIT_DIFF_UPDATE_INDEX = (1u << 15),
0119 
0120     /** Include unreadable files in the diff */
0121     GIT_DIFF_INCLUDE_UNREADABLE = (1u << 16),
0122 
0123     /** Include unreadable files in the diff */
0124     GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 17),
0125 
0126     /*
0127      * Options controlling how output will be generated
0128      */
0129 
0130     /** Use a heuristic that takes indentation and whitespace into account
0131      * which generally can produce better diffs when dealing with ambiguous
0132      * diff hunks.
0133      */
0134     GIT_DIFF_INDENT_HEURISTIC = (1u << 18),
0135 
0136     /** Ignore blank lines */
0137     GIT_DIFF_IGNORE_BLANK_LINES = (1u << 19),
0138 
0139     /** Treat all files as text, disabling binary attributes & detection */
0140     GIT_DIFF_FORCE_TEXT = (1u << 20),
0141     /** Treat all files as binary, disabling text diffs */
0142     GIT_DIFF_FORCE_BINARY = (1u << 21),
0143 
0144     /** Ignore all whitespace */
0145     GIT_DIFF_IGNORE_WHITESPACE = (1u << 22),
0146     /** Ignore changes in amount of whitespace */
0147     GIT_DIFF_IGNORE_WHITESPACE_CHANGE = (1u << 23),
0148     /** Ignore whitespace at end of line */
0149     GIT_DIFF_IGNORE_WHITESPACE_EOL = (1u << 24),
0150 
0151     /** When generating patch text, include the content of untracked
0152      *  files.  This automatically turns on GIT_DIFF_INCLUDE_UNTRACKED but
0153      *  it does not turn on GIT_DIFF_RECURSE_UNTRACKED_DIRS.  Add that
0154      *  flag if you want the content of every single UNTRACKED file.
0155      */
0156     GIT_DIFF_SHOW_UNTRACKED_CONTENT = (1u << 25),
0157 
0158     /** When generating output, include the names of unmodified files if
0159      *  they are included in the git_diff.  Normally these are skipped in
0160      *  the formats that list files (e.g. name-only, name-status, raw).
0161      *  Even with this, these will not be included in patch format.
0162      */
0163     GIT_DIFF_SHOW_UNMODIFIED = (1u << 26),
0164 
0165     /** Use the "patience diff" algorithm */
0166     GIT_DIFF_PATIENCE = (1u << 28),
0167     /** Take extra time to find minimal diff */
0168     GIT_DIFF_MINIMAL = (1u << 29),
0169 
0170     /** Include the necessary deflate / delta information so that `git-apply`
0171      *  can apply given diff information to binary files.
0172      */
0173     GIT_DIFF_SHOW_BINARY = (1u << 30)
0174 } git_diff_option_t;
0175 
0176 /**
0177  * The diff object that contains all individual file deltas.
0178  *
0179  * A `diff` represents the cumulative list of differences between two
0180  * snapshots of a repository (possibly filtered by a set of file name
0181  * patterns).
0182  *
0183  * Calculating diffs is generally done in two phases: building a list of
0184  * diffs then traversing it. This makes is easier to share logic across
0185  * the various types of diffs (tree vs tree, workdir vs index, etc.), and
0186  * also allows you to insert optional diff post-processing phases,
0187  * such as rename detection, in between the steps. When you are done with
0188  * a diff object, it must be freed.
0189  *
0190  * This is an opaque structure which will be allocated by one of the diff
0191  * generator functions below (such as `git_diff_tree_to_tree`). You are
0192  * responsible for releasing the object memory when done, using the
0193  * `git_diff_free()` function.
0194  *
0195  */
0196 typedef struct git_diff git_diff;
0197 
0198 /**
0199  * Flags for the delta object and the file objects on each side.
0200  *
0201  * These flags are used for both the `flags` value of the `git_diff_delta`
0202  * and the flags for the `git_diff_file` objects representing the old and
0203  * new sides of the delta.  Values outside of this public range should be
0204  * considered reserved for internal or future use.
0205  */
0206 typedef enum {
0207     GIT_DIFF_FLAG_BINARY     = (1u << 0), /**< file(s) treated as binary data */
0208     GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */
0209     GIT_DIFF_FLAG_VALID_ID   = (1u << 2), /**< `id` value is known correct */
0210     GIT_DIFF_FLAG_EXISTS     = (1u << 3), /**< file exists at this side of the delta */
0211     GIT_DIFF_FLAG_VALID_SIZE = (1u << 4)  /**< file size value is known correct */
0212 } git_diff_flag_t;
0213 
0214 /**
0215  * What type of change is described by a git_diff_delta?
0216  *
0217  * `GIT_DELTA_RENAMED` and `GIT_DELTA_COPIED` will only show up if you run
0218  * `git_diff_find_similar()` on the diff object.
0219  *
0220  * `GIT_DELTA_TYPECHANGE` only shows up given `GIT_DIFF_INCLUDE_TYPECHANGE`
0221  * in the option flags (otherwise type changes will be split into ADDED /
0222  * DELETED pairs).
0223  */
0224 typedef enum {
0225     GIT_DELTA_UNMODIFIED = 0,  /**< no changes */
0226     GIT_DELTA_ADDED = 1,       /**< entry does not exist in old version */
0227     GIT_DELTA_DELETED = 2,     /**< entry does not exist in new version */
0228     GIT_DELTA_MODIFIED = 3,    /**< entry content changed between old and new */
0229     GIT_DELTA_RENAMED = 4,     /**< entry was renamed between old and new */
0230     GIT_DELTA_COPIED = 5,      /**< entry was copied from another old entry */
0231     GIT_DELTA_IGNORED = 6,     /**< entry is ignored item in workdir */
0232     GIT_DELTA_UNTRACKED = 7,   /**< entry is untracked item in workdir */
0233     GIT_DELTA_TYPECHANGE = 8,  /**< type of entry changed between old and new */
0234     GIT_DELTA_UNREADABLE = 9,  /**< entry is unreadable */
0235     GIT_DELTA_CONFLICTED = 10  /**< entry in the index is conflicted */
0236 } git_delta_t;
0237 
0238 /**
0239  * Description of one side of a delta.
0240  *
0241  * Although this is called a "file", it could represent a file, a symbolic
0242  * link, a submodule commit id, or even a tree (although that only if you
0243  * are tracking type changes or ignored/untracked directories).
0244  */
0245 typedef struct {
0246     /**
0247      * The `git_oid` of the item.  If the entry represents an
0248      * absent side of a diff (e.g. the `old_file` of a `GIT_DELTA_ADDED` delta),
0249      * then the oid will be zeroes.
0250      */
0251     git_oid            id;
0252 
0253     /**
0254      * The NUL-terminated path to the entry relative to the working
0255      * directory of the repository.
0256      */
0257     const char        *path;
0258 
0259     /**
0260      * The size of the entry in bytes.
0261      */
0262     git_object_size_t  size;
0263 
0264     /**
0265      * A combination of the `git_diff_flag_t` types
0266      */
0267     uint32_t           flags;
0268 
0269     /**
0270      * Roughly, the stat() `st_mode` value for the item.  This will
0271      * be restricted to one of the `git_filemode_t` values.
0272      */
0273     uint16_t           mode;
0274 
0275     /**
0276      * Represents the known length of the `id` field, when
0277      * converted to a hex string.  It is generally `GIT_OID_SHA1_HEXSIZE`, unless this
0278      * delta was created from reading a patch file, in which case it may be
0279      * abbreviated to something reasonable, like 7 characters.
0280      */
0281     uint16_t           id_abbrev;
0282 } git_diff_file;
0283 
0284 /**
0285  * Description of changes to one entry.
0286  *
0287  * A `delta` is a file pair with an old and new revision.  The old version
0288  * may be absent if the file was just created and the new version may be
0289  * absent if the file was deleted.  A diff is mostly just a list of deltas.
0290  *
0291  * When iterating over a diff, this will be passed to most callbacks and
0292  * you can use the contents to understand exactly what has changed.
0293  *
0294  * The `old_file` represents the "from" side of the diff and the `new_file`
0295  * represents to "to" side of the diff.  What those means depend on the
0296  * function that was used to generate the diff and will be documented below.
0297  * You can also use the `GIT_DIFF_REVERSE` flag to flip it around.
0298  *
0299  * Although the two sides of the delta are named "old_file" and "new_file",
0300  * they actually may correspond to entries that represent a file, a symbolic
0301  * link, a submodule commit id, or even a tree (if you are tracking type
0302  * changes or ignored/untracked directories).
0303  *
0304  * Under some circumstances, in the name of efficiency, not all fields will
0305  * be filled in, but we generally try to fill in as much as possible.  One
0306  * example is that the "flags" field may not have either the `BINARY` or the
0307  * `NOT_BINARY` flag set to avoid examining file contents if you do not pass
0308  * in hunk and/or line callbacks to the diff foreach iteration function.  It
0309  * will just use the git attributes for those files.
0310  *
0311  * The similarity score is zero unless you call `git_diff_find_similar()`
0312  * which does a similarity analysis of files in the diff.  Use that
0313  * function to do rename and copy detection, and to split heavily modified
0314  * files in add/delete pairs.  After that call, deltas with a status of
0315  * GIT_DELTA_RENAMED or GIT_DELTA_COPIED will have a similarity score
0316  * between 0 and 100 indicating how similar the old and new sides are.
0317  *
0318  * If you ask `git_diff_find_similar` to find heavily modified files to
0319  * break, but to not *actually* break the records, then GIT_DELTA_MODIFIED
0320  * records may have a non-zero similarity score if the self-similarity is
0321  * below the split threshold.  To display this value like core Git, invert
0322  * the score (a la `printf("M%03d", 100 - delta->similarity)`).
0323  */
0324 typedef struct {
0325     git_delta_t   status;
0326     uint32_t      flags;       /**< git_diff_flag_t values */
0327     uint16_t      similarity;  /**< for RENAMED and COPIED, value 0-100 */
0328     uint16_t      nfiles;      /**< number of files in this delta */
0329     git_diff_file old_file;
0330     git_diff_file new_file;
0331 } git_diff_delta;
0332 
0333 /**
0334  * Diff notification callback function.
0335  *
0336  * The callback will be called for each file, just before the `git_diff_delta`
0337  * gets inserted into the diff.
0338  *
0339  * When the callback:
0340  * - returns < 0, the diff process will be aborted.
0341  * - returns > 0, the delta will not be inserted into the diff, but the
0342  *      diff process continues.
0343  * - returns 0, the delta is inserted into the diff, and the diff process
0344  *      continues.
0345  */
0346 typedef int GIT_CALLBACK(git_diff_notify_cb)(
0347     const git_diff *diff_so_far,
0348     const git_diff_delta *delta_to_add,
0349     const char *matched_pathspec,
0350     void *payload);
0351 
0352 /**
0353  * Diff progress callback.
0354  *
0355  * Called before each file comparison.
0356  *
0357  * @param diff_so_far The diff being generated.
0358  * @param old_path The path to the old file or NULL.
0359  * @param new_path The path to the new file or NULL.
0360  * @return Non-zero to abort the diff.
0361  */
0362 typedef int GIT_CALLBACK(git_diff_progress_cb)(
0363     const git_diff *diff_so_far,
0364     const char *old_path,
0365     const char *new_path,
0366     void *payload);
0367 
0368 /**
0369  * Structure describing options about how the diff should be executed.
0370  *
0371  * Setting all values of the structure to zero will yield the default
0372  * values.  Similarly, passing NULL for the options structure will
0373  * give the defaults.  The default values are marked below.
0374  *
0375  */
0376 typedef struct {
0377     unsigned int version;      /**< version for the struct */
0378 
0379     /**
0380      * A combination of `git_diff_option_t` values above.
0381      * Defaults to GIT_DIFF_NORMAL
0382      */
0383     uint32_t flags;
0384 
0385     /* options controlling which files are in the diff */
0386 
0387     /** Overrides the submodule ignore setting for all submodules in the diff. */
0388     git_submodule_ignore_t ignore_submodules;
0389 
0390     /**
0391      * An array of paths / fnmatch patterns to constrain diff.
0392      * All paths are included by default.
0393      */
0394     git_strarray       pathspec;
0395 
0396     /**
0397      * An optional callback function, notifying the consumer of changes to
0398      * the diff as new deltas are added.
0399      */
0400     git_diff_notify_cb   notify_cb;
0401 
0402     /**
0403      * An optional callback function, notifying the consumer of which files
0404      * are being examined as the diff is generated.
0405      */
0406     git_diff_progress_cb progress_cb;
0407 
0408     /** The payload to pass to the callback functions. */
0409     void                *payload;
0410 
0411     /* options controlling how to diff text is generated */
0412 
0413     /**
0414      * The number of unchanged lines that define the boundary of a hunk
0415      * (and to display before and after). Defaults to 3.
0416      */
0417     uint32_t    context_lines;
0418     /**
0419      * The maximum number of unchanged lines between hunk boundaries before
0420      * the hunks will be merged into one. Defaults to 0.
0421      */
0422     uint32_t    interhunk_lines;
0423 
0424     /**
0425      * The object ID type to emit in diffs; this is used by functions
0426      * that operate without a repository - namely `git_diff_buffers`,
0427      * or `git_diff_blobs` and `git_diff_blob_to_buffer` when one blob
0428      * is `NULL`.
0429      *
0430      * This may be omitted (set to `0`). If a repository is available,
0431      * the object ID format of the repository will be used. If no
0432      * repository is available then the default is `GIT_OID_SHA`.
0433      *
0434      * If this is specified and a repository is available, then the
0435      * specified `oid_type` must match the repository's object ID
0436      * format.
0437      */
0438     git_oid_t   oid_type;
0439 
0440     /**
0441      * The abbreviation length to use when formatting object ids.
0442      * Defaults to the value of 'core.abbrev' from the config, or 7 if unset.
0443      */
0444     uint16_t    id_abbrev;
0445 
0446     /**
0447      * A size (in bytes) above which a blob will be marked as binary
0448      * automatically; pass a negative value to disable.
0449      * Defaults to 512MB.
0450      */
0451     git_off_t   max_size;
0452 
0453     /**
0454      * The virtual "directory" prefix for old file names in hunk headers.
0455      * Default is "a".
0456      */
0457     const char *old_prefix;
0458 
0459     /**
0460      * The virtual "directory" prefix for new file names in hunk headers.
0461      * Defaults to "b".
0462      */
0463     const char *new_prefix;
0464 } git_diff_options;
0465 
0466 /* The current version of the diff options structure */
0467 #define GIT_DIFF_OPTIONS_VERSION 1
0468 
0469 /* Stack initializer for diff options.  Alternatively use
0470  * `git_diff_options_init` programmatic initialization.
0471  */
0472 #define GIT_DIFF_OPTIONS_INIT \
0473     {GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_UNSPECIFIED, {NULL,0}, NULL, NULL, NULL, 3}
0474 
0475 /**
0476  * Initialize git_diff_options structure
0477  *
0478  * Initializes a `git_diff_options` with default values. Equivalent to creating
0479  * an instance with GIT_DIFF_OPTIONS_INIT.
0480  *
0481  * @param opts The `git_diff_options` struct to initialize.
0482  * @param version The struct version; pass `GIT_DIFF_OPTIONS_VERSION`.
0483  * @return Zero on success; -1 on failure.
0484  */
0485 GIT_EXTERN(int) git_diff_options_init(
0486     git_diff_options *opts,
0487     unsigned int version);
0488 
0489 /**
0490  * When iterating over a diff, callback that will be made per file.
0491  *
0492  * @param delta A pointer to the delta data for the file
0493  * @param progress Goes from 0 to 1 over the diff
0494  * @param payload User-specified pointer from foreach function
0495  */
0496 typedef int GIT_CALLBACK(git_diff_file_cb)(
0497     const git_diff_delta *delta,
0498     float progress,
0499     void *payload);
0500 
0501 #define GIT_DIFF_HUNK_HEADER_SIZE   128
0502 
0503 /**
0504  * When producing a binary diff, the binary data returned will be
0505  * either the deflated full ("literal") contents of the file, or
0506  * the deflated binary delta between the two sides (whichever is
0507  * smaller).
0508  */
0509 typedef enum {
0510     /** There is no binary delta. */
0511     GIT_DIFF_BINARY_NONE,
0512 
0513     /** The binary data is the literal contents of the file. */
0514     GIT_DIFF_BINARY_LITERAL,
0515 
0516     /** The binary data is the delta from one side to the other. */
0517     GIT_DIFF_BINARY_DELTA
0518 } git_diff_binary_t;
0519 
0520 /** The contents of one of the files in a binary diff. */
0521 typedef struct {
0522     /** The type of binary data for this file. */
0523     git_diff_binary_t type;
0524 
0525     /** The binary data, deflated. */
0526     const char *data;
0527 
0528     /** The length of the binary data. */
0529     size_t datalen;
0530 
0531     /** The length of the binary data after inflation. */
0532     size_t inflatedlen;
0533 } git_diff_binary_file;
0534 
0535 /**
0536  * Structure describing the binary contents of a diff.
0537  *
0538  * A `binary` file / delta is a file (or pair) for which no text diffs
0539  * should be generated. A diff can contain delta entries that are
0540  * binary, but no diff content will be output for those files. There is
0541  * a base heuristic for binary detection and you can further tune the
0542  * behavior with git attributes or diff flags and option settings.
0543  */
0544 typedef struct {
0545     /**
0546      * Whether there is data in this binary structure or not.
0547      *
0548      * If this is `1`, then this was produced and included binary content.
0549      * If this is `0` then this was generated knowing only that a binary
0550      * file changed but without providing the data, probably from a patch
0551      * that said `Binary files a/file.txt and b/file.txt differ`.
0552      */
0553     unsigned int contains_data;
0554     git_diff_binary_file old_file; /**< The contents of the old file. */
0555     git_diff_binary_file new_file; /**< The contents of the new file. */
0556 } git_diff_binary;
0557 
0558 /**
0559  * When iterating over a diff, callback that will be made for
0560  * binary content within the diff.
0561  */
0562 typedef int GIT_CALLBACK(git_diff_binary_cb)(
0563     const git_diff_delta *delta,
0564     const git_diff_binary *binary,
0565     void *payload);
0566 
0567 /**
0568  * Structure describing a hunk of a diff.
0569  *
0570  * A `hunk` is a span of modified lines in a delta along with some stable
0571  * surrounding context. You can configure the amount of context and other
0572  * properties of how hunks are generated. Each hunk also comes with a
0573  * header that described where it starts and ends in both the old and new
0574  * versions in the delta.
0575  */
0576 typedef struct {
0577     int    old_start;     /**< Starting line number in old_file */
0578     int    old_lines;     /**< Number of lines in old_file */
0579     int    new_start;     /**< Starting line number in new_file */
0580     int    new_lines;     /**< Number of lines in new_file */
0581     size_t header_len;    /**< Number of bytes in header text */
0582     char   header[GIT_DIFF_HUNK_HEADER_SIZE];   /**< Header text, NUL-byte terminated */
0583 } git_diff_hunk;
0584 
0585 /**
0586  * When iterating over a diff, callback that will be made per hunk.
0587  */
0588 typedef int GIT_CALLBACK(git_diff_hunk_cb)(
0589     const git_diff_delta *delta,
0590     const git_diff_hunk *hunk,
0591     void *payload);
0592 
0593 /**
0594  * Line origin constants.
0595  *
0596  * These values describe where a line came from and will be passed to
0597  * the git_diff_line_cb when iterating over a diff.  There are some
0598  * special origin constants at the end that are used for the text
0599  * output callbacks to demarcate lines that are actually part of
0600  * the file or hunk headers.
0601  */
0602 typedef enum {
0603     /* These values will be sent to `git_diff_line_cb` along with the line */
0604     GIT_DIFF_LINE_CONTEXT   = ' ',
0605     GIT_DIFF_LINE_ADDITION  = '+',
0606     GIT_DIFF_LINE_DELETION  = '-',
0607 
0608     GIT_DIFF_LINE_CONTEXT_EOFNL = '=', /**< Both files have no LF at end */
0609     GIT_DIFF_LINE_ADD_EOFNL = '>',     /**< Old has no LF at end, new does */
0610     GIT_DIFF_LINE_DEL_EOFNL = '<',     /**< Old has LF at end, new does not */
0611 
0612     /* The following values will only be sent to a `git_diff_line_cb` when
0613      * the content of a diff is being formatted through `git_diff_print`.
0614      */
0615     GIT_DIFF_LINE_FILE_HDR  = 'F',
0616     GIT_DIFF_LINE_HUNK_HDR  = 'H',
0617     GIT_DIFF_LINE_BINARY    = 'B' /**< For "Binary files x and y differ" */
0618 } git_diff_line_t;
0619 
0620 /**
0621  * Structure describing a line (or data span) of a diff.
0622  *
0623  * A `line` is a range of characters inside a hunk.  It could be a context
0624  * line (i.e. in both old and new versions), an added line (i.e. only in
0625  * the new version), or a removed line (i.e. only in the old version).
0626  * Unfortunately, we don't know anything about the encoding of data in the
0627  * file being diffed, so we cannot tell you much about the line content.
0628  * Line data will not be NUL-byte terminated, however, because it will be
0629  * just a span of bytes inside the larger file.
0630  */
0631 typedef struct {
0632     char   origin;       /**< A git_diff_line_t value */
0633     int    old_lineno;   /**< Line number in old file or -1 for added line */
0634     int    new_lineno;   /**< Line number in new file or -1 for deleted line */
0635     int    num_lines;    /**< Number of newline characters in content */
0636     size_t content_len;  /**< Number of bytes of data */
0637     git_off_t content_offset; /**< Offset in the original file to the content */
0638     const char *content; /**< Pointer to diff text, not NUL-byte terminated */
0639 } git_diff_line;
0640 
0641 /**
0642  * When iterating over a diff, callback that will be made per text diff
0643  * line. In this context, the provided range will be NULL.
0644  *
0645  * When printing a diff, callback that will be made to output each line
0646  * of text.  This uses some extra GIT_DIFF_LINE_... constants for output
0647  * of lines of file and hunk headers.
0648  */
0649 typedef int GIT_CALLBACK(git_diff_line_cb)(
0650     const git_diff_delta *delta, /**< delta that contains this data */
0651     const git_diff_hunk *hunk,   /**< hunk containing this data */
0652     const git_diff_line *line,   /**< line data */
0653     void *payload);              /**< user reference data */
0654 
0655 /**
0656  * Flags to control the behavior of diff rename/copy detection.
0657  */
0658 typedef enum {
0659     /** Obey `diff.renames`. Overridden by any other GIT_DIFF_FIND_... flag. */
0660     GIT_DIFF_FIND_BY_CONFIG = 0,
0661 
0662     /** Look for renames? (`--find-renames`) */
0663     GIT_DIFF_FIND_RENAMES = (1u << 0),
0664 
0665     /** Consider old side of MODIFIED for renames? (`--break-rewrites=N`) */
0666     GIT_DIFF_FIND_RENAMES_FROM_REWRITES = (1u << 1),
0667 
0668     /** Look for copies? (a la `--find-copies`). */
0669     GIT_DIFF_FIND_COPIES = (1u << 2),
0670 
0671     /** Consider UNMODIFIED as copy sources? (`--find-copies-harder`).
0672      *
0673      * For this to work correctly, use GIT_DIFF_INCLUDE_UNMODIFIED when
0674      * the initial `git_diff` is being generated.
0675      */
0676     GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED = (1u << 3),
0677 
0678     /** Mark significant rewrites for split (`--break-rewrites=/M`) */
0679     GIT_DIFF_FIND_REWRITES = (1u << 4),
0680     /** Actually split large rewrites into delete/add pairs */
0681     GIT_DIFF_BREAK_REWRITES = (1u << 5),
0682     /** Mark rewrites for split and break into delete/add pairs */
0683     GIT_DIFF_FIND_AND_BREAK_REWRITES =
0684         (GIT_DIFF_FIND_REWRITES | GIT_DIFF_BREAK_REWRITES),
0685 
0686     /** Find renames/copies for UNTRACKED items in working directory.
0687      *
0688      * For this to work correctly, use GIT_DIFF_INCLUDE_UNTRACKED when the
0689      * initial `git_diff` is being generated (and obviously the diff must
0690      * be against the working directory for this to make sense).
0691      */
0692     GIT_DIFF_FIND_FOR_UNTRACKED = (1u << 6),
0693 
0694     /** Turn on all finding features. */
0695     GIT_DIFF_FIND_ALL = (0x0ff),
0696 
0697     /** Measure similarity ignoring leading whitespace (default) */
0698     GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE = 0,
0699     /** Measure similarity ignoring all whitespace */
0700     GIT_DIFF_FIND_IGNORE_WHITESPACE = (1u << 12),
0701     /** Measure similarity including all data */
0702     GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE = (1u << 13),
0703     /** Measure similarity only by comparing SHAs (fast and cheap) */
0704     GIT_DIFF_FIND_EXACT_MATCH_ONLY = (1u << 14),
0705 
0706     /** Do not break rewrites unless they contribute to a rename.
0707      *
0708      * Normally, GIT_DIFF_FIND_AND_BREAK_REWRITES will measure the self-
0709      * similarity of modified files and split the ones that have changed a
0710      * lot into a DELETE / ADD pair.  Then the sides of that pair will be
0711      * considered candidates for rename and copy detection.
0712      *
0713      * If you add this flag in and the split pair is *not* used for an
0714      * actual rename or copy, then the modified record will be restored to
0715      * a regular MODIFIED record instead of being split.
0716      */
0717     GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY  = (1u << 15),
0718 
0719     /** Remove any UNMODIFIED deltas after find_similar is done.
0720      *
0721      * Using GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED to emulate the
0722      * --find-copies-harder behavior requires building a diff with the
0723      * GIT_DIFF_INCLUDE_UNMODIFIED flag.  If you do not want UNMODIFIED
0724      * records in the final result, pass this flag to have them removed.
0725      */
0726     GIT_DIFF_FIND_REMOVE_UNMODIFIED = (1u << 16)
0727 } git_diff_find_t;
0728 
0729 /**
0730  * Pluggable similarity metric
0731  */
0732 typedef struct {
0733     int GIT_CALLBACK(file_signature)(
0734         void **out, const git_diff_file *file,
0735         const char *fullpath, void *payload);
0736     int GIT_CALLBACK(buffer_signature)(
0737         void **out, const git_diff_file *file,
0738         const char *buf, size_t buflen, void *payload);
0739     void GIT_CALLBACK(free_signature)(void *sig, void *payload);
0740     int GIT_CALLBACK(similarity)(int *score, void *siga, void *sigb, void *payload);
0741     void *payload;
0742 } git_diff_similarity_metric;
0743 
0744 /**
0745  * Control behavior of rename and copy detection
0746  *
0747  * These options mostly mimic parameters that can be passed to git-diff.
0748  */
0749 typedef struct {
0750     unsigned int version;
0751 
0752     /**
0753      * Combination of git_diff_find_t values (default GIT_DIFF_FIND_BY_CONFIG).
0754      * NOTE: if you don't explicitly set this, `diff.renames` could be set
0755      * to false, resulting in `git_diff_find_similar` doing nothing.
0756      */
0757     uint32_t flags;
0758 
0759     /**
0760      * Threshold above which similar files will be considered renames.
0761      * This is equivalent to the -M option. Defaults to 50.
0762      */
0763     uint16_t rename_threshold;
0764 
0765     /**
0766      * Threshold below which similar files will be eligible to be a rename source.
0767      * This is equivalent to the first part of the -B option. Defaults to 50.
0768      */
0769     uint16_t rename_from_rewrite_threshold;
0770 
0771     /**
0772      * Threshold above which similar files will be considered copies.
0773      * This is equivalent to the -C option. Defaults to 50.
0774      */
0775     uint16_t copy_threshold;
0776 
0777     /**
0778      * Threshold below which similar files will be split into a delete/add pair.
0779      * This is equivalent to the last part of the -B option. Defaults to 60.
0780      */
0781     uint16_t break_rewrite_threshold;
0782 
0783     /**
0784      * Maximum number of matches to consider for a particular file.
0785      *
0786      * This is a little different from the `-l` option from Git because we
0787      * will still process up to this many matches before abandoning the search.
0788      * Defaults to 1000.
0789      */
0790     size_t rename_limit;
0791 
0792     /**
0793      * The `metric` option allows you to plug in a custom similarity metric.
0794      *
0795      * Set it to NULL to use the default internal metric.
0796      *
0797      * The default metric is based on sampling hashes of ranges of data in
0798      * the file, which is a pretty good similarity approximation that should
0799      * work fairly well for both text and binary data while still being
0800      * pretty fast with a fixed memory overhead.
0801      */
0802     git_diff_similarity_metric *metric;
0803 } git_diff_find_options;
0804 
0805 #define GIT_DIFF_FIND_OPTIONS_VERSION 1
0806 #define GIT_DIFF_FIND_OPTIONS_INIT {GIT_DIFF_FIND_OPTIONS_VERSION}
0807 
0808 /**
0809  * Initialize git_diff_find_options structure
0810  *
0811  * Initializes a `git_diff_find_options` with default values. Equivalent to creating
0812  * an instance with GIT_DIFF_FIND_OPTIONS_INIT.
0813  *
0814  * @param opts The `git_diff_find_options` struct to initialize.
0815  * @param version The struct version; pass `GIT_DIFF_FIND_OPTIONS_VERSION`.
0816  * @return Zero on success; -1 on failure.
0817  */
0818 GIT_EXTERN(int) git_diff_find_options_init(
0819     git_diff_find_options *opts,
0820     unsigned int version);
0821 
0822 /** @name Diff Generator Functions
0823  *
0824  * These are the functions you would use to create (or destroy) a
0825  * git_diff from various objects in a repository.
0826  */
0827 /**@{*/
0828 
0829 /**
0830  * Deallocate a diff.
0831  *
0832  * @param diff The previously created diff; cannot be used after free.
0833  */
0834 GIT_EXTERN(void) git_diff_free(git_diff *diff);
0835 
0836 /**
0837  * Create a diff with the difference between two tree objects.
0838  *
0839  * This is equivalent to `git diff <old-tree> <new-tree>`
0840  *
0841  * The first tree will be used for the "old_file" side of the delta and the
0842  * second tree will be used for the "new_file" side of the delta.  You can
0843  * pass NULL to indicate an empty tree, although it is an error to pass
0844  * NULL for both the `old_tree` and `new_tree`.
0845  *
0846  * @param diff Output pointer to a git_diff pointer to be allocated.
0847  * @param repo The repository containing the trees.
0848  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
0849  * @param new_tree A git_tree object to diff to, or NULL for empty tree.
0850  * @param opts Structure with options to influence diff or NULL for defaults.
0851  * @return 0 or an error code.
0852  */
0853 GIT_EXTERN(int) git_diff_tree_to_tree(
0854     git_diff **diff,
0855     git_repository *repo,
0856     git_tree *old_tree,
0857     git_tree *new_tree,
0858     const git_diff_options *opts);
0859 
0860 /**
0861  * Create a diff between a tree and repository index.
0862  *
0863  * This is equivalent to `git diff --cached <treeish>` or if you pass
0864  * the HEAD tree, then like `git diff --cached`.
0865  *
0866  * The tree you pass will be used for the "old_file" side of the delta, and
0867  * the index will be used for the "new_file" side of the delta.
0868  *
0869  * If you pass NULL for the index, then the existing index of the `repo`
0870  * will be used.  In this case, the index will be refreshed from disk
0871  * (if it has changed) before the diff is generated.
0872  *
0873  * @param diff Output pointer to a git_diff pointer to be allocated.
0874  * @param repo The repository containing the tree and index.
0875  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
0876  * @param index The index to diff with; repo index used if NULL.
0877  * @param opts Structure with options to influence diff or NULL for defaults.
0878  * @return 0 or an error code.
0879  */
0880 GIT_EXTERN(int) git_diff_tree_to_index(
0881     git_diff **diff,
0882     git_repository *repo,
0883     git_tree *old_tree,
0884     git_index *index,
0885     const git_diff_options *opts);
0886 
0887 /**
0888  * Create a diff between the repository index and the workdir directory.
0889  *
0890  * This matches the `git diff` command.  See the note below on
0891  * `git_diff_tree_to_workdir` for a discussion of the difference between
0892  * `git diff` and `git diff HEAD` and how to emulate a `git diff <treeish>`
0893  * using libgit2.
0894  *
0895  * The index will be used for the "old_file" side of the delta, and the
0896  * working directory will be used for the "new_file" side of the delta.
0897  *
0898  * If you pass NULL for the index, then the existing index of the `repo`
0899  * will be used.  In this case, the index will be refreshed from disk
0900  * (if it has changed) before the diff is generated.
0901  *
0902  * @param diff Output pointer to a git_diff pointer to be allocated.
0903  * @param repo The repository.
0904  * @param index The index to diff from; repo index used if NULL.
0905  * @param opts Structure with options to influence diff or NULL for defaults.
0906  * @return 0 or an error code.
0907  */
0908 GIT_EXTERN(int) git_diff_index_to_workdir(
0909     git_diff **diff,
0910     git_repository *repo,
0911     git_index *index,
0912     const git_diff_options *opts);
0913 
0914 /**
0915  * Create a diff between a tree and the working directory.
0916  *
0917  * The tree you provide will be used for the "old_file" side of the delta,
0918  * and the working directory will be used for the "new_file" side.
0919  *
0920  * This is not the same as `git diff <treeish>` or `git diff-index
0921  * <treeish>`.  Those commands use information from the index, whereas this
0922  * function strictly returns the differences between the tree and the files
0923  * in the working directory, regardless of the state of the index.  Use
0924  * `git_diff_tree_to_workdir_with_index` to emulate those commands.
0925  *
0926  * To see difference between this and `git_diff_tree_to_workdir_with_index`,
0927  * consider the example of a staged file deletion where the file has then
0928  * been put back into the working dir and further modified.  The
0929  * tree-to-workdir diff for that file is 'modified', but `git diff` would
0930  * show status 'deleted' since there is a staged delete.
0931  *
0932  * @param diff A pointer to a git_diff pointer that will be allocated.
0933  * @param repo The repository containing the tree.
0934  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
0935  * @param opts Structure with options to influence diff or NULL for defaults.
0936  * @return 0 or an error code.
0937  */
0938 GIT_EXTERN(int) git_diff_tree_to_workdir(
0939     git_diff **diff,
0940     git_repository *repo,
0941     git_tree *old_tree,
0942     const git_diff_options *opts);
0943 
0944 /**
0945  * Create a diff between a tree and the working directory using index data
0946  * to account for staged deletes, tracked files, etc.
0947  *
0948  * This emulates `git diff <tree>` by diffing the tree to the index and
0949  * the index to the working directory and blending the results into a
0950  * single diff that includes staged deleted, etc.
0951  *
0952  * @param diff A pointer to a git_diff pointer that will be allocated.
0953  * @param repo The repository containing the tree.
0954  * @param old_tree A git_tree object to diff from, or NULL for empty tree.
0955  * @param opts Structure with options to influence diff or NULL for defaults.
0956  * @return 0 or an error code.
0957  */
0958 GIT_EXTERN(int) git_diff_tree_to_workdir_with_index(
0959     git_diff **diff,
0960     git_repository *repo,
0961     git_tree *old_tree,
0962     const git_diff_options *opts);
0963 
0964 /**
0965  * Create a diff with the difference between two index objects.
0966  *
0967  * The first index will be used for the "old_file" side of the delta and the
0968  * second index will be used for the "new_file" side of the delta.
0969  *
0970  * @param diff Output pointer to a git_diff pointer to be allocated.
0971  * @param repo The repository containing the indexes.
0972  * @param old_index A git_index object to diff from.
0973  * @param new_index A git_index object to diff to.
0974  * @param opts Structure with options to influence diff or NULL for defaults.
0975  * @return 0 or an error code.
0976  */
0977 GIT_EXTERN(int) git_diff_index_to_index(
0978     git_diff **diff,
0979     git_repository *repo,
0980     git_index *old_index,
0981     git_index *new_index,
0982     const git_diff_options *opts);
0983 
0984 /**
0985  * Merge one diff into another.
0986  *
0987  * This merges items from the "from" list into the "onto" list.  The
0988  * resulting diff will have all items that appear in either list.
0989  * If an item appears in both lists, then it will be "merged" to appear
0990  * as if the old version was from the "onto" list and the new version
0991  * is from the "from" list (with the exception that if the item has a
0992  * pending DELETE in the middle, then it will show as deleted).
0993  *
0994  * @param onto Diff to merge into.
0995  * @param from Diff to merge.
0996  * @return 0 or an error code.
0997  */
0998 GIT_EXTERN(int) git_diff_merge(
0999     git_diff *onto,
1000     const git_diff *from);
1001 
1002 /**
1003  * Transform a diff marking file renames, copies, etc.
1004  *
1005  * This modifies a diff in place, replacing old entries that look
1006  * like renames or copies with new entries reflecting those changes.
1007  * This also will, if requested, break modified files into add/remove
1008  * pairs if the amount of change is above a threshold.
1009  *
1010  * @param diff diff to run detection algorithms on
1011  * @param options Control how detection should be run, NULL for defaults
1012  * @return 0 on success, -1 on failure
1013  */
1014 GIT_EXTERN(int) git_diff_find_similar(
1015     git_diff *diff,
1016     const git_diff_find_options *options);
1017 
1018 /**@}*/
1019 
1020 
1021 /** @name Diff Processor Functions
1022  *
1023  * These are the functions you apply to a diff to process it
1024  * or read it in some way.
1025  */
1026 /**@{*/
1027 
1028 /**
1029  * Query how many diff records are there in a diff.
1030  *
1031  * @param diff A git_diff generated by one of the above functions
1032  * @return Count of number of deltas in the list
1033  */
1034 GIT_EXTERN(size_t) git_diff_num_deltas(const git_diff *diff);
1035 
1036 /**
1037  * Query how many diff deltas are there in a diff filtered by type.
1038  *
1039  * This works just like `git_diff_num_deltas()` with an extra parameter
1040  * that is a `git_delta_t` and returns just the count of how many deltas
1041  * match that particular type.
1042  *
1043  * @param diff A git_diff generated by one of the above functions
1044  * @param type A git_delta_t value to filter the count
1045  * @return Count of number of deltas matching delta_t type
1046  */
1047 GIT_EXTERN(size_t) git_diff_num_deltas_of_type(
1048     const git_diff *diff, git_delta_t type);
1049 
1050 /**
1051  * Return the diff delta for an entry in the diff list.
1052  *
1053  * The `git_diff_delta` pointer points to internal data and you do not
1054  * have to release it when you are done with it.  It will go away when
1055  * the * `git_diff` (or any associated `git_patch`) goes away.
1056  *
1057  * Note that the flags on the delta related to whether it has binary
1058  * content or not may not be set if there are no attributes set for the
1059  * file and there has been no reason to load the file data at this point.
1060  * For now, if you need those flags to be up to date, your only option is
1061  * to either use `git_diff_foreach` or create a `git_patch`.
1062  *
1063  * @param diff Diff list object
1064  * @param idx Index into diff list
1065  * @return Pointer to git_diff_delta (or NULL if `idx` out of range)
1066  */
1067 GIT_EXTERN(const git_diff_delta *) git_diff_get_delta(
1068     const git_diff *diff, size_t idx);
1069 
1070 /**
1071  * Check if deltas are sorted case sensitively or insensitively.
1072  *
1073  * @param diff diff to check
1074  * @return 0 if case sensitive, 1 if case is ignored
1075  */
1076 GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff);
1077 
1078 /**
1079  * Loop over all deltas in a diff issuing callbacks.
1080  *
1081  * This will iterate through all of the files described in a diff.  You
1082  * should provide a file callback to learn about each file.
1083  *
1084  * The "hunk" and "line" callbacks are optional, and the text diff of the
1085  * files will only be calculated if they are not NULL.  Of course, these
1086  * callbacks will not be invoked for binary files on the diff or for
1087  * files whose only changed is a file mode change.
1088  *
1089  * Returning a non-zero value from any of the callbacks will terminate
1090  * the iteration and return the value to the user.
1091  *
1092  * @param diff A git_diff generated by one of the above functions.
1093  * @param file_cb Callback function to make per file in the diff.
1094  * @param binary_cb Optional callback to make for binary files.
1095  * @param hunk_cb Optional callback to make per hunk of text diff.  This
1096  *                callback is called to describe a range of lines in the
1097  *                diff.  It will not be issued for binary files.
1098  * @param line_cb Optional callback to make per line of diff text.  This
1099  *                same callback will be made for context lines, added, and
1100  *                removed lines, and even for a deleted trailing newline.
1101  * @param payload Reference pointer that will be passed to your callbacks.
1102  * @return 0 on success, non-zero callback return value, or error code
1103  */
1104 GIT_EXTERN(int) git_diff_foreach(
1105     git_diff *diff,
1106     git_diff_file_cb file_cb,
1107     git_diff_binary_cb binary_cb,
1108     git_diff_hunk_cb hunk_cb,
1109     git_diff_line_cb line_cb,
1110     void *payload);
1111 
1112 /**
1113  * Look up the single character abbreviation for a delta status code.
1114  *
1115  * When you run `git diff --name-status` it uses single letter codes in
1116  * the output such as 'A' for added, 'D' for deleted, 'M' for modified,
1117  * etc.  This function converts a git_delta_t value into these letters for
1118  * your own purposes.  GIT_DELTA_UNTRACKED will return a space (i.e. ' ').
1119  *
1120  * @param status The git_delta_t value to look up
1121  * @return The single character label for that code
1122  */
1123 GIT_EXTERN(char) git_diff_status_char(git_delta_t status);
1124 
1125 /**
1126  * Possible output formats for diff data
1127  */
1128 typedef enum {
1129     GIT_DIFF_FORMAT_PATCH        = 1u, /**< full git diff */
1130     GIT_DIFF_FORMAT_PATCH_HEADER = 2u, /**< just the file headers of patch */
1131     GIT_DIFF_FORMAT_RAW          = 3u, /**< like git diff --raw */
1132     GIT_DIFF_FORMAT_NAME_ONLY    = 4u, /**< like git diff --name-only */
1133     GIT_DIFF_FORMAT_NAME_STATUS  = 5u, /**< like git diff --name-status */
1134     GIT_DIFF_FORMAT_PATCH_ID     = 6u  /**< git diff as used by git patch-id */
1135 } git_diff_format_t;
1136 
1137 /**
1138  * Iterate over a diff generating formatted text output.
1139  *
1140  * Returning a non-zero value from the callbacks will terminate the
1141  * iteration and return the non-zero value to the caller.
1142  *
1143  * @param diff A git_diff generated by one of the above functions.
1144  * @param format A git_diff_format_t value to pick the text format.
1145  * @param print_cb Callback to make per line of diff text.
1146  * @param payload Reference pointer that will be passed to your callback.
1147  * @return 0 on success, non-zero callback return value, or error code
1148  */
1149 GIT_EXTERN(int) git_diff_print(
1150     git_diff *diff,
1151     git_diff_format_t format,
1152     git_diff_line_cb print_cb,
1153     void *payload);
1154 
1155 /**
1156  * Produce the complete formatted text output from a diff into a
1157  * buffer.
1158  *
1159  * @param out A pointer to a user-allocated git_buf that will
1160  *            contain the diff text
1161  * @param diff A git_diff generated by one of the above functions.
1162  * @param format A git_diff_format_t value to pick the text format.
1163  * @return 0 on success or error code
1164  */
1165 GIT_EXTERN(int) git_diff_to_buf(
1166     git_buf *out,
1167     git_diff *diff,
1168     git_diff_format_t format);
1169 
1170 /**@}*/
1171 
1172 /*
1173  * Low-level file comparison, invoking callbacks per difference.
1174  */
1175 
1176 /**
1177  * Directly run a diff on two blobs.
1178  *
1179  * Compared to a file, a blob lacks some contextual information. As such,
1180  * the `git_diff_file` given to the callback will have some fake data; i.e.
1181  * `mode` will be 0 and `path` will be NULL.
1182  *
1183  * NULL is allowed for either `old_blob` or `new_blob` and will be treated
1184  * as an empty blob, with the `oid` set to NULL in the `git_diff_file` data.
1185  * Passing NULL for both blobs is a noop; no callbacks will be made at all.
1186  *
1187  * We do run a binary content check on the blob content and if either blob
1188  * looks like binary data, the `git_diff_delta` binary attribute will be set
1189  * to 1 and no call to the hunk_cb nor line_cb will be made (unless you pass
1190  * `GIT_DIFF_FORCE_TEXT` of course).
1191  *
1192  * @param old_blob Blob for old side of diff, or NULL for empty blob
1193  * @param old_as_path Treat old blob as if it had this filename; can be NULL
1194  * @param new_blob Blob for new side of diff, or NULL for empty blob
1195  * @param new_as_path Treat new blob as if it had this filename; can be NULL
1196  * @param options Options for diff, or NULL for default options
1197  * @param file_cb Callback for "file"; made once if there is a diff; can be NULL
1198  * @param binary_cb Callback for binary files; can be NULL
1199  * @param hunk_cb Callback for each hunk in diff; can be NULL
1200  * @param line_cb Callback for each line in diff; can be NULL
1201  * @param payload Payload passed to each callback function
1202  * @return 0 on success, non-zero callback return value, or error code
1203  */
1204 GIT_EXTERN(int) git_diff_blobs(
1205     const git_blob *old_blob,
1206     const char *old_as_path,
1207     const git_blob *new_blob,
1208     const char *new_as_path,
1209     const git_diff_options *options,
1210     git_diff_file_cb file_cb,
1211     git_diff_binary_cb binary_cb,
1212     git_diff_hunk_cb hunk_cb,
1213     git_diff_line_cb line_cb,
1214     void *payload);
1215 
1216 /**
1217  * Directly run a diff between a blob and a buffer.
1218  *
1219  * As with `git_diff_blobs`, comparing a blob and buffer lacks some context,
1220  * so the `git_diff_file` parameters to the callbacks will be faked a la the
1221  * rules for `git_diff_blobs()`.
1222  *
1223  * Passing NULL for `old_blob` will be treated as an empty blob (i.e. the
1224  * `file_cb` will be invoked with GIT_DELTA_ADDED and the diff will be the
1225  * entire content of the buffer added).  Passing NULL to the buffer will do
1226  * the reverse, with GIT_DELTA_REMOVED and blob content removed.
1227  *
1228  * @param old_blob Blob for old side of diff, or NULL for empty blob
1229  * @param old_as_path Treat old blob as if it had this filename; can be NULL
1230  * @param buffer Raw data for new side of diff, or NULL for empty
1231  * @param buffer_len Length of raw data for new side of diff
1232  * @param buffer_as_path Treat buffer as if it had this filename; can be NULL
1233  * @param options Options for diff, or NULL for default options
1234  * @param file_cb Callback for "file"; made once if there is a diff; can be NULL
1235  * @param binary_cb Callback for binary files; can be NULL
1236  * @param hunk_cb Callback for each hunk in diff; can be NULL
1237  * @param line_cb Callback for each line in diff; can be NULL
1238  * @param payload Payload passed to each callback function
1239  * @return 0 on success, non-zero callback return value, or error code
1240  */
1241 GIT_EXTERN(int) git_diff_blob_to_buffer(
1242     const git_blob *old_blob,
1243     const char *old_as_path,
1244     const char *buffer,
1245     size_t buffer_len,
1246     const char *buffer_as_path,
1247     const git_diff_options *options,
1248     git_diff_file_cb file_cb,
1249     git_diff_binary_cb binary_cb,
1250     git_diff_hunk_cb hunk_cb,
1251     git_diff_line_cb line_cb,
1252     void *payload);
1253 
1254 /**
1255  * Directly run a diff between two buffers.
1256  *
1257  * Even more than with `git_diff_blobs`, comparing two buffer lacks
1258  * context, so the `git_diff_file` parameters to the callbacks will be
1259  * faked a la the rules for `git_diff_blobs()`.
1260  *
1261  * @param old_buffer Raw data for old side of diff, or NULL for empty
1262  * @param old_len Length of the raw data for old side of the diff
1263  * @param old_as_path Treat old buffer as if it had this filename; can be NULL
1264  * @param new_buffer Raw data for new side of diff, or NULL for empty
1265  * @param new_len Length of raw data for new side of diff
1266  * @param new_as_path Treat buffer as if it had this filename; can be NULL
1267  * @param options Options for diff, or NULL for default options
1268  * @param file_cb Callback for "file"; made once if there is a diff; can be NULL
1269  * @param binary_cb Callback for binary files; can be NULL
1270  * @param hunk_cb Callback for each hunk in diff; can be NULL
1271  * @param line_cb Callback for each line in diff; can be NULL
1272  * @param payload Payload passed to each callback function
1273  * @return 0 on success, non-zero callback return value, or error code
1274  */
1275 GIT_EXTERN(int) git_diff_buffers(
1276     const void *old_buffer,
1277     size_t old_len,
1278     const char *old_as_path,
1279     const void *new_buffer,
1280     size_t new_len,
1281     const char *new_as_path,
1282     const git_diff_options *options,
1283     git_diff_file_cb file_cb,
1284     git_diff_binary_cb binary_cb,
1285     git_diff_hunk_cb hunk_cb,
1286     git_diff_line_cb line_cb,
1287     void *payload);
1288 
1289 /* Patch file parsing. */
1290 
1291 /**
1292  * Options for parsing a diff / patch file.
1293  */
1294 typedef struct {
1295     unsigned int version;
1296     git_oid_t oid_type;
1297 } git_diff_parse_options;
1298 
1299 /* The current version of the diff parse options structure */
1300 #define GIT_DIFF_PARSE_OPTIONS_VERSION 1
1301 
1302 /* Stack initializer for diff parse options.  Alternatively use
1303  * `git_diff_parse_options_init` programmatic initialization.
1304  */
1305 #define GIT_DIFF_PARSE_OPTIONS_INIT \
1306     { GIT_DIFF_PARSE_OPTIONS_VERSION, GIT_OID_DEFAULT }
1307 
1308 /**
1309  * Read the contents of a git patch file into a `git_diff` object.
1310  *
1311  * The diff object produced is similar to the one that would be
1312  * produced if you actually produced it computationally by comparing
1313  * two trees, however there may be subtle differences.  For example,
1314  * a patch file likely contains abbreviated object IDs, so the
1315  * object IDs in a `git_diff_delta` produced by this function will
1316  * also be abbreviated.
1317  *
1318  * This function will only read patch files created by a git
1319  * implementation, it will not read unified diffs produced by
1320  * the `diff` program, nor any other types of patch files.
1321  *
1322  * @param out A pointer to a git_diff pointer that will be allocated.
1323  * @param content The contents of a patch file
1324  * @param content_len The length of the patch file contents
1325  * @return 0 or an error code
1326  */
1327 GIT_EXTERN(int) git_diff_from_buffer(
1328     git_diff **out,
1329     const char *content,
1330     size_t content_len
1331 #ifdef GIT_EXPERIMENTAL_SHA256
1332     , git_diff_parse_options *opts
1333 #endif
1334     );
1335 
1336 /**
1337  * This is an opaque structure which is allocated by `git_diff_get_stats`.
1338  * You are responsible for releasing the object memory when done, using the
1339  * `git_diff_stats_free()` function.
1340  */
1341 typedef struct git_diff_stats git_diff_stats;
1342 
1343 /**
1344  * Formatting options for diff stats
1345  */
1346 typedef enum {
1347     /** No stats*/
1348     GIT_DIFF_STATS_NONE = 0,
1349 
1350     /** Full statistics, equivalent of `--stat` */
1351     GIT_DIFF_STATS_FULL = (1u << 0),
1352 
1353     /** Short statistics, equivalent of `--shortstat` */
1354     GIT_DIFF_STATS_SHORT = (1u << 1),
1355 
1356     /** Number statistics, equivalent of `--numstat` */
1357     GIT_DIFF_STATS_NUMBER = (1u << 2),
1358 
1359     /** Extended header information such as creations, renames and mode changes, equivalent of `--summary` */
1360     GIT_DIFF_STATS_INCLUDE_SUMMARY = (1u << 3)
1361 } git_diff_stats_format_t;
1362 
1363 /**
1364  * Accumulate diff statistics for all patches.
1365  *
1366  * @param out Structure containing the diff statistics.
1367  * @param diff A git_diff generated by one of the above functions.
1368  * @return 0 on success; non-zero on error
1369  */
1370 GIT_EXTERN(int) git_diff_get_stats(
1371     git_diff_stats **out,
1372     git_diff *diff);
1373 
1374 /**
1375  * Get the total number of files changed in a diff
1376  *
1377  * @param stats A `git_diff_stats` generated by one of the above functions.
1378  * @return total number of files changed in the diff
1379  */
1380 GIT_EXTERN(size_t) git_diff_stats_files_changed(
1381     const git_diff_stats *stats);
1382 
1383 /**
1384  * Get the total number of insertions in a diff
1385  *
1386  * @param stats A `git_diff_stats` generated by one of the above functions.
1387  * @return total number of insertions in the diff
1388  */
1389 GIT_EXTERN(size_t) git_diff_stats_insertions(
1390     const git_diff_stats *stats);
1391 
1392 /**
1393  * Get the total number of deletions in a diff
1394  *
1395  * @param stats A `git_diff_stats` generated by one of the above functions.
1396  * @return total number of deletions in the diff
1397  */
1398 GIT_EXTERN(size_t) git_diff_stats_deletions(
1399     const git_diff_stats *stats);
1400 
1401 /**
1402  * Print diff statistics to a `git_buf`.
1403  *
1404  * @param out buffer to store the formatted diff statistics in.
1405  * @param stats A `git_diff_stats` generated by one of the above functions.
1406  * @param format Formatting option.
1407  * @param width Target width for output (only affects GIT_DIFF_STATS_FULL)
1408  * @return 0 on success; non-zero on error
1409  */
1410 GIT_EXTERN(int) git_diff_stats_to_buf(
1411     git_buf *out,
1412     const git_diff_stats *stats,
1413     git_diff_stats_format_t format,
1414     size_t width);
1415 
1416 /**
1417  * Deallocate a `git_diff_stats`.
1418  *
1419  * @param stats The previously created statistics object;
1420  * cannot be used after free.
1421  */
1422 GIT_EXTERN(void) git_diff_stats_free(git_diff_stats *stats);
1423 
1424 /**
1425  * Patch ID options structure
1426  *
1427  * Initialize with `GIT_PATCHID_OPTIONS_INIT`. Alternatively, you can
1428  * use `git_diff_patchid_options_init`.
1429  *
1430  */
1431 typedef struct git_diff_patchid_options {
1432     unsigned int version;
1433 } git_diff_patchid_options;
1434 
1435 #define GIT_DIFF_PATCHID_OPTIONS_VERSION 1
1436 #define GIT_DIFF_PATCHID_OPTIONS_INIT { GIT_DIFF_PATCHID_OPTIONS_VERSION }
1437 
1438 /**
1439  * Initialize git_diff_patchid_options structure
1440  *
1441  * Initializes a `git_diff_patchid_options` with default values. Equivalent to
1442  * creating an instance with `GIT_DIFF_PATCHID_OPTIONS_INIT`.
1443  *
1444  * @param opts The `git_diff_patchid_options` struct to initialize.
1445  * @param version The struct version; pass `GIT_DIFF_PATCHID_OPTIONS_VERSION`.
1446  * @return Zero on success; -1 on failure.
1447  */
1448 GIT_EXTERN(int) git_diff_patchid_options_init(
1449     git_diff_patchid_options *opts,
1450     unsigned int version);
1451 
1452 /**
1453  * Calculate the patch ID for the given patch.
1454  *
1455  * Calculate a stable patch ID for the given patch by summing the
1456  * hash of the file diffs, ignoring whitespace and line numbers.
1457  * This can be used to derive whether two diffs are the same with
1458  * a high probability.
1459  *
1460  * Currently, this function only calculates stable patch IDs, as
1461  * defined in git-patch-id(1), and should in fact generate the
1462  * same IDs as the upstream git project does.
1463  *
1464  * @param out Pointer where the calculated patch ID should be stored
1465  * @param diff The diff to calculate the ID for
1466  * @param opts Options for how to calculate the patch ID. This is
1467  *  intended for future changes, as currently no options are
1468  *  available.
1469  * @return 0 on success, an error code otherwise.
1470  */
1471 GIT_EXTERN(int) git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opts);
1472 
1473 GIT_END_DECL
1474 
1475 /** @} */
1476 
1477 #endif