# # # add_dir "tests/m_selector" # # add_dir "tests/u_selector" # # add_file "tests/m_selector/__driver__.lua" # content [595d0882c8a144c189c960a4108a993a5c91cef2] # # add_file "tests/u_selector/__driver__.lua" # content [8fe1f6a14eb1c3ce47dc753495c3b5fe1d807e97] # # patch "NEWS" # from [730ace914a4621c491e14e302834289f77ed52de] # to [9cd3c7c3f2e2082f369020eb51b863462a8e584f] # # patch "cmd_merging.cc" # from [22376019b500781e104580a1dfa1678954e15872] # to [24996c053cd6ce5bfbe9466e9d4bbc36fe071c3f] # # patch "monotone.texi" # from [48bab75212b595ebbd07ce72fb3442531ed3530a] # to [45b376c07ebdff41d56cbf7ca055b845f0590621] # # patch "selectors.cc" # from [cab93c9e7cfddc4e88626713b1b94f07d489924b] # to [91d924b52e55b60329cba63adac1af6d874014d0] # # patch "work.cc" # from [8639fa3a282cb2ce24dd2b582d9be4ad833b43ac] # to [c599d6997fd914394ef1143ab131c0fc0002eeaf] # # patch "work.hh" # from [37d90e812bd3f1eff977682b7e363036b4da4f5f] # to [e78bc57d1e78333c06e831ec917384eecbe3c44f] # ============================================================ --- tests/m_selector/__driver__.lua 595d0882c8a144c189c960a4108a993a5c91cef2 +++ tests/m_selector/__driver__.lua 595d0882c8a144c189c960a4108a993a5c91cef2 @@ -0,0 +1,31 @@ +include("common/selectors.lua") +mtn_setup() + +addfile("testfile", "blah blah") +commit("testbranch", "this is revision one") +REV1=base_revision() + +writefile("testfile", "stuff stuff") +commit("testbranch", "this is revision number two") +REV2=base_revision() + +writefile("testfile", "foobar") +commit("testbranch", "this is revision number three") +REV3=base_revision() + +check(mtn("comment", REV2, "revision 2 comment"), 0, true, false) + +-- changelogs + +selmap("m:*one*", {REV1}) +selmap("m:*two*", {REV2}) +selmap("m:*three*", {REV3}) +selmap("m:*revision*", {REV1, REV2, REV3}) +selmap("m:*number*", {REV2, REV3}) +selmap("m:*foobar*", {}) + +-- comments + +selmap("m:revision*", {REV2}) +selmap("m:*2*", {REV2}) +selmap("m:*comment*", {REV2}) ============================================================ --- tests/u_selector/__driver__.lua 8fe1f6a14eb1c3ce47dc753495c3b5fe1d807e97 +++ tests/u_selector/__driver__.lua 8fe1f6a14eb1c3ce47dc753495c3b5fe1d807e97 @@ -0,0 +1,52 @@ +include("common/selectors.lua") +mtn_setup() + +addfile("testfile", "blah blah") +commit("testbranch", "this is revision one") +REV1=base_revision() + +writefile("testfile", "stuff stuff") +commit("testbranch", "this is revision number two") +REV2=base_revision() + +writefile("testfile", "foobar") +commit("testbranch", "this is revision number three") +REV3=base_revision() + +-- no updates yet + +check(mtn("automate", "select", "u:"), 1, true, false) + +-- update to rev1 from rev3 + +check(mtn("update", "-r", REV1), 0, true, false) +selmap("u:", {REV3}) + +-- update to rev2 from rev1 + +check(mtn("update", "-r", REV2), 0, true, false) +selmap("u:", {REV1}) + +-- update back to rev1 from rev2 + +check(mtn("update", "-r", "u:"), 0, true, false) +selmap("u:", {REV2}) + +-- finally update back to rev3 + +check(mtn("update"), 0, true, false) +selmap("u:", {REV1}) + +-- log the update rev + +check(mtn("log", "-r", "u:", "--no-graph", "--brief"), 0, true, false) +check(qgrep(REV1, "stdout")) +check(not qgrep(REV2, "stdout")) +check(not qgrep(REV3, "stdout")) + +-- log back to the update rev + +check(mtn("log", "--to", "u:", "--no-graph", "--brief"), 0, true, false) +check(not qgrep(REV1, "stdout")) +check(qgrep(REV2, "stdout")) +check(qgrep(REV3, "stdout")) ============================================================ --- NEWS 730ace914a4621c491e14e302834289f77ed52de +++ NEWS 9cd3c7c3f2e2082f369020eb51b863462a8e584f @@ -77,6 +77,10 @@ - Additional '--revision' option for 'mtn log' allows logging of selected sets of revisions. + - Additional 'u:' and 'm:' selector types for selecting the revision the + workspace was last updated from and revisions matching specified + message globs in changelog and comment certs. + Internal - Using 64 bit integer values to represent dates internally. This ============================================================ --- cmd_merging.cc 22376019b500781e104580a1dfa1678954e15872 +++ cmd_merging.cc 24996c053cd6ce5bfbe9466e9d4bbc36fe071c3f @@ -300,6 +300,7 @@ CMD(update, "update", "", CMD_REF(worksp merged_roster, remaining); // small race condition here... FIXME: what is it? + work.put_update_id(old_rid); work.put_work_rev(remaining); work.update_any_attrs(db); work.maybe_update_inodeprints(db); ============================================================ --- monotone.texi 48bab75212b595ebbd07ce72fb3442531ed3530a +++ monotone.texi 45b376c07ebdff41d56cbf7ca055b845f0590621 @@ -2764,6 +2764,10 @@ @heading Selectors in detail Uses selector type @code{d}. For example, @code{d:2004-04} matches @code{date} certs where the cert value begins with @code{2004-04}. This selector also accepts expanded date syntax (see below). address@hidden Message selection +Uses selector type @code{m}. For example @code{m:*foobar*} matches address@hidden and @code{comment} certs where the cert value +contains the glob @code{*foobar*}. @item "Earlier or equal than" selection Uses selector type @code{e}. For example, @code{e:2004-04-25} matches @code{date} certs where the cert value is less or equal than @@ -2784,6 +2788,24 @@ @heading Selectors in detail revision IDs which are the parent of the revision ID which begins with @code{0f3a}. If you give a bare @code{p:}, monotone will require you to be in a workspace, and query the parent of the base workspace revision. address@hidden Update selection +Uses selector type @code{u}. This selector must be used from within a +workspace and must not have any associated value. It matches the base +revision ID of the workspace before the last @command{update} command +was executed. This can be useful for reviewing incoming +revisions. After each update operation, or at least before the next +update operation, run a command similar to the following: address@hidden +$ mtn log --to u: --diffs address@hidden smallexample +to log all revisions back to the last update. It can also be +used for quickly jumping between two different revisions. For example, +the following command: address@hidden +$ mtn update -r u: address@hidden smallexample +will update back to the previous update revision. Repeating this +command will swap the current and previous update revision. @item Tag selection Uses selector type @code{t}. For example, @code{t:monotone-0.11} matches @code{tag} certs where the cert value begins with @code{monotone-0.11}. ============================================================ --- selectors.cc cab93c9e7cfddc4e88626713b1b94f07d489924b +++ selectors.cc 91d924b52e55b60329cba63adac1af6d874014d0 @@ -42,7 +42,9 @@ enum selector_type sel_cert, sel_earlier, sel_later, + sel_message, sel_parent, + sel_update, sel_unknown }; @@ -105,9 +107,15 @@ decode_selector(project_t & project, case 'e': type = sel_earlier; break; + case 'm': + type = sel_message; + break; case 'p': type = sel_parent; break; + case 'u': + type = sel_update; + break; default: W(F("unknown selector type: %c") % sel[0]); break; @@ -194,6 +202,19 @@ decode_selector(project_t & project, origin::internal); } break; + case sel_update: + E(sel.empty(), origin::user, + F("no value is allowed with the update selector u:")); + { + workspace work(opts, lua, F("the update selector u: refers to the " + "revision before the last update in the " + "workspace")); + revision_id update_id; + work.get_update_id(update_id); + sel = encode_hexenc(update_id.inner()(), origin::internal); + } + break; + default: break; } } @@ -251,6 +272,10 @@ complete_one_selector(project_t & projec project.db.select_parent(value, completions); break; + case sel_update: + project.db.complete(value, completions); + break; + case sel_author: project.db.select_cert(author_cert_name(), value, completions); break; @@ -280,6 +305,16 @@ complete_one_selector(project_t & projec project.db.select_date(value, ">", completions); break; + case sel_message: + { + set changelogs, comments; + project.db.select_cert(changelog_cert_name(), value, changelogs); + project.db.select_cert(comment_cert_name(), value, comments); + completions.insert(changelogs.begin(), changelogs.end()); + completions.insert(comments.begin(), comments.end()); + } + break; + case sel_cert: { I(!value.empty()); ============================================================ --- work.cc 8639fa3a282cb2ce24dd2b582d9be4ad833b43ac +++ work.cc c599d6997fd914394ef1143ab131c0fc0002eeaf @@ -53,6 +53,7 @@ static char const revision_file_name[] = static char const options_file_name[] = "options"; static char const user_log_file_name[] = "log"; static char const revision_file_name[] = "revision"; +static char const update_file_name[] = "update"; static void get_revision_path(bookkeeping_path & m_path) @@ -89,6 +90,13 @@ get_user_log_path(bookkeeping_path & ul_ L(FL("user log path is %s") % ul_path); } +static void +get_update_path(bookkeeping_path & update_path) +{ + update_path = bookkeeping_root / update_file_name; + L(FL("update path is %s") % update_path); +} + // bool @@ -230,6 +238,33 @@ workspace::put_work_rev(revision_t const write_data(rev_path, rev_data); } +void +workspace::get_update_id(revision_id & update_id) +{ + data update_data; + bookkeeping_path update_path; + get_update_path(update_path); + E(file_exists(update_path), origin::user, + F("no update has occurred in this workspace")); + + read_data(update_path, update_data); + + update_id = revision_id(decode_hexenc(update_data(), origin::internal), + origin::internal); + E(!null_id(update_id), origin::internal, + F("no update revision available")); +} + +void +workspace::put_update_id(revision_id const & update_id) +{ + data update_data(encode_hexenc(update_id.inner()(), origin::internal), + origin::internal); + bookkeeping_path update_path; + get_update_path(update_path); + write_data(update_path, update_data); +} + // structures derived from the work revision, the database, and possibly // the workspace ============================================================ --- work.hh 37d90e812bd3f1eff977682b7e363036b4da4f5f +++ work.hh e78bc57d1e78333c06e831ec917384eecbe3c44f @@ -169,6 +169,14 @@ public: // read the (partial) revision describing the current workspace. void get_work_rev(revision_t & rev); + // read the revision id that was the parent of this workspace before + // the last update occured. this is used for the u: (update) selector + void get_update_id(revision_id & update_id); + + // write the revision id that was the parent of this workspace before + // update completes. this is used for the u: (update) selector + void put_update_id(revision_id const & update_id); + // convenience wrappers around the above functions. // This returns the current roster, except it does not bother updating the