diff options
author | 2012-10-14 13:57:02 -0700 | |
---|---|---|
committer | 2012-10-14 22:04:54 +0100 | |
commit | 934e4074907c23af458153235e15d90016681d94 (patch) | |
tree | c07e21b807f11809c0913cda27d68e013ab17238 | |
parent | 636f8879403986797f3a72155f4af38d4ce49fce (diff) | |
download | paludis-934e4074907c23af458153235e15d90016681d94.tar.gz paludis-934e4074907c23af458153235e15d90016681d94.tar.xz |
cave: add print-unmanaged-files
This adds a new command to cave: print-unmanaged-files. This command is similar
in spirit to the print-unamanged-files demo ruby script. The default invocation
will scan the system root and recursively list all files. You may however limit
it to a subset of the filesystem by specifying the --root parameter. More than
one root may be specified simultaneously.
Signed-off-by: Saleem Abdulrasool <compnerd@compnerd.org>
-rw-r--r-- | src/clients/cave/Makefile.am | 1 | ||||
-rw-r--r-- | src/clients/cave/cmd_print_unmanaged_files.cc | 229 | ||||
-rw-r--r-- | src/clients/cave/cmd_print_unmanaged_files.hh | 43 | ||||
-rw-r--r-- | src/clients/cave/command_factory.cc | 2 |
4 files changed, 275 insertions, 0 deletions
diff --git a/src/clients/cave/Makefile.am b/src/clients/cave/Makefile.am index c8a30b2bd..8af714b63 100644 --- a/src/clients/cave/Makefile.am +++ b/src/clients/cave/Makefile.am @@ -197,6 +197,7 @@ libcave_a_SOURCES = \ cmd_print_sets.cc cmd_print_sets.hh \ cmd_print_spec.cc cmd_print_spec.hh \ cmd_print_sync_protocols.cc cmd_print_sync_protocols.hh \ + cmd_print_unmanaged_files.cc cmd_print_unmanaged_files.hh \ cmd_print_unused_distfiles.cc cmd_print_unused_distfiles.hh \ cmd_purge.cc cmd_purge.hh \ cmd_report.cc cmd_report.hh cmd_report-fmt.hh \ diff --git a/src/clients/cave/cmd_print_unmanaged_files.cc b/src/clients/cave/cmd_print_unmanaged_files.cc new file mode 100644 index 000000000..7b84669d7 --- /dev/null +++ b/src/clients/cave/cmd_print_unmanaged_files.cc @@ -0,0 +1,229 @@ +/* vim: set et fdm=syntax sts=4 sw=4: */ + +/* + * Copyright (c) 2012 Saleem Abdulrasool + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 55 Temple + * Place, Suite 330, Boston, MA 02111-1308 USA + */ + +#include "cmd_print_unmanaged_files.hh" +#include "command_command_line.hh" + +#include <paludis/args/do_help.hh> +#include <paludis/args/log_level_arg.hh> + +#include <paludis/filter.hh> +#include <paludis/contents.hh> +#include <paludis/generator.hh> +#include <paludis/selection.hh> +#include <paludis/package_id.hh> +#include <paludis/environment.hh> +#include <paludis/metadata_key.hh> +#include <paludis/filtered_generator.hh> + +#include <paludis/util/fs_path.hh> +#include <paludis/util/fs_stat.hh> +#include <paludis/util/fs_error.hh> +#include <paludis/util/fs_iterator.hh> + +#include <set> +#include <list> +#include <iostream> +#include <algorithm> + +using namespace paludis; +using namespace cave; + +using std::cerr; +using std::cout; +using std::endl; + +namespace +{ + struct PrintUnmanagedFilesCommandLine : + CaveCommandCommandLine + { + virtual std::string app_name() const + { + return "cave print-unmanaged-files"; + } + + virtual std::string app_synopsis() const + { + return "Prints a list of unamanged files."; + } + + virtual std::string app_description() const + { + return "Prints all files under a specified root which is not owned " + "by an installed package. No formatting is used, making the " + "output suitable for parsing by scripts."; + } + + args::ArgsGroup g_general; + args::StringSetArg a_root; + + PrintUnmanagedFilesCommandLine() : + g_general(main_options_section(), "General options", + "Options which are relevant for most or all actions"), + a_root(&g_general, "root", 'r', "Search under the specified root") + { + add_usage_line("[ --root root ]"); + } + }; + + class CollectRecursiveDirectoryContents + { + public: + CollectRecursiveDirectoryContents(std::set<FSPath, FSPathComparator> * contents) + : _contents(contents) + { + } + + ~CollectRecursiveDirectoryContents() + { + } + + void operator()(const FSPath& path) + { + for (FSIterator entry(path, { fsio_include_dotfiles, fsio_want_regular_files, fsio_want_directories }), end; + entry != end; ++entry) + { + try + { + if (entry->stat().is_directory()) + CollectRecursiveDirectoryContents(this->_contents)(*entry); + else + _contents->insert(*entry); + } + catch (const FSError& error) + { + cerr << error.message() << endl; + } + } + } + + private: + std::set<FSPath, FSPathComparator> * const _contents; + }; + + class CollectPackageContents + { + public: + CollectPackageContents(std::set<FSPath, FSPathComparator> * contents) + : _contents(contents) + { + } + + ~CollectPackageContents() + { + } + + void operator()(const std::shared_ptr<const PackageID>& package) + { + const auto contents(package->contents()); + + if (! contents) + return; + + for (auto entry(contents->begin()), end(contents->end()); + entry != end; ++entry) + _contents->insert((*entry)->location_key()->parse_value()); + } + + private: + std::set<FSPath, FSPathComparator> * const _contents; + }; +} + +int +PrintUnmanagedFilesCommand::run(const std::shared_ptr<Environment> & env, + const std::shared_ptr< const Sequence<std::string> > & args) +{ + PrintUnmanagedFilesCommandLine cmdline; + std::set<FSPath, FSPathComparator> roots; + std::set<FSPath, FSPathComparator> all_files; + std::set<FSPath, FSPathComparator> managed_files; + std::set<FSPath, FSPathComparator> unmanaged_files; + + cmdline.run(args, "CAVE", "CAVE_PRINT_UNMANAGED_FILES_OPTIONS", + "CAVE_PRINT_UNMANAGED_FILES_CMDLINE"); + + if (cmdline.a_help.specified()) + { + cout << cmdline; + return EXIT_SUCCESS; + } + + if (cmdline.begin_parameters() != cmdline.end_parameters()) + throw args::DoHelp("print-unmanaged-files takes no parameters"); + + const auto sysroot = env->preferred_root_key()->parse_value(); + + for (auto root(cmdline.a_root.begin_args()), end(cmdline.a_root.end_args()); + root != end; ++root) + { + const FSPath path(*root); + const FSPath realpath(path.realpath()); + + if (! realpath.stat().is_directory()) + { + std::cerr << path << " is not a directory" << std::endl; + return EXIT_FAILURE; + } + + if (! realpath.starts_with(sysroot)) + { + std::cerr << path << " is not under " << sysroot << std::endl; + return EXIT_FAILURE; + } + + roots.insert(realpath); + } + + if (roots.empty()) + roots.insert(sysroot); + + std::for_each(roots.begin(), roots.end(), + CollectRecursiveDirectoryContents(&all_files)); + + const auto selection(selection::AllVersionsUnsorted(generator::All() | filter::InstalledAtRoot(sysroot))); + const auto packages((*env)[selection]); + + std::for_each(packages->begin(), packages->end(), + CollectPackageContents(&managed_files)); + + std::set_difference(all_files.begin(), all_files.end(), + managed_files.begin(), managed_files.end(), + std::inserter(unmanaged_files, unmanaged_files.begin()), + FSPathComparator()); + + for (auto entry(unmanaged_files.begin()), end(unmanaged_files.end()); + entry != end; ++entry) + cout << *entry << endl; + + return EXIT_SUCCESS; +} + +std::shared_ptr<args::ArgsHandler> +PrintUnmanagedFilesCommand::make_doc_cmdline() +{ + return std::make_shared<PrintUnmanagedFilesCommandLine>(); +} + +CommandImportance +PrintUnmanagedFilesCommand::importance() const +{ + return ci_scripting; +} + diff --git a/src/clients/cave/cmd_print_unmanaged_files.hh b/src/clients/cave/cmd_print_unmanaged_files.hh new file mode 100644 index 000000000..2f4081aa7 --- /dev/null +++ b/src/clients/cave/cmd_print_unmanaged_files.hh @@ -0,0 +1,43 @@ +/* vim: set et fdm=syntax sts=4 sw=4: */ + +/* + * Copyright (c) 2012 Saleem Abdulrasool + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 55 Temple + * Place, Suite 330, Boston, MA 02111-1308 USA + */ + +#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_UNMANAGED_FILES_HH +#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_UNMANAGED_FILES_HH 1 + +#include "command.hh" + +namespace paludis +{ + namespace cave + { + class PALUDIS_VISIBLE PrintUnmanagedFilesCommand : + public Command + { + public: + virtual CommandImportance importance() const PALUDIS_ATTRIBUTE((warn_unused_result)); + + int run(const std::shared_ptr<Environment> &, + const std::shared_ptr< const Sequence<std::string> > & args); + + std::shared_ptr<args::ArgsHandler> make_doc_cmdline(); + }; + } +} + +#endif + diff --git a/src/clients/cave/command_factory.cc b/src/clients/cave/command_factory.cc index b373b1a2d..01fb41410 100644 --- a/src/clients/cave/command_factory.cc +++ b/src/clients/cave/command_factory.cc @@ -80,6 +80,7 @@ #include "cmd_print_sets.hh" #include "cmd_print_spec.hh" #include "cmd_print_sync_protocols.hh" +#include "cmd_print_unmanaged_files.hh" #include "cmd_print_unused_distfiles.hh" #include "cmd_purge.hh" #include "cmd_report.hh" @@ -203,6 +204,7 @@ CommandFactory::CommandFactory() : _imp->handlers.insert(std::make_pair("print-sets", std::bind(&make_command<PrintSetsCommand>))); _imp->handlers.insert(std::make_pair("print-spec", std::bind(&make_command<PrintSpecCommand>))); _imp->handlers.insert(std::make_pair("print-sync-protocols", std::bind(&make_command<PrintSyncProtocolsCommand>))); + _imp->handlers.insert(std::make_pair("print-unmanaged-files", std::bind(&make_command<PrintUnmanagedFilesCommand>))); _imp->handlers.insert(std::make_pair("print-unused-distfiles", std::bind(&make_command<PrintUnusedDistfilesCommand>))); _imp->handlers.insert(std::make_pair("report", std::bind(&make_command<ReportCommand>))); _imp->handlers.insert(std::make_pair("resolve", std::bind(&make_command<ResolveCommand>))); |