Exemplo n.º 1
0
  void
  Path::addComponent(const char * component)
  {
    Pool pool;

    if (0 == component)
      return;

    // in case of an empty string, return
    if (*component == 0)
      return;

    // if the @a component is absolute, simply
    // use it
    if (isAbsolute(component))
    {
      m_path = component;
      return;
    }

    if (Url::isValid(m_path.c_str()))
    {
      const char * newPath =
        svn_path_url_add_component(m_path.c_str(),
                                   component,
                                   pool);
      m_path = newPath;
    }
    else
    {
      svn_stringbuf_t * pathStringbuf =
        svn_stringbuf_create(m_path.c_str(), pool);

      svn_path_add_component(pathStringbuf,
                             component);

      m_path = pathStringbuf->data;
    }
  }
Exemplo n.º 2
0
svn_error_t *
svn_ra_serf__get_location_segments(svn_ra_session_t *ra_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)
{
  gls_context_t *gls_ctx;
  svn_ra_serf__session_t *session = ra_session->priv;
  svn_ra_serf__handler_t *handler;
  svn_ra_serf__xml_parser_t *parser_ctx;
  serf_bucket_t *buckets;
  const char *relative_url, *basecoll_url, *req_url;
  svn_error_t *err;

  gls_ctx = apr_pcalloc(pool, sizeof(*gls_ctx));
  gls_ctx->receiver = receiver;
  gls_ctx->receiver_baton = receiver_baton;
  gls_ctx->subpool = svn_pool_create(pool);
  gls_ctx->inside_report = FALSE;
  gls_ctx->error = SVN_NO_ERROR;
  gls_ctx->done = FALSE;

  buckets = serf_bucket_aggregate_create(session->bkt_alloc);

  svn_ra_serf__add_open_tag_buckets(buckets, session->bkt_alloc,
                                    "S:get-location-segments",
                                    "xmlns:S", SVN_XML_NAMESPACE,
                                    NULL);

  svn_ra_serf__add_tag_buckets(buckets,
                               "S:path", path,
                               session->bkt_alloc);

  svn_ra_serf__add_tag_buckets(buckets,
                               "S:peg-revision",
                               apr_ltoa(pool, peg_revision),
                               session->bkt_alloc);

  svn_ra_serf__add_tag_buckets(buckets,
                               "S:start-revision",
                               apr_ltoa(pool, start_rev),
                               session->bkt_alloc);

  svn_ra_serf__add_tag_buckets(buckets,
                               "S:end-revision",
                               apr_ltoa(pool, end_rev),
                               session->bkt_alloc);

  svn_ra_serf__add_close_tag_buckets(buckets, session->bkt_alloc,
                                     "S:get-location-segments");

  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
                                         NULL, NULL, peg_revision, NULL, pool));

  req_url = svn_path_url_add_component(basecoll_url, relative_url, pool);

  handler = apr_pcalloc(pool, sizeof(*handler));

  handler->method = "REPORT";
  handler->path = req_url;
  handler->body_buckets = buckets;
  handler->body_type = "text/xml";
  handler->conn = session->conns[0];
  handler->session = session;

  parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));

  parser_ctx->pool = pool;
  parser_ctx->user_data = gls_ctx;
  parser_ctx->start = start_gls;
  parser_ctx->end = end_gls;
  parser_ctx->status_code = &gls_ctx->status_code;
  parser_ctx->done = &gls_ctx->done;

  handler->response_handler = svn_ra_serf__handle_xml_parser;
  handler->response_baton = parser_ctx;

  svn_ra_serf__request_create(handler);

  err = svn_ra_serf__context_run_wait(&gls_ctx->done, session, pool);

  if (gls_ctx->error || parser_ctx->error)
    {
      svn_error_clear(err);
      err = SVN_NO_ERROR;
      SVN_ERR(gls_ctx->error);
      SVN_ERR(parser_ctx->error);
    }

  if (gls_ctx->inside_report)
    err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                            _("Location segment report failed on '%s'@'%ld'"),
                              path, peg_revision);

  SVN_ERR(svn_ra_serf__error_on_status(gls_ctx->status_code, handler->path));

  svn_pool_destroy(gls_ctx->subpool);

  if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE))
    return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err, NULL);

  return err;
}
Exemplo n.º 3
0
Arquivo: info.c Projeto: vocho/openqnx
/* Helper func for recursively fetching svn_dirent_t's from a remote
   directory and pushing them at an info-receiver callback.

   DEPTH is the depth starting at DIR, even though RECEIVER is never
   invoked on DIR: if DEPTH is svn_depth_immediates, then invoke
   RECEIVER on all children of DIR, but none of their children; if
   svn_depth_files, then invoke RECEIVER on file children of DIR but
   not on subdirectories; if svn_depth_infinity, recurse fully.
*/
static svn_error_t *
push_dir_info(svn_ra_session_t *ra_session,
              const char *session_URL,
              const char *dir,
              svn_revnum_t rev,
              const char *repos_UUID,
              const char *repos_root,
              svn_info_receiver_t receiver,
              void *receiver_baton,
              svn_depth_t depth,
              svn_client_ctx_t *ctx,
              apr_hash_t *locks,
              apr_pool_t *pool)
{
  apr_hash_t *tmpdirents;
  svn_dirent_t *the_ent;
  svn_info_t *info;
  apr_hash_index_t *hi;
  apr_pool_t *subpool = svn_pool_create(pool);

  SVN_ERR(svn_ra_get_dir2(ra_session, &tmpdirents, NULL, NULL,
                          dir, rev, DIRENT_FIELDS, pool));

  for (hi = apr_hash_first(pool, tmpdirents); hi; hi = apr_hash_next(hi))
    {
      const char *path, *URL, *fs_path;
      const void *key;
      svn_lock_t *lock;
      void *val;

      svn_pool_clear(subpool);

      if (ctx->cancel_func)
        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));

      apr_hash_this(hi, &key, NULL, &val);
      the_ent = val;

      path = svn_path_join(dir, key, subpool);
      URL  = svn_path_url_add_component(session_URL, key, subpool);

      fs_path = svn_path_is_child(repos_root, URL, subpool);
      fs_path = apr_pstrcat(subpool, "/", fs_path, NULL);
      fs_path = svn_path_uri_decode(fs_path, subpool);

      lock = apr_hash_get(locks, fs_path, APR_HASH_KEY_STRING);

      SVN_ERR(build_info_from_dirent(&info, the_ent, lock, URL, rev,
                                     repos_UUID, repos_root, subpool));

      if (depth >= svn_depth_immediates
          || (depth == svn_depth_files && the_ent->kind == svn_node_file))
        {
          SVN_ERR(receiver(receiver_baton, path, info, subpool));
        }

      if (depth == svn_depth_infinity && the_ent->kind == svn_node_dir)
        {
          SVN_ERR(push_dir_info(ra_session, URL, path,
                                rev, repos_UUID, repos_root,
                                receiver, receiver_baton,
                                depth, ctx, locks, subpool));
        }
    }

  svn_pool_destroy(subpool);

  return SVN_NO_ERROR;
}
Exemplo n.º 4
0
svn_error_t *svn_ra_neon__get_baseline_info(svn_boolean_t *is_dir,
                                            svn_string_t *bc_url,
                                            svn_string_t *bc_relative,
                                            svn_revnum_t *latest_rev,
                                            svn_ra_neon__session_t *sess,
                                            const char *url,
                                            svn_revnum_t revision,
                                            apr_pool_t *pool)
{
  svn_ra_neon__resource_t *baseline_rsrc, *rsrc;
  const svn_string_t *my_bc_url;
  svn_string_t my_bc_rel;

  /* Go fetch a BASELINE_RSRC that contains specific properties we
     want.  This routine will also fill in BC_RELATIVE as best it
     can. */
  SVN_ERR(svn_ra_neon__get_baseline_props(&my_bc_rel,
                                          &baseline_rsrc,
                                          sess,
                                          url,
                                          revision,
                                          baseline_props, /* specific props */
                                          pool));

  /* baseline_rsrc now points at the Baseline. We will checkout from
     the DAV:baseline-collection.  The revision we are checking out is
     in DAV:version-name */

  /* Allocate our own copy of bc_url regardless. */
  my_bc_url = apr_hash_get(baseline_rsrc->propset,
                           SVN_RA_NEON__PROP_BASELINE_COLLECTION,
                           APR_HASH_KEY_STRING);
  if (my_bc_url == NULL)
    {
      /* ### better error reporting... */
      /* ### need an SVN_ERR here */
      return svn_error_create(APR_EGENERAL, NULL,
                              _("'DAV:baseline-collection' was not present "
                                "on the baseline resource"));
    }

  /* maybe return bc_url to the caller */
  if (bc_url)
    *bc_url = *my_bc_url;

  if (latest_rev != NULL)
    {
      const svn_string_t *vsn_name= apr_hash_get(baseline_rsrc->propset,
                                                 SVN_RA_NEON__PROP_VERSION_NAME,
                                                 APR_HASH_KEY_STRING);
      if (vsn_name == NULL)
        {
          /* ### better error reporting... */

          /* ### need an SVN_ERR here */
          return svn_error_createf(APR_EGENERAL, NULL,
                                   _("'%s' was not present on the baseline "
                                     "resource"),
                                   "DAV:" SVN_DAV__VERSION_NAME);
        }
      *latest_rev = SVN_STR_TO_REV(vsn_name->data);
    }

  if (is_dir != NULL)
    {
      /* query the DAV:resourcetype of the full, assembled URL. */
      const char *full_bc_url = svn_path_url_add_component(my_bc_url->data,
                                                           my_bc_rel.data,
                                                           pool);
      SVN_ERR(svn_ra_neon__get_starting_props(&rsrc, sess, full_bc_url,
                                              NULL, pool));
      *is_dir = rsrc->is_collection;
    }

  if (bc_relative)
    *bc_relative = my_bc_rel;

  return SVN_NO_ERROR;
}
Exemplo n.º 5
0
svn_error_t *
svn_ra_neon__do_stat(svn_ra_session_t *session,
                     const char *path,
                     svn_revnum_t revision,
                     svn_dirent_t **dirent,
                     apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  const char *url = ras->url->data;
  const char *final_url;
  apr_hash_t *resources;
  apr_hash_index_t *hi;
  svn_error_t *err;

  /* If we were given a relative path to append, append it. */
  if (path)
    url = svn_path_url_add_component(url, path, pool);

  /* Invalid revision means HEAD, which is just the public URL. */
  if (! SVN_IS_VALID_REVNUM(revision))
    {
      final_url = url;
    }
  else
    {
      /* Else, convert (rev, path) into an opaque server-generated URL. */
      svn_string_t bc_url, bc_relative;

      err = svn_ra_neon__get_baseline_info(NULL, &bc_url, &bc_relative,
                                           NULL, ras,
                                           url, revision, pool);
      if (err)
        {
          if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
            {
              /* easy out: */
              svn_error_clear(err);
              *dirent = NULL;
              return SVN_NO_ERROR;
            }
          else
            return err;
        }

      final_url = svn_path_url_add_component(bc_url.data, bc_relative.data,
                                             pool);
    }

  /* Depth-zero PROPFIND is the One True DAV Way. */
  err = svn_ra_neon__get_props(&resources, ras, final_url,
                               SVN_RA_NEON__DEPTH_ZERO,
                               NULL, NULL /* all props */, pool);
  if (err)
    {
      if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
        {
          /* easy out: */
          svn_error_clear(err);
          *dirent = NULL;
          return SVN_NO_ERROR;
        }
      else
        return err;
    }

  /* Copying parsing code from svn_ra_neon__get_dir() here.  The hash
     of resources only contains one item, but there's no other way to
     get the item. */
  for (hi = apr_hash_first(pool, resources); hi; hi = apr_hash_next(hi))
    {
      void *val;
      svn_ra_neon__resource_t *resource;
      const svn_string_t *propval;
      apr_hash_index_t *h;
      svn_dirent_t *entry;

      apr_hash_this(hi, NULL, NULL, &val);
      resource = val;

      entry = apr_pcalloc(pool, sizeof(*entry));

      entry->kind = resource->is_collection ? svn_node_dir : svn_node_file;

      /* entry->size is already 0 by virtue of pcalloc(). */
      if (entry->kind == svn_node_file)
        {
          propval = apr_hash_get(resource->propset,
                                 SVN_RA_NEON__PROP_GETCONTENTLENGTH,
                                 APR_HASH_KEY_STRING);
          if (propval)
            entry->size = svn__atoui64(propval->data);
        }

      /* does this resource contain any 'dead' properties? */
      for (h = apr_hash_first(pool, resource->propset);
           h; h = apr_hash_next(h))
        {
          const void *kkey;
          apr_hash_this(h, &kkey, NULL, NULL);

          if (strncmp((const char *)kkey, SVN_DAV_PROP_NS_CUSTOM,
                      sizeof(SVN_DAV_PROP_NS_CUSTOM) - 1) == 0)
            entry->has_props = TRUE;

          else if (strncmp((const char *)kkey, SVN_DAV_PROP_NS_SVN,
                           sizeof(SVN_DAV_PROP_NS_SVN) - 1) == 0)
            entry->has_props = TRUE;
        }

      /* created_rev & friends */
      propval = apr_hash_get(resource->propset,
                             SVN_RA_NEON__PROP_VERSION_NAME,
                             APR_HASH_KEY_STRING);
      if (propval != NULL)
        entry->created_rev = SVN_STR_TO_REV(propval->data);

      propval = apr_hash_get(resource->propset,
                             SVN_RA_NEON__PROP_CREATIONDATE,
                             APR_HASH_KEY_STRING);
      if (propval != NULL)
        SVN_ERR(svn_time_from_cstring(&(entry->time),
                                      propval->data, pool));

      propval = apr_hash_get(resource->propset,
                             SVN_RA_NEON__PROP_CREATOR_DISPLAYNAME,
                             APR_HASH_KEY_STRING);
      if (propval != NULL)
        entry->last_author = propval->data;

      *dirent = entry;
    }

  return SVN_NO_ERROR;
}
Exemplo n.º 6
0
svn_error_t *
svn_ra_neon__do_check_path(svn_ra_session_t *session,
                           const char *path,
                           svn_revnum_t revision,
                           svn_node_kind_t *kind,
                           apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  const char *url = ras->url->data;
  svn_error_t *err;
  svn_boolean_t is_dir;

  /* ### For now, using svn_ra_neon__get_baseline_info() works because
     we only have three possibilities: dir, file, or none.  When we
     add symlinks, we will need to do something different.  Here's one
     way described by Greg Stein:

       That is a PROPFIND (Depth:0) for the DAV:resourcetype property.

       You can use the svn_ra_neon__get_one_prop() function to fetch
       it. If the PROPFIND fails with a 404, then you have
       svn_node_none. If the resulting property looks like:

           <D:resourcetype>
             <D:collection/>
           </D:resourcetype>

       Then it is a collection (directory; svn_node_dir). Otherwise,
       it is a regular resource (svn_node_file).

       The harder part is parsing the resourcetype property. "Proper"
       parsing means treating it as an XML property and looking for
       the DAV:collection element in there. To do that, however, means
       that get_one_prop() can't be used. I think there may be some
       Neon functions for parsing XML properties; we'd need to
       look. That would probably be the best approach. (an alternative
       is to use apr_xml_* parsing functions on the returned string;
       get back a DOM-like thing, and look for the element).
  */

  /* If we were given a relative path to append, append it. */
  if (path)
    url = svn_path_url_add_component(url, path, pool);

  err = svn_ra_neon__get_baseline_info(&is_dir, NULL, NULL, NULL,
                                       ras, url, revision, pool);

  if (err == SVN_NO_ERROR)
    {
      if (is_dir)
        *kind = svn_node_dir;
      else
        *kind = svn_node_file;
    }
  else if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
    {

      svn_error_clear(err);
      err = SVN_NO_ERROR;
      *kind = svn_node_none;
    }

  return err;
}
Exemplo n.º 7
0
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,
                           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;
  svn_string_t bc_url, 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(NULL, &bc_url, &bc_relative, NULL,
                                         ras, ras->url->data,
                                         peg_revision,
                                         pool));
  final_bc_url = svn_path_url_add_component(bc_url.data, bc_relative.data,
                                            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;
}