r4534 - trunk/src/host/opkg-utils

zecke at docs.openmoko.org zecke at docs.openmoko.org
Fri Jul 18 13:29:53 CEST 2008


Author: zecke
Date: 2008-07-18 13:29:53 +0200 (Fri, 18 Jul 2008)
New Revision: 4534

Added:
   trunk/src/host/opkg-utils/COPYING
   trunk/src/host/opkg-utils/Makefile
   trunk/src/host/opkg-utils/arfile.py
   trunk/src/host/opkg-utils/makePackage
   trunk/src/host/opkg-utils/opkg-build
   trunk/src/host/opkg-utils/opkg-buildpackage
   trunk/src/host/opkg-utils/opkg-compare-indexes
   trunk/src/host/opkg-utils/opkg-compare-versions.c
   trunk/src/host/opkg-utils/opkg-compare-versions.sh
   trunk/src/host/opkg-utils/opkg-diff
   trunk/src/host/opkg-utils/opkg-extract-file
   trunk/src/host/opkg-utils/opkg-list-fields
   trunk/src/host/opkg-utils/opkg-make-index
   trunk/src/host/opkg-utils/opkg-show-deps
   trunk/src/host/opkg-utils/opkg-unbuild
   trunk/src/host/opkg-utils/opkg-update-index
   trunk/src/host/opkg-utils/opkg.py
Log:
[opkg-utils] Add opkg-utils to the repository courtsey Richard Purdie of o-hand.com
    I've attached a first attempt at this, its basically a small set of
    helper scripts which OE/Poky use when working with ipks. I've applied
    the various OE improvements and tweaks and removed a ton of cruft we
    don't need.


Added: trunk/src/host/opkg-utils/COPYING
===================================================================
--- trunk/src/host/opkg-utils/COPYING	                        (rev 0)
+++ trunk/src/host/opkg-utils/COPYING	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

Added: trunk/src/host/opkg-utils/Makefile
===================================================================
--- trunk/src/host/opkg-utils/Makefile	                        (rev 0)
+++ trunk/src/host/opkg-utils/Makefile	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,19 @@
+UTILS = opkg-build opkg-unbuild opkg-compare-versions opkg-make-index opkg.py \
+        opkg-list-fields arfile.py opkg-buildpackage opkg-diff opkg-extract-file opkg-show-deps \
+        opkg-compare-indexes opkg-compare-versions.sh
+
+DESTDIR=
+PREFIX=/usr/local
+bindir=${prefix}/bin
+
+all: opkg-compare-versions
+
+opkg-compare-versions: opkg-compare-versions.c
+	$(CC) $(CFLAGS) -o opkg-compare-versions opkg-compare-versions.c
+
+install: opkg-compare-versions
+	install -d $(DESTDIR)$(bindir)
+	install -m 744 $(UTILS) $(DESTDIR)$(bindir)
+
+clean:
+	rm -rf opkg-compare-versions

Added: trunk/src/host/opkg-utils/arfile.py
===================================================================
--- trunk/src/host/opkg-utils/arfile.py	                        (rev 0)
+++ trunk/src/host/opkg-utils/arfile.py	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,125 @@
+"""
+arfile - A module to parse GNU ar archives.
+
+Copyright (c) 2006-7 Paul Sokolovsky
+This file is released under the terms 
+of GNU General Public License v2 or later.
+"""
+import sys
+import os
+import tarfile 
+
+
+class FileSection:
+    "A class which allows to treat portion of file as separate file object."
+
+    def __init__(self, f, offset, size):
+        self.f = f
+        self.offset = offset
+        self.size = size
+        self.seek(0, 0)
+
+    def seek(self, offset, whence = 0):
+#        print "seek(%x, %d)" % (offset, whence)
+        if whence == 0:
+            return self.f.seek(offset + self.offset, whence)
+        elif whence == 1:
+            return self.f.seek(offset, whence)
+        elif whence == 2:
+            return self.f.seek(self.offset + self.size + offset, 0)
+        else:
+            assert False
+
+    def tell(self):
+#        print "tell()"
+        return self.f.tell() - self.offset
+
+    def read(self, size = -1):
+#        print "read(%d)" % size
+        return self.f.read(size)
+
+class ArFile:
+
+    def __init__(self, f):
+        self.f = f
+        self.directory = {}
+        self.directoryRead = False
+
+        signature = self.f.readline()
+        assert signature == "!<arch>\n"
+        self.directoryOffset = self.f.tell()
+
+    def open(self, fname):
+        if self.directory.has_key(fname):
+            return FileSection(self.f, self.directory[fname][-1], int(self.directory[fname][5]))
+
+        if self.directoryRead:
+            raise IOError, (2, "AR member not found: " + fname)
+
+        f = self._scan(fname)
+        if f == None:
+            raise IOError, (2, "AR member not found: " + fname)
+        return f
+
+
+    def _scan(self, fname):
+        self.f.seek(self.directoryOffset, 0)
+
+        while True:
+            l = self.f.readline()
+            if not l: 
+                self.directoryRead = True
+                return None
+
+            if l == "\n":
+                l = self.f.readline()
+                if not l: break
+            l = l.replace('`', '')
+            descriptor = l.split()
+#            print descriptor
+            size = int(descriptor[5])
+            memberName = descriptor[0][:-1]
+            self.directory[memberName] = descriptor + [self.f.tell()]
+#            print "read:", memberName
+            if memberName == fname:
+                # Record directory offset to start from next time
+                self.directoryOffset = self.f.tell() + size
+                return FileSection(self.f, self.f.tell(), size)
+
+            # Skip data and loop
+            data = self.f.seek(size, 1)
+#            print hex(f.tell())
+
+
+if __name__ == "__main__":
+    if None:
+        f = open(sys.argv[1], "rb")
+
+        ar = ArFile(f)
+        tarStream = ar.open("data.tar.gz")
+        print "--------"
+        tarStream = ar.open("data.tar.gz")
+        print "--------"
+        tarStream = ar.open("control.tar.gz")
+        print "--------"
+        tarStream = ar.open("control.tar.gz2")
+
+        sys.exit(0)
+
+
+    dir = "."
+    if len(sys.argv) > 1:
+        dir = sys.argv[1]
+    for f in os.listdir(dir):
+        if not f.endswith(".ipk"): continue
+
+        print "=== %s ===" % f
+        f = open(dir + "/" + f, "rb")
+
+        ar = ArFile(f)
+        tarStream = ar.open("control.tar.gz")
+        tarf = tarfile.open("control.tar.gz", "r", tarStream)
+        #tarf.list()
+
+        f2 = tarf.extractfile("control")
+        print f2.read()

Added: trunk/src/host/opkg-utils/makePackage
===================================================================
--- trunk/src/host/opkg-utils/makePackage	                        (rev 0)
+++ trunk/src/host/opkg-utils/makePackage	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+# The general algorithm this program follows goes like this:
+#   Run tar to extract control from control.tar.gz from the package.
+#   Insert the filename, size, and md5 lines before the description.
+# Call it like this:
+#  find . -name \*.ipk | xargs -n 1 makePackage > Packages
+
+import sys
+import opkg
+
+fn = sys.argv[1]
+pkg = opkg.Package(fn)
+print pkg


Property changes on: trunk/src/host/opkg-utils/makePackage
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-build
===================================================================
--- trunk/src/host/opkg-utils/opkg-build	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-build	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,246 @@
+#!/bin/sh
+
+# opkg-build -- construct a .ipk from a directory
+# Carl Worth <cworth at east.isi.edu>
+# based on a script by Steve Redler IV, steve at sr-tech.com 5-21-2001
+# 2003-04-25 rea at sr.unh.edu
+#   Updated to work on Familiar Pre0.7rc1, with busybox tar.
+#   Note it Requires: binutils-ar (since the busybox ar can't create)
+#   For UID debugging it needs a better "find".
+set -e
+
+version=1.0
+
+opkg_extract_value() {
+	sed -e "s/^[^:]*:[[:space:]]*//"
+}
+
+required_field() {
+	field=$1
+
+	value=`grep "^$field:" < $CONTROL/control | opkg_extract_value`
+	if [ -z "$value" ]; then
+		echo "*** Error: $CONTROL/control is missing field $field" >&2
+		return 1
+	fi
+	echo $value
+	return 0
+}
+
+disallowed_field() {
+	field=$1
+
+	value=`grep "^$field:" < $CONTROL/control | opkg_extract_value`
+	if [ -n "$value" ]; then
+		echo "*** Error: $CONTROL/control contains disallowed field $field" >&2
+		return 1
+	fi
+	echo $value
+	return 0
+}
+
+pkg_appears_sane() {
+	local pkg_dir=$1
+
+	local owd=`pwd`
+	cd $pkg_dir
+
+	PKG_ERROR=0
+
+	tilde_files=`find . -name '*~'`
+	if [ -n "$tilde_files" ]; then
+	    if [ "$noclean" = "1" ]; then
+		echo "*** Warning: The following files have names ending in '~'.
+You probably want to remove them: " >&2
+		ls -ld $tilde_files
+		echo >&2
+	    else
+		echo "*** Removing the following files: $tilde_files"
+		rm -f "$tilde_files"
+	    fi
+	fi
+
+	large_uid_files=`find . -uid +99 || true`
+
+	if [ "$ogargs" = "" ]  && [ -n "$large_uid_files" ]; then
+		echo "*** Warning: The following files have a UID greater than 99.
+You probably want to chown these to a system user: " >&2
+		ls -ld $large_uid_files
+		echo >&2
+	fi
+	    
+
+	if [ ! -f "$CONTROL/control" ]; then
+		echo "*** Error: Control file $pkg_dir/$CONTROL/control not found." >&2
+		cd $owd
+		return 1
+	fi
+
+	pkg=`required_field Package`
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+
+	version=`required_field Version | sed 's/Version://; s/^.://g;'`
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+
+	arch=`required_field Architecture`
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+
+	required_field Maintainer >/dev/null
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+
+	required_field Description >/dev/null
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+
+	section=`required_field Section`
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+	if [ -z "$section" ]; then
+	    echo "The Section field should have one of the following values:" >&2
+	    echo "admin, base, comm, editors, extras, games, graphics, kernel, libs, misc, net, text, web, x11" >&2
+	fi
+
+	priority=`required_field Priority`
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+	if [ -z "$priority" ]; then
+	    echo "The Priority field should have one of the following values:" >&2
+	    echo "required, important, standard, optional, extra." >&2
+	    echo "If you don't know which priority value you should be using, then use \`optional'" >&2
+	fi
+
+	source=`required_field Source`
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+	if [ -z "$source" ]; then
+	    echo "The Source field contain the URL's or filenames of the source code and any patches" 
+	    echo "used to build this package.  Either gnu-style tarballs or Debian source packages "
+	    echo "are acceptable.  Relative filenames may be used if they are distributed in the same"
+	    echo "directory as the .ipk file."
+	fi
+
+	disallowed_filename=`disallowed_field Filename`
+	[ "$?" -ne 0 ] && PKG_ERROR=1
+
+	if echo $pkg | grep '[^a-z0-9.+-]'; then
+		echo "*** Error: Package name $name contains illegal characters, (other than [a-z0-9.+-])" >&2
+		PKG_ERROR=1;
+	fi
+
+	local bad_fields=`sed -ne 's/^\([^[:space:]][^:[:space:]]\+[[:space:]]\+\)[^:].*/\1/p' < $CONTROL/control | sed -e 's/\\n//'`
+	if [ -n "$bad_fields" ]; then
+		bad_fields=`echo $bad_fields`
+		echo "*** Error: The following fields in $CONTROL/control are missing a ':'" >&2
+		echo "	$bad_fields" >&2
+		echo "opkg-build: This may be due to a missing initial space for a multi-line field value" >&2
+		PKG_ERROR=1
+	fi
+
+	for script in $CONTROL/preinst $CONTROL/postinst $CONTROL/prerm $CONTROL/postrm; do
+		if [ -f $script -a ! -x $script ]; then
+			echo "*** Error: package script $script is not executable" >&2
+			PKG_ERROR=1
+		fi
+	done
+
+	if [ -f $CONTROL/conffiles ]; then
+		for cf in `cat $CONTROL/conffiles`; do
+			if [ ! -f ./$cf ]; then
+				echo "*** Error: $CONTROL/conffiles mentions conffile $cf which does not exist" >&2
+				PKG_ERROR=1
+			fi
+		done
+	fi
+
+	cd $owd
+	return $PKG_ERROR
+}
+
+###
+# opkg-build "main"
+###
+ogargs=""
+outer=ar
+noclean=0
+usage="Usage: $0 [-c] [-C] [-o owner] [-g group] <pkg_directory> [<destination_directory>]"
+while getopts "cg:ho:v" opt; do
+    case $opt in
+	o ) owner=$OPTARG
+	    ogargs="--owner=$owner"
+	    ;;
+	g ) group=$OPTARG
+	    ogargs="$ogargs --group=$group"
+	    ;;
+        c ) outer=tar
+            ;;
+        C ) noclean=1
+            ;;
+	v ) echo $version
+	    exit 0
+	    ;;
+	h ) 	echo $usage  >&2 ;;
+	\? ) 	echo $usage  >&2
+	esac
+done
+
+
+shift $(($OPTIND - 1))
+
+# continue on to process additional arguments
+
+case $# in
+1)
+	dest_dir=$PWD
+	;;
+2)
+	dest_dir=$2
+	if [ "$dest_dir" = "." -o "$dest_dir" = "./" ] ; then
+	    dest_dir=$PWD
+	fi
+	;;
+*)
+	echo $usage >&2
+	exit 1 
+	;;
+esac
+
+pkg_dir=$1
+
+if [ ! -d $pkg_dir ]; then
+	echo "*** Error: Directory $pkg_dir does not exist" >&2
+	exit 1
+fi
+
+# CONTROL is second so that it takes precedence
+CONTROL=
+[ -d $pkg_dir/DEBIAN ] && CONTROL=DEBIAN
+[ -d $pkg_dir/CONTROL ] && CONTROL=CONTROL
+if [ -z "$CONTROL" ]; then
+	echo "*** Error: Directory $pkg_dir has no CONTROL subdirectory." >&2
+	exit 1
+fi
+
+if ! pkg_appears_sane $pkg_dir; then
+	echo >&2
+	echo "opkg-build: Please fix the above errors and try again." >&2
+	exit 1
+fi
+
+tmp_dir=$dest_dir/IPKG_BUILD.$$
+mkdir $tmp_dir
+
+echo $CONTROL > $tmp_dir/tarX
+( cd $pkg_dir && tar $ogargs -X $tmp_dir/tarX -czf $tmp_dir/data.tar.gz . )
+( cd $pkg_dir/$CONTROL && tar $ogargs -czf $tmp_dir/control.tar.gz . )
+rm $tmp_dir/tarX
+
+echo "2.0" > $tmp_dir/debian-binary
+
+pkg_file=$dest_dir/${pkg}_${version}_${arch}.ipk
+rm -f $pkg_file
+if [ "$outer" = "ar" ] ; then
+  ( cd $tmp_dir && ar -crf $pkg_file ./debian-binary ./data.tar.gz ./control.tar.gz )
+else
+  ( cd $tmp_dir && tar -zcf $pkg_file ./debian-binary ./data.tar.gz ./control.tar.gz )
+fi
+
+rm $tmp_dir/debian-binary $tmp_dir/data.tar.gz $tmp_dir/control.tar.gz
+rmdir $tmp_dir
+
+echo "Packaged contents of $pkg_dir into $pkg_file"


Property changes on: trunk/src/host/opkg-utils/opkg-build
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-buildpackage
===================================================================
--- trunk/src/host/opkg-utils/opkg-buildpackage	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-buildpackage	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,223 @@
+#!/bin/sh
+#
+# Author: Oliver Kurth <oliver.kurth at innominate.com>
+#
+# Description:
+# builds an opkg package from a source tarball using opkg-build. Idea stolen
+# from Debian dpkg-buildpackage.
+# 
+# - unpack the source tarball.
+# - cd to the source distribution, change whatever you need to make the
+#   package compile and work on the ipaq.
+# - create a directory 'opkg'
+# - put all files which go to the 'CONTROL' directory of the root of the
+#   installed package into opkg.
+# - the version (Version field in control) should match the version of the
+#   source tarball, optionally with a digit (eg. -1) appended.
+# - additionally, put a file there called 'rules' which is a shell script
+#   accepting arguments 'build', 'install' and 'clean'. It can be a 
+#   Makefile starting with the line '#!/usr/bin/make -f'
+#   * the build target does things like ./configure and make.
+#   * the install target installs to a temporary directory (make
+#   DESTDIR=/tmp/package) and removes unnecessary items (eg. man pages)
+#   * clean cleans ;-)
+#
+# You should run this with fakeroot (1) or as root.
+# If all went well, you will find a diff file and an *.ipk file in the
+# directory above.
+
+set -e
+
+SCRIPTDIR=/usr/local/bin
+
+SCRIPTNAME=`basename $0`
+
+opkg_extract_value() {
+	sed -e "s/^[^:]*:[[:space:]]*//"
+}
+
+required_field() {
+	field=$1
+
+	value=`grep "^$field:" < $CONTROL/control | opkg_extract_value`
+	if [ -z "$value" ]; then
+		echo "opkg-build: Error: $CONTROL/control is missing field $field" ;
+		PKG_ERROR=1
+	fi
+	echo $value
+}
+
+pkg_appears_sane_control() {
+	local pkg_dir=$1
+
+	local owd=`pwd`
+	cd $pkg_dir
+
+	if [ ! -f "$CONTROL/control" ]; then
+		echo "opkg-build: Error: Control file $pkg_dir/$CONTROL/control not found."
+		cd $owd
+		return 1
+	fi
+
+	pkg=`required_field Package`
+	version=`required_field Version | sed 's/.*://;'`
+	arch=`required_field Architecture`
+	required_field Maintainer >/dev/null
+	required_field Description >/dev/null
+
+	if echo $pkg | grep '[^a-z0-9.+-]'; then
+		echo "opkg-build: Error: Package name $name contains illegal characters, (other than [a-z0-9.+-])"
+		PKG_ERROR=1;
+	fi
+
+	local bad_fields=`sed -ne 's/^\([^[:space:]][^:[:space:]]\+[[:space:]]\+\)[^:].*/\1/p' < $CONTROL/control | sed -e 's/\\n//'`
+	if [ -n "$bad_fields" ]; then
+		bad_fields=`echo $bad_fields`
+		echo "opkg-build: Error: The following fields in $CONTROL/control are missing a ':'"
+		echo "	$bad_fields"
+		echo "opkg-build: This may be due to a missing initial space for a multi-line field value"
+		PKG_ERROR=1
+	fi
+
+	cd $owd
+	return $PKG_ERROR
+}
+
+pkg_appears_sane_scripts() {
+	local pkg_dir=$1
+
+	local owd=`pwd`
+	cd $pkg_dir
+
+	for script in $CONTROL/preinst $CONTROL/postinst $CONTROL/prerm $CONTROL/postrm; do
+		if [ -f $script -a ! -x $script ]; then
+			echo "opkg-build: Error: package script $script is not executable"
+			PKG_ERROR=1
+		fi
+	done
+
+	cd $owd
+	return $PKG_ERROR
+}
+
+pkg_dir_abs=`pwd`
+pkg_dir_base=`basename ${pkg_dir_abs}`
+
+pkg_dir=.
+
+[ -d ./CONTROL ] && CONTROL=./CONTROL
+[ -d ./opkg ] && CONTROL=./opkg
+if [ -z "$CONTROL" ]; then
+        echo "${SCRIPT_NAME}: Error: Directory $pkg_dir has no opkg or CONTROL subdirectory."
+        exit 1
+fi
+
+if ! pkg_appears_sane_control $pkg_dir && pkg_appears_sane_control $pkg_dir; then
+        echo "Please fix the above errors and try again."
+        exit 1
+fi
+
+echo "Package = $pkg"
+echo "Version = $version"
+version_up=`echo ${version} | sed "s/\-[0-9]\+//"`
+echo "Upstream Version = $version_up"
+pkg_upname=${pkg}-${version_up}
+echo "Package Name = $pkg_upname"
+pkg_tarball=${pkg_upname}.tar.gz
+echo "Tarball Name = $pkg_tarball"
+
+if [ ! -x ${CONTROL}/rules ]; then
+	echo "${CONTROL}/rules not found or not executable."
+	exit 1
+fi
+
+#
+# unpack upstream tarball and make diff
+#
+if [ -e ../${pkg_tarball} ] ; then
+	(
+	set +e
+
+	cd ..
+
+	rm -rf ${pkg_upname}.tmp
+	rm -rf ${pkg_upname}.orig
+
+	mkdir ${pkg_upname}.tmp
+	cd ${pkg_upname}.tmp
+	echo "unpacking source tarball ${pkg_tarball}"
+	tar zxf ${pkg_dir_abs}/../${pkg_tarball}
+	dir=`find . -maxdepth 1 -name "*" -type d`
+	cnt=`echo $dir | wc -l`
+	if [ ${cnt} != 1 ] ; then
+		echo "Arrghh !!!!"
+		echo "upstream package contains more than one top level directory"
+		echo "giving up..."
+		exit 1
+	fi
+	mv ${dir} ${pkg_upname}.orig
+	mv ${pkg_upname}.orig ..
+	cd ..
+	echo "creating diff"
+	diff -uNr  ${pkg_upname}.orig ${pkg_dir_base} > ${pkg}-${version}.diff
+	rm -f ${pkg}-${version}.diff.gz
+	echo "gzipping ${pkg}-${version}.diff"
+	gzip ${pkg}-${version}.diff
+
+	echo "Removing temporary source directorys"
+	rm -rf ${pkg_upname}.tmp
+	rm -rf ${pkg_upname}.orig
+	)
+fi
+
+# build package
+if ! ${CONTROL}/rules build; then
+	echo "Build failed"
+	exit 1
+fi
+
+# install it to tmp directory
+if ! ${CONTROL}/rules install; then
+	echo "Install failed"
+	exit 1
+fi
+
+# copy contents of control directory
+mkdir /tmp/${pkg}/CONTROL
+
+files_required="control"
+files_optional="preinst postinst prerm postrm"
+
+for i in ${files_required} ; do
+	file=${CONTROL}/$i
+	
+	if [ -e ${file} ] ; then
+		cp $file /tmp/${pkg}/CONTROL
+	else
+		echo "required file ${file} missing"
+	fi
+done
+
+for i in ${files_optional} ; do
+	file=${CONTROL}/$i
+	
+	if [ -e ${file} ] ; then
+		cp $file /tmp/${pkg}/CONTROL
+	fi
+done
+
+# build the ipk package
+owd=`pwd`
+cd ..
+opkg-build /tmp/${pkg} || exit 1
+
+rm -rf /tmp/${pkg}
+
+cd $owd
+if ! ${CONTROL}/rules clean; then
+	echo "Clean failed"
+	exit 1
+fi
+
+# Yep. That's it!
+exit 0


Property changes on: trunk/src/host/opkg-utils/opkg-buildpackage
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-compare-indexes
===================================================================
--- trunk/src/host/opkg-utils/opkg-compare-indexes	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-compare-indexes	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+import sys, os
+from glob import glob
+import commands
+import opkg
+
+pkg_dir1 = sys.argv[1]
+pkg_dir2 = sys.argv[2]
+
+if ( not pkg_dir1 or not pkg_dir2 ):
+	sys.stderr.write("Usage: opkg-update-index <package_directory1> <package_directory2>\n")
+	sys.exit(1)
+
+pkgs1 = opkg.Packages()
+pkgs1.read_packages_file(pkg_dir1 + '/Packages')
+
+pkgs2 = opkg.Packages()
+pkgs2.read_packages_file(pkg_dir2 + '/Packages')
+
+names1 = pkgs1.packages.keys()
+names2 = pkgs2.packages.keys()
+
+## union of the two names lists
+pkgs = {}
+for name in names1:
+    pkgs[name] = pkgs1.packages[name]
+for name in names2:
+    pkgs[name] = pkgs2.packages[name]
+
+names = pkgs.keys()
+names.sort() 
+for name in names:
+    pkg1 = None
+    pkg2 = None
+    if pkgs1.packages.has_key(name):
+        pkg1 = pkgs1.packages[name]
+    if pkgs2.packages.has_key(name):
+        pkg2 = pkgs2.packages[name]
+    if pkg1 and pkg2 and pkg1.version != pkg2.version:
+        print "CHANGED: %s from version %s to %s (%s)" % (pkg1.package, pkg1.version, pkg2.version, pkg2.maintainer)
+        cmd = "opkg-diff %s %s > %s " % ((pkg_dir1 + pkg1.filename),  (pkg_dir2 + pkg2.filename), (pkg1.package + '.diff'))
+        print cmd
+	commands.getstatusoutput(cmd)
+    if not pkg1:
+        print "NEW: %s version %s (%s)"% (pkg2.package, pkg2.version, pkg2.maintainer)
+    if not pkg2:
+        print "DELETE: %s version %s (%s)"% (pkg1.package, pkg1.version, pkg1.maintainer)
+    


Property changes on: trunk/src/host/opkg-utils/opkg-compare-indexes
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-compare-versions.c
===================================================================
--- trunk/src/host/opkg-utils/opkg-compare-versions.c	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-compare-versions.c	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,163 @@
+/*
+ * libdpkg - Debian packaging suite library routines
+ * vercmp.c - comparison of version numbers
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10 at cus.cam.ac.uk>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+# define _(Text) Text
+
+struct versionrevision {
+  unsigned long epoch;
+  char *version;
+  const char *revision;
+};  
+
+static int verrevcmp(const char *val, const char *ref) 
+{
+  int vc, rc;
+  long vl, rl;
+  const char *vp, *rp;
+  const char *vsep, *rsep;
+
+  if (!val) val= "";
+  if (!ref) ref= "";
+  for (;;) {
+    vp= val;  while (*vp && !isdigit(*vp)) vp++;
+    rp= ref;  while (*rp && !isdigit(*rp)) rp++;
+    for (;;) {
+      vc= val == vp ? 0 : *val++;
+      rc= ref == rp ? 0 : *ref++;
+      if (!rc && !vc) break;
+      if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
+      if (rc && !isalpha(rc)) rc += 256;
+      if (vc != rc) return vc - rc;
+    }
+    val= vp;
+    ref= rp;
+    vl=0;  if (isdigit(*vp)) vl= strtol(val,(char**)&val,10);
+    rl=0;  if (isdigit(*rp)) rl= strtol(ref,(char**)&ref,10);
+    if (vl != rl) return vl - rl;
+
+    vc = *val;
+    rc = *ref;
+    vsep = strchr(".-", vc);
+    rsep = strchr(".-", rc);
+    if (vsep && !rsep) return -1;
+    if (!vsep && rsep) return +1;
+
+    if (!*val && !*ref) return 0;
+    if (!*val) return -1;
+    if (!*ref) return +1;
+  }
+}
+
+int versioncompare(const struct versionrevision *version,
+                   const struct versionrevision *refversion) 
+{
+  int r;
+
+  if (version->epoch > refversion->epoch) return 1;
+  if (version->epoch < refversion->epoch) return -1;
+  r= verrevcmp(version->version,refversion->version);  if (r) return r;
+  r= verrevcmp(version->revision,refversion->revision); if (r) return r;
+  return r;
+}
+
+int versionsatisfied3(const struct versionrevision *it,
+                      const struct versionrevision *ref,
+                      const char *op) 
+{
+  int r;
+  r= versioncompare(it,ref);
+  if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0)
+    return r <= 0;
+  if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0)
+    return r >= 0;
+  if (strcmp(op, "<<") == 0)
+    return r < 0;
+  if (strcmp(op, ">>") == 0)
+    return r > 0;
+  if (strcmp(op, "=") == 0)
+    return r == 0;
+  fprintf(stderr, "unknown operator: %s", op);
+
+  exit(1);
+}
+
+const char *parseversion(struct versionrevision *rversion, const char *string) 
+{
+  char *hyphen, *colon, *eepochcolon;
+  unsigned long epoch;
+
+  if (!*string) return _("version string is empty");
+  
+  colon= strchr(string,':');
+  if (colon) {
+    epoch= strtoul(string,&eepochcolon,10);
+    if (colon != eepochcolon) return _("epoch in version is not number");
+    if (!*++colon) return _("nothing after colon in version number");
+    string= colon;
+    rversion->epoch= epoch;
+  } else {
+    rversion->epoch= 0;
+  }
+
+  rversion->revision = "";
+
+  rversion->version= malloc(strlen(string)+1);
+  strcpy(rversion->version, string);
+
+#if 0
+  fprintf(stderr,"Parsed version: %lu, %s\n",
+	  rversion->epoch,
+	  rversion->version);
+#endif
+	  
+  return 0;
+}
+
+int main(int argc, char *argv[]) 
+{
+  const char *err;
+  struct versionrevision ver, ref;
+
+  if (argc < 4) {
+    fprintf(stderr, "usage: %s: version op refversion\n", argv[0]);
+    return 2;
+  }
+
+  err = parseversion(&ver, argv[1]);
+  if (err) {
+    fprintf(stderr, "Invalid version `%s': %s\n", argv[1], err);
+    return 2;
+  }
+    
+  err = parseversion(&ref, argv[3]);
+  if (err) {
+    fprintf(stderr, "Invalid version `%s': %s\n", argv[3], err);
+    return 2;
+  }
+
+  return ! versionsatisfied3(&ver, &ref, argv[2]);
+}
+
+


Property changes on: trunk/src/host/opkg-utils/opkg-compare-versions.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/src/host/opkg-utils/opkg-compare-versions.sh
===================================================================
--- trunk/src/host/opkg-utils/opkg-compare-versions.sh	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-compare-versions.sh	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,77 @@
+#!/bin/sh
+set -e
+
+# This is a little experiment to see how expensive it would be to
+# compare versions in a shell script. This script is not done yet
+# and the nasiest part is still left undone, (the fact that in Debian
+# versions all letters compare less than all non-letters).
+#
+# It looks to me like version comprehension might be the feature that pushes 
+# opkg from /bin/sh to compiled C code...
+
+if [ $# -lt 3 ]; then
+	echo "
+usage: opkg-compare-versions v1 op v2
+	where op in (<<, <=, =, >=, >>)
+Return value is 0 if v1 op v2 is satisfied, 1 otherwise"
+	exit 2
+fi
+
+v1=$1
+op=$2
+v2=$3
+
+# Debian has a little historical problem with operators...
+may_be_equal=0
+case $op in
+'>>')
+	op="-gt"
+;;
+'<<')
+	op="-lt"
+;;
+'>'|'>=')
+	op="-gt"
+	may_be_equal=1
+;;
+'<'|'<=')
+	op="-lt"
+	may_be_equal=1
+;;
+'=')
+	may_be_equal=1
+;;
+*)
+	echo "opkg_compare_versions: Invalid operator \`$op' valid operators are (<<, <=, =, >=, >>)"
+	exit 1
+;;
+esac
+
+if [ $may_be_equal == 1 -a $v1 == $v2 ]; then
+	exit 0;
+elif [ $op == '=' ]; then
+	exit 1;
+fi
+
+epoch1=`echo $v1 | sed -ne 's/:.*//p'`
+v1=`echo $v1 | sed -e 's/^[^:]*://'`
+epoch2=`echo $v2 | sed -ne 's/:.*//p'`
+v2=`echo $v2 | sed -e 's/^[^:]*://'`
+
+upstream1=`echo $v1 | sed -e '/-/s/\(.*\)-.*/\1/'`
+debian_rev1=`echo $v1 | sed -ne 's/.*-//p'`
+upstream2=`echo $v2 | sed -e '/-/s/\(.*\)-.*/\1/'`
+debian_rev2=`echo $v2 | sed -ne 's/.*-//p'`
+
+echo "$epoch1:$upstream1-$debian_rev1 $op $epoch2:$upstream2-$debian_rev2"
+
+exit 3
+
+[ -z $epoch1 ] && epoch1="0"
+[ -z $epoch2 ] && epoch2="0"
+
+if [ $epoch1 != $epoch2 ]; then
+	exit `[ $epoch1 $op $epoch2 ]`
+fi
+
+exit 3


Property changes on: trunk/src/host/opkg-utils/opkg-compare-versions.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-diff
===================================================================
--- trunk/src/host/opkg-utils/opkg-diff	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-diff	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+pkg1=$1
+dir1=`echo $pkg1 | sed s/.ipk//`
+dir1=`basename $dir1` 
+pkg2=$2
+dir2=`echo $pkg2 | sed s/.ipk//`
+dir2=`basename $dir2` 
+
+opkg-unbuild $pkg2
+opkg-unbuild $pkg1
+
+diff -urN $dir1 $dir2
+
+rm -fr $dir1 $dir2


Property changes on: trunk/src/host/opkg-utils/opkg-diff
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-extract-file
===================================================================
--- trunk/src/host/opkg-utils/opkg-extract-file	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-extract-file	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+set -e
+
+if [ $# -lt 1 ]; then
+	echo "usage: $0: package.ipk filename ..."
+	exit 1
+fi
+
+if [ $# -eq 2 ]; then
+  opkgfilename=$1
+  filename=$2
+else
+  echo "usage: $0 opkgfilename filename"  
+  exit -1
+fi
+
+case $opkgfilename in
+http:*)
+    wget -N $opkgfilename
+    opkgfilename=`basename $opkgfilename`
+    echo eez http url $opkgfilename
+;;
+ftp:*)
+    wget -N $opkgfilename
+    opkgfilename=`basename $opkgfilename`
+    echo eez ftp url $opkgfilename
+;;
+esac
+
+
+tmpdir=/tmp/opkg-extract-$$
+mkdir $tmpdir
+
+pkgdir=$tmpdir/`basename $opkgfilename | sed 's/.*\///;s/.ipk$//;s/.deb$//'`
+
+mkdir -p $pkgdir/CONTROL
+
+cur_dir=$PWD
+cd $pkgdir; (ar x $cur_dir/$opkgfilename || tar zxf $cur_dir/$opkgfilename) >& /dev/null
+cd $cur_dir
+
+tar xzf $pkgdir/data.tar.gz -C $pkgdir
+tar xzf $pkgdir/control.tar.gz -C $pkgdir/CONTROL
+rm -f $pkgdir/control.tar.gz $pkgdir/data.tar.gz $pkgdir/debian-binary
+
+cp $pkgdir/$filename `basename $filename`
+ls -l `basename $filename`
+file `basename $filename`
+rm -fr $tmpdir


Property changes on: trunk/src/host/opkg-utils/opkg-extract-file
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-list-fields
===================================================================
--- trunk/src/host/opkg-utils/opkg-list-fields	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-list-fields	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+import sys, opkg
+
+def usage():
+     sys.stderr.write("%s ipk\n" % (sys.argv[0],))
+     sys.exit(-1)
+
+if (len(sys.argv) < 2):
+     usage()
+
+print opkg.Package(sys.argv[1])
+


Property changes on: trunk/src/host/opkg-utils/opkg-list-fields
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-make-index
===================================================================
--- trunk/src/host/opkg-utils/opkg-make-index	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-make-index	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,201 @@
+#!/usr/bin/python
+
+import sys, os, posixpath
+from glob import glob
+import commands
+import opkg
+import getopt
+import string
+import re
+
+verbose = 0
+
+def usage():
+     sys.stderr.write("%s [-h] [-s] [-m] [-l Packages.filelist] [-p Packages] [-r Packages.old] [-L localesdir] [-v] packagesdir\n" % (sys.argv[0],))
+     sys.exit(-1)
+
+def to_morgue(filename):
+     morgue_dir = pkg_dir + "/morgue"
+     if verbose:
+          sys.stderr.write ("Moving " + filename + " to morgue\n")
+     if not os.path.exists(morgue_dir):
+          os.mkdir(morgue_dir)
+     if os.path.exists(pkg_dir + "/" + filename):
+          os.rename(pkg_dir + "/" + filename, morgue_dir + "/" + filename)
+     if os.path.exists(pkg_dir + "/" + filename + ".asc"):
+          os.rename(pkg_dir + "/" + filename + ".asc", morgue_dir + "/" + filename + ".asc")
+
+locales_dir = None
+def to_locale(filename, locale):
+     locale_dir = pkg_dir + '/' + locales_dir + '/' + locale + "/"
+     if verbose:
+          sys.stderr.write ("Moving " + filename + " to " + locale_dir + "\n")
+     if not os.path.exists(locale_dir):
+          os.mkdir(locale_dir)
+     os.rename(pkg_dir + "/" + filename, locale_dir + "/" + filename)
+     if os.path.exists(pkg_dir + "/" + filename + ".asc"):
+          os.rename(pkg_dir + "/" + filename + ".asc", locale_dir + "/" + filename + ".asc")
+
+old_filename = None
+packages_filename = None
+filelist_filename = "Packages.filelist"
+stamplist_filename = "Packages.stamps"
+opt_s = 0
+opt_m = 0
+(opts, remaining_args) = getopt.getopt(sys.argv[1:], "hl:p:vsmr:L:")
+for (optkey, optval) in opts:
+     if optkey == '-h': 
+          usage()
+     if optkey == '-s': 
+          opt_s = 1
+     if optkey == '-p': 
+          packages_filename = optval
+          stamplist_filename = optval + ".stamps"
+     if optkey == '-l':
+          filelist_filename = optval
+     if optkey == '-v':
+          verbose = 1
+     if optkey == '-m':
+          opt_m = 1
+     if optkey == '-r':
+          old_filename = optval
+     if optkey == '-L':
+          locales_dir = optval
+
+if ( not remaining_args ):
+     usage()
+
+pkg_dir=remaining_args[0]
+
+packages = opkg.Packages()
+
+old_pkg_hash = {}
+if packages_filename and not old_filename and os.path.exists(packages_filename):
+     old_filename = packages_filename
+
+pkgsStamps = {}
+if old_filename:
+     if (verbose):
+          sys.stderr.write("Reading package list from " + old_filename + "\n")
+     old_packages = opkg.Packages()
+     old_packages.read_packages_file(old_filename)
+     for k in old_packages.packages.keys():
+          p = old_packages.packages[k]
+          old_pkg_hash[p.filename] = p
+     try:
+        f = open(stamplist_filename, "r")
+        for l in f:
+            l = l.strip()
+            s, f = l.split(" ", 1)
+            pkgsStamps[f] = int(s)
+     except IOError:
+        pass
+
+if (verbose):
+     sys.stderr.write("Reading in all the package info from %s\n" % (pkg_dir, ))
+files=glob(pkg_dir + '/*.ipk') + glob(pkg_dir + '/*.deb')
+files.sort()
+for filename in files:
+     basename = os.path.basename(filename)
+     pkg = None
+     fnameStat = os.stat(filename)
+     if old_pkg_hash.has_key(basename):
+          if pkgsStamps.has_key(basename) and fnameStat.st_mtime == pkgsStamps[basename]:
+            if (verbose):
+               sys.stderr.write("Found %s in Packages\n" % (filename,))
+            pkg = old_pkg_hash[basename]
+          else:
+               sys.stderr.write("Found %s in Packages, but mtime differs - re-reading\n" % (filename,))
+
+     if not pkg:
+          if (verbose):
+               sys.stderr.write("Reading info for package %s\n" % (filename,))
+          pkg = opkg.Package(filename)
+     pkg_key = ("%s:%s" % (pkg.package, pkg.architecture))
+     if (packages.packages.has_key(pkg_key)):
+          old_filename = packages.packages[pkg_key].filename
+     else:
+          old_filename = ""
+     s = packages.add_package(pkg)
+     pkgsStamps[basename] = fnameStat.st_mtime
+     if s == 0:
+          if old_filename:
+               # old package was displaced by newer
+               if opt_m:
+                    to_morgue(old_filename)
+               if opt_s:
+                    print pkg_dir + "/" + old_filename
+     else:
+          if opt_m:
+               to_morgue(basename)
+          if opt_s:
+               print filename
+
+pkgsStampsFile = open(stamplist_filename, "w")
+for f in pkgsStamps.keys():
+    pkgsStampsFile.write("%d %s\n" % (pkgsStamps[f], f))
+pkgsStampsFile.close()
+
+if opt_s:
+     sys.exit(0)
+
+if verbose:
+     sys.stderr.write("Generating Packages file\n")
+if packages_filename:
+     old_stdout = sys.stdout
+     tmp_packages_filename = ("%s.%d" % (packages_filename, os.getpid()))
+     sys.stdout = open(tmp_packages_filename, "w")
+names = packages.packages.keys()
+names.sort()
+for name in names:
+     pkg = packages.packages[name]
+     if locales_dir and pkg.depends:
+         depends = string.split(pkg.depends, ',')
+         locale = None
+         for d in depends:
+              m = re.match('.*virtual-locale-([a-zA-Z]+).*', d)
+              mp = re.match('locale-base-([a-zA-Z]+)([-+])?.*', pkg.package)
+              if m:
+                   locale = m.group(1)
+              if mp:
+                   locale = mp.group(1)
+         if locale:
+              to_locale(pkg.filename, locale)
+              continue
+     if (verbose):
+          sys.stderr.write("Writing info for package %s\n" % (pkg.package,))
+     print pkg
+if packages_filename:
+     sys.stdout.close()
+     sys.stdout = old_stdout
+     gzip_filename = ("%s.gz" % packages_filename)
+     tmp_gzip_filename = ("%s.%d" % (gzip_filename, os.getpid()))
+     gzip_cmd = "gzip -9c < %s > %s" % (tmp_packages_filename, tmp_gzip_filename)
+     (rc, outtext) = commands.getstatusoutput(gzip_cmd)
+     print outtext
+     os.rename(tmp_packages_filename, packages_filename)
+     os.rename(tmp_gzip_filename, gzip_filename)
+
+if verbose:
+     sys.stderr.write("Generate Packages.filelist file\n")
+files = {}
+names = packages.packages.keys()
+names.sort()
+for name in names:
+     for fn in packages[name].get_file_list():
+          (h,t) = os.path.split(fn)
+          if not t: continue
+          if not files.has_key(t): files[t] = name+':'+fn
+          else: files[t] = files[t] + ',' + name+':'+fn
+
+if filelist_filename:
+     tmp_filelist_filename = ("%s.%d" % (filelist_filename, os.getpid()))
+     sys.stdout = open(tmp_filelist_filename, "w")
+     names = files.keys()
+     names.sort()
+     for name in names:
+          print name,files[name]
+     sys.stdout.close()
+     if posixpath.exists(filelist_filename):
+          os.unlink(filelist_filename)
+     os.rename(tmp_filelist_filename, filelist_filename)


Property changes on: trunk/src/host/opkg-utils/opkg-make-index
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-show-deps
===================================================================
--- trunk/src/host/opkg-utils/opkg-show-deps	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-show-deps	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+
+import sys, os, posixpath
+from glob import glob
+import commands
+import opkg
+import getopt
+import string
+import re
+
+verbose = 0
+
+def usage():
+     sys.stderr.write("%s [-p Packages] package ...\n" % (sys.argv[0],))
+     sys.exit(-1)
+
+packages_filename = "Packages"
+(opts, remaining_args) = getopt.getopt(sys.argv[1:], "hp:")
+for (optkey, optval) in opts:
+     if optkey == '-h': 
+          usage()
+     if optkey == '-p': 
+          packages_filename = optval
+
+if ( not remaining_args ):
+     usage()
+
+packages = opkg.Packages()
+packages.read_packages_file(packages_filename)
+
+required = {}
+provider_hash = {}
+
+def split_list(str):
+     r = []
+     l = string.split(str, ",")
+     for i in l:
+          ll = string.split(i, "|")
+          for ii in ll:
+               ii = string.strip(ii)
+               r.append(ii)
+     return r
+
+for i in packages.packages.keys():
+     p = packages.packages[i]
+     if not provider_hash.has_key(p.package):
+          provider_hash[p.package] = []
+     provider_hash[p.package].append(p)
+     if p.provides:
+          provides = string.split(p.provides, ",")
+          for prov in provides:
+               prov = string.strip(prov)
+               if not provider_hash.has_key(prov):
+                    provider_hash[prov] = []
+               provider_hash[prov].append(p)
+
+def find_package(name):
+     if provider_hash.has_key(name):
+          return provider_hash[name]
+     return None
+
+def recurse(pkg):
+     required[pkg.package] = 1
+     if pkg.depends:
+          deps = split_list(pkg.depends)
+          for dep in deps:
+               dep = re.sub("\s*\(.*\)", "", dep)
+               dep = re.sub("\*$", "", dep)
+               newpkgs = find_package(dep)
+               if newpkgs:
+                    for newpkg in newpkgs:
+	                 if required.has_key(newpkg.package):
+			      return
+                    recurse(newpkgs[0])
+               else:
+                    sys.stderr.write("unsatisfied dependency of %s on '%s'\n" % (pkg.package, dep))
+
+for root in remaining_args:
+     pkgs = find_package(root)
+     if not pkgs:
+          sys.stderr.write("Can't find root package '%s'\n" % root)
+          sys.exit(-1)
+     for p in pkgs:
+          recurse(p)
+     
+for pkg in required.keys():
+     print pkg
+


Property changes on: trunk/src/host/opkg-utils/opkg-show-deps
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-unbuild
===================================================================
--- trunk/src/host/opkg-utils/opkg-unbuild	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-unbuild	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+
+import sys, os, re
+
+if (len(sys.argv) == 0):
+    print 'usage: %s: package.ipk' % sys.argv[0]
+    sys.exit(1)
+
+for filename in sys.argv[1:]:
+    m = re.match('((.*/)*)(.*)', filename)
+    pkg = m.group(3)
+    m = re.match('(.*)((.ipk)|(.deb))', filename)
+    if m:
+        pkg = m.group(1)
+
+    os.system('rm -fr %s' % pkg)
+    os.mkdir(pkg)
+    os.mkdir(pkg + '/CONTROL')
+
+    os.system('cd %s; (ar x ../%s || tar zxf ../%s) >& /dev/null' % (pkg, filename, filename))
+
+    os.system('tar xzf %s/data.tar.gz -C %s' % (pkg, pkg))
+    os.system('tar xzf %s/control.tar.gz -C %s/CONTROL' % (pkg, pkg))
+    os.system('rm -f %s/control.tar.gz %s/data.tar.gz %s/debian-binary' % (pkg, pkg, pkg))


Property changes on: trunk/src/host/opkg-utils/opkg-unbuild
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg-update-index
===================================================================
--- trunk/src/host/opkg-utils/opkg-update-index	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg-update-index	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,24 @@
+#!/usr/bin/env python2.1
+
+import sys, os
+from glob import glob
+import commands
+import opkg
+
+pkg_dir=sys.argv[1]
+pkg_filename = sys.argv[2]
+
+if ( not pkg_dir or not pkg_filename ):
+	sys.stderr.write("Usage: opkg-update-index <package_directory> <pkgfilename>\n")
+	sys.exit(1)
+
+packages = opkg.Packages()
+
+packages.read_packages_file(pkg_dir + '/Packages')
+
+names = packages.packages.keys()
+
+packages.add_package(opkg.Package(pkg_filename))
+
+packages.write_packages_file(pkg_dir + '/Packages.new')
+os.rename(pkg_dir + '/Packages.new', pkg_dir + '/Packages')


Property changes on: trunk/src/host/opkg-utils/opkg-update-index
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/opkg-utils/opkg.py
===================================================================
--- trunk/src/host/opkg-utils/opkg.py	                        (rev 0)
+++ trunk/src/host/opkg-utils/opkg.py	2008-07-18 11:29:53 UTC (rev 4534)
@@ -0,0 +1,487 @@
+#!/usr/bin/env python
+#   Copyright (C) 2001 Alexander S. Guy <a7r at andern.org>
+#                      Andern Research Labs
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2, or (at your option)
+#   any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place - Suite 330,
+#   Boston, MA 02111-1307, USA.  */
+#
+#   Copyright 2001, Russell Nelson <opkg.py at russnelson.com>
+#   Added reading in of packages.
+#   Added missing package information fields.
+#   Changed render_control() to __repr__().
+#
+# Current Issues:
+#    The API doesn't validate package information fields.  It should be
+#        throwing exceptions in the right places.
+#    Executions of tar could silently fail.
+#    Executions of tar *do* fail, and loudly, because you have to specify a full filename,
+#        and tar complains if any files are missing, and the opkg spec doesn't require
+#        people to say "./control.tar.gz" or "./control" when they package files.
+#        It would be much better to require ./control or disallow ./control (either)
+#        rather than letting people pick.  Some freedoms aren't worth their cost.
+
+import tempfile
+import os
+import sys
+import glob
+import md5
+import re
+import string
+import commands
+from stat import ST_SIZE
+import arfile
+import tarfile
+
+class Version:
+    """A class for holding parsed package version information."""
+    def __init__(self, epoch, version):
+        self.epoch = epoch
+        self.version = version
+
+    def _versioncompare(self, selfversion, refversion):
+        if not selfversion: selfversion = ""
+        if not refversion: refversion = ""
+        while 1:
+            ## first look for non-numeric version component
+            selfm = re.match('([^0-9]*)(.*)', selfversion)
+            #print 'selfm', selfm.groups()
+            (selfalpha, selfversion) = selfm.groups()
+            refm = re.match('([^0-9]*)(.*)', refversion)
+            #print 'refm', refm.groups()
+            (refalpha, refversion) = refm.groups()
+            if (selfalpha > refalpha):
+                return 1
+            elif (selfalpha < refalpha):
+                return -1
+            ## now look for numeric version component
+            (selfnum, selfversion) = re.match('([0-9]*)(.*)', selfversion).groups()
+            (refnum, refversion) = re.match('([0-9]*)(.*)', refversion).groups()
+            #print 'selfnum', selfnum, selfversion
+            #print 'refnum', refnum, refversion
+            if (selfnum != ''):
+                selfnum = int(selfnum)
+            else:
+                selfnum = -1
+            if (refnum != ''):
+                refnum = int(refnum)
+            else:
+                refnum = -1
+            if (selfnum > refnum):
+                return 1
+            elif (selfnum < refnum):
+                return -1
+            if selfversion == '' and refversion == '':
+                return 0
+
+    def compare(self, ref):
+        if (self.epoch > ref.epoch):
+            return 1
+        elif (self.epoch < ref.epoch):
+            return -1
+        else:
+            self_ver_comps = re.match(r"(.+?)(-r.+)?$", self.version)
+            ref_ver_comps = re.match(r"(.+?)(-r.+)?$", ref.version)
+            #print (self_ver_comps.group(1), self_ver_comps.group(2))
+            #print (ref_ver_comps.group(1), ref_ver_comps.group(2))
+            r = self._versioncompare(self_ver_comps.group(1), ref_ver_comps.group(1))
+            if r == 0:
+                r = self._versioncompare(self_ver_comps.group(2), ref_ver_comps.group(2))
+            #print "compare: %s vs %s = %d" % (self, ref, r)
+            return r
+
+    def __str__(self):
+        return str(self.epoch) + ":" + self.version
+
+def parse_version(versionstr):
+    epoch = 0
+    # check for epoch
+    m = re.match('([0-9]*):(.*)', versionstr)
+    if m:
+        (epochstr, versionstr) = m.groups()
+        epoch = int(epochstr)
+    return Version(epoch, versionstr)
+
+class Package:
+    """A class for creating objects to manipulate (e.g. create) opkg
+       packages."""
+    def __init__(self, fn=None):
+        self.package = None
+        self.version = 'none'
+        self.parsed_version = None
+        self.architecture = None
+        self.maintainer = None
+        self.source = None
+        self.description = None
+        self.depends = None
+        self.provides = None
+        self.replaces = None
+        self.conflicts = None
+        self.recommends = None
+        self.suggests = None
+        self.section = None
+        self.filename_header = None
+        self.file_list = []
+        # md5 is lazy attribute, computed on demand
+        #self.md5 = None
+        self.size = None
+        self.installed_size = None
+        self.filename = None
+        self.isdeb = 0
+        self.homepage = None
+        self.oe = None
+        self.priority = None
+        self.fn = fn
+
+        if fn:
+            # see if it is deb format
+            f = open(fn, "rb")
+            magic = f.read(4)
+            f.seek(0, 0)
+            if (magic == "!<ar"):
+                self.isdeb = 1
+
+
+            self.filename = os.path.basename(fn)
+            assert self.isdeb == 1, "Old ipk format (non-deb) is unsupported"
+
+            ## sys.stderr.write("  extracting control.tar.gz from %s\n"% (fn,)) 
+
+            ar = arfile.ArFile(f)
+            tarStream = ar.open("control.tar.gz")
+            tarf = tarfile.open("control.tar.gz", "r", tarStream)
+
+            try:
+                control = tarf.extractfile("control")
+            except KeyError:
+                control = tarf.extractfile("./control")
+            self.read_control(control)
+            control.close()
+
+        self.scratch_dir = None
+        self.file_dir = None
+        self.meta_dir = None
+
+    def __getattr__(self, name):
+        if name == "md5":
+            self._computeFileMD5()
+            return self.md5
+        else:
+            raise AttributeError, name
+
+    def _computeFileMD5(self):
+        # compute the MD5.
+        f = open(self.fn, "rb")
+        sum = md5.new()
+        while 1:
+            data = f.read(1024)
+            if not data: break
+            sum.update(data)
+        f.close()
+        self.md5 = sum.hexdigest()
+
+    def read_control(self, control):
+        import os
+
+        line = control.readline()
+        while 1:
+            if not line: break
+            line = string.rstrip(line)
+            lineparts = re.match(r'([\w-]*?):\s*(.*)', line)
+            if lineparts:
+                name = string.lower(lineparts.group(1))
+                value = lineparts.group(2)
+                while 1:
+                    line = control.readline()
+                    if not line: break
+                    if line[0] != ' ': break
+                    value = value + '\n' + line
+                if name == 'size':
+                    self.size = int(value)
+                elif name == 'md5sum':
+                    self.md5 = value
+                elif self.__dict__.has_key(name):
+                    self.__dict__[name] = value
+                else:
+                    print "Lost field %s, %s" % (name,value)
+                    pass
+
+                if line and line[0] == '\n':
+                    return # consumes one blank line at end of package descriptoin
+            else:
+                line = control.readline()
+                pass
+        return    
+
+    def _setup_scratch_area(self):
+        self.scratch_dir = "%s/%sopkg" % (tempfile.gettempdir(),
+                                           tempfile.gettempprefix())
+        self.file_dir = "%s/files" % (self.scratch_dir)
+        self.meta_dir = "%s/meta" % (self.scratch_dir)
+
+        os.mkdir(self.scratch_dir)
+        os.mkdir(self.file_dir)
+        os.mkdir(self.meta_dir)
+
+    def set_package(self, package):
+        self.package = package
+
+    def get_package(self):
+        return self.package
+
+    def set_version(self, version):
+        self.version = version
+        self.parsed_version = parse_version(version)
+
+    def get_version(self):
+        return self.version
+
+    def set_architecture(self, architecture):
+        self.architecture = architecture
+
+    def get_architecture(self):
+        return self.architecture
+
+    def set_maintainer(self, maintainer):
+        self.maintainer = maintainer
+
+    def get_maintainer(self):
+        return self.maintainer
+
+    def set_source(self, source):
+        self.source = source
+
+    def get_source(self):
+        return self.source
+
+    def set_description(self, description):
+        self.description = description
+
+    def get_description(self):
+        return self.description
+
+    def set_depends(self, depends):
+        self.depends = depends
+
+    def get_depends(self, depends):
+        return self.depends
+
+    def set_provides(self, provides):
+        self.provides = provides
+
+    def get_provides(self, provides):
+        return self.provides
+
+    def set_replaces(self, replaces):
+        self.replaces = replaces
+
+    def get_replaces(self, replaces):
+        return self.replaces
+
+    def set_conflicts(self, conflicts):
+        self.conflicts = conflicts
+
+    def get_conflicts(self, conflicts):
+        return self.conflicts
+
+    def set_suggests(self, suggests):
+        self.suggests = suggests
+
+    def get_suggests(self, suggests):
+        return self.suggests
+
+    def set_section(self, section):
+        self.section = section
+
+    def get_section(self, section):
+        return self.section
+
+    def get_file_list(self):
+        if not self.fn:
+            return []
+        f = open(self.fn, "rb")
+        ar = arfile.ArFile(f)
+        tarStream = ar.open("data.tar.gz")
+        tarf = tarfile.open("data.tar.gz", "r", tarStream)
+        self.file_list = tarf.getnames()
+        self.file_list = map(lambda a: ["./", ""][a.startswith("./")] + a, self.file_list)
+
+        f.close()
+        return self.file_list
+
+    def write_package(self, dirname):
+        buf = self.render_control()
+        file = open("%s/control" % self.meta_dir, 'w')
+        file.write(buf)
+
+        self._setup_scratch_area()
+        cmd = "cd %s ; tar cvfz %s/control.tar.gz control" % (self.meta_dir,
+                                                              self.scratch_dir)
+
+        cmd_out, cmd_in, cmd_err = os.popen3(cmd)
+        
+        while cmd_err.readline() != "":
+            pass
+
+        cmd_out.close()
+        cmd_in.close()
+        cmd_err.close()
+
+        bits = "control.tar.gz"
+
+        if self.file_list:
+                cmd = "cd %s ; tar cvfz %s/data.tar.gz" % (self.file_dir,
+                                                              self.scratch_dir)
+
+                cmd_out, cmd_in, cmd_err = os.popen3(cmd)
+
+                while cmd_err.readline() != "":
+                    pass
+
+                cmd_out.close()
+                cmd_in.close()
+                cmd_err.close()
+
+                bits = bits + " data.tar.gz"
+
+        file = "%s_%s_%s.ipk" % (self.package, self.version, self.architecture)
+        cmd = "cd %s ; tar cvfz %s/%s %s" % (self.scratch_dir,
+                                             dirname,
+                                             file,
+                                             bits)
+
+        cmd_out, cmd_in, cmd_err = os.popen3(cmd)
+
+        while cmd_err.readline() != "":
+            pass
+
+        cmd_out.close()
+        cmd_in.close()
+        cmd_err.close()
+
+    def compare_version(self, ref):
+        """Compare package versions of self and ref"""
+        if not self.version:
+            print 'No version for package %s' % self.package
+        if not ref.version:
+            print 'No version for package %s' % ref.package
+        if not self.parsed_version:
+            self.parsed_version = parse_version(self.version)
+        if not ref.parsed_version:
+            ref.parsed_version = parse_version(ref.version)
+        return self.parsed_version.compare(ref.parsed_version)
+
+    def __repr__(self):
+        out = ""
+
+        # XXX - Some checks need to be made, and some exceptions
+        #       need to be thrown. -- a7r
+
+        if self.package: out = out + "Package: %s\n" % (self.package)
+        if self.version: out = out + "Version: %s\n" % (self.version)
+        if self.depends: out = out + "Depends: %s\n" % (self.depends)
+        if self.provides: out = out + "Provides: %s\n" % (self.provides)
+        if self.replaces: out = out + "Replaces: %s\n" % (self.replaces)
+        if self.conflicts: out = out + "Conflicts: %s\n" % (self.conflicts)
+        if self.suggests: out = out + "Suggests: %s\n" % (self.suggests)
+        if self.recommends: out = out + "Recommends: %s\n" % (self.recommends)
+        if self.section: out = out + "Section: %s\n" % (self.section)
+        if self.architecture: out = out + "Architecture: %s\n" % (self.architecture)
+        if self.maintainer: out = out + "Maintainer: %s\n" % (self.maintainer)
+        if self.md5: out = out + "MD5Sum: %s\n" % (self.md5)
+        if self.size: out = out + "Size: %d\n" % int(self.size)
+        if self.installed_size: out = out + "InstalledSize: %d\n" % int(self.installed_size)
+        if self.filename: out = out + "Filename: %s\n" % (self.filename)
+        if self.source: out = out + "Source: %s\n" % (self.source)
+        if self.description: out = out + "Description: %s\n" % (self.description)
+        if self.oe: out = out + "OE: %s\n" % (self.oe)
+        if self.homepage: out = out + "HomePage: %s\n" % (self.homepage)
+        if self.priority: out = out + "Priority: %s\n" % (self.priority)
+        out = out + "\n"
+
+        return out
+
+    def __del__(self):
+        # XXX - Why is the `os' module being yanked out before Package objects
+        #       are being destroyed?  -- a7r
+        pass
+
+class Packages:
+    """A currently unimplemented wrapper around the opkg utility."""
+    def __init__(self):
+        self.packages = {}
+        return
+
+    def add_package(self, pkg):
+        package = pkg.package
+        arch = pkg.architecture
+        name = ("%s:%s" % (package, arch))
+        if (not self.packages.has_key(name)):
+            self.packages[name] = pkg
+        
+        if pkg.compare_version(self.packages[name]) >= 0:
+            self.packages[name] = pkg
+            return 0
+        else:
+            return 1
+
+    def read_packages_file(self, fn):
+        f = open(fn, "r")
+        while 1:
+            pkg = Package()
+            pkg.read_control(f)
+            if pkg.get_package():
+                self.add_package(pkg)
+            else:
+                break
+        f.close()    
+        return
+
+    def write_packages_file(self, fn):
+        f = open(fn, "w")
+        names = self.packages.keys()
+        names.sort()
+        for name in names:
+            f.write(self.packages[name].__repr__())
+        return    
+
+    def keys(self):
+        return self.packages.keys()
+
+    def __getitem__(self, key):
+        return self.packages[key]
+
+if __name__ == "__main__":
+
+    assert Version(0, "1.2.2-r1").compare(Version(0, "1.2.3-r0")) == -1
+    assert Version(0, "1.2.2-r0").compare(Version(0, "1.2.2+cvs20070308-r0")) == -1
+    assert Version(0, "1.2.2+cvs20070308").compare(Version(0, "1.2.2-r0")) == 1
+    assert Version(0, "1.2.2-r0").compare(Version(0, "1.2.2-r0")) == 0
+    assert Version(0, "1.2.2-r5").compare(Version(0, "1.2.2-r0")) == 1
+
+    package = Package()
+
+    package.set_package("FooBar")
+    package.set_version("0.1-fam1")
+    package.set_architecture("arm")
+    package.set_maintainer("Testing <testing at testing.testing>")
+    package.set_depends("libc")
+    package.set_description("A test of the APIs.")
+
+    print "<"
+    sys.stdout.write(package)
+    print ">"
+
+    package.write_package("/tmp")
+





More information about the commitlog mailing list