/// <summary>
/// Download a package from a file repository that matches the given version and name and install it on the local system.
/// </summary>
/// <param name="packageName">Package name</param>
/// <param name="version">Package version</param>
/// <param name="request">An object passed in from the PackageManagement platform that contains APIs that can be used to interact with it </param>
/// <param name="source">Package source</param>
/// <param name="sourceFilePath">File source path pointing to the package to be installed</param>
/// <param name="progressTracker">progress tracker to help keep track of progressid, start and end of the progress</param>
/// <returns>PackageItem object</returns>
internal static PackageItem InstallPackageLocal(
string packageName,
string version,
NuGetRequest request,
PackageSource source,
string sourceFilePath,
ProgressTracker progressTracker
)
{
request.Debug(Messages.DebugInfoCallMethod, "NuGetClient", "InstallPackageLocal");
string tempSourceFilePath = null;
string tempSourceDirectory = null;
string directoryToDeleteWhenFailed = String.Empty;
bool needToDelete = false;
try
{
string destinationFilePath = request.Destination;
request.Verbose(string.Format(CultureInfo.InvariantCulture, "InstallPackageLocal' - name='{0}', version='{1}',destination='{2}'", packageName, version, destinationFilePath));
request.Debug(sourceFilePath);
if (string.IsNullOrWhiteSpace(sourceFilePath))
{
throw new ArgumentNullException(sourceFilePath);
}
if (!File.Exists(sourceFilePath)) {
throw new FileNotFoundException(sourceFilePath);
}
//Create the destination directory if it does not exist
if (!Directory.Exists(destinationFilePath)) {
Directory.CreateDirectory(destinationFilePath);
directoryToDeleteWhenFailed = destinationFilePath;
}
//Make a temp folder in the user appdata temp directory
tempSourceFilePath = FileUtility.GetTempFileFullPath(fileExtension: NuGetConstant.PackageExtension);
//Copy over the source file from the folder repository to the temp folder
File.Copy(sourceFilePath, tempSourceFilePath, true);
request.Progress(progressTracker.ProgressID, progressTracker.StartPercent, string.Format(CultureInfo.CurrentCulture, Messages.Unzipping));
//Unzip it
tempSourceDirectory = PackageUtility.DecompressFile(tempSourceFilePath);
//Get a package directory under the destination path to store the package
string installedFolder = FileUtility.MakePackageDirectoryName(request.ExcludeVersion.Value, destinationFilePath, packageName, version);
// if we did not set the directory before, then the destinationFilePath already exists, so we should not delete it
if (string.IsNullOrWhiteSpace(directoryToDeleteWhenFailed))
{
directoryToDeleteWhenFailed = installedFolder;
}
//File folder format of the Nuget packages looks like the following after installed:
//Jquery.2.0.1
// - JQuery.2.0.1.nupkg
// - contents and other stuff
// unzipping should take most of the time (assuming 70%)
request.Progress(progressTracker.ProgressID, progressTracker.ConvertPercentToProgress(0.7), string.Format(CultureInfo.CurrentCulture, Messages.CopyUnzippedFiles, installedFolder));
//Copy the unzipped files to under the package installed folder
FileUtility.CopyDirectory(tempSourceDirectory, installedFolder, true);
// copying should take another 15%
// copy the nupkg file if it's not in
var nupkgFilePath = Path.Combine(installedFolder, FileUtility.MakePackageFileName(request.ExcludeVersion.Value, packageName, version, NuGetConstant.PackageExtension));
if (!File.Exists(nupkgFilePath))
{
File.Copy(sourceFilePath, nupkgFilePath);
}
request.Progress(progressTracker.ProgressID, progressTracker.ConvertPercentToProgress(0.85), string.Format(CultureInfo.CurrentCulture, Messages.ReadingManifest));
//Read the package manifest and return the package object
string nuspec = Path.Combine(installedFolder, packageName) + NuGetConstant.ManifestExtension;
PackageBase package = PackageUtility.ProcessNuspec(nuspec);
var pkgItem = new PackageItem {
Package = package,
PackageSource = source,
FastPath = request.MakeFastPath(source, package.Id, package.Version),
FullPath = installedFolder
};
// Delete the nuspec file
//Get a package file path
var nuspecFilePath = Path.Combine(installedFolder, packageName + NuGetConstant.ManifestExtension);
if (File.Exists(nuspecFilePath))
{
FileUtility.DeleteFile(nuspecFilePath, false);
}
request.Debug(Messages.DebugInfoReturnCall, "NuGetClient", "InstallPackageLocal");
request.Progress(progressTracker.ProgressID, progressTracker.EndPercent, string.Format(CultureInfo.CurrentCulture, Messages.FinishInstalling, packageName));
return pkgItem;
} catch (Exception ex) {
needToDelete = true;
// the error will be package "packageName" failed to install because : "reason"
ex.Dump(request);
request.WriteError(ErrorCategory.InvalidResult, packageName, Resources.Messages.PackageFailedToInstallReason, packageName, ex.Message);
throw;
} finally {
if (needToDelete && Directory.Exists(directoryToDeleteWhenFailed))
{
FileUtility.DeleteDirectory(directoryToDeleteWhenFailed, true, isThrow: false);
}
FileUtility.DeleteFile(tempSourceFilePath, isThrow:false);
FileUtility.DeleteDirectory(tempSourceDirectory, recursive: true, isThrow: false);
}
}