You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/10/05 17:34:49 UTC

svn commit: r1706855 - in /subversion/trunk/subversion: include/private/svn_diff_tree.h libsvn_client/diff.c libsvn_wc/diff.h libsvn_wc/diff_editor.c libsvn_wc/diff_local.c

Author: rhuijben
Date: Mon Oct  5 15:34:49 2015
New Revision: 1706855

URL: http://svn.apache.org/viewvc?rev=1706855&view=rev
Log:
Extend 'svn diff --git' to produce 'rename from' and 'rename to' headers
on the add side of the move operation from local diffs.

* subversion/include/private/svn_diff_tree.h
  (svn_diff_source_t): Extend struct. Extend documentation.

* subversion/libsvn_client/diff.c
  (diff_file_added): Handle (direct) moves of files.

* subversion/libsvn_wc/diff.h
  (svn_wc__diff_local_only_file,
   svn_wc__diff_local_only_dir): Add moved_from argument to pass on.

* subversion/libsvn_wc/diff_editor.c
  (walk_local_nodes_diff): Update caller. Calculate moved_from when
    touching a moved node.
  (svn_wc__diff_local_only_file): Set info when available.
   svn_wc__diff_local_only_dir): Set info when available. Calculate
     moved_from on children.

* subversion/libsvn_wc/diff_local.c
  (diff_status_callback): Update caller.

Modified:
    subversion/trunk/subversion/include/private/svn_diff_tree.h
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/libsvn_wc/diff.h
    subversion/trunk/subversion/libsvn_wc/diff_editor.c
    subversion/trunk/subversion/libsvn_wc/diff_local.c

Modified: subversion/trunk/subversion/include/private/svn_diff_tree.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_diff_tree.h?rev=1706855&r1=1706854&r2=1706855&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_diff_tree.h (original)
+++ subversion/trunk/subversion/include/private/svn_diff_tree.h Mon Oct  5 15:34:49 2015
@@ -114,12 +114,24 @@ extern "C" {
  * ### How come many users don't set the 'repos_relpath' field? */
 typedef struct svn_diff_source_t
 {
-  /* Always available */
+  /* Always available
+     In case of copyfrom: the revision copied from
+   */
   svn_revnum_t revision;
 
-  /* Depending on the driver available for copyfrom */
-  /* ### What? */
+  /* In case of copyfrom: the repository relative path copied from.
+
+     NULL if the node wasn't copied or moved, or when the driver doesn't
+     have this information */
   const char *repos_relpath;
+
+  /* In case of copyfrom: the relative path of source location before the
+     move. This path is relative WITHIN THE DIFF. The repository path is
+     typically in repos_relpath
+
+     NULL if the node wasn't moved or if the driver doesn't have this
+     information. */
+  const char *moved_from_relpath;
 } svn_diff_source_t;
 
 /**

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1706855&r1=1706854&r2=1706855&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Mon Oct  5 15:34:49 2015
@@ -1197,9 +1197,13 @@ diff_file_added(const char *relpath,
                                  copyfrom_source->revision,
                                  right_source->revision,
                                  left_props, right_props,
-                                 svn_diff_op_copied,
+                                 copyfrom_source->moved_from_relpath
+                                    ? svn_diff_op_moved
+                                    : svn_diff_op_copied,
                                  TRUE /* force diff output */,
-                                 copyfrom_source->repos_relpath,
+                                 copyfrom_source->moved_from_relpath
+                                    ? copyfrom_source->moved_from_relpath
+                                    : copyfrom_source->repos_relpath,
                                  copyfrom_source->revision,
                                  dwi, scratch_pool));
   else if (right_file)

Modified: subversion/trunk/subversion/libsvn_wc/diff.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff.h?rev=1706855&r1=1706854&r2=1706855&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff.h (original)
+++ subversion/trunk/subversion/libsvn_wc/diff.h Mon Oct  5 15:34:49 2015
@@ -52,6 +52,7 @@ svn_error_t *
 svn_wc__diff_local_only_file(svn_wc__db_t *db,
                              const char *local_abspath,
                              const char *relpath,
+                             const char *moved_from_relpath,
                              const svn_diff_tree_processor_t *processor,
                              void *processor_parent_baton,
                              svn_boolean_t diff_pristine,
@@ -75,6 +76,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                             const char *local_abspath,
                             const char *relpath,
                             svn_depth_t depth,
+                            const char *moved_from_relpath,
                             const svn_diff_tree_processor_t *processor,
                             void *processor_parent_baton,
                             svn_boolean_t diff_pristine,

Modified: subversion/trunk/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff_editor.c?rev=1706855&r1=1706854&r2=1706855&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/diff_editor.c Mon Oct  5 15:34:49 2015
@@ -744,9 +744,29 @@ walk_local_nodes_diff(struct edit_baton_
 
           if (eb->local_before_remote && local_only)
             {
+              const char *moved_from_relpath;
+
+              if (info->moved_here)
+                {
+                  const char *moved_from_abspath;
+
+                  SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+                                                NULL, NULL, NULL,
+                                                db, child_abspath,
+                                                iterpool, iterpool));
+                  SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+                  moved_from_relpath = svn_dirent_skip_ancestor(
+                                                        eb->anchor_abspath,
+                                                        moved_from_abspath);
+                }
+              else
+                moved_from_relpath = NULL;
+
               if (info->kind == svn_node_file && diff_files)
                 SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                      child_relpath,
+                                                     moved_from_relpath,
                                                      eb->processor, dir_baton,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
@@ -756,6 +776,7 @@ walk_local_nodes_diff(struct edit_baton_
                 SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
                                                     child_relpath,
                                                     depth_below_here,
+                                                    moved_from_relpath,
                                                     eb->processor, dir_baton,
                                                     eb->diff_pristine,
                                                     eb->cancel_func,
@@ -810,9 +831,29 @@ walk_local_nodes_diff(struct edit_baton_
 
           if (!eb->local_before_remote && local_only)
             {
+              const char *moved_from_relpath;
+
+              if (info->moved_here)
+                {
+                  const char *moved_from_abspath;
+
+                  SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+                                                NULL, NULL, NULL,
+                                                db, child_abspath,
+                                                iterpool, iterpool));
+                  SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+                  moved_from_relpath = svn_dirent_skip_ancestor(
+                                                        eb->anchor_abspath,
+                                                        moved_from_abspath);
+                }
+              else
+                moved_from_relpath = NULL;
+
               if (info->kind == svn_node_file && diff_files)
                 SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                      child_relpath,
+                                                     moved_from_relpath,
                                                      eb->processor, dir_baton,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
@@ -820,12 +861,13 @@ walk_local_nodes_diff(struct edit_baton_
                                                      iterpool));
               else if (info->kind == svn_node_dir && diff_dirs)
                 SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
-                                                     child_relpath, depth_below_here,
-                                                     eb->processor, dir_baton,
-                                                     eb->diff_pristine,
-                                                     eb->cancel_func,
-                                                     eb->cancel_baton,
-                                                     iterpool));
+                                                    child_relpath, depth_below_here,
+                                                    moved_from_relpath,
+                                                    eb->processor, dir_baton,
+                                                    eb->diff_pristine,
+                                                    eb->cancel_func,
+                                                    eb->cancel_baton,
+                                                    iterpool));
             }
         }
     }
@@ -876,6 +918,7 @@ svn_error_t *
 svn_wc__diff_local_only_file(svn_wc__db_t *db,
                              const char *local_abspath,
                              const char *relpath,
+                             const char *moved_from_relpath,
                              const svn_diff_tree_processor_t *processor,
                              void *processor_parent_baton,
                              svn_boolean_t diff_pristine,
@@ -938,6 +981,7 @@ svn_wc__diff_local_only_file(svn_wc__db_
     {
       copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
       copyfrom_src->repos_relpath = original_repos_relpath;
+      copyfrom_src->moved_from_relpath = moved_from_relpath;
     }
 
   if (props_mod || !SVN_IS_VALID_REVNUM(revision))
@@ -1016,6 +1060,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                             const char *local_abspath,
                             const char *relpath,
                             svn_depth_t depth,
+                            const char *moved_from_relpath,
                             const svn_diff_tree_processor_t *processor,
                             void *processor_parent_baton,
                             svn_boolean_t diff_pristine,
@@ -1052,6 +1097,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
     {
       copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
       copyfrom_src->repos_relpath = original_repos_relpath;
+      copyfrom_src->moved_from_relpath = moved_from_relpath;
     }
 
   /* svn_wc__db_status_incomplete should never happen, as the result won't be
@@ -1139,12 +1185,40 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
 
           child_relpath = svn_relpath_join(relpath, name, iterpool);
 
+          if (info->moved_here)
+            {
+              const char *moved_from_abspath;
+              const char *a_abspath;
+              const char *a_relpath;
+
+              a_relpath = relpath;
+              a_abspath = local_abspath;
+              while (*a_relpath)
+                {
+                  a_relpath = svn_relpath_dirname(a_relpath, iterpool);
+                  a_abspath = svn_dirent_dirname(a_abspath, iterpool);
+                }
+
+              SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+                                            NULL, NULL, NULL,
+                                            db, child_abspath,
+                                            iterpool, iterpool));
+              SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+              moved_from_relpath = svn_dirent_skip_ancestor(
+                                                        a_abspath,
+                                                        moved_from_abspath);
+            }
+          else
+            moved_from_relpath = NULL;
+
           switch (info->kind)
             {
             case svn_node_file:
             case svn_node_symlink:
               SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                    child_relpath,
+                                                   moved_from_relpath,
                                                    processor, pdb,
                                                    diff_pristine,
                                                    cancel_func, cancel_baton,
@@ -1157,6 +1231,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                   SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
                                                       child_relpath,
                                                       depth_below_here,
+                                                      moved_from_relpath,
                                                       processor, pdb,
                                                       diff_pristine,
                                                       cancel_func,
@@ -1205,6 +1280,8 @@ handle_local_only(struct dir_baton_t *pb
 {
   struct edit_baton_t *eb = pb->eb;
   const struct svn_wc__db_info_t *info;
+  const char *child_abspath;
+  const char *moved_from_relpath;
   svn_boolean_t repos_delete = (pb->deletes
                                 && svn_hash_gets(pb->deletes, name));
 
@@ -1240,6 +1317,25 @@ handle_local_only(struct dir_baton_t *pb
         break;
     }
 
+  child_abspath = svn_dirent_join(pb->local_abspath, name, scratch_pool);
+
+  if (info->moved_here)
+    {
+      const char *moved_from_abspath;
+
+      SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+                                    NULL, NULL, NULL,
+                                    eb->db, child_abspath,
+                                    scratch_pool, scratch_pool));
+      SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+      moved_from_relpath = svn_dirent_skip_ancestor(
+                                    eb->anchor_abspath,
+                                    moved_from_abspath);
+    }
+  else
+    moved_from_relpath = NULL;
+
   if (info->kind == svn_node_dir)
     {
       svn_depth_t depth ;
@@ -1251,9 +1347,10 @@ handle_local_only(struct dir_baton_t *pb
 
       SVN_ERR(svn_wc__diff_local_only_dir(
                       eb->db,
-                      svn_dirent_join(pb->local_abspath, name, scratch_pool),
+                      child_abspath,
                       svn_relpath_join(pb->relpath, name, scratch_pool),
                       repos_delete ? svn_depth_infinity : depth,
+                      moved_from_relpath,
                       eb->processor, pb->pdb,
                       eb->diff_pristine,
                       eb->cancel_func, eb->cancel_baton,
@@ -1262,8 +1359,9 @@ handle_local_only(struct dir_baton_t *pb
   else
     SVN_ERR(svn_wc__diff_local_only_file(
                       eb->db,
-                      svn_dirent_join(pb->local_abspath, name, scratch_pool),
+                      child_abspath,
                       svn_relpath_join(pb->relpath, name, scratch_pool),
+                      moved_from_relpath,
                       eb->processor, pb->pdb,
                       eb->diff_pristine,
                       eb->cancel_func, eb->cancel_baton,

Modified: subversion/trunk/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff_local.c?rev=1706855&r1=1706854&r2=1706855&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/trunk/subversion/libsvn_wc/diff_local.c Mon Oct  5 15:34:49 2015
@@ -391,9 +391,20 @@ diff_status_callback(void *baton,
 
     if (local_only && (db_status != svn_wc__db_status_deleted))
       {
+        /* Moved from. Relative from diff anchor*/
+        const char *moved_from_relpath = NULL;
+
+        if (status->moved_from_abspath)
+          {
+            moved_from_relpath = svn_dirent_skip_ancestor(
+                                          eb->anchor_abspath,
+                                          status->moved_from_abspath);
+          }
+
         if (db_kind == svn_node_file)
           SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                child_relpath,
+                                               moved_from_relpath,
                                                eb->processor,
                                                eb->cur ? eb->cur->baton : NULL,
                                                FALSE,
@@ -403,6 +414,7 @@ diff_status_callback(void *baton,
         else if (db_kind == svn_node_dir)
           SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
                                               child_relpath, depth_below_here,
+                                              moved_from_relpath,
                                               eb->processor,
                                               eb->cur ? eb->cur->baton : NULL,
                                               FALSE,