// rebase current branch and pull from master // @handled @logs public static UpdateStatus ForcedUpdate(string repoPath, GitInstallerCredentials creds) { logger.Debug("Force updating repo \"{0}\"...", repoPath); try { var repo = new Repository(repoPath); var options = new PullOptions(); var fetchOpts = new FetchOptions(); // add username and password to clone options, if provided by user if (creds is GitInstallerCredentials && creds.IsValid()) { fetchOpts.CredentialsProvider = (_url, _usernameFromUrl, _credTypes) => creds.GetCredentials(); } options.FetchOptions = fetchOpts; // before updating, let's first // forced checkout to overwrite possible local changes // Re: https://github.com/eirannejad/pyRevit/issues/229 var checkoutOptions = new CheckoutOptions(); checkoutOptions.CheckoutModifiers = CheckoutModifiers.Force; Commands.Checkout(repo, repo.Head, checkoutOptions); // now let's pull from the tracked remote var res = Commands.Pull(repo, new Signature("GitInstaller", commiterEmail, new DateTimeOffset(DateTime.Now)), options); // process the results and let user know if (res.Status == MergeStatus.FastForward) { logger.Debug("Fast-Forwarded repo \"{0}\"", repoPath); return(UpdateStatus.FastForward); } else if (res.Status == MergeStatus.NonFastForward) { logger.Debug("Non-Fast-Forwarded repo \"{0}\"", repoPath); return(UpdateStatus.NonFastForward); } else if (res.Status == MergeStatus.Conflicts) { logger.Debug("Conflicts on updating clone \"{0}\"", repoPath); return(UpdateStatus.Conflicts); } logger.Debug("Repo \"{0}\" is already up to date.", repoPath); return(UpdateStatus.UpToDate); } catch (Exception ex) { throw new PyRevitException(ex.Message, ex); } }
// public methods // clone a repo to given destination // @handled @logs public static Repository Clone(string repoPath, string branchName, string destPath, GitInstallerCredentials creds, bool checkout = true) { // build options and clone var cloneOps = new CloneOptions() { Checkout = checkout, BranchName = branchName }; // add username and password to clone options, if provided by user if (creds is GitInstallerCredentials && creds.IsValid()) { cloneOps.CredentialsProvider = (_url, _usernameFromUrl, _credTypes) => creds.GetCredentials(); } try { // attempt at cloning the repo logger.Debug("Cloning \"{0}:{1}\" to \"{2}\"", repoPath, branchName, destPath); Repository.Clone(repoPath, destPath, cloneOps); // make repository object and return return(new Repository(destPath)); } catch (Exception ex) { // .Clone method does not return any specific exceptions for authentication failures // so let's translate the cryptic exception messages to something meaninful for the user if (ex.Message.Contains("401") || ex.Message.Contains("too many redirects or authentication replays")) { throw new PyRevitException("Access denied to the repository. Try providing --username and --password"); } // otherwise, wrap and return the original message else { throw new PyRevitException(ex.Message, ex); } } }