subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1417252 - /subversion/trunk/subversion/libsvn_client/export.c
Date Wed, 05 Dec 2012 00:49:23 GMT
Author: hwright
Date: Wed Dec  5 00:49:22 2012
New Revision: 1417252

URL: http://svn.apache.org/viewvc?rev=1417252&view=rev
Log:
Manually migrate the Ev2 export implementation (in the case of recursive
directory exports) from the ev2-export branch to trunk, guarded by the
--enable-ev2-impl configure flag.

* subversion/libsvn_client/export.c
  (fetch_kind_func): Remove.
  (get_editor): Rename to...
  (get_editor_ev1): ...this.
  (add_file_ev2, add_directory_ev2, target_revision_func, get_editor_ev2): New.
  (svn_client_export5): Optionally use the Ev2 implementation for directory
    exports.

Modified:
    subversion/trunk/subversion/libsvn_client/export.c

Modified: subversion/trunk/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/export.c?rev=1417252&r1=1417251&r2=1417252&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/export.c (original)
+++ subversion/trunk/subversion/libsvn_client/export.c Wed Dec  5 00:49:22 2012
@@ -43,8 +43,13 @@
 
 #include "svn_private_config.h"
 #include "private/svn_subr_private.h"
+#include "private/svn_delta_private.h"
 #include "private/svn_wc_private.h"
 
+#ifndef ENABLE_EV2_IMPL
+#define ENABLE_EV2_IMPL 0
+#endif
+
 
 /*** Code. ***/
 
@@ -859,26 +864,6 @@ close_file(void *file_baton,
 }
 
 static svn_error_t *
-fetch_kind_func(svn_kind_t *kind,
-                void *baton,
-                const char *path,
-                svn_revnum_t base_revision,
-                apr_pool_t *scratch_pool)
-{
-  /* We know the root of the edit is a directory. */
-  if (path[0] == '\0')
-    *kind = svn_kind_dir;
-
-  /* ### TODO: We could possibly fetch the kind of the object in question
-         from the server with a second ra_session, but right now this
-         seems to work. */
-  else
-    *kind = svn_kind_unknown;
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
 fetch_props_func(apr_hash_t **props,
                  void *baton,
                  const char *path,
@@ -908,16 +893,14 @@ fetch_base_func(const char **filename,
 }
 
 static svn_error_t *
-get_editor(const svn_delta_editor_t **export_editor,
-           void **edit_baton,
-           struct edit_baton *eb,
-           svn_client_ctx_t *ctx,
-           apr_pool_t *result_pool,
-           apr_pool_t *scratch_pool)
+get_editor_ev1(const svn_delta_editor_t **export_editor,
+               void **edit_baton,
+               struct edit_baton *eb,
+               svn_client_ctx_t *ctx,
+               apr_pool_t *result_pool,
+               apr_pool_t *scratch_pool)
 {
   svn_delta_editor_t *editor = svn_delta_default_editor(result_pool);
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                            svn_delta_shim_callbacks_default(result_pool);
   
   editor->set_target_revision = set_target_revision;
   editor->open_root = open_root;
@@ -936,19 +919,234 @@ get_editor(const svn_delta_editor_t **ex
                                             edit_baton,
                                             result_pool));
 
-  shim_callbacks->fetch_kind_func = fetch_kind_func;
-  shim_callbacks->fetch_props_func = fetch_props_func;
-  shim_callbacks->fetch_base_func = fetch_base_func;
-  shim_callbacks->fetch_baton = eb;
-
-  SVN_ERR(svn_editor__insert_shims(export_editor, edit_baton,
-                                   *export_editor, *edit_baton,
-                                   NULL, NULL, shim_callbacks,
-                                   result_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+
+/*** The Ev2 Implementation ***/
+
+static svn_error_t *
+add_file_ev2(void *baton,
+             const char *relpath,
+             const svn_checksum_t *checksum,
+             svn_stream_t *contents,
+             apr_hash_t *props,
+             svn_revnum_t replaces_rev,
+             apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *full_path = svn_dirent_join(eb->root_path, relpath,
+                                          scratch_pool);
+  /* RELPATH is not canonicalized, i.e. it may still contain spaces etc.
+   * but EB->root_url is. */
+  const char *full_url = svn_path_url_add_component2(eb->root_url,
+                                                     relpath,
+                                                     scratch_pool);
+  const svn_string_t *val;
+  /* The four svn: properties we might actually care about. */
+  const svn_string_t *eol_style_val = NULL;
+  const svn_string_t *keywords_val = NULL;
+  const svn_string_t *executable_val = NULL;
+  svn_boolean_t special = FALSE;
+  /* Any keyword vals to be substituted */
+  const char *revision = NULL;
+  const char *author = NULL;
+  apr_time_t date = 0; 
+
+  /* Look at any properties for additional information. */
+  if ( (val = apr_hash_get(props, SVN_PROP_EOL_STYLE, APR_HASH_KEY_STRING)) )
+    eol_style_val = val;
+
+  if ( !eb->ignore_keywords && (val = apr_hash_get(props, SVN_PROP_KEYWORDS,
+                                                   APR_HASH_KEY_STRING)) )
+    keywords_val = val;
+
+  if ( (val = apr_hash_get(props, SVN_PROP_EXECUTABLE, APR_HASH_KEY_STRING)) )
+    executable_val = val;
+  
+  /* Try to fill out the baton's keywords-structure too. */
+  if ( (val = apr_hash_get(props, SVN_PROP_ENTRY_COMMITTED_REV,
+                           APR_HASH_KEY_STRING)) )
+    revision = val->data;
+
+  if ( (val = apr_hash_get(props, SVN_PROP_ENTRY_COMMITTED_DATE,
+                           APR_HASH_KEY_STRING)) )
+    SVN_ERR(svn_time_from_cstring(&date, val->data, scratch_pool));
+  
+  if ( (val = apr_hash_get(props, SVN_PROP_ENTRY_LAST_AUTHOR,
+                           APR_HASH_KEY_STRING)) )
+    author = val->data;
+
+  if ( (val = apr_hash_get(props, SVN_PROP_SPECIAL, APR_HASH_KEY_STRING)) )
+    special = TRUE;
+
+  if (special)
+    {
+      svn_stream_t *tmp_stream;
+
+      SVN_ERR(svn_subst_create_specialfile(&tmp_stream, full_path,
+                                           scratch_pool, scratch_pool));
+      SVN_ERR(svn_stream_copy3(contents, tmp_stream, eb->cancel_func,
+                               eb->cancel_baton, scratch_pool));
+    }
+  else
+    {
+      svn_stream_t *tmp_stream;
+      const char *tmppath;
+
+      /* Create a temporary file in the same directory as the file. We're going
+         to rename the thing into place when we're done. */
+      SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmppath,
+                                     svn_dirent_dirname(full_path,
+                                                        scratch_pool),
+                                     svn_io_file_del_none,
+                                     scratch_pool, scratch_pool));
+
+      /* Possibly wrap the stream to be translated, as dictated by
+         the props. */
+      if (eol_style_val || keywords_val)
+        {
+          svn_subst_eol_style_t style;
+          const char *eol = NULL;
+          svn_boolean_t repair = FALSE;
+          apr_hash_t *final_kw = NULL;
+
+          if (eol_style_val)
+            {
+              SVN_ERR(get_eol_style(&style, &eol, eol_style_val->data,
+                                    eb->native_eol));
+              repair = TRUE;
+            }
+
+          if (keywords_val)
+            SVN_ERR(svn_subst_build_keywords2(&final_kw, keywords_val->data,
+                                              revision, full_url, date,
+                                              author, scratch_pool));
+
+          /* Writing through a translated stream is more efficient than
+             reading through one, so we wrap TMP_STREAM and not CONTENTS. */
+          tmp_stream = svn_subst_stream_translated(tmp_stream, eol, repair,
+                                                   final_kw, TRUE, /* expand */
+                                                   scratch_pool);
+        }
+
+      SVN_ERR(svn_stream_copy3(contents, tmp_stream, eb->cancel_func,
+                               eb->cancel_baton, scratch_pool));
+
+      /* Move the file into place. */
+      SVN_ERR(svn_io_file_rename(tmppath, full_path, scratch_pool));
+    }
+
+  if (executable_val)
+    SVN_ERR(svn_io_set_file_executable(full_path, TRUE, FALSE, scratch_pool));
+
+  if (date && (! special))
+    SVN_ERR(svn_io_set_file_affected_time(date, full_path, scratch_pool));
+
+  if (eb->notify_func)
+    {
+      svn_wc_notify_t *notify = svn_wc_create_notify(full_path,
+                                                     svn_wc_notify_update_add,
+                                                     scratch_pool);
+      notify->kind = svn_node_file;
+      (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+    }
 
-   return SVN_NO_ERROR;
+  return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+add_directory_ev2(void *baton,
+                  const char *relpath,
+                  const apr_array_header_t *children,
+                  apr_hash_t *props,
+                  svn_revnum_t replaces_rev,
+                  apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  svn_node_kind_t kind;
+  const char *full_path = svn_dirent_join(eb->root_path, relpath,
+                                          scratch_pool);
+  svn_string_t *val;
+
+  SVN_ERR(svn_io_check_path(full_path, &kind, scratch_pool));
+  if (kind == svn_node_none)
+    SVN_ERR(svn_io_dir_make(full_path, APR_OS_DEFAULT, scratch_pool));
+  else if (kind == svn_node_file)
+    return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+                             _("'%s' exists and is not a directory"),
+                             svn_dirent_local_style(full_path, scratch_pool));
+  else if (! (kind == svn_node_dir && eb->force))
+    return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+                             _("'%s' already exists"),
+                             svn_dirent_local_style(full_path, scratch_pool));
+
+  if ( (val = apr_hash_get(props, SVN_PROP_EXTERNALS, APR_HASH_KEY_STRING)) )
+    SVN_ERR(add_externals(eb->externals, full_path, val));
+  
+  if (eb->notify_func)
+    {
+      svn_wc_notify_t *notify = svn_wc_create_notify(full_path,
+                                                     svn_wc_notify_update_add,
+                                                     scratch_pool);
+      notify->kind = svn_node_dir;
+      (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+target_revision_func(void *baton,
+                     svn_revnum_t target_revision,
+                     apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+
+  *eb->target_revision = target_revision;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+get_editor_ev2(const svn_delta_editor_t **export_editor,
+               void **edit_baton,
+               struct edit_baton *eb,
+               svn_client_ctx_t *ctx,
+               apr_pool_t *result_pool,
+               apr_pool_t *scratch_pool)
+{
+  svn_editor_t *editor;
+  struct svn_delta__extra_baton *exb = apr_pcalloc(result_pool, sizeof(*exb));
+  svn_boolean_t *found_abs_paths = apr_palloc(result_pool,
+                                              sizeof(*found_abs_paths));
+
+  exb->baton = eb;
+  exb->target_revision = target_revision_func;
+
+  SVN_ERR(svn_editor_create(&editor, eb, ctx->cancel_func, ctx->cancel_baton,
+                            result_pool, scratch_pool));
+  SVN_ERR(svn_editor_setcb_add_directory(editor, add_directory_ev2,
+                                         scratch_pool));
+  SVN_ERR(svn_editor_setcb_add_file(editor, add_file_ev2, scratch_pool));
+
+  *found_abs_paths = TRUE;
+
+  SVN_ERR(svn_delta__delta_from_editor(export_editor, edit_baton,
+                                       editor, NULL, NULL, found_abs_paths,
+                                       NULL, NULL,
+                                       fetch_props_func, eb,
+                                       fetch_base_func, eb,
+                                       exb, result_pool));
+
+  /* Create the root of the export. */
+  SVN_ERR(open_root_internal(eb->root_path, eb->force, eb->notify_func,
+                             eb->notify_baton, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
 
 /*** Public Interfaces ***/
 
@@ -1087,8 +1285,12 @@ svn_client_export5(svn_revnum_t *result_
           void *report_baton;
           svn_boolean_t use_sleep = FALSE;
 
-          SVN_ERR(get_editor(&export_editor, &edit_baton, eb, ctx,
-                             pool, pool));
+          if (!ENABLE_EV2_IMPL)
+            SVN_ERR(get_editor_ev1(&export_editor, &edit_baton, eb, ctx,
+                                   pool, pool));
+          else
+            SVN_ERR(get_editor_ev2(&export_editor, &edit_baton, eb, ctx,
+                                   pool, pool));
 
           /* Manufacture a basic 'report' to the update reporter. */
           SVN_ERR(svn_ra_do_update2(ra_session,



Mime
View raw message