From 0e1aed5e361a47db9273fed7fd09f2f1f680cbcf Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 15 Feb 2019 09:21:39 +0000 Subject: [PATCH 001/179] Prepare for v0.27 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index b0068cfdf..b0cb8c411 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.26.0", + "version": "0.27.0-preview.{height}", "publicReleaseRefSpec": [ "^refs/heads/master$", // we release out of master "^refs/heads/maint/v\\d+(?:\\.\\d+)?$" // and maint/vNN branches From edbf8019c4d6be74cd0f9e93a2a71c8ad7136248 Mon Sep 17 00:00:00 2001 From: v-wilock <46005579+v-wilock@users.noreply.github.com> Date: Wed, 20 Feb 2019 08:26:46 -0800 Subject: [PATCH 002/179] Fix typos in 'Optimizing unit testing' "Insure" relates to having insurance. "ensure" means "to make sure of" "One-thousand" shouldn't be hyphenated. It should only be hyphenated in the case of a compound modifier on the word "thousand" as in "forty-five thousand". --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 904f1ecad..c67e6ec8e 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ More thorough information available in the [wiki][wiki]. [wiki]: https://github.com/libgit2/libgit2sharp/wiki ## Optimizing unit testing -LibGit2Sharp strives to have comprehensive and robust unit test suite to insure the quality of the software and to assist new contributors and users who can use the tests as sample to jump start development. There are over one-thousand unit-tests for LibGit2Sharp, this number will only grow as functionality is added. +LibGit2Sharp strives to have comprehensive and robust unit test suite to ensure the quality of the software and to assist new contributors and users who can use the tests as sample to jump start development. There are over one thousand unit-tests for LibGit2Sharp, this number will only grow as functionality is added. You can do a few things to optimize running unit-tests on Windows: From 07ea71774f9051515cb2868e11b152f32144298f Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 12:20:47 -0400 Subject: [PATCH 003/179] Update LibGit2Sharp.NativeBinaries to 2.0.278 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 4c35a6cea..4dc5085e0 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From 9a67257a8879a5f2de00e63671d895f632722634 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 13:09:13 -0400 Subject: [PATCH 004/179] Update Travis .NET Core SDK version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 58886b706..d5947ec32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: csharp dist: trusty -dotnet: 2.1.401 +dotnet: 2.1.506 mono: none osx_image: xcode8.3 From 9c04ac4938c623275d62b2b15beed5472959dceb Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 13:13:24 -0400 Subject: [PATCH 005/179] Update Travis to xenial to fix linux build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d5947ec32..573c44408 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ # see travis-ci.org for details language: csharp -dist: trusty +dist: xenial dotnet: 2.1.506 mono: none osx_image: xcode8.3 From 40a75e4be373957540643f46c21fb76f1febde74 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 19:41:19 -0400 Subject: [PATCH 006/179] Update testing packages --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 13 +++++++------ appveyor.yml | 4 ++-- buildandtest.cmd | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index c31cb9476..4b5c2a762 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -11,12 +11,13 @@ - - - - - - + + + + + + + diff --git a/appveyor.yml b/appveyor.yml index 6d5eebafa..d0cbdbe90 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -90,7 +90,7 @@ test_script: { .\packages\OpenCover\tools\OpenCover.Console.exe ` -register:user ` - "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.0\tools\net46\$runner""" ` + "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\$runner""" ` "-targetargs:""$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net46\LibGit2Sharp.Tests.dll"" -noshadow" ` "-filter:+[LibGit2Sharp]* -[LibGit2Sharp.Tests]*" ` -hideskipped:All ` @@ -98,7 +98,7 @@ test_script: } ElseIf ($Env:SHOULD_RUN_COVERITY_ANALYSIS -eq $False) { - & "$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.0\tools\net46\$runner" ` + & "$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\$runner" ` "$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net46\LibGit2Sharp.Tests.dll" -noshadow } } diff --git a/buildandtest.cmd b/buildandtest.cmd index 3bc1d6656..6b4b37d52 100644 --- a/buildandtest.cmd +++ b/buildandtest.cmd @@ -31,7 +31,7 @@ dotnet build "%~dp0\" /v:minimal /nologo /property:ExtraDefine="%EXTRADEFINE%" @IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% :: Run tests on Desktop and CoreCLR -"%userprofile%\.nuget\packages\xunit.runner.console\2.4.0\tools\net452\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net46\LibGit2Sharp.Tests.dll" -noshadow +"%userprofile%\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net46\LibGit2Sharp.Tests.dll" -noshadow @IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% dotnet test "%~dp0LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj" -f netcoreapp2.0 --no-restore --no-build @IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% From 5c62df8dba76a93b59ef90973d269493f66df791 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 20:00:06 -0400 Subject: [PATCH 007/179] Move to netcoreapp2.1 for tests --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 ++-- appveyor.yml | 2 +- buildandtest.cmd | 2 +- buildandtest.sh | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 4b5c2a762..7605eb345 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net46;netcoreapp2.0 + net46;netcoreapp2.1 @@ -44,4 +44,4 @@ - + \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index d0cbdbe90..3db8b2b8a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -103,7 +103,7 @@ test_script: } } -- dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.0 --no-restore --no-build +- dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.1 --no-restore --no-build after_test: - ps: | diff --git a/buildandtest.cmd b/buildandtest.cmd index 6b4b37d52..612161b87 100644 --- a/buildandtest.cmd +++ b/buildandtest.cmd @@ -33,7 +33,7 @@ dotnet build "%~dp0\" /v:minimal /nologo /property:ExtraDefine="%EXTRADEFINE%" :: Run tests on Desktop and CoreCLR "%userprofile%\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net46\LibGit2Sharp.Tests.dll" -noshadow @IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% -dotnet test "%~dp0LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj" -f netcoreapp2.0 --no-restore --no-build +dotnet test "%~dp0LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj" -f netcoreapp2.1 --no-restore --no-build @IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% EXIT /B %ERRORLEVEL% diff --git a/buildandtest.sh b/buildandtest.sh index a5501a042..24994cdae 100755 --- a/buildandtest.sh +++ b/buildandtest.sh @@ -15,7 +15,7 @@ export Configuration=release # On linux we don't pack because we can't build for net40. # We just build for CoreCLR and run tests for it. dotnet restore -dotnet build LibGit2Sharp.Tests -f netcoreapp2.0 -property:ExtraDefine="$EXTRADEFINE" -fl -flp:verbosity=detailed -dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.0 --no-restore --no-build +dotnet build LibGit2Sharp.Tests -f netcoreapp2.1 -property:ExtraDefine="$EXTRADEFINE" -fl -flp:verbosity=detailed +dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.1 --no-restore --no-build exit $? From de2de6f2555d61ae3fae31035944422b047809a8 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 20:17:49 -0400 Subject: [PATCH 008/179] Clean up project files --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 6 ++---- LibGit2Sharp/LibGit2Sharp.csproj | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 7605eb345..a0703f6ff 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -22,13 +22,11 @@ - + - - PreserveNewest - + diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 4dc5085e0..7a6406cd5 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -18,14 +18,12 @@ - - TextTemplatingFileGenerator - Objects.cs - - + + + From 3ad4565dd79e80f15788ac177ed5b7892eff6385 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 20:50:32 -0400 Subject: [PATCH 009/179] Disable shadow copying so all tests pass in VS runner --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 +--- LibGit2Sharp.Tests/xunit.runner.json | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 LibGit2Sharp.Tests/xunit.runner.json diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index a0703f6ff..3503801c9 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -23,10 +23,8 @@ - - - + diff --git a/LibGit2Sharp.Tests/xunit.runner.json b/LibGit2Sharp.Tests/xunit.runner.json new file mode 100644 index 000000000..e54567a36 --- /dev/null +++ b/LibGit2Sharp.Tests/xunit.runner.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://xunit.github.io/schema/current/xunit.runner.schema.json", + "shadowCopy": false +} From f5fa5536dddbbe125dbf297f9ea32e1fbeff7d74 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 20:51:29 -0400 Subject: [PATCH 010/179] Remove targets file since all platforms can sign now --- Directory.Build.targets | 7 ------- LibGit2Sharp.sln | 5 ++--- 2 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 Directory.Build.targets diff --git a/Directory.Build.targets b/Directory.Build.targets deleted file mode 100644 index 080355c7d..000000000 --- a/Directory.Build.targets +++ /dev/null @@ -1,7 +0,0 @@ - - - - true - - - diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index 43b82cf6c..a81b0ce37 100644 --- a/LibGit2Sharp.sln +++ b/LibGit2Sharp.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27009.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28803.202 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp", "LibGit2Sharp\LibGit2Sharp.csproj", "{EE6ED99F-CB12-4683-B055-D28FC7357A34}" EndProject @@ -11,7 +11,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .gitignore = .gitignore Targets\CodeGenerator.targets = Targets\CodeGenerator.targets Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets Targets\GenerateNativeDllName.targets = Targets\GenerateNativeDllName.targets nuget.config = nuget.config version.json = version.json From 97bcd0b92bbcf71176f13088e6f508b99ca6cbd3 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 21:00:42 -0400 Subject: [PATCH 011/179] Update Nerdbank.GitVersioning to 2.3.138 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 7a6406cd5..3982172fc 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From 69bea2679563f834b5fce86de1f488d28a7acecf Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 20 Apr 2019 21:36:59 -0400 Subject: [PATCH 012/179] Update version test to account for GitVersioning change --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 8 ++++---- LibGit2Sharp/Version.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 381d13d65..55260a6f5 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -22,9 +22,9 @@ public void CanGetMinimumCompiledInFeatures() public void CanRetrieveValidVersionString() { // Version string format is: - // Major.Minor.Patch[-previewTag]+g{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) + // Major.Minor.Patch[-previewTag]+{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) // Example output: - // "0.25.0-preview.52+g871d13a67f.libgit2-15e1193 (x86 - Threads, Https)" + // "0.25.0-preview.52+871d13a67f.libgit2-15e1193 (x86 - Threads, Https)" string versionInfo = GlobalSettings.Version.ToString(); @@ -33,14 +33,14 @@ public void CanRetrieveValidVersionString() // git2SharpHash: '871d13a67f' LibGit2Sharp hash. // arch: 'x86' or 'x64' libgit2 target. // git2Features: 'Threads, Ssh' libgit2 features compiled with. - string regex = @"^(?\d+\.\d+\.\d+(-[\w\-\.]+)?\+(g(?[a-f0-9]{10})\.)?libgit2-[a-f0-9]{7}) \((?\w+) - (?(?:\w*(?:, )*\w+)*)\)$"; + string regex = @"^(?\d+\.\d+\.\d+(-[\w\-\.]+)?\+((?[a-f0-9]{10})\.)?libgit2-[a-f0-9]{7}) \((?\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[-previewTag]+g{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features). " + + "Major.Minor.Patch[-previewTag]+{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features). " + "But found \"" + versionInfo + "\" instead."); } diff --git a/LibGit2Sharp/Version.cs b/LibGit2Sharp/Version.cs index 747529e84..3795382a3 100644 --- a/LibGit2Sharp/Version.cs +++ b/LibGit2Sharp/Version.cs @@ -55,7 +55,7 @@ private string RetrieveAbbrevShaFrom(string sha) /// /// /// The format of the version number is as follows: - /// Major.Minor.Patch[-previewTag]+g{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) + /// Major.Minor.Patch[-previewTag]+{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) /// /// public override string ToString() From 7546cf511538bd030917f2422d29e7abfea96a22 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 13 Aug 2019 20:10:54 +0100 Subject: [PATCH 013/179] Update libgit2 to v0.28.3 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 3982172fc..cf51b4efc 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -27,7 +27,7 @@ - + From 94b95dd7759255707ab8c3fe45f99d8a0312140f Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Mon, 9 Sep 2019 11:22:14 +0200 Subject: [PATCH 014/179] Linux: support broader range of distros/architectures by trying to load packed native libraries. LibGit2Sharp includes a number of native libraries that are built on different OSes. These native libraries have a dependency on OpenSSL and the system c-library. On x64, in case the Linux flavor is not known, a fallback is performed to the 'linux-x64' native library. This library is built with a dependency on OpenSSL 1.0. OpenSSL 1.0 is deprecated by OpenSSL 1.1, so on more recent version of Linux, the 'linux-x64' library fails to load. On arm64, native libraries are currently included for debian.* (OpenSSL 1.1) and ubuntu.18.04 (OpenSSL 1.0). Loading on other distros will fail. In both cases LibGit2Sharp is probably including a library that works, but the default resolution logic is not able to find it. By using the 'NativeLibrary' class (.NET Core 3.0) we can extend the resolution logic, and try to load the other native libraries that are packed with LibGit2Sharp. --- LibGit2Sharp/Core/NativeMethods.cs | 135 ++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 11 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index aa82516a4..9aae5980a 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; @@ -29,25 +30,30 @@ static NativeMethods() { if (Platform.IsRunningOnNetFramework() || Platform.IsRunningOnNetCore()) { - string nativeLibraryDir = GlobalSettings.GetAndLockNativeLibraryPath(); - if (nativeLibraryDir != null) + // Use .NET Core 3.0+ NativeLibrary when available. + if (!TryUseNativeLibrary()) { - string nativeLibraryPath = Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension()); + // NativeLibrary is not available, fall back. + // Use GlobalSettings.NativeLibraryPath when set. // Try to load the .dll from the path explicitly. // If this call succeeds further DllImports will find the library loaded and not attempt to load it again. // If it fails the next DllImport will load the library from safe directories. + string nativeLibraryPath = GetGlobalSettingsNativeLibraryPath(); + if (nativeLibraryPath != null) + { #if NETFRAMEWORK - if (Platform.OperatingSystem == OperatingSystemType.Windows) + if (Platform.OperatingSystem == OperatingSystemType.Windows) #else - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) #endif - { - LoadWindowsLibrary(nativeLibraryPath); - } - else - { - LoadUnixLibrary(nativeLibraryPath, RTLD_NOW); + { + LoadWindowsLibrary(nativeLibraryPath); + } + else + { + LoadUnixLibrary(nativeLibraryPath, RTLD_NOW); + } } } } @@ -55,6 +61,113 @@ static NativeMethods() InitializeNativeLibrary(); } + private delegate bool TryLoadLibraryByNameDelegate(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle); + private delegate bool TryLoadLibraryByPathDelegate(string libraryPath, out IntPtr handle); + + private static string GetGlobalSettingsNativeLibraryPath() + { + string nativeLibraryDir = GlobalSettings.GetAndLockNativeLibraryPath(); + if (nativeLibraryDir == null) + { + return null; + } + return Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension()); + } + + static TryLoadLibraryByNameDelegate _tryLoadLibraryByName; + static TryLoadLibraryByPathDelegate _tryLoadLibraryByPath; + + static bool TryLoadLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle) + { + if (_tryLoadLibraryByName == null) + { + throw new NotSupportedException(); + } + return _tryLoadLibraryByName(libraryName, assembly, searchPath, out handle); + } + + static bool TryLoadLibrary(string libraryPath, out IntPtr handle) + { + if (_tryLoadLibraryByPath == null) + { + throw new NotSupportedException(); + } + return _tryLoadLibraryByPath(libraryPath, out handle); + } + + private static bool TryUseNativeLibrary() + { + // NativeLibrary is available in .NET Core 3.0+. + // We use reflection to use NativeLibrary so this library can target 'netstandard2.0'. + + Type dllImportResolverType = Type.GetType("System.Runtime.InteropServices.DllImportResolver, System.Runtime.InteropServices", throwOnError: false); + Type nativeLibraryType = Type.GetType("System.Runtime.InteropServices.NativeLibrary, System.Runtime.InteropServices", throwOnError: false); + var tryLoadLibraryByName = (TryLoadLibraryByNameDelegate)nativeLibraryType?.GetMethod("TryLoad", + new Type[] { typeof(string), typeof(Assembly), typeof(DllImportSearchPath?), typeof(IntPtr).MakeByRefType() })?.CreateDelegate(typeof(TryLoadLibraryByNameDelegate)); + var tryLoadLibraryByPath = (TryLoadLibraryByPathDelegate)nativeLibraryType?.GetMethod("TryLoad", + new Type[] { typeof(string), typeof(IntPtr).MakeByRefType() })?.CreateDelegate(typeof(TryLoadLibraryByPathDelegate)); + MethodInfo setDllImportResolver = nativeLibraryType?.GetMethod("SetDllImportResolver", new Type[] { typeof(Assembly), dllImportResolverType}); + + if (dllImportResolverType == null || + nativeLibraryType == null || + tryLoadLibraryByName == null || + tryLoadLibraryByPath == null || + setDllImportResolver == null) + { + return false; + } + + _tryLoadLibraryByPath = tryLoadLibraryByPath; + _tryLoadLibraryByName = tryLoadLibraryByName; + + // NativeMethods.SetDllImportResolver(typeof(NativeMethods).Assembly, ResolveDll); + object resolveDelegate = typeof(NativeMethods).GetMethod(nameof(ResolveDll), BindingFlags.NonPublic | BindingFlags.Static).CreateDelegate(dllImportResolverType); + setDllImportResolver.Invoke(null, new object[] { typeof(NativeMethods).Assembly, resolveDelegate }); + + return true; + } + + private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) + { + IntPtr handle = IntPtr.Zero; + if (libraryName == libgit2) + { + // Use GlobalSettings.NativeLibraryPath when set. + string nativeLibraryPath = GetGlobalSettingsNativeLibraryPath(); + if (nativeLibraryPath != null && + TryLoadLibrary(nativeLibraryPath, out handle)) + { + return handle; + } + + // Use Default DllImport resolution. + if (TryLoadLibrary(libraryName, assembly, searchPath, out handle)) + { + return handle; + } + + // We cary a number of .so files for Linux which are linked against various + // libc/OpenSSL libraries. Try them out. + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + // The libraries are located at 'runtimes//native/lib{libraryName}.so' + // The ends with the processor architecture. e.g. fedora-x64. + + string assemblyDirectory = Path.GetDirectoryName(typeof(NativeMethods).Assembly.Location); + string processorArchitecture = RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(); + foreach (var runtimeFolder in Directory.GetDirectories(Path.Combine(assemblyDirectory, "runtimes"), $"*-{processorArchitecture}")) + { + string libPath = Path.Combine(runtimeFolder, "native", $"lib{libraryName}.so"); + if (TryLoadLibrary(libPath, out handle)) + { + return handle; + } + } + } + } + return handle; + } + public const int RTLD_NOW = 0x002; [DllImport("libdl", EntryPoint = "dlopen")] From cdab62d102d886bc71f36da1f53d6750300f73c5 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Mon, 9 Sep 2019 16:51:29 +0200 Subject: [PATCH 015/179] Fix netfx build --- LibGit2Sharp/Core/NativeMethods.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 9aae5980a..d237832be 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -61,9 +61,6 @@ static NativeMethods() InitializeNativeLibrary(); } - private delegate bool TryLoadLibraryByNameDelegate(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle); - private delegate bool TryLoadLibraryByPathDelegate(string libraryPath, out IntPtr handle); - private static string GetGlobalSettingsNativeLibraryPath() { string nativeLibraryDir = GlobalSettings.GetAndLockNativeLibraryPath(); @@ -74,6 +71,9 @@ private static string GetGlobalSettingsNativeLibraryPath() return Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension()); } + private delegate bool TryLoadLibraryByNameDelegate(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle); + private delegate bool TryLoadLibraryByPathDelegate(string libraryPath, out IntPtr handle); + static TryLoadLibraryByNameDelegate _tryLoadLibraryByName; static TryLoadLibraryByPathDelegate _tryLoadLibraryByPath; @@ -146,13 +146,14 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor return handle; } +#if NETFRAMEWORK +#else // We cary a number of .so files for Linux which are linked against various // libc/OpenSSL libraries. Try them out. if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { // The libraries are located at 'runtimes//native/lib{libraryName}.so' // The ends with the processor architecture. e.g. fedora-x64. - string assemblyDirectory = Path.GetDirectoryName(typeof(NativeMethods).Assembly.Location); string processorArchitecture = RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(); foreach (var runtimeFolder in Directory.GetDirectories(Path.Combine(assemblyDirectory, "runtimes"), $"*-{processorArchitecture}")) @@ -164,6 +165,7 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor } } } +#endif } return handle; } From f560b17b7886a7c07571eab3d5b1084bf4d12971 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Fri, 27 Sep 2019 00:54:55 -0300 Subject: [PATCH 016/179] Add support for adding and clearing multi-valued configuration Implement value adding by exposing the underlying `set_multivar`, which supports only string values in the underlying libgit2, so no other typed overloads are provided at this point. The counterpart for deleting keys exposes the underlying `delete_multivar`. No regex-based overload is exposed for consistency with the existing `Set` overloads which don't expose it either. Also exposed the boolean return value from the `Unset` calls which is already present in the Proxy API. Fixes #1719. Fix --- LibGit2Sharp.Tests/ConfigurationFixture.cs | 113 +++++++++++++++++++++ LibGit2Sharp/Configuration.cs | 75 ++++++++++++-- LibGit2Sharp/Core/NativeMethods.cs | 7 ++ LibGit2Sharp/Core/Proxy.cs | 8 ++ LibGit2Sharp/RemoteUpdater.cs | 4 +- 5 files changed, 199 insertions(+), 8 deletions(-) diff --git a/LibGit2Sharp.Tests/ConfigurationFixture.cs b/LibGit2Sharp.Tests/ConfigurationFixture.cs index 5bb985b68..999aa0336 100644 --- a/LibGit2Sharp.Tests/ConfigurationFixture.cs +++ b/LibGit2Sharp.Tests/ConfigurationFixture.cs @@ -50,6 +50,119 @@ public void CanUnsetAnEntryFromTheGlobalConfiguration() } } + [Fact] + public void CanAddAndReadMultivarFromTheLocalConfiguration() + { + string path = SandboxStandardTestRepo(); + using (var repo = new Repository(path)) + { + Assert.Empty(repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin")); + + repo.Config.Add("unittests.plugin", "value1", ConfigurationLevel.Local); + repo.Config.Add("unittests.plugin", "value2", ConfigurationLevel.Local); + + Assert.Equal(new[] { "value1", "value2" }, repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin" && x.Level == ConfigurationLevel.Local) + .Select(x => x.Value) + .ToArray()); + } + } + + [Fact] + public void CanAddAndReadMultivarFromTheGlobalConfiguration() + { + string path = SandboxBareTestRepo(); + using (var repo = new Repository(path)) + { + Assert.True(repo.Config.HasConfig(ConfigurationLevel.Global)); + Assert.Empty(repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin")); + + repo.Config.Add("unittests.plugin", "value1", ConfigurationLevel.Global); + repo.Config.Add("unittests.plugin", "value2", ConfigurationLevel.Global); + + Assert.Equal(new[] { "value1", "value2" }, repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin") + .Select(x => x.Value) + .ToArray()); + } + } + + [Fact] + public void CanUnsetAllFromTheGlobalConfiguration() + { + string path = SandboxBareTestRepo(); + using (var repo = new Repository(path)) + { + Assert.True(repo.Config.HasConfig(ConfigurationLevel.Global)); + Assert.Empty(repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin") + .Select(x => x.Value) + .ToArray()); + + repo.Config.Add("unittests.plugin", "value1", ConfigurationLevel.Global); + repo.Config.Add("unittests.plugin", "value2", ConfigurationLevel.Global); + + Assert.Equal(2, repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin" && x.Level == ConfigurationLevel.Global) + .Select(x => x.Value) + .Count()); + + repo.Config.UnsetAll("unittests.plugin"); + + Assert.Equal(2, repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin" && x.Level == ConfigurationLevel.Global) + .Select(x => x.Value) + .Count()); + + repo.Config.UnsetAll("unittests.plugin", ConfigurationLevel.Global); + + Assert.Empty(repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin") + .Select(x => x.Value) + .ToArray()); + } + } + + [Fact] + public void CanUnsetAllFromTheLocalConfiguration() + { + string path = SandboxStandardTestRepo(); + using (var repo = new Repository(path)) + { + Assert.True(repo.Config.HasConfig(ConfigurationLevel.Global)); + Assert.Empty(repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin") + .Select(x => x.Value) + .ToArray()); + + repo.Config.Add("unittests.plugin", "value1"); + repo.Config.Add("unittests.plugin", "value2"); + + Assert.Equal(2, repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin" && x.Level == ConfigurationLevel.Local) + .Select(x => x.Value) + .Count()); + + repo.Config.UnsetAll("unittests.plugin"); + + Assert.Empty(repo.Config + .OfType>() + .Where(x => x.Key == "unittests.plugin")); + } + } + [Fact] public void CanReadBooleanValue() { diff --git a/LibGit2Sharp/Configuration.cs b/LibGit2Sharp/Configuration.cs index 9297a5c37..3c8f32d76 100644 --- a/LibGit2Sharp/Configuration.cs +++ b/LibGit2Sharp/Configuration.cs @@ -233,9 +233,9 @@ public void Dispose() /// Unset a configuration variable (key and value) in the local configuration. /// /// The key to unset. - public virtual void Unset(string key) + public virtual bool Unset(string key) { - Unset(key, ConfigurationLevel.Local); + return Unset(key, ConfigurationLevel.Local); } /// @@ -243,23 +243,37 @@ public virtual void Unset(string key) /// /// The key to unset. /// The configuration file which should be considered as the target of this operation - public virtual void Unset(string key, ConfigurationLevel level) + public virtual bool Unset(string key, ConfigurationLevel level) { Ensure.ArgumentNotNullOrEmptyString(key, "key"); using (ConfigurationHandle h = RetrieveConfigurationHandle(level, true, configHandle)) { - Proxy.git_config_delete(h, key); + return Proxy.git_config_delete(h, key); } } - internal void UnsetMultivar(string key, ConfigurationLevel level) + /// + /// Unset a configuration values in a multivar variable (key and value) in the local configuration. + /// + /// The key to unset. + public virtual bool UnsetAll(string key) + { + return UnsetAll(key, ConfigurationLevel.Local); + } + + /// + /// Unset all configuration values in a multivar variable (key and value). + /// + /// The key to unset. + /// The configuration file which should be considered as the target of this operation + public virtual bool UnsetAll(string key, ConfigurationLevel level) { Ensure.ArgumentNotNullOrEmptyString(key, "key"); using (ConfigurationHandle h = RetrieveConfigurationHandle(level, true, configHandle)) { - Proxy.git_config_delete_multivar(h, key); + return Proxy.git_config_delete_multivar(h, key); } } @@ -634,6 +648,55 @@ public virtual void Set(string key, T value, ConfigurationLevel level) } } + /// + /// Adds a configuration value for a multivalue key in the local configuration. Keys are in the form 'section.name'. + /// + /// For example in order to add the value for this in a .git\config file: + /// + /// [test] + /// plugin = first + /// + /// You would call: + /// + /// repo.Config.Add("test.plugin", "first"); + /// + /// + /// The configuration value type + /// The key parts + /// The value + public virtual void Add(string key, string value) + { + Add(key, value, ConfigurationLevel.Local); + } + + /// + /// Adds a configuration value for a multivalue key. Keys are in the form 'section.name'. + /// + /// For example in order to add the value for this in a .git\config file: + /// + /// [test] + /// plugin = first + /// + /// You would call: + /// + /// repo.Config.Add("test.plugin", "first"); + /// + /// + /// The configuration value type + /// The key parts + /// The value + /// The configuration file which should be considered as the target of this operation + public virtual void Add(string key, string value, ConfigurationLevel level) + { + Ensure.ArgumentNotNull(value, "value"); + Ensure.ArgumentNotNullOrEmptyString(key, "key"); + + using (ConfigurationHandle h = RetrieveConfigurationHandle(level, true, configHandle)) + { + Proxy.git_config_add_string(h, key, value); + } + } + /// /// Find configuration entries matching . /// diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index d237832be..7079ecdc4 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -497,6 +497,13 @@ internal static extern unsafe int git_config_delete_multivar( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string regexp); + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] + internal static extern unsafe int git_config_set_multivar( + git_config* cfg, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string regexp, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string value); + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_find_global(GitBuf global_config_path); diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index de31b4a1e..c3a53b95e 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -601,6 +601,14 @@ public static unsafe void git_config_set_string(ConfigurationHandle config, stri Ensure.ZeroResult(res); } + static readonly string non_existing_regex = Guid.NewGuid().ToString(); + + public static unsafe void git_config_add_string(ConfigurationHandle config, string name, string value) + { + int res = NativeMethods.git_config_set_multivar(config, name, non_existing_regex, value); + Ensure.ZeroResult(res); + } + public static unsafe ICollection git_config_foreach( ConfigurationHandle config, Func resultSelector) diff --git a/LibGit2Sharp/RemoteUpdater.cs b/LibGit2Sharp/RemoteUpdater.cs index ec8b08bcd..53fd33a4b 100644 --- a/LibGit2Sharp/RemoteUpdater.cs +++ b/LibGit2Sharp/RemoteUpdater.cs @@ -56,7 +56,7 @@ private IEnumerable GetFetchRefSpecs() private void SetFetchRefSpecs(IEnumerable value) { - repo.Config.UnsetMultivar(string.Format("remote.{0}.fetch", remoteName), ConfigurationLevel.Local); + repo.Config.UnsetAll(string.Format("remote.{0}.fetch", remoteName), ConfigurationLevel.Local); foreach (var url in value) { @@ -74,7 +74,7 @@ private IEnumerable GetPushRefSpecs() private void SetPushRefSpecs(IEnumerable value) { - repo.Config.UnsetMultivar(string.Format("remote.{0}.push", remoteName), ConfigurationLevel.Local); + repo.Config.UnsetAll(string.Format("remote.{0}.push", remoteName), ConfigurationLevel.Local); foreach (var url in value) { From 6a8463e097ec2b76c7935923ed3d4b7c51cdb3f9 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Fri, 27 Sep 2019 22:12:39 -0300 Subject: [PATCH 017/179] Update to latest LTS stable version for .NET Core 2.1 This should fix travis failures in CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 573c44408..cc1e3c35a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: csharp dist: xenial -dotnet: 2.1.506 +dotnet: 2.1.802 mono: none osx_image: xcode8.3 From 4081885645970e440c0495140a72cb810a0255d1 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Wed, 9 Oct 2019 14:44:21 -0300 Subject: [PATCH 018/179] Update LibGit2Sharp/Configuration.cs Co-Authored-By: Brandon Ording --- LibGit2Sharp/Configuration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/Configuration.cs b/LibGit2Sharp/Configuration.cs index 3c8f32d76..cb9bc6815 100644 --- a/LibGit2Sharp/Configuration.cs +++ b/LibGit2Sharp/Configuration.cs @@ -254,7 +254,7 @@ public virtual bool Unset(string key, ConfigurationLevel level) } /// - /// Unset a configuration values in a multivar variable (key and value) in the local configuration. + /// Unset all configuration values in a multivar variable (key and value) in the local configuration. /// /// The key to unset. public virtual bool UnsetAll(string key) From dcd16d8bc4f503206920fbf0e13c291914890edd Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 16 Oct 2019 10:27:29 +0100 Subject: [PATCH 019/179] Update libgit2 to ef5a385 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index cf51b4efc..de205fc56 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -27,7 +27,7 @@ - + From 8b2ed492bdd1e22c2d6c92f83113bf0f4871ea08 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 16 Oct 2019 11:50:41 +0100 Subject: [PATCH 020/179] GitRemoteCallbacks: add url_resolve callback --- LibGit2Sharp/Core/GitRemoteCallbacks.cs | 2 ++ LibGit2Sharp/Core/NativeMethods.cs | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/LibGit2Sharp/Core/GitRemoteCallbacks.cs b/LibGit2Sharp/Core/GitRemoteCallbacks.cs index 4c797b596..54cdb46ed 100644 --- a/LibGit2Sharp/Core/GitRemoteCallbacks.cs +++ b/LibGit2Sharp/Core/GitRemoteCallbacks.cs @@ -34,5 +34,7 @@ internal struct GitRemoteCallbacks internal IntPtr transport; internal IntPtr payload; + + internal NativeMethods.url_resolve_callback resolve_url; } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 7079ecdc4..7bbc08f8d 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -2037,6 +2037,13 @@ internal static extern unsafe int git_cherrypick_commit(out git_index* index, [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void git_transaction_free(IntPtr txn); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int url_resolve_callback( + IntPtr url_resolved, + IntPtr url, + int direction, + IntPtr payload); + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_worktree_free(git_worktree* worktree); From aad6094987777d996bc162b6d591ed64b1c92f23 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 16 Oct 2019 12:00:34 +0100 Subject: [PATCH 021/179] Rebase: include new commit signing callback --- LibGit2Sharp/Core/GitRebaseOptions.cs | 2 ++ LibGit2Sharp/Core/NativeMethods.cs | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/LibGit2Sharp/Core/GitRebaseOptions.cs b/LibGit2Sharp/Core/GitRebaseOptions.cs index 3ae4e0ed1..e1416e803 100644 --- a/LibGit2Sharp/Core/GitRebaseOptions.cs +++ b/LibGit2Sharp/Core/GitRebaseOptions.cs @@ -17,5 +17,7 @@ internal class GitRebaseOptions public GitMergeOpts merge_options = new GitMergeOpts { Version = 1 }; public GitCheckoutOpts checkout_options = new GitCheckoutOpts { version = 1 }; + + public NativeMethods.commit_signing_callback signing_callback; } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 7bbc08f8d..60bd0a915 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -321,6 +321,13 @@ internal static extern unsafe int git_branch_remote_name( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string canonical_branch_name); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int commit_signing_callback( + IntPtr signature, + IntPtr signature_field, + IntPtr commit_content, + IntPtr payload); + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_rebase_init( out git_rebase* rebase, From 64ab9718f772f776bae7a90efa6f6450eead849c Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 16 Oct 2019 12:12:37 +0100 Subject: [PATCH 022/179] Clone: remove obsolete test for pathless URLs URLs without a path are perfectly valid; the path is implicitly `/`. libgit2 was incorrectly rejecting these paths, and LibGit2Sharp was incorrectly testing this bad behavior. Remove this test now that libgit2 has fixed this issue. --- LibGit2Sharp.Tests/CloneFixture.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 976ef9322..09af475fd 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -297,14 +297,6 @@ public void CanInspectCertificateOnClone(string url, string hostname, Type certT Assert.True(checksHappy); } - [Fact] - public void CloningAnUrlWithoutPathThrows() - { - var scd = BuildSelfCleaningDirectory(); - - Assert.Throws(() => Repository.Clone("http://github.com", scd.DirectoryPath)); - } - [Theory] [InlineData("git://github.com/libgit2/TestGitRepository")] public void CloningWithoutWorkdirPathThrows(string url) From 9fc472cd512133819119379cd0ad1ddf6a0bb18a Mon Sep 17 00:00:00 2001 From: Thomas Sowders Date: Wed, 28 Aug 2019 13:15:02 -0400 Subject: [PATCH 023/179] Fixed a typo in annotation of Repository.Describe --- LibGit2Sharp/IRepository.cs | 2 +- LibGit2Sharp/Repository.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/IRepository.cs b/LibGit2Sharp/IRepository.cs index 35eb34f13..fd19f9659 100644 --- a/LibGit2Sharp/IRepository.cs +++ b/LibGit2Sharp/IRepository.cs @@ -265,7 +265,7 @@ public interface IRepository : IDisposable /// /// /// Optionally, the parameter allow to tweak the - /// search strategy (considering lightweith tags, or even branches as reference points) + /// search strategy (considering lightweight tags, or even branches as reference points) /// and the formatting of the returned identifier. /// /// diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index b6399af45..721133cc6 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -1720,7 +1720,7 @@ internal void UpdatePhysicalIndex() /// /// /// Optionally, the parameter allow to tweak the - /// search strategy (considering lightweith tags, or even branches as reference points) + /// search strategy (considering lightweight tags, or even branches as reference points) /// and the formatting of the returned identifier. /// /// From 48fb428ecdbba1175f401139e1ae83ae84f99304 Mon Sep 17 00:00:00 2001 From: Thomas Sowders Date: Tue, 12 Nov 2019 11:37:22 -0500 Subject: [PATCH 024/179] Fixed a tiny typo: 'hanlder' to 'handler' --- LibGit2Sharp/FetchOptionsBase.cs | 2 +- LibGit2Sharp/PushOptions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/FetchOptionsBase.cs b/LibGit2Sharp/FetchOptionsBase.cs index 7b946e9e1..751678cf9 100644 --- a/LibGit2Sharp/FetchOptionsBase.cs +++ b/LibGit2Sharp/FetchOptionsBase.cs @@ -34,7 +34,7 @@ internal FetchOptionsBase() public CredentialsHandler CredentialsProvider { get; set; } /// - /// This hanlder will be called to let the user make a decision on whether to allow + /// This handler will be called to let the user make a decision on whether to allow /// the connection to preoceed based on the certificate presented by the server. /// public CertificateCheckHandler CertificateCheck { get; set; } diff --git a/LibGit2Sharp/PushOptions.cs b/LibGit2Sharp/PushOptions.cs index b5afc3eb2..99c65dd8b 100644 --- a/LibGit2Sharp/PushOptions.cs +++ b/LibGit2Sharp/PushOptions.cs @@ -13,7 +13,7 @@ public sealed class PushOptions public CredentialsHandler CredentialsProvider { get; set; } /// - /// This hanlder will be called to let the user make a decision on whether to allow + /// This handler will be called to let the user make a decision on whether to allow /// the connection to preoceed based on the certificate presented by the server. /// public CertificateCheckHandler CertificateCheck { get; set; } From 79870b03faa6290ff1dc32bfe0f174b922c01547 Mon Sep 17 00:00:00 2001 From: Frederik Carlier Date: Sat, 16 Nov 2019 22:22:31 +0100 Subject: [PATCH 025/179] Check whether the runtimes directory exists before accessing it --- LibGit2Sharp/Core/NativeMethods.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 60bd0a915..219615f11 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -156,12 +156,17 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor // The ends with the processor architecture. e.g. fedora-x64. string assemblyDirectory = Path.GetDirectoryName(typeof(NativeMethods).Assembly.Location); string processorArchitecture = RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(); - foreach (var runtimeFolder in Directory.GetDirectories(Path.Combine(assemblyDirectory, "runtimes"), $"*-{processorArchitecture}")) + string runtimesDirectory = Path.Combine(assemblyDirectory, "runtimes"); + + if (Directory.Exists(runtimesDirectory)) { - string libPath = Path.Combine(runtimeFolder, "native", $"lib{libraryName}.so"); - if (TryLoadLibrary(libPath, out handle)) + foreach (var runtimeFolder in Directory.GetDirectories(runtimesDirectory, $"*-{processorArchitecture}")) { - return handle; + string libPath = Path.Combine(runtimeFolder, "native", $"lib{libraryName}.so"); + if (TryLoadLibrary(libPath, out handle)) + { + return handle; + } } } } From 7754d8711cc0757cbfa316e388de8934f03437f8 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 11 Dec 2019 19:08:50 +1000 Subject: [PATCH 026/179] Update libgit2 to 6777db8 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index de205fc56..bb64842f3 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -27,7 +27,7 @@ - + From 7cdddd267ca4f2a555acf6cfb98b588a72f33d67 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 12 Dec 2019 02:04:12 +0000 Subject: [PATCH 027/179] CommitFixture: use valid tree/commit libgit2 validates objects when signing; update our test to use a valid commit and tree object. --- LibGit2Sharp.Tests/CommitFixture.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp.Tests/CommitFixture.cs b/LibGit2Sharp.Tests/CommitFixture.cs index 5533b7232..f555e7874 100644 --- a/LibGit2Sharp.Tests/CommitFixture.cs +++ b/LibGit2Sharp.Tests/CommitFixture.cs @@ -1058,8 +1058,8 @@ public void CanPrettifyAMessage() } private readonly string signedCommit = - "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n" + - "parent 34734e478d6cf50c27c9d69026d93974d052c454\n" + + "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n" + + "parent 8496071c1b46c854b31185ea97743be6a8774479\n" + "author Ben Burkert 1358451456 -0800\n" + "committer Ben Burkert 1358451456 -0800\n" + "gpgsig -----BEGIN PGP SIGNATURE-----\n" + @@ -1102,8 +1102,8 @@ public void CanPrettifyAMessage() "-----END PGP SIGNATURE-----"; private readonly string signedData = - "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n" + - "parent 34734e478d6cf50c27c9d69026d93974d052c454\n" + + "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n" + + "parent 8496071c1b46c854b31185ea97743be6a8774479\n" + "author Ben Burkert 1358451456 -0800\n" + "committer Ben Burkert 1358451456 -0800\n" + "\n" + @@ -1155,7 +1155,7 @@ public void CanCreateACommitString() [Fact] public void CanCreateASignedCommit() { - string repoPath = InitNewRepository(); + string repoPath = SandboxStandardTestRepo(); using (var repo = new Repository(repoPath)) { var odb = repo.ObjectDatabase; From 22e7c2d2649d9f2f381b648d037ccb3abc5f57bf Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 29 Jan 2020 21:01:55 -0700 Subject: [PATCH 028/179] Fix up compiler warnings --- LibGit2Sharp/Configuration.cs | 2 -- LibGit2Sharp/GlobalSettings.cs | 4 ++++ LibGit2Sharp/Remote.cs | 3 +++ LibGit2Sharp/SmartSubtransport.cs | 7 +++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Configuration.cs b/LibGit2Sharp/Configuration.cs index cb9bc6815..84a8a3e53 100644 --- a/LibGit2Sharp/Configuration.cs +++ b/LibGit2Sharp/Configuration.cs @@ -661,7 +661,6 @@ public virtual void Set(string key, T value, ConfigurationLevel level) /// repo.Config.Add("test.plugin", "first"); /// /// - /// The configuration value type /// The key parts /// The value public virtual void Add(string key, string value) @@ -682,7 +681,6 @@ public virtual void Add(string key, string value) /// repo.Config.Add("test.plugin", "first"); /// /// - /// The configuration value type /// The key parts /// The value /// The configuration file which should be considered as the target of this operation diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index f71646e76..8828cb883 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -351,6 +351,10 @@ public static void SetConfigSearchPaths(ConfigurationLevel level, params string[ Proxy.git_libgit2_opts_set_search_path(level, pathString); } + /// + /// Enable or disable strict hash verification. + /// + /// true to enable strict hash verification; false otherwise. public static void SetStrictHashVerification(bool enabled) { Proxy.git_libgit2_opts_enable_strict_hash_verification(enabled); diff --git a/LibGit2Sharp/Remote.cs b/LibGit2Sharp/Remote.cs index b41fe0634..3bf957866 100644 --- a/LibGit2Sharp/Remote.cs +++ b/LibGit2Sharp/Remote.cs @@ -34,6 +34,9 @@ internal Remote(RemoteHandle handle, Repository repository) repository.RegisterForCleanup(this); } + /// + /// The finalizer for the class. + /// ~Remote() { Dispose(false); diff --git a/LibGit2Sharp/SmartSubtransport.cs b/LibGit2Sharp/SmartSubtransport.cs index c4e7f499a..8944a84c7 100644 --- a/LibGit2Sharp/SmartSubtransport.cs +++ b/LibGit2Sharp/SmartSubtransport.cs @@ -84,6 +84,13 @@ public int CertificateCheck(Certificate cert, bool valid, string hostname) return ret; } + /// + /// Acquires credentials. + /// + /// Receives the credentials if the operation is successful. + /// The username. + /// The credential types allowed. The only supported one is . May be empty but should not be null. + /// 0 if successful; a non-zero error code that came from otherwise. public int AcquireCredentials(out Credentials cred, string user, params Type[] methods) { // Convert the user-provided types to libgit2's flags From f95e5798bd0b343b65f9cc7d69e4ca38130b086b Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 29 Jan 2020 21:04:13 -0700 Subject: [PATCH 029/179] Pin the .NET Core SDK --- .travis.yml | 23 ++++-- CONTRIBUTING.md | 15 +++- appveyor.yml | 4 +- azure-pipelines.yml | 11 ++- global.json | 5 ++ tools/DotNetSdkVersion.ps1 | 2 + tools/Install-DotNetSdk.ps1 | 160 ++++++++++++++++++++++++++++++++++++ tools/Set-EnvVars.ps1 | 79 ++++++++++++++++++ 8 files changed, 287 insertions(+), 12 deletions(-) create mode 100644 global.json create mode 100644 tools/DotNetSdkVersion.ps1 create mode 100644 tools/Install-DotNetSdk.ps1 create mode 100644 tools/Set-EnvVars.ps1 diff --git a/.travis.yml b/.travis.yml index cc1e3c35a..a6993951b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,14 +2,24 @@ # see travis-ci.org for details language: csharp -dist: xenial -dotnet: 2.1.802 mono: none -osx_image: xcode8.3 -os: - - osx - - linux +matrix: + include: + - os: linux + dist: xenial + before_install: + - | + wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb + sudo dpkg -i packages-microsoft-prod.deb + sudo apt-get update + sudo apt-get install -y powershell + - os: osx + osx_image: xcode8.3 + before_install: + - brew update # This is necessary to get pwsh 6.2 instead of some 6.0-preview that isn't named `pwsh` + - brew cask install powershell + fast_finish: true before_install: - date -u @@ -18,6 +28,7 @@ before_install: install: - git fetch --unshallow + - pwsh ./tools/Install-DotNetSdk.ps1 ; export PATH=~/.dotnet:$PATH # Build libgit2, LibGit2Sharp and run the tests script: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e1c1ab31d..218cb2a28 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ We love Pull Requests! Your contributions help make LibGit2Sharp great. ## Getting Started -So you want to contribute to LibGit2Sharp. Great! Contributions take many forms from +So you want to contribute to LibGit2Sharp. Great! Contributions take many forms from submitting issues, writing documentation, to making code changes. We welcome it all. But first things first... @@ -14,18 +14,25 @@ But first things first... * Clearly describe the issue including steps to reproduce when it is a bug. * Make sure you fill in the earliest version that you know has the issue. * Fork the repository on GitHub, then clone it using your favorite Git client. -* Make sure the project builds and all tests pass on your machine by running +* Make sure the project builds and all tests pass on your machine by running the `buildandtest.cmd` script on Windows or `buildandtest.sh` on Linux/Mac. ## LibGit2 LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .Net and Mono. -LibGit2 is a git submodule referencing the [libgit2 project](https://github.com/libgit2/libgit2). To learn more about +LibGit2 is a git submodule referencing the [libgit2 project](https://github.com/libgit2/libgit2). To learn more about submodules read [here](http://git-scm.com/book/en/v2/Git-Tools-Submodules). To build libgit2 see [here](https://github.com/libgit2/libgit2sharp/wiki/How-to-build-x64-libgit2-and-LibGit2Sharp). ## Making Changes +Make sure you have the required .NET Core SDK and runtimes installed. +The easiest way to do this is run our `tools\Install-DotNetSdk.ps1` script. +Using the `-InstallLocality Machine` switch requires elevation but ensures +that Visual Studio will be able to load the solution even when launched from a shortcut. + +Then proceed to: + * Create a topic branch off master (don't work directly on master). * Implement your feature or fix your bug. Please following existing coding styles and do not introduce new ones. * Make atomic, focused commits with good commit messages. @@ -42,7 +49,7 @@ Some things that will increase the chance that your pull request is accepted. * Following existing code conventions. * Including unit tests that would otherwise fail without the patch, but pass after applying it. * Updating the documentation and tests that are affected by the contribution. -* If code from elsewhere is used, proper credit and a link to the source should exist in the code comments. +* If code from elsewhere is used, proper credit and a link to the source should exist in the code comments. Then licensing issues can be checked against LibGit2Sharp's very permissive MIT based open source license. * Having a configured git client that converts line endings to LF. [See here.](https://help.github.com/articles/dealing-with-line-endings/). # Additional Resources diff --git a/appveyor.yml b/appveyor.yml index 3db8b2b8a..3b46955f4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ version: '{build}' -os: Visual Studio 2017 +os: Visual Studio 2019 branches: only: @@ -68,6 +68,8 @@ install: cinst curl -y } + ./tools/Install-DotNetSdk.ps1 + before_build: - ps: | msbuild "$Env:APPVEYOR_BUILD_FOLDER\LibGit2Sharp.sln" ` diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5d703aadf..d34e9af7c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -10,16 +10,25 @@ variables: jobs: - job: Windows pool: - vmImage: 'VS2017-Win2016' + vmImage: 'windows-2019' steps: + - pwsh: ./tools/Install-DotNetSdk.ps1 + displayName: Installing .NET Core SDK and runtimes - script: buildandtest.cmd + displayName: Build and test - job: Linux pool: vmImage: 'Ubuntu 16.04' steps: + - pwsh: ./tools/Install-DotNetSdk.ps1 + displayName: Installing .NET Core SDK and runtimes - script: ./buildandtest.sh + displayName: Build and test - job: macOS pool: vmImage: 'macOS 10.13' steps: + - pwsh: ./tools/Install-DotNetSdk.ps1 + displayName: Installing .NET Core SDK and runtimes - script: ./buildandtest.sh + displayName: Build and test diff --git a/global.json b/global.json new file mode 100644 index 000000000..b354da963 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "2.1.802" + } +} diff --git a/tools/DotNetSdkVersion.ps1 b/tools/DotNetSdkVersion.ps1 new file mode 100644 index 000000000..41b89d7fd --- /dev/null +++ b/tools/DotNetSdkVersion.ps1 @@ -0,0 +1,2 @@ +$globalJson = Get-Content -Path "$PSScriptRoot\..\global.json" | ConvertFrom-Json +$globalJson.sdk.version diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1 new file mode 100644 index 000000000..e769aa2ed --- /dev/null +++ b/tools/Install-DotNetSdk.ps1 @@ -0,0 +1,160 @@ +<# +.SYNOPSIS +Installs the .NET SDK specified in the global.json file at the root of this repository, +along with supporting .NET Core runtimes used for testing. +.DESCRIPTION +This MAY not require elevation, as the SDK and runtimes are installed locally to this repo location, +unless `-InstallLocality machine` is specified. +.PARAMETER InstallLocality +A value indicating whether dependencies should be installed locally to the repo or at a per-user location. +Per-user allows sharing the installed dependencies across repositories and allows use of a shared expanded package cache. +Visual Studio will only notice and use these SDKs/runtimes if VS is launched from the environment that runs this script. +Per-repo allows for high isolation, allowing for a more precise recreation of the environment within an Azure Pipelines build. +When using 'repo', environment variables are set to cause the locally installed dotnet SDK to be used. +Per-repo can lead to file locking issues when dotnet.exe is left running as a build server and can be mitigated by running `dotnet build-server shutdown`. +Per-machine requires elevation and will download and install all SDKs and runtimes to machine-wide locations so all applications can find it. +#> +[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')] +Param ( + [ValidateSet('repo','user','machine')] + [string]$InstallLocality='user' +) + +$DotNetInstallScriptRoot = "$PSScriptRoot/../obj/tools" +if (!(Test-Path $DotNetInstallScriptRoot)) { New-Item -ItemType Directory -Path $DotNetInstallScriptRoot | Out-Null } +$DotNetInstallScriptRoot = Resolve-Path $DotNetInstallScriptRoot + +# Look up actual required .NET Core SDK version from global.json +$sdkVersion = & "$PSScriptRoot/DotNetSdkVersion.ps1" + +# Search for all .NET Core runtime versions referenced from MSBuild projects and arrange to install them. +$runtimeVersions = @() +Get-ChildItem "$PSScriptRoot\..\*.*proj" -Recurse |% { + $projXml = [xml](Get-Content -Path $_) + $targetFrameworks = $projXml.Project.PropertyGroup.TargetFramework + if (!$targetFrameworks) { + $targetFrameworks = $projXml.Project.PropertyGroup.TargetFrameworks + if ($targetFrameworks) { + $targetFrameworks = $targetFrameworks -Split ';' + } + } + $targetFrameworks |? { $_ -match 'netcoreapp(\d+\.\d+)' } |% { + $runtimeVersions += $Matches[1] + } +} + +Function Get-FileFromWeb([Uri]$Uri, $OutDir) { + $OutFile = Join-Path $OutDir $Uri.Segments[-1] + if (!(Test-Path $OutFile)) { + Write-Verbose "Downloading $Uri..." + try { + (New-Object System.Net.WebClient).DownloadFile($Uri, $OutFile) + } finally { + # This try/finally causes the script to abort + } + } + + $OutFile +} + +Function Get-InstallerExe($Version, [switch]$Runtime) { + $sdkOrRuntime = 'Sdk' + if ($Runtime) { $sdkOrRuntime = 'Runtime' } + + # Get the latest/actual version for the specified one + if (([Version]$Version).Build -eq -1) { + $versionInfo = -Split (Invoke-WebRequest -Uri "https://dotnetcli.blob.core.windows.net/dotnet/$sdkOrRuntime/$Version/latest.version" -UseBasicParsing) + $Version = $versionInfo[-1] + } + + Get-FileFromWeb -Uri "https://dotnetcli.blob.core.windows.net/dotnet/$sdkOrRuntime/$Version/dotnet-$($sdkOrRuntime.ToLowerInvariant())-$Version-win-x64.exe" -OutDir "$DotNetInstallScriptRoot" +} + +Function Install-DotNet($Version, [switch]$Runtime) { + if ($Runtime) { $sdkSubstring = '' } else { $sdkSubstring = 'SDK ' } + Write-Host "Downloading .NET Core $sdkSubstring$Version..." + $Installer = Get-InstallerExe -Version $Version -Runtime:$Runtime + Write-Host "Installing .NET Core $sdkSubstring$Version..." + cmd /c start /wait $Installer /install /quiet + if ($LASTEXITCODE -ne 0) { + throw "Failure to install .NET Core SDK" + } +} + +if ($InstallLocality -eq 'machine') { + if ($IsMacOS -or $IsLinux) { + Write-Error "Installing the .NET Core SDK or runtime at a machine-wide location is only supported by this script on Windows." + exit 1 + } + + if ($PSCmdlet.ShouldProcess(".NET Core SDK $sdkVersion", "Install")) { + Install-DotNet -Version $sdkVersion + } + + $runtimeVersions |% { + if ($PSCmdlet.ShouldProcess(".NET Core runtime $_", "Install")) { + Install-DotNet -Version $_ -Runtime + } + } + + return +} + +$switches = @( + '-Architecture','x64' +) +$envVars = @{ + # For locally installed dotnet, skip first time experience which takes a long time + 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' = 'true'; +} + +if ($InstallLocality -eq 'repo') { + $DotNetInstallDir = "$DotNetInstallScriptRoot/.dotnet" +} elseif ($env:AGENT_TOOLSDIRECTORY) { + $DotNetInstallDir = "$env:AGENT_TOOLSDIRECTORY/dotnet" +} else { + $DotNetInstallDir = Join-Path $HOME .dotnet +} + +Write-Host "Installing .NET Core SDK and runtimes to $DotNetInstallDir" -ForegroundColor Blue + +if ($DotNetInstallDir) { + $switches += '-InstallDir',$DotNetInstallDir + $envVars['DOTNET_MULTILEVEL_LOOKUP'] = '0' + $envVars['DOTNET_ROOT'] = $DotNetInstallDir +} + +if ($IsMacOS -or $IsLinux) { + $DownloadUri = "https://dot.net/v1/dotnet-install.sh" + $DotNetInstallScriptPath = "$DotNetInstallScriptRoot/dotnet-install.sh" +} else { + $DownloadUri = "https://dot.net/v1/dotnet-install.ps1" + $DotNetInstallScriptPath = "$DotNetInstallScriptRoot/dotnet-install.ps1" +} + +if (-not (Test-Path $DotNetInstallScriptPath)) { + Invoke-WebRequest -Uri $DownloadUri -OutFile $DotNetInstallScriptPath -UseBasicParsing + if ($IsMacOS -or $IsLinux) { + chmod +x $DotNetInstallScriptPath + } +} + +if ($PSCmdlet.ShouldProcess(".NET Core SDK $sdkVersion", "Install")) { + Invoke-Expression -Command "$DotNetInstallScriptPath -Version $sdkVersion $switches" +} else { + Invoke-Expression -Command "$DotNetInstallScriptPath -Version $sdkVersion $switches -DryRun" +} + +$switches += '-Runtime','dotnet' + +$runtimeVersions | Get-Unique |% { + if ($PSCmdlet.ShouldProcess(".NET Core runtime $_", "Install")) { + Invoke-Expression -Command "$DotNetInstallScriptPath -Channel $_ $switches" + } else { + Invoke-Expression -Command "$DotNetInstallScriptPath -Channel $_ $switches -DryRun" + } +} + +if ($PSCmdlet.ShouldProcess("Set DOTNET environment variables to discover these installed runtimes?")) { + & "$PSScriptRoot/Set-EnvVars.ps1" -Variables $envVars -PrependPath $DotNetInstallDir | Out-Null +} diff --git a/tools/Set-EnvVars.ps1 b/tools/Set-EnvVars.ps1 new file mode 100644 index 000000000..907659a7b --- /dev/null +++ b/tools/Set-EnvVars.ps1 @@ -0,0 +1,79 @@ +<# +.SYNOPSIS + Set environment variables in the environment. + Azure Pipeline and CMD environments are considered. +.PARAMETER Variables + A hashtable of variables to be set. +.OUTPUTS + A boolean indicating whether the environment variables can be expected to propagate to the caller's environment. +#> +[CmdletBinding(SupportsShouldProcess=$true)] +Param( + [Parameter(Mandatory=$true, Position=1)] + $Variables, + [string[]]$PrependPath +) + +if ($Variables.Count -eq 0) { + return $true +} + +$cmdInstructions = !$env:TF_BUILD -and !$env:GITHUB_ACTIONS -and $env:PS1UnderCmd -eq '1' +if ($cmdInstructions) { + Write-Warning "Environment variables have been set that will be lost because you're running under cmd.exe" + Write-Host "Environment variables that must be set manually:" -ForegroundColor Blue +} else { + Write-Host "Environment variables set:" -ForegroundColor Blue + $envVars + if ($PrependPath) { + Write-Host "Paths prepended to PATH: $PrependPath" + } +} + +if ($env:TF_BUILD) { + Write-Host "Azure Pipelines detected. Logging commands will be used to propagate environment variables and prepend path." +} + +if ($env:GITHUB_ACTIONS) { + Write-Host "GitHub Actions detected. Logging commands will be used to propagate environment variables and prepend path." +} + +$Variables.GetEnumerator() |% { + Set-Item -Path env:$($_.Key) -Value $_.Value + + # If we're running in a cloud CI, set these environment variables so they propagate. + if ($env:TF_BUILD) { + Write-Host "##vso[task.setvariable variable=$($_.Key);]$($_.Value)" + } + if ($env:GITHUB_ACTIONS) { + Write-Host "::set-env name=$($_.Key)::$($_.Value)" + } + + if ($cmdInstructions) { + Write-Host "SET $($_.Key)=$($_.Value)" + } +} + +$pathDelimiter = ';' +if ($IsMacOS -or $IsLinux) { + $pathDelimiter = ':' +} + +if ($PrependPath) { + $PrependPath |% { + $newPathValue = "$_$pathDelimiter$env:PATH" + Set-Item -Path env:PATH -Value $newPathValue + if ($cmdInstructions) { + Write-Host "SET PATH=$newPathValue" + } + + if ($env:TF_BUILD) { + Write-Host "##vso[task.prependpath]$_" + } + if ($env:GITHUB_ACTIONS) { + Write-Host "::add-path::$_" + } + } +} + +return !$cmdInstructions From ffeb4867b720707c2ecc4343e9a7d9e273cafa96 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Thu, 30 Jan 2020 23:20:55 -0500 Subject: [PATCH 030/179] Improve TruncateMilliseconds test helper --- LibGit2Sharp.Tests/TestHelpers/DateTimeOffsetExtensions.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/LibGit2Sharp.Tests/TestHelpers/DateTimeOffsetExtensions.cs b/LibGit2Sharp.Tests/TestHelpers/DateTimeOffsetExtensions.cs index d1ff4024a..14b5b06f9 100644 --- a/LibGit2Sharp.Tests/TestHelpers/DateTimeOffsetExtensions.cs +++ b/LibGit2Sharp.Tests/TestHelpers/DateTimeOffsetExtensions.cs @@ -4,11 +4,6 @@ namespace LibGit2Sharp.Tests.TestHelpers { public static class DateTimeOffsetExtensions { - public static DateTimeOffset TruncateMilliseconds(this DateTimeOffset dto) - { - // From http://stackoverflow.com/a/1005222/335418 - - return dto.AddTicks( - (dto.Ticks % TimeSpan.TicksPerSecond)); - } + public static DateTimeOffset TruncateMilliseconds(this DateTimeOffset dto) => new DateTimeOffset(dto.Year, dto.Month, dto.Day, dto.Hour, dto.Minute, dto.Second, dto.Offset); } } From 972f78ac9d96419ef234b3ea0f4e84492d4cf172 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 30 Jan 2020 22:09:01 -0700 Subject: [PATCH 031/179] Improve stability of AssertRefLogEntry-based tests Fixes #1764 --- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index a61d920dc..51496c2f5 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -467,7 +467,11 @@ protected static void AssertRefLogEntry(IRepository repo, string canonicalName, Assert.Equal(@from ?? ObjectId.Zero, reflogEntry.From); Assert.Equal(committer.Email, reflogEntry.Committer.Email); - Assert.InRange(reflogEntry.Committer.When, before, DateTimeOffset.Now); + + // When verifying the timestamp range, give a little more room on the 'before' side. + // Git or file system datetime truncation seems to cause these stamps to jump up to a second earlier + // than we expect. See https://github.com/libgit2/libgit2sharp/issues/1764 + Assert.InRange(reflogEntry.Committer.When, before - TimeSpan.FromSeconds(1), DateTimeOffset.Now); } protected static void EnableRefLog(IRepository repository, bool enable = true) From a3d9f7b29ad0555dc4647f74f7b241d340670455 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 30 Jan 2020 12:55:02 -0700 Subject: [PATCH 032/179] Switch to GitHub Actions for CI/PR builds --- .github/workflows/build.yml | 97 +++++++++++ .travis.yml | 43 +---- Directory.Build.props | 4 + Directory.Build.targets | 8 + LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 3 +- .../desktop/ShadowCopyFixture.cs | 1 + LibGit2Sharp/LibGit2Sharp.csproj | 4 +- appveyor.yml | 160 +----------------- azure-pipelines.yml | 43 ++--- azure-pipelines/Convert-PDB.ps1 | 37 ++++ azure-pipelines/Get-NuGetTool.ps1 | 22 +++ azure-pipelines/Get-TempToolsPath.ps1 | 13 ++ azure-pipelines/Get-nbgv.ps1 | 24 +++ {tools => azure-pipelines}/Set-EnvVars.ps1 | 0 azure-pipelines/artifacts/_all.ps1 | 50 ++++++ azure-pipelines/artifacts/_pipelines.ps1 | 10 ++ azure-pipelines/artifacts/_stage_all.ps1 | 59 +++++++ azure-pipelines/artifacts/build_logs.ps1 | 12 ++ azure-pipelines/artifacts/coverageResults.ps1 | 22 +++ azure-pipelines/artifacts/deployables.ps1 | 13 ++ .../artifacts/projectAssetsJson.ps1 | 9 + azure-pipelines/build.yml | 64 +++++++ azure-pipelines/dotnet.yml | 58 +++++++ azure-pipelines/install-dependencies.yml | 15 ++ azure-pipelines/justnugetorg.nuget.config | 7 + azure-pipelines/publish-codecoverage.yml | 31 ++++ azure-pipelines/publish-deployables.yml | 14 ++ .../variables/DotNetSdkVersion.ps1 | 2 + azure-pipelines/variables/_all.ps1 | 11 ++ azure-pipelines/variables/_pipelines.ps1 | 19 +++ init.cmd | 4 + init.ps1 | 67 ++++++++ tools/DotNetSdkVersion.ps1 | 2 - tools/Install-DotNetSdk.ps1 | 4 +- tools/Install-NuGetCredProvider.ps1 | 66 ++++++++ 35 files changed, 764 insertions(+), 234 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 Directory.Build.targets create mode 100644 azure-pipelines/Convert-PDB.ps1 create mode 100644 azure-pipelines/Get-NuGetTool.ps1 create mode 100644 azure-pipelines/Get-TempToolsPath.ps1 create mode 100644 azure-pipelines/Get-nbgv.ps1 rename {tools => azure-pipelines}/Set-EnvVars.ps1 (100%) create mode 100644 azure-pipelines/artifacts/_all.ps1 create mode 100644 azure-pipelines/artifacts/_pipelines.ps1 create mode 100644 azure-pipelines/artifacts/_stage_all.ps1 create mode 100644 azure-pipelines/artifacts/build_logs.ps1 create mode 100644 azure-pipelines/artifacts/coverageResults.ps1 create mode 100644 azure-pipelines/artifacts/deployables.ps1 create mode 100644 azure-pipelines/artifacts/projectAssetsJson.ps1 create mode 100644 azure-pipelines/build.yml create mode 100644 azure-pipelines/dotnet.yml create mode 100644 azure-pipelines/install-dependencies.yml create mode 100644 azure-pipelines/justnugetorg.nuget.config create mode 100644 azure-pipelines/publish-codecoverage.yml create mode 100644 azure-pipelines/publish-deployables.yml create mode 100644 azure-pipelines/variables/DotNetSdkVersion.ps1 create mode 100644 azure-pipelines/variables/_all.ps1 create mode 100644 azure-pipelines/variables/_pipelines.ps1 create mode 100644 init.cmd create mode 100644 init.ps1 delete mode 100644 tools/DotNetSdkVersion.ps1 create mode 100644 tools/Install-NuGetCredProvider.ps1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..09a3ba42d --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,97 @@ +name: CI + +on: + push: + branches: + - master + - maint.* + - validate/* + pull_request: + +env: + TreatWarningsAsErrors: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + BUILDCONFIGURATION: Release + CODECOV_TOKEN: a26c421a-824d-4a30-933b-47b2a203587f + NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages + +jobs: + leak_check: + name: Leak check (ubuntu-18.04) + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # avoid shallow clone so nbgv can do its work. + - name: Install prerequisites + run: ./init.ps1 -UpgradePrerequisites + shell: pwsh + - name: Test + run: dotnet test LibGit2Sharp.Tests --no-restore -c ${{ env.BUILDCONFIGURATION }} --filter "TestCategory!=FailsInCloudTest" -v m /p:ExtraDefine=LEAKS_IDENTIFYING -f netcoreapp2.1 + + build: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-18.04 + - macos-latest + - windows-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # avoid shallow clone so nbgv can do its work. + - name: Install prerequisites + run: | + ./init.ps1 -UpgradePrerequisites + dotnet --info + shell: pwsh + - name: Build + run: dotnet build --no-restore -c ${{ env.BUILDCONFIGURATION }} /v:m /bl:"bin/build_logs/build.binlog" + - name: Pack + run: dotnet pack --no-build -c ${{ env.BUILDCONFIGURATION }} /v:m /bl:"bin/build_logs/pack.binlog" + if: runner.os == 'Windows' + - name: Test everything + run: dotnet test --no-build -c ${{ env.BUILDCONFIGURATION }} /bl:"bin/build_logs/test.binlog" --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true + if: runner.os == 'Windows' + - name: Test .NET Core + run: dotnet test --no-build -c ${{ env.BUILDCONFIGURATION }} /bl:"bin/build_logs/test.binlog" --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true -f netcoreapp2.1 + if: runner.os != 'Windows' + - name: Collect artifacts + run: azure-pipelines/artifacts/_stage_all.ps1 + shell: pwsh + if: always() + - name: Upload project.assets.json files + if: always() + uses: actions/upload-artifact@v1 + with: + name: projectAssetsJson-${{ runner.os }} + path: obj/_artifacts/projectAssetsJson + continue-on-error: true + - name: Upload build_logs + if: always() + uses: actions/upload-artifact@v1 + with: + name: build_logs-${{ runner.os }} + path: obj/_artifacts/build_logs + continue-on-error: true + - name: Upload coverageResults + if: always() + uses: actions/upload-artifact@v1 + with: + name: coverageResults-${{ runner.os }} + path: obj/_artifacts/coverageResults + continue-on-error: true + - name: Upload deployables + uses: actions/upload-artifact@v1 + with: + name: deployables + path: obj/_artifacts/deployables + if: runner.os == 'Windows' + - name: Publish code coverage results to codecov.io + run: bash <(curl -s https://codecov.io/bash) + shell: bash + timeout-minutes: 3 + continue-on-error: true diff --git a/.travis.yml b/.travis.yml index a6993951b..18e8b5c24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,46 +1,7 @@ -# Travis-CI Build for libgit2sharp -# see travis-ci.org for details - language: csharp mono: none -matrix: - include: - - os: linux - dist: xenial - before_install: - - | - wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb - sudo dpkg -i packages-microsoft-prod.deb - sudo apt-get update - sudo apt-get install -y powershell - - os: osx - osx_image: xcode8.3 - before_install: - - brew update # This is necessary to get pwsh 6.2 instead of some 6.0-preview that isn't named `pwsh` - - brew cask install powershell - fast_finish: true - -before_install: - - date -u - - uname -a - - env | sort - -install: - - git fetch --unshallow - - pwsh ./tools/Install-DotNetSdk.ps1 ; export PATH=~/.dotnet:$PATH - -# Build libgit2, LibGit2Sharp and run the tests -script: - - ./buildandtest.sh 'LEAKS_IDENTIFYING' - -# Only watch the development branch +# Disable Travis-CI branches: only: - - master - - /^maint.*/ - -# Notify of build changes -notifications: - email: - - emeric.fermas@gmail.com + - NOTTHISONE diff --git a/Directory.Build.props b/Directory.Build.props index fb2ca9ca9..d98520a64 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,11 @@ true $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ + $(MSBuildThisFileDirectory)bin\Packages\$(Configuration)\ $(DefineConstants);$(ExtraDefine) + + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 000000000..1ddcba6f4 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,8 @@ + + + cobertura + [xunit.*]* + + $(OutputPath)/ + + diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 3503801c9..4a73bd401 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -11,7 +11,8 @@ - + + diff --git a/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs b/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs index 34719635e..d9618c06c 100644 --- a/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs +++ b/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs @@ -11,6 +11,7 @@ namespace LibGit2Sharp.Tests public class ShadowCopyFixture : BaseFixture { [Fact] + [Trait("TestCategory", "FailsWhileInstrumented")] public void CanProbeForNativeBinariesFromAShadowCopiedAssembly() { Type type = typeof(Wrapper); diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index bb64842f3..2b6a252f0 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -28,8 +28,8 @@ - - + + diff --git a/appveyor.yml b/appveyor.yml index 3b46955f4..6eeeedba4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,158 +1,4 @@ -version: '{build}' - -os: Visual Studio 2019 - +# Disable AppVeyor branches: - only: - - master - - /^maint.*/ - -configuration: release - -skip_tags: true - -nuget: - disable_publish_on_pr: true - -environment: - coveralls_token: - secure: ixIsBslo9NheDb5lJknF58EYdgvZ0r3/L0ecRiXjfXmjHBLvoSU6/ZRwaMM+BAlG - coverity_token: - secure: nuzUT+HecXGIi3KaPd/1hgFEZJan/j6+oNbPV75JKjk= - coverity_email: - secure: eGVilNg1Yuq+Xj+SW8r3WCtjnzhoDV0sNJkma4NRq7A= - matrix: - - publish_on_success: False - ExtraDefine: LEAKS_IDENTIFYING - - publish_on_success: True - -matrix: - fast_finish: true - -install: -- ps: | - Write-Host "Commit being built = " -NoNewLine - Write-Host $Env:APPVEYOR_REPO_COMMIT -ForegroundColor "Green" - Write-Host "Target branch = " -NoNewLine - Write-Host $Env:APPVEYOR_REPO_BRANCH -ForegroundColor "Green" - Write-Host "Is a Pull Request = " -NoNewLine - Write-Host $($Env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null) -ForegroundColor "Green" - - $CommitDate = [DateTime]::Parse($Env:APPVEYOR_REPO_COMMIT_TIMESTAMP) - $BuildDate = $CommitDate.ToUniversalTime().ToString("yyyyMMddHHmmss") - Write-Host "Merge commit UTC timestamp = " -NoNewLine - Write-Host $BuildDate -ForegroundColor "Green" - - $Env:SHOULD_RUN_COVERITY_ANALYSIS = $($Env:APPVEYOR_SCHEDULED_BUILD -eq $True) - Write-Host "Should run Coverity analysis = " -NoNewLine - Write-Host $Env:SHOULD_RUN_COVERITY_ANALYSIS -ForegroundColor "Green" - - $Env:SHOULD_RUN_COVERALLS = $($Env:APPVEYOR_SCHEDULED_BUILD -eq $True) - Write-Host "Should run Coveralls = " -NoNewLine - Write-Host $Env:SHOULD_RUN_COVERALLS -ForegroundColor "Green" - - Write-Host "Identifying leaks = " -NoNewLine - Write-Host ($Env:ExtraDefine -eq "LEAKS_IDENTIFYING") -ForegroundColor "Green" - - Write-Host "Should publish on success = " -NoNewLine - Write-Host $Env:publish_on_success -ForegroundColor "Green" - - If ($Env:SHOULD_RUN_COVERALLS -eq $True) - { - nuget install OpenCover -Version 4.6.166 -ExcludeVersion -OutputDirectory .\packages - nuget install coveralls.net -Version 0.6.0 -ExcludeVersion -OutputDirectory .\packages - } - - If ($Env:SHOULD_RUN_COVERITY_ANALYSIS -eq $True) - { - cinst curl -y - } - - ./tools/Install-DotNetSdk.ps1 - -before_build: -- ps: | - msbuild "$Env:APPVEYOR_BUILD_FOLDER\LibGit2Sharp.sln" ` - /nologo /verbosity:quiet ` - /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" ` - /t:restore - -build_script: -- ps: | - & cov-build.exe --dir cov-int msbuild "$Env:APPVEYOR_BUILD_FOLDER\LibGit2Sharp.sln" ` - /nologo /verbosity:minimal /fl /flp:verbosity=normal ` - /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" ` - /t:build,pack - -test_script: -- ps: | - Foreach ($runner in 'xunit.console.exe','xunit.console.x86.exe') - { - If ($Env:SHOULD_RUN_COVERALLS -eq $True -and $Env:publish_on_success -eq $True) - { - .\packages\OpenCover\tools\OpenCover.Console.exe ` - -register:user ` - "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\$runner""" ` - "-targetargs:""$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net46\LibGit2Sharp.Tests.dll"" -noshadow" ` - "-filter:+[LibGit2Sharp]* -[LibGit2Sharp.Tests]*" ` - -hideskipped:All ` - -output:opencoverCoverage.xml - } - ElseIf ($Env:SHOULD_RUN_COVERITY_ANALYSIS -eq $False) - { - & "$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\$runner" ` - "$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net46\LibGit2Sharp.Tests.dll" -noshadow - } - } - -- dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.1 --no-restore --no-build - -after_test: -- ps: | - If ($Env:SHOULD_RUN_COVERALLS -eq $True -and $Env:publish_on_success -eq $True) - { - Write-Host "Uploading code coverage result..." -ForegroundColor "Green" - - .\packages\coveralls.net\tools\csmacnz.Coveralls.exe ` - --opencover -i opencoverCoverage.xml ` - --repoToken $Env:coveralls_token ` - --useRelativePaths ` - --basePath "$Env:APPVEYOR_BUILD_FOLDER\"` - } - - If ($Env:SHOULD_RUN_COVERITY_ANALYSIS -eq $True -and $Env:publish_on_success -eq $True) - { - 7z a "$Env:APPVEYOR_BUILD_FOLDER\$Env:APPVEYOR_PROJECT_NAME.zip" "$Env:APPVEYOR_BUILD_FOLDER\cov-int\" - - # cf. http://stackoverflow.com/a/25045154/335418 - Remove-item alias:curl - - Write-Host "Uploading Coverity analysis result..." -ForegroundColor "Green" - - curl --silent --show-error ` - --output curl-out.txt ` - --form token="$Env:coverity_token" ` - --form email="$Env:coverity_email" ` - --form "file=@$Env:APPVEYOR_BUILD_FOLDER\$Env:APPVEYOR_PROJECT_NAME.zip" ` - --form version="$Env:APPVEYOR_REPO_COMMIT" ` - --form description="CI server scheduled build." ` - https://scan.coverity.com/builds?project=libgit2%2Flibgit2sharp - - cat .\curl-out.txt - } - -on_finish: -- ps: Push-AppveyorArtifact "msbuild.log" - -on_success: -- ps: | - if ($Env:publish_on_success -eq $True) - { - Get-ChildItem "bin\LibGit2Sharp\$env:configuration\*.nupkg" |% { Push-AppveyorArtifact $_.FullName -FileName $_.Name } - } - -notifications: -- provider: Email - to: - - emeric.fermas@gmail.com - on_build_status_changed: true + only: + - NOTTHISONE diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d34e9af7c..f6b8ab2c2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,34 +1,19 @@ trigger: -- master -- maint/* + branches: + include: + - master + - 'maint.*' + paths: + exclude: + - doc/ + - '*.md' + - .vscode/ variables: - solution: '**/*.sln' - buildPlatform: 'Any CPU' - buildConfiguration: 'Release' + TreatWarningsAsErrors: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + BuildConfiguration: Release + NUGET_PACKAGES: $(Agent.TempDirectory)/.nuget/packages jobs: -- job: Windows - pool: - vmImage: 'windows-2019' - steps: - - pwsh: ./tools/Install-DotNetSdk.ps1 - displayName: Installing .NET Core SDK and runtimes - - script: buildandtest.cmd - displayName: Build and test -- job: Linux - pool: - vmImage: 'Ubuntu 16.04' - steps: - - pwsh: ./tools/Install-DotNetSdk.ps1 - displayName: Installing .NET Core SDK and runtimes - - script: ./buildandtest.sh - displayName: Build and test -- job: macOS - pool: - vmImage: 'macOS 10.13' - steps: - - pwsh: ./tools/Install-DotNetSdk.ps1 - displayName: Installing .NET Core SDK and runtimes - - script: ./buildandtest.sh - displayName: Build and test +- template: azure-pipelines/build.yml diff --git a/azure-pipelines/Convert-PDB.ps1 b/azure-pipelines/Convert-PDB.ps1 new file mode 100644 index 000000000..6efd380ee --- /dev/null +++ b/azure-pipelines/Convert-PDB.ps1 @@ -0,0 +1,37 @@ +<# +.SYNOPSIS + Converts between Windows PDB and Portable PDB formats. +.PARAMETER DllPath + The path to the DLL whose PDB is to be converted. +.PARAMETER PdbPath + The path to the PDB to convert. May be omitted if the DLL was compiled on this machine and the PDB is still at its original path. +.PARAMETER OutputPath + The path of the output PDB to write. +#> +#Function Convert-PortableToWindowsPDB() { + Param( + [Parameter(Mandatory=$true,Position=0)] + [string]$DllPath, + [Parameter()] + [string]$PdbPath, + [Parameter(Mandatory=$true,Position=1)] + [string]$OutputPath + ) + + $version = '1.1.0-beta2-19516-01' + $baseDir = "$PSScriptRoot\..\obj\tools" + $pdb2pdbpath = "$baseDir\pdb2pdb.$version\tools\Pdb2Pdb.exe" + if (-not (Test-Path $pdb2pdbpath)) { + if (-not (Test-Path $baseDir)) { New-Item -Type Directory -Path $baseDir | Out-Null } + $baseDir = (Resolve-Path $baseDir).Path # Normalize it + & (& $PSScriptRoot\Get-NuGetTool.ps1) install pdb2pdb -version $version -PackageSaveMode nuspec -OutputDirectory $baseDir -Source https://dotnet.myget.org/F/symreader-converter/api/v3/index.json | Out-Null + } + + $args = $DllPath,'/out',$OutputPath,'/nowarn','0021' + if ($PdbPath) { + $args += '/pdb',$PdbPath + } + + Write-Verbose "$pdb2pdbpath $args" + & $pdb2pdbpath $args +#} diff --git a/azure-pipelines/Get-NuGetTool.ps1 b/azure-pipelines/Get-NuGetTool.ps1 new file mode 100644 index 000000000..4431adb91 --- /dev/null +++ b/azure-pipelines/Get-NuGetTool.ps1 @@ -0,0 +1,22 @@ +<# +.SYNOPSIS + Downloads the NuGet.exe tool and returns the path to it. +.PARAMETER NuGetVersion + The version of the NuGet tool to acquire. +#> +Param( + [Parameter()] + [string]$NuGetVersion='5.2.0' +) + +$toolsPath = & "$PSScriptRoot\Get-TempToolsPath.ps1" +$binaryToolsPath = Join-Path $toolsPath $NuGetVersion +if (!(Test-Path $binaryToolsPath)) { $null = mkdir $binaryToolsPath } +$nugetPath = Join-Path $binaryToolsPath nuget.exe + +if (!(Test-Path $nugetPath)) { + Write-Host "Downloading nuget.exe $NuGetVersion..." -ForegroundColor Yellow + (New-Object System.Net.WebClient).DownloadFile("https://dist.nuget.org/win-x86-commandline/v$NuGetVersion/NuGet.exe", $nugetPath) +} + +return (Resolve-Path $nugetPath).Path diff --git a/azure-pipelines/Get-TempToolsPath.ps1 b/azure-pipelines/Get-TempToolsPath.ps1 new file mode 100644 index 000000000..bb3da8e33 --- /dev/null +++ b/azure-pipelines/Get-TempToolsPath.ps1 @@ -0,0 +1,13 @@ +if ($env:AGENT_TEMPDIRECTORY) { + $path = "$env:AGENT_TEMPDIRECTORY\$env:BUILD_BUILDID" +} elseif ($env:localappdata) { + $path = "$env:localappdata\gitrepos\tools" +} else { + $path = "$PSScriptRoot\..\obj\tools" +} + +if (!(Test-Path $path)) { + New-Item -ItemType Directory -Path $Path | Out-Null +} + +(Resolve-Path $path).Path diff --git a/azure-pipelines/Get-nbgv.ps1 b/azure-pipelines/Get-nbgv.ps1 new file mode 100644 index 000000000..a5be2cf7c --- /dev/null +++ b/azure-pipelines/Get-nbgv.ps1 @@ -0,0 +1,24 @@ +<# +.SYNOPSIS + Gets the path to the nbgv CLI tool, installing it if necessary. +#> +Param( +) + +$existingTool = Get-Command "nbgv" -ErrorAction SilentlyContinue +if ($existingTool) { + return $existingTool.Path +} + +$toolInstallDir = & "$PSScriptRoot/Get-TempToolsPath.ps1" + +$toolPath = "$toolInstallDir/nbgv" +if (!(Test-Path $toolInstallDir)) { New-Item -Path $toolInstallDir -ItemType Directory | Out-Null } + +if (!(Get-Command $toolPath -ErrorAction SilentlyContinue)) { + Write-Host "Installing nbgv to $toolInstallDir" + dotnet tool install --tool-path "$toolInstallDir" nbgv --configfile "$PSScriptRoot/justnugetorg.nuget.config" | Out-Null +} + +# Normalize the path on the way out. +return (Get-Command $toolPath).Path diff --git a/tools/Set-EnvVars.ps1 b/azure-pipelines/Set-EnvVars.ps1 similarity index 100% rename from tools/Set-EnvVars.ps1 rename to azure-pipelines/Set-EnvVars.ps1 diff --git a/azure-pipelines/artifacts/_all.ps1 b/azure-pipelines/artifacts/_all.ps1 new file mode 100644 index 000000000..6f62be5c3 --- /dev/null +++ b/azure-pipelines/artifacts/_all.ps1 @@ -0,0 +1,50 @@ +# This script returns all the artifacts that should be collected after a build. +# +# Each powershell artifact is expressed as an object with these properties: +# Source - the full path to the source file +# ArtifactName - the name of the artifact to upload to +# ContainerFolder - the relative path within the artifact in which the file should appear +# +# Each artifact aggregating .ps1 script should return a hashtable: +# Key = path to the directory from which relative paths within the artifact should be calculated +# Value = an array of paths (absolute or relative to the BaseDirectory) to files to include in the artifact. +# FileInfo objects are also allowed. + +$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") + +Function EnsureTrailingSlash($path) { + if ($path.length -gt 0 -and !$path.EndsWith('\') -and !$path.EndsWith('/')) { + $path = $path + [IO.Path]::DirectorySeparatorChar + } + + $path.Replace('\', [IO.Path]::DirectorySeparatorChar) +} + +Get-ChildItem "$PSScriptRoot\*.ps1" -Exclude "_*" -Recurse |% { + $ArtifactName = $_.BaseName + + $fileGroups = & $_ + if (!$fileGroups -or $fileGroups.Count -eq 0) { + Write-Warning "No files found for the `"$ArtifactName`" artifact." + } else { + $fileGroups.GetEnumerator() | % { + $BaseDirectory = New-Object Uri ((EnsureTrailingSlash $_.Key), [UriKind]::Absolute) + $_.Value | % { + if ($_.GetType() -eq [IO.FileInfo] -or $_.GetType() -eq [IO.DirectoryInfo]) { + $_ = $_.FullName + } + + $artifact = New-Object -TypeName PSObject + Add-Member -InputObject $artifact -MemberType NoteProperty -Name ArtifactName -Value $ArtifactName + + $SourceFullPath = New-Object Uri ($BaseDirectory, $_) + Add-Member -InputObject $artifact -MemberType NoteProperty -Name Source -Value $SourceFullPath.LocalPath + + $RelativePath = [Uri]::UnescapeDataString($BaseDirectory.MakeRelative($SourceFullPath)) + Add-Member -InputObject $artifact -MemberType NoteProperty -Name ContainerFolder -Value (Split-Path $RelativePath) + + Write-Output $artifact + } + } + } +} diff --git a/azure-pipelines/artifacts/_pipelines.ps1 b/azure-pipelines/artifacts/_pipelines.ps1 new file mode 100644 index 000000000..5bca7c6c1 --- /dev/null +++ b/azure-pipelines/artifacts/_pipelines.ps1 @@ -0,0 +1,10 @@ +# This script translates all the artifacts described by _all.ps1 +# into commands that instruct Azure Pipelines to actually collect those artifacts. + +param ( + [string]$ArtifactNameSuffix +) + +& "$PSScriptRoot/_stage_all.ps1" -ArtifactNameSuffix $ArtifactNameSuffix |% { + Write-Host "##vso[artifact.upload containerfolder=$($_.Name);artifactname=$($_.Name);]$($_.Path)" +} diff --git a/azure-pipelines/artifacts/_stage_all.ps1 b/azure-pipelines/artifacts/_stage_all.ps1 new file mode 100644 index 000000000..a05db5292 --- /dev/null +++ b/azure-pipelines/artifacts/_stage_all.ps1 @@ -0,0 +1,59 @@ +# This script links all the artifacts described by _all.ps1 +# into a staging directory, reading for uploading to a cloud build artifact store. +# It returns a sequence of objects with Name and Path properties. + +param ( + [string]$ArtifactNameSuffix +) + +$RepoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot (Join-Path .. ..))) +if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) { + $ArtifactStagingFolder = $env:BUILD_ARTIFACTSTAGINGDIRECTORY +} else { + $ArtifactStagingFolder = Join-Path $RepoRoot (Join-Path obj _artifacts) + if (Test-Path $ArtifactStagingFolder) { + Remove-Item $ArtifactStagingFolder -Recurse -Force + } +} + +function Create-SymbolicLink { + param ( + $Link, + $Target + ) + + if ($Link -eq $Target) { + return + } + + if (Test-Path $Link) { Remove-Item $Link } + $LinkContainer = Split-Path $Link -Parent + if (!(Test-Path $LinkContainer)) { mkdir $LinkContainer } + Write-Verbose "Linking $Link to $Target" + if ($IsMacOS -or $IsLinux) { + ln $Target $Link | Out-Null + } else { + cmd /c mklink $Link $Target | Out-Null + } +} + +# Stage all artifacts +$Artifacts = & "$PSScriptRoot\_all.ps1" +$Artifacts |% { + $DestinationFolder = (Join-Path (Join-Path $ArtifactStagingFolder "$($_.ArtifactName)$ArtifactNameSuffix") $_.ContainerFolder).TrimEnd('\') + $Name = "$(Split-Path $_.Source -Leaf)" + + #Write-Host "$($_.Source) -> $($_.ArtifactName)\$($_.ContainerFolder)" -ForegroundColor Yellow + + if (-not (Test-Path $DestinationFolder)) { New-Item -ItemType Directory -Path $DestinationFolder | Out-Null } + if (Test-Path -PathType Leaf $_.Source) { # skip folders + Create-SymbolicLink -Link (Join-Path $DestinationFolder $Name) -Target $_.Source + } +} + +$Artifacts |% { "$($_.ArtifactName)$ArtifactNameSuffix" } | Get-Unique |% { + $artifact = New-Object -TypeName PSObject + Add-Member -InputObject $artifact -MemberType NoteProperty -Name Name -Value $_ + Add-Member -InputObject $artifact -MemberType NoteProperty -Name Path -Value (Join-Path $ArtifactStagingFolder $_) + Write-Output $artifact +} diff --git a/azure-pipelines/artifacts/build_logs.ps1 b/azure-pipelines/artifacts/build_logs.ps1 new file mode 100644 index 000000000..b55ba48f3 --- /dev/null +++ b/azure-pipelines/artifacts/build_logs.ps1 @@ -0,0 +1,12 @@ +if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) { + $artifactsRoot = $env:BUILD_ARTIFACTSTAGINGDIRECTORY +} else { + $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") + $artifactsRoot = "$RepoRoot\bin" +} + +if (!(Test-Path $artifactsRoot/build_logs)) { return } + +@{ + "$artifactsRoot/build_logs" = (Get-ChildItem -Recurse "$artifactsRoot/build_logs") +} diff --git a/azure-pipelines/artifacts/coverageResults.ps1 b/azure-pipelines/artifacts/coverageResults.ps1 new file mode 100644 index 000000000..7d1e9a35f --- /dev/null +++ b/azure-pipelines/artifacts/coverageResults.ps1 @@ -0,0 +1,22 @@ +$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") + +# Prepare code coverage reports for merging on another machine +if ($env:SYSTEM_DEFAULTWORKINGDIRECTORY) { + Write-Host "Substituting $env:SYSTEM_DEFAULTWORKINGDIRECTORY with `"{reporoot}`"" + $reports = Get-ChildItem "$RepoRoot/bin/coverage.cobertura.xml" -Recurse + $reports |% { + $content = Get-Content -Path $_ |% { $_ -Replace [regex]::Escape($env:SYSTEM_DEFAULTWORKINGDIRECTORY), "{reporoot}" } + Set-Content -Path $_ -Value $content -Encoding UTF8 + } +} else { + Write-Warning "coverageResults: Azure Pipelines not detected. Machine-neutral token replacement skipped." +} + +if (!((Test-Path $RepoRoot\bin) -and (Test-Path $RepoRoot\obj))) { return } + +@{ + $RepoRoot = ( + @(Get-ChildItem "$RepoRoot\bin\coverage.cobertura.xml" -Recurse) + + (Get-ChildItem "$RepoRoot\obj\*.cs" -Recurse) + ); +} diff --git a/azure-pipelines/artifacts/deployables.ps1 b/azure-pipelines/artifacts/deployables.ps1 new file mode 100644 index 000000000..94c48cdd9 --- /dev/null +++ b/azure-pipelines/artifacts/deployables.ps1 @@ -0,0 +1,13 @@ +$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") +$BuildConfiguration = $env:BUILDCONFIGURATION +if (!$BuildConfiguration) { + $BuildConfiguration = 'Debug' +} + +$PackagesRoot = "$RepoRoot/bin/Packages/$BuildConfiguration" + +if (!(Test-Path $PackagesRoot)) { return } + +@{ + "$PackagesRoot" = (Get-ChildItem $PackagesRoot -Recurse) +} diff --git a/azure-pipelines/artifacts/projectAssetsJson.ps1 b/azure-pipelines/artifacts/projectAssetsJson.ps1 new file mode 100644 index 000000000..d2e85ffbe --- /dev/null +++ b/azure-pipelines/artifacts/projectAssetsJson.ps1 @@ -0,0 +1,9 @@ +$ObjRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\obj") + +if (!(Test-Path $ObjRoot)) { return } + +@{ + "$ObjRoot" = ( + (Get-ChildItem "$ObjRoot\project.assets.json" -Recurse) + ); +} diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml new file mode 100644 index 000000000..e5e6f479d --- /dev/null +++ b/azure-pipelines/build.yml @@ -0,0 +1,64 @@ +parameters: + windowsPool: Hosted Windows 2019 with VS2019 + +jobs: +- job: Windows + pool: ${{ parameters.windowsPool }} + steps: + - checkout: self + clean: true + - template: install-dependencies.yml + + - powershell: '& (./azure-pipelines/Get-nbgv.ps1) cloud' + displayName: Set build number + + - template: dotnet.yml + +- job: Linux + pool: + vmImage: Ubuntu 18.04 + steps: + - checkout: self + clean: true + - template: install-dependencies.yml + - template: dotnet.yml + +- job: macOS + pool: + vmImage: macOS 10.13 + steps: + - checkout: self + clean: true + - template: install-dependencies.yml + - template: dotnet.yml + +- job: WrapUp + dependsOn: + - Windows + - Linux + - macOS + pool: + vmImage: Ubuntu 18.04 + condition: succeededOrFailed() + steps: + - checkout: self + clean: true + - template: install-dependencies.yml + parameters: + initArgs: -NoRestore + - template: publish-codecoverage.yml + - template: publish-deployables.yml + +- job: leak_check + pool: + vmImage: Ubuntu 18.04 + steps: + - checkout: self + clean: true + - template: install-dependencies.yml + - task: DotNetCoreCLI@2 + displayName: dotnet test -f netcoreapp2.1 + inputs: + command: test + arguments: --no-restore -c $(BuildConfiguration) -f netcoreapp2.1 --filter "TestCategory!=FailsInCloudTest" -v m /p:ExtraDefine=LEAKS_IDENTIFYING + testRunTitle: netcoreapp2.1-$(Agent.JobName) diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml new file mode 100644 index 000000000..35aa8c979 --- /dev/null +++ b/azure-pipelines/dotnet.yml @@ -0,0 +1,58 @@ +steps: + +- script: dotnet build --no-restore -c $(BuildConfiguration) /v:m /bl:"$(Build.ArtifactStagingDirectory)/build_logs/build.binlog" + displayName: dotnet build + +- script: dotnet pack --no-build -c $(BuildConfiguration) /v:m /bl:"$(Build.ArtifactStagingDirectory)/build_logs/pack.binlog" + displayName: dotnet pack + +- task: DotNetCoreCLI@2 + displayName: dotnet test -f net46 (w/ coverage) + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f net46 --filter "TestCategory!=FailsInCloudTest & TestCategory!=FailsWhileInstrumented" -v n /p:CollectCoverage=true + testRunTitle: net46-$(Agent.JobName) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +- task: DotNetCoreCLI@2 + displayName: dotnet test -f net46 (w/o coverage) + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f net46 --filter "TestCategory!=FailsInCloudTest & TestCategory=FailsWhileInstrumented" -v n + testRunTitle: net46-$(Agent.JobName)-nocoverage + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +- task: DotNetCoreCLI@2 + displayName: dotnet test -f netcoreapp2.1 + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f netcoreapp2.1 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true + testRunTitle: netcoreapp2.1-$(Agent.JobName) + +- task: PowerShell@2 + inputs: + filePath: azure-pipelines/variables/_pipelines.ps1 + failOnStderr: true + displayName: Update pipeline variables based on build outputs + condition: succeededOrFailed() + +- task: PowerShell@2 + inputs: + filePath: azure-pipelines/artifacts/_pipelines.ps1 + arguments: -ArtifactNameSuffix "-$(Agent.JobName)" + displayName: Publish artifacts + condition: succeededOrFailed() + +- task: PublishSymbols@2 + inputs: + SymbolsFolder: $(Build.ArtifactStagingDirectory)/symbols-Windows + SearchPattern: '**/*.pdb' + IndexSources: false + SymbolServerType: TeamServices + displayName: Publish symbols to symbol server + condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Agent.OS'], 'Windows_NT')) + +- bash: bash <(curl -s https://codecov.io/bash) + displayName: Publish code coverage results to codecov.io + timeoutInMinutes: 3 + continueOnError: true diff --git a/azure-pipelines/install-dependencies.yml b/azure-pipelines/install-dependencies.yml new file mode 100644 index 000000000..9257db852 --- /dev/null +++ b/azure-pipelines/install-dependencies.yml @@ -0,0 +1,15 @@ +parameters: + initArgs: + +steps: + +- powershell: | + .\init.ps1 -AccessToken '$(System.AccessToken)' ${{ parameters['initArgs'] }} -UpgradePrerequisites + dotnet --info + displayName: Install prerequisites + +- task: PowerShell@2 + inputs: + filePath: azure-pipelines/variables/_pipelines.ps1 + failOnStderr: true + displayName: Set pipeline variables based on source diff --git a/azure-pipelines/justnugetorg.nuget.config b/azure-pipelines/justnugetorg.nuget.config new file mode 100644 index 000000000..765346e53 --- /dev/null +++ b/azure-pipelines/justnugetorg.nuget.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/azure-pipelines/publish-codecoverage.yml b/azure-pipelines/publish-codecoverage.yml new file mode 100644 index 000000000..6d367de96 --- /dev/null +++ b/azure-pipelines/publish-codecoverage.yml @@ -0,0 +1,31 @@ +steps: +- download: current + artifact: coverageResults-Windows + displayName: Download Windows code coverage results + continueOnError: true +- download: current + artifact: coverageResults-Linux + displayName: Download Linux code coverage results + continueOnError: true +- download: current + artifact: coverageResults-macOS + displayName: Download macOS code coverage results + continueOnError: true +- powershell: | + dotnet tool install --tool-path obj dotnet-reportgenerator-globaltool --version 4.2.2 --configfile azure-pipelines/justnugetorg.nuget.config + Copy-Item -Recurse $(Pipeline.Workspace)/coverageResults-Windows/obj/* $(System.DefaultWorkingDirectory)/obj + Write-Host "Substituting {reporoot} with $(System.DefaultWorkingDirectory)" + $reports = Get-ChildItem -Recurse "$(Pipeline.Workspace)/coverage.cobertura.xml" + $reports |% { + $content = Get-Content -Path $_ |% { $_.Replace("{reporoot}", "$(System.DefaultWorkingDirectory)") } + Set-Content -Path $_ -Value $content -Encoding UTF8 + } + $Inputs = [string]::join(';', ($reports |% { Resolve-Path -relative $_ })) + obj/reportgenerator -reports:"$Inputs" -targetdir:coveragereport -reporttypes:Cobertura + displayName: Merge coverage +- task: PublishCodeCoverageResults@1 + displayName: Publish code coverage results to Azure DevOps + inputs: + codeCoverageTool: cobertura + summaryFileLocation: 'coveragereport/Cobertura.xml' + failIfCoverageEmpty: true diff --git a/azure-pipelines/publish-deployables.yml b/azure-pipelines/publish-deployables.yml new file mode 100644 index 000000000..a89f389fd --- /dev/null +++ b/azure-pipelines/publish-deployables.yml @@ -0,0 +1,14 @@ +steps: +- download: current + displayName: Download deployables + artifact: deployables-Windows + +- task: NuGetCommand@2 + displayName: Push packages to CI feed + inputs: + command: push + packagesToPush: $(Pipeline.Workspace)/deployables-Windows/*.nupkg + nuGetFeedType: internal + publishVstsFeed: $(ci_feed) + allowPackageConflicts: true + condition: and(succeeded(), ne(variables['ci_feed'], ''), ne(variables['Build.Reason'], 'PullRequest')) diff --git a/azure-pipelines/variables/DotNetSdkVersion.ps1 b/azure-pipelines/variables/DotNetSdkVersion.ps1 new file mode 100644 index 000000000..b213fbc27 --- /dev/null +++ b/azure-pipelines/variables/DotNetSdkVersion.ps1 @@ -0,0 +1,2 @@ +$globalJson = Get-Content -Path "$PSScriptRoot\..\..\global.json" | ConvertFrom-Json +$globalJson.sdk.version diff --git a/azure-pipelines/variables/_all.ps1 b/azure-pipelines/variables/_all.ps1 new file mode 100644 index 000000000..ed0997922 --- /dev/null +++ b/azure-pipelines/variables/_all.ps1 @@ -0,0 +1,11 @@ +# This script returns a hashtable of build variables that should be set +# at the start of a build or release definition's execution. + +$vars = @{} + +Get-ChildItem "$PSScriptRoot\*.ps1" -Exclude "_*" |% { + Write-Host "Computing $($_.BaseName) variable" + $vars[$_.BaseName] = & $_ +} + +$vars diff --git a/azure-pipelines/variables/_pipelines.ps1 b/azure-pipelines/variables/_pipelines.ps1 new file mode 100644 index 000000000..28230b817 --- /dev/null +++ b/azure-pipelines/variables/_pipelines.ps1 @@ -0,0 +1,19 @@ +# This script translates the variables returned by the _all.ps1 script +# into commands that instruct Azure Pipelines to actually set those variables for other pipeline tasks to consume. + +# The build or release definition may have set these variables to override +# what the build would do. So only set them if they have not already been set. + +(& "$PSScriptRoot\_all.ps1").GetEnumerator() |% { + if (Test-Path -Path "env:$($_.Key)") { + Write-Host "Skipping setting $($_.Key) because variable is already set." -ForegroundColor Cyan + } else { + Write-Host "$($_.Key)=$($_.Value)" -ForegroundColor Yellow + if ($env:TF_BUILD) { + Write-Host "##vso[task.setvariable variable=$($_.Key);]$($_.Value)" + } elseif ($env:GITHUB_ACTIONS) { + Write-Host "::set-env name=$($_.Key)::$($_.Value)" + } + Set-Item -Path "env:$($_.Key)" -Value $_.Value + } +} diff --git a/init.cmd b/init.cmd new file mode 100644 index 000000000..970285c2f --- /dev/null +++ b/init.cmd @@ -0,0 +1,4 @@ +@echo off +SETLOCAL +set PS1UnderCmd=1 +powershell.exe -NoProfile -NoLogo -ExecutionPolicy bypass -Command "try { & '%~dpn0.ps1' %*; exit $LASTEXITCODE } catch { write-host $_; exit 1 }" diff --git a/init.ps1 b/init.ps1 new file mode 100644 index 000000000..33140ac5e --- /dev/null +++ b/init.ps1 @@ -0,0 +1,67 @@ +<# +.SYNOPSIS +Installs dependencies required to build and test the projects in this repository. +.DESCRIPTION +This MAY not require elevation, as the SDK and runtimes are installed to a per-user location, +unless the `-InstallLocality` switch is specified directing to a per-repo or per-machine location. +See detailed help on that switch for more information. +.PARAMETER InstallLocality +A value indicating whether dependencies should be installed locally to the repo or at a per-user location. +Per-user allows sharing the installed dependencies across repositories and allows use of a shared expanded package cache. +Visual Studio will only notice and use these SDKs/runtimes if VS is launched from the environment that runs this script. +Per-repo allows for high isolation, allowing for a more precise recreation of the environment within an Azure Pipelines build. +When using 'repo', environment variables are set to cause the locally installed dotnet SDK to be used. +Per-repo can lead to file locking issues when dotnet.exe is left running as a build server and can be mitigated by running `dotnet build-server shutdown`. +Per-machine requires elevation and will download and install all SDKs and runtimes to machine-wide locations so all applications can find it. +.PARAMETER NoPrerequisites +Skips the installation of prerequisite software (e.g. SDKs, tools). +.PARAMETER UpgradePrerequisites +Takes time to install prerequisites even if they are already present in case they need to be upgraded. +No effect if -NoPrerequisites is specified. +.PARAMETER NoRestore +Skips the package restore step. +.PARAMETER AccessToken +An optional access token for authenticating to Azure Artifacts authenticated feeds. +#> +[CmdletBinding(SupportsShouldProcess=$true)] +Param ( + [ValidateSet('repo','user','machine')] + [string]$InstallLocality='user', + [Parameter()] + [switch]$NoPrerequisites, + [Parameter()] + [switch]$UpgradePrerequisites, + [Parameter()] + [switch]$NoRestore, + [Parameter()] + [string]$AccessToken +) + +if (!$NoPrerequisites) { + & "$PSScriptRoot\tools\Install-NuGetCredProvider.ps1" -AccessToken $AccessToken -Force:$UpgradePrerequisites + & "$PSScriptRoot\tools\Install-DotNetSdk.ps1" -InstallLocality $InstallLocality +} + +# Workaround nuget credential provider bug that causes very unreliable package restores on Azure Pipelines +$env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 +$env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 + +Push-Location $PSScriptRoot +try { + $HeaderColor = 'Green' + + if (!$NoRestore -and $PSCmdlet.ShouldProcess("NuGet packages", "Restore")) { + Write-Host "Restoring NuGet packages" -ForegroundColor $HeaderColor + dotnet restore + if ($lastexitcode -ne 0) { + throw "Failure while restoring packages." + } + } +} +catch { + Write-Error $error[0] + exit $lastexitcode +} +finally { + Pop-Location +} diff --git a/tools/DotNetSdkVersion.ps1 b/tools/DotNetSdkVersion.ps1 deleted file mode 100644 index 41b89d7fd..000000000 --- a/tools/DotNetSdkVersion.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -$globalJson = Get-Content -Path "$PSScriptRoot\..\global.json" | ConvertFrom-Json -$globalJson.sdk.version diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1 index e769aa2ed..10ed02b8b 100644 --- a/tools/Install-DotNetSdk.ps1 +++ b/tools/Install-DotNetSdk.ps1 @@ -25,7 +25,7 @@ if (!(Test-Path $DotNetInstallScriptRoot)) { New-Item -ItemType Directory -Path $DotNetInstallScriptRoot = Resolve-Path $DotNetInstallScriptRoot # Look up actual required .NET Core SDK version from global.json -$sdkVersion = & "$PSScriptRoot/DotNetSdkVersion.ps1" +$sdkVersion = & "$PSScriptRoot/../azure-pipelines/variables/DotNetSdkVersion.ps1" # Search for all .NET Core runtime versions referenced from MSBuild projects and arrange to install them. $runtimeVersions = @() @@ -156,5 +156,5 @@ $runtimeVersions | Get-Unique |% { } if ($PSCmdlet.ShouldProcess("Set DOTNET environment variables to discover these installed runtimes?")) { - & "$PSScriptRoot/Set-EnvVars.ps1" -Variables $envVars -PrependPath $DotNetInstallDir | Out-Null + & "$PSScriptRoot/../azure-pipelines/Set-EnvVars.ps1" -Variables $envVars -PrependPath $DotNetInstallDir | Out-Null } diff --git a/tools/Install-NuGetCredProvider.ps1 b/tools/Install-NuGetCredProvider.ps1 new file mode 100644 index 000000000..0a8d77f62 --- /dev/null +++ b/tools/Install-NuGetCredProvider.ps1 @@ -0,0 +1,66 @@ +<# +.SYNOPSIS + Downloads and installs the Microsoft Artifacts Credential Provider + from https://github.com/microsoft/artifacts-credprovider + to assist in authenticating to Azure Artifact feeds in interactive development + or unattended build agents. +.PARAMETER Force + Forces install of the CredProvider plugin even if one already exists. This is useful to upgrade an older version. +.PARAMETER AccessToken + An optional access token for authenticating to Azure Artifacts authenticated feeds. +#> +[CmdletBinding()] +Param ( + [Parameter()] + [switch]$Force, + [Parameter()] + [string]$AccessToken +) + +$toolsPath = & "$PSScriptRoot\..\azure-pipelines\Get-TempToolsPath.ps1" + +if ($IsMacOS -or $IsLinux) { + $installerScript = "installcredprovider.sh" + $sourceUrl = "https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh" +} else { + $installerScript = "installcredprovider.ps1" + $sourceUrl = "https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.ps1" +} + +$installerScript = Join-Path $toolsPath $installerScript + +if (!(Test-Path $installerScript)) { + Invoke-WebRequest $sourceUrl -OutFile $installerScript +} + +$installerScript = (Resolve-Path $installerScript).Path + +if ($IsMacOS -or $IsLinux) { + chmod u+x $installerScript +} + +& $installerScript -Force:$Force + +if ($AccessToken) { + $endpoints = @() + + $nugetConfig = [xml](Get-Content -Path "$PSScriptRoot\..\nuget.config") + + $nugetConfig.configuration.packageSources.add |? { ($_.value -match '^https://pkgs\.dev\.azure\.com/') -or ($_.value -match '^https://[\w\-]+\.pkgs\.visualstudio\.com/') } |% { + $endpoint = New-Object -TypeName PSObject + Add-Member -InputObject $endpoint -MemberType NoteProperty -Name endpoint -Value $_.value + Add-Member -InputObject $endpoint -MemberType NoteProperty -Name username -Value ado + Add-Member -InputObject $endpoint -MemberType NoteProperty -Name password -Value $AccessToken + $endpoints += $endpoint + } + + $auth = New-Object -TypeName PSObject + Add-Member -InputObject $auth -MemberType NoteProperty -Name endpointCredentials -Value $endpoints + + $authJson = ConvertTo-Json -InputObject $auth + $envVars = @{ + 'VSS_NUGET_EXTERNAL_FEED_ENDPOINTS'=$authJson; + } + + & "$PSScriptRoot\..\azure-pipelines\Set-EnvVars.ps1" -Variables $envVars | Out-Null +} From dd006b7a7f4e706bcda4b98a7db7cdc59c45e4d7 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 30 Jan 2020 13:02:28 -0700 Subject: [PATCH 033/179] Update to .NET SDK 3.1.100 --- LibGit2Sharp/LibGit2Sharp.csproj | 5 +++-- global.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 2b6a252f0..c14a1abdd 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -14,10 +14,13 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true ..\libgit2sharp.snk + square-logo.png + MIT + @@ -37,9 +40,7 @@ - https://github.com/libgit2/libgit2sharp/raw/$(GitCommitIdShort)/square-logo.png https://github.com/libgit2/libgit2sharp/blob/$(GitCommitIdShort)/CHANGES.md#libgit2sharp-changes - https://github.com/libgit2/libgit2sharp/raw/$(GitCommitIdShort)/LICENSE.md diff --git a/global.json b/global.json index b354da963..e9aac8c22 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "2.1.802" + "version": "3.1.100" } } From 15d6464e67e530409437483dcb0641e5a463eddf Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 30 Jan 2020 14:04:19 -0700 Subject: [PATCH 034/179] Fix CanIncludeStatusOfUnalteredFiles test It was sorting in an undefined way that led it to fail on Ubuntu. --- LibGit2Sharp.Tests/StatusFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/StatusFixture.cs b/LibGit2Sharp.Tests/StatusFixture.cs index 7ba561def..698639aa4 100644 --- a/LibGit2Sharp.Tests/StatusFixture.cs +++ b/LibGit2Sharp.Tests/StatusFixture.cs @@ -640,7 +640,7 @@ public void CanIncludeStatusOfUnalteredFiles() RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = true }); Assert.Equal(unalteredPaths.Length, status.Unaltered.Count()); - Assert.Equal(unalteredPaths, status.Unaltered.OrderBy(s => s.FilePath).Select(s => s.FilePath).ToArray()); + Assert.Equal(unalteredPaths, status.Unaltered.OrderBy(s => s.FilePath, StringComparer.OrdinalIgnoreCase).Select(s => s.FilePath).ToArray()); } } From ddd499872835e5856e33896f7549e8e77fd52c11 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 31 Jan 2020 09:24:04 -0700 Subject: [PATCH 035/179] Remove GitHub workflow --- .github/workflows/build.yml | 97 ------------------------------------- 1 file changed, 97 deletions(-) delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 09a3ba42d..000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: CI - -on: - push: - branches: - - master - - maint.* - - validate/* - pull_request: - -env: - TreatWarningsAsErrors: true - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - BUILDCONFIGURATION: Release - CODECOV_TOKEN: a26c421a-824d-4a30-933b-47b2a203587f - NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages - -jobs: - leak_check: - name: Leak check (ubuntu-18.04) - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - - name: Install prerequisites - run: ./init.ps1 -UpgradePrerequisites - shell: pwsh - - name: Test - run: dotnet test LibGit2Sharp.Tests --no-restore -c ${{ env.BUILDCONFIGURATION }} --filter "TestCategory!=FailsInCloudTest" -v m /p:ExtraDefine=LEAKS_IDENTIFYING -f netcoreapp2.1 - - build: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - ubuntu-18.04 - - macos-latest - - windows-latest - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - - name: Install prerequisites - run: | - ./init.ps1 -UpgradePrerequisites - dotnet --info - shell: pwsh - - name: Build - run: dotnet build --no-restore -c ${{ env.BUILDCONFIGURATION }} /v:m /bl:"bin/build_logs/build.binlog" - - name: Pack - run: dotnet pack --no-build -c ${{ env.BUILDCONFIGURATION }} /v:m /bl:"bin/build_logs/pack.binlog" - if: runner.os == 'Windows' - - name: Test everything - run: dotnet test --no-build -c ${{ env.BUILDCONFIGURATION }} /bl:"bin/build_logs/test.binlog" --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true - if: runner.os == 'Windows' - - name: Test .NET Core - run: dotnet test --no-build -c ${{ env.BUILDCONFIGURATION }} /bl:"bin/build_logs/test.binlog" --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true -f netcoreapp2.1 - if: runner.os != 'Windows' - - name: Collect artifacts - run: azure-pipelines/artifacts/_stage_all.ps1 - shell: pwsh - if: always() - - name: Upload project.assets.json files - if: always() - uses: actions/upload-artifact@v1 - with: - name: projectAssetsJson-${{ runner.os }} - path: obj/_artifacts/projectAssetsJson - continue-on-error: true - - name: Upload build_logs - if: always() - uses: actions/upload-artifact@v1 - with: - name: build_logs-${{ runner.os }} - path: obj/_artifacts/build_logs - continue-on-error: true - - name: Upload coverageResults - if: always() - uses: actions/upload-artifact@v1 - with: - name: coverageResults-${{ runner.os }} - path: obj/_artifacts/coverageResults - continue-on-error: true - - name: Upload deployables - uses: actions/upload-artifact@v1 - with: - name: deployables - path: obj/_artifacts/deployables - if: runner.os == 'Windows' - - name: Publish code coverage results to codecov.io - run: bash <(curl -s https://codecov.io/bash) - shell: bash - timeout-minutes: 3 - continue-on-error: true From 9b91bd823210538b3c04a43abbecc13c0a2abdfa Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 30 Jan 2020 13:46:50 -0700 Subject: [PATCH 036/179] Pack symbols in snupkg --- LibGit2Sharp/LibGit2Sharp.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index bb64842f3..fab3ab541 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -12,6 +12,8 @@ true true $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + snupkg true ..\libgit2sharp.snk From ae053953704709c56050a70e37712580ea46c55c Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 8 Feb 2020 13:41:42 -0700 Subject: [PATCH 037/179] Trim down scripts This removes scripts that came from Library.Template that don't really apply to libgit2sharp, or could be added later as their own focused change. --- azure-pipelines.yml | 11 +--- azure-pipelines/Convert-PDB.ps1 | 37 ------------- azure-pipelines/Get-NuGetTool.ps1 | 22 -------- azure-pipelines/Get-TempToolsPath.ps1 | 13 ----- azure-pipelines/Get-nbgv.ps1 | 24 --------- azure-pipelines/build.yml | 14 ----- azure-pipelines/dotnet.yml | 16 ------ azure-pipelines/install-dependencies.yml | 6 --- azure-pipelines/justnugetorg.nuget.config | 7 --- azure-pipelines/publish-codecoverage.yml | 2 +- azure-pipelines/variables/_all.ps1 | 11 ---- azure-pipelines/variables/_pipelines.ps1 | 19 ------- init.ps1 | 1 - tools/Install-NuGetCredProvider.ps1 | 66 ----------------------- 14 files changed, 3 insertions(+), 246 deletions(-) delete mode 100644 azure-pipelines/Convert-PDB.ps1 delete mode 100644 azure-pipelines/Get-NuGetTool.ps1 delete mode 100644 azure-pipelines/Get-TempToolsPath.ps1 delete mode 100644 azure-pipelines/Get-nbgv.ps1 delete mode 100644 azure-pipelines/justnugetorg.nuget.config delete mode 100644 azure-pipelines/variables/_all.ps1 delete mode 100644 azure-pipelines/variables/_pipelines.ps1 delete mode 100644 tools/Install-NuGetCredProvider.ps1 diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f6b8ab2c2..c25545a56 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,13 +1,6 @@ trigger: - branches: - include: - - master - - 'maint.*' - paths: - exclude: - - doc/ - - '*.md' - - .vscode/ +- master +- maint/* variables: TreatWarningsAsErrors: true diff --git a/azure-pipelines/Convert-PDB.ps1 b/azure-pipelines/Convert-PDB.ps1 deleted file mode 100644 index 6efd380ee..000000000 --- a/azure-pipelines/Convert-PDB.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -<# -.SYNOPSIS - Converts between Windows PDB and Portable PDB formats. -.PARAMETER DllPath - The path to the DLL whose PDB is to be converted. -.PARAMETER PdbPath - The path to the PDB to convert. May be omitted if the DLL was compiled on this machine and the PDB is still at its original path. -.PARAMETER OutputPath - The path of the output PDB to write. -#> -#Function Convert-PortableToWindowsPDB() { - Param( - [Parameter(Mandatory=$true,Position=0)] - [string]$DllPath, - [Parameter()] - [string]$PdbPath, - [Parameter(Mandatory=$true,Position=1)] - [string]$OutputPath - ) - - $version = '1.1.0-beta2-19516-01' - $baseDir = "$PSScriptRoot\..\obj\tools" - $pdb2pdbpath = "$baseDir\pdb2pdb.$version\tools\Pdb2Pdb.exe" - if (-not (Test-Path $pdb2pdbpath)) { - if (-not (Test-Path $baseDir)) { New-Item -Type Directory -Path $baseDir | Out-Null } - $baseDir = (Resolve-Path $baseDir).Path # Normalize it - & (& $PSScriptRoot\Get-NuGetTool.ps1) install pdb2pdb -version $version -PackageSaveMode nuspec -OutputDirectory $baseDir -Source https://dotnet.myget.org/F/symreader-converter/api/v3/index.json | Out-Null - } - - $args = $DllPath,'/out',$OutputPath,'/nowarn','0021' - if ($PdbPath) { - $args += '/pdb',$PdbPath - } - - Write-Verbose "$pdb2pdbpath $args" - & $pdb2pdbpath $args -#} diff --git a/azure-pipelines/Get-NuGetTool.ps1 b/azure-pipelines/Get-NuGetTool.ps1 deleted file mode 100644 index 4431adb91..000000000 --- a/azure-pipelines/Get-NuGetTool.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -<# -.SYNOPSIS - Downloads the NuGet.exe tool and returns the path to it. -.PARAMETER NuGetVersion - The version of the NuGet tool to acquire. -#> -Param( - [Parameter()] - [string]$NuGetVersion='5.2.0' -) - -$toolsPath = & "$PSScriptRoot\Get-TempToolsPath.ps1" -$binaryToolsPath = Join-Path $toolsPath $NuGetVersion -if (!(Test-Path $binaryToolsPath)) { $null = mkdir $binaryToolsPath } -$nugetPath = Join-Path $binaryToolsPath nuget.exe - -if (!(Test-Path $nugetPath)) { - Write-Host "Downloading nuget.exe $NuGetVersion..." -ForegroundColor Yellow - (New-Object System.Net.WebClient).DownloadFile("https://dist.nuget.org/win-x86-commandline/v$NuGetVersion/NuGet.exe", $nugetPath) -} - -return (Resolve-Path $nugetPath).Path diff --git a/azure-pipelines/Get-TempToolsPath.ps1 b/azure-pipelines/Get-TempToolsPath.ps1 deleted file mode 100644 index bb3da8e33..000000000 --- a/azure-pipelines/Get-TempToolsPath.ps1 +++ /dev/null @@ -1,13 +0,0 @@ -if ($env:AGENT_TEMPDIRECTORY) { - $path = "$env:AGENT_TEMPDIRECTORY\$env:BUILD_BUILDID" -} elseif ($env:localappdata) { - $path = "$env:localappdata\gitrepos\tools" -} else { - $path = "$PSScriptRoot\..\obj\tools" -} - -if (!(Test-Path $path)) { - New-Item -ItemType Directory -Path $Path | Out-Null -} - -(Resolve-Path $path).Path diff --git a/azure-pipelines/Get-nbgv.ps1 b/azure-pipelines/Get-nbgv.ps1 deleted file mode 100644 index a5be2cf7c..000000000 --- a/azure-pipelines/Get-nbgv.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -<# -.SYNOPSIS - Gets the path to the nbgv CLI tool, installing it if necessary. -#> -Param( -) - -$existingTool = Get-Command "nbgv" -ErrorAction SilentlyContinue -if ($existingTool) { - return $existingTool.Path -} - -$toolInstallDir = & "$PSScriptRoot/Get-TempToolsPath.ps1" - -$toolPath = "$toolInstallDir/nbgv" -if (!(Test-Path $toolInstallDir)) { New-Item -Path $toolInstallDir -ItemType Directory | Out-Null } - -if (!(Get-Command $toolPath -ErrorAction SilentlyContinue)) { - Write-Host "Installing nbgv to $toolInstallDir" - dotnet tool install --tool-path "$toolInstallDir" nbgv --configfile "$PSScriptRoot/justnugetorg.nuget.config" | Out-Null -} - -# Normalize the path on the way out. -return (Get-Command $toolPath).Path diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml index e5e6f479d..1462628c8 100644 --- a/azure-pipelines/build.yml +++ b/azure-pipelines/build.yml @@ -5,21 +5,13 @@ jobs: - job: Windows pool: ${{ parameters.windowsPool }} steps: - - checkout: self - clean: true - template: install-dependencies.yml - - - powershell: '& (./azure-pipelines/Get-nbgv.ps1) cloud' - displayName: Set build number - - template: dotnet.yml - job: Linux pool: vmImage: Ubuntu 18.04 steps: - - checkout: self - clean: true - template: install-dependencies.yml - template: dotnet.yml @@ -27,8 +19,6 @@ jobs: pool: vmImage: macOS 10.13 steps: - - checkout: self - clean: true - template: install-dependencies.yml - template: dotnet.yml @@ -41,8 +31,6 @@ jobs: vmImage: Ubuntu 18.04 condition: succeededOrFailed() steps: - - checkout: self - clean: true - template: install-dependencies.yml parameters: initArgs: -NoRestore @@ -53,8 +41,6 @@ jobs: pool: vmImage: Ubuntu 18.04 steps: - - checkout: self - clean: true - template: install-dependencies.yml - task: DotNetCoreCLI@2 displayName: dotnet test -f netcoreapp2.1 diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index 35aa8c979..8c9f5f909 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -29,13 +29,6 @@ steps: arguments: --no-build -c $(BuildConfiguration) -f netcoreapp2.1 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true testRunTitle: netcoreapp2.1-$(Agent.JobName) -- task: PowerShell@2 - inputs: - filePath: azure-pipelines/variables/_pipelines.ps1 - failOnStderr: true - displayName: Update pipeline variables based on build outputs - condition: succeededOrFailed() - - task: PowerShell@2 inputs: filePath: azure-pipelines/artifacts/_pipelines.ps1 @@ -43,15 +36,6 @@ steps: displayName: Publish artifacts condition: succeededOrFailed() -- task: PublishSymbols@2 - inputs: - SymbolsFolder: $(Build.ArtifactStagingDirectory)/symbols-Windows - SearchPattern: '**/*.pdb' - IndexSources: false - SymbolServerType: TeamServices - displayName: Publish symbols to symbol server - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Agent.OS'], 'Windows_NT')) - - bash: bash <(curl -s https://codecov.io/bash) displayName: Publish code coverage results to codecov.io timeoutInMinutes: 3 diff --git a/azure-pipelines/install-dependencies.yml b/azure-pipelines/install-dependencies.yml index 9257db852..5b008c6e8 100644 --- a/azure-pipelines/install-dependencies.yml +++ b/azure-pipelines/install-dependencies.yml @@ -7,9 +7,3 @@ steps: .\init.ps1 -AccessToken '$(System.AccessToken)' ${{ parameters['initArgs'] }} -UpgradePrerequisites dotnet --info displayName: Install prerequisites - -- task: PowerShell@2 - inputs: - filePath: azure-pipelines/variables/_pipelines.ps1 - failOnStderr: true - displayName: Set pipeline variables based on source diff --git a/azure-pipelines/justnugetorg.nuget.config b/azure-pipelines/justnugetorg.nuget.config deleted file mode 100644 index 765346e53..000000000 --- a/azure-pipelines/justnugetorg.nuget.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/azure-pipelines/publish-codecoverage.yml b/azure-pipelines/publish-codecoverage.yml index 6d367de96..59dba9d40 100644 --- a/azure-pipelines/publish-codecoverage.yml +++ b/azure-pipelines/publish-codecoverage.yml @@ -12,7 +12,7 @@ steps: displayName: Download macOS code coverage results continueOnError: true - powershell: | - dotnet tool install --tool-path obj dotnet-reportgenerator-globaltool --version 4.2.2 --configfile azure-pipelines/justnugetorg.nuget.config + dotnet tool install --tool-path obj dotnet-reportgenerator-globaltool --version 4.2.2 Copy-Item -Recurse $(Pipeline.Workspace)/coverageResults-Windows/obj/* $(System.DefaultWorkingDirectory)/obj Write-Host "Substituting {reporoot} with $(System.DefaultWorkingDirectory)" $reports = Get-ChildItem -Recurse "$(Pipeline.Workspace)/coverage.cobertura.xml" diff --git a/azure-pipelines/variables/_all.ps1 b/azure-pipelines/variables/_all.ps1 deleted file mode 100644 index ed0997922..000000000 --- a/azure-pipelines/variables/_all.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -# This script returns a hashtable of build variables that should be set -# at the start of a build or release definition's execution. - -$vars = @{} - -Get-ChildItem "$PSScriptRoot\*.ps1" -Exclude "_*" |% { - Write-Host "Computing $($_.BaseName) variable" - $vars[$_.BaseName] = & $_ -} - -$vars diff --git a/azure-pipelines/variables/_pipelines.ps1 b/azure-pipelines/variables/_pipelines.ps1 deleted file mode 100644 index 28230b817..000000000 --- a/azure-pipelines/variables/_pipelines.ps1 +++ /dev/null @@ -1,19 +0,0 @@ -# This script translates the variables returned by the _all.ps1 script -# into commands that instruct Azure Pipelines to actually set those variables for other pipeline tasks to consume. - -# The build or release definition may have set these variables to override -# what the build would do. So only set them if they have not already been set. - -(& "$PSScriptRoot\_all.ps1").GetEnumerator() |% { - if (Test-Path -Path "env:$($_.Key)") { - Write-Host "Skipping setting $($_.Key) because variable is already set." -ForegroundColor Cyan - } else { - Write-Host "$($_.Key)=$($_.Value)" -ForegroundColor Yellow - if ($env:TF_BUILD) { - Write-Host "##vso[task.setvariable variable=$($_.Key);]$($_.Value)" - } elseif ($env:GITHUB_ACTIONS) { - Write-Host "::set-env name=$($_.Key)::$($_.Value)" - } - Set-Item -Path "env:$($_.Key)" -Value $_.Value - } -} diff --git a/init.ps1 b/init.ps1 index 33140ac5e..907d85a5c 100644 --- a/init.ps1 +++ b/init.ps1 @@ -38,7 +38,6 @@ Param ( ) if (!$NoPrerequisites) { - & "$PSScriptRoot\tools\Install-NuGetCredProvider.ps1" -AccessToken $AccessToken -Force:$UpgradePrerequisites & "$PSScriptRoot\tools\Install-DotNetSdk.ps1" -InstallLocality $InstallLocality } diff --git a/tools/Install-NuGetCredProvider.ps1 b/tools/Install-NuGetCredProvider.ps1 deleted file mode 100644 index 0a8d77f62..000000000 --- a/tools/Install-NuGetCredProvider.ps1 +++ /dev/null @@ -1,66 +0,0 @@ -<# -.SYNOPSIS - Downloads and installs the Microsoft Artifacts Credential Provider - from https://github.com/microsoft/artifacts-credprovider - to assist in authenticating to Azure Artifact feeds in interactive development - or unattended build agents. -.PARAMETER Force - Forces install of the CredProvider plugin even if one already exists. This is useful to upgrade an older version. -.PARAMETER AccessToken - An optional access token for authenticating to Azure Artifacts authenticated feeds. -#> -[CmdletBinding()] -Param ( - [Parameter()] - [switch]$Force, - [Parameter()] - [string]$AccessToken -) - -$toolsPath = & "$PSScriptRoot\..\azure-pipelines\Get-TempToolsPath.ps1" - -if ($IsMacOS -or $IsLinux) { - $installerScript = "installcredprovider.sh" - $sourceUrl = "https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh" -} else { - $installerScript = "installcredprovider.ps1" - $sourceUrl = "https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.ps1" -} - -$installerScript = Join-Path $toolsPath $installerScript - -if (!(Test-Path $installerScript)) { - Invoke-WebRequest $sourceUrl -OutFile $installerScript -} - -$installerScript = (Resolve-Path $installerScript).Path - -if ($IsMacOS -or $IsLinux) { - chmod u+x $installerScript -} - -& $installerScript -Force:$Force - -if ($AccessToken) { - $endpoints = @() - - $nugetConfig = [xml](Get-Content -Path "$PSScriptRoot\..\nuget.config") - - $nugetConfig.configuration.packageSources.add |? { ($_.value -match '^https://pkgs\.dev\.azure\.com/') -or ($_.value -match '^https://[\w\-]+\.pkgs\.visualstudio\.com/') } |% { - $endpoint = New-Object -TypeName PSObject - Add-Member -InputObject $endpoint -MemberType NoteProperty -Name endpoint -Value $_.value - Add-Member -InputObject $endpoint -MemberType NoteProperty -Name username -Value ado - Add-Member -InputObject $endpoint -MemberType NoteProperty -Name password -Value $AccessToken - $endpoints += $endpoint - } - - $auth = New-Object -TypeName PSObject - Add-Member -InputObject $auth -MemberType NoteProperty -Name endpointCredentials -Value $endpoints - - $authJson = ConvertTo-Json -InputObject $auth - $envVars = @{ - 'VSS_NUGET_EXTERNAL_FEED_ENDPOINTS'=$authJson; - } - - & "$PSScriptRoot\..\azure-pipelines\Set-EnvVars.ps1" -Variables $envVars | Out-Null -} From 5f47dac80ec65f02a190a1f9a3807dbd29346cab Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 15 Feb 2020 14:09:33 -0700 Subject: [PATCH 038/179] Link to embedded license --- LibGit2Sharp/LibGit2Sharp.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index c14a1abdd..ede588064 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -15,15 +15,15 @@ true ..\libgit2sharp.snk square-logo.png - MIT + App_Readme/LICENSE.md - - - + + + From 369a98b6e1d5ade348cb136c356ff212d5070299 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 15 Feb 2020 20:40:02 -0700 Subject: [PATCH 039/179] Remove buildandtest scripts --- buildandtest.cmd | 39 --------------------------------------- buildandtest.sh | 21 --------------------- 2 files changed, 60 deletions(-) delete mode 100644 buildandtest.cmd delete mode 100755 buildandtest.sh diff --git a/buildandtest.cmd b/buildandtest.cmd deleted file mode 100644 index 612161b87..000000000 --- a/buildandtest.cmd +++ /dev/null @@ -1,39 +0,0 @@ -@ECHO OFF - -REM Sample usages: -REM -REM Building and running tests -REM - buildandtest.cmd -REM -REM Building and identifying potential leaks while running tests -REM - buildandtest.cmd "LEAKS_IDENTIFYING" - -SETLOCAL - -SET EXTRADEFINE=%~1 - -where dotnet 1>nul 2>nul -IF ERRORLEVEL 1 ( - ECHO Cannot find dotnet.exe. Run from a VS2017 Developer Prompt. - EXIT /B 1 -) - -ECHO ON - -SET Configuration=Release - -:: Restore packages -dotnet restore "%~dp0\" -@IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% - -:: Build -dotnet build "%~dp0\" /v:minimal /nologo /property:ExtraDefine="%EXTRADEFINE%" -@IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% - -:: Run tests on Desktop and CoreCLR -"%userprofile%\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net46\LibGit2Sharp.Tests.dll" -noshadow -@IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% -dotnet test "%~dp0LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj" -f netcoreapp2.1 --no-restore --no-build -@IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% - -EXIT /B %ERRORLEVEL% diff --git a/buildandtest.sh b/buildandtest.sh deleted file mode 100755 index 24994cdae..000000000 --- a/buildandtest.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -set -e - -EXTRADEFINE="$1" - -# Setting LD_LIBRARY_PATH to the current working directory is needed to run -# the tests successfully in linux. Without this, mono can't find libgit when -# the libgit2sharp assembly has been shadow copied. OS X includes the current -# working directory in its library search path, so it works without this value. -export LD_LIBRARY_PATH=. - -# Build release for the code generator and the product itself. -export Configuration=release - -# On linux we don't pack because we can't build for net40. -# We just build for CoreCLR and run tests for it. -dotnet restore -dotnet build LibGit2Sharp.Tests -f netcoreapp2.1 -property:ExtraDefine="$EXTRADEFINE" -fl -flp:verbosity=detailed -dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.1 --no-restore --no-build - -exit $? From f9bded441ec51fde5c9e3a9c5ee4fc270db128f2 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 7 Oct 2018 18:48:34 +0100 Subject: [PATCH 040/179] Use custom HTTPS transport --- .../Core/ManagedHttpSmartSubtransport.cs | 222 ++++++++++++++++++ LibGit2Sharp/Core/NativeMethods.cs | 18 +- 2 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs new file mode 100644 index 000000000..6ded7cd7e --- /dev/null +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -0,0 +1,222 @@ +using System; +using System.IO; +using System.Net; + +namespace LibGit2Sharp.Core +{ + internal class ManagedHttpSmartSubtransport : RpcSmartSubtransport + { + protected override SmartSubtransportStream Action(string url, GitSmartSubtransportAction action) + { + string endpointUrl, contentType = null; + bool isPost = false; + + switch (action) + { + case GitSmartSubtransportAction.UploadPackList: + endpointUrl = string.Concat(url, "/info/refs?service=git-upload-pack"); + break; + + case GitSmartSubtransportAction.UploadPack: + endpointUrl = string.Concat(url, "/git-upload-pack"); + contentType = "application/x-git-upload-pack-request"; + isPost = true; + break; + + case GitSmartSubtransportAction.ReceivePackList: + endpointUrl = string.Concat(url, "/info/refs?service=git-receive-pack"); + break; + + case GitSmartSubtransportAction.ReceivePack: + endpointUrl = string.Concat(url, "/git-receive-pack"); + contentType = "application/x-git-receive-pack-request"; + isPost = true; + break; + + default: + throw new InvalidOperationException(); + } + + return new ManagedHttpSmartSubtransportStream(this, endpointUrl, isPost, contentType); + } + + private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream + { + private static int MAX_REDIRECTS = 7; + + private MemoryStream postBuffer = new MemoryStream(); + private Stream responseStream; + + public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, string endpointUrl, bool isPost, string contentType) + : base(parent) + { + EndpointUrl = endpointUrl; + IsPost = isPost; + ContentType = contentType; + } + + private string EndpointUrl + { + get; + set; + } + + private bool IsPost + { + get; + set; + } + + private string ContentType + { + get; + set; + } + + public override int Write(Stream dataStream, long length) + { + byte[] buffer = new byte[4096]; + long writeTotal = 0; + + while (length > 0) + { + int readLen = dataStream.Read(buffer, 0, (int)Math.Min(buffer.Length, length)); + + if (readLen == 0) + { + break; + } + + postBuffer.Write(buffer, 0, readLen); + length -= readLen; + writeTotal += readLen; + } + + if (writeTotal < length) + { + throw new EndOfStreamException("Could not write buffer (short read)"); + } + + return 0; + } + + private static HttpWebRequest CreateWebRequest(string endpointUrl, bool isPost, string contentType) + { + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + + HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(endpointUrl); + webRequest.UserAgent = "git/1.0 (libgit2 custom transport)"; + webRequest.ServicePoint.Expect100Continue = false; + webRequest.AllowAutoRedirect = false; + + if (isPost) + { + webRequest.Method = "POST"; + webRequest.ContentType = contentType; + } + + return webRequest; + } + + private HttpWebResponse GetResponseWithRedirects() + { + HttpWebRequest request = CreateWebRequest(EndpointUrl, IsPost, ContentType); + HttpWebResponse response = null; + int retries; + + for (retries = 0; ; retries++) + { + if (retries > MAX_REDIRECTS) + { + throw new Exception("too many redirects or authentication replays"); + } + + if (IsPost && postBuffer.Length > 0) + { + postBuffer.Seek(0, SeekOrigin.Begin); + + using (Stream requestStream = request.GetRequestStream()) + { + postBuffer.WriteTo(requestStream); + } + } + + try + { + response = (HttpWebResponse)request.GetResponse(); + } + catch (WebException ex) + { + response = (HttpWebResponse)ex.Response; + } + + if (response.StatusCode == HttpStatusCode.OK) + { + break; + } + else if (response.StatusCode == HttpStatusCode.Unauthorized) + { + Credentials cred; + int ret = SmartTransport.AcquireCredentials(out cred, null, typeof(UsernamePasswordCredentials)); + + if (ret != 0) + { + throw new InvalidOperationException("authentication cancelled"); + } + + request = CreateWebRequest(EndpointUrl, IsPost, ContentType); + UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; + request.Credentials = new NetworkCredential(userpass.Username, userpass.Password); + continue; + } + else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) + { + request = CreateWebRequest(response.Headers["Location"], IsPost, ContentType); + continue; + } + + throw new Exception(string.Format("unexpected HTTP response: {0}", response.StatusCode)); + } + + return response; + } + + public override int Read(Stream dataStream, long length, out long readTotal) + { + byte[] buffer = new byte[4096]; + readTotal = 0; + + if (responseStream == null) + { + HttpWebResponse response = GetResponseWithRedirects(); + responseStream = response.GetResponseStream(); + } + + while (length > 0) + { + int readLen = responseStream.Read(buffer, 0, (int)Math.Min(buffer.Length, length)); + + if (readLen == 0) + break; + + dataStream.Write(buffer, 0, readLen); + readTotal += readLen; + length -= readLen; + } + + return 0; + } + + protected override void Free() + { + if (responseStream != null) + { + responseStream.Dispose(); + responseStream = null; + } + + base.Free(); + } + } + } +} diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 219615f11..1e368b291 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -26,6 +26,9 @@ internal static class NativeMethods private static NativeShutdownObject shutdownObject; #pragma warning restore 0414 + private static SmartSubtransportRegistration httpSubtransportRegistration; + private static SmartSubtransportRegistration httpsSubtransportRegistration; + static NativeMethods() { if (Platform.IsRunningOnNetFramework() || Platform.IsRunningOnNetCore()) @@ -199,10 +202,11 @@ private static void InitializeNativeLibrary() shutdownObject = new NativeShutdownObject(); } - // Configure the OpenSSL locking on the first initialization of the library in the current process. + // Configure the .NET HTTP(S) mechanism on the first initialization of the library in the current process. if (initCounter == 1) { - git_openssl_set_locking(); + httpSubtransportRegistration = GlobalSettings.RegisterSmartSubtransport("http"); + httpsSubtransportRegistration = GlobalSettings.RegisterSmartSubtransport("https"); } } @@ -211,6 +215,16 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject { ~NativeShutdownObject() { + if (httpSubtransportRegistration != null) + { + GlobalSettings.UnregisterSmartSubtransport(httpSubtransportRegistration); + } + + if (httpsSubtransportRegistration != null) + { + GlobalSettings.UnregisterSmartSubtransport(httpsSubtransportRegistration); + } + git_libgit2_shutdown(); } } From dc22039d6af54f67d253f7718ff4da2d37402f25 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 14 Oct 2018 07:23:29 -0700 Subject: [PATCH 041/179] Exceptions: refactor native exceptions to include code Include the error code as a first-class citizen of exceptions that correspond to libgit2 errors. Previously, we would store the error code in exception data when creating the exception from a libgit2 native error. However, we may also want to _generate_ these exceptions and have them converted to a libgit2 error. (For example, a callback may want to return GIT_EUSER, and so throw a `UserCancelledException`.) Therefore, provide exceptions with knowledge of their corresponding libgit2 error code so that we can round-trip that data. --- .../AmbiguousSpecificationException.cs | 11 ++++- LibGit2Sharp/BareRepositoryException.cs | 14 ++++-- LibGit2Sharp/CheckoutConflictException.cs | 14 ++++-- LibGit2Sharp/Core/Ensure.cs | 30 ++++++------ LibGit2Sharp/InvalidSpecificationException.cs | 14 ++++-- LibGit2Sharp/LibGit2SharpException.cs | 6 --- LibGit2Sharp/LockedFileException.cs | 14 ++++-- LibGit2Sharp/NameConflictException.cs | 14 ++++-- LibGit2Sharp/NativeException.cs | 46 +++++++++++++++++++ LibGit2Sharp/NonFastForwardException.cs | 14 ++++-- LibGit2Sharp/NotFoundException.cs | 14 ++++-- LibGit2Sharp/PeelException.cs | 14 ++++-- LibGit2Sharp/UnmergedIndexEntriesException.cs | 14 ++++-- LibGit2Sharp/UserCanceledException.cs | 14 ++++-- 14 files changed, 181 insertions(+), 52 deletions(-) create mode 100644 LibGit2Sharp/NativeException.cs diff --git a/LibGit2Sharp/AmbiguousSpecificationException.cs b/LibGit2Sharp/AmbiguousSpecificationException.cs index 1d19bbfde..16c77f6df 100644 --- a/LibGit2Sharp/AmbiguousSpecificationException.cs +++ b/LibGit2Sharp/AmbiguousSpecificationException.cs @@ -1,3 +1,4 @@ +using LibGit2Sharp.Core; using System; using System.Runtime.Serialization; @@ -7,7 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown when the provided specification cannot uniquely identify a reference, an object or a path. /// [Serializable] - public class AmbiguousSpecificationException : LibGit2SharpException + public class AmbiguousSpecificationException : NativeException { /// /// Initializes a new instance of the class. @@ -50,5 +51,13 @@ public AmbiguousSpecificationException(string message, Exception innerException) protected AmbiguousSpecificationException(SerializationInfo info, StreamingContext context) : base(info, context) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.Ambiguous; + } + } } } diff --git a/LibGit2Sharp/BareRepositoryException.cs b/LibGit2Sharp/BareRepositoryException.cs index 75ad9695c..7ee830a0c 100644 --- a/LibGit2Sharp/BareRepositoryException.cs +++ b/LibGit2Sharp/BareRepositoryException.cs @@ -9,7 +9,7 @@ namespace LibGit2Sharp /// working directory is performed against a bare repository. /// [Serializable] - public class BareRepositoryException : LibGit2SharpException + public class BareRepositoryException : NativeException { /// /// Initializes a new instance of the class. @@ -52,8 +52,16 @@ protected BareRepositoryException(SerializationInfo info, StreamingContext conte : base(info, context) { } - internal BareRepositoryException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal BareRepositoryException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.BareRepo; + } + } } } diff --git a/LibGit2Sharp/CheckoutConflictException.cs b/LibGit2Sharp/CheckoutConflictException.cs index a06360afb..f2f5092e9 100644 --- a/LibGit2Sharp/CheckoutConflictException.cs +++ b/LibGit2Sharp/CheckoutConflictException.cs @@ -10,7 +10,7 @@ namespace LibGit2Sharp /// in the working directory. /// [Serializable] - public class CheckoutConflictException : LibGit2SharpException + public class CheckoutConflictException : NativeException { /// /// Initializes a new instance of the class. @@ -53,8 +53,16 @@ protected CheckoutConflictException(SerializationInfo info, StreamingContext con : base(info, context) { } - internal CheckoutConflictException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal CheckoutConflictException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.Conflict; + } + } } } diff --git a/LibGit2Sharp/Core/Ensure.cs b/LibGit2Sharp/Core/Ensure.cs index 261794b0a..3cf03d24b 100644 --- a/LibGit2Sharp/Core/Ensure.cs +++ b/LibGit2Sharp/Core/Ensure.cs @@ -114,20 +114,20 @@ public static void ArgumentIsExpectedIntPtr(IntPtr argumentValue, IntPtr expecte } } - private static readonly Dictionary> + private static readonly Dictionary> GitErrorsToLibGit2SharpExceptions = - new Dictionary> + new Dictionary> { - { GitErrorCode.User, (m, r, c) => new UserCancelledException(m, r, c) }, - { GitErrorCode.BareRepo, (m, r, c) => new BareRepositoryException(m, r, c) }, - { GitErrorCode.Exists, (m, r, c) => new NameConflictException(m, r, c) }, - { GitErrorCode.InvalidSpecification, (m, r, c) => new InvalidSpecificationException(m, r, c) }, - { GitErrorCode.UnmergedEntries, (m, r, c) => new UnmergedIndexEntriesException(m, r, c) }, - { GitErrorCode.NonFastForward, (m, r, c) => new NonFastForwardException(m, r, c) }, - { GitErrorCode.Conflict, (m, r, c) => new CheckoutConflictException(m, r, c) }, - { GitErrorCode.LockedFile, (m, r, c) => new LockedFileException(m, r, c) }, - { GitErrorCode.NotFound, (m, r, c) => new NotFoundException(m, r, c) }, - { GitErrorCode.Peel, (m, r, c) => new PeelException(m, r, c) }, + { GitErrorCode.User, (m, c) => new UserCancelledException(m, c) }, + { GitErrorCode.BareRepo, (m, c) => new BareRepositoryException(m, c) }, + { GitErrorCode.Exists, (m, c) => new NameConflictException(m, c) }, + { GitErrorCode.InvalidSpecification, (m, c) => new InvalidSpecificationException(m, c) }, + { GitErrorCode.UnmergedEntries, (m, c) => new UnmergedIndexEntriesException(m, c) }, + { GitErrorCode.NonFastForward, (m, c) => new NonFastForwardException(m, c) }, + { GitErrorCode.Conflict, (m, c) => new CheckoutConflictException(m, c) }, + { GitErrorCode.LockedFile, (m, c) => new LockedFileException(m, c) }, + { GitErrorCode.NotFound, (m, c) => new NotFoundException(m, c) }, + { GitErrorCode.Peel, (m, c) => new PeelException(m, c) }, }; private static unsafe void HandleError(int result) @@ -145,13 +145,13 @@ private static unsafe void HandleError(int result) errorMessage = LaxUtf8Marshaler.FromNative(error->Message); } - Func exceptionBuilder; + Func exceptionBuilder; if (!GitErrorsToLibGit2SharpExceptions.TryGetValue((GitErrorCode)result, out exceptionBuilder)) { - exceptionBuilder = (m, r, c) => new LibGit2SharpException(m, r, c); + exceptionBuilder = (m, c) => new LibGit2SharpException(m, c); } - throw exceptionBuilder(errorMessage, (GitErrorCode)result, errorCategory); + throw exceptionBuilder(errorMessage, errorCategory); } /// diff --git a/LibGit2Sharp/InvalidSpecificationException.cs b/LibGit2Sharp/InvalidSpecificationException.cs index 64654852c..3d34571a4 100644 --- a/LibGit2Sharp/InvalidSpecificationException.cs +++ b/LibGit2Sharp/InvalidSpecificationException.cs @@ -11,7 +11,7 @@ namespace LibGit2Sharp /// create a branch from a blob, or peeling a blob to a commit). /// [Serializable] - public class InvalidSpecificationException : LibGit2SharpException + public class InvalidSpecificationException : NativeException { /// /// Initializes a new instance of the class. @@ -54,8 +54,16 @@ protected InvalidSpecificationException(SerializationInfo info, StreamingContext : base(info, context) { } - internal InvalidSpecificationException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal InvalidSpecificationException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.InvalidSpecification; + } + } } } diff --git a/LibGit2Sharp/LibGit2SharpException.cs b/LibGit2Sharp/LibGit2SharpException.cs index e85dd638f..5d1c33f25 100644 --- a/LibGit2Sharp/LibGit2SharpException.cs +++ b/LibGit2Sharp/LibGit2SharpException.cs @@ -52,11 +52,5 @@ public LibGit2SharpException(string format, params object[] args) protected LibGit2SharpException(SerializationInfo info, StreamingContext context) : base(info, context) { } - - internal LibGit2SharpException(string message, GitErrorCode code, GitErrorCategory category) : this(message) - { - Data.Add("libgit2.code", (int)code); - Data.Add("libgit2.category", (int)category); - } } } diff --git a/LibGit2Sharp/LockedFileException.cs b/LibGit2Sharp/LockedFileException.cs index 05859503a..44fd65b02 100644 --- a/LibGit2Sharp/LockedFileException.cs +++ b/LibGit2Sharp/LockedFileException.cs @@ -8,7 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown attempting to open a locked file. /// [Serializable] - public class LockedFileException : LibGit2SharpException + public class LockedFileException : NativeException { /// /// Initializes a new instance of the class. @@ -51,8 +51,16 @@ protected LockedFileException(SerializationInfo info, StreamingContext context) : base(info, context) { } - internal LockedFileException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal LockedFileException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.LockedFile; + } + } } } diff --git a/LibGit2Sharp/NameConflictException.cs b/LibGit2Sharp/NameConflictException.cs index 815415729..0dcffc648 100644 --- a/LibGit2Sharp/NameConflictException.cs +++ b/LibGit2Sharp/NameConflictException.cs @@ -8,7 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown when a reference, a remote, a submodule... with the same name already exists in the repository /// [Serializable] - public class NameConflictException : LibGit2SharpException + public class NameConflictException : NativeException { /// /// Initializes a new instance of the class. @@ -51,8 +51,16 @@ protected NameConflictException(SerializationInfo info, StreamingContext context : base(info, context) { } - internal NameConflictException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal NameConflictException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.Exists; + } + } } } diff --git a/LibGit2Sharp/NativeException.cs b/LibGit2Sharp/NativeException.cs new file mode 100644 index 000000000..292372db7 --- /dev/null +++ b/LibGit2Sharp/NativeException.cs @@ -0,0 +1,46 @@ +using LibGit2Sharp.Core; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Runtime.Serialization; +using System.Text; + +namespace LibGit2Sharp +{ + /// + /// An exception thrown that corresponds to a libgit2 (native library) error. + /// + [Serializable] + public abstract class NativeException : LibGit2SharpException + { + /// + /// Needed for mocking purposes. + /// + protected NativeException() + { } + + internal NativeException(string message) + : base(message) + { } + + internal NativeException(string message, Exception innerException) + : base(message, innerException) + { } + + internal NativeException(string format, params object[] args) + : base(format, args) + { + } + + internal NativeException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + + internal NativeException(string message, GitErrorCategory category) : this(message) + { + Data.Add("libgit2.category", (int)category); + } + + internal abstract GitErrorCode ErrorCode { get; } + } +} diff --git a/LibGit2Sharp/NonFastForwardException.cs b/LibGit2Sharp/NonFastForwardException.cs index 487e8fd03..b5a858f47 100644 --- a/LibGit2Sharp/NonFastForwardException.cs +++ b/LibGit2Sharp/NonFastForwardException.cs @@ -9,7 +9,7 @@ namespace LibGit2Sharp /// against the remote without losing commits. /// [Serializable] - public class NonFastForwardException : LibGit2SharpException + public class NonFastForwardException : NativeException { /// /// Initializes a new instance of the class. @@ -52,8 +52,16 @@ protected NonFastForwardException(SerializationInfo info, StreamingContext conte : base(info, context) { } - internal NonFastForwardException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal NonFastForwardException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.NonFastForward; + } + } } } diff --git a/LibGit2Sharp/NotFoundException.cs b/LibGit2Sharp/NotFoundException.cs index 0e9b45bf3..f8c49cc91 100644 --- a/LibGit2Sharp/NotFoundException.cs +++ b/LibGit2Sharp/NotFoundException.cs @@ -8,7 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown attempting to reference a resource that does not exist. /// [Serializable] - public class NotFoundException : LibGit2SharpException + public class NotFoundException : NativeException { /// /// Initializes a new instance of the class. @@ -51,8 +51,16 @@ protected NotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { } - internal NotFoundException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal NotFoundException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.NotFound; + } + } } } diff --git a/LibGit2Sharp/PeelException.cs b/LibGit2Sharp/PeelException.cs index 09d6bdcc8..d7758d7c9 100644 --- a/LibGit2Sharp/PeelException.cs +++ b/LibGit2Sharp/PeelException.cs @@ -9,7 +9,7 @@ namespace LibGit2Sharp /// target type due to the object model. /// [Serializable] - public class PeelException : LibGit2SharpException + public class PeelException : NativeException { /// /// Initializes a new instance of the class. @@ -52,8 +52,16 @@ protected PeelException(SerializationInfo info, StreamingContext context) : base(info, context) { } - internal PeelException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal PeelException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.Peel; + } + } } } diff --git a/LibGit2Sharp/UnmergedIndexEntriesException.cs b/LibGit2Sharp/UnmergedIndexEntriesException.cs index 729882678..7594049b1 100644 --- a/LibGit2Sharp/UnmergedIndexEntriesException.cs +++ b/LibGit2Sharp/UnmergedIndexEntriesException.cs @@ -9,7 +9,7 @@ namespace LibGit2Sharp /// is performed against an index with unmerged entries /// [Serializable] - public class UnmergedIndexEntriesException : LibGit2SharpException + public class UnmergedIndexEntriesException : NativeException { /// /// Initializes a new instance of the class. @@ -52,8 +52,16 @@ protected UnmergedIndexEntriesException(SerializationInfo info, StreamingContext : base(info, context) { } - internal UnmergedIndexEntriesException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal UnmergedIndexEntriesException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.UnmergedEntries; + } + } } } diff --git a/LibGit2Sharp/UserCanceledException.cs b/LibGit2Sharp/UserCanceledException.cs index 41eebb29a..ba6458049 100644 --- a/LibGit2Sharp/UserCanceledException.cs +++ b/LibGit2Sharp/UserCanceledException.cs @@ -8,7 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown when an operation is canceled. /// [Serializable] - public class UserCancelledException : LibGit2SharpException + public class UserCancelledException : NativeException { /// /// Initializes a new instance of the class. @@ -51,8 +51,16 @@ protected UserCancelledException(SerializationInfo info, StreamingContext contex : base(info, context) { } - internal UserCancelledException(string message, GitErrorCode code, GitErrorCategory category) - : base(message, code, category) + internal UserCancelledException(string message, GitErrorCategory category) + : base(message, category) { } + + internal override GitErrorCode ErrorCode + { + get + { + return GitErrorCode.User; + } + } } } From 4381f705784d6209d55068e63da94f345d5c25e7 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 14 Oct 2018 07:26:37 -0700 Subject: [PATCH 042/179] ManagedHttpSmartSubtransport: provide certificate callbacks Provide certificate callback functionality when using the managed HTTP smart subtransport. --- LibGit2Sharp/CertificateX509.cs | 6 +++- .../Core/ManagedHttpSmartSubtransport.cs | 32 ++++++++++++++++--- LibGit2Sharp/SmartSubtransportStream.cs | 8 ++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/LibGit2Sharp/CertificateX509.cs b/LibGit2Sharp/CertificateX509.cs index 8de124b8f..da45eb43e 100644 --- a/LibGit2Sharp/CertificateX509.cs +++ b/LibGit2Sharp/CertificateX509.cs @@ -10,7 +10,6 @@ namespace LibGit2Sharp /// public class CertificateX509 : Certificate { - /// /// For mocking purposes /// @@ -30,6 +29,11 @@ internal unsafe CertificateX509(git_certificate_x509* cert) Certificate = new X509Certificate(data); } + internal CertificateX509(X509Certificate cert) + { + Certificate = cert; + } + internal unsafe IntPtr ToPointers(out IntPtr dataPtr) { var certData = Certificate.Export(X509ContentType.Cert); diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 6ded7cd7e..d9348eea8 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -1,6 +1,8 @@ using System; using System.IO; using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; namespace LibGit2Sharp.Core { @@ -50,12 +52,12 @@ private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, string endpointUrl, bool isPost, string contentType) : base(parent) { - EndpointUrl = endpointUrl; + EndpointUrl = new Uri(endpointUrl); IsPost = isPost; ContentType = contentType; } - private string EndpointUrl + private Uri EndpointUrl { get; set; @@ -100,7 +102,15 @@ public override int Write(Stream dataStream, long length) return 0; } - private static HttpWebRequest CreateWebRequest(string endpointUrl, bool isPost, string contentType) + private bool CertificateValidationProxy(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) + { + int ret = SmartTransport.CertificateCheck(new CertificateX509(cert), (errors == SslPolicyErrors.None), EndpointUrl.Host); + Ensure.ZeroResult(ret); + + return true; + } + + private HttpWebRequest CreateWebRequest(Uri endpointUrl, bool isPost, string contentType) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; @@ -108,6 +118,7 @@ private static HttpWebRequest CreateWebRequest(string endpointUrl, bool isPost, webRequest.UserAgent = "git/1.0 (libgit2 custom transport)"; webRequest.ServicePoint.Expect100Continue = false; webRequest.AllowAutoRedirect = false; + webRequest.ServerCertificateValidationCallback += CertificateValidationProxy; if (isPost) { @@ -147,7 +158,18 @@ private HttpWebResponse GetResponseWithRedirects() } catch (WebException ex) { - response = (HttpWebResponse)ex.Response; + if (ex.Response != null) + { + response = (HttpWebResponse)ex.Response; + } + else if (ex.InnerException != null) + { + throw ex.InnerException; + } + else + { + throw new Exception("unknown network failure"); + } } if (response.StatusCode == HttpStatusCode.OK) @@ -171,7 +193,7 @@ private HttpWebResponse GetResponseWithRedirects() } else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) { - request = CreateWebRequest(response.Headers["Location"], IsPost, ContentType); + request = CreateWebRequest(new Uri(response.Headers["Location"]), IsPost, ContentType); continue; } diff --git a/LibGit2Sharp/SmartSubtransportStream.cs b/LibGit2Sharp/SmartSubtransportStream.cs index eb3d23e5b..f2ba82b03 100644 --- a/LibGit2Sharp/SmartSubtransportStream.cs +++ b/LibGit2Sharp/SmartSubtransportStream.cs @@ -102,6 +102,7 @@ private unsafe static int Read( UIntPtr buf_size, out UIntPtr bytes_read) { + GitErrorCode errorCode = GitErrorCode.Error; bytes_read = UIntPtr.Zero; SmartSubtransportStream transportStream = @@ -124,6 +125,11 @@ private unsafe static int Read( return toReturn; } + catch (NativeException ex) + { + errorCode = ex.ErrorCode; + Proxy.giterr_set_str(GitErrorCategory.Net, ex); + } catch (Exception ex) { Proxy.git_error_set_str(GitErrorCategory.Net, ex); @@ -131,7 +137,7 @@ private unsafe static int Read( } } - return (int)GitErrorCode.Error; + return (int)errorCode; } private static unsafe int Write(IntPtr stream, IntPtr buffer, UIntPtr len) From 15d68e51ae779004c8b7aa5ecf2d8cfb6bd31bd7 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 14 Oct 2018 10:36:31 -0700 Subject: [PATCH 043/179] Managed HTTP transport: support user-agent --- .../Core/ManagedHttpSmartSubtransport.cs | 14 ++++++++- LibGit2Sharp/Core/NativeMethods.cs | 9 ++++++ LibGit2Sharp/Core/Proxy.cs | 31 +++++++++++++++++++ LibGit2Sharp/GlobalSettings.cs | 20 ++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index d9348eea8..2619137d7 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -110,12 +110,24 @@ private bool CertificateValidationProxy(object sender, X509Certificate cert, X50 return true; } + private string getUserAgent() + { + string userAgent = GlobalSettings.GetUserAgent(); + + if (string.IsNullOrEmpty(userAgent)) + { + userAgent = "LibGit2Sharp " + GlobalSettings.Version.InformationalVersion; + } + + return userAgent; + } + private HttpWebRequest CreateWebRequest(Uri endpointUrl, bool isPost, string contentType) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(endpointUrl); - webRequest.UserAgent = "git/1.0 (libgit2 custom transport)"; + webRequest.UserAgent = String.Format("git/2.0 ({0})", getUserAgent()); webRequest.ServicePoint.Expect100Continue = false; webRequest.AllowAutoRedirect = false; webRequest.ServerCertificateValidationCallback += CertificateValidationProxy; diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 1e368b291..71edf7d24 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -809,6 +809,15 @@ internal static extern int git_libgit2_opts(int option, uint level, // git_libgit2_opts(GIT_OPT_ENABLE_*, int enabled) [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_libgit2_opts(int option, int enabled); + + // git_libgit2_opts(GIT_OPT_SET_USER_AGENT, const char *path) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] + internal static extern int git_libgit2_opts(int option, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); + + // git_libgit2_opts(GIT_OPT_GET_USER_AGENT, git_buf *buf) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] + internal static extern int git_libgit2_opts(int option, GitBuf buf); #endregion [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index c3a53b95e..dd90e3889 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3456,6 +3456,37 @@ public static void git_libgit2_opts_set_enable_strictobjectcreation(bool enabled Ensure.ZeroResult(res); } + /// + /// Sets the user-agent string to be used by the HTTP(S) transport. + /// Note that "git/2.0" will be prepended for compatibility. + /// + /// The user-agent string to use + public static void git_libgit2_opts_set_user_agent(string userAgent) + { + var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetUserAgent, userAgent); + Ensure.ZeroResult(res); + } + + /// + /// Gets the user-agent string used by libgit2. + /// + /// The user-agent string. + /// + public static string git_libgit2_opts_get_user_agent() + { + string userAgent; + + using (var buf = new GitBuf()) + { + var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetUserAgent, buf); + Ensure.ZeroResult(res); + + userAgent = LaxUtf8Marshaler.FromNative(buf.ptr) ?? string.Empty; + } + + return userAgent; + } + #endregion #region git_worktree_ diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 8828cb883..954b90b16 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -386,5 +386,25 @@ public static void SetEnableStrictObjectCreation(bool enabled) { Proxy.git_libgit2_opts_set_enable_strictobjectcreation(enabled); } + + /// + /// Sets the user-agent string to be used by the HTTP(S) transport. + /// Note that "git/2.0" will be prepended for compatibility. + /// + /// The user-agent string to use + public static void SetUserAgent(string userAgent) + { + Proxy.git_libgit2_opts_set_user_agent(userAgent); + } + + /// + /// Gets the user-agent string used by libgit2. + /// + /// The user-agent string. + /// + public static string GetUserAgent() + { + return Proxy.git_libgit2_opts_get_user_agent(); + } } } From 9d7dd698da180fb9659d4e609c87e3c88727e22c Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 2 Nov 2018 14:16:21 +0000 Subject: [PATCH 044/179] Managed HTTP transport: allow custom transport Continue to allow a custom subtransport to override our own. --- LibGit2Sharp/Core/NativeMethods.cs | 8 +- LibGit2Sharp/GlobalSettings.cs | 123 ++++++++++++++++++ LibGit2Sharp/SmartSubtransport.cs | 2 +- LibGit2Sharp/SmartSubtransportRegistration.cs | 11 +- .../SmartSubtransportRegistrationData.cs | 21 +++ 5 files changed, 150 insertions(+), 15 deletions(-) create mode 100644 LibGit2Sharp/SmartSubtransportRegistrationData.cs diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 71edf7d24..b12000cac 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -205,8 +205,8 @@ private static void InitializeNativeLibrary() // Configure the .NET HTTP(S) mechanism on the first initialization of the library in the current process. if (initCounter == 1) { - httpSubtransportRegistration = GlobalSettings.RegisterSmartSubtransport("http"); - httpsSubtransportRegistration = GlobalSettings.RegisterSmartSubtransport("https"); + httpSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("http"); + httpsSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("https"); } } @@ -217,12 +217,12 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject { if (httpSubtransportRegistration != null) { - GlobalSettings.UnregisterSmartSubtransport(httpSubtransportRegistration); + GlobalSettings.UnregisterDefaultSmartSubtransport(httpSubtransportRegistration); } if (httpsSubtransportRegistration != null) { - GlobalSettings.UnregisterSmartSubtransport(httpsSubtransportRegistration); + GlobalSettings.UnregisterDefaultSmartSubtransport(httpsSubtransportRegistration); } git_libgit2_shutdown(); diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 954b90b16..51edc1c08 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -22,6 +22,14 @@ public static class GlobalSettings private static bool nativeLibraryPathLocked; private static string nativeLibraryDefaultPath; + internal class SmartSubtransportData + { + internal bool isCustom; + internal SmartSubtransportRegistrationData defaultSubtransport; + } + + private static readonly Dictionary smartSubtransportData = new Dictionary(); + static GlobalSettings() { bool netFX = Platform.IsRunningOnNetFramework(); @@ -79,6 +87,42 @@ public static Version Version } } + private static SmartSubtransportData GetOrCreateSmartSubtransportData(string scheme) + { + Ensure.ArgumentNotNull(scheme, "scheme"); + + lock (smartSubtransportData) + { + if (!smartSubtransportData.ContainsKey(scheme)) + { + smartSubtransportData[scheme] = new SmartSubtransportData(); + } + + return smartSubtransportData[scheme]; + } + } + + internal static SmartSubtransportRegistration RegisterDefaultSmartSubtransport(string scheme) + where T : SmartSubtransport, new() + { + Ensure.ArgumentNotNull(scheme, "scheme"); + + lock (smartSubtransportData) + { + var data = GetOrCreateSmartSubtransportData(scheme); + + if (data.defaultSubtransport != null) + { + throw new Exception(string.Format("A default subtransport is already configured for {0}", scheme)); + } + + var registration = RegisterSmartSubtransportInternal(scheme); + + data.defaultSubtransport = registration; + return registration; + } + } + /// /// Registers a new as a custom /// smart-protocol transport with libgit2. Any Git remote with @@ -96,8 +140,34 @@ public static Version Version public static SmartSubtransportRegistration RegisterSmartSubtransport(string scheme) where T : SmartSubtransport, new() { + SmartSubtransportRegistration registration; + Ensure.ArgumentNotNull(scheme, "scheme"); + lock (smartSubtransportData) + { + var data = GetOrCreateSmartSubtransportData(scheme); + + if (data.isCustom) + { + throw new EntryExistsException(string.Format("A smart subtransport is already registered for {0}", scheme)); + } + + if (data.defaultSubtransport != null) + { + Proxy.git_transport_unregister(scheme); + } + + registration = RegisterSmartSubtransportInternal(scheme); + data.isCustom = true; + } + + return registration; + } + + private static SmartSubtransportRegistration RegisterSmartSubtransportInternal(string scheme) + where T : SmartSubtransport, new() + { var registration = new SmartSubtransportRegistration(scheme); try @@ -126,6 +196,59 @@ public static void UnregisterSmartSubtransport(SmartSubtransportRegistration< { Ensure.ArgumentNotNull(registration, "registration"); + var scheme = registration.Scheme; + + lock (smartSubtransportData) + { + var data = GetOrCreateSmartSubtransportData(scheme); + + if (!data.isCustom) + { + throw new NotFoundException(string.Format("No smart subtransport has been registered for {0}", scheme)); + } + + UnregisterSmartSubtransportInternal(registration); + + data.isCustom = false; + + if (data.defaultSubtransport != null) + { + var defaultRegistration = data.defaultSubtransport; + + Proxy.git_transport_register(defaultRegistration.Scheme, + defaultRegistration.FunctionPointer, + defaultRegistration.RegistrationPointer); + } + } + } + + internal static void UnregisterDefaultSmartSubtransport(SmartSubtransportRegistration registration) + where T : SmartSubtransport, new() + { + Ensure.ArgumentNotNull(registration, "registration"); + + var scheme = registration.Scheme; + + lock (smartSubtransportData) + { + if (!smartSubtransportData.ContainsKey(scheme)) + { + throw new Exception(string.Format("No default smart subtransport has been registered for {0}", scheme)); + } + + if (registration != smartSubtransportData[scheme].defaultSubtransport) + { + throw new Exception(string.Format("The given smart subtransport is not the default for {0}", scheme)); + } + + smartSubtransportData.Remove(scheme); + UnregisterSmartSubtransportInternal(registration); + } + } + + private static void UnregisterSmartSubtransportInternal(SmartSubtransportRegistration registration) + where T : SmartSubtransport, new() + { Proxy.git_transport_unregister(registration.Scheme); registration.Free(); } diff --git a/LibGit2Sharp/SmartSubtransport.cs b/LibGit2Sharp/SmartSubtransport.cs index 8944a84c7..384e2b7a4 100644 --- a/LibGit2Sharp/SmartSubtransport.cs +++ b/LibGit2Sharp/SmartSubtransport.cs @@ -117,7 +117,7 @@ public int AcquireCredentials(out Credentials cred, string user, params Type[] m if (credHandle == IntPtr.Zero) { - throw new InvalidOperationException("creditals callback indicated success but returned no credentials"); + throw new InvalidOperationException("credentials callback indicated success but returned no credentials"); } unsafe diff --git a/LibGit2Sharp/SmartSubtransportRegistration.cs b/LibGit2Sharp/SmartSubtransportRegistration.cs index fd7cae961..d33887122 100644 --- a/LibGit2Sharp/SmartSubtransportRegistration.cs +++ b/LibGit2Sharp/SmartSubtransportRegistration.cs @@ -11,7 +11,7 @@ namespace LibGit2Sharp /// under a particular scheme (eg "http"). /// /// The type of SmartSubtransport to register - public sealed class SmartSubtransportRegistration + public sealed class SmartSubtransportRegistration : SmartSubtransportRegistrationData where T : SmartSubtransport, new() { /// @@ -26,15 +26,6 @@ internal SmartSubtransportRegistration(string scheme) FunctionPointer = CreateFunctionPointer(); } - /// - /// The URI scheme (eg "http") for this transport. - /// - public string Scheme { get; private set; } - - internal IntPtr RegistrationPointer { get; private set; } - - internal IntPtr FunctionPointer { get; private set; } - private IntPtr CreateRegistrationPointer() { var registration = new GitSmartSubtransportRegistration(); diff --git a/LibGit2Sharp/SmartSubtransportRegistrationData.cs b/LibGit2Sharp/SmartSubtransportRegistrationData.cs new file mode 100644 index 000000000..dbf612adb --- /dev/null +++ b/LibGit2Sharp/SmartSubtransportRegistrationData.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace LibGit2Sharp +{ + /// + /// Information about a smart subtransport registration. + /// + public abstract class SmartSubtransportRegistrationData + { + /// + /// The URI scheme for this transport, for example "http" or "ssh". + /// + public string Scheme { get; internal set; } + + internal IntPtr RegistrationPointer { get; set; } + + internal IntPtr FunctionPointer { get; set; } + } +} From 5a643495a42d1fc3590c23b5c74f500f0f8a1c84 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 6 Nov 2018 09:42:02 -0800 Subject: [PATCH 045/179] smart subtransports: improve safety Throwing an exception in a native callback is pointless; instead, carefully protect the entry points to return a native error code (-1) on failure. Wrap everything else in a try/catch to propagate error codes. --- LibGit2Sharp/SmartSubtransport.cs | 73 ++++++++++++++------- LibGit2Sharp/SmartSubtransportStream.cs | 84 ++++++++++++++----------- 2 files changed, 98 insertions(+), 59 deletions(-) diff --git a/LibGit2Sharp/SmartSubtransport.cs b/LibGit2Sharp/SmartSubtransport.cs index 384e2b7a4..f3c475882 100644 --- a/LibGit2Sharp/SmartSubtransport.cs +++ b/LibGit2Sharp/SmartSubtransport.cs @@ -81,6 +81,11 @@ public int CertificateCheck(Certificate cert, bool valid, string hostname) Marshal.FreeHGlobal(certPtr); } + if (ret > 0) + { + ret = valid ? 0 : -1; + } + return ret; } @@ -134,6 +139,12 @@ public int AcquireCredentials(out Credentials cred, string user, params Type[] m } } + /// + /// libgit2 will call an action back with a null url to indicate that + /// it should re-use the prior url; store the url so that we can replay. + /// + private string LastActionUrl { get; set; } + /// /// Invoked by libgit2 to create a connection using this subtransport. /// @@ -209,43 +220,57 @@ private static int Action( SmartSubtransport t = GCHandle.FromIntPtr(Marshal.ReadIntPtr(subtransport, GitSmartSubtransport.GCHandleOffset)).Target as SmartSubtransport; String urlAsString = LaxUtf8Marshaler.FromNative(url); - if (null != t && - !String.IsNullOrEmpty(urlAsString)) + if (t == null) { - try - { - stream = t.Action(urlAsString, action).GitSmartTransportStreamPointer; + Proxy.git_error_set_str(GitErrorCategory.Net, "no subtransport provided"); + return (int)GitErrorCode.Error; + } - return 0; - } - catch (Exception ex) - { - Proxy.git_error_set_str(GitErrorCategory.Net, ex); - } + if (String.IsNullOrEmpty(urlAsString)) + { + urlAsString = t.LastActionUrl; + } + + if (String.IsNullOrEmpty(urlAsString)) + { + Proxy.git_error_set_str(GitErrorCategory.Net, "no url provided"); + return (int)GitErrorCode.Error; } - return (int)GitErrorCode.Error; + try + { + stream = t.Action(urlAsString, action).GitSmartTransportStreamPointer; + t.LastActionUrl = urlAsString; + return 0; + } + catch (Exception ex) + { + Proxy.git_error_set_str(GitErrorCategory.Net, ex); + return (int)GitErrorCode.Error; + } } private static int Close(IntPtr subtransport) { SmartSubtransport t = GCHandle.FromIntPtr(Marshal.ReadIntPtr(subtransport, GitSmartSubtransport.GCHandleOffset)).Target as SmartSubtransport; - if (null != t) + if (t == null) { - try - { - t.Close(); - - return 0; - } - catch (Exception ex) - { - Proxy.git_error_set_str(GitErrorCategory.Net, ex); - } + Proxy.git_error_set_str(GitErrorCategory.Net, "no subtransport provided"); + return (int)GitErrorCode.Error; } - return (int)GitErrorCode.Error; + try + { + t.Close(); + + return 0; + } + catch (Exception ex) + { + Proxy.git_error_set_str(GitErrorCategory.Net, ex); + return (int)GitErrorCode.Error; + } } private static void Free(IntPtr subtransport) diff --git a/LibGit2Sharp/SmartSubtransportStream.cs b/LibGit2Sharp/SmartSubtransportStream.cs index f2ba82b03..a0d9accae 100644 --- a/LibGit2Sharp/SmartSubtransportStream.cs +++ b/LibGit2Sharp/SmartSubtransportStream.cs @@ -102,42 +102,48 @@ private unsafe static int Read( UIntPtr buf_size, out UIntPtr bytes_read) { - GitErrorCode errorCode = GitErrorCode.Error; bytes_read = UIntPtr.Zero; SmartSubtransportStream transportStream = GCHandle.FromIntPtr(Marshal.ReadIntPtr(stream, GitSmartSubtransportStream.GCHandleOffset)).Target as SmartSubtransportStream; - if (transportStream != null && - buf_size.ToUInt64() < (ulong)long.MaxValue) + if (transportStream == null) + { + Proxy.git_error_set_str(GitErrorCategory.Net, "no transport stream provided"); + return (int)GitErrorCode.Error; + } + + if (buf_size.ToUInt64() >= (ulong)long.MaxValue) + { + Proxy.git_error_set_str(GitErrorCategory.Net, "buffer size is too large"); + return (int)GitErrorCode.Error; + } + + try { using (UnmanagedMemoryStream memoryStream = new UnmanagedMemoryStream((byte*)buffer, 0, (long)buf_size.ToUInt64(), FileAccess.ReadWrite)) { - try - { - long longBytesRead; - - int toReturn = transportStream.Read(memoryStream, (long)buf_size.ToUInt64(), out longBytesRead); - - bytes_read = new UIntPtr((ulong)Math.Max(0, longBytesRead)); - - return toReturn; - } - catch (NativeException ex) - { - errorCode = ex.ErrorCode; - Proxy.giterr_set_str(GitErrorCategory.Net, ex); - } - catch (Exception ex) - { - Proxy.git_error_set_str(GitErrorCategory.Net, ex); - } + long longBytesRead; + + int toReturn = transportStream.Read(memoryStream, (long)buf_size.ToUInt64(), out longBytesRead); + + bytes_read = new UIntPtr((ulong)Math.Max(0, longBytesRead)); + + return toReturn; } } - - return (int)errorCode; + catch (NativeException ex) + { + Proxy.git_error_set_str(GitErrorCategory.Net, ex); + return (int)ex.ErrorCode; + } + catch (Exception ex) + { + Proxy.git_error_set_str(GitErrorCategory.Net, ex); + return (int)GitErrorCode.Error; + } } private static unsafe int Write(IntPtr stream, IntPtr buffer, UIntPtr len) @@ -145,24 +151,32 @@ private static unsafe int Write(IntPtr stream, IntPtr buffer, UIntPtr len) SmartSubtransportStream transportStream = GCHandle.FromIntPtr(Marshal.ReadIntPtr(stream, GitSmartSubtransportStream.GCHandleOffset)).Target as SmartSubtransportStream; - if (transportStream != null && len.ToUInt64() < (ulong)long.MaxValue) + if (transportStream == null) + { + Proxy.git_error_set_str(GitErrorCategory.Net, "no transport stream provided"); + return (int)GitErrorCode.Error; + } + + if (len.ToUInt64() >= (ulong)long.MaxValue) + { + Proxy.git_error_set_str(GitErrorCategory.Net, "write length is too large"); + return (int)GitErrorCode.Error; + } + + try { long length = (long)len.ToUInt64(); using (UnmanagedMemoryStream dataStream = new UnmanagedMemoryStream((byte*)buffer, length)) { - try - { - return transportStream.Write(dataStream, length); - } - catch (Exception ex) - { - Proxy.git_error_set_str(GitErrorCategory.Net, ex); - } + return transportStream.Write(dataStream, length); } } - - return (int)GitErrorCode.Error; + catch (Exception ex) + { + Proxy.git_error_set_str(GitErrorCategory.Net, ex); + return (int)GitErrorCode.Error; + } } private static void Free(IntPtr stream) From 7be9794bdb4953cd8ae78e7f638810907ee5f663 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 10 Nov 2018 17:22:13 +0000 Subject: [PATCH 046/179] Tests: Don't look for HTTPS in libgit2 We (may) explicitly remove HTTPS from libgit2. --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 55260a6f5..6026f267a 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -15,7 +15,6 @@ public void CanGetMinimumCompiledInFeatures() BuiltInFeatures features = GlobalSettings.Version.Features; Assert.True(features.HasFlag(BuiltInFeatures.Threads)); - Assert.True(features.HasFlag(BuiltInFeatures.Https)); } [Fact] From 70b393b558484cbf94590931b0690ae4212c2d6e Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 10 Nov 2018 06:27:35 -0800 Subject: [PATCH 047/179] Use the .NET standard HTTP class Use the .NET standard HTTP class for the Managed HTTP subtransport --- .../Core/ManagedHttpSmartSubtransport.cs | 158 ++++++++++-------- LibGit2Sharp/LibGit2Sharp.csproj | 8 + LibGit2Sharp/SmartSubtransportStream.cs | 31 +++- 3 files changed, 119 insertions(+), 78 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 2619137d7..a3dec8c21 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -1,7 +1,10 @@ using System; using System.IO; +using System.Linq; using System.Net; +using System.Net.Http; using System.Net.Security; +using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; namespace LibGit2Sharp.Core @@ -49,12 +52,36 @@ private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream private MemoryStream postBuffer = new MemoryStream(); private Stream responseStream; + private HttpClientHandler httpClientHandler; + private HttpClient httpClient; + public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, string endpointUrl, bool isPost, string contentType) : base(parent) { EndpointUrl = new Uri(endpointUrl); IsPost = isPost; ContentType = contentType; + + httpClientHandler = CreateClientHandler(); + httpClient = new HttpClient(httpClientHandler); + } + + private HttpClientHandler CreateClientHandler() + { +#if !NETFRAMEWORK + var httpClientHandler = new HttpClientHandler(); + httpClientHandler.SslProtocols |= SslProtocols.Tls12; + httpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationProxy; +#else + var httpClientHandler = new WebRequestHandler(); + httpClientHandler.ServerCertificateValidationCallback = CertificateValidationProxy; + + ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; +#endif + + httpClientHandler.AllowAutoRedirect = false; + + return httpClientHandler; } private Uri EndpointUrl @@ -104,13 +131,21 @@ public override int Write(Stream dataStream, long length) private bool CertificateValidationProxy(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) { - int ret = SmartTransport.CertificateCheck(new CertificateX509(cert), (errors == SslPolicyErrors.None), EndpointUrl.Host); - Ensure.ZeroResult(ret); + try + { + int ret = SmartTransport.CertificateCheck(new CertificateX509(cert), (errors == SslPolicyErrors.None), EndpointUrl.Host); + Ensure.ZeroResult(ret); - return true; + return true; + } + catch(Exception e) + { + SetError(e); + return false; + } } - private string getUserAgent() + private string GetUserAgent() { string userAgent = GlobalSettings.GetUserAgent(); @@ -122,97 +157,76 @@ private string getUserAgent() return userAgent; } - private HttpWebRequest CreateWebRequest(Uri endpointUrl, bool isPost, string contentType) + private HttpRequestMessage CreateRequest(Uri endpointUrl, bool isPost, string contentType) { - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; - - HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(endpointUrl); - webRequest.UserAgent = String.Format("git/2.0 ({0})", getUserAgent()); - webRequest.ServicePoint.Expect100Continue = false; - webRequest.AllowAutoRedirect = false; - webRequest.ServerCertificateValidationCallback += CertificateValidationProxy; + var verb = isPost ? new HttpMethod("POST") : new HttpMethod("GET"); + var request = new HttpRequestMessage(verb, endpointUrl); + request.Headers.Add("User-Agent", String.Format("git/2.0 ({0})", GetUserAgent())); + request.Headers.Remove("Expect"); - if (isPost) - { - webRequest.Method = "POST"; - webRequest.ContentType = contentType; - } - - return webRequest; + return request; } - private HttpWebResponse GetResponseWithRedirects() + private HttpResponseMessage GetResponseWithRedirects() { - HttpWebRequest request = CreateWebRequest(EndpointUrl, IsPost, ContentType); - HttpWebResponse response = null; + ICredentials credentials = null; + var url = EndpointUrl; int retries; for (retries = 0; ; retries++) { - if (retries > MAX_REDIRECTS) - { - throw new Exception("too many redirects or authentication replays"); - } + var httpClientHandler = CreateClientHandler(); + httpClientHandler.Credentials = credentials; - if (IsPost && postBuffer.Length > 0) + using (var httpClient = new HttpClient(httpClientHandler)) { - postBuffer.Seek(0, SeekOrigin.Begin); + var request = CreateRequest(url, IsPost, ContentType); - using (Stream requestStream = request.GetRequestStream()) + if (retries > MAX_REDIRECTS) { - postBuffer.WriteTo(requestStream); + throw new Exception("too many redirects or authentication replays"); } - } - try - { - response = (HttpWebResponse)request.GetResponse(); - } - catch (WebException ex) - { - if (ex.Response != null) + if (IsPost && postBuffer.Length > 0) { - response = (HttpWebResponse)ex.Response; + var bufferDup = new MemoryStream(postBuffer.GetBuffer()); + bufferDup.Seek(0, SeekOrigin.Begin); + + request.Content = new StreamContent(bufferDup); + request.Content.Headers.Add("Content-Type", ContentType); } - else if (ex.InnerException != null) + + var response = httpClient.SendAsync(request).Result; + + if (response.StatusCode == HttpStatusCode.OK) { - throw ex.InnerException; + return response; } - else + else if (response.StatusCode == HttpStatusCode.Unauthorized) { - throw new Exception("unknown network failure"); - } - } + Credentials cred; + int ret = SmartTransport.AcquireCredentials(out cred, null, typeof(UsernamePasswordCredentials)); - if (response.StatusCode == HttpStatusCode.OK) - { - break; - } - else if (response.StatusCode == HttpStatusCode.Unauthorized) - { - Credentials cred; - int ret = SmartTransport.AcquireCredentials(out cred, null, typeof(UsernamePasswordCredentials)); + if (ret != 0) + { + throw new InvalidOperationException("authentication cancelled"); + } - if (ret != 0) + UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; + credentials = new NetworkCredential(userpass.Username, userpass.Password); + continue; + } + else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) { - throw new InvalidOperationException("authentication cancelled"); + url = new Uri(response.Headers.GetValues("Location").First()); + continue; } - request = CreateWebRequest(EndpointUrl, IsPost, ContentType); - UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; - request.Credentials = new NetworkCredential(userpass.Username, userpass.Password); - continue; - } - else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) - { - request = CreateWebRequest(new Uri(response.Headers["Location"]), IsPost, ContentType); - continue; + throw new Exception(string.Format("unexpected HTTP response: {0}", response.StatusCode)); } - - throw new Exception(string.Format("unexpected HTTP response: {0}", response.StatusCode)); } - return response; + throw new Exception("too many redirects or authentication replays"); } public override int Read(Stream dataStream, long length, out long readTotal) @@ -222,8 +236,8 @@ public override int Read(Stream dataStream, long length, out long readTotal) if (responseStream == null) { - HttpWebResponse response = GetResponseWithRedirects(); - responseStream = response.GetResponseStream(); + HttpResponseMessage response = GetResponseWithRedirects(); + responseStream = response.Content.ReadAsStreamAsync().Result; } while (length > 0) @@ -249,6 +263,12 @@ protected override void Free() responseStream = null; } + if (httpClient != null) + { + httpClient.Dispose(); + httpClient = null; + } + base.Free(); } } diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 77971ea06..1776c0d43 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -31,10 +31,18 @@ + + + + + + + All + diff --git a/LibGit2Sharp/SmartSubtransportStream.cs b/LibGit2Sharp/SmartSubtransportStream.cs index a0d9accae..03009477b 100644 --- a/LibGit2Sharp/SmartSubtransportStream.cs +++ b/LibGit2Sharp/SmartSubtransportStream.cs @@ -61,6 +61,13 @@ public virtual SmartSubtransport SmartTransport get { return this.subtransport; } } + private Exception StoredError { get; set; } + + internal void SetError(Exception ex) + { + StoredError = ex; + } + private SmartSubtransport subtransport; private IntPtr nativeStreamPointer; @@ -96,6 +103,19 @@ private static class EntryPoints public static GitSmartSubtransportStream.write_callback WriteCallback = new GitSmartSubtransportStream.write_callback(Write); public static GitSmartSubtransportStream.free_callback FreeCallback = new GitSmartSubtransportStream.free_callback(Free); + private static int SetError(SmartSubtransportStream stream, Exception caught) + { + Exception ret = (stream.StoredError != null) ? stream.StoredError : caught; + GitErrorCode errorCode = GitErrorCode.Error; + + if (ret is NativeException) + { + errorCode = ((NativeException)ret).ErrorCode; + } + + return (int)errorCode; + } + private unsafe static int Read( IntPtr stream, IntPtr buffer, @@ -134,15 +154,9 @@ private unsafe static int Read( return toReturn; } } - catch (NativeException ex) - { - Proxy.git_error_set_str(GitErrorCategory.Net, ex); - return (int)ex.ErrorCode; - } catch (Exception ex) { - Proxy.git_error_set_str(GitErrorCategory.Net, ex); - return (int)GitErrorCode.Error; + return SetError(transportStream, ex); } } @@ -174,8 +188,7 @@ private static unsafe int Write(IntPtr stream, IntPtr buffer, UIntPtr len) } catch (Exception ex) { - Proxy.git_error_set_str(GitErrorCategory.Net, ex); - return (int)GitErrorCode.Error; + return SetError(transportStream, ex); } } From 04094f583dd9cdb20923e7c4a1bf656fe701b9f6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 16 Oct 2019 23:53:08 +0100 Subject: [PATCH 048/179] SSL validation: cope with GIT_PASSTHROUGH The passthrough error code for SSL validation means that the caller declined to act; we should just use our default validation in this case. --- LibGit2Sharp/SmartSubtransport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/SmartSubtransport.cs b/LibGit2Sharp/SmartSubtransport.cs index f3c475882..a8156ef54 100644 --- a/LibGit2Sharp/SmartSubtransport.cs +++ b/LibGit2Sharp/SmartSubtransport.cs @@ -81,7 +81,7 @@ public int CertificateCheck(Certificate cert, bool valid, string hostname) Marshal.FreeHGlobal(certPtr); } - if (ret > 0) + if (ret > 0 || ret == (int)GitErrorCode.PassThrough) { ret = valid ? 0 : -1; } From 4a459f1951d952ded3bf7c44fd13cf06a59ede62 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 17 Oct 2019 00:05:43 +0100 Subject: [PATCH 049/179] HTTP: complete only when actually complete --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index a3dec8c21..356b8c062 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -196,7 +196,7 @@ private HttpResponseMessage GetResponseWithRedirects() request.Content.Headers.Add("Content-Type", ContentType); } - var response = httpClient.SendAsync(request).Result; + var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).Result; if (response.StatusCode == HttpStatusCode.OK) { From 814054b69806aaa9ead8c95855a53ac246457cc1 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 7 Jan 2020 20:51:51 +0000 Subject: [PATCH 050/179] dispose the response --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 356b8c062..290132970 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -50,6 +50,7 @@ private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream private static int MAX_REDIRECTS = 7; private MemoryStream postBuffer = new MemoryStream(); + private HttpResponseMessage response; private Stream responseStream; private HttpClientHandler httpClientHandler; @@ -231,12 +232,12 @@ private HttpResponseMessage GetResponseWithRedirects() public override int Read(Stream dataStream, long length, out long readTotal) { - byte[] buffer = new byte[4096]; + byte[] buffer = new byte[16]; readTotal = 0; if (responseStream == null) { - HttpResponseMessage response = GetResponseWithRedirects(); + response = GetResponseWithRedirects(); responseStream = response.Content.ReadAsStreamAsync().Result; } @@ -245,7 +246,9 @@ public override int Read(Stream dataStream, long length, out long readTotal) int readLen = responseStream.Read(buffer, 0, (int)Math.Min(buffer.Length, length)); if (readLen == 0) + { break; + } dataStream.Write(buffer, 0, readLen); readTotal += readLen; @@ -263,6 +266,12 @@ protected override void Free() responseStream = null; } + if (response != null) + { + response.Dispose(); + response = null; + } + if (httpClient != null) { httpClient.Dispose(); From efdb363e0254dd2f9adde68696462d3cc2a7ea4a Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 29 Jan 2020 21:10:28 -0700 Subject: [PATCH 051/179] Fixed build warnings about System.Net.Http version issues --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 7 ------- LibGit2Sharp/LibGit2Sharp.csproj | 9 +-------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 290132970..d16e0de43 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -69,16 +69,9 @@ public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, s private HttpClientHandler CreateClientHandler() { -#if !NETFRAMEWORK var httpClientHandler = new HttpClientHandler(); httpClientHandler.SslProtocols |= SslProtocols.Tls12; httpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationProxy; -#else - var httpClientHandler = new WebRequestHandler(); - httpClientHandler.ServerCertificateValidationCallback = CertificateValidationProxy; - - ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; -#endif httpClientHandler.AllowAutoRedirect = false; diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 1776c0d43..bf5c75104 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -31,18 +31,11 @@ - - - - - - - All - + From f6f3cb6f8f24908e6960b54163f448552629dcc6 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 30 Jan 2020 11:05:40 -0700 Subject: [PATCH 052/179] Throw more precise exceptions when they happen --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index d16e0de43..38a41a4c0 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -190,7 +190,7 @@ private HttpResponseMessage GetResponseWithRedirects() request.Content.Headers.Add("Content-Type", ContentType); } - var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).Result; + var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult(); if (response.StatusCode == HttpStatusCode.OK) { @@ -231,7 +231,7 @@ public override int Read(Stream dataStream, long length, out long readTotal) if (responseStream == null) { response = GetResponseWithRedirects(); - responseStream = response.Content.ReadAsStreamAsync().Result; + responseStream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); } while (length > 0) From ae1563dffbab65c9d9c6fd1c0d5e0e3bca485add Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 30 Jan 2020 11:05:58 -0700 Subject: [PATCH 053/179] Improve xml doc comments for extensibility point API --- LibGit2Sharp/SmartSubtransportStream.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/SmartSubtransportStream.cs b/LibGit2Sharp/SmartSubtransportStream.cs index 03009477b..008d1fcd0 100644 --- a/LibGit2Sharp/SmartSubtransportStream.cs +++ b/LibGit2Sharp/SmartSubtransportStream.cs @@ -44,13 +44,20 @@ protected virtual void Free() } /// - /// Requests that the stream write the next length bytes of the stream to the provided Stream object. + /// Reads from the transport into the provided object. /// + /// The stream to copy the read bytes into. + /// The number of bytes expected from the underlying transport. + /// Receives the number of bytes actually read. + /// The error code to propagate back to the native code that requested this operation. 0 is expected, and exceptions may be thrown. public abstract int Read(Stream dataStream, long length, out long bytesRead); /// - /// Requests that the stream write the first length bytes of the provided Stream object to the stream. + /// Writes the content of a given stream to the transport. /// + /// The stream with the data to write to the transport. + /// The number of bytes to read from . + /// The error code to propagate back to the native code that requested this operation. 0 is expected, and exceptions may be thrown. public abstract int Write(Stream dataStream, long length); /// From a46fb8089b662f142631bc5650e0940106b2cfe6 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 30 Jan 2020 11:37:37 -0700 Subject: [PATCH 054/179] Increase the size of the very small read buffer --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 38a41a4c0..e60f1f8c6 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -225,7 +225,7 @@ private HttpResponseMessage GetResponseWithRedirects() public override int Read(Stream dataStream, long length, out long readTotal) { - byte[] buffer = new byte[16]; + byte[] buffer = new byte[4096]; readTotal = 0; if (responseStream == null) From e03424321d055f9c30e93533484a4ea10daf04dd Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 18 Feb 2020 10:27:28 +0000 Subject: [PATCH 055/179] fixup doc comments --- LibGit2Sharp/Core/Proxy.cs | 1 + LibGit2Sharp/GlobalSettings.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index dd90e3889..86d632576 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3472,6 +3472,7 @@ public static void git_libgit2_opts_set_user_agent(string userAgent) /// /// The user-agent string. /// + /// public static string git_libgit2_opts_get_user_agent() { string userAgent; diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 51edc1c08..8061bf362 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -525,6 +525,7 @@ public static void SetUserAgent(string userAgent) /// /// The user-agent string. /// + /// public static string GetUserAgent() { return Proxy.git_libgit2_opts_get_user_agent(); From 1b9656883bd8a76adc0894ea5bc609ac51784b9a Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 2 Mar 2020 07:49:40 -0700 Subject: [PATCH 056/179] Update macOS image on Azure Pipelines This resolves the warning we see on Azure Pipelines about the soon-to-be-removed image. --- azure-pipelines/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml index 1462628c8..a73ccda4c 100644 --- a/azure-pipelines/build.yml +++ b/azure-pipelines/build.yml @@ -17,7 +17,7 @@ jobs: - job: macOS pool: - vmImage: macOS 10.13 + vmImage: macOS-10.15 steps: - template: install-dependencies.yml - template: dotnet.yml From 8d83f067bf2c2cc4671d863737576fc3ed728f52 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 3 Apr 2020 12:32:08 -0400 Subject: [PATCH 057/179] Update LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs Co-Authored-By: dallmair --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index e60f1f8c6..5744d0335 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -183,8 +183,7 @@ private HttpResponseMessage GetResponseWithRedirects() if (IsPost && postBuffer.Length > 0) { - var bufferDup = new MemoryStream(postBuffer.GetBuffer()); - bufferDup.Seek(0, SeekOrigin.Begin); + var bufferDup = new MemoryStream(postBuffer.GetBuffer(), 0, (int) postBuffer.Length); request.Content = new StreamContent(bufferDup); request.Content.Headers.Add("Content-Type", ContentType); From 09503909c9841c9365a8f3662000459b5dd91488 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 3 Apr 2020 11:16:10 -0600 Subject: [PATCH 058/179] Suppress Expect: 100 Continue header --- .../Core/ManagedHttpSmartSubtransport.cs | 96 ++++++++++--------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 5744d0335..bb41bcdf6 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -53,18 +53,24 @@ private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream private HttpResponseMessage response; private Stream responseStream; - private HttpClientHandler httpClientHandler; - private HttpClient httpClient; - public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, string endpointUrl, bool isPost, string contentType) : base(parent) { EndpointUrl = new Uri(endpointUrl); IsPost = isPost; ContentType = contentType; + } - httpClientHandler = CreateClientHandler(); - httpClient = new HttpClient(httpClientHandler); + private HttpClient CreateHttpClient(HttpMessageHandler handler) + { + return new HttpClient(handler) + { + DefaultRequestHeaders = + { + // This worked fine when it was on, but git.exe doesn't specify this header, so we don't either. + ExpectContinue = false, + }, + }; } private HttpClientHandler CreateClientHandler() @@ -132,7 +138,7 @@ private bool CertificateValidationProxy(object sender, X509Certificate cert, X50 return true; } - catch(Exception e) + catch (Exception e) { SetError(e); return false; @@ -169,53 +175,55 @@ private HttpResponseMessage GetResponseWithRedirects() for (retries = 0; ; retries++) { - var httpClientHandler = CreateClientHandler(); - httpClientHandler.Credentials = credentials; - - using (var httpClient = new HttpClient(httpClientHandler)) + using (var httpClientHandler = CreateClientHandler()) { - var request = CreateRequest(url, IsPost, ContentType); + httpClientHandler.Credentials = credentials; - if (retries > MAX_REDIRECTS) + using (var httpClient = this.CreateHttpClient(httpClientHandler)) { - throw new Exception("too many redirects or authentication replays"); - } + var request = CreateRequest(url, IsPost, ContentType); - if (IsPost && postBuffer.Length > 0) - { - var bufferDup = new MemoryStream(postBuffer.GetBuffer(), 0, (int) postBuffer.Length); + if (retries > MAX_REDIRECTS) + { + throw new Exception("too many redirects or authentication replays"); + } - request.Content = new StreamContent(bufferDup); - request.Content.Headers.Add("Content-Type", ContentType); - } + if (IsPost && postBuffer.Length > 0) + { + var bufferDup = new MemoryStream(postBuffer.GetBuffer(), 0, (int)postBuffer.Length); - var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult(); + request.Content = new StreamContent(bufferDup); + request.Content.Headers.Add("Content-Type", ContentType); + } - if (response.StatusCode == HttpStatusCode.OK) - { - return response; - } - else if (response.StatusCode == HttpStatusCode.Unauthorized) - { - Credentials cred; - int ret = SmartTransport.AcquireCredentials(out cred, null, typeof(UsernamePasswordCredentials)); + var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult(); - if (ret != 0) + if (response.StatusCode == HttpStatusCode.OK) { - throw new InvalidOperationException("authentication cancelled"); + return response; } + else if (response.StatusCode == HttpStatusCode.Unauthorized) + { + Credentials cred; + int ret = SmartTransport.AcquireCredentials(out cred, null, typeof(UsernamePasswordCredentials)); - UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; - credentials = new NetworkCredential(userpass.Username, userpass.Password); - continue; - } - else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) - { - url = new Uri(response.Headers.GetValues("Location").First()); - continue; - } + if (ret != 0) + { + throw new InvalidOperationException("authentication cancelled"); + } + + UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; + credentials = new NetworkCredential(userpass.Username, userpass.Password); + continue; + } + else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) + { + url = new Uri(response.Headers.GetValues("Location").First()); + continue; + } - throw new Exception(string.Format("unexpected HTTP response: {0}", response.StatusCode)); + throw new Exception(string.Format("unexpected HTTP response: {0}", response.StatusCode)); + } } } @@ -264,12 +272,6 @@ protected override void Free() response = null; } - if (httpClient != null) - { - httpClient.Dispose(); - httpClient = null; - } - base.Free(); } } From f5abbba85c70f1e9aecb9ea200787e5e42445229 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 4 Apr 2020 21:11:23 -0400 Subject: [PATCH 059/179] Update SDK version --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index e9aac8c22..05d0ae3d2 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.1.100" + "version": "3.1.201" } } From 27a034d878fc8df9101de73a62bcb4303ff229f1 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 4 Apr 2020 21:38:26 -0400 Subject: [PATCH 060/179] Only use managed https with new net472 target --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 ++-- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 2 ++ LibGit2Sharp/Core/NativeMethods.cs | 8 +++++++- LibGit2Sharp/Core/Platform.cs | 6 +++--- LibGit2Sharp/LibGit2Sharp.csproj | 7 +++++-- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 4a73bd401..ccd188db6 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net46;netcoreapp2.1 + net46;net472;netcoreapp2.1 @@ -23,7 +23,7 @@ - + diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index bb41bcdf6..339d5bf07 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -1,3 +1,4 @@ +#if !NET46 using System; using System.IO; using System.Linq; @@ -277,3 +278,4 @@ protected override void Free() } } } +#endif diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index b12000cac..d358f5ae1 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -26,8 +26,10 @@ internal static class NativeMethods private static NativeShutdownObject shutdownObject; #pragma warning restore 0414 +#if !NET46 private static SmartSubtransportRegistration httpSubtransportRegistration; private static SmartSubtransportRegistration httpsSubtransportRegistration; +#endif static NativeMethods() { @@ -45,7 +47,7 @@ static NativeMethods() string nativeLibraryPath = GetGlobalSettingsNativeLibraryPath(); if (nativeLibraryPath != null) { -#if NETFRAMEWORK +#if NET46 if (Platform.OperatingSystem == OperatingSystemType.Windows) #else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -202,12 +204,14 @@ private static void InitializeNativeLibrary() shutdownObject = new NativeShutdownObject(); } +#if !NET46 // Configure the .NET HTTP(S) mechanism on the first initialization of the library in the current process. if (initCounter == 1) { httpSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("http"); httpsSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("https"); } +#endif } // Shutdown the native library in a finalizer. @@ -215,6 +219,7 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject { ~NativeShutdownObject() { +#if !NET46 if (httpSubtransportRegistration != null) { GlobalSettings.UnregisterDefaultSmartSubtransport(httpSubtransportRegistration); @@ -224,6 +229,7 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject { GlobalSettings.UnregisterDefaultSmartSubtransport(httpsSubtransportRegistration); } +#endif git_libgit2_shutdown(); } diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index 52859cbe2..fd9c9a7ca 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -13,7 +13,7 @@ internal enum OperatingSystemType internal static class Platform { public static string ProcessorArchitecture => IntPtr.Size == 8 ? "x64" : "x86"; -#if NETFRAMEWORK +#if NET46 private static bool? _isRunningOnMac; private static bool IsRunningOnMac() => _isRunningOnMac ?? (_isRunningOnMac = TryGetIsRunningOnMac()) ?? false; #endif @@ -22,7 +22,7 @@ public static OperatingSystemType OperatingSystem { get { -#if NETFRAMEWORK +#if NET46 var platform = (int)Environment.OSVersion.Platform; if (platform <= 3 || platform == 5) { @@ -91,7 +91,7 @@ public static bool IsRunningOnNetFramework() public static bool IsRunningOnNetCore() => typeof(object).Assembly.GetName().Name != "mscorlib"; -#if NETFRAMEWORK +#if NET46 #pragma warning disable IDE1006 // Naming Styles [DllImport("libc")] private static extern int sysctlbyname( diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index bf5c75104..350a98fbb 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net46 + netstandard2.0;net46;net472 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .Net and Mono. LibGit2Sharp contributors @@ -31,11 +31,14 @@ + + + + - From a0374ba80ef46e82a2832a4e3aa5b057646d0dc9 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 4 Apr 2020 21:40:41 -0400 Subject: [PATCH 061/179] Don't dispose HttpClientHandler separately HttpClient disposes it for you with the handler we're calling. --- .../Core/ManagedHttpSmartSubtransport.cs | 72 +++++++++---------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 339d5bf07..9d49e5cd5 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -176,55 +176,53 @@ private HttpResponseMessage GetResponseWithRedirects() for (retries = 0; ; retries++) { - using (var httpClientHandler = CreateClientHandler()) + var httpClientHandler = CreateClientHandler(); + httpClientHandler.Credentials = credentials; + + using (var httpClient = this.CreateHttpClient(httpClientHandler)) { - httpClientHandler.Credentials = credentials; + var request = CreateRequest(url, IsPost, ContentType); - using (var httpClient = this.CreateHttpClient(httpClientHandler)) + if (retries > MAX_REDIRECTS) { - var request = CreateRequest(url, IsPost, ContentType); - - if (retries > MAX_REDIRECTS) - { - throw new Exception("too many redirects or authentication replays"); - } - - if (IsPost && postBuffer.Length > 0) - { - var bufferDup = new MemoryStream(postBuffer.GetBuffer(), 0, (int)postBuffer.Length); + throw new Exception("too many redirects or authentication replays"); + } - request.Content = new StreamContent(bufferDup); - request.Content.Headers.Add("Content-Type", ContentType); - } + if (IsPost && postBuffer.Length > 0) + { + var bufferDup = new MemoryStream(postBuffer.GetBuffer(), 0, (int)postBuffer.Length); - var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult(); + request.Content = new StreamContent(bufferDup); + request.Content.Headers.Add("Content-Type", ContentType); + } - if (response.StatusCode == HttpStatusCode.OK) - { - return response; - } - else if (response.StatusCode == HttpStatusCode.Unauthorized) - { - Credentials cred; - int ret = SmartTransport.AcquireCredentials(out cred, null, typeof(UsernamePasswordCredentials)); + var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult(); - if (ret != 0) - { - throw new InvalidOperationException("authentication cancelled"); - } + if (response.StatusCode == HttpStatusCode.OK) + { + return response; + } + else if (response.StatusCode == HttpStatusCode.Unauthorized) + { + Credentials cred; + int ret = SmartTransport.AcquireCredentials(out cred, null, typeof(UsernamePasswordCredentials)); - UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; - credentials = new NetworkCredential(userpass.Username, userpass.Password); - continue; - } - else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) + if (ret != 0) { - url = new Uri(response.Headers.GetValues("Location").First()); - continue; + throw new InvalidOperationException("authentication cancelled"); } - throw new Exception(string.Format("unexpected HTTP response: {0}", response.StatusCode)); + UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; + credentials = new NetworkCredential(userpass.Username, userpass.Password); + continue; } + else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) + { + url = new Uri(response.Headers.GetValues("Location").First()); + continue; + } + + throw new Exception(string.Format("unexpected HTTP response: {0}", response.StatusCode)); } } From c3ac10332789b554e9d9edcedacfaa0a2b4dad40 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 4 Apr 2020 21:44:33 -0400 Subject: [PATCH 062/179] Minor cleanup --- .../Core/ManagedHttpSmartSubtransport.cs | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 9d49e5cd5..a77818f8a 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -85,23 +85,11 @@ private HttpClientHandler CreateClientHandler() return httpClientHandler; } - private Uri EndpointUrl - { - get; - set; - } + private Uri EndpointUrl { get; set; } - private bool IsPost - { - get; - set; - } + private bool IsPost { get; set; } - private string ContentType - { - get; - set; - } + private string ContentType { get; set; } public override int Write(Stream dataStream, long length) { @@ -204,8 +192,7 @@ private HttpResponseMessage GetResponseWithRedirects() } else if (response.StatusCode == HttpStatusCode.Unauthorized) { - Credentials cred; - int ret = SmartTransport.AcquireCredentials(out cred, null, typeof(UsernamePasswordCredentials)); + int ret = SmartTransport.AcquireCredentials(out Credentials cred, null, typeof(UsernamePasswordCredentials)); if (ret != 0) { From 807012a5c2ffe8d7b7215ce753262c800e174435 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 4 Apr 2020 21:55:07 -0400 Subject: [PATCH 063/179] Add net472 test runs --- azure-pipelines/dotnet.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index 8c9f5f909..066d14412 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -22,6 +22,22 @@ steps: testRunTitle: net46-$(Agent.JobName)-nocoverage condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) +- task: DotNetCoreCLI@2 + displayName: dotnet test -f net472 (w/ coverage) + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f net472 --filter "TestCategory!=FailsInCloudTest & TestCategory!=FailsWhileInstrumented" -v n /p:CollectCoverage=true + testRunTitle: net472-$(Agent.JobName) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +- task: DotNetCoreCLI@2 + displayName: dotnet test -f net472 (w/o coverage) + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f net472 --filter "TestCategory!=FailsInCloudTest & TestCategory=FailsWhileInstrumented" -v n + testRunTitle: net472-$(Agent.JobName)-nocoverage + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + - task: DotNetCoreCLI@2 displayName: dotnet test -f netcoreapp2.1 inputs: From 32af8db85e84bbc7e9c0cb517bc652df1965d55d Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 4 Apr 2020 22:16:31 -0400 Subject: [PATCH 064/179] Fix LoadFromSpecifiedPath test on net472 --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 ++-- .../x64/NativeLibraryLoadTestApp.x64.csproj | 2 +- .../x86/NativeLibraryLoadTestApp.x86.csproj | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index ccd188db6..6e3ac8699 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj b/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj index 5fb7e1b0c..72f64ea29 100644 --- a/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj +++ b/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj @@ -2,7 +2,7 @@ Exe - net46 + net46;net472 x64 diff --git a/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj b/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj index c7bef05c9..49cad97a0 100644 --- a/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj +++ b/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj @@ -2,7 +2,7 @@ Exe - net46 + net46;net472 x86 From 9daf4cc57aa25bff0c588b5a21a76ce73a66d709 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 5 Apr 2020 00:11:35 -0400 Subject: [PATCH 065/179] Update to binaries package that doesn't use OpenSSL on linux --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 350a98fbb..361a33903 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -36,7 +36,7 @@ - + From 80ea092d926d2e2fd459c7f8fb6c5f9bdb7e2a61 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 6 Apr 2020 21:33:42 -0400 Subject: [PATCH 066/179] Fix when Register is called before NativeMethod cctor --- LibGit2Sharp/GlobalSettings.cs | 36 ++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 8061bf362..4410fe9f9 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -116,9 +116,15 @@ internal static SmartSubtransportRegistration RegisterDefaultSmartSubtranspor throw new Exception(string.Format("A default subtransport is already configured for {0}", scheme)); } - var registration = RegisterSmartSubtransportInternal(scheme); + var registration = new SmartSubtransportRegistration(scheme); + + if (!data.isCustom) + { + RegisterSmartSubtransportInternal(registration); + } data.defaultSubtransport = registration; + return registration; } } @@ -140,8 +146,6 @@ internal static SmartSubtransportRegistration RegisterDefaultSmartSubtranspor public static SmartSubtransportRegistration RegisterSmartSubtransport(string scheme) where T : SmartSubtransport, new() { - SmartSubtransportRegistration registration; - Ensure.ArgumentNotNull(scheme, "scheme"); lock (smartSubtransportData) @@ -158,31 +162,39 @@ public static SmartSubtransportRegistration RegisterSmartSubtransport(stri Proxy.git_transport_unregister(scheme); } - registration = RegisterSmartSubtransportInternal(scheme); + var previousValue = data.isCustom; data.isCustom = true; - } - return registration; + var registration = new SmartSubtransportRegistration(scheme); + + try + { + RegisterSmartSubtransportInternal(registration); + } + catch + { + data.isCustom = previousValue; + throw; + } + + return registration; + } } - private static SmartSubtransportRegistration RegisterSmartSubtransportInternal(string scheme) + private static void RegisterSmartSubtransportInternal(SmartSubtransportRegistration registration) where T : SmartSubtransport, new() { - var registration = new SmartSubtransportRegistration(scheme); - try { Proxy.git_transport_register(registration.Scheme, registration.FunctionPointer, registration.RegistrationPointer); } - catch (Exception) + catch { registration.Free(); throw; } - - return registration; } /// From 35bca832fb74d52eb69e7b3511e36e6879ec6db6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 6 Apr 2020 21:54:13 -0400 Subject: [PATCH 067/179] Fix XML comment --- LibGit2Sharp/GlobalSettings.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 4410fe9f9..cc9e94520 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -131,10 +131,9 @@ internal static SmartSubtransportRegistration RegisterDefaultSmartSubtranspor /// /// Registers a new as a custom - /// smart-protocol transport with libgit2. Any Git remote with + /// smart-protocol transport with libgit2. Any Git remote with /// the scheme registered will delegate to the given transport - /// for all communication with the server. use this transport to communicate - /// with the server This is not commonly + /// for all communication with the server. This is not commonly /// used: some callers may want to re-use an existing connection to /// perform fetch / push operations to a remote. /// From d2db2ac45f72eefda4acf42c77dec58d0e91b8f6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 6 Apr 2020 22:25:50 -0400 Subject: [PATCH 068/179] Cleanup --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index a77818f8a..8af18398f 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -146,11 +146,11 @@ private string GetUserAgent() return userAgent; } - private HttpRequestMessage CreateRequest(Uri endpointUrl, bool isPost, string contentType) + private HttpRequestMessage CreateRequest(Uri endpointUrl, bool isPost) { var verb = isPost ? new HttpMethod("POST") : new HttpMethod("GET"); var request = new HttpRequestMessage(verb, endpointUrl); - request.Headers.Add("User-Agent", String.Format("git/2.0 ({0})", GetUserAgent())); + request.Headers.Add("User-Agent", $"git/2.0 ({GetUserAgent()})"); request.Headers.Remove("Expect"); return request; @@ -169,7 +169,7 @@ private HttpResponseMessage GetResponseWithRedirects() using (var httpClient = this.CreateHttpClient(httpClientHandler)) { - var request = CreateRequest(url, IsPost, ContentType); + var request = CreateRequest(url, IsPost); if (retries > MAX_REDIRECTS) { From 9ee00e44450b6349733030dcf384484cd1c14616 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 6 Apr 2020 23:01:43 -0400 Subject: [PATCH 069/179] Make managed http opt-in on non-Linux OSes --- LibGit2Sharp/Core/NativeMethods.cs | 2 +- LibGit2Sharp/GlobalSettings.cs | 26 +++++++++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index d358f5ae1..f1a0086b7 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -206,7 +206,7 @@ private static void InitializeNativeLibrary() #if !NET46 // Configure the .NET HTTP(S) mechanism on the first initialization of the library in the current process. - if (initCounter == 1) + if (initCounter == 1 && GlobalSettings.ManagedHttpSmartSubtransportEnabled) { httpSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("http"); httpsSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("https"); diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index cc9e94520..51e0cd860 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -22,6 +22,10 @@ public static class GlobalSettings private static bool nativeLibraryPathLocked; private static string nativeLibraryDefaultPath; +#if !NET46 + private static bool useManagedHttpSmartSubtransport; +#endif + internal class SmartSubtransportData { internal bool isCustom; @@ -79,13 +83,11 @@ private static string GetExecutingAssemblyDirectory() /// Returns information related to the current LibGit2Sharp /// library. /// - public static Version Version - { - get - { - return version.Value; - } - } + public static Version Version => version.Value; + +#if !NET46 + internal static bool ManagedHttpSmartSubtransportEnabled => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || useManagedHttpSmartSubtransport; +#endif private static SmartSubtransportData GetOrCreateSmartSubtransportData(string scheme) { @@ -541,5 +543,15 @@ public static string GetUserAgent() { return Proxy.git_libgit2_opts_get_user_agent(); } + +#if !NET46 + /// + /// Enables the managed http implementation. This is enabled autmatically on Linux, so this method is only needed when running on Windows or macOS. + /// + public static void UseManagedHttpSmartSubtransport() + { + useManagedHttpSmartSubtransport = true; + } +#endif } } From 8671cc74b9f1c6b51c6921c97b4ea429e5a38f60 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 15 Apr 2020 19:13:33 -0400 Subject: [PATCH 070/179] Update SDK version in global.json --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index e9aac8c22..05d0ae3d2 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.1.100" + "version": "3.1.201" } } From 79e11b960d3010aa8e8541cf6d2406b0d6c563a9 Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Thu, 30 Apr 2020 09:50:36 +0200 Subject: [PATCH 071/179] Added Line struct and lists for addedlines and deletedlines in content changes --- LibGit2Sharp/ContentChanges.cs | 6 ++++++ LibGit2Sharp/Core/Line.cs | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 LibGit2Sharp/Core/Line.cs diff --git a/LibGit2Sharp/ContentChanges.cs b/LibGit2Sharp/ContentChanges.cs index 221c99efa..c92f0a984 100644 --- a/LibGit2Sharp/ContentChanges.cs +++ b/LibGit2Sharp/ContentChanges.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Text; @@ -51,6 +52,11 @@ internal void AppendToPatch(string patch) /// public virtual int LinesDeleted { get; internal set; } + public IEnumerable AddedLines { get; internal set; } + + public IEnumerable DeletedLines { get; internal set; } + + /// /// The patch corresponding to these changes. /// diff --git a/LibGit2Sharp/Core/Line.cs b/LibGit2Sharp/Core/Line.cs new file mode 100644 index 000000000..4a75289bf --- /dev/null +++ b/LibGit2Sharp/Core/Line.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace LibGit2Sharp.Core +{ + internal struct Line + { + /// + /// Points to the number of the original line in the blob + /// + public int LineNumber { get; } + + /// + /// This content of the line in the original blob + /// + public String Content { get; } + + internal Line(int lineNumber, string content) + { + LineNumber = lineNumber; + Content = content; + } + } +} From 92b9e20edcb35da430ee698b20d3d12ce9ab87be Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Thu, 30 Apr 2020 10:30:47 +0200 Subject: [PATCH 072/179] Added Line struct and lists for addedlines and deletedlines in content changes --- LibGit2Sharp/ContentChanges.cs | 9 +++++++-- LibGit2Sharp/Core/Line.cs | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp/ContentChanges.cs b/LibGit2Sharp/ContentChanges.cs index c92f0a984..223fd6375 100644 --- a/LibGit2Sharp/ContentChanges.cs +++ b/LibGit2Sharp/ContentChanges.cs @@ -23,6 +23,9 @@ protected ContentChanges() internal unsafe ContentChanges(Repository repo, Blob oldBlob, Blob newBlob, GitDiffOptions options) { + AddedLines = new List(); + DeletedLines = new List(); + Proxy.git_diff_blobs(repo.Handle, oldBlob != null ? oldBlob.Id : null, newBlob != null ? newBlob.Id : null, @@ -52,9 +55,9 @@ internal void AppendToPatch(string patch) /// public virtual int LinesDeleted { get; internal set; } - public IEnumerable AddedLines { get; internal set; } + public List AddedLines { get; internal set; } - public IEnumerable DeletedLines { get; internal set; } + public List DeletedLines { get; internal set; } /// @@ -101,11 +104,13 @@ private unsafe int LineCallback(git_diff_delta* delta, GitDiffHunk hunk, GitDiff switch (line.lineOrigin) { case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION: + AddedLines.Add(new Line(line.NewLineNo, decodedContent)); LinesAdded++; prefix = Encoding.ASCII.GetString(new[] { (byte)line.lineOrigin }); break; case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION: + DeletedLines.Add(new Line(line.OldLineNo, decodedContent)); LinesDeleted++; prefix = Encoding.ASCII.GetString(new[] { (byte)line.lineOrigin }); break; diff --git a/LibGit2Sharp/Core/Line.cs b/LibGit2Sharp/Core/Line.cs index 4a75289bf..caa50c17c 100644 --- a/LibGit2Sharp/Core/Line.cs +++ b/LibGit2Sharp/Core/Line.cs @@ -4,7 +4,7 @@ namespace LibGit2Sharp.Core { - internal struct Line + public struct Line { /// /// Points to the number of the original line in the blob From 445bbbe2e317d2cb5aaa2648ca4de5fd69b81ff0 Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Thu, 30 Apr 2020 10:57:05 +0200 Subject: [PATCH 073/179] Fixed for tests --- LibGit2Sharp/ContentChanges.cs | 10 ++++++++-- LibGit2Sharp/{Core => }/Line.cs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) rename LibGit2Sharp/{Core => }/Line.cs (95%) diff --git a/LibGit2Sharp/ContentChanges.cs b/LibGit2Sharp/ContentChanges.cs index 223fd6375..f88a2d493 100644 --- a/LibGit2Sharp/ContentChanges.cs +++ b/LibGit2Sharp/ContentChanges.cs @@ -55,9 +55,15 @@ internal void AppendToPatch(string patch) /// public virtual int LinesDeleted { get; internal set; } - public List AddedLines { get; internal set; } + /// + /// Lis of all lines added. + /// + public virtual List AddedLines { get; internal set; } - public List DeletedLines { get; internal set; } + /// + /// List of all lines deleted. + /// + public virtual List DeletedLines { get; internal set; } /// diff --git a/LibGit2Sharp/Core/Line.cs b/LibGit2Sharp/Line.cs similarity index 95% rename from LibGit2Sharp/Core/Line.cs rename to LibGit2Sharp/Line.cs index caa50c17c..f62abdd99 100644 --- a/LibGit2Sharp/Core/Line.cs +++ b/LibGit2Sharp/Line.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace LibGit2Sharp.Core +namespace LibGit2Sharp { public struct Line { From 70b6bd74d7bf6d403e050a192c01e8b4ab5c7d1f Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Thu, 30 Apr 2020 11:01:19 +0200 Subject: [PATCH 074/179] Added missing documentatiion of Line --- LibGit2Sharp/Line.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/LibGit2Sharp/Line.cs b/LibGit2Sharp/Line.cs index f62abdd99..f201aeaff 100644 --- a/LibGit2Sharp/Line.cs +++ b/LibGit2Sharp/Line.cs @@ -4,6 +4,9 @@ namespace LibGit2Sharp { + /// + /// Represents a Line with line number and content. + /// public struct Line { /// From 3c777dc40211f6208edb3d2f3d06ea47ccd455c7 Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Thu, 30 Apr 2020 14:03:16 +0200 Subject: [PATCH 075/179] Set deleted and added lines in patch printcallback --- LibGit2Sharp/Patch.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/LibGit2Sharp/Patch.cs b/LibGit2Sharp/Patch.cs index 2cd4d1605..d41741216 100644 --- a/LibGit2Sharp/Patch.cs +++ b/LibGit2Sharp/Patch.cs @@ -68,6 +68,11 @@ private unsafe int PrintCallBack(git_diff_delta* delta, GitDiffHunk hunk, GitDif PatchEntryChanges currentChange = this[filePath]; string prefix = string.Empty; + string decodedContent = LaxUtf8Marshaler.FromNative(line.content, (int)line.contentLen); + + currentChange.AddedLines = new List(); + currentChange.DeletedLines = new List(); + switch (line.lineOrigin) { case GitDiffLineOrigin.GIT_DIFF_LINE_CONTEXT: @@ -77,12 +82,14 @@ private unsafe int PrintCallBack(git_diff_delta* delta, GitDiffHunk hunk, GitDif case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION: linesAdded++; currentChange.LinesAdded++; + currentChange.AddedLines.Add(new Line(line.NewLineNo, decodedContent)); prefix = "+"; break; case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION: linesDeleted++; currentChange.LinesDeleted++; + currentChange.DeletedLines.Add(new Line(line.OldLineNo, decodedContent)); prefix = "-"; break; } From a5ef816147adcc0776440b93bca684ef8cc2a160 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 10 May 2020 22:50:47 +0100 Subject: [PATCH 076/179] Managed subtransport: support Default Credentials --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 12 ++++++++++-- LibGit2Sharp/SmartSubtransport.cs | 7 +++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 8af18398f..573121f6e 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -199,8 +199,16 @@ private HttpResponseMessage GetResponseWithRedirects() throw new InvalidOperationException("authentication cancelled"); } - UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; - credentials = new NetworkCredential(userpass.Username, userpass.Password); + if (cred is DefaultCredentials) + { + credentials = CredentialCache.DefaultNetworkCredentials; + } + else if (cred is UsernamePasswordCredentials) + { + UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; + credentials = new NetworkCredential(userpass.Username, userpass.Password); + } + continue; } else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) diff --git a/LibGit2Sharp/SmartSubtransport.cs b/LibGit2Sharp/SmartSubtransport.cs index a8156ef54..66fcd12bf 100644 --- a/LibGit2Sharp/SmartSubtransport.cs +++ b/LibGit2Sharp/SmartSubtransport.cs @@ -106,6 +106,10 @@ public int AcquireCredentials(out Credentials cred, string user, params Type[] m { allowed |= (int)GitCredentialType.UserPassPlaintext; } + else if (method == typeof(DefaultCredentials)) + { + allowed |= (int)GitCredentialType.Default; + } else { throw new InvalidOperationException("Unknown type passes as allowed credential"); @@ -133,6 +137,9 @@ public int AcquireCredentials(out Credentials cred, string user, params Type[] m case GitCredentialType.UserPassPlaintext: cred = UsernamePasswordCredentials.FromNative((GitCredentialUserpass*) credHandle); return 0; + case GitCredentialType.Default: + cred = new DefaultCredentials(); + return 0; default: throw new InvalidOperationException("User returned an unkown credential type"); } From 9733e7442577c725b422cd2f2fbc6f6986df3f0c Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Wed, 27 May 2020 20:35:23 +0200 Subject: [PATCH 077/179] Added test for blobToBlob compare --- LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs | 32 +++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs index fea0bbb74..d710750e7 100644 --- a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs +++ b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs @@ -1,7 +1,7 @@ -using System.IO; +using LibGit2Sharp.Tests.TestHelpers; +using System.IO; using System.Linq; using System.Text; -using LibGit2Sharp.Tests.TestHelpers; using Xunit; namespace LibGit2Sharp.Tests @@ -202,6 +202,34 @@ public void ComparingBlobsWithNoSpacesIndentHeuristicOptionMakesNoDifference() } } + [Fact] + public void DiffSetsTheAddedAndDeletedLinesCorrectly() + { + var path = SandboxStandardTestRepoGitDir(); + + using (var repo = new Repository(path)) + { + var oldContent = + @"1 +2 +3 +4"; + + var newContent = + @"1 +2 +3 +5"; + var oldBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(oldContent))); + var newBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(newContent))); + + ContentChanges changes = repo.Diff.Compare(oldBlob, newBlob); + + Assert.Single(changes.AddedLines); + Assert.Single(changes.DeletedLines); + } + } + static string CanonicalChangedLines(ContentChanges changes) { // Create an ordered representation of lines that have been added or removed From 37fa58584a2495a46f461f363a4ff22d824f9471 Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Wed, 27 May 2020 20:48:07 +0200 Subject: [PATCH 078/179] Tests and added explicit setting of added and deleted lines in patch because linecallback isn't called in this case --- LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs | 24 ++++++- LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs | 67 ++++++++++++++----- LibGit2Sharp/Patch.cs | 10 +-- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs index 2fb359f24..6218dc858 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs @@ -1,7 +1,7 @@ +using LibGit2Sharp.Tests.TestHelpers; using System.IO; using System.Linq; using System.Text; -using LibGit2Sharp.Tests.TestHelpers; using Xunit; namespace LibGit2Sharp.Tests @@ -17,7 +17,7 @@ private static void SetUpSimpleDiffContext(IRepository repo) File.AppendAllText(fullpath, "world\n"); - Commands.Stage(repo,fullpath); + Commands.Stage(repo, fullpath); File.AppendAllText(fullpath, "!!!\n"); } @@ -509,5 +509,25 @@ public void CanCompareANullTreeAgainstTheWorkdirAndTheIndex() } } } + + [Fact] + public void CompareSetsCorrectAddedAndDeletedLines() + { + string repoPath = InitNewRepository(); + + using (var repo = new Repository(repoPath)) + { + SetUpSimpleDiffContext(repo); + + using (var changes = repo.Diff.Compare(repo.Head.Tip.Tree, + DiffTargets.WorkingDirectory | DiffTargets.Index)) + { + foreach (var entry in changes) + { + Assert.Equal(2, entry.AddedLines.Count()); + } + } + } + } } } diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs index dba762bfe..9137ab138 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs @@ -1,10 +1,9 @@ -using System; +using LibGit2Sharp.Tests.TestHelpers; +using System; using System.IO; using System.Linq; using System.Text; -using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -20,7 +19,7 @@ public void ComparingATreeAgainstItselfReturnsNoDifference() { Tree tree = repo.Head.Tip.Tree; - using(var changes = repo.Diff.Compare(tree, tree)) + using (var changes = repo.Diff.Compare(tree, tree)) { Assert.Empty(changes); } @@ -112,13 +111,13 @@ public void CanDetectABinaryChange() File.AppendAllText(filepath, "abcdef"); - using(var patch = repo.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory, new[] { filename })) + using (var patch = repo.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory, new[] { filename })) Assert.True(patch[filename].IsBinaryComparison); Commands.Stage(repo, filename); var commit2 = repo.Commit("Update binary file", Constants.Signature, Constants.Signature); - using(var patch2 = repo.Diff.Compare(commit.Tree, commit2.Tree, new[] { filename })) + using (var patch2 = repo.Diff.Compare(commit.Tree, commit2.Tree, new[] { filename })) Assert.True(patch2[filename].IsBinaryComparison); } } @@ -138,13 +137,13 @@ public void CanDetectABinaryDeletion() File.Delete(filepath); - using(var patch = repo.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory, new [] {filename})) + using (var patch = repo.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory, new[] { filename })) Assert.True(patch[filename].IsBinaryComparison); Commands.Remove(repo, filename); var commit2 = repo.Commit("Delete binary file", Constants.Signature, Constants.Signature); - using(var patch2 = repo.Diff.Compare(commit.Tree, commit2.Tree, new[] { filename })) + using (var patch2 = repo.Diff.Compare(commit.Tree, commit2.Tree, new[] { filename })) Assert.True(patch2[filename].IsBinaryComparison); } } @@ -704,7 +703,7 @@ public void CanIncludeUnmodifiedEntriesWhenEnabled() Touch(repo.Info.WorkingDirectory, "a.txt", "abc\ndef\n"); Touch(repo.Info.WorkingDirectory, "b.txt", "abc\ndef\n"); - Commands.Stage(repo, new[] {"a.txt", "b.txt"}); + Commands.Stage(repo, new[] { "a.txt", "b.txt" }); Commit old = repo.Commit("Initial", Constants.Signature, Constants.Signature); File.AppendAllText(Path.Combine(repo.Info.WorkingDirectory, "b.txt"), "ghi\njkl\n"); @@ -728,12 +727,12 @@ public void CanDetectTheExactRenamingExactCopyingOfNonModifiedAndModifiedFilesWh var path = Repository.Init(scd.DirectoryPath); using (var repo = new Repository(path)) { - const string originalPath = "original.txt"; - const string renamedPath = "renamed.txt"; + const string originalPath = "original.txt"; + const string renamedPath = "renamed.txt"; const string originalPath2 = "original2.txt"; - const string copiedPath1 = "copied.txt"; + const string copiedPath1 = "copied.txt"; const string originalPath3 = "original3.txt"; - const string copiedPath2 = "copied2.txt"; + const string copiedPath2 = "copied2.txt"; Touch(repo.Info.WorkingDirectory, originalPath, "a\nb\nc\nd\n"); Touch(repo.Info.WorkingDirectory, originalPath2, "1\n2\n3\n4\n"); @@ -986,7 +985,7 @@ public void CanHandleTwoTreeEntryChangesWithTheSamePathUsingSimilarityNone() Assert.Single(changes.Deleted); Assert.Single(changes.TypeChanged); - TreeEntryChanges change = changes.Single(c => c.Path== path); + TreeEntryChanges change = changes.Single(c => c.Path == path); Assert.Equal(Mode.SymbolicLink, change.OldMode); Assert.Equal(Mode.NonExecutableFile, change.Mode); Assert.Equal(ChangeKind.TypeChanged, change.Status); @@ -1087,7 +1086,7 @@ public void ComparingReliesOnProvidedConfigEntriesIfAny() using (var repo = new Repository(path)) { SetFilemode(repo, true); - using(var changes = repo.Diff.Compare(new[] { file })) + using (var changes = repo.Diff.Compare(new[] { file })) { Assert.Single(changes); @@ -1147,6 +1146,44 @@ public void RetrievingDiffChangesMustAlwaysBeCaseSensitive() } } + [Fact] + public void RetrievingDiffContainsRightAmountOfAddedAndDeletedLines() + { + ObjectId treeOldOid, treeNewOid; + + string repoPath = InitNewRepository(); + + using (var repo = new Repository(repoPath)) + { + Blob oldContent = OdbHelper.CreateBlob(repo, "awesome content\n"); + Blob newContent = OdbHelper.CreateBlob(repo, "more awesome content\n"); + + var td = new TreeDefinition() + .Add("A.TXT", oldContent, Mode.NonExecutableFile) + .Add("a.txt", oldContent, Mode.NonExecutableFile); + + treeOldOid = repo.ObjectDatabase.CreateTree(td).Id; + + td = new TreeDefinition() + .Add("A.TXT", newContent, Mode.NonExecutableFile) + .Add("a.txt", newContent, Mode.NonExecutableFile); + + treeNewOid = repo.ObjectDatabase.CreateTree(td).Id; + } + + using (var repo = new Repository(repoPath)) + { + using (var changes = repo.Diff.Compare(repo.Lookup(treeOldOid), repo.Lookup(treeNewOid))) + { + foreach (var entry in changes) + { + Assert.Single(entry.AddedLines); + Assert.Single(entry.DeletedLines); + } + } + } + } + [Fact] public void UsingPatienceAlgorithmCompareOptionProducesPatienceDiff() { diff --git a/LibGit2Sharp/Patch.cs b/LibGit2Sharp/Patch.cs index d41741216..b38349efc 100644 --- a/LibGit2Sharp/Patch.cs +++ b/LibGit2Sharp/Patch.cs @@ -1,11 +1,11 @@ +using LibGit2Sharp.Core; +using LibGit2Sharp.Core.Handles; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Text; -using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp { @@ -70,8 +70,8 @@ private unsafe int PrintCallBack(git_diff_delta* delta, GitDiffHunk hunk, GitDif string decodedContent = LaxUtf8Marshaler.FromNative(line.content, (int)line.contentLen); - currentChange.AddedLines = new List(); - currentChange.DeletedLines = new List(); + currentChange.AddedLines = currentChange.AddedLines ?? new List(); + currentChange.DeletedLines = currentChange.DeletedLines ?? new List(); switch (line.lineOrigin) { @@ -175,7 +175,7 @@ public virtual string Content /// /// . /// The patch content as string. - public static implicit operator string (Patch patch) + public static implicit operator string(Patch patch) { return patch.fullPatchBuilder.ToString(); } From 81965391c95d99e2556737ddd9ca59329648ceb8 Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Fri, 29 May 2020 14:24:26 +0200 Subject: [PATCH 079/179] Update LibGit2Sharp/Line.cs Co-authored-by: Brandon Ording --- LibGit2Sharp/Line.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/Line.cs b/LibGit2Sharp/Line.cs index f201aeaff..5131259d9 100644 --- a/LibGit2Sharp/Line.cs +++ b/LibGit2Sharp/Line.cs @@ -10,7 +10,7 @@ namespace LibGit2Sharp public struct Line { /// - /// Points to the number of the original line in the blob + /// The line number of the original line in the blob. /// public int LineNumber { get; } From a9d5c3614c4d499627d28fb611fc8d55ef76a8d2 Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Fri, 29 May 2020 14:25:13 +0200 Subject: [PATCH 080/179] Apply suggestions from code review Co-authored-by: Brandon Ording --- LibGit2Sharp/ContentChanges.cs | 4 ++-- LibGit2Sharp/Line.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp/ContentChanges.cs b/LibGit2Sharp/ContentChanges.cs index f88a2d493..93a30582c 100644 --- a/LibGit2Sharp/ContentChanges.cs +++ b/LibGit2Sharp/ContentChanges.cs @@ -56,12 +56,12 @@ internal void AppendToPatch(string patch) public virtual int LinesDeleted { get; internal set; } /// - /// Lis of all lines added. + /// The list of added lines. /// public virtual List AddedLines { get; internal set; } /// - /// List of all lines deleted. + /// The list of deleted lines. /// public virtual List DeletedLines { get; internal set; } diff --git a/LibGit2Sharp/Line.cs b/LibGit2Sharp/Line.cs index 5131259d9..830247fc3 100644 --- a/LibGit2Sharp/Line.cs +++ b/LibGit2Sharp/Line.cs @@ -5,7 +5,7 @@ namespace LibGit2Sharp { /// - /// Represents a Line with line number and content. + /// Represents a line with line number and content. /// public struct Line { @@ -15,9 +15,9 @@ public struct Line public int LineNumber { get; } /// - /// This content of the line in the original blob + /// The content of the line in the original blob. /// - public String Content { get; } + public string Content { get; } internal Line(int lineNumber, string content) { From 7ca3791fd2f6c13f5d4b236fd0a6190b7aa1db19 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 30 May 2020 15:11:10 -0400 Subject: [PATCH 081/179] Move to only netstandard2.0 target --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- .../Core/ManagedHttpSmartSubtransport.cs | 2 - LibGit2Sharp/Core/NativeMethods.cs | 14 +-- LibGit2Sharp/Core/Platform.cs | 86 +------------------ LibGit2Sharp/GlobalSettings.cs | 6 -- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- .../x64/NativeLibraryLoadTestApp.x64.csproj | 2 +- .../x86/NativeLibraryLoadTestApp.x86.csproj | 2 +- 8 files changed, 6 insertions(+), 110 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 6e3ac8699..0525e98c8 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net46;net472;netcoreapp2.1 + net472;netcoreapp2.1 diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 573121f6e..76bb21573 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -1,4 +1,3 @@ -#if !NET46 using System; using System.IO; using System.Linq; @@ -271,4 +270,3 @@ protected override void Free() } } } -#endif diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index f1a0086b7..3db92ba58 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -26,10 +26,8 @@ internal static class NativeMethods private static NativeShutdownObject shutdownObject; #pragma warning restore 0414 -#if !NET46 private static SmartSubtransportRegistration httpSubtransportRegistration; private static SmartSubtransportRegistration httpsSubtransportRegistration; -#endif static NativeMethods() { @@ -47,11 +45,8 @@ static NativeMethods() string nativeLibraryPath = GetGlobalSettingsNativeLibraryPath(); if (nativeLibraryPath != null) { -#if NET46 - if (Platform.OperatingSystem == OperatingSystemType.Windows) -#else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) -#endif + { LoadWindowsLibrary(nativeLibraryPath); } @@ -151,8 +146,6 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor return handle; } -#if NETFRAMEWORK -#else // We cary a number of .so files for Linux which are linked against various // libc/OpenSSL libraries. Try them out. if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) @@ -175,7 +168,6 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor } } } -#endif } return handle; } @@ -204,14 +196,12 @@ private static void InitializeNativeLibrary() shutdownObject = new NativeShutdownObject(); } -#if !NET46 // Configure the .NET HTTP(S) mechanism on the first initialization of the library in the current process. if (initCounter == 1 && GlobalSettings.ManagedHttpSmartSubtransportEnabled) { httpSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("http"); httpsSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("https"); } -#endif } // Shutdown the native library in a finalizer. @@ -219,7 +209,6 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject { ~NativeShutdownObject() { -#if !NET46 if (httpSubtransportRegistration != null) { GlobalSettings.UnregisterDefaultSmartSubtransport(httpSubtransportRegistration); @@ -229,7 +218,6 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject { GlobalSettings.UnregisterDefaultSmartSubtransport(httpsSubtransportRegistration); } -#endif git_libgit2_shutdown(); } diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index fd9c9a7ca..e8d536475 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -13,30 +13,11 @@ internal enum OperatingSystemType internal static class Platform { public static string ProcessorArchitecture => IntPtr.Size == 8 ? "x64" : "x86"; -#if NET46 - private static bool? _isRunningOnMac; - private static bool IsRunningOnMac() => _isRunningOnMac ?? (_isRunningOnMac = TryGetIsRunningOnMac()) ?? false; -#endif public static OperatingSystemType OperatingSystem { get { -#if NET46 - var platform = (int)Environment.OSVersion.Platform; - if (platform <= 3 || platform == 5) - { - return OperatingSystemType.Windows; - } - if (IsRunningOnMac()) - { - return OperatingSystemType.MacOSX; - } - if (platform == 4 || platform == 6 || platform == 128) - { - return OperatingSystemType.Unix; - } -#else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return OperatingSystemType.Windows; @@ -51,7 +32,7 @@ public static OperatingSystemType OperatingSystem { return OperatingSystemType.MacOSX; } -#endif + throw new PlatformNotSupportedException(); } } @@ -90,70 +71,5 @@ public static bool IsRunningOnNetFramework() /// public static bool IsRunningOnNetCore() => typeof(object).Assembly.GetName().Name != "mscorlib"; - -#if NET46 -#pragma warning disable IDE1006 // Naming Styles - [DllImport("libc")] - private static extern int sysctlbyname( - [MarshalAs(UnmanagedType.LPStr)] string property, - IntPtr output, - IntPtr oldLen, - IntPtr newp, - uint newlen); -#pragma warning restore IDE1006 // Naming Styles - - private static bool TryGetIsRunningOnMac() - { - const string OsType = "kern.ostype"; - const string MacOsType = "Darwin"; - - return MacOsType == GetOsType(); - - string GetOsType() - { - try - { - IntPtr - pointerLength = IntPtr.Zero, - pointerString = IntPtr.Zero; - - try - { - pointerLength = Marshal.AllocHGlobal(sizeof(int)); - - sysctlbyname(OsType, IntPtr.Zero, pointerLength, IntPtr.Zero, 0); - - var length = Marshal.ReadInt32(pointerLength); - - if (length <= 0) - { - return string.Empty; - } - - pointerString = Marshal.AllocHGlobal(length); - - sysctlbyname(OsType, pointerString, pointerLength, IntPtr.Zero, 0); - - return Marshal.PtrToStringAnsi(pointerString); - } - finally - { - if (pointerLength != IntPtr.Zero) - { - Marshal.FreeHGlobal(pointerLength); - } - if (pointerString != IntPtr.Zero) - { - Marshal.FreeHGlobal(pointerString); - } - } - } - catch - { - return null; - } - } - } -#endif } } diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 51e0cd860..c49295bec 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -22,9 +22,7 @@ public static class GlobalSettings private static bool nativeLibraryPathLocked; private static string nativeLibraryDefaultPath; -#if !NET46 private static bool useManagedHttpSmartSubtransport; -#endif internal class SmartSubtransportData { @@ -85,9 +83,7 @@ private static string GetExecutingAssemblyDirectory() /// public static Version Version => version.Value; -#if !NET46 internal static bool ManagedHttpSmartSubtransportEnabled => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || useManagedHttpSmartSubtransport; -#endif private static SmartSubtransportData GetOrCreateSmartSubtransportData(string scheme) { @@ -544,7 +540,6 @@ public static string GetUserAgent() return Proxy.git_libgit2_opts_get_user_agent(); } -#if !NET46 /// /// Enables the managed http implementation. This is enabled autmatically on Linux, so this method is only needed when running on Windows or macOS. /// @@ -552,6 +547,5 @@ public static void UseManagedHttpSmartSubtransport() { useManagedHttpSmartSubtransport = true; } -#endif } } diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 361a33903..a70de6d80 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net46;net472 + netstandard2.0 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .Net and Mono. LibGit2Sharp contributors diff --git a/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj b/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj index 72f64ea29..3bca18b34 100644 --- a/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj +++ b/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj @@ -2,7 +2,7 @@ Exe - net46;net472 + net472 x64 diff --git a/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj b/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj index 49cad97a0..0596f203c 100644 --- a/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj +++ b/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj @@ -2,7 +2,7 @@ Exe - net46;net472 + net472 x86 From 86be04252a20c5cfcd4932b1681b56ec5f3ee7bf Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 30 May 2020 15:24:24 -0400 Subject: [PATCH 082/179] Change to an opt-out model for the managed implementation --- LibGit2Sharp/GlobalSettings.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index c49295bec..a456f87f3 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -22,7 +22,7 @@ public static class GlobalSettings private static bool nativeLibraryPathLocked; private static string nativeLibraryDefaultPath; - private static bool useManagedHttpSmartSubtransport; + private static bool useManagedHttpSmartSubtransport = true; internal class SmartSubtransportData { @@ -541,11 +541,11 @@ public static string GetUserAgent() } /// - /// Enables the managed http implementation. This is enabled autmatically on Linux, so this method is only needed when running on Windows or macOS. + /// Enables the native http implementation. This can only be enabled on Windows or macOS. /// - public static void UseManagedHttpSmartSubtransport() + public static void UseNativeHttpTransport() { - useManagedHttpSmartSubtransport = true; + useManagedHttpSmartSubtransport = false; } } } From 0bea3cfd86a6d20a42b0e168b119906487239512 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 30 May 2020 17:08:12 -0400 Subject: [PATCH 083/179] WIP Try using CredentialCache --- .../Core/ManagedHttpSmartSubtransport.cs | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 76bb21573..10e3efe34 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -49,10 +49,26 @@ private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream { private static int MAX_REDIRECTS = 7; + private static readonly HttpClientHandler httpClientHandler; + private static readonly CredentialCache credentialCache; + private MemoryStream postBuffer = new MemoryStream(); private HttpResponseMessage response; private Stream responseStream; + static ManagedHttpSmartSubtransportStream() + { + httpClientHandler = new HttpClientHandler(); + + httpClientHandler.SslProtocols |= SslProtocols.Tls12; + //httpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationProxy; + + httpClientHandler.AllowAutoRedirect = false; + + credentialCache = new CredentialCache(); + httpClientHandler.Credentials = credentialCache; + } + public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, string endpointUrl, bool isPost, string contentType) : base(parent) { @@ -63,7 +79,7 @@ public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, s private HttpClient CreateHttpClient(HttpMessageHandler handler) { - return new HttpClient(handler) + return new HttpClient(handler, false) { DefaultRequestHeaders = { @@ -73,17 +89,6 @@ private HttpClient CreateHttpClient(HttpMessageHandler handler) }; } - private HttpClientHandler CreateClientHandler() - { - var httpClientHandler = new HttpClientHandler(); - httpClientHandler.SslProtocols |= SslProtocols.Tls12; - httpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationProxy; - - httpClientHandler.AllowAutoRedirect = false; - - return httpClientHandler; - } - private Uri EndpointUrl { get; set; } private bool IsPost { get; set; } @@ -157,16 +162,12 @@ private HttpRequestMessage CreateRequest(Uri endpointUrl, bool isPost) private HttpResponseMessage GetResponseWithRedirects() { - ICredentials credentials = null; var url = EndpointUrl; int retries; for (retries = 0; ; retries++) { - var httpClientHandler = CreateClientHandler(); - httpClientHandler.Credentials = credentials; - - using (var httpClient = this.CreateHttpClient(httpClientHandler)) + using (var httpClient = CreateHttpClient(httpClientHandler)) { var request = CreateRequest(url, IsPost); @@ -198,14 +199,15 @@ private HttpResponseMessage GetResponseWithRedirects() throw new InvalidOperationException("authentication cancelled"); } + var scheme = response.Headers.WwwAuthenticate.First().Scheme; + if (cred is DefaultCredentials) { - credentials = CredentialCache.DefaultNetworkCredentials; + credentialCache.Add(url, scheme, CredentialCache.DefaultNetworkCredentials); } - else if (cred is UsernamePasswordCredentials) + else if (cred is UsernamePasswordCredentials userpass) { - UsernamePasswordCredentials userpass = (UsernamePasswordCredentials)cred; - credentials = new NetworkCredential(userpass.Username, userpass.Password); + credentialCache.Add(url, scheme, new NetworkCredential(userpass.Username, userpass.Password)); } continue; From 2c763f7fba66f1f6aa10c932f26b9d4ee41d0196 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 30 May 2020 17:49:27 -0400 Subject: [PATCH 084/179] Make test pass, can't do this for real though --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 10e3efe34..9725add92 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -75,6 +75,9 @@ public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, s EndpointUrl = new Uri(endpointUrl); IsPost = isPost; ContentType = contentType; + + //If we have any concurrency, this is a bad thing to do... + httpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationProxy; } private HttpClient CreateHttpClient(HttpMessageHandler handler) From 9b6043fa6c3a6c16917dfc88576a4bd115a4973c Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 30 May 2020 18:02:15 -0400 Subject: [PATCH 085/179] Nevermind, can't change handler properties after it's been used --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 9725add92..10e3efe34 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -75,9 +75,6 @@ public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, s EndpointUrl = new Uri(endpointUrl); IsPost = isPost; ContentType = contentType; - - //If we have any concurrency, this is a bad thing to do... - httpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationProxy; } private HttpClient CreateHttpClient(HttpMessageHandler handler) From c5bd90a3ec68a8fda7ee6e533feb4da0afa2f624 Mon Sep 17 00:00:00 2001 From: Stijn Rutten Date: Thu, 11 Jun 2020 11:10:20 +0200 Subject: [PATCH 086/179] Apply suggestions from code review --- LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs | 10 ++++++++-- LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs | 2 +- LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs | 4 ++-- LibGit2Sharp/ContentChanges.cs | 8 ++------ LibGit2Sharp/Patch.cs | 13 ++++--------- 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs index d710750e7..046fe5214 100644 --- a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs +++ b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs @@ -1,7 +1,7 @@ -using LibGit2Sharp.Tests.TestHelpers; -using System.IO; +using System.IO; using System.Linq; using System.Text; +using LibGit2Sharp.Tests.TestHelpers; using Xunit; namespace LibGit2Sharp.Tests @@ -227,6 +227,12 @@ public void DiffSetsTheAddedAndDeletedLinesCorrectly() Assert.Single(changes.AddedLines); Assert.Single(changes.DeletedLines); + + Assert.Equal("4", changes.DeletedLines.First().Content); + Assert.Equal("5", changes.AddedLines.First().Content); + + Assert.Equal(4, changes.DeletedLines.First().LineNumber); + Assert.Equal(4, changes.AddedLines.First().LineNumber); } } diff --git a/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs index 6218dc858..b712a214b 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs @@ -1,7 +1,7 @@ -using LibGit2Sharp.Tests.TestHelpers; using System.IO; using System.Linq; using System.Text; +using LibGit2Sharp.Tests.TestHelpers; using Xunit; namespace LibGit2Sharp.Tests diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs index 9137ab138..d03b26e4e 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs @@ -1,8 +1,8 @@ -using LibGit2Sharp.Tests.TestHelpers; -using System; +using System; using System.IO; using System.Linq; using System.Text; +using LibGit2Sharp.Tests.TestHelpers; using Xunit; namespace LibGit2Sharp.Tests diff --git a/LibGit2Sharp/ContentChanges.cs b/LibGit2Sharp/ContentChanges.cs index f88a2d493..25e824b82 100644 --- a/LibGit2Sharp/ContentChanges.cs +++ b/LibGit2Sharp/ContentChanges.cs @@ -23,9 +23,6 @@ protected ContentChanges() internal unsafe ContentChanges(Repository repo, Blob oldBlob, Blob newBlob, GitDiffOptions options) { - AddedLines = new List(); - DeletedLines = new List(); - Proxy.git_diff_blobs(repo.Handle, oldBlob != null ? oldBlob.Id : null, newBlob != null ? newBlob.Id : null, @@ -58,13 +55,12 @@ internal void AppendToPatch(string patch) /// /// Lis of all lines added. /// - public virtual List AddedLines { get; internal set; } + public virtual List AddedLines { get; } = new List(); /// /// List of all lines deleted. /// - public virtual List DeletedLines { get; internal set; } - + public virtual List DeletedLines { get; } = new List(); /// /// The patch corresponding to these changes. diff --git a/LibGit2Sharp/Patch.cs b/LibGit2Sharp/Patch.cs index b38349efc..50157eb32 100644 --- a/LibGit2Sharp/Patch.cs +++ b/LibGit2Sharp/Patch.cs @@ -1,11 +1,11 @@ -using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Handles; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Text; +using LibGit2Sharp.Core; +using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp { @@ -68,11 +68,6 @@ private unsafe int PrintCallBack(git_diff_delta* delta, GitDiffHunk hunk, GitDif PatchEntryChanges currentChange = this[filePath]; string prefix = string.Empty; - string decodedContent = LaxUtf8Marshaler.FromNative(line.content, (int)line.contentLen); - - currentChange.AddedLines = currentChange.AddedLines ?? new List(); - currentChange.DeletedLines = currentChange.DeletedLines ?? new List(); - switch (line.lineOrigin) { case GitDiffLineOrigin.GIT_DIFF_LINE_CONTEXT: @@ -82,14 +77,14 @@ private unsafe int PrintCallBack(git_diff_delta* delta, GitDiffHunk hunk, GitDif case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION: linesAdded++; currentChange.LinesAdded++; - currentChange.AddedLines.Add(new Line(line.NewLineNo, decodedContent)); + currentChange.AddedLines.Add(new Line(line.NewLineNo, patchPart)); prefix = "+"; break; case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION: linesDeleted++; currentChange.LinesDeleted++; - currentChange.DeletedLines.Add(new Line(line.OldLineNo, decodedContent)); + currentChange.DeletedLines.Add(new Line(line.OldLineNo, patchPart)); prefix = "-"; break; } From 868eb38791eed97d6e829f88e913eda5c2d3c4ce Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 7 Nov 2020 12:09:10 -0500 Subject: [PATCH 087/179] Always use managed https transport --- LibGit2Sharp/Core/NativeMethods.cs | 2 +- LibGit2Sharp/GlobalSettings.cs | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 3db92ba58..00b035457 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -197,7 +197,7 @@ private static void InitializeNativeLibrary() } // Configure the .NET HTTP(S) mechanism on the first initialization of the library in the current process. - if (initCounter == 1 && GlobalSettings.ManagedHttpSmartSubtransportEnabled) + if (initCounter == 1) { httpSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("http"); httpsSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("https"); diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index a456f87f3..1e5d17a19 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -22,8 +22,6 @@ public static class GlobalSettings private static bool nativeLibraryPathLocked; private static string nativeLibraryDefaultPath; - private static bool useManagedHttpSmartSubtransport = true; - internal class SmartSubtransportData { internal bool isCustom; @@ -83,8 +81,6 @@ private static string GetExecutingAssemblyDirectory() /// public static Version Version => version.Value; - internal static bool ManagedHttpSmartSubtransportEnabled => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || useManagedHttpSmartSubtransport; - private static SmartSubtransportData GetOrCreateSmartSubtransportData(string scheme) { Ensure.ArgumentNotNull(scheme, "scheme"); @@ -539,13 +535,5 @@ public static string GetUserAgent() { return Proxy.git_libgit2_opts_get_user_agent(); } - - /// - /// Enables the native http implementation. This can only be enabled on Windows or macOS. - /// - public static void UseNativeHttpTransport() - { - useManagedHttpSmartSubtransport = false; - } } } From a514c5f860eafad99442a951026007611f752649 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 7 Nov 2020 12:15:48 -0500 Subject: [PATCH 088/179] Remove certificate validation check --- .../Core/ManagedHttpSmartSubtransport.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index 10e3efe34..fe2b98336 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -61,7 +61,6 @@ static ManagedHttpSmartSubtransportStream() httpClientHandler = new HttpClientHandler(); httpClientHandler.SslProtocols |= SslProtocols.Tls12; - //httpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationProxy; httpClientHandler.AllowAutoRedirect = false; @@ -122,22 +121,6 @@ public override int Write(Stream dataStream, long length) return 0; } - private bool CertificateValidationProxy(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) - { - try - { - int ret = SmartTransport.CertificateCheck(new CertificateX509(cert), (errors == SslPolicyErrors.None), EndpointUrl.Host); - Ensure.ZeroResult(ret); - - return true; - } - catch (Exception e) - { - SetError(e); - return false; - } - } - private string GetUserAgent() { string userAgent = GlobalSettings.GetUserAgent(); From 665eb5f3d8decd2abd6768a605556b876da8757f Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 7 Nov 2020 12:26:53 -0500 Subject: [PATCH 089/179] Add lock to credential cache modifications --- LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index fe2b98336..bcc2cfe3d 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -186,11 +186,17 @@ private HttpResponseMessage GetResponseWithRedirects() if (cred is DefaultCredentials) { - credentialCache.Add(url, scheme, CredentialCache.DefaultNetworkCredentials); + lock (credentialCache) + { + credentialCache.Add(url, scheme, CredentialCache.DefaultNetworkCredentials); + } } else if (cred is UsernamePasswordCredentials userpass) { - credentialCache.Add(url, scheme, new NetworkCredential(userpass.Username, userpass.Password)); + lock (credentialCache) + { + credentialCache.Add(url, scheme, new NetworkCredential(userpass.Username, userpass.Password)); + } } continue; From 2c90f417858f25a9cacd8441df6ef697d69afd72 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 7 Nov 2020 12:34:23 -0500 Subject: [PATCH 090/179] Add netcoreapp2.1 target --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index a70de6d80..655b47dac 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0;netcoreapp2.1 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .Net and Mono. LibGit2Sharp contributors From d4a6cd41e2013f2a4ccde29411d1f2fc65dcf4e5 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 7 Nov 2020 12:34:58 -0500 Subject: [PATCH 091/179] Remove unneeded reference --- LibGit2Sharp/LibGit2Sharp.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 655b47dac..fe5f98ea9 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -31,10 +31,6 @@ - - - - From 4a9af01f6af39224ca2f69a9ec0bb93fdccbf6d6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 7 Nov 2020 12:47:21 -0500 Subject: [PATCH 092/179] Use SocketsHttpHandler on .NET Core --- .../Core/ManagedHttpSmartSubtransport.cs | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs index bcc2cfe3d..88eced880 100644 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs @@ -3,9 +3,7 @@ using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Security; using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; namespace LibGit2Sharp.Core { @@ -49,7 +47,12 @@ private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream { private static int MAX_REDIRECTS = 7; - private static readonly HttpClientHandler httpClientHandler; +#if NETCOREAPP + private static readonly SocketsHttpHandler httpHandler; +#else + private static readonly HttpClientHandler httpHandler; +#endif + private static readonly CredentialCache credentialCache; private MemoryStream postBuffer = new MemoryStream(); @@ -58,14 +61,18 @@ private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream static ManagedHttpSmartSubtransportStream() { - httpClientHandler = new HttpClientHandler(); - - httpClientHandler.SslProtocols |= SslProtocols.Tls12; +#if NETCOREAPP + httpHandler = new SocketsHttpHandler(); + httpHandler.PooledConnectionLifetime = TimeSpan.FromMinutes(5); +#else + httpHandler = new HttpClientHandler(); + httpHandler.SslProtocols |= SslProtocols.Tls12; +#endif - httpClientHandler.AllowAutoRedirect = false; + httpHandler.AllowAutoRedirect = false; credentialCache = new CredentialCache(); - httpClientHandler.Credentials = credentialCache; + httpHandler.Credentials = credentialCache; } public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, string endpointUrl, bool isPost, string contentType) @@ -150,7 +157,7 @@ private HttpResponseMessage GetResponseWithRedirects() for (retries = 0; ; retries++) { - using (var httpClient = CreateHttpClient(httpClientHandler)) + using (var httpClient = CreateHttpClient(httpHandler)) { var request = CreateRequest(url, IsPost); From 2fae75f7de69a771b7d7f2488f2b3c9d8638a8ac Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 7 Nov 2020 13:05:45 -0500 Subject: [PATCH 093/179] Comment out test using deleted repo --- LibGit2Sharp.Tests/FileHistoryFixture.cs | 98 ++++++++++++------------ 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/LibGit2Sharp.Tests/FileHistoryFixture.cs b/LibGit2Sharp.Tests/FileHistoryFixture.cs index 5380e66de..e6465d1ac 100644 --- a/LibGit2Sharp.Tests/FileHistoryFixture.cs +++ b/LibGit2Sharp.Tests/FileHistoryFixture.cs @@ -10,54 +10,56 @@ namespace LibGit2Sharp.Tests { public class FileHistoryFixture : BaseFixture { - [Theory] - [InlineData("https://github.com/nulltoken/follow-test.git")] - public void CanDealWithFollowTest(string url) - { - var scd = BuildSelfCleaningDirectory(); - var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath); - - using (var repo = new Repository(clonedRepoPath)) - { - // $ git log --follow --format=oneline so-renamed.txt - // 88f91835062161febb46fb270ef4188f54c09767 Update not-yet-renamed.txt AND rename into so-renamed.txt - // ef7cb6a63e32595fffb092cb1ae9a32310e58850 Add not-yet-renamed.txt - var fileHistoryEntries = repo.Commits.QueryBy("so-renamed.txt").ToList(); - Assert.Equal(2, fileHistoryEntries.Count()); - Assert.Equal("88f91835062161febb46fb270ef4188f54c09767", fileHistoryEntries[0].Commit.Sha); - Assert.Equal("ef7cb6a63e32595fffb092cb1ae9a32310e58850", fileHistoryEntries[1].Commit.Sha); - - // $ git log --follow --format=oneline untouched.txt - // c10c1d5f74b76f20386d18674bf63fbee6995061 Initial commit - fileHistoryEntries = repo.Commits.QueryBy("untouched.txt").ToList(); - Assert.Single(fileHistoryEntries); - Assert.Equal("c10c1d5f74b76f20386d18674bf63fbee6995061", fileHistoryEntries[0].Commit.Sha); - - // $ git log --follow --format=oneline under-test.txt - // 0b5b18f2feb917dee98df1210315b2b2b23c5bec Rename file renamed.txt into under-test.txt - // 49921d463420a892c9547a326632ef6a9ba3b225 Update file renamed.txt - // 70f636e8c64bbc2dfef3735a562bb7e195d8019f Rename file under-test.txt into renamed.txt - // d3868d57a6aaf2ae6ed4887d805ae4bc91d8ce4d Updated file under test - // 9da10ef7e139c49604a12caa866aae141f38b861 Updated file under test - // 599a5d821fb2c0a25855b4233e26d475c2fbeb34 Updated file under test - // 678b086b44753000567aa64344aa0d8034fa0083 Updated file under test - // 8f7d9520f306771340a7c79faea019ad18e4fa1f Updated file under test - // bd5f8ee279924d33be8ccbde82e7f10b9d9ff237 Updated file under test - // c10c1d5f74b76f20386d18674bf63fbee6995061 Initial commit - fileHistoryEntries = repo.Commits.QueryBy("under-test.txt").ToList(); - Assert.Equal(10, fileHistoryEntries.Count()); - Assert.Equal("0b5b18f2feb917dee98df1210315b2b2b23c5bec", fileHistoryEntries[0].Commit.Sha); - Assert.Equal("49921d463420a892c9547a326632ef6a9ba3b225", fileHistoryEntries[1].Commit.Sha); - Assert.Equal("70f636e8c64bbc2dfef3735a562bb7e195d8019f", fileHistoryEntries[2].Commit.Sha); - Assert.Equal("d3868d57a6aaf2ae6ed4887d805ae4bc91d8ce4d", fileHistoryEntries[3].Commit.Sha); - Assert.Equal("9da10ef7e139c49604a12caa866aae141f38b861", fileHistoryEntries[4].Commit.Sha); - Assert.Equal("599a5d821fb2c0a25855b4233e26d475c2fbeb34", fileHistoryEntries[5].Commit.Sha); - Assert.Equal("678b086b44753000567aa64344aa0d8034fa0083", fileHistoryEntries[6].Commit.Sha); - Assert.Equal("8f7d9520f306771340a7c79faea019ad18e4fa1f", fileHistoryEntries[7].Commit.Sha); - Assert.Equal("bd5f8ee279924d33be8ccbde82e7f10b9d9ff237", fileHistoryEntries[8].Commit.Sha); - Assert.Equal("c10c1d5f74b76f20386d18674bf63fbee6995061", fileHistoryEntries[9].Commit.Sha); - } - } + //Looks like nulltoken deleted the repo this test was using + + //[Theory] + //[InlineData("https://github.com/nulltoken/follow-test.git")] + //public void CanDealWithFollowTest(string url) + //{ + // var scd = BuildSelfCleaningDirectory(); + // var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath); + + // using (var repo = new Repository(clonedRepoPath)) + // { + // // $ git log --follow --format=oneline so-renamed.txt + // // 88f91835062161febb46fb270ef4188f54c09767 Update not-yet-renamed.txt AND rename into so-renamed.txt + // // ef7cb6a63e32595fffb092cb1ae9a32310e58850 Add not-yet-renamed.txt + // var fileHistoryEntries = repo.Commits.QueryBy("so-renamed.txt").ToList(); + // Assert.Equal(2, fileHistoryEntries.Count()); + // Assert.Equal("88f91835062161febb46fb270ef4188f54c09767", fileHistoryEntries[0].Commit.Sha); + // Assert.Equal("ef7cb6a63e32595fffb092cb1ae9a32310e58850", fileHistoryEntries[1].Commit.Sha); + + // // $ git log --follow --format=oneline untouched.txt + // // c10c1d5f74b76f20386d18674bf63fbee6995061 Initial commit + // fileHistoryEntries = repo.Commits.QueryBy("untouched.txt").ToList(); + // Assert.Single(fileHistoryEntries); + // Assert.Equal("c10c1d5f74b76f20386d18674bf63fbee6995061", fileHistoryEntries[0].Commit.Sha); + + // // $ git log --follow --format=oneline under-test.txt + // // 0b5b18f2feb917dee98df1210315b2b2b23c5bec Rename file renamed.txt into under-test.txt + // // 49921d463420a892c9547a326632ef6a9ba3b225 Update file renamed.txt + // // 70f636e8c64bbc2dfef3735a562bb7e195d8019f Rename file under-test.txt into renamed.txt + // // d3868d57a6aaf2ae6ed4887d805ae4bc91d8ce4d Updated file under test + // // 9da10ef7e139c49604a12caa866aae141f38b861 Updated file under test + // // 599a5d821fb2c0a25855b4233e26d475c2fbeb34 Updated file under test + // // 678b086b44753000567aa64344aa0d8034fa0083 Updated file under test + // // 8f7d9520f306771340a7c79faea019ad18e4fa1f Updated file under test + // // bd5f8ee279924d33be8ccbde82e7f10b9d9ff237 Updated file under test + // // c10c1d5f74b76f20386d18674bf63fbee6995061 Initial commit + // fileHistoryEntries = repo.Commits.QueryBy("under-test.txt").ToList(); + // Assert.Equal(10, fileHistoryEntries.Count()); + // Assert.Equal("0b5b18f2feb917dee98df1210315b2b2b23c5bec", fileHistoryEntries[0].Commit.Sha); + // Assert.Equal("49921d463420a892c9547a326632ef6a9ba3b225", fileHistoryEntries[1].Commit.Sha); + // Assert.Equal("70f636e8c64bbc2dfef3735a562bb7e195d8019f", fileHistoryEntries[2].Commit.Sha); + // Assert.Equal("d3868d57a6aaf2ae6ed4887d805ae4bc91d8ce4d", fileHistoryEntries[3].Commit.Sha); + // Assert.Equal("9da10ef7e139c49604a12caa866aae141f38b861", fileHistoryEntries[4].Commit.Sha); + // Assert.Equal("599a5d821fb2c0a25855b4233e26d475c2fbeb34", fileHistoryEntries[5].Commit.Sha); + // Assert.Equal("678b086b44753000567aa64344aa0d8034fa0083", fileHistoryEntries[6].Commit.Sha); + // Assert.Equal("8f7d9520f306771340a7c79faea019ad18e4fa1f", fileHistoryEntries[7].Commit.Sha); + // Assert.Equal("bd5f8ee279924d33be8ccbde82e7f10b9d9ff237", fileHistoryEntries[8].Commit.Sha); + // Assert.Equal("c10c1d5f74b76f20386d18674bf63fbee6995061", fileHistoryEntries[9].Commit.Sha); + // } + //} [Theory] [InlineData(null)] From fd8e277a04e34a2628b6bf9620ec59b7362dac0b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 7 Nov 2020 13:08:34 -0500 Subject: [PATCH 094/179] Comment out certificate check test --- LibGit2Sharp.Tests/CloneFixture.cs | 118 ++++++++++++++--------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 09af475fd..bbe6a7f33 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -237,65 +237,65 @@ public void CanCloneFromBBWithCredentials(string url, string user, string pass, } } - [SkippableTheory] - [InlineData("https://github.com/libgit2/TestGitRepository.git", "github.com", typeof(CertificateX509))] - [InlineData("git@github.com:libgit2/TestGitRepository.git", "github.com", typeof(CertificateSsh))] - public void CanInspectCertificateOnClone(string url, string hostname, Type certType) - { - var scd = BuildSelfCleaningDirectory(); - - InconclusiveIf( - () => - certType == typeof (CertificateSsh) && !GlobalSettings.Version.Features.HasFlag(BuiltInFeatures.Ssh), - "SSH not supported"); - - bool wasCalled = false; - bool checksHappy = false; - - var options = new CloneOptions { - CertificateCheck = (cert, valid, host) => { - wasCalled = true; - - Assert.Equal(hostname, host); - Assert.Equal(certType, cert.GetType()); - - if (certType == typeof(CertificateX509)) { - Assert.True(valid); - var x509 = ((CertificateX509)cert).Certificate; - // we get a string with the different fields instead of a structure, so... - Assert.Contains("CN=github.com,", x509.Subject); - checksHappy = true; - return false; - } - - if (certType == typeof(CertificateSsh)) { - var hostkey = (CertificateSsh)cert; - Assert.True(hostkey.HasMD5); - /* - * Once you've connected and thus your ssh has stored the hostkey, - * you can get the hostkey for a host with - * - * ssh-keygen -F github.com -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':' - * - * though GitHub's hostkey won't change anytime soon. - */ - Assert.Equal("1627aca576282d36631b564debdfa648", - BitConverter.ToString(hostkey.HashMD5).ToLower().Replace("-", "")); - checksHappy = true; - return false; - } - - return false; - }, - }; - - Assert.Throws(() => - Repository.Clone(url, scd.DirectoryPath, options) - ); - - Assert.True(wasCalled); - Assert.True(checksHappy); - } + //[SkippableTheory] + //[InlineData("https://github.com/libgit2/TestGitRepository.git", "github.com", typeof(CertificateX509))] + //[InlineData("git@github.com:libgit2/TestGitRepository.git", "github.com", typeof(CertificateSsh))] + //public void CanInspectCertificateOnClone(string url, string hostname, Type certType) + //{ + // var scd = BuildSelfCleaningDirectory(); + + // InconclusiveIf( + // () => + // certType == typeof (CertificateSsh) && !GlobalSettings.Version.Features.HasFlag(BuiltInFeatures.Ssh), + // "SSH not supported"); + + // bool wasCalled = false; + // bool checksHappy = false; + + // var options = new CloneOptions { + // CertificateCheck = (cert, valid, host) => { + // wasCalled = true; + + // Assert.Equal(hostname, host); + // Assert.Equal(certType, cert.GetType()); + + // if (certType == typeof(CertificateX509)) { + // Assert.True(valid); + // var x509 = ((CertificateX509)cert).Certificate; + // // we get a string with the different fields instead of a structure, so... + // Assert.Contains("CN=github.com,", x509.Subject); + // checksHappy = true; + // return false; + // } + + // if (certType == typeof(CertificateSsh)) { + // var hostkey = (CertificateSsh)cert; + // Assert.True(hostkey.HasMD5); + // /* + // * Once you've connected and thus your ssh has stored the hostkey, + // * you can get the hostkey for a host with + // * + // * ssh-keygen -F github.com -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':' + // * + // * though GitHub's hostkey won't change anytime soon. + // */ + // Assert.Equal("1627aca576282d36631b564debdfa648", + // BitConverter.ToString(hostkey.HashMD5).ToLower().Replace("-", "")); + // checksHappy = true; + // return false; + // } + + // return false; + // }, + // }; + + // Assert.Throws(() => + // Repository.Clone(url, scd.DirectoryPath, options) + // ); + + // Assert.True(wasCalled); + // Assert.True(checksHappy); + //} [Theory] [InlineData("git://github.com/libgit2/TestGitRepository")] From a7445ad08fc824d3e69241f94ba3a02be394ae36 Mon Sep 17 00:00:00 2001 From: yahavx <38952809+yahavx@users.noreply.github.com> Date: Mon, 25 Jan 2021 00:54:30 +0200 Subject: [PATCH 095/179] Update Branch.cs Fix documentation typo --- LibGit2Sharp/Branch.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/Branch.cs b/LibGit2Sharp/Branch.cs index d023e6153..807456688 100644 --- a/LibGit2Sharp/Branch.cs +++ b/LibGit2Sharp/Branch.cs @@ -162,7 +162,7 @@ public virtual string UpstreamBranchCanonicalName /// If this is a local branch, this will return the configured /// to fetch from and push to. If this is a /// remote-tracking branch, this will return the name of the remote - /// containing the tracked branch. If there no tracking information + /// containing the tracked branch. If there is no tracking information, /// this will return null. /// /// From b78b2900dfe3dc835e0e79f6e542672826bdbc9a Mon Sep 17 00:00:00 2001 From: Robin Ebert Date: Tue, 25 May 2021 11:02:10 +0200 Subject: [PATCH 096/179] Adjust GitStatusOptions to match structure of native libgit2 This fixes a marshaling bug that causes a segmentation fault --- LibGit2Sharp/Core/GitStatusOptions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LibGit2Sharp/Core/GitStatusOptions.cs b/LibGit2Sharp/Core/GitStatusOptions.cs index 3e9dbd5d9..d577cefe6 100644 --- a/LibGit2Sharp/Core/GitStatusOptions.cs +++ b/LibGit2Sharp/Core/GitStatusOptions.cs @@ -13,6 +13,8 @@ internal class GitStatusOptions : IDisposable public GitStrArrayManaged PathSpec; + public IntPtr Baseline = IntPtr.Zero; + public void Dispose() { PathSpec.Dispose(); From 8a61eec544504f9cd79cf78d7bb1694e0737ec88 Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 1 Jul 2021 14:49:29 +1000 Subject: [PATCH 097/179] Update `git_worktree_add_options` struct to include ref pointer Native struct https://github.com/libgit2/libgit2/blob/main/include/git2/worktree.h#L88 Fixes https://github.com/libgit2/libgit2sharp/issues/1885 --- LibGit2Sharp/Core/GitWorktree.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp/Core/GitWorktree.cs b/LibGit2Sharp/Core/GitWorktree.cs index 64f90ebb7..c71cb16c0 100644 --- a/LibGit2Sharp/Core/GitWorktree.cs +++ b/LibGit2Sharp/Core/GitWorktree.cs @@ -33,8 +33,10 @@ internal enum GitWorktreePruneOptionFlags : uint internal class git_worktree_add_options { public uint version = 1; - + public int locked; + + public IntPtr @ref = IntPtr.Zero; } [StructLayout(LayoutKind.Sequential)] From 05fb439afe928c6579dff21f97ffa2cc59f3f8c1 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 18:18:45 -0400 Subject: [PATCH 098/179] Update .NET SDK --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 05d0ae3d2..5ecd5ee6e 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.1.201" + "version": "5.0.301" } } From ae450c9317d5fe98fd94bf7b99a5c785c2820098 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 18:24:09 -0400 Subject: [PATCH 099/179] Update test TFMs --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 8 +++---- azure-pipelines/dotnet.yml | 23 ++++++-------------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 0525e98c8..71f28b6ac 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,13 +1,13 @@  - net472;netcoreapp2.1 + net472;netcoreapp2.1;net5.0 - - + + @@ -23,7 +23,7 @@ - + diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index 066d14412..3bc1eaf50 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -6,22 +6,6 @@ steps: - script: dotnet pack --no-build -c $(BuildConfiguration) /v:m /bl:"$(Build.ArtifactStagingDirectory)/build_logs/pack.binlog" displayName: dotnet pack -- task: DotNetCoreCLI@2 - displayName: dotnet test -f net46 (w/ coverage) - inputs: - command: test - arguments: --no-build -c $(BuildConfiguration) -f net46 --filter "TestCategory!=FailsInCloudTest & TestCategory!=FailsWhileInstrumented" -v n /p:CollectCoverage=true - testRunTitle: net46-$(Agent.JobName) - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - -- task: DotNetCoreCLI@2 - displayName: dotnet test -f net46 (w/o coverage) - inputs: - command: test - arguments: --no-build -c $(BuildConfiguration) -f net46 --filter "TestCategory!=FailsInCloudTest & TestCategory=FailsWhileInstrumented" -v n - testRunTitle: net46-$(Agent.JobName)-nocoverage - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - - task: DotNetCoreCLI@2 displayName: dotnet test -f net472 (w/ coverage) inputs: @@ -45,6 +29,13 @@ steps: arguments: --no-build -c $(BuildConfiguration) -f netcoreapp2.1 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true testRunTitle: netcoreapp2.1-$(Agent.JobName) +- task: DotNetCoreCLI@2 + displayName: dotnet test -f net5.0 + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f net5.0 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true + testRunTitle: net5.0-$(Agent.JobName) + - task: PowerShell@2 inputs: filePath: azure-pipelines/artifacts/_pipelines.ps1 From 168b62f3614238b29682cd986066ee13c83a72c6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 18:29:01 -0400 Subject: [PATCH 100/179] Suppress Encoding.UTF7 warning --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 71f28b6ac..162fffac1 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -2,6 +2,7 @@ net472;netcoreapp2.1;net5.0 + $(NoWarn);SYSLIB0001 From 5bfaca5564cf0954e90cffd677caf6a1342a35b4 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 18:33:39 -0400 Subject: [PATCH 101/179] Fix Assembly.CodeBase warning --- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index 51496c2f5..5bd666a85 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -7,7 +7,6 @@ using System.Reflection; using System.Text; using System.Text.RegularExpressions; -using LibGit2Sharp.Core; using Xunit; namespace LibGit2Sharp.Tests.TestHelpers @@ -65,7 +64,11 @@ private static void SetUpTestEnvironment() if (resourcesPath == null) { +#if NETFRAMEWORK resourcesPath = Path.Combine(Directory.GetParent(new Uri(typeof(BaseFixture).GetTypeInfo().Assembly.CodeBase).LocalPath).FullName, "Resources"); +#else + resourcesPath = Path.Combine(Directory.GetParent(typeof(BaseFixture).GetTypeInfo().Assembly.Location).FullName, "Resources"); +#endif } ResourcesDirectory = new DirectoryInfo(resourcesPath); From 17ad66b3875f2c36499bc4ff53bcc8bf4d6f30a9 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 18:40:18 -0400 Subject: [PATCH 102/179] Remove explicit reference to reference assemblies package --- Directory.Build.props | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index d98520a64..06e7f5642 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,8 +7,5 @@ $(MSBuildThisFileDirectory)bin\Packages\$(Configuration)\ $(DefineConstants);$(ExtraDefine) - - - - + From f1c9dd7a578224ccb0bf76a83afae490523453a7 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 18:40:47 -0400 Subject: [PATCH 103/179] Update Nerdbank.GitVersioning --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index fe5f98ea9..ebd48acac 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -34,7 +34,7 @@ - + From b62c6737a55de52e8fe5e5a8e91fb057eeed95aa Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 18:43:39 -0400 Subject: [PATCH 104/179] Update testing packages --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 162fffac1..c22341d0c 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -13,13 +13,13 @@ - - + + - - + + From b1b6492f869cf63fb2766615ae640a5d3f3a440d Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 18:45:02 -0400 Subject: [PATCH 105/179] Remove System.ValueTuple --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index c22341d0c..e78a672a3 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -15,7 +15,6 @@ - From 7456cca6648b2b3e69f1e5f5c6d37f6bc1bb4886 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 19:00:55 -0400 Subject: [PATCH 106/179] Don't test UTF7 on .NET 5 --- LibGit2Sharp.Tests/BlobFixture.cs | 5 +++-- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/BlobFixture.cs b/LibGit2Sharp.Tests/BlobFixture.cs index e6a5f3c57..7afbe255f 100644 --- a/LibGit2Sharp.Tests/BlobFixture.cs +++ b/LibGit2Sharp.Tests/BlobFixture.cs @@ -3,7 +3,6 @@ using System.Text; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -44,6 +43,7 @@ public void CanGetBlobAsFilteredText(string autocrlf, string expectedText) } } +#if NETFRAMEWORK || NETCOREAPP2_1 [Theory] [InlineData("ascii", 4, "31 32 33 34")] [InlineData("utf-7", 4, "31 32 33 34")] @@ -83,6 +83,7 @@ public void CanGetBlobAsTextWithVariousEncodings(string encodingName, int expect Assert.Equal(expectedUtf7Chars, string.Join(" ", utf7Chars)); } } +#endif [Fact] public void CanGetBlobSize() @@ -185,7 +186,7 @@ public void CanStageAFileGeneratedFromABlobContentStream() var sb = new StringBuilder(); for (int j = 0; j < 2000; j++) { - sb.Append(((i + 1)*(j + 1)).ToString("X8")); + sb.Append(((i + 1) * (j + 1)).ToString("X8")); } File.AppendAllText(Path.Combine(repo.Info.WorkingDirectory, "small.txt"), sb.ToString()); } diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index e78a672a3..1810df2ee 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -2,7 +2,6 @@ net472;netcoreapp2.1;net5.0 - $(NoWarn);SYSLIB0001 From 37a094c678e16919608ff9c3d1b7c61202f0fccd Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Jul 2021 19:29:22 -0400 Subject: [PATCH 107/179] Fix LeaksContainer --- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index 5bd666a85..8d9b9ba0c 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -20,7 +20,7 @@ public BaseFixture() BuildFakeConfigs(this); #if LEAKS_IDENTIFYING - LeaksContainer.Clear(); + Core.LeaksContainer.Clear(); #endif } @@ -276,11 +276,11 @@ public virtual void Dispose() GC.Collect(); GC.WaitForPendingFinalizers(); - if (LeaksContainer.TypeNames.Any()) + if (Core.LeaksContainer.TypeNames.Any()) { Assert.False(true, string.Format("Some handles of the following types haven't been properly released: {0}.{1}" + "In order to get some help fixing those leaks, uncomment the define LEAKS_TRACKING in Libgit2Object.cs{1}" - + "and run the tests locally.", string.Join(", ", LeaksContainer.TypeNames), Environment.NewLine)); + + "and run the tests locally.", string.Join(", ", Core.LeaksContainer.TypeNames), Environment.NewLine)); } #endif } From 844ecd852f28caf39b23ce4cd83f5cc105c6c808 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Thu, 12 Aug 2021 22:11:20 -0400 Subject: [PATCH 108/179] Update SDK version --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 5ecd5ee6e..459551b1c 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "5.0.301" + "version": "5.0.400" } } From d68bcaa72ad7b72bcd349da7a18d23c1c073003e Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Thu, 12 Aug 2021 22:11:35 -0400 Subject: [PATCH 109/179] Update to LibGit2Sharp.NativeBinaries 2.0.314 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index ebd48acac..b00432a27 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,7 +32,7 @@ - + From 85ad3892dc1687b3da9ea10d1c98609780296b8c Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 22 Aug 2021 10:23:19 +0200 Subject: [PATCH 110/179] Update LibGit2 to version 1.1.1 --- LibGit2Sharp.Tests/CloneFixture.cs | 2 +- LibGit2Sharp.Tests/FetchFixture.cs | 8 ++--- LibGit2Sharp.Tests/RepositoryFixture.cs | 2 +- LibGit2Sharp/Core/NativeMethods.cs | 20 ++++++------- LibGit2Sharp/Core/Proxy.cs | 39 +++++++++++++------------ LibGit2Sharp/LibGit2Sharp.csproj | 2 +- LibGit2Sharp/ObjectDatabase.cs | 6 ++-- 7 files changed, 40 insertions(+), 39 deletions(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index bbe6a7f33..2408dad05 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -70,7 +70,7 @@ private void AssertLocalClone(string url, string path = null, bool isCloningAnEm Assert.NotEqual(originalRepo.Info.Path, clonedRepo.Info.Path); Assert.Equal(originalRepo.Head, clonedRepo.Head); - Assert.Equal(originalRepo.Branches.Count(), clonedRepo.Branches.Count(b => b.IsRemote)); + Assert.Equal(originalRepo.Branches.Count(), clonedRepo.Branches.Count(b => b.IsRemote && b.FriendlyName != "origin/HEAD")); Assert.Equal(isCloningAnEmptyRepository ? 0 : 1, clonedRepo.Branches.Count(b => !b.IsRemote)); Assert.Equal(originalRepo.Tags.Count(), clonedRepo.Tags.Count()); diff --git a/LibGit2Sharp.Tests/FetchFixture.cs b/LibGit2Sharp.Tests/FetchFixture.cs index 170b64d61..01c71ebfe 100644 --- a/LibGit2Sharp.Tests/FetchFixture.cs +++ b/LibGit2Sharp.Tests/FetchFixture.cs @@ -215,7 +215,7 @@ public void FetchHonorsTheFetchPruneConfigurationEntry() using (var clonedRepo = new Repository(clonedRepoPath)) { - Assert.Equal(5, clonedRepo.Branches.Count(b => b.IsRemote)); + Assert.Equal(5, clonedRepo.Branches.Count(b => b.IsRemote && b.FriendlyName != "origin/HEAD")); // Drop one of the branches in the remote repository using (var sourceRepo = new Repository(source)) @@ -226,17 +226,17 @@ public void FetchHonorsTheFetchPruneConfigurationEntry() // No pruning when the configuration entry isn't defined Assert.Null(clonedRepo.Config.Get("fetch.prune")); Commands.Fetch(clonedRepo, "origin", new string[0], null, null); - Assert.Equal(5, clonedRepo.Branches.Count(b => b.IsRemote)); + Assert.Equal(5, clonedRepo.Branches.Count(b => b.IsRemote && b.FriendlyName != "origin/HEAD")); // No pruning when the configuration entry is set to false clonedRepo.Config.Set("fetch.prune", false); Commands.Fetch(clonedRepo, "origin", new string[0], null, null); - Assert.Equal(5, clonedRepo.Branches.Count(b => b.IsRemote)); + Assert.Equal(5, clonedRepo.Branches.Count(b => b.IsRemote && b.FriendlyName != "origin/HEAD")); // Auto pruning when the configuration entry is set to true clonedRepo.Config.Set("fetch.prune", true); Commands.Fetch(clonedRepo, "origin", new string[0], null, null); - Assert.Equal(4, clonedRepo.Branches.Count(b => b.IsRemote)); + Assert.Equal(4, clonedRepo.Branches.Count(b => b.IsRemote && b.FriendlyName != "origin/HEAD")); } } diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs index 5c551fabd..7165e6cb7 100644 --- a/LibGit2Sharp.Tests/RepositoryFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryFixture.cs @@ -709,7 +709,7 @@ public void CanListRemoteReferencesWithCredentials() [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - [InlineData("git://github.com/libgit2/TestGitRepository.git")] + //[InlineData("git://github.com/libgit2/TestGitRepository.git")] public void CanListRemoteReferences(string url) { IEnumerable references = Repository.ListRemoteReferences(url).ToList(); diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 00b035457..f7c9dbf26 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -227,7 +227,7 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject internal static extern unsafe GitError* git_error_last(); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern void git_error_set_str( + internal static extern int git_error_set_str( GitErrorCategory error_class, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string errorString); @@ -252,25 +252,25 @@ internal static extern unsafe int git_blame_file( internal static extern unsafe void git_blame_free(git_blame* blame); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe int git_blob_create_fromdisk( + internal static extern unsafe int git_blob_create_from_disk( ref GitOid id, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe int git_blob_create_fromworkdir( + internal static extern unsafe int git_blob_create_from_workdir( ref GitOid id, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath relative_path); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe int git_blob_create_fromstream( + internal static extern unsafe int git_blob_create_from_stream( out IntPtr stream, git_repository* repositoryPtr, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string hintpath); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern int git_blob_create_fromstream_commit( + internal static extern int git_blob_create_from_stream_commit( ref GitOid oid, IntPtr stream); @@ -1616,7 +1616,7 @@ internal static extern unsafe int git_repository_open_ext( internal static extern unsafe FilePath git_repository_path(git_repository* repository); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe void git_repository_set_config( + internal static extern unsafe int git_repository_set_config( git_repository* repository, git_config* config); @@ -1628,7 +1628,7 @@ internal static extern unsafe int git_repository_set_ident( [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe void git_repository_set_index( + internal static extern unsafe int git_repository_set_index( git_repository* repository, git_index* index); @@ -1710,13 +1710,13 @@ internal static extern unsafe int git_revparse_ext( internal static extern unsafe int git_revwalk_push(git_revwalk* walker, ref GitOid id); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe void git_revwalk_reset(git_revwalk* walker); + internal static extern unsafe int git_revwalk_reset(git_revwalk* walker); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe void git_revwalk_sorting(git_revwalk* walk, CommitSortStrategies sort); + internal static extern unsafe int git_revwalk_sorting(git_revwalk* walk, CommitSortStrategies sort); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe void git_revwalk_simplify_first_parent(git_revwalk* walk); + internal static extern unsafe int git_revwalk_simplify_first_parent(git_revwalk* walk); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_signature_free(git_signature* signature); diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 86d632576..ca9a69f6d 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -36,34 +36,34 @@ public static unsafe BlameHandle git_blame_file( #region git_blob_ - public static unsafe IntPtr git_blob_create_fromstream(RepositoryHandle repo, string hintpath) + public static unsafe IntPtr git_blob_create_from_stream(RepositoryHandle repo, string hintpath) { IntPtr writestream_ptr; - Ensure.ZeroResult(NativeMethods.git_blob_create_fromstream(out writestream_ptr, repo, hintpath)); + Ensure.ZeroResult(NativeMethods.git_blob_create_from_stream(out writestream_ptr, repo, hintpath)); return writestream_ptr; } public static unsafe ObjectId git_blob_create_fromstream_commit(IntPtr writestream_ptr) { var oid = new GitOid(); - Ensure.ZeroResult(NativeMethods.git_blob_create_fromstream_commit(ref oid, writestream_ptr)); + Ensure.ZeroResult(NativeMethods.git_blob_create_from_stream_commit(ref oid, writestream_ptr)); return oid; } - public static unsafe ObjectId git_blob_create_fromdisk(RepositoryHandle repo, FilePath path) + public static unsafe ObjectId git_blob_create_from_disk(RepositoryHandle repo, FilePath path) { var oid = new GitOid(); - int res = NativeMethods.git_blob_create_fromdisk(ref oid, repo, path); + int res = NativeMethods.git_blob_create_from_disk(ref oid, repo, path); Ensure.ZeroResult(res); return oid; } - public static unsafe ObjectId git_blob_create_fromfile(RepositoryHandle repo, FilePath path) + public static unsafe ObjectId git_blob_create_from_workdir(RepositoryHandle repo, FilePath path) { var oid = new GitOid(); - int res = NativeMethods.git_blob_create_fromworkdir(ref oid, repo, path); + int res = NativeMethods.git_blob_create_from_workdir(ref oid, repo, path); Ensure.ZeroResult(res); return oid; @@ -855,21 +855,22 @@ public static unsafe int git_diff_num_deltas(DiffHandle diff) #region git_error_ - public static void git_error_set_str(GitErrorCategory error_class, Exception exception) + public static int git_error_set_str(GitErrorCategory error_class, Exception exception) { if (exception is OutOfMemoryException) { NativeMethods.git_error_set_oom(); + return 0; } else { - NativeMethods.git_error_set_str(error_class, ErrorMessageFromException(exception)); + return NativeMethods.git_error_set_str(error_class, ErrorMessageFromException(exception)); } } - public static void git_error_set_str(GitErrorCategory error_class, String errorString) + public static int git_error_set_str(GitErrorCategory error_class, String errorString) { - NativeMethods.git_error_set_str(error_class, errorString); + return NativeMethods.git_error_set_str(error_class, errorString); } /// @@ -2589,9 +2590,9 @@ public static unsafe FilePath git_repository_path(RepositoryHandle repo) return NativeMethods.git_repository_path(repo); } - public static unsafe void git_repository_set_config(RepositoryHandle repo, ConfigurationHandle config) + public static unsafe int git_repository_set_config(RepositoryHandle repo, ConfigurationHandle config) { - NativeMethods.git_repository_set_config(repo, config); + return NativeMethods.git_repository_set_config(repo, config); } public static unsafe void git_repository_set_ident(RepositoryHandle repo, string name, string email) @@ -2600,9 +2601,9 @@ public static unsafe void git_repository_set_ident(RepositoryHandle repo, string Ensure.ZeroResult(res); } - public static unsafe void git_repository_set_index(RepositoryHandle repo, IndexHandle index) + public static unsafe int git_repository_set_index(RepositoryHandle repo, IndexHandle index) { - NativeMethods.git_repository_set_index(repo, index); + return NativeMethods.git_repository_set_index(repo, index); } public static unsafe void git_repository_set_workdir(RepositoryHandle repo, FilePath workdir) @@ -2783,14 +2784,14 @@ public static unsafe void git_revwalk_reset(RevWalkerHandle walker) NativeMethods.git_revwalk_reset(walker); } - public static unsafe void git_revwalk_sorting(RevWalkerHandle walker, CommitSortStrategies options) + public static unsafe int git_revwalk_sorting(RevWalkerHandle walker, CommitSortStrategies options) { - NativeMethods.git_revwalk_sorting(walker, options); + return NativeMethods.git_revwalk_sorting(walker, options); } - public static unsafe void git_revwalk_simplify_first_parent(RevWalkerHandle walker) + public static unsafe int git_revwalk_simplify_first_parent(RevWalkerHandle walker) { - NativeMethods.git_revwalk_simplify_first_parent(walker); + return NativeMethods.git_revwalk_simplify_first_parent(walker); } #endregion diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index b00432a27..0c326b095 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,7 +32,7 @@ - + diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 3a4ebcdb6..52aceb321 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -104,8 +104,8 @@ public virtual Blob CreateBlob(string path) } ObjectId id = Path.IsPathRooted(path) - ? Proxy.git_blob_create_fromdisk(repo.Handle, path) - : Proxy.git_blob_create_fromfile(repo.Handle, path); + ? Proxy.git_blob_create_from_disk(repo.Handle, path) + : Proxy.git_blob_create_from_workdir(repo.Handle, path); return repo.Lookup(id); } @@ -277,7 +277,7 @@ private unsafe Blob CreateBlob(Stream stream, string hintpath, long? numberOfByt throw new ArgumentException("The stream cannot be read from.", "stream"); } - IntPtr writestream_ptr = Proxy.git_blob_create_fromstream(repo.Handle, hintpath); + IntPtr writestream_ptr = Proxy.git_blob_create_from_stream(repo.Handle, hintpath); GitWriteStream writestream = Marshal.PtrToStructure(writestream_ptr); try From 9941d39b5383691d4eb66534c37eb487bcc211ab Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 22 Aug 2021 10:24:34 +0200 Subject: [PATCH 111/179] Revert commented test --- LibGit2Sharp.Tests/RepositoryFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs index 7165e6cb7..5c551fabd 100644 --- a/LibGit2Sharp.Tests/RepositoryFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryFixture.cs @@ -709,7 +709,7 @@ public void CanListRemoteReferencesWithCredentials() [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - //[InlineData("git://github.com/libgit2/TestGitRepository.git")] + [InlineData("git://github.com/libgit2/TestGitRepository.git")] public void CanListRemoteReferences(string url) { IEnumerable references = Repository.ListRemoteReferences(url).ToList(); From 21d4f13ac7c739a5526cf088fbd8765d4ad12f57 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 5 Sep 2021 08:14:25 +0200 Subject: [PATCH 112/179] Update to libgit2 v1.2.0 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 0c326b095..d35369d94 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,7 +32,7 @@ - + From 297167eb2755c883bb14cf21ccffeffb5a8aa60e Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 5 Sep 2021 09:01:29 +0200 Subject: [PATCH 113/179] Fix rebase options --- LibGit2Sharp/Core/GitRebaseOptions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LibGit2Sharp/Core/GitRebaseOptions.cs b/LibGit2Sharp/Core/GitRebaseOptions.cs index e1416e803..981bfe919 100644 --- a/LibGit2Sharp/Core/GitRebaseOptions.cs +++ b/LibGit2Sharp/Core/GitRebaseOptions.cs @@ -18,6 +18,8 @@ internal class GitRebaseOptions public GitCheckoutOpts checkout_options = new GitCheckoutOpts { version = 1 }; + private IntPtr padding; // TODO: add git_commit_create_cb + public NativeMethods.commit_signing_callback signing_callback; } } From eb3dd1c72a0202bb0ddc669364b3c4e57e07412d Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 5 Sep 2021 09:37:19 +0200 Subject: [PATCH 114/179] Fix git remote callbacks --- LibGit2Sharp/Core/GitRemoteCallbacks.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LibGit2Sharp/Core/GitRemoteCallbacks.cs b/LibGit2Sharp/Core/GitRemoteCallbacks.cs index 54cdb46ed..4900ad562 100644 --- a/LibGit2Sharp/Core/GitRemoteCallbacks.cs +++ b/LibGit2Sharp/Core/GitRemoteCallbacks.cs @@ -33,6 +33,8 @@ internal struct GitRemoteCallbacks internal IntPtr transport; + private IntPtr padding; // TODO: add git_remote_ready_cb + internal IntPtr payload; internal NativeMethods.url_resolve_callback resolve_url; From 491d248472fd00f4fc5bef8da61cda14ba3b6735 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 5 Sep 2021 10:11:14 +0200 Subject: [PATCH 115/179] Fix memory corruption with odb backend --- LibGit2Sharp/Core/GitOdbBackend.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/LibGit2Sharp/Core/GitOdbBackend.cs b/LibGit2Sharp/Core/GitOdbBackend.cs index 0d68a3433..3ff031048 100644 --- a/LibGit2Sharp/Core/GitOdbBackend.cs +++ b/LibGit2Sharp/Core/GitOdbBackend.cs @@ -33,6 +33,9 @@ static GitOdbBackend() public exists_prefix_callback ExistsPrefix; public IntPtr Refresh; public foreach_callback Foreach; + + private IntPtr Padding; // TODO: add writemidx + public IntPtr Writepack; public IntPtr Freshen; public free_callback Free; From 29efc69f0ac78e2b44e64e7de3de6a845e7ec4a7 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 19 Sep 2021 14:22:48 -0400 Subject: [PATCH 116/179] Use native HTTPS support --- LibGit2Sharp.Tests/CloneFixture.cs | 157 +++++----- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 1 + .../Core/ManagedHttpSmartSubtransport.cs | 270 ------------------ LibGit2Sharp/Core/NativeMethods.cs | 24 +- LibGit2Sharp/GlobalSettings.cs | 143 +--------- 5 files changed, 90 insertions(+), 505 deletions(-) delete mode 100644 LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 2408dad05..0fefabbf6 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -5,7 +5,6 @@ using LibGit2Sharp.Handlers; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -110,9 +109,9 @@ public void CanCloneBarely(string url) var scd = BuildSelfCleaningDirectory(); string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions - { - IsBare = true - }); + { + IsBare = true + }); using (var repo = new Repository(clonedRepoPath)) { @@ -195,7 +194,7 @@ public void CanCloneWithCredentials() } } - static Credentials CreateUsernamePasswordCredentials (string user, string pass, bool secure) + static Credentials CreateUsernamePasswordCredentials(string user, string pass, bool secure) { if (secure) { @@ -222,7 +221,7 @@ public void CanCloneFromBBWithCredentials(string url, string user, string pass, string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions() { - CredentialsProvider = (_url, _user, _cred) => CreateUsernamePasswordCredentials (user, pass, secure) + CredentialsProvider = (_url, _user, _cred) => CreateUsernamePasswordCredentials(user, pass, secure) }); using (var repo = new Repository(clonedRepoPath)) @@ -237,65 +236,69 @@ public void CanCloneFromBBWithCredentials(string url, string user, string pass, } } - //[SkippableTheory] - //[InlineData("https://github.com/libgit2/TestGitRepository.git", "github.com", typeof(CertificateX509))] - //[InlineData("git@github.com:libgit2/TestGitRepository.git", "github.com", typeof(CertificateSsh))] - //public void CanInspectCertificateOnClone(string url, string hostname, Type certType) - //{ - // var scd = BuildSelfCleaningDirectory(); - - // InconclusiveIf( - // () => - // certType == typeof (CertificateSsh) && !GlobalSettings.Version.Features.HasFlag(BuiltInFeatures.Ssh), - // "SSH not supported"); - - // bool wasCalled = false; - // bool checksHappy = false; - - // var options = new CloneOptions { - // CertificateCheck = (cert, valid, host) => { - // wasCalled = true; - - // Assert.Equal(hostname, host); - // Assert.Equal(certType, cert.GetType()); - - // if (certType == typeof(CertificateX509)) { - // Assert.True(valid); - // var x509 = ((CertificateX509)cert).Certificate; - // // we get a string with the different fields instead of a structure, so... - // Assert.Contains("CN=github.com,", x509.Subject); - // checksHappy = true; - // return false; - // } - - // if (certType == typeof(CertificateSsh)) { - // var hostkey = (CertificateSsh)cert; - // Assert.True(hostkey.HasMD5); - // /* - // * Once you've connected and thus your ssh has stored the hostkey, - // * you can get the hostkey for a host with - // * - // * ssh-keygen -F github.com -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':' - // * - // * though GitHub's hostkey won't change anytime soon. - // */ - // Assert.Equal("1627aca576282d36631b564debdfa648", - // BitConverter.ToString(hostkey.HashMD5).ToLower().Replace("-", "")); - // checksHappy = true; - // return false; - // } - - // return false; - // }, - // }; - - // Assert.Throws(() => - // Repository.Clone(url, scd.DirectoryPath, options) - // ); - - // Assert.True(wasCalled); - // Assert.True(checksHappy); - //} + [SkippableTheory] + [InlineData("https://github.com/libgit2/TestGitRepository.git", "github.com", typeof(CertificateX509))] + [InlineData("git@github.com:libgit2/TestGitRepository.git", "github.com", typeof(CertificateSsh))] + public void CanInspectCertificateOnClone(string url, string hostname, Type certType) + { + var scd = BuildSelfCleaningDirectory(); + + InconclusiveIf( + () => + certType == typeof(CertificateSsh) && !GlobalSettings.Version.Features.HasFlag(BuiltInFeatures.Ssh), + "SSH not supported"); + + bool wasCalled = false; + bool checksHappy = false; + + var options = new CloneOptions + { + CertificateCheck = (cert, valid, host) => + { + wasCalled = true; + + Assert.Equal(hostname, host); + Assert.Equal(certType, cert.GetType()); + + if (certType == typeof(CertificateX509)) + { + Assert.True(valid); + var x509 = ((CertificateX509)cert).Certificate; + // we get a string with the different fields instead of a structure, so... + Assert.Contains("CN=github.com,", x509.Subject); + checksHappy = true; + return false; + } + + if (certType == typeof(CertificateSsh)) + { + var hostkey = (CertificateSsh)cert; + Assert.True(hostkey.HasMD5); + /* + * Once you've connected and thus your ssh has stored the hostkey, + * you can get the hostkey for a host with + * + * ssh-keygen -F github.com -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':' + * + * though GitHub's hostkey won't change anytime soon. + */ + Assert.Equal("1627aca576282d36631b564debdfa648", + BitConverter.ToString(hostkey.HashMD5).ToLower().Replace("-", "")); + checksHappy = true; + return false; + } + + return false; + }, + }; + + Assert.Throws(() => + Repository.Clone(url, scd.DirectoryPath, options) + ); + + Assert.True(wasCalled); + Assert.True(checksHappy); + } [Theory] [InlineData("git://github.com/libgit2/TestGitRepository")] @@ -441,7 +444,7 @@ public void CanRecursivelyCloneSubmodules() string clonedRepoPath = Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options); string workDirPath; - using(Repository repo = new Repository(clonedRepoPath)) + using (Repository repo = new Repository(clonedRepoPath)) { workDirPath = repo.Info.WorkingDirectory.TrimEnd(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }); } @@ -452,14 +455,14 @@ public void CanRecursivelyCloneSubmodules() Dictionary expectedCallbackInfo = new Dictionary(); expectedCallbackInfo.Add(workDirPath, new CloneCallbackInfo() - { - RecursionDepth = 0, - RemoteUrl = uri.AbsolutePath, - StartingWorkInRepositoryCalled = true, - FinishedWorkInRepositoryCalled = true, - CheckoutProgressCalled = true, - RemoteRefUpdateCalled = true, - }); + { + RecursionDepth = 0, + RemoteUrl = uri.AbsolutePath, + StartingWorkInRepositoryCalled = true, + FinishedWorkInRepositoryCalled = true, + CheckoutProgressCalled = true, + RemoteRefUpdateCalled = true, + }); expectedCallbackInfo.Add(Path.Combine(workDirPath, relativeSubmodulePath), new CloneCallbackInfo() { @@ -486,7 +489,7 @@ public void CanRecursivelyCloneSubmodules() } // Verify the state of the submodule - using(Repository repo = new Repository(clonedRepoPath)) + using (Repository repo = new Repository(clonedRepoPath)) { var sm = repo.Submodules[relativeSubmodulePath]; Assert.True(sm.RetrieveStatus().HasFlag(SubmoduleStatus.InWorkDir | @@ -533,7 +536,7 @@ public void CanCancelRecursiveClone() { Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options); } - catch(RecurseSubmodulesException ex) + catch (RecurseSubmodulesException ex) { Assert.NotNull(ex.InnerException); Assert.Equal(typeof(UserCancelledException), ex.InnerException.GetType()); @@ -541,7 +544,7 @@ public void CanCancelRecursiveClone() } // Verify that the submodule was not initialized. - using(Repository repo = new Repository(clonedRepoPath)) + using (Repository repo = new Repository(clonedRepoPath)) { var submoduleStatus = repo.Submodules[relativeSubmodulePath].RetrieveStatus(); Assert.Equal(SubmoduleStatus.InConfig | SubmoduleStatus.InHead | SubmoduleStatus.InIndex | SubmoduleStatus.WorkDirUninitialized, diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 6026f267a..55260a6f5 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -15,6 +15,7 @@ public void CanGetMinimumCompiledInFeatures() BuiltInFeatures features = GlobalSettings.Version.Features; Assert.True(features.HasFlag(BuiltInFeatures.Threads)); + Assert.True(features.HasFlag(BuiltInFeatures.Https)); } [Fact] diff --git a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs b/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs deleted file mode 100644 index 88eced880..000000000 --- a/LibGit2Sharp/Core/ManagedHttpSmartSubtransport.cs +++ /dev/null @@ -1,270 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Security.Authentication; - -namespace LibGit2Sharp.Core -{ - internal class ManagedHttpSmartSubtransport : RpcSmartSubtransport - { - protected override SmartSubtransportStream Action(string url, GitSmartSubtransportAction action) - { - string endpointUrl, contentType = null; - bool isPost = false; - - switch (action) - { - case GitSmartSubtransportAction.UploadPackList: - endpointUrl = string.Concat(url, "/info/refs?service=git-upload-pack"); - break; - - case GitSmartSubtransportAction.UploadPack: - endpointUrl = string.Concat(url, "/git-upload-pack"); - contentType = "application/x-git-upload-pack-request"; - isPost = true; - break; - - case GitSmartSubtransportAction.ReceivePackList: - endpointUrl = string.Concat(url, "/info/refs?service=git-receive-pack"); - break; - - case GitSmartSubtransportAction.ReceivePack: - endpointUrl = string.Concat(url, "/git-receive-pack"); - contentType = "application/x-git-receive-pack-request"; - isPost = true; - break; - - default: - throw new InvalidOperationException(); - } - - return new ManagedHttpSmartSubtransportStream(this, endpointUrl, isPost, contentType); - } - - private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream - { - private static int MAX_REDIRECTS = 7; - -#if NETCOREAPP - private static readonly SocketsHttpHandler httpHandler; -#else - private static readonly HttpClientHandler httpHandler; -#endif - - private static readonly CredentialCache credentialCache; - - private MemoryStream postBuffer = new MemoryStream(); - private HttpResponseMessage response; - private Stream responseStream; - - static ManagedHttpSmartSubtransportStream() - { -#if NETCOREAPP - httpHandler = new SocketsHttpHandler(); - httpHandler.PooledConnectionLifetime = TimeSpan.FromMinutes(5); -#else - httpHandler = new HttpClientHandler(); - httpHandler.SslProtocols |= SslProtocols.Tls12; -#endif - - httpHandler.AllowAutoRedirect = false; - - credentialCache = new CredentialCache(); - httpHandler.Credentials = credentialCache; - } - - public ManagedHttpSmartSubtransportStream(ManagedHttpSmartSubtransport parent, string endpointUrl, bool isPost, string contentType) - : base(parent) - { - EndpointUrl = new Uri(endpointUrl); - IsPost = isPost; - ContentType = contentType; - } - - private HttpClient CreateHttpClient(HttpMessageHandler handler) - { - return new HttpClient(handler, false) - { - DefaultRequestHeaders = - { - // This worked fine when it was on, but git.exe doesn't specify this header, so we don't either. - ExpectContinue = false, - }, - }; - } - - private Uri EndpointUrl { get; set; } - - private bool IsPost { get; set; } - - private string ContentType { get; set; } - - public override int Write(Stream dataStream, long length) - { - byte[] buffer = new byte[4096]; - long writeTotal = 0; - - while (length > 0) - { - int readLen = dataStream.Read(buffer, 0, (int)Math.Min(buffer.Length, length)); - - if (readLen == 0) - { - break; - } - - postBuffer.Write(buffer, 0, readLen); - length -= readLen; - writeTotal += readLen; - } - - if (writeTotal < length) - { - throw new EndOfStreamException("Could not write buffer (short read)"); - } - - return 0; - } - - private string GetUserAgent() - { - string userAgent = GlobalSettings.GetUserAgent(); - - if (string.IsNullOrEmpty(userAgent)) - { - userAgent = "LibGit2Sharp " + GlobalSettings.Version.InformationalVersion; - } - - return userAgent; - } - - private HttpRequestMessage CreateRequest(Uri endpointUrl, bool isPost) - { - var verb = isPost ? new HttpMethod("POST") : new HttpMethod("GET"); - var request = new HttpRequestMessage(verb, endpointUrl); - request.Headers.Add("User-Agent", $"git/2.0 ({GetUserAgent()})"); - request.Headers.Remove("Expect"); - - return request; - } - - private HttpResponseMessage GetResponseWithRedirects() - { - var url = EndpointUrl; - int retries; - - for (retries = 0; ; retries++) - { - using (var httpClient = CreateHttpClient(httpHandler)) - { - var request = CreateRequest(url, IsPost); - - if (retries > MAX_REDIRECTS) - { - throw new Exception("too many redirects or authentication replays"); - } - - if (IsPost && postBuffer.Length > 0) - { - var bufferDup = new MemoryStream(postBuffer.GetBuffer(), 0, (int)postBuffer.Length); - - request.Content = new StreamContent(bufferDup); - request.Content.Headers.Add("Content-Type", ContentType); - } - - var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult(); - - if (response.StatusCode == HttpStatusCode.OK) - { - return response; - } - else if (response.StatusCode == HttpStatusCode.Unauthorized) - { - int ret = SmartTransport.AcquireCredentials(out Credentials cred, null, typeof(UsernamePasswordCredentials)); - - if (ret != 0) - { - throw new InvalidOperationException("authentication cancelled"); - } - - var scheme = response.Headers.WwwAuthenticate.First().Scheme; - - if (cred is DefaultCredentials) - { - lock (credentialCache) - { - credentialCache.Add(url, scheme, CredentialCache.DefaultNetworkCredentials); - } - } - else if (cred is UsernamePasswordCredentials userpass) - { - lock (credentialCache) - { - credentialCache.Add(url, scheme, new NetworkCredential(userpass.Username, userpass.Password)); - } - } - - continue; - } - else if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) - { - url = new Uri(response.Headers.GetValues("Location").First()); - continue; - } - - throw new Exception(string.Format("unexpected HTTP response: {0}", response.StatusCode)); - } - } - - throw new Exception("too many redirects or authentication replays"); - } - - public override int Read(Stream dataStream, long length, out long readTotal) - { - byte[] buffer = new byte[4096]; - readTotal = 0; - - if (responseStream == null) - { - response = GetResponseWithRedirects(); - responseStream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult(); - } - - while (length > 0) - { - int readLen = responseStream.Read(buffer, 0, (int)Math.Min(buffer.Length, length)); - - if (readLen == 0) - { - break; - } - - dataStream.Write(buffer, 0, readLen); - readTotal += readLen; - length -= readLen; - } - - return 0; - } - - protected override void Free() - { - if (responseStream != null) - { - responseStream.Dispose(); - responseStream = null; - } - - if (response != null) - { - response.Dispose(); - response = null; - } - - base.Free(); - } - } - } -} diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index f7c9dbf26..04be0e683 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -26,9 +26,6 @@ internal static class NativeMethods private static NativeShutdownObject shutdownObject; #pragma warning restore 0414 - private static SmartSubtransportRegistration httpSubtransportRegistration; - private static SmartSubtransportRegistration httpsSubtransportRegistration; - static NativeMethods() { if (Platform.IsRunningOnNetFramework() || Platform.IsRunningOnNetCore()) @@ -106,7 +103,7 @@ private static bool TryUseNativeLibrary() new Type[] { typeof(string), typeof(Assembly), typeof(DllImportSearchPath?), typeof(IntPtr).MakeByRefType() })?.CreateDelegate(typeof(TryLoadLibraryByNameDelegate)); var tryLoadLibraryByPath = (TryLoadLibraryByPathDelegate)nativeLibraryType?.GetMethod("TryLoad", new Type[] { typeof(string), typeof(IntPtr).MakeByRefType() })?.CreateDelegate(typeof(TryLoadLibraryByPathDelegate)); - MethodInfo setDllImportResolver = nativeLibraryType?.GetMethod("SetDllImportResolver", new Type[] { typeof(Assembly), dllImportResolverType}); + MethodInfo setDllImportResolver = nativeLibraryType?.GetMethod("SetDllImportResolver", new Type[] { typeof(Assembly), dllImportResolverType }); if (dllImportResolverType == null || nativeLibraryType == null || @@ -196,11 +193,10 @@ private static void InitializeNativeLibrary() shutdownObject = new NativeShutdownObject(); } - // Configure the .NET HTTP(S) mechanism on the first initialization of the library in the current process. + // Configure the OpenSSL locking on the first initialization of the library in the current process. if (initCounter == 1) { - httpSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("http"); - httpsSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport("https"); + git_openssl_set_locking(); } } @@ -209,16 +205,6 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject { ~NativeShutdownObject() { - if (httpSubtransportRegistration != null) - { - GlobalSettings.UnregisterDefaultSmartSubtransport(httpSubtransportRegistration); - } - - if (httpsSubtransportRegistration != null) - { - GlobalSettings.UnregisterDefaultSmartSubtransport(httpsSubtransportRegistration); - } - git_libgit2_shutdown(); } } @@ -452,7 +438,7 @@ internal static extern unsafe int git_commit_create_from_ids( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, ref GitOid tree, UIntPtr parentCount, - [MarshalAs(UnmanagedType.LPArray)] [In] IntPtr[] parents); + [MarshalAs(UnmanagedType.LPArray)][In] IntPtr[] parents); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_commit_create_buffer( @@ -2111,7 +2097,7 @@ internal static extern unsafe int git_worktree_unlock( git_worktree* worktree); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe int git_worktree_add ( + internal static extern unsafe int git_worktree_add( out git_worktree* reference, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 1e5d17a19..00b031ca0 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -22,14 +22,6 @@ public static class GlobalSettings private static bool nativeLibraryPathLocked; private static string nativeLibraryDefaultPath; - internal class SmartSubtransportData - { - internal bool isCustom; - internal SmartSubtransportRegistrationData defaultSubtransport; - } - - private static readonly Dictionary smartSubtransportData = new Dictionary(); - static GlobalSettings() { bool netFX = Platform.IsRunningOnNetFramework(); @@ -81,48 +73,6 @@ private static string GetExecutingAssemblyDirectory() /// public static Version Version => version.Value; - private static SmartSubtransportData GetOrCreateSmartSubtransportData(string scheme) - { - Ensure.ArgumentNotNull(scheme, "scheme"); - - lock (smartSubtransportData) - { - if (!smartSubtransportData.ContainsKey(scheme)) - { - smartSubtransportData[scheme] = new SmartSubtransportData(); - } - - return smartSubtransportData[scheme]; - } - } - - internal static SmartSubtransportRegistration RegisterDefaultSmartSubtransport(string scheme) - where T : SmartSubtransport, new() - { - Ensure.ArgumentNotNull(scheme, "scheme"); - - lock (smartSubtransportData) - { - var data = GetOrCreateSmartSubtransportData(scheme); - - if (data.defaultSubtransport != null) - { - throw new Exception(string.Format("A default subtransport is already configured for {0}", scheme)); - } - - var registration = new SmartSubtransportRegistration(scheme); - - if (!data.isCustom) - { - RegisterSmartSubtransportInternal(registration); - } - - data.defaultSubtransport = registration; - - return registration; - } - } - /// /// Registers a new as a custom /// smart-protocol transport with libgit2. Any Git remote with @@ -141,53 +91,21 @@ public static SmartSubtransportRegistration RegisterSmartSubtransport(stri { Ensure.ArgumentNotNull(scheme, "scheme"); - lock (smartSubtransportData) - { - var data = GetOrCreateSmartSubtransportData(scheme); - - if (data.isCustom) - { - throw new EntryExistsException(string.Format("A smart subtransport is already registered for {0}", scheme)); - } - - if (data.defaultSubtransport != null) - { - Proxy.git_transport_unregister(scheme); - } - - var previousValue = data.isCustom; - data.isCustom = true; - - var registration = new SmartSubtransportRegistration(scheme); - - try - { - RegisterSmartSubtransportInternal(registration); - } - catch - { - data.isCustom = previousValue; - throw; - } - - return registration; - } - } + var registration = new SmartSubtransportRegistration(scheme); - private static void RegisterSmartSubtransportInternal(SmartSubtransportRegistration registration) - where T : SmartSubtransport, new() - { try { Proxy.git_transport_register(registration.Scheme, registration.FunctionPointer, registration.RegistrationPointer); } - catch + catch (Exception) { registration.Free(); throw; } + + return registration; } /// @@ -201,59 +119,6 @@ public static void UnregisterSmartSubtransport(SmartSubtransportRegistration< { Ensure.ArgumentNotNull(registration, "registration"); - var scheme = registration.Scheme; - - lock (smartSubtransportData) - { - var data = GetOrCreateSmartSubtransportData(scheme); - - if (!data.isCustom) - { - throw new NotFoundException(string.Format("No smart subtransport has been registered for {0}", scheme)); - } - - UnregisterSmartSubtransportInternal(registration); - - data.isCustom = false; - - if (data.defaultSubtransport != null) - { - var defaultRegistration = data.defaultSubtransport; - - Proxy.git_transport_register(defaultRegistration.Scheme, - defaultRegistration.FunctionPointer, - defaultRegistration.RegistrationPointer); - } - } - } - - internal static void UnregisterDefaultSmartSubtransport(SmartSubtransportRegistration registration) - where T : SmartSubtransport, new() - { - Ensure.ArgumentNotNull(registration, "registration"); - - var scheme = registration.Scheme; - - lock (smartSubtransportData) - { - if (!smartSubtransportData.ContainsKey(scheme)) - { - throw new Exception(string.Format("No default smart subtransport has been registered for {0}", scheme)); - } - - if (registration != smartSubtransportData[scheme].defaultSubtransport) - { - throw new Exception(string.Format("The given smart subtransport is not the default for {0}", scheme)); - } - - smartSubtransportData.Remove(scheme); - UnregisterSmartSubtransportInternal(registration); - } - } - - private static void UnregisterSmartSubtransportInternal(SmartSubtransportRegistration registration) - where T : SmartSubtransport, new() - { Proxy.git_transport_unregister(registration.Scheme); registration.Free(); } From b78ae80464d2ed1e0f5b4b8edf1c78686362a832 Mon Sep 17 00:00:00 2001 From: Eoin Motherway Date: Tue, 21 Sep 2021 08:50:00 +1000 Subject: [PATCH 117/179] Fix git_remote_connect not throwing on non-zero result --- LibGit2Sharp/Core/Proxy.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index ca9a69f6d..580c9872a 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -2172,6 +2172,7 @@ public static unsafe void git_remote_connect(RemoteHandle remote, GitDirection d catch (Exception) { customHeaders.Dispose(); + throw; } } From 2535e4744d257666d176dded9607dba92e294229 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 14:43:44 -0400 Subject: [PATCH 118/179] Remove old CI files --- .travis.yml | 7 -- appveyor.yml | 4 - azure-pipelines.yml | 12 --- azure-pipelines/Set-EnvVars.ps1 | 79 ------------------- azure-pipelines/artifacts/_all.ps1 | 50 ------------ azure-pipelines/artifacts/_pipelines.ps1 | 10 --- azure-pipelines/artifacts/_stage_all.ps1 | 59 -------------- azure-pipelines/artifacts/build_logs.ps1 | 12 --- azure-pipelines/artifacts/coverageResults.ps1 | 22 ------ azure-pipelines/artifacts/deployables.ps1 | 13 --- .../artifacts/projectAssetsJson.ps1 | 9 --- azure-pipelines/build.yml | 50 ------------ azure-pipelines/dotnet.yml | 49 ------------ azure-pipelines/install-dependencies.yml | 9 --- azure-pipelines/publish-codecoverage.yml | 31 -------- azure-pipelines/publish-deployables.yml | 14 ---- .../variables/DotNetSdkVersion.ps1 | 2 - 17 files changed, 432 deletions(-) delete mode 100644 .travis.yml delete mode 100644 appveyor.yml delete mode 100644 azure-pipelines.yml delete mode 100644 azure-pipelines/Set-EnvVars.ps1 delete mode 100644 azure-pipelines/artifacts/_all.ps1 delete mode 100644 azure-pipelines/artifacts/_pipelines.ps1 delete mode 100644 azure-pipelines/artifacts/_stage_all.ps1 delete mode 100644 azure-pipelines/artifacts/build_logs.ps1 delete mode 100644 azure-pipelines/artifacts/coverageResults.ps1 delete mode 100644 azure-pipelines/artifacts/deployables.ps1 delete mode 100644 azure-pipelines/artifacts/projectAssetsJson.ps1 delete mode 100644 azure-pipelines/build.yml delete mode 100644 azure-pipelines/dotnet.yml delete mode 100644 azure-pipelines/install-dependencies.yml delete mode 100644 azure-pipelines/publish-codecoverage.yml delete mode 100644 azure-pipelines/publish-deployables.yml delete mode 100644 azure-pipelines/variables/DotNetSdkVersion.ps1 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 18e8b5c24..000000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: csharp -mono: none - -# Disable Travis-CI -branches: - only: - - NOTTHISONE diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 6eeeedba4..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,4 +0,0 @@ -# Disable AppVeyor -branches: - only: - - NOTTHISONE diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index c25545a56..000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,12 +0,0 @@ -trigger: -- master -- maint/* - -variables: - TreatWarningsAsErrors: true - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - BuildConfiguration: Release - NUGET_PACKAGES: $(Agent.TempDirectory)/.nuget/packages - -jobs: -- template: azure-pipelines/build.yml diff --git a/azure-pipelines/Set-EnvVars.ps1 b/azure-pipelines/Set-EnvVars.ps1 deleted file mode 100644 index 907659a7b..000000000 --- a/azure-pipelines/Set-EnvVars.ps1 +++ /dev/null @@ -1,79 +0,0 @@ -<# -.SYNOPSIS - Set environment variables in the environment. - Azure Pipeline and CMD environments are considered. -.PARAMETER Variables - A hashtable of variables to be set. -.OUTPUTS - A boolean indicating whether the environment variables can be expected to propagate to the caller's environment. -#> -[CmdletBinding(SupportsShouldProcess=$true)] -Param( - [Parameter(Mandatory=$true, Position=1)] - $Variables, - [string[]]$PrependPath -) - -if ($Variables.Count -eq 0) { - return $true -} - -$cmdInstructions = !$env:TF_BUILD -and !$env:GITHUB_ACTIONS -and $env:PS1UnderCmd -eq '1' -if ($cmdInstructions) { - Write-Warning "Environment variables have been set that will be lost because you're running under cmd.exe" - Write-Host "Environment variables that must be set manually:" -ForegroundColor Blue -} else { - Write-Host "Environment variables set:" -ForegroundColor Blue - $envVars - if ($PrependPath) { - Write-Host "Paths prepended to PATH: $PrependPath" - } -} - -if ($env:TF_BUILD) { - Write-Host "Azure Pipelines detected. Logging commands will be used to propagate environment variables and prepend path." -} - -if ($env:GITHUB_ACTIONS) { - Write-Host "GitHub Actions detected. Logging commands will be used to propagate environment variables and prepend path." -} - -$Variables.GetEnumerator() |% { - Set-Item -Path env:$($_.Key) -Value $_.Value - - # If we're running in a cloud CI, set these environment variables so they propagate. - if ($env:TF_BUILD) { - Write-Host "##vso[task.setvariable variable=$($_.Key);]$($_.Value)" - } - if ($env:GITHUB_ACTIONS) { - Write-Host "::set-env name=$($_.Key)::$($_.Value)" - } - - if ($cmdInstructions) { - Write-Host "SET $($_.Key)=$($_.Value)" - } -} - -$pathDelimiter = ';' -if ($IsMacOS -or $IsLinux) { - $pathDelimiter = ':' -} - -if ($PrependPath) { - $PrependPath |% { - $newPathValue = "$_$pathDelimiter$env:PATH" - Set-Item -Path env:PATH -Value $newPathValue - if ($cmdInstructions) { - Write-Host "SET PATH=$newPathValue" - } - - if ($env:TF_BUILD) { - Write-Host "##vso[task.prependpath]$_" - } - if ($env:GITHUB_ACTIONS) { - Write-Host "::add-path::$_" - } - } -} - -return !$cmdInstructions diff --git a/azure-pipelines/artifacts/_all.ps1 b/azure-pipelines/artifacts/_all.ps1 deleted file mode 100644 index 6f62be5c3..000000000 --- a/azure-pipelines/artifacts/_all.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -# This script returns all the artifacts that should be collected after a build. -# -# Each powershell artifact is expressed as an object with these properties: -# Source - the full path to the source file -# ArtifactName - the name of the artifact to upload to -# ContainerFolder - the relative path within the artifact in which the file should appear -# -# Each artifact aggregating .ps1 script should return a hashtable: -# Key = path to the directory from which relative paths within the artifact should be calculated -# Value = an array of paths (absolute or relative to the BaseDirectory) to files to include in the artifact. -# FileInfo objects are also allowed. - -$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") - -Function EnsureTrailingSlash($path) { - if ($path.length -gt 0 -and !$path.EndsWith('\') -and !$path.EndsWith('/')) { - $path = $path + [IO.Path]::DirectorySeparatorChar - } - - $path.Replace('\', [IO.Path]::DirectorySeparatorChar) -} - -Get-ChildItem "$PSScriptRoot\*.ps1" -Exclude "_*" -Recurse |% { - $ArtifactName = $_.BaseName - - $fileGroups = & $_ - if (!$fileGroups -or $fileGroups.Count -eq 0) { - Write-Warning "No files found for the `"$ArtifactName`" artifact." - } else { - $fileGroups.GetEnumerator() | % { - $BaseDirectory = New-Object Uri ((EnsureTrailingSlash $_.Key), [UriKind]::Absolute) - $_.Value | % { - if ($_.GetType() -eq [IO.FileInfo] -or $_.GetType() -eq [IO.DirectoryInfo]) { - $_ = $_.FullName - } - - $artifact = New-Object -TypeName PSObject - Add-Member -InputObject $artifact -MemberType NoteProperty -Name ArtifactName -Value $ArtifactName - - $SourceFullPath = New-Object Uri ($BaseDirectory, $_) - Add-Member -InputObject $artifact -MemberType NoteProperty -Name Source -Value $SourceFullPath.LocalPath - - $RelativePath = [Uri]::UnescapeDataString($BaseDirectory.MakeRelative($SourceFullPath)) - Add-Member -InputObject $artifact -MemberType NoteProperty -Name ContainerFolder -Value (Split-Path $RelativePath) - - Write-Output $artifact - } - } - } -} diff --git a/azure-pipelines/artifacts/_pipelines.ps1 b/azure-pipelines/artifacts/_pipelines.ps1 deleted file mode 100644 index 5bca7c6c1..000000000 --- a/azure-pipelines/artifacts/_pipelines.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -# This script translates all the artifacts described by _all.ps1 -# into commands that instruct Azure Pipelines to actually collect those artifacts. - -param ( - [string]$ArtifactNameSuffix -) - -& "$PSScriptRoot/_stage_all.ps1" -ArtifactNameSuffix $ArtifactNameSuffix |% { - Write-Host "##vso[artifact.upload containerfolder=$($_.Name);artifactname=$($_.Name);]$($_.Path)" -} diff --git a/azure-pipelines/artifacts/_stage_all.ps1 b/azure-pipelines/artifacts/_stage_all.ps1 deleted file mode 100644 index a05db5292..000000000 --- a/azure-pipelines/artifacts/_stage_all.ps1 +++ /dev/null @@ -1,59 +0,0 @@ -# This script links all the artifacts described by _all.ps1 -# into a staging directory, reading for uploading to a cloud build artifact store. -# It returns a sequence of objects with Name and Path properties. - -param ( - [string]$ArtifactNameSuffix -) - -$RepoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot (Join-Path .. ..))) -if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) { - $ArtifactStagingFolder = $env:BUILD_ARTIFACTSTAGINGDIRECTORY -} else { - $ArtifactStagingFolder = Join-Path $RepoRoot (Join-Path obj _artifacts) - if (Test-Path $ArtifactStagingFolder) { - Remove-Item $ArtifactStagingFolder -Recurse -Force - } -} - -function Create-SymbolicLink { - param ( - $Link, - $Target - ) - - if ($Link -eq $Target) { - return - } - - if (Test-Path $Link) { Remove-Item $Link } - $LinkContainer = Split-Path $Link -Parent - if (!(Test-Path $LinkContainer)) { mkdir $LinkContainer } - Write-Verbose "Linking $Link to $Target" - if ($IsMacOS -or $IsLinux) { - ln $Target $Link | Out-Null - } else { - cmd /c mklink $Link $Target | Out-Null - } -} - -# Stage all artifacts -$Artifacts = & "$PSScriptRoot\_all.ps1" -$Artifacts |% { - $DestinationFolder = (Join-Path (Join-Path $ArtifactStagingFolder "$($_.ArtifactName)$ArtifactNameSuffix") $_.ContainerFolder).TrimEnd('\') - $Name = "$(Split-Path $_.Source -Leaf)" - - #Write-Host "$($_.Source) -> $($_.ArtifactName)\$($_.ContainerFolder)" -ForegroundColor Yellow - - if (-not (Test-Path $DestinationFolder)) { New-Item -ItemType Directory -Path $DestinationFolder | Out-Null } - if (Test-Path -PathType Leaf $_.Source) { # skip folders - Create-SymbolicLink -Link (Join-Path $DestinationFolder $Name) -Target $_.Source - } -} - -$Artifacts |% { "$($_.ArtifactName)$ArtifactNameSuffix" } | Get-Unique |% { - $artifact = New-Object -TypeName PSObject - Add-Member -InputObject $artifact -MemberType NoteProperty -Name Name -Value $_ - Add-Member -InputObject $artifact -MemberType NoteProperty -Name Path -Value (Join-Path $ArtifactStagingFolder $_) - Write-Output $artifact -} diff --git a/azure-pipelines/artifacts/build_logs.ps1 b/azure-pipelines/artifacts/build_logs.ps1 deleted file mode 100644 index b55ba48f3..000000000 --- a/azure-pipelines/artifacts/build_logs.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) { - $artifactsRoot = $env:BUILD_ARTIFACTSTAGINGDIRECTORY -} else { - $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") - $artifactsRoot = "$RepoRoot\bin" -} - -if (!(Test-Path $artifactsRoot/build_logs)) { return } - -@{ - "$artifactsRoot/build_logs" = (Get-ChildItem -Recurse "$artifactsRoot/build_logs") -} diff --git a/azure-pipelines/artifacts/coverageResults.ps1 b/azure-pipelines/artifacts/coverageResults.ps1 deleted file mode 100644 index 7d1e9a35f..000000000 --- a/azure-pipelines/artifacts/coverageResults.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") - -# Prepare code coverage reports for merging on another machine -if ($env:SYSTEM_DEFAULTWORKINGDIRECTORY) { - Write-Host "Substituting $env:SYSTEM_DEFAULTWORKINGDIRECTORY with `"{reporoot}`"" - $reports = Get-ChildItem "$RepoRoot/bin/coverage.cobertura.xml" -Recurse - $reports |% { - $content = Get-Content -Path $_ |% { $_ -Replace [regex]::Escape($env:SYSTEM_DEFAULTWORKINGDIRECTORY), "{reporoot}" } - Set-Content -Path $_ -Value $content -Encoding UTF8 - } -} else { - Write-Warning "coverageResults: Azure Pipelines not detected. Machine-neutral token replacement skipped." -} - -if (!((Test-Path $RepoRoot\bin) -and (Test-Path $RepoRoot\obj))) { return } - -@{ - $RepoRoot = ( - @(Get-ChildItem "$RepoRoot\bin\coverage.cobertura.xml" -Recurse) + - (Get-ChildItem "$RepoRoot\obj\*.cs" -Recurse) - ); -} diff --git a/azure-pipelines/artifacts/deployables.ps1 b/azure-pipelines/artifacts/deployables.ps1 deleted file mode 100644 index 94c48cdd9..000000000 --- a/azure-pipelines/artifacts/deployables.ps1 +++ /dev/null @@ -1,13 +0,0 @@ -$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") -$BuildConfiguration = $env:BUILDCONFIGURATION -if (!$BuildConfiguration) { - $BuildConfiguration = 'Debug' -} - -$PackagesRoot = "$RepoRoot/bin/Packages/$BuildConfiguration" - -if (!(Test-Path $PackagesRoot)) { return } - -@{ - "$PackagesRoot" = (Get-ChildItem $PackagesRoot -Recurse) -} diff --git a/azure-pipelines/artifacts/projectAssetsJson.ps1 b/azure-pipelines/artifacts/projectAssetsJson.ps1 deleted file mode 100644 index d2e85ffbe..000000000 --- a/azure-pipelines/artifacts/projectAssetsJson.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -$ObjRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\obj") - -if (!(Test-Path $ObjRoot)) { return } - -@{ - "$ObjRoot" = ( - (Get-ChildItem "$ObjRoot\project.assets.json" -Recurse) - ); -} diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml deleted file mode 100644 index a73ccda4c..000000000 --- a/azure-pipelines/build.yml +++ /dev/null @@ -1,50 +0,0 @@ -parameters: - windowsPool: Hosted Windows 2019 with VS2019 - -jobs: -- job: Windows - pool: ${{ parameters.windowsPool }} - steps: - - template: install-dependencies.yml - - template: dotnet.yml - -- job: Linux - pool: - vmImage: Ubuntu 18.04 - steps: - - template: install-dependencies.yml - - template: dotnet.yml - -- job: macOS - pool: - vmImage: macOS-10.15 - steps: - - template: install-dependencies.yml - - template: dotnet.yml - -- job: WrapUp - dependsOn: - - Windows - - Linux - - macOS - pool: - vmImage: Ubuntu 18.04 - condition: succeededOrFailed() - steps: - - template: install-dependencies.yml - parameters: - initArgs: -NoRestore - - template: publish-codecoverage.yml - - template: publish-deployables.yml - -- job: leak_check - pool: - vmImage: Ubuntu 18.04 - steps: - - template: install-dependencies.yml - - task: DotNetCoreCLI@2 - displayName: dotnet test -f netcoreapp2.1 - inputs: - command: test - arguments: --no-restore -c $(BuildConfiguration) -f netcoreapp2.1 --filter "TestCategory!=FailsInCloudTest" -v m /p:ExtraDefine=LEAKS_IDENTIFYING - testRunTitle: netcoreapp2.1-$(Agent.JobName) diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml deleted file mode 100644 index 3bc1eaf50..000000000 --- a/azure-pipelines/dotnet.yml +++ /dev/null @@ -1,49 +0,0 @@ -steps: - -- script: dotnet build --no-restore -c $(BuildConfiguration) /v:m /bl:"$(Build.ArtifactStagingDirectory)/build_logs/build.binlog" - displayName: dotnet build - -- script: dotnet pack --no-build -c $(BuildConfiguration) /v:m /bl:"$(Build.ArtifactStagingDirectory)/build_logs/pack.binlog" - displayName: dotnet pack - -- task: DotNetCoreCLI@2 - displayName: dotnet test -f net472 (w/ coverage) - inputs: - command: test - arguments: --no-build -c $(BuildConfiguration) -f net472 --filter "TestCategory!=FailsInCloudTest & TestCategory!=FailsWhileInstrumented" -v n /p:CollectCoverage=true - testRunTitle: net472-$(Agent.JobName) - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - -- task: DotNetCoreCLI@2 - displayName: dotnet test -f net472 (w/o coverage) - inputs: - command: test - arguments: --no-build -c $(BuildConfiguration) -f net472 --filter "TestCategory!=FailsInCloudTest & TestCategory=FailsWhileInstrumented" -v n - testRunTitle: net472-$(Agent.JobName)-nocoverage - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - -- task: DotNetCoreCLI@2 - displayName: dotnet test -f netcoreapp2.1 - inputs: - command: test - arguments: --no-build -c $(BuildConfiguration) -f netcoreapp2.1 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true - testRunTitle: netcoreapp2.1-$(Agent.JobName) - -- task: DotNetCoreCLI@2 - displayName: dotnet test -f net5.0 - inputs: - command: test - arguments: --no-build -c $(BuildConfiguration) -f net5.0 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true - testRunTitle: net5.0-$(Agent.JobName) - -- task: PowerShell@2 - inputs: - filePath: azure-pipelines/artifacts/_pipelines.ps1 - arguments: -ArtifactNameSuffix "-$(Agent.JobName)" - displayName: Publish artifacts - condition: succeededOrFailed() - -- bash: bash <(curl -s https://codecov.io/bash) - displayName: Publish code coverage results to codecov.io - timeoutInMinutes: 3 - continueOnError: true diff --git a/azure-pipelines/install-dependencies.yml b/azure-pipelines/install-dependencies.yml deleted file mode 100644 index 5b008c6e8..000000000 --- a/azure-pipelines/install-dependencies.yml +++ /dev/null @@ -1,9 +0,0 @@ -parameters: - initArgs: - -steps: - -- powershell: | - .\init.ps1 -AccessToken '$(System.AccessToken)' ${{ parameters['initArgs'] }} -UpgradePrerequisites - dotnet --info - displayName: Install prerequisites diff --git a/azure-pipelines/publish-codecoverage.yml b/azure-pipelines/publish-codecoverage.yml deleted file mode 100644 index 59dba9d40..000000000 --- a/azure-pipelines/publish-codecoverage.yml +++ /dev/null @@ -1,31 +0,0 @@ -steps: -- download: current - artifact: coverageResults-Windows - displayName: Download Windows code coverage results - continueOnError: true -- download: current - artifact: coverageResults-Linux - displayName: Download Linux code coverage results - continueOnError: true -- download: current - artifact: coverageResults-macOS - displayName: Download macOS code coverage results - continueOnError: true -- powershell: | - dotnet tool install --tool-path obj dotnet-reportgenerator-globaltool --version 4.2.2 - Copy-Item -Recurse $(Pipeline.Workspace)/coverageResults-Windows/obj/* $(System.DefaultWorkingDirectory)/obj - Write-Host "Substituting {reporoot} with $(System.DefaultWorkingDirectory)" - $reports = Get-ChildItem -Recurse "$(Pipeline.Workspace)/coverage.cobertura.xml" - $reports |% { - $content = Get-Content -Path $_ |% { $_.Replace("{reporoot}", "$(System.DefaultWorkingDirectory)") } - Set-Content -Path $_ -Value $content -Encoding UTF8 - } - $Inputs = [string]::join(';', ($reports |% { Resolve-Path -relative $_ })) - obj/reportgenerator -reports:"$Inputs" -targetdir:coveragereport -reporttypes:Cobertura - displayName: Merge coverage -- task: PublishCodeCoverageResults@1 - displayName: Publish code coverage results to Azure DevOps - inputs: - codeCoverageTool: cobertura - summaryFileLocation: 'coveragereport/Cobertura.xml' - failIfCoverageEmpty: true diff --git a/azure-pipelines/publish-deployables.yml b/azure-pipelines/publish-deployables.yml deleted file mode 100644 index a89f389fd..000000000 --- a/azure-pipelines/publish-deployables.yml +++ /dev/null @@ -1,14 +0,0 @@ -steps: -- download: current - displayName: Download deployables - artifact: deployables-Windows - -- task: NuGetCommand@2 - displayName: Push packages to CI feed - inputs: - command: push - packagesToPush: $(Pipeline.Workspace)/deployables-Windows/*.nupkg - nuGetFeedType: internal - publishVstsFeed: $(ci_feed) - allowPackageConflicts: true - condition: and(succeeded(), ne(variables['ci_feed'], ''), ne(variables['Build.Reason'], 'PullRequest')) diff --git a/azure-pipelines/variables/DotNetSdkVersion.ps1 b/azure-pipelines/variables/DotNetSdkVersion.ps1 deleted file mode 100644 index b213fbc27..000000000 --- a/azure-pipelines/variables/DotNetSdkVersion.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -$globalJson = Get-Content -Path "$PSScriptRoot\..\..\global.json" | ConvertFrom-Json -$globalJson.sdk.version From e04f4a084cbc3bd2497a7cc8494ab6f5dfeaa0dd Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 14:45:38 -0400 Subject: [PATCH 119/179] Remove init scripts and locked SDK --- global.json | 5 -- init.cmd | 4 - init.ps1 | 66 --------------- tools/Install-DotNetSdk.ps1 | 160 ------------------------------------ 4 files changed, 235 deletions(-) delete mode 100644 global.json delete mode 100644 init.cmd delete mode 100644 init.ps1 delete mode 100644 tools/Install-DotNetSdk.ps1 diff --git a/global.json b/global.json deleted file mode 100644 index 459551b1c..000000000 --- a/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "version": "5.0.400" - } -} diff --git a/init.cmd b/init.cmd deleted file mode 100644 index 970285c2f..000000000 --- a/init.cmd +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -SETLOCAL -set PS1UnderCmd=1 -powershell.exe -NoProfile -NoLogo -ExecutionPolicy bypass -Command "try { & '%~dpn0.ps1' %*; exit $LASTEXITCODE } catch { write-host $_; exit 1 }" diff --git a/init.ps1 b/init.ps1 deleted file mode 100644 index 907d85a5c..000000000 --- a/init.ps1 +++ /dev/null @@ -1,66 +0,0 @@ -<# -.SYNOPSIS -Installs dependencies required to build and test the projects in this repository. -.DESCRIPTION -This MAY not require elevation, as the SDK and runtimes are installed to a per-user location, -unless the `-InstallLocality` switch is specified directing to a per-repo or per-machine location. -See detailed help on that switch for more information. -.PARAMETER InstallLocality -A value indicating whether dependencies should be installed locally to the repo or at a per-user location. -Per-user allows sharing the installed dependencies across repositories and allows use of a shared expanded package cache. -Visual Studio will only notice and use these SDKs/runtimes if VS is launched from the environment that runs this script. -Per-repo allows for high isolation, allowing for a more precise recreation of the environment within an Azure Pipelines build. -When using 'repo', environment variables are set to cause the locally installed dotnet SDK to be used. -Per-repo can lead to file locking issues when dotnet.exe is left running as a build server and can be mitigated by running `dotnet build-server shutdown`. -Per-machine requires elevation and will download and install all SDKs and runtimes to machine-wide locations so all applications can find it. -.PARAMETER NoPrerequisites -Skips the installation of prerequisite software (e.g. SDKs, tools). -.PARAMETER UpgradePrerequisites -Takes time to install prerequisites even if they are already present in case they need to be upgraded. -No effect if -NoPrerequisites is specified. -.PARAMETER NoRestore -Skips the package restore step. -.PARAMETER AccessToken -An optional access token for authenticating to Azure Artifacts authenticated feeds. -#> -[CmdletBinding(SupportsShouldProcess=$true)] -Param ( - [ValidateSet('repo','user','machine')] - [string]$InstallLocality='user', - [Parameter()] - [switch]$NoPrerequisites, - [Parameter()] - [switch]$UpgradePrerequisites, - [Parameter()] - [switch]$NoRestore, - [Parameter()] - [string]$AccessToken -) - -if (!$NoPrerequisites) { - & "$PSScriptRoot\tools\Install-DotNetSdk.ps1" -InstallLocality $InstallLocality -} - -# Workaround nuget credential provider bug that causes very unreliable package restores on Azure Pipelines -$env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 -$env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 - -Push-Location $PSScriptRoot -try { - $HeaderColor = 'Green' - - if (!$NoRestore -and $PSCmdlet.ShouldProcess("NuGet packages", "Restore")) { - Write-Host "Restoring NuGet packages" -ForegroundColor $HeaderColor - dotnet restore - if ($lastexitcode -ne 0) { - throw "Failure while restoring packages." - } - } -} -catch { - Write-Error $error[0] - exit $lastexitcode -} -finally { - Pop-Location -} diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1 deleted file mode 100644 index 10ed02b8b..000000000 --- a/tools/Install-DotNetSdk.ps1 +++ /dev/null @@ -1,160 +0,0 @@ -<# -.SYNOPSIS -Installs the .NET SDK specified in the global.json file at the root of this repository, -along with supporting .NET Core runtimes used for testing. -.DESCRIPTION -This MAY not require elevation, as the SDK and runtimes are installed locally to this repo location, -unless `-InstallLocality machine` is specified. -.PARAMETER InstallLocality -A value indicating whether dependencies should be installed locally to the repo or at a per-user location. -Per-user allows sharing the installed dependencies across repositories and allows use of a shared expanded package cache. -Visual Studio will only notice and use these SDKs/runtimes if VS is launched from the environment that runs this script. -Per-repo allows for high isolation, allowing for a more precise recreation of the environment within an Azure Pipelines build. -When using 'repo', environment variables are set to cause the locally installed dotnet SDK to be used. -Per-repo can lead to file locking issues when dotnet.exe is left running as a build server and can be mitigated by running `dotnet build-server shutdown`. -Per-machine requires elevation and will download and install all SDKs and runtimes to machine-wide locations so all applications can find it. -#> -[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')] -Param ( - [ValidateSet('repo','user','machine')] - [string]$InstallLocality='user' -) - -$DotNetInstallScriptRoot = "$PSScriptRoot/../obj/tools" -if (!(Test-Path $DotNetInstallScriptRoot)) { New-Item -ItemType Directory -Path $DotNetInstallScriptRoot | Out-Null } -$DotNetInstallScriptRoot = Resolve-Path $DotNetInstallScriptRoot - -# Look up actual required .NET Core SDK version from global.json -$sdkVersion = & "$PSScriptRoot/../azure-pipelines/variables/DotNetSdkVersion.ps1" - -# Search for all .NET Core runtime versions referenced from MSBuild projects and arrange to install them. -$runtimeVersions = @() -Get-ChildItem "$PSScriptRoot\..\*.*proj" -Recurse |% { - $projXml = [xml](Get-Content -Path $_) - $targetFrameworks = $projXml.Project.PropertyGroup.TargetFramework - if (!$targetFrameworks) { - $targetFrameworks = $projXml.Project.PropertyGroup.TargetFrameworks - if ($targetFrameworks) { - $targetFrameworks = $targetFrameworks -Split ';' - } - } - $targetFrameworks |? { $_ -match 'netcoreapp(\d+\.\d+)' } |% { - $runtimeVersions += $Matches[1] - } -} - -Function Get-FileFromWeb([Uri]$Uri, $OutDir) { - $OutFile = Join-Path $OutDir $Uri.Segments[-1] - if (!(Test-Path $OutFile)) { - Write-Verbose "Downloading $Uri..." - try { - (New-Object System.Net.WebClient).DownloadFile($Uri, $OutFile) - } finally { - # This try/finally causes the script to abort - } - } - - $OutFile -} - -Function Get-InstallerExe($Version, [switch]$Runtime) { - $sdkOrRuntime = 'Sdk' - if ($Runtime) { $sdkOrRuntime = 'Runtime' } - - # Get the latest/actual version for the specified one - if (([Version]$Version).Build -eq -1) { - $versionInfo = -Split (Invoke-WebRequest -Uri "https://dotnetcli.blob.core.windows.net/dotnet/$sdkOrRuntime/$Version/latest.version" -UseBasicParsing) - $Version = $versionInfo[-1] - } - - Get-FileFromWeb -Uri "https://dotnetcli.blob.core.windows.net/dotnet/$sdkOrRuntime/$Version/dotnet-$($sdkOrRuntime.ToLowerInvariant())-$Version-win-x64.exe" -OutDir "$DotNetInstallScriptRoot" -} - -Function Install-DotNet($Version, [switch]$Runtime) { - if ($Runtime) { $sdkSubstring = '' } else { $sdkSubstring = 'SDK ' } - Write-Host "Downloading .NET Core $sdkSubstring$Version..." - $Installer = Get-InstallerExe -Version $Version -Runtime:$Runtime - Write-Host "Installing .NET Core $sdkSubstring$Version..." - cmd /c start /wait $Installer /install /quiet - if ($LASTEXITCODE -ne 0) { - throw "Failure to install .NET Core SDK" - } -} - -if ($InstallLocality -eq 'machine') { - if ($IsMacOS -or $IsLinux) { - Write-Error "Installing the .NET Core SDK or runtime at a machine-wide location is only supported by this script on Windows." - exit 1 - } - - if ($PSCmdlet.ShouldProcess(".NET Core SDK $sdkVersion", "Install")) { - Install-DotNet -Version $sdkVersion - } - - $runtimeVersions |% { - if ($PSCmdlet.ShouldProcess(".NET Core runtime $_", "Install")) { - Install-DotNet -Version $_ -Runtime - } - } - - return -} - -$switches = @( - '-Architecture','x64' -) -$envVars = @{ - # For locally installed dotnet, skip first time experience which takes a long time - 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' = 'true'; -} - -if ($InstallLocality -eq 'repo') { - $DotNetInstallDir = "$DotNetInstallScriptRoot/.dotnet" -} elseif ($env:AGENT_TOOLSDIRECTORY) { - $DotNetInstallDir = "$env:AGENT_TOOLSDIRECTORY/dotnet" -} else { - $DotNetInstallDir = Join-Path $HOME .dotnet -} - -Write-Host "Installing .NET Core SDK and runtimes to $DotNetInstallDir" -ForegroundColor Blue - -if ($DotNetInstallDir) { - $switches += '-InstallDir',$DotNetInstallDir - $envVars['DOTNET_MULTILEVEL_LOOKUP'] = '0' - $envVars['DOTNET_ROOT'] = $DotNetInstallDir -} - -if ($IsMacOS -or $IsLinux) { - $DownloadUri = "https://dot.net/v1/dotnet-install.sh" - $DotNetInstallScriptPath = "$DotNetInstallScriptRoot/dotnet-install.sh" -} else { - $DownloadUri = "https://dot.net/v1/dotnet-install.ps1" - $DotNetInstallScriptPath = "$DotNetInstallScriptRoot/dotnet-install.ps1" -} - -if (-not (Test-Path $DotNetInstallScriptPath)) { - Invoke-WebRequest -Uri $DownloadUri -OutFile $DotNetInstallScriptPath -UseBasicParsing - if ($IsMacOS -or $IsLinux) { - chmod +x $DotNetInstallScriptPath - } -} - -if ($PSCmdlet.ShouldProcess(".NET Core SDK $sdkVersion", "Install")) { - Invoke-Expression -Command "$DotNetInstallScriptPath -Version $sdkVersion $switches" -} else { - Invoke-Expression -Command "$DotNetInstallScriptPath -Version $sdkVersion $switches -DryRun" -} - -$switches += '-Runtime','dotnet' - -$runtimeVersions | Get-Unique |% { - if ($PSCmdlet.ShouldProcess(".NET Core runtime $_", "Install")) { - Invoke-Expression -Command "$DotNetInstallScriptPath -Channel $_ $switches" - } else { - Invoke-Expression -Command "$DotNetInstallScriptPath -Channel $_ $switches -DryRun" - } -} - -if ($PSCmdlet.ShouldProcess("Set DOTNET environment variables to discover these installed runtimes?")) { - & "$PSScriptRoot/../azure-pipelines/Set-EnvVars.ps1" -Variables $envVars -PrependPath $DotNetInstallDir | Out-Null -} From c91027e7fdae704e10bcd6327a64c516b6d0b93e Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 14:51:15 -0400 Subject: [PATCH 120/179] Remove R# and NCrunch files --- .../LibGit2Sharp.Tests.v2.ncrunchproject | 31 ------------------- LibGit2Sharp.sln.DotSettings | 17 ---------- LibGit2Sharp.v2.ncrunchsolution | 13 -------- LibGit2Sharp/LibGit2Sharp.v2.ncrunchproject | 25 --------------- 4 files changed, 86 deletions(-) delete mode 100644 LibGit2Sharp.Tests/LibGit2Sharp.Tests.v2.ncrunchproject delete mode 100644 LibGit2Sharp.sln.DotSettings delete mode 100644 LibGit2Sharp.v2.ncrunchsolution delete mode 100644 LibGit2Sharp/LibGit2Sharp.v2.ncrunchproject diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.v2.ncrunchproject b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.v2.ncrunchproject deleted file mode 100644 index e24470157..000000000 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.v2.ncrunchproject +++ /dev/null @@ -1,31 +0,0 @@ - - 1000 - false - true - false - true - false - false - false - false - false - true - true - false - true - true - true - 60000 - - - - AutoDetect - STA - x86 - - - LibGit2Sharp.Tests.ShadowCopyFixture.CanProbeForNativeBinariesFromAShadowCopiedAssembly - - - Resources\**;Resources\**.* - \ No newline at end of file diff --git a/LibGit2Sharp.sln.DotSettings b/LibGit2Sharp.sln.DotSettings deleted file mode 100644 index 8bc2282a8..000000000 --- a/LibGit2Sharp.sln.DotSettings +++ /dev/null @@ -1,17 +0,0 @@ - - <?xml version="1.0" encoding="utf-16"?><Profile name="LibGit2Sharp"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode></Profile> - TOGETHER - ALWAYS_ADD - ALWAYS_ADD - ALWAYS_ADD - ALWAYS_ADD - ALWAYS_ADD - True - False - True - True - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - True - True - True - diff --git a/LibGit2Sharp.v2.ncrunchsolution b/LibGit2Sharp.v2.ncrunchsolution deleted file mode 100644 index 9420cc077..000000000 --- a/LibGit2Sharp.v2.ncrunchsolution +++ /dev/null @@ -1,13 +0,0 @@ - - 1 - false - true - true - UseDynamicAnalysis - UseStaticAnalysis - UseStaticAnalysis - UseStaticAnalysis - UseStaticAnalysis - - - \ No newline at end of file diff --git a/LibGit2Sharp/LibGit2Sharp.v2.ncrunchproject b/LibGit2Sharp/LibGit2Sharp.v2.ncrunchproject deleted file mode 100644 index cc3cf2122..000000000 --- a/LibGit2Sharp/LibGit2Sharp.v2.ncrunchproject +++ /dev/null @@ -1,25 +0,0 @@ - - 1000 - false - false - false - true - false - false - false - false - false - true - true - false - true - true - true - 60000 - - - - AutoDetect - STA - x86 - \ No newline at end of file From e688d42699495c22b361c0d7c34d9110f5e65605 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 14:59:41 -0400 Subject: [PATCH 121/179] Remove Coverlet --- Directory.Build.targets | 8 -------- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 - 2 files changed, 9 deletions(-) delete mode 100644 Directory.Build.targets diff --git a/Directory.Build.targets b/Directory.Build.targets deleted file mode 100644 index 1ddcba6f4..000000000 --- a/Directory.Build.targets +++ /dev/null @@ -1,8 +0,0 @@ - - - cobertura - [xunit.*]* - - $(OutputPath)/ - - diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 1810df2ee..7ef0c4f2a 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -11,7 +11,6 @@ - From 8c7d9e54a24cd75bbc68067d0aec006593cc990b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 15:37:17 -0400 Subject: [PATCH 122/179] Add GitHub Actions workflow --- .github/workflows/ci.yml | 50 ++++++++++++++++++++ Directory.Build.props | 4 +- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 5 +- LibGit2Sharp/LibGit2Sharp.csproj | 1 + 4 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..d6010aea9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,50 @@ +name: CI +on: + push: + branches: [master, release-*] + tags: + - '[0-9]+.[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+-*' + pull_request: + workflow_dispatch: +env: + DOTNET_NOLOGO: true +jobs: + build: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: windows-2019 + name: Windows + - os: ubuntu-20.04 + name: Linux + - os: macos-10.15 + name: macOS + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v2.3.4 + with: + fetch-depth: 0 + - name: Setup .NET SDK + uses: actions/setup-dotnet@v1.8.1 + with: + dotnet-version: 5.0.x + - name: Setup .NET Core 3.1 runtime + uses: actions/setup-dotnet@v1.8.1 + with: + dotnet-version: 3.1.x + - name: Build + run: dotnet build LibGit2Sharp.sln --configuration Release + - name: Upload packages + if: matrix.name == 'Windows' + uses: actions/upload-artifact@v2.2.4 + with: + name: NuGet packages + path: bin/Packages/ + retention-days: 7 + - name: Run tests + run: dotnet test LibGit2Sharp.sln --configuration Release --no-build --logger "GitHubActions" + diff --git a/Directory.Build.props b/Directory.Build.props index 06e7f5642..30d3f82cb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,8 +4,8 @@ true $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ - $(MSBuildThisFileDirectory)bin\Packages\$(Configuration)\ + $(MSBuildThisFileDirectory)bin\Packages\ $(DefineConstants);$(ExtraDefine) - + diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 7ef0c4f2a..24e558461 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net472;netcoreapp2.1;net5.0 + net472;netcoreapp3.1;net5.0 @@ -11,7 +11,8 @@ - + + diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index d35369d94..470ef0dff 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -18,6 +18,7 @@ ..\libgit2sharp.snk square-logo.png App_Readme/LICENSE.md + true From b4165b1b34e07ffa815a695c3661dc10c52b7bcb Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 15:52:32 -0400 Subject: [PATCH 123/179] Split tests by TFM --- .github/workflows/ci.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6010aea9..d64b87e2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,6 +45,11 @@ jobs: name: NuGet packages path: bin/Packages/ retention-days: 7 - - name: Run tests - run: dotnet test LibGit2Sharp.sln --configuration Release --no-build --logger "GitHubActions" + - name: Run net472 tests + if: matrix.name == 'Windows' + run: dotnet test LibGit2Sharp.sln --configuration Release --no-build --framework net472 --logger "GitHubActions" + - name: Run netcoreapp3.1 tests + run: dotnet test LibGit2Sharp.sln --configuration Release --no-build --framework netcoreapp3.1 --logger "GitHubActions" + - name: Run net5.0 tests + run: dotnet test LibGit2Sharp.sln --configuration Release --no-build --framework net5.0 --logger "GitHubActions" From d7085fc5c424627db5d4eeb1ff27b61d8cdcd1a8 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 16:47:50 -0400 Subject: [PATCH 124/179] Run tests with LEAKS_IDENTIFYING --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d64b87e2c..d61e3350c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,9 +47,8 @@ jobs: retention-days: 7 - name: Run net472 tests if: matrix.name == 'Windows' - run: dotnet test LibGit2Sharp.sln --configuration Release --no-build --framework net472 --logger "GitHubActions" + run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net472 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING - name: Run netcoreapp3.1 tests - run: dotnet test LibGit2Sharp.sln --configuration Release --no-build --framework netcoreapp3.1 --logger "GitHubActions" + run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework netcoreapp3.1 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING - name: Run net5.0 tests - run: dotnet test LibGit2Sharp.sln --configuration Release --no-build --framework net5.0 --logger "GitHubActions" - + run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net5.0 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING From 1f917f59b5d08fbc6fbbe8b9a7402a92451f26f1 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 17:17:35 -0400 Subject: [PATCH 125/179] Set ContinuousIntegrationBuild to true for CI --- Directory.Build.props | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Directory.Build.props b/Directory.Build.props index 30d3f82cb..72eda8864 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,4 +8,8 @@ $(DefineConstants);$(ExtraDefine) + + true + + From 04114067606d7b9c229215a599a32814bd535b62 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 17:21:21 -0400 Subject: [PATCH 126/179] Switch to embedded PDBs --- LibGit2Sharp/LibGit2Sharp.csproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 470ef0dff..0885f546f 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -11,9 +11,7 @@ LibGit2Sharp contributors true true - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - true - snupkg + embedded true ..\libgit2sharp.snk square-logo.png From d9777fced3c10bff85b571c0dcecf6e4bfc7fcaa Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 17:36:18 -0400 Subject: [PATCH 127/179] Tweak package description --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 0885f546f..6907eb5ad 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -3,7 +3,7 @@ netstandard2.0;netcoreapp2.1 true - LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .Net and Mono. + LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET LibGit2Sharp contributors Copyright © LibGit2Sharp contributors libgit2 git From a557593acdec5805ecaeb25aea690b70eee27305 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 18:41:55 -0400 Subject: [PATCH 128/179] Update README --- README.md | 71 +++++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index c67e6ec8e..702d35832 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,45 @@ # LibGit2Sharp -[![master azurepipelines][master-azurepipelines-badge]][master-azurepipelines] -[![master win][master-win-badge]][master-win] -[![master nix][master-nix-badge]][master-nix] -[![coverity][coverity-badge]][coverity-project] +![master CI](https://github.com/libgit2/libgit2sharp/actions/workflows/ci.yml/badge.svg) -[master-azurepipelines-badge]: https://dev.azure.com/libgit2sharp/libgit2sharp/_apis/build/status/libgit2sharp?branchName=master -[master-azurepipelines]: https://dev.azure.com/libgit2sharp/libgit2sharp/_build/latest?definitionId=1 -[master-win-badge]: https://ci.appveyor.com/api/projects/status/8qxcoqdo9kp7x2w9/branch/master?svg=true -[master-win]: https://ci.appveyor.com/project/libgit2/libgit2sharp/branch/master -[master-nix-badge]: https://travis-ci.org/libgit2/libgit2sharp.svg?branch=master -[master-nix]: https://travis-ci.org/libgit2/libgit2sharp/branches - -[coverity-project]: https://scan.coverity.com/projects/2088 -[coverity-badge]: https://scan.coverity.com/projects/2088/badge.svg - -**LibGit2Sharp brings all the might and speed of [libgit2][libgit2], a native Git implementation, to the managed world of .NET and Mono.** - - [libgit2]: http://libgit2.github.com/ - -## Prerequisites - - - **Windows:** .NET 4.6.1+ - - **Linux/Mac OS X:** Mono 5.4+ +**LibGit2Sharp brings all the might and speed of [libgit2](http://libgit2.github.com/), a native Git implementation, to the managed world of .NET** ## Online resources - - [NuGet package][nuget] (Requires NuGet 2.7+) - - [Source code][source] - - [nuget]: http://nuget.org/List/Packages/LibGit2Sharp - [source]: https://github.com/libgit2/libgit2sharp/ +- [NuGet package](http://nuget.org/List/Packages/LibGit2Sharp) +- [Source code](https://github.com/libgit2/libgit2sharp/) ## Troubleshooting and support - - Usage or programming related question? Post it on [StackOverflow][so] using the tag *libgit2sharp* - - Found a bug or missing a feature? Feed the [issue tracker][tracker] - - Announcements and related miscellanea through Twitter ([@libgit2sharp][twitter]) - - [so]: http://stackoverflow.com/questions/tagged/libgit2sharp - [tracker]: https://github.com/libgit2/libgit2sharp/issues - [twitter]: http://twitter.com/libgit2sharp +- Usage or programming related question? Post it on [StackOverflow](http://stackoverflow.com/questions/tagged/libgit2sharp) using the tag *libgit2sharp* +- Found a bug or missing a feature? Feed the [issue tracker](https://github.com/libgit2/libgit2sharp/issues) +- Announcements and related miscellanea through Twitter ([@libgit2sharp](http://twitter.com/libgit2sharp)) ## Quick contributing guide - - Fork and clone locally - - Create a topic specific branch. Add some nice feature. Do not forget the tests ;-) - - Send a Pull Request to spread the fun! - -More thorough information available in the [wiki][wiki]. +- Fork and clone locally +- Create a topic specific branch. Add some nice feature. Do not forget the tests ;-) +- Send a Pull Request to spread the fun! - [wiki]: https://github.com/libgit2/libgit2sharp/wiki +More thorough information is available in the [wiki](https://github.com/libgit2/libgit2sharp/wiki). ## Optimizing unit testing -LibGit2Sharp strives to have comprehensive and robust unit test suite to ensure the quality of the software and to assist new contributors and users who can use the tests as sample to jump start development. There are over one thousand unit-tests for LibGit2Sharp, this number will only grow as functionality is added. -You can do a few things to optimize running unit-tests on Windows: +LibGit2Sharp strives to have a comprehensive and robust unit test suite to ensure the quality of the software and to assist new contributors and users, who can use the tests as examples to jump start development. There are over one thousand unit tests for LibGit2Sharp, and this number will only grow as functionality is added. + +You can do a few things to optimize running unit tests on Windows: 1. Set the `LibGit2TestPath` environment variable to a path in your development environment. - * If the unit-test framework cannot find the specified folder at runtime, it will fall back to the default location. + * If the unit test framework cannot find the specified folder at runtime, it will fall back to the default location. 2. Configure your anti-virus software to ignore the `LibGit2TestPath` path. 3. Install a RAM disk like [IMDisk](http://www.ltr-data.se/opencode.html/#ImDisk) and set `LibGit2TestPath` to use it. - * Use `imdisk.exe -a -s 512M -m X: -p "/fs:fat /q /v:ramdisk /y"` to create a RAM disk. This command requires elevated privileges and can be placed into a scheduled task or run manually before you begin unit-testing. + * Use `imdisk.exe -a -s 512M -m X: -p "/fs:fat /q /v:ramdisk /y"` to create a RAM disk. This command requires elevated privileges and can be placed into a scheduled task or run manually before you begin unit-testing. ## Authors - - **Code:** The LibGit2Sharp [contributors][committers] - - **Logo:** [Jason "blackant" Long][blackant] - - [committers]: https://github.com/libgit2/libgit2sharp/contributors - [blackant]: https://github.com/jasonlong +- **Code:** The LibGit2Sharp [contributors](https://github.com/libgit2/libgit2sharp/contributors) +- **Logo:** [Jason "blackant" Long](https://github.com/jasonlong) ## License -The MIT license (Refer to the [LICENSE.md][license] file) - - [license]: https://github.com/libgit2/libgit2sharp/blob/master/LICENSE.md +The MIT license (Refer to the [LICENSE.md](https://github.com/libgit2/libgit2sharp/blob/master/LICENSE.md) file) From fe27c0f33ccfacabd2237ef4b5ac612c10a9f55b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 18:57:56 -0400 Subject: [PATCH 129/179] Update TFM define --- LibGit2Sharp.Tests/BlobFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/BlobFixture.cs b/LibGit2Sharp.Tests/BlobFixture.cs index 7afbe255f..f39429b74 100644 --- a/LibGit2Sharp.Tests/BlobFixture.cs +++ b/LibGit2Sharp.Tests/BlobFixture.cs @@ -43,7 +43,7 @@ public void CanGetBlobAsFilteredText(string autocrlf, string expectedText) } } -#if NETFRAMEWORK || NETCOREAPP2_1 +#if NETFRAMEWORK || NETCOREAPP3_1 //UTF-7 is disabled in .NET 5 [Theory] [InlineData("ascii", 4, "31 32 33 34")] [InlineData("utf-7", 4, "31 32 33 34")] From a0c46f23207f9dfc7c0b3574b22f3b5eaa605ba8 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 19:09:24 -0400 Subject: [PATCH 130/179] Remove outdated dictionary file --- LibGit2Sharp/CustomDictionary.xml | 29 ----------------------------- LibGit2Sharp/LibGit2Sharp.csproj | 1 - 2 files changed, 30 deletions(-) delete mode 100644 LibGit2Sharp/CustomDictionary.xml diff --git a/LibGit2Sharp/CustomDictionary.xml b/LibGit2Sharp/CustomDictionary.xml deleted file mode 100644 index fe603c22b..000000000 --- a/LibGit2Sharp/CustomDictionary.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - git - sha - unstage - unstaged - compat - oid - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 6907eb5ad..2d03a42ee 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -20,7 +20,6 @@ - From ff9f5f02702ce548cc2f734eea8dbf5d8f345315 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 19:16:47 -0400 Subject: [PATCH 131/179] Clean up nuget.config --- .editorconfig | 2 +- nuget.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 5021a5b28..2e54d0f2d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,5 +14,5 @@ insert_final_newline = true trim_trailing_whitespace = false insert_final_newline = false -[*.{props,targets,csproj}] +[*.{props,targets,csproj,config}] indent_size = 2 \ No newline at end of file diff --git a/nuget.config b/nuget.config index 19d85b78f..35696f810 100644 --- a/nuget.config +++ b/nuget.config @@ -1,6 +1,6 @@  - + From 767724b3f8b1df131bf0b7d7f0377ebace44ee5e Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 19:20:35 -0400 Subject: [PATCH 132/179] Remove unneeded AssemblyInfo file --- LibGit2Sharp/Properties/AssemblyInfo.cs | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 LibGit2Sharp/Properties/AssemblyInfo.cs diff --git a/LibGit2Sharp/Properties/AssemblyInfo.cs b/LibGit2Sharp/Properties/AssemblyInfo.cs deleted file mode 100644 index ffa977d1d..000000000 --- a/LibGit2Sharp/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: CLSCompliant(true)] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("c6f71967-5be1-49f5-b48e-861bff498ea3")] From 47e674db765bb88c9a779bb4a7488345d429f878 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Oct 2021 19:21:09 -0400 Subject: [PATCH 133/179] Clean up items referenced only for packing --- LibGit2Sharp/LibGit2Sharp.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 2d03a42ee..58c759fa5 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -20,10 +20,10 @@ - - - - + + + + From 85f1f1b7af3380bd640c67e699c77b8af2004923 Mon Sep 17 00:00:00 2001 From: OronDF343 Date: Sun, 17 Oct 2021 12:24:17 +0300 Subject: [PATCH 134/179] Fix incorrect information in exceptions The parameters displayed in "Unknown fast forward strategy" and "Unknown merge analysis" were swapped. This change fixes that. --- LibGit2Sharp/Repository.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 721133cc6..41aaecfbf 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -1500,13 +1500,13 @@ private MergeResult Merge(AnnotatedCommitHandle[] annotatedCommits, Signature me break; default: throw new NotImplementedException( - string.Format(CultureInfo.InvariantCulture, "Unknown fast forward strategy: {0}", mergeAnalysis)); + string.Format(CultureInfo.InvariantCulture, "Unknown fast forward strategy: {0}", fastForwardStrategy)); } if (mergeResult == null) { throw new NotImplementedException( - string.Format(CultureInfo.InvariantCulture, "Unknown merge analysis: {0}", options.FastForwardStrategy)); + string.Format(CultureInfo.InvariantCulture, "Unknown merge analysis: {0}", mergeAnalysis)); } return mergeResult; From 967bb6bd3c190f2b9be93a0e90a56df19b1285ac Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 20 Oct 2021 09:03:29 +0200 Subject: [PATCH 135/179] use .net 6.0 SDK --- .github/workflows/ci.yml | 12 +++++++++--- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d61e3350c..d290e30d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,14 +28,18 @@ jobs: uses: actions/checkout@v2.3.4 with: fetch-depth: 0 - - name: Setup .NET SDK + - name: Setup .NET Core 3.1 SDK + uses: actions/setup-dotnet@v1.8.1 + with: + dotnet-version: 3.1.x + - name: Setup .NET 5.0 SDK uses: actions/setup-dotnet@v1.8.1 with: dotnet-version: 5.0.x - - name: Setup .NET Core 3.1 runtime + - name: Setup .NET 6.0 SDK uses: actions/setup-dotnet@v1.8.1 with: - dotnet-version: 3.1.x + dotnet-version: 6.0.x - name: Build run: dotnet build LibGit2Sharp.sln --configuration Release - name: Upload packages @@ -52,3 +56,5 @@ jobs: run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework netcoreapp3.1 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING - name: Run net5.0 tests run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net5.0 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING + - name: Run net6.0 tests + run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net6.0 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 24e558461..771b75696 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net472;netcoreapp3.1;net5.0 + net472;netcoreapp3.1;net5.0;net6.0 From 98363991e0c702fd9d0e8345e44fc10b1909b12e Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 8 Nov 2021 13:52:19 -0500 Subject: [PATCH 136/179] Tweaks --- .github/workflows/ci.yml | 10 +++++----- LibGit2Sharp.Tests/BlobFixture.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d290e30d4..3d1d66f5f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,18 +28,18 @@ jobs: uses: actions/checkout@v2.3.4 with: fetch-depth: 0 - - name: Setup .NET Core 3.1 SDK + - name: Install .NET SDK uses: actions/setup-dotnet@v1.8.1 with: - dotnet-version: 3.1.x - - name: Setup .NET 5.0 SDK + dotnet-version: 6.0.x + - name: Install .NET 5 runtime uses: actions/setup-dotnet@v1.8.1 with: dotnet-version: 5.0.x - - name: Setup .NET 6.0 SDK + - name: Install .NET Core 3.1 runtime uses: actions/setup-dotnet@v1.8.1 with: - dotnet-version: 6.0.x + dotnet-version: 3.1.x - name: Build run: dotnet build LibGit2Sharp.sln --configuration Release - name: Upload packages diff --git a/LibGit2Sharp.Tests/BlobFixture.cs b/LibGit2Sharp.Tests/BlobFixture.cs index f39429b74..98b30dcfc 100644 --- a/LibGit2Sharp.Tests/BlobFixture.cs +++ b/LibGit2Sharp.Tests/BlobFixture.cs @@ -43,7 +43,7 @@ public void CanGetBlobAsFilteredText(string autocrlf, string expectedText) } } -#if NETFRAMEWORK || NETCOREAPP3_1 //UTF-7 is disabled in .NET 5 +#if NETFRAMEWORK || NETCOREAPP3_1 //UTF-7 is disabled in .NET 5+ [Theory] [InlineData("ascii", 4, "31 32 33 34")] [InlineData("utf-7", 4, "31 32 33 34")] From 66dae0f806f3b7b652235c55dd3e5ac459855886 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 8 Nov 2021 19:27:26 -0500 Subject: [PATCH 137/179] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 702d35832..8ed3fb4d2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # LibGit2Sharp -![master CI](https://github.com/libgit2/libgit2sharp/actions/workflows/ci.yml/badge.svg) +[![CI](https://github.com/libgit2/libgit2sharp/actions/workflows/ci.yml/badge.svg)](https://github.com/libgit2/libgit2sharp/actions/workflows/ci.yml) **LibGit2Sharp brings all the might and speed of [libgit2](http://libgit2.github.com/), a native Git implementation, to the managed world of .NET** From 35abcc787a6148aa54521a2e5050ea52419d1231 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Oct 2021 17:45:12 -0400 Subject: [PATCH 138/179] Switch to netcoreapp3.1 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 58c759fa5..95f95a8bb 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - netstandard2.0;netcoreapp2.1 + netstandard2.0;netcoreapp3.1 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET LibGit2Sharp contributors From 2bde4cbf1f2d40bd5dcf674d1ed22fcd60a82c55 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Oct 2021 17:49:57 -0400 Subject: [PATCH 139/179] Use RuntimeInformation.ProcessArchitecture --- LibGit2Sharp/Core/Platform.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index e8d536475..42b752612 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -12,7 +12,7 @@ internal enum OperatingSystemType internal static class Platform { - public static string ProcessorArchitecture => IntPtr.Size == 8 ? "x64" : "x86"; + public static string ProcessorArchitecture => RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(); public static OperatingSystemType OperatingSystem { From b6d3e2f3a9ba79fb42aba9456e6aa8fbdc63a6a8 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Oct 2021 17:51:51 -0400 Subject: [PATCH 140/179] Don't append arch to NativeLibraryPath --- LibGit2Sharp/GlobalSettings.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 00b031ca0..d24637df0 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -32,7 +32,7 @@ static GlobalSettings() if (netFX) { // For .NET Framework apps the dependencies are deployed to lib/win32/{architecture} directory - nativeLibraryDefaultPath = Path.Combine(GetExecutingAssemblyDirectory(), "lib", "win32"); + nativeLibraryDefaultPath = Path.Combine(GetExecutingAssemblyDirectory(), "lib", "win32", Platform.ProcessorArchitecture); } else { @@ -159,8 +159,6 @@ public static LogConfiguration LogConfiguration /// /// Sets a path for loading native binaries on .NET Framework or .NET Core. /// When specified, native library will first be searched under the given path. - /// On .NET Framework a subdirectory corresponding to the architecture ("x86" or "x64") is appended, - /// otherwise the native library is expected to be found in the directory as specified. /// /// If the library is not found it will be searched in standard search paths: /// , @@ -170,10 +168,6 @@ public static LogConfiguration LogConfiguration /// This must be set before any other calls to the library, /// and is not available on other platforms than .NET Framework and .NET Core. /// - /// - /// If not specified on .NET Framework it defaults to lib/win32 subdirectory - /// of the directory where this assembly is loaded from. - /// /// public static string NativeLibraryPath { @@ -213,8 +207,7 @@ public static string NativeLibraryPath internal static string GetAndLockNativeLibraryPath() { nativeLibraryPathLocked = true; - string result = nativeLibraryPath ?? nativeLibraryDefaultPath; - return Platform.IsRunningOnNetFramework() ? Path.Combine(result, Platform.ProcessorArchitecture) : result; + return nativeLibraryPath ?? nativeLibraryDefaultPath; } /// From 709a2c80248e055ba13e95a65ec0fa7bbe16336b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Oct 2021 17:56:20 -0400 Subject: [PATCH 141/179] Use NativeLibrary directly when possible --- LibGit2Sharp/Core/NativeMethods.cs | 73 +++++++----------------------- 1 file changed, 17 insertions(+), 56 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 04be0e683..cb5fb45c3 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -30,7 +30,7 @@ static NativeMethods() { if (Platform.IsRunningOnNetFramework() || Platform.IsRunningOnNetCore()) { - // Use .NET Core 3.0+ NativeLibrary when available. + // Use NativeLibrary when available. if (!TryUseNativeLibrary()) { // NativeLibrary is not available, fall back. @@ -40,6 +40,7 @@ static NativeMethods() // If this call succeeds further DllImports will find the library loaded and not attempt to load it again. // If it fails the next DllImport will load the library from safe directories. string nativeLibraryPath = GetGlobalSettingsNativeLibraryPath(); + if (nativeLibraryPath != null) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -61,65 +62,21 @@ static NativeMethods() private static string GetGlobalSettingsNativeLibraryPath() { string nativeLibraryDir = GlobalSettings.GetAndLockNativeLibraryPath(); + if (nativeLibraryDir == null) { return null; } - return Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension()); - } - - private delegate bool TryLoadLibraryByNameDelegate(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle); - private delegate bool TryLoadLibraryByPathDelegate(string libraryPath, out IntPtr handle); - - static TryLoadLibraryByNameDelegate _tryLoadLibraryByName; - static TryLoadLibraryByPathDelegate _tryLoadLibraryByPath; - - static bool TryLoadLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle) - { - if (_tryLoadLibraryByName == null) - { - throw new NotSupportedException(); - } - return _tryLoadLibraryByName(libraryName, assembly, searchPath, out handle); - } - static bool TryLoadLibrary(string libraryPath, out IntPtr handle) - { - if (_tryLoadLibraryByPath == null) - { - throw new NotSupportedException(); - } - return _tryLoadLibraryByPath(libraryPath, out handle); + return Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension()); } +#if NETSTANDARD + private static bool TryUseNativeLibrary() => false; +#else private static bool TryUseNativeLibrary() { - // NativeLibrary is available in .NET Core 3.0+. - // We use reflection to use NativeLibrary so this library can target 'netstandard2.0'. - - Type dllImportResolverType = Type.GetType("System.Runtime.InteropServices.DllImportResolver, System.Runtime.InteropServices", throwOnError: false); - Type nativeLibraryType = Type.GetType("System.Runtime.InteropServices.NativeLibrary, System.Runtime.InteropServices", throwOnError: false); - var tryLoadLibraryByName = (TryLoadLibraryByNameDelegate)nativeLibraryType?.GetMethod("TryLoad", - new Type[] { typeof(string), typeof(Assembly), typeof(DllImportSearchPath?), typeof(IntPtr).MakeByRefType() })?.CreateDelegate(typeof(TryLoadLibraryByNameDelegate)); - var tryLoadLibraryByPath = (TryLoadLibraryByPathDelegate)nativeLibraryType?.GetMethod("TryLoad", - new Type[] { typeof(string), typeof(IntPtr).MakeByRefType() })?.CreateDelegate(typeof(TryLoadLibraryByPathDelegate)); - MethodInfo setDllImportResolver = nativeLibraryType?.GetMethod("SetDllImportResolver", new Type[] { typeof(Assembly), dllImportResolverType }); - - if (dllImportResolverType == null || - nativeLibraryType == null || - tryLoadLibraryByName == null || - tryLoadLibraryByPath == null || - setDllImportResolver == null) - { - return false; - } - - _tryLoadLibraryByPath = tryLoadLibraryByPath; - _tryLoadLibraryByName = tryLoadLibraryByName; - - // NativeMethods.SetDllImportResolver(typeof(NativeMethods).Assembly, ResolveDll); - object resolveDelegate = typeof(NativeMethods).GetMethod(nameof(ResolveDll), BindingFlags.NonPublic | BindingFlags.Static).CreateDelegate(dllImportResolverType); - setDllImportResolver.Invoke(null, new object[] { typeof(NativeMethods).Assembly, resolveDelegate }); + NativeLibrary.SetDllImportResolver(typeof(NativeMethods).Assembly, ResolveDll); return true; } @@ -127,23 +84,24 @@ private static bool TryUseNativeLibrary() private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) { IntPtr handle = IntPtr.Zero; + if (libraryName == libgit2) { // Use GlobalSettings.NativeLibraryPath when set. string nativeLibraryPath = GetGlobalSettingsNativeLibraryPath(); - if (nativeLibraryPath != null && - TryLoadLibrary(nativeLibraryPath, out handle)) + + if (nativeLibraryPath != null && NativeLibrary.TryLoad(nativeLibraryPath, out handle)) { return handle; } // Use Default DllImport resolution. - if (TryLoadLibrary(libraryName, assembly, searchPath, out handle)) + if (NativeLibrary.TryLoad(libraryName, assembly, searchPath, out handle)) { return handle; } - // We cary a number of .so files for Linux which are linked against various + // We carry a number of .so files for Linux which are linked against various // libc/OpenSSL libraries. Try them out. if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { @@ -158,7 +116,8 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor foreach (var runtimeFolder in Directory.GetDirectories(runtimesDirectory, $"*-{processorArchitecture}")) { string libPath = Path.Combine(runtimeFolder, "native", $"lib{libraryName}.so"); - if (TryLoadLibrary(libPath, out handle)) + + if (NativeLibrary.TryLoad(libPath, out handle)) { return handle; } @@ -166,8 +125,10 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor } } } + return handle; } +#endif public const int RTLD_NOW = 0x002; From 3e78e83b0123f920e0a0448d684b67c61fcebd85 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Oct 2021 17:59:37 -0400 Subject: [PATCH 142/179] Clean up unneeded pragmas --- LibGit2Sharp/Core/NativeMethods.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index cb5fb45c3..809a77309 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -9,9 +9,6 @@ // Restrict the set of directories where the native library is loaded from to safe directories. [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.ApplicationDirectory | DllImportSearchPath.SafeDirectories)] -#pragma warning disable IDE1006 // Naming Styles - -// ReSharper disable InconsistentNaming namespace LibGit2Sharp.Core { internal static class NativeMethods @@ -22,9 +19,7 @@ internal static class NativeMethods // An object tied to the lifecycle of the NativeMethods static class. // This will handle initialization and shutdown of the underlying // native library. -#pragma warning disable 0414 private static NativeShutdownObject shutdownObject; -#pragma warning restore 0414 static NativeMethods() { @@ -2071,4 +2066,3 @@ internal static extern unsafe int git_worktree_prune( git_worktree_prune_options options); } } -// ReSharper restore InconsistentNaming From 9a9a297ee49df921ba7e3268de3ff2279f0f79bd Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Oct 2021 18:41:46 -0400 Subject: [PATCH 143/179] Update tests --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 8 +++++--- NativeLibraryLoadTestApp/TestApp.cs | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 55260a6f5..8f1aa9d0b 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Reflection; using System.Text.RegularExpressions; using LibGit2Sharp.Core; using LibGit2Sharp.Tests.TestHelpers; @@ -64,12 +65,13 @@ public void LoadFromSpecifiedPath(string architecture) var testDir = Path.GetDirectoryName(typeof(GlobalSettingsFixture).Assembly.Location); var testAppExe = Path.Combine(testDir, $"NativeLibraryLoadTestApp.{architecture}.exe"); var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - var platformDir = Path.Combine(tempDir, "plat"); + var platformDir = Path.Combine(tempDir, "plat", architecture); + var libraryPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lib", "win32", architecture); try { - Directory.CreateDirectory(Path.Combine(platformDir, architecture)); - File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, architecture, nativeDllFileName), Path.Combine(platformDir, architecture, nativeDllFileName)); + Directory.CreateDirectory(platformDir); + File.Copy(Path.Combine(libraryPath, nativeDllFileName), Path.Combine(platformDir, nativeDllFileName)); var (output, exitCode) = ProcessHelper.RunProcess(testAppExe, arguments: $@"{NativeDllName.Name} ""{platformDir}""", workingDirectory: tempDir); diff --git a/NativeLibraryLoadTestApp/TestApp.cs b/NativeLibraryLoadTestApp/TestApp.cs index 234169a75..6a9f3ab60 100644 --- a/NativeLibraryLoadTestApp/TestApp.cs +++ b/NativeLibraryLoadTestApp/TestApp.cs @@ -11,7 +11,7 @@ public class TestApp private static extern IntPtr GetModuleHandle(string path); [DllImport("kernel32")] - private static extern int GetModuleFileName(IntPtr handle, [Out]StringBuilder path, int size); + private static extern int GetModuleFileName(IntPtr handle, [Out] StringBuilder path, int size); static int Main(string[] args) { @@ -23,7 +23,7 @@ static int Main(string[] args) var moduleName = args[0]; var loadFromDirectory = args[1]; - var expectedPath = Path.Combine(loadFromDirectory, (IntPtr.Size == 4) ? "x86" : "x64", moduleName + ".dll"); + var expectedPath = Path.Combine(loadFromDirectory, moduleName + ".dll"); GlobalSettings.NativeLibraryPath = loadFromDirectory; var isValid = Repository.IsValid(Path.GetTempPath()); From 2a68da8c33ce0498563d4c60c9fd81d026a5f443 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 8 Nov 2021 22:44:25 -0500 Subject: [PATCH 144/179] Update LibGit2Sharp.NativeBinaries to 2.0.315-alpha.0.7 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 95f95a8bb..7d221c3e1 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -30,7 +30,7 @@ - + From 0e7ec84e1a339e0215b71f85244dd06a06d82d61 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 10 Nov 2021 20:43:58 -0500 Subject: [PATCH 145/179] Update LibGit2Sharp.NativeBinaries to 2.0.315-alpha.0.9 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 7d221c3e1..57c81cdfb 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -30,7 +30,7 @@ - + From bd7f5da03cde06bc54a32a6cf718761c8e0d1c52 Mon Sep 17 00:00:00 2001 From: Artur Date: Thu, 11 Nov 2021 11:19:10 +0100 Subject: [PATCH 146/179] added jobs for running tests in docker for several distros --- .github/workflows/ci.yml | 36 ++++++++++++++++++++ LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d1d66f5f..c9cdc9127 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,3 +58,39 @@ jobs: run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net5.0 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING - name: Run net6.0 tests run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net6.0 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING + native_test: + name: Test on [${{ matrix.arch }}] net${{ matrix.sdk }} SDK - ${{ matrix.distro }} + runs-on: ubuntu-20.04 + strategy: + matrix: + arch: [ amd64 ] + # arch: [ amd64, arm64 ] + sdk: [ '6.0', '5.0', '3.1' ] + distro: [ alpine.3.12, alpine.3.13, alpine.3.14, centos.7, centos.8, debian.9, debian.10, debian.11, fedora.33, ubuntu.18.04, ubuntu.20.04 ] + exclude: + - arch: arm64 + distro: alpine.3.12 + - arch: arm64 + distro: alpine.3.13 + sdk: '3.1' + - arch: arm64 + distro: alpine.3.14 + sdk: '3.1' + - arch: arm64 + distro: centos.7 + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v2.3.4 + with: + fetch-depth: 0 + + - name: Setup QEMU + run: docker run --rm --privileged multiarch/qemu-user-static:register --reset + + - name: Test with docker + run: | + [[ ${{ matrix.sdk }} = '3.1' ]] && target="netcoreapp${{ matrix.sdk }}" || target="net${{ matrix.sdk }}" + + test_command="dotnet test LibGit2Sharp.sln --configuration Release -p:TargetFrameworks=$target -p:ExtraDefine=LEAKS_IDENTIFYING -p:GeneratePackageOnBuild=false" + docker run -t --rm --platform linux/${{ matrix.arch }} -v "$PWD:/app" gittools/build-images:${{ matrix.distro }}-sdk-${{ matrix.sdk }} sh -c "$test_command" diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 771b75696..6ddcfbd05 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net472;netcoreapp3.1;net5.0;net6.0 + net472;netcoreapp3.1;net5.0;net6.0 From b90a6a9c267b16678cb1257f2a354b991410817f Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 13 Nov 2021 22:48:48 -0500 Subject: [PATCH 147/179] Revise workflows to better integrate them --- .github/workflows/ci.yml | 97 ++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9cdc9127..1f7351f39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,17 +11,36 @@ env: DOTNET_NOLOGO: true jobs: build: - name: ${{ matrix.name }} + name: Build + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2.3.4 + with: + fetch-depth: 0 + - name: Install .NET SDK + uses: actions/setup-dotnet@v1.8.1 + with: + dotnet-version: 6.0.x + - name: Build + run: dotnet build LibGit2Sharp.sln --configuration Release + - name: Upload packages + uses: actions/upload-artifact@v2.2.4 + with: + name: NuGet packages + path: bin/Packages/ + retention-days: 7 + test: + name: Test / ${{ matrix.os }} / ${{ matrix.arch }} / ${{ matrix.tfm }} runs-on: ${{ matrix.os }} strategy: matrix: - include: - - os: windows-2019 - name: Windows - - os: ubuntu-20.04 - name: Linux + arch: [ amd64 ] + os: [windows-2019, macos-10.15] + tfm: [ net472, netcoreapp3.1, net5.0, net6.0 ] + exclude: - os: macos-10.15 - name: macOS + tfm: net472 fail-fast: false steps: - name: Checkout @@ -33,64 +52,54 @@ jobs: with: dotnet-version: 6.0.x - name: Install .NET 5 runtime + if: matrix.tfm == 'net5.0' uses: actions/setup-dotnet@v1.8.1 with: dotnet-version: 5.0.x - name: Install .NET Core 3.1 runtime + if: matrix.tfm == 'netcoreapp3.1' uses: actions/setup-dotnet@v1.8.1 with: dotnet-version: 3.1.x - - name: Build - run: dotnet build LibGit2Sharp.sln --configuration Release - - name: Upload packages - if: matrix.name == 'Windows' - uses: actions/upload-artifact@v2.2.4 - with: - name: NuGet packages - path: bin/Packages/ - retention-days: 7 - - name: Run net472 tests - if: matrix.name == 'Windows' - run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net472 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING - - name: Run netcoreapp3.1 tests - run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework netcoreapp3.1 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING - - name: Run net5.0 tests - run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net5.0 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING - - name: Run net6.0 tests - run: dotnet test LibGit2Sharp.sln --configuration Release --no-restore --framework net6.0 --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING - native_test: - name: Test on [${{ matrix.arch }}] net${{ matrix.sdk }} SDK - ${{ matrix.distro }} + - name: Run ${{ matrix.tfm }} tests + run: dotnet test LibGit2Sharp.sln --configuration Release --framework ${{ matrix.tfm }} --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING + test-linux: + name: Test / ${{ matrix.distro }} / ${{ matrix.arch }} / ${{ matrix.tfm }} runs-on: ubuntu-20.04 strategy: matrix: arch: [ amd64 ] # arch: [ amd64, arm64 ] - sdk: [ '6.0', '5.0', '3.1' ] distro: [ alpine.3.12, alpine.3.13, alpine.3.14, centos.7, centos.8, debian.9, debian.10, debian.11, fedora.33, ubuntu.18.04, ubuntu.20.04 ] + sdk: [ '6.0', '5.0', '3.1' ] exclude: - - arch: arm64 - distro: alpine.3.12 - - arch: arm64 - distro: alpine.3.13 - sdk: '3.1' - - arch: arm64 - distro: alpine.3.14 - sdk: '3.1' - - arch: arm64 - distro: centos.7 + - arch: arm64 + distro: alpine.3.12 + - arch: arm64 + distro: alpine.3.13 + sdk: '3.1' + - arch: arm64 + distro: alpine.3.14 + sdk: '3.1' + - arch: arm64 + distro: centos.7 + include: + - sdk: '6.0' + tfm: net6.0 + - sdk: '5.0' + tfm: net5.0 + - sdk: '3.1' + tfm: netcoreapp3.1 fail-fast: false steps: - name: Checkout uses: actions/checkout@v2.3.4 with: fetch-depth: 0 - - name: Setup QEMU + if: matrix.arch == 'arm64' run: docker run --rm --privileged multiarch/qemu-user-static:register --reset - - - name: Test with docker + - name: Run ${{ matrix.tfm }} tests run: | - [[ ${{ matrix.sdk }} = '3.1' ]] && target="netcoreapp${{ matrix.sdk }}" || target="net${{ matrix.sdk }}" - - test_command="dotnet test LibGit2Sharp.sln --configuration Release -p:TargetFrameworks=$target -p:ExtraDefine=LEAKS_IDENTIFYING -p:GeneratePackageOnBuild=false" + test_command="dotnet test LibGit2Sharp.sln --configuration Release -p:TargetFrameworks=${{ matrix.tfm }} --logger "GitHubActions" -p:ExtraDefine=LEAKS_IDENTIFYING" docker run -t --rm --platform linux/${{ matrix.arch }} -v "$PWD:/app" gittools/build-images:${{ matrix.distro }}-sdk-${{ matrix.sdk }} sh -c "$test_command" From 15fbe8e9cb92662c3fef1464cefd5de34ed573e6 Mon Sep 17 00:00:00 2001 From: Louis Zanella Date: Thu, 23 Jul 2020 16:58:42 -0400 Subject: [PATCH 148/179] Checkout branch looks to remote tracking branches as fallback --- LibGit2Sharp.Tests/CheckoutFixture.cs | 46 +++++++++++++++++++++++++++ LibGit2Sharp/Commands/Checkout.cs | 40 ++++++++++++++++++++--- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp.Tests/CheckoutFixture.cs b/LibGit2Sharp.Tests/CheckoutFixture.cs index f0c2c36ed..8962cbc1d 100644 --- a/LibGit2Sharp.Tests/CheckoutFixture.cs +++ b/LibGit2Sharp.Tests/CheckoutFixture.cs @@ -1028,6 +1028,52 @@ public void CanCheckoutPathFromCurrentBranch(string fileName) } } + [Theory] + [InlineData("br2", "origin")] + [InlineData("unique/branch", "another/remote")] + public void CheckoutBranchTriesRemoteTrackingBranchAsFallbackAndSucceedsIfOnlyOne(string branchName, string expectedRemoteName) + { + string path = SandboxStandardTestRepo(); + using (var repo = new Repository(path)) + { + ResetAndCleanWorkingDirectory(repo); + + // Define another remote + var otherRemote = "another/remote"; + repo.Network.Remotes.Add(otherRemote, "https://github.com/libgit2/TestGitRepository"); + + // Define an extra remote tracking branch that does not conflict + repo.Refs.Add($"refs/remotes/{otherRemote}/unique/branch", repo.Head.Tip.Sha); + + Branch branch = Commands.Checkout(repo, branchName); + + Assert.NotNull(branch); + Assert.True(branch.IsTracking); + Assert.Equal($"refs/remotes/{expectedRemoteName}/{branchName}", branch.TrackedBranch.CanonicalName); + } + } + + [Fact] + public void CheckoutBranchTriesRemoteTrackingBranchAsFallbackAndThrowsIfMoreThanOne() + { + string path = SandboxStandardTestRepo(); + using (var repo = new Repository(path)) + { + ResetAndCleanWorkingDirectory(repo); + + // Define another remote + var otherRemote = "another/remote"; + repo.Network.Remotes.Add(otherRemote, "https://github.com/libgit2/TestGitRepository"); + + // Define remote tracking branches that conflict + var branchName = "conflicting/branch"; + repo.Refs.Add($"refs/remotes/origin/{branchName}", repo.Head.Tip.Sha); + repo.Refs.Add($"refs/remotes/{otherRemote}/{branchName}", repo.Head.Tip.Sha); + + Assert.Throws(() => Commands.Checkout(repo, branchName)); + } + } + /// /// Helper method to populate a simple repository with /// a single file and two branches. diff --git a/LibGit2Sharp/Commands/Checkout.cs b/LibGit2Sharp/Commands/Checkout.cs index bcbd29616..17f3c3f9f 100644 --- a/LibGit2Sharp/Commands/Checkout.cs +++ b/LibGit2Sharp/Commands/Checkout.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -37,18 +38,47 @@ public static Branch Checkout(IRepository repository, string committishOrBranchS Ensure.ArgumentNotNullOrEmptyString(committishOrBranchSpec, "committishOrBranchSpec"); Ensure.ArgumentNotNull(options, "options"); - Reference reference; - GitObject obj; + Reference reference = null; + GitObject obj = null; + Branch branch = null; + + try + { + repository.RevParse(committishOrBranchSpec, out reference, out obj); + } + catch (NotFoundException) + { + // If committishOrBranchSpec is not a local branch but matches a tracking branch + // in exactly one remote, use it. This is the "git checkout" command's default behavior. + // https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt-emgitcheckoutemltbranchgt + var remoteBranches = repository.Network.Remotes + .SelectMany(r => repository.Branches.Where(b => + b.IsRemote && + b.CanonicalName == $"refs/remotes/{r.Name}/{committishOrBranchSpec}")) + .ToList(); + + if (remoteBranches.Count == 1) + { + branch = repository.CreateBranch(committishOrBranchSpec, remoteBranches[0].Tip); + repository.Branches.Update(branch, b => b.TrackedBranch = remoteBranches[0].CanonicalName); + return Checkout(repository, branch, options); + } + + if (remoteBranches.Count > 1) + throw new AmbiguousSpecificationException( + $"'{committishOrBranchSpec}' matched multiple ({remoteBranches.Count}) remote tracking branches"); + + throw; + } - repository.RevParse(committishOrBranchSpec, out reference, out obj); if (reference != null && reference.IsLocalBranch) { - Branch branch = repository.Branches[reference.CanonicalName]; + branch = repository.Branches[reference.CanonicalName]; return Checkout(repository, branch, options); } Commit commit = obj.Peel(true); - Checkout(repository, commit.Tree, options, committishOrBranchSpec); + Checkout(repository, commit.Tree, options, committishOrBranchSpec); return repository.Head; } From 44a1f22ffac7a22ce78579de9240b574fde4085e Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 11 Sep 2021 20:14:57 +0200 Subject: [PATCH 149/179] Set / get supported extensions --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 19 +++++++++++ LibGit2Sharp/Core/NativeMethods.cs | 8 +++++ LibGit2Sharp/Core/Proxy.cs | 35 +++++++++++++++++++++ LibGit2Sharp/GlobalSettings.cs | 24 ++++++++++++++ LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 5 files changed, 87 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 8f1aa9d0b..7a701ab8c 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -83,5 +83,24 @@ public void LoadFromSpecifiedPath(string architecture) DirectoryHelper.DeleteDirectory(tempDir); } } + + [Fact] + public void SetExtensions() + { + var extensions = GlobalSettings.GetExtensions(); + + // Assert that "noop" is supported by default + Assert.Equal(new[] { "noop" }, extensions); + + // Disable "noop" extensions + GlobalSettings.SetExtensions(new[] { "!noop" }); + extensions = GlobalSettings.GetExtensions(); + Assert.Empty(extensions); + + // Enable two new extensions (it will reset the configuration and "noop" will be enabled) + GlobalSettings.SetExtensions(new[] { "partialclone", "newext" }); + extensions = GlobalSettings.GetExtensions(); + Assert.Equal(new[] { "noop", "partialclone", "newext" }, extensions); + } } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 809a77309..a32325c56 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -754,6 +754,14 @@ internal static extern int git_libgit2_opts(int option, // git_libgit2_opts(GIT_OPT_GET_USER_AGENT, git_buf *buf) [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_libgit2_opts(int option, GitBuf buf); + + // git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, const char **extensions, size_t len) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] + internal static extern int git_libgit2_opts(int option, string[] extensions, int len); + + // git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, git_strarray *out) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] + internal static extern int git_libgit2_opts(int option, out GitStrArray extensions); #endregion [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index ca9a69f6d..659138b1f 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3381,6 +3381,18 @@ private enum LibGit2Option GetWindowsSharemode, // GIT_OPT_GET_WINDOWS_SHAREMODE SetWindowsSharemode, // GIT_OPT_SET_WINDOWS_SHAREMODE EnableStrictHashVerification, // GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION + SetAllocator, // GIT_OPT_SET_ALLOCATOR, + EnableUnsavedIndexSafety, // GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY, + GetPackMaxObject, // GIT_OPT_GET_PACK_MAX_OBJECTS, + SetPackMaxObjects, // GIT_OPT_SET_PACK_MAX_OBJECTS, + DisabledPackKeepFileChecks, // GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, + EnableHttpExpectContinue, // GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, + GetMWindowFileLimit, // GIT_OPT_GET_MWINDOW_FILE_LIMIT, + SetMWindowFileLimit, // GIT_OPT_SET_MWINDOW_FILE_LIMIT, + SetOdbPackedPriority, // GIT_OPT_SET_ODB_PACKED_PRIORITY, + SetOdbLoosePriority, // GIT_OPT_SET_ODB_LOOSE_PRIORITY, + GetExtensions, // GIT_OPT_GET_EXTENSIONS, + SetExtensions, // GIT_OPT_SET_EXTENSIONS } /// @@ -3489,6 +3501,29 @@ public static string git_libgit2_opts_get_user_agent() return userAgent; } + public static void git_libgit2_opts_set_extensions(string[] extensions) + { + var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetExtensions, extensions, extensions.Length); + Ensure.ZeroResult(res); + } + + public static string[] git_libgit2_opts_get_extensions() + { + var array = new GitStrArrayNative(); + + try + { + var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetExtensions, out array.Array); + Ensure.ZeroResult(res); + + return array.ReadStrings(); + } + finally + { + array.Dispose(); + } + } + #endregion #region git_worktree_ diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index d24637df0..cb3304c2c 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -383,6 +383,30 @@ public static void SetUserAgent(string userAgent) Proxy.git_libgit2_opts_set_user_agent(userAgent); } + /// + /// Set that the given git extensions are supported by the caller. + /// + /// + /// Extensions supported by libgit2 may be negated by prefixing them with a `!`. For example: setting extensions to { "!noop", "newext" } indicates that the caller does not want + /// to support repositories with the `noop` extension but does want to support repositories with the `newext` extension. + /// + /// Supported extensions + public static void SetExtensions(string[] extensions) + { + Proxy.git_libgit2_opts_set_extensions(extensions); + } + + /// + /// Returns the list of git extensions that are supported. + /// + /// + /// This is the list of built-in extensions supported by libgit2 and custom extensions that have been added with `SetExtensions`. Extensions that have been negated will not be returned. + /// + public static string[] GetExtensions() + { + return Proxy.git_libgit2_opts_get_extensions(); + } + /// /// Gets the user-agent string used by libgit2. /// diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 57c81cdfb..1bbc3073b 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;netcoreapp3.1 From 5b92d55f84db8630cc666b94beccf1f54228e62b Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 12 Sep 2021 10:01:05 +0200 Subject: [PATCH 150/179] Add params keyword --- LibGit2Sharp/GlobalSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index cb3304c2c..f8db7401a 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -391,7 +391,7 @@ public static void SetUserAgent(string userAgent) /// to support repositories with the `noop` extension but does want to support repositories with the `newext` extension. /// /// Supported extensions - public static void SetExtensions(string[] extensions) + public static void SetExtensions(params string[] extensions) { Proxy.git_libgit2_opts_set_extensions(extensions); } From 7f21164d569986fdf1fb198c7162b67cc9e7c491 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 22 Nov 2021 11:14:26 +0100 Subject: [PATCH 151/179] Use GitStrArray --- LibGit2Sharp/Core/NativeMethods.cs | 2 +- LibGit2Sharp/Core/Proxy.cs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index a32325c56..69f58fed3 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -757,7 +757,7 @@ internal static extern int git_libgit2_opts(int option, // git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, const char **extensions, size_t len) [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern int git_libgit2_opts(int option, string[] extensions, int len); + internal static extern int git_libgit2_opts(int option, GitStrArray extensions); // git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, git_strarray *out) [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 659138b1f..921fd7bbc 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3503,8 +3503,11 @@ public static string git_libgit2_opts_get_user_agent() public static void git_libgit2_opts_set_extensions(string[] extensions) { - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetExtensions, extensions, extensions.Length); - Ensure.ZeroResult(res); + using(var array = GitStrArrayManaged.BuildFrom(extensions)) + { + var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetExtensions, array.Array); + Ensure.ZeroResult(res); + } } public static string[] git_libgit2_opts_get_extensions() From 5a515d77b05660fbca56e6f74e6c446aae2b7d8c Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 22 Nov 2021 11:24:47 +0100 Subject: [PATCH 152/179] Attempt to fix memory corruption --- LibGit2Sharp/Core/NativeMethods.cs | 2 +- LibGit2Sharp/Core/Proxy.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 69f58fed3..8c24cff3a 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -757,7 +757,7 @@ internal static extern int git_libgit2_opts(int option, // git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, const char **extensions, size_t len) [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern int git_libgit2_opts(int option, GitStrArray extensions); + internal static extern int git_libgit2_opts(int option, IntPtr extensions, UIntPtr len); // git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, git_strarray *out) [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 921fd7bbc..425bec52a 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3505,7 +3505,7 @@ public static void git_libgit2_opts_set_extensions(string[] extensions) { using(var array = GitStrArrayManaged.BuildFrom(extensions)) { - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetExtensions, array.Array); + var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetExtensions, array.Array.Strings, array.Array.Count); Ensure.ZeroResult(res); } } From 0a2e640f766b947ddc1b617523bcd862c25cb5d3 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 22 Nov 2021 11:34:51 +0100 Subject: [PATCH 153/179] Cosmetic --- LibGit2Sharp/Core/Proxy.cs | 2 +- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 425bec52a..78c8bc914 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3503,7 +3503,7 @@ public static string git_libgit2_opts_get_user_agent() public static void git_libgit2_opts_set_extensions(string[] extensions) { - using(var array = GitStrArrayManaged.BuildFrom(extensions)) + using (var array = GitStrArrayManaged.BuildFrom(extensions)) { var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetExtensions, array.Array.Strings, array.Array.Count); Ensure.ZeroResult(res); diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 1bbc3073b..57c81cdfb 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;netcoreapp3.1 From b05a00f13f416b265903b86a9f38b6cca2e50b54 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 3 Oct 2021 19:23:22 +0200 Subject: [PATCH 154/179] Simplify dealing with missing git objects --- LibGit2Sharp.Tests/BlobFixture.cs | 34 ++++++++++++++++++++ LibGit2Sharp.Tests/TreeFixture.cs | 42 +++++++++++++++++++++++++ LibGit2Sharp/Blob.cs | 19 ++++++++--- LibGit2Sharp/Core/GitObjectLazyGroup.cs | 4 +-- LibGit2Sharp/Core/ObjectSafeWrapper.cs | 12 ++++--- LibGit2Sharp/Core/Proxy.cs | 6 ++-- LibGit2Sharp/GitObject.cs | 18 +++++++---- LibGit2Sharp/Tree.cs | 18 ++++++----- 8 files changed, 126 insertions(+), 27 deletions(-) diff --git a/LibGit2Sharp.Tests/BlobFixture.cs b/LibGit2Sharp.Tests/BlobFixture.cs index 98b30dcfc..ea35e59ef 100644 --- a/LibGit2Sharp.Tests/BlobFixture.cs +++ b/LibGit2Sharp.Tests/BlobFixture.cs @@ -15,6 +15,7 @@ public void CanGetBlobAsText() using (var repo = new Repository(path)) { var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6"); + Assert.False(blob.IsMissing); var text = blob.GetContentText(); @@ -36,6 +37,7 @@ public void CanGetBlobAsFilteredText(string autocrlf, string expectedText) repo.Config.Set("core.autocrlf", autocrlf); var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6"); + Assert.False(blob.IsMissing); var text = blob.GetContentText(new FilteringOptions("foo.txt")); @@ -67,6 +69,7 @@ public void CanGetBlobAsTextWithVariousEncodings(string encodingName, int expect var commit = repo.Commit("bom", Constants.Signature, Constants.Signature); var blob = (Blob)commit.Tree[bomFile].Target; + Assert.False(blob.IsMissing); Assert.Equal(expectedContentBytes, blob.Size); using (var stream = blob.GetContentStream()) { @@ -92,6 +95,7 @@ public void CanGetBlobSize() using (var repo = new Repository(path)) { var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6"); + Assert.False(blob.IsMissing); Assert.Equal(10, blob.Size); } } @@ -104,6 +108,7 @@ public void CanLookUpBlob() { var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6"); Assert.NotNull(blob); + Assert.False(blob.IsMissing); } } @@ -114,6 +119,7 @@ public void CanReadBlobStream() using (var repo = new Repository(path)) { var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6"); + Assert.False(blob.IsMissing); var contentStream = blob.GetContentStream(); Assert.Equal(blob.Size, contentStream.Length); @@ -140,6 +146,7 @@ public void CanReadBlobFilteredStream(string autocrlf, string expectedContent) repo.Config.Set("core.autocrlf", autocrlf); var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6"); + Assert.False(blob.IsMissing); var contentStream = blob.GetContentStream(new FilteringOptions("foo.txt")); Assert.Equal(expectedContent.Length, contentStream.Length); @@ -164,6 +171,7 @@ public void CanReadBlobFilteredStreamOfUnmodifiedBinary() using (var stream = new MemoryStream(binaryContent)) { Blob blob = repo.ObjectDatabase.CreateBlob(stream); + Assert.False(blob.IsMissing); using (var filtered = blob.GetContentStream(new FilteringOptions("foo.txt"))) { @@ -196,6 +204,7 @@ public void CanStageAFileGeneratedFromABlobContentStream() Assert.Equal("baae1fb3760a73481ced1fa03dc15614142c19ef", entry.Id.Sha); var blob = repo.Lookup(entry.Id.Sha); + Assert.False(blob.IsMissing); using (Stream stream = blob.GetContentStream()) using (Stream file = File.OpenWrite(Path.Combine(repo.Info.WorkingDirectory, "small.fromblob.txt"))) @@ -217,10 +226,35 @@ public void CanTellIfTheBlobContentLooksLikeBinary() using (var repo = new Repository(path)) { var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6"); + Assert.False(blob.IsMissing); Assert.False(blob.IsBinary); } } + [Fact] + public void CanTellIfABlobIsMissing() + { + string repoPath = SandboxBareTestRepo(); + + // Manually delete the objects directory to simulate a partial clone + Directory.Delete(Path.Combine(repoPath, "objects", "a8"), true); + + using (var repo = new Repository(repoPath)) + { + // Look up for the tree that reference the blob which is now missing + var tree = repo.Lookup("fd093bff70906175335656e6ce6ae05783708765"); + var blob = (Blob) tree["README"].Target; + + Assert.Equal("a8233120f6ad708f843d861ce2b7228ec4e3dec6", blob.Sha); + Assert.NotNull(blob); + Assert.True(blob.IsMissing); + Assert.Throws(() => blob.Size); + Assert.Throws(() => blob.IsBinary); + Assert.Throws(() => blob.GetContentText()); + Assert.Throws(() => blob.GetContentText(new FilteringOptions("foo.txt"))); + } + } + private static void SkipIfNotSupported(string autocrlf) { InconclusiveIf(() => autocrlf == "true" && Constants.IsRunningOnUnix, "Non-Windows does not support core.autocrlf = true"); diff --git a/LibGit2Sharp.Tests/TreeFixture.cs b/LibGit2Sharp.Tests/TreeFixture.cs index 31ca85c2d..a3a8d89eb 100644 --- a/LibGit2Sharp.Tests/TreeFixture.cs +++ b/LibGit2Sharp.Tests/TreeFixture.cs @@ -17,6 +17,7 @@ public void CanCompareTwoTreeEntries() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); TreeEntry treeEntry1 = tree["README"]; TreeEntry treeEntry2 = tree["README"]; Assert.Equal(treeEntry2, treeEntry1); @@ -31,6 +32,7 @@ public void CanConvertEntryToBlob() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); TreeEntry treeEntry = tree["README"]; var blob = treeEntry.Target as Blob; @@ -45,6 +47,7 @@ public void CanConvertEntryToTree() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); TreeEntry treeEntry = tree["1"]; var subtree = treeEntry.Target as Tree; @@ -59,6 +62,7 @@ public void CanEnumerateBlobs() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); IEnumerable blobs = tree .Where(e => e.TargetType == TreeEntryTargetType.Blob) @@ -76,6 +80,7 @@ public void CanEnumerateSubTrees() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); IEnumerable subTrees = tree .Where(e => e.TargetType == TreeEntryTargetType.Tree) @@ -93,6 +98,7 @@ public void CanEnumerateTreeEntries() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); Assert.Equal(tree.Count, tree.Count()); Assert.Equal(new[] { "1", "README", "branch_file.txt", "new.txt" }, tree.Select(te => te.Name).ToArray()); @@ -106,6 +112,7 @@ public void CanGetEntryByName() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); TreeEntry treeEntry = tree["README"]; Assert.Equal("a8233120f6ad708f843d861ce2b7228ec4e3dec6", treeEntry.Target.Sha); Assert.Equal("README", treeEntry.Name); @@ -119,6 +126,7 @@ public void GettingAnUknownTreeEntryReturnsNull() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); TreeEntry treeEntry = tree["I-do-not-exist"]; Assert.Null(treeEntry); } @@ -131,6 +139,7 @@ public void CanGetEntryCountFromTree() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); Assert.Equal(4, tree.Count); } } @@ -142,6 +151,7 @@ public void CanReadEntryAttributes() using (var repo = new Repository(path)) { var tree = repo.Lookup(sha); + Assert.False(tree.IsMissing); Assert.Equal(Mode.NonExecutableFile, tree["README"].Mode); } } @@ -154,6 +164,7 @@ public void CanReadTheTreeData() { var tree = repo.Lookup(sha); Assert.NotNull(tree); + Assert.False(tree.IsMissing); } } @@ -165,6 +176,7 @@ public void TreeDataIsPresent() { GitObject tree = repo.Lookup(sha); Assert.NotNull(tree); + Assert.False(tree.IsMissing); } } @@ -175,6 +187,7 @@ public void TreeUsesPosixStylePaths() { /* From a commit tree */ var commitTree = repo.Lookup("4c062a6").Tree; + Assert.False(commitTree.IsMissing); Assert.NotNull(commitTree["1/branch_file.txt"]); Assert.Null(commitTree["1\\branch_file.txt"]); } @@ -188,6 +201,7 @@ public void CanRetrieveTreeEntryPath() { /* From a commit tree */ var commitTree = repo.Lookup("4c062a6").Tree; + Assert.False(commitTree.IsMissing); TreeEntry treeTreeEntry = commitTree["1"]; Assert.Equal("1", treeTreeEntry.Path); @@ -201,6 +215,7 @@ public void CanRetrieveTreeEntryPath() // tree but exposes a complete path through its Path property var subTree = treeTreeEntry.Target as Tree; Assert.NotNull(subTree); + Assert.False(subTree.IsMissing); TreeEntry anInstance = subTree["branch_file.txt"]; Assert.NotEqual("branch_file.txt", anInstance.Path); @@ -239,6 +254,7 @@ public void CanParseSymlinkTreeEntries() .Add("A symlink", linkContent, Mode.SymbolicLink); Tree t = repo.ObjectDatabase.CreateTree(td); + Assert.False(t.IsMissing); var te = t["A symlink"]; @@ -248,5 +264,31 @@ public void CanParseSymlinkTreeEntries() Assert.Equal(linkContent, te.Target); } } + + [Fact] + public void CanTellIfATreeIsMissing() + { + var path = SandboxBareTestRepo(); + + // Manually delete the objects directory to simulate a partial clone + Directory.Delete(Path.Combine(path, "objects", "fd"), true); + + using (var repo = new Repository(path)) + { + // Look up for the commit that reference the tree which is now missing + var commit = repo.Lookup("4a202b346bb0fb0db7eff3cffeb3c70babbd2045"); + + Assert.True(commit.Tree.IsMissing); + Assert.Equal("fd093bff70906175335656e6ce6ae05783708765", commit.Tree.Sha); + Assert.Throws(() => commit.Tree.Count); + Assert.Throws(() => commit.Tree.Count()); + Assert.Throws(() => commit.Tree["README"]); + Assert.Throws(() => commit.Tree.ToArray()); + Assert.Throws(() => + { + foreach (var _ in commit.Tree) { } + }); + } + } } } diff --git a/LibGit2Sharp/Blob.cs b/LibGit2Sharp/Blob.cs index 9b14cb50f..d3cccf6ac 100644 --- a/LibGit2Sharp/Blob.cs +++ b/LibGit2Sharp/Blob.cs @@ -8,6 +8,9 @@ namespace LibGit2Sharp /// /// Stores the binary content of a tracked file. /// + /// + /// Since the introduction of partially cloned repositories, blobs might be missing on your local repository (see https://git-scm.com/docs/partial-clone) + /// public class Blob : GitObject { private readonly ILazy lazySize; @@ -22,8 +25,8 @@ protected Blob() internal Blob(Repository repo, ObjectId id) : base(repo, id) { - lazySize = GitObjectLazyGroup.Singleton(repo, id, Proxy.git_blob_rawsize); - lazyIsBinary = GitObjectLazyGroup.Singleton(repo, id, Proxy.git_blob_is_binary); + lazySize = GitObjectLazyGroup.Singleton(repo, id, Proxy.git_blob_rawsize, throwIfMissing: true); + lazyIsBinary = GitObjectLazyGroup.Singleton(repo, id, Proxy.git_blob_is_binary, throwIfMissing: true); } /// @@ -33,16 +36,19 @@ internal Blob(Repository repo, ObjectId id) /// can be used. /// /// - public virtual long Size { get { return lazySize.Value; } } + /// Throws if blob is missing + public virtual long Size => lazySize.Value; /// /// Determine if the blob content is most certainly binary or not. /// - public virtual bool IsBinary { get { return lazyIsBinary.Value; } } + /// Throws if blob is missing + public virtual bool IsBinary => lazyIsBinary.Value; /// /// Gets the blob content in a . /// + /// Throws if blob is missing public virtual Stream GetContentStream() { return Proxy.git_blob_rawcontent_stream(repo.Handle, Id, Size); @@ -53,6 +59,7 @@ public virtual Stream GetContentStream() /// checked out to the working directory. /// Parameter controlling content filtering behavior /// + /// Throws if blob is missing public virtual Stream GetContentStream(FilteringOptions filteringOptions) { Ensure.ArgumentNotNull(filteringOptions, "filteringOptions"); @@ -64,6 +71,7 @@ public virtual Stream GetContentStream(FilteringOptions filteringOptions) /// Gets the blob content, decoded with UTF8 encoding if the encoding cannot be detected from the byte order mark /// /// Blob content as text. + /// Throws if blob is missing public virtual string GetContentText() { return ReadToEnd(GetContentStream(), null); @@ -75,6 +83,7 @@ public virtual string GetContentText() /// /// The encoding of the text to use, if it cannot be detected /// Blob content as text. + /// Throws if blob is missing public virtual string GetContentText(Encoding encoding) { Ensure.ArgumentNotNull(encoding, "encoding"); @@ -87,6 +96,7 @@ public virtual string GetContentText(Encoding encoding) /// /// Parameter controlling content filtering behavior /// Blob content as text. + /// Throws if blob is missing public virtual string GetContentText(FilteringOptions filteringOptions) { return GetContentText(filteringOptions, null); @@ -101,6 +111,7 @@ public virtual string GetContentText(FilteringOptions filteringOptions) /// Parameter controlling content filtering behavior /// The encoding of the text. (default: detected or UTF8) /// Blob content as text. + /// Throws if blob is missing public virtual string GetContentText(FilteringOptions filteringOptions, Encoding encoding) { Ensure.ArgumentNotNull(filteringOptions, "filteringOptions"); diff --git a/LibGit2Sharp/Core/GitObjectLazyGroup.cs b/LibGit2Sharp/Core/GitObjectLazyGroup.cs index 4e0ba384e..11c83a81e 100644 --- a/LibGit2Sharp/Core/GitObjectLazyGroup.cs +++ b/LibGit2Sharp/Core/GitObjectLazyGroup.cs @@ -21,11 +21,11 @@ protected override void EvaluateInternal(Action evaluator) } } - public static ILazy Singleton(Repository repo, ObjectId id, Func resultSelector) + public static ILazy Singleton(Repository repo, ObjectId id, Func resultSelector, bool throwIfMissing = false) { return Singleton(() => { - using (var osw = new ObjectSafeWrapper(id, repo.Handle)) + using (var osw = new ObjectSafeWrapper(id, repo.Handle, throwIfMissing: throwIfMissing)) { return resultSelector(osw.ObjectPtr); } diff --git a/LibGit2Sharp/Core/ObjectSafeWrapper.cs b/LibGit2Sharp/Core/ObjectSafeWrapper.cs index 8bb7e9633..f2ab4a9e1 100644 --- a/LibGit2Sharp/Core/ObjectSafeWrapper.cs +++ b/LibGit2Sharp/Core/ObjectSafeWrapper.cs @@ -7,7 +7,7 @@ internal class ObjectSafeWrapper : IDisposable { private readonly ObjectHandle objectPtr; - public unsafe ObjectSafeWrapper(ObjectId id, RepositoryHandle handle, bool allowNullObjectId = false) + public unsafe ObjectSafeWrapper(ObjectId id, RepositoryHandle handle, bool allowNullObjectId = false, bool throwIfMissing = false) { Ensure.ArgumentNotNull(handle, "handle"); @@ -20,13 +20,15 @@ public unsafe ObjectSafeWrapper(ObjectId id, RepositoryHandle handle, bool allow Ensure.ArgumentNotNull(id, "id"); objectPtr = Proxy.git_object_lookup(handle, id, GitObjectType.Any); } - } - public ObjectHandle ObjectPtr - { - get { return objectPtr; } + if (objectPtr == null && throwIfMissing) + { + throw new NotFoundException($"No valid git object identified by '{id}' exists in the repository."); + } } + public ObjectHandle ObjectPtr => objectPtr; + public void Dispose() { Dispose(true); diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index ca9a69f6d..1e63bef33 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -72,7 +72,7 @@ public static unsafe ObjectId git_blob_create_from_workdir(RepositoryHandle repo public static unsafe UnmanagedMemoryStream git_blob_filtered_content_stream(RepositoryHandle repo, ObjectId id, string path, bool check_for_binary_data) { var buf = new GitBuf(); - var handle = new ObjectSafeWrapper(id, repo).ObjectPtr; + var handle = new ObjectSafeWrapper(id, repo, throwIfMissing: true).ObjectPtr; return new RawContentStream(handle, h => { @@ -85,7 +85,7 @@ public static unsafe UnmanagedMemoryStream git_blob_filtered_content_stream(Repo public static unsafe UnmanagedMemoryStream git_blob_rawcontent_stream(RepositoryHandle repo, ObjectId id, Int64 size) { - var handle = new ObjectSafeWrapper(id, repo).ObjectPtr; + var handle = new ObjectSafeWrapper(id, repo, throwIfMissing: true).ObjectPtr; return new RawContentStream(handle, h => NativeMethods.git_blob_rawcontent(h), h => size); } @@ -3263,7 +3263,7 @@ public static unsafe TreeEntryHandle git_tree_entry_byindex(ObjectHandle tree, l public static unsafe TreeEntryHandle git_tree_entry_bypath(RepositoryHandle repo, ObjectId id, string treeentry_path) { - using (var obj = new ObjectSafeWrapper(id, repo)) + using (var obj = new ObjectSafeWrapper(id, repo, throwIfMissing: true)) { git_tree_entry* treeEntryPtr; int res = NativeMethods.git_tree_entry_bypath(out treeEntryPtr, obj.ObjectPtr, treeentry_path); diff --git a/LibGit2Sharp/GitObject.cs b/LibGit2Sharp/GitObject.cs index 218f8f141..539fe6f8b 100644 --- a/LibGit2Sharp/GitObject.cs +++ b/LibGit2Sharp/GitObject.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp { @@ -33,6 +31,8 @@ public abstract class GitObject : IEquatable, IBelongToARepository private static readonly LambdaEqualityHelper equalityHelper = new LambdaEqualityHelper(x => x.Id); + private readonly ILazy lazyIsMissing; + /// /// The containing the object. /// @@ -53,6 +53,7 @@ protected GitObject(Repository repo, ObjectId id) { this.repo = repo; Id = id; + lazyIsMissing = GitObjectLazyGroup.Singleton(repo, id, handle => handle == null, throwIfMissing: false); } /// @@ -60,13 +61,18 @@ protected GitObject(Repository repo, ObjectId id) /// public virtual ObjectId Id { get; private set; } + /// + /// Determine if the object is missing + /// + /// + /// This is common when dealing with partially cloned repositories as blobs or trees could be missing + /// + public virtual bool IsMissing => lazyIsMissing.Value; + /// /// Gets the 40 character sha1 of this object. /// - public virtual string Sha - { - get { return Id.Sha; } - } + public virtual string Sha => Id.Sha; internal static GitObject BuildFrom(Repository repo, ObjectId id, GitObjectType type, string path) { diff --git a/LibGit2Sharp/Tree.cs b/LibGit2Sharp/Tree.cs index ca7055183..f8494ad8b 100644 --- a/LibGit2Sharp/Tree.cs +++ b/LibGit2Sharp/Tree.cs @@ -13,6 +13,9 @@ namespace LibGit2Sharp /// /// A container which references a list of other s and s. /// + /// + /// Since the introduction of partially cloned repositories, trees might be missing on your local repository (see https://git-scm.com/docs/partial-clone) + /// [DebuggerDisplay("{DebuggerDisplay,nq}")] public class Tree : GitObject, IEnumerable { @@ -31,19 +34,21 @@ internal Tree(Repository repo, ObjectId id, string path) { this.path = path ?? ""; - lazyCount = GitObjectLazyGroup.Singleton(repo, id, Proxy.git_tree_entrycount); + lazyCount = GitObjectLazyGroup.Singleton(repo, id, Proxy.git_tree_entrycount, throwIfMissing: true); } /// /// Gets the number of immediately under this . /// - public virtual int Count { get { return lazyCount.Value; } } + /// Throws if tree is missing + public virtual int Count => lazyCount.Value; /// /// Gets the pointed at by the in this instance. /// /// The relative path to the from this instance. /// null if nothing has been found, the otherwise. + /// Throws if tree is missing public virtual TreeEntry this[string relativePath] { get { return RetrieveFromPath(relativePath); } @@ -69,10 +74,7 @@ private unsafe TreeEntry RetrieveFromPath(string relativePath) } } - internal string Path - { - get { return path; } - } + internal string Path => path; #region IEnumerable Members @@ -103,9 +105,10 @@ internal static string CombinePath(string a, string b) /// Returns an enumerator that iterates through the collection. /// /// An object that can be used to iterate through the collection. + /// Throws if tree is missing public virtual IEnumerator GetEnumerator() { - using (var obj = new ObjectSafeWrapper(Id, repo.Handle)) + using (var obj = new ObjectSafeWrapper(Id, repo.Handle, throwIfMissing: true)) { for (uint i = 0; i < Count; i++) { yield return byIndex(obj, i, Id, repo, path); @@ -117,6 +120,7 @@ public virtual IEnumerator GetEnumerator() /// Returns an enumerator that iterates through the collection. /// /// An object that can be used to iterate through the collection. + /// Throws if tree is missing IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); From 3c4473c4176e5d1b4eb763ded95fa9e3450206a8 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 22 Nov 2021 14:17:45 +0100 Subject: [PATCH 155/179] Update test --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 7a701ab8c..bd9a53d1b 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -93,14 +93,19 @@ public void SetExtensions() Assert.Equal(new[] { "noop" }, extensions); // Disable "noop" extensions - GlobalSettings.SetExtensions(new[] { "!noop" }); + GlobalSettings.SetExtensions("!noop"); extensions = GlobalSettings.GetExtensions(); Assert.Empty(extensions); // Enable two new extensions (it will reset the configuration and "noop" will be enabled) - GlobalSettings.SetExtensions(new[] { "partialclone", "newext" }); + GlobalSettings.SetExtensions("partialclone", "newext"); extensions = GlobalSettings.GetExtensions(); Assert.Equal(new[] { "noop", "partialclone", "newext" }, extensions); + + // You can have multiple times the same extension + GlobalSettings.SetExtensions("noop", "test", "test" ); + extensions = GlobalSettings.GetExtensions(); + Assert.Equal(new[] { "noop", "noop", "test", "test" }, extensions); } } } From 316da3ba9daf21e2aa8af16e9f5693b256220382 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 29 Dec 2021 18:56:11 -0500 Subject: [PATCH 156/179] Formatting tweaks --- LibGit2Sharp/Commands/Checkout.cs | 6 ++++-- LibGit2Sharp/Commands/Remove.cs | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp/Commands/Checkout.cs b/LibGit2Sharp/Commands/Checkout.cs index 17f3c3f9f..46d456be1 100644 --- a/LibGit2Sharp/Commands/Checkout.cs +++ b/LibGit2Sharp/Commands/Checkout.cs @@ -61,12 +61,14 @@ public static Branch Checkout(IRepository repository, string committishOrBranchS { branch = repository.CreateBranch(committishOrBranchSpec, remoteBranches[0].Tip); repository.Branches.Update(branch, b => b.TrackedBranch = remoteBranches[0].CanonicalName); + return Checkout(repository, branch, options); } if (remoteBranches.Count > 1) - throw new AmbiguousSpecificationException( - $"'{committishOrBranchSpec}' matched multiple ({remoteBranches.Count}) remote tracking branches"); + { + throw new AmbiguousSpecificationException($"'{committishOrBranchSpec}' matched multiple ({remoteBranches.Count}) remote tracking branches"); + } throw; } diff --git a/LibGit2Sharp/Commands/Remove.cs b/LibGit2Sharp/Commands/Remove.cs index 939c427d1..f96339c12 100644 --- a/LibGit2Sharp/Commands/Remove.cs +++ b/LibGit2Sharp/Commands/Remove.cs @@ -1,7 +1,6 @@ -using System.Linq; +using System.Collections.Generic; using System.IO; -using System.Collections.Generic; -using LibGit2Sharp; +using System.Linq; using LibGit2Sharp.Core; namespace LibGit2Sharp From 1502b9332525a8047f1340c67cd0e85e1485083c Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 3 Jan 2022 16:15:59 +0100 Subject: [PATCH 157/179] Throw NotFoundException if trees are missing when computing diff --- LibGit2Sharp/Core/Proxy.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 6c6d04670..8991430bd 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -797,8 +797,8 @@ public static unsafe DiffHandle git_diff_tree_to_tree( ObjectId newTree, GitDiffOptions options) { - using (var osw1 = new ObjectSafeWrapper(oldTree, repo, true)) - using (var osw2 = new ObjectSafeWrapper(newTree, repo, true)) + using (var osw1 = new ObjectSafeWrapper(oldTree, repo, true, throwIfMissing: true)) + using (var osw2 = new ObjectSafeWrapper(newTree, repo, true, throwIfMissing: true)) { git_diff* diff; int res = NativeMethods.git_diff_tree_to_tree(out diff, repo, osw1.ObjectPtr, osw2.ObjectPtr, options); From 93d8e453c7f8698cdbdd126da981e64c51689c96 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 3 Jan 2022 18:10:54 +0100 Subject: [PATCH 158/179] Add test --- LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs index d03b26e4e..e2760757b 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs @@ -1256,5 +1256,40 @@ public void UsingPatienceAlgorithmCompareOptionProducesPatienceDiff() Assert.Equal(diffPatience, changes); } } + + [Fact] + public void DiffThrowsANotFoundExceptionIfATreeIsMissing() + { + string repoPath = SandboxBareTestRepo(); + + // Manually delete the objects directory to simulate a partial clone + File.Delete(Path.Combine(repoPath, "objects", "58", "1f9824ecaf824221bd36edf5430f2739a7c4f5")); + + using (var repo = new Repository(repoPath)) + { + // The commit is there but its tree is missing + var commit = repo.Lookup("4c062a6361ae6959e06292c1fa5e2822d9c96345"); + Assert.NotNull(commit); + Assert.Equal("581f9824ecaf824221bd36edf5430f2739a7c4f5", commit.Tree.Sha); + Assert.True(commit.Tree.IsMissing); + + var tree = repo.Lookup("581f9824ecaf824221bd36edf5430f2739a7c4f5"); + Assert.Null(tree); + + var otherCommit = repo.Lookup("be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + Assert.NotNull(otherCommit); + Assert.False(otherCommit.Tree.IsMissing); + + Assert.Throws(() => + { + using (repo.Diff.Compare(commit.Tree, otherCommit.Tree)) {} + }); + + Assert.Throws(() => + { + using (repo.Diff.Compare(otherCommit.Tree, commit.Tree)) {} + }); + } + } } } From 9780ddf9450ef6c740bce21a20d8e0765116fcbe Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 3 Jan 2022 19:40:27 +0100 Subject: [PATCH 159/179] Fix comment --- LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs index e2760757b..0fe7adee1 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs @@ -1262,7 +1262,7 @@ public void DiffThrowsANotFoundExceptionIfATreeIsMissing() { string repoPath = SandboxBareTestRepo(); - // Manually delete the objects directory to simulate a partial clone + // Manually delete the tree object to simulate a partial clone File.Delete(Path.Combine(repoPath, "objects", "58", "1f9824ecaf824221bd36edf5430f2739a7c4f5")); using (var repo = new Repository(repoPath)) From 6490ff1e57872c7f38de58fec4849fb88ee38b07 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 1 Apr 2022 16:43:20 -0400 Subject: [PATCH 160/179] Remove git protocol from test data --- LibGit2Sharp.Tests/CloneFixture.cs | 10 +++------- LibGit2Sharp.Tests/FetchFixture.cs | 10 ++++------ LibGit2Sharp.Tests/NetworkFixture.cs | 13 +++++-------- LibGit2Sharp.Tests/RepositoryFixture.cs | 2 -- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 0fefabbf6..295fc383e 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -13,8 +13,6 @@ public class CloneFixture : BaseFixture [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - [InlineData("git://github.com/libgit2/TestGitRepository")] - //[InlineData("git@github.com:libgit2/TestGitRepository")] public void CanClone(string url) { var scd = BuildSelfCleaningDirectory(); @@ -102,8 +100,6 @@ public void CanCloneALocalRepositoryFromANewlyCreatedTemporaryPath() [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - [InlineData("git://github.com/libgit2/TestGitRepository")] - //[InlineData("git@github.com:libgit2/TestGitRepository")] public void CanCloneBarely(string url) { var scd = BuildSelfCleaningDirectory(); @@ -126,7 +122,7 @@ public void CanCloneBarely(string url) } [Theory] - [InlineData("git://github.com/libgit2/TestGitRepository")] + [InlineData("https://github.com/libgit2/TestGitRepository")] public void WontCheckoutIfAskedNotTo(string url) { var scd = BuildSelfCleaningDirectory(); @@ -143,7 +139,7 @@ public void WontCheckoutIfAskedNotTo(string url) } [Theory] - [InlineData("git://github.com/libgit2/TestGitRepository")] + [InlineData("https://github.com/libgit2/TestGitRepository")] public void CallsProgressCallbacks(string url) { bool transferWasCalled = false; @@ -301,7 +297,7 @@ public void CanInspectCertificateOnClone(string url, string hostname, Type certT } [Theory] - [InlineData("git://github.com/libgit2/TestGitRepository")] + [InlineData("https://github.com/libgit2/TestGitRepository")] public void CloningWithoutWorkdirPathThrows(string url) { Assert.Throws(() => Repository.Clone(url, null)); diff --git a/LibGit2Sharp.Tests/FetchFixture.cs b/LibGit2Sharp.Tests/FetchFixture.cs index 01c71ebfe..c0c6f0478 100644 --- a/LibGit2Sharp.Tests/FetchFixture.cs +++ b/LibGit2Sharp.Tests/FetchFixture.cs @@ -4,7 +4,6 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -15,7 +14,6 @@ public class FetchFixture : BaseFixture [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - [InlineData("git://github.com/libgit2/TestGitRepository.git")] public void CanFetchIntoAnEmptyRepository(string url) { string path = InitNewRepository(); @@ -74,7 +72,6 @@ public void CanFetchIntoAnEmptyRepositoryWithCredentials() [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - [InlineData("git://github.com/libgit2/TestGitRepository.git")] public void CanFetchAllTagsIntoAnEmptyRepository(string url) { string path = InitNewRepository(); @@ -101,7 +98,8 @@ public void CanFetchAllTagsIntoAnEmptyRepository(string url) } // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { + Commands.Fetch(repo, remoteName, new string[0], new FetchOptions + { TagFetchMode = TagFetchMode.All, OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null); @@ -117,7 +115,6 @@ public void CanFetchAllTagsIntoAnEmptyRepository(string url) [Theory] [InlineData("http://github.com/libgit2/TestGitRepository", "test-branch", "master")] [InlineData("https://github.com/libgit2/TestGitRepository", "master", "master")] - [InlineData("git://github.com/libgit2/TestGitRepository.git", "master", "first-merge")] public void CanFetchCustomRefSpecsIntoAnEmptyRepository(string url, string localBranchName, string remoteBranchName) { string path = InitNewRepository(); @@ -147,7 +144,8 @@ public void CanFetchCustomRefSpecsIntoAnEmptyRepository(string url, string local } // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[] { refSpec }, new FetchOptions { + Commands.Fetch(repo, remoteName, new string[] { refSpec }, new FetchOptions + { TagFetchMode = TagFetchMode.None, OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null); diff --git a/LibGit2Sharp.Tests/NetworkFixture.cs b/LibGit2Sharp.Tests/NetworkFixture.cs index 3ac73a2e8..3a3517432 100644 --- a/LibGit2Sharp.Tests/NetworkFixture.cs +++ b/LibGit2Sharp.Tests/NetworkFixture.cs @@ -3,7 +3,6 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -12,7 +11,6 @@ public class NetworkFixture : BaseFixture [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - [InlineData("git://github.com/libgit2/TestGitRepository.git")] public void CanListRemoteReferences(string url) { string remoteName = "testRemote"; @@ -49,7 +47,6 @@ public void CanListRemoteReferences(string url) [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - [InlineData("git://github.com/libgit2/TestGitRepository.git")] public void CanListRemoteReferencesFromUrl(string url) { string repoPath = InitNewRepository(); @@ -94,9 +91,9 @@ public void CanListRemoteReferenceObjects() Remote remote = repo.Network.Remotes[remoteName]; IEnumerable references = repo.Network.ListReferences(remote).ToList(); - var actualRefs = new List>(); + var actualRefs = new List>(); - foreach(Reference reference in references) + foreach (Reference reference in references) { Assert.NotNull(reference.CanonicalName); @@ -166,7 +163,7 @@ public void CanPull(FastForwardStrategy fastForwardStrategy) MergeResult mergeResult = Commands.Pull(repo, Constants.Signature, pullOptions); - if(fastForwardStrategy == FastForwardStrategy.Default || fastForwardStrategy == FastForwardStrategy.FastForwardOnly) + if (fastForwardStrategy == FastForwardStrategy.Default || fastForwardStrategy == FastForwardStrategy.FastForwardOnly) { Assert.Equal(MergeStatus.FastForward, mergeResult.Status); Assert.Equal(mergeResult.Commit, repo.Branches["refs/remotes/origin/master"].Tip); @@ -226,7 +223,7 @@ public void PullWithoutMergeBranchThrows() { Commands.Pull(repo, Constants.Signature, new PullOptions()); } - catch(MergeFetchHeadNotFoundException ex) + catch (MergeFetchHeadNotFoundException ex) { didPullThrow = true; thrownException = ex; @@ -293,7 +290,7 @@ public void CanPruneRefs() Assert.NotNull(repo.Refs["refs/remotes/pruner/master"]); // but we do when asked by the user - Commands.Fetch(repo, "pruner", new string[0], new FetchOptions { Prune = true}, null); + Commands.Fetch(repo, "pruner", new string[0], new FetchOptions { Prune = true }, null); Assert.Null(repo.Refs["refs/remotes/pruner/master"]); } } diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs index 5c551fabd..bf27b6091 100644 --- a/LibGit2Sharp.Tests/RepositoryFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryFixture.cs @@ -4,7 +4,6 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -709,7 +708,6 @@ public void CanListRemoteReferencesWithCredentials() [Theory] [InlineData("http://github.com/libgit2/TestGitRepository")] [InlineData("https://github.com/libgit2/TestGitRepository")] - [InlineData("git://github.com/libgit2/TestGitRepository.git")] public void CanListRemoteReferences(string url) { IEnumerable references = Repository.ListRemoteReferences(url).ToList(); From 4731263c2e1e83b75eb5b278318cc58d32290b6a Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 1 Apr 2022 16:59:12 -0400 Subject: [PATCH 161/179] Comment out Bitbucket tests --- LibGit2Sharp.Tests/CloneFixture.cs | 46 ++++---- .../desktop/SmartSubtransportFixture.cs | 106 +++++++++--------- 2 files changed, 75 insertions(+), 77 deletions(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 295fc383e..1b26c1226 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -208,29 +208,29 @@ static Credentials CreateUsernamePasswordCredentials(string user, string pass, b }; } - [Theory] - [InlineData("https://libgit2@bitbucket.org/libgit2/testgitrepository.git", "libgit3", "libgit3", true)] - [InlineData("https://libgit2@bitbucket.org/libgit2/testgitrepository.git", "libgit3", "libgit3", false)] - public void CanCloneFromBBWithCredentials(string url, string user, string pass, bool secure) - { - var scd = BuildSelfCleaningDirectory(); - - string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions() - { - CredentialsProvider = (_url, _user, _cred) => CreateUsernamePasswordCredentials(user, pass, secure) - }); - - using (var repo = new Repository(clonedRepoPath)) - { - string dir = repo.Info.Path; - Assert.True(Path.IsPathRooted(dir)); - Assert.True(Directory.Exists(dir)); - - Assert.NotNull(repo.Info.WorkingDirectory); - Assert.Equal(Path.Combine(scd.RootedDirectoryPath, ".git" + Path.DirectorySeparatorChar), repo.Info.Path); - Assert.False(repo.Info.IsBare); - } - } + //[Theory] + //[InlineData("https://libgit2@bitbucket.org/libgit2/testgitrepository.git", "libgit3", "libgit3", true)] + //[InlineData("https://libgit2@bitbucket.org/libgit2/testgitrepository.git", "libgit3", "libgit3", false)] + //public void CanCloneFromBBWithCredentials(string url, string user, string pass, bool secure) + //{ + // var scd = BuildSelfCleaningDirectory(); + + // string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions() + // { + // CredentialsProvider = (_url, _user, _cred) => CreateUsernamePasswordCredentials(user, pass, secure) + // }); + + // using (var repo = new Repository(clonedRepoPath)) + // { + // string dir = repo.Info.Path; + // Assert.True(Path.IsPathRooted(dir)); + // Assert.True(Directory.Exists(dir)); + + // Assert.NotNull(repo.Info.WorkingDirectory); + // Assert.Equal(Path.Combine(scd.RootedDirectoryPath, ".git" + Path.DirectorySeparatorChar), repo.Info.Path); + // Assert.False(repo.Info.IsBare); + // } + //} [SkippableTheory] [InlineData("https://github.com/libgit2/TestGitRepository.git", "github.com", typeof(CertificateX509))] diff --git a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs index e72c0d7c1..ff4d0fcd6 100644 --- a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs +++ b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs @@ -4,9 +4,7 @@ using System.Net; using System.Net.Security; using LibGit2Sharp.Tests.TestHelpers; -using LibGit2Sharp.Core; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -79,58 +77,58 @@ public void CustomSmartSubtransportTest(string scheme, string url) } } - [Theory] - [InlineData("https", "https://bitbucket.org/libgit2/testgitrepository.git", "libgit3", "libgit3")] - public void CanUseCredentials(string scheme, string url, string user, string pass) - { - string remoteName = "testRemote"; - - var scd = BuildSelfCleaningDirectory(); - Repository.Init(scd.RootedDirectoryPath); - - SmartSubtransportRegistration registration = null; - - try - { - // Disable server certificate validation for testing. - // Do *NOT* enable this in production. - ServicePointManager.ServerCertificateValidationCallback = certificateValidationCallback; - - registration = GlobalSettings.RegisterSmartSubtransport(scheme); - Assert.NotNull(registration); - - using (var repo = new Repository(scd.DirectoryPath)) - { - repo.Network.Remotes.Add(remoteName, url); - - // Set up structures for the expected results - // and verifying the RemoteUpdateTips callback. - TestRemoteInfo expectedResults = TestRemoteInfo.TestRemoteInstance; - ExpectedFetchState expectedFetchState = new ExpectedFetchState(remoteName); - - // Add expected branch objects - foreach (KeyValuePair kvp in expectedResults.BranchTips) - { - expectedFetchState.AddExpectedBranch(kvp.Key, ObjectId.Zero, kvp.Value); - } - - // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { - OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler, TagFetchMode = TagFetchMode.Auto, - CredentialsProvider = (_user, _valid, _hostname) => new UsernamePasswordCredentials() { Username = user, Password = pass }, - }, null); - - // Verify the expected - expectedFetchState.CheckUpdatedReferences(repo); - } - } - finally - { - GlobalSettings.UnregisterSmartSubtransport(registration); - - ServicePointManager.ServerCertificateValidationCallback -= certificateValidationCallback; - } - } + //[Theory] + //[InlineData("https", "https://bitbucket.org/libgit2/testgitrepository.git", "libgit3", "libgit3")] + //public void CanUseCredentials(string scheme, string url, string user, string pass) + //{ + // string remoteName = "testRemote"; + + // var scd = BuildSelfCleaningDirectory(); + // Repository.Init(scd.RootedDirectoryPath); + + // SmartSubtransportRegistration registration = null; + + // try + // { + // // Disable server certificate validation for testing. + // // Do *NOT* enable this in production. + // ServicePointManager.ServerCertificateValidationCallback = certificateValidationCallback; + + // registration = GlobalSettings.RegisterSmartSubtransport(scheme); + // Assert.NotNull(registration); + + // using (var repo = new Repository(scd.DirectoryPath)) + // { + // repo.Network.Remotes.Add(remoteName, url); + + // // Set up structures for the expected results + // // and verifying the RemoteUpdateTips callback. + // TestRemoteInfo expectedResults = TestRemoteInfo.TestRemoteInstance; + // ExpectedFetchState expectedFetchState = new ExpectedFetchState(remoteName); + + // // Add expected branch objects + // foreach (KeyValuePair kvp in expectedResults.BranchTips) + // { + // expectedFetchState.AddExpectedBranch(kvp.Key, ObjectId.Zero, kvp.Value); + // } + + // // Perform the actual fetch + // Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { + // OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler, TagFetchMode = TagFetchMode.Auto, + // CredentialsProvider = (_user, _valid, _hostname) => new UsernamePasswordCredentials() { Username = user, Password = pass }, + // }, null); + + // // Verify the expected + // expectedFetchState.CheckUpdatedReferences(repo); + // } + // } + // finally + // { + // GlobalSettings.UnregisterSmartSubtransport(registration); + + // ServicePointManager.ServerCertificateValidationCallback -= certificateValidationCallback; + // } + //} [Fact] public void CannotReregisterScheme() From 5e78b8211b4bac24e9c94186bb46caff8687ef9f Mon Sep 17 00:00:00 2001 From: Filip Rindler Date: Fri, 1 Apr 2022 18:21:22 +0100 Subject: [PATCH 162/179] Fixed calling into native libgit2 on osx-arm64 (git_libgit2_opts variadic parameters) --- LibGit2Sharp/Core/NativeMethods.cs | 36 +++++++++++++++++ LibGit2Sharp/Core/Proxy.cs | 62 +++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 10 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 8c24cff3a..f5d45f3cf 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -764,6 +764,42 @@ internal static extern int git_libgit2_opts(int option, internal static extern int git_libgit2_opts(int option, out GitStrArray extensions); #endregion + #region git_libgit2_opts_osxarm64 + + // For RID osx-arm64 the calling convention is different: we need to pad out to 8 arguments before varargs + // (see discussion at https://github.com/dotnet/runtime/issues/48796) + + // git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, int level, git_buf *buf) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, IntPtr nop3, IntPtr nop4, IntPtr nop5, IntPtr nop6, IntPtr nop7, IntPtr nop8, uint level, GitBuf buf); + + // git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, int level, const char *path) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, IntPtr nop3, IntPtr nop4, IntPtr nop5, IntPtr nop6, IntPtr nop7, IntPtr nop8, uint level, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); + + // git_libgit2_opts(GIT_OPT_ENABLE_*, int enabled) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, IntPtr nop3, IntPtr nop4, IntPtr nop5, IntPtr nop6, IntPtr nop7, IntPtr nop8, int enabled); + + // git_libgit2_opts(GIT_OPT_SET_USER_AGENT, const char *path) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, IntPtr nop3, IntPtr nop4, IntPtr nop5, IntPtr nop6, IntPtr nop7, IntPtr nop8, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); + + // git_libgit2_opts(GIT_OPT_GET_USER_AGENT, git_buf *buf) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, IntPtr nop3, IntPtr nop4, IntPtr nop5, IntPtr nop6, IntPtr nop7, IntPtr nop8, GitBuf buf); + + // git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, const char **extensions, size_t len) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, IntPtr nop3, IntPtr nop4, IntPtr nop5, IntPtr nop6, IntPtr nop7, IntPtr nop8, IntPtr extensions, UIntPtr len); + + // git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, git_strarray *out) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, IntPtr nop3, IntPtr nop4, IntPtr nop5, IntPtr nop6, IntPtr nop7, IntPtr nop8, out GitStrArray extensions); + #endregion + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_graph_ahead_behind(out UIntPtr ahead, out UIntPtr behind, git_repository* repo, ref GitOid one, ref GitOid two); diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 8991430bd..cd32050c4 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -14,6 +14,9 @@ namespace LibGit2Sharp.Core { internal class Proxy { + internal static readonly bool isOSXArm64 = RuntimeInformation.ProcessArchitecture == Architecture.Arm64 + && RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + #region git_blame_ public static unsafe BlameHandle git_blame_file( @@ -3408,7 +3411,11 @@ public static string git_libgit2_opts_get_search_path(ConfigurationLevel level) using (var buf = new GitBuf()) { - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetSearchPath, (uint)level, buf); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.GetSearchPath, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)level, buf); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetSearchPath, (uint)level, buf); Ensure.ZeroResult(res); path = LaxUtf8Marshaler.FromNative(buf.ptr) ?? string.Empty; @@ -3419,7 +3426,10 @@ public static string git_libgit2_opts_get_search_path(ConfigurationLevel level) public static void git_libgit2_opts_enable_strict_hash_verification(bool enabled) { - NativeMethods.git_libgit2_opts((int)LibGit2Option.EnableStrictHashVerification, enabled ? 1 : 0); + if (isOSXArm64) + NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.EnableStrictHashVerification, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, enabled ? 1 : 0); + else + NativeMethods.git_libgit2_opts((int)LibGit2Option.EnableStrictHashVerification, enabled ? 1 : 0); } /// @@ -3432,7 +3442,11 @@ public static void git_libgit2_opts_enable_strict_hash_verification(bool enabled /// public static void git_libgit2_opts_set_search_path(ConfigurationLevel level, string path) { - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetSearchPath, (uint)level, path); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.SetSearchPath, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)level, path); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetSearchPath, (uint)level, path); Ensure.ZeroResult(res); } @@ -3443,7 +3457,11 @@ public static void git_libgit2_opts_set_search_path(ConfigurationLevel level, st public static void git_libgit2_opts_set_enable_caching(bool enabled) { // libgit2 expects non-zero value for true - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.EnableCaching, enabled ? 1 : 0); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.EnableCaching, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, enabled ? 1 : 0); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.EnableCaching, enabled ? 1 : 0); Ensure.ZeroResult(res); } @@ -3454,7 +3472,11 @@ public static void git_libgit2_opts_set_enable_caching(bool enabled) public static void git_libgit2_opts_set_enable_ofsdelta(bool enabled) { // libgit2 expects non-zero value for true - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.EnableOfsDelta, enabled ? 1 : 0); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.EnableOfsDelta, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, enabled ? 1 : 0); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.EnableOfsDelta, enabled ? 1 : 0); Ensure.ZeroResult(res); } @@ -3465,7 +3487,11 @@ public static void git_libgit2_opts_set_enable_ofsdelta(bool enabled) public static void git_libgit2_opts_set_enable_strictobjectcreation(bool enabled) { // libgit2 expects non-zero value for true - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.EnableStrictObjectCreation, enabled ? 1 : 0); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.EnableStrictObjectCreation, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, enabled ? 1 : 0); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.EnableStrictObjectCreation, enabled ? 1 : 0); Ensure.ZeroResult(res); } @@ -3476,7 +3502,11 @@ public static void git_libgit2_opts_set_enable_strictobjectcreation(bool enabled /// The user-agent string to use public static void git_libgit2_opts_set_user_agent(string userAgent) { - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetUserAgent, userAgent); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.SetUserAgent, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, userAgent); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetUserAgent, userAgent); Ensure.ZeroResult(res); } @@ -3492,7 +3522,11 @@ public static string git_libgit2_opts_get_user_agent() using (var buf = new GitBuf()) { - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetUserAgent, buf); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.GetUserAgent, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, buf); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetUserAgent, buf); Ensure.ZeroResult(res); userAgent = LaxUtf8Marshaler.FromNative(buf.ptr) ?? string.Empty; @@ -3505,7 +3539,11 @@ public static void git_libgit2_opts_set_extensions(string[] extensions) { using (var array = GitStrArrayManaged.BuildFrom(extensions)) { - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetExtensions, array.Array.Strings, array.Array.Count); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.SetExtensions, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, array.Array.Strings, array.Array.Count); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.SetExtensions, array.Array.Strings, array.Array.Count); Ensure.ZeroResult(res); } } @@ -3516,7 +3554,11 @@ public static string[] git_libgit2_opts_get_extensions() try { - var res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetExtensions, out array.Array); + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.GetExtensions, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, out array.Array); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetExtensions, out array.Array); Ensure.ZeroResult(res); return array.ReadStrings(); From a642baea52a5ac652d5248b4e9f064bf1b527dd7 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 2 Apr 2022 15:55:08 -0400 Subject: [PATCH 163/179] Stop testing .NET 5 --- .github/workflows/ci.yml | 11 ++--------- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f7351f39..118649aa2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: matrix: arch: [ amd64 ] os: [windows-2019, macos-10.15] - tfm: [ net472, netcoreapp3.1, net5.0, net6.0 ] + tfm: [ net472, netcoreapp3.1, net6.0 ] exclude: - os: macos-10.15 tfm: net472 @@ -51,11 +51,6 @@ jobs: uses: actions/setup-dotnet@v1.8.1 with: dotnet-version: 6.0.x - - name: Install .NET 5 runtime - if: matrix.tfm == 'net5.0' - uses: actions/setup-dotnet@v1.8.1 - with: - dotnet-version: 5.0.x - name: Install .NET Core 3.1 runtime if: matrix.tfm == 'netcoreapp3.1' uses: actions/setup-dotnet@v1.8.1 @@ -71,7 +66,7 @@ jobs: arch: [ amd64 ] # arch: [ amd64, arm64 ] distro: [ alpine.3.12, alpine.3.13, alpine.3.14, centos.7, centos.8, debian.9, debian.10, debian.11, fedora.33, ubuntu.18.04, ubuntu.20.04 ] - sdk: [ '6.0', '5.0', '3.1' ] + sdk: [ '6.0', '3.1' ] exclude: - arch: arm64 distro: alpine.3.12 @@ -86,8 +81,6 @@ jobs: include: - sdk: '6.0' tfm: net6.0 - - sdk: '5.0' - tfm: net5.0 - sdk: '3.1' tfm: netcoreapp3.1 fail-fast: false diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 6ddcfbd05..25e652522 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net472;netcoreapp3.1;net5.0;net6.0 + net472;netcoreapp3.1;net6.0 From 70d62d5adf6ac951d756d115c6b34b719947a83a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 23 Feb 2023 11:33:36 -0800 Subject: [PATCH 164/179] LibGit2Sharp: update to libgit2 v1.6.2 --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 11 +++----- LibGit2Sharp/Core/GitFetchOptions.cs | 1 + LibGit2Sharp/Core/GitOdbBackend.cs | 6 ++--- LibGit2Sharp/Core/GitPushOptions.cs | 1 + LibGit2Sharp/Core/GitWorktree.cs | 2 ++ LibGit2Sharp/LibGit2Sharp.csproj | 2 +- LibGit2Sharp/RemoteRedirectMode.cs | 28 +++++++++++++++++++++ 7 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 LibGit2Sharp/RemoteRedirectMode.cs diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index bd9a53d1b..e067fd192 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -90,22 +90,17 @@ public void SetExtensions() var extensions = GlobalSettings.GetExtensions(); // Assert that "noop" is supported by default - Assert.Equal(new[] { "noop" }, extensions); + Assert.Equal(new[] { "noop", "objectformat" }, extensions); // Disable "noop" extensions GlobalSettings.SetExtensions("!noop"); extensions = GlobalSettings.GetExtensions(); - Assert.Empty(extensions); + Assert.Equal(new[] { "objectformat" }, extensions); // Enable two new extensions (it will reset the configuration and "noop" will be enabled) GlobalSettings.SetExtensions("partialclone", "newext"); extensions = GlobalSettings.GetExtensions(); - Assert.Equal(new[] { "noop", "partialclone", "newext" }, extensions); - - // You can have multiple times the same extension - GlobalSettings.SetExtensions("noop", "test", "test" ); - extensions = GlobalSettings.GetExtensions(); - Assert.Equal(new[] { "noop", "noop", "test", "test" }, extensions); + Assert.Equal(new[] { "noop", "objectformat", "partialclone", "newext" }, extensions); } } } diff --git a/LibGit2Sharp/Core/GitFetchOptions.cs b/LibGit2Sharp/Core/GitFetchOptions.cs index 3f0baa2c2..bdf8aa585 100644 --- a/LibGit2Sharp/Core/GitFetchOptions.cs +++ b/LibGit2Sharp/Core/GitFetchOptions.cs @@ -11,6 +11,7 @@ internal class GitFetchOptions public bool UpdateFetchHead = true; public TagFetchMode download_tags; public GitProxyOptions ProxyOptions; + public RemoteRedirectMode FollowRedirects = RemoteRedirectMode.Auto; public GitStrArrayManaged CustomHeaders; } } diff --git a/LibGit2Sharp/Core/GitOdbBackend.cs b/LibGit2Sharp/Core/GitOdbBackend.cs index 3ff031048..6f017542d 100644 --- a/LibGit2Sharp/Core/GitOdbBackend.cs +++ b/LibGit2Sharp/Core/GitOdbBackend.cs @@ -33,10 +33,8 @@ static GitOdbBackend() public exists_prefix_callback ExistsPrefix; public IntPtr Refresh; public foreach_callback Foreach; - - private IntPtr Padding; // TODO: add writemidx - - public IntPtr Writepack; + public IntPtr WritePack; + public IntPtr WriteMidx; public IntPtr Freshen; public free_callback Free; diff --git a/LibGit2Sharp/Core/GitPushOptions.cs b/LibGit2Sharp/Core/GitPushOptions.cs index f733534d2..8c98ce9cc 100644 --- a/LibGit2Sharp/Core/GitPushOptions.cs +++ b/LibGit2Sharp/Core/GitPushOptions.cs @@ -9,6 +9,7 @@ internal class GitPushOptions public int PackbuilderDegreeOfParallelism; public GitRemoteCallbacks RemoteCallbacks; public GitProxyOptions ProxyOptions; + public RemoteRedirectMode FollowRedirects = RemoteRedirectMode.Auto; public GitStrArrayManaged CustomHeaders; } } diff --git a/LibGit2Sharp/Core/GitWorktree.cs b/LibGit2Sharp/Core/GitWorktree.cs index c71cb16c0..b3200dd91 100644 --- a/LibGit2Sharp/Core/GitWorktree.cs +++ b/LibGit2Sharp/Core/GitWorktree.cs @@ -37,6 +37,8 @@ internal class git_worktree_add_options public int locked; public IntPtr @ref = IntPtr.Zero; + + public GitCheckoutOpts checkoutOpts = new GitCheckoutOpts { version = 1 }; } [StructLayout(LayoutKind.Sequential)] diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 57c81cdfb..03025744f 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -30,7 +30,7 @@ - + diff --git a/LibGit2Sharp/RemoteRedirectMode.cs b/LibGit2Sharp/RemoteRedirectMode.cs new file mode 100644 index 000000000..08866e68a --- /dev/null +++ b/LibGit2Sharp/RemoteRedirectMode.cs @@ -0,0 +1,28 @@ +namespace LibGit2Sharp +{ + /// + /// Remote redirection settings; wehther redirects to another + /// host are permitted. By default, git will follow a redirect + /// on the initial request (`/info/refs`) but not subsequent + /// requests. + /// + public enum RemoteRedirectMode + { + /// + /// Do not follow any off-site redirects at any stage of + /// the fetch or push. + /// + None = 0, // GIT_REMOTE_REDIRECT_NONE + + /// + /// Allow off-site redirects only upon the initial + /// request. This is the default. + /// + Auto, // GIT_REMOTE_REDIRECT_INITIAL + + /// + /// Allow redirects at any stage in the fetch or push. + /// + All // GIT_REMOTE_REDIRECT_ALL + } +} From d0d80290360d9400aafc5814ea78ed5050853b48 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 7 Apr 2023 17:13:35 -0400 Subject: [PATCH 165/179] Update LibGit2Sharp.NativeBinaries to 2.0.319 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 03025744f..c81dd7093 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -30,7 +30,7 @@ - + From 1be14ba9a39bffca8b6a272ba780a7b1bdf1119d Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 7 Apr 2023 17:33:44 -0400 Subject: [PATCH 166/179] Update action versions --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 118649aa2..ac62110ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,17 +15,17 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.5.0 with: fetch-depth: 0 - name: Install .NET SDK - uses: actions/setup-dotnet@v1.8.1 + uses: actions/setup-dotnet@v3.0.3 with: dotnet-version: 6.0.x - name: Build run: dotnet build LibGit2Sharp.sln --configuration Release - name: Upload packages - uses: actions/upload-artifact@v2.2.4 + uses: actions/upload-artifact@v3.1.2 with: name: NuGet packages path: bin/Packages/ @@ -44,16 +44,16 @@ jobs: fail-fast: false steps: - name: Checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.5.0 with: fetch-depth: 0 - name: Install .NET SDK - uses: actions/setup-dotnet@v1.8.1 + uses: actions/setup-dotnet@v3.0.3 with: dotnet-version: 6.0.x - name: Install .NET Core 3.1 runtime if: matrix.tfm == 'netcoreapp3.1' - uses: actions/setup-dotnet@v1.8.1 + uses: actions/setup-dotnet@v3.0.3 with: dotnet-version: 3.1.x - name: Run ${{ matrix.tfm }} tests @@ -86,7 +86,7 @@ jobs: fail-fast: false steps: - name: Checkout - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v3.5.0 with: fetch-depth: 0 - name: Setup QEMU From b5bb4d5b168e325cd99539acc5143098a2dbf0e7 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 7 Apr 2023 17:45:09 -0400 Subject: [PATCH 167/179] Add .NET 7 and remove .NET Core 3.1 --- .github/workflows/ci.yml | 21 +++++++++----------- LibGit2Sharp.Tests/BlobFixture.cs | 6 +++--- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac62110ec..878d9ecd1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - name: Install .NET SDK uses: actions/setup-dotnet@v3.0.3 with: - dotnet-version: 6.0.x + dotnet-version: 7.0.x - name: Build run: dotnet build LibGit2Sharp.sln --configuration Release - name: Upload packages @@ -36,8 +36,8 @@ jobs: strategy: matrix: arch: [ amd64 ] - os: [windows-2019, macos-10.15] - tfm: [ net472, netcoreapp3.1, net6.0 ] + os: [ windows-2019, macos-10.15 ] + tfm: [ net472, net6.0, net7.0 ] exclude: - os: macos-10.15 tfm: net472 @@ -50,12 +50,9 @@ jobs: - name: Install .NET SDK uses: actions/setup-dotnet@v3.0.3 with: - dotnet-version: 6.0.x - - name: Install .NET Core 3.1 runtime - if: matrix.tfm == 'netcoreapp3.1' - uses: actions/setup-dotnet@v3.0.3 - with: - dotnet-version: 3.1.x + dotnet-version: | + 7.0.x + 6.0.x - name: Run ${{ matrix.tfm }} tests run: dotnet test LibGit2Sharp.sln --configuration Release --framework ${{ matrix.tfm }} --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING test-linux: @@ -66,7 +63,7 @@ jobs: arch: [ amd64 ] # arch: [ amd64, arm64 ] distro: [ alpine.3.12, alpine.3.13, alpine.3.14, centos.7, centos.8, debian.9, debian.10, debian.11, fedora.33, ubuntu.18.04, ubuntu.20.04 ] - sdk: [ '6.0', '3.1' ] + sdk: [ '6.0', '7.0' ] exclude: - arch: arm64 distro: alpine.3.12 @@ -81,8 +78,8 @@ jobs: include: - sdk: '6.0' tfm: net6.0 - - sdk: '3.1' - tfm: netcoreapp3.1 + - sdk: '7.0' + tfm: net7.0 fail-fast: false steps: - name: Checkout diff --git a/LibGit2Sharp.Tests/BlobFixture.cs b/LibGit2Sharp.Tests/BlobFixture.cs index ea35e59ef..314dea379 100644 --- a/LibGit2Sharp.Tests/BlobFixture.cs +++ b/LibGit2Sharp.Tests/BlobFixture.cs @@ -45,7 +45,7 @@ public void CanGetBlobAsFilteredText(string autocrlf, string expectedText) } } -#if NETFRAMEWORK || NETCOREAPP3_1 //UTF-7 is disabled in .NET 5+ +#if NETFRAMEWORK //UTF-7 is disabled in .NET 5+ [Theory] [InlineData("ascii", 4, "31 32 33 34")] [InlineData("utf-7", 4, "31 32 33 34")] @@ -239,11 +239,11 @@ public void CanTellIfABlobIsMissing() // Manually delete the objects directory to simulate a partial clone Directory.Delete(Path.Combine(repoPath, "objects", "a8"), true); - using (var repo = new Repository(repoPath)) + using (var repo = new Repository(repoPath)) { // Look up for the tree that reference the blob which is now missing var tree = repo.Lookup("fd093bff70906175335656e6ce6ae05783708765"); - var blob = (Blob) tree["README"].Target; + var blob = (Blob)tree["README"].Target; Assert.Equal("a8233120f6ad708f843d861ce2b7228ec4e3dec6", blob.Sha); Assert.NotNull(blob); diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 25e652522..dc17e6d53 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net472;netcoreapp3.1;net6.0 + net472;net6.0;net7.0 diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index c81dd7093..bb6365716 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - netstandard2.0;netcoreapp3.1 + netstandard2.0;net6.0 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET LibGit2Sharp contributors From fbbfd7121b51a7dd1797cd34f38f9ed736a8b395 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 01:29:05 -0400 Subject: [PATCH 168/179] Fix warning --- LibGit2Sharp/ObjectDatabase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 52aceb321..b48c72a99 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -315,10 +315,10 @@ private unsafe Blob CreateBlob(Stream stream, string hintpath, long? numberOfByt throw new EndOfStreamException("The stream ended unexpectedly"); } } - catch(Exception e) + catch (Exception) { writestream.free(writestream_ptr); - throw e; + throw; } ObjectId id = Proxy.git_blob_create_fromstream_commit(writestream_ptr); From 03cb81103f937385d004cadfeddf77a2470d74e1 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 01:34:36 -0400 Subject: [PATCH 169/179] Update testing packages --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index dc17e6d53..c5cbb5f24 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -11,12 +11,12 @@ - - - - - - + + + + + + From 81d501c16741a3d7b258750b1b45d56ed2ea9025 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 01:36:17 -0400 Subject: [PATCH 170/179] Update Microsoft.SourceLink.GitHub --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index bb6365716..597f37e31 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -31,7 +31,7 @@ - + From 079daef3aa558a1eb3a12f5b599c222f41077c93 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 01:52:39 -0400 Subject: [PATCH 171/179] Update workflow OSes --- .github/workflows/ci.yml | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 878d9ecd1..cf961279d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ env: jobs: build: name: Build - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v3.5.0 @@ -36,10 +36,10 @@ jobs: strategy: matrix: arch: [ amd64 ] - os: [ windows-2019, macos-10.15 ] + os: [ windows-2019, macos-11 ] tfm: [ net472, net6.0, net7.0 ] exclude: - - os: macos-10.15 + - os: macos-11 tfm: net472 fail-fast: false steps: @@ -57,24 +57,18 @@ jobs: run: dotnet test LibGit2Sharp.sln --configuration Release --framework ${{ matrix.tfm }} --logger "GitHubActions" /p:ExtraDefine=LEAKS_IDENTIFYING test-linux: name: Test / ${{ matrix.distro }} / ${{ matrix.arch }} / ${{ matrix.tfm }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: matrix: arch: [ amd64 ] # arch: [ amd64, arm64 ] - distro: [ alpine.3.12, alpine.3.13, alpine.3.14, centos.7, centos.8, debian.9, debian.10, debian.11, fedora.33, ubuntu.18.04, ubuntu.20.04 ] + distro: [ alpine.3.13, alpine.3.14, alpine.3.15, alpine.3.16, alpine.3.17, centos.7, centos.stream.8, debian.10, debian.11, fedora.36, ubuntu.18.04, ubuntu.20.04, ubuntu.22.04 ] sdk: [ '6.0', '7.0' ] exclude: - - arch: arm64 - distro: alpine.3.12 - - arch: arm64 - distro: alpine.3.13 - sdk: '3.1' - - arch: arm64 - distro: alpine.3.14 - sdk: '3.1' - - arch: arm64 - distro: centos.7 + - distro: alpine.3.13 + sdk: '7.0' + - distro: alpine.3.14 + sdk: '7.0' include: - sdk: '6.0' tfm: net6.0 From f1789346c9856f4d93718f605d62d85576a7af5e Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 12:42:43 -0400 Subject: [PATCH 172/179] Remove netstandard2.0 and add net472 --- LibGit2Sharp/Core/NativeMethods.cs | 2 +- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index f5d45f3cf..e20d755ba 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -66,7 +66,7 @@ private static string GetGlobalSettingsNativeLibraryPath() return Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension()); } -#if NETSTANDARD +#if NETFRAMEWORK private static bool TryUseNativeLibrary() => false; #else private static bool TryUseNativeLibrary() diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 597f37e31..0b88a3af5 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net6.0 + net472;net6.0 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET LibGit2Sharp contributors From 48460d087d6622159f929f9aa7476d182ca7078b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 12:46:16 -0400 Subject: [PATCH 173/179] Fix Assembly CodeBase warning --- LibGit2Sharp/GlobalSettings.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index f8db7401a..31cba0965 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -20,7 +20,7 @@ public static class GlobalSettings private static string nativeLibraryPath; private static bool nativeLibraryPathLocked; - private static string nativeLibraryDefaultPath; + private static readonly string nativeLibraryDefaultPath = null; static GlobalSettings() { @@ -29,19 +29,18 @@ static GlobalSettings() nativeLibraryPathAllowed = netFX || netCore; +#if NETFRAMEWORK if (netFX) { // For .NET Framework apps the dependencies are deployed to lib/win32/{architecture} directory nativeLibraryDefaultPath = Path.Combine(GetExecutingAssemblyDirectory(), "lib", "win32", Platform.ProcessorArchitecture); } - else - { - nativeLibraryDefaultPath = null; - } +#endif registeredFilters = new Dictionary(); } +#if NETFRAMEWORK private static string GetExecutingAssemblyDirectory() { // Assembly.CodeBase is not actually a correctly formatted @@ -66,6 +65,7 @@ private static string GetExecutingAssemblyDirectory() managedPath = Path.GetDirectoryName(managedPath); return managedPath; } +#endif /// /// Returns information related to the current LibGit2Sharp From c157b6a5a72ae64da5856fa5d24f5b7847d7793d Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 13:15:21 -0400 Subject: [PATCH 174/179] Update RemoteRedirectMode to match git_remote_redirect_t --- LibGit2Sharp/Core/GitFetchOptions.cs | 2 +- LibGit2Sharp/Core/GitPushOptions.cs | 2 +- LibGit2Sharp/RemoteRedirectMode.cs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LibGit2Sharp/Core/GitFetchOptions.cs b/LibGit2Sharp/Core/GitFetchOptions.cs index bdf8aa585..d82e2f219 100644 --- a/LibGit2Sharp/Core/GitFetchOptions.cs +++ b/LibGit2Sharp/Core/GitFetchOptions.cs @@ -11,7 +11,7 @@ internal class GitFetchOptions public bool UpdateFetchHead = true; public TagFetchMode download_tags; public GitProxyOptions ProxyOptions; - public RemoteRedirectMode FollowRedirects = RemoteRedirectMode.Auto; + public RemoteRedirectMode FollowRedirects = RemoteRedirectMode.Initial; public GitStrArrayManaged CustomHeaders; } } diff --git a/LibGit2Sharp/Core/GitPushOptions.cs b/LibGit2Sharp/Core/GitPushOptions.cs index 8c98ce9cc..ce1a58f7c 100644 --- a/LibGit2Sharp/Core/GitPushOptions.cs +++ b/LibGit2Sharp/Core/GitPushOptions.cs @@ -9,7 +9,7 @@ internal class GitPushOptions public int PackbuilderDegreeOfParallelism; public GitRemoteCallbacks RemoteCallbacks; public GitProxyOptions ProxyOptions; - public RemoteRedirectMode FollowRedirects = RemoteRedirectMode.Auto; + public RemoteRedirectMode FollowRedirects = RemoteRedirectMode.Initial; public GitStrArrayManaged CustomHeaders; } } diff --git a/LibGit2Sharp/RemoteRedirectMode.cs b/LibGit2Sharp/RemoteRedirectMode.cs index 08866e68a..029208857 100644 --- a/LibGit2Sharp/RemoteRedirectMode.cs +++ b/LibGit2Sharp/RemoteRedirectMode.cs @@ -1,7 +1,7 @@ namespace LibGit2Sharp { /// - /// Remote redirection settings; wehther redirects to another + /// Remote redirection settings; whether redirects to another /// host are permitted. By default, git will follow a redirect /// on the initial request (`/info/refs`) but not subsequent /// requests. @@ -12,17 +12,17 @@ public enum RemoteRedirectMode /// Do not follow any off-site redirects at any stage of /// the fetch or push. /// - None = 0, // GIT_REMOTE_REDIRECT_NONE + None = 1 << 0, // GIT_REMOTE_REDIRECT_NONE /// /// Allow off-site redirects only upon the initial /// request. This is the default. /// - Auto, // GIT_REMOTE_REDIRECT_INITIAL + Initial = 1 << 1, // GIT_REMOTE_REDIRECT_INITIAL /// /// Allow redirects at any stage in the fetch or push. /// - All // GIT_REMOTE_REDIRECT_ALL + All = 1 << 2 // GIT_REMOTE_REDIRECT_ALL } } From a7ded296a01358fda726eb8ac27039cc5d2f0433 Mon Sep 17 00:00:00 2001 From: Mark Adamson <3154635+mungojam@users.noreply.github.com> Date: Sat, 8 Apr 2023 18:40:50 +0100 Subject: [PATCH 175/179] Add NuGet package badge (#1980) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ed3fb4d2..3aafdceb1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # LibGit2Sharp -[![CI](https://github.com/libgit2/libgit2sharp/actions/workflows/ci.yml/badge.svg)](https://github.com/libgit2/libgit2sharp/actions/workflows/ci.yml) +[![CI](https://github.com/libgit2/libgit2sharp/actions/workflows/ci.yml/badge.svg)](https://github.com/libgit2/libgit2sharp/actions/workflows/ci.yml) +[![NuGet version (LibGit2Sharp)](https://img.shields.io/nuget/v/LibGit2Sharp.svg)](https://www.nuget.org/packages/LibGit2Sharp/) **LibGit2Sharp brings all the might and speed of [libgit2](http://libgit2.github.com/), a native Git implementation, to the managed world of .NET** From 1d64999130c392e553b827246f6963c779bf668f Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 21:33:05 -0400 Subject: [PATCH 176/179] Switch to MinVer for versioning --- LibGit2Sharp.sln | 5 ++-- LibGit2Sharp/LibGit2Sharp.csproj | 8 +++--- LibGit2Sharp/Version.cs | 12 +++++++-- Targets/CodeGenerator.targets | 37 ++++++++++----------------- Targets/GenerateNativeDllName.targets | 5 +--- version.json | 13 ---------- 6 files changed, 31 insertions(+), 49 deletions(-) delete mode 100644 version.json diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index a81b0ce37..e99eec26f 100644 --- a/LibGit2Sharp.sln +++ b/LibGit2Sharp.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28803.202 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33516.290 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp", "LibGit2Sharp\LibGit2Sharp.csproj", "{EE6ED99F-CB12-4683-B055-D28FC7357A34}" EndProject @@ -13,7 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Directory.Build.props = Directory.Build.props Targets\GenerateNativeDllName.targets = Targets\GenerateNativeDllName.targets nuget.config = nuget.config - version.json = version.json EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeLibraryLoadTestApp.x86", "NativeLibraryLoadTestApp\x86\NativeLibraryLoadTestApp.x86.csproj", "{86453D2C-4953-4DF4-B12A-ADE579608BAA}" diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 0b88a3af5..6aa70519c 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -17,6 +17,8 @@ square-logo.png App_Readme/LICENSE.md true + preview.0 + libgit2-$(libgit2_hash.Substring(0,7)) @@ -32,15 +34,15 @@ - + - + - https://github.com/libgit2/libgit2sharp/blob/$(GitCommitIdShort)/CHANGES.md#libgit2sharp-changes + https://github.com/libgit2/libgit2sharp/blob/$(SourceRevisionId)/CHANGES.md diff --git a/LibGit2Sharp/Version.cs b/LibGit2Sharp/Version.cs index 3795382a3..2c21ccad2 100644 --- a/LibGit2Sharp/Version.cs +++ b/LibGit2Sharp/Version.cs @@ -1,4 +1,5 @@ using System.Globalization; +using System.Reflection; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -22,7 +23,14 @@ internal static Version Build() /// /// Returns version of the LibGit2Sharp library. /// - public virtual string InformationalVersion => ThisAssembly.AssemblyInformationalVersion; + public virtual string InformationalVersion + { + get + { + var attribute = Assembly.GetExecutingAssembly().GetCustomAttribute(); + return attribute.InformationalVersion; + } + } /// /// Returns all the optional features that were compiled into @@ -55,7 +63,7 @@ private string RetrieveAbbrevShaFrom(string sha) /// /// /// The format of the version number is as follows: - /// Major.Minor.Patch[-previewTag]+{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) + /// Major.Minor.Patch[-previewTag]+libgit2-{libgit2_abbrev_hash}.{LibGit2Sharp_hash} (arch - features) /// /// public override string ToString() diff --git a/Targets/CodeGenerator.targets b/Targets/CodeGenerator.targets index 249cd4f38..16eb8f05b 100644 --- a/Targets/CodeGenerator.targets +++ b/Targets/CodeGenerator.targets @@ -1,22 +1,24 @@  - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - + $(IntermediateOutputPath)SourceRevisionId.txt $(IntermediateOutputPath)UniqueIdentifier.g.cs $(IntermediateOutputPath)AssemblyCommitIds.g.cs + + + + + + - - + - $([System.Guid]::NewGuid()) - $(GitCommitId) + $(SourceRevisionId) + $([System.Guid]::NewGuid()) namespace LibGit2Sharp.Core { @@ -34,24 +36,12 @@ - - - - - - - - - - - - - + - unknown - $(GitCommitId) + $(SourceRevisionId) + unknown namespace LibGit2Sharp { @@ -70,7 +60,6 @@ - diff --git a/Targets/GenerateNativeDllName.targets b/Targets/GenerateNativeDllName.targets index 244b707b4..c74dcd31e 100644 --- a/Targets/GenerateNativeDllName.targets +++ b/Targets/GenerateNativeDllName.targets @@ -1,9 +1,5 @@  - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - $(IntermediateOutputPath)NativeDllName.g.cs @@ -30,4 +26,5 @@ + diff --git a/version.json b/version.json deleted file mode 100644 index b0cb8c411..000000000 --- a/version.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.27.0-preview.{height}", - "publicReleaseRefSpec": [ - "^refs/heads/master$", // we release out of master - "^refs/heads/maint/v\\d+(?:\\.\\d+)?$" // and maint/vNN branches - ], - "cloudBuild": { - "buildNumber": { - "enabled": true - } - } -} From 2da1e0eab8bd210dca2a950d90809ff103d59980 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 8 Apr 2023 22:09:42 -0400 Subject: [PATCH 177/179] Update version test --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index e067fd192..cd237663e 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -23,25 +23,25 @@ public void CanGetMinimumCompiledInFeatures() public void CanRetrieveValidVersionString() { // Version string format is: - // Major.Minor.Patch[-previewTag]+{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) + // Major.Minor.Patch[-previewTag]+libgit2-{libgit2_abbrev_hash}.{LibGit2Sharp_hash} (arch - features) // Example output: - // "0.25.0-preview.52+871d13a67f.libgit2-15e1193 (x86 - Threads, Https)" + // "0.27.0-preview.0.1896+libgit2-c058aa8.c1ac3ed74487da5fac24cf1e48dc8ea71e917b75 (x64 - Threads, Https, NSec)" string versionInfo = GlobalSettings.Version.ToString(); // The GlobalSettings.Version returned string should contain : // version: '0.25.0[-previewTag]' LibGit2Sharp version number. - // git2SharpHash: '871d13a67f' LibGit2Sharp hash. + // git2SharpHash: 'c1ac3ed74487da5fac24cf1e48dc8ea71e917b75' LibGit2Sharp hash. // arch: 'x86' or 'x64' libgit2 target. // git2Features: 'Threads, Ssh' libgit2 features compiled with. - string regex = @"^(?\d+\.\d+\.\d+(-[\w\-\.]+)?\+((?[a-f0-9]{10})\.)?libgit2-[a-f0-9]{7}) \((?\w+) - (?(?:\w*(?:, )*\w+)*)\)$"; + string regex = @"^(?\d+\.\d+\.\d+(-[\w\-\.]+)?)\+libgit2-[a-f0-9]{7}\.((?[a-f0-9]{40}))? \((?\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[-previewTag]+{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features). " + + "Major.Minor.Patch[-previewTag]+libgit2-{libgit2_abbrev_hash}.{LibGit2Sharp_hash} (arch - features). " + "But found \"" + versionInfo + "\" instead."); } From 8e1fe56a427ad30129f2e1fbe7fd29d044c714bd Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 9 Apr 2023 02:10:38 -0400 Subject: [PATCH 178/179] Mark repo safe to fix MinVer warning --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf961279d..f44285812 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,5 +85,7 @@ jobs: run: docker run --rm --privileged multiarch/qemu-user-static:register --reset - name: Run ${{ matrix.tfm }} tests run: | + git_command="git config --global --add safe.directory /app" test_command="dotnet test LibGit2Sharp.sln --configuration Release -p:TargetFrameworks=${{ matrix.tfm }} --logger "GitHubActions" -p:ExtraDefine=LEAKS_IDENTIFYING" - docker run -t --rm --platform linux/${{ matrix.arch }} -v "$PWD:/app" gittools/build-images:${{ matrix.distro }}-sdk-${{ matrix.sdk }} sh -c "$test_command" + docker run -t --rm --platform linux/${{ matrix.arch }} -v "$PWD:/app" gittools/build-images:${{ matrix.distro }}-sdk-${{ matrix.sdk }} sh -c "$git_command && $test_command" + From 9552731c51aff4e0a76dd6c2ac87ba90cf0c0aff Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 10 Apr 2023 20:19:09 -0400 Subject: [PATCH 179/179] Add v0.27 changes --- CHANGES.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 78bd537f6..c902a8640 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,14 +1,27 @@ # LibGit2Sharp Changes -**LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .Net and Mono.** - - - Source code: - - NuGet package: - - Issue tracker: - - @libgit2sharp: - - CI servers: - - Windows (x86/amd64): - - Linux/Mac OS X: +## v0.27 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.26..0.27.0)) + +### Changes +- LibGit2Sharp now targets .NET Framework 4.7.2 and .NET 6. +- This release includes [libgit2 v1.6.3](https://github.com/libgit2/libgit2/releases/tag/v1.6.3). +- Changes to the native binaries let LibGit2Sharp work on all [.NET 6 supported OS versions and architectures](https://github.com/dotnet/core/blob/main/release-notes/6.0/supported-os.md). +- `GlobalSetings.NativeLibraryPath` used to automatically append architecture to the path when running on .NET Framework. This behavior has been removed to make it consistent. [#1918](https://github.com/libgit2/libgit2sharp/pull/1918) + +### Additions +- Add support for adding and clearing multi-valued configuration [#1720](https://github.com/libgit2/libgit2sharp/pull/1720) +- added lines and deleted lines in content changes [#1790](https://github.com/libgit2/libgit2sharp/pull/1790) +- Set / get supported extensions [#1908](https://github.com/libgit2/libgit2sharp/pull/1908) +- Simplify dealing with missing git objects [#1909](https://github.com/libgit2/libgit2sharp/pull/1909) +- Throw NotFoundException if trees are missing when computing diff [#1936](https://github.com/libgit2/libgit2sharp/pull/1936) + +### Fixes +- Adjust GitStatusOptions to match structure of native libgit2 [#1884](https://github.com/libgit2/libgit2sharp/pull/1884) +- Update git_worktree_add_options struct to include ref pointer [#1890](https://github.com/libgit2/libgit2sharp/pull/1890) +- Fix git_remote_connect not throwing on non-zero result [#1913](https://github.com/libgit2/libgit2sharp/pull/1913) +- Fix incorrect information in exceptions [#1919](https://github.com/libgit2/libgit2sharp/pull/1919) +- Checkout branch looks to remote tracking branches as fallback [#1820](https://github.com/libgit2/libgit2sharp/pull/1820) +- Fixed calling into native libgit2 on osx-arm64 [#1955](https://github.com/libgit2/libgit2sharp/pull/1955) ## v0.26 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.25..v0.26))