Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7a04017
(#1276) Add option to show last updated date in `choco list`
swaran18999 Aug 22, 2025
424b9f7
(chocolatey#1276) Add tab completion support for new list options
swaran18999 Sep 23, 2025
60dcb8a
(chocolatey#1276) Refactor space changes and added last update dated
swaran18999 Sep 23, 2025
644bf84
(#1276) Add option to show last updated date in `choco list`
swaran18999 Aug 22, 2025
0d400dc
(chocolatey#1276) Add tab completion support for new list options
swaran18999 Sep 23, 2025
9537707
(chocolatey#1276) Refactor space changes and added last update dated
swaran18999 Sep 23, 2025
4005b2b
Merge branch 'list-command-with-date' of https://github.com/swaran189…
swaran18999 Nov 2, 2025
0772bfc
Merge branch 'chocolatey:develop' into list-command-with-date
swaran18999 Nov 2, 2025
ee85b50
Merge branch 'list-command-with-date' of https://github.com/swaran189…
swaran18999 Nov 2, 2025
24f74cd
(#1276) Add option to order packages by last updated date
swaran18999 Aug 22, 2025
0d1a414
(#1276) Persist .lastUpdated in package info
swaran18999 Nov 4, 2025
0c9bfb5
(#1276]) Add LastUpdated ordering option for list command
swaran18999 Nov 5, 2025
a8437ea
(#1276]) Add LastUpdatedDate ordering with .lastUpdated file-based so…
swaran18999 Nov 7, 2025
17bd5e6
(#1276]) Consolidate LastUpdated ordering implementation
swaran18999 Nov 7, 2025
3c4b01e
Merge branch 'develop' into list-command-with-date
swaran18999 Nov 8, 2025
d06205b
(#1276]) Consolidate LastUpdated ordering implementation
swaran18999 Nov 7, 2025
17e07cc
Merge branch 'list-command-with-date' of https://github.com/swaran189…
swaran18999 Feb 2, 2026
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)
internal 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
18 changes: 11 additions & 7 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,6 +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)
{
Expand Down Expand Up @@ -281,11 +283,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 +302,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 +339,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 +365,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 +1005,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 +1830,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 +2906,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