Show number of packages to be installed / removed.
[pacman-ng.git] / scripts / repo-add.sh.in
blob9ab023d62a70ff206341b20b46f5d822f0df46ef
1 #!/bin/bash
3 # repo-add - add a package to a given repo database file
4 # repo-remove - remove a package entry from a given repo database file
5 # @configure_input@
7 # Copyright (c) 2006-2008 Aaron Griffin <aaron@archlinux.org>
8 # Copyright (c) 2007-2008 Dan McGee <dan@archlinux.org>
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.
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.
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/>.
23 # gettext initialization
24 export TEXTDOMAIN='pacman'
25 export TEXTDOMAINDIR='@localedir@'
27 myver='@PACKAGE_VERSION@'
28 confdir='@sysconfdir@'
30 QUIET=0
31 REPO_DB_FILE=""
33 # ensure we have a sane umask set
34 umask 0022
36 msg() {
37 [ $QUIET -ne 0 ] && return
38 local mesg=$1; shift
39 printf "==> ${mesg}\n" "$@" >&1
42 msg2() {
43 [ $QUIET -ne 0 ] && return
44 local mesg=$1; shift
45 printf " -> ${mesg}\n" "$@" >&1
48 warning() {
49 local mesg=$1; shift
50 printf "==> $(gettext "WARNING:") ${mesg}\n" "$@" >&2
53 error() {
54 local mesg=$1; shift
55 printf "==> $(gettext "ERROR:") ${mesg}\n" "$@" >&2
58 # print usage instructions
59 usage() {
60 printf "repo-add, repo-remove (pacman) %s\n\n" "$myver"
61 printf "$(gettext "Usage: repo-add [-q] <path-to-db> <package> ...\n")"
62 printf "$(gettext "Usage: repo-remove [-q] <path-to-db> <packagename> ...\n\n")"
63 printf "$(gettext "\
64 repo-add will update a package database by reading a package file.\n\
65 Multiple packages to add can be specified on the command line.\n\n")"
66 printf "$(gettext "\
67 repo-remove will update a package database by removing the package name\n\
68 specified on the command line from the given repo database. Multiple\n\
69 packages to remove can be specified on the command line.\n\n")"
70 printf "$(gettext "\
71 The -q/--quiet flag to either program will force silent running except\n\
72 in the case of warnings or errors.\n\n")"
73 echo "$(gettext "Example: repo-add /path/to/repo.db.tar.gz pacman-3.0.0.pkg.tar.gz")"
74 echo "$(gettext "Example: repo-remove /path/to/repo.db.tar.gz kernel26")"
77 version() {
78 printf "repo-add, repo-remove (pacman) %s\n\n" "$myver"
79 printf "$(gettext "\
80 Copyright (C) 2006-2008 Aaron Griffin <aaron@archlinux.org>.\n\
81 Copyright (c) 2007-2008 Dan McGee <dan@archlinux.org>.\n\n\
82 This is free software; see the source for copying conditions.\n\
83 There is NO WARRANTY, to the extent permitted by law.\n")"
86 # test if a file is a repository DB
87 test_repo_db_file () {
88 if bsdtar -tf "$REPO_DB_FILE" | grep -q "/desc"; then
89 return 0 # YES
90 else
91 return 1 # NO
95 # write a list entry
96 # arg1 - Entry name
97 # arg2 - List
98 # arg3 - File to write to
99 write_list_entry() {
100 if [ -n "$2" ]; then
101 echo "%$1%" >>$3
102 echo $2 | tr -s ' ' '\n' >>$3
103 echo "" >>$3
107 # write a delta entry to the pacman database
108 # arg1 - path to delta
109 db_write_delta()
111 # blank out all variables and set deltafile to absolute path
112 local deltafile=$($realpath "$1")
113 local filename=$(basename "$deltafile")
114 local deltavars pkgname fromver tover arch csize md5sum
116 # format of the delta filename:
117 # (package)-(fromver)_to_(tover)-(arch).delta
118 deltavars=( $(echo "$filename" | sed -e 's/\(.*\)-\(.*-.*\)_to_\(.*-.*\)-\(.*\).delta/\1 \2 \3 \4/') )
119 pkgname=${deltavars[0]}
120 fromver=${deltavars[1]}
121 tover=${deltavars[2]}
122 arch=${deltavars[3]}
124 # get md5sum and size of delta
125 md5sum="$(md5sum "$deltafile" | cut -d ' ' -f 1)"
126 csize=$(du -kL "$deltafile" | awk '{print $1 * 1024}')
128 # ensure variables were found
129 if [ -z "$pkgname" -o -z "$fromver" -o -z "$tover" -o -z "$arch" ]; then
130 return 1
133 # add the entry for this delta file
134 echo -e "$fromver $tover $csize $filename $md5sum" >>deltas
135 } # end db_write_delta
138 # write an entry to the pacman database
139 # arg1 - path to package
140 db_write_entry()
142 # blank out all variables and set pkgfile to an absolute path
143 local pkgfile=$($realpath "$1")
144 local pkgname pkgver pkgdesc url builddate packager csize size \
145 group depend backup license replaces provides conflict force \
146 _groups _depends _backups _licenses _replaces _provides _conflicts \
147 startdir
149 local OLDIFS="$IFS"
150 # IFS (field separator) is only the newline character
151 IFS="
154 # read info from the zipped package
155 local line
156 for line in $(bsdtar -xOf "$pkgfile" .PKGINFO | \
157 grep -v "^#" | sed 's|\(\w*\)\s*=\s*\(.*\)|\1="\2"|'); do
158 eval "$line"
159 case "$line" in
160 group=*) _groups="$_groups $group" ;;
161 depend=*) _depends="$_depends $depend" ;;
162 backup=*) _backups="$_backups $backup" ;;
163 license=*) _licenses="$_licenses $license" ;;
164 replaces=*) _replaces="$_replaces $replaces" ;;
165 provides=*) _provides="$_provides $provides" ;;
166 conflict=*) _conflicts="$_conflicts $conflict" ;;
167 esac
168 done
170 IFS=$OLDIFS
172 # get compressed size of package
173 csize=$(du -kL "$pkgfile" | awk '{print $1 * 1024}')
175 startdir=$(pwd)
176 pushd "$gstmpdir" 2>&1 >/dev/null
178 # ensure $pkgname and $pkgver variables were found
179 if [ -z "$pkgname" -o -z "$pkgver" ]; then
180 error "$(gettext "Invalid package file '%s'.")" "$pkgfile"
181 popd 2>&1 >/dev/null
182 return 1
185 # remove an existing entry if it exists, ignore failures
186 db_remove_entry "$pkgname"
188 # create package directory
189 mkdir "$pkgname-$pkgver"
190 cd "$pkgname-$pkgver"
192 # create desc entry
193 msg2 "$(gettext "Creating 'desc' db entry...")"
194 echo -e "%FILENAME%\n$(basename "$1")\n" >>desc
195 echo -e "%NAME%\n$pkgname\n" >>desc
196 echo -e "%VERSION%\n$pkgver\n" >>desc
197 [ -n "$pkgdesc" ] && echo -e "%DESC%\n$pkgdesc\n" >>desc
198 write_list_entry "GROUPS" "$_groups" "desc"
199 [ -n $csize ] && echo -e "%CSIZE%\n$csize\n" >>desc
200 [ -n $size ] && echo -e "%ISIZE%\n$size\n" >>desc
202 # compute checksums
203 msg2 "$(gettext "Computing md5 checksums...")"
204 echo -e "%MD5SUM%\n$(md5sum "$pkgfile" | cut -d ' ' -f 1)\n" >>desc
206 [ -n "$url" ] && echo -e "%URL%\n$url\n" >>desc
207 write_list_entry "LICENSE" "$_licenses" "desc"
208 [ -n "$arch" ] && echo -e "%ARCH%\n$arch\n" >>desc
209 [ -n "$builddate" ] && echo -e "%BUILDDATE%\n$builddate\n" >>desc
210 [ -n "$packager" ] && echo -e "%PACKAGER%\n$packager\n" >>desc
211 write_list_entry "REPLACES" "$_replaces" "desc"
212 [ -n "$force" ] && echo -e "%FORCE%\n" >>desc
214 # create depends entry
215 msg2 "$(gettext "Creating 'depends' db entry...")"
216 write_list_entry "DEPENDS" "$_depends" "depends"
217 write_list_entry "CONFLICTS" "$_conflicts" "depends"
218 write_list_entry "PROVIDES" "$_provides" "depends"
220 # create deltas entry if there are delta files
221 for delta in $startdir/$pkgname-*-*_to_*-*-$arch.delta; do
222 # This for loop also pulls in all files that start with the current package
223 # name and are followed by a -whatever. For instance, running this loop for
224 # gcc would also grab gcc-libs. To guard against this, compare the package
225 # name of the delta to the current package name.
226 local filename=$(basename "$delta")
227 local dpkgname="$(echo "$filename" | sed -e 's/\(.*\)-.*-.*_to_.*-.*-.*.delta/\1/')"
228 if [ "$pkgname" = "$dpkgname" -a -f "$delta" ]; then
229 # create deltas file if it does not already exist
230 if [ ! -f "deltas" ]; then
231 msg2 "$(gettext "Creating 'deltas' db entry...")"
232 echo -e "%DELTAS%" >>deltas
235 # write this delta entry
236 if db_write_delta "$delta"; then
237 msg2 "$(gettext "Added delta '%s'")" "$(basename "$delta")"
238 else
239 warning "$(gettext "Could not add delta '%s'")" "$(basename "$delta")"
242 done
243 # add the final newline
244 [ -f "deltas" ] && echo -e "" >>deltas
246 # preserve the modification time
247 touch -r "$pkgfile" desc depends
248 [ -f "deltas" ] && touch -r "$pkgfile" deltas
250 popd 2>&1 >/dev/null
251 } # end db_write_entry
253 # remove existing entries from the DB
254 # arg1 - package name
255 db_remove_entry() {
256 pushd "$gstmpdir" 2>&1 >/dev/null
258 # remove any other package in the DB with same name
259 local existing
260 for existing in *; do
261 if [ "${existing%-*-*}" = "$1" ]; then
262 msg2 "$(gettext "Removing existing package '%s'...")" "$existing"
263 rm -rf "$existing"
265 done
267 popd 2>&1 >/dev/null
268 } # end db_remove_entry
270 # PROGRAM START
272 # determine whether we have gettext; make it a no-op if we do not
273 if [ ! $(type -t gettext) ]; then
274 gettext() {
275 echo "$@"
279 # check for help flags
280 if [ "$1" = "-h" -o "$1" = "--help" ]; then
281 usage
282 exit 0
285 # check for version flags
286 if [ "$1" = "-V" -o "$1" = "--version" ]; then
287 version
288 exit 0
291 # check for correct number of args
292 if [ $# -lt 2 ]; then
293 usage
294 exit 1
297 # check for and store the name of a realpath-like program
298 if [ $(type -t realpath) ]; then
299 realpath='realpath'
300 elif [ $(type -t readlink) ]; then
301 realpath='readlink -f'
302 else
303 error "$(gettext "Either realpath or readlink are required by repo-add.")"
304 exit 1 # $E_MISSING_PROGRAM
307 # source system and user makepkg.conf
308 if [ -r "$confdir/makepkg.conf" ]; then
309 source "$confdir/makepkg.conf"
310 else
311 error "$(gettext "%s not found. Cannot continue.")" "$confdir/makepkg.conf"
312 exit 1 # $E_CONFIG_ERROR
315 if [ -r ~/.makepkg.conf ]; then
316 source ~/.makepkg.conf
319 # main routine
320 gstmpdir=$(mktemp -d /tmp/repo-tools.XXXXXXXXXX) || (\
321 error "$(gettext "Cannot create temp directory for database building.")"; \
322 exit 1)
324 # figure out what program we are
325 cmd="$(basename $0)"
326 if [ "$cmd" != "repo-add" -a "$cmd" != "repo-remove" ]; then
327 error "$(gettext "Invalid command name '%s' specified.")" "$cmd"
328 exit 1
331 success=0
332 # parse arguments
333 for arg in "$@"; do
334 if [ "$arg" == "--force" -o "$arg" == "-f" ]; then
335 warning "$(gettext "the -f and --force options are no longer recognized")"
336 msg2 "$(gettext "use options=(force) in the PKGBUILD instead")"
337 elif [ "$arg" == "--quiet" -o "$arg" == "-q" ]; then
338 QUIET=1
339 elif [ -z "$REPO_DB_FILE" ]; then
340 # store absolute path to repo DB
341 REPO_DB_FILE=$($realpath "$arg")
342 if [ -f "$REPO_DB_FILE" ]; then
343 if ! test_repo_db_file $cmd; then
344 error "$(gettext "Repository file '%s' is not a proper pacman database.")" "$REPO_DB_FILE"
345 exit 1
347 msg "$(gettext "Extracting database to a temporary location...")"
348 bsdtar -xf "$REPO_DB_FILE" -C "$gstmpdir"
349 elif [ "$cmd" == "repo-remove" ]; then
350 error "$(gettext "Repository file '%s' was not found.")" "$REPO_DB_FILE"
351 exit 1
353 else
354 if [ "$cmd" == "repo-add" ]; then
355 if [ -f "$arg" ]; then
356 if ! bsdtar -tf "$arg" .PKGINFO 2>&1 >/dev/null; then
357 error "$(gettext "'%s' is not a package file, skipping")" "$arg"
358 else
359 msg "$(gettext "Adding package '%s'")" "$arg"
361 if db_write_entry "$arg"; then
362 success=1
365 else
366 error "$(gettext "Package '%s' not found.")" "$arg"
368 elif [ "$cmd" == "repo-remove" ]; then
369 msg "$(gettext "Searching for package '%s'...")" "$arg"
371 if db_remove_entry "$arg"; then
372 success=1
373 else
374 error "$(gettext "Package matching '%s' not found.")" "$arg"
378 done
380 # if all operations were a success, re-zip database
381 if [ $success -eq 1 ]; then
382 msg "$(gettext "Creating updated database file '%s'")" "$REPO_DB_FILE"
383 pushd "$gstmpdir" 2>&1 >/dev/null
385 if [ -n "$(ls)" ]; then
386 [ -f "${REPO_DB_FILE}.old" ] && rm "${REPO_DB_FILE}.old"
387 [ -f "$REPO_DB_FILE" ] && mv "$REPO_DB_FILE" "${REPO_DB_FILE}.old"
389 case "$DB_COMPRESSION" in
390 gz) TAR_OPT="z" ;;
391 bz2) TAR_OPT="j" ;;
392 *) warning "$(gettext "No compression set.")" ;;
393 esac
395 bsdtar -c${TAR_OPT}f "$REPO_DB_FILE" *
396 else
397 # we should only end up with an empty db after a remove of the last package in the database
398 error "$(gettext "All packages have been removed from the database. Deleting '%s'.")" "$REPO_DB_FILE"
399 rm "$REPO_DB_FILE"
402 popd 2>&1 >/dev/null
403 else
404 msg "$(gettext "No packages modified, nothing to do.")"
407 # remove the temp directory used to unzip
408 [ -d "$gstmpdir" ] && rm -rf "$gstmpdir"
410 # vim: set ts=2 sw=2 noet: