using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; namespace LibGit2Sharp.Core { /// /// Ensure input parameters /// [DebuggerStepThrough] internal static class Ensure { /// /// Checks an argument to ensure it isn't null. /// /// The argument value to check. /// The name of the argument. public static void ArgumentNotNull(object argumentValue, string argumentName) { if (argumentValue == null) { throw new ArgumentNullException(argumentName); } } /// /// Checks an array argument to ensure it isn't null or empty. /// /// The argument value to check. /// The name of the argument. public static void ArgumentNotNullOrEmptyEnumerable(IEnumerable argumentValue, string argumentName) { ArgumentNotNull(argumentValue, argumentName); if (!argumentValue.Any()) { throw new ArgumentException("Enumerable cannot be empty", argumentName); } } /// /// Checks a string argument to ensure it isn't null or empty. /// /// The argument value to check. /// The name of the argument. public static void ArgumentNotNullOrEmptyString(string argumentValue, string argumentName) { ArgumentNotNull(argumentValue, argumentName); if (String.IsNullOrWhiteSpace (argumentValue)) { throw new ArgumentException("String cannot be empty", argumentName); } } /// /// Checks a string argument to ensure it doesn't contain a zero byte. /// /// The argument value to check. /// The name of the argument. public static void ArgumentDoesNotContainZeroByte(string argumentValue, string argumentName) { if (string.IsNullOrEmpty(argumentValue)) { return; } int zeroPos = -1; for (var i = 0; i < argumentValue.Length; i++) { if (argumentValue[i] == '\0') { zeroPos = i; break; } } if (zeroPos == -1) { return; } throw new ArgumentException( string.Format(CultureInfo.InvariantCulture, "Zero bytes ('\\0') are not allowed. A zero byte has been found at position {0}.", zeroPos), argumentName); } /// /// Checks an argument to ensure it isn't a IntPtr.Zero (aka null). /// /// The argument value to check. /// The name of the argument. public static void ArgumentNotZeroIntPtr(IntPtr argumentValue, string argumentName) { if (argumentValue == IntPtr.Zero) { throw new ArgumentNullException(argumentName); } } /// /// Checks a pointer argument to ensure it is the expected pointer value. /// /// The argument value to check. /// The expected value. /// The name of the argument. public static void ArgumentIsExpectedIntPtr(IntPtr argumentValue, IntPtr expectedValue, string argumentName) { if (argumentValue != expectedValue) { throw new ArgumentException("Unexpected IntPtr value", argumentName); } } private static readonly Dictionary> GitErrorsToLibGit2SharpExceptions = new Dictionary> { { GitErrorCode.User, (m, r, c) => new UserCancelledException(m, r, c) }, { GitErrorCode.BareRepo, (m, r, c) => new BareRepositoryException(m, r, c) }, { GitErrorCode.Exists, (m, r, c) => new NameConflictException(m, r, c) }, { GitErrorCode.InvalidSpecification, (m, r, c) => new InvalidSpecificationException(m, r, c) }, { GitErrorCode.UnmergedEntries, (m, r, c) => new UnmergedIndexEntriesException(m, r, c) }, { GitErrorCode.NonFastForward, (m, r, c) => new NonFastForwardException(m, r, c) }, { GitErrorCode.Conflict, (m, r, c) => new CheckoutConflictException(m, r, c) }, { GitErrorCode.LockedFile, (m, r, c) => new LockedFileException(m, r, c) }, { GitErrorCode.NotFound, (m, r, c) => new NotFoundException(m, r, c) }, { GitErrorCode.Peel, (m, r, c) => new PeelException(m, r, c) }, }; private static unsafe void HandleError(int result) { string errorMessage; GitErrorCategory errorCategory = GitErrorCategory.Unknown; GitError* error = NativeMethods.giterr_last(); if (error == null) { errorMessage = "No error message has been provided by the native library"; } else { errorMessage = LaxUtf8Marshaler.FromNative(error->Message); } Func exceptionBuilder; if (!GitErrorsToLibGit2SharpExceptions.TryGetValue((GitErrorCode)result, out exceptionBuilder)) { exceptionBuilder = (m, r, c) => new LibGit2SharpException(m, r, c); } throw exceptionBuilder(errorMessage, (GitErrorCode)result, errorCategory); } /// /// Check that the result of a C call was successful /// /// The native function is expected to return strictly 0 for /// success or a negative value in the case of failure. /// /// /// The result to examine. public static void ZeroResult(int result) { if (result == (int)GitErrorCode.Ok) { return; } HandleError(result); } /// /// Check that the result of a C call returns a boolean value. /// /// The native function is expected to return strictly 0 or 1. /// /// /// The result to examine. public static void BooleanResult(int result) { if (result == 0 || result == 1) { return; } HandleError(result); } /// /// Check that the result of a C call that returns an integer /// value was successful. /// /// The native function is expected to return 0 or a positive /// value for success or a negative value in the case of failure. /// /// /// The result to examine. public static void Int32Result(int result) { if (result >= (int)GitErrorCode.Ok) { return; } HandleError(result); } /// /// Checks an argument by applying provided checker. /// /// The argument value to check. /// The predicate which has to be satisfied /// The name of the argument. public static void ArgumentConformsTo(T argumentValue, Func checker, string argumentName) { if (checker(argumentValue)) { return; } throw new ArgumentException(argumentName); } /// /// Checks an argument is a positive integer. /// /// The argument value to check. /// The name of the argument. public static void ArgumentPositiveInt32(long argumentValue, string argumentName) { if (argumentValue >= 0 && argumentValue <= uint.MaxValue) { return; } throw new ArgumentException(argumentName); } /// /// Check that the result of a C call that returns a non-null GitObject /// using the default exception builder. /// /// The native function is expected to return a valid object value. /// /// /// The to examine. /// The identifier to examine. public static void GitObjectIsNotNull(GitObject gitObject, string identifier) { if (gitObject != null) { return; } var messageFormat = "No valid git object identified by '{0}' exists in the repository."; if (string.Equals("HEAD", identifier, StringComparison.Ordinal)) { throw new UnbornBranchException(messageFormat, identifier); } throw new NotFoundException(messageFormat, identifier); } } }