summaryrefslogtreecommitdiff
path: root/subversion/libsvn_wc/workqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_wc/workqueue.c')
-rw-r--r--subversion/libsvn_wc/workqueue.c746
1 files changed, 386 insertions, 360 deletions
diff --git a/subversion/libsvn_wc/workqueue.c b/subversion/libsvn_wc/workqueue.c
index 48bed38..b034d7d 100644
--- a/subversion/libsvn_wc/workqueue.c
+++ b/subversion/libsvn_wc/workqueue.c
@@ -34,6 +34,7 @@
#include "wc_db.h"
#include "workqueue.h"
#include "adm_files.h"
+#include "conflicts.h"
#include "translate.h"
#include "svn_private_config.h"
@@ -41,7 +42,6 @@
/* Workqueue operation names. */
-#define OP_BASE_REMOVE "base-remove"
#define OP_FILE_COMMIT "file-commit"
#define OP_FILE_INSTALL "file-install"
#define OP_FILE_REMOVE "file-remove"
@@ -49,18 +49,26 @@
#define OP_FILE_COPY_TRANSLATED "file-translate"
#define OP_SYNC_FILE_FLAGS "sync-file-flags"
#define OP_PREJ_INSTALL "prej-install"
+#define OP_DIRECTORY_REMOVE "dir-remove"
+#define OP_DIRECTORY_INSTALL "dir-install"
+
+#define OP_POSTUPGRADE "postupgrade"
+
+/* Legacy items */
+#define OP_BASE_REMOVE "base-remove"
#define OP_RECORD_FILEINFO "record-fileinfo"
#define OP_TMP_SET_TEXT_CONFLICT_MARKERS "tmp-set-text-conflict-markers"
#define OP_TMP_SET_PROPERTY_CONFLICT_MARKER "tmp-set-property-conflict-marker"
-#define OP_POSTUPGRADE "postupgrade"
/* For work queue debugging. Generates output about its operation. */
/* #define SVN_DEBUG_WORK_QUEUE */
+typedef struct work_item_baton_t work_item_baton_t;
struct work_item_dispatch {
const char *name;
- svn_error_t *(*func)(svn_wc__db_t *db,
+ svn_error_t *(*func)(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -68,30 +76,12 @@ struct work_item_dispatch {
apr_pool_t *scratch_pool);
};
-
+/* Forward definition */
static svn_error_t *
-get_and_record_fileinfo(svn_wc__db_t *db,
+get_and_record_fileinfo(work_item_baton_t *wqb,
const char *local_abspath,
svn_boolean_t ignore_enoent,
- apr_pool_t *scratch_pool)
-{
- const svn_io_dirent2_t *dirent;
-
- SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, ignore_enoent,
- scratch_pool, scratch_pool));
-
- if (dirent->kind == svn_node_none)
- {
- /* Skip file not found if ignore_enoent */
- return SVN_NO_ERROR;
- }
-
- return svn_error_trace(svn_wc__db_global_record_fileinfo(
- db, local_abspath,
- dirent->filesize, dirent->mtime,
- scratch_pool));
-}
-
+ apr_pool_t *scratch_pool);
/* ------------------------------------------------------------------------ */
/* OP_REMOVE_BASE */
@@ -99,116 +89,14 @@ get_and_record_fileinfo(svn_wc__db_t *db,
/* Removes a BASE_NODE and all it's data, leaving any adds and copies as is.
Do this as a depth first traversal to make sure than any parent still exists
on error conditions.
-
- ### This function needs review for 4th tree behavior.*/
-static svn_error_t *
-remove_base_node(svn_wc__db_t *db,
- const char *local_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_status_t base_status, wrk_status;
- svn_wc__db_kind_t base_kind, wrk_kind;
- svn_boolean_t have_base, have_work;
- svn_error_t *err;
-
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- err = svn_wc__db_read_info(&wrk_status, &wrk_kind, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL,
- &have_base, NULL, &have_work,
- db, local_abspath, scratch_pool, scratch_pool);
- if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- {
- /* No node to delete, this can happen when the wq item is rerun. */
- svn_error_clear(err);
- return SVN_NO_ERROR;
- }
-
- if(! have_base)
- /* No base node to delete, this can happen when the wq item is rerun. */
- return SVN_NO_ERROR;
-
- if (wrk_status == svn_wc__db_status_normal
- || wrk_status == svn_wc__db_status_not_present
- || wrk_status == svn_wc__db_status_server_excluded)
- {
- base_status = wrk_status;
- base_kind = wrk_kind;
- }
- else
- SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- db, local_abspath,
- scratch_pool, scratch_pool));
-
- /* Children first */
- if (base_kind == svn_wc__db_kind_dir
- && (base_status == svn_wc__db_status_normal
- || base_status == svn_wc__db_status_incomplete))
- {
- const apr_array_header_t *children;
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- int i;
-
- SVN_ERR(svn_wc__db_base_get_children(&children, db, local_abspath,
- scratch_pool, iterpool));
-
- for (i = 0; i < children->nelts; i++)
- {
- const char *child_name = APR_ARRAY_IDX(children, i, const char *);
- const char *child_abspath;
-
- svn_pool_clear(iterpool);
-
- child_abspath = svn_dirent_join(local_abspath, child_name, iterpool);
-
- SVN_ERR(remove_base_node(db, child_abspath, cancel_func, cancel_baton,
- iterpool));
- }
-
- svn_pool_destroy(iterpool);
- }
-
- if (base_status == svn_wc__db_status_normal
- && wrk_status != svn_wc__db_status_added
- && wrk_status != svn_wc__db_status_excluded)
- {
- if (wrk_status != svn_wc__db_status_deleted
- && (base_kind == svn_wc__db_kind_file
- || base_kind == svn_wc__db_kind_symlink))
- {
- SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
- }
- else if (base_kind == svn_wc__db_kind_dir
- && wrk_status != svn_wc__db_status_deleted)
- {
- err = svn_io_dir_remove_nonrecursive(local_abspath, scratch_pool);
- if (err && (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
- SVN_ERR(err);
- }
- }
-
- SVN_ERR(svn_wc__db_base_remove(db, local_abspath, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
+ */
/* Process the OP_REMOVE_BASE work item WORK_ITEM.
* See svn_wc__wq_build_remove_base() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_base_remove(svn_wc__db_t *db,
+run_base_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -219,8 +107,6 @@ run_base_remove(svn_wc__db_t *db,
const char *local_relpath;
const char *local_abspath;
svn_revnum_t not_present_rev = SVN_INVALID_REVNUM;
- svn_wc__db_kind_t not_present_kind;
- const char *repos_relpath, *repos_root_url, *repos_uuid;
apr_int64_t val;
local_relpath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
@@ -233,23 +119,6 @@ run_base_remove(svn_wc__db_t *db,
not_present_rev = (svn_revnum_t)val;
SVN_ERR(svn_skel__parse_int(&val, arg1->next->next, scratch_pool));
- not_present_kind = (svn_wc__db_kind_t)val;
-
- if (SVN_IS_VALID_REVNUM(not_present_rev))
- {
- const char *dir_abspath, *name;
-
- /* This wq operation is restartable, so we can't assume the node
- to be here. But we can assume that the parent is still there */
- svn_dirent_split(&dir_abspath, &name, local_abspath, scratch_pool);
-
- SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
- &repos_uuid,
- db, dir_abspath,
- scratch_pool, scratch_pool));
-
- repos_relpath = svn_relpath_join(repos_relpath, name, scratch_pool);
- }
}
else
{
@@ -261,55 +130,22 @@ run_base_remove(svn_wc__db_t *db,
if (keep_not_present)
{
- SVN_ERR(svn_wc__db_base_get_info(NULL, &not_present_kind,
- &not_present_rev, &repos_relpath,
- &repos_root_url, &repos_uuid, NULL,
+ SVN_ERR(svn_wc__db_base_get_info(NULL, NULL,
+ &not_present_rev, NULL,
+ NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL,
+ NULL, NULL, NULL,
db, local_abspath,
scratch_pool, scratch_pool));
}
}
- SVN_ERR(remove_base_node(db, local_abspath,
- cancel_func, cancel_baton,
- scratch_pool));
-
- if (SVN_IS_VALID_REVNUM(not_present_rev))
- {
- SVN_ERR(svn_wc__db_base_add_not_present_node(db, local_abspath,
- repos_relpath,
- repos_root_url,
- repos_uuid,
- not_present_rev,
- not_present_kind,
- NULL,
- NULL,
- scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_wc__wq_build_base_remove(svn_skel_t **work_item,
- svn_wc__db_t *db,
- const char *local_abspath,
- svn_revnum_t not_present_revision,
- svn_wc__db_kind_t not_present_kind,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const char *local_relpath;
- *work_item = svn_skel__make_empty_list(result_pool);
-
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- local_abspath, result_pool, scratch_pool));
-
- svn_skel__prepend_int(not_present_kind, *work_item, result_pool);
- svn_skel__prepend_int(not_present_revision, *work_item, result_pool);
- svn_skel__prepend_str(local_relpath, *work_item, result_pool);
- svn_skel__prepend_str(OP_BASE_REMOVE, *work_item, result_pool);
+ SVN_ERR(svn_wc__db_base_remove(db, local_abspath,
+ FALSE /* keep_as_working */,
+ TRUE /* queue_deletes */,
+ FALSE /* remove_locks */,
+ not_present_rev,
+ NULL, NULL, scratch_pool));
return SVN_NO_ERROR;
}
@@ -499,7 +335,8 @@ process_commit_file_install(svn_wc__db_t *db,
static svn_error_t *
-run_file_commit(svn_wc__db_t *db,
+run_file_commit(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -536,10 +373,6 @@ svn_wc__wq_build_file_commit(svn_skel_t **work_item,
SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
local_abspath, result_pool, scratch_pool));
- /* This are currently ignored, they are here for compat. */
- svn_skel__prepend_int(FALSE, *work_item, result_pool);
- svn_skel__prepend_int(FALSE, *work_item, result_pool);
-
svn_skel__prepend_str(local_relpath, *work_item, result_pool);
svn_skel__prepend_str(OP_FILE_COMMIT, *work_item, result_pool);
@@ -551,7 +384,8 @@ svn_wc__wq_build_file_commit(svn_skel_t **work_item,
/* OP_POSTUPGRADE */
static svn_error_t *
-run_postupgrade(svn_wc__db_t *db,
+run_postupgrade(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -570,6 +404,8 @@ run_postupgrade(svn_wc__db_t *db,
if (err && err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
/* No entry, this can happen when the wq item is rerun. */
svn_error_clear(err);
+ else
+ SVN_ERR(err);
SVN_ERR(svn_wc__db_get_wcroot(&wcroot_abspath, db, wri_abspath,
scratch_pool, scratch_pool));
@@ -617,7 +453,8 @@ svn_wc__wq_build_postupgrade(svn_skel_t **work_item,
* See svn_wc__wq_build_file_install() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_install(svn_wc__db_t *db,
+run_file_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -715,6 +552,8 @@ run_file_install(svn_wc__db_t *db,
scratch_pool));
/* No need to set exec or read-only flags on special files. */
+
+ /* ### Shouldn't this record a timestamp and size, etc.? */
return SVN_NO_ERROR;
}
@@ -781,12 +620,27 @@ run_file_install(svn_wc__db_t *db,
}
/* Tweak the on-disk file according to its properties. */
- if (props
- && (apr_hash_get(props, SVN_PROP_NEEDS_LOCK, APR_HASH_KEY_STRING)
- || apr_hash_get(props, SVN_PROP_EXECUTABLE, APR_HASH_KEY_STRING)))
+#ifndef WIN32
+ if (props && svn_hash_gets(props, SVN_PROP_EXECUTABLE))
+ SVN_ERR(svn_io_set_file_executable(local_abspath, TRUE, FALSE,
+ scratch_pool));
+#endif
+
+ /* Note that this explicitly checks the pristine properties, to make sure
+ that when the lock is locally set (=modification) it is not read only */
+ if (props && svn_hash_gets(props, SVN_PROP_NEEDS_LOCK))
{
- SVN_ERR(svn_wc__sync_flags_with_props(NULL, db, local_abspath,
- scratch_pool));
+ svn_wc__db_status_t status;
+ svn_wc__db_lock_t *lock;
+ SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, &lock, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ if (!lock && status != svn_wc__db_status_added)
+ SVN_ERR(svn_io_set_file_read_only(local_abspath, FALSE, scratch_pool));
}
if (use_commit_times)
@@ -800,7 +654,7 @@ run_file_install(svn_wc__db_t *db,
/* ### this should happen before we rename the file into place. */
if (record_fileinfo)
{
- SVN_ERR(get_and_record_fileinfo(db, local_abspath,
+ SVN_ERR(get_and_record_fileinfo(wqb, local_abspath,
FALSE /* ignore_enoent */,
scratch_pool));
}
@@ -820,19 +674,25 @@ svn_wc__wq_build_file_install(svn_skel_t **work_item,
apr_pool_t *scratch_pool)
{
const char *local_relpath;
+ const char *wri_abspath;
*work_item = svn_skel__make_empty_list(result_pool);
+ /* Use the directory of the file to install as wri_abspath to avoid
+ filestats on just obtaining the wc-root */
+ wri_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+
/* If a SOURCE_ABSPATH was provided, then put it into the skel. If this
- value is not provided, then the file's pristine contents will be used. */
+ value is not provided, then the file's pristine contents will be used. */
if (source_abspath != NULL)
{
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- source_abspath, result_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, wri_abspath,
+ source_abspath,
+ result_pool, scratch_pool));
svn_skel__prepend_str(local_relpath, *work_item, result_pool);
}
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
+ SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, wri_abspath,
local_abspath, result_pool, scratch_pool));
svn_skel__prepend_int(record_fileinfo, *work_item, result_pool);
@@ -852,12 +712,13 @@ svn_wc__wq_build_file_install(svn_skel_t **work_item,
* See svn_wc__wq_build_file_remove() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_remove(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_file_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg1 = work_item->children->next;
const char *local_relpath;
@@ -876,6 +737,7 @@ run_file_remove(svn_wc__db_t *db,
svn_error_t *
svn_wc__wq_build_file_remove(svn_skel_t **work_item,
svn_wc__db_t *db,
+ const char *wri_abspath,
const char *local_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
@@ -883,7 +745,7 @@ svn_wc__wq_build_file_remove(svn_skel_t **work_item,
const char *local_relpath;
*work_item = svn_skel__make_empty_list(result_pool);
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
+ SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, wri_abspath,
local_abspath, result_pool, scratch_pool));
svn_skel__prepend_str(local_relpath, *work_item, result_pool);
@@ -894,18 +756,101 @@ svn_wc__wq_build_file_remove(svn_skel_t **work_item,
/* ------------------------------------------------------------------------ */
+/* OP_DIRECTORY_REMOVE */
+
+/* Process the OP_FILE_REMOVE work item WORK_ITEM.
+ * See svn_wc__wq_build_file_remove() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
+static svn_error_t *
+run_dir_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const svn_skel_t *arg1 = work_item->children->next;
+ const char *local_relpath;
+ const char *local_abspath;
+ svn_boolean_t recursive;
+
+ local_relpath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
+ SVN_ERR(svn_wc__db_from_relpath(&local_abspath, db, wri_abspath,
+ local_relpath, scratch_pool, scratch_pool));
+
+ recursive = FALSE;
+ if (arg1->next)
+ {
+ apr_int64_t val;
+ SVN_ERR(svn_skel__parse_int(&val, arg1->next, scratch_pool));
+
+ recursive = (val != 0);
+ }
+
+ /* Remove the path, no worrying if it isn't there. */
+ if (recursive)
+ return svn_error_trace(
+ svn_io_remove_dir2(local_abspath, TRUE,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ else
+ {
+ svn_error_t *err;
+
+ err = svn_io_dir_remove_nonrecursive(local_abspath, scratch_pool);
+
+ if (err && (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);
+ err = NULL;
+ }
+
+ return svn_error_trace(err);
+ }
+}
+
+svn_error_t *
+svn_wc__wq_build_dir_remove(svn_skel_t **work_item,
+ svn_wc__db_t *db,
+ const char *wri_abspath,
+ const char *local_abspath,
+ svn_boolean_t recursive,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *local_relpath;
+ *work_item = svn_skel__make_empty_list(result_pool);
+
+ SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, wri_abspath,
+ local_abspath, result_pool, scratch_pool));
+
+ if (recursive)
+ svn_skel__prepend_int(TRUE, *work_item, result_pool);
+
+ svn_skel__prepend_str(local_relpath, *work_item, result_pool);
+ svn_skel__prepend_str(OP_DIRECTORY_REMOVE, *work_item, result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+/* ------------------------------------------------------------------------ */
+
/* OP_FILE_MOVE */
/* Process the OP_FILE_MOVE work item WORK_ITEM.
* See svn_wc__wq_build_file_move() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_move(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_file_move(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg1 = work_item->children->next;
const char *src_abspath, *dst_abspath;
@@ -982,7 +927,8 @@ svn_wc__wq_build_file_move(svn_skel_t **work_item,
* See run_file_copy_translated() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_copy_translated(svn_wc__db_t *db,
+run_file_copy_translated(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1071,6 +1017,52 @@ svn_wc__wq_build_file_copy_translated(svn_skel_t **work_item,
return SVN_NO_ERROR;
}
+/* ------------------------------------------------------------------------ */
+
+/* OP_DIRECTORY_INSTALL */
+
+static svn_error_t *
+run_dir_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const svn_skel_t *arg1 = work_item->children->next;
+ const char *local_relpath;
+ const char *local_abspath;
+
+ local_relpath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
+ SVN_ERR(svn_wc__db_from_relpath(&local_abspath, db, wri_abspath,
+ local_relpath, scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_wc__ensure_directory(local_abspath, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__wq_build_dir_install(svn_skel_t **work_item,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool,
+ apr_pool_t *result_pool)
+{
+ const char *local_relpath;
+
+ *work_item = svn_skel__make_empty_list(result_pool);
+
+ SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
+ local_abspath, result_pool, scratch_pool));
+ svn_skel__prepend_str(local_relpath, *work_item, result_pool);
+
+ svn_skel__prepend_str(OP_DIRECTORY_INSTALL, *work_item, result_pool);
+
+ return SVN_NO_ERROR;
+}
+
/* ------------------------------------------------------------------------ */
@@ -1080,7 +1072,8 @@ svn_wc__wq_build_file_copy_translated(svn_skel_t **work_item,
* See svn_wc__wq_build_sync_file_flags() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_sync_file_flags(svn_wc__db_t *db,
+run_sync_file_flags(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1125,7 +1118,8 @@ svn_wc__wq_build_sync_file_flags(svn_skel_t **work_item,
/* OP_PREJ_INSTALL */
static svn_error_t *
-run_prej_install(svn_wc__db_t *db,
+run_prej_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1135,29 +1129,34 @@ run_prej_install(svn_wc__db_t *db,
const svn_skel_t *arg1 = work_item->children->next;
const char *local_relpath;
const char *local_abspath;
- const svn_skel_t *conflict_skel;
+ svn_skel_t *conflicts;
+ const svn_skel_t *prop_conflict_skel;
const char *tmp_prejfile_abspath;
const char *prejfile_abspath;
local_relpath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
SVN_ERR(svn_wc__db_from_relpath(&local_abspath, db, wri_abspath,
local_relpath, scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_wc__conflict_read_prop_conflict(&prejfile_abspath,
+ NULL, NULL, NULL, NULL,
+ db, local_abspath, conflicts,
+ scratch_pool, scratch_pool));
+
if (arg1->next != NULL)
- conflict_skel = arg1->next;
+ prop_conflict_skel = arg1->next;
else
SVN_ERR_MALFUNCTION(); /* ### wc_db can't provide it ... yet. */
/* Construct a property reject file in the temporary area. */
SVN_ERR(svn_wc__create_prejfile(&tmp_prejfile_abspath,
db, local_abspath,
- conflict_skel,
+ prop_conflict_skel,
scratch_pool, scratch_pool));
- /* Get the (stored) name of where it should go. */
- SVN_ERR(svn_wc__get_prejfile_abspath(&prejfile_abspath, db, local_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR_ASSERT(prejfile_abspath != NULL);
-
/* ... and atomically move it into place. */
SVN_ERR(svn_io_file_rename(tmp_prejfile_abspath,
prejfile_abspath,
@@ -1199,7 +1198,8 @@ svn_wc__wq_build_prej_install(svn_skel_t **work_item,
static svn_error_t *
-run_record_fileinfo(svn_wc__db_t *db,
+run_record_fileinfo(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1244,49 +1244,24 @@ run_record_fileinfo(svn_wc__db_t *db,
}
- return svn_error_trace(get_and_record_fileinfo(db, local_abspath,
+ return svn_error_trace(get_and_record_fileinfo(wqb, local_abspath,
TRUE /* ignore_enoent */,
scratch_pool));
}
-
-svn_error_t *
-svn_wc__wq_build_record_fileinfo(svn_skel_t **work_item,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_time_t set_time,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const char *local_relpath;
- *work_item = svn_skel__make_empty_list(result_pool);
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- local_abspath, result_pool, scratch_pool));
-
- if (set_time)
- svn_skel__prepend_int(set_time, *work_item, result_pool);
-
- svn_skel__prepend_str(local_relpath, *work_item, result_pool);
- svn_skel__prepend_str(OP_RECORD_FILEINFO, *work_item, result_pool);
-
- return SVN_NO_ERROR;
-}
-
/* ------------------------------------------------------------------------ */
/* OP_TMP_SET_TEXT_CONFLICT_MARKERS */
static svn_error_t *
-run_set_text_conflict_markers(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_set_text_conflict_markers(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg = work_item->children->next;
const char *local_relpath;
@@ -1331,58 +1306,42 @@ run_set_text_conflict_markers(svn_wc__db_t *db,
scratch_pool, scratch_pool));
}
- return svn_error_trace(
- svn_wc__db_temp_op_set_text_conflict_marker_files(db,
- local_abspath,
- old_abspath,
- new_abspath,
- wrk_abspath,
- scratch_pool));
-}
-
+ /* Upgrade scenario: We have a workqueue item that describes how to install a
+ non skel conflict. Fetch all the information we can to create a new style
+ conflict. */
+ /* ### Before format 30 this is/was a common code path as we didn't install
+ ### the conflict directly in the db. It just calls the wc_db code
+ ### to set the right fields. */
-svn_error_t *
-svn_wc__wq_tmp_build_set_text_conflict_markers(svn_skel_t **work_item,
- svn_wc__db_t *db,
- const char *local_abspath,
- const char *old_abspath,
- const char *new_abspath,
- const char *wrk_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const char *local_relpath;
- *work_item = svn_skel__make_empty_list(result_pool);
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
- /* Abspaths in the workqueue won't work if the WC is moved. */
- if (wrk_abspath)
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- wrk_abspath, result_pool, scratch_pool));
-
- svn_skel__prepend_str(wrk_abspath ? local_relpath : "",
- *work_item, result_pool);
+ {
+ /* Check if we should combine with a property conflict... */
+ svn_skel_t *conflicts;
- if (new_abspath)
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- new_abspath, result_pool, scratch_pool));
- svn_skel__prepend_str(new_abspath ? local_relpath : "",
- *work_item, result_pool);
+ SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
+ scratch_pool, scratch_pool));
- if (old_abspath)
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- old_abspath, result_pool, scratch_pool));
- svn_skel__prepend_str(old_abspath ? local_relpath : "",
- *work_item, result_pool);
+ if (! conflicts)
+ {
+ /* No conflict exists, create a basic skel */
+ conflicts = svn_wc__conflict_skel_create(scratch_pool);
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- local_abspath, result_pool, scratch_pool));
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(conflicts, NULL, NULL,
+ scratch_pool,
+ scratch_pool));
+ }
- svn_skel__prepend_str(local_relpath, *work_item, result_pool);
- svn_skel__prepend_str(OP_TMP_SET_TEXT_CONFLICT_MARKERS, *work_item,
- result_pool);
+ /* Add the text conflict to the existing onflict */
+ SVN_ERR(svn_wc__conflict_skel_add_text_conflict(conflicts, db,
+ local_abspath,
+ wrk_abspath,
+ old_abspath,
+ new_abspath,
+ scratch_pool,
+ scratch_pool));
+ SVN_ERR(svn_wc__db_op_mark_conflict(db, local_abspath, conflicts,
+ NULL, scratch_pool));
+ }
return SVN_NO_ERROR;
}
@@ -1391,7 +1350,8 @@ svn_wc__wq_tmp_build_set_text_conflict_markers(svn_skel_t **work_item,
/* OP_TMP_SET_PROPERTY_CONFLICT_MARKER */
static svn_error_t *
-run_set_property_conflict_marker(svn_wc__db_t *db,
+run_set_property_conflict_marker(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1411,47 +1371,43 @@ run_set_property_conflict_marker(svn_wc__db_t *db,
arg = arg->next;
local_relpath = arg->len ? apr_pstrmemdup(scratch_pool, arg->data, arg->len)
- : NULL;
+ : NULL;
if (local_relpath)
SVN_ERR(svn_wc__db_from_relpath(&prej_abspath, db, wri_abspath,
local_relpath,
scratch_pool, scratch_pool));
- return svn_error_trace(
- svn_wc__db_temp_op_set_property_conflict_marker_file(db,
- local_abspath,
- prej_abspath,
- scratch_pool));
-}
-
-svn_error_t *
-svn_wc__wq_tmp_build_set_property_conflict_marker(svn_skel_t **work_item,
- svn_wc__db_t *db,
- const char *local_abspath,
- const char *prej_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- const char *local_relpath;
- *work_item = svn_skel__make_empty_list(result_pool);
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ {
+ /* Check if we should combine with a text conflict... */
+ svn_skel_t *conflicts;
+ apr_hash_t *prop_names;
- if (prej_abspath)
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- prej_abspath, result_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
+ scratch_pool, scratch_pool));
- svn_skel__prepend_str(prej_abspath ? local_relpath : "",
- *work_item, result_pool);
+ if (! conflicts)
+ {
+ /* No conflict exists, create a basic skel */
+ conflicts = svn_wc__conflict_skel_create(scratch_pool);
- SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
- local_abspath, result_pool, scratch_pool));
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(conflicts, NULL, NULL,
+ scratch_pool,
+ scratch_pool));
+ }
- svn_skel__prepend_str(local_relpath, *work_item, result_pool);
- svn_skel__prepend_str(OP_TMP_SET_PROPERTY_CONFLICT_MARKER, *work_item,
- result_pool);
+ prop_names = apr_hash_make(scratch_pool);
+ SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflicts, db,
+ local_abspath,
+ prej_abspath,
+ NULL, NULL, NULL,
+ prop_names,
+ scratch_pool,
+ scratch_pool));
+ SVN_ERR(svn_wc__db_op_mark_conflict(db, local_abspath, conflicts,
+ NULL, scratch_pool));
+ }
return SVN_NO_ERROR;
}
@@ -1465,21 +1421,35 @@ static const struct work_item_dispatch dispatch_table[] = {
{ OP_FILE_COPY_TRANSLATED, run_file_copy_translated },
{ OP_SYNC_FILE_FLAGS, run_sync_file_flags },
{ OP_PREJ_INSTALL, run_prej_install },
- { OP_RECORD_FILEINFO, run_record_fileinfo },
- { OP_BASE_REMOVE, run_base_remove },
- { OP_TMP_SET_TEXT_CONFLICT_MARKERS, run_set_text_conflict_markers },
- { OP_TMP_SET_PROPERTY_CONFLICT_MARKER, run_set_property_conflict_marker },
+ { OP_DIRECTORY_REMOVE, run_dir_remove },
+ { OP_DIRECTORY_INSTALL, run_dir_install },
/* Upgrade steps */
{ OP_POSTUPGRADE, run_postupgrade },
+ /* Legacy workqueue items. No longer created */
+ { OP_BASE_REMOVE, run_base_remove },
+ { OP_RECORD_FILEINFO, run_record_fileinfo },
+ { OP_TMP_SET_TEXT_CONFLICT_MARKERS, run_set_text_conflict_markers },
+ { OP_TMP_SET_PROPERTY_CONFLICT_MARKER, run_set_property_conflict_marker },
+
/* Sentinel. */
{ NULL }
};
+struct work_item_baton_t
+{
+ apr_pool_t *result_pool; /* Pool to allocate result in */
+
+ svn_boolean_t used; /* needs reset */
+
+ apr_hash_t *record_map; /* const char * -> svn_io_dirent2_t map */
+};
+
static svn_error_t *
-dispatch_work_item(svn_wc__db_t *db,
+dispatch_work_item(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const char *wri_abspath,
const svn_skel_t *work_item,
svn_cancel_func_t cancel_func,
@@ -1497,7 +1467,7 @@ dispatch_work_item(svn_wc__db_t *db,
#ifdef SVN_DEBUG_WORK_QUEUE
SVN_DBG(("dispatch: operation='%s'\n", scan->name));
#endif
- SVN_ERR((*scan->func)(db, work_item, wri_abspath,
+ SVN_ERR((*scan->func)(wqb, db, work_item, wri_abspath,
cancel_func, cancel_baton,
scratch_pool));
@@ -1526,10 +1496,7 @@ dispatch_work_item(svn_wc__db_t *db,
Contrary to issue #1581, we cannot simply remove work items and
continue, so bail out with an error. */
return svn_error_createf(SVN_ERR_WC_BAD_ADM_LOG, NULL,
- _("Unrecognized work item in the queue "
- "associated with '%s'"),
- svn_dirent_local_style(wri_abspath,
- scratch_pool));
+ _("Unrecognized work item in the queue"));
}
return SVN_NO_ERROR;
@@ -1545,6 +1512,8 @@ svn_wc__wq_run(svn_wc__db_t *db,
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_uint64_t last_id = 0;
+ work_item_baton_t wib = { 0 };
+ wib.result_pool = svn_pool_create(scratch_pool);
#ifdef SVN_DEBUG_WORK_QUEUE
SVN_DBG(("wq_run: wri='%s'\n", wri_abspath));
@@ -1561,14 +1530,33 @@ svn_wc__wq_run(svn_wc__db_t *db,
{
apr_uint64_t id;
svn_skel_t *work_item;
+ svn_error_t *err;
svn_pool_clear(iterpool);
- /* Make sure to do this *early* in the loop iteration. There may
- be a LAST_ID that needs to be marked as completed, *before* we
- start worrying about anything else. */
- SVN_ERR(svn_wc__db_wq_fetch_next(&id, &work_item, db, wri_abspath,
- last_id, iterpool, iterpool));
+ if (! wib.used)
+ {
+ /* Make sure to do this *early* in the loop iteration. There may
+ be a LAST_ID that needs to be marked as completed, *before* we
+ start worrying about anything else. */
+ SVN_ERR(svn_wc__db_wq_fetch_next(&id, &work_item, db, wri_abspath,
+ last_id, iterpool, iterpool));
+ }
+ else
+ {
+ /* Make sure to do this *early* in the loop iteration. There may
+ be a LAST_ID that needs to be marked as completed, *before* we
+ start worrying about anything else. */
+ SVN_ERR(svn_wc__db_wq_record_and_fetch_next(&id, &work_item,
+ db, wri_abspath,
+ last_id, wib.record_map,
+ iterpool,
+ wib.result_pool));
+
+ svn_pool_clear(wib.result_pool);
+ wib.record_map = NULL;
+ wib.used = FALSE;
+ }
/* Stop work queue processing, if requested. A future 'svn cleanup'
should be able to continue the processing. Note that we may
@@ -1580,8 +1568,20 @@ svn_wc__wq_run(svn_wc__db_t *db,
we're done. */
if (work_item == NULL)
break;
- SVN_ERR(dispatch_work_item(db, wri_abspath, work_item,
- cancel_func, cancel_baton, iterpool));
+
+ err = dispatch_work_item(&wib, db, wri_abspath, work_item,
+ cancel_func, cancel_baton, iterpool);
+ if (err)
+ {
+ const char *skel = svn_skel__unparse(work_item, scratch_pool)->data;
+
+ return svn_error_createf(SVN_ERR_WC_BAD_ADM_LOG, err,
+ _("Failed to run the WC DB work queue "
+ "associated with '%s', work item %d %s"),
+ svn_dirent_local_style(wri_abspath,
+ scratch_pool),
+ (int)id, skel);
+ }
/* The work item finished without error. Mark it completed
in the next loop. */
@@ -1639,3 +1639,29 @@ svn_wc__wq_merge(svn_skel_t *work_item1,
svn_skel__append(work_item1, work_item2->children);
return work_item1;
}
+
+
+static svn_error_t *
+get_and_record_fileinfo(work_item_baton_t *wqb,
+ const char *local_abspath,
+ svn_boolean_t ignore_enoent,
+ apr_pool_t *scratch_pool)
+{
+ const svn_io_dirent2_t *dirent;
+
+ SVN_ERR(svn_io_stat_dirent2(&dirent, local_abspath, FALSE, ignore_enoent,
+ wqb->result_pool, scratch_pool));
+
+ if (dirent->kind != svn_node_file)
+ return SVN_NO_ERROR;
+
+ wqb->used = TRUE;
+
+ if (! wqb->record_map)
+ wqb->record_map = apr_hash_make(wqb->result_pool);
+
+ svn_hash_sets(wqb->record_map, apr_pstrdup(wqb->result_pool, local_abspath),
+ dirent);
+
+ return SVN_NO_ERROR;
+}