Skip to content

Commit

Permalink
Merge branch 'ListCommand' into stable
Browse files Browse the repository at this point in the history
* ListCommand:
  (GH-223) Fix handling of LocalOnly for API
  (GH-132) Use Config.QuietOutput for List commands
  (GH-132) PackageService / ListCommand List for API
  • Loading branch information
ferventcoder committed Jun 29, 2015
2 parents 73ba21f + 9df6fd0 commit 3c12763
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 71 deletions.
Expand Up @@ -233,7 +233,7 @@ public override void Because()
[Fact]
public void should_call_service_list_run()
{
packageService.Verify(c => c.list_run(configuration, true), Times.Once);
packageService.Verify(c => c.list_run(configuration), Times.Once);
}
}
}
Expand Down
Expand Up @@ -342,7 +342,7 @@ public override void Context()
new PackageResult(package.Object, null),
new PackageResult(pinnedPackage.Object, null)
};
nugetService.Setup(n => n.list_run(It.IsAny<ChocolateyConfiguration>(), true)).Returns(packageResults);
nugetService.Setup(n => n.list_run(It.IsAny<ChocolateyConfiguration>())).Returns(packageResults);
configuration.PinCommand.Command = PinCommandType.list;
}

Expand Down Expand Up @@ -414,7 +414,7 @@ public void should_call_nuget_service_list_run_when_command_is_list()
configuration.PinCommand.Command = PinCommandType.list;
command.run(configuration);

nugetService.Verify(n => n.list_run(It.IsAny<ChocolateyConfiguration>(), true), Times.Once);
nugetService.Verify(n => n.list_run(It.IsAny<ChocolateyConfiguration>()), Times.Once);
}

[Pending("NuGet is killing me with extension methods. Need to find proper item to mock out to return the package object.")]
Expand Down
1 change: 1 addition & 0 deletions src/chocolatey/chocolatey.csproj
Expand Up @@ -170,6 +170,7 @@
<Compile Include="infrastructure\commandline\ExitScenarioHandler.cs" />
<Compile Include="infrastructure\commandline\InteractivePrompt.cs" />
<Compile Include="infrastructure\commands\ICommandExecutor.cs" />
<Compile Include="infrastructure\commands\IListCommand.cs" />
<Compile Include="infrastructure\commands\PowershellExecutor.cs" />
<Compile Include="infrastructure\cryptography\CryptoHashProviderType.cs" />
<Compile Include="infrastructure\adapters\HashAlgorithm.cs" />
Expand Down
Expand Up @@ -16,17 +16,19 @@
namespace chocolatey.infrastructure.app.commands
{
using System.Collections.Generic;
using System.Linq;
using attributes;
using commandline;
using configuration;
using domain;
using infrastructure.commands;
using logging;
using results;
using services;

[CommandFor(CommandNameType.list)]
[CommandFor(CommandNameType.search)]
public sealed class ChocolateyListCommand : ICommand
public sealed class ChocolateyListCommand : IListCommand<PackageResult>
{
private readonly IChocolateyPackageService _packageService;

Expand Down Expand Up @@ -66,12 +68,6 @@ public void configure_argument_parser(OptionSet optionSet, ChocolateyConfigurati
public void handle_additional_argument_parsing(IList<string> unparsedArguments, ChocolateyConfiguration configuration)
{
configuration.Input = string.Join(" ", unparsedArguments);

if (configuration.ListCommand.LocalOnly)
{
configuration.Sources = ApplicationParameters.PackagesLocation;
configuration.Prerelease = true;
}
}

public void handle_validation(ChocolateyConfiguration configuration)
Expand Down Expand Up @@ -114,7 +110,15 @@ public void noop(ChocolateyConfiguration configuration)

public void run(ChocolateyConfiguration configuration)
{
_packageService.list_run(configuration, logResults: true);
// you must leave the .ToList() here or else the method won't be evaluated!
_packageService.list_run(configuration).ToList();
}

public IEnumerable<PackageResult> list(ChocolateyConfiguration configuration)
{
configuration.QuietOutput = true;
// here it's up to the caller to enumerate the results
return _packageService.list_run(configuration);
}

public bool may_require_admin_access()
Expand Down
Expand Up @@ -139,7 +139,7 @@ public void run(ChocolateyConfiguration configuration)

public void list_pins(IPackageManager packageManager, ChocolateyConfiguration config)
{
foreach (var pkg in _nugetService.list_run(config, logResults: true))
foreach (var pkg in _nugetService.list_run(config))
{
var pkgInfo = _packageInfoService.get_package_information(pkg.Package);
if (pkgInfo != null && pkgInfo.IsPinned)
Expand Down
Expand Up @@ -115,7 +115,7 @@ public override void run(ChocolateyConfiguration configuration)
{
if (configuration.ListCommand.LocalOnly)
{
_packageService.list_run(configuration,logResults:true);
_packageService.list_run(configuration);
}
else
{
Expand Down
Expand Up @@ -151,7 +151,22 @@ private void append_output(StringBuilder propertyValues, string append)
public bool Force { get; set; }
public bool Noop { get; set; }
public bool HelpRequested { get; set; }

// TODO: Should look into using mutually exclusive output levels - Debug, Info (Regular), Error (Quiet)
// Verbose and Important are not part of the levels at all
/// <summary>
/// Gets or sets a value indicating whether output should be limited.
/// This supports the --limit-output parameter.
/// </summary>
/// <value><c>true</c> for regular output; <c>false</c> for limited output.</value>
public bool RegularOutput { get; set; }
/// <summary>
/// Gets or sets a value indicating whether console logging should be supressed.
/// This is for use by API calls which surface results in alternate forms.
/// </summary>
/// <value><c>true</c> for no output; <c>false</c> for regular or limited output.</value>
/// <remarks>This has only been implemented for NuGet List</remarks>
public bool QuietOutput { get; set; }
public bool PromptForConfirmation { get; set; }
public bool AcceptLicense { get; set; }
public bool AllowUnofficialBuild { get; set; }
Expand Down
Expand Up @@ -22,15 +22,16 @@ namespace chocolatey.infrastructure.app.services
using commandline;
using configuration;
using domain;
using filesystem;
using infrastructure.commands;
using infrastructure.services;
using logging;
using NuGet;
using platforms;
using results;
using tolerance;
using IFileSystem = filesystem.IFileSystem;

public class ChocolateyPackageService : IChocolateyPackageService
public class ChocolateyPackageService : IChocolateyPackageService
{
private readonly INugetService _nugetService;
private readonly IPowershellService _powershellService;
Expand Down Expand Up @@ -73,7 +74,7 @@ public void list_noop(ChocolateyConfiguration config)
}
}

public void list_run(ChocolateyConfiguration config, bool logResults)
public IEnumerable<PackageResult> list_run(ChocolateyConfiguration config)
{
this.Log().Debug(() => "Searching for package information");

Expand All @@ -83,51 +84,68 @@ public void list_run(ChocolateyConfiguration config, bool logResults)
//install webpi if not installed
//run the webpi command
this.Log().Warn("Command not yet functional, stay tuned...");
yield break;
}
else
{
var list = _nugetService.list_run(config, logResults: true);
if (config.RegularOutput)
var packages = new List<IPackage>();

if (config.ListCommand.LocalOnly)
{
config.Sources = ApplicationParameters.PackagesLocation;
config.Prerelease = true;
}
foreach (var package in _nugetService.list_run(config))
{
this.Log().Warn(() => @"{0} packages {1}.".format_with(list.Count(), config.ListCommand.LocalOnly ? "installed" : "found"));
if (!config.ListCommand.LocalOnly || !config.ListCommand.IncludeRegistryPrograms)
{
yield return package;
}

if (config.ListCommand.LocalOnly && config.ListCommand.IncludeRegistryPrograms)
if (config.ListCommand.LocalOnly && config.ListCommand.IncludeRegistryPrograms && package.Package != null)
{
report_registry_programs(config, list);
packages.Add(package.Package);
}
}
}
}

private void report_registry_programs(ChocolateyConfiguration config, IEnumerable<PackageResult> list)
{
var itemsToRemoveFromMachine = new List<string>();
foreach (var packageResult in list)
{
if (packageResult != null && packageResult.Package != null)
if (config.ListCommand.LocalOnly && config.ListCommand.IncludeRegistryPrograms)
{
var pkginfo = _packageInfoService.get_package_information(packageResult.Package);
if (pkginfo.RegistrySnapshot == null)
foreach (var installed in report_registry_programs(config, packages))
{
continue;
}
var key = pkginfo.RegistrySnapshot.RegistryKeys.FirstOrDefault();
if (key != null)
{
itemsToRemoveFromMachine.Add(key.DisplayName);
yield return installed;
}
}
}
var machineInstalled = _registryService.get_installer_keys().RegistryKeys.Where((p) => p.is_in_programs_and_features() && !itemsToRemoveFromMachine.Contains(p.DisplayName)).OrderBy((p) => p.DisplayName).Distinct().ToList();
if (machineInstalled.Count != 0)
}

private IEnumerable<PackageResult> report_registry_programs(ChocolateyConfiguration config, IEnumerable<IPackage> list)
{
var itemsToRemoveFromMachine = list.Select(package => _packageInfoService.get_package_information(package)).
Where(p => p.RegistrySnapshot != null).
Select(p => p.RegistrySnapshot.RegistryKeys.FirstOrDefault()).
Where(p => p != null).
Select(p => p.DisplayName).ToList();

var count = 0;
var machineInstalled = _registryService.get_installer_keys().RegistryKeys.
Where((p) => p.is_in_programs_and_features() && !itemsToRemoveFromMachine.Contains(p.DisplayName)).
OrderBy((p) => p.DisplayName).Distinct();
this.Log().Info(() => "");
foreach (var key in machineInstalled)
{
this.Log().Info(() => "");
foreach (var key in machineInstalled.or_empty_list_if_null())
{
this.Log().Info("{0}|{1}".format_with(key.DisplayName, key.DisplayVersion));
if (config.Verbose) this.Log().Info(" InstallLocation: {0}{1} Uninstall:{2}".format_with(key.InstallLocation.escape_curly_braces(), Environment.NewLine, key.UninstallString.escape_curly_braces()));
}
this.Log().Warn(() => @"{0} applications not managed with Chocolatey.".format_with(machineInstalled.Count));
if (config.RegularOutput)
{
this.Log().Info("{0}|{1}".format_with(key.DisplayName, key.DisplayVersion));
if (config.Verbose) this.Log().Info(" InstallLocation: {0}{1} Uninstall:{2}".format_with(key.InstallLocation.escape_curly_braces(), Environment.NewLine, key.UninstallString.escape_curly_braces()));
}
count++;

yield return new PackageResult(key.DisplayName, key.DisplayName, key.InstallLocation);
}

if (config.RegularOutput)
{
this.Log().Warn(() => @"{0} applications not managed with Chocolatey.".format_with(count));
}
}

Expand Down Expand Up @@ -476,7 +494,7 @@ public void uninstall_noop(ChocolateyConfiguration config)
this.Log().Info(@"Uninstalling the following packages:");
this.Log().Info(ChocolateyLoggers.Important, @"{0}".format_with(config.PackageNames));

foreach (var packageConfigFile in config.PackageNames.Split(new[] { ApplicationParameters.PackageNamesSeparator }, StringSplitOptions.RemoveEmptyEntries).or_empty_list_if_null().Where(p => p.EndsWith(".config")).ToList())
if (config.PackageNames.Split(new[] { ApplicationParameters.PackageNamesSeparator }, StringSplitOptions.RemoveEmptyEntries).or_empty_list_if_null().Any(p => p.EndsWith(".config")))
{
throw new ApplicationException("A packages.config file is only used with installs.");
}
Expand Down Expand Up @@ -708,4 +726,4 @@ private void remove_rollback_if_exists(PackageResult packageResult)
_nugetService.remove_rollback_directory_if_exists(packageResult.Name);
}
}
}
}
Expand Up @@ -16,6 +16,7 @@
namespace chocolatey.infrastructure.app.services
{
using System.Collections.Concurrent;
using System.Collections.Generic;
using configuration;
using results;

Expand All @@ -34,9 +35,8 @@ public interface IChocolateyPackageService
/// Lists/searches for packages that meet a search criteria
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="logResults">Should results be logged?</param>
/// <returns></returns>
void list_run(ChocolateyConfiguration config, bool logResults);
IEnumerable<PackageResult> list_run(ChocolateyConfiguration config);

/// <summary>
/// Run pack in noop mode
Expand Down
Expand Up @@ -35,7 +35,7 @@ public interface INugetService
/// <param name="config">The configuration.</param>
/// <param name="logResults">Should results be logged?</param>
/// <returns></returns>
IEnumerable<PackageResult> list_run(ChocolateyConfiguration config, bool logResults);
IEnumerable<PackageResult> list_run(ChocolateyConfiguration config);

/// <summary>
/// Run pack in noop mode.
Expand Down
39 changes: 22 additions & 17 deletions src/chocolatey/infrastructure.app/services/NugetService.cs
Expand Up @@ -74,32 +74,33 @@ public void list_noop(ChocolateyConfiguration config)
));
}

public IEnumerable<PackageResult> list_run(ChocolateyConfiguration config, bool logResults)
public IEnumerable<PackageResult> list_run(ChocolateyConfiguration config)
{
int count = 0;

if (config.RegularOutput) this.Log().Debug(() => "Running list with the following filter = '{0}'".format_with(config.Input));
if (config.RegularOutput) this.Log().Debug(() => "--- Start of List ---");
foreach (var package in NugetList.GetPackages(config, _nugetLogger))
foreach (var pkg in NugetList.GetPackages(config, _nugetLogger))

{
var pkg = package; // for lamda access
if (logResults)
var package = pkg; // for lamda access
if (!config.QuietOutput)
{
if (config.RegularOutput)
{
this.Log().Info(config.Verbose ? ChocolateyLoggers.Important : ChocolateyLoggers.Normal, () => "{0} {1}".format_with(pkg.Id, pkg.Version.to_string()));
if (config.Verbose) this.Log().Info(() => " {0}{1} Description: {2}{1} Tags: {3}{1} Number of Downloads: {4}{1}".format_with(pkg.Title.escape_curly_braces(), Environment.NewLine, pkg.Description.escape_curly_braces(), pkg.Tags.escape_curly_braces(), pkg.DownloadCount <= 0 ? "n/a" : pkg.DownloadCount.to_string()));
// Maintainer(s):{3}{1} | pkg.Owners.join(", ") - null at the moment
}
else
{
this.Log().Info(config.Verbose ? ChocolateyLoggers.Important : ChocolateyLoggers.Normal, () => "{0}|{1}".format_with(pkg.Id, pkg.Version.to_string()));
}
this.Log().Info(config.Verbose ? ChocolateyLoggers.Important : ChocolateyLoggers.Normal, () => "{0} {1}".format_with(package.Id, package.Version.to_string()));
if (config.RegularOutput && config.Verbose) this.Log().Info(() => " {0}{1} Description: {2}{1} Tags: {3}{1} Number of Downloads: {4}{1}".format_with(package.Title.escape_curly_braces(), Environment.NewLine, package.Description.escape_curly_braces(), package.Tags.escape_curly_braces(), package.DownloadCount <= 0 ? "n/a" : package.DownloadCount.to_string()));
}
else
{
this.Log().Debug(() => "{0} {1}".format_with(pkg.Id, pkg.Version.to_string()));
this.Log().Debug(() => "{0} {1}".format_with(package.Id, package.Version.to_string()));
}
count++;

yield return new PackageResult(pkg, null);
yield return new PackageResult(package, null, config.Sources);
}

if (config.RegularOutput)
{
this.Log().Warn(() => @"{0} packages {1}.".format_with(count, config.ListCommand.LocalOnly ? "installed" : "found"));
}
if (config.RegularOutput) this.Log().Debug(() => "--- End of List ---");
}
Expand Down Expand Up @@ -1027,8 +1028,12 @@ private void set_package_names_if_all_is_specified(ChocolateyConfiguration confi
config.PackageNames = string.Empty;
var input = config.Input;
config.Input = string.Empty;
var quiet = config.QuietOutput;
config.QuietOutput = true;

config.PackageNames = list_run(config).Select(p => p.Name).@join(ApplicationParameters.PackageNamesSeparator);

config.PackageNames = list_run(config, false).Select(p => p.Name).@join(ApplicationParameters.PackageNamesSeparator);
config.QuietOutput = quiet;
config.Input = input;
config.Noop = noop;
config.Prerelease = pre;
Expand Down
25 changes: 25 additions & 0 deletions src/chocolatey/infrastructure/commands/IListCommand.cs
@@ -0,0 +1,25 @@
// Copyright © 2011 - Present RealDimensions Software, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace chocolatey.infrastructure.commands
{
using System.Collections.Generic;
using app.configuration;

public interface IListCommand<T> : ICommand
{
IEnumerable<T> list(ChocolateyConfiguration configuration);
}
}

0 comments on commit 3c12763

Please sign in to comment.