/* * getlocations.c : entry point for get_locations RA functions for ra_serf * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== */ #include #include #include "svn_hash.h" #include "svn_path.h" #include "svn_pools.h" #include "svn_ra.h" #include "svn_xml.h" #include "svn_private_config.h" #include "../libsvn_ra/ra_loader.h" #include "ra_serf.h" /* * This enum represents the current state of our XML parsing for a REPORT. */ enum loc_state_e { INITIAL = 0, REPORT, LOCATION }; typedef struct loc_context_t { /* pool to allocate memory from */ apr_pool_t *pool; /* parameters set by our caller */ const char *path; const apr_array_header_t *location_revisions; svn_revnum_t peg_revision; /* Returned location hash */ apr_hash_t *paths; } loc_context_t; #define D_ "DAV:" #define S_ SVN_XML_NAMESPACE static const svn_ra_serf__xml_transition_t getloc_ttable[] = { { INITIAL, S_, "get-locations-report", REPORT, FALSE, { NULL }, FALSE }, { REPORT, S_, "location", LOCATION, FALSE, { "?rev", "?path", NULL }, TRUE }, { 0 } }; /* Conforms to svn_ra_serf__xml_closed_t */ static svn_error_t * getloc_closed(svn_ra_serf__xml_estate_t *xes, void *baton, int leaving_state, const svn_string_t *cdata, apr_hash_t *attrs, apr_pool_t *scratch_pool) { loc_context_t *loc_ctx = baton; const char *revstr; const char *path; SVN_ERR_ASSERT(leaving_state == LOCATION); revstr = svn_hash_gets(attrs, "rev"); path = svn_hash_gets(attrs, "path"); if (revstr != NULL && path != NULL) { svn_revnum_t rev = SVN_STR_TO_REV(revstr); apr_hash_set(loc_ctx->paths, apr_pmemdup(loc_ctx->pool, &rev, sizeof(rev)), sizeof(rev), apr_pstrdup(loc_ctx->pool, path)); } return SVN_NO_ERROR; } /* Implements svn_ra_serf__request_body_delegate_t */ static svn_error_t * create_get_locations_body(serf_bucket_t **body_bkt, void *baton, serf_bucket_alloc_t *alloc, apr_pool_t *pool) { serf_bucket_t *buckets; loc_context_t *loc_ctx = baton; int i; buckets = serf_bucket_aggregate_create(alloc); svn_ra_serf__add_open_tag_buckets(buckets, alloc, "S:get-locations", "xmlns:S", SVN_XML_NAMESPACE, "xmlns:D", "DAV:", NULL); svn_ra_serf__add_tag_buckets(buckets, "S:path", loc_ctx->path, alloc); svn_ra_serf__add_tag_buckets(buckets, "S:peg-revision", apr_ltoa(pool, loc_ctx->peg_revision), alloc); for (i = 0; i < loc_ctx->location_revisions->nelts; i++) { svn_revnum_t rev = APR_ARRAY_IDX(loc_ctx->location_revisions, i, svn_revnum_t); svn_ra_serf__add_tag_buckets(buckets, "S:location-revision", apr_ltoa(pool, rev), alloc); } svn_ra_serf__add_close_tag_buckets(buckets, alloc, "S:get-locations"); *body_bkt = buckets; return SVN_NO_ERROR; } svn_error_t * svn_ra_serf__get_locations(svn_ra_session_t *ra_session, apr_hash_t **locations, const char *path, svn_revnum_t peg_revision, const apr_array_header_t *location_revisions, apr_pool_t *pool) { loc_context_t *loc_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url; svn_error_t *err; loc_ctx = apr_pcalloc(pool, sizeof(*loc_ctx)); loc_ctx->pool = pool; loc_ctx->path = path; loc_ctx->peg_revision = peg_revision; loc_ctx->location_revisions = location_revisions; loc_ctx->paths = apr_hash_make(loc_ctx->pool); *locations = loc_ctx->paths; SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, session, NULL /* conn */, NULL /* url */, peg_revision, pool, pool)); xmlctx = svn_ra_serf__xml_context_create(getloc_ttable, NULL, getloc_closed, NULL, loc_ctx, pool); handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "REPORT"; handler->path = req_url; handler->body_delegate = create_get_locations_body; handler->body_delegate_baton = loc_ctx; handler->body_type = "text/xml"; handler->conn = session->conns[0]; handler->session = session; err = svn_ra_serf__context_run_one(handler, pool); SVN_ERR(svn_error_compose_create( svn_ra_serf__error_on_status(handler->sline, req_url, handler->location), err)); return SVN_NO_ERROR; }