You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/10/11 21:52:46 UTC
svn commit: r1182053 [18/30] - in /subversion/branches/svn_mutex: ./ build/
build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ contrib/client-side/
contrib/hook-scripts/enforcer/ contrib/server-side/ notes/ notes/merge-t...
Modified: subversion/branches/svn_mutex/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_wc/status.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_wc/status.c Tue Oct 11 19:52:34 2011
@@ -184,6 +184,9 @@ struct dir_baton
/* The pool in which this baton itself is allocated. */
apr_pool_t *pool;
+ /* The repository root relative path to this item in the repository. */
+ const char *repos_relpath;
+
/* out-of-date info corresponding to ood_* fields in svn_wc_status3_t. */
svn_node_kind_t ood_kind;
svn_revnum_t ood_changed_rev;
@@ -223,6 +226,9 @@ struct file_baton
the code that syncs up the adm dir and working copy. */
svn_boolean_t prop_changed;
+ /* The repository root relative path to this item in the repository. */
+ const char *repos_relpath;
+
/* out-of-date info corresponding to ood_* fields in svn_wc_status3_t. */
svn_node_kind_t ood_kind;
svn_revnum_t ood_changed_rev;
@@ -248,9 +254,10 @@ read_info(const struct svn_wc__db_info_t
SVN_ERR(svn_wc__db_read_info(&mtb->status, &mtb->kind,
&mtb->revnum, &mtb->repos_relpath,
- &mtb->repos_root_url, NULL, &mtb->changed_rev,
- &mtb->changed_date, &mtb->changed_author,
- &mtb->depth, &checksum, NULL, NULL, NULL, NULL,
+ &mtb->repos_root_url, &mtb->repos_uuid,
+ &mtb->changed_rev, &mtb->changed_date,
+ &mtb->changed_author, &mtb->depth,
+ &checksum, NULL, NULL, NULL, NULL,
NULL, &mtb->lock, &mtb->recorded_size,
&mtb->recorded_mod_time, &mtb->changelist,
&mtb->conflicted, &mtb->op_root,
@@ -265,19 +272,95 @@ read_info(const struct svn_wc__db_info_t
happy... (It might be completely unrelated, but...) */
if (mtb->have_base
&& (mtb->status == svn_wc__db_status_added
- || mtb->status == svn_wc__db_status_deleted))
+ || mtb->status == svn_wc__db_status_deleted
+ || mtb->kind == svn_kind_file))
{
+ svn_boolean_t update_root;
+ svn_wc__db_lock_t **lock_arg = NULL;
+
+ if (mtb->status == svn_wc__db_status_added
+ || mtb->status == svn_wc__db_status_deleted)
+ lock_arg = &mtb->lock;
+
SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
- &mtb->lock, NULL, NULL,
+ lock_arg, NULL, &update_root,
+ db, local_abspath,
+ result_pool, scratch_pool));
+
+ mtb->file_external = (update_root && mtb->kind == svn_kind_file);
+
+ if (mtb->status == svn_wc__db_status_deleted)
+ {
+ const char *moved_to_abspath;
+ const char *moved_to_op_root_abspath;
+
+ /* NOTE: we can't use op-root-ness as a condition here since a base
+ * node can be the root of a move and still not be an explicit
+ * op-root (having a working node with op_depth == pathelements).
+ *
+ * Both these (almost identical) situations showcase this:
+ * svn mv a/b bb
+ * svn del a
+ * and
+ * svn mv a aa
+ * svn mv aa/b bb
+ * In both, 'bb' is moved from 'a/b', but 'a/b' has no op_depth>0
+ * node at all, as its parent 'a' is locally deleted. */
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL,
+ &moved_to_abspath,
+ NULL,
+ &moved_to_op_root_abspath,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+ if (moved_to_abspath != NULL
+ && moved_to_op_root_abspath != NULL
+ && strcmp(moved_to_abspath, moved_to_op_root_abspath) == 0)
+ {
+ mtb->moved_to_abspath = apr_pstrdup(result_pool,
+ moved_to_abspath);
+ }
+ /* ### ^^^ THIS SUCKS. For at least two reasons:
+ * 1) We scan the node deletion and that's technically not necessary.
+ * We'd be fine to know if this is an actual root of a move.
+ * 2) From the elaborately calculated results, we backwards-guess
+ * whether this is a root.
+ * It works ok, and this code only gets called when a node is an
+ * explicit target of a 'status'. But it would be better to do this
+ * differently.
+ * We could return moved-to via svn_wc__db_base_get_info() (called
+ * just above), but as moved-to is only intended to be returned for
+ * roots of a move, that doesn't fit too well. */
+ }
+ }
+
+ /* ### svn_wc__db_read_info() could easily return the moved-here flag. But
+ * for now... (The per-dir query for recursive status is far more optimal.)
+ * Note that this actually scans around to get the full path, for a bool.
+ * This bool then gets returned, later is evaluated, and if true leads to
+ * the same paths being scanned again. We'd want to obtain this bool here as
+ * cheaply as svn_wc__db_read_children_info() does. */
+ if (mtb->status == svn_wc__db_status_added)
+ {
+ const char *moved_from_abspath = NULL;
+ svn_wc__db_status_t status;
+
+ SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ &moved_from_abspath,
+ NULL,
db, local_abspath,
result_pool, scratch_pool));
+ mtb->moved_here = (moved_from_abspath != NULL);
+ mtb->incomplete = (status == svn_wc__db_status_incomplete);
}
mtb->has_checksum = (checksum != NULL);
#ifdef HAVE_SYMLINK
- if (mtb->had_props || mtb->props_mod)
+ if (mtb->kind == svn_kind_file
+ && (mtb->had_props || mtb->props_mod))
{
apr_hash_t *properties;
@@ -304,9 +387,11 @@ read_info(const struct svn_wc__db_info_t
static svn_error_t *
get_repos_root_url_relpath(const char **repos_relpath,
const char **repos_root_url,
+ const char **repos_uuid,
const struct svn_wc__db_info_t *info,
const char *parent_repos_relpath,
const char *parent_repos_root_url,
+ const char *parent_repos_uuid,
svn_wc__db_t *db,
const char *local_abspath,
apr_pool_t *result_pool,
@@ -316,6 +401,7 @@ get_repos_root_url_relpath(const char **
{
*repos_relpath = info->repos_relpath;
*repos_root_url = info->repos_root_url;
+ *repos_uuid = info->repos_uuid;
}
else if (parent_repos_relpath && parent_repos_root_url)
{
@@ -324,18 +410,20 @@ get_repos_root_url_relpath(const char **
NULL),
result_pool);
*repos_root_url = parent_repos_root_url;
+ *repos_uuid = parent_repos_uuid;
}
else if (info->status == svn_wc__db_status_added)
{
SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
repos_relpath, repos_root_url,
- NULL, NULL, NULL, NULL, NULL,
- db, local_abspath,
+ repos_uuid, NULL, NULL, NULL, NULL,
+ NULL, NULL, db, local_abspath,
result_pool, scratch_pool));
}
else if (info->have_base)
{
- SVN_ERR(svn_wc__db_scan_base_repos(repos_relpath, repos_root_url, NULL,
+ SVN_ERR(svn_wc__db_scan_base_repos(repos_relpath, repos_root_url,
+ repos_uuid,
db, local_abspath,
result_pool, scratch_pool));
}
@@ -343,6 +431,7 @@ get_repos_root_url_relpath(const char **
{
*repos_relpath = NULL;
*repos_root_url = NULL;
+ *repos_uuid = NULL;
}
return SVN_NO_ERROR;
}
@@ -357,7 +446,7 @@ internal_status(svn_wc_status3_t **statu
/* Fill in *STATUS for LOCAL_ABSPATH, using DB. Allocate *STATUS in
RESULT_POOL and use SCRATCH_POOL for temporary allocations.
- PARENT_REPOS_ROOT_URL and PARENT_REPOS_RELPATH are the the repository root
+ PARENT_REPOS_ROOT_URL and PARENT_REPOS_RELPATH are the repository root
and repository relative path of the parent of LOCAL_ABSPATH or NULL if
LOCAL_ABSPATH doesn't have a versioned parent directory.
@@ -378,6 +467,7 @@ assemble_status(svn_wc_status3_t **statu
const char *local_abspath,
const char *parent_repos_root_url,
const char *parent_repos_relpath,
+ const char *parent_repos_uuid,
const struct svn_wc__db_info_t *info,
const svn_io_dirent2_t *dirent,
svn_boolean_t get_all,
@@ -393,6 +483,8 @@ assemble_status(svn_wc_status3_t **statu
svn_error_t *err;
const char *repos_relpath;
const char *repos_root_url;
+ const char *repos_uuid;
+ const char *moved_from_abspath = NULL;
svn_filesize_t filesize = (dirent && (dirent->kind == svn_node_file))
? dirent->filesize
: SVN_INVALID_FILESIZE;
@@ -411,22 +503,18 @@ assemble_status(svn_wc_status3_t **statu
else
{
/* A node is switched if it doesn't have the implied repos_relpath */
- const char *name = svn_relpath__is_child(parent_repos_relpath,
- info->repos_relpath, NULL);
- switched_p = !name || (strcmp(name, svn_dirent_basename(local_abspath, NULL)) != 0);
- }
-
- /* Examine whether our target is missing or obstructed or missing.
-
- While we are not completely in single-db mode yet, data about
- obstructed or missing nodes might be incomplete here. This is
- reported by svn_wc_db_status_obstructed_XXXX. In single-db
- mode these obstructions are no longer reported and we have
- to detect obstructions by looking at the on disk status in DIRENT.
- */
- if (info->kind == svn_wc__db_kind_dir)
+ const char *name = svn_relpath_skip_ancestor(parent_repos_relpath,
+ info->repos_relpath);
+ switched_p = !name || (strcmp(name,
+ svn_dirent_basename(local_abspath, NULL))
+ != 0);
+ }
+
+ /* Examine whether our target is missing or obstructed. To detect
+ * obstructions, we have to look at the on-disk status in DIRENT. */
+ if (info->kind == svn_kind_dir)
{
- if (info->status == svn_wc__db_status_incomplete)
+ if (info->status == svn_wc__db_status_incomplete || info->incomplete)
{
/* Highest precedence. */
node_status = svn_wc_status_incomplete;
@@ -487,7 +575,7 @@ assemble_status(svn_wc_status3_t **statu
If it was changed, then the subdir is incomplete or missing/obstructed.
*/
- if (info->kind != svn_wc__db_kind_dir
+ if (info->kind != svn_kind_dir
&& node_status == svn_wc_status_normal)
{
svn_boolean_t text_modified_p = FALSE;
@@ -499,8 +587,8 @@ assemble_status(svn_wc_status3_t **statu
precedence over M. */
/* If the entry is a file, check for textual modifications */
- if ((info->kind == svn_wc__db_kind_file
- || info->kind == svn_wc__db_kind_symlink)
+ if ((info->kind == svn_kind_file
+ || info->kind == svn_kind_symlink)
#ifdef HAVE_SYMLINK
&& (info->special == (dirent && dirent->special))
#endif /* HAVE_SYMLINK */
@@ -528,7 +616,7 @@ assemble_status(svn_wc_status3_t **statu
if (err)
{
- if (!APR_STATUS_IS_EACCES(err->apr_err))
+ if (err->apr_err != SVN_ERR_WC_PATH_ACCESS_DENIED)
return svn_error_trace(err);
/* An access denied is very common on Windows when another
@@ -575,7 +663,7 @@ assemble_status(svn_wc_status3_t **statu
{
if (!info->op_root)
copied = TRUE; /* And keep status normal */
- else if (info->kind == svn_wc__db_kind_file
+ else if (info->kind == svn_kind_file
&& !info->have_base && !info->have_more_work)
{
/* Simple addition or copy, no replacement */
@@ -595,9 +683,19 @@ assemble_status(svn_wc_status3_t **statu
else if (schedule == svn_wc_schedule_replace)
node_status = svn_wc_status_replaced;
}
+
+ /* Get moved-from info (only for potential op-roots of a move). */
+ if (info->moved_here && info->op_root)
+ 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;
@@ -623,9 +721,11 @@ assemble_status(svn_wc_status3_t **statu
return SVN_NO_ERROR;
}
- SVN_ERR(get_repos_root_url_relpath(&repos_relpath, &repos_root_url, info,
+ SVN_ERR(get_repos_root_url_relpath(&repos_relpath, &repos_root_url,
+ &repos_uuid, info,
parent_repos_relpath,
parent_repos_root_url,
+ parent_repos_uuid,
db, local_abspath,
scratch_pool, scratch_pool));
@@ -635,14 +735,14 @@ assemble_status(svn_wc_status3_t **statu
switch (info->kind)
{
- case svn_wc__db_kind_dir:
+ case svn_kind_dir:
stat->kind = svn_node_dir;
break;
- case svn_wc__db_kind_file:
- case svn_wc__db_kind_symlink:
+ case svn_kind_file:
+ case svn_kind_symlink:
stat->kind = svn_node_file;
break;
- case svn_wc__db_kind_unknown:
+ case svn_kind_unknown:
default:
stat->kind = svn_node_unknown;
}
@@ -686,6 +786,12 @@ assemble_status(svn_wc_status3_t **statu
stat->changelist = info->changelist;
stat->repos_root_url = repos_root_url;
stat->repos_relpath = repos_relpath;
+ stat->repos_uuid = repos_uuid;
+
+ stat->moved_from_abspath = moved_from_abspath;
+ stat->moved_to_abspath = info->moved_to_abspath;
+
+ stat->file_external = info->file_external;
*status = stat;
@@ -704,36 +810,23 @@ static svn_error_t *
assemble_unversioned(svn_wc_status3_t **status,
svn_wc__db_t *db,
const char *local_abspath,
- svn_node_kind_t path_kind,
+ const svn_io_dirent2_t *dirent,
+ svn_boolean_t tree_conflicted,
svn_boolean_t is_ignored,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_wc_status3_t *stat;
- const svn_wc_conflict_description2_t *tree_conflict;
- svn_error_t *err;
-
- /* Find out whether the path is a tree conflict victim.
- This function will set tree_conflict to NULL if the path
- is not a victim. */
- err = svn_wc__db_op_read_tree_conflict(&tree_conflict,
- db, local_abspath,
- scratch_pool, scratch_pool);
-
- if (path_kind == svn_node_dir &&
- err &&
- err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
- svn_error_clear(err);
- else
- SVN_ERR(err);
/* return a fairly blank structure. */
- stat = apr_pcalloc(result_pool, sizeof(**status));
+ stat = apr_pcalloc(result_pool, sizeof(*stat));
/*stat->versioned = FALSE;*/
stat->kind = svn_node_unknown; /* not versioned */
stat->depth = svn_depth_unknown;
- stat->filesize = SVN_INVALID_FILESIZE;
+ stat->filesize = (dirent && dirent->kind == svn_node_file)
+ ? dirent->filesize
+ : SVN_INVALID_FILESIZE;
stat->node_status = svn_wc_status_none;
stat->text_status = svn_wc_status_none;
stat->prop_status = svn_wc_status_none;
@@ -746,18 +839,18 @@ assemble_unversioned(svn_wc_status3_t **
to matching an ignore-pattern), the node_status is set to
svn_wc_status_ignored. Otherwise the node_status is set to
svn_wc_status_unversioned. */
- if (path_kind != svn_node_none)
+ if (dirent && dirent->kind != svn_node_none)
{
if (is_ignored)
stat->node_status = svn_wc_status_ignored;
else
stat->node_status = svn_wc_status_unversioned;
}
- else if (tree_conflict != NULL)
+ else if (tree_conflicted)
{
/* If this path has no entry, is NOT present on disk, and IS a
- tree conflict victim, count it as missing. */
- stat->node_status = svn_wc_status_missing;
+ tree conflict victim, report it as conflicted. */
+ stat->node_status = svn_wc_status_conflicted;
}
stat->revision = SVN_INVALID_REVNUM;
@@ -767,7 +860,7 @@ assemble_unversioned(svn_wc_status3_t **
/* For the case of an incoming delete to a locally deleted path during
an update, we get a tree conflict. */
- stat->conflicted = (tree_conflict != NULL);
+ stat->conflicted = tree_conflicted;
stat->changelist = NULL;
*status = stat;
@@ -783,6 +876,7 @@ send_status_structure(const struct walk_
const char *local_abspath,
const char *parent_repos_root_url,
const char *parent_repos_relpath,
+ const char *parent_repos_uuid,
const struct svn_wc__db_info_t *info,
const svn_io_dirent2_t *dirent,
svn_boolean_t get_all,
@@ -796,11 +890,13 @@ send_status_structure(const struct walk_
/* Check for a repository lock. */
if (wb->repos_locks)
{
- const char *repos_relpath, *repos_root_url;
+ const char *repos_relpath, *repos_root_url, *repos_uuid;
SVN_ERR(get_repos_root_url_relpath(&repos_relpath, &repos_root_url,
+ &repos_uuid,
info, parent_repos_relpath,
parent_repos_root_url,
+ parent_repos_uuid,
wb->db, local_abspath,
scratch_pool, scratch_pool));
if (repos_relpath)
@@ -816,6 +912,7 @@ send_status_structure(const struct walk_
SVN_ERR(assemble_status(&statstruct, wb->db, local_abspath,
parent_repos_root_url, parent_repos_relpath,
+ parent_repos_uuid,
info, dirent, get_all, wb->ignore_text_mods,
repos_lock, scratch_pool, scratch_pool));
@@ -930,7 +1027,8 @@ is_external_path(apr_hash_t *externals,
static svn_error_t *
send_unversioned_item(const struct walk_status_baton *wb,
const char *local_abspath,
- svn_node_kind_t path_kind,
+ const svn_io_dirent2_t *dirent,
+ svn_boolean_t tree_conflicted,
const apr_array_header_t *patterns,
svn_boolean_t no_ignore,
svn_wc_status_func4_t status_func,
@@ -947,7 +1045,7 @@ send_unversioned_item(const struct walk_
SVN_ERR(assemble_unversioned(&status,
wb->db, local_abspath,
- path_kind, is_ignored,
+ dirent, tree_conflicted, is_ignored,
scratch_pool, scratch_pool));
is_external = is_external_path(wb->externals, local_abspath, scratch_pool);
@@ -969,32 +1067,193 @@ send_unversioned_item(const struct walk_
return SVN_NO_ERROR;
}
-/* Send svn_wc_status3_t * structures for the directory LOCAL_ABSPATH and
- for all its entries through STATUS_FUNC/STATUS_BATON, or, if SELECTED
- is non-NULL, only for that directory entry.
+static svn_error_t *
+get_dir_status(const struct walk_status_baton *wb,
+ const char *local_abspath,
+ svn_boolean_t skip_this_dir,
+ const char *parent_repos_root_url,
+ const char *parent_repos_relpath,
+ const char *parent_repos_uuid,
+ const struct svn_wc__db_info_t *dir_info,
+ const svn_io_dirent2_t *dirent,
+ const apr_array_header_t *ignore_patterns,
+ svn_depth_t depth,
+ svn_boolean_t get_all,
+ svn_boolean_t no_ignore,
+ svn_wc_status_func4_t status_func,
+ void *status_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+/* Send out a status structure according to the information gathered on one
+ * child node. (Basically this function is the guts of the loop in
+ * get_dir_status() and of get_child_status().)
+ *
+ * Send a status structure of LOCAL_ABSPATH. PARENT_ABSPATH must be the
+ * dirname of LOCAL_ABSPATH.
+ *
+ * INFO should reflect the information on LOCAL_ABSPATH; LOCAL_ABSPATH must
+ * be an unversioned file or dir, or a versioned file. For versioned
+ * directories use get_dir_status() instead.
+ *
+ * INFO may be NULL for an unversioned node. If such node has a tree conflict,
+ * UNVERSIONED_TREE_CONFLICTED may be set to TRUE. If INFO is non-NULL,
+ * UNVERSIONED_TREE_CONFLICTED is ignored.
+ *
+ * DIRENT should reflect LOCAL_ABSPATH's dirent information.
+ *
+ * DIR_REPOS_* should reflect LOCAL_ABSPATH's parent URL, i.e. LOCAL_ABSPATH's
+ * URL treated with svn_uri_dirname(). ### TODO verify this (externals)
+ *
+ * If *COLLECTED_IGNORE_PATTERNS is NULL and ignore patterns are needed in
+ * this call, *COLLECTED_IGNORE_PATTERNS will be set to an apr_array_header_t*
+ * containing all ignore patterns, as returned by collect_ignore_patterns() on
+ * PARENT_ABSPATH and IGNORE_PATTERNS. If *COLLECTED_IGNORE_PATTERNS is passed
+ * non-NULL, it is assumed to already hold that result. This speeds up
+ * repeated calls with the same PARENT_ABSPATH.
+ *
+ * *COLLECTED_IGNORE_PATTERNS will be allocated in RESULT_POOL. All other
+ * allocations are made in SCRATCH_POOL.
+ *
+ * The remaining parameters correspond to get_dir_status(). */
+static svn_error_t*
+one_child_status(const struct walk_status_baton *wb,
+ const char *local_abspath,
+ const char *parent_abspath,
+ const struct svn_wc__db_info_t *info,
+ const svn_io_dirent2_t *dirent,
+ const char *dir_repos_root_url,
+ const char *dir_repos_relpath,
+ const char *dir_repos_uuid,
+ svn_boolean_t unversioned_tree_conflicted,
+ apr_array_header_t **collected_ignore_patterns,
+ const apr_array_header_t *ignore_patterns,
+ svn_depth_t depth,
+ svn_boolean_t get_all,
+ svn_boolean_t no_ignore,
+ svn_wc_status_func4_t status_func,
+ void *status_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t conflicted = info ? info->conflicted
+ : unversioned_tree_conflicted;
+
+ if (info
+ && info->status != svn_wc__db_status_not_present
+ && info->status != svn_wc__db_status_excluded
+ && info->status != svn_wc__db_status_server_excluded
+ && !(info->kind == svn_kind_unknown
+ && info->status == svn_wc__db_status_normal))
+ {
+ if (depth == svn_depth_files
+ && info->kind == svn_kind_dir)
+ {
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(send_status_structure(wb, local_abspath,
+ dir_repos_root_url,
+ dir_repos_relpath,
+ dir_repos_uuid,
+ info, dirent, get_all,
+ status_func, status_baton,
+ scratch_pool));
+
+ /* Descend in subdirectories. */
+ if (depth == svn_depth_infinity
+ && info->kind == svn_kind_dir)
+ {
+ SVN_ERR(get_dir_status(wb, local_abspath, TRUE,
+ dir_repos_root_url, dir_repos_relpath,
+ dir_repos_uuid, info,
+ dirent, ignore_patterns,
+ svn_depth_infinity, get_all,
+ no_ignore,
+ status_func, status_baton,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+ }
+
+ /* If conflicted, fall right through to unversioned.
+ * With depth_files, show all conflicts, even if their report is only
+ * about directories. A tree conflict may actually report two different
+ * kinds, so it's not so easy to define what depth=files means. We could go
+ * look up the kinds in the conflict ... just show all. */
+ if (! conflicted)
+ {
+ /* Selected node, but not found */
+ if (dirent == NULL)
+ return SVN_NO_ERROR;
+
+ if (depth == svn_depth_files && dirent->kind == svn_node_dir)
+ return SVN_NO_ERROR;
+
+ if (svn_wc_is_adm_dir(svn_dirent_basename(local_abspath, scratch_pool),
+ scratch_pool))
+ return SVN_NO_ERROR;
+ }
- PARENT_ENTRY is the entry for the parent of the directory or NULL
- if LOCAL_ABSPATH is a working copy root.
+ /* The node exists on disk but there is no versioned information about it,
+ * or it doesn't exist but is a tree conflicted path or should be
+ * reported not-present. */
+
+ /* Why pass ignore patterns on a tree conflicted node, even if it should
+ * always show up in clients' status reports anyway? Because the calling
+ * client decides whether to ignore, and thus this flag needs to be
+ * determined. For example, in 'svn status', plain unversioned nodes show
+ * as '? C', where ignored ones show as 'I C'. */
+
+ if (ignore_patterns && ! *collected_ignore_patterns)
+ SVN_ERR(collect_ignore_patterns(collected_ignore_patterns, wb->db,
+ parent_abspath, ignore_patterns,
+ result_pool, scratch_pool));
+
+ SVN_ERR(send_unversioned_item(wb,
+ local_abspath,
+ dirent,
+ conflicted,
+ *collected_ignore_patterns,
+ no_ignore,
+ status_func, status_baton,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Send svn_wc_status3_t * structures for the directory LOCAL_ABSPATH and
+ for all its child nodes (according to DEPTH) through STATUS_FUNC /
+ STATUS_BATON.
If SKIP_THIS_DIR is TRUE, the directory's own status will not be reported.
- However, upon recursing, all subdirs *will* be reported, regardless of this
+ All subdirs reached by recursion will be reported regardless of this
parameter's value.
- DIRENT is LOCAL_ABSPATH's own dirent and is only needed if it is reported,
- so if SKIP_THIS_DIR or SELECTED is not-NULL DIRENT can be left NULL.
+ PARENT_REPOS_* parameters can be set to refer to LOCAL_ABSPATH's parent's
+ URL, i.e. the URL the WC reflects at the dirname of LOCAL_ABSPATH, to avoid
+ retrieving them again. Otherwise they must be NULL.
DIR_INFO can be set to the information of LOCAL_ABSPATH, to avoid retrieving
- it again.
+ it again. Otherwise it must be NULL.
+
+ DIRENT is LOCAL_ABSPATH's own dirent and is only needed if it is reported,
+ so if SKIP_THIS_DIR is TRUE, DIRENT can be left NULL.
Other arguments are the same as those passed to
svn_wc_get_status_editor5(). */
static svn_error_t *
get_dir_status(const struct walk_status_baton *wb,
const char *local_abspath,
- const char *selected,
svn_boolean_t skip_this_dir,
const char *parent_repos_root_url,
const char *parent_repos_relpath,
+ const char *parent_repos_uuid,
const struct svn_wc__db_info_t *dir_info,
const svn_io_dirent2_t *dirent,
const apr_array_header_t *ignore_patterns,
@@ -1010,8 +1269,9 @@ get_dir_status(const struct walk_status_
apr_hash_index_t *hi;
const char *dir_repos_root_url;
const char *dir_repos_relpath;
+ const char *dir_repos_uuid;
apr_hash_t *dirents, *nodes, *conflicts, *all_children;
- apr_array_header_t *patterns = NULL;
+ apr_array_header_t *collected_ignore_patterns = NULL;
apr_pool_t *iterpool, *subpool = svn_pool_create(scratch_pool);
svn_error_t *err;
@@ -1039,181 +1299,161 @@ get_dir_status(const struct walk_status_
subpool, iterpool));
SVN_ERR(get_repos_root_url_relpath(&dir_repos_relpath, &dir_repos_root_url,
- dir_info, parent_repos_relpath,
- parent_repos_root_url,
+ &dir_repos_uuid, dir_info,
+ parent_repos_relpath,
+ parent_repos_root_url, parent_repos_uuid,
wb->db, local_abspath,
subpool, iterpool));
- if (selected == NULL)
- {
- /* Create a hash containing all children. The source hashes
- don't all map the same types, but only the keys of the result
- hash are subsequently used. */
- SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
+
+ /* Create a hash containing all children. The source hashes
+ don't all map the same types, but only the keys of the result
+ hash are subsequently used. */
+ SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
wb->db, local_abspath,
subpool, iterpool));
- all_children = apr_hash_overlay(subpool, nodes, dirents);
- if (apr_hash_count(conflicts) > 0)
- all_children = apr_hash_overlay(subpool, conflicts, all_children);
- }
- else
- {
- const struct svn_wc__db_info_t *info;
- const char *selected_abspath = svn_dirent_join(local_abspath, selected,
- iterpool);
- /* Create a hash containing just selected */
- all_children = apr_hash_make(subpool);
- nodes = apr_hash_make(subpool);
- conflicts = apr_hash_make(subpool);
-
- err = read_info(&info, selected_abspath, wb->db, subpool, iterpool);
-
- if (err)
- {
- if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_trace(err);
- svn_error_clear(err);
- /* The node is neither a tree conflict nor a versioned node */
- }
- else
- {
- if (!info->conflicted
- || info->status != svn_wc__db_status_normal
- || info->kind != svn_wc__db_kind_unknown)
- {
- /* The node is a normal versioned node */
- apr_hash_set(nodes, selected, APR_HASH_KEY_STRING, info);
- }
-
- /* Drop it in the list of possible conflicts */
- if (info->conflicted)
- apr_hash_set(conflicts, selected, APR_HASH_KEY_STRING, info);
- }
-
- apr_hash_set(all_children, selected, APR_HASH_KEY_STRING, selected);
- }
-
- if (!selected)
- {
- /* Handle "this-dir" first. */
- if (! skip_this_dir)
- SVN_ERR(send_status_structure(wb, local_abspath,
- parent_repos_root_url,
- parent_repos_relpath,
- dir_info, dirent, get_all,
- status_func, status_baton,
- iterpool));
+ all_children = apr_hash_overlay(subpool, nodes, dirents);
+ if (apr_hash_count(conflicts) > 0)
+ all_children = apr_hash_overlay(subpool, conflicts, all_children);
+
+ /* Handle "this-dir" first. */
+ if (! skip_this_dir)
+ SVN_ERR(send_status_structure(wb, local_abspath,
+ parent_repos_root_url,
+ parent_repos_relpath,
+ parent_repos_uuid,
+ dir_info, dirent, get_all,
+ status_func, status_baton,
+ iterpool));
- /* If the requested depth is empty, we only need status on this-dir. */
- if (depth == svn_depth_empty)
- return SVN_NO_ERROR;
- }
+ /* If the requested depth is empty, we only need status on this-dir. */
+ if (depth == svn_depth_empty)
+ return SVN_NO_ERROR;
/* Walk all the children of this directory. */
for (hi = apr_hash_first(subpool, all_children); hi; hi = apr_hash_next(hi))
{
const void *key;
apr_ssize_t klen;
- const char *node_abspath;
- svn_io_dirent2_t *dirent_p;
- const struct svn_wc__db_info_t *info;
+ const char *child_abspath;
+ svn_io_dirent2_t *child_dirent;
+ const struct svn_wc__db_info_t *child_info;
svn_pool_clear(iterpool);
apr_hash_this(hi, &key, &klen, NULL);
- node_abspath = svn_dirent_join(local_abspath, key, iterpool);
-
- dirent_p = apr_hash_get(dirents, key, klen);
-
- info = apr_hash_get(nodes, key, klen);
- if (info)
- {
- if (info->status != svn_wc__db_status_not_present
- && info->status != svn_wc__db_status_excluded
- && info->status != svn_wc__db_status_server_excluded)
- {
- if (depth == svn_depth_files
- && info->kind == svn_wc__db_kind_dir)
- {
- continue;
- }
-
- SVN_ERR(send_status_structure(wb, node_abspath,
- dir_repos_root_url,
- dir_repos_relpath,
- info, dirent_p, get_all,
- status_func, status_baton,
- iterpool));
-
- /* Descend in subdirectories. */
- if (depth == svn_depth_infinity
- && info->kind == svn_wc__db_kind_dir)
- {
- SVN_ERR(get_dir_status(wb, node_abspath, NULL, TRUE,
- dir_repos_root_url, dir_repos_relpath,
- info,
- dirent_p, ignore_patterns,
- svn_depth_infinity, get_all,
- no_ignore,
- status_func, status_baton,
- cancel_func, cancel_baton,
- iterpool));
- }
+ child_abspath = svn_dirent_join(local_abspath, key, iterpool);
- continue;
- }
- }
+ child_dirent = apr_hash_get(dirents, key, klen);
+ child_info = apr_hash_get(nodes, key, klen);
- if (apr_hash_get(conflicts, key, klen))
- {
- /* Tree conflict */
+ SVN_ERR(one_child_status(wb,
+ child_abspath,
+ local_abspath,
+ child_info,
+ child_dirent,
+ dir_repos_root_url,
+ dir_repos_relpath,
+ dir_repos_uuid,
+ apr_hash_get(conflicts, key, klen) != NULL,
+ &collected_ignore_patterns,
+ ignore_patterns,
+ depth,
+ get_all,
+ no_ignore,
+ status_func,
+ status_baton,
+ cancel_func,
+ cancel_baton,
+ subpool,
+ iterpool));
+ }
- if (ignore_patterns && ! patterns)
- SVN_ERR(collect_ignore_patterns(&patterns, wb->db, local_abspath,
- ignore_patterns, subpool,
- iterpool));
-
- SVN_ERR(send_unversioned_item(wb,
- node_abspath,
- dirent_p ? dirent_p->kind
- : svn_node_none,
- patterns,
- no_ignore,
- status_func,
- status_baton,
- iterpool));
+ /* Destroy our subpools. */
+ svn_pool_destroy(subpool);
- continue;
- }
+ return SVN_NO_ERROR;
+}
- /* Unversioned node */
- if (dirent_p == NULL)
- continue; /* Selected node, but not found */
+/* Send an svn_wc_status3_t * structure for the versioned file, or for the
+ * unversioned file or directory, LOCAL_ABSPATH, which is not ignored (an
+ * explicit target). Does not recurse.
+ *
+ * INFO should reflect LOCAL_ABSPATH's information, but should be NULL for
+ * unversioned nodes. An unversioned and tree-conflicted node however should
+ * pass a non-NULL INFO as returned by read_info() (INFO->CONFLICTED = TRUE).
+ *
+ * DIRENT should reflect LOCAL_ABSPATH.
+ *
+ * All allocations made in SCRATCH_POOL.
+ *
+ * The remaining parameters correspond to get_dir_status(). */
+static svn_error_t *
+get_child_status(const struct walk_status_baton *wb,
+ const char *local_abspath,
+ const struct svn_wc__db_info_t *info,
+ const svn_io_dirent2_t *dirent,
+ const apr_array_header_t *ignore_patterns,
+ svn_boolean_t get_all,
+ svn_wc_status_func4_t status_func,
+ void *status_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const char *dir_repos_root_url;
+ const char *dir_repos_relpath;
+ const char *dir_repos_uuid;
+ const struct svn_wc__db_info_t *dir_info;
+ apr_array_header_t *collected_ignore_patterns = NULL;
+ const svn_io_dirent2_t *dirent_p;
+ const char *parent_abspath = svn_dirent_dirname(local_abspath,
+ scratch_pool);
- if (depth == svn_depth_files && dirent_p->kind == svn_node_dir)
- continue;
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
- if (svn_wc_is_adm_dir(key, iterpool))
- continue;
+ SVN_ERR(svn_io_stat_dirent(&dirent_p, local_abspath, TRUE,
+ scratch_pool, scratch_pool));
- if (ignore_patterns && ! patterns)
- SVN_ERR(collect_ignore_patterns(&patterns, wb->db, local_abspath,
- ignore_patterns, subpool,
- iterpool));
+ if (dirent_p->kind == svn_node_none)
+ dirent_p = NULL;
- SVN_ERR(send_unversioned_item(wb,
- node_abspath,
- dirent_p->kind,
- patterns,
- no_ignore || selected,
- status_func, status_baton,
- iterpool));
- }
+ SVN_ERR(read_info(&dir_info, parent_abspath, wb->db,
+ scratch_pool, scratch_pool));
- /* Destroy our subpools. */
- svn_pool_destroy(subpool);
+ SVN_ERR(get_repos_root_url_relpath(&dir_repos_relpath, &dir_repos_root_url,
+ &dir_repos_uuid, dir_info,
+ NULL, NULL, NULL,
+ wb->db, parent_abspath,
+ scratch_pool, scratch_pool));
+ /* An unversioned node with a tree conflict will see an INFO != NULL here,
+ * in which case the FALSE passed for UNVERSIONED_TREE_CONFLICTED has no
+ * effect and INFO->CONFLICTED counts.
+ * ### Maybe svn_wc__db_read_children_info() and read_info() should be more
+ * ### alike? */
+ SVN_ERR(one_child_status(wb,
+ local_abspath,
+ parent_abspath,
+ info,
+ dirent_p,
+ dir_repos_root_url,
+ dir_repos_relpath,
+ dir_repos_uuid,
+ FALSE, /* unversioned_tree_conflicted */
+ &collected_ignore_patterns,
+ ignore_patterns,
+ svn_depth_empty,
+ get_all,
+ TRUE, /* no_ignore. This is an explicit target. */
+ status_func,
+ status_baton,
+ cancel_func,
+ cancel_baton,
+ scratch_pool,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -1339,6 +1579,27 @@ tweak_statushash(void *baton,
{
struct dir_baton *b = this_dir_baton;
+ if (!statstruct->repos_relpath && b->repos_relpath)
+ {
+ if (statstruct->repos_node_status == svn_wc_status_deleted)
+ {
+ /* When deleting PATH, BATON is for PATH's parent,
+ so we must construct PATH's real statstruct->url. */
+ statstruct->repos_relpath =
+ svn_relpath_join(b->repos_relpath,
+ svn_dirent_basename(local_abspath,
+ NULL),
+ pool);
+ }
+ else
+ statstruct->repos_relpath = apr_pstrdup(pool, b->repos_relpath);
+
+ statstruct->repos_root_url =
+ b->edit_baton->anchor_status->repos_root_url;
+ statstruct->repos_uuid =
+ b->edit_baton->anchor_status->repos_uuid;
+ }
+
/* The last committed date, and author for deleted items
isn't available. */
if (statstruct->repos_node_status == svn_wc_status_deleted)
@@ -1372,6 +1633,14 @@ tweak_statushash(void *baton,
struct file_baton *b = baton;
statstruct->ood_changed_rev = b->ood_changed_rev;
statstruct->ood_changed_date = b->ood_changed_date;
+ if (!statstruct->repos_relpath && b->repos_relpath)
+ {
+ statstruct->repos_relpath = apr_pstrdup(pool, b->repos_relpath);
+ statstruct->repos_root_url =
+ b->edit_baton->anchor_status->repos_root_url;
+ statstruct->repos_uuid =
+ b->edit_baton->anchor_status->repos_uuid;
+ }
statstruct->ood_kind = b->ood_kind;
if (b->ood_changed_author)
statstruct->ood_changed_author =
@@ -1394,9 +1663,9 @@ find_dir_repos_relpath(const struct dir_
const svn_wc_status3_t *status = apr_hash_get(pb->statii,
db->local_abspath,
APR_HASH_KEY_STRING);
- /* Note that status->url is NULL in the case of a missing
- * directory, which means we need to recurse up another level to
- * get a useful URL. */
+ /* Note that status->repos_relpath could be NULL in the case of a missing
+ * directory, which means we need to recurse up another level to get
+ * a useful relpath. */
if (status)
return status->repos_relpath;
@@ -1441,6 +1710,7 @@ make_dir_baton(void **dir_baton,
d->statii = apr_hash_make(pool);
d->ood_changed_rev = SVN_INVALID_REVNUM;
d->ood_changed_date = 0;
+ d->repos_relpath = apr_pstrdup(pool, find_dir_repos_relpath(d, pool));
d->ood_kind = svn_node_dir;
d->ood_changed_author = NULL;
@@ -1485,9 +1755,10 @@ make_dir_baton(void **dir_baton,
const svn_wc_status3_t *this_dir_status;
const apr_array_header_t *ignores = eb->ignores;
- SVN_ERR(get_dir_status(&eb->wb, local_abspath, NULL, TRUE,
+ SVN_ERR(get_dir_status(&eb->wb, local_abspath, TRUE,
status_in_parent->repos_root_url,
NULL /*parent_repos_relpath*/,
+ status_in_parent->repos_uuid,
NULL,
NULL /* dirent */, ignores,
d->depth == svn_depth_files
@@ -1533,6 +1804,8 @@ make_file_baton(struct dir_baton *parent
f->edit_baton = eb;
f->ood_changed_rev = SVN_INVALID_REVNUM;
f->ood_changed_date = 0;
+ f->repos_relpath = svn_relpath_join(find_dir_repos_relpath(pb, pool),
+ f->name, pool);
f->ood_kind = svn_node_file;
f->ood_changed_author = NULL;
return f;
@@ -1557,6 +1830,9 @@ is_sendable_status(const svn_wc_status3_
if (status->repos_lock)
return TRUE;
+ if (status->conflicted)
+ return TRUE;
+
/* If the item is ignored, and we don't want ignores, skip it. */
if ((status->node_status == svn_wc_status_ignored) && (! no_ignore))
return FALSE;
@@ -1574,8 +1850,6 @@ is_sendable_status(const svn_wc_status3_
if ((status->node_status != svn_wc_status_none
&& (status->node_status != svn_wc_status_normal)))
return TRUE;
- if (status->conflicted)
- return TRUE;
/* If it's switched, send it. */
if (status->switched)
@@ -1629,6 +1903,7 @@ static svn_error_t *
handle_statii(struct edit_baton *eb,
const char *dir_repos_root_url,
const char *dir_repos_relpath,
+ const char *dir_repos_uuid,
apr_hash_t *statii,
svn_boolean_t dir_was_deleted,
svn_depth_t depth,
@@ -1665,8 +1940,9 @@ handle_statii(struct edit_baton *eb,
|| depth == svn_depth_infinity))
{
SVN_ERR(get_dir_status(&eb->wb,
- local_abspath, NULL, TRUE,
+ local_abspath, TRUE,
dir_repos_root_url, dir_repos_relpath,
+ dir_repos_uuid,
NULL,
NULL /* dirent */,
ignores, depth, eb->get_all, eb->no_ignore,
@@ -1692,7 +1968,7 @@ handle_statii(struct edit_baton *eb,
/*** The callbacks we'll plug into an svn_delta_editor_t structure. ***/
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
set_target_revision(void *edit_baton,
svn_revnum_t target_revision,
@@ -1704,7 +1980,7 @@ set_target_revision(void *edit_baton,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
open_root(void *edit_baton,
svn_revnum_t base_revision,
@@ -1717,7 +1993,7 @@ open_root(void *edit_baton,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
delete_entry(const char *path,
svn_revnum_t revision,
@@ -1727,7 +2003,7 @@ delete_entry(const char *path,
struct dir_baton *db = parent_baton;
struct edit_baton *eb = db->edit_baton;
const char *local_abspath = svn_dirent_join(eb->anchor_abspath, path, pool);
- svn_wc__db_kind_t kind;
+ svn_kind_t kind;
/* Note: when something is deleted, it's okay to tweak the
statushash immediately. No need to wait until close_file or
@@ -1736,7 +2012,7 @@ delete_entry(const char *path,
SVN_ERR(svn_wc__db_read_kind(&kind, eb->db, local_abspath, FALSE, pool));
SVN_ERR(tweak_statushash(db, db, TRUE, eb->db,
- local_abspath, kind == svn_wc__db_kind_dir,
+ local_abspath, kind == svn_kind_dir,
svn_wc_status_deleted, 0, 0, revision, NULL, pool));
/* Mark the parent dir -- it lost an entry (unless that parent dir
@@ -1745,7 +2021,7 @@ delete_entry(const char *path,
if (db->parent_baton && (! *eb->target_basename))
SVN_ERR(tweak_statushash(db->parent_baton, db, TRUE,eb->db,
db->local_abspath,
- kind == svn_wc__db_kind_dir,
+ kind == svn_kind_dir,
svn_wc_status_modified, svn_wc_status_modified,
0, SVN_INVALID_REVNUM, NULL, pool));
@@ -1753,7 +2029,7 @@ delete_entry(const char *path,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
add_directory(const char *path,
void *parent_baton,
@@ -1779,7 +2055,7 @@ add_directory(const char *path,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
open_directory(const char *path,
void *parent_baton,
@@ -1792,7 +2068,7 @@ open_directory(const char *path,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
change_dir_prop(void *dir_baton,
const char *name,
@@ -1823,7 +2099,7 @@ change_dir_prop(void *dir_baton,
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
close_directory(void *dir_baton,
apr_pool_t *pool)
@@ -1912,6 +2188,7 @@ close_directory(void *dir_baton,
SVN_ERR(handle_statii(eb,
dir_status ? dir_status->repos_root_url : NULL,
dir_status ? dir_status->repos_relpath : NULL,
+ dir_status ? dir_status->repos_uuid : NULL,
db->statii, was_deleted, db->depth, pool));
if (dir_status && is_sendable_status(dir_status, eb->no_ignore,
eb->get_all))
@@ -1935,8 +2212,9 @@ close_directory(void *dir_baton,
&& tgt_status->kind == svn_node_dir)
{
SVN_ERR(get_dir_status(&eb->wb,
- eb->target_abspath, NULL, TRUE,
- NULL, NULL, NULL, NULL /* dirent */,
+ eb->target_abspath, TRUE,
+ NULL, NULL, NULL, NULL,
+ NULL /* dirent */,
eb->ignores,
eb->default_depth,
eb->get_all, eb->no_ignore,
@@ -1957,6 +2235,7 @@ close_directory(void *dir_baton,
SVN_ERR(handle_statii(eb,
eb->anchor_status->repos_root_url,
eb->anchor_status->repos_relpath,
+ eb->anchor_status->repos_uuid,
db->statii, FALSE, eb->default_depth, pool));
if (is_sendable_status(eb->anchor_status, eb->no_ignore,
eb->get_all))
@@ -1970,7 +2249,7 @@ close_directory(void *dir_baton,
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
add_file(const char *path,
void *parent_baton,
@@ -1993,7 +2272,7 @@ add_file(const char *path,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
open_file(const char *path,
void *parent_baton,
@@ -2009,7 +2288,7 @@ open_file(const char *path,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
apply_textdelta(void *file_baton,
const char *base_checksum,
@@ -2030,7 +2309,7 @@ apply_textdelta(void *file_baton,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
change_file_prop(void *file_baton,
const char *name,
@@ -2062,7 +2341,7 @@ change_file_prop(void *file_baton,
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
close_file(void *file_baton,
const char *text_checksum, /* ignored, as we receive no data */
@@ -2119,7 +2398,7 @@ close_file(void *file_baton,
SVN_INVALID_REVNUM, repos_lock, pool);
}
-/* */
+/* An svn_delta_editor_t function. */
static svn_error_t *
close_edit(void *edit_baton,
apr_pool_t *pool)
@@ -2163,6 +2442,7 @@ svn_wc_get_status_editor5(const svn_delt
svn_depth_t depth,
svn_boolean_t get_all,
svn_boolean_t no_ignore,
+ svn_boolean_t depth_as_sticky,
svn_boolean_t server_performs_filtering,
const apr_array_header_t *ignore_patterns,
svn_wc_status_func4_t status_func,
@@ -2244,7 +2524,7 @@ svn_wc_get_status_editor5(const svn_delt
inner_baton = eb;
if (!server_performs_filtering
- && depth == svn_depth_unknown)
+ && !depth_as_sticky)
SVN_ERR(svn_wc__ambient_depth_filter_editor(&inner_editor,
&inner_baton,
wc_ctx->db,
@@ -2263,6 +2543,10 @@ svn_wc_get_status_editor5(const svn_delt
if (set_locks_baton)
*set_locks_baton = eb;
+ SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
+ NULL, NULL, NULL, NULL,
+ result_pool, scratch_pool));
+
return SVN_NO_ERROR;
}
@@ -2282,9 +2566,8 @@ svn_wc__internal_walk_status(svn_wc__db_
{
struct walk_status_baton wb;
const svn_io_dirent2_t *dirent;
- const char *anchor_abspath, *target_name;
- svn_boolean_t skip_root;
- svn_wc__db_kind_t kind;
+ const struct svn_wc__db_info_t *info;
+ svn_error_t *err;
wb.db = db;
wb.target_abspath = local_abspath;
@@ -2305,42 +2588,53 @@ svn_wc__internal_walk_status(svn_wc__db_
ignore_patterns = ignores;
}
- SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, TRUE, scratch_pool));
- SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, TRUE,
- scratch_pool, scratch_pool));
+ err = read_info(&info, local_abspath, db, scratch_pool, scratch_pool);
- if (kind == svn_wc__db_kind_file && dirent->kind == svn_node_file)
+ if (err)
{
- anchor_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
- target_name = svn_dirent_basename(local_abspath, NULL);
- skip_root = TRUE;
+ if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ info = NULL;
+ }
+ else
+ return svn_error_trace(err);
}
- else if (kind == svn_wc__db_kind_dir && dirent->kind == svn_node_dir)
+
+ SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, TRUE,
+ scratch_pool, scratch_pool));
+
+ if (info && info->kind == svn_kind_dir)
{
- anchor_abspath = local_abspath;
- target_name = NULL;
- skip_root = FALSE;
+ SVN_ERR(get_dir_status(&wb,
+ local_abspath,
+ FALSE /* skip_root */,
+ NULL, NULL, NULL,
+ info,
+ dirent,
+ ignore_patterns,
+ depth,
+ get_all,
+ no_ignore,
+ status_func, status_baton,
+ cancel_func, cancel_baton,
+ scratch_pool));
}
else
{
- anchor_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
- target_name = svn_dirent_basename(local_abspath, NULL);
- skip_root = FALSE;
- }
-
- SVN_ERR(get_dir_status(&wb,
- anchor_abspath,
- target_name,
- skip_root,
- NULL, NULL, NULL, /* parent info */
- dirent,
- ignore_patterns,
- depth,
- get_all,
- no_ignore,
- status_func, status_baton,
- cancel_func, cancel_baton,
- scratch_pool));
+ /* It may be a file or an unversioned item. And this is an explicit
+ * target, so no ignoring. An unversioned item (file or dir) shows a
+ * status like '?', and can yield a tree conflicted path. */
+ SVN_ERR(get_child_status(&wb,
+ local_abspath,
+ info,
+ dirent,
+ ignore_patterns,
+ get_all,
+ status_func, status_baton,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ }
return SVN_NO_ERROR;
}
@@ -2422,10 +2716,12 @@ internal_status(svn_wc_status3_t **statu
apr_pool_t *scratch_pool)
{
const svn_io_dirent2_t *dirent;
- svn_wc__db_kind_t node_kind;
+ svn_kind_t node_kind;
const char *parent_repos_relpath;
const char *parent_repos_root_url;
+ const char *parent_repos_uuid;
svn_wc__db_status_t node_status;
+ svn_boolean_t conflicted;
svn_boolean_t is_root = FALSE;
svn_error_t *err;
@@ -2436,26 +2732,34 @@ internal_status(svn_wc_status3_t **statu
err = svn_wc__db_read_info(&node_status, &node_kind, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, &conflicted,
+ NULL, NULL, NULL, NULL, NULL, NULL,
db, local_abspath,
scratch_pool, scratch_pool);
- if ((err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- || node_status == svn_wc__db_status_not_present
- || node_status == svn_wc__db_status_server_excluded
- || node_status == svn_wc__db_status_excluded)
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
{
svn_error_clear(err);
- node_kind = svn_wc__db_kind_unknown;
+ node_kind = svn_kind_unknown;
+ /* Ensure conflicted is always set, but don't hide tree conflicts
+ on 'hidden' nodes. */
+ conflicted = FALSE;
+ }
+ else if (err)
+ {
+ return svn_error_trace(err);
+ }
+ else if (node_status == svn_wc__db_status_not_present
+ || node_status == svn_wc__db_status_server_excluded
+ || node_status == svn_wc__db_status_excluded)
+ {
+ node_kind = svn_kind_unknown;
}
- else
- SVN_ERR(err);
- if (node_kind == svn_wc__db_kind_unknown)
+ if (node_kind == svn_kind_unknown)
return svn_error_trace(assemble_unversioned(status,
db, local_abspath,
- dirent->kind,
+ dirent, conflicted,
FALSE /* is_ignored */,
result_pool, scratch_pool));
@@ -2472,7 +2776,7 @@ internal_status(svn_wc_status3_t **statu
err = svn_wc__db_read_info(&parent_status, NULL, NULL,
&parent_repos_relpath, &parent_repos_root_url,
- NULL, NULL, NULL, NULL,
+ &parent_repos_uuid, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
@@ -2485,28 +2789,21 @@ internal_status(svn_wc_status3_t **statu
svn_error_clear(err);
parent_repos_root_url = NULL;
parent_repos_relpath = NULL;
+ parent_repos_uuid = NULL;
}
- else if (err)
- return svn_error_trace(err);
-
- if (!err
- && parent_repos_relpath == NULL
- && parent_status != svn_wc__db_status_added
- && parent_status != svn_wc__db_status_deleted)
- SVN_ERR(svn_wc__db_scan_base_repos(&parent_repos_relpath,
- &parent_repos_root_url, NULL,
- db, local_abspath,
- result_pool, scratch_pool));
+ else SVN_ERR(err);
}
else
{
parent_repos_root_url = NULL;
parent_repos_relpath = NULL;
+ parent_repos_uuid = NULL;
}
return svn_error_trace(assemble_status(status, db, local_abspath,
parent_repos_root_url,
parent_repos_relpath,
+ parent_repos_uuid,
NULL,
dirent,
TRUE /* get_all */,
@@ -2563,6 +2860,18 @@ svn_wc_dup_status3(const svn_wc_status3_
new_stat->repos_relpath
= apr_pstrdup(pool, orig_stat->repos_relpath);
+ if (orig_stat->repos_uuid)
+ 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);
+
/* Return the new hotness. */
return new_stat;
}
Modified: subversion/branches/svn_mutex/subversion/libsvn_wc/translate.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_wc/translate.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_wc/translate.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_wc/translate.c Tue Oct 11 19:52:34 2011
@@ -263,7 +263,7 @@ svn_wc__get_translate_info(svn_subst_eol
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_string_t *propval;
+ const char *propval;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
if (props == NULL)
@@ -272,29 +272,26 @@ svn_wc__get_translate_info(svn_subst_eol
if (eol)
{
- propval = props ? apr_hash_get(props, SVN_PROP_EOL_STYLE,
- APR_HASH_KEY_STRING) : NULL;
+ propval = svn_prop_get_value(props, SVN_PROP_EOL_STYLE);
- svn_subst_eol_style_from_value(style, eol, propval ? propval->data : NULL);
+ svn_subst_eol_style_from_value(style, eol, propval);
}
if (keywords)
{
- propval = props ? apr_hash_get(props, SVN_PROP_KEYWORDS,
- APR_HASH_KEY_STRING) : NULL;
+ propval = svn_prop_get_value(props, SVN_PROP_KEYWORDS);
- if (!propval || propval->len == 0)
+ if (!propval || *propval == '\0')
*keywords = NULL;
else
SVN_ERR(svn_wc__expand_keywords(keywords,
db, local_abspath, NULL,
- propval->data, for_normalization,
+ propval, for_normalization,
result_pool, scratch_pool));
}
if (special)
{
- propval = props ? apr_hash_get(props, SVN_PROP_SPECIAL,
- APR_HASH_KEY_STRING) : NULL;
+ propval = svn_prop_get_value(props, SVN_PROP_SPECIAL);
*special = (propval != NULL);
}
@@ -368,7 +365,7 @@ svn_wc__sync_flags_with_props(svn_boolea
apr_pool_t *scratch_pool)
{
svn_wc__db_status_t status;
- svn_wc__db_kind_t kind;
+ svn_kind_t kind;
svn_wc__db_lock_t *lock;
apr_hash_t *props = NULL;
@@ -390,7 +387,7 @@ svn_wc__sync_flags_with_props(svn_boolea
/* We actually only care about the following flags on files, so just
early-out for all other types. */
- if (kind != svn_wc__db_kind_file)
+ if (kind != svn_kind_file)
return SVN_NO_ERROR;
/* If we get this far, we're going to change *something*, so just set
Modified: subversion/branches/svn_mutex/subversion/libsvn_wc/tree_conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_wc/tree_conflicts.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_wc/tree_conflicts.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_wc/tree_conflicts.c Tue Oct 11 19:52:34 2011
@@ -76,6 +76,8 @@ const svn_token_map_t svn_wc__conflict_r
{ "added", svn_wc_conflict_reason_added },
{ "replaced", svn_wc_conflict_reason_replaced },
{ "unversioned", svn_wc_conflict_reason_unversioned },
+ { "moved-here", svn_wc_conflict_reason_moved_here },
+ { "moved-away", svn_wc_conflict_reason_moved_away },
{ NULL }
};