diff --git a/.editorconfig b/.editorconfig
index 096ff2565..2e54d0f2d 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,6 +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,csproj,config}]
+indent_size = 2
\ No newline at end of file
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
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 000000000..54837ac35
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,102 @@
+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: Build
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4.1.2
+ with:
+ fetch-depth: 0
+ - name: Install .NET SDK
+ uses: actions/setup-dotnet@v4.0.0
+ with:
+ dotnet-version: 9.0.x
+ - name: Build
+ run: dotnet build LibGit2Sharp.sln --configuration Release
+ - name: Upload packages
+ uses: actions/upload-artifact@v4.3.1
+ with:
+ name: NuGet packages
+ path: artifacts/package/
+ retention-days: 7
+ - name: Verify trimming compatibility
+ run: dotnet publish TrimmingTestApp
+ test:
+ name: Test / ${{ matrix.os }} / ${{ matrix.arch }} / ${{ matrix.tfm }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ arch: [ x64 ]
+ os: [ windows-2019, windows-2022, macos-13 ]
+ tfm: [ net472, net8.0, net9.0 ]
+ exclude:
+ - os: macos-13
+ tfm: net472
+ include:
+ - arch: arm64
+ os: macos-14
+ tfm: net8.0
+ - arch: arm64
+ os: macos-14
+ tfm: net9.0
+ fail-fast: false
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4.1.2
+ with:
+ fetch-depth: 0
+ - name: Install .NET SDK
+ uses: actions/setup-dotnet@v4.0.0
+ with:
+ dotnet-version: |
+ 9.0.x
+ 8.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:
+ name: Test / ${{ matrix.distro }} / ${{ matrix.arch }} / ${{ matrix.tfm }}
+ runs-on: ${{ matrix.runnerImage }}
+ strategy:
+ matrix:
+ 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:
+ - distro: alpine.3.17
+ sdk: '9.0'
+ - distro: alpine.3.18
+ sdk: '9.0'
+ - distro: alpine.3.19
+ sdk: '9.0'
+ include:
+ - sdk: '8.0'
+ 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: 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" -e OPENSSL_ENABLE_SHA1_SIGNATURES=1 gittools/build-images:${{ matrix.distro }}-sdk-${{ matrix.sdk }} sh -c "$git_command && $test_command"
+
diff --git a/.gitignore b/.gitignore
index 2009f0208..32e17b4d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,10 +36,7 @@ _ReSharper*/
*.userprefs
*.swp
*.DotSettings
-#Ignore custom generated files
-LibGit2Sharp/Core/UniqueIdentifier.cs
-LibGit2Sharp/Core/NativeDllName.cs
-!nuget.package/build/
_NCrunch_LibGit2Sharp/
-packages/
+artifacts/
+worktree.playlist
diff --git a/.nuget/packages.config b/.nuget/packages.config
deleted file mode 100644
index 57b9c468a..000000000
--- a/.nuget/packages.config
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index d09406bbe..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-# Travis-CI Build for libgit2sharp
-# see travis-ci.org for details
-
-language: csharp
-mono:
- - 4.8.0
-
-os:
- - osx
- - linux
-
-env:
- global:
- - MONO_OPTIONS=--debug
-
-install:
- - curl -L -o nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
- - mono nuget.exe restore LibGit2Sharp.sln
-
-before_install:
- - date -u
- - uname -a
- - env | sort
-
-solution: LibGit2Sharp.sln
-
-# Build libgit2, LibGit2Sharp and run the tests
-script:
- - ./build.libgit2sharp.sh 'LEAKS_IDENTIFYING'
-
-# Only watch the development branch
-branches:
- only:
- - master
- - /^maint.*/
-
-# Notify of build changes
-notifications:
- email:
- - emeric.fermas@gmail.com
diff --git a/CHANGES.md b/CHANGES.md
index 790f7a84f..a00b598d7 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,22 +1,127 @@
# LibGit2Sharp Changes
-**LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .Net and Mono.**
+## v0.31 - ([diff](https://github.com/libgit2/libgit2sharp/compare/0.30.0..0.31.0))
- - Source code:
- - NuGet package:
- - Issue tracker:
- - @libgit2sharp:
- - CI servers:
- - Windows (x86/amd64):
- - Linux/Mac OS X:
+### 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`.
+
+### 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
+- 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
+- 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.24 + 1
+## 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)
+
+## 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)
+
+## 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))
+
+### 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))
+
+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
+ untracked files, included the `StatusOptions.IncludeUntracked` and/or
+ 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/CI/build.msbuild b/CI/build.msbuild
deleted file mode 100644
index d4b0faae4..000000000
--- a/CI/build.msbuild
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
- Release
- $(MSBuildProjectDirectory)\..
- $(RootDir)\LibGit2Sharp.Tests\bin\$(Configuration)
- $(RootDir)\Build
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d487a49aa..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
- the `build.libgit2sharp.cmd` script on Windows or `build.libgit2sharp.sh` on Linux/Mac.
+* 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,10 +49,10 @@ 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
* [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/)
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 000000000..2c14cc2bd
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,14 @@
+
+
+
+ true
+ true
+ true
+ $(DefineConstants);$(ExtraDefine)
+
+
+
+ true
+
+
+
diff --git a/Lib/.gitattributes b/Lib/.gitattributes
deleted file mode 100644
index 2fa88711b..000000000
--- a/Lib/.gitattributes
+++ /dev/null
@@ -1,3 +0,0 @@
-* binary
-.gitattributes text -binary
-*.txt text -binary
diff --git a/Lib/CustomBuildTasks/CustomBuildTasks.csproj b/Lib/CustomBuildTasks/CustomBuildTasks.csproj
deleted file mode 100644
index 351e4873f..000000000
--- a/Lib/CustomBuildTasks/CustomBuildTasks.csproj
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {B6138573-A4B9-44E7-83C2-8964CAF51EDA}
- Library
- Properties
- CustomBuildTasks
- CustomBuildTasks
- v4.0
- 512
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Lib/CustomBuildTasks/CustomBuildTasks.dll b/Lib/CustomBuildTasks/CustomBuildTasks.dll
deleted file mode 100644
index cd763a2e1..000000000
Binary files a/Lib/CustomBuildTasks/CustomBuildTasks.dll and /dev/null differ
diff --git a/Lib/CustomBuildTasks/GenerateNativeDllNameTask.cs b/Lib/CustomBuildTasks/GenerateNativeDllNameTask.cs
deleted file mode 100644
index 9b31fba34..000000000
--- a/Lib/CustomBuildTasks/GenerateNativeDllNameTask.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.IO;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace CustomBuildTasks
-{
- public class GenerateNativeDllNameTask : Task
- {
- public ITaskItem InputHashFile { get; set; }
-
- public string OutputFile { get; set; }
-
- public override bool Execute()
- {
- var fileName = InputHashFile.GetMetadata("FullPath");
- string libgit2FileName;
-
- using (var sr = new StreamReader(fileName))
- {
- libgit2FileName = sr.ReadLine();
- }
-
- var nativeDllName = @"namespace LibGit2Sharp.Core
-{{
- internal static class NativeDllName
- {{
- public const string Name = ""{0}"";
- }}
-}}
-";
-
- using (var sw = new StreamWriter(OutputFile))
- {
- sw.Write(nativeDllName, libgit2FileName);
- }
-
- return true;
- }
- }
-}
diff --git a/Lib/CustomBuildTasks/GenerateUniqueIdentifierTask.cs b/Lib/CustomBuildTasks/GenerateUniqueIdentifierTask.cs
deleted file mode 100644
index 2f26ac94d..000000000
--- a/Lib/CustomBuildTasks/GenerateUniqueIdentifierTask.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace CustomBuildTasks
-{
- public class GenerateUniqueIdentifierTask : Task
- {
- public override bool Execute()
- {
- using (FileStream fs = new FileStream(this.OutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
- using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
- {
- sw.WriteLine("using System;");
- sw.WriteLine();
- sw.WriteLine("namespace LibGit2Sharp.Core");
- sw.WriteLine("{");
- sw.WriteLine(" internal static class UniqueId");
- sw.WriteLine(" {");
- sw.WriteLine(" public const String UniqueIdentifier = \"" + Guid.NewGuid().ToString() + "\";");
- sw.WriteLine(" }");
- sw.WriteLine("}");
- }
-
- return true;
- }
-
- public String OutputFile
- {
- get;
- set;
- }
- }
-}
diff --git a/Lib/NuGet/NuGet.exe b/Lib/NuGet/NuGet.exe
deleted file mode 100644
index 66794573f..000000000
Binary files a/Lib/NuGet/NuGet.exe and /dev/null differ
diff --git a/Lib/NuGet/NuGet.license.txt b/Lib/NuGet/NuGet.license.txt
deleted file mode 100644
index 48715cacc..000000000
--- a/Lib/NuGet/NuGet.license.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
-
-1. Definitions
-
-The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
-
-A "contribution" is the original software, or any additions or changes to the software.
-
-A "contributor" is any person that distributes its contribution under this license.
-
-"Licensed patents" are a contributor's patent claims that read directly on its contribution.
-
-2. Grant of Rights
-
-(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
-
-(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
-
-3. Conditions and Limitations
-
-(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
-
-(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
-
-(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
-
-(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
-
-(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
diff --git a/LibGit2Sharp.Tests/ArchiveTarFixture.cs b/LibGit2Sharp.Tests/ArchiveTarFixture.cs
index a21847ea0..247a9a3b0 100644
--- a/LibGit2Sharp.Tests/ArchiveTarFixture.cs
+++ b/LibGit2Sharp.Tests/ArchiveTarFixture.cs
@@ -30,8 +30,8 @@ public void CanArchiveACommitWithDirectoryAsTar()
repo.ObjectDatabase.Archive(commit, archivePath);
- using (var expectedStream = new StreamReader(Path.Combine(ResourcesDirectory.FullName, "expected_archives/commit_with_directory.tar")))
- using (var actualStream = new StreamReader(archivePath))
+ using (var expectedStream = new StreamReader(File.OpenRead(Path.Combine(ResourcesDirectory.FullName, "expected_archives/commit_with_directory.tar"))))
+ using (var actualStream = new StreamReader(File.OpenRead(archivePath)))
{
string expected = expectedStream.ReadToEnd();
string actual = actualStream.ReadToEnd();
diff --git a/LibGit2Sharp.Tests/BlameFixture.cs b/LibGit2Sharp.Tests/BlameFixture.cs
index 9138646c3..8cefcfb45 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);
}
}
@@ -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,8 +78,8 @@ 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"});
- Assert.True(blame[0].FinalCommit.Sha.StartsWith("be3563a"));
+ var blame = repo.Blame("new.txt", new BlameOptions { StoppingAt = "be3563a" });
+ Assert.StartsWith("be3563a", blame[0].FinalCommit.Sha);
}
}
}
diff --git a/LibGit2Sharp.Tests/BlobFixture.cs b/LibGit2Sharp.Tests/BlobFixture.cs
index 371e50c51..314dea379 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
{
@@ -16,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();
@@ -37,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"));
@@ -44,6 +45,7 @@ public void CanGetBlobAsFilteredText(string autocrlf, string expectedText)
}
}
+#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")]
@@ -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())
{
@@ -83,6 +86,7 @@ public void CanGetBlobAsTextWithVariousEncodings(string encodingName, int expect
Assert.Equal(expectedUtf7Chars, string.Join(" ", utf7Chars));
}
}
+#endif
[Fact]
public void CanGetBlobSize()
@@ -91,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);
}
}
@@ -103,6 +108,7 @@ public void CanLookUpBlob()
{
var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6");
Assert.NotNull(blob);
+ Assert.False(blob.IsMissing);
}
}
@@ -113,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);
@@ -139,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);
@@ -163,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")))
{
@@ -185,7 +194,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());
}
@@ -195,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")))
@@ -216,7 +226,32 @@ public void CanTellIfTheBlobContentLooksLikeBinary()
using (var repo = new Repository(path))
{
var blob = repo.Lookup("a8233120f6ad708f843d861ce2b7228ec4e3dec6");
- Assert.Equal(false, blob.IsBinary);
+ 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")));
}
}
diff --git a/LibGit2Sharp.Tests/BranchFixture.cs b/LibGit2Sharp.Tests/BranchFixture.cs
index 2bc65892b..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
{
@@ -51,6 +50,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()
{
@@ -74,7 +86,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"];
@@ -90,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);
@@ -262,7 +274,7 @@ public void CreatingABranchTriggersTheCreationOfADirectReference()
Reference reference = repo.Refs[newBranch.CanonicalName];
Assert.NotNull(reference);
- Assert.IsType(typeof(DirectReference), reference);
+ Assert.IsType(reference);
}
}
@@ -563,7 +575,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);
@@ -988,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);
@@ -1113,7 +1125,7 @@ public void TrackedBranchExistsFromDefaultConfigInEmptyClone()
using (var emptyRepo = new Repository(repoPath))
{
- uri = new Uri(emptyRepo.Info.Path);
+ uri = new Uri($"file://{emptyRepo.Info.Path}");
}
SelfCleaningDirectory scd2 = BuildSelfCleaningDirectory();
@@ -1123,7 +1135,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 0648ded10..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);
}
@@ -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().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().Ignored.Count());
+ Assert.Single(repo.RetrieveStatus(new StatusOptions { IncludeIgnored = true }).Ignored);
Assert.Equal(FileStatus.Ignored, repo.RetrieveStatus(ignoredFilePath));
@@ -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);
@@ -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());
@@ -1029,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.Tests/CherryPickFixture.cs b/LibGit2Sharp.Tests/CherryPickFixture.cs
index 1bbff1428..f4a383fef 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);
}
}
@@ -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.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 ae98788eb..831f6779f 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
{
@@ -14,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();
@@ -33,8 +30,36 @@ 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());
+ }
+ }
+
+ [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());
}
}
@@ -70,18 +95,18 @@ 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());
- Assert.Equal(1, clonedRepo.Network.Remotes.Count());
+ Assert.Single(clonedRepo.Network.Remotes);
}
}
[Fact]
public void CanCloneALocalRepositoryFromALocalUri()
{
- var uri = new Uri(Path.GetFullPath(BareTestRepoPath));
+ var uri = new Uri($"file://{Path.GetFullPath(BareTestRepoPath)}");
AssertLocalClone(uri.AbsoluteUri, BareTestRepoPath);
}
@@ -103,16 +128,14 @@ 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();
string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions
- {
- IsBare = true
- });
+ {
+ IsBare = true
+ });
using (var repo = new Repository(clonedRepoPath))
{
@@ -127,7 +150,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();
@@ -144,7 +167,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;
@@ -156,10 +179,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);
@@ -179,7 +206,7 @@ public void CanCloneWithCredentials()
string clonedRepoPath = Repository.Clone(Constants.PrivateRepoUrl, scd.DirectoryPath,
new CloneOptions()
{
- CredentialsProvider = Constants.PrivateRepoCredentials
+ FetchOptions = { CredentialsProvider = Constants.PrivateRepoCredentials }
});
@@ -195,7 +222,7 @@ public void CanCloneWithCredentials()
}
}
- static Credentials CreateUsernamePasswordCredentials (string user, string pass, bool secure)
+ static Credentials CreateUsernamePasswordCredentials(string user, string pass, bool secure)
{
if (secure)
{
@@ -213,80 +240,87 @@ static Credentials CreateUsernamePasswordCredentials (string user, string pass,
};
}
- [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))]
- [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();
InconclusiveIf(
() =>
- certType == typeof (CertificateSsh) && !GlobalSettings.Version.Features.HasFlag(BuiltInFeatures.Ssh),
+ 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.True(x509.Subject.Contains("CN=github.com,"));
- checksHappy = true;
- return false;
- }
+ var options = new CloneOptions
+ {
+ FetchOptions =
+ {
+ 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;
+ }
- 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(() =>
@@ -297,16 +331,8 @@ 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")]
+ [InlineData("https://github.com/libgit2/TestGitRepository")]
public void CloningWithoutWorkdirPathThrows(string url)
{
Assert.Throws(() => Repository.Clone(url, null));
@@ -361,7 +387,7 @@ private class CloneCallbackInfo
[Fact]
public void CanRecursivelyCloneSubmodules()
{
- var uri = new Uri(Path.GetFullPath(SandboxSubmoduleSmallTestRepo()));
+ var uri = new Uri($"file://{Path.GetFullPath(SandboxSubmoduleSmallTestRepo())}");
var scd = BuildSelfCleaningDirectory();
string relativeSubmodulePath = "submodule_target_wd";
@@ -441,15 +467,18 @@ 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);
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 });
}
@@ -460,14 +489,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()
{
@@ -494,7 +523,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 |
@@ -512,7 +541,7 @@ public void CanRecursivelyCloneSubmodules()
[Fact]
public void CanCancelRecursiveClone()
{
- var uri = new Uri(Path.GetFullPath(SandboxSubmoduleSmallTestRepo()));
+ var uri = new Uri($"file://{Path.GetFullPath(SandboxSubmoduleSmallTestRepo())}");
var scd = BuildSelfCleaningDirectory();
string relativeSubmodulePath = "submodule_target_wd";
@@ -526,7 +555,7 @@ public void CanCancelRecursiveClone()
CloneOptions options = new CloneOptions()
{
RecurseSubmodules = true,
- RepositoryOperationStarting = repositoryOperationStarting,
+ FetchOptions = { RepositoryOperationStarting = repositoryOperationStarting }
};
Assert.Throws(() =>
@@ -541,7 +570,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());
@@ -549,7 +578,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,
@@ -557,5 +586,48 @@ 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();
+ cloneOptions.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();
+ cloneOptions.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();
+ cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader };
+
+ var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, cloneOptions);
+ Assert.True(Directory.Exists(clonedRepoPath));
+ }
}
}
diff --git a/LibGit2Sharp.Tests/CommitFixture.cs b/LibGit2Sharp.Tests/CommitFixture.cs
index b522e3c34..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
{
@@ -70,7 +68,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());
}
@@ -150,13 +148,13 @@ 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.True(commit.Sha.StartsWith(reversedShas[count]));
+ Assert.StartsWith(reversedShas[count], commit.Sha);
count++;
}
}
@@ -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);
@@ -204,7 +202,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);
}
}
@@ -216,13 +214,13 @@ 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.True(commit.Sha.StartsWith(expectedShas[count]));
+ Assert.StartsWith(expectedShas[count], commit.Sha);
count++;
}
}
@@ -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",
@@ -406,7 +407,7 @@ public void CanEnumerateCommitsFromATagWhichPointsToABlob()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { IncludeReachableFrom = repo.Tags["point_to_blob"] },
- new string[] { });
+ Array.Empty());
}
[Fact]
@@ -421,7 +422,7 @@ public void CanEnumerateCommitsFromATagWhichPointsToATree()
AssertEnumerationOfCommitsInRepo(repo,
r => new CommitFilter { IncludeReachableFrom = tag },
- new string[] { });
+ Array.Empty());
}
}
@@ -475,16 +476,16 @@ 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);
- Assert.Equal(0, commit.Parents.Count());
+ Assert.Empty(commit.Parents);
}
}
@@ -590,8 +591,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,18 +671,22 @@ 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);
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);
@@ -689,7 +694,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 +706,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 +726,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 +781,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);
}
@@ -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" };
@@ -889,9 +894,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);
@@ -918,7 +923,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 +1005,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);
}
}
@@ -1058,8 +1063,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 +1107,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 +1160,7 @@ public void CanCreateACommitString()
[Fact]
public void CanCreateASignedCommit()
{
- string repoPath = InitNewRepository();
+ string repoPath = SandboxStandardTestRepo();
using (var repo = new Repository(repoPath))
{
var odb = repo.ObjectDatabase;
diff --git a/LibGit2Sharp.Tests/ConfigurationFixture.cs b/LibGit2Sharp.Tests/ConfigurationFixture.cs
index 3e071c3b7..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
{
@@ -50,6 +49,113 @@ public void CanUnsetAnEntryFromTheGlobalConfiguration()
}
}
+ [Fact]
+ public void CanAddAndReadMultivarFromTheLocalConfiguration()
+ {
+ string path = SandboxStandardTestRepo();
+ using (var repo = new Repository(path))
+ {
+ 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);
+
+ 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.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);
+
+ 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.DoesNotContain(repo.Config.OfType>(), x => x.Key == "unittests.plugin");
+ }
+ }
+
[Fact]
public void CanReadBooleanValue()
{
@@ -59,9 +165,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 +216,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"));
@@ -418,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]
@@ -464,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/ConflictFixture.cs b/LibGit2Sharp.Tests/ConflictFixture.cs
index cabf4a4cf..6317bf431 100644
--- a/LibGit2Sharp.Tests/ConflictFixture.cs
+++ b/LibGit2Sharp.Tests/ConflictFixture.cs
@@ -48,7 +48,7 @@ private static List