#include <stdlib.h>
#include <apr_hash.h>
#include "svn_hash.h"
#include "svn_cmdline.h"
#include "svn_string.h"
#include "svn_error.h"
#include "svn_sorts.h"
#include "svn_subst.h"
#include "svn_props.h"
#include "svn_string.h"
#include "svn_opt.h"
#include "svn_xml.h"
#include "svn_base64.h"
#include "cl.h"
#include "private/svn_string_private.h"
#include "private/svn_cmdline_private.h"
#include "svn_private_config.h"
svn_error_t *
svn_cl__revprop_prepare(const svn_opt_revision_t *revision,
const apr_array_header_t *targets,
const char **URL,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
const char *target;
if (revision->kind != svn_opt_revision_number
&& revision->kind != svn_opt_revision_date
&& revision->kind != svn_opt_revision_head)
return svn_error_create
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Must specify the revision as a number, a date or 'HEAD' "
"when operating on a revision property"));
if (targets->nelts != 1)
return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Wrong number of targets specified"));
target = APR_ARRAY_IDX(targets, 0, const char *);
SVN_ERR(svn_client_url_from_path2(URL, target, ctx, pool, pool));
if (*URL == NULL)
return svn_error_create
(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
_("Either a URL or versioned item is required"));
return SVN_NO_ERROR;
}
void
svn_cl__check_boolean_prop_val(const char *propname, const char *propval,
apr_pool_t *pool)
{
svn_stringbuf_t *propbuf;
if (!svn_prop_is_boolean(propname))
return;
propbuf = svn_stringbuf_create(propval, pool);
svn_stringbuf_strip_whitespace(propbuf);
if (propbuf->data[0] == '\0'
|| svn_cstring_casecmp(propbuf->data, "0") == 0
|| svn_cstring_casecmp(propbuf->data, "no") == 0
|| svn_cstring_casecmp(propbuf->data, "off") == 0
|| svn_cstring_casecmp(propbuf->data, "false") == 0)
{
svn_error_t *err = svn_error_createf
(SVN_ERR_BAD_PROPERTY_VALUE, NULL,
_("To turn off the %s property, use 'svn propdel';\n"
"setting the property to '%s' will not turn it off."),
propname, propval);
svn_handle_warning2(stderr, err, "svn: ");
svn_error_clear(err);
}
}
static const char*
force_prop_option_message(svn_cl__prop_use_t prop_use, const char *prop_name,
apr_pool_t *scratch_pool)
{
switch (prop_use)
{
case svn_cl__prop_use_set:
return apr_psprintf(
scratch_pool,
_("Use '--force' to set the '%s' property."),
prop_name);
case svn_cl__prop_use_edit:
return apr_psprintf(
scratch_pool,
_("Use '--force' to edit the '%s' property."),
prop_name);
case svn_cl__prop_use_use:
default:
return apr_psprintf(
scratch_pool,
_("Use '--force' to use the '%s' property'."),
prop_name);
}
}
static const char*
wrong_prop_error_message(svn_cl__prop_use_t prop_use, const char *prop_name,
apr_pool_t *scratch_pool)
{
switch (prop_use)
{
case svn_cl__prop_use_set:
return apr_psprintf(
scratch_pool,
_("'%s' is not a valid %s property name; use '--force' to set it"),
prop_name, SVN_PROP_PREFIX);
case svn_cl__prop_use_edit:
return apr_psprintf(
scratch_pool,
_("'%s' is not a valid %s property name; use '--force' to edit it"),
prop_name, SVN_PROP_PREFIX);
case svn_cl__prop_use_use:
default:
return apr_psprintf(
scratch_pool,
_("'%s' is not a valid %s property name; use '--force' to use it"),
prop_name, SVN_PROP_PREFIX);
}
}
svn_error_t *
svn_cl__check_svn_prop_name(const char *propname,
svn_boolean_t revprop,
svn_cl__prop_use_t prop_use,
apr_pool_t *scratch_pool)
{
static const char *const nodeprops[] =
{
SVN_PROP_NODE_ALL_PROPS
};
static const apr_size_t nodeprops_len = sizeof(nodeprops)/sizeof(*nodeprops);
static const char *const revprops[] =
{
SVN_PROP_REVISION_ALL_PROPS
};
static const apr_size_t revprops_len = sizeof(revprops)/sizeof(*revprops);
const char *const *const proplist = (revprop ? revprops : nodeprops);
const apr_size_t numprops = (revprop ? revprops_len : nodeprops_len);
svn_cl__simcheck_t **propkeys;
svn_cl__simcheck_t *propbuf;
apr_size_t i;
svn_string_t propstring;
svn_string_t prefix;
svn_membuf_t buffer;
propstring.data = propname;
propstring.len = strlen(propname);
prefix.data = SVN_PROP_PREFIX;
prefix.len = strlen(SVN_PROP_PREFIX);
svn_membuf__create(&buffer, 0, scratch_pool);
if (propstring.len < prefix.len
|| propstring.data[prefix.len - 1] != prefix.data[prefix.len - 1])
return SVN_NO_ERROR;
else
{
apr_size_t lcs;
const apr_size_t name_len = propstring.len;
propstring.len = prefix.len;
svn_string__similarity(&propstring, &prefix, &buffer, &lcs);
propstring.len = name_len;
if (lcs < prefix.len - 1)
return SVN_NO_ERROR;
if (lcs == prefix.len - 1)
{
for (i = 0; i < numprops; ++i)
{
if (0 == strcmp(proplist[i] + prefix.len, propname + prefix.len))
return svn_error_quick_wrap(svn_error_createf(
SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
_("'%s' is not a valid %s property name;"
" did you mean '%s'?"),
propname, SVN_PROP_PREFIX, proplist[i]),
force_prop_option_message(prop_use, propname, scratch_pool));
}
return SVN_NO_ERROR;
}
}
propkeys = apr_palloc(scratch_pool,
numprops * sizeof(svn_cl__simcheck_t*));
propbuf = apr_palloc(scratch_pool,
numprops * sizeof(svn_cl__simcheck_t));
propstring.data += prefix.len;
propstring.len -= prefix.len;
for (i = 0; i < numprops; ++i)
{
propkeys[i] = &propbuf[i];
propbuf[i].token.data = proplist[i] + prefix.len;
propbuf[i].token.len = strlen(propbuf[i].token.data);
propbuf[i].data = proplist[i];
}
switch (svn_cl__similarity_check(
propstring.data, propkeys, numprops, scratch_pool))
{
case 0:
return SVN_NO_ERROR;
case 1:
return svn_error_create(
SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
wrong_prop_error_message(prop_use, propname, scratch_pool));
case 2:
return svn_error_quick_wrap(svn_error_createf(
SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
_("'%s' is not a valid %s property name; did you mean '%s'?"),
propname, SVN_PROP_PREFIX,
(const char *)propkeys[0]->data),
force_prop_option_message(prop_use, propname, scratch_pool));
case 3:
return svn_error_quick_wrap(svn_error_createf(
SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
_("'%s' is not a valid %s property name; "
"did you mean '%s' or '%s'?"),
propname, SVN_PROP_PREFIX,
(const char *)propkeys[0]->data, (const char *)propkeys[1]->data),
force_prop_option_message(prop_use, propname, scratch_pool));
default:
return svn_error_quick_wrap(svn_error_createf(
SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
_("'%s' is not a valid %s property name; "
"did you mean '%s', '%s' or '%s'?"),
propname, SVN_PROP_PREFIX,
(const char *)propkeys[0]->data,
(const char *)propkeys[1]->data, (const char *)propkeys[2]->data),
force_prop_option_message(prop_use, propname, scratch_pool));
}
}