Modified: subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c?rev=1658128&r1=1658127&r2=1658128&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c Sun Feb 8 03:10:25 2015 @@ -152,18 +152,29 @@ verify_write_lock(svn_wc__db_wcroot_t *w typedef struct update_move_baton_t { svn_wc__db_t *db; svn_wc__db_wcroot_t *wcroot; - const char *move_root_dst_relpath; - /* The most recent conflict raised during this drive. We rely on the - non-Ev2, depth-first, drive for this to make sense. */ - const char *conflict_root_relpath; + int src_op_depth; + int dst_op_depth; svn_wc_operation_t operation; svn_wc_conflict_version_t *old_version; svn_wc_conflict_version_t *new_version; - apr_pool_t *result_pool; /* For things that live as long as the baton. */ } update_move_baton_t; +/* Per node flags for tree conflict collection */ +typedef struct node_move_baton_t +{ + svn_boolean_t skip; + svn_boolean_t shadowed; + svn_boolean_t edited; + + const char *src_relpath; + const char *dst_relpath; + + update_move_baton_t *umb; + struct node_move_baton_t *pb; +} node_move_baton_t; + /* * Notifications are delayed until the entire update-move transaction * completes. These functions provide the necessary support by storing @@ -171,24 +182,41 @@ typedef struct update_move_baton_t { * and spooling notifications out of that table after the transaction. */ -/* Add an entry to the notification list. */ +/* Add an entry to the notification list, and at the same time install + a conflict and/or work items. */ static svn_error_t * update_move_list_add(svn_wc__db_wcroot_t *wcroot, const char *local_relpath, svn_wc_notify_action_t action, svn_node_kind_t kind, svn_wc_notify_state_t content_state, - svn_wc_notify_state_t prop_state) - + svn_wc_notify_state_t prop_state, + svn_skel_t *conflict, + svn_skel_t *work_item, + apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; + if (conflict) + { + action = svn_wc_notify_tree_conflict; + content_state = svn_wc_notify_state_inapplicable; + prop_state = svn_wc_notify_state_inapplicable; + } + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_INSERT_UPDATE_MOVE_LIST)); SVN_ERR(svn_sqlite__bindf(stmt, "sdddd", local_relpath, action, kind, content_state, prop_state)); SVN_ERR(svn_sqlite__step_done(stmt)); + if (conflict) + SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath, conflict, + scratch_pool)); + + if (work_item) + SVN_ERR(svn_wc__db_wq_add_internal(wcroot, work_item, scratch_pool)); + return SVN_NO_ERROR; } @@ -248,23 +276,25 @@ svn_wc__db_update_move_list_notify(svn_w return SVN_NO_ERROR; } -/* Mark a tree-conflict on LOCAL_RELPATH if such a tree-conflict does - not already exist. */ +/* Create a tree-conflict for recording on LOCAL_RELPATH if such + a tree-conflict does not already exist. */ static svn_error_t * -mark_tree_conflict(const char *local_relpath, - svn_wc__db_wcroot_t *wcroot, - svn_wc__db_t *db, - const svn_wc_conflict_version_t *old_version, - const svn_wc_conflict_version_t *new_version, - const char *move_root_dst_relpath, - svn_wc_operation_t operation, - svn_node_kind_t old_kind, - svn_node_kind_t new_kind, - const char *old_repos_relpath, - svn_wc_conflict_reason_t reason, - svn_wc_conflict_action_t action, - const char *move_src_op_root_relpath, - apr_pool_t *scratch_pool) +create_tree_conflict(svn_skel_t **conflict_p, + svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + const char *dst_op_root_relpath, + svn_wc__db_t *db, + const svn_wc_conflict_version_t *old_version, + const svn_wc_conflict_version_t *new_version, + svn_wc_operation_t operation, + svn_node_kind_t old_kind, + svn_node_kind_t new_kind, + const char *old_repos_relpath, + svn_wc_conflict_reason_t reason, + svn_wc_conflict_action_t action, + const char *move_src_op_root_relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_error_t *err; svn_skel_t *conflict; @@ -288,7 +318,7 @@ mark_tree_conflict(const char *local_rel if (!new_repos_relpath) { const char *child_relpath = svn_relpath_skip_ancestor( - move_root_dst_relpath, + dst_op_root_relpath, local_relpath); SVN_ERR_ASSERT(child_relpath != NULL); new_repos_relpath = svn_relpath_join(new_version->path_in_repos, @@ -296,7 +326,7 @@ mark_tree_conflict(const char *local_rel } err = svn_wc__db_read_conflict_internal(&conflict, wcroot, local_relpath, - scratch_pool, scratch_pool); + result_pool, scratch_pool); if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND) return svn_error_trace(err); else if (err) @@ -348,11 +378,12 @@ mark_tree_conflict(const char *local_rel scratch_pool)); /* Already a suitable tree-conflict. */ + *conflict_p = conflict; return SVN_NO_ERROR; } } else - conflict = svn_wc__conflict_skel_create(scratch_pool); + conflict = svn_wc__conflict_skel_create(result_pool); SVN_ERR(svn_wc__conflict_skel_add_tree_conflict( conflict, db, @@ -361,7 +392,7 @@ mark_tree_conflict(const char *local_rel reason, action, move_src_op_root_abspath, - scratch_pool, + result_pool, scratch_pool)); if (reason != svn_wc_conflict_reason_unversioned @@ -384,53 +415,71 @@ mark_tree_conflict(const char *local_rel { SVN_ERR(svn_wc__conflict_skel_set_op_update( conflict, conflict_old_version, conflict_new_version, - scratch_pool, scratch_pool)); + result_pool, scratch_pool)); } else { assert(operation == svn_wc_operation_switch); SVN_ERR(svn_wc__conflict_skel_set_op_switch( conflict, conflict_old_version, conflict_new_version, - scratch_pool, scratch_pool)); + result_pool, scratch_pool)); } - SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath, - conflict, scratch_pool)); - - SVN_ERR(update_move_list_add(wcroot, local_relpath, - svn_wc_notify_tree_conflict, - new_kind, - svn_wc_notify_state_inapplicable, - svn_wc_notify_state_inapplicable)); + *conflict_p = conflict; return SVN_NO_ERROR; } -/* Checks if a specific local path is shadowed as seen from the move root */ +static svn_error_t * +create_node_tree_conflict(svn_skel_t **conflict_p, + node_move_baton_t *nmb, + const char *dst_local_relpath, + svn_node_kind_t old_kind, + svn_node_kind_t new_kind, + const char *old_repos_relpath, + svn_wc_conflict_reason_t reason, + svn_wc_conflict_action_t action, + const char *move_src_op_root_relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + update_move_baton_t *umb = nmb->umb; + + return svn_error_trace( + create_tree_conflict(conflict_p, umb->wcroot, dst_local_relpath, + svn_relpath_limit(dst_local_relpath, + umb->dst_op_depth, + scratch_pool), + umb->db, + umb->old_version, umb->new_version, + umb->operation, old_kind, new_kind, + old_repos_relpath, + reason, action, move_src_op_root_relpath, + result_pool, scratch_pool)); +} + +/* Checks if a specific local path is shadowed as seen from the move root. + Helper for update_moved_away_node() */ static svn_error_t * check_node_shadowed(svn_boolean_t *shadowed, svn_wc__db_wcroot_t *wcroot, const char *local_relpath, - const char *move_root_dst_relpath, + int move_root_dst_op_depth, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; - /* ### This should really be optimized by using something smart - in the baton */ - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_WORKING_NODE)); SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); - if (have_row) { - int op_depth = -1; + int op_depth = svn_sqlite__column_int(stmt, 0); - *shadowed = (op_depth > relpath_depth(move_root_dst_relpath)); + *shadowed = (op_depth > move_root_dst_op_depth); } else *shadowed = FALSE; @@ -439,253 +488,284 @@ check_node_shadowed(svn_boolean_t *shado return SVN_NO_ERROR; } -/* If LOCAL_RELPATH is a child of the most recently raised - tree-conflict or is shadowed then set *IS_CONFLICTED to TRUE and - raise a tree-conflict on the root of the obstruction if such a - tree-conflict does not already exist. KIND is the kind of the - incoming LOCAL_RELPATH. This relies on the non-Ev2, depth-first, - drive. */ +/* Set a tree conflict for the shadowed node LOCAL_RELPATH, which is + the ROOT OF THE OBSTRUCTION if such a tree-conflict does not + already exist. KIND is the kind of the incoming LOCAL_RELPATH. */ static svn_error_t * -check_tree_conflict(svn_boolean_t *is_conflicted, - update_move_baton_t *b, - const char *local_relpath, - svn_node_kind_t old_kind, - svn_node_kind_t new_kind, - const char *old_repos_relpath, - svn_wc_conflict_action_t action, - apr_pool_t *scratch_pool) +mark_tc_on_op_root(node_move_baton_t *nmb, + svn_node_kind_t old_kind, + svn_node_kind_t new_kind, + const char *old_repos_relpath, + svn_wc_conflict_action_t action, + apr_pool_t *scratch_pool) { - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - int dst_op_depth = relpath_depth(b->move_root_dst_relpath); - int op_depth; - const char *conflict_root_relpath = local_relpath; + update_move_baton_t *b = nmb->umb; + const char *conflict_root_relpath = nmb->dst_relpath; const char *move_dst_relpath, *dummy1; const char *dummy2, *move_src_op_root_relpath; + svn_skel_t *conflict; - if (b->conflict_root_relpath) - { - if (svn_relpath_skip_ancestor(b->conflict_root_relpath, local_relpath)) - { - *is_conflicted = TRUE; - return SVN_NO_ERROR; - } - b->conflict_root_relpath = NULL; - } + SVN_ERR_ASSERT(nmb->shadowed && !nmb->pb->shadowed); - SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, - STMT_SELECT_LOWEST_WORKING_NODE)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, local_relpath, - dst_op_depth)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - if (have_row) - op_depth = svn_sqlite__column_int(stmt, 0); - SVN_ERR(svn_sqlite__reset(stmt)); + nmb->skip = TRUE; - if (!have_row) + SVN_ERR(svn_wc__db_op_depth_moved_to(&move_dst_relpath, + &dummy1, + &dummy2, + &move_src_op_root_relpath, + b->dst_op_depth, + b->wcroot, conflict_root_relpath, + scratch_pool, scratch_pool)); + + SVN_ERR(create_node_tree_conflict(&conflict, nmb, conflict_root_relpath, + old_kind, new_kind, + old_repos_relpath, + (move_dst_relpath + ? svn_wc_conflict_reason_moved_away + : svn_wc_conflict_reason_deleted), + action, move_src_op_root_relpath, + scratch_pool, scratch_pool)); + + SVN_ERR(update_move_list_add(b->wcroot, conflict_root_relpath, + svn_wc_notify_tree_conflict, + new_kind, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, NULL, scratch_pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +mark_node_edited(node_move_baton_t *nmb, + apr_pool_t *scratch_pool) +{ + if (nmb->edited) + return SVN_NO_ERROR; + + if (nmb->pb) { - *is_conflicted = FALSE; - return SVN_NO_ERROR; + SVN_ERR(mark_node_edited(nmb->pb, scratch_pool)); + + if (nmb->pb->skip) + nmb->skip = TRUE; } - *is_conflicted = TRUE; + nmb->edited = TRUE; + + if (nmb->skip) + return SVN_NO_ERROR; - while (relpath_depth(conflict_root_relpath) > op_depth) + if (nmb->shadowed && !(nmb->pb && nmb->pb->shadowed)) { - conflict_root_relpath = svn_relpath_dirname(conflict_root_relpath, - scratch_pool); - old_kind = new_kind = svn_node_dir; - if (old_repos_relpath) - old_repos_relpath = svn_relpath_dirname(old_repos_relpath, - scratch_pool); - action = svn_wc_conflict_action_edit; + svn_node_kind_t dst_kind, src_kind; + const char *dst_repos_relpath; + + SVN_ERR(svn_wc__db_depth_get_info(NULL, &dst_kind, NULL, + &dst_repos_relpath, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + nmb->umb->wcroot, nmb->dst_relpath, + nmb->umb->dst_op_depth, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__db_depth_get_info(NULL, &src_kind, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + nmb->umb->wcroot, nmb->src_relpath, + nmb->umb->src_op_depth, + scratch_pool, scratch_pool)); + + SVN_ERR(mark_tc_on_op_root(nmb, + dst_kind, src_kind, + dst_repos_relpath, + svn_wc_conflict_action_edit, + scratch_pool)); } - SVN_ERR(svn_wc__db_op_depth_moved_to(&move_dst_relpath, - &dummy1, - &dummy2, - &move_src_op_root_relpath, - dst_op_depth, - b->wcroot, conflict_root_relpath, - scratch_pool, scratch_pool)); + return SVN_NO_ERROR; +} + +static svn_error_t * +mark_parent_edited(node_move_baton_t *nmb, + apr_pool_t *scratch_pool) +{ + SVN_ERR_ASSERT(nmb && nmb->pb); + + SVN_ERR(mark_node_edited(nmb->pb, scratch_pool)); - SVN_ERR(mark_tree_conflict(conflict_root_relpath, - b->wcroot, b->db, b->old_version, b->new_version, - b->move_root_dst_relpath, b->operation, - old_kind, new_kind, - old_repos_relpath, - (move_dst_relpath - ? svn_wc_conflict_reason_moved_away - : svn_wc_conflict_reason_deleted), - action, move_src_op_root_relpath, - scratch_pool)); - b->conflict_root_relpath = apr_pstrdup(b->result_pool, conflict_root_relpath); + if (nmb->pb->skip) + nmb->skip = TRUE; return SVN_NO_ERROR; } static svn_error_t * -tc_editor_add_directory(update_move_baton_t *b, +tc_editor_add_directory(node_move_baton_t *nmb, const char *relpath, apr_hash_t *props, - svn_boolean_t shadowed, apr_pool_t *scratch_pool) { + update_move_baton_t *b = nmb->umb; const char *move_dst_repos_relpath; - svn_node_kind_t move_dst_kind; - svn_boolean_t is_conflicted; - const char *abspath; + const char *local_abspath; svn_node_kind_t old_kind; - svn_skel_t *work_item; + svn_skel_t *work_item = NULL; svn_wc_notify_action_t action = svn_wc_notify_update_add; - svn_error_t *err; + svn_skel_t *conflict = NULL; - /* Update NODES, only the bits not covered by the later call to - replace_moved_layer. */ - err = svn_wc__db_depth_get_info(NULL, &move_dst_kind, NULL, - &move_dst_repos_relpath, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - b->wcroot, relpath, - relpath_depth(b->move_root_dst_relpath), - scratch_pool, scratch_pool); - if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) - { - svn_error_clear(err); - old_kind = svn_node_none; - move_dst_repos_relpath = NULL; - } - else + SVN_ERR(mark_parent_edited(nmb, scratch_pool)); + if (nmb->skip) + return SVN_NO_ERROR; + + /* We can't read the information from the pre-add node to obtain the + relpath, but in WORKING we can just calculate it from the op-root */ + { + const char *dst_op_root_relpath = svn_relpath_limit(nmb->pb->dst_relpath, + b->dst_op_depth, + scratch_pool); + SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, NULL, + &move_dst_repos_relpath, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, + b->wcroot, dst_op_root_relpath, + b->dst_op_depth, + scratch_pool, scratch_pool)); + + move_dst_repos_relpath = + svn_relpath_join(move_dst_repos_relpath, + svn_relpath_skip_ancestor(dst_op_root_relpath, + relpath), + scratch_pool); + } + + if (nmb->shadowed) { - SVN_ERR(err); - old_kind = move_dst_kind; + SVN_ERR(mark_tc_on_op_root(nmb, + svn_node_none, svn_node_dir, + move_dst_repos_relpath, + svn_wc_conflict_action_add, + scratch_pool)); + return SVN_NO_ERROR; } - /* Check for NODES tree-conflict. */ - SVN_ERR(check_tree_conflict(&is_conflicted, b, relpath, - old_kind, svn_node_dir, - move_dst_repos_relpath, - svn_wc_conflict_action_add, - scratch_pool)); - if (is_conflicted || shadowed) - return SVN_NO_ERROR; - /* Check for unversioned tree-conflict */ - abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); - SVN_ERR(svn_io_check_path(abspath, &old_kind, scratch_pool)); + local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); + SVN_ERR(svn_io_check_path(local_abspath, &old_kind, scratch_pool)); switch (old_kind) { case svn_node_file: default: - SVN_ERR(mark_tree_conflict(relpath, b->wcroot, b->db, b->old_version, - b->new_version, b->move_root_dst_relpath, - b->operation, old_kind, svn_node_dir, - move_dst_repos_relpath, - svn_wc_conflict_reason_unversioned, - svn_wc_conflict_action_add, NULL, - scratch_pool)); - b->conflict_root_relpath = apr_pstrdup(b->result_pool, relpath); + SVN_ERR(create_node_tree_conflict(&conflict, nmb, relpath, + old_kind, svn_node_dir, + move_dst_repos_relpath, + svn_wc_conflict_reason_unversioned, + svn_wc_conflict_action_add, NULL, + scratch_pool, scratch_pool)); + nmb->skip = TRUE; action = svn_wc_notify_tree_conflict; - is_conflicted = TRUE; break; case svn_node_none: - SVN_ERR(svn_wc__wq_build_dir_install(&work_item, b->db, abspath, + SVN_ERR(svn_wc__wq_build_dir_install(&work_item, b->db, local_abspath, scratch_pool, scratch_pool)); - - SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, scratch_pool)); /* Fall through */ case svn_node_dir: break; } - if (!is_conflicted) - SVN_ERR(update_move_list_add(b->wcroot, relpath, - action, - svn_node_dir, - svn_wc_notify_state_inapplicable, - svn_wc_notify_state_inapplicable)); + SVN_ERR(update_move_list_add(b->wcroot, relpath, + action, + svn_node_dir, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, work_item, scratch_pool)); return SVN_NO_ERROR; } static svn_error_t * -tc_editor_add_file(update_move_baton_t *b, +tc_editor_add_file(node_move_baton_t *nmb, const char *relpath, const svn_checksum_t *checksum, apr_hash_t *props, - svn_boolean_t shadowed, apr_pool_t *scratch_pool) { + update_move_baton_t *b = nmb->umb; const char *move_dst_repos_relpath; - svn_node_kind_t move_dst_kind; svn_node_kind_t old_kind; - svn_boolean_t is_conflicted; - const char *abspath; - svn_skel_t *work_item; - svn_error_t *err; - - /* Update NODES, only the bits not covered by the later call to - replace_moved_layer. */ - err = svn_wc__db_depth_get_info(NULL, &move_dst_kind, NULL, - &move_dst_repos_relpath, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - b->wcroot, relpath, - relpath_depth(b->move_root_dst_relpath), - scratch_pool, scratch_pool); - if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) - { - svn_error_clear(err); - old_kind = svn_node_none; - move_dst_repos_relpath = NULL; - } - else - { - SVN_ERR(err); - old_kind = move_dst_kind; - } + const char *local_abspath; + svn_skel_t *work_item = NULL; + svn_skel_t *conflict = NULL; - /* Check for NODES tree-conflict. */ - SVN_ERR(check_tree_conflict(&is_conflicted, b, relpath, - old_kind, svn_node_file, move_dst_repos_relpath, - svn_wc_conflict_action_add, - scratch_pool)); - if (is_conflicted || shadowed) + SVN_ERR(mark_parent_edited(nmb, scratch_pool)); + if (nmb->skip) return SVN_NO_ERROR; - /* Check for unversioned tree-conflict */ - abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); - SVN_ERR(svn_io_check_path(abspath, &old_kind, scratch_pool)); + /* We can't read the information from the pre-add node to obtain the + relpath, but in WORKING we can just calculate it from the op-root */ + { + const char *dst_op_root_relpath = svn_relpath_limit(nmb->pb->dst_relpath, + b->dst_op_depth, + scratch_pool); + SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, NULL, + &move_dst_repos_relpath, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, + b->wcroot, dst_op_root_relpath, + b->dst_op_depth, + scratch_pool, scratch_pool)); - if (old_kind != svn_node_none) + move_dst_repos_relpath = + svn_relpath_join(move_dst_repos_relpath, + svn_relpath_skip_ancestor(dst_op_root_relpath, + relpath), + scratch_pool); + } + + /* Check for NODES tree-conflict. */ + if (nmb->shadowed) { - SVN_ERR(mark_tree_conflict(relpath, b->wcroot, b->db, b->old_version, - b->new_version, b->move_root_dst_relpath, - b->operation, old_kind, svn_node_file, + SVN_ERR(mark_tc_on_op_root(nmb, + svn_node_none, svn_node_file, move_dst_repos_relpath, - svn_wc_conflict_reason_unversioned, - svn_wc_conflict_action_add, NULL, + svn_wc_conflict_action_add, scratch_pool)); - b->conflict_root_relpath = apr_pstrdup(b->result_pool, relpath); return SVN_NO_ERROR; } - /* Update working file. */ - SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, - svn_dirent_join(b->wcroot->abspath, - relpath, - scratch_pool), - NULL, - FALSE /* FIXME: use_commit_times? */, - TRUE /* record_file_info */, - scratch_pool, scratch_pool)); + /* Check for unversioned tree-conflict */ + local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); + SVN_ERR(svn_io_check_path(local_abspath, &old_kind, scratch_pool)); - SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, scratch_pool)); + if (old_kind != svn_node_none) + { + SVN_ERR(create_node_tree_conflict(&conflict, nmb, relpath, + old_kind, svn_node_file, + move_dst_repos_relpath, + svn_wc_conflict_reason_unversioned, + svn_wc_conflict_action_add, NULL, + scratch_pool, scratch_pool)); + nmb->skip = TRUE; + } + else + { + /* Update working file. */ + SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, + svn_dirent_join(b->wcroot->abspath, + relpath, + scratch_pool), + NULL, + FALSE /*FIXME: use_commit_times?*/, + TRUE /* record_file_info */, + scratch_pool, scratch_pool)); + } SVN_ERR(update_move_list_add(b->wcroot, relpath, svn_wc_notify_update_add, svn_node_file, svn_wc_notify_state_inapplicable, - svn_wc_notify_state_inapplicable)); + svn_wc_notify_state_inapplicable, + conflict, work_item, scratch_pool)); return SVN_NO_ERROR; } @@ -810,94 +890,74 @@ update_working_props(svn_wc_notify_state } static svn_error_t * -tc_editor_alter_directory(update_move_baton_t *b, +tc_editor_alter_directory(node_move_baton_t *nmb, const char *dst_relpath, + apr_hash_t *old_props, apr_hash_t *new_props, - svn_boolean_t shadowed, apr_pool_t *scratch_pool) { - const char *move_dst_repos_relpath; - svn_revnum_t move_dst_revision; - svn_node_kind_t move_dst_kind; + update_move_baton_t *b = nmb->umb; working_node_version_t old_version, new_version; - svn_wc__db_status_t status; - svn_boolean_t is_conflicted; - - SVN_ERR(svn_wc__db_depth_get_info(&status, &move_dst_kind, &move_dst_revision, - &move_dst_repos_relpath, NULL, NULL, NULL, - NULL, NULL, &old_version.checksum, NULL, - NULL, &old_version.props, - b->wcroot, dst_relpath, - relpath_depth(b->move_root_dst_relpath), - scratch_pool, scratch_pool)); - + svn_skel_t *work_items = NULL; + svn_skel_t *conflict_skel = NULL; + const char *local_abspath = svn_dirent_join(b->wcroot->abspath, dst_relpath, + scratch_pool); + svn_wc_notify_state_t prop_state; + apr_hash_t *actual_props; + apr_array_header_t *propchanges; - /* There might be not-present nodes of a different revision as the same - depth as a copy. This is commonly caused by copying/moving mixed revision - directories */ - SVN_ERR_ASSERT(move_dst_kind == svn_node_dir); - - SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, - move_dst_kind, - svn_node_dir, - move_dst_repos_relpath, - svn_wc_conflict_action_edit, - scratch_pool)); - if (is_conflicted || shadowed) + SVN_ERR(mark_node_edited(nmb, scratch_pool)); + if (nmb->skip) return SVN_NO_ERROR; old_version.location_and_kind = b->old_version; new_version.location_and_kind = b->new_version; + old_version.checksum = NULL; /* not a file */ + old_version.props = old_props; new_version.checksum = NULL; /* not a file */ - new_version.props = new_props ? new_props : old_version.props; + new_version.props = new_props; - if (new_props) - { - const char *dst_abspath = svn_dirent_join(b->wcroot->abspath, - dst_relpath, - scratch_pool); - svn_wc_notify_state_t prop_state; - svn_skel_t *conflict_skel = NULL; - apr_hash_t *actual_props; - apr_array_header_t *propchanges; - - /* ### TODO: Only do this when there is no higher WORKING layer */ - SVN_ERR(update_working_props(&prop_state, &conflict_skel, - &propchanges, &actual_props, - b, dst_relpath, - &old_version, &new_version, - scratch_pool, scratch_pool)); + SVN_ERR(update_working_props(&prop_state, &conflict_skel, + &propchanges, &actual_props, + b, dst_relpath, + &old_version, &new_version, + scratch_pool, scratch_pool)); - if (conflict_skel) - { - svn_skel_t *work_items; + if (conflict_skel) + { + const char *move_dst_repos_relpath; - SVN_ERR(create_conflict_markers(&work_items, dst_abspath, - b->db, move_dst_repos_relpath, - conflict_skel, b->operation, - &old_version, &new_version, - svn_node_dir, - scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath, - conflict_skel, - scratch_pool)); - SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items, - scratch_pool)); - } + SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, NULL, + &move_dst_repos_relpath, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, + b->wcroot, dst_relpath, + b->dst_op_depth, + scratch_pool, scratch_pool)); - SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, - svn_wc_notify_update_update, - svn_node_dir, - svn_wc_notify_state_inapplicable, - prop_state)); + SVN_ERR(create_conflict_markers(&work_items, local_abspath, + b->db, move_dst_repos_relpath, + conflict_skel, b->operation, + &old_version, &new_version, + svn_node_dir, + scratch_pool, scratch_pool)); } + SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, + svn_wc_notify_update_update, + svn_node_dir, + svn_wc_notify_state_inapplicable, + prop_state, + conflict_skel, work_items, scratch_pool)); + return SVN_NO_ERROR; } - -/* Merge the difference between OLD_VERSION and NEW_VERSION into +/* Edit the file found at the move destination, which is initially at + * the old state. Merge the changes into the "working"/"actual" file. + * + * Merge the difference between OLD_VERSION and NEW_VERSION into * the working file at LOCAL_RELPATH. * * The term 'old' refers to the pre-update state, which is the state of @@ -912,16 +972,18 @@ tc_editor_alter_directory(update_move_ba * Set *WORK_ITEMS to any required work items, allocated in RESULT_POOL. * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -update_working_file(update_move_baton_t *b, - const char *local_relpath, - const char *repos_relpath, - svn_wc_operation_t operation, - const working_node_version_t *old_version, - const working_node_version_t *new_version, - apr_pool_t *scratch_pool) +tc_editor_alter_file(node_move_baton_t *nmb, + const char *dst_relpath, + const svn_checksum_t *old_checksum, + const svn_checksum_t *new_checksum, + apr_hash_t *old_props, + apr_hash_t *new_props, + apr_pool_t *scratch_pool) { + update_move_baton_t *b = nmb->umb; + working_node_version_t old_version, new_version; const char *local_abspath = svn_dirent_join(b->wcroot->abspath, - local_relpath, + dst_relpath, scratch_pool); const char *old_pristine_abspath; const char *new_pristine_abspath; @@ -932,13 +994,25 @@ update_working_file(update_move_baton_t svn_wc_notify_state_t prop_state, content_state; svn_skel_t *work_item, *work_items = NULL; + SVN_ERR(mark_node_edited(nmb, scratch_pool)); + if (nmb->skip) + return SVN_NO_ERROR; + + old_version.location_and_kind = b->old_version; + new_version.location_and_kind = b->new_version; + + old_version.checksum = old_checksum; + old_version.props = old_props; + new_version.checksum = new_checksum; + new_version.props = new_props; + /* ### TODO: Only do this when there is no higher WORKING layer */ SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges, - &actual_props, b, local_relpath, - old_version, new_version, + &actual_props, b, dst_relpath, + &old_version, &new_version, scratch_pool, scratch_pool)); - if (!svn_checksum_match(new_version->checksum, old_version->checksum)) + if (!svn_checksum_match(new_version.checksum, old_version.checksum)) { svn_boolean_t is_locally_modified; @@ -969,11 +1043,11 @@ update_working_file(update_move_baton_t */ SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath, b->db, b->wcroot->abspath, - old_version->checksum, + old_version.checksum, scratch_pool, scratch_pool)); SVN_ERR(svn_wc__db_pristine_get_path(&new_pristine_abspath, b->db, b->wcroot->abspath, - new_version->checksum, + new_version.checksum, scratch_pool, scratch_pool)); SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel, &merge_outcome, b->db, @@ -1005,124 +1079,78 @@ update_working_file(update_move_baton_t * too. */ if (conflict_skel) { + const char *move_dst_repos_relpath; + + SVN_ERR(svn_wc__db_depth_get_info(NULL, NULL, NULL, + &move_dst_repos_relpath, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, + b->wcroot, dst_relpath, + b->dst_op_depth, + scratch_pool, scratch_pool)); + SVN_ERR(create_conflict_markers(&work_item, local_abspath, b->db, - repos_relpath, conflict_skel, - operation, old_version, new_version, + move_dst_repos_relpath, conflict_skel, + b->operation, &old_version, &new_version, svn_node_file, scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, local_relpath, - conflict_skel, - scratch_pool)); - work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); } - SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items, scratch_pool)); - - SVN_ERR(update_move_list_add(b->wcroot, local_relpath, + SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, svn_wc_notify_update_update, svn_node_file, content_state, - prop_state)); + prop_state, + conflict_skel, work_items, scratch_pool)); return SVN_NO_ERROR; } - -/* Edit the file found at the move destination, which is initially at - * the old state. Merge the changes into the "working"/"actual" file. - */ static svn_error_t * -tc_editor_alter_file(update_move_baton_t *b, - const char *dst_relpath, - const svn_checksum_t *new_checksum, - apr_hash_t *new_props, - svn_boolean_t shadowed, - apr_pool_t *scratch_pool) -{ - const char *move_dst_repos_relpath; - svn_revnum_t move_dst_revision; - svn_node_kind_t move_dst_kind; - working_node_version_t old_version, new_version; - svn_boolean_t is_conflicted; - svn_wc__db_status_t status; - - SVN_ERR(svn_wc__db_depth_get_info(&status, &move_dst_kind, &move_dst_revision, - &move_dst_repos_relpath, NULL, NULL, NULL, - NULL, NULL, &old_version.checksum, NULL, - NULL, &old_version.props, - b->wcroot, dst_relpath, - relpath_depth(b->move_root_dst_relpath), - scratch_pool, scratch_pool)); - - SVN_ERR_ASSERT(move_dst_kind == svn_node_file); - - SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, - move_dst_kind, - svn_node_file, - move_dst_repos_relpath, - svn_wc_conflict_action_edit, - scratch_pool)); - if (is_conflicted || shadowed) - return SVN_NO_ERROR; - - old_version.location_and_kind = b->old_version; - new_version.location_and_kind = b->new_version; - - /* If new checksum is null that means no change; similarly props. */ - new_version.checksum = new_checksum ? new_checksum : old_version.checksum; - new_version.props = new_props ? new_props : old_version.props; - - /* Update file and prop contents if the update has changed them. */ - if (!svn_checksum_match(new_checksum, old_version.checksum) || new_props) - { - SVN_ERR(update_working_file(b, dst_relpath, move_dst_repos_relpath, - b->operation, &old_version, &new_version, - scratch_pool)); - } - - return SVN_NO_ERROR; -} - -static svn_error_t * -tc_editor_delete(update_move_baton_t *b, +tc_editor_delete(node_move_baton_t *nmb, const char *relpath, - svn_boolean_t shadowed, apr_pool_t *scratch_pool) { + update_move_baton_t *b = nmb->umb; svn_sqlite__stmt_t *stmt; - int op_depth = relpath_depth(b->move_root_dst_relpath); const char *move_dst_repos_relpath; svn_node_kind_t move_dst_kind; - svn_boolean_t is_conflicted; - svn_boolean_t must_delete_working_nodes = FALSE; + svn_boolean_t must_delete_wc_nodes = FALSE; const char *local_abspath; svn_boolean_t have_row; svn_boolean_t is_modified, is_all_deletes; + svn_skel_t *work_items = NULL; + svn_skel_t *conflict = NULL; + + SVN_ERR(mark_parent_edited(nmb, scratch_pool)); + if (nmb->skip) + return SVN_NO_ERROR; SVN_ERR(svn_wc__db_depth_get_info(NULL, &move_dst_kind, NULL, &move_dst_repos_relpath, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - b->wcroot, relpath, op_depth, + b->wcroot, relpath, b->dst_op_depth, scratch_pool, scratch_pool)); /* Check before retracting delete to catch delete-delete conflicts. This catches conflicts on the node itself; deleted children are caught as local modifications below.*/ - SVN_ERR(check_tree_conflict(&is_conflicted, b, relpath, - move_dst_kind, - svn_node_unknown, - move_dst_repos_relpath, - svn_wc_conflict_action_delete, - scratch_pool)); - - if (shadowed || is_conflicted) - return SVN_NO_ERROR; + if (nmb->shadowed) + { + SVN_ERR(mark_tc_on_op_root(nmb, + move_dst_kind, + svn_node_unknown, + move_dst_repos_relpath, + svn_wc_conflict_action_delete, + scratch_pool)); + return SVN_NO_ERROR; + } local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); - SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes, b->db, - local_abspath, + SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes, + nmb->umb->db, local_abspath, NULL, NULL, scratch_pool)); if (is_modified) { @@ -1131,54 +1159,50 @@ tc_editor_delete(update_move_baton_t *b, if (!is_all_deletes) { /* No conflict means no NODES rows at the relpath op-depth - so it's easy to convert the modified tree into a copy. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, - STMT_UPDATE_OP_DEPTH_RECURSIVE)); - SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath, - op_depth, relpath_depth(relpath))); - SVN_ERR(svn_sqlite__step_done(stmt)); + so it's easy to convert the modified tree into a copy. + + Note the following assumptions for relpath: + * it is not shadowed + * it is not the/an op-root. (or we can't make us a copy) + */ + + SVN_ERR(svn_wc__db_op_make_copy_internal(b->wcroot, relpath, + NULL, NULL, scratch_pool)); reason = svn_wc_conflict_reason_edited; } else { - - SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, - STMT_DELETE_WORKING_OP_DEPTH_ABOVE)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath, - op_depth)); - SVN_ERR(svn_sqlite__step_done(stmt)); - reason = svn_wc_conflict_reason_deleted; - must_delete_working_nodes = TRUE; + must_delete_wc_nodes = TRUE; } - is_conflicted = TRUE; - SVN_ERR(mark_tree_conflict(relpath, b->wcroot, b->db, b->old_version, - b->new_version, b->move_root_dst_relpath, - b->operation, - move_dst_kind, - svn_node_none, - move_dst_repos_relpath, reason, - svn_wc_conflict_action_delete, NULL, - scratch_pool)); - b->conflict_root_relpath = apr_pstrdup(b->result_pool, relpath); + SVN_ERR(create_node_tree_conflict(&conflict, nmb, relpath, + move_dst_kind, svn_node_none, + move_dst_repos_relpath, reason, + svn_wc_conflict_action_delete, NULL, + scratch_pool, scratch_pool)); + nmb->skip = TRUE; } + else + must_delete_wc_nodes = TRUE; - if (!is_conflicted || must_delete_working_nodes) + if (must_delete_wc_nodes) { apr_pool_t *iterpool = svn_pool_create(scratch_pool); - svn_skel_t *work_item; svn_node_kind_t del_kind; const char *del_abspath; + /* Get all descendants of the node in reverse order (so children are + handled before their parents, but not strictly depth first) */ SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, - STMT_SELECT_CHILDREN_OP_DEPTH)); + STMT_SELECT_DESCENDANTS_OP_DEPTH_RV)); SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath, - op_depth)); + b->dst_op_depth)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); while (have_row) { svn_error_t *err; + svn_skel_t *work_item; svn_pool_clear(iterpool); @@ -1207,95 +1231,31 @@ tc_editor_delete(update_move_baton_t *b, SVN_ERR(svn_wc__db_depth_get_info(NULL, &del_kind, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - b->wcroot, relpath, op_depth, + b->wcroot, relpath, b->dst_op_depth, iterpool, iterpool)); if (del_kind == svn_node_dir) - SVN_ERR(svn_wc__wq_build_dir_remove(&work_item, b->db, + SVN_ERR(svn_wc__wq_build_dir_remove(&work_items, b->db, b->wcroot->abspath, local_abspath, FALSE /* recursive */, - iterpool, iterpool)); + scratch_pool, iterpool)); else - SVN_ERR(svn_wc__wq_build_file_remove(&work_item, b->db, + SVN_ERR(svn_wc__wq_build_file_remove(&work_items, b->db, b->wcroot->abspath, local_abspath, iterpool, iterpool)); - SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, iterpool)); - - if (!is_conflicted) - SVN_ERR(update_move_list_add(b->wcroot, relpath, - svn_wc_notify_update_delete, - del_kind, - svn_wc_notify_state_inapplicable, - svn_wc_notify_state_inapplicable)); - svn_pool_destroy(iterpool); - } - return SVN_NO_ERROR; -} - -/* Delete handling for both WORKING and shadowed nodes */ -static svn_error_t * -delete_move_leaf(svn_wc__db_wcroot_t *wcroot, - const char *local_relpath, - int op_depth, - apr_pool_t *scratch_pool) -{ - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - int op_depth_below; - - /* Deleting the ROWS is valid as long as we update the parent before - committing the transaction. The removed rows could have been - replacing a lower layer in which case we need to add base-deleted - rows. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_SELECT_HIGHEST_WORKING_NODE)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, - svn_relpath_dirname(local_relpath, scratch_pool), - op_depth)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - if (have_row) - op_depth_below = svn_sqlite__column_int(stmt, 0); - SVN_ERR(svn_sqlite__reset(stmt)); - if (have_row) - { - /* Remove non-shadowing nodes. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_DELETE_NO_LOWER_LAYER)); - SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id, local_relpath, - op_depth, op_depth_below)); - SVN_ERR(svn_sqlite__step_done(stmt)); - /* Convert remaining shadowing nodes to presence='base-deleted'. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_REPLACE_WITH_BASE_DELETED)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, - op_depth)); - SVN_ERR(svn_sqlite__step_done(stmt)); - } - else - { - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_DELETE_WORKING_OP_DEPTH)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, - op_depth)); - SVN_ERR(svn_sqlite__step_done(stmt)); + svn_pool_destroy(iterpool); } - /* Retract any base-delete for descendants. */ - { - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_DELETE_WORKING_BASE_DELETE)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, - op_depth)); - SVN_ERR(svn_sqlite__step_done(stmt)); - } - /* And for the node itself */ - SVN_ERR(svn_wc__db_retract_parent_delete(wcroot, local_relpath, op_depth, - scratch_pool)); + SVN_ERR(update_move_list_add(b->wcroot, relpath, + svn_wc_notify_update_delete, + move_dst_kind, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, work_items, scratch_pool)); return SVN_NO_ERROR; } - /* * Driver code. * @@ -1496,99 +1456,76 @@ props_match(svn_boolean_t *match, /* ### Drive TC_EDITOR so as to ... */ static svn_error_t * -update_moved_away_node(update_move_baton_t *b, +update_moved_away_node(node_move_baton_t *nmb, svn_wc__db_wcroot_t *wcroot, const char *src_relpath, const char *dst_relpath, - int src_op_depth, - const char *move_root_dst_relpath, - svn_boolean_t shadowed, - svn_wc__db_t *db, apr_pool_t *scratch_pool) { + update_move_baton_t *b = nmb->umb; svn_node_kind_t src_kind, dst_kind; const svn_checksum_t *src_checksum, *dst_checksum; apr_hash_t *src_props, *dst_props; apr_array_header_t *src_children, *dst_children; - int dst_op_depth = relpath_depth(move_root_dst_relpath); SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool)); SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool)); SVN_ERR(get_info(&src_props, &src_checksum, &src_children, &src_kind, - src_relpath, src_op_depth, + src_relpath, b->src_op_depth, wcroot, scratch_pool, scratch_pool)); SVN_ERR(get_info(&dst_props, &dst_checksum, &dst_children, &dst_kind, - dst_relpath, dst_op_depth, + dst_relpath, b->dst_op_depth, wcroot, scratch_pool, scratch_pool)); if (src_kind == svn_node_none || (dst_kind != svn_node_none && src_kind != dst_kind)) { - SVN_ERR(tc_editor_delete(b, dst_relpath, shadowed, - scratch_pool)); - - /* And perform some work that in some ways belongs in - replace_moved_layer() after creating all conflicts */ - SVN_ERR(delete_move_leaf(b->wcroot, dst_relpath, - relpath_depth(b->move_root_dst_relpath), - scratch_pool)); + SVN_ERR(tc_editor_delete(nmb, dst_relpath, scratch_pool)); } + if (nmb->skip) + return SVN_NO_ERROR; + if (src_kind != svn_node_none && src_kind != dst_kind) { - if (shadowed) - { - SVN_ERR(svn_wc__db_extend_parent_delete( - b->wcroot, dst_relpath, src_kind, - relpath_depth(b->move_root_dst_relpath), - scratch_pool)); - } if (src_kind == svn_node_file || src_kind == svn_node_symlink) { - SVN_ERR(tc_editor_add_file(b, dst_relpath, - src_checksum, src_props, - shadowed, scratch_pool)); + SVN_ERR(tc_editor_add_file(nmb, dst_relpath, + src_checksum, src_props, scratch_pool)); } else if (src_kind == svn_node_dir) { - SVN_ERR(tc_editor_add_directory(b, dst_relpath, src_props, - shadowed, scratch_pool)); + SVN_ERR(tc_editor_add_directory(nmb, dst_relpath, + src_props, scratch_pool)); } } else if (src_kind != svn_node_none) { - svn_boolean_t match; - apr_hash_t *props; - - SVN_ERR(props_match(&match, src_props, dst_props, scratch_pool)); - props = match ? NULL: src_props; + svn_boolean_t props_equal; + SVN_ERR(props_match(&props_equal, src_props, dst_props, scratch_pool)); if (src_kind == svn_node_file || src_kind == svn_node_symlink) { - if (svn_checksum_match(src_checksum, dst_checksum)) - src_checksum = NULL; - - if (props || src_checksum) - SVN_ERR(tc_editor_alter_file(b, dst_relpath, - src_checksum, props, - shadowed, - scratch_pool)); + if (!props_equal || !svn_checksum_match(src_checksum, dst_checksum)) + SVN_ERR(tc_editor_alter_file(nmb, dst_relpath, + dst_checksum, src_checksum, + dst_props, src_props, scratch_pool)); } else if (src_kind == svn_node_dir) { - apr_array_header_t *children - = children_match(src_children, dst_children) ? NULL : src_children; - - if (props || children) - SVN_ERR(tc_editor_alter_directory(b, dst_relpath, props, - shadowed, + if (!props_equal) + SVN_ERR(tc_editor_alter_directory(nmb, dst_relpath, + dst_props, src_props, scratch_pool)); } } + if (nmb->skip) + return SVN_NO_ERROR; + if (src_kind == svn_node_dir) { apr_pool_t *iterpool = svn_pool_create(scratch_pool); @@ -1597,9 +1534,12 @@ update_moved_away_node(update_move_baton while (i < src_children->nelts || j < dst_children->nelts) { const char *child_name; - const char *src_child_relpath, *dst_child_relpath; svn_boolean_t src_only = FALSE, dst_only = FALSE; - svn_boolean_t child_shadowed = shadowed; + node_move_baton_t cnmb = { 0 }; + + cnmb.pb = nmb; + cnmb.umb = nmb->umb; + cnmb.shadowed = nmb->shadowed; svn_pool_clear(iterpool); if (i >= src_children->nelts) @@ -1628,86 +1568,28 @@ update_moved_away_node(update_move_baton child_name = dst_only ? dst_name : src_name; } - src_child_relpath = svn_relpath_join(src_relpath, child_name, - iterpool); - dst_child_relpath = svn_relpath_join(dst_relpath, child_name, - iterpool); - - if (!child_shadowed) - SVN_ERR(check_node_shadowed(&child_shadowed, wcroot, dst_child_relpath, - b->move_root_dst_relpath, iterpool)); - - SVN_ERR(update_moved_away_node(b, wcroot, src_child_relpath, - dst_child_relpath, src_op_depth, - move_root_dst_relpath, child_shadowed, - db, iterpool)); + cnmb.src_relpath = svn_relpath_join(src_relpath, child_name, + iterpool); + cnmb.dst_relpath = svn_relpath_join(dst_relpath, child_name, + iterpool); + + if (!cnmb.shadowed) + SVN_ERR(check_node_shadowed(&cnmb.shadowed, wcroot, + cnmb.dst_relpath, b->dst_op_depth, + iterpool)); + + SVN_ERR(update_moved_away_node(&cnmb, wcroot, cnmb.src_relpath, + cnmb.dst_relpath, iterpool)); if (!dst_only) ++i; if (!src_only) ++j; - } - } - - return SVN_NO_ERROR; -} - -/* Update the single op-depth layer in the move destination subtree - rooted at DST_RELPATH to make it match the move source subtree - rooted at SRC_RELPATH. */ -static svn_error_t * -replace_moved_layer(const char *src_relpath, - const char *dst_relpath, - int src_op_depth, - svn_wc__db_wcroot_t *wcroot, - apr_pool_t *scratch_pool) -{ - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - int dst_op_depth = relpath_depth(dst_relpath); - - SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool)); - SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool)); - /* Replace entire subtree at one op-depth. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_SELECT_LOCAL_RELPATH_OP_DEPTH)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, - src_relpath, src_op_depth)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - while (have_row) - { - svn_error_t *err; - svn_sqlite__stmt_t *stmt2; - const char *src_cp_relpath = svn_sqlite__column_text(stmt, 0, NULL); - svn_node_kind_t kind = svn_sqlite__column_token(stmt, 1, kind_map); - const char *dst_cp_relpath - = svn_relpath_join(dst_relpath, - svn_relpath_skip_ancestor(src_relpath, - src_cp_relpath), - scratch_pool); - - err = svn_sqlite__get_statement(&stmt2, wcroot->sdb, - STMT_COPY_NODE_MOVE); - if (!err) - err = svn_sqlite__bindf(stmt2, "isdsds", wcroot->wc_id, - src_cp_relpath, src_op_depth, - dst_cp_relpath, dst_op_depth, - svn_relpath_dirname(dst_cp_relpath, - scratch_pool)); - if (!err) - err = svn_sqlite__step_done(stmt2); - - if (!err && strlen(dst_cp_relpath) > strlen(dst_relpath)) - err = svn_wc__db_extend_parent_delete(wcroot, dst_cp_relpath, kind, - dst_op_depth, scratch_pool); - - if (err) - return svn_error_compose_create(err, svn_sqlite__reset(stmt)); - - SVN_ERR(svn_sqlite__step(&have_row, stmt)); + if (nmb->skip) /* Does parent now want a skip? */ + break; + } } - SVN_ERR(svn_sqlite__reset(stmt)); return SVN_NO_ERROR; } @@ -1727,18 +1609,19 @@ static svn_error_t * drive_tree_conflict_editor(update_move_baton_t *b, const char *src_relpath, const char *dst_relpath, - int src_op_depth, svn_wc_operation_t operation, svn_wc_conflict_reason_t local_change, svn_wc_conflict_action_t incoming_change, svn_wc_conflict_version_t *old_version, svn_wc_conflict_version_t *new_version, - svn_wc__db_t *db, svn_wc__db_wcroot_t *wcroot, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) { + node_move_baton_t nmb = { 0 }; + SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool)); + SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool)); /* * Refuse to auto-resolve unsupported tree conflicts. */ @@ -1750,16 +1633,23 @@ drive_tree_conflict_editor(update_move_b path_for_error_message(wcroot, src_relpath, scratch_pool)); + nmb.umb = b; + nmb.src_relpath = src_relpath; + nmb.dst_relpath = dst_relpath; + /* nmb.shadowed = FALSE; */ + /* nmb.edited = FALSE; */ + /* nmb.skip_children = FALSE; */ + /* We walk the move source (i.e. the post-update tree), comparing each node * with the equivalent node at the move destination and applying the update * to nodes at the move destination. */ - SVN_ERR(update_moved_away_node(b, wcroot, src_relpath, dst_relpath, - src_op_depth, - dst_relpath, FALSE /* never shadowed */, - db, scratch_pool)); + SVN_ERR(update_moved_away_node(&nmb, wcroot, src_relpath, dst_relpath, + scratch_pool)); - SVN_ERR(replace_moved_layer(src_relpath, dst_relpath, src_op_depth, - wcroot, scratch_pool)); + SVN_ERR(svn_wc__db_op_copy_layer_internal(wcroot, src_relpath, + b->src_op_depth, + dst_relpath, NULL, NULL, + scratch_pool)); return SVN_NO_ERROR; } @@ -1843,30 +1733,28 @@ update_moved_away_conflict_victim(svn_wc void *cancel_baton, apr_pool_t *scratch_pool) { - update_move_baton_t umb; + update_move_baton_t umb = { NULL }; svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; const char *dummy1, *dummy2, *dummy3; - int src_op_depth; const char *move_root_dst_abspath; + const char *move_root_dst_relpath; /* ### assumes wc write lock already held */ /* Construct editor baton. */ - memset(&umb, 0, sizeof(umb)); SVN_ERR(svn_wc__db_op_depth_moved_to( - &dummy1, &umb.move_root_dst_relpath, &dummy2, &dummy3, + &dummy1, &move_root_dst_relpath, &dummy2, &dummy3, relpath_depth(move_src_op_root_relpath) - 1, wcroot, victim_relpath, scratch_pool, scratch_pool)); - if (umb.move_root_dst_relpath == NULL) + if (move_root_dst_relpath == NULL) return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, _("The node '%s' has not been moved away"), path_for_error_message(wcroot, victim_relpath, scratch_pool)); move_root_dst_abspath - = svn_dirent_join(wcroot->abspath, umb.move_root_dst_relpath, - scratch_pool); + = svn_dirent_join(wcroot->abspath, move_root_dst_relpath, scratch_pool); SVN_ERR(svn_wc__write_check(db, move_root_dst_abspath, scratch_pool)); umb.operation = operation; @@ -1874,7 +1762,8 @@ update_moved_away_conflict_victim(svn_wc umb.new_version= new_version; umb.db = db; umb.wcroot = wcroot; - umb.result_pool = scratch_pool; + + umb.dst_op_depth = relpath_depth(move_root_dst_relpath); SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_HIGHEST_WORKING_NODE)); @@ -1883,7 +1772,7 @@ update_moved_away_conflict_victim(svn_wc relpath_depth(move_src_op_root_relpath))); SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (have_row) - src_op_depth = svn_sqlite__column_int(stmt, 0); + umb.src_op_depth = svn_sqlite__column_int(stmt, 0); SVN_ERR(svn_sqlite__reset(stmt)); if (!have_row) return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, @@ -1891,7 +1780,7 @@ update_moved_away_conflict_victim(svn_wc path_for_error_message(wcroot, victim_relpath, scratch_pool)); - if (src_op_depth == 0) + if (umb.src_op_depth == 0) SVN_ERR(suitable_for_move(wcroot, victim_relpath, scratch_pool)); /* Create a new, and empty, list for notification information. */ @@ -1902,13 +1791,12 @@ update_moved_away_conflict_victim(svn_wc /* ... and drive it. */ SVN_ERR(drive_tree_conflict_editor(&umb, victim_relpath, - umb.move_root_dst_relpath, - src_op_depth, + move_root_dst_relpath, operation, local_change, incoming_change, umb.old_version, umb.new_version, - db, wcroot, + wcroot, cancel_func, cancel_baton, scratch_pool)); @@ -2061,6 +1949,7 @@ bump_mark_tree_conflict(svn_wc__db_wcroo svn_node_kind_t new_kind; svn_wc_conflict_version_t *old_version; svn_wc_conflict_version_t *new_version; + svn_skel_t *conflict; /* Verify precondition: We are allowed to set a tree conflict here. */ SVN_ERR(verify_write_lock(wcroot, move_src_root_relpath, scratch_pool)); @@ -2112,16 +2001,23 @@ bump_mark_tree_conflict(svn_wc__db_wcroo repos_root_url, repos_uuid, new_repos_relpath, new_rev, new_kind, scratch_pool); - SVN_ERR(mark_tree_conflict(move_src_root_relpath, - wcroot, db, old_version, new_version, - move_dst_op_root_relpath, - svn_wc_operation_update, - old_kind, new_kind, - old_repos_relpath, - svn_wc_conflict_reason_moved_away, - svn_wc_conflict_action_edit, - move_src_op_root_relpath, - scratch_pool)); + SVN_ERR(create_tree_conflict(&conflict, wcroot, move_src_root_relpath, + move_dst_op_root_relpath, + db, old_version, new_version, + svn_wc_operation_update, + old_kind, new_kind, + old_repos_relpath, + svn_wc_conflict_reason_moved_away, + svn_wc_conflict_action_edit, + move_src_op_root_relpath, + scratch_pool, scratch_pool)); + + SVN_ERR(update_move_list_add(wcroot, move_src_root_relpath, + svn_wc_notify_tree_conflict, + new_kind, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, NULL, scratch_pool)); return SVN_NO_ERROR; } @@ -2190,13 +2086,10 @@ bump_moved_layer(svn_boolean_t *recurse, const char *local_relpath, int op_depth, const char *src_relpath, - int src_op_depth, - svn_node_kind_t src_kind, + int src_del_depth, svn_depth_t src_depth, const char *dst_relpath, - apr_hash_t *src_done, svn_wc__db_t *db, - apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; @@ -2204,8 +2097,6 @@ bump_moved_layer(svn_boolean_t *recurse, svn_skel_t *conflict; svn_boolean_t can_bump; - const char *src_root_relpath = src_relpath; - SVN_ERR(verify_write_lock(wcroot, local_relpath, scratch_pool)); *recurse = FALSE; @@ -2214,7 +2105,7 @@ bump_moved_layer(svn_boolean_t *recurse, STMT_HAS_LAYER_BETWEEN)); SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id, local_relpath, - op_depth, src_op_depth)); + op_depth, src_del_depth)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); SVN_ERR(svn_sqlite__reset(stmt)); @@ -2243,34 +2134,36 @@ bump_moved_layer(svn_boolean_t *recurse, can_bump = FALSE; } - if (!can_bump) - { - SVN_ERR(bump_mark_tree_conflict(wcroot, src_relpath, - src_root_relpath, dst_relpath, - db, scratch_pool)); - - return SVN_NO_ERROR; - } - - while (relpath_depth(src_root_relpath) > src_op_depth) - src_root_relpath = svn_relpath_dirname(src_root_relpath, scratch_pool); - - - if (svn_hash_gets(src_done, src_relpath)) - return SVN_NO_ERROR; - - svn_hash_sets(src_done, apr_pstrdup(result_pool, src_relpath), ""); - - SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, wcroot, - src_root_relpath, - scratch_pool, scratch_pool)); + { + const char *src_root_relpath = src_relpath; + while (relpath_depth(src_root_relpath) > src_del_depth) + src_root_relpath = svn_relpath_dirname(src_root_relpath, scratch_pool); + + if (!can_bump) + { + SVN_ERR(bump_mark_tree_conflict(wcroot, src_relpath, + src_root_relpath, dst_relpath, + db, scratch_pool)); + + return SVN_NO_ERROR; + } + + SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, wcroot, + src_root_relpath, + scratch_pool, scratch_pool)); + } /* ### TODO: check this is the right sort of tree-conflict? */ if (!conflict) { /* ### TODO: verify moved_here? */ - SVN_ERR(replace_moved_layer(src_relpath, dst_relpath, - op_depth, wcroot, scratch_pool)); + + SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool)); + + SVN_ERR(svn_wc__db_op_copy_layer_internal(wcroot, + src_relpath, op_depth, + dst_relpath, NULL, NULL, + scratch_pool)); *recurse = TRUE; } @@ -2278,28 +2171,34 @@ bump_moved_layer(svn_boolean_t *recurse, return SVN_NO_ERROR; } +/* Internal storage for bump_moved_away() */ +struct bump_pair_t +{ + const char *src_relpath; + const char *dst_relpath; + int src_del_op_depth; + svn_node_kind_t src_kind; +}; /* Bump moves of LOCAL_RELPATH and all its descendants that were originally below LOCAL_RELPATH at op-depth OP_DEPTH. - - SRC_DONE is a hash with keys that are 'const char *' relpaths - that have already been bumped. Any bumped paths are added to - SRC_DONE. */ + */ static svn_error_t * bump_moved_away(svn_wc__db_wcroot_t *wcroot, const char *local_relpath, int op_depth, - apr_hash_t *src_done, svn_depth_t depth, svn_wc__db_t *db, - apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; apr_pool_t *iterpool; - svn_error_t *err = NULL; + int i; + apr_array_header_t *pairs = apr_array_make(scratch_pool, 32, + sizeof(struct bump_pair_t*)); + /* Build an array, as we can't execute the same Sqlite query recursively */ iterpool = svn_pool_create(scratch_pool); SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, @@ -2309,51 +2208,52 @@ bump_moved_away(svn_wc__db_wcroot_t *wcr SVN_ERR(svn_sqlite__step(&have_row, stmt)); while(have_row) { - const char *src_relpath, *dst_relpath; - int src_op_depth; - svn_node_kind_t src_kind; - svn_depth_t src_depth; + struct bump_pair_t *bp = apr_pcalloc(scratch_pool, sizeof(*bp)); + + bp->src_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool); + bp->dst_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool); + bp->src_del_op_depth = svn_sqlite__column_int(stmt, 2); + bp->src_kind = svn_sqlite__column_token(stmt, 3, kind_map); + + APR_ARRAY_PUSH(pairs, struct bump_pair_t *) = bp; + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + } + + SVN_ERR(svn_sqlite__reset(stmt)); + + for (i = 0; i < pairs->nelts; i++) + { + struct bump_pair_t *bp = APR_ARRAY_IDX(pairs, i, struct bump_pair_t *); svn_boolean_t skip; + svn_depth_t src_wc_depth; svn_pool_clear(iterpool); - src_relpath = svn_sqlite__column_text(stmt, 0, iterpool); - dst_relpath = svn_sqlite__column_text(stmt, 1, iterpool); - src_op_depth = svn_sqlite__column_int(stmt, 2); - src_kind = svn_sqlite__column_token(stmt, 3, kind_map); - err = check_bump_layer(&skip, &src_depth, local_relpath, depth, - src_relpath, src_kind, iterpool); - - if (err) - break; + SVN_ERR(check_bump_layer(&skip, &src_wc_depth, local_relpath, depth, + bp->src_relpath, bp->src_kind, iterpool)); if (!skip) { svn_boolean_t recurse; - err = bump_moved_layer(&recurse, wcroot, - local_relpath, op_depth, - src_relpath, src_op_depth, src_kind, src_depth, - dst_relpath, - src_done, db, result_pool, iterpool); - - if (!err && recurse) - err = bump_moved_away(wcroot, dst_relpath, relpath_depth(dst_relpath), - src_done, depth, db, result_pool, iterpool); + SVN_ERR(bump_moved_layer(&recurse, wcroot, + local_relpath, op_depth, + bp->src_relpath, bp->src_del_op_depth, + src_wc_depth, bp->dst_relpath, + db, iterpool)); + + if (recurse) + SVN_ERR(bump_moved_away(wcroot, bp->dst_relpath, + relpath_depth(bp->dst_relpath), + depth, db, iterpool)); } - - if (err) - break; - - SVN_ERR(svn_sqlite__step(&have_row, stmt)); } - err = svn_error_compose_create(err, svn_sqlite__reset(stmt)); - svn_pool_destroy(iterpool); - return svn_error_trace(err); + return SVN_NO_ERROR; } svn_error_t * @@ -2363,8 +2263,6 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc svn_wc__db_t *db, apr_pool_t *scratch_pool) { - apr_hash_t *src_done; - SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, STMT_CREATE_UPDATE_MOVE_LIST)); @@ -2409,9 +2307,7 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc } } - src_done = apr_hash_make(scratch_pool); - SVN_ERR(bump_moved_away(wcroot, local_relpath, 0, src_done, depth, db, - scratch_pool, scratch_pool)); + SVN_ERR(bump_moved_away(wcroot, local_relpath, 0, depth, db, scratch_pool)); return SVN_NO_ERROR; } @@ -2445,19 +2341,27 @@ resolve_delete_raise_moved_away(svn_wc__ svn_node_kind_t src_kind = svn_sqlite__column_token(stmt, 1, kind_map); const char *dst_relpath = svn_sqlite__column_text(stmt, 2, NULL); const char *src_repos_relpath = svn_sqlite__column_text(stmt, 3, NULL); + svn_skel_t *conflict; svn_pool_clear(iterpool); SVN_ERR_ASSERT(src_repos_relpath != NULL); - err = mark_tree_conflict(src_relpath, - wcroot, db, old_version, new_version, - dst_relpath, operation, - src_kind /* ### old kind */, - src_kind /* ### new kind */, - src_repos_relpath, - svn_wc_conflict_reason_moved_away, - action, local_relpath, - iterpool); + err = create_tree_conflict(&conflict, wcroot, src_relpath, dst_relpath, + db, old_version, new_version, operation, + src_kind /* ### old kind */, + src_kind /* ### new kind */, + src_repos_relpath, + svn_wc_conflict_reason_moved_away, + action, local_relpath, + iterpool, iterpool); + + if (!err) + err = update_move_list_add(wcroot, src_relpath, + svn_wc_notify_tree_conflict, + src_kind, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, NULL, scratch_pool); if (err) return svn_error_compose_create(err, svn_sqlite__reset(stmt)); @@ -2605,7 +2509,8 @@ break_moved_away_children_internal(svn_w svn_wc_notify_move_broken, svn_node_unknown, svn_wc_notify_state_inapplicable, - svn_wc_notify_state_inapplicable); + svn_wc_notify_state_inapplicable, + NULL, NULL, scratch_pool); } if (err)
Modified: subversion/branches/pin-externals/subversion/svn/conflict-callbacks.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svn/conflict-callbacks.c?rev=1658128&r1=1658127&r2=1658128&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/svn/conflict-callbacks.c (original) +++ subversion/branches/pin-externals/subversion/svn/conflict-callbacks.c Sun Feb 8 03:10:25 2015 @@ -792,7 +792,7 @@ handle_text_conflict(svn_wc_conflict_res else if (strcmp(opt->code, "df") == 0) { /* Re-check preconditions. */ - if (! diff_allowed || desc->my_abspath) + if (! diff_allowed || ! desc->my_abspath) { SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, _("Invalid option; there's no " Modified: subversion/branches/pin-externals/subversion/svn/notify.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svn/notify.c?rev=1658128&r1=1658127&r2=1658128&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/svn/notify.c (original) +++ subversion/branches/pin-externals/subversion/svn/notify.c Sun Feb 8 03:10:25 2015 @@ -52,7 +52,7 @@ struct notify_baton svn_boolean_t is_export; svn_boolean_t is_wc_to_repos_copy; svn_boolean_t sent_first_txdelta; - svn_boolean_t in_external; + int in_external; svn_boolean_t had_print_error; /* Used to not keep printing error messages when we've already had one print error. */ @@ -636,7 +636,7 @@ notify_body(struct notify_baton *nb, case svn_wc_notify_update_external: /* Remember that we're now "inside" an externals definition. */ - nb->in_external = TRUE; + ++nb->in_external; /* Currently this is used for checkouts and switches too. If we want different output, we'll have to add new actions. */ @@ -653,7 +653,7 @@ notify_body(struct notify_baton *nb, if (nb->in_external) { svn_handle_warning2(stderr, n->err, "svn: "); - nb->in_external = FALSE; + --nb->in_external; SVN_ERR(svn_cmdline_printf(pool, "\n")); } /* Otherwise, we'll just print two warnings. Why? Because @@ -752,7 +752,7 @@ notify_body(struct notify_baton *nb, if (nb->in_external) { - nb->in_external = FALSE; + --nb->in_external; SVN_ERR(svn_cmdline_printf(pool, "\n")); } break; @@ -1117,7 +1117,7 @@ svn_cl__get_notifier(svn_wc_notify_func2 nb->is_checkout = FALSE; nb->is_export = FALSE; nb->is_wc_to_repos_copy = FALSE; - nb->in_external = FALSE; + nb->in_external = 0; nb->had_print_error = FALSE; nb->conflict_stats = conflict_stats; SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool)); Modified: subversion/branches/pin-externals/subversion/svnrdump/load_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnrdump/load_editor.c?rev=1658128&r1=1658127&r2=1658128&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/svnrdump/load_editor.c (original) +++ subversion/branches/pin-externals/subversion/svnrdump/load_editor.c Sun Feb 8 03:10:25 2015 @@ -786,7 +786,7 @@ set_node_property(void *baton, prop = apr_palloc(nb->rb->pool, sizeof (*prop)); prop->name = apr_pstrdup(pool, name); - prop->value = value ? svn_string_dup(value, pool) : NULL; + prop->value = svn_string_dup(value, pool); svn_hash_sets(nb->prop_changes, prop->name, prop); return SVN_NO_ERROR;
