Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 147 lines (118 sloc) 4.26 KB
#!/usr/bin/python3
import sys,re
import subprocess
import os
import stat
import tempfile
import pygit2
from time import time
from math import floor
from pprint import pprint
import gzip
def git_clone(repo, dir, branch=None):
cmd = ['git', 'clone', '-q']
if branch != None:
cmd += ['-b', branch]
cmd += [repo, dir]
rc = subprocess.call(cmd)
if rc != 0:
print('Failed ' + ' '.join(cmd))
def git_push(repo, remote, branch):
cmd = ['git', '--git-dir={}/.git'.format(repo), 'push', remote, branch]
rc = subprocess.call(cmd)
if rc != 0:
print('Failed ' + ' '.join(cmd))
def git_export(repo, branch, www):
git = ['git', '--git-dir={}/.git'.format(repo), 'archive', branch]
tar = ['tar', '-x', '-C', www]
g = subprocess.Popen(git, stdout=subprocess.PIPE)
t = subprocess.Popen(tar, stdin=g.stdout)
g.stdout.close()
rc = g.wait() + t.wait()
if rc != 0:
print('Failed ' + ' '.join(git) + ' | ' + ' '.join(tar))
for dirpath, dirnames, filenames in os.walk(www):
for dn in dirnames:
os.chmod(os.path.join(dirpath, dn), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
for fn in filenames:
os.chmod(os.path.join(dirpath, fn), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
def gzip_file(path):
with open(path, 'rb') as f_in:
with gzip.open('{}.gz'.format(path), 'wb') as f_out:
f_out.writelines(f_in)
def gzip_recursive(path):
for dirpath, dirnames, filenames in os.walk(path):
for fn in filenames:
gzip_file(os.path.join(dirpath, fn))
def jekyll(source, target):
cmd = ['jekyll', '--no-auto', source, '{}/_site'.format(target)]
rc = subprocess.call(cmd)
if rc != 0:
print('Failed ' + ' '.join(cmd))
def ensure_exists(path):
if not os.path.lexists(path):
os.makedirs(path)
def empty_dir(path):
names = os.listdir(path)
for name in names:
fullname = os.path.join(path, name)
try:
mode = os.lstat(fullname).st_mode
except os.error as e:
mode = 0
if stat.S_ISDIR(mode):
empty_dir(fullname)
os.rmdir(fullname)
else:
os.remove(fullname)
def main():
repo = os.path.realpath('.')
junk, website = os.path.split(repo)
for line in sys.stdin:
m = re.search(r'^([0-9a-f]{40}) ([0-9a-f]{40}) refs/heads/([0-9a-zA-Z]+)$', line)
if m:
branch = m.group(3)
build_branch = 'build-{}'.format(branch)
tmp_git = tempfile.TemporaryDirectory()
tmp_git_master = '{}/{}'.format(tmp_git.name, branch)
tmp_git_build = '{}/build-{}'.format(tmp_git.name, branch)
web_dir = '/var/www/{}/{}'.format(website, branch)
os.mkdir(tmp_git_master)
os.mkdir(tmp_git_build)
git_clone(repo, tmp_git_master, branch)
git_clone(repo, tmp_git_build)
master_repo = pygit2.Repository(tmp_git_master)
build_repo = pygit2.Repository(tmp_git_build)
head = build_repo.lookup_reference('HEAD')
parents = [head.resolve().oid]
try:
ref = build_repo.lookup_reference('refs/remotes/origin/{}'.format(build_branch))
parents += [ref.oid]
except KeyError as e:
# parents += []
pass
head.target = 'refs/heads/{}'.format(build_branch)
jekyll(tmp_git_master, tmp_git_build)
gzip_recursive(tmp_git_build)
build_index = build_repo.index
for dirpath, dirnames, filenames in os.walk(tmp_git_build):
m = re.search(r'\.git', dirpath)
if m:
continue
for fn in filenames:
build_index.add(os.path.relpath(os.path.join(dirpath, fn), tmp_git_build), 0)
build_index.write()
oid = build_index.write_tree()
tree = build_repo[oid]
author = pygit2.Signature('jekyll', 'jekyll@alexchamberlain.co.uk', floor(time()), 0)
committer = pygit2.Signature('git', 'git@alexchamberlain.co.uk', floor(time()), 0)
build_repo.create_commit('refs/heads/{}'.format(build_branch), author, committer, "Build", tree.oid, parents)
git_push(tmp_git_build, 'origin', build_branch)
try:
ensure_exists(web_dir)
empty_dir(web_dir)
git_export(tmp_git_build, build_branch, web_dir)
except OSError:
pass
if __name__=='__main__':
main()