Beispiel #1
0
    def check(self, is_dirty=True, all_pushed=True):
        """Check various status of current repository

        :param bool is_dirty: Default to True. To check whether there is
            uncommitted changes.
        :param bool all_pushed: Default to True. To check whether all changes
            are pushed.
        :raises rpkgError: if any unexpected status is detected. For example,
            if changes are not committed yet.

        NOTE: has_namespace is removed because it should belong to package
              metadata and be handled there using package repository information
              provided by this module.
        """
        if is_dirty:
            if self.repo.is_dirty():
                raise rpkgError('%s has uncommitted changes.  Use git status '
                                'to see details' % self.path)

        get_config = self.git.get_config
        if all_pushed:
            branch = self.repo.active_branch
            try:
                remote = get_config('branch.%s.remote' % branch)
                merge = get_config('branch.%s.merge' % branch).replace(
                    'refs/heads', remote)
            except git.GitCommandError:
                raise rpkgError(
                    'Branch {0} does not track remote branch.\n'
                    'Use the following command to fix that:\n'
                    '    git branch -u origin/REMOTE_BRANCH_NAME'.format(
                        branch))
            if self.git.rev_list('%s...%s' % (merge, branch)):
                raise rpkgError('There are unpushed changes in your repo')
Beispiel #2
0
    def load_nameverrel(self):
        """Set the release of a package module."""

        cmd = ['rpm']
        cmd.extend(self.rpmdefines)
        # We make sure there is a space at the end of our query so that
        # we can split it later.  When there are subpackages, we get a
        # listing for each subpackage.  We only care about the first.
        cmd.extend([
            '-q', '--qf', '"%{NAME} %{EPOCH} %{VERSION} %{RELEASE}??"',
            '--specfile',
            '"%s/%s"' % (self.module_build_dir, self.spec)
        ])
        joined_cmd = ' '.join(cmd)

        try:
            proc = subprocess.Popen(joined_cmd,
                                    shell=True,
                                    universal_newlines=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            output, err = proc.communicate()
        except Exception as e:
            if err:
                self.log.debug(
                    'Errors occoured while running following command to get N-V-R-E:'
                )
                self.log.debug(joined_cmd)
                self.log.error(err)
            raise rpkgError('Could not query n-v-r of %s: %s' %
                            (self.module_name, e))
        if err:
            self.log.debug(
                'Errors occoured while running following command to get N-V-R-E:'
            )
            self.log.debug(joined_cmd)
            self.log.error(err)

        # Get just the output, then split it by ??, grab the first and split
        # again to get ver and rel
        first_line_output = output.split('??')[0]
        parts = first_line_output.split()
        if len(parts) != 4:
            raise rpkgError('Could not get n-v-r-e from %r' %
                            first_line_output)
        (self._module_name_spec, self._epoch, self._ver, self._rel) = parts

        # Most packages don't include a "Epoch: 0" line, in which case RPM
        # returns '(none)'
        if self._epoch == "(none)":
            self._epoch = "0"
Beispiel #3
0
    def load_kojisession(self, anon=False):
        """Initiate a koji session.

        The koji session can be logged in or anonymous
        """

        koji_config = self.read_koji_config()

        # save the weburl and topurl for later use as well
        self._kojiweburl = koji_config['weburl']
        self._topurl = koji_config['topurl']

        self.log.debug('Initiating a %s session to %s',
                       os.path.basename(self.build_client),
                       koji_config['server'])

        # Build session options used to create instance of ClientSession
        session_opts = self.create_koji_session_opts(koji_config)

        try:
            session = koji.ClientSession(koji_config['server'], session_opts)
        except:
            raise rpkgError('Could not initiate %s session' %
                            os.path.basename(self.build_client))
        else:
            self._kojisession = session

        self.login_koji_session(koji_config, self._kojisession)
Beispiel #4
0
    def load_spec(self):
        """This sets the spec attribute"""

        deadpackage = False

        # Get a list of files in the path we're looking at
        files = os.listdir(self.module_build_dir)
        # Search the files for the first one that ends with ".spec"
        for f in files:
            if f.endswith('.spec') and f.startswith(
                    self.module_name) and not f.startswith('.'):
                self._spec = f
                return
            if f == 'dead.package':
                deadpackage = True
        if deadpackage:
            raise rpkgError('No spec file found. This package is retired')
        else:
            raise rpkgError('No spec file found.')
Beispiel #5
0
    def mock_config(self, target=None, arch=None):
        """Generate a mock config based on branch data.

        Can use option target and arch to override autodiscovery.
        Will return the mock config file text.
        """

        if (target is None):
            target = self.target
        if (arch is None):
            arch = self.arch

        # Figure out if we have a valid build target
        build_target = self.kojisession.getBuildTarget(target)
        if not build_target:
            raise rpkgError('Unknown build target: %s\n'
                            'Consider using the --target option' % target)

        try:
            repoid = self.kojisession.getRepo(
                build_target['build_tag_name'])['id']
        except Exception:
            raise rpkgError('Could not find a valid build repo')

        proxy = '10.144.1.10:8080'
        with open("/etc/yum.conf") as f:
            for line in f:
                if 'proxy' in line:
                    proxy = line.split('=')[1]
        # Generate the config
        config = koji.genMockConfig('%s-%s' % (target, arch),
                                    arch,
                                    distribution=self.disttag,
                                    tag_name=build_target['build_tag_name'],
                                    repoid=repoid,
                                    topurl=self.topurl,
                                    yum_proxy=proxy)

        # Return the mess
        return (config)
Beispiel #6
0
    def load_cmd(self):
        """This sets up the cmd object"""

        # Set target if we got it as an option
        target = None
        if hasattr(self.args, 'target') and self.args.target:
            target = self.args.target

        # load items from the config file
        items = dict(self.config.items(self.name, raw=True))

        try:
            dg_namespaced = self.config.getboolean(self.name,
                                                   "distgit_namespaced")
        except ValueError:
            raise rpkgError('distgit_namespaced option must be a boolean')
        except configparser.NoOptionError:
            dg_namespaced = False

        # Read comma separated list of kerberos realms
        realms = [
            realm for realm in items.get("kerberos_realms", '').split(',')
            if realm
        ]

        # Create the cmd object
        self._cmd = self.site.Commands(self.args.path,
                                       items['lookaside'],
                                       items['lookasidehash'],
                                       items['lookaside_cgi'],
                                       items['gitbaseurl'],
                                       items['anongiturl'],
                                       items['branchre'],
                                       items['kojiconfig'],
                                       items['build_client'],
                                       user=self.args.user,
                                       dist=self.args.dist
                                       or self.args.release,
                                       target=target,
                                       quiet=self.args.q,
                                       distgit_namespaced=dg_namespaced,
                                       realms=realms)

        self._cmd.module_name = self.args.module_name
        self._cmd.password = self.args.password
        self._cmd.runas = self.args.runas
        self._cmd.debug = self.args.debug
        self._cmd.verbose = self.args.v
        self._cmd.clone_config = items.get('clone_config')

        if hasattr(self.args, 'version_hash'):
            self._cmd.version_hash = self.args.version_hash
Beispiel #7
0
    def load_branch_merge(self):
        """Find the remote tracking branch from the branch we're on.

        The goal of this function is to catch if we are on a branch we can make
        some assumptions about.  If there is no merge point then we raise and
        ask the user to specify.

        NOTE: do not handle default branch merge. Command line option --release
              overrides return value from this method, which should be handled
              in caller side.
        """
        try:
            local_branch = self.repo.active_branch.name
        except TypeError as e:
            raise rpkgError('Repo in inconsistent state: %s' % e)
        try:
            merge = self.git.get_config(
                'branch.{0}.merge'.format(local_branch))
        except git.GitCommandError:
            raise rpkgError('Unable to find remote branch.  Use --release')
        # Trim off the refs/heads so that we're just working with
        # the branch name
        merge = merge.replace('refs/heads/', '', 1)
        self._branch_merge = merge
Beispiel #8
0
    def git_clone(self,
                  module,
                  giturl,
                  path=None,
                  branch=None,
                  bare_dir=None,
                  anon=False,
                  target=None):
        cmd = ['git', 'clone']
        if self.quiet:
            cmd.append('-q')
        # do the clone
        if branch and bare_dir:
            raise rpkgError('Cannot combine bare cloning with a branch')
        elif branch:
            # For now we have to use switch branch
            self.log.debug('Checking out a specific branch %s', giturl)
            cmd.extend(['-b', branch, giturl])
        elif bare_dir:
            self.log.debug('Cloning %s bare', giturl)
            cmd.extend(['--bare', giturl])
            if not target:
                cmd.append(bare_dir)
        else:
            self.log.debug('Cloning %s', giturl)
            cmd.extend([giturl])

        if not bare_dir:
            # --bare and --origin are incompatible
            cmd.extend(['--origin', self.default_branch_remote])

        if target:
            self.log.debug('Cloning into: %s', target)
            cmd.append(target)

        self._run_command(cmd, cwd=path)

        if self.clone_config:
            base_module = self.get_base_module(module)
            git_dir = target if target else bare_dir if bare_dir else base_module
            conf_git = git.Git(os.path.join(path, git_dir))
            self._clone_config(conf_git, module)
Beispiel #9
0
 def load_push_url(self):
     """Find the pushurl or url of remote of branch we're on."""
     try:
         url = self.repo.git.remote('get-url', '--push', self.branch_remote)
     except git.GitCommandError as e:
         try:
             url = self.git.get_config('remote.%s.pushurl' %
                                       self.branch_remote)
         except git.GitCommandError:
             try:
                 url = self.git.get_config('remote.%s.url' %
                                           self.branch_remote)
             except git.GitCommandError as e:
                 raise rpkgError(
                     'Unable to find remote push url: {0}'.format(e))
     if isinstance(url, six.text_type):
         # GitPython >= 1.0 return unicode. It must be encoded to string.
         self._push_url = url
     else:
         self._push_url = url.decode('utf-8')
Beispiel #10
0
    def build(self,
              skip_tag=False,
              scratch=False,
              background=False,
              url=None,
              chain=None,
              arches=None,
              sets=False,
              nvr_check=True):
        """Initiate a build of the module.  Available options are:

        skip_tag: Skip the tag action after the build

        scratch: Perform a scratch build

        background: Perform the build with a low priority

        url: A url to an uploaded srpm to build from

        chain: A chain build set

        arches: A set of arches to limit the scratch build for

        sets: A boolean to let us know whether or not the chain has sets

        nvr_check: A boolean; locally construct NVR and submit a build only if
                   NVR doesn't exist in a build system

        This function submits the task to koji and returns the taskID

        It is up to the client to wait or watch the task.
        """

        # Ensure the repo exists as well as repo data and site data
        # build up the command that a user would issue
        cmd = [self.build_client]
        # construct the url

        url = "git+" + self.spec_file_git + '?#'
        if self.version_hash == None:
            url += rcppkg_utils.get_local_spec_head(self.module_build_dir)
        else:
            url += self.version_hash

        # Check to see if the target is valid
        build_target = self.kojisession.getBuildTarget(self.target)
        if not build_target:
            raise rpkgError('Unknown build target: %s' % self.target)
        # see if the dest tag is locked
        dest_tag = self.kojisession.getTag(build_target['dest_tag_name'])
        if not dest_tag:
            raise rpkgError('Unknown destination tag %s' %
                            build_target['dest_tag_name'])
        if dest_tag['locked'] and not scratch:
            raise rpkgError('Destination tag %s is locked' % dest_tag['name'])
        # If we're chain building, make sure inheritance works
        if chain:
            cmd.append('chain-build')
            ancestors = self.kojisession.getFullInheritance(
                build_target['build_tag'])
            ancestors = [ancestor['parent_id'] for ancestor in ancestors]
            if dest_tag['id'] not in [build_target['build_tag']] + ancestors:
                raise rpkgError('Packages in destination tag '
                                '%(dest_tag_name)s are not inherited by'
                                'build tag %(build_tag_name)s' % build_target)
        else:
            cmd.append('build')
        # define our dictionary for options
        opts = {}
        # Set a placeholder for the build priority
        priority = None
        if skip_tag:
            opts['skip_tag'] = True
            cmd.append('--skip-tag')
        if scratch:
            opts['scratch'] = True
            cmd.append('--scratch')
        if background:
            cmd.append('--background')
            priority = 5  # magic koji number :/
        if arches:
            if not scratch:
                raise rpkgError('Cannot override arches for non-scratch '
                                'builds')
            for arch in arches:
                if not re.match(r'^[0-9a-zA-Z_.]+$', arch):
                    raise rpkgError('Invalid architecture name: %s' % arch)
            cmd.append('--arch-override=%s' % ','.join(arches))
            opts['arch_override'] = ' '.join(arches)

        cmd.append(self.target)

        if url.endswith('.src.rpm'):
            srpm = os.path.basename(url)
            build_reference = srpm
        else:
            try:
                build_reference = self.nvr
            except rpkgError as error:
                self.log.warning(error)
                if nvr_check:
                    self.log.info('Note: You can skip NVR construction & NVR'
                                  ' check with --skip-nvr-check. See help for'
                                  ' more info.')
                    raise rpkgError(
                        'Cannot continue without properly constructed NVR.')
                else:
                    self.log.info('NVR checking will be skipped so I do not'
                                  ' care that I am not able to construct NVR.'
                                  '  I will refer this build by package name'
                                  ' in following messages.')
                    build_reference = self.module_name

        # Now submit the task and get the task_id to return
        # Handle the chain build version
        if chain:
            self.log.debug('Adding %s to the chain', url)
            # If we're dealing with build sets the behaviour of the last
            # package changes, and we add it to the last (potentially empty)
            # set.  Otherwise the last package just gets added to the end of
            # the chain.
            if sets:
                chain[-1].append(url)
            else:
                chain.append([url])
            # This next list comp is ugly, but it's how we properly get a :
            # put in between each build set
            cmd.extend(' : '.join(
                [' '.join(build_sets) for build_sets in chain]).split())
            self.log.info('Chain building %s + %s for %s', build_reference,
                          chain[:-1], self.target)
            self.log.debug(
                'Building chain %s for %s with options %s and a priority of %s',
                chain, self.target, opts, priority)
            self.log.debug(' '.join(cmd))
            task_id = self.kojisession.chainBuild(chain,
                                                  self.target,
                                                  opts,
                                                  priority=priority)
        # Now handle the normal build
        else:
            cmd.append(url)
            self.log.info('Building %s for %s', build_reference, self.target)
            self.log.debug(
                'Building %s for %s with options %s and a priority of %s', url,
                self.target, opts, priority)
            self.log.debug(' '.join(cmd))
            task_id = self.kojisession.build(url,
                                             self.target,
                                             opts,
                                             priority=priority)
        self.log.info('Created task: %s', task_id)
        self.log.info('Task info: %s/taskinfo?taskID=%s', self.kojiweburl,
                      task_id)
        return task_id