raggi-rubyw_helper 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.1.0 / 2008-12-24
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
@@ -0,0 +1,20 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/rubyw_helper.rb
6
+ spec/.bacon
7
+ spec/helper.rb
8
+ spec/runner
9
+ spec/spec_rubyw_helper.rb
10
+ tasks/autospec.rake
11
+ tasks/bacon.rake
12
+ tasks/bones.rake
13
+ tasks/gem.rake
14
+ tasks/git.rake
15
+ tasks/manifest.rake
16
+ tasks/notes.rake
17
+ tasks/post_load.rake
18
+ tasks/rdoc.rake
19
+ tasks/rubyforge.rake
20
+ tasks/setup.rb
@@ -0,0 +1,88 @@
1
+ = rubyw_helper
2
+ by James Tucker
3
+ http://ra66i.org
4
+ http://github.com/raggi/rubyw_helper
5
+
6
+ == DESCRIPTION:
7
+
8
+ A simple redirector for use when you just want to safely redirect stdio.
9
+ Simply encapsulates a few different safety mechanisms when redirecting stdio,
10
+ with the primary goal of making it easier to write apps that run under
11
+ rubyw.exe, where ruby loads with stdio closed.
12
+
13
+ Whilst the primary intention for use is under win32, and was actually
14
+ developed as an external helper for specifically win32-service usage, this gem
15
+ may be useful to some other folks on other platforms. It is not win32
16
+ specific.
17
+
18
+ == FEATURES/PROBLEMS:
19
+
20
+ * Lacking any tertiary logging infrastructure specific to any platform.
21
+
22
+ == SYNOPSIS:
23
+
24
+ The following parameters are also the defaults:
25
+
26
+ stdout = File.join(Dir.pwd, 'logs', "#{app_name}.stdout.log"),
27
+ stderr = File.join(Dir.pwd, 'logs', "#{app_name}.stderr.log")
28
+ stdin = case RUBY_PLATFORM
29
+ when /mingw|mswin/
30
+ 'NUL:'
31
+ else
32
+ '/dev/null'
33
+ end
34
+
35
+ helper = RubywHelper.new(stdout, stderr, stdin)
36
+
37
+ You achieve basic redirection if you wrap your runner for your program in the
38
+ with_redirection block:
39
+
40
+ helper.with_redirection do
41
+ puts "hello logfile!"
42
+ end
43
+
44
+ Or you can simply just redirect them:
45
+
46
+ helper.redirect_stdio!
47
+
48
+ For your convenience, there is also a method which attempts to see if it may
49
+ be a good idea to redirect stdio, in other words, it returns true if all of
50
+ stdio is closed:
51
+
52
+ helper.stdio_danger?
53
+
54
+ This typically returns true under rubyw.exe and any equivalents.
55
+
56
+ == REQUIREMENTS:
57
+
58
+ * Ruby
59
+ * gem inst exception_string
60
+
61
+ == INSTALL:
62
+
63
+ * gem inst rubyw_helper
64
+
65
+ == LICENSE:
66
+
67
+ (The MIT License)
68
+
69
+ Copyright (c) 2008 James Tucker
70
+
71
+ Permission is hereby granted, free of charge, to any person obtaining
72
+ a copy of this software and associated documentation files (the
73
+ 'Software'), to deal in the Software without restriction, including
74
+ without limitation the rights to use, copy, modify, merge, publish,
75
+ distribute, sublicense, and/or sell copies of the Software, and to
76
+ permit persons to whom the Software is furnished to do so, subject to
77
+ the following conditions:
78
+
79
+ The above copyright notice and this permission notice shall be
80
+ included in all copies or substantial portions of the Software.
81
+
82
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
83
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
84
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
85
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
86
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
87
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
88
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ load 'tasks/setup.rb'
2
+
3
+ ensure_in_path 'lib'
4
+ require 'rubyw_helper'
5
+
6
+ task :default => 'spec:run'
7
+
8
+ PROJ.name = 'rubyw_helper'
9
+ PROJ.authors = 'James Tucker'
10
+ PROJ.email = 'raggi@rubyforge.org'
11
+ PROJ.url = 'http://github.com/raggi/rubyw_helper'
12
+ PROJ.rubyforge.name = 'libraggi'
13
+ PROJ.version = RubywHelper.version
14
+ PROJ.gem.dependencies << 'exception_string'
15
+
16
+ PROJ.exclude = %w(tmp$ bak$ ~$ CVS \.git \.hg \.svn ^pkg ^doc \.DS_Store \.cvs
17
+ \.svn \.hgignore \.gitignore \.dotest \.swp$ ~$ \.bin$ \.h$ \.rc$ \.res$)
@@ -0,0 +1,127 @@
1
+ require 'fileutils'
2
+ require 'exception_string'
3
+
4
+ class RubywHelper
5
+
6
+ Version = VERSION = '0.1.5'
7
+ def self.version; Version; end
8
+
9
+ app_name = File.basename($0)
10
+ Defaults = {
11
+ :out => File.join(Dir.pwd, 'logs', "#{app_name}.stdout.log"),
12
+ :err => File.join(Dir.pwd, 'logs', "#{app_name}.stderr.log"),
13
+ :in => case RUBY_PLATFORM
14
+ when /mingw|mswin/
15
+ 'NUL:'
16
+ else
17
+ '/dev/null'
18
+ end
19
+ }
20
+
21
+ attr_reader :old_out, :old_err, :old_in
22
+
23
+ # out replaces $stdout, err replaces $stderr, inn replaces $stdin, simple.
24
+ # provide nils / false to use the Defaults
25
+ def initialize(out = nil, err = nil, inn = nil)
26
+ @stdout, @stderr = out || Defaults[:out], err || Defaults[:err]
27
+ @stdin = inn || Defaults[:in]
28
+ @old_out, @old_err, @old_in = $stdout, $stderr, $stdin
29
+ end
30
+
31
+ # Returns true for the two common cases when you would not receive data from
32
+ # stdout, stderr and stdin, because they're nulled out in some way, closed,
33
+ # or in some other way unusable. This specific implementation provides
34
+ # checks for rubyw.exe behavior, where all IOs are closed, and Win32::Daemon
35
+ # behavior, where they're all nulled.
36
+ # Sometimes may not be accurate, recommendation is to redirect by
37
+ # configuration, and use this as a guide only where appropriate.
38
+ def stdio_danger?
39
+ # rubyw.exe running as a user:
40
+ $stdout.closed? && $stderr.closed? && $stdin.closed? ||
41
+ # rubyw.exe + Win32::Daemon started:
42
+ [$stdout, $stderr, $stdin].all? { |io| io.inspect =~ /NUL/ } ||
43
+ # rubyw.exe running as SYSTEM, pre Win32::Daemon started:
44
+ begin
45
+ open("CONIN$") {}
46
+ open("CONOUT$", "w") {}
47
+ false
48
+ rescue SystemCallError
49
+ true
50
+ end
51
+ end
52
+
53
+ # Takes a block, because under these conditions, it really helps developers
54
+ # if best effort is made to try and log error conditions to the files before
55
+ # leaving the process.
56
+ def with_redirection
57
+ ensure_files!
58
+ redirect_stdio!
59
+ yield
60
+ restore_stdio!
61
+ rescue Exception => exception
62
+ fatal! exception.to_s_mri
63
+ end
64
+
65
+ # Sets up the global IO objects to point to where we want.
66
+ def redirect_stdio!
67
+ inn, out, err = open(@stdin), open(@stdout, 'a+'), open(@stderr, 'a+')
68
+ no_warn do
69
+ $stdin = Object.const_set(:STDIN, inn)
70
+ $stdout = Object.const_set(:STDOUT, out)
71
+ $stderr = Object.const_set(:STDERR, err)
72
+ end
73
+ end
74
+
75
+ def restore_stdio!
76
+ no_warn do
77
+ $stdin = Object.const_set(:STDIN, @old_in)
78
+ $stdout = Object.const_set(:STDOUT, @old_out)
79
+ $stderr = Object.const_set(:STDERR, @old_err)
80
+ end
81
+ end
82
+
83
+ private
84
+ # Tries to create any containing directories, and errors out if we can't
85
+ # write to the outputs or read from the input.
86
+ def ensure_files!
87
+ fatal! "Cannot read from #{@stdin}" unless File.readable? @stdin
88
+ [@stdout, @stderr].each do |f|
89
+ dir = File.dirname(f)
90
+ safely do
91
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
92
+ open(f, 'w') {} unless File.exists?(f)
93
+ end
94
+ next if File.writable? f
95
+ fatal! "Cannot write to #{f}"
96
+ end
97
+ end
98
+
99
+ # For each output io, safely wrap the given block, and yield the io.
100
+ def safe_each
101
+ [$stderr, $stdout].each { |io| safely { yield io } }
102
+ end
103
+
104
+ # Tries real hard to log the message, then exits with failure status.
105
+ def fatal!(message)
106
+ # Not using safe_each in case that caused an error.
107
+ safely { $stdout.reopen(@stdout, 'a+'); $stdout.puts message }
108
+ safely { $stderr.reopen(@stderr, 'a+'); $stderr.puts message }
109
+ exit 1
110
+ end
111
+
112
+ # Ignores errors, which we might not be able to avoid.
113
+ def safely
114
+ yield
115
+ rescue Exception
116
+ nil
117
+ end
118
+
119
+ # Suppress warnings, most useful for constant redefinition.
120
+ def no_warn
121
+ verbose = $VERBOSE
122
+ $VERBOSE = nil
123
+ yield
124
+ ensure
125
+ $VERBOSE = verbose
126
+ end
127
+ end
File without changes
@@ -0,0 +1,16 @@
1
+ # Disable test/unit and rspec from running, in case loaded by broken tools.
2
+ Test::Unit.run = false if defined?(Test) && defined?(Test::Unit)
3
+ Spec::run = false if defined?(Spec) && Spec::respond_to?(:run=)
4
+
5
+ # Setup a nice testing environment
6
+ $DEBUG, $TESTING = true, true
7
+ $:.push File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ $:.uniq!
9
+
10
+ %w[rubygems bacon].each { |r| require r }
11
+
12
+ # Bacon doesn't do any automagic, so lets tell it to!
13
+ Bacon.summary_on_exit
14
+
15
+ require File.expand_path(
16
+ File.join(File.dirname(__FILE__), %w[.. lib rubyw_helper]))
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ __DIR__ = File.dirname(__FILE__)
3
+ __APP__ = File.expand_path(__DIR__ + '/../')
4
+
5
+ puts
6
+ Dir.chdir(__APP__) do
7
+ files = ARGV.empty? ? Dir.glob('{test,spec}/**/{test,spec}_*.rb') : ARGV
8
+ files.each { |f| require f }
9
+ end
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+ require 'stringio'
3
+ require 'tempfile'
4
+
5
+ describe "RubywHelper" do
6
+
7
+ def temp_io
8
+ stdin = case RUBY_PLATFORM
9
+ when /mingw|mswin/
10
+ 'NUL:'
11
+ else
12
+ '/dev/null'
13
+ end
14
+ tmp_io = %W(
15
+ /tmp/rubyw_helper_test_stdout.log
16
+ /tmp/rubyw_helper_test_stderr.log
17
+ )
18
+ tmp_io.each { |f| open(f, 'w') {} }
19
+ yield tmp_io + [stdin]
20
+ ensure
21
+ tmp_io.each { |f| File.delete(f) }
22
+ end
23
+
24
+ should "have stdio_danger? when stdout, stderr, and stdin are closed" do
25
+ $stdout, $stderr, $stdin = Array.new(3) { s = StringIO.new(''); s.close; s }
26
+ RubywHelper.new.stdio_danger?.should.eql true
27
+ $stdout, $stderr, $stdin = STDOUT, STDERR, STDIN
28
+ end
29
+
30
+ should "have stdio_danger? when stdout, stderr, and stdin are all nulled" do
31
+ $stdout, $stderr, $stdin = Array.new(3) do
32
+ s = StringIO.new('')
33
+ def s.inspect
34
+ '#<IO:NUL>'
35
+ end
36
+ s
37
+ end
38
+ RubywHelper.new.stdio_danger?.should.eql true
39
+ $stdout, $stderr, $stdin = STDOUT, STDERR, STDIN
40
+ end
41
+
42
+ should "restore the old stdios" do
43
+ oout, oerr, oin = $stdout, $stderr, $stdin
44
+ h = RubywHelper.new
45
+ $stdout, $stderr, $stdin = Array.new(3) do
46
+ s = StringIO.new('')
47
+ s.close
48
+ s
49
+ end
50
+ h.restore_stdio!
51
+ $stdout.should.eql oout
52
+ $stderr.should.eql oerr
53
+ $stdin.should.eql oin
54
+ end
55
+
56
+ should "redirect to the appropriate files and restore stdio afterward" do
57
+ oout, oerr, oin = $stdout, $stderr, $stdin
58
+ temp_io do |out, err, inn|
59
+ h = RubywHelper.new(out, err, inn)
60
+ h.with_redirection do
61
+ $stdout.path.should.eql out
62
+ $stderr.path.should.eql err
63
+ $stdin.path.should.eql inn
64
+ STDOUT.path.should.eql out
65
+ STDERR.path.should.eql err
66
+ STDIN.path.should.eql inn
67
+ $stdout.puts "1234567890"
68
+ $stderr.puts "1234567890"
69
+ [$stdin, $stderr, $stdout].each { |io| io.close unless io.closed? }
70
+ end
71
+ $stdout.should.eql oout
72
+ $stderr.should.eql oerr
73
+ $stdin.should.eql oin
74
+ STDOUT.should.eql oout
75
+ STDERR.should.eql oerr
76
+ STDIN.should.eql oin
77
+ File.read(out).should.eql("1234567890\n")
78
+ File.read(err).should.eql("1234567890\n")
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,33 @@
1
+ # Poor mans autotest, for when you absolutely positively, just need an autotest.
2
+ # N.B. Uses a runner under test/ or spec/, so you can customize the runtime.
3
+ # Thanks to manveru for this!
4
+ desc "Run specs every time a file changes in lib or spec"
5
+ task :autospec do
6
+ rb = Gem.ruby rescue nil
7
+ rb ||= (require 'rbconfig'; File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']))
8
+ command = 'spec/runner' if test ?e, 'spec/runner'
9
+ command ||= 'test/runner' if test ?e, 'test/runner'
10
+ files = Dir.glob('{lib,spec,test}/**/*.rb')
11
+ mtimes = {}
12
+ sigtrap = proc { puts "\rDo that again, I dare you!"; trap(:INT){ exit 0 }; sleep 0.8; trap(:INT, &sigtrap) }
13
+ trap(:INT, &sigtrap)
14
+ system "#{rb} -I#{GSpec.require_path} #{command}"
15
+ while file = files.shift
16
+ begin
17
+ mtime = File.mtime(file)
18
+ mtimes[file] ||= mtime
19
+ if mtime > mtimes[file]
20
+ files = Dir.glob('{lib,spec,test}/**/*.rb') - [file] # refresh the file list.
21
+ puts
22
+ system "#{rb} -I#{GSpec.require_path} #{command} #{file}"
23
+ puts
24
+ end
25
+ mtimes[file] = mtime
26
+ files << file
27
+ rescue Exception
28
+ retry
29
+ end
30
+ # print "\rChecking: #{file.ljust((ENV['COLUMNS']||80)-11)}";$stdout.flush
31
+ sleep 0.2
32
+ end
33
+ end
@@ -0,0 +1,7 @@
1
+ desc "Run the executable test specifications"
2
+ task :spec do
3
+ ruby 'spec/runner'
4
+ end
5
+
6
+ desc "Run the executable test specifications"
7
+ task :test => :spec
@@ -0,0 +1,21 @@
1
+ # $Id$
2
+
3
+ if HAVE_BONES
4
+
5
+ namespace :bones do
6
+
7
+ desc 'Show the PROJ open struct'
8
+ task :debug do |t|
9
+ atr = if t.application.top_level_tasks.length == 2
10
+ t.application.top_level_tasks.pop
11
+ end
12
+
13
+ if atr then Bones::Debug.show_attr(PROJ, atr)
14
+ else Bones::Debug.show PROJ end
15
+ end
16
+
17
+ end # namespace :bones
18
+
19
+ end # HAVE_BONES
20
+
21
+ # EOF
@@ -0,0 +1,138 @@
1
+ # $Id$
2
+
3
+ require 'rake/gempackagetask'
4
+
5
+ namespace :gem do
6
+
7
+ PROJ.gem._spec = Gem::Specification.new do |s|
8
+ s.name = PROJ.name
9
+ s.version = PROJ.version
10
+ s.summary = PROJ.summary
11
+ s.authors = Array(PROJ.authors)
12
+ s.email = PROJ.email
13
+ s.homepage = Array(PROJ.url).first
14
+ s.rubyforge_project = PROJ.rubyforge.name
15
+
16
+ s.description = PROJ.description
17
+
18
+ PROJ.gem.dependencies.each do |dep|
19
+ s.add_dependency(*dep)
20
+ end
21
+ PROJ.gem.development_dependencies.each do |dep|
22
+ s.add_development_dependency(*dep)
23
+ end
24
+
25
+ s.files = PROJ.gem.files
26
+ s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
27
+ s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/
28
+
29
+ s.bindir = 'bin'
30
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
31
+ s.require_paths = dirs unless dirs.empty?
32
+
33
+ incl = Regexp.new(PROJ.rdoc.include.join('|'))
34
+ excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
35
+ excl = Regexp.new(excl.join('|'))
36
+ rdoc_files = PROJ.gem.files.find_all do |fn|
37
+ case fn
38
+ when excl; false
39
+ when incl; true
40
+ else false end
41
+ end
42
+ s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
43
+ s.extra_rdoc_files = rdoc_files
44
+ s.has_rdoc = true
45
+
46
+ if test ?f, PROJ.test.file
47
+ s.test_file = PROJ.test.file
48
+ else
49
+ s.test_files = PROJ.test.files.to_a
50
+ end
51
+
52
+ # Do any extra stuff the user wants
53
+ PROJ.gem.extras.each do |msg, val|
54
+ case val
55
+ when Proc
56
+ val.call(s.send(msg))
57
+ else
58
+ s.send "#{msg}=", val
59
+ end
60
+ end
61
+ end # Gem::Specification.new
62
+
63
+ # A prerequisites task that all other tasks depend upon
64
+ task :prereqs
65
+
66
+ desc 'Show information about the gem'
67
+ task :debug => 'gem:prereqs' do
68
+ puts PROJ.gem._spec.to_ruby
69
+ end
70
+
71
+ pkg = Rake::PackageTask.new(PROJ.name, PROJ.version) do |pkg|
72
+ pkg.need_tar = PROJ.gem.need_tar
73
+ pkg.need_zip = PROJ.gem.need_zip
74
+ pkg.package_files += PROJ.gem._spec.files
75
+ end
76
+ Rake::Task['gem:package'].instance_variable_set(:@full_comment, nil)
77
+
78
+ gem_file = if PROJ.gem._spec.platform == Gem::Platform::RUBY
79
+ "#{pkg.package_name}.gem"
80
+ else
81
+ "#{pkg.package_name}-#{PROJ.gem._spec.platform}.gem"
82
+ end
83
+
84
+ desc "Build the gem file #{gem_file}"
85
+ task :package => ['gem:prereqs', "#{pkg.package_dir}/#{gem_file}"]
86
+
87
+ file "#{pkg.package_dir}/#{gem_file}" => [pkg.package_dir] + PROJ.gem._spec.files do
88
+ when_writing("Creating GEM") {
89
+ Gem::Builder.new(PROJ.gem._spec).build
90
+ verbose(true) {
91
+ mv gem_file, "#{pkg.package_dir}/#{gem_file}"
92
+ }
93
+ }
94
+ end
95
+
96
+ desc 'Install the gem'
97
+ task :install => [:clobber, 'gem:package'] do
98
+ sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
99
+
100
+ # use this version of the command for rubygems > 1.0.0
101
+ #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
102
+ end
103
+
104
+ desc 'Uninstall the gem'
105
+ task :uninstall do
106
+ installed_list = Gem.source_index.find_name(PROJ.name)
107
+ if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
108
+ sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
109
+ end
110
+ end
111
+
112
+ desc 'Reinstall the gem'
113
+ task :reinstall => [:uninstall, :install]
114
+
115
+ desc 'Cleanup the gem'
116
+ task :cleanup do
117
+ sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
118
+ end
119
+
120
+ file "#{PROJ.name}.gemspec" => PROJ.gem._spec.files do |t|
121
+ open(t.name, 'w') { |f| f.write PROJ.gem._spec.to_ruby }
122
+ end
123
+ CLOBBER.include("#{PROJ.name}.gemspec")
124
+
125
+ desc 'Generate gemspec'
126
+ task :spec => "#{PROJ.name}.gemspec"
127
+ task :release => :spec
128
+
129
+ end # namespace :gem
130
+
131
+ desc 'Alias to gem:package'
132
+ task :gem => 'gem:package'
133
+
134
+ task :clobber => 'gem:clobber_package'
135
+
136
+ remove_desc_for_task %w(gem:clobber_package)
137
+
138
+ # EOF
@@ -0,0 +1,41 @@
1
+ # $Id$
2
+
3
+ if HAVE_GIT
4
+
5
+ namespace :git do
6
+
7
+ # A prerequisites task that all other tasks depend upon
8
+ task :prereqs
9
+
10
+ desc 'Show tags from the Git repository'
11
+ task :show_tags => 'git:prereqs' do |t|
12
+ puts %x/git tag/
13
+ end
14
+
15
+ desc 'Create a new tag in the Git repository'
16
+ task :create_tag => 'git:prereqs' do |t|
17
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
18
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
19
+
20
+ tag = "%s-%s" % [PROJ.name, PROJ.version]
21
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
22
+
23
+ puts "Creating Git tag '#{tag}'"
24
+ unless system "git tag -a -m '#{msg}' #{tag}"
25
+ abort "Tag creation failed"
26
+ end
27
+
28
+ if %x/git remote/ =~ %r/^origin\s*$/
29
+ unless system "git push origin #{tag}"
30
+ abort "Could not push tag to remote Git repository"
31
+ end
32
+ end
33
+ end
34
+
35
+ end # namespace :git
36
+
37
+ task 'gem:release' => 'git:create_tag'
38
+
39
+ end # if HAVE_GIT
40
+
41
+ # EOF
@@ -0,0 +1,49 @@
1
+ # $Id$
2
+
3
+ require 'find'
4
+
5
+ namespace :manifest do
6
+
7
+ desc 'Verify the manifest'
8
+ task :check do
9
+ fn = PROJ.manifest_file + '.tmp'
10
+ files = manifest_files
11
+
12
+ File.open(fn, 'w') {|fp| fp.puts files}
13
+ lines = %x(#{DIFF} -du #{PROJ.manifest_file} #{fn}).split("\n")
14
+ if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
15
+ lines.map! do |line|
16
+ case line
17
+ when %r/^(-{3}|\+{3})/; nil
18
+ when %r/^@/; Console::ANSICode.blue line
19
+ when %r/^\+/; Console::ANSICode.green line
20
+ when %r/^\-/; Console::ANSICode.red line
21
+ else line end
22
+ end
23
+ end
24
+ puts lines.compact
25
+ rm fn rescue nil
26
+ end
27
+
28
+ desc 'Create a new manifest'
29
+ task :create do
30
+ files = manifest_files
31
+ unless test(?f, PROJ.manifest_file)
32
+ files << PROJ.manifest_file
33
+ files.sort!
34
+ end
35
+ File.open(PROJ.manifest_file, 'w') {|fp| fp.puts files}
36
+ end
37
+
38
+ task :assert do
39
+ files = manifest_files
40
+ manifest = File.read(PROJ.manifest_file).split($/)
41
+ raise "ERROR: #{PROJ.manifest_file} is out of date" unless files == manifest
42
+ end
43
+
44
+ end # namespace :manifest
45
+
46
+ desc 'Alias to manifest:check'
47
+ task :manifest => 'manifest:check'
48
+
49
+ # EOF
@@ -0,0 +1,28 @@
1
+ # $Id$
2
+
3
+ if HAVE_BONES
4
+
5
+ desc "Enumerate all annotations"
6
+ task :notes do |t|
7
+ id = if t.application.top_level_tasks.length > 1
8
+ t.application.top_level_tasks.slice!(1..-1).join(' ')
9
+ end
10
+ Bones::AnnotationExtractor.enumerate(
11
+ PROJ, PROJ.notes.tags.join('|'), id, :tag => true)
12
+ end
13
+
14
+ namespace :notes do
15
+ PROJ.notes.tags.each do |tag|
16
+ desc "Enumerate all #{tag} annotations"
17
+ task tag.downcase.to_sym do |t|
18
+ id = if t.application.top_level_tasks.length > 1
19
+ t.application.top_level_tasks.slice!(1..-1).join(' ')
20
+ end
21
+ Bones::AnnotationExtractor.enumerate(PROJ, tag, id)
22
+ end
23
+ end
24
+ end
25
+
26
+ end # if HAVE_BONES
27
+
28
+ # EOF
@@ -0,0 +1,39 @@
1
+ # $Id$
2
+
3
+ # This file does not define any rake tasks. It is used to load some project
4
+ # settings if they are not defined by the user.
5
+
6
+ PROJ.rdoc.main ||= PROJ.readme_file
7
+ PROJ.rdoc.dir ||= File.join('doc', PROJ.name)
8
+
9
+ PROJ.rdoc.exclude << "^#{Regexp.escape(PROJ.manifest_file)}$"
10
+ PROJ.exclude << ["^#{Regexp.escape(PROJ.rdoc.dir)}/",
11
+ "^#{Regexp.escape(PROJ.rcov.dir)}/"]
12
+
13
+ flatten_arrays = lambda do |this,os|
14
+ os.instance_variable_get(:@table).each do |key,val|
15
+ next if key == :dependencies
16
+ case val
17
+ when Array; val.flatten!
18
+ when OpenStruct; this.call(this,val)
19
+ end
20
+ end
21
+ end
22
+ flatten_arrays.call(flatten_arrays,PROJ)
23
+
24
+ PROJ.changes ||= paragraphs_of(PROJ.history_file, 0..1).join("\n\n")
25
+
26
+ PROJ.description ||= paragraphs_of(PROJ.readme_file, 'description').join("\n\n")
27
+
28
+ PROJ.summary ||= PROJ.description.split('.').first
29
+
30
+ PROJ.gem.files ||=
31
+ if test(?f, PROJ.manifest_file)
32
+ files = File.readlines(PROJ.manifest_file).map {|fn| fn.chomp.strip}
33
+ files.delete ''
34
+ files
35
+ else [] end
36
+
37
+ PROJ.gem.executables ||= PROJ.gem.files.find_all {|fn| fn =~ %r/^bin/}
38
+
39
+ # EOF
@@ -0,0 +1,55 @@
1
+ # $Id$
2
+
3
+ begin
4
+ require 'hanna/rdoctask'
5
+ rescue LoadError
6
+ require 'rake/rdoctask'
7
+ end
8
+
9
+ namespace :doc do
10
+
11
+ desc 'Generate RDoc documentation'
12
+ Rake::RDocTask.new do |rd|
13
+ rdoc = PROJ.rdoc
14
+ rd.main = rdoc.main
15
+ rd.rdoc_dir = rdoc.dir
16
+
17
+ incl = Regexp.new(rdoc.include.join('|'))
18
+ excl = Regexp.new(rdoc.exclude.join('|'))
19
+ files = PROJ.gem.files.find_all do |fn|
20
+ case fn
21
+ when excl; false
22
+ when incl; true
23
+ else false end
24
+ end
25
+ rd.rdoc_files.push(*files)
26
+
27
+ title = "#{PROJ.name}-#{PROJ.version} Documentation"
28
+
29
+ rf_name = PROJ.rubyforge.name
30
+ title = "#{rf_name}'s " + title if rf_name.valid? and rf_name != title
31
+
32
+ rd.options << "-t #{title}"
33
+ rd.options.concat(rdoc.opts)
34
+ end
35
+
36
+ desc 'Generate ri locally for testing'
37
+ task :ri => :clobber_ri do
38
+ sh "#{RDOC} --ri -o ri ."
39
+ end
40
+
41
+ task :clobber_ri do
42
+ rm_r 'ri' rescue nil
43
+ end
44
+
45
+ end # namespace :doc
46
+
47
+ desc 'Alias to doc:rdoc'
48
+ task :doc => 'doc:rdoc'
49
+
50
+ desc 'Remove all build products'
51
+ task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
52
+
53
+ remove_desc_for_task %w(doc:clobber_rdoc)
54
+
55
+ # EOF
@@ -0,0 +1,57 @@
1
+
2
+ if PROJ.rubyforge.name.valid? && HAVE_RUBYFORGE
3
+
4
+ require 'rubyforge'
5
+ require 'rake/contrib/sshpublisher'
6
+
7
+ namespace :gem do
8
+ desc 'Package and upload to RubyForge'
9
+ task :release => [:clobber, 'gem:package'] do |t|
10
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
11
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
12
+ pkg = "pkg/#{PROJ.gem._spec.full_name}"
13
+
14
+ if $DEBUG then
15
+ puts "release_id = rf.add_release #{PROJ.rubyforge.name.inspect}, #{PROJ.name.inspect}, #{PROJ.version.inspect}, \"#{pkg}.tgz\""
16
+ puts "rf.add_file #{PROJ.rubyforge.name.inspect}, #{PROJ.name.inspect}, release_id, \"#{pkg}.gem\""
17
+ end
18
+
19
+ rf = RubyForge.new
20
+ rf.configure rescue nil
21
+ puts 'Logging in'
22
+ rf.login
23
+
24
+ c = rf.userconfig
25
+ c['release_notes'] = PROJ.description if PROJ.description
26
+ c['release_changes'] = PROJ.changes if PROJ.changes
27
+ c['preformatted'] = true
28
+
29
+ files = [(PROJ.gem.need_tar ? "#{pkg}.tgz" : nil),
30
+ (PROJ.gem.need_zip ? "#{pkg}.zip" : nil),
31
+ "#{pkg}.gem"].compact
32
+
33
+ puts "Releasing #{PROJ.name} v. #{PROJ.version}"
34
+ rf.add_release PROJ.rubyforge.name, PROJ.name, PROJ.version, *files
35
+ end
36
+ end # namespace :gem
37
+
38
+
39
+ namespace :doc do
40
+ desc "Publish RDoc to RubyForge"
41
+ task :release => %w(doc:clobber_rdoc doc:rdoc) do
42
+ config = YAML.load(
43
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
44
+ )
45
+
46
+ host = "#{config['username']}@rubyforge.org"
47
+ remote_dir = "/var/www/gforge-projects/#{PROJ.rubyforge.name}/"
48
+ remote_dir << PROJ.rdoc.remote_dir if PROJ.rdoc.remote_dir
49
+ local_dir = File.dirname(PROJ.rdoc.dir)
50
+
51
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
52
+ end
53
+ end # namespace :doc
54
+
55
+ end # if HAVE_RUBYFORGE
56
+
57
+ # EOF
@@ -0,0 +1,238 @@
1
+ # $Id$
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'rake/clean'
6
+ require 'fileutils'
7
+ require 'ostruct'
8
+
9
+ class OpenStruct; undef :gem; end
10
+
11
+ PROJ = OpenStruct.new(
12
+ # Project Defaults
13
+ :name => nil,
14
+ :summary => nil,
15
+ :description => nil,
16
+ :changes => nil,
17
+ :authors => nil,
18
+ :email => nil,
19
+ :url => "\000",
20
+ :version => ENV['VERSION'] || '0.0.0',
21
+ :exclude => %w(tmp$ bak$ ~$ CVS \.git/ \.hg/ \.svn/ ^pkg/ ^doc/ \.DS_Store
22
+ \.hgignore \.gitignore \.dotest \.swp$ .*\.gemspec$),
23
+ :release_name => ENV['RELEASE'],
24
+
25
+ # System Defaults
26
+ :ruby_opts => %w(-w),
27
+ :libs => [],
28
+ :history_file => 'History.txt',
29
+ :manifest_file => 'Manifest.txt',
30
+ :readme_file => 'README.rdoc',
31
+
32
+ # Gem Packaging
33
+ :gem => OpenStruct.new(
34
+ :dependencies => [],
35
+ :development_dependencies => ['rake', 'bones', 'bacon'],
36
+ :executables => nil,
37
+ :extensions => FileList['ext/**/extconf.rb'],
38
+ :files => nil,
39
+ :need_tar => true,
40
+ :need_zip => false,
41
+ :extras => {}
42
+ ),
43
+
44
+ # File Annotations
45
+ :notes => OpenStruct.new(
46
+ :exclude => %w(^tasks/setup\.rb$),
47
+ :extensions => %w(.txt .rb .erb .rdoc) << '',
48
+ :tags => %w(FIXME OPTIMIZE TODO)
49
+ ),
50
+
51
+ # Rcov
52
+ :rcov => OpenStruct.new(
53
+ :dir => 'coverage',
54
+ :opts => %w[--sort coverage -T],
55
+ :threshold => 90.0,
56
+ :threshold_exact => false
57
+ ),
58
+
59
+ # Rdoc
60
+ :rdoc => OpenStruct.new(
61
+ :opts => [],
62
+ :include => %w(^lib/ ^bin/ ^ext/ \.txt$ \.rdoc$),
63
+ :exclude => %w(extconf\.rb$),
64
+ :main => nil,
65
+ :dir => nil,
66
+ :remote_dir => nil
67
+ ),
68
+
69
+ # Rubyforge
70
+ :rubyforge => OpenStruct.new(
71
+ :name => "\000"
72
+ ),
73
+
74
+ # Tests
75
+ :test => OpenStruct.new(
76
+ :files => FileList['{test,spec}/{{test,spec}_*.rb,*_spec.rb}'],
77
+ :file => '',
78
+ :opts => []
79
+ )
80
+ )
81
+
82
+ # Load the other rake files in the tasks folder
83
+ rakefiles = Dir.glob('tasks/*.rake').sort
84
+ rakefiles.unshift(rakefiles.delete('tasks/post_load.rake')).compact!
85
+ import(*rakefiles)
86
+
87
+ # Setup the project libraries
88
+ %w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
89
+
90
+ # Setup some constants
91
+ WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM unless defined? WIN32
92
+
93
+ DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
94
+
95
+ def quiet( &block )
96
+ io = [STDOUT.dup, STDERR.dup]
97
+ STDOUT.reopen DEV_NULL
98
+ STDERR.reopen DEV_NULL
99
+ block.call
100
+ ensure
101
+ STDOUT.reopen io.first
102
+ STDERR.reopen io.last
103
+ $stdout, $stderr = STDOUT, STDERR
104
+ end
105
+
106
+ DIFF = if WIN32 then 'diff.exe'
107
+ else
108
+ if quiet {system "gdiff", __FILE__, __FILE__} then 'gdiff'
109
+ else 'diff' end
110
+ end unless defined? DIFF
111
+
112
+ SUDO = if WIN32 then ''
113
+ else
114
+ if quiet {system 'which sudo'} then 'sudo'
115
+ else '' end
116
+ end
117
+
118
+ RCOV = WIN32 ? 'rcov.bat' : 'rcov'
119
+ RDOC = WIN32 ? 'rdoc.bat' : 'rdoc'
120
+ GEM = WIN32 ? 'gem.bat' : 'gem'
121
+
122
+ %w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
123
+ begin
124
+ require lib
125
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
126
+ rescue LoadError
127
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", false}
128
+ end
129
+ end
130
+ HAVE_SVN = (Dir.entries(Dir.pwd).include?('.svn') and
131
+ system("svn --version 2>&1 > #{DEV_NULL}"))
132
+ HAVE_GIT = (Dir.entries(Dir.pwd).include?('.git') and
133
+ system("git --version 2>&1 > #{DEV_NULL}"))
134
+
135
+ # Reads a file at +path+ and spits out an array of the +paragraphs+
136
+ # specified.
137
+ #
138
+ # changes = paragraphs_of('History.txt', 0..1).join("\n\n")
139
+ # summary, *description = paragraphs_of('README.rdoc', 3, 3..8)
140
+ #
141
+ def paragraphs_of( path, *paragraphs )
142
+ title = String === paragraphs.first ? paragraphs.shift : nil
143
+ ary = File.read(path).delete("\r").split(/\n\n+/)
144
+
145
+ result = if title
146
+ tmp, matching = [], false
147
+ rgxp = %r/^=+\s*#{Regexp.escape(title)}/i
148
+ paragraphs << (0..-1) if paragraphs.empty?
149
+
150
+ ary.each do |val|
151
+ if val =~ rgxp
152
+ break if matching
153
+ matching = true
154
+ rgxp = %r/^=+/i
155
+ elsif matching
156
+ tmp << val
157
+ end
158
+ end
159
+ tmp
160
+ else ary end
161
+
162
+ result.values_at(*paragraphs)
163
+ end
164
+
165
+ # Adds the given gem _name_ to the current project's dependency list. An
166
+ # optional gem _version_ can be given. If omitted, the newest gem version
167
+ # will be used.
168
+ #
169
+ def depend_on( name, version = nil )
170
+ spec = Gem.source_index.find_name(name).last
171
+ version = spec.version.to_s if version.nil? and !spec.nil?
172
+
173
+ PROJ.gem.dependencies << case version
174
+ when nil; [name]
175
+ when %r/^\d/; [name, ">= #{version}"]
176
+ else [name, version] end
177
+ end
178
+
179
+ # Adds the given arguments to the include path if they are not already there
180
+ #
181
+ def ensure_in_path( *args )
182
+ args.each do |path|
183
+ path = File.expand_path(path)
184
+ $:.unshift(path) if test(?d, path) and not $:.include?(path)
185
+ end
186
+ end
187
+
188
+ # Find a rake task using the task name and remove any description text. This
189
+ # will prevent the task from being displayed in the list of available tasks.
190
+ #
191
+ def remove_desc_for_task( names )
192
+ Array(names).each do |task_name|
193
+ task = Rake.application.tasks.find {|t| t.name == task_name}
194
+ next if task.nil?
195
+ task.instance_variable_set :@comment, nil
196
+ end
197
+ end
198
+
199
+ # Change working directories to _dir_, call the _block_ of code, and then
200
+ # change back to the original working directory (the current directory when
201
+ # this method was called).
202
+ #
203
+ def in_directory( dir, &block )
204
+ curdir = pwd
205
+ begin
206
+ cd dir
207
+ return block.call
208
+ ensure
209
+ cd curdir
210
+ end
211
+ end
212
+
213
+ # Scans the current working directory and creates a list of files that are
214
+ # candidates to be in the manifest.
215
+ #
216
+ def manifest_files
217
+ files = []
218
+ exclude = Regexp.new(PROJ.exclude.join('|'))
219
+ Find.find '.' do |path|
220
+ path.sub! %r/^(\.\/|\/)/o, ''
221
+ next unless test ?f, path
222
+ next if path =~ exclude
223
+ files << path
224
+ end
225
+ files.sort!
226
+ end
227
+
228
+ # We need a "valid" method thtat determines if a string is suitable for use
229
+ # in the gem specification.
230
+ #
231
+ class Object
232
+ def valid?
233
+ return !(self.empty? or self == "\000") if self.respond_to?(:to_str)
234
+ return false
235
+ end
236
+ end
237
+
238
+ # EOF
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: raggi-rubyw_helper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - James Tucker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-19 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: exception_string
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: rake
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: bones
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ - !ruby/object:Gem::Dependency
43
+ name: bacon
44
+ version_requirement:
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ description: A simple redirector for use when you just want to safely redirect stdio. Simply encapsulates a few different safety mechanisms when redirecting stdio, with the primary goal of making it easier to write apps that run under rubyw.exe, where ruby loads with stdio closed. Whilst the primary intention for use is under win32, and was actually developed as an external helper for specifically win32-service usage, this gem may be useful to some other folks on other platforms. It is not win32 specific.
52
+ email: raggi@rubyforge.org
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files:
58
+ - History.txt
59
+ - README.rdoc
60
+ files:
61
+ - History.txt
62
+ - Manifest.txt
63
+ - README.rdoc
64
+ - Rakefile
65
+ - lib/rubyw_helper.rb
66
+ - spec/.bacon
67
+ - spec/helper.rb
68
+ - spec/runner
69
+ - spec/spec_rubyw_helper.rb
70
+ - tasks/autospec.rake
71
+ - tasks/bacon.rake
72
+ - tasks/bones.rake
73
+ - tasks/gem.rake
74
+ - tasks/git.rake
75
+ - tasks/manifest.rake
76
+ - tasks/notes.rake
77
+ - tasks/post_load.rake
78
+ - tasks/rdoc.rake
79
+ - tasks/rubyforge.rake
80
+ - tasks/setup.rb
81
+ has_rdoc: true
82
+ homepage: http://github.com/raggi/rubyw_helper
83
+ post_install_message:
84
+ rdoc_options:
85
+ - --main
86
+ - README.rdoc
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: "0"
94
+ version:
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: "0"
100
+ version:
101
+ requirements: []
102
+
103
+ rubyforge_project: libraggi
104
+ rubygems_version: 1.2.0
105
+ signing_key:
106
+ specification_version: 2
107
+ summary: A simple redirector for use when you just want to safely redirect stdio
108
+ test_files:
109
+ - spec/spec_rubyw_helper.rb