Slightly updated, deal with x86_64 and fix bug in arch handling
[rpmbased-dist-chroot.git] / rpmbased-dist-chroot.sh
1 #!/bin/bash
2
3 # rpmbased-dist-chroot.sh - builds a simple chroot from a directory of .rpms
4 #                           best to feed it the RPMS directory of a particular
5 #                           distribution. Has been tested with FC4.
6 # Copyright (C) 2004 Brett Parker <iDunno@sommitrealweird.co.uk>
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22 # Default to expecting a Fedora CD mounted at /media/cdrom
23 # and installing bash, coreutils and yum to /mnt/temp/fedora
24
25 RPMArchives=/media/cdrom/Fedora/RPMS
26 InstallRoot=/mnt/temp/fedora
27 installpackages="bash coreutils yum basesystem redhat-release"
28
29 ourcachedirectory=$(mktemp -d)
30
31 architecture=$(uname -m)
32 export ARCH=$architecture
33
34 case $architecture in
35         x86_64)
36                 architecture="x86_64,i686,i586,i486,i386"
37                 ;;
38         i686)
39                 architecture="i686,i586,i486,i386"
40                 ;;
41         i586)
42                 architecture="i586,i486,i386"
43                 ;;
44         i486)
45                 architecture="i486,i386"
46                 ;;
47 esac
48
49 function displayHelp() {
50 cat <<END
51 Usage: $0 [options]
52
53 Options:
54         --install-root <directorytoinstallto>
55         --rpm-archives <pathtorpms>
56         --install-packages <listofpackagestoinstall>
57 END
58         exit $1
59 }
60
61 function startswithmm() {
62         if [ "${1##--*}" == "" ]; then
63                 return 0
64         else
65                 return 1
66         fi
67 }
68
69 function containsequals() {
70         if [ "${1//*=*}" == "" ]; then
71                 return 0
72         else
73                 return 1
74         fi
75 }
76
77 argcommand=""
78 for option in $@; do
79         if ( ! startswithmm $option ); then
80                 if [ "x$argcommand" == "xinstall-root" ]; then
81                         InstallRoot=$option
82                 elif [ "x$argcommand" == "xrpm-archives" ]; then
83                         RPMArchives=$option
84                 elif [ "x$argcommand" == "xinstall-packages" ]; then
85                         if [ "x$installpackages" == "x" ]; then
86                                 installpackages=$option
87                         else
88                                 installpackages="$installpackages $option"
89                         fi
90                 fi
91         else
92                 if ( containsequals $option ); then
93                         argcommand=${option%%=*}
94                         argcommand=${argcommand##--}
95                         option=${option##*=}
96
97                         if [ "x$argcommand" == "xinstall-root" ]; then
98                                 InstallRoot=$option
99                         elif [ "x$argcommand" == "xrpm-archives" ]; then
100                                 RPMArchives=$option
101                         elif [ "x$argcommand" == "xinstall-packages" ]; then
102                                 installpackages=$option
103                         else
104                                 echo "Unknown option $option"
105                                 exit 1
106                         fi
107                 else
108                         if [ "x$option" == "x--help" ]; then
109                                 displayHelp 0
110                         elif [ "x$option" == "x--install-root" ]; then
111                                 argcommand=${option##--}
112                         elif [ "x$option" == "x--rpm-archives" ]; then
113                                 argcommand=${option##--}
114                         elif [ "x$option" == "x--install-packages" ]; then
115                                 argcommand=${option##--}
116                                 installpackages=""
117                         else
118                                 echo "Unknown option $option"
119                                 exit 1
120                         fi
121                 fi
122         fi
123 done
124
125 echo "Install Packages: $installpackages"
126 echo "RPMArchives     : $RPMArchives"
127 echo "InstallRoot     : $InstallRoot"
128
129 function buildcache() {
130         cd $RPMArchives
131
132         for arch in noarch $(echo $architecture | sed -e 's/,/\n/g'); do
133                 for file in *.$arch.rpm; do
134                         rpm -qpl $file | sed 's#^#'$file':#' >> $ourcachedirectory/files-cache
135                         rpm -qp --provides $file | cut -d " " -f 1 | sed 's#^#'$file':#' >> $ourcachedirectory/package-cache
136                 done
137         done
138 }
139
140 function findrpm() {
141         name=$1
142         if [ -z $name ]; then
143                 return
144         fi
145         cd $RPMArchives
146
147         escapename=$(echo $name | sed -e 's#\+#\\+#g; s#\.#\\.#g; s#(#\\(#g; s#)#\\)#g;')
148
149         if [ ${name:0:1} == "/" ]; then
150                 grep -E "^.*:$escapename\$" $ourcachedirectory/files-cache | cut -d ":" -f 1 | head -n 1
151         else
152                 grep -E "^.*:$escapename\$" $ourcachedirectory/package-cache | cut -d ":" -f 1 | head -n 1
153         fi
154 }
155
156 function getdependencies() {
157         filename=$1
158         name=$2
159
160         rpm -qp --requires ${RPMArchives}/$filename | grep -v '^.*('$name')' | cut -d " " -f 1 | sort | uniq | grep -Ev '^[     ]*$' | while read line; do
161                 if [ ! -z $line ]; then
162                         fname=$(findrpm $line)
163                         packagename=$(getpackagename $fname)
164                         if [ ! -z $name ] && [ ! -z $packagename ]; then
165                                 if [[ $firstpackage == 0 ]]; then
166                                         if ( ! grep '^'$fname' ' $ourcachedirectory/build-packagelist > /dev/null ) && ( ! rpm -r ${InstallRoot} -qv $packagename > /dev/null ); then
167                                                 echo $fname $packagename >> $ourcachedirectory/build-packagelist
168                                                 getdependencies $fname $packagename
169                                         fi
170                                 else
171                                         if ( ! grep '^'$fname' ' $ourcachedirectory/build-packagelist > /dev/null ); then
172                                                 echo $fname $packagename >> $ourcachedirectory/build-packagelist
173                                                 getdependencies $fname $packagename
174                                         fi
175                                 fi
176                         fi
177                 fi
178         done
179 }
180
181 function getpackagename() {
182         filename=$1
183         if [ ! -z $filename ]; then
184                 rpm -qp --queryformat "%{NAME}\n" ${RPMArchives}/$filename
185         fi
186 }
187
188 cd ${InstallRoot}
189 mkdir -p var/lib/rpm
190 mkdir root
191 mkdir etc
192 mkdir usr
193 mkdir dev
194 cp /etc/resolv.conf etc/
195 mknod -m 666 dev/null c 1 3
196 touch etc/fstab
197
198 buildcache
199
200 rpm -r ${InstallRoot} --initdb
201
202 firstpackage=1
203
204 for package in $installpackages; do
205         
206         rm -f $ourcachedirectory/build-packagelist
207         touch $ourcachedirectory/build-packagelist
208
209         echo "Installing packages required for $package"
210         
211         if [[ "x$(findrpm $package)" != "x" ]]; then
212                 
213                 getdependencies $(findrpm $package) $package
214                 echo " RPM File    :" $(findrpm $package)
215                 echo " Dependencies:"
216                 cat $ourcachedirectory/build-packagelist | cut -d ' ' -f 2 | sed -e 's#^#  #;'
217                 
218                 echo rpm -r ${InstallRoot} --ignorearch --install $(cat $ourcachedirectory/build-packagelist | cut -d ' ' -f 1) >> $ourcachedirectory/install-log
219
220                 firstpackage=0
221                 
222                 cd ${RPMArchives} && rpm -r ${InstallRoot} --ignorearch --install $(cat $ourcachedirectory/build-packagelist | cut -d ' ' -f 1)
223                 if ( ! grep " $package\$" $ourcachedirectory/build-packagelist > /dev/null 2>/dev/null ); then
224                         packages="$(findrpm $package)"
225                         echo rpm -r ${InstallRoot} --ignorearch --install "${packages}" >> $ourcachedirectory/install-log
226                         echo "${packages}" >> $ourcachedirectory/packages-installed
227                         cd ${RPMArchives} && rpm -r ${InstallRoot} --ignorearch --install ${packages}
228                 fi
229         else
230                 echo " Failed to find the RPM providing $package - skipping"
231         fi
232 done
233
234 read -p "Remove cache directory ($ourcachedirectory)? [Yn]: " cleanup
235
236 cleanup=${cleanup:0:1}
237
238 if [ "$cleanup" == "N" ] || [ "$cleanup" == "n" ] ; then
239         echo leaving logs in $ourcachedirectory
240 else
241         echo removing logs directory
242         rm -r $ourcachedirectory
243 fi