Search code examples
mercurialmercurial-subreposmercurial-hook

disable/deprecate (but not delete) mercurial repository


My colleagues and I use several repositories that live on a centralized (ubuntu, if it matters) server. For several of our projects, we include the same 4 repositories as subrepositories in lots of different projects. This can be a little irritating to constantly be pushing/pulling/merging 4 different subrepositories across lots of different projects because it takes a while to transfer everything over the network, etc.

I would like to combine these 4 repositories into one master repository that can be included in all of our projects going forward. The challenge is that I do not want to delete the old subrepositories as that would break existing projects that are working just fine.

It would be great if there were a way to designate these old repositories as deprecated or, at the very least, make it impossible for my colleagues to push any new changesets to these repositories and display a helpful error message. Is this possible, perhaps with mercurial hooks as this tangential Q/A suggests?


Solution

  • I wasn't terribly inclined to manipulate permissions with the filesystem because that does not provide a very useful error message to my colleagues. I was able to accomplish this (in mercurial 2.3) with the prechangeset hook. First, create a file (.hg/deprecated.py, in this case) to store the hook in the shared repository you wish to deprecate:

    # .hg/deprecated.py
    import sys
    import textwrap
    
    # print out a helpful error message in red to make it obvious things
    # are not working
    msg = "ERROR: Pushing changesets into this repository is no longer supported. "
    msg += "This package has been merged into the /path/to/new/repo repository."
    print('\033[%im%s\033[0m'%(31, textwrap.fill(msg)))
    
    # return a non-zero exit code to disallow the changeset to be added to the 
    # target repository
    sys.exit(1)
    

    Then tell mercurial to execute this hook before any changeset is added to the repository by adding the following to your .hg/hgrc file:

    # .hg/hgrc
    [hooks]
    prechangegroup.deprecate = python .hg/deprecate.py
    

    This solution simultaneously alerts the coder that the repository is not active, instructs the coder where the changes should be committed, and prevents the coder from committing code to a deprecated repository. While this isn't as permanent solution as manipulating filesystem permissions, it does instruct people where to find the new repository. Hope someone else finds this useful!