--- /dev/null
+<refentry id="man.gbp.import.orig.rpm">
+ <refentryinfo>
+ <address>
+ &rpm-email;
+ </address>
+ <author>
+ &rpm-firstname;
+ &rpm-surname;
+ </author>
+ </refentryinfo>
+ <refmeta>
+ <refentrytitle>gbp-import-orig-rpm</refentrytitle>
+ &rpm-mansection;
+ </refmeta>
+ <refnamediv>
+ <refname>gbp-import-orig-rpm</refname>
+ <refpurpose>Import an upstream source into a git repository</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ &gbp-import-orig-rpm;
+
+ &man.common.options.synopsis;
+ <arg><option>--upstream-version=</option><replaceable>VERSION</replaceable></arg>
+ <arg><option>--[no-]merge</option></arg>
+ <arg><option>--upstream-branch=</option><replaceable>BRANCH-NAME</replaceable></arg>
+ <arg><option>--packaging-branch=</option><replaceable>BRANCH-NAME</replaceable></arg>
+ <arg><option>--packaging-dir=</option><replaceable>DIRECTORY</replaceable></arg>
+ <arg><option>--[no-]create-missing-branches</option></arg>
+ <arg><option>--upstream-vcs-tag=</option><replaceable>TAG-NAME</replaceable></arg>
+ <arg><option>--[no-]sign-tags</option></arg>
+ <arg><option>--keyid=</option><replaceable>GPG-KEYID</replaceable></arg>
+ <arg><option>--upstream-tag=</option><replaceable>TAG-FORMAT</replaceable></arg>
+ <arg rep='repeat'><option>--filter=</option><replaceable>PATTERN</replaceable></arg>
+ <arg><option>--[no-]pristine-tar</option></arg>
+ <arg><option>--[no-]filter-pristine-tar</option></arg>
+ <arg><option>--pristine-tarball-name=<replaceable>FILENAME</replaceable></option></arg>
+ <arg><option>--orig-prefix=<replaceable>PREFIX</replaceable></option></arg>
+ <arg><option>--postimport=<replaceable>CMD</replaceable></option></arg>
+ <arg><option>--[no-]interactive</option></arg>
+ <group choice="plain">
+ <arg choice="plain"><replaceable>filename</replaceable></arg>
+ <arg choice="plain"><replaceable>url</replaceable></arg>
+ </group>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ &gbp-import-orig-rpm; is an basically identical to the &gbp-import-orig;
+ tool, with only some rpm-specific functionality added and some
+ Debian-specific functionality removed.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ <replaceable>filename</replaceable>: A file in the local
+ file system. Gzip, bzip2, lzma and xz compressed tar
+ archives, zip archives and already unpacked source trees are
+ supported.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <replaceable>url</replaceable>: The tarball is downloaded
+ from a <replaceable>http</replaceable>
+ or <replaceable>https</replaceable> <replaceable>url</replaceable>.
+ This needs the python3-request package installed.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ &gbp-import-orig-rpm; tries to download the archive from a remote server if
+ a remote URL is given. In addition, if no
+ <replaceable>UPSTREAM-SOURCE</replaceable> is given &gbp-import-orig-rpm;
+ takes the archive URI from the spec file - this makes it possible to import
+ a new upstream version just by bumping the version number in the spec file
+ and running &gbp-import-orig-rpm; (assuming that the spec file contains
+ a full URL for the archive and its filename automatically follows the
+ package version e.g. by using the %{version} macro, of course).
+ </para>
+ <para>
+ The sources are placed on the upstream branch (default:
+ <replaceable>upstream</replaceable>) and tagged.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ &man.common.options.description;
+
+ <varlistentry>
+ <term><option>--upstream-version</option>=<replaceable>VERSION</replaceable></term>
+ <term><option>-u</option><replaceable>VERSION</replaceable></term>
+ <listitem>
+ <para>
+ The upstream version number.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--[no-]merge</option></term>
+ <listitem>
+ <para>
+ Merge the upstream branch to the packaging branch after import.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--upstream-branch</option>=<replaceable>BRANCH-NAME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ The branch in the &git; repository the upstream sources are put
+ onto. Default is <replaceable>upstream</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--packaging-branch</option>=<replaceable>BRANCH-NAME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ The branch in the &git; repository the package is being developed on,
+ default is <replaceable>master</replaceable>. After importing the new
+ sources on the upstream branch, &gbp-import-orig-rpm; will try to
+ merge the new version onto this branch.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--packaging-dir=</option><replaceable>DIRECTORY</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Subdirectory that contains the RPM packaging files.
+ &gbp-import-orig-rpm; uses this to try to find a spec file which, in
+ turn, is used to get the upstream source archive URI if one is not
+ specified on the command line.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--[no-]create-missing-branches</option>
+ </term>
+ <listitem>
+ <para>
+ Create missing upstream branch if it does not exist.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--upstream-vcs-tag</option>=<replaceable>TAG-NAME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Add <replaceable>TAG-NAME</replaceable> as additional parent to the
+ commit of the upstream tarball. Useful when upstream uses git and you
+ want to link to it's revision history.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--[no-]sign-tags</option>
+ </term>
+ <listitem>
+ <para>
+ GPG sign all created tags.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--keyid=</option><replaceable>GPG-KEYID</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Use this <option><replaceable>keyid</replaceable></option>
+ for gpg signing tags.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--upstream-tag=</option><replaceable>TAG-FORMAT</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Use this tag format when tagging upstream versions,
+ default is <replaceable>upstream/%(version)s</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--import-msg=</option><replaceable>MSG-FORMAT</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Use this format string for the commit message when importing upstream
+ versions, default is
+ <replaceable>Imported Upstream version %(version)s</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--filter=</option><replaceable>PATTERN</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Filter out files glob-matching
+ <option><replaceable>pattern</replaceable></option>. This
+ option can be given multiple times.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--[no-]pristine-tar</option>
+ </term>
+ <listitem>
+ <para>
+ Generate <command>pristine-tar</command> delta file.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--[no-]filter-pristine-tar</option>
+ </term>
+ <listitem>
+ <para>
+ If using a filter, also filter the files out of the tarball
+ passed to <command>pristine-tar</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--pristine-tarball-name=</option><replaceable>FILENAME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Filename to record to pristine-tar. This does not alter the tarball
+ content, just the filename with which the tarball can be checked out
+ with pristine-tar.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--orig-prefix=</option><replaceable>PREFIX</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Prefix (directory) to be used when importing sources into
+ pristine-tar. Only takes effect when <option>--pristine-tar</option>
+ is used. Special value <replaceable>auto</replaceable> causes &gbp-import-orig-rpm; to guess
+ the prefix when importing unpacked sources, or, not to change the
+ prefix when importing source archives.
+ </para>
+ <note>
+ <para>
+ Using this option will alter the source archive that is imported to
+ pristine-tar! That is, pristine-tar does not produce and identical
+ copy of the original tarball (but the mangled tarball, instead).
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--postimport=<replaceable>CMD</replaceable></option></term>
+ <listitem>
+ <para>
+ Run <replaceable>CMD</replaceable> after the import. The
+ hook gets the following environment variables passed:
+ <variablelist>
+ <varlistentry>
+ <term><envar>GBP_BRANCH</envar></term>
+ <listitem><para>
+ The name of the packaging branch
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><envar>GBP_TAG</envar></term>
+ <listitem><para>
+ The name of the just created upstream tag
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><envar>GBP_UPSTREAM_VERSION</envar></term>
+ <listitem><para>
+ The just imported upstream version
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--[no-]interactive</option></term>
+ <listitem>
+ <para>
+ Run command interactively, i.e. ask package name and version if
+ needed.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1>
+ <title>EXAMPLES</title>
+ <para>
+ Download and import a new upstream version using the informantion from the
+ spec file
+ </para>
+ <screen>
+ &gbp-import-orig-rpm;
+ </screen>
+ <para>
+ After manually downloading an upstream import it
+ </para>
+ <screen>
+ &gbp-import-orig-rpm; ../upstream-tarball-0.1.tar.gz
+ </screen>
+ <para>
+ Import unpacked sources
+ </para>
+ <screen>
+ &gbp-import-orig-rpm; --orig-prefix=upstream-0.1 ../upstream/
+ </screen>
+ </refsect1>
+ <refsect1>
+ &man.gbp.config-files;
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <xref linkend="man.gbp.buildpackage.rpm"/>,
+ <xref linkend="man.gbp.pq.rpm"/>,
+ <xref linkend="man.gbp.import.srpm"/>,
+ <xref linkend="man.gbp.rpm.ch"/>,
+ <xref linkend="man.gbp.conf"/>,
+ &man.seealso.common;
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>AUTHOR</title>
+ <para>
+ &rpm-username; &rpm-email;
+ </para>
+ </refsect1>
+</refentry>
+<!-- LocalWords: xz lzma bzip gzip tarball
+ -->
import glob
import os
+import subprocess
+import stat
+import re
+import zipfile
import gbp.command_wrappers as gbpc
+from gbp.pkg.archive import Archive
from gbp.pkg.compressor import Compressor
from gbp.pkg.pkgpolicy import PkgPolicy
@cvar _unpacked: path to the unpacked source tree
@type _unpacked: string
"""
- def __init__(self, name, unpacked=None, pkg_policy=PkgPolicy, sig=None):
+ def __init__(self, name, unpacked=None, pkg_policy=PkgPolicy, sig=None,
+ prefix=None):
self._orig = False
+ self._tarball = False
self._pkg_policy = pkg_policy
self._path = name
+ if not os.path.exists(self._path):
+ raise GbpError('UpstreamSource: unable to find %s' % self._path)
self.unpacked = unpacked
self._sig = sig
+ (self._filename_base,
+ self._archive_fmt,
+ self._compression) = Archive.parse_filename(os.path.basename(self.path))
+ self._prefix = prefix
+ if self._prefix is None:
+ self._determine_prefix()
self._check_orig()
if self.is_dir():
"""
if self.is_dir():
self._orig = False
+ self._tarball = False
return
+ self._tarball = True if self.archive_fmt == 'tar' else False
+
parts = self._path.split('.')
try:
if parts[-1] == 'tgz':
"""
return self._orig
+ def is_tarball(self):
+ """
+ @return: C{True} if source is a tarball, C{False} otherwise
+ @rtype: C{bool}
+ """
+ return self._tarball
+
def is_dir(self):
"""
@return: C{True} if if upstream sources are an unpacked directory,
def path(self):
return self._path.rstrip('/')
+ @staticmethod
+ def _get_topdir_files(file_list):
+ """Parse content of the top directory from a file list
+
+ >>> UpstreamSource._get_topdir_files([])
+ set()
+ >>> UpstreamSource._get_topdir_files([('-', 'foo/bar')])
+ {('d', 'foo')}
+ >>> UpstreamSource._get_topdir_files([('d', 'foo/'), ('-', 'foo/bar')])
+ {('d', 'foo')}
+ >>> UpstreamSource._get_topdir_files([('d', 'foo'), ('-', 'foo/bar')])
+ {('d', 'foo')}
+ >>> UpstreamSource._get_topdir_files([('-', './foo/bar')])
+ {('d', 'foo')}
+ """
+ topdir_files = set()
+ for typ, path in file_list:
+ split = re.sub('^(?:./|../)*', '', path).split('/')
+ if len(split) == 1:
+ topdir_files.add((typ, path))
+ else:
+ topdir_files.add(('d', split[0]))
+ return topdir_files
+
+ def _determine_prefix(self):
+ """Determine the prefix, i.e. the "leading directory name"""
+ self._prefix = ''
+ if self.is_dir():
+ # For directories we presume that the prefix is just the dirname
+ self._prefix = os.path.basename(self.path.rstrip('/'))
+ else:
+ files = []
+ if self._archive_fmt == 'zip':
+ archive = zipfile.ZipFile(self.path)
+ for info in archive.infolist():
+ typ = 'd' if stat.S_ISDIR(info.external_attr >> 16) else '?'
+ files.append((typ, info.filename))
+ elif self._archive_fmt == 'tar':
+ popen = subprocess.Popen(['tar', '-t', '-v', '-f', self.path],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out, _err = popen.communicate()
+ if popen.returncode:
+ raise GbpError("Listing tar archive content failed")
+ for line in out.splitlines():
+ fields = line.split(None, 5)
+ files.append((fields[0][0], fields[-1].decode()))
+ else:
+ raise GbpError("Unsupported archive format %s, unable to "
+ "determine prefix for '%s'" %
+ (self._archive_fmt, self.path))
+ # Determine prefix from the archive content
+ topdir_files = self._get_topdir_files(files)
+ if len(topdir_files) == 1:
+ typ, name = topdir_files.pop()
+ if typ == 'd':
+ self._prefix = name
+
+ @property
+ def archive_fmt(self):
+ """Archive format of the sources, e.g. 'tar'"""
+ """
+ >>> UpstreamSource('foo/bar.tar.gz').archive_fmt
+ 'tar'
+ >>> UpstreamSource('foo.bar.zip').archive_fmt
+ 'zip'
+ >>> UpstreamSource('foo.bar.baz').archive_fmt
+ """
+ return self._archive_fmt
+
+ @property
+ def compression(self):
+ """Compression format of the sources, e.g. 'gzip'"""
+ """
+ >>> UpstreamSource('foo/bar.tar.gz').compression
+ 'gzip'
+ >>> UpstreamSource('foo.bar.zip').compression
+ >>> UpstreamSource('foo.bz2').compression
+ 'bzip2'
+ """
+ return self._compression
+
+ @property
+ def prefix(self):
+ """Prefix, i.e. the 'leading directory name' of the sources"""
+ return self._prefix
+
@property
def signaturefile(self):
return self._sig
# unpackArchive already printed an error message
raise GbpError
- def pack(self, newarchive, filters=None):
+ def pack(self, newarchive, filters=None, newprefix=None):
"""
Recreate a new archive from the current one
@type newarchive: string
@param filters: tar filters to apply
@type filters: array of strings
+ @param newprefix: new prefix, None implies that prefix is not mangled
+ @type newprefix: string or None
@return: the new upstream source
@rtype: UpstreamSource
"""
if not isinstance(filters, list):
raise GbpError("Filters must be a list")
+ run_dir = os.path.dirname(self.unpacked.rstrip('/'))
+ pack_this = os.path.basename(self.unpacked.rstrip('/'))
+ transform = None
+ if newprefix is not None:
+ newprefix = newprefix.strip('/.')
+ if newprefix:
+ transform = 's!%s!%s!' % (pack_this, newprefix)
+ else:
+ transform = 's!%s!%s!' % (pack_this, '.')
try:
- unpacked = self.unpacked.rstrip('/')
repackArchive = gbpc.PackTarArchive(newarchive,
- os.path.dirname(unpacked),
- os.path.basename(unpacked),
- filters)
+ run_dir,
+ pack_this,
+ filters,
+ transform=transform)
repackArchive()
except gbpc.CommandExecFailed:
# repackArchive already printed an error
--- /dev/null
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2006, 2007, 2009, 2011, 2015, 2016, 2019 Guido Günther <agx@sigxcpu.org>
+# 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, please see
+# <http://www.gnu.org/licenses/>
+#
+"""Import a new upstream version into a Git repository"""
+
+import os
+import re
+import sys
+import tempfile
+
+import gbp.command_wrappers as gbpc
+from gbp.rpm import (RpmUpstreamSource, NoSpecError, guess_spec, guess_spec_repo)
+from gbp.rpm.policy import RpmPkgPolicy
+from gbp.rpm.git import (GitRepositoryError, RpmGitRepository)
+from gbp.config import GbpOptionParserRpm, GbpOptionGroup, no_upstream_branch_msg
+from gbp.errors import GbpError
+from gbp.format import format_str
+from gbp.pkg.archive import Archive
+import gbp.log
+from gbp.scripts.common import ExitCodes
+from gbp.scripts.common.import_orig import (cleanup_tmp_tree, ask_package_name,
+ ask_package_version)
+from gbp.scripts.common.hook import Hook
+from gbp.scripts.import_srpm import download_file
+
+
+def prepare_sources(source, pkg_name, pkg_version, pristine_commit_name,
+ filters, filter_pristine, prefix, tmpdir):
+ """
+ Prepare upstream sources for importing
+
+ Unpack, filter and repack sources for importing to git and to pristine-tar.
+
+ @param source: original upstream sources
+ @type source: C{UpstreamSource}
+ @param pkg_name: package name
+ @type pkg_name: C{str}
+ @param pkg_version: upstream version of the package
+ @type pkg_version: C{str}
+ @param pristine_commit_name: archive filename to commit to pristine-tar
+ @type pristine_commit_name: C{str} or C{None}
+ @param filters: filter to exclude files
+ @type filters: C{list} of C{str}
+ @param filter_pristine: filter pristine-tar, too
+ @type filter_pristine: C{bool}
+ @param prefix: prefix (i.e. leading directory of files) to use in
+ pristine-tar, set to C{None} to not mangle orig archive
+ @type prefix: C{str} or C{None}
+ @param tmpdir: temporary working dir (cleanup left to caller)
+ @type tmpdir: C{str}
+ @return: path to prepared source tree and tarball to commit to pristine-tar
+ @rtype: C{tuple} of C{str}
+ """
+ pristine = None
+ # Determine parameters for pristine tar
+ pristine_filters = filters if filters and filter_pristine else None
+ pristine_prefix = None
+ filtered = source
+ if prefix is not None and prefix != 'auto':
+ prefix_subst = {'name': pkg_name,
+ 'version': pkg_version,
+ 'upstreamversion': pkg_version}
+ pristine_prefix = prefix % prefix_subst
+ # Handle unpacked sources, i.e. importing a directory
+ if source.is_dir():
+ if pristine_commit_name:
+ gbp.log.warn('Preparing unpacked sources for pristine-tar')
+ pristine = prepare_pristine_tar(source, pkg_name, pkg_version,
+ pristine_commit_name,
+ pristine_filters, pristine_prefix,
+ tmpdir)
+ if filters:
+ # Re-use sources packed for pristine-tar, if available
+ if pristine:
+ packed = pristine
+ else:
+ packed_fn = tempfile.mkstemp(prefix="packed_", dir=tmpdir,
+ suffix='.tar')[1]
+ gbp.log.debug("Packing '%s' to '%s'" % (source.path, packed_fn))
+ packed = source.pack(packed_fn)
+ unpack_dir = tempfile.mkdtemp(prefix='filtered_', dir=tmpdir)
+ packed.unpack(unpack_dir, filters)
+ filtered = packed
+ # Handle source archives
+ else:
+ unpack_dir = tempfile.mkdtemp(prefix='filtered_', dir=tmpdir)
+ gbp.log.debug("Unpacking '%s' to '%s'" % (source.path, unpack_dir))
+ source.unpack(unpack_dir, filters)
+ if pristine_commit_name:
+ pristine = prepare_pristine_tar(source, pkg_name, pkg_version,
+ pristine_commit_name,
+ pristine_filters, pristine_prefix,
+ tmpdir)
+ pristine_path = pristine.path if pristine else ''
+ return (filtered.unpacked, pristine_path)
+
+
+def prepare_pristine_tar(source, pkg_name, pkg_version, pristine_commit_name,
+ filters=None, prefix=None, tmpdir=None):
+ """
+ Prepare the upstream sources for pristine-tar import
+
+ @param source: original upstream sources
+ @type source: C{UpstreamSource}
+ @param pkg_name: package name
+ @type pkg_name: C{str}
+ @param pkg_version: upstream version of the package
+ @type pkg_version: C{str}
+ @param pristine_commit_name: archive filename to commit to pristine-tar
+ @type pristine_commit_name: C{str} or C{None}
+ @param filters: filter to exclude files
+ @type filters: C{list} of C{str} or C{None}
+ @param prefix: prefix (i.e. leading directory of files) to use in
+ pristine-tar, set to C{None} to not mangle orig archive
+ @type prefix: C{str} or C{None}
+ @param tmpdir: temporary working dir (cleanup left to caller)
+ @type tmpdir: C{str}
+ @return: prepared source archive
+ @rtype: C{UpstreamSource}
+ """
+ need_repack = False
+ if source.is_dir():
+ if prefix is None:
+ prefix = '%s-%s' % (pkg_name, pkg_version)
+ gbp.log.info("Using guessed prefix '%s/' for pristine-tar" % prefix)
+ need_repack = True
+ else:
+ if prefix is not None and prefix == source.prefix:
+ prefix = None
+ comp = Archive.parse_filename(pristine_commit_name)[2]
+ if filters or prefix is not None or source.compression != comp:
+ if not source.unpacked:
+ unpack_dir = tempfile.mkdtemp(prefix='pristine_unpack_',
+ dir=tmpdir)
+ source.unpack(unpack_dir)
+ need_repack = True
+ pristine_path = os.path.join(tmpdir, pristine_commit_name)
+ if need_repack:
+ gbp.log.debug("Packing '%s' from '%s' for pristine-tar" %
+ (pristine_path, source.unpacked))
+ pristine = source.pack(pristine_path, filters, prefix)
+ else:
+ # Just create symlink for mangling the pristine tarball name
+ os.symlink(source.path, pristine_path)
+ pristine = source.__class__(pristine_path)
+
+ return pristine
+
+
+def upstream_import_commit_msg(options, version):
+ return options.import_msg % dict(version=version)
+
+
+def find_spec(repo, options):
+ """Find spec in the working tree or repository"""
+ try:
+ preferred_fn = os.path.basename(repo.path) + '.spec'
+ spec = guess_spec(os.path.join(repo.path, options.packaging_dir), True,
+ preferred_fn)
+ except NoSpecError:
+ try:
+ # Check the spec file from the repository, in case we're not on the
+ # packaging-branch (but upstream, for example).
+ spec = guess_spec_repo(repo, options.packaging_branch,
+ options.packaging_dir, True, preferred_fn)
+ except NoSpecError:
+ spec = None
+ return spec
+
+
+def detect_name_and_version(repo, source, spec, options):
+ # Guess defaults for the package name and version from the
+ # original tarball.
+ guessed_package, guessed_version = source.guess_version() or ('', '')
+
+ # Try to find the source package name
+ if spec:
+ sourcepackage = spec.name
+ else:
+ if options.interactive:
+ sourcepackage = ask_package_name(guessed_package,
+ RpmPkgPolicy.is_valid_packagename,
+ RpmPkgPolicy.packagename_msg)
+ else:
+ if guessed_package:
+ sourcepackage = guessed_package
+ else:
+ raise GbpError("Couldn't determine upstream package name. Use --interactive.")
+
+ # Try to find the version.
+ if options.version:
+ version = options.version
+ else:
+ if options.interactive:
+ version = ask_package_version(guessed_version,
+ RpmPkgPolicy.is_valid_upstreamversion,
+ RpmPkgPolicy.upstreamversion_msg)
+ else:
+ if guessed_version:
+ version = guessed_version
+ else:
+ raise GbpError("Couldn't determine upstream version. Use '-u<version>' or --interactive.")
+
+ return (sourcepackage, version)
+
+
+def find_upstream(spec, args):
+ """Find the main tarball to import
+ @return: upstream source filename or None if nothing to import
+ @rtype: string
+ @raise GbpError: raised on all detected errors
+ """
+ if len(args) > 1: # source specified
+ raise GbpError("More than one archive specified. Try --help.")
+ elif len(args) == 0:
+ if spec and spec.orig_src:
+ path = spec.orig_src['uri']
+ gbp.log.info("Archive file path from spec is used ('%s')" % path)
+ elif spec:
+ raise GbpError("No archive to import specified and unable to "
+ "determine source from spec. Try --help.")
+ else:
+ raise GbpError("No archive to import specified and no spec file "
+ "found. Try --help.")
+ else:
+ path = args[0]
+ if re.match(r'[a-z]{1,5}://', path):
+ path = download_file('..', path)
+ return RpmUpstreamSource(path)
+
+
+def postimport_hook(repo, tag, version, options):
+ if options.postimport:
+ info = {'upstreamversion': version}
+ env = {'GBP_BRANCH': options.packaging_branch,
+ 'GBP_TAG': tag,
+ 'GBP_UPSTREAM_VERSION': version,
+ }
+ Hook('Postimport',
+ format_str(options.postimport, info),
+ extra_env=env)()
+
+
+def pristine_tarball_name(source, pkg_name, pkg_version, pristine_name):
+ old_filename = os.path.basename(source.path)
+ base_name, _fmt, _comp = Archive.parse_filename(old_filename)
+ if pristine_name != 'auto':
+ ext = old_filename.replace(base_name, '', 1)
+ return pristine_name % {'name': pkg_name,
+ 'version': pkg_version,
+ 'upstreamversion': pkg_version,
+ 'filename_base': base_name,
+ 'filename_ext': ext}
+ # Need to repack and mangle filename if the archive is not
+ # pristine-tar-compatible -> we decide to create gz compressed tarball
+ elif not source.is_tarball():
+ return "%s.tar.gz" % base_name
+ return old_filename
+
+
+def set_bare_repo_options(options):
+ """Modify options for import into a bare repository"""
+ if options.pristine_tar or options.merge:
+ gbp.log.info("Bare repository: setting %s%s options"
+ % (["", " '--no-pristine-tar'"][options.pristine_tar],
+ ["", " '--no-merge'"][options.merge]))
+ options.pristine_tar = False
+ options.merge = False
+
+
+def build_parser(name):
+ try:
+ parser = GbpOptionParserRpm(command=os.path.basename(name), prefix='',
+ usage='%prog [options] /path/to/upstream-version.tar.gz')
+ except GbpError as err:
+ gbp.log.err(err)
+ return None
+
+ import_group = GbpOptionGroup(parser, "import options",
+ "pristine-tar and filtering")
+ tag_group = GbpOptionGroup(parser, "tag options",
+ "options related to git tag creation")
+ branch_group = GbpOptionGroup(parser, "version and branch naming options",
+ "version number and branch layout options")
+ cmd_group = GbpOptionGroup(parser, "external command options",
+ "how and when to invoke external commands and hooks")
+ for group in [import_group, branch_group, tag_group, cmd_group]:
+ parser.add_option_group(group)
+
+ branch_group.add_option("-u", "--upstream-version", dest="version",
+ help="Upstream Version")
+ branch_group.add_config_file_option(option_name="packaging-branch",
+ dest="packaging_branch")
+ branch_group.add_config_file_option(option_name="upstream-branch",
+ dest="upstream_branch")
+ branch_group.add_config_file_option(option_name="upstream-vcs-tag", dest="vcs_tag")
+ branch_group.add_boolean_config_file_option(option_name="merge", dest="merge")
+ branch_group.add_config_file_option(option_name="packaging-dir", dest="packaging_dir")
+ branch_group.add_boolean_config_file_option(option_name="create-missing-branches",
+ dest="create_missing_branches")
+
+ tag_group.add_boolean_config_file_option(option_name="sign-tags",
+ dest="sign_tags")
+ tag_group.add_config_file_option(option_name="keyid",
+ dest="keyid")
+ tag_group.add_config_file_option(option_name="upstream-tag",
+ dest="upstream_tag")
+ import_group.add_config_file_option(option_name="filter",
+ dest="filters", action="append")
+ import_group.add_boolean_config_file_option(option_name="pristine-tar",
+ dest="pristine_tar")
+ import_group.add_boolean_config_file_option(option_name="filter-pristine-tar",
+ dest="filter_pristine_tar")
+ import_group.add_config_file_option(option_name="pristine-tarball-name",
+ dest="pristine_tarball_name")
+ import_group.add_config_file_option(option_name="orig-prefix",
+ dest="orig_prefix")
+ import_group.add_config_file_option(option_name="import-msg",
+ dest="import_msg")
+ cmd_group.add_config_file_option(option_name="postimport", dest="postimport")
+
+ parser.add_boolean_config_file_option(option_name="interactive",
+ dest='interactive')
+ parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
+ help="verbose command execution")
+ parser.add_config_file_option(option_name="color", dest="color", type='tristate')
+ parser.add_config_file_option(option_name="color-scheme",
+ dest="color_scheme")
+ parser.add_config_file_option(option_name="tmp-dir", dest="tmp_dir")
+
+ return parser
+
+
+def parse_args(argv):
+ """Parse the command line arguments
+ @return: options and arguments
+ """
+
+ parser = build_parser(argv[0])
+ if not parser:
+ return None, None
+
+ (options, args) = parser.parse_args(argv[1:])
+ gbp.log.setup(options.color, options.verbose, options.color_scheme)
+
+ return options, args
+
+
+def main(argv):
+ ret = 0
+
+ (options, args) = parse_args(argv)
+ if not options:
+ return ExitCodes.parse_error
+
+ tmpdir = tempfile.mkdtemp(dir=options.tmp_dir, prefix='import-orig-rpm_')
+ try:
+ try:
+ repo = RpmGitRepository('.')
+ except GitRepositoryError:
+ raise GbpError("%s is not a git repository" % (os.path.abspath('.')))
+
+ spec = find_spec(repo, options)
+ source = find_upstream(spec, args)
+
+ is_empty = repo.is_empty()
+
+ if not repo.has_branch(options.upstream_branch):
+ if options.create_missing_branches:
+ gbp.log.info("Will create missing branch '%s'" %
+ options.upstream_branch)
+ elif is_empty:
+ options.create_missing_branches = True
+ else:
+ raise GbpError(no_upstream_branch_msg % options.upstream_branch)
+
+ (clean, out) = repo.is_clean()
+ if not clean and not is_empty:
+ gbp.log.err("Repository has uncommitted changes, commit these first: ")
+ raise GbpError(out)
+
+ # The main tarball
+ (name, version) = detect_name_and_version(repo, source, spec, options)
+
+ tag_str_fields = dict(upstreamversion=version, vendor="Upstream")
+ tag = repo.version_to_tag(options.upstream_tag, tag_str_fields)
+ if repo.has_tag(tag):
+ raise GbpError("Upstream tag '%s' already exists" % tag)
+
+ if repo.bare:
+ set_bare_repo_options(options)
+
+ # Prepare sources for importing
+ if options.pristine_tar:
+ prepare_pristine = pristine_tarball_name(source, name, version,
+ options.pristine_tarball_name)
+ else:
+ prepare_pristine = None
+ unpacked_orig, pristine_orig = prepare_sources(source, name, version,
+ prepare_pristine,
+ options.filters,
+ options.filter_pristine_tar,
+ options.orig_prefix, tmpdir)
+
+ # Don't mess up our repo with git metadata from an upstream tarball
+ try:
+ if os.path.isdir(os.path.join(unpacked_orig, '.git/')):
+ raise GbpError("The orig tarball contains .git metadata - giving up.")
+ except OSError:
+ pass
+
+ try:
+ import_branch = options.upstream_branch
+ filter_msg = ["", " (filtering out %s)"
+ % options.filters][len(options.filters) > 0]
+ gbp.log.info("Importing '%s' to branch '%s'%s..." % (source.path,
+ import_branch,
+ filter_msg))
+ gbp.log.info("Source package is %s" % name)
+ gbp.log.info("Upstream version is %s" % version)
+
+ msg = upstream_import_commit_msg(options, version)
+
+ if options.vcs_tag:
+ parents = [repo.rev_parse("%s^{}" % options.vcs_tag)]
+ else:
+ parents = None
+
+ commit = repo.commit_dir(unpacked_orig,
+ msg=msg,
+ branch=import_branch,
+ other_parents=parents,
+ create_missing_branch=options.create_missing_branches)
+
+ if options.pristine_tar and pristine_orig:
+ gbp.log.info("Pristine-tar: commiting %s" % pristine_orig)
+ repo.pristine_tar.commit(pristine_orig, import_branch)
+
+ repo.create_tag(name=tag,
+ msg="Upstream version %s" % version,
+ commit=commit,
+ sign=options.sign_tags,
+ keyid=options.keyid)
+
+ if options.merge:
+ gbp.log.info("Merging to '%s'" % options.packaging_branch)
+ if repo.has_branch(options.packaging_branch):
+ repo.set_branch(options.packaging_branch)
+ try:
+ repo.merge(tag)
+ except GitRepositoryError:
+ raise GbpError("""Merge failed, please resolve.""")
+ else:
+ repo.create_branch(options.packaging_branch, rev=options.upstream_branch)
+ if repo.get_branch() == options.packaging_branch:
+ repo.force_head(options.packaging_branch, hard=True)
+ # Update working copy and index if we've possibly updated the
+ # checked out branch
+ current_branch = repo.get_branch()
+ if current_branch in [options.upstream_branch,
+ repo.pristine_tar_branch]:
+ repo.force_head(current_branch, hard=True)
+
+ postimport_hook(repo, tag, version, options)
+ except (gbpc.CommandExecFailed, GitRepositoryError) as err:
+ msg = str(err) or 'Unknown error, please report a bug'
+ raise GbpError("Import of %s failed: %s" % (source.path, msg))
+ except KeyboardInterrupt:
+ raise GbpError("Import of %s failed: aborted by user" % (source.path))
+ except GbpError as err:
+ if str(err):
+ gbp.log.err(err)
+ ret = 1
+
+ if tmpdir:
+ cleanup_tmp_tree(tmpdir)
+
+ if not ret:
+ gbp.log.info("Successfully imported version %s of %s" % (version, source.path))
+ return ret
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: