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


Reply via email to