automateit 0.71221 → 0.71226

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,8 @@
1
+ 0.71226:
2
+ Date: Wed, 26 Dec 2007 11:41:03 -0800
3
+ Desc:
4
+ - (%) Fixed PackageManager::CPAN driver. It now provides a workaround to activate CPAN if it wasn't already configured, previously it'd hang as CPAN tried to get input. It now provides a workaround for rejecting all CPAN inputs because the CPAN default options are surprisingly dangerous. It now tries harder to execute the Perl helper files, previously these wouldn't be executed on some OSes. The helpers' core logic has been abstracted into a wrapper library.
5
+
1
6
  0.71221:
2
7
  Date: Sun, 23 Dec 2007 00:48:30 -0800
3
8
  Desc:
data/Rakefile CHANGED
@@ -243,7 +243,7 @@ namespace :rdoc do
243
243
  desc "Generate documentation"
244
244
  task :make do
245
245
  # Uses Jamis Buck's RDoc template from http://weblog.jamisbuck.org/2005/4/8/rdoc-template
246
- sh "rdoc --template=jamis --main README.txt --promiscuous --accessor class_inheritable_accessor=R --title 'AutomateIt: Open source server automation' lib docs/*.txt README.txt TUTORIAL.txt TESTING.txt"
246
+ sh "rdoc --template=jamis --main ./README.txt --promiscuous --accessor class_inheritable_accessor=R --title 'AutomateIt: Open source server automation' lib docs/*.txt README.txt TUTORIAL.txt TESTING.txt"
247
247
  # Create a tutorial index
248
248
  File.open("doc/tutorial.html", "w+") do |writer|
249
249
  writer.write(File.read("doc/index.html").sub(/README_txt.html/, 'TUTORIAL_txt.html'))
@@ -2,6 +2,11 @@
2
2
 
3
3
  # Example: ./install.pl Acme::please
4
4
 
5
+ use warnings "all";
6
+ use File::Basename;
7
+ my $wrapper = dirname($0)."/cpan_wrapper.pl";
8
+ require $wrapper;
9
+
5
10
  sub usage {
6
11
  my($message) = @_;
7
12
  print <<EOB;
@@ -15,10 +20,7 @@ EOB
15
20
  }
16
21
  }
17
22
 
18
- use warnings "all";
19
- use CPAN;
20
23
  use Getopt::Long;
21
-
22
24
  our $quiet = 0;
23
25
  our $dryrun = 0;
24
26
  our $help = 0;
@@ -38,10 +40,18 @@ unless ($#modules >= 0) {
38
40
  usage "No modules specified";
39
41
  }
40
42
 
43
+ $CpanWrapper::DRYRUN = $dryrun;
44
+ if (0 && $CpanWrapper::DRYRUN) { die } # Squelch warnings
45
+
46
+ # Uninstall modules
41
47
  foreach my $module (@modules) {
42
- if (my $module_ref = CPAN::Shell->expand('Module', $module)) {
43
- print "* Installing: $module\n" unless $quiet;
44
- $module_ref->install unless $dryrun;
48
+ if (CpanWrapper->is_installed($module)) {
49
+ print "! Module already installed: $module\n";
50
+ next;
51
+ }
52
+
53
+ if (CpanWrapper->install($module)) {
54
+ print "* Installed: $module\n" unless $quiet;
45
55
  } else {
46
56
  print "! Can't find CPAN module: $module\n";
47
57
  exit 1
@@ -3,7 +3,9 @@
3
3
  # Example: ./is_available.pl Acme::please CPAN
4
4
 
5
5
  use warnings "all";
6
- use CPAN;
6
+ use File::Basename;
7
+ my $wrapper = dirname($0)."/cpan_wrapper.pl";
8
+ require $wrapper;
7
9
 
8
10
  @modules = @ARGV;
9
11
  unless ($#modules >= 0) {
@@ -14,16 +16,9 @@ unless ($#modules >= 0) {
14
16
  my @available;
15
17
  my @unavailable;
16
18
  foreach my $module (@modules) {
17
- if (my $module_ref = CPAN::Shell->expand('Module', $module)) {
18
- my $path = $module_ref->inst_file;
19
- if ($path && -e $path) {
20
- #IK# print $module_ref->inst_file, "\n";
21
- push(@available, $module);
22
- } else {
23
- push(@unavailable, $module);
24
- }
19
+ if (CpanWrapper->is_installed($module)) {
20
+ push(@available, $module);
25
21
  } else {
26
- #IK# die "Can't find module: $module";
27
22
  push(@unavailable, $module);
28
23
  }
29
24
  }
@@ -2,6 +2,11 @@
2
2
 
3
3
  # Example: ./uninstall.pl Acme::please
4
4
 
5
+ use warnings "all";
6
+ use File::Basename;
7
+ my $wrapper = dirname($0)."/cpan_wrapper.pl";
8
+ require $wrapper;
9
+
5
10
  sub usage {
6
11
  my($message) = @_;
7
12
  print <<EOB;
@@ -15,11 +20,7 @@ EOB
15
20
  }
16
21
  }
17
22
 
18
- use warnings "all";
19
- use ExtUtils::Packlist;
20
- use ExtUtils::Installed;
21
23
  use Getopt::Long;
22
-
23
24
  our $quiet = 0;
24
25
  our $dryrun = 0;
25
26
  our $help = 0;
@@ -39,25 +40,19 @@ unless ($#modules >= 0) {
39
40
  usage "No modules specified";
40
41
  }
41
42
 
42
- sub nuke {
43
- my($target) = @_;
44
- if ($dryrun == 0) {
45
- unlink($target) || die "$! -- $target"
46
- }
47
- }
48
-
49
- my $packlists = ExtUtils::Installed->new();
43
+ $CpanWrapper::DRYRUN = $dryrun;
44
+ if (0 && $CpanWrapper::DRYRUN) { die } # Squelch warnings
50
45
 
51
46
  foreach my $module (@modules) {
47
+ unless (CpanWrapper->is_installed($module)) {
48
+ print "! Module isn't installed: $module\n";
49
+ next;
50
+ }
51
+
52
52
  print "* Uninstalling module: $module\n" unless $quiet;
53
53
 
54
- foreach my $item ($packlists->files($module)) {
55
- print "- File: $item\n" unless $quiet;
56
- nuke $item;
54
+ my(@files) = CpanWrapper->uninstall($module);
55
+ foreach my $file (@files) {
56
+ print "- File: $file\n" unless $quiet;
57
57
  }
58
-
59
- my $packlist = $packlists->packlist($module)->packlist_file();
60
- print "- List: $packlist\n" unless $quiet;
61
- # NOTE: Leave packlist alone so it can be uninstalled if something goes catastrophically wrong with this uninstaller.
62
- #IK# nuke $packlist;
63
58
  }
@@ -0,0 +1,98 @@
1
+ package CpanWrapper;
2
+ use CPAN;
3
+ use ExtUtils::Packlist;
4
+ use ExtUtils::Installed;
5
+
6
+ =head1 NAME
7
+
8
+ CpanWrapper - Provides a simpler wrapper for CPAN package methods.
9
+
10
+ =head1 DESCRIPTION
11
+
12
+ This module provides easy-to-use methods for performing typical tasks that the
13
+ CPAN module makes difficult for some incomprehensible reason.
14
+
15
+ =head1 CLASS VARIABLES
16
+
17
+ =item $CpanWrapper::DRYRUN
18
+
19
+ Should actions really happen? E.g., in dry-run mode, the uninstall will only
20
+ pretend to delete files.
21
+
22
+ =cut
23
+
24
+ our $DRYRUN = 0;
25
+
26
+ =item CpanWrapper->is_installed($module_name)
27
+
28
+ Returns 1 if the module is installed, else 0.
29
+
30
+ Example:
31
+
32
+ CpanWrapper->is_installed('App::Ack')
33
+ =cut
34
+ sub is_installed {
35
+ my($class, $module) = @_;
36
+ return $CPAN::META->has_inst($module);
37
+ }
38
+
39
+ =item CpanWrapper->uninstall($module_name)
40
+
41
+ Uninstall the module. Returns an array of files removed.
42
+ =cut
43
+ sub uninstall {
44
+ my($class, $module) = @_;
45
+ my $packlists = ExtUtils::Installed->new;
46
+ my @result;
47
+ foreach my $file ($packlists->files($module)) {
48
+ push(@result, $file);
49
+ unlink $file unless $DRYRUN;
50
+ }
51
+ return @result;
52
+ }
53
+
54
+ =item CpanWrapper->install($module_name)
55
+
56
+ Install the module. Returns 0 if can't find module.
57
+ =cut
58
+ sub install {
59
+ my($class, $module) = @_;
60
+ tie *NO, 'NoHandle';
61
+ open(SAVEIN, ">&STDIN");
62
+ open(STDIN, ">&NO"); # TODO why isn't this enough?
63
+ *STDIN = *NO;
64
+ my $result;
65
+ if (my $module_ref = CPAN::Shell->expand('Module', $module)) {
66
+ $module_ref->install unless $DRYRUN;
67
+ $result = 1;
68
+ } else {
69
+ $result = 0;
70
+ }
71
+ open(STDIN, ">&SAVEIN");
72
+ close NO;
73
+ return $result;
74
+ }
75
+
76
+ =item NoHandle
77
+
78
+ File handle that responds with "no" to all readline queries. This is used
79
+ during the install process to reject CPAN's bad defaults.
80
+ =cut
81
+ require Tie::Handle;
82
+ package NoHandle;
83
+ sub TIEHANDLE { my $self; bless \$self, shift }
84
+ sub WRITE { die }
85
+ sub PRINT { die }
86
+ sub PRINTF { die }
87
+ sub READ { die }
88
+ sub READLINE { print "no\n"; return "no\n" }
89
+ sub GETC { die }
90
+ sub CLOSE { }
91
+ sub OPEN { }
92
+ sub BINMODE { }
93
+ sub EOF { 0 }
94
+ sub TELL { }
95
+ sub DESTROY { }
96
+ package main;
97
+
98
+ 1;
@@ -2,23 +2,60 @@
2
2
  #
3
3
  # A PackageManager driver for Perl CPAN (Comprehensive Perl Archive Network)
4
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
5
18
  class ::AutomateIt::PackageManager::CPAN < ::AutomateIt::PackageManager::BaseDriver
6
19
  CPAN_INSTALL = File.join(::AutomateIt::Constants::HELPERS_DIR, "cpan_install.pl")
7
20
  CPAN_UNINSTALL = File.join(::AutomateIt::Constants::HELPERS_DIR, "cpan_uninstall.pl")
8
21
  CPAN_IS_INSTALLED = File.join(::AutomateIt::Constants::HELPERS_DIR, "cpan_is_installed.pl")
9
22
 
23
+ # Path to Perl interpreter
24
+ attr_accessor :perl
25
+
26
+ # 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.
10
27
  depends_on :programs => %w(perl)
11
28
 
29
+ # Setup the PackageManager::CPAN driver.
30
+ #
31
+ # Options:
32
+ # * :perl -- The absolute, relative or unqualified path for the Perl interpreter to use. E.g., "perl" or "/usr/local/bin/perl".
33
+ def setup(*args)
34
+ super(*args)
35
+
36
+ args, opts = args_and_opts(*args)
37
+ if opts[:perl]
38
+ self.perl = opts[:perl]
39
+ else
40
+ self.perl ||= "perl"
41
+ end
42
+ end
43
+
12
44
  def suitability(method, *args) # :nodoc:
13
45
  # Never select as default driver
14
46
  return 0
15
47
  end
16
48
 
49
+ # Options:
50
+ # * :perl -- Command to use as the Perl interpreter, otherwise defaults to the one specified during #setup or to "perl"
51
+ #
17
52
  # See AutomateIt::PackageManager#installed?
18
53
  def installed?(*packages)
19
54
  return _installed_helper?(*packages) do |list, opts|
20
- cmd = "#{CPAN_IS_INSTALLED} #{list.join(' ')}"
55
+ perl = opts[:perl] || self.perl
56
+ cmd = "#{perl} #{CPAN_IS_INSTALLED} #{list.join(' ')}"
21
57
 
58
+ # FIXME if CPAN isn't configured, this will hang because Perl will demand input
22
59
  log.debug(PEXEC+cmd)
23
60
  output = `#{cmd}`
24
61
  output.sub!(/.*---(\s[^\n]+)?\n/m, '')
@@ -30,19 +67,18 @@ class ::AutomateIt::PackageManager::CPAN < ::AutomateIt::PackageManager::BaseDri
30
67
 
31
68
  # See AutomateIt::PackageManager#not_installed?
32
69
  def not_installed?(*packages)
70
+ # TODO Move #not_installed? up to BaseDriver
33
71
  return _not_installed_helper?(*packages)
34
72
  end
35
73
 
36
- # *IMPORTANT*: See documentation at the top of this file for how to correctly
37
- # install packages from a specific channel.
38
- #
39
74
  # Options:
40
- # * :force -- Force installation, needed when installing unstable packages
75
+ # * :perl -- Command to use as the Perl interpreter, otherwise defaults to the one specified during #setup or to "perl"
41
76
  #
42
77
  # See AutomateIt::PackageManager#install
43
78
  def install(*packages)
44
79
  return _install_helper(*packages) do |list, opts|
45
- cmd = "#{CPAN_INSTALL} #{list.join(' ')}"
80
+ perl = opts[:perl] || self.perl
81
+ cmd = "#{perl} #{CPAN_INSTALL} #{list.join(' ')}"
46
82
  cmd << " > /dev/null" if opts[:quiet]
47
83
  cmd << " 2>&1"
48
84
 
@@ -50,10 +86,14 @@ class ::AutomateIt::PackageManager::CPAN < ::AutomateIt::PackageManager::BaseDri
50
86
  end
51
87
  end
52
88
 
89
+ # Options:
90
+ # * :perl -- Command to use as the Perl interpreter, otherwise defaults to the one specified during #setup or to "perl"
91
+ #
53
92
  # See AutomateIt::PackageManager#uninstall
54
93
  def uninstall(*packages)
55
94
  return _uninstall_helper(*packages) do |list, opts|
56
- cmd = "#{CPAN_UNINSTALL} #{list.join(' ')} < /dev/null"
95
+ perl = opts[:perl] || self.perl
96
+ cmd = "#{perl} #{CPAN_UNINSTALL} #{list.join(' ')} < /dev/null"
57
97
  cmd << " > /dev/null" if opts[:quiet]
58
98
  cmd << " 2>&1"
59
99
 
@@ -1,7 +1,7 @@
1
1
  # See AutomateIt::Interpreter for usage information.
2
2
  module AutomateIt # :nodoc:
3
3
  # AutomateIt version
4
- VERSION=Gem::Version.new("0.71221")
4
+ VERSION=Gem::Version.new("0.71226")
5
5
 
6
6
  # Instantiates a new Interpreter. See documentation for
7
7
  # Interpreter#setup.
@@ -0,0 +1,123 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ PACKAGE_FOUND_ERROR = %q{ERROR: Found the '%s' package installed for %s. You're probably not using this obscure package and should remove it so that this test can run. In the unlikely event that you actually rely on this package, change the spec to test with another unused package.}
4
+ PACKAGE_DRIVER_MISSING_ERROR = "NOTE: Can't check %s on this platform, #{__FILE__}"
5
+
6
+ if not INTERPRETER.euid?
7
+ puts "NOTE: Can't check 'euid' on this platform, #{__FILE__}"
8
+ elsif not INTERPRETER.superuser?
9
+ puts "NOTE: Must be root to check #{__FILE__}"
10
+ else
11
+ describe "AutomateIt::PackageManager", :shared => true do
12
+ before(:all) do
13
+ @level = Logger::WARN
14
+ @a = AutomateIt.new(:verbosity => @level)
15
+ @m = @a.package_manager
16
+ @fake_package = "not_a_real_package"
17
+ end
18
+
19
+ after(:all) do
20
+ @d.uninstall(@package, :quiet => true)
21
+ end
22
+
23
+ def uninstall_package(packages, opts={})
24
+ opts[:quiet] = true
25
+ return @d.uninstall(packages, opts)
26
+ end
27
+
28
+ def install_package(packages, opts={})
29
+ opts[:quiet] = true
30
+ opts[:force] = [:pecl, :pear].include?(@d.token)
31
+ return @d.install(packages, opts)
32
+ end
33
+
34
+ # Some specs below leave side-effects which others depend on, although
35
+ # these are clearly documented within the specs. This is necessary
36
+ # because doing proper setup/teardown for each test would make it run 5x
37
+ # slower and take over a minute. Although this approach is problematic,
38
+ # the performance boost is worth it.
39
+
40
+ it "should not install an invalid package" do
41
+ @d.log.silence(Logger::FATAL) do
42
+ lambda{ install_package(@fake_package) }.should raise_error(ArgumentError)
43
+ end
44
+ end
45
+
46
+ it "should install a package" do
47
+ install_package(@package).should be_true
48
+ # Leaves behind an installed package
49
+ end
50
+
51
+ it "should not re-install an installed package" do
52
+ # Expects package to be installed
53
+ install_package(@package).should be_false
54
+ end
55
+
56
+ it "should find an installed package" do
57
+ # Expects package to be installed
58
+ @d.installed?(@package).should be_true
59
+ @d.not_installed?(@package).should be_false
60
+ end
61
+
62
+ it "should not find a package that's not installed" do
63
+ @d.installed?(@fake_package).should be_false
64
+ @d.not_installed?(@fake_package).should be_true
65
+ end
66
+
67
+ it "should find group of packages" do
68
+ @d.installed?(@package, @fake_package, :details => true).should == [false, [@package]]
69
+ @d.not_installed?(@package, @fake_package, :details => true).should == [false, [@fake_package]]
70
+ # Leaves behind an installed package
71
+ end
72
+
73
+ it "should uninstall a package" do
74
+ # Expects package to be installed
75
+ uninstall_package(@package).should be_true
76
+ end
77
+
78
+ it "should not uninstall a package that's not installed" do
79
+ uninstall_package(@package).should be_false
80
+ end
81
+ end
82
+
83
+ #-----------------------------------------------------------------------
84
+
85
+ targets = {
86
+ # :apt => "nomarch", # Obscure package for extracting ARC files from the 80's
87
+ # :yum => "nomarch", # Obscure package for extracting ARC files from the 80's
88
+ # :portage => "arc", # Obscure package for extracting ARC files from the 80's
89
+ # :gem => "s33r", # Alpha-grade package its author deprecated in favor of another
90
+ # :egg => "_sre.py", # Slower reimplementation of ancient Python Regexps
91
+ # :pear => "File_DICOM", # Obscure package for DICOM X-rays, abandoned in 2003
92
+ # :pecl => "ecasound", # Obscure package for Ecasound libs, abandoned in 2003
93
+ :cpan => "Acme::please", # Insane gimmick port of intercal's please statements
94
+ }
95
+
96
+ if INTERPRETER.tagged?(:centos)
97
+ # CentOS lacks "nomarch", so use a less obscure archiver from the early 90's.
98
+ targets[:yum] = "arj"
99
+ end
100
+
101
+ targets.each_pair do |driver_token, package|
102
+ # Run the following from the shell to skip package tests:
103
+ # export AUTOMATEIT_SPEC_SKIP_PACKAGES=1
104
+ # Or clear it out:
105
+ # unset AUTOMATEIT_SPEC_SKIP_PACKAGES
106
+ next unless ENV["AUTOMATEIT_SPEC_SKIP_PACKAGES"].nil?
107
+
108
+ driver = INTERPRETER.package_manager[driver_token]
109
+ if driver.available?
110
+ describe driver.class.to_s do
111
+ it_should_behave_like "AutomateIt::PackageManager"
112
+
113
+ before(:all) do
114
+ @d = @m[driver_token]
115
+ @package = package
116
+ raise PACKAGE_FOUND_ERROR % [@package, @d.class] if @d.installed?(@package)
117
+ end
118
+ end
119
+ else
120
+ puts PACKAGE_DRIVER_MISSING_ERROR % driver.class
121
+ end
122
+ end
123
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: automateit
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.71221"
4
+ version: "0.71226"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igal Koshevoy
@@ -30,7 +30,7 @@ cert_chain:
30
30
  COR01yWDcVLdM89nNLk=
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2007-12-23 00:00:00 -08:00
33
+ date: 2007-12-26 00:00:00 -08:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
@@ -67,7 +67,7 @@ dependencies:
67
67
  requirements:
68
68
  - - ">="
69
69
  - !ruby/object:Gem::Version
70
- version: 1.3.0
70
+ version: 1.4.0
71
71
  version:
72
72
  description: AutomateIt is an open source tool for automating the setup and maintenance of servers, applications and their dependencies.
73
73
  email: igal@pragmaticraft.com
@@ -118,6 +118,7 @@ files:
118
118
  - helpers/cpan_is_installed.pl
119
119
  - helpers/cpan_uninstall.pl
120
120
  - helpers/which.cmd
121
+ - helpers/cpan_wrapper.pl
121
122
  - lib/hashcache.rb
122
123
  - lib/automateit.rb
123
124
  - lib/automateit/tag_manager.rb
@@ -232,6 +233,7 @@ files:
232
233
  - spec/integration/examples_spec_editor.rb
233
234
  - spec/integration/template_manager_erb_spec.rb
234
235
  - spec/integration/tempster_spec.rb
236
+ - spec/integration/package_manager_spec.rb.orig
235
237
  - spec/breaker.rb
236
238
  - spec/extras/scratch.rb
237
239
  - spec/extras/automateit_service_sysv_test
@@ -302,6 +304,7 @@ test_files:
302
304
  - spec/integration/examples_spec_editor.rb
303
305
  - spec/integration/template_manager_erb_spec.rb
304
306
  - spec/integration/tempster_spec.rb
307
+ - spec/integration/package_manager_spec.rb.orig
305
308
  - spec/breaker.rb
306
309
  - spec/extras
307
310
  - spec/extras/scratch.rb
metadata.gz.sig CHANGED
@@ -1,2 +1 @@
1
- Mlɏ�S�f]�� m�H^`R����,L�ꧩ��2
2
- �;~'�=-iVȢ�]凿��Ը
1
+ �,s�͢#u���Ofg�z���G�o��z���x��&� L�1R����l�S�[^���:����_p�Ku�V���a�qE���,��>�yp?O�h�JO��q��,zC ��,�����6ꓷ�?�4wOq,:�kƱe�� ���:{6��a7�m�WU��~�Ś����s�ɧ�HMK�������>؎u����W*�/ƛ��`��A,u��v#ݝ������6��,V�tM��#V���|