You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2010/05/28 14:15:01 UTC

svn commit: r949157 - in /subversion/trunk/subversion/libsvn_wc: copy.c wc-queries.sql wc_db.c wc_db.h

Author: philip
Date: Fri May 28 12:15:01 2010
New Revision: 949157

URL: http://svn.apache.org/viewvc?rev=949157&view=rev
Log:
Fix issue 3553: revprop change hook errors are not XML safe.

* subversion/mod_dav_svn/deadprops.c
  (save_value): Quote hook error.

* subversion/tests/cmdline/prop_tests.py
  (post_revprop_change_hook): Use regex for error matching, verify change.
  (test_list): Remove XFail from post_revprop_change_hook.

Modified:
    subversion/trunk/subversion/libsvn_wc/copy.c
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h

Modified: subversion/trunk/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/copy.c?rev=949157&r1=949156&r2=949157&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/copy.c (original)
+++ subversion/trunk/subversion/libsvn_wc/copy.c Fri May 28 12:15:01 2010
@@ -34,6 +34,8 @@
 #include "svn_path.h"
 
 #include "wc.h"
+#include "log.h"
+#include "workqueue.h"
 #include "adm_files.h"
 #include "entries.h"
 #include "props.h"
@@ -258,6 +260,7 @@ copy_added_dir_administratively(svn_wc_c
   return SVN_NO_ERROR;
 }
 
+#ifndef SVN_EXPERIMENTAL_COPY
 /* This function effectively creates and schedules a file for
    addition, but does extra administrative things to allow it to
    function as a 'copy'.
@@ -475,6 +478,7 @@ copy_file_administratively(svn_wc_contex
 
   return SVN_NO_ERROR;
 }
+#endif
 
 
 /* Recursively crawl over a directory PATH and do a number of things:
@@ -730,6 +734,98 @@ copy_dir_administratively(svn_wc_context
   }
 }
 
+#ifdef SVN_EXPERIMENTAL_COPY
+/* A replacement for both copy_file_administratively and
+   copy_added_file_administratively.  Not yet fully working.  Relies
+   on in-db-props.  */
+static svn_error_t *
+copy_file(svn_wc_context_t *wc_ctx,
+          const char *src_abspath,
+          const char *dst_abspath,
+          svn_cancel_func_t cancel_func,
+          void *cancel_baton,
+          svn_wc_notify_func2_t notify_func,
+          void *notify_baton,
+          apr_pool_t *scratch_pool)
+{
+  svn_skel_t *work_items = NULL;
+  const char *dir_abspath = svn_dirent_dirname(dst_abspath, scratch_pool);
+  const char *tmpdir_abspath;
+  svn_stream_t *src, *src_pristine;
+  const char *tmp_dst_abspath;
+  svn_error_t *err;
+
+  SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath, wc_ctx->db,
+                                         dst_abspath,
+                                         scratch_pool, scratch_pool));
+
+#ifndef SVN_EXPERIMENTAL_PRISTINE
+  SVN_ERR(svn_wc__get_pristine_contents(&src_pristine, wc_ctx->db,
+                                        src_abspath,
+                                        scratch_pool, scratch_pool));
+  if (src_pristine)
+    {
+      svn_skel_t *work_item;
+      svn_stream_t *tmp_pristine;
+      const char *tmp_pristine_abspath, *dst_pristine_abspath;
+
+      SVN_ERR(svn_stream_open_unique(&tmp_pristine, &tmp_pristine_abspath,
+                                     tmpdir_abspath, svn_io_file_del_none,
+                                     scratch_pool, scratch_pool));
+      SVN_ERR(svn_stream_copy3(src_pristine, tmp_pristine,
+                               cancel_func, cancel_baton, scratch_pool));
+      SVN_ERR(svn_wc__text_base_path(&dst_pristine_abspath, wc_ctx->db,
+                                     dst_abspath, scratch_pool));
+      SVN_ERR(svn_wc__loggy_move(&work_item, wc_ctx->db, dir_abspath,
+                                 tmp_pristine_abspath, dst_pristine_abspath,
+                                 scratch_pool));
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+    }
+#endif
+
+  err = svn_stream_open_readonly(&src, src_abspath, scratch_pool, scratch_pool);
+  if (err)
+    {
+      if (!APR_STATUS_IS_ENOENT(err->apr_err))
+        return svn_error_return(err);
+      /* Source may not exist when recursively copying a directory. */
+      svn_error_clear(err);
+    }
+  else
+    {
+      svn_skel_t *work_item;
+      svn_stream_t *tmp_dst;
+
+      SVN_ERR(svn_stream_open_unique(&tmp_dst, &tmp_dst_abspath,
+                                     tmpdir_abspath, svn_io_file_del_none,
+                                     scratch_pool, scratch_pool));
+      SVN_ERR(svn_io_copy_perms(src_abspath,
+                                tmp_dst_abspath, scratch_pool));
+      SVN_ERR(svn_stream_copy3(src, tmp_dst,
+                               cancel_func, cancel_baton, scratch_pool));
+      SVN_ERR(svn_wc__loggy_move(&work_item, wc_ctx->db, dir_abspath,
+                                 tmp_dst_abspath, dst_abspath,
+                                 scratch_pool));
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+    }
+
+  SVN_ERR(svn_wc__db_op_copy(wc_ctx->db, src_abspath, dst_abspath,
+                             work_items, scratch_pool));
+  SVN_ERR(svn_wc__wq_run(wc_ctx->db, dir_abspath,
+                         cancel_func, cancel_baton, scratch_pool));
+
+  if (notify_func)
+    {
+      svn_wc_notify_t *notify
+        = svn_wc_create_notify(dst_abspath, svn_wc_notify_add,
+                               scratch_pool);
+      notify->kind = svn_node_file;
+      (*notify_func)(notify_baton, notify, scratch_pool);
+    }
+  return SVN_NO_ERROR;
+}
+#endif
+
 
 
 /* Public Interface */
@@ -814,6 +910,7 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
   if (src_kind == svn_node_file ||
       (src_entry->kind == svn_node_file && src_kind == svn_node_none))
     {
+#ifndef SVN_EXPERIMENTAL_COPY
       /* Check if we are copying a file scheduled for addition,
          these require special handling. */
       if (src_entry->schedule == svn_wc_schedule_add
@@ -835,6 +932,41 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
                                              notify_func, notify_baton,
                                              scratch_pool));
         }
+#else
+      svn_node_kind_t dst_kind, dst_db_kind;
+
+      /* This is the error checking from copy_file_administratively
+         but converted to wc-ng.  It's not in copy_file since this
+         checking only needs to happen at the root of the copy and not
+         when called recursively. */
+      SVN_ERR(svn_io_check_path(dst_abspath, &dst_kind, scratch_pool));
+      if (dst_kind != svn_node_none)
+        return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL,
+                                 _("'%s' already exists and is in the way"),
+                                 svn_dirent_local_style(dst_abspath,
+                                                        scratch_pool));
+      SVN_ERR(svn_wc_read_kind(&dst_db_kind, wc_ctx, dst_abspath, TRUE,
+                               scratch_pool));
+      if (dst_db_kind != svn_node_none)
+        {
+          svn_boolean_t is_deleted, is_present;
+
+          SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, wc_ctx,
+                                                 dst_abspath, scratch_pool));
+          SVN_ERR(svn_wc__node_is_status_present(&is_present, wc_ctx,
+                                                 dst_abspath, scratch_pool));
+          if (is_present && !is_deleted)
+            return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL,
+                               _("There is already a versioned item '%s'"),
+                               svn_dirent_local_style(dst_abspath,
+                                                      scratch_pool));
+
+        }
+
+      SVN_ERR(copy_file(wc_ctx, src_abspath, dst_abspath,
+                        cancel_func, cancel_baton, notify_func, notify_baton,
+                        scratch_pool));
+#endif
     }
   else if (src_kind == svn_node_dir)
     {

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=949157&r1=949156&r2=949157&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Fri May 28 12:15:01 2010
@@ -412,6 +412,39 @@ SELECT 0 FROM BASE_NODE WHERE wc_id = ?1
 UNION
 SELECT 1 FROM WORKING_NODE WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_INSERT_WORKING_NODE_COPY_FROM_BASE
+INSERT INTO WORKING_NODE (
+    wc_id, local_relpath, parent_relpath, presence, kind, checksum,
+    translated_size, changed_rev, changed_date, changed_author, depth,
+    symlink_target, last_mod_time, properties, copyfrom_repos_id,
+    copyfrom_repos_path, copyfrom_revnum )
+SELECT wc_id, ?3 AS local_relpath, ?4 AS parent_relpath, ?5 AS presence, kind,
+    checksum, translated_size, changed_rev, changed_date, changed_author, depth,
+    symlink_target, last_mod_time, properties, ?6 AS copyfrom_repos_id,
+    ?7 AS copyfrom_repos_path, ?8 AS copyfrom_revnum FROM BASE_NODE
+WHERE wc_id = ?1 AND local_relpath = ?2;
+
+-- STMT_INSERT_WORKING_NODE_COPY_FROM_WORKING
+INSERT INTO WORKING_NODE (
+    wc_id, local_relpath, parent_relpath, presence, kind, checksum,
+    translated_size, changed_rev, changed_date, changed_author, depth,
+    symlink_target, last_mod_time, properties, copyfrom_repos_id,
+    copyfrom_repos_path, copyfrom_revnum )
+SELECT wc_id, ?3 AS local_relpath, ?4 AS parent_relpath, ?5 AS presence, kind,
+    checksum, translated_size, changed_rev, changed_date, changed_author, depth,
+    symlink_target, last_mod_time, properties, ?6 AS copyfrom_repos_id,
+    ?7 AS copyfrom_repos_path, ?8 AS copyfrom_revnum FROM WORKING_NODE
+WHERE wc_id = ?1 AND local_relpath = ?2;
+
+-- STMT_INSERT_ACTUAL_NODE_FROM_ACTUAL_NODE
+INSERT INTO ACTUAL_NODE (
+     wc_id, local_relpath, parent_relpath, properties,
+     conflict_old, conflict_new, conflict_working,
+     prop_reject, changelist, text_mod, tree_conflict_data )
+SELECT wc_id, ?3 AS local_relpath, ?4 AS parent_relpath, properties,
+     conflict_old, conflict_new, conflict_working,
+     prop_reject, changelist, text_mod, tree_conflict_data FROM ACTUAL_NODE
+WHERE wc_id = ?1 AND local_relpath = ?2;
 
 /* ------------------------------------------------------------------------- */
 

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=949157&r1=949156&r2=949157&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri May 28 12:15:01 2010
@@ -2179,17 +2179,231 @@ svn_wc__db_repos_ensure(apr_int64_t *rep
                                           scratch_pool));
 }
 
+/* Temporary helper for svn_wc__db_op_copy to handle copying from one
+   db to another, it becomes redundant when we centralise. */
+static svn_error_t *
+temp_cross_db_copy(svn_wc__db_t *db,
+                   const char *src_abspath,
+                   svn_wc__db_pdh_t *dst_pdh,
+                   const char *dst_relpath,
+                   svn_wc__db_kind_t kind,
+                   apr_int64_t copyfrom_id,
+                   const char *copyfrom_relpath,
+                   svn_revnum_t copyfrom_rev,
+                   apr_pool_t *scratch_pool)
+{
+  insert_working_baton_t iwb;
+  svn_revnum_t changed_rev;
+  apr_time_t changed_date;
+  const char *changed_author;
+  const svn_checksum_t *checksum;
+  apr_hash_t *props;
+
+  SVN_ERR_ASSERT(kind == svn_wc__db_kind_file);
+
+  SVN_ERR(svn_wc__db_read_info(NULL, /* status */
+                               NULL, /* kind */
+                               NULL, /* revision */
+                               NULL, /* repos_relpath */
+                               NULL, /* repos_root_url */
+                               NULL, /* repos_uuid */
+                               &changed_rev, &changed_date, &changed_author,
+                               NULL, /* last_mod_time */
+                               NULL, /* depth */
+                               &checksum,
+                               NULL, /* translated_size */
+                               NULL, /* target */
+                               NULL, /* changelist */
+                               NULL, /* original_repos_relpath */
+                               NULL, /* original_root_url */
+                               NULL, /* original_uuid */
+                               NULL, /* original_revision */
+                               NULL, /* text_mod */
+                               NULL, /* props_mod */
+                               NULL, /* base_shadowed */
+                               NULL, /* conflicted */
+                               NULL, /* lock */
+                               db, src_abspath, scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_wc__get_pristine_props(&props, db, src_abspath,
+                                     scratch_pool, scratch_pool));
+
+  iwb.presence = svn_wc__db_status_normal;
+  iwb.kind = kind;
+  iwb.wc_id = dst_pdh->wcroot->wc_id;
+  iwb.local_relpath = dst_relpath;
+
+  iwb.props = props;
+  iwb.changed_rev = changed_rev;
+  iwb.changed_date = changed_date;
+  iwb.changed_author = changed_author;
+  iwb.original_repos_id = copyfrom_id;
+  iwb.original_repos_relpath = copyfrom_relpath;
+  iwb.original_revnum = copyfrom_rev;
+  iwb.moved_here = FALSE;
+
+  iwb.checksum = checksum;
+
+  SVN_ERR(insert_working_node(&iwb, dst_pdh->wcroot->sdb, scratch_pool));
+
+  /* ### What about actual_node? */
+
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_wc__db_op_copy(svn_wc__db_t *db,
                    const char *src_abspath,
                    const char *dst_abspath,
+                   const svn_skel_t *work_items,
                    apr_pool_t *scratch_pool)
 {
+  svn_wc__db_pdh_t *src_pdh, *dst_pdh;
+  const char *src_relpath, *dst_relpath;
+  const char *repos_relpath, *repos_root_url, *repos_uuid, *copyfrom_relpath;
+  svn_revnum_t revision, copyfrom_rev;
+  svn_wc__db_status_t status;
+  apr_int64_t copyfrom_id;
+  svn_wc__db_kind_t kind;
+
   SVN_ERR_ASSERT(svn_dirent_is_absolute(src_abspath));
   SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
 
-  NOT_IMPLEMENTED();
+  /* ### This should all happen in one transaction, but that can't
+     ### happen until we move to a centralised database. */
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&src_pdh, &src_relpath, db,
+                                             src_abspath,
+                                             svn_sqlite__mode_readwrite,
+                                             scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(src_pdh);
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&dst_pdh, &dst_relpath, db,
+                                             dst_abspath,
+                                             svn_sqlite__mode_readwrite,
+                                             scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(dst_pdh);
+
+
+  SVN_ERR(svn_wc__db_read_info(&status, &kind, &revision,
+                               &repos_relpath, &repos_root_url, &repos_uuid,
+                               NULL, /* changed_rev */
+                               NULL, /* changed_date */
+                               NULL, /* changed_author */
+                               NULL, /* last_mod_time */
+                               NULL, /* depth */
+                               NULL, /* checksum */
+                               NULL, /* translated_size */
+                               NULL, /* target */
+                               NULL, /* changelist */
+                               NULL, /* original_repos_relpath */
+                               NULL, /* original_root_url */
+                               NULL, /* original_uuid */
+                               NULL, /* original_revision */
+                               NULL, /* text_mod */
+                               NULL, /* props_mod */
+                               NULL, /* base_shadowed */
+                               NULL, /* conflicted */
+                               NULL, /* lock */
+                               db, src_abspath, scratch_pool, scratch_pool));
+
+  SVN_ERR_ASSERT(kind == svn_wc__db_kind_file);
+
+  if (status != svn_wc__db_status_added)
+    {
+      copyfrom_relpath = repos_relpath;
+      copyfrom_rev = revision;
+      SVN_ERR(create_repos_id(&copyfrom_id,
+                              repos_root_url, repos_uuid,
+                              src_pdh->wcroot->sdb, scratch_pool));
+    }
+  else
+    {
+      const char *op_root_abspath;
+      const char *original_repos_relpath, *original_root_url, *original_uuid;
+      svn_revnum_t original_revision;
+
+      SVN_ERR(svn_wc__db_scan_addition(&status, &op_root_abspath,
+                                       NULL, /* repos_relpath */
+                                       NULL, /* repos_root_url */
+                                       NULL, /* repos_uuid */
+                                       &original_repos_relpath,
+                                       &original_root_url, &original_uuid,
+                                       &original_revision,
+                                       db, src_abspath,
+                                       scratch_pool, scratch_pool));
+
+      if (status == svn_wc__db_status_copied
+          || status == svn_wc__db_status_moved_here)
+        {
+          copyfrom_relpath
+            = svn_relpath_join(original_repos_relpath,
+                               svn_dirent_skip_ancestor(op_root_abspath,
+                                                        src_abspath),
+                               scratch_pool);
+          copyfrom_rev = original_revision;
+          SVN_ERR(create_repos_id(&copyfrom_id,
+                                  original_root_url, original_uuid,
+                                  src_pdh->wcroot->sdb, scratch_pool));
+        }
+      else
+        {
+          copyfrom_relpath = NULL;
+          copyfrom_rev = SVN_INVALID_REVNUM;
+        }
+    }
+
+
+
+  if (!strcmp(src_pdh->local_abspath, dst_pdh->local_abspath))
+    {
+      svn_sqlite__stmt_t *stmt;
+      const char *dst_parent_relpath = svn_relpath_dirname(dst_relpath,
+                                                           scratch_pool);
+
+      /* ### Need a better way to determine whether a WORKING_NODE exists */
+      if (status == svn_wc__db_status_added
+          || status == svn_wc__db_status_copied
+          || status == svn_wc__db_status_moved_here)
+        SVN_ERR(svn_sqlite__get_statement(&stmt, src_pdh->wcroot->sdb,
+                                  STMT_INSERT_WORKING_NODE_COPY_FROM_WORKING));
+      else
+        SVN_ERR(svn_sqlite__get_statement(&stmt, src_pdh->wcroot->sdb,
+                                  STMT_INSERT_WORKING_NODE_COPY_FROM_BASE));
+
+      SVN_ERR(svn_sqlite__bindf(stmt, "issst",
+                                src_pdh->wcroot->wc_id, src_relpath,
+                                dst_relpath, dst_parent_relpath,
+                                presence_map, svn_wc__db_status_normal));
+
+      if (copyfrom_relpath)
+        {
+          SVN_ERR(svn_sqlite__bind_int64(stmt, 6, copyfrom_id));
+          SVN_ERR(svn_sqlite__bind_text(stmt, 7, copyfrom_relpath));
+          SVN_ERR(svn_sqlite__bind_int64(stmt, 8, copyfrom_rev));
+        }
+      SVN_ERR(svn_sqlite__step_done(stmt));
+
+      SVN_ERR(svn_sqlite__get_statement(&stmt, src_pdh->wcroot->sdb,
+                                  STMT_INSERT_ACTUAL_NODE_FROM_ACTUAL_NODE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isss",
+                                src_pdh->wcroot->wc_id, src_relpath,
+                                dst_relpath, dst_parent_relpath));
+      SVN_ERR(svn_sqlite__step_done(stmt));
+    }
+  else
+    {
+      SVN_ERR(temp_cross_db_copy(db, src_abspath, dst_pdh, dst_relpath, kind,
+                                 copyfrom_id, copyfrom_relpath, copyfrom_rev,
+                                 scratch_pool));
+    }
+
+  /* ### Should do this earlier and insert the node with the right values. */
+  SVN_ERR(svn_wc__db_temp_elide_copyfrom(db, dst_abspath, scratch_pool));
+
+  SVN_ERR(add_work_items(dst_pdh->wcroot->sdb, work_items, scratch_pool));
+ 
+  return SVN_NO_ERROR;
 }
 
 

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=949157&r1=949156&r2=949157&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Fri May 28 12:15:01 2010
@@ -1015,6 +1015,7 @@ svn_error_t *
 svn_wc__db_op_copy(svn_wc__db_t *db,
                    const char *src_abspath,
                    const char *dst_abspath,
+                   const svn_skel_t *work_items,
                    apr_pool_t *scratch_pool);