Пример #1
0
unsigned int
svn_cstring__similarity(const char *stra, const char *strb,
                        svn_membuf_t *buffer, apr_size_t *rlcs)
{
  svn_string_t stringa, stringb;
  stringa.data = stra;
  stringa.len = strlen(stra);
  stringb.data = strb;
  stringb.len = strlen(strb);
  return svn_string__similarity(&stringa, &stringb, buffer, rlcs);
}
Пример #2
0
/* Similarity test between two property names */
static APR_INLINE apr_size_t
simcheck_key_diff(const svn_string_t *key, const svn_string_t *ctx,
                 svn_membuf_t *buffer, apr_size_t *diff)
{
  apr_size_t lcs;
  const apr_size_t score = svn_string__similarity(key, ctx, buffer, &lcs);
  if (key->len > ctx->len)
    *diff = key->len - lcs;
  else
    *diff = ctx->len - lcs;
  return score;
}
Пример #3
0
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);

  /* First, check if the name is even close to being in the svn: namespace.
     It must contain a colon in the right place, and we only allow
     one-char typos or a single transposition. */
  if (propstring.len < prefix.len
      || propstring.data[prefix.len - 1] != prefix.data[prefix.len - 1])
    return SVN_NO_ERROR;        /* Wrong prefix, ignore */
  else
    {
      apr_size_t lcs;
      const apr_size_t name_len = propstring.len;
      propstring.len = prefix.len; /* Only check up to the prefix length */
      svn_string__similarity(&propstring, &prefix, &buffer, &lcs);
      propstring.len = name_len; /* Restore the original propname length */
      if (lcs < prefix.len - 1)
        return SVN_NO_ERROR;    /* Wrong prefix, ignore */

      /* If the prefix is slightly different, the rest must be
         identical in order to trigger the 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;
        }
    }

  /* Now find the closest match from amongst the set of reserved
     node or revision property names. Skip the prefix while matching,
     we already know that it's the same and looking at it would only
     skew the results. */
  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;      /* We found an exact match. */

    case 1:
      /* The best alternative isn't good enough */
      return svn_error_create(
        SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
        wrong_prop_error_message(prop_use, propname, scratch_pool));

    case 2:
      /* There is only one good candidate */
      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:
      /* Suggest a list of the most likely candidates */
      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:
      /* Never suggest more than three candidates */
      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));
    }
}