subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From julianf...@apache.org
Subject svn commit: r1201727 [3/4] - in /subversion/branches/showing-merge-info: ./ contrib/client-side/emacs/ notes/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_delta/ subversion/libsvn_diff/ subversion/libsvn_r...
Date Mon, 14 Nov 2011 14:32:07 GMT
Modified: subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c Mon Nov 14 14:32:05 2011
@@ -153,6 +153,12 @@ struct prop_args
   const svn_string_t *value;
 };
 
+struct copy_args
+{
+  const char *copyfrom_path;
+  svn_revnum_t copyfrom_rev;
+};
+
 static svn_error_t *
 add_action(struct ev2_edit_baton *eb,
            const char *path,
@@ -258,6 +264,16 @@ process_actions(void *edit_baton,
               break;
             }
 
+          case ACTION_COPY:
+            {
+              struct copy_args *c_args = action->args;
+
+              SVN_ERR(svn_editor_copy(eb->editor, c_args->copyfrom_path,
+                                      c_args->copyfrom_rev, path,
+                                      SVN_INVALID_REVNUM));
+              break;
+            }
+
           default:
             SVN_ERR_MALFUNCTION();
         }
@@ -381,16 +397,29 @@ ev2_add_directory(const char *path,
 {
   struct ev2_dir_baton *pb = parent_baton;
   struct ev2_dir_baton *cb = apr_palloc(result_pool, sizeof(*cb));
-  svn_kind_t *kind;
-
-  kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
-  *kind = svn_kind_dir;
-  SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
 
   cb->eb = pb->eb;
   cb->path = apr_pstrdup(result_pool, path);
   *child_baton = cb;
 
+  if (!copyfrom_path)
+    {
+      /* A simple add. */
+      svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
+
+      *kind = svn_kind_dir;
+      SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
+    }
+  else
+    {
+      /* A copy */
+      struct copy_args *args = apr_palloc(pb->eb->edit_pool, sizeof(*args));
+
+      args->copyfrom_path = apr_pstrdup(pb->eb->edit_pool, copyfrom_path);
+      args->copyfrom_rev = copyfrom_revision;
+      SVN_ERR(add_action(pb->eb, path, ACTION_COPY, args));
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -454,15 +483,28 @@ ev2_add_file(const char *path,
 {
   struct ev2_file_baton *fb = apr_palloc(result_pool, sizeof(*fb));
   struct ev2_dir_baton *pb = parent_baton;
-  svn_kind_t *kind;
 
   fb->eb = pb->eb;
   fb->path = apr_pstrdup(result_pool, path);
   *file_baton = fb;
 
-  kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
-  *kind = svn_kind_file;
-  SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
+  if (!copyfrom_path)
+    {
+      /* A simple add. */
+      svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
+
+      *kind = svn_kind_file;
+      SVN_ERR(add_action(pb->eb, path, ACTION_ADD, kind));
+    }
+  else
+    {
+      /* A copy */
+      struct copy_args *args = apr_palloc(pb->eb->edit_pool, sizeof(*args));
+
+      args->copyfrom_path = apr_pstrdup(pb->eb->edit_pool, copyfrom_path);
+      args->copyfrom_rev = copyfrom_revision;
+      SVN_ERR(add_action(pb->eb, path, ACTION_COPY, args));
+    }
 
   return SVN_NO_ERROR;
 }
@@ -1024,6 +1066,10 @@ copy_cb(void *baton,
 
   SVN_ERR(ensure_root_opened(eb));
 
+  SVN_ERR(build(eb, ACTION_COPY, dst_relpath, svn_kind_unknown,
+                src_relpath, src_revision, NULL, NULL, SVN_INVALID_REVNUM,
+                scratch_pool));
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/showing-merge-info/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_diff/diff_file.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_diff/diff_file.c Mon Nov 14 14:32:05 2011
@@ -470,8 +470,9 @@ find_identical_prefix(svn_boolean_t *rea
          too many for the \r. */
       svn_boolean_t ended_at_nonmatching_newline = FALSE;
       for (i = 0; i < file_len; i++)
-        ended_at_nonmatching_newline = ended_at_nonmatching_newline
-                                       || *file[i].curp == '\n';
+        if (file[i].curp < file[i].endp)
+          ended_at_nonmatching_newline = ended_at_nonmatching_newline
+                                         || *file[i].curp == '\n';
       if (ended_at_nonmatching_newline)
         {
           lines--;

Modified: subversion/branches/showing-merge-info/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_ra/ra_loader.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_ra/ra_loader.c Mon Nov 14 14:32:05 2011
@@ -601,6 +601,22 @@ svn_error_t *svn_ra_get_path_relative_to
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_ra__get_fspath_relative_to_root(svn_ra_session_t *ra_session,
+                                    const char **fspath,
+                                    const char *url,
+                                    apr_pool_t *pool)
+{
+  const char *relpath;
+
+  SVN_ERR(svn_ra_get_path_relative_to_root(ra_session, &relpath, url, pool));
+  if (*relpath)
+    *fspath = apr_pstrcat(pool, "/", relpath, (char *)NULL);
+  else
+    *fspath = "/";
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *svn_ra_get_latest_revnum(svn_ra_session_t *session,
                                       svn_revnum_t *latest_revnum,
                                       apr_pool_t *pool)

Modified: subversion/branches/showing-merge-info/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_ra_local/ra_plugin.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_ra_local/ra_plugin.c Mon Nov 14 14:32:05 2011
@@ -220,21 +220,21 @@ reporter_link_path(void *reporter_baton,
                    apr_pool_t *pool)
 {
   reporter_baton_t *rbaton = reporter_baton;
-  const char *fs_path = NULL;
   const char *repos_url = rbaton->sess->repos_url;
+  const char *relpath = svn_uri_skip_ancestor(repos_url, url, pool);
+  const char *fs_path;
 
-  if (!svn_uri__is_ancestor(repos_url, url))
+  if (!relpath)
     return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                              _("'%s'\n"
                                "is not the same repository as\n"
                                "'%s'"), url, rbaton->sess->repos_url);
 
-  /* Skip the repos_url, but keep the last '/' to create an fspath */
-  fs_path = svn_uri_skip_ancestor(repos_url, url, pool);
-  if (fs_path[0] == '\0')
+  /* Convert the relpath to an fspath */
+  if (relpath[0] == '\0')
     fs_path = "/";
   else
-    fs_path = apr_pstrcat(pool, "/", fs_path, (char *)NULL);
+    fs_path = apr_pstrcat(pool, "/", relpath, (char *)NULL);
 
   return svn_repos_link_path3(rbaton->report_baton, path, fs_path, revision,
                               depth, start_empty, lock_token, pool);
@@ -541,12 +541,10 @@ svn_ra_local__reparent(svn_ra_session_t 
                        apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  const char *relpath = "";
+  const char *relpath = svn_uri_skip_ancestor(sess->repos_url, url, pool);
 
   /* If the new URL isn't the same as our repository root URL, then
      let's ensure that it's some child of it. */
-  if (strcmp(url, sess->repos_url) != 0)
-    relpath = svn_uri__is_child(sess->repos_url, url, pool);
   if (! relpath)
     return svn_error_createf
       (SVN_ERR_RA_ILLEGAL_URL, NULL,

Modified: subversion/branches/showing-merge-info/subversion/libsvn_ra_neon/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_ra_neon/commit.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_ra_neon/commit.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_ra_neon/commit.c Mon Nov 14 14:32:05 2011
@@ -87,7 +87,7 @@ typedef struct commit_ctx_t
   apr_hash_t *revprop_table;
 
   /* A hash mapping svn_string_t * paths (those which are valid as
-     target in the MERGE response) to svn_node_kind_t kinds. */
+     target in the MERGE response) to (void*)svn_recurse_kind. */
   apr_hash_t *valid_targets;
 
   /* The (potential) author of this commit. */

Modified: subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c Mon Nov 14 14:32:05 2011
@@ -1403,23 +1403,6 @@ svn_dirent_is_child(const char *parent_d
 }
 
 const char *
-svn_uri__is_child(const char *parent_uri,
-                  const char *child_uri,
-                  apr_pool_t *pool)
-{
-  const char *relpath;
-
-  assert(pool); /* hysterical raisins. */
-  assert(svn_uri_is_canonical(parent_uri, NULL));
-  assert(svn_uri_is_canonical(child_uri, NULL));
-
-  relpath = is_child(type_uri, parent_uri, child_uri, pool);
-  if (relpath)
-    relpath = svn_path_uri_decode(relpath, pool);
-  return relpath;
-}
-
-const char *
 svn_dirent_skip_ancestor(const char *parent_dirent,
                          const char *child_dirent)
 {

Modified: subversion/branches/showing-merge-info/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_subr/opt.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_subr/opt.c Mon Nov 14 14:32:05 2011
@@ -644,6 +644,32 @@ svn_opt__revision_to_string(const svn_op
     }
 }
 
+svn_opt_revision_range_t *
+svn_opt__revision_range_create(const svn_opt_revision_t *start_revision,
+                               const svn_opt_revision_t *end_revision,
+                               apr_pool_t *result_pool)
+{
+  svn_opt_revision_range_t *range = apr_palloc(result_pool, sizeof(*range));
+
+  range->start = *start_revision;
+  range->end = *end_revision;
+  return range;
+}
+
+svn_opt_revision_range_t *
+svn_opt__revision_range_from_revnums(svn_revnum_t start_revnum,
+                                     svn_revnum_t end_revnum,
+                                     apr_pool_t *result_pool)
+{
+  svn_opt_revision_range_t *range = apr_palloc(result_pool, sizeof(*range));
+
+  range->start.kind = svn_opt_revision_number;
+  range->start.value.number = start_revnum;
+  range->end.kind = svn_opt_revision_number;
+  range->end.value.number = end_revnum;
+  return range;
+}
+
 
 
 /*** Parsing arguments. ***/

Modified: subversion/branches/showing-merge-info/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_subr/sqlite.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_subr/sqlite.c Mon Nov 14 14:32:05 2011
@@ -606,12 +606,12 @@ static volatile svn_atomic_t sqlite_init
 static svn_error_t *
 init_sqlite(void *baton, apr_pool_t *pool)
 {
-  if (sqlite3_libversion_number() < SQLITE_VERSION_NUMBER)
+  if (sqlite3_libversion_number() < SVN_SQLITE_MIN_VERSION_NUMBER)
     {
       return svn_error_createf(
                     SVN_ERR_SQLITE_ERROR, NULL,
                     _("SQLite compiled for %s, but running with %s"),
-                    SQLITE_VERSION, sqlite3_libversion());
+                    SVN_SQLITE_MIN_VERSION, sqlite3_libversion());
     }
 
 #if APR_HAS_THREADS

Modified: subversion/branches/showing-merge-info/subversion/libsvn_subr/target.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_subr/target.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_subr/target.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_subr/target.c Mon Nov 14 14:32:05 2011
@@ -303,18 +303,12 @@ svn_path_remove_redundancies(apr_array_h
           if (is_url != keeper_is_url)
             continue;
 
-          /* Quit here if we find this path already in the keepers. */
-          if (strcmp(keeper, abs_path) == 0)
-            {
-              keep_me = FALSE;
-              break;
-            }
-
-          /* Quit here if this path is a child of one of the keepers. */
+          /* Quit here if this path is the same as or a child of one of the
+             keepers. */
           if (is_url)
-            child_relpath = svn_uri__is_child(keeper, abs_path, temp_pool);
+            child_relpath = svn_uri_skip_ancestor(keeper, abs_path, temp_pool);
           else
-            child_relpath = svn_dirent_is_child(keeper, abs_path, temp_pool);
+            child_relpath = svn_dirent_skip_ancestor(keeper, abs_path);
           if (child_relpath)
             {
               keep_me = FALSE;

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_files.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_files.c Mon Nov 14 14:32:05 2011
@@ -428,7 +428,8 @@ svn_wc__internal_ensure_adm(svn_wc__db_t
                             apr_pool_t *scratch_pool)
 {
   int format;
-  const char *repos_relpath;
+  const char *repos_relpath = svn_uri_skip_ancestor(repos_root_url, url,
+                                                    scratch_pool);
   svn_wc__db_status_t status;
   const char *db_repos_relpath, *db_repos_root_url, *db_repos_uuid;
   svn_revnum_t db_revision;
@@ -437,15 +438,11 @@ svn_wc__internal_ensure_adm(svn_wc__db_t
   SVN_ERR_ASSERT(url != NULL);
   SVN_ERR_ASSERT(repos_root_url != NULL);
   SVN_ERR_ASSERT(repos_uuid != NULL);
-  SVN_ERR_ASSERT(svn_uri__is_ancestor(repos_root_url, url));
+  SVN_ERR_ASSERT(repos_relpath != NULL);
 
   SVN_ERR(svn_wc__internal_check_wc(&format, db, local_abspath, TRUE,
                                     scratch_pool));
 
-  repos_relpath = svn_uri__is_child(repos_root_url, url, scratch_pool);
-  if (repos_relpath == NULL)
-    repos_relpath = "";
-
   /* Early out: we know we're not dealing with an existing wc, so
      just create one. */
   if (format == 0)

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/entries.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/entries.c Mon Nov 14 14:32:05 2011
@@ -1720,16 +1720,10 @@ write_entry(struct write_baton **entry_n
     {
       if (entry->copyfrom_url)
         {
-          const char *relpath;
-
           working_node->repos_id = repos_id;
-          relpath = svn_uri__is_child(this_dir->repos,
-                                      entry->copyfrom_url,
-                                      result_pool);
-          if (relpath == NULL)
-            working_node->repos_relpath = "";
-          else
-            working_node->repos_relpath = relpath;
+          working_node->repos_relpath = svn_uri_skip_ancestor(
+                                          this_dir->repos, entry->copyfrom_url,
+                                          result_pool);
           working_node->revision = entry->copyfrom_rev;
           working_node->op_depth
             = svn_wc__db_op_depth_for_upgrade(local_relpath);
@@ -1987,17 +1981,16 @@ write_entry(struct write_baton **entry_n
 
           if (entry->url != NULL)
             {
-              const char *relpath = svn_uri__is_child(this_dir->repos,
-                                                      entry->url,
-                                                      result_pool);
-              base_node->repos_relpath = relpath ? relpath : "";
+              base_node->repos_relpath = svn_uri_skip_ancestor(
+                                           this_dir->repos, entry->url,
+                                           result_pool);
             }
           else
             {
-              const char *relpath = svn_uri__is_child(this_dir->repos,
-                                                      this_dir->url,
-                                                      scratch_pool);
-              if (relpath == NULL)
+              const char *relpath = svn_uri_skip_ancestor(this_dir->repos,
+                                                          this_dir->url,
+                                                          scratch_pool);
+              if (relpath == NULL || *relpath == '\0')
                 base_node->repos_relpath = entry->name;
               else
                 base_node->repos_relpath =

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/externals.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/externals.c Mon Nov 14 14:32:05 2011
@@ -609,8 +609,8 @@ close_file(void *file_baton,
     const svn_checksum_t *original_checksum = NULL;
 
     svn_boolean_t added = !SVN_IS_VALID_REVNUM(eb->original_revision);
-    const char *repos_relpath = svn_uri__is_child(eb->repos_root_url,
-                                                  eb->url, pool);
+    const char *repos_relpath = svn_uri_skip_ancestor(eb->repos_root_url,
+                                                      eb->url, pool);
 
     if (! added)
       {
@@ -901,8 +901,8 @@ svn_wc__get_file_external_editor(const s
   eb->diff3cmd = diff3_cmd;
 
   eb->record_ancestor_abspath = apr_pstrdup(edit_pool,record_ancestor_abspath);
-  eb->recorded_repos_relpath = svn_uri__is_child(repos_root_url, recorded_url,
-                                                 edit_pool);
+  eb->recorded_repos_relpath = svn_uri_skip_ancestor(repos_root_url, recorded_url,
+                                                     edit_pool);
 
   eb->changed_rev = SVN_INVALID_REVNUM;
 
@@ -1115,6 +1115,110 @@ svn_wc__read_external_info(svn_node_kind
   return SVN_NO_ERROR;
 }
 
+/* Return TRUE in *IS_ROLLED_OUT iff a node exists at XINFO->LOCAL_ABSPATH and
+ * if that node's origin corresponds with XINFO->REPOS_ROOT_URL and
+ * XINFO->REPOS_RELPATH.  All allocations are made in SCRATCH_POOL. */
+static svn_error_t *
+is_external_rolled_out(svn_boolean_t *is_rolled_out,
+                       svn_wc_context_t *wc_ctx,
+                       svn_wc__committable_external_info_t *xinfo,
+                       apr_pool_t *scratch_pool)
+{
+  const char *x_repos_relpath;
+  const char *x_repos_root_url;
+  svn_error_t *err;
+
+  *is_rolled_out = FALSE;
+
+  err = svn_wc__node_get_origin(NULL, NULL,
+                                &x_repos_relpath,
+                                &x_repos_root_url,
+                                NULL,
+                                wc_ctx, xinfo->local_abspath,
+                                FALSE, /* scan_deleted */
+                                scratch_pool, scratch_pool);
+
+  if (err)
+    {
+      if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+        {
+          svn_error_clear(err);
+          return SVN_NO_ERROR;
+        }
+      SVN_ERR(err);
+    }
+
+  *is_rolled_out = (strcmp(xinfo->repos_root_url, x_repos_root_url) == 0 &&
+                    strcmp(xinfo->repos_relpath, x_repos_relpath) == 0);
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__committable_externals_below(apr_array_header_t **externals,
+                                    svn_wc_context_t *wc_ctx,
+                                    const char *local_abspath,
+                                    svn_depth_t depth,
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *orig_externals;
+  int i;
+  apr_pool_t *iterpool;
+
+  /* For svn_depth_files, this also fetches dirs. They are filtered later. */
+  SVN_ERR(svn_wc__db_committable_externals_below(&orig_externals,
+                                                 wc_ctx->db,
+                                                 local_abspath,
+                                                 depth != svn_depth_infinity,
+                                                 result_pool, scratch_pool));
+  
+  if (orig_externals == NULL)
+    return SVN_NO_ERROR;
+
+  iterpool = svn_pool_create(scratch_pool);
+
+  for (i = 0; i < orig_externals->nelts; i++)
+    {
+      svn_boolean_t is_rolled_out;
+
+      svn_wc__committable_external_info_t *xinfo =
+        APR_ARRAY_IDX(orig_externals, i,
+                      svn_wc__committable_external_info_t *);
+
+      /* Discard dirs for svn_depth_files (s.a.). */
+      if (depth == svn_depth_files
+          && xinfo->kind == svn_kind_dir)
+        continue;
+
+      svn_pool_clear(iterpool);
+
+      /* Discard those externals that are not currently checked out. */
+      SVN_ERR(is_external_rolled_out(&is_rolled_out, wc_ctx, xinfo,
+                                     iterpool));
+      if (! is_rolled_out)
+        continue;
+
+      if (*externals == NULL)
+        *externals = apr_array_make(
+                               result_pool, 0,
+                               sizeof(svn_wc__committable_external_info_t *));
+
+      APR_ARRAY_PUSH(*externals,
+                     svn_wc__committable_external_info_t *) = xinfo;
+
+      if (depth != svn_depth_infinity)
+        continue;
+
+      /* Are there any nested externals? */
+      SVN_ERR(svn_wc__committable_externals_below(externals, wc_ctx,
+                                                  xinfo->local_abspath,
+                                                  svn_depth_infinity,
+                                                  result_pool, iterpool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__externals_defined_below(apr_hash_t **externals,
                                 svn_wc_context_t *wc_ctx,

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/node.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/node.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/node.c Mon Nov 14 14:32:05 2011
@@ -214,6 +214,8 @@ svn_wc__internal_get_repos_info(const ch
                                        db, local_abspath,
                                        result_pool, scratch_pool));
 
+  SVN_ERR_ASSERT(repos_root_url == NULL || *repos_root_url != NULL);
+  SVN_ERR_ASSERT(repos_uuid == NULL || *repos_uuid != NULL);
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c Mon Nov 14 14:32:05 2011
@@ -4614,6 +4614,17 @@ close_edit(void *edit_baton,
   struct edit_baton *eb = edit_baton;
   apr_pool_t *scratch_pool = eb->pool;
 
+  /* The editor didn't even open the root; we have to take care of
+     some cleanup stuffs. */
+  if (! eb->root_opened
+      && *eb->target_basename == '\0')
+    {
+      /* We need to "un-incomplete" the root directory. */
+      SVN_ERR(svn_wc__db_temp_op_end_directory_update(eb->db,
+                                                      eb->anchor_abspath,
+                                                      scratch_pool));
+    }
+
   /* By definition, anybody "driving" this editor for update or switch
      purposes at a *minimum* must have called set_target_revision() at
      the outset, and close_edit() at the end -- even if it turned out
@@ -5559,14 +5570,14 @@ svn_wc_add_repos_file4(svn_wc_context_t 
                                               dir_abspath,
                                               pool, pool));
 
-      if (!svn_uri__is_ancestor(original_root_url, copyfrom_url))
+      original_repos_relpath =
+        svn_uri_skip_ancestor(original_root_url, copyfrom_url, pool);
+
+      if (!original_repos_relpath)
         return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                                  _("Copyfrom-url '%s' has different repository"
                                    " root than '%s'"),
                                  copyfrom_url, original_root_url);
-
-      original_repos_relpath =
-        svn_uri_skip_ancestor(original_root_url, copyfrom_url, pool);
     }
   else
     {

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/upgrade.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/upgrade.c Mon Nov 14 14:32:05 2011
@@ -614,8 +614,7 @@ ensure_repos_info(svn_wc_entry_t *entry,
       for (hi = apr_hash_first(scratch_pool, repos_cache);
            hi; hi = apr_hash_next(hi))
         {
-          if (svn_uri__is_child(svn__apr_hash_index_key(hi), entry->url,
-                                scratch_pool))
+          if (svn_uri__is_ancestor(svn__apr_hash_index_key(hi), entry->url))
             {
               if (!entry->repos)
                 entry->repos = svn__apr_hash_index_key(hi);

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql Mon Nov 14 14:32:05 2011
@@ -956,6 +956,40 @@ SELECT presence, kind, def_local_relpath
 FROM externals WHERE wc_id = ?1 AND local_relpath = ?2
 LIMIT 1
 
+/* Select all committable externals, i.e. only unpegged ones on the same
+ * repository as the target path ?2, that are defined by WC ?1 to
+ * live below the target path. It does not matter which ancestor has the
+ * svn:externals definition, only the local path at which the external is
+ * supposed to be checked out is queried.
+ * Arguments:
+ *  ?1: wc_id.
+ *  ?2: the target path, local relpath inside ?1.
+ *  ?3: boolean, if 1 return immediate children of ?2 only.
+ *
+ * ### NOTE: This statement deliberately removes file externals that live
+ * inside an unversioned dir, because commit still breaks on those.
+ * Once that's been fixed, the conditions below "--->8---" become obsolete. */
+-- STMT_SELECT_COMMITTABLE_EXTERNALS_BELOW
+SELECT local_relpath, kind, repos_id, def_repos_relpath, repository.root
+FROM externals
+LEFT OUTER JOIN repository ON repository.id = externals.repos_id
+WHERE wc_id = ?1
+  AND def_revision IS NULL
+  AND repos_id = (SELECT repos_id FROM nodes
+                  WHERE nodes.local_relpath = ?2)
+  AND ( ((NOT ?3)
+         AND (?2 = ''
+              /* Want only the cildren of e.local_relpath;
+               * externals can't have a local_relpath = ''. */
+              OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2)))
+        OR
+        ((?3)
+         AND parent_relpath = ?2) )
+  /* ------>8----- */
+  AND (EXISTS (SELECT 1 FROM nodes
+               WHERE nodes.wc_id = externals.wc_id
+               AND nodes.local_relpath = externals.parent_relpath))
+
 -- STMT_SELECT_EXTERNALS_DEFINED
 SELECT local_relpath, def_local_relpath
 FROM externals

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c Mon Nov 14 14:32:05 2011
@@ -3059,6 +3059,64 @@ svn_wc__db_external_read(svn_wc__db_stat
 }
 
 svn_error_t *
+svn_wc__db_committable_externals_below(apr_array_header_t **externals,
+                                       svn_wc__db_t *db,
+                                       const char *local_abspath,
+                                       svn_boolean_t immediates_only,
+                                       apr_pool_t *result_pool,
+                                       apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  svn_sqlite__stmt_t *stmt;
+  const char *local_relpath;
+  svn_boolean_t have_row;
+  svn_wc__committable_external_info_t *info;
+  svn_kind_t db_kind;
+  apr_array_header_t *result = NULL;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                              local_abspath, scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_COMMITTABLE_EXTERNALS_BELOW));
+
+  SVN_ERR(svn_sqlite__bindf(stmt, "isi", wcroot->wc_id, local_relpath,
+                            (apr_int64_t)(immediates_only ? 1 : 0)));
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (have_row)
+    result = apr_array_make(result_pool, 0,
+                            sizeof(svn_wc__committable_external_info_t *));
+
+  while (have_row)
+    {
+      info = apr_palloc(result_pool, sizeof(*info));
+
+      local_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      info->local_abspath = svn_dirent_join(wcroot->abspath, local_relpath,
+                                            result_pool);
+
+      db_kind = svn_sqlite__column_token(stmt, 1, kind_map);
+      SVN_ERR_ASSERT(db_kind == svn_kind_file || db_kind == svn_kind_dir);
+      info->kind = db_kind;
+
+      info->repos_relpath = svn_sqlite__column_text(stmt, 3, result_pool);
+      info->repos_root_url = svn_sqlite__column_text(stmt, 4, result_pool);
+
+      APR_ARRAY_PUSH(result, svn_wc__committable_external_info_t *) = info;
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+
+  *externals = result;
+  return svn_error_trace(svn_sqlite__reset(stmt));
+}
+
+svn_error_t *
 svn_wc__db_externals_defined_below(apr_hash_t **externals,
                                    svn_wc__db_t *db,
                                    const char *local_abspath,
@@ -9136,17 +9194,6 @@ bump_node_revision(svn_wc__db_wcroot_t *
                                             new_repos_id,
                                             scratch_pool));
 
-  if (db_kind == svn_kind_dir && status == svn_wc__db_status_incomplete)
-    {
-      svn_sqlite__stmt_t *stmt;
-
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_UPDATE_NODE_BASE_PRESENCE));
-      SVN_ERR(svn_sqlite__bindf(stmt, "ist", wcroot->wc_id, local_relpath,
-                                presence_map, svn_wc__db_status_normal));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-    }
-
   /* Early out */
   if (depth <= svn_depth_empty
       || db_kind != svn_kind_dir
@@ -11727,6 +11774,58 @@ svn_wc__db_wclock_owns_lock(svn_boolean_
   return SVN_NO_ERROR;
 }
 
+/* Lock helper for svn_wc__db_temp_op_end_directory_update */
+static svn_error_t *
+end_directory_update(void *baton,
+                     svn_wc__db_wcroot_t *wcroot,
+                     const char *local_relpath,
+                     apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_wc__db_status_t base_status;
+
+  SVN_ERR(base_get_info(&base_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                        NULL, NULL, NULL, NULL, NULL, NULL,
+                        wcroot, local_relpath, scratch_pool, scratch_pool));
+
+  if (base_status == svn_wc__db_status_normal)
+    return SVN_NO_ERROR;
+
+  SVN_ERR_ASSERT(base_status == svn_wc__db_status_incomplete);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_UPDATE_NODE_BASE_PRESENCE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "ist", wcroot->wc_id, local_relpath,
+                            presence_map, svn_wc__db_status_normal));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_temp_op_end_directory_update(svn_wc__db_t *db,
+                                        const char *local_dir_abspath,
+                                        apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_dir_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                              local_dir_abspath, scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, end_directory_update,
+                              NULL, scratch_pool));
+
+  SVN_ERR(flush_entries(wcroot, local_dir_abspath, svn_depth_empty,
+                        scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
 struct start_directory_update_baton_t
 {
   svn_revnum_t new_rev;

Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h Mon Nov 14 14:32:05 2011
@@ -1133,6 +1133,37 @@ svn_wc__db_external_read(svn_wc__db_stat
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
+/* Return in *EXTERNALS a list of svn_wc__committable_external_info_t *
+ * containing info on externals defined to be checked out below LOCAL_ABSPATH,
+ * returning only those externals that are not fixed to a specific revision.
+ *
+ * If IMMEDIATES_ONLY is TRUE, only those externals defined to be checked out
+ * as immediate children of LOCAL_ABSPATH are returned (this is useful for
+ * treating user requested depth < infinity).
+ *
+ * If there are no externals to be returned, set *EXTERNALS to NULL. Otherwise
+ * set *EXTERNALS to an APR array newly cleated in RESULT_POOL.
+ *
+ * NOTE: This only returns the externals known by the immediate WC root for
+ * LOCAL_ABSPATH; i.e.:
+ * - If there is a further parent WC "above" the immediate WC root, and if
+ *   that parent WC defines externals to live somewhere within this WC, these
+ *   externals will appear to be foreign/unversioned and won't be picked up.
+ * - Likewise, only the topmost level of externals nestings (externals
+ *   defined within a checked out external dir) is picked up by this function.
+ *   (For recursion, see svn_wc__committable_externals_below().)
+ *
+ * ###TODO: Add a WRI_ABSPATH (wc root indicator) separate from LOCAL_ABSPATH,
+ * to allow searching any wc-root for externals under LOCAL_ABSPATH, not only
+ * LOCAL_ABSPATH's most immediate wc-root. */
+svn_error_t *
+svn_wc__db_committable_externals_below(apr_array_header_t **externals,
+                                       svn_wc__db_t *db,
+                                       const char *local_abspath,
+                                       svn_boolean_t immediates_only,
+                                       apr_pool_t *result_pool,
+                                       apr_pool_t *scratch_pool);
+
 /* Gets a mapping from const char * local abspaths of externals to the const
    char * local abspath of where they are defined for all externals defined
    at or below LOCAL_ABSPATH.
@@ -2312,11 +2343,6 @@ svn_wc__db_global_update(svn_wc__db_t *d
    The modifications are mutually exclusive.  If NEW_REPOS_ROOT is non-NULL,
    set the repository root of the entry to NEW_REPOS_ROOT.
 
-   If LOCAL_ABSPATH is an incomplete directory then mark it complete
-   by setting the status to normal. (Removing incomplete is usually
-   done by the editor during close_directory, but if the editor driver
-   simply called close_edit it gets done here.)
-
    If LOCAL_ABSPATH is a directory, then, walk entries below LOCAL_ABSPATH
    according to DEPTH thusly:
 
@@ -2875,6 +2901,15 @@ svn_wc__db_temp_op_start_directory_updat
                                           svn_revnum_t new_rev,
                                           apr_pool_t *scratch_pool);
 
+/* Marks a directory update started with
+   svn_wc__db_temp_op_start_directory_update as completed, by removing
+   the incomplete status */
+svn_error_t *
+svn_wc__db_temp_op_end_directory_update(svn_wc__db_t *db,
+                                        const char *local_dir_abspath,
+                                        apr_pool_t *scratch_pool);
+
+
 /* Copy the base tree at LOCAL_ABSPATH into the working tree as copy,
    leaving any subtree additions and copies as-is.  This allows the
    base node tree to be removed. */

Modified: subversion/branches/showing-merge-info/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/cl.h?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/cl.h (original)
+++ subversion/branches/showing-merge-info/subversion/svn/cl.h Mon Nov 14 14:32:05 2011
@@ -230,6 +230,7 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t internal_diff;    /* override diff_cmd in config file */
   svn_boolean_t use_git_diff_format; /* Use git's extended diff format */
   svn_boolean_t allow_mixed_rev; /* Allow operation on mixed-revision WC */
+  svn_boolean_t include_externals; /* Recurses (in)to file & dir externals */
 } svn_cl__opt_state_t;
 
 

Modified: subversion/branches/showing-merge-info/subversion/svn/commit-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/commit-cmd.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/commit-cmd.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/commit-cmd.c Mon Nov 14 14:32:05 2011
@@ -166,15 +166,17 @@ svn_cl__commit(apr_getopt_t *os,
     }
 
   /* Commit. */
-  err = svn_client_commit5(targets,
+  err = svn_client_commit6(targets,
                            opt_state->depth,
                            no_unlock,
                            opt_state->keep_changelists,
                            TRUE /* commit_as_operations */,
+                           opt_state->include_externals, /* file externals */
+                           opt_state->include_externals, /* dir externals */
                            opt_state->changelists,
                            opt_state->revprop_table,
-                           ! opt_state->quiet
-                                ? svn_cl__print_commit_info : NULL,
+                           (opt_state->quiet
+                            ? NULL : svn_cl__print_commit_info),
                            NULL,
                            ctx,
                            pool);

Modified: subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c Mon Nov 14 14:32:05 2011
@@ -136,7 +136,8 @@ svn_cl__copy(apr_getopt_t *os,
   err = svn_client_copy6(sources, dst_path, TRUE,
                          opt_state->parents, opt_state->ignore_externals,
                          opt_state->revprop_table,
-                         svn_cl__print_commit_info, NULL,
+                         (opt_state->quiet ? NULL : svn_cl__print_commit_info),
+                         NULL,
                          ctx, pool);
 
   if (ctx->log_msg_func3)

Modified: subversion/branches/showing-merge-info/subversion/svn/delete-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/delete-cmd.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/delete-cmd.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/delete-cmd.c Mon Nov 14 14:32:05 2011
@@ -79,7 +79,9 @@ svn_cl__delete(apr_getopt_t *os,
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
 
   err = svn_client_delete4(targets, opt_state->force, opt_state->keep_local,
-                           opt_state->revprop_table, svn_cl__print_commit_info,
+                           opt_state->revprop_table,
+                           (opt_state->quiet
+                            ? NULL : svn_cl__print_commit_info),
                            NULL, ctx, pool);
   if (err)
     err = svn_cl__may_need_force(err);

Modified: subversion/branches/showing-merge-info/subversion/svn/import-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/import-cmd.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/import-cmd.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/import-cmd.c Mon Nov 14 14:32:05 2011
@@ -120,7 +120,8 @@ svn_cl__import(apr_getopt_t *os,
                               opt_state->no_ignore,
                               opt_state->force,
                               opt_state->revprop_table,
-                              svn_cl__print_commit_info,
+                              (opt_state->quiet
+                               ? NULL : svn_cl__print_commit_info),
                               NULL,
                               ctx,
                               pool), pool));

Modified: subversion/branches/showing-merge-info/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/main.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/main.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/main.c Mon Nov 14 14:32:05 2011
@@ -54,6 +54,7 @@
 #include "svn_version.h"
 #include "cl.h"
 
+#include "private/svn_opt_private.h"
 #include "private/svn_wc_private.h"
 #include "private/svn_cmdline_private.h"
 
@@ -123,7 +124,8 @@ typedef enum svn_cl__longopt_t {
   opt_diff,
   opt_internal_diff,
   opt_use_git_diff_format,
-  opt_allow_mixed_revisions
+  opt_allow_mixed_revisions,
+  opt_include_externals,
 } svn_cl__longopt_t;
 
 
@@ -345,6 +347,12 @@ const apr_getopt_option_t svn_cl__option
                        "Use of this option is not recommended!\n"
                        "                             "
                        "Please run 'svn update' instead.")},
+  {"include-externals", opt_include_externals, 0,
+                       N_("Also commit file and dir externals reached by\n"
+                       "                             "
+                       "recursion. This does not include externals with a\n"
+                       "                             "
+                       "fixed revision. (See the svn:externals property)")},
 
   /* Long-opt Aliases
    *
@@ -463,7 +471,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
        "  If any targets are (or contain) locked items, those will be\n"
        "  unlocked after a successful commit.\n"),
     {'q', 'N', opt_depth, opt_targets, opt_no_unlock, SVN_CL__LOG_MSG_OPTIONS,
-     opt_changelist, opt_keep_changelists} },
+     opt_changelist, opt_keep_changelists, opt_include_externals} },
 
   { "copy", svn_cl__copy, {"cp"}, N_
     ("Duplicate something in working copy or repository, remembering\n"
@@ -1622,7 +1630,6 @@ main(int argc, const char *argv[])
             {
               char *end;
               svn_revnum_t changeno, changeno_end;
-              svn_opt_revision_range_t *range;
               const char *change_str =
                 APR_ARRAY_IDX(change_revs, i, const char *);
               const char *s = change_str;
@@ -1694,15 +1701,11 @@ main(int argc, const char *argv[])
                   changeno_end = changeno - 1;
                 }
 
-              range = apr_palloc(pool, sizeof(*range));
-              range->start.value.number = changeno;
-              range->end.value.number = changeno_end;
-
               opt_state.used_change_arg = TRUE;
-              range->start.kind = svn_opt_revision_number;
-              range->end.kind = svn_opt_revision_number;
               APR_ARRAY_PUSH(opt_state.revision_ranges,
-                             svn_opt_revision_range_t *) = range;
+                             svn_opt_revision_range_t *)
+                = svn_opt__revision_range_from_revnums(changeno, changeno_end,
+                                                       pool);
             }
         }
         break;
@@ -2049,6 +2052,9 @@ main(int argc, const char *argv[])
       case opt_allow_mixed_revisions:
         opt_state.allow_mixed_rev = TRUE;
         break;
+      case opt_include_externals:
+        opt_state.include_externals = TRUE;
+        break;
       default:
         /* Hmmm. Perhaps this would be a good place to squirrel away
            opts that commands like svn diff might need. Hmmm indeed. */

Modified: subversion/branches/showing-merge-info/subversion/svn/mkdir-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/mkdir-cmd.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/mkdir-cmd.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/mkdir-cmd.c Mon Nov 14 14:32:05 2011
@@ -78,7 +78,8 @@ svn_cl__mkdir(apr_getopt_t *os,
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
 
   err = svn_client_mkdir4(targets, opt_state->parents,
-                          opt_state->revprop_table, svn_cl__print_commit_info,
+                          opt_state->revprop_table,
+                          (opt_state->quiet ? NULL : svn_cl__print_commit_info),
                           NULL, ctx, pool);
 
   if (ctx->log_msg_func3)

Modified: subversion/branches/showing-merge-info/subversion/svn/move-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/move-cmd.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/move-cmd.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/move-cmd.c Mon Nov 14 14:32:05 2011
@@ -86,7 +86,8 @@ svn_cl__move(apr_getopt_t *os,
 
   err = svn_client_move6(targets, dst_path,
                          TRUE, opt_state->parents, opt_state->revprop_table,
-                         svn_cl__print_commit_info, NULL, ctx, pool);
+                         (opt_state->quiet ? NULL : svn_cl__print_commit_info),
+                         NULL, ctx, pool);
 
   if (err)
     err = svn_cl__may_need_force(err);

Modified: subversion/branches/showing-merge-info/subversion/svn/relocate-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/relocate-cmd.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/relocate-cmd.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/relocate-cmd.c Mon Nov 14 14:32:05 2011
@@ -50,7 +50,7 @@ svn_cl__relocate(apr_getopt_t *os,
   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
   svn_boolean_t ignore_externals = opt_state->ignore_externals;
   apr_array_header_t *targets;
-  const char *from = NULL, *to = NULL, *path;
+  const char *from, *to, *path;
 
   /* We've got two different syntaxes to support:
 

Modified: subversion/branches/showing-merge-info/subversion/svnsync/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svnsync/main.c?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svnsync/main.c (original)
+++ subversion/branches/showing-merge-info/subversion/svnsync/main.c Mon Nov 14 14:32:05 2011
@@ -760,7 +760,7 @@ do_initialize(svn_ra_session_t *to_sessi
 
   /* If we're doing a partial replay, we have to check first if the server
      supports this. */
-  if (svn_uri__is_child(root_url, baton->from_url, pool))
+  if (strcmp(root_url, baton->from_url) != 0)
     {
       svn_boolean_t server_supports_partial_replay;
       svn_error_t *err = svn_ra_has_capability(from_session,

Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/basic_tests.py?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/basic_tests.py Mon Nov 14 14:32:05 2011
@@ -2821,6 +2821,63 @@ def add_multiple_targets(sbox):
                                      'status', wc_dir)
 
 
+def quiet_commits(sbox):
+  "commits with --quiet"
+
+  sbox.build()
+
+  svntest.main.file_append(sbox.ospath('A/mu'), 'xxx')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'commit', sbox.wc_dir,
+                                     '--message', 'commit', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'mkdir', sbox.repo_url + '/X',
+                                     '--message', 'mkdir URL', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'import', sbox.ospath('A/mu'),
+                                     sbox.repo_url + '/f',
+                                     '--message', 'import', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'rm', sbox.repo_url + '/f',
+                                     '--message', 'rm URL', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'copy', sbox.repo_url + '/X',
+                                     sbox.repo_url + '/Y',
+                                     '--message', 'cp URL URL', '--quiet')
+
+  svntest.actions.run_and_verify_svn(None, [], [],
+                                     'move', sbox.repo_url + '/Y',
+                                     sbox.repo_url + '/Z',
+                                     '--message', 'mv URL URL', '--quiet')
+
+  # Not fully testing each command, just that they all commit and
+  # produce no output.
+  expected_output = wc.State(sbox.wc_dir, {
+    'X' : Item(status='A '),
+    'Z' : Item(status='A '),
+    })
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 7)
+  expected_status.add({
+      'X'   : Item(status='  ', wc_rev=7),
+      'Z'   : Item(status='  ', wc_rev=7),
+      })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu',
+                      contents=expected_disk.desc['A/mu'].contents
+                      + 'xxx')
+  expected_disk.add({
+    'X' : Item(),
+    'Z' : Item()
+    })
+  svntest.actions.run_and_verify_update(sbox.wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status)
 
 ########################################################################
 # Run the tests
@@ -2885,6 +2942,7 @@ test_list = [ None,
               ls_url_special_characters,
               ls_multiple_and_non_existent_targets,
               add_multiple_targets,
+              quiet_commits,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/commit_tests.py?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/commit_tests.py Mon Nov 14 14:32:05 2011
@@ -2825,6 +2825,40 @@ def commit_incomplete(sbox):
                                         None,
                                         wc_dir)
   
+#----------------------------------------------------------------------
+# Reported here:
+#   Message-ID: <4EBF0FC9.300@gmail.com>
+#   Date: Sun, 13 Nov 2011 13:31:05 +1300
+#   From: Fergus Slorach <sugref@gmail.com>
+#   Subject: svn commit --targets behaviour change in 1.7?
+@XFail()
+def commit_add_subadd(sbox):
+  "committing add with explicit subadd targets"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  A_path = os.path.join(wc_dir, 'A')
+  A2_path = os.path.join(wc_dir, 'A2')
+
+  targets_file = sbox.ospath('targets') # ### better tempdir?
+  targets_file = os.path.abspath(targets_file)
+
+  # prepare targets file
+  targets = "A2/D A2/D/H A2/D/H/chi A2/D/H/omega A2/D/H/psi".split()
+  open(targets_file, 'w').write("\n".join(targets))
+
+  # r2: add some stuff, with specific invocation
+  import shutil
+  shutil.copytree(A_path, A2_path)
+
+  # hack to copy A to A2, without creating .svn dirs when running against 1.6
+  svntest.main.run_svn(None, 'cp', A_path, A2_path)
+  svntest.main.run_svn(None, 'revert', '-R', A2_path)
+
+  os.chdir(wc_dir)
+  svntest.main.run_svn(None, 'commit', '--targets', targets_file, '-mm')
+
 
 ########################################################################
 # Run the tests
@@ -2894,6 +2928,7 @@ test_list = [ None,
               tree_conflicts_resolved,
               commit_multiple_nested_deletes,
               commit_incomplete,
+              commit_add_subadd,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/externals_tests.py?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/externals_tests.py Mon Nov 14 14:32:05 2011
@@ -2098,6 +2098,547 @@ def copy_file_externals(sbox):
   actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
     expected_status, None, None, None, None, None, True, wc_dir)
 
+def include_externals(sbox):
+  "commit --include-externals"
+  # svntest.factory.make(sbox, """
+  #   mkdir Z
+  #   echo 'This is the file zeta.' > Z/zeta
+  #   svn add Z
+  #   svn mkdir --parents Xpegged X/Y
+  #   svn ci
+  #   svn up
+  #   svn ps svn:externals "^/Z xZ" A/D/H
+  #   svn ps svn:externals "^/iota@1 Xpegged/xiota" wc_dir
+  #   # ^^^ manually set externals to:
+  #   #  ^/iota@1 Xpegged/xiota
+  #   #  -r1 ^/A/B/E Xpegged/xE
+  #   #  ^/A/mu X/xmu
+  #   #  ^/A/B/lambda X/Y/xlambda
+  #   #  ^/A/D/G X/xG
+  #   #  ^/A/D/H X/Y/xH
+  #   """)
+  # exit(0)
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  A_D_H = os.path.join(wc_dir, 'A', 'D', 'H')
+  X = os.path.join(wc_dir, 'X')
+  X_Y = os.path.join(wc_dir, 'X', 'Y')
+  Xpegged = os.path.join(wc_dir, 'Xpegged')
+  Z = os.path.join(wc_dir, 'Z')
+  Z_zeta = os.path.join(wc_dir, 'Z', 'zeta')
+
+  # mkdir Z
+  os.makedirs(Z)
+
+  # echo 'This is the file zeta.' > Z/zeta
+  main.file_write(Z_zeta, 'This is the file zeta.\n')
+
+  # svn add Z
+  expected_stdout = verify.UnorderedOutput([
+    'A         ' + Z + '\n',
+    'A         ' + Z_zeta + '\n',
+  ])
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'add', Z)
+
+  # svn mkdir --parents Xpegged X/Y
+  expected_stdout = verify.UnorderedOutput([
+    'A         ' + Xpegged + '\n',
+    'A         ' + X + '\n',
+    'A         ' + X_Y + '\n',
+  ])
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'mkdir',
+    '--parents', Xpegged, X_Y)
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    'Z'                 : Item(verb='Adding'),
+    'Z/zeta'            : Item(verb='Adding'),
+    'X'                 : Item(verb='Adding'),
+    'X/Y'               : Item(verb='Adding'),
+    'Xpegged'           : Item(verb='Adding'),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'Z'                 : Item(status='  ', wc_rev='2'),
+    'Z/zeta'            : Item(status='  ', wc_rev='2'),
+    'X'                 : Item(status='  ', wc_rev='2'),
+    'X/Y'               : Item(status='  ', wc_rev='2'),
+    'Xpegged'           : Item(status='  ', wc_rev='2'),
+  })
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'Z'                 : Item(),
+    'Z/zeta'            : Item(contents="This is the file zeta.\n"),
+    'Xpegged'           : Item(),
+    'X'                 : Item(),
+    'X/Y'               : Item(),
+  })
+
+  expected_status.tweak(wc_rev='2')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # svn ps svn:externals "^/Z xZ" A/D/H
+  expected_stdout = ["property 'svn:externals' set on '" + A_D_H + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps',
+    'svn:externals', '^/Z xZ', A_D_H)
+
+  # svn ps svn:externals "^/iota@1 Xpegged/xiota" wc_dir
+  expected_stdout = ["property 'svn:externals' set on '" + wc_dir + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps',
+    'svn:externals',
+    '''
+      ^/iota@1 Xpegged/xiota
+      -r1 ^/A/B/E Xpegged/xE
+      ^/A/mu X/xmu
+      ^/A/B/lambda X/Y/xlambda
+      ^/A/D/G X/xG
+      ^/A/D/H X/Y/xH
+    ''', wc_dir)
+
+  # svntest.factory.make(sbox, prev_disk=expected_disk,
+  #                      prev_status=expected_status,
+  #                      commands = """
+  #   svn ci
+  #   svn up
+  #   echo mod >> Xpegged/xE/alpha
+  #   echo mod >> X/xmu
+  #   echo mod >> X/Y/xlambda
+  #   echo mod >> X/xG/pi
+  #   echo mod >> X/Y/xH/chi
+  #   echo mod >> X/Y/xH/xZ/zeta
+  #   svn status
+  #   # Expect no externals to be committed
+  #   svn ci
+  #   # Expect no externals to be committed, because pegged
+  #   svn ci --include-externals Xpegged
+  #   # Expect no externals to be committed, because of depth
+  #   svn ci --depth=immediates --include-externals
+  #   # Expect only unpegged externals to be committed (those in X/)
+  #   svn ci --include-externals
+  #   # ### Below, manually add:
+  #   # expected_status.tweak('A/D/H/xZ', 'Xpegged/xE', 'X/Y/xH', 'X/xG',
+  #   #                       wc_rev=None)
+  #   svn up
+  #   # new mods to check more cases
+  #   echo mod >> X/xmu
+  #   echo mod >> X/Y/xlambda
+  #   echo mod >> X/xG/pi
+  #   echo mod >> X/Y/xH/chi
+  #   echo mod >> X/Y/xH/xZ/zeta
+  #   svn status
+  #   # Expect no externals to be committed, because of depth
+  #   svn ci --include-externals --depth=empty X
+  #   # Expect only file external xmu to be committed, because of depth
+  #   svn ci --include-externals --depth=files X
+  #   svn status
+  #   # ### Below, manually add:
+  #   # expected_status.tweak('A/D/H/xZ', 'Xpegged/xE', 'X/Y/xH', 'X/xG',
+  #   #                       wc_rev=None)
+  #   svn up
+  #   echo mod >> X/xG/pi
+  #   svn status
+  #   # Expect explicit targets to be committed
+  #   svn ci X/Y/xlambda X/xG
+  #   svn status
+  #   """)
+
+  X = os.path.join(wc_dir, 'X')
+  X_xG = os.path.join(wc_dir, 'X', 'xG')
+  X_xG_pi = os.path.join(wc_dir, 'X', 'xG', 'pi')
+  X_xmu = os.path.join(wc_dir, 'X', 'xmu')
+  X_Y_xH_chi = os.path.join(wc_dir, 'X', 'Y', 'xH', 'chi')
+  X_Y_xH_xZ_zeta = os.path.join(wc_dir, 'X', 'Y', 'xH', 'xZ', 'zeta')
+  X_Y_xlambda = os.path.join(wc_dir, 'X', 'Y', 'xlambda')
+  Xpegged = os.path.join(wc_dir, 'Xpegged')
+  Xpegged_xE_alpha = os.path.join(wc_dir, 'Xpegged', 'xE', 'alpha')
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    ''                  : Item(verb='Sending'),
+    'A/D/H'             : Item(verb='Sending'),
+  })
+
+  expected_status.tweak('', 'A/D/H', wc_rev='3')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/xmu'             : Item(status='A '),
+    'X/xG/tau'          : Item(status='A '),
+    'X/xG/rho'          : Item(status='A '),
+    'X/xG/pi'           : Item(status='A '),
+    'X/Y/xH'            : Item(status=' U'),
+    'X/Y/xH/psi'        : Item(status='A '),
+    'X/Y/xH/xZ/zeta'    : Item(status='A '),
+    'X/Y/xH/chi'        : Item(status='A '),
+    'X/Y/xH/omega'      : Item(status='A '),
+    'X/Y/xlambda'       : Item(status='A '),
+    'A/D/H/xZ/zeta'     : Item(status='A '),
+    'Xpegged/xiota'     : Item(status='A '),
+    'Xpegged/xE/alpha'  : Item(status='A '),
+    'Xpegged/xE/beta'   : Item(status='A '),
+  })
+
+  expected_disk.add({
+    'Xpegged/xE'        : Item(),
+    'Xpegged/xE/beta'   : Item(contents="This is the file 'beta'.\n"),
+    'Xpegged/xE/alpha'  : Item(contents="This is the file 'alpha'.\n"),
+    'Xpegged/xiota'     : Item(contents="This is the file 'iota'.\n"),
+    'A/D/H/xZ'          : Item(),
+    'A/D/H/xZ/zeta'     : Item(contents="This is the file zeta.\n"),
+    'X/Y/xlambda'       : Item(contents="This is the file 'lambda'.\n"),
+    'X/Y/xH'            : Item(),
+    'X/Y/xH/chi'        : Item(contents="This is the file 'chi'.\n"),
+    'X/Y/xH/xZ'         : Item(),
+    'X/Y/xH/xZ/zeta'    : Item(contents="This is the file zeta.\n"),
+    'X/Y/xH/psi'        : Item(contents="This is the file 'psi'.\n"),
+    'X/Y/xH/omega'      : Item(contents="This is the file 'omega'.\n"),
+    'X/xmu'             : Item(contents="This is the file 'mu'.\n"),
+    'X/xG'              : Item(),
+    'X/xG/tau'          : Item(contents="This is the file 'tau'.\n"),
+    'X/xG/rho'          : Item(contents="This is the file 'rho'.\n"),
+    'X/xG/pi'           : Item(contents="This is the file 'pi'.\n"),
+  })
+
+  expected_status.tweak(wc_rev='3')
+  expected_status.add({
+    'A/D/H/xZ'          : Item(status='X '),
+    'Xpegged/xiota'     : Item(status='  ', wc_rev='1', switched='X'),
+    'Xpegged/xE'        : Item(status='X '),
+    'X/Y/xH'            : Item(status='X '),
+    'X/Y/xlambda'       : Item(status='  ', wc_rev='3', switched='X'),
+    'X/xmu'             : Item(status='  ', wc_rev='3', switched='X'),
+    'X/xG'              : Item(status='X '),
+  })
+  expected_status.tweak('Xpegged/xiota', wc_rev='1')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # echo mod >> Xpegged/xE/alpha
+  main.file_append(Xpegged_xE_alpha, 'mod\n')
+
+  # echo mod >> X/xmu
+  main.file_append(X_xmu, 'mod\n')
+
+  # echo mod >> X/Y/xlambda
+  main.file_append(X_Y_xlambda, 'mod\n')
+
+  # echo mod >> X/xG/pi
+  main.file_append(X_xG_pi, 'mod\n')
+
+  # echo mod >> X/Y/xH/chi
+  main.file_append(X_Y_xH_chi, 'mod\n')
+
+  # echo mod >> X/Y/xH/xZ/zeta
+  main.file_append(X_Y_xH_xZ_zeta, 'mod\n')
+
+  # svn status
+  expected_status.tweak('X/Y/xlambda', 'X/xmu', status='M ')
+
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # Expect no externals to be committed
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # Expect no externals to be committed, because pegged
+  # svn ci --include-externals Xpegged
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', Xpegged)
+
+  # Expect no externals to be committed, because of depth
+  # svn ci --depth=immediates --include-externals
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--depth=immediates', '--include-externals', wc_dir)
+
+  # Expect only unpegged externals to be committed (those in X/)
+  # svn ci --include-externals
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/xmu'             : Item(verb='Sending'),
+    'X/Y/xlambda'       : Item(verb='Sending'),
+    'X/Y/xH/xZ/zeta'    : Item(verb='Sending'),
+    'X/Y/xH/chi'        : Item(verb='Sending'),
+    'X/xG/pi'           : Item(verb='Sending'),
+  })
+
+  expected_status.tweak(status='  ')
+  expected_status.tweak('X/Y/xlambda', 'X/xmu', wc_rev='4')
+  expected_status.tweak('X/Y/xH', 'X/xG', 'A/D/H/xZ', 'Xpegged/xE',
+    status='X ')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'              : Item(status='U '),
+    'A/D/H/chi'         : Item(status='U '),
+    'A/D/H/xZ/zeta'     : Item(status='U '),
+    'A/D/G/pi'          : Item(status='U '),
+    'A/B/lambda'        : Item(status='U '),
+    'Z/zeta'            : Item(status='U '),
+  })
+
+  expected_disk.tweak('Xpegged/xE/alpha',
+    contents="This is the file 'alpha'.\nmod\n")
+  expected_disk.tweak('A/D/H/chi', 'X/Y/xH/chi',
+    contents="This is the file 'chi'.\nmod\n")
+  expected_disk.tweak('A/D/H/xZ/zeta', 'X/Y/xH/xZ/zeta', 'Z/zeta',
+    contents='This is the file zeta.\nmod\n')
+  expected_disk.tweak('A/D/G/pi', 'X/xG/pi',
+    contents="This is the file 'pi'.\nmod\n")
+  expected_disk.tweak('A/mu', 'X/xmu',
+    contents="This is the file 'mu'.\nmod\n")
+  expected_disk.tweak('A/B/lambda', 'X/Y/xlambda',
+    contents="This is the file 'lambda'.\nmod\n")
+
+  expected_status.tweak(wc_rev='4')
+  expected_status.tweak('Xpegged/xiota', wc_rev='1')
+  expected_status.tweak('A/D/H/xZ', 'Xpegged/xE', 'X/Y/xH', 'X/xG',
+                        wc_rev=None)
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # new mods to check more cases
+  # echo mod >> X/xmu
+  main.file_append(X_xmu, 'mod\n')
+
+  # echo mod >> X/Y/xlambda
+  main.file_append(X_Y_xlambda, 'mod\n')
+
+  # echo mod >> X/xG/pi
+  main.file_append(X_xG_pi, 'mod\n')
+
+  # echo mod >> X/Y/xH/chi
+  main.file_append(X_Y_xH_chi, 'mod\n')
+
+  # echo mod >> X/Y/xH/xZ/zeta
+  main.file_append(X_Y_xH_xZ_zeta, 'mod\n')
+
+  # svn status
+  expected_status.tweak('X/Y/xlambda', 'X/xmu', status='M ')
+
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # Expect no externals to be committed, because of depth
+  # svn ci --include-externals --depth=empty X
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', '--depth=empty', X)
+
+  # Expect only file external xmu to be committed, because of depth
+  # svn ci --include-externals --depth=files X
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/xmu'             : Item(verb='Sending'),
+  })
+
+  expected_status.tweak(status='  ')
+  expected_status.tweak('X/xmu', wc_rev='5')
+  expected_status.tweak('X/Y/xlambda', status='M ')
+  expected_status.tweak('X/Y/xH', 'X/xG', 'A/D/H/xZ', 'Xpegged/xE',
+    status='X ')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', '--depth=files', X)
+
+  # svn status
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'              : Item(status='U '),
+  })
+
+  expected_disk.tweak('A/mu', 'X/xmu',
+    contents="This is the file 'mu'.\nmod\nmod\n")
+  expected_disk.tweak('X/Y/xlambda',
+    contents="This is the file 'lambda'.\nmod\nmod\n")
+  expected_disk.tweak('X/Y/xH/chi',
+    contents="This is the file 'chi'.\nmod\nmod\n")
+  expected_disk.tweak('X/Y/xH/xZ/zeta',
+    contents='This is the file zeta.\nmod\nmod\n')
+  expected_disk.tweak('X/xG/pi',
+    contents="This is the file 'pi'.\nmod\nmod\n")
+
+  expected_status.tweak(wc_rev='5')
+  expected_status.tweak('Xpegged/xiota', wc_rev='1')
+  expected_status.tweak('A/D/H/xZ', 'Xpegged/xE', 'X/Y/xH', 'X/xG',
+                        wc_rev=None)
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # echo mod >> X/xG/pi
+  main.file_append(X_xG_pi, 'mod\n')
+
+  # svn status
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # Expect explicit targets to be committed
+  # svn ci X/Y/xlambda X/xG
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/Y/xlambda'       : Item(verb='Sending'),
+    'X/xG/pi'           : Item(verb='Sending'),
+  })
+
+  expected_status.tweak(status='  ')
+  expected_status.tweak('X/Y/xlambda', wc_rev='6')
+  expected_status.tweak('X/Y/xH', 'X/xG', 'A/D/H/xZ', 'Xpegged/xE',
+    status='X ')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, X_Y_xlambda, X_xG)
+
+  # svn status
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+
+@XFail()
+def include_immediate_dir_externals(sbox):
+  "commit --include-externals --depth=immediates"
+  # See also comment inside svn_client_commit6().
+
+  #   svntest.factory.make(sbox,"""
+  #     svn mkdir X
+  #     svn ci
+  #     svn up
+  #     svn ps svn:externals "^/A/B/E X/XE" wc_dir
+  #     svn ci
+  #     svn up
+  # 
+  #     svn ps some change X/XE
+  #     echo mod >> X/XE/alpha
+  # 
+  #     svn st X/XE
+  #     # Expect only the propset on X/XE to be committed.
+  #     # Should be like 'svn commit --include-externals --depth=empty X/XE'.
+  #     svn commit --include-externals --depth=immediates X
+  #     """)
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  X = os.path.join(wc_dir, 'X')
+  X_XE = os.path.join(wc_dir, 'X', 'XE')
+  X_XE_alpha = os.path.join(wc_dir, 'X', 'XE', 'alpha')
+
+  # svn mkdir X
+  expected_stdout = ['A         ' + X + '\n']
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'mkdir', X)
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    'X'                 : Item(verb='Adding'),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'X'                 : Item(status='  ', wc_rev='2'),
+  })
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {})
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'X'                 : Item(),
+  })
+
+  expected_status.tweak(wc_rev='2')
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # svn ps svn:externals "^/A/B/E X/XE" wc_dir
+  expected_stdout = ["property 'svn:externals' set on '" + wc_dir + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps',
+    'svn:externals', '^/A/B/E X/XE', wc_dir)
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    ''                  : Item(verb='Sending'),
+  })
+
+  expected_status.tweak('', wc_rev='3')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/XE/alpha'        : Item(status='A '),
+    'X/XE/beta'         : Item(status='A '),
+  })
+
+  expected_disk.add({
+    'X/XE'              : Item(),
+    'X/XE/alpha'        : Item(contents="This is the file 'alpha'.\n"),
+    'X/XE/beta'         : Item(contents="This is the file 'beta'.\n"),
+  })
+
+  expected_status.tweak(wc_rev='3')
+  expected_status.add({
+    'X/XE'              : Item(status='X '),
+  })
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # svn ps some change X/XE
+  expected_stdout = ["property 'some' set on '" + X_XE + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps', 'some',
+    'change', X_XE)
+
+  # echo mod >> X/XE/alpha
+  main.file_append(X_XE_alpha, 'mod\n')
+
+  # svn st X/XE
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # Expect only the propset on X/XE to be committed.
+  # Should be like 'svn commit --include-externals --depth=empty X/XE'.
+  # svn commit --include-externals --depth=immediates X
+  expected_output = svntest.wc.State(wc_dir, {
+    'X/XE'              : Item(verb='Sending'),
+  })
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, '--include-externals', '--depth=immediates', X)
+
 
 ########################################################################
 # Run the tests
@@ -2140,6 +2681,8 @@ test_list = [ None,
               file_externals_different_repos,
               file_external_in_unversioned,
               copy_file_externals,
+              include_externals,
+              include_immediate_dir_externals,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/merge_tests.py?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/merge_tests.py Mon Nov 14 14:32:05 2011
@@ -17111,6 +17111,153 @@ def record_only_merge_adds_new_subtree_m
                                        None, None, None, None,
                                        None, 1, False)
 
+#----------------------------------------------------------------------
+# Setup helper for issue #4056 and issue #4057 tests.
+def noninheritable_mergeinfo_test_set_up(sbox):
+  '''Starting with standard greek tree, copy 'A' to 'branch' in r2 and
+  then made a file edit to A/B/lambda in r3.
+  Return (expected_output, expected_mergeinfo_output, expected_elision_output,
+          expected_status, expected_disk, expected_skip) for a merge of
+  r3 from ^/A/B to branch/B.'''
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  lambda_path   = os.path.join(wc_dir, 'A', 'B', 'lambda')
+  B_branch_path = os.path.join(wc_dir, 'branch', 'B')
+
+  # r2 - Branch ^/A to ^/branch.
+  svntest.main.run_svn(None, 'copy', sbox.repo_url + '/A',
+                       sbox.repo_url + '/branch', '-m', 'make a branch')
+
+  # r3 - Make an edit to A/B/lambda.
+  svntest.main.file_write(lambda_path, "trunk edit.\n")
+  svntest.main.run_svn(None, 'commit', '-m', 'file edit', wc_dir)
+  svntest.main.run_svn(None, 'up', wc_dir)
+
+  expected_output = wc.State(B_branch_path, {
+    'lambda' : Item(status='U '),
+    })
+  expected_mergeinfo_output = wc.State(B_branch_path, {
+    ''       : Item(status=' U'),
+    'lambda' : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(B_branch_path, {
+    })
+  expected_status = wc.State(B_branch_path, {
+    ''        : Item(status=' M'),
+    'lambda'  : Item(status='M '),
+    'E'       : Item(status='  '),
+    'E/alpha' : Item(status='  '),
+    'E/beta'  : Item(status='  '),
+    'F'       : Item(status='  '),
+    })
+  expected_status.tweak(wc_rev='3')
+  expected_disk = wc.State('', {
+    ''          : Item(props={SVN_PROP_MERGEINFO : '/A/B:3'}),
+    'lambda'  : Item("trunk edit.\n"),
+    'E'       : Item(),
+    'E/alpha' : Item("This is the file 'alpha'.\n"),
+    'E/beta'  : Item("This is the file 'beta'.\n"),
+    'F'       : Item(),
+    })
+  expected_skip = wc.State(B_branch_path, {})
+
+  return expected_output, expected_mergeinfo_output, expected_elision_output, \
+    expected_status, expected_disk, expected_skip
+
+
+#----------------------------------------------------------------------
+# Test for issue #4056 "don't record non-inheritable mergeinfo if missing
+# subtrees are not touched by the full-depth diff".
+@Issue(4056)
+@XFail()
+@SkipUnless(server_has_mergeinfo)
+def unnecessary_noninheritable_mergeinfo_missing_subtrees(sbox):
+  "missing subtrees untouched by infinite depth merge"
+
+  B_branch_path = os.path.join(sbox.wc_dir, 'branch', 'B')
+
+  # Setup a simple branch to which 
+  expected_output, expected_mergeinfo_output, expected_elision_output, \
+    expected_status, expected_disk, expected_skip = \
+    noninheritable_mergeinfo_test_set_up(sbox)
+
+  # Create a shallow merge target; set depth of branch/B to files.
+  svntest.main.run_svn(None, 'up', '--set-depth=files', B_branch_path)
+  expected_status.remove('E', 'E/alpha', 'E/beta', 'F')
+  expected_disk.remove('E', 'E/alpha', 'E/beta', 'F')
+
+  # Merge r3 from ^/A/B to branch/B
+  #
+  # Currently this fails because merge isn't smart enough to
+  # realize that despite the shallow merge target, the diff can
+  # only affect branch/B/lambda, which is still present, so there
+  # is no need to record non-inheritable mergeinfo on the target
+  # or any subtree mergeinfo whatsoever:
+  #
+  #   >svn pg svn:mergeinfo -vR
+  #   Properties on 'branch\B':
+  #     svn:mergeinfo
+  #       /A/B:3* <-- Should be inheritable
+  #   Properties on 'branch\B\lambda':
+  #     svn:mergeinfo
+  #       /A/B/lambda:3 <-- Not neccessary
+  svntest.actions.run_and_verify_merge(B_branch_path,
+                                       '2', '3',
+                                       sbox.repo_url + '/A/B', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None, None, 1, 1,
+                                       B_branch_path)
+
+#----------------------------------------------------------------------
+# Test for issue #4057 "don't record non-inheritable mergeinfo in shallow
+# merge if entire diff is within requested depth".
+@Issue(4057)
+@XFail()
+@SkipUnless(server_has_mergeinfo)
+def unnecessary_noninheritable_mergeinfo_shallow_merge(sbox):
+  "shallow merge reaches all neccessary subtrees"
+
+  B_branch_path = os.path.join(sbox.wc_dir, 'branch', 'B')
+
+  # Setup a simple branch to which 
+  expected_output, expected_mergeinfo_output, expected_elision_output, \
+    expected_status, expected_disk, expected_skip = \
+    noninheritable_mergeinfo_test_set_up(sbox)
+
+  # Merge r3 from ^/A/B to branch/B at operational depth=files
+  #
+  # Currently this fails because merge isn't smart enough to
+  # realize that despite being a shallow merge, the diff can
+  # only affect branch/B/lambda, which is within the specified
+  # depth, so there is no need to record non-inheritable mergeinfo
+  # or subtree mergeinfo:
+  #
+  #   >svn pg svn:mergeinfo -vR
+  #   Properties on 'branch\B':
+  #     svn:mergeinfo
+  #       /A/B:3* <-- Should be inheritable
+  #   Properties on 'branch\B\lambda':
+  #     svn:mergeinfo
+  #       /A/B/lambda:3 <-- Not neccessary
+  expected_skip = wc.State(B_branch_path, {})
+  svntest.actions.run_and_verify_merge(B_branch_path, '2', '3',
+                                       sbox.repo_url + '/A/B', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None, None, 1, 1,
+                                       '--depth', 'files', B_branch_path)
+
 ########################################################################
 # Run the tests
 
@@ -17239,6 +17386,8 @@ test_list = [ None,
               reverse_merge_adds_subtree,
               merged_deletion_causes_tree_conflict,
               record_only_merge_adds_new_subtree_mergeinfo,
+              unnecessary_noninheritable_mergeinfo_missing_subtrees,
+              unnecessary_noninheritable_mergeinfo_shallow_merge,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/mergeinfo_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/mergeinfo_tests.py?rev=1201727&r1=1201726&r2=1201727&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/mergeinfo_tests.py (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/mergeinfo_tests.py Mon Nov 14 14:32:05 2011
@@ -679,6 +679,52 @@ def natural_history_is_not_eligible_nor_
     ['3','4','5','6','7','9'], sbox.repo_url + '/A',
     A_COPY_path, '--show-revs', 'merged', '-R')
 
+#----------------------------------------------------------------------
+# A test for issue 4050 "'svn mergeinfo' always considers non-inheritable
+# ranges as partially merged".
+@Issue(4050)
+@XFail()
+@SkipUnless(server_has_mergeinfo)
+def noninheritabled_mergeinfo_not_always_eligible(sbox):
+  "noninheritabled mergeinfo not always eligible"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  A_path      = os.path.join(wc_dir, 'A')
+  branch_path = os.path.join(wc_dir, 'branch')
+  
+  # r2 - Branch ^/A to ^/branch.
+  svntest.main.run_svn(None, 'copy', sbox.repo_url + '/A',
+                       sbox.repo_url + '/branch', '-m', 'make a branch')
+  
+  # r3 - Make prop edit to A.
+  svntest.main.run_svn(None, 'ps', 'prop', 'val', A_path)
+  svntest.main.run_svn(None, 'commit', '-m', 'file edit', wc_dir)
+  svntest.main.run_svn(None, 'up', wc_dir)
+
+  # r4 - Merge r3 from ^/A to branch at depth=empty.
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A', branch_path,
+                                     '-c3', '--depth=empty')
+  svntest.main.run_svn(None, 'commit', '-m', 'shallow merge', wc_dir)
+
+  # Now check that r3 is reported as fully merged from ^/A to ^/branch
+  # and does not show up all when asking for eligible revs.
+  #
+  # Currently this fails because r3 shows up as partially merged, even
+  # though it is fully merged to ^/branch.
+  svntest.actions.run_and_verify_mergeinfo(
+    adjust_error_for_server_version(''),
+    ['3'], sbox.repo_url + '/A', sbox.repo_url + '/branch',
+    '--show-revs', 'merged', '-R')
+  # Likewise r3 shows up as partially eligible when asking about
+  # for --show-revs=eligible.
+  svntest.actions.run_and_verify_mergeinfo(
+    adjust_error_for_server_version(''),
+    [], sbox.repo_url + '/A', sbox.repo_url + '/branch',
+    '--show-revs', 'eligible', '-R')
+
 ########################################################################
 # Run the tests
 
@@ -695,6 +741,7 @@ test_list = [ None,
               mergeinfo_on_pegged_wc_path,
               wc_target_inherits_mergeinfo_from_repos,
               natural_history_is_not_eligible_nor_merged,
+              noninheritabled_mergeinfo_not_always_eligible,
              ]
 
 if __name__ == '__main__':



Mime
View raw message