aboutsummaryrefslogtreecommitdiff
path: root/subversion/libsvn_client/mtcc.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
committerPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
commit3faf8d6bffc5d0fb2525ba37bb504c53366caf9d (patch)
tree7e47911263e75034b767fe34b2f8d3d17e91f66d /subversion/libsvn_client/mtcc.c
parenta55fb3c0d5eca7d887798125d5b95942b1f01d4b (diff)
Diffstat (limited to 'subversion/libsvn_client/mtcc.c')
-rw-r--r--subversion/libsvn_client/mtcc.c67
1 files changed, 62 insertions, 5 deletions
diff --git a/subversion/libsvn_client/mtcc.c b/subversion/libsvn_client/mtcc.c
index e0fc1e9441b0..75889cad2746 100644
--- a/subversion/libsvn_client/mtcc.c
+++ b/subversion/libsvn_client/mtcc.c
@@ -568,10 +568,44 @@ svn_client__mtcc_add_copy(const char *src_relpath,
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_client__mtcc_add_delete(const char *relpath,
- svn_client__mtcc_t *mtcc,
- apr_pool_t *scratch_pool)
+/* Check if this operation contains at least one change that is not a
+ plain delete */
+static svn_boolean_t
+mtcc_op_contains_non_delete(const mtcc_op_t *op)
+{
+ if (op->kind != OP_OPEN_DIR && op->kind != OP_OPEN_FILE
+ && op->kind != OP_DELETE)
+ {
+ return TRUE;
+ }
+
+ if (op->prop_mods && op->prop_mods->nelts)
+ return TRUE;
+
+ if (op->src_stream)
+ return TRUE;
+
+ if (op->children)
+ {
+ int i;
+
+ for (i = 0; i < op->children->nelts; i++)
+ {
+ const mtcc_op_t *c_op = APR_ARRAY_IDX(op->children, i,
+ const mtcc_op_t *);
+
+ if (mtcc_op_contains_non_delete(c_op))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static svn_error_t *
+mtcc_add_delete(const char *relpath,
+ svn_boolean_t for_move,
+ svn_client__mtcc_t *mtcc,
+ apr_pool_t *scratch_pool)
{
mtcc_op_t *op;
svn_boolean_t created;
@@ -598,6 +632,20 @@ svn_client__mtcc_add_delete(const char *relpath,
SVN_ERR(mtcc_op_find(&op, &created, relpath, mtcc->root_op, FALSE, TRUE,
TRUE, mtcc->pool, scratch_pool));
+ if (!for_move && !op && !created)
+ {
+ /* Allow deleting directories, that are unmodified except for
+ one or more deleted descendants */
+
+ SVN_ERR(mtcc_op_find(&op, &created, relpath, mtcc->root_op, TRUE,
+ FALSE, FALSE, mtcc->pool, scratch_pool));
+
+ if (op && mtcc_op_contains_non_delete(op))
+ op = NULL;
+ else
+ created = TRUE;
+ }
+
if (!op || !created)
{
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -614,6 +662,14 @@ svn_client__mtcc_add_delete(const char *relpath,
}
svn_error_t *
+svn_client__mtcc_add_delete(const char *relpath,
+ svn_client__mtcc_t *mtcc,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(mtcc_add_delete(relpath, FALSE, mtcc, scratch_pool));
+}
+
+svn_error_t *
svn_client__mtcc_add_mkdir(const char *relpath,
svn_client__mtcc_t *mtcc,
apr_pool_t *scratch_pool)
@@ -662,7 +718,7 @@ svn_client__mtcc_add_move(const char *src_relpath,
SVN_ERR(svn_client__mtcc_add_copy(src_relpath, mtcc->base_revision,
dst_relpath, mtcc, scratch_pool));
- SVN_ERR(svn_client__mtcc_add_delete(src_relpath, mtcc, scratch_pool));
+ SVN_ERR(mtcc_add_delete(src_relpath, TRUE, mtcc, scratch_pool));
return SVN_NO_ERROR;
}
@@ -712,6 +768,7 @@ mtcc_prop_getter(const svn_string_t **mime_type,
{
*mime_type = svn_string_dup(mod->value, pool);
mime_type = NULL;
+ break;
}
}
}