Skip to content

Instantly share code, notes, and snippets.

@phinze
Created September 3, 2009 16:52
Show Gist options
  • Save phinze/180399 to your computer and use it in GitHub Desktop.
Save phinze/180399 to your computer and use it in GitHub Desktop.
"""Run a command before allowing a commit."""
import sys
import os
import re
import pprint
from bzrlib import (
branch,
errors,
export,
trace,
)
import pdb
def check_protected_paths_hook(params):
branch = params.branch
repo = branch.repository
config = branch.get_config()
protected_paths = config._get_user_option("protected_paths")
authorized_paths = config._get_user_option("authorized_paths")
new_revnos = range(params.old_revno + 1, params.new_revno)
if protected_paths is None:
return
trace.note("Checking protected paths: %s" % protected_paths)
# need tree to compare delta against
oldtree = repo.revision_tree(params.old_revid)
newtree = repo.revision_tree(params.new_revid)
delta = newtree.changes_from(oldtree)
protected_file_changes = {}
# Use both trees to check for protected files to account for things that
# might be moved/added/removed across the boundaries of the protected paths
for tree in [oldtree, newtree]:
for path in protected_paths:
# Build list of all files touched by delta within this path
# From the walkdirs docs:
# > The data yielded is of the form:
# > ((directory-relpath, directory-path-from-root, directory-fileid),
# > [(relpath, basename, kind, lstat, path_from_tree_root, file_id,
# > versioned_kind), ...]),
for dir_info, file_list in tree.walkdirs(path):
# want to check for changes that touched all files and dirs
# so combine v==== all file ids ====v v== dirid ==v
for fileid in ([f[4] for f in file_list] + [dir_info[1]]):
if delta.touches_file_id(fileid):
if not protected_file_changes.has_key(path):
protected_file_changes[path] = []
filepath = tree.id2path(fileid)
# check if already there; prevents duplicate entries
if not filepath in protected_file_changes[path]:
protected_file_changes[path].append(filepath)
if len(protected_file_changes) > 0:
msg = "Cannot commit because of change to files within protected paths as follows:\n"
for path, changed_files in protected_file_changes.items():
msg += "\t(%s): %s\n" % (path, changed_files)
raise errors.TipChangeRejected(msg)
branch.Branch.hooks.install_named_hook('pre_change_branch_tip',
check_protected_paths_hook,
"Verify protected path rules before the change is made.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment