Author: gstein Date: Mon May 10 19:10:48 2010 New Revision: 942851 URL: http://svn.apache.org/viewvc?rev=942851&view=rev Log: Rebuild svn_wc_add_repos_file4() in terms of svn_wc__db_op_copy_file(). This is now a Proper function, using wc_db as it should.
* subversion/libsvn_wc/update_editor.c: (svn_wc_add_repos_file4): gut this thing, removing all the entry usage, a couple hacky DB "temp" calls, and the direct queuing of work. instead, make the (two) wc_db calls and have it queue the related work. * subversion/libsvn_wc/wc_db.c: (svn_wc__db_op_copy_dir, svn_wc__db_op_copy_file, svn_wc__db_op_copy_symlink): correct the handling of ORIGINAL_*. if it is nil, then we do NOT want to create/fetch a repos_id. Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c subversion/trunk/subversion/libsvn_wc/wc_db.c Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=942851&r1=942850&r2=942851&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/update_editor.c (original) +++ subversion/trunk/subversion/libsvn_wc/update_editor.c Mon May 10 19:10:48 2010 @@ -5894,7 +5894,12 @@ svn_wc_add_repos_file4(svn_wc_context_t svn_checksum_t *base_checksum; struct last_change_info *last_change = NULL; const char *source_abspath = NULL; + svn_skel_t *all_work_items; svn_skel_t *work_item; + const char *original_root_url; + const char *original_repos_relpath; + const char *original_uuid; + apr_hash_t *actual_props; SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); SVN_ERR_ASSERT(new_base_contents != NULL); @@ -5905,20 +5910,36 @@ svn_wc_add_repos_file4(svn_wc_context_t /* Fabricate the anticipated new URL of the target and check the copyfrom URL to be in the same repository. */ - { - const char *repos_root; + if (copyfrom_url != NULL) + { + const char *relative_url; - /* Find the repository_root via the parent directory, which - is always versioned before this function is called */ - SVN_ERR(svn_wc__node_get_repos_info(&repos_root, NULL, wc_ctx, - dir_abspath, TRUE, FALSE, pool, pool)); - - if (copyfrom_url && !svn_uri_is_ancestor(repos_root, copyfrom_url)) - return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, - _("Copyfrom-url '%s' has different repository" - " root than '%s'"), - copyfrom_url, repos_root); - } + /* Find the repository_root via the parent directory, which + is always versioned before this function is called */ + SVN_ERR(svn_wc__node_get_repos_info(&original_root_url, + &original_uuid, + wc_ctx, + dir_abspath, + TRUE /* scan_added */, + FALSE /* scan_deleted */, + pool, pool)); + + if (!svn_uri_is_ancestor(original_root_url, copyfrom_url)) + return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, + _("Copyfrom-url '%s' has different repository" + " root than '%s'"), + copyfrom_url, original_root_url); + + relative_url = svn_uri_skip_ancestor(original_root_url, copyfrom_url); + original_repos_relpath = svn_path_uri_decode(relative_url, pool); + } + else + { + original_root_url = NULL; + original_repos_relpath = NULL; + original_uuid = NULL; + copyfrom_rev = SVN_INVALID_REVNUM; /* Just to be sure. */ + } /* If we're replacing the file then we need to save the destination file's original text base and prop base before replacing it. This allows us to @@ -5971,59 +5992,6 @@ svn_wc_add_repos_file4(svn_wc_context_t } } - /* Schedule this for addition first, before the entry exists. - * Otherwise we'll get bounced out with an error about scheduling - * an already-versioned item for addition. - */ - { - svn_wc_entry_t tmp_entry; - int modify_flags = SVN_WC__ENTRY_MODIFY_SCHEDULE; - - tmp_entry.schedule = svn_wc_schedule_add; - - if (copyfrom_url) - { - SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(copyfrom_rev)); - - tmp_entry.copyfrom_url = copyfrom_url; - tmp_entry.copyfrom_rev = copyfrom_rev; - tmp_entry.copied = TRUE; - - modify_flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_URL - | SVN_WC__ENTRY_MODIFY_COPYFROM_REV - | SVN_WC__ENTRY_MODIFY_COPIED; - } - - SVN_ERR(svn_wc__loggy_entry_modify(&work_item, db, dir_abspath, - local_abspath, &tmp_entry, - modify_flags, pool)); - SVN_ERR(svn_wc__db_wq_add(db, dir_abspath, work_item, pool)); - } - - /* ### Clear working node status in preparation for writing a new node. */ - { - svn_wc_entry_t tmp_entry; - - tmp_entry.kind = svn_node_file; - /* Indicate the file was locally modified and we didn't get to - calculate the true value, but we can't set it to UNKNOWN (-1), - because that would indicate absense of this value. - If it isn't locally modified, - we'll overwrite with the actual value later. */ - tmp_entry.working_size = SVN_WC_ENTRY_WORKING_SIZE_UNKNOWN; - /* The same is true for the TEXT_TIME field, except that that doesn't - have an explicid 'changed' value, so we set the value to 'undefined'. */ - tmp_entry.text_time = 0; - - SVN_ERR(svn_wc__loggy_entry_modify(&work_item, db, dir_abspath, - local_abspath, &tmp_entry, - SVN_WC__ENTRY_MODIFY_KIND - | SVN_WC__ENTRY_MODIFY_TEXT_TIME - | SVN_WC__ENTRY_MODIFY_WORKING_SIZE, - pool)); - SVN_ERR(svn_wc__db_wq_add(db, dir_abspath, work_item, pool)); - } - /* Update LAST_CHANGE to reflect the entry props in NEW_BASE_PROPS, and filter NEW_BASE_PROPS so it contains only regular props. */ { @@ -6043,10 +6011,37 @@ svn_wc_add_repos_file4(svn_wc_context_t } /* Add some work items to install the properties. */ - SVN_ERR(svn_wc__install_props(db, local_abspath, svn_wc__db_kind_file, - new_base_props, - new_props ? new_props : new_base_props, - TRUE, pool)); + { + SVN_ERR(build_write_base_props(&all_work_items, + local_abspath, svn_wc__db_kind_file, + new_base_props, pool)); + + if (new_props == NULL) + { + actual_props = NULL; + } + else + { + apr_array_header_t *prop_diffs; + + SVN_ERR(svn_prop_diffs(&prop_diffs, new_props, new_base_props, + pool)); + if (prop_diffs->nelts == 0) + actual_props = NULL; + else + actual_props = new_props; + } + + /* ### ideally, this would be queued to go along with the call to + ### db_op_set_props(), but we need correct ACTUAL props for some + ### of the work associated with creation of the WORKING node. + ### so... we'll lump it all together, and queue it on the set_props + ### (ie. all database state is correct/final). */ + SVN_ERR(build_write_actual_props(&work_item, local_abspath, + svn_wc__db_kind_file, + actual_props, pool)); + all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool); + } /* Copy NEW_BASE_CONTENTS into a temporary file so our log can refer to it, and set TMP_TEXT_BASE_ABSPATH to its path. Compute its MD5 @@ -6093,37 +6088,9 @@ svn_wc_add_repos_file4(svn_wc_context_t SVN_ERR(svn_wc__loggy_move(&work_item, db, dir_abspath, tmp_text_base_abspath, text_base_abspath, pool)); - SVN_ERR(svn_wc__db_wq_add(db, dir_abspath, work_item, pool)); - - /* ### execute the work items which construct the node, allowing the - ### wc_db operation to tweak the WORKING_NODE row. these values - ### should be set some other way. */ - SVN_ERR(svn_wc__wq_run(db, dir_abspath, - cancel_func, cancel_baton, - pool)); - SVN_ERR(svn_wc__db_temp_op_set_working_checksum(db, local_abspath, - base_checksum, pool)); + all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool); } - /* ### HACK: The following code should be performed in the same transaction as the install */ - if (last_change) - { - /* ### execute the work items which construct the node, allowing the - ### wc_db operation to tweak the WORKING_NODE row. these values - ### should be set some other way. */ - SVN_ERR(svn_wc__wq_run(db, dir_abspath, - cancel_func, cancel_baton, - pool)); - SVN_ERR(svn_wc__db_temp_op_set_working_last_change( - db, local_abspath, - last_change->cmt_rev, - last_change->cmt_date, - last_change->cmt_author, - pool)); - } - - /* ### /HACK */ - /* For added files without NEW_CONTENTS, then generate the working file from the provided "pristine" contents. */ if (new_contents == NULL && copyfrom_url == NULL) @@ -6148,11 +6115,7 @@ svn_wc_add_repos_file4(svn_wc_context_t FALSE /* use_commit_times */, record_fileinfo, pool, pool)); - /* ### we should pass WORK_ITEM to some wc_db api that constructs - ### this new node. but alas, we do so much of this in pieces, - ### and not using wc_db apis. so just manually add the work item - ### into the queue. */ - SVN_ERR(svn_wc__db_wq_add(db, local_abspath, work_item, pool)); + all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool); /* If we installed from somewhere besides the official pristine, then it is a temporary file, which needs to be removed. */ @@ -6161,14 +6124,37 @@ svn_wc_add_repos_file4(svn_wc_context_t SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db, source_abspath, pool, pool)); - /* ### we should pass WORK_ITEM to some wc_db api that constructs - ### this new node. but alas, we do so much of this in pieces, - ### and not using wc_db apis. so just manually add the work item - ### into the queue. */ - SVN_ERR(svn_wc__db_wq_add(db, local_abspath, work_item, pool)); + all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool); } } + /* ### ideally, we would have a single DB operation, and queue the work + ### items on that. for now, we'll queue them with the second call. */ + + SVN_ERR(svn_wc__db_op_copy_file(db, local_abspath, + new_base_props, + last_change + ? last_change->cmt_rev + : SVN_INVALID_REVNUM, + last_change ? last_change->cmt_date : 0, + last_change ? last_change->cmt_author : NULL, + original_repos_relpath, + original_root_url, + original_uuid, + copyfrom_rev, + base_checksum, + NULL /* conflict */, + NULL /* work_items */, + pool)); + + /* ### if below fails, then the above db change would remain :-( */ + + SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, + actual_props, + NULL /* conflict */, + all_work_items, + pool)); + return svn_error_return(svn_wc__wq_run(db, dir_abspath, cancel_func, cancel_baton, pool)); Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=942851&r1=942850&r2=942851&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db.c (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db.c Mon May 10 19:10:48 2010 @@ -1469,6 +1469,7 @@ insert_working_node(void *baton, SVN_ERR(svn_sqlite__bind_properties(stmt, 18, piwb->props, scratch_pool)); /* Do not bind 'keep_local' (19). */ + /* 'symlink_target' (20) is bound above. */ SVN_ERR(svn_sqlite__insert(NULL, stmt)); @@ -2759,7 +2760,6 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db, svn_wc__db_pdh_t *pdh; const char *local_relpath; insert_working_baton_t iwb; - apr_int64_t original_repos_id; SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); SVN_ERR_ASSERT(props != NULL); @@ -2775,10 +2775,6 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db, scratch_pool, scratch_pool)); VERIFY_USABLE_PDH(pdh); - SVN_ERR(create_repos_id(&original_repos_id, - original_root_url, original_uuid, - pdh->wcroot->sdb, scratch_pool)); - blank_iwb(&iwb); iwb.presence = svn_wc__db_status_normal; @@ -2790,11 +2786,17 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db, iwb.changed_rev = changed_rev; iwb.changed_date = changed_date; iwb.changed_author = changed_author; - iwb.original_repos_id = original_repos_id; - iwb.original_repos_relpath = original_repos_relpath; - iwb.original_revnum = original_revision; iwb.moved_here = FALSE; + if (original_root_url != NULL) + { + SVN_ERR(create_repos_id(&iwb.original_repos_id, + original_root_url, original_uuid, + pdh->wcroot->sdb, scratch_pool)); + iwb.original_repos_relpath = original_repos_relpath; + iwb.original_revnum = original_revision; + } + iwb.children = children; iwb.depth = depth; @@ -2853,7 +2855,6 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db svn_wc__db_pdh_t *pdh; const char *local_relpath; insert_working_baton_t iwb; - apr_int64_t original_repos_id; SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); SVN_ERR_ASSERT(props != NULL); @@ -2867,10 +2868,6 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db scratch_pool, scratch_pool)); VERIFY_USABLE_PDH(pdh); - SVN_ERR(create_repos_id(&original_repos_id, - original_root_url, original_uuid, - pdh->wcroot->sdb, scratch_pool)); - blank_iwb(&iwb); iwb.presence = svn_wc__db_status_normal; @@ -2882,11 +2879,17 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db iwb.changed_rev = changed_rev; iwb.changed_date = changed_date; iwb.changed_author = changed_author; - iwb.original_repos_id = original_repos_id; - iwb.original_repos_relpath = original_repos_relpath; - iwb.original_revnum = original_revision; iwb.moved_here = FALSE; + if (original_root_url != NULL) + { + SVN_ERR(create_repos_id(&iwb.original_repos_id, + original_root_url, original_uuid, + pdh->wcroot->sdb, scratch_pool)); + iwb.original_repos_relpath = original_repos_relpath; + iwb.original_revnum = original_revision; + } + iwb.checksum = checksum; iwb.work_items = work_items; @@ -2919,7 +2922,6 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t svn_wc__db_pdh_t *pdh; const char *local_relpath; insert_working_baton_t iwb; - apr_int64_t original_repos_id; SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); SVN_ERR_ASSERT(props != NULL); @@ -2933,10 +2935,6 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t scratch_pool, scratch_pool)); VERIFY_USABLE_PDH(pdh); - SVN_ERR(create_repos_id(&original_repos_id, - original_root_url, original_uuid, - pdh->wcroot->sdb, scratch_pool)); - blank_iwb(&iwb); iwb.presence = svn_wc__db_status_normal; @@ -2948,11 +2946,17 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t iwb.changed_rev = changed_rev; iwb.changed_date = changed_date; iwb.changed_author = changed_author; - iwb.original_repos_id = original_repos_id; - iwb.original_repos_relpath = original_repos_relpath; - iwb.original_revnum = original_revision; iwb.moved_here = FALSE; + if (original_root_url != NULL) + { + SVN_ERR(create_repos_id(&iwb.original_repos_id, + original_root_url, original_uuid, + pdh->wcroot->sdb, scratch_pool)); + iwb.original_repos_relpath = original_repos_relpath; + iwb.original_revnum = original_revision; + } + iwb.target = target; iwb.work_items = work_items;