]> Tony Duckles's Git Repositories (git.nynim.org) - svn2svn.git/blob - svn2svn/run/svnancest.py
Introduce 'svnancest' utility
[svn2svn.git] / svn2svn / run / svnancest.py
1 """
2 Display ancestry for a given path in an SVN repository.
3 """
4
5 from svn2svn import base_version, full_version
6 from svn2svn import ui
7 from svn2svn import svnclient
8 from parse import HelpFormatter
9 from svn2svn.run.common import find_svn_ancestors
10
11 import optparse
12 import re
13
14 options = None
15
16 def real_main(args):
17 global options
18 url = args.pop(0)
19 ui.status("url: %s", url, level=ui.DEBUG, color='GREEN')
20 info = svnclient.info(url)
21 repos_root = info['repos_url']
22 repos_path = url[len(repos_root):]
23 ancestors = find_svn_ancestors(repos_root, repos_path, options.revision)
24 if ancestors:
25 max_len = 0
26 for idx in range(len(ancestors)):
27 d = ancestors[idx]
28 max_len = max(max_len, len(d['path']+"@"+str(d['revision'])))
29 for idx in range(len(ancestors)):
30 d = ancestors[idx]
31 ui.status("[%s] %s --> %s", len(ancestors)-idx-1,
32 str(d['path']+"@"+str(d['revision'])).ljust(max_len),
33 str(d['copyfrom_path']+"@"+str(d['copyfrom_rev'])))
34 else:
35 ui.status("No ancestor-chain found: %s", repos_root+repos_path+"@"+str(options.revision))
36
37 def main():
38 # Defined as entry point. Must be callable without arguments.
39 usage = "svn2svn, version %s\n" % str(full_version) + \
40 "<http://nynim.org/projects/svn2svn> <https://github.com/tonyduckles/svn2svn>\n\n" + \
41 "Usage: %prog [OPTIONS] url\n"
42 description = """\
43 Display ancestry for a given path in an SVN repository."""
44 parser = optparse.OptionParser(usage, description=description,
45 formatter=HelpFormatter(), version="%prog "+str(full_version))
46 parser.add_option("-v", "--verbose", dest="verbosity", action="count", default=1,
47 help="enable additional output (use -vv or -vvv for more)")
48 parser.add_option("-r", "--revision", type="string", dest="revision", metavar="ARG",
49 help="revision range to replay from source_url\n"
50 "Any revision # formats which SVN understands are "
51 "supported, e.g. 'HEAD', '{2010-01-31}', etc.")
52 parser.add_option("--debug", dest="verbosity", const=ui.DEBUG, action="store_const",
53 help="enable debugging output (same as -vvv)")
54 global options
55 options, args = parser.parse_args()
56 if len(args) != 1:
57 parser.error("incorrect number of arguments")
58 if options.verbosity < 10:
59 # Expand multiple "-v" arguments to a real ui._level value
60 options.verbosity *= 10
61 if options.revision:
62 # Reg-ex for matching a revision arg (http://svnbook.red-bean.com/en/1.5/svn.tour.revs.specifiers.html#svn.tour.revs.dates)
63 rev_patt = '[0-9A-Z]+|\{[0-9A-Za-z/\\ :-]+\}'
64 rev = None
65 match = re.match('^('+rev_patt+')$', options.revision)
66 if match is None:
67 parser.error("unexpected --revision argument format; see 'svn help log' for valid revision formats")
68 rev = match.groups()
69 options.revision = rev[0] if len(rev)>0 else None
70 else:
71 options.revision = 'HEAD'
72 ui.update_config(options)
73 return real_main(args)
74
75
76 if __name__ == "__main__":
77 sys.exit(main() or 0)