Index: machenbach/archive/archive_branches.py |
diff --git a/machenbach/archive/archive_branches.py b/machenbach/archive/archive_branches.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..c2c1c2a0475e77d35e0b6cd3c58932a89c9d3b45 |
--- /dev/null |
+++ b/machenbach/archive/archive_branches.py |
@@ -0,0 +1,87 @@ |
+#!/usr/bin/env python |
+ |
+import os |
+import re |
+import subprocess |
+import sys |
+import time |
+ |
+"""Script to archive heads under ignore/foo. |
+ |
+This adds the refs passed to the script as parents to ignore/foo and on |
+success deletes them. |
+ |
+Assumes push merge access to ignore/foo and force push access to the branches. |
+ |
+Assumes a workdir checkout with all required refs fetched. |
+ |
+archive_branches.py path/to/checkout ref1 [ref2 ...] |
+""" |
+ |
+ |
+assert len(sys.argv) > 1 |
+ |
+ |
+def git(*args, **kwargs): |
+ stdin_data = None |
+ stdin_handle = None |
+ if kwargs.get('stdin'): |
+ stdin_data = kwargs.pop('stdin') |
+ stdin_handle = subprocess.PIPE |
+ proc = subprocess.Popen(('git',) + args, |
+ stdout=subprocess.PIPE, |
+ stderr=subprocess.STDOUT, |
+ stdin=stdin_handle, |
+ **kwargs) |
+ output, _ = proc.communicate(stdin_data) |
+ assert proc.returncode == 0, output.strip() |
+ return output.strip() |
+ |
+ |
+def synthesize(refs): |
+ commits = [] |
+ for ref in refs: |
+ commits.append(git('rev-parse', ref)) |
+ |
+ name = git('config', 'user.name') |
+ email = git('config', 'user.email') |
+ |
+ # Hardcoded the tree object of the ignore/foo README file. |
+ data = ['tree c9c91bce52cd3003b6a9b0b4ae29d46210c40d51'] |
+ for commit in commits: |
+ data.append('parent %s' % commit) |
+ |
+ timestamp = int(time.time()) |
+ data.append('author %s <%s> %s +0000' % (name, email, timestamp)) |
+ data.append('committer %s <%s> %s +0000' % (name, email, timestamp)) |
+ data.append('') |
+ |
+ # We don't really care about the commit message. |
+ data.append('Placeholder commit\n') |
+ data.append('Refs merged:\n' + '\n '.join(refs) + '\n') |
+ |
+ return git('hash-object', '-t', 'commit', '-w', '--stdin', |
+ stdin='\n'.join(data)) |
+ |
+ |
+assert os.path.exists(sys.argv[1]) |
+os.chdir(sys.argv[1]) |
+ |
+refs = sys.argv[2:] |
+assert refs, 'Provide at least one ref' |
+ |
+# Make sure we only archive roll branches. |
+for ref in refs: |
+ assert re.match(r'\d*\.\d*\.\d*', ref) |
+ |
+# Merge into ignore/foo. |
+git('fetch', 'origin', 'refs/heads/ignore/foo') |
+merge = synthesize(['FETCH_HEAD'] + refs) |
+git('push', 'origin', '%s:refs/heads/ignore/foo' % merge) |
+ |
+# Delete refs. |
+del_specs = ( |
+ ['push', 'origin', '--force'] + |
+ [':refs/heads/%s' % ref for ref in refs] |
+) |
+git(*del_specs) |