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.
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
-