You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2014/10/27 17:52:23 UTC

svn commit: r1634591 [3/4] - in /subversion/branches/move-tracking-2/subversion: include/private/svn_editor3.h libsvn_delta/compat3.c libsvn_delta/editor3.c libsvn_ra/ra_loader.c svnmover/svnmover.c

Modified: subversion/branches/move-tracking-2/subversion/libsvn_delta/editor3.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_delta/editor3.c?rev=1634591&r1=1634590&r2=1634591&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/editor3.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/editor3.c Mon Oct 27 16:52:23 2014
@@ -27,6 +27,7 @@
 #include "svn_error.h"
 #include "svn_pools.h"
 #include "svn_dirent_uri.h"
+#include "svn_props.h"
 
 #include "private/svn_editor3.h"
 
@@ -112,7 +113,7 @@ svn_editor3_create(svn_editor3_t **edito
 
 
 void *
-svn_editor3_get_baton(const svn_editor3_t *editor)
+svn_editor3__get_baton(const svn_editor3_t *editor)
 {
   return editor->baton;
 }
@@ -265,21 +266,61 @@ svn_editor3_put(svn_editor3_t *editor,
  * ========================================================================
  */
 
+#define VALID_NODE_KIND(kind) ((kind) != svn_node_unknown && (kind) != svn_node_none)
+#define VALID_EID(eid) ((eid) >= 0)
+#define VALID_NAME(name) ((name) && (name)[0] && svn_relpath_is_canonical(name))
+#define VALID_CONTENT(content) ((content) && VALID_NODE_KIND((content)->kind))
+
 svn_error_t *
 svn_editor3_add(svn_editor3_t *editor,
-                svn_editor3_nbid_t local_nbid,
+                svn_editor3_nbid_t *local_nbid_p,
                 svn_node_kind_t new_kind,
                 svn_editor3_nbid_t new_parent_nbid,
                 const char *new_name,
                 const svn_editor3_node_content_t *new_content)
 {
-  /* SVN_ERR_ASSERT(...); */
+  int eid = -1;
+
+  SVN_ERR_ASSERT(VALID_NODE_KIND(new_kind));
+  SVN_ERR_ASSERT(VALID_EID(new_parent_nbid));
+  SVN_ERR_ASSERT(VALID_NAME(new_name));
+  SVN_ERR_ASSERT(VALID_CONTENT(new_content));
+  SVN_ERR_ASSERT(new_content->kind == new_kind);
 
   DO_CALLBACK(editor, cb_add,
-              5(local_nbid, new_kind,
+              5(&eid, new_kind,
                 new_parent_nbid, new_name,
                 new_content));
 
+  SVN_ERR_ASSERT(VALID_EID(eid));
+
+  /* We allow the output pointer to be null, here, so that implementations
+     may assume their output pointer is non-null. */
+  if (local_nbid_p)
+    *local_nbid_p = eid;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_editor3_instantiate(svn_editor3_t *editor,
+                        svn_editor3_nbid_t local_nbid,
+                        svn_node_kind_t new_kind,
+                        svn_editor3_nbid_t new_parent_nbid,
+                        const char *new_name,
+                        const svn_editor3_node_content_t *new_content)
+{
+  SVN_ERR_ASSERT(VALID_NODE_KIND(new_kind));
+  SVN_ERR_ASSERT(VALID_EID(local_nbid));
+  SVN_ERR_ASSERT(VALID_EID(new_parent_nbid));
+  SVN_ERR_ASSERT(VALID_NAME(new_name));
+  SVN_ERR_ASSERT(VALID_CONTENT(new_content));
+  SVN_ERR_ASSERT(new_content->kind == new_kind);
+
+  DO_CALLBACK(editor, cb_instantiate,
+              5(local_nbid, new_kind,
+                new_parent_nbid, new_name,
+                new_content));
   return SVN_NO_ERROR;
 }
 
@@ -292,7 +333,12 @@ svn_editor3_copy_one(svn_editor3_t *edit
                      const char *new_name,
                      const svn_editor3_node_content_t *new_content)
 {
-  /* SVN_ERR_ASSERT(...); */
+  SVN_ERR_ASSERT(VALID_EID(local_nbid));
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(src_revision));
+  SVN_ERR_ASSERT(VALID_EID(src_nbid));
+  SVN_ERR_ASSERT(VALID_EID(new_parent_nbid));
+  SVN_ERR_ASSERT(VALID_NAME(new_name));
+  SVN_ERR_ASSERT(! new_content || VALID_CONTENT(new_content));
 
   DO_CALLBACK(editor, cb_copy_one,
               6(local_nbid,
@@ -310,7 +356,10 @@ svn_editor3_copy_tree(svn_editor3_t *edi
                       svn_editor3_nbid_t new_parent_nbid,
                       const char *new_name)
 {
-  /* SVN_ERR_ASSERT(...); */
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(src_revision));
+  SVN_ERR_ASSERT(VALID_EID(src_nbid));
+  SVN_ERR_ASSERT(VALID_EID(new_parent_nbid));
+  SVN_ERR_ASSERT(VALID_NAME(new_name));
 
   DO_CALLBACK(editor, cb_copy_tree,
               4(src_revision, src_nbid,
@@ -324,7 +373,7 @@ svn_editor3_delete(svn_editor3_t *editor
                    svn_revnum_t since_rev,
                    svn_editor3_nbid_t nbid)
 {
-  /* SVN_ERR_ASSERT(...); */
+  SVN_ERR_ASSERT(VALID_EID(nbid));
 
   DO_CALLBACK(editor, cb_delete,
               2(since_rev, nbid));
@@ -340,7 +389,10 @@ svn_editor3_alter(svn_editor3_t *editor,
                   const char *new_name,
                   const svn_editor3_node_content_t *new_content)
 {
-  /* SVN_ERR_ASSERT(...); */
+  SVN_ERR_ASSERT(VALID_EID(nbid));
+  SVN_ERR_ASSERT(VALID_EID(new_parent_nbid));
+  SVN_ERR_ASSERT(VALID_NAME(new_name));
+  SVN_ERR_ASSERT(! new_content || VALID_CONTENT(new_content));
 
   DO_CALLBACK(editor, cb_alter,
               5(since_rev, nbid,
@@ -384,6 +436,73 @@ svn_editor3_abort(svn_editor3_t *editor)
  */
 
 svn_editor3_node_content_t *
+svn_editor3_node_content_dup(const svn_editor3_node_content_t *old,
+                             apr_pool_t *result_pool)
+{
+  svn_editor3_node_content_t *new_content;
+
+  if (old == NULL)
+    return NULL;
+
+  new_content = apr_pmemdup(result_pool, old, sizeof(*new_content));
+  if (old->props)
+    new_content->props = svn_prop_hash_dup(old->props, result_pool);
+  if (old->kind == svn_node_file && old->text)
+    new_content->text = svn_stringbuf_dup(old->text, result_pool);
+  if (old->kind == svn_node_symlink && old->target)
+    new_content->target = apr_pstrdup(result_pool, old->target);
+  return new_content;
+}
+
+svn_boolean_t
+svn_editor3_node_content_equal(const svn_editor3_node_content_t *left,
+                               const svn_editor3_node_content_t *right,
+                               apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *prop_diffs;
+
+  /* references are not supported */
+  SVN_ERR_ASSERT_NO_RETURN(! left->ref.relpath && ! right->ref.relpath);
+  SVN_ERR_ASSERT_NO_RETURN(left->kind != svn_node_unknown
+                           && right->kind != svn_node_unknown);
+
+  if (left->kind != right->kind)
+    {
+      return FALSE;
+    }
+
+  svn_error_clear(svn_prop_diffs(&prop_diffs,
+                                 left->props, right->props,
+                                 scratch_pool));
+
+  if (prop_diffs->nelts != 0)
+    {
+      return FALSE;
+    }
+  switch (left->kind)
+    {
+    case svn_node_dir:
+      break;
+    case svn_node_file:
+      if (! svn_stringbuf_compare(left->text, right->text))
+        {
+          return FALSE;
+        }
+      break;
+    case svn_node_symlink:
+      if (strcmp(left->target, right->target) != 0)
+        {
+          return FALSE;
+        }
+      break;
+    default:
+      break;
+    }
+
+  return TRUE;
+}
+
+svn_editor3_node_content_t *
 svn_editor3_node_content_create_ref(svn_editor3_peg_path_t ref,
                                     apr_pool_t *result_pool)
 {
@@ -504,7 +623,7 @@ static const char *
 nbid_str(svn_editor3_nbid_t nbid,
          apr_pool_t *result_pool)
 {
-  return txn_path_str(nbid, result_pool);
+  return apr_psprintf(result_pool, "%d", nbid);
 }
 
 static svn_error_t *
@@ -612,7 +731,7 @@ wrap_put(void *baton,
 
 static svn_error_t *
 wrap_add(void *baton,
-         svn_editor3_nbid_t local_nbid,
+         svn_editor3_nbid_t *local_nbid,
          svn_node_kind_t new_kind,
          svn_editor3_nbid_t new_parent_nbid,
          const char *new_name,
@@ -621,8 +740,8 @@ wrap_add(void *baton,
 {
   wrapper_baton_t *eb = baton;
 
-  dbg(eb, scratch_pool, "%s : add(k=%s, p=%s, n=%s, c=...)",
-      nbid_str(local_nbid, scratch_pool), svn_node_kind_to_word(new_kind),
+  dbg(eb, scratch_pool, "... : add(k=%s, p=%s, n=%s, c=...)",
+      svn_node_kind_to_word(new_kind),
       nbid_str(new_parent_nbid, scratch_pool), new_name);
   SVN_ERR(svn_editor3_add(eb->wrapped_editor,
                           local_nbid, new_kind,
@@ -631,6 +750,26 @@ wrap_add(void *baton,
 }
 
 static svn_error_t *
+wrap_instantiate(void *baton,
+         svn_editor3_nbid_t local_nbid,
+         svn_node_kind_t new_kind,
+         svn_editor3_nbid_t new_parent_nbid,
+         const char *new_name,
+         const svn_editor3_node_content_t *new_content,
+         apr_pool_t *scratch_pool)
+{
+  wrapper_baton_t *eb = baton;
+
+  dbg(eb, scratch_pool, "%s : instantiate(k=%s, p=%s, n=%s, c=...)",
+      nbid_str(local_nbid, scratch_pool), svn_node_kind_to_word(new_kind),
+      nbid_str(new_parent_nbid, scratch_pool), new_name);
+  SVN_ERR(svn_editor3_instantiate(eb->wrapped_editor,
+                                  local_nbid, new_kind,
+                                  new_parent_nbid, new_name, new_content));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 wrap_copy_one(void *baton,
               svn_editor3_nbid_t local_nbid,
               svn_revnum_t src_revision,
@@ -743,6 +882,7 @@ svn_editor3__get_debug_editor(svn_editor
     wrap_rm,
     wrap_put,
     wrap_add,
+    wrap_instantiate,
     wrap_copy_one,
     wrap_copy_tree,
     wrap_delete,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c?rev=1634591&r1=1634590&r2=1634591&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c Mon Oct 27 16:52:23 2014
@@ -54,6 +54,8 @@
 
 #include "private/svn_ra_private.h"
 #include "private/svn_delta_private.h"
+#include "private/svn_string_private.h"
+#include "../libsvn_delta/debug_editor.h"
 #include "svn_private_config.h"
 
 
@@ -700,12 +702,152 @@ svn_error_t *svn_ra_rev_prop(svn_ra_sess
   return session->vtable->rev_prop(session, rev, name, value, pool);
 }
 
+/* The default branching metadata for a new repository. */
+static const char *default_repos_info
+  = "r0: fids 0 1 root-fid 0\n"
+    "f0: bids 0 1 eids 0 1 parent-fid 0\n"
+    "f0b0: root-eid 0 at .\n"
+    "f0b0e0: -1 . .\n";
+
+/* Create a new revision-root object and read the move-tracking /
+ * branch-tracking metadata from the repository into it.
+ */
+static svn_error_t *
+svn_branch_revision_fetch_info(svn_branch_revision_root_t **rev_root_p,
+                               int *next_fid_p,
+                               svn_branch_repos_t *repos,
+                               svn_ra_session_t *ra_session,
+                               svn_revnum_t revision,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool)
+{
+  svn_string_t *value;
+  svn_stream_t *stream;
+  svn_branch_revision_root_t *rev_root;
+
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
+
+  /* Read initial state from repository */
+  SVN_ERR(svn_ra_rev_prop(ra_session, revision, "svn-br-info", &value,
+                          scratch_pool));
+  if (! value && revision == 0)
+    {
+      value = svn_string_create(default_repos_info, scratch_pool);
+      SVN_DBG(("fetch_per_revision_info(r%ld): LOADED DEFAULT INFO:\n%s",
+               revision, value->data));
+      SVN_ERR(svn_ra_change_rev_prop2(ra_session, revision, "svn-br-info",
+                                      NULL, value, scratch_pool));
+    }
+  SVN_ERR_ASSERT(value);
+  stream = svn_stream_from_string(value, scratch_pool);
+
+  SVN_ERR(svn_branch_revision_root_parse(&rev_root, next_fid_p, repos, stream,
+                                         result_pool, scratch_pool));
+
+  /* Self-test: writing out the info should produce exactly the same string. */
+  {
+    svn_stringbuf_t *buf = svn_stringbuf_create_empty(scratch_pool);
+
+    stream = svn_stream_from_stringbuf(buf, scratch_pool);
+    SVN_ERR(svn_branch_revision_root_serialize(stream, rev_root, *next_fid_p,
+                                               scratch_pool));
+    SVN_ERR(svn_stream_close(stream));
+
+    SVN_ERR_ASSERT(svn_string_compare(value,
+                                      svn_stringbuf__morph_into_string(buf)));
+  }
+
+  *rev_root_p = rev_root;
+  return SVN_NO_ERROR;
+}
+
+/* Create a new repository object and read the move-tracking /
+ * branch-tracking metadata from the repository into it.
+ */
+static svn_error_t *
+svn_branch_repos_fetch_info(svn_branch_repos_t **repos_p,
+                            svn_ra_session_t *ra_session,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  svn_branch_repos_t *repos
+    = svn_branch_repos_create(result_pool);
+  svn_revnum_t base_revision;
+  svn_revnum_t r;
+
+  SVN_ERR(svn_ra_get_latest_revnum(ra_session, &base_revision, scratch_pool));
+
+  repos->next_fid = 0;
+  for (r = 0; r <= base_revision; r++)
+    {
+      svn_branch_revision_root_t *rev_root;
+      int next_fid;
+
+      SVN_ERR(svn_branch_revision_fetch_info(&rev_root, &next_fid,
+                                             repos, ra_session, r,
+                                             result_pool, scratch_pool));
+      APR_ARRAY_PUSH(repos->rev_roots, void *) = rev_root;
+      repos->next_fid = MAX(repos->next_fid, next_fid);
+    }
+
+  *repos_p = repos;
+  return SVN_NO_ERROR;
+}
+
+/* Return a mutable state for the youngest revision in REPOS.
+ */
+static svn_error_t *
+svn_branch_get_mutable_state(svn_branch_revision_root_t **rev_root_p,
+                             svn_branch_repos_t *repos,
+                             svn_ra_session_t *ra_session,
+                             svn_revnum_t base_revision,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
+{
+  int next_fid;
+
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(base_revision));
+
+  SVN_ERR(svn_branch_revision_fetch_info(rev_root_p, &next_fid,
+                                         repos, ra_session, base_revision,
+                                         result_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+/* Store the move-tracking / branch-tracking metadata from REV_ROOT into the
+ * repository.
+ */
+static svn_error_t *
+store_repos_info(svn_branch_revision_root_t *rev_root,
+                 svn_ra_session_t *ra_session,
+                 apr_pool_t *scratch_pool)
+{
+  svn_branch_repos_t *repos = rev_root->repos;
+  svn_stringbuf_t *buf = svn_stringbuf_create_empty(scratch_pool);
+  svn_stream_t *stream = svn_stream_from_stringbuf(buf, scratch_pool);
+  svn_revnum_t youngest_rev;
+
+  SVN_ERR(svn_branch_revision_root_serialize(stream, rev_root, repos->next_fid,
+                                             scratch_pool));
+
+  SVN_ERR(svn_stream_close(stream));
+  /*SVN_DBG(("store_repos_info: %s", buf->data));*/
+  SVN_ERR(svn_ra_get_latest_revnum(ra_session, &youngest_rev,
+                                   scratch_pool));
+  SVN_ERR(svn_ra_change_rev_prop2(ra_session, youngest_rev, "svn-br-info",
+                                  NULL, svn_stringbuf__morph_into_string(buf),
+                                  scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
 struct ccw_baton
 {
   svn_commit_callback2_t original_callback;
   void *original_baton;
 
   svn_ra_session_t *session;
+  svn_branch_revision_root_t *branching_txn;
 };
 
 /* Wrapper which populates the repos_root field of the commit_info struct */
@@ -719,7 +861,16 @@ commit_callback_wrapper(const svn_commit
 
   SVN_ERR(svn_ra_get_repos_root2(ccwb->session, &ci->repos_root, pool));
 
-  return ccwb->original_callback(ci, ccwb->original_baton, pool);
+  SVN_ERR(ccwb->original_callback(ci, ccwb->original_baton, pool));
+
+  /* if this commit used element-branching info, store the new info */
+  if (ccwb->branching_txn)
+    {
+      ccwb->branching_txn->rev = commit_info->revision;
+      SVN_ERR(store_repos_info(ccwb->branching_txn, ccwb->session, pool));
+    }
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -730,6 +881,7 @@ static void
 remap_commit_callback(svn_commit_callback2_t *callback,
                       void **callback_baton,
                       svn_ra_session_t *session,
+                      svn_branch_revision_root_t *branching_txn,
                       svn_commit_callback2_t original_callback,
                       void *original_baton,
                       apr_pool_t *result_pool)
@@ -746,6 +898,7 @@ remap_commit_callback(svn_commit_callbac
       struct ccw_baton *ccwb = apr_palloc(result_pool, sizeof(*ccwb));
 
       ccwb->session = session;
+      ccwb->branching_txn = branching_txn;
       ccwb->original_callback = original_callback;
       ccwb->original_baton = original_baton;
 
@@ -839,12 +992,24 @@ svn_error_t *svn_ra_get_commit_editor_ev
                                           svn_boolean_t keep_locks,
                                           apr_pool_t *pool)
 {
+  svn_revnum_t base_revision;
+  svn_branch_repos_t *repos;
+  svn_branch_revision_root_t *branching_txn;
   const svn_delta_editor_t *deditor;
   void *dedit_baton;
   svn_editor3__shim_connector_t *shim_connector;
 
+  /* ### for element-branching, currently need to start from a single base revision */
+  SVN_ERR(svn_ra_get_latest_revnum(session, &base_revision, pool));
+
+  /* load branching info */
+  SVN_ERR(svn_branch_repos_fetch_info(&repos, session, pool, pool));
+  SVN_ERR(svn_branch_get_mutable_state(&branching_txn, repos, session,
+                                       base_revision,
+                                       pool, pool));
+
   remap_commit_callback(&commit_callback, &commit_baton,
-                        session, commit_callback, commit_baton,
+                        session, branching_txn, commit_callback, commit_baton,
                         pool);
 
   SVN_ERR(session->vtable->get_commit_editor(session, &deditor, &dedit_baton,
@@ -863,10 +1028,13 @@ svn_error_t *svn_ra_get_commit_editor_ev
     SVN_ERR(svn_ra_dup_session(&fbb->session, session, repos_root_url, pool, pool));
     fbb->session_path = base_relpath;
     fbb->repos_root_url = repos_root_url;
-    SVN_ERR(svn_delta__ev3_from_delta_for_commit(
+
+    SVN_ERR(svn_delta__get_debug_editor(&deditor, &dedit_baton,
+                                        deditor, dedit_baton, "", pool));
+    SVN_ERR(svn_delta__ev3_from_delta_for_commit2(
                         editor,
                         &shim_connector,
-                        deditor, dedit_baton,
+                        deditor, dedit_baton, branching_txn,
                         repos_root_url, base_relpath,
                         svn_ra_fetch, fbb,
                         NULL, NULL /*cancel*/,
@@ -887,7 +1055,8 @@ svn_error_t *svn_ra_get_commit_editor3(s
                                        apr_pool_t *pool)
 {
   remap_commit_callback(&commit_callback, &commit_baton,
-                        session, commit_callback, commit_baton,
+                        session, NULL /*branching_txn*/,
+                        commit_callback, commit_baton,
                         pool);
 
   SVN_ERR(session->vtable->get_commit_editor(session, editor, edit_baton,
@@ -1700,7 +1869,7 @@ svn_ra__get_commit_ev2(svn_editor_t **ed
 
       /* Remap for RA layers exposing Ev1.  */
       remap_commit_callback(&commit_callback, &commit_baton,
-                            session, commit_callback, commit_baton,
+                            session, NULL, commit_callback, commit_baton,
                             result_pool);
 
       return svn_error_trace(svn_ra__use_commit_shim(