Author: rhuijben
Date: Thu Jul  8 16:19:52 2010
New Revision: 961831

URL: http://svn.apache.org/viewvc?rev=961831&view=rev
Log:
Resolve issue #3676 for files: Committing a tree copy updates the last modified
revision of all descendants. Add a new test specifically for the directory
behavior.

* subversion/tests/cmdline/copy_tests.py
  (changed_data_should_match_checkout): Copy one level deeper to
    specifically test files.
  (changed_dir_data_should_match_checkout): New function. Copied from
    changed_data_should_match_checkout.
  (test_list): Remove XFail marking from changed_data_should_match_checkout
    and add changed_dir_data_should_match_checkout as XFail.

* subversion/libsvn_wc/workqueue.h
  (svn_wc__wq_add_postcommit): Allow passing changed_rev and fix other
    argument names to show where they belong.

* subversion/libsvn_wc/workqueue.c
  (log_do_committed): Accept and pass changed_rev. Rename arguments.
  (run_postcommit): Parse changed_rev from skel.
  (svn_wc__wq_add_postcommit): Put changed_rev in the skel.

* subversion/libsvn_wc/wc.h
  (svn_wc__process_committed_internal): Add top_of_recurse argument.

* subversion/libsvn_wc/deprecated.c
  (svn_wc_process_committed4): Pass TRUE for top_of_recurse.

* subversion/libsvn_wc/adm_ops.c
  (process_committed_leaf): Receive information on whether this is a
    descendant of an operation and use this to determine if changed_*
    must be kept. Remove some obsolete cases that can't happen after
    our move to sha based pristines.
  (svn_wc__process_committed_internal): Handle top_of_recurse forwarding.
  (svn_wc_process_committed_queue2): Update caller.

Modified:
    subversion/trunk/subversion/libsvn_wc/adm_ops.c
    subversion/trunk/subversion/libsvn_wc/deprecated.c
    subversion/trunk/subversion/libsvn_wc/wc.h
    subversion/trunk/subversion/libsvn_wc/workqueue.c
    subversion/trunk/subversion/libsvn_wc/workqueue.h
    subversion/trunk/subversion/tests/cmdline/copy_tests.py

Modified: subversion/trunk/subversion/libsvn_wc/adm_ops.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/adm_ops.c?rev=961831&r1=961830&r2=961831&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/trunk/subversion/libsvn_wc/adm_ops.c Thu Jul  8 16:19:52 2010
@@ -117,9 +117,10 @@ svn_wc__get_committed_queue_pool(const s
 static svn_error_t *
 process_committed_leaf(svn_wc__db_t *db,
                        const char *local_abspath,
+                       svn_boolean_t via_recurse,
                        svn_revnum_t new_revnum,
-                       apr_time_t new_date,
-                       const char *rev_author,
+                       apr_time_t new_changed_date,
+                       const char *new_changed_author,
                        apr_hash_t *new_dav_cache,
                        svn_boolean_t no_unlock,
                        svn_boolean_t keep_changelist,
@@ -131,6 +132,7 @@ process_committed_leaf(svn_wc__db_t *db,
   const svn_checksum_t *copied_checksum;
   const char *adm_abspath;
   const char *tmp_text_base_abspath;
+  svn_revnum_t new_changed_rev = new_revnum;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -190,27 +192,51 @@ process_committed_leaf(svn_wc__db_t *db,
          its checksum already. */
       if (checksum == NULL)
         {
-          /* It was copied and not modified. We should have a text
-             base for it. And the entry should have a checksum. */
-          if (copied_checksum != NULL)
-            {
-              checksum = copied_checksum;
-            }
-#ifdef SVN_DEBUG
-          else
+          /* It was copied and not modified. We must have a text
+             base for it. And the node should have a checksum. */
+          SVN_ERR_ASSERT(copied_checksum != NULL);
+
+          checksum = copied_checksum;
+
+          if (via_recurse)
             {
-              /* If we copy a deleted file, then it will become scheduled
-                 for deletion, but there is no base text for it. So we
-                 cannot get/compute a checksum for this file. */
-              SVN_ERR_ASSERT(
-                status == svn_wc__db_status_deleted
-                || status == svn_wc__db_status_obstructed_delete);
+              /* If a copied node itself is not modified, but the op_root of
+                the copy is committed we have to make sure that changed_rev,
+                changed_date and changed_author don't change or the working
+                copy used for committing will show different last modified
+                information then a clean checkout of exactly the same
+                revisions. (Issue #3676) */
+
+                svn_boolean_t props_modified;
+                svn_revnum_t changed_rev;
+                const char *changed_author;
+                apr_time_t changed_date;
+
+                SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL,
+                                             NULL, &changed_rev, &changed_date,
+                                             &changed_author, NULL, NULL, NULL,
+                                             NULL, NULL, NULL, NULL, NULL,
+                                             NULL, NULL, &props_modified, NULL,
+                                             NULL, NULL, NULL,
+                                             db, local_abspath,
+                                             scratch_pool, scratch_pool));
 
-              /* checksum will remain NULL in this one case. */
+                if (!props_modified)
+                  {
+                    /* Unmodified child of copy: We keep changed_rev */
+                    new_changed_rev = changed_rev;
+                    new_changed_date = changed_date;
+                    new_changed_author = changed_author;
+                  }
             }
-#endif
         }
     }
+  else
+    {
+      /* ### If we can determine that nothing below this node was changed
+         ### via this commit, we should keep new_changed_rev at its old
+         ### value, like how we handle files. */
+    }
 
   /* Set TMP_TEXT_BASE_ABSPATH to NULL.  The new text base will be found in
      the pristine store by its checksum. */
@@ -219,7 +245,8 @@ process_committed_leaf(svn_wc__db_t *db,
 
   SVN_ERR(svn_wc__wq_add_postcommit(db, local_abspath, tmp_text_base_abspath,
                                     new_revnum,
-                                    new_date, rev_author, checksum,
+                                    new_changed_rev, new_changed_date,
+                                    new_changed_author, checksum,
                                     new_dav_cache, keep_changelist, no_unlock,
                                     scratch_pool));
 
@@ -231,6 +258,7 @@ svn_error_t *
 svn_wc__process_committed_internal(svn_wc__db_t *db,
                                    const char *local_abspath,
                                    svn_boolean_t recurse,
+                                   svn_boolean_t top_of_recurse,
                                    svn_revnum_t new_revnum,
                                    apr_time_t new_date,
                                    const char *rev_author,
@@ -246,7 +274,7 @@ svn_wc__process_committed_internal(svn_w
 
   SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, TRUE, scratch_pool));
 
-  SVN_ERR(process_committed_leaf(db, local_abspath,
+  SVN_ERR(process_committed_leaf(db, local_abspath, !top_of_recurse,
                                  new_revnum, new_date, rev_author,
                                  new_dav_cache,
                                  no_unlock, keep_changelist,
@@ -337,6 +365,7 @@ svn_wc__process_committed_internal(svn_w
              this one committed item. */
           SVN_ERR(svn_wc__process_committed_internal(db, this_abspath,
                                                      TRUE /* recurse */,
+                                                     FALSE,
                                                      new_revnum, new_date,
                                                      rev_author,
                                                      NULL,
@@ -496,7 +525,7 @@ svn_wc_process_committed_queue2(svn_wc_c
         continue;
 
       SVN_ERR(svn_wc__process_committed_internal(wc_ctx->db, 
cqi->local_abspath,
-                                                 cqi->recurse, new_revnum,
+                                                 cqi->recurse, TRUE, 
new_revnum,
                                                  new_date, rev_author,
                                                  cqi->new_dav_cache,
                                                  cqi->no_unlock,

Modified: subversion/trunk/subversion/libsvn_wc/deprecated.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/deprecated.c?rev=961831&r1=961830&r2=961831&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_wc/deprecated.c Thu Jul  8 16:19:52 2010
@@ -655,7 +655,7 @@ svn_wc_process_committed4(const char *pa
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
   wcprop_changes_hash = svn_wc__prop_array_to_hash(wcprop_changes, pool);
-  SVN_ERR(svn_wc__process_committed_internal(db, local_abspath, recurse,
+  SVN_ERR(svn_wc__process_committed_internal(db, local_abspath, recurse, TRUE,
                                              new_revnum, new_date, rev_author,
                                              wcprop_changes_hash,
                                              !remove_lock, !remove_changelist,

Modified: subversion/trunk/subversion/libsvn_wc/wc.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc.h?rev=961831&r1=961830&r2=961831&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc.h Thu Jul  8 16:19:52 2010
@@ -242,11 +242,15 @@ svn_wc__get_committed_queue_pool(const s
  * If @a sha1_checksum is non-NULL, use it instead of @a md5_checksum to
  * identify the node's pristine text.
  * ### NOT YET IMPLEMENTED.
+ *
+ * Set TOP_OF_RECURSE to TRUE to show that this the top of a possibly
+ * recursive commit operation.
  */
 svn_error_t *
 svn_wc__process_committed_internal(svn_wc__db_t *db,
                                    const char *local_abspath,
                                    svn_boolean_t recurse,
+                                   svn_boolean_t top_of_recurse,
                                    svn_revnum_t new_revnum,
                                    apr_time_t new_date,
                                    const char *rev_author,

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.c?rev=961831&r1=961830&r2=961831&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.c Thu Jul  8 16:19:52 2010
@@ -1136,8 +1136,9 @@ log_do_committed(svn_wc__db_t *db,
                  const char *local_abspath,
                  const char *tmp_text_base_abspath,
                  svn_revnum_t new_revision,
-                 apr_time_t new_date,
-                 const char *new_author,
+                 svn_revnum_t changed_rev,
+                 apr_time_t changed_date,
+                 const char *changed_author,
                  const svn_checksum_t *new_checksum,
                  apr_hash_t *new_dav_cache,
                  svn_boolean_t keep_changelist,
@@ -1295,8 +1296,8 @@ log_do_committed(svn_wc__db_t *db,
       apr_time_t last_mod_time;
 
       SVN_ERR(svn_wc__db_global_commit(db, local_abspath,
-                                       new_revision,
-                                       new_revision, new_date, new_author,
+                                       new_revision, changed_rev,
+                                       changed_date, changed_author,
                                        new_checksum,
                                        NULL /* new_children */,
                                        new_dav_cache,
@@ -1380,8 +1381,8 @@ log_do_committed(svn_wc__db_t *db,
   /* It's not a file, so it's a directory. */
 
   SVN_ERR(svn_wc__db_global_commit(db, local_abspath,
-                                   new_revision,
-                                   new_revision, new_date, new_author,
+                                   new_revision, changed_rev,
+                                   changed_date, changed_author,
                                    NULL /* new_checksum */,
                                    NULL /* new_children */,
                                    new_dav_cache,
@@ -1425,9 +1426,9 @@ run_postcommit(svn_wc__db_t *db,
   const svn_skel_t *arg1 = work_item->children->next;
   const svn_skel_t *arg5 = work_item->children->next->next->next->next->next;
   const char *local_abspath;
-  svn_revnum_t new_revision;
-  apr_time_t new_date;
-  const char *new_author;
+  svn_revnum_t new_revision, changed_rev;
+  apr_time_t changed_date;
+  const char *changed_author;
   const svn_checksum_t *new_checksum;
   apr_hash_t *new_dav_cache;
   svn_boolean_t keep_changelist, no_unlock;
@@ -1436,13 +1437,13 @@ run_postcommit(svn_wc__db_t *db,
 
   local_abspath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
   new_revision = (svn_revnum_t)svn_skel__parse_int(arg1->next, scratch_pool);
-  new_date = svn_skel__parse_int(arg1->next->next, scratch_pool);
+  changed_date = svn_skel__parse_int(arg1->next->next, scratch_pool);
   if (arg1->next->next->next->len == 0)
-    new_author = NULL;
+    changed_author = NULL;
   else
-    new_author = apr_pstrmemdup(scratch_pool,
-                                arg1->next->next->next->data,
-                                arg1->next->next->next->len);
+    changed_author = apr_pstrmemdup(scratch_pool,
+                                    arg1->next->next->next->data,
+                                    arg1->next->next->next->len);
   if (arg5->len == 0)
     {
       new_checksum = NULL;
@@ -1476,9 +1477,15 @@ run_postcommit(svn_wc__db_t *db,
   else
     no_unlock = TRUE;
 
+  if (arg5->next->next->next->next->next)
+    changed_rev = svn_skel__parse_int(arg5->next->next->next->next->next,
+                                      scratch_pool);
+  else
+    changed_rev = new_revision; /* Behavior before fixing issue #3676 */
+
   err = log_do_committed(db, local_abspath, tmp_text_base_abspath,
-                         new_revision, new_date,
-                         new_author, new_checksum, new_dav_cache,
+                         new_revision, changed_rev, changed_date,
+                         changed_author, new_checksum, new_dav_cache,
                          keep_changelist, no_unlock,
                          cancel_func, cancel_baton,
                          scratch_pool);
@@ -1497,8 +1504,9 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
                           const char *local_abspath,
                           const char *tmp_text_base_abspath,
                           svn_revnum_t new_revision,
-                          apr_time_t new_date,
-                          const char *new_author,
+                          svn_revnum_t changed_rev,
+                          apr_time_t changed_date,
+                          const char *changed_author,
                           const svn_checksum_t *new_checksum,
                           apr_hash_t *new_dav_cache,
                           svn_boolean_t keep_changelist,
@@ -1507,6 +1515,7 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
 {
   svn_skel_t *work_item = svn_skel__make_empty_list(scratch_pool);
 
+  svn_skel__prepend_int(changed_rev, work_item, scratch_pool);
   svn_skel__prepend_int(no_unlock, work_item, scratch_pool);
   svn_skel__prepend_str(tmp_text_base_abspath ? tmp_text_base_abspath : "",
                         work_item, scratch_pool);
@@ -1528,8 +1537,8 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
                                                    scratch_pool, scratch_pool)
                           : "",
                         work_item, scratch_pool);
-  svn_skel__prepend_str(new_author ? new_author : "", work_item, scratch_pool);
-  svn_skel__prepend_int(new_date, work_item, scratch_pool);
+  svn_skel__prepend_str(changed_author ? changed_author : "", work_item, 
scratch_pool);
+  svn_skel__prepend_int(changed_date, work_item, scratch_pool);
   svn_skel__prepend_int(new_revision, work_item, scratch_pool);
   svn_skel__prepend_str(local_abspath, work_item, scratch_pool);
   svn_skel__prepend_str(OP_POSTCOMMIT, work_item, scratch_pool);

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.h?rev=961831&r1=961830&r2=961831&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.h Thu Jul  8 16:19:52 2010
@@ -281,8 +281,9 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
                           const char *local_abspath,
                           const char *tmp_text_base_abspath,
                           svn_revnum_t new_revision,
-                          apr_time_t new_date,
-                          const char *new_author,
+                          svn_revnum_t changed_rev,
+                          apr_time_t changed_date,
+                          const char *changed_author,
                           const svn_checksum_t *new_checksum,
                           apr_hash_t *new_dav_cache,
                           svn_boolean_t keep_changelist,

Modified: subversion/trunk/subversion/tests/cmdline/copy_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/copy_tests.py?rev=961831&r1=961830&r2=961831&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/copy_tests.py Thu Jul  8 16:19:52 
2010
@@ -4633,6 +4633,35 @@ def changed_data_should_match_checkout(s
 
   sbox.build()
   wc_dir = sbox.wc_dir
+  A_B_E = os.path.join(wc_dir, 'A', 'B', 'E')
+  E_new = os.path.join(wc_dir, 'E_new')
+
+  verify_dir = sbox.add_wc_path('verify')
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'copy', A_B_E, E_new)
+
+  sbox.simple_commit(wc_dir)
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'co', sbox.repo_url, 
verify_dir)
+
+  was_cwd = os.getcwd()
+  os.chdir(verify_dir)
+
+  rv, verify_out, err = main.run_svn(None, 'status', '-v')
+
+  os.chdir(was_cwd)
+  os.chdir(wc_dir)
+  svntest.actions.run_and_verify_svn(None, verify_out, [], 'status', '-v')
+  os.chdir(was_cwd)
+
+# Regression test for issue #3676 for copies including directories
+def changed_dir_data_should_match_checkout(sbox):
+  """changed dir after commit should match checkout"""
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
   A_B = os.path.join(wc_dir, 'A', 'B')
   B_new = os.path.join(wc_dir, 'B_new')
 
@@ -4747,7 +4776,8 @@ test_list = [ None,
               SkipUnless(copy_broken_symlink, svntest.main.is_posix_os),
               move_dir_containing_move,
               copy_dir_with_space,
-              XFail(changed_data_should_match_checkout),
+              changed_data_should_match_checkout,
+              XFail(changed_dir_data_should_match_checkout),
              ]
 
 if __name__ == '__main__':


Reply via email to