/// <summary>
        ///     Clone a remote git repo.
        /// </summary>
        /// <param name="repoUri">Repository uri to clone</param>
        /// <param name="commit">Branch, commit, or tag to checkout</param>
        /// <param name="targetDirectory">Target directory to clone to</param>
        /// <param name="gitDirectory">Location for the .git directory, or null for default</param>
        /// <returns></returns>
        protected void Clone(string repoUri, string commit, string targetDirectory, ILogger _logger, string pat, string gitDirectory)
        {
            string dotnetMaestro = "dotnet-maestro";

            LibGit2Sharp.CloneOptions cloneOptions = new LibGit2Sharp.CloneOptions
            {
                Checkout            = false,
                CredentialsProvider = (url, user, cred) =>
                                      new LibGit2Sharp.UsernamePasswordCredentials
                {
                    // The PAT is actually the only thing that matters here, the username
                    // will be ignored.
                    Username = dotnetMaestro,
                    Password = pat
                },
            };
            using (_logger.BeginScope("Cloning {repoUri} to {targetDirectory}", repoUri, targetDirectory))
            {
                try
                {
                    _logger.LogDebug($"Cloning {repoUri} to {targetDirectory}");
                    string repoPath = LibGit2Sharp.Repository.Clone(
                        repoUri,
                        targetDirectory,
                        cloneOptions);

                    LibGit2Sharp.CheckoutOptions checkoutOptions = new LibGit2Sharp.CheckoutOptions
                    {
                        CheckoutModifiers = LibGit2Sharp.CheckoutModifiers.Force,
                    };

                    _logger.LogDebug($"Reading local repo from {repoPath}");
                    using (LibGit2Sharp.Repository localRepo = new LibGit2Sharp.Repository(repoPath))
                    {
                        if (commit == null)
                        {
                            commit = localRepo.Head.Reference.TargetIdentifier;
                            _logger.LogInformation($"Repo {localRepo.Info.WorkingDirectory} has no commit to clone at, assuming it's {commit}");
                        }
                        _logger.LogDebug($"Attempting to checkout {commit} as commit in {localRepo.Info.WorkingDirectory}");
                        LibGit2SharpHelpers.SafeCheckout(localRepo, commit, checkoutOptions, _logger);
                    }
                    // LibGit2Sharp doesn't support a --git-dir equivalent yet (https://github.com/libgit2/libgit2sharp/issues/1467), so we do this manually
                    if (gitDirectory != null)
                    {
                        Directory.Move(repoPath, gitDirectory);
                        File.WriteAllText(repoPath.TrimEnd('\\', '/'), $"gitdir: {gitDirectory}");
                    }
                    using (LibGit2Sharp.Repository localRepo = new LibGit2Sharp.Repository(targetDirectory))
                    {
                        CheckoutSubmodules(localRepo, cloneOptions, gitDirectory, _logger);
                    }
                }
                catch (Exception exc)
                {
                    throw new Exception($"Something went wrong when cloning repo {repoUri} at {commit ?? "<default branch>"} into {targetDirectory}", exc);
                }
            }
        }
Example #2
0
        public void Reset()
        {
            // Undo potential impact from earlier tests
            using (var repository = new LibGit2Sharp.Repository(Module.WorkingDir))
            {
                var options = new LibGit2Sharp.CheckoutOptions();
                repository.Reset(LibGit2Sharp.ResetMode.Hard, (LibGit2Sharp.Commit)repository.Lookup(CommitHash, LibGit2Sharp.ObjectType.Commit), options);
                repository.RemoveUntrackedFiles();
            }

            CommitHelper.SetCommitMessage(Module, commitMessageText: null, amendCommit: false);
        }
Example #3
0
        /// <summary>
        /// Clone the specified target to the working directory
        /// </summary>
        /// <param name="repoUrl">The URL to the repository</param>
        /// <param name="workingDir">The working directory to clone to</param>
        private void CloneTarget(string repoUrl, string workingDir, string branch = "master")
        {
            if (!Directory.Exists(workingDir) || (Directory.GetFiles(workingDir).Length == 0 && Directory.GetDirectories(workingDir).Length == 0))
            {
                Emit.Message("INFO", "Pulling from {0} to {1}", repoUrl, workingDir);
                LibGit2Sharp.Repository.Clone(repoUrl, workingDir);
            }

            using (var repo = new LibGit2Sharp.Repository(workingDir))
            {
                if (!"master".Equals(branch))
                {
                    // Undo the current changes
                    if (Directory.GetFiles(workingDir).Length >= 0)
                    {
                        var options = new LibGit2Sharp.CheckoutOptions {
                            CheckoutModifiers = LibGit2Sharp.CheckoutModifiers.Force
                        };
                        repo.CheckoutPaths(repo.Head.FriendlyName, new[] { "*" }, options);
                    }
                    var localBranch = repo.Branches[branch];
                    if (localBranch == null)
                    {
                        var remoteBranch = repo.Branches[$"origin/{branch}"];
                        if (remoteBranch == null)
                        {
                            throw new InvalidOperationException($"Cannot find branch {branch}");
                        }
                        localBranch = repo.Branches.Add(branch, remoteBranch.Tip);
                        repo.Branches.Update(localBranch, b => b.UpstreamBranch = $"refs/heads/{branch}");
                        repo.Branches.Update(localBranch, b => b.Remote         = $"origin");
                    }
                    var outBranch = LibGit2Sharp.Commands.Checkout(repo, branch);
                    Emit.Message("INFO", "Branch switched{0}", outBranch.RemoteName);
                }
                Emit.Message("INFO", "Pulling from remote");
                LibGit2Sharp.Commands.Pull(repo, new LibGit2Sharp.Signature("SanteSuite Bot", "*****@*****.**", DateTimeOffset.Now), new LibGit2Sharp.PullOptions()
                {
                    FetchOptions = new LibGit2Sharp.FetchOptions()
                });
            }
        }
        /// <summary>
        ///     Checkout the repo to the specified state.
        /// </summary>
        /// <param name="commit">Tag, branch, or commit to checkout.</param>
        public void Checkout(string repoDir, string commit, bool force = false)
        {
            using (_logger.BeginScope("Checking out {commit}", commit ?? "default commit"))
            {
                _logger.LogDebug($"Checking out {commit}", commit ?? "default commit");
                LibGit2Sharp.CheckoutOptions checkoutOptions = new LibGit2Sharp.CheckoutOptions
                {
                    CheckoutModifiers = force ? LibGit2Sharp.CheckoutModifiers.Force : LibGit2Sharp.CheckoutModifiers.None,
                };
                try
                {
                    _logger.LogDebug($"Checking out {commit ?? "default commit"}");

                    _logger.LogDebug($"Reading local repo from {repoDir}");
                    using (LibGit2Sharp.Repository localRepo = new LibGit2Sharp.Repository(repoDir))
                    {
                        if (commit == null)
                        {
                            commit = localRepo.Head.Reference.TargetIdentifier;
                            _logger.LogInformation($"Repo {localRepo.Info.WorkingDirectory} default commit to checkout is {commit}");
                        }
                        try
                        {
                            _logger.LogDebug($"Attempting to check out {commit} in {repoDir}");
                            LibGit2SharpHelpers.SafeCheckout(localRepo, commit, checkoutOptions, _logger);
                            if (force)
                            {
                                CleanRepoAndSubmodules(localRepo, _logger);
                            }
                        }
                        catch (LibGit2Sharp.NotFoundException)
                        {
                            _logger.LogWarning($"Couldn't find commit {commit} in {repoDir} locally.  Attempting fetch.");
                            try
                            {
                                foreach (LibGit2Sharp.Remote r in localRepo.Network.Remotes)
                                {
                                    IEnumerable <string> refSpecs = r.FetchRefSpecs.Select(x => x.Specification);
                                    _logger.LogDebug($"Fetching {string.Join(";", refSpecs)} from {r.Url} in {repoDir}");
                                    try
                                    {
                                        LibGit2Sharp.Commands.Fetch(localRepo, r.Name, refSpecs, new LibGit2Sharp.FetchOptions(), $"Fetching from {r.Url}");
                                    }
                                    catch
                                    {
                                        _logger.LogWarning($"Fetching failed, are you offline or missing a remote?");
                                    }
                                }
                                _logger.LogDebug($"After fetch, attempting to checkout {commit} in {repoDir}");
                                LibGit2SharpHelpers.SafeCheckout(localRepo, commit, checkoutOptions, _logger);

                                if (force)
                                {
                                    CleanRepoAndSubmodules(localRepo, _logger);
                                }
                            }
                            catch   // Most likely network exception, could also be no remotes.  We can't do anything about any error here.
                            {
                                _logger.LogError($"After fetch, still couldn't find commit or treeish {commit} in {repoDir}.  Are you offline or missing a remote?");
                                throw;
                            }
                        }
                    }
                }
                catch (Exception exc)
                {
                    throw new Exception($"Something went wrong when checking out {commit} in {repoDir}", exc);
                }
            }
        }