~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/libsvn_ra_neon/log.c

  • Committer: Package Import Robot
  • Author(s): James McCoy, Peter Samuelson, James McCoy
  • Date: 2014-01-12 19:48:33 UTC
  • mfrom: (0.2.10)
  • Revision ID: package-import@ubuntu.com-20140112194833-w3axfwksn296jn5x
Tags: 1.8.5-1
[ Peter Samuelson ]
* New upstream release.  (Closes: #725787) Rediff patches:
  - Remove apr-abi1 (applied upstream), rename apr-abi2 to apr-abi
  - Remove loosen-sqlite-version-check (shouldn't be needed)
  - Remove java-osgi-metadata (applied upstream)
  - svnmucc prompts for a changelog if none is provided. (Closes: #507430)
  - Remove fix-bdb-version-detection, upstream uses "apu-config --dbm-libs"
  - Remove ruby-test-wc (applied upstream)
  - Fix “svn diff -r N file” when file has svn:mime-type set.
    (Closes: #734163)
  - Support specifying an encoding for mod_dav_svn's environment in which
    hooks are run.  (Closes: #601544)
  - Fix ordering of “svnadmin dump” paths with certain APR versions.
    (Closes: #687291)
  - Provide a better error message when authentication fails with an
    svn+ssh:// URL.  (Closes: #273874)
  - Updated Polish translations.  (Closes: #690815)

[ James McCoy ]
* Remove all traces of libneon, replaced by libserf.
* patches/sqlite_3.8.x_workaround: Upstream fix for wc-queries-test test
  failurse.
* Run configure with --with-apache-libexecdir, which allows removing part of
  patches/rpath.
* Re-enable auth-test as upstream has fixed the problem of picking up
  libraries from the environment rather than the build tree.
  (Closes: #654172)
* Point LD_LIBRARY_PATH at the built auth libraries when running the svn
  command during the build.  (Closes: #678224)
* Add a NEWS entry describing how to configure mod_dav_svn to understand
  UTF-8.  (Closes: #566148)
* Remove ancient transitional package, libsvn-ruby.
* Enable compatibility with Sqlite3 versions back to Wheezy.
* Enable hardening flags.  (Closes: #734918)
* patches/build-fixes: Enable verbose build logs.
* Build against the default ruby version.  (Closes: #722393)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * log.c :  routines for requesting and parsing log reports
3
 
 *
4
 
 * ====================================================================
5
 
 *    Licensed to the Apache Software Foundation (ASF) under one
6
 
 *    or more contributor license agreements.  See the NOTICE file
7
 
 *    distributed with this work for additional information
8
 
 *    regarding copyright ownership.  The ASF licenses this file
9
 
 *    to you under the Apache License, Version 2.0 (the
10
 
 *    "License"); you may not use this file except in compliance
11
 
 *    with the License.  You may obtain a copy of the License at
12
 
 *
13
 
 *      http://www.apache.org/licenses/LICENSE-2.0
14
 
 *
15
 
 *    Unless required by applicable law or agreed to in writing,
16
 
 *    software distributed under the License is distributed on an
17
 
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18
 
 *    KIND, either express or implied.  See the License for the
19
 
 *    specific language governing permissions and limitations
20
 
 *    under the License.
21
 
 * ====================================================================
22
 
 */
23
 
 
24
 
#define APR_WANT_STRFUNC
25
 
#include <apr_want.h> /* for strcmp() */
26
 
 
27
 
#include <apr_pools.h>
28
 
#include <apr_tables.h>
29
 
#include <apr_strings.h>
30
 
#include <apr_xml.h>
31
 
 
32
 
#include "svn_error.h"
33
 
#include "svn_pools.h"
34
 
#include "svn_path.h"
35
 
#include "svn_base64.h"
36
 
#include "svn_xml.h"
37
 
#include "svn_props.h"
38
 
 
39
 
#include "private/svn_dav_protocol.h"
40
 
#include "../libsvn_ra/ra_loader.h"
41
 
 
42
 
#include "ra_neon.h"
43
 
 
44
 
 
45
 
 
46
 
/*** Code ***/
47
 
 
48
 
/* Userdata for the Neon XML element callbacks. */
49
 
struct log_baton
50
 
{
51
 
  /*WARNING: WANT_CDATA should stay the first element in the baton:
52
 
    svn_ra_neon__xml_collect_cdata() assumes the baton starts with a stringbuf.
53
 
  */
54
 
  svn_stringbuf_t *want_cdata;
55
 
  svn_stringbuf_t *cdata;
56
 
  const char *cdata_encoding; /* encoding of CDATA (NULL or "base64") */
57
 
 
58
 
  /* Allocate log message information.
59
 
   * NOTE: this pool may be cleared multiple times as log messages are
60
 
   * received.
61
 
   */
62
 
  apr_pool_t *subpool;
63
 
 
64
 
  /* Information about each log item in turn. */
65
 
  svn_log_entry_t *log_entry;
66
 
  /* Place to hold revprop name. */
67
 
  const char *revprop_name;
68
 
  /* pre-1.5 compatibility */
69
 
  svn_boolean_t want_author;
70
 
  svn_boolean_t want_date;
71
 
  svn_boolean_t want_message;
72
 
 
73
 
  /* The current changed path item. */
74
 
  svn_log_changed_path2_t *this_path_item;
75
 
 
76
 
  /* Client's callback, invoked on the above fields when the end of an
77
 
     item is seen. */
78
 
  svn_log_entry_receiver_t receiver;
79
 
  void *receiver_baton;
80
 
 
81
 
  int limit;
82
 
  int nest_level; /* used to track mergeinfo nesting levels */
83
 
  int count; /* only incremented when nest_level == 0 */
84
 
 
85
 
  /* If we're in backwards compatibility mode for the svn log --limit
86
 
     stuff, we need to be able to bail out while parsing log messages.
87
 
     The way we do that is returning an error to neon, but we need to
88
 
     be able to tell that the error we returned wasn't actually a
89
 
     problem, so if this is TRUE it means we can safely ignore that
90
 
     error and return success. */
91
 
  svn_boolean_t limit_compat_bailout;
92
 
};
93
 
 
94
 
 
95
 
/* Prepare LB to start accumulating the next log item, by wiping all
96
 
 * information related to the previous item and clearing the pool in
97
 
 * which they were allocated.  Do not touch any stored error, however.
98
 
 */
99
 
static void
100
 
reset_log_item(struct log_baton *lb)
101
 
{
102
 
  lb->log_entry->revision       = SVN_INVALID_REVNUM;
103
 
  lb->log_entry->revprops       = NULL;
104
 
  lb->log_entry->changed_paths  = NULL;
105
 
  lb->log_entry->has_children   = FALSE;
106
 
  lb->log_entry->changed_paths2 = NULL;
107
 
  lb->log_entry->subtractive_merge = FALSE;
108
 
 
109
 
  svn_pool_clear(lb->subpool);
110
 
}
111
 
 
112
 
/*
113
 
 * This implements the `svn_ra_neon__xml_startelm_cb' prototype.
114
 
 */
115
 
static svn_error_t *
116
 
log_start_element(int *elem, void *baton, int parent,
117
 
                  const char *nspace, const char *name, const char **atts)
118
 
{
119
 
  const char *copyfrom_path, *copyfrom_revstr;
120
 
  svn_revnum_t copyfrom_rev;
121
 
  struct log_baton *lb = baton;
122
 
  static const svn_ra_neon__xml_elm_t log_report_elements[] =
123
 
    {
124
 
      { SVN_XML_NAMESPACE, "log-report", ELEM_log_report, 0 },
125
 
      { SVN_XML_NAMESPACE, "log-item", ELEM_log_item, 0 },
126
 
      { SVN_XML_NAMESPACE, "date", ELEM_log_date, SVN_RA_NEON__XML_CDATA },
127
 
      { SVN_XML_NAMESPACE, "added-path", ELEM_added_path,
128
 
        SVN_RA_NEON__XML_CDATA },
129
 
      { SVN_XML_NAMESPACE, "deleted-path", ELEM_deleted_path,
130
 
        SVN_RA_NEON__XML_CDATA },
131
 
      { SVN_XML_NAMESPACE, "modified-path", ELEM_modified_path,
132
 
        SVN_RA_NEON__XML_CDATA },
133
 
      { SVN_XML_NAMESPACE, "replaced-path", ELEM_replaced_path,
134
 
        SVN_RA_NEON__XML_CDATA },
135
 
      { SVN_XML_NAMESPACE, "revprop", ELEM_revprop,
136
 
        SVN_RA_NEON__XML_CDATA },
137
 
      { "DAV:", SVN_DAV__VERSION_NAME, ELEM_version_name,
138
 
        SVN_RA_NEON__XML_CDATA },
139
 
      { "DAV:", "creator-displayname", ELEM_creator_displayname,
140
 
        SVN_RA_NEON__XML_CDATA },
141
 
      { "DAV:", "comment", ELEM_comment, SVN_RA_NEON__XML_CDATA },
142
 
      { SVN_XML_NAMESPACE, "has-children", ELEM_has_children,
143
 
        SVN_RA_NEON__XML_CDATA },
144
 
      { SVN_XML_NAMESPACE, "subtractive-merge", ELEM_subtractive_merge,
145
 
        SVN_RA_NEON__XML_CDATA },
146
 
      { NULL }
147
 
    };
148
 
  const svn_ra_neon__xml_elm_t *elm
149
 
    = svn_ra_neon__lookup_xml_elem(log_report_elements, nspace, name);
150
 
 
151
 
  *elem = elm ? elm->id : SVN_RA_NEON__XML_DECLINE;
152
 
  if (!elm)
153
 
    return SVN_NO_ERROR;
154
 
 
155
 
  switch (elm->id)
156
 
    {
157
 
    case ELEM_creator_displayname:
158
 
    case ELEM_log_date:
159
 
    case ELEM_version_name:
160
 
    case ELEM_added_path:
161
 
    case ELEM_replaced_path:
162
 
    case ELEM_deleted_path:
163
 
    case ELEM_modified_path:
164
 
    case ELEM_revprop:
165
 
    case ELEM_comment:
166
 
      lb->want_cdata = lb->cdata;
167
 
      svn_stringbuf_setempty(lb->cdata);
168
 
      lb->cdata_encoding = NULL;
169
 
          
170
 
      /* Some tags might contain encoded CDATA. */
171
 
      if ((elm->id == ELEM_comment) ||
172
 
          (elm->id == ELEM_creator_displayname) ||
173
 
          (elm->id == ELEM_log_date) ||
174
 
          (elm->id == ELEM_rev_prop))
175
 
        {
176
 
          lb->cdata_encoding = svn_xml_get_attr_value("encoding", atts);
177
 
          if (lb->cdata_encoding)
178
 
            lb->cdata_encoding = apr_pstrdup(lb->subpool, lb->cdata_encoding);
179
 
        }
180
 
 
181
 
      /* revprop tags have names. */
182
 
      if (elm->id == ELEM_revprop)
183
 
        {
184
 
          const char *revprop_name = svn_xml_get_attr_value("name", atts);
185
 
          if (revprop_name == NULL)
186
 
            return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
187
 
                                     _("Missing name attr in revprop element"));
188
 
          lb->revprop_name = apr_pstrdup(lb->subpool, revprop_name);
189
 
        }
190
 
      break;
191
 
    case ELEM_has_children:
192
 
      lb->log_entry->has_children = TRUE;
193
 
      break;
194
 
    case ELEM_subtractive_merge:
195
 
      lb->log_entry->subtractive_merge = TRUE;
196
 
      break;
197
 
 
198
 
    default:
199
 
      lb->want_cdata = NULL;
200
 
      break;
201
 
    }
202
 
 
203
 
  switch (elm->id)
204
 
    {
205
 
    case ELEM_added_path:
206
 
    case ELEM_replaced_path:
207
 
    case ELEM_deleted_path:
208
 
    case ELEM_modified_path:
209
 
      lb->this_path_item = svn_log_changed_path2_create(lb->subpool);
210
 
      lb->this_path_item->node_kind = svn_node_kind_from_word(
211
 
                                     svn_xml_get_attr_value("node-kind", atts));
212
 
      lb->this_path_item->copyfrom_rev = SVN_INVALID_REVNUM;
213
 
 
214
 
      lb->this_path_item->text_modified = svn_tristate__from_word(
215
 
                                     svn_xml_get_attr_value("text-mods", atts));
216
 
      lb->this_path_item->props_modified = svn_tristate__from_word(
217
 
                                     svn_xml_get_attr_value("prop-mods", atts));
218
 
 
219
 
      /* See documentation for `svn_repos_node_t' in svn_repos.h,
220
 
         and `svn_log_changed_path_t' in svn_types.h, for more
221
 
         about these action codes. */
222
 
      if ((elm->id == ELEM_added_path) || (elm->id == ELEM_replaced_path))
223
 
        {
224
 
          lb->this_path_item->action
225
 
            = (elm->id == ELEM_added_path) ? 'A' : 'R';
226
 
          copyfrom_path = svn_xml_get_attr_value("copyfrom-path", atts);
227
 
          copyfrom_revstr = svn_xml_get_attr_value("copyfrom-rev", atts);
228
 
          if (copyfrom_path && copyfrom_revstr
229
 
              && (SVN_IS_VALID_REVNUM
230
 
                  (copyfrom_rev = SVN_STR_TO_REV(copyfrom_revstr))))
231
 
            {
232
 
              lb->this_path_item->copyfrom_path = apr_pstrdup(lb->subpool,
233
 
                                                              copyfrom_path);
234
 
              lb->this_path_item->copyfrom_rev = copyfrom_rev;
235
 
            }
236
 
        }
237
 
      else if (elm->id == ELEM_deleted_path)
238
 
        {
239
 
          lb->this_path_item->action = 'D';
240
 
        }
241
 
      else
242
 
        {
243
 
          lb->this_path_item->action = 'M';
244
 
        }
245
 
      break;
246
 
 
247
 
    default:
248
 
      lb->this_path_item = NULL;
249
 
      break;
250
 
    }
251
 
  return SVN_NO_ERROR;
252
 
}
253
 
 
254
 
/*
255
 
 * Set *DECODED_CDATA to a copy of current CDATA being tracked in LB,
256
 
 * decoded as necessary, and allocated from LB->subpool.
257
 
 */
258
 
static svn_error_t *
259
 
maybe_decode_log_cdata(const svn_string_t **decoded_cdata,
260
 
                       struct log_baton *lb)
261
 
{
262
 
  if (lb->cdata_encoding)
263
 
    {
264
 
      svn_string_t in;
265
 
      in.data = lb->cdata->data;
266
 
      in.len = lb->cdata->len;
267
 
 
268
 
      /* Check for a known encoding type.  This is easy -- there's
269
 
         only one.  */
270
 
      if (strcmp(lb->cdata_encoding, "base64") != 0)
271
 
        return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
272
 
 
273
 
      *decoded_cdata = svn_base64_decode_string(&in, lb->subpool);
274
 
    }
275
 
  else
276
 
    {
277
 
      *decoded_cdata = svn_string_create_from_buf(lb->cdata, lb->subpool);
278
 
    }
279
 
 
280
 
  return SVN_NO_ERROR;
281
 
}
282
 
 
283
 
                       
284
 
 
285
 
/*
286
 
 * This implements the `svn_ra_neon__xml_endelm_cb' prototype.
287
 
 */
288
 
static svn_error_t *
289
 
log_end_element(void *baton, int state,
290
 
                const char *nspace, const char *name)
291
 
{
292
 
  struct log_baton *lb = baton;
293
 
  const svn_string_t *decoded_cdata;
294
 
 
295
 
  if (lb->want_cdata)
296
 
    SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, lb));
297
 
 
298
 
  switch (state)
299
 
    {
300
 
    case ELEM_version_name:
301
 
      lb->log_entry->revision = SVN_STR_TO_REV(lb->cdata->data);
302
 
      break;
303
 
    case ELEM_creator_displayname:
304
 
      if (lb->want_author)
305
 
        {
306
 
          if (! lb->log_entry->revprops)
307
 
            lb->log_entry->revprops = apr_hash_make(lb->subpool);
308
 
          apr_hash_set(lb->log_entry->revprops, SVN_PROP_REVISION_AUTHOR,
309
 
                       APR_HASH_KEY_STRING, decoded_cdata);
310
 
        }
311
 
      break;
312
 
    case ELEM_log_date:
313
 
      if (lb->want_date)
314
 
        {
315
 
          if (! lb->log_entry->revprops)
316
 
            lb->log_entry->revprops = apr_hash_make(lb->subpool);
317
 
          apr_hash_set(lb->log_entry->revprops, SVN_PROP_REVISION_DATE,
318
 
                       APR_HASH_KEY_STRING, decoded_cdata);
319
 
        }
320
 
      break;
321
 
    case ELEM_added_path:
322
 
    case ELEM_replaced_path:
323
 
    case ELEM_deleted_path:
324
 
    case ELEM_modified_path:
325
 
      {
326
 
        char *path = apr_pstrdup(lb->subpool, lb->cdata->data);
327
 
        if (! lb->log_entry->changed_paths2)
328
 
          {
329
 
            lb->log_entry->changed_paths2 = apr_hash_make(lb->subpool);
330
 
            lb->log_entry->changed_paths = lb->log_entry->changed_paths2;
331
 
          }
332
 
        apr_hash_set(lb->log_entry->changed_paths2, path, APR_HASH_KEY_STRING,
333
 
                     lb->this_path_item);
334
 
        break;
335
 
      }
336
 
    case ELEM_revprop:
337
 
      if (! lb->log_entry->revprops)
338
 
        lb->log_entry->revprops = apr_hash_make(lb->subpool);
339
 
      apr_hash_set(lb->log_entry->revprops, lb->revprop_name,
340
 
                   APR_HASH_KEY_STRING, decoded_cdata);
341
 
      break;
342
 
    case ELEM_comment:
343
 
      if (lb->want_message)
344
 
        {
345
 
          if (! lb->log_entry->revprops)
346
 
            lb->log_entry->revprops = apr_hash_make(lb->subpool);
347
 
          apr_hash_set(lb->log_entry->revprops, SVN_PROP_REVISION_LOG,
348
 
                       APR_HASH_KEY_STRING, decoded_cdata);
349
 
        }
350
 
      break;
351
 
    case ELEM_log_item:
352
 
      {
353
 
        /* Compatibility cruft so that we can provide limit functionality
354
 
           even if the server doesn't support it.
355
 
 
356
 
           If we've seen as many log entries as we're going to show just
357
 
           error out of the XML parser so we can avoid having to parse the
358
 
           remaining XML, but set a flag that we will later use to ensure
359
 
           this error will not be shown to the user. */
360
 
        if (lb->limit && (lb->nest_level == 0) && (++lb->count > lb->limit))
361
 
          {
362
 
            lb->limit_compat_bailout = TRUE;
363
 
            return svn_error_create(APR_EGENERAL, NULL, NULL);
364
 
          }
365
 
        SVN_ERR((*(lb->receiver))(lb->receiver_baton,
366
 
                                  lb->log_entry,
367
 
                                  lb->subpool));
368
 
        if (lb->log_entry->has_children)
369
 
          {
370
 
            lb->nest_level++;
371
 
          }
372
 
        if (! SVN_IS_VALID_REVNUM(lb->log_entry->revision))
373
 
          {
374
 
            SVN_ERR_ASSERT(lb->nest_level);
375
 
            lb->nest_level--;
376
 
          }
377
 
        reset_log_item(lb);
378
 
      }
379
 
      break;
380
 
    }
381
 
 
382
 
  /* Stop collecting cdata */
383
 
  lb->want_cdata = NULL;
384
 
  return SVN_NO_ERROR;
385
 
}
386
 
 
387
 
 
388
 
svn_error_t * svn_ra_neon__get_log(svn_ra_session_t *session,
389
 
                                   const apr_array_header_t *paths,
390
 
                                   svn_revnum_t start,
391
 
                                   svn_revnum_t end,
392
 
                                   int limit,
393
 
                                   svn_boolean_t discover_changed_paths,
394
 
                                   svn_boolean_t strict_node_history,
395
 
                                   svn_boolean_t include_merged_revisions,
396
 
                                   const apr_array_header_t *revprops,
397
 
                                   svn_log_entry_receiver_t receiver,
398
 
                                   void *receiver_baton,
399
 
                                   apr_pool_t *pool)
400
 
{
401
 
  /* The Plan: Send a request to the server for a log report.
402
 
   * Somewhere in mod_dav_svn, there will be an implementation, R, of
403
 
   * the `svn_log_entry_receiver_t' function type.  Some other
404
 
   * function in mod_dav_svn will use svn_repos_get_logs() to loop R
405
 
   * over the log messages, and the successive invocations of R will
406
 
   * collectively transmit the report back here, where we parse the
407
 
   * report and invoke RECEIVER (which is an entirely separate
408
 
   * instance of `svn_log_entry_receiver_t') on each individual
409
 
   * message in that report.
410
 
   */
411
 
 
412
 
  int i;
413
 
  svn_ra_neon__session_t *ras = session->priv;
414
 
  svn_stringbuf_t *request_body = svn_stringbuf_create("", pool);
415
 
  svn_boolean_t want_custom_revprops;
416
 
  struct log_baton lb;
417
 
  const char *bc_url;
418
 
  const char *bc_relative;
419
 
  const char *final_bc_url;
420
 
  svn_revnum_t use_rev;
421
 
  svn_error_t *err;
422
 
 
423
 
  /* ### todo: I don't understand why the static, file-global
424
 
     variables shared by update and status are called `report_head'
425
 
     and `report_tail', instead of `request_head' and `request_tail'.
426
 
     Maybe Greg can explain?  Meanwhile, I'm tentatively using
427
 
     "request_*" for my local vars below. */
428
 
 
429
 
  static const char log_request_head[] = "<S:log-report xmlns:S=\""
430
 
    SVN_XML_NAMESPACE "\">" DEBUG_CR "<S:encode-binary-props/>";
431
 
 
432
 
  static const char log_request_tail[] = "</S:log-report>" DEBUG_CR;
433
 
 
434
 
  /* Construct the request body. */
435
 
  svn_stringbuf_appendcstr(request_body, log_request_head);
436
 
  svn_stringbuf_appendcstr(request_body,
437
 
                           apr_psprintf(pool,
438
 
                                        "<S:start-revision>%ld"
439
 
                                        "</S:start-revision>", start));
440
 
  svn_stringbuf_appendcstr(request_body,
441
 
                           apr_psprintf(pool,
442
 
                                        "<S:end-revision>%ld"
443
 
                                        "</S:end-revision>", end));
444
 
  if (limit)
445
 
    {
446
 
      svn_stringbuf_appendcstr(request_body,
447
 
                               apr_psprintf(pool,
448
 
                                            "<S:limit>%d</S:limit>", limit));
449
 
    }
450
 
 
451
 
  if (discover_changed_paths)
452
 
    {
453
 
      svn_stringbuf_appendcstr(request_body,
454
 
                               apr_psprintf(pool,
455
 
                                            "<S:discover-changed-paths/>"));
456
 
    }
457
 
 
458
 
  if (strict_node_history)
459
 
    {
460
 
      svn_stringbuf_appendcstr(request_body,
461
 
                               apr_psprintf(pool,
462
 
                                            "<S:strict-node-history/>"));
463
 
    }
464
 
 
465
 
  if (include_merged_revisions)
466
 
    {
467
 
      svn_stringbuf_appendcstr(request_body,
468
 
                               apr_psprintf(pool,
469
 
                                            "<S:include-merged-revisions/>"));
470
 
    }
471
 
 
472
 
  if (revprops)
473
 
    {
474
 
      lb.want_author = lb.want_date = lb.want_message = FALSE;
475
 
      want_custom_revprops = FALSE;
476
 
      for (i = 0; i < revprops->nelts; i++)
477
 
        {
478
 
          char *name = APR_ARRAY_IDX(revprops, i, char *);
479
 
          svn_stringbuf_appendcstr(request_body, "<S:revprop>");
480
 
          svn_stringbuf_appendcstr(request_body, name);
481
 
          svn_stringbuf_appendcstr(request_body, "</S:revprop>");
482
 
          if (strcmp(name, SVN_PROP_REVISION_AUTHOR) == 0)
483
 
            lb.want_author = TRUE;
484
 
          else if (strcmp(name, SVN_PROP_REVISION_DATE) == 0)
485
 
            lb.want_date = TRUE;
486
 
          else if (strcmp(name, SVN_PROP_REVISION_LOG) == 0)
487
 
            lb.want_message = TRUE;
488
 
          else
489
 
            want_custom_revprops = TRUE;
490
 
        }
491
 
      if (revprops->nelts == 0)
492
 
        {
493
 
          svn_stringbuf_appendcstr(request_body, "<S:no-revprops/>");
494
 
        }
495
 
    }
496
 
  else
497
 
    {
498
 
      svn_stringbuf_appendcstr(request_body,
499
 
                               apr_psprintf(pool,
500
 
                                            "<S:all-revprops/>"));
501
 
      lb.want_author = lb.want_date = lb.want_message = TRUE;
502
 
      want_custom_revprops = TRUE;
503
 
    }
504
 
 
505
 
  if (want_custom_revprops)
506
 
    {
507
 
      svn_boolean_t has_log_revprops;
508
 
      SVN_ERR(svn_ra_neon__has_capability(session, &has_log_revprops,
509
 
                                          SVN_RA_CAPABILITY_LOG_REVPROPS, pool));
510
 
      if (!has_log_revprops)
511
 
        return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL,
512
 
                                _("Server does not support custom revprops"
513
 
                                  " via log"));
514
 
    }
515
 
 
516
 
 
517
 
  if (paths)
518
 
    {
519
 
      for (i = 0; i < paths->nelts; i++)
520
 
        {
521
 
          const char *this_path =
522
 
            apr_xml_quote_string(pool,
523
 
                                 APR_ARRAY_IDX(paths, i, const char *),
524
 
                                 0);
525
 
          svn_stringbuf_appendcstr(request_body, "<S:path>");
526
 
          svn_stringbuf_appendcstr(request_body, this_path);
527
 
          svn_stringbuf_appendcstr(request_body, "</S:path>");
528
 
        }
529
 
    }
530
 
 
531
 
  svn_stringbuf_appendcstr(request_body, log_request_tail);
532
 
 
533
 
  lb.receiver = receiver;
534
 
  lb.receiver_baton = receiver_baton;
535
 
  lb.subpool = svn_pool_create(pool);
536
 
  lb.limit = limit;
537
 
  lb.count = 0;
538
 
  lb.nest_level = 0;
539
 
  lb.limit_compat_bailout = FALSE;
540
 
  lb.cdata = svn_stringbuf_create("", pool);
541
 
  lb.log_entry = svn_log_entry_create(pool);
542
 
  lb.want_cdata = NULL;
543
 
  lb.cdata_encoding = NULL;
544
 
  reset_log_item(&lb);
545
 
 
546
 
  /* ras's URL may not exist in HEAD, and thus it's not safe to send
547
 
     it as the main argument to the REPORT request; it might cause
548
 
     dav_get_resource() to choke on the server.  So instead, we pass a
549
 
     baseline-collection URL, which we get from the largest of the
550
 
     START and END revisions. */
551
 
  use_rev = (start > end) ? start : end;
552
 
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
553
 
                                         ras->url->data, use_rev, pool));
554
 
  final_bc_url = svn_path_url_add_component2(bc_url, bc_relative, pool);
555
 
 
556
 
 
557
 
  err = svn_ra_neon__parsed_request(ras,
558
 
                                    "REPORT",
559
 
                                    final_bc_url,
560
 
                                    request_body->data,
561
 
                                    0,  /* ignored */
562
 
                                    NULL,
563
 
                                    log_start_element,
564
 
                                    svn_ra_neon__xml_collect_cdata,
565
 
                                    log_end_element,
566
 
                                    &lb,
567
 
                                    NULL,
568
 
                                    NULL,
569
 
                                    FALSE,
570
 
                                    pool);
571
 
  svn_pool_destroy(lb.subpool);
572
 
 
573
 
  if (err && lb.limit_compat_bailout)
574
 
    {
575
 
      svn_error_clear(err);
576
 
      err = SVN_NO_ERROR;
577
 
    }
578
 
 
579
 
  return err;
580
 
}