helper: Print /modules when verbose >= 2
[febootstrap.git] / febootstrap.sh
1 #!/bin/bash -
2 # febootstrap
3 # (C) Copyright 2009 Red Hat Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #
19 # Written by Richard W.M. Jones <rjones@redhat.com>
20
21 unset CDPATH
22
23 TEMP=`getopt \
24         -o g:i:p:u: \
25         --long groupinstall:,group-install:,help,install:,noclean,no-clean,proxy:,updates: \
26         -n febootstrap -- "$@"`
27 if [ $? != 0 ]; then
28     echo "febootstrap: problem parsing the command line arguments"
29     exit 1
30 fi
31 eval set -- "$TEMP"
32
33 declare -a packages
34 packages[0]="@Core"
35 i=0
36
37 clean=yes
38
39 usage ()
40 {
41     echo "Usage: febootstrap [--options] REPO TARGET [MIRROR]"
42     echo "Please read febootstrap(8) man page for more information."
43 }
44
45 while true; do
46     case "$1" in
47         -i|--install)
48             packages[i++]="$2"
49             shift 2;;
50         -g|--groupinstall|--group-install)
51             packages[i++]="@$2"
52             shift 2;;
53         -p|--proxy)
54             proxy="proxy=$2"
55             shift 2;;
56         -u|--updates)
57             updates="$2";
58             shift 2;;
59         --noclean|--no-clean)
60             clean=no
61             shift;;
62         --help)
63             usage
64             exit 0;;
65         --)
66             shift
67             break;;
68         *)
69             echo "Internal error!"
70             exit 1;;
71     esac
72 done
73
74 if [ $# -lt 2 -o $# -gt 3 ]; then
75     usage
76     exit 1
77 fi
78
79 repo="$1"
80 target="$2"
81 mirror="$3"
82
83 # Architecture is currently always the same as the current arch.  We
84 # cannot do --foreign builds.  See discussion in the manpage.
85 arch=$(uname -m)
86 case $arch in
87     i?86) arch=i386 ;;
88 esac
89
90 # Create a temporary directory, make sure it gets cleaned up at the end.
91 tmpdir=$(mktemp -d)
92 remove_tmpdir ()
93 {
94   status=$?
95   rm -rf "$tmpdir" && exit $status
96 }
97 trap remove_tmpdir EXIT
98
99 # Create the temporary repository configuration.  The name of the
100 # repository is always 'febootstrap'.
101 cat > $tmpdir/febootstrap.repo <<__EOF__
102 [febootstrap]
103 name=febootstrap $repo $arch
104 failovermethod=priority
105 enabled=1
106 gpgcheck=0
107 $proxy
108 __EOF__
109
110 # "Mirror" parameter is a bit misnamed, but it means a local mirror,
111 # instead of the public Fedora mirrors.
112 if [ -n "$mirror" ]; then
113     echo "baseurl=$mirror" >> "$tmpdir"/febootstrap.repo
114 else
115     echo "mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=$repo&arch=$arch" >> "$tmpdir"/febootstrap.repo
116 fi
117
118 # Add the updates repository if asked.
119 case "$updates" in
120     ""|none|no)
121         ;;
122     *://*)
123         cat >> $tmpdir/febootstrap.repo <<EOF
124
125 [febootstrap-updates]
126 name=febootstrap updates $arch
127 failovermethod=priority
128 enabled=1
129 gpgcheck=0
130 $proxy
131 baseurl=$updates
132 EOF
133 addrepo=febootstrap-updates
134         ;;
135     *)
136         cat >> $tmpdir/febootstrap.repo <<EOF
137
138 [febootstrap-updates]
139 name=febootstrap $updates $arch
140 failovermethod=priority
141 enabled=1
142 gpgcheck=0
143 $proxy
144 mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=$updates&arch=$arch
145 EOF
146 addrepo=febootstrap-updates
147         ;;
148 esac
149
150 # Create the target filesystem.
151 rm -rf "$target"
152 mkdir "$target"
153
154 # Target must be an absolute path.
155 target=$(cd "$target" > /dev/null; pwd)
156
157 # This is necessary to keep yum happy.  It's not clear why yum can't
158 # just create this file itself.
159 mkdir -p "$target"/var/cache/yum/febootstrap/packages
160
161 # NB: REQUIRED for useradd/groupadd to run properly.
162 #
163 # However this causes 'filesystem' RPM install to give the
164 # following error.  Not sure how serious the error is:
165 # error: unpacking of archive failed on file /proc: cpio: utime
166 export FAKECHROOT_EXCLUDE_PATH=/proc
167
168 # Substitute some statically-linked commands.  This is only supported
169 # in fakechroot > 2.9.  For previous versions of fakechroot it is
170 # ignored.
171 export FAKECHROOT_CMD_SUBST=/sbin/ldconfig=/bin/true:/usr/sbin/glibc_post_upgrade.i686=/bin/true:/usr/sbin/glibc_post_upgrade.x86_64=/bin/true:/usr/sbin/build-locale-archive=/bin/true:/usr/sbin/libgcc_post_upgrade=/bin/true
172
173 # Use the libraries inside the chroot.
174 export LD_LIBRARY_PATH="$target"/usr/lib64:"$target"/usr/lib:"$target"/lib64:"$target"/usr/lib
175
176 # Make the device nodes inside the fake chroot.
177 # (Copied from mock/backend.py)  Why isn't there a base package which
178 # creates these?
179 make_device_nodes ()
180 {
181     mkdir "$target"/proc
182     mkdir "$target"/sys
183     mkdir "$target"/dev
184     (
185         cd "$target"/dev
186         mkdir pts
187         mkdir shm
188         mkdir mapper
189         mknod null c 1 3;    chmod 0666 null
190         mknod full c 1 7;    chmod 0666 full
191         mknod zero c 1 5;    chmod 0666 zero
192         mknod random c 1 8;  chmod 0666 random
193         mknod urandom c 1 9; chmod 0444 urandom
194         mknod tty c 5 0;     chmod 0666 tty
195         mknod console c 5 1; chmod 0600 console
196         mknod ptmx c 5 2;    chmod 0666 ptmx
197         ln -sf /proc/self/fd/0 stdin
198         ln -sf /proc/self/fd/1 stdout
199         ln -sf /proc/self/fd/2 stderr
200     )
201 }
202 export -f make_device_nodes
203 export target
204
205 if [ $(id -u) -ne 0 ]; then
206     fakeroot -s "$target"/fakeroot.log \
207     make_device_nodes
208 else
209     make_device_nodes
210 fi
211
212 repos=febootstrap
213 if [ -n "$addrepo" ]; then
214     repos="$repos,$addrepo"
215 fi
216
217 # Run yum.
218 run_yum ()
219 {
220     yum \
221         -y -c "$tmpdir"/febootstrap.repo \
222         --disablerepo=* --enablerepo=$repos \
223         --noplugins --nogpgcheck \
224         --installroot="$target" \
225         install "$@"
226 }
227 export -f run_yum
228 export tmpdir
229 export repos
230
231 if [ $(id -u) -ne 0 ]; then
232     # Bash doesn't support exporting array variables, hence this
233     # tortuous workaround.
234     fakeroot -i "$target"/fakeroot.log -s "$target"/fakeroot.log \
235     fakechroot -s \
236     bash -c 'run_yum "$@"' run_yum "${packages[@]}"
237 else
238     run_yum "${packages[@]}"
239 fi
240
241 # Clean up the yum repository.
242 if [ "$clean" = "yes" ]; then
243     febootstrap-run "$target" -- rm -rf /var/cache/yum/febootstrap
244     febootstrap-run "$target" -- rm -rf /var/cache/yum/febootstrap-updates
245 fi