diff options
author | Julian Andres Klode <jak@debian.org> | 2020-11-25 18:02:03 +0000 |
---|---|---|
committer | Julian Andres Klode <jak@debian.org> | 2020-11-25 18:02:03 +0000 |
commit | 6530ce64d2337ab309d6c974202243abb09d2d04 (patch) | |
tree | 20e5a01e2c7c206ccf8d4d7f72f6416b4118218d | |
parent | 1077af2e635df738f351d5ea3515804a4de367ea (diff) | |
parent | e5bb443cf58cec23503ad0deeeb06a080053da8a (diff) |
Merge branch 'feature/rred' into 'master'
Enhance rred for possible external usage
See merge request apt-team/apt!136
-rw-r--r-- | apt-private/private-cmndline.cc | 12 | ||||
-rw-r--r-- | apt-private/private-cmndline.h | 1 | ||||
-rw-r--r-- | apt-private/private-main.cc | 1 | ||||
-rw-r--r-- | doc/examples/configure-index | 3 | ||||
-rw-r--r-- | methods/CMakeLists.txt | 2 | ||||
-rw-r--r-- | methods/rred.cc | 163 | ||||
-rwxr-xr-x | test/integration/test-00-commands-have-help | 6 | ||||
-rwxr-xr-x | test/integration/test-method-rred | 51 |
8 files changed, 192 insertions, 47 deletions
diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index bcafe785b..588dea06b 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -362,6 +362,14 @@ static bool addArgumentsAPT(std::vector<CommandLine::Args> &Args, char const * c return true; } /*}}}*/ +static bool addArgumentsRred(std::vector<CommandLine::Args> &Args, char const * const /*Cmd*/)/*{{{*/ +{ + addArg('t', nullptr, "Rred::T", 0); + addArg('f', nullptr, "Rred::F", 0); + addArg('C', "compress", "Rred::Compress",CommandLine::HasArg); + return true; +} + /*}}}*/ std::vector<CommandLine::Args> getCommandArgs(APT_CMD const Program, char const * const Cmd)/*{{{*/ { std::vector<CommandLine::Args> Args; @@ -384,6 +392,7 @@ std::vector<CommandLine::Args> getCommandArgs(APT_CMD const Program, char const case APT_CMD::APT_INTERNAL_SOLVER: addArgumentsAPTInternalSolver(Args, Cmd); break; case APT_CMD::APT_MARK: addArgumentsAPTMark(Args, Cmd); break; case APT_CMD::APT_SORTPKG: addArgumentsAPTSortPkgs(Args, Cmd); break; + case APT_CMD::RRED: addArgumentsRred(Args, Cmd); break; } // options without a command @@ -441,11 +450,12 @@ static bool ShowCommonHelp(APT_CMD const Binary, CommandLine &CmdL, std::vector< case APT_CMD::APT_INTERNAL_SOLVER: cmd = nullptr; break; case APT_CMD::APT_MARK: cmd = "apt-mark(8)"; break; case APT_CMD::APT_SORTPKG: cmd = "apt-sortpkgs(1)"; break; + case APT_CMD::RRED: cmd = nullptr; break; } if (cmd != nullptr) ioprintf(std::cout, _("See %s for more information about the available commands."), cmd); if (Binary != APT_CMD::APT_DUMP_SOLVER && Binary != APT_CMD::APT_INTERNAL_SOLVER && - Binary != APT_CMD::APT_INTERNAL_PLANNER) + Binary != APT_CMD::APT_INTERNAL_PLANNER && Binary != APT_CMD::RRED) std::cout << std::endl << _("Configuration options and syntax is detailed in apt.conf(5).\n" "Information about how to configure sources can be found in sources.list(5).\n" diff --git a/apt-private/private-cmndline.h b/apt-private/private-cmndline.h index 37fe2c91a..22e25d280 100644 --- a/apt-private/private-cmndline.h +++ b/apt-private/private-cmndline.h @@ -23,6 +23,7 @@ enum class APT_CMD { APT_SORTPKG, APT_DUMP_SOLVER, APT_INTERNAL_PLANNER, + RRED, }; struct aptDispatchWithHelp { diff --git a/apt-private/private-main.cc b/apt-private/private-main.cc index e9f65bd83..d4ce0ab2a 100644 --- a/apt-private/private-main.cc +++ b/apt-private/private-main.cc @@ -33,6 +33,7 @@ void InitLocale(APT_CMD const binary) /*{{{*/ case APT_CMD::APT_HELPER: case APT_CMD::APT_GET: case APT_CMD::APT_MARK: + case APT_CMD::RRED: textdomain("apt"); break; case APT_CMD::APT_EXTRACTTEMPLATES: diff --git a/doc/examples/configure-index b/doc/examples/configure-index index d9f269344..0af923811 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -830,6 +830,9 @@ dir::filelistdir "<STRING>"; dir::dpkg::tupletable "<FILE>"; dir::dpkg::triplettable "<FILE>"; dir::dpkg::cputable "<FILE>"; +Rred::t "<BOOL>"; +Rred::f "<BOOL>"; +Rred::Compress "<STRING>"; APT::Internal::OpProgress::Absolute "<BOOL>"; APT::Color "<BOOL>"; diff --git a/methods/CMakeLists.txt b/methods/CMakeLists.txt index d575382f7..a5a360217 100644 --- a/methods/CMakeLists.txt +++ b/methods/CMakeLists.txt @@ -23,6 +23,8 @@ target_include_directories(http PRIVATE $<$<BOOL:${SYSTEMD_FOUND}>:${SYSTEMD_INC target_link_libraries(http ${GNUTLS_LIBRARIES} $<$<BOOL:${SYSTEMD_FOUND}>:${SYSTEMD_LIBRARIES}>) target_link_libraries(ftp ${GNUTLS_LIBRARIES}) +target_link_libraries(rred apt-private) + # Install the library install(TARGETS file copy store gpgv cdrom http ftp rred rsh mirror RUNTIME DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/apt/methods) diff --git a/methods/rred.cc b/methods/rred.cc index 949fa4773..2164cd19e 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -15,6 +15,8 @@ #include <apt-pkg/init.h> #include <apt-pkg/strutl.h> +#include <apt-private/private-cmndline.h> + #include <iostream> #include <list> #include <string> @@ -33,6 +35,33 @@ #define BLOCK_SIZE (512*1024) +static bool ShowHelp(CommandLine &) +{ + std::cout << + "Usage: rred [options] -t input output patch-1 … patch-N\n" + " rred [options] -f patch-1 … patch-N < input > output\n" + " rred [options] patch-1 … patch-N > merged-patch\n" + "\n" + "The main use of this binary is by APTs acquire system, a mode reached\n" + "by calling it without any arguments and driven via messages on stdin.\n" + "\n" + "For the propose of testing as well as simpler direct usage the above\n" + "mentioned modes to work with \"reversed restricted ed\" patches as well.\n" + "\n" + "The arguments used above are:\n" + "* input: denotes a file you want to patch.\n" + "* output: a file you want to store the patched content in.\n" + "* patch-1 … patch-N: One or more files containing a patch.\n" + "* merged-patch: All changes by patch-1 … patch-N in one patch.\n" + "\n" + "This rred supports the commands 'a', 'c' and 'd', both single as well\n" + "as multi line. Other commands are not supported (hence 'restricted').\n" + "The command to patch the last line must appear first in the patch\n" + "(hence 'reversed'). Such a patch can e.g. be produced with 'diff --ed'.\n" + ; + return true; +} + class MemBlock { char *start; size_t size; @@ -727,62 +756,106 @@ class RredMethod : public aptMethod { } }; -int main(int argc, char **argv) +static const APT::Configuration::Compressor *FindCompressor(std::vector<APT::Configuration::Compressor> const &compressors, std::string const &name) /*{{{*/ { - int i; - bool just_diff = true; - bool test = false; - Patch patch; - - if (argc <= 1) { + APT::Configuration::Compressor const * compressor = nullptr; + for (auto const & c : compressors) + { + if (compressor != nullptr && c.Cost >= compressor->Cost) + continue; + if (c.Name == name || c.Extension == name || (!c.Extension.empty() && c.Extension.substr(1) == name)) + compressor = &c; + } + return compressor; +} + /*}}}*/ +static std::vector<aptDispatchWithHelp> GetCommands() +{ + return {{nullptr, nullptr, nullptr}}; +} +int main(int argc, const char *argv[]) +{ + if (argc <= 1) return RredMethod().Run(); + + CommandLine CmdL; + auto const Cmds = ParseCommandLine(CmdL, APT_CMD::RRED, &_config, nullptr, argc, argv, &ShowHelp, &GetCommands); + + FileFd input, output; + unsigned int argi = 0; + auto const argmax = CmdL.FileSize(); + bool const quiet = _config->FindI("quiet", 0) >= 2; + + std::string const compressorName = _config->Find("Rred::Compress", ""); + auto const compressors = APT::Configuration::getCompressors(); + APT::Configuration::Compressor const * compressor = nullptr; + if (not compressorName.empty()) + { + compressor = FindCompressor(compressors, compressorName); + if (compressor == nullptr) + { + std::cerr << "E: Could not find compressor: " << compressorName << '\n'; + return 101; + } + } + + bool just_diff = false; + if (_config->FindB("Rred::T", false)) + { + if (argmax < 3) + { + std::cerr << "E: Not enough filenames given on the command line for mode 't'\n"; + return 101; + } + if (not quiet) + std::clog << "Patching " << CmdL.FileList[0] << " into " << CmdL.FileList[1] << "\n"; + input.Open(CmdL.FileList[0], FileFd::ReadOnly,FileFd::Extension); + if (compressor == nullptr) + output.Open(CmdL.FileList[1], FileFd::WriteOnly | FileFd::Create | FileFd::Empty | FileFd::BufferedWrite, FileFd::Extension); + else + output.Open(CmdL.FileList[1], FileFd::WriteOnly | FileFd::Create | FileFd::Empty | FileFd::BufferedWrite, *compressor); + argi = 2; + } + else + { + if (compressor == nullptr) + output.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly | FileFd::Create | FileFd::BufferedWrite); + else + output.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly | FileFd::Create | FileFd::BufferedWrite, *compressor); + if (_config->FindB("Rred::F", false)) + input.OpenDescriptor(STDIN_FILENO, FileFd::ReadOnly); + else + just_diff = true; } - // Usage: rred -t input output diff ... - if (argc > 1 && strcmp(argv[1], "-t") == 0) { - // Read config files so we see compressors. - pkgInitConfig(*_config); - just_diff = false; - test = true; - i = 4; - } else if (argc > 1 && strcmp(argv[1], "-f") == 0) { - just_diff = false; - i = 2; - } else { - i = 1; + if (argi + 1 > argmax) + { + std::cerr << "E: At least one patch needs to be given on the command line\n"; + return 101; } - for (; i < argc; i++) { - FileFd p; - if (p.Open(argv[i], FileFd::ReadOnly) == false) { + Patch merged_patch; + for (; argi < argmax; ++argi) + { + FileFd patch; + if (not patch.Open(CmdL.FileList[argi], FileFd::ReadOnly, FileFd::Extension)) + { _error->DumpErrors(std::cerr); - exit(1); + return 1; } - if (patch.read_diff(p, NULL) == false) + if (not merged_patch.read_diff(patch, nullptr)) { _error->DumpErrors(std::cerr); - exit(2); + return 2; } } - if (test) { - FileFd out, inp; - std::cerr << "Patching " << argv[2] << " into " << argv[3] << "\n"; - inp.Open(argv[2], FileFd::ReadOnly,FileFd::Extension); - out.Open(argv[3], FileFd::WriteOnly | FileFd::Create | FileFd::Empty | FileFd::BufferedWrite, FileFd::Extension); - patch.apply_against_file(out, inp); - out.Close(); - } else if (just_diff) { - FileFd out; - out.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly | FileFd::Create); - patch.write_diff(out); - out.Close(); - } else { - FileFd out, inp; - out.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly | FileFd::Create | FileFd::BufferedWrite); - inp.OpenDescriptor(STDIN_FILENO, FileFd::ReadOnly); - patch.apply_against_file(out, inp); - out.Close(); - } - return 0; + if (just_diff) + merged_patch.write_diff(output); + else + merged_patch.apply_against_file(output, input); + + output.Close(); + input.Close(); + return DispatchCommandLine(CmdL, {}); } diff --git a/test/integration/test-00-commands-have-help b/test/integration/test-00-commands-have-help index 4a0cc64d4..f91238d5d 100755 --- a/test/integration/test-00-commands-have-help +++ b/test/integration/test-00-commands-have-help @@ -49,7 +49,11 @@ for CMD in 'apt-cache' 'apt-cdrom' 'apt-config' \ checkoptions "$cmd" done -for CMD in 'apt-dump-solver' 'apt-internal-solver' 'apt-internal-planner'; do + +rred() { + runapt "${METHODSDIR}/rred" "$@" +} +for CMD in 'apt-dump-solver' 'apt-internal-solver' 'apt-internal-planner' 'rred'; do checkoptions "$(echo "$CMD" | tr -d '-')" done diff --git a/test/integration/test-method-rred b/test/integration/test-method-rred index 5a885e9d2..fcadac146 100755 --- a/test/integration/test-method-rred +++ b/test/integration/test-method-rred @@ -195,3 +195,54 @@ Package: supercoolstuff failrred 'Wrong order of commands' '7d 17d' failrred 'End before start' '7,6d' + +# deal correctly with patch merging +mergepatches() { + local CONTENT="$1" + shift + testsuccess runapt "${METHODSDIR}/rred" Packages.ed-* "$@" + cp -a rootdir/tmp/testsuccess.output patch.ed + if [ "$#" = '0' ]; then + testfileequal 'patch.ed' "$CONTENT" + fi +} +createpatch() { + echo "$2" +} + +createpatch 'Change dog to cat + kitties' '19c + And a cat! + +Package: extra-kittens +Version: unavailable +Description: fix later +.' > Packages.ed-0 +createpatch 'Remove more stuff and fix later' '23d, +6d' > Packages.ed-1 +testsuccess apthelper cat-file --compress gzip Packages.ed-1 +mv rootdir/tmp/testsuccess.output Packages.ed-1.gz +testsuccess rm Packages.ed-1 +createpatch 'Remove (old) dog paragraph' '10,19d' > Packages.ed-2 +mergepatches '11,19c +Package: extra-kittens +Version: unavailable +. +6d' -C 'gzip' +mv patch.ed patch.ed.gz +mergepatches '11,19c +Package: extra-kittens +Version: unavailable +. +6d' +testfileequal patch.ed "$(apt-helper cat-file patch.ed.gz)" +testrred 'Apply' 'merged patch' "$(cat patch.ed)" 'Package: coolstuff +Version: 0.8.15 +Description: collection of stuff + A lot, too much to iterate all, but at least this: + - stuff + - even more stuff + . + And a cow. + +Package: extra-kittens +Version: unavailable' |