Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/chocolatey.resources/helpers/ChocolateyTabExpansion.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ $commandOptions = @{
info = "--cert='' --certpassword='' --disable-repository-optimizations --include-configured-sources --local-only --password='' --prerelease --source='' --user='' --version=''"
install = "--allow-downgrade --allow-empty-checksums --allow-empty-checksums-secure --apply-args-to-dependencies --apply-package-parameters-to-dependencies --cert='' --certpassword='' --disable-repository-optimizations --download-checksum='' --download-checksum-x64='' --download-checksum-type='' --download-checksum-type-x64='' --exit-when-reboot-detected --force-dependencies --forcex86 --ignore-checksum --ignore-dependencies --ignore-detected-reboot --ignore-package-exit-codes --include-configured-sources --install-arguments='' --not-silent --override-arguments --package-parameters='' --password='' --pin --prerelease --require-checksums --skip-hooks --skip-scripts --source='' --stop-on-first-failure --use-package-exit-codes --user='' --version=''"
license = ""
list = "--by-id-only --by-tag-only --detail --exact --id-only --id-starts-with --ignore-pinned --include-programs --page='' --page-size='' --prerelease --source='' --version=''"
list = "--by-id-only --by-tag-only --detail --exact --id-only --id-starts-with --ignore-pinned --include-programs --order-by-last-updated-date --page='' --page-size='' --prerelease --show-last-updated-date --source='' --version=''"
new = "--automaticpackage --download-checksum='' --download-checksum-x64='' --download-checksum-type='' --maintainer='' --name='' --output-directory='' --template='' --use-built-in-template --version=''"
outdated = "--cert='' --certpassword='' --disable-repository-optimizations --ignore-pinned --ignore-unfound --include-configured-sources --password='' --prerelease --source='' --user=''"
pack = "--output-directory='' --version=''"
Expand Down Expand Up @@ -242,9 +242,9 @@ function Get-ChocoOrderByOptions {
manually when the enum changes.

.OUTPUTS
A string in the format "Id|LastPublished|Popularity|Title|Unsorted"
A string in the format "Id|LastPublished|Popularity|Title|Unsorted|LastUpdated"
#>
return @("Id", "LastPublished", "Popularity", "Title", "Unsorted")
return @("Id", "LastPublished", "Popularity", "Title", "Unsorted", "LastUpdated")
}

function ChocolateyTabExpansion($lastBlock) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,13 @@ public virtual void ConfigureArgumentParser(OptionSet optionSet, ChocolateyConfi
option => configuration.Verbose = option != null)
.Add("ignore-pinned",
"Ignore Pinned - Ignore pinned packages. Defaults to false.",
option => configuration.ListCommand.IgnorePinned = option != null);
option => configuration.ListCommand.IgnorePinned = option != null)
.Add("show-last-updated-date",
"Show Date - Shows the last date the package was installed/updated.",
option => configuration.ListCommand.ShowLastUpdatedDate = option != null)
.Add("order-by-last-updated-date",
"Order by Last Updated Date - Orders packages by date the package was installed/updated.",
option => configuration.ListCommand.OrderBy = PackageOrder.LastUpdated);
}

public virtual int Count(ChocolateyConfiguration config)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ public ListCommandConfiguration()
public bool ByTagOnly { get; set; }
public bool IdStartsWith { get; set; }
public bool IgnorePinned { get; set; }
public bool ShowLastUpdatedDate { get; set; }
public PackageOrder OrderBy { get; set; }

[Obsolete("This property is deprecated and will be removed in version 3.0. Use the 'OrderBy' property instead.")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ public ChocolateyPackageInformation(IPackageMetadata package)
public string ExtraInformation { get; set; }
public string DeploymentLocation { get; set; }
public string SourceInstalledFrom { get; set; }
public string LastUpdated { get; set; }
}
}
5 changes: 5 additions & 0 deletions src/chocolatey/infrastructure.app/domain/PackageOrder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public enum PackageOrder
/// </summary>
LastPublished,

/// <summary>
/// Sort by last updated date, from newest to oldest.
/// </summary>
LastUpdated,

/// <summary>
/// Do not sort; return packages in the order received from the source.
/// </summary>
Expand Down
32 changes: 30 additions & 2 deletions src/chocolatey/infrastructure.app/nuget/NugetList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using chocolatey.infrastructure.tolerance;
using chocolatey.infrastructure.app.configuration;
using chocolatey.infrastructure.filesystem;
using chocolatey.infrastructure.app.services;
using NuGet.Common;
using NuGet.Packaging;
using NuGet.Packaging.Core;
Expand All @@ -36,6 +37,8 @@ public static class NugetList
public static bool ThresholdHit { get; private set; }
public static bool LowerThresholdHit { get; private set; }

private const string LastUpdated = ".lastUpdated";

public static IEnumerable<IPackageSearchMetadata> GetPackages(ChocolateyConfiguration configuration, ILogger nugetLogger, IFileSystem filesystem)
{
return SearchPackagesAsync(configuration, nugetLogger, filesystem).GetAwaiter().GetResult();
Expand Down Expand Up @@ -320,7 +323,7 @@ private async static Task<IQueryable<IPackageSearchMetadata>> SearchPackagesAsyn
results = results.Where(p => (p.IsDownloadCacheAvailable && configuration.Information.IsLicensedVersion) || p.PackageTestResultStatus != "Failing").ToHashSet();
}

results = ApplyPackageSort(results, configuration.ListCommand.OrderBy).ToHashSet();
results = ApplyPackageSort(results, configuration.ListCommand.OrderBy, filesystem).ToHashSet();

return results.AsQueryable();
}
Expand Down Expand Up @@ -453,7 +456,7 @@ public static IPackageSearchMetadata FindPackage(
return packagesList.OrderByDescending(p => p.Identity.Version).FirstOrDefault();
}

private static IOrderedEnumerable<IPackageSearchMetadata> ApplyPackageSort(IEnumerable<IPackageSearchMetadata> query, domain.PackageOrder orderBy)
private static IOrderedEnumerable<IPackageSearchMetadata> ApplyPackageSort(IEnumerable<IPackageSearchMetadata> query, domain.PackageOrder orderBy, IFileSystem filesystem)
{
switch (orderBy)
{
Expand Down Expand Up @@ -481,6 +484,31 @@ private static IOrderedEnumerable<IPackageSearchMetadata> ApplyPackageSort(IEnum
.ThenBy(q => q.Identity.Id)
.ThenByDescending(q => q.Identity.Version);

case domain.PackageOrder.LastUpdated:
return query
.OrderByDescending(q =>
{
string lastUpdatedContent = null;
var pkgStorePath = ChocolateyPackageInformationService.GetStorePath(filesystem, q.Identity.Id, q.Identity.Version);
var lastUpdated = filesystem.CombinePaths(pkgStorePath, LastUpdated);
if (filesystem.FileExists(lastUpdated))
{
FaultTolerance.TryCatchWithLoggingException(
() =>
{
lastUpdatedContent = filesystem.ReadFile(lastUpdated);
},
"Unable to read last updated from file",
throwError: false,
logWarningInsteadOfError: true
);
}
return lastUpdatedContent;
})
.ThenBy(q => q.Identity.Id)
.ThenByDescending(q => q.Identity.Version);


default:
// Since we return an IOrderedEnumerable, some form of ordering must be applied,
// even when the user has not explicitly requested a sort order.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class ChocolateyPackageInformationService : IChocolateyPackageInformation
private const string VersionOverrideFile = ".version";
private const string DeploymentLocationFile = ".deploymentLocation";
private const string SourceInstalledFromFile = ".sourceInstalledFrom";
private const string LastUpdated = ".lastUpdated";

// We need to store the package identifiers we have warned about
// to prevent duplicated outputs.
Expand Down Expand Up @@ -208,6 +209,20 @@ has errored attempting to read it. This file will be renamed to
logWarningInsteadOfError: true
);
}

var lastUpdated = _fileSystem.CombinePaths(pkgStorePath, LastUpdated);
if (_fileSystem.FileExists(lastUpdated))
{
FaultTolerance.TryCatchWithLoggingException(
() =>
{
packageInformation.LastUpdated = _fileSystem.ReadFile(lastUpdated);
},
"Unable to read last updated from file",
throwError: false,
logWarningInsteadOfError: true
);
}

return packageInformation;
}
Expand Down Expand Up @@ -340,6 +355,23 @@ public void Save(ChocolateyPackageInformation packageInformation)
{
_fileSystem.DeleteFile(_fileSystem.CombinePaths(pkgStorePath, SourceInstalledFromFile));
}

if (!string.IsNullOrWhiteSpace(packageInformation.LastUpdated))
{
var lastUpdatedDate = _fileSystem.CombinePaths(pkgStorePath, LastUpdated);
if (_fileSystem.FileExists(lastUpdatedDate))
{
_fileSystem.DeleteFile(lastUpdatedDate);
}

_fileSystem.WriteFile(lastUpdatedDate, packageInformation.LastUpdated);
}
else
{
_fileSystem.DeleteFile(_fileSystem.CombinePaths(pkgStorePath, LastUpdated));
}


}

public void Remove(IPackageMetadata package)
Expand All @@ -353,7 +385,7 @@ public void Remove(IPackageMetadata package)
_fileSystem.DeleteDirectoryChecked(pkgStorePath, recursive: true);
}

private static string GetStorePath(IFileSystem fileSystem, string id, NuGetVersion version)
public static string GetStorePath(IFileSystem fileSystem, string id, NuGetVersion version)
{
var preferredStorePath = fileSystem.CombinePaths(ApplicationParameters.ChocolateyPackageInfoStoreLocation, "{0}.{1}".FormatWith(id, version.ToNormalizedStringChecked()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ public virtual void HandlePackageResult(PackageResult packageResult, ChocolateyC

pkgInfo.DeploymentLocation = Environment.GetEnvironmentVariable(EnvironmentVariables.Package.ChocolateyPackageInstallLocation);
pkgInfo.SourceInstalledFrom = packageResult.SourceInstalledFrom;
pkgInfo.LastUpdated = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

UpdatePackageInformation(pkgInfo);
EnsureBadPackagesPathIsClean(packageResult);
Expand Down
19 changes: 11 additions & 8 deletions src/chocolatey/infrastructure.app/services/NugetService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ it is possible that incomplete package lists are returned from a command
string packageInstallLocation = null;
string deploymentlocation = null;
string sourceInstalledFrom = null;
string lastUpdated = null;

if (package.PackagePath != null && !string.IsNullOrWhiteSpace(package.PackagePath))
{
Expand All @@ -240,7 +241,7 @@ it is possible that incomplete package lists are returned from a command
packageInfo = _packageInfoService.Get(packageLocalMetadata);
deploymentlocation = packageInfo.DeploymentLocation;
sourceInstalledFrom = packageInfo.SourceInstalledFrom;

lastUpdated = packageInfo.LastUpdated;
if (config.ListCommand.IncludeVersionOverrides)
{
if (packageInfo.VersionOverride != null)
Expand Down Expand Up @@ -281,11 +282,12 @@ it is possible that incomplete package lists are returned from a command
{
if (!(packageInfo != null && packageInfo.IsPinned && config.ListCommand.IgnorePinned))
{
this.Log().Info(logger, () => "{0}{1}".FormatWith(package.Identity.Id, config.ListCommand.IdOnly ? string.Empty : " {0}{1}{2}{3}".FormatWith(
this.Log().Info(logger, () => "{0}{1}".FormatWith(package.Identity.Id, config.ListCommand.IdOnly ? string.Empty : " {0}{1}{2}{3}{4}".FormatWith(
packageLocalMetadata != null ? packageLocalMetadata.Version.ToFullStringChecked() : package.Identity.Version.ToFullStringChecked(),
package.IsApproved ? " [Approved]" : string.Empty,
package.IsDownloadCacheAvailable ? " Downloads cached for licensed users" : string.Empty,
package.PackageTestResultStatus == "Failing" && package.IsDownloadCacheAvailable ? " - Possibly broken for FOSS users (due to original download location changes by vendor)" : package.PackageTestResultStatus == "Failing" ? " - Possibly broken" : string.Empty
package.PackageTestResultStatus == "Failing" && package.IsDownloadCacheAvailable ? " - Possibly broken for FOSS users (due to original download location changes by vendor)" : package.PackageTestResultStatus == "Failing" ? " - Possibly broken" : string.Empty,
config.ListCommand.ShowLastUpdatedDate ? " {0}".FormatWith(packageInfo.LastUpdated) ?? " Last updated not available" : string.Empty
))
);

Expand All @@ -299,7 +301,7 @@ Package url{6}
Tags: {9}
Software Site: {10}
Software License: {11}{12}{13}{14}{15}{16}
Description: {17}{18}{19}{20}{21}
Description: {17}{18}{19}{20}{21}{22}
".FormatWith(
package.Title.EscapeCurlyBraces(),
package.Published.GetValueOrDefault().UtcDateTime.ToShortDateString(),
Expand Down Expand Up @@ -336,6 +338,7 @@ Package url{6}
!string.IsNullOrWhiteSpace(package.ReleaseNotes.ToStringSafe()) ? "{0} Release Notes: {1}".FormatWith(Environment.NewLine, package.ReleaseNotes.EscapeCurlyBraces().Replace("\n ", "\n").Replace("\n", "\n ")) : string.Empty,
!string.IsNullOrWhiteSpace(deploymentlocation) ? "{0} Deployed to: '{1}'".FormatWith(Environment.NewLine, deploymentlocation) :string.Empty,
!string.IsNullOrWhiteSpace(sourceInstalledFrom) ? "{0} Source package was installed from: '{1}'".FormatWith(Environment.NewLine, sourceInstalledFrom) : string.Empty,
!string.IsNullOrWhiteSpace(lastUpdated) ? "{0} Last updated: {1}".FormatWith(Environment.NewLine, lastUpdated) : string.Empty,
packageArgumentsUnencrypted != null ? packageArgumentsUnencrypted : string.Empty
));
}
Expand All @@ -361,7 +364,7 @@ Package url{6}
}
else
{
yield return new PackageResult(packageLocalMetadata, package, config.ListCommand.LocalOnly ? packageInstallLocation : null, config.Sources, null);
yield return new PackageResult(packageLocalMetadata, package, config.ListCommand.LocalOnly ? packageInstallLocation : null, config.Sources, null, lastUpdated);
}
}

Expand Down Expand Up @@ -1001,7 +1004,7 @@ Version was specified as '{0}'. It is possible that version
packageRemoteMetadata.PackageTestResultStatus == "Failing" && packageRemoteMetadata.IsDownloadCacheAvailable ? " - Likely broken for FOSS users (due to download location changes)" : packageRemoteMetadata.PackageTestResultStatus == "Failing" ? " - Possibly broken" : string.Empty
));

var packageResult = packageResultsToReturn.GetOrAdd(packageDependencyInfo.Id.ToLowerSafe(), new PackageResult(packageMetadata, packageRemoteMetadata, installedPath, null, packageDependencyInfo.Source.ToStringSafe()));
var packageResult = packageResultsToReturn.GetOrAdd(packageDependencyInfo.Id.ToLowerSafe(), new PackageResult(packageMetadata, packageRemoteMetadata, installedPath, null, packageDependencyInfo.Source.ToStringSafe(), null));
if (shouldAddForcedResultMessage)
{
packageResult.Messages.Add(new ResultMessage(ResultType.Note, "Backing up and removing old version"));
Expand Down Expand Up @@ -1826,7 +1829,7 @@ public virtual ConcurrentDictionary<string, PackageResult> Upgrade(ChocolateyCon
packageRemoteMetadata.PackageTestResultStatus == "Failing" && packageRemoteMetadata.IsDownloadCacheAvailable ? " - Likely broken for FOSS users (due to download location changes)" : packageRemoteMetadata.PackageTestResultStatus == "Failing" ? " - Possibly broken" : string.Empty
));

var upgradePackageResult = packageResultsToReturn.GetOrAdd(packageDependencyInfo.Id.ToLowerSafe(), new PackageResult(packageMetadata, packageRemoteMetadata, installedPath, null, packageDependencyInfo.Source.ToStringSafe()));
var upgradePackageResult = packageResultsToReturn.GetOrAdd(packageDependencyInfo.Id.ToLowerSafe(), new PackageResult(packageMetadata, packageRemoteMetadata, installedPath, null, packageDependencyInfo.Source.ToStringSafe(), null));
upgradePackageResult.ResetMetadata(packageMetadata, packageRemoteMetadata);
upgradePackageResult.InstallLocation = installedPath;

Expand Down Expand Up @@ -2902,7 +2905,7 @@ protected virtual void BackupAndRunBeforeModify(
{
"chocolatey".Log().Debug("Running beforeModify step for '{0}'", packageResult.PackageMetadata.Id);

var packageResultCopy = new PackageResult(packageResult.PackageMetadata, packageResult.SearchMetadata, packageResult.InstallLocation, packageResult.Source, null);
var packageResultCopy = new PackageResult(packageResult.PackageMetadata, packageResult.SearchMetadata, packageResult.InstallLocation, packageResult.Source, null, null);

beforeModifyAction(packageResultCopy, config);

Expand Down
Loading