Bug#460101: python-debian: add update function to PackageFile which yields changed packages

Mike O'Connor stew at vireo.org
Thu Jan 10 15:40:29 UTC 2008


Package: python-debian
Version: 0.1.8
Severity: wishlist
Tags: patch

*** Please type your report below this line *** When I update a
Packages using pdiffs with patchLines debian_support.updateFile, I
really would like to know exectly which Packages inside the Packages
file are affected.

Attached I a patch which adds:
    def update( self, remote, verbose=None):

to PackageFile which will update the PackageFile, and iterate through
the list of Packages which have changed.

Please look it over and consider applying.

thanks,
stew

-- System Information:
Debian Release: lenny/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.22-3-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages python-debian depends on:
ii  python                        2.4.4-6    An interactive high-level object-o
ii  python-support                0.7.5      automated rebuilding support for p

python-debian recommends no packages.

-- no debconf information
-------------- next part --------------
--- /var/lib/python-support/python2.4/debian_bundle/debian_support.py	2007-12-28 13:46:42.000000000 -0500
+++ /tmp/debian_support.py	2008-01-10 09:37:35.000000000 -0500
@@ -102,40 +102,73 @@
         self.file = fileObj
         self.lineno = 0
 
-    def __iter__(self):
-        line = self.file.readline()
-        self.lineno += 1
-        pkg = []
-        while line:
-            if line == '\n':
-                if len(pkg) == 0:
-                    self.raiseSyntaxError('expected package record')
-                yield pkg
-                pkg = []
-                line = self.file.readline()
-                self.lineno += 1
-                continue
-            
-            match = self.re_field.match(line)
-            if not match:
-                self.raiseSyntaxError("expected package field")
-            (name, contents) = match.groups()
-            contents = contents or ''
-
-            while True:
-                line = self.file.readline()
-                self.lineno += 1
-                match = self.re_continuation.match(line)
-                if match:
-                    (ncontents,) = match.groups()
-                    if ncontents is None:
-                        ncontents = ""
-                    contents = "%s\n%s" % (contents, ncontents)
+    def update( self, remote, verbose=None):
+        """
+        updates the local file from the given remote site, and
+        iterates through the packages which have changed
+        """
+        changed_lines = set()
+        lines = updateFile(remote, self.name, verbose, changed_lines)
+
+        self.file = file(self.name)
+        self.lineno = 0
+        return self.__iter__( sorted( changed_lines ) )
+        
+    def __iter__(self, changed_lines=None):
+        """
+        iterate through packages which contain the given lines.
+        """
+        try:
+            line = self.file.readline()
+            self.lineno += 1
+            pkg = []
+            while line:
+                if line == '\n':
+                    if len(pkg) == 0:
+                        self.raiseSyntaxError('expected package record')
+                    if changed_lines is not None:
+                        if self.lineno >= changed_lines[0]:
+                            while( changed_lines[ 0 ] < self.lineno ):
+                                changed_lines.pop( 0 )
+                            yield pkg
+                    else:
+                        yield pkg
+
+                    pkg = []
+                    line = self.file.readline()
+                    self.lineno += 1
+                    continue
+
+                match = self.re_field.match(line)
+                if not match:
+                    self.raiseSyntaxError("expected package field.  instead got:" + line)
+                (name, contents) = match.groups()
+                contents = contents or ''
+
+                while True:
+                    line = self.file.readline()
+                    self.lineno += 1
+                    match = self.re_continuation.match(line)
+                    if match:
+                        (ncontents,) = match.groups()
+                        if ncontents is None:
+                            ncontents = ""
+                        contents = "%s\n%s" % (contents, ncontents)
+                    else:
+                        break
+                pkg.append((name, contents))
+            if pkg:
+                if changed_lines is not None:
+                    if self.lineno >= lines[0]:
+                        while( lines[ 0 ] < self.lineno ):
+                            lines.pop( 0 )
+                        yield pkg
                 else:
-                    break
-            pkg.append((name, contents))
-        if pkg:
-            yield pkg
+                    yield pkg
+
+        except IndexError:
+            # we must be out of changed lines, so we are done
+            return
 
     def raiseSyntaxError(self, msg, lineno=None):
         if lineno is None:
@@ -229,13 +262,30 @@
             lines.append(l)
         yield (first, last, lines)
 
-def patchLines(lines, patches):
-    """Applies patches to lines.  Updates lines in place."""
+class adjust_changed_lines:
+    def __init__( self, after, delta ):
+        self.after, self.delta = after, delta
+        
+    def __call__( self, line ):
+        if line >= self.after:
+            return line + self.delta
+        else: 
+            return line
+
+def patchLines(lines, patches, changed=None):
+    """
+    Applies patches to lines.  Updates lines in place. 
+    if changed is a set, it is updated with a list of lines which are new
+    """
     for (first, last, args) in patches:
         lines[first:last] = args
+        if isinstance( changed, set ):
+            new_changed = set( map( adjust_changed_lines( first, len( args) + first - last ), changed ) )
+            changed.clear()
+            changed.update( new_changed )
+            changed.update( range( first, first+len( args ) ) )
 
 def replaceFile(lines, local):
-
     import os.path
 
     local_new = local + '.new'
@@ -284,7 +334,7 @@
     replaceFile(lines, local)
     return lines
 
-def updateFile(remote, local, verbose=None):
+def updateFile(remote, local, verbose=None, changed_lines=None):
     """Updates the local file by downloading a remote patch.
 
     Returns a list of lines in the local file.
@@ -369,7 +419,7 @@
                                           + '.gz')
         if readLinesSHA1(patch_contents ) <> patch_hashes[patch_name]:
             raise ValueError, "patch %s was garbled" % `patch_name`
-        patchLines(lines, patchesFromEdScript(patch_contents))
+        patchLines(lines, patchesFromEdScript(patch_contents), changed_lines)
         
     new_hash = readLinesSHA1(lines)
     if new_hash <> remote_hash:


More information about the pkg-python-debian-maint mailing list