lib: add field processor for lastmod: prefix

By sharing the existing logic used by the sexp query parser, this
allows negative lastmod revisions to be interpreted as relative to the
most recent revision.
This commit is contained in:
David Bremner 2022-08-14 12:02:59 -03:00
parent 93c602a82f
commit 2e5ef69fbf
5 changed files with 82 additions and 6 deletions

View file

@ -153,10 +153,11 @@ date:<since>..<until> or date:<date>
lastmod:<initial-revision>..<final-revision>
The **lastmod:** prefix can be used to restrict the result by the
database revision number of when messages were last modified (tags
were added/removed or filenames changed). This is usually used in
conjunction with the ``--uuid`` argument to
:any:`notmuch-search(1)` to find messages that have changed since
an earlier query.
were added/removed or filenames changed). Negative revisions are
interpreted relative to the most recent database revision (see
:option:`count --lastmod`). This is usually used in conjunction
with the ``--uuid`` argument to :any:`notmuch-search(1)` to find
messages that have changed since an earlier query.
query:<name>
The **query:** prefix allows queries to refer to previously saved

View file

@ -21,6 +21,7 @@
*/
#include "database-private.h"
#include "lastmod-fp.h"
notmuch_status_t
_notmuch_lastmod_strings_to_query (notmuch_database_t *notmuch,
@ -66,3 +67,17 @@ _notmuch_lastmod_strings_to_query (notmuch_database_t *notmuch,
Xapian::sortable_serialise (to_idx));
return NOTMUCH_STATUS_SUCCESS;
}
Xapian::Query
LastModRangeProcessor::operator() (const std::string &begin, const std::string &end)
{
Xapian::Query output;
std::string msg;
if (_notmuch_lastmod_strings_to_query (notmuch, begin, end, output, msg))
throw Xapian::QueryParserError (msg);
return output;
}

41
lib/lastmod-fp.h Normal file
View file

@ -0,0 +1,41 @@
/* lastmod-fp.h - database revision query glue
*
* This file is part of notmuch.
*
* Copyright © 2022 David Bremner
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/ .
*
* Author: David Bremner <david@tethera.net>
*/
#ifndef NOTMUCH_LASTMOD_FP_H
#define NOTMUCH_LASTMOD_FP_H
#include <xapian.h>
class LastModRangeProcessor : public Xapian::RangeProcessor {
protected:
notmuch_database_t *notmuch;
public:
LastModRangeProcessor (notmuch_database_t *notmuch_, const std::string prefix_)
: Xapian::RangeProcessor (NOTMUCH_VALUE_LAST_MOD, prefix_, 0), notmuch (notmuch_)
{
}
Xapian::Query operator() (const std::string &begin, const std::string &end);
};
#endif /* NOTMUCH_LASTMOD_FP_H */

View file

@ -3,6 +3,7 @@
#include "database-private.h"
#include "parse-time-vrp.h"
#include "lastmod-fp.h"
#include "path-util.h"
#if HAVE_XAPIAN_DB_RETRY_LOCK
@ -489,8 +490,7 @@ _finish_open (notmuch_database_t *notmuch,
notmuch->value_range_processor = new Xapian::NumberRangeProcessor (NOTMUCH_VALUE_TIMESTAMP);
notmuch->date_range_processor = new ParseTimeRangeProcessor (NOTMUCH_VALUE_TIMESTAMP,
"date:");
notmuch->last_mod_range_processor = new Xapian::NumberRangeProcessor (NOTMUCH_VALUE_LAST_MOD,
"lastmod:");
notmuch->last_mod_range_processor = new LastModRangeProcessor (notmuch, "lastmod:");
notmuch->query_parser->set_default_op (Xapian::Query::OP_AND);
notmuch->query_parser->set_database (*notmuch->xapian_db);
notmuch->stemmer = new Xapian::Stem ("english");

View file

@ -103,4 +103,23 @@ if [ $NOTMUCH_HAVE_SFSEXP -eq 1 ]; then
test_expect_equal 1 "$count"
fi
test_begin_subtest 'exclude one message using negative lastmod'
total=$(notmuch count '*')
notmuch tag +${RANDOM} id:4EFC743A.3060609@april.org
count=$(notmuch count lastmod:-1..)
test_expect_equal 1 "$count"
test_begin_subtest 'exclude one message using negative lastmod (second param)'
total=$(notmuch count '*')
notmuch tag +${RANDOM} id:4EFC743A.3060609@april.org
count=$(notmuch count lastmod:..-1)
test_expect_equal 51 "$count"
test_begin_subtest 'negative lastmod (two parameters)'
notmuch tag +${RANDOM} '*'
before=$(notmuch count --lastmod '*' | cut -f3)
notmuch tag +${RANDOM} id:4EFC743A.3060609@april.org
count=$(notmuch count lastmod:-100..$before)
test_expect_equal 51 "$count"
test_done