Hi Julian,

julianf...@apache.org wrote on Fri, Nov 26, 2010 at 14:58:17 -0000:
> Author: julianfoad
> Date: Fri Nov 26 14:58:17 2010
> New Revision: 1039398
> 
> URL: http://svn.apache.org/viewvc?rev=1039398&view=rev
> Log:
> Add some more svn_fspath__* APIs, with tests for some of them.  These tests
> pass both with and without FSPATH_USE_URI defined.
> 
> * subversion/include/svn_dirent_uri.h,
>   subversion/libsvn_subr/dirent_uri.c
>   (svn_fspath__dirname, svn_fspath__split, svn_fspath__skip_ancestor,
>    svn_fspath__is_ancestor, svn_fspath__get_longest_ancestor): New functions.
> 
> * subversion/libsvn_delta/path_driver.c
>   (svn_fspath__get_longest_ancestor): Remove this temporary macro.
> 
> * subversion/tests/libsvn_subr/dirent_uri-test.c
>   (test_fspath_basename): Rename and extend to become ...
>   (test_fspath_dirname_basename_split): ... this new test.
>   (test_fspath_get_longest_ancestor): New tests.
>   (test_funcs): Add the new tests.
> ### TODO: Tests.
> 

What is that ### comment?  Is it the mailer saying you should have added
a few more tests to this commit?

Daniel

> Modified:
>     subversion/trunk/subversion/include/svn_dirent_uri.h
>     subversion/trunk/subversion/libsvn_delta/path_driver.c
>     subversion/trunk/subversion/libsvn_subr/dirent_uri.c
>     subversion/trunk/subversion/tests/libsvn_subr/dirent_uri-test.c
> 
> Modified: subversion/trunk/subversion/include/svn_dirent_uri.h
> URL: 
> http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_dirent_uri.h?rev=1039398&r1=1039397&r2=1039398&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/include/svn_dirent_uri.h (original)
> +++ subversion/trunk/subversion/include/svn_dirent_uri.h Fri Nov 26 14:58:17 
> 2010
> @@ -812,12 +812,12 @@ svn_uri_get_file_url_from_dirent(const c
>                                   apr_pool_t *pool);
>  
>  
> -/**
> +/**************************************************************************
>   * A private API for Subversion filesystem paths, otherwise known as paths
>   * within a repository, that start with a '/'.  The rules for a fspath are
>   * the same as for a relpath except for the leading '/'.  A fspath never
>   * ends with '/' except when the whole path is just '/'.
> - */
> + **************************************************************************/
>  
>  /** Return TRUE iff @a fspath is canonical.
>   * @a fspath need not be canonical, of course.
> @@ -827,6 +827,49 @@ svn_uri_get_file_url_from_dirent(const c
>  svn_boolean_t
>  svn_fspath__is_canonical(const char *fspath);
>  
> +
> +/** Return the dirname of @a fspath, defined as the path with its basename
> + * removed.  If @a fspath is "/", return "/".
> + *
> + * Allocate the result in @a pool.
> + *
> + * @since New in 1.7.
> + */
> +const char *
> +svn_fspath__dirname(const char *fspath,
> +                    apr_pool_t *pool);
> +
> +/** Return the last component of @a fspath.  The returned value will have no
> + * slashes in it.  If @a fspath is "/", return "".
> + *
> + * If @a pool is NULL, return a pointer to within @a fspath, else allocate
> + * the result in @a pool.
> + *
> + * @since New in 1.7.
> + */
> +const char *
> +svn_fspath__basename(const char *fspath,
> +                     apr_pool_t *pool);
> +
> +/** Divide the canonical @a fspath into @a *dirpath and @a
> + * *base_name, allocated in @a pool.
> + *
> + * If @a dirpath or @a base_name is NULL, then don't set that one.
> + *
> + * Either @a dirpath or @a base_name may be @a fspath's own address, but they
> + * may not both be the same address, or the results are undefined.
> + *
> + * If @a fspath has two or more components, the separator between @a dirpath
> + * and @a base_name is not included in either of the new names.
> + *
> + * @since New in 1.7.
> + */
> +void
> +svn_fspath__split(const char **dirpath,
> +                  const char **base_name,
> +                  const char *fspath,
> +                  apr_pool_t *result_pool);
> +
>  /** Return the fspath composed of @a fspath with @a relpath appended.
>   * Allocate the result in @a result_pool.
>   *
> @@ -855,16 +898,37 @@ svn_fspath__is_child(const char *parent_
>                       const char *child_fspath,
>                       apr_pool_t *pool);
>  
> -
> -/** Return the last component of @a fspath.  The returned value will have no
> - * slashes in it.  If @a pool is NULL, return a pointer to within @a fspath,
> - * else allocate the result in @a pool.
> +/** Return the relative path part of @a child_fspath that is below
> + * @a parent_fspath, or just "" if @a parent_fspath is equal to
> + * @a child_fspath. If @a child_fspath is not below @a parent_relpath,
> + * return @a child_fspath.
> + *
> + * ### Returning the child in the no-match case is a bad idea.
>   *
>   * @since New in 1.7.
>   */
>  const char *
> -svn_fspath__basename(const char *fspath,
> -                     apr_pool_t *pool);
> +svn_fspath__skip_ancestor(const char *parent_fspath,
> +                          const char *child_fspath);
> +
> +/** Return TRUE if @a parent_fspath is an ancestor of @a child_fspath or
> + * the fspaths are equal, and FALSE otherwise.
> + *
> + * @since New in 1.7.
> + */
> +svn_boolean_t
> +svn_fspath__is_ancestor(const char *parent_fspath,
> +                        const char *child_fspath);
> +
> +/** Return the longest common path shared by two fspaths, @a fspath1 and
> + * @a fspath2.  If there's no common ancestor, return "/".
> + *
> + * @since New in 1.7.
> + */
> +char *
> +svn_fspath__get_longest_ancestor(const char *fspath1,
> +                                 const char *fspath2,
> +                                 apr_pool_t *result_pool);
>  
>  
>  #ifdef __cplusplus
> 
> Modified: subversion/trunk/subversion/libsvn_delta/path_driver.c
> URL: 
> http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_delta/path_driver.c?rev=1039398&r1=1039397&r2=1039398&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_delta/path_driver.c (original)
> +++ subversion/trunk/subversion/libsvn_delta/path_driver.c Fri Nov 26 
> 14:58:17 2010
> @@ -129,14 +129,6 @@ count_components(const char *path)
>  
>  
>  /*** Public interfaces ***/
> -
> -/* ### Temporary definition, until this is available in dirent_uri.h */
> -#define svn_fspath__get_longest_ancestor(path1, path2, pool) \
> -  apr_pstrcat((pool), \
> -              "/", \
> -              svn_relpath_get_longest_ancestor((path1)+1, (path2)+1, 
> (pool)), \
> -              NULL)
> -
>  svn_error_t *
>  svn_delta_path_driver(const svn_delta_editor_t *editor,
>                        void *edit_baton,
> @@ -225,7 +217,7 @@ svn_delta_path_driver(const svn_delta_ed
>        /*** Step C - Open any directories between the common ancestor
>             and the parent of the current path. ***/
>        if (*path == '/')
> -        svn_uri_split(&pdir, &bname, path, iterpool);
> +        svn_fspath__split(&pdir, &bname, path, iterpool);
>        else
>          svn_relpath_split(&pdir, &bname, path, iterpool);
>        if (strlen(pdir) > common_len)
> 
> Modified: subversion/trunk/subversion/libsvn_subr/dirent_uri.c
> URL: 
> http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/dirent_uri.c?rev=1039398&r1=1039397&r2=1039398&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_subr/dirent_uri.c (original)
> +++ subversion/trunk/subversion/libsvn_subr/dirent_uri.c Fri Nov 26 14:58:17 
> 2010
> @@ -2475,47 +2475,78 @@ svn_fspath__is_canonical(const char *fsp
>    return fspath[0] == '/' && relpath_is_canonical(fspath + 1);
>  }
>  
> -char *
> -svn_fspath__join(const char *fspath,
> -                 const char *relpath,
> -                 apr_pool_t *result_pool)
> +
> +const char *
> +svn_fspath__is_child(const char *parent_fspath,
> +                     const char *child_fspath,
> +                     apr_pool_t *pool)
>  {
> -  char *result;
> -  assert(svn_fspath__is_canonical(fspath));
> -  assert(relpath_is_canonical(relpath));
> +  const char *result;
> +  assert(svn_fspath__is_canonical(parent_fspath));
> +  assert(svn_fspath__is_canonical(child_fspath));
>  
>  #ifdef FSPATH_USE_URI
> -  result = svn_uri_join(fspath, relpath, result_pool);
> +  result = svn_uri_is_child(parent_fspath, child_fspath, pool);
>  #else
> -  if (relpath[0] == '\0')
> -    result = apr_pstrdup(result_pool, fspath);
> -  else if (fspath[1] == '\0')
> -    result = apr_pstrcat(result_pool, "/", relpath, (char *)NULL);
> -  else
> -    result = apr_pstrcat(result_pool, fspath, "/", relpath, (char *)NULL);
> +  result = svn_relpath_is_child(parent_fspath + 1, child_fspath + 1, pool);
>  #endif
>  
> -  assert(svn_fspath__is_canonical(result));
> +  assert(result == NULL || svn_relpath_is_canonical(result, pool));
>    return result;
>  }
>  
> -
>  const char *
> -svn_fspath__is_child(const char *parent_fspath,
> -                     const char *child_fspath,
> -                     apr_pool_t *pool)
> +svn_fspath__skip_ancestor(const char *parent_fspath,
> +                          const char *child_fspath)
>  {
>    const char *result;
>    assert(svn_fspath__is_canonical(parent_fspath));
>    assert(svn_fspath__is_canonical(child_fspath));
>  
>  #ifdef FSPATH_USE_URI
> -  result = svn_uri_is_child(parent_fspath, child_fspath, pool);
> +  result = svn_uri_skip_ancestor(parent_fspath, child_fspath);
>  #else
> -  result = svn_relpath_is_child(parent_fspath + 1, child_fspath + 1, pool);
> +  if (svn_relpath_is_ancestor(parent_fspath + 1, child_fspath + 1))
> +    result = svn_relpath_skip_ancestor(parent_fspath + 1, child_fspath + 1);
> +  else
> +    result = child_fspath;
> +#endif
> +
> +  assert(svn_relpath_is_canonical(result, NULL)
> +         || strcmp(result, child_fspath) == 0);
> +  return result;
> +}
> +
> +svn_boolean_t
> +svn_fspath__is_ancestor(const char *parent_fspath,
> +                        const char *child_fspath)
> +{
> +  assert(svn_fspath__is_canonical(parent_fspath));
> +  assert(svn_fspath__is_canonical(child_fspath));
> +
> +#ifdef FSPATH_USE_URI
> +  return svn_uri_is_ancestor(parent_fspath, child_fspath);
> +#else
> +  return svn_relpath_is_ancestor(parent_fspath + 1, child_fspath + 1);
> +#endif
> +}
> +
> +
> +const char *
> +svn_fspath__dirname(const char *fspath,
> +                    apr_pool_t *pool)
> +{
> +  const char *result;
> +  assert(svn_fspath__is_canonical(fspath));
> +
> +#ifdef FSPATH_USE_URI
> +  result = svn_uri_dirname(fspath, pool);
> +#else
> +  result = apr_pstrcat(pool, "/", svn_relpath_dirname(fspath + 1, pool),
> +                       (char *)NULL);
>  #endif
>  
> -  assert(result == NULL || relpath_is_canonical(result));
> +  assert(svn_fspath__is_canonical(result));
>    return result;
>  }
>  
> @@ -2537,4 +2568,64 @@ svn_fspath__basename(const char *fspath,
>    return result;
>  }
>  
> +void
> +svn_fspath__split(const char **dirpath,
> +                  const char **base_name,
> +                  const char *fspath,
> +                  apr_pool_t *result_pool)
> +{
> +  assert(dirpath != base_name);
> +
> +  if (dirpath)
> +    *dirpath = svn_fspath__dirname(fspath, result_pool);
> +
> +  if (base_name)
> +    *base_name = svn_fspath__basename(fspath, result_pool);
> +}
> +
> +char *
> +svn_fspath__join(const char *fspath,
> +                 const char *relpath,
> +                 apr_pool_t *result_pool)
> +{
> +  char *result;
> +  assert(svn_fspath__is_canonical(fspath));
> +  assert(svn_relpath_is_canonical(relpath, result_pool));
> +
> +#ifdef FSPATH_USE_URI
> +  result = svn_uri_join(fspath, relpath, result_pool);
> +#else
> +  if (relpath[0] == '\0')
> +    result = apr_pstrdup(result_pool, fspath);
> +  else if (fspath[1] == '\0')
> +    result = apr_pstrcat(result_pool, "/", relpath, (char *)NULL);
> +  else
> +    result = apr_pstrcat(result_pool, fspath, "/", relpath, (char *)NULL);
> +#endif
> +
> +  assert(svn_fspath__is_canonical(result));
> +  return result;
> +}
> +
> +char *
> +svn_fspath__get_longest_ancestor(const char *fspath1,
> +                                 const char *fspath2,
> +                                 apr_pool_t *result_pool)
> +{
> +  char *result;
> +  assert(svn_fspath__is_canonical(fspath1));
> +  assert(svn_fspath__is_canonical(fspath2));
>  
> +#ifdef FSPATH_USE_URI
> +  result = svn_uri_get_longest_ancestor(fspath1, fspath2, result_pool);
> +#else
> +  result = apr_pstrcat(result_pool, "/",
> +                       svn_relpath_get_longest_ancestor(fspath1 + 1,
> +                                                        fspath2 + 1,
> +                                                        result_pool),
> +                       NULL);
> +#endif
> +
> +  assert(svn_fspath__is_canonical(result));
> +  return result;
> +}
> 
> Modified: subversion/trunk/subversion/tests/libsvn_subr/dirent_uri-test.c
> URL: 
> http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/dirent_uri-test.c?rev=1039398&r1=1039397&r2=1039398&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/tests/libsvn_subr/dirent_uri-test.c (original)
> +++ subversion/trunk/subversion/tests/libsvn_subr/dirent_uri-test.c Fri Nov 
> 26 14:58:17 2010
> @@ -2961,30 +2961,95 @@ test_fspath_is_child(apr_pool_t *pool)
>  }
>  
>  static svn_error_t *
> -test_fspath_basename(apr_pool_t *pool)
> +test_fspath_dirname_basename_split(apr_pool_t *pool)
>  {
>    int i;
>  
> -  struct {
> +  static const struct {
>      const char *path;
> -    const char *result;
> +    const char *dirname;
> +    const char *basename;
>    } tests[] = {
> -    { "/", "" },
> -    { "/a", "a" },
> -    { "/abc", "abc" },
> -    { "/x/abc", "abc" },
> +    { "/", "/", "" },
> +    { "/a", "/", "a" },
> +    { "/abc", "/", "abc" },
> +    { "/x/abc", "/x", "abc" },
> +    { "/x/y/abc", "/x/y", "abc" },
>    };
>  
>    for (i = 0; i < COUNT_OF(tests); i++)
>      {
> -      const char *result = svn_fspath__basename(tests[i].path, pool);
> +      const char *result_dirname, *result_basename;
> +
> +      result_dirname = svn_fspath__dirname(tests[i].path, pool);
> +      SVN_TEST_STRING_ASSERT(result_dirname, tests[i].dirname);
>  
> -      SVN_TEST_STRING_ASSERT(result, tests[i].result);
> +      result_basename = svn_fspath__basename(tests[i].path, pool);
> +      SVN_TEST_STRING_ASSERT(result_basename, tests[i].basename);
> +
> +      svn_fspath__split(&result_dirname, &result_basename, tests[i].path,
> +                        pool);
> +      SVN_TEST_STRING_ASSERT(result_dirname, tests[i].dirname);
> +      SVN_TEST_STRING_ASSERT(result_basename, tests[i].basename);
>      }
>  
>    return SVN_NO_ERROR;
>  }
>  
> +static svn_error_t *
> +test_fspath_get_longest_ancestor(apr_pool_t *pool)
> +{
> +  int i;
> +
> +  /* Paths to test and their expected results.  Same as in
> +   * test_relpath_get_longest_ancestor() but with '/' prefix. */
> +  struct {
> +    const char *path1;
> +    const char *path2;
> +    const char *result;
> +  } tests[] = {
> +    { "/foo",            "/foo/bar",         "/foo" },
> +    { "/foo/bar",        "/foo/bar",         "/foo/bar" },
> +    { "/",               "/foo",             "/" },
> +    { "/",               "/foo",             "/" },
> +    { "/",               "/.bar",            "/" },
> +    { "/.bar",           "/",                "/" },
> +    { "/foo/bar",        "/foo",             "/foo" },
> +    { "/foo/bar",        "/foo",             "/foo" },
> +    { "/rif",            "/raf",             "/" },
> +    { "/foo",            "/bar",             "/" },
> +    { "/foo",            "/foo/bar",         "/foo" },
> +    { "/foo.",           "/foo./.bar",       "/foo." },
> +    { "/",               "/",                "/" },
> +    { "/http:/test",     "/http:/test",      "/http:/test" },
> +    { "/http:/test",     "/http:/taste",     "/http:" },
> +    { "/http:/test",     "/http:/test/foo",  "/http:/test" },
> +    { "/http:/test",     "/file:/test/foo",  "/" },
> +    { "/http:/test",     "/http:/testF",     "/http:" },
> +    { "/file:/A/C",      "/file:/B/D",       "/file:" },
> +    { "/file:/A/C",      "/file:/A/D",       "/file:/A" },
> +    { "/X:/foo",         "/X:",              "/X:" },
> +    { "/X:/folder1",     "/X:/folder2",      "/X:" },
> +    { "/X:",             "/X:foo",           "/" },
> +    { "/X:foo",          "/X:bar",           "/" },
> +  };
> +
> +  for (i = 0; i < COUNT_OF(tests); i++)
> +    {
> +      const char *result;
> +
> +      result = svn_fspath__get_longest_ancestor(tests[i].path1, 
> tests[i].path2,
> +                                                pool);
> +      SVN_TEST_STRING_ASSERT(tests[i].result, result);
> +
> +      /* changing the order of the paths should return the same result */
> +      result = svn_fspath__get_longest_ancestor(tests[i].path2, 
> tests[i].path1,
> +                                                pool);
> +      SVN_TEST_STRING_ASSERT(tests[i].result, result);
> +    }
> +  return SVN_NO_ERROR;
> +}
> +
>  
>  /* The test table.  */
>  
> @@ -3091,7 +3156,9 @@ struct svn_test_descriptor_t test_funcs[
>                     "test svn_fspath__join"),
>      SVN_TEST_PASS2(test_fspath_is_child,
>                     "test svn_fspath__is_child"),
> -    SVN_TEST_PASS2(test_fspath_basename,
> -                   "test svn_fspath__basename"),
> +    SVN_TEST_PASS2(test_fspath_dirname_basename_split,
> +                   "test svn_fspath__dirname/basename/split"),
> +    SVN_TEST_PASS2(test_fspath_get_longest_ancestor,
> +                   "test svn_fspath__get_longest_ancestor"),
>      SVN_TEST_NULL
>    };
> 
> 

Reply via email to