#!/usr/bin/env python
#
# Adds missing svn:needs-lock property directly on repository files.
# Direct access to the repository is required.
#
# Specify -d to perform a "dry run".  This just indicates what needs to be done.
# Specify -i REGEXP to only include file names matching the regular expression.
#   (Defaults to all files)
# Specify -e REGEXP to exclude file names matching the regular expression.
# Specify -r REV to operate only on the files added in the specified revision.
#
# Example: Add the svn:needs-lock property to any non .c files in /trunk
#
#   add-needs-lock.py -i "/trunk/.*" -e ".*\.c" /path/to/repo
#
#
# Copyright 2008 Kevin Radke <kmradke@gmail.com>
#
# Licensed 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.
#
# $HeadURL$
# $LastChangedDate$
# $LastChangedBy$
# $LastChangedRevision$

import sys
import os
import re
import getopt
try:
  my_getopt = getopt.gnu_getopt
except AttributeError:
  my_getopt = getopt.getopt

try:
  import svn.core
  import svn.fs
  import svn.repos
except ImportError as e:
  sys.stderr.write("ERROR: Unable to import Subversion's Python bindings: '%s'\n" % e)
  sys.exit(1)

# Walk a tree returning file paths
################################################################################
def walk_tree(root, path):
  files = []

  for name in svn.fs.dir_entries(root, path).keys():
    full = path + '/' + name
    if svn.fs.is_dir(root, full):
      subfiles = walk_tree(root, full)
      for subfile in subfiles:
        files.append(subfile)
    else:
      files.append(full)

  return files

# Get a list of files
################################################################################
def get_file_list(root, included, excluded):
  files = []
  regexp = re.compile(included)
  regexpout = re.compile(excluded)
  all_files = walk_tree(root, '')

  for path in all_files:
    # Must match include and not match exclude regexp
    if regexp.match(path) and not regexpout.match(path):
      files.append(path)

  return files

# Get a list of files added in the specified revision
################################################################################
def get_rev_file_list(revroot, included, excluded):
  files = []
  regexp = re.compile(included)
  regexpout = re.compile(excluded)

  for path, change in svn.fs.paths_changed(revroot).iteritems():
    # Must be an add or replace
    if (change.change_kind == svn.fs.path_change_add
        or change.change_kind == svn.fs.path_change_replace):
      # Must be a file
      if (svn.fs.check_path(revroot, path) == svn.core.svn_node_file):
        # Must match include and not match exclude regexp
        if regexp.match(path) and not regexpout.match(path):
          files.append(path)

  return files

# Add missing svn:needs-lock to any files directly in the repository
################################################################################
def addneedslock(repos_path, uname='', commitmsg='', included='.*', excluded='^$', rev=None, dryrun=None):
  canon_path = svn.core.svn_path_canonicalize(repos_path)
  repos_ptr = svn.repos.open(canon_path)
  fsob = svn.repos.fs(repos_ptr)

  # Get the HEAD revision
  headrev = svn.fs.youngest_rev(fsob)
  root = svn.fs.revision_root(fsob, headrev)

  if rev is None:
    # Get list of all latest files in repository
    files = get_file_list(root, included, excluded)
  else:
    # Get list of all files changed in the revision
    revroot = svn.fs.revision_root(fsob, rev)
    files = get_rev_file_list(revroot, included, excluded)

  interesting_files = []

  print('Searching ' + str(len(files)) + ' file(s)...')

  for path in files:
    locked_val = svn.fs.get_lock(fsob, path)
    # Must not be locked
    if locked_val is None:
      needslock_prop_val = svn.fs.node_prop(root, path, svn.core.SVN_PROP_NEEDS_LOCK)
      # Must not already have svn:needs-lock property set
      if needslock_prop_val is None:
        interesting_files.append(path)

  if interesting_files:
    if dryrun:
      for path in interesting_files:
        print("Need to add svn:needs-lock to '" + path + "'")
    else:
      # open a transaction against HEAD
      headrev = svn.fs.youngest_rev(fsob)
      txn = svn.repos.fs_begin_txn_for_commit(repos_ptr, headrev, uname, commitmsg)
      root = svn.fs.txn_root(txn)

      for path in interesting_files:
        print("Adding svn:needs-lock to '" + path + "'...")
        svn.fs.change_node_prop(root, path, svn.core.SVN_PROP_NEEDS_LOCK, '*')

      conflict, newrev = svn.fs.commit_txn(txn)
      if conflict:
        raise Exception("Conflict encountered (%s)" % conflict)

      print('Created revision: ', newrev)
  else:
    print('Nothing changed.  Current Revision: ', headrev)


################################################################################
def usage():
  print("USAGE: add-needs-lock.py [-u username] [-m commitmsg] [-i includeregexp] [-e excluderegexp] [-r REV] [-d] REPOS-PATH")
  sys.exit(1)


################################################################################
def main():
  opts, args = my_getopt(sys.argv[1:], 'u:m:i:e:r:d')

  uname = 'svnadmin'
  commitmsg = 'Added missing svn:needs-lock property'
  included = '.*'
  excluded = '^$'
  rev = None
  dryrun = None

  for name, value in opts:
    if name == '-u':
      uname = value
    if name == '-m':
      commitmsg = value
    if name == '-i':
      included = value
    if name == '-e':
      excluded = value
    if name == '-r':
      rev = int(value)
    if name == '-d':
      print('Performing dry run...')
      dryrun = 1
  if rev is None:
    print('Searching all files...')
  else:
    print('Searching revision: ' + str(rev) + '...')
  if len(args) == 1:
    addneedslock(args[0], uname, commitmsg, included, excluded, rev, dryrun)
  else:
    usage()

if __name__ == '__main__':
  main()
  sys.exit(0)
