コード例 #1
0
def prepare_upstream_tarball(repo, spec, options, output_dir):
    """Make sure we have an upstream tarball"""
    # look in tarball_dir first, if found force a symlink to it
    orig_file = spec.orig_src['filename']
    if options.tarball_dir:
        gbp.log.debug("Looking for orig tarball '%s' at '%s'" %
                      (orig_file, options.tarball_dir))
        if not RpmPkgPolicy.symlink_orig(
                orig_file, options.tarball_dir, output_dir, force=True):
            gbp.log.info("Orig tarball '%s' not found at '%s'" %
                         (orig_file, options.tarball_dir))
        else:
            gbp.log.info("Orig tarball '%s' found at '%s'" %
                         (orig_file, options.tarball_dir))

    # build an orig unless the user forbids it, always build (and overwrite
    # pre-existing) if user forces it
    if options.force_create or (
            not options.no_create_orig
            and not RpmPkgPolicy.has_orig(orig_file, output_dir)):
        if not pristine_tar_build_orig(repo, orig_file, output_dir, options):
            upstream_tree = git_archive_build_orig(repo, spec, output_dir,
                                                   options)
            if options.pristine_tar_commit:
                if repo.pristine_tar.has_commit(orig_file):
                    gbp.log.debug("%s already on pristine tar branch" %
                                  orig_file)
                else:
                    archive = os.path.join(output_dir, orig_file)
                    gbp.log.debug("Adding %s to pristine-tar branch" % archive)
                    repo.pristine_tar.commit(archive, upstream_tree)
コード例 #2
0
def prepare_upstream_tarball(repo, spec, options, output_dir):
    """Make sure we have an upstream tarball"""
    # look in tarball_dir first, if found force a symlink to it
    orig_file = spec.orig_src['filename']
    if options.tarball_dir:
        gbp.log.debug("Looking for orig tarball '%s' at '%s'" %
                      (orig_file, options.tarball_dir))
        if not RpmPkgPolicy.symlink_orig(orig_file, options.tarball_dir,
                                         output_dir, force=True):
            gbp.log.info("Orig tarball '%s' not found at '%s'" %
                         (orig_file, options.tarball_dir))
        else:
            gbp.log.info("Orig tarball '%s' found at '%s'" %
                         (orig_file, options.tarball_dir))

    # build an orig unless the user forbids it, always build (and overwrite
    # pre-existing) if user forces it
    if options.force_create or (not options.no_create_orig and not
                                RpmPkgPolicy.has_orig(orig_file, output_dir)):
        if not pristine_tar_build_orig(repo, orig_file, output_dir, options):
            upstream_tree = git_archive_build_orig(repo, spec, output_dir,
                                                   options)
            if options.pristine_tar_commit:
                if repo.pristine_tar.has_commit(orig_file):
                    gbp.log.debug("%s already on pristine tar branch" %
                                  orig_file)
                else:
                    archive = os.path.join(output_dir, orig_file)
                    gbp.log.debug("Adding %s to pristine-tar branch" %
                                  archive)
                    repo.pristine_tar.commit(archive, upstream_tree)
コード例 #3
0
def create_packaging_tag(repo, tag, commit, version, options):
    """Create a packaging/release Git tag"""
    msg = "%s release %s" % (options.vendor,
                             RpmPkgPolicy.compose_full_version(version))
    repo.create_tag(name=tag,
                    msg=msg,
                    sign=options.sign_tags,
                    keyid=options.keyid,
                    commit=commit)
コード例 #4
0
def create_commit_message(spec, options):
    """Generate commit message"""
    fields = spec.version
    fields['version'] = version = RpmPkgPolicy.compose_full_version(
        spec.version)
    fields['vendor'] = options.vendor
    try:
        return options.commit_msg % fields
    except KeyError as err:
        raise GbpError("Unknown key %s in commit-msg string, "
                       "only %s are accepted" % (err, fields.keys()))
コード例 #5
0
def guess_commit(section, repo, options):
    """Guess the last commit documented in a changelog header"""

    if not section:
        return None
    header = section.header

    # Try to parse the fields from the header revision
    rev_re = '^%s$' % re.sub(r'%\((\S+?)\)s', r'(?P<\1>\S+)',
                             options.changelog_revision)
    match = re.match(rev_re, header['revision'], re.I)
    fields = match.groupdict() if match else {}

    # First, try to find tag-name, if present
    if 'tagname' in fields:
        gbp.log.debug("Trying to find tagname %s" % fields['tagname'])
        try:
            return repo.rev_parse("%s^0" % fields['tagname'])
        except GitRepositoryError:
            gbp.log.warn("Changelog points to tagname '%s' which is not found "
                         "in the git repository" % fields['tagname'])

    # Next, try to find packaging tag matching the version
    tag_str_fields = {'vendor': options.vendor}
    if 'version' in fields:
        gbp.log.debug("Trying to find packaging tag for version '%s'" %
                      fields['version'])
        full_version = fields['version']
        tag_str_fields.update(RpmPkgPolicy.split_full_version(full_version))
    elif 'upstreamversion' in fields:
        gbp.log.debug("Trying to find packaging tag for version '%s'" %
                      fields['upstreamversion'])
        tag_str_fields['upstreamversion'] = fields['upstreamversion']
        if 'release' in fields:
            tag_str_fields['release'] = fields['release']
    commit = repo.find_version(options.packaging_tag, tag_str_fields)
    if commit:
        return commit
    else:
        gbp.log.info("Couldn't find packaging tag for version %s" %
                     header['revision'])

    # As a last resort we look at the timestamp
    timestamp = header['time'].isoformat()
    last = repo.get_commits(num=1, options="--until='%s'" % timestamp)
    if last:
        gbp.log.info("Using commit (%s) before the last changelog timestamp "
                     "(%s)" % (last, timestamp))
        return last[0]
    return None
コード例 #6
0
def update_changelog(changelog, entries, repo, spec, options):
    """Update the changelog with a range of commits"""
    # Get info for section header
    now = datetime.now()
    name, email = get_author(repo, options.git_author)
    rev_str_fields = dict(spec.version,
                          version=RpmPkgPolicy.compose_full_version(
                              spec.version),
                          vendor=options.vendor)
    if options.commit:
        # Get fake information for the to-be-created git commit
        commit_info = {
            'author': GitModifier(date=now),
            'committer': GitModifier(date=now)
        }
        tag = packaging_tag_name(repo, spec, commit_info, options)
    else:
        commit_info = {'author': None, 'committer': None}
        tag = repo.describe('HEAD', longfmt=True, always=True)
    rev_str_fields['tagname'] = tag

    try:
        revision = options.changelog_revision % rev_str_fields
    except KeyError as err:
        raise GbpError("Unable to construct revision field: unknown key "
                       "%s, only %s are accepted" %
                       (err, rev_str_fields.keys()))

    # Add a new changelog section if new release or an empty changelog
    if options.release or not changelog.sections:
        top_section = changelog.add_section(time=now,
                                            name=name,
                                            email=email,
                                            revision=revision)
    else:
        # Re-use already parsed top section
        top_section = changelog.sections[0]
        top_section.set_header(time=now,
                               name=name,
                               email=email,
                               revision=revision)

    # Add new entries to the topmost section
    for entry in entries:
        top_section.append_entry(entry)
    return (tag, commit_info['author'], commit_info['committer'])
コード例 #7
0
ファイル: git.py プロジェクト: pombredanne/git-buildpackage-1
    def version_to_tag(format, str_fields):
        """
        Generate a tag from a given format and a version

        @param format: tag pattern
        @type format: C{str}
        @param str_fields: arguments for format string ('upstreamversion', 'release', 'vendor'...)
        @type str_fields: C{dict} of C{str}
        @return: version tag

        >>> RpmGitRepository.version_to_tag("packaging/%(version)s", dict(epoch='0', upstreamversion='0~0'))
        'packaging/0%0_0'
        >>> RpmGitRepository.version_to_tag("%(vendor)s/v%(version)s", dict(upstreamversion='1.0', release='2', vendor="myvendor"))
        'myvendor/v1.0-2'
        """
        version_tag = format % dict(
            str_fields, version=RpmPkgPolicy.compose_full_version(str_fields))
        return RpmGitRepository._sanitize_tag(version_tag)
コード例 #8
0
    def _guess_orig_prefix(self, orig):
        """Guess prefix for the orig file"""
        # Make initial guess about the prefix in the archive
        filename = orig["filename"]
        name, version = RpmPkgPolicy.guess_upstream_src_version(filename)
        if name and version:
            prefix = "%s-%s/" % (name, version)
        else:
            prefix = orig["filename_base"] + "/"

        # Refine our guess about the prefix
        for macro in self._special_directives["setup"]:
            args = macro["args"]
            opts = self._setup_macro_opts(args)
            srcnum = None
            if opts.no_unpack_default:
                if opts.unpack_before:
                    srcnum = int(opts.unpack_before)
                elif opts.unpack_after:
                    srcnum = int(opts.unpack_after)
            else:
                srcnum = 0
            if srcnum == orig["num"]:
                if opts.create_dir:
                    prefix = ""
                elif opts.name:
                    try:
                        prefix = self.macro_expand(opts.name) + "/"
                    except MacroExpandError as err:
                        gbp.log.warn(
                            "Couldn't determine prefix from %%setup "
                            "macro (%s). Using filename base as a "
                            "fallback" % err
                        )
                        prefix = orig["filename_base"] + "/"
                else:
                    # RPM default
                    prefix = "%s-%s/" % (self.name, self.upstreamversion)
                break
        return prefix
コード例 #9
0
ファイル: __init__.py プロジェクト: zhsj/git-buildpackage
    def _guess_orig_prefix(self, orig):
        """Guess prefix for the orig file"""
        # Make initial guess about the prefix in the archive
        filename = orig['filename']
        name, version = RpmPkgPolicy.guess_upstream_src_version(filename)
        if name and version:
            prefix = "%s-%s/" % (name, version)
        else:
            prefix = orig['filename_base'] + "/"

        # Refine our guess about the prefix
        for macro in self._special_directives['setup']:
            args = macro['args']
            opts = self._setup_macro_opts(args)
            srcnum = None
            if opts.no_unpack_default:
                if opts.unpack_before:
                    srcnum = int(opts.unpack_before)
                elif opts.unpack_after:
                    srcnum = int(opts.unpack_after)
            else:
                srcnum = 0
            if srcnum == orig['num']:
                if opts.create_dir:
                    prefix = ''
                elif opts.name:
                    try:
                        prefix = self.macro_expand(opts.name) + '/'
                    except MacroExpandError as err:
                        gbp.log.warn("Couldn't determine prefix from %%setup "
                                     "macro (%s). Using filename base as a "
                                     "fallback" % err)
                        prefix = orig['filename_base'] + '/'
                else:
                    # RPM default
                    prefix = "%s-%s/" % (self.name, self.upstreamversion)
                break
        return prefix
コード例 #10
0
def update_tag_str_fields(fields, tag_format_str, repo, commit_info):
    """Update string format fields for packaging tag"""
    fields['nowtime'] = datetime.now().strftime(
        RpmPkgPolicy.tag_timestamp_format)

    fields['authortime'] = datetime.fromtimestamp(
        int(commit_info['author'].date.split()[0])).strftime(
            RpmPkgPolicy.tag_timestamp_format)
    fields['committime'] = datetime.fromtimestamp(
        int(commit_info['committer'].date.split()[0])).strftime(
            RpmPkgPolicy.tag_timestamp_format)
    fields['version'] = RpmPkgPolicy.compose_full_version(fields)

    # Parse tags with incremental numbering
    re_fields = dict(
        fields,
        nowtimenum=fields['nowtime'] + ".(?P<nownum>[0-9]+)",
        authortimenum=fields['authortime'] + ".(?P<authornum>[0-9]+)",
        committimenum=fields['committime'] + ".(?P<commitnum>[0-9]+)")
    try:
        tag_re = re.compile("^%s$" % (tag_format_str % re_fields))
    except KeyError, err:
        raise GbpError, "Unknown field '%s' in packaging-tag format string" % err
コード例 #11
0
def main(argv):
    """Entry point for git-buildpackage-bb"""
    retval = 0
    prefix = "git-"
    bbfile = None
    dump_dir = None

    if not bb:
        return 1

    options, gbp_args, builder_args = parse_args(argv, prefix)
    if not options:
        return 1

    try:
        repo = RpmGitRepository(os.path.curdir)
    except GitRepositoryError:
        gbp.log.err("%s is not a git repository" % (os.path.abspath('.')))
        return 1

    # Determine tree-ish to be exported
    try:
        tree = get_tree(repo, options.export)
    except GbpError as err:
        gbp.log.err('Failed to determine export treeish: %s' % err)
        return 1
    # Re-parse config options with using the per-tree config file(s) from the
    # exported tree-ish
    options, gbp_args, builder_args = parse_args(argv, prefix, tree)

    branch = get_current_branch(repo)

    try:
        tinfoil = init_tinfoil(config_only=True)
        #bb_cfg_data = bb.data.createCopy(tinfoil.config_data)
    except GbpError:
        tinfoil = None

    # Use naive parsing because repository might only have .bb file
    gbp.log.info("Using naive standalone parsing of recipes in package repo.")
    bb_cfg_data = None

    try:
        tree = guess_export_params(repo, options)

        Command(options.cleaner, shell=True)()
        if not options.ignore_new:
            (ret, out) = repo.is_clean(options.ignore_untracked)
            if not ret:
                gbp.log.err("You have uncommitted changes in your source tree:")
                gbp.log.err(out)
                raise GbpError("Use --git-ignore-new or --git-ignore-untracked "
                               "to ignore.")

        if not options.ignore_new and not options.ignore_branch:
            if branch != options.packaging_branch:
                gbp.log.err("You are not on branch '%s' but on '%s'" %
                            (options.packaging_branch, branch))
                raise GbpError("Use --git-ignore-branch to ignore or "
                               "--git-packaging-branch to set the branch name.")

        if not options.tag_only:
            # Dump/parse meta to export dir
            if options.export_dir:
                export_dir = os.path.abspath(options.export_dir)
            else:
                export_dir = guess_export_dir(options, tinfoil, repo, tree)
            gbp.log.info("Dumping meta from tree '%s' to '%s'" %
                            (options.export, export_dir))
            bbfile = dump_meta(bb_cfg_data, options, repo, tree,
                                 export_dir)

            # Setup builder opts
            setup_builder(options, builder_args)

            if is_native(repo, options) and bbfile.getVar('SRCREV') == 'HEAD':
                # Update SRCREV for native packages that are exported from
                # pristine repository
                BBFile.set_var_val(bbfile.bb_path, 'SRCREV',
                                   repo.rev_parse(tree))

                # TODO: Re-design the handling of native packages. Updating
                #       SRCREV must probably be more explicit
            if options.patch_export:
                # Generate patches, if requested
                if options.patch_export_rev:
                    patch_tree = get_tree(repo, options.patch_export_rev)
                else:
                    patch_tree = tree
                export_patches(repo, bbfile, patch_tree, options)

            # Run postexport hook
            if options.postexport:
                RunAtCommand(options.postexport, shell=True,
                             extra_env={'GBP_GIT_DIR': repo.git_dir,
                                        'GBP_TMP_DIR': export_dir}
                             )(dir=export_dir)
            # Do actual build
            if not options.no_build:
                if options.prebuild:
                    RunAtCommand(options.prebuild, shell=True,
                                 extra_env={'GBP_GIT_DIR': repo.git_dir,
                                            'GBP_BUILD_DIR': export_dir}
                                 )(dir=export_dir)

                # Unlock cooker so that we are able to run external bitbake
                if options.builder == 'bitbake' and tinfoil:
                    bb.utils.unlockfile(tinfoil.cooker.lock)

                # Finally build the package:
                bb_path = bbfile.getVar('FILE', True)
                builder_args.extend(['-b', bb_path])
                RunAtCommand(options.builder, builder_args, shell=True,
                             extra_env={'GBP_BUILD_DIR': export_dir})()

                if options.postbuild:
                    Command(options.postbuild, shell=True,
                            extra_env={'GBP_BUILD_DIR': export_dir})()
        else:
            # Tag-only: we just need to parse the meta
            bbfile = parse_bb(bb_cfg_data, options, repo, tree)

        # Tag (note: tags the exported version)
        if options.tag or options.tag_only:
            version = pkg_version(bbfile)
            gbp.log.info("Tagging %s" %
                         RpmPkgPolicy.compose_full_version(version))
            commit_info = repo.get_commit_info(tree)
            tag = packaging_tag_name(repo, version, commit_info, options)
            if options.retag and repo.has_tag(tag):
                repo.delete_tag(tag)
            create_packaging_tag(repo, tag, commit=tree, version=version,
                                 options=options)
            vcs_info = get_vcs_info(repo, tag)
            if options.posttag:
                sha = repo.rev_parse("%s^{}" % tag)
                Command(options.posttag, shell=True,
                        extra_env={'GBP_TAG': tag,
                                   'GBP_BRANCH': branch,
                                   'GBP_SHA1': sha})()
        else:
            vcs_info = get_vcs_info(repo, tree)
        # TODO: Put VCS information to recipe
        if options.bb_vcs_info:
            raise GbpError("Injecting VCS info into recipe not yet supported")

    except CommandExecFailed:
        retval = 1
    except GitRepositoryError as err:
        gbp.log.err("Git command failed: %s" % err)
        retval = 1
    except GbpAutoGenerateError as err:
        if len(err.__str__()):
            gbp.log.err(err)
        retval = 2
    except GbpError, err:
        if len(err.__str__()):
            gbp.log.err(err)
        retval = 1
コード例 #12
0
        gbp.log.err("Git command failed: %s" % err)
        retval = 1
    except GbpAutoGenerateError as err:
        if len(err.__str__()):
            gbp.log.err(err)
        retval = 2
    except GbpError, err:
        if len(err.__str__()):
            gbp.log.err(err)
        retval = 1
    finally:
        drop_index(repo)
        if dump_dir and os.path.exists(dump_dir):
            shutil.rmtree(dump_dir)

    if not options.tag_only:
        if bbfile and options.notify:
            summary = "GBP buildpackage-bb %s" % \
                        ["failed", "successful"][not retval]
            message = ("Build of %s %s %s" % (bbfile.getVar('PN', True),
                       RpmPkgPolicy.compose_full_version(pkg_version(bbfile)),
                       ["failed", "succeeded"][not retval]))
            if not gbp.notifications.notify(summary, message, options.notify):
                gbp.log.err("Failed to send notification")
                retval = 1

    return retval

if __name__ == '__main__':
    sys.exit(main(sys.argv))
コード例 #13
0
def main(argv):
    """Main function of the gbp import-bb script"""
    dirs = dict(top=os.path.abspath(os.curdir))
    ret = 0
    skipped = False

    if not bb:
        return 1

    options, args = parse_args(argv)

    if len(args) == 0 or len(args) > 2:
        gbp.log.err("Need to give exactly one package to import. Try --help.")
        return 1

    try:
        dirs['tmp_base'] = tempfile.mkdtemp(dir=options.tmp_dir,
                                            prefix='import-bb')
        tinfoil = init_tinfoil()
        pkg_bb = guess_pkg(tinfoil, args[0])
        dirs['src'] = os.path.abspath(os.path.dirname(pkg_bb))
        gbp.log.info("Importing '%s' from '%s'" %
                     (os.path.basename(pkg_bb), dirs['src']))

        pkg_data = bb.cache.Cache.loadDataFull(pkg_bb, [], tinfoil.config_data)

        # Determine target repo dir
        target_dir = ''
        if len(args) == 2:
            target_dir = args[1]
        else:
            if 'BUILDDIR' in os.environ:
                target_dir = os.path.join(os.environ['BUILDDIR'], 'devel')
            target_dir = os.path.join(target_dir, pkg_data.getVar('PN', True))

        # Check the Git repository state
        repo = init_repo(target_dir)
        if repo.bare:
            set_bare_repo_options(options)
        if repo.is_empty():
            options.create_missing_branches = True
        os.chdir(repo.path)

        # Create more tempdirs
        dirs['origsrc'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
                                           prefix='origsrc_')
        dirs['packaging_base'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
                                                  prefix='packaging_')
        dirs['packaging'] = os.path.join(dirs['packaging_base'],
                                         options.meta_dir)

        # Copy (local) packaging files to tmp dir
        remote_srcs = bb_get_files(pkg_data, dirs['packaging'])

        version_dict = pkg_version(pkg_data)
        tag_str_fields = dict(version_dict, vendor=options.vendor.lower())
        ver_str = RpmPkgPolicy.compose_full_version(version_dict)

        # Check if the same version of the package is already imported
        if repo.find_version(options.packaging_tag, tag_str_fields):
            gbp.log.warn("Version %s already imported." % ver_str)
            if options.allow_same_version:
                gbp.log.info("Moving tag of version '%s' since import forced" %
                             ver_str)
                move_tag_stamp(repo, options.packaging_tag, tag_str_fields)
            else:
                raise SkipImport

        # Import upstream sources
        import_upstream_sources(repo, pkg_data, remote_srcs, dirs, options)

        # Import packaging files
        gbp.log.info("Importing local meta/packaging files")
        branch = options.packaging_branch
        if not repo.has_branch(branch):
            if options.create_missing_branches:
                gbp.log.info("Will create missing branch '%s'" % branch)
            else:
                gbp.log.err(NO_PACKAGING_BRANCH_MSG % branch + "\n"
                            "Also check the --create-missing-branches "
                            "option.")
                raise GbpError

        tag = repo.version_to_tag(options.packaging_tag, tag_str_fields)
        msg = "%s release %s" % (options.vendor, ver_str)

        commit = repo.commit_dir(dirs['packaging_base'],
                    "Imported %s" % msg,
                    branch,
                    create_missing_branch=options.create_missing_branches)

        # Create packaging tag
        repo.create_tag(name=tag,
                        msg=msg,
                        commit=commit,
                        sign=options.sign_tags,
                        keyid=options.keyid)

        force_to_branch_head(repo, options.packaging_branch)

    except KeyboardInterrupt:
        ret = 1
        gbp.log.err("Interrupted. Aborting.")
    except gbpc.CommandExecFailed:
        ret = 1
    except GitRepositoryError as err:
        gbp.log.err("Git command failed: %s" % err)
        ret = 1
    except GbpError as err:
        if len(err.__str__()):
            gbp.log.err(err)
        ret = 1
    except SkipImport:
        skipped = True
    finally:
        os.chdir(dirs['top'])
        gbpc.RemoveTree(dirs['tmp_base'])()

    if not ret and not skipped:
        gbp.log.info("Version '%s' imported under '%s'" %
                     (ver_str, repo.path))
    return ret
コード例 #14
0
                if f == spec.specfile:
                    dst = os.path.join(spec_dir, f)
                else:
                    dst = os.path.join(source_dir, f)
                if not os.path.isdir(src):
                    try:
                        shutil.copy2(src, dst)
                    except IOError as err:
                        raise GbpError, "Error exporting files: %s" % err
            spec.specdir = os.path.abspath(spec_dir)

            if options.orig_prefix != 'auto':
                try:
                    options.orig_prefix %= dict(
                        spec.version,
                        version=RpmPkgPolicy.compose_full_version(
                            spec.version),
                        name=spec.name,
                        vendor=options.vendor)
                except KeyError as err:
                    raise GbpError("Unknown key %s in orig prefix format "
                                   "string" % err)
            elif spec.orig_src:
                options.orig_prefix = spec.orig_src['prefix']

            # Get/build the orig tarball
            if is_native(repo, options):
                if spec.orig_src:
                    # Just build source archive from the exported tree
                    gbp.log.info(
                        "Creating (native) source archive %s from '%s'" %
                        (spec.orig_src['filename'], tree))
コード例 #15
0
def main(argv):
    """Main function of the git-import-srpm script"""
    dirs = dict(top=os.path.abspath(os.curdir))

    ret = 0
    skipped = False

    options, args = parse_args(argv)

    if len(args) != 1:
        gbp.log.err("Need to give exactly one package to import. Try --help.")
        return 1
    try:
        dirs['tmp_base'] = tempfile.mkdtemp(dir=options.tmp_dir,
                                            prefix='import-srpm')
    except GbpError as err:
        gbp.log.err(err)
        return 1
    try:
        srpm = args[0]
        if options.download:
            srpm = download_source(srpm, dirs)

        # Real srpm, we need to unpack, first
        true_srcrpm = False
        if not os.path.isdir(srpm) and not srpm.endswith(".spec"):
            src = parse_srpm(srpm)
            true_srcrpm = True
            dirs['pkgextract'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
                                                  prefix='pkgextract_')
            gbp.log.info("Extracting src rpm to '%s'" % dirs['pkgextract'])
            src.unpack(dirs['pkgextract'])
            preferred_spec = src.name + '.spec'
            srpm = dirs['pkgextract']
        elif os.path.isdir(srpm):
            preferred_spec = os.path.basename(srpm.rstrip('/')) + '.spec'
        else:
            preferred_spec = None

        # Find and parse spec file
        if os.path.isdir(srpm):
            gbp.log.debug("Trying to import an unpacked srpm from '%s'" % srpm)
            dirs['src'] = os.path.abspath(srpm)
            spec = guess_spec(srpm, True, preferred_spec)
        else:
            gbp.log.debug("Trying to import an srpm from '%s' with spec "\
                          "file '%s'" % (os.path.dirname(srpm), srpm))
            dirs['src'] = os.path.abspath(os.path.dirname(srpm))
            spec = SpecFile(srpm)

        # Check the repository state
        try:
            repo = RpmGitRepository('.')
            is_empty = repo.is_empty()

            (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

        except GitRepositoryError:
            gbp.log.info("No git repository found, creating one.")
            is_empty = True
            repo = RpmGitRepository.create(spec.name)
            os.chdir(repo.path)

        if repo.bare:
            set_bare_repo_options(options)

        # Create more tempdirs
        dirs['origsrc'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
                                           prefix='origsrc_')
        dirs['packaging_base'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
                                                  prefix='packaging_')
        dirs['packaging'] = os.path.join(dirs['packaging_base'],
                                         options.packaging_dir)
        try:
            os.mkdir(dirs['packaging'])
        except OSError as err:
            if err.errno != errno.EEXIST:
                raise

        if true_srcrpm:
            # For true src.rpm we just take everything
            files = os.listdir(dirs['src'])
        else:
            # Need to copy files to the packaging directory given by caller
            files = [os.path.basename(patch.path) \
                    for patch in spec.patchseries(unapplied=True, ignored=True)]
            for filename in spec.sources().values():
                files.append(os.path.basename(filename))
            files.append(os.path.join(spec.specdir, spec.specfile))
        # Don't copy orig source archive, though
        if spec.orig_src and spec.orig_src['filename'] in files:
            files.remove(spec.orig_src['filename'])

        for fname in files:
            fpath = os.path.join(dirs['src'], fname)
            if os.path.exists(fpath):
                shutil.copy2(fpath, dirs['packaging'])
            else:
                gbp.log.err("File '%s' listed in spec not found" % fname)
                raise GbpError

        # Unpack orig source archive
        if spec.orig_src:
            orig_tarball = os.path.join(dirs['src'], spec.orig_src['filename'])
            upstream = RpmUpstreamSource(orig_tarball)
            upstream = upstream.unpack(dirs['origsrc'], options.filters)
        else:
            upstream = None

        tag_format = [(options.upstream_tag, "Upstream"),
                      (options.packaging_tag, options.vendor)][options.native]
        tag_str_fields = dict(spec.version, vendor=options.vendor)
        tag = repo.version_to_tag(tag_format[0], tag_str_fields)

        if repo.find_version(options.packaging_tag, tag_str_fields):
            gbp.log.warn("Version %s already imported." %
                         RpmPkgPolicy.compose_full_version(spec.version))
            if options.allow_same_version:
                gbp.log.info("Moving tag of version '%s' since import forced" %
                             RpmPkgPolicy.compose_full_version(spec.version))
                move_tag_stamp(repo, options.packaging_tag, tag_str_fields)
            else:
                raise SkipImport

        if is_empty:
            options.create_missing_branches = True

        # Determine author and committer info, currently same info is used
        # for both upstream sources and packaging files
        author = None
        if spec.packager:
            match = re.match('(?P<name>.*[^ ])\s*<(?P<email>\S*)>',
                             spec.packager.strip())
            if match:
                author = GitModifier(match.group('name'), match.group('email'))
        if not author:
            author = GitModifier()
            gbp.log.debug("Couldn't determine packager info")
        committer = committer_from_author(author, options)

        # Import upstream sources
        if upstream:
            upstream_commit = repo.find_version(tag_format[0], tag_str_fields)
            if not upstream_commit:
                gbp.log.info(
                    "Tag %s not found, importing %s upstream sources" %
                    (tag, tag_format[1]))

                branch = [options.upstream_branch,
                          options.packaging_branch][options.native]
                if not repo.has_branch(branch):
                    if options.create_missing_branches:
                        gbp.log.info("Will create missing branch '%s'" %
                                     branch)
                    else:
                        gbp.log.err(
                            no_upstream_branch_msg % branch + "\n"
                            "Also check the --create-missing-branches option.")
                        raise GbpError

                msg = "%s version %s" % (tag_format[1], spec.upstreamversion)
                if options.vcs_tag:
                    parents = [repo.rev_parse("%s^{}" % options.vcs_tag)]
                else:
                    parents = None
                upstream_commit = repo.commit_dir(
                    upstream.unpacked,
                    "Imported %s" % msg,
                    branch,
                    other_parents=parents,
                    author=author,
                    committer=committer,
                    create_missing_branch=options.create_missing_branches)
                repo.create_tag(name=tag,
                                msg=msg,
                                commit=upstream_commit,
                                sign=options.sign_tags,
                                keyid=options.keyid)

                if not options.native:
                    if options.pristine_tar:
                        archive_fmt = parse_archive_filename(orig_tarball)[1]
                        if archive_fmt == 'tar':
                            repo.pristine_tar.commit(
                                orig_tarball,
                                'refs/heads/%s' % options.upstream_branch)
                        else:
                            gbp.log.warn('Ignoring pristine-tar, %s archives '
                                         'not supported' % archive_fmt)
        else:
            gbp.log.info("No orig source archive imported")

        # Import packaging files. For native packages we assume that also
        # packaging files are found in the source tarball
        if not options.native or not upstream:
            gbp.log.info("Importing packaging files")
            branch = options.packaging_branch
            if not repo.has_branch(branch):
                if options.create_missing_branches:
                    gbp.log.info("Will create missing branch '%s'" % branch)
                else:
                    gbp.log.err(no_packaging_branch_msg % branch + "\n"
                                "Also check the --create-missing-branches "
                                "option.")
                    raise GbpError

            tag_str_fields = dict(spec.version, vendor=options.vendor)
            tag = repo.version_to_tag(options.packaging_tag, tag_str_fields)
            msg = "%s release %s" % (options.vendor,
                                     RpmPkgPolicy.compose_full_version(
                                         spec.version))

            if options.orphan_packaging or not upstream:
                commit = repo.commit_dir(
                    dirs['packaging_base'],
                    "Imported %s" % msg,
                    branch,
                    author=author,
                    committer=committer,
                    create_missing_branch=options.create_missing_branches)
            else:
                # Copy packaging files to the unpacked sources dir
                try:
                    pkgsubdir = os.path.join(upstream.unpacked,
                                             options.packaging_dir)
                    os.mkdir(pkgsubdir)
                except OSError as err:
                    if err.errno != errno.EEXIST:
                        raise
                for fn in os.listdir(dirs['packaging']):
                    shutil.copy2(os.path.join(dirs['packaging'], fn),
                                 pkgsubdir)
                commit = repo.commit_dir(
                    upstream.unpacked,
                    "Imported %s" % msg,
                    branch,
                    other_parents=[upstream_commit],
                    author=author,
                    committer=committer,
                    create_missing_branch=options.create_missing_branches)
                # Import patches on top of the source tree
                # (only for non-native packages with non-orphan packaging)
                force_to_branch_head(repo, options.packaging_branch)
                if options.patch_import:
                    spec = SpecFile(
                        os.path.join(repo.path, options.packaging_dir,
                                     spec.specfile))
                    import_spec_patches(repo, spec, dirs)
                    commit = options.packaging_branch

            # Create packaging tag
            repo.create_tag(name=tag,
                            msg=msg,
                            commit=commit,
                            sign=options.sign_tags,
                            keyid=options.keyid)

        force_to_branch_head(repo, options.packaging_branch)

    except KeyboardInterrupt:
        ret = 1
        gbp.log.err("Interrupted. Aborting.")
    except gbpc.CommandExecFailed:
        ret = 1
    except GitRepositoryError as err:
        gbp.log.err("Git command failed: %s" % err)
        ret = 1
    except GbpError as err:
        if len(err.__str__()):
            gbp.log.err(err)
        ret = 1
    except NoSpecError as err:
        gbp.log.err("Failed determine spec file: %s" % err)
        ret = 1
    except PatchImportError as err:
        gbp.log.err(err)
        ret = 2
    except SkipImport:
        skipped = True
    finally:
        os.chdir(dirs['top'])
        gbpc.RemoveTree(dirs['tmp_base'])()

    if not ret and not skipped:
        gbp.log.info(
            "Version '%s' imported under '%s'" %
            (RpmPkgPolicy.compose_full_version(spec.version), spec.name))
    return ret