Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit cdba774

Browse files
authored
Merge pull request #1011 from github/fixes/1010-diff-encoding
Save PR merge base file as UTF-8 if working file is UTF-8
2 parents 0d04613 + e9e3cd9 commit cdba774

File tree

3 files changed

+74
-8
lines changed

3 files changed

+74
-8
lines changed

src/GitHub.App/GlobalSuppressions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
[assembly: SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "GitHub.Caches.CredentialCache.#InsertObject`1(System.String,!!0,System.Nullable`1<System.DateTimeOffset>)")]
66
[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Git", Scope = "resource", Target = "GitHub.App.Resources.resources")]
77
[assembly: SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "GitHub.Services.PullRequestService.#CreateTempFile(System.String,System.String,System.String)")]
8+
[assembly: SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "GitHub.Services.PullRequestService.#CreateTempFile(System.String,System.String,System.String,System.Text.Encoding)")]
89
// This file is used by Code Analysis to maintain SuppressMessage
910
// attributes that are applied to this project.
1011
// Project-level suppressions either have no target or are given

src/GitHub.App/Services/PullRequestService.cs

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -299,15 +299,53 @@ public IObservable<Tuple<string, string>> ExtractDiffFiles(
299299
throw new FileNotFoundException($"Couldn't find merge base between {baseSha} and {headSha}.");
300300
}
301301

302-
// We've found the merge base so these should already be fetched.
303-
var left = await ExtractToTempFile(repo, mergeBase, fileName);
304-
var right = isPullRequestBranchCheckedOut ?
305-
Path.Combine(repository.LocalPath, fileName) : await ExtractToTempFile(repo, headSha, fileName);
302+
string left;
303+
string right;
304+
if (isPullRequestBranchCheckedOut)
305+
{
306+
right = Path.Combine(repository.LocalPath, fileName);
307+
left = await ExtractToTempFile(repo, mergeBase, fileName, GetEncoding(right));
308+
}
309+
else
310+
{
311+
left = await ExtractToTempFile(repo, mergeBase, fileName, Encoding.Default);
312+
right = await ExtractToTempFile(repo, headSha, fileName, Encoding.Default);
313+
}
306314

307315
return Observable.Return(Tuple.Create(left, right));
308316
});
309317
}
310318

319+
static Encoding GetEncoding(string file)
320+
{
321+
if (File.Exists(file))
322+
{
323+
var encoding = Encoding.UTF8;
324+
if (IsEncoding(file, encoding))
325+
{
326+
return encoding;
327+
}
328+
}
329+
330+
return Encoding.Default;
331+
}
332+
333+
static bool IsEncoding(string file, Encoding encoding)
334+
{
335+
using (var stream = File.OpenRead(file))
336+
{
337+
foreach (var b in encoding.GetPreamble())
338+
{
339+
if(b != stream.ReadByte())
340+
{
341+
return false;
342+
}
343+
}
344+
}
345+
346+
return true;
347+
}
348+
311349
public IObservable<Unit> RemoveUnusedRemotes(ILocalRepositoryModel repository)
312350
{
313351
return Observable.Defer(async () =>
@@ -362,20 +400,20 @@ string CreateUniqueRemoteName(IRepository repo, string name)
362400
return uniqueName;
363401
}
364402

365-
async Task<string> ExtractToTempFile(IRepository repo, string commitSha, string fileName)
403+
async Task<string> ExtractToTempFile(IRepository repo, string commitSha, string fileName, Encoding encoding)
366404
{
367405
var contents = await gitClient.ExtractFile(repo, commitSha, fileName) ?? string.Empty;
368-
return CreateTempFile(fileName, commitSha, contents);
406+
return CreateTempFile(fileName, commitSha, contents, encoding);
369407
}
370408

371-
static string CreateTempFile(string fileName, string commitSha, string contents)
409+
static string CreateTempFile(string fileName, string commitSha, string contents, Encoding encoding)
372410
{
373411
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
374412
var tempFileName = $"{Path.GetFileNameWithoutExtension(fileName)}@{commitSha}{Path.GetExtension(fileName)}";
375413
var tempFile = Path.Combine(tempDir, tempFileName);
376414

377415
Directory.CreateDirectory(tempDir);
378-
File.WriteAllText(tempFile, contents, Encoding.UTF8);
416+
File.WriteAllText(tempFile, contents, encoding);
379417
return tempFile;
380418
}
381419

src/UnitTests/GitHub.App/Services/PullRequestServiceTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.IO;
3+
using System.Text;
34
using System.Collections.Generic;
45
using System.Linq;
56
using System.Reactive.Linq;
@@ -128,6 +129,32 @@ public async Task CheckedOut_BaseFromWorkingFile()
128129
Assert.Equal(workingFile, files.Item2);
129130
}
130131

132+
// https://github.com/github/VisualStudio/issues/1010
133+
[Theory]
134+
[InlineData("utf-8")] // Unicode (UTF-8)
135+
[InlineData("Windows-1252")] // Western European (Windows)
136+
public async Task CheckedOut_DifferentEncodings(string encodingName)
137+
{
138+
var encoding = Encoding.GetEncoding(encodingName);
139+
var repoDir = Path.GetTempPath();
140+
var baseFileContent = "baseFileContent";
141+
var headFileContent = null as string;
142+
var fileName = "fileName.txt";
143+
var baseSha = "baseSha";
144+
var headSha = "headSha";
145+
var baseRef = new GitReferenceModel("ref", "label", baseSha, "uri");
146+
var checkedOut = true;
147+
var workingFile = Path.Combine(repoDir, fileName);
148+
var workingFileContent = baseFileContent;
149+
File.WriteAllText(workingFile, workingFileContent, encoding);
150+
151+
var files = await ExtractDiffFiles(baseSha, baseFileContent, headSha, headFileContent,
152+
baseSha, baseFileContent, fileName, checkedOut, repoDir);
153+
154+
Assert.Equal(File.ReadAllText(files.Item1), File.ReadAllText(files.Item2));
155+
Assert.Equal(File.ReadAllBytes(files.Item1), File.ReadAllBytes(files.Item2));
156+
}
157+
131158
[Fact]
132159
public async Task HeadBranchNotAvailable_ThrowsFileNotFoundException()
133160
{

0 commit comments

Comments
 (0)