summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-01-17 19:46:28 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-01-22 14:59:10 +0300
commitd6b4ed9cc7f6b27c9180627e7d1fec4d698af28c (patch)
tree39f571c50dfa21be9be2df4b0e2f91806ec5a206
parentb83bc314314e18e76929ac9f6ae5d3715baeeb4e (diff)
downloadbdep-d6b4ed9cc7f6b27c9180627e7d1fec4d698af28c.tar.gz
bdep-d6b4ed9cc7f6b27c9180627e7d1fec4d698af28c.tar.xz
bdep-d6b4ed9cc7f6b27c9180627e7d1fec4d698af28c.zip
Add support for --force option in bdep-release and bdep-publish
-rw-r--r--bdep/ci.cxx12
-rw-r--r--bdep/project.cxx87
-rw-r--r--bdep/project.hxx6
-rw-r--r--bdep/publish.cli9
-rw-r--r--bdep/publish.cxx59
-rw-r--r--bdep/release.cli9
-rw-r--r--bdep/release.cxx102
-rw-r--r--tests/publish.testscript156
-rw-r--r--tests/release.testscript418
9 files changed, 637 insertions, 221 deletions
diff --git a/bdep/ci.cxx b/bdep/ci.cxx
index 9298ef8..304818d 100644
--- a/bdep/ci.cxx
+++ b/bdep/ci.cxx
@@ -55,6 +55,10 @@ namespace bdep
commit = move (s.commit);
+ // Note: not forcible. The use case could be to CI some commit from the
+ // past. But in this case we also won't have upstream. So maybe it will
+ // be better to invent the --commit option or some such.
+ //
if (s.branch.empty ())
fail << "project directory is in the detached HEAD state" <<
info << "run 'git status' for details";
@@ -70,9 +74,15 @@ namespace bdep
size_t p (path::traits::rfind_separator (s.upstream));
branch = p != string::npos ? string (s.upstream, p + 1) : s.upstream;
+ // Note: not forcible (for now). While the use case is valid, the
+ // current and committed package versions are likely to differ (in
+ // snapshot id). Obtaining the committed versions feels too hairy for
+ // now.
+ //
if (s.staged || s.unstaged)
fail << "project directory has uncommitted changes" <<
- info << "run 'git status' for details";
+ info << "run 'git status' for details" <<
+ info << "use 'git stash' to temporarily hide the changes";
// We definitely don't want to be ahead (upstream doesn't have this
// commit) but there doesn't seem be anything wrong with being behind.
diff --git a/bdep/project.cxx b/bdep/project.cxx
index 8092867..cf79e41 100644
--- a/bdep/project.cxx
+++ b/bdep/project.cxx
@@ -13,6 +13,7 @@
#include <bdep/diagnostics.hxx>
using namespace std;
+using namespace butl;
namespace bdep
{
@@ -384,50 +385,66 @@ namespace bdep
}
}
- standard_version
- package_version (const common_options& o,
- const dir_path& cfg,
- const package_name& p)
+ // Obtain build2 project info for package source or output directories.
+ //
+ static b_project_info
+ package_info (const common_options& o, const dir_path& d)
{
- using namespace butl;
-
- // We could have used bpkg-pkg-status but then we would have to deal with
- // iterations. So we use the build system's info meta-operation directly.
- //
try
{
- // Note: the package directory inside the configuration is a bit of an
- // assumption.
- //
- b_project_info pi (
- b_info ((dir_path (cfg) /= p.string ()),
- verb,
- [] (const char* const args[], size_t n)
- {
- if (verb >= 3)
- print_process (args, n);
- },
- path (name_b (o)),
- exec_dir,
- o.build_option ()));
-
- if (pi.version.empty ())
- fail << "empty version for package " << p;
-
- // Verify the name for good measure.
- //
- if (pi.project != p)
- fail << "name mismatch for package " << p;
-
- return move (pi.version);
+ return b_info (d,
+ verb,
+ [] (const char* const args[], size_t n)
+ {
+ if (verb >= 3)
+ print_process (args, n);
+ },
+ path (name_b (o)),
+ exec_dir,
+ o.build_option ());
}
catch (const b_error& e)
{
if (e.normal ())
throw failed (); // Assume the build2 process issued diagnostics.
- fail << "unable to obtain package " << p << " project info: " << e
- << endf;
+ fail << "unable to obtain project info for package directory " << d
+ << ": " << e << endf;
}
}
+
+ standard_version
+ package_version (const common_options& o, const dir_path& d)
+ {
+ b_project_info pi (package_info (o, d));
+
+ if (pi.version.empty ())
+ fail << "empty version for package directory " << d;
+
+ return move (pi.version);
+ }
+
+ standard_version
+ package_version (const common_options& o,
+ const dir_path& cfg,
+ const package_name& p)
+ {
+ // We could have used bpkg-pkg-status but then we would have to deal with
+ // iterations. So we use the build system's info meta-operation directly.
+ //
+ // Note: the package directory inside the configuration is a bit of an
+ // assumption.
+ //
+ b_project_info pi (package_info (o, (dir_path (cfg) /= p.string ())));
+
+ if (pi.version.empty ())
+ fail << "empty version for package " << p;
+
+ // Verify the name for good measure.
+ //
+ if (pi.project != p)
+ fail << "name mismatch for package " << p;
+
+ return move (pi.version);
+ }
}
diff --git a/bdep/project.hxx b/bdep/project.hxx
index 47373b0..de39ee5 100644
--- a/bdep/project.hxx
+++ b/bdep/project.hxx
@@ -236,9 +236,13 @@ namespace bdep
void
verify_project_packages (const project_packages&, const configurations&);
- // Determine the version of a package in the specified configuration.
+ // Determine the version of a package in the specified package (first
+ // version) or configuration (second version) directory.
//
standard_version
+ package_version (const common_options&, const dir_path& pkg);
+
+ standard_version
package_version (const common_options&,
const dir_path& cfg,
const package_name&);
diff --git a/bdep/publish.cli b/bdep/publish.cli
index 1c05cd0..cba7436 100644
--- a/bdep/publish.cli
+++ b/bdep/publish.cli
@@ -2,6 +2,8 @@
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
+include <set>;
+
include <bdep/project.cli>;
"\section=1"
@@ -125,6 +127,13 @@ namespace bdep
for details."
}
+ std::set<string> --force
+ {
+ "<check>",
+ "Force publishing, disabling the specified check. Repeat this option to
+ disable multiple checks."
+ }
+
string --simulate
{
"<outcome>",
diff --git a/bdep/publish.cxx b/bdep/publish.cxx
index 3c64706..c97c652 100644
--- a/bdep/publish.cxx
+++ b/bdep/publish.cxx
@@ -120,6 +120,27 @@ namespace bdep
};
vector<package> pkgs;
+ // If the project is under recognized VCS, it feels right to fail if it is
+ // uncommitted to decrease chances of publishing package modifications
+ // under the same version. It still make sense to allow submitting
+ // uncommitted packages if requested explicitly, for whatever reason.
+ //
+ bool git_repo (git_repository (prj));
+ optional<bool> uncommitted; // Absent if unrecognized VCS.
+
+ if (git_repo)
+ {
+ git_repository_status st (git_status (prj));
+ uncommitted = st.unstaged || st.staged;
+
+ if (*uncommitted &&
+ o.force ().find ("uncommitted") == o.force ().end ())
+ fail << "project directory has uncommitted changes" <<
+ info << "run 'git status' for details" <<
+ info << "use 'git stash' to temporarily hide the changes" <<
+ info << "use --force=uncommitted to publish anyway";
+ }
+
for (package_location& pl: pkg_locs)
{
package_name n (move (pl.name));
@@ -131,8 +152,31 @@ namespace bdep
// For example, is it correct to consider a "between betas" snapshot a
// beta version?
//
- if (v.snapshot ())
- fail << "package " << n << " version " << v << " is a snapshot";
+ // 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";
+ }
// Per semver we treat zero major versions as alpha.
//
@@ -201,11 +245,18 @@ namespace bdep
// directly to prepare the distribution. If/when we have bpkg-pkg-dist,
// we may want to switch to that.
//
+ // We need to specify config.dist.uncommitted=true for a snapshot since
+ // build2's version module by default does not allow distribution of
+ // uncommitted projects.
+ //
run_b (o,
"dist:", (dir_path (cfg) /= p.name.string ()).representation (),
"config.dist.root=" + dr.representation (),
"config.dist.archives=tar.gz",
- "config.dist.checksums=sha256");
+ "config.dist.checksums=sha256",
+ (uncommitted && *uncommitted
+ ? "config.dist.uncommitted=true"
+ : nullptr));
// This is the canonical package archive name that we expect dist to
// produce.
@@ -297,7 +348,7 @@ namespace bdep
//
// See if this is a VCS repository we recognize.
//
- if (ctrl && git_repository (prj))
+ if (ctrl && git_repo)
{
// Checkout the build2-control branch into a separate working tree not
// to interfere with the user's stuff.
diff --git a/bdep/release.cli b/bdep/release.cli
index 651288c..c90ec29 100644
--- a/bdep/release.cli
+++ b/bdep/release.cli
@@ -2,6 +2,8 @@
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
+include <set>;
+
include <bdep/common.cli>;
"\section=1"
@@ -151,6 +153,13 @@ namespace bdep
"Open the development cycle with the next major version."
}
+ std::set<string> --force
+ {
+ "<check>",
+ "Force releasing, disabling the specified check. Repeat this option to
+ disable multiple checks."
+ }
+
bool --yes|-y
{
"Don't prompt for confirmation before releasing."
diff --git a/bdep/release.cxx b/bdep/release.cxx
index dfa092c..cb4cac9 100644
--- a/bdep/release.cxx
+++ b/bdep/release.cxx
@@ -66,17 +66,19 @@ namespace bdep
static void
plan_tag (const cmd_release_options& o, project& prj, const status& st)
{
- // While there is nothing wrong with having uncommitted changes while
- // tagging, in our case we may end up with a wrong tag if the version in
- // the (modified) manifest does not correspond to the latest commit.
+ // Note: not forcible. While there is nothing wrong with having
+ // uncommitted changes while tagging, in our case we may end up with a
+ // wrong tag if the version in the (modified) manifest does not correspond
+ // to the latest commit.
//
// Note that if we are called as part of releasing a new revision, then
- // the project will have some changes staged (see plan_revision() for
+ // the project may have some changes staged (see plan_revision() for
// details).
//
if ((st.staged && !o.revision ()) || st.unstaged)
fail << "project directory has uncommitted changes" <<
- info << "run 'git status' for details";
+ info << "run 'git status' for details" <<
+ info << "use 'git stash' to temporarily hide the changes";
// All the versions are the same sans the revision. Note that our version
// can be either current (--tag mode) or release (part of the release).
@@ -86,12 +88,26 @@ namespace bdep
? *pkg.release_version
: pkg.current_version);
- if (cv.snapshot ())
- fail << "current version " << cv << " is a snapshot";
+ // It could be desirable to tag a snapshot for some kind of a pseudo-
+ // release. For example, tag a snapshot for QA or some such. Note: can't
+ // happen as part of a release or revision.
+ //
+ if (cv.snapshot () && o.force ().find ("snapshot") == o.force ().end ())
+ fail << "current version " << cv << " is a snapshot"<<
+ info << "use --force=snapshot to tag anyway";
// Canonical version tag without epoch or revision.
//
- prj.tag = "v" + cv.string_project ();
+ // For tagging a snapshot we need to use the actual package version
+ // (replacing .z with the actual snapshot information). Note: for
+ // snapshots we are always tagging the current version (see above).
+ //
+ const standard_version& v (
+ cv.latest_snapshot ()
+ ? package_version (o, pkg.manifest.directory ())
+ : cv);
+
+ prj.tag = "v" + v.string_project ();
// Replace the existing tag only if this is a revision.
//
@@ -104,9 +120,14 @@ namespace bdep
// There could be changes already added to the index but otherwise the
// repository should be clean.
//
- if (st.unstaged)
+ // Note: not forcible. Generally, we don't touch unstanged changes (which
+ // include untracked files).
+ //
+ if (st.unstaged && !o.no_commit ())
fail << "project directory has unstaged changes" <<
- info << "run 'git status' for details";
+ info << "run 'git status' for details" <<
+ info << "use 'git add' to add the changes to this commit" <<
+ info << "use 'git stash' to temporarily hide the changes";
// All the versions are the same sans the revision. Note that our version
// can be either current (--open mode) or release (part of the release).
@@ -151,10 +172,16 @@ namespace bdep
"" /* snapshot_id */);
};
+ // Note: not forcible. The following (till the end of the function) checks
+ // prevent skipping a release. Hard to think of a use case but we probably
+ // could allow this as it doesn't break anything (released versions need
+ // not be contiguous). Let's, however, postpone this until a real use
+ // case comes up in order not to complicate things needlessly.
+ //
if (cv.snapshot ())
{
- // The cv variable refers the current version as the release version
- // cannot be a snapshot.
+ // The cv variable refers to the current version since the release
+ // version cannot be a snapshot.
//
assert (!pkg.release_version);
@@ -209,9 +236,14 @@ namespace bdep
// There could be changes already added to the index but otherwise the
// repository should be clean.
//
- if (st.unstaged)
+ // Note: not forcible. Generally, we don't touch unstanged changes (which
+ // include untracked files).
+ //
+ if (st.unstaged && !o.no_commit ())
fail << "project directory has unstaged changes" <<
- info << "run 'git status' for details";
+ info << "run 'git status' for details" <<
+ info << "use 'git add' to add the changes to this commit" <<
+ info << "use 'git stash' to temporarily hide the changes";
// All the current versions are the same sans the revision.
//
@@ -219,6 +251,9 @@ namespace bdep
// Change the release version to the next (pre-)release.
//
+ // Note: not forcible. The following (till the end of the function) checks
+ // prevent skipping a release. The same reasoning as in plan_open().
+ //
standard_version rv;
if (cv.snapshot ())
{
@@ -319,19 +354,35 @@ namespace bdep
// There must be changes already added to the index but otherwise the
// repository should be clean.
//
- if (st.unstaged)
+ // Note: not forcible. Generally, we don't touch unstanged changes (which
+ // include untracked files).
+ //
+ if (st.unstaged && !o.no_commit ())
fail << "project directory has unstaged changes" <<
- info << "run 'git status' for details";
+ info << "run 'git status' for details" <<
+ info << "use 'git add' to add the changes to this commit" <<
+ info << "use 'git stash' to temporarily hide the changes";
- if (!st.staged)
+ // Note: the use-case for forcing would be to create a commit to be
+ // squashed later.
+ //
+ // Also, don't complain if we are not committing.
+ //
+ if (!st.staged &&
+ !o.no_commit () &&
+ o.force ().find ("unchanged") == o.force ().end ())
fail << "project directory has no staged changes" <<
info << "revision increment must be committed together with "
- << "associated changes";
+ << "associated changes" <<
+ info << "use --force=unchanged to release anyway";
// All the current versions are the same sans the revision.
//
const standard_version& cv (prj.packages.front ().current_version);
+ // Note: not forcible. Doesn't seem to make sense to release a revision
+ // for snapshot (just release another snapshot).
+ //
if (cv.snapshot ())
fail << "current version " << cv << " is a snapshot";
@@ -460,8 +511,12 @@ namespace bdep
return true;
}));
+ //
// Validate the *-file manifest values expansion.
//
+ // Note: not forcible. Allowing releasing broken packages we are just
+ // asking for trouble and long mailing list threads.
+ //
m.load_files ([&f] (const string& n, const path& p)
{
path vf (f.directory () / p);
@@ -696,8 +751,7 @@ namespace bdep
catch (const io_error& e)
{
fail << "unable to read/write " << p.manifest << ": " << e <<
- info << "run 'git -C " << prj.path << " checkout -- ./' to revert "
- << "any changes and try again";
+ info << "use 'git checkout' to revert any changes and try again";
}
}
@@ -782,14 +836,12 @@ namespace bdep
{
// If we are releasing, then the release/revision version have
// already been written to the manifests and the changes have been
- // committed. Thus, the user should re-try with the --open option
+ // committed. Thus, the user should re-try with the --open option
// in this case.
//
fail << "unable to read/write " << p.manifest << ": " << e <<
- info << "run 'git -C " << prj.path << " checkout -- ./' to revert "
- << "any changes and try again" << (pkg.release_version
- ? " with --open"
- : "");
+ info << "use 'git checkout' to revert any changes and try again"
+ << (pkg.release_version ? " with --open" : "");
}
}
diff --git a/tests/publish.testscript b/tests/publish.testscript
index 7913272..df3a817 100644
--- a/tests/publish.testscript
+++ b/tests/publish.testscript
@@ -37,21 +37,25 @@ init += $cxx -d prj 2>! &prj/**/bootstrap/***
windows = ($cxx.target.class == 'windows')
+g = git -C prj >! 2>!
+
# Note that using the same package name and version for tests may result in
# duplicate submissions. We will use unique version for each test,
# incrementing the patch version for 1.0.X.
#
-# Next version to use: 1.0.15
+# Next version to use: 1.0.19
#
: submit
:
{
test.arguments += --control 'none'
+ +$clone_prj
+
: single-pkg
:
{
- test.arguments += --simulate 'success'
+ test.arguments += --force=uncommitted --simulate 'success'
: single-cfg
:
@@ -65,7 +69,7 @@ windows = ($cxx.target.class == 'windows')
upgrade prj/1.0.1
submitting prj-1.0.1.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.1)?%
+ %package submission is queued(: \.*prj/1.0.1)?%d
%reference: .{12}%
EOE
}
@@ -90,12 +94,30 @@ windows = ($cxx.target.class == 'windows')
$* --all 2>'error: multiple configurations specified for publish' != 0
}
+
+ : snapshot
+ :
+ {
+ $clone_root_prj;
+ $init -C @cfg &prj-cfg/***;
+ sed -i -e 's/^(version:) .*$/\1 1.0.15-a.0.z/' prj/manifest;
+
+ $* 2>>EOE != 0;
+ synchronizing:
+ upgrade prj/1.0.15-a.0.19700101000000
+ error: package prj version 1.0.15-a.0.19700101000000 is a snapshot
+ EOE
+
+ $* --force=snapshot 2>>~%EOE% != 0
+ error: package prj version 1.0.15-a.0.19700101000000 is a snapshot
+ EOE
+ }
}
: multi-pkg
:
{
- test.arguments += --simulate 'success'
+ test.arguments += --force=uncommitted --simulate 'success'
+$new -t empty prj &prj/***
+$new --package -t lib libprj -d prj
@@ -112,11 +134,11 @@ windows = ($cxx.target.class == 'windows')
$* 2>>~%EOE%
submitting libprj-1.0.2.tar.gz
%.*
- %package submission is queued(: .*libprj/1\.0\.2)?%
+ %package submission is queued(: \.*libprj/1.0.2)?%d
%reference: .{12}%
submitting prj-1.0.2.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.2)?%
+ %package submission is queued(: \.*prj/1.0.2)?%d
%reference: .{12}%
EOE
}
@@ -135,7 +157,7 @@ windows = ($cxx.target.class == 'windows')
$* 2>>~%EOE%
submitting libprj-1.0.3.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.3)?%
+ %package submission is queued(: \.*prj/1.0.3)?%d
%reference: .{12}%
EOE
}
@@ -169,19 +191,118 @@ windows = ($cxx.target.class == 'windows')
%warning: publishing using staged build2 toolchain%?
continue? [y/n] submitting libprj-1.0.4.tar.gz
%.*
- %package submission is queued\(: .*libprj/1\\.0\\.4\)?%
+ %package submission is queued\(: \\.*libprj/1.0.4\)?%d
%reference: .{12}%
submitting prj-1.0.4.tar.gz
%.*
- %package submission is queued\(: .*prj/1\\.0\\.4\)?%
+ %package submission is queued\(: \\.*prj/1.0.4\)?%d
%reference: .{12}%
EOE
}
}
+ : commited-prj
+ :
+ {
+ test.arguments += --simulate 'success'
+
+ clone_prj = cp --no-cleanup -p -r ../prj ./ &prj/***
+
+ +$clone_prj
+
+ +$g config user.name 'Test Script'
+ +$g config user.email 'testscript@example.com'
+ +$g add '*'
+ +$g commit -m 'Create'
+
+ : final
+ :
+ {
+ $clone_prj;
+ $init -C @cfg &prj-cfg/***;
+ sed -i -e 's/^(version:) .*$/\1 1.0.16/' prj/manifest;
+
+ $* 2>>~%EOE% != 0;
+ synchronizing:
+ upgrade prj/1.0.16
+ error: project directory has uncommitted changes
+ info: run 'git status' for details
+ info: use 'git stash' to temporarily hide the changes
+ info: use --force=uncommitted to publish anyway
+ EOE
+
+ $g commit -a -m 'Version';
+
+ $* 2>>~%EOE%
+ submitting prj-1.0.16.tar.gz
+ %.*
+ %package submission is queued(: \.*prj/1.0.16)?%d
+ %reference: .{12}%
+ EOE
+ }
+
+ : snapshot
+ :
+ {
+ $clone_prj;
+ $init -C @cfg &prj-cfg/***;
+ sed -i -e 's/^(version:) .*$/\1 1.0.17-a.0.z/' prj/manifest;
+
+ $* 2>>~%EOE% != 0;
+ synchronizing:
+ % upgrade prj/1.0.17-a.0.\.+%d
+ error: project directory has uncommitted changes
+ info: run 'git status' for details
+ info: use 'git stash' to temporarily hide the changes
+ info: use --force=uncommitted to publish anyway
+ EOE
+
+ $g commit -a -m 'Version';
+
+ $* 2>>~%EOE% != 0;
+ synchronizing:
+ % upgrade prj/1.0.17-a.0.\.+%d
+ %error: package prj version 1.0.17-a.0.\.+ is a snapshot%d
+ info: use --force=snapshot to publish anyway
+ EOE
+
+ $* --force=snapshot 2>>~%EOE%
+ %submitting prj-1.0.17-a.0.\.+.tar.gz%d
+ %.*
+ %package submission is queued(: \.*prj/1.0.17-a.0.\.+)?%d
+ %reference: .{12}%
+ EOE
+ }
+ }
+
+ : non-vsc-prj
+ :
+ {
+ test.arguments += --simulate 'success'
+
+ clone_prj = cp --no-cleanup -p -r ../prj ./ &prj/***;
+
+ $clone_prj;
+ rm -r -f prj/.git;
+
+ $init -C @cfg &prj-cfg/***;
+ sed -i -e 's/^(version:) .*$/\1 1.0.18/' prj/manifest;
+
+ $* 2>>~%EOE%
+ synchronizing:
+ upgrade prj/1.0.18
+ submitting prj-1.0.18.tar.gz
+ %.*
+ %package submission is queued(: \.*prj/1.0.18)?%d
+ %reference: .{12}%
+ EOE
+ }
+
: failure
:
{
+ test.arguments += --force=uncommitted
+
: duplicate-archive
:
{
@@ -248,7 +369,8 @@ windows = ($cxx.target.class == 'windows')
# simulation. We specify it to enable the control branch-related
# functionality.
#
- test.arguments += --simulate 'success' --control 'http://example.com/rep.git'
+ test.arguments += --force=uncommitted --simulate 'success' \
+--control 'http://example.com/rep.git'
# Create the remote repository.
#
@@ -257,8 +379,6 @@ windows = ($cxx.target.class == 'windows')
+$clone_prj
- g = git -C prj >! 2>!
-
+$g config user.name 'Test Script'
+$g config user.email 'testscript@example.com'
@@ -291,7 +411,7 @@ windows = ($cxx.target.class == 'windows')
%.*
submitting prj-1.0.8.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.8)?%
+ %package submission is queued(: \.*prj/1.0.8)?%d
%reference: .{12}%
EOE
@@ -307,7 +427,7 @@ windows = ($cxx.target.class == 'windows')
%.*
submitting prj-1.0.9.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.9)?%
+ %package submission is queued(: \.*prj/1.0.9)?%d
%reference: .{12}%
EOE
@@ -325,7 +445,7 @@ windows = ($cxx.target.class == 'windows')
%.*
submitting prj-1.0.10.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.10)?%
+ %package submission is queued(: \.*prj/1.0.10)?%d
%reference: .{12}%
EOE
@@ -407,7 +527,7 @@ windows = ($cxx.target.class == 'windows')
%.*
submitting prj-1.0.12.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.12)?%
+ %package submission is queued(: \.*prj/1.0.12)?%d
%reference: .{12}%
EOE
@@ -425,7 +545,7 @@ windows = ($cxx.target.class == 'windows')
%.*
submitting prj-1.0.13.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.13)?%
+ %package submission is queued(: \.*prj/1.0.13)?%d
%reference: .{12}%
EOE
@@ -466,7 +586,7 @@ windows = ($cxx.target.class == 'windows')
%.*
submitting prj-1.0.14.tar.gz
%.*
- %package submission is queued(: .*prj/1\.0\.14)?%
+ %package submission is queued(: \.*prj/1.0.14)?%d
%reference: .{12}%
EOE
diff --git a/tests/release.testscript b/tests/release.testscript
index 98fddad..45d6867 100644
--- a/tests/release.testscript
+++ b/tests/release.testscript
@@ -61,94 +61,100 @@ log2 = $gp2 log '--pretty=format:"%d %s"'
: release
:
{
- test.arguments += --push
-
- : patch
+ : version
:
{
- $clone_root_repos;
+ test.arguments += --push
- $*;
+ : patch
+ :
+ {
+ $clone_root_repos;
- $clone2;
- $log2 >>:~%EOO%;
- % \(HEAD -> master, \.*\) Change version to 0.2.0-a.0.z%d
- (tag: v0.1.0) Release version 0.1.0
- Create
- EOO
+ $*;
- cat prj2/manifest >>~%EOO%
- %.*
- name: prj
- version: 0.2.0-a.0.z
- summary: prj executable
- %.*
+ $clone2;
+ $log2 >>:~%EOO%;
+ % \(HEAD -> master, \.*\) Change version to 0.2.0-a.0.z%d
+ (tag: v0.1.0) Release version 0.1.0
+ Create
EOO
- }
- : alpha
- :
- {
- $clone_root_repos;
+ cat prj2/manifest >>~%EOO%
+ %.*
+ name: prj
+ version: 0.2.0-a.0.z
+ summary: prj executable
+ %.*
+ EOO
+ }
- $* --alpha;
+ : alpha
+ :
+ {
+ $clone_root_repos;
- $clone2;
- $log2 >>:~%EOO%
- % \(HEAD -> master, \.*\) Change version to 0.1.0-a.1.z%d
- (tag: v0.1.0-a.1) Release version 0.1.0-a.1
- Create
- EOO
- }
+ $* --alpha;
- : beta
- :
- {
- $clone_root_repos;
+ $clone2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, \.*\) Change version to 0.1.0-a.1.z%d
+ (tag: v0.1.0-a.1) Release version 0.1.0-a.1
+ Create
+ EOO
+ }
- $* --beta;
+ : beta
+ :
+ {
+ $clone_root_repos;
- $clone2;
- $log2 >>:~%EOO%
- % \(HEAD -> master, \.*\) Change version to 0.1.0-b.1.z%d
- (tag: v0.1.0-b.1) Release version 0.1.0-b.1
- Create
- EOO
- }
+ $* --beta;
- : minor
- :
- {
- $clone_root_repos;
+ $clone2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, \.*\) Change version to 0.1.0-b.1.z%d
+ (tag: v0.1.0-b.1) Release version 0.1.0-b.1
+ Create
+ EOO
+ }
- $* --minor;
+ : minor
+ :
+ {
+ $clone_root_repos;
- $clone2;
- $log2 >>:~%EOO%
- % \(HEAD -> master, \.*\) Change version to 0.3.0-a.0.z%d
- (tag: v0.2.0) Release version 0.2.0
- Create
- EOO
- }
+ $* --minor;
- : major
- :
- {
- $clone_root_repos;
+ $clone2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, \.*\) Change version to 0.3.0-a.0.z%d
+ (tag: v0.2.0) Release version 0.2.0
+ Create
+ EOO
+ }
- $* --major;
+ : major
+ :
+ {
+ $clone_root_repos;
- $clone2;
- $log2 >>:~%EOO%
- % \(HEAD -> master, \.*\) Change version to 1.1.0-a.0.z%d
- (tag: v1.0.0) Release version 1.0.0
- Create
- EOO
+ $* --major;
+
+ $clone2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, \.*\) Change version to 1.1.0-a.0.z%d
+ (tag: v1.0.0) Release version 1.0.0
+ Create
+ EOO
+ }
}
: open
:
{
+ test.arguments += --push
+
: beta
:
{
@@ -243,87 +249,107 @@ log2 = $gp2 log '--pretty=format:"%d %s"'
}
}
- : no-open
+ : no
:
{
- $clone_root_repos;
+ test.arguments += --push
- $* --no-open;
+ : open
+ :
+ {
+ $clone_root_repos;
- $clone2;
- $log2 >>:~%EOO%;
- % \(HEAD -> master, tag: v0.1.0, \.*\) Release version 0.1.0%d
- Create
- EOO
+ $* --no-open;
- $* --open;
+ $clone2;
+ $log2 >>:~%EOO%;
+ % \(HEAD -> master, tag: v0.1.0, \.*\) Release version 0.1.0%d
+ Create
+ EOO
- $pull2;
- $log2 >>:~%EOO%
- % \(HEAD -> master, \.*\) Change version to 0.2.0-a.0.z%d
- (tag: v0.1.0) Release version 0.1.0
- Create
- EOO
- }
+ $* --open;
- : no-tag
- :
- {
- $clone_root_repos;
+ $pull2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, \.*\) Change version to 0.2.0-a.0.z%d
+ (tag: v0.1.0) Release version 0.1.0
+ Create
+ EOO
+ }
- $* --no-tag;
+ : tag
+ :
+ {
+ $clone_root_repos;
- $clone2;
- $log2 >>:~%EOO%;
- % \(HEAD -> master, \.*\) Change version to 0.2.0-a.0.z%d
- Release version 0.1.0
- Create
- EOO
+ $* --no-tag;
- $* --tag 2>'error: current version 0.2.0-a.0.z is a snapshot' != 0
- }
+ $clone2;
+ $log2 >>:~%EOO%;
+ % \(HEAD -> master, \.*\) Change version to 0.2.0-a.0.z%d
+ Release version 0.1.0
+ Create
+ EOO
- : no-tag-no-open
- :
- {
- $clone_root_repos;
+ $* --tag 2>>EOE != 0;
+ error: current version 0.2.0-a.0.z is a snapshot
+ info: use --force=snapshot to tag anyway
+ EOE
- $* --no-tag --no-open;
+ $* --tag --force=snapshot;
- $clone2;
- $log2 >>:~%EOO%;
- % \(HEAD -> master, \.*\) Release version 0.1.0%d
- Create
- EOO
+ $pull2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, tag: v0.2.0-a.0.\.*.\.*\) Change version to 0.2.0-a.0.z%d
+ Release version 0.1.0
+ Create
+ EOO
+ }
- $* --tag;
+ : tag-open
+ :
+ {
+ $clone_root_repos;
- $pull2;
- $log2 >>:~%EOO%;
- % \(HEAD -> master, tag: v0.1.0, \.*\) Release version 0.1.0%d
- Create
- EOO
+ $* --no-tag --no-open;
- $* --open;
+ $clone2;
+ $log2 >>:~%EOO%;
+ % \(HEAD -> master, \.*\) Release version 0.1.0%d
+ Create
+ EOO
- $pull2;
- $log2 >>:~%EOO%
- % \(HEAD -> master, \.*\) Change version to 0.2.0-a.0.z%d
- (tag: v0.1.0) Release version 0.1.0
- Create
- EOO
- }
+ $* --tag;
- : no-commit
- :
- {
- $clone_root_repos;
+ $pull2;
+ $log2 >>:~%EOO%;
+ % \(HEAD -> master, tag: v0.1.0, \.*\) Release version 0.1.0%d
+ Create
+ EOO
+
+ $* --open;
+
+ $pull2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, \.*\) Change version to 0.2.0-a.0.z%d
+ (tag: v0.1.0) Release version 0.1.0
+ Create
+ EOO
+ }
+
+ : commit
+ :
+ {
+ $clone_root_repos;
- $* --no-commit 2>'error: both --push and --no-commit specified' != 0
+ $* --no-commit 2>'error: both --push and --no-commit specified' != 0
+ }
}
: validate-manifest
{
+ test.arguments += --push
+
: file-value
:
{
@@ -363,6 +389,31 @@ log2 = $gp2 log '--pretty=format:"%d %s"'
EOE
}
}
+
+ : unstaged
+ :
+ {
+ $clone_root_repos;
+ echo '' >+ prj/manifest;
+
+ $* 2>>EOE != 0;
+ error: project directory has unstaged changes
+ info: run 'git status' for details
+ info: use 'git add' to add the changes to this commit
+ info: use 'git stash' to temporarily hide the changes
+ EOE
+
+ $* --no-commit;
+
+ $gp commit -a -m 'Release version';
+ $* --tag --push;
+
+ $clone2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, tag: v0.1.0, \.*\) Release version%d
+ Create
+ EOO
+ }
}
: revision
@@ -371,17 +422,74 @@ log2 = $gp2 log '--pretty=format:"%d %s"'
+$clone_root_repos
+$* --no-open --push
- +echo '' >+ prj/manifest
- +$gp add manifest
+ test.arguments += --revision
- test.arguments += --revision --push
+ : changes-staged
+ :
+ {
+ test.arguments += --push
- : default
+ +$clone_repos
+
+ +echo '' >+ prj/manifest
+ +$gp add manifest
+
+ : default
+ :
+ {
+ $clone_repos;
+
+ $* 2>>~%EOE%;
+ %Updated tag 'v0.1.0' \(was \.*\)%d
+ EOE
+
+ $clone2;
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, tag: v0.1.0, \.*\) Release version 0.1.0\+1%d
+ Release version 0.1.0
+ Create
+ EOO
+ }
+
+ : no-tag
+ :
+ {
+ $clone_repos;
+
+ $* --no-tag;
+
+ $clone2;
+ $log2 >>:~%EOO%;
+ % \(HEAD -> master, \.*\) Release version 0.1.0\+1%d
+ (tag: v0.1.0) Release version 0.1.0
+ Create
+ EOO
+
+ $release --tag --push --yes -d prj;
+
+ $pull2 --tags; # Updates the existing local tag.
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, tag: v0.1.0, \.*\) Release version 0.1.0\+1%d
+ Release version 0.1.0
+ Create
+ EOO
+ }
+ }
+
+ : no-changes-staged
:
{
+ test.arguments += --push
+
$clone_repos;
- $* 2>>~%EOE%;
+ $* 2>>~%EOE% != 0;
+ error: project directory has no staged changes
+ info: revision increment must be committed together with associated changes
+ info: use --force=unchanged to release anyway
+ EOE
+
+ $* --force=unchanged 2>>~%EOE%;
%Updated tag 'v0.1.0' \(was \.*\)%d
EOE
@@ -393,26 +501,62 @@ log2 = $gp2 log '--pretty=format:"%d %s"'
EOO
}
- : no-tag
+ : unstaged
:
{
$clone_repos;
- $* --no-tag;
+ echo '' >+ prj/manifest;
+
+ $* 2>>EOE != 0;
+ error: project directory has unstaged changes
+ info: run 'git status' for details
+ info: use 'git add' to add the changes to this commit
+ info: use 'git stash' to temporarily hide the changes
+ EOE
+
+ $* --no-commit;
+
+ $gp commit -a -m 'Release revision';
+ $release --tag --push --yes -d prj;
$clone2;
- $log2 >>:~%EOO%;
- % \(HEAD -> master, \.*\) Release version 0.1.0\+1%d
- (tag: v0.1.0) Release version 0.1.0
+ $log2 >>:~%EOO%
+ % \(HEAD -> master, tag: v0.1.0, \.*\) Release revision%d
+ Release version 0.1.0
Create
EOO
+ }
+ }
- $release --tag --push --yes -d prj;
+ : open
+ :
+ {
+ : unstaged
+ :
+ {
+ $clone_root_repos;
+
+ $* --no-open;
+
+ echo '' >+ prj/manifest;
- $pull2 --tags; # Updates the existing local tag.
+ $* --open 2>>EOE != 0;
+ error: project directory has unstaged changes
+ info: run 'git status' for details
+ info: use 'git add' to add the changes to this commit
+ info: use 'git stash' to temporarily hide the changes
+ EOE
+
+ $* --open --no-commit;
+
+ $gp commit -a -m 'Open dev cycle';
+ $gp push origin HEAD --tags;
+
+ $clone2;
$log2 >>:~%EOO%
- % \(HEAD -> master, tag: v0.1.0, \.*\) Release version 0.1.0\+1%d
- Release version 0.1.0
+ % \(HEAD -> master, \.*\) Open dev cycle%d
+ (tag: v0.1.0) Release version 0.1.0
Create
EOO
}