Initial hack at a DB operations struct
[pacman-ng.git] / contrib / bacman.in
blob2a93f8be7b0fe8fc026343528b8214c1aeeba518
1 #!@BASH@
3 #   bacman: recreate a package from a running system
4 #   This script rebuilds an already installed package using metadata
5 #   stored into the pacman database and system files
7 #   (c) 2008 - locci <carlocci_at_gmail_dot_com>
9 #   This program is free software; you can redistribute it and/or modify
10 #   it under the terms of the GNU General Public License as published by
11 #   the Free Software Foundation; either version 2 of the License, or
12 #   (at your option) any later version.
14 #   This program is distributed in the hope that it will be useful,
15 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 #   GNU General Public License for more details.
19 #   You should have received a copy of the GNU General Public License
20 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 readonly progname="bacman"
24 readonly progver="0.2.1"
27 # User Friendliness
29 function usage(){
30     echo "This program recreates a package using pacman's db and system files"
31     echo "Usage:   $progname <installed package name>"
32     echo "Example: $progname kernel26"
35 if [ $# -ne 1 ] ; then
36     usage
37     exit 1
40 if [ "$1" = "--help" -o "$1" = "-h" ] ; then
41     usage
42     exit 0
45 if [ "$1" = "--version" -o "$1" = "-v" ]; then
46     echo "$progname version $progver"
47     echo "Copyright (C) 2008 locci"
48     exit 0
52 # Fakeroot support
54 if [ $EUID -gt 0 ]; then
55     if [ -f /usr/bin/fakeroot ]; then
56         echo "Entering fakeroot environment"
57         export INFAKEROOT="1"
58         /usr/bin/fakeroot -u -- $0 $1
59         exit $?
60     else
61         echo "WARNING: installing fakeroot or running ${progname} as root is required to"
62         echo "         preserve the ownership permissions of files in some packages"
63         echo ""
64     fi
68 # Setting environmental variables
70 if [ ! -r @sysconfdir@/pacman.conf ]; then
71     echo "ERROR: unable to read @sysconfdir@/pacman.conf"
72     exit 1
75 eval $(awk '/DBPath/ {print $1$2$3}' @sysconfdir@/pacman.conf)
76 pac_db="${DBPath:-@localstatedir@/lib/pacman/}/local"
78 if [ ! -r @sysconfdir@/makepkg.conf ]; then
79     echo "ERROR: unable to read @sysconfdir@/makepkg.conf"
80     exit 1
83 source "@sysconfdir@/makepkg.conf"
84 if [ -r ~/.makepkg.conf ]; then
85     source ~/.makepkg.conf
88 pkg_arch=${CARCH:-'unknown'}
89 pkg_dest="${PKGDEST:-$PWD}"
90 pkg_pkger=${PACKAGER:-'Unknown Packager'}
92 pkg_name="$1"
93 pkg_dir="$(echo $pac_db/$pkg_name-[0-9]*)"
94 pkg_namver="${pkg_dir##*/}"
97 # Checks everything is in place
99 if [ ! -d "$pac_db" ] ; then
100     echo "ERROR: pacman database directory ${pac_db} not found"
101     exit 1
104 if [ ! -d "$pkg_dir" ] ; then
105     echo "ERROR: package ${pkg_name} not found in pacman database"
106     exit 1
110 # Begin
112 echo Package: ${pkg_namver}
113 work_dir=$(mktemp -d -p /tmp)
114 cd "$work_dir" || exit 1
117 # File copying
119 echo "Copying package files..."
121 cat "$pkg_dir"/files |
122 while read i; do
123     if [ -z "$i" ] ; then
124         continue
125     fi
127     if [[ "$i" =~ %[A-Z]*% ]] ; then
128         current=$i
129         continue
130     fi
132     case $current in
133         %FILES%)
134             ret=0
135             if [ -e "/$i" ]; then
136                 bsdtar -cnf - "/$i" 2> /dev/null | bsdtar -xpf -
138                 # Workaround to bsdtar not reporting a missing file as an error
139                 if [ ! -e "$work_dir/$i" -a ! -L "$work_dir/$i" ]; then
140                     echo ""
141                     echo "ERROR: unable to add /$i to the package"
142                     echo "       If your user does not have permssion to read this file then"
143                     echo "       you will need to run $progname as root"
144                     rm -rf "$work_dir"
145                     exit 1
146                 fi
147             else
148                 echo ""
149                 echo "WARNING: package file /$i is missing"
150                 echo ""
151             fi
154         ;;
155     esac
156 done
158 ret=$?
159 if [ $ret -ne 0 ]; then
160     rm -rf "$work_dir"
161     exit 1
164 pkg_size=$(du -sk | awk '{print $1 * 1024}')
167 # .PKGINFO stuff
169 echo Generating .PKGINFO metadata...
170 echo "# Generated by $progname $progver"    > .PKGINFO
171 if [ "$INFAKEROOT" = "1" ]; then
172     echo "# Using $(fakeroot -v)"    >> .PKGINFO
174 echo "# $(LC_ALL=C date)"            >> .PKGINFO
175 echo "#"                    >> .PKGINFO
177 cat "$pkg_dir"/{desc,files,depends} |
178 while read i; do
179     if [[ -z "$i" ]]; then
180         continue;
181     fi
183     if [[ "$i" =~ %[A-Z]*% ]] ; then
184         current=$i
185         continue
186     fi
188     case "$current" in
189         # desc
190         %NAME%)
191             echo "pkgname = $i"    >> .PKGINFO
192         ;;
193         %VERSION%)
194             echo "pkgver = $i"    >> .PKGINFO
195         ;;
196         %DESC%)
197             echo "pkgdesc = $i"    >> .PKGINFO
198         ;;
199         %URL%)
200             echo "url = $i"    >> .PKGINFO
201         ;;
202         %LICENSE%)
203             echo "license = $i"    >> .PKGINFO
204         ;;
205         %ARCH%)
206             echo "arch = $i"    >> .PKGINFO
207         ;;
208         %BUILDDATE%)
209             echo "builddate = $(date -u "+%s")"    >> .PKGINFO
210         ;;
211         %PACKAGER%)
212             echo "packager = $pkg_pkger"        >> .PKGINFO
213         ;;
214         %SIZE%)
215             echo "size = $pkg_size"        >> .PKGINFO
216         ;;
217         %GROUPS%)
218             echo "group = $i"    >> .PKGINFO
219         ;;
220         %REPLACES%)
221             echo "replaces = $i"    >> .PKGINFO
222         ;;
223         %FORCE%)
224             echo "force = true" >> .PKGINFO
225         ;;
227         # files
228         %BACKUP%)
229             # strip the md5sum after the tab
230             echo "backup = ${i%%$'\t'*}"   >> .PKGINFO
231         ;;
233         # depends
234         %DEPENDS%)
235             echo "depend = $i"   >> .PKGINFO
236         ;;
237         %OPTDEPENDS%)
238             echo "optdepend = $i" >> .PKGINFO
239         ;;
240         %CONFLICTS%)
241             echo "conflict = $i" >> .PKGINFO
242         ;;
243         %PROVIDES%)
244             echo "provides = $i"  >> .PKGINFO
245         ;;
246     esac
247 done
249 comp_files=".PKGINFO"
251 if [ -f "$pkg_dir/install" ] ; then
252     cp "$pkg_dir/install" "$work_dir/.INSTALL"
253     comp_files+=" .INSTALL"
255 if  [ -f $pkg_dir/changelog ] ; then
256     cp "$pkg_dir/changelog" "$work_dir/.CHANGELOG"
257     comp_files+=" .CHANGELOG"
261 # Fixes owner:group and permissions for .PKGINFO, .CHANGELOG, .INSTALL
263 chown root:root "$work_dir"/{.PKGINFO,.CHANGELOG,.INSTALL} 2> /dev/null
264 chmod 644 "$work_dir"/{.PKGINFO,.CHANGELOG,.INSTALL} 2> /dev/null
267 # Generate the package
269 echo "Generating the package..."
271 case "$PKGEXT" in
272         *tar.gz)  EXT=${PKGEXT%.gz} ;;
273         *tar.bz2) EXT=${PKGEXT%.bz2} ;;
274         *tar.xz)  EXT=${PKGEXT%.xz} ;;
275         *tar)     EXT=${PKGEXT} ;;
276         *) echo "WARNING: '%s' is not a valid archive extension." \
277         "$PKGEXT" ; EXT=$PKGEXT ;;
278 esac
280 pkg_file="$pkg_dest/$pkg_namver-$pkg_arch${PKGEXT}"
281 ret=0
283 # when fileglobbing, we want * in an empty directory to expand to
284 # the null string rather than itself
285 shopt -s nullglob
286 # TODO: Maybe this can be set globally for robustness
287 shopt -s -o pipefail
288 bsdtar -cf - $comp_files * |
289 case "$PKGEXT" in
290     *tar.gz)  gzip -c -f -n ;;
291     *tar.bz2) bzip2 -c -f ;;
292     *tar.xz)  xz -c -z - ;;
293     *tar)     cat ;;
294 esac > ${pkg_file} || ret=$?
296 if [ $ret -ne 0 ]; then
297     echo "ERROR: unable to write package to $pkg_dest"
298     echo "       Maybe the disk is full or you do not have write access"
299     rm -rf "$work_dir"
300     exit 1
303 rm -rf "$work_dir"
305 echo Done
307 exit 0
309 # vim: set ts=2 sw=2 noet: