Rewrite package.sh as a python script

pull/7/head
Jesus Alvarez 12 years ago
parent a960910379
commit 595d3c815c
  1. 379
      package.py
  2. 109
      package.sh

@ -0,0 +1,379 @@
#!/usr/bin/env python
# encoding: utf-8
import argparse
import subprocess
import os
import re
import logging
import datetime
import sys
import glob
SIGNING_KEY = '0EE7A126'
# Prefix for logging output
PREFIX = '[>>>]'
from logging import Formatter, getLogger, StreamHandler, DEBUG
# This function uses ansi escape sequences.
# http://bluesock.org/~willg/dev/ansi.html#sequences
# http://en.wikipedia.org/wiki/ANSI_escape_code
# http://docs.python.org/reference/lexical_analysis.html
# `\033[` is the escape sequence character. `\033` is octal.
ATTR_CODES = {
'bold': '1',
'italic': '3',
'strike': '9',
'underline': '4',
'erase': '\033[K', # Clear to the end of the line
'reset': '\033[0m', # All attributes off
}
FG_COLOR_CODES = {
'black': 30,
'red': 31,
'green': 32,
'yellow': 33,
'blue': 34,
'magenta': 35,
'cyan': 36,
'white': 37,
'default': 38,
}
BG_COLOR_CODES = {
'bgred': 41,
'bgblack': 40,
'bggreen': 42,
'bgyellow': 43,
'bgblue': 44,
'bgmagenta': 45,
'bgcyan': 46,
'bgwhite': 47,
'bgdefault': 49,
'bggrey': 100,
}
def ansi_builder(text, fgcolor, bgcolor, attr):
"""Wrap text in an ansi escape sequence, with bolding.
:color: The color to wrap the text in.
:text: The text to wrap.
:attr: The attribute to wrap the text in.
"""
fgcc = ''
if fgcolor:
assert(fgcolor in FG_COLOR_CODES)
fgcc = str(FG_COLOR_CODES[fgcolor]) + ';'
bgcc = ''
if bgcolor:
assert(bgcolor in BG_COLOR_CODES)
bgcc = str(BG_COLOR_CODES[bgcolor]) + ';'
attrc = ''
if attr:
assert(attr in ATTR_CODES)
attrc = ATTR_CODES[attr] + ';'
ccds = attrc + fgcc + bgcc
# print('033[{}m{}{}'.format(ccds[:-1], text, ATTR_CODES['reset'][1:]))
return '\033[{}m{}{}'.format(ccds[:-1], text, ATTR_CODES['reset'])
OUTPUT_PREFIX = ansi_builder(PREFIX, 'cyan', '', 'bold') + ': '
class _ANSIFormatter(Formatter):
"""Convert a `logging.LogReport' object into colored text, using ANSI
escape sequences.
"""
def format(self, record):
mtype = ''
if record.levelname is 'INFO':
mtype = ansi_builder(record.levelname + ' ', 'cyan', '', 'bold')
elif record.levelname is 'WARNING':
mtype = ansi_builder(record.levelname, 'yellow', '', 'bold')
elif record.levelname is 'ERROR':
mtype = ansi_builder(record.levelname, 'red', '', 'bold')
elif record.levelname is 'CRITICAL':
mtype = ansi_builder(record.levelname, '', 'bgred', 'bold')
elif record.levelname is 'DEBUG':
mtype = ansi_builder(record.levelname, '', 'bggrey', 'bold')
else:
mtype = ansi_builder(record.levelname, 'white', '', 'bold')
tdate = get_time_string()
return OUTPUT_PREFIX + mtype + ': ' + tdate + ': ' + record.msg
def init_logging(level, logger=getLogger(), handler=StreamHandler()):
logger = logging.getLogger()
fmt = _ANSIFormatter()
handler.setFormatter(fmt)
logger.addHandler(handler)
if not level:
level = logging.WARN
logger.setLevel(level)
init_logging(level=DEBUG)
logger = logging.getLogger(__name__)
def get_time_string():
"""Returns a formatted time string.
"""
now = datetime.datetime.now()
return now.strftime('%a %b %d %H:%M:%S %Y')
def _logger(text, text_attr='', note='', note_attr='', note_fgcolor='',
note_bgcolor='', date=True, prefix=True):
"""Prints to stdout.
_logger is responsible for making pretty output and is used throughout the
entire program. Any whitepsace characters at the start or ends of the line
are preserved. So lines containing '\r' will overlap. This is useful for
progress bars and such.
:text: The text to output.
:text_attr: ANSI attribute to wrap text with.
:note: String to append to the text.
:note_attr: ANSI attribute to wrap note with.
:note_fgcolor: Color of the appended note.
:note_bgcolor: Background color of the note.
:date: If true, the date will be appended.
:prefix: If true, the date and OUTPUT_PREFIX will be displayed.
"""
prefix = OUTPUT_PREFIX
if date:
prefix = prefix + get_time_string() + ': '
if note:
note = ansi_builder(note, note_fgcolor, note_bgcolor, note_attr) + ' '
pad_re = re.match(r'(\s*).*(\s*)', text)
if pad_re:
pre_pad = pad_re.group(1)
pos_pad = pad_re.group(2)
end = '\r' if text[-1] == '\r' else '\n'
stext = text.strip()
if text_attr:
stext = ansi_builder(stext, '', '', text_attr)
output = ''.join((pre_pad, prefix, note, stext, pos_pad,
ATTR_CODES['reset'], end))
sys.stdout.write(output)
def log_begin(text):
"""Logs output with [Begin] appended to the start of the string.
:text: The message to write to stdout.
"""
_logger(text, '', '[Begin]', 'bold', 'white', 'bgcyan')
def log_done(text):
"""Logs output with [Done] appended to the start of the string.
:text: The message to write to stdout.
"""
_logger(text, '', '[FINISHED]', 'bold', 'white', 'bgcyan')
def log_noprefix(text):
"""Logs output without the prefix.
:text: The message to write to stdout.
"""
_logger(text, date=False, prefix=False)
def log_note(text, note, fgcolor, bgcolor):
"""Logs output without the prefix.
:text: The message to write to stdout.
"""
assert(fgcolor in FG_COLOR_CODES)
assert(bgcolor in BG_COLOR_CODES)
_logger(text, '', note, 'bold', fgcolor, bgcolor)
def log(text):
"""Prints to stdout with timestap and OUTPUT_PREFIX.
:text: The message to write to stdout.
"""
_logger(text, date=True, prefix=True)
parser = argparse.ArgumentParser(description='Magically add packages to a '
'repository.')
parser.add_argument('-r', nargs='?', required=True,
help='Chroot path.')
parser.add_argument('-l', nargs='?', required=True,
help='Chroot version.')
parser.add_argument('-c', action='store_true', default=False,
help='Clean the chroot before building or installing.')
parser.add_argument('-I', nargs='+',
help='A list of packages to install into the chroot'
'environment before building.')
parser.add_argument('packages', nargs='+',
help='A list of packages to build. For all packages, use '
'"all"')
args = parser.parse_args()
def set_new_sums():
"""Get new sums and change in the PKGBUILD
"""
for pkg in ['spl-utils', 'spl', 'zfs-utils', 'zfs']:
os.chdir('devsrc/' + pkg)
proc = subprocess.Popen(['makepkg', '-g'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
sout, serr = proc.communicate()
smsum = re.findall(r'\ *(?:sha|md)\d+sums=\([\w\s\n\']+\)',
sout.decode('UTF-8'))
if len(smsum) > 1:
logger.warning('RE pattern returned more than one occurrence!')
with open('PKGBUILD', 'r') as p_file:
pkg_conf = p_file.read()
pfsum = re.findall(r'\ *(?:sha|md)\d+sums=\([\w\s\n\']+\)', pkg_conf)
if pfsum and pfsum[0] != smsum[0]:
log_noprefix('Generating hashes for "' + pkg + '"')
new_pconf = pkg_conf.replace(pfsum[0], smsum[0])
log_noprefix('Writing updated PKGBULID')
with open('PKGBUILD', 'w') as p_file:
p_file.write(new_pconf)
else:
log_noprefix('Hashes up-to-date for "' + pkg + '"')
os.chdir('../../')
def clean_chroot():
"""Creates a clean chroot.
"""
copydir = args.r + '/' + args.l
if args.c:
proc = subprocess.call(['sudo', 'mkdir', '-p', copydir])
if proc > 0:
logger.warning('Could not create chroot diretory "' + copydir +
'"')
log_noprefix('Creating clean chroot at "' + copydir + '"')
proc = subprocess.call(['sudo', 'rsync', '-a', '--delete', '-q', '-W',
'-x', args.r + '/root/', copydir])
if proc > 0:
logger.warning('A problem occurred creating the clean chroot!')
def install_packages():
"""Installs the packages passed as arguments into the chroot.
"""
copydir = args.r + '/' + args.l
for pkg in args.I:
log_noprefix('Copying "' + pkg + '" to the chroot')
proc = subprocess.call(['sudo', 'cp', pkg, copydir + '/' +
os.path.basename(pkg)])
pac_cmd = 'pacman -U /{} --noconfirm'.format(os.path.basename(pkg))
cmd = ['sudo', '/usr/sbin/mkarchroot', '-r', pac_cmd, copydir]
log_noprefix('Installing "' + pkg + '"')
proc = subprocess.call(cmd)
if proc > 0:
logger.warning('There was a problem installing the package!')
proc = subprocess.call(['sudo', 'rm', copydir + '/' +
os.path.basename(pkg)])
if proc > 0:
logger.warning('There was a problem removing the package!')
def move_sources():
"""Move the sources to a temporary directory.
"""
pass
if __name__ == '__main__':
log_note('Welcome!', 'package.py', 'white', 'bgred')
set_new_sums()
if args.c:
clean_chroot()
if args.I:
install_packages()
# # for arch in ('i686', 'x86_64'):
for pkg in ('spl-utils', 'spl', 'zfs-utils', 'zfs'):
os.chdir('devsrc/' + pkg)
proc = subprocess.call(['sudo', 'makechrootpkg', '-r', args.r,
'-l', args.l, '--', '-i'])
if proc > 0:
logger.warning('There was a problem building "' + pkg + '"')
bpkg = glob.glob('*.pkg.tar.xz')
if bpkg:
bpkg = bpkg[0]
else:
bpkg = ''
proc = subprocess.call(['gpg', '--detach-sign', '-u', '0EE7A126',
'--use-agent', bpkg])
if proc > 0:
logger.warning('There was a problem signing "' + pkg + '"')
proc = subprocess.call(['makepkg', '-S', '-f'])
if proc > 0:
logger.warning('There was a problem building the source '
'package for"' + pkg + '"')
vers = re.search(r'[\w-]+-([\d\w\._]+-[\d])-(?:i686|x86_64)', bpkg)
if vers:
proc = subprocess.call('mkdir -p ../../backup/testing/' +
vers.group(1), shell=True)
if proc > 1:
logger.warning('There was an error creating the backup '
'directory')
log('Moving "' + bpkg + '" to "backup/testing/' + vers.group(1) +
'"')
proc = subprocess.call('mv ' + bpkg + '* ../../backup/testing/' +
vers.group(1) + '/', shell=True)
if proc > 1:
logger.warning('There was a problem copying the package to '
'the backup directory')
source = glob.glob('*.src.tar.gz')
if source:
source = source[0]
else:
source = ''
proc = subprocess.call('mv ' + source + ' ../../backup/testing/x86_64/'
+ vers.group(1) + '/', shell=True)
if proc > 1:
logger.warning('There was a problem copying the package source to '
'the backup directory')
# Cleanup
proc = subprocess.call('rm -r *.log src/', shell=True)
if proc > 1:
logger.warning('There was a problem cleaning the working files')
os.chdir('../../')

@ -1,109 +0,0 @@
#!/bin/sh
unset ALL_OFF BOLD BLUE GREEN RED YELLOW
if [[ -t 2 && ! $USE_COLOR = "n" ]]; then
# prefer terminal safe colored and bold text when tput is supported
if tput setaf 0 &>/dev/null; then
ALL_OFF="$(tput sgr0)"
BOLD="$(tput bold)"
BLUE="${BOLD}$(tput setaf 4)"
GREEN="${BOLD}$(tput setaf 2)"
RED="${BOLD}$(tput setaf 1)"
YELLOW="${BOLD}$(tput setaf 3)"
else
ALL_OFF="\e[1;0m"
BOLD="\e[1;1m"
BLUE="${BOLD}\e[1;34m"
GREEN="${BOLD}\e[1;32m"
RED="${BOLD}\e[1;31m"
YELLOW="${BOLD}\e[1;33m"
fi
fi
readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
plain() {
local mesg=$1; shift
printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
msg() {
local mesg=$1; shift
printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
msg2() {
local mesg=$1; shift
printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
warning() {
local mesg=$1; shift
printf "${YELLOW}==> WARNING:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
error() {
local mesg=$1; shift
printf "${RED}==> ERROR:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
chroot_build() {
awk -v newsums="$(makepkg -g)" '
BEGIN {
if (!newsums) exit 1
}
/^[[:blank:]]*(md|sha)[[:digit:]]+sums=/,/\)[[:blank:]]*$/ {
if (!i) print newsums; i++
next
}
1
' PKGBUILD > PKGBUILD.new && mv PKGBUILD{.new,}
sudo makechrootpkg -r /opt/chroot/extra-x86_64 -l zfs64 -- -i
if [[ $? != "0" ]]; then
error "Failed building \"${1}\""
exit 1;
fi
gpg --detach-sign -u 0EE7A126 --use-agent ${1}-*.pkg.tar.xz
if [[ $? != "0" ]]; then
warning "Failed signing \"${1}\""
return 2;
fi
makepkg -Sfc
if [[ $? != "0" ]]; then
warning "Failed creating package sources for \"${1}\""
return 3;
fi
}
mkdir -p backup/new/{x86_64,i686,sources}
packages="spl-utils spl zfs-utils zfs"
for pkg in $packages; do
cd "devsrc/${pkg}"
msg "Building ${pkg}"
chroot_build "${pkg}"
cd ../../
done
msg "Moving sources to backup/new/sources"
find devsrc/ -type f -iname '*.src.tar*' -exec mv {} backup/new/sources/ \;
msg "Moving x86_64 packages to backup/new/x86_64"
find devsrc/ -type f -iname '*x86_64.pkg.tar*' -exec mv {} backup/new/x86_64/ \;
msg "Rotating backup archives"
mv backup/latest/sources/* backup/sources/
mv backup/new/sources/* backup/latest/sources/
mv backup/latest/x86_64/* backup/packages/x86_64/
mv backup/new/x86_64/* backup/latest/x86_64/
rm -rf backup/new
msg "Copying packages to the repository directories"
cp backup/latest/x86_64/* x86_64/
msg "Adding packages to the repository"
NPKGS=$(find backup/latest/x86_64/ -type f -iname '*.pkg.tar.xz' -printf "%f ")
cd x86_64/
repo-add -s -v -d archzfs.db.tar.xz $NPKGS
Loading…
Cancel
Save