1151
/* Each name is allocated in RESULT_POOL and stored into CHILDREN as a key
1152
pointed to the same name. */
1153
static svn_error_t *
1154
add_children_to_hash(apr_hash_t *children,
1156
svn_sqlite__db_t *sdb,
1158
const char *parent_relpath,
1159
apr_pool_t *result_pool)
1161
svn_sqlite__stmt_t *stmt;
1162
svn_boolean_t have_row;
1164
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, stmt_idx));
1165
SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
1166
SVN_ERR(svn_sqlite__step(&have_row, stmt));
1169
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
1170
const char *name = svn_relpath_basename(child_relpath, result_pool);
1172
svn_hash_sets(children, name, name);
1174
SVN_ERR(svn_sqlite__step(&have_row, stmt));
1177
return svn_sqlite__reset(stmt);
1181
/* Set *CHILDREN to a new array of the (const char *) basenames of the
1182
immediate children, whatever their status, of the working node at
1184
static svn_error_t *
1185
gather_children2(const apr_array_header_t **children,
1186
svn_wc__db_wcroot_t *wcroot,
1187
const char *local_relpath,
1188
apr_pool_t *result_pool,
1189
apr_pool_t *scratch_pool)
1191
apr_hash_t *names_hash = apr_hash_make(scratch_pool);
1192
apr_array_header_t *names_array;
1194
/* All of the names get allocated in RESULT_POOL. It
1195
appears to be faster to use the hash to remove duplicates than to
1196
use DISTINCT in the SQL query. */
1197
SVN_ERR(add_children_to_hash(names_hash, STMT_SELECT_WORKING_CHILDREN,
1198
wcroot->sdb, wcroot->wc_id,
1199
local_relpath, result_pool));
1201
SVN_ERR(svn_hash_keys(&names_array, names_hash, result_pool));
1202
*children = names_array;
1203
return SVN_NO_ERROR;
1206
1156
/* Return in *CHILDREN all of the children of the directory LOCAL_RELPATH,
1207
1157
of any status, in all op-depths in the NODES table. */
1208
1158
static svn_error_t *
1209
1159
gather_children(const apr_array_header_t **children,
1210
1160
svn_wc__db_wcroot_t *wcroot,
1211
const char *local_relpath,
1161
const char *parent_relpath,
1212
1164
apr_pool_t *result_pool,
1213
1165
apr_pool_t *scratch_pool)
1215
apr_hash_t *names_hash = apr_hash_make(scratch_pool);
1216
apr_array_header_t *names_array;
1218
/* All of the names get allocated in RESULT_POOL. It
1219
appears to be faster to use the hash to remove duplicates than to
1220
use DISTINCT in the SQL query. */
1221
SVN_ERR(add_children_to_hash(names_hash, STMT_SELECT_NODE_CHILDREN,
1222
wcroot->sdb, wcroot->wc_id,
1223
local_relpath, result_pool));
1225
SVN_ERR(svn_hash_keys(&names_array, names_hash, result_pool));
1226
*children = names_array;
1227
return SVN_NO_ERROR;
1231
/* Set *CHILDREN to a new array of (const char *) names of the children of
1232
the repository directory corresponding to WCROOT:LOCAL_RELPATH:OP_DEPTH -
1233
that is, only the children that are at the same op-depth as their parent. */
1234
static svn_error_t *
1235
gather_repo_children(const apr_array_header_t **children,
1236
svn_wc__db_wcroot_t *wcroot,
1237
const char *local_relpath,
1239
apr_pool_t *result_pool,
1240
apr_pool_t *scratch_pool)
1242
apr_array_header_t *result
1243
= apr_array_make(result_pool, 0, sizeof(const char *));
1167
apr_array_header_t *result;
1244
1168
svn_sqlite__stmt_t *stmt;
1245
1169
svn_boolean_t have_row;
1247
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
1248
STMT_SELECT_OP_DEPTH_CHILDREN));
1249
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
1171
result = apr_array_make(result_pool, 16, sizeof(const char*));
1173
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, stmt_idx));
1174
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, parent_relpath));
1176
SVN_ERR(svn_sqlite__bind_int(stmt, 3, op_depth));
1251
1178
SVN_ERR(svn_sqlite__step(&have_row, stmt));
1252
1179
while (have_row)
1254
1181
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
1182
const char *name = svn_relpath_basename(child_relpath, result_pool);
1256
/* Allocate the name in RESULT_POOL so we won't have to copy it. */
1257
APR_ARRAY_PUSH(result, const char *)
1258
= svn_relpath_basename(child_relpath, result_pool);
1184
APR_ARRAY_PUSH(result, const char *) = name;
1260
1186
SVN_ERR(svn_sqlite__step(&have_row, stmt));
1262
1189
SVN_ERR(svn_sqlite__reset(stmt));
1264
1190
*children = result;
1265
1191
return SVN_NO_ERROR;
1269
svn_wc__db_get_children_op_depth(apr_hash_t **children,
1270
svn_wc__db_wcroot_t *wcroot,
1271
const char *local_relpath,
1273
apr_pool_t *result_pool,
1274
apr_pool_t *scratch_pool)
1276
svn_sqlite__stmt_t *stmt;
1277
svn_boolean_t have_row;
1279
*children = apr_hash_make(result_pool);
1281
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
1282
STMT_SELECT_OP_DEPTH_CHILDREN));
1283
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
1285
SVN_ERR(svn_sqlite__step(&have_row, stmt));
1288
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
1289
svn_node_kind_t *child_kind = apr_palloc(result_pool, sizeof(svn_node_kind_t));
1291
*child_kind = svn_sqlite__column_token(stmt, 1, kind_map);
1292
svn_hash_sets(*children,
1293
svn_relpath_basename(child_relpath, result_pool),
1296
SVN_ERR(svn_sqlite__step(&have_row, stmt));
1298
SVN_ERR(svn_sqlite__reset(stmt));
1300
return SVN_NO_ERROR;
1304
1194
/* Return TRUE if CHILD_ABSPATH is an immediate child of PARENT_ABSPATH.
1305
1195
* Else, return FALSE. */
1306
1196
static svn_boolean_t
2128
2045
/* Recursively clear moved-here information at the copy-half of the move
2129
* which moved the node at SRC_RELPATH away. This transforms the move into
2046
* which moved a node to MOVED_TO_RELPATH. This transforms this side of the
2047
* move into a simple copy.
2131
2049
static svn_error_t *
2132
clear_moved_here(const char *src_relpath,
2133
svn_wc__db_wcroot_t *wcroot,
2050
clear_moved_here(svn_wc__db_wcroot_t *wcroot,
2051
const char *moved_to_relpath,
2134
2052
apr_pool_t *scratch_pool)
2136
2054
svn_sqlite__stmt_t *stmt;
2137
const char *dst_relpath;
2139
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_MOVED_TO));
2140
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
2141
src_relpath, relpath_depth(src_relpath)));
2142
SVN_ERR(svn_sqlite__step_row(stmt));
2143
dst_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
2144
SVN_ERR(svn_sqlite__reset(stmt));
2146
2057
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
2147
2058
STMT_CLEAR_MOVED_HERE_RECURSIVE));
2148
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
2149
dst_relpath, relpath_depth(dst_relpath)));
2150
SVN_ERR(svn_sqlite__step_done(stmt));
2152
return SVN_NO_ERROR;
2059
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, moved_to_relpath,
2060
relpath_depth(moved_to_relpath)));
2062
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
2064
if (affected_rows == 0)
2065
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
2066
_("The node '%s' was not found."),
2067
path_for_error_message(wcroot, moved_to_relpath,
2070
return SVN_NO_ERROR;
2074
svn_wc__db_op_break_move_internal(svn_wc__db_wcroot_t *wcroot,
2075
const char *src_relpath,
2076
int delete_op_depth,
2077
const char *dst_relpath,
2078
const svn_skel_t *work_items,
2079
apr_pool_t *scratch_pool)
2081
svn_sqlite__stmt_t *stmt;
2084
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
2085
STMT_CLEAR_MOVED_TO_RELPATH));
2086
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, src_relpath,
2088
SVN_ERR(svn_sqlite__update(&affected, stmt));
2091
return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
2092
_("Path '%s' is not moved"),
2093
path_for_error_message(wcroot, src_relpath,
2096
SVN_ERR(clear_moved_here(wcroot, dst_relpath, scratch_pool));
2098
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
2099
return SVN_NO_ERROR;
2155
2103
/* The body of svn_wc__db_base_remove().
2169
2117
svn_sqlite__stmt_t *stmt;
2170
2118
svn_boolean_t have_row;
2171
2119
svn_wc__db_status_t status;
2120
svn_revnum_t revision;
2172
2121
apr_int64_t repos_id;
2173
2122
const char *repos_relpath;
2174
2123
svn_node_kind_t kind;
2175
2124
svn_boolean_t keep_working;
2126
svn_node_kind_t wrk_kind;
2127
svn_boolean_t no_delete_wc = FALSE;
2128
svn_boolean_t file_external;
2177
SVN_ERR(svn_wc__db_base_get_info_internal(&status, &kind, NULL,
2130
SVN_ERR(svn_wc__db_base_get_info_internal(&status, &kind, &revision,
2178
2131
&repos_relpath, &repos_id,
2179
2132
NULL, NULL, NULL, NULL, NULL,
2180
NULL, NULL, NULL, NULL, NULL,
2133
NULL, NULL, NULL, NULL,
2181
2135
wcroot, local_relpath,
2182
2136
scratch_pool, scratch_pool));
2138
/* Check if there is already a working node */
2139
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
2140
STMT_SELECT_NODE_INFO));
2141
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
2142
SVN_ERR(svn_sqlite__step(&have_row, stmt));
2145
return svn_error_trace(svn_sqlite__reset(stmt)); /* No BASE */
2147
op_depth = svn_sqlite__column_int(stmt, 0);
2148
wrk_kind = svn_sqlite__column_token(stmt, 4, kind_map);
2151
&& op_depth == relpath_depth(local_relpath))
2186
svn_sqlite__stmt_t *lock_stmt;
2153
svn_wc__db_status_t presence;
2154
presence = svn_sqlite__column_token(stmt, 3, presence_map);
2188
SVN_ERR(svn_sqlite__get_statement(&lock_stmt, wcroot->sdb,
2189
STMT_DELETE_LOCK_RECURSIVELY));
2190
SVN_ERR(svn_sqlite__bindf(lock_stmt, "is", repos_id, repos_relpath));
2191
SVN_ERR(svn_sqlite__step_done(lock_stmt));
2156
if (presence == svn_wc__db_status_base_deleted)
2158
keep_working = FALSE;
2159
no_delete_wc = TRUE;
2163
keep_working = TRUE;
2167
keep_working = FALSE;
2168
SVN_ERR(svn_sqlite__reset(stmt));
2194
if (status == svn_wc__db_status_normal
2170
if (keep_as_working && op_depth == 0)
2197
SVN_ERR(svn_wc__db_op_make_copy(db,
2198
svn_dirent_join(wcroot->abspath,
2172
if (status == svn_wc__db_status_normal
2173
|| status == svn_wc__db_status_incomplete)
2175
SVN_ERR(svn_wc__db_op_make_copy_internal(wcroot, local_relpath, TRUE,
2203
2179
keep_working = TRUE;
2207
/* Check if there is already a working node */
2208
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
2209
STMT_SELECT_WORKING_NODE));
2210
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
2211
SVN_ERR(svn_sqlite__step(&keep_working, stmt));
2212
SVN_ERR(svn_sqlite__reset(stmt));
2215
2182
/* Step 1: Create workqueue operations to remove files and dirs in the
2219
&& (status == svn_wc__db_status_normal
2220
|| status == svn_wc__db_status_incomplete))
2184
if (!keep_working && !no_delete_wc)
2222
2186
svn_skel_t *work_item;
2223
2187
const char *local_abspath;
2225
2189
local_abspath = svn_dirent_join(wcroot->abspath, local_relpath,
2227
if (kind == svn_node_dir)
2191
if (wrk_kind == svn_node_dir)
2229
2193
apr_pool_t *iterpool;
2230
2194
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
2231
STMT_SELECT_BASE_PRESENT));
2195
STMT_SELECT_WORKING_PRESENT));
2232
2196
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
2234
2198
iterpool = svn_pool_create(scratch_pool);
2372
2362
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
2373
2363
SVN_ERR(svn_sqlite__step_done(stmt));
2375
/* Step 5: handle the BASE node itself */
2376
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
2377
STMT_DELETE_BASE_NODE));
2378
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
2379
SVN_ERR(svn_sqlite__step_done(stmt));
2381
SVN_ERR(svn_wc__db_retract_parent_delete(wcroot, local_relpath, 0,
2384
/* Step 6: Delete actual node if we don't keep working */
2387
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
2388
STMT_DELETE_ACTUAL_NODE));
2389
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
2390
SVN_ERR(svn_sqlite__step_done(stmt));
2393
if (SVN_IS_VALID_REVNUM(not_present_revision))
2365
SVN_ERR(db_retract_parent_delete(wcroot, local_relpath, 0, scratch_pool));
2367
if (mark_not_present || mark_excluded)
2395
2369
struct insert_base_baton_t ibb;
2398
ibb.repos_id = repos_id;
2399
ibb.status = svn_wc__db_status_not_present;
2401
ibb.repos_relpath = repos_relpath;
2402
ibb.revision = not_present_revision;
2404
/* Depending upon KIND, any of these might get used. */
2405
ibb.children = NULL;
2406
ibb.depth = svn_depth_unknown;
2407
ibb.checksum = NULL;
2410
SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
2370
svn_boolean_t no_marker = FALSE;
2374
const char *parent_local_relpath;
2378
/* For file externals we only want to place a not present marker
2379
if there is a BASE parent */
2381
svn_relpath_split(&parent_local_relpath, &name, local_relpath,
2384
err = svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
2385
&repos_relpath, &repos_id,
2386
NULL, NULL, NULL, NULL, NULL,
2387
NULL, NULL, NULL, NULL, NULL,
2388
wcroot, parent_local_relpath,
2389
scratch_pool, scratch_pool);
2391
if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
2392
return svn_error_trace(err);
2395
svn_error_clear(err);
2400
/* Replace the repos_relpath with something more expected than
2401
the unrelated old file external repository relpath, which
2402
one day may come from a different repository */
2403
repos_relpath = svn_relpath_join(repos_relpath, name, scratch_pool);
2411
ibb.repos_id = repos_id;
2412
ibb.status = mark_excluded ? svn_wc__db_status_excluded
2413
: svn_wc__db_status_not_present;
2415
ibb.repos_relpath = repos_relpath;
2416
ibb.revision = SVN_IS_VALID_REVNUM(marker_revision)
2420
/* Depending upon KIND, any of these might get used. */
2421
ibb.children = NULL;
2422
ibb.depth = svn_depth_unknown;
2423
ibb.checksum = NULL;
2426
SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
2413
2430
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
4754
4855
/* Call with the sdb in src_wcroot. It might call itself again to
4755
4856
also obtain a lock in dst_wcroot */
4756
SVN_ERR(svn_sqlite__with_lock(ocb.src_wcroot->sdb, op_copy_txn, &ocb,
4857
SVN_WC__DB_WITH_TXN(op_copy_txn(ocb.src_wcroot, &ocb, scratch_pool),
4860
return SVN_NO_ERROR;
4863
/* Remove unneeded actual nodes for svn_wc__db_op_copy_layer_internal */
4864
static svn_error_t *
4865
clear_or_remove_actual(svn_wc__db_wcroot_t *wcroot,
4866
const char *local_relpath,
4868
apr_pool_t *scratch_pool)
4870
svn_sqlite__stmt_t *stmt;
4871
svn_boolean_t have_row, shadowed;
4872
svn_boolean_t keep_conflict = FALSE;
4874
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
4875
STMT_SELECT_NODE_INFO));
4877
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
4878
SVN_ERR(svn_sqlite__step(&have_row, stmt));
4882
svn_wc__db_status_t presence;
4884
shadowed = (svn_sqlite__column_int(stmt, 0) > op_depth);
4885
presence = svn_sqlite__column_token(stmt, 3, presence_map);
4887
if (shadowed && presence == svn_wc__db_status_base_deleted)
4889
keep_conflict = TRUE;
4890
SVN_ERR(svn_sqlite__step(&have_row, stmt));
4893
shadowed = (svn_sqlite__column_int(stmt, 0) > op_depth);
4901
SVN_ERR(svn_sqlite__reset(stmt));
4903
return SVN_NO_ERROR;
4907
/* We don't want to accidentally remove delete-delete conflicts */
4908
SVN_ERR(svn_sqlite__get_statement(
4910
STMT_CLEAR_ACTUAL_NODE_LEAVING_CONFLICT));
4911
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
4912
SVN_ERR(svn_sqlite__step_done(stmt));
4913
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
4914
STMT_DELETE_ACTUAL_EMPTY));
4915
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
4916
SVN_ERR(svn_sqlite__step_done(stmt));
4920
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
4921
STMT_DELETE_ACTUAL_NODE));
4922
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
4923
SVN_ERR(svn_sqlite__step_done(stmt));
4926
return SVN_NO_ERROR;
4930
svn_wc__db_op_copy_layer_internal(svn_wc__db_wcroot_t *wcroot,
4931
const char *src_op_relpath,
4933
const char *dst_op_relpath,
4934
svn_skel_t *conflict,
4935
svn_skel_t *work_items,
4936
apr_pool_t *scratch_pool)
4938
svn_sqlite__stmt_t *stmt, *stmt2;
4939
svn_boolean_t have_row;
4940
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
4941
int dst_op_depth = relpath_depth(dst_op_relpath);
4942
svn_boolean_t locked;
4943
svn_error_t *err = NULL;
4945
SVN_ERR(svn_wc__db_wclock_owns_lock_internal(&locked, wcroot, dst_op_relpath,
4946
FALSE, scratch_pool));
4949
return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL,
4950
_("No write-lock in '%s'"),
4951
path_for_error_message(wcroot, dst_op_relpath,
4954
SVN_ERR(svn_sqlite__get_statement(&stmt2, wcroot->sdb,
4955
STMT_COPY_NODE_MOVE));
4957
/* Replace entire subtree at one op-depth. */
4958
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
4959
STMT_SELECT_LAYER_FOR_REPLACE));
4960
SVN_ERR(svn_sqlite__bindf(stmt, "isdsd", wcroot->wc_id,
4961
src_op_relpath, src_op_depth,
4962
dst_op_relpath, dst_op_depth));
4963
SVN_ERR(svn_sqlite__step(&have_row, stmt));
4966
const char *src_relpath;
4967
const char *dst_relpath;
4969
svn_pool_clear(iterpool);
4971
src_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
4972
dst_relpath = svn_sqlite__column_text(stmt, 2, iterpool);
4974
err = svn_sqlite__bindf(stmt2, "isdsds", wcroot->wc_id,
4975
src_relpath, src_op_depth,
4976
dst_relpath, dst_op_depth,
4977
svn_relpath_dirname(dst_relpath, iterpool));
4979
err = svn_sqlite__step_done(stmt2);
4981
/* stmt2 is reset (never modified or by step_done) */
4986
/* The node can't be deleted where it is added, so extension of
4987
an existing shadowing is only interesting 2 levels deep. */
4988
if (relpath_depth(dst_relpath) > (dst_op_depth+1))
4990
svn_boolean_t exists = !svn_sqlite__column_is_null(stmt, 3);
4994
svn_wc__db_status_t presence;
4996
presence = svn_sqlite__column_token(stmt, 3, presence_map);
4998
if (presence != svn_wc__db_status_normal)
5004
svn_node_kind_t kind = svn_sqlite__column_token(stmt, 1, kind_map);
5006
err = db_extend_parent_delete(wcroot, dst_relpath,
5007
kind, dst_op_depth, iterpool);
5014
SVN_ERR(svn_sqlite__step(&have_row, stmt));
5017
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
5019
/* And now remove the records that are no longer needed */
5020
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
5021
STMT_SELECT_NO_LONGER_MOVED_RV));
5022
SVN_ERR(svn_sqlite__bindf(stmt, "isdsd", wcroot->wc_id,
5023
dst_op_relpath, dst_op_depth,
5024
src_op_relpath, src_op_depth));
5025
SVN_ERR(svn_sqlite__step(&have_row, stmt));
5028
const char *dst_relpath;
5029
svn_wc__db_status_t shadowed_presence;
5031
svn_pool_clear(iterpool);
5033
dst_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
5035
if (!svn_sqlite__column_is_null(stmt, 2))
5036
shadowed_presence = svn_sqlite__column_token(stmt, 2, presence_map);
5038
shadowed_presence = svn_wc__db_status_not_present;
5040
if (shadowed_presence != svn_wc__db_status_normal
5041
&& shadowed_presence != svn_wc__db_status_incomplete)
5043
err = svn_sqlite__get_statement(&stmt2, wcroot->sdb,
5048
err =svn_sqlite__get_statement(&stmt2, wcroot->sdb,
5049
STMT_REPLACE_WITH_BASE_DELETED);
5053
err = svn_sqlite__bindf(stmt2, "isd", wcroot->wc_id, dst_relpath,
5057
err = svn_sqlite__step_done(stmt2);
5059
/* stmt2 is reset (never modified or by step_done) */
5063
/* Delete ACTUAL information about this node that we just deleted */
5064
err = clear_or_remove_actual(wcroot, dst_relpath, dst_op_depth,
5070
/* Retract base-delete for the node itself */
5071
err = db_retract_parent_delete(wcroot, dst_relpath, dst_op_depth,
5077
SVN_ERR(svn_sqlite__step(&have_row, stmt));
5079
svn_pool_destroy(iterpool);
5081
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
5083
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
5086
SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, dst_op_relpath /* ## */,
5087
conflict, scratch_pool));
4759
5089
return SVN_NO_ERROR;
6598
6935
/* If this node was moved-here, clear moved-to at the move source. */
6599
6936
if (moved_here)
6600
SVN_ERR(clear_moved_to(local_relpath, wcroot, scratch_pool));
6603
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
6937
SVN_ERR(clear_moved_to(wcroot, local_relpath, scratch_pool));
6940
if (op_depth_increased && conflict)
6942
svn_wc_operation_t operation;
6943
svn_boolean_t tree_conflicted;
6944
const apr_array_header_t *locations;
6946
SVN_ERR(svn_wc__conflict_read_info(&operation, &locations, NULL, NULL,
6948
db, wcroot->abspath,
6950
scratch_pool, scratch_pool));
6952
&& (operation == svn_wc_operation_update
6953
|| operation == svn_wc_operation_switch))
6955
svn_wc_conflict_reason_t reason;
6956
svn_wc_conflict_action_t action;
6958
SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action,
6960
db, wcroot->abspath,
6965
if (reason == svn_wc_conflict_reason_deleted
6966
|| reason == svn_wc_conflict_reason_replaced)
6968
SVN_ERR(svn_wc__db_op_raise_moved_away_internal(
6969
wcroot, local_relpath, op_depth_below, db,
6971
(locations && locations->nelts > 0)
6972
? APR_ARRAY_IDX(locations, 0,
6973
const svn_wc_conflict_version_t *)
6975
(locations && locations->nelts > 1)
6976
? APR_ARRAY_IDX(locations, 1,
6977
const svn_wc_conflict_version_t *)
6981
/* Transform the move information into revert information */
6982
SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
6983
STMT_MOVE_NOTIFY_TO_REVERT));
6988
if (rvb->clear_changelists)
6990
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
6991
STMT_DELETE_ACTUAL_NODE));
6992
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
6993
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
6997
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
6604
6998
STMT_DELETE_ACTUAL_NODE_LEAVING_CHANGELIST));
6605
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
6606
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
6609
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
6610
STMT_CLEAR_ACTUAL_NODE_LEAVING_CHANGELIST));
6611
6999
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
6612
7000
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
7003
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
7004
STMT_CLEAR_ACTUAL_NODE_LEAVING_CHANGELIST));
7005
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
7006
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
6615
7010
return SVN_NO_ERROR;
9029
9459
SVN_ERR(svn_sqlite__reset(stmt));
9031
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
9032
STMT_SELECT_ACTUAL_CHILDREN_INFO));
9033
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, dir_relpath));
9034
SVN_ERR(svn_sqlite__step(&have_row, stmt));
9461
if (!base_tree_only)
9038
struct read_children_info_item_t *child_item;
9039
struct svn_wc__db_info_t *child;
9040
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
9041
const char *name = svn_relpath_basename(child_relpath, NULL);
9463
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
9464
STMT_SELECT_ACTUAL_CHILDREN_INFO));
9465
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, dir_relpath));
9466
SVN_ERR(svn_sqlite__step(&have_row, stmt));
9043
child_item = svn_hash_gets(nodes, name);
9046
child_item = apr_pcalloc(result_pool, sizeof(*child_item));
9047
child_item->info.status = svn_wc__db_status_not_present;
9050
child = &child_item->info;
9052
child->changelist = svn_sqlite__column_text(stmt, 1, result_pool);
9054
child->props_mod = !svn_sqlite__column_is_null(stmt, 2);
9470
struct read_children_info_item_t *child_item;
9471
struct svn_wc__db_info_t *child;
9472
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
9473
const char *name = svn_relpath_basename(child_relpath, NULL);
9475
child_item = svn_hash_gets(nodes, name);
9478
child_item = apr_pcalloc(result_pool, sizeof(*child_item));
9479
child_item->info.status = svn_wc__db_status_not_present;
9482
child = &child_item->info;
9484
child->changelist = svn_sqlite__column_text(stmt, 1, result_pool);
9486
child->props_mod = !svn_sqlite__column_is_null(stmt, 2);
9055
9487
#ifdef HAVE_SYMLINK
9056
if (child->props_mod)
9059
apr_hash_t *properties;
9488
if (child->props_mod)
9491
apr_hash_t *properties;
9061
err = svn_sqlite__column_properties(&properties, stmt, 2,
9062
scratch_pool, scratch_pool);
9064
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
9065
child->special = (NULL != svn_hash_gets(properties,
9493
err = svn_sqlite__column_properties(&properties, stmt, 2,
9494
scratch_pool, scratch_pool);
9496
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
9497
child->special = (NULL != svn_hash_gets(properties,
9070
child->conflicted = !svn_sqlite__column_is_null(stmt, 3); /* conflict */
9072
if (child->conflicted)
9073
svn_hash_sets(conflicts, apr_pstrdup(result_pool, name), "");
9075
SVN_ERR(svn_sqlite__step(&have_row, stmt));
9503
child->conflicted = !svn_sqlite__column_is_null(stmt, 3);
9505
if (child->conflicted)
9506
svn_hash_sets(conflicts, apr_pstrdup(result_pool, name), "");
9508
SVN_ERR(svn_sqlite__step(&have_row, stmt));
9511
SVN_ERR(svn_sqlite__reset(stmt));
9078
SVN_ERR(svn_sqlite__reset(stmt));
9080
9514
return SVN_NO_ERROR;
9127
9568
const svn_checksum_t *checksum;
9128
9569
const char *original_repos_relpath;
9129
9570
svn_boolean_t have_work;
9571
apr_hash_t *properties;
9131
9573
mtb = apr_pcalloc(result_pool, sizeof(*mtb));
9133
SVN_ERR(read_info(&mtb->status, &mtb->kind, &mtb->revnum,
9134
&mtb->repos_relpath, &repos_id, &mtb->changed_rev,
9135
&mtb->changed_date, &mtb->changed_author, &mtb->depth,
9136
&checksum, NULL, &original_repos_relpath, NULL, NULL,
9137
&mtb->lock, &mtb->recorded_size, &mtb->recorded_time,
9138
&mtb->changelist, &mtb->conflicted, &mtb->op_root,
9139
&mtb->had_props, &mtb->props_mod, &mtb->have_base,
9140
&mtb->have_more_work, &have_work,
9141
wcroot, local_relpath,
9142
result_pool, scratch_pool));
9575
if (!base_tree_only)
9576
SVN_ERR(read_info(&mtb->status, &mtb->kind, &mtb->revnum,
9577
&mtb->repos_relpath, &repos_id, &mtb->changed_rev,
9578
&mtb->changed_date, &mtb->changed_author, &mtb->depth,
9579
&checksum, NULL, &original_repos_relpath, NULL, NULL,
9580
&mtb->lock, &mtb->recorded_size, &mtb->recorded_time,
9581
&mtb->changelist, &mtb->conflicted, &mtb->op_root,
9582
&mtb->had_props, &mtb->props_mod, &mtb->have_base,
9583
&mtb->have_more_work, &have_work,
9584
wcroot, local_relpath, result_pool, scratch_pool));
9587
svn_boolean_t update_root;
9590
original_repos_relpath = NULL;
9592
SVN_ERR(svn_wc__db_base_get_info_internal(
9593
&mtb->status, &mtb->kind, &mtb->revnum, &mtb->repos_relpath,
9594
&repos_id, &mtb->changed_rev, &mtb->changed_date,
9595
&mtb->changed_author, &mtb->depth, &checksum, NULL,
9596
&mtb->lock, &mtb->had_props, &properties, &update_root,
9597
wcroot, local_relpath, scratch_pool, scratch_pool));
9599
mtb->have_base = TRUE;
9600
mtb->file_external = (update_root && mtb->kind == svn_node_file);
9144
9603
/* Query the same rows in the database again for move information */
9145
9604
if (have_work && (mtb->have_base || mtb->have_more_work))
9147
9606
svn_sqlite__stmt_t *stmt;
9148
9607
svn_boolean_t have_row;
9149
const char *cur_relpath = NULL;
9152
9609
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
9153
9610
STMT_SELECT_MOVED_TO_NODE));
9577
/* The body of svn_wc__db_read_url().
10045
/* The body of svn_wc__db_read_repos_info().
9579
10047
static svn_error_t *
9580
read_url_txn(const char **url,
9581
svn_wc__db_wcroot_t *wcroot,
9582
const char *local_relpath,
9583
apr_pool_t *result_pool,
9584
apr_pool_t *scratch_pool)
10048
db_read_repos_info(svn_revnum_t *revision,
10049
const char **repos_relpath,
10050
apr_int64_t *repos_id,
10051
svn_wc__db_wcroot_t *wcroot,
10052
const char *local_relpath,
10053
apr_pool_t *result_pool,
10054
apr_pool_t *scratch_pool)
9586
10056
svn_wc__db_status_t status;
9587
const char *repos_relpath;
9588
const char *repos_root_url;
9589
apr_int64_t repos_id;
9590
svn_boolean_t have_base;
9592
SVN_ERR(read_info(&status, NULL, NULL, &repos_relpath, &repos_id, NULL,
10058
SVN_ERR(read_info(&status, NULL, revision, repos_relpath, repos_id, NULL,
9593
10059
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
9594
10060
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
9595
&have_base, NULL, NULL,
9596
wcroot, local_relpath, scratch_pool, scratch_pool));
10062
wcroot, local_relpath, result_pool, scratch_pool));
9598
if (repos_relpath == NULL)
10064
if ((repos_relpath && !*repos_relpath)
10065
|| (repos_id && *repos_id == INVALID_REPOS_ID))
9600
10067
if (status == svn_wc__db_status_added)
9602
SVN_ERR(scan_addition(NULL, NULL, &repos_relpath, &repos_id, NULL,
10069
SVN_ERR(scan_addition(NULL, NULL, repos_relpath, repos_id, NULL,
9603
10070
NULL, NULL, NULL, NULL, NULL,
9604
10071
wcroot, local_relpath,
9605
scratch_pool, scratch_pool));
10072
result_pool, scratch_pool));
9607
10074
else if (status == svn_wc__db_status_deleted)
9609
10076
const char *base_del_relpath;
9610
10077
const char *work_del_relpath;
9612
SVN_ERR(scan_deletion_txn(&base_del_relpath, NULL,
9619
if (base_del_relpath)
9621
SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
9626
NULL, NULL, NULL, NULL,
9632
repos_relpath = svn_relpath_join(
9634
svn_dirent_skip_ancestor(base_del_relpath,
10079
SVN_ERR(scan_deletion(&base_del_relpath, NULL,
10086
if (work_del_relpath)
9640
10088
/* The parent of the WORKING delete, must be an addition */
9641
10089
const char *work_relpath = NULL;
10745
11249
VERIFY_USABLE_WCROOT(wcroot);
10747
11251
return gather_children(children, wcroot, local_relpath,
11252
STMT_SELECT_NODE_CHILDREN, -1,
10748
11253
result_pool, scratch_pool);
11257
/* Implementation of svn_wc__db_global_relocate */
10753
11258
static svn_error_t *
10754
11259
relocate_txn(svn_wc__db_wcroot_t *wcroot,
10755
11260
const char *local_relpath,
10756
11261
const char *repos_root_url,
10757
const char *repos_uuid,
10758
svn_boolean_t have_base_node,
10759
apr_int64_t old_repos_id,
10760
11262
apr_pool_t *scratch_pool)
10762
11264
svn_sqlite__stmt_t *stmt;
10763
11265
apr_int64_t new_repos_id;
10765
/* This function affects all the children of the given local_relpath,
10766
but the way that it does this is through the repos inheritance mechanism.
10767
So, we only need to rewrite the repos_id of the given local_relpath,
10768
as well as any children with a non-null repos_id, as well as various
10769
repos_id fields in the locks and working_node tables.
10772
/* Get the repos_id for the new repository. */
10773
SVN_ERR(create_repos_id(&new_repos_id, repos_root_url, repos_uuid,
10774
wcroot->sdb, scratch_pool));
10776
/* Set the (base and working) repos_ids and clear the dav_caches */
10777
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
10778
STMT_RECURSIVE_UPDATE_NODE_REPO));
10779
SVN_ERR(svn_sqlite__bindf(stmt, "isii", wcroot->wc_id, local_relpath,
10780
old_repos_id, new_repos_id));
10781
SVN_ERR(svn_sqlite__step_done(stmt));
10783
if (have_base_node)
10785
/* Update any locks for the root or its children. */
10786
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
10787
STMT_UPDATE_LOCK_REPOS_ID));
10788
SVN_ERR(svn_sqlite__bindf(stmt, "ii", old_repos_id, new_repos_id));
10789
SVN_ERR(svn_sqlite__step_done(stmt));
10792
return SVN_NO_ERROR;
10797
svn_wc__db_global_relocate(svn_wc__db_t *db,
10798
const char *local_dir_abspath,
10799
const char *repos_root_url,
10800
apr_pool_t *scratch_pool)
10802
svn_wc__db_wcroot_t *wcroot;
10803
const char *local_relpath;
10804
11266
const char *local_dir_relpath;
10805
11267
svn_wc__db_status_t status;
10806
11268
const char *repos_uuid;
10807
11269
svn_boolean_t have_base_node;
10808
11270
apr_int64_t old_repos_id;
10810
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_dir_abspath));
10811
/* ### assert that we were passed a directory? */
10813
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_dir_relpath,
10814
db, local_dir_abspath, scratch_pool, scratch_pool));
10815
VERIFY_USABLE_WCROOT(wcroot);
10816
local_relpath = local_dir_relpath;
11272
local_dir_relpath = local_relpath;
10818
11274
SVN_ERR(read_info(&status,
10819
11275
NULL, NULL, NULL, &old_repos_id,
10884
11340
scratch_pool, scratch_pool));
10887
SVN_ERR(svn_wc__db_fetch_repos_info(NULL, &repos_uuid, wcroot->sdb,
11343
SVN_ERR(svn_wc__db_fetch_repos_info(NULL, &repos_uuid, wcroot,
10888
11344
old_repos_id, scratch_pool));
10889
SVN_ERR_ASSERT(repos_uuid);
11345
SVN_ERR_ASSERT(repos_uuid); /* This function affects all the children of the given local_relpath,
11346
but the way that it does this is through the repos inheritance mechanism.
11347
So, we only need to rewrite the repos_id of the given local_relpath,
11348
as well as any children with a non-null repos_id, as well as various
11349
repos_id fields in the locks and working_node tables.
11352
/* Get the repos_id for the new repository. */
11353
SVN_ERR(create_repos_id(&new_repos_id, repos_root_url, repos_uuid,
11354
wcroot->sdb, scratch_pool));
11356
/* Set the (base and working) repos_ids and clear the dav_caches */
11357
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
11358
STMT_RECURSIVE_UPDATE_NODE_REPO));
11359
SVN_ERR(svn_sqlite__bindf(stmt, "isii", wcroot->wc_id, local_relpath,
11360
old_repos_id, new_repos_id));
11361
SVN_ERR(svn_sqlite__step_done(stmt));
11363
if (have_base_node)
11365
/* Update any locks for the root or its children. */
11366
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
11367
STMT_UPDATE_LOCK_REPOS_ID));
11368
SVN_ERR(svn_sqlite__bindf(stmt, "ii", old_repos_id, new_repos_id));
11369
SVN_ERR(svn_sqlite__step_done(stmt));
11372
return SVN_NO_ERROR;
11377
svn_wc__db_global_relocate(svn_wc__db_t *db,
11378
const char *local_dir_abspath,
11379
const char *repos_root_url,
11380
apr_pool_t *scratch_pool)
11382
svn_wc__db_wcroot_t *wcroot;
11383
const char *local_relpath;
11385
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_dir_abspath));
11386
/* ### assert that we were passed a directory? */
11388
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
11389
db, local_dir_abspath, scratch_pool, scratch_pool));
11390
VERIFY_USABLE_WCROOT(wcroot);
10891
11392
SVN_WC__DB_WITH_TXN(
10892
relocate_txn(wcroot, local_relpath, repos_root_url, repos_uuid,
10893
have_base_node, old_repos_id, scratch_pool),
11393
relocate_txn(wcroot, local_relpath, repos_root_url, scratch_pool),
11396
SVN_ERR(flush_entries(wcroot, local_dir_abspath, svn_depth_infinity,
10896
11399
return SVN_NO_ERROR;
11654
12199
iterpool = svn_pool_create(scratch_pool);
11656
SVN_ERR(gather_repo_children(&children, wcroot, local_relpath, 0,
11657
scratch_pool, iterpool));
11658
for (i = 0; i < children->nelts; i++)
12201
SVN_ERR(base_get_children_info(&children, wcroot, local_relpath, 0,
12202
scratch_pool, iterpool));
12203
for (hi = apr_hash_first(scratch_pool, children); hi; hi = apr_hash_next(hi))
11660
const char *child_basename = APR_ARRAY_IDX(children, i, const char *);
12205
const char *child_basename = apr_hash_this_key(hi);
12206
const struct svn_wc__db_base_info_t *child_info;
11661
12207
const char *child_local_relpath;
11662
12208
const char *child_repos_relpath = NULL;
11664
12210
svn_pool_clear(iterpool);
12212
child_info = apr_hash_this_val(hi);
12214
if (child_info->update_root && child_info->kind == svn_node_file)
12215
continue; /* Skip file externals */
12217
if (depth < svn_depth_immediates && child_info->kind == svn_node_dir)
12218
continue; /* Skip directories */
12220
child_local_relpath = svn_relpath_join(local_relpath, child_basename,
12223
/* Don't touch nodes that can't be touched via the exclude list */
12224
if (svn_hash_gets(exclude_relpaths, child_local_relpath))
12227
/* If the node is still marked 'not-present', then the server did not
12228
re-add it. So it's really gone in this revision, thus we remove the
12231
If the node is still marked 'server-excluded' and yet is not the same
12232
revision as new_rev, then the server did not re-add it, nor
12233
re-server-exclude it, so we can remove the node. */
12234
if (child_info->status == svn_wc__db_status_not_present
12235
|| (child_info->status == svn_wc__db_status_server_excluded &&
12236
child_info->revnum != new_rev))
12238
svn_sqlite__stmt_t *stmt;
12239
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
12240
STMT_DELETE_BASE_NODE));
12241
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, child_local_relpath));
12242
SVN_ERR(svn_sqlite__step_done(stmt));
11666
12246
/* Derive the new URL for the current (child) entry */
11667
12247
if (new_repos_relpath)
11668
12248
child_repos_relpath = svn_relpath_join(new_repos_relpath,
11669
12249
child_basename, iterpool);
11671
child_local_relpath = svn_relpath_join(local_relpath, child_basename,
11674
SVN_ERR(bump_node_revision(wcroot, child_local_relpath, new_repos_id,
12251
SVN_ERR(bump_node_revision(wcroot, child_local_relpath,
12252
child_info->status,
12254
child_info->revnum,
12255
child_info->repos_relpath,
11675
12257
child_repos_relpath, new_rev,
11676
12258
depth_below_here,
11677
12259
exclude_relpaths, wcroot_iprops,
12661
13154
sizeof(struct svn_wc__db_moved_to_t *));
12663
13156
/* ### Wrap in a transaction */
12664
SVN_ERR(follow_moved_to(moved_tos, 0, NULL, SVN_INVALID_REVNUM,
12665
wcroot, local_relpath,
12666
result_pool, scratch_pool));
13157
SVN_WC__DB_WITH_TXN(follow_moved_to(wcroot, local_relpath, 0, moved_tos,
13158
result_pool, scratch_pool),
12668
13161
/* ### Convert moved_to to abspath */
12670
13163
return SVN_NO_ERROR;
12673
/* Extract the moved-to information for LOCAL_RELPATH at OP-DEPTH by
12674
examining the lowest working node above OP_DEPTH. The output paths
12675
are NULL if there is no move, otherwise:
12677
*MOVE_DST_RELPATH: the moved-to destination of LOCAL_RELPATH.
12679
*MOVE_DST_OP_ROOT_RELPATH: the moved-to destination of the root of
12680
the move of LOCAL_RELPATH. This may be equal to *MOVE_DST_RELPATH
12681
if LOCAL_RELPATH is the root of the move.
12683
*MOVE_SRC_ROOT_RELPATH: the root of the move source. For moves
12684
inside a delete this will be different from *MOVE_SRC_OP_ROOT_RELPATH.
12686
*MOVE_SRC_OP_ROOT_RELPATH: the root of the source layer that
12687
contains the move. For moves inside deletes this is the root of
12688
the delete, for other moves this is the root of the move.
12690
Given a path A/B/C with A/B moved to X then for A/B/C
12692
MOVE_DST_RELPATH is X/C
12693
MOVE_DST_OP_ROOT_RELPATH is X
12694
MOVE_SRC_ROOT_RELPATH is A/B
12695
MOVE_SRC_OP_ROOT_RELPATH is A/B
12697
If A is then deleted the MOVE_DST_RELPATH, MOVE_DST_OP_ROOT_RELPATH
12698
and MOVE_SRC_ROOT_RELPATH remain the same but MOVE_SRC_OP_ROOT_RELPATH
12701
### Think about combining with scan_deletion? Also with
12702
### scan_addition to get moved-to for replaces? Do we need to
12703
### return the op-root of the move source, i.e. A/B in the example
12705
13166
svn_error_t *
12706
svn_wc__db_op_depth_moved_to(const char **move_dst_relpath,
12707
const char **move_dst_op_root_relpath,
12708
const char **move_src_root_relpath,
12709
const char **move_src_op_root_relpath,
12711
svn_wc__db_wcroot_t *wcroot,
12712
const char *local_relpath,
12713
apr_pool_t *result_pool,
12714
apr_pool_t *scratch_pool)
13167
svn_wc__db_scan_moved_to_internal(const char **move_src_relpath,
13168
const char **move_dst_relpath,
13169
const char **delete_relpath,
13170
svn_wc__db_wcroot_t *wcroot,
13171
const char *local_relpath,
13173
apr_pool_t *result_pool,
13174
apr_pool_t *scratch_pool)
12716
13176
svn_sqlite__stmt_t *stmt;
12717
13177
svn_boolean_t have_row;
12718
13178
int delete_op_depth;
12719
13179
const char *relpath = local_relpath;
12721
*move_dst_relpath = *move_dst_op_root_relpath = NULL;
12722
*move_src_root_relpath = *move_src_op_root_relpath = NULL;
13180
const char *dst_relpath;
13182
SVN_ERR_ASSERT(local_relpath[0]); /* Not valid on the WC root */
13184
if (move_src_relpath)
13185
*move_src_relpath = NULL;
13186
if (move_dst_relpath)
13187
*move_dst_relpath = NULL;
13188
if (delete_relpath)
13189
*delete_relpath = NULL;
13191
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
13192
STMT_SELECT_OP_DEPTH_MOVED_TO));
13193
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath, op_depth));
13195
SVN_ERR(svn_sqlite__step(&have_row, stmt));
13199
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
13200
svn_sqlite__reset(stmt),
13201
_("Node '%s' is not shadowed"),
13202
path_for_error_message(wcroot, local_relpath,
13206
delete_op_depth = svn_sqlite__column_int(stmt, 0);
13207
dst_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
13209
SVN_ERR(svn_sqlite__reset(stmt));
13211
while (!dst_relpath && have_row)
13213
relpath = svn_relpath_dirname(relpath, scratch_pool);
13215
if (relpath_depth(relpath) < delete_op_depth)
12726
13218
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
12727
STMT_SELECT_LOWEST_WORKING_NODE));
12728
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath, op_depth));
13219
STMT_SELECT_DEPTH_NODE));
13220
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, relpath,
12729
13223
SVN_ERR(svn_sqlite__step(&have_row, stmt));
12730
13225
if (have_row)
12732
delete_op_depth = svn_sqlite__column_int(stmt, 0);
12733
*move_dst_op_root_relpath = svn_sqlite__column_text(stmt, 3,
12735
if (*move_dst_op_root_relpath)
12736
*move_src_root_relpath = apr_pstrdup(result_pool, relpath);
13226
dst_relpath = svn_sqlite__column_text(stmt, 13, scratch_pool);
12738
13228
SVN_ERR(svn_sqlite__reset(stmt));
12739
if (!*move_dst_op_root_relpath)
12740
relpath = svn_relpath_dirname(relpath, scratch_pool);
12742
while (!*move_dst_op_root_relpath
12743
&& have_row && delete_op_depth <= relpath_depth(relpath));
12745
if (*move_dst_op_root_relpath)
12748
= svn_relpath_join(*move_dst_op_root_relpath,
12749
svn_relpath_skip_ancestor(relpath, local_relpath),
12751
while (delete_op_depth < relpath_depth(relpath))
12752
relpath = svn_relpath_dirname(relpath, scratch_pool);
12753
*move_src_op_root_relpath = apr_pstrdup(result_pool, relpath);
13233
if (move_src_relpath)
13234
*move_src_relpath = apr_pstrdup(result_pool, relpath);
13236
if (move_dst_relpath)
13237
*move_dst_relpath = apr_pstrdup(result_pool, dst_relpath);
13239
if (delete_relpath)
13240
*delete_relpath = svn_relpath_prefix(local_relpath, delete_op_depth,
12756
13244
return SVN_NO_ERROR;
12850
13345
return SVN_NO_ERROR;
12855
svn_wc__db_upgrade_apply_dav_cache(svn_sqlite__db_t *sdb,
12856
const char *dir_relpath,
12857
apr_hash_t *cache_values,
12858
apr_pool_t *scratch_pool)
12860
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
12862
apr_hash_index_t *hi;
12863
svn_sqlite__stmt_t *stmt;
12865
SVN_ERR(svn_wc__db_util_fetch_wc_id(&wc_id, sdb, iterpool));
12867
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
12868
STMT_UPDATE_BASE_NODE_DAV_CACHE));
12870
/* Iterate over all the wcprops, writing each one to the wc_db. */
12871
for (hi = apr_hash_first(scratch_pool, cache_values);
12873
hi = apr_hash_next(hi))
12875
const char *name = svn__apr_hash_index_key(hi);
12876
apr_hash_t *props = svn__apr_hash_index_val(hi);
12877
const char *local_relpath;
12879
svn_pool_clear(iterpool);
12881
local_relpath = svn_relpath_join(dir_relpath, name, iterpool);
12883
SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
12884
SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, iterpool));
12885
SVN_ERR(svn_sqlite__step_done(stmt));
12888
svn_pool_destroy(iterpool);
12890
return SVN_NO_ERROR;
12895
svn_wc__db_upgrade_apply_props(svn_sqlite__db_t *sdb,
12896
const char *dir_abspath,
12897
const char *local_relpath,
12898
apr_hash_t *base_props,
12899
apr_hash_t *revert_props,
12900
apr_hash_t *working_props,
12901
int original_format,
12903
apr_pool_t *scratch_pool)
12905
svn_sqlite__stmt_t *stmt;
12906
svn_boolean_t have_row;
12907
int top_op_depth = -1;
12908
int below_op_depth = -1;
12909
svn_wc__db_status_t top_presence;
12910
svn_wc__db_status_t below_presence;
12913
/* ### working_props: use set_props_txn.
12914
### if working_props == NULL, then skip. what if they equal the
12915
### pristine props? we should probably do the compare here.
12917
### base props go into WORKING_NODE if avail, otherwise BASE.
12919
### revert only goes into BASE. (and WORKING better be there!)
12921
Prior to 1.4.0 (ORIGINAL_FORMAT < 8), REVERT_PROPS did not exist. If a
12922
file was deleted, then a copy (potentially with props) was disallowed
12923
and could not replace the deletion. An addition *could* be performed,
12924
but that would never bring its own props.
12926
1.4.0 through 1.4.5 created the concept of REVERT_PROPS, but had a
12927
bug in svn_wc_add_repos_file2() whereby a copy-with-props did NOT
12928
construct a REVERT_PROPS if the target had no props. Thus, reverting
12929
the delete/copy would see no REVERT_PROPS to restore, leaving the
12930
props from the copy source intact, and appearing as if they are (now)
12931
the base props for the previously-deleted file. (wc corruption)
12933
1.4.6 ensured that an empty REVERT_PROPS would be established at all
12934
times. See issue 2530, and r861670 as starting points.
12936
We will use ORIGINAL_FORMAT and SVN_WC__NO_REVERT_FILES to determine
12937
the handling of our inputs, relative to the state of this node.
12940
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_NODE_INFO));
12941
SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
12942
SVN_ERR(svn_sqlite__step(&have_row, stmt));
12945
top_op_depth = svn_sqlite__column_int(stmt, 0);
12946
top_presence = svn_sqlite__column_token(stmt, 3, presence_map);
12947
SVN_ERR(svn_sqlite__step(&have_row, stmt));
12950
below_op_depth = svn_sqlite__column_int(stmt, 0);
12951
below_presence = svn_sqlite__column_token(stmt, 3, presence_map);
12954
SVN_ERR(svn_sqlite__reset(stmt));
12956
/* Detect the buggy scenario described above. We cannot upgrade this
12957
working copy if we have no idea where BASE_PROPS should go. */
12958
if (original_format > SVN_WC__NO_REVERT_FILES
12959
&& revert_props == NULL
12960
&& top_op_depth != -1
12961
&& top_presence == svn_wc__db_status_normal
12962
&& below_op_depth != -1
12963
&& below_presence != svn_wc__db_status_not_present)
12965
/* There should be REVERT_PROPS, so it appears that we just ran into
12966
the described bug. Sigh. */
12967
return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
12968
_("The properties of '%s' are in an "
12969
"indeterminate state and cannot be "
12970
"upgraded. See issue #2530."),
12971
svn_dirent_local_style(
12972
svn_dirent_join(dir_abspath, local_relpath,
12973
scratch_pool), scratch_pool));
12976
/* Need at least one row, or two rows if there are revert props */
12977
if (top_op_depth == -1
12978
|| (below_op_depth == -1 && revert_props))
12979
return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
12980
_("Insufficient NODES rows for '%s'"),
12981
svn_dirent_local_style(
12982
svn_dirent_join(dir_abspath, local_relpath,
12983
scratch_pool), scratch_pool));
12985
/* one row, base props only: upper row gets base props
12986
two rows, base props only: lower row gets base props
12987
two rows, revert props only: lower row gets revert props
12988
two rows, base and revert props: upper row gets base, lower gets revert */
12991
if (revert_props || below_op_depth == -1)
12993
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
12994
STMT_UPDATE_NODE_PROPS));
12995
SVN_ERR(svn_sqlite__bindf(stmt, "isd",
12996
wc_id, local_relpath, top_op_depth));
12997
SVN_ERR(svn_sqlite__bind_properties(stmt, 4, base_props, scratch_pool));
12998
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
13000
SVN_ERR_ASSERT(affected_rows == 1);
13003
if (below_op_depth != -1)
13005
apr_hash_t *props = revert_props ? revert_props : base_props;
13007
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
13008
STMT_UPDATE_NODE_PROPS));
13009
SVN_ERR(svn_sqlite__bindf(stmt, "isd",
13010
wc_id, local_relpath, below_op_depth));
13011
SVN_ERR(svn_sqlite__bind_properties(stmt, 4, props, scratch_pool));
13012
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
13014
SVN_ERR_ASSERT(affected_rows == 1);
13017
/* If there are WORKING_PROPS, then they always go into ACTUAL_NODE. */
13018
if (working_props != NULL
13019
&& base_props != NULL)
13021
apr_array_header_t *diffs;
13023
SVN_ERR(svn_prop_diffs(&diffs, working_props, base_props, scratch_pool));
13025
if (diffs->nelts == 0)
13026
working_props = NULL; /* No differences */
13029
if (working_props != NULL)
13031
SVN_ERR(set_actual_props(wc_id, local_relpath, working_props,
13032
sdb, scratch_pool));
13035
return SVN_NO_ERROR;
13038
13348
svn_error_t *
13039
13349
svn_wc__db_upgrade_insert_external(svn_wc__db_t *db,
13040
13350
const char *local_abspath,
13682
13988
SVN_ERR(svn_sqlite__step(&have_row, stmt));
13686
/* Do this while stmt is still open to avoid closing the sqlite
13687
transaction and then reopening. */
13688
svn_sqlite__stmt_t *stmt_node;
13691
err = svn_sqlite__get_statement(&stmt_node, wcroot->sdb,
13692
STMT_SELECT_NODE_INFO);
13992
apr_size_t cfl_len;
13993
const void *cfl_data;
13995
/* svn_skel__parse doesn't copy data, so store in result_pool */
13996
cfl_data = svn_sqlite__column_blob(stmt, 2, &cfl_len, result_pool);
13999
*conflict = svn_skel__parse(cfl_data, cfl_len, result_pool);
13697
err = svn_sqlite__bindf(stmt_node, "is", wcroot->wc_id,
13701
err = svn_sqlite__step(&have_row, stmt_node);
13704
err = svn_error_compose_create(err,
13705
svn_sqlite__reset(stmt_node));
14007
err = svn_error_trace(svn_sqlite__column_properties(props, stmt, 1,
14012
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
14018
SVN_ERR(svn_sqlite__reset(stmt));
14020
if (!have_row || kind || (props && !*props))
14022
svn_error_t *err = NULL;
14023
svn_boolean_t have_info = FALSE;
14025
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
14026
STMT_SELECT_NODE_INFO));
14028
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
14031
SVN_ERR(svn_sqlite__step(&have_info, stmt));
14037
svn_wc__db_status_t status;
14038
int op_depth = svn_sqlite__column_int(stmt, 0);
14040
status = svn_sqlite__column_token(stmt, 3, presence_map);
14043
err = convert_to_working_status(&status, status);
14045
if (!err && (status == svn_wc__db_status_normal
14046
|| status == svn_wc__db_status_added
14047
|| status == svn_wc__db_status_deleted
14048
|| status == svn_wc__db_status_incomplete))
14050
*kind = svn_sqlite__column_token(stmt, 4, kind_map);
14054
/* Need props, and no props in ACTUAL? */
14055
if (!err && (props && !*props))
14057
err = svn_sqlite__column_properties(props, stmt, 14,
14058
result_pool, scratch_pool);
13707
14062
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
14064
if (!have_row && !have_info)
13712
return SVN_NO_ERROR;
13715
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
13716
_("The node '%s' was not found."),
14066
return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
14067
_("The node '%s' was not found."),
13717
14068
path_for_error_message(wcroot,
13718
14069
local_relpath,
13719
14070
scratch_pool));
13723
apr_size_t cfl_len;
13724
const void *cfl_data;
13726
/* svn_skel__parse doesn't copy data, so store in result_pool */
13727
cfl_data = svn_sqlite__column_blob(stmt, 2, &cfl_len, result_pool);
13730
*conflict = svn_skel__parse(cfl_data, cfl_len, result_pool);
13734
return svn_error_trace(svn_sqlite__reset(stmt));
14074
return SVN_NO_ERROR;
14666
15075
static svn_error_t *
14667
15076
make_copy_txn(svn_wc__db_wcroot_t *wcroot,
14668
15077
const char *local_relpath,
14670
const svn_skel_t *conflicts,
14671
const svn_skel_t *work_items,
15078
apr_int64_t last_repos_id,
15079
const char *last_repos_relpath,
15080
svn_revnum_t last_revision,
15082
svn_boolean_t shadowed,
15083
int root_shadow_depth,
14672
15084
apr_pool_t *scratch_pool)
14674
15086
svn_sqlite__stmt_t *stmt;
15087
svn_boolean_t have_row = FALSE;
15088
svn_revnum_t revision;
15089
apr_int64_t repos_id;
15090
const char *repos_relpath;
15091
svn_node_kind_t kind;
15092
int op_depth = relpath_depth(local_relpath);
15094
if (last_op_depth != op_depth)
15096
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
15097
STMT_SELECT_DEPTH_NODE));
15098
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
15100
SVN_ERR(svn_sqlite__step(&have_row, stmt));
15101
SVN_ERR(svn_sqlite__reset(stmt));
15106
SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &kind, &revision,
15107
&repos_relpath, &repos_id, NULL,
15108
NULL, NULL, NULL, NULL, NULL, NULL,
15110
wcroot, local_relpath,
15111
scratch_pool, scratch_pool));
15113
if (last_repos_relpath
15114
&& repos_id == last_repos_id
15115
&& revision == last_revision)
15117
const char *name = svn_relpath_skip_ancestor(last_repos_relpath,
15120
if (strcmp(name, svn_relpath_basename(local_relpath, NULL)) == 0)
15121
op_depth = last_op_depth;
15124
/* Can we add a new copy node at the wanted op-depth? */
15125
if (!have_row || op_depth == last_op_depth)
15129
SVN_ERR(svn_sqlite__get_statement(
15130
&stmt, wcroot->sdb,
15131
STMT_INSERT_WORKING_NODE_FROM_BASE_COPY));
15132
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
15134
SVN_ERR(svn_sqlite__step_done(stmt));
15137
SVN_ERR(db_extend_parent_delete(wcroot, local_relpath, kind,
15138
op_depth, scratch_pool));
15140
if (kind == svn_node_dir)
15142
const apr_array_header_t *children;
15143
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
15145
SVN_ERR(gather_children(&children, wcroot, local_relpath,
15146
STMT_SELECT_OP_DEPTH_CHILDREN, 0,
15147
scratch_pool, iterpool));
15149
for (i = 0; i < children->nelts; i++)
15151
const char *name = APR_ARRAY_IDX(children, i, const char *);
15152
const char *copy_relpath;
15154
svn_pool_clear(iterpool);
15156
copy_relpath = svn_relpath_join(local_relpath, name, iterpool);
15158
SVN_ERR(make_copy_txn(wcroot, copy_relpath,
15159
repos_id, repos_relpath, revision,
15160
op_depth, shadowed, root_shadow_depth,
15163
svn_pool_destroy(iterpool);
15168
/* Auch... we can't make a copy of whatever comes deeper, as this
15169
op-depth is already filled by something else. Let's hope
15170
the user doesn't mind.
15172
Luckily we know that the moves are already moved to the shadowing
15173
layer, so we can just remove dangling base-deletes if there are
15176
/* BASE_DELETED may be at op_depth, so let's use last_op_depth! */
15177
SVN_ERR(db_move_moved_to_down_recursive(wcroot, local_relpath,
15181
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
15182
STMT_DELETE_WORKING_BASE_DELETE));
15183
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
15185
SVN_ERR(svn_sqlite__step_done(stmt));
15186
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
15187
STMT_DELETE_WORKING_BASE_DELETE_RECURSIVE));
15188
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
15190
SVN_ERR(svn_sqlite__step_done(stmt));
15193
/* Insert a not-present node to mark that we don't know what exists here.
15195
We do this last (after recursing), to allow the move fix-up code to
15196
see the original moves. */
15197
if (last_op_depth > 0 && last_op_depth != op_depth)
15199
insert_working_baton_t iwb;
15202
iwb.presence = svn_wc__db_status_not_present;
15203
iwb.op_depth = last_op_depth;
15205
iwb.original_repos_id = repos_id;
15206
iwb.original_repos_relpath = repos_relpath;
15207
iwb.original_revnum = revision;
15210
SVN_ERR(insert_working_node(&iwb, wcroot, local_relpath, scratch_pool));
15213
return SVN_NO_ERROR;
15218
svn_wc__db_op_make_copy_internal(svn_wc__db_wcroot_t *wcroot,
15219
const char *local_relpath,
15220
svn_boolean_t move_move_info,
15221
const svn_skel_t *conflicts,
15222
const svn_skel_t *work_items,
15223
apr_pool_t *scratch_pool)
15225
svn_sqlite__stmt_t *stmt;
14675
15226
svn_boolean_t have_row;
14676
svn_boolean_t add_working_base_deleted = FALSE;
14677
svn_boolean_t remove_working = FALSE;
14678
const apr_array_header_t *children;
14679
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
15229
/* The update editor is supposed to call this function when there is
15230
no working node for LOCAL_ABSPATH. */
14682
15231
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
14683
STMT_SELECT_LOWEST_WORKING_NODE));
14684
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, 0));
15232
STMT_SELECT_WORKING_NODE));
15233
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
14685
15234
SVN_ERR(svn_sqlite__step(&have_row, stmt));
14689
svn_wc__db_status_t working_status;
14690
int working_op_depth;
14692
working_status = svn_sqlite__column_token(stmt, 1, presence_map);
14693
working_op_depth = svn_sqlite__column_int(stmt, 0);
14694
SVN_ERR(svn_sqlite__reset(stmt));
14696
SVN_ERR_ASSERT(working_status == svn_wc__db_status_normal
14697
|| working_status == svn_wc__db_status_base_deleted
14698
|| working_status == svn_wc__db_status_not_present
14699
|| working_status == svn_wc__db_status_incomplete);
14701
/* Only change nodes in the layers where we are creating the copy.
14702
Deletes in higher layers will just apply to the copy */
14703
if (working_op_depth <= op_depth)
14705
add_working_base_deleted = TRUE;
14707
if (working_status == svn_wc__db_status_base_deleted)
14708
remove_working = TRUE;
14712
SVN_ERR(svn_sqlite__reset(stmt));
14714
if (remove_working)
14716
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
14717
STMT_DELETE_LOWEST_WORKING_NODE));
14718
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
14719
SVN_ERR(svn_sqlite__step_done(stmt));
14722
if (add_working_base_deleted)
14724
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
14725
STMT_INSERT_DELETE_FROM_BASE));
14726
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
14728
SVN_ERR(svn_sqlite__step_done(stmt));
14732
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
14733
STMT_INSERT_WORKING_NODE_FROM_BASE_COPY));
14734
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
14736
SVN_ERR(svn_sqlite__step_done(stmt));
14739
/* Get the BASE children, as WORKING children don't need modifications */
14740
SVN_ERR(gather_repo_children(&children, wcroot, local_relpath,
14741
0, scratch_pool, iterpool));
14743
for (i = 0; i < children->nelts; i++)
14745
const char *name = APR_ARRAY_IDX(children, i, const char *);
14746
const char *copy_relpath;
14748
svn_pool_clear(iterpool);
14750
copy_relpath = svn_relpath_join(local_relpath, name, iterpool);
14752
SVN_ERR(make_copy_txn(wcroot, copy_relpath, op_depth, NULL, NULL,
14756
SVN_ERR(flush_entries(wcroot, svn_dirent_join(wcroot->abspath, local_relpath,
14758
svn_depth_empty, iterpool));
15236
op_depth = svn_sqlite__column_int(stmt, 0);
15237
SVN_ERR(svn_sqlite__reset(stmt));
15241
if (op_depth == relpath_depth(local_relpath))
15242
return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
15243
_("Modification of '%s' already exists"),
15244
path_for_error_message(wcroot,
15248
/* We have a working layer, but not one at the op-depth of local-relpath,
15249
so we can create a copy by just copying the lower layer */
15251
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
15252
STMT_COPY_OP_DEPTH_RECURSIVE));
15253
SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id, local_relpath,
15254
op_depth, relpath_depth(local_relpath)));
15255
SVN_ERR(svn_sqlite__step_done(stmt));
15261
op_depth = relpath_depth(local_relpath);
15262
/* We don't allow copies to contain server-excluded nodes;
15263
the update editor is going to have to bail out. */
15264
SVN_ERR(catch_copy_of_server_excluded(wcroot, local_relpath,
15267
/* Insert a shadowing layer */
15268
SVN_ERR(svn_sqlite__get_statement(
15269
&stmt, wcroot->sdb,
15270
STMT_INSERT_DELETE_FROM_NODE_RECURSIVE));
15272
/* As we are keeping whatever is below, move the*/
15274
SVN_ERR(svn_sqlite__bindf(stmt, "isdd",
15275
wcroot->wc_id, local_relpath,
15277
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
15278
SVN_ERR_ASSERT(affected_rows > 0);
15280
if (!move_move_info)
15281
SVN_ERR(db_move_moved_to_down_recursive(wcroot, local_relpath,
15282
op_depth, scratch_pool));
15285
SVN_ERR(make_copy_txn(wcroot, local_relpath,
15286
INVALID_REPOS_ID, NULL, SVN_INVALID_REVNUM,
15287
op_depth, FALSE, op_depth,
14760
15291
if (conflicts)
14761
15292
SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
14762
conflicts, iterpool));
14764
SVN_ERR(add_work_items(wcroot->sdb, work_items, iterpool));
14766
svn_pool_destroy(iterpool);
15293
conflicts, scratch_pool));
15295
SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
14768
15297
return SVN_NO_ERROR;
15609
16072
return SVN_NO_ERROR;
16075
/* Item queued with svn_wc__db_commit_queue_add */
16076
typedef struct commit_queue_item_t
16078
const char *local_relpath;
16079
svn_boolean_t recurse; /* Use legacy recursion */
16080
svn_boolean_t committed; /* Process the node as committed */
16081
svn_boolean_t remove_lock; /* Remove existing lock on node */
16082
svn_boolean_t remove_changelist; /* Remove changelist on node */
16084
/* The pristine text checksum. NULL if the old value should be kept
16085
and for directories */
16086
const svn_checksum_t *new_sha1_checksum;
16088
apr_hash_t *new_dav_cache; /* New DAV cache for the node */
16089
} commit_queue_item_t;
16091
/* The queue definition for vn_wc__db_create_commit_queue,
16092
svn_wc__db_commit_queue_add and finally svn_wc__db_process_commit_queue */
16093
struct svn_wc__db_commit_queue_t
16095
svn_wc__db_wcroot_t *wcroot; /* Wcroot for ITEMS */
16096
apr_array_header_t *items; /* List of commit_queue_item_t* */
16097
svn_boolean_t have_recurse; /* Is one or more item[x]->recurse TRUE? */
16100
/* Create a new svn_wc__db_commit_queue_t instance in RESULT_POOL for the
16101
working copy specified with WRI_ABSPATH */
16103
svn_wc__db_create_commit_queue(svn_wc__db_commit_queue_t **queue,
16105
const char *wri_abspath,
16106
apr_pool_t *result_pool,
16107
apr_pool_t *scratch_pool)
16109
svn_wc__db_wcroot_t *wcroot;
16110
const char *local_relpath;
16111
svn_wc__db_commit_queue_t *q;
16113
SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
16115
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
16116
wri_abspath, result_pool, scratch_pool));
16117
VERIFY_USABLE_WCROOT(wcroot);
16119
q = apr_pcalloc(result_pool, sizeof(*q));
16121
SVN_ERR_ASSERT(wcroot->sdb);
16123
q->wcroot = wcroot;
16124
q->items = apr_array_make(result_pool, 64,
16125
sizeof(commit_queue_item_t*));
16126
q->have_recurse = FALSE;
16129
return SVN_NO_ERROR;
16133
svn_wc__db_commit_queue_add(svn_wc__db_commit_queue_t *queue,
16134
const char *local_abspath,
16135
svn_boolean_t recurse,
16136
svn_boolean_t is_commited,
16137
svn_boolean_t remove_lock,
16138
svn_boolean_t remove_changelist,
16139
const svn_checksum_t *new_sha1_checksum,
16140
apr_hash_t *new_dav_cache,
16141
apr_pool_t *result_pool,
16142
apr_pool_t *scratch_pool)
16144
commit_queue_item_t *cqi;
16145
const char *local_relpath;
16147
local_relpath = svn_dirent_skip_ancestor(queue->wcroot->abspath,
16150
if (! local_relpath)
16151
return svn_error_createf(
16152
SVN_ERR_WC_PATH_NOT_FOUND, NULL,
16153
_("The path '%s' is not in the working copy '%s'"),
16154
svn_dirent_local_style(local_abspath, scratch_pool),
16155
svn_dirent_local_style(queue->wcroot->abspath, scratch_pool));
16157
cqi = apr_pcalloc(result_pool, sizeof(*cqi));
16158
cqi->local_relpath = local_relpath;
16159
cqi->recurse = recurse;
16160
cqi->committed = is_commited;
16161
cqi->remove_lock = remove_lock;
16162
cqi->remove_changelist = remove_changelist;
16163
cqi->new_sha1_checksum = new_sha1_checksum;
16164
cqi->new_dav_cache = new_dav_cache;
16166
queue->have_recurse |= recurse;
16168
APR_ARRAY_PUSH(queue->items, commit_queue_item_t *) = cqi;
16169
return SVN_NO_ERROR;
16172
/*** Finishing updates and commits. ***/
16174
/* Post process an item that is committed in the repository. Collapse layers into
16175
* BASE. Queue work items that will finish a commit of the file or directory
16176
* LOCAL_ABSPATH in DB:
16178
static svn_error_t *
16179
process_committed_leaf(svn_wc__db_t *db,
16180
svn_wc__db_wcroot_t *wcroot,
16181
const char *local_relpath,
16182
svn_boolean_t via_recurse,
16183
svn_wc__db_status_t status,
16184
svn_node_kind_t kind,
16185
svn_boolean_t prop_mods,
16186
const svn_checksum_t *old_checksum,
16187
svn_revnum_t new_revnum,
16188
apr_time_t new_changed_date,
16189
const char *new_changed_author,
16190
apr_hash_t *new_dav_cache,
16191
svn_boolean_t remove_lock,
16192
svn_boolean_t remove_changelist,
16193
const svn_checksum_t *checksum,
16194
apr_pool_t *scratch_pool)
16196
svn_revnum_t new_changed_rev = new_revnum;
16197
svn_skel_t *work_item = NULL;
16200
const char *lock_relpath;
16201
svn_boolean_t locked;
16203
if (kind == svn_node_dir)
16204
lock_relpath = local_relpath;
16206
lock_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
16208
SVN_ERR(svn_wc__db_wclock_owns_lock_internal(&locked, wcroot,
16209
lock_relpath, FALSE,
16213
return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL,
16214
_("No write-lock in '%s'"),
16215
path_for_error_message(wcroot, local_relpath,
16218
SVN_ERR(flush_entries(wcroot, lock_relpath, svn_depth_empty,
16222
if (status == svn_wc__db_status_not_present)
16224
/* We are committing the leaf of a copy operation.
16225
We leave the not-present marker to allow pulling in excluded
16226
children of a copy.
16228
The next update will remove the not-present marker. */
16230
return SVN_NO_ERROR;
16233
SVN_ERR_ASSERT(status == svn_wc__db_status_normal
16234
|| status == svn_wc__db_status_incomplete
16235
|| status == svn_wc__db_status_added
16236
|| status == svn_wc__db_status_deleted);
16238
if (kind != svn_node_dir
16239
&& status != svn_wc__db_status_deleted)
16241
/* If we sent a delta (meaning: post-copy modification),
16242
then this file will appear in the queue and so we should have
16243
its checksum already. */
16244
if (checksum == NULL)
16246
/* It was copied and not modified. We must have a text
16247
base for it. And the node should have a checksum. */
16248
SVN_ERR_ASSERT(old_checksum != NULL);
16250
checksum = old_checksum;
16252
/* Is the node completely unmodified and are we recursing? */
16253
if (via_recurse && !prop_mods)
16255
/* If a copied node itself is not modified, but the op_root of
16256
the copy is committed we have to make sure that changed_rev,
16257
changed_date and changed_author don't change or the working
16258
copy used for committing will show different last modified
16259
information then a clean checkout of exactly the same
16260
revisions. (Issue #3676) */
16262
SVN_ERR(svn_wc__db_read_info_internal(
16263
NULL, NULL, NULL, NULL, NULL,
16266
&new_changed_author, NULL, NULL,
16267
NULL, NULL, NULL, NULL, NULL,
16268
NULL, NULL, NULL, NULL,
16269
NULL, NULL, NULL, NULL,
16271
wcroot, local_relpath,
16272
scratch_pool, scratch_pool));
16276
SVN_ERR(svn_wc__wq_build_file_commit(&work_item,
16277
db, svn_dirent_join(wcroot->abspath,
16281
scratch_pool, scratch_pool));
16284
/* The new text base will be found in the pristine store by its checksum. */
16285
SVN_ERR(commit_node(wcroot, local_relpath,
16286
new_revnum, new_changed_rev,
16287
new_changed_date, new_changed_author,
16290
!remove_changelist,
16295
return SVN_NO_ERROR;
16298
/** Internal helper for svn_wc_process_committed_queue2().
16299
* Bump a commit item, collapsing local changes with the new repository
16300
* information to a new BASE node.
16302
* @a new_date is the (server-side) date of the new revision, or 0.
16304
* @a rev_author is the (server-side) author of the new
16305
* revision; it may be @c NULL.
16307
* @a new_dav_cache is a hash of all the new dav properties for LOCAL_RELPATH.
16309
* If @a remove_lock is set, release any user locks on @a
16310
* local_abspath; otherwise keep them during processing.
16312
* If @a remove_changelist is set, clear any changeset assignments
16313
* from @a local_abspath; otherwise, keep such assignments.
16315
* If @a new_sha1_checksum is non-NULL, use it to identify the node's pristine
16318
* Set TOP_OF_RECURSE to TRUE to show that this the top of a possibly
16319
* recursive commit operation. (Part of the legacy recurse handling)
16321
static svn_error_t *
16322
process_committed_internal(svn_wc__db_t *db,
16323
svn_wc__db_wcroot_t *wcroot,
16324
const char *local_relpath,
16325
svn_boolean_t recurse,
16326
svn_boolean_t top_of_recurse,
16327
svn_revnum_t new_revnum,
16328
apr_time_t new_date,
16329
const char *rev_author,
16330
apr_hash_t *new_dav_cache,
16331
svn_boolean_t remove_lock,
16332
svn_boolean_t remove_changelist,
16333
const svn_checksum_t *new_sha1_checksum,
16334
apr_hash_t *items_by_relpath,
16335
apr_pool_t *scratch_pool)
16337
svn_wc__db_status_t status;
16338
svn_node_kind_t kind;
16339
const svn_checksum_t *old_checksum;
16340
svn_boolean_t prop_mods;
16342
SVN_ERR(svn_wc__db_read_info_internal(&status, &kind, NULL, NULL, NULL, NULL, NULL,
16343
NULL, NULL, &old_checksum, NULL, NULL,
16344
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
16345
NULL, &prop_mods, NULL, NULL, NULL,
16346
wcroot, local_relpath,
16347
scratch_pool, scratch_pool));
16349
/* NOTE: be wary of making crazy semantic changes in this function, since
16350
svn_wc_process_committed4() calls this. */
16352
SVN_ERR(process_committed_leaf(db, wcroot, local_relpath, !top_of_recurse,
16353
status, kind, prop_mods, old_checksum,
16354
new_revnum, new_date, rev_author,
16356
remove_lock, remove_changelist,
16360
/* Only check for recursion on nodes that have children */
16361
if (kind != svn_node_dir
16362
|| status == svn_wc__db_status_not_present
16363
|| status == svn_wc__db_status_excluded
16364
|| status == svn_wc__db_status_server_excluded
16365
/* Node deleted -> then no longer a directory */
16366
|| status == svn_wc__db_status_deleted)
16368
return SVN_NO_ERROR;
16373
const apr_array_header_t *children;
16374
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
16377
/* Read PATH's entries; this is the absolute path. */
16378
SVN_ERR(gather_children(&children, wcroot, local_relpath,
16379
STMT_SELECT_NODE_CHILDREN, -1,
16380
scratch_pool, iterpool));
16382
/* Recursively loop over all children. */
16383
for (i = 0; i < children->nelts; i++)
16385
const char *name = APR_ARRAY_IDX(children, i, const char *);
16386
const char *this_relpath;
16387
const commit_queue_item_t *cqi;
16389
svn_pool_clear(iterpool);
16391
this_relpath = svn_dirent_join(local_relpath, name, iterpool);
16393
new_sha1_checksum = NULL;
16394
cqi = svn_hash_gets(items_by_relpath, this_relpath);
16397
new_sha1_checksum = cqi->new_sha1_checksum;
16399
/* Recurse. Pass NULL for NEW_DAV_CACHE, because the
16400
ones present in the current call are only applicable to
16401
this one committed item. */
16402
SVN_ERR(process_committed_internal(
16403
db, wcroot, this_relpath,
16404
TRUE /* recurse */,
16405
FALSE /* top_of_recurse */,
16406
new_revnum, new_date,
16408
NULL /* new_dav_cache */,
16409
FALSE /* remove_lock */,
16416
svn_pool_destroy(iterpool);
16419
return SVN_NO_ERROR;
16422
/* Return TRUE if any item of QUEUE is a parent of ITEM and will be
16423
processed recursively, return FALSE otherwise.
16425
The algorithmic complexity of this search implementation is O(queue
16426
length), but it's quite quick.
16428
static svn_boolean_t
16429
have_recursive_parent(const apr_array_header_t *all_items,
16430
const commit_queue_item_t *item,
16431
apr_pool_t *scratch_pool)
16433
const char *local_relpath = item->local_relpath;
16436
for (i = 0; i < all_items->nelts; i++)
16438
const commit_queue_item_t *qi
16439
= APR_ARRAY_IDX(all_items, i, const commit_queue_item_t *);
16444
if (qi->recurse && svn_relpath_skip_ancestor(qi->local_relpath,
16454
/* Compare function for svn_sort__array */
16456
compare_queue_items(const void *v1,
16459
const commit_queue_item_t *cqi1
16460
= *(const commit_queue_item_t **)v1;
16461
const commit_queue_item_t *cqi2
16462
= *(const commit_queue_item_t **)v2;
16464
return svn_path_compare_paths(cqi1->local_relpath, cqi2->local_relpath);
16467
/* Internal, locked version of svn_wc__db_process_commit_queue */
16468
static svn_error_t *
16469
db_process_commit_queue(svn_wc__db_t *db,
16470
svn_wc__db_commit_queue_t *queue,
16471
svn_revnum_t new_revnum,
16472
apr_time_t new_date,
16473
const char *new_author,
16474
apr_pool_t *scratch_pool)
16476
apr_hash_t *items_by_relpath = NULL;
16478
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
16480
svn_sort__array(queue->items, compare_queue_items);
16482
if (queue->have_recurse)
16484
items_by_relpath = apr_hash_make(scratch_pool);
16486
for (j = 0; j < queue->items->nelts; j++)
16488
commit_queue_item_t *cqi
16489
= APR_ARRAY_IDX(queue->items, j, commit_queue_item_t *);
16491
svn_hash_sets(items_by_relpath, cqi->local_relpath, cqi);
16495
for (j = 0; j < queue->items->nelts; j++)
16497
commit_queue_item_t *cqi
16498
= APR_ARRAY_IDX(queue->items, j, commit_queue_item_t *);
16500
svn_pool_clear(iterpool);
16502
/* Skip this item if it is a child of a recursive item, because it has
16503
been (or will be) accounted for when that recursive item was (or
16504
will be) processed. */
16505
if (queue->have_recurse && have_recursive_parent(queue->items, cqi,
16509
if (!cqi->committed)
16511
if (cqi->remove_lock)
16513
svn_skel_t *work_item;
16515
SVN_ERR(svn_wc__wq_build_sync_file_flags(
16519
queue->wcroot->abspath,
16520
cqi->local_relpath,
16522
iterpool, iterpool));
16524
lock_remove_txn(queue->wcroot, cqi->local_relpath, work_item,
16527
if (cqi->remove_changelist)
16528
SVN_ERR(svn_wc__db_op_set_changelist(db,
16530
queue->wcroot->abspath,
16531
cqi->local_relpath,
16535
NULL, NULL, /* notify */
16536
NULL, NULL, /* cancel */
16541
SVN_ERR(process_committed_internal(
16542
db, queue->wcroot, cqi->local_relpath,
16544
TRUE /* top_of_recurse */,
16545
new_revnum, new_date, new_author,
16546
cqi->new_dav_cache,
16548
cqi->remove_changelist,
16549
cqi->new_sha1_checksum,
16555
svn_pool_destroy(iterpool);
16557
return SVN_NO_ERROR;
16561
svn_wc__db_process_commit_queue(svn_wc__db_t *db,
16562
svn_wc__db_commit_queue_t *queue,
16563
svn_revnum_t new_revnum,
16564
apr_time_t new_date,
16565
const char *new_author,
16566
apr_pool_t *scratch_pool)
16568
SVN_WC__DB_WITH_TXN(db_process_commit_queue(db, queue,
16569
new_revnum, new_date,
16570
new_author, scratch_pool),
16573
return SVN_NO_ERROR;