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 2015/10/06 10:46:44 UTC

svn commit: r1706963 [4/6] - in /subversion/branches/move-tracking-2: ./ build/ subversion/ subversion/bindings/javahl/native/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_diff/ subversion/libsvn_fs_base/ ...

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c Tue Oct  6 08:46:43 2015
@@ -744,9 +744,29 @@ walk_local_nodes_diff(struct edit_baton_
 
           if (eb->local_before_remote && local_only)
             {
+              const char *moved_from_relpath;
+
+              if (info->moved_here)
+                {
+                  const char *moved_from_abspath;
+
+                  SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+                                                NULL, NULL, NULL,
+                                                db, child_abspath,
+                                                iterpool, iterpool));
+                  SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+                  moved_from_relpath = svn_dirent_skip_ancestor(
+                                                        eb->anchor_abspath,
+                                                        moved_from_abspath);
+                }
+              else
+                moved_from_relpath = NULL;
+
               if (info->kind == svn_node_file && diff_files)
                 SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                      child_relpath,
+                                                     moved_from_relpath,
                                                      eb->processor, dir_baton,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
@@ -756,6 +776,7 @@ walk_local_nodes_diff(struct edit_baton_
                 SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
                                                     child_relpath,
                                                     depth_below_here,
+                                                    moved_from_relpath,
                                                     eb->processor, dir_baton,
                                                     eb->diff_pristine,
                                                     eb->cancel_func,
@@ -810,9 +831,29 @@ walk_local_nodes_diff(struct edit_baton_
 
           if (!eb->local_before_remote && local_only)
             {
+              const char *moved_from_relpath;
+
+              if (info->moved_here)
+                {
+                  const char *moved_from_abspath;
+
+                  SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+                                                NULL, NULL, NULL,
+                                                db, child_abspath,
+                                                iterpool, iterpool));
+                  SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+                  moved_from_relpath = svn_dirent_skip_ancestor(
+                                                        eb->anchor_abspath,
+                                                        moved_from_abspath);
+                }
+              else
+                moved_from_relpath = NULL;
+
               if (info->kind == svn_node_file && diff_files)
                 SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                      child_relpath,
+                                                     moved_from_relpath,
                                                      eb->processor, dir_baton,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
@@ -820,12 +861,13 @@ walk_local_nodes_diff(struct edit_baton_
                                                      iterpool));
               else if (info->kind == svn_node_dir && diff_dirs)
                 SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
-                                                     child_relpath, depth_below_here,
-                                                     eb->processor, dir_baton,
-                                                     eb->diff_pristine,
-                                                     eb->cancel_func,
-                                                     eb->cancel_baton,
-                                                     iterpool));
+                                                    child_relpath, depth_below_here,
+                                                    moved_from_relpath,
+                                                    eb->processor, dir_baton,
+                                                    eb->diff_pristine,
+                                                    eb->cancel_func,
+                                                    eb->cancel_baton,
+                                                    iterpool));
             }
         }
     }
@@ -876,6 +918,7 @@ svn_error_t *
 svn_wc__diff_local_only_file(svn_wc__db_t *db,
                              const char *local_abspath,
                              const char *relpath,
+                             const char *moved_from_relpath,
                              const svn_diff_tree_processor_t *processor,
                              void *processor_parent_baton,
                              svn_boolean_t diff_pristine,
@@ -938,6 +981,7 @@ svn_wc__diff_local_only_file(svn_wc__db_
     {
       copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
       copyfrom_src->repos_relpath = original_repos_relpath;
+      copyfrom_src->moved_from_relpath = moved_from_relpath;
     }
 
   if (props_mod || !SVN_IS_VALID_REVNUM(revision))
@@ -1016,6 +1060,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                             const char *local_abspath,
                             const char *relpath,
                             svn_depth_t depth,
+                            const char *moved_from_relpath,
                             const svn_diff_tree_processor_t *processor,
                             void *processor_parent_baton,
                             svn_boolean_t diff_pristine,
@@ -1052,6 +1097,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
     {
       copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
       copyfrom_src->repos_relpath = original_repos_relpath;
+      copyfrom_src->moved_from_relpath = moved_from_relpath;
     }
 
   /* svn_wc__db_status_incomplete should never happen, as the result won't be
@@ -1139,12 +1185,40 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
 
           child_relpath = svn_relpath_join(relpath, name, iterpool);
 
+          if (info->moved_here)
+            {
+              const char *moved_from_abspath;
+              const char *a_abspath;
+              const char *a_relpath;
+
+              a_relpath = relpath;
+              a_abspath = local_abspath;
+              while (*a_relpath)
+                {
+                  a_relpath = svn_relpath_dirname(a_relpath, iterpool);
+                  a_abspath = svn_dirent_dirname(a_abspath, iterpool);
+                }
+
+              SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+                                            NULL, NULL, NULL,
+                                            db, child_abspath,
+                                            iterpool, iterpool));
+              SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+              moved_from_relpath = svn_dirent_skip_ancestor(
+                                                        a_abspath,
+                                                        moved_from_abspath);
+            }
+          else
+            moved_from_relpath = NULL;
+
           switch (info->kind)
             {
             case svn_node_file:
             case svn_node_symlink:
               SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                    child_relpath,
+                                                   moved_from_relpath,
                                                    processor, pdb,
                                                    diff_pristine,
                                                    cancel_func, cancel_baton,
@@ -1157,6 +1231,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                   SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
                                                       child_relpath,
                                                       depth_below_here,
+                                                      moved_from_relpath,
                                                       processor, pdb,
                                                       diff_pristine,
                                                       cancel_func,
@@ -1205,6 +1280,8 @@ handle_local_only(struct dir_baton_t *pb
 {
   struct edit_baton_t *eb = pb->eb;
   const struct svn_wc__db_info_t *info;
+  const char *child_abspath;
+  const char *moved_from_relpath;
   svn_boolean_t repos_delete = (pb->deletes
                                 && svn_hash_gets(pb->deletes, name));
 
@@ -1240,6 +1317,25 @@ handle_local_only(struct dir_baton_t *pb
         break;
     }
 
+  child_abspath = svn_dirent_join(pb->local_abspath, name, scratch_pool);
+
+  if (info->moved_here)
+    {
+      const char *moved_from_abspath;
+
+      SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath,
+                                    NULL, NULL, NULL,
+                                    eb->db, child_abspath,
+                                    scratch_pool, scratch_pool));
+      SVN_ERR_ASSERT(moved_from_abspath != NULL);
+
+      moved_from_relpath = svn_dirent_skip_ancestor(
+                                    eb->anchor_abspath,
+                                    moved_from_abspath);
+    }
+  else
+    moved_from_relpath = NULL;
+
   if (info->kind == svn_node_dir)
     {
       svn_depth_t depth ;
@@ -1251,9 +1347,10 @@ handle_local_only(struct dir_baton_t *pb
 
       SVN_ERR(svn_wc__diff_local_only_dir(
                       eb->db,
-                      svn_dirent_join(pb->local_abspath, name, scratch_pool),
+                      child_abspath,
                       svn_relpath_join(pb->relpath, name, scratch_pool),
                       repos_delete ? svn_depth_infinity : depth,
+                      moved_from_relpath,
                       eb->processor, pb->pdb,
                       eb->diff_pristine,
                       eb->cancel_func, eb->cancel_baton,
@@ -1262,8 +1359,9 @@ handle_local_only(struct dir_baton_t *pb
   else
     SVN_ERR(svn_wc__diff_local_only_file(
                       eb->db,
-                      svn_dirent_join(pb->local_abspath, name, scratch_pool),
+                      child_abspath,
                       svn_relpath_join(pb->relpath, name, scratch_pool),
+                      moved_from_relpath,
                       eb->processor, pb->pdb,
                       eb->diff_pristine,
                       eb->cancel_func, eb->cancel_baton,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c Tue Oct  6 08:46:43 2015
@@ -391,9 +391,20 @@ diff_status_callback(void *baton,
 
     if (local_only && (db_status != svn_wc__db_status_deleted))
       {
+        /* Moved from. Relative from diff anchor*/
+        const char *moved_from_relpath = NULL;
+
+        if (status->moved_from_abspath)
+          {
+            moved_from_relpath = svn_dirent_skip_ancestor(
+                                          eb->anchor_abspath,
+                                          status->moved_from_abspath);
+          }
+
         if (db_kind == svn_node_file)
           SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                child_relpath,
+                                               moved_from_relpath,
                                                eb->processor,
                                                eb->cur ? eb->cur->baton : NULL,
                                                FALSE,
@@ -403,6 +414,7 @@ diff_status_callback(void *baton,
         else if (db_kind == svn_node_dir)
           SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
                                               child_relpath, depth_below_here,
+                                              moved_from_relpath,
                                               eb->processor,
                                               eb->cur ? eb->cur->baton : NULL,
                                               FALSE,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_pristine.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_pristine.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_pristine.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_pristine.c Tue Oct  6 08:46:43 2015
@@ -835,6 +835,7 @@ pristine_cleanup_wcroot(svn_wc__db_wcroo
 {
   svn_sqlite__stmt_t *stmt;
   svn_error_t *err = NULL;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
   /* Find each unreferenced pristine in the DB and remove it. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -844,16 +845,20 @@ pristine_cleanup_wcroot(svn_wc__db_wcroo
       svn_boolean_t have_row;
       const svn_checksum_t *sha1_checksum;
 
+      svn_pool_clear(iterpool);
+
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
       if (! have_row)
         break;
 
       SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
-                                          scratch_pool));
+                                          iterpool));
       err = pristine_remove_if_unreferenced(wcroot, sha1_checksum,
-                                            scratch_pool);
+                                            iterpool);
     }
 
+  svn_pool_destroy(iterpool);
+
   return svn_error_trace(
       svn_error_compose_create(err, svn_sqlite__reset(stmt)));
 }

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c Tue Oct  6 08:46:43 2015
@@ -1729,7 +1729,7 @@ negotiate_encoding_prefs(request_rec *r,
      httpd/modules/mappers/mod_negotiation.c).  Thus, we duplicate the
      necessary ones in this file. */
   int i;
-  const apr_array_header_t *encoding_prefs;
+  apr_array_header_t *encoding_prefs;
   encoding_prefs = do_header_line(r->pool,
                                   apr_table_get(r->headers_in,
                                                 "Accept-Encoding"));
@@ -1741,8 +1741,7 @@ negotiate_encoding_prefs(request_rec *r,
     }
 
   *svndiff_version = 0;
-  qsort(encoding_prefs->elts, (size_t) encoding_prefs->nelts,
-        sizeof(accept_rec), sort_encoding_pref);
+  svn_sort__array(encoding_prefs, sort_encoding_pref);
   for (i = 0; i < encoding_prefs->nelts; i++)
     {
       struct accept_rec rec = APR_ARRAY_IDX(encoding_prefs, i,

Modified: subversion/branches/move-tracking-2/subversion/svn/notify.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svn/notify.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svn/notify.c (original)
+++ subversion/branches/move-tracking-2/subversion/svn/notify.c Tue Oct  6 08:46:43 2015
@@ -253,6 +253,13 @@ notify_body(struct notify_baton *nb,
                     _("Skipped target: '%s' -- copy-source is missing\n"),
                     path_local));
         }
+      else if (n->content_state == svn_wc_notify_state_obstructed)
+        {
+          SVN_ERR(svn_cmdline_printf(
+                    pool,
+                    _("Skipped '%s' -- obstructed by unversioned node\n"),
+                    path_local));
+        }
       else
         {
           SVN_ERR(svn_cmdline_printf(pool, _("Skipped '%s'\n"), path_local));

Modified: subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c Tue Oct  6 08:46:43 2015
@@ -74,7 +74,8 @@ print_rep_stats(svn_fs_fs__representatio
            "%20s bytes expanded size\n"
            "%20s bytes expanded shared size\n"
            "%20s bytes with rep-sharing off\n"
-           "%20s shared references\n"),
+           "%20s shared references\n"
+           "%20.3f average delta chain length\n"),
          svn__ui64toa_sep(stats->total.packed_size, ',', pool),
          svn__ui64toa_sep(stats->total.count, ',', pool),
          svn__ui64toa_sep(stats->shared.packed_size, ',', pool),
@@ -82,7 +83,8 @@ print_rep_stats(svn_fs_fs__representatio
          svn__ui64toa_sep(stats->total.expanded_size, ',', pool),
          svn__ui64toa_sep(stats->shared.expanded_size, ',', pool),
          svn__ui64toa_sep(stats->expanded_size, ',', pool),
-         svn__ui64toa_sep(stats->references - stats->total.count, ',', pool));
+         svn__ui64toa_sep(stats->references - stats->total.count, ',', pool),
+         stats->chain_len / MAX(1.0, (double)stats->total.count));
 }
 
 /* Print the (used) contents of CHANGES.  Use POOL for allocations.
@@ -413,6 +415,7 @@ print_stats(svn_fs_fs__stats_t *stats,
            "%20s bytes in %12s representations of added file nodes\n"
            "%20s bytes in %12s directory property representations\n"
            "%20s bytes in %12s file property representations\n"
+           "                         with %12.3f average delta chain length\n"
            "%20s bytes in header & footer overhead\n"),
          svn__ui64toa_sep(stats->total_rep_stats.total.packed_size, ',',
                          pool),
@@ -433,8 +436,10 @@ print_stats(svn_fs_fs__stats_t *stats,
          svn__ui64toa_sep(stats->file_prop_rep_stats.total.packed_size, ',',
                          pool),
          svn__ui64toa_sep(stats->file_prop_rep_stats.total.count, ',', pool),
+         stats->total_rep_stats.chain_len
+            / (double)stats->total_rep_stats.total.count,
          svn__ui64toa_sep(stats->total_rep_stats.total.overhead_size, ',',
-                        pool));
+                         pool));
 
   printf("\nDirectory representation statistics:\n");
   print_rep_stats(&stats->dir_rep_stats, pool);

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py Tue Oct  6 08:46:43 2015
@@ -5013,6 +5013,81 @@ def diff_incomplete_props(sbox):
   svntest.verify.compare_and_display_lines('base vs after', 'local diff',
                                            out1, out3)
 
+def diff_symlinks(sbox):
+  "diff some symlinks"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  sbox.simple_add_symlink('iota', 'to-iota')
+
+  svntest.actions.run_and_verify_svn([
+    'Index: %s\n' % sbox.path('to-iota'),
+    '===================================================================\n',
+    '--- %s\t(nonexistent)\n' % sbox.path('to-iota'),
+    '+++ %s\t(working copy)\n' % sbox.path('to-iota'),
+    '@@ -0,0 +1 @@\n',
+    '+link iota\n',
+    '\ No newline at end of file\n',
+    '\n',
+    'Property changes on: %s\n' % sbox.path('to-iota'),
+    '___________________________________________________________________\n',
+    'Added: svn:special\n',
+    '## -0,0 +1 ##\n',
+    '+*\n',
+    '\ No newline at end of property\n',
+  ], [], 'diff', wc_dir)
+
+  svntest.actions.run_and_verify_svn([
+    'Index: %s\n' % sbox.path('to-iota'),
+    '===================================================================\n',
+    'diff --git a/to-iota b/to-iota\n',
+    'new file mode 120644\n',
+    '--- /dev/null\t(nonexistent)\n',
+    '+++ b/to-iota\t(working copy)\n',
+    '@@ -0,0 +1 @@\n',
+    '+iota\n',
+    '\ No newline at end of file\n',
+    '\n',
+    'Property changes on: to-iota\n',
+    '___________________________________________________________________\n',
+    'Added: svn:special\n',
+    '## -0,0 +1 ##\n',
+    '+*\n',
+    '\ No newline at end of property\n',
+  ], [], 'diff', wc_dir, '--git')
+
+  sbox.simple_commit()
+  os.remove(sbox.ospath('to-iota'))
+  sbox.simple_symlink('A/B/E/alpha', 'to-iota')
+
+  svntest.actions.run_and_verify_svn([
+    'Index: %s\n' % sbox.path('to-iota'),
+    '===================================================================\n',
+    '--- %s\t(revision 2)\n' % sbox.path('to-iota'),
+    '+++ %s\t(working copy)\n' % sbox.path('to-iota'),
+    '@@ -1 +1 @@\n',
+    '-link iota\n',
+    '\ No newline at end of file\n',
+    '+link A/B/E/alpha\n',
+    '\ No newline at end of file\n',
+  ], [], 'diff', wc_dir)
+
+  svntest.actions.run_and_verify_svn([
+    'Index: %s\n' % sbox.path('to-iota'),
+    '===================================================================\n',
+    'diff --git a/to-iota b/to-iota\n',
+    'index 3ef26e44..9930f9a0 120644\n',
+    '--- a/to-iota\t(revision 2)\n',
+    '+++ b/to-iota\t(working copy)\n',
+    '@@ -1 +1 @@\n',
+    '-iota\n',
+    '\ No newline at end of file\n',
+    '+A/B/E/alpha\n',
+    '\ No newline at end of file\n',
+  ], [], 'diff', wc_dir, '--git')
+
+
 ########################################################################
 #Run the tests
 
@@ -5106,6 +5181,7 @@ test_list = [ None,
               diff_summarize_ignore_properties,
               diff_incomplete,
               diff_incomplete_props,
+              diff_symlinks,
               ]
 
 if __name__ == '__main__':

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py Tue Oct  6 08:46:43 2015
@@ -4302,6 +4302,57 @@ def file_external_recorded_info(sbox):
   }]
   svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('i'))
 
+def external_externally_removed(sbox):
+  "external externally removed"
+
+  sbox.build(read_only = True)
+
+  sbox.simple_propset('svn:externals', '^/A/B B', '')
+
+  # Try fetching the external with a versioned obstruction
+  sbox.simple_mkdir('B')
+  expected_err = ".*W155035: The external.*B' is already a versioned path"
+  svntest.actions.run_and_verify_svn(None, expected_err,
+                                     'up', sbox.wc_dir)
+  sbox.simple_rm('B')
+
+
+  os.makedirs(sbox.ospath('B'))
+  expected_err2 = "svn: warning: W155007:.*B'"
+  svntest.actions.run_and_verify_svn(None, expected_err2,
+                                     'up', sbox.wc_dir)
+  os.rmdir(sbox.ospath('B'))
+
+  # Fetch the external
+  sbox.simple_update()
+
+  svntest.main.safe_rmtree(sbox.ospath('B'))
+  sbox.simple_update() # Fetched again
+  if not os.path.isdir(sbox.ospath('B')):
+    raise svntest.Failure("B not recreated")
+
+  svntest.main.safe_rmtree(sbox.ospath('B'))
+  sbox.simple_propdel('svn:externals', '')
+
+  expected_output = [
+    "Updating '%s':\n" % sbox.wc_dir,
+    "Removed external '%s'\n" % sbox.ospath('B'),
+    "Updated to revision 1.\n"
+  ]
+  svntest.actions.run_and_verify_svn(expected_output, [],
+                                     'up', sbox.wc_dir)
+
+
+  sbox.simple_propset('svn:externals', '^/A/B B', '')
+  sbox.simple_update()
+  svntest.main.safe_rmtree(sbox.ospath('B'))
+  sbox.simple_mkdir('B')
+
+  svntest.actions.run_and_verify_svn(None, expected_err,
+                                     'up', sbox.wc_dir)
+
+  sbox.simple_propdel('svn:externals', '')
+  sbox.simple_update() # Should succeed
 
 ########################################################################
 # Run the tests
@@ -4377,6 +4428,7 @@ test_list = [ None,
               nested_notification,
               file_external_to_normal_file,
               file_external_recorded_info,
+              external_externally_removed,
              ]
 
 if __name__ == '__main__':