# # # add_file "maybe_workspace_updater.cc" # content [533b26f15fd2b160aaf9c2559877e754242c6fc7] # # add_file "maybe_workspace_updater.hh" # content [80862e8202b5451e46ba9361d57605460a3b1b0d] # # patch "Makefile.am" # from [2edf48887f6a0df8e512dffef242d9c3c9c7aa49] # to [e956bf588ace925767e267296316a673e7d4761a] # # patch "cmd_key_cert.cc" # from [0e5707233eb6e8687029ee792dfb75ad5668e3e2] # to [3358391c50f44b96815b3981addfba205010dc3c] # # patch "cmd_merging.cc" # from [97b6b695edfc97d361f655be497353a716976f54] # to [40235927c79e0be3ebdc416faf2718f8c63c37e8] # # patch "cmd_netsync.cc" # from [ecf459ce845f38db058d30ad04910d57ee1310f2] # to [1ac88de69ed8fc8c418e52f4cdcfa0746a892c8a] # # patch "cmd_ws_commit.cc" # from [cc042de7adfe4f6fdad0cb80fd86163af44f6442] # to [e8e241ac4a9de21a0f32bb296193c9765798213b] # # patch "options_list.hh" # from [4f0483db8e18e652824cd16c29d34ff3c8f31c79] # to [a4ce74aa1dfe7d727c444703a0f7f0bd1ad7f76c] # # patch "tests/resolve_conflicts_all_resolutions/merge-1" # from [4026a57330dfa66af8afa0eccd8aad978793991d] # to [8c59629b74fbb69e4f01b703a3e5f18fcd7a3cb5] # # patch "tests/resolve_conflicts_propagate/propagate-1" # from [b99435dfefbfda234d6fa35b2762eaf767cd1081] # to [a06cdf3cda8349b8dac49e81f63e256755a0dd68] # # patch "tests/resolve_conflicts_propagate/propagate-2" # from [834d66cde71ddbf1df55ac19f19ab2e19c8de118] # to [fc22f5cce910a723c5fe3eee405d9750c172f000] # # patch "tests/suspend/__driver__.lua" # from [dc12e9e387a9f96fb7c0d4e27745cbbed087e8f9] # to [61ffae4a8190abd0aab47c070550c458fc7a450f] # ============================================================ --- maybe_workspace_updater.cc 533b26f15fd2b160aaf9c2559877e754242c6fc7 +++ maybe_workspace_updater.cc 533b26f15fd2b160aaf9c2559877e754242c6fc7 @@ -0,0 +1,74 @@ +// Copyright (C) 2010 and later by various people +// see monotone commit logs for details and authors +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. + +#include "base.hh" +#include "maybe_workspace_updater.hh" + +#include "app_state.hh" +#include "option.hh" +#include "project.hh" +#include "revision.hh" +#include "work.hh" + +// defined in cmd_merging.cc +void update(app_state & app, args_vector const & args); + +namespace { + enum updatability { is_head, is_not_head, not_updatable }; + updatability get_updatability(app_state & app, project_t & project) + { + if (!workspace::found) + return not_updatable; + workspace work(app); + revision_t rev; + work.get_work_rev(rev); + if (rev.edges.size() != 1) + return not_updatable; + options workspace_opts; + work.get_options(workspace_opts); + std::set heads; + project.get_branch_heads(workspace_opts.branch, heads, false); + + revision_id parent = edge_old_revision(rev.edges.begin()); + if (heads.find(parent) != heads.end()) + return is_head; + else + return is_not_head; + } +} + +maybe_workspace_updater::maybe_workspace_updater(app_state & app, + project_t & project) + : can_do_update(app.opts.do_auto_update), + app(app), project(project) +{ + if (can_do_update) + can_do_update = (get_updatability(app, project) == is_head); +} + +void maybe_workspace_updater::maybe_do_update() +{ + if (can_do_update && (get_updatability(app, project) == is_not_head)) + { + update(app, args_vector()); + } + else + { + P(F("note: your workspaces have not been updated")); + } +} + +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- maybe_workspace_updater.hh 80862e8202b5451e46ba9361d57605460a3b1b0d +++ maybe_workspace_updater.hh 80862e8202b5451e46ba9361d57605460a3b1b0d @@ -0,0 +1,33 @@ +// Copyright (C) 2010 and later by various people +// see monotone commit logs for details and authors +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. +#ifndef __MAYBE_WORKSPACE_UPDATER_HH__ +#define __MAYBE_WORKSPACE_UPDATER_HH__ + +class app_state; +class project_t; + +class maybe_workspace_updater +{ + bool can_do_update; + app_state & app; + project_t & project; +public: + maybe_workspace_updater(app_state & app, project_t & project); + void maybe_do_update(); +}; + +#endif +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- Makefile.am 2edf48887f6a0df8e512dffef242d9c3c9c7aa49 +++ Makefile.am e956bf588ace925767e267296316a673e7d4761a @@ -95,6 +95,7 @@ MOST_SOURCES = \ restrictions.cc restrictions.hh \ hmac.cc hmac.hh \ string_queue.hh \ + maybe_workspace_updater.cc maybe_workspace_updater.hh \ merge_roster.cc merge_conflict.cc merge_roster.hh \ merge_content.cc merge_3way.cc merge_content.hh \ legacy.cc legacy.hh uri.cc uri.hh \ ============================================================ --- cmd_key_cert.cc 0e5707233eb6e8687029ee792dfb75ad5668e3e2 +++ cmd_key_cert.cc 3358391c50f44b96815b3981addfba205010dc3c @@ -20,6 +20,7 @@ #include "project.hh" #include "keys.hh" #include "key_store.hh" +#include "maybe_workspace_updater.hh" #include "transforms.hh" #include "vocab_cast.hh" @@ -303,7 +304,7 @@ CMD(approve, "approve", "", CMD_REF(revi CMD(approve, "approve", "", CMD_REF(review), N_("REVISION"), N_("Approves a particular revision"), "", - options::opts::branch) + options::opts::branch | options::opts::maybe_auto_update) { database db(app); key_store keys(app); @@ -312,6 +313,8 @@ CMD(approve, "approve", "", CMD_REF(revi if (args.size() != 1) throw usage(execid); + maybe_workspace_updater updater(app, project); + revision_id r; complete(app.opts, app.lua, project, idx(args, 0)(), r); guess_branch(app.opts, project, r); @@ -320,12 +323,14 @@ CMD(approve, "approve", "", CMD_REF(revi cache_user_key(app.opts, app.lua, db, keys, project); project.put_revision_in_branch(keys, r, app.opts.branch); + + updater.maybe_do_update(); } CMD(suspend, "suspend", "", CMD_REF(review), N_("REVISION"), N_("Suspends a particular revision"), "", - options::opts::branch) + options::opts::branch | options::opts::maybe_auto_update) { database db(app); key_store keys(app); @@ -334,6 +339,8 @@ CMD(suspend, "suspend", "", CMD_REF(revi if (args.size() != 1) throw usage(execid); + maybe_workspace_updater updater(app, project); + revision_id r; complete(app.opts, app.lua, project, idx(args, 0)(), r); guess_branch(app.opts, project, r); @@ -342,6 +349,8 @@ CMD(suspend, "suspend", "", CMD_REF(revi cache_user_key(app.opts, app.lua, db, keys, project); project.suspend_revision_in_branch(keys, r, app.opts.branch); + + updater.maybe_do_update(); } CMD(comment, "comment", "", CMD_REF(review), N_("REVISION [COMMENT]"), ============================================================ --- cmd_merging.cc 97b6b695edfc97d361f655be497353a716976f54 +++ cmd_merging.cc 40235927c79e0be3ebdc416faf2718f8c63c37e8 @@ -25,6 +25,7 @@ #include "work.hh" #include "safe_map.hh" #include "app_state.hh" +#include "maybe_workspace_updater.hh" #include "project.hh" #include "simplestring_xform.hh" #include "keys.hh" @@ -175,7 +176,8 @@ pick_branch_for_update(options & opts, d return switched_branch; } -static void +// also used from maybe_workspace_updater.cc +void update(app_state & app, args_vector const & args) { @@ -494,12 +496,15 @@ CMD(merge, "merge", "", CMD_REF(tree), " N_("Merges unmerged heads of a branch"), "", options::opts::branch | options::opts::date | options::opts::author | - options::opts::messages | options::opts::resolve_conflicts_opts) + options::opts::messages | options::opts::resolve_conflicts_opts | + options::opts::maybe_auto_update) { database db(app); key_store keys(app); project_t project(db); + maybe_workspace_updater updater(app, project); + if (!args.empty()) throw usage(execid); @@ -563,7 +568,7 @@ CMD(merge, "merge", "", CMD_REF(tree), " if (heads.size() > 1) P(F("note: branch '%s' still has %d heads; run merge again") % app.opts.branch % heads.size()); - P(F("note: your workspaces have not been updated")); + updater.maybe_do_update(); } CMD(propagate, "propagate", "", CMD_REF(tree), @@ -611,7 +616,7 @@ CMD(merge_into_dir, "merge_into_dir", "" N_("Merges one branch into a subdirectory in another branch"), "", options::opts::date | options::opts::author | options::opts::messages | - options::opts::resolve_conflicts_opts) + options::opts::resolve_conflicts_opts | options::opts::maybe_auto_update) { database db(app); key_store keys(app); @@ -621,6 +626,8 @@ CMD(merge_into_dir, "merge_into_dir", "" if (args.size() != 3) throw usage(execid); + maybe_workspace_updater updater(app, project); + project.get_branch_heads(typecast_vocab(idx(args, 0)), src_heads, app.opts.ignore_suspend_certs); project.get_branch_heads(typecast_vocab(idx(args, 1)), dst_heads, @@ -756,6 +763,8 @@ CMD(merge_into_dir, "merge_into_dir", "" guard.commit(); P(F("[merged] %s") % merged); } + + updater.maybe_do_update(); } CMD(merge_into_workspace, "merge_into_workspace", "", CMD_REF(tree), @@ -881,7 +890,8 @@ CMD(explicit_merge, "explicit_merge", "" N_("The results of the merge are placed on the branch specified by " "DEST-BRANCH."), options::opts::date | options::opts::author | - options::opts::messages | options::opts::resolve_conflicts_opts) + options::opts::messages | options::opts::resolve_conflicts_opts | + options::opts::maybe_auto_update) { database db(app); key_store keys(app); @@ -892,6 +902,8 @@ CMD(explicit_merge, "explicit_merge", "" if (args.size() != 3) throw usage(execid); + maybe_workspace_updater updater(app, project); + complete(app.opts, app.lua, project, idx(args, 0)(), left); complete(app.opts, app.lua, project, idx(args, 1)(), right); branch = typecast_vocab(idx(args, 2)); @@ -911,6 +923,8 @@ CMD(explicit_merge, "explicit_merge", "" merge_two(app.opts, app.lua, project, keys, left, right, branch, string("explicit merge"), std::cout, false); + + updater.maybe_do_update(); } namespace ============================================================ --- cmd_netsync.cc ecf459ce845f38db058d30ad04910d57ee1310f2 +++ cmd_netsync.cc 1ac88de69ed8fc8c418e52f4cdcfa0746a892c8a @@ -25,6 +25,7 @@ #include "vocab_cast.hh" #include "platform-wrapped.hh" #include "app_state.hh" +#include "maybe_workspace_updater.hh" #include "project.hh" #include "work.hh" #include "database.hh" @@ -549,12 +550,15 @@ CMD(pull, "pull", "", CMD_REF(network), N_("This pulls all branches that match the pattern given in PATTERN " "from the netsync server at the address ADDRESS."), options::opts::max_netsync_version | options::opts::min_netsync_version | - options::opts::set_default | options::opts::exclude) + options::opts::set_default | options::opts::exclude | + options::opts::maybe_auto_update) { database db(app); key_store keys(app); project_t project(db); + maybe_workspace_updater updater(app, project); + netsync_connection_info info; extract_client_connection_info(app.opts, app.lua, db, keys, project, args, info, false); @@ -564,6 +568,8 @@ CMD(pull, "pull", "", CMD_REF(network), run_netsync_protocol(app, app.opts, app.lua, project, keys, client_voice, sink_role, info); + + updater.maybe_do_update(); } CMD_AUTOMATE(pull, N_("[ADDRESS[:PORTNUMBER] [PATTERN ...]]"), @@ -592,12 +598,14 @@ CMD(sync, "sync", "", CMD_REF(network), "with the netsync server at the address ADDRESS."), options::opts::max_netsync_version | options::opts::min_netsync_version | options::opts::set_default | options::opts::exclude | - options::opts::key_to_push) + options::opts::key_to_push | options::opts::maybe_auto_update) { database db(app); key_store keys(app); project_t project(db); + maybe_workspace_updater updater(app, project); + netsync_connection_info info; extract_client_connection_info(app.opts, app.lua, db, keys, project, args, info); @@ -611,6 +619,8 @@ CMD(sync, "sync", "", CMD_REF(network), run_netsync_protocol(app, app.opts, app.lua, project, keys, client_voice, source_and_sink_role, info); + + updater.maybe_do_update(); } CMD_AUTOMATE(sync, N_("[ADDRESS[:PORTNUMBER] [PATTERN ...]]"), ============================================================ --- cmd_ws_commit.cc cc042de7adfe4f6fdad0cb80fd86163af44f6442 +++ cmd_ws_commit.cc e8e241ac4a9de21a0f32bb296193c9765798213b @@ -28,6 +28,7 @@ #include "xdelta.hh" #include "keys.hh" #include "key_store.hh" +#include "maybe_workspace_updater.hh" #include "simplestring_xform.hh" #include "database.hh" #include "roster.hh" @@ -491,7 +492,7 @@ CMD(disapprove, "disapprove", "", CMD_RE N_("Disapproves a particular revision"), "", options::opts::branch | options::opts::messages | options::opts::date | - options::opts::author) + options::opts::author | options::opts::maybe_auto_update) { database db(app); key_store keys(app); @@ -500,6 +501,8 @@ CMD(disapprove, "disapprove", "", CMD_RE if (args.size() != 1) throw usage(execid); + maybe_workspace_updater updater(app, project); + utf8 log_message(""); bool log_message_given; revision_id r; @@ -563,7 +566,7 @@ CMD(disapprove, "disapprove", "", CMD_RE "note: you may (or may not) wish to run '%s merge'") % prog_name); } - P(F("note: your workspaces have not been updated")); + updater.maybe_do_update(); } CMD(mkdir, "mkdir", "", CMD_REF(workspace), N_("[DIRECTORY...]"), ============================================================ --- options_list.hh 4f0483db8e18e652824cd16c29d34ff3c8f31c79 +++ options_list.hh a4ce74aa1dfe7d727c444703a0f7f0bd1ad7f76c @@ -91,6 +91,24 @@ OPT(automate_stdio_size, "automate-stdio } #endif +OPTSET(maybe_auto_update) +OPTVAR(maybe_auto_update, bool, do_auto_update, false) +OPTION(maybe_auto_update, yes_update, false, "update", + gettext_noop("automatically update the workspace, if it is clean and the base " + "revision is a head of an affected branch")) +#ifdef option_bodies +{ + do_auto_update = true; +} +#endif +OPTION(maybe_auto_update, no_update, false, "no-update", + gettext_noop("do not touch the workspace (default)")) +#ifdef option_bodies +{ + do_auto_update = false; +} +#endif + OPTSET(bind_opts) OPTVAR(bind_opts, std::list, bind_uris, ) OPTVAR(bind_opts, bool, bind_stdio, false) ============================================================ --- tests/resolve_conflicts_all_resolutions/merge-1 4026a57330dfa66af8afa0eccd8aad978793991d +++ tests/resolve_conflicts_all_resolutions/merge-1 8c59629b74fbb69e4f01b703a3e5f18fcd7a3cb5 @@ -14,3 +14,4 @@ mtn: [merged] 6363bd08ae08d7e57067ba6476 mtn: merged simple_file, simple_file mtn: replacing content of user_file, user_file with resolutions/user_file mtn: [merged] 6363bd08ae08d7e57067ba6476f76417c72f1a25 +mtn: note: your workspaces have not been updated ============================================================ --- tests/resolve_conflicts_propagate/propagate-1 b99435dfefbfda234d6fa35b2762eaf767cd1081 +++ tests/resolve_conflicts_propagate/propagate-1 a06cdf3cda8349b8dac49e81f63e256755a0dd68 @@ -6,3 +6,4 @@ mtn: [merged] a74c964afba9c299c81ec404e5 mtn: renaming thermostat.c to thermostat-westinghouse.c mtn: renaming thermostat.c to thermostat-honeywell.c mtn: [merged] a74c964afba9c299c81ec404e5233ad6faffadc1 +mtn: note: your workspaces have not been updated ============================================================ --- tests/resolve_conflicts_propagate/propagate-2 834d66cde71ddbf1df55ac19f19ab2e19c8de118 +++ tests/resolve_conflicts_propagate/propagate-2 fc22f5cce910a723c5fe3eee405d9750c172f000 @@ -2,3 +2,4 @@ mtn: no merge necessary; putting a74c964 mtn: [left] a74c964afba9c299c81ec404e5233ad6faffadc1 mtn: [right] 1337cb1059c4bc3e376b14381b43e9383c654da1 mtn: no merge necessary; putting a74c964afba9c299c81ec404e5233ad6faffadc1 in branch 'abe_branch' +mtn: note: your workspaces have not been updated ============================================================ --- tests/suspend/__driver__.lua dc12e9e387a9f96fb7c0d4e27745cbbed087e8f9 +++ tests/suspend/__driver__.lua 61ffae4a8190abd0aab47c070550c458fc7a450f @@ -12,7 +12,7 @@ selmap("h:testbranch", {REV2}) -- check that suspend hides things from the h: selector selmap("h:testbranch", {REV2}) -check(mtn("suspend", REV2)) +check(mtn("suspend", REV2), 0, nil, false) selmap("h:testbranch", {}) check(mtn("automate", "heads"), 0, true, false) @@ -48,7 +48,7 @@ OREV2=base_revision() -- now suspend the second branch and check it is gone when we list branches -check(mtn("suspend", OREV2)) +check(mtn("suspend", OREV2), 0, nil, false) check(mtn("ls", "branches"), 0, true, true) check(samelines("stdout", {"testbranch"})) @@ -66,7 +66,7 @@ selmap("h:otherbranch", {OREV2b}) -- Check that a revision suspended in one branch can still appear in another -check(mtn("approve", OREV2, "-b", "testbranch")) +check(mtn("approve", OREV2, "-b", "testbranch"), 0, nil, false) selmap("h:testbranch", {OREV2}) -- Check that update ignores the suspended revision when there is a non-suspended revision @@ -83,7 +83,7 @@ check(base_revision() == OREV1) -- Check that update complains about multiple heads when all candidates are suspended -check(mtn("suspend", OREV2b)) +check(mtn("suspend", OREV2b), 0, nil, false) check(mtn("up", "-r", OREV1, "-b", "otherbranch"), 0, false, false) check(mtn("up"), 1, false, false) check(base_revision() == OREV1)