Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / 1d / 62e9b7709ce4bdf6d11281de87b41fa35156b4
1 Return-Path: <bremner@tethera.net>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5  by arlo.cworth.org (Postfix) with ESMTP id 07D386DE0B25\r
6  for <notmuch@notmuchmail.org>; Sat, 23 Jan 2016 07:00:14 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at cworth.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.31\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.31 tagged_above=-999 required=5 tests=[AWL=0.241, \r
12  RP_MATCHES_RCVD=-0.55, SPF_PASS=-0.001] autolearn=disabled\r
13 Received: from arlo.cworth.org ([127.0.0.1])\r
14  by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
15  with ESMTP id 2FXi8wRXsBaT for <notmuch@notmuchmail.org>;\r
16  Sat, 23 Jan 2016 07:00:11 -0800 (PST)\r
17 Received: from fethera.tethera.net (fethera.tethera.net [198.245.60.197])\r
18  by arlo.cworth.org (Postfix) with ESMTPS id 5AAE76DE0943\r
19  for <notmuch@notmuchmail.org>; Sat, 23 Jan 2016 07:00:11 -0800 (PST)\r
20 Received: from remotemail by fethera.tethera.net with local (Exim 4.84)\r
21  (envelope-from <bremner@tethera.net>)\r
22  id 1aMzf2-000165-8q; Sat, 23 Jan 2016 09:59:32 -0500\r
23 Received: (nullmailer pid 4043 invoked by uid 1000);\r
24  Sat, 23 Jan 2016 15:00:06 -0000\r
25 From: David Bremner <david@tethera.net>\r
26 To: notmuch@notmuchmail.org\r
27 Subject: [PATCH 2/5] lib: config list iterators\r
28 Date: Sat, 23 Jan 2016 10:59:55 -0400\r
29 Message-Id: <1453561198-2893-3-git-send-email-david@tethera.net>\r
30 X-Mailer: git-send-email 2.6.4\r
31 In-Reply-To: <1453561198-2893-1-git-send-email-david@tethera.net>\r
32 References: <1453561198-2893-1-git-send-email-david@tethera.net>\r
33 X-BeenThere: notmuch@notmuchmail.org\r
34 X-Mailman-Version: 2.1.20\r
35 Precedence: list\r
36 List-Id: "Use and development of the notmuch mail system."\r
37  <notmuch.notmuchmail.org>\r
38 List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,\r
39  <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
40 List-Archive: <http://notmuchmail.org/pipermail/notmuch/>\r
41 List-Post: <mailto:notmuch@notmuchmail.org>\r
42 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
43 List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
44  <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
45 X-List-Received-Date: Sat, 23 Jan 2016 15:00:14 -0000\r
46 \r
47 Since xapian provides the ability to restrict the iterator to a given\r
48 prefix, we expose this ability to the user. Otherwise we mimic the other\r
49 iterator interfances in notmuch (e.g. tags.c).\r
50 ---\r
51  lib/config.cc          | 104 +++++++++++++++++++++++++++++++++++++++++++++++++\r
52  lib/notmuch.h          |  44 +++++++++++++++++++++\r
53  test/T590-libconfig.sh |  60 ++++++++++++++++++++++++++++\r
54  3 files changed, 208 insertions(+)\r
55 \r
56 diff --git a/lib/config.cc b/lib/config.cc\r
57 index af00d6f..e581f32 100644\r
58 --- a/lib/config.cc\r
59 +++ b/lib/config.cc\r
60 @@ -24,6 +24,19 @@\r
61  \r
62  static const std::string CONFIG_PREFIX="C";\r
63  \r
64 +struct _notmuch_config_list {\r
65 +    notmuch_database_t *notmuch;\r
66 +    Xapian::TermIterator *iterator;\r
67 +    char *current_key;\r
68 +    char *current_val;\r
69 +};\r
70 +\r
71 +static int\r
72 +_notmuch_config_list_destroy (notmuch_config_list_t *list) {\r
73 +    delete list->iterator;\r
74 +    return 0;\r
75 +}\r
76 +\r
77  notmuch_status_t\r
78  notmuch_database_set_config (notmuch_database_t *notmuch,\r
79                              const char *key,\r
80 @@ -88,3 +101,94 @@ notmuch_database_get_config (notmuch_database_t *notmuch,\r
81  \r
82      return NOTMUCH_STATUS_SUCCESS;\r
83  }\r
84 +\r
85 +notmuch_status_t\r
86 +notmuch_database_get_config_list (notmuch_database_t *notmuch,\r
87 +                                const char *prefix,\r
88 +                                notmuch_config_list_t **out)\r
89 +{\r
90 +    notmuch_config_list_t *list = NULL;\r
91 +    notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
92 +\r
93 +    list = talloc (notmuch, notmuch_config_list_t);\r
94 +    if (!list) {\r
95 +       status = NOTMUCH_STATUS_OUT_OF_MEMORY;\r
96 +       goto DONE;\r
97 +    }\r
98 +\r
99 +    talloc_set_destructor (list, _notmuch_config_list_destroy);\r
100 +    list->iterator = new Xapian::TermIterator;\r
101 +    list->notmuch = notmuch;\r
102 +    list->current_key = NULL;\r
103 +    list->current_val = NULL;\r
104 +\r
105 +    try {\r
106 +\r
107 +       *list->iterator = notmuch->xapian_db->metadata_keys_begin (CONFIG_PREFIX + (prefix ? prefix : ""));\r
108 +\r
109 +    } catch (const Xapian::Error &error) {\r
110 +       _notmuch_database_log (notmuch, "A Xapian exception occurred getting metadata iterator: %s.\n",\r
111 +                              error.get_msg().c_str());\r
112 +       notmuch->exception_reported = TRUE;\r
113 +       status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
114 +    }\r
115 +\r
116 +    *out = list;\r
117 +\r
118 + DONE:\r
119 +    if (status && list)\r
120 +       talloc_free (list);\r
121 +\r
122 +    return status;\r
123 +}\r
124 +\r
125 +notmuch_bool_t\r
126 +notmuch_config_list_valid (notmuch_config_list_t *metadata)\r
127 +{\r
128 +    if (*(metadata->iterator) == metadata->notmuch->xapian_db->metadata_keys_end())\r
129 +       return FALSE;\r
130 +\r
131 +    return TRUE;\r
132 +}\r
133 +\r
134 +const char *\r
135 +notmuch_config_list_key (notmuch_config_list_t *list)\r
136 +{\r
137 +    if (list->current_key)\r
138 +       talloc_free (list->current_key);\r
139 +\r
140 +    list->current_key = talloc_strdup (list, (**(list->iterator)).c_str () + CONFIG_PREFIX.length ());\r
141 +\r
142 +    return  list->current_key;\r
143 +}\r
144 +\r
145 +const char *\r
146 +notmuch_config_list_value (notmuch_config_list_t *list)\r
147 +{\r
148 +    std::string strval;\r
149 +    notmuch_status_t status;\r
150 +    const char *key = notmuch_config_list_key (list);\r
151 +\r
152 +    /* TODO: better error reporting?? */\r
153 +    status = _metadata_value (list->notmuch, key, strval);\r
154 +    if (status)\r
155 +       return NULL;\r
156 +\r
157 +    if (list->current_val)\r
158 +       talloc_free(list->current_val);\r
159 +\r
160 +    list->current_val = talloc_strdup(list, strval.c_str ());\r
161 +    return list->current_val;\r
162 +}\r
163 +\r
164 +void\r
165 +notmuch_config_list_move_to_next (notmuch_config_list_t *list)\r
166 +{\r
167 +    (*(list->iterator))++;\r
168 +}\r
169 +\r
170 +void\r
171 +notmuch_config_list_destroy (notmuch_config_list_t *list)\r
172 +{\r
173 +    talloc_free (list);\r
174 +}\r
175 diff --git a/lib/notmuch.h b/lib/notmuch.h\r
176 index c62223b..b439c88 100644\r
177 --- a/lib/notmuch.h\r
178 +++ b/lib/notmuch.h\r
179 @@ -197,6 +197,7 @@ typedef struct _notmuch_message notmuch_message_t;\r
180  typedef struct _notmuch_tags notmuch_tags_t;\r
181  typedef struct _notmuch_directory notmuch_directory_t;\r
182  typedef struct _notmuch_filenames notmuch_filenames_t;\r
183 +typedef struct _notmuch_config_list notmuch_config_list_t;\r
184  #endif /* __DOXYGEN__ */\r
185  \r
186  /**\r
187 @@ -1849,6 +1850,49 @@ notmuch_database_set_config (notmuch_database_t *db, const char *key, const char\r
188  notmuch_status_t\r
189  notmuch_database_get_config (notmuch_database_t *db, const char *key, char **value);\r
190  \r
191 +/**\r
192 + * Create an iterator for all config items with keys matching a given prefix\r
193 + */\r
194 +notmuch_status_t\r
195 +notmuch_database_get_config_list (notmuch_database_t *db, const char *prefix, notmuch_config_list_t **out);\r
196 +\r
197 +/**\r
198 + * Is 'config_list' iterator valid (i.e. _key, _value, _move_to_next can be called).\r
199 + */\r
200 +notmuch_bool_t\r
201 +notmuch_config_list_valid (notmuch_config_list_t *config_list);\r
202 +\r
203 +/**\r
204 + * return key for current config pair\r
205 + *\r
206 + * return value is owned by the iterator, and will be destroyed by the\r
207 + * next call to notmuch_config_list_key or notmuch_config_list_destroy.\r
208 + */\r
209 +const char *\r
210 +notmuch_config_list_key (notmuch_config_list_t *config_list);\r
211 +\r
212 +/**\r
213 + * return 'value' for current config pair\r
214 + *\r
215 + * return value is owned by the iterator, and will be destroyed by the\r
216 + * next call to notmuch_config_list_value or notmuch config_list_destroy\r
217 + */\r
218 +const char *\r
219 +notmuch_config_list_value (notmuch_config_list_t *config_list);\r
220 +\r
221 +\r
222 +/**\r
223 + * move 'config_list' iterator to the next pair\r
224 + */\r
225 +void\r
226 +notmuch_config_list_move_to_next (notmuch_config_list_t *config_list);\r
227 +\r
228 +/**\r
229 + * free any resources held by 'config_list'\r
230 + */\r
231 +void\r
232 +notmuch_config_list_destroy (notmuch_config_list_t *config_list);\r
233 +\r
234  /* @} */\r
235  \r
236  NOTMUCH_END_DECLS\r
237 diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh\r
238 index 85e4497..8ca6883 100755\r
239 --- a/test/T590-libconfig.sh\r
240 +++ b/test/T590-libconfig.sh\r
241 @@ -55,4 +55,64 @@ testkey2 = testvalue2\r
242  EOF\r
243  test_expect_equal_file EXPECTED OUTPUT\r
244  \r
245 +\r
246 +test_begin_subtest "notmuch_database_get_config_list: empty list"\r
247 +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}\r
248 +{\r
249 +   notmuch_config_list_t *list;\r
250 +   RUN(notmuch_database_get_config_list (db, "nonexistent", &list));\r
251 +   printf("valid = %d\n", notmuch_config_list_valid (list));\r
252 +   notmuch_config_list_destroy (list);\r
253 +}\r
254 +EOF\r
255 +cat <<'EOF' >EXPECTED\r
256 +== stdout ==\r
257 +valid = 0\r
258 +== stderr ==\r
259 +EOF\r
260 +test_expect_equal_file EXPECTED OUTPUT\r
261 +\r
262 +\r
263 +test_begin_subtest "notmuch_database_get_config_list: all pairs"\r
264 +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}\r
265 +{\r
266 +   notmuch_config_list_t *list;\r
267 +   RUN(notmuch_database_set_config (db, "zzzafter", "afterval"));\r
268 +   RUN(notmuch_database_set_config (db, "aaabefore", "beforeval"));\r
269 +   RUN(notmuch_database_get_config_list (db, "", &list));\r
270 +   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {\r
271 +      printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));\r
272 +   }\r
273 +   notmuch_config_list_destroy (list);\r
274 +}\r
275 +EOF\r
276 +cat <<'EOF' >EXPECTED\r
277 +== stdout ==\r
278 +aaabefore beforeval\r
279 +testkey1 testvalue1\r
280 +testkey2 testvalue2\r
281 +zzzafter afterval\r
282 +== stderr ==\r
283 +EOF\r
284 +test_expect_equal_file EXPECTED OUTPUT\r
285 +\r
286 +test_begin_subtest "notmuch_database_get_config_list: one prefix"\r
287 +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}\r
288 +{\r
289 +   notmuch_config_list_t *list;\r
290 +   RUN(notmuch_database_get_config_list (db, "testkey", &list));\r
291 +   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {\r
292 +      printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));\r
293 +   }\r
294 +   notmuch_config_list_destroy (list);\r
295 +}\r
296 +EOF\r
297 +cat <<'EOF' >EXPECTED\r
298 +== stdout ==\r
299 +testkey1 testvalue1\r
300 +testkey2 testvalue2\r
301 +== stderr ==\r
302 +EOF\r
303 +test_expect_equal_file EXPECTED OUTPUT\r
304 +\r
305  test_done\r
306 -- \r
307 2.6.4\r
308 \r