From 89fc2fd45cb93c6383c07cc73b9c61061ea614dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20O=C5=BCarowski?= <piotr@debian.org>
Date: Sun, 28 Nov 2010 20:35:44 +0100
Subject: [PATCH] remove public modules listed in debian/pkg.pyremove

---
 debian/changelog                     |  6 ++-
 debpython/tools.py                   | 74 +++++++++++++++++++++++++---
 dh_python2                           |  4 +-
 tests/t1/debian/python-foo.pyinstall |  1 +
 tests/t1/debian/python-foo.pyremove  |  2 +
 tests/t1/debian/spam.py              |  1 +
 6 files changed, 79 insertions(+), 9 deletions(-)
 create mode 100644 tests/t1/debian/python-foo.pyinstall
 create mode 100644 tests/t1/debian/python-foo.pyremove
 create mode 100644 tests/t1/debian/spam.py

diff --git a/debian/changelog b/debian/changelog
index 8436033..dfe2028 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,9 +2,11 @@ python-defaults (2.6.6-6) UNRELEASED; urgency=low
 
   * Make the error message about missing extension more clear
     (and more verbose in --verbose mode)
-  * dh_python2: install files listed in debian/package.pyinstall file
+  * dh_python2: install files listed in debian/pkg.pyinstall file
     as public modules for all requested Python versions (use dh_install's
-    package.install files for private modules)
+    package.install files for private modules); remove public modules listed
+    in debian/pkg.pyremove (glob.glob pattern and version range can be used in
+    both files)
   * pycompile: `pycompile $DESTDIR/usr/lib/python*` will recognize public
     site-packages directories and use the right interpreter instead of raising
     KeyError
diff --git a/debpython/tools.py b/debpython/tools.py
index efbcd49..0962ccf 100644
--- a/debpython/tools.py
+++ b/debpython/tools.py
@@ -22,11 +22,12 @@
 from __future__ import with_statement
 import codecs
 import logging
+import os
 import re
 from cPickle import dumps
 from glob import glob
-from os import link, makedirs, symlink
-from os.path import exists, join, split
+from os.path import exists, isdir, join, split
+from shutil import rmtree
 from debpython.version import RANGE_PATTERN, getver, get_requested_versions
 
 log = logging.getLogger(__name__)
@@ -39,6 +40,11 @@ INSTALL_RE = re.compile(r"""
     \s*  # optional version range:
     (?P<vrange>%s)?$
 """ % RANGE_PATTERN, re.VERBOSE)
+REMOVE_RE = re.compile(r"""
+    (?P<pattern>.+?)  # file pattern
+    \s*  # optional version range:
+    (?P<vrange>%s)?$
+""" % RANGE_PATTERN, re.VERBOSE)
 
 
 def sitedir(version, package=None, gdb=False):
@@ -80,7 +86,7 @@ def relpath(target, link):
 
 def relative_symlink(target, link):
     """Create relative symlink."""
-    return symlink(relpath(target, link), link)
+    return os.symlink(relpath(target, link), link)
 
 
 def shebang2pyver(fname):
@@ -131,7 +137,7 @@ class memoize(object):
 
 
 def pyinstall(package, vrange):
-    """Install local files listed in .pyinstall files as public modules."""
+    """Install local files listed in pkg.pyinstall files as public modules."""
     status = True
     srcfpath = "./debian/%s.pyinstall" % package
     if not exists(srcfpath):
@@ -151,6 +157,10 @@ def pyinstall(package, vrange):
         if details['module']:
             details['module'] = details['module'].replace('.', '/')
         myvers = versions & get_requested_versions(details['vrange'])
+        if not myvers:
+            log.debug('%s.pyinstall: no matching versions for line %s',
+                      package, line)
+            continue
         files = glob(details['pattern'])
         if not files:
             status = False
@@ -170,13 +180,65 @@ def pyinstall(package, vrange):
                 dstdir = split(dstfpath)[0]
                 if not exists(dstdir):
                     try:
-                        makedirs(dstdir)
+                        os.makedirs(dstdir)
                     except:
                         log.error('cannot create %s directory', dstdir)
                         return False
+                if exists(dstfpath):
+                    try:
+                        os.remove(dstfpath)
+                    except:
+                        status = False
+                        log.error('cannot replace %s file', dstfpath)
+                        continue
                 try:
-                    link(fpath, dstfpath)
+                    os.link(fpath, dstfpath)
                 except:
                     status = False
                     log.error('cannot copy %s file to %s', fpath, dstdir)
     return status
+
+
+def pyremove(package, vrange):
+    """Remove public modules listed in pkg.pyremove file."""
+    status = True
+    srcfpath = "./debian/%s.pyremove" % package
+    if not exists(srcfpath):
+        return status
+    versions = get_requested_versions(vrange)
+
+    for line in codecs.open(srcfpath, encoding='utf-8'):
+        if not line or line.startswith('#'):
+            continue
+        details = REMOVE_RE.match(line)
+        if not details:
+            status = False
+            log.warn('%s.pyremove: unrecognized line: %s',
+                     package, line)
+            continue
+        details = details.groupdict()
+        myvers = versions & get_requested_versions(details['vrange'])
+        if not myvers:
+            log.debug('%s.pyremove: no matching versions for line %s',
+                      package, line)
+            continue
+        for version in myvers:
+            files = glob(sitedir(version, package) + details['pattern'])
+            if not files:
+                log.debug('%s.pyremove: nothing to remove: python%d.%d, %s',
+                          package, version, details['pattern'])
+                continue
+            for fpath in files:
+                if isdir(fpath):
+                    try:
+                        rmtree(fpath)
+                    except Exception, e:
+                        status = False
+                        log.error(e)
+                else:
+                    try:
+                        os.remove(fpath)
+                    except (IOError, OSError), e:
+                        status = False
+                        log.error(e)
+    return status
diff --git a/dh_python2 b/dh_python2
index d838cb8..9952d6b 100755
--- a/dh_python2
+++ b/dh_python2
@@ -41,7 +41,7 @@ from debpython.pydist import validate as validate_pydist, \
                              PUBLIC_DIR_RE
 from debpython.tools import sitedir, relative_symlink, \
                             shebang2pyver, clean_egg_name,\
-                            pyinstall
+                            pyinstall, pyremove
 from debpython.option import Option
 
 # initialize script
@@ -486,6 +486,8 @@ def main():
         log.debug('processing package %s...', package)
         if not pyinstall(package, options.vrange):
             exit(4)
+        if not pyremove(package, options.vrange):
+            exit(5)
         fix_locations(package)
         stats = scan(package, private_dir)
         share(package, stats, options)
diff --git a/tests/t1/debian/python-foo.pyinstall b/tests/t1/debian/python-foo.pyinstall
new file mode 100644
index 0000000..0a369c3
--- /dev/null
+++ b/tests/t1/debian/python-foo.pyinstall
@@ -0,0 +1 @@
+debian/spam.py foo 2.5-
diff --git a/tests/t1/debian/python-foo.pyremove b/tests/t1/debian/python-foo.pyremove
new file mode 100644
index 0000000..e30c585
--- /dev/null
+++ b/tests/t1/debian/python-foo.pyremove
@@ -0,0 +1,2 @@
+foo/spam.py 2.6
+foo/bar 2.7-
diff --git a/tests/t1/debian/spam.py b/tests/t1/debian/spam.py
new file mode 100644
index 0000000..ac65b39
--- /dev/null
+++ b/tests/t1/debian/spam.py
@@ -0,0 +1 @@
+print 'SPAM'
-- 
GitLab