Example #1
0
/* This implements the svn_proplist_receiver_t interface, printing XML to
   stdout. */
static svn_error_t *
proplist_receiver_xml(void *baton,
                      const char *path,
                      apr_hash_t *prop_hash,
                      apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((proplist_baton_t *)baton)->opt_state;
  svn_boolean_t is_url = ((proplist_baton_t *)baton)->is_url;
  svn_stringbuf_t *sb = NULL;
  const char *name_local;

  if (! is_url)
    name_local = svn_path_local_style(path, pool);
  else
    name_local = path;

  /* "<target ...>" */
  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "target",
                        "path", name_local, NULL);

  SVN_ERR(svn_cl__print_xml_prop_hash(&sb, prop_hash, (! opt_state->verbose),
                                      pool));

  /* "</target>" */
  svn_xml_make_close_tag(&sb, pool, "target");

  SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));

  return SVN_NO_ERROR;
}
Example #2
0
static void
status_func (void *baton, const char *path, svn_wc_status2_t *status) {
	struct status_bt *sb = baton;
	apr_pool_t *pool = ((status_bt *)baton)->pool;
	
	print_status (svn_path_local_style (path, pool), 
			      sb->detailed, sb->show_last_committed, sb->repos_locks,
				  status, ((status_bt *) baton)->L, pool);			
}
Example #3
0
  std::string
  Path::native() const
  {
    if (m_pathIsUrl)
    {
      // this converts something like
      // http://foo/my%20location
      // to
      // http://foo/my location
	    return Url::unescape(m_path.c_str());
    }
    else
    {
      // On Windows, p://foo/bar will be converted to p:\foo\bar
	    Pool pool;
      return svn_path_local_style(m_path.c_str(), pool);
    }
  }
Example #4
0
/* Throw an SVN_ERR_CLIENT_IS_BINARY_FILE error if PROP_DIFFS indicates a
   binary MIME type.  Else, return SVN_NO_ERROR. */
static svn_error_t *
check_mimetype(apr_array_header_t *prop_diffs, const char *target,
               apr_pool_t *pool)
{
  int i;

  for (i = 0; i < prop_diffs->nelts; ++i)
    {
      const svn_prop_t *prop = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t);
      if (strcmp(prop->name, SVN_PROP_MIME_TYPE) == 0
          && prop->value
          && svn_mime_type_is_binary(prop->value->data))
        return svn_error_createf
          (SVN_ERR_CLIENT_IS_BINARY_FILE, 0,
           _("Cannot calculate blame information for binary file '%s'"),
           svn_path_local_style(target, pool));
    }
  return SVN_NO_ERROR;
}
Example #5
0
/* Called by status-cmd.c */
svn_error_t *
svn_cl__print_status(const char *path,
                     svn_wc_status2_t *status,
                     svn_boolean_t detailed,
                     svn_boolean_t show_last_committed,
                     svn_boolean_t skip_unrecognized,
                     svn_boolean_t repos_locks,
                     apr_pool_t *pool)
{
  if (! status 
      || (skip_unrecognized && ! status->entry)
      || (status->text_status == svn_wc_status_none
          && status->repos_text_status == svn_wc_status_none))
    return SVN_NO_ERROR;

  return print_status(svn_path_local_style(path, pool),
                      detailed, show_last_committed, repos_locks, status,
                      pool);
}
Example #6
0
/* This implements the svn_proplist_receiver_t interface. */
static svn_error_t *
proplist_receiver(void *baton,
                  const char *path,
                  apr_hash_t *prop_hash,
                  apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((proplist_baton_t *)baton)->opt_state;
  svn_boolean_t is_url = ((proplist_baton_t *)baton)->is_url;
  const char *name_local;

  if (! is_url)
    name_local = svn_path_local_style(path, pool);
  else
    name_local = path;

  if (!opt_state->quiet)
    SVN_ERR(svn_cmdline_printf(pool, _("Properties on '%s':\n"), name_local));
  return svn_cl__print_prop_hash(prop_hash, (! opt_state->verbose), pool);
}
        const char *
        local_style_skip_ancestor(const char *parent_path,
                const char *path,
                apr_pool_t *subpool) {
            const char *relpath = NULL;

            if (parent_path)
            {
                relpath = svn_path_is_child(parent_path, path, pool);

                if (!relpath)
                {
                    if (strcmp(path, parent_path) == 0)
                        relpath = ".";
                    else
                        relpath = path;
                }
            }

            return svn_path_local_style(relpath ? relpath : path, subpool);
        }
Example #8
0
File: add.c Project: vocho/openqnx
/* Schedule directory DIRNAME, and some of the tree under it, for
 * addition with access baton ADM_ACCESS.  DEPTH is the depth at this
 * point in the descent (it may be changed for recursive calls).
 *
 * If DIRNAME (or any item below directory DIRNAME) is already scheduled for
 * addition, add will fail and return an error unless FORCE is TRUE.
 *
 * Files and directories that match ignore patterns will not be added unless
 * NO_IGNORE is TRUE.
 *
 * If CTX->CANCEL_FUNC is non-null, call it with CTX->CANCEL_BATON to allow
 * the user to cancel the operation
 */
static svn_error_t *
add_dir_recursive(const char *dirname,
                  svn_wc_adm_access_t *adm_access,
                  svn_depth_t depth,
                  svn_boolean_t force,
                  svn_boolean_t no_ignore,
                  svn_client_ctx_t *ctx,
                  apr_pool_t *pool)
{
  apr_dir_t *dir;
  apr_finfo_t this_entry;
  svn_error_t *err;
  apr_pool_t *subpool;
  apr_int32_t flags = APR_FINFO_TYPE | APR_FINFO_NAME;
  svn_wc_adm_access_t *dir_access;
  apr_array_header_t *ignores;

  /* Check cancellation; note that this catches recursive calls too. */
  if (ctx->cancel_func)
    SVN_ERR(ctx->cancel_func(ctx->cancel_baton));

  /* Add this directory to revision control. */
  err = svn_wc_add2(dirname, adm_access,
                    NULL, SVN_INVALID_REVNUM,
                    ctx->cancel_func, ctx->cancel_baton,
                    ctx->notify_func2, ctx->notify_baton2, pool);
  if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
    svn_error_clear(err);
  else if (err)
    return err;

  SVN_ERR(svn_wc_adm_retrieve(&dir_access, adm_access, dirname, pool));

  if (!no_ignore)
    SVN_ERR(svn_wc_get_ignores(&ignores, ctx->config, dir_access, pool));

  subpool = svn_pool_create(pool);

  SVN_ERR(svn_io_dir_open(&dir, dirname, pool));

  /* Read the directory entries one by one and add those things to
     version control. */
  while (1)
    {
      const char *fullpath;

      svn_pool_clear(subpool);

      err = svn_io_dir_read(&this_entry, flags, dir, subpool);

      if (err)
        {
          /* Check if we're done reading the dir's entries. */
          if (APR_STATUS_IS_ENOENT(err->apr_err))
            {
              apr_status_t apr_err;

              svn_error_clear(err);
              apr_err = apr_dir_close(dir);
              if (apr_err)
                return svn_error_wrap_apr
                  (apr_err, _("Can't close directory '%s'"),
                   svn_path_local_style(dirname, subpool));
              break;
            }
          else
            {
              return svn_error_createf
                (err->apr_err, err,
                 _("Error during add of '%s'"),
                 svn_path_local_style(dirname, subpool));
            }
        }

      /* Skip entries for this dir and its parent.  */
      if (this_entry.name[0] == '.'
          && (this_entry.name[1] == '\0'
              || (this_entry.name[1] == '.' && this_entry.name[2] == '\0')))
        continue;

      /* Check cancellation so you can cancel during an
       * add of a directory with lots of files. */
      if (ctx->cancel_func)
        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));

      /* Skip over SVN admin directories. */
      if (svn_wc_is_adm_dir(this_entry.name, subpool))
        continue;

      if ((!no_ignore) && svn_wc_match_ignore_list(this_entry.name,
                                                   ignores, subpool))
        continue;

      /* Construct the full path of the entry. */
      fullpath = svn_path_join(dirname, this_entry.name, subpool);

      /* Recurse on directories; add files; ignore the rest. */
      if (this_entry.filetype == APR_DIR && depth >= svn_depth_immediates)
        {
          svn_depth_t depth_below_here = depth;
          if (depth == svn_depth_immediates)
            depth_below_here = svn_depth_empty;

          SVN_ERR(add_dir_recursive(fullpath, dir_access, depth_below_here,
                                    force, no_ignore, ctx, subpool));
        }
      else if (this_entry.filetype != APR_UNKFILE
               && this_entry.filetype != APR_DIR
               && depth >= svn_depth_files)
        {
          err = add_file(fullpath, ctx, dir_access, subpool);
          if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
            svn_error_clear(err);
          else if (err)
            return err;
        }
    }

  /* Opened by svn_wc_add */
  SVN_ERR(svn_wc_adm_close(dir_access));

  /* Destroy the per-iteration pool. */
  svn_pool_destroy(subpool);

  return SVN_NO_ERROR;
}
Example #9
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__propedit(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;
  int i;

  /* Validate the input and get the property's name (and a UTF-8
     version of that name). */
  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);
  if (opt_state->encoding && !svn_prop_needs_translation(pname_utf8))
      return svn_error_create
          (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
           _("--encoding option applies only to textual"
             " Subversion-controlled properties"));

  /* Suck up all the remaining arguments into a targets array */
  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, pool));

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

      /* Implicit "." is okay for revision properties; it just helps
         us find the right repository. */
      svn_opt_push_implicit_dot_target(targets, pool);

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

      /* Fetch the current property. */
      SVN_ERR(svn_client_revprop_get(pname_utf8, &propval,
                                     URL, &(opt_state->start_revision),
                                     &rev, ctx, pool));

      if (! propval)
        {
          propval = svn_string_create("", pool);
          /* This is how we signify to svn_client_revprop_set2() that
             we want it to check that the original value hasn't
             changed, but that that original value was non-existent: */
          original_propval.data = NULL;  /* and .len is ignored */
        }
      else
        {
          original_propval = *propval;
        }

      /* Run the editor on a temporary file which contains the
         original property value... */
      SVN_ERR(svn_io_temp_dir(&temp_dir, pool));
      SVN_ERR(svn_cl__edit_string_externally
              (&propval, NULL,
               opt_state->editor_cmd, temp_dir,
               propval, "svn-prop",
               ctx->config,
               svn_prop_needs_translation(pname_utf8),
               opt_state->encoding, pool));

      /* ...and re-set the property's value accordingly. */
      if (propval)
        {
          SVN_ERR(svn_client_revprop_set2(pname_utf8,
                                          propval, &original_propval,
                                          URL, &(opt_state->start_revision),
                                          &rev, opt_state->force, ctx, pool));

          SVN_ERR
            (svn_cmdline_printf
             (pool,
              _("Set new value for property '%s' on revision %ld\n"),
              pname_utf8, rev));
        }
      else
        {
          SVN_ERR(svn_cmdline_printf
                  (pool, _("No changes to property '%s' on revision %ld\n"),
                   pname_utf8, rev));
        }
    }
  else if (opt_state->start_revision.kind != svn_opt_revision_unspecified)
    {
      return svn_error_createf
        (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
         _("Cannot specify revision for editing versioned property '%s'"),
         pname_utf8);
    }
  else  /* operate on a normal, versioned property (not a revprop) */
    {
      apr_pool_t *subpool = svn_pool_create(pool);

      /* The customary implicit dot rule has been prone to user error
       * here.  For example, Jon Trowbridge <*****@*****.**> did
       *
       *    $ svn propedit HACKING
       *
       * and then when he closed his editor, he was surprised to see
       *
       *    Set new value for property 'HACKING' on ''
       *
       * ...meaning that the property named 'HACKING' had been set on
       * the current working directory, with the value taken from the
       * editor.  So we don't do the implicit dot thing anymore; an
       * explicit target is always required when editing a versioned
       * property.
       */
      if (targets->nelts == 0)
        {
          return svn_error_create
            (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
             _("Explicit target argument required"));
        }

      SVN_ERR(svn_opt__eat_peg_revisions(&targets, targets, pool));

      /* For each target, edit the property PNAME. */
      for (i = 0; i < targets->nelts; i++)
        {
          apr_hash_t *props;
          const char *target = APR_ARRAY_IDX(targets, i, const char *);
          svn_string_t *propval, *edited_propval;
          const char *base_dir = target;
          const char *target_local;
          svn_wc_adm_access_t *adm_access;
          const svn_wc_entry_t *entry;
          svn_opt_revision_t peg_revision;
          svn_revnum_t base_rev = SVN_INVALID_REVNUM;

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

          /* Propedits can only happen on HEAD or the working copy, so
             the peg revision can be as unspecified. */
          peg_revision.kind = svn_opt_revision_unspecified;

          /* Fetch the current property. */
          SVN_ERR(svn_client_propget3(&props, pname_utf8, target,
                                      &peg_revision,
                                      &(opt_state->start_revision),
                                      &base_rev, svn_depth_empty,
                                      NULL, ctx, subpool));

          /* Get the property value. */
          propval = apr_hash_get(props, target, APR_HASH_KEY_STRING);
          if (! propval)
            propval = svn_string_create("", subpool);

          if (svn_path_is_url(target))
            {
              /* For URLs, put the temporary file in the current directory. */
              base_dir = ".";
            }
          else
            {
              if (opt_state->message || opt_state->filedata ||
                  opt_state->revprop_table)
                {
                  return svn_error_create
                    (SVN_ERR_CL_UNNECESSARY_LOG_MESSAGE, NULL,
                     _("Local, non-commit operations do not take a log message "
                       "or revision properties"));
                }

              /* Split the path if it is a file path. */
              SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, target,
                                             FALSE, 0, ctx->cancel_func,
                                             ctx->cancel_baton, subpool));
              SVN_ERR(svn_wc_entry(&entry, target, adm_access, FALSE, subpool));
              if (! entry)
                return svn_error_createf
                  (SVN_ERR_ENTRY_NOT_FOUND, NULL,
                   _("'%s' does not appear to be a working copy path"), target);
              if (entry->kind == svn_node_file)
                svn_path_split(target, &base_dir, NULL, subpool);
            }

          /* Run the editor on a temporary file which contains the
             original property value... */
          SVN_ERR(svn_cl__edit_string_externally(&edited_propval, NULL,
                                                 opt_state->editor_cmd,
                                                 base_dir,
                                                 propval,
                                                 "svn-prop",
                                                 ctx->config,
                                                 svn_prop_needs_translation
                                                 (pname_utf8),
                                                 opt_state->encoding,
                                                 subpool));

          target_local = svn_path_is_url(target) ? target
            : svn_path_local_style(target, subpool);

          /* ...and re-set the property's value accordingly. */
          if (edited_propval && !svn_string_compare(propval, edited_propval))
            {
              svn_commit_info_t *commit_info = NULL;
              svn_error_t *err = SVN_NO_ERROR;

              svn_cl__check_boolean_prop_val(pname_utf8, edited_propval->data,
                                             subpool);

              if (ctx->log_msg_func3)
                SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3),
                                                   opt_state, NULL, ctx->config,
                                                   subpool));

              err = svn_client_propset3(&commit_info,
                                        pname_utf8, edited_propval, target,
                                        svn_depth_empty, opt_state->force,
                                        base_rev, NULL, opt_state->revprop_table,
                                        ctx, subpool);
              if (ctx->log_msg_func3)
                SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3,
                                                err, pool));
              else if (err)
                return err;

              /* Print a message if we successfully committed or if it
                 was just a wc propset (but not if the user aborted an URL
                 propedit). */
              if (commit_info || ! svn_path_is_url(target))
                SVN_ERR
                  (svn_cmdline_printf
                   (subpool, _("Set new value for property '%s' on '%s'\n"),
                    pname_utf8, target_local));

              if (commit_info && ! opt_state->quiet)
                SVN_ERR(svn_cl__print_commit_info(commit_info, subpool));
            }
          else
            {
              SVN_ERR
                (svn_cmdline_printf
                 (subpool, _("No changes to property '%s' on '%s'\n"),
                  pname_utf8, target_local));
            }
        }
      svn_pool_destroy(subpool);
    }

  return SVN_NO_ERROR;
}
Example #10
0
static int
l_proplist (lua_State *L) {

	const char *path = (lua_gettop (L) < 1 || lua_isnil (L, 1)) ? "" : luaL_checkstring (L, 1);

	svn_opt_revision_t peg_revision;
	svn_opt_revision_t revision;

	if (lua_gettop (L) < 2 || lua_isnil (L, 2)) {
		revision.kind = svn_opt_revision_unspecified;
	} else {
		revision.kind = svn_opt_revision_number;
		revision.value.number = lua_tointeger (L, 2);
	}	

	peg_revision.kind = svn_opt_revision_unspecified;

	apr_pool_t *pool;
	svn_error_t *err;
	svn_client_ctx_t *ctx;

	init_function (&ctx, &pool, L);

	path = svn_path_canonicalize (path, pool);

	apr_array_header_t *props;

	int is_url = svn_path_is_url (path);

	err = svn_client_proplist2 (&props, path, &peg_revision, &revision, TRUE, ctx, pool);
	IF_ERROR_RETURN (err, pool, L);

	lua_newtable (L);

	int i;
	for (i = 0; i < props->nelts; ++i)
	{
		const void *key;
		void *val;
		svn_client_proplist_item_t *item = ((svn_client_proplist_item_t **)props->elts)[i];

		const char *name_local;
		if (is_url) {
			name_local = svn_path_local_style (item->node_name->data, pool);
		} else {
			name_local = item->node_name->data;
		}

		lua_pushstring (L, name_local);

		lua_newtable (L);

		apr_hash_index_t *hi;
		for (hi = apr_hash_first (pool, item->prop_hash); hi; hi = apr_hash_next (hi)) {
			const char *pname;
			svn_string_t *pval;
			
			apr_hash_this (hi, &key, NULL, &val);

			pname = key;
			pval = (svn_string_t *) val;

			err = svn_cmdline_cstring_from_utf8 (&pname, pname, pool);
			IF_ERROR_RETURN (err, pool, L);

			lua_pushstring (L, pval->data);
			lua_setfield (L, -2, pname);
		}

		lua_settable (L, -3);

	}

	svn_pool_destroy (pool);

	return 1;

}
Example #11
0
svn_error_t *
svn_client__get_revision_number(svn_revnum_t *revnum,
                                svn_revnum_t *youngest_rev,
                                svn_ra_session_t *ra_session,
                                const svn_opt_revision_t *revision,
                                const char *path,
                                apr_pool_t *pool)
{
  switch (revision->kind)
    {
    case svn_opt_revision_unspecified:
      *revnum = SVN_INVALID_REVNUM;
      break;

    case svn_opt_revision_number:
      *revnum = revision->value.number;
      break;

    case svn_opt_revision_head:
      /* If our caller provided a value for HEAD that he wants us to
         use, we'll use it.  Otherwise, we have to query the
         repository (and possible return our fetched value in
         *YOUNGEST_REV, too). */
      if (youngest_rev && SVN_IS_VALID_REVNUM(*youngest_rev))
        {
          *revnum = *youngest_rev;
        }
      else
        {
          if (! ra_session)
            return svn_error_create(SVN_ERR_CLIENT_RA_ACCESS_REQUIRED,
                                    NULL, NULL);
          SVN_ERR(svn_ra_get_latest_revnum(ra_session, revnum, pool));
          if (youngest_rev)
            *youngest_rev = *revnum;
        }
      break;

    case svn_opt_revision_committed:
    case svn_opt_revision_working:
    case svn_opt_revision_base:
    case svn_opt_revision_previous:
      {
        svn_wc_adm_access_t *adm_access;
        const svn_wc_entry_t *ent;

        /* Sanity check. */
        if (path == NULL)
          return svn_error_create(SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED,
                                  NULL, NULL);

        SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, path, FALSE,
                                       0, NULL, NULL, pool));
        SVN_ERR(svn_wc__entry_versioned(&ent, path, adm_access, FALSE, pool));
        SVN_ERR(svn_wc_adm_close(adm_access));

        if ((revision->kind == svn_opt_revision_base)
            || (revision->kind == svn_opt_revision_working))
          {
            *revnum = ent->revision;
          }
        else
          {
            if (! SVN_IS_VALID_REVNUM(ent->cmt_rev))
              return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
                                       _("Path '%s' has no committed "
                                         "revision"), path);
            *revnum = ent->cmt_rev;
            if (revision->kind == svn_opt_revision_previous)
              (*revnum)--;
          }
      }
      break;

    case svn_opt_revision_date:
      /* ### When revision->kind == svn_opt_revision_date, is there an
         ### optimization such that we can compare
         ### revision->value->date with the committed-date in the
         ### entries file (or rather, with some range of which
         ### committed-date is one endpoint), and sometimes avoid a
         ### trip over the RA layer?  The only optimizations I can
         ### think of involve examining other entries to build a
         ### timespan across which committed-revision is known to be
         ### the head, but it doesn't seem worth it.  -kff */
      if (! ra_session)
        return svn_error_create(SVN_ERR_CLIENT_RA_ACCESS_REQUIRED, NULL, NULL);
      SVN_ERR(svn_ra_get_dated_revision(ra_session, revnum,
                                        revision->value.date, pool));
      break;

    default:
      return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
                               _("Unrecognized revision type requested for "
                                 "'%s'"),
                               svn_path_local_style(path, pool));
    }

  /* Final check -- if our caller provided a youngest revision, and
  the number we wound up with is younger than that revision, we need
  to stick to our caller's idea of "youngest". */
  if (youngest_rev
      && SVN_IS_VALID_REVNUM(*youngest_rev)
      && SVN_IS_VALID_REVNUM(*revnum)
      && (*revnum > *youngest_rev))
    *revnum = *youngest_rev;

  return SVN_NO_ERROR;
}
Example #12
0
svn_error_t *
svn_config__parse_registry(svn_config_t *cfg, const char *file,
                           svn_boolean_t must_exist, apr_pool_t *pool)
{
  apr_pool_t *subpool;
  svn_stringbuf_t *section, *option, *value;
  svn_error_t *svn_err = SVN_NO_ERROR;
  HKEY base_hkey, hkey;
  DWORD index;
  LONG err;

  if (0 == strncmp(file, SVN_REGISTRY_HKLM, SVN_REGISTRY_HKLM_LEN))
    {
      base_hkey = HKEY_LOCAL_MACHINE;
      file += SVN_REGISTRY_HKLM_LEN;
    }
  else if (0 == strncmp(file, SVN_REGISTRY_HKCU, SVN_REGISTRY_HKCU_LEN))
    {
      base_hkey = HKEY_CURRENT_USER;
      file += SVN_REGISTRY_HKCU_LEN;
    }
  else
    {
      return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
                               "Unrecognised registry path '%s'",
                               svn_path_local_style(file, pool));
    }

  err = RegOpenKeyEx(base_hkey, file, 0,
                     KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
                     &hkey);
  if (err != ERROR_SUCCESS)
    {
      const int is_enoent = APR_STATUS_IS_ENOENT(APR_FROM_OS_ERROR(err));
      if (!is_enoent)
        return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
                                 "Can't open registry key '%s'",
                                 svn_path_local_style(file, pool));
      else if (must_exist && is_enoent)
        return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
                                 "Can't find registry key '%s'",
                                 svn_path_local_style(file, pool));
      else
        return SVN_NO_ERROR;
    }


  subpool = svn_pool_create(pool);
  section = svn_stringbuf_create("", subpool);
  option = svn_stringbuf_create("", subpool);
  value = svn_stringbuf_create("", subpool);

  /* The top-level values belong to the [DEFAULT] section */
  svn_err = parse_section(cfg, hkey, SVN_CONFIG__DEFAULT_SECTION,
                          option, value);
  if (svn_err)
    goto cleanup;

  /* Now enumerate the rest of the keys. */
  svn_stringbuf_ensure(section, SVN_REG_DEFAULT_NAME_SIZE);
  for (index = 0; ; ++index)
    {
      DWORD section_len = section->blocksize;
      FILETIME last_write_time;
      HKEY sub_hkey;

      err = RegEnumKeyEx(hkey, index, section->data, &section_len,
                         NULL, NULL, NULL, &last_write_time);
      if (err == ERROR_NO_MORE_ITEMS)
          break;
      if (err == ERROR_MORE_DATA)
        {
          svn_stringbuf_ensure(section, section_len);
          err = RegEnumKeyEx(hkey, index, section->data, &section_len,
                             NULL, NULL, NULL, &last_write_time);
        }
      if (err != ERROR_SUCCESS)
        {
          svn_err =  svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
                                      "Can't enumerate registry keys");
          goto cleanup;
        }

      err = RegOpenKeyEx(hkey, section->data, 0,
                         KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
                         &sub_hkey);
      if (err != ERROR_SUCCESS)
        {
          svn_err =  svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
                                      "Can't open existing subkey");
          goto cleanup;
        }

      svn_err = parse_section(cfg, sub_hkey, section->data, option, value);
      RegCloseKey(sub_hkey);
      if (svn_err)
        goto cleanup;
    }

 cleanup:
  RegCloseKey(hkey);
  svn_pool_destroy(subpool);
  return svn_err;
}
Example #13
0
/* A callback of type svn_info_receiver_t.
   Prints svn info in xml mode to standard out */
static svn_error_t *
print_info_xml(void *baton,
               const char *target,
               const svn_info_t *info,
               apr_pool_t *pool)
{
  svn_stringbuf_t *sb = svn_stringbuf_create("", pool);
  const char *rev_str;

  if (SVN_IS_VALID_REVNUM(info->rev))
    rev_str = apr_psprintf(pool, "%ld", info->rev);
  else
    rev_str = apr_pstrdup(pool, _("Resource is not under version control."));

  /* "<entry ...>" */
  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                        "path", svn_path_local_style(target, pool),
                        "kind", svn_cl__node_kind_str_xml(info->kind),
                        "revision", rev_str,
                        NULL);

  svn_cl__xml_tagged_cdata(&sb, pool, "url", info->URL);

  if (info->repos_root_URL || info->repos_UUID)
    {
      /* "<repository>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repository", NULL);

      /* "<root> xx </root>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "root", info->repos_root_URL);

      /* "<uuid> xx </uuid>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "uuid", info->repos_UUID);

      /* "</repository>" */
      svn_xml_make_close_tag(&sb, pool, "repository");
    }

  if (info->has_wc_info)
    {
      /* "<wc-info>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "wc-info", NULL);

      /* "<schedule> xx </schedule>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "schedule",
                               schedule_str(info->schedule));

      /* "<depth> xx </depth>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "depth",
                               svn_depth_to_word(info->depth));

      /* "<copy-from-url> xx </copy-from-url>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "copy-from-url",
                               info->copyfrom_url);

      /* "<copy-from-rev> xx </copy-from-rev>" */
      if (SVN_IS_VALID_REVNUM(info->copyfrom_rev))
        svn_cl__xml_tagged_cdata(&sb, pool, "copy-from-rev",
                                 apr_psprintf(pool, "%ld",
                                              info->copyfrom_rev));

      /* "<text-updated> xx </text-updated>" */
      if (info->text_time)
        svn_cl__xml_tagged_cdata(&sb, pool, "text-updated",
                                 svn_time_to_cstring(info->text_time, pool));

      /* "<checksum> xx </checksum>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "checksum", info->checksum);

      if (info->changelist)
        /* "<changelist> xx </changelist>" */
        svn_cl__xml_tagged_cdata(&sb, pool, "changelist", info->changelist);

      /* "</wc-info>" */
      svn_xml_make_close_tag(&sb, pool, "wc-info");
    }

  if (info->last_changed_author
      || SVN_IS_VALID_REVNUM(info->last_changed_rev)
      || info->last_changed_date)
    {
      svn_cl__print_xml_commit(&sb, info->last_changed_rev,
                               info->last_changed_author,
                               svn_time_to_cstring(info->last_changed_date,
                                                   pool),
                               pool);
    }

  if (info->conflict_old || info->conflict_wrk
      || info->conflict_new || info->prejfile)
    {
      /* "<conflict>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "conflict", NULL);

      /* "<prev-base-file> xx </prev-base-file>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "prev-base-file",
                               info->conflict_old);

      /* "<prev-wc-file> xx </prev-wc-file>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "prev-wc-file",
                               info->conflict_wrk);

      /* "<cur-base-file> xx </cur-base-file>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "cur-base-file",
                               info->conflict_new);

      /* "<prop-file> xx </prop-file>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "prop-file", info->prejfile);

      /* "</conflict>" */
      svn_xml_make_close_tag(&sb, pool, "conflict");
    }

  if (info->lock)
    {
      /* "<lock>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "lock", NULL);

      /* "<token> xx </token>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "token", info->lock->token);

      /* "<owner> xx </owner>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "owner", info->lock->owner);

      /* "<comment ...> xxxx </comment>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "comment", info->lock->comment);

      /* "<created> xx </created>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "created",
                               svn_time_to_cstring
                               (info->lock->creation_date, pool));

      /* "<expires> xx </expires>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "expires",
                               svn_time_to_cstring
                               (info->lock->expiration_date, pool));

      /* "</lock>" */
      svn_xml_make_close_tag(&sb, pool, "lock");
    }

  if (info->tree_conflict)
    SVN_ERR(svn_cl__append_tree_conflict_info_xml(sb, info->tree_conflict,
                                                  pool));

  /* "</entry>" */
  svn_xml_make_close_tag(&sb, pool, "entry");

  return svn_cl__error_checked_fputs(sb->data, stdout);
}
Example #14
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__info(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;
  apr_array_header_t *targets = NULL;
  apr_pool_t *subpool = svn_pool_create(pool);
  int i;
  svn_error_t *err;
  svn_boolean_t saw_a_problem = FALSE;
  svn_opt_revision_t peg_revision;
  svn_info_receiver_t receiver;

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

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

  if (opt_state->xml)
    {
      receiver = print_info_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("info", pool));
    }
  else
    {
      receiver = print_info;

      if (opt_state->incremental)
        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("'incremental' option only valid in XML "
                                  "mode"));
    }

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

  for (i = 0; i < targets->nelts; i++)
    {
      const char *truepath;
      const char *target = APR_ARRAY_IDX(targets, i, const char *);

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

      /* Get peg revisions. */
      SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target, subpool));

      /* If no peg-rev was attached to a URL target, then assume HEAD. */
      if ((svn_path_is_url(target))
          && (peg_revision.kind == svn_opt_revision_unspecified))
        peg_revision.kind = svn_opt_revision_head;

      err = svn_client_info2(truepath,
                             &peg_revision, &(opt_state->start_revision),
                             receiver, NULL, opt_state->depth,
                             opt_state->changelists, ctx, subpool);

      if (err)
        {
          /* If one of the targets is a non-existent URL or wc-entry,
             don't bail out.  Just warn and move on to the next target. */
          if (err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE
              || err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
            {
              SVN_ERR(svn_cmdline_fprintf
                      (stderr, subpool,
                       _("%s:  (Not a versioned resource)\n\n"),
                       svn_path_local_style(target, pool)));
            }
          else if (err->apr_err == SVN_ERR_RA_ILLEGAL_URL)
            {
              SVN_ERR(svn_cmdline_fprintf
                      (stderr, subpool,
                       _("%s:  (Not a valid URL)\n\n"),
                       svn_path_local_style(target, pool)));
            }
          else
            {
              return err;
            }

          svn_error_clear(err);
          err = NULL;
          saw_a_problem = TRUE;
        }
    }
  svn_pool_destroy(subpool);

  if (opt_state->xml && (! opt_state->incremental))
    SVN_ERR(svn_cl__xml_print_footer("info", pool));

  if (saw_a_problem)
    return svn_error_create(SVN_ERR_BASE, NULL, NULL);
  else
    return SVN_NO_ERROR;
}
Example #15
0
/* A callback of type svn_info_receiver_t. */
static svn_error_t *
print_info(void *baton,
           const char *target,
           const svn_info_t *info,
           apr_pool_t *pool)
{
  SVN_ERR(svn_cmdline_printf(pool, _("Path: %s\n"),
                             svn_path_local_style(target, pool)));

  /* ### remove this someday:  it's only here for cmdline output
     compatibility with svn 1.1 and older.  */
  if (info->kind != svn_node_dir)
    SVN_ERR(svn_cmdline_printf(pool, _("Name: %s\n"),
                               svn_path_basename(target, pool)));

  if (info->URL)
    SVN_ERR(svn_cmdline_printf(pool, _("URL: %s\n"), info->URL));

  if (info->repos_root_URL)
    SVN_ERR(svn_cmdline_printf(pool, _("Repository Root: %s\n"),
                               info->repos_root_URL));

  if (info->repos_UUID)
    SVN_ERR(svn_cmdline_printf(pool, _("Repository UUID: %s\n"),
                               info->repos_UUID));

  if (SVN_IS_VALID_REVNUM(info->rev))
    SVN_ERR(svn_cmdline_printf(pool, _("Revision: %ld\n"), info->rev));

  switch (info->kind)
    {
    case svn_node_file:
      SVN_ERR(svn_cmdline_printf(pool, _("Node Kind: file\n")));
      break;

    case svn_node_dir:
      SVN_ERR(svn_cmdline_printf(pool, _("Node Kind: directory\n")));
      break;

    case svn_node_none:
      SVN_ERR(svn_cmdline_printf(pool, _("Node Kind: none\n")));
      break;

    case svn_node_unknown:
    default:
      SVN_ERR(svn_cmdline_printf(pool, _("Node Kind: unknown\n")));
      break;
    }

  if (info->has_wc_info)
    {
      switch (info->schedule)
        {
        case svn_wc_schedule_normal:
          SVN_ERR(svn_cmdline_printf(pool, _("Schedule: normal\n")));
          break;

        case svn_wc_schedule_add:
          SVN_ERR(svn_cmdline_printf(pool, _("Schedule: add\n")));
          break;

        case svn_wc_schedule_delete:
          SVN_ERR(svn_cmdline_printf(pool, _("Schedule: delete\n")));
          break;

        case svn_wc_schedule_replace:
          SVN_ERR(svn_cmdline_printf(pool, _("Schedule: replace\n")));
          break;

        default:
          break;
        }

      switch (info->depth)
        {
        case svn_depth_unknown:
          /* Unknown depth is the norm for remote directories anyway
             (although infinity would be equally appropriate).  Let's
             not bother to print it. */
          break;

        case svn_depth_empty:
          SVN_ERR(svn_cmdline_printf(pool, _("Depth: empty\n")));
          break;

        case svn_depth_files:
          SVN_ERR(svn_cmdline_printf(pool, _("Depth: files\n")));
          break;

        case svn_depth_immediates:
          SVN_ERR(svn_cmdline_printf(pool, _("Depth: immediates\n")));
          break;

        case svn_depth_infinity:
          /* Infinity is the default depth for working copy
             directories.  Let's not print it, it's not special enough
             to be worth mentioning.  */
          break;

        default:
          /* Other depths should never happen here. */
          SVN_ERR(svn_cmdline_printf(pool, _("Depth: INVALID\n")));
        }

      if (info->copyfrom_url)
        SVN_ERR(svn_cmdline_printf(pool, _("Copied From URL: %s\n"),
                                   info->copyfrom_url));

      if (SVN_IS_VALID_REVNUM(info->copyfrom_rev))
        SVN_ERR(svn_cmdline_printf(pool, _("Copied From Rev: %ld\n"),
                                   info->copyfrom_rev));
    }

  if (info->last_changed_author)
    SVN_ERR(svn_cmdline_printf(pool, _("Last Changed Author: %s\n"),
                               info->last_changed_author));

  if (SVN_IS_VALID_REVNUM(info->last_changed_rev))
    SVN_ERR(svn_cmdline_printf(pool, _("Last Changed Rev: %ld\n"),
                               info->last_changed_rev));

  if (info->last_changed_date)
    SVN_ERR(svn_cl__info_print_time(info->last_changed_date,
                                    _("Last Changed Date"), pool));

  if (info->has_wc_info)
    {
      if (info->text_time)
        SVN_ERR(svn_cl__info_print_time(info->text_time,
                                        _("Text Last Updated"), pool));

      if (info->checksum)
        SVN_ERR(svn_cmdline_printf(pool, _("Checksum: %s\n"),
                                   info->checksum));

      if (info->conflict_old)
        SVN_ERR(svn_cmdline_printf(pool,
                                   _("Conflict Previous Base File: %s\n"),
                                   svn_path_local_style(info->conflict_old,
                                                        pool)));

      if (info->conflict_wrk)
        SVN_ERR(svn_cmdline_printf
                (pool, _("Conflict Previous Working File: %s\n"),
                 svn_path_local_style(info->conflict_wrk, pool)));

      if (info->conflict_new)
        SVN_ERR(svn_cmdline_printf(pool,
                                   _("Conflict Current Base File: %s\n"),
                                   svn_path_local_style(info->conflict_new,
                                                        pool)));

      if (info->prejfile)
        SVN_ERR(svn_cmdline_printf(pool, _("Conflict Properties File: %s\n"),
                                   svn_path_local_style(info->prejfile,
                                                        pool)));
    }

  if (info->lock)
    {
      if (info->lock->token)
        SVN_ERR(svn_cmdline_printf(pool, _("Lock Token: %s\n"),
                                   info->lock->token));

      if (info->lock->owner)
        SVN_ERR(svn_cmdline_printf(pool, _("Lock Owner: %s\n"),
                                   info->lock->owner));

      if (info->lock->creation_date)
        SVN_ERR(svn_cl__info_print_time(info->lock->creation_date,
                                        _("Lock Created"), pool));

      if (info->lock->expiration_date)
        SVN_ERR(svn_cl__info_print_time(info->lock->expiration_date,
                                        _("Lock Expires"), pool));

      if (info->lock->comment)
        {
          int comment_lines;
          /* NOTE: The stdio will handle newline translation. */
          comment_lines = svn_cstring_count_newlines(info->lock->comment) + 1;
          SVN_ERR(svn_cmdline_printf(pool,
                                     Q_("Lock Comment (%i line):\n%s\n",
                                        "Lock Comment (%i lines):\n%s\n",
                                        comment_lines),
                                     comment_lines,
                                     info->lock->comment));
        }
    }

  if (info->changelist)
    SVN_ERR(svn_cmdline_printf(pool, _("Changelist: %s\n"),
                               info->changelist));

  if (info->tree_conflict)
    {
      const char *desc, *src_left_version, *src_right_version;

      SVN_ERR(svn_cl__get_human_readable_tree_conflict_description(
                &desc, info->tree_conflict, pool));
      src_left_version =
        svn_cl__node_description(info->tree_conflict->src_left_version, pool);
      src_right_version =
        svn_cl__node_description(info->tree_conflict->src_right_version, pool);

      svn_cmdline_printf(pool,
                         "%s: %s\n",
                         _("Tree conflict"),
                         desc);

      if (src_left_version)
        svn_cmdline_printf(pool,
                           "  %s: %s\n",
                           _("Source  left"), /* (1) */
                           src_left_version);
        /* (1): Sneaking in a space in "Source  left" so that it is the
         * same length as "Source right" while it still starts in the same
         * column. That's just a tiny tweak in the English `svn'. */

      if (src_right_version)
        svn_cmdline_printf(pool,
                           "  %s: %s\n",
                           _("Source right"),
                           src_right_version);
    }

  /* Print extra newline separator. */
  return svn_cmdline_printf(pool, "\n");
}
Example #16
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_wc_adm_access_t *adm_access,
                            svn_depth_t depth,
                            svn_boolean_t depth_is_sticky,
                            svn_boolean_t *timestamp_sleep,
                            svn_boolean_t ignore_externals,
                            svn_boolean_t allow_unver_obstructions,
                            svn_client_ctx_t *ctx,
                            apr_pool_t *pool)
{
  const svn_ra_reporter3_t *reporter;
  void *report_baton;
  const svn_wc_entry_t *entry;
  const char *URL, *anchor, *target, *source_root, *switch_rev_url;
  svn_ra_session_t *ra_session;
  svn_revnum_t revnum;
  svn_error_t *err = SVN_NO_ERROR;
  svn_wc_adm_access_t *dir_access;
  const svn_boolean_t close_adm_access = ! adm_access;
  const char *diff3_cmd;
  svn_boolean_t use_commit_times;
  svn_boolean_t sleep_here;
  svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
  const svn_delta_editor_t *switch_editor;
  void *switch_edit_baton;
  svn_wc_traversal_info_t *traversal_info = svn_wc_init_traversal_info(pool);
  const char *preserved_exts_str;
  apr_array_header_t *preserved_exts;
  svn_boolean_t server_supports_depth;
  svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
                                                 SVN_CONFIG_CATEGORY_CONFIG,
                                                 APR_HASH_KEY_STRING)
                                  : NULL;

  /* An unknown depth can't be sticky. */
  if (depth == svn_depth_unknown)
    depth_is_sticky = FALSE;

  /* Do not support the situation of both exclude and switch a target. */
  if (depth_is_sticky && depth == svn_depth_exclude)
    return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                             _("Cannot both exclude and switch a path"));

  /* Get the external diff3, if any. */
  svn_config_get(cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
                 SVN_CONFIG_OPTION_DIFF3_CMD, NULL);

  /* See if the user wants last-commit timestamps instead of current ones. */
  SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
                              SVN_CONFIG_SECTION_MISCELLANY,
                              SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));

  /* See which files the user wants to preserve the extension of when
     conflict files are made. */
  svn_config_get(cfg, &preserved_exts_str, SVN_CONFIG_SECTION_MISCELLANY,
                 SVN_CONFIG_OPTION_PRESERVED_CF_EXTS, "");
  preserved_exts = *preserved_exts_str
    ? svn_cstring_split(preserved_exts_str, "\n\r\t\v ", FALSE, pool)
    : NULL;

  /* Sanity check.  Without these, the switch is meaningless. */
  SVN_ERR_ASSERT(path);
  SVN_ERR_ASSERT(switch_url && (switch_url[0] != '\0'));

  /* ### Need to lock the whole target tree to invalidate wcprops. Does
     non-recursive switch really need to invalidate the whole tree? */
  if (adm_access)
    {
      svn_wc_adm_access_t *a = adm_access;
      const char *dir_access_path;

      /* This is a little hacky, but open two new read-only access
         baton's to get the anchor and target access batons that would
         be used if a locked access baton was not available. */
      SVN_ERR(svn_wc_adm_open_anchor(&adm_access, &dir_access, &target, path,
                                     FALSE, -1, ctx->cancel_func,
                                     ctx->cancel_baton, pool));
      anchor = svn_wc_adm_access_path(adm_access);
      dir_access_path = svn_wc_adm_access_path(dir_access);
      SVN_ERR(svn_wc_adm_close2(adm_access, pool));

      SVN_ERR(svn_wc_adm_retrieve(&adm_access, a, anchor, pool));
      SVN_ERR(svn_wc_adm_retrieve(&dir_access, a, dir_access_path, pool));
    }
  else
    {
      SVN_ERR(svn_wc_adm_open_anchor(&adm_access, &dir_access, &target, path,
                                     TRUE, -1, ctx->cancel_func,
                                     ctx->cancel_baton, pool));
      anchor = svn_wc_adm_access_path(adm_access);
    }

  SVN_ERR(svn_wc__entry_versioned(&entry, anchor, adm_access, FALSE, pool));
  if (! entry->url)
    return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
                             _("Directory '%s' has no URL"),
                             svn_path_local_style(anchor, pool));

  URL = apr_pstrdup(pool, entry->url);

  /* Open an RA session to 'source' URL */
  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
                                           &switch_rev_url,
                                           switch_url, adm_access,
                                           peg_revision, revision,
                                           ctx, pool));
  SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_root, pool));

  /* Disallow a switch operation to change the repository root of the
     target. */
  if (! svn_path_is_ancestor(source_root, URL))
    return svn_error_createf
      (SVN_ERR_WC_INVALID_SWITCH, NULL,
       _("'%s'\n"
         "is not the same repository as\n"
         "'%s'"), URL, source_root);

  /* We may need to crop the tree if the depth is sticky */
  if (depth_is_sticky && depth < svn_depth_infinity)
    {
      const svn_wc_entry_t *target_entry;

      SVN_ERR(svn_wc_entry(
          &target_entry,
          svn_dirent_join(svn_wc_adm_access_path(adm_access), target, pool),
          adm_access, TRUE, pool));

      if (target_entry && target_entry->kind == svn_node_dir)
        {
          SVN_ERR(svn_wc_crop_tree(adm_access, target, depth,
                                   ctx->notify_func2, ctx->notify_baton2,
                                   ctx->cancel_func, ctx->cancel_baton,
                                   pool));
        }
    }

  SVN_ERR(svn_ra_reparent(ra_session, URL, pool));

  /* Fetch the switch (update) editor.  If REVISION is invalid, that's
     okay; the RA driver will call editor->set_target_revision() later on. */
  SVN_ERR(svn_wc_get_switch_editor3(&revnum, adm_access, target,
                                    switch_rev_url, use_commit_times, depth,
                                    depth_is_sticky, allow_unver_obstructions,
                                    ctx->notify_func2, ctx->notify_baton2,
                                    ctx->cancel_func, ctx->cancel_baton,
                                    ctx->conflict_func, ctx->conflict_baton,
                                    diff3_cmd, preserved_exts,
                                    &switch_editor, &switch_edit_baton,
                                    traversal_info, pool));

  /* Tell RA to do an update of URL+TARGET to REVISION; if we pass an
     invalid revnum, that means RA will use the latest revision. */
  SVN_ERR(svn_ra_do_switch2(ra_session, &reporter, &report_baton, revnum,
                            target, depth, switch_rev_url,
                            switch_editor, switch_edit_baton, pool));

  SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
                                SVN_RA_CAPABILITY_DEPTH, pool));

  /* Drive the reporter structure, describing the revisions within
     PATH.  When we call reporter->finish_report, the update_editor
     will be driven by svn_repos_dir_delta2.

     We pass in a traversal_info for recording all externals. It
     shouldn't be needed for a switch if it wasn't for the relative
     externals of type '../path'. All of those must be resolved to 
     the new location.  */
  err = svn_wc_crawl_revisions4(path, dir_access, reporter, report_baton,
                                TRUE, depth, (! depth_is_sticky),
                                (! server_supports_depth),
                                use_commit_times,
                                ctx->notify_func2, ctx->notify_baton2,
                                traversal_info, 
                                pool);

  if (err)
    {
      /* Don't rely on the error handling to handle the sleep later, do
         it now */
      svn_io_sleep_for_timestamps(path, pool);
      return err;
    }
  *use_sleep = TRUE;

  /* We handle externals after the switch is complete, so that
     handling external items (and any errors therefrom) doesn't delay
     the primary operation. */
  if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
    err = svn_client__handle_externals(adm_access, traversal_info, switch_url,
                                       path, source_root, depth,
                                       use_sleep, ctx, pool);

  /* Sleep to ensure timestamp integrity (we do this regardless of
     errors in the actual switch operation(s)). */
  if (sleep_here)
    svn_io_sleep_for_timestamps(path, pool);

  /* Return errors we might have sustained. */
  if (err)
    return err;

  if (close_adm_access)
    SVN_ERR(svn_wc_adm_close2(adm_access, pool));

  /* Let everyone know we're finished here. */
  if (ctx->notify_func2)
    {
      svn_wc_notify_t *notify
        = svn_wc_create_notify(anchor, svn_wc_notify_update_completed, pool);
      notify->kind = svn_node_none;
      notify->content_state = notify->prop_state
        = svn_wc_notify_state_inapplicable;
      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
      notify->revision = revnum;
      (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
    }

  /* If the caller wants the result revision, give it to them. */
  if (result_rev)
    *result_rev = revnum;

  return SVN_NO_ERROR;
}
Example #17
0
static void
status_func (void *baton, const char *path, svn_wc_status2_t *status) {
	apr_pool_t *pool = ((status_bt *)baton)->pool;
	print_status (svn_path_local_style (path, pool), 
			      TRUE, TRUE, TRUE, status, ((status_bt *) baton)->L, pool);			
}
Example #18
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__propdel(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;
  int i;

  /* Get the property's name (and a UTF-8 version of that name). */
  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));
  /* No need to check svn_prop_name_is_valid for *deleting*
     properties, and it may even be useful to allow, in case invalid
     properties sneaked through somehow. */

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


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

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

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

      /* Let libsvn_client do the real work. */
      SVN_ERR(svn_client_revprop_set(pname_utf8, NULL,
                                     URL, &(opt_state->start_revision),
                                     &rev, FALSE, ctx, pool));
      if (! opt_state->quiet)
        {
          SVN_ERR(svn_cmdline_printf(pool,
                                     _("property '%s' deleted from"
                                       " repository revision %ld\n"),
                                     pname_utf8, rev));
        }
    }
  else if (opt_state->start_revision.kind != svn_opt_revision_unspecified)
    {
      return svn_error_createf
        (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
         _("Cannot specify revision for deleting versioned property '%s'"),
         pname);
    }
  else  /* operate on a normal, versioned property (not a revprop) */
    {
      apr_pool_t *subpool = svn_pool_create(pool);

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

      /* For each target, remove the property PNAME. */
      for (i = 0; i < targets->nelts; i++)
        {
          const char *target = APR_ARRAY_IDX(targets, i, const char *);
          svn_commit_info_t *commit_info;
          svn_boolean_t success;

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

          /* Pass FALSE for 'skip_checks' because it doesn't matter here,
             and opt_state->force doesn't apply to this command anyway. */
          SVN_ERR(svn_cl__try(svn_client_propset3
                              (&commit_info, pname_utf8,
                               NULL, target,
                               opt_state->depth,
                               FALSE, SVN_INVALID_REVNUM,
                               opt_state->changelists, NULL, 
                               ctx, subpool),
                              &success, opt_state->quiet,
                              SVN_ERR_UNVERSIONED_RESOURCE,
                              SVN_ERR_ENTRY_NOT_FOUND,
                              SVN_NO_ERROR));

          if (success && (! opt_state->quiet))
            {
              SVN_ERR(svn_cmdline_printf
                      (subpool,
                       SVN_DEPTH_IS_RECURSIVE(opt_state->depth)
                       ? _("property '%s' deleted (recursively) from '%s'.\n")
                       : _("property '%s' deleted from '%s'.\n"),
                       pname_utf8, svn_path_local_style(target, subpool)));
            }
        }
      svn_pool_destroy(subpool);
    }

  return SVN_NO_ERROR;
}
Example #19
0
svn_error_t *
svn_cl__print_status_xml(const char *path,
                         svn_wc_status2_t *status,
                         apr_pool_t *pool)
{
  svn_stringbuf_t *sb = svn_stringbuf_create("", pool);
  apr_hash_t *att_hash;

  if (status->text_status == svn_wc_status_none
      && status->repos_text_status == svn_wc_status_none)
    return SVN_NO_ERROR;

  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                        "path", svn_path_local_style(path, pool), NULL);

  att_hash = apr_hash_make(pool);
  apr_hash_set(att_hash, "item", APR_HASH_KEY_STRING,
               generate_status_desc(status->text_status));
  apr_hash_set(att_hash, "props", APR_HASH_KEY_STRING,
               generate_status_desc(status->prop_status));
  if (status->locked)
    apr_hash_set(att_hash, "wc-locked", APR_HASH_KEY_STRING, "true");
  if (status->copied)
    apr_hash_set(att_hash, "copied", APR_HASH_KEY_STRING, "true");
  if (status->switched)
    apr_hash_set(att_hash, "switched", APR_HASH_KEY_STRING, "true");
  if (status->entry && ! status->entry->copied)
    apr_hash_set(att_hash, "revision", APR_HASH_KEY_STRING,
                 apr_psprintf(pool, "%ld", status->entry->revision));
  svn_xml_make_open_tag_hash(&sb, pool, svn_xml_normal, "wc-status",
                             att_hash);

  if (status->entry && SVN_IS_VALID_REVNUM(status->entry->cmt_rev))
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "commit",
                            "revision",
                            apr_psprintf(pool, "%ld",
                                         status->entry->cmt_rev),
                            NULL);

      svn_cl__xml_tagged_cdata(&sb, pool, "author",
                               status->entry->cmt_author);

      if (status->entry->cmt_date)
        svn_cl__xml_tagged_cdata(&sb, pool, "date",
                                 svn_time_to_cstring
                                 (status->entry->cmt_date, pool));

      svn_xml_make_close_tag(&sb, pool, "commit");
    }

  if (status->entry && status->entry->lock_token)
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "lock", NULL);

      svn_cl__xml_tagged_cdata(&sb, pool, "token", status->entry->lock_token);

      /* If lock_owner is NULL, assume WC is corrupt. */
      if (status->entry->lock_owner)
        svn_cl__xml_tagged_cdata(&sb, pool, "owner",
                                 status->entry->lock_owner);
      else
        return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
                                 _("'%s' has lock token, but no lock owner"),
                                 svn_path_local_style(path, pool));

      svn_cl__xml_tagged_cdata(&sb, pool, "comment",
                               status->entry->lock_comment);

      svn_cl__xml_tagged_cdata(&sb, pool, "created",
                               svn_time_to_cstring
                               (status->entry->lock_creation_date, pool));

      svn_xml_make_close_tag(&sb, pool, "lock");
    }

  svn_xml_make_close_tag(&sb, pool, "wc-status");

  if (status->repos_text_status != svn_wc_status_none
      || status->repos_prop_status != svn_wc_status_none
      || status->repos_lock)
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repos-status",
                            "item",
                            generate_status_desc(status->repos_text_status),
                            "props",
                            generate_status_desc(status->repos_prop_status),
                            NULL);
      if (status->repos_lock)
        {
          svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "lock", NULL);

          svn_cl__xml_tagged_cdata(&sb, pool, "token",
                                   status->repos_lock->token);

          svn_cl__xml_tagged_cdata(&sb, pool, "owner",
                                   status->repos_lock->owner);

          svn_cl__xml_tagged_cdata(&sb, pool, "comment",
                                   status->repos_lock->comment);

          svn_cl__xml_tagged_cdata(&sb, pool, "created",
                                   svn_time_to_cstring
                                   (status->repos_lock->creation_date,
                                    pool));

          if (status->repos_lock->expiration_date != 0)
            {
              svn_cl__xml_tagged_cdata(&sb, pool, "expires",
                                       svn_time_to_cstring
                                       (status->repos_lock->expiration_date,
                                        pool));
            }

          svn_xml_make_close_tag(&sb, pool, "lock");
        }
      svn_xml_make_close_tag(&sb, pool, "repos-status");
    }

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

  return svn_cl__error_checked_fputs(sb->data, stdout);
}
Example #20
0
svn_error_t *
svn_client_status4(svn_revnum_t *result_rev,
                   const char *path,
                   const svn_opt_revision_t *revision,
                   svn_wc_status_func3_t status_func,
                   void *status_baton,
                   svn_depth_t depth,
                   svn_boolean_t get_all,
                   svn_boolean_t update,
                   svn_boolean_t no_ignore,
                   svn_boolean_t ignore_externals,
                   const apr_array_header_t *changelists,
                   svn_client_ctx_t *ctx,
                   apr_pool_t *pool)
{
  svn_wc_adm_access_t *anchor_access, *target_access;
  svn_wc_traversal_info_t *traversal_info = svn_wc_init_traversal_info(pool);
  const char *anchor, *target;
  const svn_delta_editor_t *editor;
  void *edit_baton, *set_locks_baton;
  const svn_wc_entry_t *entry = NULL;
  struct status_baton sb;
  apr_array_header_t *ignores;
  svn_error_t *err;
  apr_hash_t *changelist_hash = NULL;
  svn_revnum_t edit_revision = SVN_INVALID_REVNUM;

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

  sb.real_status_func = status_func;
  sb.real_status_baton = status_baton;
  sb.deleted_in_repos = FALSE;
  sb.changelist_hash = changelist_hash;

  /* Try to open the target directory. If the target is a file or an
     unversioned directory, open the parent directory instead */
  err = svn_wc_adm_open3(&anchor_access, NULL, path, FALSE,
                         SVN_DEPTH_IS_RECURSIVE(depth) ? -1 : 1,
                         ctx->cancel_func, ctx->cancel_baton,
                         pool);
  if (err && err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)
    {
      svn_error_clear(err);
      SVN_ERR(svn_wc_adm_open_anchor(&anchor_access, &target_access, &target,
                                     path, FALSE,
                                     SVN_DEPTH_IS_RECURSIVE(depth) ? -1 : 1,
                                     ctx->cancel_func, ctx->cancel_baton,
                                     pool));
    }
  else if (!err)
    {
      target = "";
      target_access = anchor_access;
    }
  else
    return err;

  anchor = svn_wc_adm_access_path(anchor_access);

  /* Get the status edit, and use our wrapping status function/baton
     as the callback pair. */
  SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, pool));
  SVN_ERR(svn_wc_get_status_editor4(&editor, &edit_baton, &set_locks_baton,
                                    &edit_revision, anchor_access, target,
                                    depth, get_all, no_ignore, ignores,
                                    tweak_status, &sb, ctx->cancel_func,
                                    ctx->cancel_baton, traversal_info,
                                    pool));

  /* If we want to know about out-of-dateness, we crawl the working copy and
     let the RA layer drive the editor for real.  Otherwise, we just close the
     edit.  :-) */
  if (update)
    {
      svn_ra_session_t *ra_session;
      const char *URL;
      svn_node_kind_t kind;
      svn_boolean_t server_supports_depth;

      /* Get full URL from the ANCHOR. */
      if (! entry)
        SVN_ERR(svn_wc__entry_versioned(&entry, anchor, anchor_access, FALSE,
                                        pool));
      if (! entry->url)
        return svn_error_createf
          (SVN_ERR_ENTRY_MISSING_URL, NULL,
           _("Entry '%s' has no URL"),
           svn_path_local_style(anchor, pool));
      URL = apr_pstrdup(pool, entry->url);

      /* Open a repository session to the URL. */
      SVN_ERR(svn_client__open_ra_session_internal(&ra_session, URL, anchor,
                                                   anchor_access, NULL,
                                                   FALSE, TRUE,
                                                   ctx, pool));

      /* Verify that URL exists in HEAD.  If it doesn't, this can save
         us a whole lot of hassle; if it does, the cost of this
         request should be minimal compared to the size of getting
         back the average amount of "out-of-date" information. */
      SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM,
                                &kind, pool));
      if (kind == svn_node_none)
        {
          /* Our status target does not exist in HEAD of the
             repository.  If we're just adding this thing, that's
             fine.  But if it was previously versioned, then it must
             have been deleted from the repository. */
          if (entry->schedule != svn_wc_schedule_add)
            sb.deleted_in_repos = TRUE;

          /* And now close the edit. */
          SVN_ERR(editor->close_edit(edit_baton, pool));
        }
      else
        {
          svn_revnum_t revnum;
          report_baton_t rb;

          if (revision->kind == svn_opt_revision_head)
            {
              /* Cause the revision number to be omitted from the request,
                 which implies HEAD. */
              revnum = SVN_INVALID_REVNUM;
            }
          else
            {
              /* Get a revision number for our status operation. */
              SVN_ERR(svn_client__get_revision_number
                      (&revnum, NULL, ra_session, revision, target, pool));
            }

          /* Do the deed.  Let the RA layer drive the status editor. */
          SVN_ERR(svn_ra_do_status2(ra_session, &rb.wrapped_reporter,
                                    &rb.wrapped_report_baton,
                                    target, revnum, depth, editor,
                                    edit_baton, pool));

          /* Init the report baton. */
          rb.ancestor = apr_pstrdup(pool, URL);
          rb.set_locks_baton = set_locks_baton;
          rb.ctx = ctx;
          rb.pool = pool;

          SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
                                        SVN_RA_CAPABILITY_DEPTH, pool));

          /* Drive the reporter structure, describing the revisions
             within PATH.  When we call reporter->finish_report,
             EDITOR will be driven to describe differences between our
             working copy and HEAD. */
          SVN_ERR(svn_wc_crawl_revisions4(path, target_access,
                                          &lock_fetch_reporter, &rb, FALSE,
                                          depth, TRUE, (! server_supports_depth),
                                          FALSE, NULL, NULL, NULL, pool));
        }
    }
  else
    {
      SVN_ERR(editor->close_edit(edit_baton, pool));
    }

  if (ctx->notify_func2 && update)
    {
      svn_wc_notify_t *notify
        = svn_wc_create_notify(path, svn_wc_notify_status_completed, pool);
      notify->revision = edit_revision;
      (ctx->notify_func2)(ctx->notify_baton2, notify, pool);
    }

  /* If the caller wants the result revision, give it to them. */
  if (result_rev)
    *result_rev = edit_revision;

  /* Close the access baton here, as svn_client__do_external_status()
     calls back into this function and thus will be re-opening the
     working copy. */
  SVN_ERR(svn_wc_adm_close2(anchor_access, pool));

  /* If there are svn:externals set, we don't want those to show up as
     unversioned or unrecognized, so patch up the hash.  If caller wants
     all the statuses, we will change unversioned status items that
     are interesting to an svn:externals property to
     svn_wc_status_unversioned, otherwise we'll just remove the status
     item altogether.

     We only descend into an external if depth is svn_depth_infinity or
     svn_depth_unknown.  However, there are conceivable behaviors that
     would involve descending under other circumstances; thus, we pass
     depth anyway, so the code will DTRT if we change the conditional
     in the future.
  */
  if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
    SVN_ERR(svn_client__do_external_status(traversal_info, status_func,
                                           status_baton, depth, get_all,
                                           update, no_ignore, ctx, pool));

  return SVN_NO_ERROR;
}
Example #21
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__status(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;
    apr_array_header_t *targets;
    apr_pool_t *subpool;
    apr_hash_t *master_cl_hash = apr_hash_make(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, pool));

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

    /* We want our -u statuses to be against HEAD. */
    rev.kind = svn_opt_revision_head;

    /* The notification callback, leave the notifier as NULL in XML mode */
    if (! opt_state->xml)
        svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE,
                             FALSE, FALSE, pool);

    subpool = svn_pool_create(pool);

    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", 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.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 = pool;

    SVN_ERR(svn_opt__eat_peg_revisions(&targets, targets, 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(subpool);

        SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

        if (opt_state->xml)
            SVN_ERR(print_start_target_xml(svn_path_local_style(target, subpool),
                                           subpool));

        /* Retrieve a hash of status structures with the information
           requested by the user. */
        SVN_ERR(svn_cl__try(svn_client_status4(&repos_rev, target, &rev,
                                               print_status, &sb,
                                               opt_state->depth,
                                               opt_state->verbose,
                                               opt_state->update,
                                               opt_state->no_ignore,
                                               opt_state->ignore_externals,
                                               opt_state->changelists,
                                               ctx, subpool),
                            NULL, opt_state->quiet,
                            /* not versioned: */
                            SVN_ERR_WC_NOT_DIRECTORY,
                            SVN_NO_ERROR));

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

    /* If any paths were cached because they were associatied 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("", pool);

        for (hi = apr_hash_first(pool, master_cl_hash); hi;
                hi = apr_hash_next(hi))
        {
            const char *changelist_name;
            apr_array_header_t *path_array;
            const void *key;
            void *val;
            int j;

            apr_hash_this(hi, &key, NULL, &val);
            changelist_name = key;
            path_array = val;

            /* ### 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_set(buf, "");
                svn_xml_make_open_tag(&buf, pool, svn_xml_normal, "changelist",
                                      "name", changelist_name, NULL);
                SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout));
            }
            else
                SVN_ERR(svn_cmdline_printf(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 *);
                SVN_ERR(print_status_normal_or_xml(&sb, scache->path,
                                                   scache->status, pool));
            }

            if (opt_state->xml)
            {
                svn_stringbuf_set(buf, "");
                svn_xml_make_close_tag(&buf, pool, "changelist");
                SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout));
            }
        }
    }
Example #22
0
svn_error_t *
svn_sqlite__open(svn_sqlite__db_t **db, const char *path,
                 svn_sqlite__mode_t mode, const char * const statements[],
                 int latest_schema, const char * const *upgrade_sql,
                 apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
  SVN_ERR(svn_atomic__init_once(&sqlite_init_state,
                                init_sqlite, NULL, scratch_pool));

  *db = apr_palloc(result_pool, sizeof(**db));

#if SQLITE_VERSION_AT_LEAST(3,5,0)
  {
    int flags;

    if (mode == svn_sqlite__mode_readonly)
      flags = SQLITE_OPEN_READONLY;
    else if (mode == svn_sqlite__mode_readwrite)
      flags = SQLITE_OPEN_READWRITE;
    else if (mode == svn_sqlite__mode_rwcreate)
      flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
    else
      SVN_ERR_MALFUNCTION();

    /* If this flag is defined (3.6.x), then let's turn off SQLite's mutexes.
       All svn objects are single-threaded, so we can already guarantee that
       our use of the SQLite handle will be serialized properly.
       Note: in 3.6.x, we've already config'd SQLite into MULTITHREAD mode,
       so this is probably redundant... */
    /* ### yeah. remove when autoconf magic is done for init/config. */
#ifdef SQLITE_OPEN_NOMUTEX
    flags |= SQLITE_OPEN_NOMUTEX;
#endif

    /* Open the database. Note that a handle is returned, even when an error
       occurs (except for out-of-memory); thus, we can safely use it to
       extract an error message and construct an svn_error_t. */
    SQLITE_ERR(sqlite3_open_v2(path, &(*db)->db3, flags, NULL), *db);
  }
#else
  /* Older versions of SQLite (pre-3.5.x) will always create the database
     if it doesn't exist.  So, if we are asked to be read-only or read-write,
     we ensure the database already exists - if it doesn't, then we will
     explicitly error out before asking SQLite to do anything.

     Pre-3.5.x SQLite versions also don't support read-only ops either.
   */
  if (mode == svn_sqlite__mode_readonly || mode == svn_sqlite__mode_readwrite)
    {
      svn_node_kind_t kind;
      SVN_ERR(svn_io_check_path(path, &kind, scratch_pool));
      if (kind != svn_node_file) {
          return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
                                   _("Expected SQLite database not found: %s"),
                                   svn_path_local_style(path, scratch_pool));
      }
    }
  else if (mode == svn_sqlite__mode_rwcreate)
    {
      /* do nothing - older SQLite's will create automatically. */
    }
  else
    SVN_ERR_MALFUNCTION();

  SQLITE_ERR(sqlite3_open(path, &(*db)->db3), *db);
#endif

  /* Retry until timeout when database is busy. */
  SQLITE_ERR(sqlite3_busy_timeout((*db)->db3, BUSY_TIMEOUT), *db);
#ifdef SQLITE3_DEBUG
  sqlite3_trace((*db)->db3, sqlite_tracer, (*db)->db3);
#endif

  SVN_ERR(svn_sqlite__exec(*db, "PRAGMA case_sensitive_like=on;"));

  /* Validate the schema, upgrading if necessary. */
  SVN_ERR(check_format(*db, latest_schema, upgrade_sql, scratch_pool));

  /* Store the provided statements. */
  if (statements)
    {
      (*db)->statement_strings = statements;
      (*db)->nbr_statements = 0;
      while (*statements != NULL)
        {
          statements++;
          (*db)->nbr_statements++;
        }
      (*db)->prepared_stmts = apr_pcalloc(result_pool, (*db)->nbr_statements
                                                * sizeof(svn_sqlite__stmt_t *));
    }
  else
    (*db)->nbr_statements = 0;

  (*db)->result_pool = result_pool;
  apr_pool_cleanup_register(result_pool, *db, close_apr, apr_pool_cleanup_null);

  return SVN_NO_ERROR;
}