diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index 522bde697b..1e125d1a6e 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -15,7 +15,7 @@ class GitServiceDesigner : IGitService public IRepository GetRepository(string path) => null; public UriString GetUri(string path, string remote = "origin") => null; public UriString GetUri(IRepository repository, string remote = "origin") => null; - public Task Compare(IRepository repository, string sha1, string sha2, string path) => null; + public Task Compare(IRepository repository, string sha1, string sha2, string relativePath) => null; public Task CompareWith(IRepository repository, string sha1, string sha2, string path, byte[] contents) => null; public Task Compare(IRepository repository, string sha1, string sha2, bool detectRenames = false) => null; } diff --git a/src/GitHub.App/Services/GitClient.cs b/src/GitHub.App/Services/GitClient.cs index 79dfb1df4c..96d22e6d97 100644 --- a/src/GitHub.App/Services/GitClient.cs +++ b/src/GitHub.App/Services/GitClient.cs @@ -259,40 +259,42 @@ public Task GetHttpRemote(IRepository repo, string remote) }); } - public Task ExtractFile(IRepository repository, string commitSha, string fileName) + public Task ExtractFile(IRepository repository, string commitSha, string relativePath) { Guard.ArgumentNotNull(repository, nameof(repository)); Guard.ArgumentNotEmptyString(commitSha, nameof(commitSha)); - Guard.ArgumentIsGitPath(fileName, nameof(fileName)); + Guard.ArgumentIsRelativePath(relativePath, nameof(relativePath)); + var gitPath = Paths.ToGitPath(relativePath); return Task.Run(() => { var commit = repository.Lookup(commitSha); if (commit == null) { - throw new FileNotFoundException("Couldn't find '" + fileName + "' at commit " + commitSha + "."); + throw new FileNotFoundException("Couldn't find '" + gitPath + "' at commit " + commitSha + "."); } - var blob = commit[fileName]?.Target as Blob; + var blob = commit[gitPath]?.Target as Blob; return blob?.GetContentText(); }); } - public Task ExtractFileBinary(IRepository repository, string commitSha, string fileName) + public Task ExtractFileBinary(IRepository repository, string commitSha, string relativePath) { Guard.ArgumentNotNull(repository, nameof(repository)); Guard.ArgumentNotEmptyString(commitSha, nameof(commitSha)); - Guard.ArgumentIsGitPath(fileName, nameof(fileName)); + Guard.ArgumentIsRelativePath(relativePath, nameof(relativePath)); + var gitPath = Paths.ToGitPath(relativePath); return Task.Run(() => { var commit = repository.Lookup(commitSha); if (commit == null) { - throw new FileNotFoundException("Couldn't find '" + fileName + "' at commit " + commitSha + "."); + throw new FileNotFoundException("Couldn't find '" + gitPath + "' at commit " + commitSha + "."); } - var blob = commit[fileName]?.Target as Blob; + var blob = commit[gitPath]?.Target as Blob; if (blob != null) { @@ -308,16 +310,17 @@ public Task ExtractFileBinary(IRepository repository, string commitSha, }); } - public Task IsModified(IRepository repository, string path, byte[] contents) + public Task IsModified(IRepository repository, string relativePath, byte[] contents) { Guard.ArgumentNotNull(repository, nameof(repository)); - Guard.ArgumentIsGitPath(path, nameof(path)); + Guard.ArgumentIsRelativePath(relativePath, nameof(relativePath)); + var gitPath = Paths.ToGitPath(relativePath); return Task.Run(() => { - if (repository.RetrieveStatus(path) == FileStatus.Unaltered) + if (repository.RetrieveStatus(gitPath) == FileStatus.Unaltered) { - var treeEntry = repository.Head[path]; + var treeEntry = repository.Head[gitPath]; if (treeEntry?.TargetType != TreeEntryTargetType.Blob) { return false; @@ -326,7 +329,7 @@ public Task IsModified(IRepository repository, string path, byte[] content var blob1 = (Blob)treeEntry.Target; using (var s = contents != null ? new MemoryStream(contents) : new MemoryStream()) { - var blob2 = repository.ObjectDatabase.CreateBlob(s, path); + var blob2 = repository.ObjectDatabase.CreateBlob(s, gitPath); var diff = repository.Diff.Compare(blob1, blob2); return diff.LinesAdded != 0 || diff.LinesDeleted != 0; } diff --git a/src/GitHub.App/Services/GitHubContextService.cs b/src/GitHub.App/Services/GitHubContextService.cs index df14cdbfa2..5d8944bbb4 100644 --- a/src/GitHub.App/Services/GitHubContextService.cs +++ b/src/GitHub.App/Services/GitHubContextService.cs @@ -282,7 +282,8 @@ public bool TryOpenFile(string repositoryDir, GitHubContext context) return false; } - var fullPath = Path.Combine(repositoryDir, path.Replace('/', '\\')); + var relativePath = Paths.ToWindowsPath(path); + var fullPath = Path.Combine(repositoryDir, relativePath); var textView = OpenDocument(fullPath); SetSelection(textView, context); return true; @@ -404,16 +405,17 @@ public string FindObjectishForTFSTempFile(string tempFile) } /// - public bool HasChangesInWorkingDirectory(string repositoryDir, string commitish, string path) + public bool HasChangesInWorkingDirectory(string repositoryDir, string commitish, string relativePath) { - Guard.ArgumentNotNull(path, nameof(repositoryDir)); - Guard.ArgumentNotNull(path, nameof(commitish)); - Guard.ArgumentIsGitPath(path, nameof(path)); + Guard.ArgumentNotNull(repositoryDir, nameof(repositoryDir)); + Guard.ArgumentNotNull(commitish, nameof(commitish)); + Guard.ArgumentIsRelativePath(relativePath, nameof(relativePath)); + var gitPath = Paths.ToGitPath(relativePath); using (var repo = gitService.GetRepository(repositoryDir)) { var commit = repo.Lookup(commitish); - var paths = new[] { path }; + var paths = new[] { gitPath }; return repo.Diff.Compare(commit.Tree, DiffTargets.WorkingDirectory, paths).Count() > 0; } diff --git a/src/GitHub.App/Services/PullRequestEditorService.cs b/src/GitHub.App/Services/PullRequestEditorService.cs index 597519f7ca..9824f0f0ce 100644 --- a/src/GitHub.App/Services/PullRequestEditorService.cs +++ b/src/GitHub.App/Services/PullRequestEditorService.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using EnvDTE; using GitHub.Commands; +using GitHub.Primitives; using GitHub.Extensions; using GitHub.Models; using GitHub.Models.Drafts; @@ -89,13 +90,12 @@ public async Task OpenFile( try { - var fullPath = GetAbsolutePath(session.LocalRepository, relativePath); string fileName; string commitSha; if (workingDirectory) { - fileName = fullPath; + fileName = Path.Combine(session.LocalRepository.LocalPath, relativePath); commitSha = null; } else @@ -119,7 +119,7 @@ public async Task OpenFile( if (!workingDirectory) { - AddBufferTag(wpfTextView.TextBuffer, session, fullPath, commitSha, null); + AddBufferTag(wpfTextView.TextBuffer, session, relativePath, commitSha, null); EnableNavigateToEditor(textView, session); } } @@ -478,13 +478,6 @@ public static int FindNearestMatchingLine(IList fromLines, IList return matchingLine; } - static string GetAbsolutePath(LocalRepositoryModel localRepository, string relativePath) - { - var localPath = localRepository.LocalPath; - relativePath = relativePath.Replace('/', Path.DirectorySeparatorChar); - return Path.Combine(localPath, relativePath); - } - string GetText(IVsTextView textView) { IVsTextLines buffer; @@ -561,13 +554,13 @@ void ShowErrorInStatusBar(string message, Exception e) void AddBufferTag( ITextBuffer buffer, IPullRequestSession session, - string path, + string relativePath, string commitSha, DiffSide? side) { buffer.Properties.GetOrCreateSingletonProperty( typeof(PullRequestTextBufferInfo), - () => new PullRequestTextBufferInfo(session, path, commitSha, side)); + () => new PullRequestTextBufferInfo(session, relativePath, commitSha, side)); var projection = buffer as IProjectionBuffer; @@ -575,7 +568,7 @@ void AddBufferTag( { foreach (var source in projection.SourceBuffers) { - AddBufferTag(source, session, path, commitSha, side); + AddBufferTag(source, session, relativePath, commitSha, side); } } } @@ -642,9 +635,10 @@ async Task GetBaseFileName(IPullRequestSession session, IPullRequestSess session.LocalRepository, session.PullRequest)) { - var fileChange = changes.FirstOrDefault(x => x.Path == file.RelativePath); + var gitPath = Paths.ToGitPath(file.RelativePath); + var fileChange = changes.FirstOrDefault(x => x.Path == gitPath); return fileChange?.Status == LibGit2Sharp.ChangeKind.Renamed ? - fileChange.OldPath : file.RelativePath; + Paths.ToWindowsPath(fileChange.OldPath) : file.RelativePath; } } diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index 7c143409ba..54f98852eb 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -779,7 +779,7 @@ public async Task ExtractToTempFile( Encoding encoding) { var tempFilePath = CalculateTempFileName(relativePath, commitSha, encoding); - var gitPath = relativePath.TrimStart('/').Replace('\\', '/'); + var gitPath = Paths.ToGitPath(relativePath); if (!File.Exists(tempFilePath)) { @@ -922,24 +922,22 @@ async Task ExtractToTempFile( IRepository repo, int pullRequestNumber, string commitSha, - string path, + string relativePath, Encoding encoding, string tempFilePath) { - Guard.ArgumentIsGitPath(path, nameof(path)); - string contents; try { - contents = await gitClient.ExtractFile(repo, commitSha, path) ?? string.Empty; + contents = await gitClient.ExtractFile(repo, commitSha, relativePath) ?? string.Empty; } catch (FileNotFoundException) { var pullHeadRef = $"refs/pull/{pullRequestNumber}/head"; var remote = await gitClient.GetHttpRemote(repo, "origin"); await gitClient.Fetch(repo, remote.Name, commitSha, pullHeadRef); - contents = await gitClient.ExtractFile(repo, commitSha, path) ?? string.Empty; + contents = await gitClient.ExtractFile(repo, commitSha, relativePath) ?? string.Empty; } Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath)); diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDirectoryNode.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDirectoryNode.cs index c270780ff8..bd79e0270e 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDirectoryNode.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDirectoryNode.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using GitHub.Primitives; namespace GitHub.ViewModels.GitHubPane { @@ -12,11 +13,11 @@ public class PullRequestDirectoryNode : IPullRequestDirectoryNode /// /// Initializes a new instance of the class. /// - /// The path to the directory, relative to the repository. - public PullRequestDirectoryNode(string relativePath) + /// The path to the directory, relative to the repository. + public PullRequestDirectoryNode(string relativeOrGitPath) { - DirectoryName = System.IO.Path.GetFileName(relativePath); - RelativePath = relativePath.Replace("/", "\\"); + DirectoryName = System.IO.Path.GetFileName(relativeOrGitPath); + RelativePath = Paths.ToWindowsPath(relativeOrGitPath); Directories = new List(); Files = new List(); } diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestFileNode.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestFileNode.cs index 374bd131ef..faf3a7fdb7 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestFileNode.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestFileNode.cs @@ -3,6 +3,7 @@ using GitHub.App; using GitHub.Extensions; using GitHub.Models; +using GitHub.Primitives; using ReactiveUI; namespace GitHub.ViewModels.GitHubPane @@ -21,7 +22,7 @@ public class PullRequestFileNode : ReactiveObject, IPullRequestFileNode /// Initializes a new instance of the class. /// /// The absolute path to the repository. - /// The path to the file, relative to the repository. + /// The path to the file, relative to the repository. /// The SHA of the file. /// The way the file was changed. /// The string to display in the [message] box next to the filename. @@ -31,17 +32,17 @@ public class PullRequestFileNode : ReactiveObject, IPullRequestFileNode /// public PullRequestFileNode( string repositoryPath, - string relativePath, + string relativeOrGitPath, string sha, PullRequestFileStatus status, string oldPath) { Guard.ArgumentNotEmptyString(repositoryPath, nameof(repositoryPath)); - Guard.ArgumentNotEmptyString(relativePath, nameof(relativePath)); + Guard.ArgumentNotEmptyString(relativeOrGitPath, nameof(relativeOrGitPath)); Guard.ArgumentNotEmptyString(sha, nameof(sha)); - FileName = Path.GetFileName(relativePath); - RelativePath = relativePath.Replace("/", "\\"); + FileName = Path.GetFileName(relativeOrGitPath); + RelativePath = Paths.ToWindowsPath(relativeOrGitPath); Sha = sha; Status = status; OldPath = oldPath; @@ -54,7 +55,7 @@ public PullRequestFileNode( { if (oldPath != null) { - StatusDisplay = Path.GetDirectoryName(oldPath) == Path.GetDirectoryName(relativePath) ? + StatusDisplay = Path.GetDirectoryName(oldPath) == Path.GetDirectoryName(relativeOrGitPath) ? Path.GetFileName(oldPath) : oldPath; } else diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestFilesViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestFilesViewModel.cs index e367d9611b..9be03eb613 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestFilesViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestFilesViewModel.cs @@ -12,6 +12,7 @@ using System.Windows.Input; using GitHub.Extensions; using GitHub.Models; +using GitHub.Primitives; using GitHub.Services; using LibGit2Sharp; using ReactiveUI; @@ -224,8 +225,8 @@ static string GetOldFileName(PullRequestFileModel file, TreeChanges changes) { if (file.Status == PullRequestFileStatus.Renamed) { - var fileName = file.FileName.Replace("/", "\\"); - return changes?.Renamed.FirstOrDefault(x => x.Path == fileName)?.OldPath; + var gitPath = Paths.ToGitPath(file.FileName); + return changes?.Renamed.FirstOrDefault(x => x.Path == gitPath)?.OldPath; } return null; diff --git a/src/GitHub.App/ViewModels/PullRequestReviewCommentThreadViewModel.cs b/src/GitHub.App/ViewModels/PullRequestReviewCommentThreadViewModel.cs index f5ddb65bb6..5d6b1a12c6 100644 --- a/src/GitHub.App/ViewModels/PullRequestReviewCommentThreadViewModel.cs +++ b/src/GitHub.App/ViewModels/PullRequestReviewCommentThreadViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Globalization; +using System.IO; using System.Linq; using System.Reactive.Linq; using System.Threading.Tasks; @@ -197,7 +198,7 @@ public override async Task PostComment(ICommentViewModel comment) await Session.PostReviewComment( comment.Body, File.CommitSha, - File.RelativePath.Replace("\\", "/"), + Paths.ToGitPath(File.RelativePath), File.Diff, diffPosition.DiffLineNumber).ConfigureAwait(false); } @@ -234,8 +235,8 @@ public static (string key, string secondaryKey) GetDraftKeys( string relativePath, int lineNumber) { - relativePath = relativePath.Replace("\\", "/"); - var key = Invariant($"pr-review-comment|{cloneUri}|{pullRequestNumber}|{relativePath}"); + var gitPath = Paths.ToGitPath(relativePath); + var key = Invariant($"pr-review-comment|{cloneUri}|{pullRequestNumber}|{gitPath}"); return (key, lineNumber.ToString(CultureInfo.InvariantCulture)); } diff --git a/src/GitHub.Exports/Primitives/Paths.cs b/src/GitHub.Exports/Primitives/Paths.cs new file mode 100644 index 0000000000..9cdd4e0677 --- /dev/null +++ b/src/GitHub.Exports/Primitives/Paths.cs @@ -0,0 +1,33 @@ +using System; +using System.IO; + +namespace GitHub.Primitives +{ + /// + /// Convert to and from Git paths. + /// + public static class Paths + { + public const char GitDirectorySeparatorChar = '/'; + + /// + /// Convert from a relative path to a Git path. + /// + /// A relative path. + /// A working directory relative path which uses the '/' directory separator. + public static string ToGitPath(string relativePath) + { + return relativePath.Replace(Path.DirectorySeparatorChar, GitDirectorySeparatorChar); + } + + /// + /// Convert from a Git path to a path that uses the Windows directory separator ('\'). + /// + /// A relative path that uses the '/' directory separator. + /// A relative path that uses the directory separator ('\' on Windows). + public static string ToWindowsPath(string gitPath) + { + return gitPath.Replace(GitDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + } +} diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index e2e886acb7..2ae7d650c5 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -234,13 +234,14 @@ public Task Compare( IRepository repository, string sha1, string sha2, - string path) + string relativePath) { Guard.ArgumentNotNull(repository, nameof(repository)); Guard.ArgumentNotEmptyString(sha1, nameof(sha1)); Guard.ArgumentNotEmptyString(sha2, nameof(sha2)); - Guard.ArgumentIsGitPath(path, nameof(path)); + Guard.ArgumentIsRelativePath(relativePath, nameof(relativePath)); + var gitPath = Paths.ToGitPath(relativePath); return Task.Run(() => { var commit1 = repository.Lookup(sha1); @@ -251,7 +252,7 @@ public Task Compare( return repository.Diff.Compare( commit1.Tree, commit2.Tree, - new[] { path }, + new[] { gitPath }, defaultCompareOptions); } else @@ -261,27 +262,28 @@ public Task Compare( }); } - public Task CompareWith(IRepository repository, string sha1, string sha2, string path, byte[] contents) + public Task CompareWith(IRepository repository, string sha1, string sha2, string relativePath, byte[] contents) { Guard.ArgumentNotNull(repository, nameof(repository)); Guard.ArgumentNotEmptyString(sha1, nameof(sha1)); Guard.ArgumentNotEmptyString(sha2, nameof(sha1)); - Guard.ArgumentIsGitPath(path, nameof(path)); + Guard.ArgumentIsRelativePath(relativePath, nameof(relativePath)); + var gitPath = Paths.ToGitPath(relativePath); return Task.Run(() => { var commit1 = repository.Lookup(sha1); var commit2 = repository.Lookup(sha2); var treeChanges = repository.Diff.Compare(commit1.Tree, commit2.Tree, defaultCompareOptions); - var change = treeChanges.FirstOrDefault(x => x.Path == path); + var change = treeChanges.FirstOrDefault(x => x.Path == gitPath); var oldPath = change?.OldPath; if (commit1 != null && oldPath != null) { var contentStream = contents != null ? new MemoryStream(contents) : new MemoryStream(); var blob1 = commit1[oldPath]?.Target as Blob ?? repository.ObjectDatabase.CreateBlob(new MemoryStream()); - var blob2 = repository.ObjectDatabase.CreateBlob(contentStream, path); + var blob2 = repository.ObjectDatabase.CreateBlob(contentStream, gitPath); return repository.Diff.Compare(blob1, blob2, defaultCompareOptions); } diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 7ad16ad6de..1f183ced17 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -90,13 +90,13 @@ public interface IGitService /// The repository /// The SHA of the first commit. /// The SHA of the second commit. - /// The relative path to the file (using '/' directory separator). + /// The relative path to the file. /// The contents to compare with the file. /// /// A object or null if the commit could not be found in the repository. /// /// If contains a '\'. - Task CompareWith(IRepository repository, string sha1, string sha2, string path, byte[] contents); + Task CompareWith(IRepository repository, string sha1, string sha2, string relativePath, byte[] contents); /// /// Compares two commits. diff --git a/src/GitHub.Extensions/Guard.cs b/src/GitHub.Extensions/Guard.cs index 0862f8c3f0..82bf95c509 100644 --- a/src/GitHub.Extensions/Guard.cs +++ b/src/GitHub.Extensions/Guard.cs @@ -7,15 +7,10 @@ namespace GitHub.Extensions { public static class Guard { - public static void ArgumentIsGitPath(string value, string name) + public static void ArgumentIsRelativePath(string value, string name) { ArgumentNotNull(value, name); - if (value.Contains('\\')) - { - throw new ArgumentException($"The value '{value}' must use '/' not '\\' as directory separator", name); - } - if (Path.IsPathRooted(value)) { throw new ArgumentException($"The value '{value}' must not be rooted", name); diff --git a/src/GitHub.InlineReviews/Services/DiffService.cs b/src/GitHub.InlineReviews/Services/DiffService.cs index 8f685f93ac..1dccd7120e 100644 --- a/src/GitHub.InlineReviews/Services/DiffService.cs +++ b/src/GitHub.InlineReviews/Services/DiffService.cs @@ -29,9 +29,9 @@ public async Task> Diff( IRepository repo, string baseSha, string headSha, - string path) + string relativePath) { - var patch = await gitService.Compare(repo, baseSha, headSha, path); + var patch = await gitService.Compare(repo, baseSha, headSha, relativePath); if (patch != null) { diff --git a/src/GitHub.InlineReviews/Services/PullRequestSession.cs b/src/GitHub.InlineReviews/Services/PullRequestSession.cs index 783254237e..275780d8dd 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSession.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSession.cs @@ -81,12 +81,12 @@ public async Task GetFile( try { PullRequestSessionFile file; - var normalizedPath = relativePath.Replace("\\", "/"); - var key = normalizedPath + '@' + commitSha; + var gitPath = Paths.ToGitPath(relativePath); + var key = gitPath + '@' + commitSha; if (!fileIndex.TryGetValue(key, out file)) { - file = new PullRequestSessionFile(normalizedPath, commitSha); + file = new PullRequestSessionFile(relativePath, commitSha); await UpdateFile(file); fileIndex.Add(key, file); } @@ -110,22 +110,6 @@ public async Task GetMergeBase() return mergeBase; } - /// - public string GetRelativePath(string path) - { - if (Path.IsPathRooted(path)) - { - var basePath = LocalRepository.LocalPath; - - if (path.StartsWith(basePath, StringComparison.OrdinalIgnoreCase) && path.Length > basePath.Length + 1) - { - return path.Substring(basePath.Length + 1); - } - } - - return null; - } - /// public async Task PostReviewComment( string body, diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs index 368832be71..4cdfa9be41 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs @@ -95,13 +95,13 @@ public IReadOnlyList BuildAnnotations( PullRequestDetailModel pullRequest, string relativePath) { - relativePath = relativePath.Replace("\\", "/"); + var gitPath = Paths.ToGitPath(relativePath); return pullRequest.CheckSuites ?.SelectMany(checkSuite => checkSuite.CheckRuns.Select(checkRun => new { checkSuite, checkRun })) .SelectMany(arg => arg.checkRun.Annotations - .Where(annotation => annotation.Path == relativePath) + .Where(annotation => annotation.Path == gitPath) .Select(annotation => new InlineAnnotationModel(arg.checkSuite, arg.checkRun, annotation))) .OrderBy(tuple => tuple.StartLine) .ToArray(); @@ -114,10 +114,10 @@ public IReadOnlyList BuildCommentThreads( IReadOnlyList diff, string headSha) { - relativePath = relativePath.Replace("\\", "/"); + var gitPath = Paths.ToGitPath(relativePath); var threadsByPosition = pullRequest.Threads - .Where(x => x.Path == relativePath) + .Where(x => x.Path == gitPath) .OrderBy(x => x.Id) .GroupBy(x => Tuple.Create(x.OriginalCommitSha, x.OriginalPosition)); var threads = new List(); diff --git a/test/GitHub.Exports.UnitTests/GitServiceIntegrationTests.cs b/test/GitHub.Exports.UnitTests/GitServiceIntegrationTests.cs index 30b6a49381..dd13a4c57f 100644 --- a/test/GitHub.Exports.UnitTests/GitServiceIntegrationTests.cs +++ b/test/GitHub.Exports.UnitTests/GitServiceIntegrationTests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using GitHub.Primitives; using GitHub.Services; using LibGit2Sharp; using NUnit.Framework; @@ -61,7 +62,7 @@ public async Task One_File_Is_Modified(string content1, string content2) [Test] - public void Path_Must_Not_Use_Windows_Directory_Separator() + public async Task Path_Can_Use_Windows_Directory_Separator() { using (var temp = new TempRepository()) { @@ -72,8 +73,10 @@ public void Path_Must_Not_Use_Windows_Directory_Separator() var commit2 = AddCommit(temp.Repository, path, newContent); var target = new GitService(new RepositoryFacade()); - Assert.ThrowsAsync(() => - target.Compare(temp.Repository, commit1.Sha, commit2.Sha, path)); + var patch = await target.Compare(temp.Repository, commit1.Sha, commit2.Sha, path); + + var gitPath = Paths.ToGitPath(path); + Assert.That(patch.Count(c => c.Path == gitPath), Is.EqualTo(1)); } } } @@ -134,7 +137,7 @@ public async Task Can_Handle_Renames(string oldPath, string oldContent, string n } [Test] - public void Path_Must_Not_Use_Windows_Directory_Separator() + public async Task Path_Can_Use_Windows_Directory_Separator() { using (var temp = new TempRepository()) { @@ -146,8 +149,10 @@ public void Path_Must_Not_Use_Windows_Directory_Separator() var contentBytes = new UTF8Encoding(false).GetBytes(newContent); var target = new GitService(new RepositoryFacade()); - Assert.ThrowsAsync(() => - target.CompareWith(temp.Repository, commit1.Sha, commit2.Sha, path, contentBytes)); + var contentChanges = await target.CompareWith(temp.Repository, commit1.Sha, commit2.Sha, path, contentBytes); + + Assert.That(contentChanges.LinesAdded, Is.EqualTo(1)); + Assert.That(contentChanges.LinesDeleted, Is.EqualTo(1)); } } }