From 5353665bbc02eb9f9ceafaf07c83814b02dec760 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sun, 29 Jan 2012 21:37:01 -0500 Subject: [PATCH] WIP on verify --- svn2svn/run/svn2svn.py | 62 ++++++++++++++++++++++++------------------ svn2svn/svnclient.py | 27 +++++++++++++----- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/svn2svn/run/svn2svn.py b/svn2svn/run/svn2svn.py index 5a2ef6c..a1fb532 100644 --- a/svn2svn/run/svn2svn.py +++ b/svn2svn/run/svn2svn.py @@ -1,7 +1,4 @@ -""" -Replicate (replay) changesets from one SVN repository to another. -""" - +""" Replicate (replay) changesets from one SVN repository to another. """ from .. import base_version, full_version from .. import ui from .. import svnclient @@ -26,6 +23,8 @@ source_repos_url = "" # URL to root of source SVN repo, e.g. 'http://s source_base = "" # Relative path of source_url in source SVN repo, e.g. '/trunk' source_repos_uuid = "" # UUID of source SVN repo target_url ="" # URL to target path in target SVN repo, e.g. 'file:///svn/repo_target/trunk' +target_repos_url = "" # URL to root of target SVN repo, e.g. 'file:///svn/repo_target' +target_base = "" # Relative path of target_url in target SVN repo, e.g. '/trunk' rev_map = {} # The running mapping-table dictionary for source_url rev #'s -> target_url rev #'s def commit_from_svn_log_entry(log_entry, options, commit_paths=None, target_revprops=None): @@ -127,7 +126,7 @@ def in_svn(p, require_in_repo=False, prefix=""): ui.status(prefix + ">> in_svn('%s', require_in_repo=%s) --> %s", p, str(require_in_repo), str(ret), level=ui.DEBUG, color='GREEN') return ret -def find_svn_ancestors(svn_repos_url, base_path, source_path, source_rev, prefix = ""): +def find_svn_ancestors(svn_url_or_wc, base_path, source_path, source_rev, prefix = ""): """ Given a source path, walk the SVN history backwards to inspect the ancestory of that path, seeing if it traces back to base_path. Build an array of copyfrom_path @@ -142,34 +141,45 @@ def find_svn_ancestors(svn_repos_url, base_path, source_path, source_rev, prefix 'svn_repos_url' is the full URL to the root of the SVN repository, e.g. 'file:///path/to/repo' 'base_path' is the path in the SVN repo to the target path we're trying to - trace ancestry back to, e.g. 'trunk'. + trace ancestry back to, e.g. '/trunk'. 'source_path' is the path in the SVN repo to the source path to start checking - ancestry at, e.g. 'branches/fix1/projectA/file1.txt'. + ancestry at, e.g. '/branches/fix1/projectA/file1.txt'. (full_path = svn_repos_url+base_path+"/"+path_offset) 'source_rev' is the revision to start walking the history of source_path backwards from. """ - ui.status(prefix + ">> find_svn_ancestors: Start: (%s) source_path: %s base_path: %s", - svn_repos_url, source_path+"@"+str(source_rev), base_path, level=ui.DEBUG, color='YELLOW') - done = False + info = svnclient.get_svn_info(svn_url_or_wc) + svn_repos_url = info['repos_url'] + is_wc = True if info['is_wc'] else False + ui.status(prefix + ">> find_svn_ancestors: Start (url=%s): source_path: %s, base_path: %s, is_wc: %s", + info['url'], source_path+"@"+str(source_rev), base_path, str(is_wc), level=ui.DEBUG, color='YELLOW') + # Init for first iteration working_path = base_path+"/"+source_path working_rev = source_rev - first_iter_done = False + done = False + first_iter = True ancestors_temp = [] while not done: - # Get the first "svn log" entry for this path (relative to @rev) - ui.status(prefix + ">> find_svn_ancestors: %s", svn_repos_url + working_path+"@"+str(working_rev), level=ui.DEBUG, color='YELLOW') - log_entry = svnclient.get_first_svn_log_entry(svn_repos_url + working_path+"@"+str(working_rev), 1, working_rev, True) - if not log_entry: - ui.status(prefix + ">> find_svn_ancestors: Done: no log_entry", level=ui.DEBUG, color='YELLOW') - done = True - break + if is_wc and first_iter: + # If checking ancestry for a working-copy, need to use "svn info" to detect copy-from info. + info = svnclient.get_svn_info(source_path) + print info + sys.exit(1) + else: + # Get the first "svn log" entry for this path (relative to @rev) + search_path = working_path if is_wc else (svn_repos_url + working_path+"@"+str(working_rev)) + ui.status(prefix + ">> find_svn_ancestors: %s", search_path, level=ui.DEBUG, color='YELLOW') + log_entry = svnclient.get_first_svn_log_entry(svn_repos_url + working_path+"@"+str(working_rev), 1, working_rev, True) + if not log_entry: + ui.status(prefix + ">> find_svn_ancestors: Done: no log_entry", level=ui.DEBUG, color='YELLOW') + done = True + continue # If we found a copy-from case which matches our base_path, we're done. # ...but only if we've at least tried to search for the first copy-from path. - if first_iter_done and working_path.startswith(base_path): - ui.status(prefix + ">> find_svn_ancestors: Done: Found working_path.startswith(base_path) and first_iter_done=True", level=ui.DEBUG, color='YELLOW') + if (not first_iter) and working_path.startswith(base_path): + ui.status(prefix + ">> find_svn_ancestors: Done: Found working_path.startswith(base_path) and first_iter=False", level=ui.DEBUG, color='YELLOW') done = True - break - first_iter_done = True + continue + first_iter = False # Search for any actions on our target path (or parent paths). changed_paths_temp = [] for d in log_entry['changed_paths']: @@ -344,7 +354,7 @@ def do_svn_add(path_offset, source_rev, parent_copyfrom_path="", parent_copyfrom level=ui.DEBUG, color='GREEN') # Check if the given path has ancestors which chain back to the current source_base found_ancestor = False - ancestors = find_svn_ancestors(source_repos_url, source_base, path_offset, source_rev, prefix+" ") + ancestors = find_svn_ancestors(source_url, source_base, path_offset, source_rev, prefix+" ") # ancestors[n] is the original (pre-branch-copy) trunk path. # ancestors[n-1] is the first commit on the new branch. copyfrom_path = ancestors[len(ancestors)-1]['path'] if ancestors else "" @@ -568,6 +578,7 @@ def process_svn_log_entry(log_entry, options, commit_paths, prefix = ""): assert len(d['kind'])>0 path_is_dir = True if d['kind'] == 'dir' else False desc = " %s %s%s" % (action, d['path'], (" (from %s)" % (d['copyfrom_path']+"@"+str(d['copyfrom_revision']))) if d['copyfrom_path'] else "") + ui.status(prefix+">> process_svn_log_entry: Verify: "+desc, level=ui.DEBUG, color='GREEN') status = svnclient.get_svn_status(path_offset)[0] print status if action not in _valid_svn_actions: @@ -594,7 +605,7 @@ def process_svn_log_entry(log_entry, options, commit_paths, prefix = ""): if not status['status'] == status_status: raise VerificationError("Path not scheduled for %s in _wc_target:\n%s" % \ (action_type, desc)) - source_ancestors = find_svn_ancestors(source_repos_url, source_base, \ + source_ancestors = find_svn_ancestors(source_url, source_base, \ path_offset, source_rev, prefix+" ") if d['copyfrom_path'] \ else [] if not source_ancestors: @@ -607,8 +618,7 @@ def process_svn_log_entry(log_entry, options, commit_paths, prefix = ""): if not status['copied'] or status['copied'] != 'true': raise VerificationError("Path not copy-from'd in _wc_target:\n%s" % \ (desc)) - target_ancestors = find_svn_ancestors(target_repos_url, target_base, \ - path_offset, target_rev, prefix+" ") + target_ancestors = find_svn_ancestors(".", target_base, path_offset, 'HEAD', prefix+" ") source_copyfrom_path = source_ancestors[len(source_ancestors)-1]['path'] source_copyfrom_offset = source_copyfrom_path[len(source_base):].strip('/') source_copyfrom_rev = source_ancestors[len(source_ancestors)-1]['revision'] diff --git a/svn2svn/svnclient.py b/svn2svn/svnclient.py index 0f3420a..d4ee64e 100644 --- a/svn2svn/svnclient.py +++ b/svn2svn/svnclient.py @@ -52,18 +52,31 @@ def parse_svn_info_xml(xml_string): """ d = {} xml_string = strip_forbidden_xml_chars(xml_string) + print xml_string tree = ET.fromstring(xml_string) entry = tree.find('.//entry') d['url'] = entry.find('url').text d['kind'] = entry.get('kind') d['revision'] = int(entry.get('revision')) - d['repos_url'] = tree.find('.//repository/root').text - d['repos_uuid'] = tree.find('.//repository/uuid').text - d['last_changed_rev'] = int(tree.find('.//commit').get('revision')) - author_element = tree.find('.//commit/author') - if author_element is not None: - d['last_changed_author'] = author_element.text - d['last_changed_date'] = svn_date_to_timestamp(tree.find('.//commit/date').text) + d['repos_url'] = entry.find('.//repository/root').text + elem = entry.find('.//repository/uuid') + if elem is not None: + d['repos_uuid'] = elem.text + wc_info = entry.find('.//wc-info') + d['is_wc'] = is_wc = True if wc_info is not None else False + print str(is_wc) + if is_wc: + d['schedule'] = wc_info.find('schedule').text + if wc_info.find('copy-from-url') is not None: + d['copy-from-url'] = wc_info.find('copy-from-url').text + d['copy-from-rev'] = wc_info.find('copy-from-rev').text + commit = entry.find('commit') + if commit is not None: + d['last_changed_rev'] = int(commit.get('revision')) + author = commit.find('author') + if author is not None: + d['last_changed_author'] = author.text + d['last_changed_date'] = svn_date_to_timestamp(commit.find('date').text) return d def parse_svn_log_xml(xml_string): -- 2.49.0