// installs extension from repo url // @handled @logs public static void InstallExtension(string extensionName, PyRevitExtensionTypes extensionType, string repoPath, string destPath = null, string branchName = null, string username = null, string password = null) { // make sure extension is not installed already try { var existExt = GetInstalledExtension(extensionName); if (existExt != null) { throw new PyRevitException(string.Format("Extension \"{0}\" is already installed under \"{1}\"", existExt.Name, existExt.InstallPath)); } } catch { // extension is not installed so everything is fine } // determine repo folder name // Name.extension for UI Extensions // Name.lib for Library Extensions string extDestDirName = PyRevitExtension.MakeConfigName(extensionName, extensionType); // determine destination destPath = destPath ?? PyRevitConsts.DefaultExtensionsPath; string finalExtRepoPath = Path.Combine(destPath, extDestDirName).NormalizeAsPath(); // determine branch name branchName = branchName ?? PyRevitConsts.DefaultExtensionRepoDefaultBranch; logger.Debug("Extension branch name determined as \"{0}\"", branchName); logger.Debug("Installing extension into \"{0}\"", finalExtRepoPath); // start the clone process var repo = GitInstaller.Clone(repoPath, branchName, finalExtRepoPath, username, password); // Check installation if (repo != null) { // make sure to delete the repo if error occured after cloning var clonedPath = repo.Info.WorkingDirectory; if (GitInstaller.IsValidRepo(clonedPath)) { logger.Debug("Clone successful \"{0}\"", clonedPath); RegisterExtensionSearchPath(destPath.NormalizeAsPath()); } else { logger.Debug("Invalid repo after cloning. Deleting clone \"{0}\"", repoPath); try { CommonUtils.DeleteDirectory(repoPath); } catch (Exception delEx) { logger.Error(string.Format("Error post-install cleanup on \"{0}\" | {1}", repoPath, delEx.Message)); } } } else { throw new PyRevitException(string.Format("Error installing extension. Null repo error on \"{0}\"", repoPath)); } }