diff --git a/Lib/NativeBinaries/amd64/git2-711333e.dll b/Lib/NativeBinaries/amd64/git2-711333e.dll deleted file mode 100644 index 323e12fc8..000000000 Binary files a/Lib/NativeBinaries/amd64/git2-711333e.dll and /dev/null differ diff --git a/Lib/NativeBinaries/amd64/git2-711333e.pdb b/Lib/NativeBinaries/amd64/git2-711333e.pdb deleted file mode 100644 index 1f292a6f0..000000000 Binary files a/Lib/NativeBinaries/amd64/git2-711333e.pdb and /dev/null differ diff --git a/Lib/NativeBinaries/amd64/git2-e87d9d3.dll b/Lib/NativeBinaries/amd64/git2-e87d9d3.dll new file mode 100644 index 000000000..83da88eff Binary files /dev/null and b/Lib/NativeBinaries/amd64/git2-e87d9d3.dll differ diff --git a/Lib/NativeBinaries/amd64/git2-e87d9d3.pdb b/Lib/NativeBinaries/amd64/git2-e87d9d3.pdb new file mode 100644 index 000000000..6e48bedc0 Binary files /dev/null and b/Lib/NativeBinaries/amd64/git2-e87d9d3.pdb differ diff --git a/Lib/NativeBinaries/x86/git2-711333e.dll b/Lib/NativeBinaries/x86/git2-711333e.dll deleted file mode 100644 index 391470dd3..000000000 Binary files a/Lib/NativeBinaries/x86/git2-711333e.dll and /dev/null differ diff --git a/Lib/NativeBinaries/x86/git2-711333e.pdb b/Lib/NativeBinaries/x86/git2-711333e.pdb deleted file mode 100644 index 1a39368c4..000000000 Binary files a/Lib/NativeBinaries/x86/git2-711333e.pdb and /dev/null differ diff --git a/Lib/NativeBinaries/x86/git2-e87d9d3.dll b/Lib/NativeBinaries/x86/git2-e87d9d3.dll new file mode 100644 index 000000000..e4b9970fb Binary files /dev/null and b/Lib/NativeBinaries/x86/git2-e87d9d3.dll differ diff --git a/Lib/NativeBinaries/x86/git2-e87d9d3.pdb b/Lib/NativeBinaries/x86/git2-e87d9d3.pdb new file mode 100644 index 000000000..7ad183708 Binary files /dev/null and b/Lib/NativeBinaries/x86/git2-e87d9d3.pdb differ diff --git a/LibGit2Sharp.Tests/ReflogFixture.cs b/LibGit2Sharp.Tests/ReflogFixture.cs index b73333fc7..9b3b92df4 100644 --- a/LibGit2Sharp.Tests/ReflogFixture.cs +++ b/LibGit2Sharp.Tests/ReflogFixture.cs @@ -32,7 +32,7 @@ public void CanReadReflog() } [Fact] - public void CannotReadReflogOnUnknownReference() + public void ReadingReflogOfInvalidReferenceNameThrows() { using (var repo = new Repository(StandardTestRepoWorkingDirPath)) { diff --git a/LibGit2Sharp/BranchCollection.cs b/LibGit2Sharp/BranchCollection.cs index 672cf4ce0..645922e7e 100644 --- a/LibGit2Sharp/BranchCollection.cs +++ b/LibGit2Sharp/BranchCollection.cs @@ -91,8 +91,7 @@ private Branch BuildFromReferenceName(string canonicalName) /// An object that can be used to iterate through the collection. public virtual IEnumerator GetEnumerator() { - return Proxy.git_branch_foreach(repo.Handle, GitBranchType.GIT_BRANCH_LOCAL | GitBranchType.GIT_BRANCH_REMOTE, BranchToCanonicalName) - .Select(n => this[n]) + return Proxy.git_branch_iterator(repo, GitBranchType.GIT_BRANCH_LOCAL | GitBranchType.GIT_BRANCH_REMOTE) .GetEnumerator(); } @@ -203,21 +202,6 @@ private static bool LooksLikeABranchName(string referenceName) referenceName.LooksLikeRemoteTrackingBranch(); } - private static string BranchToCanonicalName(IntPtr namePtr, GitBranchType branchType) - { - string shortName = LaxUtf8Marshaler.FromNative(namePtr); - - switch (branchType) - { - case GitBranchType.GIT_BRANCH_LOCAL: - return ShortToLocalName(shortName); - case GitBranchType.GIT_BRANCH_REMOTE: - return ShortToRemoteName(shortName); - default: - return shortName; - } - } - private string DebuggerDisplay { get diff --git a/LibGit2Sharp/ContentChanges.cs b/LibGit2Sharp/ContentChanges.cs index 79214f675..01fb41751 100644 --- a/LibGit2Sharp/ContentChanges.cs +++ b/LibGit2Sharp/ContentChanges.cs @@ -80,34 +80,34 @@ private int FileCallback(GitDiffDelta delta, float progress, IntPtr payload) return 0; } - private int HunkCallback(GitDiffDelta delta, GitDiffRange range, IntPtr header, UIntPtr headerlen, IntPtr payload) + private int HunkCallback(GitDiffDelta delta, GitDiffHunk hunk, IntPtr payload) { - string decodedContent = LaxUtf8Marshaler.FromNative(header, (int)headerlen); + string decodedContent = LaxUtf8Marshaler.FromBuffer(hunk.Header, (int)hunk.HeaderLen); AppendToPatch(decodedContent); return 0; } - private int LineCallback(GitDiffDelta delta, GitDiffRange range, GitDiffLineOrigin lineorigin, IntPtr content, UIntPtr contentlen, IntPtr payload) + private int LineCallback(GitDiffDelta delta, GitDiffHunk hunk, GitDiffLine line, IntPtr payload) { - string decodedContent = LaxUtf8Marshaler.FromNative(content, (int)contentlen); + string decodedContent = LaxUtf8Marshaler.FromNative(line.content, (int)line.contentLen); string prefix; - switch (lineorigin) + switch (line.lineOrigin) { case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION: LinesAdded++; - prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin }); + prefix = Encoding.ASCII.GetString(new[] { (byte)line.lineOrigin }); break; case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION: LinesDeleted++; - prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin }); + prefix = Encoding.ASCII.GetString(new[] { (byte)line.lineOrigin }); break; case GitDiffLineOrigin.GIT_DIFF_LINE_CONTEXT: - prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin }); + prefix = Encoding.ASCII.GetString(new[] { (byte)line.lineOrigin }); break; default: diff --git a/LibGit2Sharp/Core/EncodingMarshaler.cs b/LibGit2Sharp/Core/EncodingMarshaler.cs index c2dca5585..7cc879222 100644 --- a/LibGit2Sharp/Core/EncodingMarshaler.cs +++ b/LibGit2Sharp/Core/EncodingMarshaler.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; @@ -143,6 +144,13 @@ public static string FromBuffer(Encoding encoding, byte[] buffer) length++; } + return FromBuffer(encoding, buffer, length); + } + + public static string FromBuffer(Encoding encoding, byte[] buffer, int length) + { + Debug.Assert(buffer != null); + if (length == 0) { return String.Empty; diff --git a/LibGit2Sharp/Core/GitCheckoutOpts.cs b/LibGit2Sharp/Core/GitCheckoutOpts.cs index eedec66ad..a1d562f98 100644 --- a/LibGit2Sharp/Core/GitCheckoutOpts.cs +++ b/LibGit2Sharp/Core/GitCheckoutOpts.cs @@ -118,6 +118,9 @@ internal struct GitCheckoutOpts :IDisposable public IntPtr baseline; public IntPtr target_directory; + public IntPtr our_label; + public IntPtr their_label; + public void Dispose() { if (paths == null) diff --git a/LibGit2Sharp/Core/GitDiff.cs b/LibGit2Sharp/Core/GitDiff.cs index 57e03a010..068efd356 100644 --- a/LibGit2Sharp/Core/GitDiff.cs +++ b/LibGit2Sharp/Core/GitDiff.cs @@ -7,117 +7,157 @@ namespace LibGit2Sharp.Core internal enum GitDiffOptionFlags { /// - /// Normal diff, the default. + /// Normal diff, the default /// GIT_DIFF_NORMAL = 0, + /* + * Options controlling which files will be in the diff + */ + /// - /// Reverse the sides of the diff. + /// Reverse the sides of the diff /// GIT_DIFF_REVERSE = (1 << 0), /// - /// Treat all files as text, disabling binary attributes and detection. + /// Include ignored files in the diff /// - GIT_DIFF_FORCE_TEXT = (1 << 1), + GIT_DIFF_INCLUDE_IGNORED = (1 << 1), /// - /// Ignore all whitespace. + /// 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_IGNORE_WHITESPACE = (1 << 2), + GIT_DIFF_RECURSE_IGNORED_DIRS = (1 << 2), /// - /// Ignore changes in amount of whitespace. + /// Include untracked files in the diff /// - GIT_DIFF_IGNORE_WHITESPACE_CHANGE = (1 << 3), + GIT_DIFF_INCLUDE_UNTRACKED = (1 << 3), /// - /// Ignore whitespace at end of line. + /// 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_IGNORE_WHITESPACE_EOL = (1 << 4), + GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 4), /// - /// Exclude submodules from the diff completely. + /// Include unmodified files in the diff /// - GIT_DIFF_IGNORE_SUBMODULES = (1 << 5), + GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 5), /// - /// Use the "patience diff" algorithm (currently unimplemented). + /// 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_PATIENCE = (1 << 6), + GIT_DIFF_INCLUDE_TYPECHANGE = (1 << 6), /// - /// Include ignored files in the diff list. + /// 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_IGNORED = (1 << 7), + GIT_DIFF_INCLUDE_TYPECHANGE_TREES = (1 << 7), /// - /// Include untracked files in the diff list. + /// Ignore file mode changes /// - GIT_DIFF_INCLUDE_UNTRACKED = (1 << 8), + GIT_DIFF_IGNORE_FILEMODE = (1 << 8), /// - /// Include unmodified files in the diff list. + /// Treat all submodules as unmodified /// - GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 9), + GIT_DIFF_IGNORE_SUBMODULES = (1 << 9), /// - /// Even with the GIT_DIFF_INCLUDE_UNTRACKED flag, when an untracked - /// directory is found, only a single entry for the directory is added - /// to the diff list; with this flag, all files under the directory will - /// be included, too. + /// Use case insensitive filename comparisons /// - GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 10), + 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. + /// 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 << 11), + GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1 << 12), /// - /// Use case insensitive filename comparisons. + /// 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_DELTAS_ARE_ICASE = (1 << 12), + GIT_DIFF_SKIP_BINARY_CHECK = (1 << 13), /// - /// When generating patch text, include the content of untracked files. + /// 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_INCLUDE_UNTRACKED_CONTENT = (1 << 13), + GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = (1 << 14), + + /* + * Options controlling how output will be generated + */ /// - /// 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. + /// Treat all files as text, disabling binary attributes and detection /// - GIT_DIFF_SKIP_BINARY_CHECK = (1 << 14), + GIT_DIFF_FORCE_TEXT = (1 << 20), /// - /// 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. + /// Treat all files as binary, disabling text diffs /// - GIT_DIFF_INCLUDE_TYPECHANGE = (1 << 15), + GIT_DIFF_FORCE_BINARY = (1 << 21), /// - /// 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. + /// Ignore all whitespace /// - GIT_DIFF_INCLUDE_TYPECHANGE_TREES = (1 << 16), + GIT_DIFF_IGNORE_WHITESPACE = (1 << 22), /// - /// Ignore file mode changes. + /// Ignore changes in amount of whitespace /// - GIT_DIFF_IGNORE_FILEMODE = (1 << 17), + GIT_DIFF_IGNORE_WHITESPACE_CHANGE = (1 << 23), /// - /// Even with GIT_DIFF_INCLUDE_IGNORED, an entire ignored directory - /// will be marked with only a single entry in the diff list; this flag - /// adds all files under the directory as IGNORED entries, too. + /// Ignore whitespace at end of line /// - GIT_DIFF_RECURSE_IGNORED_DIRS = (1 << 18), + 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( @@ -131,19 +171,23 @@ internal class GitDiffOptions : IDisposable { public uint Version = 1; public GitDiffOptionFlags Flags; - public ushort ContextLines; - public ushort InterhunkLines; - // NB: These are char*s to UTF8 strings, finna marshal them by hand - public IntPtr OldPrefixString; - public IntPtr NewPrefixString; + /* options controlling which files are in the diff */ + public SubmoduleIgnore IgnoreSubmodules; public GitStrArrayIn PathSpec; - public Int64 MaxSize; - 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) @@ -176,20 +220,36 @@ internal class GitDiffFile [StructLayout(LayoutKind.Sequential)] internal class GitDiffDelta { - public GitDiffFile OldFile; - public GitDiffFile NewFile; public ChangeKind Status; - public uint Similarity; public uint Flags; + public ushort Similarity; + public ushort NumberOfFiles; + public GitDiffFile OldFile; + public GitDiffFile NewFile; } [StructLayout(LayoutKind.Sequential)] - internal class GitDiffRange + internal class GitDiffHunk { public int OldStart; public int OldLines; public int NewStart; public int NewLines; + public UIntPtr HeaderLen; + + [MarshalAsAttribute(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 IntPtr content; } enum GitDiffLineOrigin : byte @@ -205,4 +265,13 @@ enum GitDiffLineOrigin : byte 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 + } } diff --git a/LibGit2Sharp/Core/GitTransferProgress.cs b/LibGit2Sharp/Core/GitTransferProgress.cs index 29456c154..911028501 100644 --- a/LibGit2Sharp/Core/GitTransferProgress.cs +++ b/LibGit2Sharp/Core/GitTransferProgress.cs @@ -12,6 +12,9 @@ internal struct GitTransferProgress public uint total_objects; public uint indexed_objects; public uint received_objects; + public uint local_objects; + public uint total_deltas; + public uint indexed_deltas; public UIntPtr received_bytes; } } diff --git a/LibGit2Sharp/Core/Handles/BranchIteratorSafeHandle.cs b/LibGit2Sharp/Core/Handles/BranchIteratorSafeHandle.cs new file mode 100644 index 000000000..6764bee66 --- /dev/null +++ b/LibGit2Sharp/Core/Handles/BranchIteratorSafeHandle.cs @@ -0,0 +1,11 @@ +namespace LibGit2Sharp.Core.Handles +{ + internal class BranchIteratorSafeHandle : SafeHandleBase + { + protected override bool ReleaseHandleImpl() + { + Proxy.git_branch_iterator_free(handle); + return true; + } + } +} diff --git a/LibGit2Sharp/Core/Handles/DiffListSafeHandle.cs b/LibGit2Sharp/Core/Handles/DiffSafeHandle.cs similarity index 59% rename from LibGit2Sharp/Core/Handles/DiffListSafeHandle.cs rename to LibGit2Sharp/Core/Handles/DiffSafeHandle.cs index 26d697ac2..fe117cba1 100644 --- a/LibGit2Sharp/Core/Handles/DiffListSafeHandle.cs +++ b/LibGit2Sharp/Core/Handles/DiffSafeHandle.cs @@ -1,10 +1,10 @@ namespace LibGit2Sharp.Core.Handles { - internal class DiffListSafeHandle : SafeHandleBase + internal class DiffSafeHandle : SafeHandleBase { protected override bool ReleaseHandleImpl() { - Proxy.git_diff_list_free(handle); + Proxy.git_diff_free(handle); return true; } } diff --git a/LibGit2Sharp/Core/NativeDllName.cs b/LibGit2Sharp/Core/NativeDllName.cs index 872975520..30d2933ad 100644 --- a/LibGit2Sharp/Core/NativeDllName.cs +++ b/LibGit2Sharp/Core/NativeDllName.cs @@ -2,6 +2,6 @@ namespace LibGit2Sharp.Core { internal static class NativeDllName { - public const string Name = "git2-711333e"; + public const string Name = "git2-e87d9d3"; } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 82600e196..0f40b959f 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -163,11 +163,14 @@ internal delegate int branch_foreach_callback( IntPtr payload); [DllImport(libgit2)] - internal static extern int git_branch_foreach( + internal static extern void git_branch_iterator_free( + IntPtr iterator); + + [DllImport(libgit2)] + internal static extern int git_branch_iterator_new( + out BranchIteratorSafeHandle iter_out, RepositorySafeHandle repo, - GitBranchType branch_type, - branch_foreach_callback branch_cb, - IntPtr payload); + GitBranchType branch_type); [DllImport(libgit2)] internal static extern int git_branch_move( @@ -176,6 +179,12 @@ internal static extern int git_branch_move( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string new_branch_name, [MarshalAs(UnmanagedType.Bool)] bool force); + [DllImport(libgit2)] + internal static extern int git_branch_next( + out ReferenceSafeHandle ref_out, + out IntPtr type_out, + BranchIteratorSafeHandle iter); + [DllImport(libgit2)] internal static extern int git_branch_remote_name( byte[] remote_name_out, @@ -353,11 +362,11 @@ internal static extern int git_cred_userpass_plaintext_new( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof (StrictUtf8Marshaler))] string password); [DllImport(libgit2)] - internal static extern void git_diff_list_free(IntPtr diff); + internal static extern void git_diff_free(IntPtr diff); [DllImport(libgit2)] internal static extern int git_diff_tree_to_tree( - out DiffListSafeHandle diff, + out DiffSafeHandle diff, RepositorySafeHandle repo, GitObjectSafeHandle oldTree, GitObjectSafeHandle newTree, @@ -365,7 +374,7 @@ internal static extern int git_diff_tree_to_tree( [DllImport(libgit2)] internal static extern int git_diff_tree_to_index( - out DiffListSafeHandle diff, + out DiffSafeHandle diff, RepositorySafeHandle repo, GitObjectSafeHandle oldTree, IndexSafeHandle index, @@ -373,19 +382,19 @@ internal static extern int git_diff_tree_to_index( [DllImport(libgit2)] internal static extern int git_diff_merge( - DiffListSafeHandle onto, - DiffListSafeHandle from); + DiffSafeHandle onto, + DiffSafeHandle from); [DllImport(libgit2)] internal static extern int git_diff_index_to_workdir( - out DiffListSafeHandle diff, + out DiffSafeHandle diff, RepositorySafeHandle repo, IndexSafeHandle index, GitDiffOptions options); [DllImport(libgit2)] internal static extern int git_diff_tree_to_workdir( - out DiffListSafeHandle diff, + out DiffSafeHandle diff, RepositorySafeHandle repo, GitObjectSafeHandle oldTree, GitDiffOptions options); @@ -397,23 +406,20 @@ internal delegate int git_diff_file_cb( internal delegate int git_diff_hunk_cb( GitDiffDelta delta, - GitDiffRange range, - IntPtr header, - UIntPtr headerLen, + GitDiffHunk hunk, IntPtr payload); - internal delegate int git_diff_data_cb( + internal delegate int git_diff_line_cb( GitDiffDelta delta, - GitDiffRange range, - GitDiffLineOrigin lineOrigin, - IntPtr content, - UIntPtr contentLen, + GitDiffHunk hunk, + GitDiffLine line, IntPtr payload); [DllImport(libgit2)] - internal static extern int git_diff_print_patch( - DiffListSafeHandle diff, - git_diff_data_cb printCallback, + internal static extern int git_diff_print( + DiffSafeHandle diff, + GitDiffFormat format, + git_diff_line_cb printCallback, IntPtr payload); [DllImport(libgit2)] @@ -425,15 +431,15 @@ internal static extern int git_diff_blobs( GitDiffOptions options, git_diff_file_cb fileCallback, git_diff_hunk_cb hunkCallback, - git_diff_data_cb lineCallback, + git_diff_line_cb lineCallback, IntPtr payload); [DllImport(libgit2)] internal static extern int git_diff_foreach( - DiffListSafeHandle diff, + DiffSafeHandle diff, git_diff_file_cb fileCallback, git_diff_hunk_cb hunkCallback, - git_diff_data_cb lineCallback, + git_diff_line_cb lineCallback, IntPtr payload); [DllImport(libgit2)] @@ -504,7 +510,7 @@ internal static extern int git_index_open( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath indexpath); [DllImport(libgit2)] - internal static extern int git_index_read(IndexSafeHandle index); + internal static extern int git_index_read(IndexSafeHandle index, bool force); [DllImport(libgit2)] internal static extern int git_index_remove_bypath( @@ -750,7 +756,8 @@ internal static extern void git_reflog_free( [DllImport(libgit2)] internal static extern int git_reflog_read( out ReflogSafeHandle ref_out, - ReferenceSafeHandle reference); + RepositorySafeHandle repo, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] internal static extern UIntPtr git_reflog_entrycount @@ -859,7 +866,7 @@ internal static extern int git_remote_add_fetch( RemoteSafeHandle remote, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof (StrictUtf8Marshaler))] string refspec); - internal delegate void remote_progress_callback(IntPtr str, int len, IntPtr data); + internal delegate int remote_progress_callback(IntPtr str, int len, IntPtr data); internal delegate int remote_completion_callback(RemoteCompletionType type, IntPtr data); diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 86a542284..3836b948b 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -7,7 +7,6 @@ using System.Threading; using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; -using LibGit2Sharp.Handlers; // ReSharper disable InconsistentNaming namespace LibGit2Sharp.Core @@ -142,12 +141,57 @@ public static void git_branch_delete(ReferenceSafeHandle reference) } } - public static ICollection git_branch_foreach( - RepositorySafeHandle repo, - GitBranchType branch_type, - Func resultSelector) + public static IEnumerable git_branch_iterator(Repository repo, GitBranchType branchType) + { + using (ThreadAffinity()) + { + BranchIteratorSafeHandle iter_out = null; + + var branches = new List(); + + try + { + Ensure.ZeroResult(NativeMethods.git_branch_iterator_new(out iter_out, repo.Handle, branchType)); + + int res = 0; + + while (res == (int)GitErrorCode.Ok) + { + ReferenceSafeHandle ref_out = null; + try + { + IntPtr type_out; + res = NativeMethods.git_branch_next(out ref_out, out type_out, iter_out); + + if (res == (int) GitErrorCode.IterOver) + { + break; + } + + Ensure.ZeroResult(res); + + var reference = Reference.BuildFromPtr(ref_out, repo); + + branches.Add(new Branch(repo, reference, reference.CanonicalName)); + } + finally + { + ref_out.SafeDispose(); + } + } + } + finally + { + iter_out.SafeDispose(); + } + + return branches; + } + } + + public static void git_branch_iterator_free(IntPtr iter) { - return git_foreach(resultSelector, c => NativeMethods.git_branch_foreach(repo, branch_type, (x, y, p) => c(x, y, p), IntPtr.Zero)); + NativeMethods.git_branch_iterator_free(iter); } public static ReferenceSafeHandle git_branch_move(ReferenceSafeHandle reference, string new_branch_name, bool force) @@ -526,7 +570,7 @@ public static void git_diff_blobs( GitDiffOptions options, NativeMethods.git_diff_file_cb fileCallback, NativeMethods.git_diff_hunk_cb hunkCallback, - NativeMethods.git_diff_data_cb lineCallback) + NativeMethods.git_diff_line_cb lineCallback) { using (ThreadAffinity()) using (var osw1 = new ObjectSafeWrapper(oldBlob, repo, true)) @@ -541,19 +585,19 @@ public static void git_diff_blobs( } public static void git_diff_foreach( - DiffListSafeHandle diff, + DiffSafeHandle diff, NativeMethods.git_diff_file_cb fileCallback, NativeMethods.git_diff_hunk_cb hunkCallback, - NativeMethods.git_diff_data_cb dataCallback) + NativeMethods.git_diff_line_cb lineCallback) { using (ThreadAffinity()) { - int res = NativeMethods.git_diff_foreach(diff, fileCallback, hunkCallback, dataCallback, IntPtr.Zero); + int res = NativeMethods.git_diff_foreach(diff, fileCallback, hunkCallback, lineCallback, IntPtr.Zero); Ensure.ZeroResult(res); } } - public static DiffListSafeHandle git_diff_tree_to_index( + public static DiffSafeHandle git_diff_tree_to_index( RepositorySafeHandle repo, IndexSafeHandle index, ObjectId oldTree, @@ -562,7 +606,7 @@ public static DiffListSafeHandle git_diff_tree_to_index( using (ThreadAffinity()) using (var osw = new ObjectSafeWrapper(oldTree, repo, true)) { - DiffListSafeHandle diff; + DiffSafeHandle diff; int res = NativeMethods.git_diff_tree_to_index(out diff, repo, osw.ObjectPtr, index, options); Ensure.ZeroResult(res); @@ -570,12 +614,12 @@ public static DiffListSafeHandle git_diff_tree_to_index( } } - public static void git_diff_list_free(IntPtr diff) + public static void git_diff_free(IntPtr diff) { - NativeMethods.git_diff_list_free(diff); + NativeMethods.git_diff_free(diff); } - public static void git_diff_merge(DiffListSafeHandle onto, DiffListSafeHandle from) + public static void git_diff_merge(DiffSafeHandle onto, DiffSafeHandle from) { using (ThreadAffinity()) { @@ -584,16 +628,17 @@ public static void git_diff_merge(DiffListSafeHandle onto, DiffListSafeHandle fr } } - public static void git_diff_print_patch(DiffListSafeHandle diff, NativeMethods.git_diff_data_cb printCallback) + public static void git_diff_print(DiffSafeHandle diff, NativeMethods.git_diff_line_cb printCallback) { using (ThreadAffinity()) { - int res = NativeMethods.git_diff_print_patch(diff, printCallback, IntPtr.Zero); + int res = NativeMethods.git_diff_print(diff, GitDiffFormat.GIT_DIFF_FORMAT_PATCH, + printCallback, IntPtr.Zero); Ensure.ZeroResult(res); } } - public static DiffListSafeHandle git_diff_tree_to_tree( + public static DiffSafeHandle git_diff_tree_to_tree( RepositorySafeHandle repo, ObjectId oldTree, ObjectId newTree, @@ -603,7 +648,7 @@ public static DiffListSafeHandle git_diff_tree_to_tree( using (var osw1 = new ObjectSafeWrapper(oldTree, repo, true)) using (var osw2 = new ObjectSafeWrapper(newTree, repo, true)) { - DiffListSafeHandle diff; + DiffSafeHandle diff; int res = NativeMethods.git_diff_tree_to_tree(out diff, repo, osw1.ObjectPtr, osw2.ObjectPtr, options); Ensure.ZeroResult(res); @@ -611,14 +656,14 @@ public static DiffListSafeHandle git_diff_tree_to_tree( } } - public static DiffListSafeHandle git_diff_index_to_workdir( + public static DiffSafeHandle git_diff_index_to_workdir( RepositorySafeHandle repo, IndexSafeHandle index, GitDiffOptions options) { using (ThreadAffinity()) { - DiffListSafeHandle diff; + DiffSafeHandle diff; int res = NativeMethods.git_diff_index_to_workdir(out diff, repo, index, options); Ensure.ZeroResult(res); @@ -626,7 +671,7 @@ public static DiffListSafeHandle git_diff_index_to_workdir( } } - public static DiffListSafeHandle git_diff_tree_to_workdir( + public static DiffSafeHandle git_diff_tree_to_workdir( RepositorySafeHandle repo, ObjectId oldTree, GitDiffOptions options) @@ -634,7 +679,7 @@ public static DiffListSafeHandle git_diff_tree_to_workdir( using (ThreadAffinity()) using (var osw = new ObjectSafeWrapper(oldTree, repo, true)) { - DiffListSafeHandle diff; + DiffSafeHandle diff; int res = NativeMethods.git_diff_tree_to_workdir(out diff, repo, osw.ObjectPtr, options); Ensure.ZeroResult(res); @@ -804,7 +849,7 @@ public static void git_index_read(IndexSafeHandle index) { using (ThreadAffinity()) { - int res = NativeMethods.git_index_read(index); + int res = NativeMethods.git_index_read(index, false); Ensure.ZeroResult(res); } } @@ -1339,13 +1384,13 @@ public static void git_reflog_free(IntPtr reflog) NativeMethods.git_reflog_free(reflog); } - public static ReflogSafeHandle git_reflog_read(ReferenceSafeHandle reference) + public static ReflogSafeHandle git_reflog_read(RepositorySafeHandle repo, string canonicalName) { using (ThreadAffinity()) { ReflogSafeHandle reflog_out; - int res = NativeMethods.git_reflog_read(out reflog_out, reference); + int res = NativeMethods.git_reflog_read(out reflog_out, repo, canonicalName); Ensure.ZeroResult(res); return reflog_out; diff --git a/LibGit2Sharp/Core/Utf8Marshaler.cs b/LibGit2Sharp/Core/Utf8Marshaler.cs index b5a61e19d..8a480816f 100644 --- a/LibGit2Sharp/Core/Utf8Marshaler.cs +++ b/LibGit2Sharp/Core/Utf8Marshaler.cs @@ -124,5 +124,10 @@ public static string FromBuffer(byte[] buffer) { return FromBuffer(encoding, buffer); } + + public static string FromBuffer(byte[] buffer, int length) + { + return FromBuffer(encoding, buffer, length); + } } } diff --git a/LibGit2Sharp/Diff.cs b/LibGit2Sharp/Diff.cs index ffe7e3fab..8a98d136c 100644 --- a/LibGit2Sharp/Diff.cs +++ b/LibGit2Sharp/Diff.cs @@ -34,7 +34,7 @@ private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[] { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED | GitDiffOptionFlags.GIT_DIFF_RECURSE_UNTRACKED_DIRS | - GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED_CONTENT; + GitDiffOptionFlags.GIT_DIFF_SHOW_UNTRACKED_CONTENT; } if (diffOptions.HasFlag(DiffModifiers.IncludeIgnored)) @@ -90,7 +90,7 @@ private static IDictionary> ChangesBuilders = new Dictionary> + private static readonly IDictionary> ChangesBuilders = new Dictionary> { { typeof(Patch), diff => new Patch(diff) }, { typeof(TreeChanges), diff => new TreeChanges(diff) }, @@ -126,7 +126,7 @@ public virtual ContentChanges Compare(Blob oldBlob, Blob newBlob, CompareOptions public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) where T : class { - Func builder; + Func builder; if (!ChangesBuilders.TryGetValue(typeof (T), out builder)) { @@ -151,10 +151,10 @@ public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable path } } - using (DiffListSafeHandle diffList = BuildDiffList(oldTreeId, newTreeId, comparer, + using (DiffSafeHandle diff = BuildDiffList(oldTreeId, newTreeId, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)) { - return (T)builder(diffList); + return (T)builder(diff); } } @@ -179,7 +179,7 @@ public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable path public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) where T : class { - Func builder; + Func builder; if (!ChangesBuilders.TryGetValue(typeof (T), out builder)) { @@ -206,10 +206,10 @@ public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable(IEnumerable paths = null, bool includeUntrac internal virtual T Compare(DiffModifiers diffOptions, IEnumerable paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) where T : class { - Func builder; + Func builder; if (!ChangesBuilders.TryGetValue(typeof (T), out builder)) { @@ -261,14 +261,14 @@ internal virtual T Compare(DiffModifiers diffOptions, IEnumerable pat } } - using (DiffListSafeHandle diffList = BuildDiffList(null, null, comparer, + using (DiffSafeHandle diff = BuildDiffList(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)) { - return (T)builder(diffList); + return (T)builder(diff); } } - internal delegate DiffListSafeHandle TreeComparisonHandleRetriever(ObjectId oldTreeId, ObjectId newTreeId, GitDiffOptions options); + internal delegate DiffSafeHandle TreeComparisonHandleRetriever(ObjectId oldTreeId, ObjectId newTreeId, GitDiffOptions options); private static TreeComparisonHandleRetriever TreeToTree(Repository repo) { @@ -289,7 +289,7 @@ private static TreeComparisonHandleRetriever WorkdirAndIndexToTree(Repository re { TreeComparisonHandleRetriever comparisonHandleRetriever = (oh, nh, o) => { - DiffListSafeHandle diff = null, diff2 = null; + DiffSafeHandle diff = null, diff2 = null; try { @@ -318,7 +318,7 @@ private static TreeComparisonHandleRetriever IndexToTree(Repository repo) return (oh, nh, o) => Proxy.git_diff_tree_to_index(repo.Handle, repo.Index.Handle, oh, o); } - private DiffListSafeHandle BuildDiffList(ObjectId oldTreeId, ObjectId newTreeId, TreeComparisonHandleRetriever comparisonHandleRetriever, + private DiffSafeHandle BuildDiffList(ObjectId oldTreeId, ObjectId newTreeId, TreeComparisonHandleRetriever comparisonHandleRetriever, DiffModifiers diffOptions, IEnumerable paths, ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) { diff --git a/LibGit2Sharp/Handlers.cs b/LibGit2Sharp/Handlers.cs index f6a798cbe..17e822ab6 100644 --- a/LibGit2Sharp/Handlers.cs +++ b/LibGit2Sharp/Handlers.cs @@ -10,7 +10,8 @@ /// text reported by the server. /// Text can be chunked at arbitrary increments (i.e. can be composed /// of a partial line of text). - public delegate void ProgressHandler(string serverProgressOutput); + /// True to continue, false to cancel. + public delegate bool ProgressHandler(string serverProgressOutput); /// /// Delegate definition to handle UpdateTips callback. diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 2e9b9d340..c0501d556 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -72,6 +72,7 @@ + @@ -182,7 +183,7 @@ - + diff --git a/LibGit2Sharp/Patch.cs b/LibGit2Sharp/Patch.cs index d3419f9de..9f227275c 100644 --- a/LibGit2Sharp/Patch.cs +++ b/LibGit2Sharp/Patch.cs @@ -30,11 +30,11 @@ public class Patch : IEnumerable protected Patch() { } - internal Patch(DiffListSafeHandle diff) + internal Patch(DiffSafeHandle diff) { - Proxy.git_diff_foreach(diff, FileCallback, null, DataCallback); + Proxy.git_diff_foreach(diff, FileCallback, null, null); - Proxy.git_diff_print_patch(diff, PrintCallBack); + Proxy.git_diff_print(diff, PrintCallBack); } private int FileCallback(GitDiffDelta delta, float progress, IntPtr payload) @@ -50,38 +50,37 @@ private void AddFileChange(GitDiffDelta delta) changes.Add(newFilePath, new ContentChanges(delta.IsBinary())); } - private int DataCallback(GitDiffDelta delta, GitDiffRange range, GitDiffLineOrigin lineOrigin, IntPtr content, - UIntPtr contentLen, IntPtr payload) + private int PrintCallBack(GitDiffDelta delta, GitDiffHunk hunk, GitDiffLine line, IntPtr payload) { + string patchPart = LaxUtf8Marshaler.FromNative(line.content, (int)line.contentLen); var filePath = LaxFilePathMarshaler.FromNative(delta.NewFile.Path); - AddLineChange(this[filePath], lineOrigin); - return 0; - } + ContentChanges currentChange = this[filePath]; + string prefix = string.Empty; - private void AddLineChange(ContentChanges currentChange, GitDiffLineOrigin lineOrigin) - { - switch (lineOrigin) + switch (line.lineOrigin) { + case GitDiffLineOrigin.GIT_DIFF_LINE_CONTEXT: + prefix = " "; + break; + case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION: linesAdded++; currentChange.LinesAdded++; + prefix = "+"; break; case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION: linesDeleted++; currentChange.LinesDeleted++; + prefix = "-"; break; } - } - private int PrintCallBack(GitDiffDelta delta, GitDiffRange range, GitDiffLineOrigin lineorigin, IntPtr content, UIntPtr contentlen, IntPtr payload) - { - string formattedoutput = LaxUtf8Marshaler.FromNative(content, (int)contentlen); - var filePath = LaxFilePathMarshaler.FromNative(delta.NewFile.Path); + string formatedOutput = string.Concat(prefix, patchPart); - fullPatchBuilder.Append(formattedoutput); - this[filePath].AppendToPatch(formattedoutput); + fullPatchBuilder.Append(formatedOutput); + this[filePath].AppendToPatch(formatedOutput); return 0; } diff --git a/LibGit2Sharp/ReflogCollection.cs b/LibGit2Sharp/ReflogCollection.cs index 03c178cc4..3f2a756d7 100644 --- a/LibGit2Sharp/ReflogCollection.cs +++ b/LibGit2Sharp/ReflogCollection.cs @@ -36,6 +36,12 @@ internal ReflogCollection(Repository repo, string canonicalName) Ensure.ArgumentNotNullOrEmptyString(canonicalName, "canonicalName"); Ensure.ArgumentNotNull(repo, "repo"); + if (!repo.Refs.IsValidName(canonicalName)) + { + throw new InvalidSpecificationException( + string.Format("The given reference name '{0}' is not valid", canonicalName)); + } + this.repo = repo; this.canonicalName = canonicalName; } @@ -53,8 +59,7 @@ public IEnumerator GetEnumerator() { var entries = new List(); - using (ReferenceSafeHandle reference = Proxy.git_reference_lookup(repo.Handle, canonicalName, true)) - using (ReflogSafeHandle reflog = Proxy.git_reflog_read(reference)) + using (ReflogSafeHandle reflog = Proxy.git_reflog_read(repo.Handle, canonicalName)) { var entriesCount = Proxy.git_reflog_entrycount(reflog); @@ -103,8 +108,7 @@ internal virtual void Append(ObjectId target, string reflogMessage, Signature co return; } - using (ReferenceSafeHandle reference = Proxy.git_reference_lookup(repo.Handle, canonicalName, true)) - using (ReflogSafeHandle reflog = Proxy.git_reflog_read(reference)) + using (ReflogSafeHandle reflog = Proxy.git_reflog_read(repo.Handle, canonicalName)) { string prettifiedMessage = Proxy.git_message_prettify(reflogMessage); Proxy.git_reflog_append(reflog, target, committer, prettifiedMessage); diff --git a/LibGit2Sharp/RemoteCallbacks.cs b/LibGit2Sharp/RemoteCallbacks.cs index 962a5d3ae..b8e851486 100644 --- a/LibGit2Sharp/RemoteCallbacks.cs +++ b/LibGit2Sharp/RemoteCallbacks.cs @@ -86,15 +86,20 @@ internal GitRemoteCallbacks GenerateCallbacks() /// IntPtr to string from libgit2 /// length of string /// IntPtr to optional payload passed back to the callback. - private void GitProgressHandler(IntPtr str, int len, IntPtr data) + /// 0 on success; a negative value to abort the process. + private int GitProgressHandler(IntPtr str, int len, IntPtr data) { ProgressHandler onProgress = Progress; + bool shouldContinue = true; + if (onProgress != null) { string message = LaxUtf8Marshaler.FromNative(str, len); - onProgress(message); + shouldContinue = onProgress(message); } + + return Proxy.ConvertResultToCancelFlag(shouldContinue); } /// diff --git a/LibGit2Sharp/SubmoduleIgnore.cs b/LibGit2Sharp/SubmoduleIgnore.cs index cae886da4..e98407295 100644 --- a/LibGit2Sharp/SubmoduleIgnore.cs +++ b/LibGit2Sharp/SubmoduleIgnore.cs @@ -9,22 +9,26 @@ public enum SubmoduleIgnore /// /// Reset to the last saved ignore rule. /// - Default = -1, + Reset = -1, + /// /// Any change or untracked == dirty /// - None = 0, + None = 1, + /// /// Dirty if tracked files change /// - Untracked = 1, + Untracked = 2, + /// /// Only dirty if HEAD moved /// - Dirty = 2, + Dirty = 3, + /// /// Never dirty /// - All = 3, + All = 4, } } diff --git a/LibGit2Sharp/TreeChanges.cs b/LibGit2Sharp/TreeChanges.cs index 3a2e79949..1f6318923 100644 --- a/LibGit2Sharp/TreeChanges.cs +++ b/LibGit2Sharp/TreeChanges.cs @@ -44,7 +44,7 @@ private static IDictionary> Bu protected TreeChanges() { } - internal TreeChanges(DiffListSafeHandle diff) + internal TreeChanges(DiffSafeHandle diff) { Proxy.git_diff_foreach(diff, FileCallback, null, null); } diff --git a/LibGit2Sharp/libgit2_hash.txt b/LibGit2Sharp/libgit2_hash.txt index 8162e425f..93cb4ec12 100644 --- a/LibGit2Sharp/libgit2_hash.txt +++ b/LibGit2Sharp/libgit2_hash.txt @@ -1 +1 @@ -711333efe1c1388c39cd76480273b4fcea18d491 +e87d9d3d4d8de9c048476387931c4ac57d1c2b73 diff --git a/libgit2 b/libgit2 index 711333efe..e87d9d3d4 160000 --- a/libgit2 +++ b/libgit2 @@ -1 +1 @@ -Subproject commit 711333efe1c1388c39cd76480273b4fcea18d491 +Subproject commit e87d9d3d4d8de9c048476387931c4ac57d1c2b73