Created
September 3, 2009 16:52
-
-
Save phinze/180399 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""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