From 80abca23a146a2e92d8904d7cb64a209b1adf5da Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 09:30:15 +0100 Subject: [PATCH 01/39] Remove IGitService dependency from RepositoryModel Refactor the constructor that took IGitService into LocalRepositoryModel where it was used. --- .../Models/LocalRepositoryModel.cs | 15 +++++++++---- src/GitHub.Exports/Models/RepositoryModel.cs | 22 ++----------------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index fe07ef5ab8..a1e26fe939 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -41,15 +41,22 @@ public LocalRepositoryModel(string name, UriString cloneUrl, string localPath, I /// /// Initializes a new instance of the class. /// - /// The repository's local path. + /// The repository's local path. /// The service used to find the repository's URL. - public LocalRepositoryModel(string path, IGitService gitService) - : base(path, gitService) + public LocalRepositoryModel(string localPath, IGitService gitService) { Guard.ArgumentNotNull(gitService, nameof(gitService)); + Guard.ArgumentNotNull(localPath, nameof(localPath)); + var dir = new DirectoryInfo(localPath); + if (!dir.Exists) + { + throw new ArgumentException("Path does not exist", nameof(localPath)); + } + CloneUrl = gitService.GetUri(localPath); + LocalPath = localPath; + Name = CloneUrl?.RepositoryName ?? dir.Name; this.gitService = gitService; - LocalPath = path; Icon = Octicon.repo; } diff --git a/src/GitHub.Exports/Models/RepositoryModel.cs b/src/GitHub.Exports/Models/RepositoryModel.cs index 3ec99829b5..f8cfc718d6 100644 --- a/src/GitHub.Exports/Models/RepositoryModel.cs +++ b/src/GitHub.Exports/Models/RepositoryModel.cs @@ -1,9 +1,7 @@ using System; using System.Diagnostics; -using System.IO; using GitHub.Extensions; using GitHub.Primitives; -using GitHub.Services; using GitHub.UI; namespace GitHub.Models @@ -33,30 +31,14 @@ public RepositoryModel( CloneUrl = cloneUrl; } - /// - /// Initializes a new instance of the class. - /// - /// - /// The path to the local repository from which repository name and clone URL will be - /// extracted. - /// - /// The service used to find the repository's and . - protected RepositoryModel(string path, IGitService gitService) + protected RepositoryModel() { - Guard.ArgumentNotNull(path, nameof(path)); - - var dir = new DirectoryInfo(path); - if (!dir.Exists) - throw new ArgumentException("Path does not exist", nameof(path)); - var uri = gitService.GetUri(path); - Name = uri?.RepositoryName ?? dir.Name; - CloneUrl = gitService.GetUri(path); } /// /// Gets the name of the repository. /// - public string Name { get; } + public string Name { get; protected set; } /// /// Gets the repository clone URL. From 1177e933de4275615f2ab5d3e2bff8d4d7c68f07 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 11:45:14 +0100 Subject: [PATCH 02/39] Move LocalRepositoryModel ctor into GitService 1/2 --- .../SampleData/GitServiceDesigner.cs | 2 + .../PullRequestCreationViewModelDesigner.cs | 16 +++++--- src/GitHub.Exports/Models/BranchModel.cs | 3 +- .../Models/LocalRepositoryModel.cs | 28 +++---------- src/GitHub.Exports/Models/RepositoryModel.cs | 6 +-- src/GitHub.Exports/Services/GitService.cs | 39 ++++++++++++++++--- src/GitHub.Exports/Services/IGitService.cs | 7 ++++ .../RegistryHelper.cs | 3 +- .../Services/LocalRepositoryModelFactory.cs | 2 +- .../Commands/LinkCommandBase.cs | 6 +-- 10 files changed, 70 insertions(+), 42 deletions(-) diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index de81803439..1c8392730b 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using GitHub.Models; using GitHub.Primitives; using GitHub.Services; using LibGit2Sharp; @@ -7,6 +8,7 @@ namespace GitHub.SampleData { class GitServiceDesigner : IGitService { + public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; public IRepository GetRepository(string path) => null; diff --git a/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs index 99f05b86f9..816e814b10 100644 --- a/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs @@ -15,15 +15,21 @@ public class PullRequestCreationViewModelDesigner : PanePageViewModelBase, IPull { public PullRequestCreationViewModelDesigner() { + var repositoryModel = new LocalRepositoryModel + { + Name = "repo", + CloneUrl = "http://github.com/user/repo" + }; + Branches = new List { - new BranchModel("master", new LocalRepositoryModel("http://github.com/user/repo", new GitServiceDesigner())), - new BranchModel("don/stub-ui", new LocalRepositoryModel("http://github.com/user/repo", new GitServiceDesigner())), - new BranchModel("feature/pr/views", new LocalRepositoryModel("http://github.com/user/repo", new GitServiceDesigner())), - new BranchModel("release-1.0.17.0", new LocalRepositoryModel("http://github.com/user/repo", new GitServiceDesigner())), + new BranchModel("master", repositoryModel), + new BranchModel("don/stub-ui", repositoryModel), + new BranchModel("feature/pr/views", repositoryModel), + new BranchModel("release-1.0.17.0", repositoryModel), }.AsReadOnly(); - TargetBranch = new BranchModel("master", new LocalRepositoryModel("http://github.com/user/repo", new GitServiceDesigner())); + TargetBranch = new BranchModel("master", repositoryModel); SourceBranch = Branches[2]; SelectedAssignee = "Haacked (Phil Haack)"; diff --git a/src/GitHub.Exports/Models/BranchModel.cs b/src/GitHub.Exports/Models/BranchModel.cs index 9a02091871..b61bc61853 100644 --- a/src/GitHub.Exports/Models/BranchModel.cs +++ b/src/GitHub.Exports/Models/BranchModel.cs @@ -32,7 +32,8 @@ public BranchModel(LibGit2Sharp.Branch branch, IRepositoryModel repo, IGitServic Extensions.Guard.ArgumentNotNull(repo, nameof(repo)); Name = DisplayName = branch.FriendlyName; #pragma warning disable 0618 // TODO: Replace `Branch.Remote` with `Repository.Network.Remotes[branch.RemoteName]`. - Repository = branch.IsRemote ? new LocalRepositoryModel(branch.Remote.Url, gitService) : repo; + // NOTE: This method expects a localPath not a URL! + Repository = branch.IsRemote ? gitService.CreateLocalRepositoryModel(branch.Remote.Url) : repo; #pragma warning restore 0618 IsTracking = branch.IsTracking; Sha = branch.Tip?.Sha; diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index a1e26fe939..ebfedecadd 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -20,6 +20,10 @@ public class LocalRepositoryModel : RepositoryModel, ILocalRepositoryModel, IEqu { readonly IGitService gitService; + public LocalRepositoryModel() + { + } + /// /// Initializes a new instance of the class. /// @@ -38,28 +42,6 @@ public LocalRepositoryModel(string name, UriString cloneUrl, string localPath, I Icon = Octicon.repo; } - /// - /// Initializes a new instance of the class. - /// - /// The repository's local path. - /// The service used to find the repository's URL. - public LocalRepositoryModel(string localPath, IGitService gitService) - { - Guard.ArgumentNotNull(gitService, nameof(gitService)); - Guard.ArgumentNotNull(localPath, nameof(localPath)); - var dir = new DirectoryInfo(localPath); - if (!dir.Exists) - { - throw new ArgumentException("Path does not exist", nameof(localPath)); - } - - CloneUrl = gitService.GetUri(localPath); - LocalPath = localPath; - Name = CloneUrl?.RepositoryName ?? dir.Name; - this.gitService = gitService; - Icon = Octicon.repo; - } - /// /// Updates the clone URL from the local repository. /// @@ -164,7 +146,7 @@ static string GetLinkFormat(LinkType linkType) /// /// Gets the local path of the repository. /// - public string LocalPath { get; } + public string LocalPath { get; set; } /// /// Gets the head SHA of the repository. diff --git a/src/GitHub.Exports/Models/RepositoryModel.cs b/src/GitHub.Exports/Models/RepositoryModel.cs index f8cfc718d6..fe3976de98 100644 --- a/src/GitHub.Exports/Models/RepositoryModel.cs +++ b/src/GitHub.Exports/Models/RepositoryModel.cs @@ -38,7 +38,7 @@ protected RepositoryModel() /// /// Gets the name of the repository. /// - public string Name { get; protected set; } + public string Name { get; set; } /// /// Gets the repository clone URL. @@ -46,7 +46,7 @@ protected RepositoryModel() public UriString CloneUrl { get { return cloneUrl; } - protected set + set { if (cloneUrl != value) { @@ -67,7 +67,7 @@ protected set public Octicon Icon { get { return icon; } - protected set + set { if (icon != value) { diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index a02700f972..83e3f7a489 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -1,11 +1,13 @@ -using System.ComponentModel.Composition; -using GitHub.Primitives; -using LibGit2Sharp; -using System; +using System; +using System.IO; +using System.Linq; using System.Threading.Tasks; +using System.ComponentModel.Composition; +using GitHub.UI; using GitHub.Models; -using System.Linq; +using GitHub.Primitives; using GitHub.Extensions; +using LibGit2Sharp; namespace GitHub.Services { @@ -21,6 +23,33 @@ public GitService(IRepositoryFacade repositoryFacade) this.repositoryFacade = repositoryFacade; } + /// + /// Initializes a new instance of the class. + /// + /// The repository's local path. + public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) + { + Guard.ArgumentNotNull(localPath, nameof(localPath)); + + var dir = new DirectoryInfo(localPath); + if (!dir.Exists) + { + throw new ArgumentException("Path does not exist", nameof(localPath)); + } + + var cloneUrl = GetUri(localPath); + var name = cloneUrl?.RepositoryName ?? dir.Name; + var icon = Octicon.repo; + + return new LocalRepositoryModel + { + LocalPath = localPath, + CloneUrl = cloneUrl, + Name = name, + Icon = icon + }; + } + /// /// Returns the URL of the remote for the specified . If the repository /// is null or no remote named origin exists, this method returns null diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 91453ad792..40002f939f 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -7,6 +7,13 @@ namespace GitHub.Services { public interface IGitService { + /// + /// Initializes a new instance of the class. + /// + /// The repository's local path. + /// A repository model. + ILocalRepositoryModel CreateLocalRepositoryModel(string localPath); + /// /// Returns the URL of the remote for the specified . If the repository /// is null or no remote exists, this method returns null diff --git a/src/GitHub.TeamFoundation.14/RegistryHelper.cs b/src/GitHub.TeamFoundation.14/RegistryHelper.cs index f4fa44eb31..dafba2e15f 100644 --- a/src/GitHub.TeamFoundation.14/RegistryHelper.cs +++ b/src/GitHub.TeamFoundation.14/RegistryHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.Composition; using System.Diagnostics; using System.Globalization; using System.IO; @@ -40,7 +41,7 @@ internal static IEnumerable PokeTheRegistryForRepositoryL { var path = subkey?.GetValue("Path") as string; if (path != null && Directory.Exists(path)) - return new LocalRepositoryModel(path, GitService.GitServiceHelper); + return GitService.GitServiceHelper.CreateLocalRepositoryModel(path); } catch (Exception) { diff --git a/src/GitHub.TeamFoundation.14/Services/LocalRepositoryModelFactory.cs b/src/GitHub.TeamFoundation.14/Services/LocalRepositoryModelFactory.cs index f6d7dc4a54..06c4bc9572 100644 --- a/src/GitHub.TeamFoundation.14/Services/LocalRepositoryModelFactory.cs +++ b/src/GitHub.TeamFoundation.14/Services/LocalRepositoryModelFactory.cs @@ -7,7 +7,7 @@ class LocalRepositoryModelFactory : ILocalRepositoryModelFactory { public ILocalRepositoryModel Create(string localPath) { - return new LocalRepositoryModel(localPath, GitService.GitServiceHelper); + return GitService.GitServiceHelper.CreateLocalRepositoryModel(localPath); } } } diff --git a/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs b/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs index 7326e306b8..ddc442541c 100644 --- a/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs +++ b/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs @@ -46,7 +46,7 @@ protected ILocalRepositoryModel GetRepositoryByPath(string path) if (!string.IsNullOrEmpty(path)) { var repo = ServiceProvider.TryGetService().GetRepository(path); - return new LocalRepositoryModel(repo.Info.WorkingDirectory.TrimEnd('\\'), GitService.GitServiceHelper); + return GitService.GitServiceHelper.CreateLocalRepositoryModel(repo.Info.WorkingDirectory.TrimEnd('\\')); } } catch (Exception ex) @@ -66,7 +66,7 @@ protected ILocalRepositoryModel GetActiveRepo() var path = ServiceProvider.TryGetService()?.GetActiveRepoPath() ?? String.Empty; try { - activeRepo = !string.IsNullOrEmpty(path) ? new LocalRepositoryModel(path, GitService.GitServiceHelper) : null; + activeRepo = !string.IsNullOrEmpty(path) ? GitService.GitServiceHelper.CreateLocalRepositoryModel(path) : null; } catch (Exception ex) { @@ -86,7 +86,7 @@ void RefreshRepo() string path = vsGitServices?.GetActiveRepoPath() ?? String.Empty; try { - ActiveRepo = !String.IsNullOrEmpty(path) ? new LocalRepositoryModel(path, GitService.GitServiceHelper) : null; + ActiveRepo = !String.IsNullOrEmpty(path) ? GitService.GitServiceHelper.CreateLocalRepositoryModel(path) : null; } catch (Exception ex) { From c6c8b849816a296aef900f548edce3ea1ba6ec5d Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 11:56:31 +0100 Subject: [PATCH 03/39] Move LocalRepositoryModel ctor into GitService 2/2 --- .../SampleData/GitServiceDesigner.cs | 1 + .../Models/LocalRepositoryModel.cs | 18 --------------- src/GitHub.Exports/Services/GitService.cs | 23 +++++++++++++++++++ src/GitHub.Exports/Services/IGitService.cs | 9 ++++++++ 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index 1c8392730b..b2f10226d2 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -9,6 +9,7 @@ namespace GitHub.SampleData class GitServiceDesigner : IGitService { public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; + public ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString cloneUrl, string localPath) => null; public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; public IRepository GetRepository(string path) => null; diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index ebfedecadd..7b05f77463 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -24,24 +24,6 @@ public LocalRepositoryModel() { } - /// - /// Initializes a new instance of the class. - /// - /// The repository name. - /// The repository's clone URL. - /// The repository's local path. - /// The service used to refresh the repository's URL. - public LocalRepositoryModel(string name, UriString cloneUrl, string localPath, IGitService gitService) - : base(name, cloneUrl) - { - Guard.ArgumentNotEmptyString(localPath, nameof(localPath)); - Guard.ArgumentNotNull(gitService, nameof(gitService)); - - this.gitService = gitService; - LocalPath = localPath; - Icon = Octicon.repo; - } - /// /// Updates the clone URL from the local repository. /// diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 83e3f7a489..3c19afd813 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -27,6 +27,7 @@ public GitService(IRepositoryFacade repositoryFacade) /// Initializes a new instance of the class. /// /// The repository's local path. + /// A repository model. public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) { Guard.ArgumentNotNull(localPath, nameof(localPath)); @@ -50,6 +51,28 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) }; } + /// + /// Initializes a new instance of the class. + /// + /// The repository name. + /// The repository's clone URL. + /// The repository's local path. + /// A repository model. + public ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString cloneUrl, string localPath) + { + Guard.ArgumentNotEmptyString(name, nameof(name)); + Guard.ArgumentNotNull(cloneUrl, nameof(cloneUrl)); + Guard.ArgumentNotEmptyString(localPath, nameof(localPath)); + + return new LocalRepositoryModel + { + LocalPath = localPath, + CloneUrl = cloneUrl, + Name = name, + Icon = Octicon.repo + }; + } + /// /// Returns the URL of the remote for the specified . If the repository /// is null or no remote named origin exists, this method returns null diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 40002f939f..9dd4348edb 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -14,6 +14,15 @@ public interface IGitService /// A repository model. ILocalRepositoryModel CreateLocalRepositoryModel(string localPath); + /// + /// Initializes a new instance of the class. + /// + /// The repository name. + /// The repository's clone URL. + /// The repository's local path. + /// A repository model. + ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString cloneUrl, string localPath); + /// /// Returns the URL of the remote for the specified . If the repository /// is null or no remote exists, this method returns null From edb823260e1621a4eee70c6d098a6efc4ecc7983 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 12:31:43 +0100 Subject: [PATCH 04/39] Fix tests after LocalRepositoryModel refactor --- .../Models/RepositoryModelTests.cs | 12 ++++++------ .../Services/PullRequestServiceTests.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/GitHub.App.UnitTests/Models/RepositoryModelTests.cs b/test/GitHub.App.UnitTests/Models/RepositoryModelTests.cs index fc048b5c95..ef3219bdbb 100644 --- a/test/GitHub.App.UnitTests/Models/RepositoryModelTests.cs +++ b/test/GitHub.App.UnitTests/Models/RepositoryModelTests.cs @@ -20,8 +20,8 @@ public class ComparisonTests : TestBaseClass public void SameContentEqualsTrue(string name1, string url1, string path1, string name2, string url2, string path2) { var gitService = Substitute.For(); - var a = new LocalRepositoryModel(name1, new UriString(url1), path1, gitService); - var b = new LocalRepositoryModel(name2, new UriString(url2), path2, gitService); + var a = new LocalRepositoryModel { Name = name1, CloneUrl = url1, LocalPath = path1 }; + var b = new LocalRepositoryModel { Name = name2, CloneUrl = url2, LocalPath = path2 }; Assert.That(a, Is.EqualTo(b)); Assert.False(a == b); Assert.That(a.GetHashCode(), Is.EqualTo(b.GetHashCode())); @@ -58,11 +58,11 @@ public void NoRemoteUrl() { using (var temp = new TempDirectory()) { - var gitService = Substitute.For(); + var gitService = new GitService(new RepositoryFacade()); var repo = Substitute.For(); var path = temp.Directory.CreateSubdirectory("repo-name"); gitService.GetUri(path.FullName).Returns((UriString)null); - var model = new LocalRepositoryModel(path.FullName, gitService); + var model = gitService.CreateLocalRepositoryModel(path.FullName); Assert.That("repo-name", Is.EqualTo(model.Name)); } } @@ -72,11 +72,11 @@ public void WithRemoteUrl() { using (var temp = new TempDirectory()) { - var gitService = Substitute.For(); + var gitService = new GitService(new RepositoryFacade()); var repo = Substitute.For(); var path = temp.Directory.CreateSubdirectory("repo-name"); gitService.GetUri(path.FullName).Returns(new UriString("https://github.com/user/repo-name")); - var model = new LocalRepositoryModel(path.FullName, gitService); + var model = gitService.CreateLocalRepositoryModel(path.FullName); Assert.That("repo-name", Is.EqualTo(model.Name)); Assert.That("user", Is.EqualTo(model.Owner)); } diff --git a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs index c8e437cb8d..2ede44920b 100644 --- a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs +++ b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs @@ -701,10 +701,10 @@ public void CreatePullRequestAllArgsMandatory() ms = Substitute.For(); Assert.Throws(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body)); - sourceRepo = new LocalRepositoryModel("name", new GitHub.Primitives.UriString("http://github.com/github/stuff"), "c:\\path", gitService); + sourceRepo = new LocalRepositoryModel { Name = "name", CloneUrl = "http://github.com/github/stuff", LocalPath = "c:\\path" }; Assert.Throws(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body)); - targetRepo = new LocalRepositoryModel("name", new GitHub.Primitives.UriString("http://github.com/github/stuff"), "c:\\path", gitService); + targetRepo = new LocalRepositoryModel { Name = "name", CloneUrl = "http://github.com/github/stuff", LocalPath = "c:\\path" }; Assert.Throws(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body)); title = "a title"; From 835e5617396a290777ed09d7a021d9690db98d64 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 14:39:45 +0100 Subject: [PATCH 05/39] Move GenerateUrl to LinkCommandBase Move GenerateUrl from LocalRepositoryModel to LinkCommandBase. --- .../Models/ILocalRepositoryModel.cs | 11 -- .../Models/LocalRepositoryModel.cs | 91 ---------------- .../Commands/BlameLinkCommand.cs | 4 +- .../Commands/CopyLinkCommand.cs | 4 +- .../Commands/LinkCommandBase.cs | 100 +++++++++++++++++- .../Commands/OpenLinkCommand.cs | 4 +- .../Commands/LinkCommandBaseTests.cs} | 33 ++---- 7 files changed, 113 insertions(+), 134 deletions(-) rename test/{GitHub.Exports.UnitTests/LocalRepositoryModelTests.cs => GitHub.VisualStudio.UnitTests/Commands/LinkCommandBaseTests.cs} (81%) diff --git a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs index 1295599b6a..f3fa4afcd3 100644 --- a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs @@ -24,16 +24,5 @@ public interface ILocalRepositoryModel : IRepositoryModel, INotifyPropertyChange /// Updates the url information based on the local path /// void Refresh(); - - /// - /// Generates a http(s) url to the repository in the remote server, optionally - /// pointing to a specific file and specific line range in it. - /// - /// The type of repository link to create - /// The file to generate an url to. Optional. - /// A specific line, or (if specifying the as well) the start of a range - /// The end of a line range on the specified file. - /// An UriString with the generated url, or null if the repository has no remote server configured or if it can't be found locally - Task GenerateUrl(LinkType linkType, string path = null, int startLine = -1, int endLine = -1); } } diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index 7b05f77463..6e3d34e7ee 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -34,97 +34,6 @@ public void Refresh() CloneUrl = gitService.GetUri(LocalPath); } - /// - /// Generates a http(s) url to the repository in the remote server, optionally - /// pointing to a specific file and specific line range in it. - /// - /// Type of link to generate - /// The file to generate an url to. Optional. - /// A specific line, or (if specifying the as well) the start of a range - /// The end of a line range on the specified file. - /// An UriString with the generated url, or null if the repository has no remote server configured or if it can't be found locally - public async Task GenerateUrl(LinkType linkType, string path = null, int startLine = -1, int endLine = -1) - { - if (CloneUrl == null) - return null; - - var sha = await gitService.GetLatestPushedSha(path ?? LocalPath); - // this also incidentally checks whether the repo has a valid LocalPath - if (String.IsNullOrEmpty(sha)) - return CloneUrl.ToRepositoryUrl().AbsoluteUri; - - if (path != null && Path.IsPathRooted(path)) - { - // if the path root doesn't match the repository local path, then ignore it - if (!path.StartsWith(LocalPath, StringComparison.OrdinalIgnoreCase)) - { - Debug.Assert(false, String.Format(CultureInfo.CurrentCulture, "GenerateUrl: path {0} doesn't match repository {1}", path, LocalPath)); - path = null; - } - else - path = path.Substring(LocalPath.Length + 1); - } - - if (startLine > 0 && endLine > 0 && startLine > endLine) - { - // if startLine is greater than endLine and both are set, swap them - var temp = startLine; - startLine = endLine; - endLine = temp; - } - - if (startLine == endLine) - { - // if startLine is the same as endLine don't generate a range link - endLine = -1; - } - - return new UriString(GenerateUrl(linkType, CloneUrl.ToRepositoryUrl().AbsoluteUri, sha, path, startLine, endLine)); - } - - const string CommitFormat = "{0}/commit/{1}"; - const string BlobFormat = "{0}/blob/{1}/{2}"; - const string BlameFormat = "{0}/blame/{1}/{2}"; - const string StartLineFormat = "{0}#L{1}"; - const string EndLineFormat = "{0}-L{1}"; - static string GenerateUrl(LinkType linkType, string basePath, string sha, string path, int startLine = -1, int endLine = -1) - { - if (sha == null) - return basePath; - - if (String.IsNullOrEmpty(path)) - return String.Format(CultureInfo.InvariantCulture, CommitFormat, basePath, sha); - - var ret = String.Format(CultureInfo.InvariantCulture, GetLinkFormat(linkType), basePath, sha, path.Replace(@"\", "/")); - - if (startLine < 0) - return ret; - ret = String.Format(CultureInfo.InvariantCulture, StartLineFormat, ret, startLine); - if (endLine < 0) - return ret; - return String.Format(CultureInfo.InvariantCulture, EndLineFormat, ret, endLine); - } - - /// - /// Selects the proper format for the link type, defaults to the blob url when link type is not selected. - /// - /// Type of link to generate - /// The string format of the selected link type - static string GetLinkFormat(LinkType linkType) - { - switch (linkType) - { - case LinkType.Blame: - return BlameFormat; - - case LinkType.Blob: - return BlobFormat; - - default: - return BlobFormat; - } - } - /// /// Gets the local path of the repository. /// diff --git a/src/GitHub.VisualStudio/Commands/BlameLinkCommand.cs b/src/GitHub.VisualStudio/Commands/BlameLinkCommand.cs index 0d55d951be..40d0352dab 100644 --- a/src/GitHub.VisualStudio/Commands/BlameLinkCommand.cs +++ b/src/GitHub.VisualStudio/Commands/BlameLinkCommand.cs @@ -15,8 +15,8 @@ namespace GitHub.VisualStudio.Commands public class BlameLinkCommand : LinkCommandBase, IBlameLinkCommand { [ImportingConstructor] - protected BlameLinkCommand(IGitHubServiceProvider serviceProvider) - : base(CommandSet, CommandId, serviceProvider) + protected BlameLinkCommand(IGitHubServiceProvider serviceProvider, Lazy gitService) + : base(CommandSet, CommandId, serviceProvider, gitService) { } diff --git a/src/GitHub.VisualStudio/Commands/CopyLinkCommand.cs b/src/GitHub.VisualStudio/Commands/CopyLinkCommand.cs index c01aedfdfc..b195d110cf 100644 --- a/src/GitHub.VisualStudio/Commands/CopyLinkCommand.cs +++ b/src/GitHub.VisualStudio/Commands/CopyLinkCommand.cs @@ -17,8 +17,8 @@ namespace GitHub.VisualStudio.Commands public class CopyLinkCommand : LinkCommandBase, ICopyLinkCommand { [ImportingConstructor] - protected CopyLinkCommand(IGitHubServiceProvider serviceProvider) - : base(CommandSet, CommandId, serviceProvider) + protected CopyLinkCommand(IGitHubServiceProvider serviceProvider, Lazy gitService) + : base(CommandSet, CommandId, serviceProvider, gitService) { } diff --git a/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs b/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs index ddc442541c..d1abe4f1d4 100644 --- a/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs +++ b/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.IO; using System.Threading.Tasks; using GitHub.Api; @@ -20,16 +21,19 @@ public abstract class LinkCommandBase : VsCommand static readonly ILogger log = LogManager.ForContext(); readonly Lazy apiFactory; readonly Lazy usageTracker; + readonly Lazy lazyGitService; protected LinkCommandBase( Guid commandSet, int commandId, - IGitHubServiceProvider serviceProvider) + IGitHubServiceProvider serviceProvider, + Lazy gitService) : base(commandSet, commandId) { ServiceProvider = serviceProvider; apiFactory = new Lazy(() => ServiceProvider.TryGetService()); usageTracker = new Lazy(() => serviceProvider.TryGetService()); + lazyGitService = gitService; } protected ILocalRepositoryModel ActiveRepo { get; private set; } @@ -134,7 +138,7 @@ protected Task GenerateLink(LinkType linkType) var repo = GetRepositoryByPath(activeDocument.Name); - return repo.GenerateUrl(linkType, activeDocument.Name, activeDocument.StartLine, activeDocument.EndLine); + return GenerateUrl(lazyGitService.Value, repo, linkType, activeDocument.Name, activeDocument.StartLine, activeDocument.EndLine); } protected override void QueryStatus() @@ -160,5 +164,97 @@ public static bool IsFileDescendantOfDirectory(string file, string directory) } return false; } + + /// + /// Generates a http(s) url to the repository in the remote server, optionally + /// pointing to a specific file and specific line range in it. + /// + /// Type of link to generate + /// The file to generate an url to. Optional. + /// A specific line, or (if specifying the as well) the start of a range + /// The end of a line range on the specified file. + /// An UriString with the generated url, or null if the repository has no remote server configured or if it can't be found locally + public static async Task GenerateUrl(IGitService gitService, + ILocalRepositoryModel repo, LinkType linkType, string path = null, int startLine = -1, int endLine = -1) + { + if (repo.CloneUrl == null) + return null; + + var sha = await gitService.GetLatestPushedSha(path ?? repo.LocalPath); + // this also incidentally checks whether the repo has a valid LocalPath + if (String.IsNullOrEmpty(sha)) + return repo.CloneUrl.ToRepositoryUrl().AbsoluteUri; + + if (path != null && Path.IsPathRooted(path)) + { + // if the path root doesn't match the repository local path, then ignore it + if (!path.StartsWith(repo.LocalPath, StringComparison.OrdinalIgnoreCase)) + { + System.Diagnostics.Debug.Assert(false, String.Format(CultureInfo.CurrentCulture, "GenerateUrl: path {0} doesn't match repository {1}", path, repo.LocalPath)); + path = null; + } + else + path = path.Substring(repo.LocalPath.Length + 1); + } + + if (startLine > 0 && endLine > 0 && startLine > endLine) + { + // if startLine is greater than endLine and both are set, swap them + var temp = startLine; + startLine = endLine; + endLine = temp; + } + + if (startLine == endLine) + { + // if startLine is the same as endLine don't generate a range link + endLine = -1; + } + + return new UriString(GenerateUrl(linkType, repo.CloneUrl.ToRepositoryUrl().AbsoluteUri, sha, path, startLine, endLine)); + } + + const string CommitFormat = "{0}/commit/{1}"; + const string BlobFormat = "{0}/blob/{1}/{2}"; + const string BlameFormat = "{0}/blame/{1}/{2}"; + const string StartLineFormat = "{0}#L{1}"; + const string EndLineFormat = "{0}-L{1}"; + static string GenerateUrl(LinkType linkType, string basePath, string sha, string path, int startLine = -1, int endLine = -1) + { + if (sha == null) + return basePath; + + if (String.IsNullOrEmpty(path)) + return String.Format(CultureInfo.InvariantCulture, CommitFormat, basePath, sha); + + var ret = String.Format(CultureInfo.InvariantCulture, GetLinkFormat(linkType), basePath, sha, path.Replace(@"\", "/")); + + if (startLine < 0) + return ret; + ret = String.Format(CultureInfo.InvariantCulture, StartLineFormat, ret, startLine); + if (endLine < 0) + return ret; + return String.Format(CultureInfo.InvariantCulture, EndLineFormat, ret, endLine); + } + + /// + /// Selects the proper format for the link type, defaults to the blob url when link type is not selected. + /// + /// Type of link to generate + /// The string format of the selected link type + static string GetLinkFormat(LinkType linkType) + { + switch (linkType) + { + case LinkType.Blame: + return BlameFormat; + + case LinkType.Blob: + return BlobFormat; + + default: + return BlobFormat; + } + } } } diff --git a/src/GitHub.VisualStudio/Commands/OpenLinkCommand.cs b/src/GitHub.VisualStudio/Commands/OpenLinkCommand.cs index 5d5ddc7142..3c00747ca2 100644 --- a/src/GitHub.VisualStudio/Commands/OpenLinkCommand.cs +++ b/src/GitHub.VisualStudio/Commands/OpenLinkCommand.cs @@ -14,8 +14,8 @@ namespace GitHub.VisualStudio.Commands public class OpenLinkCommand : LinkCommandBase, IOpenLinkCommand { [ImportingConstructor] - protected OpenLinkCommand(IGitHubServiceProvider serviceProvider) - : base(CommandSet, CommandId, serviceProvider) + protected OpenLinkCommand(IGitHubServiceProvider serviceProvider, Lazy gitService) + : base(CommandSet, CommandId, serviceProvider, gitService) { } diff --git a/test/GitHub.Exports.UnitTests/LocalRepositoryModelTests.cs b/test/GitHub.VisualStudio.UnitTests/Commands/LinkCommandBaseTests.cs similarity index 81% rename from test/GitHub.Exports.UnitTests/LocalRepositoryModelTests.cs rename to test/GitHub.VisualStudio.UnitTests/Commands/LinkCommandBaseTests.cs index cb2c163b61..8be88301a7 100644 --- a/test/GitHub.Exports.UnitTests/LocalRepositoryModelTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Commands/LinkCommandBaseTests.cs @@ -1,14 +1,13 @@ -using System.Threading.Tasks; -using System.Collections.Generic; +using System; +using System.Threading.Tasks; using GitHub.Models; using GitHub.Exports; using GitHub.Services; -using GitHub.Primitives; +using GitHub.VisualStudio.Commands; using NSubstitute; -using LibGit2Sharp; using NUnit.Framework; -public class LocalRepositoryModelTests : TestBaseClass +public class LinkCommandBaseTests : TestBaseClass { [TestCase(1, LinkType.Blob, false, "https://github.com/foo/bar", "123123", @"src\dir\file1.cs", -1, -1, "https://github.com/foo/bar/blob/123123/src/dir/file1.cs")] [TestCase(2, LinkType.Blob, false, "https://github.com/foo/bar", "123123", @"src\dir\file1.cs", 1, -1, "https://github.com/foo/bar/blob/123123/src/dir/file1.cs#L1")] @@ -48,32 +47,18 @@ public async Task GenerateUrl(int testid, LinkType linkType, bool createRootedPa if (createRootedPath && path != null) path = System.IO.Path.Combine(basePath.FullName, path); ILocalRepositoryModel model = null; - if (!string.IsNullOrEmpty(baseUrl)) - model = new LocalRepositoryModel("bar", new UriString(baseUrl), basePath.FullName, gitService); - else - model = new LocalRepositoryModel(basePath.FullName, gitService); - var result = await model.GenerateUrl(linkType, path, startLine, endLine); - Assert.That(expected, Is.EqualTo(result?.ToString())); + model = new LocalRepositoryModel { Name = "bar", CloneUrl = baseUrl, LocalPath = basePath.FullName }; + + var result = await LinkCommandBase.GenerateUrl(gitService, model, linkType, path, startLine, endLine); + + Assert.That(result?.ToString(), Is.EqualTo(expected)); } } static IGitService CreateGitService(string sha) { var gitservice = Substitute.For(); - var repo = Substitute.For(); - gitservice.GetRepository(Args.String).Returns(repo); gitservice.GetLatestPushedSha(Args.String).Returns(Task.FromResult(sha)); - if (!string.IsNullOrEmpty(sha)) - { - var refs = Substitute.For(); - var refrence = Substitute.For(); - refs.ReachableFrom(Arg.Any>(), Arg.Any>()).Returns(new Reference[] { refrence }); - repo.Refs.Returns(refs); - var commit = Substitute.For(); - commit.Sha.Returns(sha); - repo.Commits.Returns(new FakeCommitLog { commit }); - } - return gitservice; } } From fe2dcf861a71d41ab75a139b2d8a20625173c6b3 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 15:12:07 +0100 Subject: [PATCH 06/39] Convert LocalRepositoryModel to GitService tests Move LocalRepositoryModel construction tests to new home. --- .../Models/RepositoryModelTests.cs | 33 ------------- .../GitServiceTests.cs | 49 +++++++++++++++++-- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/test/GitHub.App.UnitTests/Models/RepositoryModelTests.cs b/test/GitHub.App.UnitTests/Models/RepositoryModelTests.cs index ef3219bdbb..fd2b9a574c 100644 --- a/test/GitHub.App.UnitTests/Models/RepositoryModelTests.cs +++ b/test/GitHub.App.UnitTests/Models/RepositoryModelTests.cs @@ -50,39 +50,6 @@ public void DifferentContentEqualsFalse(long id1, string name1, string url1, lon } } - //[Collection("PackageServiceProvider global data tests")] - public class PathConstructorTests : TestBaseClass - { - [Test] - public void NoRemoteUrl() - { - using (var temp = new TempDirectory()) - { - var gitService = new GitService(new RepositoryFacade()); - var repo = Substitute.For(); - var path = temp.Directory.CreateSubdirectory("repo-name"); - gitService.GetUri(path.FullName).Returns((UriString)null); - var model = gitService.CreateLocalRepositoryModel(path.FullName); - Assert.That("repo-name", Is.EqualTo(model.Name)); - } - } - - [Test] - public void WithRemoteUrl() - { - using (var temp = new TempDirectory()) - { - var gitService = new GitService(new RepositoryFacade()); - var repo = Substitute.For(); - var path = temp.Directory.CreateSubdirectory("repo-name"); - gitService.GetUri(path.FullName).Returns(new UriString("https://github.com/user/repo-name")); - var model = gitService.CreateLocalRepositoryModel(path.FullName); - Assert.That("repo-name", Is.EqualTo(model.Name)); - Assert.That("user", Is.EqualTo(model.Owner)); - } - } - } - public class HostAddressTests : TestBaseClass { [TestCase("https://github.com/owner/repo")] diff --git a/test/GitHub.Exports.UnitTests/GitServiceTests.cs b/test/GitHub.Exports.UnitTests/GitServiceTests.cs index 1b2ac321ba..c98db18f97 100644 --- a/test/GitHub.Exports.UnitTests/GitServiceTests.cs +++ b/test/GitHub.Exports.UnitTests/GitServiceTests.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading.Tasks; using GitHub.Services; using LibGit2Sharp; @@ -10,6 +8,41 @@ public class GitServiceTests { + public class CreateLocalRepositoryModelTests : TestBaseClass + { + [Test] + public void NoRemoteUrl() + { + using (var temp = new TempDirectory()) + { + var repositoryFacade = Substitute.For(); + var gitService = new GitService(repositoryFacade); + var path = temp.Directory.CreateSubdirectory("repo-name"); + + var model = gitService.CreateLocalRepositoryModel(path.FullName); + + Assert.That(model.Name, Is.EqualTo("repo-name")); + } + } + + [Test] + public void WithRemoteUrl() + { + using (var temp = new TempDirectory()) + { + var path = temp.Directory.CreateSubdirectory("repo-name"); + var repository = CreateRepositoryWithOrigin("https://github.com/user/repo-name"); + var repositoryFacade = CreateRepositoryFacade(path.FullName, repository); + var gitService = new GitService(repositoryFacade); + + var model = gitService.CreateLocalRepositoryModel(path.FullName); + + Assert.That(model.Name, Is.EqualTo("repo-name")); + Assert.That(model.Owner, Is.EqualTo("user")); + } + } + } + [TestCase("asdf", null)] [TestCase("", null)] [TestCase(null, null)] @@ -47,12 +80,20 @@ static IRepositoryFacade CreateRepositoryFacade(string path, IRepository repo) return repositoryFacade; } - static IRepository CreateRepository() + static IRepository CreateRepositoryWithOrigin(string originUrl) { - var repo = Substitute.For(); + var repo = CreateRepository(); + var origin = Substitute.For(); + origin.Url.Returns(originUrl); + repo.Network.Remotes["origin"].Returns(origin); return repo; } + static IRepository CreateRepository() + { + return Substitute.For(); + } + public class TheGetLatestPushedShaMethod : TestBaseClass { [Test] From 683ad50db91a8bc7e3a7d110311c26c24cd8a9e3 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 15:43:50 +0100 Subject: [PATCH 07/39] Move LocalReposotoryModel.Refresh to GitService --- .../SampleData/GitServiceDesigner.cs | 1 + .../Models/ILocalRepositoryModel.cs | 10 +------ src/GitHub.Exports/Models/IRepositoryModel.cs | 2 +- .../Models/LocalRepositoryModel.cs | 10 ------- src/GitHub.Exports/Services/GitService.cs | 12 ++++++++ src/GitHub.Exports/Services/IGitService.cs | 6 ++++ .../Base/TeamExplorerServiceHolder.cs | 30 ++++++++++++------- 7 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index b2f10226d2..95bd0bc276 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -10,6 +10,7 @@ class GitServiceDesigner : IGitService { public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; public ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString cloneUrl, string localPath) => null; + public void Refresh(ILocalRepositoryModel localRepositoryModel) { } public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; public IRepository GetRepository(string path) => null; diff --git a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs index f3fa4afcd3..154e5a69cc 100644 --- a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs @@ -1,7 +1,4 @@ -using GitHub.Exports; -using GitHub.Primitives; -using System.ComponentModel; -using System.Threading.Tasks; +using System.ComponentModel; namespace GitHub.Models { @@ -19,10 +16,5 @@ public interface ILocalRepositoryModel : IRepositoryModel, INotifyPropertyChange /// Gets the current branch. /// IBranch CurrentBranch { get; } - - /// - /// Updates the url information based on the local path - /// - void Refresh(); } } diff --git a/src/GitHub.Exports/Models/IRepositoryModel.cs b/src/GitHub.Exports/Models/IRepositoryModel.cs index c3c1d577ae..084bf96fe4 100644 --- a/src/GitHub.Exports/Models/IRepositoryModel.cs +++ b/src/GitHub.Exports/Models/IRepositoryModel.cs @@ -17,7 +17,7 @@ public interface IRepositoryModel /// /// Gets the repository clone URL. /// - UriString CloneUrl { get; } + UriString CloneUrl { get; set; } /// /// Gets the name of the owner of the repository, taken from the clone URL. diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index 6e3d34e7ee..8b1a8d6346 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -24,16 +24,6 @@ public LocalRepositoryModel() { } - /// - /// Updates the clone URL from the local repository. - /// - public void Refresh() - { - if (LocalPath == null) - return; - CloneUrl = gitService.GetUri(LocalPath); - } - /// /// Gets the local path of the repository. /// diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 3c19afd813..dc6fe04157 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -73,6 +73,18 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString c }; } + /// + /// Updates the CloneUrl from the local repository. + /// + public void Refresh(ILocalRepositoryModel localRepositoryModel) + { + var localPath = localRepositoryModel.LocalPath; + if (localPath == null) + return; + + localRepositoryModel.CloneUrl = GetUri(localPath); + } + /// /// Returns the URL of the remote for the specified . If the repository /// is null or no remote named origin exists, this method returns null diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 9dd4348edb..766d2658cb 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -23,6 +23,12 @@ public interface IGitService /// A repository model. ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString cloneUrl, string localPath); + /// + /// Updates the ClonePath information based on the local path + /// + /// The repository model to refresh. + void Refresh(ILocalRepositoryModel localRepositoryModel); + /// /// Returns the URL of the remote for the specified . If the repository /// is null or no remote exists, this method returns null diff --git a/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs b/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs index 20879c8fbe..db91cfbe9b 100644 --- a/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs +++ b/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs @@ -25,14 +25,15 @@ public class TeamExplorerServiceHolder : ITeamExplorerServiceHolder bool activeRepoNotified = false; IServiceProvider serviceProvider; - readonly IVSGitExt gitService; + readonly IVSGitExt gitExt; + readonly IGitService gitService; /// /// This class relies on IVSGitExt that provides information when VS switches repositories. /// - /// Used for monitoring the active repository. + /// Used for monitoring the active repository. [ImportingConstructor] - TeamExplorerServiceHolder(IVSGitExt gitService) : this(gitService, ThreadHelper.JoinableTaskContext) + TeamExplorerServiceHolder(IVSGitExt gitExt, IGitService gitService) : this(gitExt, gitService, ThreadHelper.JoinableTaskContext) { } @@ -41,19 +42,23 @@ public class TeamExplorerServiceHolder : ITeamExplorerServiceHolder /// /// Used for monitoring the active repository. /// Used for switching to the Main thread. - public TeamExplorerServiceHolder(IVSGitExt gitService, JoinableTaskContext joinableTaskContext) + public TeamExplorerServiceHolder(IVSGitExt gitExt, IGitService gitService, JoinableTaskContext joinableTaskContext) { JoinableTaskCollection = joinableTaskContext.CreateCollection(); JoinableTaskCollection.DisplayName = nameof(TeamExplorerServiceHolder); JoinableTaskFactory = joinableTaskContext.CreateFactory(JoinableTaskCollection); - // This might be null in Blend or SafeMode - if (gitService != null) + // HACK: This might be null in SafeMode. + // We should be throwing rather than returning a null MEF service. + if (gitExt == null) { - this.gitService = gitService; - UpdateActiveRepo(); - gitService.ActiveRepositoriesChanged += UpdateActiveRepo; + return; } + + this.gitExt = gitExt; + this.gitService = gitService; + UpdateActiveRepo(); + gitExt.ActiveRepositoriesChanged += UpdateActiveRepo; } // set by the sections when they get initialized @@ -106,7 +111,10 @@ public void Subscribe(object who, Action handler) // the repo url might have changed and we don't get notifications // for that, so this is a good place to refresh it in case that happened - repo?.Refresh(); + if (repo != null) + { + gitService.Refresh(repo); + } // if the active repo hasn't changed and there's notifications queued up, // notify the subscriber. If the repo has changed, the set above will trigger @@ -152,7 +160,7 @@ void NotifyActiveRepo() void UpdateActiveRepo() { - var repo = gitService.ActiveRepositories.FirstOrDefault(); + var repo = gitExt.ActiveRepositories.FirstOrDefault(); if (!Equals(repo, ActiveRepo)) { From 59e5652f41b3b92ed50c3a3664094bc86f50fe00 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 15:50:37 +0100 Subject: [PATCH 08/39] Remove LocalRepositoryModel.HeadSha property This property wasn't being used. --- src/GitHub.Exports/Models/LocalRepositoryModel.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index 8b1a8d6346..4f8ecde94e 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -29,20 +29,6 @@ public LocalRepositoryModel() /// public string LocalPath { get; set; } - /// - /// Gets the head SHA of the repository. - /// - public string HeadSha - { - get - { - using (var repo = gitService.GetRepository(LocalPath)) - { - return repo?.Commits.FirstOrDefault()?.Sha ?? string.Empty; - } - } - } - /// /// Gets the current branch of the repository. /// From 01d2e46c5535273e85bbf9062343275f8b19447d Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 18:08:50 +0100 Subject: [PATCH 09/39] Remove CreateLocalRepositoryModel overload We Now only need the CreateLocalRepositoryModel(localPath) overload. --- src/GitHub.Exports/Services/GitService.cs | 27 +++------------------- src/GitHub.Exports/Services/IGitService.cs | 9 -------- 2 files changed, 3 insertions(+), 33 deletions(-) diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index dc6fe04157..48ad2b3a3d 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -40,37 +40,16 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) var cloneUrl = GetUri(localPath); var name = cloneUrl?.RepositoryName ?? dir.Name; - var icon = Octicon.repo; - return new LocalRepositoryModel - { - LocalPath = localPath, - CloneUrl = cloneUrl, - Name = name, - Icon = icon - }; - } - - /// - /// Initializes a new instance of the class. - /// - /// The repository name. - /// The repository's clone URL. - /// The repository's local path. - /// A repository model. - public ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString cloneUrl, string localPath) - { - Guard.ArgumentNotEmptyString(name, nameof(name)); - Guard.ArgumentNotNull(cloneUrl, nameof(cloneUrl)); - Guard.ArgumentNotEmptyString(localPath, nameof(localPath)); - - return new LocalRepositoryModel + var model = new LocalRepositoryModel { LocalPath = localPath, CloneUrl = cloneUrl, Name = name, Icon = Octicon.repo }; + + return model; } /// diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 766d2658cb..512d338b7a 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -14,15 +14,6 @@ public interface IGitService /// A repository model. ILocalRepositoryModel CreateLocalRepositoryModel(string localPath); - /// - /// Initializes a new instance of the class. - /// - /// The repository name. - /// The repository's clone URL. - /// The repository's local path. - /// A repository model. - ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString cloneUrl, string localPath); - /// /// Updates the ClonePath information based on the local path /// From 7bab4780b69807936c8385fe8b9338d85b9d0dc0 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 18:13:22 +0100 Subject: [PATCH 10/39] Read the current branch when model is created Previously the current branch was being read when CurrentBranch was fetched. This changes it to be read when the LocalRepositoryModel is created. --- .../Models/LocalRepositoryModel.cs | 9 +-------- src/GitHub.Exports/Services/GitService.cs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index 4f8ecde94e..024f7f2077 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -34,14 +34,7 @@ public LocalRepositoryModel() /// public IBranch CurrentBranch { - get - { - // BranchModel doesn't keep a reference to Repository - using (var repo = gitService.GetRepository(LocalPath)) - { - return new BranchModel(repo?.Head, this, gitService); - } - } + get; set; } /// diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 48ad2b3a3d..bdac72e308 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -49,6 +49,8 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) Icon = Octicon.repo }; + RefreshCurrentBranch(model); + return model; } @@ -196,5 +198,19 @@ public Task GetLatestPushedSha(string path, string remote = "origin") } }); } + + void RefreshCurrentBranch(LocalRepositoryModel model) + { + var localPath = model.LocalPath; + using (var repo = GetRepository(localPath)) + { + var headBranch = repo?.Head; + if (headBranch != null) + { + // BranchModel doesn't keep a reference to Repository + model.CurrentBranch = new BranchModel(headBranch, model, this); + } + } + } } } \ No newline at end of file From e3f811400f73aa722664c388253b76b24cf079c9 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 23 Oct 2018 18:20:53 +0100 Subject: [PATCH 11/39] Clean up LocalRepositoryModel Remove redundant code and usings. --- .../Models/LocalRepositoryModel.cs | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index 024f7f2077..7feae3e151 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -1,14 +1,6 @@ using System; using System.Diagnostics; using System.Globalization; -using System.IO; -using System.Linq; -using GitHub.Primitives; -using GitHub.UI; -using GitHub.Exports; -using GitHub.Services; -using GitHub.Extensions; -using System.Threading.Tasks; namespace GitHub.Models { @@ -18,16 +10,13 @@ namespace GitHub.Models [DebuggerDisplay("{DebuggerDisplay,nq}")] public class LocalRepositoryModel : RepositoryModel, ILocalRepositoryModel, IEquatable { - readonly IGitService gitService; - - public LocalRepositoryModel() - { - } - /// /// Gets the local path of the repository. /// - public string LocalPath { get; set; } + public string LocalPath + { + get; set; + } /// /// Gets the current branch of the repository. @@ -60,13 +49,13 @@ public bool Equals(LocalRepositoryModel other) if (ReferenceEquals(this, other)) return true; return other != null && - String.Equals(Name, other.Name) && - String.Equals(Owner, other.Owner) && - String.Equals(CloneUrl, other.CloneUrl) && - String.Equals(LocalPath?.TrimEnd('\\'), other.LocalPath?.TrimEnd('\\'), StringComparison.CurrentCultureIgnoreCase); + string.Equals(Name, other.Name) && + string.Equals(Owner, other.Owner) && + string.Equals(CloneUrl, other.CloneUrl) && + string.Equals(LocalPath?.TrimEnd('\\'), other.LocalPath?.TrimEnd('\\'), StringComparison.CurrentCultureIgnoreCase); } - internal string DebuggerDisplay => String.Format( + internal string DebuggerDisplay => string.Format( CultureInfo.InvariantCulture, "{4}\tOwner: {0} Name: {1} CloneUrl: {2} LocalPath: {3}", Owner, From 2f13d621cb88b1594d4247abcaeccf3d2afbcddb Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 30 Oct 2018 13:20:44 +0000 Subject: [PATCH 12/39] ClonePath -> CloneUri --- src/GitHub.Exports/Services/IGitService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 512d338b7a..1bcd0480f3 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -15,7 +15,7 @@ public interface IGitService ILocalRepositoryModel CreateLocalRepositoryModel(string localPath); /// - /// Updates the ClonePath information based on the local path + /// Updates the CloneUrl information based on the local path. /// /// The repository model to refresh. void Refresh(ILocalRepositoryModel localRepositoryModel); From c61d0f25bb48173d8e43026a4367ed3a64e620cc Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 30 Oct 2018 13:32:24 +0000 Subject: [PATCH 13/39] Make GitService.Refresh the CurrentBranch Previously CurrentBranch was created as the property was read. We now need a way to refresh it. --- src/GitHub.Exports/Models/ILocalRepositoryModel.cs | 2 +- src/GitHub.Exports/Services/GitService.cs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs index 154e5a69cc..41c6ad508f 100644 --- a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs @@ -15,6 +15,6 @@ public interface ILocalRepositoryModel : IRepositoryModel, INotifyPropertyChange /// /// Gets the current branch. /// - IBranch CurrentBranch { get; } + IBranch CurrentBranch { get; set; } } } diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index bdac72e308..30b23849c6 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -55,7 +55,7 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) } /// - /// Updates the CloneUrl from the local repository. + /// Updates the CloneUrl and CurrentBranch from the local repository. /// public void Refresh(ILocalRepositoryModel localRepositoryModel) { @@ -64,6 +64,8 @@ public void Refresh(ILocalRepositoryModel localRepositoryModel) return; localRepositoryModel.CloneUrl = GetUri(localPath); + + RefreshCurrentBranch(localRepositoryModel); } /// @@ -199,7 +201,7 @@ public Task GetLatestPushedSha(string path, string remote = "origin") }); } - void RefreshCurrentBranch(LocalRepositoryModel model) + void RefreshCurrentBranch(ILocalRepositoryModel model) { var localPath = model.LocalPath; using (var repo = GetRepository(localPath)) From 47430fd92c1a7e17acd5dd04dc34d7628d5c6f0c Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 31 Oct 2018 09:06:08 +0000 Subject: [PATCH 14/39] Add workaround for out of date CurrentBranch issue It appears VSGitExt.ActiveRepositoriesChanged is fired before the local repository has actually changed its branch. This means we can't read the branch information immediately! --- .../ViewModels/GitHubPane/PullRequestDetailViewModel.cs | 8 +++++++- .../GitHubPane/PullRequestDetailViewModelTests.cs | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs index 32d4dbe2d7..bf7c967208 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs @@ -39,6 +39,7 @@ public sealed class PullRequestDetailViewModel : PanePageViewModelBase, IPullReq readonly ITeamExplorerContext teamExplorerContext; readonly ISyncSubmodulesCommand syncSubmodulesCommand; readonly IViewViewModelFactory viewViewModelFactory; + readonly IGitService gitService; IModelService modelService; PullRequestDetailModel model; IActorViewModel author; @@ -77,7 +78,8 @@ public PullRequestDetailViewModel( ITeamExplorerContext teamExplorerContext, IPullRequestFilesViewModel files, ISyncSubmodulesCommand syncSubmodulesCommand, - IViewViewModelFactory viewViewModelFactory) + IViewViewModelFactory viewViewModelFactory, + IGitService gitService) { Guard.ArgumentNotNull(pullRequestsService, nameof(pullRequestsService)); Guard.ArgumentNotNull(sessionManager, nameof(sessionManager)); @@ -86,6 +88,7 @@ public PullRequestDetailViewModel( Guard.ArgumentNotNull(teamExplorerContext, nameof(teamExplorerContext)); Guard.ArgumentNotNull(syncSubmodulesCommand, nameof(syncSubmodulesCommand)); Guard.ArgumentNotNull(viewViewModelFactory, nameof(viewViewModelFactory)); + Guard.ArgumentNotNull(gitService, nameof(gitService)); this.pullRequestsService = pullRequestsService; this.sessionManager = sessionManager; @@ -94,6 +97,7 @@ public PullRequestDetailViewModel( this.teamExplorerContext = teamExplorerContext; this.syncSubmodulesCommand = syncSubmodulesCommand; this.viewViewModelFactory = viewViewModelFactory; + this.gitService = gitService; Files = files; Checkout = ReactiveCommand.CreateFromObservable( @@ -401,6 +405,8 @@ public async Task Load(PullRequestDetailModel pullRequest) var localBranches = await pullRequestsService.GetLocalBranches(LocalRepository, pullRequest).ToList(); + // HACK: This is only necessary because the CurrentBranch is being read too early + gitService.Refresh(LocalRepository); IsCheckedOut = localBranches.Contains(LocalRepository.CurrentBranch); if (IsCheckedOut) diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs index ac24f57097..1a15c43943 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs @@ -607,7 +607,8 @@ static Tuple CreateTargetAndSer Substitute.For(), Substitute.For(), Substitute.For(), - Substitute.For()); + Substitute.For(), + Substitute.For()); vm.InitializeAsync(repository, Substitute.For(), "owner", "repo", 1).Wait(); return Tuple.Create(vm, pullRequestService); From 713d9c40dd37738da635cb550bd0810a4e26fe7c Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 31 Oct 2018 12:38:42 +0000 Subject: [PATCH 15/39] Refactor to IGitService.CreateCurrentBranchModel Remove the ILocalRepositoryModel.CurrentBranch property and explicitly call IGitService.CreateCurrentBranchModel instead. Fix all the broken tests. --- .../SampleData/GitServiceDesigner.cs | 2 +- .../Services/TeamExplorerContext.cs | 27 ++---------- .../PullRequestCreationViewModel.cs | 13 ++++-- .../GitHubPane/PullRequestDetailViewModel.cs | 5 +-- .../Models/ILocalRepositoryModel.cs | 5 --- .../Models/LocalRepositoryModel.cs | 8 ---- src/GitHub.Exports/Services/GitService.cs | 36 ++++++++-------- src/GitHub.Exports/Services/IGitService.cs | 9 +++- .../Commands/OpenFromClipboardCommand.cs | 14 ++++--- .../Services/TeamExplorerContextTests.cs | 42 ++++--------------- .../PullRequestCreationViewModelTests.cs | 27 +++++++----- .../PullRequestDetailViewModelTests.cs | 5 ++- .../Commands/OpenFromClipboardCommandTests.cs | 22 ++++++---- 13 files changed, 90 insertions(+), 125 deletions(-) diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index 95bd0bc276..6d90eaacbb 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -9,7 +9,7 @@ namespace GitHub.SampleData class GitServiceDesigner : IGitService { public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; - public ILocalRepositoryModel CreateLocalRepositoryModel(string name, UriString cloneUrl, string localPath) => null; + public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) => null; public void Refresh(ILocalRepositoryModel localRepositoryModel) { } public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; diff --git a/src/GitHub.App/Services/TeamExplorerContext.cs b/src/GitHub.App/Services/TeamExplorerContext.cs index 6d443e4dfc..555f8962f2 100644 --- a/src/GitHub.App/Services/TeamExplorerContext.cs +++ b/src/GitHub.App/Services/TeamExplorerContext.cs @@ -40,9 +40,6 @@ public class TeamExplorerContext : ITeamExplorerContext string solutionPath; string repositoryPath; UriString cloneUrl; - string branchName; - string headSha; - string trackedSha; Tuple pullRequest; ILocalRepositoryModel repositoryModel; @@ -113,9 +110,6 @@ async Task RefreshAsync() { var newRepositoryPath = repo?.LocalPath; var newCloneUrl = repo?.CloneUrl; - var newBranchName = repo?.CurrentBranch?.Name; - var newHeadSha = repo?.CurrentBranch?.Sha; - var newTrackedSha = repo?.CurrentBranch?.TrackedSha; var newPullRequest = repo != null ? await pullRequestService.GetPullRequestForCurrentBranch(repo) : null; if (newRepositoryPath != repositoryPath) @@ -128,33 +122,20 @@ async Task RefreshAsync() log.Debug("ActiveRepository changed to {CloneUrl} @ {Path}", repo?.CloneUrl, newRepositoryPath); ActiveRepository = repo; } - else if (newBranchName != branchName) - { - log.Debug("Fire StatusChanged event when BranchName changes for ActiveRepository"); - StatusChanged?.Invoke(this, EventArgs.Empty); - } - else if (newHeadSha != headSha) - { - log.Debug("Fire StatusChanged event when HeadSha changes for ActiveRepository"); - StatusChanged?.Invoke(this, EventArgs.Empty); - } - else if (newTrackedSha != trackedSha) + else if (newPullRequest != pullRequest) { - log.Debug("Fire StatusChanged event when TrackedSha changes for ActiveRepository"); + log.Debug("Fire StatusChanged event when PullRequest changes for ActiveRepository"); StatusChanged?.Invoke(this, EventArgs.Empty); } - else if (newPullRequest != pullRequest) + else { - log.Debug("Fire StatusChanged event when PullRequest changes for ActiveRepository"); + log.Debug("Fire StatusChanged event when ***anything*** changes"); StatusChanged?.Invoke(this, EventArgs.Empty); } repositoryPath = newRepositoryPath; cloneUrl = newCloneUrl; - branchName = newBranchName; - headSha = newHeadSha; solutionPath = newSolutionPath; - trackedSha = newTrackedSha; pullRequest = newPullRequest; } } diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index f72bc605fe..764fc1ec10 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -38,6 +38,7 @@ public class PullRequestCreationViewModel : PanePageViewModelBase, IPullRequestC readonly IPullRequestService service; readonly IModelServiceFactory modelServiceFactory; readonly IMessageDraftStore draftStore; + readonly IGitService gitService; readonly IScheduler timerScheduler; readonly CompositeDisposable disposables = new CompositeDisposable(); ILocalRepositoryModel activeLocalRepo; @@ -49,8 +50,9 @@ public PullRequestCreationViewModel( IModelServiceFactory modelServiceFactory, IPullRequestService service, INotificationService notifications, - IMessageDraftStore draftStore) - : this(modelServiceFactory, service, notifications, draftStore, DefaultScheduler.Instance) + IMessageDraftStore draftStore, + IGitService gitService) + : this(modelServiceFactory, service, notifications, draftStore, gitService, DefaultScheduler.Instance) { } @@ -59,17 +61,20 @@ public PullRequestCreationViewModel( IPullRequestService service, INotificationService notifications, IMessageDraftStore draftStore, + IGitService gitService, IScheduler timerScheduler) { Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory)); Guard.ArgumentNotNull(service, nameof(service)); Guard.ArgumentNotNull(notifications, nameof(notifications)); Guard.ArgumentNotNull(draftStore, nameof(draftStore)); + Guard.ArgumentNotNull(gitService, nameof(gitService)); Guard.ArgumentNotNull(timerScheduler, nameof(timerScheduler)); this.service = service; this.modelServiceFactory = modelServiceFactory; this.draftStore = draftStore; + this.gitService = gitService; this.timerScheduler = timerScheduler; this.WhenAnyValue(x => x.Branches) @@ -137,7 +142,7 @@ public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection { modelService = await modelServiceFactory.CreateAsync(connection); activeLocalRepo = repository; - SourceBranch = repository.CurrentBranch; + SourceBranch = gitService.CreateCurrentBranchModel(repository); var obs = modelService.ApiClient.GetRepository(repository.Owner, repository.Name) .Select(r => new RemoteRepositoryModel(r)) @@ -207,7 +212,7 @@ async Task LoadInitialState(string draftKey) void LoadDescriptionFromCommits() { - SourceBranch = activeLocalRepo.CurrentBranch; + SourceBranch = gitService.CreateCurrentBranchModel(activeLocalRepo); var uniqueCommits = this.WhenAnyValue( x => x.SourceBranch, diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs index bf7c967208..fc1f6dd703 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs @@ -405,9 +405,8 @@ public async Task Load(PullRequestDetailModel pullRequest) var localBranches = await pullRequestsService.GetLocalBranches(LocalRepository, pullRequest).ToList(); - // HACK: This is only necessary because the CurrentBranch is being read too early - gitService.Refresh(LocalRepository); - IsCheckedOut = localBranches.Contains(LocalRepository.CurrentBranch); + var currentBranch = gitService.CreateCurrentBranchModel(LocalRepository); + IsCheckedOut = localBranches.Contains(currentBranch); if (IsCheckedOut) { diff --git a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs index 41c6ad508f..781180f4f2 100644 --- a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs @@ -11,10 +11,5 @@ public interface ILocalRepositoryModel : IRepositoryModel, INotifyPropertyChange /// Gets the path to the repository on the filesystem. /// string LocalPath { get; } - - /// - /// Gets the current branch. - /// - IBranch CurrentBranch { get; set; } } } diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index 7feae3e151..6e9e1e521e 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -18,14 +18,6 @@ public string LocalPath get; set; } - /// - /// Gets the current branch of the repository. - /// - public IBranch CurrentBranch - { - get; set; - } - /// /// Note: We don't consider CloneUrl a part of the hash code because it can change during the lifetime /// of a repository. Equals takes care of any hash collisions because of this diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 30b23849c6..2fee66dff7 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -49,13 +49,27 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) Icon = Octicon.repo }; - RefreshCurrentBranch(model); - return model; } + public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) + { + var localPath = model.LocalPath; + using (var repo = GetRepository(localPath)) + { + var headBranch = repo?.Head; + if (headBranch == null) + { + return null; + } + + // BranchModel doesn't keep a reference to Repository + return new BranchModel(headBranch, model, this); + } + } + /// - /// Updates the CloneUrl and CurrentBranch from the local repository. + /// Updates the CloneUrl from the "origin" remote. /// public void Refresh(ILocalRepositoryModel localRepositoryModel) { @@ -64,8 +78,6 @@ public void Refresh(ILocalRepositoryModel localRepositoryModel) return; localRepositoryModel.CloneUrl = GetUri(localPath); - - RefreshCurrentBranch(localRepositoryModel); } /// @@ -200,19 +212,5 @@ public Task GetLatestPushedSha(string path, string remote = "origin") } }); } - - void RefreshCurrentBranch(ILocalRepositoryModel model) - { - var localPath = model.LocalPath; - using (var repo = GetRepository(localPath)) - { - var headBranch = repo?.Head; - if (headBranch != null) - { - // BranchModel doesn't keep a reference to Repository - model.CurrentBranch = new BranchModel(headBranch, model, this); - } - } - } } } \ No newline at end of file diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 1bcd0480f3..96a0f044dc 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -15,7 +15,14 @@ public interface IGitService ILocalRepositoryModel CreateLocalRepositoryModel(string localPath); /// - /// Updates the CloneUrl information based on the local path. + /// Creates a new branch model for the current branch. + /// + /// The to create a current branch model for. + /// A new branch model. + IBranch CreateCurrentBranchModel(ILocalRepositoryModel model); + + /// + /// Updates the CloneUrl information based on the "origin" remote. /// /// The repository model to refresh. void Refresh(ILocalRepositoryModel localRepositoryModel); diff --git a/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs b/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs index 7476a6eb58..73e77cea96 100644 --- a/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs +++ b/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs @@ -4,7 +4,6 @@ using GitHub.Exports; using GitHub.Services; using GitHub.Services.Vssdk.Commands; -using GitHub.VisualStudio.UI; using Microsoft.VisualStudio.Shell; using Task = System.Threading.Tasks.Task; @@ -13,11 +12,12 @@ namespace GitHub.VisualStudio.Commands [Export(typeof(IOpenFromClipboardCommand))] public class OpenFromClipboardCommand : VsCommand, IOpenFromClipboardCommand { - + readonly Lazy gitHubContextService; readonly Lazy teamExplorerContext; readonly Lazy vsServices; + readonly Lazy gitService; readonly Lazy uiContext; /// @@ -34,12 +34,14 @@ public class OpenFromClipboardCommand : VsCommand, IOpenFromClipboardCom public OpenFromClipboardCommand( Lazy gitHubContextService, Lazy teamExplorerContext, - Lazy vsServices) + Lazy vsServices, + Lazy gitService) : base(CommandSet, CommandId) { this.gitHubContextService = gitHubContextService; this.teamExplorerContext = teamExplorerContext; this.vsServices = vsServices; + this.gitService = gitService; // See https://code.msdn.microsoft.com/windowsdesktop/AllowParams-2005-9442298f ParametersDescription = "u"; // accept a single url @@ -96,9 +98,11 @@ public override async Task Execute(string url) var hasChanges = gitHubContextService.Value.HasChangesInWorkingDirectory(repositoryDir, commitish, path); if (hasChanges) { - // AnnotateFile expects a branch name so we use the current branch - var branchName = activeRepository.CurrentBranch.Name; + // TODO: What if this returns null because we're not on a branch? + var currentBranch = gitService.Value.CreateCurrentBranchModel(activeRepository); + var branchName = currentBranch.Name; + // AnnotateFile expects a branch name so we use the current branch if (await gitHubContextService.Value.TryAnnotateFile(repositoryDir, branchName, context)) { return; diff --git a/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs b/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs index f539b589e0..a3fc3b5352 100644 --- a/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs +++ b/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs @@ -151,45 +151,22 @@ public void NoActiveRepositoryChange_SolutionChanges() public class TheStatusChangedEvent { - [TestCase(false, "name1", "sha1", "name1", "sha1", false)] - [TestCase(false, "name1", "sha1", "name2", "sha1", true)] - [TestCase(false, "name1", "sha1", "name1", "sha2", true)] - [TestCase(false, "name1", "sha1", "name2", "sha2", true)] - [TestCase(true, "name1", "sha1", "name1", "sha1", false)] - [TestCase(true, "name1", "sha1", "name2", "sha2", false)] - public void SameActiveRepository_ExpectWasRaised(bool changePath, string name1, string sha1, string name2, string sha2, bool expectWasRaised) + [TestCase(true, false)] + [TestCase(false, true)] + public void AlwaysFireWhenNoLocalPathChange(bool changePath, bool expectWasRaised) { var gitExt = CreateGitExt(); var repositoryPaths = new[] { Directory.GetCurrentDirectory(), Path.GetTempPath() }; var path1 = Directory.GetCurrentDirectory(); var path2 = changePath ? Path.GetTempPath() : path1; - var repoInfo1 = CreateRepositoryModel(path1, name1, sha1); - var repoInfo2 = CreateRepositoryModel(path2, name2, sha2); + var repoInfo1 = CreateRepositoryModel(path1); + var repoInfo2 = CreateRepositoryModel(path2); var target = CreateTeamExplorerContext(gitExt); - var eventWasRaised = false; - target.StatusChanged += (s, e) => eventWasRaised = true; - SetActiveRepository(gitExt, repoInfo1); - SetActiveRepository(gitExt, repoInfo2); - - Assert.That(eventWasRaised, Is.EqualTo(expectWasRaised)); - } - - [TestCase("trackedSha", "trackedSha", false)] - [TestCase("trackedSha1", "trackedSha2", true)] - public void TrackedShaChanges_CheckWasRaised(string trackedSha1, string trackedSha2, bool expectWasRaised) - { - var gitExt = CreateGitExt(); - var repositoryPaths = new[] { Directory.GetCurrentDirectory(), Path.GetTempPath() }; - var repoPath = Directory.GetCurrentDirectory(); - var repoInfo1 = CreateRepositoryModel(repoPath, "name", "sha", trackedSha1); - var repoInfo2 = CreateRepositoryModel(repoPath, "name", "sha", trackedSha2); - var target = CreateTeamExplorerContext(gitExt); SetActiveRepository(gitExt, repoInfo1); var eventWasRaised = false; target.StatusChanged += (s, e) => eventWasRaised = true; - SetActiveRepository(gitExt, repoInfo2); Assert.That(eventWasRaised, Is.EqualTo(expectWasRaised)); @@ -200,7 +177,7 @@ public void SolutionUnloadedAndReloaded_DontFireStatusChanged() { var gitExt = CreateGitExt(); var path = Directory.GetCurrentDirectory(); - var repoInfo1 = CreateRepositoryModel(path, "name", "sha"); + var repoInfo1 = CreateRepositoryModel(path); var repoInfo2 = CreateRepositoryModel(null); var target = CreateTeamExplorerContext(gitExt); SetActiveRepository(gitExt, repoInfo1); @@ -226,15 +203,10 @@ static TeamExplorerContext CreateTeamExplorerContext( return new TeamExplorerContext(gitExt, new AsyncLazy(() => Task.FromResult(dte)), pullRequestService, joinableTaskContext); } - static ILocalRepositoryModel CreateRepositoryModel(string path, string branchName = null, string headSha = null, string trackedSha = null) + static ILocalRepositoryModel CreateRepositoryModel(string path) { var repo = Substitute.For(); repo.LocalPath.Returns(path); - var currentBranch = Substitute.For(); - currentBranch.Name.Returns(branchName); - currentBranch.Sha.Returns(headSha); - currentBranch.TrackedSha.Returns(trackedSha); - repo.CurrentBranch.Returns(currentBranch); return repo; } diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index 5b21260e0a..726566dae8 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -6,14 +6,12 @@ using GitHub.Models; using GitHub.Primitives; using GitHub.Services; -using GitHub.ViewModels; using GitHub.ViewModels.GitHubPane; using NSubstitute; using Octokit; using UnitTests; using NUnit.Framework; using IConnection = GitHub.Models.IConnection; -using ReactiveUI.Testing; using System.Reactive.Concurrency; using GitHub.Models.Drafts; @@ -99,7 +97,7 @@ static TestData PrepareTestData( var targetRepo = targetRepoOwner == sourceRepoOwner ? sourceRepo : sourceRepo.Parent; var targetBranch = targetBranchName != targetRepo.DefaultBranch.Name ? new BranchModel(targetBranchName, targetRepo) : targetRepo.DefaultBranch; - activeRepo.CurrentBranch.Returns(sourceBranch); + gitService.CreateCurrentBranchModel(activeRepo).Returns(sourceBranch); api.GetRepository(Args.String, Args.String).Returns(Observable.Return(githubRepo)); ms.ApiClient.Returns(api); @@ -130,7 +128,8 @@ public async Task TargetBranchDisplayNameIncludesRepoOwnerWhenForkAsync() var data = PrepareTestData("octokit.net", "shana", "master", "octokit", "master", "origin", true, true); var prservice = new PullRequestService(data.GitClient, data.GitService, Substitute.For(), Substitute.For(), data.ServiceProvider.GetOperatingSystem(), Substitute.For()); prservice.GetPullRequestTemplate(data.ActiveRepo).Returns(Observable.Empty()); - var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, Substitute.For()); + var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, + Substitute.For(), data.GitService); await vm.InitializeAsync(data.ActiveRepo, data.Connection); Assert.That("octokit/master", Is.EqualTo(vm.TargetBranch.DisplayName)); } @@ -165,7 +164,8 @@ public async Task CreatingPRsAsync( var ms = data.ModelService; var prservice = new PullRequestService(data.GitClient, data.GitService, Substitute.For(), Substitute.For(), data.ServiceProvider.GetOperatingSystem(), Substitute.For()); - var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, Substitute.For()); + var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, + Substitute.For(), data.GitService); await vm.InitializeAsync(data.ActiveRepo, data.Connection); // the TargetBranch property gets set to whatever the repo default is (we assume master here), @@ -208,7 +208,7 @@ public async Task TemplateIsUsedIfPresentAsync() prservice.GetPullRequestTemplate(data.ActiveRepo).Returns(Observable.Return("Test PR template")); var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, - Substitute.For()); + Substitute.For(), data.GitService); await vm.InitializeAsync(data.ActiveRepo, data.Connection); Assert.That("Test PR template", Is.EqualTo(vm.Description)); @@ -227,7 +227,8 @@ public async Task LoadsDraft() }); var prservice = Substitute.For(); - var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, draftStore); + var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, + draftStore, data.GitService); await vm.InitializeAsync(data.ActiveRepo, data.Connection); Assert.That(vm.PRTitle, Is.EqualTo("This is a Title.")); @@ -241,7 +242,8 @@ public async Task UpdatesDraftWhenDescriptionChanges() var scheduler = new HistoricalScheduler(); var draftStore = Substitute.For(); var prservice = Substitute.For(); - var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, draftStore, scheduler); + var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, + draftStore, data.GitService, scheduler); await vm.InitializeAsync(data.ActiveRepo, data.Connection); vm.Description = "Body changed."; @@ -263,7 +265,8 @@ public async Task UpdatesDraftWhenTitleChanges() var scheduler = new HistoricalScheduler(); var draftStore = Substitute.For(); var prservice = Substitute.For(); - var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, draftStore, scheduler); + var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, + draftStore, data.GitService, scheduler); await vm.InitializeAsync(data.ActiveRepo, data.Connection); vm.PRTitle = "Title changed."; @@ -285,7 +288,8 @@ public async Task DeletesDraftWhenPullRequestSubmitted() var scheduler = new HistoricalScheduler(); var draftStore = Substitute.For(); var prservice = Substitute.For(); - var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, draftStore, scheduler); + var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, draftStore, + data.GitService, scheduler); await vm.InitializeAsync(data.ActiveRepo, data.Connection); await vm.CreatePullRequest.Execute(); @@ -300,7 +304,8 @@ public async Task DeletesDraftWhenCanceled() var scheduler = new HistoricalScheduler(); var draftStore = Substitute.For(); var prservice = Substitute.For(); - var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, draftStore, scheduler); + var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, draftStore, + data.GitService, scheduler); await vm.InitializeAsync(data.ActiveRepo, data.Connection); await vm.Cancel.Execute(); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs index 1a15c43943..fae1bd9fa7 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs @@ -552,7 +552,8 @@ static Tuple CreateTargetAndSer { var repository = Substitute.For(); var currentBranchModel = new BranchModel(currentBranch, repository); - repository.CurrentBranch.Returns(currentBranchModel); + var gitService = Substitute.For(); + gitService.CreateCurrentBranchModel(repository).Returns(currentBranchModel); repository.CloneUrl.Returns(new UriString(Uri.ToString())); repository.LocalPath.Returns(@"C:\projects\ThisRepo"); repository.Name.Returns("repo"); @@ -608,7 +609,7 @@ static Tuple CreateTargetAndSer Substitute.For(), Substitute.For(), Substitute.For(), - Substitute.For()); + gitService); vm.InitializeAsync(repository, Substitute.For(), "owner", "repo", 1).Wait(); return Tuple.Create(vm, pullRequestService); diff --git a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs index 0235482263..b43a203c74 100644 --- a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs @@ -3,10 +3,10 @@ using System.Threading.Tasks; using GitHub; using GitHub.Exports; +using GitHub.Models; using GitHub.Primitives; using GitHub.Services; using GitHub.VisualStudio.Commands; -using GitHub.VisualStudio.UI; using Microsoft.VisualStudio; using NSubstitute; using NUnit.Framework; @@ -146,7 +146,8 @@ public async Task HasChangesInWorkingDirectory(bool annotateFileSupported, strin var resolveBlobResult = (targetBranch, "foo.cs", ""); var vsServices = Substitute.For(); var target = CreateOpenFromClipboardCommand(gitHubContextService: gitHubContextService, vsServices: vsServices, - contextFromClipboard: context, repositoryDir: repositoryDir, repositoryName: repositoryName, currentBranch: currentBranch, resolveBlobResult: resolveBlobResult, hasChanges: true); + contextFromClipboard: context, repositoryDir: repositoryDir, repositoryName: repositoryName, + currentBranchName: currentBranch, resolveBlobResult: resolveBlobResult, hasChanges: true); await target.Execute(null); @@ -179,7 +180,7 @@ static OpenFromClipboardCommand CreateOpenFromClipboardCommand( string repositoryDir = null, string repositoryName = null, string repositoryOwner = null, - string currentBranch = null, + string currentBranchName = null, (string, string, string)? resolveBlobResult = null, bool? hasChanges = null) { @@ -189,10 +190,14 @@ static OpenFromClipboardCommand CreateOpenFromClipboardCommand( vsServices = vsServices ?? Substitute.For(); gitHubContextService.FindContextFromClipboard().Returns(contextFromClipboard); - teamExplorerContext.ActiveRepository.LocalPath.Returns(repositoryDir); - teamExplorerContext.ActiveRepository.Name.Returns(repositoryName); - teamExplorerContext.ActiveRepository.Owner.Returns(repositoryOwner); - teamExplorerContext.ActiveRepository.CurrentBranch.Name.Returns(currentBranch); + var activeRepository = teamExplorerContext.ActiveRepository; + activeRepository.LocalPath.Returns(repositoryDir); + activeRepository.Name.Returns(repositoryName); + activeRepository.Owner.Returns(repositoryOwner); + var gitService = Substitute.For(); + var currentBranch = Substitute.For(); + currentBranch.Name.Returns(currentBranchName); + gitService.CreateCurrentBranchModel(activeRepository).Returns(currentBranch); if (resolveBlobResult != null) { gitHubContextService.ResolveBlob(repositoryDir, contextFromClipboard).Returns(resolveBlobResult.Value); @@ -206,7 +211,8 @@ static OpenFromClipboardCommand CreateOpenFromClipboardCommand( return new OpenFromClipboardCommand( new Lazy(() => gitHubContextService), new Lazy(() => teamExplorerContext), - new Lazy(() => vsServices)); + new Lazy(() => vsServices), + new Lazy(() => gitService)); } static string ResolveResources(string str) From 0f59f7e93b5c99b966acafde4a571c53121ebd70 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 31 Oct 2018 13:26:37 +0000 Subject: [PATCH 16/39] Make GetPullRequestForCurrentBranch return (tuple) Convert GetPullRequestForCurrentBranch to return (string owner, int number). This allows the tuple to be compared directly. --- src/GitHub.App/Services/PullRequestService.cs | 14 +++++++------- src/GitHub.App/Services/TeamExplorerContext.cs | 4 ++-- .../Services/IPullRequestService.cs | 2 +- .../Services/PullRequestSessionManager.cs | 2 +- .../Services/PullRequestSessionManagerTests.cs | 14 +++++++------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index 9b8015cb43..3a0f16c2bd 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -231,8 +231,8 @@ public async Task> ReadPullRequests( if (hasCheckRuns) { checksHasFailure = checkRuns - .Any(model => model.Conclusion.HasValue - && (model.Conclusion.Value == CheckConclusionState.Failure + .Any(model => model.Conclusion.HasValue + && (model.Conclusion.Value == CheckConclusionState.Failure || model.Conclusion.Value == CheckConclusionState.ActionRequired)); if (!checksHasFailure) @@ -718,7 +718,7 @@ public IObservable SwitchToBranch(ILocalRepositoryModel repository, PullRe }); } - public IObservable> GetPullRequestForCurrentBranch(ILocalRepositoryModel repository) + public IObservable<(string owner, int number)> GetPullRequestForCurrentBranch(ILocalRepositoryModel repository) { return Observable.Defer(async () => { @@ -912,7 +912,7 @@ async Task IsBranchMarkedAsPullRequest(IRepository repo, string branchName { var prConfigKey = $"branch.{branchName}.{SettingGHfVSPullRequest}"; var value = ParseGHfVSConfigKeyValue(await gitClient.GetConfig(repo, prConfigKey)); - return value != null && + return value != default && value.Item1 == pullRequest.BaseRepositoryOwner && value.Item2 == pullRequest.Number; } @@ -983,7 +983,7 @@ static string BuildGHfVSConfigKeyValue(string owner, int number) return owner + '#' + number.ToString(CultureInfo.InvariantCulture); } - static Tuple ParseGHfVSConfigKeyValue(string value) + static (string owner, int number) ParseGHfVSConfigKeyValue(string value) { if (value != null) { @@ -996,12 +996,12 @@ static Tuple ParseGHfVSConfigKeyValue(string value) if (int.TryParse(value.Substring(separator + 1), NumberStyles.None, CultureInfo.InvariantCulture, out number)) { - return Tuple.Create(owner, number); + return (owner, number); } } } - return null; + return default; } class ListItemAdapter : PullRequestListItemModel diff --git a/src/GitHub.App/Services/TeamExplorerContext.cs b/src/GitHub.App/Services/TeamExplorerContext.cs index 555f8962f2..06353a747b 100644 --- a/src/GitHub.App/Services/TeamExplorerContext.cs +++ b/src/GitHub.App/Services/TeamExplorerContext.cs @@ -40,7 +40,7 @@ public class TeamExplorerContext : ITeamExplorerContext string solutionPath; string repositoryPath; UriString cloneUrl; - Tuple pullRequest; + (string owner, int number) pullRequest; ILocalRepositoryModel repositoryModel; JoinableTask refreshJoinableTask; @@ -110,7 +110,7 @@ async Task RefreshAsync() { var newRepositoryPath = repo?.LocalPath; var newCloneUrl = repo?.CloneUrl; - var newPullRequest = repo != null ? await pullRequestService.GetPullRequestForCurrentBranch(repo) : null; + var newPullRequest = repo != null ? await pullRequestService.GetPullRequestForCurrentBranch(repo) : default; if (newRepositoryPath != repositoryPath) { diff --git a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs index 48837ce2d6..0d34471afb 100644 --- a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs +++ b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs @@ -173,7 +173,7 @@ IObservable CreatePullRequest(IModelService modelService, /// This method does not do an API request - it simply checks the mark left in the git /// config by . /// - IObservable> GetPullRequestForCurrentBranch(ILocalRepositoryModel repository); + IObservable<(string owner, int number)> GetPullRequestForCurrentBranch(ILocalRepositoryModel repository); /// /// Gets the encoding for the specified local file. diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs index 0c62775f9a..b8e10ccf8e 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs @@ -203,7 +203,7 @@ async Task StatusChanged() var session = CurrentSession; var pr = await service.GetPullRequestForCurrentBranch(repository).FirstOrDefaultAsync(); - if (pr != null) + if (pr != default) { var changePR = pr.Item1 != (session?.PullRequest.BaseRepositoryOwner) || diff --git a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs index 5b6dc68a57..7b49b9ff2c 100644 --- a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs +++ b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs @@ -41,7 +41,7 @@ public void ReadsPullRequestFromCorrectFork() var sessionService = CreateSessionService(); service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs( - Observable.Return(Tuple.Create("fork", CurrentBranchPullRequestNumber))); + Observable.Return(("fork", CurrentBranchPullRequestNumber))); var connectionManager = CreateConnectionManager(); var target = CreateTarget( @@ -80,7 +80,7 @@ public void CreatesSessionForCurrentBranch() public void CurrentSessionIsNullIfNoPullRequestForCurrentBranch() { var service = CreatePullRequestService(); - service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Empty>()); + service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Empty<(string, int)>()); var target = CreateTarget(service: service); @@ -98,7 +98,7 @@ public void CurrentSessionChangesWhenBranchChanges() var session = target.CurrentSession; - service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Return(Tuple.Create("foo", 22))); + service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Return(("foo", 22))); teamExplorerContext.StatusChanged += Raise.Event(); Assert.That(session, Is.Not.SameAs(target.CurrentSession)); @@ -124,7 +124,7 @@ public void CurrentSessionChangesToNullIfNoPullRequestForCurrentBranch() teamExplorerContext: teamExplorerContext); Assert.That(target.CurrentSession, Is.Not.Null); - Tuple newPullRequest = null; + (string owner, int number) newPullRequest = default; service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Return(newPullRequest)); teamExplorerContext.StatusChanged += Raise.Event(); @@ -813,14 +813,14 @@ public async Task GetSessionUpdatesCurrentSessionIfCurrentBranchIsPullRequestBut var model = CreatePullRequestModel(); var sessionService = CreateSessionService(model); - service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Empty>()); + service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Empty<(string, int)>()); var target = CreateTarget(service: service, sessionService: sessionService); Assert.That(target.CurrentSession, Is.Null); service.EnsureLocalBranchesAreMarkedAsPullRequests(Arg.Any(), model).Returns(Observable.Return(true)); - service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Return(Tuple.Create("owner", CurrentBranchPullRequestNumber))); + service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Return(("owner", CurrentBranchPullRequestNumber))); var session = await target.GetSession("owner", "name", CurrentBranchPullRequestNumber); @@ -881,7 +881,7 @@ PullRequestDetailModel CreatePullRequestModel( IPullRequestService CreatePullRequestService(string owner = "owner") { var result = Substitute.For(); - result.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Return(Tuple.Create(owner, CurrentBranchPullRequestNumber))); + result.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Return((owner, CurrentBranchPullRequestNumber))); return result; } From 42d09faf6ebedcd82052d9e9242f9423973f515f Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 31 Oct 2018 13:30:21 +0000 Subject: [PATCH 17/39] Avoid firing StatusChanged if we're not on a repo --- src/GitHub.App/Services/TeamExplorerContext.cs | 4 ++-- .../Services/TeamExplorerContextTests.cs | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/GitHub.App/Services/TeamExplorerContext.cs b/src/GitHub.App/Services/TeamExplorerContext.cs index 06353a747b..ecbaddf742 100644 --- a/src/GitHub.App/Services/TeamExplorerContext.cs +++ b/src/GitHub.App/Services/TeamExplorerContext.cs @@ -127,9 +127,9 @@ async Task RefreshAsync() log.Debug("Fire StatusChanged event when PullRequest changes for ActiveRepository"); StatusChanged?.Invoke(this, EventArgs.Empty); } - else + else if (newRepositoryPath != null) { - log.Debug("Fire StatusChanged event when ***anything*** changes"); + log.Debug("Fire StatusChanged event when on a repository and anything changes"); StatusChanged?.Invoke(this, EventArgs.Empty); } diff --git a/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs b/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs index a3fc3b5352..6e202f0aaf 100644 --- a/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs +++ b/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs @@ -151,14 +151,13 @@ public void NoActiveRepositoryChange_SolutionChanges() public class TheStatusChangedEvent { - [TestCase(true, false)] - [TestCase(false, true)] - public void AlwaysFireWhenNoLocalPathChange(bool changePath, bool expectWasRaised) + [TestCase("path", "path", true)] + [TestCase("path1", "path2", false)] + [TestCase(null, null, false)] + public void AlwaysFireWhenNoLocalPathChange(string path1, string path2, bool expectWasRaised) { var gitExt = CreateGitExt(); var repositoryPaths = new[] { Directory.GetCurrentDirectory(), Path.GetTempPath() }; - var path1 = Directory.GetCurrentDirectory(); - var path2 = changePath ? Path.GetTempPath() : path1; var repoInfo1 = CreateRepositoryModel(path1); var repoInfo2 = CreateRepositoryModel(path2); From a47af2b3304b1b58a698ece6a144087b14c5af80 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 31 Oct 2018 15:03:57 +0000 Subject: [PATCH 18/39] Suppress "Do not directly await a Task" warning --- src/GitHub.App/GlobalSuppressions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/GitHub.App/GlobalSuppressions.cs b/src/GitHub.App/GlobalSuppressions.cs index f635f8ea1d..d3dcbf45d6 100644 --- a/src/GitHub.App/GlobalSuppressions.cs +++ b/src/GitHub.App/GlobalSuppressions.cs @@ -6,6 +6,8 @@ [assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Git", Scope = "resource", Target = "GitHub.App.Resources.resources")] [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)")] [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)")] +[assembly: SuppressMessage("Reliability", "CA2007:Do not directly await a Task", Justification = "We always need to think about what thread we're running on")] + // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given From db41ef99e5151b82bae548400e3e55d144d6df84 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 31 Oct 2018 16:02:37 +0000 Subject: [PATCH 19/39] Get rid of LocalRepositoryModelFactory We can now use GitService as a LocalRepositoryMode factory. --- .../Models/ILocalRepositoryModelFactory.cs | 15 ------- .../GitHub.TeamFoundation.14.csproj | 1 - .../Services/LocalRepositoryModelFactory.cs | 13 ------ .../Services/VSGitExt.cs | 24 +++++------ .../GitHub.TeamFoundation.15.csproj | 3 -- .../GitHub.TeamFoundation.16.csproj | 3 -- src/GitHub.VisualStudio/GitHubPackage.cs | 2 +- .../Services/VSGitExtFactory.cs | 10 +++-- .../VSGitExtTests.cs | 40 ++++++++++++------- 9 files changed, 44 insertions(+), 67 deletions(-) delete mode 100644 src/GitHub.Exports/Models/ILocalRepositoryModelFactory.cs delete mode 100644 src/GitHub.TeamFoundation.14/Services/LocalRepositoryModelFactory.cs diff --git a/src/GitHub.Exports/Models/ILocalRepositoryModelFactory.cs b/src/GitHub.Exports/Models/ILocalRepositoryModelFactory.cs deleted file mode 100644 index 3c8dfed0ce..0000000000 --- a/src/GitHub.Exports/Models/ILocalRepositoryModelFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace GitHub.Models -{ - /// - /// A factory for objects. - /// - public interface ILocalRepositoryModelFactory - { - /// - /// Construct a new . - /// - /// The local path for the repository. - /// A new repository model. - ILocalRepositoryModel Create(string localPath); - } -} diff --git a/src/GitHub.TeamFoundation.14/GitHub.TeamFoundation.14.csproj b/src/GitHub.TeamFoundation.14/GitHub.TeamFoundation.14.csproj index a27bc63e3a..d4b56fc610 100644 --- a/src/GitHub.TeamFoundation.14/GitHub.TeamFoundation.14.csproj +++ b/src/GitHub.TeamFoundation.14/GitHub.TeamFoundation.14.csproj @@ -163,7 +163,6 @@ - diff --git a/src/GitHub.TeamFoundation.14/Services/LocalRepositoryModelFactory.cs b/src/GitHub.TeamFoundation.14/Services/LocalRepositoryModelFactory.cs deleted file mode 100644 index 06c4bc9572..0000000000 --- a/src/GitHub.TeamFoundation.14/Services/LocalRepositoryModelFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -using GitHub.Models; -using GitHub.Services; - -namespace GitHub.TeamFoundation.Services -{ - class LocalRepositoryModelFactory : ILocalRepositoryModelFactory - { - public ILocalRepositoryModel Create(string localPath) - { - return GitService.GitServiceHelper.CreateLocalRepositoryModel(localPath); - } - } -} diff --git a/src/GitHub.TeamFoundation.14/Services/VSGitExt.cs b/src/GitHub.TeamFoundation.14/Services/VSGitExt.cs index d996b9e170..10167940e0 100644 --- a/src/GitHub.TeamFoundation.14/Services/VSGitExt.cs +++ b/src/GitHub.TeamFoundation.14/Services/VSGitExt.cs @@ -27,18 +27,18 @@ public class VSGitExt : IVSGitExt static readonly ILogger log = LogManager.ForContext(); readonly IServiceProvider serviceProvider; - readonly ILocalRepositoryModelFactory repositoryFactory; + readonly IGitService gitService; readonly object refreshLock = new object(); - IGitExt gitService; + IGitExt gitExt; IReadOnlyList activeRepositories; - public VSGitExt(IServiceProvider serviceProvider) - : this(serviceProvider, new VSUIContextFactory(), new LocalRepositoryModelFactory(), ThreadHelper.JoinableTaskContext) + public VSGitExt(IServiceProvider serviceProvider, IGitService gitService) + : this(serviceProvider, new VSUIContextFactory(), gitService, ThreadHelper.JoinableTaskContext) { } - public VSGitExt(IServiceProvider serviceProvider, IVSUIContextFactory factory, ILocalRepositoryModelFactory repositoryFactory, + public VSGitExt(IServiceProvider serviceProvider, IVSUIContextFactory factory, IGitService gitService, JoinableTaskContext joinableTaskContext) { JoinableTaskCollection = joinableTaskContext.CreateCollection(); @@ -46,7 +46,7 @@ public VSGitExt(IServiceProvider serviceProvider, IVSUIContextFactory factory, I JoinableTaskFactory = joinableTaskContext.CreateFactory(JoinableTaskCollection); this.serviceProvider = serviceProvider; - this.repositoryFactory = repositoryFactory; + this.gitService = gitService; // Start with empty array until we have a chance to initialize. ActiveRepositories = Array.Empty(); @@ -64,7 +64,7 @@ public VSGitExt(IServiceProvider serviceProvider, IVSUIContextFactory factory, I async Task InitializeAsync() { - gitService = await GetServiceAsync(); + gitExt = await GetServiceAsync(); if (gitService == null) { log.Error("Couldn't find IGitExt service"); @@ -74,9 +74,9 @@ async Task InitializeAsync() // Refresh on background thread await Task.Run(() => RefreshActiveRepositories()); - gitService.PropertyChanged += (s, e) => + gitExt.PropertyChanged += (s, e) => { - if (e.PropertyName == nameof(gitService.ActiveRepositories)) + if (e.PropertyName == nameof(gitExt.ActiveRepositories)) { RefreshActiveRepositories(); } @@ -91,10 +91,10 @@ public void RefreshActiveRepositories() { log.Debug( "IGitExt.ActiveRepositories (#{Id}) returned {Repositories}", - gitService.GetHashCode(), - gitService.ActiveRepositories.Select(x => x.RepositoryPath)); + gitExt.GetHashCode(), + gitExt.ActiveRepositories.Select(x => x.RepositoryPath)); - ActiveRepositories = gitService?.ActiveRepositories.Select(x => repositoryFactory.Create(x.RepositoryPath)).ToList(); + ActiveRepositories = gitExt?.ActiveRepositories.Select(x => gitService.CreateLocalRepositoryModel(x.RepositoryPath)).ToList(); } } catch (Exception e) diff --git a/src/GitHub.TeamFoundation.15/GitHub.TeamFoundation.15.csproj b/src/GitHub.TeamFoundation.15/GitHub.TeamFoundation.15.csproj index 0f872555d1..b8a8b29374 100644 --- a/src/GitHub.TeamFoundation.15/GitHub.TeamFoundation.15.csproj +++ b/src/GitHub.TeamFoundation.15/GitHub.TeamFoundation.15.csproj @@ -180,9 +180,6 @@ RegistryHelper.cs - - Services\LocalRepositoryModelFactory.cs - Services\VSGitExt.cs diff --git a/src/GitHub.TeamFoundation.16/GitHub.TeamFoundation.16.csproj b/src/GitHub.TeamFoundation.16/GitHub.TeamFoundation.16.csproj index 5e727e3fed..5f7b3d4c9a 100644 --- a/src/GitHub.TeamFoundation.16/GitHub.TeamFoundation.16.csproj +++ b/src/GitHub.TeamFoundation.16/GitHub.TeamFoundation.16.csproj @@ -180,9 +180,6 @@ RegistryHelper.cs - - Services\LocalRepositoryModelFactory.cs - Services\VSGitExt.cs diff --git a/src/GitHub.VisualStudio/GitHubPackage.cs b/src/GitHub.VisualStudio/GitHubPackage.cs index 741b9ccfe8..f8fff137dd 100644 --- a/src/GitHub.VisualStudio/GitHubPackage.cs +++ b/src/GitHub.VisualStudio/GitHubPackage.cs @@ -299,7 +299,7 @@ async Task CreateService(IAsyncServiceContainer container, CancellationT else if (serviceType == typeof(IVSGitExt)) { var vsVersion = ApplicationInfo.GetHostVersionInfo().FileMajorPart; - return new VSGitExtFactory(vsVersion, this).Create(); + return new VSGitExtFactory(vsVersion, this, GitService.GitServiceHelper).Create(); } else if (serviceType == typeof(IGitHubToolWindowManager)) { diff --git a/src/GitHub.VisualStudio/Services/VSGitExtFactory.cs b/src/GitHub.VisualStudio/Services/VSGitExtFactory.cs index 928eb96d1d..1464d32c02 100644 --- a/src/GitHub.VisualStudio/Services/VSGitExtFactory.cs +++ b/src/GitHub.VisualStudio/Services/VSGitExtFactory.cs @@ -17,11 +17,13 @@ public class VSGitExtFactory readonly int vsVersion; readonly IServiceProvider serviceProvider; + readonly IGitService gitService; - public VSGitExtFactory(int vsVersion, IServiceProvider serviceProvider) + public VSGitExtFactory(int vsVersion, IServiceProvider serviceProvider, IGitService gitService) { this.vsVersion = vsVersion; this.serviceProvider = serviceProvider; + this.gitService = gitService; } public IVSGitExt Create() @@ -29,11 +31,11 @@ public IVSGitExt Create() switch (vsVersion) { case 14: - return Create(() => new VSGitExt14(serviceProvider)); + return Create(() => new VSGitExt14(serviceProvider, gitService)); case 15: - return Create(() => new VSGitExt15(serviceProvider)); + return Create(() => new VSGitExt15(serviceProvider, gitService)); case 16: - return Create(() => new VSGitExt16(serviceProvider)); + return Create(() => new VSGitExt16(serviceProvider, gitService)); default: log.Error("There is no IVSGitExt implementation for DTE version {Version}", vsVersion); return null; diff --git a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs index 7b9ee71c58..283bc2f76d 100644 --- a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs +++ b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs @@ -10,10 +10,12 @@ using NUnit.Framework; using NSubstitute; using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility; -using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Threading; using Task = System.Threading.Tasks.Task; using static Microsoft.VisualStudio.VSConstants; +using GitHub.Primitives; +using LibGit2Sharp; +using System.Threading.Tasks; public class VSGitExtTests { @@ -149,32 +151,32 @@ public void RepositoryOpenContextNotActive_IsEmpty() public void RepositoryOpenIsActive_InitializeWithActiveRepositories() { var repoPath = "repoPath"; - var repoFactory = Substitute.For(); + var gitService = Substitute.For(); var context = CreateVSUIContext(true); var gitExt = CreateGitExt(new[] { repoPath }); - var target = CreateVSGitExt(context, gitExt, repoFactory: repoFactory); + var target = CreateVSGitExt(context, gitExt, gitService: gitService); target.JoinTillEmpty(); var activeRepositories = target.ActiveRepositories; Assert.That(activeRepositories.Count, Is.EqualTo(1)); - repoFactory.Received(1).Create(repoPath); + gitService.Received(1).CreateLocalRepositoryModel(repoPath); } [Test] public void ExceptionRefreshingRepositories_ReturnsEmptyList() { var repoPath = "repoPath"; - var repoFactory = Substitute.For(); - repoFactory.Create(repoPath).ReturnsForAnyArgs(x => { throw new Exception("Boom!"); }); + var gitService = Substitute.For(); + gitService.CreateLocalRepositoryModel(repoPath).ReturnsForAnyArgs(x => { throw new Exception("Boom!"); }); var context = CreateVSUIContext(true); var gitExt = CreateGitExt(new[] { repoPath }); - var target = CreateVSGitExt(context, gitExt, repoFactory: repoFactory); + var target = CreateVSGitExt(context, gitExt, gitService: gitService); target.JoinTillEmpty(); var activeRepositories = target.ActiveRepositories; - repoFactory.Received(1).Create(repoPath); + gitService.Received(1).CreateLocalRepositoryModel(repoPath); Assert.That(activeRepositories.Count, Is.EqualTo(0)); } @@ -182,8 +184,8 @@ public void ExceptionRefreshingRepositories_ReturnsEmptyList() public async Task ActiveRepositoriesChangedOrderingShouldBeCorrectAcrossThreads() { var gitExt = new MockGitExt(); - var repoFactory = new MockRepositoryFactory(); - var target = CreateVSGitExt(gitExt: gitExt, repoFactory: repoFactory); + var gitService = new MockGitService(); + var target = CreateVSGitExt(gitExt: gitExt, gitService: gitService); var activeRepositories1 = CreateActiveRepositories("repo1"); var activeRepositories2 = CreateActiveRepositories("repo2"); var task1 = Task.Run(() => gitExt.ActiveRepositories = activeRepositories1); @@ -211,18 +213,18 @@ static IReadOnlyList CreateActiveRepositories(params string[ } static VSGitExt CreateVSGitExt(IVSUIContext context = null, IGitExt gitExt = null, IServiceProvider sp = null, - ILocalRepositoryModelFactory repoFactory = null, JoinableTaskContext joinableTaskContext = null, string contextGuidString = null) + IGitService gitService = null, JoinableTaskContext joinableTaskContext = null, string contextGuidString = null) { context = context ?? CreateVSUIContext(true); gitExt = gitExt ?? CreateGitExt(); var contextGuid = new Guid(contextGuidString ?? Guids.GitSccProviderId); sp = sp ?? Substitute.For(); - repoFactory = repoFactory ?? Substitute.For(); + gitService = gitService ?? Substitute.For(); joinableTaskContext = joinableTaskContext ?? new JoinableTaskContext(); var factory = Substitute.For(); factory.GetUIContext(contextGuid).Returns(context); sp.GetService(typeof(IGitExt)).Returns(gitExt); - var vsGitExt = new VSGitExt(sp, factory, repoFactory, joinableTaskContext); + var vsGitExt = new VSGitExt(sp, factory, gitService, joinableTaskContext); vsGitExt.JoinTillEmpty(); return vsGitExt; } @@ -291,9 +293,9 @@ public IReadOnlyList ActiveRepositories public event PropertyChangedEventHandler PropertyChanged; } - class MockRepositoryFactory : ILocalRepositoryModelFactory + class MockGitService : IGitService { - public ILocalRepositoryModel Create(string localPath) + public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) { var result = Substitute.For(); result.LocalPath.Returns(localPath); @@ -308,5 +310,13 @@ public ILocalRepositoryModel Create(string localPath) return result; } + + public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) => throw new NotImplementedException(); + public Task GetLatestPushedSha(string path, string remote = "origin") => throw new NotImplementedException(); + public UriString GetRemoteUri(IRepository repo, string remote = "origin") => throw new NotImplementedException(); + public IRepository GetRepository(string path) => throw new NotImplementedException(); + public UriString GetUri(IRepository repository, string remote = "origin") => throw new NotImplementedException(); + public UriString GetUri(string path, string remote = "origin") => throw new NotImplementedException(); + public void Refresh(ILocalRepositoryModel localRepositoryModel) => throw new NotImplementedException(); } } From a4c83863b94da433229118c29ba7f49a80455e06 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Wed, 31 Oct 2018 17:36:04 +0000 Subject: [PATCH 20/39] Rename IGitService.Refresh to RefreshCloneUrl Be explicit about what it does. --- src/GitHub.App/SampleData/GitServiceDesigner.cs | 2 +- src/GitHub.Exports/Services/GitService.cs | 2 +- src/GitHub.Exports/Services/IGitService.cs | 2 +- src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs | 2 +- test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index 6d90eaacbb..014b79e3fa 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -10,7 +10,7 @@ class GitServiceDesigner : IGitService { public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) => null; - public void Refresh(ILocalRepositoryModel localRepositoryModel) { } + public void RefreshCloneUrl(ILocalRepositoryModel localRepositoryModel) { } public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; public IRepository GetRepository(string path) => null; diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 2fee66dff7..053821dfce 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -71,7 +71,7 @@ public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) /// /// Updates the CloneUrl from the "origin" remote. /// - public void Refresh(ILocalRepositoryModel localRepositoryModel) + public void RefreshCloneUrl(ILocalRepositoryModel localRepositoryModel) { var localPath = localRepositoryModel.LocalPath; if (localPath == null) diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 96a0f044dc..85209e34dc 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -25,7 +25,7 @@ public interface IGitService /// Updates the CloneUrl information based on the "origin" remote. /// /// The repository model to refresh. - void Refresh(ILocalRepositoryModel localRepositoryModel); + void RefreshCloneUrl(ILocalRepositoryModel localRepositoryModel); /// /// Returns the URL of the remote for the specified . If the repository diff --git a/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs b/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs index db91cfbe9b..d4f7b0ba6d 100644 --- a/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs +++ b/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs @@ -113,7 +113,7 @@ public void Subscribe(object who, Action handler) // for that, so this is a good place to refresh it in case that happened if (repo != null) { - gitService.Refresh(repo); + gitService.RefreshCloneUrl(repo); } // if the active repo hasn't changed and there's notifications queued up, diff --git a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs index 283bc2f76d..afe09c6cd8 100644 --- a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs +++ b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs @@ -317,6 +317,6 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) public IRepository GetRepository(string path) => throw new NotImplementedException(); public UriString GetUri(IRepository repository, string remote = "origin") => throw new NotImplementedException(); public UriString GetUri(string path, string remote = "origin") => throw new NotImplementedException(); - public void Refresh(ILocalRepositoryModel localRepositoryModel) => throw new NotImplementedException(); + public void RefreshCloneUrl(ILocalRepositoryModel localRepositoryModel) => throw new NotImplementedException(); } } From eb7f1dba0c51581b7c4c58383ae00fde9ae87f02 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Thu, 1 Nov 2018 13:22:12 +0000 Subject: [PATCH 21/39] Remove repo watching responsibilities from TESH Make ITeamExplorerServiceHolder responsible for holding references to services, but not watching for and marshaling repository change events. Delegate to ITeamExplorerContext for this. --- .../Services/ITeamExplorerServiceHolder.cs | 21 +--- .../Base/TeamExplorerNavigationItemBase.cs | 34 ++++- .../Base/TeamExplorerServiceHolder.cs | 118 +----------------- .../Connect/GitHubConnectSection.cs | 14 ++- .../Base/TeamExplorerItemBase.cs | 48 +++++-- .../Commands/LinkCommandBase.cs | 4 +- 6 files changed, 91 insertions(+), 148 deletions(-) diff --git a/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs b/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs index dd6ca75bd1..472a24f6ee 100644 --- a/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs +++ b/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs @@ -1,6 +1,7 @@ using System; using GitHub.Primitives; using GitHub.Models; +using Microsoft.VisualStudio.Threading; namespace GitHub.Services { @@ -17,6 +18,7 @@ public interface ITeamExplorerServiceHolder /// changes in the source control context. /// IServiceProvider ServiceProvider { get; set; } + /// /// Clears the current ServiceProvider if it matches the one that is passed in. /// This is usually called on Dispose, which might happen after another section @@ -25,21 +27,10 @@ public interface ITeamExplorerServiceHolder /// /// If the current ServiceProvider matches this, clear it void ClearServiceProvider(IServiceProvider provider); - /// - /// A IGitRepositoryInfo representing the currently active repository - /// - ILocalRepositoryModel ActiveRepo { get; } - /// - /// Subscribe to be notified when the active repository is set and Notify is called. - /// - /// The instance that is interested in being called (or a unique key/object for that instance) - /// The handler to call when ActiveRepo is set - void Subscribe(object who, Action handler); - /// - /// Unsubscribe from notifications - /// - /// The instance/key that previously subscribed to notifications - void Unsubscribe(object who); + + ITeamExplorerContext TeamExplorerContext { get; } + + JoinableTaskFactory JoinableTaskFactory { get; } IGitAwareItem HomeSection { get; } } diff --git a/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs b/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs index f8b73819db..518908e81d 100644 --- a/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs +++ b/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Drawing; +using System.ComponentModel; using GitHub.Api; using GitHub.Extensions; using GitHub.Services; @@ -14,6 +15,7 @@ namespace GitHub.VisualStudio.Base { public class TeamExplorerNavigationItemBase : TeamExplorerItemBase, ITeamExplorerNavigationItem2 { + readonly ITeamExplorerServiceHolder holder; readonly Octicon octicon; public TeamExplorerNavigationItemBase(IGitHubServiceProvider serviceProvider, @@ -24,6 +26,7 @@ public TeamExplorerNavigationItemBase(IGitHubServiceProvider serviceProvider, Guard.ArgumentNotNull(apiFactory, nameof(apiFactory)); Guard.ArgumentNotNull(holder, nameof(holder)); + this.holder = holder; this.octicon = octicon; IsVisible = false; @@ -36,7 +39,31 @@ public TeamExplorerNavigationItemBase(IGitHubServiceProvider serviceProvider, Invalidate(); }; - holder.Subscribe(this, UpdateRepo); + UpdateRepo(holder.TeamExplorerContext.ActiveRepository); + holder.TeamExplorerContext.PropertyChanged += TeamExplorerContext_PropertyChanged; + holder.TeamExplorerContext.StatusChanged += TeamExplorerContext_StatusChanged; ; + } + + void TeamExplorerContext_StatusChanged(object sender, EventArgs e) + { + UpdateRepoOnMainThread(holder.TeamExplorerContext.ActiveRepository); + } + + void TeamExplorerContext_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(holder.TeamExplorerContext.ActiveRepository)) + { + UpdateRepoOnMainThread(holder.TeamExplorerContext.ActiveRepository); + } + } + + void UpdateRepoOnMainThread(ILocalRepositoryModel repo) + { + holder.JoinableTaskFactory.RunAsync(async () => + { + await holder.JoinableTaskFactory.SwitchToMainThreadAsync(); + UpdateRepo(repo); + }).Task.Forget(); } public override async void Invalidate() @@ -75,7 +102,8 @@ protected void OpenInBrowser(Lazy browser, string endpoint void Unsubscribe() { - holder.Unsubscribe(this); + holder.TeamExplorerContext.PropertyChanged -= TeamExplorerContext_PropertyChanged; + holder.TeamExplorerContext.StatusChanged -= TeamExplorerContext_StatusChanged; ; } bool disposed; @@ -109,7 +137,7 @@ public object Icon Image image; public Image Image { - get{ return image; } + get { return image; } set { image = value; this.RaisePropertyChange(); } } } diff --git a/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs b/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs index d4f7b0ba6d..a1ee3ebf1c 100644 --- a/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs +++ b/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs @@ -1,16 +1,12 @@ using System; -using System.Collections.Generic; using System.ComponentModel.Composition; -using System.Linq; using GitHub.Extensions; using GitHub.Logging; -using GitHub.Models; using GitHub.Services; using Serilog; using Microsoft.TeamFoundation.Controls; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Threading; -using System.Windows; namespace GitHub.VisualStudio.Base { @@ -20,20 +16,15 @@ public class TeamExplorerServiceHolder : ITeamExplorerServiceHolder { static readonly ILogger log = LogManager.ForContext(); - readonly Dictionary> activeRepoHandlers = new Dictionary>(); - ILocalRepositoryModel activeRepo; - bool activeRepoNotified = false; - IServiceProvider serviceProvider; - readonly IVSGitExt gitExt; - readonly IGitService gitService; /// /// This class relies on IVSGitExt that provides information when VS switches repositories. /// /// Used for monitoring the active repository. [ImportingConstructor] - TeamExplorerServiceHolder(IVSGitExt gitExt, IGitService gitService) : this(gitExt, gitService, ThreadHelper.JoinableTaskContext) + TeamExplorerServiceHolder(ITeamExplorerContext teamExplorerContext) : + this(teamExplorerContext, ThreadHelper.JoinableTaskContext) { } @@ -42,23 +33,13 @@ public class TeamExplorerServiceHolder : ITeamExplorerServiceHolder /// /// Used for monitoring the active repository. /// Used for switching to the Main thread. - public TeamExplorerServiceHolder(IVSGitExt gitExt, IGitService gitService, JoinableTaskContext joinableTaskContext) + public TeamExplorerServiceHolder(ITeamExplorerContext teamExplorerContext, JoinableTaskContext joinableTaskContext) { JoinableTaskCollection = joinableTaskContext.CreateCollection(); JoinableTaskCollection.DisplayName = nameof(TeamExplorerServiceHolder); JoinableTaskFactory = joinableTaskContext.CreateFactory(JoinableTaskCollection); - // HACK: This might be null in SafeMode. - // We should be throwing rather than returning a null MEF service. - if (gitExt == null) - { - return; - } - - this.gitExt = gitExt; - this.gitService = gitService; - UpdateActiveRepo(); - gitExt.ActiveRepositoriesChanged += UpdateActiveRepo; + TeamExplorerContext = teamExplorerContext; } // set by the sections when they get initialized @@ -76,61 +57,6 @@ public IServiceProvider ServiceProvider } } - public ILocalRepositoryModel ActiveRepo - { - get { return activeRepo; } - private set - { - if (activeRepo == value) - return; - if (activeRepo != null) - activeRepo.PropertyChanged -= ActiveRepoPropertyChanged; - activeRepo = value; - if (activeRepo != null) - activeRepo.PropertyChanged += ActiveRepoPropertyChanged; - NotifyActiveRepo(); - } - } - - public void Subscribe(object who, Action handler) - { - Guard.ArgumentNotNull(who, nameof(who)); - Guard.ArgumentNotNull(handler, nameof(handler)); - - bool notificationsExist; - ILocalRepositoryModel repo; - lock (activeRepoHandlers) - { - repo = ActiveRepo; - notificationsExist = activeRepoNotified; - if (!activeRepoHandlers.ContainsKey(who)) - activeRepoHandlers.Add(who, handler); - else - activeRepoHandlers[who] = handler; - } - - // the repo url might have changed and we don't get notifications - // for that, so this is a good place to refresh it in case that happened - if (repo != null) - { - gitService.RefreshCloneUrl(repo); - } - - // if the active repo hasn't changed and there's notifications queued up, - // notify the subscriber. If the repo has changed, the set above will trigger - // notifications so we don't have to do it here. - if (repo == ActiveRepo && notificationsExist) - handler(repo); - } - - public void Unsubscribe(object who) - { - Guard.ArgumentNotNull(who, nameof(who)); - - if (activeRepoHandlers.ContainsKey(who)) - activeRepoHandlers.Remove(who); - } - /// /// Clears the current ServiceProvider if it matches the one that is passed in. /// This is usually called on Dispose, which might happen after another section @@ -148,39 +74,6 @@ public void ClearServiceProvider(IServiceProvider provider) ServiceProvider = null; } - void NotifyActiveRepo() - { - lock (activeRepoHandlers) - { - activeRepoNotified = true; - foreach (var handler in activeRepoHandlers.Values) - handler(activeRepo); - } - } - - void UpdateActiveRepo() - { - var repo = gitExt.ActiveRepositories.FirstOrDefault(); - - if (!Equals(repo, ActiveRepo)) - { - // Fire property change events on Main thread - JoinableTaskFactory.RunAsync(async () => - { - await JoinableTaskFactory.SwitchToMainThreadAsync(); - ActiveRepo = repo; - }).Task.Forget(log); - } - } - - void ActiveRepoPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) - { - Guard.ArgumentNotNull(e, nameof(e)); - - if (e.PropertyName == "CloneUrl") - ActiveRepo = sender as ILocalRepositoryModel; - } - public IGitAwareItem HomeSection { get @@ -200,6 +93,7 @@ ITeamExplorerPage PageService } public JoinableTaskCollection JoinableTaskCollection { get; } - JoinableTaskFactory JoinableTaskFactory { get; } + public JoinableTaskFactory JoinableTaskFactory { get; } + public ITeamExplorerContext TeamExplorerContext { get; } } } diff --git a/src/GitHub.TeamFoundation.14/Connect/GitHubConnectSection.cs b/src/GitHub.TeamFoundation.14/Connect/GitHubConnectSection.cs index bc0ef22a01..d93a1c9666 100644 --- a/src/GitHub.TeamFoundation.14/Connect/GitHubConnectSection.cs +++ b/src/GitHub.TeamFoundation.14/Connect/GitHubConnectSection.cs @@ -28,6 +28,8 @@ namespace GitHub.VisualStudio.TeamExplorer.Connect public class GitHubConnectSection : TeamExplorerSectionBase, IGitHubConnectSection { static readonly ILogger log = LogManager.ForContext(); + readonly ISimpleApiClientFactory apiFactory; + readonly ITeamExplorerServiceHolder holder; readonly IPackageSettings packageSettings; readonly ITeamExplorerServices teamExplorerServices; readonly int sectionIndex; @@ -101,8 +103,6 @@ public ILocalRepositoryModel SelectedRepository public ICommand Clone { get; } - internal ITeamExplorerServiceHolder Holder => holder; - public GitHubConnectSection(IGitHubServiceProvider serviceProvider, ISimpleApiClientFactory apiFactory, ITeamExplorerServiceHolder holder, @@ -127,6 +127,8 @@ public GitHubConnectSection(IGitHubServiceProvider serviceProvider, IsVisible = false; sectionIndex = index; + this.apiFactory = apiFactory; + this.holder = holder; this.packageSettings = packageSettings; this.teamExplorerServices = teamExplorerServices; this.localRepositories = localRepositories; @@ -325,7 +327,7 @@ async void UpdateRepositoryList(object sender, NotifyCollectionChangedEventArgs try { // TODO: Cache the icon state. - var api = await ApiFactory.Create(newrepo.CloneUrl); + var api = await apiFactory.Create(newrepo.CloneUrl); var repo = await api.GetRepository(); newrepo.SetIcon(repo.Private, repo.Fork); } @@ -344,13 +346,13 @@ async void UpdateRepositoryList(object sender, NotifyCollectionChangedEventArgs .Cast() .ForEach(async r => { - if (Equals(Holder.ActiveRepo, r)) + if (Equals(holder.TeamExplorerContext.ActiveRepository, r)) SelectedRepository = r; try { // TODO: Cache the icon state. - var api = await ApiFactory.Create(r.CloneUrl); + var api = await apiFactory.Create(r.CloneUrl); var repo = await api.GetRepository(); r.SetIcon(repo.Private, repo.Fork); } @@ -457,7 +459,7 @@ public void Retry() public bool OpenRepository() { - var old = Repositories.FirstOrDefault(x => x.Equals(Holder.ActiveRepo)); + var old = Repositories.FirstOrDefault(x => x.Equals(holder.TeamExplorerContext.ActiveRepository)); if (!Equals(SelectedRepository, old)) { try diff --git a/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs b/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs index 917a0b7fee..a92a057445 100644 --- a/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs +++ b/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs @@ -9,13 +9,14 @@ using GitHub.ViewModels; using GitHub.VisualStudio.UI; using GitHub.Extensions; +using System.ComponentModel; namespace GitHub.VisualStudio.Base { public class TeamExplorerItemBase : TeamExplorerGitRepoInfo, IServiceProviderAware { + readonly ITeamExplorerServiceHolder holder; readonly ISimpleApiClientFactory apiFactory; - protected ITeamExplorerServiceHolder holder; ISimpleApiClient simpleApiClient; public ISimpleApiClient SimpleApiClient @@ -29,8 +30,6 @@ public ISimpleApiClient SimpleApiClient } } - protected ISimpleApiClientFactory ApiFactory => apiFactory; - public TeamExplorerItemBase(IGitHubServiceProvider serviceProvider, ITeamExplorerServiceHolder holder) : base(serviceProvider) { @@ -75,21 +74,51 @@ public virtual void Invalidate() void SubscribeToRepoChanges() { - holder.Subscribe(this, (ILocalRepositoryModel repo) => + UpdateRepo(holder.TeamExplorerContext.ActiveRepository); + holder.TeamExplorerContext.PropertyChanged += TeamExplorerContext_PropertyChanged; + holder.TeamExplorerContext.StatusChanged += TeamExplorerContext_StatusChanged; + } + + void TeamExplorerContext_StatusChanged(object sender, EventArgs e) + { + UpdateRepoOnMainThread(holder.TeamExplorerContext.ActiveRepository); + } + + void TeamExplorerContext_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(holder.TeamExplorerContext.ActiveRepository)) { - var changed = !Equals(ActiveRepo, repo); - ActiveRepo = repo; - RepoChanged(changed); - }); + UpdateRepoOnMainThread(holder.TeamExplorerContext.ActiveRepository); + } + } + + void UpdateRepoOnMainThread(ILocalRepositoryModel repo) + { + holder.JoinableTaskFactory.RunAsync(async () => + { + await holder.JoinableTaskFactory.SwitchToMainThreadAsync(); + UpdateRepo(repo); + }).Task.Forget(); } void Unsubscribe() { - holder.Unsubscribe(this); + //holder.Unsubscribe(this); + holder.TeamExplorerContext.PropertyChanged -= TeamExplorerContext_PropertyChanged; + holder.TeamExplorerContext.StatusChanged -= TeamExplorerContext_StatusChanged; + if (TEServiceProvider != null) holder.ClearServiceProvider(TEServiceProvider); } + void UpdateRepo(ILocalRepositoryModel repo) + { + var changed = ActiveRepo != repo; + ActiveRepo = repo; + RepoChanged(changed); + Invalidate(); + } + protected virtual void RepoChanged(bool changed) { var repo = ActiveRepo; @@ -198,6 +227,5 @@ public string Text get { return text; } set { text = value; this.RaisePropertyChange(); } } - } } \ No newline at end of file diff --git a/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs b/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs index d1abe4f1d4..6d94938629 100644 --- a/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs +++ b/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs @@ -63,7 +63,7 @@ protected ILocalRepositoryModel GetRepositoryByPath(string path) protected ILocalRepositoryModel GetActiveRepo() { - var activeRepo = ServiceProvider.TryGetService()?.ActiveRepo; + var activeRepo = ServiceProvider.TryGetService()?.TeamExplorerContext.ActiveRepository; // activeRepo can be null at this point because it is set elsewhere as the result of async operation that may not have completed yet. if (activeRepo == null) { @@ -82,7 +82,7 @@ protected ILocalRepositoryModel GetActiveRepo() void RefreshRepo() { - ActiveRepo = ServiceProvider.TryGetService().ActiveRepo; + ActiveRepo = ServiceProvider.TryGetService()?.TeamExplorerContext.ActiveRepository; if (ActiveRepo == null) { From 925279f7097ca9c4f1d84e0ce3555b85e3e7ec88 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Thu, 1 Nov 2018 13:28:33 +0000 Subject: [PATCH 22/39] Remove obsolete RefreshCloneUrl API This is no longer called by TeamExplorerServiceHolder. --- src/GitHub.App/SampleData/GitServiceDesigner.cs | 1 - src/GitHub.Exports/Services/GitService.cs | 12 ------------ src/GitHub.Exports/Services/IGitService.cs | 6 ------ .../GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs | 1 - 4 files changed, 20 deletions(-) diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index 014b79e3fa..cf6a5a4a7d 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -10,7 +10,6 @@ class GitServiceDesigner : IGitService { public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) => null; - public void RefreshCloneUrl(ILocalRepositoryModel localRepositoryModel) { } public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; public IRepository GetRepository(string path) => null; diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 053821dfce..d866a0a55f 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -68,18 +68,6 @@ public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) } } - /// - /// Updates the CloneUrl from the "origin" remote. - /// - public void RefreshCloneUrl(ILocalRepositoryModel localRepositoryModel) - { - var localPath = localRepositoryModel.LocalPath; - if (localPath == null) - return; - - localRepositoryModel.CloneUrl = GetUri(localPath); - } - /// /// Returns the URL of the remote for the specified . If the repository /// is null or no remote named origin exists, this method returns null diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 85209e34dc..c9d54a3726 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -21,12 +21,6 @@ public interface IGitService /// A new branch model. IBranch CreateCurrentBranchModel(ILocalRepositoryModel model); - /// - /// Updates the CloneUrl information based on the "origin" remote. - /// - /// The repository model to refresh. - void RefreshCloneUrl(ILocalRepositoryModel localRepositoryModel); - /// /// Returns the URL of the remote for the specified . If the repository /// is null or no remote exists, this method returns null diff --git a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs index afe09c6cd8..d5db84b3c4 100644 --- a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs +++ b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs @@ -317,6 +317,5 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) public IRepository GetRepository(string path) => throw new NotImplementedException(); public UriString GetUri(IRepository repository, string remote = "origin") => throw new NotImplementedException(); public UriString GetUri(string path, string remote = "origin") => throw new NotImplementedException(); - public void RefreshCloneUrl(ILocalRepositoryModel localRepositoryModel) => throw new NotImplementedException(); } } From c16c91c6557739dc2b0a5da9052d1f20d5544fd9 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Thu, 1 Nov 2018 14:13:21 +0000 Subject: [PATCH 23/39] Remove unused logger --- .../Base/TeamExplorerServiceHolder.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs b/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs index a1ee3ebf1c..8d6f002b69 100644 --- a/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs +++ b/src/GitHub.TeamFoundation.14/Base/TeamExplorerServiceHolder.cs @@ -1,9 +1,7 @@ using System; using System.ComponentModel.Composition; using GitHub.Extensions; -using GitHub.Logging; using GitHub.Services; -using Serilog; using Microsoft.TeamFoundation.Controls; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Threading; @@ -14,8 +12,6 @@ namespace GitHub.VisualStudio.Base [PartCreationPolicy(CreationPolicy.Shared)] public class TeamExplorerServiceHolder : ITeamExplorerServiceHolder { - static readonly ILogger log = LogManager.ForContext(); - IServiceProvider serviceProvider; /// From 5fddfa8e973eb58917900883a96202eac78ef36e Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Thu, 1 Nov 2018 14:16:07 +0000 Subject: [PATCH 24/39] Add xmldocs to ITeamExplorerServiceHolder --- src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs b/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs index 472a24f6ee..c0ed91a252 100644 --- a/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs +++ b/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs @@ -28,8 +28,14 @@ public interface ITeamExplorerServiceHolder /// If the current ServiceProvider matches this, clear it void ClearServiceProvider(IServiceProvider provider); + /// + /// A service that can be used for repository changed events. + /// ITeamExplorerContext TeamExplorerContext { get; } + /// + /// A service for avoiding deadlocks and marshaling tasks onto the UI thread. + /// JoinableTaskFactory JoinableTaskFactory { get; } IGitAwareItem HomeSection { get; } From 2b160f80ca769c017c51a2cc6113489b337d7fed Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Thu, 1 Nov 2018 15:28:21 +0000 Subject: [PATCH 25/39] Fix error CA2214 Contains a call chain that results in a call to a virtual method defined by the class. --- .../Base/TeamExplorerNavigationItemBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs b/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs index 518908e81d..3bcfe6f458 100644 --- a/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs +++ b/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs @@ -39,9 +39,9 @@ public TeamExplorerNavigationItemBase(IGitHubServiceProvider serviceProvider, Invalidate(); }; - UpdateRepo(holder.TeamExplorerContext.ActiveRepository); + ActiveRepo = holder.TeamExplorerContext.ActiveRepository; holder.TeamExplorerContext.PropertyChanged += TeamExplorerContext_PropertyChanged; - holder.TeamExplorerContext.StatusChanged += TeamExplorerContext_StatusChanged; ; + holder.TeamExplorerContext.StatusChanged += TeamExplorerContext_StatusChanged; } void TeamExplorerContext_StatusChanged(object sender, EventArgs e) From bf4c2f9026d69b23986ea2a12660cf96746d5180 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Thu, 1 Nov 2018 16:03:07 +0000 Subject: [PATCH 26/39] Remove commented out code --- src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs b/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs index a92a057445..3094aab45a 100644 --- a/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs +++ b/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs @@ -103,7 +103,6 @@ void UpdateRepoOnMainThread(ILocalRepositoryModel repo) void Unsubscribe() { - //holder.Unsubscribe(this); holder.TeamExplorerContext.PropertyChanged -= TeamExplorerContext_PropertyChanged; holder.TeamExplorerContext.StatusChanged -= TeamExplorerContext_StatusChanged; From 1d92befc7432c8284b2ecf61acf60033fd935ffb Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 2 Nov 2018 11:58:44 +0000 Subject: [PATCH 27/39] Add comment about when StatusChanged fires Make log message a bit less bit yoda-y. --- src/GitHub.App/Services/TeamExplorerContext.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/GitHub.App/Services/TeamExplorerContext.cs b/src/GitHub.App/Services/TeamExplorerContext.cs index ecbaddf742..08b82c08d5 100644 --- a/src/GitHub.App/Services/TeamExplorerContext.cs +++ b/src/GitHub.App/Services/TeamExplorerContext.cs @@ -129,7 +129,8 @@ async Task RefreshAsync() } else if (newRepositoryPath != null) { - log.Debug("Fire StatusChanged event when on a repository and anything changes"); + // For example, this will fire when the HEAD commit changes + log.Debug("Fire StatusChanged event if anything about an active repository has changed"); StatusChanged?.Invoke(this, EventArgs.Empty); } From bccfbd07cb9d4b5136a167768f73c2f8a87285bd Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 2 Nov 2018 12:29:10 +0000 Subject: [PATCH 28/39] Rename CreateCurrentBranchModel to GetBranch --- src/GitHub.App/SampleData/GitServiceDesigner.cs | 2 +- .../ViewModels/GitHubPane/PullRequestCreationViewModel.cs | 4 ++-- .../ViewModels/GitHubPane/PullRequestDetailViewModel.cs | 2 +- src/GitHub.Exports/Services/GitService.cs | 2 +- src/GitHub.Exports/Services/IGitService.cs | 2 +- src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs | 2 +- .../GitHubPane/PullRequestCreationViewModelTests.cs | 2 +- .../ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs | 2 +- test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs | 2 +- .../Commands/OpenFromClipboardCommandTests.cs | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index cf6a5a4a7d..ef5c284285 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -9,7 +9,7 @@ namespace GitHub.SampleData class GitServiceDesigner : IGitService { public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; - public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) => null; + public IBranch GetBranch(ILocalRepositoryModel model) => null; public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; public IRepository GetRepository(string path) => null; diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index 764fc1ec10..cde9882b5a 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -142,7 +142,7 @@ public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection { modelService = await modelServiceFactory.CreateAsync(connection); activeLocalRepo = repository; - SourceBranch = gitService.CreateCurrentBranchModel(repository); + SourceBranch = gitService.GetBranch(repository); var obs = modelService.ApiClient.GetRepository(repository.Owner, repository.Name) .Select(r => new RemoteRepositoryModel(r)) @@ -212,7 +212,7 @@ async Task LoadInitialState(string draftKey) void LoadDescriptionFromCommits() { - SourceBranch = gitService.CreateCurrentBranchModel(activeLocalRepo); + SourceBranch = gitService.GetBranch(activeLocalRepo); var uniqueCommits = this.WhenAnyValue( x => x.SourceBranch, diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs index fc1f6dd703..363f8d81c8 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs @@ -405,7 +405,7 @@ public async Task Load(PullRequestDetailModel pullRequest) var localBranches = await pullRequestsService.GetLocalBranches(LocalRepository, pullRequest).ToList(); - var currentBranch = gitService.CreateCurrentBranchModel(LocalRepository); + var currentBranch = gitService.GetBranch(LocalRepository); IsCheckedOut = localBranches.Contains(currentBranch); if (IsCheckedOut) diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index d866a0a55f..5b8ea2fc52 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -52,7 +52,7 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) return model; } - public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) + public IBranch GetBranch(ILocalRepositoryModel model) { var localPath = model.LocalPath; using (var repo = GetRepository(localPath)) diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index c9d54a3726..7ebe6d6348 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -19,7 +19,7 @@ public interface IGitService /// /// The to create a current branch model for. /// A new branch model. - IBranch CreateCurrentBranchModel(ILocalRepositoryModel model); + IBranch GetBranch(ILocalRepositoryModel model); /// /// Returns the URL of the remote for the specified . If the repository diff --git a/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs b/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs index 73e77cea96..f0bb5358ff 100644 --- a/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs +++ b/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs @@ -99,7 +99,7 @@ public override async Task Execute(string url) if (hasChanges) { // TODO: What if this returns null because we're not on a branch? - var currentBranch = gitService.Value.CreateCurrentBranchModel(activeRepository); + var currentBranch = gitService.Value.GetBranch(activeRepository); var branchName = currentBranch.Name; // AnnotateFile expects a branch name so we use the current branch diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index 726566dae8..3be219088c 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -97,7 +97,7 @@ static TestData PrepareTestData( var targetRepo = targetRepoOwner == sourceRepoOwner ? sourceRepo : sourceRepo.Parent; var targetBranch = targetBranchName != targetRepo.DefaultBranch.Name ? new BranchModel(targetBranchName, targetRepo) : targetRepo.DefaultBranch; - gitService.CreateCurrentBranchModel(activeRepo).Returns(sourceBranch); + gitService.GetBranch(activeRepo).Returns(sourceBranch); api.GetRepository(Args.String, Args.String).Returns(Observable.Return(githubRepo)); ms.ApiClient.Returns(api); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs index fae1bd9fa7..d874e4e26e 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs @@ -553,7 +553,7 @@ static Tuple CreateTargetAndSer var repository = Substitute.For(); var currentBranchModel = new BranchModel(currentBranch, repository); var gitService = Substitute.For(); - gitService.CreateCurrentBranchModel(repository).Returns(currentBranchModel); + gitService.GetBranch(repository).Returns(currentBranchModel); repository.CloneUrl.Returns(new UriString(Uri.ToString())); repository.LocalPath.Returns(@"C:\projects\ThisRepo"); repository.Name.Returns("repo"); diff --git a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs index d5db84b3c4..e70c3cd918 100644 --- a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs +++ b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs @@ -311,7 +311,7 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) return result; } - public IBranch CreateCurrentBranchModel(ILocalRepositoryModel model) => throw new NotImplementedException(); + public IBranch GetBranch(ILocalRepositoryModel model) => throw new NotImplementedException(); public Task GetLatestPushedSha(string path, string remote = "origin") => throw new NotImplementedException(); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => throw new NotImplementedException(); public IRepository GetRepository(string path) => throw new NotImplementedException(); diff --git a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs index b43a203c74..062eebbcac 100644 --- a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs @@ -197,7 +197,7 @@ static OpenFromClipboardCommand CreateOpenFromClipboardCommand( var gitService = Substitute.For(); var currentBranch = Substitute.For(); currentBranch.Name.Returns(currentBranchName); - gitService.CreateCurrentBranchModel(activeRepository).Returns(currentBranch); + gitService.GetBranch(activeRepository).Returns(currentBranch); if (resolveBlobResult != null) { gitHubContextService.ResolveBlob(repositoryDir, contextFromClipboard).Returns(resolveBlobResult.Value); From b1db91ff9a5573017332a244e18fd8b73e5a0a00 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 2 Nov 2018 13:05:35 +0000 Subject: [PATCH 29/39] Remove IGitService dependency from BranchModel Removed dead and buggy code from BranchModel constructorer. We construct BranchModel from the HEAD branch, which isn't a remote branch. No need to construct a RepositoryModel from a URL. --- src/GitHub.Exports/Models/BranchModel.cs | 24 ++++++++--------------- src/GitHub.Exports/Services/GitService.cs | 12 ++++++++---- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/GitHub.Exports/Models/BranchModel.cs b/src/GitHub.Exports/Models/BranchModel.cs index b61bc61853..1e47eb883a 100644 --- a/src/GitHub.Exports/Models/BranchModel.cs +++ b/src/GitHub.Exports/Models/BranchModel.cs @@ -1,11 +1,18 @@ using System; using System.Globalization; -using GitHub.Services; namespace GitHub.Models { public class BranchModel : IBranch { + public BranchModel(string name, IRepositoryModel repo, string sha, bool isTracking, string trackedSha) : + this(name, repo) + { + IsTracking = isTracking; + Sha = sha; + TrackedSha = trackedSha; + } + public BranchModel(string name, IRepositoryModel repo) { Extensions.Guard.ArgumentNotEmptyString(name, nameof(name)); @@ -26,21 +33,6 @@ public BranchModel(Octokit.Branch branch, IRepositoryModel repo) Id = String.Format(CultureInfo.InvariantCulture, "{0}/{1}", Repository.Owner, Name); } - public BranchModel(LibGit2Sharp.Branch branch, IRepositoryModel repo, IGitService gitService) - { - Extensions.Guard.ArgumentNotNull(branch, nameof(branch)); - Extensions.Guard.ArgumentNotNull(repo, nameof(repo)); - Name = DisplayName = branch.FriendlyName; -#pragma warning disable 0618 // TODO: Replace `Branch.Remote` with `Repository.Network.Remotes[branch.RemoteName]`. - // NOTE: This method expects a localPath not a URL! - Repository = branch.IsRemote ? gitService.CreateLocalRepositoryModel(branch.Remote.Url) : repo; -#pragma warning restore 0618 - IsTracking = branch.IsTracking; - Sha = branch.Tip?.Sha; - TrackedSha = branch.TrackedBranch?.Tip?.Sha; - Id = String.Format(CultureInfo.InvariantCulture, "{0}/{1}", Repository.Owner, Name); - } - public string Id { get; private set; } public string Name { get; private set; } public IRepositoryModel Repository { get; private set; } diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 5b8ea2fc52..566a681cbc 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -57,14 +57,18 @@ public IBranch GetBranch(ILocalRepositoryModel model) var localPath = model.LocalPath; using (var repo = GetRepository(localPath)) { - var headBranch = repo?.Head; - if (headBranch == null) + var branch = repo?.Head; + if (branch == null) { return null; } - // BranchModel doesn't keep a reference to Repository - return new BranchModel(headBranch, model, this); + return new BranchModel( + name: branch.FriendlyName, + repo: model, + sha: branch.Tip?.Sha, + isTracking: branch.IsTracking, + trackedSha: branch.TrackedBranch?.Tip?.Sha); } } From 5765c18a295df7baaa0c1e9ba4917d9e2401cbcc Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 2 Nov 2018 13:11:15 +0000 Subject: [PATCH 30/39] Remove Octokit dependency from BranchModel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BranchModel is now a pure model. 🎉 --- src/GitHub.App/Services/ModelService.cs | 14 +++++++------- src/GitHub.Exports/Models/BranchModel.cs | 12 +----------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/GitHub.App/Services/ModelService.cs b/src/GitHub.App/Services/ModelService.cs index e35169d29c..90369b122c 100644 --- a/src/GitHub.App/Services/ModelService.cs +++ b/src/GitHub.App/Services/ModelService.cs @@ -270,7 +270,7 @@ public IObservable CreatePullRequest(ILocalRepositoryModel so new NewPullRequest(title, string.Format(CultureInfo.InvariantCulture, "{0}:{1}", sourceRepository.Owner, sourceBranch.Name), targetBranch.Name) - { Body = body }, + { Body = body }, targetRepository.Owner, targetRepository.Name) .Select(PullRequestCacheItem.Create) @@ -366,7 +366,7 @@ public IObservable GetBranches(IRepositoryModel repo) return Observable.Defer(() => keyobs .SelectMany(key => ApiClient.GetBranches(repo.CloneUrl.Owner, repo.CloneUrl.RepositoryName))) - .Select(x => new BranchModel(x, repo)); + .Select(x => new BranchModel(x.Name, repo)); } static GitIgnoreItem Create(GitIgnoreCacheItem item) @@ -452,7 +452,7 @@ public IObservable InsertUser(AccountCacheItem user) } protected virtual void Dispose(bool disposing) - {} + { } public void Dispose() { @@ -493,7 +493,7 @@ public static RepositoryCacheItem Create(Repository apiRepository) return new RepositoryCacheItem(apiRepository); } - public RepositoryCacheItem() {} + public RepositoryCacheItem() { } public RepositoryCacheItem(Repository apiRepository) { @@ -529,7 +529,7 @@ public static PullRequestCacheItem Create(PullRequest pr) return new PullRequestCacheItem(pr); } - public PullRequestCacheItem() {} + public PullRequestCacheItem() { } public PullRequestCacheItem(PullRequest pr) { @@ -563,7 +563,7 @@ public PullRequestCacheItem(PullRequest pr) Timestamp = UpdatedAt; } - public string Title {get; set; } + public string Title { get; set; } public int Number { get; set; } public GitReferenceCacheItem Base { get; set; } public GitReferenceCacheItem Head { get; set; } @@ -574,7 +574,7 @@ public PullRequestCacheItem(PullRequest pr) public DateTimeOffset CreatedAt { get; set; } public DateTimeOffset UpdatedAt { get; set; } public string Body { get; set; } - + // Nullable for compatibility with old caches. public PullRequestStateEnum? State { get; set; } diff --git a/src/GitHub.Exports/Models/BranchModel.cs b/src/GitHub.Exports/Models/BranchModel.cs index 1e47eb883a..0c7512c99e 100644 --- a/src/GitHub.Exports/Models/BranchModel.cs +++ b/src/GitHub.Exports/Models/BranchModel.cs @@ -20,17 +20,7 @@ public BranchModel(string name, IRepositoryModel repo) Name = DisplayName = name; Repository = repo; - Id = String.Format(CultureInfo.InvariantCulture, "{0}/{1}", Repository.Owner, Name); - } - - public BranchModel(Octokit.Branch branch, IRepositoryModel repo) - { - Extensions.Guard.ArgumentNotNull(branch, nameof(branch)); - Extensions.Guard.ArgumentNotNull(repo, nameof(repo)); - - Name = DisplayName = branch.Name; - Repository = repo; - Id = String.Format(CultureInfo.InvariantCulture, "{0}/{1}", Repository.Owner, Name); + Id = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", Repository.Owner, Name); } public string Id { get; private set; } From 9e341e04b4ccde4128f53717c138ae8521922ec9 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 2 Nov 2018 13:53:42 +0000 Subject: [PATCH 31/39] Remove IBranch interface from BranchModel --- .../Models/RemoteRepositoryModel.cs | 8 +- .../SampleData/GitServiceDesigner.cs | 2 +- .../LocalRepositoryModelDesigner.cs | 2 +- .../PullRequestCreationViewModelDesigner.cs | 8 +- .../RemoteRepositoryModelDesigner.cs | 2 +- src/GitHub.App/Services/ModelService.cs | 4 +- src/GitHub.App/Services/PullRequestService.cs | 6 +- .../PullRequestCreationViewModel.cs | 14 +-- .../Services/IModelService.cs | 4 +- .../Services/IPullRequestService.cs | 4 +- .../IPullRequestCreationViewModel.cs | 6 +- src/GitHub.Exports/Models/BranchModel.cs | 96 ------------------ src/GitHub.Exports/Models/IBranch.cs | 99 +++++++++++++++++-- .../Models/IRemoteRepositoryModel.cs | 2 +- src/GitHub.Exports/Services/GitService.cs | 2 +- src/GitHub.Exports/Services/IGitService.cs | 2 +- .../Converters/BranchNameConverter.cs | 2 +- test/GitHub.Api.UnitTests/Args.cs | 2 +- test/GitHub.App.UnitTests/Args.cs | 2 +- .../Services/PullRequestServiceTests.cs | 4 +- .../PullRequestCreationViewModelTests.cs | 4 +- .../PullRequestDetailViewModelTests.cs | 2 +- test/GitHub.Exports.UnitTests/Args.cs | 2 +- .../VSGitExtTests.cs | 2 +- test/GitHub.VisualStudio.UnitTests/Args.cs | 2 +- .../Commands/OpenFromClipboardCommandTests.cs | 2 +- 26 files changed, 135 insertions(+), 150 deletions(-) delete mode 100644 src/GitHub.Exports/Models/BranchModel.cs diff --git a/src/GitHub.App/Models/RemoteRepositoryModel.cs b/src/GitHub.App/Models/RemoteRepositoryModel.cs index 64ec5bda4a..61a16aaf5e 100644 --- a/src/GitHub.App/Models/RemoteRepositoryModel.cs +++ b/src/GitHub.App/Models/RemoteRepositoryModel.cs @@ -21,7 +21,7 @@ public class RemoteRepositoryModel : RepositoryModel, IRemoteRepositoryModel, /// Whether the repository is a fork. /// The repository owner account. /// The parent repository if this repository is a fork. - public RemoteRepositoryModel(long id, string name, UriString cloneUrl, bool isPrivate, bool isFork, IAccount ownerAccount, IRemoteRepositoryModel parent) + public RemoteRepositoryModel(long id, string name, UriString cloneUrl, bool isPrivate, bool isFork, IAccount ownerAccount, IRemoteRepositoryModel parent) : base(name, cloneUrl) { Guard.ArgumentNotEmptyString(name, nameof(name)); @@ -56,7 +56,7 @@ public RemoteRepositoryModel(Octokit.Repository repository) Parent.DefaultBranch.DisplayName = Parent.DefaultBranch.Id; } -#region Equality Things + #region Equality Things public void CopyFrom(IRemoteRepositoryModel other) { if (!Equals(other)) @@ -124,7 +124,7 @@ public int CompareTo(RemoteRepositoryModel other) { return !(lhs == rhs); } -#endregion + #endregion /// /// Gets the account that is the ower of the repository. @@ -159,7 +159,7 @@ public int CompareTo(RemoteRepositoryModel other) /// /// Gets the default branch for the repository. /// - public IBranch DefaultBranch { get; } + public BranchModel DefaultBranch { get; } internal string DebuggerDisplay { diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index ef5c284285..349a7a0ff9 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -9,7 +9,7 @@ namespace GitHub.SampleData class GitServiceDesigner : IGitService { public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; - public IBranch GetBranch(ILocalRepositoryModel model) => null; + public BranchModel GetBranch(ILocalRepositoryModel model) => null; public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; public IRepository GetRepository(string path) => null; diff --git a/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs b/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs index dbcac88908..71790fe9aa 100644 --- a/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs +++ b/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs @@ -11,7 +11,7 @@ namespace GitHub.App.SampleData public class LocalRepositoryModelDesigner : ILocalRepositoryModel { public UriString CloneUrl { get; set; } - public IBranch CurrentBranch { get; set; } + public BranchModel CurrentBranch { get; set; } public Octicon Icon { get; set; } public string LocalPath { get; set; } public string Name { get; set; } diff --git a/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs index 816e814b10..05d1bd8162 100644 --- a/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs @@ -21,7 +21,7 @@ public PullRequestCreationViewModelDesigner() CloneUrl = "http://github.com/user/repo" }; - Branches = new List + Branches = new List { new BranchModel("master", repositoryModel), new BranchModel("don/stub-ui", repositoryModel), @@ -40,9 +40,9 @@ public PullRequestCreationViewModelDesigner() }; } - public IBranch SourceBranch { get; set; } - public IBranch TargetBranch { get; set; } - public IReadOnlyList Branches { get; set; } + public BranchModel SourceBranch { get; set; } + public BranchModel TargetBranch { get; set; } + public IReadOnlyList Branches { get; set; } public string SelectedAssignee { get; set; } public List Users { get; set; } diff --git a/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs b/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs index d9179f1cb5..6768bcdaae 100644 --- a/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs +++ b/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs @@ -10,7 +10,7 @@ public class RemoteRepositoryModelDesigner : IRemoteRepositoryModel { public UriString CloneUrl { get; set; } public DateTimeOffset CreatedAt { get; set; } - public IBranch DefaultBranch { get; set; } + public BranchModel DefaultBranch { get; set; } public Octicon Icon { get; set; } public long Id { get; set; } public bool IsFork { get; set; } diff --git a/src/GitHub.App/Services/ModelService.cs b/src/GitHub.App/Services/ModelService.cs index 90369b122c..b00dad8e92 100644 --- a/src/GitHub.App/Services/ModelService.cs +++ b/src/GitHub.App/Services/ModelService.cs @@ -257,7 +257,7 @@ public ITrackingCollection GetRepositories(ITrackingColl } public IObservable CreatePullRequest(ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, - IBranch sourceBranch, IBranch targetBranch, + BranchModel sourceBranch, BranchModel targetBranch, string title, string body) { var keyobs = GetUserFromCache() @@ -359,7 +359,7 @@ IObservable> GetOrganizationRepositories(s }); } - public IObservable GetBranches(IRepositoryModel repo) + public IObservable GetBranches(IRepositoryModel repo) { var keyobs = GetUserFromCache() .Select(user => string.Format(CultureInfo.InvariantCulture, "{0}|{1}|branch", user.Login, repo.Name)); diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index 3a0f16c2bd..b59125a672 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -318,7 +318,7 @@ public async Task> ReadAssignableUsers( public IObservable CreatePullRequest(IModelService modelService, ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, - IBranch sourceBranch, IBranch targetBranch, + BranchModel sourceBranch, BranchModel targetBranch, string title, string body ) { @@ -635,7 +635,7 @@ public IObservable GetTreeChanges(ILocalRepositoryModel repository, }); } - public IObservable GetLocalBranches(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) + public IObservable GetLocalBranches(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) { return Observable.Defer(() => { @@ -926,7 +926,7 @@ async Task MarkBranchAsPullRequest(IRepository repo, string branchName, string o async Task PushAndCreatePR(IModelService modelService, ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, - IBranch sourceBranch, IBranch targetBranch, + BranchModel sourceBranch, BranchModel targetBranch, string title, string body) { // PullRequestModel doesn't keep a reference to repo diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index cde9882b5a..188a6d2e05 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -161,7 +161,7 @@ public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection githubObs.SelectMany(r => { - var b = Observable.Empty(); + var b = Observable.Empty(); if (r.IsFork) { b = modelService.GetBranches(r.Parent).Select(x => @@ -327,22 +327,22 @@ bool Initialized set { this.RaiseAndSetIfChanged(ref initialized, value); } } - IBranch sourceBranch; - public IBranch SourceBranch + BranchModel sourceBranch; + public BranchModel SourceBranch { get { return sourceBranch; } set { this.RaiseAndSetIfChanged(ref sourceBranch, value); } } - IBranch targetBranch; - public IBranch TargetBranch + BranchModel targetBranch; + public BranchModel TargetBranch { get { return targetBranch; } set { this.RaiseAndSetIfChanged(ref targetBranch, value); } } - IReadOnlyList branches; - public IReadOnlyList Branches + IReadOnlyList branches; + public IReadOnlyList Branches { get { return branches; } set { this.RaiseAndSetIfChanged(ref branches, value); } diff --git a/src/GitHub.Exports.Reactive/Services/IModelService.cs b/src/GitHub.Exports.Reactive/Services/IModelService.cs index 76f970248a..9a24371457 100644 --- a/src/GitHub.Exports.Reactive/Services/IModelService.cs +++ b/src/GitHub.Exports.Reactive/Services/IModelService.cs @@ -28,9 +28,9 @@ public interface IModelService : IDisposable IObservable GetPullRequest(string owner, string name, int number); ITrackingCollection GetPullRequests(IRepositoryModel repo, ITrackingCollection collection); IObservable CreatePullRequest(ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, - IBranch sourceBranch, IBranch targetBranch, + BranchModel sourceBranch, BranchModel targetBranch, string title, string body); - IObservable GetBranches(IRepositoryModel repo); + IObservable GetBranches(IRepositoryModel repo); IObservable InvalidateAll(); IObservable GetFileContents(IRepositoryModel repo, string commitSha, string path, string fileSha); } diff --git a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs index 0d34471afb..c45ef22c73 100644 --- a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs +++ b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs @@ -43,7 +43,7 @@ Task> ReadAssignableUsers( IObservable CreatePullRequest(IModelService modelService, ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, - IBranch sourceBranch, IBranch targetBranch, + BranchModel sourceBranch, BranchModel targetBranch, string title, string body); /// @@ -103,7 +103,7 @@ IObservable CreatePullRequest(IModelService modelService, /// The repository. /// The pull request details. /// - IObservable GetLocalBranches(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); + IObservable GetLocalBranches(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); /// /// Ensures that all local branches for the specified pull request are marked as PR branches. diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCreationViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCreationViewModel.cs index 47f1aaf31b..eaf9ec8944 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCreationViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCreationViewModel.cs @@ -9,9 +9,9 @@ namespace GitHub.ViewModels.GitHubPane { public interface IPullRequestCreationViewModel : IPanePageViewModel { - IBranch SourceBranch { get; set; } - IBranch TargetBranch { get; set; } - IReadOnlyList Branches { get; } + BranchModel SourceBranch { get; set; } + BranchModel TargetBranch { get; set; } + IReadOnlyList Branches { get; } ReactiveCommand CreatePullRequest { get; } ReactiveCommand Cancel { get; } string PRTitle { get; set; } diff --git a/src/GitHub.Exports/Models/BranchModel.cs b/src/GitHub.Exports/Models/BranchModel.cs deleted file mode 100644 index 0c7512c99e..0000000000 --- a/src/GitHub.Exports/Models/BranchModel.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Globalization; - -namespace GitHub.Models -{ - public class BranchModel : IBranch - { - public BranchModel(string name, IRepositoryModel repo, string sha, bool isTracking, string trackedSha) : - this(name, repo) - { - IsTracking = isTracking; - Sha = sha; - TrackedSha = trackedSha; - } - - public BranchModel(string name, IRepositoryModel repo) - { - Extensions.Guard.ArgumentNotEmptyString(name, nameof(name)); - Extensions.Guard.ArgumentNotNull(repo, nameof(repo)); - - Name = DisplayName = name; - Repository = repo; - Id = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", Repository.Owner, Name); - } - - public string Id { get; private set; } - public string Name { get; private set; } - public IRepositoryModel Repository { get; private set; } - public bool IsTracking { get; private set; } - public string DisplayName { get; set; } - public string Sha { get; private set; } - public string TrackedSha { get; private set; } - - #region Equality things - public void CopyFrom(IBranch other) - { - if (!Equals(other)) - throw new ArgumentException("Instance to copy from doesn't match this instance. this:(" + this + ") other:(" + other + ")", nameof(other)); - Id = other.Id; - Name = other.Name; - Repository = other.Repository; - DisplayName = other.DisplayName; - IsTracking = other.IsTracking; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(this, obj)) - return true; - var other = obj as BranchModel; - return other != null && Id == other.Id; - } - - public override int GetHashCode() - { - return Id.GetHashCode(); - } - - bool IEquatable.Equals(IBranch other) - { - if (ReferenceEquals(this, other)) - return true; - return other != null && Id == other.Id; - } - - public int CompareTo(IBranch other) - { - return other != null ? String.Compare(Id, other.Id, StringComparison.CurrentCulture) : 1; - } - - public static bool operator >(BranchModel lhs, BranchModel rhs) - { - if (ReferenceEquals(lhs, rhs)) - return false; - return lhs?.CompareTo(rhs) > 0; - } - - public static bool operator <(BranchModel lhs, BranchModel rhs) - { - if (ReferenceEquals(lhs, rhs)) - return false; - return (object)lhs == null || lhs.CompareTo(rhs) < 0; - } - - public static bool operator ==(BranchModel lhs, BranchModel rhs) - { - return Equals(lhs, rhs) && ((object)lhs == null || lhs.CompareTo(rhs) == 0); - } - - public static bool operator !=(BranchModel lhs, BranchModel rhs) - { - return !(lhs == rhs); - } - #endregion - } -} diff --git a/src/GitHub.Exports/Models/IBranch.cs b/src/GitHub.Exports/Models/IBranch.cs index 223172e8fe..cb28e905ad 100644 --- a/src/GitHub.Exports/Models/IBranch.cs +++ b/src/GitHub.Exports/Models/IBranch.cs @@ -1,17 +1,98 @@ using System; +using System.Globalization; using GitHub.Collections; namespace GitHub.Models { - public interface IBranch : ICopyable, - IEquatable, IComparable + public class BranchModel : ICopyable, + IEquatable, IComparable { - string Id { get; } - string Name { get; } - IRepositoryModel Repository { get; } - bool IsTracking { get; } - string DisplayName { get; set; } - string Sha { get; } - string TrackedSha { get; } + public BranchModel(string name, IRepositoryModel repo, string sha, bool isTracking, string trackedSha) : + this(name, repo) + { + IsTracking = isTracking; + Sha = sha; + TrackedSha = trackedSha; + } + + public BranchModel(string name, IRepositoryModel repo) + { + Extensions.Guard.ArgumentNotEmptyString(name, nameof(name)); + Extensions.Guard.ArgumentNotNull(repo, nameof(repo)); + + Name = DisplayName = name; + Repository = repo; + Id = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", Repository.Owner, Name); + } + + public string Id { get; private set; } + public string Name { get; private set; } + public IRepositoryModel Repository { get; private set; } + public bool IsTracking { get; private set; } + public string DisplayName { get; set; } + public string Sha { get; private set; } + public string TrackedSha { get; private set; } + + #region Equality things + public void CopyFrom(BranchModel other) + { + if (!Equals(other)) + throw new ArgumentException("Instance to copy from doesn't match this instance. this:(" + this + ") other:(" + other + ")", nameof(other)); + Id = other.Id; + Name = other.Name; + Repository = other.Repository; + DisplayName = other.DisplayName; + IsTracking = other.IsTracking; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(this, obj)) + return true; + var other = obj as BranchModel; + return other != null && Id == other.Id; + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } + + bool IEquatable.Equals(BranchModel other) + { + if (ReferenceEquals(this, other)) + return true; + return other != null && Id == other.Id; + } + + public int CompareTo(BranchModel other) + { + return other != null ? string.Compare(Id, other.Id, StringComparison.CurrentCulture) : 1; + } + + public static bool operator >(BranchModel lhs, BranchModel rhs) + { + if (ReferenceEquals(lhs, rhs)) + return false; + return lhs?.CompareTo(rhs) > 0; + } + + public static bool operator <(BranchModel lhs, BranchModel rhs) + { + if (ReferenceEquals(lhs, rhs)) + return false; + return (object)lhs == null || lhs.CompareTo(rhs) < 0; + } + + public static bool operator ==(BranchModel lhs, BranchModel rhs) + { + return Equals(lhs, rhs) && ((object)lhs == null || lhs.CompareTo(rhs) == 0); + } + + public static bool operator !=(BranchModel lhs, BranchModel rhs) + { + return !(lhs == rhs); + } + #endregion } } diff --git a/src/GitHub.Exports/Models/IRemoteRepositoryModel.cs b/src/GitHub.Exports/Models/IRemoteRepositoryModel.cs index d6c3224cbd..e6a91261de 100644 --- a/src/GitHub.Exports/Models/IRemoteRepositoryModel.cs +++ b/src/GitHub.Exports/Models/IRemoteRepositoryModel.cs @@ -42,6 +42,6 @@ public interface IRemoteRepositoryModel : IRepositoryModel, ICopyable /// Gets the default branch for the repository. /// - IBranch DefaultBranch { get; } + BranchModel DefaultBranch { get; } } } diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 566a681cbc..237ae472b4 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -52,7 +52,7 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) return model; } - public IBranch GetBranch(ILocalRepositoryModel model) + public BranchModel GetBranch(ILocalRepositoryModel model) { var localPath = model.LocalPath; using (var repo = GetRepository(localPath)) diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 7ebe6d6348..46be343d66 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -19,7 +19,7 @@ public interface IGitService /// /// The to create a current branch model for. /// A new branch model. - IBranch GetBranch(ILocalRepositoryModel model); + BranchModel GetBranch(ILocalRepositoryModel model); /// /// Returns the URL of the remote for the specified . If the repository diff --git a/src/GitHub.UI/Converters/BranchNameConverter.cs b/src/GitHub.UI/Converters/BranchNameConverter.cs index 0db0f51c3e..3e5e5b0ded 100644 --- a/src/GitHub.UI/Converters/BranchNameConverter.cs +++ b/src/GitHub.UI/Converters/BranchNameConverter.cs @@ -15,7 +15,7 @@ public class BranchNameConverter : IMultiValueConverter public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { - var branch = values.OfType().FirstOrDefault(); + var branch = values.OfType().FirstOrDefault(); var activeRepo = values.OfType().FirstOrDefault(); if (branch != null && activeRepo != null) diff --git a/test/GitHub.Api.UnitTests/Args.cs b/test/GitHub.Api.UnitTests/Args.cs index 2a04705cde..d0cbd27215 100644 --- a/test/GitHub.Api.UnitTests/Args.cs +++ b/test/GitHub.Api.UnitTests/Args.cs @@ -27,7 +27,7 @@ internal static class Args public static Remote LibgGit2Remote { get { return Arg.Any(); } } public static ILocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } - public static IBranch Branch { get { return Arg.Any(); } } + public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } public static Func> TwoFactorChallengCallback diff --git a/test/GitHub.App.UnitTests/Args.cs b/test/GitHub.App.UnitTests/Args.cs index 2a04705cde..d0cbd27215 100644 --- a/test/GitHub.App.UnitTests/Args.cs +++ b/test/GitHub.App.UnitTests/Args.cs @@ -27,7 +27,7 @@ internal static class Args public static Remote LibgGit2Remote { get { return Arg.Any(); } } public static ILocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } - public static IBranch Branch { get { return Arg.Any(); } } + public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } public static Func> TwoFactorChallengCallback diff --git a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs index 2ede44920b..e5d69bcc72 100644 --- a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs +++ b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs @@ -693,8 +693,8 @@ public void CreatePullRequestAllArgsMandatory() ILocalRepositoryModel targetRepo = null; string title = null; string body = null; - IBranch source = null; - IBranch target = null; + BranchModel source = null; + BranchModel target = null; Assert.Throws(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body)); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index 3be219088c..a68cc38a89 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -47,8 +47,8 @@ struct TestData public LibGit2Sharp.IRepository L2Repo; public IRepositoryModel SourceRepo; public IRepositoryModel TargetRepo; - public IBranch SourceBranch; - public IBranch TargetBranch; + public BranchModel SourceBranch; + public BranchModel TargetBranch; public IGitClient GitClient; public IGitService GitService; public INotificationService NotificationService; diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs index d874e4e26e..c90066cfd0 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs @@ -569,7 +569,7 @@ static Tuple CreateTargetAndSer else { pullRequestService.GetLocalBranches(repository, Arg.Any()) - .Returns(Observable.Empty()); + .Returns(Observable.Empty()); } pullRequestService.Checkout(repository, Arg.Any(), Arg.Any()).Returns(x => Throws("Checkout threw")); diff --git a/test/GitHub.Exports.UnitTests/Args.cs b/test/GitHub.Exports.UnitTests/Args.cs index 03bc2d7fe3..b917e86353 100644 --- a/test/GitHub.Exports.UnitTests/Args.cs +++ b/test/GitHub.Exports.UnitTests/Args.cs @@ -25,7 +25,7 @@ internal static class Args public static Remote LibgGit2Remote { get { return Arg.Any(); } } public static ILocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } - public static IBranch Branch { get { return Arg.Any(); } } + public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } public static Func> TwoFactorChallengCallback diff --git a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs index e70c3cd918..7f54e16ad0 100644 --- a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs +++ b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs @@ -311,7 +311,7 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) return result; } - public IBranch GetBranch(ILocalRepositoryModel model) => throw new NotImplementedException(); + public BranchModel GetBranch(ILocalRepositoryModel model) => throw new NotImplementedException(); public Task GetLatestPushedSha(string path, string remote = "origin") => throw new NotImplementedException(); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => throw new NotImplementedException(); public IRepository GetRepository(string path) => throw new NotImplementedException(); diff --git a/test/GitHub.VisualStudio.UnitTests/Args.cs b/test/GitHub.VisualStudio.UnitTests/Args.cs index 2a04705cde..d0cbd27215 100644 --- a/test/GitHub.VisualStudio.UnitTests/Args.cs +++ b/test/GitHub.VisualStudio.UnitTests/Args.cs @@ -27,7 +27,7 @@ internal static class Args public static Remote LibgGit2Remote { get { return Arg.Any(); } } public static ILocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } - public static IBranch Branch { get { return Arg.Any(); } } + public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } public static Func> TwoFactorChallengCallback diff --git a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs index 062eebbcac..cb17f16419 100644 --- a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs @@ -195,7 +195,7 @@ static OpenFromClipboardCommand CreateOpenFromClipboardCommand( activeRepository.Name.Returns(repositoryName); activeRepository.Owner.Returns(repositoryOwner); var gitService = Substitute.For(); - var currentBranch = Substitute.For(); + var currentBranch = Substitute.For(); currentBranch.Name.Returns(currentBranchName); gitService.GetBranch(activeRepository).Returns(currentBranch); if (resolveBlobResult != null) From d7025364b10084dabc3396f998f895c4ac6ce18d Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 2 Nov 2018 14:10:02 +0000 Subject: [PATCH 32/39] Remove the interface from RepositoryModel --- .../ForkRepositoryExecuteViewModelDesigner.cs | 2 +- .../ForkRepositorySelectViewModelDesigner.cs | 2 +- .../ForkRepositorySwitchViewModelDesigner.cs | 2 +- .../SampleData/GitServiceDesigner.cs | 4 +- .../LocalRepositoryModelDesigner.cs | 2 +- .../PullRequestCreationViewModelDesigner.cs | 2 +- .../PullRequestDetailViewModelDesigner.cs | 4 +- .../PullRequestListViewModelDesigner.cs | 4 +- ...RequestReviewAuthoringViewModelDesigner.cs | 4 +- .../PullRequestReviewViewModelDesigner.cs | 2 +- ...PullRequestUserReviewsViewModelDesigner.cs | 4 +- src/GitHub.App/Services/DialogService.cs | 2 +- src/GitHub.App/Services/ModelService.cs | 2 +- .../Services/PullRequestEditorService.cs | 2 +- src/GitHub.App/Services/PullRequestService.cs | 46 +++++++-------- .../Services/TeamExplorerContext.cs | 4 +- .../Dialog/ForkRepositoryExecuteViewModel.cs | 2 +- .../Dialog/ForkRepositorySelectViewModel.cs | 4 +- .../Dialog/ForkRepositorySwitchViewModel.cs | 2 +- .../Dialog/ForkRepositoryViewModel.cs | 4 +- .../GitHubPane/GitHubPaneViewModel.cs | 6 +- .../GitHubPane/IssueListViewModelBase.cs | 4 +- .../PullRequestCreationViewModel.cs | 4 +- .../GitHubPane/PullRequestDetailViewModel.cs | 4 +- .../PullRequestReviewAuthoringViewModel.cs | 4 +- .../PullRequestUserReviewsViewModel.cs | 4 +- .../Extensions/ConnectionManagerExtensions.cs | 2 +- .../Services/IModelService.cs | 2 +- .../Services/IPullRequestService.cs | 44 +++++++------- .../Services/IPullRequestSession.cs | 2 +- .../Services/LocalRepositoriesExtensions.cs | 4 +- .../Dialog/IForkRepositoryExecuteViewModel.cs | 2 +- .../Dialog/IForkRepositorySelectViewModel.cs | 2 +- .../Dialog/IForkRepositorySwitchViewModel.cs | 2 +- .../Dialog/IForkRepositoryViewModel.cs | 2 +- .../GitHubPane/IIssueListViewModelBase.cs | 4 +- .../IPullRequestCreationViewModel.cs | 2 +- .../GitHubPane/IPullRequestDetailViewModel.cs | 4 +- .../IPullRequestReviewAuthoringViewModel.cs | 4 +- .../IPullRequestUserReviewsViewModel.cs | 4 +- .../LocalRepositoryModelExtensions.cs | 4 +- .../Models/ILocalRepositoryModel.cs | 57 ++++++++++++++++-- .../Models/LocalRepositoryModel.cs | 59 ------------------- src/GitHub.Exports/Services/GitService.cs | 4 +- src/GitHub.Exports/Services/IDialogService.cs | 2 +- src/GitHub.Exports/Services/IGitService.cs | 6 +- .../Services/ILocalRepositories.cs | 2 +- .../Services/ITeamExplorerContext.cs | 2 +- .../Services/ITeamExplorerServiceHolder.cs | 2 +- src/GitHub.Exports/Services/IVSGitExt.cs | 2 +- src/GitHub.Exports/Services/IVSGitServices.cs | 2 +- .../GitHubPane/IGitHubPaneViewModel.cs | 2 +- .../Services/IPullRequestSessionService.cs | 38 ++++++------ .../Services/PullRequestSession.cs | 4 +- .../Services/PullRequestSessionManager.cs | 4 +- .../Services/PullRequestSessionService.cs | 38 ++++++------ .../Services/PullRequestStatusBarManager.cs | 4 +- .../Base/TeamExplorerNavigationItemBase.cs | 4 +- .../Connect/GitHubConnectSection.cs | 18 +++--- .../RegistryHelper.cs | 4 +- .../Services/VSGitExt.cs | 8 +-- .../Services/VSGitServices.cs | 4 +- .../Sync/GitHubPublishSection.cs | 4 +- .../Base/TeamExplorerGitRepoInfo.cs | 4 +- .../Base/TeamExplorerItemBase.cs | 4 +- .../UI/Views/GitHubConnectContent.xaml.cs | 4 +- .../Commands/LinkCommandBase.cs | 8 +-- .../Services/LocalRepositories.cs | 6 +- test/GitHub.Api.UnitTests/Args.cs | 2 +- test/GitHub.App.UnitTests/Args.cs | 2 +- .../Models/ModelServiceTests.cs | 6 +- .../Services/PullRequestServiceTests.cs | 38 ++++++------ .../Services/TeamExplorerContextTests.cs | 8 +-- .../GitHubPane/GitHubPaneViewModelTests.cs | 4 +- .../GitHubPane/IssueListViewModelBaseTests.cs | 6 +- .../PullRequestCreationViewModelTests.cs | 4 +- .../PullRequestDetailViewModelTests.cs | 2 +- .../PullRequestFilesViewModelTests.cs | 2 +- .../PullRequestListViewModelTests.cs | 2 +- ...ullRequestReviewAuthoringViewModelTests.cs | 6 +- .../PullRequestUserReviewsViewModelTests.cs | 6 +- test/GitHub.Exports.UnitTests/Args.cs | 2 +- .../PullRequestSessionManagerTests.cs | 14 ++--- .../Services/PullRequestSessionTests.cs | 42 ++++++------- .../VSGitExtTests.cs | 6 +- test/GitHub.VisualStudio.UnitTests/Args.cs | 2 +- .../Commands/LinkCommandBaseTests.cs | 2 +- .../Services/LocalRepositoriesTests.cs | 8 +-- 88 files changed, 330 insertions(+), 340 deletions(-) delete mode 100644 src/GitHub.Exports/Models/LocalRepositoryModel.cs diff --git a/src/GitHub.App/SampleData/ForkRepositoryExecuteViewModelDesigner.cs b/src/GitHub.App/SampleData/ForkRepositoryExecuteViewModelDesigner.cs index 1a3cf201cd..e04f605bd8 100644 --- a/src/GitHub.App/SampleData/ForkRepositoryExecuteViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/ForkRepositoryExecuteViewModelDesigner.cs @@ -57,7 +57,7 @@ public ForkRepositoryExecuteViewModelDesigner() public string Error { get; } = "I AM ERROR"; - public Task InitializeAsync(ILocalRepositoryModel sourceRepository, IAccount destinationAccount, IConnection connection) + public Task InitializeAsync(LocalRepositoryModel sourceRepository, IAccount destinationAccount, IConnection connection) { return Task.CompletedTask; } diff --git a/src/GitHub.App/SampleData/ForkRepositorySelectViewModelDesigner.cs b/src/GitHub.App/SampleData/ForkRepositorySelectViewModelDesigner.cs index a43ed6421a..4326e3fdaf 100644 --- a/src/GitHub.App/SampleData/ForkRepositorySelectViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/ForkRepositorySelectViewModelDesigner.cs @@ -43,7 +43,7 @@ public ForkRepositorySelectViewModelDesigner() public ReactiveCommand SwitchOrigin => null; - public Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) + public Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) { return Task.CompletedTask; } diff --git a/src/GitHub.App/SampleData/ForkRepositorySwitchViewModelDesigner.cs b/src/GitHub.App/SampleData/ForkRepositorySwitchViewModelDesigner.cs index 7d895dbb31..940013509d 100644 --- a/src/GitHub.App/SampleData/ForkRepositorySwitchViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/ForkRepositorySwitchViewModelDesigner.cs @@ -41,7 +41,7 @@ public ForkRepositorySwitchViewModelDesigner() public bool UpdateOrigin { get; set; } = true; - public void Initialize(ILocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository) + public void Initialize(LocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository) { } } diff --git a/src/GitHub.App/SampleData/GitServiceDesigner.cs b/src/GitHub.App/SampleData/GitServiceDesigner.cs index 349a7a0ff9..cabbf30a4c 100644 --- a/src/GitHub.App/SampleData/GitServiceDesigner.cs +++ b/src/GitHub.App/SampleData/GitServiceDesigner.cs @@ -8,8 +8,8 @@ namespace GitHub.SampleData { class GitServiceDesigner : IGitService { - public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; - public BranchModel GetBranch(ILocalRepositoryModel model) => null; + public LocalRepositoryModel CreateLocalRepositoryModel(string localPath) => null; + public BranchModel GetBranch(LocalRepositoryModel model) => null; public Task GetLatestPushedSha(string path, string remote = "origin") => Task.FromResult(null); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => null; public IRepository GetRepository(string path) => null; diff --git a/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs b/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs index 71790fe9aa..75597907b6 100644 --- a/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs +++ b/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs @@ -8,7 +8,7 @@ namespace GitHub.App.SampleData { - public class LocalRepositoryModelDesigner : ILocalRepositoryModel + public class LocalRepositoryModelDesigner : LocalRepositoryModel { public UriString CloneUrl { get; set; } public BranchModel CurrentBranch { get; set; } diff --git a/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs index 05d1bd8162..32922438d8 100644 --- a/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestCreationViewModelDesigner.cs @@ -56,6 +56,6 @@ public PullRequestCreationViewModelDesigner() public ReactivePropertyValidator BranchValidator { get; } - public Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) => Task.CompletedTask; + public Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) => Task.CompletedTask; } } \ No newline at end of file diff --git a/src/GitHub.App/SampleData/PullRequestDetailViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestDetailViewModelDesigner.cs index 6d8310a773..0bb87d5d37 100644 --- a/src/GitHub.App/SampleData/PullRequestDetailViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestDetailViewModelDesigner.cs @@ -101,7 +101,7 @@ public PullRequestDetailViewModelDesigner() public PullRequestDetailModel Model { get; } public IPullRequestSession Session { get; } - public ILocalRepositoryModel LocalRepository { get; } + public LocalRepositoryModel LocalRepository { get; } public string RemoteRepositoryOwner { get; } public int Number { get; set; } public IActorViewModel Author { get; set; } @@ -127,7 +127,7 @@ public PullRequestDetailViewModelDesigner() public IReadOnlyList Checks { get; } - public Task InitializeAsync(ILocalRepositoryModel localRepository, IConnection connection, string owner, string repo, int number) => Task.CompletedTask; + public Task InitializeAsync(LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, int number) => Task.CompletedTask; public string GetLocalFilePath(IPullRequestFileNode file) { diff --git a/src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs index 34c90b8525..f0e6d79e81 100644 --- a/src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs @@ -53,7 +53,7 @@ public PullRequestListViewModelDesigner() public IUserFilterViewModel AuthorFilter { get; set; } public IReadOnlyList Items { get; } public ICollectionView ItemsView { get; } - public ILocalRepositoryModel LocalRepository { get; set; } + public LocalRepositoryModel LocalRepository { get; set; } public IssueListMessage Message { get; set; } public IRepositoryModel RemoteRepository { get; set; } public IReadOnlyList Forks { get; } @@ -66,6 +66,6 @@ public PullRequestListViewModelDesigner() public ReactiveCommand OpenItem { get; } public ReactiveCommand OpenItemInBrowser { get; } - public Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) => Task.CompletedTask; + public Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) => Task.CompletedTask; } } \ No newline at end of file diff --git a/src/GitHub.App/SampleData/PullRequestReviewAuthoringViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestReviewAuthoringViewModelDesigner.cs index 9082f69785..cfc8eb23e4 100644 --- a/src/GitHub.App/SampleData/PullRequestReviewAuthoringViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestReviewAuthoringViewModelDesigner.cs @@ -43,7 +43,7 @@ public PullRequestReviewAuthoringViewModelDesigner() public bool CanApproveRequestChanges { get; set; } public IReadOnlyList FileComments { get; } public IPullRequestFilesViewModel Files { get; } - public ILocalRepositoryModel LocalRepository { get; set; } + public LocalRepositoryModel LocalRepository { get; set; } public PullRequestReviewModel Model { get; set; } public ReactiveCommand NavigateToPullRequest { get; } public string OperationError { get; set; } @@ -55,7 +55,7 @@ public PullRequestReviewAuthoringViewModelDesigner() public ReactiveCommand Cancel { get; } public Task InitializeAsync( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, diff --git a/src/GitHub.App/SampleData/PullRequestReviewViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestReviewViewModelDesigner.cs index 2df22707dc..ca4ce82404 100644 --- a/src/GitHub.App/SampleData/PullRequestReviewViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestReviewViewModelDesigner.cs @@ -64,7 +64,7 @@ public PullRequestReviewViewModelDesigner() public IReadOnlyList FileComments { get; set; } public bool IsExpanded { get; set; } public bool HasDetails { get; set; } - public ILocalRepositoryModel LocalRepository { get; set; } + public LocalRepositoryModel LocalRepository { get; set; } public PullRequestReviewModel Model { get; set; } public ReactiveCommand NavigateToPullRequest { get; } public IReadOnlyList OutdatedFileComments { get; set; } diff --git a/src/GitHub.App/SampleData/PullRequestUserReviewsViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestUserReviewsViewModelDesigner.cs index 0575871e59..a1aec8c4c3 100644 --- a/src/GitHub.App/SampleData/PullRequestUserReviewsViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestUserReviewsViewModelDesigner.cs @@ -63,7 +63,7 @@ public PullRequestUserReviewsViewModelDesigner() }; } - public ILocalRepositoryModel LocalRepository { get; set; } + public LocalRepositoryModel LocalRepository { get; set; } public string RemoteRepositoryOwner { get; set; } public int PullRequestNumber { get; set; } public IActorViewModel User { get; set; } @@ -71,7 +71,7 @@ public PullRequestUserReviewsViewModelDesigner() public string PullRequestTitle { get; set; } public ReactiveCommand NavigateToPullRequest { get; } - public Task InitializeAsync(ILocalRepositoryModel localRepository, IConnection connection, string owner, string repo, int pullRequestNumber, string login) + public Task InitializeAsync(LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, int pullRequestNumber, string login) { return Task.CompletedTask; } diff --git a/src/GitHub.App/Services/DialogService.cs b/src/GitHub.App/Services/DialogService.cs index a96d532893..1814522ee6 100644 --- a/src/GitHub.App/Services/DialogService.cs +++ b/src/GitHub.App/Services/DialogService.cs @@ -91,7 +91,7 @@ public async Task ShowLoginDialog() return (IConnection)await showDialog.Show(viewModel); } - public async Task ShowForkDialog(ILocalRepositoryModel repository, IConnection connection) + public async Task ShowForkDialog(LocalRepositoryModel repository, IConnection connection) { Guard.ArgumentNotNull(repository, nameof(repository)); Guard.ArgumentNotNull(connection, nameof(connection)); diff --git a/src/GitHub.App/Services/ModelService.cs b/src/GitHub.App/Services/ModelService.cs index b00dad8e92..3cd812851b 100644 --- a/src/GitHub.App/Services/ModelService.cs +++ b/src/GitHub.App/Services/ModelService.cs @@ -256,7 +256,7 @@ public ITrackingCollection GetRepositories(ITrackingColl return collection; } - public IObservable CreatePullRequest(ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + public IObservable CreatePullRequest(LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body) { diff --git a/src/GitHub.App/Services/PullRequestEditorService.cs b/src/GitHub.App/Services/PullRequestEditorService.cs index 3135c29730..aaf44c50ad 100644 --- a/src/GitHub.App/Services/PullRequestEditorService.cs +++ b/src/GitHub.App/Services/PullRequestEditorService.cs @@ -472,7 +472,7 @@ public int FindNearestMatchingLine(IList fromLines, IList toLine return matchingLine; } - static string GetAbsolutePath(ILocalRepositoryModel localRepository, string relativePath) + static string GetAbsolutePath(LocalRepositoryModel localRepository, string relativePath) { var localPath = localRepository.LocalPath; relativePath = relativePath.Replace('/', Path.DirectorySeparatorChar); diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index b59125a672..bb277e43b9 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -317,7 +317,7 @@ public async Task> ReadAssignableUsers( } public IObservable CreatePullRequest(IModelService modelService, - ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body ) @@ -333,7 +333,7 @@ public IObservable CreatePullRequest(IModelService modelServi return PushAndCreatePR(modelService, sourceRepository, targetRepository, sourceBranch, targetBranch, title, body).ToObservable(); } - public IObservable GetPullRequestTemplate(ILocalRepositoryModel repository) + public IObservable GetPullRequestTemplate(LocalRepositoryModel repository) { Extensions.Guard.ArgumentNotNull(repository, nameof(repository)); @@ -353,7 +353,7 @@ public IObservable GetPullRequestTemplate(ILocalRepositoryModel reposito } public IObservable> GetMessagesForUniqueCommits( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, string baseBranch, string compareBranch, int maxCommits) @@ -369,7 +369,7 @@ public IObservable> GetMessagesForUniqueCommits( }); } - public IObservable CountSubmodulesToSync(ILocalRepositoryModel repository) + public IObservable CountSubmodulesToSync(LocalRepositoryModel repository) { using (var repo = gitService.GetRepository(repository.LocalPath)) { @@ -399,7 +399,7 @@ public IObservable CountSubmodulesToSync(ILocalRepositoryModel repository) } } - public IObservable IsWorkingDirectoryClean(ILocalRepositoryModel repository) + public IObservable IsWorkingDirectoryClean(LocalRepositoryModel repository) { // The `using` appears to resolve this issue: // https://github.com/github/VisualStudio/issues/1306 @@ -440,7 +440,7 @@ static bool IsCheckoutBlockingChange(StatusEntry entry) } } - public IObservable Pull(ILocalRepositoryModel repository) + public IObservable Pull(LocalRepositoryModel repository) { return Observable.Defer(async () => { @@ -452,7 +452,7 @@ public IObservable Pull(ILocalRepositoryModel repository) }); } - public IObservable Push(ILocalRepositoryModel repository) + public IObservable Push(LocalRepositoryModel repository) { return Observable.Defer(async () => { @@ -466,7 +466,7 @@ public IObservable Push(ILocalRepositoryModel repository) }); } - public async Task SyncSubmodules(ILocalRepositoryModel repository, Action progress) + public async Task SyncSubmodules(LocalRepositoryModel repository, Action progress) { var exitCode = await Where("git"); if (exitCode != 0) @@ -529,7 +529,7 @@ static async Task ReadLinesAsync(TextReader reader, Action progress) } } - public IObservable Checkout(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest, string localBranchName) + public IObservable Checkout(LocalRepositoryModel repository, PullRequestDetailModel pullRequest, string localBranchName) { return Observable.Defer(async () => { @@ -567,7 +567,7 @@ public IObservable Checkout(ILocalRepositoryModel repository, PullRequestD }); } - public IObservable GetDefaultLocalBranchName(ILocalRepositoryModel repository, int pullRequestNumber, string pullRequestTitle) + public IObservable GetDefaultLocalBranchName(LocalRepositoryModel repository, int pullRequestNumber, string pullRequestTitle) { return Observable.Defer(() => { @@ -587,7 +587,7 @@ public IObservable GetDefaultLocalBranchName(ILocalRepositoryModel repos }); } - public IObservable CalculateHistoryDivergence(ILocalRepositoryModel repository, int pullRequestNumber) + public IObservable CalculateHistoryDivergence(LocalRepositoryModel repository, int pullRequestNumber) { return Observable.Defer(async () => { @@ -606,7 +606,7 @@ public IObservable CalculateHistoryDivergence(ILocalRepos }); } - public async Task GetMergeBase(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) + public async Task GetMergeBase(LocalRepositoryModel repository, PullRequestDetailModel pullRequest) { using (var repo = gitService.GetRepository(repository.LocalPath)) { @@ -620,7 +620,7 @@ public async Task GetMergeBase(ILocalRepositoryModel repository, PullReq } } - public IObservable GetTreeChanges(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) + public IObservable GetTreeChanges(LocalRepositoryModel repository, PullRequestDetailModel pullRequest) { return Observable.Defer(async () => { @@ -635,7 +635,7 @@ public IObservable GetTreeChanges(ILocalRepositoryModel repository, }); } - public IObservable GetLocalBranches(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) + public IObservable GetLocalBranches(LocalRepositoryModel repository, PullRequestDetailModel pullRequest) { return Observable.Defer(() => { @@ -648,7 +648,7 @@ public IObservable GetLocalBranches(ILocalRepositoryModel repositor }); } - public IObservable EnsureLocalBranchesAreMarkedAsPullRequests(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) + public IObservable EnsureLocalBranchesAreMarkedAsPullRequests(LocalRepositoryModel repository, PullRequestDetailModel pullRequest) { return Observable.Defer(async () => { @@ -671,12 +671,12 @@ public IObservable EnsureLocalBranchesAreMarkedAsPullRequests(ILocalReposi }); } - public bool IsPullRequestFromRepository(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) + public bool IsPullRequestFromRepository(LocalRepositoryModel repository, PullRequestDetailModel pullRequest) { return string.Equals(repository.CloneUrl?.Owner, pullRequest.HeadRepositoryOwner, StringComparison.OrdinalIgnoreCase); } - public IObservable SwitchToBranch(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) + public IObservable SwitchToBranch(LocalRepositoryModel repository, PullRequestDetailModel pullRequest) { return Observable.Defer(async () => { @@ -718,7 +718,7 @@ public IObservable SwitchToBranch(ILocalRepositoryModel repository, PullRe }); } - public IObservable<(string owner, int number)> GetPullRequestForCurrentBranch(ILocalRepositoryModel repository) + public IObservable<(string owner, int number)> GetPullRequestForCurrentBranch(LocalRepositoryModel repository) { return Observable.Defer(async () => { @@ -736,7 +736,7 @@ public IObservable SwitchToBranch(ILocalRepositoryModel repository, PullRe } public async Task ExtractToTempFile( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, PullRequestDetailModel pullRequest, string relativePath, string commitSha, @@ -756,7 +756,7 @@ public async Task ExtractToTempFile( return tempFilePath; } - public Encoding GetEncoding(ILocalRepositoryModel repository, string relativePath) + public Encoding GetEncoding(LocalRepositoryModel repository, string relativePath) { var fullPath = Path.Combine(repository.LocalPath, relativePath); @@ -788,7 +788,7 @@ static bool HasPreamble(string file, Encoding encoding) return true; } - public IObservable RemoveUnusedRemotes(ILocalRepositoryModel repository) + public IObservable RemoveUnusedRemotes(LocalRepositoryModel repository) { return Observable.Defer(async () => { @@ -889,7 +889,7 @@ async Task ExtractToTempFile( } IEnumerable GetLocalBranchesInternal( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, IRepository repository, PullRequestDetailModel pullRequest) { @@ -925,7 +925,7 @@ async Task MarkBranchAsPullRequest(IRepository repo, string branchName, string o } async Task PushAndCreatePR(IModelService modelService, - ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body) { diff --git a/src/GitHub.App/Services/TeamExplorerContext.cs b/src/GitHub.App/Services/TeamExplorerContext.cs index 08b82c08d5..3f3b1caf7e 100644 --- a/src/GitHub.App/Services/TeamExplorerContext.cs +++ b/src/GitHub.App/Services/TeamExplorerContext.cs @@ -42,7 +42,7 @@ public class TeamExplorerContext : ITeamExplorerContext UriString cloneUrl; (string owner, int number) pullRequest; - ILocalRepositoryModel repositoryModel; + LocalRepositoryModel repositoryModel; JoinableTask refreshJoinableTask; [ImportingConstructor] @@ -156,7 +156,7 @@ async Task GetSolutionPath() /// /// The active repository or null if not in a repository. /// - public ILocalRepositoryModel ActiveRepository + public LocalRepositoryModel ActiveRepository { get { diff --git a/src/GitHub.App/ViewModels/Dialog/ForkRepositoryExecuteViewModel.cs b/src/GitHub.App/ViewModels/Dialog/ForkRepositoryExecuteViewModel.cs index b1a0804572..15f2cce9b7 100644 --- a/src/GitHub.App/ViewModels/Dialog/ForkRepositoryExecuteViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/ForkRepositoryExecuteViewModel.cs @@ -65,7 +65,7 @@ IRepositoryForkService repositoryForkService public IObservable Back => BackCommand; - public async Task InitializeAsync(ILocalRepositoryModel sourceRepository, IAccount destinationAccount, IConnection connection) + public async Task InitializeAsync(LocalRepositoryModel sourceRepository, IAccount destinationAccount, IConnection connection) { var modelService = await modelServiceFactory.CreateAsync(connection); apiClient = modelService.ApiClient; diff --git a/src/GitHub.App/ViewModels/Dialog/ForkRepositorySelectViewModel.cs b/src/GitHub.App/ViewModels/Dialog/ForkRepositorySelectViewModel.cs index 83c6c33499..9cfd7f5db7 100644 --- a/src/GitHub.App/ViewModels/Dialog/ForkRepositorySelectViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/ForkRepositorySelectViewModel.cs @@ -60,7 +60,7 @@ public bool IsLoading public IObservable Done => SelectedAccount.SelectNull(); - public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) + public async Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) { IsLoading = true; @@ -97,7 +97,7 @@ public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection } } - void BuildAccounts(IReadOnlyList accessibleAccounts, ILocalRepositoryModel currentRepository, IList forks, List parents) + void BuildAccounts(IReadOnlyList accessibleAccounts, LocalRepositoryModel currentRepository, IList forks, List parents) { log.Verbose("BuildAccounts: {AccessibleAccounts} accessibleAccounts, {Forks} forks, {Parents} parents", accessibleAccounts.Count, forks.Count, parents.Count); diff --git a/src/GitHub.App/ViewModels/Dialog/ForkRepositorySwitchViewModel.cs b/src/GitHub.App/ViewModels/Dialog/ForkRepositorySwitchViewModel.cs index cff2a303a6..f6e8ca7ce4 100644 --- a/src/GitHub.App/ViewModels/Dialog/ForkRepositorySwitchViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/ForkRepositorySwitchViewModel.cs @@ -41,7 +41,7 @@ public ForkRepositorySwitchViewModel(IRepositoryForkService repositoryForkServic public IObservable Done => SwitchFork.Where(value => value != null).SelectNull(); - public void Initialize(ILocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository) + public void Initialize(LocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository) { SourceRepository = sourceRepository; DestinationRepository = remoteRepository; diff --git a/src/GitHub.App/ViewModels/Dialog/ForkRepositoryViewModel.cs b/src/GitHub.App/ViewModels/Dialog/ForkRepositoryViewModel.cs index 6907afa224..f99ba38de9 100644 --- a/src/GitHub.App/ViewModels/Dialog/ForkRepositoryViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/ForkRepositoryViewModel.cs @@ -37,7 +37,7 @@ public ForkRepositoryViewModel( executePage.Back.Subscribe(x => ShowSelectPage().Forget()); } - public ILocalRepositoryModel Repository { get; private set; } + public LocalRepositoryModel Repository { get; private set; } public IConnection Connection { get; private set; } @@ -45,7 +45,7 @@ public ForkRepositoryViewModel( public override IObservable Done => executePage.Done; - public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) + public async Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) { Repository = repository; Connection = connection; diff --git a/src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs index 6620b8a064..05f70c788c 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs @@ -56,7 +56,7 @@ public sealed class GitHubPaneViewModel : ViewModelBase, IGitHubPaneViewModel, I IDisposable connectionSubscription; Task initializeTask; IViewModel content; - ILocalRepositoryModel localRepository; + LocalRepositoryModel localRepository; string searchQuery; [ImportingConstructor] @@ -191,7 +191,7 @@ public IViewModel Content public bool IsSearchEnabled => isSearchEnabled.Value; /// - public ILocalRepositoryModel LocalRepository + public LocalRepositoryModel LocalRepository { get { return localRepository; } private set { this.RaiseAndSetIfChanged(ref localRepository, value); } @@ -390,7 +390,7 @@ async Task NavigateTo(Func initialize, Func - public ILocalRepositoryModel LocalRepository { get; private set; } + public LocalRepositoryModel LocalRepository { get; private set; } /// public IssueListMessage Message @@ -126,7 +126,7 @@ public string SelectedState public ReactiveCommand OpenItem { get; } /// - public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) + public async Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) { try { diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index 188a6d2e05..22c9a2b936 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -41,7 +41,7 @@ public class PullRequestCreationViewModel : PanePageViewModelBase, IPullRequestC readonly IGitService gitService; readonly IScheduler timerScheduler; readonly CompositeDisposable disposables = new CompositeDisposable(); - ILocalRepositoryModel activeLocalRepo; + LocalRepositoryModel activeLocalRepo; ObservableAsPropertyHelper githubRepository; IModelService modelService; @@ -138,7 +138,7 @@ public PullRequestCreationViewModel( .Subscribe(x => IsBusy = x); } - public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) + public async Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) { modelService = await modelServiceFactory.CreateAsync(connection); activeLocalRepo = repository; diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs index 363f8d81c8..f968b391c3 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestDetailViewModel.cs @@ -162,7 +162,7 @@ private set /// /// Gets the local repository. /// - public ILocalRepositoryModel LocalRepository { get; private set; } + public LocalRepositoryModel LocalRepository { get; private set; } /// /// Gets the owner of the remote repository that contains the pull request. @@ -333,7 +333,7 @@ public IReadOnlyList Checks /// The pull request's repository name. /// The pull request number. public async Task InitializeAsync( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModel.cs index fc80765fd4..c263af4585 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModel.cs @@ -96,7 +96,7 @@ public PullRequestReviewAuthoringViewModel( } /// - public ILocalRepositoryModel LocalRepository { get; private set; } + public LocalRepositoryModel LocalRepository { get; private set; } /// public string RemoteRepositoryOwner { get; private set; } @@ -152,7 +152,7 @@ public IReadOnlyList FileComments public ReactiveCommand Cancel { get; } public async Task InitializeAsync( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestUserReviewsViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestUserReviewsViewModel.cs index 2faafcb3f9..718a906f1a 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestUserReviewsViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestUserReviewsViewModel.cs @@ -50,7 +50,7 @@ public PullRequestUserReviewsViewModel( } /// - public ILocalRepositoryModel LocalRepository { get; private set; } + public LocalRepositoryModel LocalRepository { get; private set; } /// public string RemoteRepositoryOwner { get; private set; } @@ -84,7 +84,7 @@ public string PullRequestTitle /// [SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "login")] public async Task InitializeAsync( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, diff --git a/src/GitHub.Exports.Reactive/Extensions/ConnectionManagerExtensions.cs b/src/GitHub.Exports.Reactive/Extensions/ConnectionManagerExtensions.cs index a13cd327d2..36737b61aa 100644 --- a/src/GitHub.Exports.Reactive/Extensions/ConnectionManagerExtensions.cs +++ b/src/GitHub.Exports.Reactive/Extensions/ConnectionManagerExtensions.cs @@ -10,7 +10,7 @@ public static class ConnectionManagerExtensions { public static async Task GetModelService( this IConnectionManager cm, - ILocalRepositoryModel repository, + LocalRepositoryModel repository, IModelServiceFactory factory) { var connection = await cm.GetConnection(repository); diff --git a/src/GitHub.Exports.Reactive/Services/IModelService.cs b/src/GitHub.Exports.Reactive/Services/IModelService.cs index 9a24371457..8cb87e0b15 100644 --- a/src/GitHub.Exports.Reactive/Services/IModelService.cs +++ b/src/GitHub.Exports.Reactive/Services/IModelService.cs @@ -27,7 +27,7 @@ public interface IModelService : IDisposable IObservable GetGitIgnoreTemplates(); IObservable GetPullRequest(string owner, string name, int number); ITrackingCollection GetPullRequests(IRepositoryModel repo, ITrackingCollection collection); - IObservable CreatePullRequest(ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + IObservable CreatePullRequest(LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body); IObservable GetBranches(IRepositoryModel repo); diff --git a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs index c45ef22c73..f29c2bcf2b 100644 --- a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs +++ b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs @@ -42,7 +42,7 @@ Task> ReadAssignableUsers( string after); IObservable CreatePullRequest(IModelService modelService, - ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body); @@ -51,14 +51,14 @@ IObservable CreatePullRequest(IModelService modelService, /// /// The repository. /// - IObservable IsWorkingDirectoryClean(ILocalRepositoryModel repository); + IObservable IsWorkingDirectoryClean(LocalRepositoryModel repository); /// /// Count the number of submodules that require syncing. /// /// The repository. /// The number of submodules that need to be synced. - IObservable CountSubmodulesToSync(ILocalRepositoryModel repository); + IObservable CountSubmodulesToSync(LocalRepositoryModel repository); /// /// Checks out a pull request to a local branch. @@ -67,26 +67,26 @@ IObservable CreatePullRequest(IModelService modelService, /// The pull request details. /// The name of the local branch. /// - IObservable Checkout(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest, string localBranchName); + IObservable Checkout(LocalRepositoryModel repository, PullRequestDetailModel pullRequest, string localBranchName); /// /// Carries out a pull on the current branch. /// /// The repository. - IObservable Pull(ILocalRepositoryModel repository); + IObservable Pull(LocalRepositoryModel repository); /// /// Carries out a push of the current branch. /// /// The repository. - IObservable Push(ILocalRepositoryModel repository); + IObservable Push(LocalRepositoryModel repository); /// /// Sync submodules on the current branch. /// /// The repository. /// A method that will be called with progress messages - Task SyncSubmodules(ILocalRepositoryModel repository, Action progress); + Task SyncSubmodules(LocalRepositoryModel repository, Action progress); /// /// Calculates the name of a local branch for a pull request avoiding clashes with existing branches. @@ -95,7 +95,7 @@ IObservable CreatePullRequest(IModelService modelService, /// The pull request number. /// The pull request title. /// - IObservable GetDefaultLocalBranchName(ILocalRepositoryModel repository, int pullRequestNumber, string pullRequestTitle); + IObservable GetDefaultLocalBranchName(LocalRepositoryModel repository, int pullRequestNumber, string pullRequestTitle); /// /// Gets the local branches that exist for the specified pull request. @@ -103,7 +103,7 @@ IObservable CreatePullRequest(IModelService modelService, /// The repository. /// The pull request details. /// - IObservable GetLocalBranches(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); + IObservable GetLocalBranches(LocalRepositoryModel repository, PullRequestDetailModel pullRequest); /// /// Ensures that all local branches for the specified pull request are marked as PR branches. @@ -119,7 +119,7 @@ IObservable CreatePullRequest(IModelService modelService, /// for the specified pull request are indeed marked and returns a value indicating whether any branches /// have had the mark added. /// - IObservable EnsureLocalBranchesAreMarkedAsPullRequests(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); + IObservable EnsureLocalBranchesAreMarkedAsPullRequests(LocalRepositoryModel repository, PullRequestDetailModel pullRequest); /// /// Determines whether the specified pull request is from the specified repository. @@ -127,7 +127,7 @@ IObservable CreatePullRequest(IModelService modelService, /// The repository. /// The pull request details. /// - bool IsPullRequestFromRepository(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); + bool IsPullRequestFromRepository(LocalRepositoryModel repository, PullRequestDetailModel pullRequest); /// /// Switches to an existing branch for the specified pull request. @@ -135,7 +135,7 @@ IObservable CreatePullRequest(IModelService modelService, /// The repository. /// The pull request details. /// - IObservable SwitchToBranch(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); + IObservable SwitchToBranch(LocalRepositoryModel repository, PullRequestDetailModel pullRequest); /// /// Gets the history divergence between the current HEAD and the specified pull request. @@ -143,7 +143,7 @@ IObservable CreatePullRequest(IModelService modelService, /// The repository. /// The pull request number. /// - IObservable CalculateHistoryDivergence(ILocalRepositoryModel repository, int pullRequestNumber); + IObservable CalculateHistoryDivergence(LocalRepositoryModel repository, int pullRequestNumber); /// /// Gets the SHA of the merge base for a pull request. @@ -151,7 +151,7 @@ IObservable CreatePullRequest(IModelService modelService, /// The repository. /// The pull request details. /// - Task GetMergeBase(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); + Task GetMergeBase(LocalRepositoryModel repository, PullRequestDetailModel pullRequest); /// /// Gets the changes between the pull request base and head. @@ -159,7 +159,7 @@ IObservable CreatePullRequest(IModelService modelService, /// The repository. /// The pull request details. /// - IObservable GetTreeChanges(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); + IObservable GetTreeChanges(LocalRepositoryModel repository, PullRequestDetailModel pullRequest); /// /// Gets the pull request associated with the current branch. @@ -171,9 +171,9 @@ IObservable CreatePullRequest(IModelService modelService, /// /// /// This method does not do an API request - it simply checks the mark left in the git - /// config by . + /// config by . /// - IObservable<(string owner, int number)> GetPullRequestForCurrentBranch(ILocalRepositoryModel repository); + IObservable<(string owner, int number)> GetPullRequestForCurrentBranch(LocalRepositoryModel repository); /// /// Gets the encoding for the specified local file. @@ -183,7 +183,7 @@ IObservable CreatePullRequest(IModelService modelService, /// /// The file's encoding or null if the file doesn't exist locally. /// - Encoding GetEncoding(ILocalRepositoryModel repository, string relativePath); + Encoding GetEncoding(LocalRepositoryModel repository, string relativePath); /// /// Extracts a file at the specified commit to a temporary file. @@ -197,7 +197,7 @@ IObservable CreatePullRequest(IModelService modelService, /// /// The path to the temporary file. Task ExtractToTempFile( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, PullRequestDetailModel pullRequest, string relativePath, string commitSha, @@ -209,9 +209,9 @@ Task ExtractToTempFile( /// /// The repository. /// - IObservable RemoveUnusedRemotes(ILocalRepositoryModel repository); + IObservable RemoveUnusedRemotes(LocalRepositoryModel repository); - IObservable GetPullRequestTemplate(ILocalRepositoryModel repository); + IObservable GetPullRequestTemplate(LocalRepositoryModel repository); /// /// Gets the unique commits from to the merge base of @@ -224,7 +224,7 @@ Task ExtractToTempFile( /// The maximum number of commits to return. /// An enumerable of unique commits from the merge base to the compareBranch. IObservable> GetMessagesForUniqueCommits( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, string baseBranch, string compareBranch, int maxCommits); diff --git a/src/GitHub.Exports.Reactive/Services/IPullRequestSession.cs b/src/GitHub.Exports.Reactive/Services/IPullRequestSession.cs index dcc60b4d6e..05a497afdc 100644 --- a/src/GitHub.Exports.Reactive/Services/IPullRequestSession.cs +++ b/src/GitHub.Exports.Reactive/Services/IPullRequestSession.cs @@ -39,7 +39,7 @@ public interface IPullRequestSession /// /// Gets the local repository. /// - ILocalRepositoryModel LocalRepository { get; } + LocalRepositoryModel LocalRepository { get; } /// /// Gets the owner of the repository that contains the pull request. diff --git a/src/GitHub.Exports.Reactive/Services/LocalRepositoriesExtensions.cs b/src/GitHub.Exports.Reactive/Services/LocalRepositoriesExtensions.cs index 76c808724a..02237f87dc 100644 --- a/src/GitHub.Exports.Reactive/Services/LocalRepositoriesExtensions.cs +++ b/src/GitHub.Exports.Reactive/Services/LocalRepositoriesExtensions.cs @@ -16,14 +16,14 @@ public static class LocalRepositoriesExtensions /// /// The local repositories object. /// The address. - public static IReactiveDerivedList GetRepositoriesForAddress( + public static IReactiveDerivedList GetRepositoriesForAddress( this ILocalRepositories repos, HostAddress address) { return repos.Repositories.CreateDerivedCollection( x => x, x => x.CloneUrl != null && address.Equals(HostAddress.Create(x.CloneUrl)), - OrderedComparer.OrderBy(x => x.Name).Compare); + OrderedComparer.OrderBy(x => x.Name).Compare); } } } diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryExecuteViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryExecuteViewModel.cs index 251f3fd66f..b7fb392aa1 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryExecuteViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryExecuteViewModel.cs @@ -46,7 +46,7 @@ public interface IForkRepositoryExecuteViewModel : IDialogContentViewModel /// The account to fork to. /// The connection to use. Task InitializeAsync( - ILocalRepositoryModel sourceRepository, + LocalRepositoryModel sourceRepository, IAccount destinationAccount, IConnection connection); } diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySelectViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySelectViewModel.cs index 21f7b9b7f2..f5acadbda4 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySelectViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySelectViewModel.cs @@ -42,6 +42,6 @@ public interface IForkRepositorySelectViewModel : IDialogContentViewModel /// /// The repository to fork. /// The connection to use. - Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection); + Task InitializeAsync(LocalRepositoryModel repository, IConnection connection); } } diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySwitchViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySwitchViewModel.cs index d908c1bb61..41e65b8f79 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySwitchViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySwitchViewModel.cs @@ -29,6 +29,6 @@ public interface IForkRepositorySwitchViewModel : IDialogContentViewModel /// /// The repository to fork. /// - void Initialize(ILocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository); + void Initialize(LocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository); } } \ No newline at end of file diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryViewModel.cs index e02e3e64a6..cb9d8c5d3d 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryViewModel.cs @@ -19,6 +19,6 @@ public interface IForkRepositoryViewModel : IDialogContentViewModel /// /// The repository to fork. /// The connection to use. - Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection); + Task InitializeAsync(LocalRepositoryModel repository, IConnection connection); } } diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IIssueListViewModelBase.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IIssueListViewModelBase.cs index 164677ef13..c7f782fe7e 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IIssueListViewModelBase.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IIssueListViewModelBase.cs @@ -63,7 +63,7 @@ public interface IIssueListViewModelBase : ISearchablePageViewModel /// /// Gets the local repository. /// - ILocalRepositoryModel LocalRepository { get; } + LocalRepositoryModel LocalRepository { get; } /// /// Gets an enum indicating a message that should be displayed in place of a list of items. @@ -105,6 +105,6 @@ public interface IIssueListViewModelBase : ISearchablePageViewModel /// The local repository. /// The connection/ /// A task tracking the operation. - Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection); + Task InitializeAsync(LocalRepositoryModel repository, IConnection connection); } } diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCreationViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCreationViewModel.cs index eaf9ec8944..444c5bd191 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCreationViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCreationViewModel.cs @@ -17,6 +17,6 @@ public interface IPullRequestCreationViewModel : IPanePageViewModel string PRTitle { get; set; } ReactivePropertyValidator TitleValidator { get; } - Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection); + Task InitializeAsync(LocalRepositoryModel repository, IConnection connection); } } diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestDetailViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestDetailViewModel.cs index 37e87ed78b..c10c6b2376 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestDetailViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestDetailViewModel.cs @@ -79,7 +79,7 @@ public interface IPullRequestDetailViewModel : IPanePageViewModel, IOpenInBrowse /// /// Gets the local repository. /// - ILocalRepositoryModel LocalRepository { get; } + LocalRepositoryModel LocalRepository { get; } /// /// Gets the owner of the remote repository that contains the pull request. @@ -189,7 +189,7 @@ public interface IPullRequestDetailViewModel : IPanePageViewModel, IOpenInBrowse /// The pull request's repository name. /// The pull request number. Task InitializeAsync( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestReviewAuthoringViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestReviewAuthoringViewModel.cs index 14034778a3..e0be2242d9 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestReviewAuthoringViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestReviewAuthoringViewModel.cs @@ -16,7 +16,7 @@ public interface IPullRequestReviewAuthoringViewModel : IPanePageViewModel, IDis /// /// Gets the local repository. /// - ILocalRepositoryModel LocalRepository { get; } + LocalRepositoryModel LocalRepository { get; } /// /// Gets the owner of the remote repository that contains the pull request. @@ -96,7 +96,7 @@ public interface IPullRequestReviewAuthoringViewModel : IPanePageViewModel, IDis /// The pull request's repository name. /// The pull request number. Task InitializeAsync( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestUserReviewsViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestUserReviewsViewModel.cs index 4ceae3b8d3..fa21f2753d 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestUserReviewsViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestUserReviewsViewModel.cs @@ -14,7 +14,7 @@ public interface IPullRequestUserReviewsViewModel : IPanePageViewModel /// /// Gets the local repository. /// - ILocalRepositoryModel LocalRepository { get; } + LocalRepositoryModel LocalRepository { get; } /// /// Gets the owner of the remote repository that contains the pull request. @@ -60,7 +60,7 @@ public interface IPullRequestUserReviewsViewModel : IPanePageViewModel /// The pull request number. /// The user's login. Task InitializeAsync( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, IConnection connection, string owner, string repo, diff --git a/src/GitHub.Exports/Extensions/LocalRepositoryModelExtensions.cs b/src/GitHub.Exports/Extensions/LocalRepositoryModelExtensions.cs index 4cb75caa17..f11d093947 100644 --- a/src/GitHub.Exports/Extensions/LocalRepositoryModelExtensions.cs +++ b/src/GitHub.Exports/Extensions/LocalRepositoryModelExtensions.cs @@ -8,7 +8,7 @@ namespace GitHub.Extensions { public static class LocalRepositoryModelExtensions { - public static bool HasCommits(this ILocalRepositoryModel repository) + public static bool HasCommits(this LocalRepositoryModel repository) { using (var repo = GitService.GitServiceHelper.GetRepository(repository.LocalPath)) { @@ -16,7 +16,7 @@ public static bool HasCommits(this ILocalRepositoryModel repository) } } - public static bool MightContainSolution(this ILocalRepositoryModel repository) + public static bool MightContainSolution(this LocalRepositoryModel repository) { var dir = new DirectoryInfo(repository.LocalPath); return dir.EnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly) diff --git a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs index 781180f4f2..e68d916586 100644 --- a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/ILocalRepositoryModel.cs @@ -1,15 +1,64 @@ -using System.ComponentModel; +using System; +using System.Diagnostics; +using System.Globalization; +using System.ComponentModel; namespace GitHub.Models { /// /// Represents a locally cloned repository. /// - public interface ILocalRepositoryModel : IRepositoryModel, INotifyPropertyChanged + /// + /// A locally cloned repository. + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class LocalRepositoryModel : RepositoryModel, INotifyPropertyChanged, IEquatable { /// - /// Gets the path to the repository on the filesystem. + /// Gets the local path of the repository. + /// + public string LocalPath + { + get; set; + } + + /// + /// Note: We don't consider CloneUrl a part of the hash code because it can change during the lifetime + /// of a repository. Equals takes care of any hash collisions because of this /// - string LocalPath { get; } + /// + public override int GetHashCode() + { + return 17 * 23 + (Name?.GetHashCode() ?? 0) * 23 + (Owner?.GetHashCode() ?? 0) * 23 + (LocalPath?.TrimEnd('\\').ToUpperInvariant().GetHashCode() ?? 0); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(this, obj)) + return true; + var other = obj as LocalRepositoryModel; + return Equals(other); + } + + public bool Equals(LocalRepositoryModel other) + { + if (ReferenceEquals(this, other)) + return true; + return other != null && + string.Equals(Name, other.Name) && + string.Equals(Owner, other.Owner) && + string.Equals(CloneUrl, other.CloneUrl) && + string.Equals(LocalPath?.TrimEnd('\\'), other.LocalPath?.TrimEnd('\\'), StringComparison.CurrentCultureIgnoreCase); + } + + internal string DebuggerDisplay => string.Format( + CultureInfo.InvariantCulture, + "{4}\tOwner: {0} Name: {1} CloneUrl: {2} LocalPath: {3}", + Owner, + Name, + CloneUrl, + LocalPath, + GetHashCode()); + } } diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs deleted file mode 100644 index 6e9e1e521e..0000000000 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Diagnostics; -using System.Globalization; - -namespace GitHub.Models -{ - /// - /// A locally cloned repository. - /// - [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class LocalRepositoryModel : RepositoryModel, ILocalRepositoryModel, IEquatable - { - /// - /// Gets the local path of the repository. - /// - public string LocalPath - { - get; set; - } - - /// - /// Note: We don't consider CloneUrl a part of the hash code because it can change during the lifetime - /// of a repository. Equals takes care of any hash collisions because of this - /// - /// - public override int GetHashCode() - { - return 17 * 23 + (Name?.GetHashCode() ?? 0) * 23 + (Owner?.GetHashCode() ?? 0) * 23 + (LocalPath?.TrimEnd('\\').ToUpperInvariant().GetHashCode() ?? 0); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(this, obj)) - return true; - var other = obj as LocalRepositoryModel; - return Equals(other); - } - - public bool Equals(LocalRepositoryModel other) - { - if (ReferenceEquals(this, other)) - return true; - return other != null && - string.Equals(Name, other.Name) && - string.Equals(Owner, other.Owner) && - string.Equals(CloneUrl, other.CloneUrl) && - string.Equals(LocalPath?.TrimEnd('\\'), other.LocalPath?.TrimEnd('\\'), StringComparison.CurrentCultureIgnoreCase); - } - - internal string DebuggerDisplay => string.Format( - CultureInfo.InvariantCulture, - "{4}\tOwner: {0} Name: {1} CloneUrl: {2} LocalPath: {3}", - Owner, - Name, - CloneUrl, - LocalPath, - GetHashCode()); - } -} diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 237ae472b4..7b992708ed 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -28,7 +28,7 @@ public GitService(IRepositoryFacade repositoryFacade) /// /// The repository's local path. /// A repository model. - public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) + public LocalRepositoryModel CreateLocalRepositoryModel(string localPath) { Guard.ArgumentNotNull(localPath, nameof(localPath)); @@ -52,7 +52,7 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) return model; } - public BranchModel GetBranch(ILocalRepositoryModel model) + public BranchModel GetBranch(LocalRepositoryModel model) { var localPath = model.LocalPath; using (var repo = GetRepository(localPath)) diff --git a/src/GitHub.Exports/Services/IDialogService.cs b/src/GitHub.Exports/Services/IDialogService.cs index 55a09c1493..cd367726b5 100644 --- a/src/GitHub.Exports/Services/IDialogService.cs +++ b/src/GitHub.Exports/Services/IDialogService.cs @@ -70,6 +70,6 @@ public interface IDialogService /// /// The repository to fork. /// The connection to use. May not be null. - Task ShowForkDialog(ILocalRepositoryModel repository, IConnection connection); + Task ShowForkDialog(LocalRepositoryModel repository, IConnection connection); } } diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index 46be343d66..d934ae0b01 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -12,14 +12,14 @@ public interface IGitService /// /// The repository's local path. /// A repository model. - ILocalRepositoryModel CreateLocalRepositoryModel(string localPath); + LocalRepositoryModel CreateLocalRepositoryModel(string localPath); /// /// Creates a new branch model for the current branch. /// - /// The to create a current branch model for. + /// The to create a current branch model for. /// A new branch model. - BranchModel GetBranch(ILocalRepositoryModel model); + BranchModel GetBranch(LocalRepositoryModel model); /// /// Returns the URL of the remote for the specified . If the repository diff --git a/src/GitHub.Exports/Services/ILocalRepositories.cs b/src/GitHub.Exports/Services/ILocalRepositories.cs index 1d77fbd13c..6a463f1b7f 100644 --- a/src/GitHub.Exports/Services/ILocalRepositories.cs +++ b/src/GitHub.Exports/Services/ILocalRepositories.cs @@ -13,7 +13,7 @@ public interface ILocalRepositories /// /// Gets the currently known local repositories. /// - IReadOnlyObservableCollection Repositories { get; } + IReadOnlyObservableCollection Repositories { get; } /// /// Updates . diff --git a/src/GitHub.Exports/Services/ITeamExplorerContext.cs b/src/GitHub.Exports/Services/ITeamExplorerContext.cs index d90c64e867..e09d9aa3b4 100644 --- a/src/GitHub.Exports/Services/ITeamExplorerContext.cs +++ b/src/GitHub.Exports/Services/ITeamExplorerContext.cs @@ -20,7 +20,7 @@ public interface ITeamExplorerContext : INotifyPropertyChanged /// /// This property might be changed by a non-UI thread. /// - ILocalRepositoryModel ActiveRepository { get; } + LocalRepositoryModel ActiveRepository { get; } /// /// Fired when the CurrentBranch or HeadSha changes. diff --git a/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs b/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs index c0ed91a252..16316aceea 100644 --- a/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs +++ b/src/GitHub.Exports/Services/ITeamExplorerServiceHolder.cs @@ -43,7 +43,7 @@ public interface ITeamExplorerServiceHolder public interface IGitAwareItem { - ILocalRepositoryModel ActiveRepo { get; } + LocalRepositoryModel ActiveRepo { get; } /// /// Represents the web URL of the repository on GitHub.com, even if the origin is an SSH address. diff --git a/src/GitHub.Exports/Services/IVSGitExt.cs b/src/GitHub.Exports/Services/IVSGitExt.cs index 3491aef125..076191f0a3 100644 --- a/src/GitHub.Exports/Services/IVSGitExt.cs +++ b/src/GitHub.Exports/Services/IVSGitExt.cs @@ -6,7 +6,7 @@ namespace GitHub.Services { public interface IVSGitExt { - IReadOnlyList ActiveRepositories { get; } + IReadOnlyList ActiveRepositories { get; } event Action ActiveRepositoriesChanged; void RefreshActiveRepositories(); } diff --git a/src/GitHub.Exports/Services/IVSGitServices.cs b/src/GitHub.Exports/Services/IVSGitServices.cs index 3795cd5974..8343ac92b2 100644 --- a/src/GitHub.Exports/Services/IVSGitServices.cs +++ b/src/GitHub.Exports/Services/IVSGitServices.cs @@ -30,7 +30,7 @@ Task Clone( string GetActiveRepoPath(); LibGit2Sharp.IRepository GetActiveRepo(); - IEnumerable GetKnownRepositories(); + IEnumerable GetKnownRepositories(); string SetDefaultProjectPath(string path); } } \ No newline at end of file diff --git a/src/GitHub.Exports/ViewModels/GitHubPane/IGitHubPaneViewModel.cs b/src/GitHub.Exports/ViewModels/GitHubPane/IGitHubPaneViewModel.cs index 6e44ca5bf0..ecab58b39d 100644 --- a/src/GitHub.Exports/ViewModels/GitHubPane/IGitHubPaneViewModel.cs +++ b/src/GitHub.Exports/ViewModels/GitHubPane/IGitHubPaneViewModel.cs @@ -55,7 +55,7 @@ public interface IGitHubPaneViewModel : IViewModel /// /// Gets the local repository. /// - ILocalRepositoryModel LocalRepository { get; } + LocalRepositoryModel LocalRepository { get; } /// /// Gets or sets the search query for the current page. diff --git a/src/GitHub.InlineReviews/Services/IPullRequestSessionService.cs b/src/GitHub.InlineReviews/Services/IPullRequestSessionService.cs index a867a4393a..7a3d9c845d 100644 --- a/src/GitHub.InlineReviews/Services/IPullRequestSessionService.cs +++ b/src/GitHub.InlineReviews/Services/IPullRequestSessionService.cs @@ -23,7 +23,7 @@ public interface IPullRequestSessionService /// The relative path to the file. /// Task> Diff( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, string baseSha, string headSha, string relativePath); @@ -38,7 +38,7 @@ Task> Diff( /// The contents of the file. /// Task> Diff( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, string baseSha, string headSha, string relativePath, @@ -83,7 +83,7 @@ IReadOnlyList> UpdateCommentThreads( /// pushed to origin; otherwise false. /// Task IsUnmodifiedAndPushed( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, string relativePath, byte[] contents); @@ -98,7 +98,7 @@ Task IsUnmodifiedAndPushed( /// The contents of the file, or null if the file was not found at the specified commit. /// Task ExtractFileFromGit( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, int pullRequestNumber, string sha, string relativePath); @@ -124,7 +124,7 @@ Task ExtractFileFromGit( /// /// The repository. /// The tip SHA. - Task GetTipSha(ILocalRepositoryModel repository); + Task GetTipSha(LocalRepositoryModel repository); /// /// Asynchronously reads the contents of a file. @@ -163,7 +163,7 @@ Task ExtractFileFromGit( /// /// The merge base SHA for the PR. /// - Task GetPullRequestMergeBase(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest); + Task GetPullRequestMergeBase(LocalRepositoryModel repository, PullRequestDetailModel pullRequest); /// /// Gets the GraphQL ID for a pull request. @@ -173,7 +173,7 @@ Task ExtractFileFromGit( /// The pull request number. /// Task GetGraphQLPullRequestId( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string repositoryOwner, int number); @@ -199,7 +199,7 @@ Task GetGraphQLPullRequestId( /// The GraphQL ID of the pull request. /// The updated state of the pull request. Task CreatePendingReview( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pullRequestId); /// @@ -209,7 +209,7 @@ Task CreatePendingReview( /// The GraphQL ID of the review. /// The updated state of the pull request. Task CancelPendingReview( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string reviewId); /// @@ -222,7 +222,7 @@ Task CancelPendingReview( /// The review event. /// The updated state of the pull request. Task PostReview( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pullRequestId, string commitId, string body, @@ -237,7 +237,7 @@ Task PostReview( /// The review event. /// The updated state of the pull request. Task SubmitPendingReview( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pendingReviewId, string body, PullRequestReviewEvent e); @@ -254,10 +254,10 @@ Task SubmitPendingReview( /// The updated state of the pull request. /// /// This method posts a new pull request comment to a pending review started by - /// . + /// . /// Task PostPendingReviewComment( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pendingReviewId, string body, string commitId, @@ -274,10 +274,10 @@ Task PostPendingReviewComment( /// The updated state of the pull request. /// /// The method posts a new pull request comment to a pending review started by - /// . + /// . /// Task PostPendingReviewCommentReply( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pendingReviewId, string body, string inReplyTo); @@ -297,7 +297,7 @@ Task PostPendingReviewCommentReply( /// pull request review. /// Task PostStandaloneReviewComment( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pullRequestId, string body, string commitId, @@ -313,7 +313,7 @@ Task PostStandaloneReviewComment( /// The GraphQL ID of the comment to reply to. /// The updated state of the pull request. Task PostStandaloneReviewCommentReply( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pullRequestId, string body, string inReplyTo); @@ -326,7 +326,7 @@ Task PostStandaloneReviewCommentReply( /// The pull request id of the comment /// The pull request comment number. /// The updated state of the pull request. - Task DeleteComment(ILocalRepositoryModel localRepository, + Task DeleteComment(LocalRepositoryModel localRepository, string remoteRepositoryOwner, int pullRequestId, int commentDatabaseId); @@ -339,7 +339,7 @@ Task DeleteComment(ILocalRepositoryModel localRepository /// The pull request comment node id. /// The replacement comment body. /// The updated state of the pull request. - Task EditComment(ILocalRepositoryModel localRepository, + Task EditComment(LocalRepositoryModel localRepository, string remoteRepositoryOwner, string commentNodeId, string body); diff --git a/src/GitHub.InlineReviews/Services/PullRequestSession.cs b/src/GitHub.InlineReviews/Services/PullRequestSession.cs index 0759b996d2..88f2995824 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSession.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSession.cs @@ -42,7 +42,7 @@ public PullRequestSession( IPullRequestSessionService service, ActorModel user, PullRequestDetailModel pullRequest, - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string repositoryOwner, bool isCheckedOut) { @@ -402,7 +402,7 @@ private set public IObservable PullRequestChanged => pullRequestChanged; /// - public ILocalRepositoryModel LocalRepository { get; } + public LocalRepositoryModel LocalRepository { get; } /// public string RepositoryOwner { get; } diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs index b8e10ccf8e..d9f31eba5e 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs @@ -35,7 +35,7 @@ public class PullRequestSessionManager : ReactiveObject, IPullRequestSessionMana new Dictionary, WeakReference>(); TaskCompletionSource initialized; IPullRequestSession currentSession; - ILocalRepositoryModel repository; + LocalRepositoryModel repository; /// /// Initializes a new instance of the class. @@ -182,7 +182,7 @@ public PullRequestTextBufferInfo GetTextBufferInfo(ITextBuffer buffer) return null; } - async Task RepoChanged(ILocalRepositoryModel localRepositoryModel) + async Task RepoChanged(LocalRepositoryModel localRepositoryModel) { repository = localRepositoryModel; CurrentSession = null; diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs index 56f8570903..17342cab4e 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs @@ -80,7 +80,7 @@ public PullRequestSessionService( } /// - public virtual async Task> Diff(ILocalRepositoryModel repository, string baseSha, string headSha, string relativePath) + public virtual async Task> Diff(LocalRepositoryModel repository, string baseSha, string headSha, string relativePath) { using (var repo = await GetRepository(repository)) { @@ -89,7 +89,7 @@ public virtual async Task> Diff(ILocalRepositoryModel r } /// - public virtual async Task> Diff(ILocalRepositoryModel repository, string baseSha, string headSha, string relativePath, byte[] contents) + public virtual async Task> Diff(LocalRepositoryModel repository, string baseSha, string headSha, string relativePath, byte[] contents) { using (var repo = await GetRepository(repository)) { @@ -217,7 +217,7 @@ public ITextDocument GetDocument(ITextBuffer buffer) } /// - public virtual async Task GetTipSha(ILocalRepositoryModel repository) + public virtual async Task GetTipSha(LocalRepositoryModel repository) { using (var repo = await GetRepository(repository)) { @@ -226,7 +226,7 @@ public virtual async Task GetTipSha(ILocalRepositoryModel repository) } /// - public async Task IsUnmodifiedAndPushed(ILocalRepositoryModel repository, string relativePath, byte[] contents) + public async Task IsUnmodifiedAndPushed(LocalRepositoryModel repository, string relativePath, byte[] contents) { using (var repo = await GetRepository(repository)) { @@ -238,7 +238,7 @@ public async Task IsUnmodifiedAndPushed(ILocalRepositoryModel repository, } public async Task ExtractFileFromGit( - ILocalRepositoryModel repository, + LocalRepositoryModel repository, int pullRequestNumber, string sha, string relativePath) @@ -387,7 +387,7 @@ public virtual async Task ReadViewer(HostAddress address) } public async Task GetGraphQLPullRequestId( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string repositoryOwner, int number) { @@ -403,7 +403,7 @@ public async Task GetGraphQLPullRequestId( } /// - public virtual async Task GetPullRequestMergeBase(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest) + public virtual async Task GetPullRequestMergeBase(LocalRepositoryModel repository, PullRequestDetailModel pullRequest) { var baseSha = pullRequest.BaseRefSha; var headSha = pullRequest.HeadRefSha; @@ -447,7 +447,7 @@ public virtual ISubject CreateRebuildSignal() /// public async Task CreatePendingReview( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pullRequestId) { var address = HostAddress.Create(localRepository.CloneUrl.Host); @@ -462,7 +462,7 @@ public async Task CreatePendingReview( /// public async Task CancelPendingReview( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string reviewId) { var address = HostAddress.Create(localRepository.CloneUrl.Host); @@ -487,7 +487,7 @@ public async Task CancelPendingReview( /// public async Task PostReview( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pullRequestId, string commitId, string body, @@ -518,7 +518,7 @@ public async Task PostReview( } public async Task SubmitPendingReview( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pendingReviewId, string body, PullRequestReviewEvent e) @@ -548,7 +548,7 @@ public async Task SubmitPendingReview( /// public async Task PostPendingReviewComment( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pendingReviewId, string body, string commitId, @@ -582,7 +582,7 @@ public async Task PostPendingReviewComment( /// public async Task PostPendingReviewCommentReply( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pendingReviewId, string body, string inReplyTo) @@ -612,7 +612,7 @@ public async Task PostPendingReviewCommentReply( /// public async Task PostStandaloneReviewComment( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pullRequestId, string body, string commitId, @@ -654,7 +654,7 @@ public async Task PostStandaloneReviewComment( /// public async Task PostStandaloneReviewCommentReply( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string pullRequestId, string body, string inReplyTo) @@ -666,7 +666,7 @@ public async Task PostStandaloneReviewCommentReply( /// public async Task DeleteComment( - ILocalRepositoryModel localRepository, + LocalRepositoryModel localRepository, string remoteRepositoryOwner, int pullRequestId, int commentDatabaseId) @@ -684,7 +684,7 @@ await apiClient.DeletePullRequestReviewComment( } /// - public async Task EditComment(ILocalRepositoryModel localRepository, + public async Task EditComment(LocalRepositoryModel localRepository, string remoteRepositoryOwner, string commentNodeId, string body) @@ -710,7 +710,7 @@ public async Task EditComment(ILocalRepositoryModel loca return await ReadPullRequestDetail(address, result.Login, localRepository.Name, result.Number); } - async Task<(string id, string owner, int number)> CreatePendingReviewCore(ILocalRepositoryModel localRepository, string pullRequestId) + async Task<(string id, string owner, int number)> CreatePendingReviewCore(LocalRepositoryModel localRepository, string pullRequestId) { var address = HostAddress.Create(localRepository.CloneUrl.Host); var graphql = await graphqlFactory.CreateConnection(address); @@ -747,7 +747,7 @@ int GetUpdatedLineNumber(IInlineCommentThreadModel thread, IEnumerable GetRepository(ILocalRepositoryModel repository) + Task GetRepository(LocalRepositoryModel repository) { return Task.Factory.StartNew(() => gitService.GetRepository(repository.LocalPath)); } diff --git a/src/GitHub.InlineReviews/Services/PullRequestStatusBarManager.cs b/src/GitHub.InlineReviews/Services/PullRequestStatusBarManager.cs index 8bbc3ed148..94583183df 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestStatusBarManager.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestStatusBarManager.cs @@ -80,7 +80,7 @@ public void StartShowingStatus() } } - async Task RefreshCurrentSession(ILocalRepositoryModel repository, IPullRequestSession session) + async Task RefreshCurrentSession(LocalRepositoryModel repository, IPullRequestSession session) { var showStatus = await IsDotComOrEnterpriseRepository(repository); if (!showStatus) @@ -93,7 +93,7 @@ async Task RefreshCurrentSession(ILocalRepositoryModel repository, IPullRequestS ShowStatus(viewModel); } - async Task IsDotComOrEnterpriseRepository(ILocalRepositoryModel repository) + async Task IsDotComOrEnterpriseRepository(LocalRepositoryModel repository) { var cloneUrl = repository?.CloneUrl; if (cloneUrl == null) diff --git a/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs b/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs index 3bcfe6f458..f01f657860 100644 --- a/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs +++ b/src/GitHub.TeamFoundation.14/Base/TeamExplorerNavigationItemBase.cs @@ -57,7 +57,7 @@ void TeamExplorerContext_PropertyChanged(object sender, PropertyChangedEventArgs } } - void UpdateRepoOnMainThread(ILocalRepositoryModel repo) + void UpdateRepoOnMainThread(LocalRepositoryModel repo) { holder.JoinableTaskFactory.RunAsync(async () => { @@ -79,7 +79,7 @@ void OnThemeChanged() Icon = SharedResources.GetDrawingForIcon(octicon, dark ? Colors.DarkThemeNavigationItem : Colors.LightThemeNavigationItem, theme); } - void UpdateRepo(ILocalRepositoryModel repo) + void UpdateRepo(LocalRepositoryModel repo) { var changed = ActiveRepo != repo; ActiveRepo = repo; diff --git a/src/GitHub.TeamFoundation.14/Connect/GitHubConnectSection.cs b/src/GitHub.TeamFoundation.14/Connect/GitHubConnectSection.cs index d93a1c9666..7c18915ed2 100644 --- a/src/GitHub.TeamFoundation.14/Connect/GitHubConnectSection.cs +++ b/src/GitHub.TeamFoundation.14/Connect/GitHubConnectSection.cs @@ -87,15 +87,15 @@ public bool ShowRetry private set { showRetry = value; this.RaisePropertyChange(); } } - IReactiveDerivedList repositories; - public IReactiveDerivedList Repositories + IReactiveDerivedList repositories; + public IReactiveDerivedList Repositories { get { return repositories; } private set { repositories = value; this.RaisePropertyChange(); } } - ILocalRepositoryModel selectedRepository; - public ILocalRepositoryModel SelectedRepository + LocalRepositoryModel selectedRepository; + public LocalRepositoryModel SelectedRepository { get { return selectedRepository; } set { selectedRepository = value; this.RaisePropertyChange(); } @@ -314,7 +314,7 @@ async void UpdateRepositoryList(object sender, NotifyCollectionChangedEventArgs // so we can handle just one new entry separately if (isCloning || isCreating) { - var newrepo = e.NewItems.Cast().First(); + var newrepo = e.NewItems.Cast().First(); SelectedRepository = newrepo; if (isCreating) @@ -343,7 +343,7 @@ async void UpdateRepositoryList(object sender, NotifyCollectionChangedEventArgs else { e.NewItems - .Cast() + .Cast() .ForEach(async r => { if (Equals(holder.TeamExplorerContext.ActiveRepository, r)) @@ -368,7 +368,7 @@ async void UpdateRepositoryList(object sender, NotifyCollectionChangedEventArgs } } - void HandleCreatedRepo(ILocalRepositoryModel newrepo) + void HandleCreatedRepo(LocalRepositoryModel newrepo) { Guard.ArgumentNotNull(newrepo, nameof(newrepo)); @@ -377,7 +377,7 @@ void HandleCreatedRepo(ILocalRepositoryModel newrepo) ShowNotification(newrepo, msg); } - void HandleClonedRepo(ILocalRepositoryModel newrepo) + void HandleClonedRepo(LocalRepositoryModel newrepo) { Guard.ArgumentNotNull(newrepo, nameof(newrepo)); @@ -389,7 +389,7 @@ void HandleClonedRepo(ILocalRepositoryModel newrepo) ShowNotification(newrepo, msg); } - void ShowNotification(ILocalRepositoryModel newrepo, string msg) + void ShowNotification(LocalRepositoryModel newrepo, string msg) { Guard.ArgumentNotNull(newrepo, nameof(newrepo)); diff --git a/src/GitHub.TeamFoundation.14/RegistryHelper.cs b/src/GitHub.TeamFoundation.14/RegistryHelper.cs index dafba2e15f..e36aa9f536 100644 --- a/src/GitHub.TeamFoundation.14/RegistryHelper.cs +++ b/src/GitHub.TeamFoundation.14/RegistryHelper.cs @@ -24,13 +24,13 @@ static RegistryKey OpenGitKey(string path) return Registry.CurrentUser.OpenSubKey(keyName, true); } - internal static IEnumerable PokeTheRegistryForRepositoryList() + internal static IEnumerable PokeTheRegistryForRepositoryList() { using (var key = OpenGitKey("Repositories")) { if (key == null) { - return Enumerable.Empty(); + return Enumerable.Empty(); } return key.GetSubKeyNames().Select(x => diff --git a/src/GitHub.TeamFoundation.14/Services/VSGitExt.cs b/src/GitHub.TeamFoundation.14/Services/VSGitExt.cs index 10167940e0..004b9704df 100644 --- a/src/GitHub.TeamFoundation.14/Services/VSGitExt.cs +++ b/src/GitHub.TeamFoundation.14/Services/VSGitExt.cs @@ -31,7 +31,7 @@ public class VSGitExt : IVSGitExt readonly object refreshLock = new object(); IGitExt gitExt; - IReadOnlyList activeRepositories; + IReadOnlyList activeRepositories; public VSGitExt(IServiceProvider serviceProvider, IGitService gitService) : this(serviceProvider, new VSUIContextFactory(), gitService, ThreadHelper.JoinableTaskContext) @@ -49,7 +49,7 @@ public VSGitExt(IServiceProvider serviceProvider, IVSUIContextFactory factory, I this.gitService = gitService; // Start with empty array until we have a chance to initialize. - ActiveRepositories = Array.Empty(); + ActiveRepositories = Array.Empty(); // The IGitExt service isn't available when a TFS based solution is opened directly. // It will become available when moving to a Git based solution (and cause a UIContext event to fire). @@ -100,11 +100,11 @@ public void RefreshActiveRepositories() catch (Exception e) { log.Error(e, "Error refreshing repositories"); - ActiveRepositories = Array.Empty(); + ActiveRepositories = Array.Empty(); } } - public IReadOnlyList ActiveRepositories + public IReadOnlyList ActiveRepositories { get { diff --git a/src/GitHub.TeamFoundation.14/Services/VSGitServices.cs b/src/GitHub.TeamFoundation.14/Services/VSGitServices.cs index 106d76875d..0696a6f7f1 100644 --- a/src/GitHub.TeamFoundation.14/Services/VSGitServices.cs +++ b/src/GitHub.TeamFoundation.14/Services/VSGitServices.cs @@ -188,7 +188,7 @@ public string GetActiveRepoPath() return ret ?? String.Empty; } - public IEnumerable GetKnownRepositories() + public IEnumerable GetKnownRepositories() { try { @@ -197,7 +197,7 @@ public IEnumerable GetKnownRepositories() catch (Exception ex) { log.Error(ex, "Error loading the repository list from the registry"); - return Enumerable.Empty(); + return Enumerable.Empty(); } } diff --git a/src/GitHub.TeamFoundation.14/Sync/GitHubPublishSection.cs b/src/GitHub.TeamFoundation.14/Sync/GitHubPublishSection.cs index 3ce2d7c286..203e10c684 100644 --- a/src/GitHub.TeamFoundation.14/Sync/GitHubPublishSection.cs +++ b/src/GitHub.TeamFoundation.14/Sync/GitHubPublishSection.cs @@ -132,14 +132,14 @@ public void ShowPublish() }); } - void HandleCreatedRepo(ILocalRepositoryModel newrepo) + void HandleCreatedRepo(LocalRepositoryModel newrepo) { var msg = String.Format(CultureInfo.CurrentCulture, Constants.Notification_RepoCreated, newrepo.Name, newrepo.CloneUrl); msg += " " + String.Format(CultureInfo.CurrentCulture, Constants.Notification_CreateNewProject, newrepo.LocalPath); ShowNotification(newrepo, msg); } - private void ShowNotification(ILocalRepositoryModel newrepo, string msg) + private void ShowNotification(LocalRepositoryModel newrepo, string msg) { var teServices = ServiceProvider.TryGetService(); diff --git a/src/GitHub.VisualStudio.UI/Base/TeamExplorerGitRepoInfo.cs b/src/GitHub.VisualStudio.UI/Base/TeamExplorerGitRepoInfo.cs index f8e0ca43ed..b93a5bdd76 100644 --- a/src/GitHub.VisualStudio.UI/Base/TeamExplorerGitRepoInfo.cs +++ b/src/GitHub.VisualStudio.UI/Base/TeamExplorerGitRepoInfo.cs @@ -14,8 +14,8 @@ public TeamExplorerGitRepoInfo(IGitHubServiceProvider serviceProvider) : base(se activeRepoName = string.Empty; } - ILocalRepositoryModel activeRepo; - public ILocalRepositoryModel ActiveRepo + LocalRepositoryModel activeRepo; + public LocalRepositoryModel ActiveRepo { get { return activeRepo; } set diff --git a/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs b/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs index 3094aab45a..d38c679fcb 100644 --- a/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs +++ b/src/GitHub.VisualStudio.UI/Base/TeamExplorerItemBase.cs @@ -92,7 +92,7 @@ void TeamExplorerContext_PropertyChanged(object sender, PropertyChangedEventArgs } } - void UpdateRepoOnMainThread(ILocalRepositoryModel repo) + void UpdateRepoOnMainThread(LocalRepositoryModel repo) { holder.JoinableTaskFactory.RunAsync(async () => { @@ -110,7 +110,7 @@ void Unsubscribe() holder.ClearServiceProvider(TEServiceProvider); } - void UpdateRepo(ILocalRepositoryModel repo) + void UpdateRepo(LocalRepositoryModel repo) { var changed = ActiveRepo != repo; ActiveRepo = repo; diff --git a/src/GitHub.VisualStudio.UI/UI/Views/GitHubConnectContent.xaml.cs b/src/GitHub.VisualStudio.UI/UI/Views/GitHubConnectContent.xaml.cs index 7fb8770e05..72c140b07b 100644 --- a/src/GitHub.VisualStudio.UI/UI/Views/GitHubConnectContent.xaml.cs +++ b/src/GitHub.VisualStudio.UI/UI/Views/GitHubConnectContent.xaml.cs @@ -73,7 +73,7 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur if (values.Length != 2 || parameter as string != "FormatRepositoryName") return String.Empty; - var item = values[0] as ILocalRepositoryModel; + var item = values[0] as LocalRepositoryModel; var context = values[1] as IGitHubConnectSection; if (item == null) return String.Empty; @@ -98,7 +98,7 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur if (values.Length != 2 || parameter as string != "IsCurrentRepository") return false; - var item = values[0] as ILocalRepositoryModel; + var item = values[0] as LocalRepositoryModel; var context = values[1] as IGitAwareItem; return context?.ActiveRepoUri == item?.CloneUrl && String.Equals(context?.ActiveRepo?.LocalPath, item?.LocalPath, StringComparison.OrdinalIgnoreCase); } diff --git a/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs b/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs index 6d94938629..d7a1a56008 100644 --- a/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs +++ b/src/GitHub.VisualStudio/Commands/LinkCommandBase.cs @@ -36,14 +36,14 @@ protected LinkCommandBase( lazyGitService = gitService; } - protected ILocalRepositoryModel ActiveRepo { get; private set; } + protected LocalRepositoryModel ActiveRepo { get; private set; } protected ISimpleApiClientFactory ApiFactory => apiFactory.Value; protected IGitHubServiceProvider ServiceProvider { get; } protected IUsageTracker UsageTracker => usageTracker.Value; public abstract override Task Execute(); - protected ILocalRepositoryModel GetRepositoryByPath(string path) + protected LocalRepositoryModel GetRepositoryByPath(string path) { try { @@ -61,7 +61,7 @@ protected ILocalRepositoryModel GetRepositoryByPath(string path) return null; } - protected ILocalRepositoryModel GetActiveRepo() + protected LocalRepositoryModel GetActiveRepo() { var activeRepo = ServiceProvider.TryGetService()?.TeamExplorerContext.ActiveRepository; // activeRepo can be null at this point because it is set elsewhere as the result of async operation that may not have completed yet. @@ -175,7 +175,7 @@ public static bool IsFileDescendantOfDirectory(string file, string directory) /// The end of a line range on the specified file. /// An UriString with the generated url, or null if the repository has no remote server configured or if it can't be found locally public static async Task GenerateUrl(IGitService gitService, - ILocalRepositoryModel repo, LinkType linkType, string path = null, int startLine = -1, int endLine = -1) + LocalRepositoryModel repo, LinkType linkType, string path = null, int startLine = -1, int endLine = -1) { if (repo.CloneUrl == null) return null; diff --git a/src/GitHub.VisualStudio/Services/LocalRepositories.cs b/src/GitHub.VisualStudio/Services/LocalRepositories.cs index d413b39422..b66e2e1e0b 100644 --- a/src/GitHub.VisualStudio/Services/LocalRepositories.cs +++ b/src/GitHub.VisualStudio/Services/LocalRepositories.cs @@ -37,10 +37,10 @@ public async Task Refresh() list.Except(repositories).ToList().ForEach(x => repositories.Add(x)); } - readonly ObservableCollectionEx repositories - = new ObservableCollectionEx(); + readonly ObservableCollectionEx repositories + = new ObservableCollectionEx(); /// - public IReadOnlyObservableCollection Repositories => repositories; + public IReadOnlyObservableCollection Repositories => repositories; } } diff --git a/test/GitHub.Api.UnitTests/Args.cs b/test/GitHub.Api.UnitTests/Args.cs index d0cbd27215..85bd43fd9e 100644 --- a/test/GitHub.Api.UnitTests/Args.cs +++ b/test/GitHub.Api.UnitTests/Args.cs @@ -25,7 +25,7 @@ internal static class Args public static LibGit2Sharp.IRepository LibGit2Repo { get { return Arg.Any(); } } public static LibGit2Sharp.Branch LibGit2Branch { get { return Arg.Any(); } } public static Remote LibgGit2Remote { get { return Arg.Any(); } } - public static ILocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } + public static LocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } diff --git a/test/GitHub.App.UnitTests/Args.cs b/test/GitHub.App.UnitTests/Args.cs index d0cbd27215..85bd43fd9e 100644 --- a/test/GitHub.App.UnitTests/Args.cs +++ b/test/GitHub.App.UnitTests/Args.cs @@ -25,7 +25,7 @@ internal static class Args public static LibGit2Sharp.IRepository LibGit2Repo { get { return Arg.Any(); } } public static LibGit2Sharp.Branch LibGit2Branch { get { return Arg.Any(); } } public static Remote LibgGit2Remote { get { return Arg.Any(); } } - public static ILocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } + public static LocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } diff --git a/test/GitHub.App.UnitTests/Models/ModelServiceTests.cs b/test/GitHub.App.UnitTests/Models/ModelServiceTests.cs index f58cfb0255..5335ed080f 100644 --- a/test/GitHub.App.UnitTests/Models/ModelServiceTests.cs +++ b/test/GitHub.App.UnitTests/Models/ModelServiceTests.cs @@ -392,7 +392,7 @@ public async Task NonExpiredIndexReturnsCacheAsync() apiClient.GetOrganizations().Returns(Observable.Empty()); var act = modelService.GetAccounts().ToEnumerable().First().First(); - var repo = Substitute.For(); + var repo = Substitute.For(); repo.Name.Returns(reponame); repo.CloneUrl.Returns(new UriString("https://github.com/" + username + "/" + reponame)); @@ -444,7 +444,7 @@ public async Task ExpiredIndexReturnsLiveAsync() apiClient.GetOrganizations().Returns(Observable.Empty()); var act = modelService.GetAccounts().ToEnumerable().First().First(); - var repo = Substitute.For(); + var repo = Substitute.For(); repo.Name.Returns(reponame); repo.Owner.Returns(user.Login); repo.CloneUrl.Returns(new UriString("https://github.com/" + username + "/" + reponame)); @@ -513,7 +513,7 @@ public async Task ExpiredIndexClearsItemsAsync() apiClient.GetOrganizations().Returns(Observable.Empty()); var act = modelService.GetAccounts().ToEnumerable().First().First(); - var repo = Substitute.For(); + var repo = Substitute.For(); repo.Name.Returns(reponame); repo.Owner.Returns(user.Login); repo.CloneUrl.Returns(new UriString("https://github.com/" + username + "/" + reponame)); diff --git a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs index e5d69bcc72..0b3dd677cd 100644 --- a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs +++ b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs @@ -581,10 +581,10 @@ static PullRequestService CreatePullRequestService(Repository repo) return service; } - static ILocalRepositoryModel CreateLocalRepositoryModel(Repository repo) + static LocalRepositoryModel CreateLocalRepositoryModel(Repository repo) { var repoDir = repo.Info.WorkingDirectory; - var repositoryModel = Substitute.For(); + var repositoryModel = Substitute.For(); repositoryModel.LocalPath.Returns(repoDir); return repositoryModel; } @@ -598,7 +598,7 @@ public async Task ExtractsExistingFile_Async() { var gitClient = MockGitClient(); var target = CreateTarget(gitClient); - var repository = Substitute.For(); + var repository = Substitute.For(); var fileContent = "file content"; var pr = CreatePullRequest(); @@ -620,7 +620,7 @@ public async Task CreatesEmptyFileForNonExistentFileAsync() { var gitClient = MockGitClient(); var target = CreateTarget(gitClient); - var repository = Substitute.For(); + var repository = Substitute.For(); var pr = CreatePullRequest(); gitClient.ExtractFile(Arg.Any(), "123", "filename").Returns(GetFileTaskAsync(null)); @@ -647,7 +647,7 @@ public async Task CanChangeEncodingAsync(string encodingName) var fileContent = "file content"; var gitClient = MockGitClient(); var target = CreateTarget(gitClient); - var repository = Substitute.For(); + var repository = Substitute.For(); var pr = CreatePullRequest(); var expectedPath = Path.Combine(repoDir, fileName); @@ -689,8 +689,8 @@ public void CreatePullRequestAllArgsMandatory() Substitute.For()); IModelService ms = null; - ILocalRepositoryModel sourceRepo = null; - ILocalRepositoryModel targetRepo = null; + LocalRepositoryModel sourceRepo = null; + LocalRepositoryModel targetRepo = null; string title = null; string body = null; BranchModel source = null; @@ -730,7 +730,7 @@ public async Task ShouldCheckoutExistingBranchAsync() var gitClient = MockGitClient(); var service = CreateTarget(gitClient, MockGitService()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); var pr = new PullRequestDetailModel { @@ -754,7 +754,7 @@ public async Task ShouldCheckoutLocalBranchAsync() var gitClient = MockGitClient(); var service = CreateTarget(gitClient, MockGitService()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo")); var pr = new PullRequestDetailModel @@ -783,7 +783,7 @@ public async Task ShouldCheckoutLocalBranchOwnerCaseMismatchAsync() var gitClient = MockGitClient(); var service = CreateTarget(gitClient, MockGitService()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); localRepo.CloneUrl.Returns(new UriString("https://foo.bar/Owner/repo")); var pr = new PullRequestDetailModel @@ -812,7 +812,7 @@ public async Task ShouldCheckoutBranchFromForkAsync() var gitClient = MockGitClient(); var service = CreateTarget(gitClient, MockGitService()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo")); var pr = new PullRequestDetailModel @@ -845,7 +845,7 @@ public async Task ShouldUseUniquelyNamedRemoteForForkAsync() var gitService = MockGitService(); var service = CreateTarget(gitClient, gitService); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo")); using (var repo = gitService.GetRepository(localRepo.CloneUrl)) @@ -881,7 +881,7 @@ public async Task ShouldReturnCorrectDefaultLocalBranchNameAsync() { var service = CreateTarget(MockGitClient(), MockGitService()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); var result = await service.GetDefaultLocalBranchName(localRepo, 123, "Pull requests can be \"named\" all sorts of thing's (sic)"); Assert.That("pr/123-pull-requests-can-be-named-all-sorts-of-thing-s-sic", Is.EqualTo(result)); } @@ -897,7 +897,7 @@ public async Task ShouldReturnCorrectDefaultLocalBranchNameForPullRequestsWithNo Substitute.For(), Substitute.For()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); var result = await service.GetDefaultLocalBranchName(localRepo, 123, "コードをレビューする準備ができたこと"); Assert.That("pr/123", Is.EqualTo(result)); } @@ -907,7 +907,7 @@ public async Task DefaultLocalBranchNameShouldNotClashWithExistingBranchNamesAsy { var service = CreateTarget(MockGitClient(), MockGitService()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); var result = await service.GetDefaultLocalBranchName(localRepo, 123, "foo1"); Assert.That("pr/123-foo1-3", Is.EqualTo(result)); } @@ -920,7 +920,7 @@ public async Task ShouldReturnPullRequestBranchForPullRequestFromSameRepositoryA { var service = CreateTarget(MockGitClient(), MockGitService()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); localRepo.CloneUrl.Returns(new UriString("https://github.com/foo/bar")); var result = await service.GetLocalBranches(localRepo, CreatePullRequest(fromFork: false)); @@ -933,7 +933,7 @@ public async Task ShouldReturnPullRequestBranchForPullRequestFromSameRepositoryO { var service = CreateTarget(MockGitClient(), MockGitService()); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); localRepo.CloneUrl.Returns(new UriString("https://github.com/Foo/bar")); var result = await service.GetLocalBranches(localRepo, CreatePullRequest(fromFork: false)); @@ -964,7 +964,7 @@ public async Task ShouldReturnMarkedBranchForPullRequestFromForkAsync() var service = CreateTarget(MockGitClient(), MockGitService(repo)); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); localRepo.CloneUrl.Returns(new UriString("https://github.com/foo/bar.git")); var result = await service.GetLocalBranches(localRepo, CreatePullRequest(true)); @@ -1004,7 +1004,7 @@ public async Task ShouldRemoveUnusedRemoteAsync() var gitService = MockGitService(); var service = CreateTarget(gitClient, gitService); - var localRepo = Substitute.For(); + var localRepo = Substitute.For(); localRepo.CloneUrl.Returns(new UriString("https://github.com/foo/bar")); using (var repo = gitService.GetRepository(localRepo.CloneUrl)) diff --git a/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs b/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs index 6e202f0aaf..9ffe378d85 100644 --- a/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs +++ b/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs @@ -202,9 +202,9 @@ static TeamExplorerContext CreateTeamExplorerContext( return new TeamExplorerContext(gitExt, new AsyncLazy(() => Task.FromResult(dte)), pullRequestService, joinableTaskContext); } - static ILocalRepositoryModel CreateRepositoryModel(string path) + static LocalRepositoryModel CreateRepositoryModel(string path) { - var repo = Substitute.For(); + var repo = Substitute.For(); repo.LocalPath.Returns(path); return repo; } @@ -214,9 +214,9 @@ static IVSGitExt CreateGitExt() return Substitute.For(); } - static void SetActiveRepository(IVSGitExt gitExt, ILocalRepositoryModel repo) + static void SetActiveRepository(IVSGitExt gitExt, LocalRepositoryModel repo) { - var repos = repo != null ? new[] { repo } : Array.Empty(); + var repos = repo != null ? new[] { repo } : Array.Empty(); gitExt.ActiveRepositories.Returns(repos); gitExt.ActiveRepositoriesChanged += Raise.Event(); } diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/GitHubPaneViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/GitHubPaneViewModelTests.cs index c8cc19d815..621891ccb7 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/GitHubPaneViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/GitHubPaneViewModelTests.cs @@ -24,7 +24,7 @@ public class TheInitializeMethod public async Task NotAGitRepositoryShownWhenNoRepositoryAsync() { var te = Substitute.For(); - te.ActiveRepository.Returns(null as ILocalRepositoryModel); + te.ActiveRepository.Returns(null as LocalRepositoryModel); var target = CreateTarget(teamExplorerContext: te); await InitializeAsync(target); @@ -282,7 +282,7 @@ static INavigationViewModel CreateNavigator() static ITeamExplorerContext CreateTeamExplorerContext(string repositoryCloneUrl) { - var repository = Substitute.For(); + var repository = Substitute.For(); repository.CloneUrl.Returns(new UriString(repositoryCloneUrl)); var result = Substitute.For(); result.ActiveRepository.Returns(repository); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/IssueListViewModelBaseTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/IssueListViewModelBaseTests.cs index 6963c29fdd..20af1a9060 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/IssueListViewModelBaseTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/IssueListViewModelBaseTests.cs @@ -92,11 +92,11 @@ public async Task No_Items_With_Author_Filter_Returns_Message_NoOpenItems() Assert.That(target.Message, Is.EqualTo(IssueListMessage.NoItemsMatchCriteria)); } - protected static ILocalRepositoryModel CreateLocalRepository( + protected static LocalRepositoryModel CreateLocalRepository( string owner = "owner", string name = "name") { - var result = Substitute.For(); + var result = Substitute.For(); result.CloneUrl.Returns(new UriString($"https://giuthub.com/{owner}/{name}")); result.Owner.Returns(owner); result.Name.Returns(name); @@ -146,7 +146,7 @@ static Target CreateTarget(IRepositoryService repositoryService = null, int item static async Task CreateTargetAndInitialize( IRepositoryService repositoryService = null, - ILocalRepositoryModel repository = null, + LocalRepositoryModel repository = null, IConnection connection = null, int itemCount = 1000) { diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index a68cc38a89..2ccd0a3e35 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -43,7 +43,7 @@ static LibGit2Sharp.IRepository SetupLocalRepoMock(IGitClient gitClient, IGitSer struct TestData { public IServiceProvider ServiceProvider; - public ILocalRepositoryModel ActiveRepo; + public LocalRepositoryModel ActiveRepo; public LibGit2Sharp.IRepository L2Repo; public IRepositoryModel SourceRepo; public IRepositoryModel TargetRepo; @@ -82,7 +82,7 @@ static TestData PrepareTestData( connection.HostAddress.Returns(HostAddress.Create("https://github.com")); // this is the local repo instance that is available via TeamExplorerServiceHolder and friends - var activeRepo = Substitute.For(); + var activeRepo = Substitute.For(); activeRepo.LocalPath.Returns(""); activeRepo.Name.Returns(repoName); activeRepo.CloneUrl.Returns(new UriString("http://github.com/" + sourceRepoOwner + "/" + repoName)); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs index c90066cfd0..f6e2cd985f 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs @@ -550,7 +550,7 @@ static Tuple CreateTargetAndSer int behindBy = 0, IPullRequestSessionManager sessionManager = null) { - var repository = Substitute.For(); + var repository = Substitute.For(); var currentBranchModel = new BranchModel(currentBranch, repository); var gitService = Substitute.For(); gitService.GetBranch(repository).Returns(currentBranchModel); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestFilesViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestFilesViewModelTests.cs index c4fff09d4a..cf84feea92 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestFilesViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestFilesViewModelTests.cs @@ -100,7 +100,7 @@ static IPullRequestSession CreateSession() { var author = Substitute.For(); - var repository = Substitute.For(); + var repository = Substitute.For(); repository.LocalPath.Returns(@"C:\Foo"); var result = Substitute.For(); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestListViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestListViewModelTests.cs index adb8654359..0efab52f8f 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestListViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestListViewModelTests.cs @@ -45,7 +45,7 @@ static async Task CreateTargetAndInitialize( IPullRequestSessionManager sessionManager = null, IRepositoryService repositoryService = null, IPullRequestService service = null, - ILocalRepositoryModel repository = null, + LocalRepositoryModel repository = null, IConnection connection = null) { var result = CreateTarget(sessionManager, repositoryService, service); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModelTests.cs index 4036307ba2..0ac818eea2 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModelTests.cs @@ -605,9 +605,9 @@ static IPullRequestSessionManager CreateSessionManager( return result; } - static ILocalRepositoryModel CreateLocalRepositoryModel() + static LocalRepositoryModel CreateLocalRepositoryModel() { - var result = Substitute.For(); + var result = Substitute.For(); result.CloneUrl.Returns(new UriString("https://github.com/owner/repo")); result.Owner.Returns("owner"); result.Name.Returns("repo"); @@ -616,7 +616,7 @@ static ILocalRepositoryModel CreateLocalRepositoryModel() static async Task InitializeAsync( IPullRequestReviewAuthoringViewModel target, - ILocalRepositoryModel localRepository = null) + LocalRepositoryModel localRepository = null) { localRepository = localRepository ?? CreateLocalRepositoryModel(); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestUserReviewsViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestUserReviewsViewModelTests.cs index 061985d76d..94cd7a8cd6 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestUserReviewsViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestUserReviewsViewModelTests.cs @@ -161,7 +161,7 @@ public async Task First_Review_Is_Expanded_Async() async Task InitializeAsync( PullRequestUserReviewsViewModel target, - ILocalRepositoryModel localRepository = null, + LocalRepositoryModel localRepository = null, IConnection connection = null, int pullRequestNumber = 5, string login = AuthorLogin) @@ -214,9 +214,9 @@ IModelServiceFactory CreateFactory(IModelService modelService) return result; } - ILocalRepositoryModel CreateRepository(string owner = "owner", string name = "repo") + LocalRepositoryModel CreateRepository(string owner = "owner", string name = "repo") { - var result = Substitute.For(); + var result = Substitute.For(); result.Owner.Returns(owner); result.Name.Returns(name); return result; diff --git a/test/GitHub.Exports.UnitTests/Args.cs b/test/GitHub.Exports.UnitTests/Args.cs index b917e86353..f157abeefc 100644 --- a/test/GitHub.Exports.UnitTests/Args.cs +++ b/test/GitHub.Exports.UnitTests/Args.cs @@ -23,7 +23,7 @@ internal static class Args public static LibGit2Sharp.IRepository LibGit2Repo { get { return Arg.Any(); } } public static LibGit2Sharp.Branch LibGit2Branch { get { return Arg.Any(); } } public static Remote LibgGit2Remote { get { return Arg.Any(); } } - public static ILocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } + public static LocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } diff --git a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs index 7b49b9ff2c..e36b633e0c 100644 --- a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs +++ b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs @@ -237,7 +237,7 @@ public async Task DiffIsSet() sessionService.GetContents(textView.TextBuffer).Returns(contents); sessionService.GetPullRequestMergeBase(null, null).ReturnsForAnyArgs("MERGE_BASE"); sessionService.Diff( - Arg.Any(), + Arg.Any(), "MERGE_BASE", "HEADSHA", FilePath, @@ -690,7 +690,7 @@ IPullRequestSessionService CreateRealSessionService( Substitute.For()); result.CreateRebuildSignal().Returns(new Subject()); result.GetPullRequestMergeBase( - Arg.Any(), + Arg.Any(), Arg.Any()).Returns("MERGE_BASE"); result.ReadPullRequestDetail( Arg.Any(), @@ -819,7 +819,7 @@ public async Task GetSessionUpdatesCurrentSessionIfCurrentBranchIsPullRequestBut Assert.That(target.CurrentSession, Is.Null); - service.EnsureLocalBranchesAreMarkedAsPullRequests(Arg.Any(), model).Returns(Observable.Return(true)); + service.EnsureLocalBranchesAreMarkedAsPullRequests(Arg.Any(), model).Returns(Observable.Return(true)); service.GetPullRequestForCurrentBranch(null).ReturnsForAnyArgs(Observable.Return(("owner", CurrentBranchPullRequestNumber))); var session = await target.GetSession("owner", "name", CurrentBranchPullRequestNumber); @@ -912,9 +912,9 @@ IPullRequestSessionService CreateSessionService( return sessionService; } - ILocalRepositoryModel CreateRepositoryModel(string cloneUrl = OwnerCloneUrl) + LocalRepositoryModel CreateRepositoryModel(string cloneUrl = OwnerCloneUrl) { - var result = Substitute.For(); + var result = Substitute.For(); var uriString = new UriString(cloneUrl); result.CloneUrl.Returns(uriString); result.Name.Returns(uriString.RepositoryName); @@ -922,14 +922,14 @@ ILocalRepositoryModel CreateRepositoryModel(string cloneUrl = OwnerCloneUrl) return result; } - static ITeamExplorerContext CreateTeamExplorerContext(ILocalRepositoryModel repo) + static ITeamExplorerContext CreateTeamExplorerContext(LocalRepositoryModel repo) { var teamExplorerContext = Substitute.For(); teamExplorerContext.ActiveRepository.Returns(repo); return teamExplorerContext; } - static void SetActiveRepository(ITeamExplorerContext teamExplorerContext, ILocalRepositoryModel localRepositoryModel) + static void SetActiveRepository(ITeamExplorerContext teamExplorerContext, LocalRepositoryModel localRepositoryModel) { teamExplorerContext.ActiveRepository.Returns(localRepositoryModel); var eventArgs = new PropertyChangedEventArgs(nameof(teamExplorerContext.ActiveRepository)); diff --git a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionTests.cs b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionTests.cs index 7389fc99a3..124cbb5637 100644 --- a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionTests.cs +++ b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionTests.cs @@ -29,7 +29,7 @@ public void IsFalseWithNoPendingReview() CreateRealSessionService(), CreateActor(), CreatePullRequest(), - Substitute.For(), + Substitute.For(), "owner", true); @@ -48,7 +48,7 @@ public void IsFalseWithPendingReviewForOtherUser() CreateRealSessionService(), currentUser, pr, - Substitute.For(), + Substitute.For(), "owner", true); @@ -66,7 +66,7 @@ public void IsFalseWithNonPendingReviewForCurrentUser() CreateRealSessionService(), currentUser, pr, - Substitute.For(), + Substitute.For(), "owner", true); @@ -84,7 +84,7 @@ public void IsTrueWithPendingReviewForCurrentUser() CreateRealSessionService(), currentUser, pr, - Substitute.For(), + Substitute.For(), "owner", true); @@ -148,7 +148,7 @@ public async Task IsFalseWhenReviewCancelled() service, currentUser, pr, - Substitute.For(), + Substitute.For(), "owner", true); @@ -170,7 +170,7 @@ public async Task BaseShaIsSet() CreateRealSessionService(), CreateActor(), CreatePullRequest(), - Substitute.For(), + Substitute.For(), "owner", true); var file = await target.GetFile(FilePath); @@ -185,7 +185,7 @@ public async Task HeadCommitShaIsSet() CreateRealSessionService(), CreateActor(), CreatePullRequest(), - Substitute.For(), + Substitute.For(), "owner", true); var file = await target.GetFile(FilePath); @@ -201,7 +201,7 @@ public async Task PinnedCommitShaIsSet() CreateRealSessionService(), CreateActor(), CreatePullRequest(), - Substitute.For(), + Substitute.For(), "owner", true); var file = await target.GetFile(FilePath, "123"); @@ -217,7 +217,7 @@ public async Task DiffShaIsSet() var sessionService = CreateRealSessionService(); sessionService.Diff( - Arg.Any(), + Arg.Any(), "MERGE_BASE", "HEAD_SHA", FilePath).Returns(diff); @@ -226,7 +226,7 @@ public async Task DiffShaIsSet() sessionService, CreateActor(), CreatePullRequest(), - Substitute.For(), + Substitute.For(), "owner", true); var file = await target.GetFile(FilePath); @@ -264,7 +264,7 @@ Line 2 service, CreateActor(), pullRequest, - Substitute.For(), + Substitute.For(), "owner", true); @@ -281,7 +281,7 @@ public async Task SameNonHeadCommitShasReturnSameFiles() CreateRealSessionService(), CreateActor(), CreatePullRequest(), - Substitute.For(), + Substitute.For(), "owner", true); var file1 = await target.GetFile(FilePath, "123"); @@ -297,7 +297,7 @@ public async Task DifferentCommitShasReturnDifferentFiles() CreateRealSessionService(), CreateActor(), CreatePullRequest(), - Substitute.For(), + Substitute.For(), "owner", true); var file1 = await target.GetFile(FilePath, "123"); @@ -316,7 +316,7 @@ public void ThrowsWithNoPendingReview() CreateRealSessionService(), CreateActor(), CreatePullRequest(), - Substitute.For(), + Substitute.For(), "owner", true); @@ -334,7 +334,7 @@ public async Task CallsServiceWithNodeId() await target.CancelReview(); await service.Received(1).CancelPendingReview( - Arg.Any(), + Arg.Any(), "review1"); } @@ -365,7 +365,7 @@ public static PullRequestSession CreateTargetWithPendingReview( service, currentUser, pr, - Substitute.For(), + Substitute.For(), "owner", true); } @@ -747,9 +747,9 @@ static PullRequestDetailModel CreatePullRequest(params PullRequestReviewThreadMo }; } - static ILocalRepositoryModel CreateLocalRepository() + static LocalRepositoryModel CreateLocalRepository() { - var result = Substitute.For(); + var result = Substitute.For(); result.CloneUrl.Returns(new UriString("https://github.com/owner/repo")); return result; } @@ -770,8 +770,8 @@ static IPullRequestSessionService CreateRealSessionService(IDiffService diffServ Substitute.For(), Substitute.For()); - result.GetTipSha(Arg.Any()).Returns("BRANCH_TIP"); - result.GetPullRequestMergeBase(Arg.Any(), Arg.Any()) + result.GetTipSha(Arg.Any()).Returns("BRANCH_TIP"); + result.GetPullRequestMergeBase(Arg.Any(), Arg.Any()) .Returns("MERGE_BASE"); return result; } @@ -782,7 +782,7 @@ static PullRequestSession CreateTarget( string remoteRepositoryOwner, bool hasPendingReview) { - var repository = Substitute.For(); + var repository = Substitute.For(); repository.CloneUrl.Returns(new UriString($"https://github.com/{localRepositoryOwner}/reop")); repository.Owner.Returns(localRepositoryOwner); diff --git a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs index 7f54e16ad0..98a03e6427 100644 --- a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs +++ b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs @@ -295,9 +295,9 @@ public IReadOnlyList ActiveRepositories class MockGitService : IGitService { - public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) + public LocalRepositoryModel CreateLocalRepositoryModel(string localPath) { - var result = Substitute.For(); + var result = Substitute.For(); result.LocalPath.Returns(localPath); if (localPath == "repo1") @@ -311,7 +311,7 @@ public ILocalRepositoryModel CreateLocalRepositoryModel(string localPath) return result; } - public BranchModel GetBranch(ILocalRepositoryModel model) => throw new NotImplementedException(); + public BranchModel GetBranch(LocalRepositoryModel model) => throw new NotImplementedException(); public Task GetLatestPushedSha(string path, string remote = "origin") => throw new NotImplementedException(); public UriString GetRemoteUri(IRepository repo, string remote = "origin") => throw new NotImplementedException(); public IRepository GetRepository(string path) => throw new NotImplementedException(); diff --git a/test/GitHub.VisualStudio.UnitTests/Args.cs b/test/GitHub.VisualStudio.UnitTests/Args.cs index d0cbd27215..85bd43fd9e 100644 --- a/test/GitHub.VisualStudio.UnitTests/Args.cs +++ b/test/GitHub.VisualStudio.UnitTests/Args.cs @@ -25,7 +25,7 @@ internal static class Args public static LibGit2Sharp.IRepository LibGit2Repo { get { return Arg.Any(); } } public static LibGit2Sharp.Branch LibGit2Branch { get { return Arg.Any(); } } public static Remote LibgGit2Remote { get { return Arg.Any(); } } - public static ILocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } + public static LocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } diff --git a/test/GitHub.VisualStudio.UnitTests/Commands/LinkCommandBaseTests.cs b/test/GitHub.VisualStudio.UnitTests/Commands/LinkCommandBaseTests.cs index 8be88301a7..c993149b73 100644 --- a/test/GitHub.VisualStudio.UnitTests/Commands/LinkCommandBaseTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Commands/LinkCommandBaseTests.cs @@ -46,7 +46,7 @@ public async Task GenerateUrl(int testid, LinkType linkType, bool createRootedPa var basePath = temp.Directory.CreateSubdirectory("generate-url-test1-" + testid); if (createRootedPath && path != null) path = System.IO.Path.Combine(basePath.FullName, path); - ILocalRepositoryModel model = null; + LocalRepositoryModel model = null; model = new LocalRepositoryModel { Name = "bar", CloneUrl = baseUrl, LocalPath = basePath.FullName }; var result = await LinkCommandBase.GenerateUrl(gitService, model, linkType, path, startLine, endLine); diff --git a/test/GitHub.VisualStudio.UnitTests/Services/LocalRepositoriesTests.cs b/test/GitHub.VisualStudio.UnitTests/Services/LocalRepositoriesTests.cs index 16d43caaf9..cff16e8bf6 100644 --- a/test/GitHub.VisualStudio.UnitTests/Services/LocalRepositoriesTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Services/LocalRepositoriesTests.cs @@ -116,19 +116,19 @@ static IVSGitServices CreateVSGitServices(params string[] names) static IVSGitServices CreateVSGitServices(params Tuple[] namesAndAddresses) { var result = Substitute.For(); - var repositories = new List(namesAndAddresses.Select(CreateRepository)); + var repositories = new List(namesAndAddresses.Select(CreateRepository)); result.GetKnownRepositories().Returns(repositories); return result; } - static ILocalRepositoryModel CreateRepository(string name) + static LocalRepositoryModel CreateRepository(string name) { return CreateRepository(Tuple.Create(name, "https://github.com")); } - static ILocalRepositoryModel CreateRepository(Tuple nameAndAddress) + static LocalRepositoryModel CreateRepository(Tuple nameAndAddress) { - var result = Substitute.For(); + var result = Substitute.For(); result.Name.Returns(nameAndAddress.Item1); result.CloneUrl.Returns(new UriString(nameAndAddress.Item2)); return result; From a1ff038263b8fbdc601ae72ba3a49126f85fa390 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Fri, 2 Nov 2018 14:15:16 +0000 Subject: [PATCH 33/39] Correct model file names --- src/GitHub.Exports/Models/{IBranch.cs => BranchModel.cs} | 0 .../Models/{ILocalRepositoryModel.cs => LocalRepositoryModel.cs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/GitHub.Exports/Models/{IBranch.cs => BranchModel.cs} (100%) rename src/GitHub.Exports/Models/{ILocalRepositoryModel.cs => LocalRepositoryModel.cs} (100%) diff --git a/src/GitHub.Exports/Models/IBranch.cs b/src/GitHub.Exports/Models/BranchModel.cs similarity index 100% rename from src/GitHub.Exports/Models/IBranch.cs rename to src/GitHub.Exports/Models/BranchModel.cs diff --git a/src/GitHub.Exports/Models/ILocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs similarity index 100% rename from src/GitHub.Exports/Models/ILocalRepositoryModel.cs rename to src/GitHub.Exports/Models/LocalRepositoryModel.cs From e2b74f9625065e5e273816484db84e904dcdec83 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Mon, 5 Nov 2018 12:14:33 +0000 Subject: [PATCH 34/39] Remove interfaces from Remote/RepositoryModel RepositoryModel and RemoteRepositoryModel are now pure models without interfaces. --- .../Clone/SelectPageViewModelDesigner.cs | 2 +- .../ForkRepositoryExecuteViewModelDesigner.cs | 4 +- .../ForkRepositorySelectViewModelDesigner.cs | 4 +- .../ForkRepositorySwitchViewModelDesigner.cs | 6 +-- .../PullRequestListViewModelDesigner.cs | 4 +- .../RemoteRepositoryModelDesigner.cs | 10 ++-- .../RepositoryRecloneViewModelDesigner.cs | 2 +- src/GitHub.App/SampleData/SampleViewModels.cs | 2 +- src/GitHub.App/Services/DialogService.cs | 2 +- src/GitHub.App/Services/ModelService.cs | 32 ++++++------- src/GitHub.App/Services/PullRequestService.cs | 4 +- .../Services/RepositoryForkService.cs | 4 +- .../Dialog/Clone/RepositoryCloneViewModel.cs | 6 +-- .../Dialog/Clone/RepositorySelectViewModel.cs | 6 +-- .../Dialog/Clone/RepositoryUrlViewModel.cs | 6 +-- .../Dialog/ForkRepositoryExecuteViewModel.cs | 4 +- .../Dialog/ForkRepositorySelectViewModel.cs | 14 +++--- .../Dialog/ForkRepositorySwitchViewModel.cs | 6 +-- .../Dialog/ForkRepositoryViewModel.cs | 2 +- .../Dialog/RepositoryRecloneViewModel.cs | 4 +- .../GitHubPane/IssueListViewModelBase.cs | 10 ++-- .../PullRequestCreationViewModel.cs | 4 +- .../Caches/AccountCacheItem.cs | 1 + .../Models/Account.cs | 0 .../Models/RemoteRepositoryModel.cs | 26 ++++------ .../Services/IModelService.cs | 14 +++--- .../Services/IPullRequestService.cs | 2 +- .../Services/IRepositoryForkService.cs | 4 +- .../Services/ModelServiceExtensions.cs | 2 +- .../Clone/IRepositoryCloneTabViewModel.cs | 2 +- .../Dialog/IForkRepositoryExecuteViewModel.cs | 4 +- .../Dialog/IForkRepositorySelectViewModel.cs | 4 +- .../Dialog/IForkRepositorySwitchViewModel.cs | 6 +-- .../Dialog/IRepositoryRecloneViewModel.cs | 2 +- .../GitHubPane/IIssueListViewModelBase.cs | 6 +-- .../Extensions/ConnectionManagerExtensions.cs | 2 +- src/GitHub.Exports/Models/BranchModel.cs | 6 +-- .../Models/IRemoteRepositoryModel.cs | 47 ------------------- src/GitHub.Exports/Models/IRepositoryModel.cs | 39 --------------- src/GitHub.Exports/Models/RepositoryModel.cs | 2 +- src/GitHub.Exports/Services/GitService.cs | 4 +- src/GitHub.Exports/Services/IDialogService.cs | 2 +- src/GitHub.Exports/Services/IGitService.cs | 4 +- src/GitHub.StartPage/StartPagePackage.cs | 4 +- .../Converters/BranchNameConverter.cs | 4 +- src/GitHub.UI/GitHub.UI.csproj | 1 + .../Dialog/ForkRepositorySelectView.xaml.cs | 2 +- test/GitHub.Api.UnitTests/Args.cs | 11 +++-- test/GitHub.App.UnitTests/Args.cs | 6 +-- .../Clone/RepositoryCloneViewModelTests.cs | 12 ++--- .../PullRequestCreationViewModelTests.cs | 4 +- test/GitHub.Exports.UnitTests/Args.cs | 6 +-- .../GitHub.Exports.UnitTests.csproj | 1 + test/GitHub.VisualStudio.UnitTests/Args.cs | 6 +-- 54 files changed, 143 insertions(+), 231 deletions(-) rename src/{GitHub.App => GitHub.Exports.Reactive}/Models/Account.cs (100%) rename src/{GitHub.App => GitHub.Exports.Reactive}/Models/RemoteRepositoryModel.cs (90%) delete mode 100644 src/GitHub.Exports/Models/IRemoteRepositoryModel.cs delete mode 100644 src/GitHub.Exports/Models/IRepositoryModel.cs diff --git a/src/GitHub.App/SampleData/Dialog/Clone/SelectPageViewModelDesigner.cs b/src/GitHub.App/SampleData/Dialog/Clone/SelectPageViewModelDesigner.cs index ff6fc6e49e..82df1bfae9 100644 --- a/src/GitHub.App/SampleData/Dialog/Clone/SelectPageViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/Dialog/Clone/SelectPageViewModelDesigner.cs @@ -38,7 +38,7 @@ public SelectPageViewModelDesigner() public IReadOnlyList Items { get; } public ICollectionView ItemsView { get; } public IRepositoryItemViewModel SelectedItem { get; set; } - public IRepositoryModel Repository { get; } + public RepositoryModel Repository { get; } public void Initialize(IConnection connection) { diff --git a/src/GitHub.App/SampleData/ForkRepositoryExecuteViewModelDesigner.cs b/src/GitHub.App/SampleData/ForkRepositoryExecuteViewModelDesigner.cs index e04f605bd8..74d05021ab 100644 --- a/src/GitHub.App/SampleData/ForkRepositoryExecuteViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/ForkRepositoryExecuteViewModelDesigner.cs @@ -35,9 +35,9 @@ public ForkRepositoryExecuteViewModelDesigner() public string Title => null; - public IRepositoryModel SourceRepository { get; set; } + public RepositoryModel SourceRepository { get; set; } - public IRepositoryModel DestinationRepository { get; set; } + public RepositoryModel DestinationRepository { get; set; } public IAccount DestinationAccount { get; } diff --git a/src/GitHub.App/SampleData/ForkRepositorySelectViewModelDesigner.cs b/src/GitHub.App/SampleData/ForkRepositorySelectViewModelDesigner.cs index 4326e3fdaf..ddbdaf80fd 100644 --- a/src/GitHub.App/SampleData/ForkRepositorySelectViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/ForkRepositorySelectViewModelDesigner.cs @@ -33,7 +33,7 @@ public ForkRepositorySelectViewModelDesigner() public IObservable Done => null; - public IReadOnlyList ExistingForks { get; set; } + public IReadOnlyList ExistingForks { get; set; } public bool IsLoading { get; set; } @@ -41,7 +41,7 @@ public ForkRepositorySelectViewModelDesigner() public ReactiveCommand SelectedAccount => null; - public ReactiveCommand SwitchOrigin => null; + public ReactiveCommand SwitchOrigin => null; public Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) { diff --git a/src/GitHub.App/SampleData/ForkRepositorySwitchViewModelDesigner.cs b/src/GitHub.App/SampleData/ForkRepositorySwitchViewModelDesigner.cs index 940013509d..2fa298fa05 100644 --- a/src/GitHub.App/SampleData/ForkRepositorySwitchViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/ForkRepositorySwitchViewModelDesigner.cs @@ -29,9 +29,9 @@ public ForkRepositorySwitchViewModelDesigner() public IObservable Done => null; - public IRepositoryModel SourceRepository { get; } + public RepositoryModel SourceRepository { get; } - public IRepositoryModel DestinationRepository { get; } + public RepositoryModel DestinationRepository { get; } public ReactiveCommand SwitchFork => null; @@ -41,7 +41,7 @@ public ForkRepositorySwitchViewModelDesigner() public bool UpdateOrigin { get; set; } = true; - public void Initialize(LocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository) + public void Initialize(LocalRepositoryModel sourceRepository, RemoteRepositoryModel remoteRepository) { } } diff --git a/src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs index f0e6d79e81..46b572c5d9 100644 --- a/src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs @@ -55,8 +55,8 @@ public PullRequestListViewModelDesigner() public ICollectionView ItemsView { get; } public LocalRepositoryModel LocalRepository { get; set; } public IssueListMessage Message { get; set; } - public IRepositoryModel RemoteRepository { get; set; } - public IReadOnlyList Forks { get; } + public RepositoryModel RemoteRepository { get; set; } + public IReadOnlyList Forks { get; } public string SearchQuery { get; set; } public string SelectedState { get; set; } public string StateCaption { get; set; } diff --git a/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs b/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs index 6768bcdaae..d82d298979 100644 --- a/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs +++ b/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs @@ -6,7 +6,7 @@ namespace GitHub.SampleData { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1036:OverrideMethodsOnComparableTypes")] - public class RemoteRepositoryModelDesigner : IRemoteRepositoryModel + public class RemoteRepositoryModelDesigner : RemoteRepositoryModel { public UriString CloneUrl { get; set; } public DateTimeOffset CreatedAt { get; set; } @@ -17,20 +17,20 @@ public class RemoteRepositoryModelDesigner : IRemoteRepositoryModel public string Name { get; set; } public string Owner { get; set; } public IAccount OwnerAccount { get; set; } - public IRemoteRepositoryModel Parent { get; set; } + public RemoteRepositoryModel Parent { get; set; } public DateTimeOffset UpdatedAt { get; set; } - public int CompareTo(IRemoteRepositoryModel other) + public int CompareTo(RemoteRepositoryModel other) { return 0; } - public void CopyFrom(IRemoteRepositoryModel other) + public void CopyFrom(RemoteRepositoryModel other) { } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] - public bool Equals(IRemoteRepositoryModel other) + public bool Equals(RemoteRepositoryModel other) { return false; } diff --git a/src/GitHub.App/SampleData/RepositoryRecloneViewModelDesigner.cs b/src/GitHub.App/SampleData/RepositoryRecloneViewModelDesigner.cs index 477ab7cb7b..274f58d9c1 100644 --- a/src/GitHub.App/SampleData/RepositoryRecloneViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/RepositoryRecloneViewModelDesigner.cs @@ -17,7 +17,7 @@ public class RepositoryRecloneViewModelDesigner : ViewModelBase, IRepositoryRecl public ReactivePropertyValidator BaseRepositoryPathValidator { get; } public ICommand BrowseForDirectory { get; } public ReactiveCommand CloneCommand { get; } - public IRepositoryModel SelectedRepository { get; set; } + public RepositoryModel SelectedRepository { get; set; } public IObservable Done { get; } public Task InitializeAsync(IConnection connection) => Task.CompletedTask; diff --git a/src/GitHub.App/SampleData/SampleViewModels.cs b/src/GitHub.App/SampleData/SampleViewModels.cs index 552392c2de..9a2a430e9f 100644 --- a/src/GitHub.App/SampleData/SampleViewModels.cs +++ b/src/GitHub.App/SampleData/SampleViewModels.cs @@ -254,7 +254,7 @@ public IConnection SelectedConnection [ExcludeFromCodeCoverage] public static class RepositoryModelDesigner { - public static IRemoteRepositoryModel Create(string name = null, string owner = null) + public static RemoteRepositoryModel Create(string name = null, string owner = null) { name = name ?? "octocat"; owner = owner ?? "github"; diff --git a/src/GitHub.App/Services/DialogService.cs b/src/GitHub.App/Services/DialogService.cs index 1814522ee6..ecce4a1cfa 100644 --- a/src/GitHub.App/Services/DialogService.cs +++ b/src/GitHub.App/Services/DialogService.cs @@ -52,7 +52,7 @@ public async Task ShowCloneDialog(IConnection connection, str } } - public async Task ShowReCloneDialog(IRepositoryModel repository) + public async Task ShowReCloneDialog(RepositoryModel repository) { Guard.ArgumentNotNull(repository, nameof(repository)); diff --git a/src/GitHub.App/Services/ModelService.cs b/src/GitHub.App/Services/ModelService.cs index 3cd812851b..1a0a23c542 100644 --- a/src/GitHub.App/Services/ModelService.cs +++ b/src/GitHub.App/Services/ModelService.cs @@ -104,7 +104,7 @@ public IObservable> GetAccounts() .ToReadOnlyList(Create); } - public IObservable GetForks(IRepositoryModel repository) + public IObservable GetForks(RepositoryModel repository) { return ApiClient.GetForks(repository.Owner, repository.Name) .Select(x => new RemoteRepositoryModel(x)); @@ -156,7 +156,7 @@ IObservable> GetUserOrganizations() }); } - public IObservable> GetRepositories() + public IObservable> GetRepositories() { return GetUserRepositories(RepositoryType.Owner) .TakeLast(1) @@ -175,7 +175,7 @@ IObservable GetUserFromCache() /// /// /// - public ITrackingCollection GetPullRequests(IRepositoryModel repo, + public ITrackingCollection GetPullRequests(RepositoryModel repo, ITrackingCollection collection) { // Since the api to list pull requests returns all the data for each pr, cache each pr in its own entry @@ -215,7 +215,7 @@ public IObservable GetPullRequest(string owner, string name, throw new NotImplementedException(); } - public IObservable GetRepository(string owner, string repo) + public IObservable GetRepository(string owner, string repo) { var keyobs = GetUserFromCache() .Select(user => string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}/{3}", CacheIndex.RepoPrefix, user.Login, owner, repo)); @@ -228,7 +228,7 @@ public IObservable GetRepository(string owner, string re .Select(Create))); } - public ITrackingCollection GetRepositories(ITrackingCollection collection) + public ITrackingCollection GetRepositories(ITrackingCollection collection) { var keyobs = GetUserFromCache() .Select(user => string.Format(CultureInfo.InvariantCulture, "{0}|{1}", CacheIndex.RepoPrefix, user.Login)); @@ -256,7 +256,7 @@ public ITrackingCollection GetRepositories(ITrackingColl return collection; } - public IObservable CreatePullRequest(LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + public IObservable CreatePullRequest(LocalRepositoryModel sourceRepository, RepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body) { @@ -286,7 +286,7 @@ public IObservable InvalidateAll() return hostCache.InvalidateAll().ContinueAfter(() => hostCache.Vacuum()); } - public IObservable GetFileContents(IRepositoryModel repo, string commitSha, string path, string fileSha) + public IObservable GetFileContents(RepositoryModel repo, string commitSha, string path, string fileSha) { return Observable.Defer(() => Task.Run(async () => { @@ -305,7 +305,7 @@ public IObservable GetFileContents(IRepositoryModel repo, string commitS })); } - IObservable> GetUserRepositories(RepositoryType repositoryType) + IObservable> GetUserRepositories(RepositoryType repositoryType) { return Observable.Defer(() => GetUserFromCache().SelectMany(user => hostCache.GetAndRefreshObject(string.Format(CultureInfo.InvariantCulture, "{0}|{1}:repos", user.Login, repositoryType), @@ -313,14 +313,14 @@ IObservable> GetUserRepositories(Repositor TimeSpan.FromMinutes(2), TimeSpan.FromDays(7))) .ToReadOnlyList(Create)) - .Catch, KeyNotFoundException>( + .Catch, KeyNotFoundException>( // This could in theory happen if we try to call this before the user is logged in. e => { log.Error(e, "Retrieving {RepositoryType} user repositories failed because user is not stored in the cache", repositoryType); - return Observable.Return(Array.Empty()); + return Observable.Return(Array.Empty()); }); } @@ -333,14 +333,14 @@ IObservable> GetUserRepositoriesFromApi(Reposit .Catch, Exception>(_ => Observable.Return(Enumerable.Empty())); } - IObservable> GetAllRepositoriesForAllOrganizations() + IObservable> GetAllRepositoriesForAllOrganizations() { return GetUserOrganizations() .SelectMany(org => org.ToObservable()) .SelectMany(org => GetOrganizationRepositories(org.Login).TakeLast(1)); } - IObservable> GetOrganizationRepositories(string organization) + IObservable> GetOrganizationRepositories(string organization) { return Observable.Defer(() => GetUserFromCache().SelectMany(user => hostCache.GetAndRefreshObject(string.Format(CultureInfo.InvariantCulture, "{0}|{1}|repos", user.Login, organization), @@ -349,17 +349,17 @@ IObservable> GetOrganizationRepositories(s TimeSpan.FromMinutes(2), TimeSpan.FromDays(7))) .ToReadOnlyList(Create)) - .Catch, KeyNotFoundException>( + .Catch, KeyNotFoundException>( // This could in theory happen if we try to call this before the user is logged in. e => { log.Error(e, "Retrieveing {Organization} org repositories failed because user is not stored in the cache", organization); - return Observable.Return(Array.Empty()); + return Observable.Return(Array.Empty()); }); } - public IObservable GetBranches(IRepositoryModel repo) + public IObservable GetBranches(RepositoryModel repo) { var keyobs = GetUserFromCache() .Select(user => string.Format(CultureInfo.InvariantCulture, "{0}|{1}|branch", user.Login, repo.Name)); @@ -403,7 +403,7 @@ IAccount Create(string login, string avatarUrl) avatarProvider.GetAvatar(avatarUrl)); } - IRemoteRepositoryModel Create(RepositoryCacheItem item) + RemoteRepositoryModel Create(RepositoryCacheItem item) { return new RemoteRepositoryModel( item.Id, diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index bb277e43b9..9e141857fa 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -317,7 +317,7 @@ public async Task> ReadAssignableUsers( } public IObservable CreatePullRequest(IModelService modelService, - LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + LocalRepositoryModel sourceRepository, RepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body ) @@ -925,7 +925,7 @@ async Task MarkBranchAsPullRequest(IRepository repo, string branchName, string o } async Task PushAndCreatePR(IModelService modelService, - LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + LocalRepositoryModel sourceRepository, RepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body) { diff --git a/src/GitHub.App/Services/RepositoryForkService.cs b/src/GitHub.App/Services/RepositoryForkService.cs index f272ca4155..b6f1a00ab5 100644 --- a/src/GitHub.App/Services/RepositoryForkService.cs +++ b/src/GitHub.App/Services/RepositoryForkService.cs @@ -37,7 +37,7 @@ public RepositoryForkService(IGitClient gitClient, IVSGitServices vsGitServices, this.usageTracker = usageTracker; } - public IObservable ForkRepository(IApiClient apiClient, IRepositoryModel sourceRepository, NewRepositoryFork repositoryFork, bool updateOrigin, bool addUpstream, bool trackMasterUpstream) + public IObservable ForkRepository(IApiClient apiClient, RepositoryModel sourceRepository, NewRepositoryFork repositoryFork, bool updateOrigin, bool addUpstream, bool trackMasterUpstream) { log.Verbose("ForkRepository Source:{SourceOwner}/{SourceName} To:{DestinationOwner}", sourceRepository.Owner, sourceRepository.Name, repositoryFork.Organization ?? "[Current User]"); log.Verbose("ForkRepository updateOrigin:{UpdateOrigin} addUpstream:{AddUpstream} trackMasterUpstream:{TrackMasterUpstream}", updateOrigin, addUpstream, trackMasterUpstream); @@ -64,7 +64,7 @@ public IObservable ForkRepository(IApiClient apiClient, IRepositoryM }); } - public IObservable SwitchRemotes(IRepositoryModel destinationRepository, bool updateOrigin, bool addUpstream, bool trackMasterUpstream) + public IObservable SwitchRemotes(RepositoryModel destinationRepository, bool updateOrigin, bool addUpstream, bool trackMasterUpstream) { return Observable.Defer(() => Observable.Return(new object()) .ObserveOn(RxApp.MainThreadScheduler) diff --git a/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs b/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs index bfc2d3e78f..12c51171e8 100644 --- a/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs @@ -29,7 +29,7 @@ public class RepositoryCloneViewModel : ViewModelBase, IRepositoryCloneViewModel readonly IUsageTracker usageTracker; readonly IReadOnlyList tabs; string path; - IRepositoryModel previousRepository; + RepositoryModel previousRepository; ObservableAsPropertyHelper pathWarning; int selectedTabIndex; @@ -183,7 +183,7 @@ void BrowseForDirectory() } } - void UpdatePath(IRepositoryModel repository) + void UpdatePath(RepositoryModel repository) { if (repository != null) { @@ -239,7 +239,7 @@ string FindDirWithout(string dir, string match, int levels) } } - string ValidatePathWarning(IRepositoryModel repositoryModel, string path) + string ValidatePathWarning(RepositoryModel repositoryModel, string path) { if (repositoryModel != null) { diff --git a/src/GitHub.App/ViewModels/Dialog/Clone/RepositorySelectViewModel.cs b/src/GitHub.App/ViewModels/Dialog/Clone/RepositorySelectViewModel.cs index e48a0b9822..539b5d7f0a 100644 --- a/src/GitHub.App/ViewModels/Dialog/Clone/RepositorySelectViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/Clone/RepositorySelectViewModel.cs @@ -30,7 +30,7 @@ public class RepositorySelectViewModel : ViewModelBase, IRepositorySelectViewMod bool loadingStarted; IReadOnlyList items; ICollectionView itemsView; - ObservableAsPropertyHelper repository; + ObservableAsPropertyHelper repository; IRepositoryItemViewModel selectedItem; [ImportingConstructor] @@ -88,7 +88,7 @@ public IRepositoryItemViewModel SelectedItem set => this.RaiseAndSetIfChanged(ref selectedItem, value); } - public IRepositoryModel Repository => repository.Value; + public RepositoryModel Repository => repository.Value; public void Initialize(IConnection connection) { @@ -152,7 +152,7 @@ bool FilterItem(object obj) return true; } - IRepositoryModel CreateRepository(IRepositoryItemViewModel item) + RepositoryModel CreateRepository(IRepositoryItemViewModel item) { return item != null ? new RepositoryModel(item.Name, UriString.ToUriString(item.Url)) : diff --git a/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryUrlViewModel.cs b/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryUrlViewModel.cs index cb4f4abb30..0c2d69caee 100644 --- a/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryUrlViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryUrlViewModel.cs @@ -14,7 +14,7 @@ namespace GitHub.App.ViewModels.Dialog.Clone [PartCreationPolicy(CreationPolicy.NonShared)] public class RepositoryUrlViewModel : ViewModelBase, IRepositoryUrlViewModel { - ObservableAsPropertyHelper repository; + ObservableAsPropertyHelper repository; string url; public RepositoryUrlViewModel() @@ -30,11 +30,11 @@ public string Url public bool IsEnabled => true; - public IRepositoryModel Repository => repository.Value; + public RepositoryModel Repository => repository.Value; public Task Activate() => Task.CompletedTask; - IRepositoryModel ParseUrl(string s) + RepositoryModel ParseUrl(string s) { if (s != null) { diff --git a/src/GitHub.App/ViewModels/Dialog/ForkRepositoryExecuteViewModel.cs b/src/GitHub.App/ViewModels/Dialog/ForkRepositoryExecuteViewModel.cs index 15f2cce9b7..9211b06b4c 100644 --- a/src/GitHub.App/ViewModels/Dialog/ForkRepositoryExecuteViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/ForkRepositoryExecuteViewModel.cs @@ -49,11 +49,11 @@ IRepositoryForkService repositoryForkService BackCommand = ReactiveCommand.Create(() => { }); } - public IRepositoryModel SourceRepository { get; private set; } + public RepositoryModel SourceRepository { get; private set; } public IAccount DestinationAccount { get; private set; } - public IRepositoryModel DestinationRepository { get; private set; } + public RepositoryModel DestinationRepository { get; private set; } public ReactiveCommand CreateFork { get; } diff --git a/src/GitHub.App/ViewModels/Dialog/ForkRepositorySelectViewModel.cs b/src/GitHub.App/ViewModels/Dialog/ForkRepositorySelectViewModel.cs index 9cfd7f5db7..fc5a597f47 100644 --- a/src/GitHub.App/ViewModels/Dialog/ForkRepositorySelectViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/ForkRepositorySelectViewModel.cs @@ -23,7 +23,7 @@ public class ForkRepositorySelectViewModel : ViewModelBase, IForkRepositorySelec readonly IModelServiceFactory modelServiceFactory; IReadOnlyList accounts; - IReadOnlyList existingForks; + IReadOnlyList existingForks; bool isLoading; [ImportingConstructor] @@ -31,7 +31,7 @@ public ForkRepositorySelectViewModel(IModelServiceFactory modelServiceFactory) { this.modelServiceFactory = modelServiceFactory; SelectedAccount = ReactiveCommand.Create(_ => { }); - SwitchOrigin = ReactiveCommand.Create(_ => { }); + SwitchOrigin = ReactiveCommand.Create(_ => { }); } public string Title => Resources.ForkRepositoryTitle; @@ -42,7 +42,7 @@ public IReadOnlyList Accounts private set { this.RaiseAndSetIfChanged(ref accounts, value); } } - public IReadOnlyList ExistingForks + public IReadOnlyList ExistingForks { get { return existingForks; } private set { this.RaiseAndSetIfChanged(ref existingForks, value); } @@ -56,7 +56,7 @@ public bool IsLoading public ReactiveCommand SelectedAccount { get; } - public ReactiveCommand SwitchOrigin { get; } + public ReactiveCommand SwitchOrigin { get; } public IObservable Done => SelectedAccount.SelectNull(); @@ -78,7 +78,7 @@ public async Task InitializeAsync(LocalRepositoryModel repository, IConnection c { var forks = x.Forks; - var parents = new List(); + var parents = new List(); var current = x.Respoitory; while (current.Parent != null) { @@ -97,7 +97,7 @@ public async Task InitializeAsync(LocalRepositoryModel repository, IConnection c } } - void BuildAccounts(IReadOnlyList accessibleAccounts, LocalRepositoryModel currentRepository, IList forks, List parents) + void BuildAccounts(IReadOnlyList accessibleAccounts, LocalRepositoryModel currentRepository, IList forks, List parents) { log.Verbose("BuildAccounts: {AccessibleAccounts} accessibleAccounts, {Forks} forks, {Parents} parents", accessibleAccounts.Count, forks.Count, parents.Count); @@ -105,7 +105,7 @@ void BuildAccounts(IReadOnlyList accessibleAccounts, LocalRepositoryMo var readOnlyList = accessibleAccounts .Where(account => account.Login != currentRepository.Owner) - .Select(account => new {Account = account, Fork = existingForksAndParents.ContainsKey(account.Login) ? existingForksAndParents[account.Login] : null }) + .Select(account => new { Account = account, Fork = existingForksAndParents.ContainsKey(account.Login) ? existingForksAndParents[account.Login] : null }) .ToArray(); Accounts = readOnlyList.Where(arg => arg.Fork == null).Select(arg => arg.Account).ToList(); diff --git a/src/GitHub.App/ViewModels/Dialog/ForkRepositorySwitchViewModel.cs b/src/GitHub.App/ViewModels/Dialog/ForkRepositorySwitchViewModel.cs index f6e8ca7ce4..74777a7a05 100644 --- a/src/GitHub.App/ViewModels/Dialog/ForkRepositorySwitchViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/ForkRepositorySwitchViewModel.cs @@ -31,9 +31,9 @@ public ForkRepositorySwitchViewModel(IRepositoryForkService repositoryForkServic SwitchFork = ReactiveCommand.CreateFromObservable(OnSwitchFork); } - public IRepositoryModel SourceRepository { get; private set; } + public RepositoryModel SourceRepository { get; private set; } - public IRepositoryModel DestinationRepository { get; private set; } + public RepositoryModel DestinationRepository { get; private set; } public ReactiveCommand SwitchFork { get; } @@ -41,7 +41,7 @@ public ForkRepositorySwitchViewModel(IRepositoryForkService repositoryForkServic public IObservable Done => SwitchFork.Where(value => value != null).SelectNull(); - public void Initialize(LocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository) + public void Initialize(LocalRepositoryModel sourceRepository, RemoteRepositoryModel remoteRepository) { SourceRepository = sourceRepository; DestinationRepository = remoteRepository; diff --git a/src/GitHub.App/ViewModels/Dialog/ForkRepositoryViewModel.cs b/src/GitHub.App/ViewModels/Dialog/ForkRepositoryViewModel.cs index f99ba38de9..28f0fed260 100644 --- a/src/GitHub.App/ViewModels/Dialog/ForkRepositoryViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/ForkRepositoryViewModel.cs @@ -64,7 +64,7 @@ async Task ShowExecutePage(IAccount account) Content = executePage; } - void ShowSwitchRepositoryPath(IRemoteRepositoryModel remoteRepository) + void ShowSwitchRepositoryPath(RemoteRepositoryModel remoteRepository) { switchPage.Initialize(Repository, remoteRepository); Content = switchPage; diff --git a/src/GitHub.App/ViewModels/Dialog/RepositoryRecloneViewModel.cs b/src/GitHub.App/ViewModels/Dialog/RepositoryRecloneViewModel.cs index d54fb65bba..f996cd5b70 100644 --- a/src/GitHub.App/ViewModels/Dialog/RepositoryRecloneViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/RepositoryRecloneViewModel.cs @@ -131,11 +131,11 @@ public string BaseRepositoryPath /// public ReactiveCommand CloneCommand { get; private set; } - IRepositoryModel selectedRepository; + RepositoryModel selectedRepository; /// /// Selected repository to clone /// - public IRepositoryModel SelectedRepository + public RepositoryModel SelectedRepository { get { return selectedRepository; } set { this.RaiseAndSetIfChanged(ref selectedRepository, value); } diff --git a/src/GitHub.App/ViewModels/GitHubPane/IssueListViewModelBase.cs b/src/GitHub.App/ViewModels/GitHubPane/IssueListViewModelBase.cs index da21a30acf..e7e1007043 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/IssueListViewModelBase.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/IssueListViewModelBase.cs @@ -31,8 +31,8 @@ public abstract class IssueListViewModelBase : PanePageViewModelBase, IIssueList ICollectionView itemsView; IDisposable subscription; IssueListMessage message; - IRepositoryModel remoteRepository; - IReadOnlyList forks; + RepositoryModel remoteRepository; + IReadOnlyList forks; string searchQuery; string selectedState; ObservableAsPropertyHelper stateCaption; @@ -65,7 +65,7 @@ public IUserFilterViewModel AuthorFilter } /// - public IReadOnlyList Forks + public IReadOnlyList Forks { get { return forks; } set { this.RaiseAndSetIfChanged(ref forks, value); } @@ -96,7 +96,7 @@ public IssueListMessage Message } /// - public IRepositoryModel RemoteRepository + public RepositoryModel RemoteRepository { get { return remoteRepository; } set { this.RaiseAndSetIfChanged(ref remoteRepository, value); } @@ -151,7 +151,7 @@ public async Task InitializeAsync(LocalRepositoryModel repository, IConnection c repository.Name, UriString.ToUriString(repository.CloneUrl.ToRepositoryUrl(parent.Value.owner))); - Forks = new IRepositoryModel[] + Forks = new RepositoryModel[] { RemoteRepository, repository, diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index 22c9a2b936..c6a9bd2f8c 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -42,7 +42,7 @@ public class PullRequestCreationViewModel : PanePageViewModelBase, IPullRequestC readonly IScheduler timerScheduler; readonly CompositeDisposable disposables = new CompositeDisposable(); LocalRepositoryModel activeLocalRepo; - ObservableAsPropertyHelper githubRepository; + ObservableAsPropertyHelper githubRepository; IModelService modelService; [ImportingConstructor] @@ -317,7 +317,7 @@ protected string GetDraftKey() SourceBranch.Name); } - public IRemoteRepositoryModel GitHubRepository { get { return githubRepository?.Value; } } + public RemoteRepositoryModel GitHubRepository { get { return githubRepository?.Value; } } bool IsExecuting { get { return isExecuting.Value; } } bool initialized; diff --git a/src/GitHub.Exports.Reactive/Caches/AccountCacheItem.cs b/src/GitHub.Exports.Reactive/Caches/AccountCacheItem.cs index 36ad661261..6d3a0eec10 100644 --- a/src/GitHub.Exports.Reactive/Caches/AccountCacheItem.cs +++ b/src/GitHub.Exports.Reactive/Caches/AccountCacheItem.cs @@ -2,6 +2,7 @@ using GitHub.Models; using GitHub.Primitives; using Octokit; +using Account = Octokit.Account; namespace GitHub.Caches { diff --git a/src/GitHub.App/Models/Account.cs b/src/GitHub.Exports.Reactive/Models/Account.cs similarity index 100% rename from src/GitHub.App/Models/Account.cs rename to src/GitHub.Exports.Reactive/Models/Account.cs diff --git a/src/GitHub.App/Models/RemoteRepositoryModel.cs b/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs similarity index 90% rename from src/GitHub.App/Models/RemoteRepositoryModel.cs rename to src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs index 61a16aaf5e..780c6f5d8a 100644 --- a/src/GitHub.App/Models/RemoteRepositoryModel.cs +++ b/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs @@ -2,15 +2,21 @@ using System; using System.Globalization; using GitHub.Extensions; +using GitHub.Collections; namespace GitHub.Models { /// /// A repository read from the GitHub API. /// - public class RemoteRepositoryModel : RepositoryModel, IRemoteRepositoryModel, + public class RemoteRepositoryModel : RepositoryModel, ICopyable, IEquatable, IComparable { + protected RemoteRepositoryModel() + { + // Used by designer + } + /// /// Initializes a new instance of the class. /// @@ -21,7 +27,7 @@ public class RemoteRepositoryModel : RepositoryModel, IRemoteRepositoryModel, /// Whether the repository is a fork. /// The repository owner account. /// The parent repository if this repository is a fork. - public RemoteRepositoryModel(long id, string name, UriString cloneUrl, bool isPrivate, bool isFork, IAccount ownerAccount, IRemoteRepositoryModel parent) + public RemoteRepositoryModel(long id, string name, UriString cloneUrl, bool isPrivate, bool isFork, IAccount ownerAccount, RemoteRepositoryModel parent) : base(name, cloneUrl) { Guard.ArgumentNotEmptyString(name, nameof(name)); @@ -57,7 +63,7 @@ public RemoteRepositoryModel(Octokit.Repository repository) } #region Equality Things - public void CopyFrom(IRemoteRepositoryModel other) + public void CopyFrom(RemoteRepositoryModel other) { if (!Equals(other)) throw new ArgumentException("Instance to copy from doesn't match this instance. this:(" + this + ") other:(" + other + ")", nameof(other)); @@ -77,13 +83,6 @@ public override bool Equals(object obj) return Equals(other); } - public bool Equals(IRemoteRepositoryModel other) - { - if (ReferenceEquals(this, other)) - return true; - return other != null && Id == other.Id; - } - public bool Equals(RemoteRepositoryModel other) { if (ReferenceEquals(this, other)) @@ -91,11 +90,6 @@ public bool Equals(RemoteRepositoryModel other) return other != null && Id == other.Id; } - public int CompareTo(IRemoteRepositoryModel other) - { - return other != null ? UpdatedAt.CompareTo(other.UpdatedAt) : 1; - } - public int CompareTo(RemoteRepositoryModel other) { return other != null ? UpdatedAt.CompareTo(other.UpdatedAt) : 1; @@ -154,7 +148,7 @@ public int CompareTo(RemoteRepositoryModel other) /// /// Gets the repository from which this repository was forked, if any. /// - public IRemoteRepositoryModel Parent { get; } + public RemoteRepositoryModel Parent { get; } /// /// Gets the default branch for the repository. diff --git a/src/GitHub.Exports.Reactive/Services/IModelService.cs b/src/GitHub.Exports.Reactive/Services/IModelService.cs index 8cb87e0b15..aacc5164c5 100644 --- a/src/GitHub.Exports.Reactive/Services/IModelService.cs +++ b/src/GitHub.Exports.Reactive/Services/IModelService.cs @@ -20,18 +20,18 @@ public interface IModelService : IDisposable IObservable GetUser(string login); IObservable InsertUser(AccountCacheItem user); IObservable> GetAccounts(); - IObservable GetRepository(string owner, string repo); - ITrackingCollection GetRepositories(ITrackingCollection collection); - IObservable GetForks(IRepositoryModel repository); + IObservable GetRepository(string owner, string repo); + ITrackingCollection GetRepositories(ITrackingCollection collection); + IObservable GetForks(RepositoryModel repository); IObservable GetLicenses(); IObservable GetGitIgnoreTemplates(); IObservable GetPullRequest(string owner, string name, int number); - ITrackingCollection GetPullRequests(IRepositoryModel repo, ITrackingCollection collection); - IObservable CreatePullRequest(LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + ITrackingCollection GetPullRequests(RepositoryModel repo, ITrackingCollection collection); + IObservable CreatePullRequest(LocalRepositoryModel sourceRepository, RepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body); - IObservable GetBranches(IRepositoryModel repo); + IObservable GetBranches(RepositoryModel repo); IObservable InvalidateAll(); - IObservable GetFileContents(IRepositoryModel repo, string commitSha, string path, string fileSha); + IObservable GetFileContents(RepositoryModel repo, string commitSha, string path, string fileSha); } } diff --git a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs index f29c2bcf2b..29e8e1d5f4 100644 --- a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs +++ b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs @@ -42,7 +42,7 @@ Task> ReadAssignableUsers( string after); IObservable CreatePullRequest(IModelService modelService, - LocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, + LocalRepositoryModel sourceRepository, RepositoryModel targetRepository, BranchModel sourceBranch, BranchModel targetBranch, string title, string body); diff --git a/src/GitHub.Exports.Reactive/Services/IRepositoryForkService.cs b/src/GitHub.Exports.Reactive/Services/IRepositoryForkService.cs index 7cb3b79e2e..8f0b12c3b9 100644 --- a/src/GitHub.Exports.Reactive/Services/IRepositoryForkService.cs +++ b/src/GitHub.Exports.Reactive/Services/IRepositoryForkService.cs @@ -9,7 +9,7 @@ namespace GitHub.Services { public interface IRepositoryForkService { - IObservable ForkRepository(IApiClient apiClient, IRepositoryModel sourceRepository, NewRepositoryFork repositoryFork, bool updateOrigin, bool addUpstream, bool trackMasterUpstream); - IObservable SwitchRemotes(IRepositoryModel destinationRepository, bool updateOrigin, bool addUpstream, bool trackMasterUpstream); + IObservable ForkRepository(IApiClient apiClient, RepositoryModel sourceRepository, NewRepositoryFork repositoryFork, bool updateOrigin, bool addUpstream, bool trackMasterUpstream); + IObservable SwitchRemotes(RepositoryModel destinationRepository, bool updateOrigin, bool addUpstream, bool trackMasterUpstream); } } diff --git a/src/GitHub.Exports.Reactive/Services/ModelServiceExtensions.cs b/src/GitHub.Exports.Reactive/Services/ModelServiceExtensions.cs index abe5e35a88..b9413d4ab2 100644 --- a/src/GitHub.Exports.Reactive/Services/ModelServiceExtensions.cs +++ b/src/GitHub.Exports.Reactive/Services/ModelServiceExtensions.cs @@ -5,7 +5,7 @@ namespace GitHub.Services { public static class ModelServiceExtensions { - public static IObservable GetPullRequest(this IModelService service, IRepositoryModel repo, int number) + public static IObservable GetPullRequest(this IModelService service, RepositoryModel repo, int number) { return service.GetPullRequest(repo.Owner, repo.Name, number); } diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/Clone/IRepositoryCloneTabViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/Clone/IRepositoryCloneTabViewModel.cs index 6f6c7d6b43..0eb678d828 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/Clone/IRepositoryCloneTabViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/Clone/IRepositoryCloneTabViewModel.cs @@ -20,7 +20,7 @@ public interface IRepositoryCloneTabViewModel : IViewModel /// /// Gets the selected repository, or null if no repository has been selected. /// - IRepositoryModel Repository { get; } + RepositoryModel Repository { get; } /// /// Activates the tab. diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryExecuteViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryExecuteViewModel.cs index b7fb392aa1..330138c3cc 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryExecuteViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositoryExecuteViewModel.cs @@ -13,9 +13,9 @@ namespace GitHub.ViewModels.Dialog /// public interface IForkRepositoryExecuteViewModel : IDialogContentViewModel { - IRepositoryModel SourceRepository { get; } + RepositoryModel SourceRepository { get; } - IRepositoryModel DestinationRepository { get; } + RepositoryModel DestinationRepository { get; } IAccount DestinationAccount { get; } diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySelectViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySelectViewModel.cs index f5acadbda4..28e4a813cb 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySelectViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySelectViewModel.cs @@ -20,7 +20,7 @@ public interface IForkRepositorySelectViewModel : IDialogContentViewModel /// /// Gets a list of existing forks for accounts that the owner has access to. /// - IReadOnlyList ExistingForks { get; } + IReadOnlyList ExistingForks { get; } /// /// Gets a value indicating whether the view model is loading. @@ -35,7 +35,7 @@ public interface IForkRepositorySelectViewModel : IDialogContentViewModel /// /// Gets a command that is executed when the user selects an item in . /// - ReactiveCommand SwitchOrigin { get; } + ReactiveCommand SwitchOrigin { get; } /// /// Initializes the view model. diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySwitchViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySwitchViewModel.cs index 41e65b8f79..f820955bc0 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySwitchViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IForkRepositorySwitchViewModel.cs @@ -9,9 +9,9 @@ namespace GitHub.ViewModels.Dialog /// public interface IForkRepositorySwitchViewModel : IDialogContentViewModel { - IRepositoryModel SourceRepository { get; } + RepositoryModel SourceRepository { get; } - IRepositoryModel DestinationRepository { get; } + RepositoryModel DestinationRepository { get; } /// /// Gets a command that is executed when the user clicks the "Fork" button. @@ -29,6 +29,6 @@ public interface IForkRepositorySwitchViewModel : IDialogContentViewModel /// /// The repository to fork. /// - void Initialize(LocalRepositoryModel sourceRepository, IRemoteRepositoryModel remoteRepository); + void Initialize(LocalRepositoryModel sourceRepository, RemoteRepositoryModel remoteRepository); } } \ No newline at end of file diff --git a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IRepositoryRecloneViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IRepositoryRecloneViewModel.cs index 9feef83bf2..1929a198e4 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/Dialog/IRepositoryRecloneViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/Dialog/IRepositoryRecloneViewModel.cs @@ -8,6 +8,6 @@ public interface IRepositoryRecloneViewModel : IDialogContentViewModel, IConnect /// /// Gets or sets the repository to clone. /// - IRepositoryModel SelectedRepository { get; set; } + RepositoryModel SelectedRepository { get; set; } } } diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IIssueListViewModelBase.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IIssueListViewModelBase.cs index c7f782fe7e..1330142fc7 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IIssueListViewModelBase.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IIssueListViewModelBase.cs @@ -18,7 +18,7 @@ public enum IssueListMessage /// No message should be displayed; the items should be displayed. /// None, - + /// /// A "No Open Items" message should be displayed. /// @@ -47,7 +47,7 @@ public interface IIssueListViewModelBase : ISearchablePageViewModel /// /// Returns null if the current repository is not a fork. /// - IReadOnlyList Forks { get; } + IReadOnlyList Forks { get; } /// /// Gets the list of issues or pull requests. @@ -77,7 +77,7 @@ public interface IIssueListViewModelBase : ISearchablePageViewModel /// This may differ from if is /// a fork. /// - IRepositoryModel RemoteRepository { get; set; } + RepositoryModel RemoteRepository { get; set; } /// /// Gets the currently selected item in . diff --git a/src/GitHub.Exports/Extensions/ConnectionManagerExtensions.cs b/src/GitHub.Exports/Extensions/ConnectionManagerExtensions.cs index 50ede8930b..1763f728f7 100644 --- a/src/GitHub.Exports/Extensions/ConnectionManagerExtensions.cs +++ b/src/GitHub.Exports/Extensions/ConnectionManagerExtensions.cs @@ -34,7 +34,7 @@ public static async Task GetFirstLoggedInConnection(this IConnectio return connections.FirstOrDefault(x => x.IsLoggedIn); } - public static Task GetConnection(this IConnectionManager cm, IRepositoryModel repository) + public static Task GetConnection(this IConnectionManager cm, RepositoryModel repository) { if (repository?.CloneUrl != null) { diff --git a/src/GitHub.Exports/Models/BranchModel.cs b/src/GitHub.Exports/Models/BranchModel.cs index cb28e905ad..e72280f5c2 100644 --- a/src/GitHub.Exports/Models/BranchModel.cs +++ b/src/GitHub.Exports/Models/BranchModel.cs @@ -7,7 +7,7 @@ namespace GitHub.Models public class BranchModel : ICopyable, IEquatable, IComparable { - public BranchModel(string name, IRepositoryModel repo, string sha, bool isTracking, string trackedSha) : + public BranchModel(string name, RepositoryModel repo, string sha, bool isTracking, string trackedSha) : this(name, repo) { IsTracking = isTracking; @@ -15,7 +15,7 @@ public BranchModel(string name, IRepositoryModel repo, string sha, bool isTracki TrackedSha = trackedSha; } - public BranchModel(string name, IRepositoryModel repo) + public BranchModel(string name, RepositoryModel repo) { Extensions.Guard.ArgumentNotEmptyString(name, nameof(name)); Extensions.Guard.ArgumentNotNull(repo, nameof(repo)); @@ -27,7 +27,7 @@ public BranchModel(string name, IRepositoryModel repo) public string Id { get; private set; } public string Name { get; private set; } - public IRepositoryModel Repository { get; private set; } + public RepositoryModel Repository { get; private set; } public bool IsTracking { get; private set; } public string DisplayName { get; set; } public string Sha { get; private set; } diff --git a/src/GitHub.Exports/Models/IRemoteRepositoryModel.cs b/src/GitHub.Exports/Models/IRemoteRepositoryModel.cs deleted file mode 100644 index e6a91261de..0000000000 --- a/src/GitHub.Exports/Models/IRemoteRepositoryModel.cs +++ /dev/null @@ -1,47 +0,0 @@ -using GitHub.Collections; -using System; - -namespace GitHub.Models -{ - /// - /// Represents a repository read from the GitHub API. - /// - public interface IRemoteRepositoryModel : IRepositoryModel, ICopyable, - IEquatable, IComparable - { - /// - /// Gets the repository's API ID. - /// - long Id { get; } - - /// - /// Gets the account that is the ower of the repository. - /// - IAccount OwnerAccount { get; } - - /// - /// Gets the date and time at which the repository was created. - /// - DateTimeOffset CreatedAt { get; } - - /// - /// Gets the repository's last update date and time. - /// - DateTimeOffset UpdatedAt { get; } - - /// - /// Gets a value indicating whether the repository is a fork. - /// - bool IsFork { get; } - - /// - /// Gets the repository from which this repository was forked, if any. - /// - IRemoteRepositoryModel Parent { get; } - - /// - /// Gets the default branch for the repository. - /// - BranchModel DefaultBranch { get; } - } -} diff --git a/src/GitHub.Exports/Models/IRepositoryModel.cs b/src/GitHub.Exports/Models/IRepositoryModel.cs deleted file mode 100644 index 084bf96fe4..0000000000 --- a/src/GitHub.Exports/Models/IRepositoryModel.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using GitHub.Primitives; -using GitHub.UI; - -namespace GitHub.Models -{ - /// - /// Represents a repository, either local or retreived via the GitHub API. - /// - public interface IRepositoryModel - { - /// - /// Gets the name of the repository. - /// - string Name { get; } - - /// - /// Gets the repository clone URL. - /// - UriString CloneUrl { get; set; } - - /// - /// Gets the name of the owner of the repository, taken from the clone URL. - /// - string Owner { get; } - - /// - /// Gets an icon for the repository that displays its private and fork state. - /// - Octicon Icon { get; } - - /// - /// Sets the based on a private and fork state. - /// - /// Whether the repository is a private repository. - /// Whether the repository is a fork. - void SetIcon(bool isPrivate, bool isFork); - } -} diff --git a/src/GitHub.Exports/Models/RepositoryModel.cs b/src/GitHub.Exports/Models/RepositoryModel.cs index fe3976de98..c30488cdfc 100644 --- a/src/GitHub.Exports/Models/RepositoryModel.cs +++ b/src/GitHub.Exports/Models/RepositoryModel.cs @@ -10,7 +10,7 @@ namespace GitHub.Models /// The base class for local and remote repository models. /// [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class RepositoryModel : NotificationAwareObject, IRepositoryModel + public class RepositoryModel : NotificationAwareObject { UriString cloneUrl; Octicon icon; diff --git a/src/GitHub.Exports/Services/GitService.cs b/src/GitHub.Exports/Services/GitService.cs index 7b992708ed..310863f0c9 100644 --- a/src/GitHub.Exports/Services/GitService.cs +++ b/src/GitHub.Exports/Services/GitService.cs @@ -104,7 +104,7 @@ public UriString GetUri(string path, string remote = "origin") } /// - /// Probes for a git repository and if one is found, returns a instance for the + /// Probes for a git repository and if one is found, returns a instance for the /// repository. /// /// @@ -112,7 +112,7 @@ public UriString GetUri(string path, string remote = "origin") /// walks up the parent directories until it either finds a repository, or reaches the root disk. /// /// The path to start probing - /// An instance of or null + /// An instance of or null public IRepository GetRepository(string path) { var repoPath = repositoryFacade.Discover(path); diff --git a/src/GitHub.Exports/Services/IDialogService.cs b/src/GitHub.Exports/Services/IDialogService.cs index cd367726b5..ea26dd71e1 100644 --- a/src/GitHub.Exports/Services/IDialogService.cs +++ b/src/GitHub.Exports/Services/IDialogService.cs @@ -37,7 +37,7 @@ public interface IDialogService /// The re-clone dialog is shown from the VS2017+ start page when the user wants to check /// out a repository that was previously checked out on another machine. /// - Task ShowReCloneDialog(IRepositoryModel repository); + Task ShowReCloneDialog(RepositoryModel repository); /// /// Shows the Create Gist dialog. diff --git a/src/GitHub.Exports/Services/IGitService.cs b/src/GitHub.Exports/Services/IGitService.cs index d934ae0b01..4ff850c21b 100644 --- a/src/GitHub.Exports/Services/IGitService.cs +++ b/src/GitHub.Exports/Services/IGitService.cs @@ -44,7 +44,7 @@ public interface IGitService UriString GetUri(string path, string remote = "origin"); /// - /// Probes for a git repository and if one is found, returns a instance for the + /// Probes for a git repository and if one is found, returns a instance for the /// repository. /// /// @@ -52,7 +52,7 @@ public interface IGitService /// walks up the parent directories until it either finds a repository, or reaches the root disk. /// /// The path to start probing - /// An instance of or null + /// An instance of or null IRepository GetRepository(string path); /// diff --git a/src/GitHub.StartPage/StartPagePackage.cs b/src/GitHub.StartPage/StartPagePackage.cs index 245746f08a..15069c9779 100644 --- a/src/GitHub.StartPage/StartPagePackage.cs +++ b/src/GitHub.StartPage/StartPagePackage.cs @@ -50,7 +50,7 @@ public async Task AcquireCodeContainerAsync(RemoteCodeContainer o } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "cancellationToken")] - async Task RunAcquisition(IProgress downloadProgress, CancellationToken cancellationToken, IRepositoryModel repository) + async Task RunAcquisition(IProgress downloadProgress, CancellationToken cancellationToken, RepositoryModel repository) { CloneDialogResult request = null; @@ -84,7 +84,7 @@ async Task RunAcquisition(IProgress download async Task ShowCloneDialog( IGitHubServiceProvider gitHubServiceProvider, IProgress progress, - IRepositoryModel repository = null) + RepositoryModel repository = null) { var dialogService = gitHubServiceProvider.GetService(); var cloneService = gitHubServiceProvider.GetService(); diff --git a/src/GitHub.UI/Converters/BranchNameConverter.cs b/src/GitHub.UI/Converters/BranchNameConverter.cs index 3e5e5b0ded..800c959382 100644 --- a/src/GitHub.UI/Converters/BranchNameConverter.cs +++ b/src/GitHub.UI/Converters/BranchNameConverter.cs @@ -16,11 +16,11 @@ public class BranchNameConverter : IMultiValueConverter public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var branch = values.OfType().FirstOrDefault(); - var activeRepo = values.OfType().FirstOrDefault(); + var activeRepo = values.OfType().FirstOrDefault(); if (branch != null && activeRepo != null) { - var repo = (IRemoteRepositoryModel)branch.Repository; + var repo = (RemoteRepositoryModel)branch.Repository; if (repo.Parent == null && activeRepo.Owner != repo.Owner) { diff --git a/src/GitHub.UI/GitHub.UI.csproj b/src/GitHub.UI/GitHub.UI.csproj index 6a622c6772..1b8eb681cc 100644 --- a/src/GitHub.UI/GitHub.UI.csproj +++ b/src/GitHub.UI/GitHub.UI.csproj @@ -29,6 +29,7 @@ + diff --git a/src/GitHub.VisualStudio.UI/Views/Dialog/ForkRepositorySelectView.xaml.cs b/src/GitHub.VisualStudio.UI/Views/Dialog/ForkRepositorySelectView.xaml.cs index 718d2990ab..3bca75bf59 100644 --- a/src/GitHub.VisualStudio.UI/Views/Dialog/ForkRepositorySelectView.xaml.cs +++ b/src/GitHub.VisualStudio.UI/Views/Dialog/ForkRepositorySelectView.xaml.cs @@ -30,7 +30,7 @@ private void accountsListBox_SelectionChanged(object sender, SelectionChangedEve private void existingForksListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { - var repository = e.AddedItems.OfType().FirstOrDefault(); + var repository = e.AddedItems.OfType().FirstOrDefault(); if (repository != null) { ((IForkRepositorySelectViewModel)DataContext).SwitchOrigin.Execute(repository); diff --git a/test/GitHub.Api.UnitTests/Args.cs b/test/GitHub.Api.UnitTests/Args.cs index 85bd43fd9e..171cbb9b0a 100644 --- a/test/GitHub.Api.UnitTests/Args.cs +++ b/test/GitHub.Api.UnitTests/Args.cs @@ -20,16 +20,17 @@ internal static class Args public static IApiClient ApiClient { get { return Arg.Any(); } } public static IServiceProvider ServiceProvider { get { return Arg.Any(); } } public static IAvatarProvider AvatarProvider { get { return Arg.Any(); } } - public static HostAddress HostAddress { get { return Arg.Any(); } } + public static HostAddress HostAddress { get { return Arg.Any(); } } public static Uri Uri { get { return Arg.Any(); } } public static LibGit2Sharp.IRepository LibGit2Repo { get { return Arg.Any(); } } public static LibGit2Sharp.Branch LibGit2Branch { get { return Arg.Any(); } } public static Remote LibgGit2Remote { get { return Arg.Any(); } } public static LocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } - public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } + public static RemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } - public static Func> - TwoFactorChallengCallback - { get { return Arg.Any>> (); } } + public static Func> TwoFactorChallengCallback + { + get { return Arg.Any>>(); } + } } diff --git a/test/GitHub.App.UnitTests/Args.cs b/test/GitHub.App.UnitTests/Args.cs index 85bd43fd9e..35f32fc6e0 100644 --- a/test/GitHub.App.UnitTests/Args.cs +++ b/test/GitHub.App.UnitTests/Args.cs @@ -20,16 +20,16 @@ internal static class Args public static IApiClient ApiClient { get { return Arg.Any(); } } public static IServiceProvider ServiceProvider { get { return Arg.Any(); } } public static IAvatarProvider AvatarProvider { get { return Arg.Any(); } } - public static HostAddress HostAddress { get { return Arg.Any(); } } + public static HostAddress HostAddress { get { return Arg.Any(); } } public static Uri Uri { get { return Arg.Any(); } } public static LibGit2Sharp.IRepository LibGit2Repo { get { return Arg.Any(); } } public static LibGit2Sharp.Branch LibGit2Branch { get { return Arg.Any(); } } public static Remote LibgGit2Remote { get { return Arg.Any(); } } public static LocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } - public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } + public static RemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } public static Func> TwoFactorChallengCallback - { get { return Arg.Any>> (); } } + { get { return Arg.Any>>(); } } } diff --git a/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs index 2fd7b6140c..ee29b9b3ef 100644 --- a/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs @@ -343,7 +343,7 @@ public async Task Open_Is_Enabled_When_Path_DirectoryExists() Assert.That(target.Open.CanExecute(null), Is.True); } - static void SetRepository(IRepositoryCloneTabViewModel vm, IRepositoryModel repository) + static void SetRepository(IRepositoryCloneTabViewModel vm, RepositoryModel repository) { vm.Repository.Returns(repository); vm.PropertyChanged += Raise.Event( @@ -376,7 +376,7 @@ static IConnectionManager CreateConnectionManager(params string[] addresses) static IRepositorySelectViewModel CreateSelectViewModel() { var result = Substitute.For(); - result.Repository.Returns((IRepositoryModel)null); + result.Repository.Returns((RepositoryModel)null); result.WhenForAnyArgs(x => x.Initialize(null)).Do(_ => result.IsEnabled.Returns(true)); return result; } @@ -451,16 +451,16 @@ static IUsageService CreateUsageService(bool isGroupA = false) return usageService; } - static IRepositoryModel CreateRepositoryModel(string repo = "owner/repo") + static RepositoryModel CreateRepositoryModel(string repo = "owner/repo") { var split = repo.Split('/'); var (owner, name) = (split[0], split[1]); return CreateRepositoryModel(owner, name); } - static IRepositoryModel CreateRepositoryModel(string owner, string name) + static RepositoryModel CreateRepositoryModel(string owner, string name) { - var repository = Substitute.For(); + var repository = Substitute.For(); repository.Owner.Returns(owner); repository.Name.Returns(name); repository.CloneUrl.Returns(CreateGitHubUrl(owner, name)); @@ -475,7 +475,7 @@ static UriString CreateGitHubUrl(string owner, string repo) static IRepositoryUrlViewModel CreateRepositoryUrlViewModel() { var repositoryUrlViewModel = Substitute.For(); - repositoryUrlViewModel.Repository.Returns(null as IRepositoryModel); + repositoryUrlViewModel.Repository.Returns(null as RepositoryModel); repositoryUrlViewModel.Url.Returns(string.Empty); return repositoryUrlViewModel; } diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index 2ccd0a3e35..6bc23e1136 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -45,8 +45,8 @@ struct TestData public IServiceProvider ServiceProvider; public LocalRepositoryModel ActiveRepo; public LibGit2Sharp.IRepository L2Repo; - public IRepositoryModel SourceRepo; - public IRepositoryModel TargetRepo; + public RepositoryModel SourceRepo; + public RepositoryModel TargetRepo; public BranchModel SourceBranch; public BranchModel TargetBranch; public IGitClient GitClient; diff --git a/test/GitHub.Exports.UnitTests/Args.cs b/test/GitHub.Exports.UnitTests/Args.cs index f157abeefc..63f0f74765 100644 --- a/test/GitHub.Exports.UnitTests/Args.cs +++ b/test/GitHub.Exports.UnitTests/Args.cs @@ -18,16 +18,16 @@ internal static class Args public static NewRepository NewRepository { get { return Arg.Any(); } } public static IAccount Account { get { return Arg.Any(); } } public static IServiceProvider ServiceProvider { get { return Arg.Any(); } } - public static HostAddress HostAddress { get { return Arg.Any(); } } + public static HostAddress HostAddress { get { return Arg.Any(); } } public static Uri Uri { get { return Arg.Any(); } } public static LibGit2Sharp.IRepository LibGit2Repo { get { return Arg.Any(); } } public static LibGit2Sharp.Branch LibGit2Branch { get { return Arg.Any(); } } public static Remote LibgGit2Remote { get { return Arg.Any(); } } public static LocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } - public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } + public static RemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } public static Func> TwoFactorChallengCallback - { get { return Arg.Any>> (); } } + { get { return Arg.Any>>(); } } } diff --git a/test/GitHub.Exports.UnitTests/GitHub.Exports.UnitTests.csproj b/test/GitHub.Exports.UnitTests/GitHub.Exports.UnitTests.csproj index 4ae1485c51..c48202bd5e 100644 --- a/test/GitHub.Exports.UnitTests/GitHub.Exports.UnitTests.csproj +++ b/test/GitHub.Exports.UnitTests/GitHub.Exports.UnitTests.csproj @@ -9,6 +9,7 @@ + diff --git a/test/GitHub.VisualStudio.UnitTests/Args.cs b/test/GitHub.VisualStudio.UnitTests/Args.cs index 85bd43fd9e..35f32fc6e0 100644 --- a/test/GitHub.VisualStudio.UnitTests/Args.cs +++ b/test/GitHub.VisualStudio.UnitTests/Args.cs @@ -20,16 +20,16 @@ internal static class Args public static IApiClient ApiClient { get { return Arg.Any(); } } public static IServiceProvider ServiceProvider { get { return Arg.Any(); } } public static IAvatarProvider AvatarProvider { get { return Arg.Any(); } } - public static HostAddress HostAddress { get { return Arg.Any(); } } + public static HostAddress HostAddress { get { return Arg.Any(); } } public static Uri Uri { get { return Arg.Any(); } } public static LibGit2Sharp.IRepository LibGit2Repo { get { return Arg.Any(); } } public static LibGit2Sharp.Branch LibGit2Branch { get { return Arg.Any(); } } public static Remote LibgGit2Remote { get { return Arg.Any(); } } public static LocalRepositoryModel LocalRepositoryModel { get { return Arg.Any(); } } - public static IRemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } + public static RemoteRepositoryModel RemoteRepositoryModel { get { return Arg.Any(); } } public static BranchModel Branch { get { return Arg.Any(); } } public static IGitService GitService { get { return Arg.Any(); } } public static Func> TwoFactorChallengCallback - { get { return Arg.Any>> (); } } + { get { return Arg.Any>>(); } } } From ec711106dff37788cdfcf4b682e46b4b3b640487 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Mon, 5 Nov 2018 15:31:12 +0000 Subject: [PATCH 35/39] Fix tests that use repository models Convert them from using NSubstitute to creating the model object. --- .../PullRequestCreationViewModel.cs | 2 + .../Services/PullRequestServiceTests.cs | 77 +++++++++++-------- .../Services/TeamExplorerContextTests.cs | 7 +- .../Clone/RepositoryCloneViewModelTests.cs | 7 +- .../GitHubPane/GitHubPaneViewModelTests.cs | 6 +- .../GitHubPane/IssueListViewModelBaseTests.cs | 10 +-- .../PullRequestDetailViewModelTests.cs | 11 ++- .../PullRequestFilesViewModelTests.cs | 3 +- ...ullRequestReviewAuthoringViewModelTests.cs | 9 ++- .../PullRequestUserReviewsViewModelTests.cs | 17 ++-- ...equestReviewCommentThreadViewModelTests.cs | 9 ++- .../PullRequestSessionManagerTests.cs | 12 +-- .../Services/PullRequestSessionTests.cs | 17 ++-- .../InlineCommentPeekViewModelTests.cs | 2 +- .../VSGitExtTests.cs | 6 +- .../Commands/OpenFromClipboardCommandTests.cs | 14 ++-- .../Services/LocalRepositoriesTests.cs | 17 ++-- 17 files changed, 124 insertions(+), 102 deletions(-) diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index c6a9bd2f8c..8750d9db5a 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -83,7 +83,9 @@ public PullRequestCreationViewModel( .Subscribe(x => { if (!x.Any(t => t.Equals(TargetBranch))) + { TargetBranch = GitHubRepository.IsFork ? GitHubRepository.Parent.DefaultBranch : GitHubRepository.DefaultBranch; + } }); SetupValidators(); diff --git a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs index 0b3dd677cd..6fedcf1526 100644 --- a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs +++ b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs @@ -584,8 +584,11 @@ static PullRequestService CreatePullRequestService(Repository repo) static LocalRepositoryModel CreateLocalRepositoryModel(Repository repo) { var repoDir = repo.Info.WorkingDirectory; - var repositoryModel = Substitute.For(); - repositoryModel.LocalPath.Returns(repoDir); + var repositoryModel = new LocalRepositoryModel + { + LocalPath = repoDir + }; + return repositoryModel; } @@ -598,7 +601,8 @@ public async Task ExtractsExistingFile_Async() { var gitClient = MockGitClient(); var target = CreateTarget(gitClient); - var repository = Substitute.For(); + var repository = new LocalRepositoryModel { }; + var fileContent = "file content"; var pr = CreatePullRequest(); @@ -620,7 +624,7 @@ public async Task CreatesEmptyFileForNonExistentFileAsync() { var gitClient = MockGitClient(); var target = CreateTarget(gitClient); - var repository = Substitute.For(); + var repository = new LocalRepositoryModel { }; var pr = CreatePullRequest(); gitClient.ExtractFile(Arg.Any(), "123", "filename").Returns(GetFileTaskAsync(null)); @@ -647,7 +651,7 @@ public async Task CanChangeEncodingAsync(string encodingName) var fileContent = "file content"; var gitClient = MockGitClient(); var target = CreateTarget(gitClient); - var repository = Substitute.For(); + var repository = new LocalRepositoryModel { }; var pr = CreatePullRequest(); var expectedPath = Path.Combine(repoDir, fileName); @@ -730,7 +734,7 @@ public async Task ShouldCheckoutExistingBranchAsync() var gitClient = MockGitClient(); var service = CreateTarget(gitClient, MockGitService()); - var localRepo = Substitute.For(); + var localRepo = new LocalRepositoryModel { }; var pr = new PullRequestDetailModel { @@ -753,9 +757,10 @@ public async Task ShouldCheckoutLocalBranchAsync() { var gitClient = MockGitClient(); var service = CreateTarget(gitClient, MockGitService()); - - var localRepo = Substitute.For(); - localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo")); + var localRepo = new LocalRepositoryModel + { + CloneUrl = new UriString("https://foo.bar/owner/repo") + }; var pr = new PullRequestDetailModel { @@ -782,9 +787,10 @@ public async Task ShouldCheckoutLocalBranchOwnerCaseMismatchAsync() { var gitClient = MockGitClient(); var service = CreateTarget(gitClient, MockGitService()); - - var localRepo = Substitute.For(); - localRepo.CloneUrl.Returns(new UriString("https://foo.bar/Owner/repo")); + var localRepo = new LocalRepositoryModel + { + CloneUrl = new UriString("https://foo.bar/Owner/repo") + }; var pr = new PullRequestDetailModel { @@ -811,9 +817,10 @@ public async Task ShouldCheckoutBranchFromForkAsync() { var gitClient = MockGitClient(); var service = CreateTarget(gitClient, MockGitService()); - - var localRepo = Substitute.For(); - localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo")); + var localRepo = new LocalRepositoryModel + { + CloneUrl = new UriString("https://foo.bar/owner/repo") + }; var pr = new PullRequestDetailModel { @@ -844,9 +851,10 @@ public async Task ShouldUseUniquelyNamedRemoteForForkAsync() var gitClient = MockGitClient(); var gitService = MockGitService(); var service = CreateTarget(gitClient, gitService); - - var localRepo = Substitute.For(); - localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo")); + var localRepo = new LocalRepositoryModel + { + CloneUrl = new UriString("https://foo.bar/owner/repo") + }; using (var repo = gitService.GetRepository(localRepo.CloneUrl)) { @@ -881,7 +889,7 @@ public async Task ShouldReturnCorrectDefaultLocalBranchNameAsync() { var service = CreateTarget(MockGitClient(), MockGitService()); - var localRepo = Substitute.For(); + var localRepo = new LocalRepositoryModel { }; var result = await service.GetDefaultLocalBranchName(localRepo, 123, "Pull requests can be \"named\" all sorts of thing's (sic)"); Assert.That("pr/123-pull-requests-can-be-named-all-sorts-of-thing-s-sic", Is.EqualTo(result)); } @@ -897,7 +905,7 @@ public async Task ShouldReturnCorrectDefaultLocalBranchNameForPullRequestsWithNo Substitute.For(), Substitute.For()); - var localRepo = Substitute.For(); + var localRepo = new LocalRepositoryModel { }; var result = await service.GetDefaultLocalBranchName(localRepo, 123, "コードをレビューする準備ができたこと"); Assert.That("pr/123", Is.EqualTo(result)); } @@ -907,7 +915,7 @@ public async Task DefaultLocalBranchNameShouldNotClashWithExistingBranchNamesAsy { var service = CreateTarget(MockGitClient(), MockGitService()); - var localRepo = Substitute.For(); + var localRepo = new LocalRepositoryModel { }; var result = await service.GetDefaultLocalBranchName(localRepo, 123, "foo1"); Assert.That("pr/123-foo1-3", Is.EqualTo(result)); } @@ -919,9 +927,10 @@ public class TheGetLocalBranchesMethod public async Task ShouldReturnPullRequestBranchForPullRequestFromSameRepositoryAsync() { var service = CreateTarget(MockGitClient(), MockGitService()); - - var localRepo = Substitute.For(); - localRepo.CloneUrl.Returns(new UriString("https://github.com/foo/bar")); + var localRepo = new LocalRepositoryModel + { + CloneUrl = new UriString("https://github.com/foo/bar") + }; var result = await service.GetLocalBranches(localRepo, CreatePullRequest(fromFork: false)); @@ -932,9 +941,10 @@ public async Task ShouldReturnPullRequestBranchForPullRequestFromSameRepositoryA public async Task ShouldReturnPullRequestBranchForPullRequestFromSameRepositoryOwnerCaseMismatchAsync() { var service = CreateTarget(MockGitClient(), MockGitService()); - - var localRepo = Substitute.For(); - localRepo.CloneUrl.Returns(new UriString("https://github.com/Foo/bar")); + var localRepo = new LocalRepositoryModel + { + CloneUrl = new UriString("https://github.com/Foo/bar") + }; var result = await service.GetLocalBranches(localRepo, CreatePullRequest(fromFork: false)); @@ -964,8 +974,10 @@ public async Task ShouldReturnMarkedBranchForPullRequestFromForkAsync() var service = CreateTarget(MockGitClient(), MockGitService(repo)); - var localRepo = Substitute.For(); - localRepo.CloneUrl.Returns(new UriString("https://github.com/foo/bar.git")); + var localRepo = new LocalRepositoryModel + { + CloneUrl = new UriString("https://github.com/foo/bar.git") + }; var result = await service.GetLocalBranches(localRepo, CreatePullRequest(true)); @@ -1003,9 +1015,10 @@ public async Task ShouldRemoveUnusedRemoteAsync() var gitClient = MockGitClient(); var gitService = MockGitService(); var service = CreateTarget(gitClient, gitService); - - var localRepo = Substitute.For(); - localRepo.CloneUrl.Returns(new UriString("https://github.com/foo/bar")); + var localRepo = new LocalRepositoryModel + { + CloneUrl = new UriString("https://github.com/foo/bar") + }; using (var repo = gitService.GetRepository(localRepo.CloneUrl)) { diff --git a/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs b/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs index 9ffe378d85..3ccf012883 100644 --- a/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs +++ b/test/GitHub.App.UnitTests/Services/TeamExplorerContextTests.cs @@ -204,9 +204,10 @@ static TeamExplorerContext CreateTeamExplorerContext( static LocalRepositoryModel CreateRepositoryModel(string path) { - var repo = Substitute.For(); - repo.LocalPath.Returns(path); - return repo; + return new LocalRepositoryModel + { + LocalPath = path + }; } static IVSGitExt CreateGitExt() diff --git a/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs index ee29b9b3ef..a4a51b702b 100644 --- a/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs @@ -460,11 +460,8 @@ static RepositoryModel CreateRepositoryModel(string repo = "owner/repo") static RepositoryModel CreateRepositoryModel(string owner, string name) { - var repository = Substitute.For(); - repository.Owner.Returns(owner); - repository.Name.Returns(name); - repository.CloneUrl.Returns(CreateGitHubUrl(owner, name)); - return repository; + var cloneUrl = CreateGitHubUrl(owner, name); + return new RepositoryModel(name, cloneUrl); } static UriString CreateGitHubUrl(string owner, string repo) diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/GitHubPaneViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/GitHubPaneViewModelTests.cs index 621891ccb7..7c8b86edeb 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/GitHubPaneViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/GitHubPaneViewModelTests.cs @@ -282,8 +282,10 @@ static INavigationViewModel CreateNavigator() static ITeamExplorerContext CreateTeamExplorerContext(string repositoryCloneUrl) { - var repository = Substitute.For(); - repository.CloneUrl.Returns(new UriString(repositoryCloneUrl)); + var repository = new LocalRepositoryModel + { + CloneUrl = new UriString(repositoryCloneUrl) + }; var result = Substitute.For(); result.ActiveRepository.Returns(repository); return result; diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/IssueListViewModelBaseTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/IssueListViewModelBaseTests.cs index 20af1a9060..2b274342c4 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/IssueListViewModelBaseTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/IssueListViewModelBaseTests.cs @@ -96,11 +96,11 @@ protected static LocalRepositoryModel CreateLocalRepository( string owner = "owner", string name = "name") { - var result = Substitute.For(); - result.CloneUrl.Returns(new UriString($"https://giuthub.com/{owner}/{name}")); - result.Owner.Returns(owner); - result.Name.Returns(name); - return result; + return new LocalRepositoryModel + { + CloneUrl = new UriString($"https://giuthub.com/{owner}/{name}"), + Name = name + }; } protected static IPullRequestSessionManager CreateSessionManager(PullRequestDetailModel pullRequest = null) diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs index f6e2cd985f..d56dd7e272 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestDetailViewModelTests.cs @@ -550,13 +550,16 @@ static Tuple CreateTargetAndSer int behindBy = 0, IPullRequestSessionManager sessionManager = null) { - var repository = Substitute.For(); + var repository = new LocalRepositoryModel + { + CloneUrl = new UriString(Uri.ToString()), + LocalPath = @"C:\projects\ThisRepo", + Name = "repo" + }; + var currentBranchModel = new BranchModel(currentBranch, repository); var gitService = Substitute.For(); gitService.GetBranch(repository).Returns(currentBranchModel); - repository.CloneUrl.Returns(new UriString(Uri.ToString())); - repository.LocalPath.Returns(@"C:\projects\ThisRepo"); - repository.Name.Returns("repo"); var pullRequestService = Substitute.For(); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestFilesViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestFilesViewModelTests.cs index cf84feea92..d043e97dda 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestFilesViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestFilesViewModelTests.cs @@ -100,8 +100,7 @@ static IPullRequestSession CreateSession() { var author = Substitute.For(); - var repository = Substitute.For(); - repository.LocalPath.Returns(@"C:\Foo"); + var repository = new LocalRepositoryModel { LocalPath = @"C:\Foo" }; var result = Substitute.For(); result.LocalRepository.Returns(repository); diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModelTests.cs index 0ac818eea2..42c876cb35 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestReviewAuthoringViewModelTests.cs @@ -607,10 +607,11 @@ static IPullRequestSessionManager CreateSessionManager( static LocalRepositoryModel CreateLocalRepositoryModel() { - var result = Substitute.For(); - result.CloneUrl.Returns(new UriString("https://github.com/owner/repo")); - result.Owner.Returns("owner"); - result.Name.Returns("repo"); + var result = new LocalRepositoryModel + { + CloneUrl = new UriString("https://github.com/owner/repo"), + Name = "repo" + }; return result; } diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestUserReviewsViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestUserReviewsViewModelTests.cs index 94cd7a8cd6..6946d0e22e 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestUserReviewsViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestUserReviewsViewModelTests.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using GitHub.Factories; using GitHub.Models; +using GitHub.Primitives; using GitHub.Services; using GitHub.ViewModels.GitHubPane; using NSubstitute; @@ -207,19 +208,13 @@ PullRequestUserReviewsViewModel CreateTarget( sessionManager); } - IModelServiceFactory CreateFactory(IModelService modelService) - { - var result = Substitute.For(); - result.CreateAsync(null).ReturnsForAnyArgs(modelService); - return result; - } - LocalRepositoryModel CreateRepository(string owner = "owner", string name = "repo") { - var result = Substitute.For(); - result.Owner.Returns(owner); - result.Name.Returns(name); - return result; + return new LocalRepositoryModel + { + CloneUrl = new UriString($"https://github.com/{owner}/{name}"), + Name = name + }; } } } diff --git a/test/GitHub.App.UnitTests/ViewModels/PullRequestReviewCommentThreadViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/PullRequestReviewCommentThreadViewModelTests.cs index 9ae63fd2ac..bb0cbd3ddb 100644 --- a/test/GitHub.App.UnitTests/ViewModels/PullRequestReviewCommentThreadViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/PullRequestReviewCommentThreadViewModelTests.cs @@ -184,9 +184,12 @@ static IPullRequestSession CreateSession() var result = Substitute.For(); result.User.Returns(new ActorModel { Login = "Viewer" }); result.RepositoryOwner.Returns("owner"); - result.LocalRepository.CloneUrl.Returns(new UriString("https://github.com/owner/repo")); - result.LocalRepository.Name.Returns("repo"); - result.LocalRepository.Owner.Returns("shouldnt-be-used"); + var localRepository = new LocalRepositoryModel + { + CloneUrl = new UriString("https://github.com/owner/repo"), + Name = "repo" + }; + result.LocalRepository.Returns(localRepository); result.PullRequest.Returns(new PullRequestDetailModel { Number = 47, diff --git a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs index e36b633e0c..9d19927856 100644 --- a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs +++ b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionManagerTests.cs @@ -914,12 +914,12 @@ IPullRequestSessionService CreateSessionService( LocalRepositoryModel CreateRepositoryModel(string cloneUrl = OwnerCloneUrl) { - var result = Substitute.For(); - var uriString = new UriString(cloneUrl); - result.CloneUrl.Returns(uriString); - result.Name.Returns(uriString.RepositoryName); - result.Owner.Returns(uriString.Owner); - return result; + var cloneUrlString = new UriString(cloneUrl); + return new LocalRepositoryModel + { + CloneUrl = cloneUrlString, + Name = cloneUrlString.RepositoryName + }; } static ITeamExplorerContext CreateTeamExplorerContext(LocalRepositoryModel repo) diff --git a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionTests.cs b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionTests.cs index 124cbb5637..1f6d0b51fe 100644 --- a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionTests.cs +++ b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionTests.cs @@ -749,9 +749,10 @@ static PullRequestDetailModel CreatePullRequest(params PullRequestReviewThreadMo static LocalRepositoryModel CreateLocalRepository() { - var result = Substitute.For(); - result.CloneUrl.Returns(new UriString("https://github.com/owner/repo")); - return result; + return new LocalRepositoryModel + { + CloneUrl = new UriString("https://github.com/owner/repo") + }; } static IPullRequestSessionService CreateMockSessionService() @@ -782,11 +783,11 @@ static PullRequestSession CreateTarget( string remoteRepositoryOwner, bool hasPendingReview) { - var repository = Substitute.For(); - - repository.CloneUrl.Returns(new UriString($"https://github.com/{localRepositoryOwner}/reop")); - repository.Owner.Returns(localRepositoryOwner); - repository.Name.Returns("repo"); + var repository = new LocalRepositoryModel + { + CloneUrl = $"https://github.com/{localRepositoryOwner}/repo", + Name = "repo" + }; var pr = CreatePullRequest(); var user = CreateActor(); diff --git a/test/GitHub.InlineReviews.UnitTests/ViewModels/InlineCommentPeekViewModelTests.cs b/test/GitHub.InlineReviews.UnitTests/ViewModels/InlineCommentPeekViewModelTests.cs index f1e5d96122..1b4945b842 100644 --- a/test/GitHub.InlineReviews.UnitTests/ViewModels/InlineCommentPeekViewModelTests.cs +++ b/test/GitHub.InlineReviews.UnitTests/ViewModels/InlineCommentPeekViewModelTests.cs @@ -314,7 +314,7 @@ static IPullRequestSession CreateSession() var result = Substitute.For(); result.PullRequest.Returns(new PullRequestDetailModel()); result.User.Returns(new ActorModel { Login = "CurrentUser" }); - result.LocalRepository.CloneUrl.Returns(new UriString("https://foo.bar")); + result.LocalRepository.Returns(new LocalRepositoryModel { CloneUrl = new UriString("https://foo.bar") }); return result; } diff --git a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs index 98a03e6427..ddf11c119d 100644 --- a/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs +++ b/test/GitHub.TeamFoundation.UnitTests/VSGitExtTests.cs @@ -297,8 +297,10 @@ class MockGitService : IGitService { public LocalRepositoryModel CreateLocalRepositoryModel(string localPath) { - var result = Substitute.For(); - result.LocalPath.Returns(localPath); + var result = new LocalRepositoryModel + { + LocalPath = localPath + }; if (localPath == "repo1") { diff --git a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs index cb17f16419..a29b9a8afe 100644 --- a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs @@ -190,13 +190,15 @@ static OpenFromClipboardCommand CreateOpenFromClipboardCommand( vsServices = vsServices ?? Substitute.For(); gitHubContextService.FindContextFromClipboard().Returns(contextFromClipboard); - var activeRepository = teamExplorerContext.ActiveRepository; - activeRepository.LocalPath.Returns(repositoryDir); - activeRepository.Name.Returns(repositoryName); - activeRepository.Owner.Returns(repositoryOwner); + var activeRepository = new LocalRepositoryModel + { + LocalPath = repositoryDir, + Name = repositoryName, + CloneUrl = new UriString($"https://github.com/{repositoryOwner}/{repositoryName}") + }; + teamExplorerContext.ActiveRepository.Returns(activeRepository); var gitService = Substitute.For(); - var currentBranch = Substitute.For(); - currentBranch.Name.Returns(currentBranchName); + var currentBranch = currentBranchName != null ? new BranchModel(currentBranchName, activeRepository) : null; gitService.GetBranch(activeRepository).Returns(currentBranch); if (resolveBlobResult != null) { diff --git a/test/GitHub.VisualStudio.UnitTests/Services/LocalRepositoriesTests.cs b/test/GitHub.VisualStudio.UnitTests/Services/LocalRepositoriesTests.cs index cff16e8bf6..784d7b1041 100644 --- a/test/GitHub.VisualStudio.UnitTests/Services/LocalRepositoriesTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Services/LocalRepositoriesTests.cs @@ -32,7 +32,7 @@ public async Task RefreshShouldLoadRepositories() Assert.That( new[] { "repo1", "repo2" }, - Is.EqualTo(target.Repositories.Select(x => x.Name).ToList())); + Is.EqualTo(target.Repositories.Select(x => x.Name).ToList())); } [Test] @@ -53,7 +53,7 @@ public async Task RefreshShouldAddNewRepository() Assert.That( new[] { "repo1", "repo2", "new" }, - Is.EqualTo(target.Repositories.Select(x => x.Name).ToList())); + Is.EqualTo(target.Repositories.Select(x => x.Name).ToList())); } [Test] @@ -73,7 +73,7 @@ public async Task RefreshShouldRemoveRepository() Assert.That( new[] { "repo2" }, - Is.EqualTo(target.Repositories.Select(x => x.Name).ToList())); + Is.EqualTo(target.Repositories.Select(x => x.Name).ToList())); } [Test] @@ -105,7 +105,7 @@ public async Task GetRepositoriesForAddressShouldSortRepositories() Assert.That( new[] { "a", "b", "c" }, - Is.EqualTo(result.Select(x => x.Name).ToList())); + Is.EqualTo(result.Select(x => x.Name).ToList())); } static IVSGitServices CreateVSGitServices(params string[] names) @@ -128,9 +128,10 @@ static LocalRepositoryModel CreateRepository(string name) static LocalRepositoryModel CreateRepository(Tuple nameAndAddress) { - var result = Substitute.For(); - result.Name.Returns(nameAndAddress.Item1); - result.CloneUrl.Returns(new UriString(nameAndAddress.Item2)); - return result; + return new LocalRepositoryModel + { + Name = nameAndAddress.Item1, + CloneUrl = new UriString(nameAndAddress.Item2) + }; } } From dcbf8d1896629a4e2427d315cfe43ccc594a7fbe Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Mon, 5 Nov 2018 16:08:00 +0000 Subject: [PATCH 36/39] Fix tests in PullRequestCreationViewModelTests Not sure why branch in PullRequestCreationViewModel.Branches is coming up null in unit test. Need to investigate. --- .../GitHubPane/PullRequestCreationViewModel.cs | 3 ++- .../GitHubPane/PullRequestCreationViewModelTests.cs | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index 8750d9db5a..a98555751f 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -82,7 +82,8 @@ public PullRequestCreationViewModel( .Where(_ => TargetBranch != null) .Subscribe(x => { - if (!x.Any(t => t.Equals(TargetBranch))) + // HACK: Why is `t` null? + if (!x.Any(t => t != null && t.Equals(TargetBranch))) { TargetBranch = GitHubRepository.IsFork ? GitHubRepository.Parent.DefaultBranch : GitHubRepository.DefaultBranch; } diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index 6bc23e1136..24d536b9ab 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -81,12 +81,12 @@ static TestData PrepareTestData( connection.HostAddress.Returns(HostAddress.Create("https://github.com")); - // this is the local repo instance that is available via TeamExplorerServiceHolder and friends - var activeRepo = Substitute.For(); - activeRepo.LocalPath.Returns(""); - activeRepo.Name.Returns(repoName); - activeRepo.CloneUrl.Returns(new UriString("http://github.com/" + sourceRepoOwner + "/" + repoName)); - activeRepo.Owner.Returns(sourceRepoOwner); + var activeRepo = new LocalRepositoryModel + { + LocalPath = "", + Name = repoName, + CloneUrl = new UriString("http://github.com/" + sourceRepoOwner + "/" + repoName) + }; Repository githubRepoParent = null; if (repoIsFork) From c36026979392217a7c5e71eafd444566ac8319c4 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Mon, 5 Nov 2018 18:39:49 +0000 Subject: [PATCH 37/39] Make PrepareTestData default to return no branches Tests started throwing null reference exceptions when we stopped using an interface for BranchModel. This makes PrepareTestData default to return no branches. --- .../ViewModels/GitHubPane/PullRequestCreationViewModel.cs | 5 +++-- .../GitHubPane/PullRequestCreationViewModelTests.cs | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index a98555751f..4d61be1791 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -82,8 +82,9 @@ public PullRequestCreationViewModel( .Where(_ => TargetBranch != null) .Subscribe(x => { - // HACK: Why is `t` null? - if (!x.Any(t => t != null && t.Equals(TargetBranch))) + //// HACK: Why is `t` null? + //if (!x.Any(t => t != null && t.Equals(TargetBranch))) + if (!x.Any(t => t.Equals(TargetBranch))) { TargetBranch = GitHubRepository.IsFork ? GitHubRepository.Parent.DefaultBranch : GitHubRepository.DefaultBranch; } diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index 24d536b9ab..1bafead36d 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -101,6 +101,9 @@ static TestData PrepareTestData( api.GetRepository(Args.String, Args.String).Returns(Observable.Return(githubRepo)); ms.ApiClient.Returns(api); + // Default to returning no branches + ms.GetBranches(null).ReturnsForAnyArgs(Observable.Empty()); + // sets up the libgit2sharp repo and branch objects var l2repo = SetupLocalRepoMock(gitClient, gitService, remote, sourceBranchName, sourceBranchIsTracking); From 79af9aefd619badf672bb8ea5170abb45410cbe2 Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 6 Nov 2018 11:11:55 +0000 Subject: [PATCH 38/39] Remove Octokit.Repository dependency Remove Octokit.Repository dependency from RemoteRepositoryModel. --- src/GitHub.App/Services/ModelService.cs | 17 +++++++++- .../PullRequestCreationViewModel.cs | 17 +++++++++- .../Models/RemoteRepositoryModel.cs | 31 ++++--------------- .../PullRequestCreationViewModelTests.cs | 17 +++++++++- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/GitHub.App/Services/ModelService.cs b/src/GitHub.App/Services/ModelService.cs index 1a0a23c542..79fb0d0b6c 100644 --- a/src/GitHub.App/Services/ModelService.cs +++ b/src/GitHub.App/Services/ModelService.cs @@ -107,7 +107,22 @@ public IObservable> GetAccounts() public IObservable GetForks(RepositoryModel repository) { return ApiClient.GetForks(repository.Owner, repository.Name) - .Select(x => new RemoteRepositoryModel(x)); + .Select(x => CreateRemoteRepositoryModel(x)); + } + + static RemoteRepositoryModel CreateRemoteRepositoryModel(Repository repository) + { + var ownerAccount = new Models.Account(repository.Owner); + var parent = repository.Parent != null ? CreateRemoteRepositoryModel(repository.Parent) : null; + var model = new RemoteRepositoryModel(repository.Id, repository.Name, repository.CloneUrl, + repository.Private, repository.Fork, ownerAccount, parent, repository.DefaultBranch); + + if (parent != null) + { + parent.DefaultBranch.DisplayName = parent.DefaultBranch.Id; + } + + return model; } IObservable GetLicensesFromApi() diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs index 4d61be1791..16c93ede76 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCreationViewModel.cs @@ -149,7 +149,7 @@ public async Task InitializeAsync(LocalRepositoryModel repository, IConnection c SourceBranch = gitService.GetBranch(repository); var obs = modelService.ApiClient.GetRepository(repository.Owner, repository.Name) - .Select(r => new RemoteRepositoryModel(r)) + .Select(r => CreateRemoteRepositoryModel(r)) .PublishLast(); disposables.Add(obs.Connect()); var githubObs = obs; @@ -196,6 +196,21 @@ public async Task InitializeAsync(LocalRepositoryModel repository, IConnection c Initialized = true; } + static RemoteRepositoryModel CreateRemoteRepositoryModel(Repository repository) + { + var ownerAccount = new Models.Account(repository.Owner); + var parent = repository.Parent != null ? CreateRemoteRepositoryModel(repository.Parent) : null; + var model = new RemoteRepositoryModel(repository.Id, repository.Name, repository.CloneUrl, + repository.Private, repository.Fork, ownerAccount, parent, repository.DefaultBranch); + + if (parent != null) + { + parent.DefaultBranch.DisplayName = parent.DefaultBranch.Id; + } + + return model; + } + async Task LoadInitialState(string draftKey) { if (activeLocalRepo.CloneUrl == null) diff --git a/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs b/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs index 780c6f5d8a..abb4096bcf 100644 --- a/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs +++ b/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs @@ -1,6 +1,6 @@ -using GitHub.Primitives; -using System; +using System; using System.Globalization; +using GitHub.Primitives; using GitHub.Extensions; using GitHub.Collections; @@ -27,7 +27,9 @@ protected RemoteRepositoryModel() /// Whether the repository is a fork. /// The repository owner account. /// The parent repository if this repository is a fork. - public RemoteRepositoryModel(long id, string name, UriString cloneUrl, bool isPrivate, bool isFork, IAccount ownerAccount, RemoteRepositoryModel parent) + /// The default branch name (or "master" if undefined). + public RemoteRepositoryModel(long id, string name, UriString cloneUrl, bool isPrivate, bool isFork, IAccount ownerAccount, + RemoteRepositoryModel parent, string defaultBranchName = "master") : base(name, cloneUrl) { Guard.ArgumentNotEmptyString(name, nameof(name)); @@ -37,31 +39,10 @@ public RemoteRepositoryModel(long id, string name, UriString cloneUrl, bool isPr OwnerAccount = ownerAccount; IsFork = isFork; SetIcon(isPrivate, isFork); - // this is an assumption, we'd have to load the repo information from octokit to know for sure - // probably not worth it for this ctor - DefaultBranch = new BranchModel("master", this); + DefaultBranch = new BranchModel(defaultBranchName, this); Parent = parent; } - /// - /// Initializes a new instance of the class. - /// - /// The source octokit repository. - public RemoteRepositoryModel(Octokit.Repository repository) - : base(repository.Name, repository.CloneUrl) - { - Guard.ArgumentNotNull(repository, nameof(repository)); - - Id = repository.Id; - IsFork = repository.Fork; - SetIcon(repository.Private, IsFork); - OwnerAccount = new Account(repository.Owner); - DefaultBranch = new BranchModel(repository.DefaultBranch, this); - Parent = repository.Parent != null ? new RemoteRepositoryModel(repository.Parent) : null; - if (Parent != null) - Parent.DefaultBranch.DisplayName = Parent.DefaultBranch.Id; - } - #region Equality Things public void CopyFrom(RemoteRepositoryModel other) { diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index 1bafead36d..dc7b82fa73 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -93,7 +93,7 @@ static TestData PrepareTestData( githubRepoParent = CreateRepository(targetRepoOwner, repoName, id: 1); var githubRepo = CreateRepository(sourceRepoOwner, repoName, id: 2, parent: githubRepoParent); var sourceBranch = new BranchModel(sourceBranchName, activeRepo); - var sourceRepo = new RemoteRepositoryModel(githubRepo); + var sourceRepo = CreateRemoteRepositoryModel(githubRepo); var targetRepo = targetRepoOwner == sourceRepoOwner ? sourceRepo : sourceRepo.Parent; var targetBranch = targetBranchName != targetRepo.DefaultBranch.Name ? new BranchModel(targetBranchName, targetRepo) : targetRepo.DefaultBranch; @@ -125,6 +125,21 @@ static TestData PrepareTestData( }; } + static RemoteRepositoryModel CreateRemoteRepositoryModel(Repository repository) + { + var ownerAccount = new GitHub.Models.Account(repository.Owner); + var parent = repository.Parent != null ? CreateRemoteRepositoryModel(repository.Parent) : null; + var model = new RemoteRepositoryModel(repository.Id, repository.Name, repository.CloneUrl, + repository.Private, repository.Fork, ownerAccount, parent, repository.DefaultBranch); + + if (parent != null) + { + parent.DefaultBranch.DisplayName = parent.DefaultBranch.Id; + } + + return model; + } + [Test] public async Task TargetBranchDisplayNameIncludesRepoOwnerWhenForkAsync() { From 2ef556b4836b5a8e798a4be182c51f3c79c3a88c Mon Sep 17 00:00:00 2001 From: Jamie Cansdale Date: Tue, 6 Nov 2018 11:32:34 +0000 Subject: [PATCH 39/39] Clean up *Designer classes Fix warnings in LocalRepositoryModelDesigner and RemoteRepositoryModelDesigner. --- .../LocalRepositoryModelDesigner.cs | 35 +++------------- .../RemoteRepositoryModelDesigner.cs | 41 +++++-------------- .../Models/RemoteRepositoryModel.cs | 12 +++--- .../Models/LocalRepositoryModel.cs | 1 - 4 files changed, 24 insertions(+), 65 deletions(-) diff --git a/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs b/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs index 75597907b6..1a1b4f7189 100644 --- a/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs +++ b/src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs @@ -1,39 +1,16 @@ -using System; -using System.ComponentModel; -using System.Threading.Tasks; -using GitHub.Models; +using GitHub.Models; using GitHub.Primitives; using GitHub.UI; -using GitHub.Exports; namespace GitHub.App.SampleData { public class LocalRepositoryModelDesigner : LocalRepositoryModel { - public UriString CloneUrl { get; set; } + public new UriString CloneUrl { get; set; } public BranchModel CurrentBranch { get; set; } - public Octicon Icon { get; set; } - public string LocalPath { get; set; } - public string Name { get; set; } - public string Owner { get; set; } - -#pragma warning disable CS0067 - public event PropertyChangedEventHandler PropertyChanged; -#pragma warning restore CS0067 - - public Task GenerateUrl(LinkType linkType, string path = null, int startLine = -1, int endLine = -1) - { - throw new NotImplementedException(); - } - - public void Refresh() - { - throw new NotImplementedException(); - } - - public void SetIcon(bool isPrivate, bool isFork) - { - throw new NotImplementedException(); - } + public new Octicon Icon { get; set; } + public new string LocalPath { get; set; } + public new string Name { get; set; } + public new string Owner { get; set; } } } diff --git a/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs b/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs index d82d298979..a87fe8d8db 100644 --- a/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs +++ b/src/GitHub.App/SampleData/RemoteRepositoryModelDesigner.cs @@ -8,35 +8,16 @@ namespace GitHub.SampleData [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1036:OverrideMethodsOnComparableTypes")] public class RemoteRepositoryModelDesigner : RemoteRepositoryModel { - public UriString CloneUrl { get; set; } - public DateTimeOffset CreatedAt { get; set; } - public BranchModel DefaultBranch { get; set; } - public Octicon Icon { get; set; } - public long Id { get; set; } - public bool IsFork { get; set; } - public string Name { get; set; } - public string Owner { get; set; } - public IAccount OwnerAccount { get; set; } - public RemoteRepositoryModel Parent { get; set; } - public DateTimeOffset UpdatedAt { get; set; } - - public int CompareTo(RemoteRepositoryModel other) - { - return 0; - } - - public void CopyFrom(RemoteRepositoryModel other) - { - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] - public bool Equals(RemoteRepositoryModel other) - { - return false; - } - - public void SetIcon(bool isPrivate, bool isFork) - { - } + public new UriString CloneUrl { get; set; } + public new DateTimeOffset CreatedAt { get; set; } + public new BranchModel DefaultBranch { get; set; } + public new Octicon Icon { get; set; } + public new long Id { get; set; } + public new bool IsFork { get; set; } + public new string Name { get; set; } + public new string Owner { get; set; } + public new IAccount OwnerAccount { get; set; } + public new RemoteRepositoryModel Parent { get; set; } + public new DateTimeOffset UpdatedAt { get; set; } } } diff --git a/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs b/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs index abb4096bcf..838dda5b8e 100644 --- a/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs +++ b/src/GitHub.Exports.Reactive/Models/RemoteRepositoryModel.cs @@ -12,11 +12,6 @@ namespace GitHub.Models public class RemoteRepositoryModel : RepositoryModel, ICopyable, IEquatable, IComparable { - protected RemoteRepositoryModel() - { - // Used by designer - } - /// /// Initializes a new instance of the class. /// @@ -43,6 +38,13 @@ public RemoteRepositoryModel(long id, string name, UriString cloneUrl, bool isPr Parent = parent; } + /// + /// This is used by . + /// + protected RemoteRepositoryModel() + { + } + #region Equality Things public void CopyFrom(RemoteRepositoryModel other) { diff --git a/src/GitHub.Exports/Models/LocalRepositoryModel.cs b/src/GitHub.Exports/Models/LocalRepositoryModel.cs index e68d916586..edaf63a559 100644 --- a/src/GitHub.Exports/Models/LocalRepositoryModel.cs +++ b/src/GitHub.Exports/Models/LocalRepositoryModel.cs @@ -59,6 +59,5 @@ public bool Equals(LocalRepositoryModel other) CloneUrl, LocalPath, GetHashCode()); - } }