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);