From 9caa44624c688ebba6bc041c273102150b1a59e7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 29 Aug 2018 14:35:51 +0200 Subject: Add --{repositories|packages}-file options to bpkg-rep-info This allows saving both manifests with a single invocation (which is the only way to guarantee they are consistent). --- bpkg/buildfile | 2 +- bpkg/rep-info.cli | 21 ++++++++++++-- bpkg/rep-info.cxx | 83 +++++++++++++++++++++++++++++++++++++++++++++-------- tests/rep-info.test | 72 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 158 insertions(+), 20 deletions(-) diff --git a/bpkg/buildfile b/bpkg/buildfile index 5c3ba35..44c04ff 100644 --- a/bpkg/buildfile +++ b/bpkg/buildfile @@ -122,7 +122,7 @@ if $cli.configured --cli-namespace bpkg::cli --generate-vector-scanner --generate-file-scanner \ --generate-group-scanner --keep-separator --generate-specifier \ --generate-parse --page-usage 'bpkg::print_$name$_' --ansi-color \ ---include-base-last --option-length 23 +--include-base-last --option-length 24 cli.cxx{common-options}: cli.options += --short-usage --long-usage # Both. cli.cxx{bpkg-options}: cli.options += --short-usage --suppress-undocumented diff --git a/bpkg/rep-info.cli b/bpkg/rep-info.cli index 6ce1953..16f83d6 100644 --- a/bpkg/rep-info.cli +++ b/bpkg/rep-info.cli @@ -88,9 +88,24 @@ namespace bpkg bool --manifest { "Instead of printing the information in the human-readable form, dump it - as manifest(s). Normally you would use this option in combination with - \cb{--packages|-p} or \cb{--repositories|-r} to only dump one of the - manifests." + (to \cb{stdout}) as manifest(s). Normally you would use this option in + combination with \cb{--packages|-p} or \cb{--repositories|-r} to only + dump one of the manifests. See also \cb{--repositories-file} and + \cb{--packages-file}." + } + + path --repositories-file + { + "", + "If \cb{--manifest} is specified, then save the repositories manifest + to the specified file instead of dumping it to \cb{stdout}." + } + + path --packages-file + { + "", + "If \cb{--manifest} is specified, then save the packages manifest to the + specified file instead of dumping it to \cb{stdout}." } repository_type --type diff --git a/bpkg/rep-info.cxx b/bpkg/rep-info.cxx index b551084..35b06ca 100644 --- a/bpkg/rep-info.cxx +++ b/bpkg/rep-info.cxx @@ -33,6 +33,14 @@ namespace bpkg fail << "repository location argument expected" << info << "run 'bpkg help rep-info' for more information"; + if ((o.repositories_file_specified () || o.packages_file_specified ()) && + !o.manifest ()) + fail << (o.repositories_file_specified () + ? "--repositories-file" + : "--packages-file") + << " specified without --manifest" << + info << "run 'bpkg help rep-info' for more information"; + repository_location rl ( parse_location (args.next (), o.type_specified () @@ -175,14 +183,38 @@ namespace bpkg rms.push_back ( find_base_repository (rfd.fragments.back ().repositories)); - // Note: serializing without any extra repository_manifests info. - // - manifest_serializer s (cout, "stdout"); + auto serialize = [&rms] (ostream& os, const string& name) + { + // Note: serializing without any extra repository_manifests info. + // + manifest_serializer s (os, name); - for (const repository_manifest& rm: rms) - rm.serialize (s); + for (const repository_manifest& rm: rms) + rm.serialize (s); + + s.next ("", ""); // End of stream. + }; + + if (o.repositories_file_specified ()) + { + const path& p (o.repositories_file ()); - s.next ("", ""); // End of stream. + try + { + // Let's set the binary mode not to litter the manifest file + // with the carriage return characters on Windows. + // + ofdstream ofs (p, ios::binary); + serialize (ofs, p.string ()); + ofs.close (); + } + catch (const io_error& e) + { + fail << "unable to write to " << p << ": " << e; + } + } + else + serialize (cout, "stdout"); } else { @@ -266,12 +298,39 @@ namespace bpkg } } - // Note: serializing without any extra package_manifests info. - // - manifest_serializer s (cout, "stdout"); - for (const package_manifest& pm: pms) - pm.serialize (s); - s.next ("", ""); // End of stream. + auto serialize = [&pms] (ostream& os, const string& name) + { + // Note: serializing without any extra package_manifests info. + // + manifest_serializer s (os, name); + + for (const package_manifest& pm: pms) + pm.serialize (s); + + s.next ("", ""); // End of stream. + }; + + if (o.packages_file_specified ()) + { + const path& p (o.packages_file ()); + + try + { + // Let's set the binary mode not to litter the manifest file + // with the carriage return characters on Windows. + // + ofdstream ofs (p, ios::binary); + serialize (ofs, p.string ()); + ofs.close (); + } + catch (const io_error& e) + { + fail << "unable to write to " << p << ": " << e; + } + } + else + serialize (cout, "stdout"); + } else { diff --git a/tests/rep-info.test b/tests/rep-info.test index 60dd96e..d7a80a9 100644 --- a/tests/rep-info.test +++ b/tests/rep-info.test @@ -81,16 +81,18 @@ $* --name $rep/testing >"pkg:build2.org/rep-info/testing ($rep/testing)" : packages : { + test.arguments += --packages # Should go after the rep-info command argument. + : list : - $* --packages $rep/testing >>EOO + $* $rep/testing >>EOO foo/1 EOO : manifest : - $* --packages --manifest $rep/testing >>EOO + $* --manifest $rep/testing >>EOO : 1 name: foo version: 1 @@ -101,21 +103,54 @@ $* --name $rep/testing >"pkg:build2.org/rep-info/testing ($rep/testing)" location: foo-1.tar.gz sha256sum: fee330a362a4f87ff42a954aa305b6446d541b7b60000ebcd2fbf68f2b1ae58e EOO + + : to-file + : + { + : no-manifest + : + $* --packages-file m $rep/testing 2>>EOE != 0 + error: --packages-file specified without --manifest + info: run 'bpkg help rep-info' for more information + EOE + + : manifest + : + { + $* --manifest --packages-file m $rep/testing &m; + + cat m >>EOO + : 1 + name: foo + version: 1 + summary: The "Foo" utility + license: MIT + url: http://www.example.org/foo + email: foo-users@example.org + location: foo-1.tar.gz + sha256sum: fee330a362a4f87ff42a954aa305b6446d541b7b60000ebcd2fbf68f2b1ae58e + EOO + } + } } : repositories : { + # Should go after the rep-info command argument. + # + test.arguments += --repositories + : list : - $* --repositories $rep/testing >>"EOO" + $* $rep/testing >>"EOO" prerequisite pkg:build2.org/foo/testing ($rep_root/foo/testing) complement pkg:build2.org/rep-info/stable ($rep/stable) EOO : manifest : - $* --repositories --manifest $rep/testing >>EOO + $* --manifest $rep/testing >>EOO : 1 location: ../../foo/testing type: pkg @@ -126,6 +161,35 @@ $* --name $rep/testing >"pkg:build2.org/rep-info/testing ($rep/testing)" role: complement : EOO + + : to-file + : + { + : no-manifest + : + $* --repositories-file m $rep/testing 2>>EOE != 0 + error: --repositories-file specified without --manifest + info: run 'bpkg help rep-info' for more information + EOE + + : manifest + : + { + $* --manifest --repositories-file m $rep/testing &m; + + cat m >>EOO + : 1 + location: ../../foo/testing + type: pkg + role: prerequisite + : + location: ../stable + type: pkg + role: complement + : + EOO + } + } } : cert -- cgit v1.1