Checkout
 

giovannibajo in subversion

Fix an extra whitespace.

* svnmerge.py (launchsvn): Remove extra whitespace.

Rewrite the constructor of RevisionLog to use the new SvnLogParser

(parsing the XML), instead of screenscaping the output with regular

expressions.

Also, fix a typo in a codepath which is currently unused.

* svnmerge.py

(RevisionLog.__init__): Use SvnLogParser to parse the log.

analyze_source_revs() gets the latest revision of the *branch*

repository, then proceeds to use that value against the *source*

repository; it should get the latest revision of the *source*.

This of course is not a bug in the common scenario of merges

within the same repository, but it is blocking our way to

inter-repository merges.

* svnmerge.py

(analyze_source_revs): Get latest rev of source_url.

Patch by: Dustin J. Mitchell <dustin@zmanda.com>

Review by: Giovanni Bajo <rasky@develer.com>

Improve performance by avoiding redundant server round-trips when

using -S.

This patch introduces an internal cache in get_repo_root() which

allows the function to automatically detect if a given URL is part

of an already analyzed repository without doing a server roundtrip.

Since I was at it, I also removed a useless global declaration for

the other similar cache used by get_svninfo().

* svnmerge.py

(get_svninfo): Remove global declaration.

(get_repo_root): Update and use the new _cache_reporoot,

storing repository roots that were already found.

* svnmerge_test.py

(TestCase_SvnMerge.svnmerge2): empty the new cache.

Misc fixes: restore Python 2.0 compatibility and wrap text into 80 columns.

svnmerge_test.py

(TestCase_TestRepo.command_dict): use dictionary literal (for 2.0)

(TestCase_TestRepo.testUninit, TestCase_TestRepo.testUninitForce,

TestCase_TestRepo.testInitScenarios,

TestCase_TestRepo.testBidirectionalMerges,

TestCase_TestRepo.testBidirectionalMergesMultiBranch,

testMergeWithPotentialPropertyConflict): Avoid interspersed arguments,

they are not supported by getopt in 2.0). Avoid assertTrue/assertFalse,

they did not exist in 2.0.

svnmerge.py

(SvnLogParser): Add docstring.

(SvnLogParser.SvnLogRevision, SvnLogParser.SvnLogRevision.SvnLogPath):

Rename self._node into self.n. Avoid using getAttributeOrNone(), which

relied on hasAttribute() not present in 2.0. For optional attributes,

use a try/except block.

(SvnLogParser.SvnLogRevision.paths): Use list comprehension.

(getAttributeOrNone): Remove.

* STATUS: add +0 for backport of fix for Issue 2689
Add the uninit command, which removes merge tracking information for a given

head URL, including blocked revision information. This is especially useful

if multiple heads are being tracked -- without uninit, this situation requires

the new property value to be manually set by the user via svn propset.

* svnmerge.py: Added uninit to command table.

(action_uninit): New method for uninitialization of merge tracking info.

* svnmerge_test.py

(TestCase_TestRepo.testUninit): New test case, checking that uninit works.

(TestCase_TestRepo.testUninitForce): New test case.

(TestCase_TestRepo.getproperty): Prevent array index errors when

retrieving a property with no value.

(TestCase_TestRepo.getBlockedProperty): New method to get the value

of the svnmerge blocked property.

Patch by: Raman Gupta <rocketraman@fastmail.fm>

Review by: Daniel Rall <dlr@collab.net>

Madan U Sreenivasan <madan@collab.net>

Giovanni Bajo <rasky@develer.com>

As discussed on the svnmerge mailing list, there is no actual reason to block

a merge just because there are pending updates on the repository. A merge

does not do any commit, it just modifies the working copy. And it is normal

to perform updates before committing. Also, the check is actually meaningless,

because by the time the merge is finished, it might well be that there are

new pending updates on the repository.

It makes sense, instead, to make sure the working copy is clean, so not to

mistakenly commit unrelated modifies together with a merge. This check can

be disabled with --force.

A nice side effect of this patch is that it speeds out merge operations as

one less server/client round-trip is required.

* contrib/client-side/svnmerge.py:

(check_dir_clean): Do not check for pending updates.

After r19630, when no head is specified and multiple heads are found,

it is not necessary to print the full URLs in the error message: in fact,

the repository relative path (and any unambigous substring) can be specified.

* contrib/client-side/svnmerge.py:

(get_default_head): Do not print the full URL, since the repository-relative

path is accepted by the --head option.

Accept unambiguous substrings of a repository-relative path as head arguments.

When merging across multiple branches, it is often necessary to specify on

which of the multiple heads the operation must be performed (through

-S/--head). Until today, this parameter accepted either a working copy

directory or a full URL. This is unfortunate since the user really only wants

to specify one of a few possible heads.

This patch makes svnmerge accepts unambiguous substrings (of any length) of

one of the repository-relative paths recorded as head. For instance, it is

now possible to say: "svnmerge.py avail -S trunk".

Notice that this does not help in the case of "svnmerge.py init", because

you will probably need to specify a new head (as a full URL), not a previously

initialized one.

* contrib/client-side/svnmerge.py:

(main): Check if the head argument is a unambiguous substring of one the

paths in the branch properties.

(command_opts, OptionArg("-S")): modify the help string to specify that

a substring is allowed.

* contrib/client-side/svnmerge_test.py:

(TestCase_TestRepo.testBidirectionalMergesMultiBranch): Use substrings

for head parameters so to check the new feature.

Document svnmerge.py requisites (SVN client/server 1.1).

* contrib/client-side/svnmerge.py:

Document requisites in top comment.

Fix a bug with XML regexp parsing: the path information interpolated within

the regular expression must be correctly escaped.

* contrib/client-side/svnmerge.py:

(get_copyfrom): Use re.escape to interpolate the path within the regular

expression.

Speedup common paths in svnmerge.py using the Repository Root information

returned by "svn info" even on local paths since SVN 1.3.

svnmerge.py needs to compute the repository root several times. Right now

the flow of code is very contorted, and I plan to clean it up so that it

computes it once and reuse it everywhere (instead of relying on memoization).

Anyway, this path cleans up many paths of code so to request the repository

root through a local path when possible, so that it can be computed without

remote access.

* contrib/client-side/svnmerge.py:

(get_repo_root): Instead of converting immediately to URL, try running

"svn info" on a local directory before, since it is faster.

(url_to_rlpath): Rename to...

(target_to_rlpath): New function. Accepts both an URL and a local directory,

and convert it to repository-relative path. If a local directory is

provided (and the client is at least 1.3), this can be done without any

remote access.

(RevisionLog.__init__, get_copyfrom, get_default_head, analyze_head_revs,

main): Use target_to_rlpath, and provide a local directory instead of

an URL when available.

Fix computation of local URL (file://) from local path, under Windows. Given an

absolute path, it is not sufficient to replace backslashes with forward

slashes, as an absolute path under Windows does not start with any slash, but

rather the driver latter.

* contrib/client-side/svnmerge_test.py:

(abspath_to_url): New function.

(TestCase_TestRepo.setUp): Use it.

Fixed a problem with the last indent patch to remove an extra

blank line after embedded log messages.

Patch by: Raman Gupta <rocketraman@fastmail.fm>

* contrib/client-side/svnmerge.py

(construct_merged_log_message):

Removed an extra newline being appended to log messages.

Patch by: Alan Barrett <apb@cequrux.com>

Raman Gupta <rocketraman@fastmail.fm>

Reviewed by: Giovanni Bajo <rasky@develer.com>

* contrib/client-side/svnmerge.py

(prefix_lines):

New method to take a string and prepend each line of the string

with a specified string. Lines are delimited by newline

characters, and the entire string is asserted to be newline

terminated.

(construct_merged_log_message):

Added indentation for each commit message. Added check for empty

log messages, which should never happen but doesn't hurt.

* contrib/client-side/svnmerge_test.py

(TestCase_PrefixLines.test_basic):

New test for the prefix_lines functionality.

The global opts dictionary is a relic of the old svnmerge shell script. I'd

like it to go as it is bug-prone. For instance, analyze_revs should not use

opts["bidirectional"] as an implicit parameter, but just declare an explicit

additional parameter if it needs it.

* contrib/client-side/svnmerge.py:

(analyze_revs): Do not use opts["bidirectional"] anymore. Accepts a new

"find_reflected" parameter.

(analyze_head_revs): Forward keyword arguments to analyze_revs.

(action_avail, action_merge, action_block): Update accordingly.

In avail and merge, trim the range of search for phantom revisions with the

command-line specified revision list. Before this patch, svnmerge was always

trying to look for phantom revisions in head up to HEAD (last revision in

repository), which was too much and slowed down simple operations (like

merging a single revision) too much.

* contrib/client-side/svnmerge.py:

(analyze_revs): Avoid calling "svn log" at all if the range is empty.

(analyze_head_revs): Trim range of "svn log" to range specified on the

command line.

* contrib/client-side/svnmerge_test.py:

(TestCase_TestRepo.testTrimmedAvailMerge): New test.

Fix a problem when parsing the output of "svn status" in a working copy

with external directories: there are blank lines in the output which were

confusing the code.

* contrib/client-side/svnmerge_test.py:

(check_dir_clean): Robustify for blank lines.

Another small batch of compatibility fixes: after this, svnmerge is finally

fully compatible with Python 2.0.

* contrib/client-side/svnmerge_test.py:

(_run_propset): Use open, not file

(CommandOpts._fancy_getopt, CommandOpts.parse): Adjust for Python before 2.3

which didn't have gnu_getopt.

Import a new testsuite which does a complete check of svnmerge

functionalities. The previous testsuite was just unittesting small pieces of

code, while this new testsuite setups a test repository, actually performs

svnmerge operations in it, and check the results.

Moreover, the testsuite is now Python 2.0-friendly.

* contrib/client-side/svnmerge_test.py:

(True,False): Define for compatibility if not defined already.

(TestCase_kwextract.test_failure): Test also without space at the end of

the string.

(TestCase_RevisionList.test_iter): Disable if iter is not available (pre

2.2).

(TestCase_SvnMerge): New base classes for tests which need to call svnmerge.

Also provide support for regexp matching on the generated output.

(TestCase_CommandLineOptions.test_help_commands): Test more forms of the

help.

(TestCase_CommandLineOptions.test_version): Make it work on pre-2.2.

(TestCase.testOptionOrder): New test, verify that options can be intermixed

with positional arguments in any order.

(temp_path, rmtree, template_path): New support functions.

(TestCase_TestRepo): New complete testsuite, which setups a test repository

and use it to test real svnmerge execution. The generated output is then

tested to verify the functionalities.

Fix the regular expression used to parse the XML produced by "svn log" to

extract the copy-from information: it was too broad and was allowing spurious

matches (eg. when used on the GCC repository).

* contrib/client-side/svnmerge.py:

(get_copyfrom): Make the regexp more strict.

Allow command line options to be specified in any order, even before the

command name. Eg. we now allow "svnmerge -r123 merge" which was forbidden

before.

* contrib/client-side/svnmerge.py:

(CommandOpts._fancy_getopt): Split out functionalities into...

(CommandOpts._compute_flags): New.

(CommandOpts._extract_command): New.

(CommandOpts.parse): First extract command name, then validate the options.

Rename "opts" to "state" for improved readability.

Miscellaneous compatibility fixes. Allow running svnmerge.main multiple

times with a single import (will be useful for the testsuite).

* contrib/client-side/svnmerge.py:

(CommandOpts.__init__): Duplicate external data structures.

(CommandOpts.__init__, CommandOpts._command): Avoid using 'key in dict'.

Set properties using "-F" and a temporary file to avoid hitting command

line length limits.

* contrib/client-side/svnmerge.py:

(_run_propset): New.

(set_merge_props, set_blocked_revs): Use _run_propset.

Improve tree's copy-from revision extraction from "svn log --xml" output.

Avoid being fooled by copy-from information in single files.

* contrib/client-side/svnmerge.py:

(get_copyfrom): Improve error-recovery.

Do not be fooled by external directories in the tree.

* contrib/client-side/svnmerge.py:

(check_dir_clean): Improve logic to find if the tree has local modifies.

When trying to get the width of the console, also try parsing the output

of "stty -a" which usually contains this information.

* contrib/client-side/svnmerge.py:

(console_width): Try parsing 'stty -a' output.

Miscellanous fixes: word-wrap lines at 80th column, try and achieve

compatibility with older Python versions (2.0+).

* contrib/client-side/svnmerge.py:

(console_width, get_default_head, action_avail, action_merge,

CommandOpts.print_small_help, global_opts, common_opts, main): Word-wrap.

(SRCREV, SRCDATE): Rename to...

(__revision__, __date__): New.

(action_avail): Avoid printing an empty list of revisions in verbose mode.

(RevisionList.__nonzero__): Avoid 'bool'.

(RevisionList.sorted): New.

(RevisionList.normalized, RevisionList.__iter__): Use new sorted method.

(construct_merged_log_message): Avoid using '__iter__' method.

(get_svn_info): Avoid 'key in dict'.

(OptBase.__init__, Option.__init__, OptionArg.__init__): Avoid 'key in

dict' and 'dict.pop'.

(CommandOpts.__init__): Avoid 'types.StringTypes'.

(CommandOpts.print_command_help): Avoid nested scopes.

Nominate r17139