You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2014/12/14 12:44:04 UTC

svn commit: r1645439 [4/8] - in /subversion/branches/1.7.x-issue4340-repos: ./ build/ac-macros/ build/generator/ build/generator/templates/ contrib/hook-scripts/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/ja...

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(&notify_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(&copyfrom_id, &copyfrom_relpath, &copyfrom_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
         {