From 8fda78b90daac540a8c7ecc29127ee402a64081a Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 25 Nov 2021 23:14:29 +0300 Subject: Add support for publishing packages with non-standard version --- bdep/project.cxx | 2 +- bdep/publish.cli | 8 +++ bdep/publish.cxx | 128 ++++++++++++++++++++++++++++++++--------------- bdep/utility.cxx | 1 + bdep/utility.hxx | 1 + tests/publish.testscript | 22 ++++++++ 6 files changed, 120 insertions(+), 42 deletions(-) diff --git a/bdep/project.cxx b/bdep/project.cxx index 37cc732..5650dea 100644 --- a/bdep/project.cxx +++ b/bdep/project.cxx @@ -398,7 +398,7 @@ namespace bdep // Name/project is to be extracted later. // r.packages.push_back ( - package_location {package_name (), nullopt, *p.package}); + package_location {package_name (), nullopt, move (*p.package)}); } } diff --git a/bdep/publish.cli b/bdep/publish.cli index 42504ac..85925ec 100644 --- a/bdep/publish.cli +++ b/bdep/publish.cli @@ -80,6 +80,14 @@ namespace bdep See \l{brep#submit Package Submission} for details on the submission request handling by archive repositories. + + If the \cb{--forward} option is specified then the forwarded + configurations are used to prepare the package distributions. In + particular, this means that in this mode the project doesn't need to be + initialized and all that's required is for package's source directories + to be configured to forward to an out of source build configuration (see + \l{b(1)} for details on forwarded configurations). This, for example, can + be used to publish packages that don't use the standard version. " } diff --git a/bdep/publish.cxx b/bdep/publish.cxx index ee3bf9d..94cc284 100644 --- a/bdep/publish.cxx +++ b/bdep/publish.cxx @@ -128,7 +128,7 @@ namespace bdep { package_name name; dir_path dist_dir; - standard_version version; + string version; package_name project; string section; // alpha|beta|stable (or --section) @@ -167,47 +167,80 @@ namespace bdep package_name n (move (pl.name)); package_name p (pl.project ? move (*pl.project) : n); dir_path d (move (dist_dirs[i])); - standard_version v (package_version (o, d)); - // Should we allow publishing snapshots and, if so, to which section? - // For example, is it correct to consider a "between betas" snapshot a - // beta version? + // If the package has the standard version, then use it to deduce the + // section, unless it is specified explicitly. Otherwise, there is no + // way to deduce it and thus it needs to be specified explicitly. // - // Seems nothing wrong with submitting snapshots generally. We do this - // for staging most of the time. The below logic of choosing a default - // section requires no changes. Also, the submission service can - // probably have some policy of version acceptance, rejecting some - // version types for some sections. For example, rejecting pre-release - // for stable section and snapshots for any section. - // - // Note, however, that if the project is under an unrecognized VCS or - // the snapshot is uncommitted, then we make it non-forcible. Failed - // that, we might end up publishing distinct snapshots under the same - // temporary version. (To be more precise, we should have checked for - // the latest snapshot but that would require getting the original - // version from the package manifest, which feels too hairy for now). - // - bool non_forcible; - if (v.snapshot () && - ((non_forcible = (!uncommitted || *uncommitted)) || - o.force ().find ("snapshot") == o.force ().end ())) + string s; // Section. + package_info pi (package_b_info (o, d, false /* ext_mods */)); + + if (!pi.version.empty ()) // Does the package use the standard version? { - diag_record dr (fail); - dr << "package " << n << " version " << v << " is a snapshot"; + const standard_version& v (pi.version); + + // Should we allow publishing snapshots and, if so, to which section? + // For example, is it correct to consider a "between betas" snapshot a + // beta version? + // + // Seems nothing wrong with submitting snapshots generally. We do this + // for staging most of the time. The below logic of choosing a default + // section requires no changes. Also, the submission service can + // probably have some policy of version acceptance, rejecting some + // version types for some sections. For example, rejecting pre-release + // for stable section and snapshots for any section. + // + // Note, however, that if the project is under an unrecognized VCS or + // the snapshot is uncommitted, then we make it non-forcible. Failed + // that, we might end up publishing distinct snapshots under the same + // temporary version. (To be more precise, we should have checked for + // the latest snapshot but that would require getting the original + // version from the package manifest, which feels too hairy for now). + // + bool non_forcible; + if (v.snapshot () && + ((non_forcible = (!uncommitted || *uncommitted)) || + o.force ().find ("snapshot") == o.force ().end ())) + { + diag_record dr (fail); + dr << "package " << n << " version " << v << " is a snapshot"; - if (!non_forcible) - dr << info << "use --force=snapshot to publish anyway"; + if (!non_forcible) + dr << info << "use --force=snapshot to publish anyway"; + } + + // Per semver we treat zero major versions as alpha. + // + s = o.section_specified () ? o.section () : + v.alpha () || v.major () == 0 ? "alpha" : + v.beta () ? "beta" : + "stable" ; } + else + { + // Verify the package version. + // + try + { + bpkg::version (pi.version_string); + } + catch (const invalid_argument& e) + { + fail << "invalid package " << n << " version '" << pi.version_string + << "': " << e; + } - // Per semver we treat zero major versions as alpha. - // - string s (o.section_specified () ? o.section () : - v.alpha () || v.major () == 0 ? "alpha" : - v.beta () ? "beta" : "stable"); + if (!o.section_specified ()) + fail << "unable to deduce section for package " << n << " version " + << pi.version_string << + info << "use --section to specify it explicitly"; + + s = o.section (); + } pkgs.push_back (package {move (n), move (d), - move (v), + move (pi.version_string), move (p), move (s), path () /* archive */, @@ -285,7 +318,7 @@ namespace bdep // This is the canonical package archive name that we expect dist to // produce. // - path a (dr / p.name.string () + '-' + p.version.string () + ".tar.gz"); + path a (dr / p.name.string () + '-' + p.version + ".tar.gz"); path c (a + ".sha256"); if (!exists (a)) @@ -697,7 +730,7 @@ namespace bdep auto pkg_str = [] (const package& p) { - return p.name.string () + '/' + p.version.string (); + return p.name.string () + '/' + p.version; }; if (pkgs.size () == 1) @@ -990,14 +1023,27 @@ namespace bdep fail << "package " << pl.name << " source directory is not forwarded" << info << "package source directory is " << d; - // Get the configuration root. - // - (pi.out_root /= pi.amalgamation).normalize (); - dist_dirs.push_back (move (d)); - if (find (cfgs.begin (), cfgs.end (), pi.out_root) == cfgs.end ()) - cfgs.push_back (move (pi.out_root)); + // If the forwarded configuration is amalgamated and this amalgamation + // is a bpkg configuration where some packages are bdep-initialized, + // then collect it for pre-sync. + // + if (!pi.amalgamation.empty ()) + { + // Get the configuration root. + // + (pi.out_root /= pi.amalgamation).normalize (); + + if (exists (dir_path (pi.out_root) /= bpkg_dir) && + !configuration_projects (o, + pi.out_root, + dir_path () /* prj */).empty ()) + { + if (find (cfgs.begin (), cfgs.end (), pi.out_root) == cfgs.end ()) + cfgs.push_back (move (pi.out_root)); + } + } } // Pre-sync the configurations to avoid triggering the build system hook diff --git a/bdep/utility.cxx b/bdep/utility.cxx index 2a7808f..8d57b75 100644 --- a/bdep/utility.cxx +++ b/bdep/utility.cxx @@ -19,6 +19,7 @@ namespace bdep const dir_path bdep_dir (".bdep"); const path bdep_file (bdep_dir / "bdep.sqlite3"); + const dir_path bpkg_dir (".bpkg"); const path manifest_file ("manifest"); const path packages_file ("packages.manifest"); diff --git a/bdep/utility.hxx b/bdep/utility.hxx index e43b4ff..f5b0412 100644 --- a/bdep/utility.hxx +++ b/bdep/utility.hxx @@ -84,6 +84,7 @@ namespace bdep // extern const dir_path bdep_dir; // .bdep/ extern const path bdep_file; // .bdep/bdep.sqlite3 + extern const dir_path bpkg_dir; // .bpkg/ extern const path manifest_file; // manifest extern const path packages_file; // packages.manifest diff --git a/tests/publish.testscript b/tests/publish.testscript index d871e7d..add8418 100644 --- a/tests/publish.testscript +++ b/tests/publish.testscript @@ -128,6 +128,28 @@ g = git -C prj >! 2>! error: package prj version 1.0.15-a.0.19700101000000 is a snapshot EOE } + + : non-standard-version + : + : Test publishing a package with the non-standard version from a + : non-bdep-initialized project, using the forwarded build2 configuration. + : + { + $new --no-init --no-amalgamation prj 2>- &prj/***; + sed -i -e 's/^(version:) .*$/\1 12345/' prj/manifest; + + sed -i \ + -e 's/^(amalgamation =.*)$/\1\nversion = 12345\ndist.package = $project-$version/' \ + -e 's/^using version$//' \ + prj/build/bootstrap.build; + + $build 'configure:' prj/@prj-cfg/,forward &prj/build/bootstrap/*** 2>!; + + $* --no-progress --forward --section alpha 2>>~%EOE% + %package submission is queued(: .*prj/12345)?% + %reference: .{12}% + EOE + } } : multi-pkg -- cgit v1.1