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 2013/01/22 00:37:04 UTC
svn commit: r1436688 [5/12] - in /subversion/branches/ev2-export: ./
contrib/client-side/emacs/ notes/commit-access-templates/
subversion/bindings/javahl/native/ subversion/bindings/swig/perl/native/t/
subversion/bindings/swig/ruby/test/ subversion/inc...
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/io.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/io.c Mon Jan 21 23:37:01 2013
@@ -2262,7 +2262,9 @@ svn_io_remove_file2(const char *path,
apr_err = apr_file_remove(path_apr, scratch_pool);
if (!apr_err
- || (ignore_enoent && APR_STATUS_IS_ENOENT(apr_err)))
+ || (ignore_enoent
+ && (APR_STATUS_IS_ENOENT(apr_err)
+ || SVN__APR_STATUS_IS_ENOTDIR(apr_err))))
return SVN_NO_ERROR;
#ifdef WIN32
@@ -2491,20 +2493,25 @@ svn_io_get_dirents3(apr_hash_t **dirents
}
svn_error_t *
-svn_io_stat_dirent(const svn_io_dirent2_t **dirent_p,
- const char *path,
- svn_boolean_t ignore_enoent,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_io_stat_dirent2(const svn_io_dirent2_t **dirent_p,
+ const char *path,
+ svn_boolean_t verify_truename,
+ svn_boolean_t ignore_enoent,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
apr_finfo_t finfo;
svn_io_dirent2_t *dirent;
svn_error_t *err;
+ apr_int32_t wanted = APR_FINFO_TYPE | APR_FINFO_LINK
+ | APR_FINFO_SIZE | APR_FINFO_MTIME;
- err = svn_io_stat(&finfo, path,
- APR_FINFO_TYPE | APR_FINFO_LINK
- | APR_FINFO_SIZE | APR_FINFO_MTIME,
- scratch_pool);
+#if defined(WIN32) || defined(__OS2__)
+ if (verify_truename)
+ wanted |= APR_FINFO_NAME;
+#endif
+
+ err = svn_io_stat(&finfo, path, wanted, scratch_pool);
if (err && ignore_enoent &&
(APR_STATUS_IS_ENOENT(err->apr_err)
@@ -2519,6 +2526,78 @@ svn_io_stat_dirent(const svn_io_dirent2_
}
SVN_ERR(err);
+#if defined(WIN32) || defined(__OS2__) || defined(DARWIN)
+ if (verify_truename)
+ {
+ const char *requested_name = svn_dirent_basename(path, NULL);
+
+ if (requested_name[0] == '\0')
+ {
+ /* No parent directory. No need to stat/verify */
+ }
+#if defined(WIN32) || defined(__OS2__)
+ else if (finfo.name)
+ {
+ const char *name_on_disk;
+ SVN_ERR(entry_name_to_utf8(&name_on_disk, finfo.name, path,
+ scratch_pool));
+
+ if (strcmp(name_on_disk, requested_name) /* != 0 */)
+ {
+ if (ignore_enoent)
+ {
+ *dirent_p = svn_io_dirent2_create(result_pool);
+ return SVN_NO_ERROR;
+ }
+ else
+ return svn_error_createf(APR_ENOENT, NULL,
+ _("Path '%s' not found, case obstructed by '%s'"),
+ svn_dirent_local_style(path, scratch_pool),
+ name_on_disk);
+ }
+ }
+#elif defined(DARWIN)
+ /* Currently apr doesn't set finfo.name on DARWIN, returning
+ APR_INCOMPLETE.
+ ### Can we optimize this in another way? */
+ else
+ {
+ apr_hash_t *dirents;
+
+ err = svn_io_get_dirents3(&dirents,
+ svn_dirent_dirname(path, scratch_pool),
+ TRUE /* only_check_type */,
+ scratch_pool, scratch_pool);
+
+ if (err && ignore_enoent
+ && (APR_STATUS_IS_ENOENT(err->apr_err)
+ || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
+ {
+ svn_error_clear(err);
+
+ *dirent_p = svn_io_dirent2_create(result_pool);
+ return SVN_NO_ERROR;
+ }
+ else
+ SVN_ERR(err);
+
+ if (! apr_hash_get(dirents, requested_name, APR_HASH_KEY_STRING))
+ {
+ if (ignore_enoent)
+ {
+ *dirent_p = svn_io_dirent2_create(result_pool);
+ return SVN_NO_ERROR;
+ }
+ else
+ return svn_error_createf(APR_ENOENT, NULL,
+ _("Path '%s' not found"),
+ svn_dirent_local_style(path, scratch_pool));
+ }
+ }
+#endif
+ }
+#endif
+
dirent = svn_io_dirent2_create(result_pool);
map_apr_finfo_to_node_kind(&(dirent->kind), &(dirent->special), &finfo);
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/sysinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/sysinfo.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/sysinfo.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/sysinfo.c Mon Jan 21 23:37:01 2013
@@ -42,7 +42,9 @@
#include <apr_version.h>
#include <apu_version.h>
+#include "svn_pools.h"
#include "svn_ctype.h"
+#include "svn_dirent_uri.h"
#include "svn_error.h"
#include "svn_io.h"
#include "svn_string.h"
@@ -831,25 +833,19 @@ win32_shared_libs(apr_pool_t *pool)
if (GetModuleFileNameW(*module, buffer, MAX_PATH))
{
buffer[MAX_PATH] = 0;
+
version = file_version_number(buffer, pool);
filename = wcs_to_utf8(buffer, pool);
if (filename)
{
svn_version_ext_loaded_lib_t *lib;
- char *truename;
-
- if (0 == apr_filepath_merge(&truename, "", filename,
- APR_FILEPATH_NATIVE
- | APR_FILEPATH_TRUENAME,
- pool))
- filename = truename;
if (!array)
{
array = apr_array_make(pool, 32, sizeof(*lib));
}
lib = &APR_ARRAY_PUSH(array, svn_version_ext_loaded_lib_t);
- lib->name = filename;
+ lib->name = svn_dirent_local_style(filename, pool);
lib->version = version;
}
}
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/types.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/types.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/types.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/types.c Mon Jan 21 23:37:01 2013
@@ -282,6 +282,20 @@ svn_log_changed_path2_dup(const svn_log_
}
svn_dirent_t *
+svn_dirent_create(apr_pool_t *result_pool)
+{
+ svn_dirent_t *new_dirent = apr_pcalloc(result_pool, sizeof(*new_dirent));
+
+ new_dirent->kind = svn_node_unknown;
+ new_dirent->size = SVN_INVALID_FILESIZE;
+ new_dirent->created_rev = SVN_INVALID_REVNUM;
+ new_dirent->time = 0;
+ new_dirent->last_author = NULL;
+
+ return new_dirent;
+}
+
+svn_dirent_t *
svn_dirent_dup(const svn_dirent_t *dirent,
apr_pool_t *pool)
{
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=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c Mon Jan 21 23:37:01 2013
@@ -32,9 +32,7 @@
#include <stdlib.h>
#include <apr_pools.h>
-#include <apr_tables.h>
#include <apr_hash.h>
-#include <apr_file_io.h>
#include <apr_time.h>
#include <apr_errno.h>
@@ -53,13 +51,9 @@
#include "wc.h"
#include "adm_files.h"
#include "conflicts.h"
-#include "props.h"
-#include "translate.h"
#include "workqueue.h"
#include "svn_private_config.h"
-#include "private/svn_io_private.h"
-#include "private/svn_wc_private.h"
#include "private/svn_subr_private.h"
@@ -152,6 +146,7 @@ process_committed_leaf(svn_wc__db_t *db,
svn_wc__db_base_remove(
db, local_abspath,
FALSE /* keep_as_working */,
+ FALSE /* queue_deletes */,
(! via_recurse)
? new_revnum : SVN_INVALID_REVNUM,
NULL, NULL,
@@ -526,377 +521,6 @@ svn_wc_process_committed_queue2(svn_wc_c
return SVN_NO_ERROR;
}
-
-/* Remove/erase PATH from the working copy. This involves deleting PATH
- * from the physical filesystem. PATH is assumed to be an unversioned file
- * or directory.
- *
- * If ignore_enoent is TRUE, ignore missing targets.
- *
- * If CANCEL_FUNC is non-null, invoke it with CANCEL_BATON at various
- * points, return any error immediately.
- */
-static svn_error_t *
-erase_unversioned_from_wc(const char *path,
- svn_boolean_t ignore_enoent,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
-{
- svn_error_t *err;
-
- /* Optimize the common case: try to delete the file */
- err = svn_io_remove_file2(path, ignore_enoent, scratch_pool);
- if (err)
- {
- /* Then maybe it was a directory? */
- svn_error_clear(err);
-
- err = svn_io_remove_dir2(path, ignore_enoent, cancel_func, cancel_baton,
- scratch_pool);
-
- if (err)
- {
- /* We're unlikely to end up here. But we need this fallback
- to make sure we report the right error *and* try the
- correct deletion at least once. */
- svn_node_kind_t kind;
-
- svn_error_clear(err);
- SVN_ERR(svn_io_check_path(path, &kind, scratch_pool));
- if (kind == svn_node_file)
- SVN_ERR(svn_io_remove_file2(path, ignore_enoent, scratch_pool));
- else if (kind == svn_node_dir)
- SVN_ERR(svn_io_remove_dir2(path, ignore_enoent,
- cancel_func, cancel_baton,
- scratch_pool));
- else if (kind == svn_node_none)
- return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
- _("'%s' does not exist"),
- svn_dirent_local_style(path,
- scratch_pool));
- else
- return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
- _("Unsupported node kind for path '%s'"),
- svn_dirent_local_style(path,
- scratch_pool));
-
- }
- }
-
- 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,
- svn_boolean_t keep_local,
- svn_boolean_t delete_unversioned_target,
- 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_error_t *err;
- svn_wc__db_status_t status;
- svn_kind_t kind;
- svn_skel_t *work_items = NULL;
- apr_array_header_t *versioned_targets;
- const char *local_abspath;
- int i;
- apr_pool_t *iterpool;
-
- iterpool = svn_pool_create(scratch_pool);
- versioned_targets = apr_array_make(scratch_pool, targets->nelts,
- sizeof(const char *));
- for (i = 0; i < targets->nelts; i++)
- {
- svn_boolean_t conflicted = FALSE;
-
- svn_pool_clear(iterpool);
-
- local_abspath = APR_ARRAY_IDX(targets, i, const char *);
- 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, &conflicted,
- NULL, NULL, NULL, NULL, NULL, NULL,
- db, local_abspath, iterpool, iterpool);
-
- if (err)
- {
- if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- {
- svn_error_clear(err);
- if (delete_unversioned_target && !keep_local)
- SVN_ERR(erase_unversioned_from_wc(local_abspath, FALSE,
- cancel_func, cancel_baton,
- iterpool));
- continue;
- }
- else
- return svn_error_trace(err);
- }
-
- APR_ARRAY_PUSH(versioned_targets, const char *) = local_abspath;
-
- switch (status)
- {
- /* svn_wc__db_status_server_excluded handled by
- * svn_wc__db_op_delete_many */
- case svn_wc__db_status_excluded:
- case svn_wc__db_status_not_present:
- return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
- _("'%s' cannot be deleted"),
- svn_dirent_local_style(local_abspath,
- iterpool));
-
- /* Explicitly ignore other statii */
- default:
- break;
- }
-
- if (status == svn_wc__db_status_normal
- && kind == svn_kind_dir)
- {
- svn_boolean_t is_wcroot;
- SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath,
- iterpool));
-
- if (is_wcroot)
- return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
- _("'%s' is the root of a working copy and "
- "cannot be deleted"),
- svn_dirent_local_style(local_abspath,
- iterpool));
- }
-
- /* Verify if we have a write lock on the parent of this node as we might
- be changing the childlist of that directory. */
- SVN_ERR(svn_wc__write_check(db, svn_dirent_dirname(local_abspath,
- iterpool),
- 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,
- iterpool));
-
- if (work_items != NULL)
- {
- /* 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 *);
-
- SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
- iterpool));
- }
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_wc__delete_internal(svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- svn_boolean_t keep_local,
- svn_boolean_t delete_unversioned_target,
- const char *moved_to_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
-{
- apr_pool_t *pool = scratch_pool;
- svn_wc__db_t *db = wc_ctx->db;
- svn_error_t *err;
- svn_wc__db_status_t status;
- svn_kind_t kind;
- svn_boolean_t conflicted;
- 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,
- NULL, NULL, NULL, NULL, NULL, &conflicted,
- NULL, NULL, NULL, NULL, NULL, NULL,
- db, local_abspath, pool, pool);
-
- if (delete_unversioned_target &&
- err != NULL && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- {
- svn_error_clear(err);
-
- if (!keep_local)
- SVN_ERR(erase_unversioned_from_wc(local_abspath, FALSE,
- cancel_func, cancel_baton,
- pool));
- return SVN_NO_ERROR;
- }
- else
- SVN_ERR(err);
-
- switch (status)
- {
- /* svn_wc__db_status_server_excluded handled by svn_wc__db_op_delete */
- case svn_wc__db_status_excluded:
- case svn_wc__db_status_not_present:
- return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
- _("'%s' cannot be deleted"),
- svn_dirent_local_style(local_abspath, pool));
-
- /* Explicitly ignore other statii */
- default:
- break;
- }
-
- if (status == svn_wc__db_status_normal
- && kind == svn_kind_dir)
- {
- svn_boolean_t is_wcroot;
- SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, pool));
-
- if (is_wcroot)
- return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
- _("'%s' is the root of a working copy and "
- "cannot be deleted"),
- svn_dirent_local_style(local_abspath, pool));
- }
-
- /* Verify if we have a write lock on the parent of this node as we might
- be changing the childlist of that directory. */
- SVN_ERR(svn_wc__write_check(db, svn_dirent_dirname(local_abspath, pool),
- 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,
- !keep_local /* delete_dir_externals */,
- NULL, work_items,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- pool));
-
- if (work_items)
- SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
- scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_wc_delete4(svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- svn_boolean_t keep_local,
- svn_boolean_t delete_unversioned_target,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
-{
- return svn_error_trace(svn_wc__delete_internal(wc_ctx, local_abspath,
- keep_local,
- delete_unversioned_target,
- NULL,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- scratch_pool));
-}
-
-
/* Schedule the single node at LOCAL_ABSPATH, of kind KIND, for addition in
* its parent directory in the WC. It will have the regular properties
* provided in PROPS, or none if that is NULL.
@@ -1411,843 +1035,6 @@ svn_wc_add_from_disk2(svn_wc_context_t *
return SVN_NO_ERROR;
}
-/* Thoughts on Reversion.
-
- What does is mean to revert a given PATH in a tree? We'll
- consider things by their modifications.
-
- Adds
-
- - For files, svn_wc_remove_from_revision_control(), baby.
-
- - Added directories may contain nothing but added children, and
- reverting the addition of a directory necessarily means reverting
- the addition of all the directory's children. Again,
- svn_wc_remove_from_revision_control() should do the trick.
-
- Deletes
-
- - Restore properties to their unmodified state.
-
- - For files, restore the pristine contents, and reset the schedule
- to 'normal'.
-
- - For directories, reset the schedule to 'normal'. All children
- of a directory marked for deletion must also be marked for
- deletion, but it's okay for those children to remain deleted even
- if their parent directory is restored. That's what the
- recursive flag is for.
-
- Replaces
-
- - Restore properties to their unmodified state.
-
- - For files, restore the pristine contents, and reset the schedule
- to 'normal'.
-
- - For directories, reset the schedule to normal. A replaced
- directory can have deleted children (left over from the initial
- deletion), replaced children (children of the initial deletion
- now re-added), and added children (new entries under the
- replaced directory). Since this is technically an addition, it
- necessitates recursion.
-
- Modifications
-
- - Restore properties and, for files, contents to their unmodified
- state.
-
-*/
-
-
-/* Remove conflict file CONFLICT_ABSPATH, which may not exist, and set
- * *NOTIFY_REQUIRED to TRUE if the file was present and removed. */
-static svn_error_t *
-remove_conflict_file(svn_boolean_t *notify_required,
- const char *conflict_abspath,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
-{
- if (conflict_abspath)
- {
- svn_error_t *err = svn_io_remove_file2(conflict_abspath, FALSE,
- scratch_pool);
- if (err)
- svn_error_clear(err);
- else
- *notify_required = TRUE;
- }
-
- return SVN_NO_ERROR;
-}
-
-
-/* Sort copied children obtained from the revert list based on
- * their paths in descending order (longest paths first). */
-static int
-compare_revert_list_copied_children(const void *a, const void *b)
-{
- const svn_wc__db_revert_list_copied_child_info_t * const *ca = a;
- const svn_wc__db_revert_list_copied_child_info_t * const *cb = b;
- int i;
-
- i = svn_path_compare_paths(ca[0]->abspath, cb[0]->abspath);
-
- /* Reverse the result of svn_path_compare_paths() to achieve
- * descending order. */
- return -i;
-}
-
-
-/* Remove all reverted copied children from the directory at LOCAL_ABSPATH.
- * If REMOVE_SELF is TRUE, try to remove LOCAL_ABSPATH itself (REMOVE_SELF
- * should be set if LOCAL_ABSPATH is itself a reverted copy).
- *
- * If REMOVED_SELF is not NULL, indicate in *REMOVED_SELF whether
- * LOCAL_ABSPATH itself was removed.
- *
- * All reverted copied file children are removed from disk. Reverted copied
- * directories left empty as a result are also removed from disk.
- */
-static svn_error_t *
-revert_restore_handle_copied_dirs(svn_boolean_t *removed_self,
- svn_wc__db_t *db,
- const char *local_abspath,
- svn_boolean_t remove_self,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
-{
- const apr_array_header_t *copied_children;
- svn_wc__db_revert_list_copied_child_info_t *child_info;
- int i;
- svn_node_kind_t on_disk;
- apr_pool_t *iterpool;
- svn_error_t *err;
-
- if (removed_self)
- *removed_self = FALSE;
-
- SVN_ERR(svn_wc__db_revert_list_read_copied_children(&copied_children,
- db, local_abspath,
- scratch_pool,
- scratch_pool));
- iterpool = svn_pool_create(scratch_pool);
-
- /* Remove all copied file children. */
- for (i = 0; i < copied_children->nelts; i++)
- {
- child_info = APR_ARRAY_IDX(
- copied_children, i,
- svn_wc__db_revert_list_copied_child_info_t *);
-
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- if (child_info->kind != svn_kind_file)
- continue;
-
- svn_pool_clear(iterpool);
-
- /* Make sure what we delete from disk is really a file. */
- SVN_ERR(svn_io_check_path(child_info->abspath, &on_disk, iterpool));
- if (on_disk != svn_node_file)
- continue;
-
- SVN_ERR(svn_io_remove_file2(child_info->abspath, TRUE, iterpool));
- }
-
- /* Delete every empty child directory.
- * We cannot delete children recursively since we want to keep any files
- * that still exist on disk (e.g. unversioned files within the copied tree).
- * So sort the children list such that longest paths come first and try to
- * remove each child directory in order. */
- qsort(copied_children->elts, copied_children->nelts,
- sizeof(svn_wc__db_revert_list_copied_child_info_t *),
- compare_revert_list_copied_children);
- for (i = 0; i < copied_children->nelts; i++)
- {
- child_info = APR_ARRAY_IDX(
- copied_children, i,
- svn_wc__db_revert_list_copied_child_info_t *);
-
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- if (child_info->kind != svn_kind_dir)
- continue;
-
- svn_pool_clear(iterpool);
-
- err = svn_io_dir_remove_nonrecursive(child_info->abspath, iterpool);
- if (err)
- {
- if (APR_STATUS_IS_ENOENT(err->apr_err) ||
- SVN__APR_STATUS_IS_ENOTDIR(err->apr_err) ||
- APR_STATUS_IS_ENOTEMPTY(err->apr_err))
- svn_error_clear(err);
- else
- return svn_error_trace(err);
- }
- }
-
- if (remove_self)
- {
- /* Delete LOCAL_ABSPATH itself if no children are left. */
- err = svn_io_dir_remove_nonrecursive(local_abspath, iterpool);
- if (err)
- {
- if (APR_STATUS_IS_ENOTEMPTY(err->apr_err))
- svn_error_clear(err);
- else
- return svn_error_trace(err);
- }
- else if (removed_self)
- *removed_self = TRUE;
- }
-
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-
-/* Make the working tree under LOCAL_ABSPATH to depth DEPTH match the
- versioned tree. This function is called after svn_wc__db_op_revert
- has done the database revert and created the revert list. Notifies
- for all paths equal to or below LOCAL_ABSPATH that are reverted.
-
- REVERT_ROOT is true for explicit revert targets and FALSE for targets
- reached via recursion.
- */
-static svn_error_t *
-revert_restore(svn_wc__db_t *db,
- const char *local_abspath,
- svn_depth_t depth,
- svn_boolean_t use_commit_times,
- svn_boolean_t revert_root,
- 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_error_t *err;
- svn_wc__db_status_t status;
- svn_kind_t kind;
- svn_node_kind_t on_disk;
- svn_boolean_t notify_required;
- const apr_array_header_t *conflict_files;
- svn_filesize_t recorded_size;
- apr_time_t recorded_time;
- apr_finfo_t finfo;
-#ifdef HAVE_SYMLINK
- svn_boolean_t special;
-#endif
- svn_boolean_t copied_here;
- svn_kind_t reverted_kind;
- svn_boolean_t is_wcroot;
-
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, scratch_pool));
- if (is_wcroot && !revert_root)
- {
- /* Issue #4162: Obstructing working copy. We can't access the working
- copy data from the parent working copy for this node by just using
- local_abspath */
-
- if (notify_func)
- {
- svn_wc_notify_t *notify = svn_wc_create_notify(
- local_abspath,
- svn_wc_notify_update_skip_obstruction,
- scratch_pool);
-
- notify_func(notify_baton, notify, scratch_pool);
- }
-
- return SVN_NO_ERROR; /* We don't revert obstructing working copies */
- }
-
- SVN_ERR(svn_wc__db_revert_list_read(¬ify_required,
- &conflict_files,
- &copied_here, &reverted_kind,
- db, local_abspath,
- scratch_pool, scratch_pool));
-
- err = svn_wc__db_read_info(&status, &kind,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- &recorded_size, &recorded_time, 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)
- {
- svn_error_clear(err);
-
- if (!copied_here)
- {
- if (notify_func && notify_required)
- notify_func(notify_baton,
- svn_wc_create_notify(local_abspath,
- svn_wc_notify_revert,
- scratch_pool),
- scratch_pool);
-
- if (notify_func)
- SVN_ERR(svn_wc__db_revert_list_notify(notify_func, notify_baton,
- db, local_abspath,
- scratch_pool));
- return SVN_NO_ERROR;
- }
- else
- {
- /* ### Initialise to values which prevent the code below from
- * ### trying to restore anything to disk.
- * ### 'status' should be status_unknown but that doesn't exist. */
- status = svn_wc__db_status_normal;
- kind = svn_kind_unknown;
- recorded_size = SVN_INVALID_FILESIZE;
- recorded_time = 0;
- }
- }
- else if (err)
- return svn_error_trace(err);
-
- err = svn_io_stat(&finfo, local_abspath,
- APR_FINFO_TYPE | APR_FINFO_LINK
- | APR_FINFO_SIZE | APR_FINFO_MTIME
- | SVN__APR_FINFO_EXECUTABLE
- | SVN__APR_FINFO_READONLY,
- scratch_pool);
-
- if (err && (APR_STATUS_IS_ENOENT(err->apr_err)
- || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
- {
- svn_error_clear(err);
- on_disk = svn_node_none;
-#ifdef HAVE_SYMLINK
- special = FALSE;
-#endif
- }
- else
- {
- if (finfo.filetype == APR_REG || finfo.filetype == APR_LNK)
- on_disk = svn_node_file;
- else if (finfo.filetype == APR_DIR)
- on_disk = svn_node_dir;
- else
- on_disk = svn_node_unknown;
-
-#ifdef HAVE_SYMLINK
- special = (finfo.filetype == APR_LNK);
-#endif
- }
-
- if (copied_here)
- {
- /* The revert target itself is the op-root of a copy. */
- if (reverted_kind == svn_kind_file && on_disk == svn_node_file)
- {
- SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
- on_disk = svn_node_none;
- }
- else if (reverted_kind == svn_kind_dir && on_disk == svn_node_dir)
- {
- svn_boolean_t removed;
-
- SVN_ERR(revert_restore_handle_copied_dirs(&removed, db,
- local_abspath, TRUE,
- cancel_func, cancel_baton,
- scratch_pool));
- if (removed)
- on_disk = svn_node_none;
- }
- }
-
- /* If we expect a versioned item to be present then check that any
- item on disk matches the versioned item, if it doesn't match then
- fix it or delete it. */
- if (on_disk != svn_node_none
- && status != svn_wc__db_status_server_excluded
- && status != svn_wc__db_status_deleted
- && status != svn_wc__db_status_excluded
- && status != svn_wc__db_status_not_present)
- {
- if (on_disk == svn_node_dir && kind != svn_kind_dir)
- {
- SVN_ERR(svn_io_remove_dir2(local_abspath, FALSE,
- cancel_func, cancel_baton, scratch_pool));
- on_disk = svn_node_none;
- }
- else if (on_disk == svn_node_file && kind != svn_kind_file)
- {
-#ifdef HAVE_SYMLINK
- /* Preserve symlinks pointing at directories. Changes on the
- * directory node have been reverted. The symlink should remain. */
- if (!(special && kind == svn_kind_dir))
-#endif
- {
- SVN_ERR(svn_io_remove_file2(local_abspath, FALSE, scratch_pool));
- on_disk = svn_node_none;
- }
- }
- else if (on_disk == svn_node_file)
- {
- svn_boolean_t modified;
- apr_hash_t *props;
-#ifdef HAVE_SYMLINK
- svn_string_t *special_prop;
-#endif
-
- SVN_ERR(svn_wc__db_read_pristine_props(&props, db, local_abspath,
- scratch_pool, scratch_pool));
-
-#ifdef HAVE_SYMLINK
- special_prop = apr_hash_get(props, SVN_PROP_SPECIAL,
- APR_HASH_KEY_STRING);
-
- if ((special_prop != NULL) != special)
- {
- /* File/symlink mismatch. */
- SVN_ERR(svn_io_remove_file2(local_abspath, FALSE, scratch_pool));
- on_disk = svn_node_none;
- }
- else
-#endif
- {
- /* Issue #1663 asserts that we should compare a file in its
- working copy format here, but before r1101473 we would only
- do that if the file was already unequal to its recorded
- information.
-
- r1101473 removes the option of asking for a working format
- compare but *also* check the recorded information first, as
- that combination doesn't guarantee a stable behavior.
- (See the revert_test.py: revert_reexpand_keyword)
-
- But to have the same issue #1663 behavior for revert as we
- had in <=1.6 we only have to check the recorded information
- ourselves. And we already have everything we need, because
- we called stat ourselves. */
- if (recorded_size != SVN_INVALID_FILESIZE
- && recorded_time != 0
- && recorded_size == finfo.size
- && recorded_time == finfo.mtime)
- {
- modified = FALSE;
- }
- else
- SVN_ERR(svn_wc__internal_file_modified_p(&modified,
- db, local_abspath,
- TRUE, scratch_pool));
-
- if (modified)
- {
- SVN_ERR(svn_io_remove_file2(local_abspath, FALSE,
- scratch_pool));
- on_disk = svn_node_none;
- }
- else
- {
- if (status == svn_wc__db_status_normal)
- {
- svn_boolean_t read_only;
- svn_string_t *needs_lock_prop;
-
- SVN_ERR(svn_io__is_finfo_read_only(&read_only, &finfo,
- scratch_pool));
-
- needs_lock_prop = apr_hash_get(props, SVN_PROP_NEEDS_LOCK,
- APR_HASH_KEY_STRING);
- if (needs_lock_prop && !read_only)
- {
- SVN_ERR(svn_io_set_file_read_only(local_abspath,
- FALSE,
- scratch_pool));
- notify_required = TRUE;
- }
- else if (!needs_lock_prop && read_only)
- {
- SVN_ERR(svn_io_set_file_read_write(local_abspath,
- FALSE,
- scratch_pool));
- notify_required = TRUE;
- }
- }
-
-#if !defined(WIN32) && !defined(__OS2__)
-#ifdef HAVE_SYMLINK
- if (!special)
-#endif
- {
- svn_boolean_t executable;
- svn_string_t *executable_prop;
-
- SVN_ERR(svn_io__is_finfo_executable(&executable, &finfo,
- scratch_pool));
- executable_prop = apr_hash_get(props, SVN_PROP_EXECUTABLE,
- APR_HASH_KEY_STRING);
- if (executable_prop && !executable)
- {
- SVN_ERR(svn_io_set_file_executable(local_abspath,
- TRUE, FALSE,
- scratch_pool));
- notify_required = TRUE;
- }
- else if (!executable_prop && executable)
- {
- SVN_ERR(svn_io_set_file_executable(local_abspath,
- FALSE, FALSE,
- scratch_pool));
- notify_required = TRUE;
- }
- }
-#endif
- }
- }
- }
- }
-
- /* If we expect a versioned item to be present and there is nothing
- on disk then recreate it. */
- if (on_disk == svn_node_none
- && status != svn_wc__db_status_server_excluded
- && status != svn_wc__db_status_deleted
- && status != svn_wc__db_status_excluded
- && status != svn_wc__db_status_not_present)
- {
- if (kind == svn_kind_dir)
- SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT, scratch_pool));
-
- if (kind == svn_kind_file)
- {
- svn_skel_t *work_item;
-
- /* ### Get the checksum from read_info above and pass in here? */
- SVN_ERR(svn_wc__wq_build_file_install(&work_item, db, local_abspath,
- NULL, use_commit_times, TRUE,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__db_wq_add(db, local_abspath, work_item,
- scratch_pool));
- SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
- scratch_pool));
- }
- notify_required = TRUE;
- }
-
- if (conflict_files)
- {
- int i;
- for (i = 0; i < conflict_files->nelts; i++)
- {
- SVN_ERR(remove_conflict_file(¬ify_required,
- APR_ARRAY_IDX(conflict_files, i,
- const char *),
- local_abspath, scratch_pool));
- }
- }
-
- if (notify_func && notify_required)
- notify_func(notify_baton,
- svn_wc_create_notify(local_abspath, svn_wc_notify_revert,
- scratch_pool),
- scratch_pool);
-
- if (depth == svn_depth_infinity && kind == svn_kind_dir)
- {
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- const apr_array_header_t *children;
- int i;
-
- SVN_ERR(revert_restore_handle_copied_dirs(NULL, db, local_abspath, FALSE,
- cancel_func, cancel_baton,
- iterpool));
-
- SVN_ERR(svn_wc__db_read_children_of_working_node(&children, db,
- local_abspath,
- scratch_pool,
- iterpool));
- for (i = 0; i < children->nelts; ++i)
- {
- const char *child_abspath;
-
- svn_pool_clear(iterpool);
-
- child_abspath = svn_dirent_join(local_abspath,
- APR_ARRAY_IDX(children, i,
- const char *),
- iterpool);
-
- SVN_ERR(revert_restore(db, child_abspath, depth,
- use_commit_times, FALSE /* revert root */,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- iterpool));
- }
-
- svn_pool_destroy(iterpool);
- }
-
- if (notify_func)
- SVN_ERR(svn_wc__db_revert_list_notify(notify_func, notify_baton,
- db, local_abspath, scratch_pool));
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__revert_internal(svn_wc__db_t *db,
- const char *local_abspath,
- svn_depth_t depth,
- svn_boolean_t use_commit_times,
- 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_error_t *err;
-
- SVN_ERR_ASSERT(depth == svn_depth_empty || depth == svn_depth_infinity);
-
- /* We should have a write lock on the parent of local_abspath, except
- when local_abspath is the working copy root. */
- {
- const char *dir_abspath;
- svn_boolean_t is_wcroot;
-
- SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, scratch_pool));
-
- 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));
- }
-
- err = svn_wc__db_op_revert(db, local_abspath, depth,
- scratch_pool, scratch_pool);
-
- if (!err)
- err = revert_restore(db, local_abspath, depth,
- use_commit_times, TRUE /* revert root */,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- scratch_pool);
-
- err = svn_error_compose_create(err,
- svn_wc__db_revert_list_done(db,
- local_abspath,
- scratch_pool));
-
- return err;
-}
-
-
-/* Revert files in LOCAL_ABSPATH to depth DEPTH that match
- CHANGELIST_HASH and notify for all reverts. */
-static svn_error_t *
-revert_changelist(svn_wc__db_t *db,
- const char *local_abspath,
- svn_depth_t depth,
- svn_boolean_t use_commit_times,
- apr_hash_t *changelist_hash,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
-{
- apr_pool_t *iterpool;
- const apr_array_header_t *children;
- int i;
-
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- /* Revert this node (depth=empty) if it matches one of the changelists. */
- if (svn_wc__internal_changelist_match(db, local_abspath, changelist_hash,
- scratch_pool))
- SVN_ERR(svn_wc__revert_internal(db, local_abspath,
- svn_depth_empty, use_commit_times,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- scratch_pool));
-
- if (depth == svn_depth_empty)
- return SVN_NO_ERROR;
-
- iterpool = svn_pool_create(scratch_pool);
-
- /* We can handle both depth=files and depth=immediates by setting
- depth=empty here. We don't need to distinguish files and
- directories when making the recursive call because directories
- can never match a changelist, so making the recursive call for
- directories when asked for depth=files is a no-op. */
- if (depth == svn_depth_files || depth == svn_depth_immediates)
- depth = svn_depth_empty;
-
- SVN_ERR(svn_wc__db_read_children_of_working_node(&children, db,
- local_abspath,
- scratch_pool,
- iterpool));
- for (i = 0; i < children->nelts; ++i)
- {
- const char *child_abspath;
-
- svn_pool_clear(iterpool);
-
- child_abspath = svn_dirent_join(local_abspath,
- APR_ARRAY_IDX(children, i,
- const char *),
- iterpool);
-
- SVN_ERR(revert_changelist(db, child_abspath, depth,
- use_commit_times, changelist_hash,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- iterpool));
- }
-
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-
-/* Does a partially recursive revert of LOCAL_ABSPATH to depth DEPTH
- (which must be either svn_depth_files or svn_depth_immediates) by
- doing a non-recursive revert on each permissible path. Notifies
- all reverted paths.
-
- ### This won't revert a copied dir with one level of children since
- ### the non-recursive revert on the dir will fail. Not sure how a
- ### partially recursive revert should handle actual-only nodes. */
-static svn_error_t *
-revert_partial(svn_wc__db_t *db,
- const char *local_abspath,
- svn_depth_t depth,
- svn_boolean_t use_commit_times,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
-{
- apr_pool_t *iterpool;
- const apr_array_header_t *children;
- int i;
-
- SVN_ERR_ASSERT(depth == svn_depth_files || depth == svn_depth_immediates);
-
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- iterpool = svn_pool_create(scratch_pool);
-
- /* Revert the root node itself (depth=empty), then move on to the
- children. */
- SVN_ERR(svn_wc__revert_internal(db, local_abspath, svn_depth_empty,
- use_commit_times, cancel_func, cancel_baton,
- notify_func, notify_baton, iterpool));
-
- SVN_ERR(svn_wc__db_read_children_of_working_node(&children, db,
- local_abspath,
- scratch_pool,
- iterpool));
- for (i = 0; i < children->nelts; ++i)
- {
- const char *child_abspath;
-
- svn_pool_clear(iterpool);
-
- child_abspath = svn_dirent_join(local_abspath,
- APR_ARRAY_IDX(children, i, const char *),
- iterpool);
-
- /* For svn_depth_files: don't revert non-files. */
- if (depth == svn_depth_files)
- {
- svn_kind_t kind;
-
- SVN_ERR(svn_wc__db_read_kind(&kind, db, child_abspath,
- FALSE /* allow_missing */,
- FALSE /* show_hidden */,
- iterpool));
- if (kind != svn_kind_file)
- continue;
- }
-
- /* Revert just this node (depth=empty). */
- SVN_ERR(svn_wc__revert_internal(db, child_abspath,
- svn_depth_empty, use_commit_times,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- iterpool));
- }
-
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc_revert4(svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- svn_depth_t depth,
- svn_boolean_t use_commit_times,
- const apr_array_header_t *changelist_filter,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
-{
- if (changelist_filter && changelist_filter->nelts)
- {
- apr_hash_t *changelist_hash;
-
- SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
- scratch_pool));
- return svn_error_trace(revert_changelist(wc_ctx->db, local_abspath,
- depth, use_commit_times,
- changelist_hash,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- scratch_pool));
- }
-
- if (depth == svn_depth_empty || depth == svn_depth_infinity)
- return svn_error_trace(svn_wc__revert_internal(wc_ctx->db, local_abspath,
- depth, use_commit_times,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- scratch_pool));
-
- /* The user may expect svn_depth_files/svn_depth_immediates to work
- on copied dirs with one level of children. It doesn't, the user
- will get an error and will need to invoke an infinite revert. If
- we identified those cases where svn_depth_infinity would not
- revert too much we could invoke the recursive call above. */
-
- if (depth == svn_depth_files || depth == svn_depth_immediates)
- return svn_error_trace(revert_partial(wc_ctx->db, local_abspath,
- depth, use_commit_times,
- cancel_func, cancel_baton,
- notify_func, notify_baton,
- scratch_pool));
-
- /* Bogus depth. Tell the caller. */
- return svn_error_create(SVN_ERR_WC_INVALID_OPERATION_DEPTH, NULL, NULL);
-}
-
-
/* Return a path where nothing exists on disk, within the admin directory
belonging to the WCROOT_ABSPATH directory. */
static const char *
@@ -2374,103 +1161,6 @@ svn_wc__get_pristine_contents_by_checksu
return SVN_NO_ERROR;
}
-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_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
-{
- svn_boolean_t left_something = FALSE;
- svn_boolean_t is_root;
- svn_error_t *err = NULL;
-
- SVN_ERR(svn_wc__db_is_wcroot(&is_root, db, local_abspath, scratch_pool));
-
- SVN_ERR(svn_wc__write_check(db, is_root ? local_abspath
- : svn_dirent_dirname(local_abspath,
- scratch_pool),
- 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));
-
- SVN_ERR(svn_wc__wq_run(db, local_abspath,
- cancel_func, cancel_baton,
- scratch_pool));
-
- if (is_root)
- {
- /* Destroy the administrative area */
- SVN_ERR(svn_wc__adm_destroy(db, local_abspath, cancel_func, cancel_baton,
- scratch_pool));
-
- /* 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 || 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,
- 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)
-{
- 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,
- cancel_func,
- cancel_baton,
- scratch_pool));
-}
svn_error_t *
@@ -2485,6 +1175,11 @@ svn_wc_add_lock2(svn_wc_context_t *wc_ct
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ /* ### Enable after fixing callers */
+ /*SVN_ERR(svn_wc__write_check(wc_ctx->db,
+ svn_dirent_dirname(local_abspath, scratch_pool),
+ scratch_pool));*/
+
db_lock.token = lock->token;
db_lock.owner = lock->owner;
db_lock.comment = lock->comment;
@@ -2534,6 +1229,11 @@ svn_wc_remove_lock2(svn_wc_context_t *wc
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ /* ### Enable after fixing callers */
+ /*SVN_ERR(svn_wc__write_check(wc_ctx->db,
+ svn_dirent_dirname(local_abspath, scratch_pool),
+ scratch_pool));*/
+
err = svn_wc__db_lock_remove(wc_ctx->db, local_abspath, scratch_pool);
if (err)
{
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=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c Mon Jan 21 23:37:01 2013
@@ -1386,7 +1386,7 @@ generate_propconflict(svn_boolean_t *con
*conflict_remains = TRUE;
return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
NULL, _("Conflict callback violated API:"
- " returned no results."));
+ " returned no results"));
}
@@ -1428,7 +1428,7 @@ generate_propconflict(svn_boolean_t *con
return svn_error_create
(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
NULL, _("Conflict callback violated API:"
- " returned no merged file."));
+ " returned no merged file"));
else
{
svn_stringbuf_t *merged_stringbuf;
@@ -1471,7 +1471,7 @@ generate_propconflict(svn_boolean_t *con
* CHOICE.
*
* Set *WORK_ITEMS to new work items that will ...
- * Set *MERGE_OUTCOME to the result of the 3-way merge.
+ * Set *IS_RESOLVED to true if the conflicts are resolved, otherwise to false.
*
* LEFT_ABSPATH, RIGHT_ABSPATH, and TARGET_ABSPATH are the input files to
* the 3-way merge, and MERGED_FILE is the merged result as generated by the
@@ -1482,7 +1482,7 @@ generate_propconflict(svn_boolean_t *con
* diff3 implementation in case a 3-way merge has to be carried out. */
static svn_error_t*
eval_text_conflict_func_result(svn_skel_t **work_items,
- enum svn_wc_merge_outcome_t *merge_outcome,
+ svn_boolean_t *is_resolved,
svn_wc__db_t *db,
const char *local_abspath,
svn_wc_conflict_choice_t choice,
@@ -1506,19 +1506,19 @@ eval_text_conflict_func_result(svn_skel_
case svn_wc_conflict_choose_base:
{
install_from = left_abspath;
- *merge_outcome = svn_wc_merge_merged;
+ *is_resolved = TRUE;
break;
}
case svn_wc_conflict_choose_theirs_full:
{
install_from = right_abspath;
- *merge_outcome = svn_wc_merge_merged;
+ *is_resolved = TRUE;
break;
}
case svn_wc_conflict_choose_mine_full:
{
/* Do nothing to merge_target, let it live untouched! */
- *merge_outcome = svn_wc_merge_merged;
+ *is_resolved = TRUE;
return SVN_NO_ERROR;
}
case svn_wc_conflict_choose_theirs_conflict:
@@ -1566,7 +1566,7 @@ eval_text_conflict_func_result(svn_skel_
install_from = chosen_path;
remove_source = TRUE;
- *merge_outcome = svn_wc_merge_merged;
+ *is_resolved = TRUE;
break;
}
@@ -1579,19 +1579,14 @@ eval_text_conflict_func_result(svn_skel_
case svn_wc_conflict_choose_merged:
{
install_from = merged_file;
- *merge_outcome = svn_wc_merge_merged;
+ *is_resolved = TRUE;
break;
}
case svn_wc_conflict_choose_postpone:
default:
{
-#if 0
- /* ### what should this value be? no caller appears to initialize
- ### it, so we really SHOULD be setting a value here. */
- *merge_outcome = svn_wc_merge_merged;
-#endif
-
/* Assume conflict remains. */
+ *is_resolved = FALSE;
return SVN_NO_ERROR;
}
}
@@ -1672,7 +1667,7 @@ save_merge_result(svn_skel_t **work_item
external 3-way merge. */
static svn_error_t*
resolve_text_conflicts(svn_skel_t **work_items,
- svn_wc_merge_outcome_t *merge_outcome,
+ svn_boolean_t *was_resolved,
svn_wc__db_t *db,
const char *local_abspath,
const apr_array_header_t *merge_options,
@@ -1694,6 +1689,7 @@ resolve_text_conflicts(svn_skel_t **work
apr_hash_t *props;
*work_items = NULL;
+ *was_resolved = FALSE;
/* Give the conflict resolution callback a chance to clean
up the conflicts before we mark the file 'conflicted' */
@@ -1717,8 +1713,8 @@ resolve_text_conflicts(svn_skel_t **work
scratch_pool));
if (result == NULL)
return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
- _("Conflict callback violated API: "
- "returned no results"));
+ _("Conflict callback violated API:"
+ " returned no results"));
if (result->save_merged)
{
@@ -1732,27 +1728,24 @@ resolve_text_conflicts(svn_skel_t **work
result_pool, scratch_pool));
}
- SVN_ERR(eval_text_conflict_func_result(&work_item,
- merge_outcome,
- db, local_abspath,
- result->choice,
- merge_options,
- left_abspath,
- right_abspath,
- result->merged_file
- ? result->merged_file
- : result_target,
- detranslated_target,
- result_pool, scratch_pool));
- *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
-
if (result->choice != svn_wc_conflict_choose_postpone)
- /* The conflicts have been dealt with, nothing else
- * to do for us here. */
- return SVN_NO_ERROR;
-
- /* The conflicts have not been dealt with. */
- *merge_outcome = svn_wc_merge_conflict;
+ {
+ SVN_ERR(eval_text_conflict_func_result(&work_item,
+ was_resolved,
+ db, local_abspath,
+ result->choice,
+ merge_options,
+ left_abspath,
+ right_abspath,
+ result->merged_file
+ ? result->merged_file
+ : result_target,
+ detranslated_target,
+ result_pool, scratch_pool));
+ *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+ }
+ else
+ *was_resolved = FALSE;
return SVN_NO_ERROR;
}
@@ -1908,7 +1901,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_
const char *their_original_abspath;
const char *their_abspath;
svn_skel_t *work_items;
- svn_wc_merge_outcome_t merge_outcome = svn_wc_merge_conflict;
+ svn_boolean_t was_resolved;
SVN_ERR(svn_wc__conflict_read_text_conflict(&their_original_abspath,
&mine_abspath,
@@ -1917,7 +1910,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_
conflict_skel,
scratch_pool, scratch_pool));
- SVN_ERR(resolve_text_conflicts(&work_items, &merge_outcome,
+ SVN_ERR(resolve_text_conflicts(&work_items, &was_resolved,
db, local_abspath,
merge_options,
operation,
@@ -1929,7 +1922,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_
resolver_func, resolver_baton,
scratch_pool, scratch_pool));
- if (merge_outcome == svn_wc_merge_merged)
+ if (was_resolved)
{
SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, TRUE, FALSE,
FALSE, work_items, scratch_pool));
@@ -2223,7 +2216,7 @@ svn_wc__read_conflicts(const apr_array_h
db, local_abspath,
operation, left_version, right_version,
local_change, incoming_change,
- scratch_pool, scratch_pool));
+ result_pool, scratch_pool));
APR_ARRAY_PUSH(cflcts, const svn_wc_conflict_description2_t *) = desc;
}
@@ -2564,6 +2557,7 @@ svn_wc__resolve_text_conflict(svn_wc__db
/* Baton for conflict_status_walker */
struct conflict_status_walker_baton
{
+ svn_wc_context_t *wc_ctx;
svn_wc__db_t *db;
svn_boolean_t resolve_text;
const char *resolve_prop;
@@ -2653,7 +2647,29 @@ conflict_status_walker(void *baton,
scratch_pool, scratch_pool));
else if (my_choice == svn_wc_conflict_choose_theirs_conflict)
{
- /* ### TODO break move */
+ switch (status->node_status)
+ {
+ case svn_wc_status_deleted:
+ /* Break the move by reverting the deleted half of
+ * the move, keeping the copied-half as a copy.
+ * Reverting a node requires write lock on parent. */
+ SVN_WC__CALL_WITH_WRITE_LOCK(
+ svn_wc__revert_internal(cswb->db, local_abspath,
+ svn_depth_infinity,
+ FALSE,
+ cswb->cancel_func,
+ cswb->cancel_baton,
+ cswb->notify_func,
+ cswb->notify_baton,
+ scratch_pool),
+ cswb->wc_ctx,
+ svn_dirent_dirname(local_abspath, scratch_pool),
+ FALSE, scratch_pool);
+ break;
+ default:
+ /* ### TODO other node_status cases */
+ break;
+ }
}
}
else if (my_choice != svn_wc_conflict_choose_merged)
@@ -2797,6 +2813,7 @@ svn_wc__resolve_conflicts(svn_wc_context
else if (depth == svn_depth_unknown)
depth = svn_depth_infinity;
+ cswb.wc_ctx = wc_ctx;
cswb.db = wc_ctx->db;
cswb.resolve_text = resolve_text;
cswb.resolve_prop = resolve_prop;
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=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/crop.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/crop.c Mon Jan 21 23:37:01 2013
@@ -107,7 +107,9 @@ crop_children(svn_wc__db_t *db,
? svn_depth_immediates
: svn_depth_files;
if (new_depth < remove_below)
- SVN_ERR(svn_wc__db_base_remove(db, local_abspath, FALSE,
+ SVN_ERR(svn_wc__db_base_remove(db, child_abspath,
+ FALSE /* keep_as_working */,
+ FALSE /* queue_deletes */,
SVN_INVALID_REVNUM,
NULL, NULL, iterpool));
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/diff_local.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/diff_local.c Mon Jan 21 23:37:01 2013
@@ -204,11 +204,10 @@ file_diff(struct diff_baton *eb,
the latter two have corresponding pristine info to diff against. */
if (status == svn_wc__db_status_added)
SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL,
- &original_repos_relpath, NULL, NULL,
+ NULL, NULL, NULL,
NULL, NULL, NULL, db, local_abspath,
scratch_pool, scratch_pool));
-
SVN_ERR(get_empty_file(eb, &empty_file, scratch_pool));
/* When we show a delete, we show a diff of the original pristine against
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/entries.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/entries.c Mon Jan 21 23:37:01 2013
@@ -208,6 +208,7 @@ get_info_for_deleted(svn_wc_entry_t *ent
svn_kind_t *kind,
const char **repos_relpath,
const svn_checksum_t **checksum,
+ svn_wc__db_lock_t **lock,
svn_wc__db_t *db,
const char *entry_abspath,
const svn_wc_entry_t *parent_entry,
@@ -230,7 +231,7 @@ get_info_for_deleted(svn_wc_entry_t *ent
&entry->depth,
checksum,
NULL,
- NULL /* lock */,
+ lock,
&entry->has_props, NULL,
NULL,
db,
@@ -296,7 +297,7 @@ get_info_for_deleted(svn_wc_entry_t *ent
svn_wc__db_status_t status;
SVN_ERR(svn_wc__db_base_get_info(&status, NULL, &entry->revision,
NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, lock, NULL, NULL,
NULL,
db, entry_abspath,
result_pool, scratch_pool));
@@ -824,6 +825,7 @@ read_one_entry(const svn_wc_entry_t **ne
&kind,
&repos_relpath,
&checksum,
+ &lock,
db, entry_abspath,
parent_entry,
have_base, have_more_work,
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/externals.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/externals.c Mon Jan 21 23:37:01 2013
@@ -414,6 +414,9 @@ struct edit_baton
svn_revnum_t recorded_peg_revision;
svn_revnum_t recorded_revision;
+ /* Introducing a new file external */
+ svn_boolean_t added;
+
svn_wc_conflict_resolver_func2_t conflict_func;
void *conflict_baton;
svn_cancel_func_t cancel_func;
@@ -491,6 +494,7 @@ add_file(const char *path,
*file_baton = eb;
eb->original_revision = SVN_INVALID_REVNUM;
+ eb->added = TRUE;
return SVN_NO_ERROR;
}
@@ -773,7 +777,8 @@ close_file(void *file_baton,
install_pristine = TRUE;
content_state = svn_wc_notify_state_changed;
}
- else if (disk_kind != svn_node_file)
+ else if (disk_kind != svn_node_file
+ || (eb->added && disk_kind == svn_node_file))
{
/* The node is obstructed; we just change the DB */
obstructed = TRUE;
@@ -793,11 +798,12 @@ close_file(void *file_baton,
}
else
{
- enum svn_wc_merge_outcome_t merge_outcome;
+ svn_boolean_t found_text_conflict;
+
/* Ok, we have to do some work to merge a local change */
SVN_ERR(svn_wc__perform_file_merge(&work_item,
&conflict_skel,
- &merge_outcome,
+ &found_text_conflict,
eb->db,
eb->local_abspath,
eb->wri_abspath,
@@ -816,7 +822,7 @@ close_file(void *file_baton,
all_work_items = svn_wc__wq_merge(all_work_items, work_item,
pool);
- if (merge_outcome == svn_wc_merge_conflict)
+ if (found_text_conflict)
content_state = svn_wc_notify_state_conflicted;
else
content_state = svn_wc_notify_state_merged;
@@ -910,7 +916,7 @@ close_file(void *file_baton,
svn_wc_notify_action_t action;
svn_wc_notify_t *notify;
- if (SVN_IS_VALID_REVNUM(eb->original_revision))
+ if (!eb->added)
action = obstructed ? svn_wc_notify_update_shadowed_update
: svn_wc_notify_update_update;
else
@@ -1404,7 +1410,9 @@ svn_wc__external_remove(svn_wc_context_t
else
{
SVN_ERR(svn_wc__db_base_remove(wc_ctx->db, local_abspath,
- FALSE, SVN_INVALID_REVNUM,
+ FALSE /* keep_as_working */,
+ TRUE /* queue_deletes */,
+ SVN_INVALID_REVNUM,
NULL, NULL, scratch_pool));
SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath,
cancel_func, cancel_baton,