From: Frédéric Péters Date: Mon, 6 Sep 2021 12:07:49 +0000 (+0200) Subject: use internal hash calculation and only use git to amend once proper hash found X-Git-Url: https://git.0d.be/?p=git-acab.git;a=commitdiff_plain;h=acabedaa96309bb5014228e6f30f0a2930736908 use internal hash calculation and only use git to amend once proper hash found --- diff --git a/git-acab b/git-acab index b2f0af4..9645ac2 100755 --- a/git-acab +++ b/git-acab @@ -3,12 +3,12 @@ # amending the commit with a new date. import argparse +import hashlib import os +import subprocess import sys import time -import git - parser = argparse.ArgumentParser() parser.add_argument('--start', type=str, default='commit', help='now or commit') parser.add_argument('--prefix', action='store_true') @@ -16,23 +16,24 @@ parser.add_argument('--suffix', action='store_true') parser.add_argument('-q', '--quiet', action='store_true') args = parser.parse_args() -while not os.path.exists('.git'): - os.chdir('..') - if os.getcwd() == '/': - sys.stderr('failed to find a git repository') - sys.exit(1) - -def amend_commit(repo, initial_commit, start_timestamp): +def amend_commit(start_timestamp): t0 = time.time() counter = 0 + cat_file = subprocess.run(['git', 'cat-file', 'commit', 'HEAD'], capture_output=True).stdout + cat_file_lines = cat_file.splitlines() + cat_file_lines[2] = cat_file_lines[2].replace(cat_file_lines[2].rsplit(b' ', 2)[1], b'$AUTHOR__$') + cat_file_lines[3] = cat_file_lines[3].replace(cat_file_lines[3].rsplit(b' ', 2)[1], b'$COMMITER$') + hashed_bytes_template = b'commit %s\0%s\n' % ( + str(len(b'\n'.join(cat_file_lines)) + 1).encode(), + b'\n'.join(cat_file_lines), + ) authored_timestamp = start_timestamp + base_env = os.environ while True: authored_timestamp -= 1 for committed_timestamp in range(start_timestamp, authored_timestamp, -1): counter += 1 - if counter % 10000 == 0: - repo.git.prune() if not args.quiet: print( '%5d - %s - %s - [%s:%02d]' @@ -46,32 +47,45 @@ def amend_commit(repo, initial_commit, start_timestamp): end='\r', ) - commit = initial_commit.replace( - authored_date=authored_timestamp, committed_date=committed_timestamp - ) - if args.prefix and not commit.hexsha.startswith('acab'): + hashed_bytes = hashed_bytes_template.replace( + b'$AUTHOR__$', str(authored_timestamp).encode() + ).replace(b'$COMMITER$', str(committed_timestamp).encode()) + new_hash = hashlib.sha1(hashed_bytes).hexdigest() + if args.prefix and not new_hash.startswith('acab'): continue - if args.suffix and not commit.hexsha.endswith('acab'): + if args.suffix and not new_hash.endswith('acab'): continue - if 'acab' not in commit.hexsha: + if 'acab' not in new_hash: continue - repo.active_branch.set_commit(commit) - repo.git.prune() - return commit - + base_env['GIT_COMMITTER_DATE'] = time.strftime( + '%Y-%m-%d %H:%M:%S', time.localtime(committed_timestamp) + ) + subprocess.run( + [ + 'git', + 'commit', + '--no-verify', + '--amend', + '--no-edit', + '--date=%s' % time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(authored_timestamp)), + ], + capture_output=True, + env=base_env, + ) + return -repo = git.Repo() -commit = repo.commit('HEAD') if args.start == 'commit': - start_timestamp = commit.authored_date + p = subprocess.run(['git', 'show', '--format=format:%at'], capture_output=True) + start_timestamp = int(p.stdout[: p.stdout.index(b'\n')]) elif args.start == 'now': start_timestamp = int(time.time()) else: sys.stderr('unknown value for --start') sys.exit(1) -new_head = amend_commit(repo, commit, start_timestamp) +amend_commit(start_timestamp) if not args.quiet: - print('\ngot %s 🔥🚓' % new_head.hexsha) + p = subprocess.run(['git', 'rev-parse', 'HEAD'], capture_output=True) + print('\ngot %s 🔥🚓' % p.stdout.decode().strip())