commit 871478faf45ea92b1f4b93696f19fd323605a76b Author: Simone Rota Date: Thu Jul 13 04:21:42 2006 +0200 Initial import diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..069a07d --- /dev/null +++ b/ChangeLog @@ -0,0 +1,64 @@ +ChangeLog for pkg-get +0.4.4 - Fixed: pkg-repgen produces well-formed entries for + packages not available in the port tree + - Added root option for install / update command + (thanks to Gunter Coell) + +0.4.3 - Fixed: operation summary when using -do option + - pkg-repgen now also generates a html index file + for the repository + +0.4.2 - Create lock file if it does not exist + - Fixed: locked packages were not ignored in diff + commands + +0.4.1 - Fixed parsing bug for uncommon 'version' strings + +0.4.0 - Completely re-written in perl + - Added failover mechanism for unsuccessful syncronizations + - Better standardization of task summary and option handling + - Removed proxy options (now handled by wget) + - Improved general command / options / look and feel + compatibility with prt-get + - "use_scrips" config option is now called "runscripts" + - Added -im, --config=, --aargs= options + - The "current" command now prints the currently installed + version instead of the available version (uniformity + with prt-get) + +0.3.4 - Fixed: removed check for REPO files before 'sync', + 'version' and 'help commands'. + +0.3.3 - Added pre-post install success report, i.e.: [pre: ok] + - Fixed minor commandline parser bug (options were ignored + for 'sysup' command) + - Changed PKGREPO format (package name is now the 1st entry) + - pkg-repgen is now written in perl + +0.3.2 - Added 'current' and 'path' commands + - Added bash completion script + - fixes in quickdiff command + +0.3.1 - Fixes small bug in 'depends' command (duplicate entries) + +0.3.0 - Added support for multiple repositories + - Added 'dup' command + - minor bugfixes + +0.2.0 - Added support for README files + - Added support for pre-post install scripts + - Added 'printf' command + +0.1.9 - Changed wget-like progress (from busybox, 1/5 of the size!) + +0.1.8 - Added 'quickdiff', 'remove' commands. + +0.1.7 - Added 'dependent' command + +0.1.6 - Added locking support: 'lock', 'unlock', 'listlocked' + +0.1.5 - Minor fixes + +0.1.4 - Added wget-like progress for downloads + +0.1.3 - Added list, listinst; minor fixes. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1b02d9e --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +NAME=pkg-get +VERSION="0.4.4" + +PREFIX=/usr +CFGDIR=/etc + +all: + @echo "Use 'make install' to install pkg-get" + +man: + makeman doc/pkg-get.8.txt + makeman doc/pkg-repgen.8.txt + man2ps doc/pkg-get.8 | ps2pdf14 - > doc/pkg-get.pdf + +dist: man + rm -rf ${NAME}-${VERSION} + mkdir ${NAME}-${VERSION} + cp -r doc scripts Makefile ChangeLog COPYING README TODO ${NAME}-${VERSION} + rm -f ${NAME}-${VERSION}/doc/*.txt + rm -f ${NAME}-${VERSION}/doc/*.pdf + tar cvzf ${NAME}-${VERSION}.tar.gz ${NAME}-${VERSION} + rm -rf ${NAME}-${VERSION} + +install: + + install -D -m 755 scripts/pkg-get.pl ${PREFIX}/bin/pkg-get + install -D -m 755 scripts/pkg-repgen.pl ${PREFIX}/bin/pkg-repgen + install -D -m 755 scripts/pkg-get.pl ${PREFIX}/bin/pkg-get + install -D -m 644 doc/pkg-get.8 ${PREFIX}/man/man8/pkg-get.8 + install -D -m 644 doc/pkg-get.conf ${CFGDIR}/pkg-get.conf + install -D -m 644 doc/pkg-repgen.8 ${PREFIX}/man/man8/pkg-repgen.8 + install -D -m 644 doc/pkg-get.8 ${PREFIX}/man/man8/pkg-get.8 + diff --git a/README b/README new file mode 100644 index 0000000..c930507 --- /dev/null +++ b/README @@ -0,0 +1,44 @@ +INTRODUCTION +---------------------------------------------------------------------------- +pkg-get is a package / repository management tool for CRUX Linux. +Syntax and features are very close (often a carbon copy) +to the ones found in the port management tool 'prt-get' +by Johannes Winkelmann. +In fact pkg-get was developed as a prt-get/ports drop-in replacement +for systems in which it is preferable to handle binary packages instead +of compiling ports. + + +ARCHITECTURE +---------------------------------------------------------------------------- +The local machines sync metadata files (available packages, +readme files, dependencies, etc) from a remote (http or ftp) +OR a local path. +Once the metadata is present on the local machine, the usual +operations of installing, removing, getting info on packages +are available. + + +QUICK START +---------------------------------------------------------------------------- +Server: + A repository can be generated using 'pkg-repgen' in a + dir containing packages. It will take a while since md5sums + have to be calculated. + +Client: + Adjust settings in /etc/pkg-get.conf, then use the 'pkg-get sync' + command to gather metadata from the server (if remote). You can now + use the commands as described in the manual, i.e.: + + pkg-get info apache + pkg-get depinst kdebase + pkg-get listinst + +See the manual page for a detailed list of commands and options. + + +REQUIREMENTS +---------------------------------------------------------------------------- +For the client nothing outside the CRUX 'base' collection +For the server, prt-get diff --git a/TODO b/TODO new file mode 100644 index 0000000..64e83d8 --- /dev/null +++ b/TODO @@ -0,0 +1,6 @@ +TODO file for pkg-get + +- logging support (?) +- deptree command (?) + +- optimize the pkg-repgen script diff --git a/doc/pkg-get.8 b/doc/pkg-get.8 new file mode 100644 index 0000000..1ec46a0 --- /dev/null +++ b/doc/pkg-get.8 @@ -0,0 +1,234 @@ +." Text automatically generated by txt2man-1.4.7 +.TH pkg-get 8 "April 23, 2006" "" "" +.SH NAME +\fBpkg-get \fP- a package management tool for CRUX Linux +\fB +.SH SYNOPSIS +.nf +.fam C +\fBpkg-get\fP \fIcommand\fP [\fIoptions\fP] +.fam T +.fi +.SH DESCRIPTION +\fBpkg-get\fP is a simple package management tool for CRUX Linux. +It tries to replicate some of the most useful features of the +port management tool \fBprt-get\fP(8) to be used with binary packages. +\fBpkg-get\fP requires a remote or local package repository that +can be generated by repository maintainers with the +\fBpkg-repgen\fP(8) script. +.SH COMMANDS +.TP +.B +install [..] +Install given packages, +download if necessary. +.TP +.B +update [..] +Update given packages, +download if necessary. +.TP +.B +diff +Show a list of outdated packages. +.TP +.B +quickdiff +Show a compact list of outdated packages. +.TP +.B +sysup +Update all outdated packages. Download if necessary. +.TP +.B +depinst [..] +Install given packages +and relative dependencies. +.TP +.B +depends +Show a recursive list of dependencies for package +and their installation status. +.TP +.B +dependent [\fB--all\fP] +Show installed (or all with the \fB--all\fP option) packages +that depend from package. +.TP +.B +quickdep +Show a brief list of dependencies for package. +.TP +.B +info +Show information about package. +.TP +.B +current +Show currently installed version of package. +.TP +.B +path +Show local path of package. +.TP +.B +readme +Print README information (if available) for the package. +.TP +.B +list +List all packages in the repository. +.TP +.B +listinst +List all installed packages. +.TP +.B +isinst +Display whether a package is installed. +.TP +.B +dsearch +Search for packages which name or description contain . +.TP +.B +search +Search for packages which name contains . +.TP +.B +dup +List all duplicates ports (present in more than one repository). +.TP +.B +printf [\fB--filter\fP=] +Description blatantly +stolen from prt-get man file. Print formatted port list. Format string can +contain variables, which are replaced like this: +.RS +.IP \(bu 3 +%n -> name +.IP \(bu 3 +%p -> path +.IP \(bu 3 +%v -> version +.IP \(bu 3 +%r -> release +.IP \(bu 3 +%d -> description +.IP \(bu 3 +%e -> dependencies +.IP \(bu 3 +%u -> url +.IP \(bu 3 +%R -> Readme ("yes"/"no") +.IP \(bu 3 +%E -> pre-install script ("yes"/"no") +.IP \(bu 3 +%O -> post-install script ("yes"/"no") +.IP \(bu 3 +%M -> "Nobody". for compatibility with prt-get +.IP \(bu 3 +%P -> "Nobody". for compatibility with prt-get +.IP \(bu 3 +%l -> is locked ("yes"/"no") +.IP \(bu 3 +%i -> "no" if not installed, "yes" if it's installed and up to +date and "diff" if it's installed and a new version is in the +repository. +.RE +.PP +Use "\\n" and "\\t" to format your output (no additional format +specified suported). The optional format string2 can contain the +same variables as format string1 and is used to sort the output. +You can specify a wildcard filter to filter by package name. +.TP +.B +lock [..] +Lock a package (ignore updates). +.TP +.B +unlock [..] +Unlock a package. +.TP +.B +listlocked +Display a list of locked packages. +.TP +.B +sync +Syncronize local packages with the ones from the remote repository. +If the repository is local, this \fIcommand\fP does nothing. +.TP +.B +sysup +Update all outdated packages. +.TP +.B +help +Display brief help screen. +.TP +.B +version +Show \fBpkg-get\fP version. +.SH OPTIONS +.TP +.B +\fB-r\fP +Use directory when wrapping pkgadd. Note that +this only works with update / install ! +.TP +.B +\fB-do\fP +Download only. Applicable to: sysup, depinst, install, update. +.TP +.B +\fB-f\fP +Force installing / upgrading. This is passed to \fBpkgadd\fP(8). +.TP +.B +\fB-im\fP +Ignore md5sum mismatches. +.TP +.B +\fB--aargs\fP="arguments" +pass the specified arguments to \fBpkgadd\fP(8). +.TP +.B +\fB--config\fP=/path/to/file +Use the specified configuration file. +.TP +.B +\fB--pre-install\fP +executes pre-install script if available. +.TP +.B +\fB--post-install\fP +executes post-install script if available. +.TP +.B +\fB--install-scripts\fP +executes pre-install and post-install +scripts if available. +.RE +.PP + +.SH CONFIGURATION +Configuration is handled by the /etc/pkg-get.conf file, +\fIoptions\fP are explained in the file itself. +.SH EXAMPLES +.TP +.B +\fBpkg-get\fP install sqlite pysqlite +Install sqlite and pysqlite. +.TP +.B +\fBpkg-get\fP depinst kdebase \fB-f\fP +Install kdebase and all its dependencies, forcing upgrade. +.TP +.B +\fBpkg-get\fP sysup \fB-do\fP +Download new releases of all the outdated packages. +.SH AUTHORS +Simone Rota +.SH SEE ALSO +\fBpkgadd\fP(8), \fBprt-get\fP(8) diff --git a/doc/pkg-get.8.txt b/doc/pkg-get.8.txt new file mode 100644 index 0000000..aee645a --- /dev/null +++ b/doc/pkg-get.8.txt @@ -0,0 +1,101 @@ +NAME + pkg-get - a package management tool for CRUX Linux + +SYNOPSIS + pkg-get command [options] + +DESCRIPTION + pkg-get is a simple package management tool for CRUX Linux. + It tries to replicate some of the most useful features of the + port management tool prt-get(8) to be used with binary packages. + pkg-get requires a remote or local package repository that + can be generated by repository maintainers with the + pkg-repgen(8) script. + +COMMANDS + install [..] Install given packages, + download if necessary. + update [..] Update given packages, + download if necessary. + diff Show a list of outdated packages. + quickdiff Show a compact list of outdated packages. + sysup Update all outdated packages. Download if necessary. + depinst [..] Install given packages + and relative dependencies. + depends Show a recursive list of dependencies for package + and their installation status. + dependent [--all] Show installed (or all with the --all option) packages + that depend from package. + quickdep Show a brief list of dependencies for package. + info Show information about package. + current Show currently installed version of package. + path Show local path of package. + readme Print README information (if available) for the package. + list List all packages in the repository. + listinst List all installed packages. + isinst Display whether a package is installed. + dsearch Search for packages which name or description contain . + search Search for packages which name contains . + dup List all duplicates ports (present in more than one repository). + printf [--filter=] Description blatantly + stolen from prt-get man file. Print formatted port list. Format string can + contain variables, which are replaced like this: + - %n -> name + - %p -> path + - %v -> version + - %r -> release + - %d -> description + - %e -> dependencies + - %u -> url + - %R -> Readme ("yes"/"no") + - %E -> pre-install script ("yes"/"no") + - %O -> post-install script ("yes"/"no") + - %M -> "Nobody". for compatibility with prt-get + - %P -> "Nobody". for compatibility with prt-get + - %l -> is locked ("yes"/"no") + - %i -> "no" if not installed, "yes" if it's installed and up to + date and "diff" if it's installed and a new version is in the + repository. + + Use "\\n" and "\\t" to format your output (no additional format + specified suported). The optional format string2 can contain the + same variables as format string1 and is used to sort the output. + You can specify a wildcard filter to filter by package name. + + lock [..] Lock a package (ignore updates). + unlock [..] Unlock a package. + listlocked Display a list of locked packages. + sync Syncronize local packages with the ones from the remote repository. + If the repository is local, this command does nothing. + sysup Update all outdated packages. + help Display brief help screen. + version Show pkg-get version. + +OPTIONS + -r Use directory when wrapping pkgadd. Note that + this only works with update / install ! + -do Download only. Applicable to: sysup, depinst, install, update. + -f Force installing / upgrading. This is passed to pkgadd(8). + -im Ignore md5sum mismatches. + --aargs="arguments" pass the specified arguments to pkgadd(8). + --config=/path/to/file Use the specified configuration file. + --pre-install executes pre-install script if available. + --post-install executes post-install script if available. + --install-scripts executes pre-install and post-install + scripts if available. + + +CONFIGURATION + Configuration is handled by the /etc/pkg-get.conf file, + options are explained in the file itself. + +EXAMPLES + pkg-get install sqlite pysqlite Install sqlite and pysqlite. + pkg-get depinst kdebase -f Install kdebase and all its dependencies, forcing upgrade. + pkg-get sysup -do Download new releases of all the outdated packages. + +AUTHORS + Simone Rota + +SEE ALSO + pkgadd(8), prt-get(8) diff --git a/doc/pkg-get.conf b/doc/pkg-get.conf new file mode 100644 index 0000000..9c42044 --- /dev/null +++ b/doc/pkg-get.conf @@ -0,0 +1,13 @@ +## +# /etc/pkg-get.conf +# pkg-get configuration file + +# package repositories (remote) +# The first two are remote repoistories, the last is a local one +pkgdir /usr/packages/server|http://www.somesite.com/packages +pkgdir /usr/packages/java|http://www.foobar.com/java +pkgdir /usr/packages/games + +# runscripts: if "yes" pre-post install scripts are +# automatically executed. Handle with care. +runscripts no diff --git a/doc/pkg-repgen.8 b/doc/pkg-repgen.8 new file mode 100644 index 0000000..d45f844 --- /dev/null +++ b/doc/pkg-repgen.8 @@ -0,0 +1,43 @@ +." Text automatically generated by txt2man-1.4.7 +.TH pkg-repgen 8 "April 23, 2006" "" "" +.SH NAME +\fBpkg-repgen \fP- generate a package repository for pkg-get +\fB +.SH SYNOPSIS +.nf +.fam C +\fBpkg-repgen\fP [options][package1\.\.\.packageN] +.fam T +.fi +.SH DESCRIPTION +\fBpkg-repgen\fP generates files needed by a \fBpkg-get\fP(8) package +repository. It also generates a html index of the packages. +.SH USAGE +run \fBpkg-repgen\fP from the directory containing packages to +generate the whole repository. +Specify a list of package names to update only those packages +(this is expecially useful with large repositories). +Note that the html index is not updated when single +packages are specified. +.SH OPTIONS +.TP +.B +\fB--header\fP=FILE +insert FILE at the beginning of the html index +.TP +.B +\fB--header\fP=FILE +insert FILE at the beginning of the html index +.TP +.B +\fB--title\fP=title +use the specified title for the index page +.SH EXAMPLES +\fBpkg-repgen\fP +.PP +\fBpkg-repgen\fP kdebase kdelibs +.SH AUTHORS +Simone Rota +index generation code adapted from Jukka Heino's portspage +.SH SEE ALSO +\fBpkg-get\fP(8), \fBprt-get\fP(8) diff --git a/doc/pkg-repgen.8.txt b/doc/pkg-repgen.8.txt new file mode 100644 index 0000000..0225769 --- /dev/null +++ b/doc/pkg-repgen.8.txt @@ -0,0 +1,34 @@ +NAME + pkg-repgen - generate a package repository for pkg-get + +SYNOPSIS + pkg-repgen [options][package1...packageN] + +DESCRIPTION + pkg-repgen generates files needed by a pkg-get(8) package + repository. It also generates a html index of the packages. + +USAGE + run pkg-repgen from the directory containing packages to + generate the whole repository. + Specify a list of package names to update only those packages + (this is expecially useful with large repositories). + Note that the html index is not updated when single + packages are specified. + +OPTIONS + --header=FILE insert FILE at the beginning of the html index + --header=FILE insert FILE at the beginning of the html index + --title=title use the specified title for the index page + +EXAMPLES + pkg-repgen + + pkg-repgen kdebase kdelibs + +AUTHORS + Simone Rota + index generation code adapted from Jukka Heino's portspage + +SEE ALSO + pkg-get(8), prt-get(8) diff --git a/scripts/pkg-get.pl b/scripts/pkg-get.pl new file mode 100755 index 0000000..0c15609 --- /dev/null +++ b/scripts/pkg-get.pl @@ -0,0 +1,1169 @@ +#!/usr/bin/env perl +# +# pkg-get - A binary package management utility for CRUX Linux +# Copyright (C) 2004-05 Simone Rota +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +use warnings; +use strict; +use Getopt::Long; + +my $VERSION = "0.4.4"; +my $CFGFILE = "/etc/pkg-get.conf"; +my $LOCKFILE = "/var/lib/pkg/pkg-get.locker"; +my $PKGDB = "/var/lib/pkg/db" ; + +$SIG{HUP} = \&trap; $SIG{INT} = \&trap; $SIG{QUIT} = \&trap; $SIG{TERM} = \&trap; + +# Global vars +my @repos = (); # package repositories +my @donetasks; my @failtasks; my @prevtasks; my %pptasks; my %readmetasks; +my $curraction = ""; my %installed; my %deps; my @dependencies; my %missingdeps; + +# CL Options +my $download_only; my $pre_install; my $post_install; +my $install_scripts; my $filter = ""; my $all; my $unused; +my $aargs=""; my $ignore_md5sum; my $force; my $root; +GetOptions("do"=>\$download_only, + "pre-install"=>\$pre_install, "post-install"=>\$post_install, + "install-scripts"=>\$install_scripts, "all"=>\$all, + "filter=s"=>\$filter, "config=s"=>\$CFGFILE, "aargs=s"=>\$aargs, + "f"=>\$force, "im"=>\$ignore_md5sum, "margs=s"=>\$unused, + "rargs=s"=>\$unused, "r=s"=>\$root); + +if ($root) { + $LOCKFILE = $root.$LOCKFILE ; + $PKGDB = $root.$PKGDB; +} + +# Get command, verify it's valid +my $command = getcommand(@ARGV); +if (index($command,"Error: ") eq 0 ) { + $command =~ s/Error\: //; + exiterr($command); +} +readconfig(); + +SWITCH: { + if ($command eq "version") { version(); last SWITCH; } + if ($command eq "sync") { sync(); last SWITCH; } + if ($command eq "info") { info(); last SWITCH; } + if ($command eq "help") { help(); last SWITCH; } + if ($command eq "readme") { readme(); last SWITCH; } + if ($command eq "search") { search(); last SWITCH; } + if ($command eq "dsearch") { dsearch(); last SWITCH; } + if ($command eq "list") { list(); last SWITCH; } + if ($command eq "path") { path(); last SWITCH; } + if ($command eq "remove") { remove(); last SWITCH; } + if ($command eq "listinst") { listinst(); last SWITCH; } + if ($command eq "lock") { dolock(); last SWITCH; } + if ($command eq "unlock") { unlock(); last SWITCH; } + if ($command eq "listlocked") { listlocked(); last SWITCH; } + if ($command eq "printf") { doprintf(); last SWITCH; } + if ($command eq "isinst") { isinst(); last SWITCH; } + if ($command eq "diff") { diff(); last SWITCH; } + if ($command eq "quickdiff") { quickdiff(); last SWITCH; } + if ($command eq "dup") { dup(); last SWITCH; } + if ($command eq "depends") { depends(); last SWITCH; } + if ($command eq "quickdep") { quickdep(); last SWITCH; } + if ($command eq "install") { install(@ARGV); last SWITCH; } + if ($command eq "update") { update(@ARGV); last SWITCH; } + if ($command eq "sysup") { sysup(); last SWITCH; } + if ($command eq "dependent") { dependent(); last SWITCH; } + if ($command eq "depinst") { depinst(); last SWITCH; } + if ($command eq "current") { current(); last SWITCH; } +} + + +############################################################################ +# Support functions +############################################################################ + +# Exit with error +sub exiterr { + my ($msg) = @_; + print "pkg-get: $msg\n"; + exit 1; +} + +sub trap { + printresults(1); + die("\npkg-get: interrupted\n"); +} + +# Get command, return an error if not in the list of allowed commands +sub getcommand { + my @args = @_; + my $givencmd = $args[0]; + my $givenarg = $args[1]; + if (not $givenarg){$givenarg = ""}; + if (not $givencmd){$givencmd = ""}; + my @allowed = ("depinst:", "install:", "sysup", "diff", "update:", "depends:", "info:", "sync", + "version", "help", "quickdep:", "dependent:", "list", "listinst", "isinst:", + "search:", "dsearch:", "lock:", "unlock:", "listlocked", "quickdiff", "printf:", + "remove:", "readme:", "dup", "path:", "current:"); + + foreach my $valid(@allowed) { + if ($givencmd eq ""){ + return "Error: no command given. try pkg-get help for more information"; + } + if ($givencmd eq $valid) { + return $givencmd; + } elsif ($givencmd.":" eq $valid) { + if ($givenarg ne "") { + return $givencmd; + } else { + return "Error: '$givencmd' requires an argument"; + } + } + } + return "Error: unknown command '$givencmd'. try pkg-get help for more information"; +} + +# Parses the configuration file +sub readconfig { + open(CFG, $CFGFILE) + or exiterr("could not open $CFGFILE"); + while () { + chomp; + if ( /^pkgdir\s+/ ) { + my $repo = $_; + $repo =~ s/^pkgdir\s+//; + $repo =~ s/#(.*)$//; + $repo =~ s/\s+$//; + push @repos, $repo; + } elsif (/^runscripts\s+/) { + my $rs = $_; + $rs =~ s/^runscripts\s+//; + $rs =~ s/#(.*)$//; + $rs =~ s/\s+$//; + if ($rs eq "yes") {$install_scripts = 1}; + } + } + close(CFG); +} + +# Parse a line describing a package +sub parsepackage { + my @p = split(/\:/, $_[0]); + if ($#p != 6) {exiterr("$_[1]/PKGREPO appears to be in wrong format!\nAborting.")}; + my %pkg; + my $name = $p[0]; + $name =~ s/\#.*$//; + my $version = $p[0]; + $version =~ s/^.*\#//; + $version =~ s/-\w*\.pkg\.tar\.gz//; + my $release = $p[0]; + $release =~ s/^.*-//; + $release =~ s/\.pkg\.tar\.gz//; + if (not $_[2]) {$_[2] = $_[1]}; + $pkg{'name'} = $name; + $pkg{'version'} = $version; + $pkg{'release'} = $release; + $pkg{'path'} = $_[1]; + $pkg{'url'} = $_[2] . "/$p[0]"; + $pkg{'size'} = $p[1]; + $pkg{'md5sum'} = $p[2]; + $pkg{'description'} = $p[3]; + $pkg{'pre_install'} = $p[4]; + $pkg{'post_install'} = $p[5]; + $pkg{'readme'} = $p[6]; + if ($_[3] == 1) { + getinstalled(); + $pkg{'instversion'} = $installed{$name}; + } + return %pkg; +} + +# Parse a line describing a package (just the name) +sub parsepackagelight { + my @p = split(/\:/, $_[0]); + if ($#p != 6) {exiterr("$_[1]/PKGREPO appears to be in wrong format!\nAborting.")}; + my %pkg; + my $name = $p[0]; + $name =~ s/\#.*$//; + $pkg{'name'} = $name; + return %pkg; +} + +# Print info about the given package +sub printinfo { + my %pkg = @_; + print "Name : " . $pkg{'name'} . "\n"; + print "Version : " . $pkg{'version'} . "\n"; + print "Release : " . $pkg{'release'} . "\n"; + print "Description : " . $pkg{'description'} . "\n"; + print "URL : " . $pkg{'url'} . "\n"; + print "Md5sum : " . $pkg{'md5sum'} . "\n"; + print "Size : " . $pkg{'size'} . "\n"; + my $deps = getdirectdeps($pkg{'name'}, $pkg{'path'}); + if ($deps ne "") { print "Depends on : $deps\n";}; + my $files = ""; + if ($pkg{'readme'} eq "yes") {$files .= "README,"}; + if ($pkg{'pre_install'} eq "yes") {$files .= "pre-install,"}; + if ($pkg{'post_install'} eq "yes") {$files .= "post-install,"}; + $files =~ s/\,$//; + if ($files ne "") { print "Files : $files\n";}; +} + +# Get direct dependencies for package +sub getdirectdeps { + my $pkgname = $_[0]; + my $dir = $_[1]; + open(DEPS, "$dir/PKGDEPS") + or exiterr("could not open $dir/PKGDEPS"); + while () { + chomp; + if ( /^\Q$pkgname\E\s+/ ) { + my $dep = $_; + $dep =~ s/^.*\: //; + close(DEPS); + return $dep; + } + } + close(DEPS); + return ""; +} + +# Prints the README file to stdout +sub printreadme { + my %pkg = @_; + my $dir = $pkg{'path'}; + my $pkgname = $pkg{'name'}; + my $found = 0; + my $finished = 0; + open(READ, "$dir/PKGREAD") + or exiterr("could not open $dir/PKGREAD"); + while () { + if ($finished eq 1) {return;}; + chomp; + if ($found eq 1) { + if ( /PKGREADME\:/ ) { + $finished = 1; + close(READ); + return; + } else { + print "$_\n"; + } + } + if ($finished eq 0) { + if ( /PKGREADME: $pkgname$/ ) { + $found = 1; + } + } + } + close(READ); +} + +# Print results for multiple package operations +sub printresults { + my $okaction = $curraction; + my $curr = ""; + my $action; + my $pkg; + my @t; + my @readme; + my $goterror = 0; + if (@donetasks) { + print "\n-- Packages $okaction\n"; + foreach my $task(@donetasks) { + if ($readmetasks{$task}) {push(@readme, $task)} + print "$task" . $pptasks{$task}."\n"; + } + } + if (@prevtasks) { + if ($okaction eq "installed") { + print "\n-- Packages installed before this run (ignored)\n"; + } else { + print "\n-- Packages not previously installed (ignored)\n"; + } + foreach my $task(@prevtasks) { + print "$task\n"; + } + } + if (@failtasks) { + @failtasks = sort(@failtasks); + foreach my $task(@failtasks) { + @t = split(/,/,$task); + $action = $t[0]; + $pkg = $t[1]; + if ($curr ne $action) { + print "\n-- Packages $action\n"; + $curr = $action; + } + print "$pkg\n"; + } + } + if (@readme) { + print "\n-- $okaction packgages with README file\n"; + foreach my $task(@readme) { + print "$task" . $pptasks{$task}."\n"; + } + } + if(@donetasks and not @failtasks and not $_[0]) { + print "\npkg-get: $okaction successfully\n" + } +} + +# Get the list of installed packages +sub getinstalled { + if (%installed) { + return; + } + my $name; + my $version; + my $sec = 0; + open(DB, $PKGDB) + or exiterr("could not open ".$PKGDB); + while () { + chomp; + if ($_ ne "") { + if ($sec == 0) { + $name = $_; + $sec = 1; + } elsif ($sec == 1) { + $version = $_; + $sec = 3; + } + } + if ($sec == 3) { + if ($_ eq "") { + $sec = 0; + $installed{$name} = $version; + } + } + } + close(DB); +} + +# Lock the given pkgname +sub lockadd { + my $pkg = $_[0]; + my @locked = (); + if (not -e $LOCKFILE) { + open(LCK, "+>> $LOCKFILE") or exiterr("could not write to lock file"); + close(LCK); + } + open(LCK, $LOCKFILE); + while () { + chomp; + if ($_ eq $pkg) { + print "Already locked: $pkg\n"; + close(LCK); + return; + } else { + push (@locked, $_); + } + } + close(LCK); + push(@locked, $pkg); + @locked = sort(@locked); + open(LCK, "> $LOCKFILE") or exiterr("could not write to lock file"); + foreach my $lock(@locked) { + print LCK "$lock\n"; + } + close(LCK); +} + +# Rrint formatted info for given package +sub formattedprint { + my %pkg = @_; + my $fmt = $ARGV[1]; + $fmt =~ s|%n|$pkg{'name'}|; + $fmt =~ s|%p|$pkg{'path'}|; + $fmt =~ s|%v|$pkg{'version'}|; + $fmt =~ s|%r|$pkg{'release'}|; + $fmt =~ s|%d|$pkg{'description'}|; + $fmt =~ s|%u|$pkg{'url'}|; + $fmt =~ s|%R|$pkg{'readme'}|; + $fmt =~ s|%E|$pkg{'pre_install'}|; + $fmt =~ s|%O|$pkg{'post_install'}|; + $fmt =~ s|%M|Nobody|; # for prt-get compatibility + $fmt =~ s|%P|Nobody|; # for prt-get compatibility + $fmt =~ s|\\n|\n|; + $fmt =~ s|\\t|\t|; + if (index($fmt,"%e") >=0) { + my $deps = getdirectdeps($pkg{'name'}, $pkg{'path'}); + $fmt =~ s|%e|$deps|; + } + if (index($fmt,"%l") >=0) { + my $locked = islocked($pkg{'name'}); + $fmt =~ s|%l|$locked|; + } + if (index($fmt,"%i") >=0) { + my $inst = "no"; + if ($pkg{'instversion'}) { + if ($pkg{'instversion'} eq $pkg{'version'}."-".$pkg{'release'}) { + $inst = "yes"; + } else { + $inst = "diff"; + } + } + $fmt =~ s|%i|$inst|; + } + print "$fmt"; +} + +# See if package is currently locked +sub islocked { + my $pkg = $_[0]; + open(LCK, $LOCKFILE) or return "no"; + while () { + chomp; + if ($_ eq $pkg) { + close(LCK); + return "yes"; + } + } + close(LCK); + return "no"; +} + +# Get package from the repo(s) +sub getpackage { + my $pkgname = $_[0]; + my $checkver = $_[1]; + my %found; + my %res; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg = parsepackage($_, $dir, $url, $checkver); + if ($pkg{'name'} eq $pkgname) { + close (REPO); + return %pkg; + } + } + close (REPO); + } + return %res; +} + +# Get short status for package, ie [i] +sub getshortstatus { + my %pkg = @_; + if ($pkg{'instversion'}) { + if ($pkg{'instversion'} eq $pkg{'version'}."-".$pkg{'release'}) { + return "[i]"; + } else { + return "[u]"; + } + } + return "[ ]"; +} + +# Get (recursive) dependencies for pkgname +sub getdependencies { + my $pkgname = $_[0]; + my $checkver = $_[1]; + my $pkgparent = $_[2]; + my $depstring = ""; + if ($pkgparent eq "") { + #%deps = (); + }; + if (not $deps{$pkgname}) { + my %pkg = getpackage($pkgname, 1); + if (%pkg) { + my $ddeps = getdirectdeps($pkg{'name'}, $pkg{'path'}); + my @d = split(/,/, $ddeps); + foreach my $dep(@d) { + getdependencies($dep, $checkver, $pkgname); + } + if ($checkver) { + $depstring = getshortstatus(%pkg) . " $pkgname"; + } else { + $depstring = $pkgname; + } + $deps{$pkgname} = $depstring; + push(@dependencies, $depstring); + } else { + if ($pkgparent eq "") { + return 0; + } else { + $missingdeps{$pkgname} = $pkgparent; + } + } + } +} + +# Download given package (if needed), check md5sum +sub downloadpkg { + my %pkg = @_; + my $fullpath = $pkg{'path'}."/".$pkg{'name'}."#".$pkg{'version'}."-".$pkg{'release'}.".pkg.tar.gz"; + if (-f $fullpath) { + my $md5 = `md5sum $fullpath`; chomp; + $md5 =~ s/\s+.*$//; + $md5 =~ chop($md5); + if ($md5 ne $pkg{'md5sum'} and not $ignore_md5sum) { + print STDERR "=======> ERROR: md5sum mismatch for $pkg{'name'}:\n"; + print STDERR "required : $pkg{'md5sum'}\n"; + print STDERR "found : $md5\n"; + return 0; + } + return 1; + } else { + if ($pkg{'url'} eq "") {return 1}; # repo is local and pkg does not exist. + my $url = $pkg{'url'}; + $url =~ s/\#/\%23/; + system ("wget --no-directories --tries=3 --waitretry=3 --directory-prefix=$pkg{'path'} $url") == 0 or return 0; + my $md5 = `md5sum $fullpath`; chomp; + $md5 =~ s/\s+.*$//; + $md5 =~ chop($md5); + if ($md5 ne $pkg{'md5sum'} and not $ignore_md5sum) { + print STDERR "=======> ERROR: md5sum mismatch for $pkg{'name'}:\n"; + print STDERR "required : $pkg{'md5sum'}\n"; + print STDERR "found : $md5\n"; + return 0; + } + } + return 1; +} + +# Install given package +sub installpkg { + my $upgrade = shift(@_); + my %pkg = @_; + my $aa = $aargs." "; + if ($pkg{'readme'} eq "yes") {$readmetasks{$pkg{'name'}} = 1}; + $pptasks{$pkg{'name'}} = ""; + if ($download_only) {return 1}; + if ($force){$aa = $aa."-f "}; + if ($root) {$aa = $aa."-r ".$root." "}; + if ($pkg{'pre_install'} eq "yes" and ($install_scripts or $pre_install)) {dopre(%pkg)}; + my $fullpath = $pkg{'path'}."/".$pkg{'name'}."#".$pkg{'version'}."-".$pkg{'release'}.".pkg.tar.gz"; + print "pkg-get: /usr/bin/pkgadd $upgrade$aa$fullpath\n"; + system ("/usr/bin/pkgadd $upgrade$aa$fullpath") == 0 or return 0; + if ($pkg{'post_install'} eq "yes" and ($install_scripts or $post_install)) {dopost(%pkg)}; + return 1; +} + +# Execute pre-install script +sub dopre { + my %pkg = @_; + my $cmd = "/bin/bash $pkg{'path'}/PKGINST $pkg{name}_pre_install"; + if (system($cmd) == 0){ + $pptasks{$pkg{'name'}} .= " [pre: ok]"; + } else { + $pptasks{$pkg{'name'}} .= " [pre: failed]"; + } +} + +# Execute post-install script +sub dopost { + my %pkg = @_; + my $cmd = "/bin/bash $pkg{'path'}/PKGINST $pkg{name}_post_install"; + if (system($cmd) == 0){ + $pptasks{$pkg{'name'}} .= " [post: ok]"; + } else { + $pptasks{$pkg{'name'}} .= " [post: failed]"; + } +} + +############################################################################ +# Main functions (commands) +############################################################################ + +# No pun intended ########################################################## +sub version { + print "pkg-get $VERSION "; + print "by Simone Rota \n"; +} + +# Show brief help ########################################################## +sub help { + print "Usage: pkg-get command [package2 ... packageN] [options] + +Some command: + sync synchronize with the repository + depinst install package and its dependencies; + info info about package + sysup updates all outdated packages + diff list all outdated packages + +Some option: + -do download only + --install-scripts use install scripts + -r use for pkgadd + +Example: + pkg-get install sqlite pysqlite + +For other commands and samples, see the pkg-get(8) man page\n"; +} + +# Sync with the remote server(s) ########################################### +sub sync { + my @r; + my $dir; + my $url; + my $dlerror = 0; + foreach my $repo(@repos) { + @r = split(/\|/, $repo); + $dir = $r[0]; + $url = $r[1]; + if (not $url){$url = ""}; + print "Updating collection $dir\n"; + if (not -d $dir) { + mkdir($dir) or exiterr("cannot create $dir"); + } + if ($url ne "") { + for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") { + if (-f "$dir/$f") {rename("$dir/$f", "$dir/$f.old") or exiterr("cannot write to $dir")}; + if (system("wget -q -P $dir $url/$f") != 0) { + print " cannot retrieve $f\n"; + $dlerror=1; + } + } + if ($dlerror) { # restore backup repo + for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") { + if (-f "$dir/$f.old") {rename("$dir/$f.old", "$dir/$f") or exiterr("cannot write to $dir")};}; + } else { # remove backup repo + for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") { + if (-f "$dir/$f.old") {unlink("$dir/$f.old") or exiterr("cannot write to $dir")};}; + } + } + } +} + +# Show info about the package ############################################## +sub info { + my $arg = $ARGV[1]; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg = parsepackage($_, $dir, $url, 0); + if ($pkg{'name'} eq $arg) { + printinfo(%pkg); + close(REPO); + return; + } + } + close(REPO); + } + print "Package '$arg' not found\n"; +} + +# List packages containing given string in their name ###################### +sub search { + my $arg = $ARGV[1]; + my %found; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg = parsepackage($_, $dir, $url, 0); + if (index($pkg{'name'}, $arg) > -1 and not $found{$pkg{'name'}}) { + $found{$pkg{'name'}} = 1; + } + } + close(REPO); + } + foreach my $key (sort keys %found) { + print "$key\n"; + } + if (not %found) {print "No matching packages found\n"}; +} + +# List packages containing given string (name / description) ############### +sub dsearch { + my $arg = $ARGV[1]; + my %found; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg = parsepackage($_, $dir, $url, 0); + if ((index($pkg{'name'}, $arg) > -1 or index($pkg{'description'}, $arg) > -1) + and not $found{$pkg{'name'}}) { + $found{$pkg{'name'}} = 1; + } + } + close(REPO); + } + foreach my $key (sort keys %found) { + print "$key\n"; + } + if (not %found) {print "No matching packages found\n";}; +} + +# List all available packages ############################################## +sub list { + my $arg = $ARGV[1]; + my %found; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg = parsepackage($_, $dir, $url, 0); + $found{$pkg{'name'}} = 1; + } + close(REPO); + } + foreach my $key (sort keys %found) { + print "$key\n"; + } +} + +# Show path for a package ################################################## +sub path { + my $arg = $ARGV[1]; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg = parsepackage($_, $dir, $url, 0); + if ($pkg{'name'} eq $arg) { + print $pkg{'path'} . "\n"; + close(REPO); + return; + } + } + close(REPO); + } + print "Package '$arg' not found\n"; +} + +# Show current installed version of a package ############################## +sub current { + my $pkgname = $ARGV[1]; + getinstalled(); + if ($installed{$pkgname}) { + print "$installed{$pkgname}\n"; + } else { + print "Package $pkgname not installed\n"; + } +} + +# Print the README file for a package ###################################### +sub readme { + my $arg = $ARGV[1]; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg = parsepackage($_, $dir, $url, 0); + if ($pkg{'name'} eq $arg) { + printreadme(%pkg); + close(REPO); + return; + } + } + close(REPO); + } + print "Package '$arg' not found\n"; +} + +# Remove given packages #################################################### +sub remove { + $curraction = "removed"; + shift(@ARGV); + foreach my $pkg(@ARGV) { + $pptasks{$pkg} = ""; + if (system("/usr/bin/pkgrm $pkg") ==0) { + push(@donetasks, $pkg); + } else { + push(@failtasks, "where removal failed,$pkg"); + } + } + printresults(); +} + +# List installed packages ################################################## +sub listinst { + getinstalled(); + foreach my $key (sort keys %installed) { + print "$key\n"; + } +} + +# Print if package is installed ########################################### +sub isinst { + getinstalled(); + shift(@ARGV); + foreach my $pkg(@ARGV) { + if ($installed{$pkg}) { + print "package $pkg is installed\n"; + } else { + print "package $pkg is not installed\n"; + } + } +} + + +# Lock given packages ###################################################### +sub dolock { + shift(@ARGV); + foreach my $arg(@ARGV) { + my $found = 0; + foreach my $repo(@repos) { + if ($found == 0) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg = parsepackagelight($_); + if ($pkg{'name'} eq $arg) { + $found = 1; + lockadd($arg); + } + } + close(REPO); + } + } + if ($found == 0) {print "Package '$arg' not found\n"}; + } +} + +# Unlock given packages #################################################### +sub unlock { + shift(@ARGV); + my @locked; + my $found; + foreach my $arg(@ARGV) { + $found = 0; + @locked = (); + open(LCK, $LOCKFILE) or exiterr("could not open lock file"); + while () { + chomp; + if ($_ eq $arg) { + push (@locked, "-"); + $found = 1; + } else { + push (@locked, $_); + } + } + close(LCK); + if ($found == 1) { + @locked = sort(@locked); + open(LCK, ">$LOCKFILE") or exiterr("could not write to lock file"); + foreach my $lock(@locked) { + if ($lock ne "-") {print LCK "$lock\n"}; + } + close(LCK); + } else { + print "Not locked previously: $arg\n"; + } + } +} + +# List locked packages ##################################################### +sub listlocked { + open(LCK, $LOCKFILE) + or exit; + while () { + chomp; + print "$_\n"; + } + close(LCK); +} + +# Print formatted info ##################################################### +sub doprintf { + my %found; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg; + if (index($ARGV[1], "%i") >=0 ) { + %pkg = parsepackage($_, $dir, $url, 1); + } else { + %pkg = parsepackage($_, $dir, $url, 0); + } + if (not $found{$pkg{'name'}}) { + if ($filter ne "") { + my $match = $pkg{'name'}; + my $cfilter = $filter; + $cfilter =~ s/\*/\.\*/; + if ($match =~ /^$cfilter$/) { + formattedprint(%pkg); + $found{$pkg{'name'}} = 1; + } + } else { + formattedprint(%pkg); + $found{$pkg{'name'}} = 1; + } + } + } + close(REPO); + } +} + +# Show differences between installed and available packages ################ +sub diff { + my %found; + my $gotdiff = 0; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg; + %pkg = parsepackage($_, $dir, $url, 1); + if (not $found{$pkg{'name'}}) { + if ($pkg{'instversion'}) { + if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'} and (islocked($pkg{'name'}) eq "no")) { + if ($gotdiff == 0){ + print "Differences between installed packages and packages repo:\n\n"; + printf("%-19s %-19s %-19s\n\n","Package","Installed","Available in the repositories"); + $gotdiff = 1; + } + printf("%-19s %-19s %-19s\n", $pkg{'name'}, $pkg{'instversion'}, $pkg{'version'}."-".$pkg{'release'}); + } + } + $found{$pkg{'name'}} = 1; + } + } + close(REPO); + } + if ($gotdiff ==0) {print "No differences found\n"}; +} + +# Show differences between installed and available packages ################ +sub quickdiff { + my %found; + my $gotdiff = 0; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg; + %pkg = parsepackage($_, $dir, $url, 1); + if (not $found{$pkg{'name'}}) { + if ($pkg{'instversion'}) { + if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'} and islocked($pkg{'name'}) eq "no") { + if ($gotdiff == 0){ + print $pkg{'name'}; + $gotdiff = 1; + } else { + print " " . $pkg{'name'}; + } + } + } + $found{$pkg{'name'}} = 1; + } + } + close(REPO); + } + if ($gotdiff != 0) {print "\n"}; +} + +# Display duplicate packages (found in more than one repo) ################# +sub dup { + my %found; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg; + %pkg = parsepackage($_, $dir, $url, 0); + $found{$pkg{'name'}} .= "###" . $pkg{'path'}."/". $pkg{'name'}.$pkg{'version'}."-".$pkg{'release'}; + } + close(REPO); + } + my $curr = ""; + foreach my $key (sort keys %found) { + my $value = $found{$key}; + $value =~ s/^\#\#\#//; + if (rindex($value, "###") >=0){ + print "* $key\n"; + my @d = split(/\#\#\#/, $value); + foreach my $dup(@d){ + print " $dup\n"; + } + } + } +} + +# Show list of dependencies for package #################################### +sub depends { + getdependencies($ARGV[1], 1, "") or exiterr("package '$ARGV[1]' not found"); + if (@dependencies) {print "-- dependencies ([i] = installed, [u] = updatable)\n"} + foreach my $dep(@dependencies) { + print "$dep\n"; + } + if (%missingdeps) { + print "\n-- missing packages\n"; + foreach my $dep(sort keys %missingdeps) { + print "$dep from $missingdeps{$dep}\n"; + } + } +} + +# Show compact list of dependencies for package ############################ +sub quickdep { + getdependencies($ARGV[1], 0, "") or exiterr("package '$ARGV[1]' not found"); + foreach my $dep(@dependencies) { + print "$dep "; + } + print "\n"; +} + +# Show packages directly depending from given package ###################### +sub dependent { + my $arg = $ARGV[1]; + my %dp; + if (not $all) { getinstalled(); } + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(DEPS, "$dir/PKGDEPS") + or exiterr("could not open $dir/PKGDEPS"); + while () { + chomp; + my $dep = $_; + $dep =~ s/\s+\:.*$//; + s/^.*\: /\,/; + s/$/\,\$/; + if ( /\,\Q$arg\E\,/ ) { + if (not $all) { + if ($installed{$dep}) { + $dp{$dep} = 1; + } + } else { + $dp{$dep} = 1; + } + } + } + close(DEPS); + } + foreach my $res(keys %dp) { + print "$res\n"; + } +} + +# Install given package #################################################### +sub install { + $curraction = "installed"; + my @args = @_; shift(@args); + getinstalled(); + foreach my $pkgname(@args) { + my %pkg = getpackage($pkgname, 1); + if (not %pkg) { + push(@failtasks, "not found,$pkgname"); + } elsif (getshortstatus(%pkg) ne "[ ]") { + push(@prevtasks, "$pkgname"); + } elsif (downloadpkg(%pkg) and installpkg("", %pkg)) { + push(@donetasks, $pkgname); + } else { + push(@failtasks, "where install failed,$pkgname"); + } + } + printresults(); +} + +# Update given package ##################################################### +sub update { + $curraction = "updated"; + my @args = @_; shift(@args); + getinstalled(); + foreach my $pkgname(@args) { + my %pkg = getpackage($pkgname, 1); + if (not %pkg) { + push(@failtasks, "not found,$pkgname"); + } elsif (getshortstatus(%pkg) eq "[ ]") { + push(@prevtasks, "$pkgname"); + } elsif (downloadpkg(%pkg) and installpkg("-u ", %pkg)) { + push(@donetasks, $pkgname); + } else { + push(@failtasks, "where update failed,$pkgname"); + } + } + printresults(); +} + +# Update out of date packages ############################################## +sub sysup { + my %found; + my @diff; + foreach my $repo(@repos) { + my @r = split(/\|/, $repo); + my $dir = $r[0]; + my $url = $r[1]; + open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO"); + while () { + chomp; + my %pkg; + %pkg = parsepackage($_, $dir, $url, 1); + if (not $found{$pkg{'name'}}) { + if ($pkg{'instversion'}) { + if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'} and islocked($pkg{'name'}) eq "no") { + push(@diff, $pkg{'name'}); + } + } + $found{$pkg{'name'}} = 1; + } + } + close(REPO); + } + if (@diff) { + unshift(@diff, "dummy"); # is shifted later in update sub; + update(@diff); + } +} + +sub depinst { + my @toinst; my %seen; + $curraction = "installed"; + my @args = @ARGV; shift(@args); + getinstalled(); + foreach my $pkgname(@args) { + getdependencies($pkgname, 0, ""); + foreach my $dep(@dependencies) { + if (not $seen{$dep}) { + my %pkg = getpackage($dep, 1); + if (%pkg) { + if (getshortstatus(%pkg) eq "[ ]"){ + push(@toinst, $pkg{'name'}); + } + } + $seen{$dep} = 1; + } + } + } + if (@toinst) { + unshift(@toinst, "dummy"); # is shifted later in install sub; + install(@toinst); + } +} diff --git a/scripts/pkg-get_completion.sh b/scripts/pkg-get_completion.sh new file mode 100755 index 0000000..d65366c --- /dev/null +++ b/scripts/pkg-get_completion.sh @@ -0,0 +1,70 @@ +# pkg-get(8) completion by Simone Rota +# derived form Johannes Winkelmann's prt-get completion +# problems: options ending on = should not add a space afterwards + + +_pkg-get() +{ + local cur prev + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + prev=${COMP_WORDS[COMP_CWORD-1]} + + if [ $COMP_CWORD -eq 1 ]; then + COMPREPLY=( $( compgen -W ' \ + install depinst update help \ + version readme list info path \ + search dsearch printf sync \ + dependent sysup current lock unlock \ + listlocked diff quickdiff depends quickdep \ + dup isinst remove listinst' $cur )) + fi + + + if [ $COMP_CWORD '>' 1 ]; then + if [[ "$cur" != -* ]]; then + case ${COMP_WORDS[1]} in + "install" | "depinst" | "path" | "dependent" | \ + "depends" | "quickdep" | "info" | "readme" | \ + "isinst" ) + plist=`pkg-get list` + if [ ! "$plist" == "" ]; then + COMPREPLY=( $( compgen -W '$plist' $cur ) ) + fi + ;; + "current"|"lock"|"remove") + plist=`pkg-get listinst` + COMPREPLY=( $( compgen -W '$plist' $cur ) ) + ;; + "update") + plist=`pkg-get quickdiff` + COMPREPLY=( $( compgen -W '$plist' $cur ) ) + ;; + "unlock") + plist=`pkg-get listlocked` + COMPREPLY=( $( compgen -W '$plist' $cur ) ) + ;; + esac + else + case ${COMP_WORDS[1]} in + "install" | "update" | "sysup") + COMPREPLY=( $( compgen -W '-do \ + --pre-install \ + --post-install \ + --install-scripts' \ + -- $cur ) ) + ;; + "dependent" ) + COMPREPLY=( $( compgen -W '--all' -- $cur ) ) + ;; + "printf" ) + COMPREPLY=( $( compgen -W '--filter=' -- $cur ) ) + ;; + esac + fi + fi + + return 0 +} +complete -F _pkg-get -o default pkg-get diff --git a/scripts/pkg-repgen.pl b/scripts/pkg-repgen.pl new file mode 100755 index 0000000..1545b65 --- /dev/null +++ b/scripts/pkg-repgen.pl @@ -0,0 +1,333 @@ +#!/usr/bin/env perl +# +# pkg-repgen: generates a binary repository for pkg-get +# +# requires prt-get +# +# html index generation code adapted from Jukka Heino's portspage +# +# usage: pkg-repgen [..] +# + +use warnings; +use strict; +use Getopt::Long; + +our $title = "CRUX Packages"; our $header; our $footer; +GetOptions("title=s"=>\$title, "header=s"=>\$header, "footer=s"=>\$footer); + +if ($#ARGV >= 0) { # single packages + pkgrepo_single(); + pkgdeps_single(); + pkgread(); + pkginst(); +} else { + pkgrepo(); + pkgdeps(); + pkgread(); + pkginst(); +} + +######################## single packages ######################## + +# generate dependencies +sub pkgdeps_single { + print "+ Generating dependencies\n"; + my $hasnew = 0; + foreach my $p (@ARGV) { + my @packages = glob("$p#*.pkg.tar.gz"); + if ($#packages == 0) { + my $found = 0; + my $package = $packages[0]; + $package =~ s/#.*//; + my $deps = `prt-get printf "%e" --filter="$package"`; + if ($deps ne "") { + my $isnew = `grep "$p .*:" PKGDEPS`; + if ($isnew eq ""){ # package is new, put deps at the end. + open (my $fh, '>>PKGDEPS'); + printf $fh "%-30s : %-s\n", $package, $deps; + close $fh; + $hasnew = 1; + } else { + system("sed -i \"/^$p /s/: .*\$/: $deps/\" PKGDEPS"); + } + } + + } else { + print "Package '$p' not found or duplicate\n" + } + } + if ($hasnew == 1){system("sort -o PKGDEPS PKGDEPS")}; +} + +# generate the main repository file +sub pkgrepo_single { + print "+ Generating repository\n"; + my $hasnew = 0; + foreach my $p (@ARGV) { + my @packages = glob("$p#*.pkg.tar.gz"); + if ($#packages == 0) { + my $found = 0; + my $package = $packages[0]; + my $name = $package; + $name =~ s/#.*//; + my $du = (-s $package); + my $md5 = `md5sum $package`; + $md5 =~ s/ .*$|\n//g; + my $des=`prt-get printf %d --filter="$name"`; + $des =~ s/:/ /g; + if ($des eq ""){$des = "N.A."}; + my $flags=`prt-get printf %E:%O:%R --filter="$name"`; + if ($flags eq "") {$flags = "no:no:no"} + my $isnew = `grep "$p#" PKGREPO`; + if ($isnew eq ""){ # package is new, put it at the end + open (my $fh, '>>PKGREPO'); + printf $fh "%-s:%-s:%-s:%-s:%-s\n", $package,$du,$md5,$des,$flags; + close $fh; + $hasnew = 1; + } else { + my $newp = "$package:$du:$md5:$des:$flags"; + system("sed -i \"s/^$p#.*\$/$newp/\" PKGREPO"); + } + #printf $fh "%-s:%-s:%-s:%-s\n", $du,$md5,$des,$flags; + } else { + print "Package '$p' not found or duplicate\n" + } + } + if ($hasnew == 1){system("sort -o PKGREPO PKGREPO")}; +} + + +######################## full repository ######################## + +# generate dependencies +sub pkgdeps { + print "+ Generating dependencies\n"; + my @packages = glob("*#*.pkg.tar.gz"); + open (my $fh, '>PKGDEPS'); + foreach my $package (@packages) { + $package =~ s/#.*//; + my $deps = `prt-get printf "%e" --filter="$package"`; + if ($deps ne "") { + printf $fh "%-30s : %-s\n", $package, $deps; + } + } + close $fh; +} + +# generate the main repository file and index page +sub pkgrepo { + print "+ Generating repository\n"; + my @packages = glob("*#*.pkg.tar.gz"); + our $odd = "odd"; + my $count = 0; + open (my $fh, '>PKGREPO'); + printheader(); + open (my $ih, '>>index.html'); + foreach my $package (@packages) { + my $date = (stat($package))[9]; + $count++; + $package =~ s/\n//g; + my $name = $package; + $name =~ s/#.*//; + my $du = (-s $package); + my $md5 = `md5sum $package`; + $md5 =~ s/ .*$|\n//g; + my $des=`prt-get printf %d --filter="$name"`; + $des =~ s/:/ /g; + if ($des eq ""){$des = "N.A."}; + my $flags=`prt-get printf %E:%O:%R --filter="$name"`; + if ($flags eq "") {$flags = "no:no:no"} + printf $fh "%-s:%-s:%-s:%-s:%-s\n", $package,$du,$md5,$des,$flags; + my $version = $package; + $version =~ s/^.*\#//; + $version =~ s/\.pkg\.tar\.gz//; + print $ih " "; + print $ih "$name"; + my $url = $package; + $url =~ s/\#/\%23/; + print $ih "$version"; + print $ih "$des"; + print $ih "" . isotime($date, 1) . ""; + print $ih "\n"; + + if ($odd eq "odd") { $odd = "even"; } + else { $odd = "odd"; } + } + close $fh; + close $ih; + printfooter($count); +} + +# generate README file +sub pkgread { + print "+ Generating README\n"; + my @packages = glob("*#*.pkg.tar.gz"); + open (my $fh, '>PKGREAD'); + print $fh "# README files for repository. Do NOT remove this line.\n"; + foreach my $package (@packages) { + $package =~ s/#.*//; + my $path = `prt-get path $package`; + $path =~ s/\n//g; + if (-f "$path/README"){ + print $fh "##### PKGREADME: $package\n"; + open(my $readme, "$path/README"); + while (<$readme>){ + my $line = $_; + print $fh $line; + } + close($readme); + } + } + close $fh; +} + +# generate pre-post install scripts file +sub pkginst { + print "+ Generating scripts\n"; + open (my $fh, '>PKGINST'); + print $fh +" +#!/bin/bash +# +# PKGINST: pre-post install scripts for CRUX packages +"; + my @packages = glob("*#*.pkg.tar.gz"); + foreach my $package (@packages) { + $package =~ s/#.*//; + my $path = `prt-get path $package`; + $path =~ s/\n//g; + my $normal= $package; + $normal =~ s/[^[:alnum:]]/_/g; + if (-f "$path/pre-install"){ + print $fh "${normal}_pre_install() {\n"; + open(my $pre, "$path/pre-install"); + while (<$pre>){ + my $line = $_; + print $fh $line; + } + close($pre); + print $fh "}\n\n"; + } + if (-f "$path/post-install"){ + print $fh "${normal}_post_install() {\n"; + open(my $post, "$path/post-install"); + while (<$post>){ + my $line = $_; + print $fh $line; + } + close($post); + print $fh "}\n\n"; + } + } + print $fh "\n\n"; + print $fh 'if [ ! -z "$1" ]; then $1; fi'; + print $fh "\n"; + close $fh; +} + + +######################## html index subs ######################## + +sub printheader { + open (my $ih, '>index.html'); + print $ih < + + +EOH + + print $ih " $title\n"; + + print $ih < + body + { + font-family: Verdana, sans-serif; + font-size: 85%; + padding: 2em; + } + a + { + color: #67550d; + } + table + { + border: solid #e5dccf 1px; + font-size: 85%; + } + td + { + padding: 6px; + } + tr.header + { + background-color: #e5dccf; + } + tr.odd + { + background-color: #f7f3ed; + } + tr.even + { + background-color: #fcf9f8; + } + + + + +EOH + + print $ih "

$title

\n"; + if ($header) { + open(FILE, $header) or die "Couldn't open header file"; + while () { + print $ih " " . $_; + } + close(FILE); + } + + print $ih " \n"; + print $ih " "; + print $ih ""; + print $ih "\n"; + close($ih); +} + +sub printfooter { + my $count = $_[0]; + open (my $ih, '>>index.html'); + print $ih "
PortVersionDescriptionLast modified
\n"; + print $ih "

$count packages

\n"; + if ($footer) { + open(FILE, $footer) or die "Couldn't open footer file"; + while () { + print $ih " " . $_; + } + close(FILE); + } + print $ih "

Generated by pkg-repgen on " . isotime() . ".

\n"; + print $ih < + +EOH + close($ih); + +} + +sub isotime { + my $time = (shift or time); + my $accuracy = (shift or 2); + my @t = gmtime ($time); + my $year = $t[5] + 1900; + my $month = sprintf("%02d", $t[4] + 1); + my $day = sprintf("%02d", $t[3]); + + if ($accuracy == 1) { + return "$year-$month-$day"; + } + + return "$year-$month-$day " . sprintf("%02d:%02d:%02d UTC", $t[2], $t[1], $t[0]); +} +