Author: neels
Date: Fri Aug 12 23:28:00 2011
New Revision: 1157292

URL: http://svn.apache.org/viewvc?rev=1157292&view=rev
Log:
Show moved-to and moved-from information in 'svn status'.

* subversion/include/svn_client.h (svn_client_status_t),
* subversion/include/svn_wc.h (svn_wc_status3_t):
    To both of these structs, add MOVED_FROM_ABSPATH, MOVED_TO_ABSPATH and
    MOVED_TO_OP_ROOT_ABSPATH.

* subversion/libsvn_client/status.c
  (svn_client_status_dup): Dup new elements of svn_client_status_t.
  (svn_client__create_status): Shallow-copy new elements of svn_wc_status3_t.

* subversion/libsvn_wc/status.c
  (assemble_status): Scan for moved-to and moved-from info.
  (svn_wc_dup_status3): Dup new elements of svn_wc_status3_t.

* subversion/svn/status.c
  (make_relpath):
    New function. Currently only used by print_status() below, but is likely
    to get a better name and bubble up out of this file soon.
  (print_status):
    For the op-roots of the two halves of a local move, show an additional
    info line of the "  > ..." kind. For moved-away items, show the move
    destination, and for moved-here, show the move source, as WC relpaths.


Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/include/svn_wc.h
    subversion/trunk/subversion/libsvn_client/status.c
    subversion/trunk/subversion/libsvn_wc/status.c
    subversion/trunk/subversion/svn/status.c

Modified: subversion/trunk/subversion/include/svn_client.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1157292&r1=1157291&r2=1157292&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Fri Aug 12 23:28:00 2011
@@ -2206,6 +2206,19 @@ typedef struct svn_client_status_t
    * or to other data in future versions. */
   const void *backwards_compatibility_baton;
 
+  /** Set to the local absolute path that this node was moved from, if this
+   * file or directory has been moved here locally. */
+  const char *moved_from_abspath;
+
+  /** Set to the local absolute path that this node was moved to, if this file
+   * or directory has been moved away locally. */
+  const char *moved_to_abspath;
+
+  /* If this file or directory has been moved away locally, set this to the
+   * local absolute path that was the root of the move-away, i.e. to the
+   * op-root of the delete-half of the move operation. */
+  const char *moved_to_op_root_abspath;
+
   /* NOTE! Please update svn_client_status_dup() when adding new fields here. 
*/
 } svn_client_status_t;
 

Modified: subversion/trunk/subversion/include/svn_wc.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=1157292&r1=1157291&r2=1157292&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Fri Aug 12 23:28:00 2011
@@ -3619,6 +3619,19 @@ typedef struct svn_wc_status3_t
 
   /** @} */
 
+  /** Set to the local absolute path that this node was moved from, if this
+   * file or directory has been moved here locally. */
+  const char *moved_from_abspath;
+
+  /** Set to the local absolute path that this node was moved to, if this file
+   * or directory has been moved away locally. */
+  const char *moved_to_abspath;
+
+  /* If this file or directory has been moved away locally, set this to the
+   * local absolute path that was the root of the move-away, i.e. to the
+   * op-root of the delete-half of the move operation. */
+  const char *moved_to_op_root_abspath;
+
   /* NOTE! Please update svn_wc_dup_status3() when adding new fields here. */
 } svn_wc_status3_t;
 

Modified: subversion/trunk/subversion/libsvn_client/status.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/status.c?rev=1157292&r1=1157291&r2=1157292&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/status.c (original)
+++ subversion/trunk/subversion/libsvn_client/status.c Fri Aug 12 23:28:00 2011
@@ -563,6 +563,17 @@ svn_client_status_dup(const svn_client_s
                                                              result_pool);
     }
 
+  if (status->moved_from_abspath)
+    st->moved_from_abspath =
+      apr_pstrdup(result_pool, status->moved_from_abspath);
+
+  if (status->moved_to_abspath)
+    st->moved_to_abspath = apr_pstrdup(result_pool, status->moved_to_abspath);
+
+  if (status->moved_to_op_root_abspath)
+    st->moved_to_op_root_abspath =
+      apr_pstrdup(result_pool, status->moved_to_op_root_abspath);
+
   return st;
 }
 
@@ -667,6 +678,10 @@ svn_client__create_status(svn_client_sta
         (*cst)->node_status = svn_wc_status_conflicted;
     }
 
+  (*cst)->moved_from_abspath = status->moved_from_abspath;
+  (*cst)->moved_to_abspath = status->moved_to_abspath;
+  (*cst)->moved_to_op_root_abspath = status->moved_to_op_root_abspath;
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_wc/status.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/status.c?rev=1157292&r1=1157291&r2=1157292&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/status.c (original)
+++ subversion/trunk/subversion/libsvn_wc/status.c Fri Aug 12 23:28:00 2011
@@ -403,6 +403,9 @@ assemble_status(svn_wc_status3_t **statu
   const char *repos_relpath;
   const char *repos_root_url;
   const char *repos_uuid;
+  const char *moved_from_abspath = NULL;
+  const char *moved_to_abspath = NULL;
+  const char *moved_to_op_root_abspath = NULL;
   svn_filesize_t filesize = (dirent && (dirent->kind == svn_node_file))
                                 ? dirent->filesize
                                 : SVN_INVALID_FILESIZE;
@@ -608,6 +611,24 @@ assemble_status(svn_wc_status3_t **statu
         }
     }
 
+  /* Get moved-to info. */
+  if (info->status == svn_wc__db_status_deleted)
+    SVN_ERR(svn_wc__db_scan_deletion(NULL,
+                                     &moved_to_abspath,
+                                     NULL,
+                                     &moved_to_op_root_abspath,
+                                     db, local_abspath,
+                                     result_pool, scratch_pool));
+
+  /* Get moved-from info. */
+  if (info->status == svn_wc__db_status_added)
+    SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL,
+                                     NULL, NULL, NULL, NULL,
+                                     &moved_from_abspath,
+                                     NULL,
+                                     db, local_abspath,
+                                     result_pool, scratch_pool));
+
   if (node_status == svn_wc_status_normal)
     node_status = text_status;
 
@@ -700,6 +721,10 @@ assemble_status(svn_wc_status3_t **statu
   stat->repos_relpath = repos_relpath;
   stat->repos_uuid = repos_uuid;
 
+  stat->moved_from_abspath = moved_from_abspath;
+  stat->moved_to_abspath = moved_to_abspath;
+  stat->moved_to_op_root_abspath = moved_to_op_root_abspath;
+
   *status = stat;
 
   return SVN_NO_ERROR;
@@ -2591,6 +2616,18 @@ svn_wc_dup_status3(const svn_wc_status3_
     new_stat->repos_uuid
       = apr_pstrdup(pool, orig_stat->repos_uuid);
 
+  if (orig_stat->moved_from_abspath)
+    new_stat->moved_from_abspath
+      = apr_pstrdup(pool, orig_stat->moved_from_abspath);
+
+  if (orig_stat->moved_to_abspath)
+    new_stat->moved_to_abspath
+      = apr_pstrdup(pool, orig_stat->moved_to_abspath);
+
+  if (orig_stat->moved_to_op_root_abspath)
+    new_stat->moved_to_op_root_abspath
+      = apr_pstrdup(pool, orig_stat->moved_to_op_root_abspath);
+
   /* Return the new hotness. */
   return new_stat;
 }

Modified: subversion/trunk/subversion/svn/status.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/status.c?rev=1157292&r1=1157291&r2=1157292&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/status.c (original)
+++ subversion/trunk/subversion/svn/status.c Fri Aug 12 23:28:00 2011
@@ -124,6 +124,54 @@ generate_status_desc(enum svn_wc_status_
     }
 }
 
+/* Make a relative path containing '..' elements as needed.
+   RELATIVE_TO_PATH must be the path to a directory (not a file!) and
+   TARGET_PATH must be the path to any file or directory. Both
+   RELATIVE_TO_PATH and TARGET_PATH must be based on the same parent path,
+   i.e. they can either both be absolute or they can both be relative to the
+   same parent directory. Both paths are expected to be canonical.
+   
+   If above conditions are met, a relative path that leads to TARGET_ABSPATH
+   from RELATIVE_TO_PATH is returned, but there is no error checking involved.
+   
+   The returned path is allocated from RESULT_POOL, all other allocations are
+   made in SCRATCH_POOL. */
+static const char *
+make_relpath(const char *relative_to_path,
+             const char *target_path,
+             apr_pool_t *result_pool,
+             apr_pool_t *scratch_pool)
+{
+  const char *la;
+  const char *parent_dir_els = "";
+
+  /* An example:
+   *  relative_to_path = /a/b/c
+   *  target_path      = /a/x/y/z
+   *  result           = ../../x/y/z */
+
+  /* Skip the common ancestor of both paths, here '/a'. */
+  la = svn_dirent_get_longest_ancestor(relative_to_path, target_path,
+                                       scratch_pool);
+  relative_to_path = svn_dirent_skip_ancestor(la, relative_to_path);
+  target_path = svn_dirent_skip_ancestor(la, target_path);
+
+  /* In above example, we'd now have:
+   *  relative_to_path = b/c
+   *  target_path      = x/y/z */
+
+  /* Count the elements of relative_to_path and prepend as many '..' elements
+   * to target_path. */
+  while (*relative_to_path)
+    {
+      svn_dirent_split(&relative_to_path, NULL, relative_to_path,
+                       scratch_pool);
+      parent_dir_els = svn_dirent_join(parent_dir_els, "..", scratch_pool);
+    }
+
+  return svn_dirent_join(parent_dir_els, target_path, result_pool);
+}
+
 
 /* Print STATUS and PATH in a format determined by DETAILED and
    SHOW_LAST_COMMITTED. */
@@ -143,6 +191,8 @@ print_status(const char *path,
   enum svn_wc_status_kind prop_status = status->prop_status;
   char tree_status_code = ' ';
   const char *tree_desc_line = "";
+  const char *moved_from_line = "";
+  const char *moved_to_line = "";
 
   /* For historic reasons svn ignores the property status for added nodes, even
      if these nodes were copied and have local property changes.
@@ -211,6 +261,35 @@ print_status(const char *path,
         (*prop_conflicts)++;
     }
 
+  if (status->moved_from_abspath)
+    {
+      const char *cwd;
+      const char *relpath;
+      SVN_ERR(svn_dirent_get_absolute(&cwd, "", pool));
+      relpath = make_relpath(cwd, status->moved_from_abspath, pool, pool);
+      relpath = svn_dirent_local_style(relpath, pool);
+      moved_from_line = apr_psprintf(pool,
+                                     "\n   >      moved from %s",
+                                     relpath);
+    }
+
+  /* Only print an extra moved-to line for the op-root of a move-away.
+   * As each and every child node of a deleted tree is printed in status
+   * output, each of them would be "duplicated" with a moved-to line. */
+  if (status->moved_to_abspath
+      && status->moved_to_op_root_abspath
+      && 0 == strcmp(status->moved_to_op_root_abspath,
+                     status->moved_to_abspath))
+    {
+      const char *cwd;
+      const char *relpath;
+      SVN_ERR(svn_dirent_get_absolute(&cwd, "", pool));
+      relpath = make_relpath(cwd, status->moved_to_abspath, pool, pool);
+      relpath = svn_dirent_local_style(relpath, pool);
+      moved_to_line = apr_psprintf(pool, "\n>         moved to %s",
+                                   relpath);
+    }
+
   if (detailed)
     {
       char ood_status, lock_status;
@@ -273,7 +352,7 @@ print_status(const char *path,
 
           SVN_ERR
             (svn_cmdline_printf(pool,
-                                "%c%c%c%c%c%c%c %c   %6s   %6s %-12s %s%s\n",
+                                "%c%c%c%c%c%c%c %c   %6s   %6s %-12s 
%s%s%s%s\n",
                                 generate_status_code(combined_status(status)),
                                 generate_status_code(prop_status),
                                 status->wc_is_locked ? 'L' : ' ',
@@ -286,11 +365,13 @@ print_status(const char *path,
                                 commit_rev,
                                 commit_author,
                                 path,
+                                moved_to_line,
+                                moved_from_line,
                                 tree_desc_line));
         }
       else
         SVN_ERR(
-           svn_cmdline_printf(pool, "%c%c%c%c%c%c%c %c   %6s   %s%s\n",
+           svn_cmdline_printf(pool, "%c%c%c%c%c%c%c %c   %6s   %s%s%s%s\n",
                               generate_status_code(combined_status(status)),
                               generate_status_code(prop_status),
                               status->wc_is_locked ? 'L' : ' ',
@@ -301,11 +382,13 @@ print_status(const char *path,
                               ood_status,
                               working_rev,
                               path,
+                              moved_to_line,
+                              moved_from_line,
                               tree_desc_line));
     }
   else
     SVN_ERR(
-       svn_cmdline_printf(pool, "%c%c%c%c%c%c%c %s%s\n",
+       svn_cmdline_printf(pool, "%c%c%c%c%c%c%c %s%s%s%s\n",
                           generate_status_code(combined_status(status)),
                           generate_status_code(prop_status),
                           status->wc_is_locked ? 'L' : ' ',
@@ -315,6 +398,8 @@ print_status(const char *path,
                            ? 'K' : ' '),
                           tree_status_code,
                           path,
+                          moved_to_line,
+                          moved_from_line,
                           tree_desc_line));
 
   return svn_cmdline_fflush(stdout);


Reply via email to