From e4c816292ae994bfb25f4d1d515f232bf1f6ee91 Mon Sep 17 00:00:00 2001 From: Andreia Gaita Date: Thu, 7 Jan 2016 15:35:56 +0100 Subject: [PATCH 01/24] Stub of "Get Link" feature Quick stub of the VS file apis required for a potential "Get Link" feature - gets the current file name and line number to build a github url of it for sharing. --- src/GitHub.Exports/GitHub.Exports.csproj | 1 + .../Services/IActiveDocument.cs | 8 ++++ .../GitHub.VisualStudio.csproj | 1 + .../GitHub.VisualStudio.vsct | 9 +++++ src/GitHub.VisualStudio/GitHubPackage.cs | 11 ++++++ src/GitHub.VisualStudio/PkgCmdID.cs | 1 + .../Services/ActiveDocument.cs | 37 +++++++++++++++++++ 7 files changed, 68 insertions(+) create mode 100644 src/GitHub.Exports/Services/IActiveDocument.cs create mode 100644 src/GitHub.VisualStudio/Services/ActiveDocument.cs diff --git a/src/GitHub.Exports/GitHub.Exports.csproj b/src/GitHub.Exports/GitHub.Exports.csproj index 1af946bbd0..9d8276006d 100644 --- a/src/GitHub.Exports/GitHub.Exports.csproj +++ b/src/GitHub.Exports/GitHub.Exports.csproj @@ -111,6 +111,7 @@ + diff --git a/src/GitHub.Exports/Services/IActiveDocument.cs b/src/GitHub.Exports/Services/IActiveDocument.cs new file mode 100644 index 0000000000..43c6456c0f --- /dev/null +++ b/src/GitHub.Exports/Services/IActiveDocument.cs @@ -0,0 +1,8 @@ +namespace GitHub.VisualStudio +{ + public interface IActiveDocument + { + string Name { get; } + int Line { get; } + } +} diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj b/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj index 51bdd71c9a..1628e2f314 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj @@ -222,6 +222,7 @@ + diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct index 42c0218828..a04120247f 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct @@ -119,6 +119,14 @@ + + + @@ -178,6 +186,7 @@ + diff --git a/src/GitHub.VisualStudio/GitHubPackage.cs b/src/GitHub.VisualStudio/GitHubPackage.cs index 50c8c57370..64c9722b63 100644 --- a/src/GitHub.VisualStudio/GitHubPackage.cs +++ b/src/GitHub.VisualStudio/GitHubPackage.cs @@ -45,6 +45,8 @@ public GitHubPackage(IServiceProvider serviceProvider) } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals")] protected override void Initialize() { @@ -58,6 +60,15 @@ protected override void Initialize() var windowFrame = (IVsWindowFrame)window.Frame; ErrorHandler.ThrowOnFailure(windowFrame.Show()); }); + + ServiceProvider.AddTopLevelMenuItem(GuidList.guidContextMenuSet, PkgCmdIDList.getLinkCommand, (s, e) => + { + var ap = ServiceProvider.GetExportedValue(); + var name = ap.Name; + var line = ap.Line; + System.Windows.Forms.MessageBox.Show(name + " : " + line); + + }); base.Initialize(); } diff --git a/src/GitHub.VisualStudio/PkgCmdID.cs b/src/GitHub.VisualStudio/PkgCmdID.cs index 1b20104b15..c082562323 100644 --- a/src/GitHub.VisualStudio/PkgCmdID.cs +++ b/src/GitHub.VisualStudio/PkgCmdID.cs @@ -11,5 +11,6 @@ static class PkgCmdIDList public const int forwardCommand = 0x301; public const int refreshCommand = 0x302; public const int pullRequestCommand = 0x310; + public const int getLinkCommand = 0x100; }; } \ No newline at end of file diff --git a/src/GitHub.VisualStudio/Services/ActiveDocument.cs b/src/GitHub.VisualStudio/Services/ActiveDocument.cs new file mode 100644 index 0000000000..6025c5bb90 --- /dev/null +++ b/src/GitHub.VisualStudio/Services/ActiveDocument.cs @@ -0,0 +1,37 @@ +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.ComponentModel.Composition; +using System.Diagnostics; + +namespace GitHub.VisualStudio +{ + [Export(typeof(IActiveDocument))] + [PartCreationPolicy(CreationPolicy.NonShared)] + class ActiveDocument : IActiveDocument + { + public string Name { get; private set; } + public int Line { get; private set; } + public int Column { get; private set; } + + [ImportingConstructor] + public ActiveDocument([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) + { + Line = Column = -1; + Name = Services.Dte2?.ActiveDocument?.FullName; + var textManager = serviceProvider.GetService(typeof(SVsTextManager)) as IVsTextManager; + Debug.Assert(textManager != null, "No SVsTextManager service available"); + if (textManager == null) + return; + IVsTextView view; + int line, col; + if (ErrorHandler.Succeeded(textManager.GetActiveView(0, null, out view)) && + ErrorHandler.Succeeded(view.GetCaretPos(out line, out col))) + { + Line = line; + Column = col; + } + } + } +} From 069dc802a65fe21bf1ebcb2616efdebd6a51564c Mon Sep 17 00:00:00 2001 From: Austin Green Date: Thu, 7 Jan 2016 14:34:45 -0600 Subject: [PATCH 02/24] Basic implementation for opening selection in browser --- src/GitHub.App/Api/ApiClientConfiguration.cs | 4 +- .../SimpleRepositoryModelExtensions.cs | 7 ++++ .../Services/IActiveDocument.cs | 5 ++- .../GitHub.VisualStudio.vsct | 4 +- src/GitHub.VisualStudio/GitHubPackage.cs | 40 +++++++++++++++---- .../Services/ActiveDocument.cs | 25 +++++++----- 6 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/GitHub.App/Api/ApiClientConfiguration.cs b/src/GitHub.App/Api/ApiClientConfiguration.cs index 16f7eb2e97..483faffcfc 100644 --- a/src/GitHub.App/Api/ApiClientConfiguration.cs +++ b/src/GitHub.App/Api/ApiClientConfiguration.cs @@ -2,8 +2,8 @@ namespace GitHub.Api { public partial class ApiClient : IApiClient { - const string clientId = "YOUR CLIENT ID HERE"; - const string clientSecret = "YOUR CLIENT SECRET HERE"; + const string clientId = ""; + const string clientSecret = ""; partial void Configure() { diff --git a/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs b/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs index c5089e3d82..a99be833f9 100644 --- a/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs +++ b/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs @@ -30,5 +30,12 @@ public static bool MightContainSolution(this ISimpleRepositoryModel repository) .Any(x => ((x.Attributes.HasFlag(FileAttributes.Directory) || x.Attributes.HasFlag(FileAttributes.Normal)) && !x.Name.StartsWith(".", StringComparison.Ordinal) && !x.Name.StartsWith("readme", StringComparison.OrdinalIgnoreCase))); } + + public static string CurrentSha(this ISimpleRepositoryModel repository) + { + var repo = GitService.GitServiceHelper.GetRepo(repository.LocalPath); + var firstCommit = repo.Commits.ElementAt(0); + return firstCommit.Sha; + } } } diff --git a/src/GitHub.Exports/Services/IActiveDocument.cs b/src/GitHub.Exports/Services/IActiveDocument.cs index 43c6456c0f..ec3fec518a 100644 --- a/src/GitHub.Exports/Services/IActiveDocument.cs +++ b/src/GitHub.Exports/Services/IActiveDocument.cs @@ -3,6 +3,9 @@ public interface IActiveDocument { string Name { get; } - int Line { get; } + int AnchorLine { get; } + int AnchorColumn { get; } + int EndLine { get; } + int EndColumn { get; } } } diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct index a04120247f..393fa1e8f6 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct @@ -122,8 +122,10 @@ diff --git a/src/GitHub.VisualStudio/GitHubPackage.cs b/src/GitHub.VisualStudio/GitHubPackage.cs index 64c9722b63..46743846bc 100644 --- a/src/GitHub.VisualStudio/GitHubPackage.cs +++ b/src/GitHub.VisualStudio/GitHubPackage.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.InteropServices; using GitHub.Extensions; using GitHub.Services; @@ -60,16 +61,39 @@ protected override void Initialize() var windowFrame = (IVsWindowFrame)window.Frame; ErrorHandler.ThrowOnFailure(windowFrame.Show()); }); + ServiceProvider.AddDynamicMenuItem(GuidList.guidContextMenuSet, PkgCmdIDList.getLinkCommand, + IsValidGithubRepo, + OpenRepoInBrowser); + + base.Initialize(); + } + + private bool IsValidGithubRepo() + { + return !string.IsNullOrEmpty(ServiceProvider.GetExportedValue().ActiveRepo?.CloneUrl?.RepositoryName); + } + + private void OpenRepoInBrowser() + { + var activeDocument = ServiceProvider.GetExportedValue(); + var activeRepo = ServiceProvider.GetExportedValue().ActiveRepo; + + var currentCommitSha = activeRepo.CurrentSha(); + var lineTag = "L" + activeDocument.AnchorLine; - ServiceProvider.AddTopLevelMenuItem(GuidList.guidContextMenuSet, PkgCmdIDList.getLinkCommand, (s, e) => + if (activeDocument.AnchorLine != activeDocument.EndLine) { - var ap = ServiceProvider.GetExportedValue(); - var name = ap.Name; - var line = ap.Line; - System.Windows.Forms.MessageBox.Show(name + " : " + line); - - }); - base.Initialize(); + lineTag += "-L" + activeDocument.EndLine; + } + + var outputUri = string.Format(CultureInfo.CurrentCulture, "{0}/blob/{1}{2}#L{3}", + activeRepo.CloneUrl, + currentCommitSha, + activeDocument.Name.Replace(activeRepo.LocalPath, "").Replace("\\", "/"), + lineTag); + + var vsBrowserProvider = ServiceProvider.GetExportedValue(); + vsBrowserProvider.OpenUrl(new Uri(outputUri)); } void StartFlow(UIControllerFlow controllerFlow) diff --git a/src/GitHub.VisualStudio/Services/ActiveDocument.cs b/src/GitHub.VisualStudio/Services/ActiveDocument.cs index 6025c5bb90..32f345b678 100644 --- a/src/GitHub.VisualStudio/Services/ActiveDocument.cs +++ b/src/GitHub.VisualStudio/Services/ActiveDocument.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel.Composition; using System.Diagnostics; +using System.Windows.Media.TextFormatting; namespace GitHub.VisualStudio { @@ -12,25 +13,31 @@ namespace GitHub.VisualStudio class ActiveDocument : IActiveDocument { public string Name { get; private set; } - public int Line { get; private set; } - public int Column { get; private set; } + public string ShortName { get; private set; } + public int AnchorLine { get; private set; } + public int AnchorColumn { get; private set; } + public int EndLine { get; private set; } + public int EndColumn { get; private set; } [ImportingConstructor] public ActiveDocument([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) { - Line = Column = -1; + AnchorLine = AnchorColumn = EndLine = EndColumn = -1; Name = Services.Dte2?.ActiveDocument?.FullName; + ShortName = Services.Dte2?.ActiveDocument?.Name; + var textManager = serviceProvider.GetService(typeof(SVsTextManager)) as IVsTextManager; Debug.Assert(textManager != null, "No SVsTextManager service available"); - if (textManager == null) - return; + IVsTextView view; - int line, col; + int anchorLine, anchorCol, endLine, endCol; if (ErrorHandler.Succeeded(textManager.GetActiveView(0, null, out view)) && - ErrorHandler.Succeeded(view.GetCaretPos(out line, out col))) + ErrorHandler.Succeeded(view.GetSelection(out anchorLine, out anchorCol, out endLine, out endCol))) { - Line = line; - Column = col; + AnchorLine = anchorLine + 1; + AnchorColumn = anchorCol + 1; + EndLine = endLine + 1; + EndColumn = endCol + 1; } } } From d4d77627b33a5bad4c3d27696594f58d97e04d36 Mon Sep 17 00:00:00 2001 From: Austin Green Date: Fri, 8 Jan 2016 08:52:43 -0600 Subject: [PATCH 03/24] Refactored browser url creation and added copy to clipboard menu item --- src/GitHub.App/Api/ApiClientConfiguration.cs | 4 +- .../SimpleRepositoryModelExtensions.cs | 40 +++++++++++++++++- .../GitHub.VisualStudio.vsct | 9 ++++ src/GitHub.VisualStudio/GitHubPackage.cs | 42 ++++++++++++------- src/GitHub.VisualStudio/PkgCmdID.cs | 1 + .../Services/ActiveDocument.cs | 4 +- 6 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/GitHub.App/Api/ApiClientConfiguration.cs b/src/GitHub.App/Api/ApiClientConfiguration.cs index 483faffcfc..16f7eb2e97 100644 --- a/src/GitHub.App/Api/ApiClientConfiguration.cs +++ b/src/GitHub.App/Api/ApiClientConfiguration.cs @@ -2,8 +2,8 @@ namespace GitHub.Api { public partial class ApiClient : IApiClient { - const string clientId = ""; - const string clientSecret = ""; + const string clientId = "YOUR CLIENT ID HERE"; + const string clientSecret = "YOUR CLIENT SECRET HERE"; partial void Configure() { diff --git a/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs b/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs index a99be833f9..6b1d08fe76 100644 --- a/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs +++ b/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs @@ -1,9 +1,11 @@ using System; +using System.Globalization; using System.Linq; using System.IO; using GitHub.Models; using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility; using GitHub.Services; +using GitHub.VisualStudio; namespace GitHub.Extensions { @@ -33,9 +35,43 @@ public static bool MightContainSolution(this ISimpleRepositoryModel repository) public static string CurrentSha(this ISimpleRepositoryModel repository) { + if (repository == null) + return null; + var repo = GitService.GitServiceHelper.GetRepo(repository.LocalPath); - var firstCommit = repo.Commits.ElementAt(0); - return firstCommit.Sha; + + if (repo == null) + return null; + + return !repo.Commits.Any() ? null : repo.Commits.ElementAt(0).Sha; + } + + public static string BrowserUrl(this ISimpleRepositoryModel repository, IActiveDocument activeDocument) + { + if (repository == null || activeDocument == null) + return null; + + var currentCommitSha = repository.CurrentSha(); + var currentCloneUrl = repository.CloneUrl; + var localPath = repository.LocalPath; + var lineTag = "L" + activeDocument.AnchorLine; + + if (string.IsNullOrEmpty(currentCommitSha) || string.IsNullOrEmpty(currentCloneUrl) || + string.IsNullOrEmpty(localPath)) + return null; + + if (activeDocument.AnchorLine != activeDocument.EndLine) + { + lineTag += "-L" + activeDocument.EndLine; + } + + var outputUri = string.Format(CultureInfo.CurrentCulture, "{0}/blob/{1}{2}#{3}", + currentCloneUrl, + currentCommitSha, + activeDocument.Name.Replace(localPath, "").Replace("\\", "/"), + lineTag); + + return outputUri; } } } diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct index 393fa1e8f6..0f471dd264 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct @@ -129,6 +129,14 @@ + @@ -189,6 +197,7 @@ + diff --git a/src/GitHub.VisualStudio/GitHubPackage.cs b/src/GitHub.VisualStudio/GitHubPackage.cs index 46743846bc..0ac7b25a20 100644 --- a/src/GitHub.VisualStudio/GitHubPackage.cs +++ b/src/GitHub.VisualStudio/GitHubPackage.cs @@ -2,6 +2,7 @@ using System.Globalization; using System.Runtime.InteropServices; using GitHub.Extensions; +using GitHub.Models; using GitHub.Services; using GitHub.UI; using GitHub.VisualStudio.Base; @@ -64,33 +65,46 @@ protected override void Initialize() ServiceProvider.AddDynamicMenuItem(GuidList.guidContextMenuSet, PkgCmdIDList.getLinkCommand, IsValidGithubRepo, OpenRepoInBrowser); - + ServiceProvider.AddDynamicMenuItem(GuidList.guidContextMenuSet, PkgCmdIDList.copyLinkCommand, + IsValidGithubRepo, + CopyRepoLinkToClipboard); + base.Initialize(); } + private void CopyRepoLinkToClipboard() + { + if (!IsValidGithubRepo()) return; + + var activeDocument = ServiceProvider.GetExportedValue(); + var activeRepo = ServiceProvider.GetExportedValue().ActiveRepo; + var outputUri = activeRepo?.BrowserUrl(activeDocument); + + if (string.IsNullOrEmpty(outputUri)) return; + + System.Windows.Clipboard.SetText(outputUri); + } + private bool IsValidGithubRepo() { - return !string.IsNullOrEmpty(ServiceProvider.GetExportedValue().ActiveRepo?.CloneUrl?.RepositoryName); + var cloneUrl = ServiceProvider.GetExportedValue().ActiveRepo?.CloneUrl; + + if (string.IsNullOrEmpty(cloneUrl)) + return false; + + return cloneUrl.Host == "github.com"; } private void OpenRepoInBrowser() { + if (!IsValidGithubRepo()) return; + var activeDocument = ServiceProvider.GetExportedValue(); var activeRepo = ServiceProvider.GetExportedValue().ActiveRepo; - var currentCommitSha = activeRepo.CurrentSha(); - var lineTag = "L" + activeDocument.AnchorLine; + var outputUri = activeRepo?.BrowserUrl(activeDocument); - if (activeDocument.AnchorLine != activeDocument.EndLine) - { - lineTag += "-L" + activeDocument.EndLine; - } - - var outputUri = string.Format(CultureInfo.CurrentCulture, "{0}/blob/{1}{2}#L{3}", - activeRepo.CloneUrl, - currentCommitSha, - activeDocument.Name.Replace(activeRepo.LocalPath, "").Replace("\\", "/"), - lineTag); + if (string.IsNullOrEmpty(outputUri)) return; var vsBrowserProvider = ServiceProvider.GetExportedValue(); vsBrowserProvider.OpenUrl(new Uri(outputUri)); diff --git a/src/GitHub.VisualStudio/PkgCmdID.cs b/src/GitHub.VisualStudio/PkgCmdID.cs index c082562323..97b2b314ae 100644 --- a/src/GitHub.VisualStudio/PkgCmdID.cs +++ b/src/GitHub.VisualStudio/PkgCmdID.cs @@ -12,5 +12,6 @@ static class PkgCmdIDList public const int refreshCommand = 0x302; public const int pullRequestCommand = 0x310; public const int getLinkCommand = 0x100; + public const int copyLinkCommand = 0x101; }; } \ No newline at end of file diff --git a/src/GitHub.VisualStudio/Services/ActiveDocument.cs b/src/GitHub.VisualStudio/Services/ActiveDocument.cs index 32f345b678..dd43c4dbcd 100644 --- a/src/GitHub.VisualStudio/Services/ActiveDocument.cs +++ b/src/GitHub.VisualStudio/Services/ActiveDocument.cs @@ -4,7 +4,6 @@ using System; using System.ComponentModel.Composition; using System.Diagnostics; -using System.Windows.Media.TextFormatting; namespace GitHub.VisualStudio { @@ -28,7 +27,8 @@ public ActiveDocument([Import(typeof(SVsServiceProvider))] IServiceProvider serv var textManager = serviceProvider.GetService(typeof(SVsTextManager)) as IVsTextManager; Debug.Assert(textManager != null, "No SVsTextManager service available"); - + if (textManager == null) + return; IVsTextView view; int anchorLine, anchorCol, endLine, endCol; if (ErrorHandler.Succeeded(textManager.GetActiveView(0, null, out view)) && From 068c43ae0bc79abe7665ab10c43e7b5df95b747f Mon Sep 17 00:00:00 2001 From: Andreia Gaita Date: Tue, 12 Jan 2016 12:45:14 +0100 Subject: [PATCH 04/24] Give IActiveDocument a better name --- src/GitHub.Exports/GitHub.Exports.csproj | 2 +- src/GitHub.Exports/Services/IActiveDocument.cs | 11 ----------- .../Services/IActiveDocumentSnapshot.cs | 9 +++++++++ .../GitHub.VisualStudio.csproj | 2 +- .../ActiveDocumentSnapshot.cs} | 18 ++++++------------ 5 files changed, 17 insertions(+), 25 deletions(-) delete mode 100644 src/GitHub.Exports/Services/IActiveDocument.cs create mode 100644 src/GitHub.Exports/Services/IActiveDocumentSnapshot.cs rename src/GitHub.VisualStudio/{Services/ActiveDocument.cs => Helpers/ActiveDocumentSnapshot.cs} (63%) diff --git a/src/GitHub.Exports/GitHub.Exports.csproj b/src/GitHub.Exports/GitHub.Exports.csproj index 5dc57be2f0..105b6ccc07 100644 --- a/src/GitHub.Exports/GitHub.Exports.csproj +++ b/src/GitHub.Exports/GitHub.Exports.csproj @@ -111,7 +111,7 @@ - + diff --git a/src/GitHub.Exports/Services/IActiveDocument.cs b/src/GitHub.Exports/Services/IActiveDocument.cs deleted file mode 100644 index ec3fec518a..0000000000 --- a/src/GitHub.Exports/Services/IActiveDocument.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace GitHub.VisualStudio -{ - public interface IActiveDocument - { - string Name { get; } - int AnchorLine { get; } - int AnchorColumn { get; } - int EndLine { get; } - int EndColumn { get; } - } -} diff --git a/src/GitHub.Exports/Services/IActiveDocumentSnapshot.cs b/src/GitHub.Exports/Services/IActiveDocumentSnapshot.cs new file mode 100644 index 0000000000..60fcdca44b --- /dev/null +++ b/src/GitHub.Exports/Services/IActiveDocumentSnapshot.cs @@ -0,0 +1,9 @@ +namespace GitHub.VisualStudio +{ + public interface IActiveDocumentSnapshot + { + string Name { get; } + int StartLine { get; } + int EndLine { get; } + } +} diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj b/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj index 2a49fbf297..90cded55a0 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj @@ -212,6 +212,7 @@ + @@ -224,7 +225,6 @@ - diff --git a/src/GitHub.VisualStudio/Services/ActiveDocument.cs b/src/GitHub.VisualStudio/Helpers/ActiveDocumentSnapshot.cs similarity index 63% rename from src/GitHub.VisualStudio/Services/ActiveDocument.cs rename to src/GitHub.VisualStudio/Helpers/ActiveDocumentSnapshot.cs index dd43c4dbcd..a812875d40 100644 --- a/src/GitHub.VisualStudio/Services/ActiveDocument.cs +++ b/src/GitHub.VisualStudio/Helpers/ActiveDocumentSnapshot.cs @@ -7,23 +7,19 @@ namespace GitHub.VisualStudio { - [Export(typeof(IActiveDocument))] + [Export(typeof(IActiveDocumentSnapshot))] [PartCreationPolicy(CreationPolicy.NonShared)] - class ActiveDocument : IActiveDocument + class ActiveDocumentSnapshot : IActiveDocumentSnapshot { public string Name { get; private set; } - public string ShortName { get; private set; } - public int AnchorLine { get; private set; } - public int AnchorColumn { get; private set; } + public int StartLine { get; private set; } public int EndLine { get; private set; } - public int EndColumn { get; private set; } [ImportingConstructor] - public ActiveDocument([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) + public ActiveDocumentSnapshot([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) { - AnchorLine = AnchorColumn = EndLine = EndColumn = -1; + StartLine = EndLine = -1; Name = Services.Dte2?.ActiveDocument?.FullName; - ShortName = Services.Dte2?.ActiveDocument?.Name; var textManager = serviceProvider.GetService(typeof(SVsTextManager)) as IVsTextManager; Debug.Assert(textManager != null, "No SVsTextManager service available"); @@ -34,10 +30,8 @@ public ActiveDocument([Import(typeof(SVsServiceProvider))] IServiceProvider serv if (ErrorHandler.Succeeded(textManager.GetActiveView(0, null, out view)) && ErrorHandler.Succeeded(view.GetSelection(out anchorLine, out anchorCol, out endLine, out endCol))) { - AnchorLine = anchorLine + 1; - AnchorColumn = anchorCol + 1; + StartLine = anchorLine + 1; EndLine = endLine + 1; - EndColumn = endCol + 1; } } } From 72828e26a0aa63802db5da2445560f14179ad843 Mon Sep 17 00:00:00 2001 From: Andreia Gaita Date: Tue, 12 Jan 2016 12:45:56 +0100 Subject: [PATCH 05/24] Give a better name to the open link command --- src/GitHub.VisualStudio/GitHub.VisualStudio.vsct | 4 ++-- src/GitHub.VisualStudio/PkgCmdID.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct index b501483d8c..6969ae3cac 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct @@ -120,7 +120,7 @@ - diff --git a/src/GitHub.VisualStudio/Menus/CopyLink.cs b/src/GitHub.VisualStudio/Menus/CopyLink.cs index 8d5d58a0ed..9f1723b9f2 100644 --- a/src/GitHub.VisualStudio/Menus/CopyLink.cs +++ b/src/GitHub.VisualStudio/Menus/CopyLink.cs @@ -2,6 +2,8 @@ using System; using System.ComponentModel.Composition; using System.Windows; +using GitHub.Extensions; +using GitHub.Services; namespace GitHub.VisualStudio.Menus { @@ -27,6 +29,8 @@ public void Activate() if (link == null) return; Clipboard.SetText(link.AbsoluteUri); + var ns = ServiceProvider.GetExportedValue(); + ns?.ShowMessage(Resources.LinkCopiedToClipboardMessage); } public bool CanShow() diff --git a/src/GitHub.VisualStudio/Resources.Designer.cs b/src/GitHub.VisualStudio/Resources.Designer.cs index 959c260bf9..5754568ab9 100644 --- a/src/GitHub.VisualStudio/Resources.Designer.cs +++ b/src/GitHub.VisualStudio/Resources.Designer.cs @@ -303,6 +303,15 @@ public static string licenseListText { } } + /// + /// Looks up a localized string similar to Link copied to clipboard. + /// + public static string LinkCopiedToClipboardMessage { + get { + return ResourceManager.GetString("LinkCopiedToClipboardMessage", resourceCulture); + } + } + /// /// Looks up a localized string similar to Some or all repositories may not have loaded. Close the dialog and try again.. /// diff --git a/src/GitHub.VisualStudio/Resources.resx b/src/GitHub.VisualStudio/Resources.resx index 4f0f18e23e..407dd8d2bb 100644 --- a/src/GitHub.VisualStudio/Resources.resx +++ b/src/GitHub.VisualStudio/Resources.resx @@ -282,4 +282,7 @@ Repository created successfully. + + Link copied to clipboard + \ No newline at end of file From 68aef1968daa5ab500b9d8639bc75332ccae3506 Mon Sep 17 00:00:00 2001 From: Phil Haack Date: Mon, 8 Feb 2016 16:02:46 -0800 Subject: [PATCH 10/24] Minor formatting change Just want to feel like I'm contributing something. :stuck_out_tongue: --- src/GitHub.VisualStudio/Menus/CopyLink.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHub.VisualStudio/Menus/CopyLink.cs b/src/GitHub.VisualStudio/Menus/CopyLink.cs index 9f1723b9f2..5131fc289b 100644 --- a/src/GitHub.VisualStudio/Menus/CopyLink.cs +++ b/src/GitHub.VisualStudio/Menus/CopyLink.cs @@ -9,7 +9,7 @@ namespace GitHub.VisualStudio.Menus { [Export(typeof(IDynamicMenuHandler))] [PartCreationPolicy(CreationPolicy.Shared)] - public class CopyLink: LinkMenuBase, IDynamicMenuHandler + public class CopyLink : LinkMenuBase, IDynamicMenuHandler { [ImportingConstructor] public CopyLink([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) From 499cba88ddeeeb1e77726d6bbd46b397dc819d4f Mon Sep 17 00:00:00 2001 From: Andreia Gaita Date: Tue, 9 Feb 2016 13:03:40 +0100 Subject: [PATCH 11/24] Style cleanup --- .../Extensions/SimpleRepositoryModelExtensions.cs | 1 - src/GitHub.Exports/Models/SimpleRepositoryModel.cs | 2 +- src/GitHub.VisualStudio/Menus/AddConnection.cs | 4 ++-- src/GitHub.VisualStudio/Menus/CopyLink.cs | 4 ++-- src/GitHub.VisualStudio/Menus/LinkMenuBase.cs | 4 ---- src/GitHub.VisualStudio/Menus/MenuProvider.cs | 4 ++-- src/GitHub.VisualStudio/Menus/OpenLink.cs | 5 ++--- src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs | 6 +++--- 8 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs b/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs index 7ea8d9f1e7..381c5ef022 100644 --- a/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs +++ b/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs @@ -5,7 +5,6 @@ using GitHub.Models; using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility; using GitHub.Services; -using GitHub.VisualStudio; using GitHub.Primitives; using System.Text; using System.Diagnostics; diff --git a/src/GitHub.Exports/Models/SimpleRepositoryModel.cs b/src/GitHub.Exports/Models/SimpleRepositoryModel.cs index 9bb2672660..8d6ef37c18 100644 --- a/src/GitHub.Exports/Models/SimpleRepositoryModel.cs +++ b/src/GitHub.Exports/Models/SimpleRepositoryModel.cs @@ -10,7 +10,7 @@ namespace GitHub.Models { [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class SimpleRepositoryModel : NotificationAwareObject, ISimpleRepositoryModel, INotifyPropertySource, IEquatable + public class SimpleRepositoryModel : NotificationAwareObject, ISimpleRepositoryModel, IEquatable { public SimpleRepositoryModel(string name, UriString cloneUrl, string localPath = null) { diff --git a/src/GitHub.VisualStudio/Menus/AddConnection.cs b/src/GitHub.VisualStudio/Menus/AddConnection.cs index 7ed0dad0ee..c9e397f7c3 100644 --- a/src/GitHub.VisualStudio/Menus/AddConnection.cs +++ b/src/GitHub.VisualStudio/Menus/AddConnection.cs @@ -17,8 +17,8 @@ public AddConnection([Import(typeof(SVsServiceProvider))] IServiceProvider servi { } - public Guid Guid { get { return GuidList.guidGitHubCmdSet; } } - public int CmdId { get { return PkgCmdIDList.addConnectionCommand; } } + public Guid Guid => GuidList.guidGitHubCmdSet; + public int CmdId => PkgCmdIDList.addConnectionCommand; public void Activate() { diff --git a/src/GitHub.VisualStudio/Menus/CopyLink.cs b/src/GitHub.VisualStudio/Menus/CopyLink.cs index 5131fc289b..78fd592622 100644 --- a/src/GitHub.VisualStudio/Menus/CopyLink.cs +++ b/src/GitHub.VisualStudio/Menus/CopyLink.cs @@ -17,8 +17,8 @@ public CopyLink([Import(typeof(SVsServiceProvider))] IServiceProvider servicePro { } - public Guid Guid { get { return GuidList.guidContextMenuSet; } } - public int CmdId { get { return PkgCmdIDList.copyLinkCommand; } } + public Guid Guid => GuidList.guidContextMenuSet; + public int CmdId => PkgCmdIDList.copyLinkCommand; public void Activate() { diff --git a/src/GitHub.VisualStudio/Menus/LinkMenuBase.cs b/src/GitHub.VisualStudio/Menus/LinkMenuBase.cs index 24d4f2856d..410ba583be 100644 --- a/src/GitHub.VisualStudio/Menus/LinkMenuBase.cs +++ b/src/GitHub.VisualStudio/Menus/LinkMenuBase.cs @@ -1,9 +1,5 @@ using GitHub.Extensions; -using GitHub.Models; -using GitHub.Services; -using Microsoft.VisualStudio.Shell; using System; -using System.Globalization; namespace GitHub.VisualStudio.Menus { diff --git a/src/GitHub.VisualStudio/Menus/MenuProvider.cs b/src/GitHub.VisualStudio/Menus/MenuProvider.cs index 49d0bddcf2..082130dde6 100644 --- a/src/GitHub.VisualStudio/Menus/MenuProvider.cs +++ b/src/GitHub.VisualStudio/Menus/MenuProvider.cs @@ -9,9 +9,9 @@ namespace GitHub.VisualStudio.Menus [PartCreationPolicy(CreationPolicy.Shared)] public class MenuProvider : IMenuProvider { - public IReadOnlyCollection Menus { get; private set; } + public IReadOnlyCollection Menus { get; } - public IReadOnlyCollection DynamicMenus { get; private set; } + public IReadOnlyCollection DynamicMenus { get; } [ImportingConstructor] public MenuProvider([ImportMany] IEnumerable menus, [ImportMany] IEnumerable dynamicMenus) diff --git a/src/GitHub.VisualStudio/Menus/OpenLink.cs b/src/GitHub.VisualStudio/Menus/OpenLink.cs index 57214b2313..ceb9e1cb04 100644 --- a/src/GitHub.VisualStudio/Menus/OpenLink.cs +++ b/src/GitHub.VisualStudio/Menus/OpenLink.cs @@ -3,7 +3,6 @@ using Microsoft.VisualStudio.Shell; using System; using System.ComponentModel.Composition; -using System.Windows; namespace GitHub.VisualStudio.Menus { @@ -17,8 +16,8 @@ public OpenLink([Import(typeof(SVsServiceProvider))] IServiceProvider servicePro { } - public Guid Guid { get { return GuidList.guidContextMenuSet; } } - public int CmdId { get { return PkgCmdIDList.openLinkCommand; } } + public Guid Guid => GuidList.guidContextMenuSet; + public int CmdId => PkgCmdIDList.openLinkCommand; public void Activate() { diff --git a/src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs b/src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs index 7160d8c08d..e579e936de 100644 --- a/src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs +++ b/src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs @@ -2,14 +2,14 @@ using System; using System.ComponentModel.Composition; -namespace GitHub.VisualStudio +namespace GitHub.VisualStudio.Menus { [Export(typeof(IMenuHandler))] [PartCreationPolicy(CreationPolicy.Shared)] public class ShowGitHubPane: MenuBase, IMenuHandler { - public Guid Guid { get { return GuidList.guidGitHubCmdSet; } } - public int CmdId { get { return PkgCmdIDList.showGitHubPaneCommand; } } + public Guid Guid => GuidList.guidGitHubCmdSet; + public int CmdId => PkgCmdIDList.showGitHubPaneCommand; public void Activate() { From 2e2b5e039b5f9bfe60f8c509390d72b618027236 Mon Sep 17 00:00:00 2001 From: Andreia Gaita Date: Tue, 9 Feb 2016 13:05:02 +0100 Subject: [PATCH 12/24] Move useful functionality into SimpleRepositoryModel --- src/GitHub.App/SampleData/SampleViewModels.cs | 5 ++ .../SimpleRepositoryModelExtensions.cs | 57 ----------------- .../Models/ISimpleRepositoryModel.cs | 1 + .../Models/SimpleRepositoryModel.cs | 61 +++++++++++++++++++ src/GitHub.VisualStudio/Menus/CopyLink.cs | 14 ++++- src/GitHub.VisualStudio/Menus/LinkMenuBase.cs | 3 +- src/GitHub.VisualStudio/Menus/OpenLink.cs | 2 +- src/GitHub.VisualStudio/Resources.Designer.cs | 9 +++ src/GitHub.VisualStudio/Resources.resx | 3 + .../SimpleRepositoryModelTests.cs} | 3 +- src/UnitTests/UnitTests.csproj | 2 +- 11 files changed, 95 insertions(+), 65 deletions(-) rename src/UnitTests/{GitHub.Extensions/SimpleRepositoryModelExtensionTests.cs => GitHub.Exports/SimpleRepositoryModelTests.cs} (97%) diff --git a/src/GitHub.App/SampleData/SampleViewModels.cs b/src/GitHub.App/SampleData/SampleViewModels.cs index 57746efe6c..1ee0298e87 100644 --- a/src/GitHub.App/SampleData/SampleViewModels.cs +++ b/src/GitHub.App/SampleData/SampleViewModels.cs @@ -409,6 +409,11 @@ public void SetIcon(bool isPrivate, bool isFork) { } + public UriString GenerateUrl(string path = null, int startLine = -1, int endLine = -1) + { + return null; + } + public string Name { get; set; } public UriString CloneUrl { get; set; } public string LocalPath { get; set; } diff --git a/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs b/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs index 381c5ef022..c5089e3d82 100644 --- a/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs +++ b/src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs @@ -1,13 +1,9 @@ using System; -using System.Globalization; using System.Linq; using System.IO; using GitHub.Models; using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility; using GitHub.Services; -using GitHub.Primitives; -using System.Text; -using System.Diagnostics; namespace GitHub.Extensions { @@ -34,58 +30,5 @@ public static bool MightContainSolution(this ISimpleRepositoryModel repository) .Any(x => ((x.Attributes.HasFlag(FileAttributes.Directory) || x.Attributes.HasFlag(FileAttributes.Normal)) && !x.Name.StartsWith(".", StringComparison.Ordinal) && !x.Name.StartsWith("readme", StringComparison.OrdinalIgnoreCase))); } - - public static string CurrentSha(this ISimpleRepositoryModel repository) - { - var repo = GitService.GitServiceHelper.GetRepo(repository.LocalPath); - return repo.Commits.FirstOrDefault()?.Sha; - } - - public static Uri GenerateUrl(this ISimpleRepositoryModel repository, string path = null, - int startLine = -1, int endLine = -1) - { - var cloneUrl = repository.CloneUrl; - if (cloneUrl == null) - return null; - - if (path != null && Path.IsPathRooted(path)) - { - // if the path root doesn't match the repository local path, then ignore it - if (repository.LocalPath == null || - !path.StartsWith(repository.LocalPath, StringComparison.OrdinalIgnoreCase)) - { - Debug.Assert(false, String.Format(CultureInfo.CurrentCulture, "GenerateUrl: path {0} doesn't match repository {1}", path, repository.LocalPath)); - path = null; - } - else - path = path.Substring(repository.LocalPath.Length + 1); - } - - var commitSha = repository.CurrentSha(); - var uri = GenerateUrl(cloneUrl.ToRepositoryUrl().AbsoluteUri, commitSha, path, startLine, endLine); - return new UriString(uri).ToUri(); - } - - static string GenerateUrl(string basePath, string sha, string path, int startLine = -1, int endLine = -1) - { - var sb = new StringBuilder(basePath); - if (sha == null) - return sb.ToString(); - - if (String.IsNullOrEmpty(path)) - { - sb.AppendFormat("/commit/{0}", sha); - return sb.ToString(); - } - - sb.AppendFormat("/blob/{0}/{1}", sha, path.Replace(@"\", "/")); - if (startLine < 0) - return sb.ToString(); - sb.AppendFormat("#L{0}", startLine); - if (endLine < 0) - return sb.ToString(); - sb.AppendFormat("-L{0}", endLine); - return sb.ToString(); - } } } diff --git a/src/GitHub.Exports/Models/ISimpleRepositoryModel.cs b/src/GitHub.Exports/Models/ISimpleRepositoryModel.cs index 197a09378f..e1f6ece70c 100644 --- a/src/GitHub.Exports/Models/ISimpleRepositoryModel.cs +++ b/src/GitHub.Exports/Models/ISimpleRepositoryModel.cs @@ -18,5 +18,6 @@ public interface ISimpleRepositoryModel : INotifyPropertyChanged /// Updates the url information based on the local path /// void Refresh(); + UriString GenerateUrl(string path = null, int startLine = -1, int endLine = -1); } } diff --git a/src/GitHub.Exports/Models/SimpleRepositoryModel.cs b/src/GitHub.Exports/Models/SimpleRepositoryModel.cs index 8d6ef37c18..6e0e51b6e8 100644 --- a/src/GitHub.Exports/Models/SimpleRepositoryModel.cs +++ b/src/GitHub.Exports/Models/SimpleRepositoryModel.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; +using System.Linq; using GitHub.Primitives; using GitHub.UI; using GitHub.VisualStudio.Helpers; @@ -53,6 +54,57 @@ public void Refresh() CloneUrl = uri; } + /// + /// 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 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 UriString GenerateUrl(string path = null, int startLine = -1, int endLine = -1) + { + var sha = HeadSha; + if (CloneUrl == null || String.IsNullOrEmpty(sha)) + return null; + + if (path != null && Path.IsPathRooted(path)) + { + // if the path root doesn't match the repository local path, then ignore it + if (LocalPath == null || + !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); + } + + return new UriString(GenerateUrl(cloneUrl.ToRepositoryUrl().AbsoluteUri, sha, path, startLine, endLine)); + } + + const string CommitFormat = "{0}/commit/{1}"; + const string BlobFormat = "{0}/blob/{1}/{2}"; + const string StartLineFormat = "{0}#L{1}"; + const string EndLineFormat = "{0}-L{1}"; + static string GenerateUrl(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, BlobFormat, 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); + } + public string Name { get; } UriString cloneUrl; public UriString CloneUrl { get { return cloneUrl; } set { cloneUrl = value; this.RaisePropertyChange(); } } @@ -60,6 +112,15 @@ public void Refresh() Octicon icon; public Octicon Icon { get { return icon; } set { icon = value; this.RaisePropertyChange(); } } + public string HeadSha + { + get + { + var repo = GitService.GitServiceHelper.GetRepo(LocalPath); + return repo?.Commits.FirstOrDefault()?.Sha ?? String.Empty; + } + } + /// /// 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.VisualStudio/Menus/CopyLink.cs b/src/GitHub.VisualStudio/Menus/CopyLink.cs index 78fd592622..547b1cbcbf 100644 --- a/src/GitHub.VisualStudio/Menus/CopyLink.cs +++ b/src/GitHub.VisualStudio/Menus/CopyLink.cs @@ -28,9 +28,17 @@ public void Activate() var link = GenerateLink(); if (link == null) return; - Clipboard.SetText(link.AbsoluteUri); - var ns = ServiceProvider.GetExportedValue(); - ns?.ShowMessage(Resources.LinkCopiedToClipboardMessage); + try + { + Clipboard.SetText(link); + var ns = ServiceProvider.GetExportedValue(); + ns?.ShowMessage(Resources.LinkCopiedToClipboardMessage); + } + catch + { + var ns = ServiceProvider.GetExportedValue(); + ns?.ShowMessage(Resources.Error_FailedToCopyToClipboard); + } } public bool CanShow() diff --git a/src/GitHub.VisualStudio/Menus/LinkMenuBase.cs b/src/GitHub.VisualStudio/Menus/LinkMenuBase.cs index 410ba583be..49c2931580 100644 --- a/src/GitHub.VisualStudio/Menus/LinkMenuBase.cs +++ b/src/GitHub.VisualStudio/Menus/LinkMenuBase.cs @@ -1,4 +1,5 @@ using GitHub.Extensions; +using GitHub.Primitives; using System; namespace GitHub.VisualStudio.Menus @@ -10,7 +11,7 @@ public LinkMenuBase(IServiceProvider serviceProvider) { } - protected Uri GenerateLink() + protected UriString GenerateLink() { var repo = ActiveRepo; var activeDocument = ServiceProvider.GetExportedValue(); diff --git a/src/GitHub.VisualStudio/Menus/OpenLink.cs b/src/GitHub.VisualStudio/Menus/OpenLink.cs index ceb9e1cb04..03071fba52 100644 --- a/src/GitHub.VisualStudio/Menus/OpenLink.cs +++ b/src/GitHub.VisualStudio/Menus/OpenLink.cs @@ -28,7 +28,7 @@ public void Activate() if (link == null) return; var browser = ServiceProvider.GetExportedValue(); - browser?.OpenUrl(link); + browser?.OpenUrl(link.ToUri()); } public bool CanShow() diff --git a/src/GitHub.VisualStudio/Resources.Designer.cs b/src/GitHub.VisualStudio/Resources.Designer.cs index 5754568ab9..5702488628 100644 --- a/src/GitHub.VisualStudio/Resources.Designer.cs +++ b/src/GitHub.VisualStudio/Resources.Designer.cs @@ -213,6 +213,15 @@ public static string enterpriseUrlPromptText { } } + /// + /// Looks up a localized string similar to Could not copy to the clipboard. Please try again.. + /// + public static string Error_FailedToCopyToClipboard { + get { + return ResourceManager.GetString("Error_FailedToCopyToClipboard", resourceCulture); + } + } + /// /// Looks up a localized string similar to Search repositories. /// diff --git a/src/GitHub.VisualStudio/Resources.resx b/src/GitHub.VisualStudio/Resources.resx index 407dd8d2bb..b56eab92e0 100644 --- a/src/GitHub.VisualStudio/Resources.resx +++ b/src/GitHub.VisualStudio/Resources.resx @@ -285,4 +285,7 @@ Link copied to clipboard + + Could not copy to the clipboard. Please try again. + \ No newline at end of file diff --git a/src/UnitTests/GitHub.Extensions/SimpleRepositoryModelExtensionTests.cs b/src/UnitTests/GitHub.Exports/SimpleRepositoryModelTests.cs similarity index 97% rename from src/UnitTests/GitHub.Extensions/SimpleRepositoryModelExtensionTests.cs rename to src/UnitTests/GitHub.Exports/SimpleRepositoryModelTests.cs index 6d4778ffb1..0da29fc33d 100644 --- a/src/UnitTests/GitHub.Extensions/SimpleRepositoryModelExtensionTests.cs +++ b/src/UnitTests/GitHub.Exports/SimpleRepositoryModelTests.cs @@ -1,5 +1,4 @@ using System; -using GitHub.Extensions; using GitHub.Models; using GitHub.VisualStudio; using LibGit2Sharp; @@ -9,7 +8,7 @@ using GitHub.Primitives; [Collection("PackageServiceProvider global data tests")] -public class SimpleRepositoryModelExtensionTests : TempFileBaseClass +public class SimpleRepositoryModelTests : TempFileBaseClass { void SetupRepository(string sha) { diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 6d412207b0..ae12bad3b6 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -156,7 +156,7 @@ - + From 3228dc293efa58e04e5e0987bc4c1a00ca843483 Mon Sep 17 00:00:00 2001 From: Andreia Gaita Date: Tue, 9 Feb 2016 13:21:22 +0100 Subject: [PATCH 13/24] Fix tests --- src/GitHub.Exports/Models/SimpleRepositoryModel.cs | 13 ++++++++----- .../GitHub.Exports/SimpleRepositoryModelTests.cs | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/GitHub.Exports/Models/SimpleRepositoryModel.cs b/src/GitHub.Exports/Models/SimpleRepositoryModel.cs index 6e0e51b6e8..9e4aaa6af5 100644 --- a/src/GitHub.Exports/Models/SimpleRepositoryModel.cs +++ b/src/GitHub.Exports/Models/SimpleRepositoryModel.cs @@ -64,15 +64,18 @@ public void Refresh() /// 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 UriString GenerateUrl(string path = null, int startLine = -1, int endLine = -1) { - var sha = HeadSha; - if (CloneUrl == null || String.IsNullOrEmpty(sha)) + if (CloneUrl == null) return null; + var sha = HeadSha; + // 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 (LocalPath == null || - !path.StartsWith(LocalPath, StringComparison.OrdinalIgnoreCase)) + 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; @@ -81,7 +84,7 @@ public UriString GenerateUrl(string path = null, int startLine = -1, int endLine path = path.Substring(LocalPath.Length + 1); } - return new UriString(GenerateUrl(cloneUrl.ToRepositoryUrl().AbsoluteUri, sha, path, startLine, endLine)); + return new UriString(GenerateUrl(CloneUrl.ToRepositoryUrl().AbsoluteUri, sha, path, startLine, endLine)); } const string CommitFormat = "{0}/commit/{1}"; diff --git a/src/UnitTests/GitHub.Exports/SimpleRepositoryModelTests.cs b/src/UnitTests/GitHub.Exports/SimpleRepositoryModelTests.cs index 0da29fc33d..5d441ef163 100644 --- a/src/UnitTests/GitHub.Exports/SimpleRepositoryModelTests.cs +++ b/src/UnitTests/GitHub.Exports/SimpleRepositoryModelTests.cs @@ -40,6 +40,7 @@ void SetupRepository(string sha) [InlineData(true, "https://github.com/foo/bar", "123123", @"src\dir\file1.cs", -1, 2, "https://github.com/foo/bar/blob/123123/src/dir/file1.cs")] [InlineData(true, "https://github.com/foo/bar", "", @"src\dir\file1.cs", -1, 2, "https://github.com/foo/bar")] [InlineData(true, null, "123123", @"src\dir\file1.cs", 1, 2, null)] + [InlineData(false, "git@github.com/foo/bar", "123123", @"src\dir\file1.cs", -1, -1, "https://github.com/foo/bar/blob/123123/src/dir/file1.cs")] public void GenerateUrl(bool createRootedPath, string baseUrl, string sha, string path, int startLine, int endLine, string expected) { SetupRepository(sha); From 2b49df3bec3f669b054ab6d2077cdf3d9da8d66b Mon Sep 17 00:00:00 2001 From: Andreia Gaita Date: Tue, 9 Feb 2016 14:07:13 +0100 Subject: [PATCH 14/24] Move commands to submenu --- .../GitHub.VisualStudio.csproj | 8 +++++ .../GitHub.VisualStudio.imagemanifest | 8 +++++ .../GitHub.VisualStudio.vsct | 36 +++++++++++++------ .../Resources/icons/clippy.xaml | 14 ++++++++ .../Resources/icons/link_external.xaml | 14 ++++++++ 5 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 src/GitHub.VisualStudio/Resources/icons/clippy.xaml create mode 100644 src/GitHub.VisualStudio/Resources/icons/link_external.xaml diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj b/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj index 667bd013f6..342edf8ec2 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj @@ -344,6 +344,14 @@ + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + MSBuild:Compile Designer diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.imagemanifest b/src/GitHub.VisualStudio/GitHub.VisualStudio.imagemanifest index c2b9f7a2a2..f798fa065b 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.imagemanifest +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.imagemanifest @@ -8,6 +8,8 @@ + + @@ -26,5 +28,11 @@ + + + + + + \ No newline at end of file diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct index 759683c4e4..862909c517 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.vsct @@ -38,7 +38,11 @@ - + + + + + @@ -51,6 +55,14 @@ + + + + GitHub + GitHub + + + @@ -121,8 +133,8 @@ - - - - - - -