Created
March 30, 2018 15:00
-
-
Save jpigree/74dd9d671098c410dc4adb2c858f3113 to your computer and use it in GitHub Desktop.
Check Git branches duration in a repository
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import os | |
import sys | |
import operator | |
from subprocess import check_output, check_call, STDOUT | |
from datetime import timedelta | |
from time import time | |
FNULL = open(os.devnull, 'w') | |
MAIN_BRANCHES = ["develop", "master"] | |
BLUE = '\033[94m' | |
GREEN = '\033[92m' | |
YELLOW = '\033[93m' | |
RED = '\033[91m' | |
BOLD = '\033[1m' | |
DEFAULT = '\033[0m' | |
class BranchInfos(object): | |
def __init__(self, name, duration, commits, committer): | |
self.name = name | |
self.duration = duration | |
self.commits = commits | |
self.committer = committer | |
def __lt__(self, other): | |
return self.duration < other.duration | |
def feature_branches(): | |
branches = check_output( | |
["git", "ls-remote", "--heads", "origin"], | |
universal_newlines=True) | |
for branch in branches.split("\n"): | |
if branch: | |
branch = branch.split()[1].strip().replace("refs/heads/", "") | |
if branch not in MAIN_BRANCHES: | |
yield branch | |
def merge_base(base, branch): | |
return check_output( | |
["git", "merge-base", branch, base], | |
universal_newlines=True).strip() | |
def branch_commits(base, branch): | |
return check_output( | |
["git", "rev-list", "{}..{}".format(base, branch)], | |
universal_newlines=True).strip().split() | |
def commit_date(commit): | |
return check_output( | |
["git", "show", "-s", "--format=%ct", commit], | |
universal_newlines=True).strip() | |
def commit_committer(commit): | |
return check_output( | |
["git", "show", "-s", "--format=%cn", commit], | |
universal_newlines=True).strip() | |
def remote_branch(branch): | |
return "origin/{}".format(branch) | |
def branch_infos(base, branch): | |
r_branch = remote_branch(branch) | |
r_base_branch = remote_branch(base) | |
base_commit = merge_base(r_base_branch, r_branch) | |
commits = branch_commits(base_commit, r_branch) | |
duration = 0 | |
committer = commit_committer(base_commit) | |
if commits: | |
first_commit_date = commit_date(commits[-1]) | |
duration = int(time()) - int(first_commit_date) | |
committer = commit_committer(commits[0]) | |
return BranchInfos( | |
name=branch, | |
duration=duration, | |
commits=commits, | |
committer=committer) | |
def show_branches_duration(base): | |
infos = dict() | |
for branch in feature_branches(): | |
infos[branch] = branch_infos(base, branch) | |
for key, value in sorted(infos.items(), key=operator.itemgetter(1)): | |
if value == 0: | |
print("{}{}{}({}{}{}) is fully merged{} inside {}".format( | |
BLUE, | |
key, | |
DEFAULT, | |
BOLD, | |
value.committer, | |
DEFAULT, | |
GREEN, | |
base)) | |
else: | |
delta = timedelta(seconds=value.duration) | |
print( | |
"{}{}{}({}{}{}) oldest unmerged commit is {}{} days old{}".format( | |
BLUE, | |
key, | |
DEFAULT, | |
BOLD, | |
value.committer, | |
DEFAULT, | |
YELLOW, | |
delta.days, | |
DEFAULT)) | |
if __name__ == "__main__": | |
if len(sys.argv) > 1: | |
REPO_PATH = sys.argv[1] | |
if os.path.isdir(REPO_PATH): | |
os.chdir(REPO_PATH) | |
check_call(["git", "fetch"], stdout=FNULL, stderr=STDOUT) | |
show_branches_duration("develop") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment