# # add_file "tests/t_select_cert.at" # # patch "ChangeLog" # from [b12880f36e18dc09123aaed4fa78431301ebea61] # to [2dc040b5874263b71fbe9de4aafdde121ecc5b8d] # # patch "commands.cc" # from [0f3716f5547c7cb58ee746eb730116642cfbc57f] # to [31b47303bf3e25d575783392652fd3cb721452ef] # # patch "commands.hh" # from [f2f45ab20f37d33f52054ae343a0b1a099494a35] # to [47e15e3250b284fb4308d4acfb3cc8e5cd4db749] # # patch "database.cc" # from [3cd127283c020d9afadec7daae6e0a7358d1b977] # to [6fd7af26382171e448ef373402c891d5a4bc6085] # # patch "monotone.texi" # from [4d4c00faec3b836fe34b711702de0f1e8368645b] # to [39658b68662d6e52e7554098c647d20f08f140dd] # # patch "std_hooks.lua" # from [c674787159fd451501ae52361e126505047f6bb2] # to [9010afddb6fcb4912dd061bf59962a035bcd5732] # # patch "tests/t_select_cert.at" # from [] # to [b28e5221a8c1d9cf4d4f30b0490a1fbe523dda63] # # patch "testsuite.at" # from [74588ac88436f19d8649499b2d21bec35a45908d] # to [dc31b9190c2473ad27f0f3c91c5944b7dca804fc] # --- ChangeLog +++ ChangeLog @@ -1,3 +1,15 @@ +2005-04-27 Richard Levitte + + * commands.hh: Add new selector to find arbitrary cert name and + value pairs. The syntax is 'c:{name}={value}'. + * commands.cc (decode_selector): Recognise it. + * database.cc (complete): Parse it. + * std_hooks.lua (expand_selector): Add an expansion for it. + * monotone.texi (Selectors): Document it. + + * tests/t_select_cert.at: Add test. + * testsuite.at: Use it. + 2005-04-26 Nathaniel Smith * sqlite/vdbeaux.c (MAX_6BYTE): Apply patch from --- commands.cc +++ commands.cc @@ -782,6 +782,9 @@ case 't': type = sel_tag; break; + case 'c': + type = sel_cert; + break; default: W(F("unknown selector type: %c\n") % sel[0]); break; --- commands.hh +++ commands.hh @@ -32,6 +32,7 @@ sel_date, sel_tag, sel_ident, + sel_cert, sel_unknown } selector_type; --- database.cc +++ database.cc @@ -1,3 +1,4 @@ +// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*- // copyright (C) 2002, 2003 graydon hoare // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) @@ -2196,6 +2197,33 @@ lim += (F("WHERE id GLOB '%s*'") % i->second).str(); } + else if (i->first == commands::sel_cert) + { + if (i->second.length() > 0) + { + size_t spot = i->second.find("="); + + if (spot != (size_t)-1) + { + string certname; + string certvalue; + + certname = i->second.substr(0, spot); + spot++; + certvalue = i->second.substr(spot); + lim += "SELECT id FROM revision_certs "; + lim += (F("WHERE name='%s' AND unbase64(value) glob '%s'") + % certname % certvalue).str(); + } + else + { + lim += "SELECT id FROM revision_certs "; + lim += (F("WHERE name='%s'") + % i->second).str(); + } + + } + } else if (i->first == commands::sel_unknown) { lim += "SELECT id FROM revision_certs "; --- monotone.texi +++ monotone.texi @@ -2271,11 +2271,19 @@ A selector is a combination of a selector type, which is a single ASCII character, followed by a @code{:} character and a selector -value. The value is matched against identifiers or certs, depending on -its type, in an attempt to match a single revision. Selectors are -matched as prefixes. The current set of selection types are: +string. All selectors strings except for selector type @code{c} +are just values. The value is matched against identifiers or certs, +depending on its type, in an attempt to match a single revision. +Selectors are matched as prefixes. The current set of selection +types are: @table @asis address@hidden Generic cert selector +Uses selector type @code{c}. The selector string has the syntax address@hidden or @address@hidden@var{value}. The former syntax will +select any revision that has a cert with that name, regardless of +value, the latter will match any revision that has a cert with that +name and value. Values to match for can have wildcards. @item Author selection Uses selector type @code{a}. For example, @code{a:graydon} matches @code{author} certs where the cert value begins with @code{graydon}. --- std_hooks.lua +++ std_hooks.lua @@ -385,6 +385,12 @@ function expand_selector(str) + -- something which looks like a generic cert pattern + if string.find(str, "^[^=]*=.*$") + then + return ("c:" .. str) + end + -- simple date patterns if string.find(str, "^19%d%d%-%d%d") or string.find(str, "^20%d%d%-%d%d") --- tests/t_select_cert.at +++ tests/t_select_cert.at @@ -0,0 +1,47 @@ +AT_SETUP([selecting arbitrary certs]) +MONOTONE_SETUP + +ADD_FILE(testfile, [this is just a file +]) +AT_CHECK(cp testfile testfile1) +COMMIT(testbranch) +FIRST=`BASE_REVISION` + +AT_DATA(testfile, [Now, this is a different file +]) +AT_CHECK(cp testfile testfile2) +COMMIT(testbranch) +SECOND=`BASE_REVISION` + +AT_DATA(testfile, [And we change it a third time +]) +AT_CHECK(cp testfile testfile3) +COMMIT(testbranch) + +AT_CHECK(MONOTONE cert $FIRST testcert 'value=with=equal=signs') +AT_CHECK(MONOTONE cert $SECOND testcert 'value') + +# Check that inexact values fail... +AT_CHECK(MONOTONE list certs 'c:testcert=value=', [1], [ignore], [stderr]) +AT_CHECK(grep 'no match for selection' stderr, [0], [ignore]) + +# Check that wild cards succeed... +AT_CHECK(MONOTONE list certs 'c:testcert=value=*', [], [ignore], [ignore]) + +# Check that wild cards succeed (this one becomes a misuse, because it will +# match two revisions)... +AT_CHECK(MONOTONE list certs 'c:testcert=value*', [1], [ignore], [stderr]) +AT_CHECK(grep 'has multiple ambiguous expansions' stderr, [0], [ignore]) + +# Check that no value succeeds... +AT_CHECK(MONOTONE list certs 'c:testcert', [1], [ignore], [stderr]) +AT_CHECK(grep 'has multiple ambiguous expansions' stderr, [0], [ignore]) + +# Check that exact value succeed... +AT_CHECK(MONOTONE update 'c:testcert=value', [], [ignore], [ignore]) +AT_CHECK(cmp testfile testfile2, [], [ignore]) + +AT_CHECK(MONOTONE update 'c:testcert=value=with=equal=signs', [], [ignore], [ignore]) +AT_CHECK(cmp testfile testfile1, [], [ignore]) + +AT_CLEANUP --- testsuite.at +++ testsuite.at @@ -585,3 +585,4 @@ m4_include(tests/t_parents_children.at) m4_include(tests/t_automate_graph.at) m4_include(tests/t_i18n_file_data.at) +m4_include(tests/t_select_cert.at)