# vim: set fileencoding=utf-8 : # # (C) 2006-2011 Guido Guenther # (C) 2012 Intel Corporation # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """Common functionality for Debian and RPM buildpackage scripts""" import os, os.path import pipes import tempfile import shutil import subprocess from gbp.command_wrappers import (CatenateTarArchive) from gbp.git.repository import GitRepository, GitRepositoryError from gbp.errors import GbpError import gbp.log # when we want to reference the index in a treeish context we call it: index_name = "INDEX" # when we want to reference the working copy in treeish context we call it: wc_names = {'WC': {'force': True, 'untracked': True}, 'WC.TRACKED': {'force': False, 'untracked': False}, 'WC.UNTRACKED': {'force': False, 'untracked': True}, 'WC.IGNORED': {'force': True, 'untracked': True}} def sanitize_prefix(prefix): """ Sanitize the prefix used for generating source archives >>> sanitize_prefix('') '/' >>> sanitize_prefix('foo/') 'foo/' >>> sanitize_prefix('/foo/bar') 'foo/bar/' """ if prefix: return prefix.strip('/') + '/' return '/' def git_archive_submodules(repo, treeish, output, prefix, comp_type, comp_level, comp_opts): """ Create tar.gz of an archive with submodules since git-archive always writes an end of tarfile trailer we concatenate the generated archives using tar and compress the result. Exception handling is left to the caller. """ prefix = sanitize_prefix(prefix) tarfile = output.rsplit('.', 1)[0] tempdir = tempfile.mkdtemp() submodule_tarfile = os.path.join(tempdir, "submodule.tar") try: # generate main tarfile repo.archive(format='tar', prefix=prefix, output=tarfile, treeish=treeish) # generate each submodule's tarfile and append it to the main archive for (subdir, commit) in repo.get_submodules(treeish): tarpath = [subdir, subdir[2:]][subdir.startswith("./")] gbp.log.debug("Processing submodule %s (%s)" % (subdir, commit[0:8])) repo.archive(format='tar', prefix='%s%s/' % (prefix, tarpath), output=submodule_tarfile, treeish=commit, cwd=subdir) CatenateTarArchive(tarfile)(submodule_tarfile) # compress the output ret = os.system("%s -%s %s %s" % (comp_type, comp_level, comp_opts, tarfile)) if ret: raise GbpError("Error creating %s: %d" % (output, ret)) finally: shutil.rmtree(tempdir) def git_archive_single(treeish, output, prefix, comp_type, comp_level, comp_opts): """ Create tar.gz of an archive without submodules Exception handling is left to the caller. """ prefix = sanitize_prefix(prefix) pipe = pipes.Template() pipe.prepend("git archive --format=tar --prefix=%s %s" % (prefix, treeish), '.-') pipe.append('%s -c -%s %s' % (comp_type, comp_level, comp_opts), '--') ret = pipe.copy('', output) if ret: raise GbpError("Error creating %s: %d" % (output, ret)) def untar_data(outdir, data): """Extract tar provided as an iterable""" popen = subprocess.Popen(['tar', '-C', outdir, '-x'], stdin=subprocess.PIPE) for chunk in data: popen.stdin.write(chunk) popen.stdin.close() if popen.wait(): raise GbpError("Error extracting tar to %s" % outdir) #{ Functions to handle export-dir def dump_tree(repo, export_dir, treeish, with_submodules, recursive=True): """Dump a git tree-ish to output_dir""" if not os.path.exists(export_dir): os.makedirs(export_dir) if recursive: paths = '' else: paths = [nam for _mod, typ, _sha, nam in repo.list_tree(treeish) if typ == 'blob'] try: data = repo.archive('tar', '', None, treeish, paths) untar_data(export_dir, data) if recursive and with_submodules and repo.has_submodules(): repo.update_submodules() for (subdir, commit) in repo.get_submodules(treeish): gbp.log.info("Processing submodule %s (%s)" % (subdir, commit[0:8])) subrepo = GitRepository(os.path.join(repo.path, subdir)) prefix = [subdir, subdir[2:]][subdir.startswith("./")] + '/' data = subrepo.archive('tar', prefix, None, treeish) untar_data(export_dir, data) except GitRepositoryError as err: gbp.log.err("Git error when dumping tree: %s" % err) return False return True def wc_index(repo): """Get path of the temporary index file used for exporting working copy""" return os.path.join(repo.git_dir, "gbp_index") def write_wc(repo, force=True, untracked=True): """write out the current working copy as a treeish object""" clone_index(repo) repo.add_files(repo.path, force=force, untracked=untracked, index_file=wc_index(repo)) tree = repo.write_tree(index_file=wc_index(repo)) return tree def drop_index(repo): """drop our custom index""" if os.path.exists(wc_index(repo)): os.unlink(wc_index(repo)) def clone_index(repo): """Copy the current index file to our custom index file""" indexfn = os.path.join(repo.git_dir, "index") if os.path.exists(indexfn): shutil.copy2(indexfn, wc_index(repo))