Fix compiler warning due to missing function prototype.
[svn.git] / subversion / libsvn_ra_neon / get_locations.c
blob46c23e70bf35b027bce90a642f71676824ecba9f
1 /*
2 * get_locations.c : RA get-locations API implementation
4 * ====================================================================
5 * Copyright (c) 2004-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-locations-report xmlns...>
50 * <S:location rev="..." path="..."/>
51 * ...
52 * </S:get-locations-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 gloc_report_elements[] =
60 { SVN_XML_NAMESPACE, "get-locations-report", ELEM_get_locations_report, 0 },
61 { SVN_XML_NAMESPACE, "location", ELEM_location, 0 },
62 { NULL }
65 typedef struct {
66 svn_ra_neon__session_t *ras;
67 apr_hash_t *hash;
68 apr_pool_t *pool;
69 } get_locations_baton_t;
72 /* This implements the `svn_ra_neon__startelem_cb_t' prototype. */
73 static svn_error_t *
74 gloc_start_element(int *elem, void *userdata, int parent_state,
75 const char *ns, const char *ln, const char **atts)
77 get_locations_baton_t *baton = userdata;
78 const svn_ra_neon__xml_elm_t *elm;
80 elm = svn_ra_neon__lookup_xml_elem(gloc_report_elements, ns, ln);
82 /* Just skip unknown elements. */
83 if (!elm)
85 *elem = NE_XML_DECLINE;
86 return SVN_NO_ERROR;
89 if (parent_state == ELEM_get_locations_report
90 && elm->id == ELEM_location)
92 svn_revnum_t rev = SVN_INVALID_REVNUM;
93 const char *path;
94 const char *r;
96 r = svn_xml_get_attr_value("rev", atts);
97 if (r)
98 rev = SVN_STR_TO_REV(r);
100 path = svn_xml_get_attr_value("path", atts);
102 if (SVN_IS_VALID_REVNUM(rev) && path)
103 apr_hash_set(baton->hash,
104 apr_pmemdup(baton->pool, &rev, sizeof(rev)),
105 sizeof(rev), apr_pstrdup(baton->pool, path));
106 else
107 return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
108 _("Expected a valid revnum and path"));
111 *elem = elm->id;
113 return SVN_NO_ERROR;
116 svn_error_t *
117 svn_ra_neon__get_locations(svn_ra_session_t *session,
118 apr_hash_t **locations,
119 const char *relative_path,
120 svn_revnum_t peg_revision,
121 apr_array_header_t *location_revisions,
122 apr_pool_t *pool)
124 svn_ra_neon__session_t *ras = session->priv;
125 svn_stringbuf_t *request_body;
126 svn_error_t *err;
127 get_locations_baton_t request_baton;
128 const char *relative_path_quoted;
129 svn_string_t bc_url, bc_relative;
130 const char *final_bc_url;
131 int i;
132 int status_code = 0;
134 *locations = apr_hash_make(pool);
136 request_body = svn_stringbuf_create("", pool);
137 svn_stringbuf_appendcstr(request_body,
138 "<?xml version=\"1.0\" encoding=\"utf-8\"?>" DEBUG_CR
139 "<S:get-locations xmlns:S=\"" SVN_XML_NAMESPACE
140 "\" xmlns:D=\"DAV:\">" DEBUG_CR);
142 svn_stringbuf_appendcstr(request_body, "<S:path>");
143 /* We need to escape the path XML-wise. */
144 relative_path_quoted = apr_xml_quote_string(pool, relative_path, 0);
145 svn_stringbuf_appendcstr(request_body, relative_path_quoted);
146 svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);
147 svn_stringbuf_appendcstr(request_body,
148 apr_psprintf(pool,
149 "<S:peg-revision>%ld"
150 "</S:peg-revision>" DEBUG_CR,
151 peg_revision));
153 for (i = 0; i < location_revisions->nelts; ++i)
155 svn_revnum_t rev = APR_ARRAY_IDX(location_revisions, i, svn_revnum_t);
156 svn_stringbuf_appendcstr(request_body,
157 apr_psprintf(pool,
158 "<S:location-revision>%ld"
159 "</S:location-revision>" DEBUG_CR,
160 rev));
163 svn_stringbuf_appendcstr(request_body, "</S:get-locations>");
165 request_baton.ras = ras;
166 request_baton.hash = *locations;
167 request_baton.pool = pool;
169 /* ras's URL may not exist in HEAD, and thus it's not safe to send
170 it as the main argument to the REPORT request; it might cause
171 dav_get_resource() to choke on the server. So instead, we pass a
172 baseline-collection URL, which we get from the peg revision. */
173 SVN_ERR(svn_ra_neon__get_baseline_info(NULL, &bc_url, &bc_relative, NULL,
174 ras, ras->url->data,
175 peg_revision,
176 pool));
177 final_bc_url = svn_path_url_add_component(bc_url.data, bc_relative.data,
178 pool);
180 err = svn_ra_neon__parsed_request(ras, "REPORT", final_bc_url,
181 request_body->data, NULL, NULL,
182 gloc_start_element, NULL, NULL,
183 &request_baton, NULL, &status_code,
184 FALSE, pool);
186 /* Map status 501: Method Not Implemented to our not implemented error.
187 1.0.x servers and older don't support this report. */
188 if (status_code == 501)
189 return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err,
190 _("'get-locations' REPORT not implemented"));
192 return err;