using System;
using System.Runtime.InteropServices;
namespace LibGit2Sharp.Core
{
[Flags]
internal enum GitDiffOptionFlags
{
///
/// Normal diff, the default
///
GIT_DIFF_NORMAL = 0,
/*
* Options controlling which files will be in the diff
*/
///
/// Reverse the sides of the diff
///
GIT_DIFF_REVERSE = (1 << 0),
///
/// Include ignored files in the diff
///
GIT_DIFF_INCLUDE_IGNORED = (1 << 1),
///
/// Even with GIT_DIFF_INCLUDE_IGNORED, an entire ignored directory
/// will be marked with only a single entry in the diff; this flag
/// adds all files under the directory as IGNORED entries, too.
///
GIT_DIFF_RECURSE_IGNORED_DIRS = (1 << 2),
///
/// Include untracked files in the diff
///
GIT_DIFF_INCLUDE_UNTRACKED = (1 << 3),
///
/// Even with GIT_DIFF_INCLUDE_UNTRACKED, an entire untracked
/// directory will be marked with only a single entry in the diff
/// (a la what core Git does in `git status`); this flag adds *all*
/// files under untracked directories as UNTRACKED entries, too.
///
GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 4),
///
/// Include unmodified files in the diff
///
GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 5),
///
/// Normally, a type change between files will be converted into a
/// DELETED record for the old and an ADDED record for the new; this
/// options enabled the generation of TYPECHANGE delta records.
///
GIT_DIFF_INCLUDE_TYPECHANGE = (1 << 6),
///
/// Even with GIT_DIFF_INCLUDE_TYPECHANGE, blob->tree changes still
/// generally show as a DELETED blob. This flag tries to correctly
/// label blob->tree transitions as TYPECHANGE records with new_file's
/// mode set to tree. Note: the tree SHA will not be available.
///
GIT_DIFF_INCLUDE_TYPECHANGE_TREES = (1 << 7),
///
/// Ignore file mode changes
///
GIT_DIFF_IGNORE_FILEMODE = (1 << 8),
///
/// Treat all submodules as unmodified
///
GIT_DIFF_IGNORE_SUBMODULES = (1 << 9),
///
/// Use case insensitive filename comparisons
///
GIT_DIFF_IGNORE_CASE = (1 << 10),
///
/// 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.
///
GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1 << 12),
///
/// Disable updating of the `binary` flag in delta records. This is
/// useful when iterating over a diff if you don't need hunk and data
/// callbacks and want to avoid having to load file completely.
///
GIT_DIFF_SKIP_BINARY_CHECK = (1 << 13),
///
/// When diff finds an untracked directory, to match the behavior of
/// core Git, it scans the contents for IGNORED and UNTRACKED files.
/// If *all* contents are IGNORED, then the directory is IGNORED; if
/// any contents are not IGNORED, then the directory is UNTRACKED.
/// This is extra work that may not matter in many cases. This flag
/// turns off that scan and immediately labels an untracked directory
/// as UNTRACKED (changing the behavior to not match core Git).
///
GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = (1 << 14),
/*
* Options controlling how output will be generated
*/
///
/// Treat all files as text, disabling binary attributes and detection
///
GIT_DIFF_FORCE_TEXT = (1 << 20),
///
/// Treat all files as binary, disabling text diffs
///
GIT_DIFF_FORCE_BINARY = (1 << 21),
///
/// Ignore all whitespace
///
GIT_DIFF_IGNORE_WHITESPACE = (1 << 22),
///
/// Ignore changes in amount of whitespace
///
GIT_DIFF_IGNORE_WHITESPACE_CHANGE = (1 << 23),
///
/// Ignore whitespace at end of line
///
GIT_DIFF_IGNORE_WHITESPACE_EOL = (1 << 24),
///
/// When generating patch text, include the content of untracked
/// files. This automatically turns on GIT_DIFF_INCLUDE_UNTRACKED but
/// it does not turn on GIT_DIFF_RECURSE_UNTRACKED_DIRS. Add that
/// flag if you want the content of every single UNTRACKED file.
///
GIT_DIFF_SHOW_UNTRACKED_CONTENT = (1 << 25),
///
/// When generating output, include the names of unmodified files if
/// they are included in the git_diff. Normally these are skipped in
/// the formats that list files (e.g. name-only, name-status, raw).
/// Even with this, these will not be included in patch format.
///
GIT_DIFF_SHOW_UNMODIFIED = (1 << 26),
///
/// Use the "patience diff" algorithm
///
GIT_DIFF_PATIENCE = (1 << 28),
///
/// Take extra time to find minimal diff
///
GIT_DIFF_MINIMAL = (1 << 29),
}
internal delegate int diff_notify_cb(
IntPtr diff_so_far,
IntPtr delta_to_add,
IntPtr matched_pathspec,
IntPtr payload);
[StructLayout(LayoutKind.Sequential)]
internal class GitDiffOptions : IDisposable
{
public uint Version = 1;
public GitDiffOptionFlags Flags;
/* options controlling which files are in the diff */
public SubmoduleIgnore IgnoreSubmodules;
public GitStrArrayIn PathSpec;
public diff_notify_cb NotifyCallback;
public IntPtr NotifyPayload;
/* options controlling how to diff text is generated */
public ushort ContextLines;
public ushort InterhunkLines;
public ushort OidAbbrev;
public Int64 MaxSize;
public IntPtr OldPrefixString;
public IntPtr NewPrefixString;
public void Dispose()
{
if (PathSpec == null)
{
return;
}
PathSpec.Dispose();
}
}
[Flags]
internal enum GitDiffFlags
{
GIT_DIFF_FLAG_BINARY = (1 << 0),
GIT_DIFF_FLAG_NOT_BINARY = (1 << 1),
GIT_DIFF_FLAG_VALID_OID = (1 << 2),
}
[StructLayout(LayoutKind.Sequential)]
internal class GitDiffFile
{
public GitOid Oid;
public IntPtr Path;
public Int64 Size;
public GitDiffFlags Flags;
public UInt16 Mode;
}
[StructLayout(LayoutKind.Sequential)]
internal class GitDiffDelta
{
public ChangeKind Status;
public GitDiffFlags Flags;
public UInt16 Similarity;
public UInt16 NumberOfFiles;
public GitDiffFile OldFile;
public GitDiffFile NewFile;
}
[StructLayout(LayoutKind.Sequential)]
internal class GitDiffHunk
{
public int OldStart;
public int OldLines;
public int NewStart;
public int NewLines;
public UIntPtr HeaderLen;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] Header;
}
[StructLayout(LayoutKind.Sequential)]
internal class GitDiffLine
{
public GitDiffLineOrigin lineOrigin;
public int OldLineNo;
public int NewLineNo;
public int NumLines;
public UIntPtr contentLen;
public Int64 contentOffset;
public IntPtr content;
}
enum GitDiffLineOrigin : byte
{
GIT_DIFF_LINE_CONTEXT = 0x20, //' ',
GIT_DIFF_LINE_ADDITION = 0x2B, //'+',
GIT_DIFF_LINE_DELETION = 0x2D, //'-',
GIT_DIFF_LINE_ADD_EOFNL = 0x0A, //'\n', /**< LF was added at end of file */
GIT_DIFF_LINE_DEL_EOFNL = 0x0, //'\0', /**< LF was removed at end of file */
/* these values will only be sent to a `git_diff_output_fn` */
GIT_DIFF_LINE_FILE_HDR = 0x46, //'F',
GIT_DIFF_LINE_HUNK_HDR = 0x48, //'H',
GIT_DIFF_LINE_BINARY = 0x42, //'B',
}
enum GitDiffFormat
{
GIT_DIFF_FORMAT_PATCH = 1, // < full git diff
GIT_DIFF_FORMAT_PATCH_HEADER = 2, // < just the file headers of patch
GIT_DIFF_FORMAT_RAW = 3, // < like git diff --raw
GIT_DIFF_FORMAT_NAME_ONLY = 4, // < like git diff --name-only
GIT_DIFF_FORMAT_NAME_STATUS = 5, // < like git diff --name-status
}
[Flags]
enum GitDiffFindFlags
{
GIT_DIFF_FIND_RENAMES = (1 << 0),
// consider old side of modified for renames? (`--break-rewrites=N`)
GIT_DIFF_FIND_RENAMES_FROM_REWRITES = (1 << 1),
// look for copies? (a la `--find-copies`)
GIT_DIFF_FIND_COPIES = (1 << 2),
// consider unmodified as copy sources? (`--find-copies-harder`)
GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED = (1 << 3),
// mark large rewrites for split (`--break-rewrites=/M`)
GIT_DIFF_FIND_REWRITES = (1 << 4),
// actually split large rewrites into delete/add pairs
GIT_DIFF_BREAK_REWRITES = (1 << 5),
// mark rewrites for split and break into delete/add pairs
GIT_DIFF_FIND_AND_BREAK_REWRITES =
(GIT_DIFF_FIND_REWRITES | GIT_DIFF_BREAK_REWRITES),
// find renames/copies for untracked items in working directory
GIT_DIFF_FIND_FOR_UNTRACKED = (1 << 6),
// turn on all finding features
GIT_DIFF_FIND_ALL = (0x0ff),
// measure similarity ignoring leading whitespace (default)
GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE = 0,
// measure similarity ignoring all whitespace
GIT_DIFF_FIND_IGNORE_WHITESPACE = (1 << 12),
// measure similarity including all data
GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE = (1 << 13),
// measure similarity only by comparing SHAs (fast and cheap)
GIT_DIFF_FIND_EXACT_MATCH_ONLY = (1 << 14),
// do not break rewrites unless they contribute to a rename
GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY = (1 << 15),
// Remove any UNMODIFIED deltas after find_similar is done.
GIT_DIFF_FIND_REMOVE_UNMODIFIED = (1 << 16),
}
[StructLayout(LayoutKind.Sequential)]
internal class GitDiffFindOptions
{
public uint Version = 1;
public GitDiffFindFlags Flags;
public UInt16 RenameThreshold;
public UInt16 RenameFromRewriteThreshold;
public UInt16 CopyThreshold;
public UInt16 BreakRewriteThreshold;
public UIntPtr RenameLimit;
// TODO
public IntPtr SimilarityMetric;
}
}