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.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 ConcurrentDictionary<string, PackageResult> uninstall_run(ChocolateyConfi
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);
}
}
}
}
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading

0 comments on commit 3c12763

Please sign in to comment.