datatracker/hooks/svnfind
Henrik Levkowetz 7366ca6efd Various commit hooks in use currently.
- Legacy-Id: 10557
2015-12-09 21:12:36 +00:00

160 lines
4.7 KiB
Python
Executable file

#!/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, <henrik@zinfandel.tools.ietf.org>
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])