Files
github_name/main.py
Thor Kampefner e28ca3af9b updated
2024-10-10 18:19:56 -07:00

246 lines
7.9 KiB
Python

import time
import subprocess
import argparse
from datetime import timedelta
import datetime
import pytz
import random
from git import Repo # incorrect warning, ignore
import socket
# Set to True while debugging, otherwise False. Disables actively committing.
DEBUG = False
# on any given day, choose a random number of commits to add between:
COMMIT_MIN = 10
COMMIT_MAX = 20
HOSTNAME_MATCH = "boorb" # boorb, birb, crow, starchy
# this script works in a period of 26 weeks, starting from a specific date
# if the following is changed, must be 26 weeks from original, or the name-writing will be off
START_DATE = datetime.date(2021, 5, 9) # must be SUNDAY
TODAY = datetime.date.today()
TIME = datetime.datetime.now().time()
# the shape of my name to commit
THOR = [
[0, 0, 0, 0, 0, 0, 0], # START: 0
[0, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0], # 6
[0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0], # 12
[0, 0, 1, 1, 1, 0, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0], # 18
[0, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 1, 0, 0],
[0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0], # 24
[1, 1, 1, 1, 1, 1, 1] # insert a bar
]
THOR_LEN = THOR.__len__() # 26
def print_name_test(n: list[list[int]]):
"""Print the name. Check that it is correctly formatted."""
def l(x): return "#" if x == 1 else " "
output = ["", "", "", "", "", "", ""]
for week in n:
for i, day in enumerate(week):
output[i] += l(day)
for r in output:
print(r)
# print_name_test(THOR)
def get_root_directory() -> str:
"""return /home/t/projects/github_name"""
return "/home/t/projects/github_name"
# """return the root directory of the git repository."""
# stream = os.popen("/home/t/projects/github-name")
# stream = os.popen("git rev-parse --show-toplevel")
# root = stream.read().strip()
# stream.close()
# return root
DUMPFILE = get_root_directory() + "/.dump" # file to dump a billion commits into
def parse_args() -> argparse.Namespace:
"""
Parses command line arguments.
Returns argparse.Namespace: The parsed arguments.
accept arguments to:
- backdate commits some number of weeks
"""
parser = argparse.ArgumentParser()
parser.add_argument(
"--backdate", help="flag: number of weeks to backdate commits", default=1, type=int)
args = parser.parse_args()
if DEBUG:
print("args: %s" % args)
assert args.backdate <= 52 and args.backdate >= 1
return args
def is_name_day(date) -> bool:
"""return whether the date is a nameday."""
day = (date.weekday() + 1) % 7 # rotation correction
weeks_since_start_date = ((date - START_DATE) // 7).days
week = weeks_since_start_date % THOR_LEN
if THOR[week][day] == 0:
return False
else:
return True
def preexisting_commits(repo_dir: str, date):
"""
Count the number of Git commits in a given repository on a specific date.
:param repo_dir: Path to the Git repository directory as a string.
:param date_string: Date in 'YYYY-MM-DD' format as a string.
:return: Number of commits on the given date.
"""
# Convert date_string to datetime object to calculate the next day
# date = datetime.datetime.strptime(date_string, '%Y-%m-%d')
# next_day = date + timedelta(days=1)
# Format dates for git log command
# since_date = date.strftime('%Y-%m-%d')
# until_date = next_day.strftime('%Y-%m-%d')
tomorrow = date + timedelta(days=1)
date_string = date_str(date)
tomorrow_string = date_str(tomorrow)
since_date = f"{date_string} 00:00"
until_date = f"{tomorrow_string} 00:00"
# Run git log command to get commits between since_date and until_date
cmd = [
'git', '-C', repo_dir, 'log',
'--since={}'.format(since_date),
'--until={}'.format(until_date),
'--pretty=format:%h'
# '--pretty=oneline'
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
# Split the output by new lines to count commits.
# Filter out empty strings to avoid counting them as commits.
commit_lines = [line for line in result.stdout.strip().split('\n') if line]
n = len(commit_lines)
# print(f"{n} preexisting commits")
return n
except subprocess.CalledProcessError as e:
print(f"Error running git command: {e}")
return 0
def date_str(date) -> str:
"return the date in format 'YYYY-MM-DD' with 0-padding"
if date.day < 10:
day = "0%s" % date.day
else:
day = str(date.day)
if date.month < 10:
month = "0%s" % date.month
else:
month = str(date.month)
return "%s-%s-%s" % (date.year, month, day)
def git_commit_n_times_on_date(repo: Repo, n, date):
"""write `n` empty commits on `date`"""
# print(f"{date} writing {n} commits")
if DEBUG:
return
with open(DUMPFILE, "a") as commit_dump:
for i in range(n):
aware_datetime = datetime.datetime(
date.year, date.month, date.day, 14, i % 60, i % 59, i % 58, tzinfo=pytz.UTC)
commit_msg = "date: %s, n: %s" % (date, i)
commit_dump.write(commit_msg+"\n")
repo.index.add(DUMPFILE)
# The following is finicky. Non-aware datetimes are disallowed.
repo.index.commit(
commit_msg, commit_date=aware_datetime, author_date=aware_datetime)
def git_push(repo: Repo):
"""
Pushes changes to the remote repository using the GitPython library.
:param repo: A Repo instance representing the Git repository.
"""
try:
# Specify the remote name, assuming it's the default 'origin'
remote = repo.remote(name='origin')
push_info = remote.push()
for info in push_info:
print(f"Pushed {info.summary}")
except Exception as e:
print(f"An error occurred during git push: {e}")
def main():
print(f"\ngithub_name run on date: {TODAY}, at time: {TIME}")
hostname = socket.gethostname()
# only run on one machine, not all my machines
if hostname != HOSTNAME_MATCH:
print(f"Only to be run on {HOSTNAME_MATCH}, not {hostname}, exiting...")
return
print(f"hostname matches; continuing on {hostname}")
args = parse_args()
repo = Repo(get_root_directory())
assert not repo.bare # check that the repo is not empty
# backdate N weeks with commits.
date = max(START_DATE, TODAY - timedelta(weeks=args.backdate))
assert date > START_DATE
while date <= TODAY:
if not is_name_day(date):
print(f"{date} not nameday")
date += timedelta(days=1)
else:
# compute number of commits to add
n_preexisting = preexisting_commits(get_root_directory(), date)
if n_preexisting > COMMIT_MIN: # don't duplicate work
print(f"{date} is nameday with {n_preexisting} commits. Next day...")
date += timedelta(days=1)
continue
n_commits = random.randrange(COMMIT_MIN, COMMIT_MAX)
print(f"{date} is nameday with {n_preexisting} commits. Writing {n_commits} commits")
git_commit_n_times_on_date(repo, n_commits, date)
# github defends against DDOS attacks.
# be polite and wait 200ms before pushing the next day
git_push(repo)
date += timedelta(days=1)
time.sleep(0.2)
if __name__ == "__main__":
# dstr = date_str(TODAY)
# n = preexisting_commits(get_root_directory(),dstr)
# print(n, get_root_directory(), dstr)
main()