Example #1
0
def download_source(pkg):
    """Download package from a remote location"""
    if re.match(r'[a-z]{1,5}://', pkg):
        mode = 'python urllib'
    else:
        mode = 'yumdownloader'

    tmpdir = tempfile.mkdtemp(prefix='download_')
    gbp.log.info("Trying to download '%s' using '%s'..." % (pkg, mode))
    if mode == 'yumdownloader':
        gbpc.RunAtCommand('yumdownloader',
                          ['--source', '--destdir=', '.', pkg],
                          shell=False)(dir=tmpdir)
    else:
        download_file(tmpdir, pkg)
    srpm = glob.glob(os.path.join(tmpdir, '*.src.rpm'))[0]
    return srpm
Example #2
0
def download_source(pkg):
    """Download package from a remote location"""
    if re.match(r'[a-z]{1,5}://', pkg):
        mode = 'python urllib'
    else:
        mode = 'yumdownloader'

    tmpdir = tempfile.mkdtemp(prefix='download_')
    gbp.log.info("Trying to download '%s' using '%s'..." % (pkg, mode))
    if mode == 'yumdownloader':
        gbpc.RunAtCommand('yumdownloader',
                          ['--source', '--destdir=', '.', pkg],
                          shell=False)(dir=tmpdir)
    else:
        download_file(tmpdir, pkg)
    srpm = glob.glob(os.path.join(tmpdir, '*.src.rpm'))[0]
    return srpm
Example #3
0
def safe_patches(queue):
    """
    Safe the current patches in a temporary directory

    @param queue: an existing patch queue
    @return: safed queue (with patches in tmpdir)
    @rtype: tuple
    """

    tmpdir = tempfile.mkdtemp(prefix='patchimport_')
    safequeue = PatchSeries()

    if len(queue) > 0:
        gbp.log.debug("Saving patches '%s' in '%s'" %
                      (os.path.dirname(queue[0].path), tmpdir))
    for patch in queue:
        base, _archive_fmt, comp = Archive.parse_filename(patch.path)
        uncompressors = {'gzip': gzip.open, 'bzip2': bz2.BZ2File}
        if comp in uncompressors:
            gbp.log.debug("Uncompressing '%s'" % os.path.basename(patch.path))
            src = uncompressors[comp](patch.path, 'r')
            dst_name = os.path.join(tmpdir, os.path.basename(base))
        elif comp:
            raise GbpError("Unsupported patch compression '%s', giving up" %
                           comp)
        else:
            src = open(patch.path, 'rb')
            dst_name = os.path.join(tmpdir, os.path.basename(patch.path))

        dst = open(dst_name, 'wb')
        dst.write(src.read())
        src.close()
        dst.close()

        safequeue.append(patch)
        safequeue[-1].path = dst_name

    return safequeue
Example #4
0
def safe_patches(queue):
    """
    Safe the current patches in a temporary directory

    @param queue: an existing patch queue
    @return: safed queue (with patches in tmpdir)
    @rtype: tuple
    """

    tmpdir = tempfile.mkdtemp(prefix='patchimport_')
    safequeue = PatchSeries()

    if len(queue) > 0:
        gbp.log.debug("Saving patches '%s' in '%s'" %
                      (os.path.dirname(queue[0].path), tmpdir))
    for patch in queue:
        base, _archive_fmt, comp = Archive.parse_filename(patch.path)
        uncompressors = {'gzip': gzip.open, 'bzip2': bz2.BZ2File}
        if comp in uncompressors:
            gbp.log.debug("Uncompressing '%s'" % os.path.basename(patch.path))
            src = uncompressors[comp](patch.path, 'r')
            dst_name = os.path.join(tmpdir, os.path.basename(base))
        elif comp:
            raise GbpError("Unsupported patch compression '%s', giving up"
                           % comp)
        else:
            src = open(patch.path, 'rb')
            dst_name = os.path.join(tmpdir, os.path.basename(patch.path))

        dst = open(dst_name, 'wb')
        dst.write(src.read())
        src.close()
        dst.close()

        safequeue.append(patch)
        safequeue[-1].path = dst_name

    return safequeue
def main(argv):
    """Entry point for gbp-buildpackage-rpm"""
    retval = 0
    prefix = "git-"
    spec = None

    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:
        init_tmpdir(options.tmp_dir, prefix='buildpackage-rpm_')

        tree = get_tree(repo, options.export)
        spec = parse_spec(options, repo, treeish=tree)

        Command(options.cleaner, shell=True)()
        if not options.ignore_new:
            ret, out = repo.is_clean()
            if not ret:
                gbp.log.err("You have uncommitted changes in your source tree:")
                gbp.log.err(out)
                raise GbpError("Use --git-ignore-new 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.")

        # Dump from git to a temporary directory:
        packaging_tree = '%s:%s' % (tree, options.packaging_dir)
        dump_dir = tempfile.mkdtemp(prefix='packaging_')
        gbp.log.debug("Dumping packaging files to '%s'" % dump_dir)
        if not dump_tree(repo, dump_dir, packaging_tree, False, False):
            raise GbpError
        # Re-parse spec from dump dir to get version etc.
        spec = rpm.SpecFile(os.path.join(dump_dir, spec.specfile))

        if not options.tag_only:
            # Setup builder opts
            setup_builder(options, builder_args)
            if options.use_mock:
                setup_mock(options)

            # Prepare final export dirs
            export_dir = makedir(options.export_dir)
            source_dir = makedir(os.path.join(export_dir,
                                 options.export_sourcedir))
            spec_dir = makedir(os.path.join(export_dir, options.export_specdir))

            # Move packaging files to final export dir
            gbp.log.debug("Exporting packaging files from '%s' to '%s'" %
                          (dump_dir, export_dir))
            for fname in os.listdir(dump_dir):
                src = os.path.join(dump_dir, fname)
                if fname == spec.specfile:
                    dst = os.path.join(spec_dir, fname)
                else:
                    dst = os.path.join(source_dir, fname)
                try:
                    shutil.copy2(src, dst)
                except IOError as err:
                    raise GbpError("Error exporting packaging files: %s" % err)
            spec.specdir = os.path.abspath(spec_dir)

            # Get/build the orig tarball
            if is_native(repo, options):
                if spec.orig_src and not options.no_create_orig:
                    # Just build source archive from the exported tree
                    gbp.log.info("Creating (native) source archive %s from '%s'"
                                 % (spec.orig_src['filename'], tree))
                    if spec.orig_src['compression']:
                        gbp.log.debug("Building source archive with "
                                      "compression '%s -%s'" %
                                      (spec.orig_src['compression'],
                                       options.comp_level))
                    orig_prefix = spec.orig_src['prefix']
                    if not git_archive(repo, spec, source_dir, tree,
                                       orig_prefix, options.comp_level,
                                       options.with_submodules):
                        raise GbpError("Cannot create source tarball at '%s'" %
                                       source_dir)
            # Non-native packages: create orig tarball from upstream
            elif spec.orig_src:
                prepare_upstream_tarball(repo, spec, options, source_dir)

            # 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 and not options.tag_only:
                if options.prebuild:
                    RunAtCommand(options.prebuild, shell=True,
                                 extra_env={'GBP_GIT_DIR': repo.git_dir,
                                            'GBP_BUILD_DIR': export_dir}
                                 )(dir=export_dir)

                # Finally build the package:
                if options.builder.startswith("rpmbuild"):
                    builder_args.append(os.path.join(spec.specdir,
                                        spec.specfile))
                else:
                    builder_args.append(spec.specfile)
                RunAtCommand(options.builder, builder_args, shell=True,
                             extra_env={'GBP_BUILD_DIR': export_dir}
                             )(dir=export_dir)
                if options.postbuild:
                    changes = os.path.abspath("%s/%s.changes" % (source_dir,
                                                                 spec.name))
                    gbp.log.debug("Looking for changes file %s" % changes)
                    Command(options.postbuild, shell=True,
                            extra_env={'GBP_CHANGES_FILE': changes,
                                       'GBP_BUILD_DIR': export_dir})()

        # Tag (note: tags the exported version)
        if options.tag or options.tag_only:
            gbp.log.info("Tagging %s" % rpm.compose_version_str(spec.version))
            tag = create_packaging_tag(repo, tree, spec.name, spec.version,
                                       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)

    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 as err:
        if len(err.__str__()):
            gbp.log.err(err)
        retval = 1
    finally:
        drop_index()
        del_tmpdir()

    if not options.tag_only:
        if spec and options.notify:
            summary = "Gbp-rpm %s" % ["failed", "successful"][not retval]
            message = ("Build of %s %s %s" % (spec.name,
                                              rpm.compose_version_str(spec.version),
                                              ["failed", "succeeded"][not retval]))
            if not gbp.notifications.notify(summary, message, options.notify):
                gbp.log.err("Failed to send notification")
                retval = 1

    return retval
Example #6
0
def import_spec_patches(repo, options):
    """
    apply a series of patches in a spec/packaging dir to branch
    the patch-queue branch for 'branch'

    @param repo: git repository to work on
    @param options: command options
    """
    current = repo.get_branch()
    # Get spec and related information
    if is_pq_branch(current):
        base = pq_branch_base(current)
        if options.force:
            spec = parse_spec(options, repo, base)
            spec_treeish = base
        else:
            raise GbpError("Already on a patch-queue branch '%s' - doing "
                           "nothing." % current)
    else:
        spec = parse_spec(options, repo)
        spec_treeish = None
        base = current
    upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag)
    packager = get_packager(spec)
    pq_branch = pq_branch_name(base)

    # Create pq-branch
    if repo.has_branch(pq_branch) and not options.force:
        raise GbpError("Patch-queue branch '%s' already exists. "
                       "Try 'switch' instead." % pq_branch)
    try:
        if repo.get_branch() == pq_branch:
            repo.force_head(upstream_commit, hard=True)
        else:
            repo.create_branch(pq_branch, upstream_commit, force=True)
    except GitRepositoryError as err:
        raise GbpError("Cannot create patch-queue branch '%s': %s" %
                       (pq_branch, err))

    # Put patches in a safe place
    if spec_treeish:
        packaging_tmp = tempfile.mkdtemp(prefix='dump_')
        packaging_tree = '%s:%s' % (spec_treeish, options.packaging_dir)
        dump_tree(repo,
                  packaging_tmp,
                  packaging_tree,
                  with_submodules=False,
                  recursive=False)
        spec.specdir = packaging_tmp
    in_queue = spec.patchseries()
    queue = safe_patches(in_queue)
    # Do import
    try:
        gbp.log.info("Switching to branch '%s'" % pq_branch)
        repo.set_branch(pq_branch)

        if not queue:
            return
        gbp.log.info("Trying to apply patches from branch '%s' onto '%s'" %
                     (base, upstream_commit))
        for patch in queue:
            gbp.log.debug("Applying %s" % patch.path)
            apply_and_commit_patch(repo, patch, packager)
    except (GbpError, GitRepositoryError) as err:
        repo.set_branch(base)
        repo.delete_branch(pq_branch)
        raise GbpError('Import failed: %s' % err)

    gbp.log.info("%d patches listed in '%s' imported on '%s'" %
                 (len(queue), spec.specfile, pq_branch))
Example #7
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 not options:
        return ExitCodes.parse_error

    if len(args) == 1:
        srpm = args[0]
        target = None
    elif len(args) == 2:
        srpm = args[0]
        target = args[1]
    else:
        gbp.log.err("Need to give exactly one package to import. Try --help.")
        return 1
    try:
        dirs['tmp_base'] = init_tmpdir(options.tmp_dir, 'import-srpm_')
    except GbpError as err:
        gbp.log.err(err)
        return 1
    try:
        if options.download:
            srpm = download_source(srpm)

        # 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(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
            target = target or spec.name
            repo = RpmGitRepository.create(target)
            os.chdir(repo.path)
            repo_setup.set_user_name_and_email(options.repo_user, options.repo_email, repo)

        if repo.bare:
            set_bare_repo_options(options)

        # Create more tempdirs
        dirs['origsrc'] = tempfile.mkdtemp(prefix='origsrc_')
        dirs['packaging_base'] = tempfile.mkdtemp(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'])
            sources = RpmUpstreamSource(orig_tarball)
            sources.unpack(dirs['origsrc'], options.filters)
        else:
            sources = None

        tag_str_fields = dict(spec.version, vendor=options.vendor.lower())
        if options.native:
            src_tag_format = options.packaging_tag
            src_tag = repo.version_to_tag(src_tag_format, tag_str_fields)
            upstream_tag = src_tag
            upstream_str_fields = tag_str_fields
        else:
            src_tag_format = options.upstream_tag
            src_tag = repo.version_to_tag(src_tag_format, tag_str_fields)
            upstream_str_fields = filter_version(tag_str_fields, 'release', 'epoch')
            upstream_tag = repo.version_to_tag(src_tag_format, upstream_str_fields)

        ver_str = compose_version_str(spec.version)

        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

        if is_empty:
            options.create_missing_branches = True

        # Determine author and committer info, currently same info is used
        # for both sources and packaging files
        author = None
        if spec.packager:
            match = re.match(r'(?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 sources
        if sources:
            src_commit = repo.find_version(src_tag_format, upstream_str_fields)
            if not src_commit:
                gbp.log.info("Tag %s not found, importing sources" % src_tag)

                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
                src_vendor = "Native" if options.native else "Upstream"
                msg = "%s version %s" % (src_vendor, spec.upstreamversion)
                src_commit = repo.commit_dir(sources.unpacked,
                                             "Import %s" % msg,
                                             branch,
                                             author=author,
                                             committer=committer,
                                             create_missing_branch=options.create_missing_branches)
                repo.create_tag(name=src_tag if options.native else upstream_tag,
                                msg=msg,
                                commit=src_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 sources:
            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 = repo.version_to_tag(options.packaging_tag, tag_str_fields)
            msg = "%s release %s" % (options.vendor, ver_str)

            if options.orphan_packaging or not sources:
                commit = repo.commit_dir(dirs['packaging_base'],
                                         "Import %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(sources.unpacked,
                                             options.packaging_dir)
                    os.mkdir(pkgsubdir)
                except OSError as err:
                    if err.errno != errno.EEXIST:
                        raise
                for fname in os.listdir(dirs['packaging']):
                    shutil.copy2(os.path.join(dirs['packaging'], fname),
                                 pkgsubdir)
                commit = repo.commit_dir(sources.unpacked,
                                         "Import %s" % msg,
                                         branch,
                                         other_parents=[src_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)

            # 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 str(err):
            gbp.log.err(err)
        ret = 1
    except NoSpecError as err:
        gbp.log.err("Failed determine spec file: %s" % err)
        ret = 1
    except SkipImport:
        skipped = True
    finally:
        os.chdir(dirs['top'])
        del_tmpdir()

    if not ret and not skipped:
        gbp.log.info("Version '%s' imported under '%s'" % (ver_str, repo.path))
    return ret
def main(argv):
    """Entry point for gbp-buildpackage-rpm"""
    retval = 0
    prefix = "git-"
    spec = None

    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:
        init_tmpdir(options.tmp_dir, prefix='buildpackage-rpm_')

        tree = get_tree(repo, options.export)
        spec = parse_spec(options, repo, treeish=tree)

        Command(options.cleaner, shell=True)()
        if not options.ignore_new:
            ret, out = repo.is_clean()
            if not ret:
                gbp.log.err(
                    "You have uncommitted changes in your source tree:")
                gbp.log.err(out)
                raise GbpError("Use --git-ignore-new 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.")

        # Dump from git to a temporary directory:
        packaging_tree = '%s:%s' % (tree, options.packaging_dir)
        dump_dir = tempfile.mkdtemp(prefix='packaging_')
        gbp.log.debug("Dumping packaging files to '%s'" % dump_dir)
        if not dump_tree(repo, dump_dir, packaging_tree, False, False):
            raise GbpError
        # Re-parse spec from dump dir to get version etc.
        spec = rpm.SpecFile(os.path.join(dump_dir, spec.specfile))

        if not options.tag_only:
            # Setup builder opts
            setup_builder(options, builder_args)
            if options.use_mock:
                setup_mock(options)

            # Prepare final export dirs
            export_dir = makedir(options.export_dir)
            source_dir = makedir(
                os.path.join(export_dir, options.export_sourcedir))
            spec_dir = makedir(os.path.join(export_dir,
                                            options.export_specdir))

            # Move packaging files to final export dir
            gbp.log.debug("Exporting packaging files from '%s' to '%s'" %
                          (dump_dir, export_dir))
            for fname in os.listdir(dump_dir):
                src = os.path.join(dump_dir, fname)
                if fname == spec.specfile:
                    dst = os.path.join(spec_dir, fname)
                else:
                    dst = os.path.join(source_dir, fname)
                try:
                    shutil.copy2(src, dst)
                except IOError as err:
                    raise GbpError("Error exporting packaging files: %s" % err)
            spec.specdir = os.path.abspath(spec_dir)

            # Get/build the orig tarball
            if is_native(repo, options):
                if spec.orig_src and not options.no_create_orig:
                    # Just build source archive from the exported tree
                    gbp.log.info(
                        "Creating (native) source archive %s from '%s'" %
                        (spec.orig_src['filename'], tree))
                    if spec.orig_src['compression']:
                        gbp.log.debug(
                            "Building source archive with "
                            "compression '%s -%s'" %
                            (spec.orig_src['compression'], options.comp_level))
                    orig_prefix = spec.orig_src['prefix']
                    if not git_archive(repo, spec, source_dir, tree,
                                       orig_prefix, options.comp_level,
                                       options.with_submodules):
                        raise GbpError("Cannot create source tarball at '%s'" %
                                       source_dir)
            # Non-native packages: create orig tarball from upstream
            elif spec.orig_src:
                prepare_upstream_tarball(repo, spec, options, source_dir)

            # 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 and not options.tag_only:
                if options.prebuild:
                    RunAtCommand(options.prebuild,
                                 shell=True,
                                 extra_env={
                                     'GBP_GIT_DIR': repo.git_dir,
                                     'GBP_BUILD_DIR': export_dir
                                 })(dir=export_dir)

                # Finally build the package:
                if options.builder.startswith("rpmbuild"):
                    builder_args.append(
                        os.path.join(spec.specdir, spec.specfile))
                else:
                    builder_args.append(spec.specfile)
                RunAtCommand(options.builder,
                             builder_args,
                             shell=True,
                             extra_env={'GBP_BUILD_DIR':
                                        export_dir})(dir=export_dir)
                if options.postbuild:
                    changes = os.path.abspath("%s/%s.changes" %
                                              (source_dir, spec.name))
                    gbp.log.debug("Looking for changes file %s" % changes)
                    Command(options.postbuild,
                            shell=True,
                            extra_env={
                                'GBP_CHANGES_FILE': changes,
                                'GBP_BUILD_DIR': export_dir
                            })()

        # Tag (note: tags the exported version)
        if options.tag or options.tag_only:
            gbp.log.info("Tagging %s" % rpm.compose_version_str(spec.version))
            tag = create_packaging_tag(repo, tree, spec.name, spec.version,
                                       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)

    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 as err:
        if len(err.__str__()):
            gbp.log.err(err)
        retval = 1
    finally:
        drop_index()
        del_tmpdir()

    if not options.tag_only:
        if spec and options.notify:
            summary = "Gbp-rpm %s" % ["failed", "successful"][not retval]
            message = ("Build of %s %s %s" %
                       (spec.name, rpm.compose_version_str(
                           spec.version), ["failed", "succeeded"][not retval]))
            if not gbp.notifications.notify(summary, message, options.notify):
                gbp.log.err("Failed to send notification")
                retval = 1

    return retval
Example #9
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 not options:
        return ExitCodes.parse_error

    if len(args) == 1:
        srpm = args[0]
        target = None
    elif len(args) == 2:
        srpm = args[0]
        target = args[1]
    else:
        gbp.log.err("Need to give exactly one package to import. Try --help.")
        return 1
    try:
        dirs['tmp_base'] = init_tmpdir(options.tmp_dir, 'import-srpm_')
    except GbpError as err:
        gbp.log.err(err)
        return 1
    try:
        if options.download:
            srpm = download_source(srpm)

        # 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(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
            target = target or spec.name
            repo = RpmGitRepository.create(target)
            os.chdir(repo.path)
            repo_setup.set_user_name_and_email(options.repo_user, options.repo_email, repo)

        if repo.bare:
            set_bare_repo_options(options)

        # Create more tempdirs
        dirs['origsrc'] = tempfile.mkdtemp(prefix='origsrc_')
        dirs['packaging_base'] = tempfile.mkdtemp(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'])
            sources = RpmUpstreamSource(orig_tarball)
            sources.unpack(dirs['origsrc'], options.filters)
        else:
            sources = None

        tag_str_fields = dict(spec.version, vendor=options.vendor.lower())
        if options.native:
            upstream_tag_format = options.packaging_tag
            upstream_str_fields = tag_str_fields
        else:
            upstream_tag_format = options.upstream_tag
            upstream_str_fields = filter_version(tag_str_fields, 'release', 'epoch')
        upstream_tag = repo.version_to_tag(upstream_tag_format, upstream_str_fields)

        full_version = compose_version_str(spec.version)
        if repo.find_version(options.packaging_tag, tag_str_fields):
            gbp.log.warn("Version %s already imported." % full_version)

            if options.allow_same_version:
                gbp.log.info("Moving tag of version '%s' since import forced" %
                             full_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 sources and packaging files
        author = None
        if spec.packager:
            match = re.match(r'(?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 sources
        if sources:
            upstream_commit = repo.find_version(upstream_tag_format, upstream_str_fields)
            if not upstream_commit:
                gbp.log.info("Tag %s not found, importing sources" % upstream_tag)

                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
                upstream_vendor = "Native" if options.native else "Upstream"
                upstream_version = full_version if options.native else spec.upstreamversion
                msg = "%s version %s" % (upstream_vendor, upstream_version)
                if options.vcs_tag:
                    vcs_tag = repo.version_to_tag(options.vcs_tag, upstream_str_fields)
                    parents = [repo.rev_parse("%s^{}" % vcs_tag)]
                else:
                    parents = None
                upstream_commit = repo.commit_dir(sources.unpacked,
                                                  "Import %s" % msg,
                                                  branch,
                                                  other_parents=parents,
                                                  author=author,
                                                  committer=committer,
                                                  create_missing_branch=options.create_missing_branches)
                if not (options.native and options.skip_packaging_tag):
                    repo.create_tag(name=upstream_tag,
                                    msg=msg,
                                    commit=upstream_commit,
                                    sign=options.sign_tags,
                                    keyid=options.keyid)

                if not options.native:
                    if options.pristine_tar:
                        archive_fmt = Archive.parse_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 sources:
            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

            msg = "%s release %s" % (options.vendor, full_version)

            if options.orphan_packaging or not sources:
                commit = repo.commit_dir(dirs['packaging_base'],
                                         "Import %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(sources.unpacked,
                                             options.packaging_dir)
                    os.mkdir(pkgsubdir)
                except OSError as err:
                    if err.errno != errno.EEXIST:
                        raise
                for fname in os.listdir(dirs['packaging']):
                    shutil.copy2(os.path.join(dirs['packaging'], fname),
                                 pkgsubdir)
                commit = repo.commit_dir(sources.unpacked,
                                         "Import %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)

            # Create packaging tag
            if not options.skip_packaging_tag:
                tag = repo.version_to_tag(options.packaging_tag, tag_str_fields)
                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 str(err):
            gbp.log.err(err)
        ret = 1
    except NoSpecError as err:
        gbp.log.err("Failed determine spec file: %s" % err)
        ret = 1
    except SkipImport:
        skipped = True
    finally:
        os.chdir(dirs['top'])
        del_tmpdir()

    if not ret and not skipped:
        gbp.log.info("Version '%s' imported under '%s'" % (full_version, repo.path))
    return ret
Example #10
0
def import_spec_patches(repo, options):
    """
    apply a series of patches in a spec/packaging dir to branch
    the patch-queue branch for 'branch'

    @param repo: git repository to work on
    @param options: command options
    """
    current = repo.get_branch()
    # Get spec and related information
    if is_pq_branch(current):
        base = pq_branch_base(current)
        if options.force:
            spec = parse_spec(options, repo, base)
            spec_treeish = base
        else:
            raise GbpError("Already on a patch-queue branch '%s' - doing "
                           "nothing." % current)
    else:
        spec = parse_spec(options, repo)
        spec_treeish = None
        base = current
    upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag)
    packager = get_packager(spec)
    pq_branch = pq_branch_name(base)

    # Create pq-branch
    if repo.has_branch(pq_branch) and not options.force:
        raise GbpError("Patch-queue branch '%s' already exists. "
                       "Try 'switch' instead." % pq_branch)
    try:
        if repo.get_branch() == pq_branch:
            repo.force_head(upstream_commit, hard=True)
        else:
            repo.create_branch(pq_branch, upstream_commit, force=True)
    except GitRepositoryError as err:
        raise GbpError("Cannot create patch-queue branch '%s': %s" %
                       (pq_branch, err))

    # Put patches in a safe place
    if spec_treeish:
        packaging_tmp = tempfile.mkdtemp(prefix='dump_')
        packaging_tree = '%s:%s' % (spec_treeish, options.packaging_dir)
        dump_tree(repo, packaging_tmp, packaging_tree, with_submodules=False,
                  recursive=False)
        spec.specdir = packaging_tmp
    in_queue = spec.patchseries()
    queue = safe_patches(in_queue)
    # Do import
    try:
        gbp.log.info("Switching to branch '%s'" % pq_branch)
        repo.set_branch(pq_branch)

        if not queue:
            return
        gbp.log.info("Trying to apply patches from branch '%s' onto '%s'" %
                     (base, upstream_commit))
        for patch in queue:
            gbp.log.debug("Applying %s" % patch.path)
            apply_and_commit_patch(repo, patch, packager)
    except (GbpError, GitRepositoryError) as err:
        repo.set_branch(base)
        repo.delete_branch(pq_branch)
        raise GbpError('Import failed: %s' % err)

    gbp.log.info("%d patches listed in '%s' imported on '%s'" % (len(queue), spec.specfile,
                                                                 pq_branch))