history_commander 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,22 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+ *.swo
16
+
17
+ ## PROJECT::GENERAL
18
+ coverage
19
+ rdoc
20
+ pkg
21
+
22
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jeremy Deininger
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ = history_commander
2
+
3
+ == Quick Start
4
+
5
+ 'gem install history_commander'
6
+ Installs the history_commander gem. To run 'hc' you must rubygems bin directory in your path
7
+
8
+ 'hc_setup_bashrc'
9
+ This installs bash history tweaks to your .bashrc
10
+
11
+ 'hc configure --help'
12
+ This will setup the .history_commander config file with your selected options
13
+
14
+ 'hc start'
15
+ Starts history_commander
16
+
17
+ == Note on Patches/Pull Requests
18
+
19
+ * Fork the project.
20
+ * Make your feature addition or bug fix.
21
+ * Add tests for it. This is important so I don't break it in a
22
+ future version unintentionally.
23
+ * Commit, do not mess with rakefile, version, or history.
24
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
25
+ * Send me a pull request. Bonus points for topic branches.
26
+
27
+ == Copyright
28
+
29
+ Copyright (c) 2010 Jeremy Deininger. See LICENSE for details.
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "history_commander"
8
+ gem.summary = %Q{Take command of your shell history!}
9
+ gem.description = %Q{History Commander is a program designed to keep your shell history in sync across all your nodes. }
10
+ gem.email = "jeremy@rubyonlinux.org"
11
+ gem.homepage = "http://github.com/jeremyd/history_commander"
12
+ gem.authors = ["Jeremy Deininger"]
13
+ gem.add_dependency "eventmachine"
14
+ gem.add_dependency "eventmachine-tail"
15
+ gem.add_dependency "amqp"
16
+ gem.add_dependency "json"
17
+ gem.add_dependency "simple-daemon"
18
+ gem.add_dependency "trollop"
19
+ gem.add_dependency "highline"
20
+ gem.add_development_dependency "rspec", ">= 1.2.9"
21
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
22
+ end
23
+ Jeweler::GemcutterTasks.new
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
26
+ end
27
+
28
+ require 'spec/rake/spectask'
29
+ Spec::Rake::SpecTask.new(:spec) do |spec|
30
+ spec.libs << 'lib' << 'spec'
31
+ spec.spec_files = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
35
+ spec.libs << 'lib' << 'spec'
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :spec => :check_dependencies
41
+
42
+ task :default => :spec
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "history_commander #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/hc ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ## Development ENV only
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ ###
6
+
7
+ require 'rubygems'
8
+ require 'history_commander'
9
+ require 'trollop'
10
+ require 'tmpdir'
11
+
12
+ command = ARGV.shift
13
+ unless ["start", "stop", "configure"].include?(command)
14
+ puts "Syntax: hc <command> [args] [--help]"
15
+ puts " command can be 'start', 'stop', or 'configure'"
16
+ end
17
+
18
+ @@options = Trollop::options do
19
+ opt :config, "configuration file to use", :default => File.join(File.expand_path("~"), ".history_commander"), :type => :string
20
+ opt :foreground, "run in foreground (daemonize is the default)", :default => false
21
+ opt :amqp_host, "hostname of AMQP server", :type => :string
22
+ opt :mode, "operate in 'full' read/write (sync) mode -or in 'writeonly' (no sync) mode. This requires the proper AMQP permissions.", :type => :string
23
+ opt :user, "AMQP username", :type => :string
24
+ opt :pass, "AMQP pass", :type => :string
25
+ opt :vhost, "AMQP vhost", :type => :string
26
+ opt :amqp_log, "AMQP verbose logging", :default => false, :short => "-l"
27
+ end
28
+
29
+ def check_options
30
+ [:user, :pass, :vhost, :amqp_host, :mode].each do |req|
31
+ unless @@options[req]
32
+ puts "FATAL: you must specify --#{req} in your history_commander config file or on the command line, see --help"
33
+ exit 1
34
+ end
35
+ end
36
+ end
37
+
38
+ if command == "configure"
39
+ check_options
40
+ config_file = @@options[:config]
41
+ @@options.reject! { |k, v| k.to_s.include?("given") || k == :help || k == :save || k == :config }
42
+ writeme = @@options.dup
43
+ File.open(config_file, "w") {|f| f.write(writeme.to_json(:indent => " ", :object_nl => "\n"))}
44
+ File.chmod 0600, config_file
45
+ puts "wrote config to #{config_file}"
46
+ exit
47
+ end
48
+
49
+ if File.exists?(@@options[:config])
50
+ @@options.reject! { |k, v| v == nil }
51
+ saved_opts = JSON::parse(IO.read(@@options[:config])).to_mash
52
+ passed_in_opts = @@options.to_mash
53
+ @@options = saved_opts.merge passed_in_opts
54
+ end
55
+
56
+ check_options
57
+
58
+ if @@options[:foreground]
59
+ puts "History Commander running in foreground mode. CTRL-C to interrupt"
60
+ EM.run do
61
+ AMQP.start(:host => @@options[:amqp_host], :user => @@options[:user], :pass => @@options[:pass], :vhost => @@options[:vhost], :logging => @@options[:amqp_log]) do
62
+ HistWatch.start(@@options[:mode])
63
+ end
64
+ end
65
+ else
66
+ puts "Logging to #{Dir.tmpdir}/HistoryCommanderDaemon.log"
67
+ require 'simple-daemon'
68
+ class HistoryCommanderDaemon < SimpleDaemon::Base
69
+ SimpleDaemon::WORKING_DIRECTORY = Dir.tmpdir
70
+ def self.start
71
+ EM.run do
72
+ AMQP.start(:host => @@options[:amqp_host], :user => @@options[:user], :pass => @@options[:pass], :vhost => @@options[:vhost], :logging => @@options[:amqp_log]) do
73
+ HistWatch.start(@@options[:mode])
74
+ end
75
+ end
76
+ end
77
+
78
+ def self.stop
79
+ EM.stop
80
+ puts "Stopping History Commander"
81
+ end
82
+ end
83
+ HistoryCommanderDaemon.daemonize
84
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ## Development ENV only
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ ###
6
+ require 'rubygems'
7
+ require 'history_commander/setup_bashrc'
8
+
9
+ options = Trollop::options do
10
+ opt :yes, "Do not prompt", :default => false
11
+ end
12
+
13
+ SetupBashrc.install(options[:yes])
@@ -0,0 +1,80 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{history_commander}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jeremy Deininger"]
12
+ s.date = %q{2010-08-01}
13
+ s.description = %q{History Commander is a program designed to keep your shell history in sync across all your nodes. }
14
+ s.email = %q{jeremy@rubyonlinux.org}
15
+ s.executables = ["hc", "hc_setup_bashrc"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/hc",
28
+ "bin/hc_setup_bashrc",
29
+ "history_commander.gemspec",
30
+ "lib/history_commander.rb",
31
+ "lib/history_commander/setup_bashrc.rb",
32
+ "spec/history_commander_spec.rb",
33
+ "spec/spec.opts",
34
+ "spec/spec_helper.rb"
35
+ ]
36
+ s.homepage = %q{http://github.com/jeremyd/history_commander}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.7}
40
+ s.summary = %q{Take command of your shell history!}
41
+ s.test_files = [
42
+ "spec/history_commander_spec.rb",
43
+ "spec/spec_helper.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
51
+ s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
52
+ s.add_runtime_dependency(%q<eventmachine-tail>, [">= 0"])
53
+ s.add_runtime_dependency(%q<amqp>, [">= 0"])
54
+ s.add_runtime_dependency(%q<json>, [">= 0"])
55
+ s.add_runtime_dependency(%q<simple-daemon>, [">= 0"])
56
+ s.add_runtime_dependency(%q<trollop>, [">= 0"])
57
+ s.add_runtime_dependency(%q<highline>, [">= 0"])
58
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
59
+ else
60
+ s.add_dependency(%q<eventmachine>, [">= 0"])
61
+ s.add_dependency(%q<eventmachine-tail>, [">= 0"])
62
+ s.add_dependency(%q<amqp>, [">= 0"])
63
+ s.add_dependency(%q<json>, [">= 0"])
64
+ s.add_dependency(%q<simple-daemon>, [">= 0"])
65
+ s.add_dependency(%q<trollop>, [">= 0"])
66
+ s.add_dependency(%q<highline>, [">= 0"])
67
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
68
+ end
69
+ else
70
+ s.add_dependency(%q<eventmachine>, [">= 0"])
71
+ s.add_dependency(%q<eventmachine-tail>, [">= 0"])
72
+ s.add_dependency(%q<amqp>, [">= 0"])
73
+ s.add_dependency(%q<json>, [">= 0"])
74
+ s.add_dependency(%q<simple-daemon>, [">= 0"])
75
+ s.add_dependency(%q<trollop>, [">= 0"])
76
+ s.add_dependency(%q<highline>, [">= 0"])
77
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
78
+ end
79
+ end
80
+
@@ -0,0 +1,86 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+ require 'eventmachine'
4
+ require 'eventmachine-tail'
5
+ require 'mq'
6
+ require 'uuidtools'
7
+ require 'mash'
8
+ require 'fileutils'
9
+
10
+ class HistoryCommander < EventMachine::FileTail
11
+ attr_accessor :uuid
12
+ attr_accessor :pause
13
+
14
+ def safe_path
15
+ "#{path}_safe"
16
+ end
17
+
18
+ # path <~String> File path to monitor
19
+ # mode <~String> Can be set to "full" for read/write mode, and any other value for write only mode.
20
+ # startpos <~Integer> File position to start tailing the file. Default of -1 starts at the end of the file
21
+ def initialize(path, startpos=-1, mode="full")
22
+ super(path, startpos)
23
+ FileUtils.cp(path, safe_path)
24
+ @buffer = BufferedTokenizer.new
25
+ @global_history_fanout = MQ.new.fanout('global_history')
26
+ @uuid = UUIDTools::UUID.random_create.to_s
27
+ @host = `hostname`.chomp
28
+ @user = `whoami`.chomp
29
+ @pause = false
30
+ subscribe if mode == "full"
31
+ end
32
+
33
+ # Receive data from the FileTail and submit it
34
+ # to the MQ
35
+ def receive_data(data)
36
+ @buffer.extract(data).each do |line|
37
+ payload = { :uuid => @uuid,
38
+ :message => line,
39
+ :host => @host,
40
+ :user => @user }
41
+ @global_history_fanout.publish(payload.to_json)
42
+ end
43
+ end
44
+
45
+ def schedule_next_read
46
+ unless @pause
47
+ EventMachine::add_timer(@naptime) do
48
+ read
49
+ end
50
+ end
51
+ end
52
+
53
+ def skip_ahead
54
+ def skip_ahead
55
+ @pos = @file.sysseek(0, IO::SEEK_END)
56
+ end
57
+ end
58
+
59
+ # Subscribe to the global history exchange and sync the history file with any new inbound global history. Pauses FileTail and skips the output when writing to the history file.
60
+ def subscribe
61
+ @subscription = MQ.new
62
+ @subscription.queue(@uuid).bind(@subscription.fanout('global_history')).subscribe do |result|
63
+ x = Mash.new(JSON::parse(result))
64
+ puts "received: #{x[:uuid]} #{x[:user]}@#{x[:host]}$ #{x[:message]}"
65
+ if x[:uuid] != @uuid
66
+ @pause = true
67
+ File.open(path, "a") {|f| f.puts(x[:message])}
68
+ skip_ahead
69
+ @pause = false
70
+ schedule_next_read
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ # HistWatch is a wrapper class for starting EM and loading configuration information for History Commander
77
+ class HistWatch
78
+ # starts
79
+ def self.start(mode="full", file = File.join(File.expand_path('~'), ".bash_history"))
80
+ @hist_file_watch = EventMachine::file_tail(file, HistoryCommander, -1, mode)
81
+ end
82
+
83
+ def self.stop
84
+ EM.stop
85
+ end
86
+ end
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+ require 'trollop'
4
+ require 'highline/import'
5
+
6
+ class SetupBashrc
7
+ # Install necessary .bashrc customization for optimal history commander usage.
8
+ def self.install(force = false)
9
+ my_home = File.expand_path('~')
10
+ my_bashrc = File.join(my_home, ".bashrc")
11
+ unless File.exists?(my_bashrc)
12
+ if File.exists?("/etc/bashrc")
13
+ FileUtils.cp("/etc/bashrc", my_bashrc)
14
+ elsif File.exists?("/usr/etc/bashrc")
15
+ FileUtils.cp("/usr/etc/bashrc", my_bashrc)
16
+ else
17
+ `touch #{my_bashrc}`
18
+ end
19
+ end
20
+ say "using .bashrc in #{my_bashrc}"
21
+ self.apply_change(my_bashrc, force)
22
+ end
23
+
24
+ def self.goodies
25
+ <<eoh
26
+ shopt -s histappend
27
+ export HIST_CONTROL=ignoreboth
28
+ export PROMPT_COMMAND="history -a; history -n"
29
+ export HISTSIZE=1000000
30
+ export HISTFILESIZE=1000000
31
+ eoh
32
+ end
33
+
34
+ def self.do_warnings(file_contents)
35
+ if file_contents =~ /#{self.goodies}/
36
+ say "*** WARNING: modifications already installed!"
37
+ end
38
+ if file_contents =~ /PROMPT_COMMAND/
39
+ say "*** WARNING: your .bashrc already has a PROMPT_COMMAND. This setting will be overridden!"
40
+ end
41
+ end
42
+
43
+ # *file <~String>: bashrc file to detect and optionally apply changes to.
44
+ def self.apply_change(file, force = false)
45
+ say("Thanks for installing History Commander!\nThe following modifications will be applied to your ~/.bashrc file:")
46
+ say("+++\n#{self.goodies}")
47
+ self.do_warnings(IO.read(file))
48
+ unless force
49
+ confirm = ask("+++ Apply changes (y/n)?", lambda { |ans| true if (ans =~ /^[y,Y]{1}/) })
50
+ unless confirm
51
+ say "Aborting."
52
+ exit
53
+ end
54
+ end
55
+ backup = "#{file}_hc_backup#{rand(10000)}"
56
+ say "Creating backup of .bashrc in #{backup}"
57
+ FileUtils.cp(file, backup)
58
+ File.open(file, "a") { |f| f.puts(self.goodies)}
59
+ say "done installing history customization."
60
+ say "***"
61
+ say "Now you MUST load your new bash history config:"
62
+ say "Open a new terminal -or-"
63
+ say "'source #{file}'"
64
+ end
65
+ end
@@ -0,0 +1,43 @@
1
+ # This Spec requires a running AMQP server.
2
+ # Configure your AMQP server first and enter access information below before running this spec.
3
+
4
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
5
+ require 'tmpdir'
6
+
7
+ describe "HistoryCommander" do
8
+ before(:all) do
9
+ @watch_files = []
10
+ 2.times do |x|
11
+ @watch_files << File.join(Dir.tmpdir, "#{x}unique-history_commander_spec_candelete")
12
+ end
13
+ @watch_files.each {|w| `rm #{w}; touch #{w}`}
14
+ end
15
+ it "runs multiple history commanders and checks for all files to contain all history" do
16
+ EM.run do
17
+ AMQP.start(:host => "ec2-184-72-19-157.us-west-1.compute.amazonaws.com") do
18
+ EM.next_tick do
19
+ @watch_files.each do |w|
20
+ HistWatch.start(w)
21
+ end
22
+ end
23
+ EM.add_timer(2) do
24
+ @first_value = "first_command: #{rand(10000000)}"
25
+ File.open(@watch_files.first, "a") {|f| f.puts @first_value }
26
+ end
27
+ EM.add_timer(3) do
28
+ @second_value = "second_command: #{rand(10000000)}"
29
+ File.open(@watch_files.last, "a") {|f| f.puts @second_value }
30
+ end
31
+ EM.add_timer(10) do
32
+ @watch_files.each do |w|
33
+ IO.read(w).should =~ /^#{@first_value}/
34
+ IO.read(w).should =~ /^#{@second_value}/
35
+ end
36
+ end
37
+ EM.add_timer(12) do
38
+ EM.stop
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'history_commander'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,196 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: history_commander
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Jeremy Deininger
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-01 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: eventmachine
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: eventmachine-tail
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: amqp
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: json
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :runtime
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: simple-daemon
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :runtime
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: trollop
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :runtime
104
+ version_requirements: *id006
105
+ - !ruby/object:Gem::Dependency
106
+ name: highline
107
+ prerelease: false
108
+ requirement: &id007 !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ type: :runtime
118
+ version_requirements: *id007
119
+ - !ruby/object:Gem::Dependency
120
+ name: rspec
121
+ prerelease: false
122
+ requirement: &id008 !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ hash: 13
128
+ segments:
129
+ - 1
130
+ - 2
131
+ - 9
132
+ version: 1.2.9
133
+ type: :development
134
+ version_requirements: *id008
135
+ description: "History Commander is a program designed to keep your shell history in sync across all your nodes. "
136
+ email: jeremy@rubyonlinux.org
137
+ executables:
138
+ - hc
139
+ - hc_setup_bashrc
140
+ extensions: []
141
+
142
+ extra_rdoc_files:
143
+ - LICENSE
144
+ - README.rdoc
145
+ files:
146
+ - .document
147
+ - .gitignore
148
+ - LICENSE
149
+ - README.rdoc
150
+ - Rakefile
151
+ - VERSION
152
+ - bin/hc
153
+ - bin/hc_setup_bashrc
154
+ - history_commander.gemspec
155
+ - lib/history_commander.rb
156
+ - lib/history_commander/setup_bashrc.rb
157
+ - spec/history_commander_spec.rb
158
+ - spec/spec.opts
159
+ - spec/spec_helper.rb
160
+ has_rdoc: true
161
+ homepage: http://github.com/jeremyd/history_commander
162
+ licenses: []
163
+
164
+ post_install_message:
165
+ rdoc_options:
166
+ - --charset=UTF-8
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ hash: 3
175
+ segments:
176
+ - 0
177
+ version: "0"
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ hash: 3
184
+ segments:
185
+ - 0
186
+ version: "0"
187
+ requirements: []
188
+
189
+ rubyforge_project:
190
+ rubygems_version: 1.3.7
191
+ signing_key:
192
+ specification_version: 3
193
+ summary: Take command of your shell history!
194
+ test_files:
195
+ - spec/history_commander_spec.rb
196
+ - spec/spec_helper.rb