Skip to content

Implement Progress Bar for Install #552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Nov 30, 2021
84 changes: 59 additions & 25 deletions src/code/InstallHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,15 @@ private void ProcessRepositories(
PSCredential credential)
{
var listOfRepositories = RepositorySettings.Read(repository, out string[] _);
List<string> pckgNamesToInstall = packageNames.ToList();
List<string> pkgNamesToInstall = packageNames.ToList();
var yesToAll = false;
var noToAll = false;

var findHelper = new FindHelper(_cancellationToken, _cmdletPassedIn);
foreach (var repo in listOfRepositories)
{
// If no more packages to install, then return
if (!pckgNamesToInstall.Any()) return;
if (!pkgNamesToInstall.Any()) return;

string repoName = repo.Name;
_cmdletPassedIn.WriteVerbose(string.Format("Attempting to search for packages in '{0}'", repoName));
Expand Down Expand Up @@ -178,7 +178,7 @@ private void ProcessRepositories(

// Finds parent packages and dependencies
IEnumerable<PSResourceInfo> pkgsFromRepoToInstall = findHelper.FindByResourceName(
name: pckgNamesToInstall.ToArray(),
name: pkgNamesToInstall.ToArray(),
type: ResourceType.None,
version: _versionRange != null ? _versionRange.OriginalString : null,
prerelease: _prerelease,
Expand Down Expand Up @@ -218,14 +218,14 @@ private void ProcessRepositories(

List<string> pkgsInstalled = InstallPackage(
pkgsFromRepoToInstall,
repoName,
pkgNamesToInstall,
repo.Url.AbsoluteUri,
credential,
isLocalRepo);

foreach (string name in pkgsInstalled)
{
pckgNamesToInstall.Remove(name);
pkgNamesToInstall.Remove(name);
}
}
}
Expand Down Expand Up @@ -279,15 +279,26 @@ private IEnumerable<PSResourceInfo> FilterByInstalledPkgs(IEnumerable<PSResource
}

private List<string> InstallPackage(
IEnumerable<PSResourceInfo> pkgsToInstall,
string repoName,
IEnumerable<PSResourceInfo> pkgsToInstall, // those found to be required to be installed (includes Dependency packages as well)
List<string> pkgNamesToInstall, // those requested by the user to be installed
string repoUrl,
PSCredential credential,
bool isLocalRepo)
{
List<string> pkgsSuccessfullyInstalled = new List<string>();
foreach (PSResourceInfo pkgInfo in pkgsToInstall)
int totalPkgs = pkgsToInstall.Count();

// counters for tracking dependent package and current package out of total
int totalPkgsCount = 0;
int dependentPkgCount = 1;
// by default this is 1, because if a parent package was already installed and only the dependent package
// needs to be installed we don't want a default value of 0 which throws a division error.
// if parent package isn't already installed we'll set this value properly in the below if condition anyways
int currentPkgNumOfDependentPkgs = 1;

foreach (PSResourceInfo pkg in pkgsToInstall)
{
totalPkgsCount++;
var tempInstallPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
try
{
Expand All @@ -300,24 +311,47 @@ private List<string> InstallPackage(
// TODO: are there Linux accommodations we need to consider here?
dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly;

_cmdletPassedIn.WriteVerbose(string.Format("Begin installing package: '{0}'", pkgInfo.Name));
_cmdletPassedIn.WriteVerbose(string.Format("Begin installing package: '{0}'", pkg.Name));

int activityId = 0;
string activity = "";
string statusDescription = "";

if (pkgNamesToInstall.ToList().Contains(pkg.Name, StringComparer.InvariantCultureIgnoreCase))
{
// Installing parent package (one whose name was passed in to install)
activityId = 0;
activity = string.Format("Installing {0}...", pkg.Name);
statusDescription = string.Format("{0}% Complete:", Math.Round(((double) totalPkgsCount/totalPkgs) * 100), 2);
currentPkgNumOfDependentPkgs = pkg.Dependencies.Count();
dependentPkgCount = 1;
}
else
{
// Installing dependent package
activityId = 1;
activity = string.Format("Installing dependent package {0}...", pkg.Name);
statusDescription = string.Format("{0}% Complete:", Math.Round(((double) dependentPkgCount/currentPkgNumOfDependentPkgs) * 100), 2);
dependentPkgCount++;
}

// TODO: add progress bar here

var progressRecord = new ProgressRecord(activityId, activity, statusDescription);
_cmdletPassedIn.WriteProgress(progressRecord);

// Create PackageIdentity in order to download
string createFullVersion = pkgInfo.Version.ToString();
if (pkgInfo.IsPrerelease)
string createFullVersion = pkg.Version.ToString();
if (pkg.IsPrerelease)
{
createFullVersion = pkgInfo.Version.ToString() + "-" + pkgInfo.PrereleaseLabel;
createFullVersion = pkg.Version.ToString() + "-" + pkg.PrereleaseLabel;
}

if (!NuGetVersion.TryParse(createFullVersion, out NuGetVersion pkgVersion))
{
_cmdletPassedIn.WriteVerbose(string.Format("Error parsing package '{0}' version '{1}' into a NuGetVersion",
pkgInfo.Name, pkgInfo.Version.ToString()));
pkg.Name, pkg.Version.ToString()));
continue;
}
var pkgIdentity = new PackageIdentity(pkgInfo.Name, pkgVersion);
var pkgIdentity = new PackageIdentity(pkg.Name, pkgVersion);
var cacheContext = new SourceCacheContext();

if (isLocalRepo)
Expand Down Expand Up @@ -412,8 +446,8 @@ private List<string> InstallPackage(
string tempDirNameVersion = isLocalRepo ? tempInstallPath : Path.Combine(tempInstallPath, pkgIdentity.Id.ToLower(), newVersion);
var version4digitNoPrerelease = pkgIdentity.Version.Version.ToString();
string moduleManifestVersion = string.Empty;
var scriptPath = Path.Combine(tempDirNameVersion, pkgInfo.Name + ".ps1");
var modulePath = Path.Combine(tempDirNameVersion, pkgInfo.Name + ".psd1");
var scriptPath = Path.Combine(tempDirNameVersion, pkg.Name + ".ps1");
var modulePath = Path.Combine(tempDirNameVersion, pkg.Name + ".psd1");
// Check if the package is a module or a script
var isModule = File.Exists(modulePath);

Expand All @@ -439,13 +473,13 @@ private List<string> InstallPackage(
moduleManifestVersion = parsedMetadataHashtable["ModuleVersion"] as string;

// Accept License verification
if (!_savePkg && !CallAcceptLicense(pkgInfo, moduleManifest, tempInstallPath, newVersion))
if (!_savePkg && !CallAcceptLicense(pkg, moduleManifest, tempInstallPath, newVersion))
{
continue;
}

// If NoClobber is specified, ensure command clobbering does not happen
if (_noClobber && !DetectClobber(pkgInfo.Name, parsedMetadataHashtable))
if (_noClobber && !DetectClobber(pkg.Name, parsedMetadataHashtable))
{
continue;
}
Expand All @@ -471,11 +505,11 @@ private List<string> InstallPackage(

if (_includeXML)
{
CreateMetadataXMLFile(tempDirNameVersion, installPath, pkgInfo, isModule);
CreateMetadataXMLFile(tempDirNameVersion, installPath, pkg, isModule);
}

MoveFilesIntoInstallPath(
pkgInfo,
pkg,
isModule,
isLocalRepo,
tempDirNameVersion,
Expand All @@ -485,15 +519,15 @@ private List<string> InstallPackage(
moduleManifestVersion,
scriptPath);

_cmdletPassedIn.WriteVerbose(String.Format("Successfully installed package '{0}' to location '{1}'", pkgInfo.Name, installPath));
pkgsSuccessfullyInstalled.Add(pkgInfo.Name);
_cmdletPassedIn.WriteVerbose(String.Format("Successfully installed package '{0}' to location '{1}'", pkg.Name, installPath));
pkgsSuccessfullyInstalled.Add(pkg.Name);
}
catch (Exception e)
{
_cmdletPassedIn.WriteError(
new ErrorRecord(
new PSInvalidOperationException(
message: $"Unable to successfully install package '{pkgInfo.Name}': '{e.Message}'",
message: $"Unable to successfully install package '{pkg.Name}': '{e.Message}'",
innerException: e),
"InstallPackageFailed",
ErrorCategory.InvalidOperation,
Expand Down