Commits

Anonymous committed 5a75f24

- Initial commit.

  • Participants

Comments (0)

Files changed (1)

excluded-changesets.py

+#!/usr/bin/env python
+
+'''exclude_changesets is a Mercurial extension which sets up a pretxncommit hook.
+Any changesets to be pushed / pulled / bundled into the repository will have their
+changeset hashes compared against a list of excluded hashes in repo/.excludedchangesets.
+If any new hash is already in this file of excluded hashes then the entire
+changegroup will be rejected.
+
+Enable the exclude_changesets just like any other Mercurial extension by adding the
+following to your hgrc
+
+[extensions]
+exclude_changesets = /path/to/exclude_changesets
+'''
+
+import os.path, re
+from mercurial import hg
+
+#print "Checking For Excluded Changesets!"
+
+def getSetOfExcludedChangesets(repo):
+    try:
+        excludedChangesetsPath = os.path.join(repo.root,'.excludedchangesets')
+        f = open(excludedChangesetsPath, 'r')
+        excluded = set()
+        changesetPat = re.compile(r"(^[0-9a-fA-F]+).*")
+        for line in f:
+            m = re.match(changesetPat, line)
+            if m:
+                excluded.add(m.group(1))
+        f.close()
+        return excluded
+    except:
+        return {}
+
+def changesetIsExcluded(node, excludedChangesets):
+    for p in excludedChangesets:
+        if re.search(p, node):
+            return True
+    return False
+
+def colateChildren(ctx, colation = set()):
+    children = ctx.children()
+    colation.add(ctx.hex())
+    for childCtx in children:
+        if not childCtx.hex() in colation:
+            colateChildren(childCtx, colation)
+    return colation
+
+def checkForExcludedChangesets(ui, repo, **kwargs):
+    node = kwargs.get('node')
+    rejectedChangesets = set()
+    if node:
+        excludedChangesets = getSetOfExcludedChangesets(repo)
+        ctx = repo[node]
+        allChildren = colateChildren(ctx)
+        for childChangeset in allChildren:
+            if changesetIsExcluded(childChangeset, excludedChangesets):
+                rejectedChangesets.add(childChangeset)
+        if len(rejectedChangesets) > 0:
+            repoName = os.path.basename(repo.root)
+            if len(rejectedChangesets) == 1:
+                ui.warn('The following changeset was rejected by the repository \'%s\'\n' % repoName)
+            else:
+                ui.warn('The following %d changesets were rejected by the repository \'%s\'\n' % (len(rejectedChangesets), repoName))
+            for changeset in rejectedChangesets:
+                ui.warn('    %s\n' % changeset)
+            if (len(rejectedChangesets) < len(allChildren)):
+                if len(rejectedChangesets) == 1:
+                    ui.warn('Rebase, transplant, or otherwise transfer any changesets you have which are derived from this rejected changeset.\n')
+                else:
+                    ui.warn('Rebase, transplant, or otherwise transfer any changesets you have which are derived from these rejected changesets.\n')
+            return True # We found an excluded changeset, return True (exit code 1) which causes the changegroup addition to be aborted.
+    return False # No excluded changesets were found. The changegroup addition can go ahead.
+
+def reposetup(ui, repo):
+    ui.setconfig("hooks", "pretxnchangegroup.exclude_changesets", checkForExcludedChangesets)