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

Commit 2e2b5e0

Browse files
committed
Move useful functionality into SimpleRepositoryModel
1 parent 499cba8 commit 2e2b5e0

File tree

11 files changed

+95
-65
lines changed

11 files changed

+95
-65
lines changed

src/GitHub.App/SampleData/SampleViewModels.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,11 @@ public void SetIcon(bool isPrivate, bool isFork)
409409
{
410410
}
411411

412+
public UriString GenerateUrl(string path = null, int startLine = -1, int endLine = -1)
413+
{
414+
return null;
415+
}
416+
412417
public string Name { get; set; }
413418
public UriString CloneUrl { get; set; }
414419
public string LocalPath { get; set; }
Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
using System;
2-
using System.Globalization;
32
using System.Linq;
43
using System.IO;
54
using GitHub.Models;
65
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
76
using GitHub.Services;
8-
using GitHub.Primitives;
9-
using System.Text;
10-
using System.Diagnostics;
117

128
namespace GitHub.Extensions
139
{
@@ -34,58 +30,5 @@ public static bool MightContainSolution(this ISimpleRepositoryModel repository)
3430
.Any(x => ((x.Attributes.HasFlag(FileAttributes.Directory) || x.Attributes.HasFlag(FileAttributes.Normal)) &&
3531
!x.Name.StartsWith(".", StringComparison.Ordinal) && !x.Name.StartsWith("readme", StringComparison.OrdinalIgnoreCase)));
3632
}
37-
38-
public static string CurrentSha(this ISimpleRepositoryModel repository)
39-
{
40-
var repo = GitService.GitServiceHelper.GetRepo(repository.LocalPath);
41-
return repo.Commits.FirstOrDefault()?.Sha;
42-
}
43-
44-
public static Uri GenerateUrl(this ISimpleRepositoryModel repository, string path = null,
45-
int startLine = -1, int endLine = -1)
46-
{
47-
var cloneUrl = repository.CloneUrl;
48-
if (cloneUrl == null)
49-
return null;
50-
51-
if (path != null && Path.IsPathRooted(path))
52-
{
53-
// if the path root doesn't match the repository local path, then ignore it
54-
if (repository.LocalPath == null ||
55-
!path.StartsWith(repository.LocalPath, StringComparison.OrdinalIgnoreCase))
56-
{
57-
Debug.Assert(false, String.Format(CultureInfo.CurrentCulture, "GenerateUrl: path {0} doesn't match repository {1}", path, repository.LocalPath));
58-
path = null;
59-
}
60-
else
61-
path = path.Substring(repository.LocalPath.Length + 1);
62-
}
63-
64-
var commitSha = repository.CurrentSha();
65-
var uri = GenerateUrl(cloneUrl.ToRepositoryUrl().AbsoluteUri, commitSha, path, startLine, endLine);
66-
return new UriString(uri).ToUri();
67-
}
68-
69-
static string GenerateUrl(string basePath, string sha, string path, int startLine = -1, int endLine = -1)
70-
{
71-
var sb = new StringBuilder(basePath);
72-
if (sha == null)
73-
return sb.ToString();
74-
75-
if (String.IsNullOrEmpty(path))
76-
{
77-
sb.AppendFormat("/commit/{0}", sha);
78-
return sb.ToString();
79-
}
80-
81-
sb.AppendFormat("/blob/{0}/{1}", sha, path.Replace(@"\", "/"));
82-
if (startLine < 0)
83-
return sb.ToString();
84-
sb.AppendFormat("#L{0}", startLine);
85-
if (endLine < 0)
86-
return sb.ToString();
87-
sb.AppendFormat("-L{0}", endLine);
88-
return sb.ToString();
89-
}
9033
}
9134
}

src/GitHub.Exports/Models/ISimpleRepositoryModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ public interface ISimpleRepositoryModel : INotifyPropertyChanged
1818
/// Updates the url information based on the local path
1919
/// </summary>
2020
void Refresh();
21+
UriString GenerateUrl(string path = null, int startLine = -1, int endLine = -1);
2122
}
2223
}

src/GitHub.Exports/Models/SimpleRepositoryModel.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Diagnostics;
33
using System.Globalization;
44
using System.IO;
5+
using System.Linq;
56
using GitHub.Primitives;
67
using GitHub.UI;
78
using GitHub.VisualStudio.Helpers;
@@ -53,13 +54,73 @@ public void Refresh()
5354
CloneUrl = uri;
5455
}
5556

57+
/// <summary>
58+
/// Generates a http(s) url to the repository in the remote server, optionally
59+
/// pointing to a specific file and specific line range in it.
60+
/// </summary>
61+
/// <param name="path">The file to generate an url to. Optional.</param>
62+
/// <param name="startLine">A specific line, or (if specifying the <paramref name="endLine"/> as well) the start of a range</param>
63+
/// <param name="endLine">The end of a line range on the specified file.</param>
64+
/// <returns>An UriString with the generated url, or null if the repository has no remote server configured or if it can't be found locally</returns>
65+
public UriString GenerateUrl(string path = null, int startLine = -1, int endLine = -1)
66+
{
67+
var sha = HeadSha;
68+
if (CloneUrl == null || String.IsNullOrEmpty(sha))
69+
return null;
70+
71+
if (path != null && Path.IsPathRooted(path))
72+
{
73+
// if the path root doesn't match the repository local path, then ignore it
74+
if (LocalPath == null ||
75+
!path.StartsWith(LocalPath, StringComparison.OrdinalIgnoreCase))
76+
{
77+
Debug.Assert(false, String.Format(CultureInfo.CurrentCulture, "GenerateUrl: path {0} doesn't match repository {1}", path, LocalPath));
78+
path = null;
79+
}
80+
else
81+
path = path.Substring(LocalPath.Length + 1);
82+
}
83+
84+
return new UriString(GenerateUrl(cloneUrl.ToRepositoryUrl().AbsoluteUri, sha, path, startLine, endLine));
85+
}
86+
87+
const string CommitFormat = "{0}/commit/{1}";
88+
const string BlobFormat = "{0}/blob/{1}/{2}";
89+
const string StartLineFormat = "{0}#L{1}";
90+
const string EndLineFormat = "{0}-L{1}";
91+
static string GenerateUrl(string basePath, string sha, string path, int startLine = -1, int endLine = -1)
92+
{
93+
if (sha == null)
94+
return basePath;
95+
96+
if (String.IsNullOrEmpty(path))
97+
return String.Format(CultureInfo.InvariantCulture, CommitFormat, basePath, sha);
98+
99+
var ret = String.Format(CultureInfo.InvariantCulture, BlobFormat, basePath, sha, path.Replace(@"\", "/"));
100+
if (startLine < 0)
101+
return ret;
102+
ret = String.Format(CultureInfo.InvariantCulture, StartLineFormat, ret, startLine);
103+
if (endLine < 0)
104+
return ret;
105+
return String.Format(CultureInfo.InvariantCulture, EndLineFormat, ret, endLine);
106+
}
107+
56108
public string Name { get; }
57109
UriString cloneUrl;
58110
public UriString CloneUrl { get { return cloneUrl; } set { cloneUrl = value; this.RaisePropertyChange(); } }
59111
public string LocalPath { get; }
60112
Octicon icon;
61113
public Octicon Icon { get { return icon; } set { icon = value; this.RaisePropertyChange(); } }
62114

115+
public string HeadSha
116+
{
117+
get
118+
{
119+
var repo = GitService.GitServiceHelper.GetRepo(LocalPath);
120+
return repo?.Commits.FirstOrDefault()?.Sha ?? String.Empty;
121+
}
122+
}
123+
63124
/// <summary>
64125
/// Note: We don't consider CloneUrl a part of the hash code because it can change during the lifetime
65126
/// of a repository. Equals takes care of any hash collisions because of this

src/GitHub.VisualStudio/Menus/CopyLink.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,17 @@ public void Activate()
2828
var link = GenerateLink();
2929
if (link == null)
3030
return;
31-
Clipboard.SetText(link.AbsoluteUri);
32-
var ns = ServiceProvider.GetExportedValue<IStatusBarNotificationService>();
33-
ns?.ShowMessage(Resources.LinkCopiedToClipboardMessage);
31+
try
32+
{
33+
Clipboard.SetText(link);
34+
var ns = ServiceProvider.GetExportedValue<IStatusBarNotificationService>();
35+
ns?.ShowMessage(Resources.LinkCopiedToClipboardMessage);
36+
}
37+
catch
38+
{
39+
var ns = ServiceProvider.GetExportedValue<IStatusBarNotificationService>();
40+
ns?.ShowMessage(Resources.Error_FailedToCopyToClipboard);
41+
}
3442
}
3543

3644
public bool CanShow()

src/GitHub.VisualStudio/Menus/LinkMenuBase.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using GitHub.Extensions;
2+
using GitHub.Primitives;
23
using System;
34

45
namespace GitHub.VisualStudio.Menus
@@ -10,7 +11,7 @@ public LinkMenuBase(IServiceProvider serviceProvider)
1011
{
1112
}
1213

13-
protected Uri GenerateLink()
14+
protected UriString GenerateLink()
1415
{
1516
var repo = ActiveRepo;
1617
var activeDocument = ServiceProvider.GetExportedValue<IActiveDocumentSnapshot>();

src/GitHub.VisualStudio/Menus/OpenLink.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public void Activate()
2828
if (link == null)
2929
return;
3030
var browser = ServiceProvider.GetExportedValue<IVisualStudioBrowser>();
31-
browser?.OpenUrl(link);
31+
browser?.OpenUrl(link.ToUri());
3232
}
3333

3434
public bool CanShow()

src/GitHub.VisualStudio/Resources.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/GitHub.VisualStudio/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,4 +285,7 @@
285285
<data name="LinkCopiedToClipboardMessage" xml:space="preserve">
286286
<value>Link copied to clipboard</value>
287287
</data>
288+
<data name="Error_FailedToCopyToClipboard" xml:space="preserve">
289+
<value>Could not copy to the clipboard. Please try again.</value>
290+
</data>
288291
</root>

src/UnitTests/GitHub.Extensions/SimpleRepositoryModelExtensionTests.cs renamed to src/UnitTests/GitHub.Exports/SimpleRepositoryModelTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using GitHub.Extensions;
32
using GitHub.Models;
43
using GitHub.VisualStudio;
54
using LibGit2Sharp;
@@ -9,7 +8,7 @@
98
using GitHub.Primitives;
109

1110
[Collection("PackageServiceProvider global data tests")]
12-
public class SimpleRepositoryModelExtensionTests : TempFileBaseClass
11+
public class SimpleRepositoryModelTests : TempFileBaseClass
1312
{
1413
void SetupRepository(string sha)
1514
{

0 commit comments

Comments
 (0)