#
# add_file "tests/t_heads_of_certs.at"
#
# patch "ChangeLog"
# from [18d49951f0df2a781f2ceafd29a120354915574c]
# to [7dc77508deaefb79b419ce4dc589473108cc93de]
#
# patch "automate.cc"
# from [7492b76019ac6578ecc8e1fec67025cff1ffbc39]
# to [75c816d6cf3f9eed414b97e0042a6e5c288d8cb1]
#
# patch "commands.cc"
# from [302aac08e63acc1f48aa29adbbdeeff58b1c782f]
# to [346cf7133214c507802ca85f90bb21199ea16125]
#
# patch "selectors.cc"
# from [af2e5813aba3cdf936fbcbb31dbb05ddf3690ccc]
# to [d0a7bf9c23c599de5785fbd9b65112bd09a0649d]
#
# patch "selectors.hh"
# from [54ed172da5c3a3c4721152012d831f51e693cab9]
# to [035142d5ca28095e65c7fd231ff8c86c043cb96a]
#
# patch "tests/t_heads_of_certs.at"
# from []
# to [2b52c4b5acdc54ec1a7e65bf308ae9f80fe00890]
#
# patch "testsuite.at"
# from [0053f6d5ae281707c89693dbf4e0c6b3c4a8b61c]
# to [dfef0f1ec4da1158f3c5ee928dc68abdf1db2dc2]
#
===============================================
--- ChangeLog 18d49951f0df2a781f2ceafd29a120354915574c
+++ ChangeLog 7dc77508deaefb79b419ce4dc589473108cc93de
@@ -1,3 +1,17 @@
+2005-07-18 Richard Levitte
+
+ * selectors.cc (decode_selectors): If we're at the beginning of
+ the composite selector string, parse h: if it's there. Takes a
+ couple of new arguments, to return a flag saying only the heads
+ of the selection should be used, and an input flag saying if the
+ current selector is the first or not.
+ (complete_selectors, parse_selector): Adjust.
+ * commands.cc (complete): Use the new "heads only" selector.
+ * automate.cc (automate_select): Dito.
+
+ * tests/t_heads_of_certs.at: New test.
+ * testsuite.at: Use it.
+
2005-07-17 Nathaniel Smith
* configure.ac, win32/monotone.iss, monotone.spec:
===============================================
--- automate.cc 7492b76019ac6578ecc8e1fec67025cff1ffbc39
+++ automate.cc 75c816d6cf3f9eed414b97e0042a6e5c288d8cb1
@@ -494,15 +494,29 @@
if (args.size() != 1)
throw usage(help_name);
+ bool get_heads = false;
std::vector >
- sels(selectors::parse_selector(args[0](), app));
+ sels(selectors::parse_selector(args[0](), get_heads, app));
// we jam through an "empty" selection on sel_ident type
- std::set completions;
+ std::set completions;
selectors::selector_type ty = selectors::sel_ident;
- selectors::complete_selector("", sels, ty, completions, app);
+ {
+ bool dummy_get_heads = false;
+ std::set completion_strings;
+ selectors::complete_selector("", sels, ty, dummy_get_heads,
+ completion_strings, app, true);
+ for (std::set::const_iterator i = completion_strings.begin();
+ i != completion_strings.end(); ++i)
+ completions.insert(revision_id(*i));
+ }
- for (std::set::const_iterator i = completions.begin();
+ if (get_heads && completions.size() > 1)
+ {
+ erase_ancestors(completions, app);
+ }
+
+ for (std::set::const_iterator i = completions.begin();
i != completions.end(); ++i)
output << *i << std::endl;
}
===============================================
--- commands.cc 302aac08e63acc1f48aa29adbbdeeff58b1c782f
+++ commands.cc 346cf7133214c507802ca85f90bb21199ea16125
@@ -429,28 +429,42 @@
return;
}
+ bool get_heads = false;
vector >
- sels(selectors::parse_selector(str, app));
+ sels(selectors::parse_selector(str, get_heads, app));
P(F("expanding selection '%s'\n") % str);
// we jam through an "empty" selection on sel_ident type
- set completions;
+ set completions;
selectors::selector_type ty = selectors::sel_ident;
- selectors::complete_selector("", sels, ty, completions, app);
+ {
+ bool dummy_get_heads = false;
+ std::set completion_strings;
+ selectors::complete_selector("", sels, ty, dummy_get_heads,
+ completion_strings, app, true);
+ for (std::set::const_iterator i = completion_strings.begin();
+ i != completion_strings.end(); ++i)
+ completions.insert(revision_id(*i));
+ }
N(completions.size() != 0,
F("no match for selection '%s'") % str);
+
+ if (get_heads && completions.size() > 1)
+ {
+ erase_ancestors(completions, app);
+ }
if (completions.size() > 1)
{
string err = (F("selection '%s' has multiple ambiguous expansions: \n") % str).str();
- for (set::const_iterator i = completions.begin();
+ for (set::const_iterator i = completions.begin();
i != completions.end(); ++i)
- err += (describe_revision(app, revision_id(*i)) + "\n");
+ err += (describe_revision(app, *i) + "\n");
N(completions.size() == 1, boost::format(err));
}
- completion = revision_id(*(completions.begin()));
- P(F("expanded to '%s'\n") % completion);
+ completion = *(completions.begin());
+ P(F("expanded to '%s'\n") % completion);
}
static void
===============================================
--- selectors.cc af2e5813aba3cdf936fbcbb31dbb05ddf3690ccc
+++ selectors.cc d0a7bf9c23c599de5785fbd9b65112bd09a0649d
@@ -15,13 +15,24 @@
static void
decode_selector(std::string const & orig_sel,
selector_type & type,
+ bool & get_heads,
std::string & sel,
- app_state & app)
+ app_state & app,
+ bool first_selector)
{
sel = orig_sel;
L(F("decoding selector '%s'\n") % sel);
+ if (first_selector)
+ {
+ if (sel[0] == 'h' && sel[1] == ':')
+ {
+ get_heads = true;
+ sel.erase(0,2);
+ }
+ }
+
std::string tmp;
if (sel.size() < 2 || sel[1] != ':')
{
@@ -70,12 +81,12 @@
}
sel.erase(0,2);
- /* a selector date-related should be validated */
+ /* a selector date-related should be validated */
if (sel_date==type || sel_later==type || sel_earlier==type)
{
N (app.lua.hook_expand_date(sel, tmp),
- F ("selector '%s' is not a valid date\n") % sel);
-
+ F ("selector '%s' is not a valid date\n") % sel);
+
if (tmp.size()<8 && (sel_later==type || sel_earlier==type))
tmp += "-01T00:00:00";
else if (tmp.size()<11 && (sel_later==type || sel_earlier==type))
@@ -94,16 +105,19 @@
complete_selector(std::string const & orig_sel,
std::vector > const & limit,
selector_type & type,
+ bool & get_heads,
std::set & completions,
- app_state & app)
+ app_state & app,
+ bool first_selector)
{
std::string sel;
- decode_selector(orig_sel, type, sel, app);
+ decode_selector(orig_sel, type, get_heads, sel, app, first_selector);
app.db.complete(type, sel, limit, completions);
}
std::vector >
parse_selector(std::string const & str,
+ bool & get_heads,
app_state & app)
{
std::vector > sels;
@@ -124,14 +138,16 @@
std::vector selector_strings;
copy(tokens.begin(), tokens.end(), back_inserter(selector_strings));
+ bool first = true;
for (std::vector::const_iterator i = selector_strings.begin();
i != selector_strings.end(); ++i)
{
std::string sel;
selector_type type = sel_unknown;
- decode_selector(*i, type, sel, app);
+ decode_selector(*i, type, get_heads, sel, app, first);
sels.push_back(std::make_pair(type, sel));
+ first = false;
}
}
===============================================
--- selectors.hh 54ed172da5c3a3c4721152012d831f51e693cab9
+++ selectors.hh 035142d5ca28095e65c7fd231ff8c86c043cb96a
@@ -35,10 +35,13 @@
complete_selector(std::string const & orig_sel,
std::vector > const & limit,
selector_type & type,
+ bool & get_heads,
std::set & completions,
- app_state & app);
+ app_state & app,
+ bool first_selector);
std::vector >
parse_selector(std::string const & str,
+ bool & get_heads,
app_state & app);
}; // namespace selectors
===============================================
--- tests/t_heads_of_certs.at
+++ tests/t_heads_of_certs.at 2b52c4b5acdc54ec1a7e65bf308ae9f80fe00890
@@ -0,0 +1,31 @@
+AT_SETUP([selecting arbitrary certs])
+MONOTONE_SETUP
+
+ADD_FILE(testfile, [this is just a file
+])
+COMMIT(testbranch)
+FIRST=`BASE_REVISION`
+
+AT_DATA(testfile, [Now, this is a different file
+])
+COMMIT(testbranch)
+SECOND=`BASE_REVISION`
+
+AT_DATA(testfile, [And we change it a third time
+])
+COMMIT(testbranch)
+THIRD=`BASE_REVISION`
+
+AT_CHECK(MONOTONE cert $FIRST testcert 'value=with=equal=signs')
+AT_CHECK(MONOTONE cert $SECOND testcert 'value')
+
+# Check that a log with no h: fails...
+AT_CHECK(MONOTONE log --revision 'c:testcert', [1], [ignore], [stderr])
+AT_CHECK(grep 'has multiple ambiguous expansions' stderr, [0], [ignore])
+
+# Check that a log with h: succeeds...
+AT_CHECK(MONOTONE log --revision='h:c:testcert', [], [stdout], [ignore])
+# Note that if the third revision is in the log, something else is wrong...
+AT_CHECK(grep $THIRD stdout, [1], [ignore], [ignore])
+
+AT_CLEANUP
===============================================
--- testsuite.at 0053f6d5ae281707c89693dbf4e0c6b3c4a8b61c
+++ testsuite.at dfef0f1ec4da1158f3c5ee928dc68abdf1db2dc2
@@ -674,3 +674,4 @@
m4_include(tests/t_restricted_diff_unchanged.at)
m4_include(tests/t_selector_globbing.at)
m4_include(tests/t_diff_external.at)
+m4_include(tests/t_heads_of_certs.at)