You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2012/03/06 18:50:31 UTC
svn commit: r1297604 [12/12] - in
/subversion/branches/reintegrate-keep-alive: ./ build/ build/ac-macros/
build/generator/ build/generator/templates/ build/win32/ notes/
notes/api-errata/1.7/ subversion/bindings/javahl/native/
subversion/bindings/javah...
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/svntest/verify.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/svntest/verify.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/svntest/verify.py (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/svntest/verify.py Tue Mar 6 17:50:23 2012
@@ -25,7 +25,8 @@
######################################################################
import re, sys
-from difflib import unified_diff
+from difflib import unified_diff, ndiff
+import pprint
import svntest
@@ -68,6 +69,10 @@ class SVNIncorrectDatatype(SVNUnexpected
run_and_verify_* API"""
pass
+class SVNDumpParseError(svntest.Failure):
+ """Exception raised if parsing a dump file fails"""
+ pass
+
######################################################################
# Comparison of expected vs. actual output
@@ -397,3 +402,193 @@ def verify_exit_code(message, actual, ex
display_lines(message, "Exit Code",
str(expected) + '\n', str(actual) + '\n')
raise raisable
+
+# A simple dump file parser. While sufficient for the current
+# testsuite it doesn't cope with all valid dump files.
+class DumpParser:
+ def __init__(self, lines):
+ self.current = 0
+ self.lines = lines
+ self.parsed = {}
+
+ def parse_line(self, regex, required=True):
+ m = re.match(regex, self.lines[self.current])
+ if not m:
+ if required:
+ raise SVNDumpParseError("expected '%s' at line %d\n%s"
+ % (regex, self.current,
+ self.lines[self.current]))
+ else:
+ return None
+ self.current += 1
+ return m.group(1)
+
+ def parse_blank(self, required=True):
+ if self.lines[self.current] != '\n': # Works on Windows
+ if required:
+ raise SVNDumpParseError("expected blank at line %d\n%s"
+ % (self.current, self.lines[self.current]))
+ else:
+ return False
+ self.current += 1
+ return True
+
+ def parse_format(self):
+ return self.parse_line('SVN-fs-dump-format-version: ([0-9]+)$')
+
+ def parse_uuid(self):
+ return self.parse_line('UUID: ([0-9a-z-]+)$')
+
+ def parse_revision(self):
+ return self.parse_line('Revision-number: ([0-9]+)$')
+
+ def parse_prop_length(self, required=True):
+ return self.parse_line('Prop-content-length: ([0-9]+)$', required)
+
+ def parse_content_length(self, required=True):
+ return self.parse_line('Content-length: ([0-9]+)$', required)
+
+ def parse_path(self):
+ path = self.parse_line('Node-path: (.+)$', required=False)
+ if not path and self.lines[self.current] == 'Node-path: \n':
+ self.current += 1
+ path = ''
+ return path
+
+ def parse_kind(self):
+ return self.parse_line('Node-kind: (.+)$', required=False)
+
+ def parse_action(self):
+ return self.parse_line('Node-action: ([0-9a-z-]+)$')
+
+ def parse_copyfrom_rev(self):
+ return self.parse_line('Node-copyfrom-rev: ([0-9]+)$', required=False)
+
+ def parse_copyfrom_path(self):
+ path = self.parse_line('Node-copyfrom-path: (.+)$', required=False)
+ if not path and self.lines[self.current] == 'Node-copyfrom-path: \n':
+ self.current += 1
+ path = ''
+ return path
+
+ def parse_copy_md5(self):
+ return self.parse_line('Text-copy-source-md5: ([0-9a-z]+)$', required=False)
+
+ def parse_copy_sha1(self):
+ return self.parse_line('Text-copy-source-sha1: ([0-9a-z]+)$', required=False)
+
+ def parse_text_md5(self):
+ return self.parse_line('Text-content-md5: ([0-9a-z]+)$', required=False)
+
+ def parse_text_sha1(self):
+ return self.parse_line('Text-content-sha1: ([0-9a-z]+)$', required=False)
+
+ def parse_text_length(self):
+ return self.parse_line('Text-content-length: ([0-9]+)$', required=False)
+
+ # One day we may need to parse individual property name/values into a map
+ def get_props(self):
+ props = []
+ while not re.match('PROPS-END$', self.lines[self.current]):
+ props.append(self.lines[self.current])
+ self.current += 1
+ self.current += 1
+ return props
+
+ def get_content(self, length):
+ content = ''
+ while len(content) < length:
+ content += self.lines[self.current]
+ self.current += 1
+ if len(content) == length + 1:
+ content = content[:-1]
+ elif len(content) != length:
+ raise SVNDumpParseError("content length expected %d actual %d at line %d"
+ % (length, len(content), self.current))
+ return content
+
+ def parse_one_node(self):
+ node = {}
+ node['kind'] = self.parse_kind()
+ action = self.parse_action()
+ node['copyfrom_rev'] = self.parse_copyfrom_rev()
+ node['copyfrom_path'] = self.parse_copyfrom_path()
+ node['copy_md5'] = self.parse_copy_md5()
+ node['copy_sha1'] = self.parse_copy_sha1()
+ node['prop_length'] = self.parse_prop_length(required=False)
+ node['text_length'] = self.parse_text_length()
+ node['text_md5'] = self.parse_text_md5()
+ node['text_sha1'] = self.parse_text_sha1()
+ node['content_length'] = self.parse_content_length(required=False)
+ self.parse_blank()
+ if node['prop_length']:
+ node['props'] = self.get_props()
+ if node['text_length']:
+ node['content'] = self.get_content(int(node['text_length']))
+ # Hard to determine how may blanks is 'correct' (a delete that is
+ # followed by an add that is a replace and a copy has one fewer
+ # than expected but that can't be predicted until seeing the add)
+ # so allow arbitrary number
+ blanks = 0
+ while self.current < len(self.lines) and self.parse_blank(required=False):
+ blanks += 1
+ node['blanks'] = blanks
+ return action, node
+
+ def parse_all_nodes(self):
+ nodes = {}
+ while True:
+ if self.current >= len(self.lines):
+ break
+ path = self.parse_path()
+ if not path and not path is '':
+ break
+ if not nodes.get(path):
+ nodes[path] = {}
+ action, node = self.parse_one_node()
+ if nodes[path].get(action):
+ raise SVNDumpParseError("duplicate action '%s' for node '%s' at line %d"
+ % (action, path, self.current))
+ nodes[path][action] = node
+ return nodes
+
+ def parse_one_revision(self):
+ revision = {}
+ number = self.parse_revision()
+ revision['prop_length'] = self.parse_prop_length()
+ revision['content_length'] = self.parse_content_length()
+ self.parse_blank()
+ revision['props'] = self.get_props()
+ self.parse_blank()
+ revision['nodes'] = self.parse_all_nodes()
+ return number, revision
+
+ def parse_all_revisions(self):
+ while self.current < len(self.lines):
+ number, revision = self.parse_one_revision()
+ if self.parsed.get(number):
+ raise SVNDumpParseError("duplicate revision %d at line %d"
+ % (number, self.current))
+ self.parsed[number] = revision
+
+ def parse(self):
+ self.parsed['format'] = self.parse_format()
+ self.parse_blank()
+ self.parsed['uuid'] = self.parse_uuid()
+ self.parse_blank()
+ self.parse_all_revisions()
+ return self.parsed
+
+def compare_dump_files(message, label, expected, actual):
+ """Parse two dump files EXPECTED and ACTUAL, both of which are lists
+ of lines as returned by run_and_verify_dump, and check that the same
+ revisions, nodes, properties, etc. are present in both dumps.
+ """
+
+ parsed_expected = DumpParser(expected).parse()
+ parsed_actual = DumpParser(actual).parse()
+
+ if parsed_expected != parsed_actual:
+ raise svntest.Failure('\n' + '\n'.join(ndiff(
+ pprint.pformat(parsed_expected).splitlines(),
+ pprint.pformat(parsed_actual).splitlines())))
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/switch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/switch_tests.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/switch_tests.py Tue Mar 6 17:50:23 2012
@@ -1532,33 +1532,29 @@ def mergeinfo_switch_elision(sbox):
beta_path = os.path.join(wc_dir, "A", "B", "E", "beta")
# Make branches A/B_COPY_1 and A/B_COPY_2
- svntest.actions.run_and_verify_svn(
- None,
- ["A " + os.path.join(wc_dir, "A", "B_COPY_1", "lambda") + "\n",
+ expected_stdout = verify.UnorderedOutput([
+ "A " + os.path.join(wc_dir, "A", "B_COPY_1", "lambda") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_1", "E") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "alpha") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "beta") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_1", "F") + "\n",
"Checked out revision 1.\n",
- "A " + B_COPY_1_path + "\n"],
- [],
- 'copy',
- sbox.repo_url + "/A/B",
- B_COPY_1_path)
-
- svntest.actions.run_and_verify_svn(
- None,
- ["A " + os.path.join(wc_dir, "A", "B_COPY_2", "lambda") + "\n",
+ "A " + B_COPY_1_path + "\n",
+ ])
+ svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+ sbox.repo_url + "/A/B", B_COPY_1_path)
+
+ expected_stdout = verify.UnorderedOutput([
+ "A " + os.path.join(wc_dir, "A", "B_COPY_2", "lambda") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_2", "E") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "alpha") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "beta") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_2", "F") + "\n",
"Checked out revision 1.\n",
- "A " + B_COPY_2_path + "\n"],
- [],
- 'copy',
- sbox.repo_url + "/A/B",
- B_COPY_2_path)
+ "A " + B_COPY_2_path + "\n",
+ ])
+ svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+ sbox.repo_url + "/A/B", B_COPY_2_path)
expected_output = svntest.wc.State(wc_dir, {
'A/B_COPY_1' : Item(verb='Adding'),
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/update_tests.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/update_tests.py Tue Mar 6 17:50:23 2012
@@ -307,6 +307,92 @@ def update_binary_file_2(sbox):
#----------------------------------------------------------------------
+@XFail()
+@Issue(4128)
+def update_binary_file_3(sbox):
+ "update locally modified file to equal versions"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Suck up contents of a test .png file.
+ theta_contents = open(os.path.join(sys.path[0], "theta.bin"), 'rb').read()
+
+ # Write our files contents out to disk, in A/theta.
+ theta_path = os.path.join(wc_dir, 'A', 'theta')
+ svntest.main.file_write(theta_path, theta_contents, 'wb')
+
+ # Now, `svn add' that file.
+ svntest.main.run_svn(None, 'add', theta_path)
+
+ # Created expected output tree for 'svn ci'
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/theta' : Item(verb='Adding (bin)'),
+ })
+
+ # Create expected status tree
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add({
+ 'A/theta' : Item(status=' ', wc_rev=2),
+ })
+
+ # Commit the new binary file, creating revision 2.
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None, wc_dir)
+
+ # Make some mods to the binary files.
+ svntest.main.file_append(theta_path, "foobar")
+ new_theta_contents = theta_contents + "foobar"
+
+ # Created expected output tree for 'svn ci'
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/theta' : Item(verb='Sending'),
+ })
+
+ # Create expected status tree
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add({
+ 'A/theta' : Item(status=' ', wc_rev=3),
+ })
+
+ # Commit modified working copy, creating revision 3.
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None, wc_dir)
+
+ # Now we locally modify the file back to the old version.
+ svntest.main.file_write(theta_path, theta_contents, 'wb')
+
+ # Create expected output tree for an update to rev 2.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/theta' : Item(status=' '),
+ })
+
+ # Create expected disk tree for the update
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'A/theta' : Item(theta_contents,
+ props={'svn:mime-type' : 'application/octet-stream'}),
+ })
+
+ # Create expected status tree for the update.
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+ expected_status.add({
+ 'A/theta' : Item(status=' ', wc_rev=2),
+ })
+
+ # Do an update from revision 2 and make sure that our binary file
+ # gets reverted to its original contents.
+ # This used to raise a conflict.
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output,
+ expected_disk,
+ expected_status,
+ None, None, None,
+ None, None, 1,
+ '-r', '2', wc_dir)
+
+#----------------------------------------------------------------------
+
def update_missing(sbox):
"update missing items (by name) in working copy"
@@ -1189,6 +1275,7 @@ def another_hudson_problem(sbox):
# Sigh, I can't get run_and_verify_update to work (but not because
# of issue 919 as far as I can tell)
+ expected_output = svntest.verify.UnorderedOutput(expected_output)
svntest.actions.run_and_verify_svn(None,
expected_output, [],
'up', G_path)
@@ -3142,19 +3229,17 @@ def mergeinfo_update_elision(sbox):
lambda_path = os.path.join(wc_dir, "A", "B", "lambda")
# Make a branch A/B_COPY
- svntest.actions.run_and_verify_svn(
- None,
- ["A " + os.path.join(wc_dir, "A", "B_COPY", "lambda") + "\n",
+ expected_stdout = verify.UnorderedOutput([
+ "A " + os.path.join(wc_dir, "A", "B_COPY", "lambda") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY", "E") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY", "E", "alpha") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY", "E", "beta") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY", "F") + "\n",
"Checked out revision 1.\n",
- "A " + B_COPY_path + "\n"],
- [],
- 'copy',
- sbox.repo_url + "/A/B",
- B_COPY_path)
+ "A " + B_COPY_path + "\n",
+ ])
+ svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+ sbox.repo_url + "/A/B", B_COPY_path)
expected_output = wc.State(wc_dir, {'A/B_COPY' : Item(verb='Adding')})
@@ -5682,6 +5767,7 @@ test_list = [ None,
update_moved_dir_file_add,
update_moved_dir_dir_add,
update_moved_dir_file_move,
+ update_binary_file_3,
]
if __name__ == '__main__':
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/upgrade_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/upgrade_tests.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/cmdline/upgrade_tests.py Tue Mar 6 17:50:23 2012
@@ -83,7 +83,7 @@ def replace_sbox_repo_with_tarfile(sbox,
if not dir:
dir = tar_filename.split('.')[0]
-
+
tarpath = os.path.join(os.path.dirname(sys.argv[0]), 'upgrade_tests_data',
tar_filename)
t = tarfile.open(tarpath, 'r:bz2')
@@ -1079,7 +1079,7 @@ def upgrade_with_missing_subdir(sbox):
svntest.main.safe_rmtree(sbox.ospath('A/B'))
# Now upgrade the working copy and expect a missing subdir
- expected_output = [
+ expected_output = svntest.verify.UnorderedOutput([
"Upgraded '%s'\n" % sbox.wc_dir,
"Upgraded '%s'\n" % sbox.ospath('A'),
"Skipped '%s'\n" % sbox.ospath('A/B'),
@@ -1087,7 +1087,7 @@ def upgrade_with_missing_subdir(sbox):
"Upgraded '%s'\n" % sbox.ospath('A/D'),
"Upgraded '%s'\n" % sbox.ospath('A/D/G'),
"Upgraded '%s'\n" % sbox.ospath('A/D/H'),
- ]
+ ])
svntest.actions.run_and_verify_svn(None, expected_output, [],
'upgrade', sbox.wc_dir)
@@ -1163,7 +1163,7 @@ def upgrade_file_externals(sbox):
svntest.actions.run_and_verify_svn(None, None, [], 'relocate',
'file:///tmp/repo', sbox.repo_url,
sbox.wc_dir)
-
+
expected_output = svntest.wc.State(sbox.wc_dir, {
'A/mu' : Item(status=' U'),
'A/B/lambda' : Item(status=' U'),
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_diff/diff-diff3-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_diff/diff-diff3-test.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_diff/diff-diff3-test.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_diff/diff-diff3-test.c Tue Mar 6 17:50:23 2012
@@ -2394,7 +2394,40 @@ merge_adjacent_changes(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+/* Issue #4133, '"diff -x -w" showing wrong change'.
+ The magic number used in this test, 1<<17, is
+ CHUNK_SIZE from ../../libsvn_diff/diff_file.c
+ */
+static svn_error_t *
+test_wrap(apr_pool_t *pool)
+{
+ char ldata[(1<<17) + 4+4+3+1];
+ char rdata[(1<<17) + 4+3+3+1];
+ svn_string_t left, right;
+ svn_diff_file_options_t *diff_opts = svn_diff_file_options_create(pool);
+ diff_opts->ignore_space = TRUE;
+ /* Two long lines. */
+ memset(ldata, '@', 1<<17);
+ memset(rdata, '@', 1<<17);
+ strcpy(&ldata[1<<17], "foo\n" "ba \n" "x \n");
+ strcpy(&rdata[1<<17], "foo\n" "ba\n" "x\t\n");
+
+ /* Cast them to svn_string_t. */
+ left.data = ldata;
+ right.data = rdata;
+ left.len = sizeof(ldata)-1;
+ right.len = sizeof(rdata)-1;
+
+ /* Diff them. Modulo whitespace, they are identical. */
+ {
+ svn_diff_t *diff;
+ SVN_ERR(svn_diff_mem_string_diff(&diff, &left, &right, diff_opts, pool));
+ SVN_TEST_ASSERT(FALSE == svn_diff_contains_diffs(diff));
+ }
+
+ return SVN_NO_ERROR;
+}
/* ========================================================================== */
@@ -2425,5 +2458,7 @@ struct svn_test_descriptor_t test_funcs[
"3-way merge with conflict styles"),
SVN_TEST_PASS2(test_diff4,
"4-way merge; see variance-adjusted-patching.html"),
+ SVN_TEST_XFAIL2(test_wrap,
+ "difference at the start of a 128KB window"),
SVN_TEST_NULL
};
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/checksum-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/checksum-test.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/checksum-test.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/checksum-test.c Tue Mar 6 17:50:23 2012
@@ -59,11 +59,34 @@ test_checksum_parse(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_checksum_empty(apr_pool_t *pool)
+{
+ svn_checksum_t *checksum;
+ char data = '\0';
+
+ checksum = svn_checksum_empty_checksum(svn_checksum_md5, pool);
+ SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+
+ checksum = svn_checksum_empty_checksum(svn_checksum_sha1, pool);
+ SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+
+ SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, &data, 0, pool));
+ SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+
+ SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1, &data, 0, pool));
+ SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+
+ return SVN_NO_ERROR;
+}
+
/* An array of all test functions */
struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_checksum_parse,
"checksum parse"),
+ SVN_TEST_PASS2(test_checksum_empty,
+ "checksum emptiness"),
SVN_TEST_NULL
};
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/spillbuf-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/spillbuf-test.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/spillbuf-test.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/spillbuf-test.c Tue Mar 6 17:50:23 2012
@@ -112,7 +112,7 @@ test_spillbuf_callback(apr_pool_t *pool)
SVN_ERR(svn_spillbuf__process(&exhausted, buf, read_callback, &counter,
pool));
SVN_TEST_ASSERT(!exhausted);
-
+
SVN_ERR(svn_spillbuf__process(&exhausted, buf, read_callback, &counter,
pool));
SVN_TEST_ASSERT(exhausted);
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/stream-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/stream-test.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/stream-test.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_subr/stream-test.c Tue Mar 6 17:50:23 2012
@@ -568,6 +568,165 @@ test_stream_base64(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+/* This test doesn't test much unless run under valgrind when it
+ triggers the problem reported here:
+
+ http://mail-archives.apache.org/mod_mbox/subversion-dev/201202.mbox/%3C87sjik3m8q.fsf@stat.home.lan%3E
+
+ The two data writes caused the base 64 code to allocate a buffer
+ that was a byte short but exactly matched a stringbuf blocksize.
+ That meant the stringbuf didn't overallocate and a write beyond
+ the end of the buffer occured.
+ */
+static svn_error_t *
+test_stream_base64_2(apr_pool_t *pool)
+{
+ const struct data_t {
+ const char *encoded1;
+ const char *encoded2;
+ } data[] = {
+ {
+ "MTI",
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "A23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "B23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "C23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "D23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "E23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "F23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "G23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "H23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "I23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D123456789E"
+ "623456789A123456789B123456789C123456789D123456789E"
+ "723456789A123456789B123456789C123456789D123456789E"
+ "823456789A123456789B123456789C123456789D123456789E"
+ "923456789A123456789B123456789C123456789D123456789E"
+ "J23456789A123456789B123456789C123456789D123456789E"
+ "123456789A123456789B123456789C123456789D123456789E"
+ "223456789A123456789B123456789C123456789D123456789E"
+ "323456789A123456789B123456789C123456789D123456789E"
+ "423456789A123456789B123456789C123456789D123456789E"
+ "523456789A123456789B123456789C123456789D12345"
+ },
+ {
+ NULL,
+ NULL,
+ },
+ };
+ int i;
+
+ for (i = 0; data[i].encoded1; i++)
+ {
+ apr_size_t len1 = strlen(data[i].encoded1);
+
+ svn_stringbuf_t *actual = svn_stringbuf_create_empty(pool);
+ svn_stringbuf_t *expected = svn_stringbuf_create_empty(pool);
+ svn_stream_t *stream = svn_stream_from_stringbuf(actual, pool);
+
+ stream = svn_base64_encode(stream, pool);
+ stream = svn_base64_decode(stream, pool);
+
+ SVN_ERR(svn_stream_write(stream, data[i].encoded1, &len1));
+ svn_stringbuf_appendbytes(expected, data[i].encoded1, len1);
+
+ if (data[i].encoded2)
+ {
+ apr_size_t len2 = strlen(data[i].encoded2);
+ SVN_ERR(svn_stream_write(stream, data[i].encoded2, &len2));
+ svn_stringbuf_appendbytes(expected, data[i].encoded2, len2);
+ }
+
+ SVN_ERR(svn_stream_close(stream));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
struct svn_test_descriptor_t test_funcs[] =
@@ -591,5 +750,7 @@ struct svn_test_descriptor_t test_funcs[
"test compressed streams with empty files"),
SVN_TEST_PASS2(test_stream_base64,
"test base64 encoding/decoding streams"),
+ SVN_TEST_PASS2(test_stream_base64_2,
+ "base64 decoding allocation problem"),
SVN_TEST_NULL
};
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_wc/op-depth-test.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_wc/op-depth-test.c Tue Mar 6 17:50:23 2012
@@ -350,12 +350,12 @@ print_row(const nodes_row_t *row,
moved_here_str = ", here";
else
moved_here_str = "";
-
+
if (row->file_external)
file_external_str = ", file-external";
else
file_external_str = "";
-
+
if (row->repo_revnum == SVN_INVALID_REVNUM)
return apr_psprintf(result_pool, "%d, %s, %s%s%s%s",
row->op_depth, row->local_relpath, row->presence,
@@ -3727,7 +3727,7 @@ incomplete_switch(const svn_test_opts_t
{0}
};
- nodes_row_t after_update[] = {
+ nodes_row_t after_update[] = {
{0, "", "normal", 4, "X"},
{0, "B", "normal", 4, "A/B"},
{0, "B/C", "normal", 4, "A/B/C"},
@@ -4195,7 +4195,7 @@ move_to_swap(const svn_test_opts_t *opts
SVN_ERR(wc_move(&b, "A/Y", "X/Y"));
SVN_ERR(wc_move(&b, "X/B", "A/B"));
-
+
{
nodes_row_t nodes[] = {
{0, "", "normal", 1, ""},
Modified: subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_wc/wc-incomplete-tester.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_wc/wc-incomplete-tester.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_wc/wc-incomplete-tester.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/tests/libsvn_wc/wc-incomplete-tester.c Tue Mar 6 17:50:23 2012
@@ -78,7 +78,7 @@ int main(int argc, const char *argv[])
"Mark WCPATH incomplete at REVISION [and REPOS_RELPATH]\n");
exit(EXIT_FAILURE);
}
-
+
if (apr_initialize())
{
fprintf(stderr, "apr_initialize failed\n");
Modified: subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/ubuntu-x64/svnbuild.sh
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/ubuntu-x64/svnbuild.sh?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/ubuntu-x64/svnbuild.sh (original)
+++ subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/ubuntu-x64/svnbuild.sh Tue Mar 6 17:50:23 2012
@@ -30,7 +30,7 @@ echo "========= autogen.sh"
echo "========= configure"
./configure --enable-javahl --enable-maintainer-mode \
--without-berkeley-db \
- --with-jdk=/usr/lib/jvm/java-6-openjdk/ \
+ --with-jdk=/usr/lib/jvm/java-7-openjdk-amd64/ \
--with-junit=/usr/share/java/junit.jar || exit $?
echo "========= make"
Modified: subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd (original)
+++ subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd Tue Mar 6 17:50:23 2012
@@ -32,8 +32,6 @@ IF ERRORLEVEL 1 (
PATH %PATH%;%TESTDIR%\bin
SET result=0
-
-echo python win-tests.py -r -f fsfs --javahl "%TESTDIR%\tests"
python win-tests.py -r -f fsfs --javahl "%TESTDIR%\tests"
IF ERRORLEVEL 1 (
echo [python reported error %ERRORLEVEL%]
@@ -44,10 +42,10 @@ IF EXIST "%TESTDIR%\swig" rmdir /s /q "%
mkdir "%TESTDIR%\swig\py-release\libsvn"
mkdir "%TESTDIR%\swig\py-release\svn"
-xcopy "release\subversion\bindings\swig\python\*.pyd" "%TESTDIR%\swig\py-release\libsvn\*.pyd"
-xcopy "release\subversion\bindings\swig\python\libsvn_swig_py\*.dll" "%TESTDIR%\swig\py-release\libsvn\*.dll"
-xcopy "subversion\bindings\swig\python\*.py" "%TESTDIR%\swig\py-release\libsvn\*.py"
-xcopy "subversion\bindings\swig\python\svn\*.py" "%TESTDIR%\swig\py-release\svn\*.py"
+xcopy "release\subversion\bindings\swig\python\*.pyd" "%TESTDIR%\swig\py-release\libsvn\*.pyd" > nul:
+xcopy "release\subversion\bindings\swig\python\libsvn_swig_py\*.dll" "%TESTDIR%\swig\py-release\libsvn\*.dll" > nul:
+xcopy "subversion\bindings\swig\python\*.py" "%TESTDIR%\swig\py-release\libsvn\*.py" > nul:
+xcopy "subversion\bindings\swig\python\svn\*.py" "%TESTDIR%\swig\py-release\svn\*.py" > nul:
SET PYTHONPATH=%TESTDIR%\swig\py-release
@@ -57,4 +55,25 @@ IF ERRORLEVEL 1 (
SET result=1
)
+mkdir "%TESTDIR%\swig\pl-release\SVN"
+mkdir "%TESTDIR%\swig\pl-release\auto\SVN"
+xcopy subversion\bindings\swig\perl\native\*.pm "%TESTDIR%\swig\pl-release\SVN" > nul:
+pushd release\subversion\bindings\swig\perl\native
+for %%i in (*.dll) do (
+ set name=%%i
+ mkdir "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!"
+ xcopy "!name:~0,-4!.*" "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!" > nul:
+ xcopy /y "_Core.dll" "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!" > nul:
+)
+popd
+
+SET PERL5LIB=%PERL5LIB%;%TESTDIR%\swig\pl-release;
+pushd subversion\bindings\swig\perl\native
+perl -MExtUtils::Command::MM -e test_harness() t\*.t
+IF ERRORLEVEL 1 (
+ echo [Perl reported error %ERRORLEVEL%]
+ REM SET result=1
+)
+popd
+
exit /b %result%
Modified: subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd (original)
+++ subversion/branches/reintegrate-keep-alive/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd Tue Mar 6 17:50:23 2012
@@ -48,7 +48,9 @@ IF NOT ERRORLEVEL 1 (
)
POPD
+
taskkill /im svn.exe /f 2> nul:
+taskkill /im svnlook.exe /f 2> nul:
taskkill /im svnadmin.exe /f 2> nul:
taskkill /im svnserve.exe /f 2> nul:
taskkill /im svnrdump.exe /f 2> nul:
@@ -58,6 +60,9 @@ taskkill /im op-depth-test.exe /f 2> nul
IF EXIST "%TESTDIR%\tests\subversion\tests\cmdline\httpd\" (
rmdir /s /q "%TESTDIR%\tests\subversion\tests\cmdline\httpd"
)
+IF EXIST "%TESTDIR%\swig\" (
+ rmdir /s /q "%TESTDIR%\swig"
+)
del "%TESTDIR%\tests\*.log" 2> nul:
Modified: subversion/branches/reintegrate-keep-alive/tools/client-side/detach.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/client-side/detach.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/client-side/detach.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/client-side/detach.py Tue Mar 6 17:50:23 2012
@@ -67,7 +67,7 @@ def migrate_sqlite(wc_src, target, wcro
src_c.execute('select count(*) from wc_lock')
count = int(src_c.fetchone()[0])
assert count == 0
-
+
src_c.execute('select count(*) from work_queue')
count = int(src_c.fetchone()[0])
assert count == 0
Modified: subversion/branches/reintegrate-keep-alive/tools/client-side/mergeinfo-sanitizer.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/client-side/mergeinfo-sanitizer.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/client-side/mergeinfo-sanitizer.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/client-side/mergeinfo-sanitizer.py Tue Mar 6 17:50:23 2012
@@ -177,7 +177,7 @@ def sanitize_mergeinfo(parsed_original_m
for entry in parsed_original_mergeinfo:
get_new_location_segments(parsed_original_mergeinfo[entry], repo_root, wcpath, ctx)
full_mergeinfo.update(parsed_original_mergeinfo[entry])
-
+
hasher(hash_file, newmergeinfo_file)
diff_mergeinfo = core.svn_mergeinfo_diff(full_mergeinfo,
mergeinfo, 1, temp_pool)
@@ -200,7 +200,7 @@ def fix_sanitized_mergeinfo(parsed_origi
ctx, hash_file, newmergeinfo_file, temp_pool):
has_local_modification = check_local_modifications(wcpath, temp_pool)
old_hash = ''
- new_hash = ''
+ new_hash = ''
try:
with open(hash_file, "r") as f:
old_hash = pickle.load(f)
@@ -248,7 +248,7 @@ the working copy before running the scri
sys.exit(1)
def get_original_mergeinfo(wcpath, revision, depth, ctx, temp_pool):
- propget_list = client.svn_client_propget3("svn:mergeinfo", wcpath,
+ propget_list = client.svn_client_propget3("svn:mergeinfo", wcpath,
revision, revision, depth, None,
ctx, temp_pool)
Modified: subversion/branches/reintegrate-keep-alive/tools/client-side/svnmucc/svnmucc.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/client-side/svnmucc/svnmucc.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/client-side/svnmucc/svnmucc.c (original)
+++ subversion/branches/reintegrate-keep-alive/tools/client-side/svnmucc/svnmucc.c Tue Mar 6 17:50:23 2012
@@ -826,7 +826,7 @@ main(int argc, const char **argv)
sizeof(struct action *));
const char *anchor = NULL;
svn_error_t *err = SVN_NO_ERROR;
- apr_getopt_t *getopt;
+ apr_getopt_t *opts;
enum {
config_dir_opt = SVN_OPT_FIRST_LONGOPT_ID,
config_inline_opt,
@@ -866,15 +866,15 @@ main(int argc, const char **argv)
config_options = apr_array_make(pool, 0,
sizeof(svn_cmdline__config_argument_t*));
- apr_getopt_init(&getopt, pool, argc, argv);
- getopt->interleave = 1;
+ apr_getopt_init(&opts, pool, argc, argv);
+ opts->interleave = 1;
while (1)
{
int opt;
const char *arg;
const char *opt_arg;
- apr_status_t status = apr_getopt_long(getopt, options, &opt, &arg);
+ apr_status_t status = apr_getopt_long(opts, options, &opt, &arg);
if (APR_STATUS_IS_EOF(status))
break;
if (status != APR_SUCCESS)
@@ -957,7 +957,7 @@ main(int argc, const char **argv)
no_auth_cache = TRUE;
break;
case version_opt:
- SVN_INT_ERR(display_version(getopt, pool));
+ SVN_INT_ERR(display_version(opts, pool));
exit(EXIT_SUCCESS);
break;
case 'h':
@@ -968,10 +968,10 @@ main(int argc, const char **argv)
/* Copy the rest of our command-line arguments to an array,
UTF-8-ing them along the way. */
- action_args = apr_array_make(pool, getopt->argc, sizeof(const char *));
- while (getopt->ind < getopt->argc)
+ action_args = apr_array_make(pool, opts->argc, sizeof(const char *));
+ while (opts->ind < opts->argc)
{
- const char *arg = getopt->argv[getopt->ind++];
+ const char *arg = opts->argv[opts->ind++];
if ((err = svn_utf_cstring_to_utf8(&(APR_ARRAY_PUSH(action_args,
const char *)),
arg, pool)))
Modified: subversion/branches/reintegrate-keep-alive/tools/dev/merge-graph.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/dev/merge-graph.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/dev/merge-graph.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/dev/merge-graph.py Tue Mar 6 17:50:23 2012
@@ -22,237 +22,9 @@
args_message = 'GRAPH_CONFIG_FILE...'
help_message = """Produce pretty graphs representing branches and merging.
For each config file specified, construct a graph and write it as a PNG file."""
-example = """
- [graph]
- filename = merge-sync-1.png
- title = Sync Merge: CC vs SVN
- # Branches: (branch name, branched from node, first rev, last rev).
- branches = [
- ('A', 'O0', 1, 4),
- ('O', None, 0, 0),
- ('B', 'O0', 1, 5)
- ]
- # Changes: nodes in which a change was committed; merge targets need not
- # be listed here.
- changes = [
- 'A1', 'A2', 'A3', 'A4',
- 'B1', 'B2', 'B3', 'B4', 'B5'
- ]
- # Merges: (base node, source-right node, target node, label).
- # Base is also known as source-left.
- merges = [
- ('O0', 'A:1', 'B3', 'sync'),
- ('A2', 'A:3', 'B5', 'sync'),
- ]
- # Annotations for nodes: (node, annotation text).
- annotations = [
- ('A2', 'cc:YCA')
- ]
-"""
-
-# Notes about different kinds of merge.
-#
-# A basic 3-way merge is ...
-#
-# The ClearCase style of merge is a 3-way merge.
-#
-# The Subversion style of merge (that is, one phase of a Subversion merge)
-# is a three-way merge with its base (typically the YCA) on the source branch.
-
import sys
-import pydot
-from pydot import Node, Edge
-
-
-def mergeinfo_to_node_list(mi):
- """Convert a mergeinfo string such as '/foo:1,3-5*' into a list of
- node names such as ['foo1', 'foo3', 'foo4', 'foo5']."""
- ### Doesn't yet strip the leading slash.
- l = []
- if mi:
- for mi_str in mi.split(' '):
- path, ranges = mi_str.split(':')
- for r in ranges.split(','):
- if r.endswith('*'):
- # TODO: store & use this 'non-inheritable' flag
- # Remove the flag
- r = r[:-1]
- rlist = r.split('-')
- r1 = int(rlist[0])
- if len(rlist) == 2:
- r2 = int(rlist[1])
- else:
- r2 = r1
- for rev in range(r1, r2 + 1):
- l.append(path + str(rev))
- return l
-
-
-class MergeGraph(pydot.Graph):
- """Base class, not intended for direct use. Use MergeDot for the main
- graph and MergeSubgraph for a subgraph."""
-
- def mk_origin_node(graph, name):
- """Add a node to the graph"""
- graph.add_node(Node(name + '0', label=name, shape='plaintext'))
-
- def mk_invis_node(graph, name):
- """Add a node to the graph"""
- graph.add_node(Node(name, style='invis'))
-
- def mk_node(graph, name):
- """Add a node to the graph, if not already present"""
- if not graph.get_node(name):
- if name in graph.changes:
- graph.add_node(Node(name))
- else:
- graph.add_node(Node(name, color='grey', label=''))
-
- def mk_merge_target(graph, target_node, important):
- """Add a merge target node to the graph."""
- if important:
- color = 'red'
- else:
- color = 'black'
- graph.add_node(Node(target_node, color=color, fontcolor=color, style='bold'))
-
- def mk_edge(graph, name1, name2, **attrs):
- """Add an ordinary edge to the graph"""
- graph.add_edge(Edge(name1, name2, dir='none', style='dotted', color='grey', **attrs))
-
- def mk_br_edge(graph, name1, name2):
- """Add a branch-creation edge to the graph"""
- # Constraint=false to avoid the Y-shape skewing the nice parallel branch lines
- graph.mk_edge(name1, name2, constraint='false')
-
- def mk_merge_edge(graph, src_node, tgt_node, kind, label, important):
- """Add a merge edge to the graph"""
- if important:
- color = 'red'
- else:
- color = 'grey'
- e = Edge(src_node, tgt_node, constraint='false',
- label='"' + label + '"',
- color=color, fontcolor=color,
- style='bold')
- if kind == 'cherry':
- e.set_style('dashed')
- e.set_dir('both')
- e.set_arrowtail('tee')
- graph.add_edge(e)
-
- def mk_mergeinfo_edge(graph, base_node, src_node, important):
- """"""
- if important:
- color = 'red'
- else:
- color = 'grey'
- graph.add_edge(Edge(base_node, src_node,
- dir='both', arrowtail='odot', arrowhead='tee',
- color=color, constraint='false'))
-
- def mk_invis_edge(graph, name1, name2):
- """Add an invisible edge to the graph"""
- graph.add_edge(Edge(name1, name2, style='invis'))
-
- def add_merge(graph, merge, important):
- """Add a merge"""
- base_node, src_node, tgt_node, kind = merge
-
- if base_node and src_node and kind != 'cherry':
- graph.mk_mergeinfo_edge(base_node, src_node, important)
-
- # Merge target node
- graph.mk_merge_target(tgt_node, important)
-
- # Merge edge
- graph.mk_merge_edge(src_node, tgt_node, kind, kind, important)
-
- def add_annotation(graph, node, label, color='red'):
- """"""
- ann_node = node + '_annotation'
- g = pydot.Subgraph(rank='same')
- g.add_node(Node(ann_node, shape='box', color=color, label='"' + label + '"'))
- g.add_edge(Edge(ann_node, node, style='dotted', color=color, dir='none', constraint='false'))
- graph.add_subgraph(g)
-
-class MergeSubgraph(MergeGraph, pydot.Subgraph):
- """"""
- def __init__(graph, **attrs):
- """"""
- MergeGraph.__init__(graph)
- pydot.Subgraph.__init__(graph, **attrs)
-
-class MergeDot(MergeGraph, pydot.Dot):
- """
- # TODO: In the 'merges' input, find the predecessor automatically.
- """
- def __init__(graph, config_filename, **attrs):
- """Return a new MergeDot graph generated from the specified config file."""
- MergeGraph.__init__(graph)
- pydot.Dot.__init__(graph, **attrs)
-
- graph.read_config(config_filename)
-
- graph.construct()
-
- def read_config(graph, config_filename):
- """"""
- import ConfigParser
- config = ConfigParser.SafeConfigParser()
- files_read = config.read(config_filename)
- if len(files_read) == 0:
- print >> sys.stderr, 'graph: unable to read graph config from "' + config_filename + '"'
- sys.exit(1)
- graph.title = config.get('graph', 'title')
- graph.filename = config.get('graph', 'filename')
- graph.branches = eval(config.get('graph', 'branches'))
- graph.changes = eval(config.get('graph', 'changes'))
- graph.merges = eval(config.get('graph', 'merges'))
- graph.annotations = eval(config.get('graph', 'annotations'))
-
- def construct(graph):
- """"""
- # Origin nodes (done first, in an attempt to set the order)
- for br, orig, r1, head in graph.branches:
- graph.mk_origin_node(br)
-
- # Edges and target nodes for merges
- for merge in graph.merges:
- # Emphasize the last merge, as it's the important one
- important = (merge == graph.merges[-1])
- graph.add_merge(merge, important)
-
- # Edges for basic lines of descent
- for br, orig, r1, head in graph.branches:
- sub_g = MergeSubgraph(ordering='out')
- for i in range(1, head + 1):
- prev_n = br + str(i - 1)
- this_n = br + str(i)
-
- # Normal edges and nodes
- if i < r1:
- graph.mk_invis_node(this_n)
- else:
- graph.mk_node(this_n)
- if i <= r1:
- graph.mk_invis_edge(prev_n, this_n)
- else:
- graph.mk_edge(prev_n, this_n)
-
- # Branch creation edges
- if orig:
- sub_g.mk_br_edge(orig, br + str(r1))
-
- graph.add_subgraph(sub_g)
-
- # Annotations
- for node, label in graph.annotations:
- graph.add_annotation(node, label)
-
- # A title for the graph (added last so it goes at the top)
- #graph.add_node(Node('title', shape='plaintext', label='"' + graph.title + '"'))
+from mergegraph import MergeDot
# If run as a program, process each input filename as a graph config file.
Propchange: subversion/branches/reintegrate-keep-alive/tools/dev/merge-graph.py
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/reintegrate-keep-alive/tools/dev/unix-build/Makefile.svn
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/dev/unix-build/Makefile.svn?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/dev/unix-build/Makefile.svn (original)
+++ subversion/branches/reintegrate-keep-alive/tools/dev/unix-build/Makefile.svn Tue Mar 6 17:50:23 2012
@@ -70,7 +70,7 @@ SERF_VER = 1.0.0
SERF_OLD_VER = 0.3.1
CYRUS_SASL_VER = 2.1.23
SQLITE_VER = 3070603
-LIBMAGIC_VER = 5.07
+LIBMAGIC_VER = 5.11
RUBY_VER = 1.8.7-p334
BZ2_VER = 1.0.6
PYTHON_VER = 2.7.2
Modified: subversion/branches/reintegrate-keep-alive/tools/dev/which-error.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/dev/which-error.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/dev/which-error.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/dev/which-error.py Tue Mar 6 17:50:23 2012
@@ -81,7 +81,10 @@ def print_error(code):
try:
print('%08d %s' % (code, __svn_error_codes[code]))
except KeyError:
- print('%08d *** UNKNOWN ERROR CODE ***' % (code))
+ if code == -41:
+ print("Sit by a lake.")
+ else:
+ print('%08d *** UNKNOWN ERROR CODE ***' % (code))
if __name__ == "__main__":
global __svn_error_codes
Modified: subversion/branches/reintegrate-keep-alive/tools/dev/windows-build/Makefile
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/dev/windows-build/Makefile?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/dev/windows-build/Makefile (original)
+++ subversion/branches/reintegrate-keep-alive/tools/dev/windows-build/Makefile Tue Mar 6 17:50:23 2012
@@ -107,7 +107,7 @@ config: targetdir
libsvn_auth_gnome_keyring libsvn_auth_kwallet libsvn_client libsvn_delta libsvn_diff libsvn_fs libsvn_fs_base libsvn_fs_fs libsvn_fs_util libsvn_ra libsvn_ra_local libsvn_ra_neon libsvn_ra_serf libsvn_ra_svn libsvn_repos libsvn_subr libsvn_wc: targetdir
$(MSBUILD) /t:Libraries\$@
$(MAKE) package
-svn svnadmin svndumpfilter svnlook svnmucc svnserve svnsync svnversion entries-dump: targetdir
+svn svnadmin svndumpfilter svnlook svnmucc svnserve svnsync svnversion svnrdump entries-dump: targetdir
$(MSBUILD) /t:Programs\$@
$(MAKE) package
auth-test cache-test changes-test checksum-test client-test compat-test config-test db-test diff-diff3-test dir-delta-editor dirent_uri-test error-test fs-base-test fs-pack-test fs-test hashdump-test key-test locks-test mergeinfo-test opt-test path-test ra-local-test random-test repos-test revision-test skel-test stream-test string-test strings-reps-test svn_test_fs svn_test_main svndiff-test target-test time-test translate-test tree-conflict-data-test utf-test vdelta-test window-test: targetdir
@@ -128,7 +128,7 @@ all2: targetdir
package:
test -d $(SVNDIR)\$(CONFIG)\Subversion\tests\cmdline || mkdir $(SVNDIR)\$(CONFIG)\Subversion\tests\cmdline
test -d $(TARGETDIR)\bin || mkdir $(TARGETDIR)\bin
- for %%i in (svn svnadmin svndumpfilter svnlook svnserve svnsync svnversion) do @$(CP) $(CONFIG)\subversion\%%i\%%i.exe $(TARGETDIR)\bin
+ for %%i in (svn svnadmin svndumpfilter svnlook svnserve svnsync svnversion svnrdump) do @$(CP) $(CONFIG)\subversion\%%i\%%i.exe $(TARGETDIR)\bin
for %%i in (diff diff3 diff4) do @if exist $(CONFIG)\tools\diff\%%i.exe $(CP) $(CONFIG)\tools\diff\%%i.exe $(TARGETDIR)\bin
$(CP) $(APRDIR)\$(CONFIG)/*.dll $(TARGETDIR)\bin
$(CP) $(APRUTILDIR)\$(CONFIG)/*.dll $(TARGETDIR)\bin
Modified: subversion/branches/reintegrate-keep-alive/tools/diff/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/diff/diff.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/diff/diff.c (original)
+++ subversion/branches/reintegrate-keep-alive/tools/diff/diff.c Tue Mar 6 17:50:23 2012
@@ -89,6 +89,8 @@ int main(int argc, const char *argv[])
options_array = apr_array_make(pool, 0, sizeof(const char *));
+ diff_options = svn_diff_file_options_create(pool);
+
for (i = 1 ; i < argc ; i++)
{
if (!no_more_options && (argv[i][0] == '-'))
@@ -105,6 +107,11 @@ int main(int argc, const char *argv[])
show_c_function = TRUE;
continue;
}
+ if (argv[i][1] == 'w' && !argv[i][2])
+ {
+ diff_options->ignore_space = svn_diff_file_ignore_space_all;
+ continue;
+ }
APR_ARRAY_PUSH(options_array, const char *) = argv[i];
}
else
@@ -127,8 +134,6 @@ int main(int argc, const char *argv[])
return 2;
}
- diff_options = svn_diff_file_options_create(pool);
-
svn_err = svn_diff_file_options_parse(diff_options, options_array, pool);
if (svn_err)
{
Modified: subversion/branches/reintegrate-keep-alive/tools/dist/backport.pl
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/dist/backport.pl?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/dist/backport.pl (original)
+++ subversion/branches/reintegrate-keep-alive/tools/dist/backport.pl Tue Mar 6 17:50:23 2012
@@ -1,6 +1,7 @@
#!/usr/bin/perl -l
use warnings;
use strict;
+use feature qw/switch say/;
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
@@ -21,14 +22,23 @@ use strict;
use Term::ReadKey qw/ReadMode ReadKey/;
use File::Temp qw/tempfile/;
-
-$/ = ""; # paragraph mode
+use POSIX qw/ctermid/;
my $SVN = $ENV{SVN} || 'svn'; # passed unquoted to sh
my $VIM = 'vim';
my $STATUS = './STATUS';
my $BRANCHES = '^/subversion/branches';
+
+my $YES = $ENV{YES}; # batch mode: eliminate prompts, add sleeps
my $WET_RUN = qw[false true][1]; # don't commit
+my $DEBUG = qw[false true][0]; # 'set -x', etc
+
+# derived values
+my $SVNq;
+
+$SVN .= " --non-interactive" if $YES or not defined ctermid;
+$SVNq = "$SVN -q ";
+$SVNq =~ s/-q// if $DEBUG eq 'true';
sub usage {
my $basename = $0;
@@ -70,7 +80,7 @@ sub merge {
# NOTE: This doesn't escape the branch into the pattern.
$pattern = sprintf '\V\(%s branch(es)?\|branches\/%s\|Branch(es)?:\n *%s\)', $entry{branch}, $entry{branch}, $entry{branch};
$mergeargs = "--reintegrate $BRANCHES/$entry{branch}";
- print $logmsg_fh "Reintergrate the $entry{header}:";
+ print $logmsg_fh "Reintegrate the $entry{header}:";
print $logmsg_fh "";
} elsif (@{$entry{revisions}}) {
$pattern = '^ [*] \V' . 'r' . $entry{revisions}->[0];
@@ -91,13 +101,20 @@ sub merge {
my $script = <<"EOF";
#!/bin/sh
set -e
+if $DEBUG; then
+ set -x
+fi
$SVN diff > $backupfile
-$SVN revert -R .
-$SVN up
-$SVN merge $mergeargs
+$SVNq revert -R .
+$SVNq up
+$SVNq merge $mergeargs
$VIM -e -s -n -N -i NONE -u NONE -c '/$pattern/normal! dap' -c wq $STATUS
if $WET_RUN; then
- $SVN commit -F $logmsg_filename
+ if [ -n "\$PRINT_SOMETHING_BETWEEN_PROMPTS" ]; then
+ # hack for pw-driver.pl to see some output between prompts
+ head -n1 $logmsg_filename
+ fi
+ $SVNq commit -F $logmsg_filename
else
echo "Committing:"
$SVN status -q
@@ -108,13 +125,16 @@ EOF
$script .= <<"EOF" if $entry{branch};
reinteg_rev=\`$SVN info $STATUS | sed -ne 's/Last Changed Rev: //p'\`
if $WET_RUN; then
- $SVN rm $BRANCHES/$entry{branch} -m "Remove the '$entry{branch}' branch, reintegrated in r\$reinteg_rev."
+ # Sleep to avoid out-of-order commit notifications
+ if [ -n "$YES" ]; then sleep 15; fi
+ $SVNq rm $BRANCHES/$entry{branch} -m "Remove the '$entry{branch}' branch, reintegrated in r\$reinteg_rev."
+ if [ -n "$YES" ]; then sleep 1; fi
else
echo "Removing reintegrated '$entry{branch}' branch"
fi
EOF
- open SHELL, '|-', qw#/bin/sh -x# or die $!;
+ open SHELL, '|-', qw#/bin/sh# or die $!;
print SHELL $script;
close SHELL or warn "$0: sh($?): $!";
@@ -143,7 +163,7 @@ sub parse_entry {
# revisions
$branch = sanitize_branch $1 if $_[0] =~ /^(\S*) branch$/;
while ($_[0] =~ /^r/) {
- while ($_[0] =~ s/^r(\d+)(?:,\s*)?//) {
+ while ($_[0] =~ s/^r(\d+)(?:$|[,; ]+)//) {
push @revisions, $1;
}
shift;
@@ -180,21 +200,27 @@ sub parse_entry {
sub handle_entry {
my %entry = parse_entry @_;
+ my @vetoes = grep { /^ -1:/ } @{$entry{votes}};
- print "";
- print "\n>>> The $entry{header}:";
- print join ", ", map { "r$_" } @{$entry{revisions}};
- print "$BRANCHES/$entry{branch}" if $entry{branch};
- print "";
- print for @{$entry{logsummary}};
- print "";
- print for @{$entry{votes}};
- print "";
- print "Vetoes found!" if grep { /^ -1:/ } @{$entry{votes}};
+ if ($YES) {
+ merge %entry unless @vetoes;
+ } else {
+ print "";
+ print "\n>>> The $entry{header}:";
+ print join ", ", map { "r$_" } @{$entry{revisions}};
+ print "$BRANCHES/$entry{branch}" if $entry{branch};
+ print "";
+ print for @{$entry{logsummary}};
+ print "";
+ print for @{$entry{votes}};
+ print "";
+ print "Vetoes found!" if @vetoes;
+
+ merge %entry if prompt;
+ }
- # TODO: this changes ./STATUS, which we're reading below, but
+ # TODO: merge() changes ./STATUS, which we're reading below, but
# on my system the loop in main() doesn't seem to care.
- merge %entry if $ENV{YES} or prompt;
1;
}
@@ -203,19 +229,37 @@ sub main {
usage, exit 0 if @ARGV;
usage, exit 1 unless -r $STATUS;
- my $sawapproved;
@ARGV = $STATUS;
- while (<>) {
- my @lines = split /\n/;
- # Section header?
- next unless $sawapproved ||= /^Approved changes/;
- print "\n\n=== $lines[0]" and next if $lines[0] =~ /^[A-Z].*:$/i;
+ # Skip most of the file
+ while (<>) {
+ last if /^Approved changes/;
+ }
+ while (<>) {
+ last unless /^=+$/;
+ }
+ $/ = ""; # paragraph mode
- # Backport entry?
- handle_entry @lines and next if $lines[0] =~ /^ \*/ and $sawapproved;
+ while (<>) {
+ my @lines = split /\n/;
- warn "Unknown entry '$lines[0]' at $ARGV:$.\n";
+ given ($lines[0]) {
+ # Section header
+ when (/^[A-Z].*:$/i) {
+ print "\n\n=== $lines[0]" unless $YES;
+ }
+ # Separator after section header
+ when (/^=+$/i) {
+ break;
+ }
+ # Backport entry?
+ when (/^ \*/) {
+ handle_entry @lines;
+ }
+ default {
+ warn "Unknown entry '$lines[0]' at $ARGV:$.\n";
+ }
+ }
}
}
Modified: subversion/branches/reintegrate-keep-alive/tools/dist/release.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/dist/release.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/dist/release.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/dist/release.py Tue Mar 6 17:50:23 2012
@@ -396,9 +396,9 @@ def roll_tarballs(args):
raise RuntimeError('Cannot find usable %s' % dep.label)
if branch != 'trunk':
- # Make sure CHANGES is sync'd.
+ # Make sure CHANGES is sync'd.
compare_changes(repos, branch, args.revnum)
-
+
# Ensure the output directory doesn't already exist
if os.path.exists(get_deploydir(args.base_dir)):
raise RuntimeError('output directory \'%s\' already exists'
Modified: subversion/branches/reintegrate-keep-alive/tools/examples/get-location-segments.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/examples/get-location-segments.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/examples/get-location-segments.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/examples/get-location-segments.py Tue Mar 6 17:50:23 2012
@@ -105,6 +105,9 @@ def prompt_func_simple_prompt(realm, use
simple_cred.may_save = False
return simple_cred
+def prompt_func_gnome_keyring_prompt(keyring, pool):
+ return getpass.getpass(prompt="Password for '%s' GNOME keyring: " % keyring)
+
def main():
try:
url, peg_revision, start_revision, end_revision = parse_args(sys.argv[1:])
@@ -125,7 +128,12 @@ ERROR: %s
core.svn_config_ensure(None)
ctx = client.svn_client_create_context()
- providers = [
+ ctx.config = core.svn_config_get_config(None)
+
+ # Make sure that these are at the start of the list, so passwords from
+ # gnome-keyring / kwallet are checked before asking for new passwords.
+ providers = core.svn_auth_get_platform_specific_client_providers(ctx.config['config'], None)
+ providers.extend([
client.get_simple_provider(),
core.svn_auth_get_ssl_server_trust_file_provider(),
core.svn_auth_get_simple_prompt_provider(prompt_func_simple_prompt, 2),
@@ -134,9 +142,12 @@ ERROR: %s
client.get_ssl_server_trust_file_provider(),
client.get_ssl_client_cert_file_provider(),
client.get_ssl_client_cert_pw_file_provider(),
- ]
+ ])
+
ctx.auth_baton = core.svn_auth_open(providers)
- ctx.config = core.svn_config_get_config(None)
+
+ if hasattr(core, 'svn_auth_set_gnome_keyring_unlock_prompt_func'):
+ core.svn_auth_set_gnome_keyring_unlock_prompt_func(ctx.auth_baton, prompt_func_gnome_keyring_prompt)
ra_callbacks = ra.callbacks_t()
ra_callbacks.auth_baton = ctx.auth_baton
Modified: subversion/branches/reintegrate-keep-alive/tools/server-side/svnpredumpfilter.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/server-side/svnpredumpfilter.py?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/server-side/svnpredumpfilter.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/server-side/svnpredumpfilter.py Tue Mar 6 17:50:23 2012
@@ -114,12 +114,12 @@ def log(msg, min_verbosity):
elif min_verbosity == 2:
sys.stderr.write("[**] ")
sys.stderr.write(msg + "\n")
-
+
class DependencyTracker:
def __init__(self, include_paths):
self.include_paths = include_paths[:]
self.dependent_paths = []
-
+
def path_included(self, path):
for include_path in self.include_paths + self.dependent_paths:
if subsumes(include_path, path):
@@ -143,7 +143,7 @@ def readline(stream):
def svn_log_stream_get_dependencies(stream, included_paths):
import re
- dt = DependencyTracker(included_paths)
+ dt = DependencyTracker(included_paths)
header_re = re.compile(r'^r([0-9]+) \|.*$')
action_re = re.compile(r'^ [ADMR] /(.*)$')
@@ -153,7 +153,7 @@ def svn_log_stream_get_dependencies(stre
eof = False
path_copies = {}
found_changed_path = False
-
+
while not eof:
try:
line = line_buf is not None and line_buf or readline(stream)
@@ -220,7 +220,7 @@ def svn_log_stream_get_dependencies(stre
raise LogStreamError("No changed paths found; did you remember to run "
"'svn log' with the --verbose (-v) option when "
"generating the input to this script?")
-
+
return dt
def analyze_logs(included_paths):
@@ -268,13 +268,13 @@ def usage_and_exit(errmsg=None):
def main():
config_dir = None
targets_file = None
-
+
try:
opts, args = getopt.getopt(sys.argv[1:], "hv",
["help", "verbose", "targets="])
except getopt.GetoptError, e:
usage_and_exit(str(e))
-
+
for option, value in opts:
if option in ['-h', '--help']:
usage_and_exit()
Modified: subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnpubsub/client.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnpubsub/client.py?rev=1297604&r1=1295003&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnpubsub/client.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnpubsub/client.py Tue Mar 6 17:50:23 2012
@@ -145,8 +145,8 @@ class XMLStreamHandler(xml.sax.handler.C
class Revision(object):
- def __init__(self, repos, rev):
- self.repos = repos
+ def __init__(self, uuid, rev):
+ self.uuid = uuid
self.rev = rev
self.dirs_changed = [ ]
self.author = None
Modified: subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnpubsub/server.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnpubsub/server.py?rev=1297604&r1=1295003&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnpubsub/server.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnpubsub/server.py Tue Mar 6 17:50:23 2012
@@ -37,7 +37,7 @@
# URL is built into 3 parts:
# /${type}/${optional_repo_uuid}/${format}
#
-# If the repository UUID is included in the URl, you will only recieve
+# If the repository UUID is included in the URl, you will only receive
# messages about that repository.
#
# Example Pub clients:
@@ -88,7 +88,7 @@ class Revision:
'author': self.author,
'log': self.log,
'date': self.date}}) +","
- elif format == "xml":
+ elif format == "xml":
c = ET.Element('commit', {'repository': self.repos, 'revision': "%d" % (self.rev)})
ET.SubElement(c, 'author').text = self.author
ET.SubElement(c, 'date').text = self.date
@@ -107,7 +107,7 @@ class Revision:
return json.dumps({'commit': {'repository': self.repos,
'revision': self.rev,
'dirs_changed': self.dirs_changed}}) +","
- elif format == "xml":
+ elif format == "xml":
c = ET.Element('commit', {'repository': self.repos, 'revision': "%d" % (self.rev)})
d = ET.SubElement(c, 'dirs_changed')
for p in self.dirs_changed:
@@ -133,7 +133,7 @@ class Client(object):
def finished(self, reason):
self.alive = False
log.msg("CLOSE: %s:%d (%d clients online)"% (self.r.getClientIP(), self.r.client.port, self.pubsub.cc()))
- try:
+ try:
self.pubsub.remove(self)
except ValueError:
pass
@@ -210,11 +210,11 @@ class SvnPubSub(resource.Resource):
else:
fmt = uri[3]
uuid = uri[2]
-
+
if type not in self.clients.keys():
request.setResponseCode(400)
return "Invalid Reuqest Type\n"
-
+
clients = {'json': JSONClient, 'xml': XMLClient}
clientCls = clients.get(fmt)
if clientCls == None:
@@ -262,7 +262,7 @@ def svnpubsub_server():
root.putChild("commits", s)
root.putChild("commit", s)
return server.Site(root)
-
+
if __name__ == "__main__":
log.startLogging(sys.stdout)
# Port 2069 "HTTP Event Port", whatever, sounds good to me
Modified: subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svntweet.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svntweet.py?rev=1297604&r1=1295003&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svntweet.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svntweet.py Tue Mar 6 17:50:23 2012
@@ -21,7 +21,7 @@
#
# Example:
# svntweet.py my-config.json
-#
+#
# With my-config.json containing stream paths and the twitter auth info:
# {"stream": "http://svn-master.apache.org:2069/commits/xml",
# "username": "asfcommits",
@@ -90,9 +90,9 @@ class Revision:
self.log = None
self.date = None
-class StreamHandler(handler.ContentHandler):
+class StreamHandler(handler.ContentHandler):
def __init__(self, bdec):
- handler.ContentHandler.__init__(self)
+ handler.ContentHandler.__init__(self)
self.bdec = bdec
self.rev = None
self.text_value = None
@@ -115,7 +115,7 @@ class StreamHandler(handler.ContentHandl
self.bdec.stillalive()
def characters(self, data):
if self.text_value is not None:
- self.text_value = self.text_value + data
+ self.text_value = self.text_value + data
else:
self.text_value = data
@@ -179,7 +179,7 @@ class BigDoEverythingClasss(object):
def pageStart(self):
log.msg("Stream Connection Established")
self.failures = 0
-
+
def _restartStream(self):
(self.stream, self.transport) = connectTo(self.url, self)
self.stream.deferred.addBoth(self.streamDead)
@@ -253,6 +253,6 @@ def main(config_file):
if __name__ == "__main__":
if len(sys.argv) != 2:
print "invalid args, read source code"
- sys.exit(0)
+ sys.exit(0)
log.startLogging(sys.stdout)
main(sys.argv[1])
Modified: subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnwcsub.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnwcsub.py?rev=1297604&r1=1295003&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnwcsub.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/svnwcsub.py Tue Mar 6 17:50:23 2012
@@ -36,8 +36,9 @@ import os
import re
import ConfigParser
import time
-import logging
+import logging.handlers
import Queue
+import optparse
from twisted.internet import reactor, task, threads
from twisted.internet.utils import getProcessOutput
@@ -130,7 +131,7 @@ class WorkingCopy(object):
uuid = info['Repository UUID']
relpath = url[len(repos):] # also has leading '/'
return [relpath, url, repos, uuid]
-
+
class HTTPStream(HTTPClientFactory):
protocol = HTTPPageDownloader
@@ -154,9 +155,9 @@ class Revision:
self.rev = rev
self.dirs_changed = []
-class StreamHandler(handler.ContentHandler):
+class StreamHandler(handler.ContentHandler):
def __init__(self, stream, bdec):
- handler.ContentHandler.__init__(self)
+ handler.ContentHandler.__init__(self)
self.stream = stream
self.bdec = bdec
self.rev = None
@@ -167,7 +168,7 @@ class StreamHandler(handler.ContentHandl
"""
<commit revision="7">
<dirs_changed><path>/</path></dirs_changed>
- </commit>
+ </commit>
"""
if name == "commit":
self.rev = Revision(attrs['repository'], int(attrs['revision']))
@@ -175,7 +176,7 @@ class StreamHandler(handler.ContentHandl
self.bdec.stillalive(self.stream)
def characters(self, data):
if self.text_value is not None:
- self.text_value = self.text_value + data
+ self.text_value = self.text_value + data
else:
self.text_value = data
@@ -230,7 +231,6 @@ class BigDoEverythingClasss(object):
self.svnbin = config.get_value('svnbin')
self.env = config.get_env()
self.worker = BackgroundWorker(self.svnbin, self.env)
- self.worker.start()
self.service = service
self.failures = 0
self.alive = time.time()
@@ -333,12 +333,15 @@ class BackgroundWorker(threading.Thread)
threading.Thread.__init__(self)
# The main thread/process should not wait for this thread to exit.
- self.daemon = True
+ ### compat with Python 2.5
+ self.setDaemon(True)
self.svnbin = svnbin
self.env = env
self.q = Queue.Queue()
+ self.has_started = False
+
def run(self):
while True:
if self.q.qsize() > BACKLOG_TOO_HIGH:
@@ -360,6 +363,12 @@ class BackgroundWorker(threading.Thread)
self.q.task_done()
def add_work(self, operation, wc):
+ # Start the thread when work first arrives. Thread-start needs to
+ # be delayed in case the process forks itself to become a daemon.
+ if not self.has_started:
+ self.start()
+ self.has_started = True
+
self.q.put((operation, wc))
def _update(self, wc):
@@ -443,21 +452,93 @@ class ReloadableConfig(ConfigParser.Safe
return str(option)
-def main(config_file):
+def prepare_logging(logfile):
+ "Log to the specified file, or to stdout if None."
+
+ if logfile:
+ # Rotate logs daily, keeping 7 days worth.
+ handler = logging.handlers.TimedRotatingFileHandler(
+ logfile, when='midnight', backupCount=7,
+ )
+ else:
+ handler = logging.StreamHandler(sys.stdout)
+
+ # Add a timestamp to the log records
+ formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s',
+ '%Y-%m-%d %H:%M:%S')
+ handler.setFormatter(formatter)
+
+ # Apply the handler to the root logger
+ root = logging.getLogger()
+ root.addHandler(handler)
+
+ ### use logging.INFO for now. switch to cmdline option or a config?
+ root.setLevel(logging.INFO)
+
+
+def handle_options(options):
+ # Set up the logging, then process the rest of the options.
+ prepare_logging(options.logfile)
+
+ if options.pidfile:
+ pid = os.getpid()
+ open(options.pidfile, 'w').write('%s\n' % pid)
+ logging.info('pid %d written to %s', pid, options.pidfile)
+
+ if options.uid:
+ try:
+ uid = int(options.uid)
+ except ValueError:
+ import pwd
+ uid = pwd.getpwnam(options.uid)[2]
+ logging.info('setting uid %d', uid)
+ os.setuid(uid)
+
+ if options.gid:
+ try:
+ gid = int(options.gid)
+ except ValueError:
+ import grp
+ gid = grp.getgrnam(options.gid)[2]
+ logging.info('setting gid %d', gid)
+ os.setgid(gid)
+
+ if options.umask:
+ umask = int(options.umask, 8)
+ os.umask(umask)
+ logging.info('umask set to %03o', umask)
+
+
+def main(args):
+ parser = optparse.OptionParser(
+ description='An SvnPubSub client to keep working copies synchronized '
+ 'with a repository.',
+ usage='Usage: %prog [options] CONFIG_FILE',
+ )
+ parser.add_option('--logfile',
+ help='filename for logging')
+ parser.add_option('--pidfile',
+ help="the process' PID will be written to this file")
+ parser.add_option('--uid',
+ help='switch to this UID before running')
+ parser.add_option('--gid',
+ help='switch to this GID before running')
+ parser.add_option('--umask',
+ help='set this (octal) umask before running')
+
+ options, extra = parser.parse_args(args)
+
+ if len(extra) != 1:
+ parser.error('CONFIG_FILE is required')
+ config_file = extra[0]
+
+ # Process any provided options.
+ handle_options(options)
+
c = ReloadableConfig(config_file)
big = BigDoEverythingClasss(c)
reactor.run()
if __name__ == "__main__":
- if len(sys.argv) != 2:
- print "invalid args, read source code"
- sys.exit(0)
-
- ### use logging.INFO for now. review/adjust the calls above for the
- ### proper logging level. then remove the level (to return to default).
- ### future: switch to config for logfile and loglevel.
- logging.basicConfig(level=logging.INFO, stream=sys.stdout,
- datefmt='%Y-%m-%d %H:%M:%S',
- format='%(asctime)s [%(levelname)s] %(message)s')
- main(sys.argv[1])
+ main(sys.argv[1:])
Modified: subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/test.conf
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/test.conf?rev=1297604&r1=1295003&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/test.conf (original)
+++ subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/test.conf Tue Mar 6 17:50:23 2012
@@ -1,4 +1,9 @@
-# For use with testserver.py
+# For use with connecting to testserver.py
[DEFAULT]
+svnbin: svn
streams: http://127.0.0.1:2069/commits/xml
+
+[env]
+
+[track]
Modified: subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/watcher.py
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/watcher.py?rev=1297604&r1=1295003&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/watcher.py (original)
+++ subversion/branches/reintegrate-keep-alive/tools/server-side/svnpubsub/watcher.py Tue Mar 6 17:50:23 2012
@@ -53,5 +53,5 @@ def main(config_file):
if __name__ == "__main__":
if len(sys.argv) != 2:
print "invalid args, read source code"
- sys.exit(0)
+ sys.exit(0)
main(sys.argv[1])