Пример #1
0
/* Print all not-hidden subdirectories in the working copy, starting by path */
static svn_error_t *
directory_dump(const char *path,
               apr_pool_t *scratch_pool)
{
  struct directory_walk_baton bt;
  svn_error_t *err;

  SVN_ERR(svn_wc_context_create(&bt.wc_ctx, NULL, scratch_pool, scratch_pool));
  SVN_ERR(svn_dirent_get_absolute(&bt.root_abspath, path, scratch_pool));

  bt.prefix_path = path;

  err = svn_wc__internal_walk_children(bt.wc_ctx->db, bt.root_abspath, FALSE,
                                       NULL, print_dir, &bt, svn_depth_infinity,
                                       NULL, NULL, scratch_pool);
  if (err)
    {
      const char *dir_abspath;

      if (err->apr_err != SVN_ERR_WC_UPGRADE_REQUIRED)
        return err;
      svn_error_clear(err);
      SVN_ERR(svn_dirent_get_absolute(&dir_abspath, path, scratch_pool));
      SVN_ERR(directory_dump_old(&bt, dir_abspath, scratch_pool));
    }

  return svn_error_trace(svn_wc_context_destroy(bt.wc_ctx));
}
Пример #2
0
svn_error_t *
svn_client_checkout3(svn_revnum_t *result_rev,
                     const char *URL,
                     const char *path,
                     const svn_opt_revision_t *peg_revision,
                     const svn_opt_revision_t *revision,
                     svn_depth_t depth,
                     svn_boolean_t ignore_externals,
                     svn_boolean_t allow_unver_obstructions,
                     svn_client_ctx_t *ctx,
                     apr_pool_t *pool)
{
  const char *local_abspath;
  svn_error_t *err;
  svn_boolean_t sleep_here = FALSE;

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));

  err = svn_client__checkout_internal(result_rev, URL, local_abspath,
                                      peg_revision, revision, depth,
                                      ignore_externals,
                                      allow_unver_obstructions, &sleep_here,
                                      ctx, pool);
  if (sleep_here)
    svn_io_sleep_for_timestamps(local_abspath, pool);

  return svn_error_trace(err);
}
Пример #3
0
/* Return in *LINK_TARGET_ABSPATH the absolute path the symlink at
 * LOCAL_ABSPATH is pointing to. Perform all allocations in POOL. */
static svn_error_t *
read_link_target(const char **link_target_abspath,
                 const char *local_abspath,
                 apr_pool_t *pool)
{
  svn_string_t *link_target;
  const char *canon_link_target;

  SVN_ERR(svn_io_read_link(&link_target, local_abspath, pool));
  if (link_target->len == 0)
    return svn_error_createf(SVN_ERR_WC_NOT_SYMLINK, NULL,
                             _("The symlink at '%s' points nowhere"),
                             svn_dirent_local_style(local_abspath, pool));

  canon_link_target = svn_dirent_canonicalize(link_target->data, pool);

  /* Treat relative symlinks as relative to LOCAL_ABSPATH's parent. */
  if (!svn_dirent_is_absolute(canon_link_target))
    canon_link_target = svn_dirent_join(svn_dirent_dirname(local_abspath,
                                                           pool),
                                        canon_link_target, pool);

  /* Collapse any .. in the symlink part of the path. */
  if (svn_path_is_backpath_present(canon_link_target))
    SVN_ERR(svn_dirent_get_absolute(link_target_abspath, canon_link_target,
                                    pool));
  else
    *link_target_abspath = canon_link_target;

  return SVN_NO_ERROR;
}
Пример #4
0
svn_error_t *
svn_wc_create_tmp_file2(apr_file_t **fp,
                        const char **new_name,
                        const char *path,
                        svn_io_file_del_t delete_when,
                        apr_pool_t *pool)
{
  svn_wc__db_t *db;
  const char *local_abspath;
  const char *temp_dir;
  svn_error_t *err;

  SVN_ERR_ASSERT(fp || new_name);

  SVN_ERR(svn_wc__db_open(&db,
                          NULL /* config */,
                          TRUE /* auto_upgrade */,
                          TRUE /* enforce_empty_wq */,
                          pool, pool));

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
  err = svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, local_abspath,
                                       pool, pool);
  err = svn_error_compose_create(err, svn_wc__db_close(db));
  if (err)
    return svn_error_trace(err);

  SVN_ERR(svn_io_open_unique_file3(fp, new_name, temp_dir,
                                   delete_when, pool, pool));

  return SVN_NO_ERROR;
}
static svn_error_t *
obtain_lock(const char *path, svn_boolean_t recursive,
            apr_pool_t *scratch_pool)
{
  const char *local_abspath;
  svn_wc_context_t *wc_ctx;

  SVN_ERR(svn_path_cstring_to_utf8(&path, path, scratch_pool));
  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));

      SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, scratch_pool,
                                    scratch_pool));

  if (recursive)
    {
      /* The WC-NG way */
      SVN_ERR(svn_wc__acquire_write_lock(NULL, wc_ctx, local_abspath, FALSE,
                                         scratch_pool, scratch_pool));
    }
  else
    {
      SVN_ERR(svn_wc__db_wclock_obtain(wc_ctx->db, local_abspath, 0, FALSE,
                                       scratch_pool));
    }

  SVN_ERR(svn_cmdline_printf(scratch_pool, "Lock on '%s' obtained, and we "
                             "are not going to release it.\n",
                             svn_dirent_local_style(local_abspath,
                                                    scratch_pool)));

  return SVN_NO_ERROR;
}
Пример #6
0
/* For non-directory PATHs full entry information is obtained by reading
 * the entries for the parent directory of PATH and then extracting PATH's
 * entry.  If PATH is a directory then only abrieviated information is
 * available in the parent directory, more complete information is
 * available by reading the entries for PATH itself.
 *
 * Note: There is one bit of information about directories that is only
 * available in the parent directory, that is the "deleted" state.  If PATH
 * is a versioned directory then the "deleted" state information will not
 * be returned in ENTRY.  This means some bits of the code (e.g. revert)
 * need to obtain it by directly extracting the directory entry from the
 * parent directory's entries.  I wonder if this function should handle
 * that?
 */
svn_error_t *
svn_wc_entry(const svn_wc_entry_t **entry,
             const char *path,
             svn_wc_adm_access_t *adm_access,
             svn_boolean_t show_hidden,
             apr_pool_t *pool)
{
    svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
    const char *local_abspath;
    svn_wc_adm_access_t *dir_access;
    const char *entry_name;
    apr_hash_t *entries;

    SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));

    /* Does the provided path refer to a directory with an associated
       access baton?  */
    dir_access = svn_wc__adm_retrieve_internal2(db, local_abspath, pool);
    if (dir_access == NULL)
    {
        /* Damn. Okay. Assume the path is to a child, and let's look for
           a baton associated with its parent.  */

        const char *dir_abspath;

        svn_dirent_split(&dir_abspath, &entry_name, local_abspath, pool);

        dir_access = svn_wc__adm_retrieve_internal2(db, dir_abspath, pool);
    }
    else
    {
        /* Woo! Got one. Look for "this dir" in the entries hash.  */
        entry_name = "";
    }

    if (dir_access == NULL)
    {
        /* Early exit.  */
        *entry = NULL;
        return SVN_NO_ERROR;
    }

    /* Load an entries hash, and cache it into DIR_ACCESS. Go ahead and
       fetch all entries here (optimization) since we know how to filter
       out a "hidden" node.  */
    SVN_ERR(svn_wc__entries_read_internal(&entries, dir_access, TRUE, pool));
    *entry = svn_hash_gets(entries, entry_name);

    if (!show_hidden && *entry != NULL)
    {
        svn_boolean_t hidden;

        SVN_ERR(svn_wc__entry_is_hidden(&hidden, *entry));
        if (hidden)
            *entry = NULL;
    }

    return SVN_NO_ERROR;
}
Пример #7
0
svn_error_t *
svn_client__switch_internal(svn_revnum_t *result_rev,
                            const char *path,
                            const char *switch_url,
                            const svn_opt_revision_t *peg_revision,
                            const svn_opt_revision_t *revision,
                            svn_depth_t depth,
                            svn_boolean_t depth_is_sticky,
                            svn_boolean_t ignore_externals,
                            svn_boolean_t allow_unver_obstructions,
                            svn_boolean_t ignore_ancestry,
                            svn_boolean_t *timestamp_sleep,
                            svn_client_ctx_t *ctx,
                            apr_pool_t *pool)
{
  const char *local_abspath, *anchor_abspath;
  svn_boolean_t acquired_lock;
  svn_error_t *err, *err1, *err2;
  apr_hash_t *conflicted_paths
    = ctx->conflict_func2 ? apr_hash_make(pool) : NULL;

  SVN_ERR_ASSERT(path);

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));

  /* Rely on svn_wc__acquire_write_lock setting ANCHOR_ABSPATH even
     when it returns SVN_ERR_WC_LOCKED */
  err = svn_wc__acquire_write_lock(&anchor_abspath,
                                   ctx->wc_ctx, local_abspath, TRUE,
                                   pool, pool);
  if (err && err->apr_err != SVN_ERR_WC_LOCKED)
    return svn_error_trace(err);

  acquired_lock = (err == SVN_NO_ERROR);
  svn_error_clear(err);

  err1 = switch_internal(result_rev, conflicted_paths,
                         local_abspath, anchor_abspath,
                         switch_url, peg_revision, revision,
                         depth, depth_is_sticky,
                         ignore_externals,
                         allow_unver_obstructions, ignore_ancestry,
                         timestamp_sleep, ctx, pool);

  /* Give the conflict resolver callback the opportunity to
   * resolve any conflicts that were raised. */
  if (! err1 && ctx->conflict_func2)
    {
      err1 = svn_client__resolve_conflicts(NULL, conflicted_paths, ctx, pool);
    }

  if (acquired_lock)
    err2 = svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool);
  else
    err2 = SVN_NO_ERROR;

  return svn_error_compose_create(err1, err2);
}
Пример #8
0
/* Create an empty repository and WC for the test TEST_NAME.  Set *REPOS_URL
 * to the URL of the new repository and *WC_ABSPATH to the root path of the
 * new WC.
 *
 * Create the repository and WC in subdirectories called
 * REPOSITORIES_WORK_DIR/TEST_NAME and WCS_WORK_DIR/TEST_NAME respectively,
 * within the current working directory.
 *
 * Register the repo and WC to be cleaned up when the test suite exits. */
static svn_error_t *
create_repos_and_wc(const char **repos_url,
                    const char **wc_abspath,
                    const char *test_name,
                    const svn_test_opts_t *opts,
                    apr_pool_t *pool)
{
    const char *repos_path = svn_relpath_join(REPOSITORIES_WORK_DIR, test_name,
                             pool);
    const char *wc_path = svn_relpath_join(WCS_WORK_DIR, test_name, pool);

    /* Remove the repo and WC dirs if they already exist, to ensure the test
     * will run even if a previous failed attempt was not cleaned up. */
    SVN_ERR(svn_io_remove_dir2(repos_path, TRUE, NULL, NULL, pool));
    SVN_ERR(svn_io_remove_dir2(wc_path, TRUE, NULL, NULL, pool));

    /* Create the parent dirs of the repo and WC if necessary. */
    SVN_ERR(svn_io_make_dir_recursively(REPOSITORIES_WORK_DIR, pool));
    SVN_ERR(svn_io_make_dir_recursively(WCS_WORK_DIR, pool));

    /* Create a repos. Register it for clean-up. Set *REPOS_URL to its path. */
    {
        svn_repos_t *repos;

        /* Use a subpool to create the repository and then destroy the subpool
           so the repository's underlying filesystem is closed.  If opts->fs_type
           is BDB this prevents any attempt to open a second environment handle
           within the same process when we checkout the WC below.  BDB 4.4+ allows
           only a single environment handle to be open per process. */
        apr_pool_t *subpool = svn_pool_create(pool);

        SVN_ERR(svn_test__create_repos(&repos, repos_path, opts, subpool));
        SVN_ERR(svn_uri_get_file_url_from_dirent(repos_url, repos_path, pool));
        svn_pool_destroy(subpool);
    }

    /* Create a WC. Set *WC_ABSPATH to its path. */
    {
        apr_pool_t *subpool = svn_pool_create(pool); /* To cleanup CTX */
        svn_client_ctx_t *ctx;
        svn_opt_revision_t head_rev = { svn_opt_revision_head, {0} };

        SVN_ERR(svn_client_create_context(&ctx, subpool));
        SVN_ERR(svn_dirent_get_absolute(wc_abspath, wc_path, pool));
        SVN_ERR(svn_client_checkout3(NULL, *repos_url, *wc_abspath,
                                     &head_rev, &head_rev, svn_depth_infinity,
                                     FALSE /* ignore_externals */,
                                     FALSE /* allow_unver_obstructions */,
                                     ctx, subpool));
        svn_pool_destroy(subpool);
    }

    /* Register this WC for cleanup. */
    svn_test_add_dir_cleanup(*wc_abspath);

    return SVN_NO_ERROR;
}
Пример #9
0
svn_error_t *JNIUtil::preprocessPath(const char *&path, apr_pool_t *pool)
{
  /* URLs and wc-paths get treated differently. */
  if (svn_path_is_url(path))
    {
      /* No need to canonicalize a URL's case or path separators. */

      /* Convert to URI. */
      path = svn_path_uri_from_iri(path, pool);

      /* Auto-escape some ASCII characters. */
      path = svn_path_uri_autoescape(path, pool);

      /* The above doesn't guarantee a valid URI. */
      if (! svn_path_is_uri_safe(path))
        return svn_error_createf(SVN_ERR_BAD_URL, NULL,
                                 _("URL '%s' is not properly URI-encoded"),
                                 path);

      /* Verify that no backpaths are present in the URL. */
      if (svn_path_is_backpath_present(path))
        return svn_error_createf(SVN_ERR_BAD_URL, NULL,
                                 _("URL '%s' contains a '..' element"),
                                 path);

      /* strip any trailing '/' */
      path = svn_uri_canonicalize(path, pool);
    }
  else  /* not a url, so treat as a path */
    {
      /* Normalize path to subversion internal style */

      /* ### In Subversion < 1.6 this method on Windows actually tried
         to lookup the path on disk to fix possible invalid casings in
         the passed path. (An extremely expensive operation; especially
         on network drives).

         This 'feature'is now removed as it penalizes every correct
         path passed, and also breaks behavior of e.g.
           'svn status .' returns '!' file, because there is only a "File"
             on disk.
            But when you then call 'svn status file', you get '? File'.

         As JavaHL is designed to be platform independent I assume users
         don't want this broken behavior on non round-trippable paths, nor
         the performance penalty.
       */

      path = svn_dirent_internal_style(path, pool);

      /* For kicks and giggles, let's absolutize it. */
      SVN_ERR(svn_dirent_get_absolute(&path, path, pool));
    }

  return NULL;
}
Пример #10
0
/* Attempt to find the repository root url for TARGET, possibly using CTX for
 * authentication.  If one is found and *ROOT_URL is not NULL, then just check
 * that the root url for TARGET matches the value given in *ROOT_URL and
 * return an error if it does not.  If one is found and *ROOT_URL is NULL then
 * set *ROOT_URL to the root url for TARGET, allocated from POOL.
 * If a root url is not found for TARGET because it does not exist in the
 * repository, then return with no error.
 *
 * TARGET is a UTF-8 encoded string that is fully canonicalized and escaped.
 */
static svn_error_t *
check_root_url_of_target(const char **root_url,
                         const char *target,
                         svn_client_ctx_t *ctx,
                         apr_pool_t *pool)
{
  svn_error_t *err;
  const char *tmp_root_url;
  const char *truepath;
  svn_opt_revision_t opt_rev;

  SVN_ERR(svn_opt_parse_path(&opt_rev, &truepath, target, pool));
  if (!svn_path_is_url(truepath))
    SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, pool));

  err =  svn_client__get_repos_root(&tmp_root_url, truepath,
                                    ctx, pool, pool);

  if (err)
    {
      /* It is OK if the given target does not exist, it just means
       * we will not be able to determine the root url from this particular
       * argument.
       *
       * If the target itself is a URL to a repository that does not exist,
       * that's fine, too. The callers will deal with this argument in an
       * appropriate manter if it does not make any sense.
       *
       * Also tolerate locally added targets ("bad revision" error).
       */
      if ((err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
          || (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
          || (err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY)
          || (err->apr_err == SVN_ERR_RA_LOCAL_REPOS_OPEN_FAILED)
          || (err->apr_err == SVN_ERR_CLIENT_BAD_REVISION))
        {
          svn_error_clear(err);
          return SVN_NO_ERROR;
        }
      else
        return svn_error_trace(err);
     }

   if (*root_url && tmp_root_url)
     {
       if (strcmp(*root_url, tmp_root_url) != 0)
         return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                                  _("All non-relative targets must have "
                                    "the same root URL"));
     }
   else
     *root_url = tmp_root_url;

   return SVN_NO_ERROR;
}
Пример #11
0
svn_error_t *
svn_client_add4(const char *path,
                svn_depth_t depth,
                svn_boolean_t force,
                svn_boolean_t no_ignore,
                svn_boolean_t add_parents,
                svn_client_ctx_t *ctx,
                apr_pool_t *pool)
{
  const char *parent_abspath;
  const char *local_abspath;
  const char *existing_parent_abspath;

  if (svn_path_is_url(path))
    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                             _("'%s' is not a local path"), path);

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));

  /* ### this is a hack.
     ### before we switched to absolute paths, if a user tried to do
     ### 'svn add .', PATH would be "" and PARENT_PATH would also be "",
     ### thus emulating the behavior below.  Now that we are using
     ### absolute paths, svn_dirent_dirname() doesn't behave the same way
     ### w.r.t. '.', so we need to include the following hack.  This
     ### behavior is tested in schedule_tests-11. */
  if (path[0] == 0)
    parent_abspath = local_abspath;
  else
    parent_abspath = svn_dirent_dirname(local_abspath, pool);

  existing_parent_abspath = NULL;
  if (add_parents)
    {
      apr_pool_t *subpool;
      const char *existing_parent_abspath2;

      subpool = svn_pool_create(pool);
      SVN_ERR(find_existing_parent(&existing_parent_abspath2, ctx,
                                   parent_abspath, pool, subpool));
      if (strcmp(existing_parent_abspath2, parent_abspath) != 0)
        existing_parent_abspath = existing_parent_abspath2;
      svn_pool_destroy(subpool);
    }

  SVN_WC__CALL_WITH_WRITE_LOCK(
    add(local_abspath, depth, force, no_ignore, existing_parent_abspath,
        ctx, pool),
    ctx->wc_ctx,
    existing_parent_abspath ? existing_parent_abspath : parent_abspath,
    FALSE /* lock_anchor */, pool);
  return SVN_NO_ERROR;
}
Пример #12
0
static svn_error_t *
raise_tree_conflict(int argc, const char **argv, apr_pool_t *pool)
{
  int i = 0;
  svn_wc_conflict_version_t *left, *right;
  svn_wc_conflict_description2_t *c;
  svn_wc_context_t *wc_ctx;

  /* Conflict description parameters */
  const char *wc_path, *wc_abspath;
  const char *repos_url1, *repos_url2, *path_in_repos1, *path_in_repos2;
  int operation, action, reason;
  long peg_rev1, peg_rev2;
  int kind, kind1, kind2;

  if (argc != 13)
    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                            "Wrong number of arguments");

  /* Read the parameters */
  wc_path = svn_dirent_internal_style(argv[i++], pool);
  SVN_ERR(read_enum_field(&kind, node_kind_map, argv[i++], pool));
  SVN_ERR(read_enum_field(&operation, operation_map, argv[i++], pool));
  SVN_ERR(read_enum_field(&action, action_map, argv[i++], pool));
  SVN_ERR(read_enum_field(&reason, reason_map, argv[i++], pool));
  repos_url1 = argv[i++];
  path_in_repos1 = argv[i++];
  peg_rev1 = atol(argv[i++]);
  SVN_ERR(read_enum_field(&kind1, node_kind_map, argv[i++], pool));
  repos_url2 = argv[i++];
  path_in_repos2 = argv[i++];
  peg_rev2 = atol(argv[i++]);
  SVN_ERR(read_enum_field(&kind2, node_kind_map, argv[i++], pool));


  /* Allocate and fill in the description data structures */
  SVN_ERR(svn_dirent_get_absolute(&wc_abspath, wc_path, pool));
  left = svn_wc_conflict_version_create2(repos_url1, NULL, path_in_repos1,
                                         peg_rev1, kind1, pool);
  right = svn_wc_conflict_version_create2(repos_url2, NULL, path_in_repos2,
                                          peg_rev2, kind2, pool);
  c = svn_wc_conflict_description_create_tree2(wc_abspath, kind,
                                               operation, left, right, pool);
  c->action = (svn_wc_conflict_action_t)action;
  c->reason = (svn_wc_conflict_reason_t)reason;

  /* Raise the conflict */
  SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
  SVN_ERR(svn_wc__add_tree_conflict(wc_ctx, c, pool));

  return SVN_NO_ERROR;
}
Пример #13
0
svn_error_t *
svn_cl__propset_print_binary_mime_type_warning(apr_array_header_t *targets,
                                               const char *propname,
                                               const svn_string_t *propval,
                                               apr_pool_t *scratch_pool)
{
  if (strcmp(propname, SVN_PROP_MIME_TYPE) == 0)
    {
      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
      int i;

      for (i = 0; i < targets->nelts; i++)
        {
          const char *detected_mimetype;
          const char *target = APR_ARRAY_IDX(targets, i, const char *);
          const char *local_abspath;
          const svn_string_t *canon_propval;
          svn_node_kind_t node_kind;

          svn_pool_clear(iterpool);

          SVN_ERR(svn_dirent_get_absolute(&local_abspath, target, iterpool));
          SVN_ERR(svn_io_check_path(local_abspath, &node_kind, iterpool));
          if (node_kind != svn_node_file)
            continue;

          SVN_ERR(svn_wc_canonicalize_svn_prop(&canon_propval,
                                               propname, propval,
                                               local_abspath,
                                               svn_node_file,
                                               FALSE, NULL, NULL,
                                               iterpool));

          if (svn_mime_type_is_binary(canon_propval->data))
            {
              SVN_ERR(svn_io_detect_mimetype2(&detected_mimetype,
                                              local_abspath, NULL,
                                              iterpool));
              if (detected_mimetype == NULL ||
                  !svn_mime_type_is_binary(detected_mimetype))
                svn_error_clear(svn_cmdline_fprintf(stderr, iterpool,
                  _("svn: warning: '%s' is a binary mime-type but file '%s' "
                    "looks like text; diff, merge, blame, and other "
                    "operations will stop working on this file\n"),
                    canon_propval->data,
                    svn_dirent_local_style(local_abspath, iterpool)));

            }
        }
      svn_pool_destroy(iterpool);
    }
Пример #14
0
svn_error_t *
svn_client__switch_internal(svn_revnum_t *result_rev,
                            const char *path,
                            const char *switch_url,
                            const svn_opt_revision_t *peg_revision,
                            const svn_opt_revision_t *revision,
                            svn_depth_t depth,
                            svn_boolean_t depth_is_sticky,
                            svn_boolean_t ignore_externals,
                            svn_boolean_t allow_unver_obstructions,
                            svn_boolean_t ignore_ancestry,
                            svn_boolean_t *timestamp_sleep,
                            svn_client_ctx_t *ctx,
                            apr_pool_t *pool)
{
  const char *local_abspath, *anchor_abspath;
  svn_boolean_t acquired_lock;
  svn_error_t *err, *err1, *err2;

  SVN_ERR_ASSERT(path);

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));

  /* Rely on svn_wc__acquire_write_lock setting ANCHOR_ABSPATH even
     when it returns SVN_ERR_WC_LOCKED */
  err = svn_wc__acquire_write_lock(&anchor_abspath,
                                   ctx->wc_ctx, local_abspath, TRUE,
                                   pool, pool);
  if (err && err->apr_err != SVN_ERR_WC_LOCKED)
    return svn_error_trace(err);

  acquired_lock = (err == SVN_NO_ERROR);
  svn_error_clear(err);

  err1 = switch_internal(result_rev, local_abspath, anchor_abspath,
                         switch_url, peg_revision, revision,
                         depth, depth_is_sticky,
                         ignore_externals,
                         allow_unver_obstructions, ignore_ancestry,
                         timestamp_sleep, ctx, pool);

  if (acquired_lock)
    err2 = svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool);
  else
    err2 = SVN_NO_ERROR;

  return svn_error_compose_create(err1, err2);
}
Пример #15
0
svn_error_t *
svn_client__can_delete(const char *path,
                       svn_client_ctx_t *ctx,
                       apr_pool_t *scratch_pool)
{
    svn_opt_revision_t revision;
    svn_node_kind_t external_kind;
    const char *defining_abspath;
    const char* local_abspath;

    revision.kind = svn_opt_revision_unspecified;

    SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));

    /* A file external should not be deleted since the file external is
       implemented as a switched file and it would delete the file the
       file external is switched to, which is not the behavior the user
       would probably want. */
    SVN_ERR(svn_wc__read_external_info(&external_kind, &defining_abspath, NULL,
                                       NULL, NULL,
                                       ctx->wc_ctx, local_abspath,
                                       local_abspath, TRUE,
                                       scratch_pool, scratch_pool));

    if (external_kind != svn_node_none)
        return svn_error_createf(SVN_ERR_WC_CANNOT_DELETE_FILE_EXTERNAL, NULL,
                                 _("Cannot remove the external at '%s'; "
                                   "please edit or delete the svn:externals "
                                   "property on '%s'"),
                                 svn_dirent_local_style(local_abspath,
                                         scratch_pool),
                                 svn_dirent_local_style(defining_abspath,
                                         scratch_pool));


    /* Use an infinite-depth status check to see if there's anything in
       or under PATH which would make it unsafe for deletion.  The
       status callback function find_undeletables() makes the
       determination, returning an error if it finds anything that shouldn't
       be deleted. */
    return svn_error_trace(svn_client_status5(NULL, ctx, path, &revision,
                           svn_depth_infinity, FALSE,
                           FALSE, FALSE, FALSE, FALSE,
                           NULL,
                           find_undeletables, NULL,
                           scratch_pool));
}
Пример #16
0
svn_error_t *
svn_client_get_changelists(const char *path,
                           const apr_array_header_t *changelists,
                           svn_depth_t depth,
                           svn_changelist_receiver_t callback_func,
                           void *callback_baton,
                           svn_client_ctx_t *ctx,
                           apr_pool_t *pool)
{
  const char *local_abspath;

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));

  SVN_ERR(svn_wc_get_changelists(ctx->wc_ctx, local_abspath, depth, changelists,
                                 callback_func, callback_baton,
                                 ctx->cancel_func, ctx->cancel_baton, pool));
  return SVN_NO_ERROR;
}
static svn_error_t *
create_fake_wc(const char *subdir, apr_pool_t *pool)
{
  const char *root;
  const char *wc_abspath;

  root = svn_dirent_join("fake-wc", subdir, pool);

  SVN_ERR(svn_io_remove_dir2(root, TRUE, NULL, NULL, pool));

  SVN_ERR(svn_dirent_get_absolute(&wc_abspath, root, pool));
  SVN_ERR(svn_test__create_fake_wc(wc_abspath, TESTING_DATA, pool, pool));

  wc_abspath = svn_dirent_join(wc_abspath, "M", pool);
  SVN_ERR(svn_test__create_fake_wc(wc_abspath, M_TESTING_DATA, pool, pool));

  return SVN_NO_ERROR;
}
Пример #18
0
/* Add EXTERNALS_PROP_VAL for the export destination path PATH to
   TRAVERSAL_INFO.  */
static svn_error_t *
add_externals(apr_hash_t *externals,
              const char *path,
              const svn_string_t *externals_prop_val)
{
  apr_pool_t *pool = apr_hash_pool_get(externals);
  const char *local_abspath;

  if (! externals_prop_val)
    return SVN_NO_ERROR;

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));

  apr_hash_set(externals, local_abspath, APR_HASH_KEY_STRING,
               apr_pstrmemdup(pool, externals_prop_val->data,
                              externals_prop_val->len));

  return SVN_NO_ERROR;
}
Пример #19
0
svn_error_t *
svn_client_cleanup(const char *path,
                   svn_client_ctx_t *ctx,
                   apr_pool_t *scratch_pool)
{
  const char *local_abspath;
  svn_error_t *err;

  if (svn_path_is_url(path))
    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                             _("'%s' is not a local path"), path);

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));

  err = svn_wc_cleanup3(ctx->wc_ctx, local_abspath, ctx->cancel_func,
                        ctx->cancel_baton, scratch_pool);
  svn_io_sleep_for_timestamps(path, scratch_pool);
  return svn_error_trace(err);
}
static svn_error_t *
create_open(svn_wc__db_t **db,
            const char **local_abspath,
            const char *subdir,
            apr_pool_t *pool)
{
  SVN_ERR(create_fake_wc(subdir, pool));

  SVN_ERR(svn_dirent_get_absolute(local_abspath,
                                  svn_dirent_join("fake-wc", subdir, pool),
                                  pool));
  SVN_ERR(svn_wc__db_open(db,
                          NULL /* config */,
                          TRUE /* auto_upgrade */,
                          TRUE /* enforce_empty_wq */,
                          pool, pool));

  return SVN_NO_ERROR;
}
Пример #21
0
svn_error_t *
svn_client_add_to_changelist(const apr_array_header_t *paths,
                             const char *changelist,
                             svn_depth_t depth,
                             const apr_array_header_t *changelists,
                             svn_client_ctx_t *ctx,
                             apr_pool_t *pool)
{
  apr_pool_t *iterpool = svn_pool_create(pool);
  int i;

  if (changelist[0] == '\0')
    return svn_error_create(SVN_ERR_BAD_CHANGELIST_NAME, NULL,
                            _("Target changelist name must not be empty"));

  for (i = 0; i < paths->nelts; i++)
    {
      const char *path = APR_ARRAY_IDX(paths, i, const char *);

      if (svn_path_is_url(path))
        return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                                 _("'%s' is not a local path"), path);
    }

  for (i = 0; i < paths->nelts; i++)
    {
      const char *path = APR_ARRAY_IDX(paths, i, const char *);
      const char *local_abspath;

      svn_pool_clear(iterpool);
      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, iterpool));

      SVN_ERR(svn_wc_set_changelist2(ctx->wc_ctx, local_abspath, changelist,
                                     depth, changelists,
                                     ctx->cancel_func, ctx->cancel_baton,
                                     ctx->notify_func2, ctx->notify_baton2,
                                     iterpool));
    }

  svn_pool_destroy(iterpool);
  return SVN_NO_ERROR;
}
Пример #22
0
static svn_error_t *
tree_dump(const char *path,
          apr_pool_t *scratch_pool)
{
  struct directory_walk_baton bt;
  svn_sqlite__db_t *sdb;
  svn_wc__db_t *db;

  bt.prefix_path = path;

  /* Obtain an access baton to allow re-using the same wc_db for all access */
  SVN_ERR(svn_wc_adm_open3(&bt.adm_access, NULL, path, FALSE, 0, NULL, NULL,
                           scratch_pool));

  db = svn_wc__adm_get_db(bt.adm_access);

  SVN_ERR(svn_wc__context_create_with_db(&bt.wc_ctx, NULL, db, scratch_pool));

  SVN_ERR(svn_dirent_get_absolute(&bt.root_abspath, path, scratch_pool));

  /* And now get us a transaction on the database to avoid obtaining and
     releasing locks all the time */
  SVN_ERR(svn_wc__db_temp_borrow_sdb(&sdb, bt.wc_ctx->db, bt.root_abspath,
                                     scratch_pool));

  SVN_SQLITE__WITH_LOCK(
      svn_wc__internal_walk_children(db, bt.root_abspath, FALSE,
                                     NULL, tree_dump_dir, &bt,
                                     svn_depth_infinity,
                                     NULL, NULL, scratch_pool),
      sdb);

  /* And close everything we've opened */
  SVN_ERR(svn_wc_context_destroy(bt.wc_ctx));
  SVN_ERR(svn_wc_adm_close2(bt.adm_access, scratch_pool));

  return SVN_NO_ERROR;
}
Пример #23
0
static svn_error_t *
verify_db(int argc, const char *path, apr_pool_t *pool)
{
  const char *local_abspath;
  svn_wc_context_t *wc_ctx;
  struct verify_baton vb = { FALSE };

  /* Read the parameters */
  path = svn_dirent_internal_style(path, pool);

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));

  SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));

  SVN_ERR(svn_wc__db_verify_db_full(wc_ctx->db, local_abspath,
                                    verify_cb, &vb, pool));

  if (vb.found_err)
    return svn_error_create(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
              _("Found one or more potential wc.db inconsistencies"));

  return SVN_NO_ERROR;
}
Пример #24
0
svn_error_t *
svn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p,
                     void **notify_baton_p,
                     apr_pool_t *pool)
{
  struct notify_baton *nb = apr_pcalloc(pool, sizeof(*nb));

  nb->received_some_change = FALSE;
  nb->sent_first_txdelta = FALSE;
  nb->is_checkout = FALSE;
  nb->is_export = FALSE;
  nb->is_wc_to_repos_copy = FALSE;
  nb->in_external = FALSE;
  nb->had_print_error = FALSE;
  nb->text_conflicts = 0;
  nb->prop_conflicts = 0;
  nb->tree_conflicts = 0;
  nb->skipped_paths = 0;
  SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool));

  *notify_func_p = notify;
  *notify_baton_p = nb;
  return SVN_NO_ERROR;
}
/* This callback is called by the ra_layer for each path locked.
 * BATON is a 'struct lock_baton *', PATH is the path being locked,
 * and LOCK is the lock itself.
 *
 * If BATON->base_path is not null, then this function either stores
 * the LOCK on REL_URL or removes any lock tokens from REL_URL
 * (depending on whether DO_LOCK is true or false respectively), but
 * only if RA_ERR is null, or (in the unlock case) is something other
 * than SVN_ERR_FS_LOCK_OWNER_MISMATCH.
 *
 * Implements svn_ra_lock_callback_t.
 */
static svn_error_t *
store_locks_callback(void *baton,
                     const char *rel_url,
                     svn_boolean_t do_lock,
                     const svn_lock_t *lock,
                     svn_error_t *ra_err, apr_pool_t *pool)
{
  struct lock_baton *lb = baton;
  svn_wc_notify_t *notify;

  /* Create the notify struct first, so we can tweak it below. */
  notify = svn_wc_create_notify(rel_url,
                                do_lock
                                ? (ra_err
                                   ? svn_wc_notify_failed_lock
                                   : svn_wc_notify_locked)
                                : (ra_err
                                   ? svn_wc_notify_failed_unlock
                                   : svn_wc_notify_unlocked),
                                pool);
  notify->lock = lock;
  notify->err = ra_err;

  if (lb->base_path)
    {
      char *path = apr_hash_get(lb->urls_to_paths, rel_url,
                                APR_HASH_KEY_STRING);
      const char *local_abspath;

      SVN_ERR(svn_dirent_get_absolute(&local_abspath,
                                      svn_dirent_join(lb->base_path,
                                                      path, pool),
                                      pool));

      /* Notify a valid working copy path */
      notify->path = local_abspath;
      notify->path_prefix = lb->base_path;

      if (do_lock)
        {
          if (!ra_err)
            {
              SVN_ERR(svn_wc_add_lock2(lb->ctx->wc_ctx, local_abspath, lock,
                                       lb->pool));
              notify->lock_state = svn_wc_notify_lock_state_locked;
            }
          else
            notify->lock_state = svn_wc_notify_lock_state_unchanged;
        }
      else /* unlocking */
        {
          /* Remove our wc lock token either a) if we got no error, or b) if
             we got any error except for owner mismatch.  Note that the only
             errors that are handed to this callback will be locking-related
             errors. */

          if (!ra_err ||
              (ra_err && (ra_err->apr_err != SVN_ERR_FS_LOCK_OWNER_MISMATCH)))
            {
              SVN_ERR(svn_wc_remove_lock2(lb->ctx->wc_ctx, local_abspath,
                                          lb->pool));
              notify->lock_state = svn_wc_notify_lock_state_unlocked;
            }
          else
            notify->lock_state = svn_wc_notify_lock_state_unchanged;
        }
    }
  else
    notify->url = rel_url; /* Notify that path is actually a url  */

  if (lb->ctx->notify_func2)
    lb->ctx->notify_func2(lb->ctx->notify_baton2, notify, pool);

  return SVN_NO_ERROR;
}
Пример #26
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__propget(apr_getopt_t *os,
                void *baton,
                apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  const char *pname, *pname_utf8;
  apr_array_header_t *args, *targets;
  svn_stream_t *out;

  if (opt_state->verbose && (opt_state->revprop || opt_state->strict
                             || opt_state->xml))
    return svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
                            _("--verbose cannot be used with --revprop or "
                              "--strict or --xml"));

  /* PNAME is first argument (and PNAME_UTF8 will be a UTF-8 version
     thereof) */
  SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool));
  pname = APR_ARRAY_IDX(args, 0, const char *);
  SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, pool));
  if (! svn_prop_name_is_valid(pname_utf8))
    return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
                             _("'%s' is not a valid Subversion property name"),
                             pname_utf8);

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE, pool));

  /* Add "." if user passed 0 file arguments */
  svn_opt_push_implicit_dot_target(targets, pool);

  /* Open a stream to stdout. */
  SVN_ERR(svn_stream_for_stdout(&out, pool));

  if (opt_state->revprop)  /* operate on a revprop */
    {
      svn_revnum_t rev;
      const char *URL;
      svn_string_t *propval;

      SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
                                      &URL, ctx, pool));

      /* Let libsvn_client do the real work. */
      SVN_ERR(svn_client_revprop_get(pname_utf8, &propval,
                                     URL, &(opt_state->start_revision),
                                     &rev, ctx, pool));

      if (propval != NULL)
        {
          if (opt_state->xml)
            {
              svn_stringbuf_t *sb = NULL;
              char *revstr = apr_psprintf(pool, "%ld", rev);

              SVN_ERR(svn_cl__xml_print_header("properties", pool));

              svn_xml_make_open_tag(&sb, pool, svn_xml_normal,
                                    "revprops",
                                    "rev", revstr, NULL);

              svn_cmdline__print_xml_prop(&sb, pname_utf8, propval, pool);

              svn_xml_make_close_tag(&sb, pool, "revprops");

              SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
              SVN_ERR(svn_cl__xml_print_footer("properties", pool));
            }
          else
            {
              svn_string_t *printable_val = propval;

              /* If this is a special Subversion property, it is stored as
                 UTF8 and LF, so convert to the native locale and eol-style. */

              if (svn_prop_needs_translation(pname_utf8))
                SVN_ERR(svn_subst_detranslate_string(&printable_val, propval,
                                                     TRUE, pool));

              SVN_ERR(stream_write(out, printable_val->data,
                                   printable_val->len));
              if (! opt_state->strict)
                SVN_ERR(stream_write(out, APR_EOL_STR, strlen(APR_EOL_STR)));
            }
        }
    }
  else  /* operate on a normal, versioned property (not a revprop) */
    {
      apr_pool_t *subpool = svn_pool_create(pool);
      int i;

      if (opt_state->xml)
        SVN_ERR(svn_cl__xml_print_header("properties", subpool));

      if (opt_state->depth == svn_depth_unknown)
        opt_state->depth = svn_depth_empty;

      /* Strict mode only makes sense for a single target.  So make
         sure we have only a single target, and that we're not being
         asked to recurse on that target. */
      if (opt_state->strict
          && ((targets->nelts > 1) || (opt_state->depth != svn_depth_empty)))
        return svn_error_create
          (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
           _("Strict output of property values only available for single-"
             "target, non-recursive propget operations"));

      for (i = 0; i < targets->nelts; i++)
        {
          const char *target = APR_ARRAY_IDX(targets, i, const char *);
          apr_hash_t *props;
          svn_boolean_t print_filenames;
          svn_boolean_t omit_newline;
          svn_boolean_t like_proplist;
          const char *truepath;
          svn_opt_revision_t peg_revision;

          svn_pool_clear(subpool);
          SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

          /* Check for a peg revision. */
          SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
                                     subpool));

          if (!svn_path_is_url(truepath))
            SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool));

          SVN_ERR(svn_client_propget4(&props, pname_utf8, truepath,
                                      &peg_revision,
                                      &(opt_state->start_revision),
                                      NULL, opt_state->depth,
                                      opt_state->changelists, ctx, subpool,
                                      subpool));

          /* Any time there is more than one thing to print, or where
             the path associated with a printed thing is not obvious,
             we'll print filenames.  That is, unless we've been told
             not to do so with the --strict option. */
          print_filenames = ((opt_state->depth > svn_depth_empty
                              || targets->nelts > 1
                              || apr_hash_count(props) > 1
                              || opt_state->verbose)
                             && (! opt_state->strict));
          omit_newline = opt_state->strict;
          like_proplist = opt_state->verbose && !opt_state->strict;

          if (opt_state->xml)
            SVN_ERR(print_properties_xml(pname_utf8, props, subpool));
          else
            SVN_ERR(print_properties(out, svn_path_is_url(target), pname_utf8,
                                     props, print_filenames, omit_newline,
                                     like_proplist, subpool));
        }

      if (opt_state->xml)
        SVN_ERR(svn_cl__xml_print_footer("properties", subpool));

      svn_pool_destroy(subpool);
    }

  return SVN_NO_ERROR;
}
Пример #27
0
/* Print the properties in PROPS to the stream OUT. PROPS is a hash mapping
 * (const char *) path to (svn_string_t) property value.
 * If IS_URL is true, all paths are URLs, else all paths are local paths.
 * PNAME_UTF8 is the property name of all the properties.
 * If PRINT_FILENAMES is true, print the item's path before each property.
 * If OMIT_NEWLINE is true, don't add a newline at the end of each property.
 * If LIKE_PROPLIST is true, print everything in a more verbose format
 * like "svn proplist -v" does.
 * */
static svn_error_t *
print_properties(svn_stream_t *out,
                 svn_boolean_t is_url,
                 const char *pname_utf8,
                 apr_hash_t *props,
                 svn_boolean_t print_filenames,
                 svn_boolean_t omit_newline,
                 svn_boolean_t like_proplist,
                 apr_pool_t *pool)
{
  apr_array_header_t *sorted_props;
  int i;
  apr_pool_t *iterpool = svn_pool_create(pool);
  const char *path_prefix;

  SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", pool));

  sorted_props = svn_sort__hash(props, svn_sort_compare_items_as_paths, pool);
  for (i = 0; i < sorted_props->nelts; i++)
    {
      svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
      const char *filename = item.key;
      svn_string_t *propval = item.value;

      svn_pool_clear(iterpool);

      if (print_filenames)
        {
          const char *header;

          /* Print the file name. */

          if (! is_url)
            filename = svn_cl__local_style_skip_ancestor(path_prefix, filename,
                                                         iterpool);

          /* In verbose mode, print exactly same as "proplist" does;
           * otherwise, print a brief header. */
          header = apr_psprintf(iterpool, like_proplist
                                ? _("Properties on '%s':\n")
                                : "%s - ", filename);
          SVN_ERR(svn_cmdline_cstring_from_utf8(&header, header, iterpool));
          SVN_ERR(svn_subst_translate_cstring2(header, &header,
                                               APR_EOL_STR,  /* 'native' eol */
                                               FALSE, /* no repair */
                                               NULL,  /* no keywords */
                                               FALSE, /* no expansion */
                                               iterpool));
          SVN_ERR(stream_write(out, header, strlen(header)));
        }

      if (like_proplist)
        {
          /* Print the property name and value just as "proplist -v" does */
          apr_hash_t *hash = apr_hash_make(iterpool);

          apr_hash_set(hash, pname_utf8, APR_HASH_KEY_STRING, propval);
          SVN_ERR(svn_cl__print_prop_hash(out, hash, FALSE, iterpool));
        }
      else
        {
          /* If this is a special Subversion property, it is stored as
             UTF8, so convert to the native format. */
          if (svn_prop_needs_translation(pname_utf8))
            SVN_ERR(svn_subst_detranslate_string(&propval, propval,
                                                 TRUE, iterpool));

          SVN_ERR(stream_write(out, propval->data, propval->len));

          if (! omit_newline)
            SVN_ERR(stream_write(out, APR_EOL_STR,
                                 strlen(APR_EOL_STR)));
        }
    }

  svn_pool_destroy(iterpool);

  return SVN_NO_ERROR;
}
Пример #28
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__status(apr_getopt_t *os,
               void *baton,
               apr_pool_t *scratch_pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  apr_array_header_t *targets;
  apr_pool_t *iterpool;
  apr_hash_t *master_cl_hash = apr_hash_make(scratch_pool);
  int i;
  svn_opt_revision_t rev;
  struct status_baton sb;

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE,
                                                      scratch_pool));

  /* Add "." if user passed 0 arguments */
  svn_opt_push_implicit_dot_target(targets, scratch_pool);

  SVN_ERR(svn_cl__check_targets_are_local_paths(targets));

  /* We want our -u statuses to be against HEAD by default. */
  if (opt_state->start_revision.kind == svn_opt_revision_unspecified)
    rev.kind = svn_opt_revision_head;
  else if (! opt_state->update)
    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                        _("--revision (-r) option valid only with "
                          "--show-updates (-u) option"));
  else
    rev = opt_state->start_revision;

  sb.had_print_error = FALSE;

  if (opt_state->xml)
    {
      /* If output is not incremental, output the XML header and wrap
         everything in a top-level element. This makes the output in
         its entirety a well-formed XML document. */
      if (! opt_state->incremental)
        SVN_ERR(svn_cl__xml_print_header("status", scratch_pool));
    }
  else
    {
      if (opt_state->incremental)
        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("'incremental' option only valid in XML "
                                  "mode"));
    }

  sb.suppress_externals_placeholders = (opt_state->quiet
                                        && (! opt_state->verbose));
  sb.detailed = (opt_state->verbose || opt_state->update);
  sb.show_last_committed = opt_state->verbose;
  sb.skip_unrecognized = opt_state->quiet;
  sb.repos_locks = opt_state->update;
  sb.xml_mode = opt_state->xml;
  sb.cached_changelists = master_cl_hash;
  sb.cl_pool = scratch_pool;
  sb.text_conflicts = 0;
  sb.prop_conflicts = 0;
  sb.tree_conflicts = 0;
  sb.ctx = ctx;

  SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));

  iterpool = svn_pool_create(scratch_pool);
  for (i = 0; i < targets->nelts; i++)
    {
      const char *target = APR_ARRAY_IDX(targets, i, const char *);
      svn_revnum_t repos_rev = SVN_INVALID_REVNUM;

      svn_pool_clear(iterpool);

      SVN_ERR(svn_dirent_get_absolute(&(sb.target_abspath), target,
                                      scratch_pool));
      sb.target_path = target;

      SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

      if (opt_state->xml)
        SVN_ERR(print_start_target_xml(svn_dirent_local_style(target, iterpool),
                                       iterpool));

      /* Retrieve a hash of status structures with the information
         requested by the user. */
      SVN_ERR(svn_cl__try(svn_client_status6(&repos_rev, ctx, target, &rev,
                                             opt_state->depth,
                                             opt_state->verbose,
                                             opt_state->update,
                                             TRUE /* check_working_copy */,
                                             opt_state->no_ignore,
                                             opt_state->ignore_externals,
                                             FALSE /* depth_as_sticky */,
                                             opt_state->changelists,
                                             print_status, &sb,
                                             iterpool),
                          NULL, opt_state->quiet,
                          /* not versioned: */
                          SVN_ERR_WC_NOT_WORKING_COPY,
                          SVN_ERR_WC_PATH_NOT_FOUND,
                          0));

      if (opt_state->xml)
        SVN_ERR(print_finish_target_xml(repos_rev, iterpool));
    }

  /* If any paths were cached because they were associated with
     changelists, we can now display them as grouped changelists. */
  if (apr_hash_count(master_cl_hash) > 0)
    {
      apr_hash_index_t *hi;
      svn_stringbuf_t *buf;

      if (opt_state->xml)
        buf = svn_stringbuf_create_empty(scratch_pool);

      for (hi = apr_hash_first(scratch_pool, master_cl_hash); hi;
           hi = apr_hash_next(hi))
        {
          const char *changelist_name = apr_hash_this_key(hi);
          apr_array_header_t *path_array = apr_hash_this_val(hi);
          int j;

          /* ### TODO: For non-XML output, we shouldn't print the
             ### leading \n on the first changelist if there were no
             ### non-changelist entries. */
          if (opt_state->xml)
            {
              svn_stringbuf_setempty(buf);
              svn_xml_make_open_tag(&buf, scratch_pool, svn_xml_normal,
                                    "changelist", "name", changelist_name,
                                    SVN_VA_NULL);
              SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout));
            }
          else
            SVN_ERR(svn_cmdline_printf(scratch_pool,
                                       _("\n--- Changelist '%s':\n"),
                                       changelist_name));

          for (j = 0; j < path_array->nelts; j++)
            {
              struct status_cache *scache =
                APR_ARRAY_IDX(path_array, j, struct status_cache *);
              sb.target_abspath = scache->target_abspath;
              sb.target_path = scache->target_path;
              SVN_ERR(print_status_normal_or_xml(&sb, scache->path,
                                                 scache->status, scratch_pool));
            }

          if (opt_state->xml)
            {
              svn_stringbuf_setempty(buf);
              svn_xml_make_close_tag(&buf, scratch_pool, "changelist");
              SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout));
            }
        }
    }
Пример #29
0
svn_error_t *
svn_client_propset_local(const char *propname,
                         const svn_string_t *propval,
                         const apr_array_header_t *targets,
                         svn_depth_t depth,
                         svn_boolean_t skip_checks,
                         const apr_array_header_t *changelists,
                         svn_client_ctx_t *ctx,
                         apr_pool_t *scratch_pool)
{
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
  svn_boolean_t targets_are_urls;
  int i;

  if (targets->nelts == 0)
    return SVN_NO_ERROR;

  /* Check for homogeneity among our targets. */
  targets_are_urls = svn_path_is_url(APR_ARRAY_IDX(targets, 0, const char *));
  SVN_ERR(svn_client__assert_homogeneous_target_type(targets));

  if (targets_are_urls)
    return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
                            _("Targets must be working copy paths"));

  SVN_ERR(check_prop_name(propname, propval));

  for (i = 0; i < targets->nelts; i++)
    {
      svn_node_kind_t kind;
      const char *target_abspath;
      svn_error_t *err;
      struct set_props_baton baton;
      const char *target = APR_ARRAY_IDX(targets, i, const char *);

      svn_pool_clear(iterpool);

      /* Check for cancellation */
      if (ctx->cancel_func)
        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));

      SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, iterpool));

      err = svn_wc_read_kind(&kind, ctx->wc_ctx, target_abspath, FALSE,
                             iterpool);

      if ((err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
          || (!err && (kind == svn_node_unknown || kind == svn_node_none)))
        {
          if (ctx->notify_func2)
            {
              svn_wc_notify_t *notify = svn_wc_create_notify(
                                          target_abspath,
                                          svn_wc_notify_path_nonexistent,
                                          iterpool);

              ctx->notify_func2(ctx->notify_baton2, notify, iterpool);
            }

          svn_error_clear(err);
        }
      else
        SVN_ERR(err);

      baton.ctx = ctx;
      baton.local_abspath = target_abspath;
      baton.depth = depth;
      baton.kind = kind;
      baton.propname = propname;
      baton.propval = propval;
      baton.skip_checks = skip_checks;
      baton.changelist_filter = changelists;

      SVN_ERR(svn_wc__call_with_write_lock(set_props_cb, &baton,
                                           ctx->wc_ctx, target_abspath,
                                           FALSE, iterpool, iterpool));
    }
  svn_pool_destroy(iterpool);

  return SVN_NO_ERROR;
}
Пример #30
0
svn_error_t *
svn_client_proplist3(const char *path_or_url,
                     const svn_opt_revision_t *peg_revision,
                     const svn_opt_revision_t *revision,
                     svn_depth_t depth,
                     const apr_array_header_t *changelists,
                     svn_proplist_receiver_t receiver,
                     void *receiver_baton,
                     svn_client_ctx_t *ctx,
                     apr_pool_t *pool)
{
  const char *url;

  peg_revision = svn_cl__rev_default_to_head_or_working(peg_revision,
                                                        path_or_url);
  revision = svn_cl__rev_default_to_peg(revision, peg_revision);

  if (depth == svn_depth_unknown)
    depth = svn_depth_empty;

  if (! svn_path_is_url(path_or_url)
      && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(peg_revision->kind)
      && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
    {
      svn_boolean_t pristine;
      svn_node_kind_t kind;
      apr_hash_t *changelist_hash = NULL;
      const char *local_abspath;

      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path_or_url, pool));

      pristine = ((revision->kind == svn_opt_revision_committed)
                  || (revision->kind == svn_opt_revision_base));

      SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, local_abspath, FALSE,
                               pool));

      if (kind == svn_node_unknown || kind == svn_node_none)
        {
          /* svn uses SVN_ERR_UNVERSIONED_RESOURCE as warning only
             for this function. */
          return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
                                   _("'%s' is not under version control"),
                                   svn_dirent_local_style(local_abspath,
                                                          pool));
        }

      if (changelists && changelists->nelts)
        SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash,
                                           changelists, pool));

      /* Fetch, recursively or not. */
      if (kind == svn_node_dir)
        {
          struct recursive_proplist_receiver_baton rb;

          rb.wc_ctx = ctx->wc_ctx;
          rb.wrapped_receiver = receiver;
          rb.wrapped_receiver_baton = receiver_baton;

          if (strcmp(path_or_url, local_abspath) != 0)
            {
              rb.anchor = path_or_url;
              rb.anchor_abspath = local_abspath;
            }
          else
            {
              rb.anchor = NULL;
              rb.anchor_abspath = NULL;
            }

          SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, NULL,
                                              depth,
                                              FALSE, pristine, changelists,
                                              recursive_proplist_receiver, &rb,
                                              ctx->cancel_func,
                                              ctx->cancel_baton, pool));
        }
      else if (svn_wc__changelist_match(ctx->wc_ctx, local_abspath,
                                        changelist_hash, pool))
        {
          apr_hash_t *hash;

          SVN_ERR(pristine_or_working_props(&hash, ctx->wc_ctx, local_abspath,
                                            pristine, pool, pool));
          SVN_ERR(call_receiver(path_or_url, hash,
                                receiver, receiver_baton, pool));

        }
    }
  else /* remote target */
    {
      svn_ra_session_t *ra_session;
      svn_node_kind_t kind;
      apr_pool_t *subpool = svn_pool_create(pool);
      svn_revnum_t revnum;

      /* Get an RA session for this URL. */
      SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
                                               &url, path_or_url, NULL,
                                               peg_revision,
                                               revision, ctx, pool));

      SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, pool));

      SVN_ERR(remote_proplist(url, "", kind, revnum, ra_session, depth,
                              receiver, receiver_baton, pool, subpool));
      svn_pool_destroy(subpool);
    }

  return SVN_NO_ERROR;
}