Author: cmpilato
Date: Tue Apr 6 15:48:58 2010
New Revision: 931190
URL: http://svn.apache.org/viewvc?rev=931190&view=rev
Log:
Rework svn_mergeinfo__remove_prefix_from_catalog() so that its output
is more consistent with Subversion path handling/passing semantics.
* subversion/include/private/svn_mergeinfo_private.h
(svn_mergeinfo__remove_prefix_from_catalog): Update docstring to
indicate new stricter (and more useful!) semantics.
* subversion/libsvn_subr/mergeinfo.c
(svn_mergeinfo__remove_prefix_from_catalog): Rename 'prefix' to
'prefix_path', and rework this function's logic to always return
paths relative to the prefix path. (That is, suitable for
path_join'ing back to that prefix path to get the originals.)
* subversion/tests/libsvn_subr/mergeinfo-test.c
(struct catalog_bits): New test data structure.
(remove_prefix_helper, test_remove_prefix_from_catalog): New functions.
(test_funcs): Add reference to test_remove_prefix_from_catalog().
Modified:
subversion/trunk/subversion/include/private/svn_mergeinfo_private.h
subversion/trunk/subversion/libsvn_subr/mergeinfo.c
subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c
Modified: subversion/trunk/subversion/include/private/svn_mergeinfo_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_mergeinfo_private.h?rev=931190&r1=931189&r2=931190&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_mergeinfo_private.h
(original)
+++ subversion/trunk/subversion/include/private/svn_mergeinfo_private.h Tue Apr
6 15:48:58 2010
@@ -85,17 +85,18 @@ svn_boolean_t
svn_mergeinfo__remove_empty_rangelists(svn_mergeinfo_t mergeinfo,
apr_pool_t *pool);
-/* Makes a shallow (ie, mergeinfos are not duped, or altered at all;
- keys share storage) copy of IN_CATALOG in *OUT_CATALOG. PREFIX is
- removed from the beginning of each key in the catalog; it is
- illegal for any key to not start with PREFIX. The new hash and
- temporary values are allocated in POOL. (This is useful for making
- the return value from svn_ra_get_mergeinfo relative to the session
- root, say.) */
+/* Make a shallow (ie, mergeinfos are not duped, or altered at all;
+ keys share storage) copy of IN_CATALOG in *OUT_CATALOG, removing
+ PREFIX_PATH (which is an absolute path) from the beginning of each
+ key in the catalog (each of which is also an absolute path). It is
+ illegal for any key to not start with PREFIX_PATH. The new hash
+ and temporary values are allocated in POOL. (This is useful for
+ making the return value from svn_ra_get_mergeinfo relative to the
+ session root, say.) */
svn_error_t *
svn_mergeinfo__remove_prefix_from_catalog(svn_mergeinfo_catalog_t *out_catalog,
svn_mergeinfo_catalog_t in_catalog,
- const char *prefix,
+ const char *prefix_path,
apr_pool_t *pool);
/* Makes a deep copy of MERGEINFO in *OUT_MERGEINFO. If SUFFIX_REL_PATH is
Modified: subversion/trunk/subversion/libsvn_subr/mergeinfo.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/mergeinfo.c?rev=931190&r1=931189&r2=931190&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_subr/mergeinfo.c Tue Apr 6 15:48:58 2010
@@ -1679,11 +1679,13 @@ svn_mergeinfo__remove_empty_rangelists(s
svn_error_t *
svn_mergeinfo__remove_prefix_from_catalog(svn_mergeinfo_catalog_t *out_catalog,
svn_mergeinfo_catalog_t in_catalog,
- const char *prefix,
+ const char *prefix_path,
apr_pool_t *pool)
{
apr_hash_index_t *hi;
- size_t prefix_len = strlen(prefix);
+ size_t prefix_len = strlen(prefix_path);
+
+ SVN_ERR_ASSERT(prefix_path[0] == '/');
*out_catalog = apr_hash_make(pool);
@@ -1692,12 +1694,21 @@ svn_mergeinfo__remove_prefix_from_catalo
const char *original_path = svn__apr_hash_index_key(hi);
apr_ssize_t klen = svn__apr_hash_index_klen(hi);
svn_mergeinfo_t value = svn__apr_hash_index_val(hi);
+ apr_ssize_t padding = 0;
SVN_ERR_ASSERT(klen >= prefix_len);
- SVN_ERR_ASSERT(strncmp(original_path, prefix, prefix_len) == 0);
+ SVN_ERR_ASSERT(svn_uri_is_ancestor(prefix_path, original_path));
+
+ /* If the ORIGINAL_PATH doesn't match the PREFIX_PATH exactly
+ and we're not simply removing a single leading slash (such as
+ when PREFIX_PATH is "/"), we advance our string offset by an
+ extra character (to get past the directory separator that
+ follows the prefix). */
+ if ((strcmp(original_path, prefix_path) != 0) && (prefix_len != 1))
+ padding = 1;
- apr_hash_set(*out_catalog, original_path + prefix_len,
- klen-prefix_len, value);
+ apr_hash_set(*out_catalog, original_path + prefix_len + padding,
+ klen - prefix_len - padding, value);
}
return SVN_NO_ERROR;
Modified: subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c?rev=931190&r1=931189&r2=931190&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/mergeinfo-test.c Tue Apr 6
15:48:58 2010
@@ -1559,6 +1559,99 @@ test_rangelist_diff(apr_pool_t *pool)
}
return err;
}
+
+
+/* Test data structure for test_remove_prefix_from_catalog(). */
+struct catalog_bits
+{
+ const char *orig_path;
+ const char *new_path;
+ const char *mergeinfo;
+};
+
+
+/* Helper for test_remove_prefix_from_catalog(). */
+static svn_error_t *
+remove_prefix_helper(struct catalog_bits *test_data,
+ const char *prefix_path,
+ apr_pool_t *pool)
+{
+ svn_mergeinfo_catalog_t in_catalog, out_catalog, exp_out_catalog;
+ apr_hash_index_t *hi;
+ int i = 0;
+
+ in_catalog = apr_hash_make(pool);
+ exp_out_catalog = apr_hash_make(pool);
+ while (test_data[i].orig_path)
+ {
+ struct catalog_bits data = test_data[i];
+ const char *orig_path = apr_pstrdup(pool, data.orig_path);
+ const char *new_path = apr_pstrdup(pool, data.new_path);
+ svn_mergeinfo_t mergeinfo;
+ SVN_ERR(svn_mergeinfo_parse(&mergeinfo, data.mergeinfo, pool));
+ apr_hash_set(in_catalog, orig_path, APR_HASH_KEY_STRING, mergeinfo);
+ apr_hash_set(exp_out_catalog, new_path, APR_HASH_KEY_STRING, mergeinfo);
+ i++;
+ }
+ SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(&out_catalog, in_catalog,
+ prefix_path, pool));
+ if (apr_hash_count(exp_out_catalog) != apr_hash_count(out_catalog))
+ return svn_error_create(SVN_ERR_TEST_FAILED, 0,
+ "Got unexpected number of catalog entries");
+ for (hi = apr_hash_first(pool, out_catalog); hi; hi = apr_hash_next(hi))
+ {
+ const void *path;
+ apr_ssize_t path_len;
+ void *out_mergeinfo, *exp_out_mergeinfo;
+ apr_hash_this(hi, &path, &path_len, &out_mergeinfo);
+ exp_out_mergeinfo = apr_hash_get(exp_out_catalog, path, path_len);
+ if (! exp_out_mergeinfo)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, 0,
+ "Found unexpected key '%s' in catalog",
+ (const char *)path);
+ if (exp_out_mergeinfo != out_mergeinfo)
+ return svn_error_create(SVN_ERR_TEST_FAILED, 0,
+ "Detected value tampering in catalog");
+ }
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_remove_prefix_from_catalog(apr_pool_t *pool)
+{
+ apr_pool_t *subpool = svn_pool_create(pool);
+
+ /* For testing the remove of the prefix "/trunk" */
+ struct catalog_bits test_data_1[] =
+ {
+ { "/trunk", "", "/A:1" },
+ { "/trunk/foo", "foo", "/A/foo:1,3*" },
+ { "/trunk/foo/bar", "foo/bar", "/A/foo:1-4" },
+ { "/trunk/baz", "baz", "/A/baz:2" },
+ { NULL, NULL, NULL }
+ };
+
+ /* For testing the remove of the prefix "/" */
+ struct catalog_bits test_data_2[] =
+ {
+ { "/", "", "/:2" },
+ { "/trunk", "trunk", "/A:1" },
+ { "/trunk/foo", "trunk/foo", "/A/foo:1,3*" },
+ { "/trunk/foo/bar", "trunk/foo/bar", "/A/foo:1-4" },
+ { "/trunk/baz", "trunk/baz", "/A/baz:2" },
+ { NULL, NULL, NULL }
+ };
+
+ svn_pool_clear(subpool);
+ SVN_ERR(remove_prefix_helper(test_data_1, "/trunk", subpool));
+
+ svn_pool_clear(subpool);
+ SVN_ERR(remove_prefix_helper(test_data_2, "/", subpool));
+
+ svn_pool_destroy(subpool);
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
@@ -1599,5 +1692,7 @@ struct svn_test_descriptor_t test_funcs[
"merge of rangelists"),
SVN_TEST_PASS2(test_rangelist_diff,
"diff of rangelists"),
+ SVN_TEST_PASS2(test_remove_prefix_from_catalog,
+ "removal of prefix paths from catalog keys"),
SVN_TEST_NULL
};