In the command-line client, forbid
[svn.git] / subversion / libsvn_ra_neon / get_dated_rev.c
blob8a5ce64068f54b4ea54b746aab7900db95a8227e
1 /*
2 * date_rev.c : RA get-dated-revision API implementation
4 * ====================================================================
5 * Copyright (c) 2000-2007 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
21 #define APR_WANT_STRFUNC
22 #include <apr_want.h> /* for strcmp() */
24 #include <apr_pools.h>
25 #include <apr_tables.h>
26 #include <apr_strings.h>
27 #include <apr_md5.h>
28 #include <apr_xml.h>
30 #include <ne_basic.h>
32 #include "svn_error.h"
33 #include "svn_pools.h"
34 #include "svn_ra.h"
35 #include "../libsvn_ra/ra_loader.h"
36 #include "svn_path.h"
37 #include "svn_xml.h"
38 #include "svn_dav.h"
39 #include "svn_time.h"
41 #include "private/svn_dav_protocol.h"
42 #include "svn_private_config.h"
44 #include "ra_neon.h"
47 /* -------------------------------------------------------------------------
49 ** DATED REV REPORT HANDLING
51 ** DeltaV provides no mechanism for mapping a date to a revision, so
52 ** we use a custom report, S:dated-rev-report. The request contains a
53 ** DAV:creationdate element giving the requested date; the response
54 ** contains a DAV:version-name element giving the most recent revision
55 ** as of that date.
57 ** Since this report is so simple, we don't bother with validation or
58 ** baton structures or anything; we just set the revision number in
59 ** the end-element handler for DAV:version-name.
62 /* Elements used in a dated-rev-report response */
63 static const svn_ra_neon__xml_elm_t drev_report_elements[] =
65 { SVN_XML_NAMESPACE, "dated-rev-report", ELEM_dated_rev_report, 0 },
66 { "DAV:", "version-name", ELEM_version_name, SVN_RA_NEON__XML_CDATA },
67 { NULL }
70 typedef struct
72 svn_stringbuf_t *cdata;
73 apr_pool_t *pool;
74 svn_revnum_t revision;
75 } drev_baton_t;
78 /* This implements the `svn_ra_neon__xml_startelm_cb' prototype. */
79 static svn_error_t *
80 drev_start_element(int *elem, void *baton, int parent,
81 const char *nspace, const char *name, const char **atts)
83 const svn_ra_neon__xml_elm_t *elm =
84 svn_ra_neon__lookup_xml_elem(drev_report_elements, nspace, name);
85 drev_baton_t *b = baton;
87 *elem = elm ? elm->id : SVN_RA_NEON__XML_DECLINE;
88 if (!elm)
89 return SVN_NO_ERROR;
91 if (elm->id == ELEM_version_name)
92 b->cdata = svn_stringbuf_create("", b->pool);
94 return SVN_NO_ERROR;
97 /* This implements the `svn_ra_neon__xml_endelm_cb' prototype. */
98 static svn_error_t *
99 drev_end_element(void *baton, int state,
100 const char *nspace, const char *name)
102 drev_baton_t *b = baton;
104 if (state == ELEM_version_name && b->cdata)
106 b->revision = SVN_STR_TO_REV(b->cdata->data);
107 b->cdata = NULL;
110 return SVN_NO_ERROR;
113 svn_error_t *svn_ra_neon__get_dated_revision(svn_ra_session_t *session,
114 svn_revnum_t *revision,
115 apr_time_t timestamp,
116 apr_pool_t *pool)
118 svn_ra_neon__session_t *ras = session->priv;
119 const char *body;
120 const char *vcc_url;
121 svn_error_t *err;
122 drev_baton_t *b = apr_palloc(pool, sizeof(*b));
124 b->pool = pool;
125 b->cdata = NULL;
126 b->revision = SVN_INVALID_REVNUM;
128 /* Run the 'dated-rev-report' on the VCC url, which is always
129 guaranteed to exist. */
130 SVN_ERR(svn_ra_neon__get_vcc(&vcc_url, ras, ras->root.path, pool));
132 body = apr_psprintf(pool,
133 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
134 "<S:dated-rev-report xmlns:S=\"" SVN_XML_NAMESPACE "\" "
135 "xmlns:D=\"DAV:\">"
136 "<D:" SVN_DAV__CREATIONDATE ">%s</D:"
137 SVN_DAV__CREATIONDATE "></S:dated-rev-report>",
138 svn_time_to_cstring(timestamp, pool));
140 err = svn_ra_neon__parsed_request(ras, "REPORT",
141 vcc_url, body, NULL, NULL,
142 drev_start_element,
143 svn_ra_neon__xml_collect_cdata,
144 drev_end_element,
145 b, NULL, NULL, FALSE, pool);
146 if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
147 return svn_error_quick_wrap(err, _("Server does not support date-based "
148 "operations"));
149 else if (err)
150 return err;
152 if (b->revision == SVN_INVALID_REVNUM)
153 return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
154 _("Invalid server response to dated-rev request"));
156 *revision = b->revision;
157 return SVN_NO_ERROR;