Skip to content

Commit

Permalink
(chocolateyGH-121) backup changed files
Browse files Browse the repository at this point in the history
When files have changed in a package, back those files up prior to
upgrade.
  • Loading branch information
ferventcoder committed May 15, 2015
1 parent 40b4437 commit 9a68ebd
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,15 @@ public void should_not_call_get_files()
}

[Fact]
public void should_return_null()
public void should_return_a_non_null_object()
{
result.ShouldBeNull();
result.ShouldNotBeNull();
}

[Fact]
public void should_return_empty_package_files()
{
result.Files.ShouldBeEmpty();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace chocolatey.tests.infrastructure.app.services
using System.Linq;
using Moq;
using NuGet;
using chocolatey.infrastructure.app.configuration;
using chocolatey.infrastructure.app.domain;
using chocolatey.infrastructure.app.services;
using IFileSystem = chocolatey.infrastructure.filesystem.IFileSystem;
Expand Down Expand Up @@ -48,6 +49,70 @@ public override void Context()
}
}

public class when_NugetService_backs_up_changed_files : NugetServiceSpecsBase
{
private Action because;
private ChocolateyPackageInformation packageInfo;
private const string filePath = "c:\\tests";
private PackageFiles packageFiles;
private readonly ChocolateyConfiguration config = new ChocolateyConfiguration();

public override void Context()
{
base.Context();
package.Setup(x => x.Id).Returns("bob");
packageInfo = new ChocolateyPackageInformation(package.Object);
packageInfo.FilesSnapshot = new PackageFiles();
packageFiles = new PackageFiles();
fileSystem.Setup(x => x.directory_exists(It.IsAny<string>())).Returns(true);
}

public override void Because()
{
because = () => service.backup_changed_files(filePath, config, packageInfo);
}

[Fact]
public void should_ignore_an_unchanged_file()
{
Context();

var packageFile = new PackageFile { Path = filePath, Checksum = "1234" };
packageFiles.Files.Add(packageFile);
packageInfo.FilesSnapshot = packageFiles;

var fileSystemFiles = new List<string>() { filePath };
fileSystem.Setup(x => x.get_files(It.IsAny<string>(), It.IsAny<string>(), SearchOption.AllDirectories)).Returns(fileSystemFiles);
filesService.Setup(x => x.capture_package_files(It.IsAny<string>(),config)).Returns(packageFiles);

because();

fileSystem.Verify(x => x.copy_file(It.IsAny<string>(),It.IsAny<string>(),It.IsAny<bool>()),Times.Never);
}

[Fact]
public void should_backup_a_changed_file()
{
Context();

var packageFile = new PackageFile { Path = filePath, Checksum = "1234" };
packageFiles.Files.Add(packageFile);
packageInfo.FilesSnapshot = packageFiles;

var packageFileWithUpdatedChecksum = new PackageFile { Path = filePath, Checksum = "4321" };

var fileSystemFiles = new List<string>() { filePath };
fileSystem.Setup(x => x.get_files(It.IsAny<string>(), It.IsAny<string>(), SearchOption.AllDirectories)).Returns(fileSystemFiles);
var updatedPackageFiles = new PackageFiles();
updatedPackageFiles.Files = new List<PackageFile>{packageFileWithUpdatedChecksum};
filesService.Setup(x => x.capture_package_files(It.IsAny<string>(), config)).Returns(updatedPackageFiles);

because();

fileSystem.Verify(x => x.copy_file(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()), Times.Once);
}
}

public class when_NugetService_removes_installation_files_on_uninstall : NugetServiceSpecsBase
{
private Action because;
Expand All @@ -63,7 +128,6 @@ public override void Context()
packageInfo.FilesSnapshot = new PackageFiles();
packageFiles = new List<PackageFile>();
fileSystem.Setup(x => x.directory_exists(It.IsAny<string>())).Returns(true);

}

public override void Because()
Expand All @@ -80,11 +144,9 @@ public void should_do_nothing_if_the_directory_no_longer_exists()

var packageFile = new PackageFile { Path = filePath, Checksum = "1234" };
packageFiles.Add(packageFile);

packageInfo.FilesSnapshot.Files = packageFiles.ToList();

var fileSystemFiles = new List<string>() { filePath };

fileSystem.Setup(x => x.get_files(It.IsAny<string>(), It.IsAny<string>(), SearchOption.AllDirectories)).Returns(fileSystemFiles);
filesService.Setup(x => x.get_package_file(It.IsAny<string>())).Returns(packageFile);

Expand All @@ -101,14 +163,10 @@ public void should_remove_an_unchanged_file()

var packageFile = new PackageFile { Path = filePath, Checksum = "1234" };
packageFiles.Add(packageFile);

packageInfo.FilesSnapshot.Files = packageFiles.ToList();

var fileSystemFiles = new List<string>() { filePath };


fileSystem.Setup(x => x.get_files(It.IsAny<string>(), It.IsAny<string>(), SearchOption.AllDirectories)).Returns(fileSystemFiles);

filesService.Setup(x => x.get_package_file(It.IsAny<string>())).Returns(packageFile);

because();
Expand All @@ -124,14 +182,10 @@ public void should_not_delete_a_changed_file()
var packageFile = new PackageFile { Path = filePath, Checksum = "1234" };
var packageFileWithUpdatedChecksum = new PackageFile { Path = filePath, Checksum = "4321" };
packageFiles.Add(packageFile);

packageInfo.FilesSnapshot.Files = packageFiles.ToList();

var fileSystemFiles = new List<string>() { filePath };


fileSystem.Setup(x => x.get_files(It.IsAny<string>(), It.IsAny<string>(), SearchOption.AllDirectories)).Returns(fileSystemFiles);

filesService.Setup(x => x.get_package_file(It.IsAny<string>())).Returns(packageFileWithUpdatedChecksum);

because();
Expand Down
10 changes: 5 additions & 5 deletions src/chocolatey/infrastructure.app/services/FilesService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void save_to_file(PackageFiles snapshot, string filePath)

public PackageFiles capture_package_files(PackageResult packageResult, ChocolateyConfiguration config)
{
if (packageResult == null) return null;
if (packageResult == null) return new PackageFiles();

var installDirectory = packageResult.InstallLocation;
if (installDirectory.is_equal_to(ApplicationParameters.InstallLocation) || installDirectory.is_equal_to(ApplicationParameters.PackagesLocation))
Expand All @@ -72,15 +72,15 @@ public PackageFiles capture_package_files(PackageResult packageResult, Chocolate

public PackageFiles capture_package_files(string directory, ChocolateyConfiguration config)
{
var packageFiles = new PackageFiles();

if (directory.is_equal_to(ApplicationParameters.InstallLocation) || directory.is_equal_to(ApplicationParameters.PackagesLocation))
{
var logMessage = "Install location is not specific enough, cannot capture files:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, directory);
this.Log().Error(logMessage);
return null;
return packageFiles;
}

var packageFiles = new PackageFiles();


this.Log().Debug(() => "Capturing package files in '{0}'".format_with(directory));
//gather all files in the folder
var files = _fileSystem.get_files(directory, pattern: "*.*", option: SearchOption.AllDirectories);
Expand Down
49 changes: 37 additions & 12 deletions src/chocolatey/infrastructure.app/services/NugetService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public ConcurrentDictionary<string, PackageResult> install_run(ChocolateyConfigu
var forcedResult = packageInstalls.GetOrAdd(packageName, new PackageResult(installedPackage, _fileSystem.combine_paths(ApplicationParameters.PackagesLocation, installedPackage.Id)));
forcedResult.Messages.Add(new ResultMessage(ResultType.Note, "Backing up and removing old version"));

backup_existing_version(config, installedPackage);
backup_existing_version(config, installedPackage, _packageInfoService.get_package_information(installedPackage));

try
{
Expand Down Expand Up @@ -580,7 +580,7 @@ packages as of version 1.0.0. That is what the install command is for.
version == null ? null : version.ToString()))
{
rename_legacy_package_version(config, installedPackage, pkgInfo);
backup_existing_version(config, installedPackage);
backup_existing_version(config, installedPackage, pkgInfo);
if (config.Force && (installedPackage.Version == availablePackage.Version))
{
FaultTolerance.try_catch_with_logging_exception(
Expand Down Expand Up @@ -627,7 +627,7 @@ public void rename_legacy_package_version(ChocolateyConfiguration config, IPacka
}
}

public void backup_existing_version(ChocolateyConfiguration config, IPackage installedPackage)
public void backup_existing_version(ChocolateyConfiguration config, IPackage installedPackage, ChocolateyPackageInformation packageInfo)
{
_fileSystem.create_directory_if_not_exists(ApplicationParameters.PackageBackupLocation);

Expand Down Expand Up @@ -672,7 +672,7 @@ public void backup_existing_version(ChocolateyConfiguration config, IPackage ins
}
}

backup_configuration_files(pkgInstallPath, installedPackage.Version.to_string());
backup_changed_files(pkgInstallPath, config, packageInfo);

if (errored)
{
Expand All @@ -685,16 +685,41 @@ process locking the folder or files. Please make sure nothing is
}
}

private void backup_configuration_files(string packageInstallPath, string version)
public void backup_changed_files(string packageInstallPath, ChocolateyConfiguration config, ChocolateyPackageInformation packageInfo)
{
var configFiles = _fileSystem.get_files(packageInstallPath, ApplicationParameters.ConfigFileExtensions, SearchOption.AllDirectories);
foreach (var file in configFiles.or_empty_list_if_null())
if (packageInfo == null || packageInfo.Package == null) return;

var version = packageInfo.Package.Version.to_string();

if (packageInfo.FilesSnapshot == null || packageInfo.FilesSnapshot.Files.Count == 0)
{
var backupName = "{0}.{1}".format_with(_fileSystem.get_file_name(file), version);
var configFiles = _fileSystem.get_files(packageInstallPath, ApplicationParameters.ConfigFileExtensions, SearchOption.AllDirectories);
foreach (var file in configFiles.or_empty_list_if_null())
{
var backupName = "{0}.{1}".format_with(_fileSystem.get_file_name(file), version);

FaultTolerance.try_catch_with_logging_exception(
() => _fileSystem.copy_file(file, _fileSystem.combine_paths(_fileSystem.get_directory_name(file), backupName), overwriteExisting: true),
"Error backing up configuration file");
FaultTolerance.try_catch_with_logging_exception(
() => _fileSystem.copy_file(file, _fileSystem.combine_paths(_fileSystem.get_directory_name(file), backupName), overwriteExisting: true),
"Error backing up configuration file");
}
}
else
{
var currentFiles = _filesService.capture_package_files(packageInstallPath, config);
foreach (var currentFile in currentFiles.Files.or_empty_list_if_null())
{
var installedFile = packageInfo.FilesSnapshot.Files.FirstOrDefault(x => x.Path.is_equal_to(currentFile.Path));
if (installedFile != null)
{
if (!currentFile.Checksum.is_equal_to(installedFile.Checksum))
{
var backupName = "{0}.{1}".format_with(_fileSystem.get_file_name(currentFile.Path), version);
FaultTolerance.try_catch_with_logging_exception(
() => _fileSystem.copy_file(currentFile.Path, _fileSystem.combine_paths(_fileSystem.get_directory_name(currentFile.Path), backupName), overwriteExisting: true),
"Error backing up changed file");
}
}
}
}
}

Expand Down Expand Up @@ -862,7 +887,7 @@ public ConcurrentDictionary<string, PackageResult> uninstall_run(ChocolateyConfi
version == null ? null : version.ToString()))
{
rename_legacy_package_version(config, packageVersion, pkgInfo);
backup_existing_version(config, packageVersion);
backup_existing_version(config, packageVersion, pkgInfo);
packageManager.UninstallPackage(packageVersion, forceRemove: config.Force, removeDependencies: config.ForceDependencies);
ensure_nupkg_is_removed(packageVersion, pkgInfo);
remove_installation_files(packageVersion, pkgInfo);
Expand Down

0 comments on commit 9a68ebd

Please sign in to comment.