lrossett / centos / centpkg

Forked from centos/centpkg 4 years ago
Clone
Blob Blame History Raw
# pylint: disable=line-too-long,abstract-class-not-used

'''
    Top level function library for centpkg
'''

# Author(s):
#            Jesse Keating <jkeating@redhat.com>
#            Pat Riehecky <riehecky@fnal.gov>
#            Brian Stinson <bstinson@ksu.edu>
#
# 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.  See http://www.gnu.org/copyleft/gpl.html for
# the full text of the license.


import re
import warnings

import git
from pyrpkg import Commands, rpkgError
from pyrpkg.utils import cached_property

# doc/centpkg_man_page.py uses the 'cli' import
from . import cli  # noqa
from .lookaside import StreamLookasideCache, SIGLookasideCache


_DEFAULT_VERSION = '9'


class DistGitDirectory(object):

    signame = None
    centosversion = _DEFAULT_VERSION
    projectname = None
    releasename = None
    distrobranch = False
    repo = None
    git_origin_substr = 'git@gitlab.com/redhat/centos-stream'

    def __init__(self, branchtext, repo_path=None):
        if repo_path:
            self.repo = git.cmd.Git(repo_path)
        sigtobranchre = r'c(?P<centosversion>\d+[s]?)-sig-(?P<signame>\w+)-?(?P<projectname>\w+)?-?(?P<releasename>\w+)?'
        distrobranchre = r'c(?P<centosversion>\d+)-?(?P<projectname>\w+)?'
        oldbranchre = r'(?P<signame>\w+)(?P<centosversion>\d)'
        sigmatch = re.match(sigtobranchre, branchtext)
        distromatch = re.match(distrobranchre, branchtext)
        oldbranchmatch = re.match(oldbranchre, branchtext)
        if sigmatch:
            gd = sigmatch.groupdict()
            self.signame = gd['signame']
            self.centosversion = gd['centosversion']

            # Users have the option to specify (or not specify) common in their
            # git repos. Ww need to handle these cases because common is not a
            # project nor is it a release.
            if gd['projectname'] != 'common':
                self.projectname = gd['projectname']
            if gd['releasename'] != 'common':
                self.releasename = gd['releasename']
        elif distromatch:
            gd = distromatch.groupdict()
            self.distrobranch = True
            self.signame = 'centos'
            self.centosversion = gd['centosversion']

            if gd['projectname'] != 'common':
                self.projectname = gd['projectname']
        elif oldbranchmatch:
            warnings.warn("This branch is deprecated and will be removed soon",
                          DeprecationWarning)
        else:
            if not self.is_fork():
                raise ValueError("Branchname: {0} is not valid".format(branchtext))
            else:
                self.distrobranch = True
                self.signame = 'centos'
                self.projectname = self.get_origin().split('_')[-1].replace('.git', '')

                warnings.warn('Remote "origin" was detected as a fork, ignoring branch name checking')

    def get_origin(self):
        if self.repo is None:
            return ''
        return self.repo.execute('git config --get remote.origin.url'.split())

    def is_fork(self):
        """
        Check if origin remote repository is using a fork url.

        Returns
        bool
            A boolean flag indicating if origin remote url is using
            a forked repository url.
        """
        # git+ssh://git@gitlab.com/redhat/centos-stream/rpms/binutils.git
        if self.repo is None:
            return False
        return self.git_origin_substr not in self.get_origin()


    @property
    def target(self):
        projectorcommon = self.projectname
        releaseorcommon = self.releasename

        if self.distrobranch:
            if self.centosversion not in ('6', '7'):
                return 'c{}s-candidate'.format(self.centosversion)
            else:
                return '-'.join(filter(None, ['c'+self.centosversion,
                                              projectorcommon]))

        if not releaseorcommon:
            if not projectorcommon or projectorcommon == 'common':
                projectorcommon = 'common'
            else:
                releaseorcommon = 'common'

        return '-'.join(filter(None, [self.signame+self.centosversion,
                                      projectorcommon, releaseorcommon])) + '-el{0}'.format(self.centosversion)


class Commands(Commands):
    '''
        For the pyrpkg commands with centpkg behavior
    '''
    def __init__(self, *args, **kwargs):
        '''
            Init the object and some configuration details.
        '''
        super(Commands, self).__init__(*args, **kwargs)
        # For MD5 we want to use the old format of source files, the BSD format
        # should only be used when configured for SHA512
        self.source_entry_type = 'bsd' if self.lookasidehash != 'md5' else 'old'
        self.branchre = 'c\d{1,}(s)?(tream)?|master'

    @property
    def distgitdir(self):
        return DistGitDirectory(self.branch_merge, repo_path=self.path)

    @cached_property
    def lookasidecache(self):
        if self.distgitdir.distrobranch:
            return StreamLookasideCache(self.lookasidehash,
                                        self.lookaside,
                                        self.lookaside_cgi,
                                        )
        else:
            return SIGLookasideCache(self.lookasidehash,
                                     self.lookaside,
                                     self.lookaside_cgi,
                                     self.repo_name,
                                     self.branch_merge)

    # redefined loaders
    def load_rpmdefines(self):
        '''
            Populate rpmdefines based on branch data
        '''

        if not self.distgitdir.centosversion:
            raise rpkgError('Could not get the OS version from the branch:{0}'.format(self.branch_merge))

        self._distvar = self.distgitdir.centosversion
        self._distval = self._distvar.replace('.', '_')

        self._disttag = 'el%s' % self._distval
        self._rpmdefines = ["--define '_sourcedir %s'" % self.layout.sourcedir,
                            "--define '_specdir %s'" % self.layout.specdir,
                            "--define '_builddir %s'" % self.layout.builddir,
                            "--define '_srcrpmdir %s'" % self.layout.srcrpmdir,
                            "--define '_rpmdir %s'" % self.layout.rpmdir,
                            "--define 'dist .%s'" % self._disttag,
                            # int and float this to remove the decimal
                            "--define '%s 1'" % self._disttag]
        self.log.debug("RPMDefines: %s" % self._rpmdefines)

    def construct_build_url(self, *args, **kwargs):
        """Override build URL for CentOS/Fedora Koji build

        In CentOS/Fedora Koji, anonymous URL should have prefix "git+https://"
        """
        url = super(Commands, self).construct_build_url(*args, **kwargs)
        return 'git+{0}'.format(url)

    def load_target(self):
        """ This sets the target attribute (used for mock and koji) """

        self._target = self.distgitdir.target