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 2010/06/24 12:10:53 UTC
svn commit: r957484 - in /subversion/trunk/subversion/libsvn_wc: adm_ops.c
adm_ops.h update_editor.c
Author: rhuijben
Date: Thu Jun 24 10:10:52 2010
New Revision: 957484
URL: http://svn.apache.org/viewvc?rev=957484&view=rev
Log:
Move the update cleanup handling from adm_ops.c to a static function
in the update editor as this code is not and should not be used for
a different purpose.
* subversion/libsvn_wc/adm_ops.c
(includes): Remove adm_ops.h.
(tweak_node, tweak_entries, svn_wc__do_update_cleanup):
Move to update_editor.c
* subversion/libsvn_wc/adm_ops.h
Delete file.
* subversion/libsvn_wc/update_editor.c
(includes): Remove adm_ops.h.
(tweak_node, tweak_entries, do_update_cleanup):
Moved here from update_editor.c Renamed svn_wc__do_update_cleanup to
do_update_cleanup and made it static.
(close_edit): Update caller.
Removed:
subversion/trunk/subversion/libsvn_wc/adm_ops.h
Modified:
subversion/trunk/subversion/libsvn_wc/adm_ops.c
subversion/trunk/subversion/libsvn_wc/update_editor.c
Modified: subversion/trunk/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/adm_ops.c?rev=957484&r1=957483&r2=957484&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/trunk/subversion/libsvn_wc/adm_ops.c Thu Jun 24 10:10:52 2010
@@ -54,7 +54,6 @@
#include "wc.h"
#include "log.h"
#include "adm_files.h"
-#include "adm_ops.h"
#include "entries.h"
#include "lock.h"
#include "props.h"
@@ -102,341 +101,6 @@ svn_wc__get_committed_queue_pool(const s
/*** Finishing updates and commits. ***/
-/* Helper for svn_wc__do_update_cleanup().
- *
- * Tweak the information for LOCAL_ABSPATH in DB. If NEW_REPOS_RELPATH is
- * non-NULL update the entry to the new url specified by NEW_REPOS_RELPATH,
- * NEW_REPOS_ROOT_URL, NEW_REPOS_UUID.. If NEW_REV is valid, make this the
- * node's working revision.
- *
- * If ALLOW_REMOVAL is TRUE the tweaks might cause the node for
- * LOCAL_ABSPATH to be removed from the WC; if ALLOW_REMOVAL is FALSE this
- * will not happen.
- */
-static svn_error_t *
-tweak_node(svn_wc__db_t *db,
- const char *local_abspath,
- svn_wc__db_kind_t kind,
- svn_boolean_t parent_stub,
- const char *new_repos_relpath,
- const char *new_repos_root_url,
- const char *new_repos_uuid,
- svn_revnum_t new_rev,
- svn_boolean_t allow_removal,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_status_t status;
- svn_wc__db_kind_t db_kind;
- svn_revnum_t revision;
- const char *repos_relpath, *repos_root_url, *repos_uuid;
- svn_boolean_t set_repos_relpath = FALSE;
- svn_error_t *err;
-
- err = svn_wc__db_base_get_info(&status, &db_kind, &revision,
- &repos_relpath, &repos_root_url,
- &repos_uuid, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, db, local_abspath,
- scratch_pool, scratch_pool);
-
- if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- {
- /* ### Tweaking should never be necessary for nodes that don't
- ### have a base node, but we still get here from many tests */
- svn_error_clear(err);
- return SVN_NO_ERROR; /* No BASE_NODE -> Added node */
- }
- else
- SVN_ERR(err);
-
- SVN_ERR_ASSERT(db_kind == kind);
-
- /* As long as this function is only called as a helper to
- svn_wc__do_update_cleanup, then it's okay to remove any entry
- under certain circumstances:
-
- If the entry is still marked 'deleted', then the server did not
- re-add it. So it's really gone in this revision, thus we remove
- the entry.
-
- If the entry is still marked 'absent' and yet is not the same
- revision as new_rev, then the server did not re-add it, nor
- re-absent it, so we can remove the entry.
-
- ### This function cannot always determine whether removal is
- ### appropriate, hence the ALLOW_REMOVAL flag. It's all a bit of a
- ### mess. */
- if (allow_removal
- && (status == svn_wc__db_status_not_present
- || (status == svn_wc__db_status_absent && revision != new_rev)))
- {
- return svn_error_return(
- svn_wc__db_temp_op_remove_entry(db, local_abspath,
- scratch_pool));
-
- }
-
- if (new_repos_relpath != NULL)
- {
- if (!repos_relpath)
- SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
- &repos_uuid, db, local_abspath,
- scratch_pool, scratch_pool));
-
- if (strcmp(repos_relpath, new_repos_relpath))
- set_repos_relpath = TRUE;
- }
-
- if (SVN_IS_VALID_REVNUM(new_rev) && new_rev == revision)
- new_rev = SVN_INVALID_REVNUM;
-
- if (SVN_IS_VALID_REVNUM(new_rev) || set_repos_relpath)
- {
- svn_boolean_t update_stub =
- (db_kind == svn_wc__db_kind_dir && parent_stub);
-
- SVN_ERR(svn_wc__db_temp_op_set_rev_and_repos_relpath(db, local_abspath,
- new_rev,
- set_repos_relpath,
- new_repos_relpath,
- repos_root_url,
- repos_uuid,
- update_stub,
- scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-
-/* The main body of svn_wc__do_update_cleanup. */
-static svn_error_t *
-tweak_entries(svn_wc__db_t *db,
- const char *dir_abspath,
- const char *new_repos_relpath,
- const char *new_repos_root_url,
- const char *new_repos_uuid,
- svn_revnum_t new_rev,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- svn_depth_t depth,
- apr_hash_t *exclude_paths,
- apr_pool_t *pool)
-{
- apr_pool_t *iterpool;
- svn_wc_notify_t *notify;
- const apr_array_header_t *children;
- int i;
-
- /* Skip an excluded path and its descendants. */
- if (apr_hash_get(exclude_paths, dir_abspath, APR_HASH_KEY_STRING))
- return SVN_NO_ERROR;
-
- iterpool = svn_pool_create(pool);
-
- /* Tweak "this_dir" */
- SVN_ERR(tweak_node(db, dir_abspath, svn_wc__db_kind_dir, FALSE,
- new_repos_relpath, new_repos_root_url, new_repos_uuid,
- new_rev, FALSE /* allow_removal */, iterpool));
-
- if (depth == svn_depth_unknown)
- depth = svn_depth_infinity;
-
- /* Early out */
- if (depth <= svn_depth_empty)
- return SVN_NO_ERROR;
-
- SVN_ERR(svn_wc__db_base_get_children(&children, db, dir_abspath,
- pool, iterpool));
- for (i = 0; i < children->nelts; i++)
- {
- const char *child_basename = APR_ARRAY_IDX(children, i, const char *);
- const char *child_abspath;
- svn_wc__db_kind_t kind;
- svn_wc__db_status_t status;
-
- const char *child_repos_relpath = NULL;
- svn_boolean_t excluded;
-
- svn_pool_clear(iterpool);
-
- /* Derive the new URL for the current (child) entry */
- if (new_repos_relpath)
- child_repos_relpath = svn_relpath_join(new_repos_relpath,
- child_basename, iterpool);
-
- child_abspath = svn_dirent_join(dir_abspath, child_basename, iterpool);
- excluded = (apr_hash_get(exclude_paths, child_abspath,
- APR_HASH_KEY_STRING) != NULL);
-
- SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- db, child_abspath, iterpool, iterpool));
-
- /* If a file, or deleted, excluded or absent dir, then tweak the
- entry but don't recurse.
-
- ### how does this translate into wc_db land? */
- if (kind == svn_wc__db_kind_file
- || status == svn_wc__db_status_not_present
- || status == svn_wc__db_status_absent
- || status == svn_wc__db_status_excluded)
- {
- if (excluded)
- continue;
-
- if (kind == svn_wc__db_kind_dir)
- SVN_ERR(tweak_node(db, child_abspath, svn_wc__db_kind_dir, TRUE,
- child_repos_relpath, new_repos_root_url,
- new_repos_uuid, new_rev,
- TRUE /* allow_removal */, iterpool));
- else
- SVN_ERR(tweak_node(db, child_abspath, kind, FALSE,
- child_repos_relpath, new_repos_root_url,
- new_repos_uuid, new_rev,
- TRUE /* allow_removal */, iterpool));
- }
-
- /* If a directory and recursive... */
- else if ((depth == svn_depth_infinity
- || depth == svn_depth_immediates)
- && (kind == svn_wc__db_kind_dir))
- {
- svn_depth_t depth_below_here = depth;
-
- if (depth == svn_depth_immediates)
- depth_below_here = svn_depth_empty;
-
- /* If the directory is 'missing', remove it. This is safe as
- long as this function is only called as a helper to
- svn_wc__do_update_cleanup, since the update will already have
- restored any missing items that it didn't want to delete. */
- if (svn_wc__adm_missing(db, child_abspath, iterpool))
- {
- if ( (status == svn_wc__db_status_added
- || status == svn_wc__db_status_obstructed_add)
- && !excluded)
- {
- SVN_ERR(svn_wc__db_temp_op_remove_entry(db, child_abspath,
- iterpool));
-
- if (notify_func)
- {
- notify = svn_wc_create_notify(child_abspath,
- svn_wc_notify_delete,
- iterpool);
-
- if (kind == svn_wc__db_kind_dir)
- notify->kind = svn_node_dir;
- else if (kind == svn_wc__db_kind_file)
- notify->kind = svn_node_file;
- else
- notify->kind = svn_node_unknown;
-
- (* notify_func)(notify_baton, notify, iterpool);
- }
- }
- /* Else if missing item is schedule-add, do nothing. */
- }
-
- /* Not missing, deleted, or absent, so recurse. */
- else
- {
- SVN_ERR(tweak_entries(db, child_abspath, child_repos_relpath,
- new_repos_root_url, new_repos_uuid,
- new_rev, notify_func, notify_baton,
- depth_below_here,
- exclude_paths, iterpool));
- }
- }
- }
-
- /* Cleanup */
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__do_update_cleanup(svn_wc__db_t *db,
- const char *local_abspath,
- svn_depth_t depth,
- const char *new_repos_relpath,
- const char *new_repos_root_url,
- const char *new_repos_uuid,
- svn_revnum_t new_revision,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_hash_t *exclude_paths,
- apr_pool_t *pool)
-{
- svn_wc__db_status_t status;
- svn_wc__db_kind_t kind;
- svn_error_t *err;
-
- if (apr_hash_get(exclude_paths, local_abspath, APR_HASH_KEY_STRING))
- return SVN_NO_ERROR;
-
- err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL,
- db, local_abspath, pool, pool);
- if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- {
- svn_error_clear(err);
- return SVN_NO_ERROR;
- }
- else
- SVN_ERR(err);
-
- switch (status)
- {
- case svn_wc__db_status_excluded:
- case svn_wc__db_status_absent:
- case svn_wc__db_status_not_present:
- return SVN_NO_ERROR;
- case svn_wc__db_status_obstructed:
- case svn_wc__db_status_obstructed_add:
- case svn_wc__db_status_obstructed_delete:
- /* There is only a parent stub. That's fine... just tweak it
- and avoid directory recursion. */
- SVN_ERR(tweak_node(db, local_abspath, svn_wc__db_kind_dir, TRUE,
- new_repos_relpath, new_repos_root_url,
- new_repos_uuid, new_revision,
- FALSE /* allow_removal */, pool));
- return SVN_NO_ERROR;
-
- /* Explicitly ignore other statii */
- default:
- break;
- }
-
- if (kind == svn_wc__db_kind_file || kind == svn_wc__db_kind_symlink)
- {
- /* Parent not updated so don't remove PATH entry. */
- SVN_ERR(tweak_node(db, local_abspath, kind, FALSE,
- new_repos_relpath, new_repos_root_url, new_repos_uuid,
- new_revision, FALSE /* allow_removal */, pool));
- }
- else if (kind == svn_wc__db_kind_dir)
- {
- SVN_ERR(tweak_entries(db, local_abspath, new_repos_relpath,
- new_repos_root_url, new_repos_uuid, new_revision,
- notify_func, notify_baton,
- depth, exclude_paths, pool));
- }
- else
- return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
- _("Unrecognized node kind: '%s'"),
- svn_dirent_local_style(local_abspath, pool));
-
- return SVN_NO_ERROR;
-}
-
-
/* Queue work items that will finish a commit of the file or directory
* LOCAL_ABSPATH in DB:
* - queue the removal of any "revert-base" props and text files;
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=957484&r1=957483&r2=957484&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Thu Jun 24 10:10:52 2010
@@ -50,7 +50,6 @@
#include "wc.h"
#include "log.h"
#include "adm_files.h"
-#include "adm_ops.h"
#include "entries.h"
#include "lock.h"
#include "translate.h"
@@ -5080,6 +5079,369 @@ close_file(void *file_baton,
return SVN_NO_ERROR;
}
+/* Helper for svn_wc__do_update_cleanup().
+ *
+ * Tweak the information for LOCAL_ABSPATH in DB. If NEW_REPOS_RELPATH is
+ * non-NULL update the entry to the new url specified by NEW_REPOS_RELPATH,
+ * NEW_REPOS_ROOT_URL, NEW_REPOS_UUID.. If NEW_REV is valid, make this the
+ * node's working revision.
+ *
+ * If ALLOW_REMOVAL is TRUE the tweaks might cause the node for
+ * LOCAL_ABSPATH to be removed from the WC; if ALLOW_REMOVAL is FALSE this
+ * will not happen.
+ */
+static svn_error_t *
+tweak_node(svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_wc__db_kind_t kind,
+ svn_boolean_t parent_stub,
+ const char *new_repos_relpath,
+ const char *new_repos_root_url,
+ const char *new_repos_uuid,
+ svn_revnum_t new_rev,
+ svn_boolean_t allow_removal,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_status_t status;
+ svn_wc__db_kind_t db_kind;
+ svn_revnum_t revision;
+ const char *repos_relpath, *repos_root_url, *repos_uuid;
+ svn_boolean_t set_repos_relpath = FALSE;
+ svn_error_t *err;
+
+ err = svn_wc__db_base_get_info(&status, &db_kind, &revision,
+ &repos_relpath, &repos_root_url,
+ &repos_uuid, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, db, local_abspath,
+ scratch_pool, scratch_pool);
+
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ /* ### Tweaking should never be necessary for nodes that don't
+ ### have a base node, but we still get here from many tests */
+ svn_error_clear(err);
+ return SVN_NO_ERROR; /* No BASE_NODE -> Added node */
+ }
+ else
+ SVN_ERR(err);
+
+ SVN_ERR_ASSERT(db_kind == kind);
+
+ /* As long as this function is only called as a helper to
+ svn_wc__do_update_cleanup, then it's okay to remove any entry
+ under certain circumstances:
+
+ If the entry is still marked 'deleted', then the server did not
+ re-add it. So it's really gone in this revision, thus we remove
+ the entry.
+
+ If the entry is still marked 'absent' and yet is not the same
+ revision as new_rev, then the server did not re-add it, nor
+ re-absent it, so we can remove the entry.
+
+ ### This function cannot always determine whether removal is
+ ### appropriate, hence the ALLOW_REMOVAL flag. It's all a bit of a
+ ### mess. */
+ if (allow_removal
+ && (status == svn_wc__db_status_not_present
+ || (status == svn_wc__db_status_absent && revision != new_rev)))
+ {
+ return svn_error_return(
+ svn_wc__db_temp_op_remove_entry(db, local_abspath,
+ scratch_pool));
+
+ }
+
+ if (new_repos_relpath != NULL)
+ {
+ if (!repos_relpath)
+ SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
+ &repos_uuid, db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ if (strcmp(repos_relpath, new_repos_relpath))
+ set_repos_relpath = TRUE;
+ }
+
+ if (SVN_IS_VALID_REVNUM(new_rev) && new_rev == revision)
+ new_rev = SVN_INVALID_REVNUM;
+
+ if (SVN_IS_VALID_REVNUM(new_rev) || set_repos_relpath)
+ {
+ svn_boolean_t update_stub =
+ (db_kind == svn_wc__db_kind_dir && parent_stub);
+
+ SVN_ERR(svn_wc__db_temp_op_set_rev_and_repos_relpath(db, local_abspath,
+ new_rev,
+ set_repos_relpath,
+ new_repos_relpath,
+ repos_root_url,
+ repos_uuid,
+ update_stub,
+ scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+/* The main body of svn_wc__do_update_cleanup. */
+static svn_error_t *
+tweak_entries(svn_wc__db_t *db,
+ const char *dir_abspath,
+ const char *new_repos_relpath,
+ const char *new_repos_root_url,
+ const char *new_repos_uuid,
+ svn_revnum_t new_rev,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ svn_depth_t depth,
+ apr_hash_t *exclude_paths,
+ apr_pool_t *pool)
+{
+ apr_pool_t *iterpool;
+ svn_wc_notify_t *notify;
+ const apr_array_header_t *children;
+ int i;
+
+ /* Skip an excluded path and its descendants. */
+ if (apr_hash_get(exclude_paths, dir_abspath, APR_HASH_KEY_STRING))
+ return SVN_NO_ERROR;
+
+ iterpool = svn_pool_create(pool);
+
+ /* Tweak "this_dir" */
+ SVN_ERR(tweak_node(db, dir_abspath, svn_wc__db_kind_dir, FALSE,
+ new_repos_relpath, new_repos_root_url, new_repos_uuid,
+ new_rev, FALSE /* allow_removal */, iterpool));
+
+ if (depth == svn_depth_unknown)
+ depth = svn_depth_infinity;
+
+ /* Early out */
+ if (depth <= svn_depth_empty)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__db_base_get_children(&children, db, dir_abspath,
+ pool, iterpool));
+ for (i = 0; i < children->nelts; i++)
+ {
+ const char *child_basename = APR_ARRAY_IDX(children, i, const char *);
+ const char *child_abspath;
+ svn_wc__db_kind_t kind;
+ svn_wc__db_status_t status;
+
+ const char *child_repos_relpath = NULL;
+ svn_boolean_t excluded;
+
+ svn_pool_clear(iterpool);
+
+ /* Derive the new URL for the current (child) entry */
+ if (new_repos_relpath)
+ child_repos_relpath = svn_relpath_join(new_repos_relpath,
+ child_basename, iterpool);
+
+ child_abspath = svn_dirent_join(dir_abspath, child_basename, iterpool);
+ excluded = (apr_hash_get(exclude_paths, child_abspath,
+ APR_HASH_KEY_STRING) != NULL);
+
+ SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, child_abspath, iterpool, iterpool));
+
+ /* If a file, or deleted, excluded or absent dir, then tweak the
+ entry but don't recurse.
+
+ ### how does this translate into wc_db land? */
+ if (kind == svn_wc__db_kind_file
+ || status == svn_wc__db_status_not_present
+ || status == svn_wc__db_status_absent
+ || status == svn_wc__db_status_excluded)
+ {
+ if (excluded)
+ continue;
+
+ if (kind == svn_wc__db_kind_dir)
+ SVN_ERR(tweak_node(db, child_abspath, svn_wc__db_kind_dir, TRUE,
+ child_repos_relpath, new_repos_root_url,
+ new_repos_uuid, new_rev,
+ TRUE /* allow_removal */, iterpool));
+ else
+ SVN_ERR(tweak_node(db, child_abspath, kind, FALSE,
+ child_repos_relpath, new_repos_root_url,
+ new_repos_uuid, new_rev,
+ TRUE /* allow_removal */, iterpool));
+ }
+
+ /* If a directory and recursive... */
+ else if ((depth == svn_depth_infinity
+ || depth == svn_depth_immediates)
+ && (kind == svn_wc__db_kind_dir))
+ {
+ svn_depth_t depth_below_here = depth;
+
+ if (depth == svn_depth_immediates)
+ depth_below_here = svn_depth_empty;
+
+ /* If the directory is 'missing', remove it. This is safe as
+ long as this function is only called as a helper to
+ svn_wc__do_update_cleanup, since the update will already have
+ restored any missing items that it didn't want to delete. */
+ if (svn_wc__adm_missing(db, child_abspath, iterpool))
+ {
+ if ( (status == svn_wc__db_status_added
+ || status == svn_wc__db_status_obstructed_add)
+ && !excluded)
+ {
+ SVN_ERR(svn_wc__db_temp_op_remove_entry(db, child_abspath,
+ iterpool));
+
+ if (notify_func)
+ {
+ notify = svn_wc_create_notify(child_abspath,
+ svn_wc_notify_delete,
+ iterpool);
+
+ if (kind == svn_wc__db_kind_dir)
+ notify->kind = svn_node_dir;
+ else if (kind == svn_wc__db_kind_file)
+ notify->kind = svn_node_file;
+ else
+ notify->kind = svn_node_unknown;
+
+ (* notify_func)(notify_baton, notify, iterpool);
+ }
+ }
+ /* Else if missing item is schedule-add, do nothing. */
+ }
+
+ /* Not missing, deleted, or absent, so recurse. */
+ else
+ {
+ SVN_ERR(tweak_entries(db, child_abspath, child_repos_relpath,
+ new_repos_root_url, new_repos_uuid,
+ new_rev, notify_func, notify_baton,
+ depth_below_here,
+ exclude_paths, iterpool));
+ }
+ }
+ }
+
+ /* Cleanup */
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+/* Modify the entry of working copy LOCAL_ABSPATH, presumably after an update
+ completes. If LOCAL_ABSPATH doesn't exist, this routine does nothing.
+
+ Set the entry's 'url' and 'working revision' fields to BASE_URL and
+ NEW_REVISION. If BASE_URL is null, the url field is untouched; if
+ NEW_REVISION in invalid, the working revision field is untouched.
+ The modifications are mutually exclusive.
+
+ If REPOS is non-NULL, set the repository root of the entry to REPOS, but
+ only if REPOS is an ancestor of the entries URL (after possibly modifying
+ it). In addition to that requirement, if the LOCAL_ABSPATH refers to a
+ directory, the repository root is only set if REPOS is an ancestor of the
+ URLs all file entries which don't already have a repository root set. This
+ prevents the entries file from being corrupted by this operation.
+
+ If LOCAL_ABSPATH is a directory, then, walk entries below LOCAL_ABSPATH
+ according to DEPTH thusly:
+
+ If DEPTH is svn_depth_infinity, perform the following actions on
+ every entry below PATH; if svn_depth_immediates, svn_depth_files,
+ or svn_depth_empty, perform them only on LOCAL_ABSPATH.
+
+ If NEW_REVISION is valid, then tweak every entry to have this new
+ working revision (excluding files that are scheduled for addition
+ or replacement.) Likewise, if BASE_URL is non-null, then rewrite
+ all urls to be "telescoping" children of the base_url.
+
+ EXCLUDE_PATHS is a hash containing const char * pathnames. Entries
+ for pathnames contained in EXCLUDE_PATHS are not touched by this
+ function. These pathnames should be absolute paths.
+*/
+static svn_error_t *
+do_update_cleanup(svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_depth_t depth,
+ const char *new_repos_relpath,
+ const char *new_repos_root_url,
+ const char *new_repos_uuid,
+ svn_revnum_t new_revision,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_hash_t *exclude_paths,
+ apr_pool_t *pool)
+{
+ svn_wc__db_status_t status;
+ svn_wc__db_kind_t kind;
+ svn_error_t *err;
+
+ if (apr_hash_get(exclude_paths, local_abspath, APR_HASH_KEY_STRING))
+ return SVN_NO_ERROR;
+
+ err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ db, local_abspath, pool, pool);
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ return SVN_NO_ERROR;
+ }
+ else
+ SVN_ERR(err);
+
+ switch (status)
+ {
+ case svn_wc__db_status_excluded:
+ case svn_wc__db_status_absent:
+ case svn_wc__db_status_not_present:
+ return SVN_NO_ERROR;
+ case svn_wc__db_status_obstructed:
+ case svn_wc__db_status_obstructed_add:
+ case svn_wc__db_status_obstructed_delete:
+ /* There is only a parent stub. That's fine... just tweak it
+ and avoid directory recursion. */
+ SVN_ERR(tweak_node(db, local_abspath, svn_wc__db_kind_dir, TRUE,
+ new_repos_relpath, new_repos_root_url,
+ new_repos_uuid, new_revision,
+ FALSE /* allow_removal */, pool));
+ return SVN_NO_ERROR;
+
+ /* Explicitly ignore other statii */
+ default:
+ break;
+ }
+
+ if (kind == svn_wc__db_kind_file || kind == svn_wc__db_kind_symlink)
+ {
+ /* Parent not updated so don't remove PATH entry. */
+ SVN_ERR(tweak_node(db, local_abspath, kind, FALSE,
+ new_repos_relpath, new_repos_root_url, new_repos_uuid,
+ new_revision, FALSE /* allow_removal */, pool));
+ }
+ else if (kind == svn_wc__db_kind_dir)
+ {
+ SVN_ERR(tweak_entries(db, local_abspath, new_repos_relpath,
+ new_repos_root_url, new_repos_uuid, new_revision,
+ notify_func, notify_baton,
+ depth, exclude_paths, pool));
+ }
+ else
+ return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
+ _("Unrecognized node kind: '%s'"),
+ svn_dirent_local_style(local_abspath, pool));
+
+ return SVN_NO_ERROR;
+}
/* An svn_delta_editor_t function. */
static svn_error_t *
@@ -5130,16 +5492,17 @@ close_edit(void *edit_baton,
will only remove the deleted entry! */
if (! eb->target_deleted)
{
- SVN_ERR(svn_wc__do_update_cleanup(eb->db, eb->target_abspath,
- eb->requested_depth,
- eb->switch_relpath,
- eb->repos_root,
- eb->repos_uuid,
- *(eb->target_revision),
- eb->notify_func,
- eb->notify_baton,
- eb->skipped_trees,
- eb->pool));
+ SVN_ERR(do_update_cleanup(eb->db,
+ eb->target_abspath,
+ eb->requested_depth,
+ eb->switch_relpath,
+ eb->repos_root,
+ eb->repos_uuid,
+ *(eb->target_revision),
+ eb->notify_func,
+ eb->notify_baton,
+ eb->skipped_trees,
+ eb->pool));
}
/* The edit is over, free its pool.