diff --git a/LibGit2Sharp/Core/Ensure.cs b/LibGit2Sharp/Core/Ensure.cs index fe5266bb6..55ecf7fe8 100644 --- a/LibGit2Sharp/Core/Ensure.cs +++ b/LibGit2Sharp/Core/Ensure.cs @@ -62,26 +62,19 @@ public static void Success(int result, bool allowPositiveResult = false) return; } - string errorMessage; - GitError error = NativeMethods.giterr_last().MarshalAsGitError(); - - + var error = NativeMethods.giterr_last(); if (error == null) { - error = new GitError { Klass = GitErrorType.Unknown, Message = IntPtr.Zero }; - errorMessage = "No error message has been provided by the native library"; - } - else - { - errorMessage = Utf8Marshaler.FromNative(error.Message); + throw new LibGit2SharpException( + (GitErrorCode)result, + GitErrorCategory.Unknown, + "No error message has been provided by the native library"); } throw new LibGit2SharpException( - String.Format(CultureInfo.InvariantCulture, "An error was raised by libgit2. Class = {0} ({1}).{2}{3}", - error.Klass, - result, - Environment.NewLine, - errorMessage)); + (GitErrorCode)result, + error.Category, + Utf8Marshaler.FromNative(error.Message)); } /// @@ -108,8 +101,8 @@ public static void GitObjectIsNotNull(GitObject gitObject, string identifier) } throw new LibGit2SharpException(string.Format(CultureInfo.InvariantCulture, - "No valid git object identified by '{0}' exists in the repository.", - identifier)); + "No valid git object identified by '{0}' exists in the repository.", + identifier)); } } } diff --git a/LibGit2Sharp/Core/GitError.cs b/LibGit2Sharp/Core/GitError.cs index 3c75b0589..0041097da 100644 --- a/LibGit2Sharp/Core/GitError.cs +++ b/LibGit2Sharp/Core/GitError.cs @@ -7,6 +7,6 @@ namespace LibGit2Sharp.Core internal class GitError { public IntPtr Message; - public GitErrorType Klass; + public GitErrorCategory Category; } } diff --git a/LibGit2Sharp/Core/GitErrorType.cs b/LibGit2Sharp/Core/GitErrorCategory.cs similarity index 90% rename from LibGit2Sharp/Core/GitErrorType.cs rename to LibGit2Sharp/Core/GitErrorCategory.cs index 96835ccb0..afda14891 100644 --- a/LibGit2Sharp/Core/GitErrorType.cs +++ b/LibGit2Sharp/Core/GitErrorCategory.cs @@ -1,6 +1,6 @@ namespace LibGit2Sharp.Core { - internal enum GitErrorType + public enum GitErrorCategory { Unknown = -1, NoMemory, diff --git a/LibGit2Sharp/Core/GitErrorCode.cs b/LibGit2Sharp/Core/GitErrorCode.cs index d536c0328..5da44fb74 100644 --- a/LibGit2Sharp/Core/GitErrorCode.cs +++ b/LibGit2Sharp/Core/GitErrorCode.cs @@ -1,6 +1,6 @@ namespace LibGit2Sharp.Core { - internal enum GitErrorCode + public enum GitErrorCode { Ok = 0, Error = -1, diff --git a/LibGit2Sharp/Core/GitErrorMarshaler.cs b/LibGit2Sharp/Core/GitErrorMarshaler.cs new file mode 100644 index 000000000..b3ba7a425 --- /dev/null +++ b/LibGit2Sharp/Core/GitErrorMarshaler.cs @@ -0,0 +1,47 @@ +using System; +using System.Runtime.InteropServices; + +namespace LibGit2Sharp.Core +{ + internal class GitErrorMarshaler : ICustomMarshaler + { + static readonly GitErrorMarshaler staticInstance = new GitErrorMarshaler(); + + public void CleanUpManagedData(object managedObj) + { + } + + public void CleanUpNativeData(IntPtr pNativeData) + { + if (pNativeData != IntPtr.Zero) + { + Marshal.FreeHGlobal(pNativeData); + } + } + + public int GetNativeDataSize() + { + return -1; + } + + public IntPtr MarshalManagedToNative(object managedObj) + { + throw new NotImplementedException(); + } + + public object MarshalNativeToManaged(IntPtr pNativeData) + { + return NativeToGitError(pNativeData); + } + + protected GitError NativeToGitError(IntPtr pNativeData) + { + return (GitError)Marshal.PtrToStructure(pNativeData, typeof(GitError)); + } + + public static ICustomMarshaler GetInstance(string cookie) + { + return staticInstance; + } + } +} diff --git a/LibGit2Sharp/Core/Handles/GitErrorSafeHandle.cs b/LibGit2Sharp/Core/Handles/GitErrorSafeHandle.cs deleted file mode 100644 index 9a222a482..000000000 --- a/LibGit2Sharp/Core/Handles/GitErrorSafeHandle.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Runtime.InteropServices; - -namespace LibGit2Sharp.Core.Handles -{ - internal class GitErrorSafeHandle : NotOwnedSafeHandleBase - { - public GitError MarshalAsGitError() - { - return (GitError)Marshal.PtrToStructure(handle, typeof(GitError)); - } - } -} diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index d18d4f808..5adafa26a 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -65,7 +65,8 @@ public static bool RepositoryStateChecker(RepositorySafeHandle repositoryPtr, Fu } [DllImport(libgit2)] - public static extern GitErrorSafeHandle giterr_last(); + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(GitErrorMarshaler))] + public static extern GitError giterr_last(); [DllImport(libgit2)] public static extern int git_blob_create_fromdisk( diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index e7fd893c8..815399591 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -78,10 +78,10 @@ - + + - diff --git a/LibGit2Sharp/LibGit2SharpException.cs b/LibGit2Sharp/LibGit2SharpException.cs index 1ae9bf5ab..92d455884 100644 --- a/LibGit2Sharp/LibGit2SharpException.cs +++ b/LibGit2Sharp/LibGit2SharpException.cs @@ -1,5 +1,6 @@ using System; -using System.Runtime.Serialization; +using System.Globalization; +using LibGit2Sharp.Core; namespace LibGit2Sharp { @@ -39,9 +40,12 @@ public LibGit2Exception(string message, Exception innerException) /// /// The exception that is thrown when an error occurs during application execution. /// - [Serializable] public class LibGit2SharpException : Exception { + readonly GitErrorCode code; + readonly GitErrorCategory category; + readonly bool isLibraryError; + /// /// Initializes a new instance of the class. /// @@ -49,6 +53,16 @@ public LibGit2SharpException() { } + /// + /// Initializes a new instance of the class. + /// + public LibGit2SharpException(GitErrorCode code, GitErrorCategory category, string message) : base(message) + { + Data["libgit2.code"] = this.code = code; + Data["libgit2.class"] = this.category = category; + isLibraryError = true; + } + /// /// Initializes a new instance of the class with a specified error message. /// @@ -69,13 +83,30 @@ public LibGit2SharpException(string message, Exception innerException) } /// - /// Initializes a new instance of the class with a serialized data. + /// The specific libgit2 error code. /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - protected LibGit2SharpException(SerializationInfo info, StreamingContext context) - : base(info, context) + public GitErrorCode Code + { + get { return Data.Contains("libgit2.code") ? (GitErrorCode)Data["libgit2.code"] : GitErrorCode.Error; } + } + + /// + /// The specific libgit2 error class. + /// + public GitErrorCategory Category + { + get { return Data.Contains("libgit2.class") ? (GitErrorCategory)Data["libgit2.class"] : GitErrorCategory.Unknown; } + } + + public override string ToString() { + return isLibraryError + ? String.Format(CultureInfo.InvariantCulture, "An error was raised by libgit2. Class = {0} ({1}).{2}{3}", + category, + code, + Environment.NewLine, + Message) + : base.ToString(); } } }