]> git.cworth.org Git - notmuch-old/blob - lib/features.cc
rename built_with.sexpr_query to built_with.sexp_queries
[notmuch-old] / lib / features.cc
1 #include "database-private.h"
2
3 static const struct {
4     /* NOTMUCH_FEATURE_* value. */
5     _notmuch_features value;
6     /* Feature name as it appears in the database.  This name should
7      * be appropriate for displaying to the user if an older version
8      * of notmuch doesn't support this feature. */
9     const char *name;
10     /* Compatibility flags when this feature is declared. */
11     const char *flags;
12 } feature_names[] = {
13     { NOTMUCH_FEATURE_FILE_TERMS,
14       "multiple paths per message", "rw" },
15     { NOTMUCH_FEATURE_DIRECTORY_DOCS,
16       "relative directory paths", "rw" },
17     /* Header values are not required for reading a database because a
18      * reader can just refer to the message file. */
19     { NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES,
20       "from/subject/message-ID in database", "w" },
21     { NOTMUCH_FEATURE_BOOL_FOLDER,
22       "exact folder:/path: search", "rw" },
23     { NOTMUCH_FEATURE_GHOSTS,
24       "mail documents for missing messages", "w" },
25     /* Knowledge of the index mime-types are not required for reading
26      * a database because a reader will just be unable to query
27      * them. */
28     { NOTMUCH_FEATURE_INDEXED_MIMETYPES,
29       "indexed MIME types", "w" },
30     { NOTMUCH_FEATURE_LAST_MOD,
31       "modification tracking", "w" },
32     /* Existing databases will work fine for all queries not involving
33      * 'body:' */
34     { NOTMUCH_FEATURE_UNPREFIX_BODY_ONLY,
35       "index body and headers separately", "w" },
36 };
37
38 char *
39 _notmuch_database_print_features (const void *ctx, unsigned int features)
40 {
41     unsigned int i;
42     char *res = talloc_strdup (ctx, "");
43
44     for (i = 0; i < ARRAY_SIZE (feature_names); ++i)
45         if (features & feature_names[i].value)
46             res = talloc_asprintf_append_buffer (
47                 res, "%s\t%s\n", feature_names[i].name, feature_names[i].flags);
48
49     return res;
50 }
51
52
53 /* Parse a database features string from the given database version.
54  * Returns the feature bit set.
55  *
56  * For version < 3, this ignores the features string and returns a
57  * hard-coded set of features.
58  *
59  * If there are unrecognized features that are required to open the
60  * database in mode (which should be 'r' or 'w'), return a
61  * comma-separated list of unrecognized but required features in
62  * *incompat_out suitable for presenting to the user.  *incompat_out
63  * will be allocated from ctx.
64  */
65 _notmuch_features
66 _notmuch_database_parse_features (const void *ctx, const char *features, unsigned int version,
67                                   char mode, char **incompat_out)
68 {
69     _notmuch_features res = static_cast<_notmuch_features>(0);
70     unsigned int namelen, i;
71     size_t llen = 0;
72     const char *flags;
73
74     /* Prior to database version 3, features were implied by the
75      * version number. */
76     if (version == 0)
77         return NOTMUCH_FEATURES_V0;
78     else if (version == 1)
79         return NOTMUCH_FEATURES_V1;
80     else if (version == 2)
81         return NOTMUCH_FEATURES_V2;
82
83     /* Parse the features string */
84     while ((features = strtok_len_c (features + llen, "\n", &llen)) != NULL) {
85         flags = strchr (features, '\t');
86         if (! flags || flags > features + llen)
87             continue;
88         namelen = flags - features;
89
90         for (i = 0; i < ARRAY_SIZE (feature_names); ++i) {
91             if (strlen (feature_names[i].name) == namelen &&
92                 strncmp (feature_names[i].name, features, namelen) == 0) {
93                 res |= feature_names[i].value;
94                 break;
95             }
96         }
97
98         if (i == ARRAY_SIZE (feature_names) && incompat_out) {
99             /* Unrecognized feature */
100             const char *have = strchr (flags, mode);
101             if (have && have < features + llen) {
102                 /* This feature is required to access this database in
103                  * 'mode', but we don't understand it. */
104                 if (! *incompat_out)
105                     *incompat_out = talloc_strdup (ctx, "");
106                 *incompat_out = talloc_asprintf_append_buffer (
107                     *incompat_out, "%s%.*s", **incompat_out ? ", " : "",
108                     namelen, features);
109             }
110         }
111     }
112
113     return res;
114 }