From ea40732a254bd7ca1271db363ce26ca725cf5d28 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sun, 29 Jan 2012 19:09:19 -0500 Subject: [PATCH] WIP on verify --- svn2svn/run/svn2svn.py | 86 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/svn2svn/run/svn2svn.py b/svn2svn/run/svn2svn.py index 1052835..5a2ef6c 100644 --- a/svn2svn/run/svn2svn.py +++ b/svn2svn/run/svn2svn.py @@ -551,6 +551,90 @@ def process_svn_log_entry(log_entry, options, commit_paths, prefix = ""): run_svn(["export", "--force", "-r", source_rev, source_url+"/"+path_offset+"@"+str(source_rev), path_offset]) + # Optionally verify that we replayed everything correctly + if options.verify: + wc_info = svnclient.get_svn_info(".") + target_rev = wc_info['revision'] + #checked_paths = [] + for d in log_entry['changed_paths']: + path = d['path'] + if not path.startswith(source_base + "/"): + continue + path_offset = path[len(source_base):].strip("/") + #if path_in_list(checked_paths, path_offset): + # continue + #add_path(checked_paths, path_offset) + action = d['action'] + 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 "") + status = svnclient.get_svn_status(path_offset)[0] + print status + if action not in _valid_svn_actions: + continue + if action == 'D': + action_type = "delete" + status_status = "deleted" + if os.path.exists(path_offset) and not path_is_dir: + # Don't complain if (root) directory still exists. Root deleted directory + # will be removed during the commit. + raise VerificationError("Path exists in _wc_target:\n%s" % \ + (desc)) + # Verify that _wc_target tracks this as a deletion + if not status['status'] == status_status: + raise VerificationError("Path not scheduled for %s in _wc_target:\n%s" % \ + (action_type, desc)) + if action in 'AR': + action_type = ("add" if action == "A" else "replace") + status_status = ("added" if action == "A" else "replaced") + if not os.path.exists(path_offset): + raise VerificationError("Path doesn't exist in _wc_target:\n%s" % \ + (desc)) + # Verify that _wc_target tracks this as an add/replace + 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, \ + path_offset, source_rev, prefix+" ") if d['copyfrom_path'] \ + else [] + if not source_ancestors: + # For copyfrom=False, check that local path doesn't have any ancestry + if status['copied'] and status['copied'] == 'true': + raise VerificationError("Path copy-from'd in _wc_target:\n%s" % \ + (desc)) + else: + # For copyfrom=True, need to recursively check all child contents. + 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+" ") + 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'] + target_copyfrom_path = target_ancestors[len(target_ancestors)-1]['path'] + target_copyfrom_offset = target_copyfrom_path[len(target_base):].strip('/') + target_copyfrom_rev = target_ancestors[len(target_ancestors)-1]['revision'] + if source_copyfrom_offset != target_copyfrom_offset: + raise VerificationError("Path not copy-from'd same path_offset: source_copyfrom=%s, target_copyfrom=%s:\n%s" % \ + (source_copyfrom_path+"@"+str(source_copyfrom_rev), target_copyfrom_path+"@"+str(target_copyfrom_rev), desc)) + source_tgt_rev = get_rev_map(rev_map, source_copyfrom_rev, prefix+" ") + if source_tgt_rev != target_copyfrom_rev: + raise VerificationError("Path not copy-from'd same revision: get_rev_map(%s)=%s, target_rev=%s\n%s" % \ + (source_copyfrom_rev, source_tgt_rev, target_rev, desc)) + # TODO: Recursively check all child contents + pass + if action == 'M': + action_type = "modified" + if not os.path.exists(path_offset): + raise VerificationError(" %s %s" % (action, path_offset)) + if path_is_dir: + # TODO: Is there anything to check for directories? Maybe properties? + pass + else: + # TODO: Use md5sum to compare both the remote and local file? + pass + def disp_svn_log_summary(log_entry): ui.status("") ui.status("r%s | %s | %s", @@ -758,6 +842,8 @@ def main(): help="maintain original 'Author' info from source repo") parser.add_option("-c", "--continue", action="store_true", dest="cont_from_break", help="continue from previous break") + parser.add_option("-x", "--verify", action="store_true", dest="verify", default=False, + help="verify ancestry and content before target commits") parser.add_option("-l", "--limit", type="int", dest="entries_proc_limit", metavar="NUM", help="maximum number of log entries to process") parser.add_option("-n", "--dry-run", action="store_true", dest="dry_run", default=False, -- 2.49.0