You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2011/07/12 12:26:08 UTC

svn commit: r1145526 - /subversion/trunk/subversion/libsvn_ra_serf/update.c

Author: rhuijben
Date: Tue Jul 12 10:26:08 2011
New Revision: 1145526

URL: http://svn.apache.org/viewvc?rev=1145526&view=rev
Log:
Partially revert r1143860: Enable the generation of X-SVN-VR-Base headers based
on the editor url and the switched paths reported on the update request.

Rework the patch to always store the repos_relpath for every directory to make
the individual calculations easier to follow.

* subversion/libsvn_ra_serf/update.c
  (report_dir_t): Add repos_relpath.
  (report_info_t): Use const char* for a url.
  (report_context_t): Add switched_paths and root_is_switched.
  (headers_fetch): Update user.
  (start_report): Calculate repos_relpath for the root and directories.
  (end_report): Use the explicit or directory repos_relpath to create HTTPv2
    delta base urls. Apply uri escaping. Update user.
  (link_path): Update switched_paths hash and root_is_switched flag.

Modified:
    subversion/trunk/subversion/libsvn_ra_serf/update.c

Modified: subversion/trunk/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/update.c?rev=1145526&r1=1145525&r2=1145526&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/update.c Tue Jul 12 10:26:08 2011
@@ -115,9 +115,13 @@ typedef struct report_dir_t
   /* the expanded directory name (including all parent names) */
   const char *name;
 
-  /* the canonical url for this directory. */
+  /* the canonical url for this directory after updating. (received) */
   const char *url;
 
+  /* The original repos_relpath of this url (from the workingcopy)
+     or NULL if the repos_relpath can be calculated from the edit root. */
+  const char *repos_relpath;
+
   /* Our base revision - SVN_INVALID_REVNUM if we're adding this dir. */
   svn_revnum_t base_rev;
 
@@ -199,7 +203,7 @@ typedef struct report_info_t
   svn_revnum_t target_rev;
 
   /* our delta base, if present (NULL if we're adding the file) */
-  const svn_string_t *delta_base;
+  const char *delta_base;
 
   /* Path of original item if add with history */
   const char *copyfrom_path;
@@ -315,6 +319,13 @@ struct report_context_t {
   /* Path -> lock token mapping. */
   apr_hash_t *lock_path_tokens;
 
+  /* Path -> const char *repos_relpath mapping */
+  apr_hash_t *switched_paths;
+
+  /* Boolean indicating whether "" is switched.
+     (This indicates that the we are updating a single file) */
+  svn_boolean_t root_is_switched;
+
   /* Our master update editor and baton. */
   const svn_delta_editor_t *update_editor;
   void *update_baton;
@@ -716,7 +727,7 @@ headers_fetch(serf_bucket_t *headers,
       fetch_ctx->info->delta_base)
     {
       serf_bucket_headers_setn(headers, SVN_DAV_DELTA_BASE_HEADER,
-                               fetch_ctx->info->delta_base->data);
+                               fetch_ctx->info->delta_base);
       serf_bucket_headers_setn(headers, "Accept-Encoding",
                                "svndiff1;q=0.9,svndiff;q=0.8");
     }
@@ -1361,6 +1372,15 @@ start_report(svn_ra_serf__xml_parser_t *
 
       info->base_name = info->dir->base_name;
       info->name = info->dir->name;
+
+      info->dir->repos_relpath = apr_hash_get(ctx->switched_paths, "",
+                                              APR_HASH_KEY_STRING);
+
+      if (!info->dir->repos_relpath)
+        SVN_ERR(svn_ra_serf__get_relative_path(&info->dir->repos_relpath,
+                                               ctx->sess->session_url.path,
+                                               ctx->sess, ctx->conn,
+                                               info->dir->pool));
     }
   else if (state == NONE)
     {
@@ -1408,6 +1428,13 @@ start_report(svn_ra_serf__xml_parser_t *
       dir->name = svn_relpath_join(dir->parent_dir->name, dir->base_name,
                                    dir->pool);
       info->name = dir->name;
+
+      dir->repos_relpath = apr_hash_get(ctx->switched_paths, dir->name,
+                                        APR_HASH_KEY_STRING);
+
+      if (!dir->repos_relpath)
+        dir->repos_relpath = svn_relpath_join(dir->parent_dir->repos_relpath,
+                                               dir->base_name, dir->pool);
     }
   else if ((state == OPEN_DIR || state == ADD_DIR) &&
            strcmp(name.name, "add-directory") == 0)
@@ -1446,6 +1473,9 @@ start_report(svn_ra_serf__xml_parser_t *
       dir->base_rev = info->base_rev;
       dir->target_rev = ctx->target_rev;
       dir->fetch_props = TRUE;
+
+      dir->repos_relpath = svn_relpath_join(dir->parent_dir->repos_relpath,
+                                            dir->base_name, dir->pool);
     }
   else if ((state == OPEN_DIR || state == ADD_DIR) &&
            strcmp(name.name, "open-file") == 0)
@@ -1840,14 +1870,59 @@ end_report(svn_ra_serf__xml_parser_t *pa
       if (info->lock_token && info->fetch_props == FALSE)
         info->fetch_props = TRUE;
 
-      /* If we have a WC, we might be able to dive all the way into the WC to
-         get the previous URL so we can do a differential GET with the base URL.
+      /* If possible, we'd like to fetch only a delta against a
+       * version of the file we already have in our working copy,
+       * rather than fetching a fulltext.
+       *
+       * In HTTP v2, we can simply construct the URL we need given the
+       * repos_relpath and base revision number.
+       */
+      if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(ctx->sess))
+        {
+          const char *repos_relpath;
+
+          /* If this file is switched vs the editor root we should provide
+             its real url instead of the one calculated from the session root.
+           */
+          repos_relpath = apr_hash_get(ctx->switched_paths, info->name,
+                                       APR_HASH_KEY_STRING);
+
+          if (!repos_relpath)
+            {
+              if (ctx->root_is_switched)
+                {
+                  /* We are updating a direct target (most likely a file)
+                     that is switched vs its parent url */
+                  SVN_ERR_ASSERT(*svn_relpath_dirname(info->name, info->pool)
+                                    == '\0');
+
+                  repos_relpath = apr_hash_get(ctx->switched_paths, "",
+                                               APR_HASH_KEY_STRING);
+                }
+              else
+                repos_relpath = svn_relpath_join(info->dir->repos_relpath,
+                                                 info->base_name, info->pool);
+            }
+
+          info->delta_base = apr_psprintf(info->pool, "%s/%ld/%s",
+                                          ctx->sess->rev_root_stub,
+                                          info->base_rev,
+                                          svn_path_uri_encode(repos_relpath,
+                                                              info->pool));
+        }
+
+      /* Still no base URL?  If we have a WC, we might be able to dive all
+       * the way into the WC to get the previous URL so we can do a
+       * differential GET with the base URL.
        */
       if ((! info->delta_base) && (ctx->sess->wc_callbacks->get_wc_prop))
         {
+          const svn_string_t *value = NULL;
           SVN_ERR(ctx->sess->wc_callbacks->get_wc_prop(
             ctx->sess->wc_callback_baton, info->name,
-            SVN_RA_SERF__WC_CHECKED_IN_URL, &info->delta_base, info->pool));
+            SVN_RA_SERF__WC_CHECKED_IN_URL, &value, info->pool));
+
+          info->delta_base = value ? value->data : NULL;
         }
 
       SVN_ERR(fetch_file(ctx, info));
@@ -2098,11 +2173,18 @@ link_path(void *report_baton,
   SVN_ERR(svn_io_file_write_full(report->body_file, buf->data, buf->len,
                                  NULL, pool));
 
+  /* Store the switch roots to allow generating repos_relpaths from just
+     the working copy paths. (Needed for HTTPv2) */
+  path = apr_pstrdup(report->pool, path);
+  apr_hash_set(report->switched_paths, path, APR_HASH_KEY_STRING,
+               apr_pstrdup(report->pool, link+1));
+
+  if (!*path)
+    report->root_is_switched = TRUE;
+
   if (lock_token)
     {
-      apr_hash_set(report->lock_path_tokens,
-                   apr_pstrdup(report->pool, path),
-                   APR_HASH_KEY_STRING,
+      apr_hash_set(report->lock_path_tokens, path, APR_HASH_KEY_STRING,
                    apr_pstrdup(report->pool, lock_token));
     }
 
@@ -2523,6 +2605,7 @@ make_update_reporter(svn_ra_session_t *r
   report->send_copyfrom_args = send_copyfrom_args;
   report->text_deltas = text_deltas;
   report->lock_path_tokens = apr_hash_make(report->pool);
+  report->switched_paths = apr_hash_make(report->pool);
 
   report->source = src_path;
   report->destination = dest_path;