Author: rhuijben
Date: Tue Feb 24 13:01:50 2015
New Revision: 1661930

URL: http://svn.apache.org/r1661930
Log:
Create '1.9.x-commit-fixes' branch based of the '1.9.x-db-verify' branch

* subversion/libsvn_client/commit.c (r1661363)
  (post_process_commit_item): Request removing locks on restructuring
    operations. Even though the node itself has no locks, shadowed
    descendants might. (And the repository handles this the same way)

* subversion/libsvn_wc/wc-queries.sql:
  (STMT_COMMIT_DESCENDANTS_TO_BASE): Properly set moved_to to NULL. (r1660781)
  
  (STMT_SELECT_MOVED_DESCENDANTS_SHD, (r1661718)
   STMT_SELECT_MOVED_DESCENDANTS_SRC): Also scan the node itself for moves.

* subversion/libsvn_wc/wc_db.c
  (db_base_remove): Use internal api.

  (moved_descendant_collect): New function, extracted from...
  (moved_descendant_commit): ... this. Switch key/value to avoid overwriting.

  (commit_node):
    Remove unused argument. (r1661730)
    Handle deletes (r1661504)
    Fix lock removal (r1660781, r1661363)
    Properly break moves on both sides (r1660781)

  (svn_wc__db_global_commit): Update caller. Remove unused argument. (r1661730)

  (process_committed_leaf): Use commit_node for deletes (r1661504)

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_global_commit): Remove unused argument. (r1661730)

* subversion/tests/cmdline/lock_tests.py (r1661335,1661363)
  (break_delete_add): Remove XFail
  (delete_dir_with_lots_of_locked_files): Use multi-lock operation.
  (delete_locks_on_depth_commit): New test.
  (test_list): Add delete_locks_on_depth_commit.

* subversion/tests/libsvn_wc/op-depth-test.c
  (verify_db_callback,
   verify_db): New functions. (r1661718)
  (insert_dirs): Support adding moves. (r1661755)
  (commit_moved_descendant,
   commit_moved_away_descendant): Extend tests.
  (test_global_commit): New test. (r1661755)
  (test_funcs): Add test_global_commit.

* subversion/tests/libsvn_wc/wc-test-queries.sql
  (STMT_INSERT_NODE): Add data to more columns. (r1661755)

Added:
    subversion/branches/1.9.x-commit-fixes/   (props changed)
      - copied from r1661922, subversion/branches/1.9.x-db-verify/
Modified:
    subversion/branches/1.9.x-commit-fixes/subversion/libsvn_client/commit.c
    subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc-queries.sql
    subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.c
    subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.h
    
subversion/branches/1.9.x-commit-fixes/subversion/tests/cmdline/lock_tests.py
    
subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/op-depth-test.c
    
subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/wc-test-queries.sql

Propchange: subversion/branches/1.9.x-commit-fixes/
------------------------------------------------------------------------------
--- bugtraq:logregex (added)
+++ bugtraq:logregex Tue Feb 24 13:01:50 2015
@@ -0,0 +1,2 @@
+[Ii]ssues?:?(\s*(,|and)?\s*#\d+)+
+(\d+)

Propchange: subversion/branches/1.9.x-commit-fixes/
------------------------------------------------------------------------------
    bugtraq:url = http://subversion.tigris.org/issues/show_bug.cgi?id=%BUGID%

Propchange: subversion/branches/1.9.x-commit-fixes/
------------------------------------------------------------------------------
--- svn:auto-props (added)
+++ svn:auto-props Tue Feb 24 13:01:50 2015
@@ -0,0 +1,13 @@
+*.c = svn:eol-style=native
+*.cpp = svn:eol-style=native
+*.h = svn:eol-style=native
+*.hpp = svn:eol-style=native
+*.java = svn:eol-style=native
+*.py = svn:eol-style=native
+*.pl = svn:eol-style=native
+*.rb = svn:eol-style=native
+*.sql = svn:eol-style=native
+*.txt = svn:eol-style=native
+README = svn:eol-style=native
+BRANCH-README = svn:eol-style=native
+STATUS = svn:eol-style=native

Propchange: subversion/branches/1.9.x-commit-fixes/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Tue Feb 24 13:01:50 2015
@@ -0,0 +1,57 @@
+ChangeLog*
+Makefile
+config.cache
+config.log
+config.nice
+config.status
+configure
+libtool
+.gdb_history
+.swig_checked
+*.orig
+*.rej
+TAGS
+tags
+neon
+build-outputs.mk
+autogen-standalone.mk
+autom4te.cache
+gen-make.opts
+tests.log*
+fails.log*
+db4-win32
+db
+*.o
+*~
+.*~
+apr
+apr-util
+apr-iconv
+Release
+Debug
+ipch
+subversion_msvc.dsw
+subversion_msvc.ncb
+subversion_msvc.opt
+subversion_msvc.plg
+subversion_vcnet.sln
+subversion_vcnet.ncb
+subversion_vcnet.suo
+subversion_vcnet.v11.suo
+subversion_vcnet.sdf
+subversion_vcnet.opensdf
+mkmf.log
+.project
+.classpath
+.cdtproject
+.settings
+.cproject
+zlib
+sqlite-amalgamation
+serf
+gmock-fused
+.git
+.gitignore
+compile_commands.json
+.kdev4
+*.kdev4

Propchange: subversion/branches/1.9.x-commit-fixes/
------------------------------------------------------------------------------
--- svn:mergeinfo (added)
+++ svn:mergeinfo Tue Feb 24 13:01:50 2015
@@ -0,0 +1,92 @@
+/subversion/branches/1.5.x-r30215:870312
+/subversion/branches/1.7.x-fs-verify:1146708,1161180
+/subversion/branches/10Gb:1388102,1388163-1388190,1388195,1388202,1388205,1388211,1388276,1388362,1388375,1388394,1388636,1388639-1388640,1388643-1388644,1388654,1388720,1388789,1388795,1388801,1388805,1388807,1388810,1388816,1389044,1389276,1389289,1389662,1389867,1390017,1390209,1390216,1390407,1390409,1390414,1390419,1390955
+/subversion/branches/atomic-revprop:965046-1000689
+/subversion/branches/authzperf:1615360
+/subversion/branches/auto-props-sdc:1384106-1401643
+/subversion/branches/bdb-reverse-deltas:872050-872529
+/subversion/branches/cache-server:1458643-1476567
+/subversion/branches/diff-callbacks3:870059-870761
+/subversion/branches/diff-optimizations:1031270-1037352
+/subversion/branches/diff-optimizations-bytes:1037353-1067789
+/subversion/branches/dont-save-plaintext-passwords-by-default:870728-871118
+/subversion/branches/double-delete:870511-872970
+/subversion/branches/dump-load-cross-check:1654853-1657295
+/subversion/branches/ev2-export:1325914,1332738,1413107
+/subversion/branches/explore-wc:875486,875493,875497,875507,875511,875514,875559,875580-875581,875584,875587,875611,875627,875647,875667-875668,875711-875712,875733-875734,875736,875744-875748,875751,875758,875782,875795-875796,875830,875836,875838,875842,875852,875855,875864,875870,875873,875880,875885-875888,875890,875897-875898,875905,875907-875909,875935,875943-875944,875946,875979,875982-875983,875985-875986,875990,875997
+/subversion/branches/file-externals:871779-873302
+/subversion/branches/fs-rep-sharing:869036-873803
+/subversion/branches/fsfs-format7:1426304,1430673,1433848,1438408,1438982,1441129,1442051,1442068,1442504,1442910,1443171,1443803,1444690,1444693,1444695,1445040,1445080,1446103,1451129,1453590,1454307,1460579,1461851,1461865,1462837,1462904,1463120,1467362,1467382,1469487,1471208,1477166,1478055,1481447,1489817,1489949,1490673-1490674,1491784,1493042,1498029,1498103,1498155,1500054,1507729-1507731,1507735-1507736
+/subversion/branches/fsfs-improvements:1499981-1547039
+/subversion/branches/fsfs-lock-many:1571740-1577217
+/subversion/branches/fsfs-pack:873717-874575
+/subversion/branches/fsx:1507845-1509914
+/subversion/branches/fsx-id:1645603-1649011
+/subversion/branches/gnome-keyring:870558-871410
+/subversion/branches/gpg-agent-password-store:1005036-1150766
+/subversion/branches/gtest_addition:1452117-1502138
+/subversion/branches/http-protocol-v2:874395-876041
+/subversion/branches/in-memory-cache:869829-871452
+/subversion/branches/in-repo-authz:1414342-1424779
+/subversion/branches/inheritable-props:1297080-1395089
+/subversion/branches/integrate-cache-item-serialization:1068724-1068739
+/subversion/branches/integrate-cache-membuffer:998649-998852
+/subversion/branches/integrate-compression-level:1068651-1072287
+/subversion/branches/integrate-io-improvements:1068684-1072297
+/subversion/branches/integrate-is-cachable:1072568-1074082
+/subversion/branches/integrate-partial-getter:1072558-1076552
+/subversion/branches/integrate-readline-speedup:1072553-1072555
+/subversion/branches/integrate-stream-api-extensions:1068695-1072516
+/subversion/branches/integrate-string-improvements:1068251-1190617
+/subversion/branches/integrate-txdelta-caching:1072541-1078213
+/subversion/branches/issue-2779-dev:965496-984198
+/subversion/branches/issue-2843-dev:871432-874179
+/subversion/branches/issue-3000:871713,871716-871719,871721-871726,871728,871734
+/subversion/branches/issue-3067-deleted-subtrees:873375-874084
+/subversion/branches/issue-3148-dev:875193-875204
+/subversion/branches/issue-3220-dev:872210-872226
+/subversion/branches/issue-3242-dev:879653-896436
+/subversion/branches/issue-3334-dirs:875156-875867
+/subversion/branches/issue-3975:1152931-1160746
+/subversion/branches/issue-4116-dev:1424719-1425040
+/subversion/branches/issue-4194-dev:1410507-1414880
+/subversion/branches/javahl-ra:991978-1494640
+/subversion/branches/kwallet:870785-871314
+/subversion/branches/log-addressing:1509279-1546844
+/subversion/branches/log-g-performance:870941-871032
+/subversion/branches/merge-skips-obstructions:874525-874615
+/subversion/branches/move-tracking-2:1607334
+/subversion/branches/multi-layer-moves:1239019-1300930
+/subversion/branches/nfc-nfd-aware-client:870276,870376
+/subversion/branches/node_pool:1304828-1305388
+/subversion/branches/performance:979193,980118,981087,981090,981189,981194,981287,981684,981827,982043,982355,983398,983406,983430,983474,983488,983490,983760,983764,983766,983770,984927,984973,984984,985014,985037,985046,985472,985477,985482,985487-985488,985493,985497,985500,985514,985601,985603,985606,985669,985673,985695,985697,986453,986465,986485,986491-986492,986517,986521,986605,986608,986817,986832,987865,987868-987869,987872,987886-987888,987893,988319,988898,990330,990533,990535-990537,990541,990568,990572,990574-990575,990600,990759,992899,992904,992911,993127,993141,994956,995478,995507,995603,998012,998858,999098,1001413,1001417,1004291,1022668,1022670,1022676,1022715,1022719,1025660,1025672,1027193,1027203,1027206,1027214,1027227,1028077,1028092,1028094,1028104,1028107,1028111,1028354,1029038,1029042-1029043,1029054-1029055,1029062-1029063,1029078,1029080,1029090,1029092-1029093,1029111,1029151,1029158,1029229-1029230,1029232,1029335-1029336,1029339-1029340,1029342,10
 
29344,1030763,1030827,1031203,1031235,1032285,1032333,1033040,1033057,1033294,1035869,1035882,1039511,1043705,1053735,1056015,1066452,1067683,1067697-1078365
+/subversion/branches/pin-externals:1643757-1659392
+/subversion/branches/py-tests-as-modules:956579-1033052
+/subversion/branches/ra_serf-digest-authn:875693-876404
+/subversion/branches/reintegrate-improvements:873853-874164
+/subversion/branches/remote-only-status:1581845-1586090
+/subversion/branches/revprop-cache:1298521-1326293
+/subversion/branches/revprop-caching-ng:1620597,1620599
+/subversion/branches/revprop-packing:1143907,1143971,1143997,1144017,1144499,1144568,1146145
+/subversion/branches/subtree-mergeinfo:876734-878766
+/subversion/branches/svn-auth-x509:1603509-1655900
+/subversion/branches/svn-info-detail:1660035-1660413
+/subversion/branches/svn-mergeinfo-enhancements:870119-870195,870197-870288
+/subversion/branches/svn-patch-improvements:918519-934609
+/subversion/branches/svn_mutex:1141683-1182099
+/subversion/branches/svnpatch-diff:865738-876477
+/subversion/branches/svnraisetc:874709-875149
+/subversion/branches/svnserve-logging:869828-870893
+/subversion/branches/tc-issue-3334:874697-874773
+/subversion/branches/tc-merge-notify:874017-874062
+/subversion/branches/tc-resolve:874191-874239
+/subversion/branches/tc_url_rev:874351-874483
+/subversion/branches/tree-conflicts:868291-873154
+/subversion/branches/tree-conflicts-notify:873926-874008
+/subversion/branches/tristate-chunked-request:1502394-1502681
+/subversion/branches/tweak-build-take-two:1424288-1425049,1425051-1425613
+/subversion/branches/uris-as-urls:1060426-1064427
+/subversion/branches/verify-at-commit:1462039-1462408
+/subversion/branches/verify-keep-going:1439280-1546110
+/subversion/branches/wc-collate-path:1402685-1480384
+/subversion/trunk:1660587,1660610,1660633,1660641,1660659,1660671,1660687,1660758,1660781,1660874,1660928,1660955,1660961,1661335,1661363,1661504,1661730,1661755,1661890

Propchange: subversion/branches/1.9.x-commit-fixes/
------------------------------------------------------------------------------
    tsvn:logwidthmarker = 78

Propchange: subversion/branches/1.9.x-commit-fixes/
------------------------------------------------------------------------------
    webviewer:revision = http://svn.apache.org/r%REVISION%

Modified: 
subversion/branches/1.9.x-commit-fixes/subversion/libsvn_client/commit.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.9.x-commit-fixes/subversion/libsvn_client/commit.c?rev=1661930&r1=1661922&r2=1661930&view=diff
==============================================================================
--- subversion/branches/1.9.x-commit-fixes/subversion/libsvn_client/commit.c 
(original)
+++ subversion/branches/1.9.x-commit-fixes/subversion/libsvn_client/commit.c 
Tue Feb 24 13:01:50 2015
@@ -240,7 +240,9 @@ post_process_commit_item(svn_wc_committe
     loop_recurse = TRUE;
 
   remove_lock = (! keep_locks && (item->state_flags
-                                       & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN));
+                                       & (SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN
+                                          | SVN_CLIENT_COMMIT_ITEM_ADD
+                                          | SVN_CLIENT_COMMIT_ITEM_DELETE)));
 
   /* When the node was deleted (or replaced), we need to always remove the
      locks, as they're invalidated on the server. We cannot honor the

Modified: 
subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc-queries.sql
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc-queries.sql?rev=1661930&r1=1661922&r2=1661930&view=diff
==============================================================================
--- subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc-queries.sql 
(original)
+++ subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc-queries.sql 
Tue Feb 24 13:01:50 2015
@@ -378,6 +378,7 @@ UPDATE NODES SET op_depth = 0,
                  revision = ?6,
                  dav_cache = NULL,
                  moved_here = NULL,
+                 moved_to = NULL,
                  presence = CASE presence
                               WHEN MAP_NORMAL THEN MAP_NORMAL
                               WHEN MAP_EXCLUDED THEN MAP_EXCLUDED
@@ -1688,7 +1689,7 @@ JOIN nodes n ON n.wc_id = ?1 AND n.local
                  WHERE d.wc_id = ?1 AND d.local_relpath = ?2
                    AND d.op_depth < ?3)
 WHERE s.wc_id = ?1 AND s.op_depth = ?3
-  AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
+  AND (s.local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2))
   AND s.moved_to IS NOT NULL
 
 /* This statement is very similar to STMT_SELECT_MOVED_DESCENDANTS_SHD,
@@ -1703,7 +1704,7 @@ JOIN nodes s ON s.wc_id = n.wc_id AND s.
                       AND d.local_relpath = s.local_relpath
                       AND d.op_depth > ?3)
 WHERE n.wc_id = ?1 AND n.op_depth = ?3
-  AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2)
+  AND (n.local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2))
   AND s.moved_to IS NOT NULL
 
 -- STMT_COMMIT_UPDATE_ORIGIN

Modified: subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.c?rev=1661930&r1=1661922&r2=1661930&view=diff
==============================================================================
--- subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.c 
(original)
+++ subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.c Tue Feb 
24 13:01:50 2015
@@ -2251,12 +2251,9 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
   if (status == svn_wc__db_status_normal
       && keep_as_working)
     {
-      SVN_ERR(svn_wc__db_op_make_copy(db,
-                                      svn_dirent_join(wcroot->abspath,
-                                                      local_relpath,
-                                                      scratch_pool),
-                                      NULL, NULL,
-                                      scratch_pool));
+      SVN_ERR(svn_wc__db_op_make_copy_internal(wcroot, local_relpath,
+                                               NULL, NULL,
+                                               scratch_pool));
       keep_working = TRUE;
     }
   else
@@ -11383,35 +11380,18 @@ determine_repos_info(apr_int64_t *repos_
   return SVN_NO_ERROR;
 }
 
-/* Helper for svn_wc__db_global_commit()
-
-   Makes local_relpath and all its descendants at the same op-depth represent
-   the copy origin repos_id:repos_relpath@revision.
-
-   This code is only valid to fix-up a move from an old location, to a new
-   location during a commit.
-
-   Assumptions:
-     * local_relpath is not the working copy root (can't be moved)
-     * repos_relpath is not the repository root (can't be moved)
-   */
 static svn_error_t *
-moved_descendant_commit(svn_wc__db_wcroot_t *wcroot,
+moved_descendant_collect(apr_hash_t **map,
+                        svn_wc__db_wcroot_t *wcroot,
                         const char *local_relpath,
                         int op_depth,
-                        apr_int64_t repos_id,
-                        const char *repos_relpath,
-                        svn_revnum_t revision,
+                        apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool)
 {
-  apr_hash_t *children;
-  apr_pool_t *iterpool;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-  apr_hash_index_t *hi;
 
-  SVN_ERR_ASSERT(*local_relpath != '\0'
-                 && *repos_relpath != '\0');
+  *map = NULL;
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_MOVED_DESCENDANTS_SRC));
@@ -11423,21 +11403,56 @@ moved_descendant_commit(svn_wc__db_wcroo
   if (! have_row)
     return svn_error_trace(svn_sqlite__reset(stmt));
 
-  children = apr_hash_make(scratch_pool);
-
-  /* First, obtain all moved descendants */
-  /* To keep error handling simple, first cache them in a hashtable */
+  /* Find all moved descendants. Key them on target, because that is
+     always unique */
   while (have_row)
     {
-      const char *src_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
-      const char *to_relpath = svn_sqlite__column_text(stmt, 4, scratch_pool);
+      const char *src_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
+      const char *to_relpath = svn_sqlite__column_text(stmt, 4, result_pool);
+
+      if (!*map)
+        *map = apr_hash_make(result_pool);
 
-      svn_hash_sets(children, src_relpath, to_relpath);
+      svn_hash_sets(*map, to_relpath, src_relpath);
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
   SVN_ERR(svn_sqlite__reset(stmt));
 
+  return SVN_NO_ERROR;
+}
+
+/* Helper for svn_wc__db_global_commit()
+
+   Makes local_relpath and all its descendants at the same op-depth represent
+   the copy origin repos_id:repos_relpath@revision.
+
+   This code is only valid to fix-up a move from an old location, to a new
+   location during a commit.
+
+   Assumptions:
+     * local_relpath is not the working copy root (can't be moved)
+     * repos_relpath is not the repository root (can't be moved)
+ */
+static svn_error_t *
+moved_descendant_commit(svn_wc__db_wcroot_t *wcroot,
+                        const char *local_relpath,
+                        apr_int64_t repos_id,
+                        const char *repos_relpath,
+                        svn_revnum_t revision,
+                        apr_hash_t *children,
+                        apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool;
+  svn_sqlite__stmt_t *stmt;
+  apr_hash_index_t *hi;
+
+  SVN_ERR_ASSERT(*local_relpath != '\0'
+                 && *repos_relpath != '\0');
+
+  if (!children)
+    return SVN_NO_ERROR;
+
   /* Then update them */
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_COMMIT_UPDATE_ORIGIN));
@@ -11445,11 +11460,12 @@ moved_descendant_commit(svn_wc__db_wcroo
   iterpool = svn_pool_create(scratch_pool);
   for (hi = apr_hash_first(scratch_pool, children); hi; hi = apr_hash_next(hi))
     {
-      const char *src_relpath = apr_hash_this_key(hi);
-      const char *to_relpath = apr_hash_this_val(hi);
+      const char *src_relpath = apr_hash_this_val(hi);
+      const char *to_relpath = apr_hash_this_key(hi);
       const char *new_repos_relpath;
       int to_op_depth = relpath_depth(to_relpath);
       int affected;
+      apr_hash_t *map;
 
       svn_pool_clear(iterpool);
 
@@ -11476,9 +11492,11 @@ moved_descendant_commit(svn_wc__db_wcroo
       SVN_ERR_ASSERT(affected >= 1); /* If this fails there is no move dest */
 #endif
 
-      SVN_ERR(moved_descendant_commit(wcroot, to_relpath, to_op_depth,
+      SVN_ERR(moved_descendant_collect(&map, wcroot, to_relpath, to_op_depth,
+                                       iterpool, iterpool));
+      SVN_ERR(moved_descendant_commit(wcroot, to_relpath,
                                       repos_id, new_repos_relpath, revision,
-                                      iterpool));
+                                      map, iterpool));
     }
 
   svn_pool_destroy(iterpool);
@@ -11537,7 +11555,6 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
             apr_time_t changed_date,
             const char *changed_author,
             const svn_checksum_t *new_checksum,
-            const apr_array_header_t *new_children,
             apr_hash_t *new_dav_cache,
             svn_boolean_t keep_changelist,
             svn_boolean_t no_unlock,
@@ -11559,6 +11576,7 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
   const char *repos_relpath;
   int op_depth;
   svn_wc__db_status_t old_presence;
+  svn_boolean_t moved_here;
 
     /* If we are adding a file or directory, then we need to get
      repository information from the parent node since "this node" does
@@ -11588,6 +11606,7 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
 
   /* Figure out the new node's kind. It will be whatever is in WORKING_NODE,
      or there will be a BASE_NODE that has it.  */
+  old_presence = svn_sqlite__column_token(stmt_info, 3, presence_map);
   new_kind = svn_sqlite__column_token(stmt_info, 4, kind_map);
 
   /* What will the new depth be?  */
@@ -11606,26 +11625,35 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
                             svn_sqlite__column_text(stmt_info, 2, NULL)) == 0);
     }
 
-  /* Find the appropriate new properties -- ACTUAL overrides any properties
-     in WORKING that arrived as part of a copy/move.
+  if (old_presence != svn_wc__db_status_base_deleted)
+    {
+      /* Find the appropriate new properties -- ACTUAL overrides any properties
+         in WORKING that arrived as part of a copy/move.
 
-     Note: we'll keep them as a big blob of data, rather than
-     deserialize/serialize them.  */
-  if (have_act)
-    prop_blob.data = svn_sqlite__column_blob(stmt_act, 1, &prop_blob.len,
-                                             scratch_pool);
-  if (prop_blob.data == NULL)
-    prop_blob.data = svn_sqlite__column_blob(stmt_info, 14, &prop_blob.len,
-                                             scratch_pool);
-
-  inherited_prop_blob.data = svn_sqlite__column_blob(stmt_info, 16,
-                                                     &inherited_prop_blob.len,
-                                                     scratch_pool);
+         Note: we'll keep them as a big blob of data, rather than
+         deserialize/serialize them.  */
+      if (have_act)
+        prop_blob.data = svn_sqlite__column_blob(stmt_act, 1, &prop_blob.len,
+                                                 scratch_pool);
+      if (prop_blob.data == NULL)
+        prop_blob.data = svn_sqlite__column_blob(stmt_info, 14, &prop_blob.len,
+                                                 scratch_pool);
 
-  if (keep_changelist && have_act)
-    changelist = svn_sqlite__column_text(stmt_act, 0, scratch_pool);
+      inherited_prop_blob.data = svn_sqlite__column_blob(
+                                            stmt_info, 16,
+                                            &inherited_prop_blob.len,
+                                            scratch_pool);
 
-  old_presence = svn_sqlite__column_token(stmt_info, 3, presence_map);
+      if (keep_changelist && have_act)
+        changelist = svn_sqlite__column_text(stmt_act, 0, scratch_pool);
+
+      moved_here = svn_sqlite__column_int(stmt_info, 15);
+    }
+  else
+    {
+      moved_here = FALSE;
+      changelist = NULL;
+    }
 
   /* ### other stuff?  */
 
@@ -11636,6 +11664,24 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
     {
       int affected_rows;
 
+      SVN_ERR_ASSERT(op_depth == relpath_depth(local_relpath));
+
+      /* First clear the moves that we are going to delete in a bit */
+      {
+        apr_hash_t *old_moves;
+        apr_hash_index_t *hi;
+        SVN_ERR(moved_descendant_collect(&old_moves, wcroot, local_relpath, 0,
+                                         scratch_pool, scratch_pool));
+
+        if (old_moves)
+          for (hi = apr_hash_first(scratch_pool, old_moves);
+                hi; hi = apr_hash_next(hi))
+            {
+              SVN_ERR(clear_moved_here(wcroot, apr_hash_this_key(hi),
+                                        scratch_pool));
+            }
+      }
+
       /* This removes all layers of this node and at the same time determines
          if we need to remove shadowed layers below our descendants. */
 
@@ -11668,26 +11714,40 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
          be integrated, they really affect a different op-depth and
          completely different nodes (via a different recursion pattern). */
 
-      /* Collapse descendants of the current op_depth in layer 0 */
-      SVN_ERR(descendant_commit(wcroot, local_relpath, op_depth,
-                                repos_id, repos_relpath, new_revision,
-                                scratch_pool));
+      if (old_presence != svn_wc__db_status_base_deleted)
+        {
+          /* Collapse descendants of the current op_depth to layer 0,
+             this includes moved-from/to clearing */
+          SVN_ERR(descendant_commit(wcroot, local_relpath, op_depth,
+                                    repos_id, repos_relpath, new_revision,
+                                    scratch_pool));
+        }
 
-      /* And make the recorded local moves represent moves of the node we just
-         committed. */
-      SVN_ERR(moved_descendant_commit(wcroot, local_relpath, 0,
+      if (old_presence != svn_wc__db_status_base_deleted)
+        {
+          apr_hash_t *moves = NULL;
+
+          SVN_ERR(moved_descendant_collect(&moves, wcroot, local_relpath, 0,
+                                           scratch_pool, scratch_pool));
+
+          /* And make the recorded local moves represent moves of the node we
+             just committed. */
+          SVN_ERR(moved_descendant_commit(wcroot, local_relpath,
                                       repos_id, repos_relpath, new_revision,
-                                      scratch_pool));
+                                      moves, scratch_pool));
+        }
 
-      /* This node is no longer modified, so no node was moved here */
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_CLEAR_MOVED_TO_FROM_DEST));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
-                                            local_relpath));
+      if (moved_here)
+        {
+          /* This node is no longer modified, so no node was moved here */
+          SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                            STMT_CLEAR_MOVED_TO_FROM_DEST));
+          SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
+                                                local_relpath));
 
-      SVN_ERR(svn_sqlite__step_done(stmt));
+          SVN_ERR(svn_sqlite__step_done(stmt));
+        }
     }
-
   /* Update or add the BASE_NODE row with all the new information.  */
 
   if (*local_relpath == '\0')
@@ -11696,38 +11756,56 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
     parent_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
 
   /* Preserve any incomplete status */
-  new_presence = (old_presence == svn_wc__db_status_incomplete
-                  ? svn_wc__db_status_incomplete
-                  : svn_wc__db_status_normal);
+  if (old_presence != svn_wc__db_status_base_deleted)
+    {
+      new_presence = (old_presence == svn_wc__db_status_incomplete
+                      ? svn_wc__db_status_incomplete
+                      : svn_wc__db_status_normal);
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_APPLY_CHANGES_TO_BASE_NODE));
-  /* symlink_target not yet used */
-  SVN_ERR(svn_sqlite__bindf(stmt, "issisrtstrisnbn",
-                            wcroot->wc_id, local_relpath,
-                            parent_relpath,
-                            repos_id,
-                            repos_relpath,
-                            new_revision,
-                            presence_map, new_presence,
-                            new_depth_str,
-                            kind_map, new_kind,
-                            changed_rev,
-                            changed_date,
-                            changed_author,
-                            prop_blob.data, prop_blob.len));
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_APPLY_CHANGES_TO_BASE_NODE));
+      /* symlink_target not yet used */
+      SVN_ERR(svn_sqlite__bindf(stmt, "issisrtstrisnbn",
+                                wcroot->wc_id, local_relpath,
+                                parent_relpath,
+                                repos_id,
+                                repos_relpath,
+                                new_revision,
+                                presence_map, new_presence,
+                                new_depth_str,
+                                kind_map, new_kind,
+                                changed_rev,
+                                changed_date,
+                                changed_author,
+                                prop_blob.data, prop_blob.len));
 
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 13, new_checksum,
-                                    scratch_pool));
-  SVN_ERR(svn_sqlite__bind_properties(stmt, 15, new_dav_cache,
-                                      scratch_pool));
-  if (inherited_prop_blob.data != NULL)
-    {
-      SVN_ERR(svn_sqlite__bind_blob(stmt, 17, inherited_prop_blob.data,
-                                    inherited_prop_blob.len));
+      SVN_ERR(svn_sqlite__bind_checksum(stmt, 13, new_checksum,
+                                        scratch_pool));
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 15, new_dav_cache,
+                                          scratch_pool));
+      if (inherited_prop_blob.data != NULL)
+        {
+          SVN_ERR(svn_sqlite__bind_blob(stmt, 17, inherited_prop_blob.data,
+                                        inherited_prop_blob.len));
+        }
+
+      SVN_ERR(svn_sqlite__step_done(stmt));
     }
+  else
+    {
+      struct insert_base_baton_t ibb;
+      blank_ibb(&ibb);
 
-  SVN_ERR(svn_sqlite__step_done(stmt));
+      ibb.repos_id = repos_id;
+      ibb.status = svn_wc__db_status_not_present;
+      ibb.kind = new_kind;
+      ibb.repos_relpath = repos_relpath;
+      ibb.revision = new_revision;
+
+      SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
+
+      keep_changelist = FALSE; /* Nothing there */
+    }
 
   if (have_act)
     {
@@ -11755,23 +11833,21 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
         }
     }
 
-  if (new_kind == svn_node_dir)
-    {
-      /* When committing a directory, we should have its new children.  */
-      /* ### one day. just not today.  */
-#if 0
-      SVN_ERR_ASSERT(new_children != NULL);
-#endif
-
-      /* ### process the children  */
-    }
-
   if (!no_unlock)
     {
       svn_sqlite__stmt_t *lock_stmt;
+      svn_boolean_t op_root = (op_depth > 0
+                               && (relpath_depth(local_relpath) == op_depth));
 
+      /* If we are committing an add of a delete, we can assume we own
+         all locks at or below REPOS_RELPATH (or the server would have
+         denied the commit). As we must have passed these to the server
+         we can now safely remove them.
+       */
       SVN_ERR(svn_sqlite__get_statement(&lock_stmt, wcroot->sdb,
-                                        STMT_DELETE_LOCK_RECURSIVELY));
+                                        op_root
+                                          ? STMT_DELETE_LOCK_RECURSIVELY
+                                          : STMT_DELETE_LOCK));
       SVN_ERR(svn_sqlite__bindf(lock_stmt, "is", repos_id, repos_relpath));
       SVN_ERR(svn_sqlite__step_done(lock_stmt));
     }
@@ -11791,7 +11867,6 @@ svn_wc__db_global_commit(svn_wc__db_t *d
                          apr_time_t changed_date,
                          const char *changed_author,
                          const svn_checksum_t *new_checksum,
-                         const apr_array_header_t *new_children,
                          apr_hash_t *new_dav_cache,
                          svn_boolean_t keep_changelist,
                          svn_boolean_t no_unlock,
@@ -11803,7 +11878,6 @@ svn_wc__db_global_commit(svn_wc__db_t *d
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(new_revision));
-  SVN_ERR_ASSERT(new_checksum == NULL || new_children == NULL);
 
   SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
                               local_abspath, scratch_pool, scratch_pool));
@@ -11812,7 +11886,7 @@ svn_wc__db_global_commit(svn_wc__db_t *d
   SVN_WC__DB_WITH_TXN(
     commit_node(wcroot, local_relpath,
                 new_revision, changed_revision, changed_date, changed_author,
-                new_checksum, new_children, new_dav_cache, keep_changelist,
+                new_checksum, new_dav_cache, keep_changelist,
                 no_unlock, work_items, scratch_pool),
     wcroot);
 
@@ -16186,19 +16260,7 @@ process_committed_leaf(svn_wc__db_t *db,
                           scratch_pool));
   }
 
-  if (status == svn_wc__db_status_deleted)
-    {
-      return svn_error_trace(
-                 db_base_remove(wcroot, local_relpath, db,
-                                FALSE /* keep_as_working */,
-                                FALSE /* queue_deletes */,
-                                TRUE  /* remove_locks */,
-                                (! via_recurse)
-                                    ? new_revnum : SVN_INVALID_REVNUM,
-                                NULL, NULL,
-                                scratch_pool));
-    }
-  else if (status == svn_wc__db_status_not_present)
+  if (status == svn_wc__db_status_not_present)
     {
       /* We are committing the leaf of a copy operation.
          We leave the not-present marker to allow pulling in excluded
@@ -16211,9 +16273,11 @@ process_committed_leaf(svn_wc__db_t *db,
 
   SVN_ERR_ASSERT(status == svn_wc__db_status_normal
                  || status == svn_wc__db_status_incomplete
-                 || status == svn_wc__db_status_added);
+                 || status == svn_wc__db_status_added
+                 || status == svn_wc__db_status_deleted);
 
-  if (kind != svn_node_dir)
+  if (kind != svn_node_dir
+      && status != svn_wc__db_status_deleted)
     {
       /* If we sent a delta (meaning: post-copy modification),
          then this file will appear in the queue and so we should have
@@ -16263,7 +16327,6 @@ process_committed_leaf(svn_wc__db_t *db,
                       new_revnum, new_changed_rev,
                       new_changed_date, new_changed_author,
                       checksum,
-                      NULL /* new_children */,
                       new_dav_cache,
                       !remove_changelist,
                       !remove_lock,

Modified: subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.h?rev=1661930&r1=1661922&r2=1661930&view=diff
==============================================================================
--- subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.h 
(original)
+++ subversion/branches/1.9.x-commit-fixes/subversion/libsvn_wc/wc_db.h Tue Feb 
24 13:01:50 2015
@@ -2517,11 +2517,6 @@ svn_wc__db_global_relocate(svn_wc__db_t
    CHANGED_AUTHOR is the (server-side) author of CHANGED_REVISION. It may be
    NULL if the revprop is missing on the revision.
 
-   One or both of NEW_CHECKSUM and NEW_CHILDREN should be NULL. For new:
-     files: NEW_CHILDREN should be NULL
-     dirs: NEW_CHECKSUM should be NULL
-     symlinks: both should be NULL
-
    WORK_ITEMS will be place into the work queue.
 */
 svn_error_t *
@@ -2532,7 +2527,6 @@ svn_wc__db_global_commit(svn_wc__db_t *d
                          apr_time_t changed_date,
                          const char *changed_author,
                          const svn_checksum_t *new_checksum,
-                         const apr_array_header_t *new_children,
                          apr_hash_t *new_dav_cache,
                          svn_boolean_t keep_changelist,
                          svn_boolean_t no_unlock,

Modified: 
subversion/branches/1.9.x-commit-fixes/subversion/tests/cmdline/lock_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.9.x-commit-fixes/subversion/tests/cmdline/lock_tests.py?rev=1661930&r1=1661922&r2=1661930&view=diff
==============================================================================
--- 
subversion/branches/1.9.x-commit-fixes/subversion/tests/cmdline/lock_tests.py 
(original)
+++ 
subversion/branches/1.9.x-commit-fixes/subversion/tests/cmdline/lock_tests.py 
Tue Feb 24 13:01:50 2015
@@ -1997,7 +1997,6 @@ def failing_post_hooks(sbox):
                                      'unlock', pi_path)
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
-@XFail()
 def break_delete_add(sbox):
   "break a lock, delete and add the file"
 
@@ -2384,22 +2383,20 @@ def delete_dir_with_lots_of_locked_files
   nfiles = 75 # NOTE: test XPASSES with 50 files!!!
   locked_paths = []
   for i in range(nfiles):
-      locked_paths.append("A/locked_files/file-%i" % i)
+      locked_paths.append(sbox.ospath("A/locked_files/file-%i" % i))
 
   # Create files at these paths
   os.mkdir(sbox.ospath("A/locked_files"))
   for file_path in locked_paths:
-    svntest.main.file_write(sbox.ospath(file_path), "This is a file\n")
+    svntest.main.file_write(file_path, "This is '%s'.\n" % (file_path,))
   sbox.simple_add("A/locked_files")
   sbox.simple_commit()
   sbox.simple_update()
 
   # lock all the files
-  for file_path in locked_paths:
-    svntest.actions.run_and_verify_svn(None, [], 'lock',
-                                       '--username', 'jrandom',
-                                       '-m', 'lock %s' % file_path,
-                                       sbox.ospath(file_path))
+  svntest.actions.run_and_verify_svn(None, [], 'lock',
+                                     '-m', 'All locks',
+                                      *locked_paths)
   # Locally delete A
   sbox.simple_rm("A")
 
@@ -2411,6 +2408,62 @@ def delete_dir_with_lots_of_locked_files
   # This problem was introduced on the 1.8.x branch in r1606976.
   sbox.simple_commit()
 
+def delete_locks_on_depth_commit(sbox):
+  "delete locks on depth-limited commit"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  svntest.actions.run_and_verify_svn(None, [], 'lock',
+                                     '-m', 'All files',
+                                      *(sbox.ospath(x)
+                                        for x in ['iota', 'A/B/E/alpha',
+                                                  'A/B/E/beta', 'A/B/lambda',
+                                                  'A/D/G/pi', 'A/D/G/rho',
+                                                  'A/D/G/tau', 'A/D/H/chi',
+                                                  'A/D/H/omega', 'A/D/H/psi',
+                                                  'A/D/gamma', 'A/mu']))
+
+  sbox.simple_rm("A")
+
+  expected_output = svntest.wc.State(wc_dir, {
+    'A' : Item(verb='Deleting'),
+  })
+
+  expected_status = svntest.wc.State(wc_dir, {
+    ''      : Item(status='  ', wc_rev='1'),
+    'iota'  : Item(status='  ', wc_rev='1'),
+  })
+
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, [],
+                                        wc_dir, '--depth', 'immediates')
+
+  sbox.simple_update() # r2
+
+  svntest.actions.run_and_verify_svn(None, [], 'cp',
+                                     sbox.repo_url + '/A@1', sbox.ospath('A'))
+
+  expected_output = [
+    'Adding         %s\n' % sbox.ospath('A'),
+    'svn: The depth of this commit is \'immediates\', but copies ' \
+        'are always performed recursively in the repository.\n',
+    'Committing transaction...\n',
+    'Committed revision 3.\n',
+  ]
+
+  # Verifying the warning line... so can't use verify_commit()
+  svntest.actions.run_and_verify_svn(expected_output, [],
+                                     'commit', wc_dir, '--depth', 'immediates',
+                                     '-mm')
+
+  # Verify that all locks are gone at the server and at the client
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
+  expected_status.tweak('', 'iota', wc_rev=2)
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+
+
 ########################################################################
 # Run the tests
 
@@ -2477,6 +2530,7 @@ test_list = [ None,
               lock_commit_bump,
               copy_dir_with_locked_file,
               delete_dir_with_lots_of_locked_files,
+              delete_locks_on_depth_commit,
             ]
 
 if __name__ == '__main__':

Modified: 
subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/op-depth-test.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/op-depth-test.c?rev=1661930&r1=1661922&r2=1661930&view=diff
==============================================================================
--- 
subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/op-depth-test.c
 (original)
+++ 
subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/op-depth-test.c
 Tue Feb 24 13:01:50 2015
@@ -563,6 +563,35 @@ check_db_conflicts(svn_test__sandbox_t *
 }
 
 
+static svn_error_t *
+verify_db_callback(void *baton,
+                   const char *wc_abspath,
+                   const char *local_relpath,
+                   int op_depth,
+                   int id,
+                   const char *msg,
+                   apr_pool_t *scratch_pool)
+{
+  if (op_depth >= 0)
+    return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+                "Verify: %s: %s (%d): SV%04d %s",
+                wc_abspath, local_relpath, op_depth, id, msg);
+  else
+    return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+                "DB-VRFY: %s: %s: SV%04d %s",
+                wc_abspath, local_relpath, id, msg);
+}
+
+static svn_error_t *
+verify_db(svn_test__sandbox_t *b)
+{
+  SVN_ERR(svn_wc__db_verify_db_full(b->wc_ctx->db, b->wc_abspath,
+                                    verify_db_callback, NULL, b->pool));
+
+  return SVN_NO_ERROR;
+}
+
+
 /* ---------------------------------------------------------------------- */
 /* The test functions */
 
@@ -1267,6 +1296,34 @@ insert_dirs(svn_test__sandbox_t *b,
                                   ? svn_relpath_dirname(nodes->local_relpath,
                                                         b->pool)
                                   : NULL));
+
+      if (nodes->moved_to)
+        SVN_ERR(svn_sqlite__bind_text(stmt, 7, nodes->moved_to));
+      if (nodes->moved_here)
+        SVN_ERR(svn_sqlite__bind_int(stmt, 8, 1));
+      if (nodes->props)
+        {
+          int i;
+          apr_hash_t *props = apr_hash_make(b->pool);
+          apr_array_header_t *names = svn_cstring_split(nodes->props, ",",
+                                                        TRUE, b->pool);
+
+          for (i = 0; i < names->nelts; i++)
+            {
+              const char *name = APR_ARRAY_IDX(names, i, const char *);
+              svn_hash_sets(props, name, svn_string_create(name, b->pool));
+            }
+
+          SVN_ERR(svn_sqlite__bind_properties(stmt, 9, props, b->pool));
+        }
+      else if (nodes->repo_relpath
+               && strcmp(nodes->presence, "normal") == 0)
+        {
+          SVN_ERR(svn_sqlite__bind_text(stmt, 9, "()"));
+        }
+
+      /* File externals? */
+
       SVN_ERR(svn_sqlite__step_done(stmt));
       ++nodes;
     }
@@ -6917,6 +6974,31 @@ commit_moved_descendant(const svn_test_o
      shadowed, like in this case. The commit processing doesn't
      support this yet though*/
 
+   {
+    nodes_row_t nodes[] = {
+      {0, "",                 "normal",       0, ""},
+      {0, "A",                "normal",       1, "A"},
+      {0, "A/A",              "normal",       2, "A/A"},
+      {0, "A/A/A",            "normal",       2, "A/A/A"},
+      {0, "A/A/A/A",          "normal",       2, "A/A/A/A"},
+      {0, "A/A/A/A/A",        "normal",       2, "A/A/A/A/A"},
+      {0, "A/A/A/A/A/A",      "normal",       2, "A/A/A/A/A/A"},
+      {0, "A_copied",         "normal",       2, "A_copied"},
+      {0, "A_copied/A",       "normal",       2, "A_copied/A"},
+      {0, "A_copied/A/A",     "normal",       2, "A_copied/A/A"},
+      {0, "A_copied/A/A/A",   "normal",       2, "A_copied/A/A/A"},
+      {0, "A_copied/A/A/A/A", "normal",       2, "A_copied/A/A/A/A"},
+      {0, "A_copied/A/A/A/A/A","normal",       2, "A_copied/A/A/A/A/A"},
+      {0, "AAA_moved",        "normal",       2, "AAA_moved"},
+      {0, "AAA_moved/A",      "normal",       2, "AAA_moved/A"},
+      {0, "AAA_moved/A/A",    "normal",       2, "AAA_moved/A/A"},
+      {0, "AAA_moved/A/A/A",  "normal",       2, "AAA_moved/A/A/A"},
+
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
   return SVN_NO_ERROR;
 }
 
@@ -6939,10 +7021,63 @@ commit_moved_away_descendant(const svn_t
   SVN_ERR(sbox_wc_delete(&b, "A/A"));
   SVN_ERR(sbox_wc_copy(&b, "A_copied/A", "A/A"));
 
+  {
+    nodes_row_t nodes[] = {
+      {0, "",                   "normal",       0, ""},
+      {0, "A",                  "normal",       1, "A"},
+      {0, "A/A",                "normal",       1, "A/A"},
+      {0, "A/A/A",              "normal",       1, "A/A/A"},
+      {0, "A/A/A/A",            "normal",       1, "A/A/A/A"},
+      {0, "A/A/A/A/A",          "normal",       1, "A/A/A/A/A"},
+      {0, "A/A/A/A/A/A",        "normal",       1, "A/A/A/A/A/A"},
+      {1, "A_copied",           "normal",       1, "A"},
+      {1, "A_copied/A",         "normal",       1, "A/A"},
+      {1, "A_copied/A/A",       "normal",       1, "A/A/A"},
+      {1, "A_copied/A/A/A",     "normal",       1, "A/A/A/A"},
+      {1, "A_copied/A/A/A/A",   "normal",       1, "A/A/A/A/A"},
+      {1, "A_copied/A/A/A/A/A", "normal",       1, "A/A/A/A/A/A"},
+      {1, "AAA_moved",          "normal",       1, "A/A/A", MOVED_HERE},
+      {1, "AAA_moved/A",        "normal",       1, "A/A/A/A", MOVED_HERE},
+      {1, "AAA_moved/A/A",      "normal",       1, "A/A/A/A/A", MOVED_HERE},
+      {1, "AAA_moved/A/A/A",    "normal",       1, "A/A/A/A/A/A", MOVED_HERE},
+      {2, "A/A",                "normal",       1, "A/A"},
+      {2, "A/A/A",              "normal",       1, "A/A/A", FALSE, 
"AAA_moved"},
+      {2, "A/A/A/A",            "normal",       1, "A/A/A/A"},
+      {2, "A/A/A/A/A",          "normal",       1, "A/A/A/A/A"},
+      {2, "A/A/A/A/A/A",        "normal",       1, "A/A/A/A/A/A"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
   /* And now I want to make sure that I can't commit A, without also
      committing AAA_moved, as that would break the move*/
   SVN_ERR(sbox_wc_commit(&b, "A"));
 
+  {
+    nodes_row_t nodes[] = {
+      {0, "",                   "normal",       0, ""},
+      {0, "A",                  "normal",       1, "A"},
+      {0, "A/A",                "normal",       2, "A/A"},
+      {0, "A/A/A",              "normal",       2, "A/A/A"},
+      {0, "A/A/A/A",            "normal",       2, "A/A/A/A"},
+      {0, "A/A/A/A/A",          "normal",       2, "A/A/A/A/A"},
+      {0, "A/A/A/A/A/A",        "normal",       2, "A/A/A/A/A/A"},
+      {1, "A_copied",           "normal",       1, "A"},
+      {1, "A_copied/A",         "normal",       1, "A/A"},
+      {1, "A_copied/A/A",       "normal",       1, "A/A/A"},
+      {1, "A_copied/A/A/A",     "normal",       1, "A/A/A/A"},
+      {1, "A_copied/A/A/A/A",   "normal",       1, "A/A/A/A/A"},
+      {1, "A_copied/A/A/A/A/A", "normal",       1, "A/A/A/A/A/A"},
+      {1, "AAA_moved",          "normal",       1, "A/A/A"},
+      {1, "AAA_moved/A",        "normal",       1, "A/A/A/A"},
+      {1, "AAA_moved/A/A",      "normal",       1, "A/A/A/A/A"},
+      {1, "AAA_moved/A/A/A",    "normal",       1, "A/A/A/A/A/A"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
   return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                           "The commit should have failed");
 
@@ -10993,6 +11128,138 @@ move_deep_bump(const svn_test_opts_t *op
 
   return SVN_NO_ERROR;
 }
+static svn_error_t *
+test_global_commit(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "global_commit", opts, pool));
+
+  {
+    nodes_row_t before[] = {
+      { 0, "",        "normal",       2, "" },
+      { 0, "A",       "normal",       2, "A" },
+      { 0, "A/B",     "normal",       2, "A/B" },
+      { 0, "A/B/C",   "normal",       2, "A/B/C" },
+      { 0, "A/B/D",   "normal",       2, "A/B/D" },
+      { 0, "A/B/D/E", "normal",       2, "A/B/D/E" },
+      { 0, "A/F",     "normal",       2, "A/F" },
+      { 0, "A/F/G",   "normal",       2, "A/F/G" },
+      { 0, "A/F/H",   "normal",       2, "A/F/H" },
+      { 0, "A/F/E",   "normal",       2, "A/F/E" },
+      { 0, "A/X",     "normal",       2, "A/X" },
+      { 0, "A/X/Y",   "incomplete",   2, "A/X/Y" },
+      { 1, "C",       "normal",       2, "A/B/C", MOVED_HERE},
+      { 1, "E",       "normal",       2, "A/B/D/E", MOVED_HERE},
+      { 2, "A/B",     "normal",       3, "some", MOVED_HERE },
+      { 2, "A/B/C",   "base-deleted", NO_COPY_FROM, "C" },
+      { 2, "A/B/D",   "normal",       3, "some/D", MOVED_HERE},
+      { 2, "A/B/D/E", "not-present",  3, "some/D/E", FALSE, "E", TRUE},
+      { 3, "A/B/C",   "normal",       NO_COPY_FROM},
+      { 2, "A/F",     "normal",       1, "S2" },
+      { 2, "A/F/G",   "normal",       1, "S2/G" },
+      { 2, "A/F/H",   "not-present",  1, "S2/H" },
+      { 2, "A/F/E",   "base-deleted", NO_COPY_FROM },
+      { 1, "some",    "normal",       3, "some", FALSE, "A/B"},
+      { 0 }
+    };
+    SVN_ERR(insert_dirs(&b, before));
+    SVN_ERR(check_db_rows(&b, "", before)); /* Check move insertion logic */
+    SVN_ERR(verify_db(&b));
+  }
+
+  /* This should break the moves */
+  SVN_ERR(svn_wc__db_global_commit(b.wc_ctx->db,
+                                   sbox_wc_path(&b, "A/B"),
+                                   5, 5, 700, "me", NULL, NULL,
+                                   FALSE, FALSE, NULL, pool));
+  {
+    nodes_row_t after[] = {
+      { 0, "",        "normal",       2, "" },
+      { 0, "A",       "normal",       2, "A" },
+      { 0, "A/B",     "normal",       5, "A/B" },
+      { 0, "A/B/D",   "normal",       5, "A/B/D"},
+      { 0, "A/B/D/E", "not-present",  5, "A/B/D/E"},
+      { 0, "A/F",     "normal",       2, "A/F" },
+      { 0, "A/F/G",   "normal",       2, "A/F/G" },
+      { 0, "A/F/H",   "normal",       2, "A/F/H" },
+      { 0, "A/F/E",   "normal",       2, "A/F/E" },
+      { 0, "A/X",     "normal",       2, "A/X" },
+      { 0, "A/X/Y",   "incomplete",   2, "A/X/Y" },
+      { 1, "C",       "normal",       2, "A/B/C"},
+      { 1, "E",       "normal",       2, "A/B/D/E"},
+      { 1, "some",    "normal",       3, "some"},
+      { 3, "A/B/C",   "normal",       NO_COPY_FROM},
+      { 2, "A/F",     "normal",       1, "S2" },
+      { 2, "A/F/G",   "normal",       1, "S2/G" },
+      { 2, "A/F/H",   "not-present",  1, "S2/H" },
+      { 2, "A/F/E",   "base-deleted", NO_COPY_FROM },
+      { 0 }
+    };
+
+    SVN_ERR(check_db_rows(&b, "", after));
+    SVN_ERR(verify_db(&b));
+  }
+
+  SVN_ERR(svn_wc__db_global_commit(b.wc_ctx->db,
+                                   sbox_wc_path(&b, "A/F"),
+                                   6, 6, 800, "me", NULL, NULL,
+                                   FALSE, FALSE, NULL, pool));
+
+  {
+    nodes_row_t after[] = {
+      { 0, "",        "normal",       2, "" },
+      { 0, "A",       "normal",       2, "A" },
+      { 0, "A/B",     "normal",       5, "A/B" },
+      { 0, "A/B/D",   "normal",       5, "A/B/D"},
+      { 0, "A/B/D/E", "not-present",  5, "A/B/D/E"},
+      { 0, "A/F",     "normal",       6, "A/F" },
+      { 0, "A/F/G",   "normal",       6, "A/F/G" },
+      { 0, "A/F/H",   "not-present",  6, "A/F/H" },
+      { 0, "A/X",     "normal",       2, "A/X" },
+      { 0, "A/X/Y",   "incomplete",   2, "A/X/Y" },
+      { 1, "C",       "normal",       2, "A/B/C"},
+      { 1, "E",       "normal",       2, "A/B/D/E"},
+      { 1, "some",    "normal",       3, "some"},
+      { 3, "A/B/C",   "normal",       NO_COPY_FROM },
+      { 0 }
+    };
+
+    SVN_ERR(check_db_rows(&b, "", after));
+    SVN_ERR(verify_db(&b));
+  }
+
+  SVN_ERR(svn_wc__db_global_commit(b.wc_ctx->db,
+                                   sbox_wc_path(&b, "A/B/C"),
+                                   7, 7, 900, "me", NULL, NULL,
+                                   FALSE, FALSE, NULL, pool));
+
+  {
+    nodes_row_t after[] = {
+      { 0, "",        "normal",       2, "" },
+      { 0, "A",       "normal",       2, "A" },
+      { 0, "A/B",     "normal",       5, "A/B" },
+      { 0, "A/B/C",   "normal",       7, "A/B/C"},
+      { 0, "A/B/D",   "normal",       5, "A/B/D"},
+      { 0, "A/B/D/E", "not-present",  5, "A/B/D/E"},
+      { 0, "A/F",     "normal",       6, "A/F" },
+      { 0, "A/F/G",   "normal",       6, "A/F/G" },
+      { 0, "A/F/H",   "not-present",  6, "A/F/H" },
+      { 0, "A/X",     "normal",       2, "A/X" },
+      { 0, "A/X/Y",   "incomplete",   2, "A/X/Y" },
+      { 1, "some",    "normal",       3, "some"},
+      { 1, "E",       "normal",       2, "A/B/D/E"},
+      { 1, "C",       "normal",       2, "A/B/C"},
+      { 0 }
+    };
+
+    SVN_ERR(check_db_rows(&b, "", after));
+    SVN_ERR(verify_db(&b));
+  }
+
+  return SVN_NO_ERROR;
+}
+
 /* ---------------------------------------------------------------------- */
 /* The list of test functions */
 
@@ -11202,6 +11469,8 @@ static struct svn_test_descriptor_t test
                        "move edit obstruction"),
     SVN_TEST_OPTS_PASS(move_deep_bump,
                        "move deep bump"),
+    SVN_TEST_OPTS_PASS(test_global_commit,
+                       "test global commit"),
     SVN_TEST_NULL
   };
 

Modified: 
subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/wc-test-queries.sql
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/wc-test-queries.sql?rev=1661930&r1=1661922&r2=1661930&view=diff
==============================================================================
--- 
subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/wc-test-queries.sql
 (original)
+++ 
subversion/branches/1.9.x-commit-fixes/subversion/tests/libsvn_wc/wc-test-queries.sql
 Tue Feb 24 13:01:50 2015
@@ -44,8 +44,10 @@ DELETE FROM nodes;
 
 -- STMT_INSERT_NODE
 INSERT INTO nodes (local_relpath, op_depth, presence, repos_path,
-                   revision, parent_relpath, wc_id, repos_id, kind, depth)
-           VALUES (?1, ?2, ?3, ?4, ?5, ?6, 1,
+                   revision, parent_relpath, moved_to, moved_here,
+                   properties, wc_id, repos_id, kind,
+                   depth)
+           VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, 1,
                    CASE WHEN ?3 != 'base-deleted' THEN 1 END,
                    'dir',
                    CASE WHEN ?3 in ('normal', 'incomplete')


Reply via email to