From fafc5727732c7df2c98b123292f483411e0050e3 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 31 Jan 2022 12:24:28 +0300 Subject: Add support for bootstrap-build and root-build values in package manifest --- bpkg/archive.cxx | 136 +++++++++++++++++---- bpkg/archive.hxx | 11 ++ bpkg/package.cxx | 5 +- bpkg/package.hxx | 53 ++++++-- bpkg/package.xml | 7 ++ bpkg/pkg-build.cxx | 18 ++- bpkg/pkg-configure.cxx | 19 ++- bpkg/pkg-configure.hxx | 2 + bpkg/pkg-fetch.cxx | 3 +- bpkg/pkg-unpack.cxx | 1 + bpkg/pkg-verify.cli | 12 +- bpkg/pkg-verify.cxx | 106 ++++++++++++++++ bpkg/pkg-verify.hxx | 5 +- bpkg/rep-create.cxx | 6 +- bpkg/rep-fetch.cxx | 91 ++++++++++++-- bpkg/rep-fetch.hxx | 9 +- bpkg/rep-info.cli | 12 +- bpkg/rep-info.cxx | 3 +- bpkg/utility.cxx | 8 ++ bpkg/utility.hxx | 17 ++- doc/manual.cli | 19 ++- tests/common/foo-1.tar.gz | Bin 261 -> 332 bytes .../prereq-cycle/extra/libbar-1.1.0+1.tar.gz | Bin 243 -> 321 bytes tests/common/prereq-cycle/math/libbar-1.0.0.tar.gz | Bin 241 -> 319 bytes .../common/prereq-cycle/stable/libfoo-1.0.0.tar.gz | Bin 240 -> 320 bytes tests/pkg-status/extra/libbar-1.1.0+1.tar.gz | Bin 243 -> 322 bytes tests/pkg-status/stable/libbar-1.0.0.tar.gz | Bin 241 -> 323 bytes tests/pkg-status/stable/libfoo-1.0.0.tar.gz | Bin 240 -> 323 bytes tests/pkg-status/testing/libbar-1.0.0+1.tar.gz | Bin 243 -> 325 bytes tests/pkg-status/testing/libbar-1.1.0.tar.gz | Bin 242 -> 322 bytes tests/pkg-status/unstable/libbar-2.0.0.tar.gz | Bin 245 -> 322 bytes tests/pkg-system/libbar-0+1.tar.gz | Bin 239 -> 319 bytes tests/pkg-verify.testscript | 29 +++++ tests/pkg-verify/foo-2.tar.gz | Bin 437 -> 509 bytes tests/pkg-verify/foo-3.tar.gz | Bin 0 -> 412 bytes tests/rep-create.testscript | 36 +++++- tests/rep-create/stable/bar-1.tar.gz | Bin 269 -> 345 bytes tests/rep-create/testing/foo-2.tar.gz | Bin 277 -> 356 bytes .../rep-fetch/no-cycle/extra/libbar-1.1.0+1.tar.gz | Bin 243 -> 323 bytes tests/rep-fetch/no-cycle/math/libbar-1.0.0.tar.gz | Bin 241 -> 324 bytes .../rep-fetch/no-cycle/stable/libfoo-1.0.0.tar.gz | Bin 240 -> 320 bytes tests/rep-info.testscript | 39 +++++- tests/rep-list/extra/libbar-1.1.0+1.tar.gz | Bin 243 -> 323 bytes tests/rep-list/math/libbar-1.0.0.tar.gz | Bin 241 -> 324 bytes tests/rep-list/stable/libfoo-1.0.0.tar.gz | Bin 240 -> 321 bytes tests/rep-list/testing/libbar-2.0.0.tar.gz | Bin 245 -> 323 bytes tests/rep-remove/alpha/libbar-2.0.0.tar.gz | Bin 245 -> 323 bytes tests/rep-remove/testing/libbar-2.0.0.tar.gz | Bin 245 -> 28 bytes 48 files changed, 572 insertions(+), 75 deletions(-) create mode 100644 tests/pkg-verify/foo-3.tar.gz mode change 100644 => 120000 tests/rep-remove/testing/libbar-2.0.0.tar.gz diff --git a/bpkg/archive.cxx b/bpkg/archive.cxx index c096701..2d92802 100644 --- a/bpkg/archive.cxx +++ b/bpkg/archive.cxx @@ -31,9 +31,13 @@ namespace bpkg } #endif + // Only the extract ('x') and list ('t') operations are supported. + // static pair - start_extract (const common_options& co, const path& a) + start (const common_options& co, char op, const path& a) { + assert (op == 'x' || op == 't'); + cstrings args; // On Windows we default to libarchive's bsdtar with auto-decompression @@ -91,7 +95,7 @@ namespace bpkg args.push_back ("--force-local"); #endif - args.push_back ("-xf"); + args.push_back (op == 'x' ? "-xf" : "-tf"); args.push_back (i == 0 ? a.string ().c_str () : "-"); return make_pair (move (args), i); @@ -100,7 +104,7 @@ namespace bpkg pair start_extract (const common_options& co, const path& a, const dir_path& d) { - pair args_i (start_extract (co, a)); + pair args_i (start (co, 'x', a)); cstrings& args (args_i.first); size_t i (args_i.second); @@ -171,31 +175,20 @@ namespace bpkg } } - pair - start_extract (const common_options& co, - const path& a, - const path& f, - bool diag) + // Only the extract ('x') and list ('t') operations are supported. + // + static pair + start (const common_options& co, + char op, + const path& a, + const cstrings& tar_args, + bool diag) { - assert (!f.empty () && f.relative ()); - - pair args_i (start_extract (co, a)); + pair args_i (start (co, op, a)); cstrings& args (args_i.first); size_t i (args_i.second); - // -O/--to-stdout -- extract to stdout. - // - args.push_back ("-O"); - - // On Windows neither MSYS GNU tar nor BSD tar will find the archived file - // if its path is provided in the Windows notation. - // -#ifdef _WIN32 - string fs (f.posix_string ()); - args.push_back (fs.c_str ()); -#else - args.push_back (f.string ().c_str ()); -#endif + args.insert (args.end (), tar_args.begin (), tar_args.end ()); args.push_back (nullptr); args.push_back (nullptr); // Pipe end. @@ -245,6 +238,34 @@ namespace bpkg } } + pair + start_extract (const common_options& co, + const path& a, + const path& f, + bool diag) + { + assert (!f.empty () && f.relative ()); + + cstrings args; + args.reserve (2); + + // -O/--to-stdout -- extract to stdout. + // + args.push_back ("-O"); + + // On Windows neither MSYS GNU tar nor BSD tar will find the archived file + // if its path is provided in the Windows notation. + // +#ifdef _WIN32 + string fs (f.posix_string ()); + args.push_back (fs.c_str ()); +#else + args.push_back (f.string ().c_str ()); +#endif + + return start (co, 'x', a, args, diag); + } + string extract (const common_options& o, const path& a, const path& f, bool diag) try @@ -253,7 +274,7 @@ namespace bpkg try { - // Do not throw when eofbit is set (end of stream reached), and + // Do not throw when eofbit is set (end of stream is reached), and // when failbit is set (getline() failed to extract any character). // ifdstream is (move (pr.second.in_ofd), ifdstream::badbit); @@ -290,4 +311,69 @@ namespace bpkg // fail << "unable to extract " << f << " from " << a << ": " << e << endf; } + + paths + archive_contents (const common_options& o, const path& a, bool diag) + try + { + pair pr (start (o, 't', a, cstrings (), diag)); + + try + { + paths r; + + // Do not throw when eofbit is set (end of stream reached), and + // when failbit is set (getline() failed to extract any character). + // + ifdstream is (move (pr.second.in_ofd), ifdstream::badbit); + + for (string l; !eof (getline (is, l)); ) + r.emplace_back (move (l)); + + is.close (); + + if (pr.second.wait () && pr.first.wait ()) + return r; + + // Fall through. + } + catch (const invalid_path& e) + { + // Just fall through if the pipeline has failed. + // + if (pr.second.wait () && pr.first.wait ()) + { + if (diag) + error << "unable to obtain contents for " << a + << ": invalid path '" << e.path << "'"; + + throw failed (); + } + + // Fall through. + } + catch (const io_error&) + { + // Child exit status doesn't matter. Just wait for the process + // completion and fall through. + // + pr.second.wait (); pr.first.wait (); // Check throw. + } + + // While it is reasonable to assuming the child process issued diagnostics + // if exited with an error status, tar, specifically, doesn't mention the + // archive name. So print the error message whatever the child exit status + // is, if the diagnostics is requested. + // + if (diag) + error << "unable to obtain contents for " << a; + + throw failed (); + } + catch (const process_error& e) + { + // Note: this is not a tar error, so no diag check. + // + fail << "unable to obtain contents for " << a << ": " << e << endf; + } } diff --git a/bpkg/archive.hxx b/bpkg/archive.hxx index cfc4cdb..44b3f01 100644 --- a/bpkg/archive.hxx +++ b/bpkg/archive.hxx @@ -45,6 +45,17 @@ namespace bpkg const path& archive, const path& file, bool diag = true); + + // Start the processes similar to the above functions but execute tar in the + // archive contents listing mode (-t) and then parse its stdout as a list of + // paths (one per line). If diag is false, then don't issue diagnostics + // about the reason why the contents can't be obtained (the archive is + // broken, etc). + // + paths + archive_contents (const common_options&, + const path& archive, + bool diag = true); } #endif // BPKG_ARCHIVE_HXX diff --git a/bpkg/package.cxx b/bpkg/package.cxx index e2a6911..b544773 100644 --- a/bpkg/package.cxx +++ b/bpkg/package.cxx @@ -809,7 +809,10 @@ namespace bpkg } bool - evaluate_enabled (const dependency_alternative& da, const package_name& pkg) + evaluate_enabled (const dependency_alternative& da, + const string& /* bootstrap_build */, + const optional& /* root_build */, + const package_name& pkg) { // @@ DEP TMP // diff --git a/bpkg/package.hxx b/bpkg/package.hxx index 0c70328..db6b2b3 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -27,7 +27,7 @@ // #define DB_SCHEMA_VERSION_BASE 7 -#pragma db model version(DB_SCHEMA_VERSION_BASE, 14, closed) +#pragma db model version(DB_SCHEMA_VERSION_BASE, 15, closed) namespace bpkg { @@ -596,16 +596,23 @@ namespace bpkg // specified or evaluates to true. Note that the package argument is used // for diagnostics only. // - // @@ DEP We will also need to pass some additional information here for - // the actual evaluation (bootstrap/root buildfiles, reflect clauses of - // already selected dependency alternatives, etc). + // @@ DEP We will also need to pass some additional information here for the + // actual evaluation (reflect clauses of already selected dependency + // alternatives, etc). // bool - evaluate_enabled (const dependency_alternative&, const package_name&); + evaluate_enabled (const dependency_alternative&, + const string& bootstrap_build, + const optional& root_build, + const package_name&); // tests // #pragma db value(test_dependency) definition + + // @@ TMP Drop when database migration to the schema version 11 is no longer + // supported. + // #pragma db member(test_dependency::buildtime) default(false) using optional_test_dependency_type = optional; @@ -679,6 +686,14 @@ namespace bpkg small_vector tests; + // Note that while the bootstrap buildfile is always present for stub + // packages, we don't save bootstrap/root buildfiles for stubs of any kind + // (can come from repository, be based on system selected package, etc), + // leaving *_build as nullopt. + // + optional bootstrap_build; + optional root_build; + // Present for non-transient objects only (and only for certain repository // types). // @@ -689,14 +704,24 @@ namespace bpkg mutable optional system_version_; public: - // Note: version constraints must be complete. + // Note: version constraints must be complete and the bootstrap build must + // be present, unless this is a stub. // available_package (package_manifest&& m) : id (move (m.name), m.version), version (move (m.version)), dependencies (convert (move (m.dependencies))), tests (move (m.tests)), - sha256sum (move (m.sha256sum)) {} + sha256sum (move (m.sha256sum)) + { + if (!stub ()) + { + assert (m.bootstrap_build.has_value ()); + + bootstrap_build = move (m.bootstrap_build); + root_build = move (m.root_build); + } + } // Create available stub package. // @@ -785,6 +810,20 @@ namespace bpkg // #pragma db member(tests) id_column("") value_column("test_") + // *_build + // + // @@ TMP Drop when database migration to the schema version 15 is no + // longer supported. + // + // Note that since no real packages use conditional dependencies yet, + // we can just set bootstrap_build to the empty string during migration + // to the database schema version 15. Also we never rely on + // bootstrap_build to be nullopt for the stub packages, so let's not + // complicate things and set bootstrap_build to the empty string for + // them either. + // + #pragma db member(bootstrap_build) default("") + private: friend class odb::access; available_package () = default; diff --git a/bpkg/package.xml b/bpkg/package.xml index c2001f5..15e8846 100644 --- a/bpkg/package.xml +++ b/bpkg/package.xml @@ -1,4 +1,11 @@ + + + + + + + diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index caf5168..a697fb0 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -417,10 +417,12 @@ namespace bpkg ? pkg_verify (options, a->absolute () ? *a : db.config_orig / *a, true /* ignore_unknown */, - false /* expand_values */) + false /* expand_values */, + true /* load_buildfiles */) : pkg_verify (options, sp->effective_src_root (db.config_orig), true /* ignore_unknown */, + true /* load_buildfiles */, // Copy potentially fixed up version from selected package. [&sp] (version& v) {v = sp->version;})); @@ -1256,7 +1258,11 @@ namespace bpkg { for (const dependency_alternative& da: das) { - if (evaluate_enabled (da, pkg.name ())) + assert (ap->bootstrap_build); // Can't be a stub. + + if (evaluate_enabled (da, + *ap->bootstrap_build, ap->root_build, + pkg.name ())) edas.push_back (da); } } @@ -5368,6 +5374,7 @@ namespace bpkg a, true /* ignore_unknown */, false /* expand_values */, + true /* load_buildfiles */, true /* complete_depends */, diag ? 2 : 1)); @@ -5432,6 +5439,7 @@ namespace bpkg o, d, true /* ignore_unknown */, + true /* load_buildfiles */, [&o, &d, &pvi] (version& v) { pvi = package_version (o, d); @@ -8008,11 +8016,14 @@ namespace bpkg // the package manually). Maybe that a good reason not to allow // this? Or we could store this information in the database. // + assert (ap->bootstrap_build); // Can't be a stub. + pkg_configure (o, pdb, t, sp, p.dependencies ? *p.dependencies : ap->dependencies, + *ap->bootstrap_build, ap->root_build, p.config_vars, simulate, fdb); @@ -8028,6 +8039,7 @@ namespace bpkg pkg_verify (o, sp->effective_src_root (pdb.config_orig), true /* ignore_unknown */, + true /* load_buildfiles */, [&sp] (version& v) {v = sp->version;})); // @@ Note that on reconfiguration the dependent looses the potential @@ -8040,6 +8052,8 @@ namespace bpkg t, sp, convert (move (m.dependencies)), + *m.bootstrap_build, + m.root_build, p.config_vars, simulate, fdb); diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx index 8e53d62..05073a7 100644 --- a/bpkg/pkg-configure.cxx +++ b/bpkg/pkg-configure.cxx @@ -33,6 +33,8 @@ namespace bpkg database& db, transaction&, const dependencies& deps, + const string& bootstrap_build, + const optional& root_build, const package_name& package, bool simulate, const function& fdb) @@ -52,7 +54,7 @@ namespace bpkg bool enabled (false); // True if there is an enabled alternative. for (const dependency_alternative& da: das) { - if (!evaluate_enabled (da, package)) + if (!evaluate_enabled (da, bootstrap_build, root_build, package)) continue; enabled = true; @@ -199,6 +201,8 @@ namespace bpkg transaction& t, const shared_ptr& p, const dependencies& deps, + const string& bootstrap_build, + const optional& root_build, const strings& vars, bool simulate, const function& fdb) @@ -229,7 +233,15 @@ namespace bpkg assert (p->prerequisites.empty ()); pair> cpr ( - pkg_configure_prerequisites (o, db, t, deps, p->name, simulate, fdb)); + pkg_configure_prerequisites (o, + db, + t, + deps, + bootstrap_build, + root_build, + p->name, + simulate, + fdb)); p->prerequisites = move (cpr.first); @@ -414,6 +426,7 @@ namespace bpkg package_manifest m (pkg_verify (o, p->effective_src_root (c), true /* ignore_unknown */, + true /* load_buildfiles */, [&p] (version& v) {v = p->version;})); pkg_configure (o, @@ -421,6 +434,8 @@ namespace bpkg t, p, convert (move (m.dependencies)), + *m.bootstrap_build, + m.root_build, vars, false /* simulate */); } diff --git a/bpkg/pkg-configure.hxx b/bpkg/pkg-configure.hxx index c89a159..4fc99fa 100644 --- a/bpkg/pkg-configure.hxx +++ b/bpkg/pkg-configure.hxx @@ -42,6 +42,8 @@ namespace bpkg transaction&, const shared_ptr&, const dependencies&, + const string& bootstrap_build, + const optional& root_build, const strings& config_vars, bool simulate, const function& = {}); diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx index ab67ffe..273a121 100644 --- a/bpkg/pkg-fetch.cxx +++ b/bpkg/pkg-fetch.cxx @@ -162,7 +162,8 @@ namespace bpkg package_manifest m (pkg_verify (co, a, true /* ignore_unknown */, - false /* expand_values */)); + false /* expand_values */, + false /* load_buildfiles */)); l4 ([&]{trace << m.name << " " << m.version;}); diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx index 0087086..bc3452b 100644 --- a/bpkg/pkg-unpack.cxx +++ b/bpkg/pkg-unpack.cxx @@ -172,6 +172,7 @@ namespace bpkg pkg_verify (o, d, true /* ignore_unknown */, + false /* load_buildfiles */, [&o, &d, &pvi] (version& v) { pvi = package_version (o, d); diff --git a/bpkg/pkg-verify.cli b/bpkg/pkg-verify.cli index 33593e4..bd6609f 100644 --- a/bpkg/pkg-verify.cli +++ b/bpkg/pkg-verify.cli @@ -23,8 +23,9 @@ namespace bpkg the top-level directory inside the archive match the canonical \c{\i{name}\b{-}\i{version}} form and that there is a valid manifest file in that top-level directory. Additionally, if the \cb{--deep} option is - specified, it also checks that the files referenced by the \cb{*-file} - manifest values are present in the archive and are not empty." + specified, it also checks that the required \c{*-build} values/files are + present in the manifest/archive and the files referenced by the + \cb{*-file} manifest values are present in the archive and are not empty." } class pkg_verify_options: common_options @@ -39,7 +40,8 @@ namespace bpkg bool --deep { - "Verify files referenced by the \cb{*-file} manifest values." + "Verify the presence of the required \c{*-build} values/files and + the validity of files referenced by the \cb{*-file} manifest values." } bool --ignore-unknown @@ -55,7 +57,9 @@ namespace bpkg human-readable form, dump the package manifest to \cb{stdout}. If the \cb{--deep} option is specified, then in the resulting manifest the \cb{*-file} values are replaced with the contents of the referenced - files and the package dependency constraints are completed." + files, the \c{*-build} values are automatically added (unless the + corresponding files are absent), and the package dependency constraints + are completed." } }; diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx index f2d9881..b0dbf65 100644 --- a/bpkg/pkg-verify.cxx +++ b/bpkg/pkg-verify.cxx @@ -154,6 +154,7 @@ namespace bpkg const path& af, bool iu, bool ev, + bool lb, bool cd, int diag_level) try @@ -225,6 +226,52 @@ namespace bpkg iu); } + // Extract the bootstrap/root buildfiles into the respective *-build + // values, if requested and are not already specified in the manifest. + // + // Note that we don't verify that the files are not empty. + // + if (lb && (!m.bootstrap_build || !m.root_build)) + { + paths ps (archive_contents (co, af, diag_level != 0)); + + auto contains = [&ps] (const path& p) + { + return find (ps.begin (), ps.end (), p) != ps.end (); + }; + + auto extract_buildfiles = [&m, &co, &af, diag_level, &contains] + (const path& b, const path& r) + { + if (!m.bootstrap_build) + m.bootstrap_build = extract (co, af, b, diag_level != 0); + + if (!m.root_build && contains (r)) + m.root_build = extract (co, af, r, diag_level != 0); + }; + + // Check the alternative bootstrap file first since it is more + // specific. + // + path bf; + if (contains (bf = pd / alt_bootstrap_file)) + { + extract_buildfiles (bf, pd / alt_root_file); + } + else if (contains (bf = pd / std_bootstrap_file)) + { + extract_buildfiles (bf, pd / std_root_file); + } + else + { + if (diag_level != 0) + error << "unable to find bootstrap.build file in package " + << "archive " << af; + + throw failed (); + } + } + return m; } @@ -281,6 +328,7 @@ namespace bpkg pkg_verify (const common_options& co, const dir_path& d, bool iu, + bool lb, const function& tf, int diag_level) { @@ -306,6 +354,63 @@ namespace bpkg tf, iu); + // Load the bootstrap/root buildfiles into the respective *-build + // values, if requested and if they are not already specified in the + // manifest. + // + // Note that we don't verify that the files are not empty. + // + if (lb && (!m.bootstrap_build || !m.root_build)) + { + auto load_buildfiles = [&m, diag_level] (const path& b, const path& r) + { + auto load = [diag_level] (const path& f) + { + try + { + ifdstream ifs (f); + string r (ifs.read_text ()); + ifs.close (); + return r; + } + catch (const io_error& e) + { + if (diag_level != 0) + error << "unable to read from " << f << ": " << e; + + throw failed (); + } + }; + + if (!m.bootstrap_build) + m.bootstrap_build = load (b); + + if (!m.root_build && exists (r)) + m.root_build = load (r); + }; + + // Check the alternative bootstrap file first since it is more + // specific. + // + path bf; + if (exists (bf = d / alt_bootstrap_file)) + { + load_buildfiles (bf, d / alt_root_file); + } + else if (exists (bf = d / std_bootstrap_file)) + { + load_buildfiles (bf, d / std_root_file); + } + else + { + if (diag_level != 0) + error << "unable to find bootstrap.build file in package " + << "directory " << d; + + throw failed (); + } + } + // We used to verify package directory is - but it is // not clear why we should enforce it in this case (i.e., the user // provides us with a package directory). @@ -364,6 +469,7 @@ namespace bpkg a, o.ignore_unknown (), o.deep () /* expand_values */, + o.deep () /* load_buildfiles */, o.deep () /* complete_depends */, o.silent () ? 0 : 2)); diff --git a/bpkg/pkg-verify.hxx b/bpkg/pkg-verify.hxx index ac231ec..8c0b555 100644 --- a/bpkg/pkg-verify.hxx +++ b/bpkg/pkg-verify.hxx @@ -22,7 +22,8 @@ namespace bpkg // expand the file-referencing manifest values (description, changes, etc), // setting them to the contents of files they refer to, set the potentially // absent description-type value to the effective description type (see - // libbpkg/manifest.hxx), and complete the dependency constraints. + // libbpkg/manifest.hxx), load the bootstrap and root buildfiles into the + // respective *-build values, and complete the dependency constraints. // // Throw not_package (derived from failed) if this doesn't look like a // package. Throw plain failed if this does looks like a package but @@ -41,6 +42,7 @@ namespace bpkg const path& archive, bool ignore_unknown, bool expand_values, + bool load_buildfiles, bool complete_depends = true, int diag_level = 2); @@ -54,6 +56,7 @@ namespace bpkg pkg_verify (const common_options&, const dir_path& source, bool ignore_unknown, + bool load_buildfiles, const function&, int diag_level = 2); diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx index 8de8c22..b4944b7 100644 --- a/bpkg/rep-create.cxx +++ b/bpkg/rep-create.cxx @@ -98,7 +98,11 @@ namespace bpkg path a (d / p); package_manifest m ( - pkg_verify (o, a, o.ignore_unknown (), true /* expand_values */)); + pkg_verify (o, + a, + o.ignore_unknown (), + true /* expand_values */, + true /* load_buildfiles */)); // Calculate its checksum. // diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index d7e626c..69ddfd1 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -199,6 +199,7 @@ namespace bpkg const dir_path& repo_dir, vector&& pms, bool iu, + bool lb, const repository_location& rl, const optional& fragment) // For diagnostics. { @@ -230,12 +231,12 @@ namespace bpkg // package_version_infos pvs; paths mfs; + dir_paths pds; vector> nvs; { mfs.reserve (pms.size ()); nvs.reserve (pms.size ()); - dir_paths pds; pds.reserve (pms.size ()); for (const package_manifest& pm: pms) @@ -321,6 +322,70 @@ namespace bpkg // Save the package manifest, preserving its location. // m.location = move (*pm.location); + + // Load the bootstrap/root buildfiles into the respective *-build + // values, if requested and if they are not already specified in the + // manifest. + // + if (lb && (!m.bootstrap_build || !m.root_build)) + { + const dir_path& d (pds[i]); + + // Note that the paths relative to the package directory (last two + // arguments) are used for diagnostics only. + // + auto load_buildfiles = [&m, &add_package_info] (const path& bf, + const path& rf, + const path& bfr, + const path& rfr) + { + auto load = [&m, &add_package_info] (const path& f, const path& fr) + { + try + { + ifdstream ifs (f); + string r (ifs.read_text ()); + ifs.close (); + return r; + } + catch (const io_error& e) + { + diag_record dr (fail); + dr << "unable to read from " << fr << ": " << e; + add_package_info (m, dr); + dr << endf; + } + }; + + if (!m.bootstrap_build) + m.bootstrap_build = load (bf, bfr); + + if (!m.root_build && exists (rf)) + m.root_build = load (rf, rfr); + }; + + // Check the alternative bootstrap file first since it is more + // specific. + // + path bf; + if (exists (bf = d / alt_bootstrap_file)) + { + load_buildfiles (bf, d / alt_root_file, + alt_bootstrap_file, alt_root_file); + } + else if (exists (bf = d / std_bootstrap_file)) + { + load_buildfiles (bf, d / std_root_file, + std_bootstrap_file, std_root_file); + } + else + { + diag_record dr (fail); + dr << "unable to find bootstrap.build file"; + add_package_info (m, dr); + } + } + pm = move (m); } catch (const manifest_parsing& e) @@ -377,7 +442,8 @@ namespace bpkg rep_fetch_dir (const common_options& co, const repository_location& rl, bool iu, - bool ev) + bool ev, + bool lb) { assert (rl.absolute ()); @@ -403,6 +469,7 @@ namespace bpkg rd, move (pms), iu, + lb, rl, empty_string /* fragment */)); @@ -437,7 +504,8 @@ namespace bpkg const dir_path* conf, const repository_location& rl, bool iu, - bool ev) + bool ev, + bool lb) { auto i (temp_dir.find (conf != nullptr ? *conf : empty_dir_path)); assert (i != temp_dir.end ()); @@ -565,6 +633,7 @@ namespace bpkg td, move (pms), iu, + lb, rl, fr.friendly_name)); @@ -634,13 +703,14 @@ namespace bpkg const repository_location& rl, const optional& dt, bool iu, - bool ev) + bool ev, + bool lb) { switch (rl.type ()) { case repository_type::pkg: return rep_fetch_pkg (co, conf, db, rl, dt, iu); - case repository_type::dir: return rep_fetch_dir (co, rl, iu, ev); - case repository_type::git: return rep_fetch_git (co, conf, rl, iu, ev); + case repository_type::dir: return rep_fetch_dir (co, rl, iu, ev, lb); + case repository_type::git: return rep_fetch_git (co, conf, rl, iu, ev, lb); } assert (false); // Can't be here. @@ -652,7 +722,8 @@ namespace bpkg const dir_path* conf, const repository_location& rl, bool iu, - bool ev) + bool ev, + bool lb) { return rep_fetch (co, conf, @@ -660,7 +731,8 @@ namespace bpkg rl, nullopt /* dependent_trust */, iu, - ev); + ev, + lb); } // Return an existing repository fragment or create a new one. Update the @@ -1152,7 +1224,8 @@ namespace bpkg rl, dependent_trust, true /* ignore_unknow */, - false /* expand_values */)); + false /* expand_values */, + true /* load_buildfiles */)); // Save for subsequent certificate authentication for repository use by // its dependents. diff --git a/bpkg/rep-fetch.hxx b/bpkg/rep-fetch.hxx index 9a9a18e..b9d458f 100644 --- a/bpkg/rep-fetch.hxx +++ b/bpkg/rep-fetch.hxx @@ -53,15 +53,18 @@ namespace bpkg // If requested, expand the file-referencing package manifest values // (description, changes, etc), setting them to the contents of files they // refer to and set the potentially absent description-type value to the - // effective description type (see libbpkg/manifest.hxx). Note that for pkg - // repositories such values are expanded at the repository creation time. + // effective description type (see libbpkg/manifest.hxx) and load the + // bootstrap and root buildfiles into the respective *-build values. Note + // that for pkg repositories such values are expanded/loaded at the + // repository creation time. // rep_fetch_data rep_fetch (const common_options&, const dir_path* configuration, const repository_location&, bool ignore_unknown, - bool expand_values); + bool expand_values, + bool load_buildfiles); // Add (or update) repository locations to the configuration and fetch // them. If shallow is true, then don't fetch their prerequisite and/or diff --git a/bpkg/rep-info.cli b/bpkg/rep-info.cli index 60854ce..441227e 100644 --- a/bpkg/rep-info.cli +++ b/bpkg/rep-info.cli @@ -89,15 +89,17 @@ namespace bpkg "Instead of printing the information in the human-readable form, dump it (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. If the \cb{--deep} option is specified, - then in the resulting packages manifest the \cb{*-file} values are - replaced with the contents of the referenced files. See also - \cb{--repositories-file} and \cb{--packages-file}." + dump one of the manifests. If the \cb{--deep} option is specified, then + in the resulting packages manifest the \cb{*-file} values are replaced + with the contents of the referenced files and the \c{*-build} values + are automatically added (unless the corresponding files are + absent). See also \cb{--repositories-file} and \cb{--packages-file}." } bool --deep { - "Verify files referenced by the \cb{*-file} manifest values." + "Verify the presence of the required \c{*-build} values/files and + the validity of files referenced by the \cb{*-file} manifest values." } path --repositories-file diff --git a/bpkg/rep-info.cxx b/bpkg/rep-info.cxx index a5d79eb..5184048 100644 --- a/bpkg/rep-info.cxx +++ b/bpkg/rep-info.cxx @@ -71,7 +71,8 @@ namespace bpkg conf, rl, !o.manifest () /* ignore_unknow */, - o.deep () /* expand_values */)); + o.deep () /* expand_values */, + o.deep () /* load_buildfiles */)); // Now print. // diff --git a/bpkg/utility.cxx b/bpkg/utility.cxx index 4d72d7b..cb19ae7 100644 --- a/bpkg/utility.cxx +++ b/bpkg/utility.cxx @@ -26,6 +26,14 @@ namespace bpkg const dir_path certs_dir (dir_path (bpkg_dir) /= "certs"); const dir_path repos_dir (dir_path (bpkg_dir) /= "repos"); + const dir_path std_build_dir ("build"); + const path std_bootstrap_file (dir_path (std_build_dir) /= "bootstrap.build"); + const path std_root_file (dir_path (std_build_dir) /= "root.build"); + + const dir_path alt_build_dir ("build2"); + const path alt_bootstrap_file (dir_path (alt_build_dir) /= "bootstrap.build2"); + const path alt_root_file (dir_path (alt_build_dir) /= "root.build2"); + const dir_path current_dir ("."); map temp_dir; diff --git a/bpkg/utility.hxx b/bpkg/utility.hxx index 1f6027d..2cfa8fa 100644 --- a/bpkg/utility.hxx +++ b/bpkg/utility.hxx @@ -77,10 +77,19 @@ namespace bpkg // Widely-used paths. // - extern const dir_path bpkg_dir; // .bpkg/ - extern const dir_path certs_dir; // .bpkg/certs/ - extern const dir_path repos_dir; // .bpkg/repos/ - extern const dir_path current_dir; // ./ + extern const dir_path bpkg_dir; // .bpkg/ + extern const dir_path certs_dir; // .bpkg/certs/ + extern const dir_path repos_dir; // .bpkg/repos/ + + extern const dir_path std_build_dir; // build/ + extern const path std_bootstrap_file; // build/bootstrap.build + extern const path std_root_file; // build/root.build + + extern const dir_path alt_build_dir; // build2/ + extern const path alt_bootstrap_file; // build2/bootstrap.build2 + extern const path alt_root_file; // build2/root.build2 + + extern const dir_path current_dir; // ./ // Temporary directory facility. // diff --git a/doc/manual.cli b/doc/manual.cli index d9440e8..b00430a 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -620,6 +620,9 @@ license: [; ] [builds]: [; ] [build-include]: [/] [; ] [build-exclude]: [/] [; ] + +[bootstrap-build]: +[root-build]: \ \h2#manifest-package-name|\c{name}| @@ -1434,6 +1437,19 @@ Note that the comment of the matching exclusion is used by the web interface (\c{brep}) to display the reason for the build configuration exclusion. +\h2#manifest-package-bootstrap-root-build|\c{{bootstrap,root\}-build}| + +\ +[bootstrap-build]: +[root-build]: +\ + +The contents of the mandatory \c{bootstrap.build} and optional \c{root.build} +files in the package's \c{build/} (or their alternative names) subdirectory. +If unspecified, then they will be automatically added, for example, when the +\l{#manifest-package-list-pkg package list manifest} is created. + + \h#manifest-package-list-pkg|Package List Manifest for \cb{pkg} Repositories| The package list manifest (the \c{packages.manifest} file found in the @@ -1450,7 +1466,8 @@ After the list manifest comes a (potentially empty) sequence of package manifests. These manifests shall not contain any \c{*-file} or incomplete \l{#manifest-package-depends \c{depends}} values (such values should be converted to their inline versions or completed, respectively) but must -contain the following additional (to package manifest) values: +contain the \c{*-build} values (unless the corresponding files are absent) and +the following additional (to package manifest) values: \ location: diff --git a/tests/common/foo-1.tar.gz b/tests/common/foo-1.tar.gz index 0195f04..0ae2384 100644 Binary files a/tests/common/foo-1.tar.gz and b/tests/common/foo-1.tar.gz differ diff --git a/tests/common/prereq-cycle/extra/libbar-1.1.0+1.tar.gz b/tests/common/prereq-cycle/extra/libbar-1.1.0+1.tar.gz index 890e9e2..9115154 100644 Binary files a/tests/common/prereq-cycle/extra/libbar-1.1.0+1.tar.gz and b/tests/common/prereq-cycle/extra/libbar-1.1.0+1.tar.gz differ diff --git a/tests/common/prereq-cycle/math/libbar-1.0.0.tar.gz b/tests/common/prereq-cycle/math/libbar-1.0.0.tar.gz index 97e6e32..259aeb0 100644 Binary files a/tests/common/prereq-cycle/math/libbar-1.0.0.tar.gz and b/tests/common/prereq-cycle/math/libbar-1.0.0.tar.gz differ diff --git a/tests/common/prereq-cycle/stable/libfoo-1.0.0.tar.gz b/tests/common/prereq-cycle/stable/libfoo-1.0.0.tar.gz index 5e7fa17..30dbd01 100644 Binary files a/tests/common/prereq-cycle/stable/libfoo-1.0.0.tar.gz and b/tests/common/prereq-cycle/stable/libfoo-1.0.0.tar.gz differ diff --git a/tests/pkg-status/extra/libbar-1.1.0+1.tar.gz b/tests/pkg-status/extra/libbar-1.1.0+1.tar.gz index 890e9e2..08f2867 100644 Binary files a/tests/pkg-status/extra/libbar-1.1.0+1.tar.gz and b/tests/pkg-status/extra/libbar-1.1.0+1.tar.gz differ diff --git a/tests/pkg-status/stable/libbar-1.0.0.tar.gz b/tests/pkg-status/stable/libbar-1.0.0.tar.gz index 97e6e32..e49f301 100644 Binary files a/tests/pkg-status/stable/libbar-1.0.0.tar.gz and b/tests/pkg-status/stable/libbar-1.0.0.tar.gz differ diff --git a/tests/pkg-status/stable/libfoo-1.0.0.tar.gz b/tests/pkg-status/stable/libfoo-1.0.0.tar.gz index 5e7fa17..da5cc08 100644 Binary files a/tests/pkg-status/stable/libfoo-1.0.0.tar.gz and b/tests/pkg-status/stable/libfoo-1.0.0.tar.gz differ diff --git a/tests/pkg-status/testing/libbar-1.0.0+1.tar.gz b/tests/pkg-status/testing/libbar-1.0.0+1.tar.gz index 5794085..9c2d0ed 100644 Binary files a/tests/pkg-status/testing/libbar-1.0.0+1.tar.gz and b/tests/pkg-status/testing/libbar-1.0.0+1.tar.gz differ diff --git a/tests/pkg-status/testing/libbar-1.1.0.tar.gz b/tests/pkg-status/testing/libbar-1.1.0.tar.gz index b01ac44..6ca773a 100644 Binary files a/tests/pkg-status/testing/libbar-1.1.0.tar.gz and b/tests/pkg-status/testing/libbar-1.1.0.tar.gz differ diff --git a/tests/pkg-status/unstable/libbar-2.0.0.tar.gz b/tests/pkg-status/unstable/libbar-2.0.0.tar.gz index 6cc5890..98616f8 100644 Binary files a/tests/pkg-status/unstable/libbar-2.0.0.tar.gz and b/tests/pkg-status/unstable/libbar-2.0.0.tar.gz differ diff --git a/tests/pkg-system/libbar-0+1.tar.gz b/tests/pkg-system/libbar-0+1.tar.gz index 9f90936..7461443 100644 Binary files a/tests/pkg-system/libbar-0+1.tar.gz and b/tests/pkg-system/libbar-0+1.tar.gz differ diff --git a/tests/pkg-verify.testscript b/tests/pkg-verify.testscript index 9c56466..69c29b0 100644 --- a/tests/pkg-verify.testscript +++ b/tests/pkg-verify.testscript @@ -91,6 +91,10 @@ $* --deep --ignore-unknown --manifest $src/foo-2.tar.gz >>EOO url: http://www.example.org/foo email: foo-users@example.org depends: bar == 2 + bootstrap-build:\ + project = foo + + \ EOO : incomplete-dependency @@ -107,3 +111,28 @@ $* --ignore-unknown --manifest $src/foo-2.tar.gz >>EOO email: foo-users@example.org depends: bar == $ EOO + +: no-bootstrap-build +: +{ + : no-deep + : + $* --manifest $src/foo-3.tar.gz >>EOO + : 1 + name: foo + version: 3 + summary: The "Foo" utility + license: MIT + description-file: README + changes-file: NEWS + url: http://www.example.org/foo + email: foo-users@example.org + depends: bar == $ + EOO + + : deep + : + $* --deep --manifest $src/foo-3.tar.gz 2>>/~%EOE% != 0 + %error: unable to find bootstrap.build file in package archive .+/foo-3.tar.gz% + EOE +} diff --git a/tests/pkg-verify/foo-2.tar.gz b/tests/pkg-verify/foo-2.tar.gz index 5f5739d..f2d3db8 100644 Binary files a/tests/pkg-verify/foo-2.tar.gz and b/tests/pkg-verify/foo-2.tar.gz differ diff --git a/tests/pkg-verify/foo-3.tar.gz b/tests/pkg-verify/foo-3.tar.gz new file mode 100644 index 0000000..67edccd Binary files /dev/null and b/tests/pkg-verify/foo-3.tar.gz differ diff --git a/tests/rep-create.testscript b/tests/rep-create.testscript index 4f40f7a..63b7064 100644 --- a/tests/rep-create.testscript +++ b/tests/rep-create.testscript @@ -41,8 +41,12 @@ url: http://www.example.org/bar email: bar-users@example.org depends: foo == 1 + bootstrap-build:\ + project = bar + + \ location: bar-1.tar.gz - sha256sum: 514a99f5fadb94f946f8abff59caa9c3cc442cd4f30d4383a1cf6d26ca058036 + sha256sum: 56528e387d1b8e18e3ee7e8510916afdb65f881acfd49d959fae6f434c3bab3c : name: foo version: 1 @@ -50,8 +54,12 @@ license: MIT url: http://www.example.org/foo email: foo-users@example.org + bootstrap-build:\ + project = foo + + \ location: foo-1.tar.gz - sha256sum: fee330a362a4f87ff42a954aa305b6446d541b7b60000ebcd2fbf68f2b1ae58e + sha256sum: 1d88df336611286cdbd84f5c1d87bedc774bc833e200de675e34d9b219c66cfc EOO } @@ -78,8 +86,12 @@ url: http://www.example.org/bar email: bar-users@example.org depends: foo == 1 + bootstrap-build:\ + project = bar + + \ location: bar-1.tar.gz - sha256sum: 514a99f5fadb94f946f8abff59caa9c3cc442cd4f30d4383a1cf6d26ca058036 + sha256sum: 56528e387d1b8e18e3ee7e8510916afdb65f881acfd49d959fae6f434c3bab3c : name: foo version: 1 @@ -87,8 +99,12 @@ license: MIT url: http://www.example.org/foo email: foo-users@example.org + bootstrap-build:\ + project = foo + + \ location: foo-1.tar.gz - sha256sum: fee330a362a4f87ff42a954aa305b6446d541b7b60000ebcd2fbf68f2b1ae58e + sha256sum: 1d88df336611286cdbd84f5c1d87bedc774bc833e200de675e34d9b219c66cfc EOO } } @@ -132,8 +148,12 @@ url: http://www.example.org/bar email: bar-users@example.org depends: foo == 1 + bootstrap-build:\\ + project = bar + + \\ location: bar-1.tar.gz - sha256sum: 514a99f5fadb94f946f8abff59caa9c3cc442cd4f30d4383a1cf6d26ca058036 + sha256sum: 56528e387d1b8e18e3ee7e8510916afdb65f881acfd49d959fae6f434c3bab3c : name: foo version: 1 @@ -141,8 +161,12 @@ license: MIT url: http://www.example.org/foo email: foo-users@example.org + bootstrap-build:\\ + project = foo + + \\ location: foo-1.tar.gz - sha256sum: fee330a362a4f87ff42a954aa305b6446d541b7b60000ebcd2fbf68f2b1ae58e + sha256sum: 1d88df336611286cdbd84f5c1d87bedc774bc833e200de675e34d9b219c66cfc EOO } diff --git a/tests/rep-create/stable/bar-1.tar.gz b/tests/rep-create/stable/bar-1.tar.gz index 66c79a2..d4e6103 100644 Binary files a/tests/rep-create/stable/bar-1.tar.gz and b/tests/rep-create/stable/bar-1.tar.gz differ diff --git a/tests/rep-create/testing/foo-2.tar.gz b/tests/rep-create/testing/foo-2.tar.gz index cb39194..77a7678 100644 Binary files a/tests/rep-create/testing/foo-2.tar.gz and b/tests/rep-create/testing/foo-2.tar.gz differ diff --git a/tests/rep-fetch/no-cycle/extra/libbar-1.1.0+1.tar.gz b/tests/rep-fetch/no-cycle/extra/libbar-1.1.0+1.tar.gz index 890e9e2..8c5c1ee 100644 Binary files a/tests/rep-fetch/no-cycle/extra/libbar-1.1.0+1.tar.gz and b/tests/rep-fetch/no-cycle/extra/libbar-1.1.0+1.tar.gz differ diff --git a/tests/rep-fetch/no-cycle/math/libbar-1.0.0.tar.gz b/tests/rep-fetch/no-cycle/math/libbar-1.0.0.tar.gz index 97e6e32..0697d84 100644 Binary files a/tests/rep-fetch/no-cycle/math/libbar-1.0.0.tar.gz and b/tests/rep-fetch/no-cycle/math/libbar-1.0.0.tar.gz differ diff --git a/tests/rep-fetch/no-cycle/stable/libfoo-1.0.0.tar.gz b/tests/rep-fetch/no-cycle/stable/libfoo-1.0.0.tar.gz index 5e7fa17..7cb8934 100644 Binary files a/tests/rep-fetch/no-cycle/stable/libfoo-1.0.0.tar.gz and b/tests/rep-fetch/no-cycle/stable/libfoo-1.0.0.tar.gz differ diff --git a/tests/rep-info.testscript b/tests/rep-info.testscript index 7161188..992f0e9 100644 --- a/tests/rep-info.testscript +++ b/tests/rep-info.testscript @@ -109,8 +109,12 @@ $* --name $rep/testing >"pkg:build2.org/rep-info/testing ($rep/testing)" license: MIT url: http://www.example.org/foo email: foo-users@example.org + bootstrap-build:\ + project = foo + + \ location: foo-1.tar.gz - sha256sum: fee330a362a4f87ff42a954aa305b6446d541b7b60000ebcd2fbf68f2b1ae58e + sha256sum: 1d88df336611286cdbd84f5c1d87bedc774bc833e200de675e34d9b219c66cfc EOO : deep @@ -135,6 +139,15 @@ $* --name $rep/testing >"pkg:build2.org/rep-info/testing ($rep/testing)" \ description-type: text/plain %.+ + bootstrap-build:\ + project = libbar + + using config + using version + using dist + + \ + %.+ EOO rm state0/libbar.git/libbar/README; @@ -164,6 +177,15 @@ $* --name $rep/testing >"pkg:build2.org/rep-info/testing ($rep/testing)" \ description-type: text/plain %.+ + bootstrap-build:\ + project = libbar + + using config + using version + using dist + + \ + %.+ : name: libmbar version: 1.0.0 @@ -175,6 +197,15 @@ $* --name $rep/testing >"pkg:build2.org/rep-info/testing ($rep/testing)" \ description-type: text/plain %.+ + bootstrap-build:\ + project = libmbar + + using config + using version + using dist + + \ + %.+ EOO } } @@ -203,8 +234,12 @@ $* --name $rep/testing >"pkg:build2.org/rep-info/testing ($rep/testing)" license: MIT url: http://www.example.org/foo email: foo-users@example.org + bootstrap-build:\ + project = foo + + \ location: foo-1.tar.gz - sha256sum: fee330a362a4f87ff42a954aa305b6446d541b7b60000ebcd2fbf68f2b1ae58e + sha256sum: 1d88df336611286cdbd84f5c1d87bedc774bc833e200de675e34d9b219c66cfc EOO } } diff --git a/tests/rep-list/extra/libbar-1.1.0+1.tar.gz b/tests/rep-list/extra/libbar-1.1.0+1.tar.gz index 890e9e2..b761fa7 100644 Binary files a/tests/rep-list/extra/libbar-1.1.0+1.tar.gz and b/tests/rep-list/extra/libbar-1.1.0+1.tar.gz differ diff --git a/tests/rep-list/math/libbar-1.0.0.tar.gz b/tests/rep-list/math/libbar-1.0.0.tar.gz index 97e6e32..425315a 100644 Binary files a/tests/rep-list/math/libbar-1.0.0.tar.gz and b/tests/rep-list/math/libbar-1.0.0.tar.gz differ diff --git a/tests/rep-list/stable/libfoo-1.0.0.tar.gz b/tests/rep-list/stable/libfoo-1.0.0.tar.gz index 5e7fa17..1b030ab 100644 Binary files a/tests/rep-list/stable/libfoo-1.0.0.tar.gz and b/tests/rep-list/stable/libfoo-1.0.0.tar.gz differ diff --git a/tests/rep-list/testing/libbar-2.0.0.tar.gz b/tests/rep-list/testing/libbar-2.0.0.tar.gz index 6cc5890..55cd8bd 100644 Binary files a/tests/rep-list/testing/libbar-2.0.0.tar.gz and b/tests/rep-list/testing/libbar-2.0.0.tar.gz differ diff --git a/tests/rep-remove/alpha/libbar-2.0.0.tar.gz b/tests/rep-remove/alpha/libbar-2.0.0.tar.gz index 6cc5890..576b562 100644 Binary files a/tests/rep-remove/alpha/libbar-2.0.0.tar.gz and b/tests/rep-remove/alpha/libbar-2.0.0.tar.gz differ diff --git a/tests/rep-remove/testing/libbar-2.0.0.tar.gz b/tests/rep-remove/testing/libbar-2.0.0.tar.gz deleted file mode 100644 index 6cc5890..0000000 Binary files a/tests/rep-remove/testing/libbar-2.0.0.tar.gz and /dev/null differ diff --git a/tests/rep-remove/testing/libbar-2.0.0.tar.gz b/tests/rep-remove/testing/libbar-2.0.0.tar.gz new file mode 120000 index 0000000..f2d26fe --- /dev/null +++ b/tests/rep-remove/testing/libbar-2.0.0.tar.gz @@ -0,0 +1 @@ +../alpha/libbar-2.0.0.tar.gz \ No newline at end of file -- cgit v1.1