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
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@'
39 # ensure we have a sane umask set
45 printf "==> ${mesg}\n" "$@" >&1
51 printf " -> ${mesg}\n" "$@" >&1
56 printf "==> $(gettext "WARNING
:") ${mesg}\n" "$@" >&2
61 printf "==> $(gettext "ERROR
:") ${mesg}\n" "$@" >&2
64 # print usage instructions
66 printf "repo-add, repo-remove (pacman) %s\n\n" "$myver"
67 printf "$(gettext "Usage
: repo-add
[-d] [-f] [-q] [-s] [-v] <path-to-db
> <package|delta
> ...
\n")"
68 printf "$(gettext "Usage
: repo-remove
[-q] <path-to-db
> <packagename|delta
> ...
\n\n")"
70 repo-add will update a package database by reading a package
file.
\n\
71 Multiple packages to add can be specified on the
command line.
\n\n")"
73 repo-remove will update a package database by removing the package name
\n\
74 specified on the
command line from the given repo database. Multiple
\n\
75 packages to remove can be specified on the
command line.
\n\n")"
77 Use the
-q/--quiet flag to minimize output to basic messages
, warnings
,\n\
80 Use the
-d/--delta flag to automatically generate and add a delta
file\n\
81 between the old entry and the new one
, if the old package
file is found
\n\
82 next to the new one.
\n\n")"
84 Use the
-f/--files flag to update a database including
file entries.
\n\n
85 See repo-add
(8) for more details and descriptions of the available options.
\n\n")"
86 echo "$(gettext "Example
: repo-add
/path
/to
/repo.db.
tar.gz pacman-3.0
.0.pkg.
tar.gz
")"
87 echo "$(gettext "Example
: repo-remove
/path
/to
/repo.db.
tar.gz kernel26
")"
91 printf "repo-add, repo-remove (pacman) %s\n\n" "$myver"
93 Copyright
(C
) 2006-2008 Aaron Griffin
<aaron@archlinux.org
>.
\n\
94 Copyright
(c
) 2007-2008 Dan McGee
<dan@archlinux.org
>.
\n\n\
95 This is free software
; see the
source for copying conditions.
\n\
96 There is NO WARRANTY
, to the extent permitted by law.
\n")"
102 # arg3 - File to write to
114 for pkgentry
in $tmpdir/$pkgname*; do
116 if [[ ${name%-*-*} = $pkgname ]]; then
124 # Get the package name from the delta filename
125 get_delta_pkgname
() {
132 # write a delta entry
133 # arg1 - path to delta file
137 pkgname
="$(get_delta_pkgname $deltafile)"
139 pkgentry
=$
(find_pkgentry
$pkgname)
140 if [[ -z $pkgentry ]]; then
141 error
"$(gettext "No database entry
for package
'%s'.
")" "$pkgname"
144 deltas
="$pkgentry/deltas"
145 if [[ ! -f $deltas ]]; then
146 echo -e "%DELTAS%" >$deltas
148 # get md5sum and compressed size of package
149 md5sum="$(openssl dgst -md5 "$deltafile")"
150 md5sum="${md5sum##* }"
151 csize
=$
(@SIZECMD@
"$deltafile")
153 oldfile
=$
(xdelta3 printhdr
$deltafile |
grep "XDELTA filename (source)" |
sed 's/.*: *//')
154 newfile
=$
(xdelta3 printhdr
$deltafile |
grep "XDELTA filename (output)" |
sed 's/.*: *//')
156 if grep -q "$oldfile.*$newfile" $deltas; then
157 sed -i.backup
"/$oldfile.*$newfile/d" $deltas && rm -f $deltas.backup
159 msg2
"$(gettext "Adding
'deltas' entry
: %s
-> %s
")" "$oldfile" "$newfile"
160 echo ${deltafile##*/} $md5sum $csize $oldfile $newfile >> $deltas
163 } # end db_write_delta
165 # remove a delta entry
166 # arg1 - path to delta file
170 filename
=${deltafile##*/}
171 pkgname
="$(get_delta_pkgname $deltafile)"
173 pkgentry
=$
(find_pkgentry
$pkgname)
174 if [[ -z $pkgentry ]]; then
177 deltas
="$pkgentry/deltas"
178 if [[ ! -f $deltas ]]; then
181 if grep -q "$filename" $deltas; then
182 sed -i.backup
"/$filename/d" $deltas && rm -f $deltas.backup
183 msg2
"$(gettext "Removing existing entry
'%s'...
")" "$filename"
188 } # end db_remove_delta
190 # sign the package database once repackaged
192 (( ! SIGN
)) && return
195 msg
"$(gettext "Signing database...
")"
196 if [ ! $
(type -p "gpg") ]; then
197 error
"$(gettext "Cannot
find the gpg binary
! Is gnupg installed?
")"
198 exit 1 # $E_MISSING_PROGRAM
200 gpg
--detach-sign --use-agent "$dbfile" || ret
=$?
202 msg2
"$(gettext "Created signature
file %s.
")" "$dbfile.sig"
204 warning
"$(gettext "Failed to sign package database.
")"
208 # verify the existing package database signature
210 (( ! VERIFY
)) && return
213 msg
"$(gettext "Verifying database signature...
")"
214 if [ ! $
(type -p "gpg") ]; then
215 error
"$(gettext "Cannot
find the gpg binary
! Is gnupg installed?
")"
216 exit 1 # $E_MISSING_PROGRAM
218 if [[ ! -f $dbfile.sig
]]; then
219 warning
"$(gettext "No existing signature found
, skipping verification.
")"
222 gpg
--verify "$dbfile.sig" || ret
=$?
224 msg2
"$(gettext "Database signature
file verified.
")"
226 error
"$(gettext "Database signature was NOT valid
!")"
231 # write an entry to the pacman database
232 # arg1 - path to package
235 # blank out all variables
237 local pkgname pkgver pkgdesc csize size
md5sum url arch builddate packager \
238 _groups _licenses _replaces _depends _conflicts _provides _optdepends
241 # IFS (field separator) is only the newline character
245 # read info from the zipped package
247 for line
in $
(bsdtar
-xOqf "$pkgfile" .PKGINFO |
248 grep -v '^#' |
sed 's|\(\w*\)\s*=\s*\(.*\)|\1 \2|'); do
249 # bash awesomeness here- var is always one word, val is everything else
254 group
) _groups
="$_groups$group\n" ;;
255 license
) _licenses
="$_licenses$license\n" ;;
256 replaces
) _replaces
="$_replaces$replaces\n" ;;
257 depend
) _depends
="$_depends$depend\n" ;;
258 conflict
) _conflicts
="$_conflicts$conflict\n" ;;
259 provides
) _provides
="$_provides$provides\n" ;;
260 optdepend
) _optdepends
="$_optdepends$optdepend\n" ;;
266 csize
=$
(@SIZECMD@
"$pkgfile")
268 # ensure $pkgname and $pkgver variables were found
269 if [[ -z $pkgname ||
-z $pkgver ]]; then
270 error
"$(gettext "Invalid package
file '%s'.
")" "$pkgfile"
274 pushd "$tmpdir" >/dev
/null
275 if [[ -d $pkgname-$pkgver ]]; then
276 warning
"$(gettext "An entry
for '%s' already existed
")" "$pkgname-$pkgver"
279 pkgentry
=$
(find_pkgentry
$pkgname)
280 if [[ -n $pkgentry ]]; then
281 local oldfilename
=$
(grep -A1 FILENAME
$pkgentry/desc |
tail -n1)
282 local oldfile
="$(dirname $1)/$oldfilename"
288 msg2
"$(gettext "Computing checksums...
")"
289 md5sum="$(openssl dgst -md5 "$pkgfile")"
290 md5sum="${md5sum##* }"
291 sha256sum
="$(openssl dgst -sha256 "$pkgfile")"
292 sha256sum
="${sha256sum##* }"
294 # remove an existing entry if it exists, ignore failures
295 db_remove_entry
"$pkgname"
297 # create package directory
298 mkdir
"$pkgname-$pkgver"
299 pushd "$pkgname-$pkgver" >/dev
/null
301 # restore an eventual deltas file
302 [[ -f ..
/$pkgname.deltas
]] && mv "../$pkgname.deltas" deltas
305 msg2
"$(gettext "Creating
'%s' db entry...
")" 'desc'
306 echo -e "%FILENAME%\n$(basename "$1")\n" >>desc
307 echo -e "%NAME%\n$pkgname\n" >>desc
308 [[ -n $pkgbase ]] && echo -e "%BASE%\n$pkgbase\n" >>desc
309 echo -e "%VERSION%\n$pkgver\n" >>desc
310 [[ -n $pkgdesc ]] && echo -e "%DESC%\n$pkgdesc\n" >>desc
311 write_list_entry
"GROUPS" "$_groups" "desc"
312 [[ -n $csize ]] && echo -e "%CSIZE%\n$csize\n" >>desc
313 [[ -n $size ]] && echo -e "%ISIZE%\n$size\n" >>desc
316 echo -e "%MD5SUM%\n$md5sum\n" >>desc
317 echo -e "%SHA256SUM%\n$sha256sum\n" >>desc
319 # add base64'd PGP signature
320 if [[ -f $startdir/$pkgfile.sig
]]; then
321 pgpsig
=$
(openssl base64
-in "$startdir/$pkgfile.sig" |
tr -d '\n')
322 echo -e "%PGPSIG%\n$pgpsig\n" >>desc
325 [[ -n $url ]] && echo -e "%URL%\n$url\n" >>desc
326 write_list_entry
"LICENSE" "$_licenses" "desc"
327 [[ -n $arch ]] && echo -e "%ARCH%\n$arch\n" >>desc
328 [[ -n $builddate ]] && echo -e "%BUILDDATE%\n$builddate\n" >>desc
329 [[ -n $packager ]] && echo -e "%PACKAGER%\n$packager\n" >>desc
330 write_list_entry
"REPLACES" "$_replaces" "desc"
332 # create depends entry
333 msg2
"$(gettext "Creating
'%s' db entry...
")" 'depends'
334 # create the file even if it will remain empty
336 write_list_entry
"DEPENDS" "$_depends" "depends"
337 write_list_entry
"CONFLICTS" "$_conflicts" "depends"
338 write_list_entry
"PROVIDES" "$_provides" "depends"
339 write_list_entry
"OPTDEPENDS" "$_optdepends" "depends"
344 # create files file if wanted
345 if (( WITHFILES
)); then
346 msg2
"$(gettext "Creating
'%s' db entry...
")" 'files'
347 local files_path
="$tmpdir/$pkgname-$pkgver/files"
348 echo "%FILES%" >$files_path
349 bsdtar
--exclude='.*' -tf "$pkgfile" >>$files_path
352 # create a delta file
354 if [[ -n $oldfilename ]]; then
355 if [[ -f $oldfile ]]; then
356 delta
=$
(pkgdelta
-q $oldfile $1)
357 if [[ -f $delta ]]; then
358 db_write_delta
$delta
361 warning
"$(gettext "Old package
file not found
: %s
")" "$oldfilename"
367 } # end db_write_entry
369 # remove existing entries from the DB
370 # arg1 - package name
374 local pkgentry
=$
(find_pkgentry
$pkgname)
375 while [[ -n $pkgentry ]]; do
377 if [[ -f $pkgentry/deltas
]]; then
378 mv "$pkgentry/deltas" "$tmpdir/$pkgname.deltas"
380 msg2
"$(gettext "Removing existing entry
'%s'...
")" \
381 "$(basename $pkgentry)"
383 pkgentry
=$
(find_pkgentry
$pkgname)
386 } # end db_remove_entry
391 if ( set -o noclobber
; echo "$$" > "$LOCKFILE") 2> /dev
/null
; then
394 error
"$(gettext "Failed to acquire lockfile
: %s.
")" "$LOCKFILE"
395 [[ -f $LOCKFILE ]] && error
"$(gettext "Held by process
%s
")" "$(cat $LOCKFILE)"
399 if [[ -f $REPO_DB_FILE ]]; then
400 # there are two situations we can have here- a DB with some entries,
401 # or a DB with no contents at all.
402 if ! bsdtar
-tqf "$REPO_DB_FILE" '*/desc' >/dev
/null
2>&1; then
404 if [[ -n $
(bsdtar
-tqf "$REPO_DB_FILE" '*' 2>/dev
/null
) ]]; then
405 error
"$(gettext "Repository
file '%s' is not a proper pacman database.
")" "$REPO_DB_FILE"
409 verify_signature
"$REPO_DB_FILE"
410 msg
"$(gettext "Extracting database to a temporary location...
")"
411 bsdtar
-xf "$REPO_DB_FILE" -C "$tmpdir"
415 error
"$(gettext "Repository
file '%s' was not found.
")" "$REPO_DB_FILE"
419 # check if the file can be created (write permission, directory existence, etc)
420 if ! touch "$REPO_DB_FILE"; then
421 error
"$(gettext "Repository
file '%s' could not be created.
")" "$REPO_DB_FILE"
424 rm -f "$REPO_DB_FILE"
432 if [[ ! -f $1 ]]; then
433 error
"$(gettext "File
'%s' not found.
")" "$1"
437 if [[ ${1##*.} == "delta" ]]; then
439 msg
"$(gettext "Adding delta
'%s'")" "$deltafile"
440 if ! type xdelta3
&>/dev
/null
; then
441 error
"$(gettext "Cannot
find the xdelta3 binary
! Is xdelta3 installed?
")"
444 if db_write_delta
"$deltafile"; then
452 if ! bsdtar
-tqf "$pkgfile" .PKGINFO
>/dev
/null
2>&1; then
453 error
"$(gettext "'%s' is not a package
file, skipping
")" "$pkgfile"
457 msg
"$(gettext "Adding package
'%s'")" "$pkgfile"
459 db_write_entry
"$pkgfile"
464 if [[ ${1##*.} == "delta" ]]; then
466 msg
"$(gettext "Searching
for delta
'%s'...
")" "$deltafile"
467 if db_remove_delta
"$deltafile"; then
470 error
"$(gettext "Delta matching
'%s' not found.
")" "$deltafile"
476 msg
"$(gettext "Searching
for package
'%s'...
")" "$pkgname"
478 if db_remove_entry
"$pkgname"; then
479 rm -f "$tmpdir/$pkgname.deltas"
482 error
"$(gettext "Package matching
'%s' not found.
")" "$pkgname"
497 [[ -d $tmpdir ]] && rm -rf "$tmpdir"
498 (( CLEAN_LOCK
)) && [[ -f $LOCKFILE ]] && rm -f "$LOCKFILE"
505 # determine whether we have gettext; make it a no-op if we do not
506 if ! type gettext &>/dev
/null
; then
513 -h|
--help) usage
; exit 0;;
514 -V|
--version) version
; exit 0;;
517 # figure out what program we are
519 if [[ $cmd != "repo-add" && $cmd != "repo-remove" ]]; then
520 error
"$(gettext "Invalid
command name
'%s' specified.
")" "$cmd"
524 tmpdir
=$
(mktemp
-d /tmp
/repo-tools.XXXXXXXXXX
) ||
(\
525 error
"$(gettext "Cannot create temp directory
for database building.
")"; \
529 trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT
530 trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT
531 trap 'trap_exit "$(gettext "An unknown error has occured. Exiting...")"' ERR
537 -q|
--quiet) QUIET
=1;;
538 -d|
--delta) DELTA
=1;;
539 -f|
--files) WITHFILES
=1;;
541 -v|
--verify) VERIFY
=1;;
543 if [[ -z $REPO_DB_FILE ]]; then
545 LOCKFILE
="$REPO_DB_FILE.lck"
549 repo-add
) add
$arg && success
=1 ;;
550 repo-remove
) remove
$arg && success
=1 ;;
557 # if at least one operation was a success, re-zip database
558 if (( success
)); then
559 msg
"$(gettext "Creating updated database
file '%s'")" "$REPO_DB_FILE"
561 case "$REPO_DB_FILE" in
562 *tar.gz
) TAR_OPT
="z" ;;
563 *tar.bz2
) TAR_OPT
="j" ;;
564 *tar.xz
) TAR_OPT
="J" ;;
565 *) warning
"$(gettext "'%s' does not have a valid archive extension.
")" \
569 filename
=$
(basename "$REPO_DB_FILE")
571 pushd "$tmpdir" >/dev
/null
572 if [[ -n $
(ls) ]]; then
573 bsdtar
-c${TAR_OPT}f
"$filename" *
574 create_signature
"$filename"
576 # we have no packages remaining? zip up some emptyness
577 warning
"$(gettext "No packages remain
, creating empty database.
")"
578 bsdtar
-c${TAR_OPT}f
"$filename" -T /dev
/null
582 [[ -f $REPO_DB_FILE ]] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old"
583 [[ -f $REPO_DB_FILE.sig
]] && rm -f "$REPO_DB_FILE.sig"
584 [[ -f $tmpdir/$filename ]] && mv "$tmpdir/$filename" "$REPO_DB_FILE"
585 [[ -f $tmpdir/$filename.sig
]] && mv "$tmpdir/$filename.sig" "$REPO_DB_FILE.sig"
586 dblink
="${REPO_DB_FILE%.tar.*}"
587 target
=${REPO_DB_FILE##*/}
588 ln -sf "$target" "$dblink" 2>/dev
/null || \
589 ln -f "$target" "$dblink" 2>/dev
/null || \
590 cp "$REPO_DB_FILE" "$dblink"
591 if [[ -f "$target.sig" ]]; then
592 ln -sf "$target.sig" "$dblink.sig" 2>/dev
/null || \
593 ln -f "$target.sig" "$dblink.sig" 2>/dev
/null || \
594 cp "$REPO_DB_FILE.sig" "$dblink.sig"
597 msg
"$(gettext "No packages modified
, nothing to
do.
")"
602 # vim: set ts=2 sw=2 noet: