How do I set up a hook in HG / Mercurial that gets dictated by the repository?

旧街凉风 提交于 2019-12-23 15:28:54

问题


I have a need for a hook to run after update (this will build the solution they have updated) and I don't want to have to add that hook manually for each person that clones my central repository.

When someone first clones my central repository, is it possible to include hooks into that clone? It seems that the .hgrc file doesn't get cloned automatically.

I did read about site-wide hooks, but as far as I understand it, they work on each created repository, where I only want to have the hooks on some repos.


回答1:


As Rudi already said, this is (thankfully) not possible for security reasons.

However, you can reduce the per-clone workload to set up hooks manually: Ship the hook scripts as part of your repository, e.g. in a directory .hghooks, and additionally include a script in your repo which sets up these hooks in a clone's hgrc. Each coworker now only needs to call the setup script once per clone.




回答2:


This is not possible, since that hooks do not propagate to clones is a security measure. If this were possible, one could set up a rouge repository, which runs arbitrary commands on any machine where the repo is cloned.

See http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html#id402330 for more details.




回答3:


This will allow for centralised per-repo hooks, with a single setup step per user. It will however cause problems for users who are disconnected from the network. An alternative if you tend to have disconnected developers (or ones over high-latency/low bandwidth links) would be to have a repo containing the hooks, and set up each user's global hgrc to point into that repo (and require regular pulls from a central hook repo).

Note that I treat the ID of the first commit as the "repo ID" - this assumes that the first commit in each repository is unique in some way - contents or commit message. If this is not the case you could do the same thing but applying it over the first N commits - but you would then have to account for repos that have fewer than N commits - can't just take repo[:5] for example as newer commits would then change the repo ID. I'd personally suggest that the first commit should probably be a standard .ignore file with a commit message unique to that repo.

  1. Have a central shared_hgrc file, accessible from a network share (or in a hook repo).

  2. Each user's global hgrc has:

    %include /path/to/shared_hgrc
    
  3. Create a shared repository of python hook modules. The hooks must be written in python.

  4. Create your hook functions. In each function, check which repo the hook has been called on by checking the ID of the first commit:

    # hooktest.py
    
    import mercurial.util
    
    FOOBAR_REPO = 'b88c69276866d73310be679b6a4b40d875e26d84'
    
    ALLOW_PRECOMMIT_REPOS = set((
        FOOBAR_REPO,
    ))
    
    def precommit_deny_if_wrong_repo(ui, repo, **kwargs):
        """Aborts if the repo is not allowed to do this.
        The repo ID is the ID of the first commit to the repo."""
    
        repo_id = repo[0].hex().lower()
    
        if repo_id not in ALLOW_PRECOMMIT_REPOS:
            raise mercurial.util.Abort('Repository denied: %s' % (repo_id,))
    
        ui.status('Repository allowed: %s\n' % (repo_id,))
    
    def precommit_skip_if_wrong_repo(ui, repo, **kwargs):
        """Skips the hook if the repo is not allowed to do this.
        The repo ID is the ID of the first commit to the repo."""
    
        repo_id = repo[0].hex().lower()
    
        if repo_id not in ALLOW_PRECOMMIT_REPOS:
            ui.debug('Repository hook skipped: %s\n' % (repo_id,))
            return
    
        ui.status('Repository hook allowed: %s\n' % (repo_id,))
    
  5. In the shared_hgrc file, set up the hooks you need (make sure you qualify the hook names to prevent conflicts):

    [hooks]
    pre-commit.00_skip = python:/path/to/hooktest.py:precommit_skip_if_wrong_repo
    pre-commit.01_deny = python:/path/to/hooktest.py:precommit_deny_if_wrong_repo
    



回答4:


As @Rudi said first, it can't be done for security reasons.

With some prior setup you can make it so that hooks are run on clone, but putting a hook with a repo-relative path in /etc/mercurial or in each user's ~/.hgrc, which in a corporate setting can be done via your system management tools or by building a custom Mercurial installer. In a non-corporate setting follow @Oben's advice and provide the scripts and a readme.



来源:https://stackoverflow.com/questions/7462154/how-do-i-set-up-a-hook-in-hg-mercurial-that-gets-dictated-by-the-repository

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!