You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/08/05 12:24:23 UTC
svn commit: r982534 - in /subversion/trunk/subversion:
libsvn_diff/parse-diff.c tests/libsvn_diff/parse-diff-test.c
Author: dannas
Date: Thu Aug 5 10:24:23 2010
New Revision: 982534
URL: http://svn.apache.org/viewvc?rev=982534&view=rev
Log:
Make the diff parser able to handle paths with spaces in the
"--git diff a/path b/path" line. At the same time start
recording path information from other header fields.
We only need the filenames from the --git diff line if we're
dealing with added or deleted empty files. In those cases, the
paths should be identical.
The git_start() function probably needs some adjusting but it passes
the tests so I'm committing it. :).
* subversion/libsvn_diff/parse-diff.c
(git_start): First check that we have a header line on the form
"--git diff a/.+ b/.+". Then grab the old and new filename if
they are the same.
(git_minus,
git_plus,
git_move_from,
git_move_to,
git_copy_from,
git_copy_to): Start grabbing filenames.
* subversion/tests/libsvn_diff/parse-diff-test.c
(test_funcs): Remove XFail marker for test_git_diffs_with_spaces_diff.
Modified:
subversion/trunk/subversion/libsvn_diff/parse-diff.c
subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c
Modified: subversion/trunk/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_diff/parse-diff.c?rev=982534&r1=982533&r2=982534&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/trunk/subversion/libsvn_diff/parse-diff.c Thu Aug 5 10:24:23 2010
@@ -881,10 +881,12 @@ static svn_error_t *
git_start(enum parse_state *new_state, const char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
- const char *old_path;
- const char *new_path;
- char *end_old_path;
- char *slash;
+ const char *old_path_start;
+ char *old_path_end;
+ const char *new_path_start;
+ const char *new_path_end;
+ char *new_path_marker;
+ const char *old_path_marker;
/* ### Add handling of escaped paths
* http://www.kernel.org/pub/software/scm/git/docs/git-diff.html:
@@ -897,59 +899,79 @@ git_start(enum parse_state *new_state, c
/* Our line should look like this: 'git --diff a/path b/path'.
* If we find any deviations from that format, we return with state reset
* to start.
- *
- * ### We can't handle paths with spaces!
*/
- slash = strchr(line, '/');
+ old_path_marker = strstr(line, " a/");
- if (! slash)
+ if (! old_path_marker)
{
*new_state = state_start;
return SVN_NO_ERROR;
}
- old_path = slash + 1;
-
- if (! *old_path)
+ if (! *(old_path_marker + 3))
{
*new_state = state_start;
return SVN_NO_ERROR;
}
- end_old_path = strchr(old_path, ' ');
+ new_path_marker = strstr(old_path_marker, " b/");
- if (end_old_path)
- *end_old_path = '\0';
- else
+ if (! new_path_marker)
{
*new_state = state_start;
return SVN_NO_ERROR;
}
- /* The new path begins after the first slash after the old path. */
- slash = strchr(end_old_path + 1, '/');
-
- if (! slash)
+ if (! *(new_path_marker + 3))
{
*new_state = state_start;
return SVN_NO_ERROR;
}
- /* The path starts after the slash */
- new_path = slash + 1;
+ /* By now, we know that we have a line on the form '--git diff a/.+ b/.+'
+ * We only need the filenames when we have deleted or added empty
+ * files. In those cases the old_path and new_path is identical on the
+ * '--git diff' line. For all other cases we fetch the filenames from
+ * other header lines. */
+ old_path_start = line + strlen("--git diff a/");
+ new_path_end = line + strlen(line);
+ new_path_start = old_path_start;
+
+ while (TRUE)
+ {
+ int len_old;
+ int len_new;
+
+ new_path_marker = strstr(new_path_start, " b/");
+
+ /* No new path marker, bail out. */
+ if (! new_path_marker)
+ break;
+
+ old_path_end = new_path_marker;
+ new_path_start = new_path_marker + strlen(" b/");
+
+ /* No path after the marker. */
+ if (! *new_path_start)
+ break;
+
+ len_old = old_path_end - old_path_start;
+ len_new = new_path_end - new_path_start;
+
+ /* Are the paths before and after the " b/" marker the same? */
+ if (len_old == len_new
+ && ! strncmp(old_path_start, new_path_start, len_old))
+ {
+ *old_path_end = '\0';
+ SVN_ERR(grab_filename(&patch->old_filename, old_path_start,
+ result_pool, scratch_pool));
- if (! *new_path)
- {
- *new_state = state_start;
- return SVN_NO_ERROR;
+ SVN_ERR(grab_filename(&patch->new_filename, new_path_start,
+ result_pool, scratch_pool));
+ break;
+ }
}
- SVN_ERR(grab_filename(&patch->old_filename, old_path,
- result_pool, scratch_pool));
-
- SVN_ERR(grab_filename(&patch->new_filename, new_path,
- result_pool, scratch_pool));
-
/* We assume that the path is only modified until we've found a 'tree'
* header */
patch->operation = svn_diff_op_modified;
@@ -965,6 +987,16 @@ git_minus(enum parse_state *new_state, c
{
/* ### Check that the path is consistent with the 'git --diff ' line. */
+ /* If we can find a tab, it separates the filename from
+ * the rest of the line which we can discard. */
+ char *tab = strchr(line, '\t');
+ if (tab)
+ *tab = '\0';
+
+ /* ### What if we have "--- /dev/null"? */
+ SVN_ERR(grab_filename(&patch->old_filename, line + strlen("--- a/"),
+ result_pool, scratch_pool));
+
*new_state = state_git_minus_seen;
return SVN_NO_ERROR;
}
@@ -976,6 +1008,16 @@ git_plus(enum parse_state *new_state, co
{
/* ### Check that the path is consistent with the 'git --diff ' line. */
+ /* If we can find a tab, it separates the filename from
+ * the rest of the line which we can discard. */
+ char *tab = strchr(line, '\t');
+ if (tab)
+ *tab = '\0';
+
+ /* ### What if we have "+++ /dev/null" ? */
+ SVN_ERR(grab_filename(&patch->new_filename, line + strlen("+++ b/"),
+ result_pool, scratch_pool));
+
*new_state = state_git_header_found;
return SVN_NO_ERROR;
}
@@ -987,6 +1029,9 @@ git_move_from(enum parse_state *new_stat
{
/* ### Check that the path is consistent with the 'git --diff ' line. */
+ SVN_ERR(grab_filename(&patch->old_filename, line + strlen("rename from "),
+ result_pool, scratch_pool));
+
*new_state = state_move_from_seen;
return SVN_NO_ERROR;
}
@@ -998,6 +1043,9 @@ git_move_to(enum parse_state *new_state,
{
/* ### Check that the path is consistent with the 'git --diff ' line. */
+ SVN_ERR(grab_filename(&patch->new_filename, line + strlen("rename to "),
+ result_pool, scratch_pool));
+
patch->operation = svn_diff_op_moved;
*new_state = state_git_tree_seen;
@@ -1011,6 +1059,9 @@ git_copy_from(enum parse_state *new_stat
{
/* ### Check that the path is consistent with the 'git --diff ' line. */
+ SVN_ERR(grab_filename(&patch->old_filename, line + strlen("copy from "),
+ result_pool, scratch_pool));
+
*new_state = state_copy_from_seen;
return SVN_NO_ERROR;
}
@@ -1022,6 +1073,9 @@ git_copy_to(enum parse_state *new_state,
{
/* ### Check that the path is consistent with the 'git --diff ' line. */
+ SVN_ERR(grab_filename(&patch->new_filename, line + strlen("copy to "),
+ result_pool, scratch_pool));
+
patch->operation = svn_diff_op_copied;
*new_state = state_git_tree_seen;
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=982534&r1=982533&r2=982534&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_diff/parse-diff-test.c Thu Aug 5 10:24:23 2010
@@ -870,7 +870,7 @@ struct svn_test_descriptor_t test_funcs[
"test property and text unidiff parsing"),
SVN_TEST_PASS2(test_parse_diff_symbols_in_prop_unidiff,
"test property diffs with odd symbols"),
- SVN_TEST_XFAIL2(test_git_diffs_with_spaces_diff,
+ SVN_TEST_PASS2(test_git_diffs_with_spaces_diff,
"test git diffs with spaces in paths"),
SVN_TEST_NULL
};