Author: dannas
Date: Tue Jun 29 11:43:26 2010
New Revision: 958937
URL: http://svn.apache.org/viewvc?rev=958937&view=rev
Log:
Make 'svn diff --git-diff --show-copies-as-adds' show git diff headers for
copied paths.
At the moment this only works if we invoke the diff operation with
--show-copies-as-adds set. Since we need to be backward compat with
the old flags, some changes needs to be done in the callers of the
diff callbacks to distinguish between:
unidiff (don't report copied paths without modifications)
unidiff (--show-copies-as-adds means do report copies without mods)
git diff (report copies for paths without modifications)
git diff (--show-copies-as-adds... Hardly needed?)
.. Just taking it one step at a time.
* subversion/libsvn_wc/diff.c
(file_diff): Fetch original_repos_relpath and pass it to the
file_added() callback if --show-copies-as-adds has been set.
* subversion/libsvn_client/diff.c
(diff_cmd_baton): Add WC_CTX member. Needed for fetching the
repos_relpath to compare scope of copyfrom_path in diff_file_added().
(diff_content_changed): Add COPYFROM_PATH member.
(diff_file_changed): Call diff_content_changed() with NULL value for
copyfrom_path.
(diff_file_added): Check scope of copyfrom_path to determine if we have
a copy or add.
(svn_client_diff5
svn_client_diff_peg5): Initialize WC_CTX member of diff_cmd_baton.
Modified:
subversion/trunk/subversion/libsvn_client/diff.c
subversion/trunk/subversion/libsvn_wc/diff.c
Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=958937&r1=958936&r2=958937&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Tue Jun 29 11:43:26 2010
@@ -451,6 +451,8 @@ struct diff_cmd_baton {
const char *relative_to_dir;
svn_boolean_t use_git_diff_format;
+
+ svn_wc_context_t *wc_ctx;
};
/* Generate a label for the diff output for file PATH at revision REVNUM.
@@ -518,6 +520,7 @@ diff_content_changed(const char *path,
const char *mimetype1,
const char *mimetype2,
svn_diff_operation_kind_t operation,
+ const char *copyfrom_path,
void *diff_baton)
{
struct diff_cmd_baton *diff_cmd_baton = diff_baton;
@@ -713,29 +716,40 @@ diff_content_changed(const char *path,
return SVN_NO_ERROR;
}
- else if (operation == svn_diff_op_added)
+ else if (operation == svn_diff_op_copied)
{
- SVN_ERR(print_git_diff_header_added(
- os,
+ SVN_ERR(print_git_diff_header_copied(
+ os,
diff_cmd_baton->header_encoding,
- path, subpool));
- label1 = diff_label("/dev/null", rev1, subpool);
- label2 = diff_label(apr_psprintf(subpool, "b/%s", path2), rev2,
- subpool);
- }
- else if (operation == svn_diff_op_modified)
- {
- SVN_ERR(print_git_diff_header_modified(
- os,
- diff_cmd_baton->header_encoding,
- path, subpool));
+ copyfrom_path, path, subpool));
label1 = diff_label(apr_psprintf(subpool, "a/%s", path1), rev1,
subpool);
label2 = diff_label(apr_psprintf(subpool, "b/%s", path2), rev2,
subpool);
- }
+ }
+ else if (operation == svn_diff_op_added)
+ {
+ SVN_ERR(print_git_diff_header_added(
+ os,
+ diff_cmd_baton->header_encoding,
+ path, subpool));
+ label1 = diff_label("/dev/null", rev1, subpool);
+ label2 = diff_label(apr_psprintf(subpool, "b/%s", path2), rev2,
+ subpool);
+ }
+ else if (operation == svn_diff_op_modified)
+ {
+ SVN_ERR(print_git_diff_header_modified(
+ os,
+
diff_cmd_baton->header_encoding,
+ path, subpool));
+ label1 = diff_label(apr_psprintf(subpool, "a/%s", path1),
rev1,
+ subpool);
+ label2 = diff_label(apr_psprintf(subpool, "b/%s", path2),
rev2,
+ subpool);
+ }
- /* ### Print git headers for copies and renames too. */
+ /* ### Print git headers for renames too. */
}
/* Output the actual diff */
@@ -779,7 +793,7 @@ diff_file_changed(const char *local_dir_
SVN_ERR(diff_content_changed(path,
tmpfile1, tmpfile2, rev1, rev2,
mimetype1, mimetype2,
- svn_diff_op_modified, diff_baton));
+ svn_diff_op_modified, NULL, diff_baton));
if (prop_changes->nelts > 0)
SVN_ERR(diff_props_changed(local_dir_abspath, prop_state, tree_conflicted,
path, prop_changes,
@@ -826,11 +840,52 @@ diff_file_added(const char *local_dir_ab
user see that *something* happened. */
diff_cmd_baton->force_empty = TRUE;
- if (tmpfile1)
+ /* ### We still can't detect moves without extending the parameters of
+ * ### file_added(). The *right* thing to do is propably to extend
+ * ### svn_wc_diff_callbacks4_t with file_copied() and file_moved(). */
+ if (tmpfile1 && copyfrom_path)
+ {
+ const char *repos_relpath;
+ char *ancestor_of_path;
+ const char *local_abspath;
+ int offset;
+ svn_diff_operation_kind_t op_kind = svn_diff_op_copied;
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
+
+ SVN_ERR(svn_wc__node_get_repos_relpath(&repos_relpath,
+ diff_cmd_baton->wc_ctx,
+ local_abspath, scratch_pool,
+ scratch_pool));
+
+ /* We need to determine if the copyfrom_path is within scope of the
+ * diff we're producing. If not we'll just mark it as an add.
+ * Determining scope involves checking two things; the dir we executed
+ * the command from (orig_path2) and the target of the command (path).
+ *
+ * ### We'll do the same thing for moves but then we'll have to
+ * ### consider the scope of both the delete-half and the add-half. */
+ ancestor_of_path = apr_pstrdup(scratch_pool, repos_relpath);
+
+ offset = strlen(repos_relpath) - strlen(path)
+ + strlen(diff_cmd_baton->orig_path_2);
+
+ ancestor_of_path[offset] = '\0';
+
+ if (strncmp(copyfrom_path, ancestor_of_path, strlen(ancestor_of_path)))
+ op_kind = svn_diff_op_added;
+
+ SVN_ERR(diff_content_changed(path,
+ tmpfile1, tmpfile2, rev1, rev2,
+ mimetype1, mimetype2,
+ op_kind, copyfrom_path,
+ diff_baton));
+ }
+ else if (tmpfile1)
SVN_ERR(diff_content_changed(path,
tmpfile1, tmpfile2, rev1, rev2,
mimetype1, mimetype2,
- svn_diff_op_added, diff_baton));
+ svn_diff_op_added, NULL, diff_baton));
if (prop_changes->nelts > 0)
SVN_ERR(diff_props_changed(local_dir_abspath, prop_state, tree_conflicted,
path, prop_changes,
@@ -868,7 +923,7 @@ diff_file_deleted_with_diff(const char *
tmpfile1, tmpfile2, diff_cmd_baton->revnum1,
diff_cmd_baton->revnum2,
mimetype1, mimetype2,
- svn_diff_op_deleted, diff_baton));
+ svn_diff_op_deleted, NULL, diff_baton));
/* We don't list all the deleted properties. */
@@ -1914,6 +1969,7 @@ svn_client_diff5(const apr_array_header_
diff_cmd_baton.force_binary = ignore_content_type;
diff_cmd_baton.relative_to_dir = relative_to_dir;
diff_cmd_baton.use_git_diff_format = use_git_diff_format;
+ diff_cmd_baton.wc_ctx = ctx->wc_ctx;
return do_diff(&diff_params, &diff_callbacks, &diff_cmd_baton, ctx, pool);
}
@@ -1982,6 +2038,7 @@ svn_client_diff_peg5(const apr_array_hea
diff_cmd_baton.force_binary = ignore_content_type;
diff_cmd_baton.relative_to_dir = relative_to_dir;
diff_cmd_baton.use_git_diff_format = use_git_diff_format;
+ diff_cmd_baton.wc_ctx = ctx->wc_ctx;
return do_diff(&diff_params, &diff_callbacks, &diff_cmd_baton, ctx, pool);
}
Modified: subversion/trunk/subversion/libsvn_wc/diff.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff.c?rev=958937&r1=958936&r2=958937&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff.c (original)
+++ subversion/trunk/subversion/libsvn_wc/diff.c Tue Jun 29 11:43:26 2010
@@ -585,6 +585,7 @@ file_diff(struct dir_baton *db,
const char *empty_file;
svn_boolean_t replaced;
svn_wc__db_status_t status;
+ const char *original_repos_relpath;
svn_revnum_t revision;
svn_revnum_t revert_base_revnum;
svn_boolean_t have_base;
@@ -622,8 +623,9 @@ file_diff(struct dir_baton *db,
/* Now refine ADDED to one of: ADDED, COPIED, MOVED_HERE. Note that only
the latter two have corresponding pristine info to diff against. */
if (status == svn_wc__db_status_added)
- SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, eb->db, local_abspath,
+ SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL,
+ &original_repos_relpath, NULL, NULL,
+ NULL, eb->db, local_abspath,
pool, pool));
/* A wc-wc diff of replaced files actually shows a diff against the
@@ -721,9 +723,9 @@ file_diff(struct dir_baton *db,
0, revision,
NULL,
working_mimetype,
- NULL, SVN_INVALID_REVNUM,
- propchanges, baseprops,
- eb->callback_baton,
+ original_repos_relpath,
+ SVN_INVALID_REVNUM, propchanges,
+ baseprops, eb->callback_baton,
pool));
}
else