You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by kf...@collab.net on 2001/10/11 17:03:41 UTC

Re: svn commit: rev 221 - trunk trunk/subversion/libsvn_subr

brane@tigris.org writes:
> Modified:
>    trunk/configure.in
>    trunk/subversion/libsvn_subr/path.c
>    trunk/svn_private_config.hw
> Log:
> Add support for / as a path separator on Windows, and avoid creating
> paths that end in a "/.". This fixes issue #489.
> 
> Incidentally, this also adds infrastructure for describing the
> properties of path styles.

Thanks, Branko!  Nice to see our path problems getting under control
finally. :-)

-K



> * configure.in: Define SVN_PATH_ALTERNATE_SEPARATOR and
> SVN_PATH_STRIP_TRAILING_SLASHDOT.
> 
> * svn_private_config.hw: Likewise.
> 
> * subversion/libsvn_subr/path.c (path_style_context_t): New struct,
> describes the properties of a path style.
> 
> (get_path_style_context): Replacee get_separator_from_style. Returns a
> pointer to a path_style_context_t instead of a char.
> 
> (char_is_dirsep): New function.
> 
> (svn_path_canonicalize): Convert alternate separators to regular.
> 
> (add_component_internal): Don't add a '.' if the path style disallows
> trailing dots.
> 
> (svn_path_remove_component): Use separator char from style context.
> (svn_path_last_component): Check for both kinds of separators.
> (svn_path_is_thisdir, svn_path_compare_paths,
> svn_path_get_longest_ancestor, svn_path_is_child,
> svn_path_decompose, svn_path_is_single_path_component): Likewise.
> 
> (store_component): Make parameter `bytes' const.
> 
> 
> Modified: trunk/subversion/libsvn_subr/path.c
> ==============================================================================
> --- OLD/trunk/subversion/libsvn_subr/path.c	Wed Oct 10 13:17:58 2001
> +++ NEW/trunk/subversion/libsvn_subr/path.c	Wed Oct 10 13:17:58 2001
> @@ -45,34 +45,79 @@
>  #define SVN_PATH_URL_SEPARATOR   '/' /* url separators */
>  
>  
> -static char
> -get_separator_from_style (enum svn_path_style style)
> +typedef struct path_style_context_t
>  {
> +  /* The path separator used by this style. */
> +  char dirsep;
> +
> +  /* An alternate separator which is accepted, but converted to the
> +     primary separator. Should be 0 if unused. */
> +  char alt_dirsep;
> +
> +  /* Whether the trailing "/." in a path should be stripped. This is
> +     necessary, e.g., on Win32, where some API functions barf if the
> +     "/." is present. */
> +  svn_boolean_t strip_slashdot;
> +} path_style_context_t;
> +
> +
> +static const path_style_context_t *
> +get_path_style_context (enum svn_path_style style)
> +{
> +  static const path_style_context_t local_style = {
> +    SVN_PATH_LOCAL_SEPARATOR,
> +    SVN_PATH_ALTERNATE_SEPARATOR,
> +    SVN_PATH_STRIP_TRAILING_SLASHDOT
> +  };
> +
> +  /* FIXME: Should we strip trailing /.'s in repos and url paths? */
> +  static const path_style_context_t repos_style = {
> +    SVN_PATH_REPOS_SEPARATOR,
> +    0,                          /* alt_dirsep */
> +    0                           /* strip_slashdot */
> +  };
> +  static const path_style_context_t url_style = {
> +    SVN_PATH_URL_SEPARATOR,
> +    0,                          /* alt_dirsep */
> +    0                           /* strip_slashdot */
> +  };
> +
>    switch (style)
>      {
>      case svn_path_local_style:
> -      /* local style - path separators used by local filesystem */
> -      return SVN_PATH_LOCAL_SEPARATOR;
> +      /* local style - used by local filesystem */
> +      return &local_style;
>  
>      case svn_path_url_style:
> -      /* url style - path separators used in urls */
> -      return SVN_PATH_URL_SEPARATOR;
> +      /* url style - used in urls */
> +      return &url_style;
>  
> -    default:
>      case svn_path_repos_style:
> -      /* repos style - separators used in repository paths */
> -      return SVN_PATH_REPOS_SEPARATOR;
> +      /* repos style - used in repository paths */
> +      return &repos_style;
> +
> +    default:
> +      /* default case - error (we should never hit this...) */
> +      assert (!"Our paths are too stylish.");
> +      return NULL;
>      }
> -  /* default case = repos style (we should never hit this...) */
> -  return SVN_PATH_REPOS_SEPARATOR;
>  }
>   
>  
> +/* Check if CH is a directory separator in CTX */
> +static APR_INLINE int
> +char_is_dirsep (char ch, const path_style_context_t *ctx)
> +{
> +  return (ch == ctx->dirsep
> +          || (ctx->alt_dirsep && ch == ctx->alt_dirsep));
> +}
> +
> +
>  
>  void
>  svn_path_canonicalize (svn_stringbuf_t *path, enum svn_path_style style)
>  {
> -  char dirsep = get_separator_from_style (style);
> +  const path_style_context_t *ctx = get_path_style_context (style);
>  
>    /* At some point this could eliminiate redundant components.
>       For now, it just makes sure there is no trailing slash. */
> @@ -80,8 +125,19 @@
>    /* kff todo: maybe should be implemented with a new routine in
>       libsvn_string. */
>  
> +  /* Convert alternate separators in the path to primary separators. */
> +  if (ctx->alt_dirsep)
> +    {
> +      char *p;
> +      for (p = path->data; *p != '\0'; ++p)
> +        if (*p == ctx->alt_dirsep)
> +          *p = ctx->dirsep;
> +    }
> +
> +  /* FIXME: Should also remove trailing /.'s, if the style says so. */
> +  /* Remove trailing separators from the end of the path. */
>    while ((path->len > 0)
> -         && (path->data[(path->len - 1)] == dirsep))
> +         && path->data[(path->len - 1)] == ctx->dirsep)
>      {
>        path->data[(path->len - 1)] = '\0';
>        path->len--;
> @@ -95,10 +151,15 @@
>                          size_t len,
>                          enum svn_path_style style)
>  {
> -  char dirsep = get_separator_from_style (style);
> +  const path_style_context_t *ctx = get_path_style_context (style);
> +
> +  /* Check if we're trying to add a trailing "." */
> +  if (ctx->strip_slashdot
> +      && len == 1 && component[0] == '.')
> +    return;
>  
>    if (! svn_stringbuf_isempty (path))
> -    svn_stringbuf_appendbytes (path, &dirsep, sizeof (dirsep));
> +    svn_stringbuf_appendbytes (path, &ctx->dirsep, sizeof (ctx->dirsep));
>  
>    svn_stringbuf_appendbytes (path, component, len);
>    svn_path_canonicalize (path, style);
> @@ -126,15 +187,15 @@
>  void
>  svn_path_remove_component (svn_stringbuf_t *path, enum svn_path_style style)
>  {
> -  char dirsep = get_separator_from_style (style);
> +  const path_style_context_t *ctx = get_path_style_context (style);
>  
>    svn_path_canonicalize (path, style);
>  
> -  if (! svn_stringbuf_chop_back_to_char (path, dirsep))
> +  if (! svn_stringbuf_chop_back_to_char (path, ctx->dirsep))
>      svn_stringbuf_setempty (path);
>    else
>      {
> -      if (path->data[path->len - 1] == dirsep)
> +      if (path->data[path->len - 1] == ctx->dirsep)
>            path->data[--path->len] = '\0';
>      }
>  }
> @@ -145,10 +206,17 @@
>                           enum svn_path_style style,
>                           apr_pool_t *pool)
>  {
> -  char dirsep = get_separator_from_style (style);
> +  const path_style_context_t *ctx = get_path_style_context (style);
> +  apr_size_t i = svn_stringbuf_find_char_backward (path, ctx->dirsep);
>  
> -  apr_size_t i
> -    = svn_stringbuf_find_char_backward (path, dirsep);
> +  if (ctx->alt_dirsep)
> +    {
> +      /* Must check if we skipped an alternate separator. */
> +      apr_size_t alt_i =
> +        svn_stringbuf_find_char_backward (path, ctx->alt_dirsep);
> +      if (i < alt_i && alt_i < path->len)
> +        i = alt_i;
> +    }
>  
>    if (i < path->len)
>      {
> @@ -192,12 +260,13 @@
>  int
>  svn_path_is_thisdir (const svn_stringbuf_t *path, enum svn_path_style style)
>  {
> -  char dirsep = get_separator_from_style (style);
> +  const path_style_context_t *ctx = get_path_style_context (style);
>  
>    if ((path->len == 1) && (path->data[0] == '.'))
>      return 1;
>  
> -  if ((path->len == 2) && (path->data[0] == '.') && (path->data[1] == dirsep))
> +  if ((path->len == 2) && (path->data[0] == '.')
> +      && char_is_dirsep (path->data[1], ctx))
>      return 1;
>  
>    return 0;
> @@ -218,19 +287,22 @@
>                          const svn_stringbuf_t *path2,
>                          enum svn_path_style style)
>  {
> -  size_t min_len = ((path1->len) < (path2->len)) ? path1->len : path2->len;
> -  size_t i;
> -  char dirsep = get_separator_from_style (style);
> +  const path_style_context_t *ctx = get_path_style_context (style);
> +  apr_size_t min_len = ((path1->len < path2->len) ? path1->len : path2->len);
> +  apr_size_t i = 0;
>    
>    /* Skip past common prefix. */
> -  for (i = 0; (i < min_len) && (path1->data[i] == path2->data[i]); i++)
> -    ;
> +  while (i < min_len
> +         && (path1->data[i] == path2->data[i]
> +             || (char_is_dirsep (path1->data[i], ctx)
> +                 && char_is_dirsep (path2->data[i], ctx))))
> +    ++i;
>  
>    if ((path1->len == path2->len) && (i >= min_len))
>      return 0;     /* the paths are the same */
> -  if (path1->data[i] == dirsep)
> +  if (char_is_dirsep (path1->data[i], ctx))
>      return 1;     /* path1 child of path2, parent always comes before child */
> -  if (path2->data[i] == dirsep)
> +  if (char_is_dirsep (path2->data[i], ctx))
>      return -1;    /* path2 child of path1, parent always comes before child */
>  
>    /* Common prefix was skipped above, next character is compared to
> @@ -246,8 +318,8 @@
>                                 enum svn_path_style style,
>                                 apr_pool_t *pool)
>  {
> +  const path_style_context_t *ctx = get_path_style_context (style);
>    svn_stringbuf_t *common_path;
> -  char dirsep = get_separator_from_style (style);
>    apr_size_t i = 0;
>    apr_size_t last_dirsep = 0;
>  
> @@ -257,10 +329,12 @@
>        || (svn_stringbuf_isempty (path1)) || (svn_stringbuf_isempty (path2)))
>      return NULL;
>    
> -  while (path1->data[i] == path2->data[i])
> +  while (path1->data[i] == path2->data[i]
> +         || (char_is_dirsep (path1->data[i], ctx)
> +             && char_is_dirsep (path2->data[i], ctx)))
>      {
>        /* Keep track of the last directory separator we hit. */
> -      if (path1->data[i] == dirsep)
> +      if (char_is_dirsep (path1->data[i], ctx))
>          last_dirsep = i;
>  
>        i++;
> @@ -273,8 +347,8 @@
>    /* last_dirsep is now the offset of the last directory separator we
>       crossed before reaching a non-matching byte.  i is the offset of
>       that non-matching byte. */
> -  if (((i == path1->len) && (path2->data[i] == dirsep)) 
> -      || ((i == path2->len) && (path1->data[i] == dirsep))
> +  if (((i == path1->len) && char_is_dirsep (path2->data[i], ctx))
> +      || ((i == path2->len) && char_is_dirsep (path1->data[i], ctx))
>        || ((i == path1->len) && (i == path2->len)))
>      common_path = svn_stringbuf_ncreate (path1->data, i, pool);
>    else
> @@ -297,7 +371,7 @@
>                     enum svn_path_style style,
>                     apr_pool_t *pool)
>  {
> -  char dirsep = get_separator_from_style (style);
> +  const path_style_context_t *ctx = get_path_style_context (style);
>    apr_size_t i = 0;
>        
>    /* If either path is empty, return NULL. */
> @@ -313,7 +387,9 @@
>       NULL. */
>    while (i < path1->len)
>      {
> -      if (path1->data[i] != path2->data[i])
> +      if (path1->data[i] != path2->data[i]
> +          && !char_is_dirsep (path1->data[i], ctx)
> +          && !char_is_dirsep (path2->data[i], ctx))
>          return NULL;
>  
>        i++;
> @@ -325,11 +401,11 @@
>       more pathy stuff, then path2 is a child of path1. */
>    if (i == path1->len)
>      {
> -      if (path1->data[i - 1] == dirsep)
> +      if (char_is_dirsep (path1->data[i - 1], ctx))
>          return svn_stringbuf_ncreate (path2->data + i, 
>                                     path2->len - i, 
>                                     pool);
> -      else if (path2->data[i] == dirsep)
> +      else if (char_is_dirsep (path2->data[i], ctx))
>          return svn_stringbuf_ncreate (path2->data + i + 1,
>                                     path2->len - i - 1,
>                                     pool);
> @@ -342,7 +418,7 @@
>  /* helper for svn_path_decompose, because apr arrays are so darn ugly. */
>  static void
>  store_component (apr_array_header_t *array,
> -                 char *bytes,
> +                 const char *bytes,
>                   apr_size_t len,
>                   apr_pool_t *pool)
>  {
> @@ -360,28 +436,28 @@
>                      enum svn_path_style style,
>                      apr_pool_t *pool)
>  {
> +  const path_style_context_t *ctx = get_path_style_context (style);
>    apr_size_t i, oldi;
>  
>    apr_array_header_t *components = 
>      apr_array_make (pool, 1, sizeof(svn_stringbuf_t *));
>  
> -  char dirsep = get_separator_from_style (style);
>    i = oldi = 0;
>  
>    if (svn_path_is_empty (path, style))
>      return components;
>  
>    /* If PATH is absolute, store the '/' as the first component. */
> -  if (path->data[i] == dirsep)
> +  if (char_is_dirsep (path->data[i], ctx))
>      {
> -      store_component (components, path->data + i, 1, pool);
> +      store_component (components, &ctx->dirsep, 1, pool);
>        i++;
>        oldi++;
>      }
>  
>    while (i <= path->len)
>      {
> -      if ((path->data[i] == dirsep) || (path->data[i] == '\0'))
> +      if (char_is_dirsep (path->data[i], ctx) || (path->data[i] == '\0'))
>          {
>            store_component (components, path->data + oldi, i - oldi, pool);
>            i++;
> @@ -399,7 +475,7 @@
>  svn_path_is_single_path_component (svn_stringbuf_t *path,
>                                     enum svn_path_style style)
>  {
> -  char dirsep = get_separator_from_style (style);
> +  const path_style_context_t *ctx = get_path_style_context (style);
>  
>    /* Can't be NULL */
>    if (! path)
> @@ -416,7 +492,9 @@
>      return 0;
>  
>    /* slashes are bad, m'kay... */
> -  if (strchr(path->data, dirsep) != NULL)
> +  if (strchr (path->data, ctx->dirsep) != NULL
> +      || (ctx->alt_dirsep
> +          && strchr (path->data, ctx->alt_dirsep) != NULL))
>      return 0;
>  
>    /* it is valid */
> @@ -431,5 +509,3 @@
>   * eval: (load-file "../svn-dev.el")
>   * end:
>   */
> -
> -
> 
> Modified: trunk/svn_private_config.hw
> ==============================================================================
> --- OLD/trunk/svn_private_config.hw	Wed Oct 10 13:17:58 2001
> +++ NEW/trunk/svn_private_config.hw	Wed Oct 10 13:17:58 2001
> @@ -1,5 +1,5 @@
>  /*
> - * config.hw : Template used to generate config.h on Win32.
> + * svn_private_config.hw : Template for svn_private_config.h on Win32.
>   *
>   * ====================================================================
>   * Copyright (c) 2000-2001 CollabNet.  All rights reserved.
> @@ -55,9 +55,11 @@
>  #endif
>  
>  /* Path separator for local filesystem */
> -#ifndef SVN_PATH_LOCAL_SEPARATOR
> -#  define SVN_PATH_LOCAL_SEPARATOR '\\'
> -#endif
> +#define SVN_PATH_LOCAL_SEPARATOR '\\'
> +#define SVN_PATH_ALTERNATE_SEPARATOR '/'
> +
> +/* Whether the trailing /. in local paths should be stripped */
> +#define SVN_PATH_STRIP_TRAILING_SLASHDOT 1
>  
>  /* Link local repos access library to client */
>  #define SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL
> 
> Modified: trunk/configure.in
> ==============================================================================
> --- OLD/trunk/configure.in	Wed Oct 10 13:17:58 2001
> +++ NEW/trunk/configure.in	Wed Oct 10 13:17:58 2001
> @@ -275,6 +275,10 @@
>  dnl Since this is used only on Unix-y systems, define the path separator as '/'
>  AC_DEFINE_UNQUOTED(SVN_PATH_LOCAL_SEPARATOR, '/',
>          [Defined to be the path separator used on your local filesystem])
> +AC_DEFINE_UNQUOTED(SVN_PATH_ALTERNATE_SEPARATOR, 0,
> +        [Defined to be the alternate path separator accepted by Subversion])
> +AC_DEFINE_UNQUOTED(SVN_PATH_STRIP_TRAILING_SLASHDOT, 0,
> +        [Non-zero if the trailing /. in paths should be stripped])
>  
>  dnl Find a python binary, refer
>  
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: svn-unsubscribe@subversion.tigris.org
> For additional commands, e-mail: svn-help@subversion.tigris.org

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org