#!/usr/bin/env python # -*- python -*- """ NAME %(program)s - find a filename close to a given a SVN repository commit SYNOPSIS %(program)s [OPTIONS] REPO REV NAME DESCRIPTION Supposing we have a subversion repository containing a trunk and various branches. Given the repository url and the revision number of a commit, what is the top of the branch? $(program)s attempts to answer this by letting you search for a specific file name which is assumed to be unique within the branch and be situated at the top of the branch subtree. %(options)s AUTHOR Written by Henrik Levkowetz, COPYRIGHT Copyright 2015 Henrik Levkowetz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. There is NO WARRANTY; not even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. """ import sys, os.path, getopt, re version = "0.13" program = os.path.basename(sys.argv[0]) progdir = os.path.dirname(sys.argv[0]) # ---------------------------------------------------------------------- # Parse options options = "" for line in re.findall("\n +(if|elif) +opt in \[(.+)\]:\s+#(.+)\n", open(sys.argv[0]).read()): if not options: options += "OPTIONS\n" options += " %-16s %s\n" % (line[1].replace('"', ''), line[2]) options = options.strip() # with ' < 1:' on the next line, this is a no-op: if len(sys.argv) <= 1: help() try: opts, files = getopt.gnu_getopt(sys.argv[1:], "dfDhv", ["dirchange", "filechange", "dirpath", "help", "version",]) except Exception, e: print "%s: %s" % (program, e) sys.exit(1) # ---------------------------------------------------------------------- # Handle options # set default values, if any opt_dirpath = False opt_dirchange = False opt_filechange = False opt_verbose = False # ---------------------------------------------------------------------- def help(msg=None, err=0): if msg: print(msg+'\n') print(__doc__ % globals()) sys.exit(err) # handle individual options for opt, value in opts: if opt in ["-h", "--help"]: # Output this help, then exit help() elif opt in ["-v", "--version"]: # Output version information, then exit print program, version sys.exit(0) elif opt in ["-d", "--dirchange"]: # Look only for directory changes opt_dirchange = True elif opt in ["-f", "--filechange"]: #Look only for file changes opt_filechange = True elif opt in ["-D", "--dirpath"]: # Output the directory path, not the file path opt_dirpath = True # if neither filechange nor dirchange have been specified, look for both if not opt_filechange and not opt_dirchange: opt_filechange = True opt_dirchange = True # ---------------------------------------------------------------------- def help(msg=None, err=0): if msg: print(msg+'\n') print(__doc__ % globals()) sys.exit(err) # ---------------------------------------------------------------------- def say(s): sys.stderr.write("%s\n" % (s)) # ---------------------------------------------------------------------- def note(s): if opt_verbose: sys.stderr.write("%s\n" % (s)) # ---------------------------------------------------------------------- def die(s, error=1): sys.stderr.write("\n%s: Error: %s\n\n" % (program, s)) sys.exit(error) # ---------------------------------------------------------------------- # Bad args if len(files) < 3: help("Not enogh arguments\n\nExpected %s REPO REV NAME" %program, 1) # ---------------------------------------------------------------------- # The program itself import pysvn #import debug repo, rev, name = files changeset = pysvn.Transaction(repo, rev, True) changed = changeset.changed() # Each dictionary entry is a tuple, with elements as follows: CHG_ACTION, CHG_KIND, CHG_TEXTMOD, CHG_PROPMOD = range(4) node = None for key in changed: if opt_dirchange and changed[key][CHG_KIND] == pysvn.node_kind.dir: node = key break if opt_filechange and changed[key][CHG_KIND] == pysvn.node_kind.file: node = '/'.join(key.split('/')[:-1]) break while node: #debug.show('node') list = changeset.list(node) if name in list: if opt_dirpath: print node else: sys.stdout.write(node) sys.stdout.write('/') sys.stdout.write(name) sys.stdout.write('\n') break node = '/'.join(node.split('/')[:-1])