summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Wrobel <p@rdus.de>2007-09-11 05:53:25 +0000
committerGunnar Wrobel <p@rdus.de>2007-09-11 05:53:25 +0000
commit387b74f15929efbdce79a6fbf12448f90bb83766 (patch)
treec3276ef615b29a6ead43338bd7e9a8d9405a60ea
parente9543f5112a716f421d3ecf228996b0fa66d1f29 (diff)
downloadlayman-387b74f15929efbdce79a6fbf12448f90bb83766.tar.gz
layman-387b74f15929efbdce79a6fbf12448f90bb83766.tar.bz2
layman-387b74f15929efbdce79a6fbf12448f90bb83766.zip
Import layman.
-rw-r--r--.svn.ignore2
-rw-r--r--AUTHORS14
-rw-r--r--COPYING280
-rw-r--r--ChangeLog310
-rw-r--r--MANIFEST.in4
-rwxr-xr-xbin/layman37
-rw-r--r--doc/.svn.ignore3
-rw-r--r--doc/Makefile41
-rw-r--r--doc/layman.8.xml601
-rw-r--r--ebuild/layman-1.0.99.ebuild77
-rw-r--r--etc/Makefile4
-rw-r--r--etc/cache-private.xml25
-rw-r--r--etc/cache.xml531
-rw-r--r--etc/layman.cfg53
-rw-r--r--layman/.svn.ignore1
-rw-r--r--layman/__init__.py1
-rw-r--r--layman/action.py420
-rw-r--r--layman/config.py300
-rw-r--r--layman/db.py585
-rw-r--r--layman/debug.py501
-rw-r--r--layman/overlay.py247
-rw-r--r--layman/overlays/.svn.ignore1
-rw-r--r--layman/overlays/__init__.py1
-rw-r--r--layman/overlays/bzr.py66
-rw-r--r--layman/overlays/cvs.py73
-rw-r--r--layman/overlays/darcs.py64
-rw-r--r--layman/overlays/git.py63
-rw-r--r--layman/overlays/mercurial.py64
-rw-r--r--layman/overlays/overlay.py266
-rw-r--r--layman/overlays/rsync.py68
-rw-r--r--layman/overlays/svn.py65
-rw-r--r--layman/overlays/tar.py189
-rw-r--r--layman/tests/dtest.py90
-rw-r--r--layman/tests/testfiles/global-overlays.xml30
-rw-r--r--layman/tests/testfiles/layman-test.tar.bz2bin0 -> 845 bytes
-rw-r--r--layman/tests/testfiles/make.conf345
-rw-r--r--layman/utils.py208
-rw-r--r--layman/version.py24
-rwxr-xr-xsetup.py21
39 files changed, 5675 insertions, 0 deletions
diff --git a/.svn.ignore b/.svn.ignore
new file mode 100644
index 0000000..eaea68a
--- /dev/null
+++ b/.svn.ignore
@@ -0,0 +1,2 @@
+MANIFEST
+dist
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..8d72c94
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,14 @@
+AUTHORS
+-------
+
+Written by Gunnar Wrobel (wrobel@gentoo.org)
+
+Originally created after a discussion with Stuart Herbert (stuart@gentoo.org).
+
+Contributors:
+~~~~~~~~~~~~~
+
+Stefan Schweizer (genstef@gentoo.org) - git overlay support
+Adrian Perez (moebius@connectical.net) - bzr overlay support
+Andres Loeh (kosmikus@gentoo.org) - darcs overlay support
+Samuel Tardieu (sam@rfc1149.net) - mercurial overlay support
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5a965fb
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,280 @@
+ 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
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..ec01be0
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,310 @@
+2007-01-09 Gunnar Wrobel <wrobel@pardus.de>
+
+ * layman/version.py:
+
+ Update to version 1.0.10
+
+2007-01-08 Gunnar Wrobel <wrobel@pardus.de>
+
+ * layman/db.py (DB.add, MakeConf.write):
+
+ Added support for the --priority flag.
+
+ Modified order of entries in PORTDIR_OVERLAY.
+
+ * layman/config.py (Config.__init__):
+
+ Added --priority flag.
+
+ * doc/layman.8.xml:
+
+ Added documentation for --priority switch.
+
+2007-01-05 Gunnar Wrobel <wrobel@pardus.de>
+
+ * layman/db.py:
+
+ Fixed doc tests.
+
+ * layman/config.py:
+
+ Fixed doc tests.
+
+ * layman/action.py:
+
+ Fixed doc tests.
+
+ * layman/overlays/tar.py:
+
+ Fixed doc tests.
+
+2006-12-30 Gunnar Wrobel <wrobel@pardus.de>
+
+ * layman/config.py (Config.__init__):
+
+ Fixed quietness option.
+
+ * layman/overlays/tar.py (TarOverlay.__init__):
+
+ Fixed default values.
+
+ * layman/overlays/cvs.py (CvsOverlay.__init__):
+
+ Fixed default values.
+
+ * layman/action.py:
+
+ Add support for --quiet/--quietness
+
+ * layman/overlay.py (Overlays.__init__):
+
+ Add support for --quiet/--quietness
+
+ * layman/overlays/overlay.py (Overlay.__init__, Overlay.cmd):
+
+ Add support for --quiet/--quietness
+
+ * layman/db.py (DB.__init__):
+
+ Add support for --quiet/--quietness
+
+ * layman/version.py:
+
+ This will be version 1.0.9
+
+ * doc/layman.8.xml:
+
+ Added documentation for --quiet/--quietness
+
+2006-12-29 Gunnar Wrobel <wrobel@pardus.de>
+
+ * layman/config.py (Config):
+
+ Added quietness and modified OUT.info / OUT.warn calls
+ accordingly (bug #151965)
+
+ * layman/db.py (DB.sync, DB.add):
+
+ Catching error when syncing fails (bugs #148698 and #159051).
+
+ * ebuild/layman-1.0.8.ebuild:
+
+ Fixed postinstall instructions for layman (bug #149867)
+
+ Added subversion "nowebdav" check by cardoe into repository.
+
+2006-09-23 <post@gunnarwrobel.de>
+
+ * layman/version.py: Update to 1.0.8
+
+2006-09-22 <post@gunnarwrobel.de>
+
+ * layman/overlays/cvs.py (CvsOverlay.sync): CVS support
+
+2006-09-05 <post@gunnarwrobel.de>
+
+ * layman/*: Generic pylint and cleanup fixes
+
+ * layman/config.py (Config.__init__): Modified to allow switching
+ strict checking off.
+
+2006-08-08 <post@gunnarwrobel.de>
+
+ * layman/overlays/tar.py (TarOverlay.add): Support for explicit
+ file format of a tar package.
+
+2006-08-01 <post@gunnarwrobel.de>
+
+ * layman/action.py (Sync.run): Print successes and warning at the
+ end of the run.
+ (List.run): List only official overlays when not running verbose.
+
+ * layman/db.py (MakeConf.write.prio_sort): Sort overlays by
+ priority when writing make.conf
+
+ * layman/overlay.py (Overlays.list): Support for marking overlays
+ as official.
+ (Overlays.read): Only warn on invalid overlay definitions and do
+ not add them.
+
+ * layman/overlays/bzr.py: Allow whitespace.
+
+ * layman/overlays/darcs.py: Allow whitespace.
+
+ * layman/overlays/git.py: Allow whitespace.
+
+ * layman/overlays/mercurial.py: Allow whitespace.
+
+ * layman/overlays/rsync.py: Allow whitespace.
+
+ * layman/overlays/svn.py: Allow whitespace.
+
+ * layman/overlays/tar.py: Allow whitespace.
+
+ * layman/overlays/overlay.py (Overlay.__init__): Required contact,
+ description. Added support for status and priority.
+ (Overlay.__str__): Modified display according to changes given
+ above.
+ (Overlay.is_official): Added new function for official overlays.
+
+ * layman/overlay.py: Added mercurial support thanks to
+ Andres Loeh <kosmikus@gentoo.org>
+
+ * layman/overlays/mercurial.py: Added mercurial support thanks to
+ Andres Loeh <kosmikus@gentoo.org>
+
+2006-07-25 <post@gunnarwrobel.de>
+
+ * layman/config.py (Config.__init__): Fixed error introduced in
+ changeset 204. Config file gets read again.
+
+2006-07-18 <post@gunnarwrobel.de>
+
+ * layman/version.py: version bump to 1.0.5
+
+ * layman/config.py (Config.__getitem__): Fixed handling of overlays
+ specified on the command line.
+
+ * layman/db.py (RemoteDB.cache): Fixed handling of downloaded
+ overlay list.
+
+ * layman/overlay.py: Added darcs module.
+
+2006-07-17 <post@gunnarwrobel.de>
+
+ * layman/config.py (Config.__init__): Fixed some config defaults.
+
+ * layman/action.py (Actions.__init__): Reduced actions for which
+ the remote lists will be implicitely fetched.
+
+ * doc/layman.8.xml: Updated documentation for implicit fetch.
+
+ * layman/action.py (Actions.__init__): Run fetch implicitely
+ only on specific actions.
+
+ * layman/db.py (RemoteDB.cache): Modified download code for
+ improved handling of fetch problems.
+
+ * layman/action.py (Sync.__init__): Added --sync-all support.
+
+ * doc/layman.8.xml: Added --sync-all documentation.
+
+ * layman/db.py (RemoteDB.__init__): Added proxy support.
+
+ * etc/layman.cfg (make_conf): Added local file syntax example.
+ (overlays): Added proxy variable.
+
+ * doc/layman.8.xml: Added documentation about local overlay
+ definitions.
+ Added proxy documentation.
+
+2006-06-28 <post@gunnarwrobel.de>
+
+ * layman/version.py: Version bump to 1.0.4
+
+ * layman/action.py (Sync.run): Fixed src check.
+
+2006-06-27 <post@gunnarwrobel.de>
+
+ * layman/action.py (ListLocal.run): Fixed code for listing.
+
+ * doc/layman.8.xml: Fixed documentation for new nofetch option.
+
+ * layman/action.py (Actions.__init__): Made fetching the default
+ if nofetch is NOT set.
+ (Sync.run): Added source path comparison for overlay location changes.
+ (List.run): Modified output to differentiate between supported and
+ unsupported overlays.
+
+ * layman/config.py (Config.__init__): Added nofetch option.
+
+ * layman/overlay.py: Added bzr support. Thanks to Adrian Perez.
+
+ * layman/overlays/bzr.py: Added bzr support. Thanks to Adrian Perez.
+
+ * layman/overlays/overlay.py (Overlay.short_list): Fixed length
+ of short listing.
+ (Overlay.supported): Fixed check for supported overlay types.
+
+2006-06-05 <post@gunnarwrobel.de>
+
+ * layman/overlays/overlay.py (Overlay): Forgot to add a check
+ if the overlay type is actually supported. -> 1.0.2
+
+ * layman/overlay.py: genstef@gentoo.org provided support for
+ git based overlays. -> released 1.0.1
+
+2006-05-27 <post@gunnarwrobel.de>
+
+ * doc/layman.8.xml: Updated docs to multi list support
+
+ * layman/version.py: Version bump to 1.0.0
+
+ * etc/layman.cfg (overlays): Adapted configuration for change
+ in global list url and multiple list support.
+
+ * layman/config.py (Config.__init__): Fixed link for global
+ overlay list.
+
+ * layman/db.py: Added support for multiple overlay lists.
+
+ * layman/overlay.py: Added support for mutliple overlay lists.
+
+2006-05-01 <post@gunnarwrobel.de>
+
+ * layman/version.py: Version bump to 0.9.2
+
+ * layman/tests/dtest.py (test_suite): Added utils.py test
+
+ * layman/overlays/tar.py (TarOverlay): Fixed testing results.
+
+2006-04-14 <post@gunnarwrobel.de>
+
+ * layman/version.py: Version 0.9.1
+
+ * layman/overlays/tar.py (TarOverlay.__init__): Added
+ category support to packaged overlays. Could/Should
+ also allow this for other overlay types.
+
+2006-03-12 <post@gunnarwrobel.de>
+
+ * layman/db.py (RemoteDB.cache): Create storage
+ dir if it is missing.
+ (MakeConf.write): Add $PORTDIR_OVERLAY to include
+ manual PORTDIR_OVERLAY variable.
+ (MakeConf.read): Disregard PORTDIR_OVERLAY variable
+ as overlay name.
+
+ * layman/action.py (Fetch.run): Added error handling
+ for fetch problems.
+
+ * doc/layman.8.xml: Fixes to the man page.
+
+ * layman/version.py: Version bump to 0.9
+
+ * layman/action.py (Add.run): Added warning if
+ overlay is unkown.
+
+ * etc/cache.xml: Added kolab2 and xgloverlays.
+
+ * layman/overlays/overlay.py (Overlay.short_list): Added
+ shortened overlay listing
+
+ * layman/overlay.py: Added tar support.
+
+ * layman/overlays/tar.py: Added tar support.
+
+2006-02-04 <post@gunnarwrobel.de>
+
+ * etc/cache-private.xml: Added private overlay locations.
+
+ * layman/db.py (MakeConf.read): Allowed for a missing
+ make.conf. This now allows to source an external file
+ into the original make.conf
+
+ * etc/layman.cfg (cache): Fixed location of cache and
+ overlay list
+
+ * layman/config.py (Config.__init__): Fixed description of
+ layman usage.
+
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..5829965
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,4 @@
+include etc/layman.cfg
+include doc/layman.8
+include doc/layman.8.html
+recursive-include layman/tests *
diff --git a/bin/layman b/bin/layman
new file mode 100755
index 0000000..3080c05
--- /dev/null
+++ b/bin/layman
@@ -0,0 +1,37 @@
+#!python
+################################################################################
+# LAYMAN - A UTILITY TO SELECT AND UPDATE GENTOO OVERLAYS
+################################################################################
+# Distributed under the terms of the GNU General Public License v2
+#
+# Copyright:
+# (c) 2005 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+
+__version__ = "$Id$"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+from layman.config import Config
+from layman.action import Actions
+
+#===============================================================================
+#
+# MAIN
+#
+#-------------------------------------------------------------------------------
+
+def main():
+
+ Actions(Config())
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/.svn.ignore b/doc/.svn.ignore
new file mode 100644
index 0000000..ff0e9f9
--- /dev/null
+++ b/doc/.svn.ignore
@@ -0,0 +1,3 @@
+*.html
+*.8
+semantic.cache
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..64b28af
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,41 @@
+#
+# layman/doc/Makefile
+# Simple Makefile to rebuild the documentation from the
+# docbook XML sources
+#
+# Copyright (c) 1999-2005 Gentoo Foundation
+# Released under v2 of the GNU GPL
+#
+# Author(s) Stuart Herbert <stuart@gentoo.org>
+# Renat Lumpau <rl03@gentoo.org>
+# Gunnar Wrobel <php@gunnarwrobel.de>
+#
+# ========================================================================
+
+MAN_PAGES = layman.8
+HTML_PAGES = layman.8.html
+
+TMPFILE=./layman.man
+
+all: man html
+
+html: $(HTML_PAGES)
+
+man: $(MAN_PAGES)
+
+clean:
+ rm -f $(MAN_PAGES)
+ rm -f $(HTML_PAGES)
+
+%.html: %.xml
+ @echo HTML $@
+ @xmlto html-nochunks $<
+
+%: %.xml
+ @echo MAN $@
+ @xmlto man $<
+#
+# fix up the blank lines that docbook leaves behind
+#
+ @cat $@ | sed -e 's/$$/.fred/g;' | tr -d '\n' | sed -e 's/.fred.fred\./.fred./g;' | sed -e 's/.fred/\n/g;' > $(TMPFILE)
+ @mv $(TMPFILE) $@
diff --git a/doc/layman.8.xml b/doc/layman.8.xml
new file mode 100644
index 0000000..c966786
--- /dev/null
+++ b/doc/layman.8.xml
@@ -0,0 +1,601 @@
+<?xml version='1.0'?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<article>
+
+ <articleinfo>
+ <title>layman</title>
+
+ <authorgroup>
+ <author>
+ <firstname>Gunnar</firstname>
+ <surname>Wrobel</surname>
+ <affiliation>
+ <address>
+ <email>wrobel@gentoo.org</email>
+ <otheraddr>
+ <ulink url="http://gunnarwrobel.de" />
+ </otheraddr>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <copyright>
+ <year>2006</year>
+ <holder>Gunnar Wrobel</holder>
+ </copyright>
+ </articleinfo>
+
+ <section>
+ <title>Reference</title>
+
+ <refentry>
+ <refentryinfo>
+ <title>layman</title>
+ <date>February 2006</date>
+ <productname>Gentoo Linux</productname>
+ </refentryinfo>
+ <refmeta>
+ <refentrytitle>layman</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>layman</refname>
+ <refpurpose>
+ manage your local repository of gentoo overlays
+ </refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-a</arg>
+ <arg>--add</arg>
+ </group>
+ <group choice="plain">
+ <arg>ALL</arg>
+ <arg><replaceable>overlay</replaceable></arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-d</arg>
+ <arg>--delete</arg>
+ </group>
+ <group choice="plain">
+ <arg>ALL</arg>
+ <arg><replaceable>overlay</replaceable></arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-s</arg>
+ <arg>--sync</arg>
+ </group>
+ <group choice="plain">
+ <arg>ALL</arg>
+ <arg><replaceable>overlay</replaceable></arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-S</arg>
+ <arg>--sync-all</arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-L</arg>
+ <arg>--list</arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-l</arg>
+ <arg>--list-local</arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-f</arg>
+ <arg>--fetch</arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-n</arg>
+ <arg>--nofetch</arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-k</arg>
+ <arg>--nocheck</arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-q</arg>
+ <arg>--quiet</arg>
+ </group>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>layman</command>
+ <group choice="plain">
+ <arg>-Q</arg>
+ <arg>--quietness</arg>
+ <group choice="plain">
+ <arg><replaceable>0-4</replaceable></arg>
+ </group>
+ </group>
+ </cmdsynopsis>
+
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>layman</command> is a script that allows you to
+ add, remove and update gentoo overlays from a variety of
+ sources.</para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>WARNING</title>
+
+ <para><command>layman</command> makes it easy to retrieve and
+ update overlays for gentoo. In addition it makes it TRIVIAL
+ to break your system.
+ </para>
+
+ <para>The main portage tree provides you with high quality ebuilds
+ that are all maintained by gentoo developers. This will not
+ be the case for most of the overlays you can get by using
+ <command>layman</command>. Thus you are removing the
+ security shield that the standard tree provides for
+ you. You should keep that in mind when installing ebuilds
+ from an overlay.
+ </para>
+
+ <para>To ensure the security of your system you MUST read the
+ source of the ebuild you are about to install.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+
+ <title>Handling overlays</title>
+
+ <para><command>layman</command> intends to provide easy
+ maintenance of gentoo overlays while not requiring any
+ configuration.
+ </para>
+
+ <refsect2>
+
+ <title>Remote overlay lists</title>
+
+ <para><command>layman</command> allows you to fetch an overlay
+ without the need to modify any configuration files. In
+ order for this to be possible the script needs an external
+ list of possible overlay sources. There will be a
+ centralized list available <ulink
+ url="http://www.gentoo.org/proj/en/overlays/layman-global.txt">here</ulink>,
+ but nothing will prevent you from using or publishing your
+ own list of overlays. The location of the remote lists can
+ also be modified using the <option>--overlays</option> option
+ when running <command>layman</command>.
+ </para>
+
+ <para>To get a new overlay added to the central list provided
+ for layman, send a mail to
+ <email>overlays@gentoo.org</email>. Gentoo developers may
+ add their overlay entries directly into the list which can
+ be accessed over the CVS repository for the Gentoo
+ website.
+ </para>
+
+ <para>You can also use several lists at the same time. Just
+ add one url per line to the overlays variable in your
+ configuration file. <command>layman</command> will merge the
+ contents of all lists.
+ </para>
+
+ <para><command>layman</command> also allows you to define
+ local files in this list. Just make sure you prepend these
+ pathnames in standard URL notation
+ with <filename>file://</filename>.
+ </para>
+
+ <para>If you need to use a proxy for access to the internet,
+ you can use the corresponding variable in
+ the <command>layman</command> configuration file. Layman
+ will also respect the <command>http_proxy</command>
+ environment variable in case you set it.
+ </para>
+
+ </refsect2>
+
+ <refsect2>
+
+ <title>Local cache</title>
+
+ <para><command>layman</command> stores a local copy of the
+ fetched remote list. It will be stored in
+ <filename>/usr/portage/local/layman/cache.xml</filename>
+ by default. There exists only one such cache file and it
+ will be overwritten every time you
+ run <command>layman</command>.
+ </para>
+
+ </refsect2>
+
+ <refsect2>
+
+ <title>Handling <filename>/etc/make.conf</filename></title>
+
+ <para>Since <command>layman</command> is designed to
+ automatically handle the inclusion of overlays into your
+ system it needs to be able to modify
+ the <command>PORTDIR_OVERLAY</command> variable in your
+ <filename>/etc/make.conf</filename> file. But
+ <filename>/etc/make.conf</filename> is a very central and
+ essential configuration file for a gentoo
+ system. Automatically modifying this file would be
+ somewhat dangerous. You can
+ allow <command>layman</command> to do this by setting
+ the <command>make_conf</command> variable in the
+ configuration file to <filename>/etc/make.conf</filename>.
+ </para>
+
+ <para>A much safer and in fact recommended solution to the
+ problem is to let <command>layman</command> handle an
+ external file that only contains
+ the <command>PORTDIR_OVERLAY</command> variable and is
+ sourced within the
+ standard <filename>/etc/make.conf</filename> file. Just add the following line to the end of your
+ <filename>/etc/make.conf</filename> file:
+ </para>
+
+ <para>source /usr/portage/local/layman/make.conf</para>
+
+ <para><filename>/usr/portage/local/layman/make.conf</filename>
+ is the default provided in the layman
+ configuration. Change this filename in case you decide to
+ store it somewhere else.
+ </para>
+
+ <para>The file does not necessarily need to exist at the
+ beginning. If it is missing, layman will create it for you.
+ </para>
+
+ <para>There is also no need to remove the
+ original <command>PORTDIR_OVERLAY</command> variable from
+ the make.conf file. Layman will simply add new overlays to
+ this variable and all your old entries will remain in there.
+ </para>
+
+ </refsect2>
+
+ <refsect2>
+
+ <title>Adding, removing and updating overlays</title>
+
+ <para>Once a remote list of overlays has been fetched,
+ <command>layman</command> allows to add overlays from the
+ remote list to your system. The script will try to fetch
+ the overlay. If this is successful the overlay information
+ will be copied from the cache to the list of locally
+ installed overlays. In addition
+ <command>layman</command> will modify the
+ <command>PORTDIR_OVERLAY</command> variable to include the
+ new overlay path.
+ </para>
+
+ <para>Removing the overlay with <command>layman</command> will
+ delete the overlay without leaving any traces behind.
+ </para>
+
+ <para>In order to update all overlays managed by
+ <command>layman</command> you can run the script with the
+ <option>--sync ALL</option> option or
+ the <option>--sync-all</option> flag.
+ </para>
+
+ </refsect2>
+
+ <refsect2>
+
+ <title>List overlays</title>
+
+ <para><command>layman</command> provides the
+ <option>--list</option> and <option>--list-local</option>
+ options to print a list of available respectively
+ installed overlays.
+ </para>
+
+ <para> Listing will prepend all fully supported overlays
+ with a green asterisk, all non-official overlays with a
+ yellow asterisk and all overlays that you will not be able
+ to use since you do not have the necessary tools installed
+ with a red asterisk.
+ </para>
+
+ <para> In the default mode layman will be strict about
+ listing overlays and only present you with overlays that
+ are fully supported. In addition it will complain about
+ overlays that are missing a description field or a contact
+ attribute. This type of behaviour has been added with
+ layman-1.0.7 and if you'd like to return to the old
+ behaviour you may use the k option flag or set the nocheck
+ option in the configuration file.
+ </para>
+
+ </refsect2>
+
+ <refsect2>
+
+ <title>Overlay types</title>
+
+ <para>Currently <command>layman</command> supports overlays that
+ are exported via <command>rsync</command>,
+ <command>subversion</command>, <command>bzr</command>,
+ <command>darcs</command>, <command>git</command>,
+ <command>mercurial</command> or provided
+ as <command>tar</command> packages.
+ </para>
+
+ </refsect2>
+
+ </refsect1>
+
+ <refsect1>
+
+ <title>Actions</title>
+
+ <para>List of possible <command>layman</command> actions.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-f</option></term>
+ <term><option>--fetch</option></term>
+ <listitem>
+ <para>Fetches the remote list of overlays. You will
+ usually NOT need to explicitely specify this option. The
+ fetch operation will be performed automatically once you
+ run the sync, sync-all, or list action. You can prevent
+ this automatic fetching using the --nofetch option.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-a</option> <replaceable>overlay</replaceable></term>
+ <term><option>--add</option> <replaceable>overlay</replaceable></term>
+ <listitem>
+ <para>Add the given overlay from the cached remote list to
+ your locally installed overlays. Specify "ALL" to add
+ all overlays from the remote list.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d</option> <replaceable>overlay</replaceable></term>
+ <term><option>--delete</option> <replaceable>overlay</replaceable></term>
+ <listitem>
+ <para>Remove the given overlay from your locally installed
+ overlays. Specify "ALL" to remove all overlays</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-s</option> <replaceable>overlay</replaceable></term>
+ <term><option>--sync</option> <replaceable>overlay</replaceable></term>
+ <listitem>
+ <para>Update the specified overlay. Use "ALL" as
+ parameter to synchronize all overlays</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-S</option></term>
+ <term><option>--sync-all</option></term>
+ <listitem>
+ <para>Update all overlays. Shortcut for -s ALL.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-L</option></term>
+ <term><option>--list</option></term>
+ <listitem>
+ <para>List the contents of the remote list.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-l</option></term>
+ <term><option>--list-local</option></term>
+ <listitem>
+ <para>List the locally installed overlays.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+
+ <title>Options</title>
+
+ <para>List of available <command>layman</command> options.</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><option>-c</option> <replaceable>path</replaceable></term>
+ <term><option>--config</option> <replaceable>path</replaceable></term>
+ <listitem>
+ <para>Path to an alternative configuration file.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-o</option> <replaceable>url</replaceable></term>
+ <term><option>--overlays</option> <replaceable>url</replaceable></term>
+ <listitem>
+ <para>Specifies the location of additional overlay
+ lists. You can use this flag several times and the
+ specified urls will get appended to the list of urls you
+ specified in your config file. You may also specify
+ local file urls by prepending the path with
+ file://</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-n</option></term>
+ <term><option>--nofetch</option></term>
+ <listitem>
+ <para>Prevents <command>layman</command> from
+ automatically fetching the remote lists of overlays. The
+ default behaviour for <command>layman</command> is to
+ update all remote lists if you run the sync, list or
+ fetch operation.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-k</option></term>
+ <term><option>--nocheck</option></term>
+ <listitem>
+ <para>Prevents <command>layman</command> from checking
+ the remote lists of overlays for complete overlay
+ definitions. The default behaviour for layman is to
+ reject overlays that do not provide a description or a
+ contact attribute.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-q</option></term>
+ <term><option>--quiet</option></term>
+ <listitem>
+ <para>Makes <command>layman</command> completely quiet.
+ This option is dangerous: If the processes spawned by
+ layman when adding or synchronizing overlays require
+ any input layman will hang without telling you
+ why. This might happen for example if your overlay
+ resides in subversion and the SSL certificate of
+ the server needs acceptance.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-Q</option><replaceable>LEVEL</replaceable></term>
+ <term><option>--quietness</option><replaceable>LEVEL</replaceable></term>
+ <listitem>
+ <para>Makes <command>layman</command> less verbose.
+ Choose a value between 0 and 4 with 0 being completely
+ quiet. Once you set this below 3, the same warning as
+ given for --quiet applies.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-p</option><replaceable>LEVEL</replaceable></term>
+ <term><option>--priority</option><replaceable>LEVEL</replaceable></term>
+ <listitem>
+ <para>Use this option in combination with
+ the <command>--add</command>. It will modify the
+ priority of the added overlay and thus influence the
+ order of entries in the make.conf file. The lower the
+ priority, the earlier in the list the entry will be
+ mentioned. Use a value between 0 and 100. The default
+ value is 50.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+
+ <title>Examples</title>
+
+ <refsect2>
+
+ <title>Installing an overlay</title>
+
+ <para><userinput>layman -f -a wrobel</userinput></para>
+ <para>This would add the overlay with the id
+ <command>wrobel</command> to your list of installed
+ overlays.</para>
+
+ </refsect2>
+
+ <refsect2>
+
+ <title>Syncing your overlays</title>
+
+ <para><userinput>layman -s ALL</userinput></para>
+ <para>This updates all overlays</para>
+
+ </refsect2>
+
+ <refsect2>
+
+ <title>Performing several actions at the same time</title>
+
+ <para><userinput>layman -f -a wrobel -a webapps-experimental</userinput></para>
+ <para>This fetches the remote list and immediately adds two
+ overlays</para>
+
+ </refsect2>
+
+ </refsect1>
+
+ <refsect1>
+
+ <title>Files</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><filename>/etc/layman/layman.cfg</filename></term>
+ <listitem>
+ <para>Configuration file, holding the defaults for
+ <command>layman</command></para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ </refentry>
+ </section>
+</article>
diff --git a/ebuild/layman-1.0.99.ebuild b/ebuild/layman-1.0.99.ebuild
new file mode 100644
index 0000000..f246993
--- /dev/null
+++ b/ebuild/layman-1.0.99.ebuild
@@ -0,0 +1,77 @@
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/app-portage/layman/layman-1.0.10.ebuild,v 1.1 2007/01/09 18:01:15 wrobel Exp $
+
+inherit eutils distutils
+
+DESCRIPTION="A python script for retrieving gentoo overlays."
+HOMEPAGE="http://projects.gunnarwrobel.de/scripts"
+SRC_URI="http://build.pardus.de/downloads/${PF}.tar.gz"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~ppc ~ppc64 ~sparc ~x86 ~x86-fbsd"
+IUSE=""
+S=${WORKDIR}/${PF}
+
+DEPEND=""
+RDEPEND=""
+
+pkg_setup() {
+ if has_version dev-util/subversion && built_with_use dev-util/subversion nowebdav; then
+ eerror "You must rebuild your subversion without the nowebdav USE flag"
+ die "You must rebuild your subversion without the nowebdav USE flag"
+ fi
+}
+
+src_install() {
+
+ distutils_src_install
+
+ dodir /etc/layman
+ cp etc/* ${D}/etc/layman/
+
+ doman doc/layman.8
+ dohtml doc/layman.8.html
+
+}
+
+src_test() {
+ cd ${S}
+ einfo "Running layman doctests..."
+ echo
+ if ! PYTHONPATH="." ${python} layman/tests/dtest.py; then
+ eerror "DocTests failed - please submit a bug report"
+ die "DocTesting failed!"
+ fi
+}
+
+pkg_postinst() {
+ einfo "You are now ready to add overlays into your system."
+ einfo
+ einfo "layman -L"
+ einfo
+ einfo "will display a list of available overlays."
+ einfo
+ ewarn "Use the -k switch to also list overlays that are"
+ ewarn "considered less secure."
+ einfo
+ elog "Select an overlay and add it using"
+ einfo
+ elog "layman -a overlay-name"
+ einfo
+ elog "If this is the very first overlay you add with layman,"
+ elog "you need to append the following statement to your"
+ elog "/etc/make.conf file:"
+ elog
+ elog "source /usr/portage/local/layman/make.conf"
+ elog
+ elog "If you modify the 'storage' parameter in the layman"
+ elog "configuration file (/etc/layman/layman.cfg) you will"
+ elog "need to adapt the path given above to the new storage"
+ elog "directory."
+ einfo
+ ewarn "Please add the 'source' statement to make.conf only AFTER "
+ ewarn "you added your first overlay. Otherwise portage will fail."
+ epause 5
+}
diff --git a/etc/Makefile b/etc/Makefile
new file mode 100644
index 0000000..4a8c01a
--- /dev/null
+++ b/etc/Makefile
@@ -0,0 +1,4 @@
+list:
+ scp cache-private.xml root@build.pardus.de:/var/www/localhost/htdocs/downloads/private-overlays.xml
+
+.PHONY: list
diff --git a/etc/cache-private.xml b/etc/cache-private.xml
new file mode 100644
index 0000000..d1bf56a
--- /dev/null
+++ b/etc/cache-private.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<layman>
+
+ <overlay
+ type = "svn"
+ src = "http://overlays.gentoo.org/svn/dev/wrobel/stable"
+ name = "wrobel-stable"/>
+ <overlay
+ type = "svn"
+ src = "http://overlays.gentoo.org/svn/dev/wrobel/testing"
+ name = "wrobel-testing"/>
+ <overlay
+ type = "svn"
+ src = "http://overlays.gentoo.org/svn/dev/wrobel/broken"
+ name = "wrobel-broken"/>
+ <overlay
+ type = "svn"
+ src = "https://www.gunnarwrobel.de/svn/kolab/ebuilds"
+ name = "kolab2"/>
+ <overlay
+ type = "svn"
+ src = "https://www.gunnarwrobel.de/svn/kolab-pardus/ebuilds"
+ name = "kolab-pardus"/>
+
+</layman>
diff --git a/etc/cache.xml b/etc/cache.xml
new file mode 100644
index 0000000..2f4759d
--- /dev/null
+++ b/etc/cache.xml
@@ -0,0 +1,531 @@
+<?xml version="1.0" ?>
+<layman>
+
+ <overlay
+ type = "svn"
+ src = "https://gentopia.gentooexperimental.org/svn/overlay/"
+ name = "gentopia">
+
+ <link>
+ http://gentopia.gentooexperimental.org/
+ </link>
+
+ <description>
+ Purpose
+
+ To provide a smooth, seamlessly functional and enjoyable Gentoo
+ Desktop experience by following the mantra of "Just Works".
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "tar"
+ src = "http://svn.gnqs.org/downloads/gentoo-php-overlay.tar.gz"
+ name = "php">
+
+ <link>
+ http://svn.gnqs.org/projects/gentoo-php-overlay/
+ </link>
+
+ <description>
+ The Gentoo PHP Overlay is our testbed for new and improved PHP
+ packages for Gentoo21. It's a place where Gentoo developers and
+ users alike can work together on providing Gentoo Linux with the
+ very best PHP support that there is, for any platform.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "https://gentooscience.org/svn/overlay"
+ name = "science">
+
+ <link>
+ https://gentooscience.org/
+ </link>
+
+ <description>
+ The Gentoo Science Overlay is intended as a place to work
+ outside of the main portage tree on experimental ebuilds. Our
+ aim is to increase the rate of development of scientific
+ packages for Gentoo, but ebuilds in this repository are by their
+ very nature more experimental. If you wish to use them you
+ should be willing to help test and report bugs.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "https://nemesis.fprintf.net/svn/gnome-experimental/"
+ name = "gnome-experimental">
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://rsync.breakmygentoo.net/bmg-main"
+ name = "break-my-gentoo-main">
+
+ <link>
+ http://www.breakmygentoo.net
+ </link>
+
+ <description>
+ Nevertheless the name seems to be standing for something other,
+ "Break My Gentoo" is not just a project to help you destroying your
+ fine Gentoo-installation. It could, but this is not the main purpose.
+ We want to provide unstable ebuilds, which have no chance to get into
+ portage. We want to give technology previews especially focused on
+ GNOME.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://rsync.gentoo.de/gentoo-de-ebuilds"
+ name = "gentoo-de">
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "http://redeeman.kaspersandberg.com/fluidportage/trunk"
+ name = "fluidportage">
+
+ <description>
+ Contains A LOT of *-cvs packages for many things, read the
+ readme file for more information.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "http://catmur.co.uk/svn/repos/gentoo/tree"
+ name = "ecatmur">
+
+ <link>
+ http://catmur.co.uk/gentoo/
+ </link>
+
+ <description>
+ ecatmurs overlay contains a variety of ebuilds: cool applications,
+ various fixes, version bumps, bleeding-edge code grabs.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://download.berlios.de/genkdesvn_ftp/stable"
+ name = "kde-stable">
+
+ <link>
+ http://genkdesvn.berlios.de/wiki/index.php/Main_Page
+ </link>
+
+ <description>
+ This wiki has been provided as a central place for information
+ regarding the kde-svn ebuilds.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://download.berlios.de/genkdesvn_ftp/playground"
+ name = "kde-experimental">
+
+ <link>
+ http://genkdesvn.berlios.de/wiki/index.php/Main_Page
+ </link>
+
+ <description>
+ This wiki has been provided as a central place for information
+ regarding the kde-svn ebuilds.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://gentoo.zugaina.org/zugaina-portage"
+ name = "zugaina">
+
+ <link>
+ http://gentoo.zugaina.org/
+ </link>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://gentoo.xwing.info/xwing-overlay"
+ name = "xwing">
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://rsync.ebuildexchange.org/ebuildexchange"
+ name = "ebuild-exchange">
+
+ <link>
+ http://www.ebuildexchange.org/
+ </link>
+
+ <description>
+ This site tries to provide a new medium of distributing Ebuilds
+ for the Gentoo Linux Distribution.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://erazor-zone.de/portage/"
+ name = "erazor">
+
+ <link>
+ http://wiki.erazor-zone.de/wiki:projects:linux:gentoo
+ </link>
+
+ <description>
+ erazor provides some ebuilds here. At this point, most of them
+ are newer that the ones in portage, but be warned, they have not
+ been tested much and there is no warranty at all.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "https://fantoo.ru/svn"
+ name = "fantoo">
+
+ <link>
+ http://fantoo.org/
+ </link>
+
+ <description>
+ Portage Overlay tree of new gentoo based distibution called
+ Fantoo Linux. Fantoo Linux aims to be bleeding edge and bugfixes
+ in gentoo upstream.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "http://svn.gnqs.org/svn/gentoo-webapps-overlay/experimental"
+ name = "webapps-experimental">
+
+ <link>
+ http://svn.gnqs.org/projects/gentoo-webapps-overlay/
+ </link>
+
+ <description>
+ This is the home of Gentoo's wider collection of ebuilds for
+ web-based applications. This is where we collect all the ebuilds
+ submitted to Bugzilla by our users, and make them available in
+ an easy-to-use overlay for wider testing.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://gunnarwrobel.de/wrobel-stable"
+ name = "wrobel-stable">
+
+ <link>
+ http://projects.gunnarwrobel.de/ebuilds/wiki/WikiStart
+ </link>
+
+ <description>
+ A collection of stable ebuilds from Gunnar Wrobel [wrobel@gentoo.org].
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://gunnarwrobel.de/wrobel-testing"
+ name = "wrobel-experimental">
+
+ <link>
+ http://projects.gunnarwrobel.de/ebuilds/wiki/WikiStart
+ </link>
+
+ <description>
+ A collection of experimental ebuilds from Gunnar Wrobel [wrobel@gentoo.org].
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://gunnarwrobel.de/kolab2"
+ name = "kolab2">
+
+ <link>
+ http://projects.gunnarwrobel.de/kolab/wiki
+ </link>
+
+ <description>
+ Project to allow running Kolab2 on Gentoo.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "http://svn.xgl-coffee.org/xgl-coffee/trunk/"
+ name = "portage-xgl">
+
+ <link>
+ http://gentoo-wiki.com/XGL#Checkout_An_Overlay
+ </link>
+
+ <description>
+ Xgl is an Xserver that uses OpenGL for its drawing
+ operations. Together with compiz, an opengl compositing and
+ window manager, it allows for some cool desktop effects.
+
+ This is the XGL overlay from Hanno Boeck (http://www.hboeck.de)
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://svn.netdomination.org/gentoo-voip"
+ name = "voip">
+
+ <link>
+ http://svn.netdomination.org/gentoo-voip
+ </link>
+
+ <description>
+ Voice over IP related ebuilds.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://kpex.no-ip.org/kpex-media"
+ name = "kpex-media">
+
+ <link>
+ https://kpex.no-ip.org/kpex-media.html
+ </link>
+
+ <description>
+ A series of unsupported multimedia ebuilds for Gentoo
+ portage that are either updated versions, live CVS/SVN
+ packages, or have updated features not included in the
+ official portage tree.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "https://svn.initng.org/portage/gentoo"
+ name = "initng">
+
+ <link>
+ http://www.initng.org
+ </link>
+
+ <description>
+ Initng is a full replacement of the old and in many ways
+ deprecated sysvinit tool. It is designed with speed in mind
+ because it does as much as possible asynchronously. In other
+ words: It will boot your unix-system much faster, and give you
+ more control and statistics over your system.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "tar"
+ src = "http://snigel.no-ip.com/~nxsty/linux/glibc-overlay.tar.bz2"
+ name = "nxsty-glibc"
+ category = "sys-libs">
+
+ <link>
+ http://forums.gentoo.org/viewtopic-t-435659-start-0-postdays-0-postorder-asc-highlight-nxsty+glibc.html
+ </link>
+
+ <description>
+ This overlay provides an enhanced glibc 2.4 ebuild.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "tar"
+ src = "http://snigel.no-ip.com/~nxsty/linux/binutils-overlay.tar.bz2"
+ name = "nxsty-binutils"
+ category = "sys-devel">
+
+ <link>
+ http://forums.gentoo.org/viewtopic-t-435659-start-0-postdays-0-postorder-asc-highlight-nxsty+glibc.html
+ </link>
+
+ <description>
+ This overlay provides a supplemental binutils ebuild to the nxsty-glibc overlay.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "http://svn.gnqs.org/svn/gentoo-nx-overlay/testing"
+ name = "nx">
+
+ <link>
+ http://svn.gnqs.org/projects/gentoo-nx-overlay/timeline
+ </link>
+
+ <description>
+ Overlay for the NX/FreeNX packages for Gentoo.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "svn://svn.tuxfamily.org/svnroot/ckpp/proaudio"
+ name = "pro-audio">
+
+ <link>
+ http://forums.gentoo.org/viewtopic-t-427211.html
+ </link>
+
+ <description>
+ Evermind's overlay with ebuilds for a lot of pro-audio production
+ software.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "http://svn.italpro.biz/catalyst-portage"
+ name = "catalystframework">
+
+ <link>
+ http://gentoo-wiki.com/HOWTO_Catalyst_Framework
+ </link>
+
+ <description>
+ This project tries to provide ebuilds for the great Catalyst MVC
+ Framework and many of the related Perl modules, plugins, etc.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "http://callisto.cs.kun.nl:81/svn/trees/vmware/"
+ name = "vmware">
+
+ <link>
+ http://bugs.gentoo.org/show_bug.cgi?id=122500
+ </link>
+
+ <description>
+ Testing ground for vmware-server and vmware-server-console
+ ebuilds until they can eventually be committed into portage.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "https://www.gentooexperimental.org/svn/java/migration/"
+ name = "java-migration">
+
+ <link>
+ https://projects.gentooexperimental.org/expj/wiki
+ </link>
+
+ <description>
+ The current focus of this overlay is on migration to a new build
+ system which will ultimately allow us to unmask Java 1.5, and be
+ able to support Java 1.6 when it is released.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "https://www.gentooexperimental.org/svn/java/gentoo-java-experimental/"
+ name = "java-experimental">
+
+ <link>
+ https://projects.gentooexperimental.org/expj/wiki
+ </link>
+
+ <description>
+ This is the experimental Portage tree for the Gentoo Java
+ Team. Half-baked ebuilds in-progress will reside it here during
+ development time, before they are included into the
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ src = "svn://juffo.org/musicbrainz-overlay"
+ name = "musicbrainz">
+
+ <link>
+ http://juffo.org/proj/musicbrainz-overlay/README.html
+ </link>
+
+ <description>
+ This is the Gentoo Portage overlay for the most recent
+ MusicBrainz packages.
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ name = "liferea_overlay"
+ src = "https://82.224.45.203/svn/liferea_overlay" >
+
+ <link>
+ http://liferea.sourceforge.net/
+ </link>
+
+ <description>
+ Updated ebuilds for newer versions of Liferea
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "svn"
+ name = "yao"
+ src = "svn://svn.berlios.de/yao/trunk" >
+
+ <link>
+ http://developer.berlios.de/projects/yao/
+ </link>
+
+ <description>
+ Yet Another Overlay aims to provide ebuilds for light
+ applications to allow Gentoo users to maintain a light desktop
+ without being restricted to the small amount of apps which don't
+ depend on GNOME or KDE libraries.
+ </description>
+
+ </overlay>
+
+</layman>
diff --git a/etc/layman.cfg b/etc/layman.cfg
new file mode 100644
index 0000000..51f2e70
--- /dev/null
+++ b/etc/layman.cfg
@@ -0,0 +1,53 @@
+[MAIN]
+
+#-----------------------------------------------------------
+# Path to the config directory
+
+config_dir: /etc/layman
+
+#-----------------------------------------------------------
+# Defines the directory where overlays should be installed
+
+storage : /usr/portage/local/layman
+
+#-----------------------------------------------------------
+# Remote overlay lists will be stored here
+# layman will append _md5(url).xml to each filename
+
+cache : %(storage)s/cache
+
+#-----------------------------------------------------------
+# The list of locally installed overlays
+
+local_list: %(storage)s/overlays.xml
+
+#-----------------------------------------------------------
+# Path to the make.conf file that should be modified by
+# layman
+
+make_conf : %(storage)s/make.conf
+
+#-----------------------------------------------------------
+# URLs of the remote lists of overlays (one per line) or
+# local overlay definitions
+#
+#overlays : http://www.gentoo.org/proj/en/overlays/layman-global.txt
+# http://dev.gentoo.org/~wrobel/layman/global-overlays.xml
+# http://mydomain.org/my-layman-list.xml
+# file:///usr/portage/local/layman/my-list.xml
+
+overlays : http://www.gentoo.org/proj/en/overlays/layman-global.txt
+
+#-----------------------------------------------------------
+# Proxy support
+#
+#proxy : http://[user:pass@]www.my-proxy.org:3128
+
+#-----------------------------------------------------------
+# Strict checking of overlay definitions
+#
+# Set either to "yes" or "no". If "no" layman will issue
+# warnings if an overlay definition is missing either
+# description or contact information.
+#
+nocheck : no
diff --git a/layman/.svn.ignore b/layman/.svn.ignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/layman/.svn.ignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/layman/__init__.py b/layman/__init__.py
new file mode 100644
index 0000000..792d600
--- /dev/null
+++ b/layman/__init__.py
@@ -0,0 +1 @@
+#
diff --git a/layman/action.py b/layman/action.py
new file mode 100644
index 0000000..b2c67ce
--- /dev/null
+++ b/layman/action.py
@@ -0,0 +1,420 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN ACTIONS
+#################################################################################
+# File: action.py
+#
+# Handles layman actions.
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+''' Provides the different actions that can be performed by layman.'''
+
+__version__ = "$Id: action.py 312 2007-04-09 19:45:49Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+import sys
+
+from layman.db import DB, RemoteDB
+
+from layman.debug import OUT
+
+#===============================================================================
+#
+# Class Fetch
+#
+#-------------------------------------------------------------------------------
+
+class Fetch:
+ ''' Fetches the overlay listing.
+
+ >>> import os
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> cache = os.tmpnam()
+ >>> config = {'overlays' :
+ ... 'file://' + here + '/tests/testfiles/global-overlays.xml',
+ ... 'cache' : cache,
+ ... 'nocheck' : True,
+ ... 'proxy' : None,
+ ... 'quietness':3}
+ >>> a = Fetch(config)
+ >>> a.run()
+ 0
+ >>> b = open(a.db.path(config['overlays']))
+ >>> b.readlines()[24]
+ ' A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org].\\n'
+
+ >>> b.close()
+ >>> os.unlink(a.db.path(config['overlays']))
+
+ >>> a.db.overlays.keys()
+ [u'wrobel', u'wrobel-stable']
+ '''
+
+ def __init__(self, config):
+ self.db = RemoteDB(config)
+
+ def run(self):
+ '''Fetch the overlay listing.'''
+ try:
+ self.db.cache()
+ except Exception, error:
+ OUT.die('Failed to fetch overlay list!\nError was: '
+ + str(error))
+
+ return 0
+
+#===============================================================================
+#
+# Class Sync
+#
+#-------------------------------------------------------------------------------
+
+class Sync:
+ ''' Syncs the selected overlays.'''
+
+ def __init__(self, config):
+
+ self.db = DB(config)
+
+ self.rdb = RemoteDB(config)
+
+ self.selection = config['sync']
+
+ if config['sync_all'] or 'ALL' in self.selection:
+ self.selection = self.db.overlays.keys()
+
+ def run(self):
+ '''Synchronize the overlays.'''
+
+ OUT.debug('Updating selected overlays', 6)
+
+ warnings = []
+ success = []
+ for i in self.selection:
+ ordb = self.rdb.select(i)
+ odb = self.db.select(i)
+ if ordb and odb and ordb.src != odb.src:
+ warnings.append(
+ 'The source of the overlay "' + i + '" seems to have c'
+ 'hanged. You currently sync from "' + odb.src + '" whi'
+ 'le the global layman list reports "' + ordb.src + '" '
+ 'as correct location. Please consider removing and rea'
+ 'dding the overlay!')
+
+ try:
+ self.db.sync(i)
+ success.append('Successfully synchronized overlay "' + i + '".')
+ except Exception, error:
+ warnings.append(
+ 'Failed to sync overlay "' + i + '".\nError was: '
+ + str(error))
+
+ if success:
+ OUT.info('\nSuccess:\n------\n', 3)
+ for i in success:
+ OUT.info(i, 3)
+
+ if warnings:
+ OUT.warn('\nErrors:\n------\n', 2)
+ for i in warnings:
+ OUT.warn(i + '\n', 2)
+ return 1
+
+ return 0
+
+#===============================================================================
+#
+# Class Add
+#
+#-------------------------------------------------------------------------------
+
+class Add:
+ ''' Adds the selected overlays.'''
+
+ def __init__(self, config):
+
+ self.config = config
+
+ self.db = DB(config)
+
+ self.rdb = RemoteDB(config)
+
+ self.selection = config['add']
+
+ if 'ALL' in self.selection:
+ self.selection = self.rdb.overlays.keys()
+
+ def run(self):
+ '''Add the overlay.'''
+
+ OUT.debug('Adding selected overlays', 6)
+
+ result = 0
+
+ for i in self.selection:
+ overlay = self.rdb.select(i)
+
+ OUT.debug('Selected overlay', 7)
+
+ if overlay:
+ try:
+ self.db.add(overlay)
+ OUT.info('Successfully added overlay "' + i + '".', 2)
+ except Exception, error:
+ OUT.warn('Failed to add overlay "' + i + '".\nError was: '
+ + str(error), 2)
+ result = 1
+ else:
+ OUT.warn('Overlay "' + i + '" does not exist!', 2)
+ result = 1
+
+ return result
+
+#===============================================================================
+#
+# Class Delete
+#
+#-------------------------------------------------------------------------------
+
+class Delete:
+ ''' Deletes the selected overlays.'''
+
+ def __init__(self, config):
+
+ self.db = DB(config)
+
+ self.selection = config['delete']
+
+ if 'ALL' in self.selection:
+ self.selection = self.db.overlays.keys()
+
+ def run(self):
+ '''Delete the overlay.'''
+
+ OUT.debug('Deleting selected overlays', 6)
+
+ result = 0
+
+ for i in self.selection:
+ overlay = self.db.select(i)
+
+ OUT.debug('Selected overlay', 7)
+
+ if overlay:
+ try:
+ self.db.delete(overlay)
+ OUT.info('Successfully deleted overlay "' + i + '".', 2)
+ except Exception, error:
+ OUT.warn('Failed to delete overlay "' + i + '".\nError was: '
+ + str(error), 2)
+ result = 1
+ else:
+ OUT.warn('Overlay "' + i + '" does not exist!', 2)
+ result = 1
+
+ return result
+
+#===============================================================================
+#
+# Class List
+#
+#-------------------------------------------------------------------------------
+
+class List:
+ ''' Lists the available overlays.
+
+ >>> import os
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> cache = os.tmpnam()
+ >>> config = {'overlays' :
+ ... 'file://' + here + '/tests/testfiles/global-overlays.xml',
+ ... 'cache' : cache,
+ ... 'proxy' : None,
+ ... 'nocheck' : False,
+ ... 'verbose': False,
+ ... 'quietness':3}
+ >>> a = List(config)
+ >>> a.rdb.cache()
+ >>> OUT.color_off()
+ >>> a.run()
+ * wrobel [Subversion] (source: https://overlays.gentoo.or...)
+ 0
+ >>> a.config['verbose'] = True
+ >>> a.run()
+ * wrobel
+ * ~~~~~~
+ * Source : https://overlays.gentoo.org/svn/dev/wrobel
+ * Contact : nobody@gentoo.org
+ * Type : Subversion; Priority: 10
+ *
+ * Description:
+ * Test
+ *
+ * *** This is no official gentoo overlay ***
+ *
+ * wrobel-stable
+ * ~~~~~~~~~~~~~
+ * Source : rsync://gunnarwrobel.de/wrobel-stable
+ * Contact : nobody@gentoo.org
+ * Type : Rsync; Priority: 50
+ *
+ * Description:
+ * A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org].
+ *
+ 0
+ '''
+
+ def __init__(self, config):
+
+ OUT.debug('Creating RemoteDB handler', 6)
+
+ self.rdb = RemoteDB(config)
+ self.config = config
+
+ def run(self):
+ ''' List the available overlays.'''
+
+ for i in self.rdb.list(self.config['verbose']):
+ # Is the overlay supported?
+ if i[1]:
+ # Is this an official overlay?
+ if i[2]:
+ OUT.info(i[0], 1)
+ # Unofficial overlays will only be listed if we are not
+ # checking or listing verbose
+ elif self.config['nocheck'] or self.config['verbose']:
+ # Give a reason why this is marked yellow if it is a verbose
+ # listing
+ if self.config['verbose']:
+ OUT.warn('*** This is no official gentoo overlay ***\n', 1)
+ OUT.warn(i[0], 1)
+ # Unsupported overlays will only be listed if we are not checking
+ # or listing verbose
+ elif self.config['nocheck'] or self.config['verbose']:
+ # Give a reason why this is marked red if it is a verbose
+ # listing
+ if self.config['verbose']:
+ OUT.error('*** You are lacking the necessary tools to insta'
+ 'll this overlay ***\n')
+ OUT.error(i[0])
+
+ return 0
+
+#===============================================================================
+#
+# Class ListLocal
+#
+#-------------------------------------------------------------------------------
+
+class ListLocal:
+ ''' Lists the local overlays.'''
+
+ def __init__(self, config):
+ self.db = DB(config)
+ self.config = config
+
+ def run(self):
+ '''List the overlays.'''
+
+ for i in self.db.list(self.config['verbose']):
+
+ OUT.debug('Printing local overlay.', 8)
+
+ # Is the overlay supported?
+ if i[1]:
+ # Is this an official overlay?
+ if i[2]:
+ OUT.info(i[0], 1)
+ # Unofficial overlays will only be listed if we are not
+ # checking or listing verbose
+ else:
+ # Give a reason why this is marked yellow if it is a verbose
+ # listing
+ if self.config['verbose']:
+ OUT.warn('*** This is no official gentoo overlay ***\n', 1)
+ OUT.warn(i[0], 1)
+ # Unsupported overlays will only be listed if we are not checking
+ # or listing verbose
+ else:
+ # Give a reason why this is marked red if it is a verbose
+ # listing
+ if self.config['verbose']:
+ OUT.error('*** You are lacking the necessary tools to insta'
+ 'll this overlay ***\n')
+ OUT.error(i[0])
+
+ return 0
+
+#===============================================================================
+#
+# Class Actions
+#
+#-------------------------------------------------------------------------------
+
+class Actions:
+ '''Dispatches to the actions the user selected. '''
+
+ # Given in order of precedence
+ actions = [('fetch', Fetch),
+ ('add', Add),
+ ('sync', Sync),
+ ('sync_all', Sync),
+ ('delete', Delete),
+ ('list', List),
+ ('list_local', ListLocal),]
+
+ def __init__(self, config):
+
+ # Make fetching the overlay list a default action
+ if not 'nofetch' in config.keys():
+ # Actions that implicitely call the fetch operation before
+ fetch_actions = ['fetch', 'sync', 'sync_all', 'list']
+ for i in fetch_actions:
+ if i in config.keys():
+ # Implicitely call fetch, break loop
+ Fetch(config).run()
+ break
+
+ result = 0
+
+ for i in self.actions:
+
+ OUT.debug('Checking for action', 7)
+
+ if i[0] in config.keys():
+ result += i[1](config).run()
+
+
+ if not result:
+ sys.exit(0)
+ else:
+ sys.exit(1)
+
+#===============================================================================
+#
+# Testing
+#
+#-------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ import doctest, sys
+
+ # Ignore warnings here. We are just testing
+ from warnings import filterwarnings, resetwarnings
+ filterwarnings('ignore')
+
+ doctest.testmod(sys.modules[__name__])
+
+ resetwarnings()
diff --git a/layman/config.py b/layman/config.py
new file mode 100644
index 0000000..287f223
--- /dev/null
+++ b/layman/config.py
@@ -0,0 +1,300 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN CONFIGURATION
+#################################################################################
+# File: config.py
+#
+# Handles layman configuration
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+'''Defines the configuration options and provides parsing functionality.'''
+
+__version__ = "$Id: config.py 286 2007-01-09 17:48:23Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+import sys, ConfigParser
+
+from optparse import OptionParser, OptionGroup
+from layman.debug import OUT
+from layman.version import VERSION
+
+#===============================================================================
+#
+# Class Config
+#
+#-------------------------------------------------------------------------------
+
+class Config(object):
+ '''Handles the configuration.'''
+
+ def __init__(self):
+ '''
+ Creates and describes all possible polymeraZe options and creates
+ a debugging object.
+
+ >>> import os.path
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> sys.argv.append('--config')
+ >>> sys.argv.append(here + '/../etc/layman.cfg')
+ >>> a = Config()
+ >>> a['overlays']
+ '\\nhttp://www.gentoo.org/proj/en/overlays/layman-global.txt'
+ >>> sorted(a.keys())
+ ['cache', 'config', 'config_dir', 'local_list', 'make_conf', 'nocheck', 'overlays', 'proxy', 'quietness', 'storage']
+ '''
+
+ self.defaults = {'config_dir': '/etc/layman',
+ 'config' : '/etc/layman/layman.cfg',
+ 'storage' : '/usr/portage/local/layman',
+ 'cache' : '%(storage)s/cache',
+ 'local_list': '%(storage)s/overlays.xml',
+ 'make_conf' : '%(storage)s/make.conf',
+ 'nocheck' : 'no',
+ 'proxy' : '',
+ 'overlays' :
+ 'http://www.gentoo.org/proj/en/overlays/layman-global.'
+ 'txt',}
+
+
+ self.parser = OptionParser(
+ usage = '\n\nlayman -a/-d/-S|overlay\nlayman -f [-o url]\nlayman' \
+ ' -l|-L',
+ version = VERSION)
+
+ #-----------------------------------------------------------------
+ # Main Options
+
+ group = OptionGroup(self.parser,
+ '<Actions>')
+
+ group.add_option('-a',
+ '--add',
+ action = 'append',
+ help = 'Add the given overlay from the cached remote li'
+ 'st to your locally installed overlays.. Specify "ALL" '
+ 'to add all overlays from the remote list.')
+
+ group.add_option('-d',
+ '--delete',
+ action = 'append',
+ help = 'Remove the given overlay from your locally inst'
+ 'alled overlays. Specify "ALL" to remove all overlays')
+
+ group.add_option('-s',
+ '--sync',
+ action = 'append',
+ help = 'Update the specified overlay. Use "ALL" as para'
+ 'meter to synchronize all overlays')
+
+ group.add_option('-S',
+ '--sync-all',
+ action = 'store_true',
+ help = 'Update all overlays.')
+
+ group.add_option('-L',
+ '--list',
+ action = 'store_true',
+ help = 'List the contents of the remote list.')
+
+ group.add_option('-l',
+ '--list-local',
+ action = 'store_true',
+ help = 'List the locally installed overlays.')
+
+ group.add_option('-f',
+ '--fetch',
+ action = 'store_true',
+ help = 'Fetch a remote list of overlays. This option is'
+ ' deprecated. The fetch operation will be performed by '
+ 'default when you run sync, sync-all, or list.')
+
+ group.add_option('-n',
+ '--nofetch',
+ action = 'store_true',
+ help = 'Do not fetch a remote list of overlays.')
+
+ group.add_option('-p',
+ '--priority',
+ action = 'store',
+ help = 'Use this with the --add switch to set the prior'
+ 'ity of the added overlay. This will influence the sort'
+ 'ing order of the overlays in the PORTDIR_OVERLAY varia'
+ 'ble.')
+
+ self.parser.add_option_group(group)
+
+ #-----------------------------------------------------------------
+ # Additional Options
+
+ group = OptionGroup(self.parser,
+ '<Path options>')
+
+ group.add_option('-c',
+ '--config',
+ action = 'store',
+ help = 'Path to the config file [default: ' \
+ + self.defaults['config'] + '].')
+
+ group.add_option('-o',
+ '--overlays',
+ action = 'append',
+ help = 'The list of overlays [default: ' \
+ + self.defaults['overlays'] + '].')
+
+ self.parser.add_option_group(group)
+
+ #-----------------------------------------------------------------
+ # Output Options
+
+ group = OptionGroup(self.parser,
+ '<Output options>')
+
+ group.add_option('-v',
+ '--verbose',
+ action = 'store_true',
+ help = 'Increase amount of output.')
+
+ group.add_option('-q',
+ '--quiet',
+ action = 'store_true',
+ help = 'Yield no output. Please be careful with this op'
+ 'tion: If the processes spawned by layman when adding o'
+ 'r synchronizing overlays require any input layman will'
+ ' hang without telling you why. This might happen for e'
+ 'xample if your overlay resides in subversion and the S'
+ 'SL certificate of the server needs acceptance.')
+
+ group.add_option('-Q',
+ '--quietness',
+ action = 'store',
+ type = 'int',
+ default = '4',
+ help = 'Set the level of output (0-4). Default: 4. Once'
+ ' you set this below 2 the same warning as given for --'
+ 'quiet applies! ')
+
+ group.add_option('-k',
+ '--nocheck',
+ action = 'store_true',
+ help = 'Do not check overlay definitions and do not i'
+ 'ssue a warning if description or contact information'
+ ' are missing.')
+
+ self.parser.add_option_group(group)
+
+ #-----------------------------------------------------------------
+ # Debug Options
+
+ OUT.cli_opts(self.parser)
+
+ # Parse the command line first since we need to get the config
+ # file option.
+ (self.options, args) = self.parser.parse_args()
+
+ # handle debugging
+ OUT.cli_handle(self.options)
+
+ # Fetch only an alternate config setting from the options
+ if not self.options.__dict__['config'] is None:
+ self.defaults['config'] = self.options.__dict__['config']
+
+ OUT.debug('Got config file at ' + self.defaults['config'], 8)
+
+ # Now parse the config file
+ self.config = ConfigParser.ConfigParser(self.defaults)
+ self.config.add_section('MAIN')
+
+ # handle quietness
+ if self['quiet']:
+ OUT.set_info_level(1)
+ OUT.set_warn_level(1)
+ self.defaults['quietness'] = 0
+ elif 'quietness' in self.keys():
+ OUT.set_info_level(int(self['quietness']))
+ OUT.set_warn_level(int(self['quietness']))
+
+ OUT.debug('Reading config file at ' + self.defaults['config'], 8)
+
+ self.config.read(self.defaults['config'])
+
+ def __getitem__(self, key):
+
+ if key == 'overlays':
+ overlays = ''
+ if (key in self.options.__dict__.keys()
+ and not self.options.__dict__[key] is None):
+ overlays = '\n'.join(self.options.__dict__[key])
+ if self.config.has_option('MAIN', 'overlays'):
+ overlays += '\n' + self.config.get('MAIN', 'overlays')
+ if overlays:
+ return overlays
+
+ OUT.debug('Retrieving option', 8)
+
+ if (key in self.options.__dict__.keys()
+ and not self.options.__dict__[key] is None):
+ return self.options.__dict__[key]
+
+ OUT.debug('Retrieving option', 8)
+
+ if self.config.has_option('MAIN', key):
+ if key == 'nocheck':
+ if self.config.get('MAIN', key).lower() == 'yes':
+ return True
+ else:
+ return False
+ return self.config.get('MAIN', key)
+
+ OUT.debug('Retrieving option', 8)
+
+ if key in self.defaults.keys():
+ return self.defaults[key]
+
+ OUT.debug('Retrieving option', 8)
+
+ return None
+
+ def keys(self):
+ '''Special handler for the configuration keys.'''
+
+ OUT.debug('Retrieving keys', 8)
+
+ keys = [i for i in self.options.__dict__.keys()
+ if not self.options.__dict__[i] is None]
+
+ OUT.debug('Retrieving keys', 8)
+
+ keys += [name for name, value in self.config.items('MAIN')
+ if not name in keys]
+
+ OUT.debug('Retrieving keys', 8)
+
+ keys += [i for i in self.defaults.keys()
+ if not i in keys]
+
+ OUT.debug('Retrieving keys', 8)
+
+ return keys
+
+
+#===============================================================================
+#
+# Testing
+#
+#-------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod(sys.modules[__name__])
diff --git a/layman/db.py b/layman/db.py
new file mode 100644
index 0000000..ae32114
--- /dev/null
+++ b/layman/db.py
@@ -0,0 +1,585 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN OVERLAY DB
+#################################################################################
+# File: db.py
+#
+# Access to the db of overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+'''Handles different storage files.'''
+
+__version__ = "$Id: db.py 309 2007-04-09 16:23:38Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+import os, os.path, urllib2, re, md5
+
+from layman.utils import path
+from layman.overlay import Overlays
+
+from layman.debug import OUT
+
+#===============================================================================
+#
+# Class DB
+#
+#-------------------------------------------------------------------------------
+
+class DB(Overlays):
+ ''' Handle the list of local overlays.'''
+
+ def __init__(self, config):
+
+ self.config = config
+
+ self.path = config['local_list']
+
+ if config['nocheck']:
+ ignore = 2
+ else:
+ ignore = 1
+
+ quiet = int(config['quietness']) < 3
+
+ Overlays.__init__(self,
+ [config['local_list'], ],
+ ignore,
+ quiet)
+
+ OUT.debug('DB handler initiated', 6)
+
+ def add(self, overlay):
+ '''
+ Add an overlay to the local list of overlays.
+
+ >>> write = os.tmpnam()
+ >>> write2 = os.tmpnam()
+ >>> write3 = os.tmpnam()
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> config = {'local_list' :
+ ... here + '/tests/testfiles/global-overlays.xml',
+ ... 'make_conf' : write2,
+ ... 'nocheck' : True,
+ ... 'storage' : write3,
+ ... 'quietness':3}
+
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> a = DB(config)
+ >>> config['local_list'] = write
+ >>> b = DB(config)
+ >>> OUT.color_off()
+
+ >>> m = MakeConf(config, b.overlays)
+ >>> m.path = write2
+ >>> m.write()
+
+ Commented out since it needs network access:
+
+ # >>> b.add(a.select('wrobel-stable')) #doctest: +ELLIPSIS
+ # * Running command "/usr/bin/rsync -rlptDvz --progress --delete --delete-after --timeout=180 --exclude="distfiles/*" --exclude="local/*" --exclude="packages/*" "rsync://gunnarwrobel.de/wrobel-stable/*" "/tmp/file.../wrobel-stable""...
+ # >>> c = Overlays([write, ])
+ # >>> c.overlays.keys()
+ # [u'wrobel-stable']
+
+ # >>> m = MakeConf(config, b.overlays)
+ # >>> [i.name for i in m.overlays] #doctest: +ELLIPSIS
+ # [u'wrobel-stable']
+
+
+ # >>> os.unlink(write)
+ >>> os.unlink(write2)
+ >>> import shutil
+
+ # >>> shutil.rmtree(write3)
+ '''
+
+ if overlay.name not in self.overlays.keys():
+ result = overlay.add(self.config['storage'])
+ if result == 0:
+ if 'priority' in self.config.keys():
+ overlay.priority = int(self.config['priority'])
+ self.overlays[overlay.name] = overlay
+ self.write(self.path)
+ make_conf = MakeConf(self.config, self.overlays)
+ make_conf.add(overlay)
+ else:
+ overlay.delete(self.config['storage'])
+ raise Exception('Adding the overlay failed!')
+ else:
+ raise Exception('Overlay "' + overlay.name + '" already in the loca'
+ 'l list!')
+
+ def delete(self, overlay):
+ '''
+ Add an overlay to the local list of overlays.
+
+ >>> write = os.tmpnam()
+ >>> write2 = os.tmpnam()
+ >>> write3 = os.tmpnam()
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> config = {'local_list' :
+ ... here + '/tests/testfiles/global-overlays.xml',
+ ... 'make_conf' : write2,
+ ... 'nocheck' : True,
+ ... 'storage' : write3,
+ ... 'quietness':3}
+
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> a = DB(config)
+ >>> config['local_list'] = write
+ >>> b = DB(config)
+ >>> OUT.color_off()
+
+ >>> m = MakeConf(config, b.overlays)
+ >>> m.path = here + '/tests/testfiles/make.conf'
+ >>> m.read()
+
+ >>> m.path = write2
+ >>> m.write()
+
+ # >>> b.add(a.select('wrobel-stable')) #doctest: +ELLIPSIS
+ # * Running command "/usr/bin/rsync -rlptDvz --progress --delete --delete-after --timeout=180 --exclude="distfiles/*" --exclude="local/*" --exclude="packages/*" "rsync://gunnarwrobel.de/wrobel-stable/*" "/tmp/file.../wrobel-stable""...
+ # >>> b.add(a.select('wrobel')) #doctest: +ELLIPSIS
+ # * Running command "/usr/bin/svn co "https://overlays.gentoo.org/svn/dev/wrobel/" "/tmp/file.../wrobel""...
+ # >>> c = Overlays([write, ])
+ # >>> c.overlays.keys()
+ # [u'wrobel', u'wrobel-stable']
+
+ # >>> b.delete(b.select('wrobel'))
+ # >>> c = Overlays([write, ])
+ # >>> c.overlays.keys()
+ # [u'wrobel-stable']
+
+ # >>> m = MakeConf(config, b.overlays)
+ # >>> [i.name for i in m.overlays] #doctest: +ELLIPSIS
+ # [u'wrobel-stable']
+
+ # >>> os.unlink(write)
+ >>> os.unlink(write2)
+ >>> import shutil
+
+ # >>> shutil.rmtree(write3)
+ '''
+
+ if overlay.name in self.overlays.keys():
+ make_conf = MakeConf(self.config, self.overlays)
+ overlay.delete(self.config['storage'])
+ del self.overlays[overlay.name]
+ self.write(self.path)
+ make_conf.delete(overlay)
+ else:
+ raise Exception('No local overlay named "' + overlay.name + '"!')
+
+ def sync(self, overlay_name):
+ '''Synchronize the given overlay.'''
+
+ overlay = self.select(overlay_name)
+
+ if overlay:
+ result = overlay.sync(self.config['storage'])
+ if result:
+ raise Exception('Syncing overlay "' + overlay_name +
+ '" returned status ' + str(result) + '!')
+ else:
+ raise Exception('No such overlay ("' + overlay_name + '")!')
+
+#===============================================================================
+#
+# Class RemoteDB
+#
+#-------------------------------------------------------------------------------
+
+class RemoteDB(Overlays):
+ '''Handles fetching the remote overlay list.'''
+
+ def __init__(self, config):
+
+ self.config = config
+
+ self.proxies = {}
+
+ if config['proxy']:
+ self.proxies['http'] = config['proxy']
+ elif os.getenv('http_proxy'):
+ self.proxies['http'] = os.getenv('http_proxy')
+
+ if self.proxies:
+ proxy_handler = urllib2.ProxyHandler(self.proxies)
+ opener = urllib2.build_opener(proxy_handler)
+ urllib2.install_opener(opener)
+
+ self.urls = [i.strip() for i in config['overlays'].split('\n') if i]
+
+ paths = [self.path(i) for i in self.urls]
+
+ if config['nocheck']:
+ ignore = 2
+ else:
+ ignore = 0
+
+ quiet = int(config['quietness']) < 3
+
+ Overlays.__init__(self, paths, ignore, quiet)
+
+ def cache(self):
+ '''
+ Copy the remote overlay list to the local cache.
+
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> cache = os.tmpnam()
+ >>> config = {'overlays' :
+ ... 'file://' + here + '/tests/testfiles/global-overlays.xml',
+ ... 'cache' : cache,
+ ... 'nocheck' : True,
+ ... 'proxy' : None,
+ ... 'quietness':3}
+ >>> a = RemoteDB(config)
+ >>> a.cache()
+ >>> b = open(a.path(config['overlays']))
+ >>> b.readlines()[24]
+ ' A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org].\\n'
+
+ >>> b.close()
+ >>> os.unlink(a.path(config['overlays']))
+
+ >>> a.overlays.keys()
+ [u'wrobel', u'wrobel-stable']
+ '''
+ for url in self.urls:
+
+ mpath = self.path(url)
+
+ try:
+
+ # Fetch the remote list
+ olist = urllib2.urlopen(url).read()
+
+ # Create our storage directory if it is missing
+ if not os.path.exists(os.path.dirname(mpath)):
+ try:
+ os.makedirs(os.path.dirname(mpath))
+ except OSError, error:
+ raise OSError('Failed to create layman storage direct'
+ + 'ory ' + os.path.dirname(mpath) + '\n'
+ + 'Error was:' + str(error))
+
+ # Before we overwrite the old cache, check that the downloaded
+ # file is intact and can be parsed
+ try:
+ self.read(olist)
+ except Exception, error:
+ raise IOError('Failed to parse the overlays list fetched fr'
+ 'om ' + url + '\nThis means that the download'
+ 'ed file is somehow corrupt or there was a pr'
+ 'oblem with the webserver. Check the content '
+ 'of the file. Error was:\n' + str(error))
+
+ # Ok, now we can overwrite the old cache
+ try:
+ out_file = open(mpath, 'w')
+ out_file.write(olist)
+ out_file.close()
+
+ except Exception, error:
+ raise IOError('Failed to temporarily cache overlays list in'
+ ' ' + mpath + '\nError was:\n' + str(error))
+
+
+ except IOError, error:
+ OUT.warn('Failed to update the overlay list from: '
+ + url + '\nError was:\n' + str(error))
+
+ try:
+ # Finally parse the contents of the cache
+ self.read_file(mpath)
+ except IOError, error:
+ OUT.warn('Failed to read a cached version of the overlay list f'
+ 'rom ' + url + '. You probably did not download the fi'
+ 'le before. The corresponding entry in your layman.cfg'
+ ' file will be disregarded.\nError was:\n' + str(error)
+ )
+
+ def path(self, url):
+ '''Return a unique file name for the url.'''
+
+ base = self.config['cache']
+
+ OUT.debug('Generating cache path.', 6)
+
+ return base + '_' + md5.md5(url).hexdigest() + '.xml'
+
+#===============================================================================
+#
+# Helper class MakeConf
+#
+#-------------------------------------------------------------------------------
+
+class MakeConf:
+ '''
+ Handles modifications to /etc/make.conf
+
+ Check that an add/remove cycle does not modify the make.conf:
+
+ >>> import md5
+ >>> write = os.tmpnam()
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> config = {'local_list' :
+ ... here + '/tests/testfiles/global-overlays.xml',
+ ... 'make_conf' : here + '/tests/testfiles/make.conf',
+ ... 'nocheck' : True,
+ ... 'storage' : '/usr/portage/local/layman',
+ ... 'quietness':3}
+ >>> b = DB(config)
+ >>> a = MakeConf(config, b.overlays)
+ >>> o_md5 = str(md5.md5(open(here + '/tests/testfiles/make.conf').read()).hexdigest())
+ >>> a.path = write
+ >>> a.add(b.overlays['wrobel-stable'])
+ >>> [i.name for i in a.overlays]
+ [u'wrobel-stable', u'wrobel-stable']
+ >>> a.add(b.overlays['wrobel'])
+ >>> [i.name for i in a.overlays]
+ [u'wrobel', u'wrobel-stable', u'wrobel-stable']
+ >>> a.delete(b.overlays['wrobel-stable'])
+ >>> [i.name for i in a.overlays]
+ [u'wrobel']
+ >>> a.add(b.overlays['wrobel-stable'])
+ >>> [i.name for i in a.overlays]
+ [u'wrobel', u'wrobel-stable']
+ >>> a.delete(b.overlays['wrobel'])
+ >>> n_md5 = str(md5.md5(open(write).read()).hexdigest())
+ >>> o_md5 == n_md5
+ True
+ >>> os.unlink(write)
+ '''
+
+ my_re = re.compile('PORTDIR_OVERLAY\s*=\s*"([^"]*)"')
+
+ def __init__(self, config, overlays):
+
+ self.path = config['make_conf']
+ self.storage = config['storage']
+ self.data = ''
+ self.db = overlays
+ self.overlays = []
+ self.extra = []
+
+ self.read()
+
+ def add(self, overlay):
+ '''
+ Add an overlay to make.conf.
+
+ >>> write = os.tmpnam()
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> config = {'local_list' :
+ ... here + '/tests/testfiles/global-overlays.xml',
+ ... 'make_conf' : here + '/tests/testfiles/make.conf',
+ ... 'nocheck' : True,
+ ... 'storage' : '/usr/portage/local/layman',
+ ... 'quietness':3}
+ >>> c = DB(config)
+ >>> a = MakeConf(config, c.overlays)
+ >>> a.path = write
+ >>> a.add(c.select('wrobel'))
+ >>> config['make_conf'] = write
+ >>> b = MakeConf(config, c.overlays)
+ >>> [i.name for i in b.overlays]
+ [u'wrobel', u'wrobel-stable']
+ >>> b.extra
+ ['/usr/portage/local/ebuilds/testing', '/usr/portage/local/ebuilds/stable', '/usr/portage/local/kolab2', '/usr/portage/local/gentoo-webapps-overlay/experimental', '/usr/portage/local/gentoo-webapps-overlay/production-ready']
+
+ >>> os.unlink(write)
+ '''
+ self.overlays.append(overlay)
+ self.write()
+
+ def delete(self, overlay):
+ '''
+ Delete an overlay from make.conf.
+
+ >>> write = os.tmpnam()
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> config = {'local_list' :
+ ... here + '/tests/testfiles/global-overlays.xml',
+ ... 'make_conf' : here + '/tests/testfiles/make.conf',
+ ... 'nocheck' : True,
+ ... 'storage' : '/usr/portage/local/layman',
+ ... 'quietness':3}
+ >>> c = DB(config)
+ >>> a = MakeConf(config, c.overlays)
+ >>> a.path = write
+ >>> a.delete(c.select('wrobel-stable'))
+ >>> config['make_conf'] = write
+ >>> b = MakeConf(config, c.overlays)
+ >>> [i.name for i in b.overlays]
+ []
+ >>> b.extra
+ ['/usr/portage/local/ebuilds/testing', '/usr/portage/local/ebuilds/stable', '/usr/portage/local/kolab2', '/usr/portage/local/gentoo-webapps-overlay/experimental', '/usr/portage/local/gentoo-webapps-overlay/production-ready']
+
+ >>> os.unlink(write)
+ '''
+ self.overlays = [i
+ for i in self.overlays
+ if i.name != overlay.name]
+ self.write()
+
+ def read(self):
+ '''
+ Read the list of registered overlays from /etc/make.conf.
+
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> config = {'local_list' :
+ ... here + '/tests/testfiles/global-overlays.xml',
+ ... 'make_conf' : here + '/tests/testfiles/make.conf',
+ ... 'nocheck' : True,
+ ... 'storage' : '/usr/portage/local/layman',
+ ... 'quietness':3}
+ >>> c = DB(config)
+ >>> a = MakeConf(config, c.overlays)
+ >>> [i.name for i in a.overlays]
+ [u'wrobel-stable']
+ >>> a.extra
+ ['/usr/portage/local/ebuilds/testing', '/usr/portage/local/ebuilds/stable', '/usr/portage/local/kolab2', '/usr/portage/local/gentoo-webapps-overlay/experimental', '/usr/portage/local/gentoo-webapps-overlay/production-ready']
+ '''
+ if os.path.isfile(self.path):
+ self.content()
+
+ overlays = self.my_re.search(self.data)
+
+ if not overlays:
+ raise Exception('Did not find a PORTDIR_OVERLAY entry in file ' +
+ self.path +'! Did you specify the correct file?')
+
+ overlays = [i.strip()
+ for i in overlays.group(1).split('\n')
+ if i.strip()]
+
+ for i in overlays:
+ if i[:len(self.storage)] == self.storage:
+ oname = os.path.basename(i)
+ if oname in self.db.keys():
+ self.overlays.append(self.db[oname])
+ else:
+ # These are additional overlays that we dont know
+ # anything about. The user probably added them manually
+ self.extra.append(i)
+ else:
+ # These are additional overlays that we dont know anything
+ # about. The user probably added them manually
+ self.extra.append(i)
+
+
+ else:
+ self.overlays = []
+ self.data = 'PORTDIR_OVERLAY="\n"\n'
+
+ self.extra = [i for i in self.extra
+ if (i != '$PORTDIR_OVERLAY'
+ and i != '${PORTDIR_OVERLAY}')]
+
+ def write(self):
+ '''
+ Write the list of registered overlays to /etc/make.conf.
+
+ >>> write = os.tmpnam()
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> config = {'local_list' :
+ ... here + '/tests/testfiles/global-overlays.xml',
+ ... 'make_conf' : here + '/tests/testfiles/make.conf',
+ ... 'nocheck' : True,
+ ... 'storage' : '/usr/portage/local/layman',
+ ... 'quietness':3}
+ >>> c = DB(config)
+ >>> a = MakeConf(config, c.overlays)
+ >>> a.path = write
+ >>> a.write()
+ >>> config['make_conf'] = write
+ >>> b = MakeConf(config, c.overlays)
+ >>> [i.name for i in b.overlays]
+ [u'wrobel-stable']
+ >>> b.extra
+ ['/usr/portage/local/ebuilds/testing', '/usr/portage/local/ebuilds/stable', '/usr/portage/local/kolab2', '/usr/portage/local/gentoo-webapps-overlay/experimental', '/usr/portage/local/gentoo-webapps-overlay/production-ready']
+
+ >>> os.unlink(write)
+ '''
+ def prio_sort(a, b):
+ '''Sort by priority.'''
+ if a.priority < b.priority:
+ return -1
+ elif a.priority > b.priority:
+ return 1
+ return 0
+
+ self.overlays.sort(prio_sort)
+
+ paths = []
+ for i in self.overlays:
+ paths.append(path((self.storage, i.name, )))
+
+ overlays = 'PORTDIR_OVERLAY="\n'
+ overlays += '\n'.join(paths) + '\n'
+ overlays += '$PORTDIR_OVERLAY\n'
+ overlays += '\n'.join(self.extra)
+ overlays += '"'
+
+ content = self.my_re.sub(overlays, self.data)
+
+ if not self.my_re.search(content):
+ raise Exception('Ups, failed to set a proper PORTDIR_OVERLAY entry '
+ 'in file ' + self.path +'! Did not overwrite the fi'
+ 'le.')
+
+ try:
+ make_conf = open(self.path, 'w')
+
+ make_conf.write(content)
+
+ make_conf.close()
+
+ except Exception, error:
+ raise Exception('Failed to read "' + self.path + '".\nError was:\n'
+ + str(error))
+
+ def content(self):
+ '''
+ Returns the content of the /etc/make.conf file.
+ '''
+ try:
+ make_conf = open(self.path)
+
+ self.data = make_conf.read()
+
+ make_conf.close()
+
+ except Exception, error:
+ raise Exception('Failed to read "' + self.path + '".\nError was:\n'
+ + str(error))
+
+#===============================================================================
+#
+# Testing
+#
+#-------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ import doctest, sys
+
+ # Ignore warnings here. We are just testing
+ from warnings import filterwarnings, resetwarnings
+ filterwarnings('ignore')
+
+ doctest.testmod(sys.modules[__name__])
+
+ resetwarnings()
diff --git a/layman/debug.py b/layman/debug.py
new file mode 100644
index 0000000..925f49c
--- /dev/null
+++ b/layman/debug.py
@@ -0,0 +1,501 @@
+#################################################################################
+# LAYMAN - DEBUGGING FUNCTIONS
+#################################################################################
+# debug.py -- Utility function for debugging
+# Copyright 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+
+__version__ = "$Id: debug.py 153 2006-06-05 06:03:16Z wrobel $"
+
+#################################################################################
+##
+## Dependancies
+##
+#################################################################################
+
+import sys, inspect
+
+from optparse import OptionGroup
+
+#################################################################################
+##
+## Color codes (taken from portage)
+##
+#################################################################################
+
+esc_seq = '\x1b['
+
+codes = {}
+codes['reset'] = esc_seq + '39;49;00m'
+codes['red'] = esc_seq + '31;01m'
+codes['green'] = esc_seq + '32;01m'
+codes['yellow'] = esc_seq + '33;01m'
+codes['turquoise'] = esc_seq + '36;01m'
+
+#################################################################################
+##
+## Message Class
+##
+#################################################################################
+
+class Message:
+ #FIXME: Think about some simple doctests before you modify this class the
+ # next time.
+
+ def __init__(self, module = '',
+ err = sys.stderr,
+ dbg = sys.stderr,
+ debugging_level = 4,
+ debugging_verbosity = 2,
+ info_level = 4,
+ warn_level = 4,
+ col = True,
+ mth = ['*'],
+ obj = ['*'],
+ var = ['*']):
+
+ # A description of the module that is being debugged
+ self.debug_env = module
+
+ # Where should the debugging output go? This can also be a file
+ self.debug_out = dbg
+
+ # Where should the error output go? This can also be a file
+ self.error_out = err
+
+ # The higher the level the more information you will get
+ self.warn_lev = warn_level
+
+ # The higher the level the more information you will get
+ self.info_lev = info_level
+
+ # The highest level of debugging messages acceptable for output
+ # The higher the level the more output you will get
+ self.debug_lev = debugging_level
+
+ # The debugging output can range from very verbose (3) to
+ # very compressed (1)
+ self.debug_vrb = debugging_verbosity
+
+ # Which methods should actually be debugged?
+ # Use '*' to indicate 'All methods'
+ self.debug_mth = mth
+
+ # Which objects should actually be debugged?
+ # Use '*' to indicate 'All objects'
+ self.debug_obj = obj
+
+ # Which variables should actually be debugged?
+ # Use '*' to indicate 'All variables'
+ self.debug_var = var
+
+ # Exclude class variables by default
+ self.show_class_variables = False
+
+ # Should the output be colored?
+ self.use_color = col
+
+ self.has_error = False
+
+
+ ############################################################################
+ # Add command line options
+
+ def cli_opts(self, parser):
+
+ group = OptionGroup(parser,
+ '<Debugging options>',
+ 'Control the debugging features of '
+ + self.debug_env)
+
+ group.add_option('--debug',
+ action = 'store_true',
+ help = 'Activates debugging features.')
+
+ group.add_option('--debug-level',
+ action = 'store',
+ type = 'int',
+ help = 'A value between 0 and 10. 0 means no debugging '
+ 'messages will be selected, 10 selects all debugging me'
+ 'ssages. Default is "4".')
+
+ group.add_option('--debug-verbose',
+ action = 'store',
+ type = 'int',
+ help = 'A value between 1 and 3. Lower values yield les'
+ 's verbose debugging output. Default is "2".')
+
+ group.add_option('--debug-methods',
+ action = 'store',
+ help = 'Limits the methods that will return debugging o'
+ 'utput. The function name is sufficient and there is no'
+ 'difference between class methods or general functions.'
+ ' Several methods can be specified by seperating them w'
+ ' with a comma. Default is "*" which specifies all meth'
+ 'ods.')
+
+ group.add_option('--debug-classes',
+ action = 'store',
+ help = 'Limits the classes that will return debugging o'
+ 'utput. Specify only the class name not including the m'
+ 'odules in which the class is defined (e.g. MyModule.ma'
+ 'in.Main should only be represented by "Main"). Several'
+ 'classes can be specified by seperating them with a com'
+ 'ma. Default is "*" which specifies all classes.')
+
+ group.add_option('--debug-variables',
+ action = 'store',
+ help = 'Limits the variables that will return debugging'
+ ' output. Several variables can be specified by seperat'
+ 'ing them with a comma. Default is "*" which specifies '
+ 'all variables.')
+
+ group.add_option('--debug-class-vars',
+ action = 'store_true',
+ help = 'In default mode the debugging code will only re'
+ 'turn information on the local variable which does not '
+ 'include the class variables. Use this switch to add al'
+ 'l values that are provided by "self".')
+
+ group.add_option('--debug-nocolor',
+ action = 'store_true',
+ help = 'Deactivates colors in the debugging output.')
+
+ parser.add_option_group(group)
+
+
+ #############################################################################
+ # Handle command line options
+
+ def cli_handle(self, options):
+
+ if (options.__dict__.has_key('debug')
+ and options.__dict__['debug']):
+ self.debug_on()
+ else:
+ self.debug_off()
+ return
+
+ if (options.__dict__.has_key('debug_class_vars')
+ and options.__dict__['debug_class_vars']):
+ self.class_variables_on()
+ else:
+ self.class_variables_off()
+
+ if (options.__dict__.has_key('debug_nocolor')
+ and options.__dict__['debug_nocolor']):
+ self.color_off()
+ else:
+ self.color_on()
+
+ if (options.__dict__.has_key('debug_level') and
+ options.__dict__['debug_level']):
+ dbglvl = int(options.__dict__['debug_level'])
+ if dbglvl < 0:
+ dbglvl = 0
+ if dbglvl > 10:
+ dbglvl = 10
+ self.set_debug_level(dbglvl)
+
+ if (options.__dict__.has_key('debug_verbose') and
+ options.__dict__['debug_verbose']):
+ dbgvrb = int(options.__dict__['debug_verbose'])
+ if dbgvrb < 1:
+ dbgvrb = 1
+ if dbgvrb > 3:
+ dbgvrb = 3
+ self.set_debug_verbosity(dbgvrb)
+
+ for i in [('debug_methods', self.set_debug_methods),
+ ('debug_classes', self.set_debug_classes),
+ ('debug_variables', self.set_debug_variables),]:
+
+ if (options.__dict__.has_key(i[0]) and
+ options.__dict__[i[0]]):
+ i[1](options.__dict__[i[0]])
+
+
+ #############################################################################
+ ## Helper Functions
+
+ def set_module(self, module):
+
+ self.debug_env = module
+
+ def set_debug_methods(self, methods):
+
+ methods = methods.split(',')
+
+ if methods:
+ self.debug_mth = methods
+
+ def set_debug_classes(self, classes):
+
+ classes = classes.split(',')
+
+ if classes:
+ self.debug_obj = classes
+
+ def set_debug_variables(self, variables):
+
+ variables = variables.split(',')
+
+ if variables:
+ self.debug_var = variables
+
+ def maybe_color (self, col, text):
+ if self.use_color:
+ return codes[col] + text + codes['reset']
+ return text
+
+ def set_info_level(self, info_level = 4):
+ self.info_lev = info_level
+
+ def info_off(self):
+ self.set_info_level(0)
+
+ def info_on(self, info_level = 4):
+ self.set_info_level(info_level)
+
+ def set_warn_level(self, warn_level = 4):
+ self.warn_lev = warn_level
+
+ def warn_off(self):
+ self.set_warn_level(0)
+
+ def warn_on(self, warn_level = 4):
+ self.set_warn_level(warn_level)
+
+ def set_debug_level(self, debugging_level = 4):
+ self.debug_lev = debugging_level
+
+ def set_debug_verbosity(self, debugging_verbosity = 2):
+ self.debug_vrb = debugging_verbosity
+
+ def debug_off(self):
+ self.set_debug_level(0)
+
+ def debug_on(self):
+ self.set_debug_level()
+
+ def color_off(self):
+ self.use_color = False
+
+ def color_on(self):
+ self.use_color = True
+
+ def class_variables_off(self):
+ self.show_class_variables = False
+
+ def class_variables_on(self):
+ self.show_class_variables = True
+
+ #############################################################################
+ ## Output Functions
+
+ def notice (self, note):
+ print note
+
+ def info (self, info, level = 4):
+
+ info = str(info)
+
+ if level > self.info_lev:
+ return
+
+ for i in info.split('\n'):
+ print self.maybe_color('green', '* ') + i
+
+ def status (self, message, status, info = 'ignored'):
+
+ message = str(message)
+
+ lines = message.split('\n')
+
+ if not lines:
+ return
+
+ for i in lines[0:-1]:
+ print self.maybe_color('green', '* ') + i
+
+ i = lines[-1]
+
+ if len(i) > 58:
+ i = i[0:57]
+
+ if status == 1:
+ result = '[' + self.maybe_color('green', 'ok') + ']'
+ elif status == 0:
+ result = '[' + self.maybe_color('red', 'failed') + ']'
+ else:
+ result = '[' + self.maybe_color('yellow', info) + ']'
+
+ print self.maybe_color('green', '* ') + i + ' ' + '.' * (58 - len(i)) \
+ + ' ' + result
+
+ def warn (self, warn, level = 4):
+
+ warn = str(warn)
+
+ if level > self.warn_lev:
+ return
+
+ for i in warn.split('\n'):
+ print self.maybe_color('yellow', '* ') + i
+
+ def error (self, error):
+
+ error = str(error)
+
+ for i in error.split('\n'):
+ print >> self.error_out, self.maybe_color('red', '* ') + i
+ self.has_error = True
+
+ def die (self, error):
+
+ error = str(error)
+
+ for i in error.split('\n'):
+ self.error(self.maybe_color('red', 'Fatal error: ') + i)
+ self.error(self.maybe_color('red', 'Fatal error(s) - aborting'))
+ sys.exit(1)
+
+ def debug (self, message, level = 4):
+ '''
+ This is a generic debugging method.
+ '''
+ ## Check the debug level first. This is the most inexpensive check.
+ if level > self.debug_lev:
+ return
+
+ ## Maybe this should be debugged. So get the stack first.
+ stack = inspect.stack()
+
+ ## This can probably never happen but does not harm to check
+ ## that there is actually something calling this function
+ if len(stack) < 2:
+ return
+
+ ## Get the stack length to determine indentation of the debugging output
+ stacklength = len(stack)
+ ls = ' ' * stacklength
+
+ ## Get the information about the caller
+ caller = stack[1]
+
+ ## The function name of the calling frame is the fourth item in the list
+ callermethod = caller[3]
+
+ ## Is this actually one of the methods that should be debugged?
+ if not '*' in self.debug_mth and not callermethod in self.debug_mth:
+ return
+
+ ## Still looks like this should be debugged. So retrieve the dictionary
+ ## of local variables from the caller
+ callerlocals = inspect.getargvalues(caller[0])[3]
+
+ ## Is the caller an obejct? If so he provides 'self'
+ if 'self' in callerlocals.keys():
+ callerobject = callerlocals['self']
+ del callerlocals['self']
+ if self.show_class_variables:
+ cv = inspect.getmembers(callerobject,
+ lambda x: not inspect.ismethod(x))
+ callerlocals.sync(cv)
+ else:
+ callerobject = None
+
+ # Remove variables not requested
+ if not '*' in self.debug_var:
+ callerlocals = dict([i for i in callerlocals.items()
+ if i[0] in self.debug_var])
+
+ ## Is the object among the list of objects to debug?
+ if (not '*' in self.debug_obj and
+ not str(callerobject.__class__.__name__) in self.debug_obj):
+ return
+
+ message = str(message)
+
+ def breaklines(x):
+ '''
+ Helper function to keep width of the debugging output.
+
+ This may look ugly for arrays but it is acceptable and not
+ breaking the line would break the output format
+ '''
+ ## Get the number of lines we need (rounded down)
+ lines = len(x) // 60
+ if lines > 0:
+ for j in range(lines):
+ ## Print line with continuation marker
+ print >> self.debug_out, ls + '// ' + x[0:60] + ' \\'
+ ## Remove printed characters from output
+ x = x[60:]
+ ## Print final line
+ print >> self.debug_out, ls + '// ' + x
+
+ if self.debug_vrb == 1:
+ # Top line indicates class and method
+ c = ''
+ if callerobject:
+ c += 'Class: ' + str(callerobject.__class__.__name__) + ' | '
+ if callermethod:
+ c += 'Method: ' + str(callermethod)
+ print >> self.debug_out, '// ' + c
+ # Selected variables follow
+ if callerlocals:
+ for i,j in callerlocals.items():
+ print >> self.debug_out, '// ' \
+ + self.maybe_color('turquoise', str(i)) + ':' + str(j)
+ # Finally the message
+ print >> self.debug_out, self.maybe_color('yellow', message)
+ return
+
+ if self.debug_vrb == 3:
+ print >> self.debug_out, ls + '/////////////////////////////////' + \
+ '////////////////////////////////'
+
+ # General information about what is being debugged
+ #(module name or similar)
+ print >> self.debug_out, ls + '// ' + self.debug_env
+ print >> self.debug_out, ls + '//-----------------------------------' + \
+ '----------------------------'
+
+ ## If the caller is a class print the name here
+ if callerobject:
+ print >> self.debug_out, ls + \
+ '// Object Class: ' + str(callerobject.__class__.__name__)
+
+ ## If the method has been extracted print it here
+ if callermethod:
+ print >> self.debug_out, ls + '// ' \
+ + self.maybe_color('green', 'Method: ') + str(callermethod)
+ if self.debug_vrb == 3:
+ print >> self.debug_out, ls + '//---------------------------' + \
+ '------------------------------------'
+
+ ## Print the information on all available local variables
+ if callerlocals:
+ if self.debug_vrb == 3:
+ print >> self.debug_out, ls + '//'
+ print >> self.debug_out, ls + '// VALUES '
+ for i,j in callerlocals.items():
+ print >> self.debug_out, ls + '// ------------------> ' \
+ + self.maybe_color('turquoise', str(i)) + ':'
+ breaklines(str(j))
+ if self.debug_vrb == 3:
+ print >> self.debug_out, ls + '//------------------------------'\
+ '---------------------------------'
+
+ # Finally print the message
+ breaklines(self.maybe_color('yellow', message))
+
+ if self.debug_vrb == 3:
+ print >> self.debug_out, ls + '//-------------------------------' + \
+ '--------------------------------'
+ print >> self.debug_out, ls + '/////////////////////////////////' + \
+ '////////////////////////////////'
+
+## gloabal message handler
+OUT = Message('layman')
diff --git a/layman/overlay.py b/layman/overlay.py
new file mode 100644
index 0000000..38e9364
--- /dev/null
+++ b/layman/overlay.py
@@ -0,0 +1,247 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN OVERLAY HANDLER
+#################################################################################
+# File: overlay.py
+#
+# Access to an xml list of overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+'''Main handler for overlays.'''
+
+__version__ = "$Id: overlay.py 273 2006-12-30 15:54:50Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+import os, os.path, xml.dom.minidom
+
+from layman.overlays.bzr import BzrOverlay
+from layman.overlays.darcs import DarcsOverlay
+from layman.overlays.git import GitOverlay
+from layman.overlays.mercurial import MercurialOverlay
+from layman.overlays.cvs import CvsOverlay
+from layman.overlays.svn import SvnOverlay
+from layman.overlays.rsync import RsyncOverlay
+from layman.overlays.tar import TarOverlay
+
+from layman.debug import OUT
+
+#===============================================================================
+#
+# Constants
+#
+#-------------------------------------------------------------------------------
+
+OVERLAY_TYPES = {'git' : GitOverlay,
+ 'cvs' : CvsOverlay,
+ 'svn' : SvnOverlay,
+ 'rsync' : RsyncOverlay,
+ 'tar' : TarOverlay,
+ 'bzr' : BzrOverlay,
+ 'mercurial' : MercurialOverlay,
+ 'darcs' : DarcsOverlay}
+
+#===============================================================================
+#
+# Class Overlays
+#
+#-------------------------------------------------------------------------------
+
+class Overlays:
+ ''' Handle a list of overlays.'''
+
+ def __init__(self, paths, ignore = 0, quiet = False):
+
+ self.quiet = quiet
+ self.paths = paths
+ self.ignore = ignore
+
+ self.overlays = {}
+
+ OUT.debug('Initializing overlay list handler', 8)
+
+ for path in self.paths:
+ if os.path.exists(path):
+ self.read_file(path)
+
+ def read_file(self, path):
+ '''Read the overlay definition file.'''
+
+ try:
+
+ document = open(path).read()
+
+ except Exception, error:
+ raise IOError('Failed to read the overlay list at ("'
+ + path + '")!\nError was:\n' + str(error))
+
+
+ self.read(document)
+
+ def read(self, document):
+ '''
+ Read an xml list of overlays.
+
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+
+ >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ])
+ >>> a.overlays.keys()
+ [u'wrobel', u'wrobel-stable']
+
+ >>> a.overlays['wrobel-stable'].data['&src']
+ u'rsync://gunnarwrobel.de/wrobel-stable'
+ '''
+ try:
+
+ document = xml.dom.minidom.parseString(document)
+
+ except Exception, error:
+ raise Exception('Failed to parse the overlay list!\nError was:\n'
+ + str(error))
+
+ overlays = document.getElementsByTagName('overlay')
+
+ for overlay in overlays:
+
+ OUT.debug('Parsing overlay entry', 8)
+
+ for index in range(0, overlay.attributes.length):
+ attr = overlay.attributes.item(index)
+ if attr.name == 'type':
+ if attr.nodeValue in OVERLAY_TYPES.keys():
+ try:
+ ovl = OVERLAY_TYPES[attr.nodeValue](overlay,
+ self.ignore,
+ self.quiet)
+ self.overlays[ovl.name] = ovl
+ except Exception, error:
+ OUT.warn(str(error), 3)
+ else:
+ raise Exception('Unknown overlay type "' +
+ attr.nodeValue + '"!')
+
+ def write(self, path):
+ '''
+ Write the list of overlays to a file.
+
+ >>> write = os.tmpnam()
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+
+ >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ])
+ >>> b = Overlays([write,])
+ >>> b.overlays['wrobel-stable'] = a.overlays['wrobel-stable']
+ >>> b.write(write)
+ >>> c = Overlays([write,])
+ >>> c.overlays.keys()
+ [u'wrobel-stable']
+
+ >>> os.unlink(write)
+ '''
+
+ imp = xml.dom.minidom.getDOMImplementation()
+
+ doc = imp.createDocument('layman', 'overlays', None)
+
+ root = doc.childNodes[0]
+
+ for name, overlay in self.overlays.items():
+
+ root.appendChild(overlay.to_minidom(doc))
+
+ try:
+
+ out_file = open(path, 'w')
+
+ doc.writexml(out_file, '', ' ', '\n')
+
+ except Exception, error:
+ raise Exception('Failed to write to local overlays file: '
+ + path + '\nError was:\n' + str(error))
+
+ def select(self, overlay):
+ '''
+ Select an overlay from the list.
+
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ])
+ >>> a.select('wrobel-stable').data['&src']
+ u'rsync://gunnarwrobel.de/wrobel-stable'
+ '''
+
+ if overlay in self.overlays.keys():
+ return self.overlays[overlay]
+
+ def list(self, verbose = False):
+ '''
+ List all overlays.
+
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ])
+ >>> for i in a.list(True):
+ ... print i[0]
+ wrobel
+ ~~~~~~
+ Source : https://overlays.gentoo.org/svn/dev/wrobel
+ Contact : nobody@gentoo.org
+ Type : Subversion; Priority: 10
+ <BLANKLINE>
+ Description:
+ Test
+ <BLANKLINE>
+ wrobel-stable
+ ~~~~~~~~~~~~~
+ Source : rsync://gunnarwrobel.de/wrobel-stable
+ Contact : nobody@gentoo.org
+ Type : Rsync; Priority: 50
+ <BLANKLINE>
+ Description:
+ A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org].
+ <BLANKLINE>
+
+ >>> for i in a.list(False):
+ ... print i[0]
+ wrobel [Subversion] (source: https://overlays.gentoo.or...)
+ wrobel-stable [Rsync ] (source: rsync://gunnarwrobel.de/wr...)
+ '''
+ result = []
+
+ for name, overlay in self.overlays.items():
+
+ if verbose:
+ result.append((str(overlay), overlay.is_supported(),
+ overlay.is_official()))
+ else:
+ result.append((overlay.short_list(), overlay.is_supported(),
+ overlay.is_official()))
+
+ result = sorted(result)
+
+ return result
+
+#===============================================================================
+#
+# Testing
+#
+#-------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ import doctest, sys
+
+ # Ignore warnings here. We are just testing
+ from warnings import filterwarnings, resetwarnings
+ filterwarnings('ignore')
+
+ doctest.testmod(sys.modules[__name__])
+
+ resetwarnings()
diff --git a/layman/overlays/.svn.ignore b/layman/overlays/.svn.ignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/layman/overlays/.svn.ignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/layman/overlays/__init__.py b/layman/overlays/__init__.py
new file mode 100644
index 0000000..792d600
--- /dev/null
+++ b/layman/overlays/__init__.py
@@ -0,0 +1 @@
+#
diff --git a/layman/overlays/bzr.py b/layman/overlays/bzr.py
new file mode 100644
index 0000000..8e8bb47
--- /dev/null
+++ b/layman/overlays/bzr.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN BZR OVERLAY HANDLER
+#################################################################################
+# File: bzr.py
+#
+# Handles bzr overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Adrian Perez, Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Adrian Perez <moebius@connectical.net>
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+'''Should work with any version of Bzr equal to or better than 0.7 --
+ caution: tested only with 0.8 and 0.8.2...'''
+
+__version__ = "$Id: bzr.py 236 2006-09-05 20:39:37Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+from layman.utils import path
+from layman.overlays.overlay import Overlay
+
+#===============================================================================
+#
+# Class BzrOverlay
+#
+#-------------------------------------------------------------------------------
+
+class BzrOverlay(Overlay):
+ ''' Handles bzr overlays.'''
+
+ type = 'Bzr'
+
+ binary_command = '/usr/bin/bzr'
+
+ def add(self, base):
+ '''Add overlay.'''
+
+ self.supported()
+
+ return self.cmd(self.binary_command + ' get "' + self.src + '/" "' +\
+ path([base, self.name]) + '"')
+
+ def sync(self, base):
+ '''Sync overlay.'''
+
+ self.supported()
+
+ return self.cmd('cd "' + path([base, self.name]) + '" && ' + \
+ self.binary_command + ' pull --overwrite "' + self.src \
+ + '"')
+
+ def supported(self):
+ '''Overlay type supported?'''
+
+ return Overlay.supported(self, [(self.binary_command, 'bzr',
+ 'dev-util/bzr'),])
diff --git a/layman/overlays/cvs.py b/layman/overlays/cvs.py
new file mode 100644
index 0000000..95f20ea
--- /dev/null
+++ b/layman/overlays/cvs.py
@@ -0,0 +1,73 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN CVS OVERLAY HANDLER
+#################################################################################
+# File: cvs.py
+#
+# Handles cvs overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+''' Cvs overlay support.'''
+
+__version__ = "$Id$"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+from layman.utils import path
+from layman.overlays.overlay import Overlay
+
+#===============================================================================
+#
+# Class CvsOverlay
+#
+#-------------------------------------------------------------------------------
+
+class CvsOverlay(Overlay):
+ ''' Handles cvs overlays.'''
+
+ type = 'cvs'
+
+ binary = '/usr/bin/cvs'
+
+ def __init__(self, xml, ignore = 0, quiet = False):
+
+ Overlay.__init__(self, xml, ignore, quiet)
+
+ if '&subpath' in self.data.keys():
+ self.subpath = self.data['&subpath']
+ else:
+ self.subpath = ''
+
+ def add(self, base):
+ '''Add overlay.'''
+
+ self.supported()
+
+ return self.cmd('cd "' + base + '" && CVSROOT="' + self.src + '" ' +
+ self.binary + ' co -d "' + self.name
+ + '" "' + self.subpath + '"' )
+
+ def sync(self, base):
+ '''Sync overlay.'''
+
+ self.supported()
+
+ return self.cmd('cd "' + path([base, self.name]) + '" && ' +
+ self.binary + ' update')
+
+ def supported(self):
+ '''Overlay type supported?'''
+
+ return Overlay.supported(self, [(self.binary, 'cvs',
+ 'dev-util/cvs'),])
diff --git a/layman/overlays/darcs.py b/layman/overlays/darcs.py
new file mode 100644
index 0000000..56e6d91
--- /dev/null
+++ b/layman/overlays/darcs.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN DARCS OVERLAY HANDLER
+#################################################################################
+# File: darcs.py
+#
+# Handles darcs overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel, Andres Loeh
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+# Andres Loeh <kosmikus@gentoo.org>
+#
+''' Darcs overlay support.'''
+
+__version__ = "$Id: darcs.py 236 2006-09-05 20:39:37Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+from layman.utils import path
+from layman.overlays.overlay import Overlay
+
+#===============================================================================
+#
+# Class BzrOverlay
+#
+#-------------------------------------------------------------------------------
+
+class DarcsOverlay(Overlay):
+ ''' Handles darcs overlays.'''
+
+ type = 'Darcs'
+
+ binary_command = '/usr/bin/darcs'
+
+ def add(self, base):
+ '''Add overlay.'''
+
+ self.supported()
+
+ return self.cmd(self.binary_command + ' get --partial "' + self.src +
+ '/" "' + path([base, self.name]) + '"')
+
+ def sync(self, base):
+ '''Sync overlay.'''
+
+ self.supported()
+
+ return self.cmd('cd "' + path([base, self.name]) + '" && ' +
+ self.binary_command + ' pull --all "' + self.src + '"')
+
+ def supported(self):
+ '''Overlay type supported?'''
+
+ return Overlay.supported(self, [(self.binary_command, 'darcs',
+ 'dev-util/darcs'),])
diff --git a/layman/overlays/git.py b/layman/overlays/git.py
new file mode 100644
index 0000000..007e841
--- /dev/null
+++ b/layman/overlays/git.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN GIT OVERLAY HANDLER
+#################################################################################
+# File: git.py
+#
+# Handles git overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel, Stefan Schweizer
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+# Stefan Schweizer <genstef@gentoo.org>
+''' Git overlay support.'''
+
+__version__ = "$Id: git.py 146 2006-05-27 09:52:36Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+from layman.utils import path
+from layman.overlays.overlay import Overlay
+
+#===============================================================================
+#
+# Class GitOverlay
+#
+#-------------------------------------------------------------------------------
+
+class GitOverlay(Overlay):
+ ''' Handles git overlays.'''
+
+ type = 'Git'
+
+ binary_command = '/usr/bin/git'
+
+ def add(self, base):
+ '''Add overlay.'''
+
+ self.supported()
+
+ return self.cmd(self.binary_command + ' clone "' + self.src + '/" "'
+ + path([base, self.name]) + '"')
+
+ def sync(self, base):
+ '''Sync overlay.'''
+
+ self.supported()
+
+ return self.cmd('cd "' + path([base, self.name]) + '" && '
+ + self.binary_command + ' pull')
+
+ def supported(self):
+ '''Overlay type supported?'''
+
+ return Overlay.supported(self, [(self.binary_command, 'git',
+ 'dev-util/git'),])
diff --git a/layman/overlays/mercurial.py b/layman/overlays/mercurial.py
new file mode 100644
index 0000000..3def5fc
--- /dev/null
+++ b/layman/overlays/mercurial.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN MERCURIAL OVERLAY HANDLER
+#################################################################################
+# File: darcs.py
+#
+# Handles darcs overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel, Andres Loeh
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+# Andres Loeh <kosmikus@gentoo.org>
+#
+''' Mercurial overlay support.'''
+
+__version__ = "$Id: mercurial.py 236 2006-09-05 20:39:37Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+from layman.utils import path
+from layman.overlays.overlay import Overlay
+
+#===============================================================================
+#
+# Class MercurialOverlay
+#
+#-------------------------------------------------------------------------------
+
+class MercurialOverlay(Overlay):
+ ''' Handles mercurial overlays.'''
+
+ type = 'Mercurial'
+
+ binary_command = '/usr/bin/hg'
+
+ def add(self, base):
+ '''Add overlay.'''
+
+ self.supported()
+
+ return self.cmd(self.binary_command + ' clone "' + self.src + '/" "' +
+ path([base, self.name]) + '"')
+
+ def sync(self, base):
+ '''Sync overlay.'''
+
+ self.supported()
+
+ return self.cmd('cd "' + path([base, self.name]) + '" && ' +
+ self.binary_command + ' pull -u "' + self.src + '"')
+
+ def supported(self):
+ '''Overlay type supported?'''
+
+ return Overlay.supported(self, [(self.binary_command, 'mercurial',
+ 'dev-util/mercurial'),])
diff --git a/layman/overlays/overlay.py b/layman/overlays/overlay.py
new file mode 100644
index 0000000..b7a006f
--- /dev/null
+++ b/layman/overlays/overlay.py
@@ -0,0 +1,266 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN OVERLAY BASE CLASS
+#################################################################################
+# File: overlay.py
+#
+# Base class for the different overlay types.
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+''' Basic overlay class.'''
+
+__version__ = "$Id: overlay.py 273 2006-12-30 15:54:50Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+import re, os, os.path, shutil, popen2
+
+from layman.utils import node_to_dict, dict_to_node, path
+
+from layman.debug import OUT
+
+#===============================================================================
+#
+# Class Overlay
+#
+#-------------------------------------------------------------------------------
+
+class Overlay:
+ ''' Derive the real implementations from this.'''
+
+ type = 'None'
+
+ def __init__(self, xml, ignore = 0, quiet = False):
+ '''
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read()
+ >>> import xml.dom.minidom
+ >>> document = xml.dom.minidom.parseString(document)
+ >>> overlays = document.getElementsByTagName('overlay')
+ >>> a = Overlay(overlays[0])
+ >>> a.name
+ u'wrobel'
+ >>> a.is_official()
+ True
+ >>> a.src
+ u'https://overlays.gentoo.org/svn/dev/wrobel'
+ >>> a.contact
+ u'nobody@gentoo.org'
+ >>> a.description
+ u'Test'
+ >>> a.priority
+ 10
+ >>> b = Overlay(overlays[1])
+ >>> b.is_official()
+ False
+ '''
+ self.quiet = quiet
+
+ self.data = node_to_dict(xml)
+
+ if '&name' in self.data.keys():
+ self.name = self.data['&name']
+ else:
+ raise Exception('Overlay is missing a "name" attribute!')
+
+ if '&src' in self.data.keys():
+ self.src = self.data['&src']
+ else:
+ raise Exception('Overlay "' + self.name + '" is missing a "src" '
+ 'attribute!')
+
+ if '&contact' in self.data.keys():
+ self.contact = self.data['&contact']
+ else:
+ self.contact = ''
+ if not ignore:
+ raise Exception('Overlay "' + self.name + '" is missing a '
+ '"contact" attribute!')
+ elif ignore == 1:
+ OUT.warn('Overlay "' + self.name + '" is missing a '
+ '"contact" attribute!', 4)
+
+ if '<description>1' in self.data.keys():
+ self.description = self.data['<description>1']['@'].strip()
+ else:
+ self.description = ''
+ if not ignore:
+ raise Exception('Overlay "' + self.name + '" is missing a '
+ '"description" entry!')
+ elif ignore == 1:
+ OUT.warn('Overlay "' + self.name + '" is missing a '
+ '"description" entry!', 4)
+
+ if '&status' in self.data.keys():
+ self.status = self.data['&status']
+ else:
+ self.status = ''
+
+ if '&priority' in self.data.keys():
+ self.priority = int(self.data['&priority'])
+ else:
+ self.priority = 50
+
+ def to_minidom(self, document):
+ '''Convert to xml.'''
+
+ return dict_to_node(self.data, document, 'overlay')
+
+ def add(self, base):
+ '''Add the overlay.'''
+
+ mdir = path([base, self.name])
+
+ if os.path.exists(mdir):
+ raise Exception('Directory ' + mdir + ' already exists. Will not ov'
+ 'erwrite its contents!')
+
+ os.makedirs(mdir)
+
+ def sync(self, base):
+ '''Sync the overlay.'''
+ pass
+
+ def delete(self, base):
+ '''Delete the overlay.'''
+ mdir = path([base, self.name])
+
+ if not os.path.exists(mdir):
+ raise Exception('Directory ' + mdir + ' does not exist. Cannot remo'
+ 've the overlay!')
+
+ shutil.rmtree(mdir)
+
+ def cmd(self, command):
+ '''Run a command.'''
+
+ OUT.info('Running command "' + command + '"...', 2)
+
+ if not self.quiet:
+ return os.system(command)
+ else:
+ cmd = popen2.Popen4(command)
+ cmd.fromchild.readlines()
+ result = cmd.wait()
+ cmd.fromchild.readlines()
+ cmd.fromchild.close()
+ cmd.tochild.close()
+ return result
+
+ def __str__(self):
+ '''
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read()
+ >>> import xml.dom.minidom
+ >>> document = xml.dom.minidom.parseString(document)
+ >>> overlays = document.getElementsByTagName('overlay')
+ >>> a = Overlay(overlays[0])
+ >>> print str(a)
+ wrobel
+ ~~~~~~
+ Source : https://overlays.gentoo.org/svn/dev/wrobel
+ Contact : nobody@gentoo.org
+ Type : None; Priority: 10
+ <BLANKLINE>
+ Description:
+ Test
+ <BLANKLINE>
+ '''
+
+ result = ''
+
+ result += self.name + '\n' + (len(self.name) * '~')
+
+ result += '\nSource : ' + self.src
+ result += '\nContact : ' + self.contact
+ result += '\nType : ' + self.type
+ result += '; Priority: ' + str(self.priority) + '\n'
+
+ description = self.description
+ description = re.compile(' +').sub(' ', description)
+ description = re.compile('\n ').sub('\n', description)
+ result += '\nDescription:'
+ result += '\n '.join(('\n' + description).split('\n'))
+ result += '\n'
+
+ if '<link>1' in self.data.keys():
+ link = self.data['<link>1']['@'].strip()
+ link = re.compile(' +').sub(' ', link)
+ link = re.compile('\n ').sub('\n', link)
+ result += '\nLink:\n'
+ result += '\n '.join(('\n' + link).split('\n'))
+ result += '\n'
+
+ return result
+
+ def short_list(self):
+ '''
+ >>> here = os.path.dirname(os.path.realpath(__file__))
+ >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read()
+ >>> import xml.dom.minidom
+ >>> document = xml.dom.minidom.parseString(document)
+ >>> overlays = document.getElementsByTagName('overlay')
+ >>> a = Overlay(overlays[0])
+ >>> print a.short_list()
+ wrobel [None ] (source: https://overlays.gentoo.or...)
+ '''
+
+ def pad(string, length):
+ '''Pad a string with spaces.'''
+ if len(string) <= length:
+ return string + ' ' * (length - len(string))
+ else:
+ return string[:length - 3] + '...'
+
+ name = pad(self.name, 25)
+ mtype = ' [' + pad(self.type, 10) + ']'
+ source = ' (source: ' + pad(self.src, 29) + ')'
+
+ return name + mtype + source
+
+ def supported(self, binaries = []):
+ '''Is the overlay type supported?'''
+
+ if binaries:
+ for mpath, mtype, package in binaries:
+ if not os.path.exists(mpath):
+ raise Exception('Binary ' + mpath + ' seems to be missing!'
+ ' Overlay type "' + mtype + '" not support'
+ 'ed. Did you emerge ' + package + '?')
+
+ return True
+
+ def is_supported(self):
+ '''Is the overlay type supported?'''
+
+ try:
+ self.supported()
+ return True
+ except Exception, error:
+ return False
+
+ def is_official(self):
+ '''Is the overlay official?'''
+
+ return self.status == 'official'
+
+#================================================================================
+#
+# Testing
+#
+#--------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ import doctest, sys
+ doctest.testmod(sys.modules[__name__])
diff --git a/layman/overlays/rsync.py b/layman/overlays/rsync.py
new file mode 100644
index 0000000..e2483ad
--- /dev/null
+++ b/layman/overlays/rsync.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN RSYNC OVERLAY HANDLER
+#################################################################################
+# File: rsync.py
+#
+# Handles rsync overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+''' Rsync overlay support.'''
+
+__version__ = "$Id: rsync.py 236 2006-09-05 20:39:37Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+from layman.utils import path
+from layman.overlays.overlay import Overlay
+
+#===============================================================================
+#
+# Class RsyncOverlay
+#
+#-------------------------------------------------------------------------------
+
+class RsyncOverlay(Overlay):
+ ''' Handles rsync overlays.'''
+
+ type = 'Rsync'
+
+ binary = '/usr/bin/rsync'
+
+ base = binary + ' -rlptDvz --progress --delete --delete-after ' + \
+ '--timeout=180 --exclude="distfiles/*" --exclude="local/*" ' + \
+ '--exclude="packages/*" '
+
+ def add(self, base):
+ '''Add overlay.'''
+
+ self.supported()
+
+ Overlay.add(self, base)
+
+ return self.sync(base)
+
+ def sync(self, base):
+ '''Sync overlay.'''
+
+ self.supported()
+
+ return self.cmd(self.base + '"' + self.src + '/*" "' +
+ path([base, self.name]) + '"')
+
+ def supported(self):
+ '''Overlay type supported?'''
+
+ return Overlay.supported(self, [(self.binary, 'rsync',
+ 'net-misc/rsync'),])
diff --git a/layman/overlays/svn.py b/layman/overlays/svn.py
new file mode 100644
index 0000000..5086448
--- /dev/null
+++ b/layman/overlays/svn.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN SVN OVERLAY HANDLER
+#################################################################################
+# File: svn.py
+#
+# Handles subversion overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+''' Subversion overlay support.'''
+
+__version__ = "$Id: svn.py 236 2006-09-05 20:39:37Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+from layman.utils import path
+from layman.overlays.overlay import Overlay
+
+#===============================================================================
+#
+# Class SvnOverlay
+#
+#-------------------------------------------------------------------------------
+
+class SvnOverlay(Overlay):
+ ''' Handles subversion overlays.'''
+
+ type = 'Subversion'
+
+ binary = '/usr/bin/svn'
+
+ def add(self, base):
+ '''Add overlay.'''
+
+ self.supported()
+
+ Overlay.add(self, base)
+
+ return self.cmd(self.binary + ' co "' + self.src + '/" "' +
+ path([base, self.name]) + '"')
+
+ def sync(self, base):
+ '''Sync overlay.'''
+
+ self.supported()
+
+ return self.cmd(self.binary + ' update "' + path([base, self.name]) +
+ '"')
+
+ def supported(self):
+ '''Overlay type supported?'''
+
+ return Overlay.supported(self, [(self.binary, 'svn',
+ 'dev-util/subversion'),])
diff --git a/layman/overlays/tar.py b/layman/overlays/tar.py
new file mode 100644
index 0000000..24a9b91
--- /dev/null
+++ b/layman/overlays/tar.py
@@ -0,0 +1,189 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN TAR OVERLAY HANDLER
+#################################################################################
+# File: tar.py
+#
+# Handles tar overlays
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+''' Tar overlay support.'''
+
+__version__ = "$Id: tar.py 310 2007-04-09 16:30:40Z wrobel $"
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+import os, os.path, sys, urllib2, shutil
+
+from layman.utils import path
+from layman.overlays.overlay import Overlay
+
+#===============================================================================
+#
+# Class TarOverlay
+#
+#-------------------------------------------------------------------------------
+
+class TarOverlay(Overlay):
+ ''' Handles tar overlays.
+
+ A dummy tar handler that overwrites the __init__ method
+ so that we don't need to provide xml input:
+
+ >>> from layman.debug import OUT
+ >>> class DummyTar(TarOverlay):
+ ... def __init__(self):
+ ... self.name = 'dummy'
+ ... here = os.path.dirname(os.path.realpath(__file__))
+ ... self.src = 'file://' + here + '/../tests/testfiles/layman-test.tar.bz2'
+ ... self.subpath = 'layman-test'
+ ... self.format = 'bz2'
+ ... self.quiet = False
+ >>> testdir = os.tmpnam()
+ >>> os.mkdir(testdir)
+ >>> a = DummyTar()
+ >>> OUT.color_off()
+ >>> a.add(testdir) #doctest: +ELLIPSIS
+ * Running command "/bin/tar -v -x -j -f...
+ >>> sorted(os.listdir(testdir + '/dummy'))
+ ['app-admin', 'app-portage']
+ >>> shutil.rmtree(testdir)
+ '''
+
+ type = 'Tar'
+
+ binary = '/bin/tar'
+
+ def __init__(self, xml, ignore = 0, quiet = False):
+
+ Overlay.__init__(self, xml, ignore)
+
+ if '&format' in self.data.keys():
+ self.format = self.data['&format']
+ else:
+ self.format = ''
+
+ if '&subpath' in self.data.keys():
+ self.subpath = self.data['&subpath']
+ else:
+ self.subpath = ''
+
+ if '&category' in self.data.keys():
+ if self.subpath:
+ raise Exception('Cannot use "category" and "subpath" at the same'
+ ' time!')
+
+ self.category = self.data['&category']
+ else:
+ self.category = ''
+
+ def add(self, base):
+ '''Add overlay.'''
+
+ self.supported()
+
+ mdir = path([base, self.name])
+
+ if os.path.exists(mdir):
+ raise Exception('Directory ' + mdir + ' already exists. Will not ov'
+ 'erwrite its contents!')
+
+ if self.format == 'bz2' or (not self.format and self.src[-3:] == 'bz2'):
+ ext = 'bz2'
+ opt = '-j'
+ elif self.format == 'gz' or (not self.format and self.src[-2:] == 'gz'):
+ ext = 'gz'
+ opt = '-z'
+ else:
+ raise Exception('Unsupported file format!')
+
+ try:
+
+ tar = urllib2.urlopen(self.src).read()
+
+ except Exception, error:
+ raise Exception('Failed to fetch the tar package from: '
+ + self.src + '\nError was:' + str(error))
+
+ pkg = path([base, self.name + '.tar.' + ext])
+
+ try:
+
+ out_file = open(pkg, 'w')
+ out_file.write(tar)
+ out_file.close()
+
+ except Exception, error:
+ raise Exception('Failed to store tar package in '
+ + pkg + '\nError was:' + str(error))
+
+ if self.subpath:
+ target = path([base, 'tmp'])
+ else:
+ if self.category:
+ target = mdir + '/' + self.category
+ else:
+ target = mdir
+
+ os.makedirs(target)
+
+ result = self.cmd(self.binary + ' -v -x ' + opt + ' -f "' + pkg
+ + '" -C "' + target + '"')
+
+ if self.subpath:
+ source = target + '/' + self.subpath
+ if os.path.exists(source):
+ try:
+ os.rename(source, mdir)
+ except Exception, error:
+ raise Exception('Failed to rename tar subdirectory ' +
+ source + ' to ' + mdir + '\nError was:'
+ + str(error))
+ else:
+ raise Exception('Given subpath "' + source + '" does not exist '
+ ' in the tar package!')
+ try:
+ shutil.rmtree(target)
+ except Exception, error:
+ raise Exception('Failed to remove unnecessary tar structure "'
+ + target + '"\nError was:' + str(error))
+
+ os.unlink(pkg)
+
+ return result
+
+ def sync(self, base):
+ '''Sync overlay.'''
+
+ self.supported()
+
+ self.delete(base)
+
+ self.add(base)
+
+ def supported(self):
+ '''Overlay type supported?'''
+
+ return Overlay.supported(self, [(self.binary, 'tar', 'app-arch/tar'), ])
+
+if __name__ == '__main__':
+ import doctest
+
+ # Ignore warnings here. We are just testing
+ from warnings import filterwarnings, resetwarnings
+ filterwarnings('ignore')
+
+ doctest.testmod(sys.modules[__name__])
+
+ resetwarnings()
diff --git a/layman/tests/dtest.py b/layman/tests/dtest.py
new file mode 100644
index 0000000..8f65af1
--- /dev/null
+++ b/layman/tests/dtest.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN DOCTEST AGGREGATOR
+#################################################################################
+# File: dtest.py
+#
+# Combines the doctests that are available for the different modules
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+'''Aggregates doctests from all modules that provide such tests.'''
+
+__version__ = '$Id: dtest.py 237 2006-09-05 21:18:54Z wrobel $'
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+import unittest, doctest, sys
+
+# On module creation:
+
+# 1.) Check header section (copyright notice)
+# 2.) Add module doc string
+# 3.) Add version string
+# 4.) Add testing handler at bottom of module
+# 5.) Add module into tests/dtest.py. Check that tests run through
+# 6.) Run pylint over the code. Fix any reasonable complaints.
+# 7.) Whitespace clean the buffer.
+# 8.) Add svn:keywords "Id" to file.
+
+# On module change:
+
+# 1.) Check header section (copyright notice)
+# 5.) Check that tests run through
+# 6.) Run pylint over the code. Fix any reasonable complaints.
+# 7.) Whitespace clean the buffer.
+
+# clean modules : CT
+# not yet clean : UT
+# clean but no testing : CN
+# unclean but no testing: UN
+
+import layman.action #CT
+import layman.config #CT
+import layman.db #CT
+import layman.overlay #CT
+import layman.utils #CT
+import layman.overlays.overlay #CT
+import layman.overlays.tar #CT
+
+#===============================================================================
+#
+# Test Suite
+#
+#-------------------------------------------------------------------------------
+
+def test_suite():
+ return unittest.TestSuite((
+ doctest.DocTestSuite(layman.action),
+ doctest.DocTestSuite(layman.config),
+ doctest.DocTestSuite(layman.db),
+ doctest.DocTestSuite(layman.overlay),
+ doctest.DocTestSuite(layman.utils),
+ doctest.DocTestSuite(layman.overlays.overlay),
+ doctest.DocTestSuite(layman.overlays.tar),
+ ))
+
+#===============================================================================
+#
+# Run Testing
+#
+#-------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ # Ignore warnings here. We are just testing
+ from warnings import filterwarnings, resetwarnings
+ filterwarnings('ignore')
+
+ unittest.main(defaultTest='test_suite')
+
+ resetwarnings()
diff --git a/layman/tests/testfiles/global-overlays.xml b/layman/tests/testfiles/global-overlays.xml
new file mode 100644
index 0000000..d770692
--- /dev/null
+++ b/layman/tests/testfiles/global-overlays.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" ?>
+<layman>
+
+ <overlay
+ type = "svn"
+ src = "https://overlays.gentoo.org/svn/dev/wrobel"
+ contact = "nobody@gentoo.org"
+ name = "wrobel"
+ status = "official"
+ priority = "10">
+
+ <description>
+ Test
+ </description>
+
+ </overlay>
+
+ <overlay
+ type = "rsync"
+ src = "rsync://gunnarwrobel.de/wrobel-stable"
+ contact = "nobody@gentoo.org"
+ name = "wrobel-stable">
+
+ <description>
+ A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org].
+ </description>
+
+ </overlay>
+
+</layman>
diff --git a/layman/tests/testfiles/layman-test.tar.bz2 b/layman/tests/testfiles/layman-test.tar.bz2
new file mode 100644
index 0000000..85ee7fd
--- /dev/null
+++ b/layman/tests/testfiles/layman-test.tar.bz2
Binary files differ
diff --git a/layman/tests/testfiles/make.conf b/layman/tests/testfiles/make.conf
new file mode 100644
index 0000000..d32dd16
--- /dev/null
+++ b/layman/tests/testfiles/make.conf
@@ -0,0 +1,345 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.x86,v 1.5.2.5 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+
+# Use flags will be handled by polymeraZe
+USE="-*"
+
+# Host Setting
+# ============
+#
+# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
+# Change this line as appropriate (i686, i586, i486 or i386).
+# All modern systems (even Athlons) should use "i686-pc-linux-gnu".
+# All K6's are i586.
+CHOST="i686-pc-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
+# breaking compatibility with other CPUs.
+#
+# -march=<cpu-type> means to take full advantage of the ABI and instructions
+# for the particular CPU; this will break compatibility with older CPUs (for
+# example, -march=athlon-xp code will not run on a regular Athlon, and
+# -march=i686 code will not run on a Pentium Classic.
+#
+# CPU types supported in gcc-3.2 and higher: athlon-xp, athlon-mp,
+# athlon-tbird, athlon, k6, k6-2, k6-3, i386, i486, i586 (Pentium), i686
+# (PentiumPro), pentium, pentium-mmx, pentiumpro, pentium2 (Celeron),
+# pentium3, and pentium4.
+#
+# Note that Gentoo Linux 1.4 and higher include at least gcc-3.2.
+#
+# CPU types supported in gcc-2.95*: k6, i386, i486, i586 (Pentium), i686
+# (Pentium Pro), pentium, pentiumpro Gentoo Linux 1.2 and below use gcc-2.95*
+#
+# CRITICAL WARNINGS: ****************************************************** #
+# K6 markings are deceptive. Avoid setting -march for them. See Bug #24379. #
+# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
+# ************************************************************************* #
+#
+# Decent examples:
+#
+#CFLAGS="-mcpu=athlon-xp -O3 -pipe"
+
+CFLAGS="-march=athlon-xp -O3 -pipe"
+
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+
+ACCEPT_KEYWORDS="x86"
+
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+DISTDIR=/usr/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+PORT_LOGDIR=/var/log/services/portage.d
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+PORTDIR_OVERLAY="
+/usr/portage/local/layman/wrobel-stable
+$PORTDIR_OVERLAY
+/usr/portage/local/ebuilds/testing
+/usr/portage/local/ebuilds/stable
+/usr/portage/local/kolab2
+/usr/portage/local/gentoo-webapps-overlay/experimental
+/usr/portage/local/gentoo-webapps-overlay/production-ready"
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+
+FETCHCOMMAND="/usr/bin/getdelta.sh \${URI}"
+
+
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+
+GENTOO_MIRRORS="http://pandemonium.tiscali.de/pub/gentoo/ ftp://pandemonium.tiscali.de/pub/gentoo/ ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/gentoo/ http://mir.zyrianes.net/gentoo/ http://ftp.snt.utwente.nl/pub/os/linux/gentoo http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+
+SYNC="rsync://rsync.europe.gentoo.org/gentoo-portage"
+
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+FEATURES="sandbox ccache userprivs distlocks cvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+CCACHE_SIZE="1G"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
+EBEEP_IGNORE=yes
+
+CONFIG_PROTECT_MASK="/usr/X11R6/lib/X11"
+
+
diff --git a/layman/utils.py b/layman/utils.py
new file mode 100644
index 0000000..239f1b3
--- /dev/null
+++ b/layman/utils.py
@@ -0,0 +1,208 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# POLYMERAZE XML UTILITIES
+#################################################################################
+# File: xml.py
+#
+# Utilities to deal with xml nodes.
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+
+'''Utility functions to deal with xml nodes. '''
+
+__version__ = '$Id: utils.py 236 2006-09-05 20:39:37Z wrobel $'
+
+#===============================================================================
+#
+# Dependencies
+#
+#-------------------------------------------------------------------------------
+
+import types, re
+
+#===============================================================================
+#
+# Helper functions
+#
+#-------------------------------------------------------------------------------
+
+def node_to_text(node):
+ '''
+ Reduces an xml node to its text elements. The function does not
+ collect the text nodes recursively.
+
+ >>> import xml.dom.minidom
+ >>> imp = xml.dom.minidom.getDOMImplementation()
+ >>> doc = imp.createDocument('test', 'root', None)
+ >>> root = doc.childNodes[0]
+ >>> node = doc.createTextNode('text')
+ >>> a = root.appendChild(node)
+ >>> node = doc.createElement('text')
+ >>> node2 = doc.createTextNode('text')
+ >>> a = node.appendChild(node2)
+ >>> a = root.appendChild(node)
+ >>> node = doc.createTextNode('text')
+ >>> a = root.appendChild(node)
+ >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS
+ '<?xml version="1.0" ?>...<root>text<text>text</text>text</root>'
+
+ >>> node_to_text(root)
+ 'texttext'
+
+ '''
+ text = ''
+
+ for child in node.childNodes:
+ if child.nodeType == child.TEXT_NODE:
+ text = text + child.data
+
+ return text
+
+def node_to_dict(node):
+ ''' Converts a xml node to a dictionary. The function collects the
+ nodes recursively. Attributes will be prepended with '&', child
+ nodes will be surrounded with tags. An index will be appended
+ since several child nodes with the same tag may exist. Text
+ elements will be collapsed and stored in a n entry prepended with
+ '@'. Comments will be ignored.
+
+ >>> import xml.dom.minidom
+ >>> imp = xml.dom.minidom.getDOMImplementation()
+ >>> doc = imp.createDocument('test', 'root', None)
+ >>> root = doc.childNodes[0]
+ >>> node = doc.createTextNode('text')
+ >>> a = root.appendChild(node)
+ >>> node = doc.createElement('text')
+ >>> node2 = doc.createTextNode('text')
+ >>> comm = doc.createComment('comment')
+ >>> attr = doc.createAttribute('&attr')
+ >>> a = node.appendChild(node2)
+ >>> a = root.appendChild(comm)
+ >>> node.setAttributeNode(attr)
+ >>> node.setAttribute('&attr','test')
+ >>> a = root.appendChild(node)
+ >>> node3 = doc.createElement('text')
+ >>> a = root.appendChild(node3)
+ >>> node = doc.createTextNode('text')
+ >>> a = root.appendChild(node)
+ >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS
+ '<?xml version="1.0" ?>...<root>text<!--comment--><text &attr="test">text</text><text/>text</root>'
+
+ >>> node_to_dict(root)
+ {'<text>1': {'@': 'text', '&&attr': 'test'}, '<text>2': {'@': ''}, '@': 'texttext'}
+
+ '''
+ result = {}
+
+ # Map the attributes
+ for index in range(0, node.attributes.length):
+ attr = node.attributes.item(index)
+ result['&' + attr.name] = attr.nodeValue
+
+ text = ''
+
+ # Map the nodes
+ for child in node.childNodes:
+ if child.nodeType == child.TEXT_NODE:
+ text = text + child.data
+ if child.nodeType == child.ELEMENT_NODE:
+ index = 1
+ while ('<' + child.tagName + '>' + str(index)) in result.keys():
+ index += 1
+ result['<' + child.tagName + '>' + str(index)] = node_to_dict(child)
+
+ result['@'] = text
+
+ return result
+
+def dict_to_node(data, document, root_name):
+ ''' Reverts the node_to_dict operation.
+
+ >>> import xml.dom.minidom
+ >>> imp = xml.dom.minidom.getDOMImplementation()
+ >>> doc = imp.createDocument('test', 'root', None)
+ >>> a = {'<text>1': {'@': 'text', '&&attr': 'test'}, '<text>2': {'@': ''}, '@': 'texttext'}
+ >>> doc.childNodes[0] = dict_to_node(a, doc, 'root')
+ >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS
+ '<?xml version="1.0" ?>...<root><text &attr="test">text</text><text></text>texttext</root>'
+
+ '''
+ node = document.createElement(root_name)
+
+ for i, j in data.items():
+
+ if i[0] == '&':
+ attr = document.createAttribute(i[1:])
+ node.setAttributeNode(attr)
+ node.setAttribute(i[1:], j)
+ if i[0] == '<':
+ k = i[1:]
+ while k[-1] in '0123456789':
+ k = k[:-1]
+ child = dict_to_node(data[i],
+ document,
+ k[:-1])
+ node.appendChild(child)
+ if i[0] == '@':
+ child = document.createTextNode(j)
+ node.appendChild(child)
+
+ return node
+
+def path(path_elements):
+ '''
+ Concatenate a path from several elements.
+
+ >>> path([])
+ ''
+ >>> path(['a'])
+ 'a'
+ >>> path(['a','b'])
+ 'a/b'
+ >>> path(['a/','b'])
+ 'a/b'
+ >>> path(['/a/','b'])
+ '/a/b'
+ >>> path(['/a/','b/'])
+ '/a/b'
+ >>> path(['/a/','b/'])
+ '/a/b'
+ >>> path(['/a/','/b/'])
+ '/a/b'
+ >>> path(['/a/','/b','c/'])
+ '/a/b/c'
+ '''
+ pathname = ''
+
+ if type(path_elements) in types.StringTypes:
+ path_elements = [path_elements]
+
+ # Concatenate elements and seperate with /
+ for i in path_elements:
+ pathname += i + '/'
+
+ # Replace multiple consecutive slashes
+ pathname = re.compile('/+').sub('/', pathname)
+
+ # Remove the final / if there is one
+ if pathname and pathname[-1] == '/':
+ pathname = pathname[:-1]
+
+ return pathname
+
+#===============================================================================
+#
+# Testing
+#
+#-------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ import doctest, sys
+ doctest.testmod(sys.modules[__name__])
diff --git a/layman/version.py b/layman/version.py
new file mode 100644
index 0000000..943522b
--- /dev/null
+++ b/layman/version.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#################################################################################
+# LAYMAN VERSION
+#################################################################################
+# File: version.py
+#
+# Current version number
+#
+# Copyright:
+# (c) 2005 - 2006 Gunnar Wrobel
+# Distributed under the terms of the GNU General Public License v2
+#
+# Author(s):
+# Gunnar Wrobel <wrobel@gentoo.org>
+#
+
+__version__ = "$Id: version.py 309 2007-04-09 16:23:38Z wrobel $"
+
+
+VERSION = '1.0.99'
+
+if __name__ == '__main__':
+ print VERSION
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..9c50c54
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+import sys
+
+from distutils.core import setup
+
+# this affects the names of all the directories we do stuff with
+sys.path.insert(0, './')
+from layman.version import VERSION
+
+
+setup(name = 'layman',
+ version = VERSION,
+ description = 'Python script for retrieving gentoo overlays',
+ author = 'Gunnar Wrobel',
+ author_email = 'wrobel@gentoo.org',
+ url = 'http://projects.gunnarwrobel.de/scripts',
+ packages = ['layman', 'layman.overlays'],
+ scripts = ['bin/layman'],
+ license = 'GPL',
+ )