diff options
| author | Giovanni Mascellani <mascellani@poisson.phc.unipi.it> | 2011-07-31 11:36:45 +0200 | 
|---|---|---|
| committer | Sean Finney <seanius@htpc-l.(none)> | 2011-09-17 13:28:46 +0200 | 
| commit | 2728f17f36f466682d3cc27ab8021fec3f827aa9 (patch) | |
| tree | b97224b888f19fc8a0468e300888a9812ecfbce3 | |
| parent | b231a89e5bad73baa00edffc198bee93293eb295 (diff) | |
| download | patch-tracker-2728f17f36f466682d3cc27ab8021fec3f827aa9.tar.gz | |
Added ghost patches support.
The ghost options disable the actual loading in memory of the patches.
When you just want to know the number of patches or their stats,
this saves quite a lot of memory and CPU time.
| -rw-r--r-- | patchtracker/DebTarHandler.py | 4 | ||||
| -rw-r--r-- | patchtracker/DiffGzHandler.py | 13 | ||||
| -rw-r--r-- | patchtracker/Patch.py | 68 | 
3 files changed, 59 insertions, 26 deletions
| diff --git a/patchtracker/DebTarHandler.py b/patchtracker/DebTarHandler.py index 311e39b..3564af2 100644 --- a/patchtracker/DebTarHandler.py +++ b/patchtracker/DebTarHandler.py @@ -10,8 +10,8 @@ class DebTarHandler:      self.tarfile = fname      self.size = os.stat(fname)[stat.ST_SIZE] -  def series(self): -    return Patch.Quilt30PatchSeries(self.tarfile) +  def series(self, ghost=False): +    return Patch.Quilt30PatchSeries(self.tarfile, ghost=ghost)  if __name__ == "__main__":    print "DebTarHandler testing" diff --git a/patchtracker/DiffGzHandler.py b/patchtracker/DiffGzHandler.py index 515b3ed..769ce18 100644 --- a/patchtracker/DiffGzHandler.py +++ b/patchtracker/DiffGzHandler.py @@ -14,7 +14,7 @@ class DiffGzHandler:      self.diff = fname      self.size = os.stat(fname)[stat.ST_SIZE] -  def filterdiff(self, include=None, exclude=None): +  def filterdiff(self, include=None, exclude=None, ghost=False):      cmd = ["filterdiff","-z","-p","1"]      if include:        cmd += [ "-i", include] @@ -24,7 +24,8 @@ class DiffGzHandler:        raise Exception("DiffGzHandler.filterdiff called w/o include/exclude")      i,o,e=os.popen3(cmd+[self.diff])      i.close() -    p = Patch(o) +    p = Patch(o, ghost=ghost) +    o.close()      err = e.read()      if len(err):        raise DiffGzException("filterdiff gave errors: "+err) @@ -33,10 +34,10 @@ class DiffGzHandler:    def debiandir(self):      return self.filterdiff(include='debian/*') -  def nondebiandir(self): -    return self.filterdiff(exclude='debian/*') +  def nondebiandir(self, ghost=False): +    return self.filterdiff(exclude='debian/*', ghost=ghost) -  def series(self): +  def series(self, ghost=False):      patches = None      embedded = self.filterdiff(include='debian/patches*') @@ -50,7 +51,7 @@ class DiffGzHandler:        err = e.read()        if len(err):          raise Exception("unable to extract series patches:\n"+err) -      patches = PatchSeries(td) +      patches = PatchSeries(td, ghost=ghost)        os.system("rm -rf %s"%(td))      return patches diff --git a/patchtracker/Patch.py b/patchtracker/Patch.py index 6533910..80ad8dc 100644 --- a/patchtracker/Patch.py +++ b/patchtracker/Patch.py @@ -3,21 +3,43 @@ import os  import errno  from glob import glob  import tarfile +from subprocess import Popen, PIPE +from shutil import copyfileobj  class Diffstat: -  def __init__(self, patch): +  def __init__(self, patch, ghost=False, patch_fh=None):      self.patch = patch -    i,o = os.popen2("diffstat -p1") -    i.write(str(patch)) -    i.close() -    self.output = o.readlines() +    self.ghost = ghost +    if not ghost: +      i,o = os.popen2("diffstat -p1") +      i.write(str(patch)) +      i.close() +      self.output = o.readlines() +    else: +      popen = Popen("diffstat -p1 -t", shell=True, close_fds=True, +        stdin=PIPE, stdout=PIPE, stderr=PIPE) +      popen.stderr.close() +      copyfileobj(patch_fh, popen.stdin) +      popen.stdin.close() +      popen.stdout.readline() +      self._stats = map(lambda x: map(lambda y: y.strip(), x.split(',')), popen.stdout.readlines()) +      popen.wait()    def stats(self): -    i,o = os.popen2("diffstat -p1 -t") -    i.write(str(self.patch)) -    i.close() -    o.readline() -    return [map(lambda x: x.strip(), l.split(",")) for l in o.readlines()] +    if not self.ghost: +      i,o = os.popen2("diffstat -p1 -t") +      i.write(str(self.patch)) +      i.close() +      o.readline() +      return [map(lambda x: x.strip(), l.split(",")) for l in o.readlines()] +    else: +      return self._stats + +  def lines(self): +    added, removed, modified = 0, 0, 0 +    for [added2, removed2, modified2, name] in self.stats(): +      added, removed, modified = added + int(added2), removed + int(removed2), modified + int(modified2) +    return (added, removed, modified)    def summary(self):      return self.output[-1] @@ -26,8 +48,13 @@ class Diffstat:      return "".join(self.output)  class Patch: -  def __init__(self, fh, level=1): -    self.p = fh.readlines() +  def __init__(self, fh, level=1, ghost=False): +    self.ghost = ghost +    if not ghost: +      self.p = fh.readlines() +    else: +      self.p = [] +      self._diffstat = Diffstat(self, ghost=True, patch_fh=fh)      self.lvl = level    def __str__(self): @@ -37,7 +64,10 @@ class Patch:      return len(self.p)    def diffstat(self): -    return Diffstat(self) +    if not self.ghost: +      return Diffstat(self) +    else: +      return self._diffstat  class GenericPatchSeries (list):    def blank(self): @@ -68,7 +98,8 @@ class GenericPatchSeries (list):  # XXX this entire __init__ stuff is way to ugly  class PatchSeries (GenericPatchSeries): -  def __init__(self, dir): +  def __init__(self, dir, ghost=False): +    self.ghost = ghost      fd = None      self.blank()      self.style = "simple" @@ -118,11 +149,11 @@ class PatchSeries (GenericPatchSeries):      removelater=[]      for p in self.names:        try: -        self.patches[p] = Patch(file(os.sep.join([dir, p]))) +        self.patches[p] = Patch(file(os.sep.join([dir, p])), ghost=ghost)        except IOError, e:          if e.errno == errno.ENOENT and self.style == "dpatch":            try: -            self.patches[p] = Patch(file(os.sep.join([dir, p+".dpatch"]))) +            self.patches[p] = Patch(file(os.sep.join([dir, p+".dpatch"])), ghost=ghost)            except:              #print "ERROR: could not find patch",p              self.blank() @@ -138,8 +169,9 @@ class PatchSeries (GenericPatchSeries):        self.names.remove(p)  class Quilt30PatchSeries (GenericPatchSeries): -  def __init__(self, tarBall): +  def __init__(self, tarBall, ghost=False):      self.blank() +    self.ghost = ghost      self.style = "quilt (3.0)"      self.tarfh = tarfile.open(tarBall, 'r:*')      try: @@ -162,7 +194,7 @@ class Quilt30PatchSeries (GenericPatchSeries):      # XXX to lazy eval this might be better      for name in self.names: -      self.patches[name] = Patch(self.tarfh.extractfile("debian/patches/"+name)) +      self.patches[name] = Patch(self.tarfh.extractfile("debian/patches/"+name), ghost=ghost)  if __name__ == "__main__":    print "Patch.py testing" | 
