tpkg 2.3.3 → 2.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
|