Using server side hook to check files changed

Stuart Moore stuart.moore+bzr at spektrix.com
Mon Oct 29 14:53:22 UTC 2012


On 22 October 2012 17:54, Aaron Bentley <aaron at aaronbentley.com> wrote:

>  On 12-10-22 12:15 PM, Stuart Moore wrote:
> > Hello,
> >
> > We're trying to use a server-side hook to check which files are
> > changed in a commit, and if those changes are inappropriate (e.g.
> > including temporary files) prevent that change being committed.
> > (Ideally I'd also be able to examine those files' contents before
> > the commit happened.)
> >
> > I've had a real problem working out how I'm meant to do this - I've
> > been investigating the "pre_change_branch_tip" hook, but it doesn't
> > seem to have any way of geting a list of the files changed in this
> > commit.
>
>
> Not itself, but a Branch has access to all the revisions, and
> pre_change_branch_tip will tell you what revisions to look at.
>
> Using the old_revid and new_revid, you can call
> self.repository.revision_trees, to get the old and new trees, then
> Tree.compare or Tree.iter_changes to compare them.
>
>
Thank you, this seems to be giving me what I want. The last thing I'm
trying to do is get the repository's path (we have more than one repository
on the sever where this is being deployed, and it'd be good to know which
the plugin was operating in). I can't see any obvious methods on the
Repository object (which I can get from params.branch.repository). So how
do I get the repository's path?

If anyone else wants to use this, the code I've been using is below. I
haven't included the "run_filters_on_file" function as that's rather
custom, but it returns a list of strings, one for each error (reason the
commit can't happen). If there are any errors from any files, the commit
doesn't happen.  If there is an exception for another reason (e.g. our
config file has got corrupt) then it won't allow any more commits until the
situation is fixed. As far as I can tell so far, having this server side
works with the way we tend to work.

def convert_byte_string_to_unicode(bytestring):
    if(len(bytestring)==0):
        return bytestring
    # http://pypi.python.org/pypi/chardet
    import chardet
    charset = chardet.detect(bytestring)
    encoding = charset['encoding']
    if(encoding is None):
        return bytestring
    import codecs
    codec = codecs.getdecoder(encoding)
    decoded = unicode(codec(bytestring))
    return decoded

class FileInTree:
    def __init__(self, tree, path, file_id):
        self.tree = tree
        self.path = path
        self.file_id = file_id
        self.content = None

    def getContent(self):
        if(self.content is None):
            content = self.tree.get_file_text(self.file_id)
            self.content = convert_byte_string_to_unicode(content)
        return self.content

def pre_change_branch_tip(params):
    errors = []
    try:
        import os
        import bzrlib.config
        from bzrlib.errors import TipChangeRejected
        global filter_config
        # Don't interfere with uncommit.
        if params.new_revno < params.old_revno:
            return
        load_config()
        repo = params.branch.repository
        old_tree = repo.revision_tree(params.old_revid);
        new_tree = repo.revision_tree(params.new_revid);
        delta = new_tree.changes_from(old_tree);

        for added in delta.added:
            if added[2] == 'file':
                file = FileInTree(new_tree,added[0],added[1])
                errors += run_filters_on_file(file)
        for renamed in delta.renamed:
            if renamed[3] == 'file':
                file = FileInTree(new_tree,renamed[1],renamed[2])
                errors += run_filters_on_file(file)
        for modified in delta.modified:
            if modified[2]== 'file':
                file = FileInTree(new_tree, modified[0], modified[1])
                errors += run_filters_on_file(file)
    except (Exception) as e:
        import StringIO
        import logging
        exception_logger = logging.getLogger('ExceptionLogger')
        exception_msg = StringIO.StringIO()
        stream_handler = logging.StreamHandler(exception_msg);
        exception_logger.addHandler(stream_handler)
        exception_logger.exception(e);

        raise TipChangeRejected("An error occured; no more commits until
fixed." + exception_msg.getvalue())
    if(len(errors)>0):
        raise TipChangeRejected("\n".join(errors))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ubuntu.com/archives/bazaar/attachments/20121029/2acc8549/attachment.html>


More information about the bazaar mailing list