automate-it 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.hgignore +10 -0
  4. data/.loadpath +5 -0
  5. data/.project +17 -0
  6. data/CHANGES.txt +314 -0
  7. data/Hoe.rake +40 -0
  8. data/Manifest.txt +164 -0
  9. data/README.txt +40 -0
  10. data/Rakefile +256 -0
  11. data/TESTING.txt +57 -0
  12. data/TODO.txt +50 -0
  13. data/TUTORIAL.txt +391 -0
  14. data/automate-it.gemspec +25 -0
  15. data/bin/ai +3 -0
  16. data/bin/aifield +75 -0
  17. data/bin/aissh +93 -0
  18. data/bin/aitag +134 -0
  19. data/bin/automateit +133 -0
  20. data/docs/friendly_errors.txt +50 -0
  21. data/docs/previews.txt +86 -0
  22. data/examples/basic/Rakefile +26 -0
  23. data/examples/basic/config/automateit_env.rb +16 -0
  24. data/examples/basic/config/fields.yml +3 -0
  25. data/examples/basic/config/tags.yml +7 -0
  26. data/examples/basic/dist/README.txt +9 -0
  27. data/examples/basic/dist/myapp_server.erb +30 -0
  28. data/examples/basic/install.log +15 -0
  29. data/examples/basic/lib/README.txt +10 -0
  30. data/examples/basic/recipes/README.txt +4 -0
  31. data/examples/basic/recipes/install.rb +61 -0
  32. data/examples/basic/recipes/uninstall.rb +6 -0
  33. data/gpl.txt +674 -0
  34. data/helpers/cpan_wrapper.pl +220 -0
  35. data/helpers/which.cmd +7 -0
  36. data/lib/automateit.rb +55 -0
  37. data/lib/automateit/account_manager.rb +114 -0
  38. data/lib/automateit/account_manager/base.rb +138 -0
  39. data/lib/automateit/account_manager/etc.rb +128 -0
  40. data/lib/automateit/account_manager/nscd.rb +33 -0
  41. data/lib/automateit/account_manager/passwd_expect.rb +40 -0
  42. data/lib/automateit/account_manager/passwd_pty.rb +69 -0
  43. data/lib/automateit/account_manager/posix.rb +138 -0
  44. data/lib/automateit/address_manager.rb +88 -0
  45. data/lib/automateit/address_manager/base.rb +171 -0
  46. data/lib/automateit/address_manager/bsd.rb +28 -0
  47. data/lib/automateit/address_manager/freebsd.rb +59 -0
  48. data/lib/automateit/address_manager/linux.rb +42 -0
  49. data/lib/automateit/address_manager/openbsd.rb +66 -0
  50. data/lib/automateit/address_manager/portable.rb +37 -0
  51. data/lib/automateit/address_manager/sunos.rb +34 -0
  52. data/lib/automateit/cli.rb +85 -0
  53. data/lib/automateit/common.rb +65 -0
  54. data/lib/automateit/constants.rb +35 -0
  55. data/lib/automateit/download_manager.rb +48 -0
  56. data/lib/automateit/edit_manager.rb +321 -0
  57. data/lib/automateit/error.rb +10 -0
  58. data/lib/automateit/field_manager.rb +103 -0
  59. data/lib/automateit/interpreter.rb +631 -0
  60. data/lib/automateit/package_manager.rb +257 -0
  61. data/lib/automateit/package_manager/apt.rb +27 -0
  62. data/lib/automateit/package_manager/cpan.rb +101 -0
  63. data/lib/automateit/package_manager/dpkg.rb +54 -0
  64. data/lib/automateit/package_manager/egg.rb +64 -0
  65. data/lib/automateit/package_manager/gem.rb +201 -0
  66. data/lib/automateit/package_manager/pear.rb +95 -0
  67. data/lib/automateit/package_manager/pecl.rb +80 -0
  68. data/lib/automateit/package_manager/portage.rb +69 -0
  69. data/lib/automateit/package_manager/yum.rb +65 -0
  70. data/lib/automateit/platform_manager.rb +49 -0
  71. data/lib/automateit/platform_manager/darwin.rb +30 -0
  72. data/lib/automateit/platform_manager/debian.rb +26 -0
  73. data/lib/automateit/platform_manager/freebsd.rb +29 -0
  74. data/lib/automateit/platform_manager/gentoo.rb +26 -0
  75. data/lib/automateit/platform_manager/lsb.rb +44 -0
  76. data/lib/automateit/platform_manager/openbsd.rb +28 -0
  77. data/lib/automateit/platform_manager/struct.rb +80 -0
  78. data/lib/automateit/platform_manager/sunos.rb +39 -0
  79. data/lib/automateit/platform_manager/uname.rb +29 -0
  80. data/lib/automateit/platform_manager/windows.rb +40 -0
  81. data/lib/automateit/plugin.rb +7 -0
  82. data/lib/automateit/plugin/base.rb +32 -0
  83. data/lib/automateit/plugin/driver.rb +256 -0
  84. data/lib/automateit/plugin/manager.rb +224 -0
  85. data/lib/automateit/project.rb +493 -0
  86. data/lib/automateit/root.rb +17 -0
  87. data/lib/automateit/service_manager.rb +93 -0
  88. data/lib/automateit/service_manager/chkconfig.rb +39 -0
  89. data/lib/automateit/service_manager/rc_update.rb +37 -0
  90. data/lib/automateit/service_manager/sysv.rb +139 -0
  91. data/lib/automateit/service_manager/update_rcd.rb +35 -0
  92. data/lib/automateit/shell_manager.rb +316 -0
  93. data/lib/automateit/shell_manager/base_link.rb +67 -0
  94. data/lib/automateit/shell_manager/link.rb +24 -0
  95. data/lib/automateit/shell_manager/portable.rb +523 -0
  96. data/lib/automateit/shell_manager/symlink.rb +32 -0
  97. data/lib/automateit/shell_manager/which_base.rb +30 -0
  98. data/lib/automateit/shell_manager/which_unix.rb +16 -0
  99. data/lib/automateit/shell_manager/which_windows.rb +20 -0
  100. data/lib/automateit/tag_manager.rb +127 -0
  101. data/lib/automateit/tag_manager/struct.rb +121 -0
  102. data/lib/automateit/tag_manager/tag_parser.rb +93 -0
  103. data/lib/automateit/tag_manager/yaml.rb +29 -0
  104. data/lib/automateit/template_manager.rb +56 -0
  105. data/lib/automateit/template_manager/base.rb +181 -0
  106. data/lib/automateit/template_manager/erb.rb +17 -0
  107. data/lib/ext/metaclass.rb +17 -0
  108. data/lib/ext/object.rb +18 -0
  109. data/lib/ext/shell_escape.rb +7 -0
  110. data/lib/hashcache.rb +22 -0
  111. data/lib/helpful_erb.rb +63 -0
  112. data/lib/inactive_support.rb +53 -0
  113. data/lib/inactive_support/basic_object.rb +6 -0
  114. data/lib/inactive_support/clean_logger.rb +127 -0
  115. data/lib/inactive_support/core_ext/array/extract_options.rb +19 -0
  116. data/lib/inactive_support/core_ext/blank.rb +50 -0
  117. data/lib/inactive_support/core_ext/class/attribute_accessors.rb +48 -0
  118. data/lib/inactive_support/core_ext/class/inheritable_attributes.rb +140 -0
  119. data/lib/inactive_support/core_ext/enumerable.rb +63 -0
  120. data/lib/inactive_support/core_ext/hash/keys.rb +54 -0
  121. data/lib/inactive_support/core_ext/module/aliasing.rb +70 -0
  122. data/lib/inactive_support/core_ext/numeric/time.rb +91 -0
  123. data/lib/inactive_support/core_ext/string/inflections.rb +153 -0
  124. data/lib/inactive_support/core_ext/symbol.rb +14 -0
  125. data/lib/inactive_support/core_ext/time/conversions.rb +96 -0
  126. data/lib/inactive_support/duration.rb +96 -0
  127. data/lib/inactive_support/inflections.rb +53 -0
  128. data/lib/inactive_support/inflector.rb +282 -0
  129. data/lib/nested_error.rb +33 -0
  130. data/lib/nitpick.rb +33 -0
  131. data/lib/queued_logger.rb +68 -0
  132. data/lib/tempster.rb +250 -0
  133. data/misc/index_gem_repository.rb +304 -0
  134. data/misc/setup_egg.rb +12 -0
  135. data/misc/setup_gem_dependencies.sh +6 -0
  136. data/misc/setup_rubygems.sh +21 -0
  137. metadata +279 -0
@@ -0,0 +1,257 @@
1
+ # == PackageManager
2
+ #
3
+ # The PackageManager provides a way to manage packages, e.g., install,
4
+ # uninstall and query if the Apache package is installed with APT.
5
+ #
6
+ # Examples:
7
+ #
8
+ # package_manager.installed?("apache2") # => false
9
+ # package_manager.install("apache2") # => true
10
+ # package_manager.installed?("apache2") # => true
11
+ # package_manager.uninstall("apache2") # => true
12
+ # package_manager.not_installed("apache2") # => true
13
+ #
14
+ # Commands can accept arrays:
15
+ #
16
+ # package_manager.install("apache2", "bash")
17
+ # package_manager.installed? %w(apache2 bash)
18
+ #
19
+ # Commands can also accept a single, annotated string as a manifest -- useful
20
+ # for installing large numbers of packages at once:
21
+ #
22
+ # package_manager.install <<HERE, :with => :apt
23
+ # # One per line
24
+ # apache
25
+ # bash
26
+ #
27
+ # # Or many on the same line
28
+ # sysvconfig sysv-rc-conf
29
+ # HERE
30
+ #
31
+ # Commands can also accept a hash of names to paths -- necessary for installing
32
+ # packages stored on the filesystem:
33
+ #
34
+ # # Is the package called "TracTags" installed? If not, run the installer
35
+ # # with the "/tmp/tractags_latest" path as an argument:
36
+ # package.manager.install({"TracTags" => "/tmp/tractags_latest"}, :with => :egg)
37
+ class AutomateIt::PackageManager < AutomateIt::Plugin::Manager
38
+ # Alias for #install
39
+ def add(*packages) dispatch_to(:install, *packages) end
40
+
41
+ # Alias for #uninstall
42
+ def remove(*packages) dispatch_to(:uninstall, *packages) end
43
+
44
+ # Are these +packages+ installed?
45
+ #
46
+ # Options:
47
+ # * :details -- Returns an array containing the boolean result value and an
48
+ # array with a subset of installed +packages+. Boolean, defaults to false.
49
+ def installed?(*packages) dispatch(*packages) end
50
+
51
+ # Are these +packages+ not installed?
52
+ #
53
+ # Options:
54
+ # * :details -- Returns an array containing the boolean result value and an
55
+ # array with a subset of +packages+ not installed. Boolean, defaults to false.
56
+ def not_installed?(*packages) dispatch(*packages) end
57
+
58
+ # Install these +packages+. Returns +true+ if any packages are installed
59
+ # successfully; or +false+ if all packages were already installed.
60
+ def install(*packages) dispatch(*packages) end
61
+
62
+ # Uninstall these +packages+. Returns +true+ if any packages are uninstalled
63
+ # successfully; or +false+ if none of the packages are installed.
64
+ def uninstall(*packages) dispatch(*packages) end
65
+ end
66
+
67
+ # == PackageManager::BaseDriver
68
+ #
69
+ # Base class for all PackageManager drivers.
70
+ class AutomateIt::PackageManager::BaseDriver < AutomateIt::Plugin::Driver
71
+ protected
72
+
73
+ # Are these +packages+ installed? Works like PackageManager#installed?
74
+ # but calls a block that actually checks whether the packages are
75
+ # installed and returns an array of packages installed.
76
+ #
77
+ # For example:
78
+ # _installed_helper?("package1", "package2", :details => true) do |packages, opts|
79
+ # # Dummy code which reports that these packages are installed:
80
+ # ["package1]
81
+ # end
82
+ def _installed_helper?(*packages, &block) # :yields: filtered_packages, opts
83
+ _raise_unless_available
84
+
85
+ packages, opts = args_and_opts(*packages)
86
+ packages = _list_normalizer(packages)
87
+ packages = packages.keys if Hash === packages
88
+
89
+ available = block.call(packages, opts)
90
+ truth = (packages - available).empty?
91
+ result = opts[:details] ? [truth, available] : truth
92
+ log.debug(PNOTE+"installed?(#{packages.inspect}) => #{truth}: #{available.inspect}")
93
+ return result
94
+ end
95
+
96
+ # Are these +packages+ not installed?
97
+ def _not_installed_helper?(*packages)
98
+ _raise_unless_available
99
+
100
+ # Requires that your PackageManager#installed? method is implemented.
101
+ packages, opts = args_and_opts(*packages)
102
+ packages = _list_normalizer(packages)
103
+ packages = packages.keys if Hash === packages
104
+
105
+ available = [installed?(packages, :details => true)].flatten
106
+ missing = packages - available
107
+ truth = (packages - missing).empty?
108
+ result = opts[:details] ? [truth, missing] : truth
109
+ log.debug(PNOTE+"not_installed?(#{packages.inspect}) => #{truth}: #{missing.inspect}")
110
+ return result
111
+ end
112
+
113
+ # Install these +packages+. Works like PackageManager#install but calls a
114
+ # block that's responsible for actually installing the packages and
115
+ # returning true if the installation succeeded. This block is only called
116
+ # if packages need to be installed and receives a filtered list of
117
+ # packages that are guaranteed not to be installed on the system already.
118
+ #
119
+ # For example:
120
+ # _install_helper("package1", "package2", :quiet => true) do |packages, opts|
121
+ # # Dummy code that installs packages here, e.g:
122
+ # system("apt-get", "install", "-y", packages)
123
+ # end
124
+ def _install_helper(*packages, &block) # :yields: filtered_packages, opts
125
+ _raise_unless_available
126
+
127
+ packages, opts = args_and_opts(*packages)
128
+ packages = _list_normalizer(packages)
129
+
130
+ check_packages = \
131
+ case packages
132
+ when Hash
133
+ packages.keys
134
+ else
135
+ packages
136
+ end
137
+
138
+ missing = not_installed?(check_packages, :details => true)[1]
139
+ return false if missing.blank?
140
+
141
+ install_packages = \
142
+ case packages
143
+ when Hash
144
+ missing.map{|t| packages[t]}
145
+ else
146
+ missing
147
+ end
148
+ block.call(install_packages, opts)
149
+
150
+ return true if preview?
151
+ unless (failed = not_installed?(check_packages, :details => true)[1]).empty?
152
+ raise ArgumentError.new("Couldn't install: #{failed.join(' ')}")
153
+ else
154
+ return true
155
+ end
156
+ end
157
+
158
+ # Uninstall these +packages+. Works like PackageManager#uninstall but calls a
159
+ # block that's responsible for actually uninstalling the packages and
160
+ # returning true if the uninstall succeeded. This block is only called
161
+ # if packages need to be uninstalled and receives a filtered list of
162
+ # packages that are guaranteed to be installed on the system.
163
+ #
164
+ # For example:
165
+ # _uninstall_helper("package1", "package2", :quiet => true) do |packages, opts|
166
+ # # Dummy code that removes packages here, e.g:
167
+ # system("apt-get", "remove", "-y", packages)
168
+ # end
169
+ def _uninstall_helper(*packages, &block) # :yields: filtered_packages, opts
170
+ _raise_unless_available
171
+
172
+ packages, opts = args_and_opts(*packages)
173
+ packages = _list_normalizer(packages)
174
+
175
+ check_packages = \
176
+ case packages
177
+ when Hash
178
+ packages.keys
179
+ else
180
+ packages
181
+ end
182
+
183
+ present = installed?(check_packages, :details => true)[1]
184
+ return false if present.blank?
185
+
186
+ uninstall_packages = \
187
+ case packages
188
+ when Hash
189
+ present.map{|t| packages[t]}
190
+ else
191
+ present
192
+ end
193
+ block.call(uninstall_packages, opts)
194
+
195
+ return true if preview?
196
+ unless (failed = installed?(check_packages, :details => true)[1]).empty?
197
+ raise ArgumentError.new("Couldn't uninstall: #{failed.join(' ')}")
198
+ else
199
+ return true
200
+ end
201
+ end
202
+
203
+ # Returns a normalized array of packages. Transforms manifest string into
204
+ # packages. Turns symbols into string, strips blank lines and comments.
205
+ def _list_normalizer(*packages)
206
+ packages = [packages].flatten
207
+ if packages.size == 1
208
+ packages = packages.first
209
+ nitpick "LN SI %s" % packages.inspect
210
+ nitpick "LN Sc %s" % packages.class
211
+ case packages
212
+ when Symbol
213
+ nitpick "LN Sy"
214
+ packages = [packages.to_s]
215
+ when String
216
+ nitpick "LN Ss"
217
+ packages = _string_to_packages(packages)
218
+ when Hash
219
+ # Don't do anything
220
+ nitpick "LN Sh"
221
+ else
222
+ nitpick "LN S?"
223
+ raise TypeError.new("Unknown input type: #{packages.class}")
224
+ end
225
+ nitpick "LN SO %s" % packages.inspect
226
+ end
227
+
228
+ case packages
229
+ when Array
230
+ result = packages.map(&:to_s).map{|t| _string_to_packages(t)}.flatten.uniq
231
+ when Hash
232
+ result = packages.stringify_keys
233
+ when Symbol, String
234
+ result = packages.to_s
235
+ else
236
+ raise TypeError.new("Unknown input type: #{packages.class}")
237
+ end
238
+
239
+ nitpick "LN RR %s" % result.inspect
240
+ return result
241
+ end
242
+
243
+ def _string_to_packages(string)
244
+ string.scan(/^\s*([^#]+)\s*/).flatten.map{|t| t.split}.flatten.uniq
245
+ end
246
+ end
247
+
248
+ # Drivers
249
+ require 'automateit/package_manager/dpkg'
250
+ require 'automateit/package_manager/apt'
251
+ require 'automateit/package_manager/yum'
252
+ require 'automateit/package_manager/gem'
253
+ require 'automateit/package_manager/egg'
254
+ require 'automateit/package_manager/portage'
255
+ require 'automateit/package_manager/pear'
256
+ require 'automateit/package_manager/pecl'
257
+ require 'automateit/package_manager/cpan'
@@ -0,0 +1,27 @@
1
+ # == PackageManager::APT
2
+ #
3
+ # The APT driver for the PackageManager provides a way to manage software
4
+ # packages on Debian-style systems using <tt>apt-get</tt> and <tt>dpkg</tt>.
5
+ class AutomateIt::PackageManager::APT < AutomateIt::PackageManager::DPKG
6
+ depends_on :programs => %w(apt-get dpkg)
7
+
8
+ def suitability(method, *args) # :nodoc:
9
+ return available? ? 1 : 0
10
+ end
11
+
12
+ # See AutomateIt::PackageManager#install
13
+ def install(*packages)
14
+ return _install_helper(*packages) do |list, opts|
15
+ # apt-get options:
16
+ # -y : yes to all queries
17
+ # -q : no interactive progress bars
18
+ cmd = "export DEBIAN_FRONTEND=noninteractive; apt-get"
19
+ cmd << " -t #{opts[:backports]}" if opts[:backports]
20
+ cmd << " install -y -q "+list.join(" ")+" < /dev/null"
21
+ cmd << " > /dev/null" if opts[:quiet]
22
+ cmd << " 2>&1"
23
+
24
+ interpreter.sh(cmd)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,101 @@
1
+ # == PackageManager::CPAN
2
+ #
3
+ # A PackageManager driver for Perl CPAN (Comprehensive Perl Archive Network)
4
+ # software packages.
5
+ #
6
+ # === No automatic dependency installation
7
+ #
8
+ # Unlike other AutomateIt PackageManager drivers, the CPAN driver will not install a package's dependencies automatically. This protects you because many CPAN packages require a specific version of Perl, often one which you don't have installed, and installing that dependency will destroy your Perl interpreter and everything that depends on it. Therefore, you must specify all package dependencies manually. If a package dependency isn't found, the install will fail.
9
+ #
10
+ # === Specifying Perl interpreter
11
+ #
12
+ # Use #setup to specify the Perl interpreter to use for all subsequent calls.
13
+ #
14
+ # Example:
15
+ #
16
+ # package_manager[:cpan].setup(:perl => "/usr/local/bin/perl")
17
+ # package_manager.install %w(File::Next App::Ack), :with => :cpan
18
+ class ::AutomateIt::PackageManager::CPAN < ::AutomateIt::PackageManager::BaseDriver
19
+ CPAN_WRAPPER = File.join(::AutomateIt::Constants::HELPERS_DIR, "cpan_wrapper.pl")
20
+
21
+ # Path to Perl interpreter
22
+ attr_accessor :perl
23
+
24
+ # FIXME How to get #depends_on to use same Perl interpreter as #perl? The trouble is that Plugin::Driver#available? checks a class variable populated by #depends_on, so it can't see the instance's #perl variable that's been set by the user. A general solution would address this problem for all drivers that use commands with different names, e.g. "gem1.8", "python2.5.1", etc.
25
+ depends_on :programs => %w(perl)
26
+
27
+ # Setup the PackageManager::CPAN driver.
28
+ #
29
+ # Options:
30
+ # * :perl -- The absolute, relative or unqualified path for the Perl interpreter to use. E.g., "perl" or "/usr/local/bin/perl".
31
+ def setup(*args)
32
+ super(*args)
33
+
34
+ args, opts = args_and_opts(*args)
35
+ if opts[:perl]
36
+ self.perl = opts[:perl]
37
+ else
38
+ self.perl ||= "perl"
39
+ end
40
+ end
41
+
42
+ def suitability(method, *args) # :nodoc:
43
+ # Never select as default driver
44
+ return 0
45
+ end
46
+
47
+ # Options:
48
+ # * :perl -- Command to use as the Perl interpreter, otherwise defaults to the one specified during #setup or to "perl"
49
+ #
50
+ # See AutomateIt::PackageManager#installed?
51
+ def installed?(*packages)
52
+ return _installed_helper?(*packages) do |list, opts|
53
+ perl = opts[:perl] || self.perl
54
+ cmd = "#{perl} #{CPAN_WRAPPER} --query #{list.join(' ')}"
55
+
56
+ # FIXME if CPAN isn't configured, this will hang because Perl will demand input
57
+ log.debug(PEXEC+cmd)
58
+ output = `#{cmd}`
59
+ output.sub!(/.*---(\s[^\n]+)?\n/m, '')
60
+ struct = ::YAML.load(output)
61
+
62
+ struct["available"] || []
63
+ end
64
+ end
65
+
66
+ # See AutomateIt::PackageManager#not_installed?
67
+ def not_installed?(*packages)
68
+ # TODO Move #not_installed? up to BaseDriver
69
+ return _not_installed_helper?(*packages)
70
+ end
71
+
72
+ # Options:
73
+ # * :perl -- Command to use as the Perl interpreter, otherwise defaults to the one specified during #setup or to "perl"
74
+ #
75
+ # See AutomateIt::PackageManager#install
76
+ def install(*packages)
77
+ return _install_helper(*packages) do |list, opts|
78
+ perl = opts[:perl] || self.perl
79
+ cmd = "#{perl} #{CPAN_WRAPPER} --install #{list.join(' ')}"
80
+ cmd << " > /dev/null" if opts[:quiet]
81
+ cmd << " 2>&1"
82
+
83
+ interpreter.sh(cmd)
84
+ end
85
+ end
86
+
87
+ # Options:
88
+ # * :perl -- Command to use as the Perl interpreter, otherwise defaults to the one specified during #setup or to "perl"
89
+ #
90
+ # See AutomateIt::PackageManager#uninstall
91
+ def uninstall(*packages)
92
+ return _uninstall_helper(*packages) do |list, opts|
93
+ perl = opts[:perl] || self.perl
94
+ cmd = "#{perl} #{CPAN_WRAPPER} --uninstall #{list.join(' ')} < /dev/null"
95
+ cmd << " > /dev/null" if opts[:quiet]
96
+ cmd << " 2>&1"
97
+
98
+ interpreter.sh(cmd)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,54 @@
1
+ # == PackageManager::DPKG
2
+ #
3
+ # The DPKG driver for the PackageManager provides a way to manage software
4
+ # packages on Debian-style systems using <tt>dpkg</tt>.
5
+ class AutomateIt::PackageManager::DPKG < AutomateIt::PackageManager::BaseDriver
6
+ depends_on :programs => %w(dpkg)
7
+
8
+ # See AutomateIt::PackageManager#installed?
9
+ def installed?(*packages)
10
+ return _installed_helper?(*packages) do |list, opts|
11
+ ### data = `dpkg --status nomarch apache2 not_a_real_package 2>&1`
12
+ cmd = "dpkg --status "+list.join(" ")+" 2>&1"
13
+
14
+ log.debug(PEXEC+cmd)
15
+ data = `#{cmd}`
16
+ matches = data.scan(/^Package: (.+)$\s*^Status: (.+)$/)
17
+ available = matches.inject([]) do |sum, match|
18
+ package, status = match
19
+ sum << package if status.match(/(?:^|\s)installed\b/)
20
+ sum
21
+ end
22
+
23
+ available
24
+ end
25
+ end
26
+
27
+ # See AutomateIt::PackageManager#not_installed?
28
+ def not_installed?(*packages)
29
+ return _not_installed_helper?(*packages)
30
+ end
31
+
32
+ # See AutomateIt::PackageManager#install
33
+ def install(*packages)
34
+ return _install_helper(*packages) do |list, opts|
35
+ cmd = "export DEBIAN_FRONTEND=noninteractive; dpkg --install --skip-same-version "+list.join(" ")+" < /dev/null"
36
+ cmd << " > /dev/null" if opts[:quiet]
37
+ cmd << " 2>&1"
38
+
39
+ interpreter.sh(cmd)
40
+ end
41
+ end
42
+
43
+ # See AutomateIt::PackageManager#uninstall
44
+ def uninstall(*packages)
45
+ return _uninstall_helper(*packages) do |list, opts|
46
+ cmd = "export DEBIAN_FRONTEND=noninteractive; dpkg --remove "+list.join(" ")+" < /dev/null"
47
+ cmd << " > /dev/null" if opts[:quiet]
48
+ cmd << " 2>&1"
49
+
50
+ interpreter.sh(cmd)
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,64 @@
1
+ # == PackageManager::Egg
2
+ #
3
+ # The Egg driver for the PackageManager provides a way to manage
4
+ # Python software packages with the PEAK +easy_install+ tool.
5
+ class AutomateIt::PackageManager::Egg < AutomateIt::PackageManager::BaseDriver
6
+ depends_on :programs => %w(python easy_install)
7
+
8
+ def suitability(method, *args) # :nodoc:
9
+ # Never select as default driver
10
+ return 0
11
+ end
12
+
13
+ # See AutomateIt::PackageManager#installed?
14
+ def installed?(*packages)
15
+ return _installed_helper?(*packages) do |list, opts|
16
+ cmd = "python -c 'import sys; print(sys.path)' 2>&1"
17
+
18
+ log.debug(PEXEC+cmd)
19
+ data = `#{cmd}`
20
+ # Extract array elements, turn them into basenames, and then split on
21
+ # '-' because that's the separator for the name and version.
22
+ found = data.scan(/'([^']+\.egg)'/).flatten.map{|t| File.basename(t).split('-', 2)[0]}
23
+ available = found & list
24
+ end
25
+ end
26
+
27
+ # See AutomateIt::PackageManager#not_installed?
28
+ def not_installed?(*packages)
29
+ return _not_installed_helper?(*packages)
30
+ end
31
+
32
+ # See AutomateIt::PackageManager#install
33
+ def install(*packages)
34
+ return _install_helper(*packages) do |list, opts|
35
+ # easy_install options:
36
+ # -Z : install into a direcory rather than a file
37
+ cmd = "easy_install -Z "+list.join(" ")+" < /dev/null"
38
+ cmd << " > /dev/null" if opts[:quiet]
39
+ cmd << " 2>&1"
40
+
41
+ interpreter.sh(cmd)
42
+ end
43
+ end
44
+
45
+ # See AutomateIt::PackageManager#uninstall
46
+ def uninstall(*packages)
47
+ return _uninstall_helper(*packages) do |list, opts|
48
+ # easy_install options:
49
+ # -m : removes package from the easy-install.pth
50
+ cmd = "easy_install -m "+list.join(" ")+" < /dev/null"
51
+ cmd << " > /dev/null" if opts[:quiet]
52
+ cmd << " 2>&1"
53
+
54
+ # Parse output for paths and remove the orphaned entries
55
+ log.info(PEXEC+cmd)
56
+ return packages if preview?
57
+ data = `#{cmd}`
58
+ paths = data.scan(/^Using ([^\n]+\.egg)$/m).flatten
59
+ for path in paths
60
+ interpreter.rm_rf(path)
61
+ end
62
+ end
63
+ end
64
+ end