[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] Re: issue #785 (was Re: wanted: nibble-sized coding task)

From: Brian Denny <brian_at_briandenny.net>
Date: 2003-03-11 16:45:29 CET

On Mon, Mar 10, 2003 at 12:16:31PM -0800, Ben Collins-Sussman wrote:
>
> Here's what we need to commit this patch:
>
> * expand the test to try 'svn merge -r X:Y wc-file'
>
> * add new documentation to 'svn help merge' (in main.c)
>
> * add new documentation to chapters 3 and 8 in the Book.
>
> Can you add that stuff to your patch?

here it is. note that i made a couple changes to the test case in
addition to your request - i renamed it so that it would be less
confusing next to the new 'merge_catches_nonexistent_target'; i removed
an unneeded change-commit cycle; and i verified the contents of the
merged file.

documentation-wise -- it's kind of a hard 'special case' to document
completely and correctly without being extremely verbose. i won't be
offended if you want to edit my explanations.

-brian

 
Log:

  Resolves issue #785:

  * merge-cmd.c
    (svn_cl__merge): If no target path was specified, try to infer it
    from the source path(s).

  * main.c
    (svn_cl__cmd_table): Document the new use case in the output of
    'svn help merge'.

  * merge_tests.py
    (merge_with_implicit_target): New test function. Merges a file,
    specifying a revision range and source file/URL but no target path.

  * ch04.xml
    Explain the conditions under which 'svn merge' can infer a target
    path.
    
  * ch08.xml
    Document the new use case in the reference section for 'svn merge'.
    Add an example.
    

Index: subversion/clients/cmdline/merge-cmd.c
===================================================================
--- subversion/clients/cmdline/merge-cmd.c (revision 5272)
+++ subversion/clients/cmdline/merge-cmd.c (working copy)
@@ -126,6 +126,25 @@
         targetpath = "";
     }
 
+ /* If no targetpath was specified, see if we can infer it from the
+ sourcepaths. */
+ if (! strcmp (targetpath, ""))
+ {
+ char *sp1_basename, *sp2_basename;
+ sp1_basename = svn_path_basename (sourcepath1, pool);
+ sp2_basename = svn_path_basename (sourcepath2, pool);
+
+ if (! strcmp (sp1_basename, sp2_basename))
+ {
+ svn_node_kind_t kind;
+ SVN_ERR (svn_io_check_path (sp1_basename, &kind, pool));
+ if (kind == svn_node_file)
+ {
+ targetpath = sp1_basename;
+ }
+ }
+ }
+
   if (opt_state->start_revision.kind == svn_opt_revision_unspecified)
     opt_state->start_revision.kind = svn_opt_revision_head;
   if (opt_state->end_revision.kind == svn_opt_revision_unspecified)
Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c (revision 5272)
+++ subversion/clients/cmdline/main.c (working copy)
@@ -283,8 +283,13 @@
     " 2. In the second form TARGET can be an URL, or it can be a working copy\n"
     " path in which case the corresponding URL is used. This URL, at\n"
     " revisions N and M, defines the two sources to be compared.\n\n"
- " PATH is the working copy path that will receive the changes.\n"
- " If omitted, a default value of '.' is assumed.\n\n",
+ " PATH is the working copy path that will receive the changes. PATH may\n"
+ " be omitted if:\n\n"
+ " (a) the TARGET (or URLs) refer to a directory; then PATH is taken\n"
+ " to be the current working directory.\n\n"
+ " (b) there is a file in the current working directory whose name\n"
+ " is the same as the basename of TARGET (or both URLs); then\n"
+ " PATH is taken to be this file.\n",
     {'r', 'N', 'q', svn_cl__force_opt, svn_cl__dry_run_opt,
      svn_cl__merge_cmd_opt, SVN_CL__AUTH_OPTIONS} },
   
Index: subversion/tests/clients/cmdline/merge_tests.py
===================================================================
--- subversion/tests/clients/cmdline/merge_tests.py (revision 5272)
+++ subversion/tests/clients/cmdline/merge_tests.py (working copy)
@@ -994,6 +994,81 @@
 
 #----------------------------------------------------------------------
 
+def merge_with_implicit_target (sbox):
+ "merging a file, with no explicitly-specified target path (issue #785)"
+
+ if sbox.build():
+ return 1
+
+ wc_dir = sbox.wc_dir
+
+ # Change mu for revision 2
+ mu_path = os.path.join(wc_dir, 'A', 'mu')
+ orig_mu_text = svntest.tree.get_text(mu_path);
+ added_mu_text = ""
+ for x in range(2,11):
+ added_mu_text = added_mu_text + '\nThis is line ' + `x` + ' in mu'
+ added_mu_text += "\n"
+ svntest.main.file_append(mu_path, added_mu_text)
+
+ # Create expected output tree for initial commit
+ expected_output = wc.State(wc_dir, {
+ 'A/mu' : Item(verb='Sending'),
+ })
+
+ # Create expected status tree; all local revisions should be at 1,
+ # but mu should be at revision 2.
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+ expected_status.tweak(wc_rev=1)
+ expected_status.tweak('A/mu', wc_rev=2)
+
+ # Initial commit.
+ if svntest.actions.run_and_verify_commit (wc_dir,
+ expected_output,
+ expected_status,
+ None,
+ None, None, None, None,
+ wc_dir):
+ return 1
+
+ # Make the "other" working copy
+ other_wc = wc_dir + '.other'
+ svntest.actions.duplicate_dir(wc_dir, other_wc)
+
+ # Try the merge without an explicit target; it should succeed.
+ # Can't use run_and_verify_merge cuz it expects a directory argument.
+ mu_url = os.path.join(svntest.main.current_repo_url, 'A', 'mu')
+ was_cwd = os.getcwd()
+ try:
+ os.chdir(os.path.join(other_wc, 'A'))
+
+ # merge using URL for sourcepath
+ out, err = svntest.main.run_svn(0, 'merge', '-r', '2:1',
+ mu_url)
+ if err:
+ print err
+ return 1
+
+ # sanity-check resulting file
+ if (svntest.tree.get_text('mu') != orig_mu_text):
+ return 1
+
+ # merge using filename for sourcepath
+ out, err = svntest.main.run_svn(0, 'merge', '-r', '1:2',
+ 'mu')
+ if err:
+ print err
+ return 1
+
+ # sanity-check resulting file
+ if (svntest.tree.get_text('mu') != orig_mu_text + added_mu_text):
+ return 1
+
+ finally:
+ os.chdir(was_cwd)
+
+#----------------------------------------------------------------------
+
 ########################################################################
 # Run the tests
 
@@ -1004,6 +1079,7 @@
               add_with_history,
               delete_file_and_dir,
               simple_property_merges,
+ merge_with_implicit_target,
               merge_catches_nonexistent_target,
               # merge_one_file, # See issue #1150.
               # property_merges_galore, # Would be nice to have this.
Index: doc/book/book/ch04.xml
===================================================================
--- doc/book/book/ch04.xml (revision 5272)
+++ doc/book/book/ch04.xml (working copy)
@@ -573,8 +573,30 @@
       help</command>. For example, <command>svn merge</command>
       requires a working-copy path as a target, i.e. a place where it
       should apply the tree-changes. If the target isn't specified,
- it assumes you want the changes applied to the current working
- directory. If you want changes applied somewhere else, you'll
+ it will try to assume that you are trying to perform one of the
+ following common operations:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>You want to merge changes all the changes in a
+ directory into your current working directory.</para>
+ </listitem>
+ <listitem>
+ <para>You want to merge the changes in a specific file into
+ a file by the same name which exists in your current working
+ directory.</para>
+ </listitem>
+ </orderedlist>
+
+ <para>If you are merging a directory and haven't specified a
+ target path, <command>svn merge</command> assumes the first
+ case above and tries to apply the changes into your current
+ directory. If you are merging a file, and that file (or a file
+ by the same name) exists in your current working directory,
+ <command>svn merge</command> assumes the second case and tries
+ to apply the changes to the local file.</para>
+
+ <para>If you want changes applied somewhere else, you'll
       need to say so:</para>
 
 <screen>
Index: doc/book/book/ch08.xml
===================================================================
--- doc/book/book/ch08.xml (revision 5272)
+++ doc/book/book/ch08.xml (working copy)
@@ -1821,8 +1821,22 @@
               two sources to be compared.</para>
 
             <para>PATH is the working copy path that will receive the
- changes. If omitted, a default value of '.' is
- assumed.</para>
+ changes. PATH may be omitted if:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>The TARGET (or URLs) refer to a directory;
+ then PATH is taken to be the current working
+ directory.</para>
+ </listitem>
+
+ <listitem>
+ <para>There is a file in the current working directory
+ whose name is the same as the basename of TARGET
+ (or both URLs); then PATH is taken to be this file.</para>
+ </listitem>
+ </orderedlist>
+
           </refsect1>
           <refsect1>
             <title>Alternate names</title>
@@ -1879,6 +1893,14 @@
 ...
             </screen>
             
+ <para>To merge changes to a single file:</para>
+
+ <screen>
+$ cd myproj
+$ svn merge -r 30:31 thhgttg.txt
+U thhgttg.txt
+ </screen>
+
           </refsect1>
         </refentry>
 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Mar 11 16:50:35 2003

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.