#!/usr/bin/env python import sys import os import subprocess # This server-side pre-receive hook is to be put and activated in all modules # that depend on the common submodule. # # It will check whether any modifications to the common 'submodule file' has a # a valid commit SHA1 that exists in the common module. def commit_exists(sha1, gitdir): """Returns True if the sha1 is a valid commit in the given git directory""" # FIXME: We're using 'git show' for the time being, but there's a small # risk that there might be a valid SHA1 for a non-commit object. env = os.environ.copy() env["GIT_DIR"] = gitdir sub = subprocess.Popen(["git", "show", sha1], env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) while True: res = sub.poll() if res != None: return res == 0 # location of the common git module COMMON_GIT_DIR = "/git/gstreamer/common.git" pushvalid = True error_badcommon = False error_badcommit = False print "=> Checking for integrity of common submodule changes" print for line in sys.stdin.readlines(): # ref is the ref to be modified # old is the old commit it was pointing to # new is the new commit it was pointing to old, new, ref = line.split(' ', 2) # 1. Get the latest change to common (if there was any changes) sub = subprocess.Popen(["git", "diff", "%s..%s" % (old, new, ), "--", "common"], stdout=subprocess.PIPE) stdout, stderr = sub.communicate() if stdout != "": # Format of submodule special files # Subproject commit # we get a diff, therefore only grab the last line lastline = stdout.strip().rsplit('\n',1)[-1] if not lastline.startswith("+Subproject commit"): # this is bad, it means the diff has changed to something completely # different continue subsha1 = lastline.rsplit(' ', 1)[-1] print " Pack wants common to point to", subsha1 if not commit_exists(subsha1, COMMON_GIT_DIR): print " /!\\ Commit does not exist in common git module /!\\" print " /!\\ for ref", ref pushvalid = False break # 2. Figure out if that commit exists in the common submodule # (use GIT_DIR to execute commands in that directory) # Get the commit message sub = subprocess.Popen(["git", "log", "--format=%s", "%s..%s" % (old, new, )], stdout=subprocess.PIPE) stdout, stderr = sub.communicate() if stdout != "": for line in stdout.strip().rsplit('\n',1): if line.startswith("!"): error_badcommit = True pushvalid = False break if pushvalid: print " Incoming packet valid, proceeding to actual commit" sys.exit(0) else: if error_badcommit: print " Attempting to push commits with commit messages that start" print " with '!'. Commit messages starting with '!' are reserved" print " for private branches to prevent the commits from accidentally" print " getting to the main repository." if error_badcommon: print " Attempting to push commits containing modifications to common" print " that have not been commited to the actuall common module." print print " First push your changes to common/ before pushing the changes" print " to the module using it." sys.exit(-1)