From e5a4a7131f1c05230fb603708c7b666ebfbeb5e8 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 25 Jun 2017 19:57:04 -0700 Subject: [PATCH 001/384] Fix random build failure due to System.IO.FileSystem not found Applies fix for https://github.com/AArnott/CodeGeneration.Roslyn/issues/25 --- .../OfferFriendlyInteropOverloadsGenerator.cs | 4 +++- Directory.Build.props | 2 +- lkg/CodeGeneration.dll | Bin 20992 -> 20992 bytes lkg/CodeGeneration.pdb | Bin 2956 -> 3884 bytes 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CodeGeneration/OfferFriendlyInteropOverloadsGenerator.cs b/CodeGeneration/OfferFriendlyInteropOverloadsGenerator.cs index f1b980f2a..77c6b4d28 100644 --- a/CodeGeneration/OfferFriendlyInteropOverloadsGenerator.cs +++ b/CodeGeneration/OfferFriendlyInteropOverloadsGenerator.cs @@ -30,8 +30,10 @@ public OfferFriendlyInteropOverloadsGenerator(AttributeData data) { } - public Task> GenerateAsync(MemberDeclarationSyntax applyTo, CSharpCompilation compilation, IProgress progress, CancellationToken cancellationToken) + public Task> GenerateAsync(TransformationContext context, IProgress progress, CancellationToken cancellationToken) { + MemberDeclarationSyntax applyTo = context.ProcessingMember; + Compilation compilation = context.Compilation; Func findMarshalAttribute = (p, al) => { var marshalAttribute = al.Attributes.FirstOrDefault(a => (a.Name as SimpleNameSyntax)?.Identifier.ValueText == "CustomMarshaler"); diff --git a/Directory.Build.props b/Directory.Build.props index 7bf63e22b..cdcfe9cd2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ - 0.3.13-gfce1c8ba1e + 0.4.6 diff --git a/lkg/CodeGeneration.dll b/lkg/CodeGeneration.dll index 6144f55562d654a3b4f830eed02a035eb0b3bebe..2bd7491ea93440cff024e0bd18089d329e05e5ac 100644 GIT binary patch literal 20992 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 literal 20992 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 From b8b9aba7b248bf20fba4e6f872964a74eec2a7ac Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 25 Jun 2017 23:36:19 -0700 Subject: [PATCH 002/384] Update to CG.R 0.4.9 to fix build on Travis CI --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index cdcfe9cd2..52a6dde99 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ - 0.4.6 + 0.4.9 From 1171cfbbc41391a626ac5a15f69b03798b3f529a Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Sun, 2 Jul 2017 16:26:58 +0700 Subject: [PATCH 003/384] Fix CertificateSsh constructor Should fix #1383. --- LibGit2Sharp/CertificateSsh.cs | 18 ++++-------------- LibGit2Sharp/Core/GitCertificateSsh.cs | 2 +- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/LibGit2Sharp/CertificateSsh.cs b/LibGit2Sharp/CertificateSsh.cs index 3c66bd995..d72b69469 100644 --- a/LibGit2Sharp/CertificateSsh.cs +++ b/LibGit2Sharp/CertificateSsh.cs @@ -35,10 +35,6 @@ protected CertificateSsh() /// public readonly bool HasSHA1; - /// - /// True if we have the SHA1 hostkey hash from the server - /// public readonly bool HasSHA1; - internal unsafe CertificateSsh(git_certificate_ssh* cert) { @@ -46,21 +42,15 @@ internal unsafe CertificateSsh(git_certificate_ssh* cert) HasSHA1 = cert->type.HasFlag(GitCertificateSshType.SHA1); HashMD5 = new byte[16]; - fixed (byte* p = &HashMD5[0]) + for (var i = 0; i < HashMD5.Length; i++) { - for (var i = 0; i < HashMD5.Length; i++) - { - HashMD5[i] = p[i]; - } + HashMD5[i] = cert->HashMD5[i]; } HashSHA1 = new byte[20]; - fixed (byte* p = &HashSHA1[0]) + for (var i = 0; i < HashSHA1.Length; i++) { - for (var i = 0; i < HashSHA1.Length; i++) - { - HashSHA1[i] = p[i]; - } + HashSHA1[i] = cert->HashSHA1[i]; } } diff --git a/LibGit2Sharp/Core/GitCertificateSsh.cs b/LibGit2Sharp/Core/GitCertificateSsh.cs index b1b9d7940..e3e7c4927 100644 --- a/LibGit2Sharp/Core/GitCertificateSsh.cs +++ b/LibGit2Sharp/Core/GitCertificateSsh.cs @@ -14,7 +14,7 @@ internal unsafe struct git_certificate_ssh public unsafe fixed byte HashMD5[16]; /// - /// The MD5 hash (if appropriate) + /// The SHA1 hash (if appropriate) /// public unsafe fixed byte HashSHA1[20]; } From 7e98850104f55865c714b19b788e9fefbaeec0f3 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 20 Jul 2017 12:47:40 -0700 Subject: [PATCH 004/384] Update some nuget packages --- Directory.Build.props | 4 ++-- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 ++-- LibGit2Sharp/LibGit2Sharp.csproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 52a6dde99..0b47885d2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,10 +3,10 @@ $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ - 0.4.9 + 0.4.11 - + diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index b84f5399b..4d8d204de 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -18,9 +18,9 @@ - + - + diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index f3fb18896..cf3d667c6 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,8 +32,8 @@ - - + + From a83a28c1d43928f827d1890bb0f85eafc42afb48 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 19 Jul 2017 17:08:59 -0700 Subject: [PATCH 005/384] Change version number to 0.25-preview Our new version numbering system is quite clever and tries to advance the teeny version number automagically. Instead of versioning prereleases as `0.25.x` where `x` is monotonically increasing, version our prereleases as `0.25-preview`. This is roughly what our previous strategy looked like. --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index c731f2ab6..fe5217a4a 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.25", + "version": "0.25.0-preview.{height}", "publicReleaseRefSpec": [ "^refs/heads/master$", // we release out of master "^refs/heads/v\\d+(?:\\.\\d+)?$" // we also release out of vNN branches From d46136a74845c5af1bf73e2b6c0d27d5478557d5 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 20 Jul 2017 13:03:26 -0700 Subject: [PATCH 006/384] version number test: expand preview characters --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 8d93373de..365bc1a3e 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -30,7 +30,7 @@ public void CanRetrieveValidVersionString() // git2hash: '06d772d' LibGit2 library 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\-\.]+)?\+(g(?[a-f0-9]{10})\.)?LibGit2-[a-f0-9]{7}) \((?\w+) - (?(?:\w*(?:, )*\w+)*)\)$"; Assert.NotNull(versionInfo); From 12550d6009e15cf8fadef5df476398d4a96067c6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 31 Jul 2017 20:36:57 -0400 Subject: [PATCH 007/384] Remove CodeGeneration --- CodeGeneration/CodeGeneration.csproj | 12 - .../OfferFriendlyInteropOverloadsGenerator.cs | 312 ------------------ .../CodeGenerationAttributes.csproj | 12 - .../CustomMarshalerAttribute.cs | 21 -- .../OfferFriendlyInteropOverloadsAttribute.cs | 16 - LibGit2Sharp.sln | 18 +- LibGit2Sharp/CodeGenerator.targets | 135 +++----- LibGit2Sharp/LibGit2Sharp.csproj | 6 - lkg/CodeGeneration.dll | Bin 20992 -> 0 bytes lkg/CodeGeneration.pdb | Bin 3884 -> 0 bytes 10 files changed, 61 insertions(+), 471 deletions(-) delete mode 100644 CodeGeneration/CodeGeneration.csproj delete mode 100644 CodeGeneration/OfferFriendlyInteropOverloadsGenerator.cs delete mode 100644 CodeGenerationAttributes/CodeGenerationAttributes.csproj delete mode 100644 CodeGenerationAttributes/CustomMarshalerAttribute.cs delete mode 100644 CodeGenerationAttributes/OfferFriendlyInteropOverloadsAttribute.cs delete mode 100644 lkg/CodeGeneration.dll delete mode 100644 lkg/CodeGeneration.pdb diff --git a/CodeGeneration/CodeGeneration.csproj b/CodeGeneration/CodeGeneration.csproj deleted file mode 100644 index 4d9b0f60f..000000000 --- a/CodeGeneration/CodeGeneration.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - netstandard1.5 - $(PackageTargetFallback);portable-net45+win8+wp8+wpa81; - false - true - - - - - - \ No newline at end of file diff --git a/CodeGeneration/OfferFriendlyInteropOverloadsGenerator.cs b/CodeGeneration/OfferFriendlyInteropOverloadsGenerator.cs deleted file mode 100644 index 77c6b4d28..000000000 --- a/CodeGeneration/OfferFriendlyInteropOverloadsGenerator.cs +++ /dev/null @@ -1,312 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using CodeGeneration.Roslyn; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static System.FormattableString; - -namespace CodeGeneration -{ - public class OfferFriendlyInteropOverloadsGenerator : ICodeGenerator - { - private static readonly TypeSyntax IntPtrTypeSyntax = SyntaxFactory.ParseTypeName("IntPtr"); - private static readonly IdentifierNameSyntax resultLocal = SyntaxFactory.IdentifierName("_result"); - private static readonly ExpressionSyntax IntPtrZeroExpressionSyntax = SyntaxFactory.MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IntPtrTypeSyntax, - SyntaxFactory.IdentifierName(nameof(IntPtr.Zero))); - - /// - /// Initializes a new instance of the class. - /// - /// Generator attribute data. - public OfferFriendlyInteropOverloadsGenerator(AttributeData data) - { - } - - public Task> GenerateAsync(TransformationContext context, IProgress progress, CancellationToken cancellationToken) - { - MemberDeclarationSyntax applyTo = context.ProcessingMember; - Compilation compilation = context.Compilation; - Func findMarshalAttribute = (p, al) => - { - var marshalAttribute = al.Attributes.FirstOrDefault(a => (a.Name as SimpleNameSyntax)?.Identifier.ValueText == "CustomMarshaler"); - if (marshalAttribute == null) - { - return default(MarshaledParameter); - } - - var customMarshalerExpression = (TypeOfExpressionSyntax)marshalAttribute.ArgumentList.Arguments[0].Expression; - var customMarshaler = customMarshalerExpression.Type; - var friendlyTypeExpression = (TypeOfExpressionSyntax)marshalAttribute.ArgumentList.Arguments[1].Expression; - var friendlyType = friendlyTypeExpression.Type; - return new MarshaledParameter(p, customMarshaler, friendlyType); - }; - - var semanticModel = compilation.GetSemanticModel(applyTo.SyntaxTree); - var type = (ClassDeclarationSyntax)applyTo; - var generatedType = type - .WithMembers(SyntaxFactory.List()) - .WithAttributeLists(SyntaxFactory.List()); - foreach (var method in type.Members.OfType()) - { - var marshaledParameters = from p in method.ParameterList.Parameters - from al in p.AttributeLists - let a = findMarshalAttribute(p, al) - where a.OriginalParameter != null - select a; - var marshaledResult = from al in method.AttributeLists - where al.Target?.Identifier.IsKind(SyntaxKind.ReturnKeyword) ?? false - let a = findMarshalAttribute(null, al) - where a.FriendlyType != null - select a; - if (marshaledParameters.Any() || marshaledResult.Any()) - { - var wrapperMethod = method - .WithModifiers(RemoveModifier(method.Modifiers, SyntaxKind.ExternKeyword, SyntaxKind.PrivateKeyword).Insert(0, SyntaxFactory.Token(SyntaxKind.InternalKeyword))) - .WithAttributeLists(SyntaxFactory.List()) - .WithLeadingTrivia(method.GetLeadingTrivia().Where(t => !t.IsDirective)) - .WithTrailingTrivia(method.GetTrailingTrivia().Where(t => !t.IsDirective)) - .WithParameterList(CreateParameterListFor(method, marshaledParameters)) - .WithReturnType(marshaledResult.FirstOrDefault().FriendlyType ?? method.ReturnType) - .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) - .WithExpressionBody(null) - .WithBody(CreateBodyFor(method, marshaledParameters, marshaledResult.FirstOrDefault())); - - if (!marshaledParameters.Any()) - { - wrapperMethod = wrapperMethod - .WithIdentifier(SyntaxFactory.Identifier(wrapperMethod.Identifier.ValueText.TrimEnd('_'))); - } - - generatedType = generatedType.AddMembers(wrapperMethod); - } - } - - return Task.FromResult(SyntaxFactory.List().Add(generatedType)); - } - - private static SyntaxTokenList RemoveModifier(SyntaxTokenList list, params SyntaxKind[] modifiers) - { - return SyntaxFactory.TokenList(list.Where(t => Array.IndexOf(modifiers, t.Kind()) < 0)); - } - - private static readonly TypeSyntax ICustomMarshalerTypeSyntax = SyntaxFactory.ParseTypeName("ICustomMarshaler"); - - private static ArgumentSyntax ForwardParameter(ParameterSyntax parameter) - { - var refOrOut = parameter.Modifiers.FirstOrDefault(m => m.IsKind(SyntaxKind.RefKeyword) || m.IsKind(SyntaxKind.OutKeyword)); - var arg = SyntaxFactory.Argument(SyntaxFactory.IdentifierName(parameter.Identifier)) - .WithRefOrOutKeyword(refOrOut); - return arg; - } - - private ParameterListSyntax CreateParameterListFor(MethodDeclarationSyntax innerMethod, IEnumerable marshaledParameters) - { - var modifiedParameterList = SyntaxFactory.ParameterList(); - - foreach (var p in innerMethod.ParameterList.Parameters) - { - var marshaledInfo = marshaledParameters.FirstOrDefault(m => m.OriginalParameter == p); - var modifiedParameter = p - .WithAttributeLists(SyntaxFactory.List()) - .WithType(marshaledInfo.FriendlyType ?? p.Type); - modifiedParameterList = modifiedParameterList.AddParameters(modifiedParameter); - } - - return modifiedParameterList; - } - - private BlockSyntax CreateBodyFor(MethodDeclarationSyntax innerMethod, IEnumerable marshaledParameters, MarshaledParameter marshaledResult) - { - var body = SyntaxFactory.Block(); - var finallyBlock = SyntaxFactory.Block(); - var argsByParameter = innerMethod.ParameterList.Parameters.ToDictionary( - p => p, - p => ForwardParameter(p)); - var marshalerInitializers = new List(); - var inputMarshaling = new List(); - var outputMarshaling = new List(); - - var marshalersCreated = new HashSet(); - Func acquireMarshaler = type => - { - var marshalerLocalName = Invariant($"_{type}"); - if (marshalersCreated.Add(marshalerLocalName)) - { - marshalerInitializers.Add( - SyntaxFactory.LocalDeclarationStatement( - SyntaxFactory.VariableDeclaration(ICustomMarshalerTypeSyntax) - .AddVariables(SyntaxFactory.VariableDeclarator(marshalerLocalName) - .WithInitializer(SyntaxFactory.EqualsValueClause( - SyntaxFactory.InvocationExpression( - SyntaxFactory.MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - type, - SyntaxFactory.IdentifierName("GetInstance")), - SyntaxFactory.ArgumentList())))))); - } - - return marshalerLocalName; - }; - - foreach (var parameter in marshaledParameters) - { - string marshalerLocalName = acquireMarshaler(parameter.MarshalerType); - var isOutParameter = parameter.OriginalParameter.Modifiers.Any(m => m.IsKind(SyntaxKind.OutKeyword)); - TypeSyntax localVarType = isOutParameter ? parameter.OriginalParameter.Type : IntPtrTypeSyntax; - ExpressionSyntax initialValue = isOutParameter - ? (ExpressionSyntax)SyntaxFactory.DefaultExpression(parameter.OriginalParameter.Type) - : SyntaxFactory.InvocationExpression( - SyntaxFactory.MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - SyntaxFactory.IdentifierName(marshalerLocalName), - SyntaxFactory.IdentifierName("MarshalManagedToNative"))) - .AddArgumentListArguments(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(parameter.OriginalParameter.Identifier))); - var localVarIdentifier = SyntaxFactory.IdentifierName(Invariant($"_{parameter.OriginalParameter.Identifier.ValueText}")); - inputMarshaling.Add( - SyntaxFactory.LocalDeclarationStatement( - SyntaxFactory.VariableDeclaration(localVarType) - .AddVariables(SyntaxFactory.VariableDeclarator(localVarIdentifier.Identifier) - .WithInitializer(SyntaxFactory.EqualsValueClause(initialValue))))); - - argsByParameter[parameter.OriginalParameter] = argsByParameter[parameter.OriginalParameter] - .WithExpression( - isOutParameter - ? (ExpressionSyntax)localVarIdentifier - : SyntaxFactory.CastExpression(parameter.OriginalParameter.Type, localVarIdentifier)); - - if (isOutParameter) - { - outputMarshaling.Add( - SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - SyntaxFactory.IdentifierName(parameter.OriginalParameter.Identifier), - SyntaxFactory.CastExpression( - parameter.FriendlyType, - SyntaxFactory.InvocationExpression( - SyntaxFactory.MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - SyntaxFactory.IdentifierName(marshalerLocalName), - SyntaxFactory.IdentifierName("MarshalNativeToManaged")), - SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument( - SyntaxFactory.ObjectCreationExpression( - IntPtrTypeSyntax, - SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(localVarIdentifier))), - null))))))))); - } - - var cleanUpExpression = isOutParameter - ? (ExpressionSyntax)SyntaxFactory.ObjectCreationExpression(IntPtrTypeSyntax).AddArgumentListArguments( - SyntaxFactory.Argument(localVarIdentifier)) - : localVarIdentifier; - finallyBlock = finallyBlock.AddStatements( - SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression( - SyntaxFactory.MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - SyntaxFactory.IdentifierName(marshalerLocalName), - SyntaxFactory.IdentifierName("CleanUpNativeData"))) - .AddArgumentListArguments(SyntaxFactory.Argument(cleanUpExpression)))); - } - - var args = SyntaxFactory.ArgumentList().AddArguments( - (from p in innerMethod.ParameterList.Parameters - select argsByParameter[p]).ToArray()); - var invocation = SyntaxFactory.InvocationExpression( - SyntaxFactory.IdentifierName(innerMethod.Identifier), - args); - StatementSyntax invocationStatement; - StatementSyntax returnStatement = null; - if (innerMethod.ReturnType != null && (innerMethod.ReturnType as PredefinedTypeSyntax)?.Keyword.Kind() != SyntaxKind.VoidKeyword) - { - if (marshaledResult.MarshalerType != null) - { - string marshalerLocalName = acquireMarshaler(marshaledResult.MarshalerType); - inputMarshaling.Add( - SyntaxFactory.LocalDeclarationStatement( - SyntaxFactory.VariableDeclaration(IntPtrTypeSyntax) - .AddVariables(SyntaxFactory.VariableDeclarator(resultLocal.Identifier) - .WithInitializer(SyntaxFactory.EqualsValueClause(IntPtrZeroExpressionSyntax))))); - - var intPtrResultExpression = SyntaxFactory.AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - resultLocal, - SyntaxFactory.ObjectCreationExpression( - IntPtrTypeSyntax, - SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(invocation))), - null)); - var castToManagedExpression = SyntaxFactory.CastExpression( - marshaledResult.FriendlyType, - SyntaxFactory.InvocationExpression( - SyntaxFactory.MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - SyntaxFactory.IdentifierName(marshalerLocalName), - SyntaxFactory.IdentifierName("MarshalNativeToManaged")), - SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(resultLocal))))); - - invocationStatement = SyntaxFactory.ExpressionStatement(intPtrResultExpression); - returnStatement = SyntaxFactory.ReturnStatement(castToManagedExpression); - - finallyBlock = finallyBlock.AddStatements( - SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression( - SyntaxFactory.MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - SyntaxFactory.IdentifierName(marshalerLocalName), - SyntaxFactory.IdentifierName("CleanUpNativeData"))) - .AddArgumentListArguments(SyntaxFactory.Argument(resultLocal)))); - } - else - { - invocationStatement = SyntaxFactory.LocalDeclarationStatement( - SyntaxFactory.VariableDeclaration(innerMethod.ReturnType) - .AddVariables(SyntaxFactory.VariableDeclarator(resultLocal.Identifier) - .WithInitializer(SyntaxFactory.EqualsValueClause(invocation)))); - returnStatement = SyntaxFactory.ReturnStatement(resultLocal); - } - } - else - { - invocationStatement = SyntaxFactory.ExpressionStatement(invocation); - } - - var tryBlock = SyntaxFactory.Block() - .AddStatements(invocationStatement) - .AddStatements(outputMarshaling.ToArray()); - - if (returnStatement != null) - { - tryBlock = tryBlock - .AddStatements(returnStatement); - } - - body = body - .AddStatements(marshalerInitializers.ToArray()) - .AddStatements(inputMarshaling.ToArray()) - .AddStatements(SyntaxFactory.TryStatement(tryBlock, SyntaxFactory.List(), SyntaxFactory.FinallyClause(finallyBlock))); - - return body; - } - - private struct MarshaledParameter - { - internal MarshaledParameter(ParameterSyntax originalParameter, TypeSyntax marshalerType, TypeSyntax friendlyType) - { - this.OriginalParameter = originalParameter; - this.MarshalerType = marshalerType; - this.FriendlyType = friendlyType; - } - - internal ParameterSyntax OriginalParameter { get; } - - internal TypeSyntax MarshalerType { get; } - - internal TypeSyntax FriendlyType { get; } - } - } -} diff --git a/CodeGenerationAttributes/CodeGenerationAttributes.csproj b/CodeGenerationAttributes/CodeGenerationAttributes.csproj deleted file mode 100644 index 4f81e364c..000000000 --- a/CodeGenerationAttributes/CodeGenerationAttributes.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - net40;netstandard1.0 - true - ..\libgit2sharp.snk - false - - - - - - \ No newline at end of file diff --git a/CodeGenerationAttributes/CustomMarshalerAttribute.cs b/CodeGenerationAttributes/CustomMarshalerAttribute.cs deleted file mode 100644 index 549dd1241..000000000 --- a/CodeGenerationAttributes/CustomMarshalerAttribute.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; - -namespace LibGit2Sharp -{ - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false)] - [Conditional("CodeGeneration")] - public class CustomMarshalerAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - /// The type that derives from ICustomMarshaler. - /// The type to expose in the generated overload. - public CustomMarshalerAttribute(Type customMarshaler, Type friendlyType) - { - } - } -} diff --git a/CodeGenerationAttributes/OfferFriendlyInteropOverloadsAttribute.cs b/CodeGenerationAttributes/OfferFriendlyInteropOverloadsAttribute.cs deleted file mode 100644 index 6aae514a3..000000000 --- a/CodeGenerationAttributes/OfferFriendlyInteropOverloadsAttribute.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Diagnostics; -using CodeGeneration.Roslyn; - -namespace LibGit2Sharp -{ - /// - /// Causes generation of an overload of a P/Invoke method that has a more friendly signature. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - [CodeGenerationAttribute("CodeGeneration.OfferFriendlyInteropOverloadsGenerator, CodeGeneration, Version=" + ThisAssembly.AssemblyVersion + ", Culture=neutral, PublicKeyToken=null")] - [Conditional("CodeGeneration")] - public class OfferFriendlyInteropOverloadsAttribute : Attribute - { - } -} diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index 64945776b..8ca542f60 100644 --- a/LibGit2Sharp.sln +++ b/LibGit2Sharp.sln @@ -1,13 +1,10 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26407.1 +VisualStudioVersion = 15.0.26724.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibGit2Sharp", "LibGit2Sharp\LibGit2Sharp.csproj", "{EE6ED99F-CB12-4683-B055-D28FC7357A34}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp", "LibGit2Sharp\LibGit2Sharp.csproj", "{EE6ED99F-CB12-4683-B055-D28FC7357A34}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibGit2Sharp.Tests", "LibGit2Sharp.Tests\LibGit2Sharp.Tests.csproj", "{286E63EB-04DD-4ADE-88D6-041B57800761}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeGenerationAttributes", "CodeGenerationAttributes\CodeGenerationAttributes.csproj", "{E1A8B99F-B2F6-4A38-9DF6-8792056D70FF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp.Tests", "LibGit2Sharp.Tests\LibGit2Sharp.Tests.csproj", "{286E63EB-04DD-4ADE-88D6-041B57800761}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0CA739FD-DA4D-4F64-9834-DA14A3ECD04B}" ProjectSection(SolutionItems) = preProject @@ -17,8 +14,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProjectSection EndProject Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU @@ -32,12 +27,11 @@ Global {286E63EB-04DD-4ADE-88D6-041B57800761}.Debug|Any CPU.Build.0 = Debug|Any CPU {286E63EB-04DD-4ADE-88D6-041B57800761}.Release|Any CPU.ActiveCfg = Release|Any CPU {286E63EB-04DD-4ADE-88D6-041B57800761}.Release|Any CPU.Build.0 = Release|Any CPU - {E1A8B99F-B2F6-4A38-9DF6-8792056D70FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E1A8B99F-B2F6-4A38-9DF6-8792056D70FF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E1A8B99F-B2F6-4A38-9DF6-8792056D70FF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E1A8B99F-B2F6-4A38-9DF6-8792056D70FF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9BD5F77D-E47D-4621-9AA0-8598766902B9} + EndGlobalSection EndGlobal diff --git a/LibGit2Sharp/CodeGenerator.targets b/LibGit2Sharp/CodeGenerator.targets index 402001459..d55d50117 100644 --- a/LibGit2Sharp/CodeGenerator.targets +++ b/LibGit2Sharp/CodeGenerator.targets @@ -1,89 +1,64 @@ - - - - $(MSBuildProjectDirectory)\..\lkg\ - + - - - false - - - - - - $(CoreCompileDependsOn);GenerateNativeDllNameCs - GenerateCommitIdVersion;$(PrepareResourceNamesDependsOn) - $(IntermediateOutputPath)NativeDllName.cs - $(IntermediateOutputPath)UniqueIdentifier.cs - $(IntermediateOutputPath)libgit2sharp_hash.txt + $(CoreCompileDependsOn);GenerateNativeDllNameCs + GenerateCommitIdVersion;$(PrepareResourceNamesDependsOn) + $(IntermediateOutputPath)NativeDllName.cs + $(IntermediateOutputPath)UniqueIdentifier.cs + $(IntermediateOutputPath)libgit2sharp_hash.txt - - - - - - - -namespace LibGit2Sharp.Core -{ - internal static class NativeDllName - { - public const string Name = "$(libgit2FileName)"%3b - } -} - - - - - - - - + + + + + + + namespace LibGit2Sharp.Core + { + internal static class NativeDllName + { + public const string Name = "$(libgit2FileName)"%3b + } + } + + + + + + + + + + + + + - - - - + + + + - - - - + + - - + + + $(RootNamespace).libgit2sharp_hash.txt + + + - - - $(RootNamespace).libgit2sharp_hash.txt - - - diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index cf3d667c6..0c93c484c 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -27,16 +27,10 @@ Objects.tt - - - - - - diff --git a/lkg/CodeGeneration.dll b/lkg/CodeGeneration.dll deleted file mode 100644 index 2bd7491ea93440cff024e0bd18089d329e05e5ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20992 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 diff --git a/lkg/CodeGeneration.pdb b/lkg/CodeGeneration.pdb deleted file mode 100644 index 9e02155bf0e184d0e2677a2e04d05f0fbb5e6702..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3884 zcmb_feQ;D)6+h?h*V~YfB?(Isnhzia!pDXLC?5?3@&N=%ld=#BBI(QSOIW+vx4id~ zvRdVBNRxm}rBf6TTWM>dtux}NWvY%?XWEWq$B!AcI@Y07OJ}5=&Nwoo=n$kScu?QHaIu5WIk*IPA@~Ch4gs$NzYA0e{ZdC?U?&n+ z1OEtP8LTOB4e(EZ(+;i&z5(0k!Hg=5FLZw23!OPGJR4Z%&Gfj;x9U4^%^kST^?Nxs z*M-Z0>s|N-;JbmBI_t~4UEsnp2N$}q%;!ZeTngOa!qUFQE-Yb(vn$t9pkF|jpi@LYhNKt~Br2hAgAdUb@H6RQ zw561Uq>MfSUzyXXqD7F*q1=^6gOD>7LxPiz)t#4r%euLuo@Z&4ivJw?Qs(EUBrf zU1_&u#I*Eb#}v(QjU-Z5uVw7e%#oyZn|Kr+vE(8#eK?&+=6Sdf+t;V}t;M@igZfP; zb;UK2k{jIMDel_z%lwRq1Ry_Uuj{cF?9>3iA-IwdWbnx1aA8x1i^BaZUb>YbJH+#A= zS4gz4^9&`d!en9qT{F_mNPF~wPZzf%q+9Yy2KV|pw1JVK;*@5YmYRyIM!YGqs`7T7 zNS|iNct>Jpa36b>S(S?->&s93zjLMX%9ZZ9*KUMPdy2mDnKKQY^7aW=_~hdi!3!s% z{%FR8C#v#Yq+L%YwU`X68Ohm@h|O?@wkJ{tYaD*Z2;w-bMY>W5jGm5a#%Lm@nbWE} zwL@0OQQdjK(9}4xJA9`gvQsr5GH2bfl^wd7%%sBIiI}0A`k)1q;@T!0fsC0jtN*(= z(jJxGtN)*)k!U7msfXsXJ<0ZCY`?(vOKks|?W=76g|iB0YdE`#vr&)Q&@(uw8JnHc z>};}UR5Oyg8aJKT=my*!knXO`ezpAFuU{E{!y4Fk;_UZYOWxe^(duvh_K(upo2r9w zcCNfYWph@RGJfKDL8g0!5+K~sfg-QKi`ZF%Yjg=J8evZeR0IL2;bDqY$cwmuv>;~D z*}GXN_N(3v1!SM2)di?LWFdm-gZ9fp$p)!5EUP$_FOac)Stt==Z-!}&7gY@laJfdb zE<&vdO{P7Y_f$&Z(pu(4tnv7K9v|iLi~dJ-mVdwJN!;jS>IZxj?~OSAJ~D`x_?S8C z;cO32^zuX}Pn;AJ@9<{C zleCH|JfS>{FPw@K)3UtV3~~P)aBuYqWZ*M}dLo z$PX{+SOh+zKB1J00|HNKk6+eFa@WGF2~u@w%qL+9my>^Q?OwJoA?jfc1ey2RAByZY zS^dHBhq1_9p@gVGpol}czlYZNQNlF~jIKb;D1wTv41p`Az+%`@Mk`^Q58Ld|2Z|7= z5NU!|Q@^0fKo&-RiZUTu>9x zv9!J<;)F}|jYeBUxgXJ7sNli0vnZmcXQ0JGK}?;5!*n69{e3}g{+dEs7O<}tQycY` z;sNgx6!hE2ywok{M_~Y8dhF9extG=}vNUxPB|kzPLXo@5u-GpPmAe!yF`Z*u;p|+B zd9qbrT2F-qa07IEkxu2@&e>0L_AHMz@~H+s^&X#of=|E3&;6AA6PFl&lZ8B~^5ok* z)yK!)=O^AK@z@}V)7QnB<9y~lKKm9wc~P8ChPkW&*<$~O?GJfux0rmIPrW3<2-m*S z;7p3)-vCcapz2NIV9bG-vrCE?2MUL5z6{u0*}yJXPTp+Ox_rN)Dc`SJE|YZ5`W3RP zX=`jLzzhp8fjx$#q-q&=XUCXMDW;S^Q%9@hoDT`AqedKD+9+h2i_C1!R`J*d9=ps( ze0*d~WM8Ck) Date: Mon, 31 Jul 2017 20:37:34 -0400 Subject: [PATCH 008/384] Move to .NET Standard 2.0 --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 4d8d204de..4dd73ef8c 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,6 +1,6 @@  - net46;netcoreapp1.0 + net46;netcoreapp2.0 true $(DefineConstants);DESKTOP false diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 0c93c484c..4919e1a8b 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,6 +1,6 @@  - net40;netstandard1.3 + net40;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 From 8f07d9cdbafb6cf14d588d214df71d4fed90fbb4 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 1 Aug 2017 23:13:05 -0400 Subject: [PATCH 009/384] Use custom marshaling --- LibGit2Sharp/Core/EncodingMarshaler.cs | 8 - LibGit2Sharp/Core/FilePathMarshaler.cs | 17 +- LibGit2Sharp/Core/NativeMethods.cs | 630 ++++++++++++------------- LibGit2Sharp/Core/Utf8Marshaler.cs | 17 +- 4 files changed, 332 insertions(+), 340 deletions(-) diff --git a/LibGit2Sharp/Core/EncodingMarshaler.cs b/LibGit2Sharp/Core/EncodingMarshaler.cs index af10db780..0cafd9aa1 100644 --- a/LibGit2Sharp/Core/EncodingMarshaler.cs +++ b/LibGit2Sharp/Core/EncodingMarshaler.cs @@ -117,11 +117,7 @@ public static unsafe string FromNative(Encoding encoding, byte* pNativeData) return String.Empty; } -#if DESKTOP return new String((sbyte*)pNativeData, 0, (int)(walk - start), encoding); -#else - return encoding.GetString(pNativeData, (int)(walk - start)); -#endif } public static unsafe string FromNative(Encoding encoding, IntPtr pNativeData, int length) @@ -136,11 +132,7 @@ public static unsafe string FromNative(Encoding encoding, IntPtr pNativeData, in return String.Empty; } -#if DESKTOP return new String((sbyte*)pNativeData.ToPointer(), 0, length, encoding); -#else - return encoding.GetString((byte*)pNativeData.ToPointer(), length); -#endif } public static string FromBuffer(Encoding encoding, byte[] buffer) diff --git a/LibGit2Sharp/Core/FilePathMarshaler.cs b/LibGit2Sharp/Core/FilePathMarshaler.cs index 952c6de18..209254ac5 100644 --- a/LibGit2Sharp/Core/FilePathMarshaler.cs +++ b/LibGit2Sharp/Core/FilePathMarshaler.cs @@ -10,13 +10,15 @@ namespace LibGit2Sharp.Core /// free the native pointer after conversion, because the memory is owned by libgit2. /// /// Use this marshaler for return values, for example: - /// [return: CustomMarshaler(typeof(LaxFilePathNoCleanupMarshaler), typeof(FilePath))] + /// [return: MarshalAs(UnmanagedType.CustomMarshaler, + /// MarshalCookie = UniqueId.UniqueIdentifier, + /// MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))] /// internal class LaxFilePathNoCleanupMarshaler : LaxFilePathMarshaler { private static readonly LaxFilePathNoCleanupMarshaler staticInstance = new LaxFilePathNoCleanupMarshaler(); - public new static ICustomMarshaler GetInstance() + public new static ICustomMarshaler GetInstance(string cookie) { return staticInstance; } @@ -39,15 +41,16 @@ public override void CleanUpNativeData(IntPtr pNativeData) /// /// Use this marshaler for function parameters, for example: /// [DllImport(libgit2)] - /// private static extern unsafe int git_index_remove_bypath( - /// git_index* index, - /// [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* path); + /// internal static extern int git_index_open(out IndexSafeHandle index, + /// [MarshalAs(UnmanagedType.CustomMarshaler, + /// MarshalCookie = UniqueId.UniqueIdentifier, + /// MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath indexpath); /// internal class StrictFilePathMarshaler : StrictUtf8Marshaler { private static readonly StrictFilePathMarshaler staticInstance = new StrictFilePathMarshaler(); - public new static ICustomMarshaler GetInstance() + public new static ICustomMarshaler GetInstance(string cookie) { return staticInstance; } @@ -95,7 +98,7 @@ internal class LaxFilePathMarshaler : LaxUtf8Marshaler { private static readonly LaxFilePathMarshaler staticInstance = new LaxFilePathMarshaler(); - public new static ICustomMarshaler GetInstance() + public new static ICustomMarshaler GetInstance(string cookie) { return staticInstance; } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index b3e7f1297..d28a7aceb 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -2,18 +2,13 @@ using System.Globalization; using System.IO; using System.Runtime.CompilerServices; -#if DESKTOP -using System.Runtime.ConstrainedExecution; -#endif using System.Runtime.InteropServices; -using System.Threading; using LibGit2Sharp.Core.Handles; // ReSharper disable InconsistentNaming namespace LibGit2Sharp.Core { - [OfferFriendlyInteropOverloads] - internal static partial class NativeMethods + internal static class NativeMethods { public const uint GIT_PATH_MAX = 4096; private const string libgit2 = NativeDllName.Name; @@ -21,7 +16,7 @@ internal static partial 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 +#pragma warning disable 0414 private static readonly NativeShutdownObject shutdownObject; #pragma warning restore 0414 @@ -68,9 +63,9 @@ private sealed class NativeShutdownObject internal static extern unsafe GitError* giterr_last(); [DllImport(libgit2)] - private static unsafe extern void giterr_set_str( + internal static extern void giterr_set_str( GitErrorCategory error_class, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* errorString); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string errorString); [DllImport(libgit2)] internal static extern void giterr_set_oom(); @@ -83,43 +78,43 @@ private static unsafe extern void giterr_set_str( git_blame* blame, UInt32 index); [DllImport(libgit2)] - private static extern unsafe int git_blame_file( + internal static extern unsafe int git_blame_file( out git_blame* blame, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path, git_blame_options options); [DllImport(libgit2)] internal static extern unsafe void git_blame_free(git_blame* blame); [DllImport(libgit2)] - private static extern unsafe int git_blob_create_fromdisk( + internal static extern unsafe int git_blob_create_fromdisk( ref GitOid id, git_repository* repo, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* path); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path); [DllImport(libgit2)] - private static extern unsafe int git_blob_create_fromworkdir( + internal static extern unsafe int git_blob_create_fromworkdir( ref GitOid id, git_repository* repo, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* relative_path); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath relative_path); [DllImport(libgit2)] - private static extern unsafe int git_blob_create_fromstream( + internal static extern unsafe int git_blob_create_fromstream( out IntPtr stream, git_repository* repositoryPtr, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* hintpath); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string hintpath); [DllImport(libgit2)] - internal static extern unsafe int git_blob_create_fromstream_commit( + internal static extern int git_blob_create_fromstream_commit( ref GitOid oid, IntPtr stream); [DllImport(libgit2)] - private static extern unsafe int git_blob_filtered_content( + internal static extern unsafe int git_blob_filtered_content( GitBuf buf, git_object* blob, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* as_path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string as_path, [MarshalAs(UnmanagedType.Bool)] bool check_for_binary_data); [DllImport(libgit2)] @@ -129,10 +124,10 @@ private static extern unsafe int git_blob_filtered_content( internal static extern unsafe Int64 git_blob_rawsize(git_object* blob); [DllImport(libgit2)] - private static extern unsafe int git_branch_create_from_annotated( + internal static extern unsafe int git_branch_create_from_annotated( out git_reference* ref_out, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* branch_name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string branch_name, git_annotated_commit* target, [MarshalAs(UnmanagedType.Bool)] bool force); @@ -156,10 +151,10 @@ internal static extern int git_branch_iterator_new( GitBranchType branch_type); [DllImport(libgit2)] - private static extern unsafe int git_branch_move( + internal static extern unsafe int git_branch_move( out git_reference* ref_out, git_reference* reference, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* new_branch_name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string new_branch_name, [MarshalAs(UnmanagedType.Bool)] bool force); [DllImport(libgit2)] @@ -169,10 +164,10 @@ internal static extern int git_branch_next( IntPtr iter); [DllImport(libgit2)] - private static extern unsafe int git_branch_remote_name( + internal static extern unsafe int git_branch_remote_name( GitBuf buf, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* canonical_branch_name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string canonical_branch_name); [DllImport(libgit2)] internal static extern unsafe int git_rebase_init( @@ -229,21 +224,21 @@ internal static extern unsafe int git_rebase_finish( internal static extern unsafe void git_rebase_free(git_rebase* rebase); [DllImport(libgit2)] - private static extern unsafe int git_remote_rename( + internal static extern unsafe int git_remote_rename( ref GitStrArray problems, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* old_name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* new_name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string old_name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string new_name); - private unsafe delegate int git_remote_rename_problem_cb( - [CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] byte* problematic_refspec, + internal delegate int git_remote_rename_problem_cb( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] string problematic_refspec, IntPtr payload); [DllImport(libgit2)] - private static extern unsafe int git_branch_upstream_name( + internal static extern unsafe int git_branch_upstream_name( GitBuf buf, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* referenceName); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string referenceName); [DllImport(libgit2)] internal static extern void git_buf_free(GitBuf buf); @@ -261,10 +256,10 @@ internal static extern unsafe int git_checkout_index( ref GitCheckoutOpts opts); [DllImport(libgit2)] - private static extern unsafe int git_clone( + internal static extern unsafe int git_clone( out git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* origin_url, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* workdir_path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string origin_url, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath workdir_path, ref GitCloneOptions opts); [DllImport(libgit2)] @@ -274,49 +269,49 @@ private static extern unsafe int git_clone( internal static extern unsafe git_signature* git_commit_committer(git_object* commit); [DllImport(libgit2)] - private static extern unsafe int git_commit_create_from_ids( + internal static extern unsafe int git_commit_create_from_ids( out GitOid id, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* updateRef, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string updateRef, git_signature* author, git_signature* committer, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* encoding, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* message, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string encoding, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, ref GitOid tree, UIntPtr parentCount, [MarshalAs(UnmanagedType.LPArray)] [In] IntPtr[] parents); [DllImport(libgit2)] - private static extern unsafe int git_commit_create_buffer( + internal static extern unsafe int git_commit_create_buffer( GitBuf res, git_repository* repo, git_signature* author, git_signature* committer, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* encoding, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* message, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string encoding, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, git_object* tree, UIntPtr parent_count, IntPtr* parents /* git_commit** originally */); [DllImport(libgit2)] - private static extern unsafe int git_commit_create_with_signature( + internal static extern unsafe int git_commit_create_with_signature( out GitOid id, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* commit_content, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* signature, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* signature_field); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string commit_content, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string signature, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string signature_field); - [DllImport(libgit2, EntryPoint = "git_commit_message")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_commit_message_(git_object* commit); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_commit_message(git_object* commit); - [DllImport(libgit2, EntryPoint = "git_commit_summary")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_commit_summary_(git_object* commit); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_commit_summary(git_object* commit); - [DllImport(libgit2, EntryPoint = "git_commit_message_encoding")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_commit_message_encoding_(git_object* commit); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_commit_message_encoding(git_object* commit); [DllImport(libgit2)] internal static extern unsafe git_oid* git_commit_parent_id(git_object* commit, uint n); @@ -328,26 +323,26 @@ private static extern unsafe int git_commit_create_with_signature( internal static extern unsafe git_oid* git_commit_tree_id(git_object* commit); [DllImport(libgit2)] - private static extern unsafe int git_commit_extract_signature( + internal static extern unsafe int git_commit_extract_signature( GitBuf signature, GitBuf signed_data, git_repository* repo, ref GitOid commit_id, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* field); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string field); [DllImport(libgit2)] - private static extern unsafe int git_config_delete_entry( + internal static extern unsafe int git_config_delete_entry( git_config* cfg, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] internal static extern unsafe int git_config_lock(out IntPtr txn, git_config* config); [DllImport(libgit2)] - private static extern unsafe int git_config_delete_multivar( + internal static extern unsafe int git_config_delete_multivar( git_config* cfg, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* regexp); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string regexp); [DllImport(libgit2)] internal static extern int git_config_find_global(GitBuf global_config_path); @@ -368,15 +363,15 @@ private static extern unsafe int git_config_delete_multivar( internal static extern unsafe void git_config_entry_free(GitConfigEntry* entry); [DllImport(libgit2)] - private static extern unsafe int git_config_get_entry( + internal static extern unsafe int git_config_get_entry( out GitConfigEntry* entry, git_config* cfg, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] - private static extern unsafe int git_config_add_file_ondisk( + internal static extern unsafe int git_config_add_file_ondisk( git_config* cfg, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, uint level, [MarshalAs(UnmanagedType.Bool)] bool force); @@ -390,43 +385,43 @@ internal static extern unsafe int git_config_open_level( uint level); [DllImport(libgit2)] - private static unsafe extern int git_config_parse_bool( + internal static extern int git_config_parse_bool( [MarshalAs(UnmanagedType.Bool)] out bool value, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* valueToParse); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string valueToParse); [DllImport(libgit2)] - private static unsafe extern int git_config_parse_int32( + internal static extern int git_config_parse_int32( [MarshalAs(UnmanagedType.I4)] out int value, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* valueToParse); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string valueToParse); [DllImport(libgit2)] - private static unsafe extern int git_config_parse_int64( + internal static extern int git_config_parse_int64( [MarshalAs(UnmanagedType.I8)] out long value, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* valueToParse); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string valueToParse); [DllImport(libgit2)] - private static extern unsafe int git_config_set_bool( + internal static extern unsafe int git_config_set_bool( git_config* cfg, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, [MarshalAs(UnmanagedType.Bool)] bool value); [DllImport(libgit2)] - private static extern unsafe int git_config_set_int32( + internal static extern unsafe int git_config_set_int32( git_config* cfg, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, int value); [DllImport(libgit2)] - private static extern unsafe int git_config_set_int64( + internal static extern unsafe int git_config_set_int64( git_config* cfg, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, long value); [DllImport(libgit2)] - private static extern unsafe int git_config_set_string( + internal static extern unsafe int git_config_set_string( git_config* cfg, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* value); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string value); internal delegate int config_foreach_callback( IntPtr entry, @@ -439,10 +434,10 @@ internal static extern unsafe int git_config_foreach( IntPtr payload); [DllImport(libgit2)] - private static extern unsafe int git_config_iterator_glob_new( + internal static extern int git_config_iterator_glob_new( out IntPtr iter, IntPtr cfg, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* regexp); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string regexp); [DllImport(libgit2)] internal static extern int git_config_next( @@ -471,10 +466,10 @@ internal delegate int git_cred_acquire_cb( internal static extern int git_cred_default_new(out IntPtr cred); [DllImport(libgit2)] - private static unsafe extern int git_cred_userpass_plaintext_new( + internal static extern int git_cred_userpass_plaintext_new( out IntPtr cred, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* username, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* password); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string username, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string password); [DllImport(libgit2)] internal static extern void git_cred_free(IntPtr cred); @@ -554,11 +549,11 @@ internal unsafe delegate int git_diff_binary_cb( IntPtr payload); [DllImport(libgit2)] - private static extern unsafe int git_diff_blobs( + internal static extern unsafe int git_diff_blobs( git_object* oldBlob, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* old_as_path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string old_as_path, git_object* newBlob, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* new_as_path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string new_as_path, GitDiffOptions options, git_diff_file_cb fileCallback, git_diff_binary_cb binaryCallback, @@ -587,13 +582,13 @@ internal static extern unsafe int git_diff_find_similar( internal static extern unsafe git_diff_delta* git_diff_get_delta(git_diff* diff, UIntPtr idx); [DllImport(libgit2)] - private static unsafe extern int git_filter_register( - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + internal static extern int git_filter_register( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, IntPtr gitFilter, int priority); [DllImport(libgit2)] - private static extern unsafe int git_filter_unregister( - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + internal static extern int git_filter_unregister( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] internal static extern unsafe int git_filter_source_mode(git_filter_source* source); @@ -615,8 +610,8 @@ private static extern unsafe int git_filter_unregister( // git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, int level, const char *path) [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - private static unsafe extern int git_libgit2_opts(int option, uint level, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* path); + internal static extern int git_libgit2_opts(int option, 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)] @@ -633,23 +628,23 @@ internal static extern unsafe int git_graph_descendant_of( ref GitOid ancestor); [DllImport(libgit2)] - private static extern unsafe int git_ignore_add_rule( + internal static extern unsafe int git_ignore_add_rule( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* rules); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string rules); [DllImport(libgit2)] internal static extern unsafe int git_ignore_clear_internal_rules(git_repository* repo); [DllImport(libgit2)] - private static extern unsafe int git_ignore_path_is_ignored( + internal static extern unsafe int git_ignore_path_is_ignored( out int ignored, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* path); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); [DllImport(libgit2)] - private static extern unsafe int git_index_add_bypath( + internal static extern unsafe int git_index_add_bypath( git_index* index, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* path); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path); [DllImport(libgit2)] internal static extern unsafe int git_index_add( @@ -657,12 +652,12 @@ internal static extern unsafe int git_index_add( git_index_entry* entry); [DllImport(libgit2)] - private static extern unsafe int git_index_conflict_get( + internal static extern unsafe int git_index_conflict_get( out git_index_entry* ancestor, out git_index_entry* ours, out git_index_entry* theirs, git_index* index, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* path); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); [DllImport(libgit2)] internal static extern unsafe int git_index_conflict_iterator_new( @@ -693,9 +688,9 @@ internal static extern unsafe void git_index_conflict_iterator_free( internal static extern unsafe git_index_entry* git_index_get_byindex(git_index* index, UIntPtr n); [DllImport(libgit2)] - private static extern unsafe git_index_entry* git_index_get_bypath( + internal static extern unsafe git_index_entry* git_index_get_bypath( git_index* index, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path, int stage); [DllImport(libgit2)] @@ -708,9 +703,9 @@ internal static extern unsafe void git_index_conflict_iterator_free( internal static extern unsafe git_index_name_entry* git_index_name_get_byindex(git_index* handle, UIntPtr n); [DllImport(libgit2)] - private static extern unsafe int git_index_open( + internal static extern unsafe int git_index_open( out git_index* index, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* indexpath); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath indexpath); [DllImport(libgit2)] internal static extern unsafe int git_index_read( @@ -718,10 +713,9 @@ internal static extern unsafe int git_index_read( [MarshalAs(UnmanagedType.Bool)] bool force); [DllImport(libgit2)] - private static extern unsafe int git_index_remove_bypath( + internal static extern unsafe int git_index_remove_bypath( git_index* index, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* path); - + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); [DllImport(libgit2)] internal static extern unsafe UIntPtr git_index_reuc_entrycount(git_index* handle); @@ -730,9 +724,9 @@ private static extern unsafe int git_index_remove_bypath( internal static extern unsafe git_index_reuc_entry* git_index_reuc_get_byindex(git_index* handle, UIntPtr n); [DllImport(libgit2)] - private static extern unsafe git_index_reuc_entry* git_index_reuc_get_bypath( + internal static extern unsafe git_index_reuc_entry* git_index_reuc_get_bypath( git_index* handle, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* path); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); [DllImport(libgit2)] internal static extern unsafe int git_index_write(git_index* index); @@ -770,18 +764,18 @@ internal static extern unsafe int git_annotated_commit_from_ref( git_reference* reference); [DllImport(libgit2)] - private static extern unsafe int git_annotated_commit_from_fetchhead( + internal static extern unsafe int git_annotated_commit_from_fetchhead( out git_annotated_commit* annotatedCommit, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* branch_name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* remote_url, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string branch_name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote_url, ref GitOid oid); [DllImport(libgit2)] - private static extern unsafe int git_annotated_commit_from_revspec( + internal static extern unsafe int git_annotated_commit_from_revspec( out git_annotated_commit* annotatedCommit, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* revspec); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string revspec); [DllImport(libgit2)] internal static extern unsafe int git_annotated_commit_lookup( @@ -821,44 +815,44 @@ internal static extern unsafe int git_merge_analysis( internal static extern unsafe void git_annotated_commit_free(git_annotated_commit* commit); [DllImport(libgit2)] - private static unsafe extern int git_message_prettify( + internal static extern int git_message_prettify( GitBuf buf, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* message, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, [MarshalAs(UnmanagedType.Bool)] bool strip_comments, sbyte comment_char); [DllImport(libgit2)] - private static extern unsafe int git_note_create( + internal static extern unsafe int git_note_create( out GitOid noteOid, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* notes_ref, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string notes_ref, git_signature* author, git_signature* committer, ref GitOid oid, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* note, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string note, int force); [DllImport(libgit2)] internal static extern unsafe void git_note_free(git_note* note); - [DllImport(libgit2, EntryPoint = "git_note_message")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_note_message_(git_note* note); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_note_message(git_note* note); [DllImport(libgit2)] internal static extern unsafe git_oid* git_note_id(git_note* note); [DllImport(libgit2)] - private static extern unsafe int git_note_read( + internal static extern unsafe int git_note_read( out git_note* note, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* notes_ref, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string notes_ref, ref GitOid oid); [DllImport(libgit2)] - private static extern unsafe int git_note_remove( + internal static extern unsafe int git_note_remove( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* notes_ref, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string notes_ref, git_signature* author, git_signature* committer, ref GitOid oid); @@ -874,9 +868,9 @@ internal delegate int git_note_foreach_cb( IntPtr payload); [DllImport(libgit2)] - private static extern unsafe int git_note_foreach( + internal static extern unsafe int git_note_foreach( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* notes_ref, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string notes_ref, git_note_foreach_cb cb, IntPtr payload); @@ -967,10 +961,10 @@ internal static extern unsafe int git_patch_line_stats( internal static extern unsafe void git_packbuilder_free(git_packbuilder* packbuilder); [DllImport(libgit2)] - private static extern unsafe int git_packbuilder_insert( + internal static extern unsafe int git_packbuilder_insert( git_packbuilder* packbuilder, ref GitOid id, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] internal static extern unsafe int git_packbuilder_insert_commit( @@ -978,10 +972,10 @@ internal static extern unsafe int git_packbuilder_insert_commit( ref GitOid id); [DllImport(libgit2)] - private static extern unsafe int git_packbuilder_insert_recur( + internal static extern unsafe int git_packbuilder_insert_recur( git_packbuilder* packbuilder, ref GitOid id, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] internal static extern unsafe int git_packbuilder_insert_tree( @@ -998,9 +992,9 @@ internal static extern unsafe int git_packbuilder_insert_tree( internal static extern unsafe UInt32 git_packbuilder_set_threads(git_packbuilder* packbuilder, UInt32 numThreads); [DllImport(libgit2)] - private static extern unsafe int git_packbuilder_write( + internal static extern unsafe int git_packbuilder_write( git_packbuilder* packbuilder, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, uint mode, IntPtr progressCallback, IntPtr payload); @@ -1009,31 +1003,31 @@ private static extern unsafe int git_packbuilder_write( internal static extern unsafe UIntPtr git_packbuilder_written(git_packbuilder* packbuilder); [DllImport(libgit2)] - private static extern unsafe int git_reference_create( + internal static extern unsafe int git_reference_create( out git_reference* reference, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, ref GitOid oid, [MarshalAs(UnmanagedType.Bool)] bool force, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* log_message); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); [DllImport(libgit2)] - private static extern unsafe int git_reference_symbolic_create( + internal static extern unsafe int git_reference_symbolic_create( out git_reference* reference, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* target, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string target, [MarshalAs(UnmanagedType.Bool)] bool force, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* log_message); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); internal delegate int ref_glob_callback( IntPtr reference_name, IntPtr payload); [DllImport(libgit2)] - private static extern unsafe int git_reference_foreach_glob( + internal static extern unsafe int git_reference_foreach_glob( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* glob, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string glob, ref_glob_callback callback, IntPtr payload); @@ -1041,72 +1035,72 @@ private static extern unsafe int git_reference_foreach_glob( internal static extern unsafe void git_reference_free(git_reference* reference); [DllImport(libgit2)] - private static unsafe extern int git_reference_is_valid_name( - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* refname); + internal static extern int git_reference_is_valid_name( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refname); [DllImport(libgit2)] internal static extern unsafe int git_reference_list(out GitStrArray array, git_repository* repo); [DllImport(libgit2)] - private static extern unsafe int git_reference_lookup( + internal static extern unsafe int git_reference_lookup( out git_reference* reference, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2, EntryPoint = "git_reference_name")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_reference_name_(git_reference* reference); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_reference_name(git_reference* reference); [DllImport(libgit2)] - private static extern unsafe int git_reference_remove( + internal static extern unsafe int git_reference_remove( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] internal static extern unsafe git_oid* git_reference_target(git_reference* reference); [DllImport(libgit2)] - private static extern unsafe int git_reference_rename( + internal static extern unsafe int git_reference_rename( out git_reference* ref_out, git_reference* reference, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* newName, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string newName, [MarshalAs(UnmanagedType.Bool)] bool force, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* log_message); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); [DllImport(libgit2)] - private static extern unsafe int git_reference_set_target( + internal static extern unsafe int git_reference_set_target( out git_reference* ref_out, git_reference* reference, ref GitOid id, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* log_message); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); [DllImport(libgit2)] - private static extern unsafe int git_reference_symbolic_set_target( + internal static extern unsafe int git_reference_symbolic_set_target( out git_reference* ref_out, git_reference* reference, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* target, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* log_message); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string target, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); - [DllImport(libgit2, EntryPoint = "git_reference_symbolic_target")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_reference_symbolic_target_(git_reference* reference); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_reference_symbolic_target(git_reference* reference); [DllImport(libgit2)] internal static extern unsafe GitReferenceType git_reference_type(git_reference* reference); [DllImport(libgit2)] - private static extern unsafe int git_reference_ensure_log( + internal static extern unsafe int git_reference_ensure_log( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* refname); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refname); [DllImport(libgit2)] internal static extern unsafe void git_reflog_free(git_reflog* reflog); [DllImport(libgit2)] - private static extern unsafe int git_reflog_read( + internal static extern unsafe int git_reflog_read( out git_reflog* ref_out, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] internal static extern unsafe UIntPtr git_reflog_entrycount @@ -1129,53 +1123,53 @@ internal static extern unsafe UIntPtr git_reflog_entrycount internal static extern unsafe git_signature* git_reflog_entry_committer( git_reflog_entry* entry); - [DllImport(libgit2, EntryPoint = "git_reflog_entry_message")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_reflog_entry_message_(git_reflog_entry* entry); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_reflog_entry_message(git_reflog_entry* entry); [DllImport(libgit2)] - private static unsafe extern int git_refspec_transform( + internal static extern int git_refspec_transform( GitBuf buf, IntPtr refspec, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] - private static unsafe extern int git_refspec_rtransform( + internal static extern int git_refspec_rtransform( GitBuf buf, IntPtr refspec, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2, EntryPoint = "git_refspec_string")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_refspec_string_( + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern string git_refspec_string( IntPtr refSpec); [DllImport(libgit2)] - internal static extern unsafe RefSpecDirection git_refspec_direction(IntPtr refSpec); + internal static extern RefSpecDirection git_refspec_direction(IntPtr refSpec); - [DllImport(libgit2, EntryPoint = "git_refspec_dst")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_refspec_dst_( + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern string git_refspec_dst( IntPtr refSpec); - [DllImport(libgit2, EntryPoint = "git_refspec_src")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_refspec_src_( + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern string git_refspec_src( IntPtr refspec); [DllImport(libgit2)] internal static extern bool git_refspec_force(IntPtr refSpec); [DllImport(libgit2)] - private static extern unsafe bool git_refspec_src_matches( + internal static extern bool git_refspec_src_matches( IntPtr refspec, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* reference); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string reference); [DllImport(libgit2)] - private static extern unsafe bool git_refspec_dst_matches( + internal static extern bool git_refspec_dst_matches( IntPtr refspec, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* reference); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string reference); [DllImport(libgit2)] internal static extern unsafe int git_remote_autotag(git_remote* remote); @@ -1189,38 +1183,38 @@ internal static extern unsafe int git_remote_connect( ref GitStrArray custom_headers); [DllImport(libgit2)] - private static extern unsafe int git_remote_create( + internal static extern unsafe int git_remote_create( out git_remote* remote, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* url); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); [DllImport(libgit2)] - private static extern unsafe int git_remote_create_anonymous( + internal static extern unsafe int git_remote_create_anonymous( out git_remote* remote, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* url); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); [DllImport(libgit2)] - private static extern unsafe int git_remote_create_with_fetchspec( + internal static extern unsafe int git_remote_create_with_fetchspec( out git_remote* remote, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* url, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* refspec); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refspec); [DllImport(libgit2)] - private static extern unsafe int git_remote_delete( + internal static extern unsafe int git_remote_delete( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] - private static extern unsafe int git_remote_fetch( + internal static extern unsafe int git_remote_fetch( git_remote* remote, ref GitStrArray refspecs, GitFetchOptions fetch_opts, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* log_message); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); [DllImport(libgit2)] internal static extern unsafe void git_remote_free(git_remote* remote); @@ -1244,61 +1238,61 @@ internal static extern unsafe int git_remote_push( internal static extern unsafe UIntPtr git_remote_refspec_count(git_remote* remote); [DllImport(libgit2)] - private static extern unsafe int git_remote_set_url( + internal static extern unsafe int git_remote_set_url( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* remote, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* url); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); [DllImport(libgit2)] - private static extern unsafe int git_remote_add_fetch( + internal static extern unsafe int git_remote_add_fetch( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* remote, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* url); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); [DllImport(libgit2)] - private static extern unsafe int git_remote_set_pushurl( + internal static extern unsafe int git_remote_set_pushurl( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* remote, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* url); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); [DllImport(libgit2)] - private static extern unsafe int git_remote_add_push( + internal static extern unsafe int git_remote_add_push( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* remote, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* url); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); [DllImport(libgit2)] - private static unsafe extern int git_remote_is_valid_name( - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* remote_name); + internal static extern int git_remote_is_valid_name( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote_name); [DllImport(libgit2)] internal static extern unsafe int git_remote_list(out GitStrArray array, git_repository* repo); [DllImport(libgit2)] - private static extern unsafe int git_remote_lookup( + internal static extern unsafe int git_remote_lookup( out git_remote* remote, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] internal static extern unsafe int git_remote_ls(out git_remote_head** heads, out UIntPtr size, git_remote* remote); - [DllImport(libgit2, EntryPoint = "git_remote_name")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_remote_name_(git_remote* remote); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_remote_name(git_remote* remote); - [DllImport(libgit2, EntryPoint = "git_remote_url")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_remote_url_(git_remote* remote); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_remote_url(git_remote* remote); - [DllImport(libgit2, EntryPoint = "git_remote_pushurl")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_remote_pushurl_(git_remote* remote); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_remote_pushurl(git_remote* remote); [DllImport(libgit2)] - private static extern unsafe void git_remote_set_autotag( + internal static extern unsafe void git_remote_set_autotag( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, TagFetchMode option); internal delegate int remote_progress_callback(IntPtr str, int len, IntPtr data); @@ -1323,11 +1317,11 @@ IntPtr data ); [DllImport(libgit2)] - private static unsafe extern int git_repository_discover( + internal static extern int git_repository_discover( GitBuf buf, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* start_path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath start_path, [MarshalAs(UnmanagedType.Bool)] bool across_fs, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* ceiling_dirs); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath ceiling_dirs); internal delegate int git_repository_fetchhead_foreach_cb( IntPtr remote_name, @@ -1346,24 +1340,24 @@ internal static extern unsafe int git_repository_fetchhead_foreach( internal static extern unsafe void git_repository_free(git_repository* repo); [DllImport(libgit2)] - internal static extern unsafe int git_repository_head_detached(IntPtr repo); + internal static extern int git_repository_head_detached(IntPtr repo); [DllImport(libgit2)] - internal static extern unsafe int git_repository_head_unborn(IntPtr repo); + internal static extern int git_repository_head_unborn(IntPtr repo); [DllImport(libgit2)] - private static extern unsafe int git_repository_ident( - [CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] out byte* name, - [CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] out byte* email, + internal static extern unsafe int git_repository_ident( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] out string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] out string email, git_repository* repo); [DllImport(libgit2)] internal static extern unsafe int git_repository_index(out git_index* index, git_repository* repo); [DllImport(libgit2)] - private static extern unsafe int git_repository_init_ext( + internal static extern unsafe int git_repository_init_ext( out git_repository* repository, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, GitRepositoryInitOptions options); [DllImport(libgit2)] @@ -1398,20 +1392,20 @@ internal static extern unsafe int git_repository_new( internal static extern unsafe int git_repository_odb(out git_odb* odb, git_repository* repo); [DllImport(libgit2)] - private static extern unsafe int git_repository_open( + internal static extern unsafe int git_repository_open( out git_repository* repository, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* path); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path); [DllImport(libgit2)] - private static extern unsafe int git_repository_open_ext( + internal static extern unsafe int git_repository_open_ext( out git_repository* repository, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* path, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, RepositoryOpenFlags flags, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* ceilingDirs); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath ceilingDirs); - [DllImport(libgit2, EntryPoint = "git_repository_path")] - [return: CustomMarshaler(typeof(LaxFilePathNoCleanupMarshaler), typeof(FilePath))] - private static extern unsafe byte* git_repository_path_(git_repository* repository); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))] + internal static extern unsafe FilePath git_repository_path(git_repository* repository); [DllImport(libgit2)] internal static extern unsafe void git_repository_set_config( @@ -1419,10 +1413,10 @@ internal static extern unsafe void git_repository_set_config( git_config* config); [DllImport(libgit2)] - private static extern unsafe int git_repository_set_ident( + internal static extern unsafe int git_repository_set_ident( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* email); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string email); [DllImport(libgit2)] @@ -1431,9 +1425,9 @@ internal static extern unsafe void git_repository_set_index( git_index* index); [DllImport(libgit2)] - private static extern unsafe int git_repository_set_workdir( + internal static extern unsafe int git_repository_set_workdir( git_repository* repository, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* workdir, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath workdir, [MarshalAs(UnmanagedType.Bool)] bool update_gitlink); [DllImport(libgit2)] @@ -1447,21 +1441,21 @@ internal static extern unsafe int git_repository_set_head_detached_from_annotate git_annotated_commit* commit); [DllImport(libgit2)] - private static extern unsafe int git_repository_set_head( + internal static extern unsafe int git_repository_set_head( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* refname); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refname); [DllImport(libgit2)] internal static extern unsafe int git_repository_state( git_repository* repository); - [DllImport(libgit2, EntryPoint = "git_repository_workdir")] - [return: CustomMarshaler(typeof(LaxFilePathNoCleanupMarshaler), typeof(FilePath))] - private static extern unsafe byte* git_repository_workdir_(git_repository* repository); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))] + internal static extern unsafe FilePath git_repository_workdir(git_repository* repository); - [DllImport(libgit2, EntryPoint = "git_repository_workdir")] - [return: CustomMarshaler(typeof(LaxFilePathNoCleanupMarshaler), typeof(FilePath))] - private static extern unsafe byte* git_repository_workdir_(IntPtr repository); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))] + internal static extern FilePath git_repository_workdir(IntPtr repository); [DllImport(libgit2)] internal static extern unsafe int git_reset( @@ -1486,11 +1480,11 @@ internal static extern unsafe int git_revert_commit( ref GitMergeOpts opts); [DllImport(libgit2)] - private static extern unsafe int git_revparse_ext( + internal static extern unsafe int git_revparse_ext( out git_object* obj, out git_reference* reference, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* spec); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string spec); [DllImport(libgit2)] internal static extern unsafe void git_revwalk_free(git_revwalk* walker); @@ -1520,28 +1514,28 @@ private static extern unsafe int git_revparse_ext( internal static extern unsafe void git_signature_free(git_signature* signature); [DllImport(libgit2)] - private static extern unsafe int git_signature_new( + internal static extern unsafe int git_signature_new( out git_signature* signature, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* email, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string email, long time, int offset); [DllImport(libgit2)] - private static extern unsafe int git_signature_now( + internal static extern unsafe int git_signature_now( out git_signature* signature, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* email); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string email); [DllImport(libgit2)] internal static extern unsafe int git_signature_dup(out git_signature* dest, git_signature* sig); [DllImport(libgit2)] - private static extern unsafe int git_stash_save( + internal static extern unsafe int git_stash_save( out GitOid id, git_repository* repo, git_signature* stasher, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* message, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, StashModifiers flags); internal delegate int git_stash_cb( @@ -1572,10 +1566,10 @@ internal static extern unsafe int git_stash_pop( GitStashApplyOpts opts); [DllImport(libgit2)] - private static extern unsafe int git_status_file( + internal static extern unsafe int git_status_file( out FileStatus statusflags, git_repository* repo, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* filepath); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath filepath); [DllImport(libgit2)] @@ -1602,16 +1596,16 @@ internal static extern void git_strarray_free( ref GitStrArray array); [DllImport(libgit2)] - private static extern unsafe int git_submodule_lookup( + internal static extern unsafe int git_submodule_lookup( out git_submodule* reference, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); [DllImport(libgit2)] - private static extern unsafe int git_submodule_resolve_url( + internal static extern unsafe int git_submodule_resolve_url( GitBuf buf, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* url); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); [DllImport(libgit2)] internal static extern unsafe int git_submodule_update( @@ -1638,14 +1632,14 @@ internal static extern unsafe int git_submodule_add_to_index( [DllImport(libgit2)] internal static extern unsafe void git_submodule_free(git_submodule* submodule); - [DllImport(libgit2, EntryPoint = "git_submodule_path")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_submodule_path_( + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_submodule_path( git_submodule* submodule); - [DllImport(libgit2, EntryPoint = "git_submodule_url")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_submodule_url_( + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_submodule_url( git_submodule* submodule); [DllImport(libgit2)] @@ -1678,10 +1672,10 @@ internal static extern unsafe int git_submodule_reload( [MarshalAs(UnmanagedType.Bool)] bool force); [DllImport(libgit2)] - private static extern unsafe int git_submodule_status( + internal static extern unsafe int git_submodule_status( out SubmoduleStatus status, git_repository* repo, - [CustomMarshaler(typeof(StrictFilePathMarshaler), typeof(FilePath))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath name, GitSubmoduleIgnore ignore); [DllImport(libgit2)] @@ -1690,49 +1684,49 @@ internal static extern unsafe int git_submodule_init( [MarshalAs(UnmanagedType.Bool)] bool overwrite); [DllImport(libgit2)] - private static extern unsafe int git_tag_annotation_create( + internal static extern unsafe int git_tag_annotation_create( out GitOid oid, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, git_object* target, git_signature* signature, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* message); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message); [DllImport(libgit2)] - private static extern unsafe int git_tag_create( + internal static extern unsafe int git_tag_create( out GitOid oid, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, git_object* target, git_signature* signature, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* message, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, [MarshalAs(UnmanagedType.Bool)] bool force); [DllImport(libgit2)] - private static extern unsafe int git_tag_create_lightweight( + internal static extern unsafe int git_tag_create_lightweight( out GitOid oid, git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, git_object* target, [MarshalAs(UnmanagedType.Bool)] bool force); [DllImport(libgit2)] - private static extern unsafe int git_tag_delete( + internal static extern unsafe int git_tag_delete( git_repository* repo, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* tagName); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string tagName); [DllImport(libgit2)] internal static extern unsafe int git_tag_list(out GitStrArray array, git_repository* repo); - [DllImport(libgit2, EntryPoint = "git_tag_message")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_tag_message_(git_object* tag); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_tag_message(git_object* tag); - [DllImport(libgit2, EntryPoint = "git_tag_name")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_tag_name_(git_object* tag); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_tag_name(git_object* tag); [DllImport(libgit2)] internal static extern unsafe git_signature* git_tag_tagger(git_object* tag); @@ -1764,8 +1758,8 @@ private static extern unsafe int git_tag_delete( internal unsafe delegate int git_transport_certificate_check_cb(git_certificate* cert, int valid, IntPtr hostname, IntPtr payload); [DllImport(libgit2)] - private static unsafe extern int git_transport_register( - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* prefix, + internal static extern int git_transport_register( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string prefix, IntPtr transport_cb, IntPtr payload); @@ -1776,22 +1770,22 @@ internal static extern int git_transport_smart( IntPtr definition); [DllImport(libgit2)] - private static unsafe extern int git_transport_smart_certificate_check( + internal static extern int git_transport_smart_certificate_check( IntPtr transport, IntPtr cert, int valid, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* hostname); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string hostname); [DllImport(libgit2)] - private static unsafe extern int git_transport_smart_credentials( + internal static extern int git_transport_smart_credentials( out IntPtr cred_out, IntPtr transport, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* user, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string user, int methods); [DllImport(libgit2)] - private static unsafe extern int git_transport_unregister( - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* prefix); + internal static extern int git_transport_unregister( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string prefix); [DllImport(libgit2)] internal static extern unsafe uint git_tree_entry_filemode(git_tree_entry* entry); @@ -1800,10 +1794,10 @@ private static unsafe extern int git_transport_unregister( internal static extern unsafe git_tree_entry* git_tree_entry_byindex(git_object* tree, UIntPtr idx); [DllImport(libgit2)] - private static extern unsafe int git_tree_entry_bypath( + internal static extern unsafe int git_tree_entry_bypath( out git_tree_entry* tree, git_object* root, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* treeentry_path); + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string treeentry_path); [DllImport(libgit2)] internal static extern unsafe void git_tree_entry_free(git_tree_entry* treeEntry); @@ -1811,9 +1805,9 @@ private static extern unsafe int git_tree_entry_bypath( [DllImport(libgit2)] internal static extern unsafe git_oid* git_tree_entry_id(git_tree_entry* entry); - [DllImport(libgit2, EntryPoint = "git_tree_entry_name")] - [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] - private static extern unsafe byte* git_tree_entry_name_(git_tree_entry* entry); + [DllImport(libgit2)] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] + internal static extern unsafe string git_tree_entry_name(git_tree_entry* entry); [DllImport(libgit2)] internal static extern unsafe GitObjectType git_tree_entry_type(git_tree_entry* entry); @@ -1825,10 +1819,10 @@ private static extern unsafe int git_tree_entry_bypath( internal static extern unsafe int git_treebuilder_new(out git_treebuilder* builder, git_repository* repo, IntPtr src); [DllImport(libgit2)] - private static extern unsafe int git_treebuilder_insert( + internal static extern unsafe int git_treebuilder_insert( IntPtr entry_out, git_treebuilder* builder, - [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* treeentry_name, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string treeentry_name, ref GitOid id, uint attributes); diff --git a/LibGit2Sharp/Core/Utf8Marshaler.cs b/LibGit2Sharp/Core/Utf8Marshaler.cs index 53e14f4ec..a6fddb808 100644 --- a/LibGit2Sharp/Core/Utf8Marshaler.cs +++ b/LibGit2Sharp/Core/Utf8Marshaler.cs @@ -11,13 +11,15 @@ namespace LibGit2Sharp.Core /// free the native pointer after conversion, because the memory is owned by libgit2. /// /// Use this marshaler for return values, for example: - /// [return: CustomMarshaler(typeof(LaxUtf8NoCleanupMarshaler), typeof(string))] + /// [return: MarshalAs(UnmanagedType.CustomMarshaler, + /// MarshalCookie = UniqueId.UniqueIdentifier, + /// MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] /// internal class LaxUtf8NoCleanupMarshaler : LaxUtf8Marshaler { private static readonly LaxUtf8NoCleanupMarshaler staticInstance = new LaxUtf8NoCleanupMarshaler(); - public new static ICustomMarshaler GetInstance() + public new static ICustomMarshaler GetInstance(string cookie) { return staticInstance; } @@ -39,9 +41,10 @@ public override void CleanUpNativeData(IntPtr pNativeData) /// /// Use this marshaler for function parameters, for example: /// [DllImport(libgit2)] - /// private static extern unsafe int git_tag_delete( - /// git_repository* repo, - /// [CustomMarshaler(typeof(StrictUtf8Marshaler), typeof(string))] byte* tagName); + /// internal static extern int git_tag_delete(RepositorySafeHandle repo, + /// [MarshalAs(UnmanagedType.CustomMarshaler + /// MarshalCookie = UniqueId.UniqueIdentifier, + /// MarshalTypeRef = typeof(StrictUtf8Marshaler))] String tagName); /// internal class StrictUtf8Marshaler : EncodingMarshaler { @@ -57,7 +60,7 @@ static StrictUtf8Marshaler() public StrictUtf8Marshaler() : base(encoding) { } - public static ICustomMarshaler GetInstance() + public static ICustomMarshaler GetInstance(string cookie) { return staticInstance; } @@ -93,7 +96,7 @@ internal class LaxUtf8Marshaler : EncodingMarshaler public LaxUtf8Marshaler() : base(Encoding) { } - public static ICustomMarshaler GetInstance() + public static ICustomMarshaler GetInstance(string cookie) { return staticInstance; } From 8a480bc1e95e7d07786f6b2903c198902c8f7765 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 1 Aug 2017 23:50:46 -0400 Subject: [PATCH 010/384] Remove unneeded conditional compilation --- .../AmbiguousSpecificationException.cs | 7 -- LibGit2Sharp/BareRepositoryException.cs | 6 -- LibGit2Sharp/BufferedStream.cs | 96 ------------------- LibGit2Sharp/CheckoutConflictException.cs | 6 -- LibGit2Sharp/Core/Handles/Libgit2Object.cs | 12 +-- LibGit2Sharp/Core/Proxy.cs | 7 +- LibGit2Sharp/EmptyCommitException.cs | 6 -- LibGit2Sharp/EntryExistsException.cs | 6 -- LibGit2Sharp/ICustomMarshaler.cs | 21 ---- LibGit2Sharp/InvalidSpecificationException.cs | 6 -- LibGit2Sharp/LibGit2SharpException.cs | 6 -- LibGit2Sharp/LockedFileException.cs | 6 -- .../MergeFetchHeadNotFoundException.cs | 6 -- LibGit2Sharp/NameConflictException.cs | 6 -- LibGit2Sharp/NonFastForwardException.cs | 6 -- LibGit2Sharp/NotFoundException.cs | 6 -- LibGit2Sharp/PeelException.cs | 6 -- LibGit2Sharp/PortableShims.cs | 19 ---- LibGit2Sharp/RecurseSubmodulesException.cs | 6 -- LibGit2Sharp/RemoveFromIndexException.cs | 6 -- LibGit2Sharp/RepositoryNotFoundException.cs | 6 -- .../SecureUsernamePasswordCredentials.cs | 4 - LibGit2Sharp/SmartSubtransportRegistration.cs | 2 +- LibGit2Sharp/UnbornBranchException.cs | 7 -- LibGit2Sharp/UnmatchedPathException.cs | 6 -- LibGit2Sharp/UnmergedIndexEntriesException.cs | 6 -- LibGit2Sharp/UserCanceledException.cs | 6 -- LibGit2Sharp/Version.cs | 2 +- 28 files changed, 4 insertions(+), 281 deletions(-) delete mode 100644 LibGit2Sharp/BufferedStream.cs delete mode 100644 LibGit2Sharp/ICustomMarshaler.cs delete mode 100644 LibGit2Sharp/PortableShims.cs diff --git a/LibGit2Sharp/AmbiguousSpecificationException.cs b/LibGit2Sharp/AmbiguousSpecificationException.cs index 0eece24ee..1d19bbfde 100644 --- a/LibGit2Sharp/AmbiguousSpecificationException.cs +++ b/LibGit2Sharp/AmbiguousSpecificationException.cs @@ -1,17 +1,12 @@ using System; -using System.Globalization; -#if DESKTOP using System.Runtime.Serialization; -#endif namespace LibGit2Sharp { /// /// The exception that is thrown when the provided specification cannot uniquely identify a reference, an object or a path. /// -#if DESKTOP [Serializable] -#endif public class AmbiguousSpecificationException : LibGit2SharpException { /// @@ -47,7 +42,6 @@ public AmbiguousSpecificationException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -56,6 +50,5 @@ public AmbiguousSpecificationException(string message, Exception innerException) protected AmbiguousSpecificationException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif } } diff --git a/LibGit2Sharp/BareRepositoryException.cs b/LibGit2Sharp/BareRepositoryException.cs index 7954867f7..75ad9695c 100644 --- a/LibGit2Sharp/BareRepositoryException.cs +++ b/LibGit2Sharp/BareRepositoryException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -10,9 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown when an operation which requires a /// working directory is performed against a bare repository. /// -#if DESKTOP [Serializable] -#endif public class BareRepositoryException : LibGit2SharpException { /// @@ -47,7 +43,6 @@ public BareRepositoryException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -56,7 +51,6 @@ public BareRepositoryException(string message, Exception innerException) protected BareRepositoryException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal BareRepositoryException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/BufferedStream.cs b/LibGit2Sharp/BufferedStream.cs deleted file mode 100644 index 6b6a58052..000000000 --- a/LibGit2Sharp/BufferedStream.cs +++ /dev/null @@ -1,96 +0,0 @@ -#if NETSTANDARD1_3 - -namespace LibGit2Sharp -{ - using Core; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text; - using System.Threading.Tasks; - - /// - /// A cheap substitute for the .NET BufferedStream class that isn't available on portable profiles. - /// - internal class BufferedStream : Stream - { - private int bufferSize; - private Stream targetStream; - private MemoryStream bufferStream; - - public BufferedStream(Stream targetStream, int bufferSize) - { - Ensure.ArgumentNotNull(targetStream, nameof(targetStream)); - - this.targetStream = targetStream; - this.bufferSize = bufferSize; - this.bufferStream = new MemoryStream(bufferSize); - } - - public override bool CanRead => false; // this implementation only supports writing. - - public override bool CanSeek => false; - - public override bool CanWrite => this.targetStream.CanWrite; - - public override long Length - { - get { throw new NotImplementedException(); } - } - - public override long Position - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - public override void Flush() - { - if (this.bufferStream.Length > 0) - { - this.bufferStream.Position = 0; - this.bufferStream.CopyTo(this.targetStream, this.bufferSize); - this.bufferStream.Position = 0; - this.bufferStream.SetLength(0); - } - } - - public override int Read(byte[] buffer, int offset, int count) - { - throw new NotImplementedException(); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - this.bufferStream.Write(buffer, offset, count); - if (this.bufferStream.Length > this.bufferSize) - { - this.Flush(); - } - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - this.Flush(); - this.targetStream.Dispose(); - } - - base.Dispose(disposing); - } - } -} - -#endif diff --git a/LibGit2Sharp/CheckoutConflictException.cs b/LibGit2Sharp/CheckoutConflictException.cs index 8480ccf60..a06360afb 100644 --- a/LibGit2Sharp/CheckoutConflictException.cs +++ b/LibGit2Sharp/CheckoutConflictException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -11,9 +9,7 @@ namespace LibGit2Sharp /// because of a conflicting change staged in the index, or unstaged /// in the working directory. /// -#if DESKTOP [Serializable] -#endif public class CheckoutConflictException : LibGit2SharpException { /// @@ -48,7 +44,6 @@ public CheckoutConflictException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -61,6 +56,5 @@ protected CheckoutConflictException(SerializationInfo info, StreamingContext con internal CheckoutConflictException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) { } -#endif } } diff --git a/LibGit2Sharp/Core/Handles/Libgit2Object.cs b/LibGit2Sharp/Core/Handles/Libgit2Object.cs index 5d5dc5459..8b255a3f0 100644 --- a/LibGit2Sharp/Core/Handles/Libgit2Object.cs +++ b/LibGit2Sharp/Core/Handles/Libgit2Object.cs @@ -106,18 +106,8 @@ internal unsafe Libgit2Object(void* handle, bool owned) #if LEAKS_TRACKING id = Guid.NewGuid(); Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Allocating {0} handle ({1})", GetType().Name, id)); -#if DESKTOP + trace = new StackTrace(2, true).ToString(); -#else - try - { - throw new Exception(); - } - catch (Exception ex) - { - trace = new StackTrace(ex, true).ToString(); - } -#endif #endif } diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index c46d5fc1e..02ae4a1c5 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -1603,12 +1603,7 @@ public static unsafe ObjectId git_odb_write(ObjectDatabaseHandle odb, byte[] dat int res; fixed(byte* p = data) { -#if DESKTOP - UIntPtr len = new UIntPtr((ulong)data.LongLength); -#else - UIntPtr len = new UIntPtr((uint)data.Length); -#endif - res = NativeMethods.git_odb_write(out id, odb, p, len, type.ToGitObjectType()); + res = NativeMethods.git_odb_write(out id, odb, p, new UIntPtr((ulong)data.LongLength), type.ToGitObjectType()); } Ensure.ZeroResult(res); diff --git a/LibGit2Sharp/EmptyCommitException.cs b/LibGit2Sharp/EmptyCommitException.cs index b5e96a66b..8cd48e49f 100644 --- a/LibGit2Sharp/EmptyCommitException.cs +++ b/LibGit2Sharp/EmptyCommitException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif namespace LibGit2Sharp { @@ -9,9 +7,7 @@ namespace LibGit2Sharp /// The exception that is thrown when a commit would create an "empty" /// commit that is treesame to its parent without an explicit override. /// -#if DESKTOP [Serializable] -#endif public class EmptyCommitException : LibGit2SharpException { /// @@ -46,7 +42,6 @@ public EmptyCommitException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -55,6 +50,5 @@ public EmptyCommitException(string message, Exception innerException) protected EmptyCommitException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif } } diff --git a/LibGit2Sharp/EntryExistsException.cs b/LibGit2Sharp/EntryExistsException.cs index d8a5208f9..2c46e4acd 100644 --- a/LibGit2Sharp/EntryExistsException.cs +++ b/LibGit2Sharp/EntryExistsException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -9,9 +7,7 @@ namespace LibGit2Sharp /// /// The exception that is thrown attempting to create a resource that already exists. /// -#if DESKTOP [Serializable] -#endif public class EntryExistsException : LibGit2SharpException { /// @@ -46,7 +42,6 @@ public EntryExistsException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -55,7 +50,6 @@ public EntryExistsException(string message, Exception innerException) protected EntryExistsException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal EntryExistsException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/ICustomMarshaler.cs b/LibGit2Sharp/ICustomMarshaler.cs deleted file mode 100644 index 29cfec215..000000000 --- a/LibGit2Sharp/ICustomMarshaler.cs +++ /dev/null @@ -1,21 +0,0 @@ -#if NETSTANDARD1_3 - -using System; - -namespace LibGit2Sharp -{ - internal interface ICustomMarshaler - { - Object MarshalNativeToManaged(IntPtr pNativeData); - - IntPtr MarshalManagedToNative(Object ManagedObj); - - void CleanUpNativeData(IntPtr pNativeData); - - void CleanUpManagedData(Object ManagedObj); - - int GetNativeDataSize(); - } -} - -#endif diff --git a/LibGit2Sharp/InvalidSpecificationException.cs b/LibGit2Sharp/InvalidSpecificationException.cs index f3374e9e2..64654852c 100644 --- a/LibGit2Sharp/InvalidSpecificationException.cs +++ b/LibGit2Sharp/InvalidSpecificationException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -12,9 +10,7 @@ namespace LibGit2Sharp /// if the spec refers to an object of an incorrect type (e.g. asking to /// create a branch from a blob, or peeling a blob to a commit). /// -#if DESKTOP [Serializable] -#endif public class InvalidSpecificationException : LibGit2SharpException { /// @@ -49,7 +45,6 @@ public InvalidSpecificationException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -58,7 +53,6 @@ public InvalidSpecificationException(string message, Exception innerException) protected InvalidSpecificationException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal InvalidSpecificationException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/LibGit2SharpException.cs b/LibGit2Sharp/LibGit2SharpException.cs index 1fcf1a3ae..e85dd638f 100644 --- a/LibGit2Sharp/LibGit2SharpException.cs +++ b/LibGit2Sharp/LibGit2SharpException.cs @@ -1,8 +1,6 @@ using System; using System.Globalization; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -10,9 +8,7 @@ namespace LibGit2Sharp /// /// The exception that is thrown when an error occurs during application execution. /// -#if DESKTOP [Serializable] -#endif public class LibGit2SharpException : Exception { /// @@ -48,7 +44,6 @@ public LibGit2SharpException(string format, params object[] args) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -57,7 +52,6 @@ public LibGit2SharpException(string format, params object[] args) protected LibGit2SharpException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal LibGit2SharpException(string message, GitErrorCode code, GitErrorCategory category) : this(message) { diff --git a/LibGit2Sharp/LockedFileException.cs b/LibGit2Sharp/LockedFileException.cs index 6a327b620..05859503a 100644 --- a/LibGit2Sharp/LockedFileException.cs +++ b/LibGit2Sharp/LockedFileException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -9,9 +7,7 @@ namespace LibGit2Sharp /// /// The exception that is thrown attempting to open a locked file. /// -#if DESKTOP [Serializable] -#endif public class LockedFileException : LibGit2SharpException { /// @@ -46,7 +42,6 @@ public LockedFileException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -55,7 +50,6 @@ public LockedFileException(string message, Exception innerException) protected LockedFileException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal LockedFileException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/MergeFetchHeadNotFoundException.cs b/LibGit2Sharp/MergeFetchHeadNotFoundException.cs index 17393a38f..a86bf5caf 100644 --- a/LibGit2Sharp/MergeFetchHeadNotFoundException.cs +++ b/LibGit2Sharp/MergeFetchHeadNotFoundException.cs @@ -1,16 +1,12 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif namespace LibGit2Sharp { /// /// The exception that is thrown when the ref to merge with was as part of a pull operation not fetched. /// -#if DESKTOP [Serializable] -#endif public class MergeFetchHeadNotFoundException : NotFoundException { /// @@ -45,7 +41,6 @@ public MergeFetchHeadNotFoundException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -54,6 +49,5 @@ public MergeFetchHeadNotFoundException(string message, Exception innerException) protected MergeFetchHeadNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif } } diff --git a/LibGit2Sharp/NameConflictException.cs b/LibGit2Sharp/NameConflictException.cs index 88415c225..815415729 100644 --- a/LibGit2Sharp/NameConflictException.cs +++ b/LibGit2Sharp/NameConflictException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -9,9 +7,7 @@ namespace LibGit2Sharp /// /// The exception that is thrown when a reference, a remote, a submodule... with the same name already exists in the repository /// -#if DESKTOP [Serializable] -#endif public class NameConflictException : LibGit2SharpException { /// @@ -46,7 +42,6 @@ public NameConflictException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -55,7 +50,6 @@ public NameConflictException(string message, Exception innerException) protected NameConflictException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal NameConflictException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/NonFastForwardException.cs b/LibGit2Sharp/NonFastForwardException.cs index e01ef0bb4..487e8fd03 100644 --- a/LibGit2Sharp/NonFastForwardException.cs +++ b/LibGit2Sharp/NonFastForwardException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -10,9 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown when push cannot be performed /// against the remote without losing commits. /// -#if DESKTOP [Serializable] -#endif public class NonFastForwardException : LibGit2SharpException { /// @@ -47,7 +43,6 @@ public NonFastForwardException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -56,7 +51,6 @@ public NonFastForwardException(string message, Exception innerException) protected NonFastForwardException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal NonFastForwardException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/NotFoundException.cs b/LibGit2Sharp/NotFoundException.cs index 82015a7f1..0e9b45bf3 100644 --- a/LibGit2Sharp/NotFoundException.cs +++ b/LibGit2Sharp/NotFoundException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -9,9 +7,7 @@ namespace LibGit2Sharp /// /// The exception that is thrown attempting to reference a resource that does not exist. /// -#if DESKTOP [Serializable] -#endif public class NotFoundException : LibGit2SharpException { /// @@ -46,7 +42,6 @@ public NotFoundException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -55,7 +50,6 @@ public NotFoundException(string message, Exception innerException) protected NotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal NotFoundException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/PeelException.cs b/LibGit2Sharp/PeelException.cs index 21d81a4c4..09d6bdcc8 100644 --- a/LibGit2Sharp/PeelException.cs +++ b/LibGit2Sharp/PeelException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -10,9 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown when a tag cannot be peeled to the /// target type due to the object model. /// -#if DESKTOP [Serializable] -#endif public class PeelException : LibGit2SharpException { /// @@ -47,7 +43,6 @@ public PeelException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -56,7 +51,6 @@ public PeelException(string message, Exception innerException) protected PeelException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal PeelException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/PortableShims.cs b/LibGit2Sharp/PortableShims.cs deleted file mode 100644 index 220bbf642..000000000 --- a/LibGit2Sharp/PortableShims.cs +++ /dev/null @@ -1,19 +0,0 @@ -#if DESKTOP - -using System; - -namespace LibGit2Sharp -{ - /// - /// Allows portable-compatible code that uses GetTypeInfo() to compile and work on net40. - /// - internal static class PortableShims - { - /// - /// Returns the specified type. - /// - internal static Type GetTypeInfo(this Type type) => type; - } -} - -#endif diff --git a/LibGit2Sharp/RecurseSubmodulesException.cs b/LibGit2Sharp/RecurseSubmodulesException.cs index 3499519dd..cf4479701 100644 --- a/LibGit2Sharp/RecurseSubmodulesException.cs +++ b/LibGit2Sharp/RecurseSubmodulesException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif namespace LibGit2Sharp { @@ -10,9 +8,7 @@ namespace LibGit2Sharp /// through submodules. The inner exception contains the exception that was /// initially thrown while operating on the submodule. /// -#if DESKTOP [Serializable] -#endif public class RecurseSubmodulesException : LibGit2SharpException { /// @@ -38,7 +34,6 @@ public RecurseSubmodulesException(string message, Exception innerException, stri InitialRepositoryPath = initialRepositoryPath; } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -47,6 +42,5 @@ public RecurseSubmodulesException(string message, Exception innerException, stri protected RecurseSubmodulesException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif } } diff --git a/LibGit2Sharp/RemoveFromIndexException.cs b/LibGit2Sharp/RemoveFromIndexException.cs index eca11eb3e..6d9718c18 100644 --- a/LibGit2Sharp/RemoveFromIndexException.cs +++ b/LibGit2Sharp/RemoveFromIndexException.cs @@ -1,17 +1,13 @@ using System; using System.Globalization; -#if DESKTOP using System.Runtime.Serialization; -#endif namespace LibGit2Sharp { /// /// The exception that is thrown when a file cannot be removed from the index. /// -#if DESKTOP [Serializable] -#endif public class RemoveFromIndexException : LibGit2SharpException { /// @@ -47,7 +43,6 @@ public RemoveFromIndexException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -56,6 +51,5 @@ public RemoveFromIndexException(string message, Exception innerException) protected RemoveFromIndexException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif } } diff --git a/LibGit2Sharp/RepositoryNotFoundException.cs b/LibGit2Sharp/RepositoryNotFoundException.cs index 10a0742f3..2255c0891 100644 --- a/LibGit2Sharp/RepositoryNotFoundException.cs +++ b/LibGit2Sharp/RepositoryNotFoundException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif namespace LibGit2Sharp { @@ -9,9 +7,7 @@ namespace LibGit2Sharp /// The exception that is thrown when a is being built with /// a path that doesn't point at a valid Git repository or workdir. /// -#if DESKTOP [Serializable] -#endif public class RepositoryNotFoundException : LibGit2SharpException { /// @@ -46,7 +42,6 @@ public RepositoryNotFoundException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -55,6 +50,5 @@ public RepositoryNotFoundException(string message, Exception innerException) protected RepositoryNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif } } diff --git a/LibGit2Sharp/SecureUsernamePasswordCredentials.cs b/LibGit2Sharp/SecureUsernamePasswordCredentials.cs index 09ed2310d..16427ddf3 100644 --- a/LibGit2Sharp/SecureUsernamePasswordCredentials.cs +++ b/LibGit2Sharp/SecureUsernamePasswordCredentials.cs @@ -26,11 +26,7 @@ protected internal override int GitCredentialHandler(out IntPtr cred) try { -#if DESKTOP passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(Password); -#else - passwordPtr = SecureStringMarshal.SecureStringToCoTaskMemUnicode(Password); -#endif return NativeMethods.git_cred_userpass_plaintext_new(out cred, Username, Marshal.PtrToStringUni(passwordPtr)); } diff --git a/LibGit2Sharp/SmartSubtransportRegistration.cs b/LibGit2Sharp/SmartSubtransportRegistration.cs index cc756885a..e9f21dada 100644 --- a/LibGit2Sharp/SmartSubtransportRegistration.cs +++ b/LibGit2Sharp/SmartSubtransportRegistration.cs @@ -40,7 +40,7 @@ private IntPtr CreateRegistrationPointer() var registration = new GitSmartSubtransportRegistration(); registration.SubtransportCallback = Marshal.GetFunctionPointerForDelegate(EntryPoints.SubtransportCallback); - registration.Rpc = typeof(RpcSmartSubtransport).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()) ? (uint)1 : (uint)0; + registration.Rpc = typeof(RpcSmartSubtransport).IsAssignableFrom(typeof(T)) ? (uint)1 : (uint)0; var registrationPointer = Marshal.AllocHGlobal(Marshal.SizeOf(registration)); Marshal.StructureToPtr(registration, registrationPointer, false); diff --git a/LibGit2Sharp/UnbornBranchException.cs b/LibGit2Sharp/UnbornBranchException.cs index ab4bccd52..34ef437cb 100644 --- a/LibGit2Sharp/UnbornBranchException.cs +++ b/LibGit2Sharp/UnbornBranchException.cs @@ -1,8 +1,5 @@ using System; -using System.Globalization; -#if DESKTOP using System.Runtime.Serialization; -#endif namespace LibGit2Sharp { @@ -10,9 +7,7 @@ namespace LibGit2Sharp /// The exception that is thrown when a operation requiring an existing /// branch is performed against an unborn branch. /// -#if DESKTOP [Serializable] -#endif public class UnbornBranchException : LibGit2SharpException { /// @@ -47,7 +42,6 @@ public UnbornBranchException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -56,6 +50,5 @@ public UnbornBranchException(string message, Exception innerException) protected UnbornBranchException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif } } diff --git a/LibGit2Sharp/UnmatchedPathException.cs b/LibGit2Sharp/UnmatchedPathException.cs index f433eec13..7d118346d 100644 --- a/LibGit2Sharp/UnmatchedPathException.cs +++ b/LibGit2Sharp/UnmatchedPathException.cs @@ -1,16 +1,12 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif namespace LibGit2Sharp { /// /// The exception that is thrown when an explicit path or a list of explicit paths could not be matched. /// -#if DESKTOP [Serializable] -#endif public class UnmatchedPathException : LibGit2SharpException { /// @@ -45,7 +41,6 @@ public UnmatchedPathException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -54,6 +49,5 @@ public UnmatchedPathException(string message, Exception innerException) protected UnmatchedPathException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif } } diff --git a/LibGit2Sharp/UnmergedIndexEntriesException.cs b/LibGit2Sharp/UnmergedIndexEntriesException.cs index e27c1d8fc..729882678 100644 --- a/LibGit2Sharp/UnmergedIndexEntriesException.cs +++ b/LibGit2Sharp/UnmergedIndexEntriesException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -10,9 +8,7 @@ namespace LibGit2Sharp /// The exception that is thrown when an operation that requires a fully merged index /// is performed against an index with unmerged entries /// -#if DESKTOP [Serializable] -#endif public class UnmergedIndexEntriesException : LibGit2SharpException { /// @@ -47,7 +43,6 @@ public UnmergedIndexEntriesException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -56,7 +51,6 @@ public UnmergedIndexEntriesException(string message, Exception innerException) protected UnmergedIndexEntriesException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal UnmergedIndexEntriesException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/UserCanceledException.cs b/LibGit2Sharp/UserCanceledException.cs index 1d3e3fb11..41eebb29a 100644 --- a/LibGit2Sharp/UserCanceledException.cs +++ b/LibGit2Sharp/UserCanceledException.cs @@ -1,7 +1,5 @@ using System; -#if DESKTOP using System.Runtime.Serialization; -#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -9,9 +7,7 @@ namespace LibGit2Sharp /// /// The exception that is thrown when an operation is canceled. /// -#if DESKTOP [Serializable] -#endif public class UserCancelledException : LibGit2SharpException { /// @@ -46,7 +42,6 @@ public UserCancelledException(string message, Exception innerException) : base(message, innerException) { } -#if DESKTOP /// /// Initializes a new instance of the class with a serialized data. /// @@ -55,7 +50,6 @@ public UserCancelledException(string message, Exception innerException) protected UserCancelledException(SerializationInfo info, StreamingContext context) : base(info, context) { } -#endif internal UserCancelledException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/Version.cs b/LibGit2Sharp/Version.cs index bc441adeb..077951113 100644 --- a/LibGit2Sharp/Version.cs +++ b/LibGit2Sharp/Version.cs @@ -11,7 +11,7 @@ namespace LibGit2Sharp /// public class Version { - private readonly Assembly assembly = typeof(Repository).GetTypeInfo().Assembly; + private readonly Assembly assembly = typeof(Repository).Assembly; /// /// Needed for mocking purposes. From ef1fa3a08b0c36d29ca0e427a4c97731663a4431 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 1 Aug 2017 23:55:41 -0400 Subject: [PATCH 011/384] Remove unused property --- Directory.Build.props | 2 -- 1 file changed, 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 0b47885d2..0ed6c6d38 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,8 +2,6 @@ $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ - - 0.4.11 From 496fc2fc1789af1d09307c60b20d48c91e97cea0 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 1 Aug 2017 23:56:17 -0400 Subject: [PATCH 012/384] Add solution items --- LibGit2Sharp.sln | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index 8ca542f60..2563fba34 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.26724.1 +VisualStudioVersion = 15.0.26730.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp", "LibGit2Sharp\LibGit2Sharp.csproj", "{EE6ED99F-CB12-4683-B055-D28FC7357A34}" EndProject @@ -9,6 +9,8 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0CA739FD-DA4D-4F64-9834-DA14A3ECD04B}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets nuget.config = nuget.config version.json = version.json EndProjectSection From d73225f16c79c3df391a8873b67b95b3aff7fa5c Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 2 Aug 2017 00:05:23 -0400 Subject: [PATCH 013/384] Put ExtraDefine in Directory.Build.props --- Directory.Build.props | 3 +++ LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 - LibGit2Sharp/ExtraDefine.targets | 7 ------- LibGit2Sharp/LibGit2Sharp.csproj | 1 - 4 files changed, 3 insertions(+), 9 deletions(-) delete mode 100644 LibGit2Sharp/ExtraDefine.targets diff --git a/Directory.Build.props b/Directory.Build.props index 0ed6c6d38..c4e5543d3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,10 +1,13 @@ + $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ + $(DefineConstants);$(ExtraDefine) + diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 4dd73ef8c..f1c29e152 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -28,5 +28,4 @@ - \ No newline at end of file diff --git a/LibGit2Sharp/ExtraDefine.targets b/LibGit2Sharp/ExtraDefine.targets deleted file mode 100644 index b5ba508b5..000000000 --- a/LibGit2Sharp/ExtraDefine.targets +++ /dev/null @@ -1,7 +0,0 @@ - - - - - $(DefineConstants);$(ExtraDefine) - - diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 4919e1a8b..a0a810d6d 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -38,7 +38,6 @@ - https://github.com/libgit2/libgit2sharp/raw/$(GitCommitIdShort)/square-logo.png From 0a3306562f3616f42e4d42b5472fa1de40eb5973 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 2 Aug 2017 00:19:09 -0400 Subject: [PATCH 014/384] Cleanup --- .editorconfig | 3 +++ Directory.Build.targets | 2 ++ LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 16 +++++++--------- LibGit2Sharp/LibGit2Sharp.csproj | 14 +++++++++----- LibGit2Sharp/Properties/AssemblyInfo.cs | 3 --- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/.editorconfig b/.editorconfig index 096ff2565..a9e981c1a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,3 +13,6 @@ insert_final_newline = true [*.{sln,csroj}] trim_trailing_whitespace = false insert_final_newline = false + +[*.{props,targets}] +indent_size = 2 \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets index f7c1901a8..080355c7d 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,7 @@ + true + diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index f1c29e152..1a1afffef 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,22 +1,22 @@  + net46;netcoreapp2.0 true $(DefineConstants);DESKTOP false + - - TestHelpers\Epoch.cs - - - TestHelpers\Platform.cs - + + + + @@ -25,7 +25,5 @@ - - - + \ No newline at end of file diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index a0a810d6d..f02eebb76 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,18 +1,20 @@  + net40;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 + Copyright © LibGit2Sharp contributors libgit2 git https://github.com/libgit2/libgit2sharp/ LibGit2Sharp contributors - true ..\libgit2sharp.snk true $(DefineConstants);DESKTOP + @@ -22,22 +24,23 @@ - - - Objects.tt - + + + + + https://github.com/libgit2/libgit2sharp/raw/$(GitCommitIdShort)/square-logo.png @@ -45,4 +48,5 @@ https://github.com/libgit2/libgit2sharp/raw/$(GitCommitIdShort)/LICENSE.md + diff --git a/LibGit2Sharp/Properties/AssemblyInfo.cs b/LibGit2Sharp/Properties/AssemblyInfo.cs index ea5861dbd..ffa977d1d 100644 --- a/LibGit2Sharp/Properties/AssemblyInfo.cs +++ b/LibGit2Sharp/Properties/AssemblyInfo.cs @@ -1,13 +1,10 @@ using System; -using System.Reflection; 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: AssemblyCopyright("Copyright © LibGit2Sharp contributors")] - [assembly: CLSCompliant(true)] // Setting ComVisible to false makes the types in this assembly not visible From 327472da494dabfdab7a6b582228d7416ea0fa03 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 2 Aug 2017 00:19:44 -0400 Subject: [PATCH 015/384] Remove unneeded package references --- LibGit2Sharp/LibGit2Sharp.csproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index f02eebb76..6188310a8 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -33,12 +33,6 @@ - - - - - - From 23f4db405d4f5431c1d449ba6dce3ae1c7a86f70 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 2 Aug 2017 00:27:51 -0400 Subject: [PATCH 016/384] Include PDBs in package --- Directory.Build.targets | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Directory.Build.targets b/Directory.Build.targets index 080355c7d..c1631f63d 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -2,6 +2,13 @@ true + $(TargetsForTfmSpecificContentInPackage);IncludePDBsInPackage + + + + + + From c99e54d57ec8848f5709de3d1eaff41402fbac72 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 2 Aug 2017 00:33:20 -0400 Subject: [PATCH 017/384] Move tests out of desktop folder --- LibGit2Sharp.Tests/MetaFixture.cs | 38 ++++++++++++++- .../{desktop => }/SmartSubtransportFixture.cs | 0 LibGit2Sharp.Tests/desktop/MetaFixture.cs | 46 ------------------- 3 files changed, 37 insertions(+), 47 deletions(-) rename LibGit2Sharp.Tests/{desktop => }/SmartSubtransportFixture.cs (100%) delete mode 100644 LibGit2Sharp.Tests/desktop/MetaFixture.cs diff --git a/LibGit2Sharp.Tests/MetaFixture.cs b/LibGit2Sharp.Tests/MetaFixture.cs index 64e232076..b70d9022c 100644 --- a/LibGit2Sharp.Tests/MetaFixture.cs +++ b/LibGit2Sharp.Tests/MetaFixture.cs @@ -13,13 +13,49 @@ namespace LibGit2Sharp.Tests { - public partial class MetaFixture + public class MetaFixture { private static readonly HashSet explicitOnlyInterfaces = new HashSet { typeof(IBelongToARepository), typeof(IDiffResult), }; + [Fact] + public void LibGit2SharpPublicInterfacesCoverAllPublicMembers() + { + var methodsMissingFromInterfaces = + from t in typeof(IRepository).GetTypeInfo().Assembly.GetExportedTypes() + where !t.GetTypeInfo().IsInterface + where t.GetTypeInfo().GetInterfaces().Any(i => i.GetTypeInfo().IsPublic && i.Namespace == typeof(IRepository).Namespace && !explicitOnlyInterfaces.Contains(i)) + let interfaceTargetMethods = from i in t.GetTypeInfo().GetInterfaces() + from im in t.GetInterfaceMap(i).TargetMethods + select im + from tm in t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) + where !interfaceTargetMethods.Contains(tm) + select t.Name + " has extra method " + tm.Name; + + Assert.Equal("", string.Join(Environment.NewLine, + methodsMissingFromInterfaces.ToArray())); + } + + [Fact] + public void LibGit2SharpExplicitOnlyInterfacesAreIndeedExplicitOnly() + { + var methodsMissingFromInterfaces = + from t in typeof(IRepository).GetTypeInfo().Assembly.GetExportedTypes() + where t.GetInterfaces().Any(explicitOnlyInterfaces.Contains) + let interfaceTargetMethods = from i in t.GetInterfaces() + where explicitOnlyInterfaces.Contains(i) + from im in t.GetTypeInfo().GetInterfaceMap(i).TargetMethods + select im + from tm in t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) + where interfaceTargetMethods.Contains(tm) + select t.Name + " has public method " + tm.Name + " which should be explicitly implemented."; + + Assert.Equal("", string.Join(Environment.NewLine, + methodsMissingFromInterfaces.ToArray())); + } + [Fact] public void PublicTestMethodsAreFactsOrTheories() { diff --git a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs b/LibGit2Sharp.Tests/SmartSubtransportFixture.cs similarity index 100% rename from LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs rename to LibGit2Sharp.Tests/SmartSubtransportFixture.cs diff --git a/LibGit2Sharp.Tests/desktop/MetaFixture.cs b/LibGit2Sharp.Tests/desktop/MetaFixture.cs deleted file mode 100644 index 5103e19c6..000000000 --- a/LibGit2Sharp.Tests/desktop/MetaFixture.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using Xunit; - -namespace LibGit2Sharp.Tests -{ - public partial class MetaFixture - { - [Fact] - public void LibGit2SharpPublicInterfacesCoverAllPublicMembers() - { - var methodsMissingFromInterfaces = - from t in typeof(IRepository).GetTypeInfo().Assembly.GetExportedTypes() - where !t.GetTypeInfo().IsInterface - where t.GetTypeInfo().GetInterfaces().Any(i => i.GetTypeInfo().IsPublic && i.Namespace == typeof(IRepository).Namespace && !explicitOnlyInterfaces.Contains(i)) - let interfaceTargetMethods = from i in t.GetTypeInfo().GetInterfaces() - from im in t.GetInterfaceMap(i).TargetMethods - select im - from tm in t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) - where !interfaceTargetMethods.Contains(tm) - select t.Name + " has extra method " + tm.Name; - - Assert.Equal("", string.Join(Environment.NewLine, - methodsMissingFromInterfaces.ToArray())); - } - - [Fact] - public void LibGit2SharpExplicitOnlyInterfacesAreIndeedExplicitOnly() - { - var methodsMissingFromInterfaces = - from t in typeof(IRepository).GetTypeInfo().Assembly.GetExportedTypes() - where t.GetInterfaces().Any(explicitOnlyInterfaces.Contains) - let interfaceTargetMethods = from i in t.GetInterfaces() - where explicitOnlyInterfaces.Contains(i) - from im in t.GetTypeInfo().GetInterfaceMap(i).TargetMethods - select im - from tm in t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance) - where interfaceTargetMethods.Contains(tm) - select t.Name + " has public method " + tm.Name + " which should be explicitly implemented."; - - Assert.Equal("", string.Join(Environment.NewLine, - methodsMissingFromInterfaces.ToArray())); - } - } -} From 66aeba83f5d652d66f33d6678ace374d4116aebc Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 2 Aug 2017 01:10:20 -0400 Subject: [PATCH 018/384] Update code generation targets --- LibGit2Sharp/CodeGenerator.targets | 125 ++++++++++++++++------------- 1 file changed, 68 insertions(+), 57 deletions(-) diff --git a/LibGit2Sharp/CodeGenerator.targets b/LibGit2Sharp/CodeGenerator.targets index d55d50117..adb23c241 100644 --- a/LibGit2Sharp/CodeGenerator.targets +++ b/LibGit2Sharp/CodeGenerator.targets @@ -1,64 +1,75 @@  + - $(CoreCompileDependsOn);GenerateNativeDllNameCs - GenerateCommitIdVersion;$(PrepareResourceNamesDependsOn) - $(IntermediateOutputPath)NativeDllName.cs - $(IntermediateOutputPath)UniqueIdentifier.cs - $(IntermediateOutputPath)libgit2sharp_hash.txt + $(IntermediateOutputPath)NativeDllName.g.cs + $(IntermediateOutputPath)UniqueIdentifier.g.cs + - - - - - - - namespace LibGit2Sharp.Core - { - internal static class NativeDllName - { - public const string Name = "$(libgit2FileName)"%3b - } - } - - - - - - - - - - - - - - - - - - - - - - - - - $(RootNamespace).libgit2sharp_hash.txt - - - + + + + + + + + + +namespace LibGit2Sharp.Core +{ + internal static class NativeDllName + { + public const string Name = "$(libgit2FileName)"%3b + } +} + + + + + + + + + + + + + + + + + +namespace LibGit2Sharp.Core +{ + internal static class UniqueId + { + public const string UniqueIdentifier = "$([System.Guid]::NewGuid())"%3b + } +} + + + + + + + + + + + + + + + + + + + + + + + + From 1b6ad9a56af9c9d0faa840def8dd85cc8df347a1 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 5 Aug 2017 00:14:36 -0400 Subject: [PATCH 019/384] Update Version to not rely on embedded resources --- LibGit2Sharp/CodeGenerator.targets | 57 +++++++++++++++++++++++------- LibGit2Sharp/Version.cs | 30 +++------------- 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/LibGit2Sharp/CodeGenerator.targets b/LibGit2Sharp/CodeGenerator.targets index adb23c241..a4f0ad726 100644 --- a/LibGit2Sharp/CodeGenerator.targets +++ b/LibGit2Sharp/CodeGenerator.targets @@ -1,9 +1,14 @@  + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + $(IntermediateOutputPath)NativeDllName.g.cs $(IntermediateOutputPath)UniqueIdentifier.g.cs + $(IntermediateOutputPath)AssemblyCommitIds.g.cs @@ -16,13 +21,13 @@ -namespace LibGit2Sharp.Core -{ - internal static class NativeDllName - { + namespace LibGit2Sharp.Core + { + internal static class NativeDllName + { public const string Name = "$(libgit2FileName)"%3b - } -} + } + } @@ -40,13 +45,13 @@ namespace LibGit2Sharp.Core -namespace LibGit2Sharp.Core -{ - internal static class UniqueId - { + namespace LibGit2Sharp.Core + { + internal static class UniqueId + { public const string UniqueIdentifier = "$([System.Guid]::NewGuid())"%3b - } -} + } + } @@ -72,4 +77,32 @@ namespace LibGit2Sharp.Core + + + + + + + + + namespace LibGit2Sharp + { + internal static class AssemblyCommitIds + { + public const string LibGit2CommitSha = "$(libgit2hash)"%3b + public const string LibGit2SharpCommitSha = "$(GitCommitId)"%3b + } + } + + + + + + + + + + + + diff --git a/LibGit2Sharp/Version.cs b/LibGit2Sharp/Version.cs index 077951113..8b09a3ff5 100644 --- a/LibGit2Sharp/Version.cs +++ b/LibGit2Sharp/Version.cs @@ -1,7 +1,4 @@ using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -11,8 +8,6 @@ namespace LibGit2Sharp /// public class Version { - private readonly Assembly assembly = typeof(Repository).Assembly; - /// /// Needed for mocking purposes. /// @@ -42,23 +37,15 @@ public virtual BuiltInFeatures Features /// /// Returns the SHA hash for the libgit2 library. /// - public virtual string LibGit2CommitSha - { - get { return RetrieveAbbrevShaFrom("libgit2_hash.txt"); } - } + public virtual string LibGit2CommitSha => RetrieveAbbrevShaFrom(AssemblyCommitIds.LibGit2CommitSha); /// /// Returns the SHA hash for the LibGit2Sharp library. /// - public virtual string LibGit2SharpCommitSha - { - get { return RetrieveAbbrevShaFrom("libgit2sharp_hash.txt"); } - } + public virtual string LibGit2SharpCommitSha => RetrieveAbbrevShaFrom(AssemblyCommitIds.LibGit2SharpCommitSha); - private string RetrieveAbbrevShaFrom(string name) + private string RetrieveAbbrevShaFrom(string sha) { - string sha = ReadContentFromResource(assembly, name) ?? "unknown"; - var index = sha.Length > 7 ? 7 : sha.Length; return sha.Substring(0, index); } @@ -68,7 +55,7 @@ private string RetrieveAbbrevShaFrom(string name) /// /// /// The format of the version number is as follows: - /// Major.Minor.Patch-LibGit2Sharp_abbrev_hash-libgit2_abbrev_hash (x86|x64 - features) + /// Major.Minor.Patch+g{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) /// /// public override string ToString() @@ -86,14 +73,5 @@ private string RetrieveVersion() Platform.ProcessorArchitecture, features); } - - private string ReadContentFromResource(Assembly assembly, string partialResourceName) - { - string name = string.Format(CultureInfo.InvariantCulture, "LibGit2Sharp.{0}", partialResourceName); - using (var sr = new StreamReader(assembly.GetManifestResourceStream(name))) - { - return sr.ReadLine(); - } - } } } From 4c4378882b34294e3259fb09d1406b1edb7c0c9a Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 5 Aug 2017 22:43:22 -0400 Subject: [PATCH 020/384] Use .NET Core 2.0 SDK on Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 25b98d6b8..e40e71914 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: csharp dist: trusty -dotnet: 1.0.1 +dotnet: 2.0.0 mono: none os: From e6b1efa510f2022b31b8e04ee61075648f3ac842 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 5 Aug 2017 22:51:16 -0400 Subject: [PATCH 021/384] Update Microsoft.NET.Test.Sdk --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 1a1afffef..e98f150ac 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -23,7 +23,7 @@ - + - \ No newline at end of file + From 7b47408b673cff4257b018f909987974d731408a Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 5 Aug 2017 23:22:52 -0400 Subject: [PATCH 022/384] Fix build scripts --- appveyor.yml | 2 +- buildandtest.cmd | 2 +- buildandtest.sh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 31b98ac9f..e8dbeaab5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -103,7 +103,7 @@ test_script: } } -- dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp1.0 --no-build +- dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.0 --no-restore --no-build after_test: - ps: | diff --git a/buildandtest.cmd b/buildandtest.cmd index 60c96d709..b99f4d08e 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.2.0\tools\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" --no-build -f netcoreapp1.0 +dotnet test "%~dp0LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj" -f netcoreapp2.0 --no-restore --no-build @IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% EXIT /B %ERRORLEVEL% diff --git a/buildandtest.sh b/buildandtest.sh index f0221295e..47e5e1053 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 netcoreapp1.0 /property:ExtraDefine="$EXTRADEFINE" /fl /flp:verbosity=detailed -dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp1.0 --no-build +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 exit $? From 4acc222f689cdf534203327596ba5e364da7c2e0 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 5 Aug 2017 23:32:10 -0400 Subject: [PATCH 023/384] Run on macOS 10.12 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e40e71914..975828182 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ language: csharp dist: trusty dotnet: 2.0.0 mono: none +osx_image: xcode8.3 os: - osx From 7b85110fe793db466effea9a77a39f7673660193 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 6 Aug 2017 01:42:04 -0400 Subject: [PATCH 024/384] Add condition to fix design-time build --- LibGit2Sharp/CodeGenerator.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/CodeGenerator.targets b/LibGit2Sharp/CodeGenerator.targets index a4f0ad726..49a875110 100644 --- a/LibGit2Sharp/CodeGenerator.targets +++ b/LibGit2Sharp/CodeGenerator.targets @@ -77,7 +77,7 @@ - + From 53ef83bd26d93d7cc63194a7630c7b9e577c1dff Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 6 Aug 2017 02:34:18 -0400 Subject: [PATCH 025/384] Update version test --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 16 ++++++++-------- LibGit2Sharp/BuiltInFeatures.cs | 6 ++++++ LibGit2Sharp/Version.cs | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 365bc1a3e..d5dee6992 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -19,25 +19,25 @@ public void CanGetMinimumCompiledInFeatures() public void CanRetrieveValidVersionString() { // Version string format is: - // Major.Minor.Patch[-somePreleaseTag]-libgit2_abbrev_hash (x86|x64 - features) + // Major.Minor.Patch[-previewTag]+g{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) // Example output: - // "0.17.0[-beta]+gdeadcafeee.LibGit2-06d772d (x86 - Threads, Https)" + // "0.25.0-preview.52+g871d13a67f.libgit2-15e1193 (x86 - Threads, Https)" string versionInfo = GlobalSettings.Version.ToString(); // The GlobalSettings.Version returned string should contain : - // version: '0.17.0[-somePreleaseTag]+[gSomeGitCommit.]LibGit2-06d772d' LibGit2Sharp version number. - // git2hash: '06d772d' LibGit2 library 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+)*)\)$"; + // version: '0.25.0[-previewTag]' LibGit2Sharp version number. + // 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+)*)\)$"; Assert.NotNull(versionInfo); Match regexResult = Regex.Match(versionInfo, regex); Assert.True(regexResult.Success, "The following version string format is enforced:" + - "Major.Minor.Patch[-somePreleaseTag]+[gSomeGitCommit].LibGit2-abbrev_hash (x86|x64 - features). " + + "Major.Minor.Patch[-previewTag]+g{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features). " + "But found \"" + versionInfo + "\" instead."); } diff --git a/LibGit2Sharp/BuiltInFeatures.cs b/LibGit2Sharp/BuiltInFeatures.cs index db6a1a0ed..1cf0d92e9 100644 --- a/LibGit2Sharp/BuiltInFeatures.cs +++ b/LibGit2Sharp/BuiltInFeatures.cs @@ -29,5 +29,11 @@ public enum BuiltInFeatures /// libgit2. /// Ssh = (1 << 2), + + /// + /// Support for sub-second resolution in file modification times + /// is compiled into libgit2. + /// + NSec = (1 << 3), } } diff --git a/LibGit2Sharp/Version.cs b/LibGit2Sharp/Version.cs index 8b09a3ff5..747529e84 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+g{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) + /// Major.Minor.Patch[-previewTag]+g{LibGit2Sharp_abbrev_hash}.libgit2-{libgit2_abbrev_hash} (x86|x64 - features) /// /// public override string ToString() From 2cce832b8f403492541e000a0fd1f7577a376c37 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 6 Aug 2017 02:41:49 -0400 Subject: [PATCH 026/384] Put SmartSubtransportFixture back in desktop-only folder --- LibGit2Sharp.Tests/{ => desktop}/SmartSubtransportFixture.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LibGit2Sharp.Tests/{ => desktop}/SmartSubtransportFixture.cs (100%) diff --git a/LibGit2Sharp.Tests/SmartSubtransportFixture.cs b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs similarity index 100% rename from LibGit2Sharp.Tests/SmartSubtransportFixture.cs rename to LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs From c0d8eafe4172447a621b59fce62db56acc5d5dd3 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 25 Aug 2017 19:12:27 -0400 Subject: [PATCH 027/384] Update to SourceLink 2.2.0 --- LibGit2Sharp.sln | 2 +- LibGit2Sharp/LibGit2Sharp.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index 2563fba34..fb8a7101b 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.26730.0 +VisualStudioVersion = 15.0.26730.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp", "LibGit2Sharp\LibGit2Sharp.csproj", "{EE6ED99F-CB12-4683-B055-D28FC7357A34}" EndProject diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 6188310a8..c49e90b9e 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,8 +29,8 @@ - - + + From 3ba098e94006fcb8b198a5f08a4537ebcda99f3b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 25 Aug 2017 19:25:33 -0400 Subject: [PATCH 028/384] Add condition to avoid error during pack --- LibGit2Sharp/CodeGenerator.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/CodeGenerator.targets b/LibGit2Sharp/CodeGenerator.targets index 49a875110..845f3cf03 100644 --- a/LibGit2Sharp/CodeGenerator.targets +++ b/LibGit2Sharp/CodeGenerator.targets @@ -65,7 +65,7 @@ - + From 5379d6a37fa3d93eccf2ef2b34e29863c718c551 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 25 Aug 2017 19:58:52 -0400 Subject: [PATCH 029/384] Disable SourceLink on Travis CI --- LibGit2Sharp/LibGit2Sharp.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index c49e90b9e..0b37bf6af 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -15,6 +15,11 @@ $(DefineConstants);DESKTOP + + + false + + From c923e6baa55fce433fef07a14652fb48c50648df Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 19 Oct 2017 23:15:07 +0100 Subject: [PATCH 030/384] README: reorganize build/code analysis badges Drop vNext branch information, since it's now unused. Reorganize build badges up top. --- README.md | 52 ++++++++++++++++------------------------------------ 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index e82907553..f316b4a39 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,21 @@ # LibGit2Sharp +[![master win][master-win-badge]][master-win] +[![master nix][master-nix-badge]][master-nix] +[![coverity][coverity-badge]][coverity-project] +[![coveralls][coveralls-badge]][coveralls-project] + +[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 + +[coveralls-project]: https://coveralls.io/r/libgit2/libgit2sharp?branch=vNext +[coveralls-badge]: https://coveralls.io/repos/libgit2/libgit2sharp/badge.svg?branch=vNext + **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/ @@ -27,42 +43,6 @@ [tracker]: https://github.com/libgit2/libgit2sharp/issues [twitter]: http://twitter.com/libgit2sharp -## Current project status - -The CI builds are generously hosted and run on the [Travis][travis] and [AppVeyor][appveyor] infrastructures. - -| | Windows (x86/amd64) | Linux/Mac OS X | -| :------ | :------: | :------: | -| **master** | [![master win][master-win-badge]][master-win] | [![master nix][master-nix-badge]][master-nix] | -| **vNext** | [![vNext win][vNext-win-badge]][vNext-win] | [![vNext nix][vNext-nix-badge]][vNext-nix] | - -The security-oriented static code analysis is kindly run through the [Coverity][coverity] service. Code coverage is kindly run through [Coveralls.io][coveralls]. - -| | Static Analysis | Code Coverage | -|-------|-----------------|---------------| -| **vNext** | [![coverity][coverity-badge]][coverity-project] | [![coveralls][coveralls-badge]][coveralls-project] | - - - [travis]: https://travis-ci.org/ - [appveyor]: http://appveyor.com/ - [coverity]: https://scan.coverity.com/ - [coveralls]: https://coveralls.io/ - - [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 - [vNext-win-badge]: https://ci.appveyor.com/api/projects/status/8qxcoqdo9kp7x2w9/branch/vNext?svg=true - [vNext-win]: https://ci.appveyor.com/project/libgit2/libgit2sharp/branch/vNext - [vNext-nix-badge]: https://travis-ci.org/libgit2/libgit2sharp.svg?branch=vNext - [vNext-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 - - [coveralls-project]: https://coveralls.io/r/libgit2/libgit2sharp?branch=vNext - [coveralls-badge]: https://coveralls.io/repos/libgit2/libgit2sharp/badge.svg?branch=vNext - ## Quick contributing guide - Fork and clone locally From 4001ea17ff18d62e577b68bf98ee4edefe2c9086 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 8 Nov 2017 19:07:54 +0000 Subject: [PATCH 031/384] README: point coveralls to master branch (We haven't done vNext for years, ugh.) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f316b4a39..6e215f489 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ [coverity-project]: https://scan.coverity.com/projects/2088 [coverity-badge]: https://scan.coverity.com/projects/2088/badge.svg -[coveralls-project]: https://coveralls.io/r/libgit2/libgit2sharp?branch=vNext -[coveralls-badge]: https://coveralls.io/repos/libgit2/libgit2sharp/badge.svg?branch=vNext +[coveralls-project]: https://coveralls.io/r/libgit2/libgit2sharp?branch=master +[coveralls-badge]: https://coveralls.io/repos/libgit2/libgit2sharp/badge.svg?branch=master **LibGit2Sharp brings all the might and speed of [libgit2][libgit2], a native Git implementation, to the managed world of .NET and Mono.** From c5c8f106187d29a9880172c1a925c515d7e522fd Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 12:10:18 -0500 Subject: [PATCH 032/384] Move Nerdbank.GitVersioning reference to project file --- Directory.Build.props | 4 ---- LibGit2Sharp/LibGit2Sharp.csproj | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c4e5543d3..ff10549b4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,8 +6,4 @@ $(DefineConstants);$(ExtraDefine) - - - - diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 0b37bf6af..b300f5a2e 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -34,6 +34,7 @@ + From 12c6de3794b8757204000de241d16fbebc3d9b78 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 12:25:03 -0500 Subject: [PATCH 033/384] Update dependencies --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 10 +++++----- LibGit2Sharp.Tests/RemoveFixture.cs | 6 +++--- LibGit2Sharp/LibGit2Sharp.csproj | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index e98f150ac..c0e0d6ff8 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -18,12 +18,12 @@ - - + + - - - + + + diff --git a/LibGit2Sharp.Tests/RemoveFixture.cs b/LibGit2Sharp.Tests/RemoveFixture.cs index a89977fce..6ceef6045 100644 --- a/LibGit2Sharp.Tests/RemoveFixture.cs +++ b/LibGit2Sharp.Tests/RemoveFixture.cs @@ -28,14 +28,14 @@ public class RemoveFixture : BaseFixture * 'git rm ' fails ("error: '' has local modifications"). */ [InlineData(false, "modified_unstaged_file.txt", false, FileStatus.ModifiedInWorkdir, true, true, FileStatus.NewInWorkdir | FileStatus.DeletedFromIndex)] - [InlineData(true, "modified_unstaged_file.txt", true, FileStatus.ModifiedInWorkdir, true, true, 0)] + [InlineData(true, "modified_unstaged_file.txt", true, FileStatus.ModifiedInWorkdir, true, true, FileStatus.Unaltered)] /*** * Test case: modified file in wd, the modifications have already been promoted to the index. * 'git rm --cached ' works (removes the file from the index) * 'git rm ' fails ("error: '' has changes staged in the index") */ [InlineData(false, "modified_staged_file.txt", false, FileStatus.ModifiedInIndex, true, true, FileStatus.NewInWorkdir | FileStatus.DeletedFromIndex)] - [InlineData(true, "modified_staged_file.txt", true, FileStatus.ModifiedInIndex, true, true, 0)] + [InlineData(true, "modified_staged_file.txt", true, FileStatus.ModifiedInIndex, true, true, FileStatus.Unaltered)] /*** * Test case: modified file in wd, the modifications have already been promoted to the index, and * the file does not exist in the HEAD. @@ -43,7 +43,7 @@ public class RemoveFixture : BaseFixture * 'git rm ' throws ("error: '' has changes staged in the index") */ [InlineData(false, "new_tracked_file.txt", false, FileStatus.NewInIndex, true, true, FileStatus.NewInWorkdir)] - [InlineData(true, "new_tracked_file.txt", true, FileStatus.NewInIndex, true, true, 0)] + [InlineData(true, "new_tracked_file.txt", true, FileStatus.NewInIndex, true, true, FileStatus.Unaltered)] public void CanRemoveAnUnalteredFileFromTheIndexWithoutRemovingItFromTheWorkingDirectory( bool removeFromWorkdir, string filename, bool throws, FileStatus initialStatus, bool existsBeforeRemove, bool existsAfterRemove, FileStatus lastStatus) { diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index b300f5a2e..2c2a2ed16 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -34,9 +34,9 @@ - - - + + + From fa10103f16de17bbe78df33db721676c025fe023 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 12:36:33 -0500 Subject: [PATCH 034/384] Use new mechanism to include PDBs in package --- Directory.Build.targets | 7 ------- LibGit2Sharp/LibGit2Sharp.csproj | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index c1631f63d..080355c7d 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -2,13 +2,6 @@ true - $(TargetsForTfmSpecificContentInPackage);IncludePDBsInPackage - - - - - - diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 2c2a2ed16..46388db49 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -9,6 +9,7 @@ libgit2 git https://github.com/libgit2/libgit2sharp/ LibGit2Sharp contributors + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true ..\libgit2sharp.snk true From cf7a478470602d03e12938b90684e3f8019dcb24 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 12:40:03 -0500 Subject: [PATCH 035/384] Clean up tests project file --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index c0e0d6ff8..933d69ef0 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -4,26 +4,25 @@ net46;netcoreapp2.0 true $(DefineConstants);DESKTOP - false - - - - - - + - - - + + + + + + + + From 43b4c077906c2e15b26bf12a53b25f80c548af26 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 12:43:41 -0500 Subject: [PATCH 036/384] Move AllowUnsafeBlocks to props file --- Directory.Build.props | 1 + LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 - LibGit2Sharp/LibGit2Sharp.csproj | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ff10549b4..fb2ca9ca9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,7 @@ + true $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ $(DefineConstants);$(ExtraDefine) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 933d69ef0..30bb076fd 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -2,7 +2,6 @@ net46;netcoreapp2.0 - true $(DefineConstants);DESKTOP diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 46388db49..bb584d0fa 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -12,7 +12,6 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true ..\libgit2sharp.snk - true $(DefineConstants);DESKTOP From 67c39dae194cf7e3f71b81784ba5d45c83ade8b1 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 15:25:47 -0500 Subject: [PATCH 037/384] Remove net40 target --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 6 +- LibGit2Sharp.Tests/app.config | 6 -- LibGit2Sharp/Core/ArrayMarshaler.cs | 2 +- LibGit2Sharp/Core/GitOdbBackend.cs | 2 +- LibGit2Sharp/Core/GitOdbBackendStream.cs | 2 +- LibGit2Sharp/Core/GitSmartSubtransport.cs | 2 +- .../Core/GitSmartSubtransportStream.cs | 2 +- LibGit2Sharp/Core/MarshalPortable.cs | 35 ---------- LibGit2Sharp/Core/Platform.cs | 68 ++++--------------- LibGit2Sharp/Filter.cs | 6 +- LibGit2Sharp/GlobalSettings.cs | 4 -- LibGit2Sharp/LibGit2Sharp.csproj | 3 +- LibGit2Sharp/ObjectDatabase.cs | 2 +- 13 files changed, 27 insertions(+), 113 deletions(-) delete mode 100644 LibGit2Sharp.Tests/app.config delete mode 100644 LibGit2Sharp/Core/MarshalPortable.cs diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 30bb076fd..bacf2e1ff 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,8 +1,8 @@  - net46;netcoreapp2.0 - $(DefineConstants);DESKTOP + net461;netcoreapp2.0 + $(DefineConstants);DESKTOP @@ -21,7 +21,7 @@ - + diff --git a/LibGit2Sharp.Tests/app.config b/LibGit2Sharp.Tests/app.config deleted file mode 100644 index 34dc4a041..000000000 --- a/LibGit2Sharp.Tests/app.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/LibGit2Sharp/Core/ArrayMarshaler.cs b/LibGit2Sharp/Core/ArrayMarshaler.cs index 13a50c1ad..4a37d241b 100644 --- a/LibGit2Sharp/Core/ArrayMarshaler.cs +++ b/LibGit2Sharp/Core/ArrayMarshaler.cs @@ -13,7 +13,7 @@ public ArrayMarshaler(T[] objs) for (var i = 0; i < objs.Length; i++) { - IntPtr ptr = Marshal.AllocHGlobal(MarshalPortable.SizeOf()); + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf()); ptrs[i] = ptr; Marshal.StructureToPtr(objs[i], ptr, false); } diff --git a/LibGit2Sharp/Core/GitOdbBackend.cs b/LibGit2Sharp/Core/GitOdbBackend.cs index a3f5777fe..a83c7d424 100644 --- a/LibGit2Sharp/Core/GitOdbBackend.cs +++ b/LibGit2Sharp/Core/GitOdbBackend.cs @@ -8,7 +8,7 @@ internal struct GitOdbBackend { static GitOdbBackend() { - GCHandleOffset = MarshalPortable.OffsetOf(nameof(GCHandle)).ToInt32(); + GCHandleOffset = Marshal.OffsetOf(nameof(GCHandle)).ToInt32(); } public uint Version; diff --git a/LibGit2Sharp/Core/GitOdbBackendStream.cs b/LibGit2Sharp/Core/GitOdbBackendStream.cs index d2771f598..5e51baabe 100644 --- a/LibGit2Sharp/Core/GitOdbBackendStream.cs +++ b/LibGit2Sharp/Core/GitOdbBackendStream.cs @@ -15,7 +15,7 @@ internal class GitOdbBackendStream { static GitOdbBackendStream() { - GCHandleOffset = MarshalPortable.OffsetOf(nameof(GCHandle)).ToInt32(); + GCHandleOffset = Marshal.OffsetOf(nameof(GCHandle)).ToInt32(); } public IntPtr Backend; diff --git a/LibGit2Sharp/Core/GitSmartSubtransport.cs b/LibGit2Sharp/Core/GitSmartSubtransport.cs index 9c545d3c0..b0a321635 100644 --- a/LibGit2Sharp/Core/GitSmartSubtransport.cs +++ b/LibGit2Sharp/Core/GitSmartSubtransport.cs @@ -8,7 +8,7 @@ internal class GitSmartSubtransport { static GitSmartSubtransport() { - GCHandleOffset = MarshalPortable.OffsetOf(nameof(GCHandle)).ToInt32(); + GCHandleOffset = Marshal.OffsetOf(nameof(GCHandle)).ToInt32(); } public action_callback Action; diff --git a/LibGit2Sharp/Core/GitSmartSubtransportStream.cs b/LibGit2Sharp/Core/GitSmartSubtransportStream.cs index 90853b415..4bf531e82 100644 --- a/LibGit2Sharp/Core/GitSmartSubtransportStream.cs +++ b/LibGit2Sharp/Core/GitSmartSubtransportStream.cs @@ -8,7 +8,7 @@ internal class GitSmartSubtransportStream { static GitSmartSubtransportStream() { - GCHandleOffset = MarshalPortable.OffsetOf(nameof(GCHandle)).ToInt32(); + GCHandleOffset = Marshal.OffsetOf(nameof(GCHandle)).ToInt32(); } public IntPtr SmartTransport; diff --git a/LibGit2Sharp/Core/MarshalPortable.cs b/LibGit2Sharp/Core/MarshalPortable.cs deleted file mode 100644 index 034675004..000000000 --- a/LibGit2Sharp/Core/MarshalPortable.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace LibGit2Sharp.Core -{ - internal static class MarshalPortable - { - internal static int SizeOf() - { -#if NET40 - return Marshal.SizeOf(typeof(T)); -#else - return Marshal.SizeOf(); -#endif - } - - internal static IntPtr OffsetOf(string fieldName) - { -#if NET40 - return Marshal.OffsetOf(typeof(T), fieldName); -#else - return Marshal.OffsetOf(fieldName); -#endif - } - - internal static T PtrToStructure(IntPtr ptr) - { -#if NET40 - return (T)Marshal.PtrToStructure(ptr, typeof(T)); -#else - return Marshal.PtrToStructure(ptr); -#endif - } - } -} diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index 19aed7ccb..a07d5172e 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Runtime.InteropServices; namespace LibGit2Sharp.Core @@ -13,68 +12,29 @@ internal enum OperatingSystemType internal static class Platform { - private static Lazy _operatingSystem = new Lazy( - DetermineOperatingSystem, - System.Threading.LazyThreadSafetyMode.PublicationOnly); + public static string ProcessorArchitecture => IntPtr.Size == 8 ? "x64" : "x86"; - public static string ProcessorArchitecture + public static OperatingSystemType OperatingSystem { - get { return IntPtr.Size == 8 ? "x64" : "x86"; } - } - - public static OperatingSystemType OperatingSystem => _operatingSystem.Value; - - private static OperatingSystemType DetermineOperatingSystem() - { -#if DESKTOP - // See http://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform - switch ((int)Environment.OSVersion.Platform) + get { - case 4: - case 128: + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return OperatingSystemType.Windows; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { return OperatingSystemType.Unix; + } - case 6: + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { return OperatingSystemType.MacOSX; + } - default: - return OperatingSystemType.Windows; - } -#else - try - { - return OperatingSystem_CoreFxStyle(); - } - catch (FileNotFoundException) - { - // We're probably running on .NET 4.6.1 or earlier where the API isn't available. - // This would suggest we're running on Windows. Although if our portable library - // is being used on mono, it could be *nix or OSX too. - return OperatingSystemType.Windows; - } -#endif - } - -#if !DESKTOP - private static OperatingSystemType OperatingSystem_CoreFxStyle() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return OperatingSystemType.Windows; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return OperatingSystemType.Unix; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return OperatingSystemType.MacOSX; - } - else - { throw new InvalidOperationException(); } } -#endif } } diff --git a/LibGit2Sharp/Filter.cs b/LibGit2Sharp/Filter.cs index 723b50359..1fd0587e5 100644 --- a/LibGit2Sharp/Filter.cs +++ b/LibGit2Sharp/Filter.cs @@ -261,8 +261,8 @@ int StreamCreateCallback(out IntPtr git_writestream_out, GitFilter self, IntPtr Marshal.StructureToPtr(state.thisStream, state.thisPtr, false); state.nextPtr = git_writestream_next; - state.nextStream = MarshalPortable.PtrToStructure(state.nextPtr); - + state.nextStream = Marshal.PtrToStructure(state.nextPtr); + state.filterSource = FilterSource.FromNativePtr(filterSourcePtr); state.output = new WriteStream(state.nextStream, state.nextPtr); @@ -270,7 +270,7 @@ int StreamCreateCallback(out IntPtr git_writestream_out, GitFilter self, IntPtr if (!activeStreams.TryAdd(state.thisPtr, state)) { - // AFAICT this is a theoretical error that could only happen if we manage + // AFAICT this is a theoretical error that could only happen if we manage // to free the stream pointer but fail to remove the dictionary entry. throw new InvalidOperationException("Overlapping stream pointers"); } diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index eef92c07c..3868a671b 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -23,7 +23,6 @@ static GlobalSettings() { if (Platform.OperatingSystem == OperatingSystemType.Windows) { -#if DESKTOP /* Assembly.CodeBase is not actually a correctly formatted * URI. It's merely prefixed with `file:///` and has its * backslashes flipped. This is superior to EscapedCodeBase, @@ -45,9 +44,6 @@ static GlobalSettings() } managedPath = Path.GetDirectoryName(managedPath); -#else - string managedPath = AppContext.BaseDirectory; -#endif nativeLibraryPath = Path.Combine(managedPath, "lib", "win32"); } diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index bb584d0fa..863c04d98 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - net40;netstandard2.0 + 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 @@ -12,7 +12,6 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true ..\libgit2sharp.snk - $(DefineConstants);DESKTOP diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 1f42d82dc..379d3e048 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -239,7 +239,7 @@ private unsafe Blob CreateBlob(Stream stream, string hintpath, long? numberOfByt } IntPtr writestream_ptr = Proxy.git_blob_create_fromstream(repo.Handle, hintpath); - GitWriteStream writestream = MarshalPortable.PtrToStructure(writestream_ptr); + GitWriteStream writestream = Marshal.PtrToStructure(writestream_ptr); try { From 587d2edc5b9c34d6c0169fccf2e3ee0169c05184 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 15:28:28 -0500 Subject: [PATCH 038/384] Remove unused package sources --- nuget.config | 2 -- 1 file changed, 2 deletions(-) diff --git a/nuget.config b/nuget.config index 82b40bac5..19d85b78f 100644 --- a/nuget.config +++ b/nuget.config @@ -2,7 +2,5 @@ - - From e3d2565a1389ea39787b76c79342b73d4f47dd7c Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 16:40:04 -0500 Subject: [PATCH 039/384] Fix test warnings --- LibGit2Sharp.Tests/BlameFixture.cs | 6 +- LibGit2Sharp.Tests/BlobFixture.cs | 2 +- LibGit2Sharp.Tests/BranchFixture.cs | 8 +- LibGit2Sharp.Tests/CheckoutFixture.cs | 25 +++-- LibGit2Sharp.Tests/CherryPickFixture.cs | 4 +- LibGit2Sharp.Tests/CleanFixture.cs | 4 +- LibGit2Sharp.Tests/CloneFixture.cs | 8 +- LibGit2Sharp.Tests/CommitFixture.cs | 36 +++---- LibGit2Sharp.Tests/ConfigurationFixture.cs | 22 ++--- LibGit2Sharp.Tests/ConflictFixture.cs | 4 +- LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs | 32 +++---- LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs | 94 +++++++++---------- .../DiffWorkdirToIndexFixture.cs | 8 +- LibGit2Sharp.Tests/FetchFixture.cs | 4 +- LibGit2Sharp.Tests/FileHistoryFixture.cs | 10 +- LibGit2Sharp.Tests/FilterBranchFixture.cs | 14 +-- LibGit2Sharp.Tests/FilterFixture.cs | 8 +- .../FilterSubstitutionCipherFixture.cs | 2 +- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 2 +- LibGit2Sharp.Tests/IgnoreFixture.cs | 6 +- LibGit2Sharp.Tests/IndexFixture.cs | 12 +-- LibGit2Sharp.Tests/LogFixture.cs | 4 +- LibGit2Sharp.Tests/MergeFixture.cs | 30 +++--- LibGit2Sharp.Tests/NetworkFixture.cs | 8 +- LibGit2Sharp.Tests/NoteFixture.cs | 30 +++--- LibGit2Sharp.Tests/ObjectDatabaseFixture.cs | 4 +- LibGit2Sharp.Tests/ObjectIdFixture.cs | 2 +- LibGit2Sharp.Tests/RebaseFixture.cs | 8 +- LibGit2Sharp.Tests/RefSpecFixture.cs | 5 +- LibGit2Sharp.Tests/ReferenceFixture.cs | 12 +-- LibGit2Sharp.Tests/ReflogFixture.cs | 10 +- LibGit2Sharp.Tests/RemoteFixture.cs | 2 +- LibGit2Sharp.Tests/RemoveFixture.cs | 2 +- LibGit2Sharp.Tests/RepositoryFixture.cs | 22 ++--- .../RepositoryOptionsFixture.cs | 4 +- LibGit2Sharp.Tests/ResetHeadFixture.cs | 2 +- LibGit2Sharp.Tests/ResetIndexFixture.cs | 12 +-- LibGit2Sharp.Tests/RevertFixture.cs | 2 +- LibGit2Sharp.Tests/StashFixture.cs | 16 ++-- LibGit2Sharp.Tests/StatusFixture.cs | 24 ++--- LibGit2Sharp.Tests/TagFixture.cs | 6 +- LibGit2Sharp.Tests/TreeFixture.cs | 2 +- LibGit2Sharp.Tests/UnstageFixture.cs | 12 +-- .../desktop/ShadowCopyFixture.cs | 2 +- .../desktop/SmartSubtransportFixture.cs | 2 +- 45 files changed, 266 insertions(+), 268 deletions(-) diff --git a/LibGit2Sharp.Tests/BlameFixture.cs b/LibGit2Sharp.Tests/BlameFixture.cs index 9138646c3..da63dc124 100644 --- a/LibGit2Sharp.Tests/BlameFixture.cs +++ b/LibGit2Sharp.Tests/BlameFixture.cs @@ -9,7 +9,7 @@ public class BlameFixture : BaseFixture { private static void AssertCorrectHeadBlame(BlameHunkCollection blame) { - Assert.Equal(1, blame.Count()); + Assert.Single(blame); Assert.Equal(0, blame[0].FinalStartLineNumber); Assert.Equal("schacon@gmail.com", blame[0].FinalSignature.Email); Assert.Equal("4a202b3", blame[0].FinalCommit.Id.ToString(7)); @@ -39,7 +39,7 @@ public void CanBlameFromADifferentCommit() Assert.Throws(() => repo.Blame("ancestor-only.txt")); var blame = repo.Blame("ancestor-only.txt", new BlameOptions { StartingAt = "9107b30" }); - Assert.Equal(1, blame.Count()); + Assert.Single(blame); } } @@ -79,7 +79,7 @@ public void CanStopBlame() // 9fd738e8 (Scott Chacon 2010-05-24 10:19:19 -0700 1) my new file // (be3563a comes after 9fd738e8) var blame = repo.Blame("new.txt", new BlameOptions {StoppingAt = "be3563a"}); - Assert.True(blame[0].FinalCommit.Sha.StartsWith("be3563a")); + Assert.StartsWith("be3563a", blame[0].FinalCommit.Sha); } } } diff --git a/LibGit2Sharp.Tests/BlobFixture.cs b/LibGit2Sharp.Tests/BlobFixture.cs index 371e50c51..e6a5f3c57 100644 --- a/LibGit2Sharp.Tests/BlobFixture.cs +++ b/LibGit2Sharp.Tests/BlobFixture.cs @@ -216,7 +216,7 @@ public void CanTellIfTheBlobContentLooksLikeBinary() using (var repo = new Repository(path)) { var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6"); - Assert.Equal(false, blob.IsBinary); + Assert.False(blob.IsBinary); } } diff --git a/LibGit2Sharp.Tests/BranchFixture.cs b/LibGit2Sharp.Tests/BranchFixture.cs index e06e81784..d8a47edfb 100644 --- a/LibGit2Sharp.Tests/BranchFixture.cs +++ b/LibGit2Sharp.Tests/BranchFixture.cs @@ -74,7 +74,7 @@ public void CanCreateAnUnbornBranch() Commit c = repo.Commit("New initial root commit", Constants.Signature, Constants.Signature); // Ensure this commit has no parent - Assert.Equal(0, c.Parents.Count()); + Assert.Empty(c.Parents); // The branch now exists... Branch orphan = repo.Branches["orphan"]; @@ -262,7 +262,7 @@ public void CreatingABranchTriggersTheCreationOfADirectReference() Reference reference = repo.Refs[newBranch.CanonicalName]; Assert.NotNull(reference); - Assert.IsType(typeof(DirectReference), reference); + Assert.IsType(reference); } } @@ -563,7 +563,7 @@ public void CanGetInformationFromUnbornBranch() var head = repo.Head; Assert.Equal("refs/heads/master", head.CanonicalName); - Assert.Equal(0, head.Commits.Count()); + Assert.Empty(head.Commits); Assert.True(head.IsCurrentRepositoryHead); Assert.False(head.IsRemote); Assert.Equal("master", head.FriendlyName); @@ -1123,7 +1123,7 @@ public void TrackedBranchExistsFromDefaultConfigInEmptyClone() using (var repo = new Repository(clonedRepoPath)) { Assert.Empty(Directory.GetFiles(scd2.RootedDirectoryPath)); - Assert.Equal(repo.Head.FriendlyName, "master"); + Assert.Equal("master", repo.Head.FriendlyName); Assert.Null(repo.Head.Tip); Assert.NotNull(repo.Head.TrackedBranch); diff --git a/LibGit2Sharp.Tests/CheckoutFixture.cs b/LibGit2Sharp.Tests/CheckoutFixture.cs index 8510b3d81..f0c2c36ed 100644 --- a/LibGit2Sharp.Tests/CheckoutFixture.cs +++ b/LibGit2Sharp.Tests/CheckoutFixture.cs @@ -526,13 +526,13 @@ public void CheckoutRetainsUntrackedChanges() string fullPathFileB = Touch(repo.Info.WorkingDirectory, "b.txt", alternateFileContent); // Verify that there is an untracked entry. - Assert.Equal(1, repo.RetrieveStatus().Untracked.Count()); + Assert.Single(repo.RetrieveStatus().Untracked); Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(fullPathFileB)); Commands.Checkout(repo, otherBranchName); // Verify untracked entry still exists. - Assert.Equal(1, repo.RetrieveStatus().Untracked.Count()); + Assert.Single(repo.RetrieveStatus().Untracked); Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(fullPathFileB)); } } @@ -550,13 +550,13 @@ public void ForceCheckoutRetainsUntrackedChanges() string fullPathFileB = Touch(repo.Info.WorkingDirectory, "b.txt", alternateFileContent); // Verify that there is an untracked entry. - Assert.Equal(1, repo.RetrieveStatus().Untracked.Count()); + Assert.Single(repo.RetrieveStatus().Untracked); Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(fullPathFileB)); Commands.Checkout(repo, otherBranchName, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force }); // Verify untracked entry still exists. - Assert.Equal(1, repo.RetrieveStatus().Untracked.Count()); + Assert.Single(repo.RetrieveStatus().Untracked); Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(fullPathFileB)); } } @@ -574,13 +574,13 @@ public void CheckoutRetainsUnstagedChanges() string fullPathFileA = Touch(repo.Info.WorkingDirectory, originalFilePath, alternateFileContent); // Verify that there is a modified entry. - Assert.Equal(1, repo.RetrieveStatus().Modified.Count()); + Assert.Single(repo.RetrieveStatus().Modified); Assert.Equal(FileStatus.ModifiedInWorkdir, repo.RetrieveStatus(fullPathFileA)); Commands.Checkout(repo, otherBranchName); // Verify modified entry still exists. - Assert.Equal(1, repo.RetrieveStatus().Modified.Count()); + Assert.Single(repo.RetrieveStatus().Modified); Assert.Equal(FileStatus.ModifiedInWorkdir, repo.RetrieveStatus(fullPathFileA)); } } @@ -599,13 +599,13 @@ public void CheckoutRetainsStagedChanges() Commands.Stage(repo, fullPathFileA); // Verify that there is a staged entry. - Assert.Equal(1, repo.RetrieveStatus().Staged.Count()); + Assert.Single(repo.RetrieveStatus().Staged); Assert.Equal(FileStatus.ModifiedInIndex, repo.RetrieveStatus(fullPathFileA)); Commands.Checkout(repo, otherBranchName); // Verify staged entry still exists. - Assert.Equal(1, repo.RetrieveStatus().Staged.Count()); + Assert.Single(repo.RetrieveStatus().Staged); Assert.Equal(FileStatus.ModifiedInIndex, repo.RetrieveStatus(fullPathFileA)); } } @@ -625,7 +625,7 @@ public void CheckoutRetainsIgnoredChanges() "bin/some_ignored_file.txt", "hello from this ignored file."); - Assert.Equal(1, repo.RetrieveStatus(new StatusOptions { IncludeIgnored = true }).Ignored.Count()); + Assert.Single(repo.RetrieveStatus(new StatusOptions { IncludeIgnored = true }).Ignored); Assert.Equal(FileStatus.Ignored, repo.RetrieveStatus(ignoredFilePath)); @@ -652,7 +652,7 @@ public void ForceCheckoutRetainsIgnoredChanges() "bin/some_ignored_file.txt", "hello from this ignored file."); - Assert.Equal(1, repo.RetrieveStatus(new StatusOptions { IncludeIgnored = true }).Ignored.Count()); + Assert.Single(repo.RetrieveStatus(new StatusOptions { IncludeIgnored = true }).Ignored); Assert.Equal(FileStatus.Ignored, repo.RetrieveStatus(ignoredFilePath)); @@ -958,7 +958,7 @@ public void CanCheckoutPath(string originalBranch, string checkoutFrom, string p repo.CheckoutPaths(checkoutFrom, new[] { path }); Assert.Equal(expectedStatus, repo.RetrieveStatus(path)); - Assert.Equal(1, repo.RetrieveStatus().Count()); + Assert.Single(repo.RetrieveStatus()); } } @@ -995,8 +995,7 @@ public void CannotCheckoutPathsWithEmptyOrNullPathArgument() Assert.False(repo.RetrieveStatus().IsDirty); // Passing null 'paths' parameter should throw - Assert.Throws(typeof(ArgumentNullException), - () => repo.CheckoutPaths("i-do-numbers", null)); + Assert.Throws(() => repo.CheckoutPaths("i-do-numbers", null)); // Passing empty list should do nothing repo.CheckoutPaths("i-do-numbers", Enumerable.Empty()); diff --git a/LibGit2Sharp.Tests/CherryPickFixture.cs b/LibGit2Sharp.Tests/CherryPickFixture.cs index 1bbff1428..3c0026df5 100644 --- a/LibGit2Sharp.Tests/CherryPickFixture.cs +++ b/LibGit2Sharp.Tests/CherryPickFixture.cs @@ -66,7 +66,7 @@ public void CherryPickWithConflictDoesNotCommit() Assert.Equal(CherryPickStatus.Conflicts, cherryPickResult.Status); Assert.Null(cherryPickResult.Commit); - Assert.Equal(1, repo.Index.Conflicts.Count()); + Assert.Single(repo.Index.Conflicts); var conflict = repo.Index.Conflicts.First(); var changes = repo.Diff.Compare(repo.Lookup(conflict.Theirs.Id), repo.Lookup(conflict.Ours.Id)); @@ -139,7 +139,7 @@ public void CanCherryPickCommit() var result = repo.ObjectDatabase.CherryPickCommit(commitToMerge, ours, 0, null); Assert.Equal(MergeTreeStatus.Succeeded, result.Status); - Assert.Equal(0, result.Conflicts.Count()); + Assert.Empty(result.Conflicts); } } diff --git a/LibGit2Sharp.Tests/CleanFixture.cs b/LibGit2Sharp.Tests/CleanFixture.cs index f674285c6..39c7a6152 100644 --- a/LibGit2Sharp.Tests/CleanFixture.cs +++ b/LibGit2Sharp.Tests/CleanFixture.cs @@ -14,13 +14,13 @@ public void CanCleanWorkingDirectory() { // Verify that there are the expected number of entries and untracked files Assert.Equal(6, repo.RetrieveStatus().Count()); - Assert.Equal(1, repo.RetrieveStatus().Untracked.Count()); + Assert.Single(repo.RetrieveStatus().Untracked); repo.RemoveUntrackedFiles(); // Verify that there are the expected number of entries and 0 untracked files Assert.Equal(5, repo.RetrieveStatus().Count()); - Assert.Equal(0, repo.RetrieveStatus().Untracked.Count()); + Assert.Empty(repo.RetrieveStatus().Untracked); } } diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 84fa5f312..00dc9fee6 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -33,8 +33,8 @@ public void CanClone(string url) Assert.False(repo.Info.IsBare); Assert.True(File.Exists(Path.Combine(scd.RootedDirectoryPath, "master.txt"))); - Assert.Equal(repo.Head.FriendlyName, "master"); - Assert.Equal(repo.Head.Tip.Id.ToString(), "49322bb17d3acc9146f98c97d078513228bbf3c0"); + Assert.Equal("master", repo.Head.FriendlyName); + Assert.Equal("49322bb17d3acc9146f98c97d078513228bbf3c0", repo.Head.Tip.Id.ToString()); } } @@ -74,7 +74,7 @@ private void AssertLocalClone(string url, string path = null, bool isCloningAnEm Assert.Equal(isCloningAnEmptyRepository ? 0 : 1, clonedRepo.Branches.Count(b => !b.IsRemote)); Assert.Equal(originalRepo.Tags.Count(), clonedRepo.Tags.Count()); - Assert.Equal(1, clonedRepo.Network.Remotes.Count()); + Assert.Single(clonedRepo.Network.Remotes); } } @@ -263,7 +263,7 @@ public void CanInspectCertificateOnClone(string url, string hostname, Type certT Assert.True(valid); var x509 = ((CertificateX509)cert).Certificate; // we get a string with the different fields instead of a structure, so... - Assert.True(x509.Subject.Contains("CN=github.com,")); + Assert.Contains("CN=github.com,", x509.Subject); checksHappy = true; return false; } diff --git a/LibGit2Sharp.Tests/CommitFixture.cs b/LibGit2Sharp.Tests/CommitFixture.cs index b522e3c34..179a4975c 100644 --- a/LibGit2Sharp.Tests/CommitFixture.cs +++ b/LibGit2Sharp.Tests/CommitFixture.cs @@ -70,7 +70,7 @@ public void CanEnumerateCommitsInDetachedHeadState() ObjectId parentOfHead = repo.Head.Tip.Parents.First().Id; repo.Refs.Add("HEAD", parentOfHead.Sha, true); - Assert.Equal(true, repo.Info.IsHeadDetached); + Assert.True(repo.Info.IsHeadDetached); Assert.Equal(6, repo.Commits.Count()); } @@ -156,7 +156,7 @@ public void CanEnumerateCommitsWithReverseTimeSorting() })) { Assert.NotNull(commit); - Assert.True(commit.Sha.StartsWith(reversedShas[count])); + Assert.StartsWith(reversedShas[count], commit.Sha); count++; } } @@ -204,7 +204,7 @@ public void CanGetParentsCount() string path = SandboxBareTestRepo(); using (var repo = new Repository(path)) { - Assert.Equal(1, repo.Commits.First().Parents.Count()); + Assert.Single(repo.Commits.First().Parents); } } @@ -222,7 +222,7 @@ public void CanEnumerateCommitsWithTimeSorting() })) { Assert.NotNull(commit); - Assert.True(commit.Sha.StartsWith(expectedShas[count])); + Assert.StartsWith(expectedShas[count], commit.Sha); count++; } } @@ -484,7 +484,7 @@ public void CanReadCommitData() Assert.Equal("181037049a54a1eb5fab404658a3a250b44335d7", commit.Tree.Sha); - Assert.Equal(0, commit.Parents.Count()); + Assert.Empty(commit.Parents); } } @@ -590,8 +590,8 @@ public void CommitParentsAreMergeHeads() Assert.Equal(CurrentOperation.None, repo.Info.CurrentOperation); Assert.Equal(2, newMergedCommit.Parents.Count()); - Assert.Equal(newMergedCommit.Parents.First().Sha, "c47800c7266a2be04c571c04d5a6614691ea99bd"); - Assert.Equal(newMergedCommit.Parents.Skip(1).First().Sha, "9fd738e8f7967c078dceed8190330fc8648ee56a"); + Assert.Equal("c47800c7266a2be04c571c04d5a6614691ea99bd", newMergedCommit.Parents.First().Sha); + Assert.Equal("9fd738e8f7967c078dceed8190330fc8648ee56a", newMergedCommit.Parents.Skip(1).First().Sha); // Assert reflog entry is created var reflogEntry = repo.Refs.Log(repo.Refs.Head).First(); @@ -670,11 +670,11 @@ public void CanCommitALittleBit() AssertBlobContent(repo.Head[relativeFilepath], "nulltoken\n"); AssertBlobContent(commit[relativeFilepath], "nulltoken\n"); - Assert.Equal(0, commit.Parents.Count()); + Assert.Empty(commit.Parents); Assert.False(repo.Info.IsHeadUnborn); // Assert a reflog entry is created on HEAD - Assert.Equal(1, repo.Refs.Log("HEAD").Count()); + Assert.Single(repo.Refs.Log("HEAD")); var reflogEntry = repo.Refs.Log("HEAD").First(); Assert.Equal(identity.Name, reflogEntry.Committer.Name); @@ -689,7 +689,7 @@ public void CanCommitALittleBit() // Assert a reflog entry is created on HEAD target var targetCanonicalName = repo.Refs.Head.TargetIdentifier; - Assert.Equal(1, repo.Refs.Log(targetCanonicalName).Count()); + Assert.Single(repo.Refs.Log(targetCanonicalName)); Assert.Equal(commit.Id, repo.Refs.Log(targetCanonicalName).First().To); File.WriteAllText(filePath, "nulltoken commits!\n"); @@ -701,7 +701,7 @@ public void CanCommitALittleBit() AssertBlobContent(repo.Head[relativeFilepath], "nulltoken commits!\n"); AssertBlobContent(commit2[relativeFilepath], "nulltoken commits!\n"); - Assert.Equal(1, commit2.Parents.Count()); + Assert.Single(commit2.Parents); Assert.Equal(commit.Id, commit2.Parents.First().Id); // Assert the reflog is shifted @@ -721,7 +721,7 @@ public void CanCommitALittleBit() AssertBlobContent(repo.Head[relativeFilepath], "davidfowl commits!\n"); AssertBlobContent(commit3[relativeFilepath], "davidfowl commits!\n"); - Assert.Equal(1, commit3.Parents.Count()); + Assert.Single(commit3.Parents); Assert.Equal(commit.Id, commit3.Parents.First().Id); AssertBlobContent(firstCommitBranch[relativeFilepath], "nulltoken\n"); @@ -776,17 +776,17 @@ public void CanAmendARootCommit() using (var repo = new Repository(repoPath)) { - Assert.Equal(1, repo.Head.Commits.Count()); + Assert.Single(repo.Head.Commits); Commit originalCommit = repo.Head.Tip; - Assert.Equal(0, originalCommit.Parents.Count()); + Assert.Empty(originalCommit.Parents); CreateAndStageANewFile(repo); Commit amendedCommit = repo.Commit("I'm rewriting the history!", Constants.Signature, Constants.Signature, new CommitOptions { AmendPreviousCommit = true }); - Assert.Equal(1, repo.Head.Commits.Count()); + Assert.Single(repo.Head.Commits); AssertCommitHasBeenAmended(repo, amendedCommit, originalCommit); } @@ -918,7 +918,7 @@ public void CanCommitOnOrphanedBranch() Commands.Stage(repo, relativeFilepath); repo.Commit("Initial commit", Constants.Signature, Constants.Signature); - Assert.Equal(1, repo.Head.Commits.Count()); + Assert.Single(repo.Head.Commits); } } @@ -1000,8 +1000,8 @@ public void CanCommitAnEmptyCommitWhenMerging() Commit newMergedCommit = repo.Commit("Merge commit", Constants.Signature, Constants.Signature); Assert.Equal(2, newMergedCommit.Parents.Count()); - Assert.Equal(newMergedCommit.Parents.First().Sha, "32eab9cb1f450b5fe7ab663462b77d7f4b703344"); - Assert.Equal(newMergedCommit.Parents.Skip(1).First().Sha, "f705abffe7015f2beacf2abe7a36583ebee3487e"); + Assert.Equal("32eab9cb1f450b5fe7ab663462b77d7f4b703344", newMergedCommit.Parents.First().Sha); + Assert.Equal("f705abffe7015f2beacf2abe7a36583ebee3487e", newMergedCommit.Parents.Skip(1).First().Sha); } } diff --git a/LibGit2Sharp.Tests/ConfigurationFixture.cs b/LibGit2Sharp.Tests/ConfigurationFixture.cs index 3e071c3b7..5bb985b68 100644 --- a/LibGit2Sharp.Tests/ConfigurationFixture.cs +++ b/LibGit2Sharp.Tests/ConfigurationFixture.cs @@ -59,9 +59,9 @@ public void CanReadBooleanValue() Assert.True(repo.Config.Get("core.ignorecase").Value); Assert.True(repo.Config.GetValueOrDefault("core.ignorecase")); - Assert.Equal(false, repo.Config.GetValueOrDefault("missing.key")); - Assert.Equal(true, repo.Config.GetValueOrDefault("missing.key", true)); - Assert.Equal(true, repo.Config.GetValueOrDefault("missing.key", () => true)); + Assert.False(repo.Config.GetValueOrDefault("missing.key")); + Assert.True(repo.Config.GetValueOrDefault("missing.key", true)); + Assert.True(repo.Config.GetValueOrDefault("missing.key", () => true)); } } @@ -110,26 +110,26 @@ public void CanReadStringValue() Assert.Equal("+refs/heads/*:refs/remotes/origin/*", repo.Config.GetValueOrDefault("remote", "origin", "fetch")); Assert.Equal("+refs/heads/*:refs/remotes/origin/*", repo.Config.GetValueOrDefault(new[] { "remote", "origin", "fetch" })); - Assert.Equal(null, repo.Config.GetValueOrDefault("missing.key")); - Assert.Equal(null, repo.Config.GetValueOrDefault("missing.key", default(string))); + Assert.Null(repo.Config.GetValueOrDefault("missing.key")); + Assert.Null(repo.Config.GetValueOrDefault("missing.key", default(string))); Assert.Throws(() => repo.Config.GetValueOrDefault("missing.key", default(Func))); Assert.Equal("value", repo.Config.GetValueOrDefault("missing.key", "value")); Assert.Equal("value", repo.Config.GetValueOrDefault("missing.key", () => "value")); - Assert.Equal(null, repo.Config.GetValueOrDefault("missing.key", ConfigurationLevel.Local)); - Assert.Equal(null, repo.Config.GetValueOrDefault("missing.key", ConfigurationLevel.Local, default(string))); + Assert.Null(repo.Config.GetValueOrDefault("missing.key", ConfigurationLevel.Local)); + Assert.Null(repo.Config.GetValueOrDefault("missing.key", ConfigurationLevel.Local, default(string))); Assert.Throws(() => repo.Config.GetValueOrDefault("missing.key", ConfigurationLevel.Local, default(Func))); Assert.Equal("value", repo.Config.GetValueOrDefault("missing.key", ConfigurationLevel.Local, "value")); Assert.Equal("value", repo.Config.GetValueOrDefault("missing.key", ConfigurationLevel.Local, () => "value")); - Assert.Equal(null, repo.Config.GetValueOrDefault("missing", "config", "key")); - Assert.Equal(null, repo.Config.GetValueOrDefault("missing", "config", "key", default(string))); + Assert.Null(repo.Config.GetValueOrDefault("missing", "config", "key")); + Assert.Null(repo.Config.GetValueOrDefault("missing", "config", "key", default(string))); Assert.Throws(() => repo.Config.GetValueOrDefault("missing", "config", "key", default(Func))); Assert.Equal("value", repo.Config.GetValueOrDefault("missing", "config", "key", "value")); Assert.Equal("value", repo.Config.GetValueOrDefault("missing", "config", "key", () => "value")); - Assert.Equal(null, repo.Config.GetValueOrDefault(new[] { "missing", "key" })); - Assert.Equal(null, repo.Config.GetValueOrDefault(new[] { "missing", "key" }, default(string))); + Assert.Null(repo.Config.GetValueOrDefault(new[] { "missing", "key" })); + Assert.Null(repo.Config.GetValueOrDefault(new[] { "missing", "key" }, default(string))); Assert.Throws(() => repo.Config.GetValueOrDefault(new[] { "missing", "key" }, default(Func))); Assert.Equal("value", repo.Config.GetValueOrDefault(new[] { "missing", "key" }, "value")); Assert.Equal("value", repo.Config.GetValueOrDefault(new[] { "missing", "key" }, () => "value")); diff --git a/LibGit2Sharp.Tests/ConflictFixture.cs b/LibGit2Sharp.Tests/ConflictFixture.cs index cabf4a4cf..b28270b7e 100644 --- a/LibGit2Sharp.Tests/ConflictFixture.cs +++ b/LibGit2Sharp.Tests/ConflictFixture.cs @@ -75,7 +75,7 @@ public void CanResolveConflictsByRemovingFromTheIndex( Assert.Equal(existsBeforeRemove, File.Exists(fullpath)); Assert.NotNull(repo.Index.Conflicts[filename]); - Assert.Equal(0, repo.Index.Conflicts.ResolvedConflicts.Count()); + Assert.Empty(repo.Index.Conflicts.ResolvedConflicts); Commands.Remove(repo, filename, removeFromWorkdir); @@ -84,7 +84,7 @@ public void CanResolveConflictsByRemovingFromTheIndex( Assert.Equal(existsAfterRemove, File.Exists(fullpath)); Assert.Equal(lastStatus, repo.RetrieveStatus(filename)); - Assert.Equal(1, repo.Index.Conflicts.ResolvedConflicts.Count()); + Assert.Single(repo.Index.Conflicts.ResolvedConflicts); Assert.NotNull(repo.Index.Conflicts.ResolvedConflicts[filename]); } } diff --git a/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs index 71aad3755..2fb359f24 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs @@ -46,7 +46,7 @@ public void CanCompareASimpleTreeAgainstTheWorkDir() using (var changes = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTargets.WorkingDirectory)) { - Assert.Equal(1, changes.Modified.Count()); + Assert.Single(changes.Modified); } using (var patch = repo.Diff.Compare(repo.Head.Tip.Tree, @@ -116,7 +116,7 @@ public void CanCompareASimpleTreeAgainstTheWorkDirAndTheIndex() using (var changes = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTargets.Index | DiffTargets.WorkingDirectory)) { - Assert.Equal(1, changes.Modified.Count()); + Assert.Single(changes.Modified); } using (var patch = repo.Diff.Compare(repo.Head.Tip.Tree, @@ -178,8 +178,8 @@ public void ShowcaseTheDifferenceBetweenTheTwoKindOfComparison() using (var wrkDirToIdxToTree = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTargets.Index | DiffTargets.WorkingDirectory)) { - Assert.Equal(1, wrkDirToIdxToTree.Deleted.Count()); - Assert.Equal(0, wrkDirToIdxToTree.Modified.Count()); + Assert.Single(wrkDirToIdxToTree.Deleted); + Assert.Empty(wrkDirToIdxToTree.Modified); } using (var patch = repo.Diff.Compare(repo.Head.Tip.Tree, @@ -200,8 +200,8 @@ public void ShowcaseTheDifferenceBetweenTheTwoKindOfComparison() using (var wrkDirToTree = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTargets.WorkingDirectory)) { - Assert.Equal(0, wrkDirToTree.Deleted.Count()); - Assert.Equal(1, wrkDirToTree.Modified.Count()); + Assert.Empty(wrkDirToTree.Deleted); + Assert.Single(wrkDirToTree.Modified); } using (var patch = repo.Diff.Compare(repo.Head.Tip.Tree, @@ -244,7 +244,7 @@ public void CanCompareASimpleTreeAgainstTheIndex() using (var changes = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTargets.Index)) { - Assert.Equal(1, changes.Modified.Count()); + Assert.Single(changes.Modified); } using (var patch = repo.Diff.Compare(repo.Head.Tip.Tree, @@ -331,7 +331,7 @@ public void CanCompareASubsetofTheTreeAgainstTheIndex() { Assert.NotNull(changes); - Assert.Equal(1, changes.Count()); + Assert.Single(changes); Assert.Equal("deleted_staged_file.txt", changes.Deleted.Single().Path); } } @@ -340,7 +340,7 @@ public void CanCompareASubsetofTheTreeAgainstTheIndex() private static void AssertCanCompareASubsetOfTheTreeAgainstTheIndex(TreeChanges changes) { Assert.NotNull(changes); - Assert.Equal(1, changes.Count()); + Assert.Single(changes); Assert.Equal("deleted_staged_file.txt", changes.Deleted.Single().Path); } @@ -413,7 +413,7 @@ public void CanCopeWithEndOfFileNewlineChanges() using (var changes = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTargets.Index)) { - Assert.Equal(1, changes.Modified.Count()); + Assert.Single(changes.Modified); } using (var patch = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTargets.Index)) @@ -462,8 +462,8 @@ public void CanCompareANullTreeAgainstTheIndex() using (var changes = repo.Diff.Compare(null, DiffTargets.Index)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Added.Count()); + Assert.Single(changes); + Assert.Single(changes.Added); Assert.Equal("file.txt", changes.Added.Single().Path); } @@ -482,8 +482,8 @@ public void CanCompareANullTreeAgainstTheWorkdir() using (var changes = repo.Diff.Compare(null, DiffTargets.WorkingDirectory)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Added.Count()); + Assert.Single(changes); + Assert.Single(changes.Added); Assert.Equal("file.txt", changes.Added.Single().Path); } @@ -502,8 +502,8 @@ public void CanCompareANullTreeAgainstTheWorkdirAndTheIndex() using (var changes = repo.Diff.Compare(null, DiffTargets.WorkingDirectory | DiffTargets.Index)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Added.Count()); + Assert.Single(changes); + Assert.Single(changes.Added); Assert.Equal("file.txt", changes.Added.Single().Path); } diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs index e1e6359e1..dba762bfe 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs @@ -64,8 +64,8 @@ public void CanCompareACommitTreeAgainstItsParent() using (var changes = repo.Diff.Compare(parentCommitTree, commitTree)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Added.Count()); + Assert.Single(changes); + Assert.Single(changes.Added); TreeEntryChanges treeEntryChanges = changes.Single(c => c.Path == "1.txt"); @@ -172,7 +172,7 @@ public void CanCompareASubsetofTheTreeAgainstOneOfItsAncestor() { Assert.NotNull(changes); - Assert.Equal(1, changes.Count()); + Assert.Single(changes); Assert.Equal(subBranchFilePath, changes.Added.Single().Path); } } @@ -205,7 +205,7 @@ public void CanCompareACommitTreeAgainstATreeWithNoCommonAncestor() { Assert.Equal(10, changes.Count()); Assert.Equal(9, changes.Added.Count()); - Assert.Equal(1, changes.Deleted.Count()); + Assert.Single(changes.Deleted); Assert.Equal("readme.txt", changes.Deleted.Single().Path); Assert.Equal(new[] { "1.txt", subBranchFilePath, "README", "branch_file.txt", "deleted_staged_file.txt", "deleted_unstaged_file.txt", "modified_staged_file.txt", "modified_unstaged_file.txt", "new.txt" }, @@ -233,13 +233,13 @@ public void CanCompareATreeAgainstAnotherTreeWithLaxExplicitPathsValidationAndNo using (var changes = repo.Diff.Compare(commitTreeWithDifferentAncestor, commitTree, new[] { "if-I-exist-this-test-is-really-unlucky.txt" }, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false })) { - Assert.Equal(0, changes.Count()); + Assert.Empty(changes); } using (var changes = repo.Diff.Compare(commitTreeWithDifferentAncestor, commitTree, new[] { "if-I-exist-this-test-is-really-unlucky.txt" })) { - Assert.Equal(0, changes.Count()); + Assert.Empty(changes); } } } @@ -288,9 +288,9 @@ public void DetectsTheRenamingOfAModifiedFileByDefault() using (var changes = repo.Diff.Compare(rootCommitTree, commitTreeWithRenamedFile)) { - Assert.Equal(1, changes.Count()); + Assert.Single(changes); Assert.Equal("my-name-does-not-feel-right.txt", changes.Single(c => c.Path == "super-file.txt").OldPath); - Assert.Equal(1, changes.Renamed.Count()); + Assert.Single(changes.Renamed); } } } @@ -317,8 +317,8 @@ public void DetectsTheExactRenamingOfFilesByDefault() using (var changes = repo.Diff.Compare(old.Tree, @new.Tree)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Renamed.Count()); + Assert.Single(changes); + Assert.Single(changes.Renamed); Assert.Equal(originalPath, changes.Renamed.Single().OldPath); Assert.Equal(renamedPath, changes.Renamed.Single().Path); } @@ -370,7 +370,7 @@ public void RenameThresholdsAreObeyed() compareOptions.Similarity.RenameThreshold = 90; using (var changes = repo.Diff.Compare(old.Tree, @new.Tree, compareOptions: compareOptions)) - Assert.False(changes.Any(x => x.Status == ChangeKind.Renamed)); + Assert.DoesNotContain(changes, x => x.Status == ChangeKind.Renamed); } } @@ -400,8 +400,8 @@ public void ExactModeDetectsExactRenames() Similarity = SimilarityOptions.Exact, })) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Renamed.Count()); + Assert.Single(changes); + Assert.Single(changes.Renamed); Assert.Equal(originalPath, changes.Renamed.Single().OldPath); Assert.Equal(renamedPath, changes.Renamed.Single().Path); } @@ -435,8 +435,8 @@ public void ExactModeDetectsExactCopies() Similarity = SimilarityOptions.Exact, })) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Copied.Count()); + Assert.Single(changes); + Assert.Single(changes.Copied); } } } @@ -470,9 +470,9 @@ public void ExactModeDoesntDetectRenamesWithEdits() })) { Assert.Equal(2, changes.Count()); - Assert.Equal(0, changes.Renamed.Count()); - Assert.Equal(1, changes.Added.Count()); - Assert.Equal(1, changes.Deleted.Count()); + Assert.Empty(changes.Renamed); + Assert.Single(changes.Added); + Assert.Single(changes.Deleted); } } } @@ -509,8 +509,8 @@ public void CanIncludeUnmodifiedEntriesWhenDetectingTheExactRenamingOfFilesWhenE })) { Assert.Equal(2, changes.Count()); - Assert.Equal(1, changes.Unmodified.Count()); - Assert.Equal(1, changes.Copied.Count()); + Assert.Single(changes.Unmodified); + Assert.Single(changes.Copied); Assert.Equal(originalPath, changes.Copied.Single().OldPath); Assert.Equal(copiedPath, changes.Copied.Single().Path); } @@ -545,7 +545,7 @@ public void CanNotDetectTheExactRenamingFilesWhenNotEnabled() })) { Assert.Equal(2, changes.Count()); - Assert.Equal(0, changes.Renamed.Count()); + Assert.Empty(changes.Renamed); } } } @@ -580,8 +580,8 @@ public void CanDetectTheExactCopyingOfNonModifiedFilesWhenEnabled() Similarity = SimilarityOptions.CopiesHarder, })) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Copied.Count()); + Assert.Single(changes); + Assert.Single(changes.Copied); Assert.Equal(originalPath, changes.Copied.Single().OldPath); Assert.Equal(copiedPath, changes.Copied.Single().Path); } @@ -613,8 +613,8 @@ public void CanNotDetectTheExactCopyingOfNonModifiedFilesWhenNotEnabled() using (var changes = repo.Diff.Compare(old.Tree, @new.Tree)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(0, changes.Copied.Count()); + Assert.Single(changes); + Assert.Empty(changes.Copied); } } } @@ -653,7 +653,7 @@ public void CanDetectTheExactCopyingOfModifiedFilesWhenEnabled() })) { Assert.Equal(2, changes.Count()); - Assert.Equal(1, changes.Copied.Count()); + Assert.Single(changes.Copied); Assert.Equal(originalPath, changes.Copied.Single().OldPath); Assert.Equal(copiedPath, changes.Copied.Single().Path); } @@ -689,7 +689,7 @@ public void CanNotDetectTheExactCopyingOfModifiedFilesWhenNotEnabled() using (var changes = repo.Diff.Compare(old.Tree, @new.Tree)) { Assert.Equal(2, changes.Count()); - Assert.Equal(0, changes.Copied.Count()); + Assert.Empty(changes.Copied); } } } @@ -715,8 +715,8 @@ public void CanIncludeUnmodifiedEntriesWhenEnabled() compareOptions: new CompareOptions { IncludeUnmodified = true })) { Assert.Equal(2, changes.Count()); - Assert.Equal(1, changes.Unmodified.Count()); - Assert.Equal(1, changes.Modified.Count()); + Assert.Single(changes.Unmodified); + Assert.Single(changes.Modified); } } } @@ -768,8 +768,8 @@ public void CanDetectTheExactRenamingExactCopyingOfNonModifiedAndModifiedFilesWh })) { Assert.Equal(4, changes.Count()); - Assert.Equal(1, changes.Modified.Count()); - Assert.Equal(1, changes.Renamed.Count()); + Assert.Single(changes.Modified); + Assert.Single(changes.Renamed); Assert.Equal(originalPath, changes.Renamed.Single().OldPath); Assert.Equal(renamedPath, changes.Renamed.Single().Path); Assert.Equal(2, changes.Copied.Count()); @@ -818,8 +818,8 @@ public void CanCompareTwoVersionsOfAFileWithATrailingNewlineDeletion(int context using (var changes = repo.Diff.Compare(rootCommitTree, commitTreeWithUpdatedFile)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Modified.Count()); + Assert.Single(changes); + Assert.Single(changes.Modified); } using (var patch = repo.Diff.Compare(rootCommitTree, commitTreeWithUpdatedFile, @@ -917,9 +917,9 @@ public void CanCompareTwoVersionsOfAFileWithADiffOfTwoHunks(int contextLines, in using (var changes = repo.Diff.Compare(rootCommitTree, mergedCommitTree, compareOptions: compareOptions)) { Assert.Equal(3, changes.Count()); - Assert.Equal(1, changes.Modified.Count()); - Assert.Equal(1, changes.Deleted.Count()); - Assert.Equal(1, changes.Added.Count()); + Assert.Single(changes.Modified); + Assert.Single(changes.Deleted); + Assert.Single(changes.Added); Assert.Equal(Mode.Nonexistent, changes.Single(c => c.Path == "my-name-does-not-feel-right.txt").Mode); } @@ -983,8 +983,8 @@ public void CanHandleTwoTreeEntryChangesWithTheSamePathUsingSimilarityNone() (path, changes) => { Assert.Equal(2, changes.Count()); - Assert.Equal(1, changes.Deleted.Count()); - Assert.Equal(1, changes.TypeChanged.Count()); + Assert.Single(changes.Deleted); + Assert.Single(changes.TypeChanged); TreeEntryChanges change = changes.Single(c => c.Path== path); Assert.Equal(Mode.SymbolicLink, change.OldMode); @@ -1005,8 +1005,8 @@ public void CanHandleTwoTreeEntryChangesWithTheSamePathUsingSimilarityDefault() (path, changes) => { Assert.Equal(2, changes.Count()); - Assert.Equal(1, changes.Deleted.Count()); - Assert.Equal(1, changes.Renamed.Count()); + Assert.Single(changes.Deleted); + Assert.Single(changes.Renamed); TreeEntryChanges renamed = changes.Renamed.Single(); Assert.Equal(Mode.NonExecutableFile, renamed.OldMode); @@ -1032,16 +1032,16 @@ public void CanCompareATreeAgainstANullTree() using (var changes = repo.Diff.Compare(tree, null)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Deleted.Count()); + Assert.Single(changes); + Assert.Single(changes.Deleted); Assert.Equal("readme.txt", changes.Deleted.Single().Path); } using (var changes = repo.Diff.Compare(null, tree)) { - Assert.Equal(1, changes.Count()); - Assert.Equal(1, changes.Added.Count()); + Assert.Single(changes); + Assert.Single(changes.Added); Assert.Equal("readme.txt", changes.Added.Single().Path); } @@ -1056,7 +1056,7 @@ public void ComparingTwoNullTreesReturnsAnEmptyTreeChanges() { using (var changes = repo.Diff.Compare(default(Tree), default(Tree))) { - Assert.Equal(0, changes.Count()); + Assert.Empty(changes); } } } @@ -1089,7 +1089,7 @@ public void ComparingReliesOnProvidedConfigEntriesIfAny() SetFilemode(repo, true); using(var changes = repo.Diff.Compare(new[] { file })) { - Assert.Equal(1, changes.Count()); + Assert.Single(changes); var change = changes.Modified.Single(); Assert.Equal(Mode.ExecutableFile, change.OldMode); @@ -1102,7 +1102,7 @@ public void ComparingReliesOnProvidedConfigEntriesIfAny() SetFilemode(repo, false); using (var changes = repo.Diff.Compare(new[] { file })) { - Assert.Equal(0, changes.Count()); + Assert.Empty(changes); } } } diff --git a/LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs b/LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs index ba7658ebc..430859577 100644 --- a/LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs +++ b/LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs @@ -54,12 +54,12 @@ public void CanCompareTheWorkDirAgainstTheIndexWithLaxUnmatchedExplicitPathsVali using (var changes = repo.Diff.Compare(new[] { relativePath }, false, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false })) { - Assert.Equal(0, changes.Count()); + Assert.Empty(changes); } using (var changes = repo.Diff.Compare(new[] { relativePath })) { - Assert.Equal(0, changes.Count()); + Assert.Empty(changes); } } } @@ -139,7 +139,7 @@ public void ComparingReliesOnProvidedConfigEntriesIfAny() SetFilemode(repo, true); using(var changes = repo.Diff.Compare(new[] { file })) { - Assert.Equal(1, changes.Count()); + Assert.Single(changes); var change = changes.Modified.Single(); Assert.Equal(Mode.ExecutableFile, change.OldMode); @@ -152,7 +152,7 @@ public void ComparingReliesOnProvidedConfigEntriesIfAny() SetFilemode(repo, false); using(var changes = repo.Diff.Compare(new[] { file })) { - Assert.Equal(0, changes.Count()); + Assert.Empty(changes); } } } diff --git a/LibGit2Sharp.Tests/FetchFixture.cs b/LibGit2Sharp.Tests/FetchFixture.cs index 6c88317dc..dfe958fc0 100644 --- a/LibGit2Sharp.Tests/FetchFixture.cs +++ b/LibGit2Sharp.Tests/FetchFixture.cs @@ -110,7 +110,7 @@ public void CanFetchAllTagsIntoAnEmptyRepository(string url) expectedFetchState.CheckUpdatedReferences(repo); // Verify the reflog entries - Assert.Equal(1, repo.Refs.Log(string.Format("refs/remotes/{0}/master", remoteName)).Count()); // Branches are also retrieved + Assert.Single(repo.Refs.Log(string.Format("refs/remotes/{0}/master", remoteName))); // Branches are also retrieved } } @@ -157,7 +157,7 @@ public void CanFetchCustomRefSpecsIntoAnEmptyRepository(string url, string local // Verify the reflog entries var reflogEntry = repo.Refs.Log(string.Format("refs/remotes/{0}/{1}", remoteName, localBranchName)).Single(); - Assert.True(reflogEntry.Message.StartsWith("fetch ")); + Assert.StartsWith("fetch ", reflogEntry.Message); } } diff --git a/LibGit2Sharp.Tests/FileHistoryFixture.cs b/LibGit2Sharp.Tests/FileHistoryFixture.cs index 096cdbeeb..5380e66de 100644 --- a/LibGit2Sharp.Tests/FileHistoryFixture.cs +++ b/LibGit2Sharp.Tests/FileHistoryFixture.cs @@ -30,7 +30,7 @@ public void CanDealWithFollowTest(string url) // $ git log --follow --format=oneline untouched.txt // c10c1d5f74b76f20386d18674bf63fbee6995061 Initial commit fileHistoryEntries = repo.Commits.QueryBy("untouched.txt").ToList(); - Assert.Equal(1, fileHistoryEntries.Count()); + Assert.Single(fileHistoryEntries); Assert.Equal("c10c1d5f74b76f20386d18674bf63fbee6995061", fileHistoryEntries[0].Commit.Sha); // $ git log --follow --format=oneline under-test.txt @@ -223,8 +223,8 @@ public void CanTellSingleCommitHistory() IEnumerable history = repo.Commits.QueryBy(path).ToList(); var changedBlobs = history.Blobs().Distinct(); - Assert.Equal(1, history.Count()); - Assert.Equal(1, changedBlobs.Count()); + Assert.Single(history); + Assert.Single(changedBlobs); Assert.Equal(path, history.First().Path); Assert.Equal(commit, history.First().Commit); @@ -239,8 +239,8 @@ public void EmptyRepositoryHasNoHistory() using (var repo = new Repository(repoPath)) { IEnumerable history = repo.Commits.QueryBy("Test.txt").ToList(); - Assert.Equal(0, history.Count()); - Assert.Equal(0, history.Blobs().Count()); + Assert.Empty(history); + Assert.Empty(history.Blobs()); } } diff --git a/LibGit2Sharp.Tests/FilterBranchFixture.cs b/LibGit2Sharp.Tests/FilterBranchFixture.cs index d71cb22d8..60aee38f3 100644 --- a/LibGit2Sharp.Tests/FilterBranchFixture.cs +++ b/LibGit2Sharp.Tests/FilterBranchFixture.cs @@ -366,7 +366,7 @@ public void OnlyRewriteSelectedCommits() var commit = repo.Branches["packed"].Tip; var parent = commit.Parents.Single(); - Assert.True(parent.Sha.StartsWith("5001298")); + Assert.StartsWith("5001298", parent.Sha); Assert.NotEqual(Constants.Signature, commit.Author); Assert.NotEqual(Constants.Signature, parent.Author); @@ -557,7 +557,7 @@ public void CanNotOverWriteAnExistingReference() AssertErrorFired(ex); AssertSucceedingNotFired(); - Assert.Equal(0, repo.Refs.FromGlob("refs/original/*").Count()); + Assert.Empty(repo.Refs.FromGlob("refs/original/*")); } // Graft the orphan "test" branch to the tip of "packed" @@ -633,7 +633,7 @@ public void CanRewriteParentWithRewrittenCommit() var commitToRewrite = repo.Lookup("6dcf9bf"); var newParent = repo.Branches["packed"].Tip; - Assert.True(newParent.Sha.StartsWith("41bc8c6")); + Assert.StartsWith("41bc8c6", newParent.Sha); repo.Refs.RewriteHistory(new RewriteHistoryOptions { @@ -649,22 +649,22 @@ public void CanRewriteParentWithRewrittenCommit() AssertSucceedingButNotError(); // Assert "packed" hasn't been rewritten - Assert.True(repo.Branches["packed"].Tip.Sha.StartsWith("41bc8c6")); + Assert.StartsWith("41bc8c6", repo.Branches["packed"].Tip.Sha); // Assert (test, tag: lw, tag: e90810b, tag: test) have been rewritten var rewrittenTestCommit = repo.Branches["test"].Tip; - Assert.True(rewrittenTestCommit.Sha.StartsWith("f558880")); + Assert.StartsWith("f558880", rewrittenTestCommit.Sha); Assert.Equal(rewrittenTestCommit, repo.Lookup("refs/tags/lw^{commit}")); Assert.Equal(rewrittenTestCommit, repo.Lookup("refs/tags/e90810b^{commit}")); Assert.Equal(rewrittenTestCommit, repo.Lookup("refs/tags/test^{commit}")); // Assert parent of rewritten commit var rewrittenTestCommitParent = rewrittenTestCommit.Parents.Single(); - Assert.True(rewrittenTestCommitParent.Sha.StartsWith("0c25efa")); + Assert.StartsWith("0c25efa", rewrittenTestCommitParent.Sha); // Assert grand parent of rewritten commit var rewrittenTestCommitGrandParent = rewrittenTestCommitParent.Parents.Single(); - Assert.True(rewrittenTestCommitGrandParent.Sha.StartsWith("41bc8c6")); + Assert.StartsWith("41bc8c6", rewrittenTestCommitGrandParent.Sha); } [Fact] diff --git a/LibGit2Sharp.Tests/FilterFixture.cs b/LibGit2Sharp.Tests/FilterFixture.cs index 0e2a32428..4de354003 100644 --- a/LibGit2Sharp.Tests/FilterFixture.cs +++ b/LibGit2Sharp.Tests/FilterFixture.cs @@ -314,23 +314,23 @@ public void CanFilterLargeFiles() [Fact] public void DoubleRegistrationFailsButDoubleDeregistrationDoesNot() { - Assert.Equal(0, GlobalSettings.GetRegisteredFilters().Count()); + Assert.Empty(GlobalSettings.GetRegisteredFilters()); var filter = new EmptyFilter(FilterName, attributes); var registration = GlobalSettings.RegisterFilter(filter); Assert.Throws(() => { GlobalSettings.RegisterFilter(filter); }); - Assert.Equal(1, GlobalSettings.GetRegisteredFilters().Count()); + Assert.Single(GlobalSettings.GetRegisteredFilters()); Assert.True(registration.IsValid, "FilterRegistration.IsValid should be true."); GlobalSettings.DeregisterFilter(registration); - Assert.Equal(0, GlobalSettings.GetRegisteredFilters().Count()); + Assert.Empty(GlobalSettings.GetRegisteredFilters()); Assert.False(registration.IsValid, "FilterRegistration.IsValid should be false."); GlobalSettings.DeregisterFilter(registration); - Assert.Equal(0, GlobalSettings.GetRegisteredFilters().Count()); + Assert.Empty(GlobalSettings.GetRegisteredFilters()); Assert.False(registration.IsValid, "FilterRegistration.IsValid should be false."); } diff --git a/LibGit2Sharp.Tests/FilterSubstitutionCipherFixture.cs b/LibGit2Sharp.Tests/FilterSubstitutionCipherFixture.cs index a8705fe81..89b61c546 100644 --- a/LibGit2Sharp.Tests/FilterSubstitutionCipherFixture.cs +++ b/LibGit2Sharp.Tests/FilterSubstitutionCipherFixture.cs @@ -122,8 +122,8 @@ public void WhenStagedFileDoesNotMatchPathSpecFileIsNotFiltered(string pathSpec, [InlineData("rot13", "*.txt filter=rot13", 1)] [InlineData("rot13", "*.txt filter=fake", 0)] [InlineData("rot13", "*.bat filter=rot13", 0)] - [InlineData("rot13", "*.txt filter=fake", 0)] [InlineData("fake", "*.txt filter=fake", 1)] + [InlineData("fake", "*.txt filter=rot13", 0)] [InlineData("fake", "*.bat filter=fake", 0)] [InlineData("rot13", "*.txt filter=rot13 -crlf", 1)] public void CleanIsCalledIfAttributeEntryMatches(string filterAttribute, string attributeEntry, int cleanCount) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index d5dee6992..76b2c2ad3 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -45,7 +45,7 @@ public void CanRetrieveValidVersionString() public void TryingToResetNativeLibraryPathAfterLoadedThrows() { // Do something that loads the native library - Assert.NotNull(GlobalSettings.Version.Features); + var features = GlobalSettings.Version.Features; Assert.Throws(() => { GlobalSettings.NativeLibraryPath = "C:/Foo"; }); } diff --git a/LibGit2Sharp.Tests/IgnoreFixture.cs b/LibGit2Sharp.Tests/IgnoreFixture.cs index f085d35a2..fc9d65bc2 100644 --- a/LibGit2Sharp.Tests/IgnoreFixture.cs +++ b/LibGit2Sharp.Tests/IgnoreFixture.cs @@ -16,15 +16,15 @@ public void TemporaryRulesShouldApplyUntilCleared() { Touch(repo.Info.WorkingDirectory, "Foo.cs", "Bar"); - Assert.True(repo.RetrieveStatus().Untracked.Select(s => s.FilePath).Contains("Foo.cs")); + Assert.Contains("Foo.cs", repo.RetrieveStatus().Untracked.Select(s => s.FilePath)); repo.Ignore.AddTemporaryRules(new[] { "*.cs" }); - Assert.False(repo.RetrieveStatus().Untracked.Select(s => s.FilePath).Contains("Foo.cs")); + Assert.DoesNotContain("Foo.cs", repo.RetrieveStatus().Untracked.Select(s => s.FilePath)); repo.Ignore.ResetAllTemporaryRules(); - Assert.True(repo.RetrieveStatus().Untracked.Select(s => s.FilePath).Contains("Foo.cs")); + Assert.Contains("Foo.cs", repo.RetrieveStatus().Untracked.Select(s => s.FilePath)); } } diff --git a/LibGit2Sharp.Tests/IndexFixture.cs b/LibGit2Sharp.Tests/IndexFixture.cs index 0aea8cd99..4c0d150f0 100644 --- a/LibGit2Sharp.Tests/IndexFixture.cs +++ b/LibGit2Sharp.Tests/IndexFixture.cs @@ -462,18 +462,18 @@ public void CanMimicGitAddAll() using (var repo = new Repository(path)) { var before = repo.RetrieveStatus(); - Assert.True(before.Any(se => se.State == FileStatus.NewInWorkdir)); - Assert.True(before.Any(se => se.State == FileStatus.ModifiedInWorkdir)); - Assert.True(before.Any(se => se.State == FileStatus.DeletedFromWorkdir)); + Assert.Contains(before, se => se.State == FileStatus.NewInWorkdir); + Assert.Contains(before, se => se.State == FileStatus.ModifiedInWorkdir); + Assert.Contains(before, se => se.State == FileStatus.DeletedFromWorkdir); AddSomeCornerCases(repo); Commands.Stage(repo, "*"); var after = repo.RetrieveStatus(); - Assert.False(after.Any(se => se.State == FileStatus.NewInWorkdir)); - Assert.False(after.Any(se => se.State == FileStatus.ModifiedInWorkdir)); - Assert.False(after.Any(se => se.State == FileStatus.DeletedFromWorkdir)); + Assert.DoesNotContain(after, se => se.State == FileStatus.NewInWorkdir); + Assert.DoesNotContain(after, se => se.State == FileStatus.ModifiedInWorkdir); + Assert.DoesNotContain(after, se => se.State == FileStatus.DeletedFromWorkdir); } } diff --git a/LibGit2Sharp.Tests/LogFixture.cs b/LibGit2Sharp.Tests/LogFixture.cs index b74fe97b0..b8d43fe36 100644 --- a/LibGit2Sharp.Tests/LogFixture.cs +++ b/LibGit2Sharp.Tests/LogFixture.cs @@ -25,13 +25,13 @@ public void CanEnableAndDisableLogging() GlobalSettings.LogConfiguration = new LogConfiguration(LogLevel.Warning, (l, m) => { level = l; message = m; }); Assert.Equal(LogLevel.None, level); - Assert.Equal(null, message); + Assert.Null(message); // Similarly, turning logging off should produce no messages. GlobalSettings.LogConfiguration = LogConfiguration.None; Assert.Equal(LogLevel.None, level); - Assert.Equal(null, message); + Assert.Null(message); } } } diff --git a/LibGit2Sharp.Tests/MergeFixture.cs b/LibGit2Sharp.Tests/MergeFixture.cs index 9feff9c79..8b236aa82 100644 --- a/LibGit2Sharp.Tests/MergeFixture.cs +++ b/LibGit2Sharp.Tests/MergeFixture.cs @@ -16,7 +16,7 @@ public void ANewRepoIsFullyMerged() using (var repo = new Repository(repoPath)) { - Assert.Equal(true, repo.Index.IsFullyMerged); + Assert.True(repo.Index.IsFullyMerged); } } @@ -26,7 +26,7 @@ public void AFullyMergedRepoOnlyContainsStagedIndexEntries() string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { - Assert.Equal(true, repo.Index.IsFullyMerged); + Assert.True(repo.Index.IsFullyMerged); foreach (var entry in repo.Index) { @@ -41,7 +41,7 @@ public void SoftResetARepoWithUnmergedEntriesThrows() var path = SandboxMergedTestRepo(); using (var repo = new Repository(path)) { - Assert.Equal(false, repo.Index.IsFullyMerged); + Assert.False(repo.Index.IsFullyMerged); var headCommit = repo.Head.Tip; var firstCommitParent = headCommit.Parents.First(); @@ -56,7 +56,7 @@ public void CommitAgainARepoWithUnmergedEntriesThrows() var path = SandboxMergedTestRepo(); using (var repo = new Repository(path)) { - Assert.Equal(false, repo.Index.IsFullyMerged); + Assert.False(repo.Index.IsFullyMerged); var author = Constants.Signature; Assert.Throws( @@ -204,7 +204,7 @@ public void CanFastForwardRepos(bool shouldMergeOccurInDetachedHeadState) Assert.Equal(repo.Branches["FirstBranch"].Tip, repo.Head.Tip); Assert.Equal(repo.Head.Tip, mergeResult.Commit); - Assert.Equal(0, repo.RetrieveStatus().Count()); + Assert.Empty(repo.RetrieveStatus()); Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached); if (!shouldMergeOccurInDetachedHeadState) @@ -246,7 +246,7 @@ public void ConflictingMergeRepos() Assert.Equal(MergeStatus.Conflicts, mergeResult.Status); Assert.Null(mergeResult.Commit); - Assert.Equal(1, repo.Index.Conflicts.Count()); + Assert.Single(repo.Index.Conflicts); var conflict = repo.Index.Conflicts.First(); var changes = repo.Diff.Compare(repo.Lookup(conflict.Theirs.Id), repo.Lookup(conflict.Ours.Id)); @@ -285,7 +285,7 @@ public void ConflictingMergeReposBinary() Assert.Equal(MergeStatus.Conflicts, mergeResult.Status); - Assert.Equal(1, repo.Index.Conflicts.Count()); + Assert.Single(repo.Index.Conflicts); Conflict conflict = repo.Index.Conflicts.First(); @@ -515,12 +515,12 @@ public void CanMergeAndNotCommit() MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { CommitOnSuccess = false}); Assert.Equal(MergeStatus.NonFastForward, result.Status); - Assert.Equal(null, result.Commit); + Assert.Null(result.Commit); RepositoryStatus repoStatus = repo.RetrieveStatus(); // Verify that there is a staged entry. - Assert.Equal(1, repoStatus.Count()); + Assert.Single(repoStatus); Assert.Equal(FileStatus.ModifiedInIndex, repo.RetrieveStatus("b.txt")); } } @@ -570,7 +570,7 @@ public void VerifyUpToDateMerge() MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = FastForwardStrategy.NoFastForward }); Assert.Equal(MergeStatus.UpToDate, result.Status); - Assert.Equal(null, result.Commit); + Assert.Null(result.Commit); Assert.False(repo.RetrieveStatus().Any()); } } @@ -776,7 +776,7 @@ public void CanMergeTreeIntoSameTree() var result = repo.ObjectDatabase.MergeCommits(master, master, null); Assert.Equal(MergeTreeStatus.Succeeded, result.Status); - Assert.Equal(0, result.Conflicts.Count()); + Assert.Empty(result.Conflicts); } } @@ -800,7 +800,7 @@ public void CanMergeTreeIntoTreeFromUnbornBranch() var result = repo.ObjectDatabase.MergeCommits(master, branch, null); Assert.Equal(MergeTreeStatus.Succeeded, result.Status); Assert.NotNull(result.Tree); - Assert.Equal(0, result.Conflicts.Count()); + Assert.Empty(result.Conflicts); } } @@ -822,7 +822,7 @@ public void CanMergeCommitsAndDetectConflicts() var result = repo.ObjectDatabase.MergeCommits(master, branch, null); Assert.Equal(MergeTreeStatus.Conflicts, result.Status); Assert.Null(result.Tree); - Assert.NotEqual(0, result.Conflicts.Count()); + Assert.NotEmpty(result.Conflicts); } } @@ -838,7 +838,7 @@ public void CanMergeFastForwardTreeWithoutConflicts() var result = repo.ObjectDatabase.MergeCommits(master, branch, null); Assert.Equal(MergeTreeStatus.Succeeded, result.Status); Assert.NotNull(result.Tree); - Assert.Equal(0, result.Conflicts.Count()); + Assert.Empty(result.Conflicts); } } @@ -856,7 +856,7 @@ public void CanIdentifyConflictsInMergeCommits() Assert.Equal(MergeTreeStatus.Conflicts, result.Status); Assert.Null(result.Tree); - Assert.Equal(1, result.Conflicts.Count()); + Assert.Single(result.Conflicts); var conflict = result.Conflicts.First(); Assert.Equal(new ObjectId("8e9daea300fbfef6c0da9744c6214f546d55b279"), conflict.Ancestor.Id); diff --git a/LibGit2Sharp.Tests/NetworkFixture.cs b/LibGit2Sharp.Tests/NetworkFixture.cs index 9153ffeb0..3ac73a2e8 100644 --- a/LibGit2Sharp.Tests/NetworkFixture.cs +++ b/LibGit2Sharp.Tests/NetworkFixture.cs @@ -168,13 +168,13 @@ public void CanPull(FastForwardStrategy fastForwardStrategy) if(fastForwardStrategy == FastForwardStrategy.Default || fastForwardStrategy == FastForwardStrategy.FastForwardOnly) { - Assert.Equal(mergeResult.Status, MergeStatus.FastForward); + Assert.Equal(MergeStatus.FastForward, mergeResult.Status); Assert.Equal(mergeResult.Commit, repo.Branches["refs/remotes/origin/master"].Tip); Assert.Equal(repo.Head.Tip, repo.Branches["refs/remotes/origin/master"].Tip); } else { - Assert.Equal(mergeResult.Status, MergeStatus.NonFastForward); + Assert.Equal(MergeStatus.NonFastForward, mergeResult.Status); } } } @@ -199,7 +199,7 @@ public void CanPullIntoEmptyRepo() // Pull! MergeResult mergeResult = Commands.Pull(repo, Constants.Signature, new PullOptions()); - Assert.Equal(mergeResult.Status, MergeStatus.FastForward); + Assert.Equal(MergeStatus.FastForward, mergeResult.Status); Assert.Equal(mergeResult.Commit, repo.Branches["refs/remotes/origin/master"].Tip); Assert.Equal(repo.Head.Tip, repo.Branches["refs/remotes/origin/master"].Tip); } @@ -260,7 +260,7 @@ public void CanMergeFetchedRefs() }; MergeResult mergeResult = repo.MergeFetchedRefs(Constants.Signature, mergeOptions); - Assert.Equal(mergeResult.Status, MergeStatus.NonFastForward); + Assert.Equal(MergeStatus.NonFastForward, mergeResult.Status); } } diff --git a/LibGit2Sharp.Tests/NoteFixture.cs b/LibGit2Sharp.Tests/NoteFixture.cs index 48ad98eee..e3cb9d7a0 100644 --- a/LibGit2Sharp.Tests/NoteFixture.cs +++ b/LibGit2Sharp.Tests/NoteFixture.cs @@ -20,7 +20,7 @@ public void RetrievingNotesFromANonExistingGitObjectYieldsNoResult() { var notes = repo.Notes[ObjectId.Zero]; - Assert.Equal(0, notes.Count()); + Assert.Empty(notes); } } @@ -32,7 +32,7 @@ public void RetrievingNotesFromAGitObjectWhichHasNoNoteYieldsNoResult() { var notes = repo.Notes[new ObjectId("4c062a6361ae6959e06292c1fa5e2822d9c96345")]; - Assert.Equal(0, notes.Count()); + Assert.Empty(notes); } } @@ -308,19 +308,19 @@ public void CanRetrieveTheListOfNotesForAGivenNamespace() } } - [Fact] - public void CanRetrieveNotesWhenThereAreNotAny() - { - string path = InitNewRepository(); // doesn't reproduce an error when using a sandbox repository so we have to create an actual repo. - using (var repo = new Repository(path)) - { - foreach (var note in repo.Notes) - { - Assert.NotNull(note); - } - Assert.Equal(0, repo.Notes.Count()); - } - } + [Fact] + public void CanRetrieveNotesWhenThereAreNotAny() + { + string path = InitNewRepository(); // doesn't reproduce an error when using a sandbox repository so we have to create an actual repo. + using (var repo = new Repository(path)) + { + foreach (var note in repo.Notes) + { + Assert.NotNull(note); + } + Assert.Empty(repo.Notes); + } + } private static T[] SortedNotes(IEnumerable notes, Func selector) diff --git a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs index fc06ef713..767732487 100644 --- a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs +++ b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs @@ -61,7 +61,7 @@ public void RetrieveObjectMetadataReturnsCorrectSizeAndTypeForBlob() GitObjectMetadata blobMetadata = repo.ObjectDatabase.RetrieveObjectMetadata(blob.Id); Assert.Equal(blobMetadata.Size, blob.Size); - Assert.Equal(blobMetadata.Type, ObjectType.Blob); + Assert.Equal(ObjectType.Blob, blobMetadata.Type); Blob fetchedBlob = repo.Lookup(blob.Id); Assert.Equal(blobMetadata.Size, fetchedBlob.Size); @@ -449,7 +449,7 @@ public void CanCreateABinaryBlobFromAStream() { Blob blob = repo.ObjectDatabase.CreateBlob(stream); Assert.Equal(6, blob.Size); - Assert.Equal(true, blob.IsBinary); + Assert.True(blob.IsBinary); } } } diff --git a/LibGit2Sharp.Tests/ObjectIdFixture.cs b/LibGit2Sharp.Tests/ObjectIdFixture.cs index e118cfdb8..8d3468bdd 100644 --- a/LibGit2Sharp.Tests/ObjectIdFixture.cs +++ b/LibGit2Sharp.Tests/ObjectIdFixture.cs @@ -133,7 +133,7 @@ public void TryParse(string maybeSha, bool isValidSha) Assert.NotNull(parsedObjectId); Assert.Equal(maybeSha, parsedObjectId.Sha); - Assert.True(maybeSha.StartsWith(parsedObjectId.ToString(3))); + Assert.StartsWith(parsedObjectId.ToString(3), maybeSha); Assert.Equal(maybeSha, parsedObjectId.ToString(42)); } diff --git a/LibGit2Sharp.Tests/RebaseFixture.cs b/LibGit2Sharp.Tests/RebaseFixture.cs index 28c49738e..240ca8985 100644 --- a/LibGit2Sharp.Tests/RebaseFixture.cs +++ b/LibGit2Sharp.Tests/RebaseFixture.cs @@ -253,10 +253,10 @@ public void VerifyRebaseDetailed(string attributes, string lineEnding, string[] repo.Rebase.Start(null, upstreamBranch, null, Constants.Identity2, options); - Assert.Equal(true, wasCheckoutNotifyCalledForResetingHead); - Assert.Equal(true, wasCheckoutProgressCalledForResetingHead); - Assert.Equal(true, wasCheckoutNotifyCalled); - Assert.Equal(true, wasCheckoutProgressCalled); + Assert.True(wasCheckoutNotifyCalledForResetingHead); + Assert.True(wasCheckoutProgressCalledForResetingHead); + Assert.True(wasCheckoutNotifyCalled); + Assert.True(wasCheckoutProgressCalled); // Verify the chain of resultant rebased commits. CommitFilter commitFilter = new CommitFilter() diff --git a/LibGit2Sharp.Tests/RefSpecFixture.cs b/LibGit2Sharp.Tests/RefSpecFixture.cs index b8f2b6a09..50bf3343b 100644 --- a/LibGit2Sharp.Tests/RefSpecFixture.cs +++ b/LibGit2Sharp.Tests/RefSpecFixture.cs @@ -15,7 +15,7 @@ public void CanCountRefSpecs() using (var repo = new Repository(path)) { var remote = repo.Network.Remotes["origin"]; - Assert.Equal(1, remote.RefSpecs.Count()); + Assert.Single(remote.RefSpecs); } } @@ -63,7 +63,7 @@ public void CanReadRefSpecDetails() Assert.Equal("refs/heads/*", refSpec.Source); Assert.Equal("refs/remotes/origin/*", refSpec.Destination); - Assert.Equal(true, refSpec.ForceUpdate); + Assert.True(refSpec.ForceUpdate); } } @@ -225,7 +225,6 @@ public void CanCheckForMatches(string reference, bool shouldMatchSource, bool sh [Theory] [InlineData("refs/heads/master", "refs/remotes/foo/master")] [InlineData("refs/heads/bar/master", "refs/remotes/foo/bar/master")] - [InlineData("refs/heads/master", "refs/remotes/foo/master")] public void CanTransformRefspecs(string lhs, string rhs) { using (var repo = new Repository(InitNewRepository())) diff --git a/LibGit2Sharp.Tests/ReferenceFixture.cs b/LibGit2Sharp.Tests/ReferenceFixture.cs index ac2af3c24..186d2e869 100644 --- a/LibGit2Sharp.Tests/ReferenceFixture.cs +++ b/LibGit2Sharp.Tests/ReferenceFixture.cs @@ -295,12 +295,12 @@ public void RemovingAReferenceDecreasesTheRefsCount() const string refName = "refs/heads/test"; List refs = repo.Refs.Select(r => r.CanonicalName).ToList(); - Assert.True(refs.Contains(refName)); + Assert.Contains(refName, refs); repo.Refs.Remove(refName); List refs2 = repo.Refs.Select(r => r.CanonicalName).ToList(); - Assert.False(refs2.Contains(refName)); + Assert.DoesNotContain(refName, refs2); Assert.Equal(refs.Count - 1, refs2.Count); } @@ -736,13 +736,13 @@ public void RenamingAReferenceDoesNotDecreaseTheRefsCount() const string newName = "refs/atic/tagtest"; List refs = repo.Refs.Select(r => r.CanonicalName).ToList(); - Assert.True(refs.Contains(oldName)); + Assert.Contains(oldName, refs); repo.Refs.Rename(oldName, newName); List refs2 = repo.Refs.Select(r => r.CanonicalName).ToList(); - Assert.False(refs2.Contains(oldName)); - Assert.True(refs2.Contains(newName)); + Assert.DoesNotContain(oldName, refs2); + Assert.Contains(newName, refs2); Assert.Equal(refs2.Count, refs.Count); } @@ -774,7 +774,7 @@ public void CanFilterReferencesWithAGlob() Assert.Equal(5, repo.Refs.FromGlob("refs/heads/*").Count()); Assert.Equal(5, repo.Refs.FromGlob("refs/tags/*").Count()); Assert.Equal(3, repo.Refs.FromGlob("*t?[pqrs]t*").Count()); - Assert.Equal(0, repo.Refs.FromGlob("test").Count()); + Assert.Empty(repo.Refs.FromGlob("test")); } } diff --git a/LibGit2Sharp.Tests/ReflogFixture.cs b/LibGit2Sharp.Tests/ReflogFixture.cs index fa5a0d842..f93952e6e 100644 --- a/LibGit2Sharp.Tests/ReflogFixture.cs +++ b/LibGit2Sharp.Tests/ReflogFixture.cs @@ -23,7 +23,7 @@ public void CanReadReflog() // Initial commit assertions Assert.Equal("timothy.clem@gmail.com", reflog.Last().Committer.Email); - Assert.True(reflog.Last().Message.StartsWith("clone: from")); + Assert.StartsWith("clone: from", reflog.Last().Message); Assert.Equal(ObjectId.Zero, reflog.Last().From); // second commit assertions @@ -78,7 +78,7 @@ public void CommitShouldCreateReflogEntryOnHeadAndOnTargetedDirectReference() Commit commit = repo.Commit(commitMessage, author, author); // Assert a reflog entry is created on HEAD - Assert.Equal(1, repo.Refs.Log("HEAD").Count()); + Assert.Single(repo.Refs.Log("HEAD")); var reflogEntry = repo.Refs.Log("HEAD").First(); Assert.Equal(identity.Name, reflogEntry.Committer.Name); @@ -91,7 +91,7 @@ public void CommitShouldCreateReflogEntryOnHeadAndOnTargetedDirectReference() Assert.Equal(ObjectId.Zero, reflogEntry.From); // Assert the same reflog entry is created on refs/heads/master - Assert.Equal(1, repo.Refs.Log("refs/heads/master").Count()); + Assert.Single(repo.Refs.Log("refs/heads/master")); reflogEntry = repo.Refs.Log("HEAD").First(); Assert.Equal(identity.Name, reflogEntry.Committer.Name); @@ -103,7 +103,7 @@ public void CommitShouldCreateReflogEntryOnHeadAndOnTargetedDirectReference() Assert.Equal(ObjectId.Zero, reflogEntry.From); // Assert no reflog entry is created on refs/heads/unit_test - Assert.Equal(0, repo.Refs.Log("refs/heads/unit_test").Count()); + Assert.Empty(repo.Refs.Log("refs/heads/unit_test")); } } @@ -123,7 +123,7 @@ public void CommitOnUnbornReferenceShouldCreateReflogEntryWithInitialTag() repo.Commit(commitMessage, author, author); // Assert the reflog entry message is correct - Assert.Equal(1, repo.Refs.Log("HEAD").Count()); + Assert.Single(repo.Refs.Log("HEAD")); Assert.Equal(string.Format("commit (initial): {0}", commitMessage), repo.Refs.Log("HEAD").First().Message); } } diff --git a/LibGit2Sharp.Tests/RemoteFixture.cs b/LibGit2Sharp.Tests/RemoteFixture.cs index 28049f0e0..36990bb6e 100644 --- a/LibGit2Sharp.Tests/RemoteFixture.cs +++ b/LibGit2Sharp.Tests/RemoteFixture.cs @@ -203,7 +203,7 @@ public void DoesNotThrowWhenARemoteHasNoUrlSet() { var noUrlRemote = repo.Network.Remotes["no_url"]; Assert.NotNull(noUrlRemote); - Assert.Equal(null, noUrlRemote.Url); + Assert.Null(noUrlRemote.Url); var remotes = repo.Network.Remotes.ToList(); Assert.Equal(1, remotes.Count(r => r.Name == "no_url")); diff --git a/LibGit2Sharp.Tests/RemoveFixture.cs b/LibGit2Sharp.Tests/RemoveFixture.cs index 6ceef6045..e97636d9c 100644 --- a/LibGit2Sharp.Tests/RemoveFixture.cs +++ b/LibGit2Sharp.Tests/RemoveFixture.cs @@ -88,7 +88,7 @@ public void RemovingAModifiedFileWhoseChangesHaveBeenPromotedToTheIndexAndWithAd { string fullpath = Path.Combine(repo.Info.WorkingDirectory, filename); - Assert.Equal(true, File.Exists(fullpath)); + Assert.True(File.Exists(fullpath)); File.AppendAllText(fullpath, "additional content"); Assert.Equal(FileStatus.ModifiedInIndex | FileStatus.ModifiedInWorkdir, repo.RetrieveStatus(filename)); diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs index 4934629b9..b8a84a4e9 100644 --- a/LibGit2Sharp.Tests/RepositoryFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryFixture.cs @@ -123,7 +123,7 @@ public void CanCreateStandardRepoAndSpecifyAFolderWhichWillContainTheNewlyCreate Assert.True(Repository.IsValid(repo.Info.WorkingDirectory)); Assert.True(Repository.IsValid(repo.Info.Path)); - Assert.Equal(false, repo.Info.IsBare); + Assert.False(repo.Info.IsBare); char sep = Path.DirectorySeparatorChar; Assert.Equal(scd1.RootedDirectoryPath + sep, repo.Info.WorkingDirectory); @@ -148,7 +148,7 @@ public void CanCreateStandardRepoAndDirectlySpecifyAGitDirectory() Assert.True(Repository.IsValid(repo.Info.WorkingDirectory)); Assert.True(Repository.IsValid(repo.Info.Path)); - Assert.Equal(false, repo.Info.IsBare); + Assert.False(repo.Info.IsBare); char sep = Path.DirectorySeparatorChar; Assert.Equal(scd1.RootedDirectoryPath + sep, repo.Info.WorkingDirectory); @@ -267,18 +267,18 @@ private static void AssertInitializedRepository(IRepository repo, string expecte Assert.Equal(headRef.TargetIdentifier, repo.Head.CanonicalName); Assert.Null(repo.Head.Tip); - Assert.Equal(0, repo.Commits.Count()); - Assert.Equal(0, repo.Commits.QueryBy(new CommitFilter()).Count()); - Assert.Equal(0, repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = repo.Refs.Head }).Count()); - Assert.Equal(0, repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = repo.Head }).Count()); - Assert.Equal(0, repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = "HEAD" }).Count()); - Assert.Equal(0, repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = expectedHeadTargetIdentifier }).Count()); + Assert.Empty(repo.Commits); + Assert.Empty(repo.Commits.QueryBy(new CommitFilter())); + Assert.Empty(repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = repo.Refs.Head })); + Assert.Empty(repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = repo.Head })); + Assert.Empty(repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = "HEAD" })); + Assert.Empty(repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = expectedHeadTargetIdentifier })); Assert.Null(repo.Head["subdir/I-do-not-exist"]); - Assert.Equal(0, repo.Branches.Count()); - Assert.Equal(0, repo.Refs.Count()); - Assert.Equal(0, repo.Tags.Count()); + Assert.Empty(repo.Branches); + Assert.Empty(repo.Refs); + Assert.Empty(repo.Tags); } [Fact] diff --git a/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs b/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs index b7c56ff4f..707e0ecae 100644 --- a/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs @@ -174,8 +174,8 @@ public void CanCommitOnBareRepository() Commands.Stage(repo, relativeFilepath); Assert.NotNull(repo.Commit("Initial commit", Constants.Signature, Constants.Signature)); - Assert.Equal(1, repo.Head.Commits.Count()); - Assert.Equal(1, repo.Commits.Count()); + Assert.Single(repo.Head.Commits); + Assert.Single(repo.Commits); } } } diff --git a/LibGit2Sharp.Tests/ResetHeadFixture.cs b/LibGit2Sharp.Tests/ResetHeadFixture.cs index 0379c855a..83a7efcb9 100644 --- a/LibGit2Sharp.Tests/ResetHeadFixture.cs +++ b/LibGit2Sharp.Tests/ResetHeadFixture.cs @@ -256,7 +256,7 @@ public void HardResetUpdatesTheContentOfTheWorkingDirectory() names = new DirectoryInfo(repo.Info.WorkingDirectory).GetFileSystemInfos().Select(fsi => fsi.Name).ToList(); names.Sort(StringComparer.Ordinal); - Assert.Equal(true, progressCalled); + Assert.True(progressCalled); Assert.Equal(new[] { ".git", "README", "WillNotBeRemoved.txt", "branch_file.txt", "new.txt", "new_untracked_file.txt" }, names); } } diff --git a/LibGit2Sharp.Tests/ResetIndexFixture.cs b/LibGit2Sharp.Tests/ResetIndexFixture.cs index 2e8257f22..97a1eef88 100644 --- a/LibGit2Sharp.Tests/ResetIndexFixture.cs +++ b/LibGit2Sharp.Tests/ResetIndexFixture.cs @@ -62,7 +62,7 @@ public void ResetTheIndexWithTheHeadUnstagesEverything() repo.Index.Replace(repo.Head.Tip); RepositoryStatus newStatus = repo.RetrieveStatus(); - Assert.Equal(0, newStatus.Where(IsStaged).Count()); + Assert.Empty(newStatus.Where(IsStaged)); // Assert that no reflog entry is created Assert.Equal(reflogEntriesCount, repo.Refs.Log(repo.Refs.Head).Count()); @@ -120,7 +120,7 @@ public void CanResetTheIndexWhenARenameExists() repo.Index.Replace(repo.Lookup("32eab9c")); RepositoryStatus status = repo.RetrieveStatus(); - Assert.Equal(0, status.Where(IsStaged).Count()); + Assert.Empty(status.Where(IsStaged)); } } @@ -132,14 +132,14 @@ public void CanResetSourceOfARenameInIndex() Commands.Move(repo, "branch_file.txt", "renamed_branch_file.txt"); RepositoryStatus oldStatus = repo.RetrieveStatus(); - Assert.Equal(1, oldStatus.RenamedInIndex.Count()); + Assert.Single(oldStatus.RenamedInIndex); Assert.Equal(FileStatus.Nonexistent, oldStatus["branch_file.txt"].State); Assert.Equal(FileStatus.RenamedInIndex, oldStatus["renamed_branch_file.txt"].State); repo.Index.Replace(repo.Lookup("32eab9c"), new string[] { "branch_file.txt" }); RepositoryStatus newStatus = repo.RetrieveStatus(); - Assert.Equal(0, newStatus.RenamedInIndex.Count()); + Assert.Empty(newStatus.RenamedInIndex); Assert.Equal(FileStatus.DeletedFromWorkdir, newStatus["branch_file.txt"].State); Assert.Equal(FileStatus.NewInIndex, newStatus["renamed_branch_file.txt"].State); } @@ -153,13 +153,13 @@ public void CanResetTargetOfARenameInIndex() Commands.Move(repo, "branch_file.txt", "renamed_branch_file.txt"); RepositoryStatus oldStatus = repo.RetrieveStatus(); - Assert.Equal(1, oldStatus.RenamedInIndex.Count()); + Assert.Single(oldStatus.RenamedInIndex); Assert.Equal(FileStatus.RenamedInIndex, oldStatus["renamed_branch_file.txt"].State); repo.Index.Replace(repo.Lookup("32eab9c"), new string[] { "renamed_branch_file.txt" }); RepositoryStatus newStatus = repo.RetrieveStatus(); - Assert.Equal(0, newStatus.RenamedInIndex.Count()); + Assert.Empty(newStatus.RenamedInIndex); Assert.Equal(FileStatus.NewInWorkdir, newStatus["renamed_branch_file.txt"].State); Assert.Equal(FileStatus.DeletedFromIndex, newStatus["branch_file.txt"].State); } diff --git a/LibGit2Sharp.Tests/RevertFixture.cs b/LibGit2Sharp.Tests/RevertFixture.cs index cf17dcfe1..b0f12b9dc 100644 --- a/LibGit2Sharp.Tests/RevertFixture.cs +++ b/LibGit2Sharp.Tests/RevertFixture.cs @@ -421,7 +421,7 @@ public void RevertWithNothingToRevert(bool commitOnSuccess) new RevertOptions() { CommitOnSuccess = commitOnSuccess }); Assert.NotNull(result); - Assert.Equal(null, result.Commit); + Assert.Null(result.Commit); Assert.Equal(RevertStatus.NothingToRevert, result.Status); if (commitOnSuccess) diff --git a/LibGit2Sharp.Tests/StashFixture.cs b/LibGit2Sharp.Tests/StashFixture.cs index 6d6d5565d..7ba379621 100644 --- a/LibGit2Sharp.Tests/StashFixture.cs +++ b/LibGit2Sharp.Tests/StashFixture.cs @@ -69,7 +69,7 @@ public void CanAddAndRemoveStash() //Remove one stash repo.Stashes.Remove(0); - Assert.Equal(1, repo.Stashes.Count()); + Assert.Single(repo.Stashes); Stash newTopStash = repo.Stashes.First(); Assert.Equal("stash@{0}", newTopStash.CanonicalName); Assert.Equal(stash.WorkTree.Sha, newTopStash.WorkTree.Sha); @@ -220,7 +220,7 @@ public void CanStashAndApplyWithOptions() Assert.Equal(StashApplyStatus.Applied, repo.Stashes.Apply(0)); Assert.Equal(FileStatus.NewInIndex, repo.RetrieveStatus(filename)); - Assert.Equal(1, repo.Stashes.Count()); + Assert.Single(repo.Stashes); Commands.Stage(repo, filename); @@ -245,7 +245,7 @@ public void CanStashAndPop() { var stasher = Constants.Signature; - Assert.Equal(0, repo.Stashes.Count()); + Assert.Empty(repo.Stashes); const string filename = "staged_file_path.txt"; const string contents = "I'm staged"; @@ -253,10 +253,10 @@ public void CanStashAndPop() Commands.Stage(repo, filename); repo.Stashes.Add(stasher, "This stash with default options"); - Assert.Equal(1, repo.Stashes.Count()); + Assert.Single(repo.Stashes); Assert.Equal(StashApplyStatus.Applied, repo.Stashes.Pop(0)); - Assert.Equal(0, repo.Stashes.Count()); + Assert.Empty(repo.Stashes); Assert.Equal(FileStatus.NewInIndex, repo.RetrieveStatus(filename)); Assert.Equal(contents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename))); @@ -290,7 +290,7 @@ public void StashFailsWithUncommittedChangesIntheIndex() { ApplyModifiers = StashApplyModifiers.ReinstateIndex, })); - Assert.Equal(1, repo.Stashes.Count()); + Assert.Single(repo.Stashes); Assert.Equal(newContents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename))); Assert.Equal(newContents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename2))); } @@ -321,7 +321,7 @@ public void StashCallsTheCallback() ProgressHandler = (progress) => { called = true; return true; } }); - Assert.Equal(true, called); + Assert.True(called); repo.Reset(ResetMode.Hard); @@ -331,7 +331,7 @@ public void StashCallsTheCallback() ProgressHandler = (progress) => { called = true; return true; } }); - Assert.Equal(true, called); + Assert.True(called); } } diff --git a/LibGit2Sharp.Tests/StatusFixture.cs b/LibGit2Sharp.Tests/StatusFixture.cs index 270ae276c..7ba561def 100644 --- a/LibGit2Sharp.Tests/StatusFixture.cs +++ b/LibGit2Sharp.Tests/StatusFixture.cs @@ -255,15 +255,15 @@ public void CanRetrieveTheStatusOfANewRepository(bool includeUnaltered) { RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = includeUnaltered }); Assert.NotNull(status); - Assert.Equal(0, status.Count()); + Assert.Empty(status); Assert.False(status.IsDirty); - Assert.Equal(0, status.Untracked.Count()); - Assert.Equal(0, status.Modified.Count()); - Assert.Equal(0, status.Missing.Count()); - Assert.Equal(0, status.Added.Count()); - Assert.Equal(0, status.Staged.Count()); - Assert.Equal(0, status.Removed.Count()); + Assert.Empty(status.Untracked); + Assert.Empty(status.Modified); + Assert.Empty(status.Missing); + Assert.Empty(status.Added); + Assert.Empty(status.Staged); + Assert.Empty(status.Removed); } } @@ -286,7 +286,7 @@ public void RetrievingTheStatusOfARepositoryReturnsGitPaths() // Get the repository status RepositoryStatus repoStatus = repo.RetrieveStatus(); - Assert.Equal(1, repoStatus.Count()); + Assert.Single(repoStatus); StatusEntry statusEntry = repoStatus.Single(); Assert.Equal(relFilePath.Replace('\\', '/'), statusEntry.FilePath); @@ -515,7 +515,7 @@ public void RetrievingTheStatusOfTheRepositoryHonorsTheGitIgnoreDirectivesThroug newStatus = repo.RetrieveStatus(new StatusOptions { IncludeIgnored = true }); Assert.Equal(new[] { "bin/look-ma.txt" }, newStatus.Ignored.Select(s => s.FilePath)); - Assert.True(newStatus.Untracked.Select(s => s.FilePath).Contains("bin/what-about-me.txt")); + Assert.Contains("bin/what-about-me.txt", newStatus.Untracked.Select(s => s.FilePath)); } } @@ -571,8 +571,8 @@ public void CanRetrieveTheStatusOfARelativeWorkingDirectory() Assert.Equal(2, status.Untracked.Count()); status = repo.RetrieveStatus(new StatusOptions() { PathSpec = new[] { "just_a_dir/another_dir" } }); - Assert.Equal(1, status.Count()); - Assert.Equal(1, status.Untracked.Count()); + Assert.Single(status); + Assert.Single(status.Untracked); } } @@ -656,7 +656,7 @@ public void UnalteredFilesDontMarkIndexAsDirty() RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = true }); - Assert.Equal(false, status.IsDirty); + Assert.False(status.IsDirty); Assert.Equal(9, status.Count()); } } diff --git a/LibGit2Sharp.Tests/TagFixture.cs b/LibGit2Sharp.Tests/TagFixture.cs index e6897935e..5c1628a7b 100644 --- a/LibGit2Sharp.Tests/TagFixture.cs +++ b/LibGit2Sharp.Tests/TagFixture.cs @@ -606,12 +606,12 @@ public void RemovingATagDecreasesTheTagsCount() const string tagName = "e90810b"; List tags = repo.Tags.Select(r => r.FriendlyName).ToList(); - Assert.True(tags.Contains(tagName)); + Assert.Contains(tagName, tags); repo.Tags.Remove(tagName); List tags2 = repo.Tags.Select(r => r.FriendlyName).ToList(); - Assert.False(tags2.Contains(tagName)); + Assert.DoesNotContain(tagName, tags2); Assert.Equal(tags.Count - 1, tags2.Count); } @@ -661,7 +661,7 @@ public void CanListAllTagsInAEmptyRepository() using (var repo = new Repository(repoPath)) { Assert.True(repo.Info.IsHeadUnborn); - Assert.Equal(0, repo.Tags.Count()); + Assert.Empty(repo.Tags); } } diff --git a/LibGit2Sharp.Tests/TreeFixture.cs b/LibGit2Sharp.Tests/TreeFixture.cs index 5187cd142..31ca85c2d 100644 --- a/LibGit2Sharp.Tests/TreeFixture.cs +++ b/LibGit2Sharp.Tests/TreeFixture.cs @@ -82,7 +82,7 @@ public void CanEnumerateSubTrees() .Select(e => e.Target) .Cast(); - Assert.Equal(1, subTrees.Count()); + Assert.Single(subTrees); } } diff --git a/LibGit2Sharp.Tests/UnstageFixture.cs b/LibGit2Sharp.Tests/UnstageFixture.cs index c4791d10d..a5dc143d3 100644 --- a/LibGit2Sharp.Tests/UnstageFixture.cs +++ b/LibGit2Sharp.Tests/UnstageFixture.cs @@ -167,8 +167,8 @@ public void CanUnstageUntrackedFileAgainstAnOrphanedHead() Commands.Unstage(repo, relativePath); RepositoryStatus status = repo.RetrieveStatus(); - Assert.Equal(0, status.Staged.Count()); - Assert.Equal(1, status.Untracked.Count()); + Assert.Empty(status.Staged); + Assert.Single(status.Untracked); Assert.Throws(() => Commands.Unstage(repo, "i-dont-exist", new ExplicitPathsOptions())); } @@ -264,14 +264,14 @@ public void CanUnstageSourceOfARename() Commands.Move(repo, "branch_file.txt", "renamed_branch_file.txt"); RepositoryStatus oldStatus = repo.RetrieveStatus(); - Assert.Equal(1, oldStatus.RenamedInIndex.Count()); + Assert.Single(oldStatus.RenamedInIndex); Assert.Equal(FileStatus.Nonexistent, oldStatus["branch_file.txt"].State); Assert.Equal(FileStatus.RenamedInIndex, oldStatus["renamed_branch_file.txt"].State); Commands.Unstage(repo, new string[] { "branch_file.txt" }); RepositoryStatus newStatus = repo.RetrieveStatus(); - Assert.Equal(0, newStatus.RenamedInIndex.Count()); + Assert.Empty(newStatus.RenamedInIndex); Assert.Equal(FileStatus.DeletedFromWorkdir, newStatus["branch_file.txt"].State); Assert.Equal(FileStatus.NewInIndex, newStatus["renamed_branch_file.txt"].State); } @@ -285,13 +285,13 @@ public void CanUnstageTargetOfARename() Commands.Move(repo, "branch_file.txt", "renamed_branch_file.txt"); RepositoryStatus oldStatus = repo.RetrieveStatus(); - Assert.Equal(1, oldStatus.RenamedInIndex.Count()); + Assert.Single(oldStatus.RenamedInIndex); Assert.Equal(FileStatus.RenamedInIndex, oldStatus["renamed_branch_file.txt"].State); Commands.Unstage(repo, new string[] { "renamed_branch_file.txt" }); RepositoryStatus newStatus = repo.RetrieveStatus(); - Assert.Equal(0, newStatus.RenamedInIndex.Count()); + Assert.Empty(newStatus.RenamedInIndex); Assert.Equal(FileStatus.NewInWorkdir, newStatus["renamed_branch_file.txt"].State); Assert.Equal(FileStatus.DeletedFromIndex, newStatus["branch_file.txt"].State); } diff --git a/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs b/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs index dd3fdbaab..34719635e 100644 --- a/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs +++ b/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs @@ -55,7 +55,7 @@ public void CanProbeForNativeBinariesFromAShadowCopiedAssembly() // ...that the assembly in the other domain is stored in the shadow copy cache... string cachedAssembliesPath = Path.Combine(setup.CachePath, setup.ApplicationName); - Assert.True(cachedAssemblyLocation.StartsWith(cachedAssembliesPath)); + Assert.StartsWith(cachedAssembliesPath, cachedAssemblyLocation); if (!Constants.IsRunningOnUnix) { diff --git a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs index d55785baa..950b6fc85 100644 --- a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs +++ b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs @@ -117,7 +117,7 @@ public void CanUseCredentials(string scheme, string url, string user, string pas // 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 = "libgit3", Password = "libgit3" }, + CredentialsProvider = (_user, _valid, _hostname) => new UsernamePasswordCredentials() { Username = user, Password = pass }, }, null); // Verify the expected From a267283de0633e0fc96fb69443b286e12507050d Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 21:11:22 -0500 Subject: [PATCH 040/384] Update NativeBinaries to 1.0.192 --- LibGit2Sharp/CodeGenerator.targets | 24 ++++++------------------ LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/LibGit2Sharp/CodeGenerator.targets b/LibGit2Sharp/CodeGenerator.targets index 845f3cf03..e30b9dc83 100644 --- a/LibGit2Sharp/CodeGenerator.targets +++ b/LibGit2Sharp/CodeGenerator.targets @@ -13,19 +13,14 @@ - - - - - - + namespace LibGit2Sharp.Core { internal static class NativeDllName { - public const string Name = "$(libgit2FileName)"%3b + public const string Name = "$(libgit2_filename)"%3b } } @@ -65,23 +60,16 @@ - - - - - + - + - - - - + @@ -89,7 +77,7 @@ { internal static class AssemblyCommitIds { - public const string LibGit2CommitSha = "$(libgit2hash)"%3b + public const string LibGit2CommitSha = "$(libgit2_hash)"%3b public const string LibGit2SharpCommitSha = "$(GitCommitId)"%3b } } diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 863c04d98..a9bbb7499 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,7 +32,7 @@ - + From f16b9c6b82db6ab9ea8e89844699adbaa2974af6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 18 Nov 2017 21:26:39 -0500 Subject: [PATCH 041/384] Update build scripts to point to new console runner --- appveyor.yml | 8 ++++---- buildandtest.cmd | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e8dbeaab5..8cb01abab 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -90,16 +90,16 @@ test_script: { .\packages\OpenCover\tools\OpenCover.Console.exe ` -register:user ` - "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.2.0\tools\$runner""" ` - "-targetargs:""$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net46\LibGit2Sharp.Tests.dll"" -noshadow" ` + "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.3.1\tools\net452\$runner""" ` + "-targetargs:""$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net461\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.2.0\tools\$runner" ` - "$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net46\LibGit2Sharp.Tests.dll" -noshadow + & "$Env:userprofile\.nuget\packages\xunit.runner.console\2.3.1\tools\net452\$runner" ` + "$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net461\LibGit2Sharp.Tests.dll" -noshadow } } diff --git a/buildandtest.cmd b/buildandtest.cmd index b99f4d08e..d1b114076 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.2.0\tools\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net46\LibGit2Sharp.Tests.dll" -noshadow +"%userprofile%\.nuget\packages\xunit.runner.console\2.3.1\tools\net452\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net461\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 d9dd593febf5a8fcedbb2f0ccd328abbfa8056ea Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 20 Nov 2017 21:22:34 -0500 Subject: [PATCH 042/384] Improve GenerateAssemblyCommitIdsCs Makes it handle being run when the project is not in a git repo. --- LibGit2Sharp/CodeGenerator.targets | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/CodeGenerator.targets b/LibGit2Sharp/CodeGenerator.targets index e30b9dc83..a317d9261 100644 --- a/LibGit2Sharp/CodeGenerator.targets +++ b/LibGit2Sharp/CodeGenerator.targets @@ -69,16 +69,18 @@ - + + unknown + $(GitCommitId) namespace LibGit2Sharp { internal static class AssemblyCommitIds { public const string LibGit2CommitSha = "$(libgit2_hash)"%3b - public const string LibGit2SharpCommitSha = "$(GitCommitId)"%3b + public const string LibGit2SharpCommitSha = "$(LibGit2SharpCommitSha)"%3b } } From f3306fd063d513aee1d824265cc26707cebd7d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 23 Nov 2017 16:44:57 +0100 Subject: [PATCH 043/384] Remove two Console.WriteLine calls from the test fixture --- LibGit2Sharp.Tests/RepositoryFixture.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs index 4934629b9..2ff1abb4a 100644 --- a/LibGit2Sharp.Tests/RepositoryFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryFixture.cs @@ -615,10 +615,8 @@ public void QueryingTheRemoteForADetachedHeadBranchReturnsNull() string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { - Console.WriteLine("head, {0}", repo.Head); Commands.Checkout(repo, repo.Head.Tip.Sha, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force }); Branch trackLocal = repo.Head; - Console.WriteLine("head, {0}", repo.Head); Assert.Null(trackLocal.RemoteName); } } From 4b720c5acedf3d5be4c59f7ed44acc6114faf3e4 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 25 Nov 2017 16:27:20 +0000 Subject: [PATCH 044/384] TreeDefinition: allow `Add` a blob by ID Allow consumers to add a blob to a `TreeDefinition` by specifying only the object ID and mode. This lets users build tree entries without having to create a `Blob` object (and thus load the object itself) which is beneficial for users building trees with large objects. This is only useful for Blobs, since they do not need to be fetched from the object database to be realized within the tree builder. Users are not able to add Trees by ID, since we would need to load them (and cannot, since we are not guaranteed to be instantiated within the context of a repository). --- LibGit2Sharp.Tests/TreeDefinitionFixture.cs | 43 +++++++++++++++++++++ LibGit2Sharp/TreeDefinition.cs | 17 ++++++++ LibGit2Sharp/TreeEntryDefinition.cs | 15 +++++++ 3 files changed, 75 insertions(+) diff --git a/LibGit2Sharp.Tests/TreeDefinitionFixture.cs b/LibGit2Sharp.Tests/TreeDefinitionFixture.cs index 9011cad89..c31bd588e 100644 --- a/LibGit2Sharp.Tests/TreeDefinitionFixture.cs +++ b/LibGit2Sharp.Tests/TreeDefinitionFixture.cs @@ -266,6 +266,49 @@ public void CanAddAnExistingBlob(string blobSha, string targetPath) } } + [Theory] + [InlineData("a8233120f6ad708f843d861ce2b7228ec4e3dec6", "README_TOO")] + [InlineData("a8233120f6ad708f843d861ce2b7228ec4e3dec6", "1/README")] + [InlineData("45b983be36b73c0788dc9cbcb76cbb80fc7bb057", "1/another_one.txt")] + [InlineData("45b983be36b73c0788dc9cbcb76cbb80fc7bb057", "another_one.txt")] + public void CanAddBlobById(string blobSha, string targetPath) + { + string path = SandboxBareTestRepo(); + using (var repo = new Repository(path)) + { + TreeDefinition td = TreeDefinition.From(repo.Head.Tip.Tree); + Assert.Null(td[targetPath]); + + var objectId = new ObjectId(blobSha); + + td.Add(targetPath, objectId, Mode.NonExecutableFile); + + TreeEntryDefinition fetched = td[targetPath]; + Assert.NotNull(fetched); + + Assert.Equal(objectId, fetched.TargetId); + Assert.Equal(Mode.NonExecutableFile, fetched.Mode); + } + } + + [Fact] + public void CannotAddTreeById() + { + const string treeSha = "7f76480d939dc401415927ea7ef25c676b8ddb8f"; + const string targetPath = "1/2"; + + string path = SandboxBareTestRepo(); + using (var repo = new Repository(path)) + { + TreeDefinition td = TreeDefinition.From(repo.Head.Tip.Tree); + Assert.Null(td[targetPath]); + + var objectId = new ObjectId(treeSha); + + Assert.Throws(() => td.Add(targetPath, objectId, Mode.Directory)); + } + } + [Fact] public void CanAddAnExistingSubmodule() { diff --git a/LibGit2Sharp/TreeDefinition.cs b/LibGit2Sharp/TreeDefinition.cs index 1830ed55a..73c21aac7 100644 --- a/LibGit2Sharp/TreeDefinition.cs +++ b/LibGit2Sharp/TreeDefinition.cs @@ -201,6 +201,23 @@ public virtual TreeDefinition Add(string targetTreeEntryPath, string filePath, M return Add(targetTreeEntryPath, ted); } + /// + /// Adds or replaces a from an existing blob specified by its Object ID at the specified location. + /// + /// The path within this . + /// The object ID for this entry. + /// The file related attributes. + /// The current . + public virtual TreeDefinition Add(string targetTreeEntryPath, ObjectId id, Mode mode) + { + Ensure.ArgumentNotNull(id, "id"); + Ensure.ArgumentConformsTo(mode, m => m.HasAny(TreeEntryDefinition.BlobModes), "mode"); + + TreeEntryDefinition ted = TreeEntryDefinition.From(id, mode); + + return Add(targetTreeEntryPath, ted); + } + /// /// Adds or replaces a , dynamically built from the provided , at the specified location. /// diff --git a/LibGit2Sharp/TreeEntryDefinition.cs b/LibGit2Sharp/TreeEntryDefinition.cs index b89c59306..2a3ceb35f 100644 --- a/LibGit2Sharp/TreeEntryDefinition.cs +++ b/LibGit2Sharp/TreeEntryDefinition.cs @@ -54,6 +54,8 @@ internal static TreeEntryDefinition From(TreeEntry treeEntry) internal static TreeEntryDefinition From(Blob blob, Mode mode) { + Ensure.ArgumentNotNull(blob, "blob"); + return new TreeEntryDefinition { Mode = mode, @@ -63,6 +65,19 @@ internal static TreeEntryDefinition From(Blob blob, Mode mode) }; } + internal static TreeEntryDefinition From(ObjectId id, Mode mode) + { + Ensure.ArgumentNotNull(id, "id"); + Ensure.ArgumentNotNull(mode, "mode"); + + return new TreeEntryDefinition + { + Mode = mode, + TargetType = TreeEntryTargetType.Blob, + TargetId = id + }; + } + internal static TreeEntryDefinition TransientBlobFrom(string filePath, Mode mode) { Ensure.ArgumentConformsTo(mode, m => m.HasAny(BlobModes), "mode"); From 0cdc81a9c87bc87f791c2bb3156aebac020c1c3d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 25 Nov 2017 16:32:47 +0000 Subject: [PATCH 045/384] ObjectDatabase: update method documentation Update the method documentation for `ObjectDatabase.Write` to be consistent with the other methods. --- LibGit2Sharp/ObjectDatabase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 379d3e048..d0fb57f30 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -178,7 +178,7 @@ public int Provider(IntPtr content, int max_length, IntPtr data) } /// - /// Write an object to the object database + /// Writes an object to the object database. /// /// The contents of the object /// The type of object to write From 923bd8348be48307582cca1d0953038363d9f274 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 24 Nov 2017 14:45:45 +0000 Subject: [PATCH 046/384] ObjectDatabase: test `Write`ing a blob Test that we can `ObjectDatabase.Write` a blob. --- LibGit2Sharp.Tests/ObjectDatabaseFixture.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs index 767732487..7cb79d924 100644 --- a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs +++ b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs @@ -121,6 +121,18 @@ public void CanCreateABlobFromAStream(string expectedSha, string hintPath) } } + [Fact] + public void CanWriteABlobFromAByteArray() + { + var ba = Encoding.ASCII.GetBytes("libgit2\r\n"); + + using (var repo = new Repository(InitNewRepository())) + { + var id = repo.ObjectDatabase.Write(ba); + Assert.Equal(new ObjectId("99115ea359379a218c47cffc83cd0af8c91c4061"), id); + } + } + Stream PrepareMemoryStream(int contentSize) { var sb = new StringBuilder(); From 1abf368c7e439cec821098e9f7babeaa55f03d5f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 24 Nov 2017 15:32:57 +0000 Subject: [PATCH 047/384] ObjectDatabase: Add `Write(Stream, ...)` Provide a mechanism to write a stream directly to an object database. --- LibGit2Sharp.Tests/ObjectDatabaseFixture.cs | 13 ++++ LibGit2Sharp/ObjectDatabase.cs | 72 ++++++++++++--------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs index 7cb79d924..34d3eb77c 100644 --- a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs +++ b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs @@ -133,6 +133,19 @@ public void CanWriteABlobFromAByteArray() } } + [Fact] + public void CanWriteABlobFromAStream() + { + var ba = Encoding.ASCII.GetBytes("libgit2\r\n"); + + using (var stream = new MemoryStream(ba)) + using (var repo = new Repository(InitNewRepository())) + { + var id = repo.ObjectDatabase.Write(stream, stream.Length); + Assert.Equal(new ObjectId("99115ea359379a218c47cffc83cd0af8c91c4061"), id); + } + } + Stream PrepareMemoryStream(int contentSize) { var sb = new StringBuilder(); diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index d0fb57f30..d0f877def 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -187,6 +187,45 @@ public virtual ObjectId Write(byte[] data) where T : GitObject return Proxy.git_odb_write(handle, data, GitObject.TypeToKindMap[typeof(T)]); } + /// + /// Writes an object to the object database. + /// + /// The contents of the object + /// The number of bytes to consume from the stream + /// The type of object to write + public virtual ObjectId Write(Stream stream, long numberOfBytesToConsume) where T : GitObject + { + Ensure.ArgumentNotNull(stream, "stream"); + + if (!stream.CanRead) + { + throw new ArgumentException("The stream cannot be read from.", "stream"); + } + + using (var odbStream = Proxy.git_odb_open_wstream(handle, numberOfBytesToConsume, GitObjectType.Blob)) + { + var buffer = new byte[4 * 1024]; + long totalRead = 0; + + while (totalRead < numberOfBytesToConsume) + { + long left = numberOfBytesToConsume - totalRead; + int toRead = left < buffer.Length ? (int)left : buffer.Length; + var read = stream.Read(buffer, 0, toRead); + + if (read == 0) + { + throw new EndOfStreamException("The stream ended unexpectedly"); + } + + Proxy.git_odb_stream_write(odbStream, buffer, read); + totalRead += read; + } + + return Proxy.git_odb_stream_finalize_write(odbStream); + } + } + /// /// Inserts a into the object database, created from the content of a stream. /// Optionally, git filters will be applied to the content before storing it. @@ -294,37 +333,8 @@ private unsafe Blob CreateBlob(Stream stream, string hintpath, long? numberOfByt /// The created . public virtual Blob CreateBlob(Stream stream, long numberOfBytesToConsume) { - Ensure.ArgumentNotNull(stream, "stream"); - - if (!stream.CanRead) - { - throw new ArgumentException("The stream cannot be read from.", "stream"); - } - - using (var odbStream = Proxy.git_odb_open_wstream(handle, numberOfBytesToConsume, GitObjectType.Blob)) - { - var buffer = new byte[4 * 1024]; - long totalRead = 0; - - while (totalRead < numberOfBytesToConsume) - { - long left = numberOfBytesToConsume - totalRead; - int toRead = left < buffer.Length ? (int)left : buffer.Length; - var read = stream.Read(buffer, 0, toRead); - - if (read == 0) - { - throw new EndOfStreamException("The stream ended unexpectedly"); - } - - Proxy.git_odb_stream_write(odbStream, buffer, read); - totalRead += read; - } - - var id = Proxy.git_odb_stream_finalize_write(odbStream); - - return repo.Lookup(id); - } + var id = Write(stream, numberOfBytesToConsume); + return repo.Lookup(id); } /// From e090ca0d6d2785ef4a4e25360ff21fd7f49b566b Mon Sep 17 00:00:00 2001 From: Jiange Sun Date: Mon, 13 Nov 2017 08:57:58 -0500 Subject: [PATCH 048/384] Adding Support to turn on/off Ofs_Delta and Strict_Object_Creation --- LibGit2Sharp/Core/Proxy.cs | 24 +++++++++++++++++++++++- LibGit2Sharp/GlobalSettings.cs | 18 ++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index c46d5fc1e..0aed20552 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3429,7 +3429,29 @@ public static void git_libgit2_opts_set_enable_caching(bool enabled) Ensure.ZeroResult(res); } -#endregion + /// + /// Enable or disable the ofs_delta capabilty + /// + /// true to enable the ofs_delta capabilty, false otherwise + 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); + Ensure.ZeroResult(res); + } + + /// + /// Enable or disable the strict_object_creation capabilty + /// + /// true to enable the strict_object_creation capabilty, false otherwise + 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); + Ensure.ZeroResult(res); + } + + #endregion private static ICollection git_foreach( Func resultSelector, diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index eef92c07c..386213c76 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -338,5 +338,23 @@ public static void SetEnableCaching(bool enabled) { Proxy.git_libgit2_opts_set_enable_caching(enabled); } + + /// + /// Enable or disable the ofs_delta capability + /// + /// true to enable the ofs_delta capability, false otherwise + public static void SetEnableOfsDelta(bool enabled) + { + Proxy.git_libgit2_opts_set_enable_ofsdelta(enabled); + } + + /// + /// Enable or disable the libgit2 strict_object_creation capability + /// + /// true to enable the strict_object_creation capability, false otherwise + public static void SetEnableStrictObjectCreation(bool enabled) + { + Proxy.git_libgit2_opts_set_enable_strictobjectcreation(enabled); + } } } From 504f95e6205019aeaaf97b2bf212fec354f8bfb2 Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Mon, 12 Feb 2018 09:35:24 -0800 Subject: [PATCH 049/384] Add MergeCommitsIntoIndex to ObjectDatabase --- LibGit2Sharp.Tests/MergeFixture.cs | 42 +++++++++++ LibGit2Sharp/Index.cs | 21 +++++- LibGit2Sharp/ObjectDatabase.cs | 116 ++++++++++++++++++++++------- 3 files changed, 149 insertions(+), 30 deletions(-) diff --git a/LibGit2Sharp.Tests/MergeFixture.cs b/LibGit2Sharp.Tests/MergeFixture.cs index 8b236aa82..4c802871b 100644 --- a/LibGit2Sharp.Tests/MergeFixture.cs +++ b/LibGit2Sharp.Tests/MergeFixture.cs @@ -902,6 +902,48 @@ public void CanIgnoreWhitespaceChangeMergeConflict(string branchName) } } + [Fact] + public void CanMergeIntoIndex() + { + string path = SandboxMergeTestRepo(); + using (var repo = new Repository(path)) + { + var master = repo.Lookup("master"); + + Index index = repo.ObjectDatabase.MergeCommitsIntoIndex(master, master, null); + var tree = index.WriteToTree(); + Assert.Equal(master.Tree.Id, tree.Id); + } + } + + [Fact] + public void CanMergeIntoIndexWithConflicts() + { + string path = SandboxMergeTestRepo(); + using (var repo = new Repository(path)) + { + var master = repo.Lookup("master"); + var branch = repo.Lookup("conflicts"); + + Index index = repo.ObjectDatabase.MergeCommitsIntoIndex(branch, master, null); + Assert.False(index.IsFullyMerged); + + var conflict = index.Conflicts.First(); + + //Resolve the conflict by taking the blob from branch + var blob = repo.Lookup(conflict.Ours.Id); + //Add() does not remove conflict entries for the same path, so they must be explicitly removed first. + index.Remove(conflict.Ours.Path); + index.Add(blob, conflict.Ours.Path, Mode.NonExecutableFile); + + Assert.True(index.IsFullyMerged); + var tree = index.WriteToTree(); + + //Since we took the conflicted blob from the branch, the merged result should be the same as the branch. + Assert.Equal(branch.Tree.Id, tree.Id); + } + } + private Commit AddFileCommitToRepo(IRepository repository, string filename, string content = null) { Touch(repository.Info.WorkingDirectory, filename, content); diff --git a/LibGit2Sharp/Index.cs b/LibGit2Sharp/Index.cs index d68419ab1..13bc1c9f5 100644 --- a/LibGit2Sharp/Index.cs +++ b/LibGit2Sharp/Index.cs @@ -26,16 +26,20 @@ public class Index : IEnumerable protected Index() { } - internal Index(Repository repo) + internal Index(IndexHandle handle, Repository repo) { this.repo = repo; - - handle = Proxy.git_repository_index(repo.Handle); + this.handle = handle; conflicts = new ConflictCollection(this); repo.RegisterForCleanup(handle); } + internal Index(Repository repo) + : this(Proxy.git_repository_index(repo.Handle), repo) + { + } + internal Index(Repository repo, string indexPath) { this.repo = repo; @@ -305,5 +309,16 @@ public virtual void Write() { Proxy.git_index_write(handle); } + + /// + /// Write the contents of this to a tree + /// + /// + public virtual Tree WriteToTree() + { + var treeId = Proxy.git_index_write_tree_to(this.handle, this.repo.Handle); + var result = this.repo.Lookup(treeId); + return result; + } } } diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index d0f877def..1a5034940 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -755,47 +755,36 @@ public virtual Commit FindMergeBase(IEnumerable commits, MergeBaseFindin /// /// Perform a three-way merge of two commits, looking up their - /// commit ancestor. The returned index will contain the results - /// of the merge and can be examined for conflicts. The returned - /// index must be disposed. + /// commit ancestor. The returned will contain the results + /// of the merge and can be examined for conflicts. /// - /// The first tree - /// The second tree + /// The first commit + /// The second commit /// The controlling the merge - /// The containing the merged trees and any conflicts + /// The containing the merged trees and any conflicts public virtual MergeTreeResult MergeCommits(Commit ours, Commit theirs, MergeTreeOptions options) { Ensure.ArgumentNotNull(ours, "ours"); Ensure.ArgumentNotNull(theirs, "theirs"); - options = options ?? new MergeTreeOptions(); + var modifiedOptions = new MergeTreeOptions(); // We throw away the index after looking at the conflicts, so we'll never need the REUC // entries to be there - GitMergeFlag mergeFlags = GitMergeFlag.GIT_MERGE_NORMAL | GitMergeFlag.GIT_MERGE_SKIP_REUC; - if (options.FindRenames) - { - mergeFlags |= GitMergeFlag.GIT_MERGE_FIND_RENAMES; - } - if (options.FailOnConflict) - { - mergeFlags |= GitMergeFlag.GIT_MERGE_FAIL_ON_CONFLICT; - } + modifiedOptions.SkipReuc = true; - - var mergeOptions = new GitMergeOpts + if (options != null) { - Version = 1, - MergeFileFavorFlags = options.MergeFileFavor, - MergeTreeFlags = mergeFlags, - RenameThreshold = (uint)options.RenameThreshold, - TargetLimit = (uint)options.TargetLimit, - }; + modifiedOptions.FailOnConflict = options.FailOnConflict; + modifiedOptions.FindRenames = options.FindRenames; + modifiedOptions.IgnoreWhitespaceChange = options.IgnoreWhitespaceChange; + modifiedOptions.MergeFileFavor = options.MergeFileFavor; + modifiedOptions.RenameThreshold = options.RenameThreshold; + modifiedOptions.TargetLimit = options.TargetLimit; + } bool earlyStop; - using (var oneHandle = Proxy.git_object_lookup(repo.Handle, ours.Id, GitObjectType.Commit)) - using (var twoHandle = Proxy.git_object_lookup(repo.Handle, theirs.Id, GitObjectType.Commit)) - using (var indexHandle = Proxy.git_merge_commits(repo.Handle, oneHandle, twoHandle, mergeOptions, out earlyStop)) + using (var indexHandle = MergeCommits(ours, theirs, modifiedOptions, out earlyStop)) { MergeTreeResult mergeResult; @@ -859,6 +848,79 @@ public virtual PackBuilderResults Pack(PackBuilderOptions options, Action + /// Perform a three-way merge of two commits, looking up their + /// commit ancestor. The returned index will contain the results + /// of the merge and can be examined for conflicts. + /// + /// The first tree + /// The second tree + /// The controlling the merge + /// The containing the merged trees and any conflicts, or null if the merge stopped early due to conflicts + public virtual Index MergeCommitsIntoIndex(Commit ours, Commit theirs, MergeTreeOptions options) + { + Ensure.ArgumentNotNull(ours, "ours"); + Ensure.ArgumentNotNull(theirs, "theirs"); + + options = options ?? new MergeTreeOptions(); + + bool earlyStop; + var indexHandle = MergeCommits(ours, theirs, options, out earlyStop); + if (earlyStop) + { + if (indexHandle != null) + { + indexHandle.Dispose(); + } + return null; + } + var result = new Index(indexHandle, repo); + return result; + } + + /// + /// Perform a three-way merge of two commits, looking up their + /// commit ancestor. The returned index will contain the results + /// of the merge and can be examined for conflicts. + /// + /// The first tree + /// The second tree + /// The controlling the merge + /// True if the merge stopped early due to conflicts + /// The containing the merged trees and any conflicts + private IndexHandle MergeCommits(Commit ours, Commit theirs, MergeTreeOptions options, out bool earlyStop) + { + GitMergeFlag mergeFlags = GitMergeFlag.GIT_MERGE_NORMAL; + if (options.SkipReuc) + { + mergeFlags |= GitMergeFlag.GIT_MERGE_SKIP_REUC; + } + if (options.FindRenames) + { + mergeFlags |= GitMergeFlag.GIT_MERGE_FIND_RENAMES; + } + if (options.FailOnConflict) + { + mergeFlags |= GitMergeFlag.GIT_MERGE_FAIL_ON_CONFLICT; + } + + var mergeOptions = new GitMergeOpts + { + Version = 1, + MergeFileFavorFlags = options.MergeFileFavor, + MergeTreeFlags = mergeFlags, + RenameThreshold = (uint)options.RenameThreshold, + TargetLimit = (uint)options.TargetLimit, + }; + using (var oneHandle = Proxy.git_object_lookup(repo.Handle, ours.Id, GitObjectType.Commit)) + using (var twoHandle = Proxy.git_object_lookup(repo.Handle, theirs.Id, GitObjectType.Commit)) + { + var indexHandle = Proxy.git_merge_commits(repo.Handle, oneHandle, twoHandle, mergeOptions, out earlyStop); + return indexHandle; + } + } + + /// /// Packs objects in the and write a pack (.pack) and index (.idx) files for them. /// For internal use only. From b685aa8e7ed1311250885b93840020d4f750b4da Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 28 Feb 2018 11:55:04 +0000 Subject: [PATCH 050/384] SmartSubtransport: use TLS 1.2 for tests The subtransport tests create a new subtransport and tests that it can talk to github.com. GitHub recently required TLS 1.2 connections, upgrade our test to build a TLS 1.2 connection to GitHub. --- LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs index 950b6fc85..e72c0d7c1 100644 --- a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs +++ b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs @@ -259,6 +259,8 @@ public override int Write(Stream dataStream, long length) 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; From 32f34090ee9d54311fa6499201356154c78ab79f Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Wed, 28 Feb 2018 09:18:55 -0800 Subject: [PATCH 051/384] Return TransientIndex from ObjectDatabase.MergeCommitsIntoIndex --- LibGit2Sharp.Tests/MergeFixture.cs | 34 +++++++++++++++++------------- LibGit2Sharp/Index.cs | 3 +-- LibGit2Sharp/ObjectDatabase.cs | 7 +++--- LibGit2Sharp/TransientIndex.cs | 31 +++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 LibGit2Sharp/TransientIndex.cs diff --git a/LibGit2Sharp.Tests/MergeFixture.cs b/LibGit2Sharp.Tests/MergeFixture.cs index 4c802871b..7ce3ff496 100644 --- a/LibGit2Sharp.Tests/MergeFixture.cs +++ b/LibGit2Sharp.Tests/MergeFixture.cs @@ -910,9 +910,11 @@ public void CanMergeIntoIndex() { var master = repo.Lookup("master"); - Index index = repo.ObjectDatabase.MergeCommitsIntoIndex(master, master, null); - var tree = index.WriteToTree(); - Assert.Equal(master.Tree.Id, tree.Id); + using (TransientIndex index = repo.ObjectDatabase.MergeCommitsIntoIndex(master, master, null)) + { + var tree = index.WriteToTree(); + Assert.Equal(master.Tree.Id, tree.Id); + } } } @@ -925,22 +927,24 @@ public void CanMergeIntoIndexWithConflicts() var master = repo.Lookup("master"); var branch = repo.Lookup("conflicts"); - Index index = repo.ObjectDatabase.MergeCommitsIntoIndex(branch, master, null); - Assert.False(index.IsFullyMerged); + using (TransientIndex index = repo.ObjectDatabase.MergeCommitsIntoIndex(branch, master, null)) + { + Assert.False(index.IsFullyMerged); - var conflict = index.Conflicts.First(); + var conflict = index.Conflicts.First(); - //Resolve the conflict by taking the blob from branch - var blob = repo.Lookup(conflict.Ours.Id); - //Add() does not remove conflict entries for the same path, so they must be explicitly removed first. - index.Remove(conflict.Ours.Path); - index.Add(blob, conflict.Ours.Path, Mode.NonExecutableFile); + //Resolve the conflict by taking the blob from branch + var blob = repo.Lookup(conflict.Ours.Id); + //Add() does not remove conflict entries for the same path, so they must be explicitly removed first. + index.Remove(conflict.Ours.Path); + index.Add(blob, conflict.Ours.Path, Mode.NonExecutableFile); - Assert.True(index.IsFullyMerged); - var tree = index.WriteToTree(); + Assert.True(index.IsFullyMerged); + var tree = index.WriteToTree(); - //Since we took the conflicted blob from the branch, the merged result should be the same as the branch. - Assert.Equal(branch.Tree.Id, tree.Id); + //Since we took the conflicted blob from the branch, the merged result should be the same as the branch. + Assert.Equal(branch.Tree.Id, tree.Id); + } } } diff --git a/LibGit2Sharp/Index.cs b/LibGit2Sharp/Index.cs index 13bc1c9f5..46d756e04 100644 --- a/LibGit2Sharp/Index.cs +++ b/LibGit2Sharp/Index.cs @@ -31,13 +31,12 @@ internal Index(IndexHandle handle, Repository repo) this.repo = repo; this.handle = handle; conflicts = new ConflictCollection(this); - - repo.RegisterForCleanup(handle); } internal Index(Repository repo) : this(Proxy.git_repository_index(repo.Handle), repo) { + repo.RegisterForCleanup(handle); } internal Index(Repository repo, string indexPath) diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 1a5034940..19801a94b 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -856,8 +856,9 @@ public virtual PackBuilderResults Pack(PackBuilderOptions options, ActionThe first tree /// The second tree /// The controlling the merge - /// The containing the merged trees and any conflicts, or null if the merge stopped early due to conflicts - public virtual Index MergeCommitsIntoIndex(Commit ours, Commit theirs, MergeTreeOptions options) + /// The containing the merged trees and any conflicts, or null if the merge stopped early due to conflicts. + /// The index must be disposed by the caller. + public virtual TransientIndex MergeCommitsIntoIndex(Commit ours, Commit theirs, MergeTreeOptions options) { Ensure.ArgumentNotNull(ours, "ours"); Ensure.ArgumentNotNull(theirs, "theirs"); @@ -874,7 +875,7 @@ public virtual Index MergeCommitsIntoIndex(Commit ours, Commit theirs, MergeTree } return null; } - var result = new Index(indexHandle, repo); + var result = new TransientIndex(indexHandle, repo); return result; } diff --git a/LibGit2Sharp/TransientIndex.cs b/LibGit2Sharp/TransientIndex.cs new file mode 100644 index 000000000..65b7b7872 --- /dev/null +++ b/LibGit2Sharp/TransientIndex.cs @@ -0,0 +1,31 @@ +using System; +using LibGit2Sharp.Core.Handles; + +namespace LibGit2Sharp +{ + /// + /// An implementation of with disposal managed by the caller + /// (instead of automatically disposing when the repository is disposed) + /// + public class TransientIndex: Index, IDisposable + { + /// + /// Needed for mocking purposes. + /// + protected TransientIndex() + { } + + internal TransientIndex(IndexHandle handle, Repository repo) + : base(handle, repo) + { + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + this.Handle.SafeDispose(); + } + } +} From 03e3791c26e6120c455739b0994fdba44e9200db Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 28 Feb 2018 11:56:25 +0000 Subject: [PATCH 052/384] Upgrade dependencies --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 ++-- LibGit2Sharp/LibGit2Sharp.csproj | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index bacf2e1ff..29cc60403 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index a9bbb7499..cf211bc03 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -33,9 +33,9 @@ - - - + + + From 70229b085e66430892659a6106deca0a158ce8cc Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 5 Mar 2018 16:19:55 +0000 Subject: [PATCH 053/384] Update nativebinaries to 1.0.196 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index cf211bc03..569ee0a6b 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,7 +32,7 @@ - + From ff2d847e3a9e53d21eee6b5c1af6fc3050e476ea Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 5 Mar 2018 16:20:13 +0000 Subject: [PATCH 054/384] Configuration: now backed by a repository Configurations are now (optionally) backed by a repository. Provide one whenever possible. --- LibGit2Sharp/Configuration.cs | 17 +++++++++-------- LibGit2Sharp/Core/NativeMethods.cs | 1 + LibGit2Sharp/Core/Proxy.cs | 6 ++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/LibGit2Sharp/Configuration.cs b/LibGit2Sharp/Configuration.cs index 5a0aa03f3..9297a5c37 100644 --- a/LibGit2Sharp/Configuration.cs +++ b/LibGit2Sharp/Configuration.cs @@ -52,41 +52,42 @@ internal Configuration( private void Init(Repository repository) { configHandle = Proxy.git_config_new(); + RepositoryHandle repoHandle = (repository != null) ? repository.Handle : null; - if (repository != null) + if (repoHandle != null) { //TODO: push back this logic into libgit2. // As stated by @carlosmn "having a helper function to load the defaults and then allowing you // to modify it before giving it to git_repository_open_ext() would be a good addition, I think." // -- Agreed :) string repoConfigLocation = Path.Combine(repository.Info.Path, "config"); - Proxy.git_config_add_file_ondisk(configHandle, repoConfigLocation, ConfigurationLevel.Local); + Proxy.git_config_add_file_ondisk(configHandle, repoConfigLocation, ConfigurationLevel.Local, repoHandle); - Proxy.git_repository_set_config(repository.Handle, configHandle); + Proxy.git_repository_set_config(repoHandle, configHandle); } else if (repoConfigPath != null) { - Proxy.git_config_add_file_ondisk(configHandle, repoConfigPath, ConfigurationLevel.Local); + Proxy.git_config_add_file_ondisk(configHandle, repoConfigPath, ConfigurationLevel.Local, repoHandle); } if (globalConfigPath != null) { - Proxy.git_config_add_file_ondisk(configHandle, globalConfigPath, ConfigurationLevel.Global); + Proxy.git_config_add_file_ondisk(configHandle, globalConfigPath, ConfigurationLevel.Global, repoHandle); } if (xdgConfigPath != null) { - Proxy.git_config_add_file_ondisk(configHandle, xdgConfigPath, ConfigurationLevel.Xdg); + Proxy.git_config_add_file_ondisk(configHandle, xdgConfigPath, ConfigurationLevel.Xdg, repoHandle); } if (systemConfigPath != null) { - Proxy.git_config_add_file_ondisk(configHandle, systemConfigPath, ConfigurationLevel.System); + Proxy.git_config_add_file_ondisk(configHandle, systemConfigPath, ConfigurationLevel.System, repoHandle); } if (programDataConfigPath != null) { - Proxy.git_config_add_file_ondisk(configHandle, programDataConfigPath, ConfigurationLevel.ProgramData); + Proxy.git_config_add_file_ondisk(configHandle, programDataConfigPath, ConfigurationLevel.ProgramData, repoHandle); } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index d28a7aceb..ddcb0cdd1 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -373,6 +373,7 @@ internal static extern unsafe int git_config_add_file_ondisk( git_config* cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, uint level, + git_repository* repo, [MarshalAs(UnmanagedType.Bool)] bool force); [DllImport(libgit2)] diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 6bef3b6b1..9c1d1218f 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -517,9 +517,11 @@ public static unsafe SignatureInfo git_commit_extract_signature(RepositoryHandle #region git_config_ - public static unsafe void git_config_add_file_ondisk(ConfigurationHandle config, FilePath path, ConfigurationLevel level) + public static unsafe void git_config_add_file_ondisk(ConfigurationHandle config, FilePath path, ConfigurationLevel level, RepositoryHandle repo) { - int res = NativeMethods.git_config_add_file_ondisk(config, path, (uint)level, true); + // RepositoryHandle does implicit cast voodoo that is not null-safe, thus this explicit check + git_repository* repoHandle = (repo != null) ? (git_repository*)repo : null; + int res = NativeMethods.git_config_add_file_ondisk(config, path, (uint)level, repoHandle, true); Ensure.ZeroResult(res); } From 7c48ef0a9ef0387355358e4a0974d5a15c5e8d0c Mon Sep 17 00:00:00 2001 From: Rama Shenai Date: Fri, 9 Mar 2018 15:36:16 -0800 Subject: [PATCH 055/384] Wireup http custom headers in fetch options --- LibGit2Sharp.Tests/CloneFixture.cs | 49 +++++++++++++++++++ LibGit2Sharp.Tests/FetchFixture.cs | 52 +++++++++++++++++++++ LibGit2Sharp/CloneOptions.cs | 5 ++ LibGit2Sharp/Commands/Fetch.cs | 14 ++++-- LibGit2Sharp/Core/GitFetchOptions.cs | 2 +- LibGit2Sharp/Core/GitFetchOptionsWrapper.cs | 36 ++++++++++++++ LibGit2Sharp/FetchOptions.cs | 21 +++++++++ LibGit2Sharp/Repository.cs | 17 ++++--- 8 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 LibGit2Sharp/Core/GitFetchOptionsWrapper.cs diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 00dc9fee6..976ef9322 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -557,5 +557,54 @@ public void CanCancelRecursiveClone() } } + + [Fact] + public void CannotCloneWithForbiddenCustomHeaders() + { + var scd = BuildSelfCleaningDirectory(); + + const string url = "https://github.com/libgit2/TestGitRepository"; + + const string knownHeader = "User-Agent: mygit-201"; + var cloneOptions = new CloneOptions() + { + FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } + }; + + Assert.Throws(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions)); + } + + [Fact] + public void CannotCloneWithMalformedCustomHeaders() + { + var scd = BuildSelfCleaningDirectory(); + + const string url = "https://github.com/libgit2/TestGitRepository"; + + const string knownHeader = "hello world"; + var cloneOptions = new CloneOptions() + { + FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } + }; + + Assert.Throws(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions)); + } + + [Fact] + public void CanCloneWithCustomHeaders() + { + var scd = BuildSelfCleaningDirectory(); + + const string url = "https://github.com/libgit2/TestGitRepository"; + + const string knownHeader = "X-Hello: world"; + var cloneOptions = new CloneOptions() + { + FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } + }; + + var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, cloneOptions); + Assert.True(Directory.Exists(clonedRepoPath)); + } } } diff --git a/LibGit2Sharp.Tests/FetchFixture.cs b/LibGit2Sharp.Tests/FetchFixture.cs index dfe958fc0..170b64d61 100644 --- a/LibGit2Sharp.Tests/FetchFixture.cs +++ b/LibGit2Sharp.Tests/FetchFixture.cs @@ -239,5 +239,57 @@ public void FetchHonorsTheFetchPruneConfigurationEntry() Assert.Equal(4, clonedRepo.Branches.Count(b => b.IsRemote)); } } + + [Fact] + public void CannotFetchWithForbiddenCustomHeaders() + { + var scd = BuildSelfCleaningDirectory(); + + const string url = "https://github.com/libgit2/TestGitRepository"; + + string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath); + + const string knownHeader = "User-Agent: mygit-201"; + var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; + using (var repo = new Repository(clonedRepoPath)) + { + Assert.Throws(() => Commands.Fetch(repo, "origin", new string[0], options, null)); + } + } + + [Fact] + public void CanFetchWithCustomHeaders() + { + var scd = BuildSelfCleaningDirectory(); + + const string url = "https://github.com/libgit2/TestGitRepository"; + + string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath); + + const string knownHeader = "X-Hello: mygit-201"; + var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; + using (var repo = new Repository(clonedRepoPath)) + { + Commands.Fetch(repo, "origin", new string[0], options, null); + } + } + + [Fact] + public void CannotFetchWithMalformedCustomHeaders() + { + var scd = BuildSelfCleaningDirectory(); + + const string url = "https://github.com/libgit2/TestGitRepository"; + + string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath); + + const string knownHeader = "Hello world"; + var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; + using (var repo = new Repository(clonedRepoPath)) + { + Assert.Throws(() => Commands.Fetch(repo, "origin", new string[0], options, null)); + } + } + } } diff --git a/LibGit2Sharp/CloneOptions.cs b/LibGit2Sharp/CloneOptions.cs index 8d260db74..f88ff58d7 100644 --- a/LibGit2Sharp/CloneOptions.cs +++ b/LibGit2Sharp/CloneOptions.cs @@ -43,6 +43,11 @@ public CloneOptions() /// public CheckoutProgressHandler OnCheckoutProgress { get; set; } + /// + /// Gets or sets the fetch options. + /// + public FetchOptions FetchOptions { get; set; } + #region IConvertableToGitCheckoutOpts CheckoutCallbacks IConvertableToGitCheckoutOpts.GenerateCallbacks() diff --git a/LibGit2Sharp/Commands/Fetch.cs b/LibGit2Sharp/Commands/Fetch.cs index ed8ca66c0..d61fca5a5 100644 --- a/LibGit2Sharp/Commands/Fetch.cs +++ b/LibGit2Sharp/Commands/Fetch.cs @@ -38,6 +38,7 @@ public static void Fetch(Repository repository, string remote, IEnumerable 0) + { + fetchOptions.CustomHeaders = GitStrArrayManaged.BuildFrom(options.CustomHeaders); + } + fetchOptions.ProxyOptions = new GitProxyOptions { Version = 1 }; Proxy.git_remote_fetch(remoteHandle, refspecs, fetchOptions, logMessage); diff --git a/LibGit2Sharp/Core/GitFetchOptions.cs b/LibGit2Sharp/Core/GitFetchOptions.cs index 298c5ae33..3f0baa2c2 100644 --- a/LibGit2Sharp/Core/GitFetchOptions.cs +++ b/LibGit2Sharp/Core/GitFetchOptions.cs @@ -11,6 +11,6 @@ internal class GitFetchOptions public bool UpdateFetchHead = true; public TagFetchMode download_tags; public GitProxyOptions ProxyOptions; - public GitStrArrayManaged custom_headers; + public GitStrArrayManaged CustomHeaders; } } diff --git a/LibGit2Sharp/Core/GitFetchOptionsWrapper.cs b/LibGit2Sharp/Core/GitFetchOptionsWrapper.cs new file mode 100644 index 000000000..351947bbe --- /dev/null +++ b/LibGit2Sharp/Core/GitFetchOptionsWrapper.cs @@ -0,0 +1,36 @@ +using System; + +namespace LibGit2Sharp.Core +{ + /// + /// Git fetch options wrapper. Disposable wrapper for GitFetchOptions + /// + internal class GitFetchOptionsWrapper : IDisposable + { + public GitFetchOptionsWrapper() : this(new GitFetchOptions()) { } + + public GitFetchOptionsWrapper(GitFetchOptions fetchOptions) + { + this.Options = fetchOptions; + } + + public GitFetchOptions Options { get; private set; } + + #region IDisposable + private bool disposedValue = false; // To detect redundant calls + protected virtual void Dispose(bool disposing) + { + if (disposedValue) + return; + + this.Options.CustomHeaders.Dispose(); + disposedValue = true; + } + + public void Dispose() + { + Dispose(true); + } + #endregion + } +} diff --git a/LibGit2Sharp/FetchOptions.cs b/LibGit2Sharp/FetchOptions.cs index a9d2fb2c7..487baed97 100644 --- a/LibGit2Sharp/FetchOptions.cs +++ b/LibGit2Sharp/FetchOptions.cs @@ -25,5 +25,26 @@ public sealed class FetchOptions : FetchOptionsBase /// /// public bool? Prune { get; set; } + + /// + /// Get/Set the custom headers. + /// + /// + /// This allows you to set custom headers (e.g. X-Forwarded-For, + /// X-Request-Id, etc), + /// + /// + /// + /// Libgit2 sets some headers for HTTP requests (User-Agent, Host, + /// Accept, Content-Type, Transfer-Encoding, Content-Length, Accept) that + /// cannot be overriden. + /// + /// + /// var fetchOptions - new FetchOptions() { + /// CustomHeaders = new String[] {"X-Request-Id: 12345"} + /// }; + /// + /// The custom headers string array + public string[] CustomHeaders { get; set; } } } diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 84110f409..f49e2fcfc 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -703,21 +703,26 @@ public static string Clone(string sourceUrl, string workdirPath, throw new UserCancelledException("Clone cancelled by the user."); } - using (GitCheckoutOptsWrapper checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) + using (var checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) + using (var fetchOptionsWrapper = new GitFetchOptionsWrapper()) { var gitCheckoutOptions = checkoutOptionsWrapper.Options; - var remoteCallbacks = new RemoteCallbacks(options); - var gitRemoteCallbacks = remoteCallbacks.GenerateCallbacks(); - - var gitProxyOptions = new GitProxyOptions { Version = 1 }; + var gitFetchOptions = fetchOptionsWrapper.Options; + gitFetchOptions.ProxyOptions = new GitProxyOptions { Version = 1 }; + gitFetchOptions.RemoteCallbacks = new RemoteCallbacks(options).GenerateCallbacks(); + if (options.FetchOptions != null && options.FetchOptions.CustomHeaders != null) + { + gitFetchOptions.CustomHeaders = + GitStrArrayManaged.BuildFrom(options.FetchOptions.CustomHeaders); + } var cloneOpts = new GitCloneOptions { Version = 1, Bare = options.IsBare ? 1 : 0, CheckoutOpts = gitCheckoutOptions, - FetchOpts = new GitFetchOptions { ProxyOptions = gitProxyOptions, RemoteCallbacks = gitRemoteCallbacks }, + FetchOpts = gitFetchOptions, }; string clonedRepoPath; From 8411c9f4c42710a802d2c5c1ff62237fba2940c3 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 26 Mar 2018 05:05:14 -0700 Subject: [PATCH 056/384] Update libgit2 to v0.27.0 (6311e88) --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 569ee0a6b..fc15f0e2f 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,7 +32,7 @@ - + From 7cc420cf0739616f5dfc079b1c386f6dd43fb72d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 26 Mar 2018 07:07:48 -0700 Subject: [PATCH 057/384] Release 0.25 --- CHANGES.md | 23 ++++++++++++++++++++++- version.json | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5d459cefc..6ec51a0e1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,10 +10,27 @@ - Windows (x86/amd64): - Linux/Mac OS X: -## v0.24 + 1 +## v0.25 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.24..v0.25)) + +LibGit2Sharp is now .NET Core 2.0+ and .NET Framework compatible. ### Additions + - `GitObject` now has a `Peel` method that will let you peel (for example) + a `Tag` to a `Tree`. + - `MergeOptions` now includes an option to `IgnoreWhitespaceChanges`. + - `TreeDefinition` can now `Add` an object with only the ID, which allows + users of large files to add entries without realizing a `Blob`. + - `ObjectDatabase` can now `Write` a `Stream`, which allows users of + large files to stream an object into storage without loading it into + memory. + - `ObjectDatabase` can now `MergeCommitsIntoIndex` allowing users to perform + an in-memory merge that produces an `Index` structure with conflicts. + - Users can enable or disable dependent object existence checks when + creating new objects with `GlobalSettings.SetEnableStrictObjectCreation` + - Users can enable or disable `ofs_delta` support with + `GlobalSettings.SetEnableOfsDelta` + ### Changes - Status now does not show untracked files by default. To retrieve @@ -21,11 +38,15 @@ the `StatusOptions.RecurseUntrackedDirs` options. - Status now does not show the ignored files by default. To retrieve ignored files, include the `StatusOptions.IncludeIgnored` option. + - `Commands.Pull` can now provide a `null` value for `PullOptions`, + which indicates that default values should be used. ### Fixes - The exception thrown when the native library cannot be loaded is now able to be caught and will no longer crash the process. + - Getting the `Notes` collection from a `Repository` no longer throws an + exception when the repository has no notes. ## v0.24 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.23..v0.24)) diff --git a/version.json b/version.json index fe5217a4a..557aaf883 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.25.0-preview.{height}", + "version": "0.25.0", "publicReleaseRefSpec": [ "^refs/heads/master$", // we release out of master "^refs/heads/v\\d+(?:\\.\\d+)?$" // we also release out of vNN branches From 706b92ba224326b4dbf9d3d1d2b5d2ba2f732750 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 16 Apr 2018 12:09:20 +0100 Subject: [PATCH 058/384] Prepare for v0.26 Update the `version.json` to begin producing 0.26-preview builds. Update the `CHANGES.md` to include an 0.26 section. --- CHANGES.md | 2 ++ version.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 6ec51a0e1..5f606ea43 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ - Windows (x86/amd64): - Linux/Mac OS X: +## v0.26 + ## v0.25 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.24..v0.25)) LibGit2Sharp is now .NET Core 2.0+ and .NET Framework compatible. diff --git a/version.json b/version.json index 557aaf883..a70502173 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.25.0", + "version": "0.26.0-preview.{height}", "publicReleaseRefSpec": [ "^refs/heads/master$", // we release out of master "^refs/heads/v\\d+(?:\\.\\d+)?$" // we also release out of vNN branches From b01c549fa0ee4eb1668fb8caec71154ca6eafddc Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Tue, 10 Apr 2018 18:50:28 -0700 Subject: [PATCH 059/384] Avoid reading and writing global state when loading native library --- LibGit2Sharp/Core/NativeMethods.cs | 50 ++++++++++++++++++++---------- LibGit2Sharp/Core/Platform.cs | 12 +++++++ LibGit2Sharp/GlobalSettings.cs | 38 +++++++++++++++-------- 3 files changed, 70 insertions(+), 30 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index ddcb0cdd1..bc1ae8a15 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -1,10 +1,15 @@ using System; -using System.Globalization; using System.IO; using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using LibGit2Sharp.Core.Handles; +// 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 { @@ -17,41 +22,52 @@ internal static class NativeMethods // This will handle initialization and shutdown of the underlying // native library. #pragma warning disable 0414 - private static readonly NativeShutdownObject shutdownObject; - #pragma warning restore 0414 + private static NativeShutdownObject shutdownObject; +#pragma warning restore 0414 static NativeMethods() { - if (Platform.OperatingSystem == OperatingSystemType.Windows) + if (Platform.IsRunningOnNetFramework()) { - string nativeLibraryPath = GlobalSettings.GetAndLockNativeLibraryPath(); - - string path = Path.Combine(nativeLibraryPath, Platform.ProcessorArchitecture); + string dllPath = Path.Combine(GlobalSettings.GetAndLockNativeLibraryPath(), libgit2 + ".dll"); - const string pathEnvVariable = "PATH"; - Environment.SetEnvironmentVariable(pathEnvVariable, - String.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", path, Path.PathSeparator, Environment.GetEnvironmentVariable(pathEnvVariable))); + // 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. + LoadWindowsLibrary(dllPath); } - LoadNativeLibrary(); - shutdownObject = new NativeShutdownObject(); + InitializeNativeLibrary(); } + [DllImport("kernel32", EntryPoint = "LoadLibrary")] + private static extern IntPtr LoadWindowsLibrary(string path); + // Avoid inlining this method because otherwise mono's JITter may try // to load the library _before_ we've configured the path. [MethodImpl(MethodImplOptions.NoInlining)] - private static void LoadNativeLibrary() + private static void InitializeNativeLibrary() { - // Configure the OpenSSL locking on the true initialization - // of the library. - if (git_libgit2_init() == 1) + int initCounter; + try + { + } + finally // avoid thread aborts + { + // Initialization can be called multiple times as long as there is a corresponding shutdown to each initialization. + initCounter = git_libgit2_init(); + shutdownObject = new NativeShutdownObject(); + } + + // Configure the OpenSSL locking on the first initialization of the library in the current process. + if (initCounter == 1) { git_openssl_set_locking(); } } // Shutdown the native library in a finalizer. - private sealed class NativeShutdownObject + private sealed class NativeShutdownObject : CriticalFinalizerObject { ~NativeShutdownObject() { diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index a07d5172e..8fdbb9b62 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -36,5 +36,17 @@ public static OperatingSystemType OperatingSystem throw new InvalidOperationException(); } } + + /// + /// Returns true if the runtime is Mono. + /// + public static bool IsRunningOnMono() + => Type.GetType("Mono.Runtime") != null; + + /// + /// Returns true if the runtime is .NET Framework. + /// + public static bool IsRunningOnNetFramework() + => typeof(object).Assembly.GetName().Name == "mscorlib" && !IsRunningOnMono(); } } diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index c953a7b0e..eaffbedab 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -13,6 +14,7 @@ public static class GlobalSettings { private static readonly Lazy version = new Lazy(Version.Build); private static readonly Dictionary registeredFilters; + private static readonly bool nativeLibraryPathAllowed; private static LogConfiguration logConfiguration = LogConfiguration.None; @@ -21,7 +23,9 @@ public static class GlobalSettings static GlobalSettings() { - if (Platform.OperatingSystem == OperatingSystemType.Windows) + nativeLibraryPathAllowed = Platform.IsRunningOnNetFramework(); + + if (nativeLibraryPathAllowed) { /* Assembly.CodeBase is not actually a correctly formatted * URI. It's merely prefixed with `file:///` and has its @@ -148,23 +152,24 @@ public static LogConfiguration LogConfiguration } /// - /// Sets a hint path for searching for native binaries: when - /// specified, native binaries will first be searched in a - /// subdirectory of the given path corresponding to the operating - /// system and architecture (eg, "x86" or "x64") before falling - /// back to the default path ("lib\win32\x86" or "lib\win32\x64" - /// next to the application). + /// Sets a path for loading native binaries on .NET Framework. + /// When specified, native .dll will first be searched in a + /// subdirectory of the given path corresponding to the + /// architecture ("x86" or "x64") before falling + /// back to searching the default load directories + /// (, + /// and + /// ). /// /// This must be set before any other calls to the library, - /// and is not available on Unix platforms: see your dynamic - /// library loader's documentation for details. + /// and is not available on other platforms than .NET Framework. /// /// public static string NativeLibraryPath { get { - if (Platform.OperatingSystem != OperatingSystemType.Windows) + if (!nativeLibraryPathAllowed) { throw new LibGit2SharpException("Querying the native hint path is only supported on Windows platforms"); } @@ -174,7 +179,7 @@ public static string NativeLibraryPath set { - if (Platform.OperatingSystem != OperatingSystemType.Windows) + if (!nativeLibraryPathAllowed) { throw new LibGit2SharpException("Setting the native hint path is only supported on Windows platforms"); } @@ -184,14 +189,21 @@ public static string NativeLibraryPath throw new LibGit2SharpException("You cannot set the native library path after it has been loaded"); } - nativeLibraryPath = value; + try + { + nativeLibraryPath = Path.GetFullPath(value); + } + catch (Exception e) + { + throw new LibGit2SharpException(e.Message); + } } } internal static string GetAndLockNativeLibraryPath() { nativeLibraryPathLocked = true; - return nativeLibraryPath; + return Path.Combine(nativeLibraryPath, Platform.ProcessorArchitecture); } /// From 0e2665c1de6d55de8f4fef80c07663776985e2c4 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Wed, 11 Apr 2018 18:07:24 -0700 Subject: [PATCH 060/384] Add test. Sign all assemblies. Add InternalsVisibleTo to the product assembly, so that tests can access internal APIs. --- Directory.Build.props | 2 + .../LibGit2Sharp.TestApp.csproj | 13 ++++++ LibGit2Sharp.TestApp/TestApp.cs | 46 +++++++++++++++++++ LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 35 +++++++++++++- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 +- LibGit2Sharp.Tests/SetErrorFixture.cs | 2 +- .../TestHelpers/ConditionalFactAttribute.cs | 36 +++++++++++++++ .../TestHelpers/ProcessHelper.cs | 36 +++++++++++++++ LibGit2Sharp.sln | 6 +++ LibGit2Sharp/LibGit2Sharp.csproj | 4 +- LibGit2Sharp/Properties/AssemblyInfo.cs | 3 ++ 11 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 LibGit2Sharp.TestApp/LibGit2Sharp.TestApp.csproj create mode 100644 LibGit2Sharp.TestApp/TestApp.cs create mode 100644 LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs create mode 100644 LibGit2Sharp.Tests/TestHelpers/ProcessHelper.cs diff --git a/Directory.Build.props b/Directory.Build.props index fb2ca9ca9..26d936e15 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,6 +5,8 @@ $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ $(DefineConstants);$(ExtraDefine) + true + ..\libgit2sharp.snk diff --git a/LibGit2Sharp.TestApp/LibGit2Sharp.TestApp.csproj b/LibGit2Sharp.TestApp/LibGit2Sharp.TestApp.csproj new file mode 100644 index 000000000..a802df9ae --- /dev/null +++ b/LibGit2Sharp.TestApp/LibGit2Sharp.TestApp.csproj @@ -0,0 +1,13 @@ + + + + Exe + net461 + AnyCPU + + + + + + + diff --git a/LibGit2Sharp.TestApp/TestApp.cs b/LibGit2Sharp.TestApp/TestApp.cs new file mode 100644 index 000000000..234169a75 --- /dev/null +++ b/LibGit2Sharp.TestApp/TestApp.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace LibGit2Sharp.Tests +{ + public class TestApp + { + [DllImport("kernel32")] + private static extern IntPtr GetModuleHandle(string path); + + [DllImport("kernel32")] + private static extern int GetModuleFileName(IntPtr handle, [Out]StringBuilder path, int size); + + static int Main(string[] args) + { + if (args.Length < 1 || args.Length > 2) + { + Console.Error.WriteLine("Usage: "); + return -1; + } + + var moduleName = args[0]; + var loadFromDirectory = args[1]; + var expectedPath = Path.Combine(loadFromDirectory, (IntPtr.Size == 4) ? "x86" : "x64", moduleName + ".dll"); + + GlobalSettings.NativeLibraryPath = loadFromDirectory; + var isValid = Repository.IsValid(Path.GetTempPath()); + + var capacity = ushort.MaxValue; + var moduleHandle = GetModuleHandle(moduleName); + var buffer = new StringBuilder(capacity); + int actualLength = GetModuleFileName(moduleHandle, buffer, capacity); + var actualPath = buffer.ToString(0, actualLength); + + if (expectedPath != actualPath) + { + Console.WriteLine(actualPath); + return 1; + } + + return 0; + } + } +} diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 76b2c2ad3..9df459ddf 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -1,4 +1,7 @@ -using System.Text.RegularExpressions; +using System; +using System.IO; +using System.Text.RegularExpressions; +using LibGit2Sharp.Core; using LibGit2Sharp.Tests.TestHelpers; using Xunit; @@ -49,5 +52,35 @@ public void TryingToResetNativeLibraryPathAfterLoadedThrows() Assert.Throws(() => { GlobalSettings.NativeLibraryPath = "C:/Foo"; }); } + + [ConditionalFact(typeof(NetFramework))] + public void LoadFromSpecifiedPath() + { +#if NET461 + var nativeDllFileName = NativeDllName.Name + ".dll"; + + var testAppExe = typeof(TestApp).Assembly.Location; + var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var platformDir = Path.Combine(tempDir, "plat"); + + try + { + Directory.CreateDirectory(Path.Combine(platformDir, "x86")); + Directory.CreateDirectory(Path.Combine(platformDir, "x64")); + + File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, "x86", nativeDllFileName), Path.Combine(platformDir, "x86", nativeDllFileName)); + File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, "x64", nativeDllFileName), Path.Combine(platformDir, "x64", nativeDllFileName)); + + var (output, exitCode) = ProcessHelper.RunProcess(testAppExe, arguments: $@"{NativeDllName.Name} ""{platformDir}""", workingDirectory: tempDir); + + Assert.Empty(output); + Assert.Equal(0, exitCode); + } + finally + { + DirectoryHelper.DeleteDirectory(tempDir); + } +#endif + } } } diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 29cc60403..7b0c17e19 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -2,11 +2,11 @@ net461;netcoreapp2.0 - $(DefineConstants);DESKTOP + @@ -19,8 +19,6 @@ - - diff --git a/LibGit2Sharp.Tests/SetErrorFixture.cs b/LibGit2Sharp.Tests/SetErrorFixture.cs index 31b7513a2..609e0f77c 100644 --- a/LibGit2Sharp.Tests/SetErrorFixture.cs +++ b/LibGit2Sharp.Tests/SetErrorFixture.cs @@ -49,7 +49,7 @@ public void FormatAggregateException() Exception exceptionToThrow = new AggregateException(aggregateExceptionMessage, new Exception(innerExceptionMessage), new Exception(innerExceptionMessage2)); StringBuilder sb = new StringBuilder(); -#if DESKTOP +#if NET461 sb.AppendLine(aggregateExceptionMessage); #else sb.AppendLine($"{aggregateExceptionMessage} ({innerExceptionMessage}) ({innerExceptionMessage2})"); diff --git a/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs b/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs new file mode 100644 index 000000000..2e97ecaaf --- /dev/null +++ b/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using LibGit2Sharp.Core; +using Xunit; + +namespace LibGit2Sharp.Tests +{ + public class ConditionalFactAttribute : FactAttribute + { + public ConditionalFactAttribute(params Type[] skipConditions) + { + foreach (var skipCondition in skipConditions) + { + ExecutionCondition condition = (ExecutionCondition)Activator.CreateInstance(skipCondition); + if (condition.ShouldSkip) + { + Skip = condition.SkipReason; + break; + } + } + } + } + + public abstract class ExecutionCondition + { + public abstract bool ShouldSkip { get; } + public abstract string SkipReason { get; } + } + + public class NetFramework : ExecutionCondition + { + public override bool ShouldSkip => !Platform.IsRunningOnNetFramework(); + public override string SkipReason => ".NET Framework only test"; + } +} diff --git a/LibGit2Sharp.Tests/TestHelpers/ProcessHelper.cs b/LibGit2Sharp.Tests/TestHelpers/ProcessHelper.cs new file mode 100644 index 000000000..7c2855528 --- /dev/null +++ b/LibGit2Sharp.Tests/TestHelpers/ProcessHelper.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace LibGit2Sharp.Tests +{ + public static class ProcessHelper + { + public static (string, int) RunProcess(string fileName, string arguments, string workingDirectory = null) + { + var process = new Process + { + StartInfo = new ProcessStartInfo(fileName, arguments) + { + RedirectStandardError = true, + RedirectStandardOutput = true, + CreateNoWindow = true, + UseShellExecute = false, + WorkingDirectory = workingDirectory ?? string.Empty + } + }; + + var output = new StringBuilder(); + + process.OutputDataReceived += (_, e) => output.AppendLine(e.Data); + process.ErrorDataReceived += (_, e) => output.AppendLine(e.Data); + + process.Start(); + + process.WaitForExit(); + + return (output.ToString(), process.ExitCode); + } + } +} diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index fb8a7101b..b9ecd1f45 100644 --- a/LibGit2Sharp.sln +++ b/LibGit2Sharp.sln @@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution version.json = version.json EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibGit2Sharp.TestApp", "LibGit2Sharp.TestApp\LibGit2Sharp.TestApp.csproj", "{86453D2C-4953-4DF4-B12A-ADE579608BAA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,6 +31,10 @@ Global {286E63EB-04DD-4ADE-88D6-041B57800761}.Debug|Any CPU.Build.0 = Debug|Any CPU {286E63EB-04DD-4ADE-88D6-041B57800761}.Release|Any CPU.ActiveCfg = Release|Any CPU {286E63EB-04DD-4ADE-88D6-041B57800761}.Release|Any CPU.Build.0 = Release|Any CPU + {86453D2C-4953-4DF4-B12A-ADE579608BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86453D2C-4953-4DF4-B12A-ADE579608BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86453D2C-4953-4DF4-B12A-ADE579608BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86453D2C-4953-4DF4-B12A-ADE579608BAA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index fc15f0e2f..f161ddddb 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -9,9 +9,7 @@ libgit2 git https://github.com/libgit2/libgit2sharp/ LibGit2Sharp contributors - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - true - ..\libgit2sharp.snk + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb diff --git a/LibGit2Sharp/Properties/AssemblyInfo.cs b/LibGit2Sharp/Properties/AssemblyInfo.cs index ffa977d1d..ccbbf7b5f 100644 --- a/LibGit2Sharp/Properties/AssemblyInfo.cs +++ b/LibGit2Sharp/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -16,3 +17,5 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("c6f71967-5be1-49f5-b48e-861bff498ea3")] + +[assembly: InternalsVisibleTo("LibGit2Sharp.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010013172CAC3D61EF825164EF8443ED2F97316D0C2A4A65D3B2F6E5C9175C6C589D6A0EAE803E3E7FC0DA9E6672B1DE036CF74E1D33E21DD83E1145E3A454F92E52107495082DCCD1D9F521592F79F41DF26ED727059F8A4E5D3C23ECC525306831A15F1E56B693FDE112137E973B599A13209A5B63E05EE00886DE594E70A993B5")] From 8a10035c2cbd5ad635386c8675c2489f624f882d Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Wed, 11 Apr 2018 19:06:25 -0700 Subject: [PATCH 061/384] Make test types internal --- LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs b/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs index 2e97ecaaf..cc052a4b8 100644 --- a/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs +++ b/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs @@ -6,7 +6,7 @@ namespace LibGit2Sharp.Tests { - public class ConditionalFactAttribute : FactAttribute + internal class ConditionalFactAttribute : FactAttribute { public ConditionalFactAttribute(params Type[] skipConditions) { @@ -22,13 +22,13 @@ public ConditionalFactAttribute(params Type[] skipConditions) } } - public abstract class ExecutionCondition + internal abstract class ExecutionCondition { public abstract bool ShouldSkip { get; } public abstract string SkipReason { get; } } - public class NetFramework : ExecutionCondition + internal class NetFramework : ExecutionCondition { public override bool ShouldSkip => !Platform.IsRunningOnNetFramework(); public override string SkipReason => ".NET Framework only test"; From 748e5968ab804244acafe127cfe8a05fc89233f0 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Thu, 12 Apr 2018 15:43:39 -0700 Subject: [PATCH 062/384] PR feedback and test both x64 and x86 platforms --- Directory.Build.props | 2 +- .../LibGit2Sharp.TestApp.x64.csproj} | 8 +++-- .../x86/LibGit2Sharp.TestApp.x86.csproj | 17 +++++++++ LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 21 ++++++----- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 20 +++++++++-- LibGit2Sharp.Tests/SetErrorFixture.cs | 2 +- .../TestHelpers/ConditionalFactAttribute.cs | 36 ------------------- LibGit2Sharp.sln | 8 ++++- 8 files changed, 59 insertions(+), 55 deletions(-) rename LibGit2Sharp.TestApp/{LibGit2Sharp.TestApp.csproj => x64/LibGit2Sharp.TestApp.x64.csproj} (52%) create mode 100644 LibGit2Sharp.TestApp/x86/LibGit2Sharp.TestApp.x86.csproj delete mode 100644 LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs diff --git a/Directory.Build.props b/Directory.Build.props index 26d936e15..5402df162 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,7 @@ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ $(DefineConstants);$(ExtraDefine) true - ..\libgit2sharp.snk + $(MSBuildThisFileDirectory)libgit2sharp.snk diff --git a/LibGit2Sharp.TestApp/LibGit2Sharp.TestApp.csproj b/LibGit2Sharp.TestApp/x64/LibGit2Sharp.TestApp.x64.csproj similarity index 52% rename from LibGit2Sharp.TestApp/LibGit2Sharp.TestApp.csproj rename to LibGit2Sharp.TestApp/x64/LibGit2Sharp.TestApp.x64.csproj index a802df9ae..a3c313a59 100644 --- a/LibGit2Sharp.TestApp/LibGit2Sharp.TestApp.csproj +++ b/LibGit2Sharp.TestApp/x64/LibGit2Sharp.TestApp.x64.csproj @@ -3,11 +3,15 @@ Exe net461 - AnyCPU + x64 - + + + + + diff --git a/LibGit2Sharp.TestApp/x86/LibGit2Sharp.TestApp.x86.csproj b/LibGit2Sharp.TestApp/x86/LibGit2Sharp.TestApp.x86.csproj new file mode 100644 index 000000000..daaf8f51f --- /dev/null +++ b/LibGit2Sharp.TestApp/x86/LibGit2Sharp.TestApp.x86.csproj @@ -0,0 +1,17 @@ + + + + Exe + net461 + x86 + + + + + + + + + + + diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 9df459ddf..2bd350eb3 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -53,23 +53,23 @@ public void TryingToResetNativeLibraryPathAfterLoadedThrows() Assert.Throws(() => { GlobalSettings.NativeLibraryPath = "C:/Foo"; }); } - [ConditionalFact(typeof(NetFramework))] - public void LoadFromSpecifiedPath() + [SkippableTheory] + [InlineData(new object[] { "x86" })] + [InlineData(new object[] { "x64" })] + public void LoadFromSpecifiedPath(string platform) { -#if NET461 - var nativeDllFileName = NativeDllName.Name + ".dll"; + Skip.IfNot(Platform.IsRunningOnNetFramework(), ".NET Framework only test."); - var testAppExe = typeof(TestApp).Assembly.Location; + var nativeDllFileName = NativeDllName.Name + ".dll"; + var testDir = Path.GetDirectoryName(typeof(GlobalSettingsFixture).Assembly.Location); + var testAppExe = Path.Combine(testDir, $"LibGit2Sharp.TestApp.{platform}.exe"); var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); var platformDir = Path.Combine(tempDir, "plat"); try { - Directory.CreateDirectory(Path.Combine(platformDir, "x86")); - Directory.CreateDirectory(Path.Combine(platformDir, "x64")); - - File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, "x86", nativeDllFileName), Path.Combine(platformDir, "x86", nativeDllFileName)); - File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, "x64", nativeDllFileName), Path.Combine(platformDir, "x64", nativeDllFileName)); + Directory.CreateDirectory(Path.Combine(platformDir, platform)); + File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, platform, nativeDllFileName), Path.Combine(platformDir, platform, nativeDllFileName)); var (output, exitCode) = ProcessHelper.RunProcess(testAppExe, arguments: $@"{NativeDllName.Name} ""{platformDir}""", workingDirectory: tempDir); @@ -80,7 +80,6 @@ public void LoadFromSpecifiedPath() { DirectoryHelper.DeleteDirectory(tempDir); } -#endif } } } diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 7b0c17e19..5e5d610a6 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -2,11 +2,13 @@ net461;netcoreapp2.0 + $(DefineConstants);DESKTOP - + + @@ -18,8 +20,20 @@ - - + + + <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).exe')" /> + <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).exe.config')" /> + <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).pdb')" /> + + + + + + + + + diff --git a/LibGit2Sharp.Tests/SetErrorFixture.cs b/LibGit2Sharp.Tests/SetErrorFixture.cs index 609e0f77c..31b7513a2 100644 --- a/LibGit2Sharp.Tests/SetErrorFixture.cs +++ b/LibGit2Sharp.Tests/SetErrorFixture.cs @@ -49,7 +49,7 @@ public void FormatAggregateException() Exception exceptionToThrow = new AggregateException(aggregateExceptionMessage, new Exception(innerExceptionMessage), new Exception(innerExceptionMessage2)); StringBuilder sb = new StringBuilder(); -#if NET461 +#if DESKTOP sb.AppendLine(aggregateExceptionMessage); #else sb.AppendLine($"{aggregateExceptionMessage} ({innerExceptionMessage}) ({innerExceptionMessage2})"); diff --git a/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs b/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs deleted file mode 100644 index cc052a4b8..000000000 --- a/LibGit2Sharp.Tests/TestHelpers/ConditionalFactAttribute.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using LibGit2Sharp.Core; -using Xunit; - -namespace LibGit2Sharp.Tests -{ - internal class ConditionalFactAttribute : FactAttribute - { - public ConditionalFactAttribute(params Type[] skipConditions) - { - foreach (var skipCondition in skipConditions) - { - ExecutionCondition condition = (ExecutionCondition)Activator.CreateInstance(skipCondition); - if (condition.ShouldSkip) - { - Skip = condition.SkipReason; - break; - } - } - } - } - - internal abstract class ExecutionCondition - { - public abstract bool ShouldSkip { get; } - public abstract string SkipReason { get; } - } - - internal class NetFramework : ExecutionCondition - { - public override bool ShouldSkip => !Platform.IsRunningOnNetFramework(); - public override string SkipReason => ".NET Framework only test"; - } -} diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index b9ecd1f45..ed3dd1b56 100644 --- a/LibGit2Sharp.sln +++ b/LibGit2Sharp.sln @@ -15,7 +15,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution version.json = version.json EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibGit2Sharp.TestApp", "LibGit2Sharp.TestApp\LibGit2Sharp.TestApp.csproj", "{86453D2C-4953-4DF4-B12A-ADE579608BAA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp.TestApp.x86", "LibGit2Sharp.TestApp\x86\LibGit2Sharp.TestApp.x86.csproj", "{86453D2C-4953-4DF4-B12A-ADE579608BAA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp.TestApp.x64", "LibGit2Sharp.TestApp\x64\LibGit2Sharp.TestApp.x64.csproj", "{5C55175D-6A1F-4C51-B791-BF7DD00124EE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -35,6 +37,10 @@ Global {86453D2C-4953-4DF4-B12A-ADE579608BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU {86453D2C-4953-4DF4-B12A-ADE579608BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU {86453D2C-4953-4DF4-B12A-ADE579608BAA}.Release|Any CPU.Build.0 = Release|Any CPU + {5C55175D-6A1F-4C51-B791-BF7DD00124EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C55175D-6A1F-4C51-B791-BF7DD00124EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C55175D-6A1F-4C51-B791-BF7DD00124EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C55175D-6A1F-4C51-B791-BF7DD00124EE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 671d0589465a92389f7cb1d84bee2231c15f5445 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Thu, 12 Apr 2018 15:44:38 -0700 Subject: [PATCH 063/384] Rename platform to architecture --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 2bd350eb3..65b897f7f 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -54,22 +54,22 @@ public void TryingToResetNativeLibraryPathAfterLoadedThrows() } [SkippableTheory] - [InlineData(new object[] { "x86" })] - [InlineData(new object[] { "x64" })] - public void LoadFromSpecifiedPath(string platform) + [InlineData("x86")] + [InlineData("x64")] + public void LoadFromSpecifiedPath(string architecture) { Skip.IfNot(Platform.IsRunningOnNetFramework(), ".NET Framework only test."); var nativeDllFileName = NativeDllName.Name + ".dll"; var testDir = Path.GetDirectoryName(typeof(GlobalSettingsFixture).Assembly.Location); - var testAppExe = Path.Combine(testDir, $"LibGit2Sharp.TestApp.{platform}.exe"); + var testAppExe = Path.Combine(testDir, $"LibGit2Sharp.TestApp.{architecture}.exe"); var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); var platformDir = Path.Combine(tempDir, "plat"); try { - Directory.CreateDirectory(Path.Combine(platformDir, platform)); - File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, platform, nativeDllFileName), Path.Combine(platformDir, platform, nativeDllFileName)); + Directory.CreateDirectory(Path.Combine(platformDir, architecture)); + File.Copy(Path.Combine(GlobalSettings.NativeLibraryPath, architecture, nativeDllFileName), Path.Combine(platformDir, architecture, nativeDllFileName)); var (output, exitCode) = ProcessHelper.RunProcess(testAppExe, arguments: $@"{NativeDllName.Name} ""{platformDir}""", workingDirectory: tempDir); From 2c1e96d323b36ea48359c14a99d516342bd1726a Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Fri, 13 Apr 2018 19:16:25 -0700 Subject: [PATCH 064/384] Do not create packages for test app projects --- LibGit2Sharp.TestApp/Directory.Build.props | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 LibGit2Sharp.TestApp/Directory.Build.props diff --git a/LibGit2Sharp.TestApp/Directory.Build.props b/LibGit2Sharp.TestApp/Directory.Build.props new file mode 100644 index 000000000..c55b35c72 --- /dev/null +++ b/LibGit2Sharp.TestApp/Directory.Build.props @@ -0,0 +1,7 @@ + + + + false + + + From fc7b5b34daa0ade8f04163e2ed140f95fb080aa9 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Fri, 13 Apr 2018 19:17:59 -0700 Subject: [PATCH 065/384] Search for native library in runtimes dir and allow setting NativeLibraryPath on .NET Core. --- LibGit2Sharp/Core/NativeMethods.cs | 18 +++++-- LibGit2Sharp/Core/Platform.cs | 46 +++++++++++++++- LibGit2Sharp/GlobalSettings.cs | 85 +++++++++++++++++++----------- 3 files changed, 115 insertions(+), 34 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index bc1ae8a15..4c54388b7 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -27,19 +27,31 @@ internal static class NativeMethods static NativeMethods() { - if (Platform.IsRunningOnNetFramework()) + if (Platform.IsRunningOnNetFramework() || Platform.IsRunningOnNetCore()) { - string dllPath = Path.Combine(GlobalSettings.GetAndLockNativeLibraryPath(), libgit2 + ".dll"); + string dllPath = Path.Combine(GlobalSettings.GetAndLockNativeLibraryPath(), libgit2 + Platform.GetNativeLibraryExtension()); // 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. - LoadWindowsLibrary(dllPath); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + LoadWindowsLibrary(dllPath); + } + else + { + LoadUnixLibrary(dllPath, RTLD_NOW); + } } InitializeNativeLibrary(); } + public const int RTLD_NOW = 0x002; + + [DllImport("libdl", EntryPoint = "dlopen")] + private static extern IntPtr LoadUnixLibrary(string path, int flags); + [DllImport("kernel32", EntryPoint = "LoadLibrary")] private static extern IntPtr LoadWindowsLibrary(string path); diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index 8fdbb9b62..53475bec0 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -33,10 +33,48 @@ public static OperatingSystemType OperatingSystem return OperatingSystemType.MacOSX; } - throw new InvalidOperationException(); + throw new PlatformNotSupportedException(); } } + /// + /// Determines the RID to use when loading libgit2 native library. + /// This method only supports RIDs that are currently used by LibGit2Sharp.NativeBinaries. + /// + public static string GetNativeLibraryRuntimeId() + { + switch (OperatingSystem) + { + case OperatingSystemType.MacOSX: + return "osx"; + + case OperatingSystemType.Unix: + return "linux-" + ProcessorArchitecture; + + case OperatingSystemType.Windows: + return "win7-" + ProcessorArchitecture; + } + + throw new PlatformNotSupportedException(); + } + + public static string GetNativeLibraryExtension() + { + switch (OperatingSystem) + { + case OperatingSystemType.MacOSX: + return ".dylib"; + + case OperatingSystemType.Unix: + return ".so"; + + case OperatingSystemType.Windows: + return ".dll"; + } + + throw new PlatformNotSupportedException(); + } + /// /// Returns true if the runtime is Mono. /// @@ -48,5 +86,11 @@ public static bool IsRunningOnMono() /// public static bool IsRunningOnNetFramework() => typeof(object).Assembly.GetName().Name == "mscorlib" && !IsRunningOnMono(); + + /// + /// Returns true if the runtime is .NET Core. + /// + public static bool IsRunningOnNetCore() + => typeof(object).Assembly.GetName().Name != "mscorlib"; } } diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index eaffbedab..5378a6829 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -23,36 +23,57 @@ public static class GlobalSettings static GlobalSettings() { - nativeLibraryPathAllowed = Platform.IsRunningOnNetFramework(); + bool netFX = Platform.IsRunningOnNetFramework(); + bool netCore = Platform.IsRunningOnNetCore(); + + nativeLibraryPathAllowed = netFX || netCore; if (nativeLibraryPathAllowed) { - /* Assembly.CodeBase is not actually a correctly formatted - * URI. It's merely prefixed with `file:///` and has its - * backslashes flipped. This is superior to EscapedCodeBase, - * which does not correctly escape things, and ambiguates a - * space (%20) with a literal `%20` in the path. Sigh. - */ - var managedPath = Assembly.GetExecutingAssembly().CodeBase; - if (managedPath == null) - { - managedPath = Assembly.GetExecutingAssembly().Location; - } - else if (managedPath.StartsWith("file:///")) + string assemblyDirectory = GetExecutingAssemblyDirectory(); + + if (netFX) { - managedPath = managedPath.Substring(8).Replace('/', '\\'); + // For .NET Framework apps the dependencies are deployed to lib/win32/{architecture} directory + nativeLibraryPath = Path.Combine(assemblyDirectory, "lib", "win32"); } - else if (managedPath.StartsWith("file://")) + else { - managedPath = @"\\" + managedPath.Substring(7).Replace('/', '\\'); + // .NET Core apps that depend on native libraries load them directly from paths specified + // in .deps.json file of that app and the native library loader just works. + // However, .NET Core doesn't support .deps.json for plugins yet (such as msbuild tasks). + // To address that shortcoming we assume that the plugin deploys the native binaries to runtimes\{rid}\native + // directories and search there. + nativeLibraryPath = Path.Combine(assemblyDirectory, "runtimes", Platform.GetNativeLibraryRuntimeId(), "native"); } + } - managedPath = Path.GetDirectoryName(managedPath); + registeredFilters = new Dictionary(); + } - nativeLibraryPath = Path.Combine(managedPath, "lib", "win32"); + private static string GetExecutingAssemblyDirectory() + { + // Assembly.CodeBase is not actually a correctly formatted + // URI. It's merely prefixed with `file:///` and has its + // backslashes flipped. This is superior to EscapedCodeBase, + // which does not correctly escape things, and ambiguates a + // space (%20) with a literal `%20` in the path. Sigh. + var managedPath = Assembly.GetExecutingAssembly().CodeBase; + if (managedPath == null) + { + managedPath = Assembly.GetExecutingAssembly().Location; + } + else if (managedPath.StartsWith("file:///")) + { + managedPath = managedPath.Substring(8).Replace('/', '\\'); + } + else if (managedPath.StartsWith("file://")) + { + managedPath = @"\\" + managedPath.Substring(7).Replace('/', '\\'); } - registeredFilters = new Dictionary(); + managedPath = Path.GetDirectoryName(managedPath); + return managedPath; } /// @@ -152,17 +173,18 @@ public static LogConfiguration LogConfiguration } /// - /// Sets a path for loading native binaries on .NET Framework. - /// When specified, native .dll will first be searched in a - /// subdirectory of the given path corresponding to the - /// architecture ("x86" or "x64") before falling - /// back to searching the default load directories - /// (, + /// 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: + /// , /// and - /// ). + /// . /// /// This must be set before any other calls to the library, - /// and is not available on other platforms than .NET Framework. + /// and is not available on other platforms than .NET Framework and .NET Core. /// /// public static string NativeLibraryPath @@ -171,7 +193,7 @@ public static string NativeLibraryPath { if (!nativeLibraryPathAllowed) { - throw new LibGit2SharpException("Querying the native hint path is only supported on Windows platforms"); + throw new LibGit2SharpException("Querying the native hint path is only supported on .NET Framework and .NET Core platforms"); } return nativeLibraryPath; @@ -181,7 +203,7 @@ public static string NativeLibraryPath { if (!nativeLibraryPathAllowed) { - throw new LibGit2SharpException("Setting the native hint path is only supported on Windows platforms"); + throw new LibGit2SharpException("Setting the native hint path is only supported on .NET Framework and .NET Core platforms"); } if (nativeLibraryPathLocked) @@ -203,7 +225,10 @@ public static string NativeLibraryPath internal static string GetAndLockNativeLibraryPath() { nativeLibraryPathLocked = true; - return Path.Combine(nativeLibraryPath, Platform.ProcessorArchitecture); + + return Platform.IsRunningOnNetFramework() ? + Path.Combine(nativeLibraryPath, Platform.ProcessorArchitecture) : + nativeLibraryPath; } /// From fe71caa5b87adb09184f9233a2f94b99f36ebce2 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Mon, 16 Apr 2018 09:59:30 -0700 Subject: [PATCH 066/384] Avoid IVT --- Directory.Build.props | 2 -- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 12 +++++++----- LibGit2Sharp/LibGit2Sharp.csproj | 4 +++- LibGit2Sharp/Properties/AssemblyInfo.cs | 3 --- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 5402df162..fb2ca9ca9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,8 +5,6 @@ $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ $(DefineConstants);$(ExtraDefine) - true - $(MSBuildThisFileDirectory)libgit2sharp.snk diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 5e5d610a6..5eacddd31 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -20,20 +20,22 @@ + + + + + + <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).exe')" /> <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).exe.config')" /> <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).pdb')" /> - + - - - - diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index f161ddddb..fc15f0e2f 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -9,7 +9,9 @@ libgit2 git https://github.com/libgit2/libgit2sharp/ LibGit2Sharp contributors - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + ..\libgit2sharp.snk diff --git a/LibGit2Sharp/Properties/AssemblyInfo.cs b/LibGit2Sharp/Properties/AssemblyInfo.cs index ccbbf7b5f..ffa977d1d 100644 --- a/LibGit2Sharp/Properties/AssemblyInfo.cs +++ b/LibGit2Sharp/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -17,5 +16,3 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("c6f71967-5be1-49f5-b48e-861bff498ea3")] - -[assembly: InternalsVisibleTo("LibGit2Sharp.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010013172CAC3D61EF825164EF8443ED2F97316D0C2A4A65D3B2F6E5C9175C6C589D6A0EAE803E3E7FC0DA9E6672B1DE036CF74E1D33E21DD83E1145E3A454F92E52107495082DCCD1D9F521592F79F41DF26ED727059F8A4E5D3C23ECC525306831A15F1E56B693FDE112137E973B599A13209A5B63E05EE00886DE594E70A993B5")] From 9aadf0bcae8b73107cb91c219a64d2378ccb3ec1 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Mon, 16 Apr 2018 10:13:47 -0700 Subject: [PATCH 067/384] Generate NativeDllName in tests --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 ++ LibGit2Sharp/LibGit2Sharp.csproj | 3 +- .../CodeGenerator.targets | 24 -------------- Targets/GenerateNativeDllName.targets | 33 +++++++++++++++++++ 4 files changed, 37 insertions(+), 25 deletions(-) rename {LibGit2Sharp => Targets}/CodeGenerator.targets (75%) create mode 100644 Targets/GenerateNativeDllName.targets diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 5eacddd31..d1d11ef31 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -37,5 +37,7 @@ + + diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index fc15f0e2f..9b910685e 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -38,7 +38,8 @@ - + + diff --git a/LibGit2Sharp/CodeGenerator.targets b/Targets/CodeGenerator.targets similarity index 75% rename from LibGit2Sharp/CodeGenerator.targets rename to Targets/CodeGenerator.targets index a317d9261..ae73a4725 100644 --- a/LibGit2Sharp/CodeGenerator.targets +++ b/Targets/CodeGenerator.targets @@ -6,36 +6,12 @@ - $(IntermediateOutputPath)NativeDllName.g.cs $(IntermediateOutputPath)UniqueIdentifier.g.cs $(IntermediateOutputPath)AssemblyCommitIds.g.cs - - - - namespace LibGit2Sharp.Core - { - internal static class NativeDllName - { - public const string Name = "$(libgit2_filename)"%3b - } - } - - - - - - - - - - - - - diff --git a/Targets/GenerateNativeDllName.targets b/Targets/GenerateNativeDllName.targets new file mode 100644 index 000000000..244b707b4 --- /dev/null +++ b/Targets/GenerateNativeDllName.targets @@ -0,0 +1,33 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + $(IntermediateOutputPath)NativeDllName.g.cs + + + + + + + namespace LibGit2Sharp.Core + { + internal static class NativeDllName + { + public const string Name = "$(libgit2_filename)"%3b + } + } + + + + + + + + + + + From 896eb24e14045e6b0af5110dea20c2f9e2892734 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Mon, 16 Apr 2018 10:19:32 -0700 Subject: [PATCH 068/384] Rename TestApp to NativeLibraryLoadTestApp --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 2 +- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 ++-- LibGit2Sharp.sln | 4 ++-- .../Directory.Build.props | 0 {LibGit2Sharp.TestApp => NativeLibraryLoadTestApp}/TestApp.cs | 0 .../x64/NativeLibraryLoadTestApp.x64.csproj | 0 .../x86/NativeLibraryLoadTestApp.x86.csproj | 0 7 files changed, 5 insertions(+), 5 deletions(-) rename {LibGit2Sharp.TestApp => NativeLibraryLoadTestApp}/Directory.Build.props (100%) rename {LibGit2Sharp.TestApp => NativeLibraryLoadTestApp}/TestApp.cs (100%) rename LibGit2Sharp.TestApp/x64/LibGit2Sharp.TestApp.x64.csproj => NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj (100%) rename LibGit2Sharp.TestApp/x86/LibGit2Sharp.TestApp.x86.csproj => NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj (100%) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 65b897f7f..381d13d65 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -62,7 +62,7 @@ public void LoadFromSpecifiedPath(string architecture) var nativeDllFileName = NativeDllName.Name + ".dll"; var testDir = Path.GetDirectoryName(typeof(GlobalSettingsFixture).Assembly.Location); - var testAppExe = Path.Combine(testDir, $"LibGit2Sharp.TestApp.{architecture}.exe"); + var testAppExe = Path.Combine(testDir, $"NativeLibraryLoadTestApp.{architecture}.exe"); var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); var platformDir = Path.Combine(tempDir, "plat"); diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index d1d11ef31..4a705d51b 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index ed3dd1b56..1bcc15392 100644 --- a/LibGit2Sharp.sln +++ b/LibGit2Sharp.sln @@ -15,9 +15,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution version.json = version.json EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp.TestApp.x86", "LibGit2Sharp.TestApp\x86\LibGit2Sharp.TestApp.x86.csproj", "{86453D2C-4953-4DF4-B12A-ADE579608BAA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeLibraryLoadTestApp.x86", "NativeLibraryLoadTestApp\x86\NativeLibraryLoadTestApp.x86.csproj", "{86453D2C-4953-4DF4-B12A-ADE579608BAA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp.TestApp.x64", "LibGit2Sharp.TestApp\x64\LibGit2Sharp.TestApp.x64.csproj", "{5C55175D-6A1F-4C51-B791-BF7DD00124EE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeLibraryLoadTestApp.x64", "NativeLibraryLoadTestApp\x64\NativeLibraryLoadTestApp.x64.csproj", "{5C55175D-6A1F-4C51-B791-BF7DD00124EE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/LibGit2Sharp.TestApp/Directory.Build.props b/NativeLibraryLoadTestApp/Directory.Build.props similarity index 100% rename from LibGit2Sharp.TestApp/Directory.Build.props rename to NativeLibraryLoadTestApp/Directory.Build.props diff --git a/LibGit2Sharp.TestApp/TestApp.cs b/NativeLibraryLoadTestApp/TestApp.cs similarity index 100% rename from LibGit2Sharp.TestApp/TestApp.cs rename to NativeLibraryLoadTestApp/TestApp.cs diff --git a/LibGit2Sharp.TestApp/x64/LibGit2Sharp.TestApp.x64.csproj b/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj similarity index 100% rename from LibGit2Sharp.TestApp/x64/LibGit2Sharp.TestApp.x64.csproj rename to NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj diff --git a/LibGit2Sharp.TestApp/x86/LibGit2Sharp.TestApp.x86.csproj b/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj similarity index 100% rename from LibGit2Sharp.TestApp/x86/LibGit2Sharp.TestApp.x86.csproj rename to NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj From 53e1feafc3b0017c8cd9e49ac8b95882a4826b31 Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Mon, 16 Apr 2018 10:33:26 -0700 Subject: [PATCH 069/384] Fix path --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 4a705d51b..ae58206ec 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -7,8 +7,8 @@ - - + + From e618156c150d0bf2c318f5e6fa30b468f63ee45f Mon Sep 17 00:00:00 2001 From: Tomas Matousek Date: Mon, 16 Apr 2018 10:34:01 -0700 Subject: [PATCH 070/384] Do not set default value for NativeLibararyPath on .NET Core --- LibGit2Sharp/Core/NativeMethods.cs | 26 ++++++++++++--------- LibGit2Sharp/Core/Platform.cs | 21 ----------------- LibGit2Sharp/GlobalSettings.cs | 37 ++++++++++++------------------ 3 files changed, 30 insertions(+), 54 deletions(-) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 4c54388b7..b5aa8097e 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -29,18 +29,22 @@ static NativeMethods() { if (Platform.IsRunningOnNetFramework() || Platform.IsRunningOnNetCore()) { - string dllPath = Path.Combine(GlobalSettings.GetAndLockNativeLibraryPath(), libgit2 + Platform.GetNativeLibraryExtension()); - - // 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. - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - LoadWindowsLibrary(dllPath); - } - else + string nativeLibraryDir = GlobalSettings.GetAndLockNativeLibraryPath(); + if (nativeLibraryDir != null) { - LoadUnixLibrary(dllPath, RTLD_NOW); + string nativeLibraryPath = Path.Combine(nativeLibraryDir, libgit2 + Platform.GetNativeLibraryExtension()); + + // 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. + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + LoadWindowsLibrary(nativeLibraryPath); + } + else + { + LoadUnixLibrary(nativeLibraryPath, RTLD_NOW); + } } } diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index 53475bec0..e8d536475 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -37,27 +37,6 @@ public static OperatingSystemType OperatingSystem } } - /// - /// Determines the RID to use when loading libgit2 native library. - /// This method only supports RIDs that are currently used by LibGit2Sharp.NativeBinaries. - /// - public static string GetNativeLibraryRuntimeId() - { - switch (OperatingSystem) - { - case OperatingSystemType.MacOSX: - return "osx"; - - case OperatingSystemType.Unix: - return "linux-" + ProcessorArchitecture; - - case OperatingSystemType.Windows: - return "win7-" + ProcessorArchitecture; - } - - throw new PlatformNotSupportedException(); - } - public static string GetNativeLibraryExtension() { switch (OperatingSystem) diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 5378a6829..f71646e76 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -20,6 +20,7 @@ public static class GlobalSettings private static string nativeLibraryPath; private static bool nativeLibraryPathLocked; + private static string nativeLibraryDefaultPath; static GlobalSettings() { @@ -28,24 +29,14 @@ static GlobalSettings() nativeLibraryPathAllowed = netFX || netCore; - if (nativeLibraryPathAllowed) + if (netFX) { - string assemblyDirectory = GetExecutingAssemblyDirectory(); - - if (netFX) - { - // For .NET Framework apps the dependencies are deployed to lib/win32/{architecture} directory - nativeLibraryPath = Path.Combine(assemblyDirectory, "lib", "win32"); - } - else - { - // .NET Core apps that depend on native libraries load them directly from paths specified - // in .deps.json file of that app and the native library loader just works. - // However, .NET Core doesn't support .deps.json for plugins yet (such as msbuild tasks). - // To address that shortcoming we assume that the plugin deploys the native binaries to runtimes\{rid}\native - // directories and search there. - nativeLibraryPath = Path.Combine(assemblyDirectory, "runtimes", Platform.GetNativeLibraryRuntimeId(), "native"); - } + // For .NET Framework apps the dependencies are deployed to lib/win32/{architecture} directory + nativeLibraryDefaultPath = Path.Combine(GetExecutingAssemblyDirectory(), "lib", "win32"); + } + else + { + nativeLibraryDefaultPath = null; } registeredFilters = new Dictionary(); @@ -186,6 +177,10 @@ 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 { @@ -196,7 +191,7 @@ public static string NativeLibraryPath throw new LibGit2SharpException("Querying the native hint path is only supported on .NET Framework and .NET Core platforms"); } - return nativeLibraryPath; + return nativeLibraryPath ?? nativeLibraryDefaultPath; } set @@ -225,10 +220,8 @@ public static string NativeLibraryPath internal static string GetAndLockNativeLibraryPath() { nativeLibraryPathLocked = true; - - return Platform.IsRunningOnNetFramework() ? - Path.Combine(nativeLibraryPath, Platform.ProcessorArchitecture) : - nativeLibraryPath; + string result = nativeLibraryPath ?? nativeLibraryDefaultPath; + return Platform.IsRunningOnNetFramework() ? Path.Combine(result, Platform.ProcessorArchitecture) : result; } /// From d9496ba00be1bb3669626a0552ee5da0319a7f72 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 16 Apr 2018 20:35:06 -0400 Subject: [PATCH 071/384] Clean up trailing whitespace --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index ae58206ec..6837e02eb 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -37,7 +37,7 @@ - + From 497f91f181cf13c5ac41c63bf1d5052e21bd8f99 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 16 Apr 2018 20:36:04 -0400 Subject: [PATCH 072/384] Add code generation targets to Solution Items --- LibGit2Sharp.sln | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index 1bcc15392..921aee2d4 100644 --- a/LibGit2Sharp.sln +++ b/LibGit2Sharp.sln @@ -9,8 +9,10 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0CA739FD-DA4D-4F64-9834-DA14A3ECD04B}" ProjectSection(SolutionItems) = preProject .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 EndProjectSection From 7062b0aa1db962eb02f7abc42e51e27f77547301 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 17 Apr 2018 20:07:52 -0400 Subject: [PATCH 073/384] Replace helper implementation with DateOffset members --- LibGit2Sharp/Core/Epoch.cs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/LibGit2Sharp/Core/Epoch.cs b/LibGit2Sharp/Core/Epoch.cs index 0f2657267..69aaf16dc 100644 --- a/LibGit2Sharp/Core/Epoch.cs +++ b/LibGit2Sharp/Core/Epoch.cs @@ -7,30 +7,20 @@ namespace LibGit2Sharp.Core /// internal static class Epoch { - private static readonly DateTimeOffset epochDateTimeOffset = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); - /// /// Builds a from a Unix timestamp and a timezone offset. /// /// The number of seconds since 00:00:00 UTC on 1 January 1970. /// The number of minutes from UTC in a timezone. /// A representing this instant. - public static DateTimeOffset ToDateTimeOffset(long secondsSinceEpoch, int timeZoneOffsetInMinutes) - { - DateTimeOffset utcDateTime = epochDateTimeOffset.AddSeconds(secondsSinceEpoch); - TimeSpan offset = TimeSpan.FromMinutes(timeZoneOffsetInMinutes); - return new DateTimeOffset(utcDateTime.DateTime.Add(offset), offset); - } + public static DateTimeOffset ToDateTimeOffset(long secondsSinceEpoch, int timeZoneOffsetInMinutes) => + DateTimeOffset.FromUnixTimeSeconds(secondsSinceEpoch).ToOffset(TimeSpan.FromMinutes(timeZoneOffsetInMinutes)); /// /// Converts the part of a into a Unix timestamp. /// /// The to convert. /// The number of seconds since 00:00:00 UTC on 1 January 1970. - public static Int32 ToSecondsSinceEpoch(this DateTimeOffset date) - { - DateTimeOffset utcDate = date.ToUniversalTime(); - return (Int32)utcDate.Subtract(epochDateTimeOffset).TotalSeconds; - } + public static Int32 ToSecondsSinceEpoch(this DateTimeOffset date) => (int)date.ToUnixTimeSeconds(); } } From faffe4a9b7ec1ae6da5d91cd8e288817087c6c7a Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 17 Apr 2018 20:15:13 -0400 Subject: [PATCH 074/384] Replace primary usages --- LibGit2Sharp/Core/Proxy.cs | 2 +- LibGit2Sharp/Core/TarWriter.cs | 2 +- LibGit2Sharp/Signature.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 9c1d1218f..4bf144524 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -2793,7 +2793,7 @@ public static unsafe SignatureHandle git_signature_new(string name, string email { git_signature* ptr; - int res = NativeMethods.git_signature_new(out ptr, name, email, when.ToSecondsSinceEpoch(), + int res = NativeMethods.git_signature_new(out ptr, name, email, when.ToUnixTimeSeconds(), (int)when.Offset.TotalMinutes); Ensure.ZeroResult(res); diff --git a/LibGit2Sharp/Core/TarWriter.cs b/LibGit2Sharp/Core/TarWriter.cs index 7c479cec9..609449316 100644 --- a/LibGit2Sharp/Core/TarWriter.cs +++ b/LibGit2Sharp/Core/TarWriter.cs @@ -332,7 +332,7 @@ public UsTarHeader( this.mode = Convert.ToString(mode, 8).PadLeft(7, '0'); this.size = size; - unixTime = Convert.ToString(lastModificationTime.ToSecondsSinceEpoch(), 8).PadLeft(11, '0'); + unixTime = Convert.ToString(lastModificationTime.ToUnixTimeSeconds(), 8).PadLeft(11, '0'); this.userId = userId.PadLeft(7, '0'); this.groupId = userId.PadLeft(7, '0'); this.userName = userName; diff --git a/LibGit2Sharp/Signature.cs b/LibGit2Sharp/Signature.cs index 003abd629..bad656d05 100644 --- a/LibGit2Sharp/Signature.cs +++ b/LibGit2Sharp/Signature.cs @@ -21,7 +21,7 @@ internal unsafe Signature(git_signature* sig) { name = LaxUtf8Marshaler.FromNative(sig->name); email = LaxUtf8Marshaler.FromNative(sig->email); - when = Epoch.ToDateTimeOffset(sig->when.time, sig->when.offset); + when = DateTimeOffset.FromUnixTimeSeconds(sig->when.time).ToOffset(TimeSpan.FromMinutes(sig->when.offset)); } /// From 6be1b5195120a5091e5a781606fdb6656bc93ab0 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 17 Apr 2018 20:27:03 -0400 Subject: [PATCH 075/384] Replace test usages --- LibGit2Sharp.Tests/CommitFixture.cs | 8 +- LibGit2Sharp.Tests/EpochFixture.cs | 87 ------------------- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 - LibGit2Sharp.Tests/NoteFixture.cs | 2 +- LibGit2Sharp.Tests/TagFixture.cs | 2 +- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 4 +- LibGit2Sharp/Core/Epoch.cs | 26 ------ 7 files changed, 8 insertions(+), 122 deletions(-) delete mode 100644 LibGit2Sharp.Tests/EpochFixture.cs delete mode 100644 LibGit2Sharp/Core/Epoch.cs diff --git a/LibGit2Sharp.Tests/CommitFixture.cs b/LibGit2Sharp.Tests/CommitFixture.cs index 179a4975c..5533b7232 100644 --- a/LibGit2Sharp.Tests/CommitFixture.cs +++ b/LibGit2Sharp.Tests/CommitFixture.cs @@ -475,12 +475,12 @@ public void CanReadCommitData() Assert.NotNull(commit.Author); Assert.Equal("Scott Chacon", commit.Author.Name); Assert.Equal("schacon@gmail.com", commit.Author.Email); - Assert.Equal(1273360386, commit.Author.When.ToSecondsSinceEpoch()); + Assert.Equal(1273360386, commit.Author.When.ToUnixTimeSeconds()); Assert.NotNull(commit.Committer); Assert.Equal("Scott Chacon", commit.Committer.Name); Assert.Equal("schacon@gmail.com", commit.Committer.Email); - Assert.Equal(1273360386, commit.Committer.When.ToSecondsSinceEpoch()); + Assert.Equal(1273360386, commit.Committer.When.ToUnixTimeSeconds()); Assert.Equal("181037049a54a1eb5fab404658a3a250b44335d7", commit.Tree.Sha); @@ -889,9 +889,9 @@ public void CanCorrectlyDistinguishAuthorFromCommitter() using (var repo = new Repository(path)) { var author = new Signature("Wilbert van Dolleweerd", "getit@xs4all.nl", - Epoch.ToDateTimeOffset(1244187936, 120)); + DateTimeOffset.FromUnixTimeSeconds(1244187936).ToOffset(TimeSpan.FromMinutes(120))); var committer = new Signature("Henk Westhuis", "Henk_Westhuis@hotmail.com", - Epoch.ToDateTimeOffset(1244286496, 120)); + DateTimeOffset.FromUnixTimeSeconds(1244286496).ToOffset(TimeSpan.FromMinutes(120))); Commit c = repo.Commit("I can haz an author and a committer!", author, committer); diff --git a/LibGit2Sharp.Tests/EpochFixture.cs b/LibGit2Sharp.Tests/EpochFixture.cs deleted file mode 100644 index 773f4c846..000000000 --- a/LibGit2Sharp.Tests/EpochFixture.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using LibGit2Sharp.Core; -using Xunit; -using Xunit.Extensions; - -namespace LibGit2Sharp.Tests -{ - public class EpochFixture - { - [Theory] - [InlineData(0)] - [InlineData(17)] - public void UnixTimestampShouldBeCastIntoAUtcBasedDateTimeOffset(long secondsSinceEpoch) - { - DateTimeOffset date = Epoch.ToDateTimeOffset(secondsSinceEpoch, 0); - Assert.Equal(0, date.Offset.TotalMinutes); - - Assert.Equal(TimeSpan.Zero, date.Offset); - Assert.Equal(DateTimeKind.Utc, date.UtcDateTime.Kind); - } - - [Theory] - [InlineData(0, 0)] - [InlineData(17, -120)] - [InlineData(31, 60)] - public void AreEqual(long secondsSinceEpoch, int timezoneOffset) - { - DateTimeOffset one = Epoch.ToDateTimeOffset(secondsSinceEpoch, timezoneOffset); - DateTimeOffset another = Epoch.ToDateTimeOffset(secondsSinceEpoch, timezoneOffset); - - Assert.Equal(one, another); - Assert.Equal(another, one); - - Assert.True(one == another); - Assert.True(another == one); - - Assert.False(one != another); - Assert.False(another != one); - - Assert.Equal(one.GetHashCode(), another.GetHashCode()); - } - - [Theory] - [InlineData(1291801952, "Wed, 08 Dec 2010 09:52:32 +0000")] - [InlineData(1234567890, "Fri, 13 Feb 2009 23:31:30 +0000")] - [InlineData(1288114383, "Tue, 26 Oct 2010 17:33:03 +0000")] - public void UnixTimestampShouldShouldBeCastIntoAPlainUtcDate(long secondsSinceEpoch, string expected) - { - DateTimeOffset expectedDate = DateTimeOffset.Parse(expected); - - DateTimeOffset date = Epoch.ToDateTimeOffset(secondsSinceEpoch, 0); - - Assert.Equal(secondsSinceEpoch, date.ToSecondsSinceEpoch()); - Assert.Equal(expectedDate, date); - Assert.Equal(TimeSpan.Zero, date.Offset); - } - - [Theory] - [InlineData(1250379778, -210, "Sat, 15 Aug 2009 20:12:58 -0330")] - public void UnixTimestampAndTimezoneOffsetShouldBeCastIntoAUtcDateBearingAnOffset(long secondsSinceEpoch, Int32 offset, string expected) - { - DateTimeOffset expectedDate = DateTimeOffset.Parse(expected); - - DateTimeOffset date = Epoch.ToDateTimeOffset(secondsSinceEpoch, offset); - Assert.Equal(offset, date.Offset.TotalMinutes); - Assert.Equal(secondsSinceEpoch, date.ToSecondsSinceEpoch()); - - Assert.Equal(expectedDate, date); - Assert.Equal(expectedDate.Offset, date.Offset); - } - - [Theory] - [InlineData("Wed, 08 Dec 2010 09:52:32 +0000", 1291801952, 0)] - [InlineData("Fri, 13 Feb 2009 23:31:30 +0000", 1234567890, 0)] - [InlineData("Tue, 26 Oct 2010 17:33:03 +0000", 1288114383, 0)] - [InlineData("Sat, 14 Feb 2009 00:31:30 +0100", 1234567890, 60)] - [InlineData("Sat, 15 Aug 2009 20:12:58 -0330", 1250379778, -210)] - [InlineData("Sat, 15 Aug 2009 23:42:58 +0000", 1250379778, 0)] - [InlineData("Sun, 16 Aug 2009 00:42:58 +0100", 1250379778, 60)] - public void DateTimeOffsetShoudlBeCastIntoAUnixTimestampAndATimezoneOffset(string formattedDate, long expectedSeconds, Int32 expectedOffset) - { - DateTimeOffset when = DateTimeOffset.Parse(formattedDate); - DateTimeOffset date = Epoch.ToDateTimeOffset(expectedSeconds, expectedOffset); - Assert.Equal(when, date); - } - } -} diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 6837e02eb..ddb97b176 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -21,7 +21,6 @@ - diff --git a/LibGit2Sharp.Tests/NoteFixture.cs b/LibGit2Sharp.Tests/NoteFixture.cs index e3cb9d7a0..98801e3b2 100644 --- a/LibGit2Sharp.Tests/NoteFixture.cs +++ b/LibGit2Sharp.Tests/NoteFixture.cs @@ -10,7 +10,7 @@ namespace LibGit2Sharp.Tests public class NoteFixture : BaseFixture { private static readonly Signature signatureNullToken = new Signature("nulltoken", "emeric.fermas@gmail.com", DateTimeOffset.UtcNow); - private static readonly Signature signatureYorah = new Signature("yorah", "yoram.harmelin@gmail.com", Epoch.ToDateTimeOffset(1300557894, 60)); + private static readonly Signature signatureYorah = new Signature("yorah", "yoram.harmelin@gmail.com", DateTimeOffset.FromUnixTimeSeconds(1300557894).ToOffset(TimeSpan.FromMinutes(60))); [Fact] public void RetrievingNotesFromANonExistingGitObjectYieldsNoResult() diff --git a/LibGit2Sharp.Tests/TagFixture.cs b/LibGit2Sharp.Tests/TagFixture.cs index 5c1628a7b..82a940640 100644 --- a/LibGit2Sharp.Tests/TagFixture.cs +++ b/LibGit2Sharp.Tests/TagFixture.cs @@ -13,7 +13,7 @@ public class TagFixture : BaseFixture private readonly string[] expectedTags = new[] { "e90810b", "lw", "point_to_blob", "tag_without_tagger", "test", }; private static readonly Signature signatureTim = new Signature("Tim Clem", "timothy.clem@gmail.com", TruncateSubSeconds(DateTimeOffset.UtcNow)); - private static readonly Signature signatureNtk = new Signature("nulltoken", "emeric.fermas@gmail.com", Epoch.ToDateTimeOffset(1300557894, 60)); + private static readonly Signature signatureNtk = new Signature("nulltoken", "emeric.fermas@gmail.com", DateTimeOffset.FromUnixTimeSeconds(1300557894).ToOffset(TimeSpan.FromMinutes(60))); private const string tagTestSha = "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"; private const string commitE90810BSha = "e90810b8df3e80c413d903f631643c716887138d"; private const string tagE90810BSha = "7b4384978d2493e851f9cca7858815fac9b10980"; diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index f1ac7eddd..c188efb9c 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -51,8 +51,8 @@ static BaseFixture() protected static DateTimeOffset TruncateSubSeconds(DateTimeOffset dto) { - int seconds = dto.ToSecondsSinceEpoch(); - return Epoch.ToDateTimeOffset(seconds, (int)dto.Offset.TotalMinutes); + var seconds = dto.ToUnixTimeSeconds(); + return DateTimeOffset.FromUnixTimeSeconds(seconds).ToOffset(dto.Offset); } private static void SetUpTestEnvironment() diff --git a/LibGit2Sharp/Core/Epoch.cs b/LibGit2Sharp/Core/Epoch.cs deleted file mode 100644 index 69aaf16dc..000000000 --- a/LibGit2Sharp/Core/Epoch.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; - -namespace LibGit2Sharp.Core -{ - /// - /// Provides helper methods to help converting between Epoch (unix timestamp) and . - /// - internal static class Epoch - { - /// - /// Builds a from a Unix timestamp and a timezone offset. - /// - /// The number of seconds since 00:00:00 UTC on 1 January 1970. - /// The number of minutes from UTC in a timezone. - /// A representing this instant. - public static DateTimeOffset ToDateTimeOffset(long secondsSinceEpoch, int timeZoneOffsetInMinutes) => - DateTimeOffset.FromUnixTimeSeconds(secondsSinceEpoch).ToOffset(TimeSpan.FromMinutes(timeZoneOffsetInMinutes)); - - /// - /// Converts the part of a into a Unix timestamp. - /// - /// The to convert. - /// The number of seconds since 00:00:00 UTC on 1 January 1970. - public static Int32 ToSecondsSinceEpoch(this DateTimeOffset date) => (int)date.ToUnixTimeSeconds(); - } -} From dba67464a843db50d21651b31bd02e2378d43a3b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 18 Apr 2018 09:43:59 +0100 Subject: [PATCH 076/384] github: add an issue template Add an issue template to encourage people to ask questions on Stack Overflow. --- .github/ISSUE_TEMPLATE | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE new file mode 100644 index 000000000..c37520864 --- /dev/null +++ b/.github/ISSUE_TEMPLATE @@ -0,0 +1,17 @@ +You are opening a _bug report_ against the LibGit2Sharp project: we +use GitHub Issues for tracking bug reports and feature requests. If +you have a question about an API or usage, please ask on StackOverflow: +http://stackoverflow.com/questions/tagged/libgit2sharp. + +Otherwise, to report a bug, please fill out the reproduction steps +(below) and delete these introductory paragraphs. Thanks! + +### Reproduction steps + +### Expected behavior + +### Actual behavior + +### Version of LibGit2Sharp (release number or SHA1) + +### Operating system(s) tested; .NET runtime tested From f147a31983e13faeb41e907654bd99250c839aba Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Thu, 19 Apr 2018 15:27:43 -0700 Subject: [PATCH 077/384] Add CherryPickCommitIntoIndex to ObjectDatabase --- LibGit2Sharp.Tests/CherryPickFixture.cs | 50 +++++++++++ LibGit2Sharp/ObjectDatabase.cs | 105 +++++++++++++++++++----- 2 files changed, 133 insertions(+), 22 deletions(-) diff --git a/LibGit2Sharp.Tests/CherryPickFixture.cs b/LibGit2Sharp.Tests/CherryPickFixture.cs index 3c0026df5..f4a383fef 100644 --- a/LibGit2Sharp.Tests/CherryPickFixture.cs +++ b/LibGit2Sharp.Tests/CherryPickFixture.cs @@ -162,6 +162,56 @@ public void CherryPickWithConflictsReturnsConflicts() } } + [Fact] + public void CanCherryPickCommitIntoIndex() + { + string path = SandboxMergeTestRepo(); + using (var repo = new Repository(path)) + { + var ours = repo.Head.Tip; + + Commit commitToMerge = repo.Branches["fast_forward"].Tip; + + using (TransientIndex index = repo.ObjectDatabase.CherryPickCommitIntoIndex(commitToMerge, ours, 0, null)) + { + var tree = index.WriteToTree(); + Assert.Equal(commitToMerge.Tree.Id, tree.Id); + } + } + } + + [Fact] + public void CanCherryPickIntoIndexWithConflicts() + { + const string conflictBranchName = "conflicts"; + + string path = SandboxMergeTestRepo(); + using (var repo = new Repository(path)) + { + Branch branch = repo.Branches[conflictBranchName]; + Assert.NotNull(branch); + + using (TransientIndex index = repo.ObjectDatabase.CherryPickCommitIntoIndex(branch.Tip, repo.Head.Tip, 0, null)) + { + Assert.False(index.IsFullyMerged); + + var conflict = index.Conflicts.First(); + + //Resolve the conflict by taking the blob from branch + var blob = repo.Lookup(conflict.Theirs.Id); + //Add() does not remove conflict entries for the same path, so they must be explicitly removed first. + index.Remove(conflict.Ours.Path); + index.Add(blob, conflict.Ours.Path, Mode.NonExecutableFile); + + Assert.True(index.IsFullyMerged); + var tree = index.WriteToTree(); + + //Since we took the conflicted blob from the branch, the merged result should be the same as the branch. + Assert.Equal(branch.Tip.Tree.Id, tree.Id); + } + } + } + private Commit AddFileCommitToRepo(IRepository repository, string filename, string content = null) { Touch(repository.Info.WorkingDirectory, filename, content); diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 19801a94b..3a4ebcdb6 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -562,37 +562,26 @@ public virtual HistoryDivergence CalculateHistoryDivergence(Commit one, Commit a public virtual MergeTreeResult CherryPickCommit(Commit cherryPickCommit, Commit cherryPickOnto, int mainline, MergeTreeOptions options) { Ensure.ArgumentNotNull(cherryPickCommit, "cherryPickCommit"); - Ensure.ArgumentNotNull(cherryPickOnto, "ours"); + Ensure.ArgumentNotNull(cherryPickOnto, "cherryPickOnto"); - options = options ?? new MergeTreeOptions(); + var modifiedOptions = new MergeTreeOptions(); // We throw away the index after looking at the conflicts, so we'll never need the REUC // entries to be there - GitMergeFlag mergeFlags = GitMergeFlag.GIT_MERGE_NORMAL | GitMergeFlag.GIT_MERGE_SKIP_REUC; - if (options.FindRenames) - { - mergeFlags |= GitMergeFlag.GIT_MERGE_FIND_RENAMES; - } - if (options.FailOnConflict) - { - mergeFlags |= GitMergeFlag.GIT_MERGE_FAIL_ON_CONFLICT; - } - + modifiedOptions.SkipReuc = true; - var opts = new GitMergeOpts + if (options != null) { - Version = 1, - MergeFileFavorFlags = options.MergeFileFavor, - MergeTreeFlags = mergeFlags, - RenameThreshold = (uint)options.RenameThreshold, - TargetLimit = (uint)options.TargetLimit - }; + modifiedOptions.FailOnConflict = options.FailOnConflict; + modifiedOptions.FindRenames = options.FindRenames; + modifiedOptions.MergeFileFavor = options.MergeFileFavor; + modifiedOptions.RenameThreshold = options.RenameThreshold; + modifiedOptions.TargetLimit = options.TargetLimit; + } bool earlyStop; - using (var cherryPickOntoHandle = Proxy.git_object_lookup(repo.Handle, cherryPickOnto.Id, GitObjectType.Commit)) - using (var cherryPickCommitHandle = Proxy.git_object_lookup(repo.Handle, cherryPickCommit.Id, GitObjectType.Commit)) - using (var indexHandle = Proxy.git_cherrypick_commit(repo.Handle, cherryPickCommitHandle, cherryPickOntoHandle, (uint)mainline, opts, out earlyStop)) + using (var indexHandle = CherryPickCommit(cherryPickCommit, cherryPickOnto, mainline, modifiedOptions, out earlyStop)) { MergeTreeResult cherryPickResult; @@ -879,6 +868,36 @@ public virtual TransientIndex MergeCommitsIntoIndex(Commit ours, Commit theirs, return result; } + /// + /// Performs a cherry-pick of onto commit. + /// + /// The commit to cherry-pick. + /// The commit to cherry-pick onto. + /// Which commit to consider the parent for the diff when cherry-picking a merge commit. + /// The options for the merging in the cherry-pick operation. + /// The containing the cherry-pick result tree and any conflicts, or null if the merge stopped early due to conflicts. + /// The index must be disposed by the caller. + public virtual TransientIndex CherryPickCommitIntoIndex(Commit cherryPickCommit, Commit cherryPickOnto, int mainline, MergeTreeOptions options) + { + Ensure.ArgumentNotNull(cherryPickCommit, "cherryPickCommit"); + Ensure.ArgumentNotNull(cherryPickOnto, "cherryPickOnto"); + + options = options ?? new MergeTreeOptions(); + + bool earlyStop; + var indexHandle = CherryPickCommit(cherryPickCommit, cherryPickOnto, mainline, options, out earlyStop); + if (earlyStop) + { + if (indexHandle != null) + { + indexHandle.Dispose(); + } + return null; + } + var result = new TransientIndex(indexHandle, repo); + return result; + } + /// /// Perform a three-way merge of two commits, looking up their /// commit ancestor. The returned index will contain the results @@ -921,6 +940,48 @@ private IndexHandle MergeCommits(Commit ours, Commit theirs, MergeTreeOptions op } } + /// + /// Performs a cherry-pick of onto commit. + /// + /// The commit to cherry-pick. + /// The commit to cherry-pick onto. + /// Which commit to consider the parent for the diff when cherry-picking a merge commit. + /// The options for the merging in the cherry-pick operation. + /// True if the cherry-pick stopped early due to conflicts + /// The containing the cherry-pick result tree and any conflicts + private IndexHandle CherryPickCommit(Commit cherryPickCommit, Commit cherryPickOnto, int mainline, MergeTreeOptions options, out bool earlyStop) + { + GitMergeFlag mergeFlags = GitMergeFlag.GIT_MERGE_NORMAL; + if (options.SkipReuc) + { + mergeFlags |= GitMergeFlag.GIT_MERGE_SKIP_REUC; + } + if (options.FindRenames) + { + mergeFlags |= GitMergeFlag.GIT_MERGE_FIND_RENAMES; + } + if (options.FailOnConflict) + { + mergeFlags |= GitMergeFlag.GIT_MERGE_FAIL_ON_CONFLICT; + } + + var mergeOptions = new GitMergeOpts + { + Version = 1, + MergeFileFavorFlags = options.MergeFileFavor, + MergeTreeFlags = mergeFlags, + RenameThreshold = (uint)options.RenameThreshold, + TargetLimit = (uint)options.TargetLimit, + }; + + using (var cherryPickOntoHandle = Proxy.git_object_lookup(repo.Handle, cherryPickOnto.Id, GitObjectType.Commit)) + using (var cherryPickCommitHandle = Proxy.git_object_lookup(repo.Handle, cherryPickCommit.Id, GitObjectType.Commit)) + { + var indexHandle = Proxy.git_cherrypick_commit(repo.Handle, cherryPickCommitHandle, cherryPickOntoHandle, (uint)mainline, mergeOptions, out earlyStop); + return indexHandle; + } + } + /// /// Packs objects in the and write a pack (.pack) and index (.idx) files for them. From 05417129c4d415155c049fff9ae118921d0532e4 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 29 May 2018 23:02:09 +0100 Subject: [PATCH 078/384] Update libgit2 to v0.27.1 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 9b910685e..64653bbdc 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,7 +32,7 @@ - + From 2fa48608e36a71daff8cac3e9486def4fbfd4ac6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 11 Jun 2018 17:20:07 +0100 Subject: [PATCH 079/384] version.json: correct our maint branch names --- version.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.json b/version.json index a70502173..6d9e98151 100644 --- a/version.json +++ b/version.json @@ -2,8 +2,8 @@ "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", "version": "0.26.0-preview.{height}", "publicReleaseRefSpec": [ - "^refs/heads/master$", // we release out of master - "^refs/heads/v\\d+(?:\\.\\d+)?$" // we also release out of vNN branches + "^refs/heads/master$", // we release out of master + "^refs/heads/maint/v\\d+(?:\\.\\d+)?$" // and maint/vNN branches ], "cloudBuild": { "buildNumber": { From b2defd564a63ed3da82ce4d8525bd550d95a3873 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 11 Jun 2018 20:08:12 -0400 Subject: [PATCH 080/384] Update LibGit2Sharp.NativeBinaries to 1.0.226 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 64653bbdc..d993848ca 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -32,7 +32,7 @@ - + From 4222e221ce09eb2f561d59289e7f920c8ba8b754 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 21:07:34 -0400 Subject: [PATCH 081/384] Update Nerdbank.GitVersioning to 2.2.10 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index d993848ca..95f01a55e 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -33,7 +33,7 @@ - + From e66106546de3bca3b79aaae121cb00802f7849d5 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 21:08:42 -0400 Subject: [PATCH 082/384] Update Microsoft.NET.Test.Sdk to 15.8.0 --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 6837e02eb..e38418b2d 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -12,7 +12,7 @@ - + From 95a1338f9790956165050b2f8f215b1dfbb63c7c Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 21:15:10 -0400 Subject: [PATCH 083/384] Update xunit to 2.4.0 --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index e38418b2d..a088b325a 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -14,9 +14,9 @@ - - - + + + From 0da5102610d2ba4ce2835dea152e346c15fb8220 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 21:15:53 -0400 Subject: [PATCH 084/384] Update xunit.skippablefact to 1.3.6 --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index a088b325a..356701ee2 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -17,7 +17,7 @@ - + From ad284bd5ad463cc2dd344733b59b75d79cc26c7f Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 21:17:24 -0400 Subject: [PATCH 085/384] Update Moq to 4.9.0 --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 356701ee2..160e65829 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -13,7 +13,7 @@ - + From 02019068ced78afaf8047e3babb2de4ae5126cda Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 21:31:05 -0400 Subject: [PATCH 086/384] Move to Microsoft.SourceLink.GitHub --- LibGit2Sharp/LibGit2Sharp.csproj | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 95f01a55e..a0bdc0c87 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -9,16 +9,13 @@ libgit2 git https://github.com/libgit2/libgit2sharp/ LibGit2Sharp contributors + true + true $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true ..\libgit2sharp.snk - - - false - - @@ -33,9 +30,8 @@ + - - From 8360c3dfb752f03d1a38c7f73a9f5a9004517450 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 21:33:37 -0400 Subject: [PATCH 087/384] Fix editorconfig --- .editorconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index a9e981c1a..5021a5b28 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,9 +10,9 @@ trim_trailing_whitespace = true insert_final_newline = true ; Not change VS generated files -[*.{sln,csroj}] +[*.{sln,csproj}] trim_trailing_whitespace = false insert_final_newline = false -[*.{props,targets}] +[*.{props,targets,csproj}] indent_size = 2 \ No newline at end of file From a0c6e11febd63506504f372f295af93dcf2fac23 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 22:04:26 -0400 Subject: [PATCH 088/384] Update Nerdbank.GitVersioning to 2.1.84 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index a0bdc0c87..80697f731 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -31,7 +31,7 @@ - + From f4a5261f46e684ea15b4a2651b0e95f31166f75d Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 24 Aug 2018 22:17:56 -0400 Subject: [PATCH 089/384] 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 975828182..58886b706 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: csharp dist: trusty -dotnet: 2.0.0 +dotnet: 2.1.401 mono: none osx_image: xcode8.3 From fdf46b49b99a62efb74b7bebdca7438ca8da3282 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Aug 2018 16:47:52 -0400 Subject: [PATCH 090/384] Update Nerdbank.GitVersioning to 2.2.13 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 80697f731..0d212b812 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -31,7 +31,7 @@ - + From 6969225c4749255fd04363ac6e4ffe7fdfe33ad7 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Aug 2018 19:26:11 -0400 Subject: [PATCH 091/384] Improve GenerateUniqueIdentifierCs --- Targets/CodeGenerator.targets | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Targets/CodeGenerator.targets b/Targets/CodeGenerator.targets index ae73a4725..249cd4f38 100644 --- a/Targets/CodeGenerator.targets +++ b/Targets/CodeGenerator.targets @@ -12,15 +12,17 @@ - + + $([System.Guid]::NewGuid()) + $(GitCommitId) namespace LibGit2Sharp.Core { internal static class UniqueId { - public const string UniqueIdentifier = "$([System.Guid]::NewGuid())"%3b + public const string UniqueIdentifier = "$(UniqueIdentifier)"%3b } } From 777ce1766f918a081d4386dbff800f9ea2df1fb0 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 26 Aug 2018 23:41:38 -0400 Subject: [PATCH 092/384] Update appveyor.yml for xunit runner version --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8cb01abab..ea3e2eef9 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.3.1\tools\net452\$runner""" ` + "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.0\tools\net461\$runner""" ` "-targetargs:""$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net461\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.3.1\tools\net452\$runner" ` + & "$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.0\tools\net461\$runner" ` "$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net461\LibGit2Sharp.Tests.dll" -noshadow } } From 9d1418b7fc8009ee8058a3a433044d4fcd7f5793 Mon Sep 17 00:00:00 2001 From: Mattias Karlsson Date: Wed, 5 Sep 2018 21:23:09 +0200 Subject: [PATCH 093/384] Update Readme Prerequisites .NET/Mono versions Library now targets .NETStandard 2.0 which bumps .NET to 4.6.1+ and Mono to 5.4+ https://docs.microsoft.com/en-us/dotnet/standard/net-standard --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6e215f489..49c1ea019 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ ## Prerequisites - - **Windows:** .NET 4.0+ - - **Linux/Mac OS X:** Mono 3.6+ + - **Windows:** .NET 4.6.1+ + - **Linux/Mac OS X:** Mono 5.4+ ## Online resources From 7c3994427647ed68f91bab10beadc9ccdcd591e5 Mon Sep 17 00:00:00 2001 From: "azure-pipelines[bot]" Date: Thu, 13 Sep 2018 21:35:50 +0000 Subject: [PATCH 094/384] Set up CI with Azure Pipelines --- azure-pipelines.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000..5d703aadf --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,25 @@ +trigger: +- master +- maint/* + +variables: + solution: '**/*.sln' + buildPlatform: 'Any CPU' + buildConfiguration: 'Release' + +jobs: +- job: Windows + pool: + vmImage: 'VS2017-Win2016' + steps: + - script: buildandtest.cmd +- job: Linux + pool: + vmImage: 'Ubuntu 16.04' + steps: + - script: ./buildandtest.sh +- job: macOS + pool: + vmImage: 'macOS 10.13' + steps: + - script: ./buildandtest.sh From 5671a7ac125f4800c3e4ebc8d0543cece868b897 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 14 Sep 2018 11:19:52 +0100 Subject: [PATCH 095/384] build script: update to xunit 2.4.0 We've updated to xunit 2.4.0; update the build script to match. --- buildandtest.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildandtest.cmd b/buildandtest.cmd index d1b114076..93090259b 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.3.1\tools\net452\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net461\LibGit2Sharp.Tests.dll" -noshadow +"%userprofile%\.nuget\packages\xunit.runner.console\2.4.0\tools\net452\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net461\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 0a2d25af2e0fd3e2df08961d55ad57c049521334 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 14 Sep 2018 11:31:34 +0100 Subject: [PATCH 096/384] README: add azurepipelines badge --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 49c1ea019..a3d72d938 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ # 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] [![coveralls][coveralls-badge]][coveralls-project] +[master-azurepipelines-badge]: https://dev.azure.com/libgit2sharp/libgit2sharp/_apis/build/status/libgit2sharp +[master-azurepipelines]: https://dev.azure.com/libgit2sharp/libgit2sharp/_apis/build/status/libgit2sharp?branchName=master [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 From 60884e80bff06e289cb9fe478b155ec1bf8abce1 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 14 Sep 2018 11:43:31 +0100 Subject: [PATCH 097/384] README: correct the azure pipelines badge --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a3d72d938..7b3317aa7 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ [![coverity][coverity-badge]][coverity-project] [![coveralls][coveralls-badge]][coveralls-project] -[master-azurepipelines-badge]: https://dev.azure.com/libgit2sharp/libgit2sharp/_apis/build/status/libgit2sharp -[master-azurepipelines]: https://dev.azure.com/libgit2sharp/libgit2sharp/_apis/build/status/libgit2sharp?branchName=master +[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 From a0c8ec29f1bb27592e0373beb4e572350b4c57d3 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 14 Sep 2018 12:40:58 +0100 Subject: [PATCH 098/384] README: remove coveralls We haven't actually reported anything to coveralls in over 3 years. Remove the badge. --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 7b3317aa7..904f1ecad 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ [![master win][master-win-badge]][master-win] [![master nix][master-nix-badge]][master-nix] [![coverity][coverity-badge]][coverity-project] -[![coveralls][coveralls-badge]][coveralls-project] [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 @@ -16,9 +15,6 @@ [coverity-project]: https://scan.coverity.com/projects/2088 [coverity-badge]: https://scan.coverity.com/projects/2088/badge.svg -[coveralls-project]: https://coveralls.io/r/libgit2/libgit2sharp?branch=master -[coveralls-badge]: https://coveralls.io/repos/libgit2/libgit2sharp/badge.svg?branch=master - **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/ From d6f6322d9f4c4a0b0a3352bb89a07dc1d79e3845 Mon Sep 17 00:00:00 2001 From: Mattias Karlsson Date: Sat, 8 Sep 2018 21:31:56 +0200 Subject: [PATCH 099/384] Added .NET 4.6.1 target * adds Pollyfil for System.Runtime.InteropServices.RuntimeInformation * fixes #1605 --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 - LibGit2Sharp/Core/NativeMethods.cs | 4 + LibGit2Sharp/Core/Platform.cs | 86 +++++++++++++++++++- LibGit2Sharp/LibGit2Sharp.csproj | 4 +- 4 files changed, 91 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 619be5603..68ea2cfd0 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -28,7 +28,6 @@ <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).exe')" /> - <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).exe.config')" /> <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).pdb')" /> diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index b5aa8097e..fd0594384 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -37,7 +37,11 @@ static NativeMethods() // 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. +#if NETFRAMEWORK + if (Platform.OperatingSystem == OperatingSystemType.Windows) +#else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) +#endif { LoadWindowsLibrary(nativeLibraryPath); } diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index e8d536475..52859cbe2 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -13,11 +13,30 @@ internal enum OperatingSystemType internal static class Platform { public static string ProcessorArchitecture => IntPtr.Size == 8 ? "x64" : "x86"; +#if NETFRAMEWORK + private static bool? _isRunningOnMac; + private static bool IsRunningOnMac() => _isRunningOnMac ?? (_isRunningOnMac = TryGetIsRunningOnMac()) ?? false; +#endif public static OperatingSystemType OperatingSystem { get { +#if NETFRAMEWORK + 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; @@ -32,7 +51,7 @@ public static OperatingSystemType OperatingSystem { return OperatingSystemType.MacOSX; } - +#endif throw new PlatformNotSupportedException(); } } @@ -71,5 +90,70 @@ public static bool IsRunningOnNetFramework() /// public static bool IsRunningOnNetCore() => typeof(object).Assembly.GetName().Name != "mscorlib"; + +#if NETFRAMEWORK +#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/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 0d212b812..e46b9df9f 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0;net461 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .Net and Mono. LibGit2Sharp contributors @@ -29,7 +29,7 @@ - + From 8f9f8e706e1ff8b963e145d2a06f7167f72d8c10 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 7 Oct 2018 11:04:36 +0100 Subject: [PATCH 100/384] tests: allow override of resources directory We attempt to determine the test resource directory based on the path of the currently running assembly. If this fails, or if the user is running in a nonstandard environment (perhaps not building out of source) then provide users a mechanism to explicitly specify the path to the resources. --- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index c188efb9c..daa7451ae 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -59,25 +59,32 @@ private static void SetUpTestEnvironment() { IsFileSystemCaseSensitive = IsFileSystemCaseSensitiveInternal(); - string initialAssemblyParentFolder = Directory.GetParent(new Uri(typeof(BaseFixture).GetTypeInfo().Assembly.CodeBase).LocalPath).FullName; + var resourcesPath = Environment.GetEnvironmentVariable("LIBGIT2SHARP_RESOURCES"); - const string sourceRelativePath = @"../../../../LibGit2Sharp.Tests/Resources"; - ResourcesDirectory = new DirectoryInfo(Path.Combine(initialAssemblyParentFolder, sourceRelativePath)); + if (resourcesPath == null) + { + string initialAssemblyParentFolder = Directory.GetParent(new Uri(typeof(BaseFixture).GetTypeInfo().Assembly.CodeBase).LocalPath).FullName; + const string sourceRelativePath = @"../../../../LibGit2Sharp.Tests/Resources"; + + resourcesPath = Path.Combine(initialAssemblyParentFolder, sourceRelativePath); + } + + ResourcesDirectory = new DirectoryInfo(resourcesPath); // Setup standard paths to our test repositories - BareTestRepoPath = Path.Combine(sourceRelativePath, "testrepo.git"); - StandardTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "testrepo_wd"); + BareTestRepoPath = Path.Combine(ResourcesDirectory.FullName, "testrepo.git"); + StandardTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "testrepo_wd"); StandardTestRepoPath = Path.Combine(StandardTestRepoWorkingDirPath, "dot_git"); - ShallowTestRepoPath = Path.Combine(sourceRelativePath, "shallow.git"); - MergedTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "mergedrepo_wd"); - MergeRenamesTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "mergerenames_wd"); - MergeTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "merge_testrepo_wd"); - RevertTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "revert_testrepo_wd"); - SubmoduleTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "submodule_wd"); - SubmoduleTargetTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "submodule_target_wd"); - AssumeUnchangedRepoWorkingDirPath = Path.Combine(sourceRelativePath, "assume_unchanged_wd"); - SubmoduleSmallTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "submodule_small_wd"); - PackBuilderTestRepoPath = Path.Combine(sourceRelativePath, "packbuilder_testrepo_wd"); + ShallowTestRepoPath = Path.Combine(ResourcesDirectory.FullName, "shallow.git"); + MergedTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "mergedrepo_wd"); + MergeRenamesTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "mergerenames_wd"); + MergeTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "merge_testrepo_wd"); + RevertTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "revert_testrepo_wd"); + SubmoduleTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_wd"); + SubmoduleTargetTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_target_wd"); + AssumeUnchangedRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "assume_unchanged_wd"); + SubmoduleSmallTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_small_wd"); + PackBuilderTestRepoPath = Path.Combine(ResourcesDirectory.FullName, "packbuilder_testrepo_wd"); CleanupTestReposOlderThan(TimeSpan.FromMinutes(15)); } From 028e019718f19535b87cdc5690c08fdea8677240 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 7 Oct 2018 12:26:09 +0100 Subject: [PATCH 101/384] Update NativeBinaries to 1.0.235 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index e46b9df9f..d41ed810c 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From c4c15a5e3f61e1bb3f1ee76d1e82e9305a0237c0 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Tue, 23 Oct 2018 20:54:36 +0100 Subject: [PATCH 102/384] Issue-1471 Add worktree support, based on the current level of support in libgit2 --- .gitignore | 2 + .../Resources/worktree/testrepo_wd/1.txt | 1 + .../worktree/testrepo_wd/1/branch_file.txt | 1 + .../Resources/worktree/testrepo_wd/README | 1 + .../worktree/testrepo_wd/branch_file.txt | 1 + .../testrepo_wd/dot_git/COMMIT_EDITMSG | 1 + .../worktree/testrepo_wd/dot_git/HEAD | 1 + .../worktree/testrepo_wd/dot_git/config | 23 ++++ .../worktree/testrepo_wd/dot_git/index | Bin 0 -> 768 bytes .../worktree/testrepo_wd/dot_git/info/exclude | 6 + .../worktree/testrepo_wd/dot_git/logs/HEAD | 3 + .../testrepo_wd/dot_git/logs/refs/heads/logo | 2 + .../dot_git/logs/refs/heads/master | 3 + .../04/c9b35f51fbff2338d5cdc959b23a93a14c5063 | Bin 0 -> 183 bytes .../0a/99448e920a3615f33273047412949d09015ff8 | Bin 0 -> 186 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 0 -> 19 bytes .../15/d2ecc60893449f4fe4593dd51a4706dec212f5 | Bin 0 -> 28 bytes .../16/bdf1dece5c56c92a9187550fafe0270a03a93a | 2 + .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 0 -> 51 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 0 -> 119 bytes .../32/eab9cb1f450b5fe7ab663462b77d7f4b703344 | 1 + .../33/a9574ff4dca3fbf68c6785859b80895c6b77b1 | Bin 0 -> 183 bytes .../37/d22f870ffe688c0d1220fbbf1f06629c64142c | Bin 0 -> 91 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../46/25a3628cb78970c57e23a2fe2574514ba403c7 | Bin 0 -> 51 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 + .../4b/e51d6fc0943aa42b635c762145ca209cf39771 | 2 + .../4c/062a6361ae6959e06292c1fa5e2822d9c96345 | Bin 0 -> 162 bytes .../4e/935b73cf0fe06c513267d517fc2e65fc0d100e | Bin 0 -> 53 bytes .../50/9d02afef0632c7f733ddcd62500b0538d9157f | Bin 0 -> 91 bytes .../56/05472eb48cb4e60b5aa8810cc5ec8138026fad | Bin 0 -> 22 bytes .../56/26abf0f72e58d7a153368ba57db4c673c0e171 | Bin 0 -> 19 bytes .../58/0c2111be43802dab11328176d94c391f1deae9 | 2 + .../58/1f9824ecaf824221bd36edf5430f2739a7c4f5 | Bin 0 -> 146 bytes .../59/2d3c869dbc4127fc57c189cb94f2794fa84e7e | Bin 0 -> 166 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 + .../67/b8324ec2fefc01fd9d31d328116df0474e7acd | Bin 0 -> 52 bytes .../6b/53f5d357f29607605ce2e612d2fda6693ff8d7 | Bin 0 -> 91 bytes .../72/52fe2da2c4dd6d85231a150d0485ec46abaa7a | Bin 0 -> 216 bytes .../74/9a42f6ef33405e5ac16687963aebab8b78abd1 | Bin 0 -> 170 bytes .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 0 -> 119 bytes .../79/09961ae96accd75b6813d32e0fc1d6d52ec941 | Bin 0 -> 50 bytes .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 0 -> 145 bytes .../7f/76480d939dc401415927ea7ef25c676b8ddb8f | Bin 0 -> 60 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 0 -> 82 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 0 -> 126 bytes .../84/9f67c87f926a81af895fc037c04ad85549d73f | Bin 0 -> 270 bytes .../89/657cd6da3ada7bfef880e6dfdb9732f28c272b | 2 + .../92/17230e462ada4319e332e2a4b2d325c2d60550 | Bin 0 -> 31 bytes .../93/5a81d39fd68adb3b7ba3fc60c9663f326435e3 | Bin 0 -> 27 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 + .../a1/7e31b5f9b445610fe3bd9a08f04eee314b5595 | Bin 0 -> 108 bytes .../a4/47ba2ca8fffd46dece72f7db6faf324afb8fcd | Bin 0 -> 157 bytes .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 + .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 0 -> 28 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 0 -> 26 bytes .../ab/38987d12dc243c103a432608648c78fc6651a1 | 2 + .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 + .../b3/e375c923d50c589b11b6da4a769bdd7f6502e3 | Bin 0 -> 30 bytes .../b5/9b86c5f4874aea5255bf14d67a5ce13c80265f | Bin 0 -> 24 bytes .../b7/58c5bc1c8117c2a4c545dae2903e36360501c5 | Bin 0 -> 12482 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 + .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 + .../c7/69ecde1af25ba729b92be431570f32418c3ccd | Bin 0 -> 56 bytes .../ce/40c7a2a2a2d35827ff4de3feb284894ff6e29f | 2 + .../d0/0491fd7e5bb6fa28c517a0bb32b8b506539d4d | Bin 0 -> 17 bytes .../da/6413144c9053a78c3406f440cdc9fcb037fcf9 | Bin 0 -> 108 bytes .../db/9c482bd00c69d8a2d12242cee5f981ea040140 | Bin 0 -> 141 bytes .../e5/d221fc5da11a3169bf503d76497c81be3207b6 | Bin 0 -> 296 bytes .../e6/8bcc7b5d6370fac1ea9929f4b6982a4ebb99a2 | Bin 0 -> 37 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../e7/039e6d0e7dd4d4c1e2e8e5aa5306b2776436ca | 1 + .../e8/953ab38d30b11c45b5ac7229fcef0ab4d603c6 | 1 + .../ec/9e401198937e33a8617be9f235a449728d9f6d | 4 + .../f2/e41136eac73c39554dede1fd7e67b12502d577 | Bin 0 -> 21 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 0 -> 82 bytes .../f7/05abffe7015f2beacf2abe7a36583ebee3487e | 1 + .../f8/d44d712e0680d942a4015058dd84e382879fe2 | Bin 0 -> 131 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 0 -> 24 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 0 -> 82 bytes ...1e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 0 -> 46656 bytes ...e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 0 -> 386089 bytes ...c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 0 -> 1240 bytes ...6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 0 -> 491 bytes ...5f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 0 -> 1240 bytes ...f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 0 -> 498 bytes .../worktree/testrepo_wd/dot_git/packed-refs | 10 ++ .../dot_git/refs/heads/diff-test-cases | 1 + .../dot_git/refs/heads/i-do-numbers | 1 + .../testrepo_wd/dot_git/refs/heads/logo | 1 + .../testrepo_wd/dot_git/refs/heads/master | 1 + .../dot_git/refs/heads/track-local | 1 + .../dot_git/refs/heads/treesame_as_32eab | 1 + .../dot_git/refs/remotes/origin/HEAD | 1 + .../dot_git/worktrees/i-do-numbers/HEAD | 1 + .../dot_git/worktrees/i-do-numbers/ORIG_HEAD | 1 + .../dot_git/worktrees/i-do-numbers/commondir | 1 + .../dot_git/worktrees/i-do-numbers/gitdir | 1 + .../dot_git/worktrees/i-do-numbers/index | Bin 0 -> 225 bytes .../dot_git/worktrees/i-do-numbers/logs/HEAD | 1 + .../testrepo_wd/dot_git/worktrees/logo/HEAD | 1 + .../dot_git/worktrees/logo/ORIG_HEAD | 1 + .../dot_git/worktrees/logo/commondir | 1 + .../testrepo_wd/dot_git/worktrees/logo/gitdir | 1 + .../testrepo_wd/dot_git/worktrees/logo/index | Bin 0 -> 475 bytes .../testrepo_wd/dot_git/worktrees/logo/locked | 1 + .../dot_git/worktrees/logo/logs/HEAD | 1 + .../testrepo_wd/modified_staged_file.txt | 2 + .../testrepo_wd/modified_unstaged_file.txt | 2 + .../Resources/worktree/testrepo_wd/new.txt | 1 + .../worktree/testrepo_wd/new_tracked_file.txt | 1 + .../testrepo_wd/new_untracked_file.txt | 1 + .../worktrees/i-do-numbers/numbers.txt | 17 +++ .../worktrees/i-do-numbers/super-file.txt | 5 + .../worktree/worktrees/logo/1/branch_file.txt | 1 + .../Resources/worktree/worktrees/logo/README | 1 + .../worktree/worktrees/logo/branch_file.txt | 1 + .../Resources/worktree/worktrees/logo/new.txt | 1 + .../worktree/worktrees/logo/square-logo.png | Bin 0 -> 12959 bytes LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 9 ++ LibGit2Sharp.Tests/WorktreeFixture.cs | 89 +++++++++++++++ LibGit2Sharp.sln | 2 +- LibGit2Sharp/Core/Handles/Objects.cs | 23 ++++ LibGit2Sharp/Core/Handles/Objects.tt | 2 + LibGit2Sharp/Core/NativeMethods.cs | 29 +++++ LibGit2Sharp/Core/Opaques.cs | 1 + LibGit2Sharp/Core/Proxy.cs | 86 ++++++++++++++ LibGit2Sharp/LibGit2Sharp.csproj | 9 +- LibGit2Sharp/Repository.cs | 60 +++++++++- LibGit2Sharp/Worktree.cs | 106 ++++++++++++++++++ LibGit2Sharp/WorktreeCollection.cs | 100 +++++++++++++++++ LibGit2Sharp/WorktreeLock.cs | 33 ++++++ 132 files changed, 689 insertions(+), 3 deletions(-) create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/1.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/1/branch_file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/README create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/branch_file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/COMMIT_EDITMSG create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/config create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/index create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/info/exclude create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/refs/heads/logo create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/refs/heads/master create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/04/c9b35f51fbff2338d5cdc959b23a93a14c5063 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/0a/99448e920a3615f33273047412949d09015ff8 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/15/d2ecc60893449f4fe4593dd51a4706dec212f5 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/16/bdf1dece5c56c92a9187550fafe0270a03a93a create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/18/10dff58d8a660512d4832e740f692884338ccd create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/32/eab9cb1f450b5fe7ab663462b77d7f4b703344 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/33/a9574ff4dca3fbf68c6785859b80895c6b77b1 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/37/d22f870ffe688c0d1220fbbf1f06629c64142c create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/46/25a3628cb78970c57e23a2fe2574514ba403c7 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4b/e51d6fc0943aa42b635c762145ca209cf39771 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4c/062a6361ae6959e06292c1fa5e2822d9c96345 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4e/935b73cf0fe06c513267d517fc2e65fc0d100e create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/50/9d02afef0632c7f733ddcd62500b0538d9157f create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/56/05472eb48cb4e60b5aa8810cc5ec8138026fad create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/56/26abf0f72e58d7a153368ba57db4c673c0e171 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/58/0c2111be43802dab11328176d94c391f1deae9 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/58/1f9824ecaf824221bd36edf5430f2739a7c4f5 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/59/2d3c869dbc4127fc57c189cb94f2794fa84e7e create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/67/b8324ec2fefc01fd9d31d328116df0474e7acd create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/6b/53f5d357f29607605ce2e612d2fda6693ff8d7 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/72/52fe2da2c4dd6d85231a150d0485ec46abaa7a create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/74/9a42f6ef33405e5ac16687963aebab8b78abd1 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/79/09961ae96accd75b6813d32e0fc1d6d52ec941 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/7f/76480d939dc401415927ea7ef25c676b8ddb8f create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/84/96071c1b46c854b31185ea97743be6a8774479 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/84/9f67c87f926a81af895fc037c04ad85549d73f create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/89/657cd6da3ada7bfef880e6dfdb9732f28c272b create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/92/17230e462ada4319e332e2a4b2d325c2d60550 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/93/5a81d39fd68adb3b7ba3fc60c9663f326435e3 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a1/7e31b5f9b445610fe3bd9a08f04eee314b5595 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a4/47ba2ca8fffd46dece72f7db6faf324afb8fcd create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ab/38987d12dc243c103a432608648c78fc6651a1 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b3/e375c923d50c589b11b6da4a769bdd7f6502e3 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b5/9b86c5f4874aea5255bf14d67a5ce13c80265f create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b7/58c5bc1c8117c2a4c545dae2903e36360501c5 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/c7/69ecde1af25ba729b92be431570f32418c3ccd create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ce/40c7a2a2a2d35827ff4de3feb284894ff6e29f create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/d0/0491fd7e5bb6fa28c517a0bb32b8b506539d4d create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/da/6413144c9053a78c3406f440cdc9fcb037fcf9 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/db/9c482bd00c69d8a2d12242cee5f981ea040140 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e5/d221fc5da11a3169bf503d76497c81be3207b6 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e6/8bcc7b5d6370fac1ea9929f4b6982a4ebb99a2 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e7/039e6d0e7dd4d4c1e2e8e5aa5306b2776436ca create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e8/953ab38d30b11c45b5ac7229fcef0ab4d603c6 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ec/9e401198937e33a8617be9f235a449728d9f6d create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f2/e41136eac73c39554dede1fd7e67b12502d577 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f7/05abffe7015f2beacf2abe7a36583ebee3487e create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f8/d44d712e0680d942a4015058dd84e382879fe2 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/fd/093bff70906175335656e6ce6ae05783708765 create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/packed-refs create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/diff-test-cases create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/i-do-numbers create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/logo create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/master create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/track-local create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/treesame_as_32eab create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/remotes/origin/HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/ORIG_HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/commondir create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/index create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/logs/HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/ORIG_HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/commondir create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/index create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/locked create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/logs/HEAD create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/modified_staged_file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/modified_unstaged_file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new_tracked_file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new_untracked_file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/numbers.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/super-file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/1/branch_file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/README create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/branch_file.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/new.txt create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/square-logo.png create mode 100644 LibGit2Sharp.Tests/WorktreeFixture.cs create mode 100644 LibGit2Sharp/Worktree.cs create mode 100644 LibGit2Sharp/WorktreeCollection.cs create mode 100644 LibGit2Sharp/WorktreeLock.cs diff --git a/.gitignore b/.gitignore index 9c0b3cdb0..2f75ccc1d 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ _ReSharper*/ *.DotSettings _NCrunch_LibGit2Sharp/ +packages/ +worktree.playlist diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/1.txt b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/1.txt new file mode 100644 index 000000000..5626abf0f --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/1.txt @@ -0,0 +1 @@ +one diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/1/branch_file.txt b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/1/branch_file.txt new file mode 100644 index 000000000..45b983be3 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/1/branch_file.txt @@ -0,0 +1 @@ +hi diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/README b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/README new file mode 100644 index 000000000..a8233120f --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/README @@ -0,0 +1 @@ +hey there diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/branch_file.txt b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/branch_file.txt new file mode 100644 index 000000000..45b983be3 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/branch_file.txt @@ -0,0 +1 @@ +hi diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/COMMIT_EDITMSG b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/COMMIT_EDITMSG new file mode 100644 index 000000000..63ec8fdda --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/COMMIT_EDITMSG @@ -0,0 +1 @@ +Add "1.txt" file beside "1" folder diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/HEAD b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/HEAD new file mode 100644 index 000000000..cb4380516 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/config b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/config new file mode 100644 index 000000000..1599f0b76 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/config @@ -0,0 +1,23 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = c:/GitHub/libgit2sharp/Resources/testrepo.git +[remote "no_url"] + url = + fetch = +refs/heads/*:refs/remotes/no_url/* +[branch "master"] + remote = origin + merge = refs/heads/master +[branch "track-local"] + remote = . + merge = refs/heads/master +[unittests] + longsetting = 15234 + intsetting = 2 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/index b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/index new file mode 100644 index 0000000000000000000000000000000000000000..1f5bd73a76fa0eb3b3aecfe218359244118b555f GIT binary patch literal 768 zcmZ?q402{*U|<4b&M3>g$7*$n5)o4ja}9FNE&+-`K_e2IfhA0B^@s0z5!V+6n{_X( z-Eyq>z{5fYRztm#iW0DTkU1I`<2=CT)UdsPnZm%(_!hxtV0PWvyw7aA4SUC(IeWI} z>~8o|y&;@I&`>|AC^0WNBR(xNClzca*gOyR4Pf(j%A7%%f#NQ%70QMR-_{oNx7fDH zJld|*cjWQCV+?FTu8uCgt{^>N|DBro2W-xX@C7)`!R{`8bXPGj_-^|=8)OEI#$g`Y zrze7Dua4VThWfsJ__r>7qbk$Yat6ti)ST3k)Rg$ryyB9?bRYx8zv}FB_5j_P$FaM~ z28X$#&$`c4$0is2I{0d)=9g_VwET9@T*M%eo1c=ImI*Wu-B^%2Z$sS+rg4}nF-csR z&rR!=v*cr=M@u$cRy}l$HGn}1ZZ4*Sp$37%SAD|g5Rkh$)mHQ1FrR0+XxqX2FP6*X z?9UOJ@8A>W^xtqV1AAU-IWz@<%{lw`3D}(EC=(p!a8HhEygdI}*KO 1303768198 -0700 clone: from c:/GitHub/libgit2sharp/Resources/testrepo.git +4c062a6361ae6959e06292c1fa5e2822d9c96345 592d3c869dbc4127fc57c189cb94f2794fa84e7e Tim Clem 1303835722 -0700 commit: add more test files +592d3c869dbc4127fc57c189cb94f2794fa84e7e 32eab9cb1f450b5fe7ab663462b77d7f4b703344 nulltoken 1320047537 +0100 commit: Add "1.txt" file beside "1" folder diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/refs/heads/logo b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/refs/heads/logo new file mode 100644 index 000000000..e3e3e53ff --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/refs/heads/logo @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 4c062a6361ae6959e06292c1fa5e2822d9c96345 nulltoken 1359021419 +0100 branch: Created from 4c062a6361ae6959e06292c1fa5e2822d9c96345 +4c062a6361ae6959e06292c1fa5e2822d9c96345 a447ba2ca8fffd46dece72f7db6faf324afb8fcd nulltoken 1359021433 +0100 commit: Add logo diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/refs/heads/master b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/refs/heads/master new file mode 100644 index 000000000..23375c60c --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/logs/refs/heads/master @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 4c062a6361ae6959e06292c1fa5e2822d9c96345 Tim Clem 1303768198 -0700 clone: from c:/GitHub/libgit2sharp/Resources/testrepo.git +4c062a6361ae6959e06292c1fa5e2822d9c96345 592d3c869dbc4127fc57c189cb94f2794fa84e7e Tim Clem 1303835722 -0700 commit: add more test files +592d3c869dbc4127fc57c189cb94f2794fa84e7e 32eab9cb1f450b5fe7ab663462b77d7f4b703344 nulltoken 1320047537 +0100 commit: Add "1.txt" file beside "1" folder diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/04/c9b35f51fbff2338d5cdc959b23a93a14c5063 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/04/c9b35f51fbff2338d5cdc959b23a93a14c5063 new file mode 100644 index 0000000000000000000000000000000000000000..a8660a9ea3a02d5a64b2820b7fb58107c74c191e GIT binary patch literal 183 zcmV;o07(CM0V^p=O;s?ouwXDT00IR=hWauO-pO;1Fgix6zpDEblb+psyWh~jz|6!% zA;{Iy#n+W#g|eZ-x3vZREw*hkkG3oI9eI537*s`4QDRMG1rJ&gOk) z+ilo8?#$VMG1rJ&gOk) z+ilo8?#$V-^#BL!muTYQEXFPSoo-i>uE3ugX0Hu@)QUCw| literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/16/bdf1dece5c56c92a9187550fafe0270a03a93a b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/16/bdf1dece5c56c92a9187550fafe0270a03a93a new file mode 100644 index 000000000..6f579f741 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/16/bdf1dece5c56c92a9187550fafe0270a03a93a @@ -0,0 +1,2 @@ +x ̱ +1EQjm\,Dl,'Ä:"큛3^47uو \0yVg(Wϝ XmL?2ʍjK=yPK™I #Y \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 new file mode 100644 index 0000000000000000000000000000000000000000..93a16f146306fea6df405db1e6e065e52994ee5f GIT binary patch literal 51 zcmb7G-5C`FfcPQQ3!H%bn$g%SfOmF@NI2De~WFK%%kl}eMcVO zI|fyeRFs&PoDrXvnUktlQc=R-y0dwo*>)TDjyrSqY|q)<@TYo1I8Fm*0&IVk`D literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/32/eab9cb1f450b5fe7ab663462b77d7f4b703344 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/32/eab9cb1f450b5fe7ab663462b77d7f4b703344 new file mode 100644 index 000000000..9690a6ad0 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/32/eab9cb1f450b5fe7ab663462b77d7f4b703344 @@ -0,0 +1 @@ +x]j!)} ?!dm+qq]3䥠>Z&0M1h}VvY+.a9z4O *LGxxdVðc^Zg(e-<n-Qo߀kBgORE5%6r %bx7GP diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/33/a9574ff4dca3fbf68c6785859b80895c6b77b1 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/33/a9574ff4dca3fbf68c6785859b80895c6b77b1 new file mode 100644 index 0000000000000000000000000000000000000000..95151430cbcad740b6dc6b1ea3c2a016356b56e9 GIT binary patch literal 183 zcmV;o07(CM0V^p=O;s?ouwXDT00IR=hWauO-pO;1Fgix6zpDEblb+psyWh~jz|6!% zA;{Iy#n+W#g|eZ-x3vZREw*hkkG3oI9eI537*s`4QDRMG1rJ&gOk) z+ilo8?#$Vp2e=+u7Tf>; literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 new file mode 100644 index 000000000..8953b6cef --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 @@ -0,0 +1,2 @@ +xQ +0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4b/e51d6fc0943aa42b635c762145ca209cf39771 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4b/e51d6fc0943aa42b635c762145ca209cf39771 new file mode 100644 index 000000000..e1ab3daf0 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4b/e51d6fc0943aa42b635c762145ca209cf39771 @@ -0,0 +1,2 @@ +xK +1D] C tg&`&QVkQFgauxved0Sr.yJ!'C^! @`2,@ ({Oi_eO\VRag):w>R-&BEy \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4c/062a6361ae6959e06292c1fa5e2822d9c96345 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/4c/062a6361ae6959e06292c1fa5e2822d9c96345 new file mode 100644 index 0000000000000000000000000000000000000000..4d86b3208c7b28e95649240cbd52517e13e15f17 GIT binary patch literal 162 zcmV;T0A2rh0hNwj3c@fDgniB_@-CEgH-7~Yud+!tZNV6c5$)~G6?~W(_+W;KwUoU} z0DtO@SsFj*#e?QZc?7^55?W5#XjB;-F65%lMm(wUqszc(ED~dOiwO`k8VoTqk^x6a zkB0I \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/58/1f9824ecaf824221bd36edf5430f2739a7c4f5 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/58/1f9824ecaf824221bd36edf5430f2739a7c4f5 new file mode 100644 index 0000000000000000000000000000000000000000..2ae137844696e737c9c8d5b7073570fbcbd74b2e GIT binary patch literal 146 zcmV;D0B!$x0V^p=O;s>7F<>w;00IR=hWauO-pO;1Fgix6zpDEblb+psyWh~jz|6!% zA;{Iy#n+W#g|eZ-x3vZREw*hkkG3oI9eI537*s`4QDRMG1rJ&gOk) z+ilo8?#$V literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/59/2d3c869dbc4127fc57c189cb94f2794fa84e7e b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/59/2d3c869dbc4127fc57c189cb94f2794fa84e7e new file mode 100644 index 0000000000000000000000000000000000000000..33d011c419acc1873be4ddf19d7979f27c934c2f GIT binary patch literal 166 zcmV;X09pTd0iBLpY6CG00Q2or=mHI1`6(!+kSp{8LY5oDIxZXaqqonVp`SA_FtX+x z1{mVS4ppd;dM;8+C(K+o?v+v(ABy*ImC)S}ANnwe;xlp%d1K9#NKYh`t#eYW zh>e7Dh{^G<-PZwMW5R9M3GX)MvisjvPWt?wJoc-s`2kz-p@vit;msHC-D%H7(|^T| UTZ6d{1=FWNAG +F- \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/67/b8324ec2fefc01fd9d31d328116df0474e7acd b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/67/b8324ec2fefc01fd9d31d328116df0474e7acd new file mode 100644 index 0000000000000000000000000000000000000000..8c4a659949a97fadb4bbd2350a87b1171d5e139e GIT binary patch literal 52 zcmV-40L%Y)0ZYosPf{>3U@+t|;xgtk;WFhi<1*(m*E8a>;Iia0G~hBc0wZHCLlZ7T KQ!W6`bq9`eg%%nB literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/6b/53f5d357f29607605ce2e612d2fda6693ff8d7 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/6b/53f5d357f29607605ce2e612d2fda6693ff8d7 new file mode 100644 index 0000000000000000000000000000000000000000..c0685b971855345b89f783fd44e685308ac5934d GIT binary patch literal 91 zcmV-h0HptT0V^p=O;xZkWH2-^Ff%bx$SciFN-ZkZE2$`9sN|d`^)l-Y%X<6= xuU*wU=?GO;Tw0J?q??wRlL}TTw)f+`b1`8jwI;TQ@~?lO&c(da3ILhkA=M8_D`Efu literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/72/52fe2da2c4dd6d85231a150d0485ec46abaa7a b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/72/52fe2da2c4dd6d85231a150d0485ec46abaa7a new file mode 100644 index 0000000000000000000000000000000000000000..15682ca4d2044305601cbfc5e304d2d1992b9372 GIT binary patch literal 216 zcmV;}04M)=0iBOKZo@DT1yk!3>|6vgmRx>BATV-)9Ad>?S_Dinpyh+vp<7L1ZwLC4)zkLJo+`iM??ED>z&@Y8UeKOoam6_qRKv+ SDl@lvf7Vs{G5r8Xlwo~F`eXF~ literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/74/9a42f6ef33405e5ac16687963aebab8b78abd1 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/74/9a42f6ef33405e5ac16687963aebab8b78abd1 new file mode 100644 index 0000000000000000000000000000000000000000..dbebba8e4cc5b7262abbed5a1815d92e491d05ee GIT binary patch literal 170 zcmV;b09F5Z0iBLPZo@DP1bfyi_<@3!+H7B?~ku4+y1JpzC*z9mN_v^aPs868+1JE Y_Mfi1T5a77G-5C`FfcPQQ3!H%bn$g%5N`dHvVMD1*wTH+ot*d0HmhE8 ziUX=5sVFfoIU_zTGbdHAq@skub!YQFv+XwQ9e3vJ*`Bkz;ZOC3aH!I})N-(rU!EJv Zrz=lf8^K%<@M(E`$>VgnNdSzWFYprfIFkSX literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/79/09961ae96accd75b6813d32e0fc1d6d52ec941 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/79/09961ae96accd75b6813d32e0fc1d6d52ec941 new file mode 100644 index 0000000000000000000000000000000000000000..a1f7d97f355a5b0f50c8d5cda4971342a6b20d97 GIT binary patch literal 50 zcmV-20L}k+0ZYosPf{?pU@+t|<}%?jJ7Sl2^4W-v4`FgG<-NGeLqOU{T-%gjmDE2$`9aNXIw&uqI5d&iwQ Sd$#B7ZunEZAshg_Jrs<)a2eeI literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d new file mode 100644 index 0000000000000000000000000000000000000000..2f9b6b6e3d9250ba09360734aa47973a993b59d1 GIT binary patch literal 82 zcmV-Y0ImOc0V^p=O;s?nWH2-^Ff%bx2y%6F@pWZbp=_w|ZEZn+i*1|CqwPw4M;_lh o233)lTCP`8QNplXwC&*i7t3XG_U8!Ackl^w`fs=w02$OB|A$m1)Bpeg literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/84/96071c1b46c854b31185ea97743be6a8774479 new file mode 100644 index 0000000000000000000000000000000000000000..5df58dda56789631c78aeed62708e1b694440195 GIT binary patch literal 126 zcmV-^0D=E_0iBK82?8+?0R2uC+kmpkZXSY&U

RiSaIAE^xQ@?_ml44FkiJ(R)*{ z(H(TH6>PFd5&0~h#n$X!k{LPpBqYvbW+w8_Xyl{wSm9BID%@u&V}Z+7esG(*wD+lu geg*3yQ9w!oju;WmZug_se_Eq;)3!|J3!n-%%(!(uEdT%j literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/84/9f67c87f926a81af895fc037c04ad85549d73f b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/84/9f67c87f926a81af895fc037c04ad85549d73f new file mode 100644 index 0000000000000000000000000000000000000000..eb5f7b2309545f787e2d657ef31f51615470cf77 GIT binary patch literal 270 zcmV+p0rCEL0V^p=O;s>9HDE9?00IR=hWauO-pO;1Fgix6zpDEblb+psyWh~jz|6!% zA;{Iy#n+W#g|eZ-x3vZREw*hkkG3oI9eI537*s`4QDRMG1rJ&gOk) z+ilo8?#$V9XpfYpelKU3sbHU{5a>Z991X#d4XP U{W(JO9el!^{u}NE0M@>Z`N9~A82|tP literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/89/657cd6da3ada7bfef880e6dfdb9732f28c272b b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/89/657cd6da3ada7bfef880e6dfdb9732f28c272b new file mode 100644 index 000000000..89e7566cd --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/89/657cd6da3ada7bfef880e6dfdb9732f28c272b @@ -0,0 +1,2 @@ +xA + E/cJ=8TA#]M ϭjDnswn8ZiZrDF literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a4/47ba2ca8fffd46dece72f7db6faf324afb8fcd b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a4/47ba2ca8fffd46dece72f7db6faf324afb8fcd new file mode 100644 index 0000000000000000000000000000000000000000..188e38554633b6d481c0dc94a881d5861b2642db GIT binary patch literal 157 zcmV;O0Al}m0iBLp3c@fDMg7hy@-LLhQvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S + U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd new file mode 100644 index 0000000000000000000000000000000000000000..d0d7e736e536a41bcb885005f8bf258c61cad682 GIT binary patch literal 28 kcmbBQQQ6W+Sv9;eTEK4oHX{LN+y0Ic;3tpET3 literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 new file mode 100644 index 0000000000000000000000000000000000000000..18a7f61c29ea8c5c9a48e3b30bead7f058d06293 GIT binary patch literal 26 icmbI-Ws@Ԡ\"KZ Gw: \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 new file mode 100644 index 000000000..f460f2547 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 @@ -0,0 +1,2 @@ +xA +0a9I p'1Ѷv\x{cVpvWgǎ0x[ ]"g#{rD Cot N U $?9-p+1^Qx9O\C m'D {mV(+l, \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b3/e375c923d50c589b11b6da4a769bdd7f6502e3 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/b3/e375c923d50c589b11b6da4a769bdd7f6502e3 new file mode 100644 index 0000000000000000000000000000000000000000..511e72c6a190ad5f92d0c991b1367bcd3ee34964 GIT binary patch literal 30 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 Mq|8G97vb3}#0$W;Z(a1ZUm8cn7wk6L Ov6U@&t}g(8*b+iU=oWea literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ce/40c7a2a2a2d35827ff4de3feb284894ff6e29f b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ce/40c7a2a2a2d35827ff4de3feb284894ff6e29f new file mode 100644 index 000000000..5f74e8a94 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ce/40c7a2a2a2d35827ff4de3feb284894ff6e29f @@ -0,0 +1,2 @@ +xA + E/G!n{q2Ft{k):M^xL ݚ̛W6~ ZPr4-3Qku?z'9;I \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/d0/0491fd7e5bb6fa28c517a0bb32b8b506539d4d b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/d0/0491fd7e5bb6fa28c517a0bb32b8b506539d4d new file mode 100644 index 0000000000000000000000000000000000000000..8dab6a9eaf1fff6a519dfb7bec1a5bdb56ff845d GIT binary patch literal 17 YcmbC^@q10gQFy%8_q>cfNgzLcC( z0}S!hswzmBqROhsoAV0?7nkT39SMD~8@Ul@A(7SatL>%2yHwuc@|`^FT(chOd3$6| v#~>wN0bLC9gw9$xTeQ}6+8>+#;}UuD-bU(fFBo%wrk41CU&MR>Ie9xvQr1LU literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e5/d221fc5da11a3169bf503d76497c81be3207b6 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e5/d221fc5da11a3169bf503d76497c81be3207b6 new file mode 100644 index 0000000000000000000000000000000000000000..2020d89af3589ad3e0db4de2673e40cc79c08e4d GIT binary patch literal 296 zcmV+@0oVR`0V^p=O;s?qFlI0`FfcPQQ83gisVHFxQ(OJvyI#cgg~4XsOKZ0rD?aeB z(8K@;6bu>a%RG1|&ppEE7^(iM?o&*9cJJ+esOBJ7M;BjLh84<&3g6Zi^tafy$voPw z)OY0Zy<<=nNkxfy$r)c5Vfzjf&w zRhh1qLp9~*r(~vOVzEf{(wk!(lU?TfKZ&%xD&@|0?~u?}bUm0hO%hk;bJM!zEcw{z u(UMJU)KHoIc~J8}@{Wq2nH>DgY{l4~_r; literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 new file mode 100644 index 0000000000000000000000000000000000000000..711223894375fe1186ac5bfffdc48fb1fa1e65cc GIT binary patch literal 15 Wcmb e^7t:wo܂ p@.=..nD"JHqDV1tUeޕi n afu9FkcOe׿*qk9rL^"!ay%_2fw3G_K \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e8/953ab38d30b11c45b5ac7229fcef0ab4d603c6 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e8/953ab38d30b11c45b5ac7229fcef0ab4d603c6 new file mode 100644 index 000000000..16eca526d --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/e8/953ab38d30b11c45b5ac7229fcef0ab4d603c6 @@ -0,0 +1 @@ +x A@0P[!N#ϋz]ld uE/DnDT$hXϼzp0(=bhj73|e~#[ \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ec/9e401198937e33a8617be9f235a449728d9f6d b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ec/9e401198937e33a8617be9f235a449728d9f6d new file mode 100644 index 000000000..9ba063ec3 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/ec/9e401198937e33a8617be9f235a449728d9f6d @@ -0,0 +1,4 @@ +xA +0E]$ fL#1 +>ǃ?ScU`=J'DdQ)xFDGު'WD¨0x2L-Z#qbm-> +n呶ے9=+hG7B3jDuaZuO-[WcT_FHn \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f2/e41136eac73c39554dede1fd7e67b12502d577 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f2/e41136eac73c39554dede1fd7e67b12502d577 new file mode 100644 index 0000000000000000000000000000000000000000..1cccf654304bf6be13d240161e95b7831434126b GIT binary patch literal 21 ccmbG!`!N%PTo8)}08ZovBme*a literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 new file mode 100644 index 0000000000000000000000000000000000000000..03770969aa16f40d4192c733408f152fc17b1f19 GIT binary patch literal 82 zcmV-Y0ImOc0V^p=O;s?nWH2-^Ff%bx2y%6F@pWYoZvB+9etT5d(tXFBocGN(t6p-7 o1F9k~wOp^HqJ-g>=Z5m>$`jW{Fc$=TS{`5WI9+ZM01*fsda7_Ea{vGU literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f7/05abffe7015f2beacf2abe7a36583ebee3487e b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f7/05abffe7015f2beacf2abe7a36583ebee3487e new file mode 100644 index 000000000..7490425a2 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f7/05abffe7015f2beacf2abe7a36583ebee3487e @@ -0,0 +1 @@ +x B!D=S h؅Bb;XGc|/Kdz-FѲDXy) Y1X4z.rdv4Mbst+ҌS/zkuk}I\qVOlm QΣCPp1J \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f8/d44d712e0680d942a4015058dd84e382879fe2 b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/f8/d44d712e0680d942a4015058dd84e382879fe2 new file mode 100644 index 0000000000000000000000000000000000000000..639e890949ca448d9943b6eb287ca2a89017b948 GIT binary patch literal 131 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 rcaKYLMm*}NJR{E;Zd?;1?Rz=-Xf;gsm+2PX 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

=uHz#4%J0P!RYVlzYKcqTl#P^Wo1(_e1-EG? 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

&SG& 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�eTY#b?LX)(ib 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

oIQ4YOXU$0Mi5i`Sf+bbJ=L9 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ǧ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 z zM-FyiMRZT%Sr9#-bU~1l&1TSvAKJ}&pPtc*J@lNuS=2lXy1o^E)HIg#kCsux3cKzL zyTB~Aiko% zDrT$xH9&i)HF*97>lpNWX)Sy)Pg&#&vM}-IA@P_d-~(p?l+ysu6Hp<3olXbn>Krle z5uvG@F6ax}`4u2g5r2?>Pl(C=DvAQA@AUT-g0XmI;~kp~F2 zyNb5~y14M6VSsI17j$&aufR(yA7L77d&xEA-mWFOl*87NEEAG;itj|?SFwj`mh$`G zUPsOs;-;6m7xY36-`i&Js9?Q9fz#s;RsZ(!Kj)Kqr&GPAn=jhfk}ex#OqQD>dj_3% z?j-f)M+MVWLG&wAUDGxnNpJI<5_** z-m1_4u<~QKur!ugEs$txW05$p7OlZoE_I9cXmxe9wK&4T(}w@8gf*+(&j1%E*V4TI z0Mx%r1kZ|5mPnz}NE9(i6RNV5CP7xvLduY2MHJ8oM`5wrpzRuAwB9-{D`Y}al@>`B zCjuuaI8ibUGE4|AL>kjnsVHWS3r3Ez5Qm)5m~&ikEP0}ef{3C}oQMQ-#<>hJjT{$_ zoS;dHu}H!=W+7LYiYN&LrZQr29MCum6w5L$9Y;nkrCE$Y8E_hlG@_gYK^lQJNhske zW+{BoBy$`cxrj#`hY^DuITcwz;7v%%XqXYoNE#DfkeE`(MIHBTw_Lus`SaCn{`Th0 zTkq3JwO?|nEYqdQyJ_*43)c{%zp5Pi;yNOlQ*EImowX^vOP_qSy%;Zz^dZjTR2zL) zD~U9)deI9>EWX5;{k~c?HdygdFpkc0jf6(^u zzH`+cb5@p(@Fe$l7e5@f(w>yp3m@#!?Yq~n`xJ|&MV}*rjSi8A!H2;}(O8RK z9vC!i<)b~!%8xa>hpGw=6tG70*z>#Y{|W;CpM!BbzZHH$|6T@%)*DCh@n7|0e=-IC zDR*5xL;GJr)5cu8B)%=r*8rT|qE&7*{n>4ii?V^4?a%bh?H~Q!wfqjx4=;7&3WX4O zocqIjhj+qSk)qV%{L-T2)MEYO#N2|MRNefPq=~!K8966DHDTnOEXxQYL&0P(m^=z5 z|1xe=;Y`mgi3ciI&`L?N<^uDIQp*bR^K%rmK%_Mn7w6>LOd3+0U@=<-po*e`_{5x? z{A7)kBu${6&C1M+nMF7u5@|)LsTv@qAeqSz*kk}?nKZGvSa_VBRNIczFc5vuR}5Q$ z>}_eoN<5{h1lkI%v=qb!i3g-8P29#Ju}k8>c31s(#&&bvATEB0Q+v*wGiRoma1m!! z!r(%&QiU1c&eIEL(mzdEc3?%>zlmj@bJaUr?zvjX1XHXAhjsAEao(=q-E6{OeHW07 zV{*lFR>}fjkcv7E;6g}fA)$@|{qTl2LSptyVb8fxz-Mrd(m6u~hl2g!vMLRS=Qxvu z?YLl|$-}!3pMv!@q43o}da>Zc%_a!nzxm?X+np?c2t3wG<|&I34+K2(Ve|R+R=@fn zUakbYSJVO??WR{=VU=6dQ&fy#l$BramT&3z1yHZW50#ClI0H`Bz?|hJQ{;t~I|KLL zok7VTnB0+pwUk=N$|4d8A(bfkUa&;_Np)JH3)Dfa4GJ~59w=DC74Fk1cFmOBD2}DT zrsa|$F$Esl2(S*qy^hj{AHyN5J!_O^0NB$xEUbg+jjs1we4MeUs5xJq1J8VDbx<5ZN#n7ZX!yxh3g`$V5qb*jdlhB#w&fkm zuUxld_Tz|xe>C}t!QHX=Yd=q;AC7S!M?Czae`C(E{Gg7;zyIcT)|+edEp&bX6bz=) z?-YX>c%19xzRx*fk_2aZW=VWG)Q2-IvT$~d(i12V`=9MU9>L`Hu*YssM zISYzX%QEvzi{nc&b5j*;6+Hby;(Z+>tYf%1C#y4Rvnf;qS)7xT87-KA)M7?WR?b>3 zpxkvvT}IBy985|;QjbZ3RiPTBER;!`g_BcXYjPKpG@F8!K1ggGlRO((mUFTviyz(i4XP<3UPJO(6k1LA7@r%2P*-Z`juIo6>REc zMHWe@l|VBkIXRPc?Vw(U`oq8)Y%0(OsDpv#3t|{QnVl8r5}?WYtm06Uf$D%>Dqxia z03eA?O1zT+c$|$@Yfs}w6#brGF@=h?vxba4oZe7$pgp3l}k`oy-K#a|cu%_!9~ZcE0l)CcS#oU^2!j+EfHkXIZ!wZ^4#_b#MfbmUyL^gBPR^L9{DRg{%&01jX$P6V&lx@w&h9SZ)0h$87EQ%bz-9=W7RuH|UTh9N|m)850s9By1 zMM?Of3Ro{x7EEOpGS@1!6Xe1!JHP`Ag-lMW!scow532~eg{5hQj0L9+4x-yQb_q)e z<%r8UD9IGCsL2MiT$lvq--u7DT!#P5B7h&egqHmh(=w*>$A)A=GS#Z%Ij$c`;GE`R z)K`Q+drHDsiSZjn5|eF(*M?-~i1sBkIFNtBwLVlIWD0T;C6nw*Qd|q-+6Tpy;E_m@8vBd{G%T6C#3tNJ0h5~9|+U%P0&EB03(*mEa8KGX%>pc zfy7wI(qB37o(Xq|=1Pg0W4jDhPC`n|Of|rlv#qWr^C2=V8Ghr$W}(Y!QWggEG zr!%T}8Bq52N1nZk1}}cgPG+qQ=mIXh*r~2Ip73na?$6V&Ev`chRAp4RA(FW!WgoKN zIP{#fVl?TJ*3QxDPu%>x^~*W=)TgYH>34WQF4k(PLexx5bya~ppY`lk1p~Qr0bXO! z0#QLQpvkTS`Ob$QwN0DLE!g17l}2M-aeevhFz&X(sH&MxCZj>;AWxTbLZ7;_dTod6 zd3k2q(dX+uOjNF7hmU0*TJGoWn-zhWfj9`t;ycMnOSuhm|8y%}c}u&g*#X%<8eX^? zhPlp^cBi(w))lsbg6D9tJAZ_@sjJK~?-)1WH6l#s2A~UEtoy|7@2?gx8gZKE@Cd&Q z{ds+Chu6uRGyf>1YihR7N+ZR!+R!T&&R`n}esnWxQ!rs-`U%`n^5SlJ7<)S!DQl>} znetynYJYNf^Kf%{ns{2WV`$vLB-h$O zaI+_&WLFfOFkq4p(fRHAtliz`t($zvwL$JK?cA?>_WyE2Q&8G5 z`7<(2M@s#3QFn7&9aTo|?PuAKmX43|@kWKdtOx%I{3sz!DXVU2)Q0A*q_uf)0-0Qr87RVy+2%HD@9i4RPecBW=q-Dm*01{ER_;Vvg+Tfod^* z-9N5_aN|MHfv0>Aatq@zcTqE66AbVt>%ZOr^B6+MUU&q=c|IY_(90?;0eF!v(V-Oa z0GW-(9W4zY^LUkP;IzPk8CC-{a#Q;rMSr| zyVnmA5`QEr@LjMWRTDJZ_{l63knysTnp;DJ6@vGy5)>r5(p&|l_W4Xp)I6XG8se5a z_$jr5K29{lg}PDkK)$5fO7DvdXZUHw5Ag=1PBximtr48WH&G#!L-ep;(3b2xLT+8% z8Lx%Cxgb7fY+ zIJe^f9hQE3$o>FYkl9+yEsF2E%XwAYrOBzs7()Ux$6$#WTB?9x9Ec)Cu+QisTd$E0 zls^FBDjpapxSbp3_r^TtOs~yV@R=!3Ch0s<3baOREoRsquP`kHXG z`Z_eU_NbxVZ>PvdShVSK%jA`3RZWP_SHUdl6g(`1EsPvf+rsP9NaKna6FQ}-M>8+S zKex(L>j~d&ls#{v+C0wI8h)x$gB0-8_f~LyZo3=h_IvrVv`_RSfbGmVc zMDjt!|DO!5-W#$AW^-kx?qKK&Xk1mRzOQ@CWp~c`8+n+8#0~AXIRWQ;ciaF?heivUG+bb@m_?&Sz7z z?Z+oQGLLkja>k1Z5EHEW_jJh3m`jh~LwbkNzDW?zaKe9gU&b0>bcpXz)G zyB&R$MveFsl*s*~TBF;T^@h1TaoWEw2%8`{g_vKTWErj#o_tOLG5h>^-3ChU)1!;% zul+FbqIuyWwFX6z{_u3x&cO z38Md5u04`1KVK3+utA8GpK%y^yu?k-!)tAveC51Vr0?tR>z9@Cz|!6?$W?T+Ypbwt zu>JBEyxun*iPJ>qw){q?X90C?MS23-d@JT7F8mPc_xA_lT|r(VO60_7@-;4+`^WWC zqo^C9Nm|3~Is#Q2W7gmZ{4a>!WvmP(+#an^l`!^Rx#2J}IbcX@9;}^ZATzV1@u9RX zjQNrNj@6REPz9cnk`MjKMU^meK!P=$y|C=+6ZcE#rU6d&Uf@oL9TdDq0wb#&%dT(k z!_nu5FF%{551}IC62@5%6onnj%{11=^+tHojK^XHLzGEC}EOCMJ$yFLFn@Ql{i@yoz<1Vgd`z?T&KP)sk2UQZt&>fBBM#F^IdMp$9|gC! z1@tFB9tM`NPt=@#WE1`Pj%LuB?H=308WN~~`rX(wo4}Dx{$WX3ebNikt`C74zq)Zq zlD6Q8$7IQ>eQZQDUY|uHtc&MnEjl998;%AsyQ<tPeF=2utW?wI78U-*8!&AOGPmBjP>~@hi;H6Rv1_=_li@arf@V-L$T-v6#iGs?Gs;z-sZcP8!o__a26;%%z z@TFeZ;+y+St6_mB>xx?N%r5@dZ6{14T_&BSFNymJKU5Pk zjvBULx3UWOb-mO_Z($E8->UP;Js(2LzUX}$ya6X1l_O1UG|k%Q@JUVd=#2Ut-%>Nr z?ah%nmHg5FP~z~Oj4iuP7;mM&7q!%A&DUbxrrx@00UpOW+z`e@^@vaCeTw6n$1@k9 z0x16c4V70lvRhfZd@_Kv5C!&=)#ql_FGd>b44)Zacb`tioRKa$2M>6aW9Yg^l#6X; zHdL;28k6I%=pwmEx@OseFD7@RBMCK4R^WF`NQ4B}ivJ9W#gdnvLye$ZB#Cc0)Gy&_ zHqK+T4&=31(iuFl;Uf0!Do-j~88?~>(FS-rY1P5JYhW%XQB@pLP6yKPg~G5c3H5$2 zo`3{0w$S6NzM;NJo_gHX#zx+6bKWPmPs#ouNw?}^qan^D7g*P786tP|^<{M+$k8d8 z`lN$I@vyIR_LNBsJw^*QQdU(i6}{uc6>gm>b4FYQIVC%BSB)T_%1BKKjI#_qL4WZS z`A+-bxpQa!IP&$8yAPA-OQ4oe;rWbBd0?phQUqFqK~T+0(nn;l$drv$4!1zQNIkkc zYKSmqO|-!&3b(vI!2#Gecke8{vAQHPQD!L>TbBSE71#6Obc{4Gd03dSF7#nqoStN!QNuz9BM|k(9dxHLvMh|d$Uo(NJ5rV#=9H+W6qAsbSuftJ z^bdU}*|BRijU#kpkv5L}=^Gj^jEne5@oOJv1 z-69IHc<&E~Z#FO4f{5qpGXsMk9f_1`Ip3q+hF7G&8z($&=L)!;$OGdr0$J0zg`yu?GRnj|mDx!U?jIu+$* zS_PkfQOZ=RS&X}7B(MjMnifh|c>kuTOz`%2D%0x3xd-fJmpL>@n}YCE%MDp_$P>$U zJ6!Y#H58r0s$ZKCyKRUCA>TY)R;)ZN0s*|QNuRB{kBL{iS`C8EGjMuX%Xye`#RMGa zmkIi4*3G1p9;y1D+qx(jr%cv>D}ly*_P0rfQNfPEMLE9n$HBmmtfo9)l*j6>;%} zv1HIWS{L?=hd>*y12S|BpRLN#BQ2xeZ4A~&%#6b9al$+qcn>ulOh&$*=NFA}gB@O? zD#bXmsX%80(EWT?s{tXp3gGC)4ADu!q%a!8Zeb_ZSqR4+nGOuGN!fjMuIb%h6*S@D zju@S*Dp6YEukP`1YwXZtKv8SRqv!V5U{@}Ri`a@Tr@7- zHk(MKMJ8js*BEhI2!ShuyOQ(qb~7H{=Z(A)eCEz_fAZGU{F;-h3{HR<5#79y-w1Ut zwuUoscIG9I=XX0T7>Ggq2jg=lS*r0?8rW1eTJvTL7H@< zWH(6xt3AtwAZl65K>QB2vV(#2#Srr7&gSkxiPPKG{jC!}MkS zdc9&;<2(COwQceC1sO8SJln{T1!w7r=kiqT_c1*yAQV0S~9?vKInmY10U_-c=z!l+G zb~3L#bIGJ>xRP*OsS2w9U`ymeO8EsGQY!*{bbJR!a4ezIdxnx8{oM0o_Co}C9 zKUK8Z{NPj((cBFh!Em^DG{=BTDXMt)ijbNSGqYlSb@XqJ5Az~yUfNPQ(TNF<$#=3H zKvv9=yFF859NpH9SCBBIJcX{$Hq$xhjN%+ftsdE&Pk*eZ`SqIQWL|Z0yD3uB37`wO z))pv|lye%_s`6ZsToM?n8UEN+f0mu-XrFoD8uIQJT3ljRI=!32(A#3^z6-~}2z)0N zOIr7vMV~RJgIjhCERp3*h$GIyS%{mj#P9kPa2HD+=&*XeJBa=0vg4LYNeOxPC$%L= z1MDjP@or=L%aSIGwZG^msIBY|S$CoU)fx69TGf)Hn=s2ia(Js$yVs7;nS8G>HAB%} zrzGJvpmzqwW^MOi)C$bM{H?B~V!5bp6eo_ArD3F~if!aSuLkC7n(Uty6-jFvX_Q1( zP-*zvA~j?n3&|OUKJ!xd@Mw@TN?=ral2kC0pO^=5ajGcR;+08Az&De!F_V6n=dX|gITB_K($^@tsiAE>dx|&SC*H%v~P=Z=FCfwBl>(aA@q{OP+jaUNiPX zuo7@_O~)H?&$+RCef?GSA~zj~D&1j=uf(66+6L!B3)>uultc6EA?&JknE*7VVT4^r z|2P_23Qh#vs9i5wi1FXaX%e#o2roGz$mGVsqs&hWVwJ#~CXyp6M;XVOs<7XF`VTD0 z((_BAV~WfLqh)5{O?N(6S}r(dDF<8H9nol{Q@pRp%1jr&8)|=%(Nj}q;Lu5@IjPdc zCbrB8QCuIMAEuz&az)L;;!8+*)lE$GJQyw9i|eyigeWV*!ZW~`kRReuuUk~)I#bjw zi7sAIhy|tJ+3zm1pC0fN&}_QholY_oX38*yArM>%o|Mv z1=mK>ysm3Y(R)yft%Xi6N`5JHg&kEgmkmTFu3I}4X553-_>_Mvn1z2_t4l}Z>gitd znt_WH=G#o zmY#wdDzgwuUGgp-XbmnnSAs3152b%sVB*Aj{ZP`iw(rl8*`Lrb@1jYOxGinhWK*@X z91D;1iE6~k@nU@%Alc-=|~>5VJ(`f;@)#?Sl|D9=cetK%-1>yjV+v!j=6)|y~N z(iEl2gU3)8^iURq^d@eNfv`*p+xhb-%(fR4CBmb*jL9n~aqru|%Os9hI_vxM9i9P& z%y@%9ykJP9hMz&FJ&~!I?%@;+QPiFga%Bm33!%}Enq|1OPL+jMG||t$4aRhG`^Vh~ z)fkj{DU|TmpT(bKYH&sA+PvT5nIA8)VsN%(YS=sSs+0Ryo<)lURM5!{aCP+}Wqt$J z^^$iEZ3XbR4U>LeZ?zVn(VC>tO=OO_rEJ=IOpGl}9m;viMIX}Hr&V%}e061-T^l@L z;LVE~ZZI9Hl5ZRP9(@6kUL9d})?Zmh2%+secpeN&A4+Zai2USZN4{yrh5d;X{k5Q1 zF+rv&Wq=qyR`a?4+#vl0Gh?tlZMwrieqs3?n<#uw#A#aB_v-HRln-!@HZ4#`b%r-v zlPnLK&dHR+_Jr0DK@N$j7%vIE-v7(&7$i%I-L14M=Vq;Ze?4<$GHg6S$@vaR7tE<3 zeUAn*<%Ma(;4&osL{+$T5<*C_Te89&wW>YO*TqP3TKncBPMwsAds*sESqoK1CC|jy z<%3ld7PISi%<4{fqHcX}9W$(n!vw1NLWUbaw?9loZOcyOZVG4NFw(rD@y^>EsJ=cMLd)1-MVIV zCAOkJAbv#~k|ZY*GR~w4eh6|dQL9KZ4+=0T5wn z@VFL<^aqvC1okKnu%Hg(P&qNkBbIo|REQ4g4}v2~N5rhj9>|#`ttMY#!i#>v$;o3L z>~Qwn;(F`Y9ecif*?RiC^Ydum@3-4BPh%{OwjzkzbDnMocPm59F}%(-A|Za-hFVUh zqqhs1g|jLmG{VV_@!?N!EQN~nie}}`B}41uQ?o+8dqiR%kvLa+>xG!%!O6UV#&yXJ&T!wX+K47is&DpFO53EN^C^Z3!k8> z)*NKQT33z2FWHOJf{!!ys+|4@Xp`*DuFHvFo@@?;M7UdnKY?d0@*PQm_VVQkz$_2rP-!SqI&PDU3CM zrzxQJ&%ui+j46KQ-Q`YNWrk#kg7x!jjwlM0hYDOe`}vV;H}gHr=EF4#XBqEBb2{i+ z4ApdS+UG%imk$^sEGZ9?vpKWXDmieZTn}YJm!mgqEN@h`Krg8~Uro3YZd-VN$YgZ_ z({<=6Oi#74%=vQZyoQ(uw;-=A9eOCNG{CE!-A>8g2|;flI*Ey!1A7sjmWn(;$dasY z3(=-1-cE+vm`t|^tv}r70@Rx=3v45p+Kr`mObZEjWs*P?LvyqE0*T;QISXG+-fxTz z4_}L?WZZqT=6`Nge+Ki6|D7eAmQg-0D+oM=;+y<#qY`axdu@oFNU6~uP&_oAt zF|=HaX^75Z#n$0XC;>fWHfx+oF!6xFH>`@KR{A;9{&tkdntC>1A!_@33dpee;MSk! zdZR?EBf33WPMN$f?O{~)`2#J!d~yjq)iZI)%3Y^4Gh@7It!hBdcc@&VWWs|Y1vJm;w%@~i-ogkK@SvX)xA`t zif6?v*<+PTpvtK<{d3`V9GQ#{wg2Ztqb|V+=CYVu>Eh~b;K0~DoDoG;R|!&%Tsp?b zSALs64$aTL09b|t3X~%ZGx0Pk)UIW2;xatpUgwK?TMn(b@O(M{@wQh^)Mr0mWWpT0 z>y>Y+Lq+)B%!JmS?EjfVhE=GJ_14dx-5Vd--Xr`u;AZU)Y42Ay&s_)6BECoFQlgE# zvd4-G$R=E+kYFA&=#1?O?diBn@$KbURVs~xj%!FEesv_gD4BifdJ%wVP+;EHTDzj% zND-@kmDmF+0wa22|NKVoFXfc^&?QNl+D0UN8pe32)UZ)hZmMrS7}HFjbwH(NU!kn- z!^@>akhlUb1UMFLm*#PDxq+Q~Yc6xWtiinx#}1LZFoH$Abf9?0r)q4(mao;|CFPNr z{dCq46v%snq`c!LdtCNxW?>|i!3uuXBG*jkx> zaN6k`&)S^sh!g8p#)bDN?>0^aC;N|jH1SG0EQ5}eSr5|Xt+2T|wX443xlhd#>lZCx zJd=Hk1nz{hgXwS;668ER0woCo5i5viHo!fSz*(2lrPjd<+n?p%;$PGk6x5rb{Ni&= z$fXb~i5uw~Uj_83$G&a9DhkYv@NK#UEOZb==M;C1ao9gPVF#%EdVo_ptGJZ6rlP5_mF(qRoMeMTJxQT`|SX|Hq(?exkOjZsowxSh~KhdQyfKx>2I8 z{tvrUh((gz)S7`Nom5639sqZVaJ_2|WWuI2^_=!4F$0i$_Awjj#0_1`o>et9WU%W~ z(7*M%W0fUxuA1Rm2$)Spi&-~)be%*yFv+YZx9gTMe;qk__TS+hShGP;{G^M3kRDHX zy5WqhY2`S8NYbmB8qWe1R?^Q$o>C;n4kKS=wJuz(mf%1Oo0Cj;1ihINd_dKb$Nu5W zuG5R8waEgv;7Th2-a@uFegnv9trMkhMWlglP>v5WxW!D-`zcuLbL=6=vYZye>wZ=M z@e~5DodM4WUeYBOv=&;_iXHN-i-Z{>uYI<>uB{zOeZ9eyjM?U_J^q=rC|*?1CrPL!dNHN;ZEwW#=`6fOGAIOXu;-zeqyCtihLPXc$P8jiDB-ZYbk(j5? zBHT#v=W9xX%$N=3GjYm1%&BC^KqjtoNbpx|RisLq!<5~M@}U(dr7R-hu*O@f6dd%Y z0WUrI*ex~08t8;aSAu(5-`$rDPAMmDyJ}&ZlR5DSI64&ZEjHrcRyj$rjCIe33ZQ!M z55`4EQ+5WZu9FFb+@iADJ`DA$&|gz958QD5+l|CovIKfh_UyT`#8HBYnqMQe@*%ls zSlGs=S&o`lQNHZNSgz#GT6kk^hs{Bd;vTSML?651?#vj&F6=SD*Wk1a;K}1OoW1#l ztj_Q{nM;doTlSG>+NpmTC&HNLLJt&X)vZ)4uC=659KeVrQxMc1x(8XYpnqF2l?f+6 zbM@4KkH3&VEH$^bYZ{s$n0+)U=eec)yA3hK;}f_M+n^+mpE!vyxDi#m1CM~B zD)NnvPgzEW`dK|ak7uuBUx)mpr*fKfiSp5PiV4?Cg9%6cwzhNqwc)&$vp#%`U;EnC zt@-%*5>21Zqtllr*n4cE;lrcHLsyTQF{v^tzC2ii7oyLx; z=7LHyG^jMDDg456YtlSu-H0(Os&IDMylCRnkE*G-|%%J=Ti zanXfGJ#=G@-k|{bGZwRl>ob4o@Tk@pmSTxhVp{1-<7(+X!RG36pX&J`TBX_WCkl}Q z>`oLGaz!p##kwpEjbD0w%Aeoys{0&oi&8?61_ay6wOGfa_us9(v^5#L&Q)t9x%Vhy zC2vdRTzq~>T^!1MU-V6oBlP0?ES4Jk_R@2D5Q4Z*X#}_Q2O3P29ob3BMZU*z0Pg)9 zsncJKzPt^cZ(o>vz%S+9M6h5?$_VMnf9*sh+!5;%0cwD8&_!2lkISPpB#YT5`kFQJ*S^&i6vPd}nT2HXONkjCEMowLCmCXd1_O>W>y?ww# z94K$fzP-dDKpiM5NBFX9TO%Gk4GB`h5ulv#FjW6s5lsL~UCXnHl(}BwRmUBUx7Ef= zA7b7C(g(TAqf-(=!Bh{6lyPcUPak1Es2C7`IFqk=Ory_-*>!2Y*>ylEaZluD5A9Vj zw?`{-MvVQH^m^LMjz7(ZtVK`D_wUezztk1%BUM30o1Rn3b^yM4ihfOY6+n6dS-Qs> zT43p&<)Nye)Gv(M<-OMRh$D&Lk4*;_M@q;sn1(A5L2aL*+dNxnKX#px7GE4VIM}l* zw77QEAcC?rIXUfnyX_vhSu^o-=DVs}Q833BCuZA48S$iJcH|b>3GvB|@1KeknJfju zI_3rrc+#Q`sTTVL&|V7%#aj=VexXbief3D0?EN*|7V)juWs;Fyqa`rQ#JR7~ue$`Z zbKQ( zCIW37GO^r4O$&~quBrviYy_{Kud7Sgy4Z5#zd81JhoZ=i$e-b*&IjY?q+g2gPGA1W zSJ6V+WL#XzEG3e>{1zK{Ug_)J{PdkqYcJ~|9u8C)7kBPGp-EJ-*}f5!K1TnOstJ_A zRdKvODL*s8EW1=S4r&poFg+u;w|}QFr7$h6Fx~75?RE>SuWbBUui-QFq^sYguMgPN zMm@a*i=4v%b<`yU9DMu&{{>#F4~D7ek)j!x8}?q6wUD-OP^k{|aiM`ga|{NCnagdgVHG z@oPr`YxAPCRZ4wYbU*Kvkd4&=fcbjFvn!~GOfJxm8vuTMyu!c2*K&blE;31>g%oJE86Q9@7|`u{az*$RBPnLHfZYA>(nD5TXSs8J~W-w`9~NxmF`gS7Nzpee>K z7!N2ttvZuAF~EV0y=u_m{;6P7UAC&itR4sWaJ(UpkPcw~jxuBuo(K{W-+uRa8`0l` zHYWhAHpm~l;E_vcpp}sVcK&tx0$`Yc@FI^q3j-##({`nwuLGYpTPFs9%3!2FJyDde z!NL(Z7e7*9tB-zxy)*+_17Vb`EeS$3H1 zgFPnvFNaoy^8msq$iOSquk&ZnUZ53TfHo% zABwPi$*h9#^x*Lb|Ye>f?xHY>~p zwO=(Bn8iVQt>N-6pfh1X45+l#ySzdQJun6R+elrindr}BVM)c|=g!Gjflyl}#p(IU zPIR$`NA%DigRXWIpX0}LQqq9wrWU0TrX`w5g~vsO{jEckk!NL^lE$7QrZSR#infM6 zGGWR2XtVLUp^aICccyksOw+2D*iWPgfEe}J6;)85V41N=IW6gN29?=)7`?=79aN(n zqa*{>qzw2b+)`T38j5ZTA>z`_aa8k-W3poYXh6S>aKa@->{rKS91cmhu8zLWv$R3=cDXQKF}0k$|Jla%Pbn^Bj|pnG z$ZM;Um9W)ZC#FXX8|8D4^V6^`$hdEc7ewDzbB^&Aa}=cGQwk;O9r3xwd1O z9nSGzA!nhz83&+dK0zW9e4tv}A(KTE5gz7?WCOx~@+Lv^`_X>FGVblE&~X6v`mP|M zAile?;Bp0++z5-FR~tT>r^RG_2^CZzHh1<;dD9c{agX6)BG$M9735chM&x?;oJ*ye z-^9j_D8`W5{R+O#$GQT$c3_E z%BMRjem1eNX&cWu0-8avMv!IN*igG=lZ@k(;_m#zN?CjpIflMnPPM4YZ=rgZUPkbV6evL&HHS+6uTLLSBK3jYBW2Rgst1zG2O|m51f?uoMOr4V!lXhW0b+#v(H<4g!v}63fwu6 zOaApr5wU0`DIYtz7H+-ucujX+oJS7`KWu*h{5VUC1i@+KPoO4mz9lmLLZgH{jBggx z9~7-yoK9=R{>qJ{R1{XN+d||Z$Vuf_cdu6mfA#4g9G5xtj78q`e79L4zyKGmP*<{H zh&o$l1x%^6z7~}vQ5{t><6<9my4r^7rtc?J^M*}9smwCf;EIgBkn!-JMyjBsZI?&V zhKL0UR}|7LGJM%J3eN?*$QYU+eK=luc8b}UX4Mu6qHUl4VyFR~w4^mBEvaKyhbg-< zFp8uJo= z(-#bY&|U49c2 zo+I`=A{6*jV<{|A3w~x(PC6i0K(r~7>J7-j)Qg63PtFMX{kcGtV5IrHOei8wKHId> z-CEk>scf#|H^O+$k6!@1z)Q8GU9cr=pd+N5o{`A>w=bM}32EPtVv<-H*c|J>DV!r&&n3}(hdxweldDz$k4>?f; z+5Jy|?T>4?Yq;7h2+Z^1&zLFBbY}zRTq!wQn-6C}9uf_;5TC(tG*Go1=j}kqkDO1z zeE>;w_;Kn%=b;_|p!9bb0qSy&Cc?`St8m8Gsi2?Ny zh{gG!=E&?EEG+D-Dx;HfGF8Uf>OHsS?{-!%3I^x>^ogmN$L-x6$beCKq>ep^Mg6~1 zD>;kSNJj>x2L(9>sA_^<)9V5(L6{_Teh@q%at4a)|FNXDLUc_Kl>G;l|4&?Irbt%L z#+iOKJLk23exKvN{w`Dh4=#J9LZ#S8j9~{&ruInTGQb`?1)s&)3FMxTsi&Z(vXT!V zb^7_ErU-Ta=e|>sa=f;BR=F|=ACv46l57yN0rp1 zK`m6ry zYnq4lSE-*RH)CMY@PKC>6!ksu6v%(e&R@Kr4UUNmHY4mHhw}@sB=X||DA_kvpOny0 z2R;D~utj+}h7JM+@cAaTa+!)zd>onw2qHsqa)vTM@o!AMy>?#$kwPrEzssrDDs$55%3kNu%WwisGCSn#<7~V3_XP{2O^$+SpszJDJ&mJQcK{ znJq790^Xe|S4-rYNkXl-p9sKxu#W%l?GT5fnLHo~p9P7(FO#5-Ed&BRF!9f!Qf2J> z*wdFGO8B94jk4dA@MTz(zj@2PoKfPzH^UE6N(eWHby!JvW|qWN#Pu|Ib=rwXR2bEk z^yC(E;!vxrfj};_dMf9NxfmDy?@10Qq#;m_Oyle0V$|e*qA5~5{?r%}VIuIPmR5%J zOnFwa-u(uF>uT(aJ^r7zvbHg(WPIMIv9)$j}zs8zM#ahsqY-W z2oOdC9Jedtcfmur|8sn>xf{a>@ACKzBt9e^79;i>w1K==y@vovD8Nz;63ZdvHxS1C zU%)x|;iLmT!c6Xce{hC_482aKS`c^i#H3<*}s19^EWsf`lRw>m=yGF|FP zQ^(Eam_nzX^byji5pK@xkq>;Q1fQys9uK|CO2;}1-9;{^D(5|-fjFb?Hpj)sR5hsT%v!@@ijcmYOmJvB*Y4-JIAe17TMt^H&oXnew zj(UzZMtK^$QAp7;-N-6Tnr3@SXkI*o!Z!tGFH#0I4jzuIC#u?_28OgjL-{_x484Rt z^R+>r(WF`HDtW4>ru5TJa6aWXH-_l`HM`YBtJ{xJ;O{tXD+?Rp=H0<)DJFBsN)TQxuVSksHWG1;Yvp(%4F+zb+`DOhhKB}zjMFFt(2dMwXK1Oam)XH^ z-DSxe3!)qKX@VVgKW_d_(nq4eOOsiL4-+17b^VvtkX6j8NYg3E$uZ8W^e#d#e*;PU zWthAUWi1N#!vvGbp3L+NJ(CIzlMKU{e2#rhAuq39B#;`z+FC^=0BzPEI`buIn;lNn zUYx5~NrT|~DXoTE#9pN>Su|ifFsEVV>v#V*$E^1 zo8_gRzT_C}s1@*wmAHHtJQn{yauk8rB5X0_)7-0;Kq8Cyj@^xfesr5b*jow!jBg`C zTtP*Xf#m3aGHl9g-rje)i(|?qg-NaJFGy0UO@4nFwz>|Yh&V(;JnB%c#oQAATF&Q@ z>i-h3b+3dxaswPD-@`xs={x~*V<58iuYh44(*=TE13J==KjY#W&ey0(J41nIZ^;)Uywv0R7srvwq-!=JgcV ztEd2gIuUZ}5MNU=+-dx1dqv|Fe>ayTM4Wj;!+Q9NS}kzK1E9Vt3>#kH0Iq5=81g zg((3sxnSOa@Q-HrbGZ0GOgjWiJUEI=t;Fx&+|f()OUyq{rq%(G!GKp_GMGjFxR(9a zw7*G{-;_vibxt%GRG%7T!P&vN=nKq_B6L!RAQMTV<6OPV0=qr<{(YS8t`-&`6rx7Q zEO}V^(WlpxFPH(&C6bC}U|4Rh(vfi4za++wBh?8tLLHze7#Z&}YLQ*o3KEEq z8)}O6AD}NDb6}7H5W7LaTtJ0QfNshQjVskH<(V zk)EEJnqru1-0nMskpSEnS9&!&*WLJ?|ETm4*3MkC%xtKbSR!nOX4C@#Or#HJ^lU&|2e3}9LVI6 z-6fN8>wm&eP5s96BJlXUCZkCEpnZv9Jsux_ZHAE_n)g{iITGvJZvj0jl{9u#L=nH)a1a&+o;jkF!{{MQ zTZARodnApwm^jifGm}|=1KG3WU}t=j1E@V$)qUoTK~iZL*PYReLn-0BoAG2>A=5-T zYU`&xbk~{PyPL-PyILHEs^w*jH2&mW0TE?A&2Op-Ob{Lo6TdNc^!4}7uB?-`Nr;Ke z#>vrTv)?66HP=@wa#t^eV3OT*^Noa3R?$zuLMsG8M>yd3)kU<={IlfKm_>BPf0RvU z0($%sEX3^JA`W_g7*(x0nlsU&r{~pM@!bN_dsZW@l7R!N`Vjh$p+ciU4-jCQfU=Ja z_$S!f3UExU(ct#uG&cNper(1&9!d%H2J8!94>%U)7QUVyzYj5ASF$ZEtd%m@H8e*6 z@DyAC6WTyhQS`>;=Wa}mkeA3&VWtruz{j<(R<)RPsW}-8 z2vTJl8Ac{r%h`ntuj!bHqhYInjogc)$#qSE13w4=`%nC?6PPe-&^~wpB0kRH{?T)u z{Gy&f!)WM?q1+17`G>OV9lQ{Xe=Dq+lY@heJ4j_!C7f>t+VpgD31c3lffB@!zrlR! zTG+uby=h)BxoN-m2(hkPXybTT8eX1FHN1nRfnka=J?(_eH<$;+WI$1}ekWqz%H?P% zhY$t}qU4}FW{t>a2JyVAMs^Fzghd{-3YW{1&1dFC@9P!~XBk{zBHGJzvdOdszBJz^ z(HHKUzcwooUzSCVl&pE8Whmp*R+N9C5(*FD-lYrNk@+%10SjEGa#{4vwx z4twN$hebI%-}%Mc6xIeAvvZavjN+lk*-?{c6+6;b%7R#hlJ|en_LgB;E??XD9h7vp z(%s!6-3>}3-QC@d)Qz+t(k0T;0#ec;A)V5xwD4ZA_kQ;Cd!P6DfBS#n3&(ZL%)Mr2 z&06Q2=NepclkVlkzME*$kL>%&be)`3>yeUq^<&;n-*c3ZaCeWrswx|v39FGcoL^l0 zfMm0CD=`n&k*{R3&IJUFY3ln~{h<9NEy-1cWA<_8D~ei~|L`;;K`<5v9N+7bWn*@- zb41vQsT$(x?5_2d?aHR}Wja7p(myjVtQHsPB#kcTp8yg#EG>PSo7!Lp85U4PPVWhvoBWzrMoepHgg)mC+%K z>zWo{DYNj-&Ft($QaLPO$3_H(Yi7(pfW*oJPNm;1QLbm~%a@_A zk`w}>e0;T%Y@xwFTi?ikD=*R+K>jf2jDhxs$-+;tMNKLd3#4(6NxKD!Y&HOrESjrq zPw{WPoD{tSJk0W0Gwk*j#=x}_qq0&4b3ZL-Q?iJ^i)aEj2v;6WU=%o2@5rKHFx{=6zO|2?rjB zKiUg4jJmuy-;lM3lNBI$oR) zXj^^Xa9?vJ1H%YLdGwh$*P?}fBq!>Lmlwkb#1Ahk*esY2`vp&q>GC?AxG8OCY+@MP zF~2jcln4uzYZ82!q6T}O_^hV@EE>5uociTPkcq7OwgS8C)Dhto6rNRs&){8Z%)VMX zIbs5NnNH*3wt;Rfi|r@pqcyEdTAFhfQI62aY)Z4ladtZ2)WL!X!KF=fzQG%lZ-!c8 zz=49c=3}>=sj(Jrb9?{Is~NS{{@5SsYWLotyXd&lHa(fPaFsPpFk;D6lxxQ@i#hH7 zK)#i}@1>(qv*D@bi3Y>4f{jAcl6VJLMULEN1rqz;<8q@>mftOO=id+MMH*LKyH;Ib zl(`F!NEmbrLwFUb6~H^e!Jq&DIVyVa{#X|d?A;;eFBIUIkR@ccZ7p!<{)hKhtr+X! zacK{(?~(AXkz^t|q<*52)VTW?2=;WK&PiRg&=A*5qK^#3r!%$JWdmWoLhU?635+`- zYGrzvL)Fi8qL8!%BdwEWkUxhB!+FE5;6g=O`SiD-u}Hv{S`{2{56%8m)Q(S39Fi&? z)e+nAR$Mv2Bt~3L&8AG;!ceYV{Bg%ei$4OX16$h0jsc*K?^wbsNKq+_51!;W%U67( zci*gcfH^J%mXWauI2014_Q8s-|Nk6H%txkR+ejb)6zb>BwT7asoAF3ngYf1cM=J;s zE5NkuX^DKS$xHS>dv@L(X9piG)ll$ixd$V!7urP$Jv^VT4aFZTJ zA#5NN{J5=jki$(Jck6tf5QOT{pnJ48)up3toG_`t+!^P zczR6-%a1tIN-$c)A!-P~J<#iIigOijllr<_Zt(k?PvoM{t54?JdS&0GnT~k=LbU%5 zcL!h7n|^OqyVZ|g9j-sCSUV#Kn-{JM{Oo*VR^*dkKDw}gPHI@jtrEPRl(Og27dhGS zf`_0mb(7A#kT&#J?%Y#VS1-O%ZlXyP5v>|*)LQf-6)}1ym7#%Y1q&zq*G6|OHZE0S zYgdbU%!kj$eTXJwi|9jFZ<5Xo(aSidg_#_NFg4A5D|VK6b`CerhGxKJT$)^)@Cm^5 z>aG4*sWE2Svw-LIcsc!OuwlW4+c+4^3pZ~8J;&NE^IBIw8(9~b;*Rz1C9=R(Gy^gX zP#q6B!<*&``L#I>@|B!U=>ScZX?WWe*y@J(+YwPzIuJXyFtSHlif??iW5Rw}Yiqbt7WnjXy zLJEUeGyiRYbX<%z9am?7>6;AMZ7@zgU1R3&R03LwrxnHi3}B z94wGoJ7VglX7~vW5Nm1(IpT<6;*)0$^;Ui5U6JXcjdxc3j0vs5q|=jjdxE{1bhjD;gAPg|+xLDjq$CTQL%L;qH5>JQg>Pq+VKA3(EiYcf9)Al zhp)p$UP4eAk>=Yc;InWx%l3=}NV%A<{v1Y9{UNE|>kL3HOC?t4j zX`Hfo`Lyk%aq_hT+c@4KCz~Q}6XkHUjX8a==JYRwy(alFI{jFSG!CZhv;=u5 zR1-1i86rDM;tJl(`;0K9@2buF<4}VmdhO&KnOOTOMD>j7Oa=J7OXdO7VUGaj9M$jIJ|C0Aq6dfC@pljH@E4Hh0A6 z*vE7-N91F@c9zSmJV{@H3u}W*7auOvjho$?@?&F4`07%XI24(l|=lHO- z}@`8@MqQP5iDJt}qlvo~al&Tuu$Q1KMnA}ktc^lEv4ujwscvFlEajrIG?tTbJ8 z4*bcl1ACVTNefr0_guvv4GaV1ZK{iYZ!tkQ6hUacjxmSm;Tx|2pWf-8YAe3<)q(-- zqYW!O`GeOT9aU88SFDaWi~X-!s2g8VYW7v@aYPvvLbv}y)ivK2wPJ_IeO*JfEvY*; zBauc6vsoSZ9(RjRDERQ(*IjX9Ybk!HZX};6oXL}~!8|!L^D=w-Af~qL(Lr-C`;3Aw zal=@OTp6?kHBm~+#`T*k>dM0k1B&Yq(D=0!{t-$L0AC6X)~DEtN4^&a6xI**G6Nne zw*hkNpI@(hn8`Z_FfzjEj!aE*FXJ^*YPqZUxkT9TN~o(ODX6OXyNSzI$f)Mc?4@bK z;sfLS5cErSWB(ai$@U=*+S)L$_zh!$|4k=T^Hy9+5Y8OXP*h=RW(|E~<@83$ z4Kj35wlPVHAl7b{ocTyzP0v$Rpe@t+Vlp!p##KqrqXnfzT$@o=#>LIJjeUn`vS8s5 zkE~oldylgZ27M@C!T3Z0)U;7kQ3++o6`fZ(;ba{PjgpyDil)eLGv2NT>%LE_FJiGV zxjk%1YLadEJ#l-t)y9kY&a5@G_4Bf@sF~*3MS_oCA+(U*DJ1c>AOb=$?`%T)vh9;| z`MEDmRpj@OTq?uMa^E2)T?;lnab7o>Z!!1<{p79DBSMTdG?=uX47;WD?ox&uHbRDj zD;Az+H)4tR?v~cC(4H%_Gw^f~G@q(gBe2`5hkbcEda1R@gKR3M{n57EtyvWuseL*M zjq5VUl(8hPSDz-`+p;dH%u0gZxn~Lp$x-AY|R0k>0 z3Pzojs=$-xldZ-V4{Ra^1FXrcFD?n*;^$_(y=m6wR~Zb*I~g=m@FyqmQl&sNS9-D; zEigy?qWbc~R87e3Eh#(;W~udXcm+RC6}@N&oJIz^tk^@HRR@dc5d5&|?Ar)6c#xGP zbKDV}A#iH-`9*k(cc4D5F5s)btFiVo%dyBa53m83KiQwhUtmkL18o%$(hEeZr6#%7 zQ05~g)|u%egOcQkVL!nDTna#BG2WqIs>jn0N7|O%V2JPu$Up|se-8{}{|6sq&UY%; zcsE;2J5M0Jq-QhN;eS*^KL7?57@|J6&87#M={t$_52ZibP~0j8ks`o_?L*rE4E3L@ zqiFH9E6*gyk2Svc0>`_T@2t4a6mZ%z2|>Z)ayHI#9NiJiJyN;ZDfZ?{qugNp9 z(sf~hZ1PBs*5Ff+fwV&%RC!ku)qr5tcJY;Ino&v1kuJ5C>ls(mLzg5cGJgQCHGYc-+>X3s$Q0#4B0H%1@@^mcqkHGSNK~(#tmR zY%5~1H!mee4?;Hak+8YK*={OREqr!`X$iL=ph}G{LNR+ayO{A?=1qzSf9+A5_tC}k zt>O9G8t;q!Mx&$Om6^NfL-uLoX}E#m`PJ6VH%r>Q zvXTz`A=|~(Dhy{&mzfRpe?Kja_K77~X+UUz}duy^XkOwK5iAVXU&nQQ)PxfPWV&UU~! zU$Rv3{AC+fwK!vQ-YY&l=*zN!uyVA*KTYx5ka-roX698ifioYRkS1(?|E&)-0VYZU zO#yee8L<+QUvQN0M}|GnHqQ@y-<+|(s!V^&tYY=Tew)8fy4$*yp$AEy9qtNGMtJC} z)X#D7GAi=Hs1P32yfU|Y+jte~)u|ZSkM>1@oxJ7g}n1(}&YS(Own;}Svqxd>`xYp4U=fN4=5)O^^c; zBTzSDmGCgS%fuwalW)BwsJTy>MR|^?or~BCnYWD{MzwpJj5`1bZwmG zCj6D`K1#;>h16?`Au}t<+wG&v)x|gc`mZEQ=Im{0jbUS>(U|oNg+-A2`Q-%@H=SPu zIna_4ZA}<6;@l&~=|6Yx)c*wI zzapWrND{+=9mw^&>n4BJ2zo|6DilCQy3MDoU@S}5RAH#xlU>owVyxn^Hsx>`lvA|i zf#Oc}bRYFgmoB~94g*;>#4e#}341;x^eaO88ZjNKWw_3i+b{ngffcr7S$F()BdmGc zm4dm_!Ta>?JE|6MSf@~L%&w?mt|8uHL*WMRGDDzdI-jx(v@R}x>|+rNF^m*8K;H<) zOY3nBAZG5d#hTRm2DMSZy_pOeB^qr8ga%1d1)t1K6cX$I80R?4B5lv>cw>1zD?`=8 zGtV_6P!win*M$}4_9bRYDoS>Rb{8Kpl~TpNS%3;MzGDEKfgmxzcgN!n5|zGYlZ(#@$JpPiCGG zjxK5a;bY}_(Qfc0prWNIozcwETGMmsJM9@!?Dqc1cTs2SiQ#$3dtO6KXYN#~=`3+? zbk^Q{bN5k~A{x#t`SHn;*=AZs6I*1Efc8fFg@C|y$O~;)!bg$f-7F8&Gjdo9myMF^ zWTf+#n!}GNeAOaBdN&g{{KUwg_qwulKN04@4+K+@8AAx1jhn2ulkn?j(Pxh z9Lt%L&tr|G!|3E|wX?}g>ANsV3Vzv@I&N+`J(@A3dfEgz7plIQ`YLcC@(u!ioq7_& zI9|z(Jp7Yt6DYQu2E_>mIkrKAI#vi?6j#FDD^-08Z7*TZL(lfJcdlDQ3kgOy)E7P3 zG_eibR2?6W4!exhmdW|mbXi~@)G}V;7TB**oS<9QdKq6WG#SI^adMPxQu?YaH=<_0 z_*G5wqNB0o=_PS%AqERs*N;Z|Pg(OQkn6N=rH*~KvLXS?b<)Up1D0R*pST3;lrh=K zWSNT>EU#L>sBqt0lVu`KPZ{(fvUDbXnc?7XkEn3KzG-)HjeyDN{A=dp2M>Q=JpWAaCWc#FoIXL_CvCDoWvnfGhqB{H5a`?F== zy*vjT!U?fu0^Vi{w)z(FhB~cY&R4e+ zcJVl7K7PN7SU@W+4Q4{e>*tAzqqCFFiwAN_$16B4Duh2+jTwL{+JWz{LJg6>B>oW~ z9GwMxOM9DcZ*=|c7Ok6h(C)E^HXY2H8 zNYL^ucKphkDL4P+n5zZJ&_80~mj+@{zi}+-s4pW}dQ?bT`V_qiZ}lsKw!ftw6Q&QM zK(P5#Byl|PS&DH()ZJD(+6N0nlvssgf;0jb$fvb^OPR01Tx0P34)UUnUP4~=JA7)Q ze|mOMsu>#-hek&REjBw}&s<)f1S5Hu5*@2ikf;u!j`mUU$dXC=?vOkuXgfL;PZzy0 zXyezjrSou`AX)ShHX37$u%e-jCo7d{`K0!2%*feSKbw+AgZhY=$52w#<)(8^q)}!w zl8H)X*bb(ZD9!b(81KMTy#&+wwCov~!erk3>IMgjo76njz=j(Oa=77H+#d|Af-I^M zg?BGEveYwL7gv%DF@&|WBMps;h(d{Sne7x3)eSRqer3ouf*c)oKfG|;V=~LoHWyXW0zj#R^PATKNK(TTg@tukUS!J zktMpE$zChA&XsCVphDOpw`QG5O&Z5T$D*SCyg%8KVA|5rwtzWo>)Vv_5NcN0w^gs) zF*#N{l}SnXseZ{sZP9Eo6)>i93pwHl`xv4WJt|)mQRij+T;4gGVBCv;G1A6Lx+`rN zrSGN_F)P*)Y|T=|jBxcNGItY)EnX*4yCq0Q=<7Z&`o*Uwwy7^ebHG)SrO*2CS5Jw9 zlx}o)C4bY}+aOIPONup&+H1F0)mYy3`*{zOX2HvwozO4)Xe4cFPO_-Z*P`%(M)W_%ZlXY8ZrbrN{9w0pPdZ? zwL>DyY}y9_(7C!>jm8&Df2Lh^n?fn4@$9SZA#E;W83@BqZd1EQNo zZ?)r?GsyC#vxLX{-6w9YC|~v2Bn*&J1is4(v4R4InGM)mnD^A&VJ+9@taj{~6(myr9{azF0#JGKEcp zH1zw_jOCp8sAs9Zb&tAa_dbBjlw^oU%e^)I4+qz>-`Vi~r{&P+aHTbgC5jM#1%}Sd zuOhMP@vE;HqrxK8d%rcSA23GFkRm7-q4!Jl<%Q1%(Z}q+`1RfD%I8uS{2it)Zr9oJXg~NZa2RNT!jZJ*3(0JpW!bY7*Mmi~mhvJ= zc#Y=DN@7D#WL*4S>L3VhQI>LI9MfK1t|8_gHi8vXF^&S?Wsor!XQ2%p&ael6H+y>7INxK2R({~)-jP9h zLBgO%lnk3G|1z|Np!H0FPSZj!TJ$|3%ZEV|S@@XRlqBF8HN}_Cm)^M?)fr;JpYF8r z-rV-SCb3flN{{Sz8jWDp}7UJDiJj?u*6f1JKE zg1!E6v$SS=6!Nm4p~P#Ug`BmUw>$CWXC3SE^QkHL?pyX#AA+&FWX1i1$i3yhHb+8D z8&b+Xc_-atbRj6uFKxWEVn46hCqtKVC)+G>0|-Od2v`DDdly0XgwJAxJ&AurCPk@# zXeHXx+>RHa3sYqDw5z7&6oDZ0WmnvUDciU>Gbe>^MUEDY%}R#Qrr_KhsxlS~Z71Q3 zo8H*DW2H=J6&~6p7&jR(zj(JA^`=f(aua2w%L2&*$InZVRnPX+O?4Dun`IB zAJZX}Pkw9p2|Rxp$Z8-GxBfA?Mat$BGo=^C`L;)${*Z%E~nu)I>#dpj}Tvk7u zNgg`zeqQ^An+YNNNx`yf}l#(cN#-2k5_Q^cHLVZiwVp+mpMZ({`rkS0) zfwaffa=83JLKz&oJqx_|+iyD(6_qYFRqrRpY|XK$dN=Wfy6{5{H>yIns|_KuvGD>b zYNN{dcs!ckf#olc_a)Wv{3iW8^i@3-Rv5kmA8B;CwS*4eRoq#ULYpD8qG1**6?@43 zmGA^hQyN4P$ig$CO}LB<{Z+mx%ho-rp6H$(hlm7PDtE>1V3nehlF63-HtB>{8?DwBX!|f{8@qGFJ7-i z)4T{?S(35-Lr`9!L;h`70x&^*^I8?WLm6+jUZ0ohgD5KDoHrof0HPk48Z>`@g>;Sh zDF}k=iMCbVfl^CW13KQth-ha1@uxrxAZ!K0QlOi{Dp+|d;LaBSyk6j{7y&UldVCcg}S}p4$l-HD3wHZnCrmj54}IA za2^n=PpME`gFy3Ti__Lzp5XoJVi*(0=Yg2K2mI-36!Z0tSY$i^=)KVxwZ##`ElM3e zRP=zcgxUWPe^&_)Q<^AvTlT5peYy>X9QoJ$un&`;GY=z%aZ%RB6{@|`YgNUBV?D7( z4O@N21I3Q1)sKhwrTOf~4Yv;3$(C>0`5X<|Naq|8zrn33GIU+Zdn5ehbImkT(K&gQ z{;hK+z$Ss*F$)(#Y^ua+lfY; zNbX5aGqP;t?%IAy%)*a-x4q$)mig|*-Wn!;YOg9zoLUxb1~JE7XuTmU;J7h%RPmbL zj`beogBt@;iGiT?ZRFx!`?F(GJ*1ReH- zls`XW2_UciY*YJ=d4N$WE5eydQIp)HCjW~fUgg3Jr*r1HvuF0Uz#T=t*k*Cu4ZE&# z62mv;xxA$JNIZt}6R5IN4zky7Sy=d(7~dKQ-|BgP3l+chKCj`C=B}aq#Ulju3otKt zV$C4oO8#CQ8#W9&XB%$K4i%`BWj$U}P)*6G34khdP-(3|N&)KfKM1Sri?M*o*((t- z*3#(MVv;KQ@;heB=K?`$V9-o0YRw+ey#nxYw|j`j_pcx%++^T^m|FK(E^IWSrMba_ zBONDW&*1Kuc+n#aAKY9l>x>c`d>mD;@3QU#m01{NY}vOfn?AP$(A;4sh}G zKs;zOi)d7^4Kd=4kuwmjWPIK6v(7m4^}2>84-u+)MJ8WNE)z#k@#n4Oc9xi6yqt#rLS0v0CUUzuL^sFjj zy}7V>I(zT!f)3jPDig%T{g!@}+tl=wzg5#Z2hvByFtZttQ5+b&%O=k`|hW7E%+Z8 zzP-K-*l0})wTa^yjUnNJ!{d2o+w7^-jG_gPtn@ya?E`OL4W$o(&wc#5x8Q}Hi_wVg z;y^Sr1uU@UGL~N%uOdmOj9x>-B(;tD$Hhc6o8u*2-zP>8NL&1)*C8YX1h}?N@Be9k z{>IUxalQ84utm0bzc!hz?;$c48}^z8LlBUcA(r0;f*{~b%s^T9{eUx}0azF8?Bpg7 zqAV6yD`O52{qT}wZk4Xr7uoqv7oE#@Q#B3@Ni@8;qjp0l3@%}zf|*d97_wLV*Q9nS z)sFALxSoazirA?;>zFExyx+2~cx-T<=+u%!8o;ni=oqpqLx^4Y1yJ3g<%?^wB~)n8 z;yFGYEr_%P>ah+V>I@7;161)?^&v4ISCuf|5G8tkWQuD=HEX71|d3X+WR@jE3fOi#e3lan%j9lQ!{SJnADCr!bRxfS2Bfn#~8 zv6R?Kglb1Vxcx#5Y}=?CfcSCKHQ8Oe`ee_Hj28{`^cYU`2pmfQ{JZBa);}bp-*oya zsd%X9n{HGwBJs!OJXi`$$UlDu!2&cEh5Fq-d_ou)3ag9085k%3#6p^u4;@723Qbyv zK8}P7H1v-Z0h6g8d0l@LTMEraW zk9hMH(U+gtA!nc_3lD_lfo2Hk1p$@8e;j9-tn<-+u;THKu9&iNl2q?02K&|0h9I4ZcG@fOG|*itshbzzOv4w86s-Z3AQF#-yj~DFq9!efGe;sV;@8^BSY3fYveP1-CR4vRfR-Ee1R#^mOn@tk4E^t^FqLw3W@>6 zn1~?wV6>w>#OMe+;Pav8aCeF4>l@h8^#f-_f9L`&+}4$W3u26Or#Mga==A-5Y8%KV zNv|)EygJctno)V_e`6@M&hRcpcH+r{XNaaL&4&4=Q*W$0&#B>-Wf(=V+; z0gpT1)turUiVw5<6lvP(Dho$vsjloHoYGyGot&APkyge&mmp{Cf(84wp`)k{a^ORc zS%HKCx3K@^smEZ=KNSlN@zr2Nj8)GyFZxk_cx80K4o~WQJK+-iN0Mu2;)lbJH5y}!rK}6X zew97nK;HTC8g0wA3Muq(Gw%#1s~zS;(?~0gl%X%R>{uTtEtXbcaN5iIIZ{6xJ-;Aq z*uLmTE~qV`4(vvM$Cy+nr)02pToU0B_zU}IlZj?5#z*y-e2;lnbV=l2ASP@$cs_HA zRUd$GTyj31@UejXSAR&n%utfe`vYy?u=lr|Qo2ru`c2BeXWpDexyFP?GO3ngb&Z=; zdK=rUNjtuIqji<}HG(fK;!DaD0%@x$hcnWpU{Y}QpnWpzs#ljgOn^Y{`5(=Ge$P{7 z*|)S|fi$g7D9lG*)XA6)X8w$mJQPJ`Pl;xp>z$eZ8GohW$f0)?rz~*R8daZwvps9N zI=RPL5@`Zk)x>)NkGi_y41y?&{V1RBQ8^qmfj{bzaC}zE>Ot$;82}#nB0;f^6bwAc zVN1};{Am?yaKn;$80M-|tg`ibFiXEDmFEgxFInra*$xx00V<`_C7Kc*Wu)nR$V;uT zM%#?UFQ85>fJnLF2E|D}4bPquPTbfaMc*0Nn|n%~7`MVaQXvnpxccETcr$V(Y-?B| zd1Wa;hv{_Kp8!Us#)#sef}E1Z@h{i&C+^N~*nlk)HyV}jQyn43Vyn?*IJj+cUrocvqt+i%X4&nX(Ni77XK?fKVM)dOsR8k=hRLg_9=*1gsT?F2}Ptw5sm{#~d2!8?Ks zA;9~o@ux%VuqWCq8CUH$`;QF4iB!~#|GCL$P4@dI2ThmvGpYGn4C4fNYPYwEB&hL- zP+RI}Y<7P7wbfqMSh+{MUmC3y###e?0})`@MF2dy`TeP_y3Sx*SJoL04iJR|T>Bw7 z=;6}$8EEw%C)+pV*Snr4i%fWZI~MMi&u5lkb(z%I^oI&_;Q$gn%nE$X0-Ct*r@Nv3 zR0n~zLgv9-wdv4#I21>6R~J(@Mm9!P$J#I?cKF&&v?Fls8pakhzYJ?|A8PaOPmbO? zv&jvsnN!vhuIdQa%MEDF_d6%~R~y0Zao{u4%Wi9Qla`<)?x!E;nRU$y0WlU5&#gk@ zjUT+EcZe&LsWvK1dgE1TdW#MlK|q3r-=eMP?=Ix^;pCw`BJg$rI{OM-#1^pP^caLx zJVK$lat<~QE@Fk!0oKv+;?8nO@!~ll??N6pGabbWt&z5pPAMTG#LG4=BDwgWB0rqv z9cVhx8(09;dw-31jhM)byLnIRhEOgqWxG=6z<<4*uuZutR4oq=#_hMU#Ht6-;EiVh5@_2rVHMI4?b^H6Xd$3%3Y?o&D4?&>v*sSO3OSd)p@|y; zh?7~lTn;AL!dU{jRe#Z2c%&!o)BDFc4(K(7 zGgw~Cc`+S3UeV0aHYPhRQqlZ71GA&emNU<~h0J$-M~D&oBy$G>Hs%mPSHnd8Yw#fu zz$Onwf&M4`4@3cD%>ESVQ~GBHO^xaAuOS$f4yLQsuto^3uU)vE1D!)AZ*-DO+JsIF z->=mxm?4xOm(f10FEP+cccc0Z$Hb9C-;?C@b3l0V49r|aySW4X$L4>xkM=ogeu~%L zv1T)p*tS_f16}Bw(_{N;?5Espqlc;c zyP4e4;Afy~>C~tc!6fxgd*vOBrqah|z7@-jCmZKagoO%K+J{PZa5X#lJT`+jLVUUo zE|Yx3Ww-tlm;IOw0%^WLbX)@u0`v{N;$~goup-I7GqdM?J1l0$Aq?UzhsW51WIbRS z<(F#C5>F8G?>6Mo4QT!U3^0*TxuX{j-}9Ty1z~gCPGpr|W)Xp3Y@s!-A%p_*N3aR# z-Q$u2a%zzg3CU|!UsO}}e64iVfnh>>5_pz>|88%)cE_5aT@TrB6Wck1I8CDvar>p>hl1wR zi1?OU_!|Y{!_#X0P-|xSVJ2`{3vD=sJPw zirk*xn<&Ui0*mLno3tzOvo8|=?(oF%Kbm+=u%Cqk?ZxUEo;1^cyuDhHK~Gai zT2~-)|F#pgxDoa{_cDOzXNGdK*NfYOYv90bdeo$zlAxQeLLz``i${MPN>JNhx|u^j zN5k4aHDTAr+c;<5aq_XXY}k27Ck_OsguZB34P-pP9mnC{dx@h4L~97oy8#Ym0`^cv zo2qX&%g2Gnrgmuc+7{cwo&ea2=SdzANCUO%{v(jSh`S~9yQ}mb+`Vx?Wxot5o#|A0 z2&D09FvIO4uz|)Z1(n=Gv%YLu1%qfo&tAbnRv^J-|NgB0h2c@rx%7K_S9HhSKUsW^ z0~1?QRgXUlK>=fE6%u9s@6VEb-${p4jyEtWI=!?i_lK2dGE*tW-<8xAp9-|Si#ogq zjRZn*y~^uX=Ao?RHflC<)@nH+sS(oFhRzl~hBg2v(J(qB)xsj?qk%utqeLl{WXK6SwKO8t|sR$3^4I$ZmoWcJv*atLM!QA59!n(mG({!^d zE}DJ1q6dQ=m!UiFgMnlHu~$H#85MU}T-N_im`&+iQ2V`T7n6JE z2S@p)21!865BXU5NGB_fZT}V+a6NsGuRc`{ow~VfQIrMfWQt(i(w$`?Yr~{yg)KXF zUPpAMA=mp<;QTPajb<1j3mb)A3E}X;twMbMow+ELZ!=%A zCI;9V&RrH-6A$SE-5aKt|5}jOX6U`!P+;|f`9XdEjPn0|meE6TFTRe-zo5|;YMKWn1MOpC#tnk?6xoHYtycK<`V}zZT2h7xctK za03z0=R?eu3(18fcHlyM)ZUx*=Fj0IpOJBX5^EtM-+!Gnsn{EY7HSvyP<%6s_WXrg zH)LdZhW{xcmkOP;)nMfU zk<3A}fNCtZ|1Kt3PG4J>`%2q1(?z^Wf_g2ylCD z2IYoHuPlhw@BuOo2Qc7&)}(AiT1DmHj)*<}Y4j@xVmKtNk#}T5kIjsdpsE4|s&N0E zr+$GWL_~~@3nF<-zn?p}u~)fsB$Leo@dB|}psN{l&I7mztp}^QC<9i*Km3aUUI*~L zlLrWN3IGeLnPyguuy)M7YfCaueytEPNb!btO+g`&vQex{9Pm2Fh(2BPVtyLHth97v?*ht)fJSOj2Ua2B z5A4y0c=y4-rp(wo&p9)n3JgxiRN{>ZS$cmfu>Napt(*a0gM+w%uZwGB%)7Cthi!Ev z1o&Lfgt(v}u?qyqHW-LO=ksgy%)6hwJWu`#aM_iH2N0XMdGBAluYy6|AAwo|&`1CW z`^TVig{k}JXFi;sj%}vSdd@b30f#Ef0a^dWCk>rl7;4DSBQ;Xiw8_c-{@KReXrr1B zB=nh7_dgDiex}O#GUN|_9h^S)!q2q}7rF3%>~TF#%rpb4(>|E_?>-+Y)P~yp3>TkP zSfcZx{WYZE({kl_9ajo!hM@ERhXaz$eDTU(>Hg#LtkzdvS#Inm#< za^LRauxWd*btrBe{82Rp$nmGJ8g-Z$?ZwlqhJsn6A%E85U(VCX3JrYsZ~3WG-qLNE z?a^@AonC!Nd)9hyo$+Upb1>Jk1!hqrDyfmuNscXWK~?H`w=NVfb5qJY(A4=lx4NM*lZn%Q`;z z`Z%W5`Y3lcztU4h_XO^yREf2-;tI+9fg|lRfJ*u%T;}jLFu&{fRr{#p7ShtTh^}|m zD~>@92#DRB<=Gk%5Y7H$)BX2s;tNJ1+)`V10Y;fEOfS|v^V|O~n|8;d$h>j8OOqyR zJZKg9K3lj`+?CNn(s*Q2Bdlttzv*irGU+t9)#1BOL~7U^r4nJoD$nwd9*w1~df2M# z<8NP;bV=)%%?Qnc{yx>-c(tTdpnzF^4!{Cv|5_kq?`Q`fR?~jLIONIIcCnlZmhmd+L`f zetg8b9j%+c$k6O9WmJeCE>GVi1XHuKtQ^4u=_J?)^#1X@__PbgZIV7I`u!&sR~2I? zV*JfhP}~>>;UgJZVE^0srMbq>dtMNB!YgxnHL{KSTvw=RekVjhw&gRqoW7eS4Vg?(@@!^Jrkk?>{dI zP$Nu#pyk$B2*FqVAo9DE?&@hrRQ5IHb;upk>{!{#w2q`AlhcnMF}mkqy9!ia?GsTQ zmMS%WRNayPvGhQkB3&BhQtJIBuJX15uDhc9Mg#L7yWoB^O-$yLJ zbl=z#73>p&%4yS+d^yQ8rYD1{`4q3LGJrk!aoC7AB!3MFTp}O zSb)$5=~u(l`&j&BUj4h@X(vH z4QX#EEWAydM<>k-m{d4$Wb^)9@9@{@FxY`Qa)>nkSO07OkN*8Fvlse|JCiet-g8`$ zMv`QOya@@Wo!MyWQirkd^Uwxb5JdJX{d5EL5eCYlBDK^H+QGlxE0kaX zA|qt#XJ=>srJX`P%%M2>c&BVQawjI12d4PQn&rxGlcCL-w`&eK{ne#GWKeWIX(=GY zw*J?+{d)}ZmCB@)oA%0+zsmfTf%gQw$3-8FJ6VPLWd#z4|L@1LefEwK^ntNk3A=oE zXKXo*3t#zuxILcJORK17yIJ5B!-scfmu>a5NG(k!bLOdsk8+hl0jE}u@Bo*Tp zMTLEV!(a8UgvBoxUes)i#GHK~=|5^(#`>vpXyDB1p%p9VvebryJ$!k6%b^TFMcgbNc~MJZNjgCl;SqP*1Nyis`(v z%+qYw;R-*J{n^zNg-)jtVezov2MVH2R& z@lzugRt%%FDx9}eYU{oH?VMRPUEjdqi@J+)x_T~|T@S$09=q}|e-n>Rqz&;M#7;+MW=0e!{JzF9dpB&+DfXH*x;t)^6mANfMhD(UXN9Eg3rQn z`2Yc>KVdB0wLAUF6K&Ms-d7x9CHx(6ksL(T`(sWDr}!+c2IUf`IbSE$@AreC^WT<; zG^Jlx;Wbf;MGPbr+1n?SGD>@hI6DMQe&0Cb*C|~~OSUe>c-ss^eRo+!4eYkW`b{Ai z4x);C1QiuZR-c(f26&n{n>S_d#Pmiw5DwX(UiIAs%G7fcNkMd^r+UjD7t~{rL(7_AkRS8Y zEB9(`I8zs?Swb%^J9L_>*MYhlm}$rQ&A8+S_8_qn%bkUkW3cBH)KW)Jh*UEme<$q( zJ70$&sm9eUKyt}pypDjC9WNANX(zpKGXbHIXkt%of6q3S&bg@Ck-Yx}HqGqwA1~Ug zzVHQvRHeT&ZFv!n{H||W?_2h(n{&rT%cm5q1U9=7=mz%^2#oiyEUd9@$MYi&G}t#% z@0@5?lY7?qEKDd)0yP{nb!)pxEjosnEehg|`6`+z>8EEKwiN_O#Sh-h;pD5oIUcMv zF4WVVy{u~Ha3H}BfVk)^;|845;9ic-<+r4UFUPjotwo)(;RVM6==sD0jL8cc_$yoF z#wF_g02#>_Cu?L2P*iTh$k!LZ(@c`}#6?bIOYKMg_8VD4mUA_lc_E|1o&(4tx%%)C zS0It+@Q-PvtXn9vkb+Kt#WxFh4|HiHg{=G(=QAEpL@y^MV1P*#lbVevV=WE5*D1!v3n)`LEv(^b8FAL#JE+hqbp1t7BWXK-a=8xQE~pB)A5G26uON4-UcILLj)i zYjAf7PH+hB?hy#~dL`NW?0fD#_q*?V?@xYYHQlpk*POFz)TmK4>21m4Z!U!yXNPE- zOp^W0Ku=UMZH89(Zz!S{wr`hv7z8P}{R?U38g?+2(u@FI0KZ7@z9^ zrV?OgfF(f<0M1zo;VQk-CQVON8RR1P=$+L)_1r7Z&`e41>;PkS|32i6aCkjg4z=rxGS-?rEkiBlX*qVVx%iB^S{qj<^*o>F8CCPoYFS$ zSFL*)`p4k09Dp0%`hAH`?|w^*pSe z%xC--G&%D|MLK{^0D{tgenI6ay)!|uU5#6)zwEd7$ZC7Gan%3&xF-1UpRPln0j@yW zW_y=YFIwUljfQHl=A{z76sK>z#!&T*pAkESwU(lf-jJEcj;+G(b{btPcy|pe`wW~2 zc|L^G@Fx?%$p19I;gS$4`f}mI_vnHAA+BnxI*tS8G!vb68w>>J+Uqwf-Xb_>+pqW} z0WYMg0xRH5fzZ$-6po?%~>Tx0|6IsT?3aOQ)rV6U2eq4S%L?>q$Vu-??B!IQDHlI{Q?KyZqHR&F#>EKcToYv0&e9{hmXMigNIL-d0-2G2+F`em{}$B~2j~hz$wU-O{F=vn%}0nGE|8#_?t}gF zS$=^y!}UV3A0`cIpp0MUt!$$XG>oyzG>?Kbi{VBAkQT^W{PoI%eMO_~l4a31E&`Sh zcdvFz*hlI-4}Za{cjc((yU@!31M&Z|tI7Ff88mLfr1`2PeYs%6CB#3ohz52wAu-&L zb#Ry(z)Gb2GTbN>=}-$733X)RQn>U}Vv)Xit7)*;^^03+3ioea*B67Z4EBC- zz%Rugh3$H^JBGgT*~EFk$bi{WVYQE;OUeE!C&%6Z|1&o+O}H#%;-G;nfW}cJO=-T)kDPfX6bpy=c<TFUDCeusf4-^W!yH9eT5^z10gsYWdRG3Nu`WSY2L?07Ui=~aF zAcee(Lwha<4eF_Xmaqlw7vTlmw|9D?y*tU&5wnaQJ+g)h7dwBq08l`k%qSl%Wlo9W zczgLuZE^@+)0C$v-k%ks@R=TorUgij_yIgq-Vv8z?_S!0Ay^qFu2$9}7KmDEfk~kQ z803b9V6z7s2v`Yk@f$U>UR>0MzJLHgloycrv15^29e%-b!PP<0_Ja-TFR2P14A0d|S8# zHm$!PiA|QDyo~)O%4Wudgy(h$Yo`s&XM;v^0v!az<4YyZ@(#VO4P&7T%PIMe%1)8W z((F>0agItZCzqGXN|7$uD0C>!*wkE(`10SkbQ(1?Mq({5MHz3#tli&gf?5}FAbRM5 zl)vUU#ajenYnx6i3xNMixdei5C2+0qyo^V5uazQrL2EmP1z|SPFDMRp7FN~ z+;plm7{RK!OGV4)Lx31iwqF5N`hMts*~(_tfGY0n3ee~6FDXaZ6dVQ7iQ^-%pp{R> zNq1x-kH4509FU;XWVbLNC2jBOnnkv9 z&oFJ2!T<@B#~s_gkJt=YjduA;2}jNwM~v350|kXTarRE$@J9V(`b~QuWmhS-?PJrk z($X|@)qhE&<{Fe47>pHwV3|t*d4udA{o?3o4m=G_Nb=n_b3`j64}l5>6JaXj`dpNY+rS$i9N1;RJ5WpSM0K>DJ| zRCl%Uto6pT-9u*XZn?#wl_hVG7@lInt!ixI#;fsFBBT3fYBg4m)m`6r{O`VTl=kfS zhq^EzC(RL!AYR=YQQ|f>mECPTt<+B_81k+%A%)Yk#$&|HXc7 z&|~dAI3w>^Nx+@uJ%SC4fX*v|>HIn;4j{W98I^B)rE@;7)!J!%Sy>x5i;MZ$a?lUR zX$gSGukT!fsmX|jJCUDs z{_I0m%e-d7^6>2Z1Hk?nq+>XMYp+#XN=MxHFYh@@k(j?|Hu1dD4`=&(nABNJZx6a} zvl18AUew-sH1Jwd--@t{0u@ysoCF-dTHVw2TBCO00_0Us7cg8 zgum>gaC*RhNy(a-4exrXQP_dnzao9z0Efu~*N*asdiR=`$ua(20KxhU7W)h>j2|#t z+8?S`y|9Txotn6^K3y#_iwe_kuf#Z!3y09IUsK;+O33(hIrNu9v_KY8BY|D2%LZ0E z7@|6&%gZd!M8Uz*PspI1`5`5)G#iYYsnbuzar2Di=^#GE$FNG>-y$T`uUTpw6mHsP zA~3^DPE71q>*JnyP|-MDTFRboZl<>RODi=%bL!2+AosYI=*^8FHC_@Fdi*YqdEs6`;q!PPZ(+V$piOY- z*T0cX*-0uuBk+oihlQqtyR*1&_;YHR>m{QY4v2n+l6W5qV1V!r)V;IpA#WZ9w9@(j zxg_g9IzkZjHdrN|lzu8CERuXMi2ekP5%^x%e;m_a?GAy4cNmLKLkgbi7MH!46O{5WE*Wm5Gi8Kb(^Rx#e!_`NBRHZn2_QVCQeYw4Us5vC~odBTx z^-2Kx&%ljdJlk%lb{|goDf`qEZcLk~=fQ5-ZuEH%fhqkVW~-I$&V5IMeIwD@YWx0O z4Upu?Ab9pCIe>3M^W$`6xsdLx-)nVw=xftMFl`f*N*-j3B!093fD5lXgBqy1a72wz0*z6ZZDP zwz9&G>32C%ilx>^|B&347;0SuW*RY}LZ!k;4tgIzC}X?34c~)A3Y*r-&B!d*(KpN9 z9Hi}h31g>d7j}U}YIO;RI5ft}H@(PthDm1(53(#`iQ0sYLx*e{{39IQzQ$U}6rR7e zp1zrgQH!qrOWUVeGhiq&TB>)^=7g#UQ!5d{YL2pNPOdeF_UL%g7MH$EU0F0h_=`b$j!03qM@J zB%g;x(Zmr|bkp3NLKSC9KqY8Yt_3JMQURgK7&Sj`s#gHZJ4NdnqPXjA z1L})0-efZtDU)5CBHRRveDlOU5$AzD6I`GwT2}89d2e??`k$^v(d7I?TdzZZ0=bd| zl?kRkLG1S?_xs0(#1iGC1gK>=vWbx*CwdE{i@NYc>G{dJSSxB@Ffciv!sE@mIpTyz z2A)S>W8EPV!G_C;AC!x>i4=LCd9JnHtfuL`*F{@frdg+Q0Hb9b$?_R0XQd!)bY0Vr zZ$Xc&av)_Mv96)q!}HEiYit?5awZCvw^NOdVK%^SSbm$qx^hQ6EpTn@8HNr2L4+EU z@Xa&_l-!SUE9~z&^80gTPoyKQ& zyw|Uel)e)652iJR8yVd4qJN<=EQsggwaLP*$a)@g9L>KL`%;H?`b|je=SW;bJ`U3m zaqB!9fdP`YJ;qjVgcPhb{fpkY<2toV-UYVR#Ilgl%qlmjR?}T|rKS4ssc6~paAn?V zn!!YK+E^B$M5t20fB77agkd+ljOO)25n)BaryZ+- zud$%I2o72Fdlrk9_)oSYF8D6rC7%w5v1oYLL|wIGg82%5uHzJ_f+Ovu*2irgoQMha zJwwGYh97*8-+lEs)!w7CE{M&>A$t(WmU|JlEi)r{#)-be+?tw`YTe zmw&2aycV2Ve7C{nTGQri&X|i3Qmn(UVrk^I`Fx4oFDAi@Opd8dlrTsDU-nAGGmz%U zgh_2|$Vo%w2**!QKN9&htp#n9huC$C7VS1Qt|>h>pgMqyW1d*Bt3nrVlK)4J0K2Rg z|2wlR89_+`k|0a)@*N5A?}I!xKxn#EJdcfrnu($g>Ps!9k+- zd?PJyw==g9LI)Er&p+}M4ODF|-vpq+f9b?Qngr3FRa{yoF4|OZGU{D6l*UaZo&Dta z1q}?Qpuis?p8#RjU!D|K>ly&4IE;Iy{n$zt4;^ z?5j#eYq)pt{$jsi7_&qk#@J|1B%9mGy;VMYKH6+D-f}}i!JGF#^Y4dZM+s5?FiHZf zE^h_G#hb2QQia~jtNDJqj(vq-WvggKprHsCxSCYN#n1q&q95l{akHD4Sm(Vt2^}}V z_6P%FoRlpGTqZGKr9#>m{zUkR0HIq$p+f`xm>a~@|vIlbPF#i#t!t7 z6Ift|es#2gTn;E_?}V@H2=$X63MS@JAe=sHZkc8F`1j>bw3I3@&+Hk6#LhD}leqVo zos)w1i)w(?7;5qAnz4m}ftgWm%JSVQzH{Py0xm2dM?U$KG zO7&86u>#X>g3RM|f*K0YbklNH@;eN9mrU>&uZHM|pyIM>EM+psOqHvu`U^l%f5|ux z5tIxqA^}kc6+sEo?~@xTr5`DrN3v7l4D0O+X zsK(>Pnl&eg#ayb$ItH*3-cJuPw!jXuO}I-6B20kZ+J>nIr~&`^R5;YkMPDj2o{VfY zwC{NnIv3TShW5Mn&~N7 zMG7%lS$TOe$w|4tTR?(T03t?AQfg{!Dys)a-j`j?QJi-yL)TE~qRr8_dhBIB3NPJ?CTu}LX)^XI(&}PvNKweI4hm!dX@jFV ze?gCokD~s$DjAhNK!302#-Yq8jZurwvPPReh^(Gu&5lhLa`Z)Z*K}_KE*!TYF&=kEQ(n&ehZ(FifS9hr8``>VHFY6?d{?+_Ez`__ zX&$JHuVIdKX3w0;=J7&`*-lnnkqr6m(#jaC|Wp6HR=2pZGsH0z?^XuDmBKsv?3up>= zDW#^)>7+w|fCvL(JR0*qe00b`h+PyedCc9dfD zU&Qu9o)t&6Fh|uhuUEQxqN#?vW}&?1pcy{Aqje~Wf88eRvk^asr9AG4=lts*s}*Cl znC}JX`FVaCstz%G&JdYJa{!CAk^iz@>92V1GAI=|AFaVm#z=Pg^Ndb-> z-cLSJraf3fK;!yf&CUQ(l;BZpYsT>*-FIJ%(hEHLQw}^zXpw&RGEfV72@s{yI@zR{ z|6%f<1hJpB0oi5SC>G=%X6&H7HvJ0=^^*Pd&tZ`-5jJ;;q}HS_vt^W84%IkN*adi(d!*~J)S^0azBp@Tg zB2Gg_MyzWXj#eRrVD{o>D@;cC+K~ z9o$xaS^d9k+Hx*Wdyk>df$aBR-*zZHO5IFV_Qs>7ZguiV(rD?^iWx7%zcO<6!>V74L=TfSA(WWs3M zvcE1Knt(3-z}FCVuxvzgbMn&#kjA;e`=k*OA~>55q0!+$&wd?q0vh$Kyxxd+i}MZ3 zMgL^Z7GZV<#$A2EJ5d)SHGDA}67D$Ud!4M|Fnvm9@ zw9rMPcV4Y^VO0_Oz0YteDBclPymOh{n?tG(ix?Ze&U3%&hDR>WjeVCp(}%q>6+224 z6R7f9l)q}Cy)P|Isr9PjriM3yE3iJBuFR2Dh%wf;_hopqcUiLJ&9(@qnB^=H(mfY= zBGKYt3-%I1-1vu#L23y_jlJaOAeeg^M!2wVUf~%Za3L}VPHA^|$*oCh{El6cL=(|# z$5mG1|CBN4B1aoG{~8&gD`Y&&iycBPy_J)!RztP0LG=}wW0#mQsa`?sU`fStaB!tF zg`SmVTq*5r1&)?BL#|qCKtN>jmlDK$HdC|BwOn0<%3xB)z6z$8P=}523MNv7&95}F z=*wd%XQMnn#@&9txIdo}C?}}T8_uab3tS0#x+xq9q9$Uv!W62A{3vKGXyKQ#a`2Mt zjj0i16^Le?6=qrZv$Mm9&D=y^vFlO_uF`^v{dA??|$$(nU8wc`|wZFcz@mPqN z9ehKGw=|FCV7fK-BzmBBIC#uyQIGrVn$PivaP1?eZ`P&W9zSl6Jbiw=!u5|Uf$DzW z?87yxj(q(L+?LmSXaR@-pjR}v{*kiMH1=Qh*3H~xvE4%BNMC^V#G*q#VPS`U_7jAMyd7ee z%$9SOB&|q7iwj+NqLh0C#l;N)tRfF2dF~)hhDq778)Q1Vsd+VnUS*J+DusE(C4Hn} zwz5^*{cLJFg}hqcV?7E7dgUVy0%8gvU4NwLU0OpHlp!juUuIWBR<*zFdt4J&d)-WP zdnpZ++;#*agPH=7W;P(DQJ$qWnx=u!XS))s0y1e=Fdb}AAQ5qR;zRfpQ^3OCf`Weq z0smbySXMI?YvUNUIF-Scy08=XEYbKbPEnW(rm0rB{V-bn^co2SxD!6rEza+ zf{};K>=R;Rku77@mOC0~8--@C4(b0`i0|(V1H=6ZqNw3WOK-AEwHIHQPxl-LoAM|S z`_S~c1K_)17m-U-?`+eU9|h!pnAwJ;^@S{9yv(wt>I^kob`Qhr~zfBA8nX zj?o67t1Qt>k=5jcnO-3!T9$)Ic44A{bj3d^E(gDnv|aG#ADOB(Y0!=>cxKyO2`5?q zf_-*lo-A*|1Om1M76!Hd4rY6yIQ-Rbc03nXwVJiVZ_^!O3(Nw^zy66C?M;k;>HsEE zZPGhjVLsv77R8!F_xa{W4)@w?r~ojn6LFV)=pJBxOP_uwn~I?Ps~-V<3#6@RIKZ9w z>ktdOun&o9K;a>qo@a(j2{*Sx{#f45`O8rnutUy2gY|t*{LW=HMLJRo&Dk6|+6PIRgj!{%wAP{)2**k=nTpobvAL z&iAXm9Com{WWUVsh!NEU;JX06?LVKExV^@^gaGyM&A@HzvPQl`+OaP0KRs>x?pYC_ zm;ke=_}IrhR|M$a{Jl~ggee09({bu-aUvpP zzaayP84%^GZ?TF^f?7=Yg+vy(A(vh#J2%Wb=s*0N_gi3!d&=d;Xyy8ie3j&U92-uz zzu7q2DC}x-Mh%f4AKbmE5(L^D2fgxFw60|hWu%YOJ2%78Gv)++_LrAD2K(6quS*2l z`klSe0b}3i@+L{7>}}j|8^)wON50SDT`n1HK(#pohXR?KKij}yhpM8d2v*aqlO7W% zo7KI`kMBX)TTyymqoB2!CqwH{K;M)9k`tQnh;85S+AB&g(?=m0+0RA~B|CxSgy00x zI8LDgff<7sl*qs9eQ_Tvdrc5zEg3G<-*08PptLU@)md|uhSY#Sq1zb8|9#I!Sm@jG z=IAP+U(;y%S$djiJ8kacWgnJL9%v{&d{4=HG+uw8`>cJh&BNPlPWl-fh`XH-Z6C%j z1SpQSc52yb@)vbwt+Kh_EdhXg)PO`l zb>qQ9h#<X~uyt>|W&b;;PV3cJ)(xft zRY&+Dpcceaf`TIcgLvp9%iV2uTCTiP3(go6?fl#bFPyE`3q z-0~QM>jzG^5WA_gy#obP!K6T)sx%F)*bn+Dqg@~BZw!m%-W+62)2gmIwp>+;*`oQ; zjSa~_m9kIKOU#Xo8e2R}e=XX`n9g7geKXHNMSopZwyV#~0)h(O%r$}g6gnrBAclpJkbC5( z-)-BhY`%Lf0*88wz2-Eq=Zf!Y`*>~sOvL{C%M-0XkZk_uWgk>K3fwBkvj&-@@d%50 zp9}fPpDx~F=Ofg`vD+pqfGS)-A7*xqUr(7>skGgSmxA}kHaycjvU1COO?UhbB!9n8 z#fI$|-lo!-SI)aL6Y6^+{q^SY@v8E*YFu|0;kwfz*O}vJW@-v-yVL;&@`PI`MF}Jf zxmokc-FKIkYdTC5KG1=k^KEU=UxHVSi%nIIEl$%=h*3tY`>gCNHOph}p=?p#A!B|c9a2%j+@lDv+{XNZR6oq;@~Sh zx=X?;%3WccKjDq-ZC^w4_kzQvXVFd*C3o#Fu=gy>oG?{o;d-&p| zUufL09g;OJP6axA&)h-92&Ew#qg84?#aw)(yUOhwl6>s!yz~r#bgh%C8=sC8mm@yS ztl?L9OHj1*p0!#G>&;!Ec_K4@q^3%!$;jIQJ}0NCw724h<5W&+#TW$P{RD#2bZxK= zHqUhjIzJY5wHP;#7(MJ%ReVr20Rbc;8#l9v?$FykejV>R0n3O-bJOAooi|g=$Jf4| zSDR&T?{Km__;jLpX-c^Fy0HO$iX;l9Pg@}ikB2hfea&pVs(CxA&Qs3C<4Bkj`b{N< zo?CLvPc*0IV8KK^`ZCHcJUXPV+F%s-08nUlt+qOM7KU7A`I6JO%}BU}jKXhiIieCs ztoUDXa&aEQcow;BS8n#b+xz>4!R?W%dgCsLNP#g&_q# zj2G~Eg<6_RnfIK7MYOSwk_|qdd@~ihW1Hdacy@akWkYBNg(Qt=JW1Lx3fyi9ul0^| z=W)qREJvB8=XnHT)W%cN4*Ic?asvYm6>P&k`wpYa1T6V_GbuTyLE2q^LKs%Ch3bgX z&dmbs&Rk8$&TR#^^_ z&C4|fX5pVfY@Fa5^>cKu@~LB{Mc;VT1>xbAc$p5CiF!aeVp^VIP-aM;ad(P|R*GT# z^X!y#g~ZO(#E^{C1Op4OHSJDKjlgfdW(<3msQ1=UiadFE1YY^ZR0ni8k8ODb&VZb5 zm9CPuA}>dF2@_Gx#45&yiCW5K-gc*{x<@U70*l~FPta(9tMVK4{?pk`l>D!=-M;q! z|Fd25*V&E=ob8W`Q#TuW{y(d-?wPqj`a-hCo54*q5zJKIX?Ck&#wDKh`PH~xaD%M%@t$@MV9*vZ_7&2~G+ymH#5aM$igOVBg zU!Zy+Wsc**^?F-JfxZWPbpX6qdoZ?u3dv6kXgI6fB}uvf+Vxs(4Wr&TEf`Y449OLn zcpxjSO;f987KnOfrfVi<2O{EtHu|4Hpk)3Gr?X6}lyI;=F4}xW=9=#Q)cG8G4z&PU z@c`fGmH1B1Q$le(N87mcuU|vZj8FNCQ)hB>?{bZ@Q#(B5T-~bDo~K{hU7{&sZ(iFJ zI-rzN3s4~zlNuE%N{zQXcbW_lUUOO7MY{y(EYtRl8nXHb5vQh=hIOC!2lD5+>kFln!42_m!L&IlOE9rhG-Nhuwpa^hBCg6W_`gp6 z*hL`Dfxp1qWM^fEvr7Kt@0?C^#q^A z57v?@f}#-~O7km=%^%y*;-6CWQZfyDu)GVMArb1dhR%`?eMe2=`L_2%E!{5JB|PDraQ}g8K$KQthn@jyGXDk-yg;^(;4-1gVexTvH`SK2T1MuIBU}qm zif+~j=lss@(`PON#*Z<+Zs{mc2e=7{JCx$iq^c=mh0R(kXI!p$-=ttssQq9VGTpmG z_{jat7mC~^BooizmAOVUSD{^2v=c3ba8e0{X$$+Ih?T)T6b4@ebHhZZ>_>A;P(}l6 zlPyUk2kpO9Br;6)k{M%Dcf28IMK;ay${k_yz$(+U3%iFzU=)pFcD>KU#45+!2<|<= zbgQt0_F-4R_Lx?@nA1!akVMO7@5EX~%nPD>0aLSs_!NLsK6~X?8zS*$2?Jgskl@x7 z@-mW?oZL1&_N8IkS*YbnaiX0zV;?zNCWzJm@aS)anjXs7~py=1q&lf{iK?T%jn0l-{La(7g z7iL`OKwJk4;57NwYE~lXw`M*a1_MK$*VE0@Y|@)oztbh0w+La?AP|tNT;G=h0`XvF zS$ixNbk*Q^5nm9_8-n2i73pbghhf?ZiKjD69O0!z8Q*N?O6T~UEgEBii9~!3Xel!}Ah&5lv&_;FXha#++88Q;N<}~2s_xOpF zc)hXGf~7+yeP^Q$ADlo}mJ&2hM=>chhym5o6F9axaj=6gH<^t^SXox0Mw?!S9rcOY z-_u!76IvWG4grly{hEkM<_O`eHhV(~{p$-C41ZF17=zI+zZj(p449{6RQ2ka9ItCM;I=30^Ut5X(+Y*)27T$B0~o@LMHT z*GU}r`j)d7ue~F?flXLQ?8vcNoe>B7vkmA%RdnU4N1yt0fz6*LNjg<88>u{Lpv)aB z>q0D@DaxFoRECHe11A?}uSXExCSf(5tSoDq8w!$NVc>HEEW#8JFI59=kyMfZE}afd!ca~{+%B&7#F?HR zh+c=E3z*&NxbWfVD4g|AOlPXADqL7Tf0~15?AY(#P%Lt~&bhky7}w>#pxtH_)%XQ@ z>5B)@D)nv5nO&zc^=!iHg^ZHVdS15ei&l@An%dJ#INbqtD884 zruiBMFy5~a$w{`qWGFeWs^v_eL9^t@3|ojmqAiVqU&u=YidP+=UMChpmfz$y!*{t4 zxdA}G!_67YC)o%ws%oJ4tkLmmb^Paw3R>y@Ab zI5t*{KU2T`Q;yE%K zcXh7>ya)Cs19gA&Qb#gtEk&LfeQ9MC;c#B-zNbkb$EoW4dY5eeoA#h!WME;CpOzJ` zs-ziHnl!qOZR=FO=RQlhI2vH7dZf-H&!>CF(HuP~n}0mLE$5pR{NhH)e@?D#zD52A zqe|9Y0L$8`@g`5sG?U8d{f1LGzptlThpk{2OY#Q5lD;4);ejm??H8R3T|;f|8VsHk$+rY30V^Z!NFk&PxY;5o>#2rXa}KH$z3_(O7b5es3gys7QbcdiT}sV}ACURN4R^fo0lc^i~#Tot&`3JSLkr+Wy$O!?7y zioNGd97q^Al8u~%|5{Lz{W;Y85Rc*B|9ic!0?^RrScK$d-iPuJ6sERstOAARmOaOT zZeDsrRr+l|Eq6j|9=jY{?#X&ST4;I8z^$HIVt}FvXAXN#OE!9*1-yJ&qjQaqOZ(j- z*g129@mmBT=&P3>24{}=ieZv)buL99;W;m8QJhpmVoSilg$BtVHz2~zYQ`I9*T=OK z6NX+;TEsoR37@WTLuD|gG)DB}Qs1l4_l8>|2wuKl*oD)C&VwbT#4wCK^uN3&@~G7{ zTEaC&3U2MNc(wc@bd%LrE07>311p>12hAsT zf#^SsK3*JQonH=QU^h&r33hfQJkjMH461yl66k9$n_a);TV6Q)fZJ*kpsO)5Fc8gJ zeUWGNu^QJHKC5a{WwuWe=7tTvd2#5qooi|L8scR;l;jbMl+{CXOw_W4897(#?7FF8 zz@55ba%?Y!tJ2r`qs7l=-#3^QIRuZeN_;gtJ=YqEkZiY5jug%5Cc=YNNMDY#=1kQV zOFG}as}f}~)v!K3D?1m_P|jO@msfrC(&i}Iu%U`AYGZzN@)6T+u!lGYh0d~Yun(7wfRJF zhgw9Kp!hjA7W!Z0M>nT3HViox7BNSm!N`Ajw)|n|8-;hM+?wM!whGTSVp9ItB4UrX zj00bQdtuuL{NsoyL4nH`biMV>V+E*e}d&UT2c?s!vv6M50*8PRIarbTS~I^9-)inA$2=v786KV=GSv+0+> zVu@&x8tX>_PwM#*g}Y6G@7qd}?T&+4Bg>vOG?lY_QJXN|Vcu;m?j&qPkkAkfn2!x` z(zC&Aen}8X-xss z97ftMJkXx@?7Q(O!t>Qq4Z&yMHrR#cNZ&mVa3efh#qv3y$5a)&TN`zcR1P(3%QA)2 zPbh!hzKE1rjZZ;&>S6o2>pKeP8z{S;l|h)iMj|vd0w;^^dl}?+ncH1+D5&`DumsG8 znfks>9DxsF@`vDu_pSNF>oYg6y43fMz`$LQDNm0Mz;dMDK(|~U^N9^cfuC@JpAtXf zLu2j&KZP(wXHUjz86>divjm8ljAO8CeZG-TuCj!Q3S$qrejF~??`)41@NrkXiXs7S zctdr1^KC85@GdB#c46+~)5a|==n-s41C6%_<-Y>R!KG2(X;}1{;FiSC)Qz^OzyfVe zuH6M5-O=Rn=H2zhNl1M6#?Ukx0B;b-{7KmvIMee_0-;A8W1iS$aW(Io8BjuZ6T+as zS?JyT!i|;2_$BC|_sKC(xpV>$S<1f(Z#`yE2PbH(dm8@H288s|E*&|cZf8lFmjJv~IKWdTCjzlz%?rbi4u>rkt% zeQ)kkG6}6@SQ;<}TGX<7(X2k;V;&RKvc6RFnLf$Znl`6T&DBS=P2hq6kzYqKLp& zJ1j2=B{lJxr*uTUm*XrQe`({(v0jM1tUeNrzPT1`eI7T(WDJ>bX_u&xdZ)R;Scgb! z*0tr}K0LRq-e{XfAOGtIbvQQdx!k2pE!k8wPH}O{XPHF(xgZc!v@xwsM3OKt!J|uE ztvQJ>66!kNQTh(xy&QSHOfIHY z(VJIgdv?wuHT`Z(!xE_@{hBED`%iX%A}{U*)DaV&)Sr5n3k{NK=CuJ zQ7{p?)(?-O}*Rdny(yViWhSu0u_*@4|mN%otGC_D(t^&SWS}ak0Dr-)<3G%sc z*QZ`nUXFpYZaF;p^r_UY#;*R*5n2ap{#`9jl3oi}Q!>;V(MZO8F<%n8te<2eG|uPH zKw<=LD9cLMr;n#ETT&e8Pg@*jgpe73E)C(`?=V6C_e_OF!&};~n}@3=JqZPFH+MFR8TRDW`> z!bwtW0O2W$bUIy^t4xLd^N$mf1?e-SPb?UP^WuV77PmX?f4tL+iE=Ax*%rZ+?Uea3 zE$@aFddvF}&5amd91amJ7JnNXQ@)QGhaVo-Aq+3>(UHdgb*^7;{T-uMR`(m0i(rvm z^_~r((G3BGs@W;2)09nZXza_*b9t7~XI* zh;EiVRc2DXj{g}G7nH*&a)RDjxNRhhp#h~A8`Mcc%$PKCr~|K)FnN6b*4-uSiwSe$ zw29;yY;C< z!s3b4*snPMo?JV4Q3?_vIFLyXW9#v%q0=-Ti|3is6Y>M68Z<6N1#*_yIa?d%qy9Yo z$-nrX-I+2f^COIjgxb@v2E_ zmPGL@?%t!`u~%N};AnK#6-~{Xaul~>ZA)!$e7zGT9KU|_SjS__WQn&JWEqZ*`Vwu* zvn~pq^n;QP_y}zMdn5+!ohSTKXn<4mHorz|*3vzC`+Xp)gGb zUd$tIz>uNfQO}u_&_aW4HbU>_GS2=|^(Kr$7z$a$SM>bALh;>6THmwT@w*g7W!lX0 z^Glk3ie%{|LY*I)!!Ru?N;f-0ADj;^1fR$YW06r8W20LRyZ2=^*GeqF@ZtqBRUwk~67lLi}Eu z{op&CI&^v@!a)D}>8=-FNaPZRv*E(Cl_x)csIOq4oQd}?UGNxXMZL}^<5|>!4L;VH zLfC6UzvIs1J_*OqyV52 zsE2u}w%zwlX+N%1IMy&jK`t;?-p!-??*c5GiiSW#r2~q%<{m^(s<2_h-!vIR&2eF2>`U@auk^zIf*Zgcrx^QnD-Kwf=XPcE`fG?-5|-TsS`I@9IjW z>g=~oyJQuj9lR_8DeS#5-{ZpIet`P1X?M)hdU$er+*b$CJYsu94{M}xJzwd+Ttm_M ztbgl9Vz?%mIW|82eyU64mi}b52LE9hOo&3N00bVWtG9gae#*rzHGvvldr5$zOci|z zj>6U(0qp~K)FjviC(hpUH@$}0b(<)M0g>Hr-bKUDhBhOJqbVdFxFls+M{hqgdpIr^ zQ+V(O_swDQyXbIQ*3VPAys&Jf9(5`7l6B0day=t4nlzd;`$K!akoO$T=oK>Xw zt6&$e#bjqfM1TR6!Oag6jEpxAe6PB`=O5KI*74mdYqbKbo_~)&oaobL_Y8(fb zzpyE#C(kMg*~QG)wKZtIC-AX*)lqtbE?xO065Otli?d!ut(T!XD_i)M4(2>VJoeK8 z{M%G2J-x3pjfYi^?+Xpf^S(X2nu(TO2z;BDV<7e7#FpV?7jEPyXJW;Z5b-7aIZk}y z$96Ku^$LckOB!~gHO)~wg$(iyEDWa2{7y5)i_$6P{uS7X#3!nG`zgK|!g(d|i%$pY zm#-57-cKv(<{h}VN(g(6D>}9Ds2=G0)<0xx8UyXPJ+9;B)Ge~yIUZ*6M_YY;1=B7AwYny$l7b~b-%XH zx%UUuXtTx~^Bwl|-e25nQ_#iO36nHu(zgNa`?A%pKWM!d2X-cQ3(bHJhi2NjDJ+ilW=FZm2h|V@koC>;>uuKt~w@OnYIe*k2AMMNu_pPL- z+i$N+@rH&q3~W54I{Bo{8hR>lRF?KYh-tmsVBW1fc3c+JMwna{qWvX_ug?Q(Yf^*x z_Um>1{`weB=1M{ipBwEtN1u5UBhQvND^BLhG7~)vPb4XI3$23I+%@55w)W1(UPNofw+r{oPLH_s z5_&ENcY^PVk5wm&bDe+^SH!46@`Nyr`(7{ zp`evV7U2`LXR)KA$sblt>q+v86`6_k95!-5*;=42AIPM`JCJPMI-nJ{oF>||y66Xd zkJbZy#|LrC9%szn(GFs5;W=*aG48$`5;)ZKyZh3}$QzFpofLS^Xk8sXq(^L%F%)Cg zJL_tuMzn&=jdth>Gj&cNA=u0j(pk+vJT(KbS4cY`us?kG8-mJ3k8z2J99SmhwxB zQ%zo=-PP)B`+Bq3A*&+~9xK)v*L z{hiN8JUYb>7-ed|C=u9+=HXbKLgWtlpP^(5bldR0w0DC}l?o{aWe#SZ!VT2n_h>6z zoH>tkvmD_zh|P^tliyv~&ZFx$9iQNNur_>Utdj)Es}4yvnw8tj9_RqFgRU~YthmE_ z%)j$|K!XzQ3PuqtRQm+Hho`uSMaVN%h$|w3M|!-s3{mn5D7uU{j$7_VSpH^x%*oz+|rb90ym<2M(KuztHA8zfQ~ z-+TO!FQX~d(z&aRfqEC}aaqjgCZe%lAYu(HRWux=n#~}(-UdH3^EYAZ zypV7{qBPq9QIL(fG#_}k@oA=&D)pE1m$kxfNdp(p#O@O}q?Lg;eea?q6ZOoOVkO^Y z#e~FeY4?21aTgOsaq2(>E*5X#MzdWcSJI3}epCKL8!U&$%|IzdF7HaW!AXGnjaC$@ zya_4){p1(q>S2a&OYQ^$cQCF=PWIy`;Rd!8^^-F!_k#Qq4l4z+`Mye$hQ~uu9qmpE zsGpLVInICAJLcFD8MSm+HCmv*I4(vQ@WeEG-I~L>0n;>tM zjbAwsAV2yC$hFx15V9FqBk&RA7~q2IT4rfbAv4k*rvH+qvZPHymhpjx_Ima^Lg8RW zGCfs%TD+VH7M3$bg5QHv^BoQ6p~gG7bjL7$*T@&p)afp1vf8KcNzzUy%Z-npVK0}P zrGw=N(`7Rb4P&~h9`h_vl;?C$t}49BZrQ1XIIyEb*0$3&38Z46pZ2aRf!q7rBB^a5 zkEuuYC(WUXOhin*G``d`if8m$zr*iXHub%y?S79eKYE&9zHguWfSZ14e#C2kJbef; zj`89#x7wb)E2hBL66^Mb8?}2st6E%9@*_IzxUSx>(&eNCxerrBh?8A9x;~NXWA!h< zg(7FZb%@B8E7;-!2+IK3ppd_;sCNU=8Vd@~WxD-Debwad&v5J34nRkKQz z_N;BBICdIlxhP-IJ&_pV9*jlH{Oel(PeS7dJO?qHwpeLpudhAr+X~bKOiCiJg!Gal zHK}z(9hf@R9ubK27A3ga7BRyI;AlWrfQ39}|LP~OrZ#NWnkfFA`GJvH@zIF=wd8@X zaYpN>Kk(=%FOoU7|RVAvnZ|C8>s&Pj{4xb~U*N_u;1Zh80{ z!0-}M@+m~*?JJ+i2$*~sJ_c^C18bO}6HB1?>t|rFdF#(bb08AkRHf?AB$Qzi&qYz{ z#gy)lkRNCCqjFK{XYm>m6^Y8`As3@J!P?tve_yQ6nwQ8(GhI@pc>Ll*DIAjgAU zpymJZV2>>A>2&GX4gwB}3tPUDEOyF8Q|)6 zu$(M+Qd6iGXaUjbKdm(zHOIaRhvAbF>KEiCbKV;k9d6_MI~!`z2B0|ZS~@vG_-m}1 ztr=)2Ft!|a3{5g0M7bx%e&@2=jqd!01PIPj28Xi*zIN6>M?K8kI?sK1#}i+wg)iRI zwzBo=@%z_N5A_3eYy%S-c;y=@+SmA_O?3V;RU2hMyaR_sfbV1eZd&T+Oey6O{YvY zFWU52UFV(V;N@9t9nx|vcQc3hr|COh6#8ulFsht6SR3mt(iyhPQvT310i8n1>tedd z@zzuAZQ@3|qm$s)u1X1a6aZ-urRWF>?1cf81vLEMaHrx*j>*~LW`5)w5j}0xOT8r) zXyaFexN&&d^@+slRJWTINFuUo?=~~zOZQApzX3T2W;5E0K1td3dVacpWgWd4I=x=; z$)~A~Q3S41KGul^i!0bqx^rWz9mh6+ZW*++GvFLpq4`G_x&X5P1I}5K@>m&EtC}k3 zeWbX|nlJ7d=j}tSl|h00?SvYB3j6~L{Uf#RzdvQ`o;OO*)}Mrze?Z)w$SeagyS7We zvqH7Gv9UKgpX{Sv|55nx3e{E5jlE8ifV!}4rNHLQqfl)JzUD53p9=WitLRqF9g=r? zo1C(J2sVA2gUO7;Z1H#6N@lVqr@mnw_m`1ftX1#N02m3Rx-(!aBDfR&B|Er%nwAXe zx8GjL=ycqStTJ#!I7Yi#hC> zuWetMX&_2)5R3NvTi21aAD9r{>JncJoh`C{yM!lj#R0a8fz*#7|5?a}`ZD{iH1eUJ z=+wxjIO+B|zUCIj8yW$i5GcTRo&8AGR$e--=JG8mxNoWF9QRH&CGx*_0p=ue;truA z6~Qm!H4W@5>{nQ-zlkej24j0$2Sb-v=<3;QGQkxcxMlgY|4tQE?BmztcePZyKu~{w z1ag%J(nXl&Wg=x>bCDw1_Hca~kP?FZkOT?uXz53^NcDg@i{1esdL8@v^oUGbh4p}{~-vEzP+WOOId?NA<=-1qI zpfaHPPv^vyfjl)CC+eKy?UIj4{PM^Q!BI@@obernph+VlM)syaDy&RLjZ@bHFCL-brI)HgiuSZJYT%^m5{n2KCR7Y#b%uC7Y%2_wH6h!Rg(B(F{2NX*E>WDdhMoA4TV^@6iK$ zx;bq0w3*O{-ig#6u1MB@<*ecYO1Qd;kOd{MqDO)nE>%X@TPvs(&5?{I#uTNY>o^ga zrLO>hdtc09YcLYm&g8A)(Gxmm6UFHcAn}EI-U3FwMln6Mh1Oc4Zozyn8=F#wiONhB z(>H+ts5!wdgF~N~!9DRhN&f4F6>Pk#zbQ+N?5K;napC{u)PIOpQV#-(L7?=aCV(f& zc`)d7q#;n!&>i)@sD-?iTwU@{I;3zVaV@!MVx@<(;2Dt_pyv=VYY#Hu)jZ?h*H^=! zhs&jd;wczObk?pi%b1b1I?3S4_*Fd+-nuQ~Xhe^OBa(kxLcW!W!t%Ao>%=UHNuX*S zSppX1TARC%bQn@>ZTCho0thgm95)~W#K4We8hN~ym6`$|=*%D9a8}Z=FIoOZ!?v7e zq)DABN_B zy|@RSs(F?Lfb9n^`?75E3hpYihGU&iRog!myQo<1&Pq2kH2?Icr5&P{k(ZlfU>F(& za!ZM;ZC^e7lP@lv4dSSw>hXvuyH0P7aV`n<`WxNy}?_WBy53MXF zI!S(L-3U3$jJ`z5zp+%_{j0RwTbh82`qi8tV-h(<2Rfpq<5p*|ICM^pas0GnD-5;l zA#V61SWFfiQ!CT=id#}_Vrju~a1<&_L*R+6t;3SS{4jNNi>VaAFmQ+>KZec^n$8b8`~s=ckNi;aaz_S1&wlE>g#J=MSa>b&iewmZa~ zrHY&+_#+*Lk_&^2&!3o_vC<$+z1`DP<$BmB>9OzWdY$wu&DJ%K0@=i<)wM9b)dFC+ zE>P$Q9lQ0ruLwTJtf@_A;Lgs&!66?Kgj6vQ1DH6QJND%;@plfSQ-iHx8ujan={_e7uO)Gn9vpH0Ia6EegROppio zO}&EUe?~qQ5OgJ#?s|JW8<=@;;fT}jB-l0}6P`#5dEN*)<-`*?2 zGKVJeK`??+4Fnjl4NURPrD43b7X3ymvmEskeIO1&@VFjqbjI(4y4qGItRsE{Cq;f; zBzi%L)Gn}K+C_XN1%Lg!`|AtqJ)=qKoQsL~XaM3)sN@Y`R5-Y#@-}8({IdIw9K0l# z?w&c)AQ}ab)P#ixtM5-<_c>I&>YsX56-q`s#=da9XNEW!Vr}IW*7=y@LO77?Zbehnn;J5+Ve{_%;IBr^RHa(TmKF5Oe(4_M~ifgO% zj~mx+3351i^8#M_Ef0Wquz@g%Qg$*aXD1`DKJ4zYT2(c-3qMaLr@9tHUUyX|yvW^P z#U*&o`g>LxbYZ%9G3q{i-=nw;gL4mG&Ql&zA%|k11_1OaBSaoT`hy29kO$EJSKsRc zL3OM7C+4CdWYQ9K2J*Mjj!mvp-G3%#TN5k!<>_w^0kXI}WxP`Lky1gie1X}C67*V4X9p6TR*CPI$ zfYP)B=?`9$0oeh=fBG%%5@d9W7@i#DUX6QXaS>U^zsXfna9$4sEP?=i4YgZ}JnWQY zHP~F9EU4D=yA{`)o5lZe02|Q{etOS-j|g|L$>>ly#)}nPs~e1_vtzMFQW1Fl0^ml_ zN?gHFhg4;WRJoD?HAJXjsQTF;*F=@D%Nc?rDk4Obt=!GtaxBW_jc;fD-c%!R9STjK z0Rl0pKbOM%XMz}_pOQ8EVDvIJHTy{;t97FB$CGv<<4ReM>pWTkF#{_VdsiM#*?z=< za}#Vc)=;hPsCi2q8vdfM)DlDmHD@iL>|24oLc+|?`3PiljBTV8o~#w?K|&ve>{8in8)aNl#Y1$PP#jq4_)LN zGIJ*dA4l3S-g}TWFCb6Me-)3P!blxp z#t*Ek2RZ?w|9TO=Aoev?A;$bpKlkC*&dx9|cjnA5xABRi+`9W&olyu#k=MUP6Jz0b z!Z})c2L4sx|0CE1SysSH!0jl$XE8hLnHnAJSB1y=SldzTN-X zBa?6eDy>!aDuQ+TN<|gKazz>Hl=Jg5*tZ=LAZ13_z6k^`xsFs%lvd880vo{zi|jsE zk}<7W0EsGChXY_BcpS(o=AzN7WWG@?Y7suHA4NimPpelhX&pG61$xcFw;Vu(o`KIh zcuCyE9D0%GhV(Tt$yvZwMiH!)Dqy#q%jv02SvJgLkQ`ep7iVORtsw+Jqz>6_3pySR z-1q;mugEJoEyMBqITS=>@yS?ujgbXq4HjlZ7^ak%4-UiB?%^gh|DrsX=XUbYy5$R$Yp2OqOwIbV8MyQA&PX zZbXhj<;T>XiiVW5JfyU!djEhZP9jyU1`r@JMV)31o(HviKE^wXvW;wiq&EfN-9o7z zL3{^S3F~$533kKcw1A9^0HZ(tp;i$RUL9Xbb3I#XC%>EeM`gOFE4;Jw8DhzP1K|FJ z5_twp{?86OZ0=*A{F_9s7W3Tnq26JEN=}lglifeH@!LLP#s)Ck=ud5=sqqj0KWZae zE%e?N{Nd{aod~e`*Fh)me|yjW`j!kGEE!Gg-Q3Mh?EwFMd5rx(o`-uHPC`ODonQl6AB*Xf6hw(r#<=q zG!ja=;^+G-YEzYJF4E(PKjv7~9I?bFUVtFBciL%CF~ER_Muh!p4 zsSt3)Y<=y&cm@UvEAFCQuRj700JMzd^it3=)Z5#8#iC)Go1+yoztF82O@n8$Hr4X* zaMKD#JJ3M~9Z91NV*#U%a)4j%>~bgYe&8MZa!+G`bs)Q{_kYGikc z2%QDa)yet(Q7C#8Om#Sv+bE}KROP{;30YVS;-S~(Z6a8%WWG(g)1+Gp!36EnzCH=9 z8k!#s9pm_CnP{fkRj+887GY*-k0-$<6|__E&q%K?NgYOszlMiMqvlA<%U2InsaOWNEVL^a zQ?$DUV|!Vgomh+w`2(-E=e;MohKZ`)dq167u5TZ$&K-xqz?e}|B2d6cz(};cngep* z-}je;Lq}t)I=(!Q#%WTm;FhR({uHrj70sYdFfs=9|IAh82=(cBx#uceh%GvxVCb}V zT@9h*;CMH~z%)#sPB2Zx;>+ebu93@^JoG)nb|c??*`3Me z$*8`Ogj)PoQSYo+{~Z}PJbTlbCGnaC=VA9y@f?oZ!8-5+am|@19aZ661C;%T*{=-q z%in-}r@#e!za>7pN5^5F?(z2`0d5`$@i%~A$^K)Ji>zfJ@qn3TjK|y< zotq*vBtW1B#(L`)bl@VlTUMi%cC3!%8x0WDFm-sGO{fFLSirHaXNTu0HUSxgV*#8I z*)d!=HQspf#3^~bb4t4A7s4l0J+sz>dH9s@n!E@w%^A7_7ql{K~AkE5jF! zRcgG6Ywi{Gn~$^aXJ;S#3%j15f+xh9YZFFhO%%sbwvAdlo0%V0UG&CKtZ7ykva3HW zwf$UuBtf-fn@+bu-5;AAzlm>Q#HuUn|7@G8(y$|0r^O&%Z*kXeHGvf7(YF6$i5=VA zAIR@h^cFZrnpf8!T~4O1m^Eb1%G9V6j6Y&vtcJFdTkIH`uwSbFiPCskYX0^X4={I@RQPGi+_WJ)c*))XX|$m6EGTAZsSaEN z&4Y9#meobILgdfj(xyZtzi^UMlM%|QAnvm@MAe@L5wv?vpMQ6mR#gdi`n@N5GN@1ddSzsxrGoO&w1@~t|J0mXzN;6;s|lz!o$Bdw6SJ_b)?!MB_&;V$`@c7HmMlk=1QK_}eXcvdYM zhPMec>6|WY33Fl63ZR1%Rebe?C&PXbWBjd;;~7-IP--viTiKRW;Zrse!+Wo4YR)+dg2XY_UhSZ^uBVPAi%$+q9uJ?GGjL za;|=(!*^@R_iar#q57Q5(s8xDV%_|`TB&%#l4aJ7=~9)PLZ--DMyrdjj{Crv-AzWq zsa{E`ZbYnsQ+cfWjn=RASi^6RLB~Y{oj2x8ItN}MEg~*t*hvH-dDv^G6blfm1sIqI zQ*898Ug=BJQc|Ky?r_g}&Ajv)Q;_npDdll5Dyj2c97|MZal6yhsWs@x-O!T`7a23+ zB}v11C^PsxvY4aqiGSd6^UoVvSV5r&i3P3)MeZg9R+CKTWMlkTax4tgU5uRvdK}l5 zcpJ?no|6(w?DsVw4Z<-)d_qK!?Ht7YhE)Bd1m*E)XF*YIqiBi{S9fpI$LQakXe41uw6(lSRB}~`(92;YCdB!?hPE_1PlPD z4$$ANt16buNQkM3H7HkO7gL$cw_zIt? zoB7k>eg?`rt$V1z1?5n|hhgo>0bl)%geD?S7|$T7&;{mq9JH+lgKx{U<6zg{wQWPO z=ADZuEzy!3ONoJng&zngh&n*axl0hTAv{t+>01f}Pqn0ycL0iuEuLdvK$u^ExvXj*tyjr6 zcNldD2rL&JjO?IK31&38od6x^VX<^261x+u{L#;Z0iV&UBGmCd>n*jx?%-6cF^aFk zySW0;BSb^hgt>47wYk&L@BuvW-42m_duoB3nD!X3pFH%9Db;Nt0Da?$*!zX#I<%8H zMg*ATk*sLpvdYV(slsW~rV zfB89xtc=-S>Xecy_}cGX@2f4V-yh|eu<#Fx-G=Kl^qG9oWs$ob%gr%iR%2pJwG_Nj zxM%xV8n83eeRQO+Cj&!(n(kqH1NNkH`>^G7pRn`GX)dLdlsK^z>Fl$9m&?gv8Z-+_ zPH;hXA^GoA@y*7&$68e`LeqfA5Xz}_C_E1Gdrrg4s*yD!E(G{_h|fQOq@UCvFDF<5 z3H-L;C(4zbcR5u;%smIO?iY2CaSanOX}byR4=4muaiJ(~2OTrV!LWr+7EKX9Jzm}z zvJuv4;{Z+Iv22y;NoF;_Pu4l6rTm5Bg~~I3(R7%G_!wW8A;qp=+CDCd*!zf(~4uWjK=Y<$}bey z{&k+aK)jT0lKi1mR1!5>04SKQ^z6Y6)I(NO$S$8%qUQk| zDqwf?dTR4pbx?t2+hs);R@kh^}zSLTAzXdgXr=|ymBPKsel zQ!}6XFldo46X2N6`WCmCxzuyJ@RyUq1DvQu^pyZgO7aTnOkXqxHk{gVSF9O9zLMs) zh>M!{Em5QLu+Kw$p%>rWw4!$tG)mA{DWiCYkd79|}8k<_|J;#$gu zAJ3wTWsJJv$heNEwi5r~^aAmx>EavB5oZFpXB3uh4ug5`BS9%GC4JXPh)*-C{Rh>h zbBIVve)?og-*_EFW(et>Iq>4JnxN0}nFBQZhSATt5lH%+^RgF?DE-n4UPJu#7~is%NPE*~2;7kNl@3o_QJzgrhzi zvVu=K^e!3fwa)h;R-`=NDSjRIsxQWFRy1N<2@hx+a_|LueDj!&|eSbC-RPk zRdvcJL9Q;S1OWXb?Q4b5ihXnAM3~EbD6hPOZ$C;>dlfYzAtO3MGf6N$VCDgyZkPsF zTyn?d{>@MIpN;xuaqdv-&lN|H!B>)0$)Rir7yI0Ok>*wvz8iZ{ z6v&ZbSZ%Z0RZ8V(s9*B;GsHeEM8D%Q}V@b+5A2x+9Z$ zmhkcI5e{l1(hZ)#%T=(=s@1#|jpD`xEvp;VUfiMK-IoL?%O zgeMO4b$zMOnWArWPi`OV?>XC^7lV@5I+kSd5!sIp8w6V28h!I_G!Nes^6Lar&W_SI ze;f%G5iFBMI^&9D+V*)o$GxrY%JAuQ{-%*Cx)<~?DwT)?8xdU(d`f24wcw{pi$>oA zY96m~kqycW!-qw#AWF7iGXsRPpx2pV)ia;mHxMz$Vb3<^a5oq}#THgRY+xfZ4RNJH zR;EwD8x;2S^VB3b5o~_)*#PB>WsUehhEKrjSM~JsI52HP@e}B_ywJYcD-12%+v(H_ zMl1;}#Q0h%6B8MdYLXTCc4l-Bsz!O!3vSQ62$pPTe5JX}4nO)Cb#H7$Y^xbEQvn=% zlRi>GsE!sQErg5;qy*u(DfPg^jN|m?_Omw>#U}nQ2>8uW z$JM^tJZIPW_mx&BiOMV%57&Cl6%R*Wx-_1>ym!v#-}^jobsh|qDy9H+Oa1 zooAlC6=-oitLz=yyy6WF9dW{W%kSy+H&DHr`w<*L>SYPz{^iyjld+me;iZRJ?s4skenM~e^P_Vd_fd=BqnR(3X$I@? zyoy9K3nPosOC6!?eQN^6BZoZgf(T60fFiDAfm8OU4#9#RK;-X&+YwO;r)oFMlOqSpe?TOoz*ZXHLOwHhu zdR#$NC#_YC$E&UrrY{ahByNQM!cM-o;jLaEt<^SFp_u6J@XO}%PKFlU(srr)IOYXO zh-U40cU(DMH|&?I$lCmK<(t(gJ=3;BB7s4&TOt$63~?kjOF>*O!)B?~4WPj(%^(y} zbm`f|7s_aXTAMAA=|Jj4Lei1j?Kd~IRQRQJ*e>+_QVqW!mctzh$)?E*^@yBxh8Qh+ z97$XIG7ThJOHK43mI`Vfv=Mzb&CYwb{Cau>FdZJ}bB%*7M%8wNup90Re`#!D9=he1x%)=nf&_I%UEt87W?atI#|D;fZS-mL9Cw1iWVaI!&& zA^if;uST?xC>^F9F=qh4bGV1yKUgK?7dE@~#4LRa@p@O8c^KzVEBPMcLJZ5NbHy^EY zJKA0jKAGx2E;s9B=GCjDpS<&6tlxaNtk*XUy=QRsE9n!J^)k-g=~38FZ_Lr>YrUPU z^tF3-p-^oKlZ=3WfKt(6q|t^GMMNYX3Ud&d9z{qK3o1(e%s>Cu_~KhhF~lkZ5}gS~ zNxZ&A>H_aKbCuPIH{t%3gJv53-qec51&Lxozc`sFD|XSss_Y4);Iv8Mtiu_+l)WSC zlG9}?45Up=5VTgCO$xK#+?H1bZ0IBn30aNQBcHNb*wxsCv{R!iOArgwaP?N)5-ACV z!);_t*2eA_SXg30!@e0GS{a1w5c<7X;6N`7Opd1t4gOF(Y&-DwdmND;HXA=~dH1*M z5yM97@e0lpF}5_$DkI}i(j8Dd1#g}kVh6}b>l^Ib`VVXM%)@3KM+)cBK}D(=BF zCaLZ~(BK8Szm;+8Mv<;gsLwkF_nhHB+=`Qt_d>^G>t8UC71njpH4XzV}y=bfJa=> z?Z}MVW?AJ7pML@sVL$bIu~$jgCcJSQjcrf|Ax;7yrEO=hpAgHk=sErl1%`g-hq?-d zw802m(s3ACz*|Fy2W7Pe$S}3OR+4rtO}tpTe(JV%&jAS53!=+(enq_nlpe)!oG_v} z6%SL~DMXyj>&aa-a}Po-hdkMmZ>d__@}1xX>7zOoj4O}SUQv}g|0$o2VvEJhC-d($iN#V| zx<$*EehwPl!(kCW-Wx89va*Dr&4zQ2$80MGJq~#QrnyxNtr(#JRGsc25ITnx zts+}UZNIu@c+w$Ldmw4$I1Gqg*+b^J=~#3qQn(y=_MlCCm|L5_AKNJ<`!^$<(=UCQ zX>@(m-uG8zDdUhSCL#e^`sTeo)|zJT7S_tD55b8LW)~XWhm+d~DXnh4%E6E{j-&-> zZOmc(kY$lUb?CMuBmh#FKfLpZ2=vwZPJJ7SSexKOLh z_n8{H+Flrcv(uhK{3#t9pp>o~IrSY?Q*_@;5p`BI%8I{_WF^f~RF26g6mqUq$QDZw z9nw7*t0jIN-#BK3#_DSF?FMIG7A$DUDWb zlvH-2xDOp!+{SZH#Ol_n@>JV49B6pO`0H9lRMo*ocXDapuskLd!ER#Mva}23_kfc{ zWb8+|#05n|=)|hxw}>i)Xk-RD$>=Jkb4)bVK>?A4-&rI4Vit?TpF{iX1fv;eDuXe( zhfcgS7Bf!?giJrtRisjj;g!P!qC-ku&a4-ishSucJT-abUtrD12zUUDPE{{c#S-T3@_J$nPMB$I&0&nK}7*Z^wzy+LQ;)@Y6FxjpVk*6@5L*3(<>10e)tJR$Hp zh8zWZhyUSH|96Dzk1e4E;J+bU@pTDq5BQt)Uw~j`y@sy+G6%>z$G2bn(FoRV(`7kv zxuANh2ttMG9Jb8>2T7)Yz8bweUQMTJ-*>Gw>4YnK{_6}Jab}19-cRQ*PM@aoF|@Xa zl}iw$e}m&?Sku?w=t5`GGSKsfhSj+3)pb16+|haXSyN;ZD?V=!b5(w%Ww_T#NNsX4 zsXO1YYAd2EFUEvknRCoXZ_@~$QMf(O(<+TBN%f8)AyBtjcS=|J33Vo0ZT__?lo2@r z4mDMkt46U%x~P1U?2@uYZLpeP;A7EstkpWP4XITw{*gu1si~jtkx24zVN$4HR)Nxk z>baDhrhj7+*|8tgs3#Bms39gDq1C4bWdSNkbJ=8eYdV>E(s`OtfpwgIuKStAnNjaR zpBmF1>|<2k;(3c48c|DjFH~7>ibKY<&_V)-pg_ME714r!#8%KncO7-u0#`6rk4 z)RhoVy}E(hLKDmZcxvdwD<5;~?;yYObA4UeR!QU#sDY12uMq0PVu{%{PoL52EBo4P zdrMX<5SM(ql$9Bgj*+v|qAV`#xK3IbDbSr@>=lJ|W}kwHCx5oTWx;_jkL}va-+Zap zln(;XiiI41{_z#~_VyVZX1~^Jdd=7tgXIdv!dTev!je0^GZrP`!kfWRaB=CuR=B)# zd}}5E1SfsEvTPF%w4*b@vYUz$wpTPuA_8x67)(~|@%$HQ`#96KTWaR@| z{VJXbN1!P|XJDa11W)oc(ttUdayVhU;E~I?0z|kyq`=p}5zDtRMwM}g2wKb+Yf7Bu zN%U%dDZmlv_ti$PA4Sr6D~k<(&w_ z2xOhn%R5V$Eyf7>OFezR80R`wWA-v-SOnvIvVV=Ijx!NVMj&70)F4NefdodyhEcj^ zmde>DR1***dj<7Tp7B0?JtaoILs~&Ve1kB&vlmE>YSGJq!P_+rs6+pOcCr4B*H*dF z7CJat89Rq6nSGo2J;BBg)LX8~^)YVuj2jOr(-Xc4TT_DxZRD-di!AIp`vHeXc-Dz( z^q@nr5Pl3ZD1l&5_07yjT;ovxy_O5x_9h~RZZkYeR3`54e(xx4IT0jJpE)eDJ#05L zAaW_~j=Z?vUj3|$Iu!>}_8ypc)VG8)!tpZpq6J1xccM}H(o@!3V%K=^;=SLYT0cF# z{s=+)m}V6{EZU{uu=Q#l{lKDxOsZPlf(KrVIgv(kUMT0qG<*di5$9HVwh{e*JXtS>t2sL?R-g?OlDoov9d0q z0H~(Uk86H{Y+=kQ)O7r2wS@lf0|hqD#{6J~e$e$~pkF_HeDo5%zk3$&n#foXJz8&b%Ac@MDcfDs_Yj)LuY#Kv3!^X*l8?D*cw9^ zG(gfoiue|qA1?O#hlwR8J82l0Y*I!n4(2e57fCzrIEgtP?_1QIc3V{K^1C>l^%V5a z6&Cc@?+$#wwrul`;-DBCJH^y|_4nG#)9Uh*_uXFS&|dNiY`(N=VPMN?6%8R}tJuPL zmihyIm@8$M##hk5A%=*kB~BEfnf$vqa5Y9Vc+?EXI8h1f%^mFF@l$YLZatoQJF%Y% z_v~ZWggr;Dw7#OsiW~8T4lby1gh2!|&h{gy#B0FxkVbtbZEq6| zI4UjGK3e}#BG!Y8Xqm%}LkvfwJT8qSBM&E@kOz(F@07<<^NZv?*3PIxw+|QL+BO}k zt^)4R?v&0o%3vo6uoEI&vY4lQ?*MPN}@kIz{BL8_vHzyiO1 zcX~L2G1hOVpf`b8Td?Tnb~3G2E)o&n>FdIxcOf!pf_xo@uPCyi$s5h~E+0=moiNRg zCsdoyfO()yT2EaoQ7$F`5+g**21GZ-zaWV~!NRcAu-WGj%q4gKNbDm=!HrwQ>|Bbk z-02r|WPq9XNN(o-J>Vl1ZA+IA-o1u~0OVarxg)4peei7l4?&gLxT~Qn}SANknzvDZE?7ZfROJXjTaFwx4r*!+}7GNeZL{WJd2ru;ab zTUNH(nB9^Pnuc`6;4*=y&CDB?Ach5HXYv*Zf>88HG{g5Y#WGmTlpmm@Y^LM%ybkbx zQFwgrt7THY0eYNht7YE^S|*6nFY-QrwKwY`Wc^M5>~`<{#bN2FNgWU;v>#3^_l5op zEtRQgLMeo4Z!QAO{d_~`=%~zWs(j-oJzpl;jtG9kbxlY^HP$Uc_s#7FA|vd3igh|o z4qe~nYJT?|<#e`RH!iEVf#z*Fp644c9Rr z=~jA{jI`1VDvyQC>9E0V&>7llnWNtZ+)~4|lqJ=U`gD0m1iXAG!WNy-)oXj3^a0X} zVlG1~t5}B`G)-zvq8fU&jg0TMlZI$PN7yiU{f%=SdF?a0-7T&|f2Iwdl+y`4Tfjqo zg731p3(un+8MEdD;brZ;W1#o_g}BoS3Bj|3>73qu(fnZz|Yi(n=wwj<5#In12W-vi=GLqUD7moB=~@ zUMo#g_-pRcn5zHwSBBh8C)pI&4i_&qyj6NO$HI9;O28fk%J3dA)C!E}4!>lZi@bbq z$BIhSO%t%aH9a-U(HXEq0{HO5gB1lKs{h%&4HkCM;z=`SXf~Or)UPb9+GW)$h#LKo zT&y!8b)Eq;z+Uoy6a^xkgUQ*Z7(KTO^R$f@4KFWGm%}nmIJ?n_jp@J>3l#q&m?f1O zC(806lpnbI{jVBOVd0g)ozm7UU#7ZbhaATK6076EKY}}#jQDwxW>q~r7pq-|KqUt~ zDp;vMV5yJ_;W&7z0E4Xmo+@_IV^Z#;Wu8->>*7OqRNv}4TX_sEI|c}b8- z{O-joDf7ksG7DZrYJsxup4kBd1lXAWt2{6u9e4dHdEvpHbs!-gO+=V=SpB$f_wbU|!JR6E(Xk1PsAfOG)reYr)xUOU~?Bp!Qjmqu~9ES}&%E6||r_J#-Q> zahhx~x}74|ppvFc1ak=U&H0hV$t7vt<18~+w>H#f8UwIlL+c<4l|ZoPhv~$r4?^(4 zgZKoRN;!SpX3i9+3T&V_E-b?T1MvgF>4IM}MCHWLV--I6$OQgclVuguCv|iIf}p~&11dzB{~9V; z3+3p{Zi$9j=CdE{O6&X?Ri&pVEl)$W9EWzZhZqRRe!T#BHT4Vq|*&=UXDOeQrZ;UEng-MLMz1B*jz7CzS< z1tR|;P;YU9>@rN?k9aX>aAxnno5SWklTdJKc+&8M6g&@nw*WZU0}CV9wa2e`kfj_M zM63+kxeYf9Y*gTvpr(g9Q!{f4D?1ko zXJ;!fGXobvXa=kts>y%JqN$*>ux?OXc=Bu|g7poU-@yD8?B>q3lBj;;C!eT~Ala)} zkd(%V27}nVwfOy0D#k4}o+*dpHyY3t6kYrX61fYk+jschJ*}SD!$LAe(~*hOAA~{) z*x>aHYeX{NbBkPY@bd76KZkyrdy|bFg^TSxgu@*5$S39mgcE-rBkz)MRaL(Q2tE3p zdMJsKD~W2xBn}0=Q3wTOs)-|}rN;2_v*y%pN?Tr!4Cjtp?9l19+o?aOp=&|C8*f5; zYkEhrdJD7Ogy+kew_IP{v|KY;2F!_z--{!+AopkJ=~0+uJqlc%Fb8AfJ=`OrS_GCzAFb#zp!ANOr`y}x422dcz4%2bxS%;`t|KE1NPgR} zehnOb4yc3wr9cD2jHnmMXZFC!`+#53BO(C;GRD76vFR_Kja+=ktaef5=HD_;7=6dk zuS}k-5BBTOZg$~<9}8*!JIT8E4c=Egsk!n`u>SIrQ@r$V-rByerU%173@|HUrgg|+ zQGe4KT;hCZANNyteVQ@lP$JY_m{nlz0#hc-6-cn&mZbl|DX-{eS_hiafogK;XDxIV z4q{;wuIwHat31ELkHQ0)Xk&x|JBiTW?)_)W*zOg|(veUfhp^W5q)2U6an#4Bd%q+> zciMz~{Nw*rT2)!XLfVq27J{>_pc@CsI4LGZ4_89;7=WaY4KmmITCmXOVoAjfNA+u! zJgc0E;AqhnK^fp8fdrhj1MVsI!MrH101kM!xnv5J4AMK=J!Bb>e>c+Nf7>t&FOBa? zj^mcsLq%PCh+4kiTK!@f<_uww9UhSzWoJNO66hCdG%!Q%xY+yFhm%`tH?McSeqmbr zVWAf$FX(4<8dV>fYOa~NLwIji4Ckn@#%FYpD>q}I?GD?cn&WC%m@)}Si7=Vw)BsT* z!9UxFjrrU8BPaE-J$Ej@P1x65o?S#qm3?bsuKaKI1gRDRI$L~9SGw23GGr-Ao-SR3 z{ydq&5UQD&(f%YD=^W(YM<`~K99f!19d)`zsbTb zd~pJd4M=c61Hvdj0FfcE-~JuWKwpHLdc9RfiSKo)AIz=z-eg7c z{t?dPjZZTAk{y^#SfS$iT5O`Oyt7CMJ10c221xAlz2Cp`io2VvNYa6DBVmt#ut1W3 zzpAYzaWTJ5Kabt~Y2D?nv`GkTQ)1gqnv0G7megTz{GU_ns?)qQrrXdzTZT(MgWve=Y9=Ml<| zW`sNw@Cu2IyEhF}FPxb|fmO{?wb;~L{&hw%;%{WKZXlQ80ToxAhE3q=VZ7~P+53*h zew+NrqG(J0M()NV-UN!NwUYdGdZ82=eP3jc)=hLCEi51t*$inVu*Lm<= z2*l+^`dx&P)axDo)Tv;ioU;9HhI&G=f=VI+*6Eoyzkb?DtJhiFj0uR2oph9P;j(z( zml+zL@_evRQxQ~RZd;9U&rxx*jag$)HN5dYRa0Vr|zb!mD=CF@Xk zUysp@*hm$dr_=nMFS%#ReR;T=S(OIgQD5N(GP=Rj-c093G`s=x@c0Qv1DgL!0Pp-C zU6RP?Z=0u;?Hy`c?$vJVh1}FcbZ0=9gjWaa`oKMM4XDwCs*l?fOG8qq-z2z7AXPAd zEB;I~^)`@%QK?20mr48#2$EoW9gq33uH60WT!foNdAfGVYFGma|9B`hA36nPk|dif z$rTDHLNrj#TVky@lkl^9qsq@Ho{ld^?ML266%W>;+TR^k4_hgf)W*Dyd5#3kj1r~c zDjkVt(CuE~(z;AU9eFHSm#m8;@`iC!I*84Dyx-|QqHol{{rFrm{oeK*@vh)UMqupy zx0~Og7w+f2zU^1Vx;_hSJ9x{y-gb^Z7hIzJGvC=wX16w5;$1X~{JuL-x>ycE)B2Xn zH-C8D+RWN`>2251^=JO{Xy^F${k^B334+)ISBFak2KtW@?Q=Oy@y6|mX+BZT(moWCa<^}%R9wl9hWb8sURI&J`8~5#XnbN)lu0y%usqr`MXIwY2n^12@lKb5Kigu!6yHr;^%Sn1 z*j%VRf>TL1%;QLoM;S5i)i#AuTFV{vnc?c|=bb$~s*iuggtRUuR#Nv}>IC0aaJ+Y9MhiI;Y0H)ZK=sYXz9>5O%70Y?orW8a1z$h z%nDu;aulZ59r#v~aG|A)Mwd`B$P7@?_ZXQspb)+aPdaxD3JgnHxlH>&lh}hV<&fDE zT$5XB;s&d8PB*lp-ZECGZ5>)LYib!nWXD3>ABU{=2b$X2T)oZ^Ux_H0Op?AHIHmu*5pWydXnvt8w`3 z{0uE3t~lHGi{NFPIGJjh=_~(^rb7SrKi3cZAps2QFfoyU>zrUiyyKQcKU#EoX1(?m zA>Vuz?P(RBg+@`oy*>l?plNNhw~bw(mDRHaIb@7Yhb^*^Ty3<%Mw<)Xpuq@JBBb8Bp_I=+6MmuSMFUJhPQv zCK3JdyeN0b!y)(8m;a`|)(A1BP-hL@p81uZ@J##l#*Qbm?-MjuS0f9vxdI#$_SD+* z+5!`NPyNnM^+4otaMd=Mz!{rKdHUKb7-4>kp}}__L>>lbvjP)|0o=mh_59CnrXm|F zB`|b#c%&vvrhcQR=ERgz(j=%7# zgianT%NMK8A%|lbzc;^(Z~B~W`^-rs__^5m zOSoy(yNbElYny1`8F;nBCTTu4)o67T)=<kv9xD1gs(7P#YYShUX@d?AQdrDDlU!U>gvV&PG&E~k$kda9ubl?AFi(S0xR!=hl+5yE%Oxc^8d@-mN}p?v zldCseTs0Th9umRG>VHBxrYmNBN>WK=4*FrN_xk`P08r!YCB9(#0z8-mBVV-`yJWB~vGX9>sc~JY+#wa;-=BE;@$J z-$ca}ktjDqEeqN7Q*991qRptz5Vt4JO~t4$3C{>9Y)0_m1Kj`OdGJ4d#SbX3fS5{0 z!x>cQyZTEyl;;=25_^SWnT3^WSKWSktugr`hY)=P0Orcl(LVv)1 zoX6SaHLHBJI*xKGR!$KTj&fA-vNc<4Eb^?3tV6IUmJpg0(_ajwxb(Jo=AK``^BENhQ5dmZ%w^#rfEPhXUEM6JQCV>1U7JS@A z7AsyU=B5)FE1_!bWu8Mfkut&!k4D2~gUda1!lhQn?TSV(=rr&K;k{cbi`3Cv*A>EBTD>s`-d~8{6bF=?(HflPJq7>9k9ax z(_e`J2GVZ!$04=&fqqGZG(NU#MyS8)UiRtp3F#E0bsZd&1YG@bqy7GG8?CD+7$j|v zfWHq0%A!v{{)l9{H|g>}+twH3G5xvp^1ZkaY&tfk0#(|ee%yhL1h^+pmAXy%P57!s zFvR22yctH~Fn3Ax+yj0d&S~(^&MW9Km=F?%6cAxM*^}Oy1dkanz{`JV)L{uFgZV1) ziFgnYy@refpP2uMUjLtoUUU5a5xxE+di_WA`j6=KAJOYSqSt>!um6Z%{}H|ZBYOQu z^!ktJ_5bgp*Jkx$$^TD@Ufcc=z5XM5{YUirkLdLu(d$2=*MCH>|A=1yUx{8_5I!vK z!+!o7SvA6GWvunPxIuQIlf8)7gJ7rWbwBkX9fDZi6GeQ40)LDBV)Zz&=;3GKVw%qn zrKOv~IeZZFBr(h?%xAv8w+#Ry>q%K;_&AqSd%dsISDbfS)6BZ7bx&PN>^zJOn|go{ zC&={WjgKVb@KzZM!aj&16;ApH{23mgi4I*SxptFc<-XDE+409+y!1SJhrdI5?QYwi zc-xO*KnVV6gsyW)6q+UJk!2e{Di8Y{5?TfyCiNTK(h@_#_03Ta3I3T~p>&7<#rNbS z%Hn6FKd+1u#S8y{dle`#)@6M0$ou4U{dbtc78Z`OpxeRp7KCXU)Fia&2u105$1K|r z-E@Z)&tmT1&zOA&w3wzBk;V*Tv7W^dKKoumG#tZ1kV`fwgi%rDK6zjmfIr=KkhA|# z)p^luC0Nm)pRbsDLew0j_M0DmX~*L`3@!FT!xXI&%8zX@>R~YlrMPgT_j0oc zxYNKl9$?!71l51Ffd)1e+(;fGUmIw@X>G|UeKE4UTYoqFL}FY0foA**wiXe1pD#dP zpIX!L{tzk>=dW6$cOw42y}Fp1wj>8Zob`_ez_5wx;kd)!Efgrj=$^@r>yX#5**(4H z>RJzn2BSTA&?||4&65S`Sw#e!bM|_s*I8B^noql!ZcK6AY;QyxGpBY=W7nqg3V1CrzKp+>Fje`@aCIc_T^y zu|NR*?%%rKHnNj?Tcu4S;`-&yge*GV(4K{)M>qSkJM=CVB@ti=&1SU{EvAfEcKER_PtQ23rP&7S)G-T8rJir`!B9`zVlz&jiQ zXA_B*A*Rct#2D@6{L582uuQJ%DdfzF&~XKB)CjnW7^vf+ntX(;Dgg}52NytfVM=TH zVWYuFtTrZ2o(?YdwNr4hU`*s^PPP=R<`m9OChU)Kc(rZ_YH%0Yz&qL5 z8RwKPisLN^^ph6VZUw#*Xf^I7Hqm_%Pjak5E7|(|MPWWRJ zbnIVEPz!HZ5OWYb9kA>q{%hHVllE*1e|c+8|H`ccvfgBt&3a}#_VJ12zOsszz6BQu zkVl^wA?*n52vs6r{;$8a$^Ve&nee4xvp%C_744y|`~KgCFGYCb9%DW^a2c$9baalp zgy`syTk8()2M^qlT3XW#ges*@oIr{GxrO-Y{ z)R(~w0%ppzM2}X(0?5r*jAc0QM)?pq$*@77&|%yVYgynqif_d{gSKRD4uU`=uyC;( z;O^ItL#ajex1r1*ohOiN0!cU_AOb>-zqfyveGvth?NLOHAnA2x^4_N2VM$iJpm8O% zidAr=*W=FL664xK)jx<&SWg&3_h9A&28ksi@&FuDX<%Ibmc6C{6@6$r;mm#(*IZ#3 z3a0}Z+-G^@m~M}9TQPA_+9)Zfiux1F~ z!v?ZB7$h8xkiP>T<^FW+gq!tH$t-`E?oGlFt^G7(JR~8o* z3Rg0TlO{l_Ie&c6%kKiN7ih^YR?^{{yc~(#jO9BGPO(cH`1lp}Ko%bjZ&-fHT4t!O z1=LU@znb8QMvLbaJBtpI?TGiN$FCxLFkX4?h;Gy zj1S1J^t2!)XvLI|?o4DY!!VK?_DFkcnZQwo@onmCHV}Wjip(7@59OzJ&9iF!$+uNO zRk|OFsteo61>S4ONzIv{(RLp8Nt2@0sTy&AuZooVXemz;-h|H}VavEj$z^jyuBhM2 zs(N@l@$!scNKry@vHQi(jF$2SggAnsPeY}fJ{-*^I|&CN3(0<%@hzOPogpVJMY-|0 zq?l=`v0&%B5U+)PP~bo9s^?&;*uU{$~-3 zW@SD{X$uJQ33D~&t3iEv#&V+dQ6<&#Cnq%iF=Q3%e`cfW-rh!)QZMRD7 zMcvxYpKNlz)2O}FsWhY(M+l6$qyME7Y!$+SY7X$mer6zij*6km6w3`^R4UOqc0qe> zr*@k5ez4vwx%LctrSFp=xlw_FT!0-X_eQ=(9kX$kl(SaZPO&Jl(e&do_8d+%pY+e% zO%)o~%EcF35cgQVeq`Z=Cbh=0rNIcMcLMKoVMd>Qgyk4f$Z(^kkE9mRC7TG5*`M@B zw`4zjf83J2y;OjnfG=U0diW`EiiT#=5L;%fb8Xaoy+6^CP4HpDd@cgX0Wi%n7$}Od3|T1BULK}dwtV>#W;}(Fgt%q>R5G5mnZCx} zT_=p`QZ7m&hg6$Cr`_u9kUpFL&is9O)==-_=7s1HS)UBkZgb>EYCT@4RSPxEg4WpbamBXN}G zqWQYUx0-txiI1y1znWn~fh{OIT`-PR8Z)$BCS`If_BDr;P+P;+1;$AN}CoX84YOFw-t+dGy|9=+p4p<oT`7jajpz?3&h$ zBHj3va?Z1}g4&<4Zr;t6CUUq?q6F(q51mu#&wqsx@(PhTG|8| z>pJt3)kFmv`s~K9GSNtSQz}O>S7%U~RKM^9Qv&lHChrDy3vILBd$$*^d{xNlo5>`0Yk5V-eE~W{Yst~28xB#I zW!kKuc9P=hp5%hr@pJTWqXL^rg@%pTH*{!S%6f5l{^-c6Sw5`UUgAq`Hh?Le^B2fX zpj5nBF^@t}B%Gy{4@`znI zjlq^D#4Z7ZL12Se)id=Pq~>SmS(?-)nmKK9yGSxqw(Ue)`|<*?FQ^KL*FA z6t#sC9LwwmMU8K0rmGE6ZZTc!#cgJJwy3!N6a%|?RyTC@kKINV)mqcb2TGIa4~^tk z{}Kx>z=yhgSnh1skgyE{%R4U}C$Z<(7j&|H#XBK+xjyD-ikv{et!QqGqC#{^RpXvC zowPK-jEPwU2aoBYWjm;mT%2$)Nsca(+Mhij=2^)UOw#}u*ui-uH7?DD$||V2SWR`! zbfP`b5u&kAQij`JmT`fz^rAfz>gWf4wcGrce;snBhK*EJ6-9JOx1yMFxb-Q@&zS-H z&y+AJiS`|$E>4w$nXYYM)!HdbLe$B3zF)HGGdmM@WzR4w{cnEfW{Pgi5I^%HvK9T9 z$lE1y9FCd-sQU*v=XDO9obE1O&iBO~)gg)*_6f|(ZN;UNRf@Y^pFw;2l#c3fu<5w) zFTVQ?C+GBY+6x+pHr-sW6`mKh(JU%=QKSxQA4DbfPQ&_eMr4(GZ6OuWBw#9i&(V#! z$0HTz6i;B5#uDn`NPFqJ-X`uZgUbC@oR9>5TpRu^RbVI$w;aiDyBs^?_LtA*=D!!o zn<|k^avk&88^gaoVCG6aEJv*-@{aPCBHoPtrTU2 zk91k+6vhkncX;kLs;ytL>VSMw88Lq=y~W^ z%G9M;R~fW)vCL6iWV2}8rL;t|CWjz0bYHFrQTh~yX3{l^rJs$)Z%eE#@XQsp^Vu(X z3&ptXY!a72ub_URRNM+%GJivq_h+yC1a&a~gE0UM%B_2SEVPwH8YEs(NePuOB!6_Sdv6>b zsT_keW7(7jS>#^!bi^V?x9(y*v6x@aJCxD0%x~rmkO499Zgx&YiYFHG0lszc<(m@< zA2n5XSgFs6++Xd>kf}HbXzad&#RQD&%-pVOT<|m#6S&;HdmfGJLeCt>D`aV_G+kca zo3NH?rUdGDVwNCgOJ?o7x10)Odo9jxlK7*A?feVwRG@0=mP`DYocE~LLVy@xT!&CL zJTc6;7?QnlAHTC5AJjUpBpCdrJQ5y8qMdBmaP}ClnrV@toAX;D(yx8%_f+(o$*c+J zo`wA~KW1HqR0ql{3zmcW!WnJF^a*F!bTR_u<6ziTKg=H(n7-4(Fhr1Kl1GyO(Jy)f z#&y<=&H4SS#I(GOq+5AKzr-4Mb`0H%-#Vw5HrbRruDEg-{yMMr z#J0T85AP@ek!~cMpr-#aX7QK@Y_FYQ-lm6SSacX_i!R*BW38=yB)ANRY1g8~}}6Qpyh z*xrd?K6f9>igy)F`pByOt$4zSf>WNaGcnl>X1P=2i z&BcYb`O$k+G3hl<-QGQ1Dh0r_P8~3<<6_yzy!mA@n3FX2QA3gh6;=bIr@GZw4s8ANw^(NPccl4_sBddB^3 ze=6cXORMaRbn$=pBWr;*UVoP*CVq5Y#_l98LB2;w8E>0*18yw(66|ddTV^y2LI* zARrC_TZ5AS8i`VftSZ=d2lhCB}`__VxBO_)e4$M~Q~ua&mh zdJZLqrRovm99shioB%Iup1MxmQj!j(U~S_yUePF2TcZX95?p{kw8;U=q5#HL^z5O$ zA1%3bO#?BWz?&a{&j|tWI^39RFG&Ramnk7{#HcOHH-h}v#Ju7%px`7#pB0#Fz^me4 z<-PEi3m*^BDx*)agVWvausJ5|bt#DcVtJ1{qjUo5SD*qiKirUN8%$a-kjkhuq)wj0 z<~>Jx=5>B>y;R)2ay=>@{h1I<7=T%P1kQaN^kN@9Pf0e!S3scR&=yl{%xh?e1F~K0 z+L+;-PozN@kbf17QoQ~2e*a#uGJ8Ki6OvoaoBNV**;3QwAhR$=_pxC0@{XfNIVyS3 zdl27C`wpEI8CJsm@dY8gB{W|_C^ZqeGj%xnE zD_4P-C9v+Za2=4etWzwnDZP)yJVjrHHiE~YMKEdEQ)GBMf`NyC_$MZ@OTGt)w`JF_ zp(i(b6VDwpnWKwB6)ti70bX1_JTpc+yp^`K?1QX++4%Y=4@Wl~-EW1vv_@`Qxeqs~ zcP=7ssl(ZvF>iWX)?;&0|eEoF6@YpTnX^a{^i| znATqKf0Jfg@e)W+!{bElX6~x@4u^edVhw+WnL|ND+3%&0yAiGZVYg5(fdF=c%l8L_ zRL3rh7iPLfmN8{dXLfMrr^d*-Y-)M?1R_)Dl;Kxll1LwpMr`YWv{`dLp1s+|e2nBV zq!zotC`)+x2M;^gy2;E{4s4tol!j7Lj4fcxM8ymbXo z&BGep8eCN+SX{}jVh^c#V)9pY?e0Ka+t`OPJxfs(P2d)HcE>HmgG5m4%ysd1v^@G|={UXB-Ffsvw32Mt5eLO8}j+FCU+ zE@qT6R8kayyfmTlmi~y8fn1!Nez5MldzHJb|AtG+$7An(-Tn;Qe~w-j@#6MB-T1M* zY$wumw(6a`*!-}0<1Tu=@lE&QaPiBHG!6XA+i_i*zK_=nzAB*{|fiv-1`U9&n=o!QYsHM#;`UBw-=zLMRANyb? zhK!tq^_HUUY>om5c!%&tEnnHmnyK;;L=G>ljf;y%LO(aFu@B6@KLFPmj%^!@#uJ#P zJ4QhBsK7hf&8?(3pg@#Gqy{lzjZt_~XqwiLrb~Vli;jDIS;vpZ&~w3AqpmD7=MTi-r{i<|RLUUKB z#h1mT_Y0{k-jN8SDfTdDhzrvb4_j2yw0U472Zj^ zJbkA0?{5*a`R)A&lJgr1I#~dGy6?R{>Sv0YKrkI=Zi^ByDy0b3;?LvkSjee3s z*7lMS=a~3yxF?>gMf{}hU=^~VadbF3v{xF!Q$HK7Wz;o69w`8RM#(hF{!4?lqy0US zmOP*af48Amz_;fCTS!+lxj^_K^<>R0=QYgBF+Ty%gWIro{sv!i@$5Fvs~Zm(WOu`_ zWvLT2uahPvWvwmzNeu+OFE&oDa_N=gzIf%6ih=i%2SqqLltLT`rK-Pld=b394t100 zFx}eEnYS02`KC2gQDQq@>u=ZQbKjS_OiBvrm`>dwmM7qL{-S*Qfu8arAYY39hq4MGEM6ggQz9R3jsx>rW$A_eWv(*ZsOE2kFmX2x@vH$u$v2s$m>&G2 zeEBN{?`>@N^jvFbbHXz&v-$GjiZ7GXot^X1tEs%v{NVtw8m?9$2Y}VKKO6=*wssp36=e`gA(Qb2ozF)2F{rE<$QN0xxT&jkF{vnPxQ5 znOj=lv;4w>T!Gq@k5zau0_mQu8t-Q$ZYX|Th3qR3S5+T~H58#kNgF5opkJ9(iHb(`Nm)B) z7oLbYl9VRbQFlw*gzc#Gg)4TSpfuY+$(KJ7WcA#yzC$FdDLqwp#V6~KBV69XMpXk| zj4v?l4Sfk=96&7#>E9&Z(IaLcUqdmb5k| zVMA8j7>wI!D4pbUDd|$LkdJ(N(UEp7M|Isuq=@jV1edjTj>_)TY=0&eh{dQukQOIH zOI*sqDPjwPFqjmlUrczc)%Ph_y7{d#Zq#uMFIbtS8^B0RYYRfnzUjnK%!32zt?fpE z>6dZ4ULD&ReFC%0EwB&ODbviuV(f1Y6OaT+HKNgX*9vs$!~t*BFVak{4xB2ZI8{l6M%kg)+9X>z@hfia7ekb zCgF@NqM(}g4ajAv0&7B*Gns5fVo`t_Mow{8(gK3`(3?9ArO#Ve43Kfs_`y0jBMa@E zp*^r|iqZ)FIoB;;)QQG!`H87I7p3ewxfd9eJUGhu)-U%@RPn_h^&HbTVUniDs;qy8 zU1+?TNbWEatfL8%G$F<`81@%mE3~5suGn7ieVf;jcSW1T-b3uuP%4SOlSCG)FO{_u zW+3>LjitTuY%g&O7Rwnwor`7>qsUrerjE&lAUt{s&Eefz#5=4iZ{@T+ywwgES` zfyRyO2njk2#nrihVP9Ar$i^2v;C5stKw1!kUp1{eVvccx8i z_c33PQE^1FQzFVOO)cMBm^>Dzbk=TCl!W4GxB#XelQtqex9~e(ua}3T)S>;!EV3Wg zVhfqE_bf-R#p=_}WX0q>mEcKd`zC+zOYN?hV;aE46c=xUR??g#c6On^9hGAIl>0*; z4)e=?^sHJeFIRtqhw1mOV$omu`Ig=twJ?=aj@tCJC2>A_e7QOE0mDSH#&QKFk@A0m zX(9Q-gVibBRrBvK%oXKpI;Posv&|dI;o>m@Cywe*|M}A6M>r-mye|B=!DkB@m^*|*iiZ7LxXB%etBzz5eE8e98Mxt{*{>jD2VB@y^b`VMR z5_*K3_J!^@+-q_?CQ~?&PzgTKraaKP4OQ#1CVq}t1aU(81M8Go44JBmIY`R!agxY> zL8Dkj8WeY8{hj$kGM?N!i~K6`1l^9ju%&C_yV9`%x3#JFIVs6o?VhJwJ2zd87Ych0 z_~=H7%oyoYNVl%xE4Fwk-A4G{n6I1oBslGpv%ki{vLgY_PTRPKStID5gnyFf?~>GZ<;S^vH#e`4N<7 zUlxS~$4><^K|lyeij1R}MPe*#KN;B*PfwNRR*~Kx;rW2v>`Jy}9q9Ob$WpyjOecr1 zIZR_qgi2L6X(QA0{V0v&F1;jLvf9k+bcUZjs-Yw-fuu<>wa)a&9T|(VTT3qXDhFy*S_@G6c6?AXI2lk)NhHr!t2-HaHsKP2 zk)|O&BKr__*8LE^SNqnfc6T9VKN~4)uxN_Nd@`nd>X|aF^8y;(_K!w@FmR7!6|g-Y$ADGY`D1o`G-AmjYo9TATj>E z;KgJ|w`vwGLVn${si%DYX`$Gw0r=1fqezGhAt~eDLtCkNyG%YSJS76FU58#@If@@E zTZX%rFBd85xa=v#IxS6=OQf0w-_dGOYHH^;`degYCGTLzJWh#=8F3lXo1Z%Pu)fB= zD{G&~>f!{m&%ch9xX}mBJ03aOZ(Dzs7G(QHxP8-llqBa$i*>%uR7aMXy`jFh9hd#t z-VauE6w15}9|DkOGK;RI%z7|VMuo~B(&%oSEp02;Ui5I!1*YvK zrK?_~ouHTSeXU1xU0#iS{il~L-e1%{+45!bSV|xgA{N)QCx2ZhcfUcIn+e8$wfU|8 z^7L+U`kROS=G4Q1>1VQgJ-RH4q@Tv^?0WGPm0w;9uYJ+LwF zBz{7#Fa%3nVQSI4!wD^UJ9XD%PTmB569*>>7NdAwbAR-Fy}-Ovteahwqa^@-wOxlT zRk=>I`(2(sfNQs{Nv=>;Bf#61t*A5FFH*ruP%OiY1rqdYv)tD)@S`!axnEb|3Iz}A z_qt2n=t*BOLHbb|oEmM!ho0#ZBw@NcX55VY0Y6qz1v%^ZZ3JmMk*Q2X?TE7t>A~-l z;Az|59LZjrY0zC9+T!Vs8m4vp3j-9##GgJD_WM6`#bf)^O~~@vvR~v6?G?Q6_4io_ zl9H?ARZ5Xsz>&3BZ%@_eq38A*d$$^>G&EeElDJVysu)Fw(ciTd%awGqn6%%01VtGVV@Mv#LEo%he)f!akurSDcUIaO)M^^1@; zbs`jnYi_riVD(Fs2-9IWyVzu)SgKnWUu{9R{{CVtQ(Jh;2?XMBf4B2J3KJ~_oMDfC3QuR)78p|ESMKv7dSfKJ zOb^xk_ZJ$xJ*?EHqY6PB1Ahf35BU3kmGNYI^?@5<_tbalzKtOs)q3GntHv1xaY3Q;H?n%^Kvp%Rpx>VnhxywAXLDuE zMV3u@LLqa%yEux4ns+WB8;7mc6IYjk7?j#dwsQy$(D?UX9yl8><*kGL^m&`sX2*0( zm!|d>1^DILY0PLFfMX=c-mK}=gT6IdlBUfMrg4UA+J+4T%Bz2`S*~!-nw(+xdcVw^ z3%P6Eq}QHi0vN&CuimlXD_De9;^WFU%JhWNp(|VZvqceFvEQgkhvb|oSlCHt$_NPY;yes`GalxGtH^X{Wsqmb;(Nw ztl&Upf+*Vua7BPC;lI__h>dXkGg$58|JW6jTzf|}UGmq!{Ezju-mY{S11KukDFe;N zZ~=a9x$jKyvA#C5OCi09{CI6$FR0@=PrujZNZUr%RMH#x%(cX%5uZoSC?r2?gyv24 z^oI{Z+-60d>0-&2IsgSQ>J|1Y4(V4+D5_E7-4w?WEN+=R>4hJ7z5BzT+bPCW7-!vb zR~k9F-R_SHJ>&8OZIKCpHfmu3%4~MJaO{>8=6fCr8aG-b%qlRkPiDE+bMbk*`9(|i z04cFfu*1zZDwKzcCL1$?i(*s`No*ki$q~N)%tiBz&$Ko0EN0PP{p^dq`q}--_Nb`; z;_dm(jVF2|zWa8|DPjL9f6Hm}P^MMFa?cgX!olhAddJtvy{n6cL9U^!bssj)ZP{%u z#qHX?y(}7gZ$jbW7yhvW?%8d-o2L}7`kNJZXC+cHHr?ZUj{TDP1Fy2}XbL3#McfIu z&BiEYNNVrSSI<4ovA2m#yCM{{#e@(&8YADb@lg`&vok|yn=W;gJeFP-aBw`)=-w=>^tW8(P;9&FBgmeZm3tm|Ao5?EH=$$ujFxKbE`|-2ZBY*dV))p3XhstjTUjuPACN&NqiA z-awZA8No9?xRp=W6{?Q6Pu^4C8mMl~awO{uIH zp8a9Y4+OCl3BDj!kn*2G5K(>QxqnifumA@>tXs`F1B8VE0&MK zT2OmKdC)LiD`UHWbxuebR>i5-V9L5*>VeWHX{Q0;Olk%$1h7{`cN`%?+$gKuB z?Oq-?0?W6*6+Z=ozVBuVo8C{!E+t51id>x>ZXF07(D>gtJnUuSv!ClO&a3V;4Wj#Z zTpe$H%qudd2~$qFT>Ky;q|%e9w4wXyJ#*2BhO*iWX5!$_`O<_jAS)>(SO=MaVKX=( zIg6ci#1Nm>)oR^YnQi3$h z55GZwb|Y`=-81kG5l-f*;NXuHQE0C;3Rzf)NbccnawE$W|K8h#IR3K}Y?VN1`#!lWK~efCiM$CU(`6(Fo~gR*d&y zUW0J0&XE6DvCY14rzlg^9YnXt&-|p(On(Q<5CC6RjJ65WC94$hGeM}$_RU8ofa|f! zbhY8+mnEZ`olyuQ+>VEfgcO5ZAV*^<@JX4qVi!K6NSz|GhHH$JoBKrylPbMRyjoL` zk9Gen!}x1h(-=0$t5N6)T4Y0?Owl_wfa@{sv;N5S@O{>a`zwpDB-Kp;y@fCI-Z1AK z(`0pwCpxv$5wWDPBxsf4wWnq9f$ABeEd6>dGQ0-EpApT&_XK%39b$4m z)xzR@sUS$v8_~AF=!scMEBRxsR~5!i8UWQ}H%04Go8I<`>cNUMW89>LyXZ3A86)t) z1#8;(|6=UD$(N?efZk>fn_v3FU#-#;iD zE6u5Foxpje+fh*G96hsR$$W=G&kTmfa#oSeF{X1}<9)>+m5y)YpHx`XeQ^}JtEF&U z{1}KeGC+s|NlQQd79Aldewhqk*!P3p#6cO4Cr+&S%OG7lhb~bm#6t4YrEF99; zsgw{nq_%#fdbDH^5h7i3^JY$$Vl%Gj>Foj)A+}=McNtJs<-^ylx$cZQ{S4vJ1K(+q zij;ANzqq{9E~etioO#HeK0&F-e#h$el#H@-_DQuZ{t8U#TE?3%^k|Rzql8#KX2wQg zT3@VFQ$hBFLYNQ&B|TNl>I-WliB}u(jl&T`Hiq=xkMrHx1$6u}d5h~{DKQTfxp&L< zL&dJiV}!BgIx`YQT*6vvC`z9oFv#esTn?G0&_aAtqV;9X?J13PVF^nw$<%~M0{Jh% zI2kpTU|e4~UlGeWYS0}rhb^ic%ik!1jT7w9hgPjy7KvtI6xA&mcbt^c@NZCPv!UDD zNseB7eqzAewK;+dR!u-A zt_P{RWLUT3&|+LpcSabzyfrgIzG_6ylp|9)!E8vo@S>J!bp&L3jA;%C?9=bQ?Fyp^ z_*U@6M6wjoj77yALz3C9J@KW21jjy{$%G81+|?zYwsy&#mA=N(I5T-py{>Il!xD1N zH86kS7$cRzDgb-c{^Rajj{sWZv;GN>+uL&44ve@_IThI0U0OKDuSwr2+MgOFf=rL9 z;uq+9L=^L zYxwEKZvB9xjk?3B>B+Yb$Gtu0UQPh~4213fmFDn;n(A54X+^0Vaa>bV`N$HVJdZO9 zKifYdsGWw#0$<|XJ&@*2e;(!NNigaixfe%BJvlmCq49ZlKr^yyKD2`xHra#UY3uWb z@;sIQYTYzjhq?Y>nJq*whE}+Wh{pZfZIJ)Y&R%KLkrC%u(3Li1NH6I9uyT}y6hVK7 zMV^z3)x0-<1y6iM-&5YeX+Z3t%0+N7TaF!q);?2dt|NRhF`AGcetRBU#ivO z!}jg&2wQ$q2>3OUv4@eSF8IUcM5!qvm~IW73P)iq>u;s?;>Wzd28Q&%$5RAzkw6Fe^Bez!6Pdl)XWa~B zm)>~o9wq0u-mH0Cv+(RZO#)6tjcUi8)bcpc=$&`{Nq5jMlNd^ zmFujx9Uq&zr@5w@zpIfd9Xc=bIuXP_nmzw9>Wc!HG8#tds~(I-ghVk3qJoU@I|w@MD1EX_(%O(F=*o0U7!%gt=8JAS*-Q3 z7jp>Xt4UXLGj?Q|);0cXys%}}Hl3V>nP=3&ZY;Ge{=CY>{JkS7 zi`DXDm$sr}X9qWDaCZoL)h(EYuB1-GHEj*#3#Tnve6^jsT-|WP>f?-p{ka+vQ|3=! zE+iy=w!W(x%l9KS`6`RJd!X;}90lcO+s^f4qyYYjrU1Xfb_m}9n1etT#Yghu9Y5|( z@x13fph^pIaEtW2@{2b7zhbJ&*9&vE@KJ5pbTa|Q{##W$dehG2! zHBPw-pNkmL80`=vS!qEfQ_B*2Kf@&{rLW9%LgZ0F7#OYfudea%-sx4pN%gAo;Dr@M z$AWr(t{+qm@4qnx_jmgH3FVC0hWfCP$hw@=L1HY?+L!*!{rYC-j{28k+@5)aAE<&n zZ~Whho{wG}4I`7}YMRT+mP~4>gS6@9oadF^C7dGLU>jtx@NS)j_6X6lrToJFio?wX zJmG}4*^4W-0ivkB|DMq{2*T|J>dsgt=u#Tu=M?;z$3OOgxzQB_Ge3Rt&R%BOwsuEj z-+k$z_Iv=r8ahGEJem&}9srYps?PGkJ|b2{C@RO);aG|Ro)k|*b}^(l_Z%wne>1na zm95#sM^1ph{RrTl8=(=m30k(*WL2X`4#qIl${1mRu$qYr3^NohpsY$cR23xDTnvyu z@u$AJEHzYrIVyo612^vSNK6%x0U1Zmvj^t=&tm1{m6X%bRq3%rd~gZr`$fOAj#X|_ znBSFj4d1KV@LctJpVm66_MTt5Bdstl<^9(nf=nzHgVH`Cs^^-D_PmBL4fs!8UpjWW z86|&HF<7pfpth_vYoe{QnIQ+W!2-r{Z<>u4)!|j!SOSF@UrFmX3m}Q@L|$|V!HyYj%0n*_mtc~6ttmqyd~ILb^th|O@2aG4+n+5!l`>D5 zuOKp?%c_43zvLo!QdL?TJ|=@6bcbpj%>bwWhZSDMiKue+{T+_ayNO>mCML8I+ck-l zFx|}4-M~Wi&ch2W-G|;!cWZ)E==`@Gg%${XQE7E=zGYNAAl{y1VdC2S64E&nWgIql zTr)!wFc;c%8NJZ2DJrz>D89KVL|swg#THoz@QL|v`d!DdZkA6>TI7|O$?552SCi}E zknadrZR1erV(*)px%GW;`VX^0n=>!+ec<%?GN*A$u3=Cx8f+vD2cGY`3@ zobHcsxfL7D*s!DWeB$JJ-6pY<_$g=eo zXKg`bcQp69ziZj{b{9KU0yS*W72kad_Oc3~3!{ne#cdE*2%WTY`^~v7*(pN;zUa(T z@E0Ig?9aN-L)x0YJMkS=O`!EeIVZm*{lV%z+;g66IjfIs;aDA%bourK@GynW>?LA?YCgOL&3Z0CCV$okVy>%E^_Uurrc>Z|XS<-iayRbko^ zuqaSJ|I!GJlC=)=HF3Qpr=D)%hB1W?eloP7Gy?i7!q_Re>+fHqn6Ov_PPV^>l@skEH3YSUjx(qxq0dPmdSSLnVeG zZ6VAiFks>z>Q638=|}{5ftI|AdANM3*8Qr4nZ?xj`Jv~h2uOhLaruwscXC69iQCR* zUAm=DuQa63ZQNc;KrK(WKzwNh=Fierq!#hmJl?zCoj za(d#s@aw^sX$Ta-j_>{XGJg7VsS&nnj5E`?us{lznVzTIn_gQ7Jm+w0&mFwxc{F`+ zx_?MGEQ^-+u4waZq4gGD?0(!h(M&Eb{x1m^=xBR4lmy!2mE;~+eGJ>~C&GfAOE{T{ zi$k`7!eGpa`q-;tz_ttAot|RQWkPg(+W=taiMC0EdpFW#bqytmmq5^!VRUm)OiJ+g zc3XRx1^dg$bze+)Rh$g#e&YG@q4jaY`Aw{80`HJ`cLb@9fn>KSU%Oa3nZw!>cfT6JqM+%Qd1zov3M zJboFiQ5V+j&BSOkcn55#^(oR_`ugnLlh2nS+DbJ0hf$Y+H0nA{bn$EW{6pz;7hi%O z6^#EY`Ul$=HsECKI{{Aqm;(z5N;dJ(Wo@)ZFc#t;n0m1D`djK5cF-xF_uz-#g33Is zgj0$2??wbaPV07?ZR|xalO|P(c7%4-ifApQp+h`oGbaA}n) zIdqhQ>m3}K z`3bdx0agiWEXljhB-H7;d`R%q`KQp$qv*ucXq~|*c z$9`YL!hpQSqYZeM-1O5}86A(9OOy7zLiY|jsyH_hhw3uYCBZ^fyt}|CJdY1^4ln2W zD;s|DUi4mD1%zUD=1r}1$G$IbF5oZB@>TJ2Q(IEBYSP=33YGmdrHC!=N*ZpWg2@p1 zZcJhMfD&c>W~Xo)|H}iWlv!;{x#WzwGVVBF79h@20;AQz<^g)HJ5Aexdov?W8+EV@ z&fW7W;rr-TBEd_|K*Cc!iF%<$_CjW-*T~0rU4=?7E3muxbe|;&QNt zi-z*U(Q9}&hU)zu5h#at4tqBCa(0D4G6agatL8bp&=raNQWV*mZY z97Ax8a*4Ak7F&vUn^WX?AzdDKe)UdPl_BQ_w|)I}49zOv5#HsgeMn9+Rpa<|31LK> z2ut34b*F{XlrKF$mN`AGqHNgM9q}L|ckWEdn)wjdPg`4~FVuEnbLQV~iCD?_8U2tN@ zEe=_sUX}>qE3>TJ7b*`=iw{2}+{G!I4HSKe%r%z9(a=L|7F}qzy0yK!ysS`sjT5gc zi@SU9PUnNrDDoRdic`Zu?-m|yAF10rc^I5wt8vgfL6M<;-Xe#wL z`*aW{!AA|d*nv*5iUXHtA)WZB9`b3ia0X9 z8n1W5A7n+883q}HxsPK7h9+-IoH9B7i`5|?Ge;-r zHhjmQy+`t@{96WYS-riz>qg;wBjepGD}lNOo;^XMAssd=474B^GY z8*O9M&ZS&}i9h;)IhVN&m}pdiD78)oW{pQve+Tb_w$Et^p%6_n+D8z;(g0ieN9b(6 zXbj`lZk={@PQ)YcV4YwQ#ZMth)q#C-c~dP~fQPxI-P*W(-c(jrOO3hZ zzUrczg%I8Cz5D3w`sju|GjHbF^r^LkB<|x)!=Xo#1RLux-y6R#?~`$)b}F}5*LsxE zwD){@g12rC_k)r_Rjm7Qi{H-;v9VBmW>9kA2#$#ggr46x z@Kf9jCB83?-kspMEOpu?+sNjv+?;l9_?(#$bgv?OfLQ(W@wOg*rhxn2C*0FWi(p2N z$uMym!(n4%2n`1eaA0i4+nA}{c5YHh)gj;4FArUD<%=_1WP*kbsT{r|+`zJ^MkeQO zi8opBhg~`ksqpt55kdiuP)&e{NOyEpnsYrD2%Xj|WUqSte zd9atfteUlPh`p7(xk`yqV85vl!9xgL8=uws6^Nt(Od{T0>gzcrTy#QP0mjHb{JvIC zLX4s-_wM5Ao)qBd$b}?mt4t1FJ2yspZ{blbVfg5RgIPhbe-0*^W5Yfzd}Dv1Ku1P+ zG`sI>F9~5JlAkPJ(onB!zl(UpPTjXf^NQ6)9R9h;QB5)uYsZe6h_bAl_I)R==XN(3 zKG*djr9m#$lyi`1D10V;pl$;(F7|SYW4k-`{9W#1@=i{}7bMSbBHG<=7QF6eTRycr zQ=pFW)5I?IyHN>zB2jAQTiUW0pg|eD+n~crAFv-qKRG|MLeQnl?H%@ex*iDZ*&>fL zH2B^tJ>IFTm}^rARe)ws@Lx?KUYsg|d+BkHG4ZFLHMNr+ZR6pn8N2kdVH3u12{o`G zX@Gj3in+(+F29JM-eX7Z?T)qg_@z_DW1_T zB8hMC0xJn)`PN4-bkunmZmy5+-iQq+)7xc>r-FQ?o|t3%OE){ETC@k)6>yH$vEVvr zcf3v7GAZLT!MFk$2}x(z`1TkBP-&{7y{;k2-I3Ob5~7+!!?q3!u|wVQyJ)LVU2SZk z;t;hK8s;2f8U=X1H~Y$7er={ApU0J|0+BljJ2y22%MRvPvSwK>6W9E*T2LmIe5Mt$ zhlkz&>M5T@wA!8CA$6=x*UfTuIZn2AZuM5VPQ|viPDP#G{-lt#*|w5?=GXHNa@|%Ef5-&+geq39!F+&5J7PMM@$zS=21Ph>HQ8z5*=hN* zprR^d!Q5iE>mrnL0efNt4K=g!a=naKE{ ziPXt)3n}2JzD@RyoC&uqURlK~c=FgMGboarLqa5olk(HZQ>1btDa4aX^Ku;)i2a)n z{etDTe%_xIu^|*MytClUrtj@;vopS$5q!xTYTqSzVB@n05G9XB(KJ_on$bDq4+;=X z0U9PigHS~?|E#g=*-<79mf29AeYVu^5*69oAfAhZ@FLhQyEn5?%|Z< z=v!Njz*$xjM{Uy32Nn z*n_mL^~tNew)<1D$5E?;hkM(vvkO@}J%c9<4Ic=~S#NFoSliAYTt=JhBvhPd-!I8s z{!(8`WIFEK8|5ptfstlWBW>GU-ht_^-<+`@*CS6>;E5WzlqW2PU~$@HqREm zw414*)H0^s+Wf6ZQX{(I+Fpa>XHO54Vb{0p6P}}WEnCDLM(8LE93UqTrd}Gf=2x1B zBoTY>lEpADXDfgrA?dJIIgW1V?#$UH*J4KXaQ>;iXZ#0l@4BtQ;l0sFEz@hZTw+8Y zMERPh8c&?)io{3K_?yqlcr|6b6i9lX$LZnHHM<+uzu(z%&Riy^^TdBAq#DTDssv-R zG{M`cZC?9eds@gFEFyKVQ8}o{?Z?KVz{#%K*@nSpT~l*ii+QCi$g^*>?ZWlR_2h%& zHweJ87`5E04|Q#EbLyB@?rwK+a#|fVrDMJdQQ!?xC)IFPROEHK>Fe76-m0j~soAf# z{Q<$E@U3Hl+dHtS*sMg#+(^aT z$T}p|FIGIRR7$~`CL()kotk80X>oRGF;7ihFCs7ZjzN@eR05t>0Yoxt+fSAO4qzh52 zpoBzznqtk1{4&BgM{6Sma~eu0F_d6-4JHm`1p8s6#r9Q-+k&UZ#}@-o^Mu}fDTUK} zY|(PbK!sOv4Q+sxd(`UWZ_(&E*e0RN4!c~8?)_cNXC9PShN*WcG+w({?`EYU{%I0B z%FgiX_QD-BH7X-#`sdN{S%STc>GIhu{gj&wPpQ*B#a)x{u(oTdxq2+&b&p|kVrYG_ zMMZMnm_a7uXRkOVf7ca^+GjZ#eF?3MqzaiqYz&gTGIC2C*)*vY1Z$3RJGeCr8w*<; zV)eC%>#`dr&uC^Fsz_FcAOBF;%K3i9--c^s7LDSnGGlW{JukJ%=;|JRc8keJj}KC* zaXcv&@S?@C1X}8Y*&hmz!U#J*St`)Jy30#Di^GtA_X77!D9>Wne1k}tiR}vlj&gdKxg*`)#8m0trj31gXNKcdWCqK7 zV=lSnjFjh{?+MRT9#4P7;7i2TDGcNi0(~+ zwHd_AaS$WYC)(wA_Ai?=CzO96I6c;soP2B=78-rI7R(~kw3Aj|>C%`N(PQS;t`w`h z`_*&X;j5fB)Vo7MYvUUPjKpd#7kTSO&eXO&cQ)uU9lG@liO&)sC*_xt1b)}ZZVA~R z*81kZwZ{oIfTq!!Qf%Pw->z?pIRK>c!q@ z_~v@+p}Qz_Ma*+p)}WFt*Xaf~+GT|d#cUsg!HE`(s}X z9_}KwwSWj61VIfvGzAbt1(y83)EGO>zy;TahNX$?dx7F26kEr&ed{PSwtYtU0^pyw zfB!rfJ@`Dlvh(yZZgF%{#^4CGMRj$HrV`c1UStkz`uhZ-)pvv+NNx0>dBWoC&&{qV zX)OPF0ZUr|{hEzqb{@$s%cMMlE6;YcIpeWEZ4D+jV?oM6WHeK7qypF}DzDBTKV7a> zn=xO@Q*5BH$nhy_L+-|Ic^Z7RM% zz@fV6eE20-|LxewTr0#qGyusCq-`t8RNR)0i%DrtF( z5`j4$9J=!o({Tpo3pOQ6R>kKG6Vd>1l|b8ZR#x}vr(id(N) zvjf8P$tNzJkroSFwk!D%^0(h_S#?qP=yAw>nbGw@X4N^H+5)LC1K1fc_0>7d2w*$H zoS_$IzfL1eKy0ADP|wJg(~|+1A zi5k+O>|ZybaEb|^hxyI}*8=FfR-+Eh0iuabh8; z^_RBOC8Jtl4;dfxDxY~pVHD<)+Dyr2mJ@0FhO9y1_0x){rsC;C!_ijdb*YL@?Z7IlF5vx2ikWt~ibuyP7O33WNgRSiKv8nU` zUxVoi6v271#5w_l21Y-Rb%-^%nJAHgDz`j@3&68={-#7ZEM(*Mc;Q}srm$&3-IKx$ z9?9IGUryBg20kn;?Yq$8M)V?j;O-PD8PSEtoP34B8qx@}R zp+Uz+R1+Hf_>lDN38;QjBY^Jq zVjWJw^NGMIx=TV${AQbq-AQS09iYZorWlOhIGHgtNbwZp*uPBnJaL3o?S6asIrQFP8F!TI+qnKB39T@ zcLH1OZX%VO7KSp)p4;6KYWR=4GJzK6rew4yvDv#RzkQ8@y(g=AC8lz- zWGfbNMoRmLLssuX_`!V;mH&9DfVp=K5tgHU{&2~thjUVGn2BnN>NE}LtV!;y(WKYn zEtxdJ(kkYV;4>>_O21M4#}xc%P5xmP?i&wOKQIYotQ%>$UjOS)QIX#_T@NcJcvR|o zG++>JHo*}9Wl*8|zdX51FtSvRuQ=}ywM`Yq@<{6rW+z+fL)TG>?I#38*Ow44!%;0v zo7{pNKCxZlO6$xpW=A)qi&;+Y%!uxMa~FL)83Z@3a4mvJg>yu7wt~yA9;0k>iMY`1 zW72P{2#3FUQU2JsfYdxs!lp8T+U;p{jrN>w!d4OrD3G^ykmqTnlw3JYZm&5KGI444 z;3mIbQ*k%~gF@kyvP%d*Vz6&iO!ZtBbHm6i)nu+E$0}E5q}X^JJh(Y(d98uxTmonF zw$O_6cimD+MFf_|(R(ydv`e9M(Q`@4C+n~Pa9@A>3aMn@OPp`z=J&VN3F6+$*`L0y zz&*(fhJCLP5mTb0ESvIn`q+)@>ui&kjGL86@Wlq{U>FJ!N^RX^U4o&Y>vuY8P;E2{&BFs zAZLK$5G*yK_!;>5gItEj!GkoTMXZvwXAe)c?ps{kuV`zqFA3vmmxF(cf+-+h!j2U0 zk*F`h-hfP#BPMTYFMmh)9$S_TquYUCvF+xg8_Dds{8x_Z-GY$ zkTExYa>HCa5knWpJ^MUjiB88a`X*BTE?GVIOhG$kAD?!&4}0#Izw{o_WO-z{I*M`+ zzSCH~gS#aUsB*L_wW)F~^mDT+aCG;6?N=<6oA2-Mz?`|og+&Mr@Zq?wzzTpm6=gh> zcWbm;XzPg&S28#Ms(-PuomV8rY1&k%hyqIA#0djXJt!0r?RHMK0s#7@m!OYKkF@v( z4kvfn{$ufHuXl64HLa0CBPIkf8?Zv4B4TOio*b{0i z=u2{hV{oAcbleBC=su5rQ$`Ewyy;|^h=tAr&WFa$>MeCN+lt3Bho}6JG0|L8 zDNY80xci8)Qr7hHNHQP)lQM9F-H(l%1kUv1mGMZ|rG^T)5aYL;7=;!QMXKkdp?AKU zi%hTi17_Zso}glqAVK6^r*my+7cwE5S}4tY%`7#!z4B4%1sz@w2T5Z!2R2HGNuE^M z7UU9Ea}?{}m%cEt;I5>v2fIR#_Hzm0j{ti|@nkbvGg>h*jI7_#P_&zV4!Y?9gYoLb zNcK_Wd_saYbYwSrxmfOOD|>Vtigl?(#9NF7>%Bml!loT8DBsvt$^vE3yzTGdkG5^j zy?_al_im$E%)kRcAVPG*^{#oNEJbX8RA+KqxbC5l_kDbm;Tq|ND6`Uls{J`v>tG1I zlz`AK-0Yn3x`i9ujH?$-89&=XSF+IRfW!m%;`zh*UrT>p)_x9-AUrmM^T^dXh> zXmuxwrxpxHg<(nd98BRMm7iXgB$XH!^G23OMBSh^{Q#c&AN<6nFsRzY(Wlzoqu8M| z)G_rxaM%VBQPu*&4`ej_b9r^r&r#3bGc;!r?z&bL4%o(JmhqvMZ$ML;ATG-*R97ln zmLF1QUh}#q2bM37qmiooH#`5=^5;BFuL9T`4$-FIJzIf40}{8I?!D6t75)5;bhNQMJ{!B!a9Eg!uDy&EO6x}-W6 zbs@%7baD`olKz{96Jh@u#xHz{Pqvx%J=X3M*)%O({@ekf=Hkdn@ z+YJScIcdSK=&72%HI9Qr1Mw7JrqTRCjuA`}s{6$<+%SPz(%oJ`UskJE*4?)=Z8g$r z_rG)hCZva^#=rwHZ9`74Im@%3N{%1q%5HhNSf?@fQrS8z3ZQ4_A(l^K#Jk-0 zyua(@JiePz_vpvyyR(`&qpZFrWh69=B)Dy}1F~I!GShw1h%<4n%q|6^`Aoq=l~GJq zu5H=q7~9sPTP5^XZNCc-l5WMUwF&^yNsn$f9|u2>@N@|x!$p9$bG{&u`G=jb$|Xa* zyCSXLcCQ)pv%JgoVtZ9lZdrOg9S*g&-~sQ}2Y550?T*oA(hTWxHQ2XbWt_Fo?Vip* zb-yRrUFSTu(Ko0483A>_Be-Q70etrA%Pu#q0Y2DuK{xgh1YJEs=Kw2$kjto!*K-@!?RJ-OH(j7CcCq6BB4qf2O}TinW-~ZYD2UEzVQy zsSt6edQ<4Ni^I^j?XgtQfXIr zs8T32v4?*J@DPxN=R9-{ae9&k+^0O+y=6M<{y11xJZ4BU_TyL0$Ve_STN=(#k-oZ~ zb+HJ>Wfcsg56nh zo;*qFqMqb~L30=IBxYg0C2XiCagaA|^d3~Ubx=Zns}ic8X*I@xv?egWf!r)$+`;Ie zsk3vzvO|V#v8$;W0q_6tUEYAG3%8VT`|TML8zw$$Pk^zC0A|ylXAFM$Zt!aJM;$w% z(Mwp$aq+PkbT;?w{|@S6Hpktai}sAzb=Xw>zE@doUsMpq0~N+oAp>9^(?qCr z77(b+*Z<3vrbevclV6xU#Y(QKW3cj>`GHd^1+KLH4ow@tr^^8URA1hVwD=U)hNN0a z2*nfZ;4w5GDd@^zv?Rl5 z-6GgLtL1!L?01%{i;LuOEYS<(7Fmm#Su9sAu2QgC!eXo(wVWIlvKE*qHLW4?gIk2<^-|~Aov!E z&;U+2%C13~KtPkWY7)m)+&`QAtnWVJADgC`Up8K2x_3_B&1-l@O9)iZ>0i&J*Gzi+ zYS}#8z}MjH0KuH75)g+n*#GBe`nF3A04qP>wf+erw_a+QTER^?GRks4F5osiW0YmR zdCRhtB%K5rE5Iw5gC&6&gJ^SIh$n)NPf@|kdeanUzS1V&NexLaW3VnFo}nxjlz8}U zZNWBF3t@P(m1s=y434G4*Q2rBp8#u%>{h&)l6!Dw$~!g6)PB49=mIwUiUK2(;H zY6%epqMzXJ|=gHZE7qYJ-w5Y zmX@7%G#8*WgS?V}fQ_Z&dIEzLcp~SX&hN9TWcYr*sF$xrk@U2xNW=OouKeH+pkDi` z30}{@!nn^BUzm5JKGWcgU(=hJF7No%VhB==#1fr?1JV5F;pMtsUwr-k=#Aj*4>z9N zB`^B^!g3Zs!7kS7bI z=&>o+YkDX;o&54N99Rm~S&q_AwywqsKlp1ERFN_$P6m@nx;FIs-C;wKc=~|0ul(a) zZ+P4-R3*}xjjSJj5QxdRw<4al?|80DTgdQAS1>~X8U*uzp8Zm7t2)LbWcrb}gxl08 z-r0Lj5*J+8elGf7Ca8Ar^YDewWU9MY);k{ikZPw!>yG`M-N@Ppv%A;tyNQ4A8c9V^sr|_w8j=MfrSLlmFCju$pqo2Aa2aU`+>Qp-(2SB z`CsQMWWHzOII`M&u}3%osZ0#bcjNXiA_AO$)9i1ab1)90FqCp?xJT2^OVH@ox|ODF zjgl|eVPykWGcSxZv_@m>wvS}4(y6YX@TphRVilRH}#2y zrk8Q*39ld~Z{jta%mlZ+dKBSQQ4Hh zxt7o|zZ12yRahbH+n!uvmHISXYm9hZj@^`U#caXBfg(GLC5LiFRCpg#RQRS?VOmkq zE93P0*)y-YniKT1pbVjU6FcL%-W{|+_?OPE+SP1o=4?l6p4@LrkEa#Pg4~d}ko1(B zz%;fmu%VLJh2obz>sp^^T$PF7hd- z_YHk6O=XapaL4z+=E!BbR*caiWvJRl*<)ny?)JVwyk95TE5G&Jm{A*CKVEYM{^tv~ zxIDJqVQG=5D9s!tAKK#yx39IY4~N(I4Dv5o9oi@g8wdt0bNx==fD9S5q{P^j#i|yhN2K?CI zUw&+O&-3s_b&Phih0K|#1@-Pu#coz*d96F}_V0^-$o0D!3v6Ef7piVcMYn48g6~}3 z-+HorHTFskL_v=DX^jN01VZm|7JeI_ZvhjN1_!bF2580KlfPKHItqG0K1{f`CHcZN zQM1LB8}%9c?LuGKj8@U0)=&89|M_D@^Y7~4AN~AcSblHM^!7-ZqH4{Exk)O|OP?8U@my^taD_i7Vg7qr3uf(D-0#3l5Py7_eTG~3+D`txEjO7 z7}Ski(zPqQs>~A19{xs8%#)U&ap_%<>+P(o@>~9_iI_i_bP3kpWx!Z=Rg6u-Z7e>I zDutCU(X6>Va83Mxf5CtuV;Ozr8@7He|0B5hX=_QsZE(Zwd!9O&_4oVqH%qQkb5&T|Mbg$T%=3_I6qQ zes)dG7M+h4CF#+<`}5d5l2!(MWw$R~ak7k#HOrD*YI@p#D4>ya9mAE)?!dzHhgu8U z8XK*?+EMzAs1WFQ9TsBsTUUKzjhv{@r77TU*LkaF|G*`;{Gry*g6pxtd%Un|Y=Zt7 zm|q5P5j;9j!4N@@U-0;{Z2EX8B&&kSv;hP0-*ct+Nr$++u%xujgE4a4U8go;+u1^|fF&Vi1&?|1yU(%yMicqgXKQi!7Yym8I#N{k$=`VD&aQU$|6Lk4D z8Uy$OD(G~MbLvE{XB)h%;=<1oRm6)Cy~o8~%>LBj2`_UxE%a>?Ut=2P13>vBE`BWl z9t?Jc>+(?xQI?eP!XW9l7`HZHz9>NXAKu|DmdWz4S6@3W$CJ|zrM#zS;DMz+U8}!i<><-N2Fo~6-ncCZovFN-szt!vx>R5 zCE9s;pnh_0@q(yISyj(?9#TEGY;d*7Di7jkg)>~Zq+ zP%1FT_ppd{Y{P-D0D4XBkw3w9=QZud7Bf>D4sJI&Y$Zc+u;ADfD19vr1Oyk4``-+4BZuy?%B#pl0$ zDOuWxl`s>ugIpnM80EeAtkLGXEpEWIsXJ_R$s_N5N8ngjFb5^=GTB6#UY8BZITNux z^C{ZB-?8r?dasd_##ySdblghoqY}BL*zPoTiq7Citu&EmL4g;Z29P{9yrrtA`uGb% zLox38%?MohH6{W249%x#4YG35DY|_2ILp z0on^ZmvQuk<`PW<2k0FZbVTvrYYeF*j1BA_?0O|{xCj?rV&lJW``kXN*;b2xMwpj&nvcSc zNL2l7wqn&g>d-t^tgx~aUz8c%via&=pyAIqwk~uzNRdnZ$Mz-N3<(dX81xFG-0Ld6 zb|}(*1Ss_Rgv7HxR*CQJ6AP_NEBNe+CU4)bm-x`9Gd}C!X_VPD!vcC=v(ol~%_p%1 z_bZJ!DTklc^bo1?m_~({6QvY#W*Qh1DI94u36aUFF28%Ga7UPyLXIJ(uORE_Fh$1X zeWp*-akJ*dSy%ki9L|yJMjS#*$FWzl8Q*3TVrC16?fz5}_Xzjgzmf6gTKGG)R``43 zCwU50kMas#cou~QG1qHVr?#wxYmP;ZT|`zJuPeHJlYHx%rEo~e%8(Lnu_A$7GYYVK zpq#rqYF)jSq89dPQ!imEtGDphzHE%|j(?wJWSA`FSE0PuuibV};bjgv6}G;!0G>YL zI5cu@)QasA(#!Y;v7DmI0@QgBBnaqt)rWdFy2N&s>z(qd)U`dvhHj!^_ADZvTL2;S z50s|5-n95@L#6R(if;SFnOnn!ug&BrFUn$)>Pt}n%SnmaSY5#_lD)P5LtB(=GN!y_ zWE%_^=7{^p-TVI7+vbGkPTJ7rAT*9OL@cNjNNRBOb(gAD(>yKB4oJz*j-?wAUpw>a zBS`gM!ax-pMx^R}`pD#E*PMY@sQWPJ^L(U4O_8?EMb626jZ|VthLWbpDj%S|M~(Y_ z4pIwEBTpcT6*RjU_;V12f}x_Kv+#O&#N)_BB-z&Z=6Yv(;#HThH0G$A+PP|>CYE~P5=UwQcAet{`}svUBbV|Gb5N3N*GlSQDiedl5wlfO(r=O`lQtkw{W7{Jt`j2m3hFN0Oifc>(s_ zi-5_hzyP&tw=f5({qtQjqRE5hP&n>CrM_QHj)_E1)oFBscR^Z(RxNVYrW19uCx(QL z*1jl+tunbfL`VTnx)vv44^F>iG8ppKWeUokP56|~x_RhCF zevG$nW{#Zly@0|9H1Rp>s}6ZS=hK z{yEI_)d8<(7Vakp_Ka#@(Tk{qM>5MrB43h4`f=P@nLDW0ulC1UJ=oQHWbA5yybIIh zSte##hXMEgp9)z1n$7yu2U}m~3+tDl+Zg5ZZBZ9cco-)EY#JjBP{|Q@FY`5qu%YI0 zzN_Nm^sRiIJWVdf&l6wQBX!Q5Oj(fR=U}Do5bT#{RQfW{sP1KmtUKss>}aeOBITe~ zS{G|nn#B|s)X@}l`2x2tuX2$o!2{P_!skDKI!!(ea3{cprXuKY7GWR+y+Z2NBf(&2 zvckvo_y(cQZOWlnT{4|cx{zHomJTT20toIuH&1tceukrZIL#t_e0zlk6dKp$@PN%P z9TVZ)t3kv zCd&BmHLinBiCqg3GhQhx1nTK$tEu|)fW7zIiIMx|eu4?c39nm0ZU8~$kJURdvH6_n zZClrmP|+}y3;ba5hD=}=-~1L={_>OjA8SACy^BLSh>WFB4x~qWTN~kItef?jQ_Yc0 z^S}n5#ch3z1~Stuh+K^KghwKyT(>3MWk`JkwA)*e?xMTd*~4wV|H0;~^d>HGHN`vh zlC^6hqZU6qxC!&BL5{T;5Ay}fPfbiIK0~Tr>){jQotq1b<-L9xTU0r3qC&xNSF&+b z9NG9)JF-aGDJ6xSVpWU4Nw|e!##K1af=@7p8ZSy?jF59jaUh|(a%!%W6nT|$rAGn} zV*26`um%qVQVYfj^`F%P?!NjPUP5JsSviBOu+Xx_FQ1x=1hZE~{1Tui+wiIn=_OY$ zz(UbTz5wC|q1r#h{T#_cHx$KH9k+R=@ZpS~GJ5Nf*~{x3>uZ?Cy8xaWB>_NDW%?n?dx#I~ zu!sMq7bCaK8j`-T;oEAnc4t&oV<#!CDS%#n*b$T4KC?s7%YJ*gWU~7<-hwa%bV(KM zV(#BiL+|z@7iR~2z3A=9t^Ib~&RAmRf>%oughj@?9p$8;p-vrY52*O`(vOmZ zmGS^bBgf5T?dCFiHef(gM+?>$msOU1QF#42*y`ZR?5;i=jlGnqqWTNP5Nd)D?)R;% zNAzp6GikjWPOjqydW;~73q_9C0-^qQ487+UyzuqkarA!%vhR-)(63-W2ice_q!rCV z3=uc@xJ9!08C{I!E=WY@rlsn=d7Bx>qZgnikFLidBJuya`^vDax^CU)p}QrO5|Hi& zDd}zmk?!s;>F!2Qxes>x>R{R?p0M#GOp`AgYO+lUrpy@w1{3D6Gsm&+=psW<(<#j7Tg3JB z;-HKUuEGi+GaFygNC`PsYh9k35n0ldz7CR4#l7%Z zvgA6LV1`Yj5rTCsyhCd*20$GCPELy`CxK7ETzpWEHm4(%?9)kK=>h80n9YY(tux69 z-8WsU)ikQEK!b(5fjsAzKzy6vogS^eToF2(doOp1@5^-`6&Mx8)OgZJB`6>VGB&NB z)ZAT0a}=!ZvrH0+Hv2#zK?R$AtH>Sf$C%~)pO}S_84P+p39DBG9MJ#BD58*A9IM3p zAt}qt`&`!ds9b+oU(%(^^7+8SH_wXj`~DHP8*@e0*30Wt){^Yux^SRFVsZERK`f6W z2-<&Wohjak^i;rF3tREYj-C_T9uEclD{;nLCH3OlS;B|wTvsl~)~hRqTGC>EIMAh| zc<=#q@Iw*;avEKxAro61;aU+axcTNVn8&t-B-}kmuzuRAs_(H?7-#n=-zG=J7T|NpS(3aED zGHKQc)-fRt7^=@-BMC_RkaeutqTiM6d{B6JVkDHbSx5mMfmp0AhW2?g~?jtZi$oh>z@aIvY%4RNA!4~ge%cQ?+YCOviFK_8yH-9;p z1zNITL1FPv&;NexaM*N*AID%-80B?TeVOjCL%!EVjG;q=@(@u0pxi?g_vpKlppu|s zy>Qrmo{bWWzMGkNpG`f1S0i!yNIzsd<*1# z|JsECX!Ca#_s1lH3)(Xk`UY z1;-J-?DNi_WY8ZihS1%Rs-QJVP0{DIylpzJIyg%;fhm^%p?K>cn|nd($D0N9A@NM_ z>*3X8qh&t)5$_z&E7_D%5dyA8l@VuXk9O_ZeEuOk(7C?tPpiOrAW3*l?WAkgEtot4 zRTf4MqDq9BtN;w;A4~ZEL&)%W5ll;YuaX`=_)|#h<9x?W{}|^?on`85ak7X*XxA7Xi?W~`u*!5C|SJ{dNq9+{M;^1cli zRl|lWTsk3Q|bR^2| z8GEfzrE~4pQ-j_QA!h>!>xU%u!zYMDNdhIKF<-C3@4w2U7xVEf65i_I+*+;$8i5we z(X4@-?|=dDzxnfd&8zT3CdBG=^$_Ak@eIqx%~`OD7F_f?bQFMk0RPQC1TX%IcV}*m zeV%3H^{ZUl6|U(V@xQYV?iPeyJMi)tFFejh?{geY$0;p^QH^9H z`mDw5GA{RyYG_X-3n_D@tS%$mC$P95+3`R%p)Xo~JQ9KZwf8_Cq{7#Yr0#a9eb#;V zwkCedJWTvS#1yp?hrdm6$}Hur6$F7~Fix0KB+%Nu#3QJNSZF~Yt`xk*zwbSql+@NP zpSO+G$dG%DX~PO7$s3Io2T(F zbT|yxc+@~6J*a;FUSS&2L%7y?c_#5}efq}W$x(ntx1d!^_bnD^5*Dpy0~~Y(qzzi= z*fcDN>Goo{AkE+ae~8q+6L2C#4g+t(sp~? ztlwoJUd07aes4nW`1g0qm{6B$a8DhX8XBA}&^bP1(3;O(A^Cs`ntg`;d<$F)T)HfA zUk`QYb0QbYStu##wCe;fZH3Xl9|mc1z_b4UY<0SM9X0I?`-k4()i14jeb2h(F-?9d zDrT?5+FfZZLUZh@`l4*utBL&G-a@T6?D0OvT>K09aZtp zAkZif3mTzG2tn~WJce578Mg&A`ZgLu8V3wKF}qe4mG~k&BWwx+W}#1grZ>0aNNc6K zYb$(ZS*$W;4RRf3ZX;s0UR;H1tArtK+Y7T-&H(r&_nT=U;5T0YD<{uwT1Vz=S$(nSsK0{L!#`5o4z~Pv)fio0AeZ?6J)=Gng z2esiZ!Ct^?L(9+*@X}KC%$DFPHK|=cl_zKoCKdY#gKtJGMYZ?~bX5_#ZwcG+%J|mh zfO?U@1|DYt#73vUq)*a(Qjq@HOFE7E%T^@8d%pJz3N5B`W_U30@wDt*Nm23BUjE)E z`*L?$oo#EP)V^AFPRIi99{oxhqgQ1g0qS01%HpUtDWat9Syf(eu}!~V)Q z{Lx+w(w6&dE*Fvg!T#%R8IHVKg$j8PQa@kluRtx1z?ZB ztOiGW2NQtW6^CY)8lSqTSgsvXl2d_*vmrY=Mh6+DlY=b=xD99+234q`sx6x=ni@X_ zb5^H)MtwO(6)~d-D-sL^s_9|T+k+1Q?y0}+ZgIR^oi?hu@72Y!;EM65O?P*HNsf@l zhl-BT7UgzgK_2VVFPpgQHXa%qoD$aUKVOp6ZB}wCyi$FLiDhkY1u7r)c`P(5d>bsQd)?u%5q4jUx`sNO@j(4*?H z}fl>Q<>ALEHCC15?hzl59Zx zC%^!Ipl_D5d&LZ&VJRAF8N0F}iAE#_+&8=#7+^!RU>Up_UB_bGGz3%J@H9+G7&j+d z6NlLuL4hDNgnyTfAwA}#tIf^1o1cZ@MHAs)O6wC8;O?T~LEX<#U93V7fp<}zNm>N( z?QNN*&Hmk()whF z1Eb_8Za6FRE_S?kN_;r(^NT?mf(p|~M<7a|aTL)DfCoyucTnx7@6KI;#7lxUQ@j34 zE)a4D)GRP$`1K#T3c$^kyjtBwWHeTZZol!k=_;G(=j&>WbON_7p}q$SwLlsE(Hnk# z_%0rtPr2~ES?AvpF6V+X7Es_3-^`E?#mPB-lR-gACq3aw0C0KsE5FA$zdzcCmm(ZGGr%dl#3aTMYCoPzdk{R#I?O z=DjvQMpaLO&}r6|3wN34yF-qS1_#~4nu-YlXz_pX8k(gyHgZS&=8#1x19T9S$4?x( z4+S8cGkTZ0A0GR>hl86!pl8Ls8e|#G9ogO6tC^^!46tnI>5Zrj!Gf?wQ4rUmg8}H{ zV_^3f`{v@bd`&;AjaO=?HA-y@tPO2>1yhk6*Wifrt~96iCe}r?D}`fk`0$tPw`X5@ zd*h$-uMy<~ab`=eYli15q=_x40-QbwSDG=^y+Lw$gW4k_`80goQBzo&y9Y#@?5I6D z%jf70DK-8|Tbq`U>_{L>K3#nvo+nMpg8+$^keE@pGo6&OqLb{X0<%I$jrmLuPLa3^ zwD7Hr25AC1Z|Nl&Qd1+P$N{UlMGfGo3 z(@It2s-IptNI3ZDNLlDevEUVk2iLF-s6J4%xqiHA&iacavKcY}%r_d5u)F2ZCv@I> z*M&B~ibTta(6RGthh}Fh&omhyK+A2??i6Gf^=y&8{sv|OWhc;ri7g8$Ovp?3>3Wvb; z#i+SJ$OiqFl_ZLD>Q?bFfGo76=i&#XNju_Uyc9Q9kbLlhERc`QG%O)d~EAQo9hgdew(q;PYIX% zyY)jY72jeosQwZS>9^B+43_=F1|q4ZexBq{uRPhdmFF#EoBQUV?bY@0vE#d_10{f= z`U|@S+^m-X@P3<7Flxly-nO?V^Hu*y{al0lEKhDFT_$HBtqcQW*ce0>s>I-po7u9< zGV+^_Su1M<>A2g38P8q3<`R_PW-9n+cRfVd!=bMA@!t;)HHZ@E3wY+ zEk}JJV>&Tu33VAz=R=il=`RE7Id^)jFh;;XwbYq+sle%^WYn_qYZX9Q@PzIx7U}x?nt% z9v|H(wfoibsRUv$DGSY08jB#HSkyA&o#Y7+)ZcQHf$)c5fEYgpsCfP{%%PiPlyW+& zQt0f9M8hPo`yCYNPiyQA0LrN%CFFrksBeHhwZv=z2yT!IjqIhAYK5)J{G+1$!wN*A zM6{HAY`nxR#7>Q{E096IKB3|Q78B@H{c}}{gZHv2{qWS;(WBB!IK+QRV>g{;S^i=taG7)DG5fa*k!@ z52?P3jAAtf`!}XW$Hf{VmSIv``E3GVdEg>i@cSYdpMe^+H{fu}pv49RuO~e1R9KZ;|5JvGjK=8)_4rTB*)H&c;E}4db zd~{Nhh`h-I*{xSCO(&3O1!8gXF)_-u+{nRg+3_NBJ#Z zgvn2g7%wVT-FaYMuz(_}kZOOIs{UwE=$=giZYRVUZ;#5N+*)VnIjx|Slv7T>1*m%( z<&{;`J`iCp$Nsm%k@?P!$z|bV3S#A6zbLOD)ZY!>*ku0a~7k8GM~l& zj)NQ>3_&C#m#nklmFOPrlIZH3Uq-W$vJs!UGM82XHIILlV}5r9gP3JtssI)a3m|;! zneSy4w#?}*fVf0%CA?r&SCBU>0fSyozz_XnbCOR}UoN20&JX09-}2IUklSzF)Nz15 zaH0rR{$G`WA-$hJHapyTJCj~E)(Q3bR4)k|&ZJ17U_P>$ao@|y+b3N0c^*k}uBgsL zDU@(ArlYAPe29lp{p8WV<`p30b;aWl(oQv|e_F#cYk{N^n+B!&?bD6oRNC4v_YNwH z{LJ=J_m{sS6cAN~|5Q8_$1TaCnC3XOE?&@U9tTaFe+-A%@1B5CT*ScJP*I0~R9WI( zGuE!+>={u-L%be%733=p0C&k)F)EM{Q=K)-AF)ohzCo!C0TF7U1(-hsZf`ngN4UwX z4QgmXm{`!p-(mg501fIt&9KjL2#t&>tSQy~L>EwSNtWrt$++$7`rf!P(15dVK$9e$ zo9C<9)rZ6Fn)+l-@3&Sxil+OzzdT4j@|D@MsrHkmC`fdUF)OToYW7{1hAorrZ_s1NQHcRQ|W^Ik2 zdNCpS5N82Kam8@4RH`2Fbn7$|-r~`cTpJ|qfArbH{)>~E32rfZp z(^)znAhd<(`3KGD~v4iR~Pp2iH;TlVjlZ2C{>7&cg0-7n4OfZ55#zsTQf`o8Ki7O4AiB8 zWX=NBk*?D#G@{(Q4Q)<)(z(Hc-l7h7=nTXmBXeSNP!bt}T~!^RoJs0(3hR;>ZQB}& z-=L_W**vw+nWL8w8DRM=`Iz66_a6vVK5f{HVIDWTyKevPLdqP$?g?^kF4a+Mqt%$2 z>J4Qapp&sUU00b=&efXQSG5oG^a)qXUZ@z~Yo92{DWfg2eX<*_HNn+X&1L!4cqEIn zV6NWKV|ocYEx7K=>{oPs!55-T(@2(rG9}eglhPLXC#qZ~g~(5v3(L9%Vc%D?k2QN3 zg)XWFnY2xRw^qB@{x)CeI$CGM318`;B2;h72Qz8>GughTZth5>t)Y_@PRW=zvy=tK zNrv(p{^qQiTB~!o9vc%|o7%``NY>{yOd5Cv42$vZ7Ch7U$V|kyzNSw7aIZaeL%llB3{he&ooL{UU6WeH&-rue`crYLMA3=U1vy zbT^z0iHMNbqc+OTVO#G)v5&j_IBuzB4S6&RFc0KgVFq8^1b4t=t>9KkVuc&TH$*hS z5To?yq)Nv{YQ7D=^CB3qXVcZ&ur7!3lh(FNt!Sh%hCgmsCMQSmOIe()sV{Aq2=~4)} zI7&w#AEw=O#&8f@h#xcovfwl5GQ$Ey|$seYjkhZ^!CU*p@2*hoLy#w;|H9ukez ze{ojk{?V^-BYiBvn4BSqRaWdN6JBv-mt)>7F$xbFzZrb;0d=i@Kqa-0p7vI^iJ|NT z7t{sIgr(+*P)I%q=GSf&MVbHDDYXt#uN9*y`6+CNIEoV!w*A5J3+&{$(aSdYAsHfp zZPfOrbtSPFYZoc`au2%~bN9l;YH~gmIQCAv(O3V<+NO_auZZ&7^hZ<9VbTA7QliY@wcAJEAy+ zFXwaRVtz~At0a0$>yf{43|X!qLX~c`Zni8LDyvcHO1H~gmR`FsH2n1oVZGs$8Ly1c z=*J-mXNoP&C!HL7$ItlUsuz1$sE!jFP0t9vds-6`k9`u-e4EmJx+UOk9`G{H1((sA zF^CJryL%fu%lTR>^A*LOc8f;o)ZCnWgGafHY-kO3k&*XY=KBvHu#wRrxA>MA9;<04 zC0+aj?zZ6AjO*!53x#D7<*cOqvlNaw{V0N7FWw+E*B^G|!?1Xyv*j|q*$v)VrS(gv z#!ap)BuzoKz1#9fSClK27#S#OOu=$RmBIEfJ>tgYMEr@z8}r7-=;uSzv2RppILdgqfVaI7q@*v=JGk=o>qa-ifLWP_eIu9BbzY7=U)AL} zMjtYTk4X}&A8Vdl{c`Y$)WP5UHs!h;5ZqSKTM>9qYkBAhA+Ius$-0(ggf=69quGTs8rCWL zfyLw_Oj&UnyLvlmCwqd>+`5Y;7yQ^t{Y-lMG&R?x?4qBP@NNMUVQ&F-=!?&|_E1VT zp=j%!hdUee6p~>}ZOF*Wt)Ppmf(-h4tf~Ckv@{aUoBAz{DI2X~ zVgyF~4{!bHvS44XqYtVhAWgenFE-QJj48Do~LSED3{i9sGojEmqsHd*cvHw=azgi#g1bc0TrX zTH0gVrV+4;NL;jqMq9b2hfI}>Ov~@aV`&G)(BR+02{bhM9#uOxm$}`Ti5!U)#Sk;R zQ-sMBvZ^gRj6$XqT;}EAGG4D&YZ6Ohzk^Nfcsf6S6rw?LKU4OsauGw9#&kPP1J)?d z?MX&F^V~iN}t^Zh$|C)Oa##ESXa zrGKySX+wk{TDdpv*wrvb4wWD!V$rwLNZ&%nrz{^>f7B#xlvx)w)^iu1(>gzAFAkqd)2YP(V0mbCXTe)Z_HtP)JcaJ!aHxS;~nNrcxStb zwW!IjE|;HgW|R_WgZZ9*Ug$4m_TvgT8Y^h)^F)%Gm?v|)W`^7ID7wb&>-77fZc=ZTShozaKH_NgJWSN(|8u(S@7kEBb*Y& zZy9zW6$X1B1RwYum^kizO-J)NYb3iq^JwNC0>hV;cH9S(U;n(?^97rdo9XF21R(y2 z{6QOMtKps2S}^O0 z721I$Dw*?Ju5-@ToYYkBY66)xKYB(2+H_uSLDCNzZp^i6MI-Na-?WOkDctbl$%7JH zUoVn-YAenfIVUH=prI;ywn9%rw$eQi`IChDFwUH$>r7JsyMH%am1V9+uv1UyEh zxf~X0%Dkc<`%25kMVVfMP~AAozS!>xfm(rac7Ccxb59F$!KX`qgUbf!yD@Qx{EvyG z(;3>N#GJ8ZU;Il02gTyH)TqLZp+do8#bkJv*(@q4QdYN~luwe8UpuB%{0truV?1Sa zd5iE?u^+bH=###3MD1W&pd2Mv{@PJ-ZjWpcyQ#rQjpc@)_q&xNkpQhK{`j>2i8olWQ?tf?pN{HsYqu^)9YjMO&kV9Gdi4(_ggP;HbaZAlJ&P~2Me3X8g||4 z$EDsghKkXT9l#t3Zmz3S+s}X8(QD>K^&{>du{tmOkkj&keP|6-w5}l! zKV<|=jnPX^TM&gD408)mc~4Rsb3Eq6cp1`RAj5>XPIa+mWCc!V;XI2`l#l!*rf5ko zUY`JQYQJw&V1*#Wc!xFw&PR<2l=aq3K4U0-?eHMN!@vl

buibo}hicx6&l@gJNcsJI;tJeTH?p}*-9#Ii z@3706gDGL2Hg}@!j5ElkxtG8o`A&fNTHKigV?Ae#^La0ar2fE1v!ai3$O0s_2`(ic z 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«< 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 Ly^wf#eqsC{v)m?j literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx new file mode 100644 index 0000000000000000000000000000000000000000..94c3c71da52ca3d4761c4e9041b384d9bc75ad9b GIT binary patch literal 1240 zcmexg;-AdGz`z8=qW}^Pps*kZGXwPvCCmbJ??}b0K);VP%m(x`PVCs+bpPZ39eaPT zF#d95_t~f2a`oYw4{Y+*Z5}2Csyees*{;KHB55dV&?dF#`kRGN5~TfOsX4T@J*P yfLQIszKM4h+|MXn`snRCm0er%Quq9yFn5~doV&qSCs?ySKaj$-^Vag-Df$4qg=3fi literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack new file mode 100644 index 0000000000000000000000000000000000000000..74c7fe4f3a657d606a4a004c87336749079c0edf GIT binary patch literal 491 zcmWG=boORoU|<4bwrPA7bLRHNavd@dXt`h9wYOo@&ulXVr3x1R33=PLWk|2oj=R6e z{6ngQ-HiT=p)71gtxNdtSc@#my7+iQ>e4qWip{2_EIvQCa!ROJYez<`n&YvUtTcI* z9TTeiTBZe0nUf^pW%6`sa`eMPzM|)nA8tGF@Z|lXUFTAFz2AA(eS_Z5b4eUxWitfM zx;^&{{dY4@|EHR09p8m=V|lCdF3HolfsX5m=3+ABVfbI&731*Idp5t|LFI}jHQzg~ zyQiAoi@zxS!<^^L4J{_ighMw%nza;7mv(7p=6M|PE%R{fdiLnm>17)awYE#nS$-B0AgjUCm@D?V9#TFX)~ z$JoTcz}PU*66+=E@hWo`*7*&jWecg0;xw=p8Q#< znGm{LIG-cz>zd?K^@r5dt1_-_DeboX%y8$7^v#Wo6?0bm=)z13@;H6Q^C=U9)d4m= z>xwzr=RI@+K|))fGcic~WZt)&iFo@NUWM`6pV&9?&Vu_Hg-aj3U8k~ZOJ3@p{}TZ5 CmFm|3 literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx new file mode 100644 index 0000000000000000000000000000000000000000..555cfa977d92b199d541285af6997543062dbb5f GIT binary patch literal 1240 zcmexg;-AdGz`z8=Fu(|8jAF{d02H2-U}m6xVlWF(-6*Ck3|N6-I8-nj(5*DVOle|P zo{t)ie0?j&@$0PFqP>OL=Y#(kT`Ve_JpcH-3(;%WeY(v#lR+%mtR?&EiC&|hR!?hN z(wd)1Z9Qs`dw%x!5V?meVL>yD15}(ow=(kB?z_;%ZLnQyuGiaosUIg!3HkM=?0m@~ zu;ad6!x7<|%-;-CYzi~lg?rcd+wO~5?(_a%q=V;#6!|H$|2e3=YcE{|%zhz2tPI5a zfqq^Fr2Bw0kGu4gOS9IUbq@E_@MF5DBm1P@&x?V@nN22yqrhMG{sG3n*SE{>v{(-S DZ%AIa literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack new file mode 100644 index 0000000000000000000000000000000000000000..4d539ed0a554c2b1b03e38f5eb389b515fc37792 GIT binary patch literal 498 zcmWG=boORoU|<4bwh4R{bLO6LB2ZL-fLMnU}tes`9ibm`tURpR~n zN4$6HD)yU)CWLQZoTPkI!7rVgzg+9v``Z_ETFHpbhKWQbKFLPm4J!}4hZ-;;1 za#iqhJ1^nhV_bNmPxbulr)SmY-soaD~5%da!2C_U9Y#XivXB zA!=`fYW_quaW@M^#aa1lT|@sZc&3)$dY@s6GLb^dz-uTluNVLoplcP)9_=us3ZHN-p>mFO;6gd literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/packed-refs b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/packed-refs new file mode 100644 index 000000000..71a7668ba --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/packed-refs @@ -0,0 +1,10 @@ +# pack-refs with: peeled +b25fa35b38051e4ae45d4222e795f9df2e43f1d1 refs/tags/test +^e90810b8df3e80c413d903f631643c716887138d +e90810b8df3e80c413d903f631643c716887138d refs/tags/lw +7b4384978d2493e851f9cca7858815fac9b10980 refs/tags/e90810b +^e90810b8df3e80c413d903f631643c716887138d +e90810b8df3e80c413d903f631643c716887138d refs/remotes/origin/test +4a202b346bb0fb0db7eff3cffeb3c70babbd2045 refs/remotes/origin/packed-test +580c2111be43802dab11328176d94c391f1deae9 refs/remotes/origin/master +a4a7dce85cf63874e984719f4fdd239f5145052f refs/remotes/origin/br2 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/diff-test-cases b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/diff-test-cases new file mode 100644 index 000000000..f385e58ba --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/diff-test-cases @@ -0,0 +1 @@ +e7039e6d0e7dd4d4c1e2e8e5aa5306b2776436ca diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/i-do-numbers b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/i-do-numbers new file mode 100644 index 000000000..882969dfc --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/i-do-numbers @@ -0,0 +1 @@ +7252fe2da2c4dd6d85231a150d0485ec46abaa7a diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/logo b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/logo new file mode 100644 index 000000000..2bbca050f --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/logo @@ -0,0 +1 @@ +a447ba2ca8fffd46dece72f7db6faf324afb8fcd diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/master b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/master new file mode 100644 index 000000000..bca334acf --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/master @@ -0,0 +1 @@ +32eab9cb1f450b5fe7ab663462b77d7f4b703344 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/track-local b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/track-local new file mode 100644 index 000000000..99098dc82 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/track-local @@ -0,0 +1 @@ +580c2111be43802dab11328176d94c391f1deae9 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/treesame_as_32eab b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/treesame_as_32eab new file mode 100644 index 000000000..2f412c398 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/heads/treesame_as_32eab @@ -0,0 +1 @@ +f705abffe7015f2beacf2abe7a36583ebee3487e diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/remotes/origin/HEAD b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 000000000..b827f0c47 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/HEAD b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/HEAD new file mode 100644 index 000000000..43d92a0f8 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/HEAD @@ -0,0 +1 @@ +ref: refs/heads/i-do-numbers diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/ORIG_HEAD b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/ORIG_HEAD new file mode 100644 index 000000000..882969dfc --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/ORIG_HEAD @@ -0,0 +1 @@ +7252fe2da2c4dd6d85231a150d0485ec46abaa7a diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/commondir b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/commondir new file mode 100644 index 000000000..aab0408ce --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/commondir @@ -0,0 +1 @@ +../.. diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir new file mode 100644 index 000000000..3644e42d1 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir @@ -0,0 +1 @@ +../../../../worktrees/i-do-numbers/.git diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/index b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/index new file mode 100644 index 0000000000000000000000000000000000000000..d8a77a02197d72a49625c84b48b8bdaf26bc34ac GIT binary patch literal 225 zcmZ?q402{*U|<5_D9fS?rk2ePVEV%hpb!i+E`hOtw2j~7=;HJI4{`#H(yxmD(M$cq zE5OIVomZNhlv-4*S5i>|RSYu6Y<<)bFn#v!7K9ln=H-g*{dn(OOxQ`SiS42M>mR6d zF|V{@;43aING;M$%gjlI85t7f>IyVNlEFy9fGc1w)B5*pM#sM!-#wcYz|CrLQ?%aw Y>G7`9bLKOO2wst@o4tT*qxt+l06bhnH2?qr literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/logs/HEAD b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/logs/HEAD new file mode 100644 index 000000000..f08b3ba25 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/logs/HEAD @@ -0,0 +1 @@ +7252fe2da2c4dd6d85231a150d0485ec46abaa7a 7252fe2da2c4dd6d85231a150d0485ec46abaa7a Mike Minns 1513714384 +0000 reset: moving to HEAD diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/HEAD b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/HEAD new file mode 100644 index 000000000..846e685a7 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/HEAD @@ -0,0 +1 @@ +ref: refs/heads/logo diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/ORIG_HEAD b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/ORIG_HEAD new file mode 100644 index 000000000..2bbca050f --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/ORIG_HEAD @@ -0,0 +1 @@ +a447ba2ca8fffd46dece72f7db6faf324afb8fcd diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/commondir b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/commondir new file mode 100644 index 000000000..aab0408ce --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/commondir @@ -0,0 +1 @@ +../.. diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir new file mode 100644 index 000000000..ad8863ee6 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir @@ -0,0 +1 @@ +../../../../worktrees/logo/.git diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/index b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/index new file mode 100644 index 0000000000000000000000000000000000000000..2b8b35b7744226508c04182519fcecb68aa6d518 GIT binary patch literal 475 zcmZ?q402{*U|<4b)+oz@0_|Bx-+<{w`*#4vprG+Bj0L1wTz59_Guv*%-f?Hnp6xli z8~#*p2xky9)K4l(%uCLQPs_|n)hnqeVE~(Rs4xXgUufQgFr#q^g3Z9aLfKH^+uDNu z7TY$NN86S9jy%41jDao4)zQV*6{HTNUx#;c0+_aqK7-JUVh(n9@uRy6YF?&%0N6Yr zjl(?N<)Uo|@4r|sle0fZXug9_nA3m5y$tMmspVkbLCtAj-~%>i+KUYA<`~W29&vP! zOr!XrB}ZLvJ(^%=X2!~Rl!3pvur#qKRW~O;JzuXNFCC~kB*+!yUtaXfP#iVEV-tKSrx*;~v+FQNr Q)A^r{(idh3n04y{0AcTs9{>OV literal 0 HcmV?d00001 diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/locked b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/locked new file mode 100644 index 000000000..9f0b8bf32 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/locked @@ -0,0 +1 @@ +Test lock reason diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/logs/HEAD b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/logs/HEAD new file mode 100644 index 000000000..ab8778340 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/logs/HEAD @@ -0,0 +1 @@ +a447ba2ca8fffd46dece72f7db6faf324afb8fcd a447ba2ca8fffd46dece72f7db6faf324afb8fcd Mike Minns 1513713776 +0000 reset: moving to HEAD diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/modified_staged_file.txt b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/modified_staged_file.txt new file mode 100644 index 000000000..e68bcc7b5 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/modified_staged_file.txt @@ -0,0 +1,2 @@ +a change +more files! diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/modified_unstaged_file.txt b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/modified_unstaged_file.txt new file mode 100644 index 000000000..da6fd6537 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/modified_unstaged_file.txt @@ -0,0 +1,2 @@ +some more text +more files! more files! diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new.txt b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new.txt new file mode 100644 index 000000000..a71586c1d --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new.txt @@ -0,0 +1 @@ +my new file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new_tracked_file.txt b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new_tracked_file.txt new file mode 100644 index 000000000..935a81d39 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new_tracked_file.txt @@ -0,0 +1 @@ +a new file diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new_untracked_file.txt b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new_untracked_file.txt new file mode 100644 index 000000000..d95f3ad14 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/new_untracked_file.txt @@ -0,0 +1 @@ +content diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/numbers.txt b/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/numbers.txt new file mode 100644 index 000000000..85e1bcbc0 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/numbers.txt @@ -0,0 +1,17 @@ +1 +2 +3 +4 +5 +6 +7 +7.2 +8 +9 +10 +11 +12 +13 +14 +15 +16 diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/super-file.txt b/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/super-file.txt new file mode 100644 index 000000000..f9ff5589e --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/super-file.txt @@ -0,0 +1,5 @@ +That's a terrible name! +I don't like it. +People look down at me and laugh. :-( +Really!!!! +Yeah! Better! diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/1/branch_file.txt b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/1/branch_file.txt new file mode 100644 index 000000000..edf0effbb --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/1/branch_file.txt @@ -0,0 +1 @@ +hi diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/README b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/README new file mode 100644 index 000000000..ca8c64728 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/README @@ -0,0 +1 @@ +hey there diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/branch_file.txt b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/branch_file.txt new file mode 100644 index 000000000..edf0effbb --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/branch_file.txt @@ -0,0 +1 @@ +hi diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/new.txt b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/new.txt new file mode 100644 index 000000000..8e0884e36 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/new.txt @@ -0,0 +1 @@ +my new file diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/square-logo.png b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/square-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b758c5bc1c8117c2a4c545dae2903e36360501c5 GIT binary patch literal 12959 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 w.Name, StringComparer.Ordinal); + + Assert.Equal(expectedWorktrees, worktrees.Select(w => w.Name).ToArray()); + } + } + + [Fact] + public void CanViewLockStatusForWorktrees() + { + var testpath = SandboxWorktreeTestRepo(); + var repoPath = testpath; + using (var repo = new Repository(repoPath)) + { + // locked + var worktreeLogo = repo.Worktrees["logo"]; + Assert.Equal("logo", worktreeLogo.Name); + Assert.True(worktreeLogo.IsLocked); + Assert.Equal("Test lock reason\n", worktreeLogo.LockReason); + + // not locked + var worktreeIDoNumbers = repo.Worktrees["i-do-numbers"]; + Assert.Equal("i-do-numbers", worktreeIDoNumbers.Name); + Assert.False(worktreeIDoNumbers.IsLocked); + Assert.Null(worktreeIDoNumbers.LockReason); + } + } + + [Fact] + public void CanGetRepositoryForWorktree() + { + var testpath = SandboxWorktreeTestRepo(); + var repoPath = testpath; + using (var repo = new Repository(repoPath)) + { + var worktree = repo.Worktrees["logo"]; + + Assert.Equal("logo", worktree.Name); + var worktreeRepo = worktree.WorktreeRepository; + Assert.NotNull(worktreeRepo); + } + } + } +} diff --git a/LibGit2Sharp.sln b/LibGit2Sharp.sln index 921aee2d4..43b82cf6c 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.26730.10 +VisualStudioVersion = 15.0.27009.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibGit2Sharp", "LibGit2Sharp\LibGit2Sharp.csproj", "{EE6ED99F-CB12-4683-B055-D28FC7357A34}" EndProject diff --git a/LibGit2Sharp/Core/Handles/Objects.cs b/LibGit2Sharp/Core/Handles/Objects.cs index f904b75b9..5f8db722e 100644 --- a/LibGit2Sharp/Core/Handles/Objects.cs +++ b/LibGit2Sharp/Core/Handles/Objects.cs @@ -556,4 +556,27 @@ public override void Free() } } + internal unsafe class WorktreeHandle : Libgit2Object + { + internal WorktreeHandle(git_worktree *ptr, bool owned) + : base((void *) ptr, owned) + { + } + + internal WorktreeHandle(IntPtr ptr, bool owned) + : base(ptr, owned) + { + } + + public override void Free() + { + NativeMethods.git_worktree_free((git_worktree*) ptr); + } + + public static implicit operator git_worktree*(WorktreeHandle handle) + { + return (git_worktree*) handle.Handle; + } + } + } diff --git a/LibGit2Sharp/Core/Handles/Objects.tt b/LibGit2Sharp/Core/Handles/Objects.tt index 3ecfe811e..a6d1fa251 100644 --- a/LibGit2Sharp/Core/Handles/Objects.tt +++ b/LibGit2Sharp/Core/Handles/Objects.tt @@ -36,6 +36,7 @@ var cNames = new[] { "git_object", "git_rebase", "git_odb_stream", + "git_worktree", }; var csNames = new[] { @@ -63,6 +64,7 @@ var csNames = new[] { "ObjectHandle", "RebaseHandle", "OdbStreamHandle", + "WorktreeHandle" }; for (var i = 0; i < cNames.Length; i++) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index fd0594384..064b9ba84 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -1888,6 +1888,35 @@ internal static extern unsafe int git_cherrypick_commit(out git_index* index, [DllImport(libgit2)] internal static extern void git_transaction_free(IntPtr txn); + + [DllImport(libgit2)] + internal static extern unsafe void git_worktree_free(git_worktree* worktree); + + [DllImport(libgit2)] + internal static extern unsafe int git_worktree_lookup( + out git_worktree* reference, + git_repository* repo, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); + + [DllImport(libgit2)] + internal static extern unsafe int git_worktree_list( + out GitStrArray array, + git_repository* repo); + + [DllImport(libgit2)] + internal static extern unsafe int git_repository_open_from_worktree( + out git_repository* repository, + git_worktree* worktree); + + [DllImport(libgit2)] + internal static extern unsafe int git_worktree_is_locked( + GitBuf reason, + git_worktree* worktree); + + [DllImport(libgit2)] + internal static extern unsafe int git_worktree_validate( + git_worktree* worktree); + } } // ReSharper restore InconsistentNaming diff --git a/LibGit2Sharp/Core/Opaques.cs b/LibGit2Sharp/Core/Opaques.cs index 0d0bb55f0..f5613a276 100644 --- a/LibGit2Sharp/Core/Opaques.cs +++ b/LibGit2Sharp/Core/Opaques.cs @@ -27,5 +27,6 @@ internal struct git_remote {} internal struct git_object {} internal struct git_rebase {} internal struct git_odb_stream {} + internal struct git_worktree { } } diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 4bf144524..d58305568 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3450,6 +3450,92 @@ public static void git_libgit2_opts_set_enable_strictobjectcreation(bool enabled #endregion + #region git_worktree_ + + ///

+ /// Returns a handle to the corresponding worktree, + /// or an invalid handle if a worktree is not found. + /// + public static unsafe WorktreeHandle git_worktree_lookup(RepositoryHandle repo, string name) + { + git_worktree* worktree; + var res = NativeMethods.git_worktree_lookup(out worktree, repo, name); + + switch (res) + { + case (int)GitErrorCode.Error: + case (int)GitErrorCode.NotFound: + case (int)GitErrorCode.Exists: + case (int)GitErrorCode.OrphanedHead: + return null; + + default: + Ensure.ZeroResult(res); + return new WorktreeHandle(worktree, true); + } + } + + public static unsafe IList git_worktree_list(RepositoryHandle repo) + { + var array = new GitStrArrayNative(); + + try + { + int res = NativeMethods.git_worktree_list(out array.Array, repo); + Ensure.ZeroResult(res); + + return array.ReadStrings(); + } + finally + { + array.Dispose(); + } + } + + public static unsafe RepositoryHandle git_repository_open_from_worktree(WorktreeHandle handle) + { + git_repository* repo; + int res = NativeMethods.git_repository_open_from_worktree(out repo, handle); + + if (res == (int)GitErrorCode.NotFound) + { + throw new RepositoryNotFoundException("Handle doesn't point at a valid Git repository or workdir."); + } + + Ensure.ZeroResult(res); + + return new RepositoryHandle(repo, true); + } + + public static unsafe WorktreeLock git_worktree_is_locked(WorktreeHandle worktree) + { + using (var buf = new GitBuf()) + { + int res = NativeMethods.git_worktree_is_locked(buf, worktree); + + if(res < 0) + { + // error + return null; + } + + if (res == (int)GitErrorCode.Ok) + { + return new WorktreeLock(); + } + + return new WorktreeLock(true, LaxUtf8Marshaler.FromNative(buf.ptr)); + } + } + + public static unsafe bool git_worktree_validate(WorktreeHandle worktree) + { + int res = NativeMethods.git_worktree_validate(worktree); + return res == (int)GitErrorCode.Ok; + } + + #endregion + private static ICollection git_foreach( Func resultSelector, Func, int> iterator, diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index d41ed810c..1be15d938 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -25,7 +25,10 @@ - + + True + True + @@ -34,6 +37,10 @@ + + + + diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index f49e2fcfc..4c64a47be 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -35,6 +35,7 @@ public sealed class Repository : IRepository private readonly Stack toCleanup = new Stack(); private readonly Ignore ignore; private readonly SubmoduleCollection submodules; + private readonly WorktreeCollection worktrees; private readonly Lazy pathCase; [Flags] @@ -91,7 +92,55 @@ public Repository(string path, RepositoryOptions options) : this(path, options, RepositoryRequiredParameter.Path | RepositoryRequiredParameter.Options) { } - + + internal Repository(WorktreeHandle worktreeHandle) + { + try + { + handle = Proxy.git_repository_open_from_worktree(worktreeHandle); + RegisterForCleanup(handle); + + isBare = Proxy.git_repository_is_bare(handle); + + Func indexBuilder = () => new Index(this); + + string configurationGlobalFilePath = null; + string configurationXDGFilePath = null; + string configurationSystemFilePath = null; + + if (!isBare) + { + index = new Lazy(() => indexBuilder()); + } + + commits = new CommitLog(this); + refs = new ReferenceCollection(this); + branches = new BranchCollection(this); + tags = new TagCollection(this); + stashes = new StashCollection(this); + info = new Lazy(() => new RepositoryInformation(this, isBare)); + config = new Lazy(() => RegisterForCleanup(new Configuration(this, + null, + configurationGlobalFilePath, + configurationXDGFilePath, + configurationSystemFilePath))); + odb = new Lazy(() => new ObjectDatabase(this)); + diff = new Diff(this); + notes = new NoteCollection(this); + ignore = new Ignore(this); + network = new Lazy(() => new Network(this)); + rebaseOperation = new Lazy(() => new Rebase(this)); + pathCase = new Lazy(() => new PathCase(this)); + submodules = new SubmoduleCollection(this); + worktrees = new WorktreeCollection(this); + } + catch + { + CleanupDisposableDependencies(); + throw; + } + } + private Repository(string path, RepositoryOptions options, RepositoryRequiredParameter requiredParameter) { if ((requiredParameter & RepositoryRequiredParameter.Path) == RepositoryRequiredParameter.Path) @@ -180,6 +229,7 @@ private Repository(string path, RepositoryOptions options, RepositoryRequiredPar rebaseOperation = new Lazy(() => new Rebase(this)); pathCase = new Lazy(() => new PathCase(this)); submodules = new SubmoduleCollection(this); + worktrees = new WorktreeCollection(this); EagerlyLoadComponentsWithSpecifiedPaths(options); } @@ -396,6 +446,14 @@ public SubmoduleCollection Submodules get { return submodules; } } + /// + /// Worktrees in the repository. + /// + public WorktreeCollection Worktrees + { + get { return worktrees; } + } + #region IDisposable Members /// diff --git a/LibGit2Sharp/Worktree.cs b/LibGit2Sharp/Worktree.cs new file mode 100644 index 000000000..b99e54528 --- /dev/null +++ b/LibGit2Sharp/Worktree.cs @@ -0,0 +1,106 @@ +using LibGit2Sharp.Core; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Text; + +namespace LibGit2Sharp +{ + /// + /// A Worktree. + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class Worktree : IEquatable, IBelongToARepository + { + private static readonly LambdaEqualityHelper equalityHelper = + new LambdaEqualityHelper(x => x.Name); + + private readonly Repository parent; + private readonly Repository worktree; + private readonly string name; + private readonly WorktreeLock worktreeLock; + + /// + /// Needed for mocking purposes. + /// + protected Worktree() + { } + + internal Worktree(Repository repo, string name, Repository worktree, WorktreeLock worktreeLock) + { + this.parent = repo; + this.name = name; + this.worktree = worktree; + this.worktreeLock = worktreeLock; + } + + /// + /// The name of the worktree. + /// + public virtual string Name { get { return name; } } + + /// + /// The Repository representation of the worktree + /// + public virtual Repository WorktreeRepository { get { return worktree; } } + + /// + /// A flag indicating if the worktree is locked or not. + /// + public virtual bool IsLocked { get { return worktreeLock == null ? false : worktreeLock.IsLocked; } } + + /// + /// Gets the reason associated with the lock + /// + public virtual string LockReason { get { return worktreeLock == null ? null : worktreeLock.Reason; } } + + /// + /// Determines whether the specified is equal to the current . + /// + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. + public override bool Equals(object obj) + { + return Equals(obj as Worktree); + } + + /// + /// Determines whether the specified is equal to the current . + /// + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. + public bool Equals(Worktree other) + { + return equalityHelper.Equals(this, other); + } + + /// + /// Returns the hash code for this instance. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() + { + return equalityHelper.GetHashCode(this); + } + + /// + /// Returns the , a representation of the current . + /// + /// The that represents the current . + public override string ToString() + { + return Name; + } + + private string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "{0} => {1}", Name, worktreeLock); + } + } + + IRepository IBelongToARepository.Repository { get { return parent; } } + } +} diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs new file mode 100644 index 000000000..2ce472f64 --- /dev/null +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -0,0 +1,100 @@ +using LibGit2Sharp.Core; +using LibGit2Sharp.Core.Handles; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; + +namespace LibGit2Sharp +{ + /// + /// The collection of worktrees in a + /// + public class WorktreeCollection : IEnumerable + { + internal readonly Repository repo; + + /// + /// Needed for mocking purposes. + /// + protected WorktreeCollection() + { } + + /// + /// Initializes a new instance of the class. + /// + /// The repo. + internal WorktreeCollection(Repository repo) + { + this.repo = repo; + } + + /// + /// Gets the with the specified name. + /// + public virtual Worktree this[string name] + { + get + { + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + + return Lookup(name, handle => new Worktree(repo, + name, + new Repository(handle), + Proxy.git_worktree_is_locked(handle))); + } + } + + internal T Lookup(string name, Func selector, bool throwIfNotFound = false) + { + using (var handle = Proxy.git_worktree_lookup(repo.Handle, name)) + { + if (handle != null && Proxy.git_worktree_validate(handle)) + { + return selector(handle); + } + + if (throwIfNotFound) + { + throw new LibGit2SharpException("Worktree lookup failed for '{0}'.", name); + } + + return default(T); + } + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An object that can be used to iterate through the collection. + public virtual IEnumerator GetEnumerator() + { + return Proxy.git_worktree_list(repo.Handle) + .Select(n => Lookup(n, handle => new Worktree(repo, n, + new Repository(handle), Proxy.git_worktree_is_locked(handle)))) + .GetEnumerator(); + //return Proxy.git_submodule_foreach(repo.Handle, (h, n) => LaxUtf8Marshaler.FromNative(n)) + // .Select(n => this[n]) + // .GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An object that can be used to iterate through the collection. + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + private string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "Count = {0}", this.Count()); + } + } + } +} diff --git a/LibGit2Sharp/WorktreeLock.cs b/LibGit2Sharp/WorktreeLock.cs new file mode 100644 index 000000000..c3751b996 --- /dev/null +++ b/LibGit2Sharp/WorktreeLock.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Text; + +namespace LibGit2Sharp +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class WorktreeLock + { + public WorktreeLock() : this(false, null) + { + + } + + public WorktreeLock(bool isLocked, string reason) + { + IsLocked = isLocked; + Reason = reason; + } + public bool IsLocked { get; } + public string Reason { get; } + + private string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "{0} => {1}", IsLocked, Reason); + } + } + } +} From 5ee02bdd7b166d98a41b45bd94b717d827ed9662 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Tue, 6 Feb 2018 10:41:25 +0000 Subject: [PATCH 103/384] Issue-1471 Added functionality to apply or remove locks. --- LibGit2Sharp.Tests/WorktreeFixture.cs | 46 +++++++++++++++++++++++++++ LibGit2Sharp/Core/NativeMethods.cs | 9 ++++++ LibGit2Sharp/Core/Proxy.cs | 15 +++++++++ LibGit2Sharp/Worktree.cs | 25 +++++++++++++-- LibGit2Sharp/WorktreeCollection.cs | 7 ++-- 5 files changed, 95 insertions(+), 7 deletions(-) diff --git a/LibGit2Sharp.Tests/WorktreeFixture.cs b/LibGit2Sharp.Tests/WorktreeFixture.cs index 7ddf2e60c..7f4cb7b31 100644 --- a/LibGit2Sharp.Tests/WorktreeFixture.cs +++ b/LibGit2Sharp.Tests/WorktreeFixture.cs @@ -71,6 +71,52 @@ public void CanViewLockStatusForWorktrees() } } + [Fact] + public void CanUnlockWorktree() + { + var testpath = SandboxWorktreeTestRepo(); + var repoPath = testpath; + using (var repo = new Repository(repoPath)) + { + // locked + var worktreeLocked = repo.Worktrees["logo"]; + Assert.Equal("logo", worktreeLocked.Name); + Assert.True(worktreeLocked.IsLocked); + Assert.Equal("Test lock reason\n", worktreeLocked.LockReason); + + worktreeLocked.Unlock(); + + // not locked + var worktreeUnlocked = repo.Worktrees["logo"]; + Assert.Equal("logo", worktreeLocked.Name); + Assert.False(worktreeUnlocked.IsLocked); + Assert.Null(worktreeUnlocked.LockReason); + } + } + + [Fact] + public void CanLockWorktree() + { + var testpath = SandboxWorktreeTestRepo(); + var repoPath = testpath; + using (var repo = new Repository(repoPath)) + { + // locked + var worktreeUnlocked = repo.Worktrees["i-do-numbers"]; + Assert.Equal("i-do-numbers", worktreeUnlocked.Name); + Assert.False(worktreeUnlocked.IsLocked); + Assert.Null(worktreeUnlocked.LockReason); + + worktreeUnlocked.Lock("add a lock"); + + // not locked + var worktreeLocked = repo.Worktrees["i-do-numbers"]; + Assert.Equal("i-do-numbers", worktreeLocked.Name); + Assert.True(worktreeLocked.IsLocked); + Assert.Equal("add a lock", worktreeLocked.LockReason); + } + } + [Fact] public void CanGetRepositoryForWorktree() { diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 064b9ba84..ca08a11d1 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -1917,6 +1917,15 @@ internal static extern unsafe int git_worktree_is_locked( internal static extern unsafe int git_worktree_validate( git_worktree* worktree); + [DllImport(libgit2)] + internal static extern unsafe int git_worktree_lock( + git_worktree* worktree, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string reason); + + [DllImport(libgit2)] + internal static extern unsafe int git_worktree_unlock( + git_worktree* worktree); + } } // ReSharper restore InconsistentNaming diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index d58305568..71e44c84c 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3531,6 +3531,21 @@ public static unsafe WorktreeLock git_worktree_is_locked(WorktreeHandle worktree public static unsafe bool git_worktree_validate(WorktreeHandle worktree) { int res = NativeMethods.git_worktree_validate(worktree); + + return res == (int)GitErrorCode.Ok; + } + + public static unsafe bool git_worktree_unlock(WorktreeHandle worktree) + { + int res = NativeMethods.git_worktree_unlock(worktree); + + return res == (int)GitErrorCode.Ok; + } + + public static unsafe bool git_worktree_lock(WorktreeHandle worktree, string reason) + { + int res = NativeMethods.git_worktree_lock(worktree, reason); + return res == (int)GitErrorCode.Ok; } diff --git a/LibGit2Sharp/Worktree.cs b/LibGit2Sharp/Worktree.cs index b99e54528..4f539081d 100644 --- a/LibGit2Sharp/Worktree.cs +++ b/LibGit2Sharp/Worktree.cs @@ -1,4 +1,5 @@ using LibGit2Sharp.Core; +using LibGit2Sharp.Core.Handles; using System; using System.Collections.Generic; using System.Diagnostics; @@ -16,10 +17,11 @@ public class Worktree : IEquatable, IBelongToARepository private static readonly LambdaEqualityHelper equalityHelper = new LambdaEqualityHelper(x => x.Name); + private readonly WorktreeHandle handle; private readonly Repository parent; private readonly Repository worktree; private readonly string name; - private readonly WorktreeLock worktreeLock; + private WorktreeLock worktreeLock; /// /// Needed for mocking purposes. @@ -27,8 +29,9 @@ public class Worktree : IEquatable, IBelongToARepository protected Worktree() { } - internal Worktree(Repository repo, string name, Repository worktree, WorktreeLock worktreeLock) + internal Worktree(WorktreeHandle handle, Repository repo, string name, Repository worktree, WorktreeLock worktreeLock) { + this.handle = Proxy.git_worktree_lookup(repo.Handle, name); this.parent = repo; this.name = name; this.worktree = worktree; @@ -75,6 +78,24 @@ public bool Equals(Worktree other) return equalityHelper.Equals(this, other); } + /// + /// Unlock the worktree + /// + public void Unlock() + { + Proxy.git_worktree_unlock(handle); + this.worktreeLock = Proxy.git_worktree_is_locked(handle); + } + + /// + /// Lock the worktree + /// + public void Lock(string reason) + { + Proxy.git_worktree_lock(handle, reason); + this.worktreeLock = Proxy.git_worktree_is_locked(handle); + } + /// /// Returns the hash code for this instance. /// diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs index 2ce472f64..24865f8c5 100644 --- a/LibGit2Sharp/WorktreeCollection.cs +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -40,7 +40,7 @@ public virtual Worktree this[string name] { Ensure.ArgumentNotNullOrEmptyString(name, "name"); - return Lookup(name, handle => new Worktree(repo, + return Lookup(name, handle => new Worktree(handle, repo, name, new Repository(handle), Proxy.git_worktree_is_locked(handle))); @@ -72,12 +72,9 @@ internal T Lookup(string name, Func selector, bool throwIf public virtual IEnumerator GetEnumerator() { return Proxy.git_worktree_list(repo.Handle) - .Select(n => Lookup(n, handle => new Worktree(repo, n, + .Select(n => Lookup(n, handle => new Worktree(handle, repo, n, new Repository(handle), Proxy.git_worktree_is_locked(handle)))) .GetEnumerator(); - //return Proxy.git_submodule_foreach(repo.Handle, (h, n) => LaxUtf8Marshaler.FromNative(n)) - // .Select(n => this[n]) - // .GetEnumerator(); } /// From aba76876ed98091e7db5bf2d527c3621555eeab0 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Wed, 7 Feb 2018 18:51:16 +0000 Subject: [PATCH 104/384] Issue-1471 Added functionality to add and prune worktrees --- LibGit2Sharp.Tests/WorktreeFixture.cs | 138 +++++++++++++++++++++++++- LibGit2Sharp/Core/GitWorktree.cs | 47 +++++++++ LibGit2Sharp/Core/NativeMethods.cs | 12 +++ LibGit2Sharp/Core/Proxy.cs | 20 ++++ LibGit2Sharp/IRepository.cs | 5 + LibGit2Sharp/Worktree.cs | 6 +- LibGit2Sharp/WorktreeCollection.cs | 98 ++++++++++++++++++ LibGit2Sharp/WorktreeLock.cs | 4 +- 8 files changed, 323 insertions(+), 7 deletions(-) create mode 100644 LibGit2Sharp/Core/GitWorktree.cs diff --git a/LibGit2Sharp.Tests/WorktreeFixture.cs b/LibGit2Sharp.Tests/WorktreeFixture.cs index 7f4cb7b31..0d32ee9f3 100644 --- a/LibGit2Sharp.Tests/WorktreeFixture.cs +++ b/LibGit2Sharp.Tests/WorktreeFixture.cs @@ -1,6 +1,7 @@ using LibGit2Sharp.Tests.TestHelpers; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -86,7 +87,7 @@ public void CanUnlockWorktree() worktreeLocked.Unlock(); - // not locked + // unlocked var worktreeUnlocked = repo.Worktrees["logo"]; Assert.Equal("logo", worktreeLocked.Name); Assert.False(worktreeUnlocked.IsLocked); @@ -101,7 +102,7 @@ public void CanLockWorktree() var repoPath = testpath; using (var repo = new Repository(repoPath)) { - // locked + // unlocked var worktreeUnlocked = repo.Worktrees["i-do-numbers"]; Assert.Equal("i-do-numbers", worktreeUnlocked.Name); Assert.False(worktreeUnlocked.IsLocked); @@ -109,7 +110,7 @@ public void CanLockWorktree() worktreeUnlocked.Lock("add a lock"); - // not locked + // locked var worktreeLocked = repo.Worktrees["i-do-numbers"]; Assert.Equal("i-do-numbers", worktreeLocked.Name); Assert.True(worktreeLocked.IsLocked); @@ -131,5 +132,136 @@ public void CanGetRepositoryForWorktree() Assert.NotNull(worktreeRepo); } } + + [Fact] + public void CanPruneUnlockedWorktree() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + + // unlocked + var worktreeUnlocked = repo.Worktrees["i-do-numbers"]; + Assert.Equal("i-do-numbers", worktreeUnlocked.Name); + Assert.False(worktreeUnlocked.IsLocked); + + Assert.True(repo.Worktrees.Prune(worktreeUnlocked)); + + Assert.Single(repo.Worktrees); + } + } + + [Fact] + public void CanNotPruneLockedWorktree() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + + // locked + var worktreeUnlocked = repo.Worktrees["logo"]; + Assert.Equal("logo", worktreeUnlocked.Name); + Assert.True(worktreeUnlocked.IsLocked); + + Assert.Throws(() => repo.Worktrees.Prune(worktreeUnlocked)); + } + } + + [Fact] + public void CanUnlockThenPruneLockedWorktree() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + + // locked + var worktreeLocked = repo.Worktrees["logo"]; + Assert.Equal("logo", worktreeLocked.Name); + Assert.True(worktreeLocked.IsLocked); + + worktreeLocked.Unlock(); + + repo.Worktrees.Prune(worktreeLocked); + + Assert.Single(repo.Worktrees); + } + } + + [Fact] + public void CanForcePruneLockedWorktree() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + + // locked + var worktreeLocked = repo.Worktrees["logo"]; + Assert.Equal("logo", worktreeLocked.Name); + Assert.True(worktreeLocked.IsLocked); + + repo.Worktrees.Prune(worktreeLocked, true); + + Assert.Single(repo.Worktrees); + } + } + + [Fact] + public void CanAddWorktree() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + + var name = "blah"; + var path = Path.Combine(repo.Info.WorkingDirectory, @"..\worktrees", name); + var worktree = repo.Worktrees.Add(name, path, false); + Assert.Equal(name, worktree.Name); + Assert.False(worktree.IsLocked); + + Assert.Equal(3, repo.Worktrees.Count()); + } + } + + [Fact] + public void CanAddLockedWorktree() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + + var name = "blah"; + var path = Path.Combine(repo.Info.WorkingDirectory, @"..\worktrees", name); + var worktree = repo.Worktrees.Add(name, path, true); + Assert.Equal(name, worktree.Name); + Assert.True(worktree.IsLocked); + + Assert.Equal(3, repo.Worktrees.Count()); + } + } + + [Fact] + public void CanAddWorktreeForCommittish() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + + var name = "blah"; + var committish = "diff-test-cases"; + var path = Path.Combine(repo.Info.WorkingDirectory, @"..\worktrees", name); + var worktree = repo.Worktrees.Add(committish, name, path, false); + Assert.Equal(name, worktree.Name); + Assert.False(worktree.IsLocked); + Assert.Equal(committish, worktree.WorktreeRepository.Head.FriendlyName); + Assert.Equal(3, repo.Worktrees.Count()); + } + } } } diff --git a/LibGit2Sharp/Core/GitWorktree.cs b/LibGit2Sharp/Core/GitWorktree.cs new file mode 100644 index 000000000..64f90ebb7 --- /dev/null +++ b/LibGit2Sharp/Core/GitWorktree.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace LibGit2Sharp.Core +{ + /** + * Flags which can be passed to git_worktree_prune to alter its + * behavior. + */ + [Flags] + internal enum GitWorktreePruneOptionFlags : uint + { + /// + /// Prune working tree even if working tree is valid + /// + GIT_WORKTREE_PRUNE_VALID = (1u << 0), + + /// + /// Prune working tree even if it is locked + /// + GIT_WORKTREE_PRUNE_LOCKED = (1u << 1), + + /// + /// Prune checked out working tree + /// + GIT_WORKTREE_PRUNE_WORKING_TREE = (1u << 2) + } + + + [StructLayout(LayoutKind.Sequential)] + internal class git_worktree_add_options + { + public uint version = 1; + + public int locked; + } + + [StructLayout(LayoutKind.Sequential)] + internal class git_worktree_prune_options + { + public uint version = 1; + + public GitWorktreePruneOptionFlags flags; + } +} diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index ca08a11d1..56d836b0f 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -1926,6 +1926,18 @@ internal static extern unsafe int git_worktree_lock( internal static extern unsafe int git_worktree_unlock( git_worktree* worktree); + [DllImport(libgit2)] + 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, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path, + git_worktree_add_options options); + + [DllImport(libgit2)] + internal static extern unsafe int git_worktree_prune( + git_worktree* worktree, + git_worktree_prune_options options); } } // ReSharper restore InconsistentNaming diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 71e44c84c..b8e607ecd 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3549,6 +3549,26 @@ public static unsafe bool git_worktree_lock(WorktreeHandle worktree, string reas return res == (int)GitErrorCode.Ok; } + public static unsafe WorktreeHandle git_worktree_add( + RepositoryHandle repo, + string name, + string path, + git_worktree_add_options options) + { + git_worktree* worktree; + int res = NativeMethods.git_worktree_add(out worktree, repo, name, path, options); + Ensure.ZeroResult(res); + return new WorktreeHandle(worktree, true); + } + + public static unsafe bool git_worktree_prune(WorktreeHandle worktree, + git_worktree_prune_options options) + { + int res = NativeMethods.git_worktree_prune(worktree, options); + Ensure.ZeroResult(res); + return true; + } + #endregion private static ICollection git_foreach( diff --git a/LibGit2Sharp/IRepository.cs b/LibGit2Sharp/IRepository.cs index e97a84c92..35eb34f13 100644 --- a/LibGit2Sharp/IRepository.cs +++ b/LibGit2Sharp/IRepository.cs @@ -69,6 +69,11 @@ public interface IRepository : IDisposable /// SubmoduleCollection Submodules { get; } + /// + /// Worktrees in the repository. + /// + WorktreeCollection Worktrees { get; } + /// /// Checkout the specified tree. /// diff --git a/LibGit2Sharp/Worktree.cs b/LibGit2Sharp/Worktree.cs index 4f539081d..9698634e0 100644 --- a/LibGit2Sharp/Worktree.cs +++ b/LibGit2Sharp/Worktree.cs @@ -81,7 +81,7 @@ public bool Equals(Worktree other) /// /// Unlock the worktree /// - public void Unlock() + public virtual void Unlock() { Proxy.git_worktree_unlock(handle); this.worktreeLock = Proxy.git_worktree_is_locked(handle); @@ -90,7 +90,7 @@ public void Unlock() /// /// Lock the worktree /// - public void Lock(string reason) + public virtual void Lock(string reason) { Proxy.git_worktree_lock(handle, reason); this.worktreeLock = Proxy.git_worktree_is_locked(handle); @@ -123,5 +123,7 @@ private string DebuggerDisplay } IRepository IBelongToARepository.Repository { get { return parent; } } + + internal WorktreeHandle Handle { get { return this.handle; } } } } diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs index 24865f8c5..69bb02c06 100644 --- a/LibGit2Sharp/WorktreeCollection.cs +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Text; @@ -47,6 +48,103 @@ public virtual Worktree this[string name] } } + /// + /// + /// + /// + /// + /// + /// + /// + public virtual Worktree Add(string committishOrBranchSpec, string name, string path, bool isLocked) + { + if(string.Equals(committishOrBranchSpec, name)) + { + // Proxy.git_worktree_add() creates a new branch of name = name, so if we want to checkout a given branch then the 'name' cannot be the same as the target branch + return null; + } + + git_worktree_add_options options = new git_worktree_add_options + { + version = 1, + locked = Convert.ToInt32(isLocked) + }; + + var handle = Proxy.git_worktree_add(repo.Handle, name, path, options); + var worktree = new Worktree(handle, + repo, + name, + new Repository(handle), + Proxy.git_worktree_is_locked(handle)); + + // switch the worktree to the target branch + Commands.Checkout(worktree.WorktreeRepository, committishOrBranchSpec); + + return this[name]; + } + + /// + /// + /// + /// + /// + /// + public virtual Worktree Add(string name, string path, bool isLocked) + { + git_worktree_add_options options = new git_worktree_add_options + { + version = 1, + locked = Convert.ToInt32(isLocked) + }; + + var handle = Proxy.git_worktree_add(repo.Handle, name, path, options); + return new Worktree(handle, + repo, + name, + new Repository(handle), + Proxy.git_worktree_is_locked(handle)); + } + + /// + /// + /// + /// + /// + public virtual bool Prune(Worktree worktree) + { + return Prune(worktree, false); + } + + /// + /// + /// + /// + /// + /// + public virtual bool Prune(Worktree worktree, bool ifLocked) + { + string wd = worktree.WorktreeRepository.Info.WorkingDirectory; + + if (!Directory.Exists(wd)) + { + return false; + } + + git_worktree_prune_options options = new git_worktree_prune_options + { + version = 1, + // default + flags = GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_WORKING_TREE | GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_VALID + }; + + if (ifLocked) + { + options.flags |= GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_LOCKED; + } + + return Proxy.git_worktree_prune(worktree.Handle, options); + } + internal T Lookup(string name, Func selector, bool throwIfNotFound = false) { using (var handle = Proxy.git_worktree_lookup(repo.Handle, name)) diff --git a/LibGit2Sharp/WorktreeLock.cs b/LibGit2Sharp/WorktreeLock.cs index c3751b996..7362102ab 100644 --- a/LibGit2Sharp/WorktreeLock.cs +++ b/LibGit2Sharp/WorktreeLock.cs @@ -19,8 +19,8 @@ public WorktreeLock(bool isLocked, string reason) IsLocked = isLocked; Reason = reason; } - public bool IsLocked { get; } - public string Reason { get; } + public virtual bool IsLocked { get; } + public virtual string Reason { get; } private string DebuggerDisplay { From e87a9fb6fdfc5f27f7d5407731ca388893e1ba48 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Tue, 18 Sep 2018 20:31:21 +0100 Subject: [PATCH 105/384] Issue-1471 The paths in the dot_git\worktree\repo\gitdir file are very fragile. In real life they will use absolute paths, but luckily they do work with relative paths, but they have a habit of getting re-written as soon as you use Git to inspect the repository --- .../worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir | 2 +- .../worktree/testrepo_wd/dot_git/worktrees/logo/gitdir | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir index 3644e42d1..9e981bbab 100644 --- a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir @@ -1 +1 @@ -../../../../worktrees/i-do-numbers/.git +../../worktrees/i-do-numbers/.git diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir index ad8863ee6..d6b6e3aca 100644 --- a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir @@ -1 +1 @@ -../../../../worktrees/logo/.git +../../worktrees/logo/.git From 60d4e67438b57dbf2589c5fc82dc72345fd2a65b Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Tue, 25 Sep 2018 20:45:48 +0100 Subject: [PATCH 106/384] Issue-1471 Fix handle leaks --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- LibGit2Sharp.Tests/WorktreeFixture.cs | 11 ++- LibGit2Sharp/Core/Handles/Libgit2Object.cs | 2 +- LibGit2Sharp/LibGit2Sharp.csproj | 4 + LibGit2Sharp/Repository.cs | 1 + LibGit2Sharp/Worktree.cs | 34 +++++--- LibGit2Sharp/WorktreeCollection.cs | 83 +++++++++++--------- 7 files changed, 84 insertions(+), 53 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 68ea2cfd0..94ed29028 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -2,7 +2,7 @@ net461;netcoreapp2.0 - $(DefineConstants);DESKTOP + TRACE;DEBUG;DESKTOP;NET461;LEAKS_IDENTIFYING;LEAKS_TRACKING diff --git a/LibGit2Sharp.Tests/WorktreeFixture.cs b/LibGit2Sharp.Tests/WorktreeFixture.cs index 0d32ee9f3..ca27f9b51 100644 --- a/LibGit2Sharp.Tests/WorktreeFixture.cs +++ b/LibGit2Sharp.Tests/WorktreeFixture.cs @@ -128,8 +128,10 @@ public void CanGetRepositoryForWorktree() var worktree = repo.Worktrees["logo"]; Assert.Equal("logo", worktree.Name); - var worktreeRepo = worktree.WorktreeRepository; - Assert.NotNull(worktreeRepo); + using (var repository = worktree.WorktreeRepository) + { + Assert.NotNull(repository); + } } } @@ -259,7 +261,10 @@ public void CanAddWorktreeForCommittish() var worktree = repo.Worktrees.Add(committish, name, path, false); Assert.Equal(name, worktree.Name); Assert.False(worktree.IsLocked); - Assert.Equal(committish, worktree.WorktreeRepository.Head.FriendlyName); + using (var repository = worktree.WorktreeRepository) + { + Assert.Equal(committish, repository.Head.FriendlyName); + } Assert.Equal(3, repo.Worktrees.Count()); } } diff --git a/LibGit2Sharp/Core/Handles/Libgit2Object.cs b/LibGit2Sharp/Core/Handles/Libgit2Object.cs index 8b255a3f0..892ebde90 100644 --- a/LibGit2Sharp/Core/Handles/Libgit2Object.cs +++ b/LibGit2Sharp/Core/Handles/Libgit2Object.cs @@ -138,7 +138,7 @@ internal IntPtr AsIntPtr() void Dispose(bool disposing) { - #if LEAKS_IDENTIFYING +#if LEAKS_IDENTIFYING bool leaked = !disposing && ptr != null; if (leaked) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 1be15d938..2e376e2c0 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -16,6 +16,10 @@ ..\libgit2sharp.snk + + TRACE;DEBUG;NETSTANDARD2_0;LEAKS_IDENTIFYING;LEAKS_TRACKING + + diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 4c64a47be..b6399af45 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -99,6 +99,7 @@ internal Repository(WorktreeHandle worktreeHandle) { handle = Proxy.git_repository_open_from_worktree(worktreeHandle); RegisterForCleanup(handle); + RegisterForCleanup(worktreeHandle); isBare = Proxy.git_repository_is_bare(handle); diff --git a/LibGit2Sharp/Worktree.cs b/LibGit2Sharp/Worktree.cs index 9698634e0..13fea072b 100644 --- a/LibGit2Sharp/Worktree.cs +++ b/LibGit2Sharp/Worktree.cs @@ -17,9 +17,8 @@ public class Worktree : IEquatable, IBelongToARepository private static readonly LambdaEqualityHelper equalityHelper = new LambdaEqualityHelper(x => x.Name); - private readonly WorktreeHandle handle; private readonly Repository parent; - private readonly Repository worktree; + //private readonly Repository worktree; private readonly string name; private WorktreeLock worktreeLock; @@ -29,15 +28,22 @@ public class Worktree : IEquatable, IBelongToARepository protected Worktree() { } - internal Worktree(WorktreeHandle handle, Repository repo, string name, Repository worktree, WorktreeLock worktreeLock) + internal Worktree(Repository repo, string name, WorktreeLock worktreeLock) { - this.handle = Proxy.git_worktree_lookup(repo.Handle, name); this.parent = repo; this.name = name; - this.worktree = worktree; this.worktreeLock = worktreeLock; } + /// + /// + /// + /// + internal WorktreeHandle GetWorktreeHandle() + { + return Proxy.git_worktree_lookup(parent.Handle, name); + } + /// /// The name of the worktree. /// @@ -46,7 +52,7 @@ internal Worktree(WorktreeHandle handle, Repository repo, string name, Repositor /// /// The Repository representation of the worktree /// - public virtual Repository WorktreeRepository { get { return worktree; } } + public virtual Repository WorktreeRepository { get { return new Repository(GetWorktreeHandle()); } } /// /// A flag indicating if the worktree is locked or not. @@ -83,8 +89,11 @@ public bool Equals(Worktree other) /// public virtual void Unlock() { - Proxy.git_worktree_unlock(handle); - this.worktreeLock = Proxy.git_worktree_is_locked(handle); + using (var handle = GetWorktreeHandle()) + { + Proxy.git_worktree_unlock(handle); + this.worktreeLock = Proxy.git_worktree_is_locked(handle); + } } /// @@ -92,8 +101,11 @@ public virtual void Unlock() /// public virtual void Lock(string reason) { - Proxy.git_worktree_lock(handle, reason); - this.worktreeLock = Proxy.git_worktree_is_locked(handle); + using (var handle = GetWorktreeHandle()) + { + Proxy.git_worktree_lock(handle, reason); + this.worktreeLock = Proxy.git_worktree_is_locked(handle); + } } /// @@ -123,7 +135,5 @@ private string DebuggerDisplay } IRepository IBelongToARepository.Repository { get { return parent; } } - - internal WorktreeHandle Handle { get { return this.handle; } } } } diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs index 69bb02c06..7b288d551 100644 --- a/LibGit2Sharp/WorktreeCollection.cs +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -41,9 +41,8 @@ public virtual Worktree this[string name] { Ensure.ArgumentNotNullOrEmptyString(name, "name"); - return Lookup(name, handle => new Worktree(handle, repo, + return Lookup(name, handle => new Worktree(repo, name, - new Repository(handle), Proxy.git_worktree_is_locked(handle))); } } @@ -70,15 +69,21 @@ public virtual Worktree Add(string committishOrBranchSpec, string name, string p locked = Convert.ToInt32(isLocked) }; - var handle = Proxy.git_worktree_add(repo.Handle, name, path, options); - var worktree = new Worktree(handle, - repo, - name, - new Repository(handle), - Proxy.git_worktree_is_locked(handle)); + using (var handle = Proxy.git_worktree_add(repo.Handle, name, path, options)) + { + var worktree = new Worktree( + repo, + name, + Proxy.git_worktree_is_locked(handle)); + + // switch the worktree to the target branch + using (var repository = worktree.WorktreeRepository) + { + Commands.Checkout(repository, committishOrBranchSpec); + } + } - // switch the worktree to the target branch - Commands.Checkout(worktree.WorktreeRepository, committishOrBranchSpec); + return this[name]; } @@ -97,12 +102,13 @@ public virtual Worktree Add(string name, string path, bool isLocked) locked = Convert.ToInt32(isLocked) }; - var handle = Proxy.git_worktree_add(repo.Handle, name, path, options); - return new Worktree(handle, - repo, - name, - new Repository(handle), - Proxy.git_worktree_is_locked(handle)); + using (var handle = Proxy.git_worktree_add(repo.Handle, name, path, options)) + { + return new Worktree( + repo, + name, + Proxy.git_worktree_is_locked(handle)); + } } /// @@ -123,26 +129,32 @@ public virtual bool Prune(Worktree worktree) /// public virtual bool Prune(Worktree worktree, bool ifLocked) { - string wd = worktree.WorktreeRepository.Info.WorkingDirectory; - - if (!Directory.Exists(wd)) - { - return false; - } - - git_worktree_prune_options options = new git_worktree_prune_options + using (var handle = worktree.GetWorktreeHandle()) { - version = 1, - // default - flags = GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_WORKING_TREE | GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_VALID - }; - - if (ifLocked) - { - options.flags |= GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_LOCKED; + using (var repository = worktree.WorktreeRepository) + { + string wd = repository.Info.WorkingDirectory; + + if (!Directory.Exists(wd)) + { + return false; + } + + git_worktree_prune_options options = new git_worktree_prune_options + { + version = 1, + // default + flags = GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_WORKING_TREE | GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_VALID + }; + + if (ifLocked) + { + options.flags |= GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_LOCKED; + } + + return Proxy.git_worktree_prune(handle, options); + } } - - return Proxy.git_worktree_prune(worktree.Handle, options); } internal T Lookup(string name, Func selector, bool throwIfNotFound = false) @@ -170,8 +182,7 @@ internal T Lookup(string name, Func selector, bool throwIf public virtual IEnumerator GetEnumerator() { return Proxy.git_worktree_list(repo.Handle) - .Select(n => Lookup(n, handle => new Worktree(handle, repo, n, - new Repository(handle), Proxy.git_worktree_is_locked(handle)))) + .Select(n => Lookup(n, handle => new Worktree(repo, n, Proxy.git_worktree_is_locked(handle)))) .GetEnumerator(); } From 049d3137c2d55906b65185ae3dae286179585bb0 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Fri, 28 Sep 2018 10:12:39 +0100 Subject: [PATCH 107/384] Issue-1471 Undo setting of LEAK constants --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 94ed29028..68ea2cfd0 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -2,7 +2,7 @@ net461;netcoreapp2.0 - TRACE;DEBUG;DESKTOP;NET461;LEAKS_IDENTIFYING;LEAKS_TRACKING + $(DefineConstants);DESKTOP From e642bf9ab5f22a5539d32590d07c4dd1ad768b02 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Fri, 28 Sep 2018 11:27:40 +0100 Subject: [PATCH 108/384] Issue-1471 ensure the directory stuctures used in worktree tests are cross-platform compatible --- LibGit2Sharp.Tests/WorktreeFixture.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/WorktreeFixture.cs b/LibGit2Sharp.Tests/WorktreeFixture.cs index ca27f9b51..896abdb96 100644 --- a/LibGit2Sharp.Tests/WorktreeFixture.cs +++ b/LibGit2Sharp.Tests/WorktreeFixture.cs @@ -220,7 +220,7 @@ public void CanAddWorktree() Assert.Equal(2, repo.Worktrees.Count()); var name = "blah"; - var path = Path.Combine(repo.Info.WorkingDirectory, @"..\worktrees", name); + var path = Path.Combine(repo.Info.WorkingDirectory, "..", "worktrees", name); var worktree = repo.Worktrees.Add(name, path, false); Assert.Equal(name, worktree.Name); Assert.False(worktree.IsLocked); @@ -238,7 +238,7 @@ public void CanAddLockedWorktree() Assert.Equal(2, repo.Worktrees.Count()); var name = "blah"; - var path = Path.Combine(repo.Info.WorkingDirectory, @"..\worktrees", name); + var path = Path.Combine(repo.Info.WorkingDirectory, "..", "worktrees", name); var worktree = repo.Worktrees.Add(name, path, true); Assert.Equal(name, worktree.Name); Assert.True(worktree.IsLocked); @@ -257,7 +257,7 @@ public void CanAddWorktreeForCommittish() var name = "blah"; var committish = "diff-test-cases"; - var path = Path.Combine(repo.Info.WorkingDirectory, @"..\worktrees", name); + var path = Path.Combine(repo.Info.WorkingDirectory, "..", "worktrees", name); var worktree = repo.Worktrees.Add(committish, name, path, false); Assert.Equal(name, worktree.Name); Assert.False(worktree.IsLocked); From bd98667dfd0cbc9ab5aa823256a39663bed54a6a Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Tue, 23 Oct 2018 20:40:06 +0100 Subject: [PATCH 109/384] Issue-1471 Added the ability to prune already deleted repositories. Fixed test data to correctly reference the worktree's working directories --- .../dot_git/worktrees/i-do-numbers/gitdir | 2 +- .../testrepo_wd/dot_git/worktrees/logo/gitdir | 2 +- LibGit2Sharp.Tests/WorktreeFixture.cs | 23 +++++++++++++ LibGit2Sharp/WorktreeCollection.cs | 32 +++++++------------ 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir index 9e981bbab..3644e42d1 100644 --- a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/i-do-numbers/gitdir @@ -1 +1 @@ -../../worktrees/i-do-numbers/.git +../../../../worktrees/i-do-numbers/.git diff --git a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir index d6b6e3aca..ad8863ee6 100644 --- a/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir +++ b/LibGit2Sharp.Tests/Resources/worktree/testrepo_wd/dot_git/worktrees/logo/gitdir @@ -1 +1 @@ -../../worktrees/logo/.git +../../../../worktrees/logo/.git diff --git a/LibGit2Sharp.Tests/WorktreeFixture.cs b/LibGit2Sharp.Tests/WorktreeFixture.cs index 896abdb96..ada939317 100644 --- a/LibGit2Sharp.Tests/WorktreeFixture.cs +++ b/LibGit2Sharp.Tests/WorktreeFixture.cs @@ -154,6 +154,29 @@ public void CanPruneUnlockedWorktree() } } + [Fact] + public void CanPruneDeletedWorktree() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + var repoPath2 = repo.Info.Path; + var repoWd = repo.Info.WorkingDirectory; + // unlocked + var worktreeUnlocked = repo.Worktrees["i-do-numbers"]; + Assert.Equal("i-do-numbers", worktreeUnlocked.Name); + Assert.False(worktreeUnlocked.IsLocked); + var info = worktreeUnlocked.WorktreeRepository.Info; + + Directory.Delete(info.WorkingDirectory, true); + + Assert.True(repo.Worktrees.Prune(worktreeUnlocked)); + + Assert.Single(repo.Worktrees); + } + } + [Fact] public void CanNotPruneLockedWorktree() { diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs index 7b288d551..9822e882c 100644 --- a/LibGit2Sharp/WorktreeCollection.cs +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -131,29 +131,19 @@ public virtual bool Prune(Worktree worktree, bool ifLocked) { using (var handle = worktree.GetWorktreeHandle()) { - using (var repository = worktree.WorktreeRepository) + git_worktree_prune_options options = new git_worktree_prune_options + { + version = 1, + // default + flags = GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_WORKING_TREE | GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_VALID + }; + + if (ifLocked) { - string wd = repository.Info.WorkingDirectory; - - if (!Directory.Exists(wd)) - { - return false; - } - - git_worktree_prune_options options = new git_worktree_prune_options - { - version = 1, - // default - flags = GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_WORKING_TREE | GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_VALID - }; - - if (ifLocked) - { - options.flags |= GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_LOCKED; - } - - return Proxy.git_worktree_prune(handle, options); + options.flags |= GitWorktreePruneOptionFlags.GIT_WORKTREE_PRUNE_LOCKED; } + + return Proxy.git_worktree_prune(handle, options); } } From 0b69d4d427633772cdeb25eb9d7b9e10c3e83b91 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Tue, 23 Oct 2018 21:06:31 +0100 Subject: [PATCH 110/384] Issue-1471 Corrected tests. --- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index dfecc00df..d15462b83 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -87,8 +87,8 @@ private static void SetUpTestEnvironment() AssumeUnchangedRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "assume_unchanged_wd"); SubmoduleSmallTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_small_wd"); PackBuilderTestRepoPath = Path.Combine(ResourcesDirectory.FullName, "packbuilder_testrepo_wd"); - WorktreeTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "worktree", "testrepo_wd"); - WorktreeTestRepoWorktreesDirPath = Path.Combine(sourceRelativePath, "worktree", "worktrees"); + WorktreeTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "worktree", "testrepo_wd"); + WorktreeTestRepoWorktreesDirPath = Path.Combine(ResourcesDirectory.FullName, "worktree", "worktrees"); CleanupTestReposOlderThan(TimeSpan.FromMinutes(15)); } From 6e97b66be739b1a03f61bf7ffab6e90d24442092 Mon Sep 17 00:00:00 2001 From: Andrea Spadaccini Date: Fri, 2 Nov 2018 11:38:04 +0000 Subject: [PATCH 111/384] Fix name of bootstrap script in CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d487a49aa..e1c1ab31d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ But first things first... * 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 - the `build.libgit2sharp.cmd` script on Windows or `build.libgit2sharp.sh` on Linux/Mac. + the `buildandtest.cmd` script on Windows or `buildandtest.sh` on Linux/Mac. ## LibGit2 @@ -48,4 +48,4 @@ Some things that will increase the chance that your pull request is accepted. # Additional Resources * [General GitHub documentation](http://help.github.com/) -* [GitHub pull request documentation](https://help.github.com/articles/using-pull-requests/) \ No newline at end of file +* [GitHub pull request documentation](https://help.github.com/articles/using-pull-requests/) From 664c12dea3c9077bd9b34b98f396c0c8e5d63db2 Mon Sep 17 00:00:00 2001 From: Andrea Spadaccini Date: Fri, 2 Nov 2018 11:46:55 +0000 Subject: [PATCH 112/384] Fix buildandtest.sh to use - instead of / The '/' character will be interpreted as a path start under Linux (and WSL), so change it to a '-'. Tested locally under WSL (Windows Subsystem for Linux). --- buildandtest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildandtest.sh b/buildandtest.sh index 47e5e1053..a5501a042 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 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 exit $? From 356d77b1abd609cd077ea165b394caa10e6f1427 Mon Sep 17 00:00:00 2001 From: Andrea Spadaccini Date: Fri, 2 Nov 2018 15:47:30 +0000 Subject: [PATCH 113/384] Fix resources path computation in test setup The resources path is set based on the path of the current assembly. The problem is that the assembly directory has a different number of components, depending on whether the Configuration environment variable is set or not. Therefore, the previous code, that depended on the number of subdirs, would fail if there is no value for the Configuration environment variable. The new code looks for the occurrence of a well-known string in the path and bases the path of the test resources off that position. It is still pretty sub-optimal, but I think it's a bit less sub-optimal than it was. Tested in the following ways: - run dotnet test on one test from the command line on Windows; - click on "Run Test" from Visual Studio Code. Fixes #1629. --- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index daa7451ae..762037637 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -64,9 +64,8 @@ private static void SetUpTestEnvironment() if (resourcesPath == null) { string initialAssemblyParentFolder = Directory.GetParent(new Uri(typeof(BaseFixture).GetTypeInfo().Assembly.CodeBase).LocalPath).FullName; - const string sourceRelativePath = @"../../../../LibGit2Sharp.Tests/Resources"; - - resourcesPath = Path.Combine(initialAssemblyParentFolder, sourceRelativePath); + int pos = initialAssemblyParentFolder.IndexOf("LibGit2Sharp.Tests"); + resourcesPath = Path.Combine(initialAssemblyParentFolder.Substring(0, pos), "../LibGit2Sharp.Tests/Resources"); } ResourcesDirectory = new DirectoryInfo(resourcesPath); From 24074779c1a52c2c0932828d2a8b67cf6db9e403 Mon Sep 17 00:00:00 2001 From: Paolo Viotti Date: Fri, 2 Nov 2018 16:40:05 +0000 Subject: [PATCH 114/384] add CanHeadBeDetached; close #1116 --- LibGit2Sharp.Tests/BranchFixture.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/LibGit2Sharp.Tests/BranchFixture.cs b/LibGit2Sharp.Tests/BranchFixture.cs index d8a47edfb..736b0faec 100644 --- a/LibGit2Sharp.Tests/BranchFixture.cs +++ b/LibGit2Sharp.Tests/BranchFixture.cs @@ -51,6 +51,19 @@ public void CanCreateBranch(string name) } } + [Theory] + [InlineData("32eab9cb1f450b5fe7ab663462b77d7f4b703344")] + public void CanHeadBeDetached(string commit) + { + string path = SandboxStandardTestRepo(); + using (var repo = new Repository(path)) + { + Assert.False(repo.Info.IsHeadDetached); + Commands.Checkout(repo, commit); + Assert.True(repo.Info.IsHeadDetached); + } + } + [Fact] public void CanCreateAnUnbornBranch() { From f20a29603e88865a893b37de1fd6e2e6914b9dde Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 2 Nov 2018 10:20:25 -0700 Subject: [PATCH 115/384] Tests: copy test resources to output directory Copy the test resources to the output directory so that we can resolve the easily, instead of trying to resolve them from the source directory. --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 6 ++++++ LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 68ea2cfd0..77259ae1b 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -25,6 +25,12 @@ + + + PreserveNewest + + + <_TestAppFile Include="@(TestAppExe->'%(RootDir)%(Directory)%(Filename).exe')" /> diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index 762037637..595ef301f 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -63,9 +63,7 @@ private static void SetUpTestEnvironment() if (resourcesPath == null) { - string initialAssemblyParentFolder = Directory.GetParent(new Uri(typeof(BaseFixture).GetTypeInfo().Assembly.CodeBase).LocalPath).FullName; - int pos = initialAssemblyParentFolder.IndexOf("LibGit2Sharp.Tests"); - resourcesPath = Path.Combine(initialAssemblyParentFolder.Substring(0, pos), "../LibGit2Sharp.Tests/Resources"); + resourcesPath = Path.Combine(Directory.GetParent(new Uri(typeof(BaseFixture).GetTypeInfo().Assembly.CodeBase).LocalPath).FullName, "Resources"); } ResourcesDirectory = new DirectoryInfo(resourcesPath); From e669627eed88e263791a7abcab5d02e27e9a715f Mon Sep 17 00:00:00 2001 From: Arialdo Martini Date: Sat, 3 Nov 2018 09:43:42 +0100 Subject: [PATCH 116/384] Typo: path => patch --- LibGit2Sharp.Tests/PatchEntryChangesFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/PatchEntryChangesFixture.cs b/LibGit2Sharp.Tests/PatchEntryChangesFixture.cs index c93c55c5f..dc2552a10 100644 --- a/LibGit2Sharp.Tests/PatchEntryChangesFixture.cs +++ b/LibGit2Sharp.Tests/PatchEntryChangesFixture.cs @@ -23,7 +23,7 @@ public void PatchEntryBasics() Tree rootCommitTree = repo.Lookup("f8d44d7").Tree; Tree commitTreeWithUpdatedFile = repo.Lookup("ec9e401").Tree; - // Create path by diffing + // Create patch by diffing using (var patch = repo.Diff.Compare(rootCommitTree, commitTreeWithUpdatedFile)) { PatchEntryChanges entryChanges = patch[file]; From 8874842ec3071a805f16fb472af959e2942458ea Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Sat, 3 Nov 2018 19:23:25 +0000 Subject: [PATCH 117/384] Trigger CI From 016fc950eb4266560417b16acd96b454eeb4f669 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Sat, 3 Nov 2018 19:52:46 +0000 Subject: [PATCH 118/384] Issue 1471 add .git files into the repository --- .../Resources/worktree/worktrees/i-do-numbers/dot_git | 1 + LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/dot_git | 1 + 2 files changed, 2 insertions(+) create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/dot_git create mode 100644 LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/dot_git diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/dot_git b/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/dot_git new file mode 100644 index 000000000..c14c3a26c --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/worktrees/i-do-numbers/dot_git @@ -0,0 +1 @@ +gitdir: ../../testrepo_wd/.git/worktrees/i-do-numbers diff --git a/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/dot_git b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/dot_git new file mode 100644 index 000000000..8295ccb37 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/worktree/worktrees/logo/dot_git @@ -0,0 +1 @@ +gitdir: ../../testrepo_wd/.git/worktrees/logo From 65fb410d2f2ec1983a778cc7817991b8778e2e11 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 3 Nov 2018 16:54:31 -0400 Subject: [PATCH 119/384] Update LibGit2Sharp.NativeBinaries to 1.0.245 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index d41ed810c..4ce81921d 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From 9d17daacf9dbf0a424d2a2a449a41dba8961c8f4 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Tue, 6 Nov 2018 19:59:38 +0000 Subject: [PATCH 120/384] Issue-1471 Fix memory leak in test --- LibGit2Sharp.Tests/WorktreeFixture.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/WorktreeFixture.cs b/LibGit2Sharp.Tests/WorktreeFixture.cs index ada939317..5a706515b 100644 --- a/LibGit2Sharp.Tests/WorktreeFixture.cs +++ b/LibGit2Sharp.Tests/WorktreeFixture.cs @@ -167,9 +167,12 @@ public void CanPruneDeletedWorktree() var worktreeUnlocked = repo.Worktrees["i-do-numbers"]; Assert.Equal("i-do-numbers", worktreeUnlocked.Name); Assert.False(worktreeUnlocked.IsLocked); - var info = worktreeUnlocked.WorktreeRepository.Info; + using (var wtRepo = worktreeUnlocked.WorktreeRepository) + { + var info = wtRepo.Info; - Directory.Delete(info.WorkingDirectory, true); + Directory.Delete(info.WorkingDirectory, true); + } Assert.True(repo.Worktrees.Prune(worktreeUnlocked)); From 222d4c432303063aee5f7b0fbb603db102a848f7 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Tue, 6 Nov 2018 20:31:07 +0000 Subject: [PATCH 121/384] Issue-1471 Added code comments to WorktreeLock --- LibGit2Sharp/WorktreeLock.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/LibGit2Sharp/WorktreeLock.cs b/LibGit2Sharp/WorktreeLock.cs index 7362102ab..4ae5d799f 100644 --- a/LibGit2Sharp/WorktreeLock.cs +++ b/LibGit2Sharp/WorktreeLock.cs @@ -6,20 +6,38 @@ namespace LibGit2Sharp { + /// + /// Represents the lock state of a Worktree + /// [DebuggerDisplay("{DebuggerDisplay,nq}")] public class WorktreeLock { + /// + /// Creates a new instance of with default, unlocked, state + /// public WorktreeLock() : this(false, null) { } + /// + /// Creates a new instance of + /// + /// the locked state + /// the reason given for the lock public WorktreeLock(bool isLocked, string reason) { IsLocked = isLocked; Reason = reason; } + /// + /// Gets a flag indicating if the worktree is locked + /// public virtual bool IsLocked { get; } + + /// + /// Gets the reason, if set, for the lock + /// public virtual string Reason { get; } private string DebuggerDisplay From e736ba1ff324f82ac34b8e37c362053616c9bd5b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 6 Nov 2018 22:50:54 +0000 Subject: [PATCH 122/384] Update NativeBinaries to libgit2 0.27.7 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 4ce81921d..da462e246 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From e7e41d71564acd0dad14aa331fd84b065b3040bf Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 7 Nov 2018 08:05:18 -0800 Subject: [PATCH 123/384] NativeBinaries: cherry-pick transport fix from libgit2 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index da462e246..bdb7f7a0b 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From 9c97dcddaf5eda731462aa56d931266937b257c9 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 29 Nov 2018 04:36:00 -0800 Subject: [PATCH 124/384] Update NativeBinaries to 1.0.258 No more zlib or libcurl dependencies. --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index bdb7f7a0b..2acbf29e0 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From 9a90a757f1c5be22ae088c501f74e06a115c777a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 29 Nov 2018 13:17:04 -0800 Subject: [PATCH 125/384] GitConfigEntry: add include_depth Add the `include_depth` field to mirror the libgit2 addition. --- LibGit2Sharp/Core/GitConfigEntry.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LibGit2Sharp/Core/GitConfigEntry.cs b/LibGit2Sharp/Core/GitConfigEntry.cs index 30550126b..9eaa9e468 100644 --- a/LibGit2Sharp/Core/GitConfigEntry.cs +++ b/LibGit2Sharp/Core/GitConfigEntry.cs @@ -8,6 +8,7 @@ internal unsafe struct GitConfigEntry { public char* namePtr; public char* valuePtr; + public uint include_depth; public uint level; public void* freePtr; public void* payloadPtr; From 7e7e84a2029eecbe21b1850f40db88169f2f8eab Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Sun, 2 Dec 2018 18:21:27 -0800 Subject: [PATCH 126/384] Issue-1471 undo unneeded csproj changes --- LibGit2Sharp/LibGit2Sharp.csproj | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 2e376e2c0..fecc80f0f 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -17,7 +17,7 @@ - TRACE;DEBUG;NETSTANDARD2_0;LEAKS_IDENTIFYING;LEAKS_TRACKING + $(DefineConstants);DESKTOP @@ -29,10 +29,7 @@ - - True - True - + @@ -41,10 +38,6 @@ - - - - From 87517d91f9f5fd2cb39ac37bb94e3fccc22593e2 Mon Sep 17 00:00:00 2001 From: Mike Minns Date: Sun, 2 Dec 2018 18:48:42 -0800 Subject: [PATCH 127/384] ssue-1471 Removed unneeded build constants --- LibGit2Sharp/LibGit2Sharp.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index fecc80f0f..d41ed810c 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -16,10 +16,6 @@ ..\libgit2sharp.snk - - $(DefineConstants);DESKTOP - - From 52f8c73fbbeb3186f2054a6fa2ed38487cfafea9 Mon Sep 17 00:00:00 2001 From: Marek Petak Date: Mon, 10 Dec 2018 12:11:48 +0000 Subject: [PATCH 128/384] Fix spelling in comments --- LibGit2Sharp/CommitFilter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/CommitFilter.cs b/LibGit2Sharp/CommitFilter.cs index 56b23389c..8997ca772 100644 --- a/LibGit2Sharp/CommitFilter.cs +++ b/LibGit2Sharp/CommitFilter.cs @@ -6,7 +6,7 @@ namespace LibGit2Sharp { /// - /// Criterias used to filter out and order the commits of the repository when querying its history. + /// Criteria used to filter out and order the commits of the repository when querying its history. /// public sealed class CommitFilter { @@ -21,7 +21,7 @@ public CommitFilter() } /// - /// The ordering stragtegy to use. + /// The ordering strategy to use. /// /// By default, the commits are shown in reverse chronological order. /// From 58b55c6b69cb44b072b3010d34b69c53ebbf0b72 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 18 Dec 2018 19:36:24 -0500 Subject: [PATCH 129/384] Update LibGit2Sharp.NativeBinaries to 1.0.260 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 2acbf29e0..c5425e851 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From 2ccceca6114d4bf1eca3f722819e7a45fa87fd9f Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 18 Dec 2018 19:37:39 -0500 Subject: [PATCH 130/384] Target net46 instead of net461 --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 10 +++++----- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- .../x64/NativeLibraryLoadTestApp.x64.csproj | 2 +- .../x86/NativeLibraryLoadTestApp.x86.csproj | 2 +- appveyor.yml | 8 ++++---- buildandtest.cmd | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 77259ae1b..3121e4a50 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,14 +1,14 @@  - net461;netcoreapp2.0 - $(DefineConstants);DESKTOP + net46;netcoreapp2.0 + $(DefineConstants);DESKTOP - - + + @@ -22,7 +22,7 @@ - + diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index c5425e851..987cd5777 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net461 + netstandard2.0;net46 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 a3c313a59..5fb7e1b0c 100644 --- a/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj +++ b/NativeLibraryLoadTestApp/x64/NativeLibraryLoadTestApp.x64.csproj @@ -2,7 +2,7 @@ Exe - net461 + net46 x64 diff --git a/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj b/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj index daaf8f51f..c7bef05c9 100644 --- a/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj +++ b/NativeLibraryLoadTestApp/x86/NativeLibraryLoadTestApp.x86.csproj @@ -2,7 +2,7 @@ Exe - net461 + net46 x86 diff --git a/appveyor.yml b/appveyor.yml index ea3e2eef9..6d5eebafa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -90,16 +90,16 @@ test_script: { .\packages\OpenCover\tools\OpenCover.Console.exe ` -register:user ` - "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.0\tools\net461\$runner""" ` - "-targetargs:""$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net461\LibGit2Sharp.Tests.dll"" -noshadow" ` + "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.0\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.0\tools\net461\$runner" ` - "$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net461\LibGit2Sharp.Tests.dll" -noshadow + & "$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.0\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 93090259b..3bc1d6656 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%\net461\LibGit2Sharp.Tests.dll" -noshadow +"%userprofile%\.nuget\packages\xunit.runner.console\2.4.0\tools\net452\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 7a61bb975384d2a32e2cb5e24027a46bfdaf9c0c Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 18 Dec 2018 19:45:15 -0500 Subject: [PATCH 131/384] Remove unneeded DESKTOP compilation symbol --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 - LibGit2Sharp.Tests/SetErrorFixture.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 3121e4a50..c31cb9476 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -2,7 +2,6 @@ net46;netcoreapp2.0 - $(DefineConstants);DESKTOP diff --git a/LibGit2Sharp.Tests/SetErrorFixture.cs b/LibGit2Sharp.Tests/SetErrorFixture.cs index 31b7513a2..e7e1dbed4 100644 --- a/LibGit2Sharp.Tests/SetErrorFixture.cs +++ b/LibGit2Sharp.Tests/SetErrorFixture.cs @@ -49,7 +49,7 @@ public void FormatAggregateException() Exception exceptionToThrow = new AggregateException(aggregateExceptionMessage, new Exception(innerExceptionMessage), new Exception(innerExceptionMessage2)); StringBuilder sb = new StringBuilder(); -#if DESKTOP +#if NETFRAMEWORK sb.AppendLine(aggregateExceptionMessage); #else sb.AppendLine($"{aggregateExceptionMessage} ({innerExceptionMessage}) ({innerExceptionMessage2})"); From e34ae5b3da37e77728fae6264ac53346a3c2d1b8 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 19 Dec 2018 18:00:52 +0000 Subject: [PATCH 132/384] Add IndentHeuristic option to CompareOptions --- LibGit2Sharp/CompareOptions.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/LibGit2Sharp/CompareOptions.cs b/LibGit2Sharp/CompareOptions.cs index fbd147c79..fb4234439 100644 --- a/LibGit2Sharp/CompareOptions.cs +++ b/LibGit2Sharp/CompareOptions.cs @@ -44,5 +44,11 @@ public CompareOptions() /// By default, will be used. /// public DiffAlgorithm Algorithm { get; set; } + + /// + /// Enable --indent-heuristic Diff option, that attempts to produce more aesthetically pleasing diffs. + /// By default, this option will be false. + /// + public bool IndentHeuristic { get; set; } } } From 6a6f1345d8bcbbd560fd75098621336581777e46 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 19 Dec 2018 18:02:20 +0000 Subject: [PATCH 133/384] Test for IndentHeuristic Diff option This test is based on example from: https://github.com/git/git/blob/433860f3d0beb0c6f205290bd16cda413148f098/t/t4061-diff-indent.sh#L17 --- LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs | 39 +++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs index 00ef0ab2b..9173674b8 100644 --- a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs +++ b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs @@ -126,5 +126,44 @@ public void ComparingTwoNullBlobsReturnsAnEmptyContentChanges() Assert.Equal(0, changes.LinesDeleted); } } + + [Fact] + public void ComparingBlobsWithIndentHeuristicOptionMakesADifference() + { + var path = SandboxStandardTestRepoGitDir(); + using (var repo = new Repository(path)) + { + // Based on test diff indent heuristic from: + // https://github.com/git/git/blob/433860f3d0beb0c6f205290bd16cda413148f098/t/t4061-diff-indent.sh#L17 + var oldContent = +@" 1 + 2 + a + + b + 3 + 4"; + var newContent = +@" 1 + 2 + a + + b + a + + b + 3 + 4"; + var oldBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(oldContent))); + var newBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(newContent))); + var noIndentHeuristicOption = new CompareOptions { IndentHeuristic = false }; + var indentHeuristicOption = new CompareOptions { IndentHeuristic = true }; + + ContentChanges changes0 = repo.Diff.Compare(oldBlob, newBlob, noIndentHeuristicOption); + ContentChanges changes1 = repo.Diff.Compare(oldBlob, newBlob, indentHeuristicOption); + + Assert.NotEqual(changes0.Patch, changes1.Patch); + } + } } } From 98be00ae5269f468d25394986e0e42716294cf7a Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 19 Dec 2018 18:18:34 +0000 Subject: [PATCH 134/384] Take account of CompareOptions.IndentHeuristic When this flag is set, enable the GIT_DIFF_INDENT_HEURISTIC option. --- LibGit2Sharp/Core/GitDiff.cs | 15 +++++++++++---- LibGit2Sharp/Diff.cs | 7 ++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp/Core/GitDiff.cs b/LibGit2Sharp/Core/GitDiff.cs index eb21d6881..956bc89ab 100644 --- a/LibGit2Sharp/Core/GitDiff.cs +++ b/LibGit2Sharp/Core/GitDiff.cs @@ -133,6 +133,13 @@ internal enum GitDiffOptionFlags * Options controlling how output will be generated */ + /// + /// Use a heuristic that takes indentation and whitespace into account + /// which generally can produce better diffs when dealing with ambiguous + /// diff hunks. + /// + GIT_DIFF_INDENT_HEURISTIC = (1 << 18), + /// /// Treat all files as text, disabling binary attributes and detection /// @@ -304,11 +311,11 @@ enum GitDiffLineOrigin : byte enum GitDiffFormat { - GIT_DIFF_FORMAT_PATCH = 1, // < full git diff + GIT_DIFF_FORMAT_PATCH = 1, // < full git diff GIT_DIFF_FORMAT_PATCH_HEADER = 2, // < just the file headers of patch - GIT_DIFF_FORMAT_RAW = 3, // < like git diff --raw - GIT_DIFF_FORMAT_NAME_ONLY = 4, // < like git diff --name-only - GIT_DIFF_FORMAT_NAME_STATUS = 5, // < like git diff --name-status + GIT_DIFF_FORMAT_RAW = 3, // < like git diff --raw + GIT_DIFF_FORMAT_NAME_ONLY = 4, // < like git diff --name-only + GIT_DIFF_FORMAT_NAME_STATUS = 5, // < like git diff --name-status } [Flags] diff --git a/LibGit2Sharp/Diff.cs b/LibGit2Sharp/Diff.cs index 9bf14660c..087ee8d6d 100644 --- a/LibGit2Sharp/Diff.cs +++ b/LibGit2Sharp/Diff.cs @@ -63,6 +63,11 @@ private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[] options.Flags |= GitDiffOptionFlags.GIT_DIFF_DISABLE_PATHSPEC_MATCH; } + if (compareOptions.IndentHeuristic) + { + options.Flags |= GitDiffOptionFlags.GIT_DIFF_INDENT_HEURISTIC; + } + if (matchedPathsAggregator != null) { options.NotifyCallback = matchedPathsAggregator.OnGitDiffNotify; @@ -351,7 +356,7 @@ public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable(diff); From e0636802a901a57ed9a6498b2ee3220cf64ac951 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 19 Dec 2018 18:25:17 +0000 Subject: [PATCH 135/384] Test for when IndentHeuristic makes no difference When compared files don't contain spaces, the --indent-heuristic option won't make a difference. --- LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs | 37 ++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs index 9173674b8..0107294af 100644 --- a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs +++ b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs @@ -128,7 +128,7 @@ public void ComparingTwoNullBlobsReturnsAnEmptyContentChanges() } [Fact] - public void ComparingBlobsWithIndentHeuristicOptionMakesADifference() + public void ComparingBlobsWithNoSpacesAndIndentHeuristicOptionMakesADifference() { var path = SandboxStandardTestRepoGitDir(); using (var repo = new Repository(path)) @@ -165,5 +165,40 @@ public void ComparingBlobsWithIndentHeuristicOptionMakesADifference() Assert.NotEqual(changes0.Patch, changes1.Patch); } } + + + [Fact] + public void ComparingBlobsWithNoSpacesIndentHeuristicOptionMakesNoDifference() + { + var path = SandboxStandardTestRepoGitDir(); + using (var repo = new Repository(path)) + { + var oldContent = +@" 1 + 2 + a + b + 3 + 4"; + var newContent = +@" 1 + 2 + a + b + a + b + 3 + 4"; + var oldBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(oldContent))); + var newBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(newContent))); + var noIndentHeuristicOption = new CompareOptions { IndentHeuristic = false }; + var indentHeuristicOption = new CompareOptions { IndentHeuristic = true }; + + ContentChanges changes0 = repo.Diff.Compare(oldBlob, newBlob, noIndentHeuristicOption); + ContentChanges changes1 = repo.Diff.Compare(oldBlob, newBlob, indentHeuristicOption); + + Assert.Equal(changes0.Patch, changes1.Patch); + } + } } } From 2f583cbf16dee63fcbcf16f0d6fcace8a81f3a2c Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 19 Dec 2018 23:25:34 +0000 Subject: [PATCH 136/384] Check the same lines have been added or removed The --indent-heuristic option should create patches that add or remove the same lines, but potentially in a different order. --- LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs index 0107294af..fea0bbb74 100644 --- a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs +++ b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Linq; using System.Text; using LibGit2Sharp.Tests.TestHelpers; using Xunit; @@ -163,10 +164,10 @@ public void ComparingBlobsWithNoSpacesAndIndentHeuristicOptionMakesADifference() ContentChanges changes1 = repo.Diff.Compare(oldBlob, newBlob, indentHeuristicOption); Assert.NotEqual(changes0.Patch, changes1.Patch); + Assert.Equal(CanonicalChangedLines(changes0), CanonicalChangedLines(changes1)); } } - [Fact] public void ComparingBlobsWithNoSpacesIndentHeuristicOptionMakesNoDifference() { @@ -200,5 +201,11 @@ public void ComparingBlobsWithNoSpacesIndentHeuristicOptionMakesNoDifference() Assert.Equal(changes0.Patch, changes1.Patch); } } + + static string CanonicalChangedLines(ContentChanges changes) + { + // Create an ordered representation of lines that have been added or removed + return string.Join("\n", changes.Patch.Split('\n').Where(l => l.StartsWith("+") || l.StartsWith("-")).OrderBy(l => l)); + } } } From 2e9428e7d34f5a0d71fb2c9ebd8948e4de7c1707 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 5 Feb 2019 22:26:35 +0000 Subject: [PATCH 137/384] Update native binaries to 2.0.263 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 987cd5777..685531ac3 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From 142eea28cc942d32c9f52323aaecf64e622c7790 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 9 Jan 2019 18:48:52 +0000 Subject: [PATCH 138/384] Use cdecl calling conventions Join the rest of the world and use cdecl calling conventions to pinvoke libgit2. --- LibGit2Sharp/Core/GitCheckoutOpts.cs | 3 + LibGit2Sharp/Core/GitDiff.cs | 2 + LibGit2Sharp/Core/GitFilter.cs | 6 + LibGit2Sharp/Core/GitOdbBackend.cs | 11 + LibGit2Sharp/Core/GitOdbBackendStream.cs | 4 + LibGit2Sharp/Core/GitSmartSubtransport.cs | 3 + .../Core/GitSmartSubtransportRegistration.cs | 1 + .../Core/GitSmartSubtransportStream.cs | 3 + LibGit2Sharp/Core/GitStashApplyOpts.cs | 1 + LibGit2Sharp/Core/GitWriteStream.cs | 5 + LibGit2Sharp/Core/NativeMethods.cs | 730 +++++++++--------- 11 files changed, 417 insertions(+), 352 deletions(-) diff --git a/LibGit2Sharp/Core/GitCheckoutOpts.cs b/LibGit2Sharp/Core/GitCheckoutOpts.cs index 3424094be..053258565 100644 --- a/LibGit2Sharp/Core/GitCheckoutOpts.cs +++ b/LibGit2Sharp/Core/GitCheckoutOpts.cs @@ -118,6 +118,7 @@ internal enum CheckoutStrategy GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = (1 << 17), } + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int checkout_notify_cb( CheckoutNotifyFlags why, IntPtr path, @@ -126,12 +127,14 @@ internal delegate int checkout_notify_cb( IntPtr workdir, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void progress_cb( IntPtr strPtr, UIntPtr completed_steps, UIntPtr total_steps, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int perfdata_cb( IntPtr perfdata, IntPtr payload); diff --git a/LibGit2Sharp/Core/GitDiff.cs b/LibGit2Sharp/Core/GitDiff.cs index 956bc89ab..cc1ab1af1 100644 --- a/LibGit2Sharp/Core/GitDiff.cs +++ b/LibGit2Sharp/Core/GitDiff.cs @@ -198,12 +198,14 @@ internal enum GitDiffOptionFlags GIT_DIFF_SHOW_BINARY = (1 << 30), } + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int diff_notify_cb( IntPtr diff_so_far, IntPtr delta_to_add, IntPtr matched_pathspec, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int diff_progress_cb( IntPtr diff_so_far, IntPtr old_path, diff --git a/LibGit2Sharp/Core/GitFilter.cs b/LibGit2Sharp/Core/GitFilter.cs index 1ca228e79..72fa2f763 100644 --- a/LibGit2Sharp/Core/GitFilter.cs +++ b/LibGit2Sharp/Core/GitFilter.cs @@ -43,6 +43,7 @@ internal class GitFilter /// before the first use of the filter, so you can defer expensive /// initialization operations (in case libgit2 is being used in a way that doesn't need the filter). /// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int git_filter_init_fn(IntPtr filter); /// @@ -53,6 +54,7 @@ internal class GitFilter /// will be called once at most and should release resources as needed. /// Typically this function will free the `git_filter` object itself. /// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void git_filter_shutdown_fn(IntPtr filter); /// @@ -69,6 +71,7 @@ internal class GitFilter /// away before the `apply` callback can use it. If a filter allocates and assigns a value to the `payload`, it will need a `cleanup` /// callback to free the payload. /// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int git_filter_check_fn( GitFilter gitFilter, IntPtr payload, @@ -85,6 +88,7 @@ public delegate int git_filter_check_fn( /// /// The `payload` value will refer to any payload that was set by the `check` callback. It may be read from or written to as needed. /// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int git_filter_apply_fn( GitFilter gitFilter, IntPtr payload, @@ -92,6 +96,7 @@ public delegate int git_filter_apply_fn( IntPtr gitBufFrom, IntPtr filterSource); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int git_filter_stream_fn( out IntPtr git_writestream_out, GitFilter self, @@ -104,6 +109,7 @@ public delegate int git_filter_stream_fn( /// after the filter has been applied. If the `check` or `apply` callbacks allocated a `payload` /// to keep per-source filter state, use this callback to free that payload and release resources as required. /// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void git_filter_cleanup_fn(IntPtr gitFilter, IntPtr payload); } /// diff --git a/LibGit2Sharp/Core/GitOdbBackend.cs b/LibGit2Sharp/Core/GitOdbBackend.cs index a83c7d424..0d68a3433 100644 --- a/LibGit2Sharp/Core/GitOdbBackend.cs +++ b/LibGit2Sharp/Core/GitOdbBackend.cs @@ -55,6 +55,7 @@ static GitOdbBackend() /// [in] A pointer to the backend which is being asked to perform the task. /// [in] The OID which the backend is being asked to look up. /// 0 if successful; an error code otherwise. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int read_callback( out IntPtr buffer_p, out UIntPtr len_p, @@ -77,6 +78,7 @@ public delegate int read_callback( /// [in] The short-form OID which the backend is being asked to look up. /// [in] The length of the short-form OID (short_oid). /// 0 if successful; an error code otherwise. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int read_prefix_callback( out GitOid out_oid, out IntPtr buffer_p, @@ -95,6 +97,7 @@ public delegate int read_prefix_callback( /// [in] A pointer to the backend which is being asked to perform the task. /// [in] The OID which the backend is being asked to look up. /// 0 if successful; an error code otherwise. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int read_header_callback( out UIntPtr len_p, out GitObjectType type_p, @@ -111,6 +114,7 @@ public delegate int read_header_callback( /// [in] The length of the buffer pointed to by data. /// [in] The type of the object. /// 0 if successful; an error code otherwise. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int write_callback( IntPtr backend, ref GitOid oid, @@ -128,6 +132,7 @@ public delegate int write_callback( /// [in] The length of the object's contents. /// [in] The type of the object being written. /// 0 if successful; an error code otherwise. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int writestream_callback( out IntPtr stream_out, IntPtr backend, @@ -142,6 +147,7 @@ public delegate int writestream_callback( /// [in] A pointer to the backend which is being asked to perform the task. /// [in] The object ID that the caller is requesting. /// 0 if successful; an error code otherwise. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int readstream_callback( out IntPtr stream_out, IntPtr backend, @@ -154,6 +160,7 @@ public delegate int readstream_callback( /// [in] A pointer to the backend which is being asked to perform the task. /// [in] The object ID that the caller is requesting. /// True if the object exists; false otherwise + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate bool exists_callback( IntPtr backend, ref GitOid oid); @@ -169,6 +176,7 @@ public delegate bool exists_callback( /// [in] The short-form OID which the backend is being asked to look up. /// [in] The length of the short-form OID (short_oid). /// 1 if the object exists, 0 if the object doesn't; an error code otherwise. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int exists_prefix_callback( ref GitOid found_oid, IntPtr backend, @@ -182,6 +190,7 @@ public delegate int exists_prefix_callback( /// [in] A pointer to the backend which is being asked to perform the task. /// [in] The callback function to invoke. /// [in] An arbitrary parameter to pass through to the callback + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int foreach_callback( IntPtr backend, foreach_callback_callback cb, @@ -191,6 +200,7 @@ public delegate int foreach_callback( /// The owner of this backend is finished with it. The backend is asked to clean up and shut down. /// /// [in] A pointer to the backend which is being freed. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void free_callback( IntPtr backend); @@ -200,6 +210,7 @@ public delegate void free_callback( /// The oid of each object in the backing store. /// The arbitrary parameter given to foreach_callback. /// A non-negative result indicates the enumeration should continue. Otherwise, the enumeration should stop. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int foreach_callback_callback( IntPtr oid, IntPtr data); diff --git a/LibGit2Sharp/Core/GitOdbBackendStream.cs b/LibGit2Sharp/Core/GitOdbBackendStream.cs index 5e51baabe..984274f04 100644 --- a/LibGit2Sharp/Core/GitOdbBackendStream.cs +++ b/LibGit2Sharp/Core/GitOdbBackendStream.cs @@ -38,18 +38,22 @@ static GitOdbBackendStream() public static int GCHandleOffset; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int read_callback( IntPtr stream, IntPtr buffer, UIntPtr len); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int write_callback( IntPtr stream, IntPtr buffer, UIntPtr len); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int finalize_write_callback(IntPtr stream, ref GitOid oid); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void free_callback(IntPtr stream); } } diff --git a/LibGit2Sharp/Core/GitSmartSubtransport.cs b/LibGit2Sharp/Core/GitSmartSubtransport.cs index b0a321635..d4ce6d728 100644 --- a/LibGit2Sharp/Core/GitSmartSubtransport.cs +++ b/LibGit2Sharp/Core/GitSmartSubtransport.cs @@ -23,14 +23,17 @@ static GitSmartSubtransport() public static int GCHandleOffset; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int action_callback( out IntPtr stream, IntPtr subtransport, IntPtr url, GitSmartSubtransportAction action); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int close_callback(IntPtr subtransport); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void free_callback(IntPtr subtransport); } } diff --git a/LibGit2Sharp/Core/GitSmartSubtransportRegistration.cs b/LibGit2Sharp/Core/GitSmartSubtransportRegistration.cs index e721c1e79..c8ae4fde7 100644 --- a/LibGit2Sharp/Core/GitSmartSubtransportRegistration.cs +++ b/LibGit2Sharp/Core/GitSmartSubtransportRegistration.cs @@ -10,6 +10,7 @@ internal class GitSmartSubtransportRegistration public uint Rpc; public uint Param; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int create_callback( out IntPtr subtransport, IntPtr owner, diff --git a/LibGit2Sharp/Core/GitSmartSubtransportStream.cs b/LibGit2Sharp/Core/GitSmartSubtransportStream.cs index 4bf531e82..ae371b980 100644 --- a/LibGit2Sharp/Core/GitSmartSubtransportStream.cs +++ b/LibGit2Sharp/Core/GitSmartSubtransportStream.cs @@ -25,17 +25,20 @@ static GitSmartSubtransportStream() public static int GCHandleOffset; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int read_callback( IntPtr stream, IntPtr buffer, UIntPtr buf_size, out UIntPtr bytes_read); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int write_callback( IntPtr stream, IntPtr buffer, UIntPtr len); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void free_callback(IntPtr stream); } } diff --git a/LibGit2Sharp/Core/GitStashApplyOpts.cs b/LibGit2Sharp/Core/GitStashApplyOpts.cs index e7f2be19c..739c40b0c 100644 --- a/LibGit2Sharp/Core/GitStashApplyOpts.cs +++ b/LibGit2Sharp/Core/GitStashApplyOpts.cs @@ -3,6 +3,7 @@ namespace LibGit2Sharp.Core { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int stash_apply_progress_cb(StashApplyProgress progress, IntPtr payload); [StructLayout(LayoutKind.Sequential)] diff --git a/LibGit2Sharp/Core/GitWriteStream.cs b/LibGit2Sharp/Core/GitWriteStream.cs index a53e7bd74..891a765fb 100644 --- a/LibGit2Sharp/Core/GitWriteStream.cs +++ b/LibGit2Sharp/Core/GitWriteStream.cs @@ -15,8 +15,13 @@ internal struct GitWriteStream [MarshalAs(UnmanagedType.FunctionPtr)] public free_fn free; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int write_fn(IntPtr stream, IntPtr buffer, UIntPtr len); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int close_fn(IntPtr stream); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void free_fn(IntPtr stream); } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 56d836b0f..e8dfc833c 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -95,71 +95,71 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject } } - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe GitError* giterr_last(); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void giterr_set_str( GitErrorCategory error_class, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string errorString); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void giterr_set_oom(); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UInt32 git_blame_get_hunk_count(git_blame* blame); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_blame_hunk* git_blame_get_hunk_byindex( git_blame* blame, UInt32 index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_blame_file( out git_blame* blame, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path, git_blame_options options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_blame_free(git_blame* blame); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_blob_create_fromdisk( ref GitOid id, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_blob_create_fromworkdir( ref GitOid id, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath relative_path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_blob_create_fromstream( out IntPtr stream, git_repository* repositoryPtr, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string hintpath); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_blob_create_fromstream_commit( ref GitOid oid, IntPtr stream); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_blob_filtered_content( GitBuf buf, git_object* blob, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string as_path, [MarshalAs(UnmanagedType.Bool)] bool check_for_binary_data); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe IntPtr git_blob_rawcontent(git_object* blob); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe Int64 git_blob_rawsize(git_object* blob); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_branch_create_from_annotated( out git_reference* ref_out, git_repository* repo, @@ -167,45 +167,46 @@ internal static extern unsafe int git_branch_create_from_annotated( git_annotated_commit* target, [MarshalAs(UnmanagedType.Bool)] bool force); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_branch_delete( git_reference* reference); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int branch_foreach_callback( IntPtr branch_name, GitBranchType branch_type, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void git_branch_iterator_free( IntPtr iterator); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_branch_iterator_new( out IntPtr iter_out, IntPtr repo, GitBranchType branch_type); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_branch_move( out git_reference* ref_out, git_reference* reference, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string new_branch_name, [MarshalAs(UnmanagedType.Bool)] bool force); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_branch_next( out IntPtr ref_out, out GitBranchType type_out, IntPtr iter); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_branch_remote_name( GitBuf buf, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string canonical_branch_name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_rebase_init( out git_rebase* rebase, git_repository* repo, @@ -214,31 +215,31 @@ internal static extern unsafe int git_rebase_init( git_annotated_commit* onto, GitRebaseOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_rebase_open( out git_rebase* rebase, git_repository* repo, GitRebaseOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_rebase_operation_entrycount( git_rebase* rebase); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_rebase_operation_current( git_rebase* rebase); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_rebase_operation* git_rebase_operation_byindex( git_rebase* rebase, UIntPtr index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_rebase_next( out git_rebase_operation* operation, git_rebase* rebase); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_rebase_commit( ref GitOid id, git_rebase* rebase, @@ -247,64 +248,65 @@ internal static extern unsafe int git_rebase_commit( IntPtr message_encoding, IntPtr message); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_rebase_abort( git_rebase* rebase); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_rebase_finish( git_rebase* repo, git_signature* signature); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_rebase_free(git_rebase* rebase); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_rename( ref GitStrArray problems, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string old_name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string new_name); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_remote_rename_problem_cb( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] string problematic_refspec, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_branch_upstream_name( GitBuf buf, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string referenceName); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void git_buf_free(GitBuf buf); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_checkout_tree( git_repository* repo, git_object* treeish, ref GitCheckoutOpts opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_checkout_index( git_repository* repo, git_object* treeish, ref GitCheckoutOpts opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_clone( out git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string origin_url, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath workdir_path, ref GitCloneOptions opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_signature* git_commit_author(git_object* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_signature* git_commit_committer(git_object* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_commit_create_from_ids( out GitOid id, git_repository* repo, @@ -317,7 +319,7 @@ internal static extern unsafe int git_commit_create_from_ids( UIntPtr parentCount, [MarshalAs(UnmanagedType.LPArray)] [In] IntPtr[] parents); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_commit_create_buffer( GitBuf res, git_repository* repo, @@ -329,7 +331,7 @@ internal static extern unsafe int git_commit_create_buffer( UIntPtr parent_count, IntPtr* parents /* git_commit** originally */); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_commit_create_with_signature( out GitOid id, git_repository* repo, @@ -337,28 +339,28 @@ internal static extern unsafe int git_commit_create_with_signature( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string signature, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string signature_field); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_commit_message(git_object* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_commit_summary(git_object* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_commit_message_encoding(git_object* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_commit_parent_id(git_object* commit, uint n); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe uint git_commit_parentcount(git_object* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_commit_tree_id(git_object* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_commit_extract_signature( GitBuf signature, GitBuf signed_data, @@ -366,45 +368,45 @@ internal static extern unsafe int git_commit_extract_signature( ref GitOid commit_id, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string field); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_delete_entry( git_config* cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_lock(out IntPtr txn, git_config* config); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_delete_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); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_find_global(GitBuf global_config_path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_find_system(GitBuf system_config_path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_find_xdg(GitBuf xdg_config_path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_find_programdata(GitBuf programdata_config_path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_config_free(git_config* cfg); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_config_entry_free(GitConfigEntry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_get_entry( out GitConfigEntry* entry, git_config* cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_add_file_ondisk( git_config* cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, @@ -412,79 +414,80 @@ internal static extern unsafe int git_config_add_file_ondisk( git_repository* repo, [MarshalAs(UnmanagedType.Bool)] bool force); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_new(out git_config* cfg); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_open_level( out git_config* cfg, git_config* parent, uint level); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_parse_bool( [MarshalAs(UnmanagedType.Bool)] out bool value, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string valueToParse); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_parse_int32( [MarshalAs(UnmanagedType.I4)] out int value, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string valueToParse); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_parse_int64( [MarshalAs(UnmanagedType.I8)] out long value, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string valueToParse); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_set_bool( git_config* cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, [MarshalAs(UnmanagedType.Bool)] bool value); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_set_int32( git_config* cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, int value); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_set_int64( git_config* cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, long value); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_set_string( git_config* cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string value); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int config_foreach_callback( IntPtr entry, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_foreach( git_config* cfg, config_foreach_callback callback, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_iterator_glob_new( out IntPtr iter, IntPtr cfg, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string regexp); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_config_next( out IntPtr entry, IntPtr iter); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void git_config_iterator_free(IntPtr iter); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_config_snapshot(out git_config* @out, git_config* config); // Ordinarily we would decorate the `url` parameter with the StrictUtf8Marshaler like we do everywhere @@ -492,6 +495,7 @@ internal static extern int git_config_next( // sometimes vomit when using a custom IMarshaler. So yeah, don't do that. If you need the url, // call StrictUtf8Marshaler.FromNative manually. See the discussion here: // http://social.msdn.microsoft.com/Forums/en-US/netfx64bit/thread/1eb746c6-d695-4632-8a9e-16c4fa98d481 + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_cred_acquire_cb( out IntPtr cred, IntPtr url, @@ -499,37 +503,37 @@ internal delegate int git_cred_acquire_cb( GitCredentialType allowed_types, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_cred_default_new(out IntPtr cred); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_cred_userpass_plaintext_new( out IntPtr cred, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string username, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string password); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void git_cred_free(IntPtr cred); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_describe_commit( out git_describe_result* describe, git_object* committish, ref GitDescribeOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_describe_format( GitBuf buf, git_describe_result* describe, ref GitDescribeFormatOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_describe_result_free(git_describe_result* describe); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_diff_free(git_diff* diff); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_diff_tree_to_tree( out git_diff* diff, git_repository* repo, @@ -537,7 +541,7 @@ internal static extern unsafe int git_diff_tree_to_tree( git_object* newTree, GitDiffOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_diff_tree_to_index( out git_diff* diff, git_repository* repo, @@ -545,47 +549,51 @@ internal static extern unsafe int git_diff_tree_to_index( git_index* index, GitDiffOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_diff_merge( git_diff* onto, git_diff* from); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_diff_index_to_workdir( out git_diff* diff, git_repository* repo, git_index* index, GitDiffOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_diff_tree_to_workdir( out git_diff* diff, git_repository* repo, git_object* oldTree, GitDiffOptions options); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal unsafe delegate int git_diff_file_cb( [In] git_diff_delta* delta, float progress, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal unsafe delegate int git_diff_hunk_cb( [In] git_diff_delta* delta, [In] GitDiffHunk hunk, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal unsafe delegate int git_diff_line_cb( [In] git_diff_delta* delta, [In] GitDiffHunk hunk, [In] GitDiffLine line, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal unsafe delegate int git_diff_binary_cb( [In] git_diff_delta* delta, [In] GitDiffBinary binary, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_diff_blobs( git_object* oldBlob, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string old_as_path, @@ -598,7 +606,7 @@ internal static extern unsafe int git_diff_blobs( git_diff_line_cb lineCallback, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_diff_foreach( git_diff* diff, git_diff_file_cb fileCallback, @@ -607,30 +615,30 @@ internal static extern unsafe int git_diff_foreach( git_diff_line_cb lineCallback, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_diff_find_similar( git_diff* diff, GitDiffFindOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_diff_num_deltas(git_diff* diff); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_diff_delta* git_diff_get_delta(git_diff* diff, UIntPtr idx); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_filter_register( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, IntPtr gitFilter, int priority); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_filter_unregister( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_filter_source_mode(git_filter_source* source); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_libgit2_features(); #region git_libgit2_opts @@ -655,40 +663,40 @@ internal static extern int git_libgit2_opts(int option, uint level, internal static extern int git_libgit2_opts(int option, int enabled); #endregion - [DllImport(libgit2)] + [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); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_graph_descendant_of( git_repository* repo, ref GitOid commit, ref GitOid ancestor); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_ignore_add_rule( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string rules); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_ignore_clear_internal_rules(git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_ignore_path_is_ignored( out int ignored, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_add_bypath( git_index* index, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_add( git_index* index, git_index_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_conflict_get( out git_index_entry* ancestor, out git_index_entry* ours, @@ -696,111 +704,111 @@ internal static extern unsafe int git_index_conflict_get( git_index* index, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_conflict_iterator_new( out git_index_conflict_iterator* iterator, git_index* index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_conflict_next( out git_index_entry* ancestor, out git_index_entry* ours, out git_index_entry* theirs, git_index_conflict_iterator* iterator); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_index_conflict_iterator_free( git_index_conflict_iterator* iterator); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_index_entrycount(git_index* index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_entry_stage(git_index_entry* indexentry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_index_free(git_index* index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_index_entry* git_index_get_byindex(git_index* index, UIntPtr n); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_index_entry* git_index_get_bypath( git_index* index, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path, int stage); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_has_conflicts(git_index* index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_index_name_entrycount(git_index* handle); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_index_name_entry* git_index_name_get_byindex(git_index* handle, UIntPtr n); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_open( out git_index* index, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath indexpath); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_read( git_index* index, [MarshalAs(UnmanagedType.Bool)] bool force); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_remove_bypath( git_index* index, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_index_reuc_entrycount(git_index* handle); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_index_reuc_entry* git_index_reuc_get_byindex(git_index* handle, UIntPtr n); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_index_reuc_entry* git_index_reuc_get_bypath( git_index* handle, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_write(git_index* index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_write_tree(out GitOid treeOid, git_index* index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_write_tree_to(out GitOid treeOid, git_index* index, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_read_tree(git_index* index, git_object* tree); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_index_clear(git_index* index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_merge_base_many( out GitOid mergeBase, git_repository* repo, int length, [In] GitOid[] input_array); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_merge_base_octopus( out GitOid mergeBase, git_repository* repo, int length, [In] GitOid[] input_array); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_annotated_commit_from_ref( out git_annotated_commit* annotatedCommit, git_repository* repo, git_reference* reference); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_annotated_commit_from_fetchhead( out git_annotated_commit* annotatedCommit, git_repository* repo, @@ -808,23 +816,23 @@ internal static extern unsafe int git_annotated_commit_from_fetchhead( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote_url, ref GitOid oid); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_annotated_commit_from_revspec( out git_annotated_commit* annotatedCommit, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string revspec); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_annotated_commit_lookup( out git_annotated_commit* annotatedCommit, git_repository* repo, ref GitOid id); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_annotated_commit_id( git_annotated_commit* annotatedCommit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_merge( git_repository* repo, [In] IntPtr[] their_heads, @@ -832,7 +840,7 @@ internal static extern unsafe int git_merge( ref GitMergeOpts merge_opts, ref GitCheckoutOpts checkout_opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_merge_commits( out git_index* index, git_repository* repo, @@ -840,7 +848,7 @@ internal static extern unsafe int git_merge_commits( git_object* their_commit, ref GitMergeOpts merge_opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_merge_analysis( out GitMergeAnalysis status_out, out GitMergePreference preference_out, @@ -848,17 +856,17 @@ internal static extern unsafe int git_merge_analysis( [In] IntPtr[] their_heads, int their_heads_len); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_annotated_commit_free(git_annotated_commit* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_message_prettify( GitBuf buf, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, [MarshalAs(UnmanagedType.Bool)] bool strip_comments, sbyte comment_char); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_note_create( out GitOid noteOid, git_repository* repo, @@ -869,24 +877,24 @@ internal static extern unsafe int git_note_create( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string note, int force); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_note_free(git_note* note); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_note_message(git_note* note); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_note_id(git_note* note); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_note_read( out git_note* note, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string notes_ref, ref GitOid oid); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_note_remove( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string notes_ref, @@ -894,141 +902,145 @@ internal static extern unsafe int git_note_remove( git_signature* committer, ref GitOid oid); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_note_default_ref( GitBuf notes_ref, git_repository* repo); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_note_foreach_cb( ref GitOid blob_id, ref GitOid annotated_object_id, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_note_foreach( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string notes_ref, git_note_foreach_cb cb, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_odb_add_backend(git_odb* odb, IntPtr backend, int priority); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr git_odb_backend_malloc(IntPtr backend, UIntPtr len); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_odb_exists(git_odb* odb, ref GitOid id); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_odb_foreach_cb( IntPtr id, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_odb_foreach( git_odb* odb, git_odb_foreach_cb cb, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_odb_open_wstream(out git_odb_stream* stream, git_odb* odb, Int64 size, GitObjectType type); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_odb_free(git_odb* odb); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_odb_read_header(out UIntPtr len_out, out GitObjectType type, git_odb* odb, ref GitOid id); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_object_free(git_object* obj); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_odb_stream_write(git_odb_stream* Stream, IntPtr Buffer, UIntPtr len); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_odb_stream_finalize_write(out GitOid id, git_odb_stream* stream); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_odb_stream_free(git_odb_stream* stream); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_odb_write(out GitOid id, git_odb* odb, byte* data, UIntPtr len, GitObjectType type); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_object_id(git_object* obj); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_object_lookup(out git_object* obj, git_repository* repo, ref GitOid id, GitObjectType type); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_object_peel( out git_object* peeled, git_object* obj, GitObjectType type); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_object_short_id( GitBuf buf, git_object* obj); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe GitObjectType git_object_type(git_object* obj); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_patch_from_diff(out git_patch* patch, git_diff* diff, UIntPtr idx); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_patch_print(git_patch* patch, git_diff_line_cb print_cb, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_patch_line_stats( out UIntPtr total_context, out UIntPtr total_additions, out UIntPtr total_deletions, git_patch* patch); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_patch_free(git_patch* patch); /* Push network progress notification function */ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_push_transfer_progress(uint current, uint total, UIntPtr bytes, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_packbuilder_progress(int stage, uint current, uint total, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_packbuilder_free(git_packbuilder* packbuilder); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_packbuilder_insert( git_packbuilder* packbuilder, ref GitOid id, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_packbuilder_insert_commit( git_packbuilder* packbuilder, ref GitOid id); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_packbuilder_insert_recur( git_packbuilder* packbuilder, ref GitOid id, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_packbuilder_insert_tree( git_packbuilder* packbuilder, ref GitOid id); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_packbuilder_new(out git_packbuilder* packbuilder, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_packbuilder_object_count(git_packbuilder* packbuilder); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UInt32 git_packbuilder_set_threads(git_packbuilder* packbuilder, UInt32 numThreads); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_packbuilder_write( git_packbuilder* packbuilder, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, @@ -1036,10 +1048,10 @@ internal static extern unsafe int git_packbuilder_write( IntPtr progressCallback, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_packbuilder_written(git_packbuilder* packbuilder); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_create( out git_reference* reference, git_repository* repo, @@ -1048,7 +1060,7 @@ internal static extern unsafe int git_reference_create( [MarshalAs(UnmanagedType.Bool)] bool force, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_symbolic_create( out git_reference* reference, git_repository* repo, @@ -1057,46 +1069,47 @@ internal static extern unsafe int git_reference_symbolic_create( [MarshalAs(UnmanagedType.Bool)] bool force, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int ref_glob_callback( IntPtr reference_name, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_foreach_glob( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string glob, ref_glob_callback callback, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_reference_free(git_reference* reference); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_reference_is_valid_name( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refname); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_list(out GitStrArray array, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_lookup( out git_reference* reference, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_reference_name(git_reference* reference); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_remove( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_reference_target(git_reference* reference); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_rename( out git_reference* ref_out, git_reference* reference, @@ -1104,114 +1117,114 @@ internal static extern unsafe int git_reference_rename( [MarshalAs(UnmanagedType.Bool)] bool force, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_set_target( out git_reference* ref_out, git_reference* reference, ref GitOid id, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_symbolic_set_target( out git_reference* ref_out, git_reference* reference, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string target, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_reference_symbolic_target(git_reference* reference); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe GitReferenceType git_reference_type(git_reference* reference); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reference_ensure_log( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refname); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_reflog_free(git_reflog* reflog); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reflog_read( out git_reflog* ref_out, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_reflog_entrycount (git_reflog* reflog); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_reflog_entry* git_reflog_entry_byindex( git_reflog* reflog, UIntPtr idx); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_reflog_entry_id_old( git_reflog_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_reflog_entry_id_new( git_reflog_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_signature* git_reflog_entry_committer( git_reflog_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_reflog_entry_message(git_reflog_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_refspec_transform( GitBuf buf, IntPtr refspec, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_refspec_rtransform( GitBuf buf, IntPtr refspec, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern string git_refspec_string( IntPtr refSpec); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern RefSpecDirection git_refspec_direction(IntPtr refSpec); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern string git_refspec_dst( IntPtr refSpec); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern string git_refspec_src( IntPtr refspec); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern bool git_refspec_force(IntPtr refSpec); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern bool git_refspec_src_matches( IntPtr refspec, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string reference); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern bool git_refspec_dst_matches( IntPtr refspec, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string reference); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_autotag(git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_connect( git_remote* remote, GitDirection direction, @@ -1219,21 +1232,21 @@ internal static extern unsafe int git_remote_connect( ref GitProxyOptions proxy_options, ref GitStrArray custom_headers); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_create( out git_remote* remote, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_create_anonymous( out git_remote* remote, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_create_with_fetchspec( out git_remote* remote, git_repository* repo, @@ -1241,125 +1254,131 @@ internal static extern unsafe int git_remote_create_with_fetchspec( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refspec); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_delete( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_fetch( git_remote* remote, ref GitStrArray refspecs, GitFetchOptions fetch_opts, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string log_message); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_remote_free(git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_get_fetch_refspecs(out GitStrArray array, git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_refspec* git_remote_get_refspec(git_remote* remote, UIntPtr n); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_get_push_refspecs(out GitStrArray array, git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_push( git_remote* remote, ref GitStrArray refSpecs, GitPushOptions opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_remote_refspec_count(git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_set_url( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_add_fetch( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_set_pushurl( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_add_push( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_remote_is_valid_name( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote_name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_list(out GitStrArray array, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_lookup( out git_remote* remote, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_remote_ls(out git_remote_head** heads, out UIntPtr size, git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_remote_name(git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_remote_url(git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_remote_pushurl(git_remote* remote); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_remote_set_autotag( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, TagFetchMode option); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int remote_progress_callback(IntPtr str, int len, IntPtr data); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int remote_completion_callback(RemoteCompletionType type, IntPtr data); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int remote_update_tips_callback( IntPtr refName, ref GitOid oldId, ref GitOid newId, IntPtr data); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int push_negotiation_callback( IntPtr updates, UIntPtr len, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int push_update_reference_callback( IntPtr refName, IntPtr status, IntPtr data ); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_repository_discover( GitBuf buf, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath start_path, [MarshalAs(UnmanagedType.Bool)] bool across_fs, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath ceiling_dirs); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_repository_fetchhead_foreach_cb( IntPtr remote_name, IntPtr remote_url, @@ -1367,147 +1386,148 @@ internal delegate int git_repository_fetchhead_foreach_cb( [MarshalAs(UnmanagedType.Bool)] bool is_merge, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_fetchhead_foreach( git_repository* repo, git_repository_fetchhead_foreach_cb cb, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_repository_free(git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_repository_head_detached(IntPtr repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_repository_head_unborn(IntPtr repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_ident( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] out string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] out string email, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_index(out git_index* index, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_init_ext( out git_repository* repository, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, GitRepositoryInitOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_repository_is_bare(IntPtr handle); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_repository_is_shallow(IntPtr repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_state_cleanup(git_repository* repo); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_repository_mergehead_foreach_cb( ref GitOid oid, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_mergehead_foreach( git_repository* repo, git_repository_mergehead_foreach_cb cb, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_message( GitBuf buf, git_repository* repository); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_new( out git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_odb(out git_odb* odb, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_open( out git_repository* repository, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_open_ext( out git_repository* repository, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path, RepositoryOpenFlags flags, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath ceilingDirs); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))] internal static extern unsafe FilePath git_repository_path(git_repository* repository); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_repository_set_config( git_repository* repository, git_config* config); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_set_ident( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string email); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_repository_set_index( git_repository* repository, git_index* index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_set_workdir( git_repository* repository, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath workdir, [MarshalAs(UnmanagedType.Bool)] bool update_gitlink); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_set_head_detached( git_repository* repo, ref GitOid commitish); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_set_head_detached_from_annotated( git_repository* repo, git_annotated_commit* commit); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_set_head( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refname); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_state( git_repository* repository); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))] internal static extern unsafe FilePath git_repository_workdir(git_repository* repository); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))] internal static extern FilePath git_repository_workdir(IntPtr repository); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_reset( git_repository* repo, git_object* target, ResetMode reset_type, ref GitCheckoutOpts opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_revert( git_repository* repo, git_object* commit, GitRevertOpts opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_revert_commit( out git_index* index, git_repository* repo, @@ -1516,41 +1536,41 @@ internal static extern unsafe int git_revert_commit( uint mainline, ref GitMergeOpts opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_revparse_ext( out git_object* obj, out git_reference* reference, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string spec); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_revwalk_free(git_revwalk* walker); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_revwalk_hide(git_revwalk* walker, ref GitOid commit_id); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_revwalk_new(out git_revwalk* walker, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_revwalk_next(out GitOid id, git_revwalk* walker); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_revwalk_push(git_revwalk* walker, ref GitOid id); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_revwalk_reset(git_revwalk* walker); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_revwalk_sorting(git_revwalk* walk, CommitSortStrategies sort); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_revwalk_simplify_first_parent(git_revwalk* walk); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_signature_free(git_signature* signature); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_signature_new( out git_signature* signature, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, @@ -1558,16 +1578,16 @@ internal static extern unsafe int git_signature_new( long time, int offset); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_signature_now( out git_signature* signature, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string email); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_signature_dup(out git_signature* dest, git_signature* sig); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_stash_save( out GitOid id, git_repository* repo, @@ -1575,152 +1595,154 @@ internal static extern unsafe int git_stash_save( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message, StashModifiers flags); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_stash_cb( UIntPtr index, IntPtr message, ref GitOid stash_id, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_stash_foreach( git_repository* repo, git_stash_cb callback, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_stash_drop(git_repository* repo, UIntPtr index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_stash_apply( git_repository* repo, UIntPtr index, GitStashApplyOpts opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_stash_pop( git_repository* repo, UIntPtr index, GitStashApplyOpts opts); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_status_file( out FileStatus statusflags, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath filepath); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_status_list_new( out git_status_list* git_status_list, git_repository* repo, GitStatusOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_status_list_entrycount( git_status_list* statusList); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_status_entry* git_status_byindex( git_status_list* list, UIntPtr idx); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_status_list_free( git_status_list* statusList); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void git_strarray_free( ref GitStrArray array); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_submodule_lookup( out git_submodule* reference, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_submodule_resolve_url( GitBuf buf, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_submodule_update( git_submodule* sm, [MarshalAs(UnmanagedType.Bool)] bool init, ref GitSubmoduleUpdateOptions submoduleUpdateOptions); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int submodule_callback( IntPtr sm, IntPtr name, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_submodule_foreach( git_repository* repo, submodule_callback callback, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_submodule_add_to_index( git_submodule* submodule, [MarshalAs(UnmanagedType.Bool)] bool write_index); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_submodule_free(git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_submodule_path( git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_submodule_url( git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_submodule_index_id( git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_submodule_head_id( git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_submodule_wd_id( git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe SubmoduleIgnore git_submodule_ignore( git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe SubmoduleUpdate git_submodule_update_strategy( git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe SubmoduleRecurse git_submodule_fetch_recurse_submodules( git_submodule* submodule); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_submodule_reload( git_submodule* submodule, [MarshalAs(UnmanagedType.Bool)] bool force); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_submodule_status( out SubmoduleStatus status, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath name, GitSubmoduleIgnore ignore); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_submodule_init( git_submodule* submodule, [MarshalAs(UnmanagedType.Bool)] bool overwrite); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_tag_annotation_create( out GitOid oid, git_repository* repo, @@ -1729,7 +1751,7 @@ internal static extern unsafe int git_tag_annotation_create( git_signature* signature, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_tag_create( out GitOid oid, git_repository* repo, @@ -1740,7 +1762,7 @@ internal static extern unsafe int git_tag_create( [MarshalAs(UnmanagedType.Bool)] bool force); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_tag_create_lightweight( out GitOid oid, git_repository* repo, @@ -1749,113 +1771,117 @@ internal static extern unsafe int git_tag_create_lightweight( [MarshalAs(UnmanagedType.Bool)] bool force); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_tag_delete( git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string tagName); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_tag_list(out GitStrArray array, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_tag_message(git_object* tag); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_tag_name(git_object* tag); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_signature* git_tag_tagger(git_object* tag); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_tag_target_id(git_object* tag); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe GitObjectType git_tag_target_type(git_object* tag); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_libgit2_init(); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_libgit2_shutdown(); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_openssl_set_locking(); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void git_trace_cb(LogLevel level, IntPtr message); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_trace_set(LogLevel level, git_trace_cb trace_cb); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_transfer_progress_callback(ref GitTransferProgress stats, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int git_transport_cb(out IntPtr transport, IntPtr remote, IntPtr payload); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal unsafe delegate int git_transport_certificate_check_cb(git_certificate* cert, int valid, IntPtr hostname, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_transport_register( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string prefix, IntPtr transport_cb, IntPtr payload); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_transport_smart( out IntPtr transport, IntPtr remote, IntPtr definition); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_transport_smart_certificate_check( IntPtr transport, IntPtr cert, int valid, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string hostname); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_transport_smart_credentials( out IntPtr cred_out, IntPtr transport, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string user, int methods); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_transport_unregister( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string prefix); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe uint git_tree_entry_filemode(git_tree_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_tree_entry* git_tree_entry_byindex(git_object* tree, UIntPtr idx); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_tree_entry_bypath( out git_tree_entry* tree, git_object* root, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string treeentry_path); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_tree_entry_free(git_tree_entry* treeEntry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_oid* git_tree_entry_id(git_tree_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))] internal static extern unsafe string git_tree_entry_name(git_tree_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe GitObjectType git_tree_entry_type(git_tree_entry* entry); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UIntPtr git_tree_entrycount(git_object* tree); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_treebuilder_new(out git_treebuilder* builder, git_repository* repo, IntPtr src); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_treebuilder_insert( IntPtr entry_out, git_treebuilder* builder, @@ -1863,19 +1889,19 @@ internal static extern unsafe int git_treebuilder_insert( ref GitOid id, uint attributes); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_treebuilder_write(out GitOid id, git_treebuilder* bld); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_treebuilder_free(git_treebuilder* bld); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_blob_is_binary(git_object* blob); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_cherrypick(git_repository* repo, git_object* commit, GitCherryPickOptions options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_cherrypick_commit(out git_index* index, git_repository* repo, git_object* cherrypick_commit, @@ -1883,50 +1909,50 @@ internal static extern unsafe int git_cherrypick_commit(out git_index* index, uint mainline, ref GitMergeOpts options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_transaction_commit(IntPtr txn); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern void git_transaction_free(IntPtr txn); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_worktree_free(git_worktree* worktree); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_worktree_lookup( out git_worktree* reference, git_repository* repo, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_worktree_list( out GitStrArray array, git_repository* repo); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_repository_open_from_worktree( out git_repository* repository, git_worktree* worktree); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_worktree_is_locked( GitBuf reason, git_worktree* worktree); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_worktree_validate( git_worktree* worktree); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_worktree_lock( git_worktree* worktree, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string reason); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_worktree_unlock( git_worktree* worktree); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_worktree_add ( out git_worktree* reference, git_repository* repo, @@ -1934,7 +1960,7 @@ internal static extern unsafe int git_worktree_add ( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path, git_worktree_add_options options); - [DllImport(libgit2)] + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_worktree_prune( git_worktree* worktree, git_worktree_prune_options options); From 2d6d3e6252544a836c2b2b27fa86116f1e22d446 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 5 Feb 2019 22:54:07 +0000 Subject: [PATCH 139/384] git_buf: dispose instead of free libgit2 has updated some function signatures for consistency, including `git_buf_free` which is now `git_buf_dispose`. --- LibGit2Sharp/Core/GitBuf.cs | 2 +- LibGit2Sharp/Core/NativeMethods.cs | 2 +- LibGit2Sharp/Core/Proxy.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp/Core/GitBuf.cs b/LibGit2Sharp/Core/GitBuf.cs index 09860fdc3..19b1328b9 100644 --- a/LibGit2Sharp/Core/GitBuf.cs +++ b/LibGit2Sharp/Core/GitBuf.cs @@ -12,7 +12,7 @@ internal class GitBuf : IDisposable public void Dispose() { - Proxy.git_buf_free(this); + Proxy.git_buf_dispose(this); } } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index e8dfc833c..b21a2a211 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -279,7 +279,7 @@ internal static extern unsafe int git_branch_upstream_name( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string referenceName); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern void git_buf_free(GitBuf buf); + internal static extern void git_buf_dispose(GitBuf buf); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_checkout_tree( diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index b8e607ecd..4a955e6bd 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -286,9 +286,9 @@ public static unsafe string git_branch_upstream_name(RepositoryHandle handle, st #region git_buf_ - public static void git_buf_free(GitBuf buf) + public static void git_buf_dispose(GitBuf buf) { - NativeMethods.git_buf_free(buf); + NativeMethods.git_buf_dispose(buf); } #endregion From ba308b8f49bdf700ba556ff3ad88e1dcbbb1479c Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 5 Feb 2019 23:00:02 +0000 Subject: [PATCH 140/384] git_error: instead of giterr libgit2 has updated some function signatures for consistency, including the `giterr` family of functions which is now `git_error`. --- LibGit2Sharp/Core/Ensure.cs | 2 +- LibGit2Sharp/Core/NativeMethods.cs | 6 +- LibGit2Sharp/Core/Proxy.cs | 158 +++++++++--------- LibGit2Sharp/Filter.cs | 10 +- LibGit2Sharp/OdbBackend.cs | 22 +-- LibGit2Sharp/OdbBackendStream.cs | 8 +- LibGit2Sharp/RemoteCallbacks.cs | 6 +- LibGit2Sharp/SmartSubtransport.cs | 6 +- LibGit2Sharp/SmartSubtransportRegistration.cs | 4 +- LibGit2Sharp/SmartSubtransportStream.cs | 6 +- 10 files changed, 114 insertions(+), 114 deletions(-) diff --git a/LibGit2Sharp/Core/Ensure.cs b/LibGit2Sharp/Core/Ensure.cs index d82fa3a4b..261794b0a 100644 --- a/LibGit2Sharp/Core/Ensure.cs +++ b/LibGit2Sharp/Core/Ensure.cs @@ -134,7 +134,7 @@ private static unsafe void HandleError(int result) { string errorMessage; GitErrorCategory errorCategory = GitErrorCategory.Unknown; - GitError* error = NativeMethods.giterr_last(); + GitError* error = NativeMethods.git_error_last(); if (error == null) { diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index b21a2a211..aa82516a4 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -96,15 +96,15 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject } [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe GitError* giterr_last(); + internal static extern unsafe GitError* git_error_last(); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern void giterr_set_str( + internal static extern void git_error_set_str( GitErrorCategory error_class, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string errorString); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern void giterr_set_oom(); + internal static extern void git_error_set_oom(); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe UInt32 git_blame_get_hunk_count(git_blame* blame); diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 4a955e6bd..de31b4a1e 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -14,85 +14,6 @@ namespace LibGit2Sharp.Core { internal class Proxy { - #region giterr_ - - public static void giterr_set_str(GitErrorCategory error_class, Exception exception) - { - if (exception is OutOfMemoryException) - { - NativeMethods.giterr_set_oom(); - } - else - { - NativeMethods.giterr_set_str(error_class, ErrorMessageFromException(exception)); - } - } - - public static void giterr_set_str(GitErrorCategory error_class, String errorString) - { - NativeMethods.giterr_set_str(error_class, errorString); - } - - /// - /// This method will take an exception and try to generate an error message - /// that captures the important messages of the error. - /// The formatting is a bit subjective. - /// - /// - /// - public static string ErrorMessageFromException(Exception ex) - { - StringBuilder sb = new StringBuilder(); - BuildErrorMessageFromException(sb, 0, ex); - return sb.ToString(); - } - - private static void BuildErrorMessageFromException(StringBuilder sb, int level, Exception ex) - { - string indent = new string(' ', level * 4); - sb.AppendFormat("{0}{1}", indent, ex.Message); - - if (ex is AggregateException) - { - AggregateException aggregateException = ((AggregateException)ex).Flatten(); - - if (aggregateException.InnerExceptions.Count == 1) - { - sb.AppendLine(); - sb.AppendLine(); - - sb.AppendFormat("{0}Contained Exception:{1}", indent, Environment.NewLine); - BuildErrorMessageFromException(sb, level + 1, aggregateException.InnerException); - } - else - { - sb.AppendLine(); - sb.AppendLine(); - - sb.AppendFormat("{0}Contained Exceptions:{1}", indent, Environment.NewLine); - for (int i = 0; i < aggregateException.InnerExceptions.Count; i++) - { - if (i != 0) - { - sb.AppendLine(); - sb.AppendLine(); - } - - BuildErrorMessageFromException(sb, level + 1, aggregateException.InnerExceptions[i]); - } - } - } - else if (ex.InnerException != null) - { - sb.AppendLine(); - sb.AppendLine(); - sb.AppendFormat("{0}Inner Exception:{1}", indent, Environment.NewLine); - BuildErrorMessageFromException(sb, level + 1, ex.InnerException); - } - } - - #endregion - #region git_blame_ public static unsafe BlameHandle git_blame_file( @@ -924,6 +845,85 @@ public static unsafe int git_diff_num_deltas(DiffHandle diff) #endregion + #region git_error_ + + public static void git_error_set_str(GitErrorCategory error_class, Exception exception) + { + if (exception is OutOfMemoryException) + { + NativeMethods.git_error_set_oom(); + } + else + { + NativeMethods.git_error_set_str(error_class, ErrorMessageFromException(exception)); + } + } + + public static void git_error_set_str(GitErrorCategory error_class, String errorString) + { + NativeMethods.git_error_set_str(error_class, errorString); + } + + /// + /// This method will take an exception and try to generate an error message + /// that captures the important messages of the error. + /// The formatting is a bit subjective. + /// + /// + /// + public static string ErrorMessageFromException(Exception ex) + { + StringBuilder sb = new StringBuilder(); + BuildErrorMessageFromException(sb, 0, ex); + return sb.ToString(); + } + + private static void BuildErrorMessageFromException(StringBuilder sb, int level, Exception ex) + { + string indent = new string(' ', level * 4); + sb.AppendFormat("{0}{1}", indent, ex.Message); + + if (ex is AggregateException) + { + AggregateException aggregateException = ((AggregateException)ex).Flatten(); + + if (aggregateException.InnerExceptions.Count == 1) + { + sb.AppendLine(); + sb.AppendLine(); + + sb.AppendFormat("{0}Contained Exception:{1}", indent, Environment.NewLine); + BuildErrorMessageFromException(sb, level + 1, aggregateException.InnerException); + } + else + { + sb.AppendLine(); + sb.AppendLine(); + + sb.AppendFormat("{0}Contained Exceptions:{1}", indent, Environment.NewLine); + for (int i = 0; i < aggregateException.InnerExceptions.Count; i++) + { + if (i != 0) + { + sb.AppendLine(); + sb.AppendLine(); + } + + BuildErrorMessageFromException(sb, level + 1, aggregateException.InnerExceptions[i]); + } + } + } + else if (ex.InnerException != null) + { + sb.AppendLine(); + sb.AppendLine(); + sb.AppendFormat("{0}Inner Exception:{1}", indent, Environment.NewLine); + BuildErrorMessageFromException(sb, level + 1, ex.InnerException); + } + } + + #endregion + #region git_filter_ public static void git_filter_register(string name, IntPtr filterPtr, int priority) diff --git a/LibGit2Sharp/Filter.cs b/LibGit2Sharp/Filter.cs index 1fd0587e5..5a46e12b5 100644 --- a/LibGit2Sharp/Filter.cs +++ b/LibGit2Sharp/Filter.cs @@ -236,7 +236,7 @@ int InitializeCallback(IntPtr filterPointer) { Log.Write(LogLevel.Error, "Filter.InitializeCallback exception"); Log.Write(LogLevel.Error, exception.ToString()); - Proxy.giterr_set_str(GitErrorCategory.Filter, exception); + Proxy.git_error_set_str(GitErrorCategory.Filter, exception); result = (int)GitErrorCode.Error; } return result; @@ -286,7 +286,7 @@ int StreamCreateCallback(out IntPtr git_writestream_out, GitFilter self, IntPtr Log.Write(LogLevel.Error, "Filter.StreamCreateCallback exception"); Log.Write(LogLevel.Error, exception.ToString()); - Proxy.giterr_set_str(GitErrorCategory.Filter, exception); + Proxy.git_error_set_str(GitErrorCategory.Filter, exception); result = (int)GitErrorCode.Error; } @@ -322,7 +322,7 @@ int StreamCloseCallback(IntPtr stream) { Log.Write(LogLevel.Error, "Filter.StreamCloseCallback exception"); Log.Write(LogLevel.Error, exception.ToString()); - Proxy.giterr_set_str(GitErrorCategory.Filter, exception); + Proxy.git_error_set_str(GitErrorCategory.Filter, exception); result = (int)GitErrorCode.Error; } @@ -384,7 +384,7 @@ unsafe int StreamWriteCallback(IntPtr stream, IntPtr buffer, UIntPtr len) break; default: - Proxy.giterr_set_str(GitErrorCategory.Filter, "Unexpected filter mode."); + Proxy.git_error_set_str(GitErrorCategory.Filter, "Unexpected filter mode."); return (int)GitErrorCode.Ambiguous; } } @@ -393,7 +393,7 @@ unsafe int StreamWriteCallback(IntPtr stream, IntPtr buffer, UIntPtr len) { Log.Write(LogLevel.Error, "Filter.StreamWriteCallback exception"); Log.Write(LogLevel.Error, exception.ToString()); - Proxy.giterr_set_str(GitErrorCategory.Filter, exception); + Proxy.git_error_set_str(GitErrorCategory.Filter, exception); result = (int)GitErrorCode.Error; } diff --git a/LibGit2Sharp/OdbBackend.cs b/LibGit2Sharp/OdbBackend.cs index d96e15909..9736ed803 100644 --- a/LibGit2Sharp/OdbBackend.cs +++ b/LibGit2Sharp/OdbBackend.cs @@ -238,7 +238,7 @@ private static OdbBackend MarshalOdbBackend(IntPtr backendPtr) if (odbBackend == null) { - Proxy.giterr_set_str(GitErrorCategory.Reference, "Cannot retrieve the managed OdbBackend."); + Proxy.git_error_set_str(GitErrorCategory.Reference, "Cannot retrieve the managed OdbBackend."); return null; } @@ -288,7 +288,7 @@ private unsafe static int Read( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return (int)GitErrorCode.Error; } finally @@ -352,7 +352,7 @@ private unsafe static int ReadPrefix( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return (int)GitErrorCode.Error; } finally @@ -397,7 +397,7 @@ private static int ReadHeader( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return (int)GitErrorCode.Error; } @@ -428,7 +428,7 @@ private static unsafe int Write( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return (int)GitErrorCode.Error; } } @@ -463,7 +463,7 @@ private static int WriteStream( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return (int)GitErrorCode.Error; } } @@ -495,7 +495,7 @@ private static int ReadStream( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return (int)GitErrorCode.Error; } } @@ -516,7 +516,7 @@ private static bool Exists( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return false; } } @@ -550,7 +550,7 @@ private static int ExistsPrefix( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return (int)GitErrorCode.Error; } } @@ -572,7 +572,7 @@ private static int Foreach( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); return (int)GitErrorCode.Error; } } @@ -601,7 +601,7 @@ private static void Free( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); } } diff --git a/LibGit2Sharp/OdbBackendStream.cs b/LibGit2Sharp/OdbBackendStream.cs index 2889ac20b..e7d177903 100644 --- a/LibGit2Sharp/OdbBackendStream.cs +++ b/LibGit2Sharp/OdbBackendStream.cs @@ -140,7 +140,7 @@ private unsafe static int Read(IntPtr stream, IntPtr buffer, UIntPtr len) } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); } } } @@ -164,7 +164,7 @@ private static unsafe int Write(IntPtr stream, IntPtr buffer, UIntPtr len) } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); } } } @@ -184,7 +184,7 @@ private static int FinalizeWrite(IntPtr stream, ref GitOid oid) } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); } } @@ -203,7 +203,7 @@ private static void Free(IntPtr stream) } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Odb, ex); + Proxy.git_error_set_str(GitErrorCategory.Odb, ex); } } } diff --git a/LibGit2Sharp/RemoteCallbacks.cs b/LibGit2Sharp/RemoteCallbacks.cs index 9958c6844..ce5dccf81 100644 --- a/LibGit2Sharp/RemoteCallbacks.cs +++ b/LibGit2Sharp/RemoteCallbacks.cs @@ -297,7 +297,7 @@ private int GitCredentialHandler( } catch (Exception exception) { - Proxy.giterr_set_str(GitErrorCategory.Callback, exception); + Proxy.git_error_set_str(GitErrorCategory.Callback, exception); return (int)GitErrorCode.Error; } } @@ -324,7 +324,7 @@ private unsafe int GitCertificateCheck(git_certificate* certPtr, int valid, IntP } catch (Exception exception) { - Proxy.giterr_set_str(GitErrorCategory.Callback, exception); + Proxy.git_error_set_str(GitErrorCategory.Callback, exception); } return Proxy.ConvertResultToCancelFlag(result); @@ -365,7 +365,7 @@ private int GitPushNegotiationHandler(IntPtr updates, UIntPtr len, IntPtr payloa catch (Exception exception) { Log.Write(LogLevel.Error, exception.ToString()); - Proxy.giterr_set_str(GitErrorCategory.Callback, exception); + Proxy.git_error_set_str(GitErrorCategory.Callback, exception); result = false; } diff --git a/LibGit2Sharp/SmartSubtransport.cs b/LibGit2Sharp/SmartSubtransport.cs index 709f0c230..c4e7f499a 100644 --- a/LibGit2Sharp/SmartSubtransport.cs +++ b/LibGit2Sharp/SmartSubtransport.cs @@ -213,7 +213,7 @@ private static int Action( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Net, ex); + Proxy.git_error_set_str(GitErrorCategory.Net, ex); } } @@ -234,7 +234,7 @@ private static int Close(IntPtr subtransport) } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Net, ex); + Proxy.git_error_set_str(GitErrorCategory.Net, ex); } } @@ -253,7 +253,7 @@ private static void Free(IntPtr subtransport) } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Net, ex); + Proxy.git_error_set_str(GitErrorCategory.Net, ex); } } } diff --git a/LibGit2Sharp/SmartSubtransportRegistration.cs b/LibGit2Sharp/SmartSubtransportRegistration.cs index e9f21dada..fd7cae961 100644 --- a/LibGit2Sharp/SmartSubtransportRegistration.cs +++ b/LibGit2Sharp/SmartSubtransportRegistration.cs @@ -85,7 +85,7 @@ private static int Subtransport( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Net, ex); + Proxy.git_error_set_str(GitErrorCategory.Net, ex); } return (int)GitErrorCode.Error; @@ -104,7 +104,7 @@ private static int Transport( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Net, ex); + Proxy.git_error_set_str(GitErrorCategory.Net, ex); } return (int)GitErrorCode.Error; diff --git a/LibGit2Sharp/SmartSubtransportStream.cs b/LibGit2Sharp/SmartSubtransportStream.cs index b5cb21c02..eb3d23e5b 100644 --- a/LibGit2Sharp/SmartSubtransportStream.cs +++ b/LibGit2Sharp/SmartSubtransportStream.cs @@ -126,7 +126,7 @@ private unsafe static int Read( } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Net, ex); + Proxy.git_error_set_str(GitErrorCategory.Net, ex); } } } @@ -151,7 +151,7 @@ private static unsafe int Write(IntPtr stream, IntPtr buffer, UIntPtr len) } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Net, ex); + Proxy.git_error_set_str(GitErrorCategory.Net, ex); } } } @@ -172,7 +172,7 @@ private static void Free(IntPtr stream) } catch (Exception ex) { - Proxy.giterr_set_str(GitErrorCategory.Net, ex); + Proxy.git_error_set_str(GitErrorCategory.Net, ex); } } } From 7adb53894bd02ad0c72e792eba02bacd2d985100 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 14 Feb 2019 22:08:28 +0000 Subject: [PATCH 141/384] Update libgit2 to v0.28.1 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 685531ac3..4c35a6cea 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From c2375780b9a12bb824456b1b34fa5cb5e65ee2d6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 14 Feb 2019 23:56:58 +0000 Subject: [PATCH 142/384] CHANGES: update for v0.26.0 --- CHANGES.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 5f606ea43..78bd537f6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,7 +10,14 @@ - Windows (x86/amd64): - Linux/Mac OS X: -## v0.26 +## v0.26 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.25..v0.26)) + +### Additions + +* Add `CherryPickCommitIntoIndex` to `ObjectDatabase` +* The underlying native library (libgit2) now no longer relies on libcurl +* The underlying native library now no longer relies on zlib +* Add `IndentHeuristic` option to `CompareOptions` ## v0.25 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.24..v0.25)) From a709ab84d4b3c14e7aa9038c2c6b05c57a6b007f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 15 Feb 2019 08:44:52 +0000 Subject: [PATCH 143/384] Release 0.26 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 6d9e98151..b0068cfdf 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-preview.{height}", + "version": "0.26.0", "publicReleaseRefSpec": [ "^refs/heads/master$", // we release out of master "^refs/heads/maint/v\\d+(?:\\.\\d+)?$" // and maint/vNN branches From 0e1aed5e361a47db9273fed7fd09f2f1f680cbcf Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 15 Feb 2019 09:21:39 +0000 Subject: [PATCH 144/384] 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 145/384] 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 146/384] 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 147/384] 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 148/384] 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 149/384] 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 150/384] 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 151/384] 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 152/384] 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 153/384] 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 154/384] 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 155/384] 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 156/384] 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 157/384] 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 158/384] 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 159/384] 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 160/384] 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 161/384] 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 162/384] 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 163/384] 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 164/384] 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 165/384] 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 166/384] 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 167/384] 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 168/384] 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 169/384] 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 170/384] 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 171/384] 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 172/384] 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 173/384] 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 174/384] 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 175/384] 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 176/384] 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 177/384] 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 178/384] 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 179/384] 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 180/384] 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 181/384] 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 182/384] 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 183/384] 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 184/384] 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 185/384] 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 186/384] 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 187/384] 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 188/384] 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 189/384] 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 190/384] 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 191/384] 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 192/384] 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 193/384] 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 194/384] 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 195/384] 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 196/384] 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 197/384] 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 198/384] 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 199/384] 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 200/384] 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 201/384] 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 202/384] 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 203/384] 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 204/384] 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 205/384] 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 206/384] 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 207/384] 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 208/384] 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 209/384] 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 210/384] 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 211/384] 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 212/384] 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 213/384] 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 214/384] 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 215/384] 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 216/384] 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 217/384] 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 218/384] 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 219/384] 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 220/384] 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 221/384] 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 222/384] 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 223/384] 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 224/384] 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 225/384] 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 226/384] 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 227/384] 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 228/384] 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 229/384] 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 230/384] 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 231/384] 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 232/384] 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 233/384] 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 234/384] 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 235/384] 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 236/384] 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 237/384] 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 238/384] 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 239/384] 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 240/384] 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 241/384] 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 242/384] 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 243/384] 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 244/384] 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 245/384] 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 246/384] 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 247/384] 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 248/384] 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 249/384] 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 250/384] 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 251/384] 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 252/384] 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 253/384] 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 254/384] 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 255/384] 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 256/384] 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 257/384] 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 258/384] 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 259/384] 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 260/384] 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 261/384] 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 262/384] 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 263/384] 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 264/384] 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 265/384] 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 266/384] 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 267/384] 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 268/384] 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 269/384] 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 270/384] 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 271/384] 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 272/384] 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 273/384] 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 274/384] 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 275/384] 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 276/384] 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 277/384] 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 278/384] 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 279/384] 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 280/384] 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 281/384] 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 282/384] 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 283/384] 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 284/384] 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 285/384] 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 286/384] 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 287/384] 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 288/384] 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 289/384] 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 290/384] 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 291/384] 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 292/384] 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 293/384] 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 294/384] 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 295/384] 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 296/384] 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 297/384] 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 298/384] 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 299/384] 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 300/384] 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 301/384] 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 302/384] 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 303/384] 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 304/384] 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 305/384] 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 306/384] 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 307/384] 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 308/384] 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 309/384] 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 310/384] 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 311/384] 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 312/384] 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 313/384] 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 314/384] 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 315/384] 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 316/384] 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 317/384] 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 318/384] 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 319/384] 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 320/384] 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 321/384] 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 322/384] 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)) From 10cd32c43a73995e6c61e091868d9722e8060ff3 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 10 Apr 2023 21:04:31 -0400 Subject: [PATCH 323/384] Add PackageReadmeFile property --- LibGit2Sharp/LibGit2Sharp.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 6aa70519c..db0d2b29f 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -15,6 +15,7 @@ true ..\libgit2sharp.snk square-logo.png + App_Readme/README.md App_Readme/LICENSE.md true preview.0 From 4dc402a36e795b956475fbde41d50555dfdde58b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 11 Apr 2023 13:07:20 -0400 Subject: [PATCH 324/384] Fix AssemblyVersion and PackageVersion --- LibGit2Sharp/LibGit2Sharp.csproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index db0d2b29f..abab84c8a 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -47,4 +47,12 @@ + + + $(MinVerMajor).$(MinVerMinor).0.0 + $(MinVerMajor).$(MinVerMinor).$(MinVerPatch) + $(PackageVersion)-$(MinVerPreRelease) + + + From 82c190bb997b5e1a003d47b51f662150332697ae Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 11 Apr 2023 13:21:18 -0400 Subject: [PATCH 325/384] Add fix to Changes doc --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index c902a8640..6341b4438 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # LibGit2Sharp Changes +## v0.27.1 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.27.0..0.27.1)) + +### Fixes + - AssemblyVersion of v0.27.0 is `0.0.0.0`, which is lower than the AssemblyVersion of the v0.26.x releases. [#2030](https://github.com/libgit2/libgit2sharp/pull/2030) + ## v0.27 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.26..0.27.0)) ### Changes From 2419633cf4673b6a7d36af9cf47f25a84587acdd Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 12 Apr 2023 12:45:06 -0400 Subject: [PATCH 326/384] Update LibGit2Sharp.NativeBinaries to 2.0.320 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index abab84c8a..f690c9107 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -33,7 +33,7 @@ - + From ce3be35fb51968e007b6a9f3478bb5078ba3c4c3 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 12 Apr 2023 15:05:26 -0400 Subject: [PATCH 327/384] Update CHANGES doc --- CHANGES.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 6341b4438..a3a74c0d5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,9 +1,17 @@ # LibGit2Sharp Changes +## v0.27.2 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.27.1..0.27.2)) + +### Changes +- This release includes [libgit2 v1.6.4](https://github.com/libgit2/libgit2/releases/tag/v1.6.4). + +### Fixes +- Can't access GIT config (Repository.Config) since v0.27.0 [#2031](https://github.com/libgit2/libgit2sharp/issues/2031) + ## v0.27.1 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.27.0..0.27.1)) ### Fixes - - AssemblyVersion of v0.27.0 is `0.0.0.0`, which is lower than the AssemblyVersion of the v0.26.x releases. [#2030](https://github.com/libgit2/libgit2sharp/pull/2030) +- AssemblyVersion of v0.27.0 is `0.0.0.0`, which is lower than the AssemblyVersion of the v0.26.x releases. [#2030](https://github.com/libgit2/libgit2sharp/pull/2030) ## v0.27 - ([diff](https://github.com/libgit2/libgit2sharp/compare/v0.26..0.27.0)) From 714a4262374c8da4964debb7a049ef7a9d88b823 Mon Sep 17 00:00:00 2001 From: James La Novara-Gsell Date: Thu, 2 Nov 2023 23:04:14 -0400 Subject: [PATCH 328/384] feat: Add CustomHeaders to PushOptions Wires up CustomHeaders in PushOptions in the same vain as FetchOptions. --- LibGit2Sharp.Tests/PushFixture.cs | 27 ++++++++++++++++ LibGit2Sharp/Core/GitPushOptionsWrapper.cs | 36 ++++++++++++++++++++++ LibGit2Sharp/Network.cs | 21 +++++++++---- LibGit2Sharp/PushOptions.cs | 20 ++++++++++++ 4 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 LibGit2Sharp/Core/GitPushOptionsWrapper.cs diff --git a/LibGit2Sharp.Tests/PushFixture.cs b/LibGit2Sharp.Tests/PushFixture.cs index d8cf2befe..fc6c0c42d 100644 --- a/LibGit2Sharp.Tests/PushFixture.cs +++ b/LibGit2Sharp.Tests/PushFixture.cs @@ -196,6 +196,33 @@ public void CanForcePush() } } + [Fact] + public void CanPushWithCustomHeaders() + { + const string knownHeader = "X-Hello: mygit-201"; + var options = new PushOptions { CustomHeaders = new string[] { knownHeader } }; + AssertPush(repo => + repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options)); + } + + [Fact] + public void CannotPushWithForbiddenCustomHeaders() + { + const string knownHeader = "User-Agent: mygit-201"; + var options = new PushOptions { CustomHeaders = new string[] { knownHeader } }; + Assert.Throws( + () => AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options))); + } + + [Fact] + public void CannotPushWithMalformedCustomHeaders() + { + const string knownHeader = "Hello world"; + var options = new PushOptions { CustomHeaders = new string[] { knownHeader } }; + Assert.Throws( + () => AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options))); + } + private static void AssertRemoteHeadTipEquals(IRepository localRepo, string sha) { var remoteReferences = localRepo.Network.ListReferences(localRepo.Network.Remotes.Single()); diff --git a/LibGit2Sharp/Core/GitPushOptionsWrapper.cs b/LibGit2Sharp/Core/GitPushOptionsWrapper.cs new file mode 100644 index 000000000..ffac5a220 --- /dev/null +++ b/LibGit2Sharp/Core/GitPushOptionsWrapper.cs @@ -0,0 +1,36 @@ +using System; + +namespace LibGit2Sharp.Core +{ + /// + /// Git push options wrapper. Disposable wrapper for . + /// + internal class GitPushOptionsWrapper : IDisposable + { + public GitPushOptionsWrapper() : this(new GitPushOptions()) { } + + public GitPushOptionsWrapper(GitPushOptions pushOptions) + { + this.Options = pushOptions; + } + + public GitPushOptions Options { get; private set; } + + #region IDisposable + private bool disposedValue = false; // To detect redundant calls + protected virtual void Dispose(bool disposing) + { + if (disposedValue) + return; + + this.Options.CustomHeaders.Dispose(); + disposedValue = true; + } + + public void Dispose() + { + Dispose(true); + } + #endregion + } +} diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs index d5f032058..825f3c886 100644 --- a/LibGit2Sharp/Network.cs +++ b/LibGit2Sharp/Network.cs @@ -365,18 +365,27 @@ public virtual void Push(Remote remote, IEnumerable pushRefSpecs, PushOp // Load the remote. using (RemoteHandle remoteHandle = Proxy.git_remote_lookup(repository.Handle, remote.Name, true)) + + // Create a git options wrapper so managed strings are disposed. + using (var pushOptionsWrapper = new GitPushOptionsWrapper()) { var callbacks = new RemoteCallbacks(pushOptions); GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks(); + var gitPushOptions = pushOptionsWrapper.Options; + gitPushOptions.PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism; + gitPushOptions.RemoteCallbacks = gitCallbacks; + gitPushOptions.ProxyOptions = new GitProxyOptions { Version = 1 }; + + // If there are custom headers, create a managed string array. + if (pushOptions.CustomHeaders != null && pushOptions.CustomHeaders.Length > 0) + { + gitPushOptions.CustomHeaders = GitStrArrayManaged.BuildFrom(pushOptions.CustomHeaders); + } + Proxy.git_remote_push(remoteHandle, pushRefSpecs, - new GitPushOptions() - { - PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism, - RemoteCallbacks = gitCallbacks, - ProxyOptions = new GitProxyOptions { Version = 1 }, - }); + gitPushOptions); } } diff --git a/LibGit2Sharp/PushOptions.cs b/LibGit2Sharp/PushOptions.cs index 99c65dd8b..f7d37eba9 100644 --- a/LibGit2Sharp/PushOptions.cs +++ b/LibGit2Sharp/PushOptions.cs @@ -51,5 +51,25 @@ public sealed class PushOptions /// information about what updates will be performed. /// public PrePushHandler OnNegotiationCompletedBeforePush { get; set; } + + /// + /// Get/Set the custom headers. + /// + /// This allows you to set custom headers (e.g. X-Forwarded-For, + /// X-Request-Id, etc), + /// + /// + /// + /// Libgit2 sets some headers for HTTP requests (User-Agent, Host, + /// Accept, Content-Type, Transfer-Encoding, Content-Length, Accept) that + /// cannot be overriden. + /// + /// + /// var pushOptions - new PushOptions() { + /// CustomHeaders = new String[] {"X-Request-Id: 12345"} + /// }; + /// + /// The custom headers string array + public string[] CustomHeaders { get; set; } } } From feb83448abaec82446ba6b6e37986890f0fcbd59 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 4 Nov 2023 16:37:00 -0400 Subject: [PATCH 329/384] Update MinVer --- LibGit2Sharp/LibGit2Sharp.csproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index f690c9107..b80d75cd0 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -35,7 +35,7 @@ - + @@ -50,8 +50,6 @@ $(MinVerMajor).$(MinVerMinor).0.0 - $(MinVerMajor).$(MinVerMinor).$(MinVerPatch) - $(PackageVersion)-$(MinVerPreRelease) From 1c409f9dc5ad0a06d210c0a3f693e021875645d0 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 4 Nov 2023 16:40:17 -0400 Subject: [PATCH 330/384] Update CHANGES.md for v0.28 --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index a3a74c0d5..0cb2c978b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # LibGit2Sharp Changes +## v0.28 + +### Additions +- Add CustomHeaders to PushOptions [#2052](https://github.com/libgit2/libgit2sharp/pull/2052) + ## v0.27.2 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.27.1..0.27.2)) ### Changes From 7ac90abbe9426cba7e2ad634cf740cfddc52eba1 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 26 Nov 2023 21:09:16 -0500 Subject: [PATCH 331/384] Update LibGit2Sharp.NativeBinaries to 2.0.321 libgit2 v1.7.1 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index b80d75cd0..a12496899 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -33,7 +33,7 @@ - + From cd6936506ca7808c2fab7454fe5df95c99188d2d Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 26 Nov 2023 21:12:14 -0500 Subject: [PATCH 332/384] Update GitFetchOptions to include new Depth value --- LibGit2Sharp/Core/GitFetchOptions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LibGit2Sharp/Core/GitFetchOptions.cs b/LibGit2Sharp/Core/GitFetchOptions.cs index d82e2f219..26f4c8c7e 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 int Depth = 0; // GIT_FETCH_DEPTH_FULL public RemoteRedirectMode FollowRedirects = RemoteRedirectMode.Initial; public GitStrArrayManaged CustomHeaders; } From 143e83f9b4c88f3f535db4a827ac96f9e59182c6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 26 Nov 2023 21:14:34 -0500 Subject: [PATCH 333/384] Remove CentOS 7 from test matrix --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f44285812..5214b064f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,7 +62,7 @@ jobs: matrix: arch: [ amd64 ] # arch: [ amd64, arm64 ] - 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 ] + distro: [ alpine.3.13, alpine.3.14, alpine.3.15, alpine.3.16, alpine.3.17, centos.stream.8, debian.10, debian.11, fedora.36, ubuntu.18.04, ubuntu.20.04, ubuntu.22.04 ] sdk: [ '6.0', '7.0' ] exclude: - distro: alpine.3.13 From 42e98263699776009aeb70cf45673a60a4847dfa Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 26 Nov 2023 21:15:47 -0500 Subject: [PATCH 334/384] Update test to match new sort order --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index cd237663e..dd7aef1e1 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -100,7 +100,7 @@ public void SetExtensions() // 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", "objectformat", "partialclone", "newext" }, extensions); + Assert.Equal(new[] { "newext", "noop", "objectformat", "partialclone" }, extensions); } } } From e13df56af676eb4bf89dc864d20eabeeca4fe2c3 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Nov 2023 02:05:00 -0500 Subject: [PATCH 335/384] Update GitProxyOptions --- LibGit2Sharp/Core/GitProxyOptions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp/Core/GitProxyOptions.cs b/LibGit2Sharp/Core/GitProxyOptions.cs index b62b8e08f..85d4057ab 100644 --- a/LibGit2Sharp/Core/GitProxyOptions.cs +++ b/LibGit2Sharp/Core/GitProxyOptions.cs @@ -16,8 +16,8 @@ internal struct GitProxyOptions public uint Version; public GitProxyType Type; public IntPtr Url; - public IntPtr CredentialsCb; - public IntPtr CertificateCheck; - public IntPtr CbPayload; + public NativeMethods.git_cred_acquire_cb Credentials; + public NativeMethods.git_transport_certificate_check_cb CertificateCheck; + public IntPtr Payload; } } From 75b443221c9238711912e2471565648a3193cdf8 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Nov 2023 02:14:44 -0500 Subject: [PATCH 336/384] Add public proxy APIs --- LibGit2Sharp/FetchOptionsBase.cs | 2 ++ LibGit2Sharp/ProxyOptions.cs | 15 +++++++++++++++ LibGit2Sharp/ProxyType.cs | 9 +++++++++ 3 files changed, 26 insertions(+) create mode 100644 LibGit2Sharp/ProxyOptions.cs create mode 100644 LibGit2Sharp/ProxyType.cs diff --git a/LibGit2Sharp/FetchOptionsBase.cs b/LibGit2Sharp/FetchOptionsBase.cs index 751678cf9..652a06378 100644 --- a/LibGit2Sharp/FetchOptionsBase.cs +++ b/LibGit2Sharp/FetchOptionsBase.cs @@ -48,5 +48,7 @@ internal FetchOptionsBase() /// Completed operating on the current repository. /// public RepositoryOperationCompleted RepositoryOperationCompleted { get; set; } + + public ProxyOptions ProxyOptions { get; set; } } } diff --git a/LibGit2Sharp/ProxyOptions.cs b/LibGit2Sharp/ProxyOptions.cs new file mode 100644 index 000000000..fa3669d95 --- /dev/null +++ b/LibGit2Sharp/ProxyOptions.cs @@ -0,0 +1,15 @@ +using LibGit2Sharp.Handlers; + +namespace LibGit2Sharp +{ + public class ProxyOptions + { + public ProxyType ProxyType { get; set; } + + public string Url { get; set; } + + public CredentialsHandler CredentialsProvider { get; set; } + + public CertificateCheckHandler CertificateCheck { get; set; } + } +} diff --git a/LibGit2Sharp/ProxyType.cs b/LibGit2Sharp/ProxyType.cs new file mode 100644 index 000000000..e78606a72 --- /dev/null +++ b/LibGit2Sharp/ProxyType.cs @@ -0,0 +1,9 @@ +namespace LibGit2Sharp +{ + public enum ProxyType + { + None, + Auto, + Specified + } +} From db161ee8baad1a8969c1e6a150ab5618e84521c6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Nov 2023 19:16:49 -0500 Subject: [PATCH 337/384] No reason to derive from FetchOptionsBase and have FetchOptions property --- LibGit2Sharp.Tests/CloneFixture.cs | 90 +++++++++++++++++------------- LibGit2Sharp/CloneOptions.cs | 2 +- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 1b26c1226..c1ff7bc74 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -151,10 +151,14 @@ public void CallsProgressCallbacks(string url) Repository.Clone(url, scd.DirectoryPath, new CloneOptions() { - OnTransferProgress = _ => { transferWasCalled = true; return true; }, - OnProgress = progress => { progressWasCalled = true; return true; }, - OnUpdateTips = (name, oldId, newId) => { updateTipsWasCalled = true; return true; }, + FetchOptions = + { + OnTransferProgress = _ => { transferWasCalled = true; return true; }, + OnProgress = progress => { progressWasCalled = true; return true; }, + OnUpdateTips = (name, oldId, newId) => { updateTipsWasCalled = true; return true; } + }, OnCheckoutProgress = (a, b, c) => checkoutWasCalled = true + }); Assert.True(transferWasCalled); @@ -174,7 +178,7 @@ public void CanCloneWithCredentials() string clonedRepoPath = Repository.Clone(Constants.PrivateRepoUrl, scd.DirectoryPath, new CloneOptions() { - CredentialsProvider = Constants.PrivateRepoCredentials + FetchOptions = { CredentialsProvider = Constants.PrivateRepoCredentials } }); @@ -249,43 +253,46 @@ public void CanInspectCertificateOnClone(string url, string hostname, Type certT var options = new CloneOptions { - CertificateCheck = (cert, valid, host) => + FetchOptions = { - wasCalled = true; - - Assert.Equal(hostname, host); - Assert.Equal(certType, cert.GetType()); - - if (certType == typeof(CertificateX509)) + CertificateCheck = (cert, valid, host) => { - 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; - } + 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; + } - 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(() => @@ -432,9 +439,12 @@ public void CanRecursivelyCloneSubmodules() { RecurseSubmodules = true, OnCheckoutProgress = checkoutProgressHandler, - OnUpdateTips = remoteRefUpdated, - RepositoryOperationStarting = repositoryOperationStarting, - RepositoryOperationCompleted = repositoryOperationCompleted, + FetchOptions = + { + OnUpdateTips = remoteRefUpdated, + RepositoryOperationStarting = repositoryOperationStarting, + RepositoryOperationCompleted = repositoryOperationCompleted + } }; string clonedRepoPath = Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options); @@ -517,7 +527,7 @@ public void CanCancelRecursiveClone() CloneOptions options = new CloneOptions() { RecurseSubmodules = true, - RepositoryOperationStarting = repositoryOperationStarting, + FetchOptions = { RepositoryOperationStarting = repositoryOperationStarting } }; Assert.Throws(() => diff --git a/LibGit2Sharp/CloneOptions.cs b/LibGit2Sharp/CloneOptions.cs index f88ff58d7..05430085e 100644 --- a/LibGit2Sharp/CloneOptions.cs +++ b/LibGit2Sharp/CloneOptions.cs @@ -6,7 +6,7 @@ namespace LibGit2Sharp /// /// Options to define clone behaviour /// - public sealed class CloneOptions : FetchOptionsBase, IConvertableToGitCheckoutOpts + public sealed class CloneOptions : IConvertableToGitCheckoutOpts { /// /// Creates default for a non-bare clone From 4de7c4f12bbc86b333a54f572fe2f2e8f116fce0 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Nov 2023 19:18:23 -0500 Subject: [PATCH 338/384] Wire up proxy options --- LibGit2Sharp/Commands/Fetch.cs | 3 +- LibGit2Sharp/Core/GitFetchOptionsWrapper.cs | 9 +- LibGit2Sharp/Core/GitProxyOptionsWrapper.cs | 32 +++++++ LibGit2Sharp/Core/GitPushOptionsWrapper.cs | 1 + LibGit2Sharp/FetchOptionsBase.cs | 2 +- LibGit2Sharp/LibGit2Sharp.csproj | 1 + LibGit2Sharp/Network.cs | 67 +++++++++++---- LibGit2Sharp/ProxyOptions.cs | 92 ++++++++++++++++++++- LibGit2Sharp/PushOptions.cs | 2 + LibGit2Sharp/Repository.cs | 63 ++++++++------ LibGit2Sharp/SubmoduleCollection.cs | 2 +- 11 files changed, 222 insertions(+), 52 deletions(-) create mode 100644 LibGit2Sharp/Core/GitProxyOptionsWrapper.cs diff --git a/LibGit2Sharp/Commands/Fetch.cs b/LibGit2Sharp/Commands/Fetch.cs index d61fca5a5..e531aac51 100644 --- a/LibGit2Sharp/Commands/Fetch.cs +++ b/LibGit2Sharp/Commands/Fetch.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using LibGit2Sharp; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; @@ -75,7 +74,7 @@ public static void Fetch(Repository repository, string remote, IEnumerable - /// Git fetch options wrapper. Disposable wrapper for GitFetchOptions + /// + /// Git fetch options wrapper. Disposable wrapper for GitFetchOptions /// internal class GitFetchOptionsWrapper : IDisposable { @@ -11,7 +11,7 @@ public GitFetchOptionsWrapper() : this(new GitFetchOptions()) { } public GitFetchOptionsWrapper(GitFetchOptions fetchOptions) { - this.Options = fetchOptions; + Options = fetchOptions; } public GitFetchOptions Options { get; private set; } @@ -23,7 +23,8 @@ protected virtual void Dispose(bool disposing) if (disposedValue) return; - this.Options.CustomHeaders.Dispose(); + Options.CustomHeaders.Dispose(); + EncodingMarshaler.Cleanup(Options.ProxyOptions.Url); disposedValue = true; } diff --git a/LibGit2Sharp/Core/GitProxyOptionsWrapper.cs b/LibGit2Sharp/Core/GitProxyOptionsWrapper.cs new file mode 100644 index 000000000..053213e96 --- /dev/null +++ b/LibGit2Sharp/Core/GitProxyOptionsWrapper.cs @@ -0,0 +1,32 @@ +using System; + +namespace LibGit2Sharp.Core +{ + internal class GitProxyOptionsWrapper : IDisposable + { + public GitProxyOptionsWrapper() : this(new GitProxyOptions()) { } + + public GitProxyOptionsWrapper(GitProxyOptions fetchOptions) + { + Options = fetchOptions; + } + + public GitProxyOptions Options { get; private set; } + + private bool disposedValue = false; + + protected virtual void Dispose(bool disposing) + { + if (disposedValue) + return; + + EncodingMarshaler.Cleanup(Options.Url); + disposedValue = true; + } + + public void Dispose() + { + Dispose(true); + } + } +} diff --git a/LibGit2Sharp/Core/GitPushOptionsWrapper.cs b/LibGit2Sharp/Core/GitPushOptionsWrapper.cs index ffac5a220..3ccffcf06 100644 --- a/LibGit2Sharp/Core/GitPushOptionsWrapper.cs +++ b/LibGit2Sharp/Core/GitPushOptionsWrapper.cs @@ -24,6 +24,7 @@ protected virtual void Dispose(bool disposing) return; this.Options.CustomHeaders.Dispose(); + EncodingMarshaler.Cleanup(Options.ProxyOptions.Url); disposedValue = true; } diff --git a/LibGit2Sharp/FetchOptionsBase.cs b/LibGit2Sharp/FetchOptionsBase.cs index 652a06378..57de331d1 100644 --- a/LibGit2Sharp/FetchOptionsBase.cs +++ b/LibGit2Sharp/FetchOptionsBase.cs @@ -49,6 +49,6 @@ internal FetchOptionsBase() /// public RepositoryOperationCompleted RepositoryOperationCompleted { get; set; } - public ProxyOptions ProxyOptions { get; set; } + public ProxyOptions ProxyOptions { get; set; } = new(); } } diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index a12496899..4d0876c4d 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -2,6 +2,7 @@ net472;net6.0 + 10.0 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET LibGit2Sharp contributors diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs index 825f3c886..19070a344 100644 --- a/LibGit2Sharp/Network.cs +++ b/LibGit2Sharp/Network.cs @@ -52,7 +52,14 @@ public virtual IEnumerable ListReferences(Remote remote) { Ensure.ArgumentNotNull(remote, "remote"); - return ListReferencesInternal(remote.Url, null); + return ListReferencesInternal(remote.Url, null, new ProxyOptions()); + } + + public virtual IEnumerable ListReferences(Remote remote, ProxyOptions proxyOptions) + { + Ensure.ArgumentNotNull(remote, "remote"); + + return ListReferencesInternal(remote.Url, null, proxyOptions); } /// @@ -72,7 +79,15 @@ public virtual IEnumerable ListReferences(Remote remote, CredentialsH Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); - return ListReferencesInternal(remote.Url, credentialsProvider); + return ListReferencesInternal(remote.Url, credentialsProvider, new ProxyOptions()); + } + + public virtual IEnumerable ListReferences(Remote remote, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) + { + Ensure.ArgumentNotNull(remote, "remote"); + Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); + + return ListReferencesInternal(remote.Url, credentialsProvider, proxyOptions); } /// @@ -90,7 +105,14 @@ public virtual IEnumerable ListReferences(string url) { Ensure.ArgumentNotNull(url, "url"); - return ListReferencesInternal(url, null); + return ListReferencesInternal(url, null, new ProxyOptions()); + } + + public virtual IEnumerable ListReferences(string url, ProxyOptions proxyOptions) + { + Ensure.ArgumentNotNull(url, "url"); + + return ListReferencesInternal(url, null, proxyOptions); } /// @@ -110,25 +132,36 @@ public virtual IEnumerable ListReferences(string url, CredentialsHand Ensure.ArgumentNotNull(url, "url"); Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); - return ListReferencesInternal(url, credentialsProvider); + return ListReferencesInternal(url, credentialsProvider, new ProxyOptions()); } - private IEnumerable ListReferencesInternal(string url, CredentialsHandler credentialsProvider) + public virtual IEnumerable ListReferences(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { - using (RemoteHandle remoteHandle = BuildRemoteHandle(repository.Handle, url)) - { - GitRemoteCallbacks gitCallbacks = new GitRemoteCallbacks { version = 1 }; - GitProxyOptions proxyOptions = new GitProxyOptions { Version = 1 }; + Ensure.ArgumentNotNull(url, "url"); + Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); - if (credentialsProvider != null) - { - var callbacks = new RemoteCallbacks(credentialsProvider); - gitCallbacks = callbacks.GenerateCallbacks(); - } + return ListReferencesInternal(url, credentialsProvider, new ProxyOptions()); + } - Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref proxyOptions); - return Proxy.git_remote_ls(repository, remoteHandle); + private IEnumerable ListReferencesInternal(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) + { + proxyOptions ??= new(); + + using RemoteHandle remoteHandle = BuildRemoteHandle(repository.Handle, url); + using var proxyOptionsWrapper = new GitProxyOptionsWrapper(proxyOptions.CreateGitProxyOptions()); + + GitRemoteCallbacks gitCallbacks = new GitRemoteCallbacks { version = 1 }; + + if (credentialsProvider != null) + { + var callbacks = new RemoteCallbacks(credentialsProvider); + gitCallbacks = callbacks.GenerateCallbacks(); } + + var gitProxyOptions = proxyOptionsWrapper.Options; + + Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref gitProxyOptions); + return Proxy.git_remote_ls(repository, remoteHandle); } static RemoteHandle BuildRemoteHandle(RepositoryHandle repoHandle, string url) @@ -375,7 +408,7 @@ public virtual void Push(Remote remote, IEnumerable pushRefSpecs, PushOp var gitPushOptions = pushOptionsWrapper.Options; gitPushOptions.PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism; gitPushOptions.RemoteCallbacks = gitCallbacks; - gitPushOptions.ProxyOptions = new GitProxyOptions { Version = 1 }; + gitPushOptions.ProxyOptions = pushOptions.ProxyOptions.CreateGitProxyOptions(); // If there are custom headers, create a managed string array. if (pushOptions.CustomHeaders != null && pushOptions.CustomHeaders.Length > 0) diff --git a/LibGit2Sharp/ProxyOptions.cs b/LibGit2Sharp/ProxyOptions.cs index fa3669d95..02b75bdd8 100644 --- a/LibGit2Sharp/ProxyOptions.cs +++ b/LibGit2Sharp/ProxyOptions.cs @@ -1,15 +1,103 @@ -using LibGit2Sharp.Handlers; +using System; +using LibGit2Sharp.Core; +using LibGit2Sharp.Handlers; namespace LibGit2Sharp { public class ProxyOptions { - public ProxyType ProxyType { get; set; } + public ProxyType ProxyType { get; set; } = ProxyType.Auto; public string Url { get; set; } public CredentialsHandler CredentialsProvider { get; set; } public CertificateCheckHandler CertificateCheck { get; set; } + + internal unsafe GitProxyOptions CreateGitProxyOptions() + { + var gitProxyOptions = new GitProxyOptions + { + Version = 1, + Type = (GitProxyType)ProxyType + }; + + if (Url is not null) + { + gitProxyOptions.Url = StrictUtf8Marshaler.FromManaged(Url); + } + + if (CredentialsProvider is not null) + { + gitProxyOptions.Credentials = GitCredentialHandler; + } + + if (CertificateCheck is not null) + { + gitProxyOptions.CertificateCheck = GitCertificateCheck; + } + + return gitProxyOptions; + } + + private int GitCredentialHandler(out IntPtr ptr, IntPtr cUrl, IntPtr usernameFromUrl, GitCredentialType credTypes, IntPtr payload) + { + string url = LaxUtf8Marshaler.FromNative(cUrl); + string username = LaxUtf8Marshaler.FromNative(usernameFromUrl); + + SupportedCredentialTypes types = default(SupportedCredentialTypes); + if (credTypes.HasFlag(GitCredentialType.UserPassPlaintext)) + { + types |= SupportedCredentialTypes.UsernamePassword; + } + if (credTypes.HasFlag(GitCredentialType.Default)) + { + types |= SupportedCredentialTypes.Default; + } + + ptr = IntPtr.Zero; + try + { + var cred = CredentialsProvider(url, username, types); + if (cred == null) + { + return (int)GitErrorCode.PassThrough; + } + return cred.GitCredentialHandler(out ptr); + } + catch (Exception exception) + { + Proxy.git_error_set_str(GitErrorCategory.Callback, exception); + return (int)GitErrorCode.Error; + } + } + + private unsafe int GitCertificateCheck(git_certificate* certPtr, int valid, IntPtr cHostname, IntPtr payload) + { + string hostname = LaxUtf8Marshaler.FromNative(cHostname); + Certificate cert = null; + + switch (certPtr->type) + { + case GitCertificateType.X509: + cert = new CertificateX509((git_certificate_x509*)certPtr); + break; + case GitCertificateType.Hostkey: + cert = new CertificateSsh((git_certificate_ssh*)certPtr); + break; + } + + bool result = false; + try + { + result = CertificateCheck(cert, valid != 0, hostname); + } + catch (Exception exception) + { + Proxy.git_error_set_str(GitErrorCategory.Callback, exception); + } + + return Proxy.ConvertResultToCancelFlag(result); + } } } diff --git a/LibGit2Sharp/PushOptions.cs b/LibGit2Sharp/PushOptions.cs index f7d37eba9..501e8d8d2 100644 --- a/LibGit2Sharp/PushOptions.cs +++ b/LibGit2Sharp/PushOptions.cs @@ -71,5 +71,7 @@ public sealed class PushOptions /// /// The custom headers string array public string[] CustomHeaders { get; set; } + + public ProxyOptions ProxyOptions { get; set; } = new(); } } diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 41aaecfbf..d7c759e8b 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -656,7 +656,12 @@ internal Commit LookupCommit(string committish) /// The references in the remote repository. public static IEnumerable ListRemoteReferences(string url) { - return ListRemoteReferences(url, null); + return ListRemoteReferences(url, null, new ProxyOptions()); + } + + public static IEnumerable ListRemoteReferences(string url, ProxyOptions proxyOptions) + { + return ListRemoteReferences(url, null, proxyOptions); } /// @@ -671,24 +676,32 @@ public static IEnumerable ListRemoteReferences(string url) /// The used to connect to remote repository. /// The references in the remote repository. public static IEnumerable ListRemoteReferences(string url, CredentialsHandler credentialsProvider) + { + return ListRemoteReferences(url, credentialsProvider, new ProxyOptions()); + } + + public static IEnumerable ListRemoteReferences(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(url, "url"); - using (RepositoryHandle repositoryHandle = Proxy.git_repository_new()) - using (RemoteHandle remoteHandle = Proxy.git_remote_create_anonymous(repositoryHandle, url)) - { - var gitCallbacks = new GitRemoteCallbacks { version = 1 }; - var proxyOptions = new GitProxyOptions { Version = 1 }; + proxyOptions ??= new(); - if (credentialsProvider != null) - { - var callbacks = new RemoteCallbacks(credentialsProvider); - gitCallbacks = callbacks.GenerateCallbacks(); - } + using RepositoryHandle repositoryHandle = Proxy.git_repository_new(); + using RemoteHandle remoteHandle = Proxy.git_remote_create_anonymous(repositoryHandle, url); + using var proxyOptionsWrapper = new GitProxyOptionsWrapper(proxyOptions.CreateGitProxyOptions()); + + var gitCallbacks = new GitRemoteCallbacks { version = 1 }; - Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref proxyOptions); - return Proxy.git_remote_ls(null, remoteHandle); + if (credentialsProvider != null) + { + var callbacks = new RemoteCallbacks(credentialsProvider); + gitCallbacks = callbacks.GenerateCallbacks(); } + + var gitProxyOptions = proxyOptionsWrapper.Options; + + Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref gitProxyOptions); + return Proxy.git_remote_ls(null, remoteHandle); } /// @@ -754,7 +767,7 @@ public static string Clone(string sourceUrl, string workdirPath, var context = new RepositoryOperationContext(Path.GetFullPath(workdirPath), sourceUrl); // Notify caller that we are starting to work with the current repository. - bool continueOperation = OnRepositoryOperationStarting(options.RepositoryOperationStarting, + bool continueOperation = OnRepositoryOperationStarting(options.FetchOptions.RepositoryOperationStarting, context); if (!continueOperation) @@ -768,8 +781,8 @@ public static string Clone(string sourceUrl, string workdirPath, var gitCheckoutOptions = checkoutOptionsWrapper.Options; var gitFetchOptions = fetchOptionsWrapper.Options; - gitFetchOptions.ProxyOptions = new GitProxyOptions { Version = 1 }; - gitFetchOptions.RemoteCallbacks = new RemoteCallbacks(options).GenerateCallbacks(); + gitFetchOptions.ProxyOptions = options.FetchOptions.ProxyOptions.CreateGitProxyOptions(); + gitFetchOptions.RemoteCallbacks = new RemoteCallbacks(options.FetchOptions).GenerateCallbacks(); if (options.FetchOptions != null && options.FetchOptions.CustomHeaders != null) { gitFetchOptions.CustomHeaders = @@ -801,7 +814,7 @@ public static string Clone(string sourceUrl, string workdirPath, } // Notify caller that we are done with the current repository. - OnRepositoryOperationCompleted(options.RepositoryOperationCompleted, + OnRepositoryOperationCompleted(options.FetchOptions.RepositoryOperationCompleted, context); // Recursively clone submodules if requested. @@ -837,11 +850,11 @@ private static void RecursivelyCloneSubmodules(CloneOptions options, string repo SubmoduleUpdateOptions updateOptions = new SubmoduleUpdateOptions() { Init = true, - CredentialsProvider = options.CredentialsProvider, + CredentialsProvider = options.FetchOptions.CredentialsProvider, OnCheckoutProgress = options.OnCheckoutProgress, - OnProgress = options.OnProgress, - OnTransferProgress = options.OnTransferProgress, - OnUpdateTips = options.OnUpdateTips, + OnProgress = options.FetchOptions.OnProgress, + OnTransferProgress = options.FetchOptions.OnTransferProgress, + OnUpdateTips = options.FetchOptions.OnUpdateTips, }; string parentRepoWorkDir = repo.Info.WorkingDirectory; @@ -862,7 +875,7 @@ private static void RecursivelyCloneSubmodules(CloneOptions options, string repo sm.Name, recursionDepth); - bool continueOperation = OnRepositoryOperationStarting(options.RepositoryOperationStarting, + bool continueOperation = OnRepositoryOperationStarting(options.FetchOptions.RepositoryOperationStarting, context); if (!continueOperation) @@ -872,7 +885,7 @@ private static void RecursivelyCloneSubmodules(CloneOptions options, string repo repo.Submodules.Update(sm.Name, updateOptions); - OnRepositoryOperationCompleted(options.RepositoryOperationCompleted, + OnRepositoryOperationCompleted(options.FetchOptions.RepositoryOperationCompleted, context); submodules.Add(Path.Combine(repo.Info.WorkingDirectory, sm.Path)); @@ -1050,7 +1063,7 @@ public Commit Commit(string message, Signature author, Signature committer, Comm if (treesame && !amendMergeCommit) { - throw (options.AmendPreviousCommit ? + throw (options.AmendPreviousCommit ? new EmptyCommitException("Amending this commit would produce a commit that is identical to its parent (id = {0})", parents[0].Id) : new EmptyCommitException("No changes; nothing to commit.")); } @@ -1241,7 +1254,7 @@ public MergeResult MergeFetchedRefs(Signature merger, MergeOptions options) if (fetchHeads.Length == 0) { var expectedRef = this.Head.UpstreamBranchCanonicalName; - throw new MergeFetchHeadNotFoundException("The current branch is configured to merge with the reference '{0}' from the remote, but this reference was not fetched.", + throw new MergeFetchHeadNotFoundException("The current branch is configured to merge with the reference '{0}' from the remote, but this reference was not fetched.", expectedRef); } diff --git a/LibGit2Sharp/SubmoduleCollection.cs b/LibGit2Sharp/SubmoduleCollection.cs index fc508107a..c4cc1c020 100644 --- a/LibGit2Sharp/SubmoduleCollection.cs +++ b/LibGit2Sharp/SubmoduleCollection.cs @@ -104,7 +104,7 @@ public virtual void Update(string name, SubmoduleUpdateOptions options) { Version = 1, CheckoutOptions = gitCheckoutOptions, - FetchOptions = new GitFetchOptions { ProxyOptions = new GitProxyOptions { Version = 1 }, RemoteCallbacks = gitRemoteCallbacks }, + FetchOptions = new GitFetchOptions { ProxyOptions = options.ProxyOptions.CreateGitProxyOptions(), RemoteCallbacks = gitRemoteCallbacks }, CloneCheckoutStrategy = CheckoutStrategy.GIT_CHECKOUT_SAFE }; From 4ab3b4604d8eab831d60ef427675ff0b82d26664 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Nov 2023 19:44:54 -0500 Subject: [PATCH 339/384] Ensure FetchOptions property is non-null --- LibGit2Sharp/CloneOptions.cs | 2 +- LibGit2Sharp/Repository.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/CloneOptions.cs b/LibGit2Sharp/CloneOptions.cs index 05430085e..620896e94 100644 --- a/LibGit2Sharp/CloneOptions.cs +++ b/LibGit2Sharp/CloneOptions.cs @@ -46,7 +46,7 @@ public CloneOptions() /// /// Gets or sets the fetch options. /// - public FetchOptions FetchOptions { get; set; } + public FetchOptions FetchOptions { get; set; } = new(); #region IConvertableToGitCheckoutOpts diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index d7c759e8b..3791dfbd1 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -760,7 +760,7 @@ public static string Clone(string sourceUrl, string workdirPath, Ensure.ArgumentNotNull(sourceUrl, "sourceUrl"); Ensure.ArgumentNotNull(workdirPath, "workdirPath"); - options = options ?? new CloneOptions(); + options ??= new CloneOptions(); // context variable that contains information on the repository that // we are cloning. From 7bf2e3b803b3a3b477e4c4afa978e589ef7e2bce Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Nov 2023 19:47:48 -0500 Subject: [PATCH 340/384] Make ProxyOptions sealed to satisfy test --- LibGit2Sharp/ProxyOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/ProxyOptions.cs b/LibGit2Sharp/ProxyOptions.cs index 02b75bdd8..932dc40ef 100644 --- a/LibGit2Sharp/ProxyOptions.cs +++ b/LibGit2Sharp/ProxyOptions.cs @@ -4,7 +4,7 @@ namespace LibGit2Sharp { - public class ProxyOptions + public sealed class ProxyOptions { public ProxyType ProxyType { get; set; } = ProxyType.Auto; From 747bfc62fff758c309b581655d200983e7c066f3 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Nov 2023 22:34:42 -0500 Subject: [PATCH 341/384] Remove property setters since options are initialized --- LibGit2Sharp.Tests/CloneFixture.cs | 18 ++++++------------ LibGit2Sharp/CloneOptions.cs | 2 +- LibGit2Sharp/FetchOptionsBase.cs | 2 +- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index c1ff7bc74..b4de8797a 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -567,10 +567,8 @@ public void CannotCloneWithForbiddenCustomHeaders() const string url = "https://github.com/libgit2/TestGitRepository"; const string knownHeader = "User-Agent: mygit-201"; - var cloneOptions = new CloneOptions() - { - FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } - }; + var cloneOptions = new CloneOptions(); + cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader }; Assert.Throws(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions)); } @@ -583,10 +581,8 @@ public void CannotCloneWithMalformedCustomHeaders() const string url = "https://github.com/libgit2/TestGitRepository"; const string knownHeader = "hello world"; - var cloneOptions = new CloneOptions() - { - FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } - }; + var cloneOptions = new CloneOptions(); + cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader }; Assert.Throws(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions)); } @@ -599,10 +595,8 @@ public void CanCloneWithCustomHeaders() const string url = "https://github.com/libgit2/TestGitRepository"; const string knownHeader = "X-Hello: world"; - var cloneOptions = new CloneOptions() - { - FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } - }; + var cloneOptions = new CloneOptions(); + cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader }; var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, cloneOptions); Assert.True(Directory.Exists(clonedRepoPath)); diff --git a/LibGit2Sharp/CloneOptions.cs b/LibGit2Sharp/CloneOptions.cs index 620896e94..a315d76fc 100644 --- a/LibGit2Sharp/CloneOptions.cs +++ b/LibGit2Sharp/CloneOptions.cs @@ -46,7 +46,7 @@ public CloneOptions() /// /// Gets or sets the fetch options. /// - public FetchOptions FetchOptions { get; set; } = new(); + public FetchOptions FetchOptions { get; } = new(); #region IConvertableToGitCheckoutOpts diff --git a/LibGit2Sharp/FetchOptionsBase.cs b/LibGit2Sharp/FetchOptionsBase.cs index 57de331d1..dffd34412 100644 --- a/LibGit2Sharp/FetchOptionsBase.cs +++ b/LibGit2Sharp/FetchOptionsBase.cs @@ -49,6 +49,6 @@ internal FetchOptionsBase() /// public RepositoryOperationCompleted RepositoryOperationCompleted { get; set; } - public ProxyOptions ProxyOptions { get; set; } = new(); + public ProxyOptions ProxyOptions { get; } = new(); } } From c6ef24d85b31a2121d25559f16424feb5a85a3fa Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 25 Nov 2023 23:06:02 -0500 Subject: [PATCH 342/384] Add XML comments --- LibGit2Sharp/FetchOptions.cs | 8 ++--- LibGit2Sharp/FetchOptionsBase.cs | 5 +++- LibGit2Sharp/Network.cs | 50 ++++++++++++++++++++++++++++++++ LibGit2Sharp/ProxyOptions.cs | 16 ++++++++++ LibGit2Sharp/ProxyType.cs | 14 +++++++++ LibGit2Sharp/PushOptions.cs | 3 ++ LibGit2Sharp/Repository.cs | 18 ++++++++++++ 7 files changed, 109 insertions(+), 5 deletions(-) diff --git a/LibGit2Sharp/FetchOptions.cs b/LibGit2Sharp/FetchOptions.cs index 487baed97..5bcf74bfa 100644 --- a/LibGit2Sharp/FetchOptions.cs +++ b/LibGit2Sharp/FetchOptions.cs @@ -28,14 +28,14 @@ public sealed class FetchOptions : FetchOptionsBase /// /// Get/Set the custom headers. - /// - /// - /// This allows you to set custom headers (e.g. X-Forwarded-For, + /// + /// + /// This allows you to set custom headers (e.g. X-Forwarded-For, /// X-Request-Id, etc), /// /// /// - /// Libgit2 sets some headers for HTTP requests (User-Agent, Host, + /// Libgit2 sets some headers for HTTP requests (User-Agent, Host, /// Accept, Content-Type, Transfer-Encoding, Content-Length, Accept) that /// cannot be overriden. /// diff --git a/LibGit2Sharp/FetchOptionsBase.cs b/LibGit2Sharp/FetchOptionsBase.cs index dffd34412..0e548652f 100644 --- a/LibGit2Sharp/FetchOptionsBase.cs +++ b/LibGit2Sharp/FetchOptionsBase.cs @@ -35,7 +35,7 @@ internal FetchOptionsBase() /// /// 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. + /// the connection to proceed based on the certificate presented by the server. /// public CertificateCheckHandler CertificateCheck { get; set; } @@ -49,6 +49,9 @@ internal FetchOptionsBase() /// public RepositoryOperationCompleted RepositoryOperationCompleted { get; set; } + /// + /// Options for connecting through a proxy. + /// public ProxyOptions ProxyOptions { get; } = new(); } } diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs index 19070a344..bd80834bb 100644 --- a/LibGit2Sharp/Network.cs +++ b/LibGit2Sharp/Network.cs @@ -55,6 +55,18 @@ public virtual IEnumerable ListReferences(Remote remote) return ListReferencesInternal(remote.Url, null, new ProxyOptions()); } + /// + /// List references in a repository. + /// + /// When the remote tips are ahead of the local ones, the retrieved + /// s may point to non existing + /// s in the local repository. In that + /// case, will return null. + /// + /// + /// The to list from. + /// Options for connecting through a proxy. + /// The references in the repository. public virtual IEnumerable ListReferences(Remote remote, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(remote, "remote"); @@ -82,6 +94,19 @@ public virtual IEnumerable ListReferences(Remote remote, CredentialsH return ListReferencesInternal(remote.Url, credentialsProvider, new ProxyOptions()); } + /// + /// List references in a repository. + /// + /// When the remote tips are ahead of the local ones, the retrieved + /// s may point to non existing + /// s in the local repository. In that + /// case, will return null. + /// + /// + /// The to list from. + /// The used to connect to remote repository. + /// Options for connecting through a proxy. + /// The references in the repository. public virtual IEnumerable ListReferences(Remote remote, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(remote, "remote"); @@ -108,6 +133,18 @@ public virtual IEnumerable ListReferences(string url) return ListReferencesInternal(url, null, new ProxyOptions()); } + /// + /// List references in a remote repository. + /// + /// When the remote tips are ahead of the local ones, the retrieved + /// s may point to non existing + /// s in the local repository. In that + /// case, will return null. + /// + /// + /// The url to list from. + /// Options for connecting through a proxy. + /// The references in the remote repository. public virtual IEnumerable ListReferences(string url, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(url, "url"); @@ -135,6 +172,19 @@ public virtual IEnumerable ListReferences(string url, CredentialsHand return ListReferencesInternal(url, credentialsProvider, new ProxyOptions()); } + /// + /// List references in a remote repository. + /// + /// When the remote tips are ahead of the local ones, the retrieved + /// s may point to non existing + /// s in the local repository. In that + /// case, will return null. + /// + /// + /// The url to list from. + /// The used to connect to remote repository. + /// Options for connecting through a proxy. + /// The references in the remote repository. public virtual IEnumerable ListReferences(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(url, "url"); diff --git a/LibGit2Sharp/ProxyOptions.cs b/LibGit2Sharp/ProxyOptions.cs index 932dc40ef..076c4e357 100644 --- a/LibGit2Sharp/ProxyOptions.cs +++ b/LibGit2Sharp/ProxyOptions.cs @@ -4,14 +4,30 @@ namespace LibGit2Sharp { + /// + /// Options for connecting through a proxy. + /// public sealed class ProxyOptions { + /// + /// The type of proxy to use. Set to Auto by default. + /// public ProxyType ProxyType { get; set; } = ProxyType.Auto; + /// + /// The URL of the proxy when is set to Specified. + /// public string Url { get; set; } + /// + /// Handler to generate for authentication. + /// public CredentialsHandler CredentialsProvider { get; set; } + /// + /// This handler will be called to let the user make a decision on whether to allow + /// the connection to proceed based on the certificate presented by the server. + /// public CertificateCheckHandler CertificateCheck { get; set; } internal unsafe GitProxyOptions CreateGitProxyOptions() diff --git a/LibGit2Sharp/ProxyType.cs b/LibGit2Sharp/ProxyType.cs index e78606a72..13ec705ee 100644 --- a/LibGit2Sharp/ProxyType.cs +++ b/LibGit2Sharp/ProxyType.cs @@ -1,9 +1,23 @@ namespace LibGit2Sharp { + /// + /// The type of proxy to use. + /// public enum ProxyType { + /// + /// Do not attempt to connect through a proxy. + /// None, + + /// + /// Try to auto-detect the proxy from the git configuration. + /// Auto, + + /// + /// Connect via the URL given in the options. + /// Specified } } diff --git a/LibGit2Sharp/PushOptions.cs b/LibGit2Sharp/PushOptions.cs index 501e8d8d2..829eb0d60 100644 --- a/LibGit2Sharp/PushOptions.cs +++ b/LibGit2Sharp/PushOptions.cs @@ -72,6 +72,9 @@ public sealed class PushOptions /// The custom headers string array public string[] CustomHeaders { get; set; } + /// + /// Options for connecting through a proxy. + /// public ProxyOptions ProxyOptions { get; set; } = new(); } } diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 3791dfbd1..a4f2e3077 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -659,6 +659,12 @@ public static IEnumerable ListRemoteReferences(string url) return ListRemoteReferences(url, null, new ProxyOptions()); } + /// + /// Lists the Remote Repository References. + /// + /// The url to list from. + /// Options for connecting through a proxy. + /// The references in the remote repository. public static IEnumerable ListRemoteReferences(string url, ProxyOptions proxyOptions) { return ListRemoteReferences(url, null, proxyOptions); @@ -680,6 +686,18 @@ public static IEnumerable ListRemoteReferences(string url, Credential return ListRemoteReferences(url, credentialsProvider, new ProxyOptions()); } + /// + /// Lists the Remote Repository References. + /// + /// + /// Does not require a local Repository. The retrieved + /// + /// throws in this case. + /// + /// The url to list from. + /// The used to connect to remote repository. + /// Options for connecting through a proxy. + /// The references in the remote repository. public static IEnumerable ListRemoteReferences(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(url, "url"); From 01a6ccb3549e6713261638c4e8fe29da732b97a5 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 26 Nov 2023 00:28:16 -0500 Subject: [PATCH 343/384] Update how submodule fetch options are handled --- LibGit2Sharp.Tests/SubmoduleFixture.cs | 4 +- LibGit2Sharp/Core/GitSubmoduleOptions.cs | 2 - LibGit2Sharp/Repository.cs | 7 +--- LibGit2Sharp/SubmoduleCollection.cs | 48 ++++++++++++------------ LibGit2Sharp/SubmoduleUpdateOptions.cs | 7 +++- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/LibGit2Sharp.Tests/SubmoduleFixture.cs b/LibGit2Sharp.Tests/SubmoduleFixture.cs index 735bfd938..2d7f04e6d 100644 --- a/LibGit2Sharp.Tests/SubmoduleFixture.cs +++ b/LibGit2Sharp.Tests/SubmoduleFixture.cs @@ -3,7 +3,6 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -240,9 +239,10 @@ public void CanUpdateSubmodule() OnCheckoutProgress = (x, y, z) => checkoutProgressCalled = true, OnCheckoutNotify = (x, y) => { checkoutNotifyCalled = true; return true; }, CheckoutNotifyFlags = CheckoutNotifyFlags.Updated, - OnUpdateTips = (x, y, z) => { updateTipsCalled = true; return true; }, }; + options.FetchOptions.OnUpdateTips = (x, y, z) => { updateTipsCalled = true; return true; }; + repo.Submodules.Init(submodule.Name, false); repo.Submodules.Update(submodule.Name, options); diff --git a/LibGit2Sharp/Core/GitSubmoduleOptions.cs b/LibGit2Sharp/Core/GitSubmoduleOptions.cs index 59c2b3f80..09a8e8265 100644 --- a/LibGit2Sharp/Core/GitSubmoduleOptions.cs +++ b/LibGit2Sharp/Core/GitSubmoduleOptions.cs @@ -11,8 +11,6 @@ internal struct GitSubmoduleUpdateOptions public GitFetchOptions FetchOptions; - public CheckoutStrategy CloneCheckoutStrategy; - public int AllowFetch; } } diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index a4f2e3077..73f560c3c 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -865,14 +865,11 @@ private static void RecursivelyCloneSubmodules(CloneOptions options, string repo using (Repository repo = new Repository(repoPath)) { - SubmoduleUpdateOptions updateOptions = new SubmoduleUpdateOptions() + var updateOptions = new SubmoduleUpdateOptions() { Init = true, - CredentialsProvider = options.FetchOptions.CredentialsProvider, OnCheckoutProgress = options.OnCheckoutProgress, - OnProgress = options.FetchOptions.OnProgress, - OnTransferProgress = options.FetchOptions.OnTransferProgress, - OnUpdateTips = options.FetchOptions.OnUpdateTips, + FetchOptions = options.FetchOptions }; string parentRepoWorkDir = repo.Info.WorkingDirectory; diff --git a/LibGit2Sharp/SubmoduleCollection.cs b/LibGit2Sharp/SubmoduleCollection.cs index c4cc1c020..061196c7d 100644 --- a/LibGit2Sharp/SubmoduleCollection.cs +++ b/LibGit2Sharp/SubmoduleCollection.cs @@ -74,43 +74,41 @@ public virtual void Init(string name, bool overwrite) /// Update specified submodule. /// /// This will: - /// 1) Optionally initialize the if it not already initialzed, + /// 1) Optionally initialize the if it not already initialized, /// 2) clone the sub repository if it has not already been cloned, and /// 3) checkout the commit ID for the submodule in the sub repository. /// /// /// The name of the submodule to update. - /// Options controlling submodule udpate behavior and callbacks. + /// Options controlling submodule update behavior and callbacks. public virtual void Update(string name, SubmoduleUpdateOptions options) { - options = options ?? new SubmoduleUpdateOptions(); + options ??= new SubmoduleUpdateOptions(); - using (var handle = Proxy.git_submodule_lookup(repo.Handle, name)) - { - if (handle == null) - { - throw new NotFoundException("Submodule lookup failed for '{0}'.", - name); - } + using var handle = Proxy.git_submodule_lookup(repo.Handle, name) ?? throw new NotFoundException("Submodule lookup failed for '{0}'.", name); + using var checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options); + using var fetchOptionsWrapper = new GitFetchOptionsWrapper(); - using (GitCheckoutOptsWrapper checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) - { - var gitCheckoutOptions = checkoutOptionsWrapper.Options; + var gitCheckoutOptions = checkoutOptionsWrapper.Options; - var remoteCallbacks = new RemoteCallbacks(options); - var gitRemoteCallbacks = remoteCallbacks.GenerateCallbacks(); + var gitFetchOptions = fetchOptionsWrapper.Options; + gitFetchOptions.ProxyOptions = options.FetchOptions.ProxyOptions.CreateGitProxyOptions(); + gitFetchOptions.RemoteCallbacks = new RemoteCallbacks(options.FetchOptions).GenerateCallbacks(); - var gitSubmoduleUpdateOpts = new GitSubmoduleUpdateOptions - { - Version = 1, - CheckoutOptions = gitCheckoutOptions, - FetchOptions = new GitFetchOptions { ProxyOptions = options.ProxyOptions.CreateGitProxyOptions(), RemoteCallbacks = gitRemoteCallbacks }, - CloneCheckoutStrategy = CheckoutStrategy.GIT_CHECKOUT_SAFE - }; - - Proxy.git_submodule_update(handle, options.Init, ref gitSubmoduleUpdateOpts); - } + if (options.FetchOptions != null && options.FetchOptions.CustomHeaders != null) + { + gitFetchOptions.CustomHeaders = + GitStrArrayManaged.BuildFrom(options.FetchOptions.CustomHeaders); } + + var gitSubmoduleUpdateOpts = new GitSubmoduleUpdateOptions + { + Version = 1, + CheckoutOptions = gitCheckoutOptions, + FetchOptions = gitFetchOptions + }; + + Proxy.git_submodule_update(handle, options.Init, ref gitSubmoduleUpdateOpts); } /// diff --git a/LibGit2Sharp/SubmoduleUpdateOptions.cs b/LibGit2Sharp/SubmoduleUpdateOptions.cs index 89f895d75..082e17338 100644 --- a/LibGit2Sharp/SubmoduleUpdateOptions.cs +++ b/LibGit2Sharp/SubmoduleUpdateOptions.cs @@ -6,7 +6,7 @@ namespace LibGit2Sharp /// /// Options controlling Submodule Update behavior and callbacks. /// - public sealed class SubmoduleUpdateOptions : FetchOptionsBase, IConvertableToGitCheckoutOpts + public sealed class SubmoduleUpdateOptions : IConvertableToGitCheckoutOpts { /// /// Initialize the submodule if it is not already initialized. @@ -30,6 +30,11 @@ public sealed class SubmoduleUpdateOptions : FetchOptionsBase, IConvertableToGit /// public CheckoutNotifyFlags CheckoutNotifyFlags { get; set; } + /// + /// Collection of parameters controlling Fetch behavior. + /// + public FetchOptions FetchOptions { get; internal set; } = new(); + CheckoutCallbacks IConvertableToGitCheckoutOpts.GenerateCallbacks() { return CheckoutCallbacks.From(OnCheckoutProgress, OnCheckoutNotify); From de87973b56633459d770602fc87d8f896af93175 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 3 Dec 2023 15:42:35 -0500 Subject: [PATCH 344/384] Update CHANGES.md for v0.29 --- CHANGES.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 0cb2c978b..ae27d7716 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,16 @@ # LibGit2Sharp Changes -## v0.28 +## v0.29 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.28.0..0.29.0)) + +### Changes +- This release includes [libgit2 v1.7.1](https://github.com/libgit2/libgit2/releases/tag/v1.7.1). + - CI changes for the native binaries has removed support for CentOS 7. See [#2066](https://github.com/libgit2/libgit2sharp/pull/2066) for details. + +### Additions +- Add proxy options [#2065](https://github.com/libgit2/libgit2sharp/pull/2065) + - See PR for details, including some breaking changes to `CloneOptions` and `SubmoduleUpdateOptions` + +## v0.28 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.27.2..0.28.0)) ### Additions - Add CustomHeaders to PushOptions [#2052](https://github.com/libgit2/libgit2sharp/pull/2052) From 2cad6cd44dcb419d9bcadaeab92dd75d3b68ff9a Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 13 Mar 2024 23:50:12 -0400 Subject: [PATCH 345/384] Add project to test trimming compatibility --- .github/workflows/ci.yml | 2 ++ LibGit2Sharp/LibGit2Sharp.csproj | 4 ++++ TrimmingTestApp/Program.cs | 3 +++ TrimmingTestApp/TrimmingTestApp.csproj | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+) create mode 100644 TrimmingTestApp/Program.cs create mode 100644 TrimmingTestApp/TrimmingTestApp.csproj diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5214b064f..9d3551569 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,8 @@ jobs: name: NuGet packages path: bin/Packages/ retention-days: 7 + - name: Verify trimming compatibility + run: dotnet publish TrimmingTestApp test: name: Test / ${{ matrix.os }} / ${{ matrix.arch }} / ${{ matrix.tfm }} runs-on: ${{ matrix.os }} diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 4d0876c4d..e8836b90c 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -23,6 +23,10 @@ libgit2-$(libgit2_hash.Substring(0,7)) + + true + + diff --git a/TrimmingTestApp/Program.cs b/TrimmingTestApp/Program.cs new file mode 100644 index 000000000..e568c227b --- /dev/null +++ b/TrimmingTestApp/Program.cs @@ -0,0 +1,3 @@ +using LibGit2Sharp; + +_ = new Repository(); diff --git a/TrimmingTestApp/TrimmingTestApp.csproj b/TrimmingTestApp/TrimmingTestApp.csproj new file mode 100644 index 000000000..9cb7e75b4 --- /dev/null +++ b/TrimmingTestApp/TrimmingTestApp.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + Exe + enable + enable + true + true + true + + + + + + + + From 70ac848e7faa2f42a3d90a32dbc118a932051617 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 13 Mar 2024 23:54:52 -0400 Subject: [PATCH 346/384] Address trimming warnings --- LibGit2Sharp/Core/GitObjectLazyGroup.cs | 6 ++++++ LibGit2Sharp/Core/LazyGroup.cs | 9 +++++++++ LibGit2Sharp/Core/NativeMethods.cs | 2 +- LibGit2Sharp/Core/Platform.cs | 4 ++++ LibGit2Sharp/ReferenceWrapper.cs | 5 +++++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp/Core/GitObjectLazyGroup.cs b/LibGit2Sharp/Core/GitObjectLazyGroup.cs index 11c83a81e..f00900837 100644 --- a/LibGit2Sharp/Core/GitObjectLazyGroup.cs +++ b/LibGit2Sharp/Core/GitObjectLazyGroup.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp.Core @@ -21,7 +22,12 @@ protected override void EvaluateInternal(Action evaluator) } } +#if NET + public static ILazy Singleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TResult>(Repository repo, ObjectId id, Func resultSelector, bool throwIfMissing = false) +#else public static ILazy Singleton(Repository repo, ObjectId id, Func resultSelector, bool throwIfMissing = false) +#endif + { return Singleton(() => { diff --git a/LibGit2Sharp/Core/LazyGroup.cs b/LibGit2Sharp/Core/LazyGroup.cs index d8b13fa42..bcd160290 100644 --- a/LibGit2Sharp/Core/LazyGroup.cs +++ b/LibGit2Sharp/Core/LazyGroup.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace LibGit2Sharp.Core { @@ -44,7 +45,11 @@ public void Evaluate() protected abstract void EvaluateInternal(Action evaluator); +#if NET + protected static ILazy Singleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TResult>(Func resultSelector) +#else protected static ILazy Singleton(Func resultSelector) +#endif { return new LazyWrapper(resultSelector); } @@ -90,7 +95,11 @@ void IEvaluator.Evaluate(TInput input) } } +#if NET + protected class LazyWrapper<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TType> : Lazy, ILazy +#else protected class LazyWrapper : Lazy, ILazy +#endif { public LazyWrapper(Func evaluator) : base(evaluator) diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index e20d755ba..cd3e1de7a 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -102,7 +102,7 @@ private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImpor { // 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 assemblyDirectory = Path.GetDirectoryName(AppContext.BaseDirectory); string processorArchitecture = RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(); string runtimesDirectory = Path.Combine(assemblyDirectory, "runtimes"); diff --git a/LibGit2Sharp/Core/Platform.cs b/LibGit2Sharp/Core/Platform.cs index 42b752612..1fcb59faf 100644 --- a/LibGit2Sharp/Core/Platform.cs +++ b/LibGit2Sharp/Core/Platform.cs @@ -58,7 +58,11 @@ public static string GetNativeLibraryExtension() /// Returns true if the runtime is Mono. /// public static bool IsRunningOnMono() +#if NETFRAMEWORK => Type.GetType("Mono.Runtime") != null; +#else + => false; +#endif /// /// Returns true if the runtime is .NET Framework. diff --git a/LibGit2Sharp/ReferenceWrapper.cs b/LibGit2Sharp/ReferenceWrapper.cs index 3e4243a7e..eff09e6ce 100644 --- a/LibGit2Sharp/ReferenceWrapper.cs +++ b/LibGit2Sharp/ReferenceWrapper.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using LibGit2Sharp.Core; @@ -10,7 +11,11 @@ namespace LibGit2Sharp /// /// The type of the referenced Git object. [DebuggerDisplay("{DebuggerDisplay,nq}")] +#if NET + public abstract class ReferenceWrapper<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TObject> : IEquatable>, IBelongToARepository where TObject : GitObject +#else public abstract class ReferenceWrapper : IEquatable>, IBelongToARepository where TObject : GitObject +#endif { /// /// The repository. From 29b7380483d6de917a3edb45108d332eab197460 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Wed, 13 Mar 2024 23:58:40 -0400 Subject: [PATCH 347/384] Use .NET 8 SDK --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d3551569..f09880169 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: 7.0.x + dotnet-version: 8.0.x - name: Build run: dotnet build LibGit2Sharp.sln --configuration Release - name: Upload packages @@ -53,6 +53,7 @@ jobs: uses: actions/setup-dotnet@v3.0.3 with: dotnet-version: | + 8.0.x 7.0.x 6.0.x - name: Run ${{ matrix.tfm }} tests From ea4e6c979e9fa0c744eca4f42c5dc6bdbfde3dae Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Mar 2024 21:01:32 -0400 Subject: [PATCH 348/384] Fix failing test --- LibGit2Sharp.Tests/CloneFixture.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index b4de8797a..f205eddc2 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -267,7 +267,7 @@ public void CanInspectCertificateOnClone(string url, string hostname, Type certT 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); + Assert.Contains("CN=github.com", x509.Subject); checksHappy = true; return false; } From 4e8e00e8d8d8fb9ea046a4302ceca3655e17a912 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Mar 2024 22:53:13 -0400 Subject: [PATCH 349/384] Add net8.0 test targets --- .github/workflows/ci.yml | 10 ++++++++-- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f09880169..aba8ce0a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: matrix: arch: [ amd64 ] os: [ windows-2019, macos-11 ] - tfm: [ net472, net6.0, net7.0 ] + tfm: [ net472, net6.0, net7.0, net8.0 ] exclude: - os: macos-11 tfm: net472 @@ -66,17 +66,23 @@ jobs: arch: [ amd64 ] # arch: [ amd64, arm64 ] distro: [ alpine.3.13, alpine.3.14, alpine.3.15, alpine.3.16, alpine.3.17, centos.stream.8, debian.10, debian.11, fedora.36, ubuntu.18.04, ubuntu.20.04, ubuntu.22.04 ] - sdk: [ '6.0', '7.0' ] + sdk: [ '6.0', '7.0' , '8.0' ] exclude: - distro: alpine.3.13 sdk: '7.0' - distro: alpine.3.14 sdk: '7.0' + - distro: alpine.3.13 + sdk: '8.0' + - distro: alpine.3.14 + sdk: '8.0' include: - sdk: '6.0' tfm: net6.0 - sdk: '7.0' tfm: net7.0 + - sdk: '8.0' + tfm: net8.0 fail-fast: false steps: - name: Checkout diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index c5cbb5f24..7501b9560 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net472;net6.0;net7.0 + net472;net6.0;net7.0;net8.0 From 2b585e991a7efe0a471a6f411efdef4c12ff7016 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Mar 2024 23:26:45 -0400 Subject: [PATCH 350/384] Use .NET 8 SDK artifacts output --- .github/workflows/ci.yml | 2 +- .gitignore | 2 +- Directory.Build.props | 4 +--- LibGit2Sharp/LibGit2Sharp.csproj | 1 + NativeLibraryLoadTestApp/Directory.Build.props | 7 ------- 5 files changed, 4 insertions(+), 12 deletions(-) delete mode 100644 NativeLibraryLoadTestApp/Directory.Build.props diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aba8ce0a0..f751435bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: uses: actions/upload-artifact@v3.1.2 with: name: NuGet packages - path: bin/Packages/ + path: artifacts/package/ retention-days: 7 - name: Verify trimming compatibility run: dotnet publish TrimmingTestApp diff --git a/.gitignore b/.gitignore index 2f75ccc1d..32e17b4d0 100644 --- a/.gitignore +++ b/.gitignore @@ -38,5 +38,5 @@ _ReSharper*/ *.DotSettings _NCrunch_LibGit2Sharp/ -packages/ +artifacts/ worktree.playlist diff --git a/Directory.Build.props b/Directory.Build.props index 72eda8864..95f095732 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,9 +2,7 @@ true - $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ - $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ - $(MSBuildThisFileDirectory)bin\Packages\ + true $(DefineConstants);$(ExtraDefine) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index e8836b90c..36f0d8672 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -19,6 +19,7 @@ App_Readme/README.md App_Readme/LICENSE.md true + $(ArtifactsPath)\package preview.0 libgit2-$(libgit2_hash.Substring(0,7)) diff --git a/NativeLibraryLoadTestApp/Directory.Build.props b/NativeLibraryLoadTestApp/Directory.Build.props deleted file mode 100644 index c55b35c72..000000000 --- a/NativeLibraryLoadTestApp/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - false - - - From c9352c3236b882e2b83f64d917ab1b7ba32f2776 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Mar 2024 23:37:25 -0400 Subject: [PATCH 351/384] Update packages --- LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 12 ++++++------ LibGit2Sharp.Tests/MetaFixture.cs | 3 --- LibGit2Sharp/LibGit2Sharp.csproj | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 7501b9560..8f5ac09dd 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -11,12 +11,12 @@ - - - - - - + + + + + + diff --git a/LibGit2Sharp.Tests/MetaFixture.cs b/LibGit2Sharp.Tests/MetaFixture.cs index b70d9022c..eac08793d 100644 --- a/LibGit2Sharp.Tests/MetaFixture.cs +++ b/LibGit2Sharp.Tests/MetaFixture.cs @@ -1,15 +1,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; -using Moq; namespace LibGit2Sharp.Tests { diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 36f0d8672..fcf965c7d 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -40,8 +40,8 @@ - - + + From 9e4669c3d95931acb486cda43fab227217d5e258 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 15 Mar 2024 23:53:35 -0400 Subject: [PATCH 352/384] Fix test analyzer warnings --- LibGit2Sharp.Tests/BranchFixture.cs | 5 ++--- LibGit2Sharp.Tests/FilterFixture.cs | 15 ++++++--------- LibGit2Sharp.Tests/MetaFixture.cs | 8 ++++---- LibGit2Sharp.Tests/PushFixture.cs | 3 +-- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 2 +- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/LibGit2Sharp.Tests/BranchFixture.cs b/LibGit2Sharp.Tests/BranchFixture.cs index 736b0faec..88247e256 100644 --- a/LibGit2Sharp.Tests/BranchFixture.cs +++ b/LibGit2Sharp.Tests/BranchFixture.cs @@ -4,7 +4,6 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -103,7 +102,7 @@ public void CanCreateAnUnbornBranch() public void CanCreateBranchUsingAbbreviatedSha() { string path = SandboxBareTestRepo(); - using (var repo = new Repository(path, new RepositoryOptions{ Identity = Constants.Identity })) + using (var repo = new Repository(path, new RepositoryOptions { Identity = Constants.Identity })) { EnableRefLog(repo); @@ -1001,7 +1000,7 @@ public void OnlyOneBranchIsTheHead() continue; } - Assert.True(false, string.Format("Both '{0}' and '{1}' appear to be Head.", head.CanonicalName, branch.CanonicalName)); + Assert.Fail(string.Format("Both '{0}' and '{1}' appear to be Head.", head.CanonicalName, branch.CanonicalName)); } Assert.NotNull(head); diff --git a/LibGit2Sharp.Tests/FilterFixture.cs b/LibGit2Sharp.Tests/FilterFixture.cs index 4de354003..832ca0cad 100644 --- a/LibGit2Sharp.Tests/FilterFixture.cs +++ b/LibGit2Sharp.Tests/FilterFixture.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; -using System.Linq; using System.IO; +using System.Threading.Tasks; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using System.Threading.Tasks; namespace LibGit2Sharp.Tests { @@ -174,7 +173,7 @@ public void CleanFilterWritesOutputToObjectTree() } [Fact] - public void CanHandleMultipleSmudgesConcurrently() + public async Task CanHandleMultipleSmudgesConcurrently() { const string decodedInput = "This is a substitution cipher"; const string encodedInput = "Guvf vf n fhofgvghgvba pvcure"; @@ -193,20 +192,18 @@ public void CanHandleMultipleSmudgesConcurrently() for (int i = 0; i < count; i++) { - tasks[i] = Task.Factory.StartNew(() => + tasks[i] = Task.Run(() => { string repoPath = InitNewRepository(); return CheckoutFileForSmudge(repoPath, branchName, encodedInput); }); } - Task.WaitAll(tasks); + var files = await Task.WhenAll(tasks); - foreach(var task in tasks) + foreach (var file in files) { - FileInfo expectedFile = task.Result; - - string readAllText = File.ReadAllText(expectedFile.FullName); + string readAllText = File.ReadAllText(file.FullName); Assert.Equal(decodedInput, readAllText); } } diff --git a/LibGit2Sharp.Tests/MetaFixture.cs b/LibGit2Sharp.Tests/MetaFixture.cs index eac08793d..5ff76e307 100644 --- a/LibGit2Sharp.Tests/MetaFixture.cs +++ b/LibGit2Sharp.Tests/MetaFixture.cs @@ -112,7 +112,7 @@ public void TypesInLibGit2DecoratedWithDebuggerDisplayMustFollowTheStandardImplP if (typesWithDebuggerDisplayAndInvalidImplPattern.Any()) { - Assert.True(false, Environment.NewLine + BuildMissingDebuggerDisplayPropertyMessage(typesWithDebuggerDisplayAndInvalidImplPattern)); + Assert.Fail(Environment.NewLine + BuildMissingDebuggerDisplayPropertyMessage(typesWithDebuggerDisplayAndInvalidImplPattern)); } } @@ -167,7 +167,7 @@ public void TypesInLibGit2SharpMustBeExtensibleInATestingContext() if (nonTestableTypes.Any()) { - Assert.True(false, Environment.NewLine + BuildNonTestableTypesMessage(nonTestableTypes)); + Assert.Fail(Environment.NewLine + BuildNonTestableTypesMessage(nonTestableTypes)); } } @@ -287,7 +287,7 @@ public void GetEnumeratorMethodsInLibGit2SharpMustBeVirtualForTestability() method.DeclaringType, Environment.NewLine); } - Assert.True(false, Environment.NewLine + sb.ToString()); + Assert.Fail(Environment.NewLine + sb.ToString()); } } @@ -316,7 +316,7 @@ public void NoPublicTypesUnderLibGit2SharpCoreNamespace() type.FullName, coreNamespace, Environment.NewLine); } - Assert.True(false, Environment.NewLine + sb.ToString()); + Assert.Fail(Environment.NewLine + sb.ToString()); } } diff --git a/LibGit2Sharp.Tests/PushFixture.cs b/LibGit2Sharp.Tests/PushFixture.cs index fc6c0c42d..824c1d8c0 100644 --- a/LibGit2Sharp.Tests/PushFixture.cs +++ b/LibGit2Sharp.Tests/PushFixture.cs @@ -12,8 +12,7 @@ public class PushFixture : BaseFixture { private void OnPushStatusError(PushStatusError pushStatusErrors) { - Assert.True(false, string.Format("Failed to update reference '{0}': {1}", - pushStatusErrors.Reference, pushStatusErrors.Message)); + Assert.Fail(string.Format("Failed to update reference '{0}': {1}", pushStatusErrors.Reference, pushStatusErrors.Message)); } private void AssertPush(Action push) diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index 8d9b9ba0c..cde8f3ddb 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -278,7 +278,7 @@ public virtual void Dispose() if (Core.LeaksContainer.TypeNames.Any()) { - Assert.False(true, string.Format("Some handles of the following types haven't been properly released: {0}.{1}" + Assert.Fail(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(", ", Core.LeaksContainer.TypeNames), Environment.NewLine)); } From 8d79ff45f67f632e26ff2e3d29f863fac3aa4c22 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Mar 2024 00:10:10 -0400 Subject: [PATCH 353/384] Update workflow actions --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f751435bf..6cac69258 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,17 +15,17 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v4.1.2 with: fetch-depth: 0 - name: Install .NET SDK - uses: actions/setup-dotnet@v3.0.3 + uses: actions/setup-dotnet@v4.0.0 with: dotnet-version: 8.0.x - name: Build run: dotnet build LibGit2Sharp.sln --configuration Release - name: Upload packages - uses: actions/upload-artifact@v3.1.2 + uses: actions/upload-artifact@v4.3.1 with: name: NuGet packages path: artifacts/package/ @@ -46,11 +46,11 @@ jobs: fail-fast: false steps: - name: Checkout - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v4.1.2 with: fetch-depth: 0 - name: Install .NET SDK - uses: actions/setup-dotnet@v3.0.3 + uses: actions/setup-dotnet@v4.0.0 with: dotnet-version: | 8.0.x @@ -86,7 +86,7 @@ jobs: fail-fast: false steps: - name: Checkout - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v4.1.2 with: fetch-depth: 0 - name: Setup QEMU From 4193f6bbd0c18efc81419640fed61cb4fe791aee Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Mar 2024 01:09:18 -0400 Subject: [PATCH 354/384] Update testing matrix --- .github/workflows/ci.yml | 40 ++++++++++++++------ LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 2 +- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6cac69258..35f0241ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,12 +37,25 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - arch: [ amd64 ] - os: [ windows-2019, macos-11 ] - tfm: [ net472, net6.0, net7.0, net8.0 ] + arch: [ x64 ] + os: [ windows-2019, windows-2022, macos-11, macos-12, macos-13 ] + tfm: [ net472, net6.0, net8.0 ] exclude: - os: macos-11 tfm: net472 + - os: macos-11 + tfm: net8.0 + - os: macos-12 + tfm: net472 + - os: macos-13 + tfm: net472 + include: + - arch: arm64 + os: macos-14 + tfm: net6.0 + - arch: arm64 + os: macos-14 + tfm: net8.0 fail-fast: false steps: - name: Checkout @@ -54,7 +67,6 @@ jobs: with: dotnet-version: | 8.0.x - 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 @@ -65,22 +77,26 @@ jobs: matrix: arch: [ amd64 ] # arch: [ amd64, arm64 ] - distro: [ alpine.3.13, alpine.3.14, alpine.3.15, alpine.3.16, alpine.3.17, centos.stream.8, debian.10, debian.11, fedora.36, ubuntu.18.04, ubuntu.20.04, ubuntu.22.04 ] - sdk: [ '6.0', '7.0' , '8.0' ] + distro: [ alpine.3.13, alpine.3.14, alpine.3.15, alpine.3.16, alpine.3.17, alpine.3.18, centos.stream.8, debian.10, debian.11, fedora.36, fedora.37, ubuntu.18.04, ubuntu.20.04, ubuntu.22.04 ] + sdk: [ '6.0', '8.0' ] exclude: - - distro: alpine.3.13 - sdk: '7.0' - - distro: alpine.3.14 - sdk: '7.0' - distro: alpine.3.13 sdk: '8.0' - distro: alpine.3.14 sdk: '8.0' + - distro: alpine.3.15 + sdk: '8.0' + - distro: alpine.3.16 + sdk: '8.0' + - distro: debian.10 + sdk: '8.0' + - distro: fedora.36 + sdk: '8.0' + - distro: ubuntu.18.04 + sdk: '8.0' include: - sdk: '6.0' tfm: net6.0 - - sdk: '7.0' - tfm: net7.0 - sdk: '8.0' tfm: net8.0 fail-fast: false diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 8f5ac09dd..4d648eead 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net472;net6.0;net7.0;net8.0 + net472;net6.0;net8.0 From c4073715055b2d8c6009ced0a52db6659ceaa104 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Mar 2024 00:45:34 -0400 Subject: [PATCH 355/384] Fix analyzer warnings --- Directory.Build.props | 1 + .../desktop/SmartSubtransportFixture.cs | 2 +- LibGit2Sharp/AmbiguousSpecificationException.cs | 10 ++++++++-- LibGit2Sharp/BareRepositoryException.cs | 6 ++++++ LibGit2Sharp/CheckoutConflictException.cs | 6 ++++++ LibGit2Sharp/EmptyCommitException.cs | 6 ++++++ LibGit2Sharp/EntryExistsException.cs | 7 +++++++ LibGit2Sharp/InvalidSpecificationException.cs | 6 ++++++ LibGit2Sharp/LibGit2SharpException.cs | 9 +++++++-- LibGit2Sharp/LockedFileException.cs | 6 ++++++ LibGit2Sharp/MergeFetchHeadNotFoundException.cs | 6 ++++++ LibGit2Sharp/NameConflictException.cs | 6 ++++++ LibGit2Sharp/NativeException.cs | 13 ++++++++----- LibGit2Sharp/NonFastForwardException.cs | 6 ++++++ LibGit2Sharp/NotFoundException.cs | 6 ++++++ LibGit2Sharp/PeelException.cs | 6 ++++++ LibGit2Sharp/RecurseSubmodulesException.cs | 6 ++++++ LibGit2Sharp/RemoveFromIndexException.cs | 7 ++++++- LibGit2Sharp/RepositoryNotFoundException.cs | 6 ++++++ LibGit2Sharp/UnbornBranchException.cs | 6 ++++++ LibGit2Sharp/UnmatchedPathException.cs | 6 ++++++ LibGit2Sharp/UnmergedIndexEntriesException.cs | 6 ++++++ LibGit2Sharp/UserCanceledException.cs | 6 ++++++ 23 files changed, 134 insertions(+), 11 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 95f095732..2c14cc2bd 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,7 @@ + true true true $(DefineConstants);$(ExtraDefine) diff --git a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs index ff4d0fcd6..bc7e7ac15 100644 --- a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs +++ b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs @@ -313,7 +313,7 @@ private HttpWebResponse GetResponseWithRedirects() } // rethrow if it's not 401 - throw ex; + throw; } if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) diff --git a/LibGit2Sharp/AmbiguousSpecificationException.cs b/LibGit2Sharp/AmbiguousSpecificationException.cs index 16c77f6df..4903d9df9 100644 --- a/LibGit2Sharp/AmbiguousSpecificationException.cs +++ b/LibGit2Sharp/AmbiguousSpecificationException.cs @@ -1,13 +1,17 @@ -using LibGit2Sharp.Core; using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif +using LibGit2Sharp.Core; namespace LibGit2Sharp { /// /// The exception that is thrown when the provided specification cannot uniquely identify a reference, an object or a path. /// +#if NETFRAMEWORK [Serializable] +#endif public class AmbiguousSpecificationException : NativeException { /// @@ -30,7 +34,7 @@ public AmbiguousSpecificationException(string message) /// A composite format string for use in . /// An object array that contains zero or more objects to format. public AmbiguousSpecificationException(string format, params object[] args) - : base(String.Format(format, args)) + : base(string.Format(format, args)) { } @@ -43,6 +47,7 @@ public AmbiguousSpecificationException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -51,6 +56,7 @@ public AmbiguousSpecificationException(string message, Exception innerException) protected AmbiguousSpecificationException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal override GitErrorCode ErrorCode { diff --git a/LibGit2Sharp/BareRepositoryException.cs b/LibGit2Sharp/BareRepositoryException.cs index 7ee830a0c..461204acd 100644 --- a/LibGit2Sharp/BareRepositoryException.cs +++ b/LibGit2Sharp/BareRepositoryException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -8,7 +10,9 @@ namespace LibGit2Sharp /// The exception that is thrown when an operation which requires a /// working directory is performed against a bare repository. /// +#if NETFRAMEWORK [Serializable] +#endif public class BareRepositoryException : NativeException { /// @@ -43,6 +47,7 @@ public BareRepositoryException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -51,6 +56,7 @@ public BareRepositoryException(string message, Exception innerException) protected BareRepositoryException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal BareRepositoryException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/CheckoutConflictException.cs b/LibGit2Sharp/CheckoutConflictException.cs index f2f5092e9..23b97143e 100644 --- a/LibGit2Sharp/CheckoutConflictException.cs +++ b/LibGit2Sharp/CheckoutConflictException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -9,7 +11,9 @@ namespace LibGit2Sharp /// because of a conflicting change staged in the index, or unstaged /// in the working directory. /// +#if NETFRAMEWORK [Serializable] +#endif public class CheckoutConflictException : NativeException { /// @@ -44,6 +48,7 @@ public CheckoutConflictException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -52,6 +57,7 @@ public CheckoutConflictException(string message, Exception innerException) protected CheckoutConflictException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal CheckoutConflictException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/EmptyCommitException.cs b/LibGit2Sharp/EmptyCommitException.cs index 8cd48e49f..0c247bec7 100644 --- a/LibGit2Sharp/EmptyCommitException.cs +++ b/LibGit2Sharp/EmptyCommitException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif namespace LibGit2Sharp { @@ -7,7 +9,9 @@ namespace LibGit2Sharp /// The exception that is thrown when a commit would create an "empty" /// commit that is treesame to its parent without an explicit override. /// +#if NETFRAMEWORK [Serializable] +#endif public class EmptyCommitException : LibGit2SharpException { /// @@ -42,6 +46,7 @@ public EmptyCommitException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -50,5 +55,6 @@ public EmptyCommitException(string message, Exception innerException) protected EmptyCommitException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/LibGit2Sharp/EntryExistsException.cs b/LibGit2Sharp/EntryExistsException.cs index 2c46e4acd..8039f5edd 100644 --- a/LibGit2Sharp/EntryExistsException.cs +++ b/LibGit2Sharp/EntryExistsException.cs @@ -1,5 +1,8 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif + using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -7,7 +10,9 @@ namespace LibGit2Sharp /// /// The exception that is thrown attempting to create a resource that already exists. /// +#if NETFRAMEWORK [Serializable] +#endif public class EntryExistsException : LibGit2SharpException { /// @@ -42,6 +47,7 @@ public EntryExistsException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -50,6 +56,7 @@ public EntryExistsException(string message, Exception innerException) protected EntryExistsException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal EntryExistsException(string message, GitErrorCode code, GitErrorCategory category) : base(message, code, category) diff --git a/LibGit2Sharp/InvalidSpecificationException.cs b/LibGit2Sharp/InvalidSpecificationException.cs index 3d34571a4..573a8a1db 100644 --- a/LibGit2Sharp/InvalidSpecificationException.cs +++ b/LibGit2Sharp/InvalidSpecificationException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -10,7 +12,9 @@ namespace LibGit2Sharp /// if the spec refers to an object of an incorrect type (e.g. asking to /// create a branch from a blob, or peeling a blob to a commit). /// +#if NETFRAMEWORK [Serializable] +#endif public class InvalidSpecificationException : NativeException { /// @@ -45,6 +49,7 @@ public InvalidSpecificationException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -53,6 +58,7 @@ public InvalidSpecificationException(string message, Exception innerException) protected InvalidSpecificationException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal InvalidSpecificationException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/LibGit2SharpException.cs b/LibGit2Sharp/LibGit2SharpException.cs index 5d1c33f25..e5d90f61f 100644 --- a/LibGit2Sharp/LibGit2SharpException.cs +++ b/LibGit2Sharp/LibGit2SharpException.cs @@ -1,14 +1,17 @@ using System; using System.Globalization; +#if NETFRAMEWORK using System.Runtime.Serialization; -using LibGit2Sharp.Core; +#endif namespace LibGit2Sharp { /// /// The exception that is thrown when an error occurs during application execution. /// +#if NETFRAMEWORK [Serializable] +#endif public class LibGit2SharpException : Exception { /// @@ -40,10 +43,11 @@ public LibGit2SharpException(string message, Exception innerException) /// A composite format string for use in . /// An object array that contains zero or more objects to format. public LibGit2SharpException(string format, params object[] args) - : base(String.Format(CultureInfo.InvariantCulture, format, args)) + : base(string.Format(CultureInfo.InvariantCulture, format, args)) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -52,5 +56,6 @@ public LibGit2SharpException(string format, params object[] args) protected LibGit2SharpException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/LibGit2Sharp/LockedFileException.cs b/LibGit2Sharp/LockedFileException.cs index 44fd65b02..d58c8dbec 100644 --- a/LibGit2Sharp/LockedFileException.cs +++ b/LibGit2Sharp/LockedFileException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -7,7 +9,9 @@ namespace LibGit2Sharp /// /// The exception that is thrown attempting to open a locked file. /// +#if NETFRAMEWORK [Serializable] +#endif public class LockedFileException : NativeException { /// @@ -42,6 +46,7 @@ public LockedFileException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -50,6 +55,7 @@ public LockedFileException(string message, Exception innerException) protected LockedFileException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal LockedFileException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/MergeFetchHeadNotFoundException.cs b/LibGit2Sharp/MergeFetchHeadNotFoundException.cs index a86bf5caf..34b6b71aa 100644 --- a/LibGit2Sharp/MergeFetchHeadNotFoundException.cs +++ b/LibGit2Sharp/MergeFetchHeadNotFoundException.cs @@ -1,12 +1,16 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif namespace LibGit2Sharp { /// /// The exception that is thrown when the ref to merge with was as part of a pull operation not fetched. /// +#if NETFRAMEWORK [Serializable] +#endif public class MergeFetchHeadNotFoundException : NotFoundException { /// @@ -41,6 +45,7 @@ public MergeFetchHeadNotFoundException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -49,5 +54,6 @@ public MergeFetchHeadNotFoundException(string message, Exception innerException) protected MergeFetchHeadNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/LibGit2Sharp/NameConflictException.cs b/LibGit2Sharp/NameConflictException.cs index 0dcffc648..0f4dde744 100644 --- a/LibGit2Sharp/NameConflictException.cs +++ b/LibGit2Sharp/NameConflictException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -7,7 +9,9 @@ namespace LibGit2Sharp /// /// The exception that is thrown when a reference, a remote, a submodule... with the same name already exists in the repository /// +#if NETFRAMEWORK [Serializable] +#endif public class NameConflictException : NativeException { /// @@ -42,6 +46,7 @@ public NameConflictException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -50,6 +55,7 @@ public NameConflictException(string message, Exception innerException) protected NameConflictException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal NameConflictException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/NativeException.cs b/LibGit2Sharp/NativeException.cs index 292372db7..66dc03c57 100644 --- a/LibGit2Sharp/NativeException.cs +++ b/LibGit2Sharp/NativeException.cs @@ -1,16 +1,17 @@ -using LibGit2Sharp.Core; -using System; -using System.Collections.Generic; -using System.Globalization; +using System; +#if NETFRAMEWORK using System.Runtime.Serialization; -using System.Text; +#endif +using LibGit2Sharp.Core; namespace LibGit2Sharp { /// /// An exception thrown that corresponds to a libgit2 (native library) error. /// +#if NETFRAMEWORK [Serializable] +#endif public abstract class NativeException : LibGit2SharpException { /// @@ -32,9 +33,11 @@ internal NativeException(string format, params object[] args) { } +#if NETFRAMEWORK internal NativeException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal NativeException(string message, GitErrorCategory category) : this(message) { diff --git a/LibGit2Sharp/NonFastForwardException.cs b/LibGit2Sharp/NonFastForwardException.cs index b5a858f47..f63e2eb1d 100644 --- a/LibGit2Sharp/NonFastForwardException.cs +++ b/LibGit2Sharp/NonFastForwardException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -8,7 +10,9 @@ namespace LibGit2Sharp /// The exception that is thrown when push cannot be performed /// against the remote without losing commits. /// +#if NETFRAMEWORK [Serializable] +#endif public class NonFastForwardException : NativeException { /// @@ -43,6 +47,7 @@ public NonFastForwardException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -51,6 +56,7 @@ public NonFastForwardException(string message, Exception innerException) protected NonFastForwardException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal NonFastForwardException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/NotFoundException.cs b/LibGit2Sharp/NotFoundException.cs index f8c49cc91..4aefe3f8a 100644 --- a/LibGit2Sharp/NotFoundException.cs +++ b/LibGit2Sharp/NotFoundException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -7,7 +9,9 @@ namespace LibGit2Sharp /// /// The exception that is thrown attempting to reference a resource that does not exist. /// +#if NETFRAMEWORK [Serializable] +#endif public class NotFoundException : NativeException { /// @@ -42,6 +46,7 @@ public NotFoundException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -50,6 +55,7 @@ public NotFoundException(string message, Exception innerException) protected NotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal NotFoundException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/PeelException.cs b/LibGit2Sharp/PeelException.cs index d7758d7c9..92a6a0f13 100644 --- a/LibGit2Sharp/PeelException.cs +++ b/LibGit2Sharp/PeelException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -8,7 +10,9 @@ namespace LibGit2Sharp /// The exception that is thrown when a tag cannot be peeled to the /// target type due to the object model. /// +#if NETFRAMEWORK [Serializable] +#endif public class PeelException : NativeException { /// @@ -43,6 +47,7 @@ public PeelException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -51,6 +56,7 @@ public PeelException(string message, Exception innerException) protected PeelException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal PeelException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/RecurseSubmodulesException.cs b/LibGit2Sharp/RecurseSubmodulesException.cs index cf4479701..2269f0d16 100644 --- a/LibGit2Sharp/RecurseSubmodulesException.cs +++ b/LibGit2Sharp/RecurseSubmodulesException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif namespace LibGit2Sharp { @@ -8,7 +10,9 @@ namespace LibGit2Sharp /// through submodules. The inner exception contains the exception that was /// initially thrown while operating on the submodule. /// +#if NETFRAMEWORK [Serializable] +#endif public class RecurseSubmodulesException : LibGit2SharpException { /// @@ -34,6 +38,7 @@ public RecurseSubmodulesException(string message, Exception innerException, stri InitialRepositoryPath = initialRepositoryPath; } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -42,5 +47,6 @@ public RecurseSubmodulesException(string message, Exception innerException, stri protected RecurseSubmodulesException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/LibGit2Sharp/RemoveFromIndexException.cs b/LibGit2Sharp/RemoveFromIndexException.cs index 6d9718c18..37e7daf79 100644 --- a/LibGit2Sharp/RemoveFromIndexException.cs +++ b/LibGit2Sharp/RemoveFromIndexException.cs @@ -1,13 +1,16 @@ using System; -using System.Globalization; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif namespace LibGit2Sharp { /// /// The exception that is thrown when a file cannot be removed from the index. /// +#if NETFRAMEWORK [Serializable] +#endif public class RemoveFromIndexException : LibGit2SharpException { /// @@ -43,6 +46,7 @@ public RemoveFromIndexException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -51,5 +55,6 @@ public RemoveFromIndexException(string message, Exception innerException) protected RemoveFromIndexException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/LibGit2Sharp/RepositoryNotFoundException.cs b/LibGit2Sharp/RepositoryNotFoundException.cs index 2255c0891..2e8deb393 100644 --- a/LibGit2Sharp/RepositoryNotFoundException.cs +++ b/LibGit2Sharp/RepositoryNotFoundException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif namespace LibGit2Sharp { @@ -7,7 +9,9 @@ namespace LibGit2Sharp /// The exception that is thrown when a is being built with /// a path that doesn't point at a valid Git repository or workdir. /// +#if NETFRAMEWORK [Serializable] +#endif public class RepositoryNotFoundException : LibGit2SharpException { /// @@ -42,6 +46,7 @@ public RepositoryNotFoundException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -50,5 +55,6 @@ public RepositoryNotFoundException(string message, Exception innerException) protected RepositoryNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/LibGit2Sharp/UnbornBranchException.cs b/LibGit2Sharp/UnbornBranchException.cs index 34ef437cb..8f56eed3d 100644 --- a/LibGit2Sharp/UnbornBranchException.cs +++ b/LibGit2Sharp/UnbornBranchException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif namespace LibGit2Sharp { @@ -7,7 +9,9 @@ namespace LibGit2Sharp /// The exception that is thrown when a operation requiring an existing /// branch is performed against an unborn branch. /// +#if NETFRAMEWORK [Serializable] +#endif public class UnbornBranchException : LibGit2SharpException { /// @@ -42,6 +46,7 @@ public UnbornBranchException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -50,5 +55,6 @@ public UnbornBranchException(string message, Exception innerException) protected UnbornBranchException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/LibGit2Sharp/UnmatchedPathException.cs b/LibGit2Sharp/UnmatchedPathException.cs index 7d118346d..daf48db6d 100644 --- a/LibGit2Sharp/UnmatchedPathException.cs +++ b/LibGit2Sharp/UnmatchedPathException.cs @@ -1,12 +1,16 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif namespace LibGit2Sharp { /// /// The exception that is thrown when an explicit path or a list of explicit paths could not be matched. /// +#if NETFRAMEWORK [Serializable] +#endif public class UnmatchedPathException : LibGit2SharpException { /// @@ -41,6 +45,7 @@ public UnmatchedPathException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -49,5 +54,6 @@ public UnmatchedPathException(string message, Exception innerException) protected UnmatchedPathException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif } } diff --git a/LibGit2Sharp/UnmergedIndexEntriesException.cs b/LibGit2Sharp/UnmergedIndexEntriesException.cs index 7594049b1..ca01c256d 100644 --- a/LibGit2Sharp/UnmergedIndexEntriesException.cs +++ b/LibGit2Sharp/UnmergedIndexEntriesException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -8,7 +10,9 @@ namespace LibGit2Sharp /// The exception that is thrown when an operation that requires a fully merged index /// is performed against an index with unmerged entries /// +#if NETFRAMEWORK [Serializable] +#endif public class UnmergedIndexEntriesException : NativeException { /// @@ -43,6 +47,7 @@ public UnmergedIndexEntriesException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -51,6 +56,7 @@ public UnmergedIndexEntriesException(string message, Exception innerException) protected UnmergedIndexEntriesException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal UnmergedIndexEntriesException(string message, GitErrorCategory category) : base(message, category) diff --git a/LibGit2Sharp/UserCanceledException.cs b/LibGit2Sharp/UserCanceledException.cs index ba6458049..0139bdb1c 100644 --- a/LibGit2Sharp/UserCanceledException.cs +++ b/LibGit2Sharp/UserCanceledException.cs @@ -1,5 +1,7 @@ using System; +#if NETFRAMEWORK using System.Runtime.Serialization; +#endif using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -7,7 +9,9 @@ namespace LibGit2Sharp /// /// The exception that is thrown when an operation is canceled. /// +#if NETFRAMEWORK [Serializable] +#endif public class UserCancelledException : NativeException { /// @@ -42,6 +46,7 @@ public UserCancelledException(string message, Exception innerException) : base(message, innerException) { } +#if NETFRAMEWORK /// /// Initializes a new instance of the class with a serialized data. /// @@ -50,6 +55,7 @@ public UserCancelledException(string message, Exception innerException) protected UserCancelledException(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif internal UserCancelledException(string message, GitErrorCategory category) : base(message, category) From 729ef8d939bc578f3f226761bf53d245d62b7d4b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Mar 2024 12:51:14 -0400 Subject: [PATCH 356/384] Clean up more analyzer warnings --- LibGit2Sharp.Tests/CommitFixture.cs | 4 +-- LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs | 4 +-- LibGit2Sharp.Tests/FetchFixture.cs | 28 +++++++++---------- LibGit2Sharp.Tests/FilterBranchFixture.cs | 2 +- LibGit2Sharp.Tests/FilterFixture.cs | 2 +- LibGit2Sharp.Tests/MetaFixture.cs | 14 +++++----- LibGit2Sharp.Tests/NetworkFixture.cs | 8 +++--- LibGit2Sharp.Tests/ReferenceFixture.cs | 2 +- LibGit2Sharp.Tests/RemoveFixture.cs | 2 +- LibGit2Sharp.Tests/RepositoryFixture.cs | 4 +-- LibGit2Sharp.Tests/StageFixture.cs | 6 ++-- LibGit2Sharp.Tests/TestHelpers/Constants.cs | 4 +-- LibGit2Sharp.Tests/UnstageFixture.cs | 2 +- .../desktop/SmartSubtransportFixture.cs | 14 +++++----- .../AmbiguousSpecificationException.cs | 2 +- LibGit2Sharp/BareRepositoryException.cs | 2 +- LibGit2Sharp/BlameHunk.cs | 6 ++-- LibGit2Sharp/BlameHunkCollection.cs | 2 +- LibGit2Sharp/Blob.cs | 2 +- LibGit2Sharp/CheckoutConflictException.cs | 2 +- LibGit2Sharp/Commands/Pull.cs | 3 +- LibGit2Sharp/Commands/Stage.cs | 2 +- LibGit2Sharp/Conflict.cs | 6 ++-- LibGit2Sharp/Core/EncodingMarshaler.cs | 16 +++++------ LibGit2Sharp/Core/Ensure.cs | 2 +- LibGit2Sharp/Core/FileHistory.cs | 2 +- LibGit2Sharp/Core/FilePathMarshaler.cs | 4 +-- LibGit2Sharp/Core/GitBlame.cs | 2 +- LibGit2Sharp/Core/GitDiff.cs | 22 +++++++-------- LibGit2Sharp/Core/GitOdbBackend.cs | 2 +- LibGit2Sharp/Core/GitOdbBackendStream.cs | 4 +-- LibGit2Sharp/Core/GitStrArrayNative.cs | 4 +-- LibGit2Sharp/Core/HistoryRewriter.cs | 2 +- LibGit2Sharp/Core/NativeMethods.cs | 10 +++---- LibGit2Sharp/Core/Proxy.cs | 20 ++++++------- LibGit2Sharp/Core/TarWriter.cs | 14 +++++----- LibGit2Sharp/Core/Utf8Marshaler.cs | 4 +-- LibGit2Sharp/Diff.cs | 5 ++-- LibGit2Sharp/EmptyCommitException.cs | 2 +- LibGit2Sharp/EntryExistsException.cs | 2 +- LibGit2Sharp/FetchHead.cs | 2 +- LibGit2Sharp/Filter.cs | 12 ++++---- LibGit2Sharp/GitObject.cs | 8 +++--- LibGit2Sharp/GlobalSettings.cs | 4 +-- LibGit2Sharp/IndexEntry.cs | 6 ++-- LibGit2Sharp/IndexNameEntry.cs | 6 ++-- LibGit2Sharp/IndexReucEntry.cs | 6 ++-- LibGit2Sharp/InvalidSpecificationException.cs | 2 +- LibGit2Sharp/LibGit2SharpException.cs | 2 +- LibGit2Sharp/LockedFileException.cs | 2 +- .../MergeFetchHeadNotFoundException.cs | 2 +- LibGit2Sharp/NameConflictException.cs | 2 +- LibGit2Sharp/NonFastForwardException.cs | 2 +- LibGit2Sharp/NotFoundException.cs | 2 +- LibGit2Sharp/Note.cs | 6 ++-- LibGit2Sharp/ObjectDatabase.cs | 18 ++++++------ LibGit2Sharp/ObjectId.cs | 14 +++++----- LibGit2Sharp/OdbBackend.cs | 2 +- LibGit2Sharp/PackBuilder.cs | 2 +- LibGit2Sharp/PeelException.cs | 2 +- LibGit2Sharp/PushUpdate.cs | 4 +-- LibGit2Sharp/Reference.cs | 8 +++--- LibGit2Sharp/ReferenceCollection.cs | 2 +- LibGit2Sharp/ReferenceWrapper.cs | 6 ++-- LibGit2Sharp/RemoveFromIndexException.cs | 2 +- LibGit2Sharp/RenameDetails.cs | 6 ++-- LibGit2Sharp/Repository.cs | 6 ++-- LibGit2Sharp/RepositoryNotFoundException.cs | 2 +- LibGit2Sharp/Signature.cs | 6 ++-- LibGit2Sharp/SmartSubtransport.cs | 8 +++--- LibGit2Sharp/StashCollection.cs | 8 +++--- LibGit2Sharp/StatusEntry.cs | 6 ++-- LibGit2Sharp/Submodule.cs | 8 +++--- LibGit2Sharp/Tree.cs | 2 +- LibGit2Sharp/TreeChanges.cs | 4 +-- LibGit2Sharp/TreeEntry.cs | 6 ++-- LibGit2Sharp/TreeEntryDefinition.cs | 6 ++-- LibGit2Sharp/UnbornBranchException.cs | 2 +- LibGit2Sharp/UnmatchedPathException.cs | 2 +- LibGit2Sharp/UnmergedIndexEntriesException.cs | 2 +- LibGit2Sharp/UserCanceledException.cs | 2 +- LibGit2Sharp/Worktree.cs | 8 +++--- 82 files changed, 223 insertions(+), 225 deletions(-) diff --git a/LibGit2Sharp.Tests/CommitFixture.cs b/LibGit2Sharp.Tests/CommitFixture.cs index f555e7874..1a849c2df 100644 --- a/LibGit2Sharp.Tests/CommitFixture.cs +++ b/LibGit2Sharp.Tests/CommitFixture.cs @@ -406,7 +406,7 @@ public void CanEnumerateCommitsFromATagWhichPointsToABlob() { AssertEnumerationOfCommits( repo => new CommitFilter { IncludeReachableFrom = repo.Tags["point_to_blob"] }, - new string[] { }); + Array.Empty()); } [Fact] @@ -421,7 +421,7 @@ public void CanEnumerateCommitsFromATagWhichPointsToATree() AssertEnumerationOfCommitsInRepo(repo, r => new CommitFilter { IncludeReachableFrom = tag }, - new string[] { }); + Array.Empty()); } } diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs index 0fe7adee1..9212dfa99 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs @@ -9,7 +9,7 @@ namespace LibGit2Sharp.Tests { public class DiffTreeToTreeFixture : BaseFixture { - private static readonly string subBranchFilePath = String.Join("/", "1", "branch_file.txt"); + private static readonly string subBranchFilePath = string.Join("/", "1", "branch_file.txt"); [Fact] public void ComparingATreeAgainstItselfReturnsNoDifference() @@ -27,7 +27,7 @@ public void ComparingATreeAgainstItselfReturnsNoDifference() using (var patch = repo.Diff.Compare(tree, tree)) { Assert.Empty(patch); - Assert.Equal(String.Empty, patch); + Assert.Equal(string.Empty, patch); } } } diff --git a/LibGit2Sharp.Tests/FetchFixture.cs b/LibGit2Sharp.Tests/FetchFixture.cs index c0c6f0478..b36da7ccd 100644 --- a/LibGit2Sharp.Tests/FetchFixture.cs +++ b/LibGit2Sharp.Tests/FetchFixture.cs @@ -42,7 +42,7 @@ public void CanFetchIntoAnEmptyRepository(string url) } // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null); + Commands.Fetch(repo, remoteName, Array.Empty(), new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null); // Verify the expected expectedFetchState.CheckUpdatedReferences(repo); @@ -62,7 +62,7 @@ public void CanFetchIntoAnEmptyRepositoryWithCredentials() repo.Network.Remotes.Add(remoteName, Constants.PrivateRepoUrl); // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions + Commands.Fetch(repo, remoteName, Array.Empty(), new FetchOptions { CredentialsProvider = Constants.PrivateRepoCredentials }, null); @@ -98,7 +98,7 @@ public void CanFetchAllTagsIntoAnEmptyRepository(string url) } // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions + Commands.Fetch(repo, remoteName, Array.Empty(), new FetchOptions { TagFetchMode = TagFetchMode.All, OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler @@ -179,7 +179,7 @@ public void FetchRespectsConfiguredAutoTagSetting(TagFetchMode tagFetchMode, int r => r.TagFetchMode = tagFetchMode); // Perform the actual fetch. - Commands.Fetch(repo, remoteName, new string[0], null, null); + Commands.Fetch(repo, remoteName, Array.Empty(), null, null); // Verify the number of fetched tags. Assert.Equal(expectedTagCount, repo.Tags.Count()); @@ -197,7 +197,7 @@ public void CanFetchAllTagsAfterAnInitialClone() using (var repo = new Repository(clonedRepoPath)) { - Commands.Fetch(repo, "origin", new string[0], new FetchOptions { TagFetchMode = TagFetchMode.All }, null); + Commands.Fetch(repo, "origin", Array.Empty(), new FetchOptions { TagFetchMode = TagFetchMode.All }, null); } } @@ -223,17 +223,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); + Commands.Fetch(clonedRepo, "origin", Array.Empty(), null, null); 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); + Commands.Fetch(clonedRepo, "origin", Array.Empty(), null, null); 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); + Commands.Fetch(clonedRepo, "origin", Array.Empty(), null, null); Assert.Equal(4, clonedRepo.Branches.Count(b => b.IsRemote && b.FriendlyName != "origin/HEAD")); } } @@ -248,10 +248,10 @@ public void CannotFetchWithForbiddenCustomHeaders() string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath); const string knownHeader = "User-Agent: mygit-201"; - var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; + var options = new FetchOptions { CustomHeaders = new string[] { knownHeader } }; using (var repo = new Repository(clonedRepoPath)) { - Assert.Throws(() => Commands.Fetch(repo, "origin", new string[0], options, null)); + Assert.Throws(() => Commands.Fetch(repo, "origin", Array.Empty(), options, null)); } } @@ -265,10 +265,10 @@ public void CanFetchWithCustomHeaders() string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath); const string knownHeader = "X-Hello: mygit-201"; - var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; + var options = new FetchOptions { CustomHeaders = new string[] { knownHeader } }; using (var repo = new Repository(clonedRepoPath)) { - Commands.Fetch(repo, "origin", new string[0], options, null); + Commands.Fetch(repo, "origin", Array.Empty(), options, null); } } @@ -282,10 +282,10 @@ public void CannotFetchWithMalformedCustomHeaders() string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath); const string knownHeader = "Hello world"; - var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; + var options = new FetchOptions { CustomHeaders = new string[] { knownHeader } }; using (var repo = new Repository(clonedRepoPath)) { - Assert.Throws(() => Commands.Fetch(repo, "origin", new string[0], options, null)); + Assert.Throws(() => Commands.Fetch(repo, "origin", Array.Empty(), options, null)); } } diff --git a/LibGit2Sharp.Tests/FilterBranchFixture.cs b/LibGit2Sharp.Tests/FilterBranchFixture.cs index 60aee38f3..2ca3e507a 100644 --- a/LibGit2Sharp.Tests/FilterBranchFixture.cs +++ b/LibGit2Sharp.Tests/FilterBranchFixture.cs @@ -234,7 +234,7 @@ public void CanRewriteTreesByInjectingTreeEntry() AssertSucceedingButNotError(); - Assert.Equal(new Commit[0], + Assert.Equal(Array.Empty(), repo.Commits .QueryBy(new CommitFilter {IncludeReachableFrom = repo.Branches}) .Where(c => c["README"] != null diff --git a/LibGit2Sharp.Tests/FilterFixture.cs b/LibGit2Sharp.Tests/FilterFixture.cs index 832ca0cad..8fd9c8392 100644 --- a/LibGit2Sharp.Tests/FilterFixture.cs +++ b/LibGit2Sharp.Tests/FilterFixture.cs @@ -396,7 +396,7 @@ private FileInfo CheckoutFileForSmudge(string repoPath, string branchName, strin return expectedPath; } - private static FileInfo CommitFileOnBranch(Repository repo, string branchName, String content) + private static FileInfo CommitFileOnBranch(Repository repo, string branchName, string content) { var branch = repo.CreateBranch(branchName); Commands.Checkout(repo, branch.FriendlyName); diff --git a/LibGit2Sharp.Tests/MetaFixture.cs b/LibGit2Sharp.Tests/MetaFixture.cs index 5ff76e307..1d0a1d101 100644 --- a/LibGit2Sharp.Tests/MetaFixture.cs +++ b/LibGit2Sharp.Tests/MetaFixture.cs @@ -83,7 +83,7 @@ public void TypesInLibGit2DecoratedWithDebuggerDisplayMustFollowTheStandardImplP var typesWithDebuggerDisplayAndInvalidImplPattern = new List(); IEnumerable libGit2SharpTypes = typeof(IRepository).GetTypeInfo().Assembly.GetExportedTypes() - .Where(t => t.GetTypeInfo().GetCustomAttributes(typeof(DebuggerDisplayAttribute), false).Any()); + .Where(t => t.GetTypeInfo().GetCustomAttributes(typeof(DebuggerDisplayAttribute), false).Length != 0); foreach (Type type in libGit2SharpTypes) { @@ -110,7 +110,7 @@ public void TypesInLibGit2DecoratedWithDebuggerDisplayMustFollowTheStandardImplP } } - if (typesWithDebuggerDisplayAndInvalidImplPattern.Any()) + if (typesWithDebuggerDisplayAndInvalidImplPattern.Count != 0) { Assert.Fail(Environment.NewLine + BuildMissingDebuggerDisplayPropertyMessage(typesWithDebuggerDisplayAndInvalidImplPattern)); } @@ -131,7 +131,7 @@ public void TypesInLibGit2SharpMustBeExtensibleInATestingContext() continue; var nonVirtualMethodNamesForType = GetNonVirtualPublicMethodsNames(type).ToList(); - if (nonVirtualMethodNamesForType.Any()) + if (nonVirtualMethodNamesForType.Count != 0) { nonTestableTypes.Add(type, nonVirtualMethodNamesForType); continue; @@ -165,7 +165,7 @@ public void TypesInLibGit2SharpMustBeExtensibleInATestingContext() } } - if (nonTestableTypes.Any()) + if (nonTestableTypes.Count != 0) { Assert.Fail(Environment.NewLine + BuildNonTestableTypesMessage(nonTestableTypes)); } @@ -193,7 +193,7 @@ private static bool MustBeMockable(Type type) public void EnumsWithFlagsHaveMutuallyExclusiveValues() { var flagsEnums = typeof(IRepository).GetTypeInfo().Assembly.GetExportedTypes() - .Where(t => t.GetTypeInfo().IsEnum && t.GetTypeInfo().GetCustomAttributes(typeof(FlagsAttribute), false).Any()); + .Where(t => t.GetTypeInfo().IsEnum && t.GetTypeInfo().GetCustomAttributes(typeof(FlagsAttribute), false).Length != 0); var overlaps = from t in flagsEnums from int x in Enum.GetValues(t) @@ -277,7 +277,7 @@ public void GetEnumeratorMethodsInLibGit2SharpMustBeVirtualForTestability() (!m.IsVirtual || m.IsFinal)) .ToList(); - if (nonVirtualGetEnumeratorMethods.Any()) + if (nonVirtualGetEnumeratorMethods.Count != 0) { var sb = new StringBuilder(); @@ -306,7 +306,7 @@ public void NoPublicTypesUnderLibGit2SharpCoreNamespace() .Where(t => t.FullName != "LibGit2Sharp.Core.LeaksContainer") .ToList(); - if (types.Any()) + if (types.Count != 0) { var sb = new StringBuilder(); diff --git a/LibGit2Sharp.Tests/NetworkFixture.cs b/LibGit2Sharp.Tests/NetworkFixture.cs index 3a3517432..f4ad922f6 100644 --- a/LibGit2Sharp.Tests/NetworkFixture.cs +++ b/LibGit2Sharp.Tests/NetworkFixture.cs @@ -249,7 +249,7 @@ public void CanMergeFetchedRefs() Assert.False(repo.RetrieveStatus().Any()); Assert.Equal(repo.Lookup("refs/remotes/origin/master~1"), repo.Head.Tip); - Commands.Fetch(repo, repo.Head.RemoteName, new string[0], null, null); + Commands.Fetch(repo, repo.Head.RemoteName, Array.Empty(), null, null); MergeOptions mergeOptions = new MergeOptions() { @@ -276,7 +276,7 @@ public void CanPruneRefs() using (var repo = new Repository(clonedRepoPath)) { repo.Network.Remotes.Add("pruner", clonedRepoPath2); - Commands.Fetch(repo, "pruner", new string[0], null, null); + Commands.Fetch(repo, "pruner", Array.Empty(), null, null); Assert.NotNull(repo.Refs["refs/remotes/pruner/master"]); // Remove the branch from the source repository @@ -286,11 +286,11 @@ public void CanPruneRefs() } // and by default we don't prune it - Commands.Fetch(repo, "pruner", new string[0], null, null); + Commands.Fetch(repo, "pruner", Array.Empty(), null, null); 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", Array.Empty(), new FetchOptions { Prune = true }, null); Assert.Null(repo.Refs["refs/remotes/pruner/master"]); } } diff --git a/LibGit2Sharp.Tests/ReferenceFixture.cs b/LibGit2Sharp.Tests/ReferenceFixture.cs index 186d2e869..ad34d0fb2 100644 --- a/LibGit2Sharp.Tests/ReferenceFixture.cs +++ b/LibGit2Sharp.Tests/ReferenceFixture.cs @@ -894,7 +894,7 @@ public void CanHandleInvalidArguments() Assert.Throws(() => repo.Refs.ReachableFrom(null)); Assert.Throws(() => repo.Refs.ReachableFrom(null, repo.Commits.Take(2))); Assert.Throws(() => repo.Refs.ReachableFrom(repo.Refs, null)); - Assert.Empty(repo.Refs.ReachableFrom(new Commit[] { })); + Assert.Empty(repo.Refs.ReachableFrom(Array.Empty())); } } } diff --git a/LibGit2Sharp.Tests/RemoveFixture.cs b/LibGit2Sharp.Tests/RemoveFixture.cs index e97636d9c..921bc417d 100644 --- a/LibGit2Sharp.Tests/RemoveFixture.cs +++ b/LibGit2Sharp.Tests/RemoveFixture.cs @@ -182,7 +182,7 @@ public void RemovingFileWithBadParamsThrows() { Assert.Throws(() => Commands.Remove(repo, string.Empty)); Assert.Throws(() => Commands.Remove(repo, (string)null)); - Assert.Throws(() => Commands.Remove(repo, new string[] { })); + Assert.Throws(() => Commands.Remove(repo, Array.Empty())); Assert.Throws(() => Commands.Remove(repo, new string[] { null })); } } diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs index bf27b6091..ef3e72f07 100644 --- a/LibGit2Sharp.Tests/RepositoryFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryFixture.cs @@ -212,13 +212,13 @@ public void CanFetchFromRemoteByName() } // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null); + Commands.Fetch(repo, remoteName, Array.Empty(), new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null); // Verify the expected state expectedFetchState.CheckUpdatedReferences(repo); // Now fetch the rest of the tags - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { TagFetchMode = TagFetchMode.All }, null); + Commands.Fetch(repo, remoteName, Array.Empty(), new FetchOptions { TagFetchMode = TagFetchMode.All }, null); // Verify that the "nearly-dangling" tag is now in the repo. Tag nearlyDanglingTag = repo.Tags["nearly-dangling"]; diff --git a/LibGit2Sharp.Tests/StageFixture.cs b/LibGit2Sharp.Tests/StageFixture.cs index 51cb31a51..c087aa7be 100644 --- a/LibGit2Sharp.Tests/StageFixture.cs +++ b/LibGit2Sharp.Tests/StageFixture.cs @@ -265,7 +265,7 @@ public void StagingFileWithBadParamsThrows() { Assert.Throws(() => Commands.Stage(repo, string.Empty)); Assert.Throws(() => Commands.Stage(repo, (string)null)); - Assert.Throws(() => Commands.Stage(repo, new string[] { })); + Assert.Throws(() => Commands.Stage(repo, Array.Empty())); Assert.Throws(() => Commands.Stage(repo, new string[] { null })); } } @@ -362,7 +362,7 @@ public void IgnoredFilesAreOnlyStagedIfTheyreInTheRepo(string filename, FileStat using (var repo = new Repository(path)) { File.WriteAllText(Path.Combine(repo.Info.WorkingDirectory, ".gitignore"), - String.Format("{0}\n", filename)); + string.Format("{0}\n", filename)); Commands.Stage(repo, filename); Assert.Equal(expected, repo.RetrieveStatus(filename)); @@ -384,7 +384,7 @@ public void CanStageConflictedIgnoredFiles(string filename, FileStatus expected) using (var repo = new Repository(path)) { File.WriteAllText(Path.Combine(repo.Info.WorkingDirectory, ".gitignore"), - String.Format("{0}\n", filename)); + string.Format("{0}\n", filename)); Commands.Stage(repo, filename); Assert.Equal(expected, repo.RetrieveStatus(filename)); diff --git a/LibGit2Sharp.Tests/TestHelpers/Constants.cs b/LibGit2Sharp.Tests/TestHelpers/Constants.cs index b5cd96d7e..d8c14dbca 100644 --- a/LibGit2Sharp.Tests/TestHelpers/Constants.cs +++ b/LibGit2Sharp.Tests/TestHelpers/Constants.cs @@ -61,10 +61,10 @@ public static string BuildPath() if (Environment.GetEnvironmentVariables().Contains(LibGit2TestPath)) { Trace.TraceInformation("{0} environment variable detected", LibGit2TestPath); - tempPath = Environment.GetEnvironmentVariables()[LibGit2TestPath] as String; + tempPath = Environment.GetEnvironmentVariables()[LibGit2TestPath] as string; } - if (String.IsNullOrWhiteSpace(tempPath) || !Directory.Exists(tempPath)) + if (string.IsNullOrWhiteSpace(tempPath) || !Directory.Exists(tempPath)) { Trace.TraceInformation("Using default test path value"); tempPath = Path.GetTempPath(); diff --git a/LibGit2Sharp.Tests/UnstageFixture.cs b/LibGit2Sharp.Tests/UnstageFixture.cs index a5dc143d3..1eeee0e72 100644 --- a/LibGit2Sharp.Tests/UnstageFixture.cs +++ b/LibGit2Sharp.Tests/UnstageFixture.cs @@ -251,7 +251,7 @@ public void UnstagingFileWithBadParamsThrows() { Assert.Throws(() => Commands.Unstage(repo, string.Empty)); Assert.Throws(() => Commands.Unstage(repo, (string)null)); - Assert.Throws(() => Commands.Unstage(repo, new string[] { })); + Assert.Throws(() => Commands.Unstage(repo, Array.Empty())); Assert.Throws(() => Commands.Unstage(repo, new string[] { null })); } } diff --git a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs index bc7e7ac15..4e3b03ce3 100644 --- a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs +++ b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs @@ -61,7 +61,7 @@ public void CustomSmartSubtransportTest(string scheme, string url) } // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], + Commands.Fetch(repo, remoteName, Array.Empty(), new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler, TagFetchMode = TagFetchMode.Auto }, null); @@ -161,29 +161,29 @@ public void CannotUnregisterTwice() private class MockSmartSubtransport : RpcSmartSubtransport { - protected override SmartSubtransportStream Action(String url, GitSmartSubtransportAction action) + protected override SmartSubtransportStream Action(string url, GitSmartSubtransportAction action) { - String endpointUrl, contentType = null; + string endpointUrl, contentType = null; bool isPost = false; switch (action) { case GitSmartSubtransportAction.UploadPackList: - endpointUrl = String.Concat(url, "/info/refs?service=git-upload-pack"); + endpointUrl = string.Concat(url, "/info/refs?service=git-upload-pack"); break; case GitSmartSubtransportAction.UploadPack: - endpointUrl = String.Concat(url, "/git-upload-pack"); + 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"); + endpointUrl = string.Concat(url, "/info/refs?service=git-receive-pack"); break; case GitSmartSubtransportAction.ReceivePack: - endpointUrl = String.Concat(url, "/git-receive-pack"); + endpointUrl = string.Concat(url, "/git-receive-pack"); contentType = "application/x-git-receive-pack-request"; isPost = true; break; diff --git a/LibGit2Sharp/AmbiguousSpecificationException.cs b/LibGit2Sharp/AmbiguousSpecificationException.cs index 4903d9df9..b5ddd7963 100644 --- a/LibGit2Sharp/AmbiguousSpecificationException.cs +++ b/LibGit2Sharp/AmbiguousSpecificationException.cs @@ -31,7 +31,7 @@ public AmbiguousSpecificationException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public AmbiguousSpecificationException(string format, params object[] args) : base(string.Format(format, args)) diff --git a/LibGit2Sharp/BareRepositoryException.cs b/LibGit2Sharp/BareRepositoryException.cs index 461204acd..412e5e4d4 100644 --- a/LibGit2Sharp/BareRepositoryException.cs +++ b/LibGit2Sharp/BareRepositoryException.cs @@ -32,7 +32,7 @@ public BareRepositoryException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public BareRepositoryException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/BlameHunk.cs b/LibGit2Sharp/BlameHunk.cs index 553efb14e..4feac239d 100644 --- a/LibGit2Sharp/BlameHunk.cs +++ b/LibGit2Sharp/BlameHunk.cs @@ -135,10 +135,10 @@ public bool Equals(BlameHunk other) } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as BlameHunk); diff --git a/LibGit2Sharp/BlameHunkCollection.cs b/LibGit2Sharp/BlameHunkCollection.cs index 869daf527..2766ee7a6 100644 --- a/LibGit2Sharp/BlameHunkCollection.cs +++ b/LibGit2Sharp/BlameHunkCollection.cs @@ -82,7 +82,7 @@ public virtual BlameHunk HunkForLine(int line) { return hunk; } - throw new ArgumentOutOfRangeException("line", "No hunk for that line"); + throw new ArgumentOutOfRangeException(nameof(line), "No hunk for that line"); } /// diff --git a/LibGit2Sharp/Blob.cs b/LibGit2Sharp/Blob.cs index d3cccf6ac..29ef8d812 100644 --- a/LibGit2Sharp/Blob.cs +++ b/LibGit2Sharp/Blob.cs @@ -13,7 +13,7 @@ namespace LibGit2Sharp /// public class Blob : GitObject { - private readonly ILazy lazySize; + private readonly ILazy lazySize; private readonly ILazy lazyIsBinary; /// diff --git a/LibGit2Sharp/CheckoutConflictException.cs b/LibGit2Sharp/CheckoutConflictException.cs index 23b97143e..67dc8d2cc 100644 --- a/LibGit2Sharp/CheckoutConflictException.cs +++ b/LibGit2Sharp/CheckoutConflictException.cs @@ -33,7 +33,7 @@ public CheckoutConflictException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public CheckoutConflictException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/Commands/Pull.cs b/LibGit2Sharp/Commands/Pull.cs index bee1bbbda..f0a68fe9b 100644 --- a/LibGit2Sharp/Commands/Pull.cs +++ b/LibGit2Sharp/Commands/Pull.cs @@ -1,5 +1,4 @@ using System; -using LibGit2Sharp; using LibGit2Sharp.Core; namespace LibGit2Sharp @@ -34,7 +33,7 @@ public static MergeResult Pull(Repository repository, Signature merger, PullOpti throw new LibGit2SharpException("No upstream remote for the current branch."); } - Commands.Fetch(repository, currentBranch.RemoteName, new string[0], options.FetchOptions, null); + Commands.Fetch(repository, currentBranch.RemoteName, Array.Empty(), options.FetchOptions, null); return repository.MergeFetchedRefs(merger, options.MergeOptions); } } diff --git a/LibGit2Sharp/Commands/Stage.cs b/LibGit2Sharp/Commands/Stage.cs index a1febafcb..d11bf6f76 100644 --- a/LibGit2Sharp/Commands/Stage.cs +++ b/LibGit2Sharp/Commands/Stage.cs @@ -237,7 +237,7 @@ public static void Move(IRepository repository, IEnumerable sourcePaths, if (batch.Count == 0) { - throw new ArgumentNullException("sourcePaths"); + throw new ArgumentNullException(nameof(sourcePaths)); } foreach (KeyValuePair, Tuple> keyValuePair in batch) diff --git a/LibGit2Sharp/Conflict.cs b/LibGit2Sharp/Conflict.cs index 252535af1..705f66d15 100644 --- a/LibGit2Sharp/Conflict.cs +++ b/LibGit2Sharp/Conflict.cs @@ -61,12 +61,12 @@ public virtual IndexEntry Theirs } /// - /// Determines whether the specified is + /// Determines whether the specified is /// equal to the current . /// - /// The to compare with + /// The to compare with /// the current . - /// true if the specified is equal + /// true if the specified is equal /// to the current ; otherwise, /// false. public override bool Equals(object obj) diff --git a/LibGit2Sharp/Core/EncodingMarshaler.cs b/LibGit2Sharp/Core/EncodingMarshaler.cs index 0cafd9aa1..cb02c649b 100644 --- a/LibGit2Sharp/Core/EncodingMarshaler.cs +++ b/LibGit2Sharp/Core/EncodingMarshaler.cs @@ -32,7 +32,7 @@ public int GetNativeDataSize() return -1; } - public virtual IntPtr MarshalManagedToNative(Object managedObj) + public virtual IntPtr MarshalManagedToNative(object managedObj) { if (managedObj == null) { @@ -51,14 +51,14 @@ public virtual IntPtr MarshalManagedToNative(Object managedObj) return FromManaged(encoding, str); } - public virtual Object MarshalNativeToManaged(IntPtr pNativeData) + public virtual object MarshalNativeToManaged(IntPtr pNativeData) { return FromNative(encoding, pNativeData); } #endregion - public static unsafe IntPtr FromManaged(Encoding encoding, String value) + public static unsafe IntPtr FromManaged(Encoding encoding, string value) { if (encoding == null || value == null) { @@ -114,10 +114,10 @@ public static unsafe string FromNative(Encoding encoding, byte* pNativeData) if (walk == start) { - return String.Empty; + return string.Empty; } - return new String((sbyte*)pNativeData, 0, (int)(walk - start), encoding); + return new string((sbyte*)pNativeData, 0, (int)(walk - start), encoding); } public static unsafe string FromNative(Encoding encoding, IntPtr pNativeData, int length) @@ -129,10 +129,10 @@ public static unsafe string FromNative(Encoding encoding, IntPtr pNativeData, in if (length == 0) { - return String.Empty; + return string.Empty; } - return new String((sbyte*)pNativeData.ToPointer(), 0, length, encoding); + return new string((sbyte*)pNativeData.ToPointer(), 0, length, encoding); } public static string FromBuffer(Encoding encoding, byte[] buffer) @@ -160,7 +160,7 @@ public static string FromBuffer(Encoding encoding, byte[] buffer, int length) if (length == 0) { - return String.Empty; + return string.Empty; } return encoding.GetString(buffer, 0, length); diff --git a/LibGit2Sharp/Core/Ensure.cs b/LibGit2Sharp/Core/Ensure.cs index 3cf03d24b..7adea961a 100644 --- a/LibGit2Sharp/Core/Ensure.cs +++ b/LibGit2Sharp/Core/Ensure.cs @@ -49,7 +49,7 @@ public static void ArgumentNotNullOrEmptyString(string argumentValue, string arg { ArgumentNotNull(argumentValue, argumentName); - if (String.IsNullOrWhiteSpace (argumentValue)) + if (string.IsNullOrWhiteSpace (argumentValue)) { throw new ArgumentException("String cannot be empty", argumentName); } diff --git a/LibGit2Sharp/Core/FileHistory.cs b/LibGit2Sharp/Core/FileHistory.cs index 5c10a1a24..5775d0ab8 100644 --- a/LibGit2Sharp/Core/FileHistory.cs +++ b/LibGit2Sharp/Core/FileHistory.cs @@ -74,7 +74,7 @@ internal FileHistory(Repository repo, string path, CommitFilter queryFilter) if (!AllowedSortStrategies.Contains(queryFilter.SortBy)) { throw new ArgumentException("Unsupported sort strategy. Only 'Topological', 'Time', or 'Topological | Time' are allowed.", - "queryFilter"); + nameof(queryFilter)); } _repo = repo; diff --git a/LibGit2Sharp/Core/FilePathMarshaler.cs b/LibGit2Sharp/Core/FilePathMarshaler.cs index 209254ac5..af6afb048 100644 --- a/LibGit2Sharp/Core/FilePathMarshaler.cs +++ b/LibGit2Sharp/Core/FilePathMarshaler.cs @@ -57,7 +57,7 @@ internal class StrictFilePathMarshaler : StrictUtf8Marshaler #region ICustomMarshaler - public override IntPtr MarshalManagedToNative(Object managedObj) + public override IntPtr MarshalManagedToNative(object managedObj) { if (null == managedObj) { @@ -105,7 +105,7 @@ internal class LaxFilePathMarshaler : LaxUtf8Marshaler #region ICustomMarshaler - public override Object MarshalNativeToManaged(IntPtr pNativeData) + public override object MarshalNativeToManaged(IntPtr pNativeData) { return FromNative(pNativeData); } diff --git a/LibGit2Sharp/Core/GitBlame.cs b/LibGit2Sharp/Core/GitBlame.cs index df99f44b7..b2683cc73 100644 --- a/LibGit2Sharp/Core/GitBlame.cs +++ b/LibGit2Sharp/Core/GitBlame.cs @@ -46,7 +46,7 @@ internal class git_blame_options public uint version = 1; public GitBlameOptionFlags flags; - public UInt16 min_match_characters; + public ushort min_match_characters; public git_oid newest_commit; public git_oid oldest_commit; public UIntPtr min_line; diff --git a/LibGit2Sharp/Core/GitDiff.cs b/LibGit2Sharp/Core/GitDiff.cs index cc1ab1af1..44679124d 100644 --- a/LibGit2Sharp/Core/GitDiff.cs +++ b/LibGit2Sharp/Core/GitDiff.cs @@ -231,7 +231,7 @@ internal class GitDiffOptions : IDisposable public uint ContextLines; public uint InterhunkLines; public ushort IdAbbrev; - public Int64 MaxSize; + public long MaxSize; public IntPtr OldPrefixString; public IntPtr NewPrefixString; @@ -255,10 +255,10 @@ internal unsafe struct git_diff_file { public git_oid Id; public char* Path; - public Int64 Size; + public long Size; public GitDiffFlags Flags; - public UInt16 Mode; - public UInt16 IdAbbrev; + public ushort Mode; + public ushort IdAbbrev; } [StructLayout(LayoutKind.Sequential)] @@ -266,8 +266,8 @@ internal unsafe struct git_diff_delta { public ChangeKind status; public GitDiffFlags flags; - public UInt16 similarity; - public UInt16 nfiles; + public ushort similarity; + public ushort nfiles; public git_diff_file old_file; public git_diff_file new_file; } @@ -293,7 +293,7 @@ internal class GitDiffLine public int NewLineNo; public int NumLines; public UIntPtr contentLen; - public Int64 contentOffset; + public long contentOffset; public IntPtr content; } @@ -371,10 +371,10 @@ internal class GitDiffFindOptions { public uint Version = 1; public GitDiffFindFlags Flags; - public UInt16 RenameThreshold; - public UInt16 RenameFromRewriteThreshold; - public UInt16 CopyThreshold; - public UInt16 BreakRewriteThreshold; + public ushort RenameThreshold; + public ushort RenameFromRewriteThreshold; + public ushort CopyThreshold; + public ushort BreakRewriteThreshold; public UIntPtr RenameLimit; // TODO diff --git a/LibGit2Sharp/Core/GitOdbBackend.cs b/LibGit2Sharp/Core/GitOdbBackend.cs index 6f017542d..c102c94eb 100644 --- a/LibGit2Sharp/Core/GitOdbBackend.cs +++ b/LibGit2Sharp/Core/GitOdbBackend.cs @@ -137,7 +137,7 @@ public delegate int write_callback( public delegate int writestream_callback( out IntPtr stream_out, IntPtr backend, - Int64 length, + long length, GitObjectType type); /// diff --git a/LibGit2Sharp/Core/GitOdbBackendStream.cs b/LibGit2Sharp/Core/GitOdbBackendStream.cs index 984274f04..14b126c7a 100644 --- a/LibGit2Sharp/Core/GitOdbBackendStream.cs +++ b/LibGit2Sharp/Core/GitOdbBackendStream.cs @@ -22,8 +22,8 @@ static GitOdbBackendStream() public GitOdbBackendStreamMode Mode; public IntPtr HashCtx; - public Int64 DeclaredSize; - public Int64 ReceivedBytes; + public long DeclaredSize; + public long ReceivedBytes; public read_callback Read; public write_callback Write; diff --git a/LibGit2Sharp/Core/GitStrArrayNative.cs b/LibGit2Sharp/Core/GitStrArrayNative.cs index 8813f8e6e..01cd18e6e 100644 --- a/LibGit2Sharp/Core/GitStrArrayNative.cs +++ b/LibGit2Sharp/Core/GitStrArrayNative.cs @@ -15,11 +15,11 @@ internal struct GitStrArrayNative : IDisposable /// /// Enumerates each string from the array using the UTF-8 marshaler. /// - public String[] ReadStrings() + public string[] ReadStrings() { var count = checked((int)Array.Count.ToUInt32()); - String[] toReturn = new String[count]; + string[] toReturn = new string[count]; for (int i = 0; i < count; i++) { diff --git a/LibGit2Sharp/Core/HistoryRewriter.cs b/LibGit2Sharp/Core/HistoryRewriter.cs index c4cc2be8b..094d5ca1c 100644 --- a/LibGit2Sharp/Core/HistoryRewriter.cs +++ b/LibGit2Sharp/Core/HistoryRewriter.cs @@ -170,7 +170,7 @@ private Reference RewriteReference( if (repo.Refs.Resolve(backupName) != null) { - throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, + throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Can't back up reference '{0}' - '{1}' already exists", oldRef.CanonicalName, backupName)); diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index cd3e1de7a..e8e59843e 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -177,11 +177,11 @@ internal static extern int git_error_set_str( internal static extern void git_error_set_oom(); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe UInt32 git_blame_get_hunk_count(git_blame* blame); + internal static extern unsafe uint git_blame_get_hunk_count(git_blame* blame); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe git_blame_hunk* git_blame_get_hunk_byindex( - git_blame* blame, UInt32 index); + git_blame* blame, uint index); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_blame_file( @@ -227,7 +227,7 @@ internal static extern unsafe int git_blob_filtered_content( internal static extern unsafe IntPtr git_blob_rawcontent(git_object* blob); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe Int64 git_blob_rawsize(git_object* blob); + internal static extern unsafe long git_blob_rawsize(git_object* blob); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_branch_create_from_annotated( @@ -1078,7 +1078,7 @@ internal static extern unsafe int git_odb_foreach( IntPtr payload); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe int git_odb_open_wstream(out git_odb_stream* stream, git_odb* odb, Int64 size, GitObjectType type); + internal static extern unsafe int git_odb_open_wstream(out git_odb_stream* stream, git_odb* odb, long size, GitObjectType type); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe void git_odb_free(git_odb* odb); @@ -1175,7 +1175,7 @@ internal static extern unsafe int git_packbuilder_insert_tree( internal static extern unsafe UIntPtr git_packbuilder_object_count(git_packbuilder* packbuilder); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe UInt32 git_packbuilder_set_threads(git_packbuilder* packbuilder, UInt32 numThreads); + internal static extern unsafe uint git_packbuilder_set_threads(git_packbuilder* packbuilder, uint numThreads); [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern unsafe int git_packbuilder_write( diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 50cefc0df..18e952e68 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -86,7 +86,7 @@ public static unsafe UnmanagedMemoryStream git_blob_filtered_content_stream(Repo new[] { buf }); } - public static unsafe UnmanagedMemoryStream git_blob_rawcontent_stream(RepositoryHandle repo, ObjectId id, Int64 size) + public static unsafe UnmanagedMemoryStream git_blob_rawcontent_stream(RepositoryHandle repo, ObjectId id, long size) { var handle = new ObjectSafeWrapper(id, repo, throwIfMissing: true).ObjectPtr; return new RawContentStream(handle, h => NativeMethods.git_blob_rawcontent(h), h => size); @@ -341,7 +341,7 @@ public static unsafe string git_commit_create_buffer( using (var treeHandle = Proxy.git_object_lookup(tree.repo.Handle, tree.Id, GitObjectType.Tree)) using (var buf = new GitBuf()) { - ObjectHandle[] handles = new ObjectHandle[0]; + ObjectHandle[] handles = Array.Empty(); try { handles = parents.Select(c => Proxy.git_object_lookup(c.repo.Handle, c.Id, GitObjectType.Commit)).ToArray(); @@ -871,7 +871,7 @@ public static int git_error_set_str(GitErrorCategory error_class, Exception exce } } - public static int git_error_set_str(GitErrorCategory error_class, String errorString) + public static int git_error_set_str(GitErrorCategory error_class, string errorString) { return NativeMethods.git_error_set_str(error_class, errorString); } @@ -2368,7 +2368,7 @@ public static unsafe IEnumerable git_remote_ls(Repository repository, } var refs = directRefs.Values.ToList(); - refs.Sort((r1, r2) => String.CompareOrdinal(r1.CanonicalName, r2.CanonicalName)); + refs.Sort((r1, r2) => string.CompareOrdinal(r1.CanonicalName, r2.CanonicalName)); return refs; } @@ -3211,7 +3211,7 @@ public static void git_trace_set(LogLevel level, NativeMethods.git_trace_cb call #region git_transport_ - public static void git_transport_register(String prefix, IntPtr transport_cb, IntPtr param) + public static void git_transport_register(string prefix, IntPtr transport_cb, IntPtr param) { int res = NativeMethods.git_transport_register(prefix, transport_cb, param); @@ -3224,7 +3224,7 @@ public static void git_transport_register(String prefix, IntPtr transport_cb, In Ensure.ZeroResult(res); } - public static void git_transport_unregister(String prefix) + public static void git_transport_unregister(string prefix) { int res = NativeMethods.git_transport_unregister(prefix); @@ -3707,7 +3707,7 @@ private static ICollection git_foreach( if (ignoredErrorCodes != null && ignoredErrorCodes.Contains((GitErrorCode)res)) { - return new TResult[0]; + return Array.Empty(); } Ensure.ZeroResult(res); @@ -3728,7 +3728,7 @@ private static ICollection git_foreach( if (ignoredErrorCodes != null && ignoredErrorCodes.Contains((GitErrorCode)res)) { - return new TResult[0]; + return Array.Empty(); } Ensure.ZeroResult(res); @@ -3749,7 +3749,7 @@ private static ICollection git_foreach( if (ignoredErrorCodes != null && ignoredErrorCodes.Contains((GitErrorCode)res)) { - return new TResult[0]; + return Array.Empty(); } Ensure.ZeroResult(res); @@ -3772,7 +3772,7 @@ private static ICollection git_foreach( if (ignoredErrorCodes != null && ignoredErrorCodes.Contains((GitErrorCode)res)) { - return new TResult[0]; + return Array.Empty(); } Ensure.ZeroResult(res); diff --git a/LibGit2Sharp/Core/TarWriter.cs b/LibGit2Sharp/Core/TarWriter.cs index 609449316..0a051b9e6 100644 --- a/LibGit2Sharp/Core/TarWriter.cs +++ b/LibGit2Sharp/Core/TarWriter.cs @@ -301,31 +301,31 @@ public UsTarHeader( if (userName.Length > 32) { - throw new ArgumentException("ustar userName cannot be longer than 32 characters.", "userName"); + throw new ArgumentException("ustar userName cannot be longer than 32 characters.", nameof(userName)); } if (groupName.Length > 32) { - throw new ArgumentException("ustar groupName cannot be longer than 32 characters.", "groupName"); + throw new ArgumentException("ustar groupName cannot be longer than 32 characters.", nameof(groupName)); } if (userId.Length > 7) { - throw new ArgumentException("ustar userId cannot be longer than 7 characters.", "userId"); + throw new ArgumentException("ustar userId cannot be longer than 7 characters.", nameof(userId)); } if (groupId.Length > 7) { - throw new ArgumentException("ustar groupId cannot be longer than 7 characters.", "groupId"); + throw new ArgumentException("ustar groupId cannot be longer than 7 characters.", nameof(groupId)); } if (deviceMajorNumber.Length > 7) { - throw new ArgumentException("ustar deviceMajorNumber cannot be longer than 7 characters.", "deviceMajorNumber"); + throw new ArgumentException("ustar deviceMajorNumber cannot be longer than 7 characters.", nameof(deviceMajorNumber)); } if (deviceMinorNumber.Length > 7) { - throw new ArgumentException("ustar deviceMinorNumber cannot be longer than 7 characters.", "deviceMinorNumber"); + throw new ArgumentException("ustar deviceMinorNumber cannot be longer than 7 characters.", nameof(deviceMinorNumber)); } if (link.Length > 100) { - throw new ArgumentException("ustar link cannot be longer than 100 characters.", "link"); + throw new ArgumentException("ustar link cannot be longer than 100 characters.", nameof(link)); } #endregion diff --git a/LibGit2Sharp/Core/Utf8Marshaler.cs b/LibGit2Sharp/Core/Utf8Marshaler.cs index a6fddb808..54e0086cb 100644 --- a/LibGit2Sharp/Core/Utf8Marshaler.cs +++ b/LibGit2Sharp/Core/Utf8Marshaler.cs @@ -67,7 +67,7 @@ public static ICustomMarshaler GetInstance(string cookie) #region ICustomMarshaler - public override Object MarshalNativeToManaged(IntPtr pNativeData) + public override object MarshalNativeToManaged(IntPtr pNativeData) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "{0} cannot be used to retrieve data from libgit2.", @@ -76,7 +76,7 @@ public override Object MarshalNativeToManaged(IntPtr pNativeData) #endregion - public static IntPtr FromManaged(String value) + public static IntPtr FromManaged(string value) { return FromManaged(encoding, value); } diff --git a/LibGit2Sharp/Diff.cs b/LibGit2Sharp/Diff.cs index 087ee8d6d..857eb8ed1 100644 --- a/LibGit2Sharp/Diff.cs +++ b/LibGit2Sharp/Diff.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Text; using LibGit2Sharp.Core; @@ -546,7 +545,7 @@ private DiffHandle BuildDiffList( MatchedPathsAggregator matchedPaths = null; - // We can't match paths unless we've got something to match + // We can't match paths unless we've got something to match // against and we're told to do so. if (filePaths != null && explicitPathsOptions != null) { @@ -653,7 +652,7 @@ private static void DispatchUnmatchedPaths( List unmatchedPaths = (filePaths != null ? filePaths.Except(matchedPaths) : Enumerable.Empty()).ToList(); - if (!unmatchedPaths.Any()) + if (unmatchedPaths.Count == 0) { return; } diff --git a/LibGit2Sharp/EmptyCommitException.cs b/LibGit2Sharp/EmptyCommitException.cs index 0c247bec7..00d1081e5 100644 --- a/LibGit2Sharp/EmptyCommitException.cs +++ b/LibGit2Sharp/EmptyCommitException.cs @@ -31,7 +31,7 @@ public EmptyCommitException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public EmptyCommitException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/EntryExistsException.cs b/LibGit2Sharp/EntryExistsException.cs index 8039f5edd..3ebfbdfba 100644 --- a/LibGit2Sharp/EntryExistsException.cs +++ b/LibGit2Sharp/EntryExistsException.cs @@ -32,7 +32,7 @@ public EntryExistsException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public EntryExistsException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/FetchHead.cs b/LibGit2Sharp/FetchHead.cs index 456abedc2..812865cf3 100644 --- a/LibGit2Sharp/FetchHead.cs +++ b/LibGit2Sharp/FetchHead.cs @@ -61,7 +61,7 @@ public virtual GitObject Target /// The URL of the remote repository this /// has been built from. /// - public virtual String Url { get; private set; } + public virtual string Url { get; private set; } /// /// Determines if this fetch head entry has been explicitly fetched. diff --git a/LibGit2Sharp/Filter.cs b/LibGit2Sharp/Filter.cs index 5a46e12b5..50f5fe8c5 100644 --- a/LibGit2Sharp/Filter.cs +++ b/LibGit2Sharp/Filter.cs @@ -165,10 +165,10 @@ protected virtual void Smudge(string path, string root, Stream input, Stream out } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as Filter); @@ -306,7 +306,7 @@ int StreamCloseCallback(IntPtr stream) if(!activeStreams.TryGetValue(stream, out state)) { - throw new ArgumentException("Unknown stream pointer", "stream"); + throw new ArgumentException("Unknown stream pointer", nameof(stream)); } Ensure.ArgumentIsExpectedIntPtr(stream, state.thisPtr, "stream"); @@ -339,7 +339,7 @@ void StreamFreeCallback(IntPtr stream) if (!activeStreams.TryRemove(stream, out state)) { - throw new ArgumentException("Double free or invalid stream pointer", "stream"); + throw new ArgumentException("Double free or invalid stream pointer", nameof(stream)); } Ensure.ArgumentIsExpectedIntPtr(stream, state.thisPtr, "stream"); @@ -365,7 +365,7 @@ unsafe int StreamWriteCallback(IntPtr stream, IntPtr buffer, UIntPtr len) if (!activeStreams.TryGetValue(stream, out state)) { - throw new ArgumentException("Invalid or already freed stream pointer", "stream"); + throw new ArgumentException("Invalid or already freed stream pointer", nameof(stream)); } Ensure.ArgumentIsExpectedIntPtr(stream, state.thisPtr, "stream"); diff --git a/LibGit2Sharp/GitObject.cs b/LibGit2Sharp/GitObject.cs index 539fe6f8b..f9813a3ea 100644 --- a/LibGit2Sharp/GitObject.cs +++ b/LibGit2Sharp/GitObject.cs @@ -129,10 +129,10 @@ public virtual T Peel() where T : GitObject } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as GitObject); @@ -180,7 +180,7 @@ public override int GetHashCode() } /// - /// Returns the , a representation of the current . + /// Returns the , a representation of the current . /// /// The that represents the current . public override string ToString() diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index 31cba0965..bf7875f96 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -247,9 +247,9 @@ public static FilterRegistration RegisterFilter(Filter filter, int priority) Ensure.ArgumentNotNull(filter, "filter"); if (priority < FilterRegistration.FilterPriorityMin || priority > FilterRegistration.FilterPriorityMax) { - throw new ArgumentOutOfRangeException("priority", + throw new ArgumentOutOfRangeException(nameof(priority), priority, - String.Format(System.Globalization.CultureInfo.InvariantCulture, + string.Format(System.Globalization.CultureInfo.InvariantCulture, "Filter priorities must be within the inclusive range of [{0}, {1}].", FilterRegistration.FilterPriorityMin, FilterRegistration.FilterPriorityMax)); diff --git a/LibGit2Sharp/IndexEntry.cs b/LibGit2Sharp/IndexEntry.cs index e07e284b7..554d9a9f1 100644 --- a/LibGit2Sharp/IndexEntry.cs +++ b/LibGit2Sharp/IndexEntry.cs @@ -60,10 +60,10 @@ internal static unsafe IndexEntry BuildFromPtr(git_index_entry* entry) } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as IndexEntry); diff --git a/LibGit2Sharp/IndexNameEntry.cs b/LibGit2Sharp/IndexNameEntry.cs index 79b3f6993..40c202acc 100644 --- a/LibGit2Sharp/IndexNameEntry.cs +++ b/LibGit2Sharp/IndexNameEntry.cs @@ -63,10 +63,10 @@ internal static unsafe IndexNameEntry BuildFromPtr(git_index_name_entry* entry) public virtual string Theirs { get; private set; } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as IndexNameEntry); diff --git a/LibGit2Sharp/IndexReucEntry.cs b/LibGit2Sharp/IndexReucEntry.cs index 583df95ba..becd20122 100644 --- a/LibGit2Sharp/IndexReucEntry.cs +++ b/LibGit2Sharp/IndexReucEntry.cs @@ -88,10 +88,10 @@ internal static unsafe IndexReucEntry BuildFromPtr(git_index_reuc_entry* entry) public virtual Mode TheirMode { get; private set; } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as IndexReucEntry); diff --git a/LibGit2Sharp/InvalidSpecificationException.cs b/LibGit2Sharp/InvalidSpecificationException.cs index 573a8a1db..d9625dc32 100644 --- a/LibGit2Sharp/InvalidSpecificationException.cs +++ b/LibGit2Sharp/InvalidSpecificationException.cs @@ -34,7 +34,7 @@ public InvalidSpecificationException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public InvalidSpecificationException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/LibGit2SharpException.cs b/LibGit2Sharp/LibGit2SharpException.cs index e5d90f61f..0518fa757 100644 --- a/LibGit2Sharp/LibGit2SharpException.cs +++ b/LibGit2Sharp/LibGit2SharpException.cs @@ -40,7 +40,7 @@ public LibGit2SharpException(string message, Exception innerException) /// /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public LibGit2SharpException(string format, params object[] args) : base(string.Format(CultureInfo.InvariantCulture, format, args)) diff --git a/LibGit2Sharp/LockedFileException.cs b/LibGit2Sharp/LockedFileException.cs index d58c8dbec..b38f40496 100644 --- a/LibGit2Sharp/LockedFileException.cs +++ b/LibGit2Sharp/LockedFileException.cs @@ -31,7 +31,7 @@ public LockedFileException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public LockedFileException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/MergeFetchHeadNotFoundException.cs b/LibGit2Sharp/MergeFetchHeadNotFoundException.cs index 34b6b71aa..d7d761c1d 100644 --- a/LibGit2Sharp/MergeFetchHeadNotFoundException.cs +++ b/LibGit2Sharp/MergeFetchHeadNotFoundException.cs @@ -30,7 +30,7 @@ public MergeFetchHeadNotFoundException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public MergeFetchHeadNotFoundException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/NameConflictException.cs b/LibGit2Sharp/NameConflictException.cs index 0f4dde744..0517f2550 100644 --- a/LibGit2Sharp/NameConflictException.cs +++ b/LibGit2Sharp/NameConflictException.cs @@ -31,7 +31,7 @@ public NameConflictException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public NameConflictException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/NonFastForwardException.cs b/LibGit2Sharp/NonFastForwardException.cs index f63e2eb1d..d8ed8f474 100644 --- a/LibGit2Sharp/NonFastForwardException.cs +++ b/LibGit2Sharp/NonFastForwardException.cs @@ -32,7 +32,7 @@ public NonFastForwardException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public NonFastForwardException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/NotFoundException.cs b/LibGit2Sharp/NotFoundException.cs index 4aefe3f8a..f282c4340 100644 --- a/LibGit2Sharp/NotFoundException.cs +++ b/LibGit2Sharp/NotFoundException.cs @@ -31,7 +31,7 @@ public NotFoundException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public NotFoundException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/Note.cs b/LibGit2Sharp/Note.cs index 1df0125e4..2ffc89690 100644 --- a/LibGit2Sharp/Note.cs +++ b/LibGit2Sharp/Note.cs @@ -59,10 +59,10 @@ internal static Note BuildFromPtr(NoteHandle note, string @namespace, ObjectId t } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as Note); diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index b48c72a99..42b65d7d0 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -199,7 +199,7 @@ public virtual ObjectId Write(Stream stream, long numberOfBytesToConsume) whe if (!stream.CanRead) { - throw new ArgumentException("The stream cannot be read from.", "stream"); + throw new ArgumentException("The stream cannot be read from.", nameof(stream)); } using (var odbStream = Proxy.git_odb_open_wstream(handle, numberOfBytesToConsume, GitObjectType.Blob)) @@ -274,7 +274,7 @@ private unsafe Blob CreateBlob(Stream stream, string hintpath, long? numberOfByt if (!stream.CanRead) { - throw new ArgumentException("The stream cannot be read from.", "stream"); + throw new ArgumentException("The stream cannot be read from.", nameof(stream)); } IntPtr writestream_ptr = Proxy.git_blob_create_from_stream(repo.Handle, hintpath); @@ -588,7 +588,7 @@ public virtual MergeTreeResult CherryPickCommit(Commit cherryPickCommit, Commit // Stopped due to FailOnConflict so there's no index or conflict list if (earlyStop) { - return new MergeTreeResult(new Conflict[] { }); + return new MergeTreeResult(Array.Empty()); } if (Proxy.git_index_has_conflicts(indexHandle)) @@ -639,7 +639,7 @@ public virtual string ShortenObjectId(GitObject gitObject, int minLength) if (minLength <= 0 || minLength > ObjectId.HexSize) { - throw new ArgumentOutOfRangeException("minLength", + throw new ArgumentOutOfRangeException(nameof(minLength), minLength, string.Format("Expected value should be greater than zero and less than or equal to {0}.", ObjectId.HexSize)); @@ -714,7 +714,7 @@ public virtual Commit FindMergeBase(IEnumerable commits, MergeBaseFindin { if (commit == null) { - throw new ArgumentException("Enumerable contains null at position: " + count.ToString(CultureInfo.InvariantCulture), "commits"); + throw new ArgumentException("Enumerable contains null at position: " + count.ToString(CultureInfo.InvariantCulture), nameof(commits)); } ids.Add(commit.Id.Oid); count++; @@ -722,7 +722,7 @@ public virtual Commit FindMergeBase(IEnumerable commits, MergeBaseFindin if (count < 2) { - throw new ArgumentException("The enumerable must contains at least two commits.", "commits"); + throw new ArgumentException("The enumerable must contains at least two commits.", nameof(commits)); } switch (strategy) @@ -736,7 +736,7 @@ public virtual Commit FindMergeBase(IEnumerable commits, MergeBaseFindin break; default: - throw new ArgumentException("", "strategy"); + throw new ArgumentException("", nameof(strategy)); } return id == null ? null : repo.Lookup(id); @@ -780,7 +780,7 @@ public virtual MergeTreeResult MergeCommits(Commit ours, Commit theirs, MergeTre // Stopped due to FailOnConflict so there's no index or conflict list if (earlyStop) { - return new MergeTreeResult(new Conflict[] { }); + return new MergeTreeResult(Array.Empty()); } if (Proxy.git_index_has_conflicts(indexHandle)) @@ -1063,7 +1063,7 @@ public virtual MergeTreeResult RevertCommit(Commit revertCommit, Commit revertOn // Stopped due to FailOnConflict so there's no index or conflict list if (earlyStop) { - return new MergeTreeResult(new Conflict[] { }); + return new MergeTreeResult(Array.Empty()); } if (Proxy.git_index_has_conflicts(indexHandle)) diff --git a/LibGit2Sharp/ObjectId.cs b/LibGit2Sharp/ObjectId.cs index 9d754781c..ad61cba36 100644 --- a/LibGit2Sharp/ObjectId.cs +++ b/LibGit2Sharp/ObjectId.cs @@ -39,7 +39,7 @@ internal ObjectId(GitOid oid) { if (oid.Id == null || oid.Id.Length != rawSize) { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "A non null array of {0} bytes is expected.", rawSize), "oid"); + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "A non null array of {0} bytes is expected.", rawSize), nameof(oid)); } this.oid = oid; @@ -145,10 +145,10 @@ public static bool TryParse(string sha, out ObjectId result) } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as ObjectId); @@ -174,7 +174,7 @@ public override int GetHashCode() } /// - /// Returns the , a representation of the current . + /// Returns the , a representation of the current . /// /// The that represents the current . public override string ToString() @@ -183,7 +183,7 @@ public override string ToString() } /// - /// Returns the , a representation of the current . + /// Returns the , a representation of the current . /// /// The number of chars the should be truncated to. /// The that represents the current . @@ -327,7 +327,7 @@ private static bool LooksValid(string objectId, bool throwIfInvalid) "'{0}' is not a valid object identifier. Its length should be {1}.", objectId, HexSize), - "objectId"); + nameof(objectId)); } return objectId.All(c => hexDigits.IndexOf(c) >= 0); diff --git a/LibGit2Sharp/OdbBackend.cs b/LibGit2Sharp/OdbBackend.cs index 9736ed803..645d0ac5f 100644 --- a/LibGit2Sharp/OdbBackend.cs +++ b/LibGit2Sharp/OdbBackend.cs @@ -63,7 +63,7 @@ protected unsafe UnmanagedMemoryStream Allocate(long size) { if (size < 0 || (UIntPtr.Size == sizeof(int) && size > int.MaxValue)) { - throw new ArgumentOutOfRangeException("size"); + throw new ArgumentOutOfRangeException(nameof(size)); } IntPtr buffer = Proxy.git_odb_backend_malloc(this.GitOdbBackendPointer, new UIntPtr((ulong)size)); diff --git a/LibGit2Sharp/PackBuilder.cs b/LibGit2Sharp/PackBuilder.cs index dcaa2617a..2ede4ab7b 100644 --- a/LibGit2Sharp/PackBuilder.cs +++ b/LibGit2Sharp/PackBuilder.cs @@ -189,7 +189,7 @@ public int MaximumNumberOfThreads { if (value < 0) { - throw new ArgumentException("Argument can not be negative", "value"); + throw new ArgumentException("Argument can not be negative", nameof(value)); } nThreads = value; diff --git a/LibGit2Sharp/PeelException.cs b/LibGit2Sharp/PeelException.cs index 92a6a0f13..b5a3d628b 100644 --- a/LibGit2Sharp/PeelException.cs +++ b/LibGit2Sharp/PeelException.cs @@ -32,7 +32,7 @@ public PeelException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public PeelException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/PushUpdate.cs b/LibGit2Sharp/PushUpdate.cs index bbabb6817..0aa915dc0 100644 --- a/LibGit2Sharp/PushUpdate.cs +++ b/LibGit2Sharp/PushUpdate.cs @@ -29,9 +29,9 @@ internal unsafe PushUpdate(git_push_update* update) protected PushUpdate() { DestinationObjectId = ObjectId.Zero; - DestinationRefName = String.Empty; + DestinationRefName = string.Empty; SourceObjectId = ObjectId.Zero; - SourceRefName = String.Empty; + SourceRefName = string.Empty; } /// diff --git a/LibGit2Sharp/Reference.cs b/LibGit2Sharp/Reference.cs index 40a85f79f..616b386a9 100644 --- a/LibGit2Sharp/Reference.cs +++ b/LibGit2Sharp/Reference.cs @@ -153,10 +153,10 @@ public virtual string TargetIdentifier } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as Reference); @@ -204,7 +204,7 @@ public override int GetHashCode() } /// - /// Returns the , a representation of the current . + /// Returns the , a representation of the current . /// /// The that represents the current . public override string ToString() diff --git a/LibGit2Sharp/ReferenceCollection.cs b/LibGit2Sharp/ReferenceCollection.cs index 602a20f17..456b1a043 100644 --- a/LibGit2Sharp/ReferenceCollection.cs +++ b/LibGit2Sharp/ReferenceCollection.cs @@ -539,7 +539,7 @@ public virtual Reference UpdateTarget(string name, string canonicalRefNameOrObje if (refState == RefState.DoesNotLookValid) { - throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The reference specified by {0} is a Symbolic reference, you must provide a reference canonical name as the target.", name), "canonicalRefNameOrObjectish"); + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The reference specified by {0} is a Symbolic reference, you must provide a reference canonical name as the target.", name), nameof(canonicalRefNameOrObjectish)); } return UpdateTarget(symbolicReference, targetRef, logMessage); diff --git a/LibGit2Sharp/ReferenceWrapper.cs b/LibGit2Sharp/ReferenceWrapper.cs index eff09e6ce..7fb8497c6 100644 --- a/LibGit2Sharp/ReferenceWrapper.cs +++ b/LibGit2Sharp/ReferenceWrapper.cs @@ -129,10 +129,10 @@ public bool Equals(ReferenceWrapper other) } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as ReferenceWrapper); diff --git a/LibGit2Sharp/RemoveFromIndexException.cs b/LibGit2Sharp/RemoveFromIndexException.cs index 37e7daf79..847e4026e 100644 --- a/LibGit2Sharp/RemoveFromIndexException.cs +++ b/LibGit2Sharp/RemoveFromIndexException.cs @@ -30,7 +30,7 @@ public RemoveFromIndexException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public RemoveFromIndexException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/RenameDetails.cs b/LibGit2Sharp/RenameDetails.cs index b866aac60..8742ff0d3 100644 --- a/LibGit2Sharp/RenameDetails.cs +++ b/LibGit2Sharp/RenameDetails.cs @@ -56,10 +56,10 @@ public virtual int Similarity } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as RenameDetails); diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 73f560c3c..e23c9cd3b 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -1456,7 +1456,7 @@ private FastForwardStrategy FastForwardStrategyFromMergePreference(GitMergePrefe case GitMergePreference.GIT_MERGE_PREFERENCE_NO_FASTFORWARD: return FastForwardStrategy.NoFastForward; default: - throw new InvalidOperationException(String.Format("Unknown merge preference: {0}", preference)); + throw new InvalidOperationException(string.Format("Unknown merge preference: {0}", preference)); } } @@ -1674,7 +1674,7 @@ internal FilePath[] ToFilePaths(IEnumerable paths) { if (string.IsNullOrEmpty(path)) { - throw new ArgumentException("At least one provided path is either null or empty.", "paths"); + throw new ArgumentException("At least one provided path is either null or empty.", nameof(paths)); } filePaths.Add(this.BuildRelativePathFrom(path)); @@ -1682,7 +1682,7 @@ internal FilePath[] ToFilePaths(IEnumerable paths) if (filePaths.Count == 0) { - throw new ArgumentException("No path has been provided.", "paths"); + throw new ArgumentException("No path has been provided.", nameof(paths)); } return filePaths.ToArray(); diff --git a/LibGit2Sharp/RepositoryNotFoundException.cs b/LibGit2Sharp/RepositoryNotFoundException.cs index 2e8deb393..e2bc63d8b 100644 --- a/LibGit2Sharp/RepositoryNotFoundException.cs +++ b/LibGit2Sharp/RepositoryNotFoundException.cs @@ -31,7 +31,7 @@ public RepositoryNotFoundException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public RepositoryNotFoundException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/Signature.cs b/LibGit2Sharp/Signature.cs index bad656d05..7ed7a4916 100644 --- a/LibGit2Sharp/Signature.cs +++ b/LibGit2Sharp/Signature.cs @@ -86,10 +86,10 @@ public DateTimeOffset When } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as Signature); diff --git a/LibGit2Sharp/SmartSubtransport.cs b/LibGit2Sharp/SmartSubtransport.cs index 66fcd12bf..e7a331b4b 100644 --- a/LibGit2Sharp/SmartSubtransport.cs +++ b/LibGit2Sharp/SmartSubtransport.cs @@ -158,7 +158,7 @@ public int AcquireCredentials(out Credentials cred, string user, params Type[] m /// The endpoint to connect to /// The type of connection to create /// A SmartSubtransportStream representing the connection - protected abstract SmartSubtransportStream Action(String url, GitSmartSubtransportAction action); + protected abstract SmartSubtransportStream Action(string url, GitSmartSubtransportAction action); /// /// Invoked by libgit2 when this subtransport is no longer needed, but may be re-used in the future. @@ -225,7 +225,7 @@ private static int Action( stream = IntPtr.Zero; SmartSubtransport t = GCHandle.FromIntPtr(Marshal.ReadIntPtr(subtransport, GitSmartSubtransport.GCHandleOffset)).Target as SmartSubtransport; - String urlAsString = LaxUtf8Marshaler.FromNative(url); + string urlAsString = LaxUtf8Marshaler.FromNative(url); if (t == null) { @@ -233,12 +233,12 @@ private static int Action( return (int)GitErrorCode.Error; } - if (String.IsNullOrEmpty(urlAsString)) + if (string.IsNullOrEmpty(urlAsString)) { urlAsString = t.LastActionUrl; } - if (String.IsNullOrEmpty(urlAsString)) + if (string.IsNullOrEmpty(urlAsString)) { Proxy.git_error_set_str(GitErrorCategory.Net, "no url provided"); return (int)GitErrorCode.Error; diff --git a/LibGit2Sharp/StashCollection.cs b/LibGit2Sharp/StashCollection.cs index 5fe775eba..42162ada5 100644 --- a/LibGit2Sharp/StashCollection.cs +++ b/LibGit2Sharp/StashCollection.cs @@ -67,7 +67,7 @@ public virtual Stash this[int index] { if (index < 0) { - throw new ArgumentOutOfRangeException("index", "The passed index must be a positive integer."); + throw new ArgumentOutOfRangeException(nameof(index), "The passed index must be a positive integer."); } GitObject stashCommit = repo.Lookup(string.Format(CultureInfo.InvariantCulture, @@ -146,7 +146,7 @@ public virtual StashApplyStatus Apply(int index, StashApplyOptions options) { if (index < 0) { - throw new ArgumentException("The passed index must be a positive integer.", "index"); + throw new ArgumentException("The passed index must be a positive integer.", nameof(index)); } if (options == null) @@ -189,7 +189,7 @@ public virtual StashApplyStatus Pop(int index, StashApplyOptions options) { if (index < 0) { - throw new ArgumentException("The passed index must be a positive integer.", "index"); + throw new ArgumentException("The passed index must be a positive integer.", nameof(index)); } if (options == null) @@ -231,7 +231,7 @@ public virtual void Remove(int index) { if (index < 0) { - throw new ArgumentException("The passed index must be a positive integer.", "index"); + throw new ArgumentException("The passed index must be a positive integer.", nameof(index)); } Proxy.git_stash_drop(repo.Handle, index); diff --git a/LibGit2Sharp/StatusEntry.cs b/LibGit2Sharp/StatusEntry.cs index 7008712c6..bd2ef8883 100644 --- a/LibGit2Sharp/StatusEntry.cs +++ b/LibGit2Sharp/StatusEntry.cs @@ -66,10 +66,10 @@ public virtual RenameDetails IndexToWorkDirRenameDetails } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as StatusEntry); diff --git a/LibGit2Sharp/Submodule.cs b/LibGit2Sharp/Submodule.cs index ace995205..f8193af13 100644 --- a/LibGit2Sharp/Submodule.cs +++ b/LibGit2Sharp/Submodule.cs @@ -107,10 +107,10 @@ public virtual SubmoduleStatus RetrieveStatus() } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as Submodule); @@ -136,7 +136,7 @@ public override int GetHashCode() } /// - /// Returns the , a representation of the current . + /// Returns the , a representation of the current . /// /// The that represents the current . public override string ToString() diff --git a/LibGit2Sharp/Tree.cs b/LibGit2Sharp/Tree.cs index f8494ad8b..64d46145d 100644 --- a/LibGit2Sharp/Tree.cs +++ b/LibGit2Sharp/Tree.cs @@ -90,7 +90,7 @@ internal static string CombinePath(string a, string b) { var bld = new StringBuilder(); bld.Append(a); - if (!String.IsNullOrEmpty(a) && + if (!string.IsNullOrEmpty(a) && !a.EndsWith("/", StringComparison.Ordinal) && !b.StartsWith("/", StringComparison.Ordinal)) { diff --git a/LibGit2Sharp/TreeChanges.cs b/LibGit2Sharp/TreeChanges.cs index 6e8a0eff5..6a54d9c09 100644 --- a/LibGit2Sharp/TreeChanges.cs +++ b/LibGit2Sharp/TreeChanges.cs @@ -55,7 +55,7 @@ private IEnumerable GetChangesOfKind(ChangeKind changeKind) private unsafe bool TryGetEntryWithChangeTypeAt(int index, ChangeKind changeKind, out TreeEntryChanges entry) { if (index < 0 || index > count.Value) - throw new ArgumentOutOfRangeException("index", "Index was out of range. Must be non-negative and less than the size of the collection."); + throw new ArgumentOutOfRangeException(nameof(index), "Index was out of range. Must be non-negative and less than the size of the collection."); var delta = Proxy.git_diff_get_delta(diff, index); @@ -90,7 +90,7 @@ public virtual IEnumerator GetEnumerator() private unsafe TreeEntryChanges GetEntryAt(int index) { if (index < 0 || index > count.Value) - throw new ArgumentOutOfRangeException("index", "Index was out of range. Must be non-negative and less than the size of the collection."); + throw new ArgumentOutOfRangeException(nameof(index), "Index was out of range. Must be non-negative and less than the size of the collection."); return new TreeEntryChanges(Proxy.git_diff_get_delta(diff, index)); } diff --git a/LibGit2Sharp/TreeEntry.cs b/LibGit2Sharp/TreeEntry.cs index e500a8ee1..943e14570 100644 --- a/LibGit2Sharp/TreeEntry.cs +++ b/LibGit2Sharp/TreeEntry.cs @@ -93,10 +93,10 @@ private GitObject RetrieveTreeEntryTarget() } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as TreeEntry); diff --git a/LibGit2Sharp/TreeEntryDefinition.cs b/LibGit2Sharp/TreeEntryDefinition.cs index 2a3ceb35f..d32cc722c 100644 --- a/LibGit2Sharp/TreeEntryDefinition.cs +++ b/LibGit2Sharp/TreeEntryDefinition.cs @@ -112,10 +112,10 @@ internal static TreeEntryDefinition From(Tree tree) } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as TreeEntryDefinition); diff --git a/LibGit2Sharp/UnbornBranchException.cs b/LibGit2Sharp/UnbornBranchException.cs index 8f56eed3d..8f01a63ab 100644 --- a/LibGit2Sharp/UnbornBranchException.cs +++ b/LibGit2Sharp/UnbornBranchException.cs @@ -31,7 +31,7 @@ public UnbornBranchException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public UnbornBranchException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/UnmatchedPathException.cs b/LibGit2Sharp/UnmatchedPathException.cs index daf48db6d..96e5654c7 100644 --- a/LibGit2Sharp/UnmatchedPathException.cs +++ b/LibGit2Sharp/UnmatchedPathException.cs @@ -30,7 +30,7 @@ public UnmatchedPathException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public UnmatchedPathException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/UnmergedIndexEntriesException.cs b/LibGit2Sharp/UnmergedIndexEntriesException.cs index ca01c256d..f9f1a834b 100644 --- a/LibGit2Sharp/UnmergedIndexEntriesException.cs +++ b/LibGit2Sharp/UnmergedIndexEntriesException.cs @@ -32,7 +32,7 @@ public UnmergedIndexEntriesException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public UnmergedIndexEntriesException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/UserCanceledException.cs b/LibGit2Sharp/UserCanceledException.cs index 0139bdb1c..f3c6af7dd 100644 --- a/LibGit2Sharp/UserCanceledException.cs +++ b/LibGit2Sharp/UserCanceledException.cs @@ -31,7 +31,7 @@ public UserCancelledException(string message) /// /// Initializes a new instance of the class with a specified error message. /// - /// A composite format string for use in . + /// A composite format string for use in . /// An object array that contains zero or more objects to format. public UserCancelledException(string format, params object[] args) : base(format, args) diff --git a/LibGit2Sharp/Worktree.cs b/LibGit2Sharp/Worktree.cs index 13fea072b..bd10f6110 100644 --- a/LibGit2Sharp/Worktree.cs +++ b/LibGit2Sharp/Worktree.cs @@ -65,10 +65,10 @@ internal WorktreeHandle GetWorktreeHandle() public virtual string LockReason { get { return worktreeLock == null ? null : worktreeLock.Reason; } } /// - /// Determines whether the specified is equal to the current . + /// Determines whether the specified is equal to the current . /// - /// The to compare with the current . - /// True if the specified is equal to the current ; otherwise, false. + /// The to compare with the current . + /// True if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { return Equals(obj as Worktree); @@ -118,7 +118,7 @@ public override int GetHashCode() } /// - /// Returns the , a representation of the current . + /// Returns the , a representation of the current . /// /// The that represents the current . public override string ToString() From e1703369d6eb7bdcc9bc13aa10d31324a07d6f5c Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Mar 2024 14:38:00 -0400 Subject: [PATCH 357/384] Update LibGit2Sharp.NativeBinaries to 2.0.322 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index fcf965c7d..28404d948 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -39,7 +39,7 @@ - + From a37362367aeadbebbfa22c28cdff16a3da26f081 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 16 Mar 2024 22:20:57 -0400 Subject: [PATCH 358/384] Increase assert range to avoid flaky tests --- LibGit2Sharp.Tests/CommitFixture.cs | 75 ++++++++++--------- LibGit2Sharp.Tests/ReflogFixture.cs | 23 ++++-- LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs | 6 +- 3 files changed, 59 insertions(+), 45 deletions(-) diff --git a/LibGit2Sharp.Tests/CommitFixture.cs b/LibGit2Sharp.Tests/CommitFixture.cs index 1a849c2df..e99ca918f 100644 --- a/LibGit2Sharp.Tests/CommitFixture.cs +++ b/LibGit2Sharp.Tests/CommitFixture.cs @@ -3,10 +3,8 @@ using System.IO; using System.Linq; using System.Text; -using LibGit2Sharp.Core; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -150,10 +148,10 @@ public void CanEnumerateCommitsWithReverseTimeSorting() using (var repo = new Repository(path)) { foreach (Commit commit in repo.Commits.QueryBy(new CommitFilter - { - IncludeReachableFrom = "a4a7dce85cf63874e984719f4fdd239f5145052f", - SortBy = CommitSortStrategies.Time | CommitSortStrategies.Reverse - })) + { + IncludeReachableFrom = "a4a7dce85cf63874e984719f4fdd239f5145052f", + SortBy = CommitSortStrategies.Time | CommitSortStrategies.Reverse + })) { Assert.NotNull(commit); Assert.StartsWith(reversedShas[count], commit.Sha); @@ -170,10 +168,10 @@ public void CanEnumerateCommitsWithReverseTopoSorting() using (var repo = new Repository(path)) { List commits = repo.Commits.QueryBy(new CommitFilter - { - IncludeReachableFrom = "a4a7dce85cf63874e984719f4fdd239f5145052f", - SortBy = CommitSortStrategies.Time | CommitSortStrategies.Reverse - }).ToList(); + { + IncludeReachableFrom = "a4a7dce85cf63874e984719f4fdd239f5145052f", + SortBy = CommitSortStrategies.Time | CommitSortStrategies.Reverse + }).ToList(); foreach (Commit commit in commits) { Assert.NotNull(commit); @@ -216,10 +214,10 @@ public void CanEnumerateCommitsWithTimeSorting() using (var repo = new Repository(path)) { foreach (Commit commit in repo.Commits.QueryBy(new CommitFilter - { - IncludeReachableFrom = "a4a7dce85cf63874e984719f4fdd239f5145052f", - SortBy = CommitSortStrategies.Time - })) + { + IncludeReachableFrom = "a4a7dce85cf63874e984719f4fdd239f5145052f", + SortBy = CommitSortStrategies.Time + })) { Assert.NotNull(commit); Assert.StartsWith(expectedShas[count], commit.Sha); @@ -236,10 +234,10 @@ public void CanEnumerateCommitsWithTopoSorting() using (var repo = new Repository(path)) { List commits = repo.Commits.QueryBy(new CommitFilter - { - IncludeReachableFrom = "a4a7dce85cf63874e984719f4fdd239f5145052f", - SortBy = CommitSortStrategies.Topological - }).ToList(); + { + IncludeReachableFrom = "a4a7dce85cf63874e984719f4fdd239f5145052f", + SortBy = CommitSortStrategies.Topological + }).ToList(); foreach (Commit commit in commits) { Assert.NotNull(commit); @@ -331,9 +329,12 @@ public void CanEnumerateCommitsFromTwoHeads() public void CanEnumerateCommitsFromMixedStartingPoints() { AssertEnumerationOfCommits( - repo => new CommitFilter { IncludeReachableFrom = new object[] { repo.Branches["br2"], + repo => new CommitFilter + { + IncludeReachableFrom = new object[] { repo.Branches["br2"], "refs/heads/master", - new ObjectId("e90810b8df3e80c413d903f631643c716887138d") } }, + new ObjectId("e90810b8df3e80c413d903f631643c716887138d") } + }, new[] { "4c062a6", "e90810b", "6dcf9bf", "a4a7dce", @@ -389,9 +390,9 @@ public void CanEnumerateAllCommits() { AssertEnumerationOfCommits( repo => new CommitFilter - { - IncludeReachableFrom = repo.Refs.OrderBy(r => r.CanonicalName, StringComparer.Ordinal), - }, + { + IncludeReachableFrom = repo.Refs.OrderBy(r => r.CanonicalName, StringComparer.Ordinal), + }, new[] { "44d5d18", "bb65291", "532740a", "503a16f", "3dfd6fd", @@ -680,8 +681,12 @@ public void CanCommitALittleBit() Assert.Equal(identity.Name, reflogEntry.Committer.Name); Assert.Equal(identity.Email, reflogEntry.Committer.Email); - var now = DateTimeOffset.Now; - Assert.InRange(reflogEntry.Committer.When, before, now); + // When verifying the timestamp range, give a little more room on the range. + // 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 + var low = before - TimeSpan.FromSeconds(1); + var high = DateTimeOffset.Now.TruncateMilliseconds() + TimeSpan.FromSeconds(1); + Assert.InRange(reflogEntry.Committer.When, low, high); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(ObjectId.Zero, reflogEntry.From); @@ -859,21 +864,21 @@ public void CanRetrieveChildrenOfASpecificCommit() const string parentSha = "5b5b025afb0b4c913b4c338a42934a3863bf3644"; var filter = new CommitFilter - { - /* Revwalk from all the refs (git log --all) ... */ - IncludeReachableFrom = repo.Refs, + { + /* Revwalk from all the refs (git log --all) ... */ + IncludeReachableFrom = repo.Refs, - /* ... and stop when the parent is reached */ - ExcludeReachableFrom = parentSha - }; + /* ... and stop when the parent is reached */ + ExcludeReachableFrom = parentSha + }; var commits = repo.Commits.QueryBy(filter); var children = from c in commits - from p in c.Parents - let pId = p.Id - where pId.Sha == parentSha - select c; + from p in c.Parents + let pId = p.Id + where pId.Sha == parentSha + select c; var expectedChildren = new[] { "c47800c7266a2be04c571c04d5a6614691ea99bd", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045" }; diff --git a/LibGit2Sharp.Tests/ReflogFixture.cs b/LibGit2Sharp.Tests/ReflogFixture.cs index f93952e6e..52973454b 100644 --- a/LibGit2Sharp.Tests/ReflogFixture.cs +++ b/LibGit2Sharp.Tests/ReflogFixture.cs @@ -3,7 +3,6 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -59,7 +58,7 @@ public void CommitShouldCreateReflogEntryOnHeadAndOnTargetedDirectReference() var identity = Constants.Identity; - using (var repo = new Repository(repoPath, new RepositoryOptions{ Identity = identity })) + using (var repo = new Repository(repoPath, new RepositoryOptions { Identity = identity })) { // setup refs as HEAD => unit_test => master var newRef = repo.Refs.Add("refs/heads/unit_test", "refs/heads/master"); @@ -84,8 +83,12 @@ public void CommitShouldCreateReflogEntryOnHeadAndOnTargetedDirectReference() Assert.Equal(identity.Name, reflogEntry.Committer.Name); Assert.Equal(identity.Email, reflogEntry.Committer.Email); - var now = DateTimeOffset.Now; - Assert.InRange(reflogEntry.Committer.When, before, now); + // When verifying the timestamp range, give a little more room on the range. + // 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 + var low = before - TimeSpan.FromSeconds(1); + var high = DateTimeOffset.Now.TruncateMilliseconds() + TimeSpan.FromSeconds(1); + Assert.InRange(reflogEntry.Committer.When, low, high); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(ObjectId.Zero, reflogEntry.From); @@ -97,7 +100,7 @@ public void CommitShouldCreateReflogEntryOnHeadAndOnTargetedDirectReference() Assert.Equal(identity.Name, reflogEntry.Committer.Name); Assert.Equal(identity.Email, reflogEntry.Committer.Email); - Assert.InRange(reflogEntry.Committer.When, before, now); + Assert.InRange(reflogEntry.Committer.When, low, high); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(ObjectId.Zero, reflogEntry.From); @@ -160,8 +163,12 @@ public void CommitOnDetachedHeadShouldInsertReflogEntry() Assert.Equal(identity.Name, reflogEntry.Committer.Name); Assert.Equal(identity.Email, reflogEntry.Committer.Email); - var now = DateTimeOffset.Now; - Assert.InRange(reflogEntry.Committer.When, before, now); + // When verifying the timestamp range, give a little more room on the range. + // 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 + var low = before - TimeSpan.FromSeconds(1); + var high = DateTimeOffset.Now.TruncateMilliseconds() + TimeSpan.FromSeconds(1); + Assert.InRange(reflogEntry.Committer.When, low, high); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(string.Format("commit: {0}", commitMessage), repo.Refs.Log("HEAD").First().Message); @@ -202,7 +209,7 @@ public void AppendingToReflogDependsOnCoreLogAllRefUpdatesSetting(bool isBare, b public void UnsignedMethodsWriteCorrectlyToTheReflog() { var repoPath = InitNewRepository(true); - using (var repo = new Repository(repoPath, new RepositoryOptions{ Identity = Constants.Identity })) + using (var repo = new Repository(repoPath, new RepositoryOptions { Identity = Constants.Identity })) { EnableRefLog(repo); diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index cde8f3ddb..e9429d562 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -471,10 +471,12 @@ protected static void AssertRefLogEntry(IRepository repo, string canonicalName, Assert.Equal(committer.Email, reflogEntry.Committer.Email); - // When verifying the timestamp range, give a little more room on the 'before' side. + // When verifying the timestamp range, give a little more room on the range. // 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); + var low = before - TimeSpan.FromSeconds(1); + var high = DateTimeOffset.Now.TruncateMilliseconds() + TimeSpan.FromSeconds(1); + Assert.InRange(reflogEntry.Committer.When, low, high); } protected static void EnableRefLog(IRepository repository, bool enable = true) From 5085a0c6173cdb2a3fde205330b327a8eb0a26c4 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 18 Mar 2024 22:48:32 -0400 Subject: [PATCH 359/384] Update CHANGES.md for v0.30 --- CHANGES.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index ae27d7716..1d68e6169 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,12 @@ # LibGit2Sharp Changes +## v0.30 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.29.0..0.30.0)) + +### Changes +- This release includes [libgit2 v1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). +- Updates for trimming compatibility [#2084](https://github.com/libgit2/libgit2sharp/pull/2084) +- Updates for .NET 8 [#2085](https://github.com/libgit2/libgit2sharp/pull/2085) + ## v0.29 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.28.0..0.29.0)) ### Changes @@ -8,7 +15,7 @@ ### Additions - Add proxy options [#2065](https://github.com/libgit2/libgit2sharp/pull/2065) - - See PR for details, including some breaking changes to `CloneOptions` and `SubmoduleUpdateOptions` + - See PR for details, including some breaking changes to `CloneOptions` and `SubmoduleUpdateOptions` ## v0.28 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.27.2..0.28.0)) From 77cfeaffd34b98f966f5efb232446b2884369be6 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Thu, 21 Nov 2024 00:54:31 -0500 Subject: [PATCH 360/384] Remove macos-11 --- .github/workflows/ci.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35f0241ef..9a7f9a0de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,13 +38,9 @@ jobs: strategy: matrix: arch: [ x64 ] - os: [ windows-2019, windows-2022, macos-11, macos-12, macos-13 ] + os: [ windows-2019, windows-2022, macos-12, macos-13 ] tfm: [ net472, net6.0, net8.0 ] exclude: - - os: macos-11 - tfm: net472 - - os: macos-11 - tfm: net8.0 - os: macos-12 tfm: net472 - os: macos-13 From 66f6940c242b6539c74ec9ebf9a0c6f221dfb9e3 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Thu, 21 Nov 2024 00:56:00 -0500 Subject: [PATCH 361/384] Use private protected --- LibGit2Sharp/Reference.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/LibGit2Sharp/Reference.cs b/LibGit2Sharp/Reference.cs index 616b386a9..9530f2378 100644 --- a/LibGit2Sharp/Reference.cs +++ b/LibGit2Sharp/Reference.cs @@ -25,11 +25,7 @@ public abstract class Reference : IEquatable, IBelongToARepository protected Reference() { } - /// - /// This would be protected+internal, were that supported by C#. - /// Do not use except in subclasses. - /// - internal Reference(IRepository repo, string canonicalName, string targetIdentifier) + private protected Reference(IRepository repo, string canonicalName, string targetIdentifier) { this.repo = repo; this.canonicalName = canonicalName; From a88e2a02e04ed8acc5455df04c1e6cd91ced3265 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Thu, 21 Nov 2024 01:13:13 -0500 Subject: [PATCH 362/384] Use SafeHandles (#2127) * Remove unneeded cast * Use SafeHandles --- LibGit2Sharp/Core/Handles/Libgit2Object.cs | 87 ++----- LibGit2Sharp/Core/Handles/Objects.cs | 250 ++++++++++++--------- LibGit2Sharp/Core/Handles/Objects.tt | 10 +- LibGit2Sharp/Network.cs | 4 +- LibGit2Sharp/Reference.cs | 2 +- LibGit2Sharp/Repository.cs | 4 +- 6 files changed, 184 insertions(+), 173 deletions(-) diff --git a/LibGit2Sharp/Core/Handles/Libgit2Object.cs b/LibGit2Sharp/Core/Handles/Libgit2Object.cs index 892ebde90..a96d99e10 100644 --- a/LibGit2Sharp/Core/Handles/Libgit2Object.cs +++ b/LibGit2Sharp/Core/Handles/Libgit2Object.cs @@ -1,13 +1,13 @@ // This activates a lightweight mode which will help put under the light -// incorrectly released handles by outputing a warning message in the console. +// incorrectly released handles by outputting a warning message in the console. // // This should be activated when tests are being run on the CI server. // // Uncomment the line below or add a conditional symbol to activate this mode -// #define LEAKS_IDENTIFYING +//#define LEAKS_IDENTIFYING -// This activates a more throrough mode which will show the stack trace of the +// This activates a more thorough mode which will show the stack trace of the // allocation code path for each handle that has been improperly released. // // This should be manually activated when some warnings have been raised as @@ -15,17 +15,17 @@ // // Uncomment the line below or add a conditional symbol to activate this mode -// #define LEAKS_TRACKING +//#define LEAKS_TRACKING using System; -using System.Linq; -using System.Diagnostics; -using System.Globalization; -using System.Collections.Generic; +using Microsoft.Win32.SafeHandles; #if LEAKS_IDENTIFYING namespace LibGit2Sharp.Core { + using System.Collections.Generic; + using System.Linq; + /// /// Holds leaked handle type names reported by /// @@ -78,30 +78,27 @@ public static IEnumerable TypeNames namespace LibGit2Sharp.Core.Handles { - internal unsafe abstract class Libgit2Object : IDisposable +#if LEAKS_TRACKING + using System.Diagnostics; + using System.Globalization; +#endif + + internal unsafe abstract class Libgit2Object : SafeHandleZeroOrMinusOneIsInvalid { #if LEAKS_TRACKING private readonly string trace; private readonly Guid id; #endif - protected void* ptr; - - internal void* Handle + internal unsafe Libgit2Object(void* ptr, bool owned) + : this(new IntPtr(ptr), owned) { - get - { - return ptr; - } } - bool owned; - bool disposed; - - internal unsafe Libgit2Object(void* handle, bool owned) + internal unsafe Libgit2Object(IntPtr ptr, bool owned) + : base(owned) { - this.ptr = handle; - this.owned = owned; + SetHandle(ptr); #if LEAKS_TRACKING id = Guid.NewGuid(); @@ -111,35 +108,12 @@ internal unsafe Libgit2Object(void* handle, bool owned) #endif } - internal unsafe Libgit2Object(IntPtr ptr, bool owned) - : this(ptr.ToPointer(), owned) - { - } + internal IntPtr AsIntPtr() => DangerousGetHandle(); - ~Libgit2Object() - { - Dispose(false); - } - - internal bool IsNull - { - get - { - return ptr == null; - } - } - - internal IntPtr AsIntPtr() - { - return new IntPtr(ptr); - } - - public abstract void Free(); - - void Dispose(bool disposing) + protected override void Dispose(bool disposing) { #if LEAKS_IDENTIFYING - bool leaked = !disposing && ptr != null; + bool leaked = !disposing && DangerousGetHandle() != IntPtr.Zero; if (leaked) { @@ -147,17 +121,7 @@ void Dispose(bool disposing) } #endif - if (!disposed) - { - if (owned) - { - Free(); - } - - ptr = null; - } - - disposed = true; + base.Dispose(disposing); #if LEAKS_TRACKING if (!leaked) @@ -172,11 +136,6 @@ void Dispose(bool disposing) } #endif } - - public void Dispose() - { - Dispose(true); - } } } diff --git a/LibGit2Sharp/Core/Handles/Objects.cs b/LibGit2Sharp/Core/Handles/Objects.cs index 5f8db722e..7666a7412 100644 --- a/LibGit2Sharp/Core/Handles/Objects.cs +++ b/LibGit2Sharp/Core/Handles/Objects.cs @@ -7,7 +7,7 @@ namespace LibGit2Sharp.Core.Handles internal unsafe class TreeEntryHandle : Libgit2Object { internal TreeEntryHandle(git_tree_entry *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -16,21 +16,23 @@ internal TreeEntryHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_tree_entry_free((git_tree_entry*) ptr); + NativeMethods.git_tree_entry_free((git_tree_entry*)AsIntPtr()); + + return true; } public static implicit operator git_tree_entry*(TreeEntryHandle handle) { - return (git_tree_entry*) handle.Handle; + return (git_tree_entry*)handle.AsIntPtr(); } } internal unsafe class ReferenceHandle : Libgit2Object { internal ReferenceHandle(git_reference *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -39,21 +41,23 @@ internal ReferenceHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_reference_free((git_reference*) ptr); + NativeMethods.git_reference_free((git_reference*)AsIntPtr()); + + return true; } public static implicit operator git_reference*(ReferenceHandle handle) { - return (git_reference*) handle.Handle; + return (git_reference*)handle.AsIntPtr(); } } internal unsafe class RepositoryHandle : Libgit2Object { internal RepositoryHandle(git_repository *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -62,21 +66,23 @@ internal RepositoryHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_repository_free((git_repository*) ptr); + NativeMethods.git_repository_free((git_repository*)AsIntPtr()); + + return true; } public static implicit operator git_repository*(RepositoryHandle handle) { - return (git_repository*) handle.Handle; + return (git_repository*)handle.AsIntPtr(); } } internal unsafe class SignatureHandle : Libgit2Object { internal SignatureHandle(git_signature *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -85,21 +91,23 @@ internal SignatureHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_signature_free((git_signature*) ptr); + NativeMethods.git_signature_free((git_signature*)AsIntPtr()); + + return true; } public static implicit operator git_signature*(SignatureHandle handle) { - return (git_signature*) handle.Handle; + return (git_signature*)handle.AsIntPtr(); } } internal unsafe class StatusListHandle : Libgit2Object { internal StatusListHandle(git_status_list *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -108,21 +116,23 @@ internal StatusListHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_status_list_free((git_status_list*) ptr); + NativeMethods.git_status_list_free((git_status_list*)AsIntPtr()); + + return true; } public static implicit operator git_status_list*(StatusListHandle handle) { - return (git_status_list*) handle.Handle; + return (git_status_list*)handle.AsIntPtr(); } } internal unsafe class BlameHandle : Libgit2Object { internal BlameHandle(git_blame *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -131,21 +141,23 @@ internal BlameHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_blame_free((git_blame*) ptr); + NativeMethods.git_blame_free((git_blame*)AsIntPtr()); + + return true; } public static implicit operator git_blame*(BlameHandle handle) { - return (git_blame*) handle.Handle; + return (git_blame*)handle.AsIntPtr(); } } internal unsafe class DiffHandle : Libgit2Object { internal DiffHandle(git_diff *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -154,21 +166,23 @@ internal DiffHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_diff_free((git_diff*) ptr); + NativeMethods.git_diff_free((git_diff*)AsIntPtr()); + + return true; } public static implicit operator git_diff*(DiffHandle handle) { - return (git_diff*) handle.Handle; + return (git_diff*)handle.AsIntPtr(); } } internal unsafe class PatchHandle : Libgit2Object { internal PatchHandle(git_patch *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -177,21 +191,23 @@ internal PatchHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_patch_free((git_patch*) ptr); + NativeMethods.git_patch_free((git_patch*)AsIntPtr()); + + return true; } public static implicit operator git_patch*(PatchHandle handle) { - return (git_patch*) handle.Handle; + return (git_patch*)handle.AsIntPtr(); } } internal unsafe class ConfigurationHandle : Libgit2Object { internal ConfigurationHandle(git_config *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -200,21 +216,23 @@ internal ConfigurationHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_config_free((git_config*) ptr); + NativeMethods.git_config_free((git_config*)AsIntPtr()); + + return true; } public static implicit operator git_config*(ConfigurationHandle handle) { - return (git_config*) handle.Handle; + return (git_config*)handle.AsIntPtr(); } } internal unsafe class ConflictIteratorHandle : Libgit2Object { internal ConflictIteratorHandle(git_index_conflict_iterator *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -223,21 +241,23 @@ internal ConflictIteratorHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_index_conflict_iterator_free((git_index_conflict_iterator*) ptr); + NativeMethods.git_index_conflict_iterator_free((git_index_conflict_iterator*)AsIntPtr()); + + return true; } public static implicit operator git_index_conflict_iterator*(ConflictIteratorHandle handle) { - return (git_index_conflict_iterator*) handle.Handle; + return (git_index_conflict_iterator*)handle.AsIntPtr(); } } internal unsafe class IndexHandle : Libgit2Object { internal IndexHandle(git_index *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -246,21 +266,23 @@ internal IndexHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_index_free((git_index*) ptr); + NativeMethods.git_index_free((git_index*)AsIntPtr()); + + return true; } public static implicit operator git_index*(IndexHandle handle) { - return (git_index*) handle.Handle; + return (git_index*)handle.AsIntPtr(); } } internal unsafe class ReflogHandle : Libgit2Object { internal ReflogHandle(git_reflog *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -269,21 +291,23 @@ internal ReflogHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_reflog_free((git_reflog*) ptr); + NativeMethods.git_reflog_free((git_reflog*)AsIntPtr()); + + return true; } public static implicit operator git_reflog*(ReflogHandle handle) { - return (git_reflog*) handle.Handle; + return (git_reflog*)handle.AsIntPtr(); } } internal unsafe class TreeBuilderHandle : Libgit2Object { internal TreeBuilderHandle(git_treebuilder *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -292,21 +316,23 @@ internal TreeBuilderHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_treebuilder_free((git_treebuilder*) ptr); + NativeMethods.git_treebuilder_free((git_treebuilder*)AsIntPtr()); + + return true; } public static implicit operator git_treebuilder*(TreeBuilderHandle handle) { - return (git_treebuilder*) handle.Handle; + return (git_treebuilder*)handle.AsIntPtr(); } } internal unsafe class PackBuilderHandle : Libgit2Object { internal PackBuilderHandle(git_packbuilder *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -315,21 +341,23 @@ internal PackBuilderHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_packbuilder_free((git_packbuilder*) ptr); + NativeMethods.git_packbuilder_free((git_packbuilder*)AsIntPtr()); + + return true; } public static implicit operator git_packbuilder*(PackBuilderHandle handle) { - return (git_packbuilder*) handle.Handle; + return (git_packbuilder*)handle.AsIntPtr(); } } internal unsafe class NoteHandle : Libgit2Object { internal NoteHandle(git_note *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -338,21 +366,23 @@ internal NoteHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_note_free((git_note*) ptr); + NativeMethods.git_note_free((git_note*)AsIntPtr()); + + return true; } public static implicit operator git_note*(NoteHandle handle) { - return (git_note*) handle.Handle; + return (git_note*)handle.AsIntPtr(); } } internal unsafe class DescribeResultHandle : Libgit2Object { internal DescribeResultHandle(git_describe_result *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -361,21 +391,23 @@ internal DescribeResultHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_describe_result_free((git_describe_result*) ptr); + NativeMethods.git_describe_result_free((git_describe_result*)AsIntPtr()); + + return true; } public static implicit operator git_describe_result*(DescribeResultHandle handle) { - return (git_describe_result*) handle.Handle; + return (git_describe_result*)handle.AsIntPtr(); } } internal unsafe class SubmoduleHandle : Libgit2Object { internal SubmoduleHandle(git_submodule *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -384,21 +416,23 @@ internal SubmoduleHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_submodule_free((git_submodule*) ptr); + NativeMethods.git_submodule_free((git_submodule*)AsIntPtr()); + + return true; } public static implicit operator git_submodule*(SubmoduleHandle handle) { - return (git_submodule*) handle.Handle; + return (git_submodule*)handle.AsIntPtr(); } } internal unsafe class AnnotatedCommitHandle : Libgit2Object { internal AnnotatedCommitHandle(git_annotated_commit *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -407,21 +441,23 @@ internal AnnotatedCommitHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_annotated_commit_free((git_annotated_commit*) ptr); + NativeMethods.git_annotated_commit_free((git_annotated_commit*)AsIntPtr()); + + return true; } public static implicit operator git_annotated_commit*(AnnotatedCommitHandle handle) { - return (git_annotated_commit*) handle.Handle; + return (git_annotated_commit*)handle.AsIntPtr(); } } internal unsafe class ObjectDatabaseHandle : Libgit2Object { internal ObjectDatabaseHandle(git_odb *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -430,21 +466,23 @@ internal ObjectDatabaseHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_odb_free((git_odb*) ptr); + NativeMethods.git_odb_free((git_odb*)AsIntPtr()); + + return true; } public static implicit operator git_odb*(ObjectDatabaseHandle handle) { - return (git_odb*) handle.Handle; + return (git_odb*)handle.AsIntPtr(); } } internal unsafe class RevWalkerHandle : Libgit2Object { internal RevWalkerHandle(git_revwalk *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -453,21 +491,23 @@ internal RevWalkerHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_revwalk_free((git_revwalk*) ptr); + NativeMethods.git_revwalk_free((git_revwalk*)AsIntPtr()); + + return true; } public static implicit operator git_revwalk*(RevWalkerHandle handle) { - return (git_revwalk*) handle.Handle; + return (git_revwalk*)handle.AsIntPtr(); } } internal unsafe class RemoteHandle : Libgit2Object { internal RemoteHandle(git_remote *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -476,21 +516,23 @@ internal RemoteHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_remote_free((git_remote*) ptr); + NativeMethods.git_remote_free((git_remote*)AsIntPtr()); + + return true; } public static implicit operator git_remote*(RemoteHandle handle) { - return (git_remote*) handle.Handle; + return (git_remote*)handle.AsIntPtr(); } } internal unsafe class ObjectHandle : Libgit2Object { internal ObjectHandle(git_object *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -499,21 +541,23 @@ internal ObjectHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_object_free((git_object*) ptr); + NativeMethods.git_object_free((git_object*)AsIntPtr()); + + return true; } public static implicit operator git_object*(ObjectHandle handle) { - return (git_object*) handle.Handle; + return (git_object*)handle.AsIntPtr(); } } internal unsafe class RebaseHandle : Libgit2Object { internal RebaseHandle(git_rebase *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -522,21 +566,23 @@ internal RebaseHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_rebase_free((git_rebase*) ptr); + NativeMethods.git_rebase_free((git_rebase*)AsIntPtr()); + + return true; } public static implicit operator git_rebase*(RebaseHandle handle) { - return (git_rebase*) handle.Handle; + return (git_rebase*)handle.AsIntPtr(); } } internal unsafe class OdbStreamHandle : Libgit2Object { internal OdbStreamHandle(git_odb_stream *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -545,21 +591,23 @@ internal OdbStreamHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_odb_stream_free((git_odb_stream*) ptr); + NativeMethods.git_odb_stream_free((git_odb_stream*)AsIntPtr()); + + return true; } public static implicit operator git_odb_stream*(OdbStreamHandle handle) { - return (git_odb_stream*) handle.Handle; + return (git_odb_stream*)handle.AsIntPtr(); } } internal unsafe class WorktreeHandle : Libgit2Object { internal WorktreeHandle(git_worktree *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -568,14 +616,16 @@ internal WorktreeHandle(IntPtr ptr, bool owned) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.git_worktree_free((git_worktree*) ptr); + NativeMethods.git_worktree_free((git_worktree*)AsIntPtr()); + + return true; } public static implicit operator git_worktree*(WorktreeHandle handle) { - return (git_worktree*) handle.Handle; + return (git_worktree*)handle.AsIntPtr(); } } diff --git a/LibGit2Sharp/Core/Handles/Objects.tt b/LibGit2Sharp/Core/Handles/Objects.tt index a6d1fa251..93707590e 100644 --- a/LibGit2Sharp/Core/Handles/Objects.tt +++ b/LibGit2Sharp/Core/Handles/Objects.tt @@ -73,7 +73,7 @@ for (var i = 0; i < cNames.Length; i++) internal unsafe class <#= csNames[i] #> : Libgit2Object { internal <#= csNames[i] #>(<#= cNames[i] #> *ptr, bool owned) - : base((void *) ptr, owned) + : base(ptr, owned) { } @@ -82,14 +82,16 @@ for (var i = 0; i < cNames.Length; i++) { } - public override void Free() + protected override bool ReleaseHandle() { - NativeMethods.<#= cNames[i] #>_free((<#= cNames[i] #>*) ptr); + NativeMethods.<#= cNames[i] #>_free((<#= cNames[i] #>*)AsIntPtr()); + + return true; } public static implicit operator <#= cNames[i] #>*(<#= csNames[i] #> handle) { - return (<#= cNames[i] #>*) handle.Handle; + return (<#= cNames[i] #>*)handle.AsIntPtr(); } } diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs index bd80834bb..ba0a33144 100644 --- a/LibGit2Sharp/Network.cs +++ b/LibGit2Sharp/Network.cs @@ -216,11 +216,11 @@ private IEnumerable ListReferencesInternal(string url, CredentialsHan static RemoteHandle BuildRemoteHandle(RepositoryHandle repoHandle, string url) { - Debug.Assert(repoHandle != null && !repoHandle.IsNull); + Debug.Assert(repoHandle != null && !repoHandle.IsInvalid); Debug.Assert(url != null); RemoteHandle remoteHandle = Proxy.git_remote_create_anonymous(repoHandle, url); - Debug.Assert(remoteHandle != null && !(remoteHandle.IsNull)); + Debug.Assert(remoteHandle != null && !remoteHandle.IsInvalid); return remoteHandle; } diff --git a/LibGit2Sharp/Reference.cs b/LibGit2Sharp/Reference.cs index 9530f2378..9a86195d1 100644 --- a/LibGit2Sharp/Reference.cs +++ b/LibGit2Sharp/Reference.cs @@ -35,7 +35,7 @@ private protected Reference(IRepository repo, string canonicalName, string targe // This overload lets public-facing methods avoid having to use the pointers directly internal static unsafe T BuildFromPtr(ReferenceHandle handle, Repository repo) where T : Reference { - return BuildFromPtr((git_reference*) handle.Handle, repo); + return BuildFromPtr((git_reference*)handle.AsIntPtr(), repo); } internal static unsafe T BuildFromPtr(git_reference* handle, Repository repo) where T : Reference diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index e23c9cd3b..fc777404e 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -575,7 +575,7 @@ internal GitObject LookupInternal(ObjectId id, GitObjectType type, string knownP using (ObjectHandle obj = Proxy.git_object_lookup(handle, id, type)) { - if (obj == null || obj.IsNull) + if (obj == null || obj.IsInvalid) { return null; } @@ -1781,7 +1781,7 @@ public void RevParse(string revision, out Reference reference, out GitObject obj using (var objH = handles.Item1) using (var refH = handles.Item2) { - reference = refH.IsNull ? null : Reference.BuildFromPtr(refH, this); + reference = refH.IsInvalid ? null : Reference.BuildFromPtr(refH, this); obj = GitObject.BuildFrom(this, Proxy.git_object_id(objH), Proxy.git_object_type(objH), PathFromRevparseSpec(revision)); } } From f4fc1440b7d5345d49321dcd242190a55a1df68f Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Thu, 21 Nov 2024 23:53:17 -0500 Subject: [PATCH 363/384] Updates (#2128) * Remove net6.0 * Add net9.0 * Update supported distros * Fix centos.stream.9 * Update packages * Reorder package reference item group * Remove distro combinations that are missing images --- .github/workflows/ci.yml | 44 ++++++++------------ LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 14 +++---- LibGit2Sharp/LibGit2Sharp.csproj | 17 ++++---- TrimmingTestApp/TrimmingTestApp.csproj | 2 +- 4 files changed, 33 insertions(+), 44 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a7f9a0de..6d29a0999 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - name: Install .NET SDK uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 8.0.x + dotnet-version: 9.0.x - name: Build run: dotnet build LibGit2Sharp.sln --configuration Release - name: Upload packages @@ -38,20 +38,18 @@ jobs: strategy: matrix: arch: [ x64 ] - os: [ windows-2019, windows-2022, macos-12, macos-13 ] - tfm: [ net472, net6.0, net8.0 ] + os: [ windows-2019, windows-2022, macos-13 ] + tfm: [ net472, net8.0, net9.0 ] exclude: - - os: macos-12 - tfm: net472 - os: macos-13 tfm: net472 include: - arch: arm64 os: macos-14 - tfm: net6.0 + tfm: net8.0 - arch: arm64 os: macos-14 - tfm: net8.0 + tfm: net9.0 fail-fast: false steps: - name: Checkout @@ -62,8 +60,8 @@ jobs: uses: actions/setup-dotnet@v4.0.0 with: dotnet-version: | + 9.0.x 8.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: @@ -73,28 +71,20 @@ jobs: matrix: arch: [ amd64 ] # arch: [ amd64, arm64 ] - distro: [ alpine.3.13, alpine.3.14, alpine.3.15, alpine.3.16, alpine.3.17, alpine.3.18, centos.stream.8, debian.10, debian.11, fedora.36, fedora.37, ubuntu.18.04, ubuntu.20.04, ubuntu.22.04 ] - sdk: [ '6.0', '8.0' ] + distro: [ alpine.3.17, alpine.3.18, alpine.3.19, alpine.3.20, centos.stream.9, debian.12, fedora.40, ubuntu.20.04, ubuntu.22.04, ubuntu.24.04 ] + sdk: [ '8.0', '9.0' ] exclude: - - distro: alpine.3.13 - sdk: '8.0' - - distro: alpine.3.14 - sdk: '8.0' - - distro: alpine.3.15 - sdk: '8.0' - - distro: alpine.3.16 - sdk: '8.0' - - distro: debian.10 - sdk: '8.0' - - distro: fedora.36 - sdk: '8.0' - - distro: ubuntu.18.04 - sdk: '8.0' + - distro: alpine.3.17 + sdk: '9.0' + - distro: alpine.3.18 + sdk: '9.0' + - distro: alpine.3.19 + sdk: '9.0' include: - - sdk: '6.0' - tfm: net6.0 - sdk: '8.0' tfm: net8.0 + - sdk: '9.0' + tfm: net9.0 fail-fast: false steps: - name: Checkout @@ -108,5 +98,5 @@ jobs: 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 "$git_command && $test_command" + docker run -t --rm --platform linux/${{ matrix.arch }} -v "$PWD:/app" -e OPENSSL_ENABLE_SHA1_SIGNATURES=1 gittools/build-images:${{ matrix.distro }}-sdk-${{ matrix.sdk }} sh -c "$git_command && $test_command" diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 4d648eead..fb81a76a3 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -1,7 +1,7 @@  - net472;net6.0;net8.0 + net472;net8.0;net9.0 @@ -11,12 +11,12 @@ - - - - - - + + + + + + diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 28404d948..8eadb87df 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -1,8 +1,8 @@  - net472;net6.0 - 10.0 + net472;net8.0 + 12.0 true LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET LibGit2Sharp contributors @@ -24,10 +24,15 @@ libgit2-$(libgit2_hash.Substring(0,7)) - + true + + + + + @@ -38,12 +43,6 @@ - - - - - - diff --git a/TrimmingTestApp/TrimmingTestApp.csproj b/TrimmingTestApp/TrimmingTestApp.csproj index 9cb7e75b4..3c6d341f6 100644 --- a/TrimmingTestApp/TrimmingTestApp.csproj +++ b/TrimmingTestApp/TrimmingTestApp.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 Exe enable enable From d935c4959017e2bbe36124ac58449d7e1b3a659b Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 22 Nov 2024 22:46:19 -0500 Subject: [PATCH 364/384] Fix test warnings --- LibGit2Sharp.Tests/ConfigurationFixture.cs | 29 ++++++++-------------- LibGit2Sharp.Tests/FilterBranchFixture.cs | 19 ++++++-------- LibGit2Sharp.Tests/ResetIndexFixture.cs | 5 ++-- 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/LibGit2Sharp.Tests/ConfigurationFixture.cs b/LibGit2Sharp.Tests/ConfigurationFixture.cs index 999aa0336..aaee77b02 100644 --- a/LibGit2Sharp.Tests/ConfigurationFixture.cs +++ b/LibGit2Sharp.Tests/ConfigurationFixture.cs @@ -4,7 +4,6 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -56,9 +55,7 @@ public void CanAddAndReadMultivarFromTheLocalConfiguration() string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { - Assert.Empty(repo.Config - .OfType>() - .Where(x => x.Key == "unittests.plugin")); + Assert.DoesNotContain(repo.Config.OfType>(), x => x.Key == "unittests.plugin"); repo.Config.Add("unittests.plugin", "value1", ConfigurationLevel.Local); repo.Config.Add("unittests.plugin", "value2", ConfigurationLevel.Local); @@ -78,9 +75,7 @@ public void CanAddAndReadMultivarFromTheGlobalConfiguration() using (var repo = new Repository(path)) { Assert.True(repo.Config.HasConfig(ConfigurationLevel.Global)); - Assert.Empty(repo.Config - .OfType>() - .Where(x => x.Key == "unittests.plugin")); + Assert.DoesNotContain(repo.Config.OfType>(), x => x.Key == "unittests.plugin"); repo.Config.Add("unittests.plugin", "value1", ConfigurationLevel.Global); repo.Config.Add("unittests.plugin", "value2", ConfigurationLevel.Global); @@ -157,9 +152,7 @@ public void CanUnsetAllFromTheLocalConfiguration() repo.Config.UnsetAll("unittests.plugin"); - Assert.Empty(repo.Config - .OfType>() - .Where(x => x.Key == "unittests.plugin")); + Assert.DoesNotContain(repo.Config.OfType>(), x => x.Key == "unittests.plugin"); } } @@ -531,20 +524,20 @@ public void CanSetAndGetSearchPath() { string globalPath = Path.Combine(Constants.TemporaryReposPath, Path.GetRandomFileName()); string systemPath = Path.Combine(Constants.TemporaryReposPath, Path.GetRandomFileName()); - string xdgPath = Path.Combine(Constants.TemporaryReposPath, Path.GetRandomFileName()); + string xdgPath = Path.Combine(Constants.TemporaryReposPath, Path.GetRandomFileName()); GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.Global, globalPath); GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.System, systemPath); - GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.Xdg, xdgPath); + GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.Xdg, xdgPath); Assert.Equal(globalPath, GlobalSettings.GetConfigSearchPaths(ConfigurationLevel.Global).Single()); Assert.Equal(systemPath, GlobalSettings.GetConfigSearchPaths(ConfigurationLevel.System).Single()); - Assert.Equal(xdgPath, GlobalSettings.GetConfigSearchPaths(ConfigurationLevel.Xdg).Single()); + Assert.Equal(xdgPath, GlobalSettings.GetConfigSearchPaths(ConfigurationLevel.Xdg).Single()); // reset the search paths to their defaults GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.Global, null); GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.System, null); - GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.Xdg, null); + GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.Xdg, null); } [Fact] @@ -577,12 +570,12 @@ public void CanResetSearchPaths() var newPaths = new string[] { Path.Combine(Constants.TemporaryReposPath, Path.GetRandomFileName()) }; // change to the non-default path - GlobalSettings.SetConfigSearchPaths (ConfigurationLevel.Global, newPaths); - Assert.Equal (newPaths, GlobalSettings.GetConfigSearchPaths (ConfigurationLevel.Global)); + GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.Global, newPaths); + Assert.Equal(newPaths, GlobalSettings.GetConfigSearchPaths(ConfigurationLevel.Global)); // set it back to the default - GlobalSettings.SetConfigSearchPaths (ConfigurationLevel.Global, null); - Assert.Equal (oldPaths, GlobalSettings.GetConfigSearchPaths (ConfigurationLevel.Global)); + GlobalSettings.SetConfigSearchPaths(ConfigurationLevel.Global, null); + Assert.Equal(oldPaths, GlobalSettings.GetConfigSearchPaths(ConfigurationLevel.Global)); } [Fact] diff --git a/LibGit2Sharp.Tests/FilterBranchFixture.cs b/LibGit2Sharp.Tests/FilterBranchFixture.cs index 2ca3e507a..0041e7646 100644 --- a/LibGit2Sharp.Tests/FilterBranchFixture.cs +++ b/LibGit2Sharp.Tests/FilterBranchFixture.cs @@ -3,7 +3,6 @@ using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; -using Xunit.Extensions; namespace LibGit2Sharp.Tests { @@ -162,10 +161,8 @@ public void CanRewriteAuthorOfCommits() AssertSucceedingButNotError(); - var nonBackedUpRefs = repo.Refs.Where( - x => !x.CanonicalName.StartsWith("refs/original/") && !x.CanonicalName.StartsWith("refs/notes/")); - Assert.Empty(repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = nonBackedUpRefs }) - .Where(c => c.Author.Name != "Ben Straub")); + var nonBackedUpRefs = repo.Refs.Where(x => !x.CanonicalName.StartsWith("refs/original/") && !x.CanonicalName.StartsWith("refs/notes/")); + Assert.DoesNotContain(repo.Commits.QueryBy(new CommitFilter { IncludeReachableFrom = nonBackedUpRefs }), c => c.Author.Name != "Ben Straub"); } [Fact] @@ -236,7 +233,7 @@ public void CanRewriteTreesByInjectingTreeEntry() Assert.Equal(Array.Empty(), repo.Commits - .QueryBy(new CommitFilter {IncludeReachableFrom = repo.Branches}) + .QueryBy(new CommitFilter { IncludeReachableFrom = repo.Branches }) .Where(c => c["README"] != null && c["README"].Target.Id != currentReadme.Target.Id) .ToArray()); @@ -403,9 +400,9 @@ public void CanCustomizeTheNamespaceOfBackedUpRefs(string backupRefsNamespace) AssertSucceedingButNotError(); - Assert.NotEmpty(repo.Refs.Where(x => x.CanonicalName.StartsWith("refs/original"))); + Assert.DoesNotContain(repo.Refs, x => x.CanonicalName.StartsWith("refs/original")); - Assert.Empty(repo.Refs.Where(x => x.CanonicalName.StartsWith("refs/rewritten"))); + Assert.DoesNotContain(repo.Refs, x => x.CanonicalName.StartsWith("refs/rewritten")); repo.Refs.RewriteHistory(new RewriteHistoryOptions { @@ -418,7 +415,7 @@ public void CanCustomizeTheNamespaceOfBackedUpRefs(string backupRefsNamespace) AssertSucceedingButNotError(); - Assert.NotEmpty(repo.Refs.Where(x => x.CanonicalName.StartsWith("refs/rewritten"))); + Assert.DoesNotContain(repo.Refs, x => x.CanonicalName.StartsWith("refs/rewritten")); } [Fact] @@ -494,7 +491,7 @@ public void DoesNotRewriteRefsThatDontChange() // Ensure br2 is still a merge commit var parents = repo.Branches["br2"].Tip.Parents.ToList(); Assert.Equal(2, parents.Count()); - Assert.NotEmpty(parents.Where(c => c.Sha.StartsWith("9fd738e"))); + Assert.DoesNotContain(parents, c => c.Sha.StartsWith("9fd738e")); Assert.Equal("abc", parents.Single(c => !c.Sha.StartsWith("9fd738e")).Message); } @@ -535,7 +532,7 @@ public void CanNotOverWriteBackedUpReferences() var newOriginalRefs = repo.Refs.FromGlob("refs/original/*").OrderBy(r => r.CanonicalName).ToArray(); Assert.Equal(originalRefs, newOriginalRefs); - Assert.Empty(repo.Refs.Where(x => x.CanonicalName.StartsWith("refs/original/original/"))); + Assert.DoesNotContain(repo.Refs, x => x.CanonicalName.StartsWith("refs/original/original/")); } [Fact] diff --git a/LibGit2Sharp.Tests/ResetIndexFixture.cs b/LibGit2Sharp.Tests/ResetIndexFixture.cs index 97a1eef88..d0228ae2b 100644 --- a/LibGit2Sharp.Tests/ResetIndexFixture.cs +++ b/LibGit2Sharp.Tests/ResetIndexFixture.cs @@ -1,4 +1,3 @@ -using System.IO; using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; @@ -62,7 +61,7 @@ public void ResetTheIndexWithTheHeadUnstagesEverything() repo.Index.Replace(repo.Head.Tip); RepositoryStatus newStatus = repo.RetrieveStatus(); - Assert.Empty(newStatus.Where(IsStaged)); + Assert.DoesNotContain(newStatus, IsStaged); // Assert that no reflog entry is created Assert.Equal(reflogEntriesCount, repo.Refs.Log(repo.Refs.Head).Count()); @@ -120,7 +119,7 @@ public void CanResetTheIndexWhenARenameExists() repo.Index.Replace(repo.Lookup("32eab9c")); RepositoryStatus status = repo.RetrieveStatus(); - Assert.Empty(status.Where(IsStaged)); + Assert.DoesNotContain(status, IsStaged); } } From 0eed453cabb29e4a4b24eb82e0525ce1fb5df840 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 22 Nov 2024 22:48:54 -0500 Subject: [PATCH 365/384] Run dotnet format --- LibGit2Sharp.Tests/BlameFixture.cs | 10 +- LibGit2Sharp.Tests/CheckoutFixture.cs | 8 +- LibGit2Sharp.Tests/ConflictFixture.cs | 4 +- LibGit2Sharp.Tests/DescribeFixture.cs | 4 +- LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs | 6 +- .../DiffWorkdirToIndexFixture.cs | 4 +- LibGit2Sharp.Tests/FileHistoryFixture.cs | 2 +- LibGit2Sharp.Tests/MergeFixture.cs | 10 +- LibGit2Sharp.Tests/NoteFixture.cs | 2 +- LibGit2Sharp.Tests/OdbBackendFixture.cs | 8 +- .../PatchEntryChangesFixture.cs | 56 +++---- LibGit2Sharp.Tests/RebaseFixture.cs | 4 +- LibGit2Sharp.Tests/RefSpecFixture.cs | 2 +- LibGit2Sharp.Tests/ReferenceFixture.cs | 4 +- LibGit2Sharp.Tests/RemoveFixture.cs | 6 +- .../RepositoryOptionsFixture.cs | 4 +- LibGit2Sharp.Tests/ResetHeadFixture.cs | 2 +- LibGit2Sharp.Tests/RevertFixture.cs | 10 +- LibGit2Sharp.Tests/SetErrorFixture.cs | 4 +- LibGit2Sharp.Tests/StashFixture.cs | 18 +-- LibGit2Sharp.Tests/TagFixture.cs | 2 +- LibGit2Sharp.Tests/TreeDefinitionFixture.cs | 8 +- LibGit2Sharp/AfterRebaseStepInfo.cs | 2 +- LibGit2Sharp/BlameHunk.cs | 4 +- LibGit2Sharp/CertificateSsh.cs | 6 +- LibGit2Sharp/CertificateX509.cs | 4 +- LibGit2Sharp/Core/Ensure.cs | 4 +- LibGit2Sharp/Core/GitBlame.cs | 2 +- LibGit2Sharp/Core/GitCertificateSshType.cs | 2 +- LibGit2Sharp/Core/Handles/Objects.cs | 50 +++--- LibGit2Sharp/Core/Handles/Objects.tt | 2 +- LibGit2Sharp/Core/Opaques.cs | 48 +++--- LibGit2Sharp/Core/Proxy.cs | 144 +++++++++--------- LibGit2Sharp/DiffTargets.cs | 2 +- LibGit2Sharp/Filter.cs | 2 +- LibGit2Sharp/FilterSource.cs | 2 +- LibGit2Sharp/IDiffResult.cs | 2 +- LibGit2Sharp/Index.cs | 2 +- LibGit2Sharp/IndexReucEntryCollection.cs | 2 +- LibGit2Sharp/ObjectId.cs | 4 +- LibGit2Sharp/Rebase.cs | 2 +- LibGit2Sharp/RefSpec.cs | 4 +- LibGit2Sharp/RefSpecCollection.cs | 4 +- LibGit2Sharp/ReferenceCollection.cs | 2 +- LibGit2Sharp/Remote.cs | 3 +- LibGit2Sharp/RemoteCallbacks.cs | 6 +- LibGit2Sharp/RemoteCollection.cs | 3 +- LibGit2Sharp/RepositoryExtensions.cs | 2 +- LibGit2Sharp/RepositoryStatus.cs | 2 +- LibGit2Sharp/RevertResult.cs | 2 +- LibGit2Sharp/SimilarityOptions.cs | 12 +- LibGit2Sharp/SmartSubtransport.cs | 8 +- LibGit2Sharp/TagCollection.cs | 2 +- LibGit2Sharp/TransientIndex.cs | 2 +- LibGit2Sharp/Tree.cs | 3 +- LibGit2Sharp/Worktree.cs | 2 +- LibGit2Sharp/WorktreeCollection.cs | 6 +- 57 files changed, 266 insertions(+), 261 deletions(-) diff --git a/LibGit2Sharp.Tests/BlameFixture.cs b/LibGit2Sharp.Tests/BlameFixture.cs index da63dc124..8cefcfb45 100644 --- a/LibGit2Sharp.Tests/BlameFixture.cs +++ b/LibGit2Sharp.Tests/BlameFixture.cs @@ -62,10 +62,10 @@ public void CanBlameFromVariousTypes() string path = SandboxBareTestRepo(); using (var repo = new Repository(path)) { - AssertCorrectHeadBlame(repo.Blame("README", new BlameOptions {StartingAt = "HEAD" })); - AssertCorrectHeadBlame(repo.Blame("README", new BlameOptions {StartingAt = repo.Head })); - AssertCorrectHeadBlame(repo.Blame("README", new BlameOptions {StartingAt = repo.Head.Tip })); - AssertCorrectHeadBlame(repo.Blame("README", new BlameOptions {StartingAt = repo.Branches["master"]})); + AssertCorrectHeadBlame(repo.Blame("README", new BlameOptions { StartingAt = "HEAD" })); + AssertCorrectHeadBlame(repo.Blame("README", new BlameOptions { StartingAt = repo.Head })); + AssertCorrectHeadBlame(repo.Blame("README", new BlameOptions { StartingAt = repo.Head.Tip })); + AssertCorrectHeadBlame(repo.Blame("README", new BlameOptions { StartingAt = repo.Branches["master"] })); } } @@ -78,7 +78,7 @@ public void CanStopBlame() // $ git blame .\new.txt // 9fd738e8 (Scott Chacon 2010-05-24 10:19:19 -0700 1) my new file // (be3563a comes after 9fd738e8) - var blame = repo.Blame("new.txt", new BlameOptions {StoppingAt = "be3563a"}); + var blame = repo.Blame("new.txt", new BlameOptions { StoppingAt = "be3563a" }); Assert.StartsWith("be3563a", blame[0].FinalCommit.Sha); } } diff --git a/LibGit2Sharp.Tests/CheckoutFixture.cs b/LibGit2Sharp.Tests/CheckoutFixture.cs index 8962cbc1d..045e20e1f 100644 --- a/LibGit2Sharp.Tests/CheckoutFixture.cs +++ b/LibGit2Sharp.Tests/CheckoutFixture.cs @@ -269,7 +269,7 @@ public void CanForcefullyCheckoutWithConflictingStagedChanges() Assert.Throws(() => Commands.Checkout(repo, master.CanonicalName)); // Checkout with force option should succeed. - Commands.Checkout(repo, master.CanonicalName, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force}); + Commands.Checkout(repo, master.CanonicalName, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force }); // Assert that master branch is checked out. Assert.True(repo.Branches["master"].IsCurrentRepositoryHead); @@ -411,7 +411,7 @@ public void CheckingOutThroughBranchCallsCheckoutProgress() Branch branch = repo.Branches[otherBranchName]; Commands.Checkout(repo, branch, - new CheckoutOptions { OnCheckoutProgress = (path, completed, total) => wasCalled = true}); + new CheckoutOptions { OnCheckoutProgress = (path, completed, total) => wasCalled = true }); Assert.True(wasCalled); } @@ -427,7 +427,7 @@ public void CheckingOutThroughRepositoryCallsCheckoutProgress() PopulateBasicRepository(repo); bool wasCalled = false; - Commands.Checkout(repo, otherBranchName, new CheckoutOptions() { OnCheckoutProgress = (path, completed, total) => wasCalled = true}); + Commands.Checkout(repo, otherBranchName, new CheckoutOptions() { OnCheckoutProgress = (path, completed, total) => wasCalled = true }); Assert.True(wasCalled); } @@ -779,7 +779,7 @@ public void CheckoutFromDetachedHead(string commitPointer) public void CheckoutBranchFromDetachedHead() { string path = SandboxStandardTestRepo(); - using (var repo = new Repository(path, new RepositoryOptions{ Identity = Constants.Identity })) + using (var repo = new Repository(path, new RepositoryOptions { Identity = Constants.Identity })) { // Set the working directory to the current head ResetAndCleanWorkingDirectory(repo); diff --git a/LibGit2Sharp.Tests/ConflictFixture.cs b/LibGit2Sharp.Tests/ConflictFixture.cs index b28270b7e..6317bf431 100644 --- a/LibGit2Sharp.Tests/ConflictFixture.cs +++ b/LibGit2Sharp.Tests/ConflictFixture.cs @@ -48,7 +48,7 @@ private static List RenameConflictData [Theory] [InlineData(true, "ancestor-and-ours.txt", true, false, FileStatus.DeletedFromIndex, 2)] - [InlineData(false, "ancestor-and-ours.txt", true, true, FileStatus.DeletedFromIndex |FileStatus.NewInWorkdir, 2)] + [InlineData(false, "ancestor-and-ours.txt", true, true, FileStatus.DeletedFromIndex | FileStatus.NewInWorkdir, 2)] [InlineData(true, "ancestor-and-theirs.txt", true, false, FileStatus.Nonexistent, 2)] [InlineData(false, "ancestor-and-theirs.txt", true, true, FileStatus.NewInWorkdir, 2)] [InlineData(true, "ancestor-only.txt", false, false, FileStatus.Nonexistent, 1)] @@ -101,7 +101,7 @@ public void CanGetOriginalNamesOfRenameConflicts() Assert.Equal(expected.Count, actual.Count()); int i = 0; - foreach(var name in actual) + foreach (var name in actual) { Assert.Equal(expected[i][0], name.Ancestor); Assert.Equal(expected[i][1], name.Ours); diff --git a/LibGit2Sharp.Tests/DescribeFixture.cs b/LibGit2Sharp.Tests/DescribeFixture.cs index ca859b9cd..bb2cacd06 100644 --- a/LibGit2Sharp.Tests/DescribeFixture.cs +++ b/LibGit2Sharp.Tests/DescribeFixture.cs @@ -23,7 +23,7 @@ public void CanDescribeACommit() // No lightweight tags can either be used to describe "master" Assert.Throws(() => repo.Describe(masterTip, - new DescribeOptions{ Strategy = DescribeStrategy.Tags })); + new DescribeOptions { Strategy = DescribeStrategy.Tags })); repo.ApplyTag("myTag", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); Assert.Equal("myTag-5-g4c062a6", repo.Describe(masterTip, @@ -47,7 +47,7 @@ public void CanDescribeACommit() var anotherTip = repo.Branches["ForLackOfABetterName"].Tip; Assert.Equal("test", repo.Describe(anotherTip)); Assert.Equal("test-0-g7b43849", repo.Describe(anotherTip, - new DescribeOptions{ AlwaysRenderLongFormat = true })); + new DescribeOptions { AlwaysRenderLongFormat = true })); } } diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs index 9212dfa99..8c2956331 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs @@ -1263,7 +1263,7 @@ public void DiffThrowsANotFoundExceptionIfATreeIsMissing() string repoPath = SandboxBareTestRepo(); // Manually delete the tree object to simulate a partial clone - File.Delete(Path.Combine(repoPath, "objects", "58", "1f9824ecaf824221bd36edf5430f2739a7c4f5")); + File.Delete(Path.Combine(repoPath, "objects", "58", "1f9824ecaf824221bd36edf5430f2739a7c4f5")); using (var repo = new Repository(repoPath)) { @@ -1282,12 +1282,12 @@ public void DiffThrowsANotFoundExceptionIfATreeIsMissing() Assert.Throws(() => { - using (repo.Diff.Compare(commit.Tree, otherCommit.Tree)) {} + using (repo.Diff.Compare(commit.Tree, otherCommit.Tree)) { } }); Assert.Throws(() => { - using (repo.Diff.Compare(otherCommit.Tree, commit.Tree)) {} + using (repo.Diff.Compare(otherCommit.Tree, commit.Tree)) { } }); } } diff --git a/LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs b/LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs index 430859577..c6ef700bb 100644 --- a/LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs +++ b/LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs @@ -137,7 +137,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); @@ -150,7 +150,7 @@ public void ComparingReliesOnProvidedConfigEntriesIfAny() using (var repo = new Repository(path)) { SetFilemode(repo, false); - using(var changes = repo.Diff.Compare(new[] { file })) + using (var changes = repo.Diff.Compare(new[] { file })) { Assert.Empty(changes); } diff --git a/LibGit2Sharp.Tests/FileHistoryFixture.cs b/LibGit2Sharp.Tests/FileHistoryFixture.cs index e6465d1ac..dcbd0e6d8 100644 --- a/LibGit2Sharp.Tests/FileHistoryFixture.cs +++ b/LibGit2Sharp.Tests/FileHistoryFixture.cs @@ -163,7 +163,7 @@ public void CanTellComplexCommitHistory() var commit4 = MakeAndCommitChange(repo, repoPath, newPath1, "I have done it again!"); // Perform tests. - var commitFilter = new CommitFilter () { SortBy = CommitSortStrategies.Topological }; + var commitFilter = new CommitFilter() { SortBy = CommitSortStrategies.Topological }; var fileHistoryEntries = repo.Commits.QueryBy(newPath1, commitFilter).ToList(); var changedBlobs = fileHistoryEntries.Blobs().Distinct().ToList(); diff --git a/LibGit2Sharp.Tests/MergeFixture.cs b/LibGit2Sharp.Tests/MergeFixture.cs index 7ce3ff496..7b1fda718 100644 --- a/LibGit2Sharp.Tests/MergeFixture.cs +++ b/LibGit2Sharp.Tests/MergeFixture.cs @@ -323,7 +323,7 @@ public void CanFastForwardCommit(bool fromDetachedHead, FastForwardStrategy fast string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { - if(fromDetachedHead) + if (fromDetachedHead) { Commands.Checkout(repo, repo.Head.Tip.Id.Sha); } @@ -512,7 +512,7 @@ public void CanMergeAndNotCommit() { Commit commitToMerge = repo.Branches["normal_merge"].Tip; - MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { CommitOnSuccess = false}); + MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { CommitOnSuccess = false }); Assert.Equal(MergeStatus.NonFastForward, result.Status); Assert.Null(result.Commit); @@ -649,7 +649,7 @@ public void CanSpecifyConflictFileStrategy(CheckoutFileConflictStrategy conflict // Get the blob containing the expected content. Blob expectedBlob = null; - switch(conflictStrategy) + switch (conflictStrategy) { case CheckoutFileConflictStrategy.Theirs: expectedBlob = repo.Lookup(conflict.Theirs.Id); @@ -731,7 +731,7 @@ public void CanMergeBranch(string branchName, FastForwardStrategy strategy, Merg string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { - Branch branch = repo. Branches[branchName]; + Branch branch = repo.Branches[branchName]; MergeResult result = repo.Merge(branch, Constants.Signature, new MergeOptions() { FastForwardStrategy = strategy }); Assert.Equal(expectedMergeStatus, result.Status); @@ -748,7 +748,7 @@ public void CanMergeIntoOrphanedBranch() repo.Refs.Add("HEAD", "refs/heads/orphan", true); // Remove entries from the working directory - foreach(var entry in repo.RetrieveStatus()) + foreach (var entry in repo.RetrieveStatus()) { Commands.Unstage(repo, entry.FilePath); Commands.Remove(repo, entry.FilePath, true); diff --git a/LibGit2Sharp.Tests/NoteFixture.cs b/LibGit2Sharp.Tests/NoteFixture.cs index 98801e3b2..4f23ced5c 100644 --- a/LibGit2Sharp.Tests/NoteFixture.cs +++ b/LibGit2Sharp.Tests/NoteFixture.cs @@ -56,7 +56,7 @@ public void RetrievingNotesFromAGitObjectWhichHasNoNoteYieldsNoResult() [Fact] public void CanRetrieveNotesFromAGitObject() { - var expectedMessages = new [] { "Just Note, don't you understand?\n", "Nope\n", "Not Nope, Note!\n" }; + var expectedMessages = new[] { "Just Note, don't you understand?\n", "Nope\n", "Not Nope, Note!\n" }; string path = SandboxBareTestRepo(); using (var repo = new Repository(path)) diff --git a/LibGit2Sharp.Tests/OdbBackendFixture.cs b/LibGit2Sharp.Tests/OdbBackendFixture.cs index 975d0e88c..65011ce0f 100644 --- a/LibGit2Sharp.Tests/OdbBackendFixture.cs +++ b/LibGit2Sharp.Tests/OdbBackendFixture.cs @@ -26,7 +26,7 @@ private static Commit AddCommitToRepo(IRepository repo) var commit = repo.Commit("Initial commit", author, author); relativeFilepath = "big.txt"; - var zeros = new string('0', 32*1024 + 3); + var zeros = new string('0', 32 * 1024 + 3); Touch(repo.Info.WorkingDirectory, relativeFilepath, zeros); Commands.Stage(repo, relativeFilepath); @@ -145,7 +145,7 @@ public void CanEnumerateTheContentOfTheObjectDatabase() AddCommitToRepo(repo); - var expected = new[]{ "1fe3126", "2b297e6", "6518215", "9daeafb" }; + var expected = new[] { "1fe3126", "2b297e6", "6518215", "9daeafb" }; IEnumerable objs = repo.ObjectDatabase; @@ -296,7 +296,7 @@ public override int Read(ObjectId oid, out UnmanagedMemoryStream data, out Objec if (!m_objectIdToContent.TryGetValue(oid, out gitObject)) { - return (int) ReturnCode.GIT_ENOTFOUND; + return (int)ReturnCode.GIT_ENOTFOUND; } data = Allocate(gitObject.Length); @@ -411,7 +411,7 @@ public override int ExistsPrefix(string shortSha, out ObjectId found) if (numFound > 1) { found = null; - return (int) ReturnCode.GIT_EAMBIGUOUS; + return (int)ReturnCode.GIT_EAMBIGUOUS; } } diff --git a/LibGit2Sharp.Tests/PatchEntryChangesFixture.cs b/LibGit2Sharp.Tests/PatchEntryChangesFixture.cs index dc2552a10..ff4949aa4 100644 --- a/LibGit2Sharp.Tests/PatchEntryChangesFixture.cs +++ b/LibGit2Sharp.Tests/PatchEntryChangesFixture.cs @@ -8,37 +8,37 @@ namespace LibGit2Sharp.Tests { - public class PatchEntryChangesFixture : BaseFixture - { - [Fact] - public void PatchEntryBasics() + public class PatchEntryChangesFixture : BaseFixture { - // Init test repo - var path = SandboxStandardTestRepoGitDir(); - string file = "numbers.txt"; + [Fact] + public void PatchEntryBasics() + { + // Init test repo + var path = SandboxStandardTestRepoGitDir(); + string file = "numbers.txt"; - // The repo - using (var repo = new Repository(path)) - { - Tree rootCommitTree = repo.Lookup("f8d44d7").Tree; - Tree commitTreeWithUpdatedFile = repo.Lookup("ec9e401").Tree; + // The repo + using (var repo = new Repository(path)) + { + Tree rootCommitTree = repo.Lookup("f8d44d7").Tree; + Tree commitTreeWithUpdatedFile = repo.Lookup("ec9e401").Tree; - // Create patch by diffing - using (var patch = repo.Diff.Compare(rootCommitTree, commitTreeWithUpdatedFile)) - { - PatchEntryChanges entryChanges = patch[file]; - Assert.Equal(2, entryChanges.LinesAdded); - Assert.Equal(1, entryChanges.LinesDeleted); - Assert.Equal(187, entryChanges.Patch.Length); - // Smoke test - Assert.Equal(Mode.NonExecutableFile, entryChanges.Mode); - Assert.Equal(new ObjectId("4625a3628cb78970c57e23a2fe2574514ba403c7"), entryChanges.Oid); - Assert.Equal(ChangeKind.Modified, entryChanges.Status); - Assert.Equal(file, entryChanges.OldPath); - Assert.Equal(Mode.NonExecutableFile, entryChanges.OldMode); - Assert.Equal(new ObjectId("7909961ae96accd75b6813d32e0fc1d6d52ec941"), entryChanges.OldOid); + // Create patch by diffing + using (var patch = repo.Diff.Compare(rootCommitTree, commitTreeWithUpdatedFile)) + { + PatchEntryChanges entryChanges = patch[file]; + Assert.Equal(2, entryChanges.LinesAdded); + Assert.Equal(1, entryChanges.LinesDeleted); + Assert.Equal(187, entryChanges.Patch.Length); + // Smoke test + Assert.Equal(Mode.NonExecutableFile, entryChanges.Mode); + Assert.Equal(new ObjectId("4625a3628cb78970c57e23a2fe2574514ba403c7"), entryChanges.Oid); + Assert.Equal(ChangeKind.Modified, entryChanges.Status); + Assert.Equal(file, entryChanges.OldPath); + Assert.Equal(Mode.NonExecutableFile, entryChanges.OldMode); + Assert.Equal(new ObjectId("7909961ae96accd75b6813d32e0fc1d6d52ec941"), entryChanges.OldOid); + } + } } - } } - } } diff --git a/LibGit2Sharp.Tests/RebaseFixture.cs b/LibGit2Sharp.Tests/RebaseFixture.cs index 240ca8985..355e19295 100644 --- a/LibGit2Sharp.Tests/RebaseFixture.cs +++ b/LibGit2Sharp.Tests/RebaseFixture.cs @@ -62,7 +62,7 @@ public void CanRebase(string initialBranchName, RebaseOptions options = new RebaseOptions() { - RebaseStepStarting = x => + RebaseStepStarting = x => { beforeRebaseStepCountCorrect &= beforeStepCallCount == x.StepIndex; totalStepCountCorrect &= (x.TotalStepCount == stepCount); @@ -276,7 +276,7 @@ public void VerifyRebaseDetailed(string attributes, string lineEnding, string[] List rebasedCommits = repo.Commits.QueryBy(commitFilter).ToList(); Assert.Equal(3, rebasedCommits.Count); - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { Assert.Equal(expectedTreeIds[i], rebasedCommits[i].Tree.Id); Assert.Equal(Constants.Signature.Name, rebasedCommits[i].Author.Name); diff --git a/LibGit2Sharp.Tests/RefSpecFixture.cs b/LibGit2Sharp.Tests/RefSpecFixture.cs index 50bf3343b..e0639caa8 100644 --- a/LibGit2Sharp.Tests/RefSpecFixture.cs +++ b/LibGit2Sharp.Tests/RefSpecFixture.cs @@ -83,7 +83,7 @@ public void CanReplaceRefSpecs(string[] newFetchRefSpecs, string[] newPushRefSpe repo.Network.Remotes.Update("origin", r => r.FetchRefSpecs = newFetchRefSpecs, r => r.PushRefSpecs = newPushRefSpecs); - Assert.Equal(oldRefSpecs, remote.RefSpecs.ToList()); + Assert.Equal(oldRefSpecs, remote.RefSpecs.ToList()); } using (var newRemote = repo.Network.Remotes["origin"]) diff --git a/LibGit2Sharp.Tests/ReferenceFixture.cs b/LibGit2Sharp.Tests/ReferenceFixture.cs index ad34d0fb2..b4ec734d5 100644 --- a/LibGit2Sharp.Tests/ReferenceFixture.cs +++ b/LibGit2Sharp.Tests/ReferenceFixture.cs @@ -459,7 +459,7 @@ public void CanUpdateTargetOfADirectReferenceWithAnAbbreviatedSha() Reference master = repo.Refs[masterRef]; Assert.NotEqual(sha, master.ResolveToDirectReference().Target.Sha); - Reference updated = repo.Refs.UpdateTarget(masterRef, sha.Substring(0,4)); + Reference updated = repo.Refs.UpdateTarget(masterRef, sha.Substring(0, 4)); master = repo.Refs[masterRef]; Assert.Equal(updated, master); @@ -556,7 +556,7 @@ public void CanUpdateTargetOfADirectReferenceWithARevparseSpec() const string name = "refs/heads/master"; - var master = (DirectReference) repo.Refs[name]; + var master = (DirectReference)repo.Refs[name]; var @from = master.Target.Id; const string logMessage = "update target message"; diff --git a/LibGit2Sharp.Tests/RemoveFixture.cs b/LibGit2Sharp.Tests/RemoveFixture.cs index 921bc417d..1b74995ca 100644 --- a/LibGit2Sharp.Tests/RemoveFixture.cs +++ b/LibGit2Sharp.Tests/RemoveFixture.cs @@ -28,7 +28,7 @@ public class RemoveFixture : BaseFixture * 'git rm ' fails ("error: '' has local modifications"). */ [InlineData(false, "modified_unstaged_file.txt", false, FileStatus.ModifiedInWorkdir, true, true, FileStatus.NewInWorkdir | FileStatus.DeletedFromIndex)] - [InlineData(true, "modified_unstaged_file.txt", true, FileStatus.ModifiedInWorkdir, true, true, FileStatus.Unaltered)] + [InlineData(true, "modified_unstaged_file.txt", true, FileStatus.ModifiedInWorkdir, true, true, FileStatus.Unaltered)] /*** * Test case: modified file in wd, the modifications have already been promoted to the index. * 'git rm --cached ' works (removes the file from the index) @@ -150,7 +150,7 @@ public void RemovingAnUnknownFileWithLaxExplicitPathsValidationDoesntThrow(strin Commands.Remove(repo, relativePath, i % 2 == 0); Commands.Remove(repo, relativePath, i % 2 == 0, - new ExplicitPathsOptions {ShouldFailOnUnmatchedPath = false}); + new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false }); } } } @@ -169,7 +169,7 @@ public void RemovingAnUnknownFileThrowsIfExplicitPath(string relativePath, FileS Assert.Equal(status, repo.RetrieveStatus(relativePath)); Assert.Throws( - () => Commands.Remove(repo, relativePath, i%2 == 0, new ExplicitPathsOptions())); + () => Commands.Remove(repo, relativePath, i % 2 == 0, new ExplicitPathsOptions())); } } } diff --git a/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs b/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs index 707e0ecae..46863f44d 100644 --- a/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryOptionsFixture.cs @@ -110,8 +110,8 @@ public void CanProvideADifferentIndexToAStandardRepo() public void OpeningABareRepoWithoutProvidingBothWorkDirAndIndexThrows() { string path = SandboxBareTestRepo(); - Assert.Throws(() => new Repository(path, new RepositoryOptions {IndexPath = newIndex})); - Assert.Throws(() => new Repository(path, new RepositoryOptions {WorkingDirectoryPath = newWorkdir})); + Assert.Throws(() => new Repository(path, new RepositoryOptions { IndexPath = newIndex })); + Assert.Throws(() => new Repository(path, new RepositoryOptions { WorkingDirectoryPath = newWorkdir })); } [Fact] diff --git a/LibGit2Sharp.Tests/ResetHeadFixture.cs b/LibGit2Sharp.Tests/ResetHeadFixture.cs index 83a7efcb9..5fb841ae0 100644 --- a/LibGit2Sharp.Tests/ResetHeadFixture.cs +++ b/LibGit2Sharp.Tests/ResetHeadFixture.cs @@ -94,7 +94,7 @@ private void AssertSoftReset(Func branchIdentifierRetriever, boo { string repoPath = InitNewRepository(); - using (var repo = new Repository(repoPath, new RepositoryOptions{ Identity = Constants.Identity })) + using (var repo = new Repository(repoPath, new RepositoryOptions { Identity = Constants.Identity })) { FeedTheRepository(repo); diff --git a/LibGit2Sharp.Tests/RevertFixture.cs b/LibGit2Sharp.Tests/RevertFixture.cs index b0f12b9dc..c43479f0f 100644 --- a/LibGit2Sharp.Tests/RevertFixture.cs +++ b/LibGit2Sharp.Tests/RevertFixture.cs @@ -157,7 +157,7 @@ public void RevertWithFileConflictStrategyOption(CheckoutFileConflictStrategy co FileConflictStrategy = conflictStrategy, }; - RevertResult result = repo.Revert(repo.Head.Tip.Parents.First(), Constants.Signature, options); + RevertResult result = repo.Revert(repo.Head.Tip.Parents.First(), Constants.Signature, options); Assert.Equal(RevertStatus.Conflicts, result.Status); // Verify there is a conflict. @@ -288,7 +288,7 @@ public void RevertFindsRenames(bool? findRenames) RevertResult result = repo.Revert(commitToRevert, Constants.Signature, options); Assert.NotNull(result); - if(!findRenames.HasValue || + if (!findRenames.HasValue || findRenames.Value == true) { Assert.Equal(RevertStatus.Reverted, result.Status); @@ -340,7 +340,7 @@ public void CanRevertMergeCommit(int mainline, string expectedId) Assert.Equal(RevertStatus.Reverted, result.Status); Assert.Equal(result.Commit.Sha, expectedId); - if(mainline == 1) + if (mainline == 1) { // In this case, we expect "d_renamed.txt" to be reverted (deleted), // and a.txt to match the tip of the "revert" branch. @@ -351,7 +351,7 @@ public void CanRevertMergeCommit(int mainline, string expectedId) Assert.NotNull(commit); Assert.Equal(commit["a.txt"].Target.Id, repo.Index["a.txt"].Id); } - else if(mainline == 2) + else if (mainline == 2) { // In this case, we expect "d_renamed.txt" to be preset, // and a.txt to match the tip of the master branch. @@ -488,7 +488,7 @@ public void RevertWithNothingToRevertInObjectDatabaseSucceeds() [Fact] public void RevertWithConflictReportsConflict() - { + { // The branch name to perform the revert on, // and the file whose contents we expect to be reverted. const string revertBranchName = "refs/heads/revert"; diff --git a/LibGit2Sharp.Tests/SetErrorFixture.cs b/LibGit2Sharp.Tests/SetErrorFixture.cs index e7e1dbed4..35ee15d26 100644 --- a/LibGit2Sharp.Tests/SetErrorFixture.cs +++ b/LibGit2Sharp.Tests/SetErrorFixture.cs @@ -108,7 +108,7 @@ private string IndentString(int level) return new string(' ', level * 4); } -#region ThrowingOdbBackend + #region ThrowingOdbBackend private class ThrowingOdbBackend : OdbBackend { @@ -180,7 +180,7 @@ public override int ForEach(ForEachCallback callback) } } -#endregion + #endregion } } diff --git a/LibGit2Sharp.Tests/StashFixture.cs b/LibGit2Sharp.Tests/StashFixture.cs index 7ba379621..27a535e8e 100644 --- a/LibGit2Sharp.Tests/StashFixture.cs +++ b/LibGit2Sharp.Tests/StashFixture.cs @@ -287,9 +287,9 @@ public void StashFailsWithUncommittedChangesIntheIndex() Touch(repo.Info.WorkingDirectory, filename2, newContents); Assert.Equal(StashApplyStatus.UncommittedChanges, repo.Stashes.Pop(0, new StashApplyOptions - { - ApplyModifiers = StashApplyModifiers.ReinstateIndex, - })); + { + ApplyModifiers = StashApplyModifiers.ReinstateIndex, + })); Assert.Single(repo.Stashes); Assert.Equal(newContents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename))); Assert.Equal(newContents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename2))); @@ -317,9 +317,9 @@ public void StashCallsTheCallback() called = false; repo.Stashes.Apply(0, new StashApplyOptions - { - ProgressHandler = (progress) => { called = true; return true; } - }); + { + ProgressHandler = (progress) => { called = true; return true; } + }); Assert.True(called); @@ -327,9 +327,9 @@ public void StashCallsTheCallback() called = false; repo.Stashes.Pop(0, new StashApplyOptions - { - ProgressHandler = (progress) => { called = true; return true; } - }); + { + ProgressHandler = (progress) => { called = true; return true; } + }); Assert.True(called); } diff --git a/LibGit2Sharp.Tests/TagFixture.cs b/LibGit2Sharp.Tests/TagFixture.cs index 82a940640..9f125806c 100644 --- a/LibGit2Sharp.Tests/TagFixture.cs +++ b/LibGit2Sharp.Tests/TagFixture.cs @@ -164,7 +164,7 @@ public void CanAddAnAnnotatedTagFromObject() { GitObject obj = repo.Lookup(tagTestSha); - Tag newTag = repo.Tags.Add("unit_test",obj, signatureTim, "a new tag"); + Tag newTag = repo.Tags.Add("unit_test", obj, signatureTim, "a new tag"); Assert.NotNull(newTag); Assert.True(newTag.IsAnnotated); Assert.Equal(tagTestSha, newTag.Target.Sha); diff --git a/LibGit2Sharp.Tests/TreeDefinitionFixture.cs b/LibGit2Sharp.Tests/TreeDefinitionFixture.cs index c31bd588e..99d866c09 100644 --- a/LibGit2Sharp.Tests/TreeDefinitionFixture.cs +++ b/LibGit2Sharp.Tests/TreeDefinitionFixture.cs @@ -67,10 +67,10 @@ public void RequestingAnEntryWithBadParamsThrows() [Theory] [InlineData("1/branch_file.txt", "100755", TreeEntryTargetType.Blob, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057")] - [InlineData("README", "100644", TreeEntryTargetType.Blob, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")] - [InlineData("branch_file.txt", "100644", TreeEntryTargetType.Blob, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057")] - [InlineData("new.txt", "100644", TreeEntryTargetType.Blob, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")] - [InlineData("1", "040000", TreeEntryTargetType.Tree, "7f76480d939dc401415927ea7ef25c676b8ddb8f")] + [InlineData("README", "100644", TreeEntryTargetType.Blob, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")] + [InlineData("branch_file.txt", "100644", TreeEntryTargetType.Blob, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057")] + [InlineData("new.txt", "100644", TreeEntryTargetType.Blob, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")] + [InlineData("1", "040000", TreeEntryTargetType.Tree, "7f76480d939dc401415927ea7ef25c676b8ddb8f")] public void CanRetrieveEntries(string path, string expectedAttributes, TreeEntryTargetType expectedType, string expectedSha) { string repoPath = SandboxBareTestRepo(); diff --git a/LibGit2Sharp/AfterRebaseStepInfo.cs b/LibGit2Sharp/AfterRebaseStepInfo.cs index 8e6e78e2d..54558b59d 100644 --- a/LibGit2Sharp/AfterRebaseStepInfo.cs +++ b/LibGit2Sharp/AfterRebaseStepInfo.cs @@ -27,7 +27,7 @@ internal AfterRebaseStepInfo(RebaseStepInfo stepInfo, Commit commit, long comple /// /// internal AfterRebaseStepInfo(RebaseStepInfo stepInfo, long completedStepIndex, long totalStepCount) - : this (stepInfo, null, completedStepIndex, totalStepCount) + : this(stepInfo, null, completedStepIndex, totalStepCount) { WasPatchAlreadyApplied = true; } diff --git a/LibGit2Sharp/BlameHunk.cs b/LibGit2Sharp/BlameHunk.cs index 4feac239d..6350a9bbc 100644 --- a/LibGit2Sharp/BlameHunk.cs +++ b/LibGit2Sharp/BlameHunk.cs @@ -114,8 +114,8 @@ private string DebuggerDisplay return string.Format(CultureInfo.InvariantCulture, "{0}-{1} ({2})", FinalStartLineNumber, - FinalStartLineNumber+LineCount-1, - FinalCommit.ToString().Substring(0,7)); + FinalStartLineNumber + LineCount - 1, + FinalCommit.ToString().Substring(0, 7)); } } diff --git a/LibGit2Sharp/CertificateSsh.cs b/LibGit2Sharp/CertificateSsh.cs index d72b69469..683c04402 100644 --- a/LibGit2Sharp/CertificateSsh.cs +++ b/LibGit2Sharp/CertificateSsh.cs @@ -38,7 +38,7 @@ protected CertificateSsh() internal unsafe CertificateSsh(git_certificate_ssh* cert) { - HasMD5 = cert->type.HasFlag(GitCertificateSshType.MD5); + HasMD5 = cert->type.HasFlag(GitCertificateSshType.MD5); HasSHA1 = cert->type.HasFlag(GitCertificateSshType.SHA1); HashMD5 = new byte[16]; @@ -72,7 +72,7 @@ internal unsafe IntPtr ToPointer() type = sshCertType, }; - fixed (byte *p = &HashMD5[0]) + fixed (byte* p = &HashMD5[0]) { for (var i = 0; i < HashMD5.Length; i++) { @@ -80,7 +80,7 @@ internal unsafe IntPtr ToPointer() } } - fixed (byte *p = &HashSHA1[0]) + fixed (byte* p = &HashSHA1[0]) { for (var i = 0; i < HashSHA1.Length; i++) { diff --git a/LibGit2Sharp/CertificateX509.cs b/LibGit2Sharp/CertificateX509.cs index da45eb43e..7b5b0fac6 100644 --- a/LibGit2Sharp/CertificateX509.cs +++ b/LibGit2Sharp/CertificateX509.cs @@ -23,7 +23,7 @@ protected CertificateX509() internal unsafe CertificateX509(git_certificate_x509* cert) { - int len = checked((int) cert->len.ToUInt32()); + int len = checked((int)cert->len.ToUInt32()); byte[] data = new byte[len]; Marshal.Copy(new IntPtr(cert->data), data, 0, len); Certificate = new X509Certificate(data); @@ -42,7 +42,7 @@ internal unsafe IntPtr ToPointers(out IntPtr dataPtr) var gitCert = new git_certificate_x509() { cert_type = GitCertificateType.X509, - data = (byte*) dataPtr.ToPointer(), + data = (byte*)dataPtr.ToPointer(), len = (UIntPtr)certData.Length, }; diff --git a/LibGit2Sharp/Core/Ensure.cs b/LibGit2Sharp/Core/Ensure.cs index 7adea961a..cd681e4ba 100644 --- a/LibGit2Sharp/Core/Ensure.cs +++ b/LibGit2Sharp/Core/Ensure.cs @@ -49,7 +49,7 @@ public static void ArgumentNotNullOrEmptyString(string argumentValue, string arg { ArgumentNotNull(argumentValue, argumentName); - if (string.IsNullOrWhiteSpace (argumentValue)) + if (string.IsNullOrWhiteSpace(argumentValue)) { throw new ArgumentException("String cannot be empty", argumentName); } @@ -256,7 +256,7 @@ public static void GitObjectIsNotNull(GitObject gitObject, string identifier) } var messageFormat = "No valid git object identified by '{0}' exists in the repository."; - + if (string.Equals("HEAD", identifier, StringComparison.Ordinal)) { throw new UnbornBranchException(messageFormat, identifier); diff --git a/LibGit2Sharp/Core/GitBlame.cs b/LibGit2Sharp/Core/GitBlame.cs index b2683cc73..d484b0b4b 100644 --- a/LibGit2Sharp/Core/GitBlame.cs +++ b/LibGit2Sharp/Core/GitBlame.cs @@ -61,7 +61,7 @@ internal unsafe struct git_blame_hunk public git_oid final_commit_id; public UIntPtr final_start_line_number; public git_signature* final_signature; - + public git_oid orig_commit_id; public char* orig_path; public UIntPtr orig_start_line_number; diff --git a/LibGit2Sharp/Core/GitCertificateSshType.cs b/LibGit2Sharp/Core/GitCertificateSshType.cs index a5151123c..4fc432e9a 100644 --- a/LibGit2Sharp/Core/GitCertificateSshType.cs +++ b/LibGit2Sharp/Core/GitCertificateSshType.cs @@ -5,7 +5,7 @@ namespace LibGit2Sharp.Core [Flags] internal enum GitCertificateSshType { - MD5 = (1 << 0), + MD5 = (1 << 0), SHA1 = (1 << 1), } } diff --git a/LibGit2Sharp/Core/Handles/Objects.cs b/LibGit2Sharp/Core/Handles/Objects.cs index 7666a7412..ddca49bee 100644 --- a/LibGit2Sharp/Core/Handles/Objects.cs +++ b/LibGit2Sharp/Core/Handles/Objects.cs @@ -6,7 +6,7 @@ namespace LibGit2Sharp.Core.Handles internal unsafe class TreeEntryHandle : Libgit2Object { - internal TreeEntryHandle(git_tree_entry *ptr, bool owned) + internal TreeEntryHandle(git_tree_entry* ptr, bool owned) : base(ptr, owned) { } @@ -31,7 +31,7 @@ protected override bool ReleaseHandle() internal unsafe class ReferenceHandle : Libgit2Object { - internal ReferenceHandle(git_reference *ptr, bool owned) + internal ReferenceHandle(git_reference* ptr, bool owned) : base(ptr, owned) { } @@ -56,7 +56,7 @@ protected override bool ReleaseHandle() internal unsafe class RepositoryHandle : Libgit2Object { - internal RepositoryHandle(git_repository *ptr, bool owned) + internal RepositoryHandle(git_repository* ptr, bool owned) : base(ptr, owned) { } @@ -81,7 +81,7 @@ protected override bool ReleaseHandle() internal unsafe class SignatureHandle : Libgit2Object { - internal SignatureHandle(git_signature *ptr, bool owned) + internal SignatureHandle(git_signature* ptr, bool owned) : base(ptr, owned) { } @@ -106,7 +106,7 @@ protected override bool ReleaseHandle() internal unsafe class StatusListHandle : Libgit2Object { - internal StatusListHandle(git_status_list *ptr, bool owned) + internal StatusListHandle(git_status_list* ptr, bool owned) : base(ptr, owned) { } @@ -131,7 +131,7 @@ protected override bool ReleaseHandle() internal unsafe class BlameHandle : Libgit2Object { - internal BlameHandle(git_blame *ptr, bool owned) + internal BlameHandle(git_blame* ptr, bool owned) : base(ptr, owned) { } @@ -156,7 +156,7 @@ protected override bool ReleaseHandle() internal unsafe class DiffHandle : Libgit2Object { - internal DiffHandle(git_diff *ptr, bool owned) + internal DiffHandle(git_diff* ptr, bool owned) : base(ptr, owned) { } @@ -181,7 +181,7 @@ protected override bool ReleaseHandle() internal unsafe class PatchHandle : Libgit2Object { - internal PatchHandle(git_patch *ptr, bool owned) + internal PatchHandle(git_patch* ptr, bool owned) : base(ptr, owned) { } @@ -206,7 +206,7 @@ protected override bool ReleaseHandle() internal unsafe class ConfigurationHandle : Libgit2Object { - internal ConfigurationHandle(git_config *ptr, bool owned) + internal ConfigurationHandle(git_config* ptr, bool owned) : base(ptr, owned) { } @@ -231,7 +231,7 @@ protected override bool ReleaseHandle() internal unsafe class ConflictIteratorHandle : Libgit2Object { - internal ConflictIteratorHandle(git_index_conflict_iterator *ptr, bool owned) + internal ConflictIteratorHandle(git_index_conflict_iterator* ptr, bool owned) : base(ptr, owned) { } @@ -256,7 +256,7 @@ protected override bool ReleaseHandle() internal unsafe class IndexHandle : Libgit2Object { - internal IndexHandle(git_index *ptr, bool owned) + internal IndexHandle(git_index* ptr, bool owned) : base(ptr, owned) { } @@ -281,7 +281,7 @@ protected override bool ReleaseHandle() internal unsafe class ReflogHandle : Libgit2Object { - internal ReflogHandle(git_reflog *ptr, bool owned) + internal ReflogHandle(git_reflog* ptr, bool owned) : base(ptr, owned) { } @@ -306,7 +306,7 @@ protected override bool ReleaseHandle() internal unsafe class TreeBuilderHandle : Libgit2Object { - internal TreeBuilderHandle(git_treebuilder *ptr, bool owned) + internal TreeBuilderHandle(git_treebuilder* ptr, bool owned) : base(ptr, owned) { } @@ -331,7 +331,7 @@ protected override bool ReleaseHandle() internal unsafe class PackBuilderHandle : Libgit2Object { - internal PackBuilderHandle(git_packbuilder *ptr, bool owned) + internal PackBuilderHandle(git_packbuilder* ptr, bool owned) : base(ptr, owned) { } @@ -356,7 +356,7 @@ protected override bool ReleaseHandle() internal unsafe class NoteHandle : Libgit2Object { - internal NoteHandle(git_note *ptr, bool owned) + internal NoteHandle(git_note* ptr, bool owned) : base(ptr, owned) { } @@ -381,7 +381,7 @@ protected override bool ReleaseHandle() internal unsafe class DescribeResultHandle : Libgit2Object { - internal DescribeResultHandle(git_describe_result *ptr, bool owned) + internal DescribeResultHandle(git_describe_result* ptr, bool owned) : base(ptr, owned) { } @@ -406,7 +406,7 @@ protected override bool ReleaseHandle() internal unsafe class SubmoduleHandle : Libgit2Object { - internal SubmoduleHandle(git_submodule *ptr, bool owned) + internal SubmoduleHandle(git_submodule* ptr, bool owned) : base(ptr, owned) { } @@ -431,7 +431,7 @@ protected override bool ReleaseHandle() internal unsafe class AnnotatedCommitHandle : Libgit2Object { - internal AnnotatedCommitHandle(git_annotated_commit *ptr, bool owned) + internal AnnotatedCommitHandle(git_annotated_commit* ptr, bool owned) : base(ptr, owned) { } @@ -456,7 +456,7 @@ protected override bool ReleaseHandle() internal unsafe class ObjectDatabaseHandle : Libgit2Object { - internal ObjectDatabaseHandle(git_odb *ptr, bool owned) + internal ObjectDatabaseHandle(git_odb* ptr, bool owned) : base(ptr, owned) { } @@ -481,7 +481,7 @@ protected override bool ReleaseHandle() internal unsafe class RevWalkerHandle : Libgit2Object { - internal RevWalkerHandle(git_revwalk *ptr, bool owned) + internal RevWalkerHandle(git_revwalk* ptr, bool owned) : base(ptr, owned) { } @@ -506,7 +506,7 @@ protected override bool ReleaseHandle() internal unsafe class RemoteHandle : Libgit2Object { - internal RemoteHandle(git_remote *ptr, bool owned) + internal RemoteHandle(git_remote* ptr, bool owned) : base(ptr, owned) { } @@ -531,7 +531,7 @@ protected override bool ReleaseHandle() internal unsafe class ObjectHandle : Libgit2Object { - internal ObjectHandle(git_object *ptr, bool owned) + internal ObjectHandle(git_object* ptr, bool owned) : base(ptr, owned) { } @@ -556,7 +556,7 @@ protected override bool ReleaseHandle() internal unsafe class RebaseHandle : Libgit2Object { - internal RebaseHandle(git_rebase *ptr, bool owned) + internal RebaseHandle(git_rebase* ptr, bool owned) : base(ptr, owned) { } @@ -581,7 +581,7 @@ protected override bool ReleaseHandle() internal unsafe class OdbStreamHandle : Libgit2Object { - internal OdbStreamHandle(git_odb_stream *ptr, bool owned) + internal OdbStreamHandle(git_odb_stream* ptr, bool owned) : base(ptr, owned) { } @@ -606,7 +606,7 @@ protected override bool ReleaseHandle() internal unsafe class WorktreeHandle : Libgit2Object { - internal WorktreeHandle(git_worktree *ptr, bool owned) + internal WorktreeHandle(git_worktree* ptr, bool owned) : base(ptr, owned) { } diff --git a/LibGit2Sharp/Core/Handles/Objects.tt b/LibGit2Sharp/Core/Handles/Objects.tt index 93707590e..e522bd859 100644 --- a/LibGit2Sharp/Core/Handles/Objects.tt +++ b/LibGit2Sharp/Core/Handles/Objects.tt @@ -72,7 +72,7 @@ for (var i = 0; i < cNames.Length; i++) #> internal unsafe class <#= csNames[i] #> : Libgit2Object { - internal <#= csNames[i] #>(<#= cNames[i] #> *ptr, bool owned) + internal <#= csNames[i] #>(<#= cNames[i] #>* ptr, bool owned) : base(ptr, owned) { } diff --git a/LibGit2Sharp/Core/Opaques.cs b/LibGit2Sharp/Core/Opaques.cs index f5613a276..f83e8be10 100644 --- a/LibGit2Sharp/Core/Opaques.cs +++ b/LibGit2Sharp/Core/Opaques.cs @@ -2,31 +2,31 @@ namespace LibGit2Sharp.Core { - internal struct git_tree_entry {} + internal struct git_tree_entry { } internal struct git_reference { } - internal struct git_refspec {} - internal struct git_repository {} - internal struct git_status_list {} - internal struct git_blame {} - internal struct git_diff {} - internal struct git_patch {} - internal struct git_config {} - internal struct git_index_conflict_iterator {} - internal struct git_index {} - internal struct git_reflog {} - internal struct git_reflog_entry {} - internal struct git_treebuilder {} - internal struct git_packbuilder {} - internal struct git_note {} - internal struct git_describe_result {} - internal struct git_submodule {} - internal struct git_annotated_commit {} - internal struct git_odb {} - internal struct git_revwalk {} - internal struct git_remote {} - internal struct git_object {} - internal struct git_rebase {} - internal struct git_odb_stream {} + internal struct git_refspec { } + internal struct git_repository { } + internal struct git_status_list { } + internal struct git_blame { } + internal struct git_diff { } + internal struct git_patch { } + internal struct git_config { } + internal struct git_index_conflict_iterator { } + internal struct git_index { } + internal struct git_reflog { } + internal struct git_reflog_entry { } + internal struct git_treebuilder { } + internal struct git_packbuilder { } + internal struct git_note { } + internal struct git_describe_result { } + internal struct git_submodule { } + internal struct git_annotated_commit { } + internal struct git_odb { } + internal struct git_revwalk { } + internal struct git_remote { } + internal struct git_object { } + internal struct git_rebase { } + internal struct git_odb_stream { } internal struct git_worktree { } } diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 18e952e68..cf0a7e3d0 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -274,7 +274,7 @@ public static unsafe RepositoryHandle git_clone( string workdir, ref GitCloneOptions opts) { - git_repository *repo; + git_repository* repo; int res = NativeMethods.git_clone(out repo, url, workdir, ref opts); Ensure.ZeroResult(res); return new RepositoryHandle(repo, true); @@ -347,7 +347,7 @@ public static unsafe string git_commit_create_buffer( handles = parents.Select(c => Proxy.git_object_lookup(c.repo.Handle, c.Id, GitObjectType.Commit)).ToArray(); var ptrs = handles.Select(p => p.AsIntPtr()).ToArray(); int res; - fixed(IntPtr* objs = ptrs) + fixed (IntPtr* objs = ptrs) { res = NativeMethods.git_commit_create_buffer(buf, repo, @@ -497,7 +497,7 @@ public static FilePath git_config_find_programdata() return ConvertPath(NativeMethods.git_config_find_programdata); } - public static unsafe void git_config_free(git_config *config) + public static unsafe void git_config_free(git_config* config) { NativeMethods.git_config_free(config); } @@ -1615,7 +1615,7 @@ public static unsafe ObjectId git_odb_write(ObjectDatabaseHandle odb, byte[] dat { GitOid id; int res; - fixed(byte* p = data) + fixed (byte* p = data) { res = NativeMethods.git_odb_write(out id, odb, p, new UIntPtr((ulong)data.LongLength), type.ToGitObjectType()); } @@ -1624,9 +1624,9 @@ public static unsafe ObjectId git_odb_write(ObjectDatabaseHandle odb, byte[] dat return id; } -#endregion + #endregion -#region git_patch_ + #region git_patch_ public static unsafe PatchHandle git_patch_from_diff(DiffHandle diff, int idx) { @@ -1650,9 +1650,9 @@ public static unsafe Tuple git_patch_line_stats(PatchHandle patch) return new Tuple((int)add, (int)del); } -#endregion + #endregion -#region git_packbuilder_ + #region git_packbuilder_ public static unsafe PackBuilderHandle git_packbuilder_new(RepositoryHandle repo) { @@ -1716,9 +1716,9 @@ public static unsafe UIntPtr git_packbuilder_written(PackBuilderHandle packbuild { return NativeMethods.git_packbuilder_written(packbuilder); } -#endregion + #endregion -#region git_rebase + #region git_rebase public static unsafe RebaseHandle git_rebase_init( RepositoryHandle repo, @@ -1872,9 +1872,9 @@ public static unsafe void git_rebase_finish( } } -#endregion + #endregion -#region git_reference_ + #region git_reference_ public static unsafe ReferenceHandle git_reference_create( RepositoryHandle repo, @@ -2022,9 +2022,9 @@ public static unsafe void git_reference_ensure_log(RepositoryHandle repo, string Ensure.ZeroResult(res); } -#endregion + #endregion -#region git_reflog_ + #region git_reflog_ public static unsafe ReflogHandle git_reflog_read(RepositoryHandle repo, string canonicalName) { @@ -2066,9 +2066,9 @@ public static unsafe string git_reflog_entry_message(git_reflog_entry* entry) return NativeMethods.git_reflog_entry_message(entry); } -#endregion + #endregion -#region git_refspec + #region git_refspec public static unsafe string git_refspec_transform(IntPtr refSpecPtr, string name) { @@ -2127,9 +2127,9 @@ public static bool git_refspec_dst_matches(IntPtr refspec, string reference) return NativeMethods.git_refspec_dst_matches(refspec, reference); } -#endregion + #endregion -#region git_remote_ + #region git_remote_ public static unsafe TagFetchMode git_remote_autotag(RemoteHandle remote) { @@ -2441,9 +2441,9 @@ public static unsafe string git_remote_pushurl(RemoteHandle remote) return NativeMethods.git_remote_pushurl(remote); } -#endregion + #endregion -#region git_repository_ + #region git_repository_ public static FilePath git_repository_discover(FilePath start_path) { @@ -2575,7 +2575,7 @@ public static unsafe RepositoryHandle git_repository_new() public static unsafe void git_repository_open_ext(string path, RepositoryOpenFlags flags, string ceilingDirs) { int res; - git_repository *repo; + git_repository* repo; res = NativeMethods.git_repository_open_ext(out repo, path, flags, ceilingDirs); NativeMethods.git_repository_free(repo); @@ -2652,9 +2652,9 @@ public static unsafe void git_repository_set_head(RepositoryHandle repo, string Ensure.ZeroResult(res); } -#endregion + #endregion -#region git_reset_ + #region git_reset_ public static unsafe void git_reset( RepositoryHandle repo, @@ -2669,9 +2669,9 @@ public static unsafe void git_reset( } } -#endregion + #endregion -#region git_revert_ + #region git_revert_ public static unsafe void git_revert( RepositoryHandle repo, @@ -2741,9 +2741,9 @@ public static ObjectHandle git_revparse_single(RepositoryHandle repo, string obj return handles.Item1; } -#endregion + #endregion -#region git_revwalk_ + #region git_revwalk_ public static unsafe void git_revwalk_hide(RevWalkerHandle walker, ObjectId commit_id) { @@ -2798,9 +2798,9 @@ public static unsafe int git_revwalk_simplify_first_parent(RevWalkerHandle walke return NativeMethods.git_revwalk_simplify_first_parent(walker); } -#endregion + #endregion -#region git_signature_ + #region git_signature_ public static unsafe SignatureHandle git_signature_new(string name, string email, DateTimeOffset when) { @@ -2830,9 +2830,9 @@ public static unsafe SignatureHandle git_signature_now(string name, string email return handle; } -#endregion + #endregion -#region git_stash_ + #region git_stash_ public static unsafe ObjectId git_stash_save( RepositoryHandle repo, @@ -2912,9 +2912,9 @@ public static unsafe StashApplyStatus git_stash_pop( return get_stash_status(NativeMethods.git_stash_pop(repo, (UIntPtr)index, opts)); } -#endregion + #endregion -#region git_status_ + #region git_status_ public static unsafe FileStatus git_status_file(RepositoryHandle repo, FilePath path) { @@ -2960,9 +2960,9 @@ public static unsafe int git_status_list_entrycount(StatusListHandle list) return NativeMethods.git_status_byindex(list, (UIntPtr)idx); } -#endregion + #endregion -#region git_submodule_ + #region git_submodule_ /// /// Returns a handle to the corresponding submodule, @@ -3074,9 +3074,9 @@ public static unsafe void git_submodule_init(SubmoduleHandle submodule, bool ove Ensure.ZeroResult(res); } -#endregion + #endregion -#region git_tag_ + #region git_tag_ public static unsafe ObjectId git_tag_annotation_create( RepositoryHandle repo, @@ -3185,9 +3185,9 @@ public static unsafe GitObjectType git_tag_target_type(ObjectHandle tag) return NativeMethods.git_tag_target_type(tag); } -#endregion + #endregion -#region git_trace_ + #region git_trace_ /// /// Install/Enable logging inside of LibGit2 to send messages back to LibGit2Sharp. @@ -3207,9 +3207,9 @@ public static void git_trace_set(LogLevel level, NativeMethods.git_trace_cb call Ensure.ZeroResult(res); } -#endregion + #endregion -#region git_transport_ + #region git_transport_ public static void git_transport_register(string prefix, IntPtr transport_cb, IntPtr param) { @@ -3236,18 +3236,18 @@ public static void git_transport_unregister(string prefix) Ensure.ZeroResult(res); } -#endregion + #endregion -#region git_transport_smart_ + #region git_transport_smart_ public static int git_transport_smart_credentials(out IntPtr cred, IntPtr transport, string user, int methods) { return NativeMethods.git_transport_smart_credentials(out cred, transport, user, methods); } -#endregion + #endregion -#region git_tree_ + #region git_tree_ public static unsafe Mode git_tree_entry_attributes(git_tree_entry* entry) { @@ -3303,9 +3303,9 @@ public static unsafe int git_tree_entrycount(ObjectHandle tree) return (int)NativeMethods.git_tree_entrycount(tree); } -#endregion + #endregion -#region git_treebuilder_ + #region git_treebuilder_ public static unsafe TreeBuilderHandle git_treebuilder_new(RepositoryHandle repo) { @@ -3333,9 +3333,9 @@ public static unsafe ObjectId git_treebuilder_write(TreeBuilderHandle bld) return oid; } -#endregion + #endregion -#region git_transaction_ + #region git_transaction_ public static void git_transaction_commit(IntPtr txn) { @@ -3347,9 +3347,9 @@ public static void git_transaction_free(IntPtr txn) NativeMethods.git_transaction_free(txn); } -#endregion + #endregion -#region git_libgit2_ + #region git_libgit2_ /// /// Returns the features with which libgit2 was compiled. @@ -3444,10 +3444,10 @@ 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) { 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); + 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); } @@ -3459,10 +3459,10 @@ public static void git_libgit2_opts_set_enable_caching(bool enabled) { // libgit2 expects non-zero value for true 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); + 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); } @@ -3474,10 +3474,10 @@ public static void git_libgit2_opts_set_enable_ofsdelta(bool enabled) { // libgit2 expects non-zero value for true 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); + 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); } @@ -3489,10 +3489,10 @@ public static void git_libgit2_opts_set_enable_strictobjectcreation(bool enabled { // libgit2 expects non-zero value for true 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); + 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); } @@ -3504,10 +3504,10 @@ public static void git_libgit2_opts_set_enable_strictobjectcreation(bool enabled public static void git_libgit2_opts_set_user_agent(string 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); + 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); } @@ -3635,7 +3635,7 @@ public static unsafe WorktreeLock git_worktree_is_locked(WorktreeHandle worktree { int res = NativeMethods.git_worktree_is_locked(buf, worktree); - if(res < 0) + if (res < 0) { // error return null; diff --git a/LibGit2Sharp/DiffTargets.cs b/LibGit2Sharp/DiffTargets.cs index 58e3f2f4d..40203ee60 100644 --- a/LibGit2Sharp/DiffTargets.cs +++ b/LibGit2Sharp/DiffTargets.cs @@ -18,4 +18,4 @@ public enum DiffTargets /// WorkingDirectory = 2, } -} \ No newline at end of file +} diff --git a/LibGit2Sharp/Filter.cs b/LibGit2Sharp/Filter.cs index 50f5fe8c5..0ab999f19 100644 --- a/LibGit2Sharp/Filter.cs +++ b/LibGit2Sharp/Filter.cs @@ -304,7 +304,7 @@ int StreamCloseCallback(IntPtr stream) { Ensure.ArgumentNotZeroIntPtr(stream, "stream"); - if(!activeStreams.TryGetValue(stream, out state)) + if (!activeStreams.TryGetValue(stream, out state)) { throw new ArgumentException("Unknown stream pointer", nameof(stream)); } diff --git a/LibGit2Sharp/FilterSource.cs b/LibGit2Sharp/FilterSource.cs index ed551aba8..ab1dcb35c 100644 --- a/LibGit2Sharp/FilterSource.cs +++ b/LibGit2Sharp/FilterSource.cs @@ -28,7 +28,7 @@ internal unsafe FilterSource(FilePath path, FilterMode mode, git_filter_source* /// internal static unsafe FilterSource FromNativePtr(IntPtr ptr) { - return FromNativePtr((git_filter_source*) ptr.ToPointer()); + return FromNativePtr((git_filter_source*)ptr.ToPointer()); } /// diff --git a/LibGit2Sharp/IDiffResult.cs b/LibGit2Sharp/IDiffResult.cs index ed6e521fd..5090de88e 100644 --- a/LibGit2Sharp/IDiffResult.cs +++ b/LibGit2Sharp/IDiffResult.cs @@ -5,6 +5,6 @@ namespace LibGit2Sharp /// /// Marker interface to identify Diff results. /// - public interface IDiffResult: IDisposable + public interface IDiffResult : IDisposable { } } diff --git a/LibGit2Sharp/Index.cs b/LibGit2Sharp/Index.cs index 46d756e04..321673606 100644 --- a/LibGit2Sharp/Index.cs +++ b/LibGit2Sharp/Index.cs @@ -247,7 +247,7 @@ private unsafe void AddEntryToTheIndex(string path, ObjectId id, Mode mode) var indexEntry = new git_index_entry { mode = (uint)mode, - path = (char*) pathPtr, + path = (char*)pathPtr, }; Marshal.Copy(id.RawId, 0, new IntPtr(indexEntry.id.Id), GitOid.Size); diff --git a/LibGit2Sharp/IndexReucEntryCollection.cs b/LibGit2Sharp/IndexReucEntryCollection.cs index 61af48b18..818bce70c 100644 --- a/LibGit2Sharp/IndexReucEntryCollection.cs +++ b/LibGit2Sharp/IndexReucEntryCollection.cs @@ -40,7 +40,7 @@ public virtual unsafe IndexReucEntry this[string path] } } - private unsafe IndexReucEntry this[int idx] + private unsafe IndexReucEntry this[int idx] { get { diff --git a/LibGit2Sharp/ObjectId.cs b/LibGit2Sharp/ObjectId.cs index ad61cba36..d87bbcb34 100644 --- a/LibGit2Sharp/ObjectId.cs +++ b/LibGit2Sharp/ObjectId.cs @@ -59,7 +59,7 @@ public ObjectId(byte[] rawId) internal static unsafe ObjectId BuildFromPtr(IntPtr ptr) { - return BuildFromPtr((git_oid*) ptr.ToPointer()); + return BuildFromPtr((git_oid*)ptr.ToPointer()); } internal static unsafe ObjectId BuildFromPtr(git_oid* id) @@ -71,7 +71,7 @@ internal unsafe ObjectId(byte* rawId) { byte[] id = new byte[GitOid.Size]; - fixed(byte* p = id) + fixed (byte* p = id) { for (int i = 0; i < rawSize; i++) { diff --git a/LibGit2Sharp/Rebase.cs b/LibGit2Sharp/Rebase.cs index 00dc3f267..c573ffa65 100644 --- a/LibGit2Sharp/Rebase.cs +++ b/LibGit2Sharp/Rebase.cs @@ -88,7 +88,7 @@ public virtual RebaseResult Start(Branch branch, Branch upstream, Branch onto, I if (this.repository.Info.CurrentOperation != CurrentOperation.None) { - throw new LibGit2SharpException("A {0} operation is already in progress.", + throw new LibGit2SharpException("A {0} operation is already in progress.", this.repository.Info.CurrentOperation); } diff --git a/LibGit2Sharp/RefSpec.cs b/LibGit2Sharp/RefSpec.cs index 5819820eb..4d9e28fbe 100644 --- a/LibGit2Sharp/RefSpec.cs +++ b/LibGit2Sharp/RefSpec.cs @@ -13,9 +13,9 @@ namespace LibGit2Sharp public class RefSpec { // This is here to keep the pointer alive - #pragma warning disable 0414 +#pragma warning disable 0414 readonly Remote remote; - #pragma warning restore 0414 +#pragma warning restore 0414 readonly IntPtr handle; internal unsafe RefSpec(Remote remote, git_refspec* handle) diff --git a/LibGit2Sharp/RefSpecCollection.cs b/LibGit2Sharp/RefSpecCollection.cs index 6ba813e47..a35710719 100644 --- a/LibGit2Sharp/RefSpecCollection.cs +++ b/LibGit2Sharp/RefSpecCollection.cs @@ -16,10 +16,10 @@ namespace LibGit2Sharp public class RefSpecCollection : IEnumerable { // These are here to keep the pointer alive - #pragma warning disable 0414 +#pragma warning disable 0414 readonly Remote remote; readonly RemoteHandle handle; - #pragma warning restore 0414 +#pragma warning restore 0414 readonly Lazy> refspecs; /// diff --git a/LibGit2Sharp/ReferenceCollection.cs b/LibGit2Sharp/ReferenceCollection.cs index 456b1a043..92bf85426 100644 --- a/LibGit2Sharp/ReferenceCollection.cs +++ b/LibGit2Sharp/ReferenceCollection.cs @@ -404,7 +404,7 @@ public virtual Reference Rename(string currentName, string newName, if (reference == null) { - throw new LibGit2SharpException("Reference '{0}' doesn't exist. One cannot move a non existing reference.", + throw new LibGit2SharpException("Reference '{0}' doesn't exist. One cannot move a non existing reference.", currentName); } diff --git a/LibGit2Sharp/Remote.cs b/LibGit2Sharp/Remote.cs index 3bf957866..401a7ddd0 100644 --- a/LibGit2Sharp/Remote.cs +++ b/LibGit2Sharp/Remote.cs @@ -83,7 +83,8 @@ public virtual string Name /// public virtual string Url { - get { return Proxy.git_remote_url(handle); } } + get { return Proxy.git_remote_url(handle); } + } /// /// Gets the distinct push url for this remote repository, if set. diff --git a/LibGit2Sharp/RemoteCallbacks.cs b/LibGit2Sharp/RemoteCallbacks.cs index ce5dccf81..6061b10e1 100644 --- a/LibGit2Sharp/RemoteCallbacks.cs +++ b/LibGit2Sharp/RemoteCallbacks.cs @@ -310,10 +310,10 @@ private unsafe int GitCertificateCheck(git_certificate* certPtr, int valid, IntP switch (certPtr->type) { case GitCertificateType.X509: - cert = new CertificateX509((git_certificate_x509*) certPtr); + cert = new CertificateX509((git_certificate_x509*)certPtr); break; case GitCertificateType.Hostkey: - cert = new CertificateSsh((git_certificate_ssh*) certPtr); + cert = new CertificateSsh((git_certificate_ssh*)certPtr); break; } @@ -355,7 +355,7 @@ private int GitPushNegotiationHandler(IntPtr updates, UIntPtr len, IntPtr payloa throw new NullReferenceException("Unexpected null git_push_update pointer was encountered"); } - PushUpdate pushUpdate = new PushUpdate((git_push_update*) ptr[i].ToPointer()); + PushUpdate pushUpdate = new PushUpdate((git_push_update*)ptr[i].ToPointer()); pushUpdates[i] = pushUpdate; } diff --git a/LibGit2Sharp/RemoteCollection.cs b/LibGit2Sharp/RemoteCollection.cs index 634f6e770..45e71c8b2 100644 --- a/LibGit2Sharp/RemoteCollection.cs +++ b/LibGit2Sharp/RemoteCollection.cs @@ -58,7 +58,8 @@ public virtual void Update(string remote, params Action[] actions { var updater = new RemoteUpdater(repository, remote); - repository.Config.WithinTransaction(() => { + repository.Config.WithinTransaction(() => + { foreach (Action action in actions) { action(updater); diff --git a/LibGit2Sharp/RepositoryExtensions.cs b/LibGit2Sharp/RepositoryExtensions.cs index edeb6b93f..5d0788c8a 100644 --- a/LibGit2Sharp/RepositoryExtensions.cs +++ b/LibGit2Sharp/RepositoryExtensions.cs @@ -24,7 +24,7 @@ public static T Lookup(this IRepository repository, string objectish) where T { EnsureNoGitLink(); - if (typeof (T) == typeof (GitObject)) + if (typeof(T) == typeof(GitObject)) { return (T)repository.Lookup(objectish); } diff --git a/LibGit2Sharp/RepositoryStatus.cs b/LibGit2Sharp/RepositoryStatus.cs index 490dc6798..cc1c6e7e0 100644 --- a/LibGit2Sharp/RepositoryStatus.cs +++ b/LibGit2Sharp/RepositoryStatus.cs @@ -64,7 +64,7 @@ internal unsafe RepositoryStatus(Repository repo, StatusOptions options) for (int i = 0; i < count; i++) { - git_status_entry *entry = Proxy.git_status_byindex(list, i); + git_status_entry* entry = Proxy.git_status_byindex(list, i); AddStatusEntryForDelta(entry->status, entry->head_to_index, entry->index_to_workdir); } diff --git a/LibGit2Sharp/RevertResult.cs b/LibGit2Sharp/RevertResult.cs index da54046a4..8f9a270d3 100644 --- a/LibGit2Sharp/RevertResult.cs +++ b/LibGit2Sharp/RevertResult.cs @@ -34,7 +34,7 @@ internal RevertResult(RevertStatus status, Commit commit = null) public virtual RevertStatus Status { get; private set; } } - /// + /// /// The status of what happened as a result of a revert. /// public enum RevertStatus diff --git a/LibGit2Sharp/SimilarityOptions.cs b/LibGit2Sharp/SimilarityOptions.cs index 13d26abf2..4d2b0cd95 100644 --- a/LibGit2Sharp/SimilarityOptions.cs +++ b/LibGit2Sharp/SimilarityOptions.cs @@ -81,7 +81,7 @@ public SimilarityOptions() /// public static SimilarityOptions None { - get { return new SimilarityOptions {RenameDetectionMode = RenameDetectionMode.None}; } + get { return new SimilarityOptions { RenameDetectionMode = RenameDetectionMode.None }; } } /// @@ -89,7 +89,7 @@ public static SimilarityOptions None /// public static SimilarityOptions Renames { - get { return new SimilarityOptions {RenameDetectionMode = RenameDetectionMode.Renames}; } + get { return new SimilarityOptions { RenameDetectionMode = RenameDetectionMode.Renames }; } } /// @@ -97,7 +97,7 @@ public static SimilarityOptions Renames /// public static SimilarityOptions Exact { - get { return new SimilarityOptions {RenameDetectionMode = RenameDetectionMode.Exact}; } + get { return new SimilarityOptions { RenameDetectionMode = RenameDetectionMode.Exact }; } } /// @@ -105,7 +105,7 @@ public static SimilarityOptions Exact /// public static SimilarityOptions Copies { - get { return new SimilarityOptions {RenameDetectionMode = RenameDetectionMode.Copies}; } + get { return new SimilarityOptions { RenameDetectionMode = RenameDetectionMode.Copies }; } } /// @@ -113,7 +113,7 @@ public static SimilarityOptions Copies /// public static SimilarityOptions CopiesHarder { - get { return new SimilarityOptions {RenameDetectionMode = RenameDetectionMode.CopiesHarder}; } + get { return new SimilarityOptions { RenameDetectionMode = RenameDetectionMode.CopiesHarder }; } } /// @@ -121,7 +121,7 @@ public static SimilarityOptions CopiesHarder /// public static SimilarityOptions Default { - get { return new SimilarityOptions {RenameDetectionMode = RenameDetectionMode.Default}; } + get { return new SimilarityOptions { RenameDetectionMode = RenameDetectionMode.Default }; } } /// diff --git a/LibGit2Sharp/SmartSubtransport.cs b/LibGit2Sharp/SmartSubtransport.cs index e7a331b4b..6160c849b 100644 --- a/LibGit2Sharp/SmartSubtransport.cs +++ b/LibGit2Sharp/SmartSubtransport.cs @@ -73,7 +73,9 @@ public int CertificateCheck(Certificate cert, bool valid, string hostname) var certPtr = sshCert.ToPointer(); ret = NativeMethods.git_transport_smart_certificate_check(Transport, certPtr, valid ? 1 : 0, hostname); Marshal.FreeHGlobal(certPtr); - } else { + } + else + { IntPtr certPtr, dataPtr; certPtr = x509Cert.ToPointers(out dataPtr); ret = NativeMethods.git_transport_smart_certificate_check(Transport, certPtr, valid ? 1 : 0, hostname); @@ -131,11 +133,11 @@ public int AcquireCredentials(out Credentials cred, string user, params Type[] m unsafe { - var baseCred = (GitCredential*) credHandle; + var baseCred = (GitCredential*)credHandle; switch (baseCred->credtype) { case GitCredentialType.UserPassPlaintext: - cred = UsernamePasswordCredentials.FromNative((GitCredentialUserpass*) credHandle); + cred = UsernamePasswordCredentials.FromNative((GitCredentialUserpass*)credHandle); return 0; case GitCredentialType.Default: cred = new DefaultCredentials(); diff --git a/LibGit2Sharp/TagCollection.cs b/LibGit2Sharp/TagCollection.cs index 8bd9168b0..98bfd257d 100644 --- a/LibGit2Sharp/TagCollection.cs +++ b/LibGit2Sharp/TagCollection.cs @@ -114,7 +114,7 @@ public virtual Tag Add(string name, string objectish) /// The name. /// Revparse spec for the target object. /// True to allow silent overwriting a potentially existing tag, false otherwise. - public virtual Tag Add( string name, string objectish, bool allowOverwrite) + public virtual Tag Add(string name, string objectish, bool allowOverwrite) { Ensure.ArgumentNotNullOrEmptyString(objectish, "objectish"); diff --git a/LibGit2Sharp/TransientIndex.cs b/LibGit2Sharp/TransientIndex.cs index 65b7b7872..b62678c83 100644 --- a/LibGit2Sharp/TransientIndex.cs +++ b/LibGit2Sharp/TransientIndex.cs @@ -7,7 +7,7 @@ namespace LibGit2Sharp /// An implementation of with disposal managed by the caller /// (instead of automatically disposing when the repository is disposed) /// - public class TransientIndex: Index, IDisposable + public class TransientIndex : Index, IDisposable { /// /// Needed for mocking purposes. diff --git a/LibGit2Sharp/Tree.cs b/LibGit2Sharp/Tree.cs index 64d46145d..30f534a99 100644 --- a/LibGit2Sharp/Tree.cs +++ b/LibGit2Sharp/Tree.cs @@ -110,7 +110,8 @@ public virtual IEnumerator GetEnumerator() { using (var obj = new ObjectSafeWrapper(Id, repo.Handle, throwIfMissing: true)) { - for (uint i = 0; i < Count; i++) { + for (uint i = 0; i < Count; i++) + { yield return byIndex(obj, i, Id, repo, path); } } diff --git a/LibGit2Sharp/Worktree.cs b/LibGit2Sharp/Worktree.cs index bd10f6110..ca7f5ef16 100644 --- a/LibGit2Sharp/Worktree.cs +++ b/LibGit2Sharp/Worktree.cs @@ -95,7 +95,7 @@ public virtual void Unlock() this.worktreeLock = Proxy.git_worktree_is_locked(handle); } } - + /// /// Lock the worktree /// diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs index 9822e882c..7bdd5fefa 100644 --- a/LibGit2Sharp/WorktreeCollection.cs +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -57,7 +57,7 @@ public virtual Worktree this[string name] /// public virtual Worktree Add(string committishOrBranchSpec, string name, string path, bool isLocked) { - if(string.Equals(committishOrBranchSpec, name)) + if (string.Equals(committishOrBranchSpec, name)) { // Proxy.git_worktree_add() creates a new branch of name = name, so if we want to checkout a given branch then the 'name' cannot be the same as the target branch return null; @@ -83,9 +83,9 @@ public virtual Worktree Add(string committishOrBranchSpec, string name, string p } } - - return this[name]; + + return this[name]; } /// From 5162c68b35bc9f83754649dc86c853e8108a71fd Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Fri, 22 Nov 2024 23:05:26 -0500 Subject: [PATCH 366/384] Fix tests --- LibGit2Sharp.Tests/FilterBranchFixture.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/FilterBranchFixture.cs b/LibGit2Sharp.Tests/FilterBranchFixture.cs index 0041e7646..de4663a22 100644 --- a/LibGit2Sharp.Tests/FilterBranchFixture.cs +++ b/LibGit2Sharp.Tests/FilterBranchFixture.cs @@ -400,7 +400,7 @@ public void CanCustomizeTheNamespaceOfBackedUpRefs(string backupRefsNamespace) AssertSucceedingButNotError(); - Assert.DoesNotContain(repo.Refs, x => x.CanonicalName.StartsWith("refs/original")); + Assert.Contains(repo.Refs, x => x.CanonicalName.StartsWith("refs/original")); Assert.DoesNotContain(repo.Refs, x => x.CanonicalName.StartsWith("refs/rewritten")); @@ -415,7 +415,7 @@ public void CanCustomizeTheNamespaceOfBackedUpRefs(string backupRefsNamespace) AssertSucceedingButNotError(); - Assert.DoesNotContain(repo.Refs, x => x.CanonicalName.StartsWith("refs/rewritten")); + Assert.Contains(repo.Refs, x => x.CanonicalName.StartsWith("refs/rewritten")); } [Fact] @@ -491,7 +491,7 @@ public void DoesNotRewriteRefsThatDontChange() // Ensure br2 is still a merge commit var parents = repo.Branches["br2"].Tip.Parents.ToList(); Assert.Equal(2, parents.Count()); - Assert.DoesNotContain(parents, c => c.Sha.StartsWith("9fd738e")); + Assert.Contains(parents, c => c.Sha.StartsWith("9fd738e")); Assert.Equal("abc", parents.Single(c => !c.Sha.StartsWith("9fd738e")).Message); } From 47b2ee01f00d5eaf94b31d4914cf8960ee62e344 Mon Sep 17 00:00:00 2001 From: Anders Klepaker <78612332+andersklepaker@users.noreply.github.com> Date: Sat, 23 Nov 2024 18:50:48 +0100 Subject: [PATCH 367/384] Adds Depth to FetchOptions allowing for shallow cloning (#2070) * Added Depth as a fetch option * Map Depth from FetchOptions to GitFetchOptions * Added tests for shallow cloning --- LibGit2Sharp.Tests/CloneFixture.cs | 28 ++++++++++++++++++++++++++++ LibGit2Sharp/FetchOptions.cs | 8 ++++++++ LibGit2Sharp/Repository.cs | 9 ++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index f205eddc2..9a4cfbb37 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -35,6 +35,34 @@ public void CanClone(string url) } } + [Theory] + [InlineData("https://github.com/libgit2/TestGitRepository",1)] + [InlineData("https://github.com/libgit2/TestGitRepository",5)] + [InlineData("https://github.com/libgit2/TestGitRepository",7)] + public void CanCloneShallow(string url, int depth) + { + var scd = BuildSelfCleaningDirectory(); + + var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions + { + FetchOptions = + { + Depth = depth, + }, + }); + + using (var repo = new Repository(clonedRepoPath)) + { + var commitsFirstParentOnly = repo.Commits.QueryBy(new CommitFilter + { + FirstParentOnly = true, + }); + + Assert.Equal(depth, commitsFirstParentOnly.Count()); + Assert.Equal("49322bb17d3acc9146f98c97d078513228bbf3c0", repo.Head.Tip.Id.ToString()); + } + } + [Theory] [InlineData("br2", "a4a7dce85cf63874e984719f4fdd239f5145052f")] [InlineData("packed", "41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9")] diff --git a/LibGit2Sharp/FetchOptions.cs b/LibGit2Sharp/FetchOptions.cs index 5bcf74bfa..378c4ad5c 100644 --- a/LibGit2Sharp/FetchOptions.cs +++ b/LibGit2Sharp/FetchOptions.cs @@ -26,6 +26,14 @@ public sealed class FetchOptions : FetchOptionsBase /// public bool? Prune { get; set; } + /// + /// Specifies the depth of the fetch to perform. + /// + /// Default value is 0 (full) fetch. + /// + /// + public int Depth { get; set; } = 0; + /// /// Get/Set the custom headers. /// diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index fc777404e..19fd58668 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -780,6 +780,13 @@ public static string Clone(string sourceUrl, string workdirPath, options ??= new CloneOptions(); + // As default behaviour for GitFetchOptionsWrapper ctor is to create + // a new instance of GitFetchOptions we only populate the Depth field. + var fetchOptions = new GitFetchOptions + { + Depth = options.FetchOptions.Depth, + }; + // context variable that contains information on the repository that // we are cloning. var context = new RepositoryOperationContext(Path.GetFullPath(workdirPath), sourceUrl); @@ -794,7 +801,7 @@ public static string Clone(string sourceUrl, string workdirPath, } using (var checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) - using (var fetchOptionsWrapper = new GitFetchOptionsWrapper()) + using (var fetchOptionsWrapper = new GitFetchOptionsWrapper(fetchOptions)) { var gitCheckoutOptions = checkoutOptionsWrapper.Options; From 19236dbeba446882773fc4ff9f5a741bf0659bb2 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 23 Nov 2024 12:55:05 -0500 Subject: [PATCH 368/384] Tweak shallow cloning implementation --- LibGit2Sharp/FetchOptions.cs | 2 +- LibGit2Sharp/Repository.cs | 27 ++++++++------------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/LibGit2Sharp/FetchOptions.cs b/LibGit2Sharp/FetchOptions.cs index 378c4ad5c..6f354a5d5 100644 --- a/LibGit2Sharp/FetchOptions.cs +++ b/LibGit2Sharp/FetchOptions.cs @@ -29,7 +29,7 @@ public sealed class FetchOptions : FetchOptionsBase /// /// Specifies the depth of the fetch to perform. /// - /// Default value is 0 (full) fetch. + /// Default value is 0 (full fetch). /// /// public int Depth { get; set; } = 0; diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 19fd58668..9ac5e2424 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -772,28 +772,19 @@ public static string Clone(string sourceUrl, string workdirPath) /// Local path to clone into /// controlling clone behavior /// The path to the created repository. - public static string Clone(string sourceUrl, string workdirPath, - CloneOptions options) + public static string Clone(string sourceUrl, string workdirPath, CloneOptions options) { Ensure.ArgumentNotNull(sourceUrl, "sourceUrl"); Ensure.ArgumentNotNull(workdirPath, "workdirPath"); options ??= new CloneOptions(); - // As default behaviour for GitFetchOptionsWrapper ctor is to create - // a new instance of GitFetchOptions we only populate the Depth field. - var fetchOptions = new GitFetchOptions - { - Depth = options.FetchOptions.Depth, - }; - // context variable that contains information on the repository that // we are cloning. var context = new RepositoryOperationContext(Path.GetFullPath(workdirPath), sourceUrl); // Notify caller that we are starting to work with the current repository. - bool continueOperation = OnRepositoryOperationStarting(options.FetchOptions.RepositoryOperationStarting, - context); + bool continueOperation = OnRepositoryOperationStarting(options.FetchOptions.RepositoryOperationStarting, context); if (!continueOperation) { @@ -801,17 +792,18 @@ public static string Clone(string sourceUrl, string workdirPath, } using (var checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) - using (var fetchOptionsWrapper = new GitFetchOptionsWrapper(fetchOptions)) + using (var fetchOptionsWrapper = new GitFetchOptionsWrapper()) { var gitCheckoutOptions = checkoutOptionsWrapper.Options; var gitFetchOptions = fetchOptionsWrapper.Options; + gitFetchOptions.Depth = options.FetchOptions.Depth; gitFetchOptions.ProxyOptions = options.FetchOptions.ProxyOptions.CreateGitProxyOptions(); gitFetchOptions.RemoteCallbacks = new RemoteCallbacks(options.FetchOptions).GenerateCallbacks(); + if (options.FetchOptions != null && options.FetchOptions.CustomHeaders != null) { - gitFetchOptions.CustomHeaders = - GitStrArrayManaged.BuildFrom(options.FetchOptions.CustomHeaders); + gitFetchOptions.CustomHeaders = GitStrArrayManaged.BuildFrom(options.FetchOptions.CustomHeaders); } var cloneOpts = new GitCloneOptions @@ -839,8 +831,7 @@ public static string Clone(string sourceUrl, string workdirPath, } // Notify caller that we are done with the current repository. - OnRepositoryOperationCompleted(options.FetchOptions.RepositoryOperationCompleted, - context); + OnRepositoryOperationCompleted(options.FetchOptions.RepositoryOperationCompleted, context); // Recursively clone submodules if requested. try @@ -849,9 +840,7 @@ public static string Clone(string sourceUrl, string workdirPath, } catch (Exception ex) { - throw new RecurseSubmodulesException("The top level repository was cloned, but there was an error cloning its submodules.", - ex, - clonedRepoPath); + throw new RecurseSubmodulesException("The top level repository was cloned, but there was an error cloning its submodules.", ex, clonedRepoPath); } return clonedRepoPath; From e1a94a1acf9ce58947aa4be50f40c08c4dfea104 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 23 Nov 2024 16:59:22 -0500 Subject: [PATCH 369/384] Update LibGit2Sharp.NativeBinaries to 2.0.323 --- LibGit2Sharp/LibGit2Sharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 8eadb87df..1c4abef7b 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -29,7 +29,7 @@ - + From 95b283b0d228219c4b4d47ab0b761f657dd22168 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 23 Nov 2024 20:00:44 -0500 Subject: [PATCH 370/384] React to ABI changes --- LibGit2Sharp/ConfigurationLevel.cs | 5 +++++ LibGit2Sharp/Core/GitConfigEntry.cs | 4 ++-- LibGit2Sharp/Core/GitPushOptions.cs | 1 + LibGit2Sharp/Core/GitWorktree.cs | 4 ++-- LibGit2Sharp/WorktreeCollection.cs | 16 +++++++--------- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/LibGit2Sharp/ConfigurationLevel.cs b/LibGit2Sharp/ConfigurationLevel.cs index 9fd57df28..f0971a1c1 100644 --- a/LibGit2Sharp/ConfigurationLevel.cs +++ b/LibGit2Sharp/ConfigurationLevel.cs @@ -5,6 +5,11 @@ /// public enum ConfigurationLevel { + /// + /// Worktree specific configuration file; $GIT_DIR/config.worktree + /// + Worktree = 6, + /// /// The local .git/config of the current repository. /// diff --git a/LibGit2Sharp/Core/GitConfigEntry.cs b/LibGit2Sharp/Core/GitConfigEntry.cs index 9eaa9e468..7af657894 100644 --- a/LibGit2Sharp/Core/GitConfigEntry.cs +++ b/LibGit2Sharp/Core/GitConfigEntry.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace LibGit2Sharp.Core @@ -8,9 +7,10 @@ internal unsafe struct GitConfigEntry { public char* namePtr; public char* valuePtr; + public char* backend_type; + public char* origin_path; public uint include_depth; public uint level; public void* freePtr; - public void* payloadPtr; } } diff --git a/LibGit2Sharp/Core/GitPushOptions.cs b/LibGit2Sharp/Core/GitPushOptions.cs index ce1a58f7c..ac9a99e1e 100644 --- a/LibGit2Sharp/Core/GitPushOptions.cs +++ b/LibGit2Sharp/Core/GitPushOptions.cs @@ -11,5 +11,6 @@ internal class GitPushOptions public GitProxyOptions ProxyOptions; public RemoteRedirectMode FollowRedirects = RemoteRedirectMode.Initial; public GitStrArrayManaged CustomHeaders; + public GitStrArrayManaged remote_push_options; } } diff --git a/LibGit2Sharp/Core/GitWorktree.cs b/LibGit2Sharp/Core/GitWorktree.cs index b3200dd91..6cc3c4d9a 100644 --- a/LibGit2Sharp/Core/GitWorktree.cs +++ b/LibGit2Sharp/Core/GitWorktree.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; -using System.Text; namespace LibGit2Sharp.Core { @@ -36,6 +34,8 @@ internal class git_worktree_add_options public int locked; + public int checkout_existing; + public IntPtr @ref = IntPtr.Zero; public GitCheckoutOpts checkoutOpts = new GitCheckoutOpts { version = 1 }; diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs index 7bdd5fefa..29023b3dc 100644 --- a/LibGit2Sharp/WorktreeCollection.cs +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -1,12 +1,10 @@ -using LibGit2Sharp.Core; -using LibGit2Sharp.Core.Handles; -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; -using System.Text; +using LibGit2Sharp.Core; +using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp { @@ -48,7 +46,7 @@ public virtual Worktree this[string name] } /// - /// + /// /// /// /// @@ -89,7 +87,7 @@ public virtual Worktree Add(string committishOrBranchSpec, string name, string p } /// - /// + /// /// /// /// @@ -112,7 +110,7 @@ public virtual Worktree Add(string name, string path, bool isLocked) } /// - /// + /// /// /// /// @@ -122,7 +120,7 @@ public virtual bool Prune(Worktree worktree) } /// - /// + /// /// /// /// From 9a11cbd903d85a831237ef2ca790226a5f195b22 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 23 Nov 2024 20:50:36 -0500 Subject: [PATCH 371/384] Update tests --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index dd7aef1e1..e91449b02 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -90,17 +90,17 @@ public void SetExtensions() var extensions = GlobalSettings.GetExtensions(); // Assert that "noop" is supported by default - Assert.Equal(new[] { "noop", "objectformat" }, extensions); + Assert.Equal(new[] { "noop", "objectformat", "worktreeconfig" }, extensions); // Disable "noop" extensions GlobalSettings.SetExtensions("!noop"); extensions = GlobalSettings.GetExtensions(); - Assert.Equal(new[] { "objectformat" }, extensions); + Assert.Equal(new[] { "objectformat", "worktreeconfig" }, 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[] { "newext", "noop", "objectformat", "partialclone" }, extensions); + Assert.Equal(new[] { "newext", "noop", "objectformat", "partialclone", "worktreeconfig" }, extensions); } } } From 8ef523da62d26385894ed40364b932d9c7ccbd8a Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sat, 23 Nov 2024 21:06:43 -0500 Subject: [PATCH 372/384] Comment out SSH test for now --- LibGit2Sharp.Tests/CloneFixture.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 9a4cfbb37..831f6779f 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -36,9 +36,9 @@ public void CanClone(string url) } [Theory] - [InlineData("https://github.com/libgit2/TestGitRepository",1)] - [InlineData("https://github.com/libgit2/TestGitRepository",5)] - [InlineData("https://github.com/libgit2/TestGitRepository",7)] + [InlineData("https://github.com/libgit2/TestGitRepository", 1)] + [InlineData("https://github.com/libgit2/TestGitRepository", 5)] + [InlineData("https://github.com/libgit2/TestGitRepository", 7)] public void CanCloneShallow(string url, int depth) { var scd = BuildSelfCleaningDirectory(); @@ -266,7 +266,7 @@ static Credentials CreateUsernamePasswordCredentials(string user, string pass, b [SkippableTheory] [InlineData("https://github.com/libgit2/TestGitRepository.git", "github.com", typeof(CertificateX509))] - [InlineData("git@github.com:libgit2/TestGitRepository.git", "github.com", typeof(CertificateSsh))] + //[InlineData("git@github.com:libgit2/TestGitRepository.git", "github.com", typeof(CertificateSsh))] public void CanInspectCertificateOnClone(string url, string hostname, Type certType) { var scd = BuildSelfCleaningDirectory(); From aacf7cd43422a5c1408df3b2052d2cbbb02dd707 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 24 Nov 2024 01:36:29 -0500 Subject: [PATCH 373/384] Add a CloneOptions constructor that takes a FetchOptions --- LibGit2Sharp/CloneOptions.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/LibGit2Sharp/CloneOptions.cs b/LibGit2Sharp/CloneOptions.cs index a315d76fc..12d47c9f3 100644 --- a/LibGit2Sharp/CloneOptions.cs +++ b/LibGit2Sharp/CloneOptions.cs @@ -4,12 +4,23 @@ namespace LibGit2Sharp { /// - /// Options to define clone behaviour + /// Options to define clone behavior /// public sealed class CloneOptions : IConvertableToGitCheckoutOpts { /// - /// Creates default for a non-bare clone + /// Creates with specified for a non-bare clone. + /// + /// The fetch options to use. + public CloneOptions(FetchOptions fetchOptions) : this() + { + Ensure.ArgumentNotNull(fetchOptions, "fetchOptions"); + + FetchOptions = fetchOptions; + } + + /// + /// Creates default for a non-bare clone. /// public CloneOptions() { From 08fafd57295015a30a51257e980217819a12095e Mon Sep 17 00:00:00 2001 From: Enrique Raso Barbero Date: Tue, 4 Jun 2024 10:43:01 +0200 Subject: [PATCH 374/384] Set GIT_CHECKOUT_FORCE as checkout strategy when creating a worktree --- LibGit2Sharp.Tests/WorktreeFixture.cs | 109 +++++++++++++++++++++++++- LibGit2Sharp/Core/GitWorktree.cs | 6 +- LibGit2Sharp/WorktreeCollection.cs | 19 ++--- 3 files changed, 118 insertions(+), 16 deletions(-) diff --git a/LibGit2Sharp.Tests/WorktreeFixture.cs b/LibGit2Sharp.Tests/WorktreeFixture.cs index 5a706515b..e51a79942 100644 --- a/LibGit2Sharp.Tests/WorktreeFixture.cs +++ b/LibGit2Sharp.Tests/WorktreeFixture.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Xunit; namespace LibGit2Sharp.Tests @@ -238,7 +236,7 @@ public void CanForcePruneLockedWorktree() } [Fact] - public void CanAddWorktree() + public void CanAddWorktree_WithUncommitedChanges() { var repoPath = SandboxWorktreeTestRepo(); using (var repo = new Repository(repoPath)) @@ -252,15 +250,96 @@ public void CanAddWorktree() Assert.False(worktree.IsLocked); Assert.Equal(3, repo.Worktrees.Count()); + + // Check that branch contains same number of files and folders + // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) + Assert.True(repo.RetrieveStatus().IsDirty); + var filesInMain = GetFilesOfRepo(repoPath); + var filesInBranch = GetFilesOfRepo(path); + Assert.NotEqual(filesInMain, filesInBranch); + + repo.Reset(ResetMode.Hard); + repo.RemoveUntrackedFiles(); + + Assert.False(repo.RetrieveStatus().IsDirty); + filesInMain = GetFilesOfRepo(repoPath); + filesInBranch = GetFilesOfRepo(path); + Assert.Equal(filesInMain, filesInBranch); + } + } + + [Fact] + public void CanAddWorktree_WithCommitedChanges() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + // stage all changes + Commands.Stage(repo, "*"); + repo.Commit("Apply all changes", Constants.Signature, Constants.Signature); + + Assert.Equal(2, repo.Worktrees.Count()); + + var name = "blah"; + var path = Path.Combine(repo.Info.WorkingDirectory, "..", "worktrees", name); + var worktree = repo.Worktrees.Add(name, path, false); + Assert.Equal(name, worktree.Name); + Assert.False(worktree.IsLocked); + + Assert.Equal(3, repo.Worktrees.Count()); + + // Check that branch contains same number of files and folders + // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) + Assert.False(repo.RetrieveStatus().IsDirty); + var filesInMain = GetFilesOfRepo(repoPath); + var filesInBranch = GetFilesOfRepo(path); + Assert.Equal(filesInMain, filesInBranch); + } + } + + [Fact] + public void CanAddLockedWorktree_WithUncommitedChanges() + { + var repoPath = SandboxWorktreeTestRepo(); + using (var repo = new Repository(repoPath)) + { + Assert.Equal(2, repo.Worktrees.Count()); + + var name = "blah"; + var path = Path.Combine(repo.Info.WorkingDirectory, "..", "worktrees", name); + var worktree = repo.Worktrees.Add(name, path, true); + Assert.Equal(name, worktree.Name); + Assert.True(worktree.IsLocked); + + Assert.Equal(3, repo.Worktrees.Count()); + + // Check that branch contains same number of files and folders + // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) + Assert.True(repo.RetrieveStatus().IsDirty); + var filesInMain = GetFilesOfRepo(repoPath); + var filesInBranch = GetFilesOfRepo(path); + Assert.NotEqual(filesInMain, filesInBranch); + + repo.Reset(ResetMode.Hard); + repo.RemoveUntrackedFiles(); + + Assert.False(repo.RetrieveStatus().IsDirty); + filesInMain = GetFilesOfRepo(repoPath); + filesInBranch = GetFilesOfRepo(path); + Assert.Equal(filesInMain, filesInBranch); } } [Fact] - public void CanAddLockedWorktree() + public void CanAddLockedWorktree_WithCommitedChanges() { var repoPath = SandboxWorktreeTestRepo(); using (var repo = new Repository(repoPath)) { + // stage all changes + Commands.Stage(repo, "*"); + repo.Commit("Apply all changes", Constants.Signature, Constants.Signature); + Assert.Equal(2, repo.Worktrees.Count()); var name = "blah"; @@ -270,6 +349,13 @@ public void CanAddLockedWorktree() Assert.True(worktree.IsLocked); Assert.Equal(3, repo.Worktrees.Count()); + + // Check that branch contains same number of files and folders + // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) + Assert.False(repo.RetrieveStatus().IsDirty); + var filesInMain = GetFilesOfRepo(repoPath); + var filesInBranch = GetFilesOfRepo(path); + Assert.Equal(filesInMain, filesInBranch); } } @@ -292,7 +378,22 @@ public void CanAddWorktreeForCommittish() Assert.Equal(committish, repository.Head.FriendlyName); } Assert.Equal(3, repo.Worktrees.Count()); + + // Check that branch contains same number of files and folders + // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) + var filesInCommittish = new string[] { "numbers.txt", "super-file.txt" }; + var filesInBranch = GetFilesOfRepo(path); + Assert.Equal(filesInCommittish, filesInBranch); } } + + private static IEnumerable GetFilesOfRepo(string repoPath) + { + return Directory.GetFiles(repoPath, "*", SearchOption.AllDirectories) + .Where(fileName => !fileName.StartsWith($"{repoPath}\\.git", StringComparison.InvariantCultureIgnoreCase)) + .Select(fileName => fileName.Replace($"{repoPath}\\", "", StringComparison.InvariantCultureIgnoreCase)) + .OrderBy(fileName => fileName, StringComparer.InvariantCultureIgnoreCase) + .ToList(); + } } } diff --git a/LibGit2Sharp/Core/GitWorktree.cs b/LibGit2Sharp/Core/GitWorktree.cs index 6cc3c4d9a..5e2aca023 100644 --- a/LibGit2Sharp/Core/GitWorktree.cs +++ b/LibGit2Sharp/Core/GitWorktree.cs @@ -38,7 +38,11 @@ internal class git_worktree_add_options public IntPtr @ref = IntPtr.Zero; - public GitCheckoutOpts checkoutOpts = new GitCheckoutOpts { version = 1 }; + public GitCheckoutOpts checkoutOpts = new GitCheckoutOpts + { + version = 1, + checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_FORCE + }; } [StructLayout(LayoutKind.Sequential)] diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs index 29023b3dc..b79623c4c 100644 --- a/LibGit2Sharp/WorktreeCollection.cs +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -48,11 +48,10 @@ public virtual Worktree this[string name] /// /// /// - /// - /// - /// + /// A committish or branch name./param> + /// Name of the worktree. + /// Location of the worktree. /// - /// public virtual Worktree Add(string committishOrBranchSpec, string name, string path, bool isLocked) { if (string.Equals(committishOrBranchSpec, name)) @@ -61,7 +60,7 @@ public virtual Worktree Add(string committishOrBranchSpec, string name, string p return null; } - git_worktree_add_options options = new git_worktree_add_options + var options = new git_worktree_add_options { version = 1, locked = Convert.ToInt32(isLocked) @@ -81,20 +80,18 @@ public virtual Worktree Add(string committishOrBranchSpec, string name, string p } } - - return this[name]; } /// /// /// - /// - /// - /// + /// A committish or branch name./param> + /// Name of the worktree. + /// Location of the worktree. public virtual Worktree Add(string name, string path, bool isLocked) { - git_worktree_add_options options = new git_worktree_add_options + var options = new git_worktree_add_options { version = 1, locked = Convert.ToInt32(isLocked) From f145a2c276fefb10d3e20ab92bd398f4251f0b8f Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 24 Nov 2024 02:48:19 -0500 Subject: [PATCH 375/384] Tweaks --- LibGit2Sharp.Tests/WorktreeFixture.cs | 16 ++++++---------- LibGit2Sharp/WorktreeCollection.cs | 8 ++++---- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/LibGit2Sharp.Tests/WorktreeFixture.cs b/LibGit2Sharp.Tests/WorktreeFixture.cs index e51a79942..224a99dbe 100644 --- a/LibGit2Sharp.Tests/WorktreeFixture.cs +++ b/LibGit2Sharp.Tests/WorktreeFixture.cs @@ -1,8 +1,8 @@ -using LibGit2Sharp.Tests.TestHelpers; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; +using LibGit2Sharp.Tests.TestHelpers; using Xunit; namespace LibGit2Sharp.Tests @@ -252,7 +252,6 @@ public void CanAddWorktree_WithUncommitedChanges() Assert.Equal(3, repo.Worktrees.Count()); // Check that branch contains same number of files and folders - // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) Assert.True(repo.RetrieveStatus().IsDirty); var filesInMain = GetFilesOfRepo(repoPath); var filesInBranch = GetFilesOfRepo(path); @@ -289,10 +288,10 @@ public void CanAddWorktree_WithCommitedChanges() Assert.Equal(3, repo.Worktrees.Count()); // Check that branch contains same number of files and folders - // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) Assert.False(repo.RetrieveStatus().IsDirty); var filesInMain = GetFilesOfRepo(repoPath); var filesInBranch = GetFilesOfRepo(path); + Assert.Equal(filesInMain, filesInBranch); } } @@ -314,7 +313,6 @@ public void CanAddLockedWorktree_WithUncommitedChanges() Assert.Equal(3, repo.Worktrees.Count()); // Check that branch contains same number of files and folders - // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) Assert.True(repo.RetrieveStatus().IsDirty); var filesInMain = GetFilesOfRepo(repoPath); var filesInBranch = GetFilesOfRepo(path); @@ -351,7 +349,6 @@ public void CanAddLockedWorktree_WithCommitedChanges() Assert.Equal(3, repo.Worktrees.Count()); // Check that branch contains same number of files and folders - // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) Assert.False(repo.RetrieveStatus().IsDirty); var filesInMain = GetFilesOfRepo(repoPath); var filesInBranch = GetFilesOfRepo(path); @@ -380,7 +377,6 @@ public void CanAddWorktreeForCommittish() Assert.Equal(3, repo.Worktrees.Count()); // Check that branch contains same number of files and folders - // NOTE: There is an open bug - [Repository.Worktrees.Add leaves now worktree empty](https://github.com/libgit2/libgit2sharp/issues/2037) var filesInCommittish = new string[] { "numbers.txt", "super-file.txt" }; var filesInBranch = GetFilesOfRepo(path); Assert.Equal(filesInCommittish, filesInBranch); @@ -390,9 +386,9 @@ public void CanAddWorktreeForCommittish() private static IEnumerable GetFilesOfRepo(string repoPath) { return Directory.GetFiles(repoPath, "*", SearchOption.AllDirectories) - .Where(fileName => !fileName.StartsWith($"{repoPath}\\.git", StringComparison.InvariantCultureIgnoreCase)) - .Select(fileName => fileName.Replace($"{repoPath}\\", "", StringComparison.InvariantCultureIgnoreCase)) - .OrderBy(fileName => fileName, StringComparer.InvariantCultureIgnoreCase) + .Where(fileName => !fileName.StartsWith(Path.Combine(repoPath, ".git"))) + .Select(fileName => fileName.Replace($"{repoPath}{Path.DirectorySeparatorChar}", "")) + .OrderBy(fileName => fileName) .ToList(); } } diff --git a/LibGit2Sharp/WorktreeCollection.cs b/LibGit2Sharp/WorktreeCollection.cs index b79623c4c..d99e11d7a 100644 --- a/LibGit2Sharp/WorktreeCollection.cs +++ b/LibGit2Sharp/WorktreeCollection.cs @@ -46,9 +46,9 @@ public virtual Worktree this[string name] } /// - /// + /// Creates a worktree. /// - /// A committish or branch name./param> + /// The committish to checkout into the new worktree. /// Name of the worktree. /// Location of the worktree. /// @@ -84,11 +84,11 @@ public virtual Worktree Add(string committishOrBranchSpec, string name, string p } /// - /// + /// Creates a worktree. /// - /// A committish or branch name./param> /// Name of the worktree. /// Location of the worktree. + /// public virtual Worktree Add(string name, string path, bool isLocked) { var options = new git_worktree_add_options From 704a25bb73b13c9301346286d8120158fc950365 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Sun, 24 Nov 2024 02:50:24 -0500 Subject: [PATCH 376/384] Use safe instead of force --- LibGit2Sharp/Core/GitWorktree.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/Core/GitWorktree.cs b/LibGit2Sharp/Core/GitWorktree.cs index 5e2aca023..2e17bc20d 100644 --- a/LibGit2Sharp/Core/GitWorktree.cs +++ b/LibGit2Sharp/Core/GitWorktree.cs @@ -41,7 +41,7 @@ internal class git_worktree_add_options public GitCheckoutOpts checkoutOpts = new GitCheckoutOpts { version = 1, - checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_FORCE + checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_SAFE }; } From 9014820e3a81cf65bf78a623c36a34e6e3a1aa6e Mon Sep 17 00:00:00 2001 From: Lucas Trzesniewski Date: Tue, 7 May 2024 18:06:22 +0200 Subject: [PATCH 377/384] Make owner validation configurable --- .gitignore | 1 + LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 15 ++++++++++ LibGit2Sharp/Core/NativeMethods.cs | 8 ++++++ LibGit2Sharp/Core/Proxy.cs | 32 +++++++++++++++++++++ LibGit2Sharp/GlobalSettings.cs | 13 +++++++++ 5 files changed, 69 insertions(+) diff --git a/.gitignore b/.gitignore index 32e17b4d0..77452df54 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ Thumbs.db *.ncb *.suo .vs/ +.idea/ *.sln.ide/ *.tlb *.tlh diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index e91449b02..17c11083d 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -102,5 +102,20 @@ public void SetExtensions() extensions = GlobalSettings.GetExtensions(); Assert.Equal(new[] { "newext", "noop", "objectformat", "partialclone", "worktreeconfig" }, extensions); } + + [Fact] + public void OwnerValidation() + { + // Assert that owner validation is enabled by default + Assert.True(GlobalSettings.OwnerValidation); + + // Disable owner validation + GlobalSettings.OwnerValidation = false; + Assert.False(GlobalSettings.OwnerValidation); + + // Enable it again + GlobalSettings.OwnerValidation = true; + Assert.True(GlobalSettings.OwnerValidation); + } } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index e8e59843e..f6e6d9a31 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -746,6 +746,10 @@ internal static extern int git_libgit2_opts(int option, uint level, [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_libgit2_opts(int option, int enabled); + // git_libgit2_opts(GIT_OPT_GET_*, int *enabled) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] + internal static extern unsafe 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, @@ -782,6 +786,10 @@ internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, In [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_GET_*, int enabled) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern unsafe 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, diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index cf0a7e3d0..08555eb02 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3397,6 +3397,8 @@ private enum LibGit2Option SetOdbLoosePriority, // GIT_OPT_SET_ODB_LOOSE_PRIORITY, GetExtensions, // GIT_OPT_GET_EXTENSIONS, SetExtensions, // GIT_OPT_SET_EXTENSIONS + GetOwnerValidation, // GIT_OPT_GET_OWNER_VALIDATION + SetOwnerValidation, // GIT_OPT_SET_OWNER_VALIDATION } /// @@ -3570,6 +3572,36 @@ public static string[] git_libgit2_opts_get_extensions() } } + /// + /// Gets the value of owner validation + /// + public static unsafe bool git_libgit2_opts_get_owner_validation() + { + // libgit2 expects non-zero value for true + int res, enabled; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.GetOwnerValidation, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, &enabled); + else + res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetOwnerValidation, &enabled); + Ensure.ZeroResult(res); + return enabled != 0; + } + + /// + /// Enable or disable owner validation + /// + /// true to enable owner validation, false otherwise + public static void git_libgit2_opts_set_owner_validation(bool enabled) + { + // libgit2 expects non-zero value for true + int res; + if (isOSXArm64) + res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.SetOwnerValidation, 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.SetOwnerValidation, enabled ? 1 : 0); + Ensure.ZeroResult(res); + } + #endregion #region git_worktree_ diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index bf7875f96..e11410e28 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -204,6 +204,19 @@ public static string NativeLibraryPath } } + /// + /// Controls the status of repository directory owner validation. + /// + /// + /// By default, repository directories must be owned by the current user to be opened. This can be disabled by setting this property to false. + /// Note that disabling this can lead to security vulnerabilities (see CVE-2022-24765). + /// + public static bool OwnerValidation + { + get => Proxy.git_libgit2_opts_get_owner_validation(); + set => Proxy.git_libgit2_opts_set_owner_validation(value); + } + internal static string GetAndLockNativeLibraryPath() { nativeLibraryPathLocked = true; From f2185721892e3fff3978d11d63df1b208497d7aa Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 25 Nov 2024 23:36:47 -0500 Subject: [PATCH 378/384] Undo gitignore change --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 77452df54..32e17b4d0 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,6 @@ Thumbs.db *.ncb *.suo .vs/ -.idea/ *.sln.ide/ *.tlb *.tlh From d623e3e1af4c6297a725f1703a01c753cb53c0e8 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 25 Nov 2024 23:48:47 -0500 Subject: [PATCH 379/384] Tweaks --- LibGit2Sharp.Tests/GlobalSettingsFixture.cs | 10 +++--- LibGit2Sharp/Core/NativeMethods.cs | 20 +++++++----- LibGit2Sharp/Core/Proxy.cs | 19 +++++++++--- LibGit2Sharp/GlobalSettings.cs | 34 +++++++++++++-------- 4 files changed, 53 insertions(+), 30 deletions(-) diff --git a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs index 17c11083d..925efc3d0 100644 --- a/LibGit2Sharp.Tests/GlobalSettingsFixture.cs +++ b/LibGit2Sharp.Tests/GlobalSettingsFixture.cs @@ -107,15 +107,15 @@ public void SetExtensions() public void OwnerValidation() { // Assert that owner validation is enabled by default - Assert.True(GlobalSettings.OwnerValidation); + Assert.True(GlobalSettings.GetOwnerValidation()); // Disable owner validation - GlobalSettings.OwnerValidation = false; - Assert.False(GlobalSettings.OwnerValidation); + GlobalSettings.SetOwnerValidation(false); + Assert.False(GlobalSettings.GetOwnerValidation()); // Enable it again - GlobalSettings.OwnerValidation = true; - Assert.True(GlobalSettings.OwnerValidation); + GlobalSettings.SetOwnerValidation(true); + Assert.True(GlobalSettings.GetOwnerValidation()); } } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index f6e6d9a31..cbb850b16 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -1,6 +1,8 @@ using System; using System.IO; +#if NET using System.Reflection; +#endif using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; @@ -743,13 +745,10 @@ internal static extern int git_libgit2_opts(int option, uint level, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); // git_libgit2_opts(GIT_OPT_ENABLE_*, int enabled) + // git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, int enabled) [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] internal static extern int git_libgit2_opts(int option, int enabled); - // git_libgit2_opts(GIT_OPT_GET_*, int *enabled) - [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe 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, @@ -766,6 +765,10 @@ internal static extern int git_libgit2_opts(int option, // 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); + + // git_libgit2_opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] + internal static extern unsafe int git_libgit2_opts(int option, int* enabled); #endregion #region git_libgit2_opts_osxarm64 @@ -783,13 +786,10 @@ internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, In [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path); // git_libgit2_opts(GIT_OPT_ENABLE_*, int enabled) + // git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 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_GET_*, int enabled) - [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] - internal static extern unsafe 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, @@ -806,6 +806,10 @@ internal static extern int git_libgit2_opts_osxarm64(int option, IntPtr nop2, In // 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); + + // git_libgit2_opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled) + [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl, EntryPoint = "git_libgit2_opts")] + internal static extern unsafe int git_libgit2_opts_osxarm64(int option, IntPtr nop2, IntPtr nop3, IntPtr nop4, IntPtr nop5, IntPtr nop6, IntPtr nop7, IntPtr nop8, int* enabled); #endregion [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index 08555eb02..83d35e22c 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -3577,13 +3577,20 @@ public static string[] git_libgit2_opts_get_extensions() /// public static unsafe bool git_libgit2_opts_get_owner_validation() { - // libgit2 expects non-zero value for true - int res, enabled; + int res; + int enabled; + if (isOSXArm64) + { res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.GetOwnerValidation, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, &enabled); + } else + { res = NativeMethods.git_libgit2_opts((int)LibGit2Option.GetOwnerValidation, &enabled); + } + Ensure.ZeroResult(res); + return enabled != 0; } @@ -3593,15 +3600,19 @@ public static unsafe bool git_libgit2_opts_get_owner_validation() /// true to enable owner validation, false otherwise public static void git_libgit2_opts_set_owner_validation(bool enabled) { - // libgit2 expects non-zero value for true int res; + if (isOSXArm64) + { res = NativeMethods.git_libgit2_opts_osxarm64((int)LibGit2Option.SetOwnerValidation, 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.SetOwnerValidation, enabled ? 1 : 0); + } + Ensure.ZeroResult(res); } - #endregion #region git_worktree_ diff --git a/LibGit2Sharp/GlobalSettings.cs b/LibGit2Sharp/GlobalSettings.cs index e11410e28..9807155e7 100644 --- a/LibGit2Sharp/GlobalSettings.cs +++ b/LibGit2Sharp/GlobalSettings.cs @@ -204,19 +204,6 @@ public static string NativeLibraryPath } } - /// - /// Controls the status of repository directory owner validation. - /// - /// - /// By default, repository directories must be owned by the current user to be opened. This can be disabled by setting this property to false. - /// Note that disabling this can lead to security vulnerabilities (see CVE-2022-24765). - /// - public static bool OwnerValidation - { - get => Proxy.git_libgit2_opts_get_owner_validation(); - set => Proxy.git_libgit2_opts_set_owner_validation(value); - } - internal static string GetAndLockNativeLibraryPath() { nativeLibraryPathLocked = true; @@ -430,5 +417,26 @@ public static string GetUserAgent() { return Proxy.git_libgit2_opts_get_user_agent(); } + + /// + /// Gets the owner validation setting for repository directories. + /// + /// + public static bool GetOwnerValidation() + { + return Proxy.git_libgit2_opts_get_owner_validation(); + } + + /// + /// Sets whether repository directories should be owned by the current user. The default is to validate ownership. + /// + /// + /// Disabling owner validation can lead to security vulnerabilities (see CVE-2022-24765). + /// + /// true to enable owner validation; otherwise, false. + public static void SetOwnerValidation(bool enabled) + { + Proxy.git_libgit2_opts_set_owner_validation(enabled); + } } } From d89638caed7baca525ac02d0098dfb834310c45a Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Thu, 4 Jan 2024 12:51:40 -0800 Subject: [PATCH 380/384] fix #2071 ObjectDatabase.Write(Stream, long) does not respect T --- LibGit2Sharp/ObjectDatabase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 42b65d7d0..1bad9c907 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -202,7 +202,7 @@ public virtual ObjectId Write(Stream stream, long numberOfBytesToConsume) whe throw new ArgumentException("The stream cannot be read from.", nameof(stream)); } - using (var odbStream = Proxy.git_odb_open_wstream(handle, numberOfBytesToConsume, GitObjectType.Blob)) + using (var odbStream = Proxy.git_odb_open_wstream(handle, numberOfBytesToConsume, GitObject.TypeToGitKindMap[typeof(T)])) { var buffer = new byte[4 * 1024]; long totalRead = 0; From 2dd7eca45c2f95f24817ba8fc6270989df14f78e Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Thu, 11 Feb 2021 13:28:49 -0800 Subject: [PATCH 381/384] Test and fix for https://github.com/libgit2/libgit2sharp/issues/1869 --- LibGit2Sharp.Tests/TreeDefinitionFixture.cs | 18 ++++++++++++++++++ LibGit2Sharp/TreeDefinition.cs | 1 + 2 files changed, 19 insertions(+) diff --git a/LibGit2Sharp.Tests/TreeDefinitionFixture.cs b/LibGit2Sharp.Tests/TreeDefinitionFixture.cs index 99d866c09..6c0c0a41a 100644 --- a/LibGit2Sharp.Tests/TreeDefinitionFixture.cs +++ b/LibGit2Sharp.Tests/TreeDefinitionFixture.cs @@ -587,5 +587,23 @@ public void CanAddAnExistingBlobEntryWithAnExistingTree() Assert.NotNull(td["1/branch_file.txt"]); } } + + [Fact] + public void CanRemoveADirectoryWithChildren() + { + const string blobSha = "a8233120f6ad708f843d861ce2b7228ec4e3dec6"; + string path = SandboxBareTestRepo(); + using (var repo = new Repository(path)) + { + TreeDefinition td = new TreeDefinition(); + var blob = repo.Lookup(blobSha); + td.Add("folder/subfolder/file1", blob, Mode.NonExecutableFile); + td.Add("folder/file1", blob, Mode.NonExecutableFile); + td.Remove("folder"); + Assert.Null(td["folder"]); + Tree t = repo.ObjectDatabase.CreateTree(td); + Assert.Null(t["folder"]); + } + } } } diff --git a/LibGit2Sharp/TreeDefinition.cs b/LibGit2Sharp/TreeDefinition.cs index 73c21aac7..91389f6e3 100644 --- a/LibGit2Sharp/TreeDefinition.cs +++ b/LibGit2Sharp/TreeDefinition.cs @@ -94,6 +94,7 @@ public virtual TreeDefinition Remove(string treeEntryPath) if (segments.Item2 == null) { entries.Remove(segments.Item1); + unwrappedTrees.Remove(segments.Item1); } if (!unwrappedTrees.ContainsKey(segments.Item1)) From ee53bdd8a9f5cfecfc8750e28a1f5c0d34690ce0 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 2 Dec 2024 22:02:44 -0500 Subject: [PATCH 382/384] Update CHANGES.md for v0.31 --- CHANGES.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 1d68e6169..3f0fc677b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,22 @@ # LibGit2Sharp Changes +## v0.31 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.30.0..0.31.0)) + +### Changes +- This release includes [libgit2 v1.8.4](https://github.com/libgit2/libgit2/releases/tag/v1.8.4). +- The ppc64le architecture is now supported on Linux. +- .NET 6 has reached end of support, so LibGit2Sharp now targets `net472` and `net8.0`. + +### Additions +- Adds Depth to FetchOptions allowing for shallow cloning [#2070](https://github.com/libgit2/libgit2sharp/pull/2070) +- Make owner validation configurable [#2093](https://github.com/libgit2/libgit2sharp/pull/2093) +- Add a CloneOptions constructor that takes a FetchOptions [#2132](https://github.com/libgit2/libgit2sharp/pull/2132) + +### Fixes +- TreeDefinition.Remove fails to remove unwrapped trees [#1869](https://github.com/libgit2/libgit2sharp/issues/1869) +- ObjectDatabase.Write(Stream stream...) overload does not respect T [#2071](https://github.com/libgit2/libgit2sharp/issues/2071) +- Repository.Worktrees.Add leaves now worktree empty [#2037](https://github.com/libgit2/libgit2sharp/issues/2037) + ## v0.30 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.29.0..0.30.0)) ### Changes From 827658917a337d508615e78f89b0102ea68fc6d5 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Tue, 3 Dec 2024 17:40:35 -0500 Subject: [PATCH 383/384] Add note about new SSH support --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 3f0fc677b..a00b598d7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ ### Changes - This release includes [libgit2 v1.8.4](https://github.com/libgit2/libgit2/releases/tag/v1.8.4). + - SSH is now supported through [libgit2's support for OpenSSH](https://github.com/libgit2/libgit2/pull/6617). - The ppc64le architecture is now supported on Linux. - .NET 6 has reached end of support, so LibGit2Sharp now targets `net472` and `net8.0`. From 50d697881e857ea0c78d63cc7f23fece3f526852 Mon Sep 17 00:00:00 2001 From: Brandon Ording Date: Mon, 20 Jan 2025 17:49:17 -0500 Subject: [PATCH 384/384] Use arm runner images (#2141) --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d29a0999..54837ac35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,11 +66,10 @@ 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-22.04 + runs-on: ${{ matrix.runnerImage }} strategy: matrix: - arch: [ amd64 ] - # arch: [ amd64, arm64 ] + arch: [ amd64, arm64 ] distro: [ alpine.3.17, alpine.3.18, alpine.3.19, alpine.3.20, centos.stream.9, debian.12, fedora.40, ubuntu.20.04, ubuntu.22.04, ubuntu.24.04 ] sdk: [ '8.0', '9.0' ] exclude: @@ -85,15 +84,16 @@ jobs: tfm: net8.0 - sdk: '9.0' tfm: net9.0 + - arch: amd64 + runnerImage: ubuntu-22.04 + - arch: arm64 + runnerImage: ubuntu-22.04-arm fail-fast: false steps: - name: Checkout uses: actions/checkout@v4.1.2 with: fetch-depth: 0 - - name: Setup QEMU - if: matrix.arch == 'arm64' - 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"