From 4a288a4c3ee60a55f7d9ac4c6678efdd6614eb89 Mon Sep 17 00:00:00 2001 From: Mike McLean Date: Jun 27 2017 16:58:15 +0000 Subject: first stab at inverted scm rules --- diff --git a/koji/daemon.py b/koji/daemon.py index d479de6..aecb7c1 100644 --- a/koji/daemon.py +++ b/koji/daemon.py @@ -284,8 +284,17 @@ class SCM(object): Verify that the host and repository of this SCM is in the provided list of allowed repositories. - allowed is a space-separated list of host:repository[:use_common[:source_cmd]] tuples. Incorrectly-formatted - tuples will be ignored. + allowed is a space-separated list entries in one of the following forms: + + host:repository[:use_common[:source_cmd]] + !host:repository + + Incorrectly-formatted entries will be ignored. + + The first form allows a specific host:repository and optionally sets a + few options for it. + + The second form explicitly blocks a specific host:repository TODO If use_common is not present, kojid will attempt to checkout a common/ directory from the repository. If use_common is set to no, off, false, or 0, it will not attempt to checkout a common/ @@ -295,26 +304,36 @@ class SCM(object): It is generally used to retrieve source files from a remote location. If no source_cmd is specified, "make sources" is run by default. """ + is_allowed = False for allowed_scm in allowed.split(): scm_tuple = allowed_scm.split(':') - if len(scm_tuple) >= 2: - if fnmatch(self.host, scm_tuple[0]) and fnmatch(self.repository, scm_tuple[1]): - # SCM host:repository is in the allowed list - # check if we specify a value for use_common - if len(scm_tuple) >= 3: - if scm_tuple[2].lower() in ('no', 'off', 'false', '0'): - self.use_common = False - # check if we specify a custom source_cmd - if len(scm_tuple) >= 4: - if scm_tuple[3]: - self.source_cmd = scm_tuple[3].split(',') - else: - # there was nothing after the trailing :, so they don't want to run a source_cmd at all - self.source_cmd = None - break - else: + if len(scm_tuple) < 2: self.logger.warn('Ignoring incorrectly formatted SCM host:repository: %s' % allowed_scm) - else: + continue + host_pat = scm_tuple[0] + repo_pat = scm_tuple[1] + invert = False + if host_pat.startwith('!'): + invert = True + host_pat = host_pat[1:] + if fnmatch(self.host, host_pat) and fnmatch(self.repository, repo_pat): + # match + if invert: + break + is_allowed = True + # check if we specify a value for use_common + if len(scm_tuple) >= 3: + if scm_tuple[2].lower() in ('no', 'off', 'false', '0'): + self.use_common = False + # check if we specify a custom source_cmd + if len(scm_tuple) >= 4: + if scm_tuple[3]: + self.source_cmd = scm_tuple[3].split(',') + else: + # there was nothing after the trailing :, so they don't want to run a source_cmd at all + self.source_cmd = None + break + if not allowed: raise koji.BuildError('%s:%s is not in the list of allowed SCMs' % (self.host, self.repository)) def checkout(self, scmdir, session=None, uploadpath=None, logfile=None):