Эх сурвалжийг харах

git-branchp: remove local branches whose remotes are gone

raylu 2 жил өмнө
parent
commit
a48be55a5d
1 өөрчлөгдсөн 37 нэмэгдсэн , 33 устгасан
  1. 37 33
      git-branchp

+ 37 - 33
git-branchp

@@ -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()