Propchange: subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_subr/svn_temp_serializer.c ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Sun Dec 14 11:44:03 2014 @@ -1,4 +1,6 @@ +/subversion/branches/1.7.x/subversion/libsvn_subr/svn_temp_serializer.c:1480943-1645438 /subversion/branches/1.7.x-issue4087/subversion/libsvn_subr/svn_temp_serializer.c:1243707-1336073 +/subversion/branches/1.7.x-issue4153/subversion/libsvn_subr/svn_temp_serializer.c:1309894-1539233 /subversion/branches/1.7.x-issue4169/subversion/libsvn_subr/svn_temp_serializer.c:1330537-1336116 /subversion/branches/1.7.x-r1210147/subversion/libsvn_subr/svn_temp_serializer.c:1213310-1293110 /subversion/branches/1.7.x-r1423646/subversion/libsvn_subr/svn_temp_serializer.c:1423647-1424282
Modified: subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/adm_ops.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/adm_ops.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/adm_ops.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/adm_ops.c Sun Dec 14 11:44:03 2014 @@ -1405,12 +1405,17 @@ revert_restore_handle_copied_dirs(svn_bo /* Make the working tree under LOCAL_ABSPATH to depth DEPTH match the versioned tree. This function is called after svn_wc__db_op_revert has done the database revert and created the revert list. Notifies - for all paths equal to or below LOCAL_ABSPATH that are reverted. */ + for all paths equal to or below LOCAL_ABSPATH that are reverted. + + REVERT_ROOT is true for explicit revert targets and FALSE for targets + reached via recursion. + */ static svn_error_t * revert_restore(svn_wc__db_t *db, const char *local_abspath, svn_depth_t depth, svn_boolean_t use_commit_times, + svn_boolean_t revert_root, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, @@ -1434,10 +1439,31 @@ revert_restore(svn_wc__db_t *db, #endif svn_boolean_t copied_here; svn_wc__db_kind_t reverted_kind; + svn_boolean_t is_wcroot; if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); + SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, scratch_pool)); + if (is_wcroot && !revert_root) + { + /* Issue #4162: Obstructing working copy. We can't access the working + copy data from the parent working copy for this node by just using + local_abspath */ + + if (notify_func) + { + svn_wc_notify_t *notify = svn_wc_create_notify( + local_abspath, + svn_wc_notify_update_skip_obstruction, + scratch_pool); + + notify_func(notify_baton, notify, scratch_pool); + } + + return SVN_NO_ERROR; /* We don't revert obstructing working copies */ + } + SVN_ERR(svn_wc__db_revert_list_read(¬ify_required, &conflict_old, &conflict_new, &conflict_working, &prop_reject, @@ -1743,7 +1769,7 @@ revert_restore(svn_wc__db_t *db, iterpool); SVN_ERR(revert_restore(db, child_abspath, depth, - use_commit_times, + use_commit_times, FALSE /* revert root */, cancel_func, cancel_baton, notify_func, notify_baton, iterpool)); @@ -1795,7 +1821,7 @@ new_revert_internal(svn_wc__db_t *db, if (!err) err = revert_restore(db, local_abspath, depth, - use_commit_times, + use_commit_times, TRUE /* revert root */, cancel_func, cancel_baton, notify_func, notify_baton, scratch_pool); Modified: subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/diff_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/diff_editor.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/diff_editor.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/diff_editor.c Sun Dec 14 11:44:03 2014 @@ -1281,11 +1281,10 @@ add_directory(const char *path, dir_pool); *child_baton = db; - /* Add this path to the parent directory's list of elements that - have been compared. */ - apr_hash_set(pb->compared, apr_pstrdup(pb->pool, db->path), - APR_HASH_KEY_STRING, ""); - + /* Issue #3797: Don't add this filename to the parent directory's list of + elements that have been compared, to show local additions via the local + diff. The repository node is unrelated from the working copy version + (similar to not-present in the working copy) */ return SVN_NO_ERROR; } @@ -1430,10 +1429,10 @@ add_file(const char *path, fb = make_file_baton(path, TRUE, pb, file_pool); *file_baton = fb; - /* Add this filename to the parent directory's list of elements that - have been compared. */ - apr_hash_set(pb->compared, apr_pstrdup(pb->pool, path), - APR_HASH_KEY_STRING, ""); + /* Issue #3797: Don't add this filename to the parent directory's list of + elements that have been compared, to show local additions via the local + diff. The repository node is unrelated from the working copy version + (similar to not-present in the working copy) */ return SVN_NO_ERROR; } Modified: subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/diff_local.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/diff_local.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/diff_local.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/diff_local.c Sun Dec 14 11:44:03 2014 @@ -204,11 +204,10 @@ file_diff(struct diff_baton *eb, the latter two have corresponding pristine info to diff against. */ if (status == svn_wc__db_status_added) SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL, - &original_repos_relpath, NULL, NULL, + NULL, NULL, NULL, NULL, db, local_abspath, scratch_pool, scratch_pool)); - SVN_ERR(get_empty_file(eb, &empty_file, scratch_pool)); /* When we show a delete, we show a diff of the original pristine against Modified: subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/old-and-busted.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/old-and-busted.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/old-and-busted.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/old-and-busted.c Sun Dec 14 11:44:03 2014 @@ -810,11 +810,15 @@ atts_to_entry(svn_wc_entry_t **new_entry ### not used by loggy; no need to set MODIFY_FLAGS */ entry->url = extract_string(atts, ENTRIES_ATTR_URL, pool); + if (entry->url) + entry->url = svn_uri_canonicalize(entry->url, pool); /* Set up repository root. Make sure it is a prefix of url. ### not used by loggy; no need to set MODIFY_FLAGS */ entry->repos = extract_string(atts, ENTRIES_ATTR_REPOS, pool); + if (entry->repos) + entry->repos = svn_uri_canonicalize(entry->repos, pool); if (entry->url && entry->repos && !svn_uri__is_ancestor(entry->repos, entry->url)) Modified: subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/update_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/update_editor.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/update_editor.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/update_editor.c Sun Dec 14 11:44:03 2014 @@ -1579,16 +1579,29 @@ check_tree_conflict(svn_wc_conflict_desc if (reason == svn_wc_conflict_reason_edited || reason == svn_wc_conflict_reason_deleted || reason == svn_wc_conflict_reason_replaced) - /* When the node existed before (it was locally deleted, replaced or - * edited), then 'update' cannot add it "again". So it can only send - * _action_edit, _delete or _replace. */ - SVN_ERR_ASSERT(action == svn_wc_conflict_action_edit - || action == svn_wc_conflict_action_delete - || action == svn_wc_conflict_action_replace); + { + /* When the node existed before (it was locally deleted, replaced or + * edited), then 'update' cannot add it "again". So it can only send + * _action_edit, _delete or _replace. */ + if (action != svn_wc_conflict_action_edit + && action != svn_wc_conflict_action_delete + && action != svn_wc_conflict_action_replace) + return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL, + _("Unexpected attempt to add a node at path '%s'"), + svn_dirent_local_style(local_abspath, scratch_pool)); + } else if (reason == svn_wc_conflict_reason_added) - /* When the node did not exist before (it was locally added), then 'update' - * cannot want to modify it in any way. It can only send _action_add. */ - SVN_ERR_ASSERT(action == svn_wc_conflict_action_add); + { + /* When the node did not exist before (it was locally added), + * then 'update' cannot want to modify it in any way. + * It can only send _action_add. */ + if (action != svn_wc_conflict_action_add) + return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL, + _("Unexpected attempt to edit, delete, or replace " + "a node at path '%s'"), + svn_dirent_local_style(local_abspath, scratch_pool)); + + } /* A conflict was detected. Append log commands to the log accumulator Modified: subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/wc_db.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/wc_db.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_wc/wc_db.c Sun Dec 14 11:44:03 2014 @@ -3308,8 +3308,9 @@ get_info_for_copy(apr_int64_t *copyfrom_ svn_wc__db_kind_t *kind, svn_boolean_t *op_root, svn_boolean_t *have_work, - svn_wc__db_wcroot_t *wcroot, + svn_wc__db_wcroot_t *src_wcroot, const char *local_relpath, + svn_wc__db_wcroot_t *dst_wcroot, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -3322,7 +3323,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ NULL /* have_base */, NULL /* have_more_work */, have_work, - wcroot, local_relpath, result_pool, scratch_pool)); + src_wcroot, local_relpath, result_pool, scratch_pool)); if (*status == svn_wc__db_status_excluded) { @@ -3339,7 +3340,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ &parent_status, &parent_kind, NULL, &parent_have_work, - wcroot, parent_relpath, + src_wcroot, parent_relpath, dst_wcroot, scratch_pool, scratch_pool)); if (*copyfrom_relpath) *copyfrom_relpath = svn_relpath_join(*copyfrom_relpath, base_name, @@ -3352,7 +3353,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ SVN_ERR(scan_addition(NULL, &op_root_relpath, NULL, NULL, /* repos_* */ copyfrom_relpath, copyfrom_id, copyfrom_rev, - wcroot, local_relpath, + src_wcroot, local_relpath, scratch_pool, scratch_pool)); if (*copyfrom_relpath) { @@ -3368,7 +3369,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ const char *base_del_relpath, *work_del_relpath; SVN_ERR(scan_deletion(&base_del_relpath, NULL, &work_del_relpath, - wcroot, local_relpath, scratch_pool, + src_wcroot, local_relpath, scratch_pool, scratch_pool)); if (work_del_relpath) { @@ -3381,7 +3382,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ SVN_ERR(scan_addition(NULL, &op_root_relpath, NULL, NULL, /* repos_* */ copyfrom_relpath, copyfrom_id, copyfrom_rev, - wcroot, parent_del_relpath, + src_wcroot, parent_del_relpath, scratch_pool, scratch_pool)); *copyfrom_relpath = svn_relpath_join(*copyfrom_relpath, @@ -3395,7 +3396,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ copyfrom_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - wcroot, local_relpath, + src_wcroot, local_relpath, result_pool, scratch_pool)); } else @@ -3407,6 +3408,24 @@ get_info_for_copy(apr_int64_t *copyfrom_ *copyfrom_rev = revision; } + if (src_wcroot != dst_wcroot && *copyfrom_relpath) + { + const char *repos_root_url; + const char *repos_uuid; + + /* Pass the right repos-id for the destination db. We can't just use + the id of the source database, as this value can change after + relocation (and perhaps also when we start storing multiple + working copies in a single db)! */ + + SVN_ERR(fetch_repos_info(&repos_root_url, &repos_uuid, + src_wcroot->sdb, *copyfrom_id, + scratch_pool)); + + SVN_ERR(create_repos_id(copyfrom_id, repos_root_url, repos_uuid, + dst_wcroot->sdb, scratch_pool)); + } + return SVN_NO_ERROR; } @@ -3455,7 +3474,8 @@ db_op_copy(svn_wc__db_wcroot_t *src_wcro SVN_ERR(get_info_for_copy(©from_id, ©from_relpath, ©from_rev, &status, &kind, &op_root, &have_work, src_wcroot, - src_relpath, scratch_pool, scratch_pool)); + src_relpath, dst_wcroot, + scratch_pool, scratch_pool)); SVN_ERR(op_depth_for_copy(&dst_op_depth, &dst_np_op_depth, copyfrom_id, copyfrom_relpath, copyfrom_rev, Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/dav_svn.h URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/dav_svn.h?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/dav_svn.h (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/dav_svn.h Sun Dec 14 11:44:03 2014 @@ -841,6 +841,12 @@ dav_svn__simple_parse_uri(dav_svn__uri_i const char *uri, apr_pool_t *pool); +/* Test the request R to determine if we should return the list of + * repositories at the parent path. Only true if SVNListParentPath directive + * is 'on' and the request is for our configured root path. */ +svn_boolean_t +dav_svn__is_parentpath_list(request_rec *r); + int dav_svn__find_ns(const apr_array_header_t *namespaces, const char *uri); Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/mod_dav_svn.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/mod_dav_svn.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/mod_dav_svn.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/mod_dav_svn.c Sun Dec 14 11:44:03 2014 @@ -924,7 +924,95 @@ static int dav_svn__handler(request_rec return DECLINED; } +#define NO_MAP_TO_STORAGE_NOTE "dav_svn-no-map-to-storage" +/* Fill the filename on the request with a bogus path since we aren't serving + * a file off the disk. This means that <Directory> blocks will not match and + * that %f in logging formats will show as "svn:/path/to/repo/path/in/repo". */ +static int dav_svn__translate_name(request_rec *r) +{ + const char *fs_path, *repos_basename, *repos_path, *slash; + const char *ignore_cleaned_uri, *ignore_relative_path; + int ignore_had_slash; + dir_conf_t *conf = ap_get_module_config(r->per_dir_config, &dav_svn_module); + + /* module is not configured, bail out early */ + if (!conf->fs_path && !conf->fs_parent_path) + return DECLINED; + + if (dav_svn__is_parentpath_list(r)) + { + /* SVNListParentPath is on and the request is for the conf->root_dir, + * so just set the repos_basename to an empty string and the repos_path + * to NULL so we end up just reporting our parent path as the bogus + * path. */ + repos_basename = ""; + repos_path = NULL; + } + else + { + /* Retrieve path to repo and within repo for the request */ + dav_error *err = dav_svn_split_uri(r, r->uri, conf->root_dir, + &ignore_cleaned_uri, + &ignore_had_slash, &repos_basename, + &ignore_relative_path, &repos_path); + if (err) + { + dav_svn__log_err(r, err, APLOG_ERR); + return err->status; + } + } + + if (conf->fs_parent_path) + { + fs_path = svn_dirent_join(conf->fs_parent_path, repos_basename, + r->pool); + } + else + { + fs_path = conf->fs_path; + } + + /* Avoid a trailing slash on the bogus path when repos_path is just "/" and + * ensure that there is always a slash between fs_path and repos_path as + * long as the repos_path is not an empty path. */ + slash = ""; + if (repos_path) + { + if ('/' == repos_path[0] && '\0' == repos_path[1]) + repos_path = NULL; + else if ('/' != repos_path[0] && '\0' != repos_path[0]) + slash = "/"; + } + + /* Combine 'svn:', fs_path and repos_path to produce the bogus path we're + * placing in r->filename. We can't use our standard join helpers such + * as svn_dirent_join. fs_path is a dirent and repos_path is a fspath + * (that can be trivially converted to a relpath by skipping the leading + * slash). In general it is safe to join these, but when a path in a + * repository is 'trunk/c:hi' this results in a non canonical dirent on + * Windows. Instead we just cat them together. */ + r->filename = apr_pstrcat(r->pool, + "svn:", fs_path, slash, repos_path, NULL); + + /* Leave a note to ourselves so that we know not to decline in the + * map_to_storage hook. */ + apr_table_setn(r->notes, NO_MAP_TO_STORAGE_NOTE, (const char*)1); + return OK; +} + +/* Prevent core_map_to_storage from running if we prevented the r->filename + * from being set since core_map_to_storage doesn't like r->filename being + * bogus. */ +static int dav_svn__map_to_storage(request_rec *r) +{ + /* Check a note we left in translate_name since map_to_storage doesn't + * have access to our configuration. */ + if (apr_table_get(r->notes, NO_MAP_TO_STORAGE_NOTE)) + return OK; + + return DECLINED; +} @@ -1071,6 +1159,12 @@ register_hooks(apr_pool_t *pconf) ap_register_input_filter("IncomingRewrite", dav_svn__location_in_filter, NULL, AP_FTYPE_CONTENT_SET); ap_hook_fixups(dav_svn__proxy_request_fixup, NULL, NULL, APR_HOOK_MIDDLE); + /* translate_name hook is LAST so that it doesn't interfere with modules + * like mod_alias that are MIDDLE. */ + ap_hook_translate_name(dav_svn__translate_name, NULL, NULL, APR_HOOK_LAST); + /* map_to_storage hook is LAST to avoid interferring with mod_http's + * handling of OPTIONS and TRACE. */ + ap_hook_map_to_storage(dav_svn__map_to_storage, NULL, NULL, APR_HOOK_LAST); } Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/deleted-rev.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/deleted-rev.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/deleted-rev.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/deleted-rev.c Sun Dec 14 11:44:03 2014 @@ -56,6 +56,9 @@ dav_svn__get_deleted_rev_report(const da dav_error *derr = NULL; /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0, Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/file-revs.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/file-revs.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/file-revs.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/file-revs.c Sun Dec 14 11:44:03 2014 @@ -251,6 +251,9 @@ dav_svn__file_revs_report(const dav_reso arb.repos = resource->info->repos; /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); /* ### This is done on other places, but the document element is in this namespace, so is this necessary at all? */ Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/get-location-segments.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/get-location-segments.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/get-location-segments.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/get-location-segments.c Sun Dec 14 11:44:03 2014 @@ -123,6 +123,9 @@ dav_svn__get_location_segments_report(co struct location_segment_baton location_segment_baton; /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/get-locations.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/get-locations.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/get-locations.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/get-locations.c Sun Dec 14 11:44:03 2014 @@ -106,6 +106,9 @@ dav_svn__get_locations_report(const dav_ sizeof(svn_revnum_t)); /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/log.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/log.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/log.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/log.c Sun Dec 14 11:44:03 2014 @@ -307,6 +307,9 @@ dav_svn__log_report(const dav_resource * = apr_array_make(resource->pool, 1, sizeof(const char *)); /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/mergeinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/mergeinfo.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/mergeinfo.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/reports/mergeinfo.c Sun Dec 14 11:44:03 2014 @@ -67,6 +67,9 @@ dav_svn__get_mergeinfo_report(const dav_ = apr_array_make(resource->pool, 0, sizeof(const char *)); /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/repos.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/repos.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/repos.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/repos.c Sun Dec 14 11:44:03 2014 @@ -506,6 +506,9 @@ parse_vtxnstub_uri(dav_resource_combined if (parse_txnstub_uri(comb, path, label, use_checked_in)) return TRUE; + if (!comb->priv.root.txn_name) + return TRUE; + comb->priv.root.vtxn_name = comb->priv.root.txn_name; comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.vtxn_name); @@ -574,6 +577,9 @@ parse_vtxnroot_uri(dav_resource_combined if (parse_txnroot_uri(comb, path, label, use_checked_in)) return TRUE; + if (!comb->priv.root.txn_name) + return TRUE; + comb->priv.root.vtxn_name = comb->priv.root.txn_name; comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.vtxn_name); @@ -919,6 +925,10 @@ prep_working(dav_resource_combined *comb point. */ if (txn_name == NULL) { + if (!comb->priv.root.activity_id) + return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0, + "The request did not specify an activity ID"); + txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.activity_id); if (txn_name == NULL) @@ -1029,8 +1039,13 @@ prep_working(dav_resource_combined *comb static dav_error * prep_activity(dav_resource_combined *comb) { - const char *txn_name = dav_svn__get_txn(comb->priv.repos, - comb->priv.root.activity_id); + const char *txn_name; + + if (!comb->priv.root.activity_id) + return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0, + "The request did not specify an activity ID"); + + txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.activity_id); comb->priv.root.txn_name = txn_name; comb->res.exists = txn_name != NULL; @@ -1788,14 +1803,106 @@ do_out_of_date_check(dav_resource_combin "Could not get created rev of " "resource", r->pool); - if (comb->priv.version_name < created_rev) + if (SVN_IS_VALID_REVNUM(created_rev)) + { + if (comb->priv.version_name < created_rev) + { + serr = svn_error_createf(SVN_ERR_RA_OUT_OF_DATE, NULL, + comb->res.collection + ? "Directory '%s' is out of date" + : (comb->res.exists + ? "File '%s' is out of date" + : "'%s' is out of date"), + comb->priv.repos_path); + return dav_svn__convert_err(serr, HTTP_CONFLICT, + "Attempting to modify out-of-date resource.", + r->pool); + } + } + else if (SVN_IS_VALID_REVNUM(comb->priv.version_name) + && comb->res.collection) { - serr = svn_error_createf(SVN_ERR_RA_OUT_OF_DATE, NULL, - "Item '%s' is out of date", - comb->priv.repos_path); - return dav_svn__convert_err(serr, HTTP_CONFLICT, - "Attempting to modify out-of-date resource.", - r->pool); + /* Issue #4480: With HTTPv2 we can receive the first change for a + directory after it has been made mutable, because one of its + descendants was changed before changing the directory. + + We have to check if whatever the node is in HEAD is equivalent + to what it was in the provided BASE revision. + + If the node was copied, we would process it before its decendants + and we already performed quite a few checks when making it mutable + via its descendant, so what we should really check here is if the + properties changed since the BASE version. + + ### I think svn_fs_node_relation() checks for more changes than we + should check for here. Needs further review. But it looks like\ + this check matches the checks in the libsvn_fs commit editor. + + For now I would say reporting out of date in a few too many + cases is safer than not reporting out of date when we should. + */ + svn_revnum_t youngest; + svn_fs_root_t *youngest_root; + svn_fs_root_t *rev_root; + const svn_fs_id_t *youngest_id; + const svn_fs_id_t *rev_id; + + serr = svn_fs_youngest_rev(&youngest, comb->res.info->repos->fs, + r->pool); + if (serr != NULL) + { + return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, + "Could not determine the youngest " + "revision for verification against " + "the baseline being checked out", + r->pool); + } + + if (comb->priv.version_name == youngest) + return NULL; /* Easy out: we commit against HEAD */ + + serr = svn_fs_revision_root(&youngest_root, comb->res.info->repos->fs, + youngest, r->pool); + + if (!serr) + serr = svn_fs_node_id(&youngest_id, youngest_root, + comb->priv.repos_path, r->pool); + + if (serr != NULL) + { + return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, + "Could not open youngest revision root " + "for verification against the base " + "revision", r->pool); + } + + serr = svn_fs_revision_root(&rev_root, comb->res.info->repos->fs, + comb->priv.version_name, r->pool); + + if (!serr) + serr = svn_fs_node_id(&rev_id, rev_root, + comb->priv.repos_path, r->pool); + + if (serr != NULL) + { + return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, + "Could not open the base revision" + "for verification against the youngest " + "revision", r->pool); + } + + svn_fs_close_root(rev_root); + svn_fs_close_root(youngest_root); + + if (0 != svn_fs_compare_ids(youngest_id, rev_id)) + { + serr = svn_error_createf(SVN_ERR_RA_OUT_OF_DATE, NULL, + "Directory '%s' is out of date", + comb->priv.repos_path); + return dav_svn__convert_err(serr, HTTP_CONFLICT, + "Attempting to modify out-of-date resource.", + r->pool); + } } return NULL; @@ -1957,26 +2064,31 @@ get_resource(request_rec *r, /* Special case: detect and build the SVNParentPath as a unique type of private resource, iff the SVNListParentPath directive is 'on'. */ - if (fs_parent_path && dav_svn__get_list_parentpath_flag(r)) + if (dav_svn__is_parentpath_list(r)) { - char *uri = apr_pstrdup(r->pool, r->uri); - char *parentpath = apr_pstrdup(r->pool, root_path); - apr_size_t uri_len = strlen(uri); - apr_size_t parentpath_len = strlen(parentpath); - - if (uri[uri_len-1] == '/') - uri[uri_len-1] = '\0'; + /* Only allow GET and HEAD on the parentpath resource + * httpd uses the same method_number for HEAD as GET */ + if (r->method_number != M_GET) + { + int status; - if (parentpath[parentpath_len-1] == '/') - parentpath[parentpath_len-1] = '\0'; + /* Marshall the error back to the client by generating by + * way of the dav_svn__error_response_tag trick. */ + err = dav_svn__new_error(r->pool, HTTP_METHOD_NOT_ALLOWED, + SVN_ERR_APMOD_MALFORMED_URI, + "The URI does not contain the name " + "of a repository."); + /* can't use r->allowed since the default handler isn't called */ + apr_table_setn(r->headers_out, "Allow", "GET,HEAD"); + status = dav_svn__error_response_tag(r, err); - if (strcmp(parentpath, uri) == 0) - { - err = get_parentpath_resource(r, resource); - if (err) - return err; - return NULL; + return dav_push_error(r->pool, status, err->error_id, NULL, err); } + + err = get_parentpath_resource(r, resource); + if (err) + return err; + return NULL; } /* This does all the work of interpreting/splitting the request uri. */ @@ -2390,21 +2502,12 @@ get_parent_path(const char *path, svn_boolean_t is_urlpath, apr_pool_t *pool) { - apr_size_t len; - char *tmp = apr_pstrdup(pool, path); - - len = strlen(tmp); - - if (len > 0) + if (*path != '\0') /* not an empty string */ { - /* Remove any trailing slash; else svn_path_dirname() asserts. */ - if (tmp[len-1] == '/') - tmp[len-1] = '\0'; - if (is_urlpath) - return svn_urlpath__dirname(tmp, pool); + return svn_urlpath__dirname(path, pool); else - return svn_fspath__dirname(tmp, pool); + return svn_fspath__dirname(path, pool); } return path; @@ -2440,13 +2543,18 @@ get_parent_resource(const dav_resource * parent->versioned = 1; parent->hooks = resource->hooks; parent->pool = resource->pool; - parent->uri = get_parent_path(resource->uri, TRUE, resource->pool); + parent->uri = get_parent_path(svn_urlpath__canonicalize(resource->uri, + resource->pool), + TRUE, resource->pool); parent->info = parentinfo; parentinfo->uri_path = - svn_stringbuf_create(get_parent_path(resource->info->uri_path->data, - TRUE, resource->pool), - resource->pool); + svn_stringbuf_create( + get_parent_path( + svn_urlpath__canonicalize(resource->info->uri_path->data, + resource->pool), + TRUE, resource->pool), + resource->pool); parentinfo->repos = resource->info->repos; parentinfo->root = resource->info->root; parentinfo->r = resource->info->r; @@ -4085,7 +4193,9 @@ typedef struct walker_ctx_t { static dav_error * -do_walk(walker_ctx_t *ctx, int depth) +do_walk(walker_ctx_t *ctx, + int depth, + apr_pool_t *scratch_pool) { const dav_walk_params *params = ctx->params; int isdir = ctx->res.collection; @@ -4158,19 +4268,19 @@ do_walk(walker_ctx_t *ctx, int depth) svn_log__get_dir(ctx->info.repos_path, ctx->info.root.rev, TRUE, FALSE, SVN_DIRENT_ALL, - params->pool)); + scratch_pool)); /* fetch this collection's children */ serr = svn_fs_dir_entries(&children, ctx->info.root.root, - ctx->info.repos_path, params->pool); + ctx->info.repos_path, scratch_pool); if (serr != NULL) return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "could not fetch collection members", params->pool); /* iterate over the children in this collection */ - iterpool = svn_pool_create(params->pool); - for (hi = apr_hash_first(params->pool, children); hi; hi = apr_hash_next(hi)) + iterpool = svn_pool_create(scratch_pool); + for (hi = apr_hash_first(scratch_pool, children); hi; hi = apr_hash_next(hi)) { const void *key; apr_ssize_t klen; @@ -4223,7 +4333,7 @@ do_walk(walker_ctx_t *ctx, int depth) ctx->res.uri = ctx->uri->data; /* recurse on this collection */ - err = do_walk(ctx, depth - 1); + err = do_walk(ctx, depth - 1, iterpool); if (err != NULL) return err; @@ -4305,7 +4415,7 @@ walk(const dav_walk_params *params, int /* ### is the root already/always open? need to verify */ /* always return the error, and any/all multistatus responses */ - err = do_walk(&ctx, depth); + err = do_walk(&ctx, depth, params->pool); *response = ctx.wres.response; return err; Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/util.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/util.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/util.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/util.c Sun Dec 14 11:44:03 2014 @@ -412,6 +412,32 @@ dav_svn__simple_parse_uri(dav_svn__uri_i "Unsupported URI form"); } +svn_boolean_t +dav_svn__is_parentpath_list(request_rec *r) +{ + const char *fs_parent_path = dav_svn__get_fs_parent_path(r); + + if (fs_parent_path && dav_svn__get_list_parentpath_flag(r)) + { + const char *root_path = dav_svn__get_root_dir(r); + char *uri = apr_pstrdup(r->pool, r->uri); + char *parentpath = apr_pstrdup(r->pool, root_path); + apr_size_t uri_len = strlen(uri); + apr_size_t parentpath_len = strlen(parentpath); + + if (uri[uri_len-1] == '/') + uri[uri_len-1] = '\0'; + + if (parentpath[parentpath_len-1] == '/') + parentpath[parentpath_len-1] = '\0'; + + if (strcmp(parentpath, uri) == 0) + { + return TRUE; + } + } + return FALSE; +} /* ### move this into apr_xml */ int Modified: subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/version.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/version.c?rev=1645439&r1=1645438&r2=1645439&view=diff ============================================================================== --- subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/version.c (original) +++ subversion/branches/1.7.x-issue4340-repos/subversion/mod_dav_svn/version.c Sun Dec 14 11:44:03 2014 @@ -953,8 +953,11 @@ dav_svn__checkin(dav_resource *resource, if (serr) { + int status; + if (serr->apr_err == SVN_ERR_FS_CONFLICT) { + status = HTTP_CONFLICT; msg = apr_psprintf(resource->pool, "A conflict occurred during the CHECKIN " "processing. The problem occurred with " @@ -962,10 +965,12 @@ dav_svn__checkin(dav_resource *resource, conflict_msg); } else - msg = "An error occurred while committing the transaction."; + { + status = HTTP_INTERNAL_SERVER_ERROR; + msg = "An error occurred while committing the transaction."; + } - return dav_svn__convert_err(serr, HTTP_CONFLICT, msg, - resource->pool); + return dav_svn__convert_err(serr, status, msg, resource->pool); } else { @@ -1455,8 +1460,11 @@ merge(dav_resource *target, if (serr) { const char *msg; + int status; + if (serr->apr_err == SVN_ERR_FS_CONFLICT) { + status = HTTP_CONFLICT; /* ### we need to convert the conflict path into a URI */ msg = apr_psprintf(pool, "A conflict occurred during the MERGE " @@ -1465,9 +1473,12 @@ merge(dav_resource *target, conflict); } else - msg = "An error occurred while committing the transaction."; + { + status = HTTP_INTERNAL_SERVER_ERROR; + msg = "An error occurred while committing the transaction."; + } - return dav_svn__convert_err(serr, HTTP_CONFLICT, msg, pool); + return dav_svn__convert_err(serr, status, msg, pool); } else {
