Skip to content

Instantly share code, notes, and snippets.

@wware
Last active April 18, 2019 20:05
Show Gist options
  • Save wware/9eae07798605c50714acf0863672c800 to your computer and use it in GitHub Desktop.
Save wware/9eae07798605c50714acf0863672c800 to your computer and use it in GitHub Desktop.
A breadth-first-search decorator to search the history of a git repository to find the most recent commit(s) satisfying some criterion.
import os
from functools import wraps
def cmd(x):
return os.popen(x).read().strip()
def predecessors(hash):
return cmd("git log --pretty=%P -n 1 {0}".format(hash)).split(" ")
def is_a_merge_commit(hash):
return len(predecessors(hash)) > 1
def find_ancestors(criterion):
"""
Going back thru the history of a git repository starting at a given
root, search for commits that satisfy a given criterion. Return a set
of satisfying commits from the first generation where any satisfy.
:param criterion: a criterion function
:type criterion: Callable
:return:
"""
@wraps(criterion)
def breadth_first_search(root):
visited = current = {root}
while True:
nextgen = set()
for hash in current:
nextgen = nextgen.union(predecessors(hash))
nextgen = nextgen - visited
if len(nextgen) == 0:
return None
winners = {hash for hash in nextgen if criterion(hash)}
if len(winners) > 0:
return winners
current = nextgen
visited = visited.union(nextgen)
return breadth_first_search
@find_ancestors
def most_recent_merge_prior_to(hash):
# alternatively:
# return "Merge" in cmd("git show {0}".format(hash))
return is_a_merge_commit(hash)
# This is a branch we use at my job, here only for purposes of illustration.
develop = cmd("git rev-parse origin/develop")
print most_recent_merge_prior_to(develop)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment