carrousel 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDllYjNiM2Y5MzY0NDI0MzEyZDZhMTZlNGM0MDY3N2EwYTJiZTY5Zg==
5
+ data.tar.gz: !binary |-
6
+ YjhlYzMzNDBlNzE0OTg2YmM5NjIxZmY0NTY2NzZhODE2YTM4NDhlMQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MmRjYWJjNjI1Y2M1NmExNjI0NzIxZGZjZTRkM2QxZjdmMTMzNjM0MDU1MjAx
10
+ MzYxZjI3MjUyZTlhY2NmYTZhYmRhZDZhODlkZTMzOTM2YjIxYmQwZWNjMjE2
11
+ ZjY5ZTYxNjI2ODZkZmUxZTI2NzkwODVjMzk3NzUxZGIyZTZiNTM=
12
+ data.tar.gz: !binary |-
13
+ YWJiZWI4YjViZmJkZTk4ZTIyNDllOWZlZGQ1ZmYxODFhMDNmMjAwNGRhZjgy
14
+ N2EwMGY3MDVmY2ZjZTFmZTk1OTQ1Mzk5ODdlYjNlNjJkNGFkOGY5NzIzNDQ5
15
+ MmRhYWQxMzJhMjU5ODljMDAwNTcxOGQ5NDRlZmZmZWRiYzM1YzY=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in carrousel.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Raj Sahae
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # Carrousel
2
+
3
+ The Carrousel gem is a command line utility for running a single command on
4
+ multiple targets. Carrousel tracks which commands have succeeded or failed
5
+ based on the return of the system call, and sends failed jobs to the back of
6
+ the line to be tried again later.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'carrousel'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install carrousel
21
+
22
+ ## Usage
23
+
24
+ The most basic use case for Carrousel is to give it a command and a list of
25
+ items as command line arguments:
26
+
27
+ $ carrousel -c 'echo' foo bar baz
28
+
29
+ In addition to passing in arguments on the command line, you can also pass them
30
+ in a file. These will be in addition to anything on the command line:
31
+
32
+ $ carrousel -c 'echo' -l things-to-echo.txt foo bar baz
33
+
34
+ While running, carrousel will track it's progress in a carrousel runner status
35
+ file. This file is stored in the present working directory. If you need to kill
36
+ carrousel for any reason, you can pick up where you left off by passing the
37
+ status file into carrousel. The status file will save your completed items,
38
+ incompleted items, and the command used. The file will always be of the form
39
+ ~/PWD/.carrousel\_runner\_status\_XXXXXXX. The following example kills the echo
40
+ carrousel and resumes it using a carrousel runner status file:
41
+
42
+ $ carrousel -c 'echo' foo bar baz
43
+ ... CTRL-C to kill this for some reason ...
44
+ $ carrousel -s .carrousel\_runner\_status\_130b02b
45
+
46
+ If you would like there to be some sort of delay between individual jobs, you
47
+ can specify that with a delay argument. The following example inserts a 30
48
+ second delay between each echo command:
49
+
50
+ $ carrousel -c 'echo' --delay 30 foo bar baz
51
+
52
+
53
+ ## Contributing
54
+
55
+ 1. Fork it
56
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
57
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
58
+ 4. Push to the branch (`git push origin my-new-feature`)
59
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ end
7
+
8
+ task :default => :test
data/bin/carrousel ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'carrousel'
4
+ require 'optparse'
5
+
6
+ @opts = {}
7
+ OptionParser.new do |op|
8
+ op.banner = "Usage: #{__FILE__} [options] -c COMMAND arg1 [arg2 ...]"
9
+
10
+ op.on('-c', '--command COMMAND', 'Execute the given COMMAND') do |c|
11
+ @opts[:command] = c
12
+ end
13
+
14
+ op.on('-d', '--delay DELAY', 'Sleep for DELAY seconds between commands') do |d|
15
+ @opts[:delay] = d.to_i
16
+ end
17
+
18
+ op.on('-l', '--listfile FILE', 'Load list of arguments from FILE') do |l|
19
+ @opts[:listfile] = File.expand_path(l)
20
+ end
21
+
22
+ op.on('-s', '--statusfile FILE', 'Replay FILE with saved command and args') do |s|
23
+ @opts[:statusfile] = File.expand_path(s)
24
+ end
25
+
26
+ op.on('-v', '--[no-]verbose', 'Enable verbose output') do |v|
27
+ @opts[:verbose] = v
28
+ end
29
+
30
+ op.on('--[no-]debug', 'Enable debug output') do |d|
31
+ @opts[:debug] = d
32
+ @opts[:verbose] ||= d
33
+ end
34
+ end.parse!
35
+
36
+ @opts = {
37
+ :command => nil,
38
+ :delay => 0,
39
+ :listfile => nil,
40
+ :statusfile => nil,
41
+ :verbose => false,
42
+ :debug => false
43
+ }.merge(@opts)
44
+
45
+ Carrousel::Runner.new(ARGV, @opts).run
data/carrousel.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'carrousel/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "carrousel"
8
+ spec.version = Carrousel::VERSION
9
+ spec.authors = ["Raj Sahae"]
10
+ spec.email = ["rajsahae@gmail.com"]
11
+ spec.description = %q{Carrousel is a robust utility designed to take a list
12
+ of generic items, and given some command, perform that command on each item
13
+ in that list. Depending on the commands return value, Carrousel will track
14
+ which items have been completed successfully, and retry items as necessary.
15
+ It will save your progress in a status database and you can quit the loop
16
+ and come back later to finish unprocessed items.}
17
+ spec.summary = %q{Robust list based action tracking utility.}
18
+ spec.homepage = "https://github.com/rajsahae/carrousel"
19
+ spec.license = "MIT"
20
+
21
+ spec.files = `git ls-files`.split($/)
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "minitest"
29
+ end
data/lib/carrousel.rb ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/env ruby
2
+ # enconding: UTF-8
3
+
4
+ require "carrousel/version"
5
+ require 'digest'
6
+ require 'yaml'
7
+
8
+ ##
9
+ # "Enter the Carrousel. This is the time of renewal."
10
+ #
11
+ # Carrousel is a system command execution and tracker utility.
12
+ module Carrousel
13
+
14
+ class Runner
15
+
16
+ def initialize(args, opts = {})
17
+ @args = args
18
+ @opts = opts
19
+ @incomplete = []
20
+ @complete = []
21
+
22
+ unless @opts[:listfile].nil?
23
+ lines = File.readlines(@opts[:listfile]).map(&:strip)
24
+ @incomplete.concat(lines)
25
+ end
26
+ @incomplete.concat(@args)
27
+
28
+ @opts[:statusfile] ||= generate_status_filename
29
+ open_status_file
30
+
31
+ p self if @opts[:debug]
32
+
33
+ raise ArgumentError.new("Command option is required") if @opts[:command].nil?
34
+ end # def initialize
35
+
36
+ def run
37
+ # Loop over everything in the list. Run the command. If the command fails
38
+ # then we move the item to the bottom of the list. If the command
39
+ # succeeds, we move the item to the completed list. If we are interrupted
40
+ # in the middle of processing, we ensure that the item is saved in the
41
+ # normal list, and we ensure that we write out the completed list.
42
+ until @incomplete.empty?
43
+ begin
44
+ command = [@opts[:command], @incomplete.first].join(' ')
45
+ warn "Executing command: #{command}" if @opts[:verbose]
46
+ resp = system(command)
47
+ warn "System response: #{resp}" if @opts[:verbose]
48
+ if resp
49
+ @complete << @incomplete.delete(@incomplete.first)
50
+ else
51
+ @incomplete.rotate!
52
+ end
53
+ ensure
54
+ save_status_file
55
+ end
56
+
57
+ if @opts[:delay] > 0
58
+ warn "Sleeping for #{@opts[:delay]} seconds" if @opts[:verbose]
59
+ sleep @opts[:delay]
60
+ end
61
+ end # until @incomplete.empty?
62
+ end # def run
63
+
64
+ private
65
+ def generate_status_filename
66
+ key = Digest::SHA256.hexdigest(@incomplete.sort.join).slice(0...7)
67
+ warn "status file key: #{key}" if @opts[:debug]
68
+ name = self.class.name.gsub('::', '_').downcase
69
+ File.expand_path(".#{name}_status_#{key}", Dir.pwd)
70
+ end # def generate_status_filename
71
+
72
+ private
73
+ def open_status_file
74
+ if File.exists?(@opts[:statusfile])
75
+ dbs = YAML.load(File.read(@opts[:statusfile]))
76
+ warn "opened status file:\n#{dbs}" if @opts[:debug]
77
+ if dbs
78
+ @opts[:command] ||= dbs[:command]
79
+ @complete.concat(dbs[:complete])
80
+ @incomplete.concat(dbs[:incomplete])
81
+ end
82
+ end
83
+ end # def open_status_file
84
+
85
+ private
86
+ def save_status_file
87
+ warn "Saving status file: #{@opts[:statusfile]}" if @opts[:verbose]
88
+ File.open(@opts[:statusfile], 'w') do |f|
89
+ ydb = {
90
+ :command => @opts[:command],
91
+ :complete => @complete,
92
+ :incomplete => @incomplete
93
+ }.to_yaml
94
+ f.puts(ydb)
95
+ warn "Saved status file:\n#{ydb}" if @opts[:debug]
96
+ end
97
+ true
98
+ end # def save_status_file
99
+
100
+ end # class Runner
101
+ end # module Carrousel
@@ -0,0 +1,3 @@
1
+ module Carrousel
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'carrousel'
3
+
4
+ require 'minitest/autorun'
@@ -0,0 +1,11 @@
1
+ require 'minitest_helper'
2
+
3
+ class TestCarrousel < MiniTest::Unit::TestCase
4
+ def test_that_it_has_a_version_number
5
+ refute_nil ::Carrousel::VERSION
6
+ end
7
+
8
+ def test_it_does_something_useful
9
+ assert true
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carrousel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Raj Sahae
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: ! "Carrousel is a robust utility designed to take a list\n of generic
56
+ items, and given some command, perform that command on each item\n in that list.
57
+ Depending on the commands return value, Carrousel will track \n which items have
58
+ been completed successfully, and retry items as necessary.\n It will save your
59
+ progress in a status database and you can quit the loop \n and come back later
60
+ to finish unprocessed items."
61
+ email:
62
+ - rajsahae@gmail.com
63
+ executables:
64
+ - carrousel
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - .gitignore
69
+ - .travis.yml
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - bin/carrousel
75
+ - carrousel.gemspec
76
+ - lib/carrousel.rb
77
+ - lib/carrousel/version.rb
78
+ - test/minitest_helper.rb
79
+ - test/test_carrousel.rb
80
+ homepage: https://github.com/rajsahae/carrousel
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.2.2
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Robust list based action tracking utility.
104
+ test_files:
105
+ - test/minitest_helper.rb
106
+ - test/test_carrousel.rb