You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/10/21 04:00:47 UTC
svn commit: r1400556 [17/29] - in /subversion/branches/ev2-export: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/ build/hudson/
contrib/client-side/emacs/ contrib/client-side/svn-push/
contrib/client-side/svnmerge/ contrib/hook-...
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/version.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/version.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/version.c Sun Oct 21 02:00:31 2012
@@ -26,7 +26,9 @@
#include "svn_error.h"
#include "svn_version.h"
+#include "sysinfo.h"
#include "svn_private_config.h"
+#include "private/svn_subr_private.h"
const svn_version_t *
svn_subr_version(void)
@@ -96,3 +98,181 @@ svn_ver_check_list(const svn_version_t *
return err;
}
+
+
+struct svn_version_extended_t
+{
+ const char *build_date; /* Compilation date */
+ const char *build_time; /* Compilation time */
+ const char *build_host; /* Build canonical host name */
+ const char *copyright; /* Copyright notice (localized) */
+ const char *runtime_host; /* Runtime canonical host name */
+ const char *runtime_osname; /* Running OS release name */
+
+ /* Array of svn_version_ext_linked_lib_t describing dependent
+ libraries. */
+ const apr_array_header_t *linked_libs;
+
+ /* Array of svn_version_ext_loaded_lib_t describing loaded shared
+ libraries. */
+ const apr_array_header_t *loaded_libs;
+};
+
+
+const svn_version_extended_t *
+svn_version_extended(svn_boolean_t verbose,
+ apr_pool_t *pool)
+{
+ svn_version_extended_t *info = apr_pcalloc(pool, sizeof(*info));
+
+ info->build_date = __DATE__;
+ info->build_time = __TIME__;
+ info->build_host = SVN_BUILD_HOST;
+ info->copyright = apr_pstrdup
+ (pool, _("Copyright (C) 2012 The Apache Software Foundation.\n"
+ "This software consists of contributions made by many people;\n"
+ "see the NOTICE file for more information.\n"
+ "Subversion is open source software, see "
+ "http://subversion.apache.org/\n"));
+
+ if (verbose)
+ {
+ info->runtime_host = svn_sysinfo__canonical_host(pool);
+ info->runtime_osname = svn_sysinfo__release_name(pool);
+ info->linked_libs = svn_sysinfo__linked_libs(pool);
+ info->loaded_libs = svn_sysinfo__loaded_libs(pool);
+ }
+
+ return info;
+}
+
+
+const char *
+svn_version_ext_build_date(const svn_version_extended_t *ext_info)
+{
+ return ext_info->build_date;
+}
+
+const char *
+svn_version_ext_build_time(const svn_version_extended_t *ext_info)
+{
+ return ext_info->build_time;
+}
+
+const char *
+svn_version_ext_build_host(const svn_version_extended_t *ext_info)
+{
+ return ext_info->build_host;
+}
+
+const char *
+svn_version_ext_copyright(const svn_version_extended_t *ext_info)
+{
+ return ext_info->copyright;
+}
+
+const char *
+svn_version_ext_runtime_host(const svn_version_extended_t *ext_info)
+{
+ return ext_info->runtime_host;
+}
+
+const char *
+svn_version_ext_runtime_osname(const svn_version_extended_t *ext_info)
+{
+ return ext_info->runtime_osname;
+}
+
+const apr_array_header_t *
+svn_version_ext_linked_libs(const svn_version_extended_t *ext_info)
+{
+ return ext_info->linked_libs;
+}
+
+const apr_array_header_t *
+svn_version_ext_loaded_libs(const svn_version_extended_t *ext_info)
+{
+ return ext_info->loaded_libs;
+}
+
+svn_error_t *
+svn_version__parse_version_string(svn_version_t **version_p,
+ const char *version_string,
+ apr_pool_t *result_pool)
+{
+ svn_error_t *err;
+ svn_version_t *version;
+ apr_array_header_t *pieces =
+ svn_cstring_split(version_string, ".", FALSE, result_pool);
+
+ if ((pieces->nelts < 2) || (pieces->nelts > 3))
+ return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, NULL, NULL);
+
+ version = apr_pcalloc(result_pool, sizeof(*version));
+ version->tag = "";
+
+ /* Parse the major and minor integers strictly. */
+ err = svn_cstring_atoi(&(version->major),
+ APR_ARRAY_IDX(pieces, 0, const char *));
+ if (err)
+ return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, err, NULL);
+ err = svn_cstring_atoi(&(version->minor),
+ APR_ARRAY_IDX(pieces, 1, const char *));
+ if (err)
+ return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, err, NULL);
+
+ /* If there's a third component, we'll parse it, too. But we don't
+ require that it be present. */
+ if (pieces->nelts == 3)
+ {
+ const char *piece = APR_ARRAY_IDX(pieces, 2, const char *);
+ char *hyphen = strchr(piece, '-');
+ if (hyphen)
+ {
+ version->tag = apr_pstrdup(result_pool, hyphen + 1);
+ *hyphen = '\0';
+ }
+ err = svn_cstring_atoi(&(version->patch), piece);
+ if (err)
+ return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING,
+ err, NULL);
+ }
+
+ *version_p = version;
+ return SVN_NO_ERROR;
+}
+
+
+svn_boolean_t
+svn_version__at_least(svn_version_t *version,
+ int major,
+ int minor,
+ int patch)
+{
+ /* Compare major versions. */
+ if (version->major < major)
+ return FALSE;
+ if (version->major > major)
+ return TRUE;
+
+ /* Major versions are the same. Compare minor versions. */
+ if (version->minor < minor)
+ return FALSE;
+ if (version->minor > minor)
+ return TRUE;
+
+ /* Major and minor versions are the same. Compare patch
+ versions. */
+ if (version->patch < patch)
+ return FALSE;
+ if (version->patch > patch)
+ return TRUE;
+
+ /* Major, minor, and patch versions are identical matches. But tags
+ in our schema are always used for versions not yet quite at the
+ given patch level. */
+ if (version->tag && version->tag[0])
+ return FALSE;
+
+ return TRUE;
+}
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/win32_crypto.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/win32_crypto.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/win32_crypto.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/win32_crypto.c Sun Oct 21 02:00:31 2012
@@ -145,7 +145,7 @@ windows_password_decrypter(svn_boolean_t
SVN_ERR(svn_auth__simple_password_get(done, &in, creds, realmstring, username,
parameters, non_interactive, pool));
- if (!done)
+ if (!*done)
return SVN_NO_ERROR;
orig = svn_base64_decode_string(svn_string_create(in, pool), pool);
@@ -270,7 +270,7 @@ windows_ssl_client_cert_pw_decrypter(svn
SVN_ERR(svn_auth__ssl_client_cert_pw_get(done, &in, creds, realmstring,
username, parameters,
non_interactive, pool));
- if (!done)
+ if (!*done)
return SVN_NO_ERROR;
orig = svn_base64_decode_string(svn_string_create(in, pool), pool);
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c Sun Oct 21 02:00:31 2012
@@ -528,23 +528,22 @@ svn_wc__adm_destroy(svn_wc__db_t *db,
void *cancel_baton,
apr_pool_t *scratch_pool)
{
- const char *adm_abspath;
+ svn_boolean_t is_wcroot;
SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
- SVN_ERR(svn_wc__db_get_wcroot(&adm_abspath, db, dir_abspath,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, dir_abspath, scratch_pool));
/* Well, the coast is clear for blowing away the administrative
directory, which also removes remaining locks */
/* Now close the DB, and we can delete the working copy */
- if (strcmp(adm_abspath, dir_abspath) == 0)
+ if (is_wcroot)
{
- SVN_ERR(svn_wc__db_drop_root(db, adm_abspath, scratch_pool));
- SVN_ERR(svn_io_remove_dir2(svn_wc__adm_child(adm_abspath, NULL,
+ SVN_ERR(svn_wc__db_drop_root(db, dir_abspath, scratch_pool));
+ SVN_ERR(svn_io_remove_dir2(svn_wc__adm_child(dir_abspath, NULL,
scratch_pool),
FALSE,
cancel_func, cancel_baton,
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c Sun Oct 21 02:00:31 2012
@@ -52,6 +52,7 @@
#include "wc.h"
#include "adm_files.h"
+#include "conflicts.h"
#include "props.h"
#include "translate.h"
#include "workqueue.h"
@@ -108,11 +109,19 @@ svn_wc__get_committed_queue_pool(const s
* - queue deletion of the old pristine texts by the remembered checksums.
*
* CHECKSUM is the checksum of the new text base for LOCAL_ABSPATH, and must
- * be provided if there is one, else NULL. */
+ * be provided if there is one, else NULL.
+ *
+ * STATUS, KIND, PROP_MODS and OLD_CHECKSUM are the current in-db values of
+ * the node LOCAL_ABSPATH.
+ */
static svn_error_t *
process_committed_leaf(svn_wc__db_t *db,
const char *local_abspath,
svn_boolean_t via_recurse,
+ svn_wc__db_status_t status,
+ svn_kind_t kind,
+ svn_boolean_t prop_mods,
+ const svn_checksum_t *old_checksum,
svn_revnum_t new_revnum,
apr_time_t new_changed_date,
const char *new_changed_author,
@@ -122,26 +131,11 @@ process_committed_leaf(svn_wc__db_t *db,
const svn_checksum_t *checksum,
apr_pool_t *scratch_pool)
{
- svn_wc__db_status_t status;
- svn_kind_t kind;
- const svn_checksum_t *copied_checksum;
svn_revnum_t new_changed_rev = new_revnum;
- svn_boolean_t have_base;
- svn_boolean_t have_work;
- svn_boolean_t had_props;
- svn_boolean_t prop_mods;
svn_skel_t *work_item = NULL;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, &copied_checksum,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, &had_props, &prop_mods,
- &have_base, NULL, &have_work,
- db, local_abspath,
- scratch_pool, scratch_pool));
-
{
const char *adm_abspath;
@@ -155,11 +149,12 @@ process_committed_leaf(svn_wc__db_t *db,
if (status == svn_wc__db_status_deleted)
{
return svn_error_trace(
- svn_wc__db_op_remove_node(
+ svn_wc__db_base_remove(
db, local_abspath,
- (have_base && !via_recurse)
+ FALSE /* keep_as_working */,
+ (! via_recurse)
? new_revnum : SVN_INVALID_REVNUM,
- kind,
+ NULL, NULL,
scratch_pool));
}
else if (status == svn_wc__db_status_not_present)
@@ -186,9 +181,9 @@ process_committed_leaf(svn_wc__db_t *db,
{
/* It was copied and not modified. We must have a text
base for it. And the node should have a checksum. */
- SVN_ERR_ASSERT(copied_checksum != NULL);
+ SVN_ERR_ASSERT(old_checksum != NULL);
- checksum = copied_checksum;
+ checksum = old_checksum;
/* Is the node completely unmodified and are we recursing? */
if (via_recurse && !prop_mods)
@@ -250,26 +245,41 @@ svn_wc__process_committed_internal(svn_w
const svn_wc_committed_queue_t *queue,
apr_pool_t *scratch_pool)
{
+ svn_wc__db_status_t status;
svn_kind_t kind;
+ const svn_checksum_t *old_checksum;
+ svn_boolean_t prop_mods;
+
+ SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, &old_checksum, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, &prop_mods, NULL, NULL, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
/* NOTE: be wary of making crazy semantic changes in this function, since
svn_wc_process_committed4() calls this. */
SVN_ERR(process_committed_leaf(db, local_abspath, !top_of_recurse,
+ status, kind, prop_mods, old_checksum,
new_revnum, new_date, rev_author,
new_dav_cache,
no_unlock, keep_changelist,
sha1_checksum,
scratch_pool));
- /* Only check kind after processing the node itself. The node might
- have been deleted */
- SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath,
- TRUE /* allow_missing */,
- TRUE /* show_hidden */,
- scratch_pool));
+ /* Only check for recursion on nodes that have children */
+ if (kind != svn_kind_file
+ || status == svn_wc__db_status_not_present
+ || status == svn_wc__db_status_excluded
+ || status == svn_wc__db_status_server_excluded
+ /* Node deleted -> then no longer a directory */
+ || status == svn_wc__db_status_deleted)
+ {
+ return SVN_NO_ERROR;
+ }
- if (recurse && kind == svn_kind_dir)
+ if (recurse)
{
const apr_array_header_t *children;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -284,38 +294,17 @@ svn_wc__process_committed_internal(svn_w
{
const char *name = APR_ARRAY_IDX(children, i, const char *);
const char *this_abspath;
- svn_wc__db_status_t status;
+ const committed_queue_item_t *cqi;
svn_pool_clear(iterpool);
this_abspath = svn_dirent_join(local_abspath, name, iterpool);
- 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, NULL, NULL, NULL,
- db, this_abspath,
- iterpool, iterpool));
-
- /* We come to this branch since we have committed a copied tree.
- svn_depth_exclude is possible in this situation. So check and
- skip */
- if (status == svn_wc__db_status_excluded)
- continue;
-
sha1_checksum = NULL;
- if (kind != svn_kind_dir && queue != NULL)
- {
- const committed_queue_item_t *cqi;
+ cqi = apr_hash_get(queue->queue, this_abspath, APR_HASH_KEY_STRING);
- cqi = apr_hash_get(queue->queue, this_abspath,
- APR_HASH_KEY_STRING);
- if (cqi != NULL)
- {
- sha1_checksum = cqi->sha1_checksum;
- }
- }
+ if (cqi != NULL)
+ sha1_checksum = cqi->sha1_checksum;
/* Recurse. Pass NULL for NEW_DAV_CACHE, because the
ones present in the current call are only applicable to
@@ -598,6 +587,72 @@ erase_unversioned_from_wc(const char *pa
return SVN_NO_ERROR;
}
+/* Helper for svn_wc__delete and svn_wc__delete_many */
+static svn_error_t *
+create_delete_wq_items(svn_skel_t **work_items,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_kind_t kind,
+ svn_boolean_t conflicted,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *work_items = NULL;
+
+ /* Schedule the on-disk delete */
+ if (kind == svn_kind_dir)
+ SVN_ERR(svn_wc__wq_build_dir_remove(work_items, db, local_abspath,
+ local_abspath,
+ TRUE /* recursive */,
+ result_pool, scratch_pool));
+ else
+ SVN_ERR(svn_wc__wq_build_file_remove(work_items, db, local_abspath,
+ local_abspath,
+ result_pool, scratch_pool));
+
+ /* Read conflicts, to allow deleting the markers after updating the DB */
+ if (conflicted)
+ {
+ svn_skel_t *conflict;
+ const apr_array_header_t *markers;
+ int i;
+
+ SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_wc__conflict_read_markers(&markers, db, local_abspath,
+ conflict,
+ scratch_pool, scratch_pool));
+
+ /* Maximum number of markers is 4, so no iterpool */
+ for (i = 0; markers && i < markers->nelts; i++)
+ {
+ const char *marker_abspath;
+ svn_node_kind_t marker_kind;
+
+ marker_abspath = APR_ARRAY_IDX(markers, i, const char *);
+ SVN_ERR(svn_io_check_path(marker_abspath, &marker_kind,
+ scratch_pool));
+
+ if (marker_kind == svn_node_file)
+ {
+ svn_skel_t *work_item;
+
+ SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+ local_abspath,
+ marker_abspath,
+ result_pool,
+ scratch_pool));
+
+ *work_items = svn_wc__wq_merge(*work_items, work_item,
+ result_pool);
+ }
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc__delete_many(svn_wc_context_t *wc_ctx,
const apr_array_header_t *targets,
@@ -613,7 +668,7 @@ svn_wc__delete_many(svn_wc_context_t *wc
svn_error_t *err;
svn_wc__db_status_t status;
svn_kind_t kind;
- const apr_array_header_t *conflicts = NULL;
+ svn_skel_t *work_items = NULL;
apr_array_header_t *versioned_targets;
const char *local_abspath;
int i;
@@ -689,74 +744,39 @@ svn_wc__delete_many(svn_wc_context_t *wc
iterpool),
iterpool));
- /* Read conflicts, to allow deleting the markers after updating the DB */
- if (!keep_local && conflicted)
- SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath,
- scratch_pool, iterpool));
+ /* Prepare the on-disk delete */
+ if (!keep_local)
+ {
+ svn_skel_t *work_item;
+
+ SVN_ERR(create_delete_wq_items(&work_item, db, local_abspath, kind,
+ conflicted,
+ scratch_pool, iterpool));
+ work_items = svn_wc__wq_merge(work_items, work_item,
+ scratch_pool);
+ }
}
if (versioned_targets->nelts == 0)
return SVN_NO_ERROR;
SVN_ERR(svn_wc__db_op_delete_many(db, versioned_targets,
+ !keep_local /* delete_dir_externals */,
+ work_items,
cancel_func, cancel_baton,
- notify_func, notify_baton, scratch_pool));
+ notify_func, notify_baton,
+ iterpool));
- if (!keep_local && conflicts != NULL)
+ if (work_items != NULL)
{
- svn_pool_clear(iterpool);
-
- /* Do we have conflict markers that should be removed? */
- for (i = 0; i < conflicts->nelts; i++)
- {
- const svn_wc_conflict_description2_t *desc;
-
- desc = APR_ARRAY_IDX(conflicts, i,
- const svn_wc_conflict_description2_t*);
+ /* Our only caller locked the wc, so for now assume it only passed
+ nodes from a single wc (asserted in svn_wc__db_op_delete_many) */
+ local_abspath = APR_ARRAY_IDX(versioned_targets, 0, const char *);
- if (desc->kind == svn_wc_conflict_kind_text)
- {
- if (desc->base_abspath != NULL)
- {
- SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
- iterpool));
- }
- if (desc->their_abspath != NULL)
- {
- SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
- iterpool));
- }
- if (desc->my_abspath != NULL)
- {
- SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
- iterpool));
- }
- }
- else if (desc->kind == svn_wc_conflict_kind_property
- && desc->their_abspath != NULL)
- {
- SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
- iterpool));
- }
- }
- }
-
- /* By the time we get here, the db knows that all targets are now
- * unversioned. */
- if (!keep_local)
- {
- for (i = 0; i < versioned_targets->nelts; i++)
- {
- svn_pool_clear(iterpool);
-
- local_abspath = APR_ARRAY_IDX(versioned_targets, i, const char *);
- SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
- cancel_func, cancel_baton,
- iterpool));
- }
+ SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+ iterpool));
}
-
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
@@ -780,7 +800,7 @@ svn_wc__delete_internal(svn_wc_context_t
svn_wc__db_status_t status;
svn_kind_t kind;
svn_boolean_t conflicted;
- const apr_array_header_t *conflicts;
+ svn_skel_t *work_items = NULL;
err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -834,64 +854,24 @@ svn_wc__delete_internal(svn_wc_context_t
SVN_ERR(svn_wc__write_check(db, svn_dirent_dirname(local_abspath, pool),
pool));
- /* Read conflicts, to allow deleting the markers after updating the DB */
- if (!keep_local && conflicted)
- SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath,
- scratch_pool, scratch_pool));
+ /* Prepare the on-disk delete */
+ if (!keep_local)
+ {
+ SVN_ERR(create_delete_wq_items(&work_items, db, local_abspath, kind,
+ conflicted,
+ scratch_pool, scratch_pool));
+ }
SVN_ERR(svn_wc__db_op_delete(db, local_abspath, moved_to_abspath,
- NULL, NULL,
+ !keep_local /* delete_dir_externals */,
+ NULL, work_items,
cancel_func, cancel_baton,
notify_func, notify_baton,
pool));
- if (!keep_local && conflicted && conflicts != NULL)
- {
- int i;
-
- /* Do we have conflict markers that should be removed? */
- for (i = 0; i < conflicts->nelts; i++)
- {
- const svn_wc_conflict_description2_t *desc;
-
- desc = APR_ARRAY_IDX(conflicts, i,
- const svn_wc_conflict_description2_t*);
-
- if (desc->kind == svn_wc_conflict_kind_text)
- {
- if (desc->base_abspath != NULL)
- {
- SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
- scratch_pool));
- }
- if (desc->their_abspath != NULL)
- {
- SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
- scratch_pool));
- }
- if (desc->my_abspath != NULL)
- {
- SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
- scratch_pool));
- }
- }
- else if (desc->kind == svn_wc_conflict_kind_property
- && desc->their_abspath != NULL)
- {
- SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
- scratch_pool));
- }
- }
- }
-
- /* By the time we get here, the db knows that everything that is still at
- LOCAL_ABSPATH is unversioned. */
- if (!keep_local)
- {
- SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
- cancel_func, cancel_baton,
- pool));
- }
+ if (work_items)
+ SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -1039,6 +1019,7 @@ check_can_add_node(svn_node_kind_t *kind
const char *base_name = svn_dirent_basename(local_abspath, scratch_pool);
svn_boolean_t is_wc_root;
svn_node_kind_t kind;
+ svn_boolean_t is_special;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
SVN_ERR_ASSERT(!copyfrom_url || (svn_uri_is_canonical(copyfrom_url,
@@ -1055,7 +1036,8 @@ check_can_add_node(svn_node_kind_t *kind
SVN_ERR(svn_path_check_valid(local_abspath, scratch_pool));
/* Make sure something's there; set KIND and *KIND_P. */
- SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
+ SVN_ERR(svn_io_check_special_path(local_abspath, &kind, &is_special,
+ scratch_pool));
if (kind == svn_node_none)
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("'%s' not found"),
@@ -1117,14 +1099,20 @@ check_can_add_node(svn_node_kind_t *kind
SVN_ERR_ASSERT(!is_wc_root);
break;
case svn_wc__db_status_normal:
- if (copyfrom_url)
- {
- SVN_ERR(svn_wc__check_wc_root(&is_wc_root, NULL, NULL,
- db, local_abspath,
- scratch_pool));
+ SVN_ERR(svn_wc__db_is_wcroot(&is_wc_root, db, local_abspath,
+ scratch_pool));
- if (is_wc_root)
- break;
+ if (is_wc_root && copyfrom_url)
+ {
+ /* Integrate a sub working copy in a parent working copy
+ (legacy behavior) */
+ break;
+ }
+ else if (is_wc_root && is_special)
+ {
+ /* Adding a symlink to a working copy root.
+ (special_tests.py 23: externals as symlink targets) */
+ break;
}
/* else: Fall through in default error */
@@ -1972,12 +1960,14 @@ revert_internal(svn_wc__db_t *db,
when local_abspath is the working copy root. */
{
const char *dir_abspath;
+ svn_boolean_t is_wcroot;
- SVN_ERR(svn_wc__db_get_wcroot(&dir_abspath, db, local_abspath,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, scratch_pool));
- if (svn_dirent_is_child(dir_abspath, local_abspath, NULL))
+ if (! is_wcroot)
dir_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+ else
+ dir_abspath = local_abspath;
SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
}
@@ -2127,7 +2117,7 @@ revert_partial(svn_wc__db_t *db,
{
svn_kind_t kind;
- SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath,
+ SVN_ERR(svn_wc__db_read_kind(&kind, db, child_abspath,
FALSE /* allow_missing */,
FALSE /* show_hidden */,
iterpool));
@@ -2330,214 +2320,68 @@ svn_error_t *
svn_wc__internal_remove_from_revision_control(svn_wc__db_t *db,
const char *local_abspath,
svn_boolean_t destroy_wf,
- svn_boolean_t instant_error,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *scratch_pool)
{
- svn_error_t *err;
svn_boolean_t left_something = FALSE;
- svn_wc__db_status_t status;
- svn_kind_t kind;
+ svn_boolean_t is_root;
+ svn_error_t *err = NULL;
- /* ### This whole function should be rewritten to run inside a transaction,
- ### to allow a stable cancel behavior.
- ###
- ### Subversion < 1.7 marked the directory as incomplete to allow updating
- ### it from a canceled state. But this would not work because update
- ### doesn't retrieve deleted items.
- ###
- ### WC-NG doesn't support a delete+incomplete state, but we can't build
- ### transactions over multiple databases yet. */
+ SVN_ERR(svn_wc__db_is_wcroot(&is_root, db, local_abspath, scratch_pool));
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
- /* Check cancellation here, so recursive calls get checked early. */
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- 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, NULL, NULL, NULL,
- db, local_abspath, scratch_pool, scratch_pool));
-
- if (kind == svn_kind_file || kind == svn_kind_symlink)
- {
- svn_boolean_t text_modified_p = FALSE;
-
- if (instant_error || destroy_wf)
- {
- svn_node_kind_t on_disk;
- SVN_ERR(svn_io_check_path(local_abspath, &on_disk, scratch_pool));
- if (on_disk == svn_node_file)
- {
- /* Check for local mods. before removing entry */
- SVN_ERR(svn_wc__internal_file_modified_p(&text_modified_p, db,
- local_abspath, FALSE,
- scratch_pool));
- if (text_modified_p && instant_error)
- return svn_error_createf(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
- _("File '%s' has local modifications"),
- svn_dirent_local_style(local_abspath, scratch_pool));
- }
- }
+ SVN_ERR(svn_wc__db_op_remove_node(&left_something,
+ db, local_abspath,
+ destroy_wf /* destroy_wc */,
+ destroy_wf /* destroy_changes */,
+ SVN_INVALID_REVNUM,
+ svn_wc__db_status_not_present,
+ svn_kind_none,
+ NULL, NULL,
+ cancel_func, cancel_baton,
+ scratch_pool));
- /* Remove NAME from DB */
- SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
- SVN_INVALID_REVNUM,
- svn_kind_unknown,
- scratch_pool));
-
- /* If we were asked to destroy the working file, do so unless
- it has local mods. */
- if (destroy_wf)
- {
- /* Don't kill local mods. */
- if (text_modified_p)
- return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL, NULL);
- else /* The working file is still present; remove it. */
- SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
- }
+ SVN_ERR(svn_wc__wq_run(db, local_abspath,
+ cancel_func, cancel_baton,
+ scratch_pool));
- } /* done with file case */
- else /* looking at THIS_DIR */
+ if (is_root)
{
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- const apr_array_header_t *children;
- int i;
-
- /* ### sanity check: check 2 places for DELETED flag? */
-
- /* Walk over every entry. */
- SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
- scratch_pool, iterpool));
-
- for (i = 0; i < children->nelts; i++)
- {
- const char *node_name = APR_ARRAY_IDX(children, i, const char*);
- const char *node_abspath;
- svn_wc__db_status_t node_status;
- svn_kind_t node_kind;
-
- svn_pool_clear(iterpool);
-
- node_abspath = svn_dirent_join(local_abspath, node_name, iterpool);
-
- SVN_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,
- db, node_abspath,
- iterpool, iterpool));
-
- if (node_status == svn_wc__db_status_normal
- && node_kind == svn_kind_dir)
- {
- svn_boolean_t is_root;
-
- SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL,
- db, node_abspath, iterpool));
-
- if (is_root)
- continue; /* Just skip working copies as obstruction */
- }
-
- if (node_status != svn_wc__db_status_normal
- && node_status != svn_wc__db_status_added
- && node_status != svn_wc__db_status_incomplete)
- {
- /* The node is already 'deleted', so nothing to do on
- versioned nodes */
- SVN_ERR(svn_wc__db_op_remove_node(db, node_abspath,
- SVN_INVALID_REVNUM,
- svn_kind_unknown,
- iterpool));
-
- continue;
- }
-
- err = svn_wc__internal_remove_from_revision_control(
- db, node_abspath,
- destroy_wf, instant_error,
- cancel_func, cancel_baton,
- iterpool);
-
- if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
- {
- if (instant_error)
- return svn_error_trace(err);
- else
- {
- svn_error_clear(err);
- left_something = TRUE;
- }
- }
- else if (err)
- return svn_error_trace(err);
- }
-
- /* At this point, every directory below this one has been
- removed from revision control. */
-
- /* Remove self from parent's entries file, but only if parent is
- a working copy. If it's not, that's fine, we just move on. */
- {
- svn_boolean_t is_root;
-
- SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL,
- db, local_abspath, iterpool));
-
- /* If full_path is not the top of a wc, then its parent
- directory is also a working copy and has an entry for
- full_path. We need to remove that entry: */
- if (! is_root)
- {
- SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
- SVN_INVALID_REVNUM,
- svn_kind_unknown,
- iterpool));
- }
- else
- {
- /* Remove the entire administrative .svn area, thereby removing
- _this_ dir from revision control too. */
- SVN_ERR(svn_wc__adm_destroy(db, local_abspath,
- cancel_func, cancel_baton, iterpool));
- }
- }
-
- /* If caller wants us to recursively nuke everything on disk, go
- ahead, provided that there are no dangling local-mod files
- below */
- if (destroy_wf && (! left_something))
- {
- /* If the dir is *truly* empty (i.e. has no unversioned
- resources, all versioned files are gone, all .svn dirs are
- gone, and contains nothing but empty dirs), then a
- *non*-recursive dir_remove should work. If it doesn't,
- no big deal. Just assume there are unversioned items in
- there and set "left_something" */
- err = svn_io_dir_remove_nonrecursive(local_abspath, iterpool);
- if (err)
- {
- if (!APR_STATUS_IS_ENOENT(err->apr_err))
- left_something = TRUE;
- svn_error_clear(err);
- }
- }
-
- svn_pool_destroy(iterpool);
+ /* Destroy the administrative area */
+ SVN_ERR(svn_wc__adm_destroy(db, local_abspath, cancel_func, cancel_baton,
+ scratch_pool));
- } /* end of directory case */
+ /* And if we didn't leave something interesting, remove the directory */
+ if (!left_something && destroy_wf)
+ err = svn_io_dir_remove_nonrecursive(local_abspath, scratch_pool);
+ }
- if (left_something)
- return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL, NULL);
+ if (left_something || err)
+ return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, err, NULL);
return SVN_NO_ERROR;
}
+/* Implements svn_wc_status_func4_t for svn_wc_remove_from_revision_control2 */
+static svn_error_t *
+remove_from_revision_status_callback(void *baton,
+ const char *local_abspath,
+ const svn_wc_status3_t *status,
+ apr_pool_t *scratch_pool)
+{
+ /* For legacy reasons we only check the file contents for changes */
+ if (status->versioned
+ && status->kind == svn_node_file
+ && (status->text_status == svn_wc_status_modified
+ || status->text_status == svn_wc_status_conflicted))
+ {
+ return svn_error_createf(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
+ _("File '%s' has local modifications"),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+ }
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_wc_remove_from_revision_control2(svn_wc_context_t *wc_ctx,
@@ -2548,11 +2392,18 @@ svn_wc_remove_from_revision_control2(svn
void *cancel_baton,
apr_pool_t *scratch_pool)
{
+ if (instant_error)
+ {
+ SVN_ERR(svn_wc_walk_status(wc_ctx, local_abspath, svn_depth_infinity,
+ FALSE, FALSE, FALSE, NULL,
+ remove_from_revision_status_callback, NULL,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ }
return svn_error_trace(
svn_wc__internal_remove_from_revision_control(wc_ctx->db,
local_abspath,
destroy_wf,
- instant_error,
cancel_func,
cancel_baton,
scratch_pool));
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/cleanup.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/cleanup.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/cleanup.c Sun Oct 21 02:00:31 2012
@@ -142,7 +142,7 @@ cleanup_internal(svn_wc__db_t *db,
apr_pool_t *scratch_pool)
{
int wc_format;
- const char *cleanup_abspath;
+ svn_boolean_t is_wcroot;
/* Can we even work with this directory? */
SVN_ERR(can_be_cleaned(&wc_format, db, dir_abspath, scratch_pool));
@@ -157,8 +157,7 @@ cleanup_internal(svn_wc__db_t *db,
SVN_ERR(svn_wc__wq_run(db, dir_abspath, cancel_func, cancel_baton,
scratch_pool));
- SVN_ERR(svn_wc__db_get_wcroot(&cleanup_abspath, db, dir_abspath,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, dir_abspath, scratch_pool));
#ifdef SVN_DEBUG
SVN_ERR(svn_wc__db_verify(db, dir_abspath, scratch_pool));
@@ -169,7 +168,7 @@ cleanup_internal(svn_wc__db_t *db,
svn_wc__check_wcroot() as that function, will just return true
once we start sharing databases with externals.
*/
- if (strcmp(cleanup_abspath, dir_abspath) == 0)
+ if (is_wcroot)
{
/* Cleanup the tmp area of the admin subdir, if running the log has not
removed it! The logs have been run, so anything left here has no hope
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c Sun Oct 21 02:00:31 2012
@@ -511,9 +511,6 @@ static const svn_token_map_t local_chang
{ "replaced", svn_wc_conflict_reason_replaced },
{ "moved-away", svn_wc_conflict_reason_moved_away },
{ "moved-here", svn_wc_conflict_reason_moved_here },
- /* ### Do we really need this. The edit state is on a different node,
- which might just change while the tree conflict exists? */
- { "moved-and-edited", svn_wc_conflict_reason_moved_away_and_edited },
{ NULL }
};
@@ -1155,7 +1152,7 @@ svn_wc__conflict_create_markers(svn_skel
SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath,
scratch_pool, scratch_pool));
else
- old_props = their_props;
+ old_props = their_original_props;
prop_data = prop_conflict_skel_new(result_pool);
@@ -1165,7 +1162,7 @@ svn_wc__conflict_create_markers(svn_skel
{
const char *propname = svn__apr_hash_index_key(hi);
- prop_conflict_skel_add(
+ SVN_ERR(prop_conflict_skel_add(
prop_data, propname,
old_props
? apr_hash_get(old_props, propname,
@@ -1183,7 +1180,7 @@ svn_wc__conflict_create_markers(svn_skel
? apr_hash_get(their_original_props, propname,
APR_HASH_KEY_STRING)
: NULL,
- result_pool, scratch_pool);
+ result_pool, scratch_pool));
}
SVN_ERR(svn_wc__wq_build_prej_install(work_items,
@@ -1603,11 +1600,15 @@ eval_text_conflict_func_result(svn_skel_
FALSE /* record_fileinfo */,
result_pool, scratch_pool));
*work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+
+ SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db, local_abspath,
+ result_pool, scratch_pool));
+ *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
if (remove_source)
{
SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
- db, install_from,
+ db, local_abspath, install_from,
result_pool, scratch_pool));
*work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
}
@@ -1682,7 +1683,6 @@ save_merge_result(svn_skel_t **work_item
db, local_abspath,
source, edited_copy_abspath,
result_pool, scratch_pool));
-
return SVN_NO_ERROR;
}
@@ -1828,7 +1828,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_
SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath,
scratch_pool, scratch_pool));
else
- old_props = their_props;
+ old_props = old_their_props;
iterpool = svn_pool_create(scratch_pool);
@@ -1910,10 +1910,164 @@ svn_wc__conflict_invoke_resolver(svn_wc_
return SVN_NO_ERROR;
}
+/* Read all property conflicts contained in CONFLICT_SKEL into
+ * individual conflict descriptions, and append those descriptions
+ * to the CONFLICTS array.
+ *
+ * If NOT create_tempfiles, always create a legacy property conflict
+ * descriptor.
+ *
+ * Allocate results in RESULT_POOL. SCRATCH_POOL is used for temporary
+ * allocations. */
+static svn_error_t *
+read_prop_conflicts(apr_array_header_t *conflicts,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_skel_t *conflict_skel,
+ svn_boolean_t create_tempfiles,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *prop_reject_file;
+ apr_hash_t *my_props;
+ apr_hash_t *their_old_props;
+ apr_hash_t *their_props;
+ apr_hash_t *conflicted_props;
+ apr_hash_index_t *hi;
+ apr_pool_t *iterpool;
+
+ SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file,
+ &my_props,
+ &their_old_props,
+ &their_props,
+ &conflicted_props,
+ db, local_abspath,
+ conflict_skel,
+ scratch_pool, scratch_pool));
+
+ if ((! create_tempfiles) || apr_hash_count(conflicted_props) == 0)
+ {
+ /* Legacy prop conflict with only a .reject file. */
+ svn_wc_conflict_description2_t *desc;
+
+ desc = svn_wc_conflict_description_create_prop2(local_abspath,
+ svn_node_unknown,
+ "", result_pool);
+
+ /* ### This should be changed. The prej file should be stored
+ * ### separately from the other files. We need to rev the
+ * ### conflict description struct for this. */
+ desc->their_abspath = apr_pstrdup(result_pool, prop_reject_file);
+
+ APR_ARRAY_PUSH(conflicts, svn_wc_conflict_description2_t*) = desc;
+
+ return SVN_NO_ERROR;
+ }
+
+ iterpool = svn_pool_create(scratch_pool);
+ for (hi = apr_hash_first(scratch_pool, conflicted_props);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *propname = svn__apr_hash_index_key(hi);
+ svn_string_t *old_value;
+ svn_string_t *my_value;
+ svn_string_t *their_value;
+ svn_wc_conflict_description2_t *desc;
+
+ svn_pool_clear(iterpool);
+
+ desc = svn_wc_conflict_description_create_prop2(local_abspath,
+ svn_node_unknown,
+ propname,
+ result_pool);
+
+ desc->property_name = apr_pstrdup(result_pool, propname);
+
+ my_value = apr_hash_get(my_props, propname, APR_HASH_KEY_STRING);
+ their_value = apr_hash_get(their_props, propname,
+ APR_HASH_KEY_STRING);
+
+ /* Compute the incoming side of the conflict ('action'). */
+ if (their_value == NULL)
+ desc->action = svn_wc_conflict_action_delete;
+ else if (my_value == NULL)
+ desc->action = svn_wc_conflict_action_add;
+ else
+ desc->action = svn_wc_conflict_action_edit;
+
+ /* Compute the local side of the conflict ('reason'). */
+ if (my_value == NULL)
+ desc->reason = svn_wc_conflict_reason_deleted;
+ else if (their_value == NULL)
+ desc->reason = svn_wc_conflict_reason_added;
+ else
+ desc->reason = svn_wc_conflict_reason_edited;
+
+ /* ### This should be changed. The prej file should be stored
+ * ### separately from the other files. We need to rev the
+ * ### conflict description struct for this. */
+ desc->their_abspath = apr_pstrdup(result_pool, prop_reject_file);
+
+ /* ### This should be changed. The conflict description for
+ * ### props should contain these values as svn_string_t,
+ * ### rather than in temporary files. We need to rev the
+ * ### conflict description struct for this. */
+ if (my_value)
+ {
+ svn_stream_t *s;
+ apr_size_t len;
+
+ SVN_ERR(svn_stream_open_unique(&s, &desc->my_abspath, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, iterpool));
+ len = my_value->len;
+ SVN_ERR(svn_stream_write(s, my_value->data, &len));
+ SVN_ERR(svn_stream_close(s));
+ }
+
+ if (their_value)
+ {
+ svn_stream_t *s;
+ apr_size_t len;
+
+ /* ### Currently, their_abspath is used for the prop reject file.
+ * ### Put their value into merged instead...
+ * ### We need to rev the conflict description struct to fix this. */
+ SVN_ERR(svn_stream_open_unique(&s, &desc->merged_file, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, iterpool));
+ len = their_value->len;
+ SVN_ERR(svn_stream_write(s, their_value->data, &len));
+ SVN_ERR(svn_stream_close(s));
+ }
+
+ old_value = apr_hash_get(their_old_props, propname, APR_HASH_KEY_STRING);
+ if (old_value)
+ {
+ svn_stream_t *s;
+ apr_size_t len;
+
+ SVN_ERR(svn_stream_open_unique(&s, &desc->base_abspath, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, iterpool));
+ len = old_value->len;
+ SVN_ERR(svn_stream_write(s, old_value->data, &len));
+ SVN_ERR(svn_stream_close(s));
+ }
+
+ APR_ARRAY_PUSH(conflicts, svn_wc_conflict_description2_t*) = desc;
+ }
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc__read_conflicts(const apr_array_header_t **conflicts,
svn_wc__db_t *db,
const char *local_abspath,
+ svn_boolean_t create_tempfiles,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -1945,21 +2099,9 @@ svn_wc__read_conflicts(const apr_array_h
sizeof(svn_wc_conflict_description2_t*));
if (prop_conflicted)
- {
- svn_wc_conflict_description2_t *desc;
- desc = svn_wc_conflict_description_create_prop2(local_abspath,
- svn_node_unknown,
- "",
- result_pool);
-
- SVN_ERR(svn_wc__conflict_read_prop_conflict(&desc->their_abspath,
- NULL, NULL, NULL, NULL,
- db, local_abspath,
- conflict_skel,
- result_pool, scratch_pool));
-
- APR_ARRAY_PUSH(cflcts, svn_wc_conflict_description2_t*) = desc;
- }
+ SVN_ERR(read_prop_conflicts(cflcts, db, local_abspath, conflict_skel,
+ create_tempfiles,
+ result_pool, scratch_pool));
if (text_conflicted)
{
@@ -2084,10 +2226,9 @@ svn_wc__read_conflicts(const apr_array_h
and clearing the conflict filenames from the entry. The latter needs to
be done whether or not the conflict files exist.
- PATH is the path to the item to be resolved, BASE_NAME is the basename
- of PATH, and CONFLICT_DIR is the access baton for PATH. ORIG_ENTRY is
- the entry prior to resolution. RESOLVE_TEXT and RESOLVE_PROPS are TRUE
- if text and property conflicts respectively are to be resolved.
+ LOCAL_ABSPATH in DB is the path to the item to be resolved.
+ RESOLVE_TEXT, RESOLVE_PROPS and RESOLVE_TREE are TRUE iff text, property
+ and tree conflicts respectively are to be resolved.
If this call marks any conflict as resolved, set *DID_RESOLVE to true,
else do not change *DID_RESOLVE.
@@ -2102,15 +2243,16 @@ resolve_conflict_on_node(svn_boolean_t *
svn_boolean_t resolve_props,
svn_boolean_t resolve_tree,
svn_wc_conflict_choice_t conflict_choice,
+ svn_skel_t *work_items,
svn_cancel_func_t cancel_func_t,
void *cancel_baton,
apr_pool_t *scratch_pool)
{
svn_skel_t *conflicts;
+ svn_wc_operation_t operation;
svn_boolean_t text_conflicted;
svn_boolean_t prop_conflicted;
svn_boolean_t tree_conflicted;
- svn_skel_t *work_items = NULL;
svn_skel_t *work_item;
apr_pool_t *pool = scratch_pool;
@@ -2122,7 +2264,7 @@ resolve_conflict_on_node(svn_boolean_t *
if (!conflicts)
return SVN_NO_ERROR;
- SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, &text_conflicted,
+ SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, &text_conflicted,
&prop_conflicted, &tree_conflicted,
db, local_abspath, conflicts,
scratch_pool, scratch_pool));
@@ -2210,6 +2352,11 @@ resolve_conflict_on_node(svn_boolean_t *
&work_item, db, local_abspath,
auto_resolve_src, local_abspath, pool, pool));
work_items = svn_wc__wq_merge(work_items, work_item, pool);
+
+ SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db,
+ local_abspath,
+ pool, pool));
+ work_items = svn_wc__wq_merge(work_items, work_item, pool);
}
/* Legacy behavior: Only report text conflicts as resolved when at least
@@ -2224,6 +2371,7 @@ resolve_conflict_on_node(svn_boolean_t *
if (node_kind == svn_node_file)
{
SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+ local_abspath,
conflict_old,
pool, pool));
work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2237,6 +2385,7 @@ resolve_conflict_on_node(svn_boolean_t *
if (node_kind == svn_node_file)
{
SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+ local_abspath,
conflict_new,
pool, pool));
work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2250,6 +2399,7 @@ resolve_conflict_on_node(svn_boolean_t *
if (node_kind == svn_node_file)
{
SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+ local_abspath,
conflict_working,
pool, pool));
work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2262,12 +2412,83 @@ resolve_conflict_on_node(svn_boolean_t *
{
svn_node_kind_t node_kind;
const char *prop_reject_file;
+ apr_hash_t *mine_props;
+ apr_hash_t *their_old_props;
+ apr_hash_t *their_props;
+ apr_hash_t *conflicted_props;
+ apr_hash_t *old_props;
+ apr_hash_t *resolve_from = NULL;
SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file,
- NULL, NULL, NULL, NULL,
+ &mine_props, &their_old_props,
+ &their_props, &conflicted_props,
db, local_abspath, conflicts,
scratch_pool, scratch_pool));
+ if (operation == svn_wc_operation_merge)
+ SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath,
+ scratch_pool, scratch_pool));
+ else
+ old_props = their_old_props;
+
+ /* We currently handle *_conflict as *_full as this argument is currently
+ always applied for all conflicts on a node at the same time. Giving
+ an error would break some tests that assumed that this would just
+ resolve property conflicts to working.
+
+ An alternative way to handle these conflicts would be to just copy all
+ property state from mine/theirs on the _full option instead of just the
+ conflicted properties. In some ways this feels like a sensible option as
+ that would take both properties and text from mine/theirs, but when not
+ both properties and text are conflicted we would fail in doing so.
+ */
+ switch (conflict_choice)
+ {
+ case svn_wc_conflict_choose_base:
+ resolve_from = their_old_props ? their_old_props : old_props;
+ break;
+ case svn_wc_conflict_choose_mine_full:
+ case svn_wc_conflict_choose_mine_conflict:
+ resolve_from = mine_props;
+ break;
+ case svn_wc_conflict_choose_theirs_full:
+ case svn_wc_conflict_choose_theirs_conflict:
+ resolve_from = their_props;
+ break;
+ case svn_wc_conflict_choose_merged:
+ resolve_from = NULL;
+ break;
+ default:
+ return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+ _("Invalid 'conflict_result' argument"));
+ }
+
+ if (conflicted_props && apr_hash_count(conflicted_props) && resolve_from)
+ {
+ apr_hash_index_t *hi;
+ apr_hash_t *actual_props;
+
+ SVN_ERR(svn_wc__db_read_props(&actual_props, db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ for (hi = apr_hash_first(scratch_pool, conflicted_props);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *propname = svn__apr_hash_index_key(hi);
+ svn_string_t *new_value = NULL;
+
+ new_value = apr_hash_get(resolve_from, propname,
+ APR_HASH_KEY_STRING);
+
+ apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING,
+ new_value);
+ }
+ SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props,
+ FALSE, NULL, NULL,
+ scratch_pool));
+ }
+
/* Legacy behavior: Only report property conflicts as resolved when the
property reject file exists
@@ -2280,6 +2501,7 @@ resolve_conflict_on_node(svn_boolean_t *
if (node_kind == svn_node_file)
{
SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+ local_abspath,
prop_reject_file,
pool, pool));
work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2320,6 +2542,7 @@ svn_wc__resolve_text_conflict(svn_wc__db
FALSE /* resolve_props */,
FALSE /* resolve_tree */,
svn_wc_conflict_choose_merged,
+ NULL,
NULL, NULL, /* cancel_func */
scratch_pool));
}
@@ -2361,7 +2584,7 @@ conflict_status_walker(void *baton,
iterpool = svn_pool_create(scratch_pool);
- SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath,
+ SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath, TRUE,
scratch_pool, iterpool));
for (i = 0; i < conflicts->nelts; i++)
@@ -2369,6 +2592,8 @@ conflict_status_walker(void *baton,
const svn_wc_conflict_description2_t *cd;
svn_boolean_t did_resolve;
svn_wc_conflict_choice_t my_choice = cswb->conflict_choice;
+ svn_skel_t *work_items = NULL;
+
cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *);
@@ -2399,15 +2624,32 @@ conflict_status_walker(void *baton,
if (!cswb->resolve_tree)
break;
- /* For now, we only clear tree conflict information and resolve
- * to the working state. There is no way to pick theirs-full
- * or mine-full, etc. Throw an error if the user expects us
- * to be smarter than we really are. */
- if (my_choice != svn_wc_conflict_choose_merged)
+ /* After updates, we can resolve local moved-away vs. any incoming
+ * change, either by updating the moved-away node (mine-conflict)
+ * or by breaking the move (theirs-conflict). */
+ if ((cd->operation == svn_wc_operation_update ||
+ cd->operation == svn_wc_operation_switch) &&
+ cd->reason == svn_wc_conflict_reason_moved_away)
+ {
+ if (my_choice == svn_wc_conflict_choose_mine_conflict)
+ SVN_ERR(svn_wc__update_moved_away_conflict_victim(
+ &work_items, local_abspath, cswb->db,
+ cswb->notify_func, cswb->notify_baton,
+ cswb->cancel_func, cswb->cancel_baton,
+ scratch_pool, scratch_pool));
+ else if (my_choice == svn_wc_conflict_choose_theirs_conflict)
+ {
+ /* ### TODO break move */
+ }
+ }
+ else if (my_choice != svn_wc_conflict_choose_merged)
{
+ /* For other tree conflicts, there is no way to pick
+ * theirs-full or mine-full, etc. Throw an error if the
+ * user expects us to be smarter than we really are. */
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
NULL,
- _("Tree conflicts can only be "
+ _("Tree conflict can only be "
"resolved to 'working' state; "
"'%s' not resolved"),
svn_dirent_local_style(local_abspath,
@@ -2421,6 +2663,7 @@ conflict_status_walker(void *baton,
FALSE /* resolve_props */,
TRUE /* resolve_tree */,
my_choice,
+ work_items,
cswb->cancel_func,
cswb->cancel_baton,
iterpool));
@@ -2439,6 +2682,7 @@ conflict_status_walker(void *baton,
FALSE /* resolve_props */,
FALSE /* resolve_tree */,
my_choice,
+ NULL,
cswb->cancel_func,
cswb->cancel_baton,
iterpool));
@@ -2468,6 +2712,7 @@ conflict_status_walker(void *baton,
TRUE /* resolve_props */,
FALSE /* resolve_tree */,
my_choice,
+ NULL,
cswb->cancel_func,
cswb->cancel_baton,
iterpool));
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h Sun Oct 21 02:00:31 2012
@@ -260,6 +260,8 @@ svn_wc__conflict_skel_resolve(svn_boolea
*
* Output arguments can be NULL if the value is not necessary.
*
+ * ### stsp asks: what is LOCATIONS?
+ *
* TEXT_, PROP_ and TREE_CONFLICTED (when not NULL) will be set to TRUE
* when the conflict contains the specified kind of conflict, otherwise
* to false.
@@ -392,6 +394,20 @@ svn_wc__resolve_text_conflict(svn_wc__db
const char *local_abspath,
apr_pool_t *scratch_pool);
+/* Update a moved-away tree conflict victim at VICTIM_ABSPATH with changes
+ * brought in by the update operation which flagged the tree conflict.
+ * Set *WORK_ITEMS to a list of work items, allocated in RESULT_POOL, that
+ * need to run as part of marking the conflict resolved. */
+svn_error_t *
+svn_wc__update_moved_away_conflict_victim(svn_skel_t **work_items,
+ const char *victim_abspath,
+ svn_wc__db_t *db,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/copy.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/copy.c Sun Oct 21 02:00:31 2012
@@ -36,6 +36,7 @@
#include "wc.h"
#include "workqueue.h"
#include "props.h"
+#include "conflicts.h"
#include "svn_private_config.h"
#include "private/svn_wc_private.h"
@@ -206,7 +207,6 @@ copy_versioned_file(svn_wc__db_t *db,
if (!metadata_only)
{
const char *my_src_abspath = NULL;
- int i;
svn_boolean_t handle_as_unversioned = FALSE;
/* By default, take the copy source as given. */
@@ -214,26 +214,27 @@ copy_versioned_file(svn_wc__db_t *db,
if (conflicted)
{
- const apr_array_header_t *conflicts;
- const char *conflict_working = NULL;
+ svn_skel_t *conflict;
+ const char *conflict_working;
+ svn_error_t *err;
/* Is there a text conflict at the source path? */
- SVN_ERR(svn_wc__read_conflicts(&conflicts, db, src_abspath,
+ SVN_ERR(svn_wc__db_read_conflict(&conflict, db, src_abspath,
scratch_pool, scratch_pool));
- for (i = 0; i < conflicts->nelts; i++)
- {
- const svn_wc_conflict_description2_t *desc;
-
- desc = APR_ARRAY_IDX(conflicts, i,
- const svn_wc_conflict_description2_t*);
+ err = svn_wc__conflict_read_text_conflict(&conflict_working, NULL, NULL,
+ db, src_abspath, conflict,
+ scratch_pool,
+ scratch_pool);
- if (desc->kind == svn_wc_conflict_kind_text)
- {
- conflict_working = desc->my_abspath;
- break;
- }
+ if (err && err->apr_err == SVN_ERR_WC_MISSING)
+ {
+ /* not text conflicted */
+ svn_error_clear(err);
+ conflict_working = NULL;
}
+ else
+ SVN_ERR(err);
if (conflict_working)
{
@@ -287,7 +288,9 @@ copy_versioned_file(svn_wc__db_t *db,
otherwise copy both the versioned metadata and the filesystem nodes (even
if they are the wrong kind, and including unversioned children).
If IS_MOVE is true, record move information in working copy meta
- data in addition to copying the directory.
+ data in addition to copying the directory. If IS_MOVE is TRUE and
+ ALLOW_MIXED_REVISIONS is FALSE, raise an error if a move of a
+ mixed-revision subtree is attempted.
WITHIN_ONE_WC is TRUE if the copy/move is within a single working copy (root)
*/
@@ -299,6 +302,7 @@ copy_versioned_dir(svn_wc__db_t *db,
const char *tmpdir_abspath,
svn_boolean_t metadata_only,
svn_boolean_t is_move,
+ svn_boolean_t allow_mixed_revisions,
svn_boolean_t within_one_wc,
svn_cancel_func_t cancel_func,
void *cancel_baton,
@@ -315,6 +319,24 @@ copy_versioned_dir(svn_wc__db_t *db,
svn_node_kind_t disk_kind;
apr_pool_t *iterpool;
+ if (is_move && !allow_mixed_revisions)
+ {
+ svn_revnum_t min_rev;
+ svn_revnum_t max_rev;
+
+ /* Verify that the move source is a single-revision subtree. */
+ SVN_ERR(svn_wc__db_min_max_revisions(&min_rev, &max_rev, db,
+ src_abspath, FALSE, scratch_pool));
+ if (SVN_IS_VALID_REVNUM(min_rev) && SVN_IS_VALID_REVNUM(max_rev) &&
+ min_rev != max_rev)
+ return svn_error_createf(SVN_ERR_WC_MIXED_REVISIONS, NULL,
+ _("Cannot move mixed-revision subtree '%s' "
+ "[%lu:%lu]; try updating it first"),
+ svn_dirent_local_style(src_abspath,
+ scratch_pool),
+ min_rev, max_rev);
+ }
+
/* Prepare a temp copy of the single filesystem node (usually a dir). */
if (!metadata_only)
{
@@ -412,7 +434,8 @@ copy_versioned_dir(svn_wc__db_t *db,
SVN_ERR(copy_versioned_dir(db,
child_src_abspath, child_dst_abspath,
dst_op_root_abspath, tmpdir_abspath,
- metadata_only, is_move, within_one_wc,
+ metadata_only, is_move,
+ allow_mixed_revisions, within_one_wc,
cancel_func, cancel_baton, NULL, NULL,
iterpool));
else
@@ -523,6 +546,7 @@ copy_or_move(svn_wc_context_t *wc_ctx,
const char *dst_abspath,
svn_boolean_t metadata_only,
svn_boolean_t is_move,
+ svn_boolean_t allow_mixed_revisions,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
@@ -737,8 +761,8 @@ copy_or_move(svn_wc_context_t *wc_ctx,
else
{
err = copy_versioned_dir(db, src_abspath, dst_abspath, dst_abspath,
- tmpdir_abspath,
- metadata_only, is_move, within_one_wc,
+ tmpdir_abspath, metadata_only, is_move,
+ allow_mixed_revisions, within_one_wc,
cancel_func, cancel_baton,
notify_func, notify_baton,
scratch_pool);
@@ -773,6 +797,7 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
{
return svn_error_trace(copy_or_move(wc_ctx, src_abspath, dst_abspath,
metadata_only, FALSE /* is_move */,
+ TRUE /* allow_mixed_revisions */,
cancel_func, cancel_baton,
notify_func, notify_baton,
scratch_pool));
@@ -792,75 +817,40 @@ remove_node_conflict_markers(svn_wc__db_
const char *node_abspath,
apr_pool_t *scratch_pool)
{
- const apr_array_header_t *conflicts;
+ svn_skel_t *conflict;
- SVN_ERR(svn_wc__read_conflicts(&conflicts, db, src_abspath,
+ SVN_ERR(svn_wc__db_read_conflict(&conflict, db, src_abspath,
scratch_pool, scratch_pool));
/* Do we have conflict markers that should be removed? */
- if (conflicts != NULL)
+ if (conflict != NULL)
{
+ const apr_array_header_t *markers;
int i;
const char *src_dir = svn_dirent_dirname(src_abspath, scratch_pool);
const char *dst_dir = svn_dirent_dirname(node_abspath, scratch_pool);
- /* No iterpool: Maximum number of possible conflict markers is 4 */
+ SVN_ERR(svn_wc__conflict_read_markers(&markers, db, src_abspath,
+ conflict,
+ scratch_pool, scratch_pool));
- for (i = 0; i < conflicts->nelts; i++)
+ /* No iterpool: Maximum number of possible conflict markers is 4 */
+ for (i = 0; markers && (i < markers->nelts); i++)
{
- const svn_wc_conflict_description2_t *desc;
+ const char *marker_abspath;
const char *child_relpath;
const char *child_abpath;
- desc = APR_ARRAY_IDX(conflicts, i,
- const svn_wc_conflict_description2_t*);
-
- if (desc->kind != svn_wc_conflict_kind_text
- && desc->kind != svn_wc_conflict_kind_property)
- continue;
-
- if (desc->base_abspath != NULL)
- {
- child_relpath = svn_dirent_is_child(src_dir, desc->base_abspath,
- NULL);
+ marker_abspath = APR_ARRAY_IDX(markers, i, const char *);
- if (child_relpath)
- {
- child_abpath = svn_dirent_join(dst_dir, child_relpath,
- scratch_pool);
+ child_relpath = svn_dirent_is_child(src_dir, marker_abspath, NULL);
- SVN_ERR(svn_io_remove_file2(child_abpath, TRUE,
- scratch_pool));
- }
- }
- if (desc->their_abspath != NULL)
+ if (child_relpath)
{
- child_relpath = svn_dirent_is_child(src_dir, desc->their_abspath,
- NULL);
-
- if (child_relpath)
- {
- child_abpath = svn_dirent_join(dst_dir, child_relpath,
- scratch_pool);
+ child_abpath = svn_dirent_join(dst_dir, child_relpath,
+ scratch_pool);
- SVN_ERR(svn_io_remove_file2(child_abpath, TRUE,
- scratch_pool));
- }
- }
- if (desc->my_abspath != NULL)
- {
- child_relpath = svn_dirent_is_child(src_dir, desc->my_abspath,
- NULL);
-
- if (child_relpath)
- {
- child_abpath = svn_dirent_join(dst_dir, child_relpath,
- scratch_pool);
-
- /* ### Copy child_abspath to node_abspath if it exists? */
- SVN_ERR(svn_io_remove_file2(child_abpath, TRUE,
- scratch_pool));
- }
+ SVN_ERR(svn_io_remove_file2(child_abpath, TRUE, scratch_pool));
}
}
}
@@ -928,21 +918,23 @@ remove_all_conflict_markers(svn_wc__db_t
}
svn_error_t *
-svn_wc_move(svn_wc_context_t *wc_ctx,
- const char *src_abspath,
- const char *dst_abspath,
- svn_boolean_t metadata_only,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
+svn_wc__move2(svn_wc_context_t *wc_ctx,
+ const char *src_abspath,
+ const char *dst_abspath,
+ svn_boolean_t metadata_only,
+ svn_boolean_t allow_mixed_revisions,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
{
svn_wc__db_t *db = wc_ctx->db;
SVN_ERR(copy_or_move(wc_ctx, src_abspath, dst_abspath,
TRUE /* metadata_only */,
TRUE /* is_move */,
+ allow_mixed_revisions,
cancel_func, cancel_baton,
notify_func, notify_baton,
scratch_pool));
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/crop.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/crop.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/crop.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/crop.c Sun Oct 21 02:00:31 2012
@@ -31,24 +31,10 @@
#include "svn_path.h"
#include "wc.h"
+#include "workqueue.h"
#include "svn_private_config.h"
-/* Evaluate EXPR. If it returns an error, return that error, unless
- the error's code is SVN_ERR_WC_LEFT_LOCAL_MOD, in which case clear
- the error and do not return. */
-#define IGNORE_LOCAL_MOD(expr) \
- do { \
- svn_error_t *__temp = (expr); \
- if (__temp) \
- { \
- if (__temp->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD) \
- svn_error_clear(__temp); \
- else \
- return svn_error_trace(__temp); \
- } \
- } while (0)
-
/* Helper function that crops the children of the LOCAL_ABSPATH, under the
* constraint of NEW_DEPTH. The DIR_PATH itself will never be cropped. The
* whole subtree should have been locked.
@@ -121,29 +107,25 @@ crop_children(svn_wc__db_t *db,
? svn_depth_immediates
: svn_depth_files;
if (new_depth < remove_below)
- SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
- SVN_INVALID_REVNUM,
- svn_kind_unknown,
- iterpool));
+ SVN_ERR(svn_wc__db_base_remove(db, local_abspath, FALSE,
+ SVN_INVALID_REVNUM,
+ NULL, NULL, iterpool));
continue;
}
else if (kind == svn_kind_file)
{
- /* We currently crop on a directory basis. So don't worry about
- svn_depth_exclude here. And even we permit excluding a single
- file in the future, svn_wc_remove_from_revision_control() can
- also handle it. We only need to skip the notification in that
- case. */
if (new_depth == svn_depth_empty)
- IGNORE_LOCAL_MOD(
- svn_wc__internal_remove_from_revision_control(
- db,
- child_abspath,
- TRUE, /* destroy */
- FALSE, /* instant error */
- cancel_func, cancel_baton,
- iterpool));
+ SVN_ERR(svn_wc__db_op_remove_node(NULL,
+ db, child_abspath,
+ TRUE /* destroy */,
+ FALSE /* destroy_changes */,
+ SVN_INVALID_REVNUM,
+ svn_wc__db_status_not_present,
+ svn_kind_none,
+ NULL, NULL,
+ cancel_func, cancel_baton,
+ iterpool));
else
continue;
@@ -152,15 +134,16 @@ crop_children(svn_wc__db_t *db,
{
if (new_depth < svn_depth_immediates)
{
- IGNORE_LOCAL_MOD(
- svn_wc__internal_remove_from_revision_control(
- db,
- child_abspath,
- TRUE, /* destroy */
- FALSE, /* instant error */
- cancel_func,
- cancel_baton,
- iterpool));
+ SVN_ERR(svn_wc__db_op_remove_node(NULL,
+ db, child_abspath,
+ TRUE /* destroy */,
+ FALSE /* destroy_changes */,
+ SVN_INVALID_REVNUM,
+ svn_wc__db_status_not_present,
+ svn_kind_none,
+ NULL, NULL,
+ cancel_func, cancel_baton,
+ iterpool));
}
else
{
@@ -272,27 +255,21 @@ svn_wc_exclude(svn_wc_context_t *wc_ctx,
break; /* Ok to exclude */
}
- /* ### This could use some kind of transaction */
-
/* Remove all working copy data below local_abspath */
- IGNORE_LOCAL_MOD(svn_wc__internal_remove_from_revision_control(
- wc_ctx->db,
- local_abspath,
- TRUE,
- FALSE,
+ SVN_ERR(svn_wc__db_op_remove_node(NULL,
+ wc_ctx->db, local_abspath,
+ TRUE /* destroy */,
+ FALSE /* destroy_changes */,
+ revision,
+ svn_wc__db_status_excluded,
+ kind,
+ NULL, NULL,
cancel_func, cancel_baton,
scratch_pool));
- SVN_ERR(svn_wc__db_base_add_excluded_node(wc_ctx->db,
- local_abspath,
- repos_relpath,
- repos_root,
- repos_uuid,
- revision,
- kind,
- svn_wc__db_status_excluded,
- NULL, NULL,
- scratch_pool));
+ SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath,
+ cancel_func, cancel_baton,
+ scratch_pool));
if (notify_func)
{
@@ -372,7 +349,11 @@ svn_wc_crop_tree2(svn_wc_context_t *wc_c
SVN_ERR_MALFUNCTION();
}
- return crop_children(db, local_abspath, dir_depth, depth,
- notify_func, notify_baton,
- cancel_func, cancel_baton, scratch_pool);
+ SVN_ERR(crop_children(db, local_abspath, dir_depth, depth,
+ notify_func, notify_baton,
+ cancel_func, cancel_baton, scratch_pool));
+
+ return svn_error_trace(svn_wc__wq_run(db, local_abspath,
+ cancel_func, cancel_baton,
+ scratch_pool));
}