Author: dannas Date: Tue Jul 13 18:46:31 2010 New Revision: 963814 URL: http://svn.apache.org/viewvc?rev=963814&view=rev Log: Start recording what operation is perfomed on a property in a patch.
* subversion/include/svn_diff.h (svn_prop_patch_t): New. Should only deal with the property part of a patch. (svn_patch_t): Use an array of 'svn_prop_patch_t' instead of a hash table of hunks for representing parsed property content. * subversion/libsvn_diff/parse-diff.c (parse_next_hunk): Add 'prop_operation' parameter for recording if a property patch was deleted, added or modified. (add_property_hunk): New. svn_diff_parse_next_patch): Call add_property_hunk() if we have a property hunk. Use the new 'svn_prop_patch_t' type. * subversion/tests/libsvn_diff/parse-diff-test.c (test_parse_property_diff, test_parse_property_and_text_diff): Adjust the tests to use the new 'svn_prop_patch_t' type and loop over an array instead of fetching the properties from a hash table.. Modified: subversion/trunk/subversion/include/svn_diff.h subversion/trunk/subversion/libsvn_diff/parse-diff.c subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c Modified: subversion/trunk/subversion/include/svn_diff.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_diff.h?rev=963814&r1=963813&r2=963814&view=diff ============================================================================== --- subversion/trunk/subversion/include/svn_diff.h (original) +++ subversion/trunk/subversion/include/svn_diff.h Tue Jul 13 18:46:31 2010 @@ -933,6 +933,22 @@ svn_linenum_t svn_diff_hunk_get_trailing_context(const svn_hunk_t *hunk); /** + * Data type to manage parsing of properties in patches. + * + * @since New in 1.7. */ +typedef struct svn_prop_patch_t { + const char *name; + + /** Represents the operation performed on the property */ + svn_diff_operation_kind_t operation; + + /** + * An array containing an svn_hunk_t object for each hunk parsed from the + * patch associated with our property name */ + apr_array_header_t *hunks; +} svn_prop_patch_t; + +/** * Data type to manage parsing of patches. * * @since New in 1.7. */ @@ -956,9 +972,9 @@ typedef struct svn_patch_t { apr_array_header_t *hunks; /** - * A hash table containing an array of svn_hunk_t object for each property - * parsed from the patch. The property names act as keys. */ - apr_hash_t *property_hunks; + * An array containing svn_patch_property_t object for each property + * parsed from the patch. */ + apr_array_header_t *prop_patches; /** * Represents the operation performed on the file. */ Modified: subversion/trunk/subversion/libsvn_diff/parse-diff.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_diff/parse-diff.c?rev=963814&r1=963813&r2=963814&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_diff/parse-diff.c (original) +++ subversion/trunk/subversion/libsvn_diff/parse-diff.c Tue Jul 13 18:46:31 2010 @@ -501,14 +501,15 @@ parse_prop_name(const char **prop_name, /* Return the next *HUNK from a PATCH, using STREAM to read data * from the patch file. If no hunk can be found, set *HUNK to NULL. If we - * have a property hunk, PROP_NAME will be set. If we have a text hunk, - * PROP_NAME will be NULL. If REVERSE is TRUE, invert the hunk while - * parsing it. If IGNORE_WHiTESPACES is TRUE, let lines without leading - * spaces be recognized as context lines. Allocate results in RESULT_POOL. - * Use SCRATCH_POOL for all other allocations. */ + * have a property hunk, PROP_NAME and PROP_OPERATION will be set. If we + * have a text hunk, PROP_NAME will be NULL. If REVERSE is TRUE, invert the + * hunk while parsing it. If IGNORE_WHiTESPACES is TRUE, let lines without + * leading spaces be recognized as context lines. Allocate results in + * RESULT_POOL. Use SCRATCH_POOL for all other allocations. */ static svn_error_t * parse_next_hunk(svn_hunk_t **hunk, const char **prop_name, + svn_diff_operation_kind_t *prop_operation, svn_patch_t *patch, svn_stream_t *stream, svn_boolean_t reverse, @@ -685,16 +686,19 @@ parse_next_hunk(svn_hunk_t **hunk, { SVN_ERR(parse_prop_name(prop_name, line->data, "Added: ", result_pool)); + *prop_operation = svn_diff_op_added; } else if (starts_with(line->data, "Deleted: ")) { SVN_ERR(parse_prop_name(prop_name, line->data, "Deleted: ", result_pool)); + *prop_operation = svn_diff_op_deleted; } else if (starts_with(line->data, "Modified: ")) { SVN_ERR(parse_prop_name(prop_name, line->data, "Modified: ", result_pool)); + *prop_operation = svn_diff_op_modified; } else if (starts_with(line->data, minus) || starts_with(line->data, "git --diff ")) @@ -1042,6 +1046,47 @@ git_deleted_file(enum parse_state *new_s return SVN_NO_ERROR; } +/* Add a HUNK associated with the property PROP_NAME to PATCH. */ +static svn_error_t * +add_property_hunk(svn_patch_t *patch, const char *prop_name, + svn_hunk_t *hunk, svn_diff_operation_kind_t operation, + apr_pool_t *result_pool) +{ + int i; + svn_boolean_t prop_name_seen = FALSE; + + /* Find the right property name and insert the hunk.. */ + for (i = 0; i < patch->prop_patches->nelts; i++) + { + svn_prop_patch_t *prop_patch = APR_ARRAY_IDX(patch->prop_patches, + i, + svn_prop_patch_t *); + if (! strcmp(prop_name, prop_patch->name)) + { + APR_ARRAY_PUSH(prop_patch->hunks, svn_hunk_t *) = hunk; + prop_name_seen = TRUE; + break; + } + } + + /* .. No property found named prop_name so we create it. */ + if (! prop_name_seen) + { + svn_prop_patch_t *prop_patch; + + prop_patch = apr_palloc(result_pool, + sizeof(svn_prop_patch_t *)); + prop_patch->name = prop_name; + prop_patch->operation = operation; + prop_patch->hunks = apr_array_make(result_pool, 1, + sizeof(svn_hunk_t *)); + APR_ARRAY_PUSH(prop_patch->hunks, svn_hunk_t *) = hunk; + APR_ARRAY_PUSH(patch->prop_patches, + svn_prop_patch_t *) = prop_patch; + } + + return SVN_NO_ERROR; +} svn_error_t * svn_diff_parse_next_patch(svn_patch_t **patch, @@ -1182,33 +1227,28 @@ svn_diff_parse_next_patch(svn_patch_t ** { svn_hunk_t *hunk; const char *prop_name; + svn_diff_operation_kind_t prop_operation; /* Parse hunks. */ (*patch)->hunks = apr_array_make(result_pool, 10, sizeof(svn_hunk_t *)); - (*patch)->property_hunks = apr_hash_make(result_pool); + (*patch)->prop_patches = apr_array_make(result_pool, 1, sizeof(svn_hunk_t *)); do { svn_pool_clear(iterpool); - SVN_ERR(parse_next_hunk(&hunk, &prop_name, *patch, stream, - reverse, ignore_whitespace, + SVN_ERR(parse_next_hunk(&hunk, &prop_name, &prop_operation, + *patch, stream, reverse, + ignore_whitespace, result_pool, iterpool)); + + /* We have a property hunk. */ if (hunk && prop_name) { - apr_array_header_t *hunks; - - hunks = apr_hash_get((*patch)->property_hunks, prop_name, - APR_HASH_KEY_STRING); - if (! hunks) - { - hunks = apr_array_make(result_pool, 1, - sizeof(svn_hunk_t *)); - apr_hash_set((*patch)->property_hunks, prop_name, - APR_HASH_KEY_STRING, hunks); - } - - APR_ARRAY_PUSH(hunks, svn_hunk_t *) = hunk; + SVN_ERR(add_property_hunk(*patch, prop_name, hunk, prop_operation, + result_pool)); } + + /* We have a regular text hunk. */ else if (hunk) APR_ARRAY_PUSH((*patch)->hunks, svn_hunk_t *) = hunk; Modified: subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c?rev=963814&r1=963813&r2=963814&view=diff ============================================================================== --- subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c (original) +++ subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c Tue Jul 13 18:46:31 2010 @@ -489,6 +489,7 @@ test_parse_property_diff(apr_pool_t *poo { apr_file_t *patch_file; svn_patch_t *patch; + svn_prop_patch_t *prop_patch; svn_hunk_t *hunk; apr_array_header_t *hunks; const char *fname = "test_parse_property_diff.patch"; @@ -503,36 +504,51 @@ test_parse_property_diff(apr_pool_t *poo SVN_TEST_ASSERT(! strcmp(patch->old_filename, "iota")); SVN_TEST_ASSERT(! strcmp(patch->new_filename, "iota")); SVN_TEST_ASSERT(patch->hunks->nelts == 0); - SVN_TEST_ASSERT(apr_hash_count(patch->property_hunks) == 3); + SVN_TEST_ASSERT(patch->prop_patches->nelts == 3); + + /* Check the deleted property */ + prop_patch = APR_ARRAY_IDX(patch->prop_patches, 0 , svn_prop_patch_t *); + + SVN_TEST_ASSERT(!strcmp("prop_del", prop_patch->name)); + SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_deleted); + hunks = prop_patch->hunks; - /* Check the added property */ - hunks = apr_hash_get(patch->property_hunks, "prop_add", APR_HASH_KEY_STRING); SVN_TEST_ASSERT(hunks->nelts == 1); hunk = APR_ARRAY_IDX(hunks, 0 , svn_hunk_t *); SVN_ERR(check_content(hunk, TRUE, - "", + "value" NL, pool)); SVN_ERR(check_content(hunk, FALSE, - "value" NL, + "", pool)); - /* Check the deleted property */ - hunks = apr_hash_get(patch->property_hunks, "prop_del", APR_HASH_KEY_STRING); + /* Check the added property */ + prop_patch = APR_ARRAY_IDX(patch->prop_patches, 1 , svn_prop_patch_t *); + + SVN_TEST_ASSERT(!strcmp("prop_add", prop_patch->name)); + SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_added); + hunks = prop_patch->hunks; + SVN_TEST_ASSERT(hunks->nelts == 1); hunk = APR_ARRAY_IDX(hunks, 0 , svn_hunk_t *); SVN_ERR(check_content(hunk, TRUE, - "value" NL, + "", pool)); SVN_ERR(check_content(hunk, FALSE, - "", + "value" NL, pool)); /* Check the modified property */ - hunks = apr_hash_get(patch->property_hunks, "prop_mod", APR_HASH_KEY_STRING); + prop_patch = APR_ARRAY_IDX(patch->prop_patches, 2 , svn_prop_patch_t *); + + SVN_TEST_ASSERT(!strcmp("prop_mod", prop_patch->name)); + SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_modified); + hunks = prop_patch->hunks; + SVN_TEST_ASSERT(hunks->nelts == 1); hunk = APR_ARRAY_IDX(hunks, 0 , svn_hunk_t *); @@ -552,6 +568,7 @@ test_parse_property_and_text_diff(apr_po { apr_file_t *patch_file; svn_patch_t *patch; + svn_prop_patch_t *prop_patch; svn_hunk_t *hunk; apr_array_header_t *hunks; const char *fname = "test_parse_property_and_text_diff.patch"; @@ -567,7 +584,7 @@ test_parse_property_and_text_diff(apr_po SVN_TEST_ASSERT(! strcmp(patch->old_filename, "iota")); SVN_TEST_ASSERT(! strcmp(patch->new_filename, "iota")); SVN_TEST_ASSERT(patch->hunks->nelts == 1); - SVN_TEST_ASSERT(apr_hash_count(patch->property_hunks) == 1); + SVN_TEST_ASSERT(patch->prop_patches->nelts == 1); /* Check contents of text hunk */ hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_hunk_t *); @@ -582,7 +599,11 @@ test_parse_property_and_text_diff(apr_po pool)); /* Check the added property */ - hunks = apr_hash_get(patch->property_hunks, "prop_add", APR_HASH_KEY_STRING); + prop_patch = APR_ARRAY_IDX(patch->prop_patches, 0 , svn_prop_patch_t *); + SVN_TEST_ASSERT(!strcmp("prop_add", prop_patch->name)); + SVN_TEST_ASSERT(prop_patch->operation == svn_diff_op_added); + + hunks = prop_patch->hunks; SVN_TEST_ASSERT(hunks->nelts == 1); hunk = APR_ARRAY_IDX(hunks, 0 , svn_hunk_t *);