Skip to content

Implement encoding fallback for commit data #427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions LibGit2Sharp.Tests/EncodingFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using LibGit2Sharp.Tests.TestHelpers;
using System;
using System.IO;
using Xunit;
using Xunit.Extensions;

namespace LibGit2Sharp.Tests
{
public class EncodingFixture : BaseFixture
{
[Theory]
//[InlineData("7bc349e5efdb52884cf47d860852e4912b12c244", "MãcRömãñ", 1000)]
[InlineData("782dced4c3930bc3c291b24c115ba9a231049d80", "Lãtïñ Òñê", 1250)]
//[InlineData("29b28e7d3e84aef886c0e00ff9de1a8cc1fda352", "Cõdêpâgê850", 850)]
public void CorruptAuthorNameEncoding(string commitId, string authorName, int commitEncoding)
{
string path = CloneEncodingTestRepo();

using (var repo = new Repository(path))
{
Commit commit = repo.Lookup<Commit>(commitId);
Assert.Equal(authorName, commit.Author.Name);
}
}

}
}
1 change: 1 addition & 0 deletions LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
<Compile Include="TreeFixture.cs" />
<Compile Include="TupleFixture.cs" />
<Compile Include="UnstageFixture.cs" />
<Compile Include="EncodingFixture.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LibGit2Sharp\LibGit2Sharp.csproj">
Expand Down
1 change: 1 addition & 0 deletions LibGit2Sharp.Tests/Resources/commitencodings.git/HEAD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/master
9 changes: 9 additions & 0 deletions LibGit2Sharp.Tests/Resources/commitencodings.git/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[core]
repositoryformatversion = 0
filemode = false
bare = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[remote "origin"]
url = D:/temp/.\\commitencodings
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
6 changes: 6 additions & 0 deletions LibGit2Sharp.Tests/Resources/commitencodings.git/info/exclude
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
x��M
�0@a�9���i�� "x�4�F��#�wӃz�Gp�V/�e�u �w��� 8'3"t3E�F�2q�'FF�³_K��'���W��T[��
K�ˡ�|Ҏ �5�q@T�w���p����Q_~86
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x5˱�0 Qj$v�%4�ك�K�F��CCyһtjB�F��t)v�,,L}���a��\
uǜb^@�k���6�(ڧ��?!�^�Cb#[_ �&U
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
3 changes: 3 additions & 0 deletions LibGit2Sharp.Tests/Resources/commitencodings.git/packed-refs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# pack-refs with: peeled
29b28e7d3e84aef886c0e00ff9de1a8cc1fda352 refs/heads/dos850
c62f9da614246e7f459a2a9d3dc2c325748435b3 refs/heads/master
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c62f9da614246e7f459a2a9d3dc2c325748435b3
7 changes: 7 additions & 0 deletions LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ static BaseFixture()
public static string StandardTestRepoPath { get; private set; }
public static string MergedTestRepoWorkingDirPath { get; private set; }
public static string SubmoduleTestRepoWorkingDirPath { get; private set; }
public static string BareEncodingRepoPath { get; private set; }
public static DirectoryInfo ResourcesDirectory { get; private set; }

public static readonly Signature DummySignature = new Signature("Author N. Ame", "him@there.com", TruncateSubSeconds(DateTimeOffset.Now));
Expand Down Expand Up @@ -56,6 +57,7 @@ private static void SetUpTestEnvironment()
StandardTestRepoPath = Path.Combine(StandardTestRepoWorkingDirPath, ".git");
MergedTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "mergedrepo_wd");
SubmoduleTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_wd");
BareEncodingRepoPath = Path.Combine(ResourcesDirectory.FullName, "commitencodings.git");
}

private static bool IsFileSystemCaseSensitiveInternal()
Expand Down Expand Up @@ -107,6 +109,11 @@ protected string CloneMergedTestRepo()
return Clone(MergedTestRepoWorkingDirPath);
}

protected string CloneEncodingTestRepo()
{
return Clone(BareEncodingRepoPath);
}

public string CloneSubmoduleTestRepo()
{
var submoduleTarget = Path.Combine(ResourcesDirectory.FullName, "submodule_target_wd");
Expand Down
36 changes: 33 additions & 3 deletions LibGit2Sharp/Core/Utf8Marshaler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ internal class Utf8Marshaler : ICustomMarshaler
{
private static readonly Utf8Marshaler staticInstance = new Utf8Marshaler();

private static readonly Encoding marshallerEncoding = UTF8EncodingWithFallBack;

public static Encoding UTF8EncodingWithFallBack
{
get
{
Encoding encoding = (Encoding)Encoding.UTF8.Clone();
encoding.DecoderFallback = new DecoderExceptionFallback();
return encoding;
}
}

public static ICustomMarshaler GetInstance(String cookie)
{
return staticInstance;
Expand Down Expand Up @@ -141,7 +153,7 @@ public static unsafe String FromNative(IntPtr pNativeData)
return String.Empty;
}

return new String((sbyte*)pNativeData.ToPointer(), 0, (int)(walk - start), Encoding.UTF8);
return FromNative(pNativeData, (int)(walk - start));
}

public static unsafe String FromNative(IntPtr pNativeData, int length)
Expand All @@ -156,7 +168,16 @@ public static unsafe String FromNative(IntPtr pNativeData, int length)
return String.Empty;
}

return new String((sbyte*)pNativeData.ToPointer(), 0, length, Encoding.UTF8);
try
{
// Try UTF8 with fallback
return new String((sbyte*)pNativeData.ToPointer(), 0, length, marshallerEncoding);
}
catch (DecoderFallbackException)
{
// If this fails, try the platform default.
return new String((sbyte*)pNativeData.ToPointer(), 0, length, Encoding.Default);
}
}

public static String Utf8FromBuffer(byte[] buffer)
Expand All @@ -180,7 +201,16 @@ public static String Utf8FromBuffer(byte[] buffer)
return String.Empty;
}

return Encoding.UTF8.GetString(buffer, 0, length);
try
{
// Try UTF8 with fallback
return marshallerEncoding.GetString(buffer, 0, length);
}
catch (DecoderFallbackException)
{
// If fails, use platform default
return Encoding.Default.GetString(buffer, 0, length);
}
}
}
}