From: Nishanth Aravamudan <[email protected]>

Passing in 3.0 to autotest results in messages about
being unable to parse the major/minor version. This
is because the code assumes a 3-digit verions number.
Additionally, the 'raise' in this chunk of code throws
its own exception due to a raw string parameter.

Fix both by having an alternate function to check
post-2.x version numbers, that will also consider
this new naming schema. It's forward compatible,
for the (potentially) far away 4.x times (well,
assuming that the naming schema will remain the
same).

Changes from v1:
 * Rewrite of the original patch code
 * Addition of unittests
 * Fixed incorrect logic that printed unavailable
   URLs when it shouldn't do that
 * Used urllib2 instead of external programs to
   verify the state of a given URL
 * Fixed docstrings and comments
 * Fixed use of string exceptions

Signed-off-by: Lucas Meneghel Rodrigues <[email protected]>
Signed-off-by: Nishanth Aravamudan <[email protected]>
---
 client/bin/kernelexpand.py          |  186 +++++++++++++++++++++++++----------
 client/bin/kernelexpand_unittest.py |   58 +++++++++++
 2 files changed, 194 insertions(+), 50 deletions(-)

diff --git a/client/bin/kernelexpand.py b/client/bin/kernelexpand.py
index 871b053..51932ba 100755
--- a/client/bin/kernelexpand.py
+++ b/client/bin/kernelexpand.py
@@ -1,43 +1,75 @@
 #!/usr/bin/python
-#
-# (C) International Business Machines 2008
-# Author: Andy Whitcroft
-#
-# Inspired by kernelexpand by:
-# (C) Martin J. Bligh 2003
-#
-# Released under the GPL, version 2
-
-import sys, re, os
-
-kernel = 'http://www.kernel.org/pub/linux/kernel/'
-mappings = [
+"""
+Program and API used to expand kernel versions, trying to match
+them with the URL of the correspondent package on kernel.org or
+a mirror. Example:
+
+$ ./kernelexpand.py 3.1
+http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.1.tar.bz2
+
+@author: Andy Whitcroft ([email protected])
+@copyright: IBM 2008
+@license: GPL v2
+@see: Inspired by kernelexpand by Martin J. Bligh, 2003
+"""
+import sys, re, os, urllib2
+
+
+KERNEL_BASE_URL = 'http://www.kernel.org/pub/linux/kernel/'
+
+MAPPINGS_2X = [
+        [ r'^\d+\.\d+$', '', True, [
+                KERNEL_BASE_URL + 'v%(major)s/linux-%(full)s.tar.bz2'
+        ]],
         [ r'^\d+\.\d+\.\d+$', '', True, [
-                kernel + 'v%(major)s/linux-%(full)s.tar.bz2'
+                KERNEL_BASE_URL + 'v%(major)s/linux-%(full)s.tar.bz2'
         ]],
         [ r'^\d+\.\d+\.\d+\.\d+$', '', True, [
-                kernel + 'v%(major)s/linux-%(full)s.tar.bz2'
+                KERNEL_BASE_URL + 'v%(major)s/linux-%(full)s.tar.bz2'
         ]],
         [ r'-rc\d+$', '%(minor-prev)s', True, [
-                kernel + 
'v%(major)s/testing/v%(minor)s/linux-%(full)s.tar.bz2',
-                kernel + 'v%(major)s/testing/linux-%(full)s.tar.bz2',
+                KERNEL_BASE_URL + 
'v%(major)s/testing/v%(minor)s/linux-%(full)s.tar.bz2',
+                KERNEL_BASE_URL + 'v%(major)s/testing/linux-%(full)s.tar.bz2',
         ]],
         [ r'-(git|bk)\d+$', '%(base)s', False, [
-                kernel + 'v%(major)s/snapshots/old/patch-%(full)s.bz2',
-                kernel + 'v%(major)s/snapshots/patch-%(full)s.bz2',
+                KERNEL_BASE_URL + 
'v%(major)s/snapshots/old/patch-%(full)s.bz2',
+                KERNEL_BASE_URL + 'v%(major)s/snapshots/patch-%(full)s.bz2',
         ]],
         [ r'-mm\d+$', '%(base)s', False, [
-                kernel + 'people/akpm/patches/' +
+                KERNEL_BASE_URL + 'people/akpm/patches/' +
                         '%(major)s/%(base)s/%(full)s/%(full)s.bz2'
         ]],
         [ r'-mjb\d+$', '%(base)s', False, [
-                kernel + 'people/mbligh/%(base)s/patch-%(full)s.bz2'
+                KERNEL_BASE_URL + 'people/mbligh/%(base)s/patch-%(full)s.bz2'
         ]]
 ];
 
-def decompose_kernel_once(kernel):
-    ##print "S<" + kernel + ">"
-    for mapping in mappings:
+MAPPINGS_POST_2X = [
+        [ r'^\d+\.\d+$', '', True, [
+                KERNEL_BASE_URL + 'v%(major)s/linux-%(full)s.tar.bz2'
+        ]],
+        [ r'^\d+\.\d+\.\d+$', '', True, [
+                KERNEL_BASE_URL + 'v%(major)s/linux-%(full)s.tar.bz2'
+        ]],
+        [ r'-rc\d+$', '%(minor-prev)s', True, [
+                KERNEL_BASE_URL + 'v%(major)s/testing/linux-%(full)s.tar.bz2',
+        ]],
+];
+
+
+def decompose_kernel_2x_once(kernel):
+    """
+    Generate the parameters for the patches (2.X version):
+
+    full         => full kernel name
+    base         => all but the matches suffix
+    minor        => 2.n.m
+    major        => 2.n
+    minor-prev   => 2.n.m-1
+
+    @param kernel: String representing a kernel version to be expanded.
+    """
+    for mapping in MAPPINGS_2X:
         (suffix, becomes, is_full, patch_templates) = mapping
 
         params = {}
@@ -46,18 +78,13 @@ def decompose_kernel_once(kernel):
         if not match:
             continue
 
-        # Generate the parameters for the patches:
-        #  full         => full kernel name
-        #  base         => all but the matches suffix
-        #  minor        => 2.n.m
-        #  major        => 2.n
-        #  minor-prev   => 2.n.m-1
         params['full'] = kernel
         params['base'] = match.group(1)
 
         match = re.search(r'^((\d+\.\d+)\.(\d+))', kernel)
         if not match:
-            raise "unable to determine major/minor version"
+            raise NameError("Unable to determine major/minor version for "
+                            "kernel %s" % kernel)
         params['minor'] = match.group(1)
         params['major'] = match.group(2)
         params['minor-prev'] = match.group(2) + '.%d' % (int(match.group(3)) 
-1)
@@ -73,16 +100,83 @@ def decompose_kernel_once(kernel):
     return (True, kernel, None)
 
 
+def decompose_kernel_post_2x_once(kernel):
+    """
+    Generate the parameters for the patches (post 2.X version):
+
+    full         => full kernel name
+    base         => all but the matches suffix
+    minor        => o.n.m
+    major        => o.n
+    minor-prev   => o.n.m-1
+
+    @param kernel: String representing a kernel version to be expanded.
+    """
+    for mapping in MAPPINGS_POST_2X:
+        (suffix, becomes, is_full, patch_templates) = mapping
+
+        params = {}
+
+        match = re.search(r'^(.*)' + suffix, kernel)
+        if not match:
+            continue
+
+        params['full'] = kernel
+        params['base'] = match.group(1)
+        major = ''
+
+        match = re.search(r'^((\d+\.\d+)\.(\d+))', kernel)
+        if not match:
+            match = re.search(r'^(\d+\.\d+)', kernel)
+            if not match:
+                raise NameError("Unable to determine major/minor version for "
+                                "kernel %s" % kernel)
+            else:
+                params['minor'] = 0
+                major = match.group(1)
+                params['minor-prev'] = match.group(1)
+        else:
+            params['minor'] = match.group(1)
+            major = match.group(1)
+            params['minor-prev'] = match.group(2) + '.%d' % 
(int(match.group(3)) -1)
+
+        # Starting with kernels 3.x, we have folders named '3.x' on kernel.org
+        first_number = major.split('.')[0]
+        params['major'] = '%s.x' % first_number
+
+        # It makes no sense a 3.1.1-rc1 version, for example
+        if re.search(r'-rc\d+$', params['full']) and params['minor'] != 0:
+            continue
+
+        # Build the new kernel and patch list.
+        new_kernel = becomes % params
+        patch_list = []
+        for template in patch_templates:
+            patch_list.append(template % params)
+
+        return (is_full, new_kernel, patch_list)
+
+    return (True, kernel, None)
+
+
 def decompose_kernel(kernel):
-    kernel_patches = []
+    match = re.search(r'^(\d+\.\d+)', kernel)
+    if not match:
+        raise NameError("Unable to determine major/minor version for "
+                        "kernel %s" % kernel)
+    if int(match.group(1).split('.')[0]) == 2:
+        decompose_func = decompose_kernel_2x_once
+    elif int(match.group(1).split('.')[0]) > 2:
+        decompose_func = decompose_kernel_post_2x_once
 
+    kernel_patches = []
     done = False
     while not done:
-        (done, kernel, patch_list) = decompose_kernel_once(kernel)
+        (done, kernel, patch_list) = decompose_func(kernel)
         if patch_list:
             kernel_patches.insert(0, patch_list)
     if not len(kernel_patches):
-        raise NameError('kernelexpand: %s: unknown kernel' % (kernel))
+        raise NameError('Unknown kernel: %s' % kernel)
 
     return kernel_patches
 
@@ -106,10 +200,11 @@ def mirror_kernel_components(mirrors, components):
 
 
 def url_accessible(url):
-    status = os.system("wget --spider -q '%s'" % (url))
-    #print url + ": status=%d" % (status)
-
-    return status == 0
+    try:
+        urllib2.urlopen(url)
+        return True
+    except urllib2.HTTPError:
+        return False
 
 
 def select_kernel_components(components):
@@ -120,8 +215,6 @@ def select_kernel_components(components):
             if url_accessible(patch):
                 new_patches.append(patch)
                 break
-        if not len(new_patches):
-            new_patches.append(component[-1])
         new_components.append(new_patches)
     return new_components
 
@@ -160,14 +253,6 @@ if __name__ == '__main__':
         usage()
     kernel = args[0]
 
-    #mirrors = [
-    #       [ 'http://www.kernel.org/pub/linux/kernel/v2.4',
-    #         'http://kernel.beaverton.ibm.com/mirror/v2.4' ],
-    #       [ 'http://www.kernel.org/pub/linux/kernel/v2.6',
-    #         'http://kernel.beaverton.ibm.com/mirror/v2.6' ],
-    #       [ 'http://www.kernel.org/pub/linux/kernel/people/akpm/patches',
-    #         'http://kernel.beaverton.ibm.com/mirror/akpm' ],
-    #]
     mirrors = options.mirror
 
     try:
@@ -182,6 +267,7 @@ if __name__ == '__main__':
     if options.validate:
         components = select_kernel_components(components)
 
-    # Dump them out.
+    # Dump them out
     for component in components:
-        print " ".join(component)
+        if component:
+            print " ".join(component)
diff --git a/client/bin/kernelexpand_unittest.py 
b/client/bin/kernelexpand_unittest.py
index bbf1163..061a984 100755
--- a/client/bin/kernelexpand_unittest.py
+++ b/client/bin/kernelexpand_unittest.py
@@ -22,6 +22,64 @@ class kernelexpandTest(unittest.TestCase):
         self.assertEqual(sample, correct)
 
 
+    def test_decompose_simple_30(self):
+        correct = [ [ km + 'v3.x/linux-3.0.14.tar.bz2' ] ]
+        sample = decompose_kernel('3.0.14')
+        self.assertEqual(sample, correct)
+
+
+    def test_decompose_simple_3X(self):
+        correct = [ [ km + 'v3.x/linux-3.2.1.tar.bz2' ] ]
+        sample = decompose_kernel('3.2.1')
+        self.assertEqual(sample, correct)
+
+
+    def test_decompose_nominor_30(self):
+        correct = [ [ km + 'v3.x/linux-3.0.tar.bz2' ] ]
+        sample = decompose_kernel('3.0')
+        self.assertEqual(sample, correct)
+
+
+    def test_decompose_nominor_26_fail(self):
+        success = False
+        try:
+            sample = decompose_kernel('2.6')
+            success = True
+        except NameError:
+            pass
+        except Exception, e:
+            self.fail('expected NameError, got something else')
+
+        if success:
+            self.fail('expected NameError, was successful')
+
+
+    def test_decompose_testing_26(self):
+        correct = km + 'v2.6/testing/linux-2.6.35-rc1.tar.bz2'
+        sample = decompose_kernel('2.6.35-rc1')[0][1]
+        self.assertEqual(sample, correct)
+
+
+    def test_decompose_testing_30(self):
+        correct = km + 'v3.x/testing/linux-3.2-rc1.tar.bz2'
+        sample = decompose_kernel('3.2-rc1')[0][0]
+        self.assertEqual(sample, correct)
+
+
+    def test_decompose_testing_30_fail(self):
+        success = False
+        try:
+            sample = decompose_kernel('3.2.1-rc1')
+            success = True
+        except NameError:
+            pass
+        except Exception, e:
+            self.fail('expected NameError, got something else')
+
+        if success:
+            self.fail('expected NameError, was successful')
+
+
     def test_decompose_fail(self):
         success = False
         try:
-- 
1.7.7.6

_______________________________________________
Autotest mailing list
[email protected]
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

Reply via email to