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@'
37 # ensure we have a sane umask set
43 printf "==> ${mesg}\n" "$@" >&1
49 printf " -> ${mesg}\n" "$@" >&1
54 printf "==> $(gettext "WARNING
:") ${mesg}\n" "$@" >&2
59 printf "==> $(gettext "ERROR
:") ${mesg}\n" "$@" >&2
62 # print usage instructions
64 printf "repo-add, repo-remove (pacman) %s\n\n" "$myver"
65 printf "$(gettext "Usage
: repo-add
[-d] [-q] <path-to-db
> <package|delta
> ...
\n")"
66 printf "$(gettext "Usage
: repo-remove
[-q] <path-to-db
> <packagename|delta
> ...
\n\n")"
68 repo-add will update a package database by reading a package
file.
\n\
69 Multiple packages to add can be specified on the
command line.
\n\n")"
71 repo-remove will update a package database by removing the package name
\n\
72 specified on the
command line from the given repo database. Multiple
\n\
73 packages to remove can be specified on the
command line.
\n\n")"
75 Use the
-q/--quiet flag to minimize output to basic messages
, warnings
,\n\
78 Use the
-d/--delta flag to automatically generate and add a delta
file\n\
79 between the old entry and the new one
, if the old package
file is found
\n\
80 next to the new one.
\n\n")"
81 echo "$(gettext "Example
: repo-add
/path
/to
/repo.db.
tar.gz pacman-3.0
.0.pkg.
tar.gz
")"
82 echo "$(gettext "Example
: repo-remove
/path
/to
/repo.db.
tar.gz kernel26
")"
86 printf "repo-add, repo-remove (pacman) %s\n\n" "$myver"
88 Copyright
(C
) 2006-2008 Aaron Griffin
<aaron@archlinux.org
>.
\n\
89 Copyright
(c
) 2007-2008 Dan McGee
<dan@archlinux.org
>.
\n\n\
90 This is free software
; see the
source for copying conditions.
\n\
91 There is NO WARRANTY
, to the extent permitted by law.
\n")"
97 # arg3 - File to write to
109 for pkgentry
in $tmpdir/$pkgname*; do
111 if [[ ${name%-*-*} = $pkgname ]]; then
119 # Get the package name from the delta filename
120 get_delta_pkgname
() {
127 # write a delta entry
128 # arg1 - path to delta file
132 pkgname
="$(get_delta_pkgname $deltafile)"
134 pkgentry
=$
(find_pkgentry
$pkgname)
135 if [[ -z $pkgentry ]]; then
136 error
"$(gettext "No database entry
for package
'%s'.
")" "$pkgname"
139 deltas
="$pkgentry/deltas"
140 if [[ ! -f $deltas ]]; then
141 echo -e "%DELTAS%" >$deltas
143 # get md5sum and compressed size of package
144 md5sum="$(openssl dgst -md5 "$deltafile")"
145 md5sum="${md5sum##* }"
146 csize
=$
(@SIZECMD@
"$deltafile")
148 oldfile
=$
(xdelta3 printhdr
$deltafile |
grep "XDELTA filename (source)" |
sed 's/.*: *//')
149 newfile
=$
(xdelta3 printhdr
$deltafile |
grep "XDELTA filename (output)" |
sed 's/.*: *//')
151 if grep -q "$oldfile.*$newfile" $deltas; then
152 sed -i.backup
"/$oldfile.*$newfile/d" $deltas && rm -f $deltas.backup
154 msg2
"$(gettext "Adding
'deltas' entry
: %s
-> %s
")" "$oldfile" "$newfile"
155 echo ${deltafile##*/} $md5sum $csize $oldfile $newfile >> $deltas
158 } # end db_write_delta
160 # remove a delta entry
161 # arg1 - path to delta file
165 filename
=${deltafile##*/}
166 pkgname
="$(get_delta_pkgname $deltafile)"
168 pkgentry
=$
(find_pkgentry
$pkgname)
169 if [[ -z $pkgentry ]]; then
172 deltas
="$pkgentry/deltas"
173 if [[ ! -f $deltas ]]; then
176 if grep -q "$filename" $deltas; then
177 sed -i.backup
"/$filename/d" $deltas && rm -f $deltas.backup
178 msg2
"$(gettext "Removing existing entry
'%s'...
")" "$filename"
183 } # end db_remove_delta
185 # write an entry to the pacman database
186 # arg1 - path to package
189 # blank out all variables
191 local pkgname pkgver pkgdesc epoch csize size
md5sum url arch builddate packager force \
192 _groups _licenses _replaces _depends _conflicts _provides _optdepends
195 # IFS (field separator) is only the newline character
199 # read info from the zipped package
201 for line
in $
(bsdtar
-xOqf "$pkgfile" .PKGINFO |
202 grep -v '^#' |
sed 's|\(\w*\)\s*=\s*\(.*\)|\1 \2|'); do
203 # bash awesomeness here- var is always one word, val is everything else
208 group
) _groups
="$_groups$group\n" ;;
209 license
) _licenses
="$_licenses$license\n" ;;
210 replaces
) _replaces
="$_replaces$replaces\n" ;;
211 depend
) _depends
="$_depends$depend\n" ;;
212 conflict
) _conflicts
="$_conflicts$conflict\n" ;;
213 provides
) _provides
="$_provides$provides\n" ;;
214 optdepend
) _optdepends
="$_optdepends$optdepend\n" ;;
220 # get md5sum and compressed size of package
221 md5sum="$(openssl dgst -md5 "$pkgfile")"
222 md5sum="${md5sum##* }"
223 csize
=$
(@SIZECMD@
"$pkgfile")
225 # ensure $pkgname and $pkgver variables were found
226 if [[ -z $pkgname ||
-z $pkgver ]]; then
227 error
"$(gettext "Invalid package
file '%s'.
")" "$pkgfile"
233 if [[ -d $pkgname-$pkgver ]]; then
234 warning
"$(gettext "An entry
for '%s' already existed
")" "$pkgname-$pkgver"
236 if [ $DELTA -eq 1 ]; then
237 pkgentry
=$
(find_pkgentry
$pkgname)
238 if [ -n "$pkgentry" ]; then
239 local oldfilename
=$
(grep -A1 FILENAME
$pkgentry/desc |
tail -n1)
240 local oldfile
="$(dirname $1)/$oldfilename"
245 # remove an existing entry if it exists, ignore failures
246 db_remove_entry
"$pkgname"
248 # create package directory
249 mkdir
"$pkgname-$pkgver"
250 cd "$pkgname-$pkgver"
252 # restore an eventual deltas file
253 [[ -f ..
/$pkgname.deltas
]] && mv "../$pkgname.deltas" deltas
256 msg2
"$(gettext "Creating
'desc' db entry...
")"
257 echo -e "%FILENAME%\n$(basename "$1")\n" >>desc
258 echo -e "%NAME%\n$pkgname\n" >>desc
259 [[ -n $pkgbase ]] && echo -e "%BASE%\n$pkgbase\n" >>desc
260 echo -e "%VERSION%\n$pkgver\n" >>desc
261 [[ -n $pkgdesc ]] && echo -e "%DESC%\n$pkgdesc\n" >>desc
262 write_list_entry
"GROUPS" "$_groups" "desc"
263 [[ -n $csize ]] && echo -e "%CSIZE%\n$csize\n" >>desc
264 [[ -n $size ]] && echo -e "%ISIZE%\n$size\n" >>desc
267 msg2
"$(gettext "Computing md5 checksums...
")"
268 echo -e "%MD5SUM%\n$md5sum\n" >>desc
270 [[ -n $url ]] && echo -e "%URL%\n$url\n" >>desc
271 write_list_entry
"LICENSE" "$_licenses" "desc"
272 [[ -n $arch ]] && echo -e "%ARCH%\n$arch\n" >>desc
273 [[ -n $builddate ]] && echo -e "%BUILDDATE%\n$builddate\n" >>desc
274 [[ -n $packager ]] && echo -e "%PACKAGER%\n$packager\n" >>desc
275 write_list_entry
"REPLACES" "$_replaces" "desc"
276 # remain backward-compatible for now; put a force entry in the database
277 if [[ -n $epoch ]]; then
278 echo -e "%EPOCH%\n#epoch\n" >>desc
279 echo -e "%FORCE%\n" >>desc
281 [[ -n $force ]] && echo -e "%FORCE%\n" >>desc
283 # create depends entry
284 msg2
"$(gettext "Creating
'depends' db entry...
")"
285 # create the file even if it will remain empty
287 write_list_entry
"DEPENDS" "$_depends" "depends"
288 write_list_entry
"CONFLICTS" "$_conflicts" "depends"
289 write_list_entry
"PROVIDES" "$_provides" "depends"
290 write_list_entry
"OPTDEPENDS" "$_optdepends" "depends"
294 # create a delta file
295 if [ -n "$oldfilename" -a -f "$oldfile" ]; then
296 delta
=$
(pkgdelta
-q $oldfile $1)
297 if [ -f "$delta" ]; then
298 db_write_delta
$delta
300 warning
"$(gettext "Old package
file not found
: %s
")" "$oldfilename"
305 } # end db_write_entry
307 # remove existing entries from the DB
308 # arg1 - package name
312 local pkgentry
=$
(find_pkgentry
$pkgname)
313 while [[ -n $pkgentry ]]; do
315 if [[ -f $pkgentry/deltas
]]; then
316 mv "$pkgentry/deltas" "$tmpdir/$pkgname.deltas"
318 msg2
"$(gettext "Removing existing entry
'%s'...
")" \
319 "$(basename $pkgentry)"
321 pkgentry
=$
(find_pkgentry
$pkgname)
324 } # end db_remove_entry
329 if ( set -o noclobber
; echo "$$" > "$LOCKFILE") 2> /dev
/null
; then
332 error
"$(gettext "Failed to acquire lockfile
: %s.
")" "$LOCKFILE"
333 [[ -f $LOCKFILE ]] && error
"$(gettext "Held by process
%s
")" "$(cat $LOCKFILE)"
337 if [[ -f $REPO_DB_FILE ]]; then
338 # there are two situations we can have here- a DB with some entries,
339 # or a DB with no contents at all.
340 if ! bsdtar
-tqf "$REPO_DB_FILE" '*/desc' >/dev
/null
2>&1; then
342 if [[ -n $
(bsdtar
-tqf "$REPO_DB_FILE" '*' 2>/dev
/null
) ]]; then
343 error
"$(gettext "Repository
file '%s' is not a proper pacman database.
")" "$REPO_DB_FILE"
347 msg
"$(gettext "Extracting database to a temporary location...
")"
348 bsdtar
-xf "$REPO_DB_FILE" -C "$tmpdir"
352 error
"$(gettext "Repository
file '%s' was not found.
")" "$REPO_DB_FILE"
356 # check if the file can be created (write permission, directory existence, etc)
357 if ! touch "$REPO_DB_FILE"; then
358 error
"$(gettext "Repository
file '%s' could not be created.
")" "$REPO_DB_FILE"
361 rm -f "$REPO_DB_FILE"
369 if [[ ! -f $1 ]]; then
370 error
"$(gettext "File
'%s' not found.
")" "$1"
374 if [[ ${1##*.} == "delta" ]]; then
376 msg
"$(gettext "Adding delta
'%s'")" "$deltafile"
377 if ! type xdelta3
&>/dev
/null
; then
378 error
"$(gettext "Cannot
find the xdelta3 binary
! Is xdelta3 installed?
")"
381 if db_write_delta
"$deltafile"; then
389 if ! bsdtar
-tqf "$pkgfile" .PKGINFO
>/dev
/null
2>&1; then
390 error
"$(gettext "'%s' is not a package
file, skipping
")" "$pkgfile"
394 msg
"$(gettext "Adding package
'%s'")" "$pkgfile"
396 db_write_entry
"$pkgfile"
401 if [[ ${1##*.} == "delta" ]]; then
403 msg
"$(gettext "Searching
for delta
'%s'...
")" "$deltafile"
404 if db_remove_delta
"$deltafile"; then
407 error
"$(gettext "Delta matching
'%s' not found.
")" "$deltafile"
413 msg
"$(gettext "Searching
for package
'%s'...
")" "$pkgname"
415 if db_remove_entry
"$pkgname"; then
416 rm -f "$tmpdir/$pkgname.deltas"
419 error
"$(gettext "Package matching
'%s' not found.
")" "$pkgname"
435 [[ -d $tmpdir ]] && rm -rf "$tmpdir"
436 (( CLEAN_LOCK
)) && [[ -f $LOCKFILE ]] && rm -f "$LOCKFILE"
443 # determine whether we have gettext; make it a no-op if we do not
444 if ! type gettext &>/dev
/null
; then
451 -h|
--help) usage
; exit 0;;
452 -V|
--version) version
; exit 0;;
455 # figure out what program we are
457 if [[ $cmd != "repo-add" && $cmd != "repo-remove" ]]; then
458 error
"$(gettext "Invalid
command name
'%s' specified.
")" "$cmd"
462 tmpdir
=$
(mktemp
-d /tmp
/repo-tools.XXXXXXXXXX
) ||
(\
463 error
"$(gettext "Cannot create temp directory
for database building.
")"; \
467 trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT
468 trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT
469 trap 'trap_exit "$(gettext "An unknown error has occured. Exiting...")"' ERR
475 -q|
--quiet) QUIET
=1;;
476 -d|
--delta) DELTA
=1;;
478 if [[ -z $REPO_DB_FILE ]]; then
480 LOCKFILE
="$REPO_DB_FILE.lck"
484 repo-add
) add
$arg && success
=1 ;;
485 repo-remove
) remove
$arg && success
=1 ;;
492 # if at least one operation was a success, re-zip database
493 if (( success
)); then
494 msg
"$(gettext "Creating updated database
file '%s'")" "$REPO_DB_FILE"
496 case "$REPO_DB_FILE" in
497 *tar.gz
) TAR_OPT
="z" ;;
498 *tar.bz2
) TAR_OPT
="j" ;;
499 *tar.xz
) TAR_OPT
="J" ;;
500 *) warning
"$(gettext "'%s' does not have a valid archive extension.
")" \
504 filename
=$
(basename "$REPO_DB_FILE")
507 if [[ -n $
(ls) ]]; then
508 bsdtar
-c${TAR_OPT}f
"$filename" *
510 # we have no packages remaining? zip up some emptyness
511 warning
"$(gettext "No packages remain
, creating empty database.
")"
512 bsdtar
-c${TAR_OPT}f
"$filename" -T /dev
/null
516 [[ -f $REPO_DB_FILE ]] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old"
517 [[ -f $tmpdir/$filename ]] && mv "$tmpdir/$filename" "$REPO_DB_FILE"
518 dblink
="${REPO_DB_FILE%.tar.*}"
519 target
=${REPO_DB_FILE##*/}
520 ln -sf "$target" "$dblink" 2>/dev
/null || \
521 ln -f "$target" "$dblink" 2>/dev
/null || \
522 cp "$REPO_DB_FILE" "$dblink"
524 msg
"$(gettext "No packages modified
, nothing to
do.
")"
529 # vim: set ts=2 sw=2 noet: