Hello community, here is the log from the commit of package spec-cleaner for openSUSE:Factory checked in at 2017-06-08 16:38:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/spec-cleaner (Old) and /work/SRC/openSUSE:Factory/.spec-cleaner.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "spec-cleaner" Thu Jun 8 16:38:32 2017 rev:42 rq:501887 version:0.9.6 Changes: -------- --- /work/SRC/openSUSE:Factory/spec-cleaner/spec-cleaner.changes 2017-05-17 17:20:24.691666785 +0200 +++ /work/SRC/openSUSE:Factory/.spec-cleaner.new/spec-cleaner.changes 2017-06-08 16:38:35.905364661 +0200 @@ -1,0 +2,8 @@ +Thu Jun 8 11:25:30 UTC 2017 - [email protected] + +- Version update to 0.9.6: + * Deduplication of requires/buildrequires + * Preamble detection fixups + * Detect buildignores + +------------------------------------------------------------------- Old: ---- spec-cleaner-0.9.5.tar.gz New: ---- spec-cleaner-0.9.6.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ spec-cleaner.spec ++++++ --- /var/tmp/diff_new_pack.DoHZUx/_old 2017-06-08 16:38:36.489282208 +0200 +++ /var/tmp/diff_new_pack.DoHZUx/_new 2017-06-08 16:38:36.493281643 +0200 @@ -20,7 +20,7 @@ # This is used for Fedora, we need to sync this %{!?py3_ver: %define py3_ver %{python3_version}} Name: spec-cleaner -Version: 0.9.5 +Version: 0.9.6 Release: 0 Summary: .spec file cleaner License: BSD-3-Clause ++++++ spec-cleaner-0.9.5.tar.gz -> spec-cleaner-0.9.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/__init__.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/__init__.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/__init__.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/__init__.py 2017-06-08 13:14:12.000000000 +0200 @@ -12,7 +12,7 @@ from .rpmcleaner import RpmSpecCleaner -__version__ = '0.9.5' +__version__ = '0.9.6' def process_args(argv): @@ -42,6 +42,8 @@ help='inline the changes directly to the parsed file.') parser.add_argument('-m', '--minimal', action='store_true', help='run in minimal mode that does not do anything intrusive (ie. just sets the Copyright)') + parser.add_argument('--no-curlification', action='store_true', + help='do not convert variables bracketing (%{macro}) and keep it as it was on the input') parser.add_argument('--no-copyright', action='store_true', help='do not include official SUSE copyright hear and just keep what is present') output_group.add_argument('-o', '--output', default='', @@ -84,6 +86,7 @@ 'diff': options.diff, 'diff_prog': options.diff_prog, 'minimal': options.minimal, + 'no_curlification': options.no_curlification, 'no_copyright': options.no_copyright, 'perl': options.perl, 'tex': options.tex, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/dependency_parser.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/dependency_parser.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/dependency_parser.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/dependency_parser.py 2017-06-08 13:14:12.000000000 +0200 @@ -1,21 +1,13 @@ -"""RPM dependency lines parser and helpers. - -Contains class DependencyParser which parses string and generates -token tree. For common manipulation is method flat_out() useful, it -just splits dependencies into list. - -For future development is useful find_end_of_macro(). - -""" import re import logging - from .rpmexception import NoMatchException +from .rpmrequirestoken import RpmRequiresToken -DEBUG = None +chunk_types = [ + 'text', 'space', 'macro', 'operator', 'version' +] -if DEBUG: - logging.basicConfig(level=logging.DEBUG) +state_types = ['start', 'name', 'operator', 'version'] re_parens = re.compile( r'(' + @@ -39,22 +31,19 @@ re_macro_unbraced = re.compile('%[A-Za-z0-9_]{3,}') re_version_operator = re.compile('(>=|<=|=>|=<|>|<|=)') +logger = logging.getLogger("DepParser") +# Switch to logging.DEBUG if needed +logger.setLevel(logging.ERROR) def find_end_of_macro(string, regex, opening, closing): - if DEBUG: - logger = logging.getLogger('DepParser') - else: - logger = None macro = string[0:2] # eat '%{' string = string[2:] opened = 1 while opened and string: - if logger: - logger.debug('opened: %d string: %s', opened, string) try: - bite, string = consume_chars(regex, string, logger) + bite, string = consume_chars(regex, string) except NoMatchException: raise Exception('unexpected parser error when looking for end of ' 'macro') @@ -68,216 +57,205 @@ if opened: raise Exception('Unexpectedly met end of string when looking for end ' 'of macro') - return macro + return macro, string -def consume_chars(regex, string, logger=None): - if logger: - logger.debug('consume_chars: regex: "%s"', regex.pattern) - logger.debug('consume_chars: string:"%s"', string) +def consume_chars(regex, string): match = regex.match(string) if match: end = match.end() - if logger: - logger.debug('consume_chars: split "%s", "%s"', - string[0:end], string[end:]) return string[0:end], string[end:] else: - raise NoMatchException('Expected match failed') + raise NoMatchException('Expected match failed (string: "%s", regex: "%s" )' % (string, regex.pattern)) +def read_boolean(string): + return find_end_of_macro(string, re_parens, '(', ')') -class DependencyParser(object): +def read_macro(string): + if string[1] == '{': + regex = re_braces + opening = '{' + closing = '}' + elif string[1] == '(': + regex = re_parens + opening = '(' + closing = ')' + else: + raise Exception('Unexpected character') - logger = None + return find_end_of_macro(string, regex, opening, closing) - def __init__(self, string): - self.string = string.rstrip() - self.token = [] - self.parsed = [] - self.state = ['name'] - if DEBUG: - self.logger = logging.getLogger('DepParser') - self.logger.setLevel(logging.DEBUG) - self.state_change_loop() - - def dump_token(self): - if self.logger: - self.logger.debug('dump_token') - self.status() - if not self.token: - return - if self.token[0].isspace(): - self.token = self.token[1:] - if not self.token: - return - self.parsed.append(self.token) - self.token = [] - self.state = ['name'] +def read_next_chunk(string): + chunk = '' + chunk_type = '' + + if not string: + return '', '', 'text' + + if string[0:2] in ['>=', '<=', '=>', '=<']: + chunk = string[0:2] + chunk_type = 'operator' + rest = string[2:] + + elif string[0:1] in ['<', '>', '=']: + chunk = string[0:1] + chunk_type = 'operator' + rest = string[1:] + + elif string[0].isspace(): + chunk = '' + chunk_type = 'space' + rest = consume_chars(re_spaces, string)[1] + + elif string[0:2] == '%%': + chunk = '%%' + chunk_type = 'text' + rest = string[2:] + + elif string[0:2] in ['%{', '%(']: + chunk, rest = read_macro(string) + chunk_type = 'macro' + + elif string[0] == '%': + chunk, rest = consume_chars(re_macro_unbraced, string) + chunk_type = 'macro' + + elif string[0] == '(': + chunk, rest = read_boolean(string) + chunk_type = 'macro' + + elif string[0] == ',': + chunk = '' + chunk_type = 'space' + rest = string[1:] - def state_change_loop(self): - while self.string: - if self.state[-1] == 'name': - self.read_name() - elif self.state[-1] == 'version_operator': - self.read_version_operator() - elif self.state[-1] == 'version': - self.read_version() - elif self.state[-1] == 'macro_name': - self.read_macro_name() - elif self.state[-1] == 'macro_shell': - self.read_macro_shell() - elif self.state[-1] == 'macro_unbraced': - self.read_macro_unbraced() - elif self.state[-1] == 'spaces': - self.read_spaces() - self.dump_token() - - def status(self): - if self.logger: - self.logger.debug('token: %s', self.token) - self.logger.debug('string: "%s"', self.string) - self.logger.debug('parsed: %s', self.parsed) - self.logger.debug('state: %s', self.state) - self.logger.debug('--------------------------------') + else: + chunk, rest = consume_chars(re_name, string) + chunk_type = 'text' - def read_spaces(self, state_change=True): - try: - spaces, self.string = consume_chars( - re_spaces, self.string, self.logger) - self.token.append(spaces) - if state_change: - self.state.pop() # remove 'spaces' state - # if we were reading version, space definitely means - # end of that - if self.state[-1] == 'version': - self.dump_token() - self.status() - except NoMatchException: - pass + return (rest, chunk, chunk_type) - def read_unknown(self): - ''' - Try to identify, what is to be read now. - ''' - if self.string[0:2] in ['>=', '<=', '=>', '=<'] or \ - self.string[0:1] in ['<', '>', '=']: - self.state.append('version') - self.state.append('version_operator') - elif self.string[0] == ' ': - self.state.append('spaces') - elif self.string[0:2] == '%{': - self.state.append('macro_name') - elif self.string[0:2] == '%(': - self.state.append('macro_shell') - elif self.string[0:2] == '%%': - self.read_double_percent() - elif self.string[0] == '%': - self.state.append('macro_unbraced') - elif self.string[0] == ',': - self.string = self.string[1:] - self.dump_token() - if self.logger: - self.logger.debug('read_unknown: states: %s string: "%s"', - self.state, self.string) +class DepParserError(Exception): + pass - def read_name(self): - try: - name, self.string = consume_chars( - re_name, self.string, self.logger) - if self.token and self.token[-1].isspace(): - self.dump_token() - self.token.append(name) - self.status() - except NoMatchException: - self.read_unknown() - def read_double_percent(self): - self.token.append('%%') - self.string = self.string[2:] +class DependencyParser: + def __init__(self, line): + self.line = line - def read_macro_unbraced(self): - try: - if ( - self.state[-2] == 'name' and self.token and - self.token[-1].isspace()): - self.dump_token() - self.state.append('macro_unbraced') - except IndexError: - pass - try: - # 3 or more alphanumeric characters - macro, self.string = consume_chars( - re_macro_unbraced, self.string, self.logger) - self.token.append(macro) - self.state.pop() # remove 'macro_unbraced' state - self.status() - except NoMatchException: - self.read_unknown() + def parse(self): + # adding comma will cause flush in the end of line + self.string = self.line + "," + self.parsed = [] + self.token = [] + self.state = 'start' + self.space = False + self.token_name = '' + self.token_operator = None + self.token_version = None + self.go_on = True + while self.go_on: + self.string, self.next, self.next_type = read_next_chunk(self.string) + logger.debug( + """======== + chunk: '%s' + chunk_type: '%s' + rest: '%s' + token: '%s' + parsed: '%s'""", + self.next, self.next_type, self.string, self.token, self.parsed) + self.state_change() - def read_version_operator(self): - try: - operator, self.string = consume_chars( - re_version_operator, self.string, self.logger) - self.token.append(operator) - # Note: this part is a bit tricky, I need to read possible - # spaces or tabs now so I won't get to [ ..., 'version', - # 'spaces' ] state before the end - self.read_spaces(state_change=False) - self.state.pop() # get rid of 'version_operator' - self.status() - except NoMatchException: - self.read_unknown() + def flat_out(self): + self.parse() + result = [] + for name, operator, ver in self.parsed: + result.append(RpmRequiresToken(name, operator, ver)) + return result - def read_version(self): - try: - version, self.string = consume_chars( - re_version, self.string, self.logger) - self.token.append(version) - self.status() - except NoMatchException: - self.read_unknown() + def flush(self): + self.parsed.append( + (self.token_name, self.token_operator, self.token_version) + ) + # cleanup state + self.token = [] + self.token_name = '' + self.token_operator = None + self.token_version = None + if not self.string: + self.go_on = False + + def reconstitute_token(self): + r = ''.join(self.token) + logger.debug("reconstituting '%s'", r) + self.token = [] + return r - def read_macro_name(self): - try: - if ( - self.state[-2] == 'name' and - self.token and self.token[-1].isspace()): - self.dump_token() - self.state.append('macro_name') - except IndexError: - pass - macro = find_end_of_macro(self.string, re_braces, '{', '}') - # remove macro from string - self.string = self.string[len(macro):] - self.token.append(macro) - # now we expect previous state - self.state.pop() - self.status() + def name_state_change(self): + if self.next_type in ['text', 'macro']: + if self.space: + logger.debug('text after space --> flush') + self.token_name = self.reconstitute_token() + self.space = False + self.flush() + elif self.next_type == 'space': + self.space = True + elif self.next_type == 'operator': + self.token_name = self.reconstitute_token() + self.state = 'operator' + self.space = False + + self.token.append(self.next) + + + def operator_state_change(self): + if self.next_type in ['text', 'macro']: + self.state = 'version' + self.token_operator = self.reconstitute_token() + self.space = False + elif self.next_type == 'space': + self.space = True + elif self.next_type == 'operator': + if self.space: + raise DepParserError("found operator after operator") - def read_macro_shell(self): - try: - if ( - self.state[-2] == 'name' and - self.token and self.token[-1].isspace()): - self.dump_token() - self.state.append('macro_shell') - except IndexError: + self.token.append(self.next) + + + def version_state_change(self): + if self.next_type == 'text': + pass + elif self.next_type == 'space': + self.token_version = self.reconstitute_token() + self.flush() + self.state = 'name' + self.space = False + elif self.next_type == 'macro': pass - macro = find_end_of_macro(self.string, re_parens, '(', ')') - self.string = self.string[len(macro):] - self.token.append(macro) - # now we expect previous state - self.state.pop() - self.status() + elif self.next_type == 'operator': + raise DepParserError("found operator after version") - def flat_out(self): - result = [] - for token in self.parsed: - if isinstance(token, list): - if token and token[-1].isspace(): - token = token[:-1] - result.append(''.join(token)) - else: - if not token.isspace(): - result.append(token) - return result + self.token.append(self.next) + + def start_state_change(self): + if self.next_type == 'text': + self.state = 'name' + elif self.next_type == 'space': + pass + elif self.next_type == 'macro': + self.state = 'name' + elif self.next_type == 'operator': + raise DepParserError("found operator when name expected") + + self.token.append(self.next) + + def state_change(self): + if self.state == 'name': + self.name_state_change() + elif self.state == 'operator': + self.operator_state_change() + elif self.state == 'version': + self.version_state_change() + elif self.state == 'start': + self.start_state_change() + logger.debug("new state: %s", self.state) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmcleaner.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmcleaner.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmcleaner.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmcleaner.py 2017-06-08 13:14:12.000000000 +0200 @@ -156,25 +156,10 @@ def _detect_preamble_section(self, line): # This is seriously ugly but can't think of cleaner way - # WARN: Keep in sync with rpmregexps for rpmpreamble section if not isinstance(self.current_section, (RpmPreamble, RpmPackage)): if any([re.match(line) for re in [ - self.reg.re_bcond_with, self.reg.re_requires, - self.reg.re_requires_phase, self.reg.re_buildrequires, - self.reg.re_prereq, self.reg.re_recommends, - self.reg.re_suggests, self.reg.re_name, - self.reg.re_version, self.reg.re_release, - self.reg.re_license, self.reg.re_summary, - self.reg.re_summary_localized, self.reg.re_url, - self.reg.re_group, self.reg.re_vendor, - self.reg.re_source, self.reg.re_patch, - self.reg.re_enhances, self.reg.re_supplements, - self.reg.re_conflicts, self.reg.re_provides, - self.reg.re_obsoletes, self.reg.re_buildroot, - self.reg.re_buildarch, self.reg.re_epoch, - self.reg.re_icon, self.reg.re_packager, - self.reg.re_debugpkg, self.reg.re_requires_eq, - self.reg.re_preamble_prefix, + self.reg.re_bcond_with, + self.reg.re_debugpkg, ]]): return True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmhelpers.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmhelpers.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmhelpers.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmhelpers.py 2017-06-08 13:14:12.000000000 +0200 @@ -5,6 +5,7 @@ from .fileutils import FileUtils from .rpmexception import RpmException +from .rpmrequirestoken import RpmRequiresToken LICENSES_CHANGES = 'licenses_changes.txt' TEX_CONVERSIONS = 'tex_conversions.txt' @@ -139,7 +140,7 @@ licenses[index] = my_license # create back new string with replaced licenses - s = ' '.join(licenses).replace("( ", "(").replace(" )", ")") + s = ' '.join(licenses).replace("( ", "(").replace(" )", ")").replace(' and ', ' AND ').replace(' or ', ' OR ') return s @@ -195,11 +196,17 @@ """ if isinstance(group, str): return [group] + elif isinstance(group, RpmRequiresToken): + items = [] + if group.comments: + items += group.comments + items.append(group) + return items elif isinstance(group, list): - x = [] + items = [] for subgroup in group: - x += add_group(subgroup) - return x + items += add_group(subgroup) + return items else: raise RpmException('Unknown type of group in preamble: %s' % type(group)) @@ -208,9 +215,12 @@ """ Find pkgconfig() statement in the list and return true if matched """ + + pkgconfig_found = find_pkgconfig_declaration(elements) for i in elements: - if 'pkgconfig(' in i and not find_pkgconfig_declaration(elements): - return True + if isinstance(i, RpmRequiresToken): + if 'pkgconfig(' in i.name and not pkgconfig_found: + return True return False @@ -219,6 +229,7 @@ Find if there is direct pkgconfig dependency in the paragraph """ for i in elements: - if 'pkgconfig ' in i or i.endswith('pkgconfig'): - return True + if isinstance(i, RpmRequiresToken): + if 'pkgconfig ' in i.name or i.name.endswith('pkgconfig'): + return True return False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmpreamble.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmpreamble.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmpreamble.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmpreamble.py 2017-06-08 13:14:12.000000000 +0200 @@ -12,6 +12,7 @@ from .rpmpreambleelements import RpmPreambleElements from .dependency_parser import DependencyParser from .rpmhelpers import fix_license +from .rpmrequirestoken import RpmRequiresToken class RpmPreamble(Section): @@ -67,11 +68,6 @@ self.allowed_groups = options['allowed_groups'] # start the object self.paragraph = RpmPreambleElements(options) - # initialize list of groups that need to pass over conversion fixer - self.categories_with_package_tokens = self.paragraph.categories_with_sorted_package_tokens[:] - # these packages actually need fixing after we sent the values to - # reorder them - self.categories_with_package_tokens.append('provides_obsoletes') # license handling self.subpkglicense = options['subpkglicense'] # modname detection @@ -89,6 +85,7 @@ # for source, we have a special match to keep the source number # for patch, we have a special match to keep the patch number 'buildrequires': self.reg.re_buildrequires, + 'buildignores': self.reg.re_buildignores, 'conflicts': self.reg.re_conflicts, # for prereq we append warning comment so we don't mess it there 'requires': self.reg.re_requires, @@ -101,6 +98,7 @@ 'buildarch': self.reg.re_buildarch, 'excludearch': self.reg.re_excludearch, 'exclusivearch': self.reg.re_exclusivearch, + 'tail': self.reg.re_tail_macros, } # deprecated definitions that we no longer want to see @@ -210,44 +208,20 @@ self._condition_bcond = False self.paragraph.items['conditions'] = [] - def _split_name_and_version(self, value): - # split the name and version from the requires element - if self.reg.re_version_separator.match(value): - match = self.reg.re_version_separator.match(value) - pkgname = match.group(1) - version = match.group(2) - if not version: - version = '' - return pkgname, version - - def _fix_pkgconfig_name(self, value): - # we just rename pkgconfig names to one unified one working everywhere - pkgname, version = self._split_name_and_version(value) - if pkgname == 'pkgconfig(pkg-config)' or \ - pkgname == 'pkg-config': - # If we have pkgconfig dep in pkgconfig it is nuts, replace it - return 'pkgconfig{0}'.format(version) - else: - return value - - def _pkgname_to_brackety(self, value, name, conversions): - # we just want the pkgname if we have version string there - # and for the pkgconfig deps we need to put the version into - # the braces - pkgname, version = self._split_name_and_version(value) + def _pkgname_to_brackety(self, token, brackety, conversions): converted = [] - if pkgname == 'pkgconfig': - return [value] - if pkgname not in conversions: - # first check if the package is in the replacements - return [value] + # just never convert pkgconfig dependency + # The same if we do not have a match + if token.name == 'pkgconfig' or token.name not in conversions: + return token else: # first split the data - convers_list = conversions[pkgname].split() + convers_list = conversions[token.name].split() # then add each pkgconfig to the list # print pkgconf_list for j in convers_list: - converted.append('{0}({1}){2}'.format(name, j, version)) + name = '{0}({1})'.format(brackety, j) + converted.append(RpmRequiresToken(name, token.operator, token.version)) return converted def _fix_list_of_packages(self, value, category): @@ -261,22 +235,12 @@ # loop over all and do formatting as we can get more deps for one expanded = [] for token in tokens: - # there is allowed syntax => and =< ; hidious - token = token.replace('=<', '<=') - token = token.replace('=>', '>=') - # we also skip all various rpm-macroed content as it + # skip all various rpm-macroed content as it # is usually not easy to determine how that should be # split - if token.startswith('%'): + if token.name.startswith('%'): expanded.append(token) continue - # cleanup whitespace - token = token.replace(' ', '') - token = re.sub(r'([<>]=?|=)', r' \1 ', token) - if not token: - continue - # replace pkgconfig name first - token = self._fix_pkgconfig_name(token) # in scriptlets we most probably do not want the converted deps if category != 'prereq' and category != 'requires_phase': # here we go with descending priority to find match and replace @@ -292,12 +256,10 @@ token = self._pkgname_to_brackety(token, 'tex', self.tex_conversions) if not isinstance(token, list) and self.cmake: token = self._pkgname_to_brackety(token, 'cmake', self.cmake_conversions) - if isinstance(token, str): - expanded.append(token) - else: + if isinstance(token, list): expanded += token - # and then sort them :) - expanded.sort() + else: + expanded.append(token) return expanded def _add_line_value_to(self, category, value, key=None): @@ -309,24 +271,31 @@ """ key = self.paragraph.compile_category_prefix(category, key) - if category in self.categories_with_package_tokens: + if category in self.paragraph.categories_with_package_tokens: values = self._fix_list_of_packages(value, category) + for value in values: + if isinstance(value, str): + value = key + value + else: + value.prefix = key + self._add_line_to(category, value) else: - values = [value] - - for value in values: line = key + value self._add_line_to(category, line) def _add_line_to(self, category, line): if self.paragraph.current_group: - self.paragraph.current_group.append(line) - self.paragraph.items[category].append(self.paragraph.current_group) + if isinstance(line, RpmRequiresToken): + line.comments = self.paragraph.current_group + self.paragraph.items[category].append(line) + else: + self.paragraph.current_group.append(line) + self.paragraph.items[category].append(self.paragraph.current_group) self.paragraph.current_group = [] else: self.paragraph.items[category].append(line) - self.previous_line = line + self.previous_line = str(line) def add(self, line): line = self._complete_cleanup(line) @@ -378,7 +347,7 @@ self.previous_line = line return - elif self.reg.re_comment.match(line): + elif self.reg.re_comment.match(line) and not self.reg.re_buildignores.match(line): if line or self.previous_line: self.paragraph.current_group.append(line) self.previous_line = line @@ -506,9 +475,9 @@ match = regexp.match(line) if match: # instead of matching first group as there is only one, - # take the last group + # take the last group (including "whole match" if no groups present) # (so I can have more advanced regexp for RPM tags) - self._add_line_value_to(category, match.groups()[len(match.groups()) - 1]) + self._add_line_value_to(category, match.group(len(match.groups()))) return self._add_line_to('misc', line) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmpreambleelements.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmpreambleelements.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmpreambleelements.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmpreambleelements.py 2017-06-08 13:14:12.000000000 +0200 @@ -2,6 +2,7 @@ from .rpmhelpers import sort_uniq, add_group, find_pkgconfig_statement, find_pkgconfig_declaration, fix_license from .rpmexception import RpmException +from .rpmrequirestoken import RpmRequiresToken class RpmPreambleElements(object): """ @@ -22,6 +23,7 @@ 'nosource': 'NoSource', 'patch': 'Patch', 'buildrequires': 'BuildRequires', + 'buildignores': '#!BuildIgnore', 'conflicts': 'Conflicts', 'prereq': 'PreReq', 'requires': 'Requires', @@ -54,6 +56,7 @@ 'nosource', 'patch', 'buildrequires', + 'buildignores', 'requires', 'requires_eq', 'prereq', @@ -71,11 +74,13 @@ 'misc', 'build_conditions', 'conditions', + 'tail', ] # categories that are sorted based on value in them categories_with_sorted_package_tokens = [ 'buildrequires', + 'buildignores', 'prereq', 'requires', 'requires_eq', @@ -108,14 +113,18 @@ self.license = options['license'] # dict of license replacement options self.license_conversions = options['license_conversions'] + # initialize list of groups that need to pass over conversion fixer + self.categories_with_package_tokens = self.categories_with_sorted_package_tokens[:] + # these packages actually need fixing after we sent the values to + # reorder them + self.categories_with_package_tokens.append('provides_obsoletes') def _sort_helper_key(self, a): - t = type(a) - if t == str: - key = a - elif t == list: + if isinstance(a, str) or isinstance(a, RpmRequiresToken): + key = str(a) + elif isinstance(a, list): # if this is a list then all items except last are comment or whitespace - key = a[-1] + key = str(a[-1]) else: raise RpmException('Unknown type during sort: %s' % t) @@ -142,7 +151,7 @@ Add value to specified keystore """ key = self.compile_category_prefix(category, key) - line = key + value + line = RpmRequiresToken(value, None, None, key) self.items[category].append(line) def _add_pkgconfig_buildrequires(self, nested): @@ -173,12 +182,24 @@ """ message = '# FIXME: use proper Requires(pre/post/preun/...)' + prereq_found = False + message_found = False + # Check first if we have prereq values included - if not any("PreReq" in s for s in elements): + for element in elements: + if isinstance(element, RpmRequiresToken): + if element.prefix.startswith('PreReq'): + prereq_found = True + break + if not prereq_found: return elements # Verify the message is not already present - if any(message in s for s in elements): + for element in elements: + if isinstance(element, str): + if element.startswith(message): + message_found = True + if message_found: return elements # add the message on the first position after any whitespace @@ -187,6 +208,56 @@ return elements + def _remove_duplicates(self, elements): + """ + Remove duplicate requires/buildrequires/etc + """ + results = [] + for element in elements: + match = False + # anything else than requirestoken + if not isinstance(element, RpmRequiresToken): + results.append(element) + continue + # no results stored yet + if not results: + results.append(element) + continue + # search already stored content + for index, item in enumerate(results): + # names and prefix must always match + if item.name == element.name and item.prefix == element.prefix: + # do we have full match on everything + if item.version == element.version and item.operator == element.operator: + # append comment if needed only as we are 100% match + if element.comments: + tmp = results[index] + if tmp.comments: + tmp.comments += element.comments + else: + tmp.comments = element.comments + results[index] = tmp + match = True + break + # new one specifies version + if not item.version and element.version: + if item.comments: + if element.comments: + element.comments += item.comments + else: + element.comments = item.comments + results[index] = element + match = True + break + # for version determination which could be ommited one + # must use rpm versionCompare to get same results + # unfortunately it uses too many resources so we simply + # leave this to the maintainer + if not match: + results.append(element) + return results + + def _run_global_list_operations(self, phase, elements): """ Run all the checks that need to be run on the finalized sorted list @@ -205,7 +276,9 @@ """ keylen = len('BuildRequires: ') - if key: + if category == 'tail': + return '' + elif key: pass elif category in self.category_to_key: key = self.category_to_key[category] @@ -228,6 +301,7 @@ Do the finalized output for the itemlist. """ lines = [] + elements = [] # add license to the package if missing and needed if needs_license and not self.items['license']: @@ -235,10 +309,15 @@ self._insert_value('license', self.license) # add pkgconfig dep self._add_pkgconfig_buildrequires(nested) + # remove duplicates + for i in self.categories_with_package_tokens: + self.items[i] = self._remove_duplicates(self.items[i]) for i in self.categories_order: sorted_list = [] + if i in self.categories_with_sorted_package_tokens: + self.items[i].sort(key=self._sort_helper_key) # sort-out within the ordered groups based on the key - if i in self.categories_with_sorted_package_tokens + self.categories_with_sorted_keyword_tokens: + if i in self.categories_with_sorted_keyword_tokens: self.items[i].sort(key=self._sort_helper_key) self.items[i] = sort_uniq(self.items[i]) # flatten the list from list of lists as no reordering is planned @@ -251,4 +330,7 @@ # random stuff that should be at the end anyway. lines += add_group(self.current_group) self.current_group = [] - return lines + + for line in lines: + elements.append(str(line)) + return elements diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmregexp.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmregexp.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmregexp.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmregexp.py 2017-06-08 13:14:12.000000000 +0200 @@ -42,6 +42,7 @@ re_nosource = re.compile(r'^NoSource:\s*(.*)', re.IGNORECASE) re_patch = re.compile(r'^((?:#[#\s]*)?)Patch(\d*):\s*(\S*)', re.IGNORECASE) re_buildrequires = re.compile(r'^BuildRequires:\s*(.*)', re.IGNORECASE) + re_buildignores = re.compile(r'^#!BuildIgnore:\s*(.*)', re.IGNORECASE) re_prereq = re.compile(r'^PreReq:\s*(.*)', re.IGNORECASE) re_requires = re.compile(r'^Requires:\s*(.*)', re.IGNORECASE) re_requires_phase = re.compile(r'^Requires(\([^)]+\)):\s*(.*)', re.IGNORECASE) @@ -65,6 +66,7 @@ re_bcond_with = re.compile(r'^\s*%bcond_with(out)?\s*(.*)', re.IGNORECASE) re_autoreqprov = re.compile(r'^\s*AutoReqProv:.*$', re.IGNORECASE) re_debugpkg = re.compile(r'^%{?(debug_package|___debug_install_post)}?\s*$', re.IGNORECASE) + re_tail_macros = re.compile(r'^%{?python_subpackages}?') re_preamble_prefix = re.compile(r'^Prefix:\s*(.*)', re.IGNORECASE) # here we need to grab all submacros with rpm calls so just match almost # everything diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmrequirestoken.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmrequirestoken.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmrequirestoken.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmrequirestoken.py 2017-06-08 13:14:12.000000000 +0200 @@ -5,35 +5,52 @@ Class containing informations about the dependency token Can be used to specify all the values present on the line Later on we use this to do various conversions - - prefix name comparator version + + prefix name operator version BuildRequires: boringpackage >= 5.2.8 """ - + name = None - comparator = None + operator = None version = None prefix = None - - def __init__(self, name, comparator = None, version = None, prefix = None): + comments = None + + def __init__(self, name, operator = None, version = None, prefix = None): self.prefix = prefix self.name = name - self.comparator = comparator + self.operator = operator self.version = version - - def dump_token(self): + + def _format_operator(self, operator): + """ + Make sure the operators look sane and not use all permutations + """ + operator = operator.replace('=<', '<=') + operator = operator.replace('=>', '>=') + return operator + + def _format_name(self, name): + # we just rename pkgconfig names to one unified one working everywhere + if name == 'pkgconfig(pkg-config)' or name == 'pkg-config': + name = 'pkgconfig' + return name + + def __str__(self): """ Output it all on nice pretty line """ + self.name = self._format_name(self.name) if not self.prefix: raise RpmException('No defined prefix in RequiresToken') if not self.name: raise RpmException('No defined name in RequiresToken') string = self.prefix + self.name - if self.version and not self.comparator: - raise RpmException('Have defined version and no comparator %s' % self.version) + if self.version and not self.operator: + raise RpmException('Have defined version and no operator %s' % self.version) if self.version: - string += ' ' + self.comparator + ' ' + self.version - + self.operator = self._format_operator(self.operator) + string += ' ' + self.operator + ' ' + self.version + return string diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmsection.py new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmsection.py --- old/spec-cleaner-spec-cleaner-0.9.5/spec_cleaner/rpmsection.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/spec_cleaner/rpmsection.py 2017-06-08 13:14:12.000000000 +0200 @@ -18,6 +18,7 @@ self.previous_line = None self.spec = options['specfile'] self.minimal = options['minimal'] + self.no_curlification = options['no_curlification'] self.reg = options['reg'] # Are we inside of conditional or not self.condition = False @@ -33,7 +34,7 @@ line = line.rstrip() if not line.startswith('#'): - if not self.minimal: + if not self.minimal and not self.no_curlification: line = self.embrace_macros(line) line = self.replace_buildroot(line) line = self.replace_optflags(line) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/acceptance-tests.py new/spec-cleaner-spec-cleaner-0.9.6/tests/acceptance-tests.py --- old/spec-cleaner-spec-cleaner-0.9.5/tests/acceptance-tests.py 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/acceptance-tests.py 2017-06-08 13:14:12.000000000 +0200 @@ -32,6 +32,7 @@ 'diff': False, 'diff_prog': 'vimdiff', 'minimal': False, + 'no_curlification': False, 'no_copyright': True, 'tex': False, 'perl': False, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/in/boolean.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/in/boolean.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/in/boolean.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/in/boolean.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,7 @@ +Requires: (pkgA or pkgB or pkgC) +Requires: (pkgA or (pkgB and pkgC)) +Requires: (pkgA >= 3.2 or pkgB) +Supplements: (foo and (lang-support-cz or lang-support-all)) +Conflicts: (pkgA and pkgB) +Recommends: (myPkg-langCZ if langsupportCZ) +Requires: (myPkg-backend-mariaDB if mariaDB else sqlite) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/in/buildignore.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/in/buildignore.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/in/buildignore.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/in/buildignore.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,4 @@ +Name: buildignore +#!BuildIgnore: xerces-j2 xml-commons xml-commons-apis xml-commons-resolver +BuildRoot: bla +BuildRequires: compiler diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/in/description.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/in/description.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/in/description.spec 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/in/description.spec 2017-06-08 13:14:12.000000000 +0200 @@ -34,3 +34,9 @@ Oswald Buddenhagen <[email protected]> Theodore Ts'o <[email protected]> Nicolas Boullis <[email protected]> + +%description other +This project contains reference implementations, test cases, and other +documents under source code control for Java Specification Request 305: +Annotations for Software Defect Detection. More information at the Google +group: http://groups.google.com/group/jsr-305. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/in/licenseoptions.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/in/licenseoptions.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/in/licenseoptions.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/in/licenseoptions.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,11 @@ +Name: licenses +License: GPL-2.0 or LGPL-2.1 + +%package samelicense +Summary: blabla +License: ( GPL-2.0 and GPL-3.0) or MIT + + +%package differentone +Summary: otherblabla +License: GPL-2.0+ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/in/patterns.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/in/patterns.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/in/patterns.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/in/patterns.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,11 @@ +%package dhcp_dns_server +%pattern_serverfunctions +Summary: DHCP and DNS Server +Group: Metapackages +Provides: pattern() = dhcp_dns_server +Provides: pattern-icon() = yast-dns-server +Provides: pattern-order() = 3040 +Provides: pattern-visible() +Provides: patterns-openSUSE-dhcp_dns_server = %{version} +Obsoletes: patterns-openSUSE-dhcp_dns_server < %{version} +Requires: pattern() = basesystem diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/in/python_subpackages.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/in/python_subpackages.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/in/python_subpackages.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/in/python_subpackages.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,9 @@ +Name: python-subpackages +BuildRequires: %{python_module foo} +%ifpython2 +Requires: python2-backports.abc +%endif +%python_subpackages + +%description +bla bla diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/in/requires.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/in/requires.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/in/requires.spec 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/in/requires.spec 2017-06-08 13:14:12.000000000 +0200 @@ -22,3 +22,11 @@ Provides: %{name} = 0.3.0+gitbcaa Obsoletes: %{name} = 0.3.0+gitbcaa Requires: alsa%{dep_postfix} >= 1.0.23 + +BuildRequires: yast2-core-devel +BuildRequires: yast2-core-devel >= 2.16.37 +BuildRequires: yast2-ycp-ui-bindings-devel +BuildRequires: yast2-ycp-ui-bindings-devel >= 2.16.37 +BuildRequires: alsa >= 1.0 +BuildRequires: alsa >= 1.3 +BuildRequires: alsa < 3.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out/boolean.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out/boolean.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out/boolean.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out/boolean.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,9 @@ +Requires: (myPkg-backend-mariaDB if mariaDB else sqlite) +Requires: (pkgA >= 3.2 or pkgB) +Requires: (pkgA or (pkgB and pkgC)) +Requires: (pkgA or pkgB or pkgC) +Recommends: (myPkg-langCZ if langsupportCZ) +Supplements: (foo and (lang-support-cz or lang-support-all)) +Conflicts: (pkgA and pkgB) + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out/buildignore.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out/buildignore.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out/buildignore.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out/buildignore.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,9 @@ +Name: buildignore +BuildRequires: compiler +#!BuildIgnore: xerces-j2 +#!BuildIgnore: xml-commons +#!BuildIgnore: xml-commons-apis +#!BuildIgnore: xml-commons-resolver +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out/description.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out/description.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out/description.spec 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out/description.spec 2017-06-08 13:14:12.000000000 +0200 @@ -13,4 +13,10 @@ %description somethingelse Another subpkg +%description other +This project contains reference implementations, test cases, and other +documents under source code control for Java Specification Request 305: +Annotations for Software Defect Detection. More information at the Google +group: http://groups.google.com/group/jsr-305. + %changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out/licenseand.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out/licenseand.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out/licenseand.spec 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out/licenseand.spec 2017-06-08 13:14:12.000000000 +0200 @@ -1,7 +1,7 @@ -License: GPL-2.0 and GPL-3.0 +License: GPL-2.0 AND GPL-3.0 %package test -License: BSD and GPL-3.0 +License: BSD AND GPL-3.0 %package test2 License: MIT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out/licenseoptions.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out/licenseoptions.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out/licenseoptions.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out/licenseoptions.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,12 @@ +Name: licenses +License: GPL-2.0 OR LGPL-2.1 + +%package samelicense +Summary: blabla +License: (GPL-2.0 AND GPL-3.0) OR MIT + +%package differentone +Summary: otherblabla +License: GPL-2.0+ + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out/patterns.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out/patterns.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out/patterns.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out/patterns.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,13 @@ +%package dhcp_dns_server +Summary: DHCP and DNS Server +Group: Metapackages +Requires: pattern() = basesystem +Provides: pattern() = dhcp_dns_server +Provides: pattern-icon() = yast-dns-server +Provides: pattern-order() = 3040 +Provides: pattern-visible() +Provides: patterns-openSUSE-dhcp_dns_server = %{version} +Obsoletes: patterns-openSUSE-dhcp_dns_server < %{version} +%{pattern_serverfunctions} + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out/python_subpackages.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out/python_subpackages.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out/python_subpackages.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out/python_subpackages.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,11 @@ +Name: python-subpackages +BuildRequires: %{python_module foo} +%ifpython2 +Requires: python2-backports.abc +%endif +%python_subpackages + +%description +bla bla + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out/requires.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out/requires.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out/requires.spec 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out/requires.spec 2017-06-08 13:14:12.000000000 +0200 @@ -1,13 +1,19 @@ BuildRequires: %{rubygem fast_gettext} BuildRequires: %{rubygem rails >= 3.2} BuildRequires: aaa < 3.2.1 +BuildRequires: alsa < 3.0 +BuildRequires: alsa >= 1.0 +BuildRequires: alsa >= 1.3 BuildRequires: bbb BuildRequires: eee = %{version}-%{release} BuildRequires: iii <= 4.2.1 BuildRequires: jjj > %{version} BuildRequires: kkk +BuildRequires: pkgconfig BuildRequires: rrr >= %{version} BuildRequires: zzz +BuildRequires: pkgconfig(yast2-core) >= 2.16.37 +BuildRequires: pkgconfig(yast2-ycp-ui-bindings) >= 2.16.37 Requires: %{libname} >= %{version} Requires: %{some_packagename} >= %{some_version} Requires: aaa < 3.2.1 @@ -24,7 +30,6 @@ Requires: pkgconfig(glib-2.0) Requires: pkgconfig(libcurl) # FIXME: use proper Requires(pre/post/preun/...) -PreReq: aaa PreReq: aaa < 3.2.1 PreReq: eee = %{version}-%{release} PreReq: iii <= 4.2.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/boolean.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/boolean.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/boolean.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/boolean.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,9 @@ +Requires: (myPkg-backend-mariaDB if mariaDB else sqlite) +Requires: (pkgA >= 3.2 or pkgB) +Requires: (pkgA or (pkgB and pkgC)) +Requires: (pkgA or pkgB or pkgC) +Recommends: (myPkg-langCZ if langsupportCZ) +Supplements: (foo and (lang-support-cz or lang-support-all)) +Conflicts: (pkgA and pkgB) + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/buildignore.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/buildignore.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/buildignore.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/buildignore.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,9 @@ +Name: buildignore +BuildRequires: compiler +#!BuildIgnore: xerces-j2 +#!BuildIgnore: xml-commons +#!BuildIgnore: xml-commons-apis +#!BuildIgnore: xml-commons-resolver +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/description.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/description.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/description.spec 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/description.spec 2017-06-08 13:14:12.000000000 +0200 @@ -33,4 +33,10 @@ Theodore Ts'o <[email protected]> Nicolas Boullis <[email protected]> +%description other +This project contains reference implementations, test cases, and other +documents under source code control for Java Specification Request 305: +Annotations for Software Defect Detection. More information at the Google +group: http://groups.google.com/group/jsr-305. + %changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/licenseand.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/licenseand.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/licenseand.spec 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/licenseand.spec 2017-06-08 13:14:12.000000000 +0200 @@ -1,7 +1,7 @@ -License: GPL-2.0 and GPL-3.0 +License: GPL-2.0 AND GPL-3.0 %package test -License: BSD and GPL-3.0 +License: BSD AND GPL-3.0 %package test2 License: MIT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/licenseoptions.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/licenseoptions.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/licenseoptions.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/licenseoptions.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,12 @@ +Name: licenses +License: GPL-2.0 OR LGPL-2.1 + +%package samelicense +Summary: blabla +License: (GPL-2.0 AND GPL-3.0) OR MIT + +%package differentone +Summary: otherblabla +License: GPL-2.0+ + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/patterns.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/patterns.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/patterns.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/patterns.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,13 @@ +%package dhcp_dns_server +Summary: DHCP and DNS Server +Group: Metapackages +Requires: pattern() = basesystem +Provides: pattern() = dhcp_dns_server +Provides: pattern-icon() = yast-dns-server +Provides: pattern-order() = 3040 +Provides: pattern-visible() +Provides: patterns-openSUSE-dhcp_dns_server = %{version} +Obsoletes: patterns-openSUSE-dhcp_dns_server < %{version} +%pattern_serverfunctions + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/python_subpackages.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/python_subpackages.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/python_subpackages.spec 1970-01-01 01:00:00.000000000 +0100 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/python_subpackages.spec 2017-06-08 13:14:12.000000000 +0200 @@ -0,0 +1,11 @@ +Name: python-subpackages +BuildRequires: %{python_module foo} +%ifpython2 +Requires: python2-backports.abc +%endif +%python_subpackages + +%description +bla bla + +%changelog diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/requires.spec new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/requires.spec --- old/spec-cleaner-spec-cleaner-0.9.5/tests/out-minimal/requires.spec 2017-05-17 14:22:32.000000000 +0200 +++ new/spec-cleaner-spec-cleaner-0.9.6/tests/out-minimal/requires.spec 2017-06-08 13:14:12.000000000 +0200 @@ -1,13 +1,19 @@ BuildRequires: %{rubygem fast_gettext} BuildRequires: %{rubygem rails >= 3.2} BuildRequires: aaa < 3.2.1 +BuildRequires: alsa < 3.0 +BuildRequires: alsa >= 1.0 +BuildRequires: alsa >= 1.3 BuildRequires: bbb BuildRequires: eee = %{version}-%{release} BuildRequires: iii <= 4.2.1 BuildRequires: jjj > %{version} BuildRequires: kkk +BuildRequires: pkgconfig BuildRequires: rrr >= %{version} BuildRequires: zzz +BuildRequires: pkgconfig(yast2-core) >= 2.16.37 +BuildRequires: pkgconfig(yast2-ycp-ui-bindings) >= 2.16.37 Requires: %{libname} >= %{version} Requires: %{some_packagename} >= %{some_version} Requires: aaa < 3.2.1 @@ -23,7 +29,6 @@ Requires: perl(DBD::SQLite) Requires: pkgconfig(glib-2.0) Requires: pkgconfig(libcurl) -PreReq: aaa PreReq: aaa < 3.2.1 PreReq: eee = %{version}-%{release} PreReq: iii <= 4.2.1 ++++++ spec-cleaner.dsc ++++++ --- /var/tmp/diff_new_pack.DoHZUx/_old 2017-06-08 16:38:36.765243241 +0200 +++ /var/tmp/diff_new_pack.DoHZUx/_new 2017-06-08 16:38:36.765243241 +0200 @@ -1,6 +1,6 @@ Format: 3.0 (quilt) Source: spec-cleaner -Version: 0.9.5-1 +Version: 0.9.6-1 Binary: spec-cleaner Maintainer: Přemysl Janouch <[email protected]> Architecture: all
