|
|
@@ -3,36 +3,40 @@
|
|
|
|
|
|
import subprocess
|
|
|
import sys
|
|
|
-import time
|
|
|
-
|
|
|
-force = len(sys.argv) == 2 and sys.argv[1] == '-f'
|
|
|
-
|
|
|
-output = subprocess.check_output(['git', 'branch', '--merged', 'origin/master', '-a'], universal_newlines=True)
|
|
|
-branches = []
|
|
|
-for line in output.split('\n'):
|
|
|
- if not line.startswith(' ') or ' -> ' in line:
|
|
|
- continue
|
|
|
- line = line[2:]
|
|
|
- if line.startswith('remotes/origin/'):
|
|
|
- line = line[8:]
|
|
|
- branches.append(line)
|
|
|
-
|
|
|
-day_seconds = 24 * 60 * 60
|
|
|
-now = time.time()
|
|
|
-cutoff = now - 30 * day_seconds
|
|
|
-for branch in branches:
|
|
|
- if branch == 'origin/master':
|
|
|
- continue
|
|
|
- output = subprocess.check_output(['git', 'show', branch, '-s', '--format=%at %ct'], universal_newlines=True)
|
|
|
- if not output.endswith('\n'):
|
|
|
- raise Exception()
|
|
|
- timestamp = max(map(int, output[:-1].split(' ', 2)))
|
|
|
- if timestamp > cutoff:
|
|
|
- print('ignoring', branch)
|
|
|
- continue
|
|
|
-
|
|
|
- print('deleting %s (%.1f days old)' % (branch, (now - timestamp) / day_seconds))
|
|
|
- if branch.startswith('origin/'):
|
|
|
- subprocess.check_call(['git', 'push', 'origin', ':' + branch[7:]])
|
|
|
- else:
|
|
|
- subprocess.check_call(['git', 'branch', '-d', branch])
|
|
|
+
|
|
|
+def main():
|
|
|
+ delete = len(sys.argv) == 2 and sys.argv[1] == '-d'
|
|
|
+
|
|
|
+ remotes = all_remotes()
|
|
|
+
|
|
|
+ to_delete = []
|
|
|
+ print('will delete:')
|
|
|
+ for local, remote in iter_locals():
|
|
|
+ if remote not in remotes:
|
|
|
+ to_delete.append(local)
|
|
|
+ sys.stdout.buffer.write(b'\t' + local)
|
|
|
+ print()
|
|
|
+
|
|
|
+ if delete and len(to_delete) > 0:
|
|
|
+ subprocess.run([b'git', b'branch', b'-D'] + to_delete, check=True)
|
|
|
+
|
|
|
+def all_remotes():
|
|
|
+ refs = subprocess.run(['git', 'for-each-ref', '--format=%(refname:short)', 'refs/remotes'],
|
|
|
+ capture_output=True, check=True)
|
|
|
+ return frozenset(refs.stdout.rstrip(b'\n').split(b'\n'))
|
|
|
+
|
|
|
+def iter_locals():
|
|
|
+ refs = subprocess.run(['git', 'for-each-ref', '--format=%(refname:short) %(upstream)', 'refs/heads'],
|
|
|
+ capture_output=True, check=True)
|
|
|
+ for line in refs.stdout.split(b'\n'):
|
|
|
+ if not line:
|
|
|
+ continue
|
|
|
+ local, remote = line.split(b' ', 1)
|
|
|
+ if not remote:
|
|
|
+ continue
|
|
|
+ assert remote.startswith(b'refs/remotes/')
|
|
|
+ remote = remote.removeprefix(b'refs/remotes/')
|
|
|
+ yield local, remote
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ main()
|