#!/usr/bin/python3 import os, sys, subprocess, time class Commit: def __init__(self, hash, text): self.hash = hash self.text = text self.parents = [] self.time = None for line in text.split(b'\n'): words = line.split() if not words: break if words[0] == b'parent': self.parents.append(words[1].decode('utf-8')) elif words[0] == b'committer': self.time = int(words[-2].decode('utf-8')) class Gread: def __init__(self): self.git = 'git' cmd = [self.git, 'cat-file', '--batch'] self.kid = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) def read_commit_raw(self, hash): self.kid.stdin.write(hash.encode('utf-8') + b'\n') self.kid.stdin.flush() result = self.kid.stdout.readline().split() if result[1] != b'commit': raise OSError(result) length = int(result[2].decode('utf-8')) text = self.kid.stdout.read(length) nl = self.kid.stdout.read(1) if nl != b'\n': raise IOError(result, text, nl) return hash, text def read_commit(self, hash): hash, text = self.read_commit_raw(hash) return Commit(hash, text) def walk(self, start): "Yield all commits ancestral to start." stack = [start] seen = set() while stack: hash = stack.pop() if hash in seen: continue seen.add(hash) commit = self.read_commit(hash) yield commit for parent in commit.parents: stack.append(parent) def day_of(time_t): "Counts days from the epoch in UTC." return time_t // 86400 def power_of(base, n): "Return true iff n is a power of base." while n and 0 == n % base: n //= base return n == 1 if __name__ == '__main__': today = day_of(time.time()) g = Gread() for commit in g.walk('HEAD'): delta = today - day_of(commit.time) if power_of(3, delta): #print(commit.hash) subprocess.run([g.git, 'show', '-s', commit.hash]) #print(commit.text.decode('utf-8'))