|
6 | 6 | using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility; |
7 | 7 | using GitHub.Services; |
8 | 8 | using GitHub.VisualStudio; |
| 9 | +using GitHub.Primitives; |
| 10 | +using System.Text; |
| 11 | +using System.Diagnostics; |
9 | 12 |
|
10 | 13 | namespace GitHub.Extensions |
11 | 14 | { |
@@ -35,43 +38,55 @@ public static bool MightContainSolution(this ISimpleRepositoryModel repository) |
35 | 38 |
|
36 | 39 | public static string CurrentSha(this ISimpleRepositoryModel repository) |
37 | 40 | { |
38 | | - if (repository == null) |
39 | | - return null; |
40 | | - |
41 | 41 | var repo = GitService.GitServiceHelper.GetRepo(repository.LocalPath); |
42 | | - |
43 | | - if (repo == null) |
44 | | - return null; |
45 | | - |
46 | | - return !repo.Commits.Any() ? null : repo.Commits.ElementAt(0).Sha; |
| 42 | + return repo.Commits.FirstOrDefault()?.Sha; |
47 | 43 | } |
48 | 44 |
|
49 | | - public static string BrowserUrl(this ISimpleRepositoryModel repository, IActiveDocument activeDocument) |
| 45 | + public static Uri GenerateUrl(this ISimpleRepositoryModel repository, string path = null, |
| 46 | + int startLine = -1, int endLine = -1) |
50 | 47 | { |
51 | | - if (repository == null || activeDocument == null) |
| 48 | + var cloneUrl = repository.CloneUrl; |
| 49 | + if (cloneUrl == null) |
52 | 50 | return null; |
53 | 51 |
|
54 | | - var currentCommitSha = repository.CurrentSha(); |
55 | | - var currentCloneUrl = repository.CloneUrl; |
56 | | - var localPath = repository.LocalPath; |
57 | | - var lineTag = "L" + activeDocument.AnchorLine; |
| 52 | + if (path != null && Path.IsPathRooted(path)) |
| 53 | + { |
| 54 | + // if the path root doesn't match the repository local path, then ignore it |
| 55 | + if (repository.LocalPath == null || |
| 56 | + !path.StartsWith(repository.LocalPath, StringComparison.OrdinalIgnoreCase)) |
| 57 | + { |
| 58 | + Debug.Assert(false, String.Format(CultureInfo.CurrentCulture, "GenerateUrl: path {0} doesn't match repository {1}", path, repository.LocalPath)); |
| 59 | + path = null; |
| 60 | + } |
| 61 | + else |
| 62 | + path = path.Substring(repository.LocalPath.Length + 1); |
| 63 | + } |
| 64 | + |
| 65 | + var commitSha = repository.CurrentSha(); |
| 66 | + var uri = GenerateUrl(cloneUrl.ToRepositoryUrl().AbsoluteUri, commitSha, path, startLine, endLine); |
| 67 | + return new UriString(uri).ToUri(); |
| 68 | + } |
58 | 69 |
|
59 | | - if (string.IsNullOrEmpty(currentCommitSha) || string.IsNullOrEmpty(currentCloneUrl) || |
60 | | - string.IsNullOrEmpty(localPath)) |
61 | | - return null; |
| 70 | + static string GenerateUrl(string basePath, string sha, string path, int startLine = -1, int endLine = -1) |
| 71 | + { |
| 72 | + var sb = new StringBuilder(basePath); |
| 73 | + if (sha == null) |
| 74 | + return sb.ToString(); |
62 | 75 |
|
63 | | - if (activeDocument.AnchorLine != activeDocument.EndLine) |
| 76 | + if (String.IsNullOrEmpty(path)) |
64 | 77 | { |
65 | | - lineTag += "-L" + activeDocument.EndLine; |
| 78 | + sb.AppendFormat("/commit/{0}", sha); |
| 79 | + return sb.ToString(); |
66 | 80 | } |
67 | 81 |
|
68 | | - var outputUri = string.Format(CultureInfo.CurrentCulture, "{0}/blob/{1}{2}#{3}", |
69 | | - currentCloneUrl, |
70 | | - currentCommitSha, |
71 | | - activeDocument.Name.Replace(localPath, "").Replace("\\", "/"), |
72 | | - lineTag); |
73 | | - |
74 | | - return outputUri; |
| 82 | + sb.AppendFormat("/blob/{0}/{1}", sha, path.Replace(@"\", "/")); |
| 83 | + if (startLine < 0) |
| 84 | + return sb.ToString(); |
| 85 | + sb.AppendFormat("#L{0}", startLine); |
| 86 | + if (endLine < 0) |
| 87 | + return sb.ToString(); |
| 88 | + sb.AppendFormat("-L{0}", endLine); |
| 89 | + return sb.ToString(); |
75 | 90 | } |
76 | 91 | } |
77 | 92 | } |
0 commit comments