/[soft]/mga-gnome/trunk/mga-gnome
ViewVC logotype

Diff of /mga-gnome/trunk/mga-gnome

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2936 by ovitters, Sun Feb 12 12:23:46 2012 UTC revision 3034 by ovitters, Wed Feb 22 20:47:36 2012 UTC
# Line 9  import urllib2 Line 9  import urllib2
9  import urlparse  import urlparse
10  import argparse  import argparse
11  import errno  import errno
12    import tempfile
13    import shutil
14  from sgmllib import SGMLParser  from sgmllib import SGMLParser
15    
16  MEDIA="Core Release Source"  MEDIA="Core Release Source"
17  URL="http://download.gnome.org/sources/"  URL="http://download.gnome.org/sources/"
18  PKGROOT='~/pkgs'  PKGROOT='~/pkgs'
19    
20    re_version = re.compile(r'([-.]|\d+|[^-.\d]+)')
21    
22    def version_cmp(a, b):
23        """Compares two versions
24    
25        Returns
26          -1 if a < b
27          0  if a == b
28          1  if a > b
29    
30        Logic from Bugzilla::Install::Util::vers_cmp"""
31        A = re_version.findall(a.lstrip('0'))
32        B = re_version.findall(b.lstrip('0'))
33    
34        while A and B:
35            a = A.pop(0)
36            b = B.pop(0)
37    
38            if a == b:
39                continue
40            elif a == '-':
41                return -1
42            elif b == '-':
43                return 1
44            elif a == '.':
45                return -1
46            elif b == '.':
47                return 1
48            elif a.isdigit() and b.isdigit():
49                c = cmp(a, b) if (a.startswith('0') or b.startswith('0')) else cmp(int(a, 10), int(b, 10))
50                if c:
51                    return c
52            else:
53                c = cmp(a.upper(), b.upper())
54                if c:
55                    return c
56    
57        return cmp(len(A), len(B))
58    
59    def get_latest_version(versions, max_version=None):
60        """Gets the latest version number
61    
62        if max_version is specified, gets the latest version number before
63        max_version"""
64        latest = None
65        for version in versions:
66            if ( latest is None or version_cmp(version, latest) > 0 ) \
67               and ( max_version is None or version_cmp(version, max_version) < 0 ):
68                latest = version
69        return latest
70    
71  def line_input (file):  def line_input (file):
72      for line in file:      for line in file:
73          if line[-1] == '\n':          if line[-1] == '\n':
# Line 22  def line_input (file): Line 75  def line_input (file):
75          else:          else:
76              yield line              yield line
77    
78    def call_editor(filename):
79        """Return a sequence of possible editor binaries for the current platform"""
80    
81        editors = []
82    
83        for varname in 'VISUAL', 'EDITOR':
84            if varname in os.environ:
85                editors.append(os.environ[varname])
86    
87        editors.extend(('/usr/bin/editor', 'vi', 'pico', 'nano', 'joe'))
88    
89        for editor in editors:
90            try:
91                ret = subprocess.call([editor, filename])
92            except OSError, e:
93                if e.errno == 2:
94                    continue
95                raise
96    
97            if ret == 127:
98                continue
99    
100            return True
101    
102  class urllister(SGMLParser):  class urllister(SGMLParser):
103      def reset(self):      def reset(self):
104          SGMLParser.reset(self)          SGMLParser.reset(self)
# Line 32  class urllister(SGMLParser): Line 109  class urllister(SGMLParser):
109          if href:          if href:
110              self.urls.extend(href)              self.urls.extend(href)
111    
112    class SpecFile(object):
113        re_update_version = re.compile(r'^(?P<pre>Version:\s*)(?P<version>.+)(?P<post>\s*)$', re.MULTILINE + re.IGNORECASE)
114        re_update_release = re.compile(r'^(?P<pre>Release:\s*)(?P<release>%mkrel \d+)(?P<post>\s*)$', re.MULTILINE + re.IGNORECASE)
115    
116        def __init__(self, path):
117            self.path = path
118            self.cwd = os.path.dirname(path)
119    
120        @property
121        def version(self):
122            return subprocess.check_output(["rpm", "--specfile", self.path, "--queryformat", "%{VERSION}\n"]).splitlines()[0]
123        def update(self, version):
124            """Update specfile (increase version)"""
125            cur_version = self.version
126    
127            if version_cmp(version, cur_version) != 1:
128                print >>sys.stderr, "ERROR: Version %s is older than current version %s!" % (version, cur_version)
129                return False
130    
131            with open(self.path, "rw") as f:
132                data = f.read()
133    
134                if data.count("%mkrel") != 1:
135                    print "WARNING: Multiple %mkrel found; don't know what to do!"
136                    return False
137    
138                data, nr = self.re_update_version.subn(r'\g<pre>%s\g<post>' % version, data, 1)
139                if nr != 1:
140                    print "WARNING: Could not increase version!"
141                    return False
142    
143                data, nr = self.re_update_release.subn(r'\g<pre>%mkrel 1\g<post>', data, 1)
144                if nr != 1:
145                    print "WARNING: Could not reset release!"
146                    return False
147    
148                # Overwrite file with new version number
149                write_file(self.path, data)
150    
151    
152            # Check RPM also agrees that version number has increased
153            if self.version != version:
154                print "ERROR: Increased version to %s, but RPM doesn't agree!?!" % version
155                return False
156    
157            try:
158                # Download new tarball
159                subprocess.check_call(['mgarepo', 'sync', '-d'], cwd=self.cwd)
160                # Check patches still apply
161                subprocess.check_call(['bm', '-p', '--nodeps'], cwd=self.cwd)
162            except subprocess.CalledProcessError:
163                return False
164    
165            return True
166    
167  class Patch(object):  class Patch(object):
168      """Do things with patches"""      """Do things with patches"""
169    
# Line 47  class Patch(object): Line 179  class Patch(object):
179          return self.path if self.show_path else os.path.basename(self.path)          return self.path if self.show_path else os.path.basename(self.path)
180    
181      def add_dep3(self):      def add_dep3(self):
182          pass          """Add DEP-3 headers to a patch file"""
183            if self.dep3['valid']:
184                return False
185    
186            new_headers = (
187                ('Author', self.svn_author),
188                ('Subject', ''),
189                ('Applied-Upstream', ''),
190                ('Forwarded', ''),
191                ('Bug', ''),
192            )
193    
194            with tempfile.NamedTemporaryFile(dir=os.path.dirname(self.path), delete=False) as fdst:
195                with open(self.path, "r") as fsrc:
196                    # Start with any existing DEP3 headers
197                    for i in range(self.dep3['last_nr']):
198                        fdst.write(fsrc.read())
199    
200                    # After that add the DEP3 headers
201                    add_line = False
202                    for header, data in new_headers:
203                        if header in self.dep3['headers']:
204                            continue
205    
206                        # XXX - wrap this at 80 chars
207                        add_line = True
208                        print >>fdst, "%s: %s" % (header, "" if data is None else data)
209    
210                    if add_line: print >>fdst, ""
211                    # Now copy any other data and the patch
212                    shutil.copyfileobj(fsrc, fdst)
213    
214                fdst.flush()
215                os.rename(fdst.name, self.path)
216    
217            call_editor(self.path)
218    
219      #Author: fwang      #Author: fwang
220      #Subject: Build fix: Fix glib header inclusion      #Subject: Build fix: Fix glib header inclusion
221      #Applied-Upstream: commit:30602      #Applied-Upstream: commit:30602
# Line 55  class Patch(object): Line 223  class Patch(object):
223      #Bug: http://bugzilla.abisource.com/show_bug.cgi?id=13247      #Bug: http://bugzilla.abisource.com/show_bug.cgi?id=13247
224    
225      def _read_dep3(self):      def _read_dep3(self):
226          """This will also parse git headers"""          """Read DEP-3 headers from an existing patch file
227    
228            This will also parse git headers"""
229          dep3 = {}          dep3 = {}
230            headers = {}
231    
232          last_header = None          last_header = None
233            last_nr = 0
234            nr = 0
235          try:          try:
236              with open(self.path, "r") as f:              with open(self.path, "r") as f:
237                  for line in line_input(f):                  for line in line_input(f):
238                      # Check for start of real patch                      nr += 1
239                        # stop trying to parse when real patch begins
240                      if line == '---':                      if line == '---':
241                          break                          break
242    
243                      r = self.re_dep3.match(line)                      r = self.re_dep3.match(line)
244                      if r:                      if r:
245                          info = r.groupdict()                          info = r.groupdict()
246                          dep3[info['header']] = info['data']  
247                            # Avoid matching URLS
248                            if info['data'].startswith('//') and info['header'].lower () == info['header']:
249                                continue
250    
251                            headers[info['header']] = info['data']
252                          last_header = info['header']                          last_header = info['header']
253                            last_nr = nr
254                          continue                          continue
255    
256                      r = self.re_dep3_cont.match(line)                      r = self.re_dep3_cont.match(line)
257                      if r:                      if r:
258                          info = r.groupdict()                          info = r.groupdict()
259                          if last_header:                          if last_header:
260                              dep3[last_header] = " ".join((dep3[last_header], info['data']))                              headers[last_header] = " ".join((headers[last_header], info['data']))
261                                last_nr = nr
262                          continue                          continue
263    
264                      last_header = None                      last_header = None
265          except IOError:          except IOError:
266              pass              pass
267    
268            dep3['valid'] = \
269                (('Description' in headers and headers['Description'].strip() != '')
270                    or ('Subject' in headers and headers['Subject'].strip() != '')) \
271                and (('Origin' in headers and headers['Origin'].strip() != '') \
272                    or ('Author' in headers and headers['Author'].strip() != '') \
273                    or ('From' in headers and headers['From'].strip() != ''))
274            dep3['last_nr'] = last_nr
275            dep3['headers'] = headers
276    
277          self._dep3 = dep3          self._dep3 = dep3
278    
279      @property      @property
# Line 92  class Patch(object): Line 283  class Patch(object):
283    
284          return self._dep3          return self._dep3
285    
286        @property
287        def svn_author(self):
288            if not hasattr(self, '_svn_author'):
289                p = subprocess.Popen(['svn', 'log', '-q', "--", self.path], stdout=subprocess.PIPE, close_fds=True)
290                contents = p.stdout.read().strip("\n").splitlines()
291                ecode = p.wait()
292                if ecode == 0:
293                    for line in contents:
294                        if ' | ' not in line:
295                            continue
296    
297                        fields = line.split(' | ')
298                        if len(fields) >= 3:
299                            self._svn_author = fields[1]
300    
301            if not hasattr(self, '_svn_author'):
302                return None
303    
304            return self._svn_author
305    
306  def get_upstream_names():  def get_upstream_names():
307      urlopen = urllib2.build_opener()      urlopen = urllib2.build_opener()
# Line 145  def get_downstream_names(): Line 355  def get_downstream_names():
355    
356      return TARBALLS, FILES      return TARBALLS, FILES
357    
358    
359    def write_file(path, data):
360        with tempfile.NamedTemporaryFile(dir=os.path.dirname(path), delete=False) as fdst:
361            fdst.write(data)
362            fdst.flush()
363            os.rename(fdst.name, path)
364    
365  def cmd_co(options, parser):  def cmd_co(options, parser):
366      upstream = get_upstream_names()      upstream = get_upstream_names()
367      downstream, downstream_files = get_downstream_names()      downstream, downstream_files = get_downstream_names()
# Line 178  def cmd_patches(options, parser): Line 395  def cmd_patches(options, parser):
395          for srpm in downstream[module]:          for srpm in downstream[module]:
396              for filename in downstream_files[srpm]:              for filename in downstream_files[srpm]:
397                  if '.patch' in filename or '.diff' in filename:                  if '.patch' in filename or '.diff' in filename:
398    
399                      p = Patch(os.path.join(path, srpm, "SOURCES", filename), show_path=options.path)                      p = Patch(os.path.join(path, srpm, "SOURCES", filename), show_path=options.path)
400                      print "\t".join((module, srpm, str(p)))                      valid = ""
401                      if p.dep3:                      forwarded = ""
402                          pprint.pprint(p.dep3)                      if p.dep3['headers']:
403                            forwarded = p.dep3['headers'].get('Forwarded', "no")
404                            if p.dep3['valid']:
405                                valid="VALID"
406                        print "\t".join((module, srpm, str(p), forwarded, valid))
407    
408    def cmd_dep3(options, parser):
409        p = Patch(options.patch)
410        p.add_dep3()
411    
412    def cmd_package_new_version(options, parser):
413        cwd = os.path.expanduser(PKGROOT)
414        package = options.package
415    
416        subprocess.call(['mgarepo', 'co', package], cwd=cwd)
417        s = SpecFile(os.path.join(cwd, package, "SPECS", "%s.spec" % package))
418        print s.version
419        if not s.update(options.version):
420            sys.exit(1)
421    
422    
423  def main():  def main():
424      description = """Mageia GNOME commands."""      description = """Mageia GNOME commands."""
# Line 203  def main(): Line 440  def main():
440    
441      subparser = subparsers.add_parser('patches', help='list all GNOME patches')      subparser = subparsers.add_parser('patches', help='list all GNOME patches')
442      subparser.add_argument("-p", "--path", action="store_true", dest="path",      subparser.add_argument("-p", "--path", action="store_true", dest="path",
443                                         help="Full path to patch")                                         help="Show full path to patch")
444      subparser.set_defaults(      subparser.set_defaults(
445          func=cmd_patches, path=False          func=cmd_patches, path=False
446      )      )
447    
448        subparser = subparsers.add_parser('dep3', help='Add dep3 headers')
449        subparser.add_argument("patch", help="Patch")
450        subparser.set_defaults(
451            func=cmd_dep3, path=False
452        )
453    
454        subparser = subparsers.add_parser('increase', help='Increase version number')
455        subparser.add_argument("package", help="Package name")
456        subparser.add_argument("version", help="Version number")
457        subparser.set_defaults(
458            func=cmd_package_new_version, path=False
459        )
460    
461      if len(sys.argv) == 1:      if len(sys.argv) == 1:
462          parser.print_help()          parser.print_help()

Legend:
Removed from v.2936  
changed lines
  Added in v.3034

  ViewVC Help
Powered by ViewVC 1.1.30