tpkg 2.3.3 → 2.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/Portfile +39 -0
- data/Portfile.template +39 -0
- data/README.md +43 -0
- data/Rakefile +468 -18
- data/bin/gem2tpkg +2 -2
- data/bin/tpkg +18 -13
- data/bin/tpkg_uploader +132 -0
- data/ca.pem +1 -0
- data/control +7 -0
- data/depend +3 -0
- data/externals-etch/authorized_keys +40 -0
- data/externals-etch/group +9 -0
- data/externals-etch/iptables +38 -0
- data/externals-etch/limits +30 -0
- data/externals-etch/nfs +30 -0
- data/externals-etch/sudo +30 -0
- data/externals-etch/supplemental_groups +8 -0
- data/externals-etch/sysctl +30 -0
- data/externals-etch/user +41 -0
- data/externals/group +39 -0
- data/externals/supplemental_groups +48 -0
- data/externals/user +39 -0
- data/lib/tpkg.rb +260 -991
- data/lib/tpkg/os.rb +164 -0
- data/lib/tpkg/os/debian.rb +159 -0
- data/lib/tpkg/os/freebsd.rb +113 -0
- data/lib/tpkg/os/macosx.rb +113 -0
- data/lib/tpkg/os/redhat.rb +173 -0
- data/lib/tpkg/os/solaris.rb +101 -0
- data/lib/tpkg/os/windows.rb +26 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify.rb +67 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/errors.rb +127 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/kwalify.schema.yaml +58 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/main.rb +442 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/messages.rb +173 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/meta-validator.rb +275 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/parser/base.rb +127 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/parser/yaml.rb +841 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/rule.rb +559 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/templates/genclass-java.eruby +222 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/templates/genclass-php.eruby +104 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/templates/genclass-ruby.eruby +113 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/types.rb +156 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util.rb +158 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/assert-text-equal.rb +46 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/hash-interface.rb +18 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/hashlike.rb +51 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/option-parser.rb +220 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/ordered-hash.rb +57 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/testcase-helper.rb +112 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/validator.rb +282 -0
- data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/yaml-parser.rb +870 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh.rb +219 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/agent.rb +179 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/constants.rb +18 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/key_manager.rb +219 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/abstract.rb +60 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/hostbased.rb +71 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/keyboard_interactive.rb +66 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/password.rb +39 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/publickey.rb +92 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/pageant.rb +183 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/session.rb +134 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/buffer.rb +340 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/buffered_io.rb +198 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/config.rb +205 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/connection/channel.rb +630 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/connection/constants.rb +33 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/connection/session.rb +597 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/connection/term.rb +178 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/errors.rb +85 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/key_factory.rb +102 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/known_hosts.rb +129 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/loggable.rb +61 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/packet.rb +102 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/prompt.rb +93 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/command.rb +75 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/errors.rb +14 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/http.rb +94 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/socks4.rb +70 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/socks5.rb +142 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/ruby_compat.rb +43 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/service/forward.rb +288 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test.rb +89 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/channel.rb +129 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/extensions.rb +152 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/kex.rb +44 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/local_packet.rb +51 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/packet.rb +81 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/remote_packet.rb +38 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/script.rb +157 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/socket.rb +64 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/algorithms.rb +384 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/cipher_factory.rb +97 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/constants.rb +30 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac.rb +31 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/abstract.rb +79 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/md5.rb +12 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/none.rb +15 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/sha1.rb +13 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/identity_cipher.rb +55 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/kex.rb +13 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +77 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/openssl.rb +127 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/packet_stream.rb +235 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/server_version.rb +71 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/session.rb +276 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/state.rb +206 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/verifiers/lenient.rb +30 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/verifiers/null.rb +12 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/verifiers/strict.rb +53 -0
- data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/version.rb +62 -0
- data/lib/tpkg/version.rb +3 -0
- data/man/man1/cpan2tpkg.1 +82 -0
- data/man/man1/gem2tpkg.1 +120 -0
- data/man/man1/tpkg.1 +411 -0
- data/pkginfo +8 -0
- data/postinstall.solaris +11 -0
- data/postremove.solaris +16 -0
- data/schema/schema-1.0.5.yml +0 -0
- data/schema/schema-1.0.6.yml +0 -0
- data/schema/schema-1.0.7.yml +0 -0
- data/schema/schema-1.0.8.yml +0 -0
- data/schema/schema-1.0.9.yml +0 -0
- data/schema/schema.yml +0 -0
- data/schema/tpkg-1.0.0.dtd +0 -0
- data/schema/tpkg-1.0.1.dtd +0 -0
- data/schema/tpkg-1.0.2.dtd +0 -0
- data/schema/tpkg-1.0.3.dtd +0 -0
- data/schema/tpkg-1.0.4.dtd +0 -0
- data/schema/tpkg-1.0.5.dtd +0 -0
- data/schema/tpkg-1.0.6.dtd +0 -0
- data/schema/tpkg-1.0.7.dtd +0 -0
- data/schema/tpkg-1.0.8.dtd +0 -0
- data/schema/tpkg-1.0.9.dtd +0 -0
- data/schema/tpkg.dtd +0 -0
- data/test/TODO +30 -0
- data/test/premadetestpkg/pkg_without_file_metadata-1.0-1.tpkg +0 -0
- data/test/test_checksum.rb +53 -0
- data/test/test_compress.rb +55 -0
- data/test/test_conflict.rb +41 -0
- data/test/test_crontabs.rb +398 -0
- data/test/test_dependency.rb +1113 -0
- data/test/test_downgrade.rb +80 -0
- data/test/test_download.rb +95 -0
- data/test/test_encrypt.rb +136 -0
- data/test/test_filemetadata.rb +131 -0
- data/test/test_initscript.rb +93 -0
- data/test/test_install.rb +186 -0
- data/test/test_lock.rb +82 -0
- data/test/test_make.rb +410 -0
- data/test/test_metadata.rb +805 -0
- data/test/test_misc.rb +379 -0
- data/test/test_options.rb +1711 -0
- data/test/test_os.rb +193 -0
- data/test/test_os_debian.rb +99 -0
- data/test/test_os_freebsd.rb +89 -0
- data/test/test_os_macosx.rb +79 -0
- data/test/test_os_redhat.rb +124 -0
- data/test/test_os_solaris.rb +85 -0
- data/test/test_os_windows.rb +26 -0
- data/test/test_query.rb +134 -0
- data/test/test_remove.rb +539 -0
- data/test/test_tar.rb +99 -0
- data/test/test_unpack.rb +977 -0
- data/test/test_upgrade.rb +398 -0
- data/test/test_version.rb +54 -0
- data/test/testcmds/crontab +14 -0
- data/test/testcmds/debian/apt-cache +145 -0
- data/test/testcmds/debian/dpkg-query +16 -0
- data/test/testcmds/freebsd/pkg_info +13 -0
- data/test/testcmds/macosx/port +35 -0
- data/test/testcmds/redhat/rpmbuild +6 -0
- data/test/testcmds/redhat/yum +90 -0
- data/test/testcmds/solaris/pkginfo +25 -0
- data/test/testcmds/solaris/pkgutil +36 -0
- data/test/testpkg/reloc/encfile +2 -0
- data/test/testpkg/reloc/file +2 -0
- data/test/testpkg/reloc/precryptfile +1 -0
- data/test/testpkg/reloc/precryptfile.plaintext +3 -0
- data/test/testpkg/tpkg-bad-ownergroup.xml +25 -0
- data/test/testpkg/tpkg-bad-ownergroup.yml +18 -0
- data/test/testpkg/tpkg-default-perms.xml +28 -0
- data/test/testpkg/tpkg-default-perms.yml +20 -0
- data/test/testpkg/tpkg-good-ownergroup.xml +25 -0
- data/test/testpkg/tpkg-good-ownergroup.yml +18 -0
- data/test/testpkg/tpkg-nativedeps.yml +13 -0
- data/test/testpkg/tpkg-nofiles.xml +14 -0
- data/test/testpkg/tpkg-nofiles.yml +9 -0
- data/test/testpkg/tpkg.xml +35 -0
- data/test/testpkg/tpkg.yml +25 -0
- data/test/tpkgtest.rb +300 -0
- data/tpkg.conf +16 -0
- data/tpkg.gemspec +24 -0
- data/tpkg.spec +28 -0
- data/tpkg.xml +17 -0
- data/tpkg_profile.sh +32 -0
- metadata +306 -31
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
pkgfile=$1
|
6
|
+
operation=$2
|
7
|
+
|
8
|
+
requestfile=/var/etch/requests/etc/sysctl.conf/$pkgfile
|
9
|
+
|
10
|
+
case "$operation" in
|
11
|
+
'install')
|
12
|
+
mkdir -p `dirname "$requestfile"`
|
13
|
+
tmpfile=`mktemp "$requestfile.XXXXXX"` || exit 1
|
14
|
+
echo "<request>" > $tmpfile
|
15
|
+
# Dump in the data passed to us on stdin
|
16
|
+
cat >> $tmpfile
|
17
|
+
echo "</request>" >> $tmpfile
|
18
|
+
chmod 644 "$tmpfile"
|
19
|
+
;;
|
20
|
+
'remove')
|
21
|
+
rm -f "$requestfile".*
|
22
|
+
;;
|
23
|
+
*)
|
24
|
+
echo "$0: Invalid arguments"
|
25
|
+
exit 1
|
26
|
+
;;
|
27
|
+
esac
|
28
|
+
|
29
|
+
/usr/sbin/etch /etc/sysctl.conf
|
30
|
+
|
data/externals-etch/user
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
pkgfile=$1
|
6
|
+
operation=$2
|
7
|
+
|
8
|
+
pwrequestfile=/var/etch/requests/etc/passwd/$pkgfile
|
9
|
+
shrequestfile=/var/etch/requests/etc/shadow/$pkgfile
|
10
|
+
|
11
|
+
case "$operation" in
|
12
|
+
'install')
|
13
|
+
# Grab the data passed to us on stdin
|
14
|
+
datafile=`mktemp`
|
15
|
+
cat > $datafile
|
16
|
+
for requestfile in $pwrequestfile $shrequestfile
|
17
|
+
do
|
18
|
+
mkdir -p `dirname "$requestfile"`
|
19
|
+
tmpfile=`mktemp "$requestfile.XXXXXX"` || exit 1
|
20
|
+
echo "<request>" > $tmpfile
|
21
|
+
# Dump in the data we captured above
|
22
|
+
cat $datafile >> $tmpfile
|
23
|
+
echo "</request>" >> $tmpfile
|
24
|
+
chmod 644 $tmpfile
|
25
|
+
done
|
26
|
+
rm -f $datafile
|
27
|
+
;;
|
28
|
+
'remove')
|
29
|
+
for requestfile in $pwrequestfile $shrequestfile
|
30
|
+
do
|
31
|
+
rm -f "$requestfile".*
|
32
|
+
done
|
33
|
+
;;
|
34
|
+
*)
|
35
|
+
echo "$0: Invalid arguments"
|
36
|
+
exit 1
|
37
|
+
;;
|
38
|
+
esac
|
39
|
+
|
40
|
+
/usr/sbin/etch /etc/passwd /etc/shadow
|
41
|
+
|
data/externals/group
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# The group name might not have a trailing newline, depending on the
|
4
|
+
# syntax the user used in their tpkg.xml/tpkg.yml file. read treats
|
5
|
+
# that as an error, although it will still read the name fine. So if
|
6
|
+
# the read is after the "set -e" then the script aborts. We could work
|
7
|
+
# around it by dumping stdin to a file and reading from there, but that
|
8
|
+
# seems lame.
|
9
|
+
read group
|
10
|
+
|
11
|
+
set -e
|
12
|
+
|
13
|
+
pkgfile=$1
|
14
|
+
operation=$2
|
15
|
+
|
16
|
+
# Discard any remaining data fed to us so as not to trigger a
|
17
|
+
# SIGPIPE in the caller.
|
18
|
+
cat > /dev/null
|
19
|
+
|
20
|
+
case "$operation" in
|
21
|
+
'install')
|
22
|
+
if ! grep ^$group: /etc/group > /dev/null 2>&1
|
23
|
+
then
|
24
|
+
groupadd $group
|
25
|
+
fi
|
26
|
+
;;
|
27
|
+
'remove')
|
28
|
+
# We have no way to know if this package is the only reason this
|
29
|
+
# group is on the system. It could have been requested by other
|
30
|
+
# packages, or added by something outside of tpkg. So just warn
|
31
|
+
# the user that we're leaving it behind.
|
32
|
+
echo "tpkg local external leaving behind group $group from $pkgfile"
|
33
|
+
;;
|
34
|
+
*)
|
35
|
+
echo "$0: Invalid arguments"
|
36
|
+
exit 1
|
37
|
+
;;
|
38
|
+
esac
|
39
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# The groups name might not have a trailing newline, depending on the
|
4
|
+
# syntax the user used in their tpkg.xml/tpkg.yml file. read treats
|
5
|
+
# that as an error, although it will still read the name fine. So if
|
6
|
+
# the read is after the "set -e" then the script aborts. We could work
|
7
|
+
# around it by dumping stdin to a file and reading from there, but that
|
8
|
+
# seems lame.
|
9
|
+
|
10
|
+
# This is a colon delimited value.
|
11
|
+
# supplemental_group:group
|
12
|
+
|
13
|
+
read groups
|
14
|
+
|
15
|
+
suppl=`echo "${groups%%:*}"`
|
16
|
+
group=`echo "${groups#*:}"`
|
17
|
+
|
18
|
+
set -e
|
19
|
+
|
20
|
+
pkgfile=$1
|
21
|
+
operation=$2
|
22
|
+
|
23
|
+
# Discard any remaining data fed to us so as not to trigger a
|
24
|
+
# SIGPIPE in the caller.
|
25
|
+
cat > /dev/null
|
26
|
+
|
27
|
+
case "$operation" in
|
28
|
+
'install')
|
29
|
+
if grep ^$group: /etc/group > /dev/null 2>&1
|
30
|
+
then
|
31
|
+
if grep ^$suppl: /etc/group > /dev/null 2>&1
|
32
|
+
then
|
33
|
+
[ `uname -s` = "Linux" ] && usermod -a -G $suppl $group
|
34
|
+
fi
|
35
|
+
fi
|
36
|
+
;;
|
37
|
+
'remove')
|
38
|
+
# We have no way to know if this package is the only reason this
|
39
|
+
# supplemental group is on the system. It could have been requested
|
40
|
+
# by other packages, or added by something outside of tpkg. So just
|
41
|
+
# warn the user that we're leaving it behind.
|
42
|
+
echo "tpkg local external leaving behind supplemental group $suppl on $group from $pkgfile"
|
43
|
+
;;
|
44
|
+
*)
|
45
|
+
echo "$0: Invalid arguments"
|
46
|
+
exit 1
|
47
|
+
;;
|
48
|
+
esac
|
data/externals/user
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# The username might not have a trailing newline, depending on the
|
4
|
+
# syntax the user used in their tpkg.xml/tpkg.yml file. read treats
|
5
|
+
# that as an error, although it will still read the name fine. So if
|
6
|
+
# the read is after the "set -e" then the script aborts. We could work
|
7
|
+
# around it by dumping stdin to a file and reading from there, but that
|
8
|
+
# seems lame.
|
9
|
+
read user
|
10
|
+
|
11
|
+
set -e
|
12
|
+
|
13
|
+
pkgfile=$1
|
14
|
+
operation=$2
|
15
|
+
|
16
|
+
# Discard any remaining data fed to us so as not to trigger a
|
17
|
+
# SIGPIPE in the caller.
|
18
|
+
cat > /dev/null
|
19
|
+
|
20
|
+
case "$operation" in
|
21
|
+
'install')
|
22
|
+
if ! grep ^$user: /etc/passwd > /dev/null 2>&1
|
23
|
+
then
|
24
|
+
useradd $user
|
25
|
+
fi
|
26
|
+
;;
|
27
|
+
'remove')
|
28
|
+
# We have no way to know if this package is the only reason this
|
29
|
+
# user is on the system. It could have been requested by other
|
30
|
+
# packages, or added by something outside of tpkg. So just warn
|
31
|
+
# the user that we're leaving it behind.
|
32
|
+
echo "tpkg local external leaving behind user $user from $pkgfile"
|
33
|
+
;;
|
34
|
+
*)
|
35
|
+
echo "$0: Invalid arguments"
|
36
|
+
exit 1
|
37
|
+
;;
|
38
|
+
esac
|
39
|
+
|
data/lib/tpkg.rb
CHANGED
@@ -10,14 +10,6 @@ STDOUT.sync = STDERR.sync = true # All outputs/prompts to the kernel ASAP
|
|
10
10
|
# ruby 1.9 and there's nothing we can do to fix that.
|
11
11
|
require 'tpkg/silently'
|
12
12
|
Silently.silently do
|
13
|
-
begin
|
14
|
-
# Try loading facter w/o gems first so that we don't introduce a
|
15
|
-
# dependency on gems if it is not needed.
|
16
|
-
require 'facter' # Facter
|
17
|
-
rescue LoadError
|
18
|
-
require 'rubygems'
|
19
|
-
require 'facter'
|
20
|
-
end
|
21
13
|
require 'digest/sha2' # Digest::SHA256#hexdigest, etc.
|
22
14
|
require 'etc' # Etc.getpwnam, getgrnam
|
23
15
|
require 'fileutils' # FileUtils.cp, rm, etc.
|
@@ -34,15 +26,15 @@ Silently.silently do
|
|
34
26
|
require 'uri' # URI
|
35
27
|
require 'yaml' # YAML
|
36
28
|
end
|
37
|
-
require 'tpkg/deployer'
|
38
|
-
require 'tpkg/metadata'
|
39
|
-
require 'tpkg/versiontype' # Version
|
40
29
|
|
41
30
|
OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError
|
42
31
|
|
43
32
|
class Tpkg
|
44
|
-
|
45
|
-
|
33
|
+
require 'tpkg/deployer'
|
34
|
+
require 'tpkg/metadata'
|
35
|
+
require 'tpkg/versiontype'
|
36
|
+
require 'tpkg/os'
|
37
|
+
require 'tpkg/version'
|
46
38
|
|
47
39
|
GENERIC_ERR = 1
|
48
40
|
POSTINSTALL_ERR = 2
|
@@ -56,8 +48,6 @@ class Tpkg
|
|
56
48
|
DEFAULT_FILE_PERMS = nil
|
57
49
|
DEFAULT_DIR_PERMS = 0755
|
58
50
|
|
59
|
-
attr_reader :installed_directory
|
60
|
-
|
61
51
|
#
|
62
52
|
# Class methods
|
63
53
|
#
|
@@ -356,8 +346,8 @@ class Tpkg
|
|
356
346
|
raise "File #{tpkg_path} referenced in tpkg.yml but not found"
|
357
347
|
end
|
358
348
|
|
359
|
-
# check permission/ownership of crontab files
|
360
|
-
if tpkgfile[:crontab]
|
349
|
+
# check permission/ownership of cron.d-style crontab files
|
350
|
+
if tpkgfile[:crontab] && !tpkgfile[:crontab][:user]
|
361
351
|
data = {:actual_file => working_path, :metadata => metadata, :file_metadata => tpkgfile}
|
362
352
|
perms, uid, gid = predict_file_perms_and_ownership(data)
|
363
353
|
# crontab needs to be owned by root, and is not writable by group or others
|
@@ -419,8 +409,6 @@ class Tpkg
|
|
419
409
|
system("#{find_tar} -C #{workdir} -cf #{tpkgfile} tpkg") || raise("tpkg.tar creation failed")
|
420
410
|
|
421
411
|
# Checksum the tarball
|
422
|
-
# Older ruby version doesn't support this
|
423
|
-
# digest = Digest::SHA256.file(tpkgfile).hexdigest
|
424
412
|
digest = Digest::SHA256.hexdigest(File.read(tpkgfile))
|
425
413
|
|
426
414
|
# Create checksum.xml
|
@@ -681,91 +669,12 @@ class Tpkg
|
|
681
669
|
Dir.mkdir(tmpdir)
|
682
670
|
tmpdir
|
683
671
|
end
|
684
|
-
|
685
|
-
@@arch = nil
|
686
|
-
def self.get_arch
|
687
|
-
if !@@arch
|
688
|
-
Facter.loadfacts
|
689
|
-
@@arch = Facter['hardwaremodel'].value
|
690
|
-
end
|
691
|
-
@@arch.dup
|
692
|
-
end
|
693
|
-
|
694
|
-
# Returns a string representing the OS of this box of the form:
|
695
|
-
# "OSname-OSmajorversion". The OS name is currently whatever facter
|
696
|
-
# returns for the 'operatingsystem' fact. The major version is a bit
|
697
|
-
# messier, as we try on a per-OS basis to come up with something that
|
698
|
-
# represents the major version number of the OS, where binaries are
|
699
|
-
# expected to be compatible across all versions of the OS with that
|
700
|
-
# same major version number. Examples include RedHat-5, CentOS-5,
|
701
|
-
# FreeBSD-7, Darwin-10.5, and Solaris-5.10
|
702
|
-
@@os = nil
|
703
|
-
def self.get_os
|
704
|
-
if !@@os
|
705
|
-
# Tell facter to load everything, otherwise it tries to dynamically
|
706
|
-
# load the individual fact libraries using a very broken mechanism
|
707
|
-
Facter.loadfacts
|
708
|
-
|
709
|
-
operatingsystem = Facter['operatingsystem'].value
|
710
|
-
osver = nil
|
711
|
-
if Facter['lsbmajdistrelease'] &&
|
712
|
-
Facter['lsbmajdistrelease'].value &&
|
713
|
-
!Facter['lsbmajdistrelease'].value.empty?
|
714
|
-
osver = Facter['lsbmajdistrelease'].value
|
715
|
-
elsif operatingsystem == 'Ubuntu'
|
716
|
-
# Work around lack of lsbmajdistrelease on older versions of Ubuntu
|
717
|
-
# due to older version of facter. Support for lsbmajdistrelease on
|
718
|
-
# Ubuntu was added in facter 1.5.3, but there's no good way to force
|
719
|
-
# older Ubuntu systems to a newer version of facter.
|
720
|
-
osver = Facter['lsbdistrelease'].value.split('.').first
|
721
|
-
elsif Facter['kernel'] &&
|
722
|
-
Facter['kernel'].value == 'Darwin' &&
|
723
|
-
Facter['macosx_productversion'] &&
|
724
|
-
Facter['macosx_productversion'].value &&
|
725
|
-
!Facter['macosx_productversion'].value.empty?
|
726
|
-
macver = Facter['macosx_productversion'].value
|
727
|
-
# Extract 10.5 from 10.5.6, for example
|
728
|
-
osver = macver.split('.')[0,2].join('.')
|
729
|
-
elsif Facter['operatingsystem'] &&
|
730
|
-
Facter['operatingsystem'].value == 'FreeBSD'
|
731
|
-
# Extract 7 from 7.1-RELEASE, for example
|
732
|
-
fbver = Facter['operatingsystemrelease'].value
|
733
|
-
osver = fbver.split('.').first
|
734
|
-
elsif Facter['operatingsystem'] &&
|
735
|
-
Facter['operatingsystem'].value == 'windows'
|
736
|
-
# Extract 6.1 from 6.1.7601, for example
|
737
|
-
# That seems like the right level to split at
|
738
|
-
# based on http://en.wikipedia.org/wiki/Ver_(command)
|
739
|
-
winver = Facter['operatingsystemrelease'].value
|
740
|
-
osver = winver.split('.')[0,2].join('.')
|
741
|
-
elsif Facter['operatingsystemrelease'] &&
|
742
|
-
Facter['operatingsystemrelease'].value &&
|
743
|
-
!Facter['operatingsystemrelease'].value.empty?
|
744
|
-
osver = Facter['operatingsystemrelease'].value
|
745
|
-
else
|
746
|
-
raise "Unable to determine proper OS value on this platform"
|
747
|
-
end
|
748
|
-
@@os = "#{operatingsystem}-#{osver}"
|
749
|
-
end
|
750
|
-
@@os.dup
|
751
|
-
end
|
752
|
-
|
753
|
-
# Should sudo be on by default?
|
754
|
-
def self.sudo_default?
|
755
|
-
# Neither of the common Windows environments for running Ruby have
|
756
|
-
# sudo, so turn it off by default on those platforms
|
757
|
-
if RUBY_PLATFORM == 'i386-mingw32' || RUBY_PLATFORM == 'i386-cygwin'
|
758
|
-
false
|
759
|
-
else
|
760
|
-
true
|
761
|
-
end
|
762
|
-
end
|
763
672
|
|
764
673
|
# Given an array of pkgs. Determine if any of those package
|
765
674
|
# satisfy the requirement specified by req
|
766
|
-
def
|
675
|
+
def packages_meet_requirement?(pkgs, req)
|
767
676
|
pkgs.each do | pkg |
|
768
|
-
return true if
|
677
|
+
return true if package_meets_requirement?(pkg, req)
|
769
678
|
end
|
770
679
|
return false
|
771
680
|
end
|
@@ -774,7 +683,7 @@ class Tpkg
|
|
774
683
|
# available package
|
775
684
|
# req is a standard Hash format used in the library to represent package
|
776
685
|
# requirements
|
777
|
-
def
|
686
|
+
def package_meets_requirement?(pkg, req)
|
778
687
|
result = true
|
779
688
|
puts "pkg_meets_req checking #{pkg.inspect} against #{req.inspect}" if @@debug
|
780
689
|
metadata = pkg[:metadata]
|
@@ -872,16 +781,16 @@ class Tpkg
|
|
872
781
|
# field matches all clients.
|
873
782
|
if metadata[:operatingsystem] &&
|
874
783
|
!metadata[:operatingsystem].empty? &&
|
875
|
-
!metadata[:operatingsystem].include?(
|
876
|
-
!metadata[:operatingsystem].any?{|
|
784
|
+
!metadata[:operatingsystem].include?(os.os) &&
|
785
|
+
!metadata[:operatingsystem].any?{|mos| os.os =~ /#{mos}/}
|
877
786
|
puts "Package fails operatingsystem" if @@debug
|
878
787
|
result = false
|
879
788
|
end
|
880
789
|
# Same deal with empty? here
|
881
790
|
if metadata[:architecture] &&
|
882
791
|
!metadata[:architecture].empty? &&
|
883
|
-
!metadata[:architecture].include?(
|
884
|
-
!metadata[:architecture].any?{|
|
792
|
+
!metadata[:architecture].include?(os.arch) &&
|
793
|
+
!metadata[:architecture].any?{|march| os.arch =~ /#{march}/}
|
885
794
|
puts "Package fails architecture" if @@debug
|
886
795
|
result = false
|
887
796
|
end
|
@@ -1338,7 +1247,7 @@ class Tpkg
|
|
1338
1247
|
DEFAULT_BASE = '/opt/tpkg'
|
1339
1248
|
DEFAULT_CONFIGDIR = '/etc'
|
1340
1249
|
|
1341
|
-
def initialize(options)
|
1250
|
+
def initialize(options={})
|
1342
1251
|
# Options
|
1343
1252
|
@base = options[:base] ? options[:base] : DEFAULT_BASE
|
1344
1253
|
# An array of filenames or URLs which point to individual package files
|
@@ -1367,9 +1276,10 @@ class Tpkg
|
|
1367
1276
|
if options.has_key?(:force)
|
1368
1277
|
@force = options[:force]
|
1369
1278
|
end
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1279
|
+
|
1280
|
+
@cmd_crontab = 'crontab'
|
1281
|
+
if options[:cmd_crontab]
|
1282
|
+
@cmd_crontab = options[:cmd_crontab]
|
1373
1283
|
end
|
1374
1284
|
|
1375
1285
|
@configdir = DEFAULT_CONFIGDIR
|
@@ -1398,7 +1308,7 @@ class Tpkg
|
|
1398
1308
|
rescue Errno::EACCES
|
1399
1309
|
raise if Process.euid == 0
|
1400
1310
|
rescue Errno::EIO => e
|
1401
|
-
if
|
1311
|
+
if os.os =~ /Darwin/
|
1402
1312
|
# Try to help our Mac OS X users, otherwise this could be
|
1403
1313
|
# rather confusing.
|
1404
1314
|
warn "\nNote: /home is controlled by the automounter by default on Mac OS X.\n" +
|
@@ -1417,12 +1327,10 @@ class Tpkg
|
|
1417
1327
|
dirs_to_create = [@installed_directory, @metadata_directory, @sources_directory,
|
1418
1328
|
@tmp_directory, @log_directory]
|
1419
1329
|
dirs_to_create.each do |dir|
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
raise if Process.euid == 0
|
1425
|
-
end
|
1330
|
+
begin
|
1331
|
+
FileUtils.mkdir_p(dir)
|
1332
|
+
rescue Errno::EACCES
|
1333
|
+
raise if Process.euid == 0
|
1426
1334
|
end
|
1427
1335
|
end
|
1428
1336
|
@tar = Tpkg::find_tar
|
@@ -1432,16 +1340,28 @@ class Tpkg
|
|
1432
1340
|
@locks = 0
|
1433
1341
|
@installed_metadata = {}
|
1434
1342
|
@available_packages_cache = {}
|
1343
|
+
@os = nil
|
1435
1344
|
end
|
1436
1345
|
|
1437
1346
|
attr_reader :base
|
1347
|
+
attr_reader :installed_directory
|
1438
1348
|
attr_reader :sources
|
1439
1349
|
attr_reader :report_server
|
1440
1350
|
attr_reader :lockforce
|
1441
1351
|
attr_reader :force
|
1442
|
-
attr_reader :sudo
|
1443
1352
|
attr_reader :file_system_root
|
1444
1353
|
|
1354
|
+
# This allows us to avoid creating an OS object (which is rather slow due to
|
1355
|
+
# Facter loading) unless it is needed. Many tpkg operations don't require
|
1356
|
+
# an OS object, so it is nice to not spend the time creating one if it is
|
1357
|
+
# not needed.
|
1358
|
+
def os
|
1359
|
+
if !@os
|
1360
|
+
@os = Tpkg::OS.create(:debug => @@debug)
|
1361
|
+
end
|
1362
|
+
@os
|
1363
|
+
end
|
1364
|
+
|
1445
1365
|
def gethttp(uri)
|
1446
1366
|
if uri.scheme != 'http' && uri.scheme != 'https'
|
1447
1367
|
# It would be possible to add support for FTP and possibly
|
@@ -1450,12 +1370,6 @@ class Tpkg
|
|
1450
1370
|
end
|
1451
1371
|
http = Net::HTTP.new(uri.host, uri.port)
|
1452
1372
|
if uri.scheme == 'https'
|
1453
|
-
# Eliminate the OpenSSL "using default DH parameters" warning
|
1454
|
-
if File.exist?(File.join(@configdir, 'tpkg', 'dhparams'))
|
1455
|
-
dh = OpenSSL::PKey::DH.new(IO.read(File.join(@configdir, 'tpkg', 'dhparams')))
|
1456
|
-
Net::HTTP.ssl_context_accessor(:tmp_dh_callback)
|
1457
|
-
http.tmp_dh_callback = proc { dh }
|
1458
|
-
end
|
1459
1373
|
http.use_ssl = true
|
1460
1374
|
if File.exist?(File.join(@configdir, 'tpkg', 'ca.pem'))
|
1461
1375
|
http.ca_file = File.join(@configdir, 'tpkg', 'ca.pem')
|
@@ -1538,9 +1452,7 @@ class Tpkg
|
|
1538
1452
|
# Attempt to save a local copy, might not work if we're not
|
1539
1453
|
# running with sufficient privileges
|
1540
1454
|
begin
|
1541
|
-
|
1542
|
-
FileUtils.mkdir_p(localdir)
|
1543
|
-
end
|
1455
|
+
FileUtils.mkdir_p(localdir)
|
1544
1456
|
File.open(localpath, 'w') do |file|
|
1545
1457
|
file.puts(response.body)
|
1546
1458
|
end
|
@@ -1611,10 +1523,10 @@ class Tpkg
|
|
1611
1523
|
end
|
1612
1524
|
end
|
1613
1525
|
|
1614
|
-
# Used by
|
1526
|
+
# Used by available_native_packages to stuff all the info about a
|
1615
1527
|
# native package into a hash to match the structure we pass around
|
1616
1528
|
# internally for tpkgs
|
1617
|
-
def pkg_for_native_package(name, version, package_version, source)
|
1529
|
+
def self.pkg_for_native_package(name, version, package_version, source)
|
1618
1530
|
metadata = {}
|
1619
1531
|
metadata[:name] = name
|
1620
1532
|
metadata[:version] = version
|
@@ -1626,260 +1538,18 @@ class Tpkg
|
|
1626
1538
|
pkg
|
1627
1539
|
end
|
1628
1540
|
|
1629
|
-
def
|
1630
|
-
if
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
{:arg => 'available', :header => 'Available', :source => :native_available} ].each do |yum|
|
1635
|
-
cmd = "yum info #{yum[:arg]} #{pkgname}"
|
1636
|
-
puts "available_native_packages running '#{cmd}'" if @@debug
|
1637
|
-
stderr_first_line = nil
|
1638
|
-
Open3.popen3(cmd) do |stdin, stdout, stderr|
|
1639
|
-
stdin.close
|
1640
|
-
read_packages = false
|
1641
|
-
name = version = package_version = nil
|
1642
|
-
stdout.each_line do |line|
|
1643
|
-
if line =~ /#{yum[:header]} Packages/
|
1644
|
-
# Skip the header lines until we get to this line
|
1645
|
-
read_packages = true
|
1646
|
-
elsif read_packages
|
1647
|
-
if line =~ /^Name\s*:\s*(.+)/
|
1648
|
-
name = $1.strip
|
1649
|
-
elsif line =~ /^Arch\s*:\s*(.+)/
|
1650
|
-
arch = $1.strip
|
1651
|
-
elsif line =~ /^Version\s*:\s*(.+)/
|
1652
|
-
version = $1.strip.to_s
|
1653
|
-
elsif line =~ /^Release\s*:\s*(.+)/
|
1654
|
-
package_version = $1.strip.to_s
|
1655
|
-
elsif line =~ /^Repo\s*:\s*(.+)/
|
1656
|
-
repo = $1.strip
|
1657
|
-
elsif line =~ /^\s*$/
|
1658
|
-
pkg = pkg_for_native_package(name, version, package_version, yum[:source])
|
1659
|
-
native_packages << pkg
|
1660
|
-
name = version = package_version = nil
|
1661
|
-
end
|
1662
|
-
# In the end we ignore the architecture. Anything that
|
1663
|
-
# shows up in yum should be installable on this box, and
|
1664
|
-
# the chance of a mismatch between facter's idea of the
|
1665
|
-
# architecture and RPM's idea is high. I.e. i386 vs i686
|
1666
|
-
# or i32e vs x86_64 or whatever.
|
1667
|
-
end
|
1668
|
-
end
|
1669
|
-
stderr_first_line = stderr.gets
|
1670
|
-
end
|
1671
|
-
# FIXME: popen3 doesn't set $?
|
1672
|
-
if !$?.success?
|
1673
|
-
# Ignore 'no matching packages', raise anything else
|
1674
|
-
if stderr_first_line != "Error: No matching Packages to list\n"
|
1675
|
-
raise "available_native_packages error running yum"
|
1676
|
-
end
|
1677
|
-
end
|
1678
|
-
end
|
1679
|
-
elsif Tpkg::get_os =~ /Debian|Ubuntu/
|
1680
|
-
# The default 'dpkg -l' format has an optional third column for
|
1681
|
-
# errors, which makes it hard to parse reliably.
|
1682
|
-
puts "available_native_packages running dpkg-query -W -f='${Package} ${Version} ${Status}\n' #{pkgname}" if @@debug
|
1683
|
-
stderr_first_line = nil
|
1684
|
-
Open3.popen3("dpkg-query -W -f='${Package} ${Version} ${Status}\n' #{pkgname}") do |stdin, stdout, stderr|
|
1685
|
-
stdin.close
|
1686
|
-
stdout.each_line do |line|
|
1687
|
-
name, debversion, status = line.split(' ', 3)
|
1688
|
-
# Seems to be Debian convention that if the package has a
|
1689
|
-
# package version you seperate that from the upstream version
|
1690
|
-
# with a hyphen.
|
1691
|
-
version = nil
|
1692
|
-
package_version = nil
|
1693
|
-
if debversion =~ /-/
|
1694
|
-
version, package_version = debversion.split('-', 2)
|
1695
|
-
else
|
1696
|
-
version = debversion
|
1697
|
-
end
|
1698
|
-
# We want packages with a state of "installed". However,
|
1699
|
-
# there's also a state of "not-installed", and the state
|
1700
|
-
# field contains several space-seperated values, so we have
|
1701
|
-
# to be somewhat careful to pick out "installed".
|
1702
|
-
if status.split(' ').include?('installed')
|
1703
|
-
pkg = pkg_for_native_package(name, version, package_version, :native_installed)
|
1704
|
-
native_packages << pkg
|
1705
|
-
end
|
1706
|
-
end
|
1707
|
-
stderr_first_line = stderr.gets
|
1708
|
-
end
|
1709
|
-
# FIXME: popen3 doesn't set $?
|
1710
|
-
if !$?.success?
|
1711
|
-
# Ignore 'no matching packages', raise anything else
|
1712
|
-
if stderr_first_line !~ 'No packages found matching'
|
1713
|
-
raise "available_native_packages error running dpkg-query"
|
1714
|
-
end
|
1715
|
-
end
|
1716
|
-
puts "available_native_packages running 'apt-cache show #{pkgname}'" if @@debug
|
1717
|
-
IO.popen("apt-cache show #{pkgname}") do |pipe|
|
1718
|
-
name = nil
|
1719
|
-
version = nil
|
1720
|
-
package_version = nil
|
1721
|
-
pipe.each_line do |line|
|
1722
|
-
if line =~ /^Package: (.*)/
|
1723
|
-
name = $1
|
1724
|
-
version = nil
|
1725
|
-
package_version = nil
|
1726
|
-
elsif line =~ /^Version: (.*)/
|
1727
|
-
debversion = $1
|
1728
|
-
# Seems to be Debian convention that if the package has a
|
1729
|
-
# package version you seperate that from the upstream version
|
1730
|
-
# with a hyphen.
|
1731
|
-
if debversion =~ /-/
|
1732
|
-
version, package_version = debversion.split('-', 2)
|
1733
|
-
else
|
1734
|
-
version = debversion
|
1735
|
-
end
|
1736
|
-
pkg = pkg_for_native_package(name, version, package_version, :native_available)
|
1737
|
-
native_packages << pkg
|
1738
|
-
end
|
1739
|
-
end
|
1740
|
-
end
|
1741
|
-
if !$?.success?
|
1742
|
-
raise "available_native_packages error running apt-cache"
|
1743
|
-
end
|
1744
|
-
elsif Tpkg::get_os =~ /Solaris/
|
1745
|
-
# Example of pkginfo -x output:
|
1746
|
-
# SUNWzfsu ZFS (Usr)
|
1747
|
-
# (i386) 11.10.0,REV=2006.05.18.01.46
|
1748
|
-
puts "available_native_packages running 'pkginfo -x #{pkgname}'" if @@debug
|
1749
|
-
IO.popen("pkginfo -x #{pkgname}") do |pipe|
|
1750
|
-
name = nil
|
1751
|
-
version = nil
|
1752
|
-
package_version = nil
|
1753
|
-
pipe.each_line do |line|
|
1754
|
-
if line =~ /^\w/
|
1755
|
-
name = line.split(' ')
|
1756
|
-
version = nil
|
1757
|
-
package_version = nil
|
1758
|
-
else
|
1759
|
-
arch, solversion = line.split(' ')
|
1760
|
-
# Lots of Sun and some third party packages (including CSW)
|
1761
|
-
# seem to use this REV= convention in the version. I've
|
1762
|
-
# never seen it documented, but since it seems to be a
|
1763
|
-
# widely used convention we'll go with it.
|
1764
|
-
if solversion =~ /,REV=/
|
1765
|
-
version, package_version = solversion.split(',REV=')
|
1766
|
-
else
|
1767
|
-
version = solversion
|
1768
|
-
end
|
1769
|
-
pkg = pkg_for_native_package(name, version, package_version, :native_installed)
|
1770
|
-
native_packages << pkg
|
1771
|
-
end
|
1772
|
-
end
|
1773
|
-
end
|
1774
|
-
if !$?.success?
|
1775
|
-
raise "available_native_packages error running pkginfo"
|
1776
|
-
end
|
1777
|
-
if File.exist?('/opt/csw/bin/pkg-get')
|
1778
|
-
puts "available_native_packages running '/opt/csw/bin/pkg-get -a'" if @@debug
|
1779
|
-
IO.popen('/opt/csw/bin/pkg-get -a') do |pipe|
|
1780
|
-
pipe.each_line do |line|
|
1781
|
-
next if line =~ /^#/ # Skip comments
|
1782
|
-
name, solversion = line.split
|
1783
|
-
# pkg-get doesn't have an option to only show available
|
1784
|
-
# packages matching a specific name, so we have to look over
|
1785
|
-
# all available packages and pick out the ones that match.
|
1786
|
-
next if name != pkgname
|
1787
|
-
# Lots of Sun and some third party packages (including CSW)
|
1788
|
-
# seem to use this REV= convention in the version. I've
|
1789
|
-
# never seen it documented, but since it seems to be a
|
1790
|
-
# widely used convention we'll go with it.
|
1791
|
-
version = nil
|
1792
|
-
package_version = nil
|
1793
|
-
if solversion =~ /,REV=/
|
1794
|
-
version, package_version = solversion.split(',REV=')
|
1795
|
-
else
|
1796
|
-
version = solversion
|
1797
|
-
end
|
1798
|
-
pkg = pkg_for_native_package(name, version, package_version, :native_available)
|
1799
|
-
native_packages << pkg
|
1800
|
-
end
|
1801
|
-
end
|
1802
|
-
end
|
1803
|
-
elsif Tpkg::get_os =~ /FreeBSD/
|
1804
|
-
puts "available_native_packages running 'pkg_info #{pkgname}'" if @@debug
|
1805
|
-
IO.popen("pkg_info #{pkgname}") do |pipe|
|
1806
|
-
pipe.each_line do |line|
|
1807
|
-
name_and_version = line.split(' ', 3)
|
1808
|
-
nameparts = name_and_version.split('-')
|
1809
|
-
fbversion = nameparts.pop
|
1810
|
-
name = nameparts.join('-')
|
1811
|
-
# Seems to be FreeBSD convention that if the package has a
|
1812
|
-
# package version you seperate that from the upstream version
|
1813
|
-
# with an underscore.
|
1814
|
-
version = nil
|
1815
|
-
package_version = nil
|
1816
|
-
if fbversion =~ /_/
|
1817
|
-
version, package_version = fbversion.split('_', 2)
|
1818
|
-
else
|
1819
|
-
version = fbversion
|
1820
|
-
end
|
1821
|
-
pkg = pkg_for_native_package(name, version, package_version, :native_installed)
|
1822
|
-
package_version << pkg
|
1823
|
-
end
|
1824
|
-
end
|
1825
|
-
if !$?.success?
|
1826
|
-
raise "available_native_packages error running pkg_info"
|
1827
|
-
end
|
1828
|
-
# FIXME: FreeBSD available packages
|
1829
|
-
# We could either poke around in the ports tree (if installed), or
|
1830
|
-
# try to recreate the URL "pkg_add -r" would use and pull a
|
1831
|
-
# directory listing.
|
1832
|
-
elsif Tpkg::get_os =~ /Darwin/
|
1833
|
-
if File.exist?('/opt/local/bin/port')
|
1834
|
-
puts "available_native_packages running '/opt/local/bin/port installed #{pkgname}'" if @@debug
|
1835
|
-
IO.popen("/opt/local/bin/port installed #{pkgname}") do |pipe|
|
1836
|
-
pipe.each_line do |line|
|
1837
|
-
next if line =~ /The following ports are currently installed/
|
1838
|
-
next if line =~ /None of the specified ports are installed/
|
1839
|
-
next if line !~ /\(active\)/
|
1840
|
-
name, version = line.split(' ')
|
1841
|
-
version.sub!(/^@/, '')
|
1842
|
-
# Remove variant names
|
1843
|
-
version.sub!(/\+.*/, '')
|
1844
|
-
# Remove the _number that is always listed on installed ports,
|
1845
|
-
# presumably some sort of differentiator if multiple copies of
|
1846
|
-
# the same port version are installed.
|
1847
|
-
version.sub!(/_\d+$/, '')
|
1848
|
-
package_version = nil
|
1849
|
-
pkg = pkg_for_native_package(name, version, package_version, :native_installed)
|
1850
|
-
native_packages << pkg
|
1851
|
-
end
|
1852
|
-
end
|
1853
|
-
if !$?.success?
|
1854
|
-
raise "available_native_packages error running port"
|
1855
|
-
end
|
1856
|
-
puts "available_native_packages running '/opt/local/bin/port list #{pkgname}'" if @@debug
|
1857
|
-
IO.popen("/opt/local/bin/port list #{pkgname}") do |pipe|
|
1858
|
-
pipe.each_line do |line|
|
1859
|
-
name, version = line.split(' ')
|
1860
|
-
version.sub!(/^@/, '')
|
1861
|
-
package_version = nil
|
1862
|
-
pkg = pkg_for_native_package(name, version, package_version, :native_available)
|
1863
|
-
native_packages << pkg
|
1864
|
-
end
|
1865
|
-
end
|
1866
|
-
if !$?.success?
|
1867
|
-
raise "available_native_packages error running port"
|
1868
|
-
end
|
1869
|
-
else
|
1870
|
-
# Fink support would be nice
|
1871
|
-
raise "No supported native package tool available on #{Tpkg::get_os}"
|
1872
|
-
end
|
1873
|
-
else
|
1874
|
-
puts "Unknown value for OS: #{Tpkg::get_os}"
|
1875
|
-
end
|
1876
|
-
@available_native_packages[pkgname] = native_packages
|
1541
|
+
def available_native_packages(pkgname)
|
1542
|
+
if @available_native_packages[pkgname]
|
1543
|
+
return @available_native_packages[pkgname]
|
1544
|
+
else
|
1545
|
+
native_packages = os.available_native_packages(pkgname)
|
1877
1546
|
if @@debug
|
1878
1547
|
nicount = native_packages.select{|pkg| pkg[:source] == :native_installed}.length
|
1879
1548
|
nacount = native_packages.select{|pkg| pkg[:source] == :native_available}.length
|
1880
1549
|
puts "Found #{nicount} installed native packages for #{pkgname}"
|
1881
1550
|
puts "Found #{nacount} available native packages for #{pkgname}"
|
1882
1551
|
end
|
1552
|
+
@available_native_packages[pkgname] = native_packages
|
1883
1553
|
end
|
1884
1554
|
end
|
1885
1555
|
|
@@ -1982,16 +1652,15 @@ class Tpkg
|
|
1982
1652
|
# that we clone it here. Otherwise, req can be changed later on from
|
1983
1653
|
# the calling method and modify our cache inadvertently
|
1984
1654
|
if req[:type] == :native
|
1985
|
-
|
1986
|
-
|
1987
|
-
if Tpkg::package_meets_requirement?(pkg, req)
|
1655
|
+
available_native_packages(req[:name]).each do |pkg|
|
1656
|
+
if package_meets_requirement?(pkg, req)
|
1988
1657
|
pkgs << pkg
|
1989
1658
|
end
|
1990
1659
|
end
|
1991
1660
|
else
|
1992
1661
|
load_available_packages(req[:name])
|
1993
1662
|
@available_packages[req[:name]].each do |pkg|
|
1994
|
-
if
|
1663
|
+
if package_meets_requirement?(pkg, req)
|
1995
1664
|
pkgs << pkg
|
1996
1665
|
end
|
1997
1666
|
end
|
@@ -2028,10 +1697,9 @@ class Tpkg
|
|
2028
1697
|
def installed_packages_that_meet_requirement(req=nil)
|
2029
1698
|
pkgs = []
|
2030
1699
|
if req && req[:type] == :native
|
2031
|
-
|
2032
|
-
@available_native_packages[req[:name]].each do |pkg|
|
1700
|
+
available_native_packages(req[:name]).each do |pkg|
|
2033
1701
|
if pkg[:source] == :native_installed &&
|
2034
|
-
|
1702
|
+
package_meets_requirement?(pkg, req)
|
2035
1703
|
pkgs << pkg
|
2036
1704
|
end
|
2037
1705
|
end
|
@@ -2060,7 +1728,7 @@ class Tpkg
|
|
2060
1728
|
# makes the process more consistent and easier to follow.
|
2061
1729
|
installed_packages(pkgname).each do |pkg|
|
2062
1730
|
if req
|
2063
|
-
if
|
1731
|
+
if package_meets_requirement?(pkg, req)
|
2064
1732
|
pkgs << pkg
|
2065
1733
|
end
|
2066
1734
|
else
|
@@ -2169,7 +1837,7 @@ class Tpkg
|
|
2169
1837
|
# nil entry inserted into packages by the sorting code
|
2170
1838
|
# below. We need to skip those.
|
2171
1839
|
if pkg != nil
|
2172
|
-
|
1840
|
+
package_meets_requirement?(pkg, req)
|
2173
1841
|
end
|
2174
1842
|
end
|
2175
1843
|
end
|
@@ -2405,7 +2073,7 @@ class Tpkg
|
|
2405
2073
|
if packages[newreq[:type]][newreq[:name]]
|
2406
2074
|
pkg = solution[:pkgs].find{|solpkg| solpkg[:metadata][:name] == newreq[:name]}
|
2407
2075
|
puts "checksol newreq pkg: #{pkg.inspect}" if @@debug
|
2408
|
-
if pkg &&
|
2076
|
+
if pkg && package_meets_requirement?(pkg, newreq)
|
2409
2077
|
# No change to solution needed
|
2410
2078
|
else
|
2411
2079
|
# Solution no longer works
|
@@ -2456,9 +2124,7 @@ class Tpkg
|
|
2456
2124
|
# If downloaddir is specified, then download to that directory. Otherwise,
|
2457
2125
|
# download to default source directory
|
2458
2126
|
localdir = downloaddir || localdir
|
2459
|
-
|
2460
|
-
FileUtils.mkdir_p(localdir)
|
2461
|
-
end
|
2127
|
+
FileUtils.mkdir_p(localdir)
|
2462
2128
|
localpath = File.join(localdir, File.basename(path))
|
2463
2129
|
end
|
2464
2130
|
uri = URI.join(source, path)
|
@@ -2503,119 +2169,62 @@ class Tpkg
|
|
2503
2169
|
end
|
2504
2170
|
init_scripts
|
2505
2171
|
end
|
2506
|
-
|
2507
2172
|
# Given a package's metadata return a hash of init scripts in the
|
2508
2173
|
# package and where they need to be linked to on the system
|
2509
2174
|
def init_links(metadata)
|
2510
2175
|
links = {}
|
2511
2176
|
init_scripts(metadata).each do |installed_path, tpkgfile|
|
2512
|
-
|
2513
|
-
|
2514
|
-
|
2515
|
-
Tpkg::get_os =~ /Solaris/
|
2516
|
-
start = '99'
|
2517
|
-
if tpkgfile[:init][:start]
|
2518
|
-
start = tpkgfile[:init][:start]
|
2519
|
-
end
|
2520
|
-
levels = nil
|
2521
|
-
if Tpkg::get_os =~ /RedHat|CentOS|Fedora/ ||
|
2522
|
-
Tpkg::get_os =~ /Debian|Ubuntu/
|
2523
|
-
levels = ['2', '3', '4', '5']
|
2524
|
-
elsif Tpkg::get_os =~ /Solaris/
|
2525
|
-
levels = ['2', '3']
|
2526
|
-
end
|
2527
|
-
if tpkgfile[:init][:levels]
|
2528
|
-
levels = tpkgfile[:init][:levels]
|
2529
|
-
end
|
2530
|
-
init_directory = nil
|
2531
|
-
if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
|
2532
|
-
init_directory = File.join(@file_system_root, 'etc', 'rc.d')
|
2533
|
-
elsif Tpkg::get_os =~ /Debian|Ubuntu/ ||
|
2534
|
-
Tpkg::get_os =~ /Solaris/
|
2535
|
-
init_directory = File.join(@file_system_root, 'etc')
|
2536
|
-
end
|
2537
|
-
|
2538
|
-
# in case user specify levels in yaml as string/integer instead of array
|
2539
|
-
if !levels.kind_of?(Array)
|
2540
|
-
levels = levels.to_s.split(//)
|
2541
|
-
end
|
2542
|
-
|
2543
|
-
levels.each do |level|
|
2544
|
-
links[File.join(init_directory, "rc#{level}.d", 'S' + start.to_s + File.basename(installed_path))] = installed_path
|
2545
|
-
end
|
2546
|
-
elsif Tpkg::get_os =~ /FreeBSD/
|
2547
|
-
init_directory = File.join(@file_system_root, 'usr', 'local', 'etc', 'rc.d')
|
2548
|
-
if tpkgfile[:init][:levels] && tpkgfile[:init][:levels].empty?
|
2549
|
-
# User doesn't want the init script linked in to auto-start
|
2550
|
-
else
|
2551
|
-
links[File.join(init_directory, File.basename(installed_path))] = installed_path
|
2552
|
-
end
|
2553
|
-
else
|
2554
|
-
warn "No init script support for #{Tpkg::get_os}"
|
2177
|
+
os.init_links(installed_path, tpkgfile).each do |link_path|
|
2178
|
+
link = File.join(@file_system_root, link_path)
|
2179
|
+
links[link] = File.join(@file_system_root, installed_path)
|
2555
2180
|
end
|
2556
2181
|
end
|
2557
2182
|
links
|
2558
2183
|
end
|
2559
|
-
|
2560
2184
|
# Given a package's metadata return a hash of crontabs in the
|
2561
|
-
# package and
|
2562
|
-
def
|
2563
|
-
|
2564
|
-
|
2565
|
-
# Don't do anything unless we have to
|
2185
|
+
# package and the entry for that file from the metadata
|
2186
|
+
def crontabs(metadata)
|
2187
|
+
crontabs = {}
|
2566
2188
|
unless metadata[:files] && metadata[:files][:files]
|
2567
|
-
return
|
2189
|
+
return crontabs
|
2568
2190
|
end
|
2569
|
-
|
2570
2191
|
metadata[:files][:files].each do |tpkgfile|
|
2571
2192
|
if tpkgfile[:crontab]
|
2572
2193
|
tpkg_path = tpkgfile[:path]
|
2573
2194
|
installed_path = normalize_path(tpkg_path)
|
2574
|
-
|
2575
|
-
|
2576
|
-
# Decide whether we're going to add the file to a per-user
|
2577
|
-
# crontab or link it into a directory of misc. crontabs. If the
|
2578
|
-
# system only supports per-user crontabs we have to go the
|
2579
|
-
# per-user route. If the system supports both we decide based on
|
2580
|
-
# whether the package specifies a user for the crontab.
|
2581
|
-
# Systems that only support per-user style
|
2582
|
-
if Tpkg::get_os =~ /FreeBSD/ ||
|
2583
|
-
Tpkg::get_os =~ /Solaris/ ||
|
2584
|
-
Tpkg::get_os =~ /Darwin/
|
2585
|
-
if tpkgfile[:crontab][:user]
|
2586
|
-
user = tpkgfile[:crontab][:user]
|
2587
|
-
if Tpkg::get_os =~ /FreeBSD/
|
2588
|
-
destinations[installed_path][:file] = File.join(@file_system_root, 'var', 'cron', 'tabs', user)
|
2589
|
-
elsif Tpkg::get_os =~ /Solaris/
|
2590
|
-
destinations[installed_path][:file] = File.join(@file_system_root, 'var', 'spool', 'cron', 'crontabs', user)
|
2591
|
-
elsif Tpkg::get_os =~ /Darwin/
|
2592
|
-
destinations[installed_path][:file] = File.join(@file_system_root, 'usr', 'lib', 'cron', 'tabs', user)
|
2593
|
-
end
|
2594
|
-
else
|
2595
|
-
raise "No user specified for crontab in #{metadata[:filename]}"
|
2596
|
-
end
|
2597
|
-
# Systems that support cron.d style
|
2598
|
-
elsif Tpkg::get_os =~ /RedHat|CentOS|Fedora/ ||
|
2599
|
-
Tpkg::get_os =~ /Debian|Ubuntu/
|
2600
|
-
# If a user is specified go the per-user route
|
2601
|
-
if tpkgfile[:crontab][:user]
|
2602
|
-
user = tpkgfile[:crontab][:user]
|
2603
|
-
if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
|
2604
|
-
destinations[installed_path][:file] = File.join(@file_system_root, 'var', 'spool', 'cron', user)
|
2605
|
-
elsif Tpkg::get_os =~ /Debian|Ubuntu/
|
2606
|
-
destinations[installed_path][:file] = File.join(@file_system_root, 'var', 'spool', 'cron', 'crontabs', user)
|
2607
|
-
end
|
2608
|
-
# Otherwise go the cron.d route
|
2609
|
-
else
|
2610
|
-
destinations[installed_path][:link] = File.join(@file_system_root, 'etc', 'cron.d', File.basename(installed_path))
|
2611
|
-
end
|
2612
|
-
else
|
2613
|
-
warn "No crontab support for #{Tpkg::get_os}"
|
2614
|
-
end
|
2195
|
+
crontabs[installed_path] = tpkgfile
|
2615
2196
|
end
|
2616
2197
|
end
|
2198
|
+
crontabs
|
2199
|
+
end
|
2200
|
+
# Given a package's metadata return a hash of crontabs in the
|
2201
|
+
# package and where they need to be installed on the system
|
2202
|
+
def crontab_destinations(metadata)
|
2203
|
+
destinations = {}
|
2204
|
+
crontabs(metadata).each do |installed_path, tpkgfile|
|
2205
|
+
destinations[installed_path] = crontab_destination(installed_path, tpkgfile)
|
2206
|
+
end
|
2617
2207
|
destinations
|
2618
2208
|
end
|
2209
|
+
# Given info for a crontab from a package's metadata return info about
|
2210
|
+
# where the crontab needs to be installed on the system
|
2211
|
+
def crontab_destination(installed_path, tpkgfile)
|
2212
|
+
destination = {}
|
2213
|
+
# Decide whether we're going to add the file to a per-user crontab or
|
2214
|
+
# link it into a directory of cron.d-style crontabs.
|
2215
|
+
if tpkgfile[:crontab][:user]
|
2216
|
+
destination[:type] = :file
|
2217
|
+
destination[:user] = tpkgfile[:crontab][:user]
|
2218
|
+
else
|
2219
|
+
if os.cron_dot_d_directory
|
2220
|
+
destination[:type] = :link
|
2221
|
+
destination[:path] = File.join(os.cron_dot_d_directory, File.basename(installed_path))
|
2222
|
+
else
|
2223
|
+
warn "No cron.d-style crontab support for #{os}"
|
2224
|
+
end
|
2225
|
+
end
|
2226
|
+
destination
|
2227
|
+
end
|
2619
2228
|
|
2620
2229
|
def run_external(pkgfile, operation, name, data)
|
2621
2230
|
externalpath = File.join(@external_directory, name)
|
@@ -2938,70 +2547,74 @@ class Tpkg
|
|
2938
2547
|
end
|
2939
2548
|
|
2940
2549
|
def install_init_scripts(metadata)
|
2941
|
-
init_links(metadata).each do |link,
|
2942
|
-
|
2943
|
-
|
2944
|
-
|
2945
|
-
|
2550
|
+
init_links(metadata).each do |link, installed_path|
|
2551
|
+
install_init_script(metadata, link, installed_path)
|
2552
|
+
end
|
2553
|
+
end
|
2554
|
+
def install_init_script(metadata, link, installed_path)
|
2555
|
+
# We don't have to do anything if there's already symlink to our init
|
2556
|
+
# script. This can happen if the user removes a package manually without
|
2557
|
+
# removing the init symlink
|
2558
|
+
return if File.symlink?(link) && File.readlink(link) == installed_path
|
2559
|
+
begin
|
2560
|
+
FileUtils.mkdir_p(File.dirname(link))
|
2946
2561
|
begin
|
2947
|
-
|
2948
|
-
|
2949
|
-
|
2950
|
-
|
2951
|
-
|
2952
|
-
|
2953
|
-
|
2954
|
-
|
2955
|
-
|
2956
|
-
|
2957
|
-
|
2958
|
-
|
2959
|
-
|
2960
|
-
begin
|
2961
|
-
File.symlink(init_script, link + i.to_s)
|
2962
|
-
throw :init_link_done
|
2963
|
-
rescue Errno::EEXIST
|
2964
|
-
end
|
2562
|
+
File.symlink(installed_path, link)
|
2563
|
+
rescue Errno::EEXIST
|
2564
|
+
# The link name that init_links provides is not guaranteed to
|
2565
|
+
# be unique. It might collide with a base system init script
|
2566
|
+
# or an init script from another tpkg. If the link name
|
2567
|
+
# supplied by init_links results in EEXIST then try appending
|
2568
|
+
# a number to the end of the link name.
|
2569
|
+
catch :init_link_done do
|
2570
|
+
1.upto(9) do |i|
|
2571
|
+
begin
|
2572
|
+
File.symlink(installed_path, link + i.to_s)
|
2573
|
+
throw :init_link_done
|
2574
|
+
rescue Errno::EEXIST
|
2965
2575
|
end
|
2966
|
-
# If we get here (i.e. we never reached the throw) then we
|
2967
|
-
# failed to create any of the possible link names.
|
2968
|
-
raise "Failed to install init script #{init_script} -> #{link} for #{File.basename(metadata[:filename].to_s)}, too many overlapping filenames"
|
2969
2576
|
end
|
2970
|
-
|
2971
|
-
|
2972
|
-
|
2973
|
-
|
2974
|
-
|
2975
|
-
|
2976
|
-
|
2977
|
-
|
2978
|
-
|
2979
|
-
|
2980
|
-
|
2577
|
+
# If we get here (i.e. we never reached the throw) then we
|
2578
|
+
# failed to create any of the possible link names.
|
2579
|
+
raise "Failed to install init script #{installed_path} -> #{link} for #{File.basename(metadata[:filename].to_s)}, too many overlapping filenames"
|
2580
|
+
end
|
2581
|
+
end
|
2582
|
+
# EACCES for file/directory permissions issues
|
2583
|
+
rescue Errno::EACCES => e
|
2584
|
+
# If creating the link fails due to permission problems and
|
2585
|
+
# we're not running as root just warn the user, allowing folks
|
2586
|
+
# to run tpkg as a non-root user with reduced functionality.
|
2587
|
+
if Process.euid != 0
|
2588
|
+
warn "Failed to install init script for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
2589
|
+
else
|
2590
|
+
raise e
|
2981
2591
|
end
|
2982
2592
|
end
|
2983
2593
|
end
|
2984
2594
|
def remove_init_scripts(metadata)
|
2985
|
-
init_links(metadata).each do |link,
|
2986
|
-
|
2987
|
-
|
2988
|
-
|
2989
|
-
|
2990
|
-
|
2991
|
-
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
2995
|
-
|
2996
|
-
|
2997
|
-
|
2998
|
-
|
2999
|
-
|
3000
|
-
|
3001
|
-
|
3002
|
-
|
3003
|
-
|
3004
|
-
|
2595
|
+
init_links(metadata).each do |link, installed_path|
|
2596
|
+
remove_init_script(metadata, link, installed_path)
|
2597
|
+
end
|
2598
|
+
end
|
2599
|
+
def remove_init_script(metadata, link, installed_path)
|
2600
|
+
# The link we ended up making when we unpacked the package could be any
|
2601
|
+
# of a series (see the code in install_init_scripts for the reasoning),
|
2602
|
+
# we need to check them all.
|
2603
|
+
links = [link]
|
2604
|
+
links.concat((1..9).to_a.map { |i| link + i.to_s })
|
2605
|
+
links.each do |l|
|
2606
|
+
if File.symlink?(l) && File.readlink(l) == installed_path
|
2607
|
+
begin
|
2608
|
+
File.delete(l)
|
2609
|
+
# EACCES for file/directory permissions issues
|
2610
|
+
rescue Errno::EACCES => e
|
2611
|
+
# If removing the link fails due to permission problems and
|
2612
|
+
# we're not running as root just warn the user, allowing folks
|
2613
|
+
# to run tpkg as a non-root user with reduced functionality.
|
2614
|
+
if Process.euid != 0
|
2615
|
+
warn "Failed to remove init script for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
2616
|
+
else
|
2617
|
+
raise e
|
3005
2618
|
end
|
3006
2619
|
end
|
3007
2620
|
end
|
@@ -3010,220 +2623,131 @@ class Tpkg
|
|
3010
2623
|
|
3011
2624
|
def install_crontabs(metadata)
|
3012
2625
|
crontab_destinations(metadata).each do |crontab, destination|
|
3013
|
-
|
3014
|
-
|
3015
|
-
|
3016
|
-
|
3017
|
-
install_crontab_bycmd(metadata, crontab, destination)
|
3018
|
-
next
|
3019
|
-
end
|
3020
|
-
|
3021
|
-
begin
|
3022
|
-
if destination[:link]
|
3023
|
-
install_crontab_link(metadata, crontab, destination)
|
3024
|
-
elsif destination[:file]
|
3025
|
-
install_crontab_file(metadata, crontab, destination)
|
3026
|
-
end
|
3027
|
-
# EACCES for file/directory permissions issues
|
3028
|
-
rescue Errno::EACCES => e
|
3029
|
-
# If installing the crontab fails due to permission problems and
|
3030
|
-
# we're not running as root just warn the user, allowing folks
|
3031
|
-
# to run tpkg as a non-root user with reduced functionality.
|
3032
|
-
if Process.euid != 0
|
3033
|
-
warn "Failed to install crontab for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
3034
|
-
else
|
3035
|
-
raise e
|
3036
|
-
end
|
3037
|
-
rescue RuntimeError => e
|
3038
|
-
if e.message.include?('cannot generate tempfile') && Process.euid != 0
|
3039
|
-
warn "Failed to install crontab for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
3040
|
-
else
|
3041
|
-
raise e
|
3042
|
-
end
|
2626
|
+
if destination[:type] == :link
|
2627
|
+
install_crontab_link(metadata, crontab, destination[:path])
|
2628
|
+
elsif destination[:type] == :file
|
2629
|
+
install_crontab_file(metadata, crontab, destination[:user])
|
3043
2630
|
end
|
3044
2631
|
end
|
3045
2632
|
end
|
3046
2633
|
def install_crontab_link(metadata, crontab, destination)
|
3047
|
-
return if File.symlink?(destination
|
3048
|
-
if !File.exist?(File.dirname(destination[:link]))
|
3049
|
-
FileUtils.mkdir_p(File.dirname(destination[:link]))
|
3050
|
-
end
|
2634
|
+
return if (File.symlink?(destination) && File.readlink(destination) == crontab)
|
3051
2635
|
begin
|
3052
|
-
File.
|
3053
|
-
|
3054
|
-
|
3055
|
-
|
3056
|
-
|
3057
|
-
|
3058
|
-
|
3059
|
-
|
3060
|
-
|
3061
|
-
|
3062
|
-
|
3063
|
-
|
3064
|
-
|
3065
|
-
|
2636
|
+
FileUtils.mkdir_p(File.dirname(destination))
|
2637
|
+
begin
|
2638
|
+
File.symlink(crontab, destination)
|
2639
|
+
rescue Errno::EEXIST
|
2640
|
+
# The link name that crontab_destinations provides is not
|
2641
|
+
# guaranteed to be unique. It might collide with a base
|
2642
|
+
# system crontab or a crontab from another tpkg. If the
|
2643
|
+
# link name supplied by crontab_destinations results in
|
2644
|
+
# EEXIST then try appending a number to the end of the link
|
2645
|
+
# name.
|
2646
|
+
catch :crontab_link_done do
|
2647
|
+
1.upto(9) do |i|
|
2648
|
+
begin
|
2649
|
+
File.symlink(crontab, destination + i.to_s)
|
2650
|
+
throw :crontab_link_done
|
2651
|
+
rescue Errno::EEXIST
|
2652
|
+
end
|
3066
2653
|
end
|
2654
|
+
# If we get here (i.e. we never reached the throw) then we
|
2655
|
+
# failed to create any of the possible link names.
|
2656
|
+
raise "Failed to install crontab #{crontab} -> #{destination} for #{File.basename(metadata[:filename].to_s)}, too many overlapping filenames"
|
3067
2657
|
end
|
3068
|
-
|
3069
|
-
|
3070
|
-
|
2658
|
+
end
|
2659
|
+
rescue Errno::EACCES => e
|
2660
|
+
# If installing the crontab fails due to permission problems and
|
2661
|
+
# we're not running as root just warn the user, allowing folks
|
2662
|
+
# to run tpkg as a non-root user with reduced functionality.
|
2663
|
+
if Process.euid != 0
|
2664
|
+
warn "Failed to install crontab for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
2665
|
+
else
|
2666
|
+
raise e
|
3071
2667
|
end
|
3072
2668
|
end
|
3073
2669
|
end
|
3074
|
-
|
3075
|
-
|
3076
|
-
if
|
3077
|
-
|
3078
|
-
|
3079
|
-
|
3080
|
-
|
3081
|
-
|
3082
|
-
|
3083
|
-
|
3084
|
-
|
3085
|
-
File.chown(st.uid, st.gid, tmpfile.path)
|
3086
|
-
# EPERM for attempts to chown/chmod as non-root user
|
3087
|
-
rescue Errno::EPERM => e
|
3088
|
-
# If installing the crontab fails due to permission problems and
|
3089
|
-
# we're not running as root just warn the user, allowing folks
|
3090
|
-
# to run tpkg as a non-root user with reduced functionality.
|
3091
|
-
if Process.euid != 0
|
3092
|
-
warn "Failed to install crontab for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
3093
|
-
else
|
3094
|
-
raise e
|
3095
|
-
end
|
3096
|
-
rescue Errno::EINVAL
|
3097
|
-
raise if RUBY_PLATFORM != 'i386-cygwin'
|
2670
|
+
def crontab_uoption(user)
|
2671
|
+
# The crontab command generally seems unwilling to let you specify the -u
|
2672
|
+
# option, even for your own username, if you aren't root. So if the user
|
2673
|
+
# requested is the same as the current user omit the option.
|
2674
|
+
uoption = nil
|
2675
|
+
if user == 'ANY' || user == Etc.getpwuid.name
|
2676
|
+
uoption = ''
|
2677
|
+
else
|
2678
|
+
uoption = "-u #{user}"
|
2679
|
+
if Process.uid != 0
|
2680
|
+
warn "Package requests user #{user} for crontab, likely to fail due to lack of root privileges"
|
3098
2681
|
end
|
3099
|
-
# Insert the contents of the current crontab file
|
3100
|
-
File.open(destination[:file]) { |file| tmpfile.write(file.read) }
|
3101
2682
|
end
|
3102
|
-
|
3103
|
-
tmpfile.puts "### TPKG START - #{@base} - #{File.basename(metadata[:filename].to_s)}"
|
3104
|
-
# Insert the package crontab contents
|
3105
|
-
crontab_contents = IO.read(crontab)
|
3106
|
-
tmpfile.write(crontab_contents)
|
3107
|
-
# Insert a newline if the crontab doesn't end with one
|
3108
|
-
if crontab_contents.chomp == crontab_contents
|
3109
|
-
tmpfile.puts
|
3110
|
-
end
|
3111
|
-
# Insert a footer line
|
3112
|
-
tmpfile.puts "### TPKG END - #{@base} - #{File.basename(metadata[:filename].to_s)}"
|
3113
|
-
tmpfile.close
|
3114
|
-
File.rename(tmpfile.path, destination[:file])
|
3115
|
-
# FIXME: On Solaris we should bounce cron or use the crontab
|
3116
|
-
# command, otherwise cron won't pick up the changes
|
2683
|
+
uoption
|
3117
2684
|
end
|
3118
|
-
def
|
3119
|
-
|
3120
|
-
|
3121
|
-
|
3122
|
-
|
3123
|
-
|
3124
|
-
|
3125
|
-
|
3126
|
-
|
3127
|
-
|
3128
|
-
|
2685
|
+
def install_crontab_file(metadata, crontab, user)
|
2686
|
+
uoption = crontab_uoption(user)
|
2687
|
+
tf = Tempfile.new('tpkg_crontab')
|
2688
|
+
oldcron = `#{@cmd_crontab} #{uoption} -l`
|
2689
|
+
tf.write(oldcron)
|
2690
|
+
tf.write("\n") if (oldcron.chomp == oldcron)
|
2691
|
+
# Insert a header line so we can find this section to remove later
|
2692
|
+
tf.puts "### TPKG START - #{@base} - #{File.basename(metadata[:filename].to_s)}"
|
2693
|
+
newcron = File.read(crontab)
|
2694
|
+
tf.write(newcron)
|
2695
|
+
tf.write("\n") if (newcron.chomp == newcron)
|
2696
|
+
tf.puts "### TPKG END - #{@base} - #{File.basename(metadata[:filename].to_s)}"
|
2697
|
+
tf.close
|
2698
|
+
system("#{@cmd_crontab} #{uoption} #{tf.path}")
|
2699
|
+
tf.close!
|
3129
2700
|
end
|
3130
2701
|
def remove_crontabs(metadata)
|
3131
2702
|
crontab_destinations(metadata).each do |crontab, destination|
|
3132
|
-
|
3133
|
-
|
3134
|
-
|
3135
|
-
|
3136
|
-
remove_crontab_bycmd(metadata, crontab, destination)
|
3137
|
-
next
|
3138
|
-
end
|
3139
|
-
|
3140
|
-
begin
|
3141
|
-
if destination[:link]
|
3142
|
-
remove_crontab_link(metadata, crontab, destination)
|
3143
|
-
elsif destination[:file]
|
3144
|
-
remove_crontab_file(metadata, crontab, destination)
|
3145
|
-
end
|
3146
|
-
# EACCES for file/directory permissions issues
|
3147
|
-
rescue Errno::EACCES => e
|
3148
|
-
# If removing the crontab fails due to permission problems and
|
3149
|
-
# we're not running as root just warn the user, allowing folks
|
3150
|
-
# to run tpkg as a non-root user with reduced functionality.
|
3151
|
-
if Process.euid != 0
|
3152
|
-
warn "Failed to remove crontab for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
3153
|
-
else
|
3154
|
-
raise e
|
3155
|
-
end
|
2703
|
+
if destination[:type] == :link
|
2704
|
+
remove_crontab_link(metadata, crontab, destination[:path])
|
2705
|
+
elsif destination[:type] == :file
|
2706
|
+
remove_crontab_file(metadata, destination[:user])
|
3156
2707
|
end
|
3157
2708
|
end
|
3158
2709
|
end
|
3159
2710
|
def remove_crontab_link(metadata, crontab, destination)
|
3160
|
-
|
3161
|
-
|
3162
|
-
|
3163
|
-
|
3164
|
-
|
3165
|
-
|
3166
|
-
|
3167
|
-
File.
|
3168
|
-
|
3169
|
-
end
|
3170
|
-
end
|
3171
|
-
# FIXME: Can this be replaced by remove_crontab_bycmd?
|
3172
|
-
def remove_crontab_file(metadata, crontab, destination)
|
3173
|
-
if File.exist?(destination[:file])
|
3174
|
-
tmpfile = Tempfile.new(File.basename(destination[:file]), File.dirname(destination[:file]))
|
3175
|
-
# Match permissions and ownership of current crontab
|
3176
|
-
st = File.stat(destination[:file])
|
3177
|
-
begin
|
3178
|
-
File.chmod(st.mode & 07777, tmpfile.path)
|
3179
|
-
File.chown(st.uid, st.gid, tmpfile.path)
|
3180
|
-
# EPERM for attempts to chown/chmod as non-root user
|
3181
|
-
rescue Errno::EPERM => e
|
3182
|
-
# If installing the crontab fails due to permission problems and
|
3183
|
-
# we're not running as root just warn the user, allowing folks
|
3184
|
-
# to run tpkg as a non-root user with reduced functionality.
|
3185
|
-
if Process.euid != 0
|
3186
|
-
warn "Failed to install crontab for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
3187
|
-
else
|
3188
|
-
raise
|
2711
|
+
begin
|
2712
|
+
# The link we ended up making when we unpacked the package could
|
2713
|
+
# be any of a series (see the code in unpack for the reasoning),
|
2714
|
+
# we need to check them all.
|
2715
|
+
links = [destination]
|
2716
|
+
links.concat((1..9).to_a.map { |i| destination + i.to_s })
|
2717
|
+
links.each do |l|
|
2718
|
+
if File.symlink?(l) && File.readlink(l) == crontab
|
2719
|
+
File.delete(l)
|
3189
2720
|
end
|
3190
|
-
rescue Errno::EINVAL
|
3191
|
-
raise if RUBY_PLATFORM != 'i386-cygwin'
|
3192
2721
|
end
|
3193
|
-
|
3194
|
-
|
3195
|
-
|
3196
|
-
|
3197
|
-
|
3198
|
-
|
3199
|
-
|
3200
|
-
|
3201
|
-
tmpfile.write(line)
|
3202
|
-
end
|
2722
|
+
rescue Errno::EACCES => e
|
2723
|
+
# If removing the crontab fails due to permission problems and
|
2724
|
+
# we're not running as root just warn the user, allowing folks
|
2725
|
+
# to run tpkg as a non-root user with reduced functionality.
|
2726
|
+
if Process.euid != 0
|
2727
|
+
warn "Failed to remove crontab for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
|
2728
|
+
else
|
2729
|
+
raise e
|
3203
2730
|
end
|
3204
|
-
tmpfile.close
|
3205
|
-
File.rename(tmpfile.path, destination[:file])
|
3206
|
-
# FIXME: On Solaris we should bounce cron or use the crontab
|
3207
|
-
# command, otherwise cron won't pick up the changes
|
3208
2731
|
end
|
3209
2732
|
end
|
3210
|
-
def
|
3211
|
-
|
3212
|
-
|
3213
|
-
|
2733
|
+
def remove_crontab_file(metadata, user)
|
2734
|
+
uoption = crontab_uoption(user)
|
2735
|
+
oldcron = `#{@cmd_crontab} #{uoption} -l`
|
2736
|
+
tf = Tempfile.new('tpkg_crontab')
|
2737
|
+
# Remove section associated with this package
|
3214
2738
|
skip = false
|
3215
|
-
oldcron.each do |line|
|
2739
|
+
oldcron.lines.each do |line|
|
3216
2740
|
if line == "### TPKG START - #{@base} - #{File.basename(metadata[:filename].to_s)}\n"
|
3217
2741
|
skip = true
|
3218
2742
|
elsif line == "### TPKG END - #{@base} - #{File.basename(metadata[:filename].to_s)}\n"
|
3219
2743
|
skip = false
|
3220
2744
|
elsif !skip
|
3221
|
-
|
2745
|
+
tf.write(line)
|
3222
2746
|
end
|
3223
2747
|
end
|
3224
|
-
|
3225
|
-
|
3226
|
-
|
2748
|
+
tf.close
|
2749
|
+
system("#{@cmd_crontab} #{uoption} #{tf.path}")
|
2750
|
+
tf.close!
|
3227
2751
|
end
|
3228
2752
|
|
3229
2753
|
def run_preinstall(package_file, workdir)
|
@@ -3513,7 +3037,7 @@ class Tpkg
|
|
3513
3037
|
req = { :name => metadata[:name], :type => :tpkg }
|
3514
3038
|
# Quick sanity check that the package can be installed on this machine.
|
3515
3039
|
puts "check_requests checking that available package for request works on this machine: #{pkg.inspect}" if @@debug
|
3516
|
-
if !
|
3040
|
+
if !package_meets_requirement?(pkg, req)
|
3517
3041
|
possible_errors << " Requested package #{metadata[:filename]} doesn't match this machine's OS or architecture"
|
3518
3042
|
good_package = false
|
3519
3043
|
next
|
@@ -3522,7 +3046,7 @@ class Tpkg
|
|
3522
3046
|
# available for each dependency of this package
|
3523
3047
|
metadata[:dependencies].each do |depreq|
|
3524
3048
|
puts "check_requests checking for available packages to satisfy dependency: #{depreq.inspect}" if @@debug
|
3525
|
-
if available_packages_that_meet_requirement(depreq).empty? && !
|
3049
|
+
if available_packages_that_meet_requirement(depreq).empty? && !packages_meet_requirement?(packages.values.flatten, depreq)
|
3526
3050
|
possible_errors << " Requested package #{metadata[:filename]} depends on #{depreq.inspect}, no packages that satisfy that dependency are available"
|
3527
3051
|
good_package = false
|
3528
3052
|
end
|
@@ -3603,7 +3127,7 @@ class Tpkg
|
|
3603
3127
|
next if pkg1[:metadata][:conflicts].nil?
|
3604
3128
|
pkg1[:metadata][:conflicts].each do | conflict |
|
3605
3129
|
pkgs_to_install.each do |pkg2|
|
3606
|
-
if
|
3130
|
+
if package_meets_requirement?(pkg2, conflict)
|
3607
3131
|
conflicting_pkgs << pkg1
|
3608
3132
|
end
|
3609
3133
|
end
|
@@ -3625,7 +3149,7 @@ class Tpkg
|
|
3625
3149
|
next if pkg1[:metadata][:conflicts].nil?
|
3626
3150
|
pkg1[:metadata][:conflicts].each do | conflict |
|
3627
3151
|
pkgs_to_install.each do |pkg2|
|
3628
|
-
if
|
3152
|
+
if package_meets_requirement?(pkg2, conflict)
|
3629
3153
|
raise "Package conflicts between #{pkg2[:metadata][:filename]} and #{pkg1[:metadata][:filename]}"
|
3630
3154
|
end
|
3631
3155
|
end
|
@@ -3689,20 +3213,8 @@ class Tpkg
|
|
3689
3213
|
puts "The following packages will be #{promptstring}:"
|
3690
3214
|
pkgs_to_report.sort(&SORT_PACKAGES).each do |pkg|
|
3691
3215
|
if pkg[:source] == :native_available
|
3692
|
-
|
3693
|
-
|
3694
|
-
package_version = pkg[:metadata][:package_version]
|
3695
|
-
pkgname = "#{name}"
|
3696
|
-
if Tpkg::get_os =~ /Debian|Ubuntu/
|
3697
|
-
pkgname << "=#{version}"
|
3698
|
-
else
|
3699
|
-
pkgname <<"-#{version}"
|
3700
|
-
end
|
3701
|
-
if package_version
|
3702
|
-
pkgname << "-#{package_version}"
|
3703
|
-
end
|
3704
|
-
puts "Native #{pkgname}"
|
3705
|
-
else
|
3216
|
+
puts "Native #{os.native_pkg_to_install_string(pkg)}"
|
3217
|
+
else
|
3706
3218
|
puts pkg[:metadata][:filename]
|
3707
3219
|
end
|
3708
3220
|
end
|
@@ -3770,67 +3282,7 @@ class Tpkg
|
|
3770
3282
|
# Nothing to do for packages currently installed
|
3771
3283
|
warn "Skipping #{pkg[:metadata][:name]}, already installed"
|
3772
3284
|
elsif pkg[:source] == :native_available
|
3773
|
-
|
3774
|
-
name = pkg[:metadata][:name]
|
3775
|
-
version = pkg[:metadata][:version]
|
3776
|
-
package_version = pkg[:metadata][:package_version]
|
3777
|
-
# RPMs always have a release/package_version
|
3778
|
-
pkgname = "#{name}-#{version}-#{package_version}"
|
3779
|
-
puts "Running 'yum -y install #{pkgname}' to install native package" if @@debug
|
3780
|
-
system("yum -y install #{pkgname}")
|
3781
|
-
elsif Tpkg::get_os =~ /Debian|Ubuntu/
|
3782
|
-
name = pkg[:metadata][:name]
|
3783
|
-
version = pkg[:metadata][:version]
|
3784
|
-
pkgname = "#{name}=#{version}"
|
3785
|
-
if pkg[:metadata][:package_version]
|
3786
|
-
pkgname << "-#{pkg[:metadata][:package_version]}"
|
3787
|
-
end
|
3788
|
-
puts "Running 'apt-get -y install #{pkgname}' to install native package" if @@debug
|
3789
|
-
system("apt-get -y install #{pkgname}")
|
3790
|
-
elsif Tpkg::get_os =~ /Solaris/
|
3791
|
-
name = pkg[:metadata][:name]
|
3792
|
-
version = pkg[:metadata][:version]
|
3793
|
-
pkgname = "#{name}-#{version}"
|
3794
|
-
if pkg[:metadata][:package_version]
|
3795
|
-
pkgname << ",REV=#{pkg[:metadata][:package_version]}"
|
3796
|
-
end
|
3797
|
-
if File.exist?('/opt/csw/bin/pkg-get')
|
3798
|
-
puts "Running '/opt/csw/bin/pkg-get -i #{pkgname}' to install native package" if @@debug
|
3799
|
-
system("/opt/csw/bin/pkg-get -i #{pkgname}")
|
3800
|
-
else
|
3801
|
-
raise "No native package installation tool available"
|
3802
|
-
end
|
3803
|
-
elsif Tpkg::get_os =~ /FreeBSD/
|
3804
|
-
name = pkg[:metadata][:name]
|
3805
|
-
version = pkg[:metadata][:version]
|
3806
|
-
pkgname = "#{name}-#{version}"
|
3807
|
-
if pkg[:metadata][:package_version]
|
3808
|
-
pkgname << "_#{pkg[:metadata][:package_version]}"
|
3809
|
-
end
|
3810
|
-
puts "Running 'pkg_add -r #{pkgname}' to install native package" if @@debug
|
3811
|
-
system("pkg_add -r #{pkgname}")
|
3812
|
-
elsif Tpkg::get_os =~ /Darwin/
|
3813
|
-
if File.exist?('/opt/local/bin/port')
|
3814
|
-
name = pkg[:metadata][:name]
|
3815
|
-
# MacPorts doesn't support installing a specific version (AFAIK)
|
3816
|
-
if pkg[:metadata][:version]
|
3817
|
-
warn "Ignoring version with MacPorts"
|
3818
|
-
end
|
3819
|
-
# Nor does it have a concept of a package version
|
3820
|
-
if pkg[:metadata][:package_version]
|
3821
|
-
warn "Ignoring package version with MacPorts"
|
3822
|
-
end
|
3823
|
-
# Just for consistency with the code for other platforms
|
3824
|
-
pkgname = name
|
3825
|
-
puts "Running '/opt/local/bin/port install #{pkgname}' to install native package" if @@debug
|
3826
|
-
system("/opt/local/bin/port install #{pkgname}")
|
3827
|
-
else
|
3828
|
-
# Fink, Homebrew support would be nice
|
3829
|
-
raise "No supported native package tool available on #{Tpkg::get_os}"
|
3830
|
-
end
|
3831
|
-
else
|
3832
|
-
raise "No native package installation support for #{Tpkg::get_os}"
|
3833
|
-
end
|
3285
|
+
os.install_native_package(pkg)
|
3834
3286
|
else # regular tpkg that needs to be installed
|
3835
3287
|
pkgfile = nil
|
3836
3288
|
if File.file?(pkg[:source])
|
@@ -3846,8 +3298,7 @@ class Tpkg
|
|
3846
3298
|
else
|
3847
3299
|
if prompt_for_conflicting_files(pkgfile)
|
3848
3300
|
ret_val |= unpack(pkgfile, :passphrase => passphrase)
|
3849
|
-
|
3850
|
-
stub_native_pkg(pkg)
|
3301
|
+
os.stub_native_pkg(pkg)
|
3851
3302
|
end
|
3852
3303
|
end
|
3853
3304
|
end
|
@@ -3980,79 +3431,9 @@ class Tpkg
|
|
3980
3431
|
pkg[:source] == :native_installed
|
3981
3432
|
# Nothing to do for packages currently installed
|
3982
3433
|
elsif pkg[:source] == :native_available
|
3983
|
-
|
3984
|
-
|
3985
|
-
|
3986
|
-
package_version = pkg[:metadata][:package_version]
|
3987
|
-
# RPMs always have a release/package_version
|
3988
|
-
pkgname = "#{name}-#{version}-#{package_version}"
|
3989
|
-
puts "Running 'yum -y install #{pkgname}' to upgrade native package" if @@debug
|
3990
|
-
system("yum -y install #{pkgname}")
|
3991
|
-
has_updates = true
|
3992
|
-
elsif Tpkg::get_os =~ /Debian|Ubuntu/
|
3993
|
-
name = pkg[:metadata][:name]
|
3994
|
-
version = pkg[:metadata][:version]
|
3995
|
-
pkgname = "#{name}=#{version}"
|
3996
|
-
if pkg[:metadata][:package_version]
|
3997
|
-
pkgname << "-#{pkg[:metadata][:package_version]}"
|
3998
|
-
end
|
3999
|
-
puts "Running 'apt-get -y install #{pkgname}' to upgrade native package" if @@debug
|
4000
|
-
system("apt-get -y install #{pkgname}")
|
4001
|
-
has_updates = true
|
4002
|
-
elsif Tpkg::get_os =~ /Solaris/
|
4003
|
-
name = pkg[:metadata][:name]
|
4004
|
-
version = pkg[:metadata][:version]
|
4005
|
-
pkgname = "#{name}-#{version}"
|
4006
|
-
if pkg[:metadata][:package_version]
|
4007
|
-
pkgname << ",REV=#{pkg[:metadata][:package_version]}"
|
4008
|
-
end
|
4009
|
-
if File.exist?('/opt/csw/bin/pkg-get')
|
4010
|
-
puts "Running '/opt/csw/bin/pkg-get -i #{pkgname}' to upgrade native package" if @@debug
|
4011
|
-
system("/opt/csw/bin/pkg-get -i #{pkgname}")
|
4012
|
-
has_updates = true
|
4013
|
-
else
|
4014
|
-
raise "No native package upgrade tool available"
|
4015
|
-
end
|
4016
|
-
elsif Tpkg::get_os =~ /FreeBSD/
|
4017
|
-
name = pkg[:metadata][:name]
|
4018
|
-
version = pkg[:metadata][:version]
|
4019
|
-
pkgname = "#{name}-#{version}"
|
4020
|
-
if pkg[:metadata][:package_version]
|
4021
|
-
pkgname << "_#{pkg[:metadata][:package_version]}"
|
4022
|
-
end
|
4023
|
-
# This is not very ideal. It would be better to download the
|
4024
|
-
# new package, and if the download is successful remove the
|
4025
|
-
# old package and install the new one. The way we're doing it
|
4026
|
-
# here we risk leaving the system with neither version
|
4027
|
-
# installed if the download of the new package fails.
|
4028
|
-
# However, the FreeBSD package tools don't make it easy to
|
4029
|
-
# handle things properly.
|
4030
|
-
puts "Running 'pkg_delete #{name}' and 'pkg_add -r #{pkgname}' to upgrade native package" if @@debug
|
4031
|
-
system("pkg_delete #{name}")
|
4032
|
-
system("pkg_add -r #{pkgname}")
|
4033
|
-
has_updates = true
|
4034
|
-
elsif Tpkg::get_os =~ /Darwin/
|
4035
|
-
if File.exist?('/opt/local/bin/port')
|
4036
|
-
name = pkg[:metadata][:name]
|
4037
|
-
# MacPorts doesn't support installing a specific version (AFAIK)
|
4038
|
-
if pkg[:metadata][:version]
|
4039
|
-
warn "Ignoring version with MacPorts"
|
4040
|
-
end
|
4041
|
-
# Nor does it have a concept of a package version
|
4042
|
-
if pkg[:metadata][:package_version]
|
4043
|
-
warn "Ignoring package version with MacPorts"
|
4044
|
-
end
|
4045
|
-
# Just for consistency with the code for other platforms
|
4046
|
-
pkgname = name
|
4047
|
-
puts "Running '/opt/local/bin/port upgrade #{pkgname}' to upgrade native package" if @@debug
|
4048
|
-
system("/opt/local/bin/port upgrade #{pkgname}")
|
4049
|
-
else
|
4050
|
-
# Fink support would be nice
|
4051
|
-
raise "No supported native package tool available on #{Tpkg::get_os}"
|
4052
|
-
end
|
4053
|
-
else
|
4054
|
-
raise "No native package upgrade support for #{Tpkg::get_os}"
|
4055
|
-
end
|
3434
|
+
os.upgrade_native_package(pkg)
|
3435
|
+
has_updates = true
|
3436
|
+
@available_native_packages.delete(pkg[:metadata][:name]) # to have the status of this native package reloaded
|
4056
3437
|
else # tpkg
|
4057
3438
|
pkgfile = nil
|
4058
3439
|
if File.file?(pkg[:source])
|
@@ -4101,8 +3482,7 @@ class Tpkg
|
|
4101
3482
|
is_doing_upgrade = true if removed_pkgs.include?(pkg[:metadata][:name])
|
4102
3483
|
ret_val |= unpack(pkgfile, :passphrase => passphrase, :externals_to_skip => externals_to_skip,
|
4103
3484
|
:is_doing_upgrade => is_doing_upgrade)
|
4104
|
-
|
4105
|
-
stub_native_pkg(pkg)
|
3485
|
+
os.stub_native_pkg(pkg)
|
4106
3486
|
end
|
4107
3487
|
has_updates = true
|
4108
3488
|
end
|
@@ -4312,7 +3692,7 @@ class Tpkg
|
|
4312
3692
|
# don't remove conf files that have been modified
|
4313
3693
|
next if modified_conf_files.include?(file)
|
4314
3694
|
begin
|
4315
|
-
if !File.directory?(file)
|
3695
|
+
if File.symlink?(file) || !File.directory?(file)
|
4316
3696
|
File.delete(file)
|
4317
3697
|
else
|
4318
3698
|
begin
|
@@ -4364,8 +3744,7 @@ class Tpkg
|
|
4364
3744
|
package_metadata_dir = File.join(@metadata_directory, File.basename(package_file, File.extname(package_file)))
|
4365
3745
|
FileUtils.rm_rf(package_metadata_dir)
|
4366
3746
|
|
4367
|
-
|
4368
|
-
remove_native_stub_pkg(pkg)
|
3747
|
+
os.remove_native_stub_pkg(pkg)
|
4369
3748
|
|
4370
3749
|
# Cleanup
|
4371
3750
|
FileUtils.rm_rf(workdir)
|
@@ -4692,15 +4071,8 @@ class Tpkg
|
|
4692
4071
|
# Packages are downloaded into the current directory or into the directory
|
4693
4072
|
# specified in options[:out]
|
4694
4073
|
def download_pkgs(requests, options={})
|
4695
|
-
if options[:out]
|
4696
|
-
if !File.exists?(options[:out])
|
4697
|
-
FileUtils.mkdir_p(options[:out])
|
4698
|
-
elsif !File.directory?(options[:out])
|
4699
|
-
puts "#{options[:out]} is not a valid directory."
|
4700
|
-
return GENERIC_ERR
|
4701
|
-
end
|
4702
|
-
end
|
4703
4074
|
output_dir = options[:out] || Dir.pwd
|
4075
|
+
FileUtils.mkdir_p(output_dir)
|
4704
4076
|
|
4705
4077
|
requirements = []
|
4706
4078
|
packages = {}
|
@@ -4773,13 +4145,7 @@ class Tpkg
|
|
4773
4145
|
end
|
4774
4146
|
|
4775
4147
|
def send_update_to_server(options={})
|
4776
|
-
|
4777
|
-
fqdn = Facter['fqdn'].value
|
4778
|
-
if fqdn == nil
|
4779
|
-
fqdn = Facter['hostname'].value<<"."<<Facter['domain'].value
|
4780
|
-
end
|
4781
|
-
|
4782
|
-
request = {"client"=>fqdn}
|
4148
|
+
request = {"client"=>os.fqdn}
|
4783
4149
|
request[:user] = Etc.getlogin || Etc.getpwuid(Process.uid).name
|
4784
4150
|
request[:tpkg_home] = ENV['TPKG_HOME']
|
4785
4151
|
|
@@ -4832,101 +4198,4 @@ class Tpkg
|
|
4832
4198
|
puts "Failed to send update to reporter server"
|
4833
4199
|
end
|
4834
4200
|
end
|
4835
|
-
|
4836
|
-
# create and install native stub package if needed
|
4837
|
-
# this stub package helps prevent user from removing native packages that
|
4838
|
-
# our tpkg packages depend on
|
4839
|
-
def stub_native_pkg(pkg)
|
4840
|
-
# gather all of the native dependencies
|
4841
|
-
native_deps = pkg[:metadata].get_native_deps
|
4842
|
-
return if native_deps.empty?
|
4843
|
-
|
4844
|
-
if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
|
4845
|
-
rpm = create_rpm("stub_for_#{pkg[:metadata][:name]}", native_deps)
|
4846
|
-
return if rpm.nil?
|
4847
|
-
|
4848
|
-
# install the rpm
|
4849
|
-
cmd = "rpm -i #{rpm}"
|
4850
|
-
puts cmd if @@debug
|
4851
|
-
system(cmd)
|
4852
|
-
if !$?.success?
|
4853
|
-
warn "Warning: Failed to install native stub package for #{pkg[:metadata][:name]}"
|
4854
|
-
end
|
4855
|
-
else
|
4856
|
-
# TODO: support other OSes
|
4857
|
-
end
|
4858
|
-
end
|
4859
|
-
|
4860
|
-
# remove the native dependency stub packages if there's any
|
4861
|
-
def remove_native_stub_pkg(pkg)
|
4862
|
-
# Don't have to do anything if this package has no native dependencies
|
4863
|
-
native_deps = pkg[:metadata].get_native_deps
|
4864
|
-
return if native_deps.empty?
|
4865
|
-
|
4866
|
-
# the convention is that stub package is named as "stub_for_pkgname"
|
4867
|
-
stub_pkg_name = "stub_for_#{pkg[:metadata][:name]}"
|
4868
|
-
|
4869
|
-
if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
|
4870
|
-
cmd = "yum -y remove #{stub_pkg_name}"
|
4871
|
-
puts cmd if @@debug
|
4872
|
-
system(cmd)
|
4873
|
-
if !$?.success?
|
4874
|
-
warn "Warning: Failed to remove native stub package for #{pkg[:metadata][:name]}"
|
4875
|
-
end
|
4876
|
-
else
|
4877
|
-
# TODO: support other OSes
|
4878
|
-
end
|
4879
|
-
end
|
4880
|
-
|
4881
|
-
def create_rpm(name, deps=[])
|
4882
|
-
# setup directories for rpmbuild
|
4883
|
-
topdir = Tpkg::tempdir('rpmbuild')
|
4884
|
-
%w[BUILD RPMS SOURCES SPECS SRPMS].each do |dir|
|
4885
|
-
FileUtils.mkdir_p(File.join(topdir, dir))
|
4886
|
-
end
|
4887
|
-
|
4888
|
-
dep_list = deps.collect{|dep|dep[:name]}.join(",")
|
4889
|
-
|
4890
|
-
# create rpm spec file
|
4891
|
-
spec = <<-EOS.gsub(/^\s+/, "")
|
4892
|
-
Name: #{name}
|
4893
|
-
Summary: stub pkg created by tpkg
|
4894
|
-
Version: 1
|
4895
|
-
Release: 1
|
4896
|
-
buildarch: noarch
|
4897
|
-
Requires: #{dep_list}
|
4898
|
-
Group: Applications/System
|
4899
|
-
License: MIT
|
4900
|
-
BuildRoot: %{_builddir}/%{name}-buildroot
|
4901
|
-
%description
|
4902
|
-
stub pkg created by tpkg for the following dependencies: #{dep_list}
|
4903
|
-
%files
|
4904
|
-
EOS
|
4905
|
-
spec_file = File.join(topdir, 'SPECS', 'pkg.spec')
|
4906
|
-
File.open(spec_file, 'w') do |file|
|
4907
|
-
file.puts(spec)
|
4908
|
-
end
|
4909
|
-
|
4910
|
-
# run rpmbuild
|
4911
|
-
system("rpmbuild -bb --define '_topdir #{topdir}' #{spec_file}")
|
4912
|
-
if !$?.success?
|
4913
|
-
warn "Warning: Failed to create native stub package for #{name}"
|
4914
|
-
return nil
|
4915
|
-
end
|
4916
|
-
|
4917
|
-
# copy result over to tmpfile
|
4918
|
-
result = File.join(topdir, 'RPMS', 'noarch', "#{name}-1-1.noarch.rpm")
|
4919
|
-
rpm = nil
|
4920
|
-
if File.exists?(result)
|
4921
|
-
tmpfile = Tempfile.new(File.basename(result))
|
4922
|
-
FileUtils.cp(result, tmpfile.path)
|
4923
|
-
rpm = tmpfile.path
|
4924
|
-
end
|
4925
|
-
|
4926
|
-
# cleanup
|
4927
|
-
FileUtils.rm_rf(topdir)
|
4928
|
-
|
4929
|
-
return rpm
|
4930
|
-
end
|
4931
4201
|
end
|
4932
|
-
|