/// <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); } } }
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); }
/// <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); } } }