In the command-line client, forbid
[svn.git] / subversion / libsvn_ra_serf / getlocationsegments.c
blobe1c1f5d204489b583cf5e0b9c912d139f255fa67
1 /*
2 * getlocationsegments.c : entry point for get_location_segments
3 * RA functions for ra_serf
5 * ====================================================================
6 * Copyright (c) 2007 CollabNet. All rights reserved.
8 * This software is licensed as described in the file COPYING, which
9 * you should have received as part of this distribution. The terms
10 * are also available at http://subversion.tigris.org/license-1.html.
11 * If newer versions of this license are posted there, you may use a
12 * newer version instead, at your option.
14 * This software consists of voluntary contributions made by many
15 * individuals. For exact contribution history, see the revision
16 * history and logs, available at http://subversion.tigris.org/.
17 * ====================================================================
22 #include <apr_uri.h>
23 #include <expat.h>
24 #include <serf.h>
26 #include "svn_pools.h"
27 #include "svn_ra.h"
28 #include "svn_xml.h"
29 #include "svn_path.h"
30 #include "svn_private_config.h"
31 #include "../libsvn_ra/ra_loader.h"
33 #include "ra_serf.h"
37 typedef struct {
38 /* location segment callback function/baton */
39 svn_location_segment_receiver_t receiver;
40 void *receiver_baton;
42 /* subpool used only as long as a single receiver invocation */
43 apr_pool_t *subpool;
45 /* True iff we're looking at a child of the outer report tag */
46 svn_boolean_t inside_report;
48 /* Return error code */
49 svn_error_t *error;
51 int status_code;
53 svn_boolean_t done;
54 } gls_context_t;
57 static svn_error_t *
58 start_gls(svn_ra_serf__xml_parser_t *parser,
59 void *userData,
60 svn_ra_serf__dav_props_t name,
61 const char **attrs)
63 gls_context_t *gls_ctx = userData;
65 if ((! gls_ctx->inside_report)
66 && strcmp(name.name, "get-location-segments-report") == 0)
68 gls_ctx->inside_report = TRUE;
70 else if (gls_ctx->inside_report
71 && strcmp(name.name, "location-segment") == 0)
73 const char *rev_str;
74 svn_revnum_t range_start = SVN_INVALID_REVNUM;
75 svn_revnum_t range_end = SVN_INVALID_REVNUM;
76 const char *path = NULL;
78 path = svn_xml_get_attr_value("path", attrs);
79 rev_str = svn_xml_get_attr_value("range-start", attrs);
80 if (rev_str)
81 range_start = SVN_STR_TO_REV(rev_str);
82 rev_str = svn_xml_get_attr_value("range-end", attrs);
83 if (rev_str)
84 range_end = SVN_STR_TO_REV(rev_str);
86 if (SVN_IS_VALID_REVNUM(range_start) && SVN_IS_VALID_REVNUM(range_end))
88 svn_location_segment_t *segment = apr_pcalloc(gls_ctx->subpool,
89 sizeof(*segment));
90 segment->path = path;
91 segment->range_start = range_start;
92 segment->range_end = range_end;
93 SVN_ERR(gls_ctx->receiver(segment,
94 gls_ctx->receiver_baton,
95 gls_ctx->subpool));
96 svn_pool_clear(gls_ctx->subpool);
98 else
100 return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
101 _("Expected valid revision range"));
105 return SVN_NO_ERROR;
108 static svn_error_t *
109 end_gls(svn_ra_serf__xml_parser_t *parser,
110 void *userData,
111 svn_ra_serf__dav_props_t name)
113 gls_context_t *gls_ctx = userData;
115 if (strcmp(name.name, "get-location-segments-report") == 0)
116 gls_ctx->inside_report = FALSE;
118 return SVN_NO_ERROR;
121 svn_error_t *
122 svn_ra_serf__get_location_segments(svn_ra_session_t *ra_session,
123 const char *path,
124 svn_revnum_t peg_revision,
125 svn_revnum_t start_rev,
126 svn_revnum_t end_rev,
127 svn_location_segment_receiver_t receiver,
128 void *receiver_baton,
129 apr_pool_t *pool)
131 gls_context_t *gls_ctx;
132 svn_ra_serf__session_t *session = ra_session->priv;
133 svn_ra_serf__handler_t *handler;
134 svn_ra_serf__xml_parser_t *parser_ctx;
135 serf_bucket_t *buckets, *tmp;
136 const char *relative_url, *basecoll_url, *req_url;
137 svn_error_t *err;
139 gls_ctx = apr_pcalloc(pool, sizeof(*gls_ctx));
140 gls_ctx->receiver = receiver;
141 gls_ctx->receiver_baton = receiver_baton;
142 gls_ctx->subpool = svn_pool_create(pool);
143 gls_ctx->inside_report = FALSE;
144 gls_ctx->error = SVN_NO_ERROR;
145 gls_ctx->done = FALSE;
147 buckets = serf_bucket_aggregate_create(session->bkt_alloc);
149 tmp = SERF_BUCKET_SIMPLE_STRING_LEN("<S:get-location-segments xmlns:S=\"",
150 sizeof("<S:get-location-segments "
151 "xmlns:S=\"")-1,
152 session->bkt_alloc);
153 serf_bucket_aggregate_append(buckets, tmp);
155 tmp = SERF_BUCKET_SIMPLE_STRING_LEN(SVN_XML_NAMESPACE,
156 sizeof(SVN_XML_NAMESPACE)-1,
157 session->bkt_alloc);
158 serf_bucket_aggregate_append(buckets, tmp);
160 tmp = SERF_BUCKET_SIMPLE_STRING_LEN("\">",
161 sizeof("\">")-1,
162 session->bkt_alloc);
163 serf_bucket_aggregate_append(buckets, tmp);
165 svn_ra_serf__add_tag_buckets(buckets,
166 "S:path", path,
167 session->bkt_alloc);
169 svn_ra_serf__add_tag_buckets(buckets,
170 "S:peg-revision",
171 apr_ltoa(pool, peg_revision),
172 session->bkt_alloc);
174 svn_ra_serf__add_tag_buckets(buckets,
175 "S:start-revision",
176 apr_ltoa(pool, start_rev),
177 session->bkt_alloc);
179 svn_ra_serf__add_tag_buckets(buckets,
180 "S:end-revision",
181 apr_ltoa(pool, end_rev),
182 session->bkt_alloc);
184 tmp = SERF_BUCKET_SIMPLE_STRING_LEN("</S:get-location-segments>",
185 sizeof("</S:get-location-segments>")-1,
186 session->bkt_alloc);
187 serf_bucket_aggregate_append(buckets, tmp);
189 SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
190 session, NULL, peg_revision, pool));
192 req_url = svn_path_url_add_component(basecoll_url, relative_url, pool);
194 handler = apr_pcalloc(pool, sizeof(*handler));
196 handler->method = "REPORT";
197 handler->path = req_url;
198 handler->body_buckets = buckets;
199 handler->body_type = "text/xml";
200 handler->conn = session->conns[0];
201 handler->session = session;
203 parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
205 parser_ctx->pool = pool;
206 parser_ctx->user_data = gls_ctx;
207 parser_ctx->start = start_gls;
208 parser_ctx->end = end_gls;
209 parser_ctx->status_code = &gls_ctx->status_code;
210 parser_ctx->done = &gls_ctx->done;
212 handler->response_handler = svn_ra_serf__handle_xml_parser;
213 handler->response_baton = parser_ctx;
215 svn_ra_serf__request_create(handler);
217 err = svn_ra_serf__context_run_wait(&gls_ctx->done, session, pool);
219 if (gls_ctx->error || parser_ctx->error)
221 svn_error_clear(err);
222 err = SVN_NO_ERROR;
223 SVN_ERR(gls_ctx->error);
224 SVN_ERR(parser_ctx->error);
227 svn_pool_destroy(gls_ctx->subpool);
229 if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE))
230 return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err, NULL);
232 return err;