tpkg 2.3.3 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +20 -0
  5. data/Portfile +39 -0
  6. data/Portfile.template +39 -0
  7. data/README.md +43 -0
  8. data/Rakefile +468 -18
  9. data/bin/gem2tpkg +2 -2
  10. data/bin/tpkg +18 -13
  11. data/bin/tpkg_uploader +132 -0
  12. data/ca.pem +1 -0
  13. data/control +7 -0
  14. data/depend +3 -0
  15. data/externals-etch/authorized_keys +40 -0
  16. data/externals-etch/group +9 -0
  17. data/externals-etch/iptables +38 -0
  18. data/externals-etch/limits +30 -0
  19. data/externals-etch/nfs +30 -0
  20. data/externals-etch/sudo +30 -0
  21. data/externals-etch/supplemental_groups +8 -0
  22. data/externals-etch/sysctl +30 -0
  23. data/externals-etch/user +41 -0
  24. data/externals/group +39 -0
  25. data/externals/supplemental_groups +48 -0
  26. data/externals/user +39 -0
  27. data/lib/tpkg.rb +260 -991
  28. data/lib/tpkg/os.rb +164 -0
  29. data/lib/tpkg/os/debian.rb +159 -0
  30. data/lib/tpkg/os/freebsd.rb +113 -0
  31. data/lib/tpkg/os/macosx.rb +113 -0
  32. data/lib/tpkg/os/redhat.rb +173 -0
  33. data/lib/tpkg/os/solaris.rb +101 -0
  34. data/lib/tpkg/os/windows.rb +26 -0
  35. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify.rb +67 -0
  36. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/errors.rb +127 -0
  37. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/kwalify.schema.yaml +58 -0
  38. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/main.rb +442 -0
  39. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/messages.rb +173 -0
  40. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/meta-validator.rb +275 -0
  41. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/parser/base.rb +127 -0
  42. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/parser/yaml.rb +841 -0
  43. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/rule.rb +559 -0
  44. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/templates/genclass-java.eruby +222 -0
  45. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/templates/genclass-php.eruby +104 -0
  46. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/templates/genclass-ruby.eruby +113 -0
  47. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/types.rb +156 -0
  48. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util.rb +158 -0
  49. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/assert-text-equal.rb +46 -0
  50. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/hash-interface.rb +18 -0
  51. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/hashlike.rb +51 -0
  52. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/option-parser.rb +220 -0
  53. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/ordered-hash.rb +57 -0
  54. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/util/testcase-helper.rb +112 -0
  55. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/validator.rb +282 -0
  56. data/lib/tpkg/thirdparty/kwalify-0.7.2/lib/kwalify/yaml-parser.rb +870 -0
  57. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh.rb +219 -0
  58. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/agent.rb +179 -0
  59. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/constants.rb +18 -0
  60. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/key_manager.rb +219 -0
  61. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/abstract.rb +60 -0
  62. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/hostbased.rb +71 -0
  63. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/keyboard_interactive.rb +66 -0
  64. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/password.rb +39 -0
  65. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/methods/publickey.rb +92 -0
  66. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/pageant.rb +183 -0
  67. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/authentication/session.rb +134 -0
  68. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/buffer.rb +340 -0
  69. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/buffered_io.rb +198 -0
  70. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/config.rb +205 -0
  71. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/connection/channel.rb +630 -0
  72. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/connection/constants.rb +33 -0
  73. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/connection/session.rb +597 -0
  74. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/connection/term.rb +178 -0
  75. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/errors.rb +85 -0
  76. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/key_factory.rb +102 -0
  77. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/known_hosts.rb +129 -0
  78. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/loggable.rb +61 -0
  79. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/packet.rb +102 -0
  80. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/prompt.rb +93 -0
  81. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/command.rb +75 -0
  82. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/errors.rb +14 -0
  83. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/http.rb +94 -0
  84. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/socks4.rb +70 -0
  85. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/proxy/socks5.rb +142 -0
  86. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/ruby_compat.rb +43 -0
  87. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/service/forward.rb +288 -0
  88. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test.rb +89 -0
  89. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/channel.rb +129 -0
  90. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/extensions.rb +152 -0
  91. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/kex.rb +44 -0
  92. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/local_packet.rb +51 -0
  93. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/packet.rb +81 -0
  94. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/remote_packet.rb +38 -0
  95. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/script.rb +157 -0
  96. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/test/socket.rb +64 -0
  97. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/algorithms.rb +384 -0
  98. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/cipher_factory.rb +97 -0
  99. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/constants.rb +30 -0
  100. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac.rb +31 -0
  101. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/abstract.rb +79 -0
  102. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/md5.rb +12 -0
  103. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
  104. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/none.rb +15 -0
  105. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/sha1.rb +13 -0
  106. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
  107. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/identity_cipher.rb +55 -0
  108. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/kex.rb +13 -0
  109. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
  110. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +77 -0
  111. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/openssl.rb +127 -0
  112. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/packet_stream.rb +235 -0
  113. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/server_version.rb +71 -0
  114. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/session.rb +276 -0
  115. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/transport/state.rb +206 -0
  116. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/verifiers/lenient.rb +30 -0
  117. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/verifiers/null.rb +12 -0
  118. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/verifiers/strict.rb +53 -0
  119. data/lib/tpkg/thirdparty/net-ssh-2.1.0/lib/net/ssh/version.rb +62 -0
  120. data/lib/tpkg/version.rb +3 -0
  121. data/man/man1/cpan2tpkg.1 +82 -0
  122. data/man/man1/gem2tpkg.1 +120 -0
  123. data/man/man1/tpkg.1 +411 -0
  124. data/pkginfo +8 -0
  125. data/postinstall.solaris +11 -0
  126. data/postremove.solaris +16 -0
  127. data/schema/schema-1.0.5.yml +0 -0
  128. data/schema/schema-1.0.6.yml +0 -0
  129. data/schema/schema-1.0.7.yml +0 -0
  130. data/schema/schema-1.0.8.yml +0 -0
  131. data/schema/schema-1.0.9.yml +0 -0
  132. data/schema/schema.yml +0 -0
  133. data/schema/tpkg-1.0.0.dtd +0 -0
  134. data/schema/tpkg-1.0.1.dtd +0 -0
  135. data/schema/tpkg-1.0.2.dtd +0 -0
  136. data/schema/tpkg-1.0.3.dtd +0 -0
  137. data/schema/tpkg-1.0.4.dtd +0 -0
  138. data/schema/tpkg-1.0.5.dtd +0 -0
  139. data/schema/tpkg-1.0.6.dtd +0 -0
  140. data/schema/tpkg-1.0.7.dtd +0 -0
  141. data/schema/tpkg-1.0.8.dtd +0 -0
  142. data/schema/tpkg-1.0.9.dtd +0 -0
  143. data/schema/tpkg.dtd +0 -0
  144. data/test/TODO +30 -0
  145. data/test/premadetestpkg/pkg_without_file_metadata-1.0-1.tpkg +0 -0
  146. data/test/test_checksum.rb +53 -0
  147. data/test/test_compress.rb +55 -0
  148. data/test/test_conflict.rb +41 -0
  149. data/test/test_crontabs.rb +398 -0
  150. data/test/test_dependency.rb +1113 -0
  151. data/test/test_downgrade.rb +80 -0
  152. data/test/test_download.rb +95 -0
  153. data/test/test_encrypt.rb +136 -0
  154. data/test/test_filemetadata.rb +131 -0
  155. data/test/test_initscript.rb +93 -0
  156. data/test/test_install.rb +186 -0
  157. data/test/test_lock.rb +82 -0
  158. data/test/test_make.rb +410 -0
  159. data/test/test_metadata.rb +805 -0
  160. data/test/test_misc.rb +379 -0
  161. data/test/test_options.rb +1711 -0
  162. data/test/test_os.rb +193 -0
  163. data/test/test_os_debian.rb +99 -0
  164. data/test/test_os_freebsd.rb +89 -0
  165. data/test/test_os_macosx.rb +79 -0
  166. data/test/test_os_redhat.rb +124 -0
  167. data/test/test_os_solaris.rb +85 -0
  168. data/test/test_os_windows.rb +26 -0
  169. data/test/test_query.rb +134 -0
  170. data/test/test_remove.rb +539 -0
  171. data/test/test_tar.rb +99 -0
  172. data/test/test_unpack.rb +977 -0
  173. data/test/test_upgrade.rb +398 -0
  174. data/test/test_version.rb +54 -0
  175. data/test/testcmds/crontab +14 -0
  176. data/test/testcmds/debian/apt-cache +145 -0
  177. data/test/testcmds/debian/dpkg-query +16 -0
  178. data/test/testcmds/freebsd/pkg_info +13 -0
  179. data/test/testcmds/macosx/port +35 -0
  180. data/test/testcmds/redhat/rpmbuild +6 -0
  181. data/test/testcmds/redhat/yum +90 -0
  182. data/test/testcmds/solaris/pkginfo +25 -0
  183. data/test/testcmds/solaris/pkgutil +36 -0
  184. data/test/testpkg/reloc/encfile +2 -0
  185. data/test/testpkg/reloc/file +2 -0
  186. data/test/testpkg/reloc/precryptfile +1 -0
  187. data/test/testpkg/reloc/precryptfile.plaintext +3 -0
  188. data/test/testpkg/tpkg-bad-ownergroup.xml +25 -0
  189. data/test/testpkg/tpkg-bad-ownergroup.yml +18 -0
  190. data/test/testpkg/tpkg-default-perms.xml +28 -0
  191. data/test/testpkg/tpkg-default-perms.yml +20 -0
  192. data/test/testpkg/tpkg-good-ownergroup.xml +25 -0
  193. data/test/testpkg/tpkg-good-ownergroup.yml +18 -0
  194. data/test/testpkg/tpkg-nativedeps.yml +13 -0
  195. data/test/testpkg/tpkg-nofiles.xml +14 -0
  196. data/test/testpkg/tpkg-nofiles.yml +9 -0
  197. data/test/testpkg/tpkg.xml +35 -0
  198. data/test/testpkg/tpkg.yml +25 -0
  199. data/test/tpkgtest.rb +300 -0
  200. data/tpkg.conf +16 -0
  201. data/tpkg.gemspec +24 -0
  202. data/tpkg.spec +28 -0
  203. data/tpkg.xml +17 -0
  204. data/tpkg_profile.sh +32 -0
  205. 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
+
@@ -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
+
@@ -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
@@ -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
+
@@ -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
- VERSION = '2.3.3'
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 self.packages_meet_requirement?(pkgs, req)
675
+ def packages_meet_requirement?(pkgs, req)
767
676
  pkgs.each do | pkg |
768
- return true if Tpkg::package_meets_requirement?(pkg, req)
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 self.package_meets_requirement?(pkg, req)
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?(get_os) &&
876
- !metadata[:operatingsystem].any?{|os| get_os =~ /#{os}/}
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?(get_arch) &&
884
- !metadata[:architecture].any?{|arch| get_arch =~ /#{arch}/}
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
- @sudo = Tpkg.sudo_default?
1371
- if options.has_key?(:sudo)
1372
- @sudo = options[:sudo]
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 Tpkg::get_os =~ /Darwin/
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
- if !File.exist?(dir)
1421
- begin
1422
- FileUtils.mkdir_p(dir)
1423
- rescue Errno::EACCES
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
- if !File.exist?(localdir)
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 load_available_native_packages to stuff all the info about a
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 load_available_native_packages(pkgname)
1630
- if !@available_native_packages[pkgname]
1631
- native_packages = []
1632
- if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
1633
- [ {:arg => 'installed', :header => 'Installed', :source => :native_installed},
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
- load_available_native_packages(req[:name])
1986
- @available_native_packages[req[:name]].each do |pkg|
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 Tpkg::package_meets_requirement?(pkg, req)
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
- load_available_native_packages(req[:name])
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
- Tpkg::package_meets_requirement?(pkg, req)
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 Tpkg::package_meets_requirement?(pkg, req)
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
- Tpkg::package_meets_requirement?(pkg, req)
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 && Tpkg::package_meets_requirement?(pkg, newreq)
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
- if !File.exist?(localdir)
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
- # SysV-style init
2513
- if Tpkg::get_os =~ /RedHat|CentOS|Fedora/ ||
2514
- Tpkg::get_os =~ /Debian|Ubuntu/ ||
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 where they need to be installed on the system
2562
- def crontab_destinations(metadata)
2563
- destinations = {}
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 destinations
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
- destinations[installed_path] = {}
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, init_script|
2942
- # We don't have to do anything if there's already symlink to our init
2943
- # script. This can happen if the user removes a package manually without
2944
- # removing the init symlink
2945
- next if File.symlink?(link) && File.readlink(link) == init_script
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
- if !File.exist?(File.dirname(link))
2948
- FileUtils.mkdir_p(File.dirname(link))
2949
- end
2950
- begin
2951
- File.symlink(init_script, link)
2952
- rescue Errno::EEXIST
2953
- # The link name that init_links provides is not guaranteed to
2954
- # be unique. It might collide with a base system init script
2955
- # or an init script from another tpkg. If the link name
2956
- # supplied by init_links results in EEXIST then try appending
2957
- # a number to the end of the link name.
2958
- catch :init_link_done do
2959
- 1.upto(9) do |i|
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
- end
2971
- # EACCES for file/directory permissions issues
2972
- rescue Errno::EACCES => e
2973
- # If creating the link fails due to permission problems and
2974
- # we're not running as root just warn the user, allowing folks
2975
- # to run tpkg as a non-root user with reduced functionality.
2976
- if Process.euid != 0
2977
- warn "Failed to install init script for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
2978
- else
2979
- raise e
2980
- end
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, init_script|
2986
- # The link we ended up making when we unpacked the package could be any
2987
- # of a series (see the code in install_init_scripts for the reasoning),
2988
- # we need to check them all.
2989
- links = [link]
2990
- links.concat((1..9).to_a.map { |i| link + i.to_s })
2991
- links.each do |l|
2992
- if File.symlink?(l) && File.readlink(l) == init_script
2993
- begin
2994
- File.delete(l)
2995
- # EACCES for file/directory permissions issues
2996
- rescue Errno::EACCES => e
2997
- # If removing the link fails due to permission problems and
2998
- # we're not running as root just warn the user, allowing folks
2999
- # to run tpkg as a non-root user with reduced functionality.
3000
- if Process.euid != 0
3001
- warn "Failed to remove init script for #{File.basename(metadata[:filename].to_s)}, probably due to lack of root privileges: #{e.message}"
3002
- else
3003
- raise e
3004
- end
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
- # FIXME: Besides the regex being ugly it is also only going to match on
3014
- # Linux, need to figure out if there's a reason for that or if this can
3015
- # be made more generic.
3016
- if !@sudo && (destination[destination.keys.first] =~ /\/var\/spool\/cron/)
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[:link]) && File.readlink(destination[:link]) == crontab
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.symlink(crontab, destination[:link])
3053
- rescue Errno::EEXIST
3054
- # The link name that crontab_destinations provides is not
3055
- # guaranteed to be unique. It might collide with a base
3056
- # system crontab or a crontab from another tpkg. If the
3057
- # link name supplied by crontab_destinations results in
3058
- # EEXIST then try appending a number to the end of the link
3059
- # name.
3060
- catch :crontab_link_done do
3061
- 1.upto(9) do |i|
3062
- begin
3063
- File.symlink(crontab, destination[:link] + i.to_s)
3064
- throw :crontab_link_done
3065
- rescue Errno::EEXIST
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
- # If we get here (i.e. we never reached the throw) then we
3069
- # failed to create any of the possible link names.
3070
- raise "Failed to install crontab #{crontab} -> #{destination[:link]} for #{File.basename(metadata[:filename].to_s)}, too many overlapping filenames"
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
- # FIXME: Can this be replaced by install_crontab_bycmd?
3075
- def install_crontab_file(metadata, crontab, destination)
3076
- if !File.exist?(File.dirname(destination[:file]))
3077
- FileUtils.mkdir_p(File.dirname(destination[:file]))
3078
- end
3079
- tmpfile = Tempfile.new(File.basename(destination[:file]), File.dirname(destination[:file]))
3080
- if File.exist?(destination[:file])
3081
- # Match permissions and ownership of current crontab
3082
- st = File.stat(destination[:file])
3083
- begin
3084
- File.chmod(st.mode & 07777, tmpfile.path)
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
- # Insert a header line so we can find this section to remove later
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 install_crontab_bycmd(metadata, crontab, destination)
3119
- oldcron = `crontab -l`
3120
- tmpf = '/tmp/tpkg_cron.' + rand.to_s
3121
- tmpfh = File.open(tmpf,'w')
3122
- tmpfh.write(oldcron) unless oldcron.empty?
3123
- tmpfh.puts "### TPKG START - #{@base} - #{File.basename(metadata[:filename].to_s)}"
3124
- tmpfh.write File.readlines(crontab)
3125
- tmpfh.puts "### TPKG END - #{@base} - #{File.basename(metadata[:filename].to_s)}"
3126
- tmpfh.close
3127
- `crontab #{tmpf}`
3128
- FileUtils.rm(tmpf)
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
- # FIXME: Besides the regex being ugly it is also only going to match on
3133
- # Linux, need to figure out if there's a reason for that or if this can
3134
- # be made more generic.
3135
- if !@sudo && (destination[destination.keys.first] =~ /\/var\/spool\/cron/)
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
- # The link we ended up making when we unpacked the package could
3161
- # be any of a series (see the code in unpack for the reasoning),
3162
- # we need to check them all.
3163
- links = [destination[:link]]
3164
- links.concat((1..9).to_a.map { |i| destination[:link] + i.to_s })
3165
- links.each do |l|
3166
- if File.symlink?(l) && File.readlink(l) == crontab
3167
- File.delete(l)
3168
- end
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
- # Remove section associated with this package
3194
- skip = false
3195
- IO.foreach(destination[:file]) do |line|
3196
- if line == "### TPKG START - #{@base} - #{File.basename(metadata[:filename].to_s)}\n"
3197
- skip = true
3198
- elsif line == "### TPKG END - #{@base} - #{File.basename(metadata[:filename].to_s)}\n"
3199
- skip = false
3200
- elsif !skip
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 remove_crontab_bycmd(metadata, crontab, destination)
3211
- oldcron = `crontab -l`
3212
- tmpf = '/tmp/tpkg_cron.' + rand.to_s
3213
- tmpfh = File.open(tmpf,'w')
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
- tmpfh.write(line)
2745
+ tf.write(line)
3222
2746
  end
3223
2747
  end
3224
- tmpfh.close
3225
- `crontab #{tmpf}`
3226
- FileUtils.rm(tmpf)
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 !Tpkg::package_meets_requirement?(pkg, req)
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? && !Tpkg::packages_meet_requirement?(packages.values.flatten, depreq)
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 Tpkg::package_meets_requirement?(pkg2, conflict)
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 Tpkg::package_meets_requirement?(pkg2, conflict)
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
- name = pkg[:metadata][:name]
3693
- version = pkg[:metadata][:version]
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
- if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
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
- # create and install stubbed native package if needed
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
- if Tpkg::get_os =~ /RedHat|CentOS|Fedora/
3984
- name = pkg[:metadata][:name]
3985
- version = pkg[:metadata][:version]
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
- # create and install stubbed native package if needed
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
- # remove native dependency stub packages if needed
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
-