From 9bfe6505f93bb802a33937f49f390804d8169e59 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sun, 8 Apr 2012 19:45:30 -0500 Subject: [PATCH] Correctly handle source_url/target_url with chars needing URL-encoding Use urllib.unquote() to URL-decode source_url/target_url values. All URLs passed to run_svn() should go through svnclient.safe_path() and we don't want to end-up *double* urllib.quote'ing if the user- supplied source/target URL's are already URL-encoded or have chars which need URL-encoding. * svn2svn/run/svn2svn.py (real_main): Maintain source_url/target_url as URL-decoded values. * svn2svn/run/svn2svn.py (gen_tracking_revprops, build_rev_map): Translate "internal" source_url back to an "external" (URL-encoded) value. * svn2svn/svnclient (parse_svn_info_xml): URL-decode 'url' and 'repos_url' values, since all downstream consumers should want these to be in the "internal" (URL-decoded) format. * tests/make-ref-repo.sh: Add test-cases to further stress-test URL-encoding/decoding. --- svn2svn/run/svn2svn.py | 12 ++++++++---- svn2svn/svnclient.py | 5 +++++ tests/make-ref-repo.sh | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/svn2svn/run/svn2svn.py b/svn2svn/run/svn2svn.py index 1a0f209..3b928d6 100644 --- a/svn2svn/run/svn2svn.py +++ b/svn2svn/run/svn2svn.py @@ -371,7 +371,7 @@ def gen_tracking_revprops(source_rev): Build an array of svn2svn-specific source-tracking revprops. """ revprops = [{'name':'svn2svn:source_uuid', 'value':source_repos_uuid}, - {'name':'svn2svn:source_url', 'value':source_url}, + {'name':'svn2svn:source_url', 'value':urllib.quote(source_url, ":/")}, {'name':'svn2svn:source_rev', 'value':source_rev}] return revprops @@ -584,7 +584,7 @@ def build_rev_map(target_url, target_end_rev, source_info): revprops[v['name']] = v['value'] if revprops and \ revprops['svn2svn:source_uuid'] == source_info['repos_uuid'] and \ - revprops['svn2svn:source_url'] == source_info['url']: + revprops['svn2svn:source_url'] == urllib.quote(source_info['url'], ":/"): source_rev = revprops['svn2svn:source_rev'] target_rev = log_entry['revision'] set_rev_map(source_rev, target_rev) @@ -964,8 +964,12 @@ def disp_svn_log_summary(log_entry): def real_main(args): global source_url, target_url, rev_map - source_url = urllib.quote(args.pop(0).rstrip("/"),"/:") # e.g. 'http://server/svn/source/trunk' - target_url = urllib.quote(args.pop(0).rstrip("/"),"/:") # e.g. 'file:///svn/target/trunk' + # Use urllib.unquote() to URL-decode source_url/target_url values. + # All URLs passed to run_svn() should go through svnclient.safe_path() + # and we don't want to end-up *double* urllib.quote'ing if the user- + # supplied source/target URL's are already URL-encoded. + source_url = urllib.unquote(args.pop(0).rstrip("/")) # e.g. 'http://server/svn/source/trunk' + target_url = urllib.unquote(args.pop(0).rstrip("/")) # e.g. 'file:///svn/target/trunk' ui.status("options: %s", str(options), level=ui.DEBUG, color='GREEN') # Make sure that both the source and target URL's are valid diff --git a/svn2svn/svnclient.py b/svn2svn/svnclient.py index 8c36415..f77a75a 100644 --- a/svn2svn/svnclient.py +++ b/svn2svn/svnclient.py @@ -79,6 +79,11 @@ def parse_svn_info_xml(xml_string): 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) + # URL-decode "url" and "repos_url" values, since all paths passed + # to run_svn() should be filtered through safe_path() and we don't + # want to *double* URL-encode paths which are constructed used these values. + d['url'] = urllib.unquote(d['url']) + d['repos_url'] = urllib.unquote(d['repos_url']) return d def get_kind(svn_repos_url, svn_path, svn_rev, action, paths): diff --git a/tests/make-ref-repo.sh b/tests/make-ref-repo.sh index ef1be38..2cabadc 100755 --- a/tests/make-ref-repo.sh +++ b/tests/make-ref-repo.sh @@ -324,12 +324,15 @@ svn mkdir -q "Module2/My Folder" echo "Module2/My Folder/file@2x.txt" >> $WC/Module2/My\ Folder/file@2x.txt echo "Module2/My Folder/%some_file.txt" >> $WC/Module2/My\ Folder/%some_file.txt echo "Module2/My Folder/file%20test.txt" >> $WC/Module2/My\ Folder/file%20test.txt +echo "Module2/My Folder/file test2.txt" >> $WC/Module2/My\ Folder/file\ test2.txt svn add -q Module2/My\ Folder/file@2x.txt@ svn add -q Module2/My\ Folder/%some_file.txt svn add -q Module2/My\ Folder/file%20test.txt +svn add -q Module2/My\ Folder/file\ test2.txt svn propset -q desc "file@2x" $WC/Module2/My\ Folder/file@2x.txt@ svn propset -q desc "%some_file" $WC/Module2/My\ Folder/%some_file.txt svn propset -q desc "file%20test" $WC/Module2/My\ Folder/file%20test.txt +svn propset -q desc "file test2" $WC/Module2/My\ Folder/file\ test2.txt svn_commit "Test 18: Add Module2/My Folder/*.txt" svn switch -q $TRUNK svn merge -q $BRANCH -- 2.45.2