Index: subversion/libsvn_client/copy.c
===================================================================
--- subversion/libsvn_client/copy.c	(revision 33235)
+++ subversion/libsvn_client/copy.c	(working copy)
@@ -129,7 +129,8 @@
           SVN_ERR(svn_client__get_wc_mergeinfo(&src_mergeinfo, &inherited,
                                                FALSE, svn_mergeinfo_inherited,
                                                entry, src_path_or_url, NULL,
-                                               NULL, adm_access, ctx, pool));
+                                               NULL, NULL, NULL, adm_access,
+                                               FALSE, ctx, pool));
         }
     }
 
@@ -172,57 +173,109 @@
                               svn_client_ctx_t *ctx, apr_pool_t *pool)
 {
   apr_hash_t *mergeinfo;
-  const svn_wc_entry_t *entry;
+  const svn_wc_entry_t *src_entry;
 
-  SVN_ERR(svn_wc__entry_versioned(&entry, pair->src, src_access, FALSE, pool));
+  svn_mergeinfo_t src_mergeinfo;
+  svn_boolean_t src_inherited;
+  const char *src_original_mergeinfo_url;
+  svn_mergeinfo_t src_original_mergeinfo;
 
-  /* Don't attempt to figure out implied mergeinfo for a locally
-     added/replaced PAIR->src without history (if its deleted we
-     should never even get this far). */
-  if (entry->schedule == svn_wc_schedule_normal
-      || (entry->schedule == svn_wc_schedule_add && entry->copied))
-    {
-      pair->src_revnum = entry->revision;
+  svn_mergeinfo_t dst_mergeinfo;
+  svn_wc_entry_t *dst_entry;
+  svn_boolean_t dst_inherited;
+  const char *dst_original_mergeinfo_url;
+  svn_mergeinfo_t dst_original_mergeinfo;
 
-      /* ASSUMPTION: Non-numeric operative and peg revisions --
-         other than working or unspecified -- won't be encountered
-         here.  For those cases, WC paths will have already been
-         transformed into repository URLs (as done towards the end
-         of the try_copy() routine), and be handled by a
-         different code path. */
-      SVN_ERR(calculate_target_mergeinfo(NULL, &mergeinfo,
-                                         src_access, pair->src,
-                                         pair->src_revnum, TRUE,
-                                         ctx, pool));
+  SVN_ERR(svn_wc__entry_versioned(&src_entry, pair->src, src_access, FALSE, pool));
 
-      /* NULL mergeinfo could be due to there being no mergeinfo.  But
-         it could also be due to us not being able to query the server
-         about mergeinfo on some parent directory of ours.  We need to
-         turn "no mergeinfo" into "empty mergeinfo", just in case. */
-      if (! mergeinfo)
-        mergeinfo = apr_hash_make(pool);
+  pair->src_revnum = src_entry->revision;
 
-      /* Because any local mergeinfo from the copy source will have
-         already been propagated to the destination, we can avoid
-         looking at WC-local mergeinfo for the source. */
-      SVN_ERR(svn_wc__entry_versioned(&entry, pair->dst, dst_access, FALSE,
-                                      pool));
+  SVN_ERR(svn_client__get_wc_mergeinfo(&src_mergeinfo, &src_inherited,
+                                       FALSE, svn_mergeinfo_inherited,
+                                       src_entry, pair->src, NULL,
+                                       NULL, &src_original_mergeinfo,
+                                       &src_original_mergeinfo_url,
+                                       src_access, TRUE, ctx, pool));
 
-      return extend_wc_mergeinfo(pair->dst, entry, mergeinfo, dst_access,
-                                 ctx, pool);
-    }
+  /* In the case of 'mergeinfo affecting' copy we will setup src_mergeinfo
+     on dst or setup empty mergeinfo if src_mergeinfo is NULL */
+  if (src_mergeinfo)
+    mergeinfo = src_mergeinfo;
+  else
+    mergeinfo = apr_hash_make(pool);
 
-  /* If the source had no explicit mergeinfo, set empty explicit
-     mergeinfo for PAIR->dst, as it almost certainly won't be correct
-     for that path to inherit the mergeinfo of its parent. */
-  SVN_ERR(svn_client__parse_mergeinfo(&mergeinfo, entry, pair->src, FALSE,
-                                      src_access, ctx, pool));
-  if (mergeinfo == NULL)
+  SVN_ERR(svn_wc__entry_versioned(&dst_entry, pair->dst, dst_access, FALSE,
+                                  pool));
+
+  /* Now we will try to eliminate explicit mergeinfo on the dst. Explicit
+     mergeinfo can be eliminated if it's a 'mergeinfo NON-affecting'
+     WC-to-WC copy.
+
+     WC-to-WC copy can be considered as 'megeinfo NON-affecting' if and
+     only if the following conditions are satisfied:
+      a) src and dst are located below the same URL
+      b) mergeinfo (if any) for src and dst are inherited from this URL
+      c) inherited mergeinfos (if any) for src and dst are equal.
+  
+     There is no need in further checks if src has an explicit mergeinfo
+     set on it (src_mergeinfo != NULL and src_inherited = FALSE). Above
+     mentioned condition b) will be violated in that case. */
+  if (!(src_mergeinfo && !src_inherited))
     {
-      mergeinfo = apr_hash_make(pool);
-      return svn_client__record_wc_mergeinfo(pair->dst, mergeinfo, dst_access,
-                                             pool);
-    }
+      SVN_ERR(svn_client__get_wc_mergeinfo(&dst_mergeinfo, &dst_inherited,
+                                           FALSE, svn_mergeinfo_inherited,
+                                           dst_entry, pair->dst, NULL,
+                                           NULL, &dst_original_mergeinfo,
+                                           &dst_original_mergeinfo_url,
+                                           dst_access, TRUE, ctx, pool));
+
+      /* WC-to-WC copy can be considered as 'mergeinfo NON-affecting' copy
+         if and only if src and dst have the same (not null) effective
+         mergeinfo urls. */
+      if (src_original_mergeinfo_url != NULL
+          && dst_original_mergeinfo_url != NULL
+          && strcmp(src_original_mergeinfo_url, dst_original_mergeinfo_url)
+             == 0)
+        {
+          svn_boolean_t mergeinfos_are_equal = FALSE;
+
+          if (src_original_mergeinfo == NULL
+              && dst_original_mergeinfo == NULL)
+            {
+              /* Effective mergeinfos are considered as equal when both of
+                 them are equal to zero (i.e. there is no mergeinfo for
+                 both src and dst). */
+              mergeinfos_are_equal = TRUE;
+            }
+          else
+            {
+              /* We compare mergeinfos if both of them are not null. */
+              if (src_original_mergeinfo != NULL
+                  && dst_original_mergeinfo != NULL)
+                {
+                  SVN_ERR(svn_mergeinfo__equals(&mergeinfos_are_equal,
+                                                src_original_mergeinfo,
+                                                dst_original_mergeinfo,
+                                                TRUE, pool));
+                }
+              else
+                {
+                  /* Otherwise mergeinfos are not equal. */
+                  mergeinfos_are_equal = FALSE;
+                }
+            }
+
+          /* WC-to-WC copy is considered as 'mergeinfo NON-affecting' copy
+             if src and dst have the same (not null) effective mergeinfo
+             urls and the same effective mergeinfos set to them. */
+          if (mergeinfos_are_equal)
+              mergeinfo = NULL;
+        }
+  }
+
+  if (mergeinfo != NULL)
+    return extend_wc_mergeinfo(pair->dst, dst_entry, mergeinfo, dst_access,
+                               ctx, pool);
   else
     return SVN_NO_ERROR;
 }
Index: subversion/libsvn_client/merge.c
===================================================================
--- subversion/libsvn_client/merge.c	(revision 33235)
+++ subversion/libsvn_client/merge.c	(working copy)
@@ -3177,8 +3177,9 @@
           svn_boolean_t inherited;
           SVN_ERR(svn_client__get_wc_mergeinfo(&mergeinfo, &inherited, TRUE,
                                                svn_mergeinfo_nearest_ancestor,
-                                               entry, path, NULL, NULL,
-                                               adm_access, ctx, subpool));
+                                               entry, path, NULL, NULL, NULL,
+                                               NULL, adm_access, FALSE, ctx,
+                                               subpool));
         }
 
       if (mergeinfo == NULL)
@@ -4569,8 +4570,9 @@
                               (&mergeinfo, &inherited, FALSE,
                                svn_mergeinfo_nearest_ancestor,
                                entry, child_of_noninheritable->path,
-                               merge_cmd_baton->target, NULL, adm_access,
-                               merge_cmd_baton->ctx, iterpool));
+                               merge_cmd_baton->target, NULL, NULL, NULL,
+                               adm_access, FALSE, merge_cmd_baton->ctx,
+                               iterpool));
 
                       SVN_ERR(svn_client__record_wc_mergeinfo(
                         child_of_noninheritable->path, mergeinfo, adm_access,
@@ -5538,7 +5540,8 @@
                                                svn_mergeinfo_explicit,
                                                path_entry,
                                                path_with_new_mergeinfo,
-                                               NULL, NULL, adm_access,
+                                               NULL, NULL, NULL, NULL,
+                                               adm_access, FALSE,
                                                merge_b->ctx, iterpool));
           /* ...there *should* always be explicit mergeinfo at this point
              but you can't be too careful. */
@@ -6169,7 +6172,8 @@
                   SVN_ERR(svn_client__get_wc_mergeinfo(
                     &added_path_mergeinfo, &inherited, FALSE,
                     svn_mergeinfo_explicit, entry, added_path,
-                    NULL, NULL, adm_access, merge_b->ctx, iterpool));
+                    NULL, NULL, NULL, NULL, adm_access, FALSE, merge_b->ctx,
+                    iterpool));
 
                   /* Combine the explict mergeinfo on the added path (if any)
                      with the mergeinfo for this merge. */
Index: subversion/libsvn_client/mergeinfo.c
===================================================================
--- subversion/libsvn_client/mergeinfo.c	(revision 33235)
+++ subversion/libsvn_client/mergeinfo.c	(working copy)
@@ -133,7 +133,10 @@
                              const char *wcpath,
                              const char *limit_path,
                              const char **walked_path,
+                             svn_mergeinfo_t *original_mergeinfo,
+                             const char **original_mergeinfo_url,
                              svn_wc_adm_access_t *adm_access,
+                             svn_boolean_t allow_mixed_revisions,
                              svn_client_ctx_t *ctx,
                              apr_pool_t *pool)
 {
@@ -141,6 +144,7 @@
   svn_mergeinfo_t wc_mergeinfo;
   svn_boolean_t switched;
   svn_revnum_t base_revision = entry->revision;
+  const char *orig_url = NULL;
 
   if (limit_path)
     SVN_ERR(svn_path_get_absolute(&limit_path, limit_path, pool));
@@ -164,6 +168,8 @@
           SVN_ERR(svn_client__parse_mergeinfo(&wc_mergeinfo, entry, wcpath,
                                               pristine, adm_access, ctx,
                                               pool));
+
+          orig_url = entry->url;
         }
 
       /* If WCPATH is switched, don't look any higher for inherited
@@ -219,6 +225,12 @@
                   err = SVN_NO_ERROR;
                   *inherited = FALSE;
                   *mergeinfo = wc_mergeinfo;
+
+                  if (original_mergeinfo_url)
+                    *original_mergeinfo_url = orig_url;
+
+                  if (original_mergeinfo)
+                    *original_mergeinfo = wc_mergeinfo;
                 }
               return err;
             }
@@ -227,9 +239,12 @@
 
           /* Look in WCPATH's parents only if the parents share the same
              working revision. */
-          if (base_revision < entry->cmt_rev
-              || entry->revision < base_revision)
-            break;
+          if (!allow_mixed_revisions)
+            {
+              if (base_revision < entry->cmt_rev
+                || entry->revision < base_revision)
+                break;
+            }
 
           if (entry)
             /* We haven't yet risen above the root of the WC. */
@@ -264,6 +279,12 @@
   if (walked_path)
     *walked_path = walk_path;
 
+  if (original_mergeinfo_url)
+    *original_mergeinfo_url = orig_url;
+
+  if (original_mergeinfo)
+    *original_mergeinfo = wc_mergeinfo;
+
   /* Remove non-inheritable mergeinfo and paths mapped to empty ranges
      which may occur if WCPATH's mergeinfo is not explicit. */
   if (*inherited)
@@ -352,7 +373,8 @@
   else
     SVN_ERR(svn_client__get_wc_mergeinfo(target_mergeinfo, indirect, FALSE,
                                          inherit, entry, target_wcpath,
-                                         NULL, NULL, adm_access, ctx, pool));
+                                         NULL, NULL, NULL, NULL, adm_access,
+                                         FALSE, ctx, pool));
 
   /* If there is no WC mergeinfo check the repository. */
   if (*target_mergeinfo == NULL)
@@ -735,8 +757,8 @@
                                            wc_elision_limit_path
                                              ? wc_elision_limit_path
                                              : NULL,
-                                           &walk_path, adm_access,
-                                           ctx, pool));
+                                           &walk_path, NULL, NULL, adm_access,
+                                           FALSE, ctx, pool));
 
      /* If TARGET_WCPATH has no explicit mergeinfo, there's nothing to
          elide, we're done. */
@@ -750,8 +772,8 @@
                                            wc_elision_limit_path
                                              ? wc_elision_limit_path
                                              : NULL,
-                                           &walk_path, adm_access,
-                                           ctx, pool));
+                                           &walk_path, NULL, NULL, adm_access,
+                                           FALSE, ctx, pool));
 
       /* If TARGET_WCPATH inherited no mergeinfo from the WC and we are
          not limiting our search to the working copy then check if it
Index: subversion/libsvn_client/mergeinfo.h
===================================================================
--- subversion/libsvn_client/mergeinfo.h	(revision 33235)
+++ subversion/libsvn_client/mergeinfo.h	(working copy)
@@ -71,10 +71,13 @@
    in *MERGEINFO (NULL if no mergeinfo is set).  Set *INHERITED to
    whether the mergeinfo was inherited (TRUE or FALSE).
 
-   This function will search for inherited mergeinfo in the parents of
-   WCPATH only if the working revision of WCPATH falls within the range
-   of the parent's last committed revision to the parent's working
-   revision (inclusive).
+   This function will search for inherited mergeinfo in the parents of WCPATH.
+   If ALLOW_MIXED_REVISIONS is FALSE, then the search will be continued until
+   the working revision of WCPATH falls within the range of the parent's last
+   committed revision to the parent's working revision (inclusive). If
+   ALLOW_MIXED_REVISIONS is TRUE, then the last condition will be ignored (the
+   search will be continued independently of parents's last committed and
+   working revisions).
 
    INHERIT indicates whether explicit, explicit or inherited, or only
    inherited mergeinfo for WCPATH is retrieved.
@@ -83,7 +86,16 @@
    (ignored if NULL) or beyond any switched path.
 
    Set *WALKED_PATH to the path climbed from WCPATH to find inherited
-   mergeinfo, or "" if none was found. (ignored if NULL). */
+   mergeinfo, or "" if none was found. (ignored if NULL).
+
+   Set *ORIGINAL_MERGEINFO to the original (not adjusted) mergeinfo found on
+   WCPATH or one of its ancestors. Set *ORIGINAL_MERGEINFO to NULL if there is
+   no mergeinfo found. (Ignore if ORIGINAL_MERGEINFO is NULL).
+
+   Set *ORIGINAL_MERGEINFO_URL to the last url scanned for mergeinfo. It can be
+   the url of WCPATH (in the case of explicit mergeinfo) or one of its
+   ancestors (in the case of inherited mergeinfo).
+   */
 svn_error_t *
 svn_client__get_wc_mergeinfo(svn_mergeinfo_t *mergeinfo,
                              svn_boolean_t *inherited,
@@ -93,7 +105,10 @@
                              const char *wcpath,
                              const char *limit_path,
                              const char **walked_path,
+                             svn_mergeinfo_t *original_mergeinfo,
+                             const char **original_mergeinfo_url,
                              svn_wc_adm_access_t *adm_access,
+                             svn_boolean_t allow_mixed_revisions,
                              svn_client_ctx_t *ctx,
                              apr_pool_t *pool);
 
Index: subversion/tests/cmdline/copy_tests.py
===================================================================
--- subversion/tests/cmdline/copy_tests.py	(revision 33235)
+++ subversion/tests/cmdline/copy_tests.py	(working copy)
@@ -145,11 +145,7 @@
                                      'cp', pi_src, rho_path)
 
   # Verify both content and props have been copied
-  if wc_copy:
-    props = { SVN_PROP_MERGEINFO : '',
-              'phony-prop' : '*'}
-  else:
-    props = { 'phony-prop' : '*'}
+  props = { 'phony-prop' : '*'}
 
   expected_disk.tweak('A/D/G/rho',
                       contents="This is the file 'pi'.\n",
@@ -2603,11 +2599,9 @@
 
   # Tweak expected disk tree
   expected_disk.add({
-    'A/C/upsilon' : Item(props={ 'foo' : 'bar',
-                                 SVN_PROP_MERGEINFO : '' },
+    'A/C/upsilon' : Item(props={ 'foo' : 'bar' },
                          contents="This is the file 'upsilon'\n"),
-    'A/C/I'       : Item(props={ 'foo' : 'bar',
-                                 SVN_PROP_MERGEINFO : '' }),
+    'A/C/I'       : Item(props={ 'foo' : 'bar' }),
     })
 
   svntest.actions.run_and_verify_commit(wc_dir,
@@ -3230,8 +3224,8 @@
   expected_disk = svntest.main.greek_state.copy()
   expected_disk.tweak('A/D/H/psi', contents=iota_text)
   expected_disk.add({
-    'iota'      : Item(contents=psi_text, props={SVN_PROP_MERGEINFO : ''}),
-    'A/D/H/psi' : Item(contents=iota_text, props={SVN_PROP_MERGEINFO : ''}),
+    'iota'      : Item(contents=psi_text),
+    'A/D/H/psi' : Item(contents=iota_text),
     'sigma'     : Item(contents=psi_text, props={}),
     })
 
@@ -3306,11 +3300,11 @@
   expected_disk.remove('A/D/G/rho')
   expected_disk.remove('A/D/G/tau')
   expected_disk.add({
-    'A/B/E'       : Item(props={SVN_PROP_MERGEINFO : ''}),
+    'A/B/E'       : Item(),
     'A/B/E/pi'    : Item(contents="This is the file 'pi'.\n"),
     'A/B/E/rho'   : Item(contents="This is the file 'rho'.\n"),
     'A/B/E/tau'   : Item(contents="This is the file 'tau'.\n"),
-    'A/D/G'       : Item(props={SVN_PROP_MERGEINFO : ''}),
+    'A/D/G'       : Item(),
     'A/D/G/beta'  : Item(contents="This is the file 'beta'.\n"),
     'A/J'         : Item(props={}),
     'A/J/alpha'   : Item(contents="This is the file 'alpha'.\n"),
@@ -3986,6 +3980,495 @@
   finally:
     os.chdir(saved_cwd)
 
+#----------------------------------------------------------------------
+# Test that empty mergeinfo isn't created when file is copied within
+# single working copy and there is no of any explicit mergeinfos at all
+
+def no_empty_mergeinfo_on_local_copy_file(sbox):
+  "local copy file with no mergeinfo at all"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  iota_path = wc_dir + '/iota'
+  iota_cp_path = wc_dir + '/A/D/H/iota-copy'
+
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     iota_path, iota_cp_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/D/H/iota-copy'           : Item(contents="This is the file 'iota'.\n"),
+    })
+
+  svntest.actions.verify_disk(wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/D/H/iota-copy'           : Item(status='A ', copied='+', wc_rev='-'),
+    })
+
+  svntest.actions.run_and_verify_status(wc_dir,
+                                        expected_status)
+
+
+#----------------------------------------------------------------------
+# Test that empty mergeinfo isn't created when dir is copied within
+# single working copy and there is no of any explicit mergeinfos at all
+
+def no_empty_mergeinfo_on_local_copy_dir(sbox):
+  "local copy dir with no mergeinfo at all"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  E_path = wc_dir + '/A/B/E'
+  E_cp_path = wc_dir + '/A/D/G/E-COPY'
+
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     E_path, E_cp_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/D/G/E-COPY'              : Item(),
+    'A/D/G/E-COPY/alpha'        : Item(contents="This is the file 'alpha'.\n"),
+    'A/D/G/E-COPY/beta'         : Item(contents="This is the file 'beta'.\n"),
+    })
+
+  svntest.actions.verify_disk(wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/D/G/E-COPY'              : Item(status='A ', copied='+', wc_rev='-'),
+    'A/D/G/E-COPY/alpha'        : Item(status='  ', copied='+', wc_rev='-'),
+    'A/D/G/E-COPY/beta'         : Item(status='  ', copied='+', wc_rev='-'),
+    })
+
+  svntest.actions.run_and_verify_status(wc_dir,
+                                        expected_status)
+
+# Helper to generate some mergeinfo in the working copy
+def branch_change_and_merge_back(sbox, wc_dir):
+  E_path = wc_dir + '/A/B/E'
+  E2_alpha_path = wc_dir + '/A/B/E2/alpha'
+
+  E_url = sbox.repo_url + '/A/B/E'
+  E2_url = sbox.repo_url + '/A/B/E2'
+
+  # Copy E folder in the repo
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',  '-m', 'log msg',
+                                     E_url, E2_url)
+
+  # Update the whole working copy
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'up', wc_dir)
+
+  # Modify E2/alpha to make it 'changed in the branch'.
+  svntest.main.file_append(E2_alpha_path,
+                          "Changed in the branch.\n")
+
+  # Commit E2/alpha changes to the repository
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ci',  '-m', 'log msg',
+                                     wc_dir)
+
+  # Merge E2 folder into E
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'merge', E2_url, E_path)
+
+  # Commit changes in E folder (mergeinfo will be commited to repository)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ci',  '-m', 'log msg',
+                                     E_path)
+
+  # Update the whole working copy
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'up', wc_dir)
+
+
+#----------------------------------------------------------------------
+# Test that explicit mergeinfo is created when it's 'mergeinfo
+# affecting' copy
+
+def local_copy_with_explicit_mergeinfo(sbox):
+  "'mergeinfo affecting' copy"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  alpha_path = wc_dir + '/A/B/E/alpha'
+  alpha_cp_path = wc_dir + '/A/alpha-copy'
+
+  branch_change_and_merge_back(sbox, wc_dir)
+
+  # Copy alpha in the working copy
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     alpha_path, alpha_cp_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/alpha-copy'     : Item(
+              contents="This is the file 'alpha'.\nChanged in the branch.\n",
+                         props = { SVN_PROP_MERGEINFO : '/A/B/E2/alpha:2-3' }),
+    'A/B/E2/alpha'     : Item(
+              contents="This is the file 'alpha'.\nChanged in the branch.\n"),
+    'A/B/E2/beta'      : Item(contents="This is the file 'beta'.\n"),
+    })
+
+  expected_disk.tweak(
+      'A/B/E/alpha',
+      contents="This is the file 'alpha'.\nChanged in the branch.\n")
+  expected_disk.tweak(
+      'A/B/E', props = { SVN_PROP_MERGEINFO : '/A/B/E2:2-3' })
+
+  svntest.actions.verify_disk(wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 4)
+  expected_status.add({
+    'A/alpha-copy'              : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2'                    : Item(status='  ', wc_rev=4),
+    'A/B/E2/alpha'              : Item(status='  ', wc_rev=4),
+    'A/B/E2/beta'               : Item(status='  ', wc_rev=4),
+    })
+
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+#----------------------------------------------------------------------
+# Test that explicit mergeinfo isn't created when it's 'mergeinfo
+# NON-affecting' copy
+
+def local_mergeinfo_non_affecting_copy(sbox):
+  "'mergeinfo NON-affecting' copy"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  alpha_path = wc_dir + '/A/B/E/alpha'
+  alpha_cp_path = wc_dir + '/A/B/E/alpha-copy'
+
+  branch_change_and_merge_back(sbox, wc_dir)
+
+  # Copy alpha in the working copy
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     alpha_path, alpha_cp_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/B/E/alpha-copy'    : Item(
+               contents="This is the file 'alpha'.\nChanged in the branch.\n"),
+    'A/B/E2/alpha'        : Item(
+               contents="This is the file 'alpha'.\nChanged in the branch.\n"),
+    'A/B/E2/beta'         : Item(contents="This is the file 'beta'.\n"),
+    })
+
+  expected_disk.tweak(
+      'A/B/E/alpha',
+      contents="This is the file 'alpha'.\nChanged in the branch.\n")
+  expected_disk.tweak(
+      'A/B/E', props = { SVN_PROP_MERGEINFO : '/A/B/E2:2-3' })
+
+  svntest.actions.verify_disk(wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 4)
+  expected_status.add({
+    'A/B/E/alpha-copy'          : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2'                    : Item(status='  ', wc_rev=4),
+    'A/B/E2/alpha'              : Item(status='  ', wc_rev=4),
+    'A/B/E2/beta'               : Item(status='  ', wc_rev=4),
+    })
+
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+#----------------------------------------------------------------------
+# Test that empty mergeinfo isn't created when file is copied between
+# two working copies
+
+def non_local_copy_between_wc(sbox):
+  "'mergeinfo NON-affecting' copy file between wc"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  wc2_dir = sbox.add_wc_path('other')
+
+  # Checkout second working copy from the same URL
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'co',
+                                     sbox.repo_url, wc2_dir)
+
+  iota_path = wc_dir + '/iota'
+  iota_cp_path = wc2_dir + '/A/D/H/iota-copy'
+
+  # Copy iota between working copies
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     iota_path, iota_cp_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/D/H/iota-copy'           : Item(contents="This is the file 'iota'.\n"),
+    })
+
+  svntest.actions.verify_disk(wc2_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc2_dir, 1)
+  expected_status.add({
+    'A/D/H/iota-copy'           : Item(status='A ', copied='+', wc_rev='-'),
+    })
+
+  svntest.actions.run_and_verify_status(wc2_dir, expected_status)
+
+#----------------------------------------------------------------------
+# Test that empty mergeinfo is created when file is copied into
+# switched WC
+
+def non_local_copy_into_switched(sbox):
+  "'mergeinfo affecting' copy file into switched wc"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  G_path = sbox.wc_dir + '/A/D/G'
+  H_url = sbox.repo_url + '/A/D/H'
+
+  # Switch the part of the working copy
+  svntest.actions.run_and_verify_switch(wc_dir, G_path, H_url,
+                                        None, None, None)
+
+  iota_path = wc_dir + '/iota'
+  iota_cp_path = wc_dir + '/A/D/G/iota-copy'
+
+  # Copy iota into the switched dir
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     iota_path, iota_cp_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/D/G/iota-copy'           : Item(contents="This is the file 'iota'.\n",
+                                       props = { SVN_PROP_MERGEINFO : '' }),
+
+    'A/D/G/chi'                 : Item(contents="This is the file 'chi'.\n"),
+    'A/D/G/omega'               : Item(contents="This is the file 'omega'.\n"),
+    'A/D/G/psi'                 : Item(contents="This is the file 'psi'.\n"),
+
+    })
+
+  expected_disk.remove('A/D/G/pi')
+  expected_disk.remove('A/D/G/rho')
+  expected_disk.remove('A/D/G/tau')
+
+  svntest.actions.verify_disk(wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/D/G/iota-copy'           : Item(status='A ', copied='+', wc_rev='-'),
+    'A/D/G/chi'                 : Item(status='  ', wc_rev=1),
+    'A/D/G/omega'               : Item(status='  ', wc_rev=1),
+    'A/D/G/psi'                 : Item(status='  ', wc_rev=1),
+    })
+  expected_status.tweak('A/D/G', switched = 'S')
+  expected_status.remove('A/D/G/pi')
+  expected_status.remove('A/D/G/rho')
+  expected_status.remove('A/D/G/tau')
+
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+#----------------------------------------------------------------------
+# Test that empty mergeinfo isn't created when file is copied into
+# nested WC
+
+def non_local_copy_into_nested(sbox):
+  "'mergeinfo NON-affecting' copy file into nested wc"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  nested_wc_dir = sbox.wc_dir + '/A/X'
+
+  # Create nested working copy
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'co',
+                                     sbox.repo_url, nested_wc_dir)
+
+  iota_path = wc_dir + '/iota'
+  iota_cp_path = wc_dir + '/A/X/A/iota-copy'
+
+  # Copy iota file into the nested WC
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     iota_path, iota_cp_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/iota-copy'               : Item(contents="This is the file 'iota'.\n"),
+    })
+
+  svntest.actions.verify_disk(nested_wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(nested_wc_dir, 1)
+  expected_status.add({
+    'A/iota-copy'           : Item(status='A ', copied='+', wc_rev='-'),
+    })
+
+  svntest.actions.run_and_verify_status(nested_wc_dir, expected_status)
+
+#----------------------------------------------------------------------
+# Test that empty mergeinfo isn't created when file is copied within
+# mixed revision working copy and there is no of any explicit mergeinfos
+# at all
+
+def no_empty_mergeinfo_in_mixed_revision_wc(sbox):
+  "copy in the mixed revision WC"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  iota_path = wc_dir + '/iota'
+  iota_cp_path = wc_dir + '/A/D/H/iota-copy'
+
+  chi_path = wc_dir + '/A/D/H/chi'
+
+  # Modify chi
+  svntest.main.file_append(iota_path,
+                          "Changed.\n")
+
+  # Commit changes in iota. Working copy becomes mixed revision WC.
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ci',  '-m', 'log msg',
+                                     wc_dir)
+  # Copy iota path in the WC
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     iota_path, iota_cp_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/D/H/iota-copy'  : Item(contents="This is the file 'iota'.\nChanged.\n"),
+    })
+
+  expected_disk.tweak(
+      'iota', contents="This is the file 'iota'.\nChanged.\n")
+
+  svntest.actions.verify_disk(wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/D/H/iota-copy'           : Item(status='A ', copied='+', wc_rev='-'),
+    })
+
+  expected_status.tweak('iota', wc_rev='2')
+
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+#----------------------------------------------------------------------
+# Test that explicit mergeinfo is created when src has explicit mergeinfo
+
+def copy_src_explicit_mergeinfo(sbox):
+  "copy explicit mergeinfo set on src"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  E_path  = wc_dir + '/A/B/E'
+  X_path = wc_dir + '/A/B/X'
+
+  branch_change_and_merge_back(sbox, wc_dir)
+
+  # Copy alpha in the working copy
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     E_path, X_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/B/E2/alpha'      : Item(
+               contents="This is the file 'alpha'.\nChanged in the branch.\n"),
+    'A/B/E2/beta'       : Item(contents="This is the file 'beta'.\n"),
+    'A/B/X'             : Item(props = { SVN_PROP_MERGEINFO : '/A/B/E2:2-3' }),
+    'A/B/X/alpha'       : Item(
+               contents="This is the file 'alpha'.\nChanged in the branch.\n"),
+    'A/B/X/beta'        : Item(contents="This is the file 'beta'.\n"),
+    })
+
+  expected_disk.tweak(
+      'A/B/E/alpha',
+       contents="This is the file 'alpha'.\nChanged in the branch.\n")
+  expected_disk.tweak(
+      'A/B/E', props = { SVN_PROP_MERGEINFO : '/A/B/E2:2-3' })
+
+  svntest.actions.verify_disk(wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 4)
+  expected_status.add({
+    'A/B/X'                     : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/X/alpha'               : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/X/beta'                : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/E2'                    : Item(status='  ', wc_rev=4),
+    'A/B/E2/alpha'              : Item(status='  ', wc_rev=4),
+    'A/B/E2/beta'               : Item(status='  ', wc_rev=4),
+    })
+
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+#----------------------------------------------------------------------
+# Test that empty explicit mergeinfo is created when added src file is
+# copied to a tree with different mergeinfo
+
+def copy_added_file_with_empty_explicit_mergeinfo(sbox):
+  "copy added file with explicit empty mergeinfo"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  dzetta_path = wc_dir + '/dzetta'
+  dzetta_copy_path = wc_dir + '/A/B/E/dzetta-copy'
+
+  branch_change_and_merge_back(sbox, wc_dir)
+
+  # Create dzetta file and put it under Subversion
+  svntest.main.file_append(dzetta_path, "This is added dzetta file.\n")
+
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'add', dzetta_path)
+
+  # Copy dzetta to the tree with different mergeinfo
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp',
+                                     dzetta_path, dzetta_copy_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'dzetta'              : Item(contents="This is added dzetta file.\n"),
+    'A/B/E/dzetta-copy'   : Item(contents="This is added dzetta file.\n",
+                                 props = { SVN_PROP_MERGEINFO : ''} ),
+    'A/B/E2/alpha'        : Item(
+               contents="This is the file 'alpha'.\nChanged in the branch.\n"),
+    'A/B/E2/beta'               : Item(contents="This is the file 'beta'.\n"),
+    })
+
+  expected_disk.tweak(
+      'A/B/E/alpha',
+      contents="This is the file 'alpha'.\nChanged in the branch.\n")
+  expected_disk.tweak(
+      'A/B/E', props = { SVN_PROP_MERGEINFO : '/A/B/E2:2-3' })
+
+  svntest.actions.verify_disk(wc_dir, expected_disk, check_props = True)
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 4)
+  expected_status.add({
+    'dzetta'                    : Item(status='A ', wc_rev='0'),
+    'A/B/E/dzetta-copy'         : Item(status='A ', wc_rev='0'),
+    'A/B/E2'                    : Item(status='  ', wc_rev=4),
+    'A/B/E2/alpha'              : Item(status='  ', wc_rev=4),
+    'A/B/E2/beta'               : Item(status='  ', wc_rev=4),
+    })
+
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
 ########################################################################
 # Run the tests
 
@@ -4067,7 +4550,17 @@
               copy_into_absent_dir,
               # svn_path_is_ancestor() is broken; see r33211.
               XFail(find_copyfrom_information_upstairs,
-                    svntest.main.is_os_windows)
+                    svntest.main.is_os_windows),
+              no_empty_mergeinfo_on_local_copy_file,
+              no_empty_mergeinfo_on_local_copy_dir,
+              local_copy_with_explicit_mergeinfo,
+              local_mergeinfo_non_affecting_copy,
+              non_local_copy_between_wc,
+              non_local_copy_into_switched,
+              non_local_copy_into_nested,
+              no_empty_mergeinfo_in_mixed_revision_wc,
+              copy_src_explicit_mergeinfo,
+              copy_added_file_with_empty_explicit_mergeinfo,
              ]
 
 if __name__ == '__main__':
