예제 #1
0
파일: cleanup.c 프로젝트: DJEX93/dsploit
/* svn_wc_upgrade_get_repos_info_t implementation for calling
   svn_wc_upgrade() from svn_client_upgrade() */
static svn_error_t *
fetch_repos_info(const char **repos_root,
                 const char **repos_uuid,
                 void *baton,
                 const char *url,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
{
  struct repos_info_baton *ri = baton;
  apr_pool_t *subpool;
  svn_ra_session_t *ra_session;

  /* The same info is likely to retrieved multiple times (e.g. externals) */
  if (ri->last_repos && svn_uri__is_child(ri->last_repos, url, scratch_pool))
    {
      *repos_root = apr_pstrdup(result_pool, ri->last_repos);
      *repos_uuid = apr_pstrdup(result_pool, ri->last_uuid);
      return SVN_NO_ERROR;
    }

  subpool = svn_pool_create(scratch_pool);

  SVN_ERR(svn_client_open_ra_session(&ra_session, url, ri->ctx, subpool));

  SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool));
  SVN_ERR(svn_ra_get_uuid2(ra_session, repos_uuid, result_pool));

  /* Store data for further calls */
  ri->last_repos = apr_pstrdup(ri->state_pool, *repos_root);
  ri->last_uuid = apr_pstrdup(ri->state_pool, *repos_uuid);

  svn_pool_destroy(subpool);

  return SVN_NO_ERROR;
}
예제 #2
0
svn_error_t *
svn_client_get_repos_root(const char **repos_root,
                          const char **repos_uuid,
                          const char *abspath_or_url,
                          svn_client_ctx_t *ctx,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
{
  svn_ra_session_t *ra_session;

  /* If PATH_OR_URL is a local path we can fetch the repos root locally. */
  if (!svn_path_is_url(abspath_or_url))
    {
      SVN_ERR(svn_wc__node_get_repos_info(repos_root, repos_uuid,
                                          ctx->wc_ctx, abspath_or_url,
                                          result_pool, scratch_pool));

      return SVN_NO_ERROR;
    }

  /* If PATH_OR_URL was a URL, we use the RA layer to look it up. */
  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL,
                                               abspath_or_url,
                                               NULL, NULL, FALSE, TRUE,
                                               ctx, scratch_pool));

  if (repos_root)
    SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool));
  if (repos_uuid)
    SVN_ERR(svn_ra_get_uuid2(ra_session, repos_uuid, result_pool));

  return SVN_NO_ERROR;
}
예제 #3
0
svn_error_t *
svn_client__pathrev_create_with_session(svn_client__pathrev_t **pathrev_p,
                                        svn_ra_session_t *ra_session,
                                        svn_revnum_t rev,
                                        const char *url,
                                        apr_pool_t *result_pool)
{
  svn_client__pathrev_t *pathrev = apr_palloc(result_pool, sizeof(*pathrev));

  SVN_ERR_ASSERT(svn_path_is_url(url));

  SVN_ERR(svn_ra_get_repos_root2(ra_session, &pathrev->repos_root_url,
                                 result_pool));
  SVN_ERR(svn_ra_get_uuid2(ra_session, &pathrev->repos_uuid, result_pool));
  pathrev->rev = rev;
  pathrev->url = apr_pstrdup(result_pool, url);
  *pathrev_p = pathrev;
  return SVN_NO_ERROR;
}
예제 #4
0
/* Replay revisions START_REVISION thru END_REVISION (inclusive) of
 * the repository located at URL, using callbacks which generate
 * Subversion repository dumpstreams describing the changes made in
 * those revisions.  If QUIET is set, don't generate progress
 * messages.
 */
static svn_error_t *
replay_revisions(svn_ra_session_t *session,
                 svn_ra_session_t *extra_ra_session,
                 const char *url,
                 svn_revnum_t start_revision,
                 svn_revnum_t end_revision,
                 svn_boolean_t quiet,
                 svn_boolean_t incremental,
                 apr_pool_t *pool)
{
    struct replay_baton *replay_baton;
    const char *uuid;
    svn_stream_t *stdout_stream;

    SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));

    replay_baton = apr_pcalloc(pool, sizeof(*replay_baton));
    replay_baton->stdout_stream = stdout_stream;
    replay_baton->extra_ra_session = extra_ra_session;
    replay_baton->quiet = quiet;

    /* Write the magic header and UUID */
    SVN_ERR(svn_stream_printf(stdout_stream, pool,
                              SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n",
                              SVN_REPOS_DUMPFILE_FORMAT_VERSION));
    SVN_ERR(svn_ra_get_uuid2(session, &uuid, pool));
    SVN_ERR(svn_stream_printf(stdout_stream, pool,
                              SVN_REPOS_DUMPFILE_UUID ": %s\n\n", uuid));

    /* Fake revision 0 if necessary */
    if (start_revision == 0)
    {
        SVN_ERR(dump_revision_header(session, stdout_stream,
                                     start_revision, pool));

        /* Revision 0 has no tree changes, so we're done. */
        if (! quiet)
            SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
                                        start_revision));
        start_revision++;

        /* If our first revision is 0, we can treat this as an
           incremental dump. */
        incremental = TRUE;
    }

    if (incremental)
    {
        SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
                                    0, TRUE, replay_revstart, replay_revend,
                                    replay_baton, pool));
    }
    else
    {
        const svn_ra_reporter3_t *reporter;
        void *report_baton;
        const svn_delta_editor_t *dump_editor;
        void *dump_baton;

        /* First, we need to dump the start_revision in full.  We'll
           start with a revision record header. */
        SVN_ERR(dump_revision_header(session, stdout_stream,
                                     start_revision, pool));

        /* Then, we'll drive the dump editor with what would look like a
           full checkout of the repository as it looked in
           START_REVISION.  We do this by manufacturing a basic 'report'
           to the update reporter, telling it that we have nothing to
           start with.  The delta between nothing and everything-at-REV
           is, effectively, a full dump of REV. */
        SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton,
                                           start_revision,
                                           stdout_stream, extra_ra_session,
                                           check_cancel, NULL, pool));
        SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton,
                                  start_revision, "", svn_depth_infinity,
                                  FALSE, dump_editor, dump_baton, pool));
        SVN_ERR(reporter->set_path(report_baton, "", start_revision,
                                   svn_depth_infinity, TRUE, NULL, pool));
        SVN_ERR(reporter->finish_report(report_baton, pool));

        /* All finished with START_REVISION! */
        if (! quiet)
            SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
                                        start_revision));
        start_revision++;

        /* Now go pick up additional revisions in the range, if any. */
        if (start_revision <= end_revision)
            SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
                                        0, TRUE, replay_revstart, replay_revend,
                                        replay_baton, pool));
    }

    SVN_ERR(svn_stream_close(stdout_stream));
    return SVN_NO_ERROR;
}
예제 #5
0
svn_error_t *
svn_client_info3(const char *abspath_or_url,
                 const svn_opt_revision_t *peg_revision,
                 const svn_opt_revision_t *revision,
                 svn_depth_t depth,
                 svn_boolean_t fetch_excluded,
                 svn_boolean_t fetch_actual_only,
                 const apr_array_header_t *changelists,
                 svn_client_info_receiver2_t receiver,
                 void *receiver_baton,
                 svn_client_ctx_t *ctx,
                 apr_pool_t *pool)
{
  svn_ra_session_t *ra_session, *parent_ra_session;
  svn_revnum_t rev;
  const char *url;
  svn_node_kind_t url_kind;
  const char *repos_root_URL, *repos_UUID;
  svn_lock_t *lock;
  svn_boolean_t related;
  apr_hash_t *parent_ents;
  const char *parent_url, *base_name;
  svn_dirent_t *the_ent;
  svn_client_info2_t *info;
  svn_error_t *err;

  if (depth == svn_depth_unknown)
    depth = svn_depth_empty;

  if ((revision == NULL
       || revision->kind == svn_opt_revision_unspecified)
      && (peg_revision == NULL
          || peg_revision->kind == svn_opt_revision_unspecified))
    {
      /* Do all digging in the working copy. */
      wc_info_receiver_baton_t b = { receiver, receiver_baton };
      return svn_error_trace(
        svn_wc__get_info(ctx->wc_ctx, abspath_or_url, depth,
                        fetch_excluded, fetch_actual_only, changelists,
                         wc_info_receiver, &b,
                         ctx->cancel_func, ctx->cancel_baton, pool));
    }

  /* Go repository digging instead. */

  /* Trace rename history (starting at path_or_url@peg_revision) and
     return RA session to the possibly-renamed URL as it exists in REVISION.
     The ra_session returned will be anchored on this "final" URL. */
  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev,
                                           &url, abspath_or_url, NULL,
                                           peg_revision,
                                           revision, ctx, pool));

  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_URL, pool));
  SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_UUID, pool));

  svn_uri_split(&parent_url, &base_name, url, pool);

  /* Get the dirent for the URL itself. */
  err = svn_ra_stat(ra_session, "", rev, &the_ent, pool);

  /* svn_ra_stat() will work against old versions of mod_dav_svn, but
     not old versions of svnserve.  In the case of a pre-1.2 svnserve,
     catch the specific error it throws:*/
  if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
    {
      /* Fall back to pre-1.2 strategy for fetching dirent's URL. */
      svn_error_clear(err);

      if (strcmp(url, repos_root_URL) == 0)
        {
          /* In this universe, there's simply no way to fetch
             information about the repository's root directory!
             If we're recursing, degrade gracefully: rather than
             throw an error, return no information about the
             repos root. */
          if (depth > svn_depth_empty)
            goto pre_1_2_recurse;

          /* Otherwise, we really are stuck.  Better tell the user
             what's going on. */
          return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                                   _("Server does not support retrieving "
                                     "information about the repository root"));
        }

      SVN_ERR(svn_ra_check_path(ra_session, "", rev, &url_kind, pool));
      if (url_kind == svn_node_none)
        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                                 _("URL '%s' non-existent in revision %ld"),
                                 url, rev);

      /* Open a new RA session to the item's parent. */
      SVN_ERR(svn_client__open_ra_session_internal(&parent_ra_session, NULL,
                                                   parent_url, NULL,
                                                   NULL, FALSE, TRUE,
                                                   ctx, pool));

      /* Get all parent's entries, and find the item's dirent in the hash. */
      SVN_ERR(svn_ra_get_dir2(parent_ra_session, &parent_ents, NULL, NULL,
                              "", rev, DIRENT_FIELDS, pool));
      the_ent = apr_hash_get(parent_ents, base_name, APR_HASH_KEY_STRING);
      if (the_ent == NULL)
        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                                 _("URL '%s' non-existent in revision %ld"),
                                 url, rev);
    }
  else if (err)
    {
      return svn_error_trace(err);
    }

  if (! the_ent)
    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                             _("URL '%s' non-existent in revision %ld"),
                             url, rev);

  /* Check if the URL exists in HEAD and refers to the same resource.
     In this case, we check the repository for a lock on this URL.

     ### There is a possible race here, since HEAD might have changed since
     ### we checked it.  A solution to this problem could be to do the below
     ### check in a loop which only terminates if the HEAD revision is the same
     ### before and after this check.  That could, however, lead to a
     ### starvation situation instead.  */
  SVN_ERR(same_resource_in_head(&related, url, rev, ra_session, ctx, pool));
  if (related)
    {
      err = svn_ra_get_lock(ra_session, &lock, "", pool);

      /* An old mod_dav_svn will always work; there's nothing wrong with
         doing a PROPFIND for a property named "DAV:supportedlock". But
         an old svnserve will error. */
      if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
        {
          svn_error_clear(err);
          lock = NULL;
        }
      else if (err)
        return svn_error_trace(err);
    }
  else
    lock = NULL;

  /* Push the URL's dirent (and lock) at the callback.*/
  SVN_ERR(build_info_from_dirent(&info, the_ent, lock, url, rev,
                                 repos_UUID, repos_root_URL, pool));
  SVN_ERR(receiver(receiver_baton, base_name, info, pool));

  /* Possibly recurse, using the original RA session. */
  if (depth > svn_depth_empty && (the_ent->kind == svn_node_dir))
    {
      apr_hash_t *locks;

pre_1_2_recurse:
      if (peg_revision->kind == svn_opt_revision_head)
        {
          err = svn_ra_get_locks2(ra_session, &locks, "", depth,
                                  pool);

          /* Catch specific errors thrown by old mod_dav_svn or svnserve. */
          if (err &&
              (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED
               || err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE))
            {
              svn_error_clear(err);
              locks = apr_hash_make(pool); /* use an empty hash */
            }
          else if (err)
            return svn_error_trace(err);
        }
      else
        locks = apr_hash_make(pool); /* use an empty hash */

      SVN_ERR(push_dir_info(ra_session, url, "", rev,
                            repos_UUID, repos_root_URL,
                            receiver, receiver_baton,
                            depth, ctx, locks, pool));
    }

  return SVN_NO_ERROR;
}