[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

controling commit behavior to tags path

From: Wesley Leggette <wleggette_at_cleversafe.com>
Date: 2006-07-11 19:20:51 CEST


I have the following standard structure in my repository:


In another repository (repos2), I use svn:externals to reference a
specific tag of repos1. My concern is that I don't want people to
accidentally commit changes to the tag referenced by the externals

I've written a pre-commit hook to prevent changes to paths below
tags/<dir>, where <dir> is a specific tag. The hook still allows
deletion, addition, and copying from tags.

Any comments? Suggestions for improvements? Anybody see anything else
that does this?

Wesley Leggette
Cleversafe, LLC

#!/usr/bin/env python

import sys
import os
import os.path
from svn import repos, fs, delta, core

### DEAR USER: Please populate the test_props() and test_path_change()
### to do your bidding.

def test_props(props):
  """Validate the PROPS (a dictionary mapping property names to
  values) set on the transaction. Return 0 if all is well, non-zero

  ### Test the transaction (revision-to-be) properties. If there is
  ### bogosity, write to sys.stderr and return non-zero.

  return 0

def test_path_change(path, change):
  """Validate the CHANGE made to PATH in the transaction. Return 0
  if all is well, non-zero otherwise."""
  # The svn_node_kind of the path.
  item_kind = change.item_kind

  # Non-zero iff properties of this path were changed.
  prop_changes = change.prop_changes

  # Non-zero iff path is a file, and its text was changed.
  text_changed = change.text_changed

  # The location of the previous revision of this resource, if any.
  base_path = change.base_path
  base_rev = change.base_rev

  # Non-zero iff this change represents an addition (see
  # base_path/base_rev for whether it was an addition with history).
  added = change.added

  ### Test the path change as you see fit. If there is bogosity,
  ### write to sys.stderr and return non-zero.
  # Debug statements
  #sys.stderr.write('item_kind = ' + str(item_kind) + '\n')
  #sys.stderr.write('prop_changes = ' + str(prop_changes) + '\n')
  #sys.stderr.write('text_changed = ' + str(text_changed) + '\n')
  #sys.stderr.write('base_path = ' + str(base_path) + '\n')
  #sys.stderr.write('base_rev = ' + str(base_rev) + '\n')
  #sys.stderr.write('added = ' + str(added) + '\n')
  #sys.stderr.write('change.path = ' + str(change.path) + '\n')
  #sys.stderr.write(str(dir(change)) + '\n')
  if change.path is not None:
    if change.path.startswith('tags'):
      if text_changed or prop_changes:
        sys.stderr.write('Modifying tags is prohibited. Try commiting in a branch.\n')
        return 1
      destpath = change.path.lstrip('tags')
      if len(destpath) > 0 and destpath[0] == '/':
        destpath = destpath.lstrip('/')
        if destpath.find('/') >= 0:
          #sys.stderr.write('destpath = ' + str(destpath) + '\n')
          #sys.stderr.write('FOUND = ' + str(destpath.find('/')) + '\n')
          sys.stderr.write('Tag modifications must occur below the tag directory.\n')
          sys.stderr.write('If you are adding or modifying directories or files \n')
          sys.stderr.write('within a tag, try commiting in a branch.\n')
          return 1
  if base_path is not None:
    if base_path.startswith('tags'):
      if change.path is None:
        srcpath = base_path.lstrip('tags')
        if len(srcpath) > 0 and srcpath[0] == '/':
          srcpath = srcpath.lstrip('/')
          if srcpath.find('/') >= 0:
            #sys.stderr.write('srcpath = ' + str(srcpath) + '\n')
            sys.stderr.write('Deleting files and directories within a tag is prohibited.\n')
            sys.stderr.write('Try commiting in a branch.\n')
            return 1

  return 0

def main(pool, repos_dir, txn, config_fp):
  # Construct a ChangeCollector to fetch our changes.
  fs_ptr = repos.svn_repos_fs(repos.svn_repos_open(repos_dir, pool))
  root = fs.txn_root(fs.open_txn(fs_ptr, txn, pool), pool)
  cc = repos.ChangeCollector(fs_ptr, root, pool)

  # Call the transaction property validator. Might as well get the
  # cheap checks outta the way first.
  retval = test_props(cc.get_root_props())
  if retval:
    return retval

  # Generate the path-based changes list.
  e_ptr, e_baton = delta.make_editor(cc, pool)
  repos.svn_repos_replay(root, e_ptr, e_baton, pool)

  # Call the path change validator.
  changes = cc.get_changes()
  paths = changes.keys()
  paths.sort(lambda a, b: core.svn_path_compare_paths(a, b))
  for path in paths:
    change = changes[path]
    retval = test_path_change(path, change)
    if retval:
      return retval
  return 0

def _usage_and_exit():
  sys.stderr.write("USAGE: %s REPOS-DIR TXN-NAME\n" % (sys.argv[0]))

if __name__ == '__main__':
  if len(sys.argv) < 3:
  sys.exit(core.run_app(main, sys.argv[1], sys.argv[2], None))

To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Tue Jul 11 19:22:31 2006

This is an archived mail posted to the Subversion Users mailing list.