Fix compiler warning due to missing function prototype.
[svn.git] / subversion / libsvn_ra_neon / get_location_segments.c
blobb46609fc34d44206060ff84ab9677f748c65c596
1 /*
2 * get_location_segments.c : RA get-location-segments API implementation
4 * ====================================================================
5 * Copyright (c) 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"
40 #include "private/svn_dav_protocol.h"
41 #include "svn_private_config.h"
43 #include "ra_neon.h"
47 * Plan for processing the XML. The XML will be of the form:
49 * <S:get-location-segments-report xmlns...>
50 * <S:location [path="..."] range_start="..." range_end="..."/>
51 * ...
52 * </S:get-location-segments-report>
54 * We extract what we want at the start of <S:location>.
57 /* Elements used in a get-locations response */
58 static const svn_ra_neon__xml_elm_t gls_report_elements[] =
60 { SVN_XML_NAMESPACE, "get-location-segments-report",
61 ELEM_get_location_segments_report, 0 },
62 { SVN_XML_NAMESPACE, "location-segment", ELEM_location_segment, 0 },
63 { NULL }
66 typedef struct {
67 svn_location_segment_receiver_t receiver;
68 void *receiver_baton;
69 apr_pool_t *subpool;
70 } get_location_segments_baton_t;
72 /* This implements the `svn_ra_neon__startelem_cb_t' prototype. */
73 static svn_error_t *
74 gls_start_element(int *elem, void *userdata, int parent_state,
75 const char *ns, const char *ln, const char **atts)
77 get_location_segments_baton_t *baton = userdata;
78 const svn_ra_neon__xml_elm_t *elm;
80 /* Just skip unknown elements. */
81 if (! ((elm = svn_ra_neon__lookup_xml_elem(gls_report_elements, ns, ln))))
83 *elem = NE_XML_DECLINE;
84 return SVN_NO_ERROR;
87 if (parent_state == ELEM_get_location_segments_report
88 && elm->id == ELEM_location_segment)
90 const char *rev_str;
91 svn_revnum_t range_start = SVN_INVALID_REVNUM;
92 svn_revnum_t range_end = SVN_INVALID_REVNUM;
93 const char *path = NULL;
95 path = svn_xml_get_attr_value("path", atts);
96 rev_str = svn_xml_get_attr_value("range-start", atts);
97 if (rev_str)
98 range_start = SVN_STR_TO_REV(rev_str);
99 rev_str = svn_xml_get_attr_value("range-end", atts);
100 if (rev_str)
101 range_end = SVN_STR_TO_REV(rev_str);
103 if (SVN_IS_VALID_REVNUM(range_start) && SVN_IS_VALID_REVNUM(range_end))
105 svn_location_segment_t *segment = apr_pcalloc(baton->subpool,
106 sizeof(*segment));
107 segment->path = path;
108 segment->range_start = range_start;
109 segment->range_end = range_end;
110 SVN_ERR(baton->receiver(segment,
111 baton->receiver_baton,
112 baton->subpool));
113 svn_pool_clear(baton->subpool);
115 else
117 return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
118 _("Expected valid revision range"));
122 *elem = elm->id;
124 return SVN_NO_ERROR;
127 svn_error_t *
128 svn_ra_neon__get_location_segments(svn_ra_session_t *session,
129 const char *path,
130 svn_revnum_t peg_revision,
131 svn_revnum_t start_rev,
132 svn_revnum_t end_rev,
133 svn_location_segment_receiver_t receiver,
134 void *receiver_baton,
135 apr_pool_t *pool)
138 svn_ra_neon__session_t *ras = session->priv;
139 svn_stringbuf_t *request_body;
140 svn_error_t *err;
141 get_location_segments_baton_t request_baton;
142 svn_string_t bc_url, bc_relative;
143 const char *bc;
144 int status_code = 0;
145 apr_pool_t *subpool = svn_pool_create(pool);
147 /* Build the request body. */
148 request_body = svn_stringbuf_create("", subpool);
149 svn_stringbuf_appendcstr(request_body,
150 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
151 DEBUG_CR "<S:get-location-segments xmlns:S=\""
152 SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">" DEBUG_CR);
154 /* Tack on the path... */
155 svn_stringbuf_appendcstr(request_body, "<S:path>");
156 svn_stringbuf_appendcstr(request_body, apr_xml_quote_string(subpool, path, 0));
157 svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);
159 /* ...and maybe a peg revision... */
160 if (SVN_IS_VALID_REVNUM(peg_revision))
161 svn_stringbuf_appendcstr
162 (request_body, apr_psprintf(subpool,
163 "<S:peg-revision>%ld</S:peg-revision>"
164 DEBUG_CR, peg_revision));
166 /* ...and maybe a start revision... */
167 if (SVN_IS_VALID_REVNUM(start_rev))
168 svn_stringbuf_appendcstr
169 (request_body, apr_psprintf(subpool,
170 "<S:start-revision>%ld</S:start-revision>"
171 DEBUG_CR, start_rev));
173 /* ...and maybe an end revision. */
174 if (SVN_IS_VALID_REVNUM(end_rev))
175 svn_stringbuf_appendcstr
176 (request_body, apr_psprintf(subpool,
177 "<S:end-revision>%ld</S:end-revision>"
178 DEBUG_CR, end_rev));
180 svn_stringbuf_appendcstr(request_body, "</S:get-location-segments>");
182 request_baton.receiver = receiver;
183 request_baton.receiver_baton = receiver_baton;
184 request_baton.subpool = svn_pool_create(subpool);
186 /* ras's URL may not exist in HEAD, and thus it's not safe to send
187 it as the main argument to the REPORT request; it might cause
188 dav_get_resource() to choke on the server. So instead, we pass a
189 baseline-collection URL, which we get from the PEG_REVISION. */
190 SVN_ERR(svn_ra_neon__get_baseline_info(NULL, &bc_url, &bc_relative, NULL,
191 ras, ras->url->data,
192 peg_revision, subpool));
193 bc = svn_path_url_add_component(bc_url.data, bc_relative.data, subpool);
195 err = svn_ra_neon__parsed_request(ras, "REPORT", bc,
196 request_body->data, NULL, NULL,
197 gls_start_element, NULL, NULL,
198 &request_baton, NULL, &status_code,
199 FALSE, subpool);
200 svn_pool_destroy(request_baton.subpool);
201 svn_pool_destroy(subpool);
203 /* Map status 501: Method Not Implemented to our not implemented error.
204 1.0.x servers and older don't support this report. */
205 if (status_code == 501)
206 return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err,
207 _("'get-location-segments' REPORT "
208 "not implemented"));
210 return err;