diff --git a/.mailmap b/.mailmap index abdf4421f..ef9348df1 100644 --- a/.mailmap +++ b/.mailmap @@ -5,3 +5,4 @@ Saaman nulltoken Martin Woodward Carlos Martín Nieto +someoneigna diff --git a/.travis.yml b/.travis.yml index f564a6e81..8932fc543 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,13 +3,22 @@ language: c +os: + - osx + - linux + +before_install: + - date -u + - uname -a + - env | sort + # Make sure CMake and Mono are installed install: - - sudo apt-get install cmake mono-devel mono-gmcs + - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/travis.linux.install.deps.sh; fi + - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/travis.osx.install.deps.sh; fi # Build libgit2, LibGit2Sharp and run the tests script: - - git submodule update --init - ./build.libgit2sharp.sh # Only watch the development branch @@ -17,10 +26,7 @@ branches: only: - vNext -# Notify development list when needed +# Notify of build changes notifications: - recipients: - - emeric.fermas@gmail.com email: - on_success: change - on_failure: always + - emeric.fermas@gmail.com diff --git a/CHANGES.md b/CHANGES.md index e53a67013..a7cc7ea13 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,8 +5,38 @@ - Source code: - NuGet package: - Issue tracker: - - CI server: - @libgit2sharp: + - CI servers: + - CodeBetter TeamCity: + - Travis: + +## v0.18.0 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.17.0...v0.18.0)) + +### Additions + + - Introduce repo.Revert() (#706) + - Enhanced control over Merge behavior through MergeOptions (#685) + - Introduce repo.Network.Remotes.Remove() (#729, #731) + - Teach repo.Network.ListReferences() to accept a Credentials (#647, #704) + - Introduce Reference.IsValidName() (#680, #691) + - Introduce Remote.IsValidName() (#679, #690) + - Expose StatusOptions.RecurseIgnoredDirs (#728) + - Introduce GlobalSettings.Features() (#717) + - Make Repository.Version output the libgit2 built-in features (#676, #694) + +### Changes + + - LibGit2Sharp now requires .Net 4.0 (#654, #678) + - Repository.Checkout() and Branch.Checkout() overloads now accept a CheckoutOptions parameter (#685) + - Deprecate repo.Refs.IsValidName() (#680, #691) + - Deprecate repo.Network.Remotes.IsValidName() (#679, #690) + - Deprecate repo.Branches.Move() in favor of repo.Branches.Rename() (#737, #738) + - Update libgit2 binaries to libgit2/libgit2@2f6f6eb + +### Fixes + + - Do not fail enumerating the ObjectDatabase content when an unexpected file is found under .git/objects (#704) + - Fix update of HEAD when committing against a bare repository with a temporary working directory (#692) ## v0.17.0 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.16.0...v0.17.0)) @@ -20,7 +50,7 @@ - Teach repo.Commits.FindMergeBase to leverage either Standard or Octopus strategy (#634 and #629) - Make ObjectDatabase.CreateCommit() accept an option controlling the prettifying of the message (#619) - Allow notes retrieval by namespace and ObjectId (#653) - + ### Changes - Deprecate repo.Commits.FindCommonAncestor() in favor of repo.Commits.FindMergeBase() (#634) diff --git a/CI-build.msbuild b/CI/build.msbuild similarity index 92% rename from CI-build.msbuild rename to CI/build.msbuild index 0d5a12ffa..5a94395e7 100644 --- a/CI-build.msbuild +++ b/CI/build.msbuild @@ -1,12 +1,12 @@ Release - $(MSBuildProjectDirectory) + $(MSBuildProjectDirectory)\.. $(RootDir)\LibGit2Sharp.Tests\bin\$(Configuration) $(RootDir)\Build - @@ -30,7 +30,7 @@ diff --git a/CI/travis.linux.install.deps.sh b/CI/travis.linux.install.deps.sh new file mode 100755 index 000000000..94400152c --- /dev/null +++ b/CI/travis.linux.install.deps.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -ev + +sudo apt-get install cmake mono-devel mono-gmcs diff --git a/CI/travis.osx.install.deps.sh b/CI/travis.osx.install.deps.sh new file mode 100755 index 000000000..19e7552a4 --- /dev/null +++ b/CI/travis.osx.install.deps.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -ev + +MONO_VER=2.10.10 + +brew update +brew install cmake + +wget "http://download.mono-project.com/archive/${MONO_VER}/macos-10-x86/MonoFramework-MDK-${MONO_VER}.macos10.xamarin.x86.dmg" +hdid "MonoFramework-MDK-${MONO_VER}.macos10.xamarin.x86.dmg" +sudo installer -pkg "/Volumes/Mono Framework MDK ${MONO_VER}/MonoFramework-MDK-${MONO_VER}.macos10.xamarin.x86.pkg" -target / diff --git a/Lib/MoQ/Moq.dll b/Lib/MoQ/Moq.dll index 3d3b8ccd0..bdd4235f2 100644 Binary files a/Lib/MoQ/Moq.dll and b/Lib/MoQ/Moq.dll differ diff --git a/Lib/MoQ/Moq.xml b/Lib/MoQ/Moq.xml index 432077576..160c1b516 100644 --- a/Lib/MoQ/Moq.xml +++ b/Lib/MoQ/Moq.xml @@ -47,6 +47,62 @@ The setter expression. + + + Handle interception + + the current invocation context + shared data for the interceptor as a whole + shared data among the strategies during a single interception + InterceptionAction.Continue if further interception has to be processed, otherwise InterceptionAction.Stop + + + + Covarient interface for Mock<T> such that casts between IMock<Employee> to IMock<Person> + are possible. Only covers the covariant members of Mock<T>. + + + + + Exposes the mocked object instance. + + + + + Behavior of the mock, according to the value set in the constructor. + + + + + Whether the base member virtual implementation will be called + for mocked classes if no setup is matched. Defaults to . + + + + + Specifies the behavior to use when returning default values for + unexpected invocations on loose mocks. + + + + + Get an eventInfo for a given event name. Search type ancestors depth first if necessary. + + Name of the event, with the set_ or get_ prefix already removed + + + + Get an eventInfo for a given event name. Search type ancestors depth first if necessary. + Searches also in non public events. + + Name of the event, with the set_ or get_ prefix already removed + + + + Given a type return all of its ancestors, both types and interfaces. + + The type to find immediate ancestors of + Defines the Callback verb and overloads. @@ -1622,6 +1678,12 @@ + + + Calls the real method of the object and returns its return value. + + The value calculated by the real method of the object. + Specifies a function that will calculate the value to return from the method, @@ -2177,6 +2239,58 @@ + + + Hook used to tells Castle which methods to proxy in mocked classes. + + Here we proxy the default methods Castle suggests (everything Object's methods) + plus Object.ToString(), so we can give mocks useful default names. + + This is required to allow Moq to mock ToString on proxy *class* implementations. + + + + + Extends AllMethodsHook.ShouldInterceptMethod to also intercept Object.ToString(). + + + + + The base class used for all our interface-inheriting proxies, which overrides the default + Object.ToString() behavior, to route it via the mock by default, unless overriden by a + real implementation. + + This is required to allow Moq to mock ToString on proxy *interface* implementations. + + + This is internal to Moq and should not be generally used. + + Unfortunately it must be public, due to cross-assembly visibility issues with reflection, + see github.com/Moq/moq4/issues/98 for details. + + + + + Overrides the default ToString implementation to instead find the mock for this mock.Object, + and return MockName + '.Object' as the mocked object's ToString, to make it easy to relate + mocks and mock object instances in error messages. + + + + + Defines async extension methods on IReturns. + + + + + Allows to specify the return value of an asynchronous method. + + + + + Allows to specify the exception thrown by an asynchronous method. + + Language for ReturnSequence @@ -2197,6 +2311,11 @@ Throws an exception + + + Calls original method + + The first method call or member access will be the @@ -2300,7 +2419,7 @@ // that expectation was not marked as verifiable. this.VerifyAll(); - At least one expectation was not met. + At least one expectation was not met. @@ -2385,6 +2504,20 @@ This is used in the auto-mocking of hierarchy access. + + + If this is a mock of a delegate, this property contains the method + on the autogenerated interface so that we can convert setup + verify + expressions on the delegate into expressions on the interface proxy. + + + + + Allows to check whether expression conversion to the + must be performed on the mock, without causing unnecessarily early initialization of + the mock instance, which breaks As{T}. + + Specifies the class that will determine the default @@ -3006,658 +3139,30 @@ that moment. + + + Calls the real property of the object and returns its return value. + + The value calculated by the real property of the object. + Implements the fluent API. - - - Encapsulates a method that has five parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has five parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has six parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has six parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has seven parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has seven parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has eight parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has eight parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has nine parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has nine parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has ten parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has ten parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has eleven parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has eleven parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has twelve parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has twelve parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has thirteen parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the thirteenth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The thirteenth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has thirteen parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the thirteenth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The thirteenth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has fourteen parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the thirteenth parameter of the method that this delegate encapsulates. - The type of the fourteenth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The thirteenth parameter of the method that this delegate encapsulates. - The fourteenth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has fourteen parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the thirteenth parameter of the method that this delegate encapsulates. - The type of the fourteenth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The thirteenth parameter of the method that this delegate encapsulates. - The fourteenth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has fifteen parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the thirteenth parameter of the method that this delegate encapsulates. - The type of the fourteenth parameter of the method that this delegate encapsulates. - The type of the fifteenth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The thirteenth parameter of the method that this delegate encapsulates. - The fourteenth parameter of the method that this delegate encapsulates. - The fifteenth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has fifteen parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the thirteenth parameter of the method that this delegate encapsulates. - The type of the fourteenth parameter of the method that this delegate encapsulates. - The type of the fifteenth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The thirteenth parameter of the method that this delegate encapsulates. - The fourteenth parameter of the method that this delegate encapsulates. - The fifteenth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. - - - - Encapsulates a method that has sixteen parameters and does not return a value. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the thirteenth parameter of the method that this delegate encapsulates. - The type of the fourteenth parameter of the method that this delegate encapsulates. - The type of the fifteenth parameter of the method that this delegate encapsulates. - The type of the sixteenth parameter of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The thirteenth parameter of the method that this delegate encapsulates. - The fourteenth parameter of the method that this delegate encapsulates. - The fifteenth parameter of the method that this delegate encapsulates. - The sixteenth parameter of the method that this delegate encapsulates. - - - - Encapsulates a method that has sixteen parameters and returns a value of the type specified by the parameter. - - The type of the first parameter of the method that this delegate encapsulates. - The type of the second parameter of the method that this delegate encapsulates. - The type of the third parameter of the method that this delegate encapsulates. - The type of the fourth parameter of the method that this delegate encapsulates. - The type of the fifth parameter of the method that this delegate encapsulates. - The type of the sixth parameter of the method that this delegate encapsulates. - The type of the seventh parameter of the method that this delegate encapsulates. - The type of the eighth parameter of the method that this delegate encapsulates. - The type of the nineth parameter of the method that this delegate encapsulates. - The type of the tenth parameter of the method that this delegate encapsulates. - The type of the eleventh parameter of the method that this delegate encapsulates. - The type of the twelfth parameter of the method that this delegate encapsulates. - The type of the thirteenth parameter of the method that this delegate encapsulates. - The type of the fourteenth parameter of the method that this delegate encapsulates. - The type of the fifteenth parameter of the method that this delegate encapsulates. - The type of the sixteenth parameter of the method that this delegate encapsulates. - The type of the return value of the method that this delegate encapsulates. - The first parameter of the method that this delegate encapsulates. - The second parameter of the method that this delegate encapsulates. - The third parameter of the method that this delegate encapsulates. - The fourth parameter of the method that this delegate encapsulates. - The fifth parameter of the method that this delegate encapsulates. - The sixth parameter of the method that this delegate encapsulates. - The seventh parameter of the method that this delegate encapsulates. - The eighth parameter of the method that this delegate encapsulates. - The nineth parameter of the method that this delegate encapsulates. - The tenth parameter of the method that this delegate encapsulates. - The eleventh parameter of the method that this delegate encapsulates. - The twelfth parameter of the method that this delegate encapsulates. - The thirteenth parameter of the method that this delegate encapsulates. - The fourteenth parameter of the method that this delegate encapsulates. - The fifteenth parameter of the method that this delegate encapsulates. - The sixteenth parameter of the method that this delegate encapsulates. - The return value of the method that this delegate encapsulates. + + + Provides additional methods on mocks. + + + Those methods are useful for Testeroids support. + + + + + Resets the calls previously made on the specified mock. + + The mock whose calls need to be reset. @@ -3918,6 +3423,11 @@ var mock = new Mock<MyProvider>(someArgument, 25); Behavior of the mock.Optional constructor arguments if the mocked type is a class. + + + Returns the name of the mock + + Returns the mocked object value. @@ -4090,6 +3600,15 @@ . Expression to verify.The number of times a method is allowed to be called. + + + Verifies that a specific invocation matching the given expression was performed on the mock. Use + in conjuntion with the default . + + The invocation was not call the times specified by + . + Expression to verify.The number of times a method is allowed to be called. + Verifies that a specific invocation matching the given expression was performed on the mock, @@ -4117,6 +3636,16 @@ . Expression to verify.The number of times a method is allowed to be called.Message to show if verification fails. + + + Verifies that a specific invocation matching the given expression was performed on the mock, + specifying a failure error message. Use in conjuntion with the default + . + + The invocation was not call the times specified by + . + Expression to verify.The number of times a method is allowed to be called.Message to show if verification fails. + Verifies that a specific invocation matching the given expression was performed on the mock. Use @@ -4143,6 +3672,16 @@ . Expression to verify.The number of times a method is allowed to be called.Type of return value from the expression. + + + Verifies that a specific invocation matching the given + expression was performed on the mock. Use in conjuntion + with the default . + + The invocation was not call the times specified by + . + Expression to verify.The number of times a method is allowed to be called.Type of return value from the expression. + Verifies that a specific invocation matching the given @@ -4201,6 +3740,17 @@ be inferred from the expression's return type. + + + Verifies that a property was read on the mock. + + The invocation was not call the times specified by + . + The number of times a method is allowed to be called.Expression to verify. + Type of the property to verify. Typically omitted as it can + be inferred from the expression's return type. + + Verifies that a property was read on the mock, specifying a failure @@ -4233,6 +3783,18 @@ be inferred from the expression's return type. + + + Verifies that a property was read on the mock, specifying a failure + error message. + + The invocation was not call the times specified by + . + The number of times a method is allowed to be called.Expression to verify.Message to show if verification fails. + Type of the property to verify. Typically omitted as it can + be inferred from the expression's return type. + + Verifies that a property was set on the mock. @@ -4257,6 +3819,14 @@ . The number of times a method is allowed to be called.Expression to verify. + + + Verifies that a property was set on the mock. + + The invocation was not call the times specified by + . + The number of times a method is allowed to be called.Expression to verify. + Verifies that a property was set on the mock, specifying @@ -4283,6 +3853,15 @@ . The number of times a method is allowed to be called.Expression to verify.Message to show if verification fails. + + + Verifies that a property was set on the mock, specifying + a failure message. + + The invocation was not call the times specified by + . + The number of times a method is allowed to be called.Expression to verify.Message to show if verification fails. + Raises the event referenced in using @@ -4341,6 +3920,14 @@ Exposes the mocked object instance. + + + Allows naming of your mocks, so they can be easily identified in error messages (e.g. from failed assertions). + + + + + Provides legacy API members as extensions so that @@ -4363,7 +3950,7 @@ Obsolete. - + Provides additional methods on mocks. @@ -4372,7 +3959,7 @@ with the overloads taking Action. - + Specifies a setup on the mocked type for a call to to a property setter, regardless of its value. @@ -4395,7 +3982,7 @@ confusing the compiler with the new Action syntax. - + Verifies that a property has been set on the mock, regarless of its value. @@ -4418,7 +4005,7 @@ Type of the property to verify. Typically omitted as it can be inferred from the expression's return type. - + Verifies that a property has been set on the mock, specifying a failure error message. @@ -4443,7 +4030,7 @@ Type of the property to verify. Typically omitted as it can be inferred from the expression's return type. - + Verifies that a property has been set on the mock, regardless of the value but only the specified number of times. @@ -4470,7 +4057,7 @@ Type of the property to verify. Typically omitted as it can be inferred from the expression's return type. - + Verifies that a property has been set on the mock, regardless of the value but only the specified number of times, and specifying a failure @@ -4564,6 +4151,18 @@ is fixed. + + + Extracts, into a common form, information from a + around either a (for a normal method call) + or a (for a delegate invocation). + + + + + Tests if a type is a delegate type (subclasses ). + + Provides partial evaluation of subtrees, whenever they can be evaluated locally. @@ -4659,18 +4258,6 @@ all mocks. - - - Get an eventInfo for a given event name. Search type ancestors depth first if necessary. - - Name of the event, with the set_ or get_ prefix already removed - - - - Given a type return all of its ancestors, both types and interfaces. - - The type to find immediate ancestors of - Implements the fluent API. @@ -4720,6 +4307,11 @@ Type of the value. + + + Matches any value of the given type, except null. + Type of the value. + Matches any value that satisfies the given predicate. @@ -4757,6 +4349,66 @@ + + + Matches any value that is present in the sequence specified. + Type of the argument to check.The sequence of possible values. + The following example shows how to expect a method call + with an integer argument with value from a list. + + var values = new List<int> { 1, 2, 3 }; + + mock.Setup(x => x.HasInventory( + It.IsAny<string>(), + It.IsIn(values))) + .Returns(false); + + + + + + Matches any value that is present in the sequence specified. + Type of the argument to check.The sequence of possible values. + The following example shows how to expect a method call + with an integer argument with a value of 1, 2, or 3. + + mock.Setup(x => x.HasInventory( + It.IsAny<string>(), + It.IsIn(1, 2, 3))) + .Returns(false); + + + + + + Matches any value that is not found in the sequence specified. + Type of the argument to check.The sequence of disallowed values. + The following example shows how to expect a method call + with an integer argument with value not found from a list. + + var values = new List<int> { 1, 2, 3 }; + + mock.Setup(x => x.HasInventory( + It.IsAny<string>(), + It.IsNotIn(values))) + .Returns(false); + + + + + + Matches any value that is not found in the sequence specified. + Type of the argument to check.The sequence of disallowed values. + The following example shows how to expect a method call + with an integer argument of any value except 1, 2, or 3. + + mock.Setup(x => x.HasInventory( + It.IsAny<string>(), + It.IsNotIn(1, 2, 3))) + .Returns(false); + + + Matches a string argument if it matches the given regular expression pattern. @@ -4856,6 +4508,11 @@ Serialization information. Streaming context. + + + Indicates whether this exception is a verification fault raised by Verify() + + Made internal as it's of no use for @@ -4910,6 +4567,11 @@ Looks up a localized string similar to Can't set return value for void method {0}.. + + + Looks up a localized string similar to Constructor arguments cannot be passed for delegate mocks.. + + Looks up a localized string similar to Constructor arguments cannot be passed for interface mocks.. @@ -5678,6 +5340,25 @@ Retrieves a fluent mock from the given setup expression. + + + Gets an autogenerated interface with a method on it that matches the signature of the specified + . + + + Such an interface can then be mocked, and a delegate pointed at the method on the mocked instance. + This is how we support delegate mocking. The factory caches such interfaces and reuses them + for repeated requests for the same delegate type. + + The delegate type for which an interface is required. + The method on the autogenerated interface. + + + + + + + Defines the number of invocations allowed by a mocked method. diff --git a/Lib/NativeBinaries/amd64/git2-06d772d.dll b/Lib/NativeBinaries/amd64/git2-06d772d.dll deleted file mode 100644 index 639b55ef4..000000000 Binary files a/Lib/NativeBinaries/amd64/git2-06d772d.dll and /dev/null differ diff --git a/Lib/NativeBinaries/amd64/git2-06d772d.pdb b/Lib/NativeBinaries/amd64/git2-06d772d.pdb deleted file mode 100644 index 589a0487c..000000000 Binary files a/Lib/NativeBinaries/amd64/git2-06d772d.pdb and /dev/null differ diff --git a/Lib/NativeBinaries/amd64/git2-2f6f6eb.dll b/Lib/NativeBinaries/amd64/git2-2f6f6eb.dll new file mode 100644 index 000000000..53f104730 Binary files /dev/null and b/Lib/NativeBinaries/amd64/git2-2f6f6eb.dll differ diff --git a/Lib/NativeBinaries/amd64/git2-2f6f6eb.pdb b/Lib/NativeBinaries/amd64/git2-2f6f6eb.pdb new file mode 100644 index 000000000..4578d77fd Binary files /dev/null and b/Lib/NativeBinaries/amd64/git2-2f6f6eb.pdb differ diff --git a/Lib/NativeBinaries/x86/git2-06d772d.dll b/Lib/NativeBinaries/x86/git2-06d772d.dll deleted file mode 100644 index 1ceb3b2ec..000000000 Binary files a/Lib/NativeBinaries/x86/git2-06d772d.dll and /dev/null differ diff --git a/Lib/NativeBinaries/x86/git2-06d772d.pdb b/Lib/NativeBinaries/x86/git2-06d772d.pdb deleted file mode 100644 index e98d16c55..000000000 Binary files a/Lib/NativeBinaries/x86/git2-06d772d.pdb and /dev/null differ diff --git a/Lib/NativeBinaries/x86/git2-2f6f6eb.dll b/Lib/NativeBinaries/x86/git2-2f6f6eb.dll new file mode 100644 index 000000000..3c955415d Binary files /dev/null and b/Lib/NativeBinaries/x86/git2-2f6f6eb.dll differ diff --git a/Lib/NativeBinaries/x86/git2-2f6f6eb.pdb b/Lib/NativeBinaries/x86/git2-2f6f6eb.pdb new file mode 100644 index 000000000..69de6e262 Binary files /dev/null and b/Lib/NativeBinaries/x86/git2-2f6f6eb.pdb differ diff --git a/LibGit2Sharp.Tests/BlobFixture.cs b/LibGit2Sharp.Tests/BlobFixture.cs index 3092ee2ae..f615aed18 100644 --- a/LibGit2Sharp.Tests/BlobFixture.cs +++ b/LibGit2Sharp.Tests/BlobFixture.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; using System.Linq; using System.Text; using LibGit2Sharp.Tests.TestHelpers; diff --git a/LibGit2Sharp.Tests/BranchFixture.cs b/LibGit2Sharp.Tests/BranchFixture.cs index 1f44618ce..b24cf582a 100644 --- a/LibGit2Sharp.Tests/BranchFixture.cs +++ b/LibGit2Sharp.Tests/BranchFixture.cs @@ -551,14 +551,14 @@ public void CanGetTrackingInformationForLocalTrackingBranch() } [Fact] - public void MovingARemoteTrackingBranchThrows() + public void RenamingARemoteTrackingBranchThrows() { using (var repo = new Repository(StandardTestRepoPath)) { Branch master = repo.Branches["refs/remotes/origin/master"]; Assert.True(master.IsRemote); - Assert.Throws(() => repo.Branches.Move(master, "new_name", true)); + Assert.Throws(() => repo.Branches.Rename(master, "new_name", true)); } } @@ -821,7 +821,7 @@ public void TwoBranchesPointingAtTheSameCommitAreNotBothCurrent() } [Fact] - public void CanMoveABranch() + public void CanRenameABranch() { string path = CloneBareTestRepo(); using (var repo = new Repository(path)) @@ -832,7 +832,7 @@ public void CanMoveABranch() var br2 = repo.Branches["br2"]; Assert.NotNull(br2); - Branch newBranch = repo.Branches.Move("br2", "br3"); + Branch newBranch = repo.Branches.Rename("br2", "br3"); Assert.Equal("br3", newBranch.Name); @@ -846,16 +846,16 @@ public void CanMoveABranch() } [Fact] - public void BlindlyMovingABranchOverAnExistingOneThrows() + public void BlindlyRenamingABranchOverAnExistingOneThrows() { using (var repo = new Repository(BareTestRepoPath)) { - Assert.Throws(() => repo.Branches.Move("br2", "test")); + Assert.Throws(() => repo.Branches.Rename("br2", "test")); } } [Fact] - public void CanMoveABranchWhileOverwritingAnExistingOne() + public void CanRenameABranchWhileOverwritingAnExistingOne() { string path = CloneBareTestRepo(); using (var repo = new Repository(path)) @@ -868,7 +868,7 @@ public void CanMoveABranchWhileOverwritingAnExistingOne() Branch br2 = repo.Branches["br2"]; Assert.NotNull(br2); - Branch newBranch = repo.Branches.Move("br2", "test", true); + Branch newBranch = repo.Branches.Rename("br2", "test", true); Assert.Equal("test", newBranch.Name); Assert.Null(repo.Branches["br2"]); @@ -1000,18 +1000,18 @@ public void CreatingABranchIncludesTheCorrectReflogEntries() } [Fact] - public void MovingABranchIncludesTheCorrectReflogEntries() + public void RenamingABranchIncludesTheCorrectReflogEntries() { string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { EnableRefLog(repo); var master = repo.Branches["master"]; - var newMaster = repo.Branches.Move(master, "new-master"); - AssertRefLogEntry(repo, newMaster.CanonicalName, newMaster.Tip.Id, + var newMaster = repo.Branches.Rename(master, "new-master"); + AssertRefLogEntry(repo, newMaster.CanonicalName, newMaster.Tip.Id, "branch: renamed refs/heads/master to refs/heads/new-master"); - newMaster = repo.Branches.Move(newMaster, "new-master2", null, "MOVE"); + newMaster = repo.Branches.Rename(newMaster, "new-master2", null, "MOVE"); AssertRefLogEntry(repo, newMaster.CanonicalName, newMaster.Tip.Id, "MOVE"); } } diff --git a/LibGit2Sharp.Tests/CheckoutFixture.cs b/LibGit2Sharp.Tests/CheckoutFixture.cs index f4ea97bc2..abe4ad9aa 100644 --- a/LibGit2Sharp.Tests/CheckoutFixture.cs +++ b/LibGit2Sharp.Tests/CheckoutFixture.cs @@ -266,7 +266,7 @@ public void CanForcefullyCheckoutWithConflictingStagedChanges() Assert.Throws(() => repo.Checkout(master.CanonicalName)); // Checkout with force option should succeed. - repo.Checkout(master.CanonicalName, CheckoutModifiers.Force, null, null); + repo.Checkout(master.CanonicalName, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force}); // Assert that master branch is checked out. Assert.True(repo.Branches["master"].IsCurrentRepositoryHead); @@ -338,8 +338,14 @@ public void CanCancelCheckoutThroughNotifyCallback() // Verify that we get called for the notify conflict cb string conflictPath = string.Empty; - CheckoutNotificationOptions checkoutNotifications = new CheckoutNotificationOptions((path, flags) => { conflictPath = path; return false; }, CheckoutNotifyFlags.Conflict); - Assert.Throws(() => repo.Checkout("master", CheckoutModifiers.None, null, checkoutNotifications)); + + CheckoutOptions options = new CheckoutOptions() + { + OnCheckoutNotify = (path, flags) => { conflictPath = path; return false; }, + CheckoutNotifyFlags = CheckoutNotifyFlags.Conflict, + }; + + Assert.Throws(() => repo.Checkout("master", options)); Assert.Equal(relativePath, conflictPath); } } @@ -398,7 +404,7 @@ public void CheckingOutThroughBranchCallsCheckoutProgress() bool wasCalled = false; Branch branch = repo.Branches[otherBranchName]; - branch.Checkout(CheckoutModifiers.None, (path, completed, total) => wasCalled = true, null); + branch.Checkout(new CheckoutOptions() { OnCheckoutProgress = (path, completed, total) => wasCalled = true}); Assert.True(wasCalled); } @@ -414,7 +420,7 @@ public void CheckingOutThroughRepositoryCallsCheckoutProgress() PopulateBasicRepository(repo); bool wasCalled = false; - repo.Checkout(otherBranchName, CheckoutModifiers.None, (path, completed, total) => wasCalled = true, null); + repo.Checkout(otherBranchName, new CheckoutOptions() { OnCheckoutProgress = (path, completed, total) => wasCalled = true}); Assert.True(wasCalled); } @@ -486,11 +492,13 @@ public void CheckingOutCallsCheckoutNotify(CheckoutNotifyFlags notifyFlags, stri string actualNotificationPath = string.Empty; CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; - CheckoutNotificationOptions checkoutNotifications = new CheckoutNotificationOptions( - (path, notificationType) => { wasCalled = true; actualNotificationPath = path; actualNotifyFlags = notificationType; return true; }, - notifyFlags); + CheckoutOptions options = new CheckoutOptions() + { + OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotificationPath = path; actualNotifyFlags = notificationType; return true; }, + CheckoutNotifyFlags = notifyFlags, + }; - Assert.Throws(() => repo.Checkout("master", CheckoutModifiers.None, null, checkoutNotifications)); + Assert.Throws(() => repo.Checkout("master", options)); Assert.True(wasCalled); Assert.Equal(expectedNotificationPath, actualNotificationPath); @@ -538,7 +546,7 @@ public void ForceCheckoutRetainsUntrackedChanges() Assert.Equal(1, repo.Index.RetrieveStatus().Untracked.Count()); Assert.Equal(FileStatus.Untracked, repo.Index.RetrieveStatus(fullPathFileB)); - repo.Checkout(otherBranchName, CheckoutModifiers.Force, null, null); + repo.Checkout(otherBranchName, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force }); // Verify untracked entry still exists. Assert.Equal(1, repo.Index.RetrieveStatus().Untracked.Count()); @@ -641,7 +649,7 @@ public void ForceCheckoutRetainsIgnoredChanges() Assert.Equal(FileStatus.Ignored, repo.Index.RetrieveStatus(ignoredFilePath)); - repo.Checkout(otherBranchName, CheckoutModifiers.Force, null, null); + repo.Checkout(otherBranchName, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force }); // Verify that the ignored file still exists. Assert.Equal(FileStatus.Ignored, repo.Index.RetrieveStatus(ignoredFilePath)); @@ -718,7 +726,7 @@ public void CheckingOutABranchDoesNotAlterBinaryFiles() // The blob actually exists in the object database with the correct Sha Assert.Equal(expectedSha, repo.Lookup(expectedSha).Sha); - repo.Checkout("refs/heads/logo", CheckoutModifiers.Force, null, null); + repo.Checkout("refs/heads/logo", new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force }); // The Index has been updated as well with the blob Assert.Equal(expectedSha, repo.Index["square-logo.png"].Id.Sha); diff --git a/LibGit2Sharp.Tests/FetchFixture.cs b/LibGit2Sharp.Tests/FetchFixture.cs index 0838f4696..26b5c0460 100644 --- a/LibGit2Sharp.Tests/FetchFixture.cs +++ b/LibGit2Sharp.Tests/FetchFixture.cs @@ -87,9 +87,9 @@ public void CanFetchAllTagsIntoAnEmptyRepository(string url) } // Perform the actual fetch - repo.Network.Fetch(remote, new FetchOptions { + repo.Network.Fetch(remote, new FetchOptions { TagFetchMode = TagFetchMode.All, - OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler + OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }); // Verify the expected @@ -111,7 +111,7 @@ public void CanFetchCustomRefSpecsIntoAnEmptyRepository(string url, string local Remote remote = repo.Network.Remotes.Add(remoteName, url); string refSpec = string.Format("refs/heads/{2}:refs/remotes/{0}/{1}", remoteName, localBranchName, remoteBranchName); - + // Set up structures for the expected results // and verifying the RemoteUpdateTips callback. TestRemoteInfo remoteInfo = TestRemoteInfo.TestRemoteInstance; @@ -121,7 +121,7 @@ public void CanFetchCustomRefSpecsIntoAnEmptyRepository(string url, string local // Perform the actual fetch repo.Network.Fetch(remote, new string[] { refSpec }, new FetchOptions { TagFetchMode = TagFetchMode.None, - OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler + OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }); // Verify the expected diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs new file mode 100644 index 000000000..299359034 --- /dev/null +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -0,0 +1,19 @@ +using System; +using LibGit2Sharp; +using LibGit2Sharp.Tests.TestHelpers; +using Xunit; + +namespace LibGit2Sharp.Tests +{ + public class GlobalSettingsFixture : BaseFixture + { + [Fact] + public void CanGetMinimumCompiledInFeatures() + { + BuiltInFeatures features = GlobalSettings.Features(); + + Assert.True(features.HasFlag(BuiltInFeatures.Threads)); + Assert.True(features.HasFlag(BuiltInFeatures.Https)); + } + } +} diff --git a/LibGit2Sharp.Tests/LazyFixture.cs b/LibGit2Sharp.Tests/LazyFixture.cs deleted file mode 100644 index 14b797ea6..000000000 --- a/LibGit2Sharp.Tests/LazyFixture.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using LibGit2Sharp.Core.Compat; -using Xunit; - -namespace LibGit2Sharp.Tests -{ - public class LazyFixture - { - [Fact] - public void CanReturnTheValue() - { - var lazy = new Lazy(() => 2); - Assert.Equal(2, lazy.Value); - } - - [Fact] - public void IsLazilyEvaluated() - { - int i = 0; - - var evaluator = new Func(() => ++i); - - var lazy = new Lazy(evaluator); - Assert.Equal(1, lazy.Value); - } - - [Fact] - public void IsEvaluatedOnlyOnce() - { - int i = 0; - - var evaluator = new Func(() => ++i); - - var lazy = new Lazy(evaluator); - - Assert.Equal(1, lazy.Value); - Assert.Equal(1, lazy.Value); - } - } -} diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 0d5e17a4d..b07fcec44 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -10,15 +10,16 @@ Properties LibGit2Sharp.Tests LibGit2Sharp.Tests - v3.5 + v4.0 512 + true full false bin\Debug\ - TRACE;DEBUG;NET35 + TRACE;DEBUG;NET40 prompt 4 @@ -37,7 +38,7 @@ full false bin\Leaks\ - TRACE;DEBUG;NET35;LEAKS + TRACE;DEBUG;NET40;LEAKS prompt 4 @@ -61,9 +62,11 @@ + + @@ -96,7 +99,6 @@ - @@ -122,7 +124,6 @@ - @@ -147,4 +148,4 @@ --> - \ No newline at end of file + diff --git a/LibGit2Sharp.Tests/MergeFixture.cs b/LibGit2Sharp.Tests/MergeFixture.cs index bf1861a30..2fcf9c646 100644 --- a/LibGit2Sharp.Tests/MergeFixture.cs +++ b/LibGit2Sharp.Tests/MergeFixture.cs @@ -1,4 +1,7 @@ -using System.Linq; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; using Xunit.Extensions; @@ -73,7 +76,7 @@ public void CanRetrieveTheBranchBeingMerged() Assert.Equal(CurrentOperation.Merge, repo.Info.CurrentOperation); } } - + [Theory] [InlineData(true)] [InlineData(false)] @@ -341,6 +344,122 @@ public void CanNonFastForwardMergeCommit(bool fromDetachedHead, FastForwardStrat } } + [Fact] + public void MergeReportsCheckoutProgress() + { + string repoPath = CloneMergeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Commit commitToMerge = repo.Branches["normal_merge"].Tip; + + bool wasCalled = false; + + MergeOptions options = new MergeOptions() + { + OnCheckoutProgress = (path, completed, total) => wasCalled = true, + }; + + MergeResult result = repo.Merge(commitToMerge, Constants.Signature, options); + + Assert.True(wasCalled); + } + } + + [Fact] + public void MergeReportsCheckoutNotifications() + { + string repoPath = CloneMergeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Commit commitToMerge = repo.Branches["normal_merge"].Tip; + + bool wasCalled = false; + CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; + + MergeOptions options = new MergeOptions() + { + OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotifyFlags = notificationType; return true; }, + CheckoutNotifyFlags = CheckoutNotifyFlags.Updated, + }; + + MergeResult result = repo.Merge(commitToMerge, Constants.Signature, options); + + Assert.True(wasCalled); + Assert.Equal(CheckoutNotifyFlags.Updated, actualNotifyFlags); + } + } + + [Fact] + public void FastForwardMergeReportsCheckoutProgress() + { + string repoPath = CloneMergeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Commit commitToMerge = repo.Branches["fast_forward"].Tip; + + bool wasCalled = false; + + MergeOptions options = new MergeOptions() + { + OnCheckoutProgress = (path, completed, total) => wasCalled = true, + }; + + MergeResult result = repo.Merge(commitToMerge, Constants.Signature, options); + + Assert.True(wasCalled); + } + } + + [Fact] + public void FastForwardMergeReportsCheckoutNotifications() + { + string repoPath = CloneMergeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Commit commitToMerge = repo.Branches["fast_forward"].Tip; + + bool wasCalled = false; + CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; + + MergeOptions options = new MergeOptions() + { + OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotifyFlags = notificationType; return true; }, + CheckoutNotifyFlags = CheckoutNotifyFlags.Updated, + }; + + MergeResult result = repo.Merge(commitToMerge, Constants.Signature, options); + + Assert.True(wasCalled); + Assert.Equal(CheckoutNotifyFlags.Updated, actualNotifyFlags); + } + } + + [Fact] + public void MergeCanDetectRenames() + { + // The environment is set up such that: + // file b.txt is edited in the "rename" branch and + // edited and renamed in the "rename_source" branch. + // The edits are automergable. + // We can rename "rename_source" into "rename" + // if rename detection is enabled, + // but the merge will fail with conflicts if this + // change is not detected as a rename. + + string repoPath = CloneMergeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Branch currentBranch = repo.Checkout("rename_source"); + Assert.NotNull(currentBranch); + + Branch branchToMerge = repo.Branches["rename"]; + + MergeResult result = repo.Merge(branchToMerge, Constants.Signature); + + Assert.Equal(MergeStatus.NonFastForward, result.Status); + } + } + [Fact] public void FastForwardNonFastForwardableMergeThrows() { @@ -422,6 +541,112 @@ public void CanMergeCommittish(string committish, FastForwardStrategy strategy, } } + [Theory] + [InlineData(CheckoutFileConflictStrategy.Ours)] + [InlineData(CheckoutFileConflictStrategy.Theirs)] + public void CanSpecifyConflictFileStrategy(CheckoutFileConflictStrategy conflictStrategy) + { + const string conflictFile = "a.txt"; + const string conflictBranchName = "conflicts"; + + string path = CloneMergeTestRepo(); + using (var repo = new Repository(path)) + { + Branch branch = repo.Branches[conflictBranchName]; + Assert.NotNull(branch); + + MergeOptions mergeOptions = new MergeOptions() + { + FileConflictStrategy = conflictStrategy, + }; + + MergeResult result = repo.Merge(branch, Constants.Signature, mergeOptions); + Assert.Equal(MergeStatus.Conflicts, result.Status); + + // Get the information on the conflict. + Conflict conflict = repo.Index.Conflicts[conflictFile]; + + Assert.NotNull(conflict); + Assert.NotNull(conflict.Theirs); + Assert.NotNull(conflict.Ours); + + // Get the blob containing the expected content. + Blob expectedBlob = null; + switch(conflictStrategy) + { + case CheckoutFileConflictStrategy.Theirs: + expectedBlob = repo.Lookup(conflict.Theirs.Id); + break; + case CheckoutFileConflictStrategy.Ours: + expectedBlob = repo.Lookup(conflict.Ours.Id); + break; + default: + throw new Exception("Unexpected FileConflictStrategy"); + } + + Assert.NotNull(expectedBlob); + + // Check the content of the file on disk matches what is expected. + string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictFile)); + Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictFile))); + } + } + + [Theory] + [InlineData(MergeFileFavor.Ours)] + [InlineData(MergeFileFavor.Theirs)] + public void MergeCanSpecifyMergeFileFavorOption(MergeFileFavor fileFavorFlag) + { + const string conflictFile = "a.txt"; + const string conflictBranchName = "conflicts"; + + string path = CloneMergeTestRepo(); + using (var repo = InitIsolatedRepository(path)) + { + Branch branch = repo.Branches[conflictBranchName]; + Assert.NotNull(branch); + + var status = repo.Index.RetrieveStatus(); + MergeOptions mergeOptions = new MergeOptions() + { + MergeFileFavor = fileFavorFlag, + }; + + MergeResult result = repo.Merge(branch, Constants.Signature, mergeOptions); + + Assert.Equal(MergeStatus.NonFastForward, result.Status); + + // Verify that the index and working directory are clean + Assert.True(repo.Index.IsFullyMerged); + Assert.False(repo.Index.RetrieveStatus().IsDirty); + + // Get the blob containing the expected content. + Blob expectedBlob = null; + switch (fileFavorFlag) + { + case MergeFileFavor.Theirs: + expectedBlob = repo.Lookup("3dd9738af654bbf1c363f6c3bbc323bacdefa179"); + break; + case MergeFileFavor.Ours: + expectedBlob = repo.Lookup("610b16886ca829cebd2767d9196f3c4378fe60b5"); + break; + default: + throw new Exception("Unexpected MergeFileFavor"); + } + + Assert.NotNull(expectedBlob); + + // Verify the index has the expected contents + IndexEntry entry = repo.Index[conflictFile]; + Assert.NotNull(entry); + Assert.Equal(expectedBlob.Id, entry.Id); + + // Verify the content of the file on disk matches what is expected. + string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictFile)); + Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictFile))); + } + } + [Theory] [InlineData("refs/heads/normal_merge", FastForwardStrategy.Default, MergeStatus.NonFastForward)] [InlineData("fast_forward", FastForwardStrategy.Default, MergeStatus.FastForward)] diff --git a/LibGit2Sharp.Tests/MetaFixture.cs b/LibGit2Sharp.Tests/MetaFixture.cs index 49471d258..0c86eccb0 100644 --- a/LibGit2Sharp.Tests/MetaFixture.cs +++ b/LibGit2Sharp.Tests/MetaFixture.cs @@ -209,7 +209,7 @@ public void GetEnumeratorMethodsInLibGit2SharpMustBeVirtualForTestability() !t.IsAbstract && t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(IEnumerable<>)))) .Select(t => t.GetMethod("GetEnumerator")) - .Where(m => + .Where(m => m.ReturnType.Name == "IEnumerator`1" && (!m.IsVirtual || m.IsFinal)) .ToList(); diff --git a/LibGit2Sharp.Tests/NetworkFixture.cs b/LibGit2Sharp.Tests/NetworkFixture.cs index 3b5050395..d1d221de5 100644 --- a/LibGit2Sharp.Tests/NetworkFixture.cs +++ b/LibGit2Sharp.Tests/NetworkFixture.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Tests.TestHelpers; using Xunit; using Xunit.Extensions; @@ -107,6 +107,29 @@ public void CanListRemoteReferenceObjects() } } + [SkippableFact] + public void CanListRemoteReferencesWithCredentials() + { + InconclusiveIf(() => string.IsNullOrEmpty(Constants.PrivateRepoUrl), + "Populate Constants.PrivateRepo* to run this test"); + + string remoteName = "origin"; + + string repoPath = InitNewRepository(); + + using (var repo = new Repository(repoPath)) + { + Remote remote = repo.Network.Remotes.Add(remoteName, Constants.PrivateRepoUrl); + + var references = repo.Network.ListReferences(remote, Constants.PrivateRepoCredentials); + + foreach (var directReference in references) + { + Assert.NotNull(directReference); + } + } + } + [Theory] [InlineData(FastForwardStrategy.Default)] [InlineData(FastForwardStrategy.NoFastFoward)] diff --git a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs index f5ab9712b..b0d622ee2 100644 --- a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs +++ b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs @@ -28,7 +28,7 @@ public void CanTellIfObjectsExists(string sha, bool shouldExists) [Fact] public void CanCreateABlobFromAFileInTheWorkingDirectory() { - string path = CloneStandardTestRepo(); + string path = InitNewRepository(); using (var repo = new Repository(path)) { Assert.Equal(FileStatus.Nonexistent, repo.Index.RetrieveStatus("hello.txt")); @@ -51,7 +51,7 @@ public void CanCreateABlobFromAFileInTheWorkingDirectory() [Fact] public void CanCreateABlobIntoTheDatabaseOfABareRepository() { - string path = CloneBareTestRepo(); + string path = InitNewRepository(); SelfCleaningDirectory directory = BuildSelfCleaningDirectory(); @@ -83,7 +83,7 @@ public void CanCreateABlobIntoTheDatabaseOfABareRepository() [InlineData("e9671e138a780833cb689753570fd10a55be84fb", "dummy.guess")] public void CanCreateABlobFromAStream(string expectedSha, string hintPath) { - string path = CloneBareTestRepo(); + string path = InitNewRepository(); var sb = new StringBuilder(); for (int i = 0; i < 6; i++) @@ -103,31 +103,53 @@ public void CanCreateABlobFromAStream(string expectedSha, string hintPath) } } + Stream PrepareMemoryStream(int contentSize) + { + var sb = new StringBuilder(); + for (int i = 0; i < contentSize; i++) + { + sb.Append(i % 10); + } + + return new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString())); + } + [Theory] - [InlineData(16, 32)] [InlineData(34, 8)] [InlineData(7584, 5879)] [InlineData(7854, 1247)] - [InlineData(7854, 9785)] [InlineData(8192, 4096)] [InlineData(8192, 4095)] [InlineData(8192, 4097)] public void CanCreateABlobFromAStreamWithANumberOfBytesToConsume(int contentSize, int numberOfBytesToConsume) { - string path = CloneBareTestRepo(); + string path = InitNewRepository(); - var sb = new StringBuilder(); - for (int i = 0; i < contentSize; i++) + + using (var repo = new Repository(path)) { - sb.Append(i % 10); + using (var stream = PrepareMemoryStream(contentSize)) + { + Blob blob = repo.ObjectDatabase.CreateBlob(stream, numberOfBytesToConsume: numberOfBytesToConsume); + Assert.Equal(numberOfBytesToConsume, blob.Size); + } } + } + + [Theory] + [InlineData(16, 32, null)] + [InlineData(7854, 9785, null)] + [InlineData(16, 32, "binary.bin")] + [InlineData(7854, 9785, "binary.bin")] + public void CreatingABlobFromTooShortAStreamThrows(int contentSize, int numberOfBytesToConsume, string hintpath) + { + string path = InitNewRepository(); using (var repo = new Repository(path)) { - using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString()))) + using (var stream = PrepareMemoryStream(contentSize)) { - Blob blob = repo.ObjectDatabase.CreateBlob(stream, numberOfBytesToConsume: numberOfBytesToConsume); - Assert.Equal(Math.Min(numberOfBytesToConsume, contentSize), blob.Size); + Assert.Throws(() => repo.ObjectDatabase.CreateBlob(stream, hintpath, numberOfBytesToConsume)); } } } @@ -135,10 +157,12 @@ public void CanCreateABlobFromAStreamWithANumberOfBytesToConsume(int contentSize [Fact] public void CreatingABlobFromANonReadableStreamThrows() { - string path = CloneStandardTestRepo(); + string path = InitNewRepository(); - using (var stream = new FileStream(Path.Combine(path, "file.txt"), FileMode.CreateNew, FileAccess.Write)) using (var repo = new Repository(path)) + using (var stream = new FileStream( + Path.Combine(repo.Info.WorkingDirectory, "file.txt"), + FileMode.CreateNew, FileAccess.Write)) { Assert.Throws(() => repo.ObjectDatabase.CreateBlob(stream)); } @@ -218,7 +242,7 @@ public void RemovingANonExistingEntryFromATreeDefinitionHasNoSideEffect() [Fact] public void CanCreateAnEmptyTree() { - string path = CloneBareTestRepo(); + string path = InitNewRepository(); using (var repo = new Repository(path)) { var td = new TreeDefinition(); @@ -364,7 +388,7 @@ public void CanCreateABinaryBlobFromAStream() { var binaryContent = new byte[] { 0, 1, 2, 3, 4, 5 }; - string path = CloneBareTestRepo(); + string path = InitNewRepository(); using (var repo = new Repository(path)) { using (var stream = new MemoryStream(binaryContent)) diff --git a/LibGit2Sharp.Tests/ReferenceFixture.cs b/LibGit2Sharp.Tests/ReferenceFixture.cs index a224f5fb1..9b25d47b4 100644 --- a/LibGit2Sharp.Tests/ReferenceFixture.cs +++ b/LibGit2Sharp.Tests/ReferenceFixture.cs @@ -648,7 +648,7 @@ public void CanMoveAReferenceToADifferentReferenceHierarchy() Assert.Equal(newName, moved.CanonicalName); Assert.Equal(oldId, moved.ResolveToDirectReference().Target.Id); - AssertRefLogEntry(repo, newName, moved.ResolveToDirectReference().Target.Id, + AssertRefLogEntry(repo, newName, moved.ResolveToDirectReference().Target.Id, string.Format("reference: renamed {0} to {1}", oldName, newName)); } } @@ -752,7 +752,7 @@ public void CanTellIfAReferenceIsValid(string refname, bool expectedResult) { using (var repo = new Repository(BareTestRepoPath)) { - Assert.Equal(expectedResult, repo.Refs.IsValidName(refname)); + Assert.Equal(expectedResult, Reference.IsValidName(refname)); } } diff --git a/LibGit2Sharp.Tests/RemoteFixture.cs b/LibGit2Sharp.Tests/RemoteFixture.cs index ebe67591d..b33213495 100644 --- a/LibGit2Sharp.Tests/RemoteFixture.cs +++ b/LibGit2Sharp.Tests/RemoteFixture.cs @@ -151,10 +151,7 @@ public void AddingARemoteWithAnInvalidNameThrows(string name) [InlineData("/", false)] public void CanTellIfARemoteNameIsValid(string refname, bool expectedResult) { - using (var repo = new Repository(BareTestRepoPath)) - { - Assert.Equal(expectedResult, repo.Network.Remotes.IsValidName(refname)); - } + Assert.Equal(expectedResult, Remote.IsValidName(refname)); } [Fact] @@ -192,5 +189,30 @@ public void CanCreateARemoteWithASpecifiedFetchRefSpec() Assert.Equal("+refs/heads/*:refs/remotes/grmpf/*", remote.RefSpecs.Single().Specification); } } + + [Fact] + public void CanDeleteExistingRemote() + { + var path = CloneStandardTestRepo(); + using (var repo = new Repository(path)) + { + Assert.NotNull(repo.Network.Remotes["origin"]); + Assert.NotEmpty(repo.Refs.FromGlob("refs/remotes/origin/*")); + + repo.Network.Remotes.Remove("origin"); + Assert.Null(repo.Network.Remotes["origin"]); + Assert.Empty(repo.Refs.FromGlob("refs/remotes/origin/*")); + } + } + + [Fact] + public void CanDeleteNonExistingRemote() + { + using (var repo = new Repository(StandardTestRepoPath)) + { + Assert.Null(repo.Network.Remotes["i_dont_exist"]); + repo.Network.Remotes.Remove("i_dont_exist"); + } + } } } diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs index f493cf7ca..f5916f5f2 100644 --- a/LibGit2Sharp.Tests/RepositoryFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryFixture.cs @@ -4,6 +4,7 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; +using System.Text.RegularExpressions; namespace LibGit2Sharp.Tests { @@ -85,6 +86,40 @@ public void CanCreateStandardRepo() } } + [Fact] + public void CanRetrieveValidVersionString() + { + // Version string format is: + // Major.Minor.Patch-LibGit2Sharp_abbrev_hash-libgit2_abbrev_hash (x86|amd64 - features) + // Example output: + // "0.17.0-unknown-06d772d (x86 - Threads, Https)" + + string versionInfo = Repository.Version; + + // The Repository.Version returned string should contain : + // version:'0.17.0' LibGit2Sharp version number. + // git2SharpHash:'unknown' ( when compiled from source ) else LibGit2Sharp library hash. + // git2hash: '06d772d' LibGit2 library hash. + // arch: 'x86' or 'amd64' LibGit2 target. + // git2Features: 'Threads, Ssh' LibGit2 features compiled with. + string regex = @"^(?\d{1,}\.\d{1,2}\.\d{1,3})-(?\w+)-(?\w+) \((?\w+) - (?(?:\w*(?:, )*\w+)*)\)$"; + + Assert.NotNull(versionInfo); + + Match regexResult = Regex.Match(versionInfo, regex); + + Assert.True(regexResult.Success, "The following version string format is enforced:" + + "Major.Minor.Patch-LibGit2Sharp_abbrev_hash-libgit2_abbrev_hash (x86|amd64 - features)"); + + GroupCollection matchGroups = regexResult.Groups; + + // Check that all groups are valid + foreach(Group group in matchGroups) + { + Assert.True(group.Success); + } + } + [Fact] public void CanCreateStandardRepoAndSpecifyAFolderWhichWillContainTheNewlyCreatedGitDirectory() { @@ -557,7 +592,7 @@ public void QueryingTheRemoteForADetachedHeadBranchReturnsNull() string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { - repo.Checkout(repo.Head.Tip.Sha, CheckoutModifiers.Force, null, null); + repo.Checkout(repo.Head.Tip.Sha, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force }); Branch trackLocal = repo.Head; Assert.Null(trackLocal.Remote); } diff --git a/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs b/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs index 0a816bc76..946d4a31a 100644 --- a/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using System.Text; using LibGit2Sharp.Tests.TestHelpers; using Xunit; @@ -174,5 +175,31 @@ public void CanProvideDifferentConfigurationFilesToARepository() AssertValueInConfigFile(systemLocation, "xpaulbettsx"); } + + [Fact] + public void CanCommitOnBareRepository() + { + string repoPath = InitNewRepository(true); + SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); + string workPath = Path.Combine(scd.RootedDirectoryPath, "work"); + Directory.CreateDirectory(workPath); + + var repositoryOptions = new RepositoryOptions + { + WorkingDirectoryPath = workPath, + IndexPath = Path.Combine(scd.RootedDirectoryPath, "index") + }; + + using (var repo = new Repository(repoPath, repositoryOptions)) + { + const string relativeFilepath = "test.txt"; + Touch(repo.Info.WorkingDirectory, relativeFilepath, "test\n"); + repo.Index.Stage(relativeFilepath); + + Assert.NotNull(repo.Commit("Initial commit", Constants.Signature, Constants.Signature)); + Assert.Equal(1, repo.Head.Commits.Count()); + Assert.Equal(1, repo.Commits.Count()); + } + } } } diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/index b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/index index 1cadb2feb..abbebf181 100644 Binary files a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/index and b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/index differ diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/info/refs b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/info/refs index 6568969b2..d3a074d46 100644 --- a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/info/refs +++ b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/info/refs @@ -2,3 +2,5 @@ 4dfaa1500526214ae7b33f9b2c1144ca8b6b1f53 refs/heads/fast_forward 83cebf5389a4adbcb80bda6b68513caee4559802 refs/heads/master 625186280ed2a6ec9b65d250ed90cf2e4acef957 refs/heads/normal_merge +24434077dec097c1203ef9e1345c0545c190936a refs/heads/rename +2bc71d0e8acfbb9fd1cc2d9d48c23dbf8aea52c9 refs/heads/rename_source diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/logs/refs/heads/rename b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/logs/refs/heads/rename new file mode 100644 index 000000000..a2466a9d2 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/logs/refs/heads/rename @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 83cebf5389a4adbcb80bda6b68513caee4559802 Jameson Miller 1398366152 -0400 branch: Created from HEAD +83cebf5389a4adbcb80bda6b68513caee4559802 9075c06ff9cd736610dea688bca7e912903ff2d1 Jameson Miller 1398366254 -0400 commit: Add content to b.txt +9075c06ff9cd736610dea688bca7e912903ff2d1 24434077dec097c1203ef9e1345c0545c190936a Jameson Miller 1398366641 -0400 commit: edit to b.txt diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/logs/refs/heads/rename_source b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/logs/refs/heads/rename_source new file mode 100644 index 000000000..1515dd26e --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/logs/refs/heads/rename_source @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 9075c06ff9cd736610dea688bca7e912903ff2d1 Jameson Miller 1398366267 -0400 branch: Created from rename +9075c06ff9cd736610dea688bca7e912903ff2d1 2bc71d0e8acfbb9fd1cc2d9d48c23dbf8aea52c9 Jameson Miller 1398366593 -0400 commit: rename and edit b.txt diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/info/packs b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/info/packs index 3cea2e143..2dd2e88a9 100644 --- a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/info/packs +++ b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/info/packs @@ -1,2 +1,2 @@ -P pack-52e214e240728e3b0ce2fc2d5e6513772fed0523.pack +P pack-f9b2f231d5e59d4a265578d02283f848a5dc4694.pack diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-52e214e240728e3b0ce2fc2d5e6513772fed0523.idx b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-52e214e240728e3b0ce2fc2d5e6513772fed0523.idx deleted file mode 100644 index a2a5e21ed..000000000 Binary files a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-52e214e240728e3b0ce2fc2d5e6513772fed0523.idx and /dev/null differ diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-52e214e240728e3b0ce2fc2d5e6513772fed0523.pack b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-52e214e240728e3b0ce2fc2d5e6513772fed0523.pack deleted file mode 100644 index faf8cbdd6..000000000 Binary files a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-52e214e240728e3b0ce2fc2d5e6513772fed0523.pack and /dev/null differ diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-f9b2f231d5e59d4a265578d02283f848a5dc4694.idx b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-f9b2f231d5e59d4a265578d02283f848a5dc4694.idx new file mode 100644 index 000000000..72d56baa5 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-f9b2f231d5e59d4a265578d02283f848a5dc4694.idx differ diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-f9b2f231d5e59d4a265578d02283f848a5dc4694.pack b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-f9b2f231d5e59d4a265578d02283f848a5dc4694.pack new file mode 100644 index 000000000..037aa5388 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/objects/pack/pack-f9b2f231d5e59d4a265578d02283f848a5dc4694.pack differ diff --git a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/packed-refs b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/packed-refs index c952e5bc6..7930b20e4 100644 --- a/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/packed-refs +++ b/LibGit2Sharp.Tests/Resources/merge_testrepo_wd/dot_git/packed-refs @@ -3,3 +3,5 @@ 4dfaa1500526214ae7b33f9b2c1144ca8b6b1f53 refs/heads/fast_forward 83cebf5389a4adbcb80bda6b68513caee4559802 refs/heads/master 625186280ed2a6ec9b65d250ed90cf2e4acef957 refs/heads/normal_merge +24434077dec097c1203ef9e1345c0545c190936a refs/heads/rename +2bc71d0e8acfbb9fd1cc2d9d48c23dbf8aea52c9 refs/heads/rename_source diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/a.txt b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/a.txt new file mode 100644 index 000000000..bc90ea420 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/a.txt @@ -0,0 +1,7 @@ +This is file a.txt +This is the 3rd revision of this file. +It +also +has +several +lines. \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/b.txt b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/b.txt new file mode 100644 index 000000000..1ca53b49d --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/b.txt @@ -0,0 +1,7 @@ +This is file b.txt +This is the 3rd revision of this file. +It +also +has +several +lines. \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/c.txt b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/c.txt new file mode 100644 index 000000000..88925a548 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/c.txt @@ -0,0 +1,7 @@ +This is file c.txt +This is the 3rd revision of this file. +It +also +has +several +lines. \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/HEAD b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/config b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/config new file mode 100644 index 000000000..78387c50b --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/config @@ -0,0 +1,8 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/index b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/index new file mode 100644 index 000000000..c39bce8fb Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/index differ diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/info/packs b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/info/packs new file mode 100644 index 000000000..59da9792c --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-29d1a036908407037b737d1cb436707551c3cedf.pack + diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.idx b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.idx new file mode 100644 index 000000000..ce6281cd8 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.idx differ diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.pack b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.pack new file mode 100644 index 000000000..e1eee599a Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.pack differ diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/master b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/master new file mode 100644 index 000000000..743c907ae --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/master @@ -0,0 +1 @@ +cb4f7f0eca7a0114cdafd8537332aa17de36a4e9 diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert new file mode 100644 index 000000000..7438cbb2d --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert @@ -0,0 +1 @@ +b6fbb29b625aabe0fb5736da6fd61d4147e4405e diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_merge b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_merge new file mode 100644 index 000000000..0a6cfc127 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_merge @@ -0,0 +1 @@ +2747045c29b5b9c5624225ce600f3117fdcf0b87 diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_rename b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_rename new file mode 100644 index 000000000..c2ca6d982 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_rename @@ -0,0 +1 @@ +c4b5cea70e4cd5b633ed0f10ae0ed5384e8190d8 diff --git a/LibGit2Sharp.Tests/Resources/testrepo_wd/dot_git/index b/LibGit2Sharp.Tests/Resources/testrepo_wd/dot_git/index index ba522b9fd..43efbb719 100644 Binary files a/LibGit2Sharp.Tests/Resources/testrepo_wd/dot_git/index and b/LibGit2Sharp.Tests/Resources/testrepo_wd/dot_git/index differ diff --git a/LibGit2Sharp.Tests/RevertFixture.cs b/LibGit2Sharp.Tests/RevertFixture.cs new file mode 100644 index 000000000..046179b17 --- /dev/null +++ b/LibGit2Sharp.Tests/RevertFixture.cs @@ -0,0 +1,395 @@ +using System.IO; +using System.Linq; +using LibGit2Sharp.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; +using System; + +namespace LibGit2Sharp.Tests +{ + public class RevertFixture : BaseFixture + { + [Fact] + public void CanRevert() + { + // The branch name to perform the revert on, + // and the file whose contents we expect to be reverted. + const string revertBranchName = "refs/heads/revert"; + const string revertedFile = "a.txt"; + + string path = CloneRevertTestRepo(); + using (var repo = new Repository(path)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + // Revert tip commit. + RevertResult result = repo.Revert(repo.Head.Tip, Constants.Signature); + Assert.NotNull(result); + Assert.Equal(RevertStatus.Reverted, result.Status); + + // Verify commit was made. + Assert.NotNull(result.Commit); + + // Verify the expected commit ID. + Assert.Equal("04746060fa753c9970d88a0b59151d7b212ac903", result.Commit.Id.Sha); + + // Verify workspace is clean. + Assert.True(repo.Index.IsFullyMerged); + Assert.False(repo.Index.RetrieveStatus().IsDirty); + + // Lookup the blob containing the expected reverted content of a.txt. + Blob expectedBlob = repo.Lookup("bc90ea420cf6c5ae3db7dcdffa0d79df567f219b"); + Assert.NotNull(expectedBlob); + + // Verify contents of Index. + IndexEntry revertedIndexEntry = repo.Index[revertedFile]; + Assert.NotNull(revertedIndexEntry); + + // Verify the contents of the index. + Assert.Equal(expectedBlob.Id, revertedIndexEntry.Id); + + // Verify contents of workspace. + string fullPath = Path.Combine(repo.Info.WorkingDirectory, revertedFile); + Assert.Equal(expectedBlob.GetContentText(new FilteringOptions(revertedFile)), File.ReadAllText(fullPath)); + } + } + + [Fact] + public void CanRevertAndNotCommit() + { + // The branch name to perform the revert on, + // and the file whose contents we expect to be reverted. + const string revertBranchName = "refs/heads/revert"; + const string revertedFile = "a.txt"; + + string path = CloneRevertTestRepo(); + using (var repo = new Repository(path)) + { + string modifiedFileFullPath = Path.Combine(repo.Info.WorkingDirectory, revertedFile); + + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + // Revert tip commit. + RevertResult result = repo.Revert(repo.Head.Tip, Constants.Signature, new RevertOptions() { CommitOnSuccess = false }); + Assert.NotNull(result); + Assert.Equal(RevertStatus.Reverted, result.Status); + + // Verify the commit was made. + Assert.Null(result.Commit); + + // Verify workspace is dirty. + FileStatus fileStatus = repo.Index.RetrieveStatus(revertedFile); + Assert.Equal(FileStatus.Staged, fileStatus); + + // This is the ID of the blob containing the expected content. + Blob expectedBlob = repo.Lookup("bc90ea420cf6c5ae3db7dcdffa0d79df567f219b"); + Assert.NotNull(expectedBlob); + + // Verify contents of Index. + IndexEntry revertedIndexEntry = repo.Index[revertedFile]; + Assert.NotNull(revertedIndexEntry); + + Assert.Equal(expectedBlob.Id, revertedIndexEntry.Id); + + // Verify contents of workspace. + string fullPath = Path.Combine(repo.Info.WorkingDirectory, revertedFile); + Assert.Equal(expectedBlob.GetContentText(new FilteringOptions(revertedFile)), File.ReadAllText(fullPath)); + } + } + + [Fact] + public void RevertWithConflictDoesNotCommit() + { + // The branch name to perform the revert on, + // and the file whose contents we expect to be reverted. + const string revertBranchName = "refs/heads/revert"; + + string path = CloneRevertTestRepo(); + using (var repo = new Repository(path)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + // The commit to revert - we know that reverting this + // specific commit will generate conflicts. + Commit commitToRevert = repo.Lookup("cb4f7f0eca7a0114cdafd8537332aa17de36a4e9"); + Assert.NotNull(commitToRevert); + + // Perform the revert and verify there were conflicts. + RevertResult result = repo.Revert(commitToRevert, Constants.Signature); + Assert.NotNull(result); + Assert.Equal(RevertStatus.Conflicts, result.Status); + Assert.Null(result.Commit); + + // Verify there is a conflict on the expected path. + Assert.False(repo.Index.IsFullyMerged); + Assert.NotNull(repo.Index.Conflicts["a.txt"]); + + // Verify the non-conflicting paths are staged. + Assert.Equal(FileStatus.Staged, repo.Index.RetrieveStatus("b.txt")); + Assert.Equal(FileStatus.Staged, repo.Index.RetrieveStatus("c.txt")); + } + } + + [Theory] + [InlineData(CheckoutFileConflictStrategy.Ours)] + [InlineData(CheckoutFileConflictStrategy.Theirs)] + public void RevertWithFileConflictStrategyOption(CheckoutFileConflictStrategy conflictStrategy) + { + // The branch name to perform the revert on, + // and the file which we expect conflicts as result of the revert. + const string revertBranchName = "refs/heads/revert"; + const string conflictedFilePath = "a.txt"; + + string path = CloneRevertTestRepo(); + using (var repo = new Repository(path)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + // Specify FileConflictStrategy. + RevertOptions options = new RevertOptions() + { + FileConflictStrategy = conflictStrategy, + }; + + RevertResult result = repo.Revert(repo.Head.Tip.Parents.First(), Constants.Signature, options); + + // Verify there is a conflict. + Assert.False(repo.Index.IsFullyMerged); + + Conflict conflict = repo.Index.Conflicts[conflictedFilePath]; + Assert.NotNull(conflict); + + Assert.NotNull(conflict); + Assert.NotNull(conflict.Theirs); + Assert.NotNull(conflict.Ours); + + // Get the blob containing the expected content. + Blob expectedBlob = null; + switch (conflictStrategy) + { + case CheckoutFileConflictStrategy.Theirs: + expectedBlob = repo.Lookup(conflict.Theirs.Id); + break; + case CheckoutFileConflictStrategy.Ours: + expectedBlob = repo.Lookup(conflict.Ours.Id); + break; + default: + throw new Exception("Unexpected FileConflictStrategy"); + } + + Assert.NotNull(expectedBlob); + + // Check the content of the file on disk matches what is expected. + string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictedFilePath)); + Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictedFilePath))); + } + } + + [Fact] + public void RevertReportsCheckoutProgress() + { + const string revertBranchName = "refs/heads/revert"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + bool wasCalled = false; + + RevertOptions options = new RevertOptions() + { + OnCheckoutProgress = (path, completed, total) => wasCalled = true + }; + + repo.Revert(repo.Head.Tip, Constants.Signature, options); + + Assert.True(wasCalled); + } + } + + [Fact] + public void RevertReportsCheckoutNotification() + { + const string revertBranchName = "refs/heads/revert"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + bool wasCalled = false; + CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; + + RevertOptions options = new RevertOptions() + { + OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotifyFlags = notificationType; return true; }, + CheckoutNotifyFlags = CheckoutNotifyFlags.Updated, + }; + + repo.Revert(repo.Head.Tip, Constants.Signature, options); + + Assert.True(wasCalled); + } + } + + [Theory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void RevertFindsRenames(bool? findRenames) + { + // The environment is set up such that: + // - file d.txt is edited in the commit that is to be reverted (commit A) + // - file d.txt is renamed to d_renamed.txt + // - commit A is reverted. + // If rename detection is enabled, then the revert is applied + // to d_renamed.txt. If rename detection is not enabled, + // then the revert results in a conflict. + const string revertBranchName = "refs/heads/revert_rename"; + const string commitIdToRevert = "ca3e813"; + const string expectedBlobId = "0ff3bbb9c8bba2291654cd64067fa417ff54c508"; + const string modifiedFilePath = "d_renamed.txt"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + Branch currentBranch = repo.Checkout(revertBranchName); + Assert.NotNull(currentBranch); + + Commit commitToRevert = repo.Lookup(commitIdToRevert); + Assert.NotNull(currentBranch); + + RevertOptions options; + if (findRenames.HasValue) + { + options = new RevertOptions() + { + FindRenames = findRenames.Value, + }; + } + else + { + options = new RevertOptions(); + } + + RevertResult result = repo.Revert(commitToRevert, Constants.Signature, options); + Assert.NotNull(result); + + if(!findRenames.HasValue || + findRenames.Value == true) + { + Assert.Equal(RevertStatus.Reverted, result.Status); + Assert.NotNull(result.Commit); + Blob expectedBlob = repo.Lookup(expectedBlobId); + Assert.NotNull(expectedBlob); + + GitObject blob = result.Commit.Tree[modifiedFilePath].Target as Blob; + Assert.NotNull(blob); + Assert.Equal(blob.Id, expectedBlob.Id); + + // Verify contents of workspace + string fullPath = Path.Combine(repo.Info.WorkingDirectory, modifiedFilePath); + Assert.Equal(expectedBlob.GetContentText(new FilteringOptions(modifiedFilePath)), File.ReadAllText(fullPath)); + } + else + { + Assert.Equal(RevertStatus.Conflicts, result.Status); + Assert.Null(result.Commit); + } + } + } + + [Theory] + [InlineData(1, "a04ef5f22c2413a9743046436c0e5354ed903f78")] + [InlineData(2, "1ae0cd88802bb4f4e6413ba63e41376d235b6fd0")] + public void CanRevertMergeCommit(int mainline, string expectedId) + { + const string revertBranchName = "refs/heads/revert_merge"; + const string commitIdToRevert = "2747045"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + Commit commitToRevert = repo.Lookup(commitIdToRevert); + Assert.NotNull(commitToRevert); + + RevertOptions options = new RevertOptions() + { + Mainline = mainline, + }; + + RevertResult result = repo.Revert(commitToRevert, Constants.Signature, options); + + Assert.NotNull(result); + Assert.Equal(RevertStatus.Reverted, result.Status); + Assert.Equal(result.Commit.Sha, expectedId); + + if(mainline == 1) + { + // In this case, we expect "d_renamed.txt" to be reverted (deleted), + // and a.txt to match the tip of the "revert" branch. + Assert.Equal(FileStatus.Nonexistent, repo.Index.RetrieveStatus("d_renamed.txt")); + + // This is the commit containing the expected contents of a.txt. + Commit commit = repo.Lookup("b6fbb29b625aabe0fb5736da6fd61d4147e4405e"); + Assert.NotNull(commit); + Assert.Equal(commit["a.txt"].Target.Id, repo.Index["a.txt"].Id); + } + else if(mainline == 2) + { + // In this case, we expect "d_renamed.txt" to be preset, + // and a.txt to match the tip of the master branch. + + // In this case, we expect "d_renamed.txt" to be reverted (deleted), + // and a.txt to match the tip of the "revert" branch. + Assert.Equal(FileStatus.Unaltered, repo.Index.RetrieveStatus("d_renamed.txt")); + + // This is the commit containing the expected contents of "d_renamed.txt". + Commit commit = repo.Lookup("c4b5cea70e4cd5b633ed0f10ae0ed5384e8190d8"); + Assert.NotNull(commit); + Assert.Equal(commit["d_renamed.txt"].Target.Id, repo.Index["d_renamed.txt"].Id); + + // This is the commit containing the expected contents of a.txt. + commit = repo.Lookup("cb4f7f0eca7a0114cdafd8537332aa17de36a4e9"); + Assert.NotNull(commit); + Assert.Equal(commit["a.txt"].Target.Id, repo.Index["a.txt"].Id); + } + } + } + + [Fact] + public void CanNotRevertAMergeCommitWithoutSpecifyingTheMainlineBranch() + { + const string revertBranchName = "refs/heads/revert_merge"; + const string commitIdToRevert = "2747045"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + var commitToRevert = repo.Lookup(commitIdToRevert); + Assert.NotNull(commitToRevert); + + Assert.Throws(() => repo.Revert(commitToRevert, Constants.Signature)); + } + } + } +} diff --git a/LibGit2Sharp.Tests/StatusFixture.cs b/LibGit2Sharp.Tests/StatusFixture.cs index b70ff0ae0..4a63bc93d 100644 --- a/LibGit2Sharp.Tests/StatusFixture.cs +++ b/LibGit2Sharp.Tests/StatusFixture.cs @@ -495,8 +495,12 @@ public void RetrievingTheStatusOfTheRepositoryHonorsTheGitIgnoreDirectivesThroug Assert.Equal(FileStatus.Ignored, repo.Index.RetrieveStatus("bin/look-ma.txt")); Assert.Equal(FileStatus.Untracked, repo.Index.RetrieveStatus("bin/what-about-me.txt")); + // bin/* is considered as ignoring the dir itself newStatus = repo.Index.RetrieveStatus(); + Assert.Equal(new[] { "bin" + dirSep }, newStatus.Ignored.Select(s => s.FilePath)); + // if we recurse into ignored dirs, then we get the actual list + newStatus = repo.Index.RetrieveStatus(new StatusOptions { RecurseIgnoredDirs = true }); Assert.Equal(new[] { "bin" + dirSep + "look-ma.txt" }, newStatus.Ignored.Select(s => s.FilePath)); Assert.True(newStatus.Untracked.Select(s => s.FilePath).Contains("bin" + dirSep + "what-about-me.txt")); } diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index c4514e3c1..5dfa5b123 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -30,6 +30,7 @@ static BaseFixture() public static string ShallowTestRepoPath { get; private set; } public static string MergedTestRepoWorkingDirPath { get; private set; } public static string MergeTestRepoWorkingDirPath { get; private set; } + public static string RevertTestRepoWorkingDirPath { get; private set; } public static string SubmoduleTestRepoWorkingDirPath { get; private set; } public static DirectoryInfo ResourcesDirectory { get; private set; } @@ -63,6 +64,7 @@ private static void SetUpTestEnvironment() ShallowTestRepoPath = Path.Combine(ResourcesDirectory.FullName, "shallow.git"); MergedTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "mergedrepo_wd"); MergeTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "merge_testrepo_wd"); + RevertTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "revert_testrepo_wd"); SubmoduleTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_wd"); } @@ -129,6 +131,11 @@ protected string CloneMergeTestRepo() return Clone(MergeTestRepoWorkingDirPath); } + protected string CloneRevertTestRepo() + { + return Clone(RevertTestRepoWorkingDirPath); + } + public string CloneSubmoduleTestRepo() { var submoduleTarget = Path.Combine(ResourcesDirectory.FullName, "submodule_target_wd"); diff --git a/LibGit2Sharp.Tests/TupleFixture.cs b/LibGit2Sharp.Tests/TupleFixture.cs deleted file mode 100644 index c6258648b..000000000 --- a/LibGit2Sharp.Tests/TupleFixture.cs +++ /dev/null @@ -1,54 +0,0 @@ -using LibGit2Sharp.Core.Compat; -using Xunit; - -namespace LibGit2Sharp.Tests -{ - public class TupleFixture - { - const int integer = 2; - const string stringy = "hello"; - - private readonly Tuple sut = new Tuple(integer, stringy); - - [Fact] - public void Properties() - { - Assert.Equal(integer, sut.Item1); - Assert.Equal(stringy, sut.Item2); - } - - [Fact] - public void GetHashCodeIsTheSame() - { - var sut2 = new Tuple(integer, stringy); - - Assert.Equal(sut2.GetHashCode(), sut.GetHashCode()); - } - - [Fact] - public void GetHashCodeIsDifferent() - { - var sut2 = new Tuple(integer + 1, stringy); - - Assert.NotEqual(sut2.GetHashCode(), sut.GetHashCode()); - } - - [Fact] - public void VerifyEquals() - { - var sut2 = new Tuple(integer, stringy); - - Assert.True(sut.Equals(sut2)); - Assert.True(Equals(sut, sut2)); - } - - [Fact] - public void VerifyNotEquals() - { - var sut2 = new Tuple(integer + 1, stringy); - - Assert.False(sut.Equals(sut2)); - Assert.False(Equals(sut, sut2)); - } - } -} diff --git a/LibGit2Sharp/BlameHunk.cs b/LibGit2Sharp/BlameHunk.cs index 1fdbe16bc..79dbf3945 100644 --- a/LibGit2Sharp/BlameHunk.cs +++ b/LibGit2Sharp/BlameHunk.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.Globalization; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp { diff --git a/LibGit2Sharp/Branch.cs b/LibGit2Sharp/Branch.cs index ae2fa7d96..1e64b8b9c 100644 --- a/LibGit2Sharp/Branch.cs +++ b/LibGit2Sharp/Branch.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Handlers; namespace LibGit2Sharp @@ -234,9 +233,37 @@ public virtual void Checkout() /// Options controlling checkout behavior. /// Callback method to report checkout progress updates through. /// to manage checkout notifications. + [Obsolete("This overload will be removed in the next release. Please use Branch.Checkout(CheckoutOptions, Signature) instead.")] public virtual void Checkout(CheckoutModifiers checkoutModifiers, CheckoutProgressHandler onCheckoutProgress, CheckoutNotificationOptions checkoutNotificationOptions) { - repo.Checkout(this, checkoutModifiers, onCheckoutProgress, checkoutNotificationOptions); + var options = new CheckoutOptions + { + CheckoutModifiers = checkoutModifiers, + OnCheckoutProgress = onCheckoutProgress, + }; + + if (checkoutNotificationOptions != null) + { + options.OnCheckoutNotify = checkoutNotificationOptions.CheckoutNotifyHandler; + options.CheckoutNotifyFlags = checkoutNotificationOptions.NotifyFlags; + } + + Checkout(options, null); + } + + /// + /// Checkout the tip commit of this object with + /// parameter specifying checkout + /// behavior. If this commit is the current tip of the branch, will + /// checkout the named branch. Otherwise, will checkout the tip + /// commit as a detached HEAD. + /// + /// controlling checkout behavior. + /// Identity for use when updating the reflog. + public virtual void Checkout(CheckoutOptions options, Signature signature = null) + { + Ensure.ArgumentNotNull(options, "options"); + repo.Checkout(this, options, signature); } private Branch ResolveTrackedBranch() diff --git a/LibGit2Sharp/BranchCollection.cs b/LibGit2Sharp/BranchCollection.cs index 8075bada7..d09513284 100644 --- a/LibGit2Sharp/BranchCollection.cs +++ b/LibGit2Sharp/BranchCollection.cs @@ -91,7 +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_iterator(repo, GitBranchType.GIT_BRANCH_LOCAL | GitBranchType.GIT_BRANCH_REMOTE) + return Proxy.git_branch_iterator(repo, GitBranchType.GIT_BRANCH_ALL) .ToList().GetEnumerator(); } @@ -166,7 +166,7 @@ public virtual void Remove(Branch branch) /// Message added to the reflog. If null, the default is "branch: renamed [old] to [new]". /// True to allow silent overwriting a potentially existing branch, false otherwise. /// A new . - public virtual Branch Move(Branch branch, string newName, Signature signature, string logMessage = null, bool allowOverwrite = false) + public virtual Branch Rename(Branch branch, string newName, Signature signature, string logMessage = null, bool allowOverwrite = false) { Ensure.ArgumentNotNull(branch, "branch"); Ensure.ArgumentNotNullOrEmptyString(newName, "newName"); @@ -195,6 +195,33 @@ public virtual Branch Move(Branch branch, string newName, Signature signature, s return newBranch; } + /// + /// Rename an existing local branch + /// + /// The current local branch. + /// The new name the existing branch should bear. + /// Identity used for updating the reflog + /// Message added to the reflog. If null, the default is "branch: renamed [old] to [new]". + /// True to allow silent overwriting a potentially existing branch, false otherwise. + /// A new . + [Obsolete("This will be removed in the next release. Please use BranchCollection.Rename(Branch, string, Signature, string, bool) instead.")] + public virtual Branch Move(Branch branch, string newName, Signature signature, string logMessage = null, bool allowOverwrite = false) + { + return Rename(branch, newName, signature, logMessage, allowOverwrite); + } + + /// + /// Rename an existing local branch, using the default reflog message + /// + /// The current local branch. + /// The new name the existing branch should bear. + /// True to allow silent overwriting a potentially existing branch, false otherwise. + /// A new . + public virtual Branch Rename(Branch branch, string newName, bool allowOverwrite = false) + { + return Rename(branch, newName, null, null, allowOverwrite); + } + /// /// Rename an existing local branch, using the default reflog message /// @@ -202,9 +229,10 @@ public virtual Branch Move(Branch branch, string newName, Signature signature, s /// The new name the existing branch should bear. /// True to allow silent overwriting a potentially existing branch, false otherwise. /// A new . + [Obsolete("This will be removed in the next release. Please use BranchCollection.Rename(Branch, string, bool) instead.")] public virtual Branch Move(Branch branch, string newName, bool allowOverwrite = false) { - return Move(branch, newName, null, null, allowOverwrite); + return Rename(branch, newName, allowOverwrite); } /// diff --git a/LibGit2Sharp/BranchCollectionExtensions.cs b/LibGit2Sharp/BranchCollectionExtensions.cs index c63dd3217..4adebf68e 100644 --- a/LibGit2Sharp/BranchCollectionExtensions.cs +++ b/LibGit2Sharp/BranchCollectionExtensions.cs @@ -1,4 +1,5 @@ using LibGit2Sharp.Core; +using System; namespace LibGit2Sharp { @@ -82,7 +83,7 @@ public static void Remove(this BranchCollection branches, string name, bool isRe /// True to allow silent overwriting a potentially existing branch, false otherwise. /// The being worked with. /// A new . - public static Branch Move(this BranchCollection branches, string currentName, string newName, bool allowOverwrite = false) + public static Branch Rename(this BranchCollection branches, string currentName, string newName, bool allowOverwrite = false) { Ensure.ArgumentNotNullOrEmptyString(currentName, "currentName"); Ensure.ArgumentNotNullOrEmptyString(newName, "newName"); @@ -94,7 +95,21 @@ public static Branch Move(this BranchCollection branches, string currentName, st throw new LibGit2SharpException("No branch named '{0}' exists in the repository."); } - return branches.Move(branch, newName, allowOverwrite); + return branches.Rename(branch, newName, allowOverwrite); + } + + /// + /// Rename an existing local branch, using the default reflog message + /// + /// The current branch name. + /// The new name the existing branch should bear. + /// True to allow silent overwriting a potentially existing branch, false otherwise. + /// The being worked with. + /// A new . + [Obsolete("This will be removed in the next release. Please use BranchCollection.Rename(string, string, bool) instead.")] + public static Branch Move(this BranchCollection branches, string currentName, string newName, bool allowOverwrite = false) + { + return Rename(branches, currentName, newName, allowOverwrite); } } } diff --git a/LibGit2Sharp/BranchUpdater.cs b/LibGit2Sharp/BranchUpdater.cs index e31a94703..83a61d34c 100644 --- a/LibGit2Sharp/BranchUpdater.cs +++ b/LibGit2Sharp/BranchUpdater.cs @@ -125,7 +125,7 @@ private void SetUpstream(string upstreamBranchName) /// The merge branch in the upstream remote's namespace. private void SetUpstreamBranch(string mergeBranchName) { - string configKey = string.Format("branch.{0}.merge", branch.Name); + string configKey = string.Format(CultureInfo.InvariantCulture, "branch.{0}.merge", branch.Name); if (string.IsNullOrEmpty(mergeBranchName)) { @@ -143,7 +143,7 @@ private void SetUpstreamBranch(string mergeBranchName) /// The name of the remote to set as the upstream branch. private void SetUpstreamRemote(string remoteName) { - string configKey = string.Format("branch.{0}.remote", branch.Name); + string configKey = string.Format(CultureInfo.InvariantCulture, "branch.{0}.remote", branch.Name); if (string.IsNullOrEmpty(remoteName)) { diff --git a/LibGit2Sharp/BuiltInFeatures.cs b/LibGit2Sharp/BuiltInFeatures.cs new file mode 100644 index 000000000..db6a1a0ed --- /dev/null +++ b/LibGit2Sharp/BuiltInFeatures.cs @@ -0,0 +1,33 @@ +using System; + +namespace LibGit2Sharp +{ + /// + /// Flags to identify libgit2 compiled features. + /// + [Flags] + public enum BuiltInFeatures + { + /// + /// No optional features are compiled into libgit2. + /// + None = 0, + + /// + /// Threading support is compiled into libgit2. + /// + Threads = (1 << 0), + + /// + /// Support for remotes over the HTTPS protocol is compiled into + /// libgit2. + /// + Https = (1 << 1), + + /// + /// Support for remotes over the SSH protocol is compiled into + /// libgit2. + /// + Ssh = (1 << 2), + } +} diff --git a/LibGit2Sharp/CheckoutCallbacks.cs b/LibGit2Sharp/CheckoutCallbacks.cs index fa8817b81..dc03846bf 100644 --- a/LibGit2Sharp/CheckoutCallbacks.cs +++ b/LibGit2Sharp/CheckoutCallbacks.cs @@ -69,7 +69,7 @@ public checkout_notify_cb CheckoutNotifyCallback /// that should be wrapped in the native callback. /// delegate to call in response to checkout notification callback. /// The delegate with signature matching the expected native callback. - internal static CheckoutCallbacks GenerateCheckoutCallbacks(CheckoutProgressHandler onCheckoutProgress, CheckoutNotifyHandler onCheckoutNotify) + internal static CheckoutCallbacks From(CheckoutProgressHandler onCheckoutProgress, CheckoutNotifyHandler onCheckoutNotify) { return new CheckoutCallbacks(onCheckoutProgress, onCheckoutNotify); } diff --git a/LibGit2Sharp/CheckoutFileConflictStrategy.cs b/LibGit2Sharp/CheckoutFileConflictStrategy.cs new file mode 100644 index 000000000..578ebe03e --- /dev/null +++ b/LibGit2Sharp/CheckoutFileConflictStrategy.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LibGit2Sharp +{ + /// + /// Enum specifying what content checkout should write to disk + /// for conflicts. + /// + public enum CheckoutFileConflictStrategy + { + /// + /// Use the default behavior for handling file conflicts. This is + /// controlled by the merge.conflictstyle config option, and is "Merge" + /// if no option is explicitly set. + /// + Normal, + + /// + /// For conflicting files, checkout the "ours" (stage 2) version of + /// the file from the index. + /// + Ours, + + /// + /// For conflicting files, checkout the "theirs" (stage 3) version of + /// the file from the index. + /// + Theirs, + + /// + /// Write normal merge files for conflicts. + /// + Merge, + + /// + /// Write diff3 formated files for conflicts. + /// + Diff3 + } +} diff --git a/LibGit2Sharp/CheckoutNotificationOptions.cs b/LibGit2Sharp/CheckoutNotificationOptions.cs index 97b5012c0..c1d0a1672 100644 --- a/LibGit2Sharp/CheckoutNotificationOptions.cs +++ b/LibGit2Sharp/CheckoutNotificationOptions.cs @@ -45,6 +45,7 @@ public enum CheckoutNotifyFlags /// /// Class to specify options and callback on CheckoutNotifications. /// + [Obsolete("This class will be removed in the next release. Specify CheckoutNotification options through CheckoutOptions instead.")] public class CheckoutNotificationOptions { /// diff --git a/LibGit2Sharp/CheckoutOptions.cs b/LibGit2Sharp/CheckoutOptions.cs index 69fd04398..9e297cd47 100644 --- a/LibGit2Sharp/CheckoutOptions.cs +++ b/LibGit2Sharp/CheckoutOptions.cs @@ -1,11 +1,12 @@ -using LibGit2Sharp.Handlers; +using LibGit2Sharp.Core; +using LibGit2Sharp.Handlers; namespace LibGit2Sharp { /// /// Collection of parameters controlling Checkout behavior. /// - public sealed class CheckoutOptions + public sealed class CheckoutOptions : IConvertableToGitCheckoutOpts { /// /// Options controlling checkout behavior. @@ -13,13 +14,39 @@ public sealed class CheckoutOptions public CheckoutModifiers CheckoutModifiers { get; set; } /// - /// Callback method to report checkout progress updates through. + /// The flags specifying what conditions are + /// reported through the OnCheckoutNotify delegate. /// + public CheckoutNotifyFlags CheckoutNotifyFlags { get; set; } + + /// + /// Delegate to be called during checkout for files that match + /// desired filter specified with the NotifyFlags property. + /// + public CheckoutNotifyHandler OnCheckoutNotify { get; set; } + + /// Delegate through which checkout will notify callers of + /// certain conditions. The conditions that are reported is + /// controlled with the CheckoutNotifyFlags property. public CheckoutProgressHandler OnCheckoutProgress { get; set; } + CheckoutStrategy IConvertableToGitCheckoutOpts.CheckoutStrategy + { + get + { + return CheckoutModifiers.HasFlag(CheckoutModifiers.Force) ? + CheckoutStrategy.GIT_CHECKOUT_FORCE : CheckoutStrategy.GIT_CHECKOUT_SAFE; + } + } + /// - /// Options to manage checkout notifications. + /// Generate a object with the delegates + /// hooked up to the native callbacks. /// - public CheckoutNotificationOptions CheckoutNotificationOptions { get; set; } + /// + CheckoutCallbacks IConvertableToGitCheckoutOpts.GenerateCallbacks() + { + return CheckoutCallbacks.From(OnCheckoutProgress, OnCheckoutNotify); + } } } diff --git a/LibGit2Sharp/CloneOptions.cs b/LibGit2Sharp/CloneOptions.cs index 09e513f75..65b98bd04 100644 --- a/LibGit2Sharp/CloneOptions.cs +++ b/LibGit2Sharp/CloneOptions.cs @@ -1,11 +1,12 @@ -using LibGit2Sharp.Handlers; +using LibGit2Sharp.Core; +using LibGit2Sharp.Handlers; namespace LibGit2Sharp { /// /// Options to define clone behaviour /// - public sealed class CloneOptions + public sealed class CloneOptions : IConvertableToGitCheckoutOpts { /// /// Creates default for a non-bare clone @@ -40,5 +41,29 @@ public CloneOptions() /// Credentials to use for user/pass authentication /// public Credentials Credentials { get; set; } + + #region IConvertableToGitCheckoutOpts + + CheckoutCallbacks IConvertableToGitCheckoutOpts.GenerateCallbacks() + { + return CheckoutCallbacks.From(OnCheckoutProgress, null); + } + + CheckoutStrategy IConvertableToGitCheckoutOpts.CheckoutStrategy + { + get + { + return this.Checkout ? + CheckoutStrategy.GIT_CHECKOUT_SAFE_CREATE : + CheckoutStrategy.GIT_CHECKOUT_NONE; + } + } + + CheckoutNotifyFlags IConvertableToGitCheckoutOpts.CheckoutNotifyFlags + { + get { return CheckoutNotifyFlags.None; } + } + + #endregion } } diff --git a/LibGit2Sharp/Commit.cs b/LibGit2Sharp/Commit.cs index 6f96ec9b1..6ea9d0608 100644 --- a/LibGit2Sharp/Commit.cs +++ b/LibGit2Sharp/Commit.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.Linq; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp diff --git a/LibGit2Sharp/CommitLog.cs b/LibGit2Sharp/CommitLog.cs index a5306c8c3..1056437af 100644 --- a/LibGit2Sharp/CommitLog.cs +++ b/LibGit2Sharp/CommitLog.cs @@ -81,29 +81,6 @@ public ICommitLog QueryBy(CommitFilter filter) return new CommitLog(repo, filter); } - /// - /// Find the best possible common ancestor given two s. - /// - /// The first . - /// The second . - /// The common ancestor or null if none found. - [Obsolete("This method will be removed in the next release. Please use FindMergeBase(Commit, Commit).")] - public Commit FindCommonAncestor(Commit first, Commit second) - { - return FindMergeBase(first, second); - } - - /// - /// Find the best possible common ancestor given two or more . - /// - /// The s for which to find the common ancestor. - /// The common ancestor or null if none found. - [Obsolete("This method will be removed in the next release. Please use FindMergeBase(IEnumerable, MergeBaseFindingStrategy).")] - public Commit FindCommonAncestor(IEnumerable commits) - { - return FindMergeBase(commits, MergeBaseFindingStrategy.Octopus); - } - /// /// Find the best possible merge base given two s. /// diff --git a/LibGit2Sharp/Configuration.cs b/LibGit2Sharp/Configuration.cs index 43f4eb204..f70442245 100644 --- a/LibGit2Sharp/Configuration.cs +++ b/LibGit2Sharp/Configuration.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; @@ -89,7 +88,8 @@ public Configuration(string globalConfigurationFileLocation = null, string xdgCo /// public virtual bool HasConfig(ConfigurationLevel level) { - using (ConfigurationSafeHandle handle = RetrieveConfigurationHandle(level, false)) + using (ConfigurationSafeHandle snapshot = Snapshot ()) + using (ConfigurationSafeHandle handle = RetrieveConfigurationHandle(level, false, snapshot)) { return handle != null; } @@ -118,7 +118,7 @@ public virtual void Unset(string key, ConfigurationLevel level = ConfigurationLe { Ensure.ArgumentNotNullOrEmptyString(key, "key"); - using (ConfigurationSafeHandle h = RetrieveConfigurationHandle(level, true)) + using (ConfigurationSafeHandle h = RetrieveConfigurationHandle(level, true, configHandle)) { Proxy.git_config_delete(h, key); } @@ -165,7 +165,10 @@ public virtual ConfigurationEntry Get(string key) { Ensure.ArgumentNotNullOrEmptyString(key, "key"); - return Proxy.git_config_get_entry(configHandle, key); + using (ConfigurationSafeHandle snapshot = Snapshot()) + { + return Proxy.git_config_get_entry(snapshot, key); + } } /// @@ -193,7 +196,8 @@ public virtual ConfigurationEntry Get(string key, ConfigurationLevel level { Ensure.ArgumentNotNullOrEmptyString(key, "key"); - using (ConfigurationSafeHandle handle = RetrieveConfigurationHandle(level, false)) + using (ConfigurationSafeHandle snapshot = Snapshot()) + using (ConfigurationSafeHandle handle = RetrieveConfigurationHandle(level, false, snapshot)) { if (handle == null) { @@ -225,7 +229,7 @@ public virtual void Set(string key, T value, ConfigurationLevel level = Confi { Ensure.ArgumentNotNullOrEmptyString(key, "key"); - using (ConfigurationSafeHandle h = RetrieveConfigurationHandle(level, true)) + using (ConfigurationSafeHandle h = RetrieveConfigurationHandle(level, true, configHandle)) { if (!configurationTypedUpdater.ContainsKey(typeof(T))) { @@ -247,18 +251,19 @@ public virtual IEnumerable> Find(string regexp, { Ensure.ArgumentNotNullOrEmptyString(regexp, "regexp"); - using (ConfigurationSafeHandle h = RetrieveConfigurationHandle(level, true)) + using (ConfigurationSafeHandle snapshot = Snapshot()) + using (ConfigurationSafeHandle h = RetrieveConfigurationHandle(level, true, snapshot)) { return Proxy.git_config_iterator_glob(h, regexp, BuildConfigEntry).ToList(); } } - private ConfigurationSafeHandle RetrieveConfigurationHandle(ConfigurationLevel level, bool throwIfStoreHasNotBeenFound) + private ConfigurationSafeHandle RetrieveConfigurationHandle(ConfigurationLevel level, bool throwIfStoreHasNotBeenFound, ConfigurationSafeHandle fromHandle) { ConfigurationSafeHandle handle = null; - if (configHandle != null) + if (fromHandle != null) { - handle = Proxy.git_config_open_level(configHandle, level); + handle = Proxy.git_config_open_level(fromHandle, level); } if (handle == null && throwIfStoreHasNotBeenFound) @@ -346,8 +351,14 @@ internal Signature BuildSignature(DateTimeOffset now, bool shouldThrowIfNotFound return new Signature( name != null ? name.Value : "unknown", - email != null ? email.Value : string.Format("{0}@{1}", Environment.UserName, Environment.UserDomainName), + email != null ? email.Value : string.Format( + CultureInfo.InvariantCulture, "{0}@{1}", Environment.UserName, Environment.UserDomainName), now); } + + private ConfigurationSafeHandle Snapshot() + { + return Proxy.git_config_snapshot(configHandle); + } } } diff --git a/LibGit2Sharp/ContentChanges.cs b/LibGit2Sharp/ContentChanges.cs index 01fb41751..e5d84503e 100644 --- a/LibGit2Sharp/ContentChanges.cs +++ b/LibGit2Sharp/ContentChanges.cs @@ -13,7 +13,6 @@ namespace LibGit2Sharp public class ContentChanges { private readonly StringBuilder patchBuilder = new StringBuilder(); - private bool isBinaryComparison; /// /// Needed for mocking purposes. @@ -31,7 +30,7 @@ internal ContentChanges(Repository repo, Blob oldBlob, Blob newBlob, GitDiffOpti internal ContentChanges(bool isBinaryComparison) { - this.isBinaryComparison = isBinaryComparison; + this.IsBinaryComparison = isBinaryComparison; } internal void AppendToPatch(string patch) @@ -60,11 +59,7 @@ public virtual string Patch /// /// Determines if at least one side of the comparison holds binary content. /// - public virtual bool IsBinaryComparison - { - get { return isBinaryComparison; } - private set { isBinaryComparison = value; } - } + public virtual bool IsBinaryComparison { get; private set; } private int FileCallback(GitDiffDelta delta, float progress, IntPtr payload) { diff --git a/LibGit2Sharp/Core/Compat/EnumExtensions.cs b/LibGit2Sharp/Core/Compat/EnumExtensions.cs deleted file mode 100644 index beac535f8..000000000 --- a/LibGit2Sharp/Core/Compat/EnumExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace LibGit2Sharp.Core.Compat -{ - internal static class EnumExtensions - { - // Based on the following Stack Overflow post - // http://stackoverflow.com/questions/93744/most-common-c-sharp-bitwise-operations-on-enums/417217#417217 - // Reused with permission of Hugo Bonacci on Jan 04 2013. - public static bool HasFlag(this Enum enumInstance, T entry) - { - return ((int)(object)enumInstance & (int)(object)entry) == (int)(object)(entry); - } - } -} diff --git a/LibGit2Sharp/Core/Compat/Environment.cs b/LibGit2Sharp/Core/Compat/Environment.cs deleted file mode 100644 index 49b8e33c7..000000000 --- a/LibGit2Sharp/Core/Compat/Environment.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace LibGit2Sharp.Core.Compat -{ - /// - /// Provides information about, and means to manipulate, the current environment and platform. - /// - public static class Environment - { - /// - /// Determines whether the current process is a 64-bit process. - /// - public static bool Is64BitProcess - { - get { return IntPtr.Size == 8; } - } - } -} diff --git a/LibGit2Sharp/Core/Compat/Lazy.cs b/LibGit2Sharp/Core/Compat/Lazy.cs deleted file mode 100644 index 2f08a24a9..000000000 --- a/LibGit2Sharp/Core/Compat/Lazy.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Diagnostics; - -namespace LibGit2Sharp.Core.Compat -{ - /// - /// Provides support for lazy initialization. - /// - /// Specifies the type of object that is being lazily initialized. - [DebuggerStepThrough] - public class Lazy - { - private readonly Func evaluator; - private TType value; - private bool hasBeenEvaluated; - private readonly object padLock = new object(); - - /// - /// Initializes a new instance of the class. - /// - /// The that will be called to evaluate the value of this Lazy instance. - public Lazy(Func evaluator) - { - Ensure.ArgumentNotNull(evaluator, "evaluator"); - - this.evaluator = evaluator; - } - - /// - /// Gets the lazily initialized value of the current instance. - /// - public TType Value - { - get { return Evaluate(); } - } - - private TType Evaluate() - { - if (!hasBeenEvaluated) - { - lock (padLock) - { - if (!hasBeenEvaluated) - { - value = evaluator(); - hasBeenEvaluated = true; - } - } - } - - return value; - } - } -} diff --git a/LibGit2Sharp/Core/Compat/Tuple.cs b/LibGit2Sharp/Core/Compat/Tuple.cs deleted file mode 100644 index b8cf7f005..000000000 --- a/LibGit2Sharp/Core/Compat/Tuple.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Collections.Generic; - -namespace LibGit2Sharp.Core.Compat -{ - /// - /// Represents a 2-tuple, or pair. - /// - /// The type of the tuple's first component. - /// The type of the tuple's second component. - public class Tuple - { - private readonly KeyValuePair kvp; - - /// - /// Initializes a new instance of the class. - /// - /// The value of the tuple's first component. - /// The value of the tuple's second component. - public Tuple(T1 item1, T2 item2) - { - kvp = new KeyValuePair(item1, item2); - } - - /// - /// Gets the value of the current object's second component. - /// - public T2 Item2 - { - get { return kvp.Value; } - } - - /// - /// Gets the value of the current object's first component. - /// - public T1 Item1 - { - get { return kvp.Key; } - } - - /// - /// Returns the hash code for the current object. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return kvp.GetHashCode(); - } - - /// - /// Returns a value that indicates whether the current object is equal to a specified object. - /// - /// The object to compare with this instance. - /// true if the current instance is equal to the specified object; otherwise, false. - public override bool Equals(object obj) - { - if (!(obj is Tuple)) - { - return false; - } - return kvp.Equals(((Tuple)obj).kvp); - } - - - } -} diff --git a/LibGit2Sharp/Core/EncodingMarshaler.cs b/LibGit2Sharp/Core/EncodingMarshaler.cs index 7cc879222..ad85c5ec9 100644 --- a/LibGit2Sharp/Core/EncodingMarshaler.cs +++ b/LibGit2Sharp/Core/EncodingMarshaler.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Globalization; using System.Runtime.InteropServices; using System.Text; @@ -43,7 +44,7 @@ public virtual IntPtr MarshalManagedToNative(Object managedObj) if (str == null) { throw new MarshalDirectiveException( - string.Format("{0} must be used on a string.", GetType().Name)); + string.Format(CultureInfo.InvariantCulture, "{0} must be used on a string.", GetType().Name)); } return FromManaged(encoding, str); diff --git a/LibGit2Sharp/Core/Ensure.cs b/LibGit2Sharp/Core/Ensure.cs index 368ffe9eb..19925489e 100644 --- a/LibGit2Sharp/Core/Ensure.cs +++ b/LibGit2Sharp/Core/Ensure.cs @@ -67,7 +67,8 @@ public static void ArgumentDoesNotContainZeroByte(string argumentValue, string a } throw new ArgumentException( - string.Format("Zero bytes ('\\0') are not allowed. A zero byte has been found at position {0}.", zeroPos), argumentName); + string.Format(CultureInfo.InvariantCulture, + "Zero bytes ('\\0') are not allowed. A zero byte has been found at position {0}.", zeroPos), argumentName); } private static readonly Dictionary> diff --git a/LibGit2Sharp/Core/EnumExtensions.cs b/LibGit2Sharp/Core/EnumExtensions.cs index 40d6d4cd4..faaf42642 100644 --- a/LibGit2Sharp/Core/EnumExtensions.cs +++ b/LibGit2Sharp/Core/EnumExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp.Core { diff --git a/LibGit2Sharp/Core/FilePathMarshaler.cs b/LibGit2Sharp/Core/FilePathMarshaler.cs index 9c5df4b2e..6b17df4cb 100644 --- a/LibGit2Sharp/Core/FilePathMarshaler.cs +++ b/LibGit2Sharp/Core/FilePathMarshaler.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.InteropServices; using System.Text; @@ -69,7 +70,7 @@ public override IntPtr MarshalManagedToNative(Object managedObj) if (null == filePath) { throw new MarshalDirectiveException( - string.Format("{0} must be used on a FilePath.", GetType().Name)); + string.Format(CultureInfo.InvariantCulture, "{0} must be used on a FilePath.", GetType().Name)); } return FromManaged(filePath); diff --git a/LibGit2Sharp/Core/GitBlame.cs b/LibGit2Sharp/Core/GitBlame.cs index 21193daa3..fd08b991c 100644 --- a/LibGit2Sharp/Core/GitBlame.cs +++ b/LibGit2Sharp/Core/GitBlame.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.InteropServices; namespace LibGit2Sharp.Core @@ -36,7 +37,7 @@ internal enum GitBlameOptionFlags /// Restrict the search of commits to those reachable /// following only the first parents. /// - GIT_BLAME_FIRST_PARENT = (1<<4), + GIT_BLAME_FIRST_PARENT = (1<<4), } [StructLayout(LayoutKind.Sequential)] @@ -78,7 +79,8 @@ public static GitBlameOptionFlags ToGitBlameOptionFlags(this BlameStrategy strat return GitBlameOptionFlags.GIT_BLAME_NORMAL; default: - throw new NotSupportedException(string.Format("{0} is not supported at this time", strategy)); + throw new NotSupportedException( + string.Format(CultureInfo.InvariantCulture, "{0} is not supported at this time", strategy)); } } } diff --git a/LibGit2Sharp/Core/GitBranchType.cs b/LibGit2Sharp/Core/GitBranchType.cs index 6304715f7..f843c11da 100644 --- a/LibGit2Sharp/Core/GitBranchType.cs +++ b/LibGit2Sharp/Core/GitBranchType.cs @@ -7,5 +7,6 @@ internal enum GitBranchType { GIT_BRANCH_LOCAL = 1, GIT_BRANCH_REMOTE = 2, + GIT_BRANCH_ALL = GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, } } diff --git a/LibGit2Sharp/Core/GitCheckoutOpts.cs b/LibGit2Sharp/Core/GitCheckoutOpts.cs index ca6943959..214251d60 100644 --- a/LibGit2Sharp/Core/GitCheckoutOpts.cs +++ b/LibGit2Sharp/Core/GitCheckoutOpts.cs @@ -120,7 +120,7 @@ internal delegate void progress_cb( IntPtr payload); [StructLayout(LayoutKind.Sequential)] - internal struct GitCheckoutOpts :IDisposable + internal struct GitCheckoutOpts { public uint version; @@ -146,15 +146,18 @@ internal struct GitCheckoutOpts :IDisposable public IntPtr ancestor_label; public IntPtr our_label; public IntPtr their_label; + } + + /// + /// An inteface for objects that specify parameters from which a + /// GitCheckoutOpts struct can be populated. + /// + internal interface IConvertableToGitCheckoutOpts + { + CheckoutCallbacks GenerateCallbacks(); - public void Dispose() - { - if (paths == null) - { - return; - } + CheckoutStrategy CheckoutStrategy { get; } - paths.Dispose(); - } + CheckoutNotifyFlags CheckoutNotifyFlags { get; } } } diff --git a/LibGit2Sharp/Core/GitCheckoutOptsWrapper.cs b/LibGit2Sharp/Core/GitCheckoutOptsWrapper.cs new file mode 100644 index 000000000..b98a5cd96 --- /dev/null +++ b/LibGit2Sharp/Core/GitCheckoutOptsWrapper.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LibGit2Sharp.Core +{ + /// + /// A wrapper around the native GitCheckoutOpts structure. This class is responsible + /// for the managed objects that the native code points to. + /// + internal class GitCheckoutOptsWrapper : IDisposable + { + /// + /// Create wrapper around from . + /// + /// Options to create native GitCheckoutOpts structure from. + /// Paths to checkout. + public GitCheckoutOptsWrapper(IConvertableToGitCheckoutOpts options, FilePath[] paths = null) + { + Callbacks = options.GenerateCallbacks(); + + if (paths != null) + { + PathArray = GitStrArrayIn.BuildFrom(paths); + } + + Options = new GitCheckoutOpts + { + version = 1, + checkout_strategy = options.CheckoutStrategy, + progress_cb = Callbacks.CheckoutProgressCallback, + notify_cb = Callbacks.CheckoutNotifyCallback, + notify_flags = options.CheckoutNotifyFlags, + paths = PathArray, + }; + } + + /// + /// Native struct to pass to libgit. + /// + public GitCheckoutOpts Options { get; set; } + + /// + /// The managed class mapping native callbacks into the + /// corresponding managed delegate. + /// + public CheckoutCallbacks Callbacks { get; private set; } + + /// + /// Keep the paths around so we can dispose them. + /// + private GitStrArrayIn PathArray; + + public void Dispose() + { + Dispose(true); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + if (PathArray != null) + { + PathArray.Dispose(); + PathArray = null; + } + } + } + + /// + /// Method to translate from to flags. + /// + internal static CheckoutStrategy CheckoutStrategyFromFileConflictStrategy(CheckoutFileConflictStrategy fileConflictStrategy) + { + CheckoutStrategy flags = default(CheckoutStrategy); + + switch (fileConflictStrategy) + { + case CheckoutFileConflictStrategy.Ours: + flags = CheckoutStrategy.GIT_CHECKOUT_USE_OURS; + break; + case CheckoutFileConflictStrategy.Theirs: + flags = CheckoutStrategy.GIT_CHECKOUT_USE_THEIRS; + break; + case CheckoutFileConflictStrategy.Merge: + flags = CheckoutStrategy.GIT_CHECKOUT_CONFLICT_STYLE_MERGE; + break; + case CheckoutFileConflictStrategy.Diff3: + flags = CheckoutStrategy.GIT_CHECKOUT_CONFLICT_STYLE_DIFF3; + break; + } + + return flags; + } + } +} diff --git a/LibGit2Sharp/Core/GitCloneOptions.cs b/LibGit2Sharp/Core/GitCloneOptions.cs index f3d87cb91..915c56b12 100644 --- a/LibGit2Sharp/Core/GitCloneOptions.cs +++ b/LibGit2Sharp/Core/GitCloneOptions.cs @@ -3,6 +3,14 @@ namespace LibGit2Sharp.Core { + internal enum GitCloneLocal + { + CloneLocalAuto, + CloneLocal, + CloneNoLocal, + CloneLocalNoLinks + } + [StructLayout(LayoutKind.Sequential)] internal struct GitCloneOptions { @@ -13,6 +21,7 @@ internal struct GitCloneOptions public int Bare; public int IgnoreCertErrors; + public GitCloneLocal Local; public IntPtr RemoteName; public IntPtr CheckoutBranch; diff --git a/LibGit2Sharp/Core/GitCredentialType.cs b/LibGit2Sharp/Core/GitCredentialType.cs index 51a8d49ae..6ae636588 100644 --- a/LibGit2Sharp/Core/GitCredentialType.cs +++ b/LibGit2Sharp/Core/GitCredentialType.cs @@ -27,6 +27,10 @@ public enum GitCredentialType /// A key for NTLM/Kerberos "default" credentials. /// Default = (1 << 3), + + /// + /// TODO + /// + SshInteractive = (1 << 4), } } - diff --git a/LibGit2Sharp/Core/GitDiff.cs b/LibGit2Sharp/Core/GitDiff.cs index c126598e4..4ef6a251f 100644 --- a/LibGit2Sharp/Core/GitDiff.cs +++ b/LibGit2Sharp/Core/GitDiff.cs @@ -104,6 +104,14 @@ internal enum GitDiffOptionFlags /// GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = (1 << 14), + /// + /// When diff finds a file in the working directory with stat + /// information different from the index, but the OID ends up being the + /// same, write the correct stat information into the index. Note: + /// without this flag, diff will always leave the index untouched. + /// + GIT_DIFF_UPDATE_INDEX = (1 << 15), + /* * Options controlling how output will be generated */ @@ -158,6 +166,12 @@ internal enum GitDiffOptionFlags /// Take extra time to find minimal diff /// GIT_DIFF_MINIMAL = (1 << 29), + + /// + /// Include the necessary deflate / delta information so that `git-apply` + /// can apply given diff information to binary files. + /// + GIT_DIFF_SHOW_BINARY = (1 << 30), } internal delegate int diff_notify_cb( @@ -282,7 +296,7 @@ enum GitDiffFindFlags // Obey `diff.renames`. Overridden by any other GIT_DIFF_FIND_... flag. GIT_DIFF_FIND_BY_CONFIG = 0, - // Look for renames? (`--find-renames`) + // Look for renames? (`--find-renames`) GIT_DIFF_FIND_RENAMES = (1 << 0), // consider old side of modified for renames? (`--break-rewrites=N`) GIT_DIFF_FIND_RENAMES_FROM_REWRITES = (1 << 1), diff --git a/LibGit2Sharp/Core/GitDiffExtensions.cs b/LibGit2Sharp/Core/GitDiffExtensions.cs index a885901a5..a131d2091 100644 --- a/LibGit2Sharp/Core/GitDiffExtensions.cs +++ b/LibGit2Sharp/Core/GitDiffExtensions.cs @@ -1,5 +1,3 @@ -using LibGit2Sharp.Core.Compat; - namespace LibGit2Sharp.Core { internal static class GitDiffExtensions diff --git a/LibGit2Sharp/Core/GitMergeOpts.cs b/LibGit2Sharp/Core/GitMergeOpts.cs index 0f5cf445b..a2ebe979d 100644 --- a/LibGit2Sharp/Core/GitMergeOpts.cs +++ b/LibGit2Sharp/Core/GitMergeOpts.cs @@ -30,12 +30,13 @@ internal struct GitMergeOpts /// /// Flags for automerging content. /// - public GitMergeFileFavorFlags MergeFileFavorFlags; + public MergeFileFavor MergeFileFavorFlags; } - /// - /// The results of `git_merge_analysis` indicate the merge opportunities. - /// + /// + /// The results of `git_merge_analysis` indicate the merge opportunities. + /// + [Flags] internal enum GitMergeAnalysis { /// @@ -44,8 +45,8 @@ internal enum GitMergeAnalysis GIT_MERGE_ANALYSIS_NONE = 0, /// - /// A "normal" merge; both HEAD and the given merge input have diverged - /// from their common ancestor. The divergent commits must be merged. + /// A "normal" merge; both HEAD and the given merge input have diverged + /// from their common ancestor. The divergent commits must be merged. /// GIT_MERGE_ANALYSIS_NORMAL = (1 << 0), @@ -70,6 +71,27 @@ internal enum GitMergeAnalysis GIT_MERGE_ANALYSIS_UNBORN = (1 << 3), } + internal enum GitMergePreference + { + /// + /// No configuration was found that suggests a preferred behavior for + /// merge. + /// + GIT_MERGE_PREFERENCE_NONE = 0, + + /// + /// There is a `merge.ff=false` configuration setting, suggesting that + /// the user does not want to allow a fast-forward merge. + /// + GIT_MERGE_PREFERENCE_NO_FASTFORWARD = (1 << 0), + + /// + /// There is a `merge.ff=only` configuration setting, suggesting that + /// the user only wants fast-forward merges. + /// + GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = (1 << 1), + } + [Flags] internal enum GitMergeTreeFlags { @@ -83,12 +105,4 @@ internal enum GitMergeTreeFlags /// GIT_MERGE_TREE_FIND_RENAMES = (1 << 0), } - - internal enum GitMergeFileFavorFlags - { - GIT_MERGE_FILE_FAVOR_NORMAL = 0, - GIT_MERGE_FILE_FAVOR_OURS = 1, - GIT_MERGE_FILE_FAVOR_THEIRS = 2, - GIT_MERGE_FILE_FAVOR_UNION = 3, - } } diff --git a/LibGit2Sharp/Core/GitObjectType.cs b/LibGit2Sharp/Core/GitObjectType.cs index a099c4806..a38523f2c 100644 --- a/LibGit2Sharp/Core/GitObjectType.cs +++ b/LibGit2Sharp/Core/GitObjectType.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; namespace LibGit2Sharp.Core { @@ -74,7 +75,8 @@ public static TreeEntryTargetType ToTreeEntryTargetType(this GitObjectType type) return TreeEntryTargetType.Blob; default: - throw new InvalidOperationException(string.Format("Cannot map {0} to a TreeEntryTargetType.", type)); + throw new InvalidOperationException( + string.Format(CultureInfo.InvariantCulture, "Cannot map {0} to a TreeEntryTargetType.", type)); } } @@ -95,7 +97,8 @@ public static ObjectType ToObjectType(this GitObjectType type) return ObjectType.Tag; default: - throw new InvalidOperationException(string.Format("Cannot map {0} to a ObjectType.", type)); + throw new InvalidOperationException( + string.Format(CultureInfo.InvariantCulture, "Cannot map {0} to a ObjectType.", type)); } } } diff --git a/LibGit2Sharp/Core/GitOid.cs b/LibGit2Sharp/Core/GitOid.cs index 8b6947a8d..9c5930908 100644 --- a/LibGit2Sharp/Core/GitOid.cs +++ b/LibGit2Sharp/Core/GitOid.cs @@ -7,10 +7,15 @@ namespace LibGit2Sharp.Core /// internal struct GitOid { + /// + /// Number of bytes in the Id. + /// + public const int Size = 20; + /// /// The raw binary 20 byte Id. /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Size)] public byte[] Id; public static implicit operator ObjectId(GitOid oid) diff --git a/LibGit2Sharp/Core/GitRemoteHead.cs b/LibGit2Sharp/Core/GitRemoteHead.cs index 2c6bce911..02c2def8b 100644 --- a/LibGit2Sharp/Core/GitRemoteHead.cs +++ b/LibGit2Sharp/Core/GitRemoteHead.cs @@ -10,5 +10,6 @@ internal struct GitRemoteHead public GitOid Oid; public GitOid Loid; public IntPtr NamePtr; + public IntPtr SymRefTargetPtr; } } diff --git a/LibGit2Sharp/Core/GitRevertOpts.cs b/LibGit2Sharp/Core/GitRevertOpts.cs new file mode 100644 index 000000000..7976243c2 --- /dev/null +++ b/LibGit2Sharp/Core/GitRevertOpts.cs @@ -0,0 +1,17 @@ +using System.Runtime.InteropServices; + +namespace LibGit2Sharp.Core +{ + [StructLayout(LayoutKind.Sequential)] + internal class GitRevertOpts + { + public uint Version = 1; + + // For merge commits, the "mainline" is treated as the parent + public uint Mainline = 0; + + public GitMergeOpts MergeOpts = new GitMergeOpts { Version = 1 }; + + public GitCheckoutOpts CheckoutOpts = new GitCheckoutOpts {version = 1}; + } +} diff --git a/LibGit2Sharp/Core/GitStatusOptions.cs b/LibGit2Sharp/Core/GitStatusOptions.cs index 5d02ebfe9..ce8504109 100644 --- a/LibGit2Sharp/Core/GitStatusOptions.cs +++ b/LibGit2Sharp/Core/GitStatusOptions.cs @@ -49,5 +49,7 @@ internal enum GitStatusOptionFlags SortCaseSensitively = (1 << 9), SortCaseInsensitively = (1 << 10), RenamesFromRewrites = (1 << 11), + NoRefresh = (1 << 12), + UpdateIndex = (1 << 13), } } diff --git a/LibGit2Sharp/Core/Handles/DisposableExtensions.cs b/LibGit2Sharp/Core/Handles/DisposableExtensions.cs new file mode 100644 index 000000000..0941ffcda --- /dev/null +++ b/LibGit2Sharp/Core/Handles/DisposableExtensions.cs @@ -0,0 +1,17 @@ +using System; + +namespace LibGit2Sharp.Core.Handles +{ + internal static class DisposableExtensions + { + public static void SafeDispose(this IDisposable disposable) + { + if (disposable == null) + { + return; + } + + disposable.Dispose(); + } + } +} diff --git a/LibGit2Sharp/Core/Handles/OdbStreamSafeHandle.cs b/LibGit2Sharp/Core/Handles/OdbStreamSafeHandle.cs new file mode 100644 index 000000000..10dc69db8 --- /dev/null +++ b/LibGit2Sharp/Core/Handles/OdbStreamSafeHandle.cs @@ -0,0 +1,11 @@ +namespace LibGit2Sharp.Core.Handles +{ + internal class OdbStreamSafeHandle : SafeHandleBase + { + protected override bool ReleaseHandleImpl() + { + Proxy.git_odb_stream_free(handle); + return true; + } + } +} diff --git a/LibGit2Sharp/Core/Handles/OidSafeHandle.cs b/LibGit2Sharp/Core/Handles/OidSafeHandle.cs index 9b806aab1..f6e00ec31 100644 --- a/LibGit2Sharp/Core/Handles/OidSafeHandle.cs +++ b/LibGit2Sharp/Core/Handles/OidSafeHandle.cs @@ -6,7 +6,14 @@ internal class OidSafeHandle : NotOwnedSafeHandleBase { private GitOid? MarshalAsGitOid() { - return IsInvalid ? null : (GitOid?)handle.MarshalAs(); + return IsInvalid ? null : (GitOid?)MarshalAsGitOid(handle); + } + + private static GitOid MarshalAsGitOid(System.IntPtr data) + { + var gitOid = new GitOid { Id = new byte[GitOid.Size] }; + Marshal.Copy(data, gitOid.Id, 0, GitOid.Size); + return gitOid; } public ObjectId MarshalAsObjectId() diff --git a/LibGit2Sharp/Core/Handles/SafeHandleExtensions.cs b/LibGit2Sharp/Core/Handles/SafeHandleExtensions.cs deleted file mode 100644 index 00a4b6ed7..000000000 --- a/LibGit2Sharp/Core/Handles/SafeHandleExtensions.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; - -namespace LibGit2Sharp.Core.Handles -{ - internal static class SafeHandleExtensions - { - public static void SafeDispose(this IDisposable disposable) - { - if (disposable == null) - return; - - var handle = disposable as SafeHandleBase; - if (handle != null) - { - SafeDispose(handle); - return; - } - - disposable.Dispose(); - } - - public static void SafeDispose(this SafeHandleBase handle) - { - if (handle == null || handle.IsClosed || handle.IsInvalid) - { - return; - } - - handle.Dispose(); - } - } -} diff --git a/LibGit2Sharp/Core/Handles/StatusEntrySafeHandle.cs b/LibGit2Sharp/Core/Handles/StatusEntrySafeHandle.cs index 0a85125f3..45b6eacd4 100644 --- a/LibGit2Sharp/Core/Handles/StatusEntrySafeHandle.cs +++ b/LibGit2Sharp/Core/Handles/StatusEntrySafeHandle.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; namespace LibGit2Sharp.Core.Handles { diff --git a/LibGit2Sharp/Core/HistoryRewriter.cs b/LibGit2Sharp/Core/HistoryRewriter.cs index 1e61fc1f4..3931f9cba 100644 --- a/LibGit2Sharp/Core/HistoryRewriter.cs +++ b/LibGit2Sharp/Core/HistoryRewriter.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; namespace LibGit2Sharp.Core @@ -157,7 +158,9 @@ private Reference RewriteReference( if (repo.Refs.Resolve(backupName) != null) { throw new InvalidOperationException( - String.Format("Can't back up reference '{0}' - '{1}' already exists", oldRef.CanonicalName, backupName)); + String.Format( + CultureInfo.InvariantCulture, "Can't back up reference '{0}' - '{1}' already exists", + oldRef.CanonicalName, backupName)); } repo.Refs.Add(backupName, oldRef.TargetIdentifier, signature, "filter-branch: backup"); @@ -230,7 +233,7 @@ private void RewriteCommit(Commit commit) var newCommit = repo.ObjectDatabase.CreateCommit(newHeader.Author, newHeader.Committer, - newHeader.Message, + newHeader.Message, true, newTree, mappedNewParents); diff --git a/LibGit2Sharp/Core/LazyGroup.cs b/LibGit2Sharp/Core/LazyGroup.cs index ec341dda8..3c82fa3ad 100644 --- a/LibGit2Sharp/Core/LazyGroup.cs +++ b/LibGit2Sharp/Core/LazyGroup.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp.Core { diff --git a/LibGit2Sharp/Core/NativeDllName.cs b/LibGit2Sharp/Core/NativeDllName.cs index 76e361687..ec9cc1fcc 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-06d772d"; + public const string Name = "git2-2f6f6eb"; } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 84dbee9be..faf1e02b5 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -79,7 +79,7 @@ public static string ProcessorArchitecture { get { - if (Compat.Environment.Is64BitProcess) + if (Environment.Is64BitProcess) { return "amd64"; } @@ -122,7 +122,7 @@ internal static extern int git_blame_file( GitBlameOptions options); [DllImport(libgit2)] - internal static extern int git_blame_free(IntPtr blame); + internal static extern void git_blame_free(IntPtr blame); [DllImport(libgit2)] internal static extern int git_blob_create_fromdisk( @@ -306,7 +306,7 @@ internal static extern int git_config_add_file_ondisk( ConfigurationSafeHandle cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, uint level, - bool force); + [MarshalAs(UnmanagedType.Bool)] bool force); [DllImport(libgit2)] internal static extern int git_config_new(out ConfigurationSafeHandle cfg); @@ -380,6 +380,9 @@ internal static extern int git_config_next( [DllImport(libgit2)] internal static extern void git_config_iterator_free(IntPtr iter); + [DllImport(libgit2)] + internal static extern int git_config_snapshot(out ConfigurationSafeHandle @out, ConfigurationSafeHandle config); + // Ordinarily we would decorate the `url` parameter with the StrictUtf8Marshaler like we do everywhere // else, but apparently doing a native->managed callback with the 64-bit version of CLR 2.0 can // sometimes vomit when using a custom IMarshaler. So yeah, don't do that. If you need the url, @@ -455,13 +458,6 @@ internal delegate int git_diff_line_cb( [In] GitDiffLine line, IntPtr payload); - [DllImport(libgit2)] - internal static extern int git_diff_print( - DiffSafeHandle diff, - GitDiffFormat format, - git_diff_line_cb printCallback, - IntPtr payload); - [DllImport(libgit2)] internal static extern int git_diff_blobs( GitObjectSafeHandle oldBlob, @@ -493,6 +489,9 @@ internal static extern int git_diff_find_similar( [DllImport(libgit2)] internal static extern IntPtr git_diff_get_delta(DiffSafeHandle diff, UIntPtr idx); + [DllImport(libgit2)] + internal static extern int git_libgit2_features(); + [DllImport(libgit2)] internal static extern int git_graph_ahead_behind(out UIntPtr ahead, out UIntPtr behind, RepositorySafeHandle repo, ref GitOid one, ref GitOid two); @@ -540,12 +539,6 @@ internal static extern int git_index_conflict_get( [DllImport(libgit2)] internal static extern int git_index_entry_stage(IndexEntrySafeHandle indexentry); - [DllImport(libgit2)] - internal static extern int git_index_find( - out UIntPtr pos, - IndexSafeHandle index, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path); - [DllImport(libgit2)] internal static extern void git_index_free(IntPtr index); @@ -567,7 +560,9 @@ 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, bool force); + internal static extern int git_index_read( + IndexSafeHandle index, + [MarshalAs(UnmanagedType.Bool)] bool force); [DllImport(libgit2)] internal static extern int git_index_remove_bypath( @@ -629,6 +624,7 @@ internal static extern int git_merge( [DllImport(libgit2)] internal static extern int git_merge_analysis( out GitMergeAnalysis status_out, + out GitMergePreference preference_out, RepositorySafeHandle repo, [In] IntPtr[] their_heads, int their_heads_len); @@ -641,7 +637,8 @@ internal static extern void git_merge_head_free( internal static extern int git_message_prettify( GitBuf buf, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, - bool strip_comments); + [MarshalAs(UnmanagedType.Bool)] bool strip_comments, + sbyte comment_char); [DllImport(libgit2)] internal static extern int git_note_create( @@ -715,12 +712,24 @@ internal static extern int git_odb_foreach( git_odb_foreach_cb cb, IntPtr payload); + [DllImport(libgit2)] + internal static extern int git_odb_open_wstream(out OdbStreamSafeHandle stream, ObjectDatabaseSafeHandle odb, UIntPtr size, GitObjectType type); + [DllImport(libgit2)] internal static extern void git_odb_free(IntPtr odb); [DllImport(libgit2)] internal static extern void git_object_free(IntPtr obj); + [DllImport(libgit2)] + internal static extern int git_odb_stream_write(OdbStreamSafeHandle Stream, IntPtr Buffer, UIntPtr len); + + [DllImport(libgit2)] + internal static extern int git_odb_stream_finalize_write(out GitOid id, OdbStreamSafeHandle stream); + + [DllImport(libgit2)] + internal static extern void git_odb_stream_free(IntPtr stream); + [DllImport(libgit2)] internal static extern OidSafeHandle git_object_id(GitObjectSafeHandle obj); @@ -925,16 +934,6 @@ internal static extern OidSafeHandle git_reflog_entry_id_new( internal static extern IntPtr git_reflog_entry_committer( SafeHandle entry); - [DllImport(libgit2)] - internal static extern int git_reflog_append( - ReflogSafeHandle reflog, - ref GitOid id, - SignatureSafeHandle committer, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string msg); - - [DllImport(libgit2)] - internal static extern int git_reflog_write(ReflogSafeHandle reflog); - [DllImport(libgit2)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern string git_reflog_entry_message(SafeHandle entry); @@ -995,6 +994,9 @@ internal static extern int git_remote_create_with_fetchspec( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refspec); + [DllImport(libgit2)] + internal static extern int git_remote_delete(RemoteSafeHandle remote); + [DllImport(libgit2)] internal static extern void git_remote_disconnect(RemoteSafeHandle remote); @@ -1104,9 +1106,6 @@ internal static extern int git_repository_init_ext( [DllImport(libgit2)] internal static extern int git_repository_is_bare(RepositorySafeHandle handle); - [DllImport(libgit2)] - internal static extern int git_repository_is_empty(RepositorySafeHandle repo); - [DllImport(libgit2)] internal static extern int git_repository_is_shallow(RepositorySafeHandle repo); @@ -1161,7 +1160,7 @@ internal static extern void git_repository_set_index( internal static extern int git_repository_set_workdir( RepositorySafeHandle repository, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath workdir, - bool update_gitlink); + [MarshalAs(UnmanagedType.Bool)] bool update_gitlink); [DllImport(libgit2)] internal static extern int git_repository_set_head_detached( @@ -1193,6 +1192,12 @@ internal static extern int git_reset( SignatureSafeHandle signature, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); + [DllImport(libgit2)] + internal static extern int git_revert( + RepositorySafeHandle repo, + GitObjectSafeHandle commit, + GitRevertOpts opts); + [DllImport(libgit2)] internal static extern int git_revparse_ext( out GitObjectSafeHandle obj, @@ -1307,7 +1312,7 @@ internal static extern int git_submodule_foreach( [DllImport(libgit2)] internal static extern int git_submodule_add_to_index( SubmoduleSafeHandle submodule, - bool write_index); + [MarshalAs(UnmanagedType.Bool)] bool write_index); [DllImport(libgit2)] internal static extern int git_submodule_save( diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index e8a682455..ed6a39b24 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Runtime.InteropServices; using System.Threading; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; // ReSharper disable InconsistentNaming @@ -70,6 +69,12 @@ public static ObjectId git_blob_create_fromchunks(RepositorySafeHandle repo, Fil { var oid = new GitOid(); int res = NativeMethods.git_blob_create_fromchunks(ref oid, repo, hintpath, fileCallback, IntPtr.Zero); + + if (res == (int)GitErrorCode.User) + { + throw new EndOfStreamException("The stream ended unexpectedly"); + } + Ensure.ZeroResult(res); return oid; @@ -114,16 +119,6 @@ public static UnmanagedMemoryStream git_blob_filtered_content_stream(RepositoryS new[] { buf }); } - public static byte[] git_blob_rawcontent(RepositorySafeHandle repo, ObjectId id, int size) - { - using (var obj = new ObjectSafeWrapper(id, repo)) - { - var arr = new byte[size]; - Marshal.Copy(NativeMethods.git_blob_rawcontent(obj.ObjectPtr), arr, 0, size); - return arr; - } - } - public static UnmanagedMemoryStream git_blob_rawcontent_stream(RepositorySafeHandle repo, ObjectId id, Int64 size) { var handle = new ObjectSafeWrapper(id, repo).ObjectPtr; @@ -147,7 +142,7 @@ public static bool git_blob_is_binary(GitObjectSafeHandle obj) #region git_branch_ - public static ReferenceSafeHandle git_branch_create(RepositorySafeHandle repo, string branch_name, ObjectId targetId, bool force, + public static ReferenceSafeHandle git_branch_create(RepositorySafeHandle repo, string branch_name, ObjectId targetId, bool force, Signature signature, string logMessage) { using (ThreadAffinity()) @@ -166,8 +161,8 @@ public static void git_branch_delete(ReferenceSafeHandle reference) using (ThreadAffinity()) { int res = NativeMethods.git_branch_delete(reference); - reference.SetHandleAsInvalid(); Ensure.ZeroResult(res); + reference.SetHandleAsInvalid(); } } @@ -580,6 +575,18 @@ public static void git_config_iterator_free(IntPtr iter) NativeMethods.git_config_iterator_free(iter); } + public static ConfigurationSafeHandle git_config_snapshot(ConfigurationSafeHandle config) + { + using (ThreadAffinity()) + { + ConfigurationSafeHandle handle; + int res = NativeMethods.git_config_snapshot(out handle, config); + Ensure.ZeroResult(res); + + return handle; + } + } + #endregion #region git_diff_ @@ -649,16 +656,6 @@ public static void git_diff_merge(DiffSafeHandle onto, DiffSafeHandle from) } } - public static void git_diff_print(DiffSafeHandle diff, NativeMethods.git_diff_line_cb printCallback) - { - using (ThreadAffinity()) - { - int res = NativeMethods.git_diff_print(diff, GitDiffFormat.GIT_DIFF_FORMAT_PATCH, - printCallback, IntPtr.Zero); - Ensure.ZeroResult(res); - } - } - public static DiffSafeHandle git_diff_tree_to_tree( RepositorySafeHandle repo, ObjectId oldTree, @@ -1043,25 +1040,24 @@ public static void git_merge(RepositorySafeHandle repo, GitMergeHeadHandle[] hea } } - public static GitMergeAnalysis git_merge_analysis( + public static void git_merge_analysis( RepositorySafeHandle repo, - GitMergeHeadHandle[] heads) + GitMergeHeadHandle[] heads, + out GitMergeAnalysis analysis_out, + out GitMergePreference preference_out) { using (ThreadAffinity()) { - GitMergeAnalysis ret; - IntPtr[] their_heads = heads.Select(head => head.DangerousGetHandle()).ToArray(); int res = NativeMethods.git_merge_analysis( - out ret, + out analysis_out, + out preference_out, repo, their_heads, their_heads.Length); Ensure.ZeroResult(res); - - return ret; } } @@ -1084,7 +1080,7 @@ public static string git_message_prettify(string message) using (ThreadAffinity()) using (var buf = new GitBuf()) { - int res= NativeMethods.git_message_prettify(buf, message, false); + int res= NativeMethods.git_message_prettify(buf, message, false, (sbyte)'#'); Ensure.Int32Result(res); return LaxUtf8Marshaler.FromNative(buf.ptr) ?? string.Empty; @@ -1300,11 +1296,57 @@ public static ICollection git_odb_foreach( IntPtr.Zero)); } + public static OdbStreamSafeHandle git_odb_open_wstream(ObjectDatabaseSafeHandle odb, UIntPtr size, GitObjectType type) + { + using (ThreadAffinity()) + { + OdbStreamSafeHandle stream; + int res = NativeMethods.git_odb_open_wstream(out stream, odb, size, type); + Ensure.ZeroResult(res); + + return stream; + } + } + public static void git_odb_free(IntPtr odb) { NativeMethods.git_odb_free(odb); } + public static void git_odb_stream_write(OdbStreamSafeHandle stream, byte[] data, int len) + { + using (ThreadAffinity()) + { + int res; + unsafe + { + fixed (byte *p = data) + { + res = NativeMethods.git_odb_stream_write(stream, (IntPtr) p, (UIntPtr) len); + } + } + + Ensure.ZeroResult(res); + } + } + + public static ObjectId git_odb_stream_finalize_write(OdbStreamSafeHandle stream) + { + using (ThreadAffinity()) + { + GitOid id; + int res = NativeMethods.git_odb_stream_finalize_write(out id, stream); + Ensure.ZeroResult(res); + + return id; + } + } + + public static void git_odb_stream_free(IntPtr stream) + { + NativeMethods.git_odb_stream_free(stream); + } + #endregion #region git_patch_ @@ -1343,7 +1385,7 @@ public static Tuple git_patch_line_stats(PatchSafeHandle patch) Ensure.ZeroResult(res); return new Tuple((int)add, (int)del); } - } + } #endregion @@ -1648,21 +1690,6 @@ public static string git_reflog_entry_message(SafeHandle entry) return NativeMethods.git_reflog_entry_message(entry); } - public static void git_reflog_append(ReflogSafeHandle reflog, ObjectId commit_id, Signature committer, string message) - { - using (ThreadAffinity()) - using (SignatureSafeHandle sigHandle = committer.BuildHandle()) - { - var oid = commit_id.Oid; - - int res = NativeMethods.git_reflog_append(reflog, ref oid, sigHandle, message); - Ensure.ZeroResult(res); - - res = NativeMethods.git_reflog_write(reflog); - Ensure.ZeroResult(res); - } - } - #endregion #region git_refspec @@ -1758,6 +1785,24 @@ public static void git_remote_connect(RemoteSafeHandle remote, GitDirection dire } } + public static void git_remote_delete(RepositorySafeHandle repo, string name) + { + using (ThreadAffinity()) + { + using (RemoteSafeHandle remote = git_remote_load(repo, name, false)) + { + if (remote == null) + { + return; + } + + int res = NativeMethods.git_remote_delete(remote); + Ensure.ZeroResult(res); + remote.SetHandleAsInvalid(); + } + } + } + public static void git_remote_disconnect(RemoteSafeHandle remote) { using (ThreadAffinity()) @@ -2005,11 +2050,6 @@ public static bool git_repository_is_bare(RepositorySafeHandle repo) return RepositoryStateChecker(repo, NativeMethods.git_repository_is_bare); } - public static bool git_repository_is_empty(RepositorySafeHandle repo) - { - return RepositoryStateChecker(repo, NativeMethods.git_repository_is_empty); - } - public static bool git_repository_is_shallow(RepositorySafeHandle repo) { return RepositoryStateChecker(repo, NativeMethods.git_repository_is_shallow); @@ -2185,6 +2225,23 @@ public static void git_reset( #endregion + #region git_revert_ + + public static void git_revert( + RepositorySafeHandle repo, + ObjectId commit, + GitRevertOpts opts) + { + using (ThreadAffinity()) + using (var nativeCommit = git_object_lookup(repo, commit, GitObjectType.Commit)) + { + int res = NativeMethods.git_revert(repo, nativeCommit, opts); + Ensure.ZeroResult(res); + } + } + + #endregion + #region git_revparse_ public static Tuple git_revparse_ext(RepositorySafeHandle repo, string objectish) @@ -2762,6 +2819,18 @@ public static ObjectId git_treebuilder_write(RepositorySafeHandle repo, TreeBuil #endregion + #region git_libgit2_ + + /// + /// Returns the features with which libgit2 was compiled. + /// + public static BuiltInFeatures git_libgit2_features() + { + return (BuiltInFeatures)NativeMethods.git_libgit2_features(); + } + + #endregion + private static ICollection git_foreach( Func resultSelector, Func, int> iterator, @@ -2896,8 +2965,7 @@ private static IEnumerable git_iterator_next 100) { - return new LinkExtendedHeader(link, string.Format("see %s.paxheader{0}", entrySha), true); + return new LinkExtendedHeader(link, + string.Format(CultureInfo.InvariantCulture, "see %s.paxheader{0}", entrySha), true); } return new LinkExtendedHeader(link, link, false); @@ -196,19 +198,19 @@ private void WriteExtendedHeader(FileNameExtendedHeader fileNameExtendedHeader, using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(extHeader))) { - Write(string.Format("{0}.paxheader", entrySha), stream, modificationTime, "666".OctalToInt32(), + Write(string.Format(CultureInfo.InvariantCulture, "{0}.paxheader", entrySha), stream, modificationTime, "666".OctalToInt32(), "0", "0", 'x', "root", "root", "0", "0", entrySha, false); } } - private string BuildKeyValueExtHeader(string key, string value) + private static string BuildKeyValueExtHeader(string key, string value) { // "%u %s=%s\n" int len = key.Length + value.Length + 3; for (int i = len; i > 9; i /= 10) len++; - return string.Format("{0} {1}={2}\n", len, key, value); + return string.Format(CultureInfo.InvariantCulture, "{0} {1}={2}\n", len, key, value); } /// @@ -331,7 +333,7 @@ public byte[] GetHeaderValue() return buffer; } - private string CalculateChecksum(byte[] buf) + private static string CalculateChecksum(byte[] buf) { Encoding.ASCII.GetBytes(new string(' ', 8)).CopyTo(buf, 148); @@ -408,7 +410,8 @@ public static FileNameExtendedHeader Parse(string posixPath, string entrySha) return new FileNameExtendedHeader(posixPath, posixPath.Substring(0, position), posixPath.Substring(position, posixPath.Length - position), false); } - return new FileNameExtendedHeader(posixPath, string.Empty, string.Format("{0}.data", entrySha), true); + return new FileNameExtendedHeader(posixPath, string.Empty, + string.Format(CultureInfo.InvariantCulture, "{0}.data", entrySha), true); } return new FileNameExtendedHeader(posixPath, string.Empty, posixPath, false); diff --git a/LibGit2Sharp/Core/Utf8Marshaler.cs b/LibGit2Sharp/Core/Utf8Marshaler.cs index 8a480816f..c623fe99f 100644 --- a/LibGit2Sharp/Core/Utf8Marshaler.cs +++ b/LibGit2Sharp/Core/Utf8Marshaler.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.InteropServices; using System.Text; @@ -70,7 +71,7 @@ public static ICustomMarshaler GetInstance(String cookie) public override Object MarshalNativeToManaged(IntPtr pNativeData) { throw new InvalidOperationException( - string.Format("{0} cannot be used to retrieve data from libgit2.", GetType().Name)); + string.Format(CultureInfo.InvariantCulture, "{0} cannot be used to retrieve data from libgit2.", GetType().Name)); } #endregion @@ -105,7 +106,7 @@ public static ICustomMarshaler GetInstance(String cookie) public override IntPtr MarshalManagedToNative(object managedObj) { throw new InvalidOperationException( - string.Format("{0} cannot be used to pass data to libgit2.", GetType().Name)); + string.Format(CultureInfo.InvariantCulture, "{0} cannot be used to pass data to libgit2.", GetType().Name)); } #endregion diff --git a/LibGit2Sharp/Diff.cs b/LibGit2Sharp/Diff.cs index bde61d7ef..6f0191e78 100644 --- a/LibGit2Sharp/Diff.cs +++ b/LibGit2Sharp/Diff.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Text; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; using Environment = System.Environment; @@ -293,23 +292,12 @@ private static TreeComparisonHandleRetriever WorkdirAndIndexToTree(Repository re { TreeComparisonHandleRetriever comparisonHandleRetriever = (oh, nh, o) => { - DiffSafeHandle diff = null, diff2 = null; + DiffSafeHandle diff = Proxy.git_diff_tree_to_index(repo.Handle, repo.Index.Handle, oh, o); - try + using (DiffSafeHandle diff2 = Proxy.git_diff_index_to_workdir(repo.Handle, repo.Index.Handle, o)) { - diff = Proxy.git_diff_tree_to_index(repo.Handle, repo.Index.Handle, oh, o); - diff2 = Proxy.git_diff_index_to_workdir(repo.Handle, repo.Index.Handle, o); Proxy.git_diff_merge(diff, diff2); } - catch - { - diff.SafeDispose(); - throw; - } - finally - { - diff2.SafeDispose(); - } return diff; }; @@ -333,17 +321,9 @@ private DiffSafeHandle BuildDiffList(ObjectId oldTreeId, ObjectId newTreeId, Tre { var diffList = comparisonHandleRetriever(oldTreeId, newTreeId, options); - try - { - if (explicitPathsOptions != null) - { - DispatchUnmatchedPaths(explicitPathsOptions, filePaths, matchedPaths); - } - } - catch + if (explicitPathsOptions != null) { - diffList.Dispose(); - throw; + DispatchUnmatchedPaths(explicitPathsOptions, filePaths, matchedPaths); } DetectRenames(diffList, compareOptions); @@ -352,7 +332,7 @@ private DiffSafeHandle BuildDiffList(ObjectId oldTreeId, ObjectId newTreeId, Tre } } - private void DetectRenames(DiffSafeHandle diffList, CompareOptions compareOptions) + private static void DetectRenames(DiffSafeHandle diffList, CompareOptions compareOptions) { var similarityOptions = (compareOptions == null) ? null : compareOptions.Similarity; if (similarityOptions == null || diff --git a/LibGit2Sharp/DirectReference.cs b/LibGit2Sharp/DirectReference.cs index 1111a2919..d5de46621 100644 --- a/LibGit2Sharp/DirectReference.cs +++ b/LibGit2Sharp/DirectReference.cs @@ -1,4 +1,4 @@ -using LibGit2Sharp.Core.Compat; +using System; namespace LibGit2Sharp { diff --git a/LibGit2Sharp/FetchHead.cs b/LibGit2Sharp/FetchHead.cs index 7d5e6dfda..75f12ae01 100644 --- a/LibGit2Sharp/FetchHead.cs +++ b/LibGit2Sharp/FetchHead.cs @@ -7,8 +7,7 @@ namespace LibGit2Sharp /// Represents a local reference data from a remote repository which /// has been retreived through a Fetch process. /// - [Obsolete("This class is meant for internal use only and will not be public in the next release.")] - public class FetchHead : ReferenceWrapper + internal class FetchHead : ReferenceWrapper { /// /// Needed for mocking purposes. diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs new file mode 100644 index 000000000..0e01ef570 --- /dev/null +++ b/LibGit2Sharp/GlobalSettings.cs @@ -0,0 +1,20 @@ +using LibGit2Sharp.Core; + +namespace LibGit2Sharp +{ + /// + /// Global settings for libgit2 and LibGit2Sharp. + /// + public static class GlobalSettings + { + /// + /// Returns all the optional features that were compiled into + /// libgit2. + /// + /// A enumeration. + public static BuiltInFeatures Features() + { + return Proxy.git_libgit2_features(); + } + } +} diff --git a/LibGit2Sharp/HistoryDivergence.cs b/LibGit2Sharp/HistoryDivergence.cs index 51044bd7b..c5dab176b 100644 --- a/LibGit2Sharp/HistoryDivergence.cs +++ b/LibGit2Sharp/HistoryDivergence.cs @@ -1,5 +1,5 @@ +using System; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp { diff --git a/LibGit2Sharp/IQueryableCommitLog.cs b/LibGit2Sharp/IQueryableCommitLog.cs index d73a43072..7642d4122 100644 --- a/LibGit2Sharp/IQueryableCommitLog.cs +++ b/LibGit2Sharp/IQueryableCommitLog.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; namespace LibGit2Sharp { @@ -15,23 +14,6 @@ public interface IQueryableCommitLog : ICommitLog /// A list of commits, ready to be enumerated. ICommitLog QueryBy(CommitFilter filter); - /// - /// Find the best possible common ancestor given two s. - /// - /// The first . - /// The second . - /// The common ancestor or null if none found. - [Obsolete("This method will be removed in the next release. Please use FindMergeBase(Commit, Commit).")] - Commit FindCommonAncestor(Commit first, Commit second); - - /// - /// Find the best possible common ancestor given two or more s. - /// - /// The for which to find the common ancestor. - /// The common ancestor or null if none found. - [Obsolete("This method will be removed in the next release. Please use FindMergeBase(IEnumerable, MergeBaseFindingStrategy).")] - Commit FindCommonAncestor(IEnumerable commits); - /// /// Find the best possible merge base given two s. /// diff --git a/LibGit2Sharp/IRepository.cs b/LibGit2Sharp/IRepository.cs index 78f1a1563..3dbb6247b 100644 --- a/LibGit2Sharp/IRepository.cs +++ b/LibGit2Sharp/IRepository.cs @@ -83,6 +83,7 @@ public interface IRepository : IDisposable /// to manage checkout notifications. /// Identity for use when updating the reflog. /// The that was checked out. + [Obsolete("This overload will be removed in the next release. Please use Repository.Checkout(Branch, CheckoutOptions, Signature) instead.")] Branch Checkout(Branch branch, CheckoutModifiers checkoutModifiers, CheckoutProgressHandler onCheckoutProgress, CheckoutNotificationOptions checkoutNotificationOptions, Signature signature = null); /// @@ -98,6 +99,7 @@ public interface IRepository : IDisposable /// to manage checkout notifications. /// Identity for use when updating the reflog. /// The that was checked out. + [Obsolete("This overload will be removed in the next release. Please use Repository.Checkout(string, CheckoutOptions, Signature) instead.")] Branch Checkout(string committishOrBranchSpec, CheckoutModifiers checkoutModifiers, CheckoutProgressHandler onCheckoutProgress, CheckoutNotificationOptions checkoutNotificationOptions, Signature signature = null); /// @@ -112,8 +114,47 @@ public interface IRepository : IDisposable /// to manage checkout notifications. /// Identity for use when updating the reflog. /// The that was checked out. + [Obsolete("This overload will be removed in the next release. Please use Repository.Checkout(Commit, CheckoutOptions, Signature) instead.")] Branch Checkout(Commit commit, CheckoutModifiers checkoutModifiers, CheckoutProgressHandler onCheckoutProgress, CheckoutNotificationOptions checkoutNotificationOptions, Signature signature = null); + /// + /// Checkout the commit pointed at by the tip of the specified . + /// + /// If this commit is the current tip of the branch as it exists in the repository, the HEAD + /// will point to this branch. Otherwise, the HEAD will be detached, pointing at the commit sha. + /// + /// + /// The to check out. + /// controlling checkout behavior. + /// Identity for use when updating the reflog. + /// The that was checked out. + Branch Checkout(Branch branch, CheckoutOptions options, Signature signature = null); + + /// + /// Checkout the specified branch, reference or SHA. + /// + /// If the committishOrBranchSpec parameter resolves to a branch name, then the checked out HEAD will + /// will point to the branch. Otherwise, the HEAD will be detached, pointing at the commit sha. + /// + /// + /// A revparse spec for the commit or branch to checkout. + /// controlling checkout behavior. + /// Identity for use when updating the reflog. + /// The that was checked out. + Branch Checkout(string committishOrBranchSpec, CheckoutOptions options, Signature signature = null); + + /// + /// Checkout the specified . + /// + /// Will detach the HEAD and make it point to this commit sha. + /// + /// + /// The to check out. + /// controlling checkout behavior. + /// Identity for use when updating the reflog. + /// The that was checked out. + Branch Checkout(Commit commit, CheckoutOptions options, Signature signature = null); + /// /// Updates specifed paths in the index and working directory with the versions from the specified branch, reference, or SHA. /// @@ -167,19 +208,6 @@ public interface IRepository : IDisposable /// The generated . Commit Commit(string message, Signature author, Signature committer, CommitOptions options = null); - /// - /// Stores the content of the as a new into the repository. - /// The tip of the will be used as the parent of this new Commit. - /// Once the commit is created, the will move forward to point at it. - /// - /// The description of why a change was made to the repository. - /// The of who made the change. - /// The of who added the change to the repository. - /// True to amend the current pointed at by , false otherwise. - /// The generated . - [Obsolete("This method will be removed in the next release. Please use a Commit overload that accepts a CommitOptions instead.")] - Commit Commit(string message, Signature author, Signature committer, bool amendPreviousCommit); - /// /// Sets the current to the specified commit and optionally resets the and /// the content of the working tree to match. @@ -207,10 +235,13 @@ public interface IRepository : IDisposable void RemoveUntrackedFiles(); /// - /// Gets the references to the tips that are currently being merged. + /// Revert the specified commit. /// - [Obsolete("This property is meant for internal use only and will not be public in the next release.")] - IEnumerable MergeHeads { get; } + /// The to revert. + /// The of who is performing the reverte. + /// controlling revert behavior. + /// The result of the revert. + RevertResult Revert(Commit commit, Signature reverter, RevertOptions options = null); /// /// Merge changes from commit into the branch pointed at by HEAD.. diff --git a/LibGit2Sharp/Index.cs b/LibGit2Sharp/Index.cs index d2906ad13..1f6501b4e 100644 --- a/LibGit2Sharp/Index.cs +++ b/LibGit2Sharp/Index.cs @@ -6,7 +6,6 @@ using System.IO; using System.Linq; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index bcbffa842..8d2f44ca6 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -10,7 +10,7 @@ Properties LibGit2Sharp LibGit2Sharp - v3.5 + v4.0 512 @@ -19,7 +19,7 @@ full false bin\Debug\ - TRACE;DEBUG;NET35 + TRACE;DEBUG;NET40 prompt 4 false @@ -43,7 +43,7 @@ full false bin\Leaks\ - TRACE;DEBUG;NET35;LEAKS + TRACE;DEBUG;NET40;LEAKS prompt 4 false @@ -69,6 +69,7 @@ + @@ -78,12 +79,17 @@ + + + + + @@ -111,7 +117,9 @@ + + @@ -169,7 +177,6 @@ - @@ -202,12 +209,10 @@ - - @@ -253,9 +258,7 @@ - - @@ -309,6 +312,7 @@ + diff --git a/LibGit2Sharp/MergeHead.cs b/LibGit2Sharp/MergeHead.cs index 896b34aab..2ad508179 100644 --- a/LibGit2Sharp/MergeHead.cs +++ b/LibGit2Sharp/MergeHead.cs @@ -1,13 +1,11 @@ -using System; -using System.Globalization; +using System.Globalization; namespace LibGit2Sharp { /// /// A merge head is a parent for the next commit. /// - [Obsolete("This class is meant for internal use only and will not be public in the next release.")] - public class MergeHead : ReferenceWrapper + internal class MergeHead : ReferenceWrapper { /// /// Needed for mocking purposes. diff --git a/LibGit2Sharp/MergeOptions.cs b/LibGit2Sharp/MergeOptions.cs index 49096dbd5..be25665ee 100644 --- a/LibGit2Sharp/MergeOptions.cs +++ b/LibGit2Sharp/MergeOptions.cs @@ -1,32 +1,107 @@ - +using LibGit2Sharp.Core; +using LibGit2Sharp.Handlers; + namespace LibGit2Sharp { /// /// Options controlling Merge behavior. /// - public class MergeOptions + public sealed class MergeOptions : IConvertableToGitCheckoutOpts { /// /// Initializes a new instance of the class. - /// By default, a fast-forward merge will be performed if possible, and - /// if a merge commit is created, then it will be commited. + /// + /// Default behavior: + /// A fast-forward merge will be performed if possible. + /// A merge commit will be committed, if one was created. + /// Merge will attempt to find renames. + /// /// public MergeOptions() { CommitOnSuccess = true; + + FindRenames = true; + // TODO: libgit2 should provide reasonable defaults for these + // values, but it currently does not. + RenameThreshold = 50; + TargetLimit = 200; } + /// + /// The Flags specifying what conditions are + /// reported through the OnCheckoutNotify delegate. + /// + public CheckoutNotifyFlags CheckoutNotifyFlags { get; set; } + /// /// Commit the merge if the merge is successful and this is a non-fast-forward merge. /// If this is a fast-forward merge, then there is no merge commit and this option /// will not affect the merge. /// - public virtual bool CommitOnSuccess { get; set; } + public bool CommitOnSuccess { get; set; } /// /// The type of merge to perform. /// - public virtual FastForwardStrategy FastForwardStrategy { get; set; } + public FastForwardStrategy FastForwardStrategy { get; set; } + + /// + /// How conflicting index entries should be written out during checkout. + /// + public CheckoutFileConflictStrategy FileConflictStrategy { get; set; } + + /// + /// Find renames. Default is true. + /// + public bool FindRenames { get; set; } + + /// + /// Similarity to consider a file renamed. + /// + public int RenameThreshold; + + /// + /// Maximum similarity sources to examine (overrides + /// 'merge.renameLimit' config (default 200) + /// + public int TargetLimit; + + /// + /// How to handle conflicts encountered during a merge. + /// + public MergeFileFavor MergeFileFavor { get; set; } + + /// + /// Delegate that the checkout will report progress through. + /// + public CheckoutProgressHandler OnCheckoutProgress { get; set; } + + /// + /// Delegate that checkout will notify callers of + /// certain conditions. The conditions that are reported is + /// controlled with the CheckoutNotifyFlags property. + /// + public CheckoutNotifyHandler OnCheckoutNotify { get; set; } + + #region IConvertableToGitCheckoutOpts + + CheckoutCallbacks IConvertableToGitCheckoutOpts.GenerateCallbacks() + { + return CheckoutCallbacks.From(OnCheckoutProgress, OnCheckoutNotify); + } + + CheckoutStrategy IConvertableToGitCheckoutOpts.CheckoutStrategy + { + get + { + return CheckoutStrategy.GIT_CHECKOUT_SAFE| + CheckoutStrategy.GIT_CHECKOUT_ALLOW_CONFLICTS | + GitCheckoutOptsWrapper.CheckoutStrategyFromFileConflictStrategy(FileConflictStrategy); + } + } + + #endregion } /// @@ -51,4 +126,41 @@ public enum FastForwardStrategy /// FastForwardOnly = 2, /* GIT_MERGE_FASTFORWARD_ONLY */ } + + /// + /// Enum specifying how merge should deal with conflicting regions + /// of the files. + /// + public enum MergeFileFavor + { + /// + /// When a region of a file is changed in both branches, a conflict + /// will be recorded in the index so that the checkout operation can produce + /// a merge file with conflict markers in the working directory. + /// This is the default. + /// + Normal = 0, + + /// + /// When a region of a file is changed in both branches, the file + /// created in the index will contain the "ours" side of any conflicting + /// region. The index will not record a conflict. + /// + Ours = 1, + + /// + /// When a region of a file is changed in both branches, the file + /// created in the index will contain the "theirs" side of any conflicting + /// region. The index will not record a conflict. + /// + Theirs = 2, + + /// + /// When a region of a file is changed in both branches, the file + /// created in the index will contain each unique line from each side, + /// which has the result of combining both files. The index will not + /// record a conflict. + /// + Union = 3, + } } diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs index 4f67b7187..e0621f884 100644 --- a/LibGit2Sharp/Network.cs +++ b/LibGit2Sharp/Network.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.Linq; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; using LibGit2Sharp.Handlers; @@ -47,13 +46,21 @@ public virtual RemoteCollection Remotes /// /// /// The to list from. + /// The optional used to connect to remote repository. /// The references in the repository. - public virtual IEnumerable ListReferences(Remote remote) + public virtual IEnumerable ListReferences(Remote remote, Credentials credentials = null) { Ensure.ArgumentNotNull(remote, "remote"); using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true)) { + if (credentials != null) + { + var callbacks = new RemoteCallbacks(null, null, null, credentials); + GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks(); + Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks); + } + Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch); return Proxy.git_remote_ls(repository, remoteHandle); } @@ -220,7 +227,7 @@ public virtual void Push( Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNullOrEmptyString(pushRefSpec, "pushRefSpec"); - Push(remote, new string[] { pushRefSpec }, pushOptions, signature, logMessage); + Push(remote, new[] { pushRefSpec }, pushOptions, signature, logMessage); } /// @@ -349,8 +356,7 @@ public virtual MergeResult Pull(Signature merger, PullOptions options) /// /// The heads that have been updated during the last fetch. /// - [Obsolete("This property is meant for internal use only and will not be public in the next release.")] - public virtual IEnumerable FetchHeads + internal virtual IEnumerable FetchHeads { get { diff --git a/LibGit2Sharp/NetworkExtensions.cs b/LibGit2Sharp/NetworkExtensions.cs index 6016aafa4..e9e6f75a2 100644 --- a/LibGit2Sharp/NetworkExtensions.cs +++ b/LibGit2Sharp/NetworkExtensions.cs @@ -44,14 +44,19 @@ public static void Push( { if (string.IsNullOrEmpty(branch.UpstreamBranchCanonicalName)) { - throw new LibGit2SharpException(string.Format("The branch '{0}' (\"{1}\") that you are trying to push does not track an upstream branch.", - branch.Name, branch.CanonicalName)); + throw new LibGit2SharpException( + string.Format( + CultureInfo.InvariantCulture, + "The branch '{0}' (\"{1}\") that you are trying to push does not track an upstream branch.", + branch.Name, branch.CanonicalName)); } } foreach (var branch in enumeratedBranches) { - network.Push(branch.Remote, string.Format("{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), pushOptions); + network.Push(branch.Remote, string.Format( + CultureInfo.InvariantCulture, + "{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), pushOptions); } } } diff --git a/LibGit2Sharp/NoteCollection.cs b/LibGit2Sharp/NoteCollection.cs index c889d22fd..678ffdeac 100644 --- a/LibGit2Sharp/NoteCollection.cs +++ b/LibGit2Sharp/NoteCollection.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.Linq; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp @@ -76,11 +75,9 @@ internal IEnumerable NamespaceRefs { get { - return new[] { NormalizeToCanonicalName(DefaultNamespace) }.Concat( - from reference in repo.Refs - select reference.CanonicalName into refCanonical - where refCanonical.StartsWith(Reference.NotePrefix, StringComparison.Ordinal) && refCanonical != NormalizeToCanonicalName(DefaultNamespace) - select refCanonical); + return new[] { NormalizeToCanonicalName(DefaultNamespace) }.Concat(repo.Refs + .Select(reference => reference.CanonicalName) + .Where(refCanonical => refCanonical.StartsWith(Reference.NotePrefix, StringComparison.Ordinal) && refCanonical != NormalizeToCanonicalName(DefaultNamespace))); } } @@ -156,7 +153,7 @@ internal static string NormalizeToCanonicalName(string name) return string.Concat(Reference.NotePrefix, name); } - internal string UnCanonicalizeName(string name) + internal static string UnCanonicalizeName(string name) { Ensure.ArgumentNotNullOrEmptyString(name, "name"); diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index c180d4249..b9412ddf4 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -7,7 +7,6 @@ using System.Runtime.InteropServices; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; -using LibGit2Sharp.Handlers; namespace LibGit2Sharp { @@ -108,7 +107,7 @@ public virtual void AddBackend(OdbBackend backend, int priority) Ensure.ArgumentNotNull(backend, "backend"); Ensure.ArgumentConformsTo(priority, s => s > 0, "priority"); - Proxy.git_odb_add_backend(this.handle, backend.GitOdbBackendPointer, priority); + Proxy.git_odb_add_backend(handle, backend.GitOdbBackendPointer, priority); } private class Processor @@ -139,7 +138,19 @@ public int Provider(IntPtr content, int max_length, IntPtr data) } } + if (bytesToRead == 0) + { + return 0; + } + int numberOfReadBytes = stream.Read(local, 0, bytesToRead); + + if (numberOfBytesToConsume.HasValue + && numberOfReadBytes == 0) + { + return (int)GitErrorCode.User; + } + totalNumberOfReadBytes += numberOfReadBytes; Marshal.Copy(local, 0, content, numberOfReadBytes); @@ -149,7 +160,8 @@ public int Provider(IntPtr content, int max_length, IntPtr data) } /// - /// Inserts a into the object database, created from the content of a data provider. + /// Inserts a into the object database, created from the content of a stream. + /// Optionally, git filters will be applied to the content before storing it. /// /// The stream from which will be read the content of the blob to be created. /// The hintpath is used to determine what git filters should be applied to the object before it can be placed to the object database. @@ -159,6 +171,12 @@ public virtual Blob CreateBlob(Stream stream, string hintpath = null, int? numbe { Ensure.ArgumentNotNull(stream, "stream"); + // there's no need to buffer the file for filtering, so simply use a stream + if (hintpath == null && numberOfBytesToConsume.HasValue) + { + return CreateBlob(stream, numberOfBytesToConsume.Value); + } + if (!stream.CanRead) { throw new ArgumentException("The stream cannot be read from.", "stream"); @@ -170,6 +188,47 @@ public virtual Blob CreateBlob(Stream stream, string hintpath = null, int? numbe return repo.Lookup(id); } + /// + /// Inserts a into the object database created from the content of the stream. + /// + /// The stream from which will be read the content of the blob to be created. + /// Number of bytes to consume from the stream. + /// The created . + public virtual Blob CreateBlob(Stream stream, int numberOfBytesToConsume) + { + Ensure.ArgumentNotNull(stream, "stream"); + + if (!stream.CanRead) + { + throw new ArgumentException("The stream cannot be read from.", "stream"); + } + + using (var odbStream = Proxy.git_odb_open_wstream(handle, (UIntPtr)numberOfBytesToConsume, GitObjectType.Blob)) + { + var buffer = new byte[4*1024]; + int totalRead = 0; + + while (totalRead < numberOfBytesToConsume) + { + var left = numberOfBytesToConsume - totalRead; + var toRead = left < buffer.Length ? left : buffer.Length; + var read = stream.Read(buffer, 0, toRead); + + if (read == 0) + { + throw new EndOfStreamException("The stream ended unexpectedly"); + } + + Proxy.git_odb_stream_write(odbStream, buffer, read); + totalRead += read; + } + + var id = Proxy.git_odb_stream_finalize_write(odbStream); + + return repo.Lookup(id); + } + } + /// /// Inserts a into the object database, created from a . /// @@ -182,21 +241,6 @@ public virtual Tree CreateTree(TreeDefinition treeDefinition) return treeDefinition.Build(repo); } - /// - /// Inserts a into the object database, referencing an existing . - /// - /// The description of why a change was made to the repository. - /// The of who made the change. - /// The of who added the change to the repository. - /// The of the to be created. - /// The parents of the to be created. - /// The created . - [Obsolete("This method will be removed in the next release. Please use CreateCommit(Signature, Signature, string, bool, Tree, IEnumerable) instead.")] - public virtual Commit CreateCommit(string message, Signature author, Signature committer, Tree tree, IEnumerable parents) - { - return CreateCommit(author, committer, message, true, tree, parents); - } - /// /// Inserts a into the object database, referencing an existing . /// diff --git a/LibGit2Sharp/ObjectType.cs b/LibGit2Sharp/ObjectType.cs index 9b4e007d5..3e5d415fb 100644 --- a/LibGit2Sharp/ObjectType.cs +++ b/LibGit2Sharp/ObjectType.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -48,7 +49,8 @@ public static GitObjectType ToGitObjectType(this ObjectType type) return GitObjectType.Tag; default: - throw new InvalidOperationException(string.Format("Cannot map {0} to a GitObjectType.", type)); + throw new InvalidOperationException( + string.Format(CultureInfo.InvariantCulture, "Cannot map {0} to a GitObjectType.", type)); } } } diff --git a/LibGit2Sharp/OdbBackend.cs b/LibGit2Sharp/OdbBackend.cs index 1862d26b9..549942537 100644 --- a/LibGit2Sharp/OdbBackend.cs +++ b/LibGit2Sharp/OdbBackend.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.IO; using System.Runtime.InteropServices; using LibGit2Sharp.Core; @@ -569,7 +570,9 @@ internal static long ConverToLong(UIntPtr len) if (len.ToUInt64() > long.MaxValue) { throw new InvalidOperationException( - string.Format("Provided length ({0}) exceeds long.MaxValue ({1}).", + string.Format( + CultureInfo.InvariantCulture, + "Provided length ({0}) exceeds long.MaxValue ({1}).", len.ToUInt64(), long.MaxValue)); } diff --git a/LibGit2Sharp/Properties/AssemblyInfo.cs b/LibGit2Sharp/Properties/AssemblyInfo.cs index db3ca028a..08988c23f 100644 --- a/LibGit2Sharp/Properties/AssemblyInfo.cs +++ b/LibGit2Sharp/Properties/AssemblyInfo.cs @@ -42,5 +42,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.17.0")] -[assembly: AssemblyFileVersion("0.17.0")] +[assembly: AssemblyVersion("0.18.0")] +[assembly: AssemblyFileVersion("0.18.0")] diff --git a/LibGit2Sharp/RefSpecCollection.cs b/LibGit2Sharp/RefSpecCollection.cs index 81d4b70c8..26042f9bf 100644 --- a/LibGit2Sharp/RefSpecCollection.cs +++ b/LibGit2Sharp/RefSpecCollection.cs @@ -1,12 +1,10 @@ -using System; -using System.Collections; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Diagnostics; using System.Globalization; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp { diff --git a/LibGit2Sharp/Reference.cs b/LibGit2Sharp/Reference.cs index 9be471a5c..c338bf050 100644 --- a/LibGit2Sharp/Reference.cs +++ b/LibGit2Sharp/Reference.cs @@ -64,6 +64,24 @@ internal static T BuildFromPtr(ReferenceSafeHandle handle, Repository repo) w return reference as T; } + /// + /// Determines if the proposed reference name is well-formed. + /// + /// + /// - Top-level names must contain only capital letters and underscores, + /// and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD"). + /// + /// - Names prefixed with "refs/" can be almost anything. You must avoid + /// the characters '~', '^', ':', '\\', '?', '[', and '*', and the + /// sequences ".." and "@{" which have special meaning to revparse. + /// + /// The name to be checked. + /// true is the name is valid; false otherwise. + public static bool IsValidName(string canonicalName) + { + return Proxy.git_reference_is_valid_name(canonicalName); + } + /// /// Gets the full name of this reference. /// diff --git a/LibGit2Sharp/ReferenceCollection.cs b/LibGit2Sharp/ReferenceCollection.cs index f7c60fc01..95afe8208 100644 --- a/LibGit2Sharp/ReferenceCollection.cs +++ b/LibGit2Sharp/ReferenceCollection.cs @@ -98,20 +98,6 @@ public virtual DirectReference Add(string name, ObjectId targetId, bool allowOve return Add(name, targetId, null, null, allowOverwrite); } - /// - /// Creates a direct reference with the specified name and target - /// - /// The canonical name of the reference to create. - /// Id of the target object. - /// The optional message to log in the when adding the - /// True to allow silent overwriting a potentially existing reference, false otherwise. - /// A new . - [Obsolete("This method will be removed in the next release. Prefer the overload that takes a signature and a message for the reflog.")] - public virtual DirectReference Add(string name, ObjectId targetId, bool allowOverwrite, string logMessage) - { - return Add(name, targetId, null, logMessage, allowOverwrite); - } - /// /// Creates a symbolic reference with the specified name and target /// @@ -145,20 +131,6 @@ public virtual SymbolicReference Add(string name, Reference targetRef, bool allo return Add(name, targetRef, null, null, allowOverwrite); } - /// - /// Creates a symbolic reference with the specified name and target - /// - /// The canonical name of the reference to create. - /// The target reference. - /// The optional message to log in the when adding the - /// True to allow silent overwriting a potentially existing reference, false otherwise. - /// A new . - [Obsolete("This method will be removed in the next release. Prefer the overload that takes a signature and a message for the reflog.")] - public virtual SymbolicReference Add(string name, Reference targetRef, bool allowOverwrite, string logMessage) - { - return Add(name, targetRef, null, logMessage, allowOverwrite); - } - /// /// Remove a reference from the repository /// @@ -186,7 +158,7 @@ public virtual Reference Move(Reference reference, string newName, Signature sig if (logMessage == null) { - logMessage = string.Format("{0}: renamed {1} to {2}", + logMessage = string.Format(CultureInfo.InvariantCulture, "{0}: renamed {1} to {2}", reference.IsLocalBranch() ? "branch" : "reference", reference.CanonicalName, newName); } @@ -257,19 +229,6 @@ public virtual Reference UpdateTarget(Reference directRef, ObjectId targetId) return UpdateTarget(directRef, targetId, null, null); } - /// - /// Updates the target of a direct reference - /// - /// The direct reference which target should be updated. - /// The new target. - /// The optional message to log in the of the reference - /// A new . - [Obsolete("This method will be removed in the next release. Prefer the overload that takes a signature and a message for the reflog.")] - public virtual Reference UpdateTarget(Reference directRef, ObjectId targetId, string logMessage) - { - return UpdateTarget(directRef, targetId, null, logMessage); - } - /// /// Updates the target of a symbolic reference /// @@ -308,19 +267,6 @@ public virtual Reference UpdateTarget(Reference symbolicRef, Reference targetRef return UpdateTarget(symbolicRef, targetRef, null, null); } - /// - /// Updates the target of a symbolic reference - /// - /// The symbolic reference which target should be updated. - /// The new target. - /// The optional message to log in the of the reference. - /// A new . - [Obsolete("This method will be removed in the next release. Prefer the overload that takes a signature and a message for the reflog.")] - public virtual Reference UpdateTarget(Reference symbolicRef, Reference targetRef, string logMessage) - { - return UpdateTarget(symbolicRef, targetRef, null, logMessage); - } - internal Reference UpdateHeadTarget(T target, Signature signature, string logMessage) { Debug.Assert(signature != null); @@ -337,7 +283,7 @@ internal Reference UpdateHeadTarget(T target, Signature signature, string log { var targetIdentifier = target as string; - if (IsValidName(targetIdentifier)) + if (Reference.IsValidName(targetIdentifier)) { Proxy.git_repository_set_head(repo.Handle, targetIdentifier, signature, logMessage); } @@ -394,9 +340,10 @@ public virtual IEnumerable FromGlob(string pattern) /// /// The name to be checked. /// true is the name is valid; false otherwise. + [Obsolete("This method will be removed in the next release. Please use Reference.IsValidName(string) instead.")] public virtual bool IsValidName(string canonicalName) { - return Proxy.git_reference_is_valid_name(canonicalName); + return Reference.IsValidName(canonicalName); } /// diff --git a/LibGit2Sharp/ReferenceCollectionExtensions.cs b/LibGit2Sharp/ReferenceCollectionExtensions.cs index ee5526498..4442b48da 100644 --- a/LibGit2Sharp/ReferenceCollectionExtensions.cs +++ b/LibGit2Sharp/ReferenceCollectionExtensions.cs @@ -21,7 +21,7 @@ private enum RefState private static RefState TryResolveReference(out Reference reference, ReferenceCollection refsColl, string canonicalName) { - if (!refsColl.IsValidName(canonicalName)) + if (!Reference.IsValidName(canonicalName)) { reference = null; return RefState.DoesNotLookValid; @@ -70,7 +70,7 @@ public static Reference Add(this ReferenceCollection refsColl, string name, stri if (logMessage == null) { - logMessage = string.Format("{0}: Created from {1}", + logMessage = string.Format(CultureInfo.InvariantCulture, "{0}: Created from {1}", name.LooksLikeLocalBranch() ? "branch" : "reference", canonicalRefNameOrObjectish); } @@ -91,21 +91,6 @@ public static Reference Add(this ReferenceCollection refsColl, string name, stri return Add(refsColl, name, canonicalRefNameOrObjectish, null, null, allowOverwrite); } - /// - /// Creates a direct or symbolic reference with the specified name and target - /// - /// The being worked with. - /// The name of the reference to create. - /// The target which can be either the canonical name of a reference or a revparse spec. - /// The optional message to log in the when adding the - /// True to allow silent overwriting a potentially existing reference, false otherwise. - /// A new . - [Obsolete("This method will be removed in the next release. Prefer the overload that takes a signature and a message for the reflog.")] - public static Reference Add(this ReferenceCollection refsColl, string name, string canonicalRefNameOrObjectish, bool allowOverwrite, string logMessage) - { - return Add(refsColl, name, canonicalRefNameOrObjectish, null, logMessage, allowOverwrite); - } - /// /// Updates the target of a direct reference. /// @@ -139,20 +124,6 @@ public static Reference UpdateTarget(this ReferenceCollection refsColl, Referenc return UpdateTarget(refsColl, directRef, objectish, null, null); } - /// - /// Updates the target of a direct reference - /// - /// The being worked with. - /// The direct reference which target should be updated. - /// The revparse spec of the target. - /// The optional message to log in the of the reference. - /// A new . - [Obsolete("This method will be removed in the next release. Prefer the overload that takes a signature and a message for the reflog.")] - public static Reference UpdateTarget(this ReferenceCollection refsColl, Reference directRef, string objectish, string logMessage) - { - return UpdateTarget(refsColl, directRef, objectish, null, logMessage); - } - /// /// Rename an existing reference with a new name /// @@ -239,21 +210,6 @@ public static Reference UpdateTarget(this ReferenceCollection refsColl, string n return UpdateTarget(refsColl, name, canonicalRefNameOrObjectish, null, null); } - /// - /// Updates the target of a reference - /// - /// The being worked with. - /// The canonical name of the reference. - /// The target which can be either the canonical name of a reference or a revparse spec. - /// The optional message to log in the of the reference. - /// A new . - [Obsolete("This method will be removed in the next release. Prefer the overload that takes a signature and a message for the reflog.")] - public static Reference UpdateTarget(this ReferenceCollection refsColl, string name, string canonicalRefNameOrObjectish, string logMessage) - { - return UpdateTarget(refsColl, name, canonicalRefNameOrObjectish, null, logMessage); - } - - /// /// Delete a reference with the specified name /// diff --git a/LibGit2Sharp/ReferenceWrapper.cs b/LibGit2Sharp/ReferenceWrapper.cs index 4a6eeb7ab..aaf560709 100644 --- a/LibGit2Sharp/ReferenceWrapper.cs +++ b/LibGit2Sharp/ReferenceWrapper.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.Globalization; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp { diff --git a/LibGit2Sharp/ReflogCollection.cs b/LibGit2Sharp/ReflogCollection.cs index 3d6fa660d..d95efbcb7 100644 --- a/LibGit2Sharp/ReflogCollection.cs +++ b/LibGit2Sharp/ReflogCollection.cs @@ -36,10 +36,10 @@ internal ReflogCollection(Repository repo, string canonicalName) Ensure.ArgumentNotNullOrEmptyString(canonicalName, "canonicalName"); Ensure.ArgumentNotNull(repo, "repo"); - if (!repo.Refs.IsValidName(canonicalName)) + if (!Reference.IsValidName(canonicalName)) { throw new InvalidSpecificationException( - string.Format("The given reference name '{0}' is not valid", canonicalName)); + string.Format(CultureInfo.InvariantCulture, "The given reference name '{0}' is not valid", canonicalName)); } this.repo = repo; diff --git a/LibGit2Sharp/Remote.cs b/LibGit2Sharp/Remote.cs index 4524e77aa..d86e44ebc 100644 --- a/LibGit2Sharp/Remote.cs +++ b/LibGit2Sharp/Remote.cs @@ -95,6 +95,16 @@ internal string FetchSpecTransformToSource(string reference) } } + /// + /// Determines if the proposed remote name is well-formed. + /// + /// The name to be checked. + /// true is the name is valid; false otherwise. + public static bool IsValidName(string name) + { + return Proxy.git_remote_is_valid_name(name); + } + /// /// Determines whether the specified is equal to the current . /// diff --git a/LibGit2Sharp/RemoteCollection.cs b/LibGit2Sharp/RemoteCollection.cs index ca58c51d7..443dc3f5f 100644 --- a/LibGit2Sharp/RemoteCollection.cs +++ b/LibGit2Sharp/RemoteCollection.cs @@ -131,9 +131,22 @@ public virtual Remote Add(string name, string url, string fetchRefSpec) /// /// The name to be checked. /// true is the name is valid; false otherwise. + [Obsolete("This method will be removed in the next release. Please use Remote.IsValidName(string) instead.")] public virtual bool IsValidName(string name) { - return Proxy.git_remote_is_valid_name(name); + return Remote.IsValidName(name); + } + + /// + /// Deletes the with the specified name. + /// + /// The name of the remote to remove. + /// A new . + public virtual void Remove(string name) + { + Ensure.ArgumentNotNull(name, "name"); + + Proxy.git_remote_delete(repository.Handle, name); } private string DebuggerDisplay diff --git a/LibGit2Sharp/RemoteUpdater.cs b/LibGit2Sharp/RemoteUpdater.cs index 74b989a3e..3759ff498 100644 --- a/LibGit2Sharp/RemoteUpdater.cs +++ b/LibGit2Sharp/RemoteUpdater.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp { diff --git a/LibGit2Sharp/RemoveFromIndexException.cs b/LibGit2Sharp/RemoveFromIndexException.cs index 7e138120a..52e9ffc79 100644 --- a/LibGit2Sharp/RemoveFromIndexException.cs +++ b/LibGit2Sharp/RemoveFromIndexException.cs @@ -45,10 +45,5 @@ protected RemoveFromIndexException(SerializationInfo info, StreamingContext cont : base(info, context) { } - - internal RemoveFromIndexException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) - { - } } } diff --git a/LibGit2Sharp/RenameDetails.cs b/LibGit2Sharp/RenameDetails.cs index bfc470589..199b7269f 100644 --- a/LibGit2Sharp/RenameDetails.cs +++ b/LibGit2Sharp/RenameDetails.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Globalization; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -109,7 +110,9 @@ private string DebuggerDisplay { get { - return string.Format("{0} -> {1} [{2}%]", OldFilePath, NewFilePath, Similarity); + return string.Format( + CultureInfo.InvariantCulture, + "{0} -> {1} [{2}%]", OldFilePath, NewFilePath, Similarity); } } } diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 5523fb6de..3e56327f1 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -7,7 +7,6 @@ using System.Reflection; using System.Text.RegularExpressions; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; using LibGit2Sharp.Handlers; @@ -341,7 +340,6 @@ public SubmoduleCollection Submodules public void Dispose() { Dispose(true); - GC.SuppressFinalize(this); } /// @@ -442,12 +440,8 @@ internal GitObject LookupInternal(ObjectId id, GitObjectType type, FilePath know { Ensure.ArgumentNotNull(id, "id"); - GitObjectSafeHandle obj = null; - - try + using (GitObjectSafeHandle obj = Proxy.git_object_lookup(handle, id, type)) { - obj = Proxy.git_object_lookup(handle, id, type); - if (obj == null) { return null; @@ -455,10 +449,6 @@ internal GitObject LookupInternal(ObjectId id, GitObjectType type, FilePath know return GitObject.BuildFrom(this, id, Proxy.git_object_type(obj), knownPath); } - finally - { - obj.SafeDispose(); - } } private static string PathFromRevparseSpec(string spec) @@ -547,81 +537,33 @@ public static string Discover(string startingPath) /// controlling clone behavior /// The path to the created repository. public static string Clone(string sourceUrl, string workdirPath, - CloneOptions options) + CloneOptions options = null) { - CheckoutCallbacks checkoutCallbacks = CheckoutCallbacks.GenerateCheckoutCallbacks( - options.OnCheckoutProgress, null); + options = options ?? new CloneOptions(); - var callbacks = new RemoteCallbacks(null, options.OnTransferProgress, null, - options.Credentials); - GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks(); - - var cloneOpts = new GitCloneOptions + using (GitCheckoutOptsWrapper checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) { - Version = 1, - Bare = options.IsBare ? 1 : 0, - CheckoutOpts = - { - version = 1, - progress_cb = - checkoutCallbacks.CheckoutProgressCallback, - checkout_strategy = options.Checkout - ? CheckoutStrategy.GIT_CHECKOUT_SAFE_CREATE - : CheckoutStrategy.GIT_CHECKOUT_NONE - }, - RemoteCallbacks = gitCallbacks, - }; + var gitCheckoutOptions = checkoutOptionsWrapper.Options; - FilePath repoPath; - using (RepositorySafeHandle repo = Proxy.git_clone(sourceUrl, workdirPath, ref cloneOpts)) - { - repoPath = Proxy.git_repository_path(repo); - } + var remoteCallbacks = new RemoteCallbacks(null, options.OnTransferProgress, null, options.Credentials); + var gitRemoteCallbacks = remoteCallbacks.GenerateCallbacks(); - return repoPath.Native; - } + var cloneOpts = new GitCloneOptions + { + Version = 1, + Bare = options.IsBare ? 1 : 0, + CheckoutOpts = gitCheckoutOptions, + RemoteCallbacks = gitRemoteCallbacks, + }; - /// - /// Clone with specified options. - /// - /// URI for the remote repository - /// Local path to clone into - /// True will result in a bare clone, false a full clone. - /// If true, the origin's HEAD will be checked out. This only applies - /// to non-bare repositories. - /// Handler for network transfer and indexing progress information - /// Handler for checkout progress information - /// Credentials to use for user/pass authentication - /// The path to the created repository. - [Obsolete("This overload will be removed in the next release. Please use Repository.Clone(string, string, CloneOptions) instead.")] - public static string Clone(string sourceUrl, string workdirPath, - bool bare = false, - bool checkout = true, - TransferProgressHandler onTransferProgress = null, - CheckoutProgressHandler onCheckoutProgress = null, - Credentials credentials = null) - { - return Clone(sourceUrl, workdirPath, new CloneOptions() - { - IsBare = bare, - Checkout = checkout, - OnTransferProgress = onTransferProgress, - OnCheckoutProgress = onCheckoutProgress, - Credentials = credentials - }); - } + FilePath repoPath; + using (RepositorySafeHandle repo = Proxy.git_clone(sourceUrl, workdirPath, ref cloneOpts)) + { + repoPath = Proxy.git_repository_path(repo); + } - /// - /// Clone without options. - /// - /// URI for the remote repository - /// Local path to clone into - /// The path to the created repository. - public static string Clone(string sourceUrl, string workdirPath) - { - // This overload is required to supress the obsolete warning if called without arguments. - // Should be removed once the obsolete overload is removed. - return Clone(sourceUrl, workdirPath, new CloneOptions()); + return repoPath.Native; + } } /// @@ -648,9 +590,39 @@ public BlameHunkCollection Blame(string path, BlameOptions options = null) /// to manage checkout notifications. /// Identity for use when updating the reflog. /// The that was checked out. + [Obsolete("This overload will be removed in the next release. Please use Repository.Checkout(string, CheckoutOptions, Signature) instead.")] public Branch Checkout(string committishOrBranchSpec, CheckoutModifiers checkoutModifiers, CheckoutProgressHandler onCheckoutProgress, CheckoutNotificationOptions checkoutNotifications, Signature signature = null) + { + var options = new CheckoutOptions() + { + CheckoutModifiers = checkoutModifiers, + OnCheckoutProgress = onCheckoutProgress + }; + + if (checkoutNotifications != null) + { + options.OnCheckoutNotify = checkoutNotifications.CheckoutNotifyHandler; + options.CheckoutNotifyFlags = checkoutNotifications.NotifyFlags; + } + + return Checkout(committishOrBranchSpec, options, signature); + } + + /// + /// Checkout the specified , reference or SHA. + /// + /// If the committishOrBranchSpec parameter resolves to a branch name, then the checked out HEAD will + /// will point to the branch. Otherwise, the HEAD will be detached, pointing at the commit sha. + /// + /// + /// A revparse spec for the commit or branch to checkout. + /// controlling checkout behavior. + /// Identity for use when updating the reflog. + /// The that was checked out. + public Branch Checkout(string committishOrBranchSpec, CheckoutOptions options, Signature signature = null) { Ensure.ArgumentNotNullOrEmptyString(committishOrBranchSpec, "committishOrBranchSpec"); + Ensure.ArgumentNotNull(options, "options"); var handles = Proxy.git_revparse_ext(Handle, committishOrBranchSpec); if (handles == null) @@ -669,7 +641,7 @@ public Branch Checkout(string committishOrBranchSpec, CheckoutModifiers checkout if (reference.IsLocalBranch()) { Branch branch = Branches[reference.CanonicalName]; - return Checkout(branch, checkoutModifiers, onCheckoutProgress, checkoutNotifications); + return Checkout(branch, options, signature); } } @@ -683,7 +655,7 @@ public Branch Checkout(string committishOrBranchSpec, CheckoutModifiers checkout } Commit commit = obj.DereferenceToCommit(true); - Checkout(commit.Tree, checkoutModifiers, onCheckoutProgress, checkoutNotifications, commit.Id.Sha, committishOrBranchSpec, signature); + Checkout(commit.Tree, options, commit.Id.Sha, committishOrBranchSpec, signature); return Head; } @@ -699,10 +671,40 @@ public Branch Checkout(string committishOrBranchSpec, CheckoutModifiers checkout /// to manage checkout notifications. /// Identity for use when updating the reflog. /// The that was checked out. + [Obsolete("This overload will be removed in the next release. Please use Repository.Checkout(Branch, CheckoutOptions, Signature) instead.")] public Branch Checkout(Branch branch, CheckoutModifiers checkoutModifiers, CheckoutProgressHandler onCheckoutProgress, CheckoutNotificationOptions checkoutNotificationOptions, Signature signature = null) { Ensure.ArgumentNotNull(branch, "branch"); + var options = new CheckoutOptions + { + CheckoutModifiers = checkoutModifiers, + OnCheckoutProgress = onCheckoutProgress, + }; + + if (checkoutNotificationOptions != null) + { + options.OnCheckoutNotify = checkoutNotificationOptions.CheckoutNotifyHandler; + options.CheckoutNotifyFlags = checkoutNotificationOptions.NotifyFlags; + } + + return Checkout(branch, options, signature); + } + + /// + /// Checkout the tip commit of the specified object. If this commit is the + /// current tip of the branch, will checkout the named branch. Otherwise, will checkout the tip commit + /// as a detached HEAD. + /// + /// The to check out. + /// controlling checkout behavior. + /// Identity for use when updating the reflog. + /// The that was checked out. + public Branch Checkout(Branch branch, CheckoutOptions options, Signature signature = null) + { + Ensure.ArgumentNotNull(branch, "branch"); + Ensure.ArgumentNotNull(options, "options"); + // Make sure this is not an unborn branch. if (branch.Tip == null) { @@ -715,11 +717,11 @@ public Branch Checkout(Branch branch, CheckoutModifiers checkoutModifiers, Check string.Equals(Refs[branch.CanonicalName].TargetIdentifier, branch.Tip.Id.Sha, StringComparison.OrdinalIgnoreCase)) { - Checkout(branch.Tip.Tree, checkoutModifiers, onCheckoutProgress, checkoutNotificationOptions, branch.CanonicalName, branch.Name, signature); + Checkout(branch.Tip.Tree, options, branch.CanonicalName, branch.Name, signature); } else { - Checkout(branch.Tip.Tree, checkoutModifiers, onCheckoutProgress, checkoutNotificationOptions, branch.Tip.Id.Sha, branch.Name, signature); + Checkout(branch.Tip.Tree, options, branch.Tip.Id.Sha, branch.Name, signature); } return Head; @@ -737,9 +739,43 @@ public Branch Checkout(Branch branch, CheckoutModifiers checkoutModifiers, Check /// to manage checkout notifications. /// Identity for use when updating the reflog. /// The that was checked out. + [Obsolete("This overload will be removed in the next release. Please use Repository.Checkout(Commit, CheckoutOptions, Signature) instead.")] public Branch Checkout(Commit commit, CheckoutModifiers checkoutModifiers, CheckoutProgressHandler onCheckoutProgress, CheckoutNotificationOptions checkoutNotificationOptions, Signature signature = null) { - Checkout(commit.Tree, checkoutModifiers, onCheckoutProgress, checkoutNotificationOptions, commit.Id.Sha, commit.Id.Sha, signature); + + var options = new CheckoutOptions + { + CheckoutModifiers = checkoutModifiers, + OnCheckoutProgress = onCheckoutProgress, + }; + + if (checkoutNotificationOptions != null) + { + options.OnCheckoutNotify = checkoutNotificationOptions.CheckoutNotifyHandler; + options.CheckoutNotifyFlags = checkoutNotificationOptions.NotifyFlags; + } + + Checkout(commit.Tree, options, commit.Id.Sha, commit.Id.Sha, signature); + + return Head; + } + + /// + /// Checkout the specified . + /// + /// Will detach the HEAD and make it point to this commit sha. + /// + /// + /// The to check out. + /// controlling checkout behavior. + /// Identity for use when updating the reflog. + /// The that was checked out. + public Branch Checkout(Commit commit, CheckoutOptions options, Signature signature = null) + { + Ensure.ArgumentNotNull(commit, "commit"); + Ensure.ArgumentNotNull(options, "options"); + + Checkout(commit.Tree, options, commit.Id.Sha, commit.Id.Sha, signature); return Head; } @@ -749,32 +785,23 @@ public Branch Checkout(Commit commit, CheckoutModifiers checkoutModifiers, Check /// to already be in the form of a canonical branch name or a commit ID. /// /// The to checkout. - /// controlling checkout behavior. - /// that checkout progress is reported through. - /// to manage checkout notifications. + /// controlling checkout behavior. /// Target for the new HEAD. /// The spec which will be written as target in the reflog. /// Identity for use when updating the reflog. private void Checkout( Tree tree, - CheckoutModifiers checkoutModifiers, - CheckoutProgressHandler onCheckoutProgress, - CheckoutNotificationOptions checkoutNotificationOptions, + CheckoutOptions checkoutOptions, string headTarget, string refLogHeadSpec, Signature signature) { var previousHeadName = Info.IsHeadDetached ? Head.Tip.Sha : Head.Name; - var opts = new CheckoutOptions - { - CheckoutModifiers = checkoutModifiers, - OnCheckoutProgress = onCheckoutProgress, - CheckoutNotificationOptions = checkoutNotificationOptions - }; - - CheckoutTree(tree, null, opts); + CheckoutTree(tree, null, checkoutOptions); Refs.UpdateTarget("HEAD", headTarget, signature, - string.Format("checkout: moving from {0} to {1}", previousHeadName, refLogHeadSpec)); + string.Format( + CultureInfo.InvariantCulture, + "checkout: moving from {0} to {1}", previousHeadName, refLogHeadSpec)); } /// @@ -786,37 +813,14 @@ private void Checkout( private void CheckoutTree( Tree tree, IList paths, - CheckoutOptions opts) + IConvertableToGitCheckoutOpts opts) { - CheckoutNotifyHandler onCheckoutNotify = opts.CheckoutNotificationOptions != null ? opts.CheckoutNotificationOptions.CheckoutNotifyHandler : null; - CheckoutNotifyFlags checkoutNotifyFlags = opts.CheckoutNotificationOptions != null ? opts.CheckoutNotificationOptions.NotifyFlags : default(CheckoutNotifyFlags); - CheckoutCallbacks checkoutCallbacks = CheckoutCallbacks.GenerateCheckoutCallbacks(opts.OnCheckoutProgress, onCheckoutNotify); - - GitStrArrayIn strArray = (paths != null && paths.Count > 0) ? GitStrArrayIn.BuildFrom(ToFilePaths(paths)) : null; - - var options = new GitCheckoutOpts - { - version = 1, - checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_SAFE, - progress_cb = checkoutCallbacks.CheckoutProgressCallback, - notify_cb = checkoutCallbacks.CheckoutNotifyCallback, - notify_flags = checkoutNotifyFlags, - paths = strArray - }; - try + using(GitCheckoutOptsWrapper checkoutOptionsWrapper = new GitCheckoutOptsWrapper(opts, ToFilePaths(paths))) { - if (opts.CheckoutModifiers.HasFlag(CheckoutModifiers.Force)) - { - options.checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_FORCE; - } - + var options = checkoutOptionsWrapper.Options; Proxy.git_checkout_tree(Handle, tree.Id, ref options); } - finally - { - options.Dispose(); - } } /// @@ -833,7 +837,9 @@ public void Reset(ResetMode resetMode, Commit commit, Signature signature = null if (logMessage == null) { - logMessage = string.Format("reset: moving to {0}", commit.Sha); + logMessage = string.Format( + CultureInfo.InvariantCulture, + "reset: moving to {0}", commit.Sha); } Proxy.git_reset(handle, commit.Id, resetMode, signature.OrDefault(Config), logMessage); @@ -923,7 +929,8 @@ public Commit Commit(string message, Signature author, Signature committer, Comm { throw new EmptyCommitException( options.AmendPreviousCommit ? - String.Format("Amending this commit would produce a commit that is identical to its parent (id = {0})", parents[0].Id) : + String.Format(CultureInfo.InvariantCulture, + "Amending this commit would produce a commit that is identical to its parent (id = {0})", parents[0].Id) : "No changes; nothing to commit."); } } @@ -932,35 +939,13 @@ public Commit Commit(string message, Signature author, Signature committer, Comm Proxy.git_repository_state_cleanup(handle); - var logAllRefUpdates = Config.GetValueOrDefault("core.logAllRefUpdates", false); - if (!logAllRefUpdates) - { - return result; - } - var logMessage = BuildCommitLogMessage(result, options.AmendPreviousCommit, isHeadOrphaned, parents.Count > 1); - LogCommit(result, logMessage); + UpdateHeadAndTerminalReference(result, logMessage); return result; } - /// - /// Stores the content of the as a new into the repository. - /// The tip of the will be used as the parent of this new Commit. - /// Once the commit is created, the will move forward to point at it. - /// - /// The description of why a change was made to the repository. - /// The of who made the change. - /// The of who added the change to the repository. - /// True to amend the current pointed at by , false otherwise. - /// The generated . - [Obsolete("This method will be removed in the next release. Please use a Commit overload that accepts a CommitOptions instead.")] - public Commit Commit(string message, Signature author, Signature committer, bool amendPreviousCommit) - { - return Commit(message, author, committer, new CommitOptions { AmendPreviousCommit = amendPreviousCommit }); - } - - private string BuildCommitLogMessage(Commit commit, bool amendPreviousCommit, bool isHeadOrphaned, bool isMergeCommit) + private static string BuildCommitLogMessage(Commit commit, bool amendPreviousCommit, bool isHeadOrphaned, bool isMergeCommit) { string kind = string.Empty; if (isHeadOrphaned) @@ -976,10 +961,10 @@ private string BuildCommitLogMessage(Commit commit, bool amendPreviousCommit, bo kind = " (merge)"; } - return string.Format("commit{0}: {1}", kind, commit.MessageShort); + return string.Format(CultureInfo.InvariantCulture, "commit{0}: {1}", kind, commit.MessageShort); } - private void LogCommit(Commit commit, string reflogMessage) + private void UpdateHeadAndTerminalReference(Commit commit, string reflogMessage) { Reference reference = Refs.Head; @@ -1037,14 +1022,7 @@ public void RemoveUntrackedFiles() | CheckoutStrategy.GIT_CHECKOUT_ALLOW_CONFLICTS, }; - try - { - Proxy.git_checkout_index(Handle, new NullGitObjectSafeHandle(), ref options); - } - finally - { - options.Dispose(); - } + Proxy.git_checkout_index(Handle, new NullGitObjectSafeHandle(), ref options); } private void CleanupDisposableDependencies() @@ -1065,7 +1043,7 @@ internal T RegisterForCleanup(T disposable) where T : IDisposable /// Gets the current LibGit2Sharp version. /// /// The format of the version number is as follows: - /// Major.Minor.Patch-LibGit2Sharp_abbrev_hash-libgit2_abbrev_hash (x86|amd64) + /// Major.Minor.Patch-LibGit2Sharp_abbrev_hash-libgit2_abbrev_hash (x86|amd64 - features) /// /// public static string Version @@ -1081,15 +1059,16 @@ private static string RetrieveVersion() string libgit2Hash = ReadContentFromResource(assembly, "libgit2_hash.txt"); string libgit2sharpHash = ReadContentFromResource(assembly, "libgit2sharp_hash.txt"); + string features = GlobalSettings.Features().ToString(); return string.Format( CultureInfo.InvariantCulture, - "{0}-{1}-{2} ({3})", + "{0}-{1}-{2} ({3} - {4})", version.ToString(3), libgit2sharpHash.Substring(0, 7), libgit2Hash.Substring(0, 7), - NativeMethods.ProcessorArchitecture - ); + NativeMethods.ProcessorArchitecture, + features); } private static string ReadContentFromResource(Assembly assembly, string partialResourceName) @@ -1117,7 +1096,7 @@ public MergeResult Merge(Commit commit, Signature merger, MergeOptions options = using (GitMergeHeadHandle mergeHeadHandle = Proxy.git_merge_head_from_id(Handle, commit.Id.Oid)) { - return Merge(new GitMergeHeadHandle[] { mergeHeadHandle }, merger, options); + return Merge(new[] { mergeHeadHandle }, merger, options); } } @@ -1138,7 +1117,7 @@ public MergeResult Merge(Branch branch, Signature merger, MergeOptions options = using (ReferenceSafeHandle referencePtr = Refs.RetrieveReferencePtr(branch.CanonicalName)) using (GitMergeHeadHandle mergeHeadHandle = Proxy.git_merge_head_from_ref(Handle, referencePtr)) { - return Merge(new GitMergeHeadHandle[] { mergeHeadHandle }, merger, options); + return Merge(new[] { mergeHeadHandle }, merger, options); } } @@ -1156,7 +1135,7 @@ public MergeResult Merge(string committish, Signature merger, MergeOptions optio options = options ?? new MergeOptions(); - Commit commit = this.LookupCommit(committish); + Commit commit = LookupCommit(committish); return Merge(commit, merger, options); } @@ -1198,6 +1177,63 @@ internal MergeResult MergeFetchHeads(Signature merger, MergeOptions options) } } + /// + /// Revert the specified commit. + /// + /// The to revert. + /// The of who is performing the reverte. + /// controlling revert behavior. + /// The result of the revert. + public RevertResult Revert(Commit commit, Signature reverter, RevertOptions options = null) + { + Ensure.ArgumentNotNull(commit, "commit"); + Ensure.ArgumentNotNull(reverter, "reverter"); + + options = options ?? new RevertOptions(); + + RevertResult result = null; + + using (GitCheckoutOptsWrapper checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) + { + var mergeOptions = new GitMergeOpts + { + Version = 1, + MergeFileFavorFlags = options.MergeFileFavor, + MergeTreeFlags = options.FindRenames ? GitMergeTreeFlags.GIT_MERGE_TREE_FIND_RENAMES : + GitMergeTreeFlags.GIT_MERGE_TREE_NORMAL, + RenameThreshold = (uint)options.RenameThreshold, + TargetLimit = (uint)options.TargetLimit, + }; + + GitRevertOpts gitRevertOpts = new GitRevertOpts() + { + Mainline = (uint) options.Mainline, + MergeOpts = mergeOptions, + + CheckoutOpts = checkoutOptionsWrapper.Options, + }; + + Proxy.git_revert(handle, commit.Id.Oid, gitRevertOpts); + + if(Index.IsFullyMerged) + { + Commit revertCommit = null; + if(options.CommitOnSuccess) + { + revertCommit = this.Commit(Info.Message, author: reverter, committer: reverter); + } + + result = new RevertResult(RevertStatus.Reverted, revertCommit); + } + else + { + result = new RevertResult(RevertStatus.Conflicts); + } + } + + return result; + } + /// /// Internal implementation of merge. /// @@ -1207,7 +1243,10 @@ internal MergeResult MergeFetchHeads(Signature merger, MergeOptions options) /// The of the merge. private MergeResult Merge(GitMergeHeadHandle[] mergeHeads, Signature merger, MergeOptions options) { - GitMergeAnalysis mergeAnalysis = Proxy.git_merge_analysis(Handle, mergeHeads); + GitMergeAnalysis mergeAnalysis; + GitMergePreference mergePreference; + + Proxy.git_merge_analysis(Handle, mergeHeads, out mergeAnalysis, out mergePreference); MergeResult mergeResult = null; @@ -1227,7 +1266,7 @@ private MergeResult Merge(GitMergeHeadHandle[] mergeHeads, Signature merger, Mer throw new LibGit2SharpException("Unable to perform Fast-Forward merge with mith multiple merge heads."); } - mergeResult = FastForwardMerge(mergeHeads[0], merger); + mergeResult = FastForwardMerge(mergeHeads[0], merger, options); } else if (mergeAnalysis.HasFlag(GitMergeAnalysis.GIT_MERGE_ANALYSIS_NORMAL)) { @@ -1243,7 +1282,7 @@ private MergeResult Merge(GitMergeHeadHandle[] mergeHeads, Signature merger, Mer throw new LibGit2SharpException("Unable to perform Fast-Forward merge with mith multiple merge heads."); } - mergeResult = FastForwardMerge(mergeHeads[0], merger); + mergeResult = FastForwardMerge(mergeHeads[0], merger, options); } else { @@ -1259,12 +1298,14 @@ private MergeResult Merge(GitMergeHeadHandle[] mergeHeads, Signature merger, Mer } break; default: - throw new NotImplementedException(string.Format("Unknown fast forward strategy: {0}", mergeAnalysis)); + throw new NotImplementedException( + string.Format(CultureInfo.InvariantCulture, "Unknown fast forward strategy: {0}", mergeAnalysis)); } if (mergeResult == null) { - throw new NotImplementedException(string.Format("Unknown merge analysis: {0}", options.FastForwardStrategy)); + throw new NotImplementedException( + string.Format(CultureInfo.InvariantCulture, "Unknown merge analysis: {0}", options.FastForwardStrategy)); } return mergeResult; @@ -1281,17 +1322,22 @@ private MergeResult NormalMerge(GitMergeHeadHandle[] mergeHeads, Signature merge { MergeResult mergeResult; - GitMergeOpts mergeOptions = new GitMergeOpts() + var mergeOptions = new GitMergeOpts { - Version = 1 + Version = 1, + MergeFileFavorFlags = options.MergeFileFavor, + MergeTreeFlags = options.FindRenames ? GitMergeTreeFlags.GIT_MERGE_TREE_FIND_RENAMES : + GitMergeTreeFlags.GIT_MERGE_TREE_NORMAL, + RenameThreshold = (uint) options.RenameThreshold, + TargetLimit = (uint) options.TargetLimit, }; - GitCheckoutOpts checkoutOpts = new GitCheckoutOpts() + using (GitCheckoutOptsWrapper checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) { - version = 1 - }; + var checkoutOpts = checkoutOptionsWrapper.Options; - Proxy.git_merge(Handle, mergeHeads, mergeOptions, checkoutOpts); + Proxy.git_merge(Handle, mergeHeads, mergeOptions, checkoutOpts); + } if (Index.IsFullyMerged) { @@ -1299,7 +1345,7 @@ private MergeResult NormalMerge(GitMergeHeadHandle[] mergeHeads, Signature merge if (options.CommitOnSuccess) { // Commit the merge - mergeCommit = this.Commit(Info.Message, author: merger, committer: merger); + mergeCommit = Commit(Info.Message, author: merger, committer: merger); } mergeResult = new MergeResult(MergeStatus.NonFastForward, mergeCommit); @@ -1317,23 +1363,22 @@ private MergeResult NormalMerge(GitMergeHeadHandle[] mergeHeads, Signature merge /// /// The merge head handle to fast-forward merge. /// The of who is performing the merge. + /// Options controlling merge behavior. /// The of the merge. - private MergeResult FastForwardMerge(GitMergeHeadHandle mergeHead, Signature merger) + private MergeResult FastForwardMerge(GitMergeHeadHandle mergeHead, Signature merger, MergeOptions options) { ObjectId id = Proxy.git_merge_head_id(mergeHead); Commit fastForwardCommit = (Commit) Lookup(id, ObjectType.Commit); Ensure.GitObjectIsNotNull(fastForwardCommit, id.Sha); - var checkoutOpts = new CheckoutOptions - { - CheckoutModifiers = CheckoutModifiers.None, - }; - CheckoutTree(fastForwardCommit.Tree, null, checkoutOpts); + CheckoutTree(fastForwardCommit.Tree, null, options); var reference = Refs.Head.ResolveToDirectReference(); // TODO: This reflog entry could be more specific - string refLogEntry = string.Format("merge {0}: Fast-forward", fastForwardCommit.Sha); + string refLogEntry = string.Format( + CultureInfo.InvariantCulture, "merge {0}: Fast-forward", fastForwardCommit.Sha); + if (reference == null) { // Reference does not exist, create it. @@ -1351,8 +1396,7 @@ private MergeResult FastForwardMerge(GitMergeHeadHandle mergeHead, Signature mer /// /// Gets the references to the tips that are currently being merged. /// - [Obsolete("This property is meant for internal use only and will not be public in the next release.")] - public IEnumerable MergeHeads + internal IEnumerable MergeHeads { get { diff --git a/LibGit2Sharp/RepositoryExtensions.cs b/LibGit2Sharp/RepositoryExtensions.cs index 54981b2f7..43907b767 100644 --- a/LibGit2Sharp/RepositoryExtensions.cs +++ b/LibGit2Sharp/RepositoryExtensions.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using LibGit2Sharp.Core; -using LibGit2Sharp.Handlers; namespace LibGit2Sharp { @@ -213,24 +212,6 @@ public static Commit Commit(this IRepository repository, string message, CommitO return repository.Commit(message, author, options); } - /// - /// Stores the content of the as a new into the repository. - /// The tip of the will be used as the parent of this new Commit. - /// Once the commit is created, the will move forward to point at it. - /// Both the Author and Committer will be guessed from the Git configuration. An exception will be raised if no configuration is reachable. - /// - /// The being worked with. - /// The description of why a change was made to the repository. - /// True to amend the current pointed at by , false otherwise. - /// The generated . - [Obsolete("This method will be removed in the next release. Please use a Commit overload that accepts a CommitOptions instead.")] - public static Commit Commit(this IRepository repository, string message, bool amendPreviousCommit) - { - Signature author = repository.Config.BuildSignature(DateTimeOffset.Now, true); - - return repository.Commit(message, author, new CommitOptions { AmendPreviousCommit = amendPreviousCommit }); - } - /// /// Stores the content of the as a new into the repository. /// The tip of the will be used as the parent of this new Commit. @@ -249,23 +230,6 @@ public static Commit Commit(this IRepository repository, string message, Signatu return repository.Commit(message, author, committer, options); } - /// - /// Stores the content of the as a new into the repository. - /// The tip of the will be used as the parent of this new Commit. - /// Once the commit is created, the will move forward to point at it. - /// The Committer will be guessed from the Git configuration. An exception will be raised if no configuration is reachable. - /// - /// The being worked with. - /// The of who made the change. - /// The description of why a change was made to the repository. - /// True to amend the current pointed at by , false otherwise. - /// The generated . - [Obsolete("This method will be removed in the next release. Please use a Commit overload that accepts a CommitOptions instead.")] - public static Commit Commit(this IRepository repository, string message, Signature author, bool amendPreviousCommit) - { - return repository.Commit(message, author, new CommitOptions { AmendPreviousCommit = amendPreviousCommit }); - } - /// /// Fetch from the specified remote. /// @@ -290,7 +254,8 @@ public static void Fetch(this IRepository repository, string remoteName, FetchOp /// The that was checked out. public static Branch Checkout(this IRepository repository, string commitOrBranchSpec, Signature signature = null) { - return repository.Checkout(commitOrBranchSpec, CheckoutModifiers.None, null, null, signature); + CheckoutOptions options = new CheckoutOptions(); + return repository.Checkout(commitOrBranchSpec, options, signature); } /// @@ -306,7 +271,8 @@ public static Branch Checkout(this IRepository repository, string commitOrBranch /// The that was checked out. public static Branch Checkout(this IRepository repository, Branch branch, Signature signature = null) { - return repository.Checkout(branch, CheckoutModifiers.None, null, null, signature); + CheckoutOptions options = new CheckoutOptions(); + return repository.Checkout(branch, options, signature); } /// @@ -321,7 +287,8 @@ public static Branch Checkout(this IRepository repository, Branch branch, Signat /// The that was checked out. public static Branch Checkout(this IRepository repository, Commit commit, Signature signature = null) { - return repository.Checkout(commit, CheckoutModifiers.None, null, null, signature); + CheckoutOptions options = new CheckoutOptions(); + return repository.Checkout(commit, options, signature); } internal static string BuildRelativePathFrom(this Repository repo, string path) @@ -449,6 +416,7 @@ internal static IEnumerable Committishes(this Repository repo, object { throw new LibGit2SharpException(string.Format(CultureInfo.InvariantCulture, "Unexpected kind of identifier '{0}'.", identifier)); } + yield return null; } diff --git a/LibGit2Sharp/RepositoryStatus.cs b/LibGit2Sharp/RepositoryStatus.cs index 92af33244..235f514d7 100644 --- a/LibGit2Sharp/RepositoryStatus.cs +++ b/LibGit2Sharp/RepositoryStatus.cs @@ -4,9 +4,7 @@ using System.Diagnostics; using System.Globalization; using System.Linq; -using System.Runtime.InteropServices; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp @@ -119,6 +117,12 @@ private static GitStatusOptions CreateStatusOptions(StatusOptions options) GitStatusOptionFlags.ExcludeSubmodules; } + if (options.RecurseIgnoredDirs) + { + coreOptions.Flags |= + GitStatusOptionFlags.RecurseIgnoredDirs; + } + return coreOptions; } diff --git a/LibGit2Sharp/RevertOptions.cs b/LibGit2Sharp/RevertOptions.cs new file mode 100644 index 000000000..49a350e58 --- /dev/null +++ b/LibGit2Sharp/RevertOptions.cs @@ -0,0 +1,115 @@ +using LibGit2Sharp.Core; +using LibGit2Sharp.Handlers; + +namespace LibGit2Sharp +{ + /// + /// Options controlling Revert behavior. + /// + public sealed class RevertOptions : IConvertableToGitCheckoutOpts + { + /// + /// Initializes a new instance of the class. + /// By default the revert will be committed if there are no conflicts. + /// + public RevertOptions() + { + CommitOnSuccess = true; + + FindRenames = true; + + // TODO: libgit2 should provide reasonable defaults for these + // values, but it currently does not. + RenameThreshold = 50; + TargetLimit = 200; + } + + /// + /// The Flags specifying what conditions are + /// reported through the OnCheckoutNotify delegate. + /// + public CheckoutNotifyFlags CheckoutNotifyFlags { get; set; } + + /// + /// Delegate that checkout progress will be reported through. + /// + public CheckoutProgressHandler OnCheckoutProgress { get; set; } + + /// + /// Delegate that checkout will notify callers of + /// certain conditions. The conditions that are reported is + /// controlled with the CheckoutNotifyFlags property. + /// + public CheckoutNotifyHandler OnCheckoutNotify { get; set; } + + /// + /// Commit the revert if the revert is successful. + /// + public bool CommitOnSuccess { get; set; } + + /// + /// When reverting a merge commit, the parent number to consider as + /// mainline, starting from offset 1. + /// + /// As a merge commit has multiple parents, reverting a merge commit + /// will reverse all the changes brought in by the merge except for + /// one parent's line of commits. The parent to preserve is called the + /// mainline, and must be specified by its number (i.e. offset). + /// + /// + public int Mainline { get; set; } + + /// + /// How to handle conflicts encountered during a merge. + /// + public MergeFileFavor MergeFileFavor { get; set; } + + /// + /// How Checkout should handle writing out conflicting index entries. + /// + public CheckoutFileConflictStrategy FileConflictStrategy { get; set; } + + /// + /// Find renames. Default is true. + /// + public bool FindRenames { get; set; } + + /// + /// Similarity to consider a file renamed (default 50). If + /// `FindRenames` is enabled, added files will be compared + /// with deleted files to determine their similarity. Files that are + /// more similar than the rename threshold (percentage-wise) will be + /// treated as a rename. + /// + public int RenameThreshold; + + /// + /// Maximum similarity sources to examine for renames (default 200). + /// If the number of rename candidates (add / delete pairs) is greater + /// than this value, inexact rename detection is aborted. + /// + /// This setting overrides the `merge.renameLimit` configuration value. + /// + public int TargetLimit; + + #region IConvertableToGitCheckoutOpts + + CheckoutCallbacks IConvertableToGitCheckoutOpts.GenerateCallbacks() + { + return CheckoutCallbacks.From(OnCheckoutProgress, OnCheckoutNotify); + } + + CheckoutStrategy IConvertableToGitCheckoutOpts.CheckoutStrategy + { + get + { + return CheckoutStrategy.GIT_CHECKOUT_SAFE | + CheckoutStrategy.GIT_CHECKOUT_ALLOW_CONFLICTS | + GitCheckoutOptsWrapper.CheckoutStrategyFromFileConflictStrategy(FileConflictStrategy); + } + } + + #endregion IConvertableToGitCheckoutOpts + + } +} diff --git a/LibGit2Sharp/RevertResult.cs b/LibGit2Sharp/RevertResult.cs new file mode 100644 index 000000000..bb8700c79 --- /dev/null +++ b/LibGit2Sharp/RevertResult.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace LibGit2Sharp +{ + /// + /// Class to report the result of a revert. + /// + public class RevertResult + { + /// + /// Needed for mocking purposes. + /// + protected RevertResult() + { } + + internal RevertResult(RevertStatus status, Commit commit = null) + { + Commit = commit; + Status = status; + } + + /// + /// The resulting commit of the revert. + /// + /// This will return null if the revert was not committed. + /// This can happen if: + /// 1) The revert resulted in conflicts. + /// 2) The option to not commit on success is set. + /// + /// + public virtual Commit Commit { get; private set; } + + /// + /// The status of the revert. + /// + public virtual RevertStatus Status { get; private set; } + } + + /// + /// The status of what happened as a result of a revert. + /// + public enum RevertStatus + { + /// + /// The commit was successfully reverted. + /// + Reverted, + + /// + /// The revert resulted in conflicts. + /// + Conflicts + } +} diff --git a/LibGit2Sharp/Signature.cs b/LibGit2Sharp/Signature.cs index bc9dc7786..74be26448 100644 --- a/LibGit2Sharp/Signature.cs +++ b/LibGit2Sharp/Signature.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.InteropServices; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; @@ -130,7 +131,7 @@ public override int GetHashCode() /// The and of the current . public override string ToString() { - return string.Format("{0} <{1}>", Name, Email); + return string.Format(CultureInfo.InvariantCulture, "{0} <{1}>", Name, Email); } } } diff --git a/LibGit2Sharp/Stash.cs b/LibGit2Sharp/Stash.cs index b8ba98a0d..07bd6559c 100644 --- a/LibGit2Sharp/Stash.cs +++ b/LibGit2Sharp/Stash.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Globalization; +using System.Linq; namespace LibGit2Sharp { @@ -15,7 +16,7 @@ protected Stash() { } internal Stash(Repository repo, ObjectId targetId, int index) - : base(repo, new DirectReference(string.Format("stash@{{{0}}}", index), repo, targetId), r => r.CanonicalName) + : base(repo, new DirectReference(string.Format(CultureInfo.InvariantCulture, "stash@{{{0}}}", index), repo, targetId), r => r.CanonicalName) { } /// diff --git a/LibGit2Sharp/StashCollection.cs b/LibGit2Sharp/StashCollection.cs index e0bd7d24a..07fc33797 100644 --- a/LibGit2Sharp/StashCollection.cs +++ b/LibGit2Sharp/StashCollection.cs @@ -69,7 +69,8 @@ public virtual Stash this[int index] throw new ArgumentOutOfRangeException("index", "The passed index must be a positive integer."); } - GitObject stashCommit = repo.Lookup(string.Format("stash@{{{0}}}", index), GitObjectType.Commit, LookUpOptions.None); + GitObject stashCommit = repo.Lookup( + string.Format(CultureInfo.InvariantCulture, "stash@{{{0}}}", index), GitObjectType.Commit, LookUpOptions.None); return stashCommit == null ? null : new Stash(repo, stashCommit.Id, index); } diff --git a/LibGit2Sharp/StatusEntry.cs b/LibGit2Sharp/StatusEntry.cs index a049d3164..ecf56dbee 100644 --- a/LibGit2Sharp/StatusEntry.cs +++ b/LibGit2Sharp/StatusEntry.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Globalization; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -125,10 +126,10 @@ private string DebuggerDisplay string oldFilePath = ((State & FileStatus.RenamedInIndex) == FileStatus.RenamedInIndex) ? HeadToIndexRenameDetails.OldFilePath : IndexToWorkDirRenameDetails.OldFilePath; - return string.Format("{0}: {1} -> {2}", State, oldFilePath, FilePath); + return string.Format(CultureInfo.InvariantCulture, "{0}: {1} -> {2}", State, oldFilePath, FilePath); } - return string.Format("{0}: {1}", State, FilePath); + return string.Format(CultureInfo.InvariantCulture, "{0}: {1}", State, FilePath); } } } diff --git a/LibGit2Sharp/StatusOptions.cs b/LibGit2Sharp/StatusOptions.cs index 13963711a..9c7528017 100644 --- a/LibGit2Sharp/StatusOptions.cs +++ b/LibGit2Sharp/StatusOptions.cs @@ -61,5 +61,10 @@ public StatusOptions() /// Exclude submodules from being scanned for status /// public bool ExcludeSubmodules { get; set; } + + /// + /// Recurse into ignored directories + /// + public bool RecurseIgnoredDirs { get; set; } } } diff --git a/LibGit2Sharp/TarArchiver.cs b/LibGit2Sharp/TarArchiver.cs index f6fe75203..0710734fb 100644 --- a/LibGit2Sharp/TarArchiver.cs +++ b/LibGit2Sharp/TarArchiver.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.IO; using System.Text; using LibGit2Sharp.Core; @@ -28,9 +29,10 @@ public override void BeforeArchiving(Tree tree, ObjectId oid, DateTimeOffset mod } // Store the sha in the pax_global_header - using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(string.Format("52 comment={0}\n", oid.Sha)))) + using (var stream = new MemoryStream(Encoding.ASCII.GetBytes( + string.Format(CultureInfo.InvariantCulture, "52 comment={0}\n", oid.Sha)))) { - writer.Write("pax_global_header", stream, modificationTime, "666".OctalToInt32(), + writer.Write("pax_global_header", stream, modificationTime, "666".OctalToInt32(), "0", "0", 'g', "root", "root", "0", "0", oid.Sha, false); } } @@ -41,7 +43,7 @@ protected override void AddTreeEntry(string path, TreeEntry entry, DateTimeOffse { case Mode.GitLink: case Mode.Directory: - writer.Write(path + "/", null, modificationTime, "775".OctalToInt32(), + writer.Write(path + "/", null, modificationTime, "775".OctalToInt32(), "0", "0", '5', "root", "root", "0", "0", entry.TargetId.Sha, false); break; case Mode.ExecutableFile: @@ -55,12 +57,13 @@ protected override void AddTreeEntry(string path, TreeEntry entry, DateTimeOffse case Mode.SymbolicLink: using (Stream contentStream = ((Blob)entry.Target).GetContentStream(new FilteringOptions(path))) { - writer.Write(path, contentStream, modificationTime, "777".OctalToInt32(), + writer.Write(path, contentStream, modificationTime, "777".OctalToInt32(), "0", "0", '2', "root", "root", "0", "0", entry.TargetId.Sha, true); } break; default: - throw new InvalidOperationException(string.Format("Unsupported file mode: {0} (sha1: {1}).", entry.Mode, entry.TargetId.Sha)); + throw new InvalidOperationException( + string.Format(CultureInfo.InvariantCulture, "Unsupported file mode: {0} (sha1: {1}).", entry.Mode, entry.TargetId.Sha)); } } diff --git a/LibGit2Sharp/TreeDefinition.cs b/LibGit2Sharp/TreeDefinition.cs index 63bbb0caf..bedd07851 100644 --- a/LibGit2Sharp/TreeDefinition.cs +++ b/LibGit2Sharp/TreeDefinition.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp diff --git a/LibGit2Sharp/TreeEntry.cs b/LibGit2Sharp/TreeEntry.cs index ffdf22d3d..54dd95998 100644 --- a/LibGit2Sharp/TreeEntry.cs +++ b/LibGit2Sharp/TreeEntry.cs @@ -2,7 +2,6 @@ using System.Globalization; using System.Runtime.InteropServices; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp { diff --git a/LibGit2Sharp/TreeEntryDefinition.cs b/LibGit2Sharp/TreeEntryDefinition.cs index e97066824..c0eb979d3 100644 --- a/LibGit2Sharp/TreeEntryDefinition.cs +++ b/LibGit2Sharp/TreeEntryDefinition.cs @@ -1,6 +1,5 @@ using System; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp { diff --git a/LibGit2Sharp/TreeEntryTargetType.cs b/LibGit2Sharp/TreeEntryTargetType.cs index 0dfca339f..a4e54d73a 100644 --- a/LibGit2Sharp/TreeEntryTargetType.cs +++ b/LibGit2Sharp/TreeEntryTargetType.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -37,7 +38,8 @@ public static GitObjectType ToGitObjectType(this TreeEntryTargetType type) return GitObjectType.Blob; default: - throw new InvalidOperationException(string.Format("Cannot map {0} to a GitObjectType.", type)); + throw new InvalidOperationException( + string.Format(CultureInfo.InvariantCulture, "Cannot map {0} to a GitObjectType.", type)); } } } diff --git a/LibGit2Sharp/UnmatchedPathException.cs b/LibGit2Sharp/UnmatchedPathException.cs index 50d8cd70b..19f061efd 100644 --- a/LibGit2Sharp/UnmatchedPathException.cs +++ b/LibGit2Sharp/UnmatchedPathException.cs @@ -45,10 +45,5 @@ protected UnmatchedPathException(SerializationInfo info, StreamingContext contex : base(info, context) { } - - internal UnmatchedPathException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) - { - } } } diff --git a/LibGit2Sharp/libgit2_hash.txt b/LibGit2Sharp/libgit2_hash.txt index 17a851d88..682059084 100644 --- a/LibGit2Sharp/libgit2_hash.txt +++ b/LibGit2Sharp/libgit2_hash.txt @@ -1 +1 @@ -06d772d8d45e3e2830614a62a51910547afb6666 +2f6f6ebc9937220302875de96ce129919296670a diff --git a/UpdateLibgit2ToSha.ps1 b/UpdateLibgit2ToSha.ps1 index 2bafd6aca..e86e2f74d 100644 --- a/UpdateLibgit2ToSha.ps1 +++ b/UpdateLibgit2ToSha.ps1 @@ -4,7 +4,7 @@ .PARAMETER sha Desired libgit2 version. This is run through `git rev-parse`, so branch names are okay too. .PARAMETER vs - Version of Visual Studio project files to generate. Cmake supports "10" (default) and "11". + Version of Visual Studio project files to generate. Cmake supports "10" (default), "11" and "12". .PARAMETER libgit2Name The base name (i.e without the file extension) of the libgit2 DLL to generate. Default is to use git2-$suffix, where $suffix is the first 7 characters of the SHA1 of the corresponding libgi2 commit as the suffix. .PARAMETER test diff --git a/build.libgit2sharp.cmd b/build.libgit2sharp.cmd index f1d19c36b..54ecc1a26 100644 --- a/build.libgit2sharp.cmd +++ b/build.libgit2sharp.cmd @@ -5,7 +5,7 @@ SET FrameworkVersion=v4.0.30319 SET FrameworkDir=%SystemRoot%\Microsoft.NET\Framework SET CommitSha=%~1 -"%FrameworkDir%\%FrameworkVersion%\msbuild.exe" "%BASEDIR%CI-build.msbuild" /property:CommitSha=%CommitSha% +"%FrameworkDir%\%FrameworkVersion%\msbuild.exe" "%BASEDIR%CI\build.msbuild" /property:CommitSha=%CommitSha% ENDLOCAL diff --git a/build.libgit2sharp.sh b/build.libgit2sharp.sh index a948e0e5e..1a97e214a 100755 --- a/build.libgit2sharp.sh +++ b/build.libgit2sharp.sh @@ -26,6 +26,6 @@ export MONO_OPTIONS=--debug echo $DYLD_LIBRARY_PATH echo $LD_LIBRARY_PATH -xbuild CI-build.msbuild /t:Deploy +xbuild CI/build.msbuild /t:Deploy exit $? diff --git a/build.libgit2sharp.x64.cmd b/build.libgit2sharp.x64.cmd index 8a4909aef..41702104b 100644 --- a/build.libgit2sharp.x64.cmd +++ b/build.libgit2sharp.x64.cmd @@ -5,7 +5,7 @@ SET FrameworkVersion=v4.0.30319 SET FrameworkDir=%SystemRoot%\Microsoft.NET\Framework64 SET CommitSha=%~1 -"%FrameworkDir%\%FrameworkVersion%\msbuild.exe" "%BASEDIR%CI-build.msbuild" /property:CommitSha=%CommitSha% +"%FrameworkDir%\%FrameworkVersion%\msbuild.exe" "%BASEDIR%CI\build.msbuild" /property:CommitSha=%CommitSha% ENDLOCAL diff --git a/libgit2 b/libgit2 index 06d772d8d..2f6f6ebc9 160000 --- a/libgit2 +++ b/libgit2 @@ -1 +1 @@ -Subproject commit 06d772d8d45e3e2830614a62a51910547afb6666 +Subproject commit 2f6f6ebc9937220302875de96ce129919296670a diff --git a/nuget.package/LibGit2Sharp.nuspec b/nuget.package/LibGit2Sharp.nuspec index 3bacd546a..99c326536 100644 --- a/nuget.package/LibGit2Sharp.nuspec +++ b/nuget.package/LibGit2Sharp.nuspec @@ -17,8 +17,8 @@ - - + + diff --git a/nuget.package/Tools/GetLibGit2SharpPostBuildCmd.ps1 b/nuget.package/Tools/GetLibGit2SharpPostBuildCmd.ps1 index 225ad5338..e1847e610 100644 --- a/nuget.package/Tools/GetLibGit2SharpPostBuildCmd.ps1 +++ b/nuget.package/Tools/GetLibGit2SharpPostBuildCmd.ps1 @@ -1,7 +1,7 @@ $solutionDir = [System.IO.Path]::GetDirectoryName($dte.Solution.FullName) + "\" $path = $installPath.Replace($solutionDir, "`$(SolutionDir)") -$NativeAssembliesDir = Join-Path $path "lib\net35\NativeBinaries" +$NativeAssembliesDir = Join-Path $path "lib\net40\NativeBinaries" $x86 = $(Join-Path $NativeAssembliesDir "x86\*.*") $x64 = $(Join-Path $NativeAssembliesDir "amd64\*.*")