eobuilder/eobuilder-ctl

322 lines
12 KiB
Python
Executable File

#!/usr/bin/env python
import re
import shutil
import sys
import tarfile
import time
import os
from eobuilder import settings, VERSION
from eobuilder.cmdline import parse_cmdline, error, cat, touch, Execute
def smart_cleaning(files_path):
now = time.time()
project_files = {}
for file_path in files_path:
project_name = os.path.basename(file_path).split('_')[0]
if not project_files.has_key(project_name):
project_files[project_name] = []
project_files[project_name].append(file_path)
for project in project_files.iterkeys():
nb_versions = len(project_files[project])
if nb_versions > settings.MIN_PACKAGE_VERSIONS:
project_files[project] = \
sorted(project_files[project],
key=lambda x: os.stat(x).st_mtime)
for filename in project_files[project]:
if nb_versions > settings.MIN_PACKAGE_VERSIONS and \
os.stat(filename).st_mtime < now - settings.MIN_AGE * 86400:
os.remove(filename)
nb_versions -= 1
def clean(method):
print "+ Cleanning %s" % method
if method == "all":
shutil.rmtree(settings.ORIGIN_PATH)
shutil.rmtree(settings.PBUILDER_RESULT)
shutil.rmtree(settings.GIT_PATH)
shutil.rmtree(settings.LOCK_PATH)
elif method == "git":
shutil.rmtree(settings.GIT_PATH)
elif method == "deb":
shutil.rmtree(settings.PBUILDER_RESULT)
elif method == "archives":
shutil.rmtree(settings.ORIGIN_PATH)
elif method == "locks":
shutil.rmtree(settings.LOCK_PATH)
elif method == "smart":
results_files = []
origin_files = [os.path.join(settings.ORIGIN_PATH, f) \
for f in os.listdir(settings.ORIGIN_PATH)]
for root, dirs, files in os.walk(settings.PBUILDER_RESULT):
for fname in files:
results_files.append(os.path.join(root, fname))
smart_cleaning(results_files)
smart_cleaning(origin_files)
now = time.time()
for root, dirs, files in os.walk(settings.PBUILDER_RESULT):
for fname in files:
fname = os.path.join(root, fname)
if os.stat(fname).st_mtime < now - 365 * 86400:
os.remove(fname)
else:
error("Cleanning: unknow '%s' option" % method)
def init():
print "+ Init EO Builder"
if not os.path.exists(settings.GIT_PATH):
os.mkdir(settings.GIT_PATH, 0755)
if not os.path.exists(settings.ORIGIN_PATH):
os.mkdir(settings.ORIGIN_PATH, 0755)
if not os.path.exists(settings.PBUILDER_RESULT):
os.mkdir(settings.PBUILDER_RESULT, 0755)
if not os.path.exists(settings.LOCK_PATH):
os.mkdir(settings.LOCK_PATH, 0755)
def get_project_infos(git_project_path):
""" return a dict with project informations
"""
e = Execute()
os.chdir(git_project_path)
results = {
'name': '',
'version': '',
'fullname': '',
'ac_version': '',
'build_dir': '',
'commit_number': '',
'git_path': git_project_path,
}
if os.path.exists("setup.py"):
# Hack to support setup_requires
e.output("python setup.py --help")
results['name'] = e.output("python setup.py --name")[:-1]
results['version'] = e.output("python setup.py --version")[:-1]
results['fullname'] = e.output("python setup.py --fullname")[:-1]
elif os.path.exists("configure.ac"):
e.call("./autogen.sh")
e.call('make all')
results['name'] = e.output(
"./configure --version | head -n1 | sed 's/ configure.*//'"
)[:-1]
results['ac_version'] = e.output(
"./configure --version | head -n1 | sed 's/.* configure //'"
)[:-1]
results['version'] = results['ac_version'].replace('-', '.')
results['fullname'] = results['name']
elif os.path.exists("Makefile"):
results['name'] = e.output("make name")[:-1]
results['version'] = e.output("make version")[:-1]
results['fullname'] = e.output("make fullname")[:-1]
else:
error("Unsupported project type")
results['build_dir'] = os.path.join(
settings.EOBUILDER_TMP, results['name']
)
results['commit_number'] = e.output("git rev-parse HEAD")[:-1]
results['lock_path'] = os.path.join(settings.LOCK_PATH,
results['name'])
return results
def prepare_build(dist, project, build_branch, new):
"""
Create origin archive, update git and Debian changelog
"""
os.chdir(project['git_path'])
e = Execute(project['build_dir'])
print "+ Updating Debian branch for %s" % dist
debian_branch = "debian"
if "debian-%s" % dist in e.output("git branch -r -l"):
debian_branch = "debian-" + dist
e.call("git checkout %s" % debian_branch)
e.call("git pull")
package_name = re.search(r"^Source\s*:\s*(.*?)\n",
cat(os.path.join('debian', 'control')),
re.MULTILINE
).group(1)
last_version_file = os.path.join(project['lock_path'],
"%s_%s.last_version" % (project['name'], dist))
if os.path.exists(last_version_file):
last_debian_package_version = cat(last_version_file)
else:
last_debian_package_version = re.search(r"^Version:\s(.*?)$",
e.output("dpkg-parsechangelog"),
re.MULTILINE).group(1)
last_version = last_debian_package_version.split('-')[0]
package_version = last_debian_package_version
shutil.copy("debian/changelog", "debian/changelog.git")
e.call('dch "Eobuilder version" -v %s --distribution %s-eobuilder \
--force-distribution' % (last_debian_package_version, dist))
if last_version == project['version'] and new:
e.call('dch "Auto Debian update (commit %s)" -i \
--distribution %s-eobuilder --force-distribution' % \
(project['commit_number'], dist))
package_version = re.search(r"^Version:\s(.*?)$",
e.output("dpkg-parsechangelog"),
re.MULTILINE).group(1)
elif last_version != project['version']:
package_version = "%s-1+eob%s~eo%s+1" % \
(project['version'],
VERSION,
settings.DEBIAN_VERSIONS[dist])
e.call('dch "Auto update commit %s" -v %s \
--distribution %s-eobuilder --force-distribution' % \
(project['commit_number'], package_version, dist))
if os.path.exists(project['build_dir']):
shutil.rmtree(project['build_dir'])
os.makedirs(project['build_dir'], 0755)
shutil.move("debian/changelog", project['build_dir'])
shutil.move("debian/changelog.git", "debian/changelog")
build_file = os.path.join(project['lock_path'],
"%s_%s_%s.build" % \
(project['name'], package_version, dist))
if os.path.exists(build_file):
print "+ Already built for %s !" % dist
return None, None
origin_archive = os.path.join(settings.ORIGIN_PATH,
"%s_%s.orig.tar.bz2" % (package_name, project['version']))
if not os.path.exists(origin_archive):
print "+ Generating origin tarball ..."
os.chdir(project['git_path'])
e.call("git checkout %s" % build_branch)
if os.path.exists('setup.py'):
e.call("python setup.py clean --all")
e.call("python setup.py sdist --formats=bztar")
shutil.move("dist/%s.tar.bz2" % project['fullname'], origin_archive)
elif os.path.exists('./configure.ac'):
e.call("make dist-bzip2")
shutil.move("%s-%s.tar.bz2" % \
(project['name'], project['ac_version']),
origin_archive)
elif os.path.exists('Makefile'):
e.call("make dist-bzip2")
shutil.move("sdist/%s.tar.bz2" % project['fullname'], origin_archive)
else:
error('Unsupported project type', project['build_dir'])
print "+ Preparing Debian build (%s %s) ..." % (package_name, package_version)
e.call("git checkout " + debian_branch)
os.chdir(project['build_dir'])
project_build_path = os.path.join(project['build_dir'],
"%s-%s" % (project['name'], project['version']))
shutil.copy(origin_archive, project['build_dir'])
tar = tarfile.open('%s_%s.orig.tar.bz2' % \
(package_name, project['version']),
'r:bz2')
tar.extractall()
tar.close()
if os.path.exists("%s/debian" % project_build_path):
shutil.rmtree("%s/debian" % project_build_path)
shutil.copytree("%s/debian" % project['git_path'],
"%s/debian" % project_build_path)
os.remove("%s/debian/changelog" % project_build_path)
shutil.move("changelog", "%s/debian" % project_build_path)
return package_name, package_version
def build_project(dist, arch, project, new, package_name, package_version):
e = Execute(project['build_dir'])
pbuilder_project_result = os.path.join(settings.PBUILDER_RESULT,
'%s-%s' % (dist, arch))
project_build_path = os.path.join(project['build_dir'],
"%s-%s" % (project['name'], project['version']))
debian_repository = "%s-eobuilder" % dist
if not os.path.exists(pbuilder_project_result):
os.makedirs(pbuilder_project_result, 0755)
os.chdir(project['lock_path'])
source_build = os.path.join(project['lock_path'],
"%s_%s_%s_source.build" % \
(project['name'], project['version'], dist))
bin_build = os.path.join(project['lock_path'],
"%s_%s_%s_%s.build" % \
(project['name'], package_version, dist, arch)
)
if os.path.exists(source_build):
source_opt = '-b'
else:
source_opt = '-sa'
if new == 0 and os.path.exists(bin_build):
print "+ Already build !"
return
os.chdir(project_build_path)
print "+ Building %s %s %s %s" % \
(project['name'], project['version'], dist, arch)
e.call('DIST=%s ARCH=%s pdebuild --use-pdebuild-internal --architecture %s --debbuildopts "%s"' % \
(dist, arch, arch, source_opt))
print "+ Lock build"
touch(bin_build)
if not os.path.exists(source_build):
touch(source_build)
print "+ Sending package..."
os.chdir(pbuilder_project_result)
e.call("dput -u %s %s_%s_%s.changes" % \
(debian_repository, package_name, package_version, arch))
print "+ Updating repository ..."
e.call('ssh root@leucas.entrouvert.org "/etc/cron.hourly/process-incoming"')
def main():
new = 1
options, args = parse_cmdline()
for method in options.cleanning:
clean(method)
if options.cleanning:
sys.exit(0)
e = Execute()
init()
project_name = args[0]
git_project_path = os.path.join(settings.GIT_PATH, project_name)
if os.path.exists(git_project_path):
os.chdir(git_project_path)
if not e.output("git fetch", True):
new = 0
else:
os.chdir(settings.GIT_PATH)
e.call("git clone %s/%s.git" % \
(settings.GIT_REPOSITORY_URL, project_name))
print "+ Updating git repository and parsing configuration ..."
os.chdir(git_project_path)
e.call("git checkout %s" % options.branch)
e.call("git pull")
project = get_project_infos(git_project_path)
if not os.path.exists(project['lock_path']):
os.mkdir(project['lock_path'], 0755)
for dist in options.distrib:
package_name, package_version = prepare_build(dist, project, options.branch, new)
if package_version:
for arch in options.architectures:
build_project(dist, arch, project, new, package_name, package_version)
print "+ Add a build file to lock new build for %s" % dist
touch(os.path.join(project['lock_path'],
"%s_%s_%s.build" % (project['name'], package_version, dist)
))
last_version_file = os.path.join(project['lock_path'],
"%s_%s.last_version" % (project['name'], dist))
with open(last_version_file, 'w+') as f:
f.write(package_version)
f.close()
if __name__ == "__main__":
main()