]>
Commit | Line | Data |
---|---|---|
9efd10cd | 1 | #!/bin/bash |
fcac2376 AM |
2 | # |
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 | |
6 | # | |
958b41fa | 7 | # Copyright (c) 2008 locci <carlocci_at_gmail_dot_com> |
1dd34058 | 8 | # Copyright (c) 2008-2013 Pacman Development Team <pacman-dev@archlinux.org> |
fcac2376 AM |
9 | # |
10 | # This program is free software; you can redistribute it and/or modify | |
11 | # it under the terms of the GNU General Public License as published by | |
12 | # the Free Software Foundation; either version 2 of the License, or | |
13 | # (at your option) any later version. | |
14 | # | |
15 | # This program is distributed in the hope that it will be useful, | |
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | # GNU General Public License for more details. | |
19 | # | |
20 | # You should have received a copy of the GNU General Public License | |
21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
22 | # | |
23 | ||
273cc66a | 24 | shopt -s extglob |
25 | shopt -s nullglob | |
26 | ||
1038e669 | 27 | declare -r myname='bacman' |
a77e638c | 28 | declare -r myver='@PACKAGE_VERSION@' |
6e0c47d2 | 29 | USE_COLOR='y' |
ec15e859 X |
30 | # Required for fakeroot because options are shifted off the array. |
31 | ARGS=("$@") | |
6e0c47d2 WG |
32 | |
33 | m4_include(../scripts/library/output_format.sh) | |
fcac2376 AM |
34 | |
35 | # | |
36 | # User Friendliness | |
37 | # | |
7e5bbf03 | 38 | usage() { |
3f937c84 | 39 | echo "This program recreates a package using pacman's db and system files" |
6e0c47d2 | 40 | echo "Usage: $myname [--nocolor] <installed package name>" |
1038e669 | 41 | echo "Example: $myname kernel26" |
fcac2376 AM |
42 | } |
43 | ||
a77e638c LF |
44 | version() { |
45 | printf "%s %s\n" "$myname" "$myver" | |
46 | echo 'Copyright (C) 2008 locci <carlocci_at_gmail_dot_com>' | |
47 | } | |
48 | ||
6e0c47d2 WG |
49 | if [[ $1 == "--nocolor" ]]; then |
50 | USE_COLOR='n' | |
51 | shift | |
52 | fi | |
53 | ||
54 | m4_include(../scripts/library/term_colors.sh) | |
55 | ||
7e5bbf03 | 56 | if (( $# != 1 )); then |
3f937c84 | 57 | usage |
58 | exit 1 | |
fcac2376 AM |
59 | fi |
60 | ||
a77e638c | 61 | if [[ $1 = -@(h|-help) ]]; then |
3f937c84 | 62 | usage |
63 | exit 0 | |
a77e638c LF |
64 | elif [[ $1 = -@(V|-version) ]]; then |
65 | version | |
3f937c84 | 66 | exit 0 |
fcac2376 AM |
67 | fi |
68 | ||
69 | # | |
70 | # Fakeroot support | |
71 | # | |
7e5bbf03 | 72 | if (( EUID )); then |
73 | if [[ -f /usr/bin/fakeroot ]]; then | |
6e0c47d2 | 74 | msg "Entering fakeroot environment" |
3f937c84 | 75 | export INFAKEROOT="1" |
ec15e859 | 76 | /usr/bin/fakeroot -u -- "$0" "${ARGS[@]}" |
3f937c84 | 77 | exit $? |
78 | else | |
6e0c47d2 WG |
79 | warning "installing fakeroot or running $myname as root is required to" |
80 | plain " preserve the ownership permissions of files in some packages\n" | |
3f937c84 | 81 | fi |
fcac2376 AM |
82 | fi |
83 | ||
84 | # | |
85 | # Setting environmental variables | |
86 | # | |
7e5bbf03 | 87 | if [[ ! -r @sysconfdir@/pacman.conf ]]; then |
6e0c47d2 | 88 | error "unable to read @sysconfdir@/pacman.conf" |
3f937c84 | 89 | exit 1 |
fcac2376 AM |
90 | fi |
91 | ||
05f0a289 N |
92 | eval $(awk '/DBPath/ {print $1$2$3}' @sysconfdir@/pacman.conf) |
93 | pac_db="${DBPath:-@localstatedir@/lib/pacman/}/local" | |
fcac2376 | 94 | |
7e5bbf03 | 95 | if [[ ! -r @sysconfdir@/makepkg.conf ]]; then |
6e0c47d2 | 96 | error "unable to read @sysconfdir@/makepkg.conf" |
3f937c84 | 97 | exit 1 |
fcac2376 AM |
98 | fi |
99 | ||
05f0a289 | 100 | source "@sysconfdir@/makepkg.conf" |
7e5bbf03 | 101 | if [[ -r ~/.makepkg.conf ]]; then |
3f937c84 | 102 | source ~/.makepkg.conf |
fcac2376 AM |
103 | fi |
104 | ||
fcac2376 AM |
105 | pkg_dest="${PKGDEST:-$PWD}" |
106 | pkg_pkger=${PACKAGER:-'Unknown Packager'} | |
107 | ||
108 | pkg_name="$1" | |
d6e3446e | 109 | pkg_dir=("$pac_db/$pkg_name"-+([^-])-+([^-])) |
22abe27b | 110 | pkg_namver=("${pkg_dir[@]##*/}") |
fcac2376 AM |
111 | |
112 | # | |
113 | # Checks everything is in place | |
114 | # | |
7e5bbf03 | 115 | if [[ ! -d $pac_db ]]; then |
6e0c47d2 | 116 | error "pacman database directory ${pac_db} not found" |
3f937c84 | 117 | exit 1 |
fcac2376 AM |
118 | fi |
119 | ||
22abe27b | 120 | if (( ${#pkg_dir[@]} != 1 )); then |
6e0c47d2 | 121 | error "%d entries for package %s found in pacman database" \ |
22abe27b | 122 | ${#pkg_dir[@]} "${pkg_name}" |
6e0c47d2 | 123 | msg2 "%s" "${pkg_dir[@]}" |
22abe27b | 124 | exit 1 |
125 | fi | |
126 | ||
7e5bbf03 | 127 | if [[ ! -d $pkg_dir ]]; then |
6e0c47d2 | 128 | error "package %s is found in pacman database," "${pkg_name}" |
3f99cfba | 129 | plain " but '%s' is not a directory" "${pkg_dir}" |
3f937c84 | 130 | exit 1 |
fcac2376 AM |
131 | fi |
132 | ||
133 | # | |
134 | # Begin | |
135 | # | |
6e0c47d2 | 136 | msg "Package: ${pkg_namver}" |
273cc66a | 137 | work_dir=$(mktemp -d --tmpdir bacman.XXXXXXXXXX) |
b15fb504 | 138 | cd "$work_dir" || exit 1 |
fcac2376 AM |
139 | |
140 | # | |
141 | # File copying | |
142 | # | |
6e0c47d2 | 143 | msg2 "Copying package files..." |
fcac2376 AM |
144 | |
145 | cat "$pkg_dir"/files | | |
146 | while read i; do | |
7e5bbf03 | 147 | if [[ -z $i ]]; then |
3f937c84 | 148 | continue |
149 | fi | |
150 | ||
273cc66a | 151 | if [[ $i == %+([A-Z])% ]]; then |
3f937c84 | 152 | current=$i |
153 | continue | |
154 | fi | |
155 | ||
273cc66a | 156 | case "$current" in |
3f937c84 | 157 | %FILES%) |
158 | ret=0 | |
7e5bbf03 | 159 | if [[ -e /$i ]]; then |
3f937c84 | 160 | bsdtar -cnf - "/$i" 2> /dev/null | bsdtar -xpf - |
161 | ||
162 | # Workaround to bsdtar not reporting a missing file as an error | |
7e5bbf03 | 163 | if ! [[ -e $work_dir/$i || -L $work_dir/$i ]]; then |
6e0c47d2 WG |
164 | error "unable to add /$i to the package" |
165 | plain " If your user does not have permssion to read this file then" | |
166 | plain " you will need to run $myname as root" | |
3f937c84 | 167 | rm -rf "$work_dir" |
168 | exit 1 | |
169 | fi | |
170 | else | |
6e0c47d2 | 171 | warning "package file /$i is missing" |
3f937c84 | 172 | fi |
173 | ;; | |
174 | esac | |
fcac2376 AM |
175 | done |
176 | ||
177 | ret=$? | |
7e5bbf03 | 178 | if (( ret )); then |
3f937c84 | 179 | rm -rf "$work_dir" |
180 | exit 1 | |
fcac2376 AM |
181 | fi |
182 | ||
183 | pkg_size=$(du -sk | awk '{print $1 * 1024}') | |
184 | ||
fcac2376 AM |
185 | # |
186 | # .PKGINFO stuff | |
273cc66a | 187 | # TODO adopt makepkg's write_pkginfo() into this or scripts/library |
fcac2376 | 188 | # |
6e0c47d2 | 189 | msg2 "Generating .PKGINFO metadata..." |
a77e638c | 190 | echo "# Generated by $myname $myver" > .PKGINFO |
7e5bbf03 | 191 | if [[ $INFAKEROOT == "1" ]]; then |
3f937c84 | 192 | echo "# Using $(fakeroot -v)" >> .PKGINFO |
fcac2376 AM |
193 | fi |
194 | echo "# $(LC_ALL=C date)" >> .PKGINFO | |
195 | echo "#" >> .PKGINFO | |
196 | ||
fcac2376 | 197 | while read i; do |
273cc66a | 198 | if [[ -z $i ]]; then |
3f937c84 | 199 | continue; |
200 | fi | |
201 | ||
273cc66a | 202 | if [[ $i == %+([A-Z])% ]]; then |
3f937c84 | 203 | current=$i |
204 | continue | |
205 | fi | |
206 | ||
207 | case "$current" in | |
208 | # desc | |
209 | %NAME%) | |
210 | echo "pkgname = $i" >> .PKGINFO | |
211 | ;; | |
212 | %VERSION%) | |
213 | echo "pkgver = $i" >> .PKGINFO | |
214 | ;; | |
215 | %DESC%) | |
216 | echo "pkgdesc = $i" >> .PKGINFO | |
217 | ;; | |
218 | %URL%) | |
219 | echo "url = $i" >> .PKGINFO | |
220 | ;; | |
221 | %LICENSE%) | |
222 | echo "license = $i" >> .PKGINFO | |
223 | ;; | |
224 | %ARCH%) | |
225 | echo "arch = $i" >> .PKGINFO | |
958b41fa | 226 | pkg_arch="$i" |
3f937c84 | 227 | ;; |
228 | %BUILDDATE%) | |
229 | echo "builddate = $(date -u "+%s")" >> .PKGINFO | |
230 | ;; | |
231 | %PACKAGER%) | |
232 | echo "packager = $pkg_pkger" >> .PKGINFO | |
233 | ;; | |
234 | %SIZE%) | |
235 | echo "size = $pkg_size" >> .PKGINFO | |
236 | ;; | |
237 | %GROUPS%) | |
238 | echo "group = $i" >> .PKGINFO | |
239 | ;; | |
240 | %REPLACES%) | |
241 | echo "replaces = $i" >> .PKGINFO | |
242 | ;; | |
243 | %DEPENDS%) | |
244 | echo "depend = $i" >> .PKGINFO | |
245 | ;; | |
246 | %OPTDEPENDS%) | |
247 | echo "optdepend = $i" >> .PKGINFO | |
248 | ;; | |
249 | %CONFLICTS%) | |
250 | echo "conflict = $i" >> .PKGINFO | |
251 | ;; | |
252 | %PROVIDES%) | |
253 | echo "provides = $i" >> .PKGINFO | |
254 | ;; | |
255 | ||
256 | # files | |
257 | %BACKUP%) | |
258 | # strip the md5sum after the tab | |
259 | echo "backup = ${i%%$'\t'*}" >> .PKGINFO | |
260 | ;; | |
261 | esac | |
958b41fa | 262 | done < <(cat "$pkg_dir"/{desc,files}) |
fcac2376 | 263 | |
fd383191 AM |
264 | comp_files=".PKGINFO" |
265 | ||
7e5bbf03 | 266 | if [[ -f $pkg_dir/install ]]; then |
3f937c84 | 267 | cp "$pkg_dir/install" "$work_dir/.INSTALL" |
268 | comp_files+=" .INSTALL" | |
fd383191 | 269 | fi |
7e5bbf03 | 270 | if [[ -f $pkg_dir/changelog ]]; then |
3f937c84 | 271 | cp "$pkg_dir/changelog" "$work_dir/.CHANGELOG" |
272 | comp_files+=" .CHANGELOG" | |
fd383191 AM |
273 | fi |
274 | ||
fcac2376 AM |
275 | # |
276 | # Fixes owner:group and permissions for .PKGINFO, .CHANGELOG, .INSTALL | |
277 | # | |
b15fb504 CB |
278 | chown root:root "$work_dir"/{.PKGINFO,.CHANGELOG,.INSTALL} 2> /dev/null |
279 | chmod 644 "$work_dir"/{.PKGINFO,.CHANGELOG,.INSTALL} 2> /dev/null | |
fcac2376 AM |
280 | |
281 | # | |
282 | # Generate the package | |
283 | # | |
6e0c47d2 | 284 | msg2 "Generating the package..." |
fcac2376 | 285 | |
fd383191 | 286 | pkg_file="$pkg_dest/$pkg_namver-$pkg_arch${PKGEXT}" |
fcac2376 | 287 | ret=0 |
fd383191 | 288 | |
fd383191 AM |
289 | # TODO: Maybe this can be set globally for robustness |
290 | shopt -s -o pipefail | |
291 | bsdtar -cf - $comp_files * | | |
292 | case "$PKGEXT" in | |
3f937c84 | 293 | *tar.gz) gzip -c -f -n ;; |
294 | *tar.bz2) bzip2 -c -f ;; | |
295 | *tar.xz) xz -c -z - ;; | |
4928f9ed | 296 | *tar.Z) compress -c -f ;; |
3f937c84 | 297 | *tar) cat ;; |
6e0c47d2 WG |
298 | *) warning "'%s' is not a valid archive extension." \ |
299 | "$PKGEXT"; cat ;; | |
273cc66a | 300 | esac > "${pkg_file}"; ret=$? |
fd383191 | 301 | |
7e5bbf03 | 302 | if (( ret )); then |
6e0c47d2 WG |
303 | error "Unable to write package to $pkg_dest" |
304 | plain " Maybe the disk is full or you do not have write access" | |
3f937c84 | 305 | rm -rf "$work_dir" |
306 | exit 1 | |
fcac2376 AM |
307 | fi |
308 | ||
b15fb504 | 309 | rm -rf "$work_dir" |
fcac2376 | 310 | |
6e0c47d2 | 311 | msg "Done." |
fcac2376 AM |
312 | |
313 | exit 0 | |
314 | ||
b15fb504 | 315 | # vim: set ts=2 sw=2 noet: |