svn_error_t *
svn_ra_neon__replay(svn_ra_session_t *session,
                    svn_revnum_t revision,
                    svn_revnum_t low_water_mark,
                    svn_boolean_t send_deltas,
                    const svn_delta_editor_t *editor,
                    void *edit_baton,
                    apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  replay_baton_t rb;

  const char *body
    = apr_psprintf(pool,
                   "<S:replay-report xmlns:S=\"svn:\">\n"
                   "  <S:revision>%ld</S:revision>\n"
                   "  <S:low-water-mark>%ld</S:low-water-mark>\n"
                   "  <S:send-deltas>%d</S:send-deltas>\n"
                   "</S:replay-report>",
                   revision, low_water_mark, send_deltas);

  memset(&rb, 0, sizeof(rb));

  rb.editor = editor;
  rb.edit_baton = edit_baton;
  rb.pool = pool;
  rb.dirs = apr_array_make(pool, 5, sizeof(dir_item_t));
  rb.prop_pool = svn_pool_create(pool);
  rb.prop_accum = svn_stringbuf_create("", rb.prop_pool);

  return svn_ra_neon__parsed_request(ras, "REPORT", ras->url->data, body,
                                     NULL, NULL,
                                     start_element,
                                     cdata_handler,
                                     end_element,
                                     &rb,
                                     NULL, /* extra headers */
                                     NULL, /* status code */
                                     FALSE, /* spool response */
                                     pool);
}
svn_error_t *
svn_ra_neon__get_location_segments(svn_ra_session_t *session,
                                   const char *path,
                                   svn_revnum_t peg_revision,
                                   svn_revnum_t start_rev,
                                   svn_revnum_t end_rev,
                                   svn_location_segment_receiver_t receiver,
                                   void *receiver_baton,
                                   apr_pool_t *pool)

{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body;
  svn_error_t *err;
  get_location_segments_baton_t request_baton;
  const char *bc_url;
  const char *bc_relative;
  const char *bc;
  int status_code = 0;
  apr_pool_t *subpool = svn_pool_create(pool);

  /* Build the request body. */
  request_body = svn_stringbuf_create("", subpool);
  svn_stringbuf_appendcstr(request_body,
                           "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                           DEBUG_CR "<S:get-location-segments xmlns:S=\""
                           SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">" DEBUG_CR);

  /* Tack on the path... */
  svn_stringbuf_appendcstr(request_body, "<S:path>");
  svn_stringbuf_appendcstr(request_body, apr_xml_quote_string(subpool, path, 0));
  svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);

  /* ...and maybe a peg revision... */
  if (SVN_IS_VALID_REVNUM(peg_revision))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:peg-revision>%ld</S:peg-revision>"
                                  DEBUG_CR, peg_revision));

  /* ...and maybe a start revision... */
  if (SVN_IS_VALID_REVNUM(start_rev))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:start-revision>%ld</S:start-revision>"
                                  DEBUG_CR, start_rev));

  /* ...and maybe an end revision. */
  if (SVN_IS_VALID_REVNUM(end_rev))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:end-revision>%ld</S:end-revision>"
                                  DEBUG_CR, end_rev));

  svn_stringbuf_appendcstr(request_body, "</S:get-location-segments>");

  request_baton.receiver = receiver;
  request_baton.receiver_baton = receiver_baton;
  request_baton.subpool = svn_pool_create(subpool);

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from the PEG_REVISION.  */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, peg_revision,
                                         subpool));
  bc = svn_path_url_add_component2(bc_url, bc_relative, subpool);

  err = svn_ra_neon__parsed_request(ras, "REPORT", bc,
                                    request_body->data, NULL, NULL,
                                    gls_start_element, NULL, NULL,
                                    &request_baton, NULL, &status_code,
                                    FALSE, subpool);
  svn_pool_destroy(request_baton.subpool);
  svn_pool_destroy(subpool);

  /* Map status 501: Method Not Implemented to our not implemented error.
     1.0.x servers and older don't support this report. */
  if (status_code == 501)
    return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                             _("'%s' REPORT not implemented"),
                             "get-location-segments");

  return err;
}
svn_error_t *
svn_ra_neon__get_locations(svn_ra_session_t *session,
                           apr_hash_t **locations,
                           const char *relative_path,
                           svn_revnum_t peg_revision,
                           const apr_array_header_t *location_revisions,
                           apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body;
  svn_error_t *err;
  get_locations_baton_t request_baton;
  const char *relative_path_quoted;
  const char *bc_url;
  const char *bc_relative;
  const char *final_bc_url;
  int i;
  int status_code = 0;

  *locations = apr_hash_make(pool);

  request_body = svn_stringbuf_create("", pool);
  svn_stringbuf_appendcstr(request_body,
                           "<?xml version=\"1.0\" encoding=\"utf-8\"?>" DEBUG_CR
                           "<S:get-locations xmlns:S=\"" SVN_XML_NAMESPACE
                           "\" xmlns:D=\"DAV:\">" DEBUG_CR);

  svn_stringbuf_appendcstr(request_body, "<S:path>");
  /* We need to escape the path XML-wise. */
  relative_path_quoted = apr_xml_quote_string(pool, relative_path, 0);
  svn_stringbuf_appendcstr(request_body, relative_path_quoted);
  svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:peg-revision>%ld"
                                        "</S:peg-revision>" DEBUG_CR,
                                        peg_revision));

  for (i = 0; i < location_revisions->nelts; ++i)
    {
      svn_revnum_t rev = APR_ARRAY_IDX(location_revisions, i, svn_revnum_t);
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:location-revision>%ld"
                                            "</S:location-revision>" DEBUG_CR,
                                            rev));
    }

  svn_stringbuf_appendcstr(request_body, "</S:get-locations>");

  request_baton.ras = ras;
  request_baton.hash = *locations;
  request_baton.pool = pool;

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from the peg revision.  */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, peg_revision, pool));
  final_bc_url = svn_path_url_add_component2(bc_url, bc_relative, pool);

  err = svn_ra_neon__parsed_request(ras, "REPORT", final_bc_url,
                                    request_body->data, NULL, NULL,
                                    gloc_start_element, NULL, NULL,
                                    &request_baton, NULL, &status_code,
                                    FALSE, pool);

  /* Map status 501: Method Not Implemented to our not implemented error.
     1.0.x servers and older don't support this report. */
  if (status_code == 501)
    return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                             _("'%s' REPORT not implemented"), "get-locations");

  return err;
}
/* Request a mergeinfo-report from the URL attached to SESSION,
   and fill in the CATALOG with the results.  */
svn_error_t *
svn_ra_neon__get_mergeinfo(svn_ra_session_t *session,
                           svn_mergeinfo_catalog_t *catalog,
                           const apr_array_header_t *paths,
                           svn_revnum_t revision,
                           svn_mergeinfo_inheritance_t inherit,
                           svn_boolean_t include_descendants,
                           apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body = svn_stringbuf_create("", pool);
  struct mergeinfo_baton mb;
  const char *bc_url;
  const char *bc_relative;
  const char *final_bc_url;

  static const char minfo_report_head[] =
    "<S:" SVN_DAV__MERGEINFO_REPORT " xmlns:S=\"" SVN_XML_NAMESPACE "\">"
    DEBUG_CR;

  static const char minfo_report_tail[] =
    "</S:" SVN_DAV__MERGEINFO_REPORT ">" DEBUG_CR;

  *catalog = NULL;

  /* Construct the request body. */
  svn_stringbuf_appendcstr(request_body, minfo_report_head);
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:revision>%ld"
                                        "</S:revision>", revision));
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:inherit>%s"
                                        "</S:inherit>",
                                        svn_inheritance_to_word(inherit)));

  if (include_descendants)
    {
      /* Send it only if true; server will default to "no". */
      svn_stringbuf_appendcstr(request_body,
                               "<S:include-descendants>yes"
                               "</S:include-descendants>");
    }

  if (paths)
    {
      int i;

      for (i = 0; i < paths->nelts; i++)
        {
          const char *this_path =
            apr_xml_quote_string(pool,
                                 ((const char **)paths->elts)[i],
                                 0);
          svn_stringbuf_appendcstr(request_body, "<S:path>");
          svn_stringbuf_appendcstr(request_body, this_path);
          svn_stringbuf_appendcstr(request_body, "</S:path>");
        }
    }

  svn_stringbuf_appendcstr(request_body, minfo_report_tail);

  mb.pool = pool;
  mb.curr_path = svn_stringbuf_create("", pool);
  mb.curr_info = svn_stringbuf_create("", pool);
  mb.catalog = apr_hash_make(pool);
  mb.err = SVN_NO_ERROR;

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from END. */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, revision, pool));
  final_bc_url = svn_path_url_add_component2(bc_url, bc_relative, pool);

  SVN_ERR(svn_ra_neon__parsed_request(ras,
                                      "REPORT",
                                      final_bc_url,
                                      request_body->data,
                                      NULL, NULL,
                                      start_element,
                                      cdata_handler,
                                      end_element,
                                      &mb,
                                      NULL,
                                      NULL,
                                      FALSE,
                                      pool));

  if (mb.err == SVN_NO_ERROR && apr_hash_count(mb.catalog))
    *catalog = mb.catalog;

  return mb.err;
}
svn_error_t *
svn_ra_neon__get_locks(svn_ra_session_t *session,
                       apr_hash_t **locks,
                       const char *path,
                       svn_depth_t depth,
                       apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  const char *body, *url, *rel_path;
  svn_error_t *err;
  int status_code = 0;
  get_locks_baton_t baton;

  /* We always run the report on the 'public' URL, which represents
     HEAD anyway.  If the path doesn't exist in HEAD, then there can't
     possibly be a lock, so we just return no locks. */
  url = svn_path_url_add_component2(ras->url->data, path, pool);

  SVN_ERR(svn_ra_neon__get_path_relative_to_root(session, &rel_path,
                                                 url, pool));

  baton.lock_hash = apr_hash_make(pool);
  baton.path = svn_fspath__canonicalize(rel_path, pool);
  baton.requested_depth = depth;
  baton.pool = pool;
  baton.scratchpool = svn_pool_create(pool);
  baton.current_lock = NULL;
  baton.encoding = NULL;
  baton.cdata_accum = svn_stringbuf_create("", pool);

  body = apr_psprintf(pool,
                      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                      "<S:get-locks-report xmlns:S=\"" SVN_XML_NAMESPACE "\" "
                      "xmlns:D=\"DAV:\" depth=\"%s\">"
                      "</S:get-locks-report>",
                      svn_depth_to_word(depth));

  err = svn_ra_neon__parsed_request(ras, "REPORT", url,
                                    body, NULL, NULL,
                                    getlocks_start_element,
                                    getlocks_cdata_handler,
                                    getlocks_end_element,
                                    &baton,
                                    NULL, /* extra headers */
                                    &status_code,
                                    FALSE,
                                    pool);

  svn_pool_destroy(baton.scratchpool);

  if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
    {
      svn_error_clear(err);
      *locks = baton.lock_hash;
      return SVN_NO_ERROR;
    }

  /* ### Should svn_ra_neon__parsed_request() take care of storing auth
     ### info itself? */
  err = svn_ra_neon__maybe_store_auth_info_after_result(err, ras, pool);

  /* Map status 501: Method Not Implemented to our not implemented error.
     1.0.x servers and older don't support this report. */
  if (status_code == 501)
    return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                            _("Server does not support locking features"));

  if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
    return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                            _("Server does not support locking features"));

  else if (err)
    return err;

  *locks = baton.lock_hash;
  return SVN_NO_ERROR;
}
Beispiel #6
0
svn_error_t * svn_ra_neon__get_props(apr_hash_t **results,
                                     svn_ra_neon__session_t *sess,
                                     const char *url,
                                     int depth,
                                     const char *label,
                                     const ne_propname *which_props,
                                     apr_pool_t *pool)
{
  propfind_ctx_t pc;
  svn_stringbuf_t *body;
  apr_hash_t *extra_headers = apr_hash_make(pool);

  svn_ra_neon__add_depth_header(extra_headers, depth);

  /* If we have a label, use it. */
  if (label != NULL)
    apr_hash_set(extra_headers, "Label", 5, label);

  /* It's easier to roll our own PROPFIND here than use neon's current
     interfaces. */
  /* The start of the request body is fixed: */
  body = svn_stringbuf_create
    ("<?xml version=\"1.0\" encoding=\"utf-8\"?>" DEBUG_CR
     "<propfind xmlns=\"DAV:\">" DEBUG_CR, pool);

  /* Are we asking for specific propert(y/ies), or just all of them? */
  if (which_props)
    {
      int n;
      apr_pool_t *iterpool = svn_pool_create(pool);

      svn_stringbuf_appendcstr(body, "<prop>" DEBUG_CR);
      for (n = 0; which_props[n].name != NULL; n++)
        {
          svn_pool_clear(iterpool);
          svn_stringbuf_appendcstr
            (body, apr_pstrcat(iterpool, "<", which_props[n].name, " xmlns=\"",
                               which_props[n].nspace, "\"/>" DEBUG_CR, NULL));
        }
      svn_stringbuf_appendcstr(body, "</prop></propfind>" DEBUG_CR);
      svn_pool_destroy(iterpool);
    }
  else
    {
      svn_stringbuf_appendcstr(body, "<allprop/></propfind>" DEBUG_CR);
    }

  /* Initialize our baton. */
  memset(&pc, 0, sizeof(pc));
  pc.pool = pool;
  pc.propbuffer = apr_hash_make(pool);
  pc.props = apr_hash_make(pool);
  pc.cdata = svn_stringbuf_create("", pool);

  /* Create and dispatch the request! */
  SVN_ERR(svn_ra_neon__parsed_request(sess, "PROPFIND", url,
                                      body->data, 0,
                                      set_parser,
                                      start_element,
                                      svn_ra_neon__xml_collect_cdata,
                                      end_element,
                                      &pc, extra_headers, NULL, FALSE, pool));

  *results = pc.props;
  return SVN_NO_ERROR;
}