Author: gstein
Date: Fri May  4 01:39:23 2012
New Revision: 1333739

URL: http://svn.apache.org/viewvc?rev=1333739&view=rev
Log:
Ev2 shims:

The editor collects a bunch of data while in debug mode, to verify a
bunch of constraints. There are a number of other constraints we can
look for, so code up the assertions...

* subversion/libsvn_delta/editor.c:
  (MARK_PARENT_STABLE): used to mark the parent of a node as needing
    to stay where it is (no delets, move, replace).
  (VERIFY_PARENT_MAY_EXIST): there are cases wen we know a parent
    doesn't exist (thus an operation on a child is not possible), and
    this macro can catch those.
  (CHILD_DELETIONS_ALLOWED): added directories, and directories moved
    away cannot possibly have children which can be deleted. catch
    these situations.
  (mark_parent_stable): helper function for the above macro
  (svn_editor_add_directory, svn_editor_add_file,
      svn_editor_add_symlink, svn_editor_add_absent,
      svn_editor_alter_directory, svn_editor_alter_file,
      svn_editor_alter_symlink): use VERIFY_PARENT_MAY_EXIST() to
    eliminate definitely-missing parents. use MARK_PARENT_STABLE() to
    deny structural changes to the parent, now that we've performed an
    operation on a child.
  (svn_editor_delete): ensure a parent might exist, and that deletions
    are allowed in this directory. use MARK_PARENT_STABLE() now that
    we've munged a child.
  (svn_editor_copy): verify the parents of the source and destination
    might exist. stabilize the parent of the destination.
  (svn_editor_move): verify the parents of the source and destination,
    and that deletions are allowed in the source directory. mark both
    source and destination as needing to remain stable.
  (svn_editor_create): verify all parents exist and that deletions are
    allowed. mark all new parents as needing to be stable.

Modified:
    subversion/trunk/subversion/libsvn_delta/editor.c

Modified: subversion/trunk/subversion/libsvn_delta/editor.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_delta/editor.c?rev=1333739&r1=1333738&r2=1333739&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_delta/editor.c (original)
+++ subversion/trunk/subversion/libsvn_delta/editor.c Fri May  4 01:39:23 2012
@@ -129,6 +129,36 @@ static const int marker_added_dir;
 #define CHECK_UNKNOWN_CHILD(editor, relpath) \
   SVN_ERR_ASSERT(check_unknown_child(editor, relpath))
 
+/* When a child is changed in some way, mark the parent directory as needing
+   to be "stable" (no future structural changes). IOW, only allow "alter" on
+   the parent. Prevents parent-add/delete/move after any child operation.  */
+#define MARK_PARENT_STABLE(editor, relpath) \
+  mark_parent_stable(editor, relpath)
+
+/* If the parent is MARKER_ALLOW_ADD, then it has been moved-away, and we
+   know it does not exist. All other cases: it might exist.  */
+#define VERIFY_PARENT_MAY_EXIST(editor, relpath) \
+  SVN_ERR_ASSERT(apr_hash_get((editor)->completed_nodes, \
+                              svn_relpath_dirname(relpath, \
+                                                  (editor)->scratch_pool), \
+                              APR_HASH_KEY_STRING) != MARKER_ALLOW_ADD)
+
+/* If the parent is MARKER_ADDED_DIR, then we should not be deleting
+   children(*). If the parent is MARKER_ALLOW_ADD, then it has been
+   moved-away, so children cannot exist. That leaves MARKER_DONE,
+   MARKER_ALLOW_ALTER, and NULL as possible values. Just assert that
+   we didn't get either of the bad ones.
+
+   (*) if the child as added via add_*(), then it would have been marked
+   as completed and delete/move-away already test against completed nodes.
+   This test is to beware of trying to delete "children" that are not
+   actually (and can't possibly be) present.  */
+#define CHILD_DELETIONS_ALLOWED(editor, relpath) \
+  SVN_ERR_ASSERT(!allow_either(editor, \
+                               svn_relpath_dirname(relpath, \
+                                                   (editor)->scratch_pool), \
+                               MARKER_ADDED_DIR, MARKER_ALLOW_ADD))
+
 static svn_boolean_t
 allow_either(const svn_editor_t *editor,
              const char *relpath,
@@ -166,6 +196,31 @@ check_unknown_child(const svn_editor_t *
   return TRUE;
 }
 
+static void
+mark_parent_stable(const svn_editor_t *editor,
+                   const char *relpath)
+{
+  const char *parent = svn_relpath_dirname(relpath, editor->scratch_pool);
+  const void *marker = apr_hash_get(editor->completed_nodes,
+                                    parent, APR_HASH_KEY_STRING);
+
+  /* If RELPATH has already been marked (to disallow adds, or that it
+     has been fully-completed), then do nothing.  */
+  if (marker == MARKER_ALLOW_ALTER
+      || marker == MARKER_DONE
+      || marker == MARKER_ADDED_DIR)
+    return;
+
+  /* If the marker is MARKER_ALLOW_ADD, then that means the parent was
+     moved away. There is no way to work on a child. That should have
+     been tested before we got here by VERIFY_PARENT_MAY_EXIST().  */
+  SVN_ERR_ASSERT_NO_RETURN(marker != MARKER_ALLOW_ADD);
+
+  /* MARKER is NULL. Upgrade it to MARKER_ALLOW_ALTER.  */
+  apr_hash_set(editor->completed_nodes, parent, APR_HASH_KEY_STRING,
+               MARKER_ALLOW_ALTER);
+}
+
 #else
 
 /* Be wary with the definition of these macros so that we don't
@@ -192,6 +247,10 @@ check_unknown_child(const svn_editor_t *
 #define MARK_ADDED_DIR(editor, relpath)  /* empty */
 #define CHECK_UNKNOWN_CHILD(editor, relpath)  /* empty */
 
+#define MARK_PARENT_STABLE(editor, relpath)  /* empty */
+#define VERIFY_PARENT_MAY_EXIST(editor, relpath)  /* empty */
+#define CHILD_DELETIONS_ALLOWED(editor, relpath)  /* empty */
+
 #endif /* ENABLE_ORDERING_CHECK */
 
 
@@ -416,6 +475,7 @@ svn_editor_add_directory(svn_editor_t *e
   /* ### validate children are just basenames?  */
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, relpath);
   CHECK_UNKNOWN_CHILD(editor, relpath);
 
   SVN_ERR(check_cancel(editor));
@@ -430,6 +490,7 @@ svn_editor_add_directory(svn_editor_t *e
     }
 
   MARK_ADDED_DIR(editor, relpath);
+  MARK_PARENT_STABLE(editor, relpath);
   CLEAR_INCOMPLETE(editor, relpath);
 
 #ifdef ENABLE_ORDERING_CHECK
@@ -469,6 +530,7 @@ svn_editor_add_file(svn_editor_t *editor
   SVN_ERR_ASSERT(props != NULL);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, relpath);
   CHECK_UNKNOWN_CHILD(editor, relpath);
 
   SVN_ERR(check_cancel(editor));
@@ -483,6 +545,7 @@ svn_editor_add_file(svn_editor_t *editor
     }
 
   MARK_COMPLETED(editor, relpath);
+  MARK_PARENT_STABLE(editor, relpath);
   CLEAR_INCOMPLETE(editor, relpath);
 
   svn_pool_clear(editor->scratch_pool);
@@ -503,6 +566,7 @@ svn_editor_add_symlink(svn_editor_t *edi
   SVN_ERR_ASSERT(props != NULL);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, relpath);
   CHECK_UNKNOWN_CHILD(editor, relpath);
 
   SVN_ERR(check_cancel(editor));
@@ -516,6 +580,7 @@ svn_editor_add_symlink(svn_editor_t *edi
     }
 
   MARK_COMPLETED(editor, relpath);
+  MARK_PARENT_STABLE(editor, relpath);
   CLEAR_INCOMPLETE(editor, relpath);
 
   svn_pool_clear(editor->scratch_pool);
@@ -534,6 +599,7 @@ svn_editor_add_absent(svn_editor_t *edit
   SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, relpath);
   CHECK_UNKNOWN_CHILD(editor, relpath);
 
   SVN_ERR(check_cancel(editor));
@@ -547,6 +613,7 @@ svn_editor_add_absent(svn_editor_t *edit
     }
 
   MARK_COMPLETED(editor, relpath);
+  MARK_PARENT_STABLE(editor, relpath);
   CLEAR_INCOMPLETE(editor, relpath);
 
   svn_pool_clear(editor->scratch_pool);
@@ -566,6 +633,7 @@ svn_editor_alter_directory(svn_editor_t 
   SVN_ERR_ASSERT(props != NULL);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ALTER(editor, relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, relpath);
 
   SVN_ERR(check_cancel(editor));
 
@@ -579,6 +647,7 @@ svn_editor_alter_directory(svn_editor_t 
     }
 
   MARK_COMPLETED(editor, relpath);
+  MARK_PARENT_STABLE(editor, relpath);
 
   svn_pool_clear(editor->scratch_pool);
   return svn_error_trace(err);
@@ -603,6 +672,7 @@ svn_editor_alter_file(svn_editor_t *edit
     SVN_ERR_ASSERT(checksum->kind == SVN_EDITOR_CHECKSUM_KIND);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ALTER(editor, relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, relpath);
 
   SVN_ERR(check_cancel(editor));
 
@@ -617,6 +687,7 @@ svn_editor_alter_file(svn_editor_t *edit
     }
 
   MARK_COMPLETED(editor, relpath);
+  MARK_PARENT_STABLE(editor, relpath);
 
   svn_pool_clear(editor->scratch_pool);
   return svn_error_trace(err);
@@ -636,6 +707,7 @@ svn_editor_alter_symlink(svn_editor_t *e
   SVN_ERR_ASSERT(props != NULL || target != NULL);
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ALTER(editor, relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, relpath);
 
   SVN_ERR(check_cancel(editor));
 
@@ -650,6 +722,7 @@ svn_editor_alter_symlink(svn_editor_t *e
     }
 
   MARK_COMPLETED(editor, relpath);
+  MARK_PARENT_STABLE(editor, relpath);
 
   svn_pool_clear(editor->scratch_pool);
   return svn_error_trace(err);
@@ -666,6 +739,8 @@ svn_editor_delete(svn_editor_t *editor,
   SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_NOT_BE_COMPLETED(editor, relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, relpath);
+  CHILD_DELETIONS_ALLOWED(editor, relpath);
 
   SVN_ERR(check_cancel(editor));
 
@@ -678,6 +753,7 @@ svn_editor_delete(svn_editor_t *editor,
     }
 
   MARK_COMPLETED(editor, relpath);
+  MARK_PARENT_STABLE(editor, relpath);
 
   svn_pool_clear(editor->scratch_pool);
   return svn_error_trace(err);
@@ -697,6 +773,8 @@ svn_editor_copy(svn_editor_t *editor,
   SVN_ERR_ASSERT(svn_relpath_is_canonical(dst_relpath));
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_ALLOW_ADD(editor, dst_relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, src_relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, dst_relpath);
 
   SVN_ERR(check_cancel(editor));
 
@@ -710,6 +788,7 @@ svn_editor_copy(svn_editor_t *editor,
     }
 
   MARK_ALLOW_ALTER(editor, dst_relpath);
+  MARK_PARENT_STABLE(editor, dst_relpath);
   CLEAR_INCOMPLETE(editor, dst_relpath);
 
   svn_pool_clear(editor->scratch_pool);
@@ -731,6 +810,9 @@ svn_editor_move(svn_editor_t *editor,
   SHOULD_NOT_BE_FINISHED(editor);
   SHOULD_NOT_BE_COMPLETED(editor, src_relpath);
   SHOULD_ALLOW_ADD(editor, dst_relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, src_relpath);
+  CHILD_DELETIONS_ALLOWED(editor, src_relpath);
+  VERIFY_PARENT_MAY_EXIST(editor, dst_relpath);
 
   SVN_ERR(check_cancel(editor));
 
@@ -744,7 +826,9 @@ svn_editor_move(svn_editor_t *editor,
     }
 
   MARK_ALLOW_ADD(editor, src_relpath);
+  MARK_PARENT_STABLE(editor, src_relpath);
   MARK_ALLOW_ALTER(editor, dst_relpath);
+  MARK_PARENT_STABLE(editor, dst_relpath);
   CLEAR_INCOMPLETE(editor, dst_relpath);
 
   svn_pool_clear(editor->scratch_pool);
@@ -769,6 +853,8 @@ svn_editor_rotate(svn_editor_t *editor,
 
         SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
         SHOULD_NOT_BE_COMPLETED(editor, relpath);
+        VERIFY_PARENT_MAY_EXIST(editor, relpath);
+        CHILD_DELETIONS_ALLOWED(editor, relpath);
       }
   }
 #endif
@@ -790,6 +876,7 @@ svn_editor_rotate(svn_editor_t *editor,
       {
         const char *relpath = APR_ARRAY_IDX(relpaths, i, const char *);
         MARK_ALLOW_ALTER(editor, relpath);
+        MARK_PARENT_STABLE(editor, relpath);
       }
   }
 #endif


Reply via email to