From: Jan Kupec Date: Fri, 19 Sep 2008 20:44:38 +0000 (+0000) Subject: - 'licenses' command added (fate #303703) X-Git-Tag: BASE-SuSE-Code-11-Branch~136 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=73c237b9de020d397d80e274a9ea3338a5c5e253;p=platform%2Fupstream%2Fzypper.git - 'licenses' command added (fate #303703) --- diff --git a/doc/zypper.8 b/doc/zypper.8 index 1c70c57..1b56d91 100644 --- a/doc/zypper.8 +++ b/doc/zypper.8 @@ -925,6 +925,23 @@ Shows the ID string of the target operating system. The string has a form of is read from /etc/products.d/baseproduct and the architecture is determined from uname and CPU flags. +.TP +.B licenses +Prints a report about \fBlicenses\fR and \fBEULA\fRs of installed packages +to standard output. + +First, a list of all packages and their licenses and/or EULAs is shown. +This is followed by a summary, including the total number of installed +packages, the number of installed +packages with EULAs that required a confirmation from the user. Since the +EULAs are not stored on the system and can only be read from repository +metadata, the summary includes also the number of installed packages +that have their counterpart in repositories. The report ends with a list +of all licenses uses by the installed packages. + +This command can be useful for companies redistributiong a custom +distribution (like appliances) to figure out what licenses they are bound by. + .SH "GLOBAL OPTIONS" diff --git a/src/Command.cc b/src/Command.cc index 80cb777..78f0fc6 100644 --- a/src/Command.cc +++ b/src/Command.cc @@ -63,6 +63,7 @@ const ZypperCommand ZypperCommand::CLEAN_LOCKS(ZypperCommand::CLEAN_LOCKS_e); const ZypperCommand ZypperCommand::TARGET_OS(ZypperCommand::TARGET_OS_e); const ZypperCommand ZypperCommand::VERSION_CMP(ZypperCommand::VERSION_CMP_e); +const ZypperCommand ZypperCommand::LICENSES(ZypperCommand::LICENSES_e); const ZypperCommand ZypperCommand::HELP(ZypperCommand::HELP_e); const ZypperCommand ZypperCommand::SHELL(ZypperCommand::SHELL_e); @@ -134,6 +135,7 @@ ZypperCommand::Command ZypperCommand::parse(const std::string & strval_r) _table["targetos"] = _table["tos"] = ZypperCommand::TARGET_OS_e; _table["versioncmp"] = _table["vcmp"] = ZypperCommand::VERSION_CMP_e; + _table["licenses"] = ZypperCommand::LICENSES_e; _table["help"] = _table["?"] = ZypperCommand::HELP_e; _table["shell"] = _table["sh"] = ZypperCommand::SHELL_e; diff --git a/src/Command.h b/src/Command.h index f96b98e..3a6dbae 100644 --- a/src/Command.h +++ b/src/Command.h @@ -59,6 +59,7 @@ struct ZypperCommand // utils/others static const ZypperCommand TARGET_OS; static const ZypperCommand VERSION_CMP; + static const ZypperCommand LICENSES; static const ZypperCommand HELP; static const ZypperCommand SHELL; @@ -126,6 +127,7 @@ struct ZypperCommand TARGET_OS_e, VERSION_CMP_e, + LICENSES_e, HELP_e, SHELL_e, diff --git a/src/Zypper.cc b/src/Zypper.cc index 8cf6636..c644596 100644 --- a/src/Zypper.cc +++ b/src/Zypper.cc @@ -239,6 +239,7 @@ void print_main_help(Zypper & zypper) static string help_other_commands = _("\tOther Commands:\n" "\tversioncmp, vcmp\tCompare two version strings.\n" "\ttargetos, tos\t\tPrint the target operating system ID string.\n" + "\tlicenses\t\tPrint report about licenses and EULAs of installed packages.\n" ); static string help_usage = _( @@ -1949,6 +1950,24 @@ void Zypper::processCommandOptions() break; } + case ZypperCommand::LICENSES_e: + { + static struct option options[] = + { + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + specific_options = options; + _command_help = _( + "licenses\n" + "\n" + "Report Licenses and EULA of currently installed software packages.\n" + "\n" + "This command has no additional options.\n" + ); + break; + } + case ZypperCommand::SHELL_QUIT_e: { static struct option quit_options[] = { @@ -3002,10 +3021,10 @@ void Zypper::doCommand() if (command() == ZypperCommand::RUG_PATCH_SEARCH) _gopts.is_rug_compatible = true; - zypp::PoolQuery query; - if (runningHelp()) { out().info(_command_help, Out::QUIET); return; } + zypp::PoolQuery query; + TriBool inst_notinst = indeterminate; if (globalOpts().disable_system_resolvables || copts.count("uninstalled-only")) { @@ -3698,6 +3717,31 @@ void Zypper::doCommand() break; } + case ZypperCommand::LICENSES_e: + { + if (runningHelp()) { out().info(_command_help, Out::QUIET); return; } + + if (!_arguments.empty()) + { + report_too_many_arguments(_command_help); + setExitCode(ZYPPER_EXIT_ERR_INVALID_ARGS); + return; + } + + init_repos(*this); + if (exitCode() != ZYPPER_EXIT_OK) + return; + init_target(*this); + // now load resolvables: + load_resolvables(*this); + // needed to compute status of PPP + resolve(*this); + + report_licenses(*this); + + break; + } + // -----------------------------( shell )------------------------------------ case ZypperCommand::SHELL_QUIT_e: diff --git a/src/misc.cc b/src/misc.cc index ed23a7f..cd49379 100644 --- a/src/misc.cc +++ b/src/misc.cc @@ -5,6 +5,7 @@ |__/|_| |_| \*---------------------------------------------------------------------------*/ +#include #include #include @@ -12,10 +13,14 @@ #include "zypp/base/Logger.h" #include "zypp/SrcPackage.h" +#include "zypp/Package.h" #include "zypp/Capabilities.h" + #include "zypp/RepoInfo.h" +#include "zypp/PoolQuery.h" + #include "main.h" #include "utils/misc.h" #include "utils/pager.h" @@ -207,6 +212,86 @@ bool confirm_licenses(Zypper & zypper) return confirmed; } +// ---------------------------------------------------------------------------- + +void report_licenses(Zypper & zypper) +{ + PoolQuery q; + + ui::Selectable::constPtr s; + PoolItem inst; + PoolItem inst_with_repo; + + unsigned count_installed = 0, count_installed_repo = 0, count_installed_eula = 0; + set unique_licenses; + + for_(pit, q.selectableBegin(), q.selectableEnd()) + { + s = *pit; + if (!s) // FIXME this must not be necessary! + continue; + + for_(iit, s->installedBegin(), s->installedEnd()) + { + inst = *iit; + ++count_installed; + + cout + << s->name() << "-" << inst.resolvable()->edition() + << " (" << kind_to_string_localized(s->kind(), 1) << ")" + << endl; + + if (s->kind() == ResKind::package) + { + cout + << _("License") << ": " + << asKind(inst.resolvable())->license() + << endl; + unique_licenses.insert(asKind(inst.resolvable())->license()); + } + + for_(it, s->availableBegin(), s->availableEnd()) + { + if (equalNVRA(*it->resolvable(), *inst.resolvable())) + { + inst_with_repo = *it; + ++count_installed_repo; + break; + } + } + + if (inst_with_repo && !inst_with_repo.resolvable()->licenseToConfirm().empty()) + { + cout << _("EULA") << ":" << endl; + + const string & licenseText = + inst_with_repo.resolvable()->licenseToConfirm(); + if (licenseText.find("DT:Rich")==licenseText.npos) + cout << licenseText; + else + cout << processRichText(licenseText); + cout << endl; + + ++count_installed_eula; + } + else if (!inst.resolvable()->licenseToConfirm().empty()) + cout << "look! got an installed-only item and it has EULA! he?" << inst << endl; + cout << "-" << endl; + } + } + + cout << endl << _("SUMMARY") << endl << endl; + cout << _("Installed packages: ") << count_installed << endl; + cout << _("Installed packages with counterparts in repositories: ") << count_installed_repo << endl; + cout << _("Installed packages with EULAs: ") << count_installed_eula << endl; + + cout << str::form("Package licenses (%u):", (unsigned int) unique_licenses.size()) << endl; + for_(it, unique_licenses.begin(), unique_licenses.end()) + cout << "* " << *it << endl; +} + +// ---------------------------------------------------------------------------- + static SrcPackage::constPtr source_find( const string & arg ) { /* diff --git a/src/misc.h b/src/misc.h index fb7cc2b..2a83dd6 100644 --- a/src/misc.h +++ b/src/misc.h @@ -22,6 +22,11 @@ */ bool confirm_licenses(Zypper & zypper); +/** + * Prints a report about licenses and EULAs of installed packages to stdout. + */ +void report_licenses(Zypper & zypper); + zypp::ResKind string_to_kind (const std::string & skind); /**