summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimone Rota <simone@sip.local>2006-07-13 04:21:42 +0200
committerSimone Rota <simone@sip.local>2006-07-13 04:21:42 +0200
commit871478faf45ea92b1f4b93696f19fd323605a76b (patch)
tree465e6d55d54b5d8f175d62f8eff8bb773da3dc7a
downloadpkg-get-871478faf45ea92b1f4b93696f19fd323605a76b.tar.gz
pkg-get-871478faf45ea92b1f4b93696f19fd323605a76b.tar.xz
Initial import
-rw-r--r--COPYING340
-rw-r--r--ChangeLog64
-rw-r--r--Makefile33
-rw-r--r--README44
-rw-r--r--TODO6
-rw-r--r--doc/pkg-get.8234
-rw-r--r--doc/pkg-get.8.txt101
-rw-r--r--doc/pkg-get.conf13
-rw-r--r--doc/pkg-repgen.843
-rw-r--r--doc/pkg-repgen.8.txt34
-rwxr-xr-xscripts/pkg-get.pl1169
-rwxr-xr-xscripts/pkg-get_completion.sh70
-rwxr-xr-xscripts/pkg-repgen.pl333
13 files changed, 2484 insertions, 0 deletions
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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 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.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
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 <arguments> [\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 <package1> [<package2>..<packageN>]
+Install given packages,
+download if necessary.
+.TP
+.B
+update <package1> [<package2>..<packageN>]
+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 <package1> [<package2>..<packageN>]
+Install given packages
+and relative dependencies.
+.TP
+.B
+depends <package>
+Show a recursive list of dependencies for package
+and their installation status.
+.TP
+.B
+dependent <package> [\fB--all\fP]
+Show installed (or all with the \fB--all\fP option) packages
+that depend from package.
+.TP
+.B
+quickdep <package>
+Show a brief list of dependencies for package.
+.TP
+.B
+info <package>
+Show information about package.
+.TP
+.B
+current <package>
+Show currently installed version of package.
+.TP
+.B
+path <package>
+Show local path of package.
+.TP
+.B
+readme <package>
+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 <package>
+Display whether a package is installed.
+.TP
+.B
+dsearch <string>
+Search for packages which name or description contain <string>.
+.TP
+.B
+search <string>
+Search for packages which name contains <string>.
+.TP
+.B
+dup
+List all duplicates ports (present in more than one repository).
+.TP
+.B
+printf <format string1> [\fB--filter\fP=<filter>]
+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 <package1> [<package2>..<packageN>]
+Lock a package (ignore updates).
+.TP
+.B
+unlock <package1> [<package2>..<packageN>]
+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 <root>
+Use <root> 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 <sip@varlock.com>
+.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 <arguments> [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 <package1> [<package2>..<packageN>] Install given packages,
+ download if necessary.
+ update <package1> [<package2>..<packageN>] 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 <package1> [<package2>..<packageN>] Install given packages
+ and relative dependencies.
+ depends <package> Show a recursive list of dependencies for package
+ and their installation status.
+ dependent <package> [--all] Show installed (or all with the --all option) packages
+ that depend from package.
+ quickdep <package> Show a brief list of dependencies for package.
+ info <package> Show information about package.
+ current <package> Show currently installed version of package.
+ path <package> Show local path of package.
+ readme <package> Print README information (if available) for the package.
+ list List all packages in the repository.
+ listinst List all installed packages.
+ isinst <package> Display whether a package is installed.
+ dsearch <string> Search for packages which name or description contain <string>.
+ search <string> Search for packages which name contains <string>.
+ dup List all duplicates ports (present in more than one repository).
+ printf <format string1> [--filter=<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 <package1> [<package2>..<packageN>] Lock a package (ignore updates).
+ unlock <package1> [<package2>..<packageN>] 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 <root> Use <root> 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 <sip@varlock.com>
+
+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 <sip@varlock.com>
+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 <sip@varlock.com>
+ 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 <sip@varlock.com>
+#
+# 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 (<CFG>) {
+ 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 (<DEPS>) {
+ 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 (<READ>) {
+ 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 (<DB>) {
+ 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 (<LCK>) {
+ 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 (<LCK>) {
+ 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 (<REPO>) {
+ 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 <sip\@varlock.com>\n";
+}
+
+# Show brief help ##########################################################
+sub help {
+ print "Usage: pkg-get command <package1> [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 <root> use <root> 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<LCK>) {
+ 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 (<LCK>) {
+ 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<REPO>) {
+ 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 (<DEPS>) {
+ 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 (<REPO>) {
+ 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 [<pkgname1>..<pkgnameN>]
+#
+
+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 " <tr class=\"$odd\">";
+ print $ih "<td>$name</td>";
+ my $url = $package;
+ $url =~ s/\#/\%23/;
+ print $ih "<td><a href=\"$url\">$version</a></td>";
+ print $ih "<td>$des</td>";
+ print $ih "<td>" . isotime($date, 1) . "</td>";
+ print $ih "</tr>\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;
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+EOH
+
+ print $ih " <title>$title</title>\n";
+
+ print $ih <<EOH;
+ <style type="text/css">
+ 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;
+ }
+ </style>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+ </head>
+ <body>
+EOH
+
+ print $ih " <h2>$title</h2>\n";
+ if ($header) {
+ open(FILE, $header) or die "Couldn't open header file";
+ while (<FILE>) {
+ print $ih " " . $_;
+ }
+ close(FILE);
+ }
+
+ print $ih " <table width=\"100%\" cellspacing=\"0\">\n";
+ print $ih " <tr class=\"header\"><td><b>Port</b></td><td><b>Version</b></td><td><b>Description</b></td>";
+ print $ih "<td><b>Last modified</b></td>";
+ print $ih "</tr>\n";
+ close($ih);
+}
+
+sub printfooter {
+ my $count = $_[0];
+ open (my $ih, '>>index.html');
+ print $ih " </table>\n";
+ print $ih " <p><b>$count packages</b></p>\n";
+ if ($footer) {
+ open(FILE, $footer) or die "Couldn't open footer file";
+ while (<FILE>) {
+ print $ih " " . $_;
+ }
+ close(FILE);
+ }
+ print $ih " <p><i>Generated by <a href=\"http://www.varlock.com/blosxom.cgi/CruxProjects/pkgget/index.html\">pkg-repgen</a> on " . isotime() . ".</i></p>\n";
+ print $ih <<EOH;
+ </body>
+</html>
+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]);
+}
+

Generated by cgit