Index: subversion/svn/cl.h =================================================================== --- subversion/svn/cl.h (revision 39024) +++ subversion/svn/cl.h (working copy) @@ -365,7 +365,7 @@ svn_cl__time_cstring_to_human_cstring(const char * apr_pool_t *pool); -/* Print STATUS for PATH to stdout for human consumption. Prints in +/* Print STATUS for LOCAL_ABSPATH to stdout for human consumption. Prints in abbreviated format by default, or DETAILED format if flag is set. When DETAILED is set, use SHOW_LAST_COMMITTED to toggle display of @@ -377,7 +377,7 @@ svn_cl__time_cstring_to_human_cstring(const char * When DETAILED is set, and REPOS_LOCKS is set, treat missing repository locks as broken WC locks. */ svn_error_t * -svn_cl__print_status(const char *path, +svn_cl__print_status(const char *local_abspath, const svn_wc_status2_t *status, svn_boolean_t detailed, svn_boolean_t show_last_committed, @@ -389,7 +389,7 @@ svn_error_t * /* Print STATUS for PATH in XML to stdout. Use POOL for temporary allocations. */ svn_error_t * -svn_cl__print_status_xml(const char *path, +svn_cl__print_status_xml(const char *local_abspath, const svn_wc_status2_t *status, apr_pool_t *pool); Index: subversion/svn/status.c =================================================================== --- subversion/svn/status.c (revision 39024) +++ subversion/svn/status.c (working copy) @@ -237,7 +237,7 @@ print_status(const char *path, svn_error_t * -svn_cl__print_status_xml(const char *path, +svn_cl__print_status_xml(const char *local_abspath, const svn_wc_status2_t *status, apr_pool_t *pool) { @@ -249,7 +249,8 @@ svn_error_t * return SVN_NO_ERROR; svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry", - "path", svn_dirent_local_style(path, pool), NULL); + "path", svn_dirent_local_style(local_abspath, pool), + NULL); att_hash = apr_hash_make(pool); apr_hash_set(att_hash, "item", APR_HASH_KEY_STRING, @@ -295,7 +296,7 @@ svn_error_t * else return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL, _("'%s' has lock token, but no lock owner"), - svn_dirent_local_style(path, pool)); + svn_dirent_local_style(local_abspath, pool)); svn_cl__xml_tagged_cdata(&sb, pool, "comment", status->entry->lock_comment); @@ -357,7 +358,7 @@ svn_error_t * /* Called by status-cmd.c */ svn_error_t * -svn_cl__print_status(const char *path, +svn_cl__print_status(const char *local_abspath, const svn_wc_status2_t *status, svn_boolean_t detailed, svn_boolean_t show_last_committed, @@ -365,13 +366,26 @@ svn_error_t * svn_boolean_t repos_locks, apr_pool_t *pool) { + const char *path_prefix; + const char *path_local; + if (! status || (skip_unrecognized && !(status->entry || status->tree_conflict)) || (status->text_status == svn_wc_status_none && status->repos_text_status == svn_wc_status_none)) return SVN_NO_ERROR; - return print_status(svn_dirent_local_style(path, pool), + apr_filepath_get((char **)&path_prefix, 0 /* flags */, pool); + path_local = svn_dirent_is_child(path_prefix, local_abspath, pool); + if (!path_local) + { + if (strcmp(local_abspath, path_prefix) == 0) + path_local = "."; + else + path_local = local_abspath; + } + + return print_status(svn_dirent_local_style(path_local, pool), detailed, show_last_committed, repos_locks, status, pool); } Index: subversion/svn/status-cmd.c =================================================================== --- subversion/svn/status-cmd.c (revision 39024) +++ subversion/svn/status-cmd.c (working copy) @@ -65,7 +65,7 @@ struct status_baton struct status_cache { - const char *path; + const char *local_abspath; svn_wc_status2_t *status; }; @@ -111,16 +111,16 @@ print_finish_target_xml(svn_revnum_t repos_rev, the user. Called by both print_status() and svn_cl__status(). */ static svn_error_t * print_status_normal_or_xml(void *baton, - const char *path, + const char *local_abspath, const svn_wc_status2_t *status, apr_pool_t *pool) { struct status_baton *sb = baton; if (sb->xml_mode) - return svn_cl__print_status_xml(path, status, pool); + return svn_cl__print_status_xml(local_abspath, status, pool); else - return svn_cl__print_status(path, status, sb->detailed, + return svn_cl__print_status(local_abspath, status, sb->detailed, sb->show_last_committed, sb->skip_unrecognized, sb->repos_locks, @@ -131,7 +131,7 @@ print_status_normal_or_xml(void *baton, /* A status callback function for printing STATUS for PATH. */ static svn_error_t * print_status(void *baton, - const char *path, + const char *local_abspath, const svn_wc_status2_t *status, apr_pool_t *pool) { @@ -146,7 +146,7 @@ print_status(void *baton, apr_array_header_t *path_array; const char *cl_key = apr_pstrdup(sb->cl_pool, status->entry->changelist); struct status_cache *scache = apr_pcalloc(sb->cl_pool, sizeof(*scache)); - scache->path = apr_pstrdup(sb->cl_pool, path); + scache->local_abspath = apr_pstrdup(sb->cl_pool, local_abspath); scache->status = svn_wc_dup_status2(status, sb->cl_pool); path_array = (apr_array_header_t *) @@ -163,7 +163,7 @@ print_status(void *baton, return SVN_NO_ERROR; } - return print_status_normal_or_xml(baton, path, status, pool); + return print_status_normal_or_xml(baton, local_abspath, status, pool); } /* This implements the `svn_opt_subcommand_t' interface. */ @@ -294,7 +294,7 @@ svn_cl__status(apr_getopt_t *os, { struct status_cache *scache = APR_ARRAY_IDX(path_array, j, struct status_cache *); - SVN_ERR(print_status_normal_or_xml(&sb, scache->path, + SVN_ERR(print_status_normal_or_xml(&sb, scache->local_abspath, scache->status, pool)); } Index: subversion/include/svn_wc.h =================================================================== --- subversion/include/svn_wc.h (revision 39024) +++ subversion/include/svn_wc.h (working copy) @@ -3374,7 +3374,7 @@ svn_wc_status(svn_wc_status_t **status, /** - * A callback for reporting a @a status about @a path. + * A callback for reporting a @a status about @a local_abspath. * * @a baton is a closure object; it should be provided by the * implementation, and passed by the caller. @@ -3389,7 +3389,7 @@ svn_wc_status(svn_wc_status_t **status, * @since New in 1.7. */ typedef svn_error_t *(*svn_wc_status_func4_t)(void *baton, - const char *path, + const char *local_abspath, const svn_wc_status2_t *status, apr_pool_t *scratch_pool); Index: subversion/libsvn_wc/status.c =================================================================== --- subversion/libsvn_wc/status.c (revision 39024) +++ subversion/libsvn_wc/status.c (working copy) @@ -155,8 +155,8 @@ struct dir_baton svn_boolean_t text_changed; /* Working copy status structures for children of this directory. - This hash maps const char * paths (relative to the root of the - edit) to svn_wc_status2_t * status items. */ + This hash maps absolute const char * paths to svn_wc_status2_t * status + items. */ apr_hash_t *statii; /* The pool in which this baton itself is allocated. */ @@ -625,7 +625,7 @@ send_status_structure(const char *path, path_kind, path_special, get_all, is_ignored, repos_locks, repos_root, pool, pool)); if (statstruct && (status_func)) - return (*status_func)(status_baton, path, statstruct, pool); + return (*status_func)(status_baton, local_abspath, statstruct, pool); return SVN_NO_ERROR; } @@ -1250,7 +1250,7 @@ tweak_statushash(void *baton, SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); /* Is PATH already a hash-key? */ - statstruct = apr_hash_get(statushash, path, APR_HASH_KEY_STRING); + statstruct = apr_hash_get(statushash, local_abspath, APR_HASH_KEY_STRING); /* If not, make it so. */ if (! statstruct) @@ -1272,7 +1272,7 @@ tweak_statushash(void *baton, /* Use the public API to get a statstruct, and put it into the hash. */ SVN_ERR(internal_status(&statstruct, db, local_abspath, pool, pool)); statstruct->repos_lock = repos_lock; - apr_hash_set(statushash, apr_pstrdup(pool, path), + apr_hash_set(statushash, apr_pstrdup(pool, local_abspath), APR_HASH_KEY_STRING, statstruct); } @@ -1361,8 +1361,12 @@ find_dir_url(const struct dir_baton *db, apr_pool_ { const char *url; struct dir_baton *pb = db->parent_baton; - const svn_wc_status2_t *status = apr_hash_get(pb->statii, db->name, - APR_HASH_KEY_STRING); + const char *dir_abspath; + const svn_wc_status2_t *status; + + svn_error_clear(svn_dirent_get_absolute(&dir_abspath, db->path, pool)); + status = apr_hash_get(pb->statii, dir_abspath, APR_HASH_KEY_STRING); + /* Note that status->entry->url is NULL in the case of a missing * directory, which means we need to recurse up another level to * get a useful URL. */ @@ -1392,9 +1396,12 @@ make_dir_baton(void **dir_baton, struct dir_baton *d = apr_pcalloc(pool, sizeof(*d)); const char *full_path; const svn_wc_status2_t *status_in_parent; + const char *local_abspath; SVN_ERR_ASSERT(path || (! pb)); + SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); + /* Construct the full path of this directory. */ if (pb) full_path = svn_dirent_join(eb->anchor, path, pool); @@ -1437,7 +1444,8 @@ make_dir_baton(void **dir_baton, /* Get the status for this path's children. Of course, we only want to do this if the path is versioned as a directory. */ if (pb) - status_in_parent = apr_hash_get(pb->statii, d->path, APR_HASH_KEY_STRING); + status_in_parent = apr_hash_get(pb->statii, local_abspath, + APR_HASH_KEY_STRING); else status_in_parent = eb->anchor_status; @@ -1471,7 +1479,8 @@ make_dir_baton(void **dir_baton, NULL, pool)); /* If we found a depth here, it should govern. */ - this_dir_status = apr_hash_get(d->statii, d->path, APR_HASH_KEY_STRING); + this_dir_status = apr_hash_get(d->statii, local_abspath, + APR_HASH_KEY_STRING); if (this_dir_status && this_dir_status->entry && (d->depth == svn_depth_unknown || d->depth > status_in_parent->entry->depth)) @@ -1634,13 +1643,9 @@ handle_statii(struct edit_baton *eb, /* Loop over all the statuses still in our hash, handling each one. */ for (hi = apr_hash_first(pool, statii); hi; hi = apr_hash_next(hi)) { - const void *key; - void *val; - svn_wc_status2_t *status; + const char *local_abspath = svn_apr_hash_index_key(hi); + svn_wc_status2_t *status = svn_apr_hash_index_val(hi); - apr_hash_this(hi, &key, NULL, &val); - status = val; - /* Clear the subpool. */ svn_pool_clear(subpool); @@ -1654,8 +1659,8 @@ handle_statii(struct edit_baton *eb, { svn_wc_adm_access_t *dir_access; - SVN_ERR(svn_wc_adm_retrieve(&dir_access, eb->adm_access, - key, subpool)); + dir_access = svn_wc__adm_retrieve_internal2(eb->db, local_abspath, + subpool); SVN_ERR(get_dir_status(eb, dir_entry, dir_access, NULL, ignores, depth, eb->get_all, @@ -1666,7 +1671,8 @@ handle_statii(struct edit_baton *eb, if (dir_was_deleted) status->repos_text_status = svn_wc_status_deleted; if (svn_wc__is_sendable_status(status, eb->no_ignore, eb->get_all)) - SVN_ERR((eb->status_func)(eb->status_baton, key, status, subpool)); + SVN_ERR((eb->status_func)(eb->status_baton, local_abspath, status, + subpool)); } /* Destroy the subpool. */ @@ -1865,7 +1871,10 @@ close_directory(void *dir_baton, struct dir_baton *db = dir_baton; struct dir_baton *pb = db->parent_baton; struct edit_baton *eb = db->edit_baton; + const char *dir_abspath; + SVN_ERR(svn_dirent_get_absolute(&dir_abspath, db->path, pool)); + /* If nothing has changed and directory has no out of date descendants, return. */ if (db->added || db->prop_changed || db->text_changed @@ -1931,7 +1940,7 @@ close_directory(void *dir_baton, const svn_wc_status2_t *dir_status; /* See if the directory was deleted or replaced. */ - dir_status = apr_hash_get(pb->statii, db->path, APR_HASH_KEY_STRING); + dir_status = apr_hash_get(pb->statii, dir_abspath, APR_HASH_KEY_STRING); if (dir_status && ((dir_status->repos_text_status == svn_wc_status_deleted) || (dir_status->repos_text_status == svn_wc_status_replaced))) @@ -1943,9 +1952,9 @@ close_directory(void *dir_baton, pool)); if (dir_status && svn_wc__is_sendable_status(dir_status, eb->no_ignore, eb->get_all)) - SVN_ERR((eb->status_func)(eb->status_baton, db->path, dir_status, + SVN_ERR((eb->status_func)(eb->status_baton, dir_abspath, dir_status, pool)); - apr_hash_set(pb->statii, db->path, APR_HASH_KEY_STRING, NULL); + apr_hash_set(pb->statii, dir_abspath, APR_HASH_KEY_STRING, NULL); } else if (! pb) { @@ -1955,8 +1964,12 @@ close_directory(void *dir_baton, { const svn_wc_status2_t *tgt_status; const char *path = svn_dirent_join(eb->anchor, eb->target, pool); + const char *local_abspath; - tgt_status = apr_hash_get(db->statii, path, APR_HASH_KEY_STRING); + SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); + + tgt_status = apr_hash_get(db->statii, local_abspath, + APR_HASH_KEY_STRING); if (tgt_status) { if (tgt_status->entry @@ -1974,8 +1987,8 @@ close_directory(void *dir_baton, } if (svn_wc__is_sendable_status(tgt_status, eb->no_ignore, eb->get_all)) - SVN_ERR((eb->status_func)(eb->status_baton, path, tgt_status, - pool)); + SVN_ERR((eb->status_func)(eb->status_baton, local_abspath, + tgt_status, pool)); } } else @@ -1987,7 +2000,7 @@ close_directory(void *dir_baton, db->statii, FALSE, eb->default_depth, pool)); if (svn_wc__is_sendable_status(eb->anchor_status, eb->no_ignore, eb->get_all)) - SVN_ERR((eb->status_func)(eb->status_baton, db->path, + SVN_ERR((eb->status_func)(eb->status_baton, dir_abspath, eb->anchor_status, pool)); eb->anchor_status = NULL; }