Add command 'nix profile diff-closure'

This shows all changes between generations of a profile. E.g.

  $ nix profile diff-closures --profile /nix/var/nix/profiles/system
  Generation 654 -> 655:
    nix: 2.4pre20200617_5d69bbf → 2.4pre20200701_6ff9aa8, +42.2 KiB

  Generation 655 -> 656:
    blender-bin: 2.83.0 → 2.83.1, -294.2 KiB

  Generation 656 -> 657:
    curl: 7.68.0 → 7.70.0, +19.1 KiB
    firmware-linux-nonfree: 2020-01-22 → 2020-05-19, +30827.7 KiB
    ibus: -21.8 KiB
    initrd-linux: 5.4.46 → 5.4.49
    ...
This commit is contained in:
Eelco Dolstra 2020-07-16 17:00:42 +02:00
parent 5517eee17e
commit 16c9f6762d
3 changed files with 104 additions and 45 deletions

View file

@ -244,4 +244,10 @@ void completeFlakeRefWithFragment(
const Strings & defaultFlakeAttrPaths, const Strings & defaultFlakeAttrPaths,
std::string_view prefix); std::string_view prefix);
void printClosureDiff(
ref<Store> store,
const StorePath & beforePath,
const StorePath & afterPath,
std::string_view indent);
} }

View file

@ -6,7 +6,7 @@
#include <regex> #include <regex>
using namespace nix; namespace nix {
struct Info struct Info
{ {
@ -52,40 +52,12 @@ std::string showVersions(const std::set<std::string> & versions)
return concatStringsSep(", ", versions2); return concatStringsSep(", ", versions2);
} }
struct CmdDiffClosures : SourceExprCommand void printClosureDiff(
ref<Store> store,
const StorePath & beforePath,
const StorePath & afterPath,
std::string_view indent)
{ {
std::string _before, _after;
CmdDiffClosures()
{
expectArg("before", &_before);
expectArg("after", &_after);
}
std::string description() override
{
return "show what packages and versions were added and removed between two closures";
}
Category category() override { return catSecondary; }
Examples examples() override
{
return {
{
"To show what got added and removed between two versions of the NixOS system profile:",
"nix diff-closures /nix/var/nix/profiles/system-655-link /nix/var/nix/profiles/system-658-link",
},
};
}
void run(ref<Store> store) override
{
auto before = parseInstallable(store, _before);
auto beforePath = toStorePath(store, Realise::Outputs, operateOn, before);
auto after = parseInstallable(store, _after);
auto afterPath = toStorePath(store, Realise::Outputs, operateOn, after);
auto beforeClosure = getClosureInfo(store, beforePath); auto beforeClosure = getClosureInfo(store, beforePath);
auto afterClosure = getClosureInfo(store, afterPath); auto afterClosure = getClosureInfo(store, afterPath);
@ -125,10 +97,50 @@ struct CmdDiffClosures : SourceExprCommand
items.push_back(fmt("%s → %s", showVersions(removed), showVersions(added))); items.push_back(fmt("%s → %s", showVersions(removed), showVersions(added)));
if (showDelta) if (showDelta)
items.push_back(fmt("%s%+.1f KiB" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, sizeDelta / 1024.0)); items.push_back(fmt("%s%+.1f KiB" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, sizeDelta / 1024.0));
std::cout << fmt("%s: %s\n", name, concatStringsSep(", ", items)); std::cout << fmt("%s%s: %s\n", indent, name, concatStringsSep(", ", items));
} }
} }
} }
}
using namespace nix;
struct CmdDiffClosures : SourceExprCommand
{
std::string _before, _after;
CmdDiffClosures()
{
expectArg("before", &_before);
expectArg("after", &_after);
}
std::string description() override
{
return "show what packages and versions were added and removed between two closures";
}
Category category() override { return catSecondary; }
Examples examples() override
{
return {
{
"To show what got added and removed between two versions of the NixOS system profile:",
"nix diff-closures /nix/var/nix/profiles/system-655-link /nix/var/nix/profiles/system-658-link",
},
};
}
void run(ref<Store> store) override
{
auto before = parseInstallable(store, _before);
auto beforePath = toStorePath(store, Realise::Outputs, operateOn, before);
auto after = parseInstallable(store, _after);
auto afterPath = toStorePath(store, Realise::Outputs, operateOn, after);
printClosureDiff(store, beforePath, afterPath, "");
}
}; };
static auto r1 = registerCommand<CmdDiffClosures>("diff-closures"); static auto r1 = registerCommand<CmdDiffClosures>("diff-closures");

View file

@ -7,6 +7,7 @@
#include "builtins/buildenv.hh" #include "builtins/buildenv.hh"
#include "flake/flakeref.hh" #include "flake/flakeref.hh"
#include "../nix-env/user-env.hh" #include "../nix-env/user-env.hh"
#include "profiles.hh"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <regex> #include <regex>
@ -394,6 +395,46 @@ struct CmdProfileInfo : virtual EvalCommand, virtual StoreCommand, MixDefaultPro
} }
}; };
struct CmdProfileDiffClosures : virtual EvalCommand, virtual StoreCommand, MixDefaultProfile
{
std::string description() override
{
return "show the closure difference between each generation of a profile";
}
Examples examples() override
{
return {
Example{
"To show what changed between each generation of the NixOS system profile:",
"nix profile diff-closure --profile /nix/var/nix/profiles/system"
},
};
}
void run(ref<Store> store) override
{
auto [gens, curGen] = findGenerations(*profile);
std::optional<Generation> prevGen;
bool first = true;
for (auto & gen : gens) {
if (prevGen) {
if (!first) std::cout << "\n";
first = false;
std::cout << fmt("Generation %d -> %d:\n", prevGen->number, gen.number);
printClosureDiff(store,
store->followLinksToStorePath(prevGen->path),
store->followLinksToStorePath(gen.path),
" ");
}
prevGen = gen;
}
}
};
struct CmdProfile : virtual MultiCommand, virtual Command struct CmdProfile : virtual MultiCommand, virtual Command
{ {
CmdProfile() CmdProfile()
@ -402,6 +443,7 @@ struct CmdProfile : virtual MultiCommand, virtual Command
{"remove", []() { return make_ref<CmdProfileRemove>(); }}, {"remove", []() { return make_ref<CmdProfileRemove>(); }},
{"upgrade", []() { return make_ref<CmdProfileUpgrade>(); }}, {"upgrade", []() { return make_ref<CmdProfileUpgrade>(); }},
{"info", []() { return make_ref<CmdProfileInfo>(); }}, {"info", []() { return make_ref<CmdProfileInfo>(); }},
{"diff-closures", []() { return make_ref<CmdProfileDiffClosures>(); }},
}) })
{ } { }
@ -425,4 +467,3 @@ struct CmdProfile : virtual MultiCommand, virtual Command
}; };
static auto r1 = registerCommand<CmdProfile>("profile"); static auto r1 = registerCommand<CmdProfile>("profile");