322 lines
12 KiB
Python
Executable File
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()
|
|
|