Skip to content

Commit 21bebcb

Browse files
authored
Merge pull request #5188 from brong/saved-sequence
index: parse '$' in vanished as well
2 parents f5ae3de + f27fa5a commit 21bebcb

File tree

2 files changed

+56
-27
lines changed

2 files changed

+56
-27
lines changed

cassandane/Cassandane/Cyrus/QResync.pm

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,36 @@ sub test_qresync_simple
104104
$self->assert_equals("5:10,25:45", $vanished[0][1]);
105105
}
106106

107+
sub test_qresync_saved_search
108+
{
109+
my ($self) = @_;
110+
111+
xlog $self, "Make some messages";
112+
my $uid = 1;
113+
my %msgs;
114+
for (1..3)
115+
{
116+
$msgs{$uid} = $self->make_message("Message $uid");
117+
$msgs{$uid}->set_attribute('uid', $uid);
118+
$uid++;
119+
}
120+
121+
my $talk = $self->{store}->get_client();
122+
$talk->uid(1);
123+
$talk->enable("qresync");
124+
$talk->select("INBOX");
125+
my $since = $talk->get_response_code('highestmodseq');
126+
for (4..6)
127+
{
128+
$msgs{$uid} = $self->make_message("Message $uid");
129+
$msgs{$uid}->set_attribute('uid', $uid);
130+
$uid++;
131+
}
132+
$talk->store('5', '+flags', '(\\Deleted)');
133+
$talk->expunge();
134+
$talk->search('RETURN', ['SAVE'], 'SINCE', '1-Feb-1994');
135+
my $res = $talk->fetch('$', ['FLAGS'], ['CHANGEDSINCE', $since, 'VANISHED']);
136+
$self->assert_str_equals("4,6", join(',', sort keys %$res));
137+
}
138+
107139
1;

imap/index.c

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ EXPORTED int index_expunge(struct index_state *state, const char *sequence,
426426
continue; /* no \Deleted flag */
427427

428428
/* if there is a sequence list, check it */
429-
if (sequence && !seqset_ismember(seq, im->uid))
429+
if (seq && !seqset_ismember(seq, im->uid))
430430
continue; /* not in the list */
431431

432432
/* load first once we know we have to process this one */
@@ -469,7 +469,7 @@ EXPORTED int index_expunge(struct index_state *state, const char *sequence,
469469
mboxevent_extract_record(mboxevent, state->mailbox, &record);
470470
}
471471

472-
seqset_free(&seq);
472+
if (seq != state->searchres) seqset_free(&seq);
473473

474474
mboxevent_extract_mailbox(mboxevent, state->mailbox);
475475
mboxevent_set_access(mboxevent, NULL, NULL, state->userid, mailbox_name(state->mailbox), 1);
@@ -877,16 +877,16 @@ EXPORTED void index_select(struct index_state *state, struct index_init *init)
877877
}
878878

879879
sequence = init->vanished.sequence;
880-
if (sequence) seq = _parse_sequence(state, sequence, 1);
880+
seq = _parse_sequence(state, sequence, 1);
881881
for (msgno = 1; msgno <= state->exists; msgno++) {
882882
im = &state->map[msgno-1];
883-
if (sequence && !seqset_ismember(seq, im->uid))
883+
if (seq && !seqset_ismember(seq, im->uid))
884884
continue;
885885
if (im->modseq <= init->vanished.modseq)
886886
continue;
887887
index_printflags(state, msgno, TELL_UID);
888888
}
889-
seqset_free(&seq);
889+
if (seq != state->searchres) seqset_free(&seq);
890890
}
891891
}
892892

@@ -972,7 +972,7 @@ seqset_t *index_vanished(struct index_state *state,
972972
const struct index_record *record = msg_record(msg);
973973
if (!(record->internal_flags & FLAG_INTERNAL_EXPUNGED))
974974
continue;
975-
if (!params->sequence || seqset_ismember(seq, record->uid))
975+
if (!seq || seqset_ismember(seq, record->uid))
976976
seqset_add(outlist, record->uid, 1);
977977
}
978978
mailbox_iter_done(&iter);
@@ -1036,7 +1036,7 @@ seqset_t *index_vanished(struct index_state *state,
10361036
}
10371037
}
10381038

1039-
seqset_free(&seq);
1039+
if (seq != state->searchres) seqset_free(&seq);
10401040

10411041
return outlist;
10421042
}
@@ -1211,11 +1211,11 @@ EXPORTED int index_fetch(struct index_state *state,
12111211
r = index_lock(state, readonly);
12121212
if (r) return r;
12131213

1214-
if (!strcmp("$", sequence)) {
1215-
seq = state->searchres;
1214+
seq = _parse_sequence(state, sequence, usinguid);
1215+
if (!strcmpsafe("$", sequence)) {
12161216
usinguid = 1;
12171217

1218-
if (!seqset_first(state->searchres)) {
1218+
if (!seqset_first(seq)) {
12191219
/* RFC 5182: 2.1
12201220
* Note that even if the "$" marker contains the empty list of
12211221
* messages, it must be treated by all commands accepting message
@@ -1227,9 +1227,6 @@ EXPORTED int index_fetch(struct index_state *state,
12271227
goto done;
12281228
}
12291229
}
1230-
else {
1231-
seq = _parse_sequence(state, sequence, usinguid);
1232-
}
12331230

12341231
/* set the \Seen flag if necessary - while we still have the lock */
12351232
if (!readonly) {
@@ -1365,11 +1362,11 @@ EXPORTED int index_store(struct index_state *state, const char *sequence,
13651362

13661363
mailbox = state->mailbox;
13671364

1365+
seq = _parse_sequence(state, sequence, storeargs->usinguid);
13681366
if (!strcmp("$", sequence)) {
1369-
seq = state->searchres;
13701367
storeargs->usinguid = 1;
13711368

1372-
if (!seqset_first(state->searchres)) {
1369+
if (!seqset_first(seq)) {
13731370
/* RFC 5182: 2.1
13741371
* Note that even if the "$" marker contains the empty list of
13751372
* messages, it must be treated by all commands accepting message
@@ -1378,9 +1375,6 @@ EXPORTED int index_store(struct index_state *state, const char *sequence,
13781375
goto done;
13791376
}
13801377
}
1381-
else {
1382-
seq = _parse_sequence(state, sequence, storeargs->usinguid);
1383-
}
13841378

13851379
for (i = 0; i < flags->count ; i++) {
13861380
r = mailbox_user_flag(mailbox, flags->data[i], &userflag, 1);
@@ -1615,7 +1609,7 @@ EXPORTED int index_run_annotator(struct index_state *state,
16151609
}
16161610

16171611
out:
1618-
seqset_free(&seq);
1612+
if (seq != state->searchres) seqset_free(&seq);
16191613

16201614
if (msgrec) msgrecord_unref(&msgrec);
16211615
if (!r) {
@@ -3147,7 +3141,9 @@ EXPORTED int index_copy(struct index_state *state,
31473141

31483142
srcmailbox = state->mailbox;
31493143

3150-
if (!strcmp("$", sequence)) {
3144+
seq = _parse_sequence(state, sequence, usinguid);
3145+
if (!strcmpsafe("$", sequence)) {
3146+
usinguid = 1;
31513147
if (!seqset_first(state->searchres)) {
31523148
/* RFC 5182: 2.1
31533149
* Note that even if the "$" marker contains the empty list of
@@ -3156,12 +3152,6 @@ EXPORTED int index_copy(struct index_state *state,
31563152
*/
31573153
return 0;
31583154
}
3159-
3160-
seq = state->searchres;
3161-
usinguid = 1;
3162-
}
3163-
else {
3164-
seq = _parse_sequence(state, sequence, usinguid);
31653155
}
31663156

31673157
for (msgno = 1; msgno <= state->exists; msgno++) {
@@ -3369,7 +3359,7 @@ EXPORTED int index_copy_remote(struct index_state *state, const char *sequence,
33693359
index_appendremote(state, msgno, pout);
33703360
}
33713361

3372-
seqset_free(&seq);
3362+
if (seq != state->searchres) seqset_free(&seq);
33733363

33743364
return 0;
33753365
}
@@ -8249,6 +8239,13 @@ static seqset_t *_parse_sequence(struct index_state *state,
82498239
{
82508240
unsigned maxval;
82518241

8242+
// handle no sequence
8243+
if (!sequence) return NULL;
8244+
8245+
// handle saved sequences
8246+
if (!strcmpsafe("$", sequence))
8247+
return state->searchres;
8248+
82528249
/* Per RFC 3501, seq-number ABNF:
82538250
"*" represents the largest number in use.
82548251
In the case of message sequence numbers,

0 commit comments

Comments
 (0)