示例#1
0
        /// <inheritdoc/>
        public Uri ToRepositoryUrl(GitHubContext context)
        {
            var builder = new UriBuilder("https", context.Host ?? "github.com");

            builder.Path = $"{context.Owner}/{context.RepositoryName}";
            return(builder.Uri);
        }
示例#2
0
        static void SetSelection(IVsTextView textView, GitHubContext context)
        {
            var line    = context.Line;
            var lineEnd = context.LineEnd ?? line;

            if (line != null)
            {
                ErrorHandler.ThrowOnFailure(textView.GetBuffer(out IVsTextLines buffer));
                buffer.GetLengthOfLine(lineEnd.Value - 1, out int lineEndLength);
                ErrorHandler.ThrowOnFailure(textView.SetSelection(line.Value - 1, 0, lineEnd.Value - 1, lineEndLength));
                ErrorHandler.ThrowOnFailure(textView.CenterLines(line.Value - 1, lineEnd.Value - line.Value + 1));
            }
        }
示例#3
0
        /// <inheritdoc/>
        public bool TryOpenFile(string repositoryDir, GitHubContext context)
        {
            var(commitish, path, isSha) = ResolveBlob(repositoryDir, context);
            if (path == null)
            {
                return(false);
            }

            var fullPath = Path.Combine(repositoryDir, path.Replace('/', '\\'));
            var textView = OpenDocument(fullPath);

            SetSelection(textView, context);
            return(true);
        }
示例#4
0
        /// <inheritdoc/>
        public GitHubContext FindContextFromUrl(string url)
        {
            var uri = new UriString(url);

            if (!uri.IsValidUri)
            {
                return(null);
            }

            if (!uri.IsHypertextTransferProtocol)
            {
                return(null);
            }

            var context = new GitHubContext
            {
                Host           = uri.Host,
                Owner          = uri.Owner,
                RepositoryName = uri.RepositoryName,
                Url            = uri
            };

            var repositoryPrefix = uri.ToRepositoryUrl().ToString() + "/";

            if (!url.StartsWith(repositoryPrefix, StringComparison.OrdinalIgnoreCase))
            {
                return(context);
            }

            var subpath = url.Substring(repositoryPrefix.Length);

            (context.Line, context.LineEnd) = FindLine(subpath);

            context.PullRequest = FindPullRequest(url);

            var match = urlBlobRegex.Match(subpath);

            if (match.Success)
            {
                context.TreeishPath = match.Groups["treeish"].Value;
                context.BlobName    = match.Groups["blobName"].Value;
                context.LinkType    = LinkType.Blob;
                return(context);
            }

            return(context);
        }
示例#5
0
        /// <inheritdoc/>
        public void TryNavigateToContext(string repositoryDir, GitHubContext context)
        {
            if (context?.LinkType == LinkType.Blob)
            {
                var(commitish, path, commitSha) = ResolveBlob(repositoryDir, context);
                if (commitish == null && path == null)
                {
                    var message = string.Format(CultureInfo.CurrentCulture, Resources.CouldntFindCorrespondingFile, context.Url);
                    vsServices.ShowMessageBoxInfo(message);
                    return;
                }

                var hasChanges = HasChangesInWorkingDirectory(repositoryDir, commitish, path);
                if (hasChanges)
                {
                    var message = string.Format(CultureInfo.CurrentCulture, Resources.ChangesInWorkingDirectoryMessage, commitish);
                    vsServices.ShowMessageBoxInfo(message);
                }

                TryOpenFile(repositoryDir, context);
            }
        }
示例#6
0
        /// <inheritdoc/>
        public async Task <bool> TryAnnotateFile(string repositoryDir, string currentBranch, GitHubContext context)
        {
            var(commitish, path, commitSha) = ResolveBlob(repositoryDir, context);
            if (path == null)
            {
                return(false);
            }

            if (!AnnotateFile(repositoryDir, currentBranch, path, commitSha))
            {
                return(false);
            }

            if (context.Line != null)
            {
                await Task.Delay(1000);

                var activeView = FindActiveView();
                SetSelection(activeView, context);
            }

            return(true);
        }
示例#7
0
        /// <inheritdoc/>
        public (string commitish, string path, string commitSha) ResolveBlob(string repositoryDir, GitHubContext context, string remoteName = "origin")
        {
            Guard.ArgumentNotNull(repositoryDir, nameof(repositoryDir));
            Guard.ArgumentNotNull(context, nameof(context));

            using (var repository = gitService.GetRepository(repositoryDir))
            {
                if (context.TreeishPath == null)
                {
                    // Blobs without a TreeishPath aren't currently supported
                    return(null, null, null);
                }

                if (context.BlobName == null)
                {
                    // Not a blob
                    return(null, null, null);
                }

                var objectishPath = $"{context.TreeishPath}/{context.BlobName}";
                var objectish     = ToObjectish(objectishPath);
                var(commitSha, pathSha) = objectish.First();
                if (ObjectId.TryParse(commitSha, out ObjectId objectId) && repository.Lookup(objectId) != null)
                {
                    if (repository.Lookup($"{commitSha}:{pathSha}") != null)
                    {
                        return(commitSha, pathSha, commitSha);
                    }
                }

                foreach (var(commitish, path) in objectish)
                {
                    var resolveRefs = new[] { $"refs/remotes/{remoteName}/{commitish}", $"refs/tags/{commitish}" };
                    foreach (var resolveRef in resolveRefs)
                    {
                        var commit = repository.Lookup(resolveRef);
                        if (commit != null)
                        {
                            var blob = repository.Lookup($"{resolveRef}:{path}");
                            if (blob != null)
                            {
                                return(resolveRef, path, commit.Sha);
                            }

                            // Resolved commitish but not path
                            return(resolveRef, null, commit.Sha);
                        }
                    }
                }

                return(null, null, null);
            }

            IEnumerable <(string commitish, string path)> ToObjectish(string treeishPath)
            {
                var index = 0;

                while ((index = treeishPath.IndexOf('/', index + 1)) != -1)
                {
                    var commitish = treeishPath.Substring(0, index);
                    var path      = treeishPath.Substring(index + 1);
                    yield return(commitish, path);
                }
            }
        }