#!/usr/bin/env python # # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # import sys import os import getpass from svn import client, ra, core def printer(segment, pool): path = segment.path is not None and segment.path or "(null)" print("r%d-r%d: %s" % (segment.range_start, segment.range_end, path)) def parse_args(args): argc = len(sys.argv) # parse the target URL and optional peg revision path_pieces = args[0].split('@') if len(path_pieces) > 1: peg_revision = int(path_pieces[-1]) assert peg_revision >= 0 url = '@'.join(path_pieces[:-1]) else: peg_revision = core.SVN_INVALID_REVNUM url = path_pieces[0] url = core.svn_path_canonicalize(url) # parse the revision range, if any if argc > 2: rev_pieces = args[1].split(':') num_revs = len(rev_pieces) assert num_revs < 3 if num_revs == 2: start_revision = int(rev_pieces[0]) end_revision = int(rev_pieces[1]) else: start_revision = end_revision = int(rev_pieces[0]) assert(start_revision >= 0) assert(end_revision >= 0) else: start_revision = peg_revision end_revision = 0 # validate if start_revision >= 0 \ and end_revision >= 0 \ and end_revision > start_revision: raise Exception("End revision must not be younger than start revision") if peg_revision >= 0 \ and start_revision >= 0 \ and start_revision > peg_revision: raise Exception("Start revision must not be younger than peg revision") return url, peg_revision, start_revision, end_revision def prompt_func_ssl_unknown_cert(realm, failures, cert_info, may_save, pool): print( "The certficate details are as follows:") print("--------------------------------------") print("Issuer : " + str(cert_info.issuer_dname)) print("Hostname : " + str(cert_info.hostname)) print("ValidFrom : " + str(cert_info.valid_from)) print("ValidUpto : " + str(cert_info.valid_until)) print("Fingerprint: " + str(cert_info.fingerprint)) print("") ssl_trust = core.svn_auth_cred_ssl_server_trust_t() if may_save: choice = raw_input( "accept (t)temporarily (p)permanently: ") else: choice = raw_input( "(r)Reject or accept (t)temporarily: ") if choice[0] == "t" or choice[0] == "T": ssl_trust.may_save = False ssl_trust.accepted_failures = failures elif choice[0] == "p" or choice[0] == "P": ssl_trust.may_save = True ssl_trust.accepted_failures = failures else: ssl_trust = None return ssl_trust def prompt_func_simple_prompt(realm, username, may_save, pool): username = raw_input("username: ") password = getpass.getpass(prompt="password: ") simple_cred = core.svn_auth_cred_simple_t() simple_cred.username = username simple_cred.password = password 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:]) except Exception as e: sys.stderr.write("""Usage: %s URL[@PEG-REV] [START-REV[:END-REV]] Trace the history of URL@PEG-REV, printing the location(s) of its existence between START-REV and END-REV. If START-REV is not provided, the entire history of URL@PEG-REV back to its origin will be displayed. If provided, START-REV must not be younger than PEG-REV. If END-REV is provided, it must not be younger than START-REV. (This is a wrapper around Subversion's svn_ra_get_location_segments() API.) ERROR: %s """ % (os.path.basename(sys.argv[0]), str(e))) sys.exit(1) core.svn_config_ensure(None) ctx = client.svn_client_create_context() 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), core.svn_auth_get_ssl_server_trust_prompt_provider(prompt_func_ssl_unknown_cert), client.get_username_provider(), 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) 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 ra_session = ra.open(url, ra_callbacks, None, ctx.config) ra.get_location_segments(ra_session, "", peg_revision, start_revision, end_revision, printer) if __name__ == "__main__": main()