rye 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,6 +6,14 @@ TODO
6
6
  * Fingerprints: ssh-keygen -l -f id_rsa_repos.pub
7
7
  * Add S3 support for Rye::Box.upload / download
8
8
 
9
+ #### 0.8.1 (2009-06-22) #############################
10
+
11
+ * FIXED: file_upload now handles globs like a champ
12
+ * FIXED: Handling of relative paths in Rye::Box#cd and Rye::Box#[]
13
+ * ADDED: file_upload now assumes uploading to home directory when only 1 arg
14
+ * ADDED: Rudyfile for remote 'clean-machine' tests
15
+ * CHANGE: guess_user_home, ostype, and getenv now run quietly
16
+
9
17
 
10
18
  #### 0.8.0 (2009-06-21) #############################
11
19
 
@@ -0,0 +1,135 @@
1
+ # = Rudy configuration
2
+ #
3
+
4
+ # ----------------------------------------------------------- DEFAULTS --------
5
+ # These values are used as defaults for their respective global settings. All
6
+ # non-boolean values are expected to be Symbols.
7
+ #
8
+ defaults do
9
+ zone :'eu-west-1b'
10
+ environment :rye
11
+ color true # Terminal colors? true/false
12
+ yes false # Auto-confirm? true/false
13
+ end
14
+
15
+ # --------------------------------------------------------- MACHINES --------
16
+ # The machines block describes the 'physical' characteristics of your machines.
17
+ machines do
18
+
19
+ zone :'us-east-1b' do
20
+ ami 'ami-e348af8a' # Alestic Debian 5.0, 32-bit (US)
21
+ bucket 'rudy-ami-us'
22
+ end
23
+ zone :'eu-west-1b' do
24
+ ami 'ami-1dbd9569' # rudy-ami-eu/debian-5.0-32-ruby-r1
25
+ bucket 'rudy-ami-eu'
26
+ end
27
+
28
+ hostname :rudy # One of: :default, :rudy, 'your-name'
29
+
30
+ env :rye do
31
+ user :root # User to connect as
32
+ size 'm1.small' # EC2 machine type for all machines
33
+ end
34
+
35
+ end
36
+
37
+
38
+ # ----------------------------------------------------------- COMMANDS --------
39
+ # The commands block defines shell commands that can be used in routines. The
40
+ # ones defined here are added to the default list defined by Rye::Cmd (Rudy
41
+ # executes all SSH commands via Rye).
42
+ #
43
+ # Usage:
44
+ #
45
+ # allow COMMAND-NAME
46
+ # allow COMMAND-NAME, '/path/2/COMMAND'
47
+ # allow COMMAND-NAME, '/path/2/COMMAND', 'default argument', 'another arg'
48
+ #
49
+ commands do
50
+ allow :apt_get, "apt-get", :y, :q
51
+ allow :gem18_install, "/usr/bin/gem1.8", "install", :n, '/usr/bin', :y, :V, "--no-rdoc", "--no-ri"
52
+ allow :gem18_sources, "/usr/bin/gem1.8", "sources"
53
+ allow :gem19_install, "/usr/local/bin/gem", "install", :n, '/usr/bin', :y, :V, "--no-rdoc", "--no-ri"
54
+ allow :gem19_sources, "/usr/local/bin/gem", "sources"
55
+ allow :update_rubygems
56
+ allow :ruby18, "/usr/bin/ruby1.8"
57
+ allow :ruby19, "/usr/local/bin/ruby"
58
+ allow :ssh_keygen, 'ssh-keygen'
59
+ allow :rm
60
+ end
61
+
62
+ # ----------------------------------------------------------- ROUTINES --------
63
+ # The routines block describes the repeatable processes for each machine group.
64
+ # To run a routine, specify its name on the command-line: rudy startup
65
+ routines do
66
+
67
+ env :rye do
68
+ startup do
69
+ after :installdeps, :authorize
70
+ after :runtest
71
+ end
72
+ end
73
+
74
+ runtest do
75
+ remote :root do
76
+ ruby18 :r, 'rubygems', 'rye/bin/try'
77
+ ruby19 'rye/bin/try'
78
+ end
79
+ end
80
+
81
+ authorize do
82
+ remote :root do
83
+ rm :f, '/root/.ssh/id_rsa'
84
+ ssh_keygen :q, :f, '/root/.ssh/id_rsa', :N, ''
85
+ rye 'authorize_local'
86
+ end
87
+ end
88
+
89
+ installdeps do
90
+ local do
91
+ rake 'package'
92
+ end
93
+ remote :root do
94
+ gem18_install "rye", "delano-rye"
95
+ gem19_install "rye", 'delano-rye'
96
+ disable_safe_mode
97
+ rm :r, :f, 'rye*'
98
+ file_upload 'pkg/rye-*gz'
99
+ tar :z, :x, :f, 'rye-*gz'
100
+ rm 'rye-*gz'
101
+ mv 'rye-*', 'rye'
102
+ cd 'rye'
103
+ end
104
+ end
105
+
106
+ # NOTE: sysupdate only needs to be run for the bare instances.
107
+ sysupdate do
108
+ remote :root do
109
+ apt_get "update"
110
+ apt_get "install", "build-essential", "git-core"
111
+ apt_get "install", "libssl-dev", "libreadline5-dev", "zlib1g-dev"
112
+ apt_get "install", "ruby1.8-dev", "rubygems"
113
+ gem18_install 'rubygems-update' # for 1.8
114
+ update_rubygems # for 1.8
115
+ gem18_sources :a, "http://gems.github.com"
116
+ end
117
+ after :install_ruby19
118
+ end
119
+
120
+ install_ruby19 do
121
+ remote :root do
122
+ wget :q, 'ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p129.tar.gz'
123
+ tar :z, :x, :f, 'ruby-1.9.1-p129.tar.gz'
124
+ cd 'ruby-1.9.1-p129'
125
+ configure
126
+ make
127
+ make 'install'
128
+ apt_get "install", "rubygems1.9"
129
+ gem19_sources :a, "http://gems.github.com"
130
+ end
131
+ end
132
+
133
+ end
134
+
135
+
data/bin/try ADDED
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Rye -- A working example
4
+ #
5
+ # If your reading this via the rdocs you won't be able to see the code
6
+ # See: http://github.com/delano/rye/blob/master/bin/try
7
+ #
8
+ # Usage: bin/try
9
+ #
10
+
11
+ RYE_HOME = File.join(File.dirname(__FILE__), '..')
12
+ $:.unshift File.join(RYE_HOME, 'lib')
13
+ %w{net-ssh sysinfo storable drydock}.each { |dir| $:.unshift File.join(File.dirname(__FILE__), '..', '..', dir, 'lib') }
14
+
15
+ require 'stringio'
16
+ require 'yaml'
17
+ require 'rye'
18
+
19
+
20
+ puts %Q(
21
+ # ------------------------------------------------------------------
22
+ # EXAMPLE 1 -- Basic Usage
23
+ #)
24
+
25
+ rbox = Rye::Box.new('localhost')
26
+
27
+ # Commands are run as methods on the Rye::Box object
28
+ puts rbox.uptime # => 11:02 up 16:01, 3 users
29
+
30
+ # The response value for all commands is a Rye::Rap object. The rap is a
31
+ # subclass of Array so you can treat it as an Array, but it can also act
32
+ # like a String if there's only one element.
33
+ p rbox.ls(:a, '/') # => ['.', '..', 'bin', 'etc', ...]
34
+
35
+ # You can change directories
36
+ puts rbox.pwd # => /home/rye
37
+ puts rbox['/usr/bin'].pwd # => /usr/bin
38
+ puts rbox.pwd # => /usr/bin
39
+
40
+ # You can specify environment variables
41
+ rbox.setenv(:RYE, "Forty Creek")
42
+ rbox.env # => ['HOME=/home/rye', 'RYE=Forty Creek', ...]
43
+
44
+ # The commands method returns an Array of available commands:
45
+ puts rbox.commands.join(', ') # => pwd, touch, echo, wc, ...
46
+
47
+ # When you're done you can disconnect explicitly.
48
+ # (Although Rye does this automatically at exit.)
49
+ rbox.disconnect
50
+
51
+
52
+ puts %Q(
53
+ # ------------------------------------------------------------------
54
+ # EXAMPLE 2 -- Disabling Safe-Mode
55
+ #)
56
+
57
+ rbox_safe = Rye::Box.new('localhost')
58
+ rbox_wild = Rye::Box.new('localhost', :safe => false)
59
+
60
+ # Safe-mode is enabled by default. In safe-mode, all command
61
+ # arguments are thoroughly escaped. This prevents access to
62
+ # environment variables and file globs (among other things).
63
+ p rbox_safe.echo('$HOME') # => "$HOME"
64
+ p rbox_safe['/etc'].ls('host*') rescue Rye::CommandError # Doesn't exist
65
+ p rbox_safe.ls('-l | wc -l') rescue Rye::CommandError # => '|' is not a valid ls arg
66
+
67
+ # Here's the same commands with safe-mode disabled:
68
+ p rbox_wild.echo('$HOME') # => "/home/rye"
69
+ p rbox_wild['/etc'].ls('host*') # => ["hostconfig", "hosts"]
70
+ p rbox_wild.ls('-l | wc -l') # => 110
71
+ p rbox_wild.echo('$HOME > /tmp/rye-home') # =>
72
+ p rbox_wild.cat('/tmp/rye-home') # => "/home/rye"
73
+
74
+
75
+
76
+ puts %Q(
77
+ # ------------------------------------------------------------------
78
+ # EXAMPLE 3 -- Custom Commands
79
+ #)
80
+
81
+ rbox = Rye::Box.new('localhost')
82
+ rbox.add_keys('/private/key/path') # Specify additional private keys
83
+
84
+ # There's currently no rye900 command
85
+ p rbox.commands.member?('rye9000') # => false
86
+
87
+ # But we can add our own commands to the Rye::Cmd class. They
88
+ # automatically become available to all Rye::Box objects.
89
+ module Rye::Cmd
90
+ def rye9000(*args)
91
+ run_command("ls", args)
92
+ end
93
+ def somescript(*args)
94
+ run_command("/path/to/my/script", args)
95
+ end
96
+ end
97
+
98
+ # We can now run rye9000 (with arguments)
99
+ p rbox.rye9000('-a') # => [".", "..", ".bashrc", ...]
100
+ p rbox.commands.member?('rye9000') # => true
101
+
102
+
103
+ puts %Q(
104
+ # ------------------------------------------------------------------
105
+ # EXAMPLE 4 -- Accessing Multiple Machines
106
+ #)
107
+
108
+ rset = Rye::Set.new('default', :parallel => true)
109
+ rbox = Rye::Box.new
110
+ p rbox
111
+
112
+ rset.add_keys('/private/key/path') # For passwordless logins
113
+ rset.add_boxes(rbox, '127.0.0.1') # Add boxes as hostnames or objects
114
+
115
+ # Calling methods on Rye::Set objects is very similar to calling them on
116
+ # Rye::Box objects. In fact, it's identical:
117
+ p rset.uptime # => [[14:19:02 up 32 days, 19:35 ...], [14:19:02 up 30 days, 01:35]]
118
+ p rset['/usr'].ls # => [['bin', 'etc', ...], ['bin', 'etc', ...]]
119
+
120
+ # Like Rye::Box, the response value is a Rye::Rap object containing the
121
+ # responses from each box. Each response is itself a Rye::Rap object.
122
+ unames = rset.uname
123
+ p unames # => [["Darwin"], ["Darwin"]]
124
+ puts unames.class # => Rye::Rap
125
+
126
+ # The Rye::Rap object also keeps a reference to the object that called the
127
+ # command. In this case, it will keep a reference to Rye::Set:
128
+ puts unames.set.class # => Rye::Set
129
+ puts unames.set == rset # => true
130
+ puts unames.size # => 2
131
+ puts unames.first # => Darwin
132
+ puts unames.first.class # => Rye::Rap
133
+ puts unames.first.box.class # => Rye::Box
134
+ puts unames.first.box == rbox # => true
135
+
136
+ # Envrionment variables can be set the same way as with Rye::Box
137
+ rset.setenv(:RYE, "Forty Creek")
138
+ p rset.env.first.select { |env| env =~ /RYE/ } # => ["RYE=Forty Creek"]
139
+
140
+
141
+ puts %Q(
142
+ # ------------------------------------------------------------------
143
+ # EXAMPLE 5 -- ERROR HANDLING
144
+ #)
145
+
146
+ rbox = Rye::Box.new('localhost', :safe => false) # Note: safe mode is off
147
+
148
+ # Rye follows the standard convention of taking exception to a non-zero
149
+ # exit code by raising a Rye::CommandError. In this case, rye9000.test
150
+ # is not found by the ls command.
151
+ begin
152
+ rbox.ls('rye.test')
153
+ rescue Rye::CommandError => ex
154
+ puts ex.exit_code # => 1
155
+ puts ex.stderr # => ls: rye.test: No such file or directory
156
+ end
157
+
158
+ # The Rye:Rap response objects also give you the STDOUT and STDERR
159
+ # content separately. Here we redirect STDOUT to STDERR, so this
160
+ # will return nothing:
161
+ puts rbox.uname('-a 1>&2').stdout # =>
162
+
163
+ # It all went to STDERR:
164
+ puts rbox.uname('-a 1>&2').stderr # => Darwin ryehost 9.6.0 ...
165
+
166
+ # There were no actual errors so the exit code should be 0.
167
+ puts rbox.uname('-a 1>&2').exit_code # => 0
168
+
169
+
170
+ puts %Q(
171
+ # ------------------------------------------------------------------
172
+ # EXAMPLE 6 -- FILE TRANSFERS
173
+ #)
174
+
175
+ dir_upload = "#{Rye.sysinfo.tmpdir}/rye-upload/"
176
+ dir_download = "#{Rye.sysinfo.tmpdir}/rye-download/"
177
+
178
+ rbox = Rye::Box.new("localhost", :info => false)
179
+
180
+ # Rye ships without an rm method (for safety!). Here
181
+ # we add the rm method only to this instance of rbox.
182
+ def rbox.rm(*args); cmd('rm', args); end
183
+
184
+ rbox.rm(:r, :f, dir_upload) # Silently delete test dirs
185
+ rbox.rm(:r, :f, dir_download)
186
+
187
+ rbox.file_upload("#{RYE_HOME}/README.rdoc",
188
+ "#{RYE_HOME}/LICENSE.txt", dir_upload)
189
+
190
+ applejack = StringIO.new("Some in-memory content")
191
+ rbox.file_upload(applejack, "#{dir_upload}/applejack.txt")
192
+
193
+ p rbox.ls(dir_upload) # => [README.rdoc, LICENSE.txt, applejack.txt]
194
+ p rbox.cat("#{dir_upload}/applejack.txt") # => "Some in-memory content"
195
+
196
+ filecontent = StringIO.new
197
+ rbox.file_download("#{dir_upload}/applejack.txt", filecontent)
198
+ filecontent.rewind
199
+ p filecontent.read
200
+
201
+
202
+
data/lib/rye.rb CHANGED
@@ -43,7 +43,7 @@ module Rye
43
43
  extend self
44
44
 
45
45
  unless defined?(SYSINFO)
46
- VERSION = "0.8.0".freeze
46
+ VERSION = "0.8.1".freeze
47
47
  SYSINFO = SysInfo.new.freeze
48
48
  end
49
49
 
@@ -155,28 +155,26 @@ module Rye
155
155
  # rbox['/usr/bin'].pwd # => /usr/bin ($ cd /usr/bin && pwd)
156
156
  # rbox.pwd # => /usr/bin ($ cd /usr/bin && pwd)
157
157
  #
158
- def [](key=nil)
159
- if key.nil? || key.index('/') == 0
160
- @rye_current_working_directory = key
158
+ def [](fpath=nil)
159
+ if fpath.nil? || fpath.index('/') == 0
160
+ @rye_current_working_directory = fpath
161
161
  else
162
162
  # Append to non-absolute paths
163
- newpath = File.join(@rye_current_working_directory, key)
164
- @rye_current_working_directory = File.expand_path(newpath)
163
+ if @rye_current_working_directory
164
+ newpath = File.join(@rye_current_working_directory, fpath)
165
+ @rye_current_working_directory = newpath
166
+ else
167
+ @rye_current_working_directory = fpath
168
+ end
165
169
  end
170
+ info "CWD: #{@rye_current_working_directory}"
166
171
  self
167
172
  end
168
173
  # Like [] except it returns an empty Rye::Rap object to mimick
169
174
  # a regular command method. Call with nil key (or no arg) to
170
175
  # reset.
171
- def cd(key=nil)
172
- if key.nil? || key.index('/') == 0
173
- @rye_current_working_directory = key
174
- else
175
- # Append to non-absolute paths
176
- newpath = File.join(@rye_current_working_directory, key)
177
- @rye_current_working_directory = File.expand_path(newpath)
178
- end
179
- ret = Rye::Rap.new(self)
176
+ def cd(fpath=nil)
177
+ Rye::Rap.new(self[fpath])
180
178
  end
181
179
 
182
180
  # Change the current umask (sort of -- works the same way as cd)
@@ -237,7 +235,7 @@ module Rye
237
235
  # it, execute it directly, parse the output.
238
236
  def ostype
239
237
  return @rye_ostype if @rye_ostype # simple cache
240
- os = self.uname.first rescue nil
238
+ os = self.quietly { uname.first } rescue nil
241
239
  os ||= 'unknown'
242
240
  os &&= os.downcase
243
241
  @rye_ostype = os
@@ -256,11 +254,11 @@ module Rye
256
254
  #
257
255
  def getenv
258
256
  if @rye_getenv && @rye_getenv.empty? && self.can?(:env)
259
- env = self.env rescue []
260
- env.each do |nv|
257
+ vars = self.quietly { env } rescue []
258
+ vars.each do |nvpair|
261
259
  # Parse "GLORIA_HOME=/gloria/lives/here" into a name/value
262
260
  # pair. The regexp ensures we split only at the 1st = sign
263
- n, v = nv.scan(/\A([\w_-]+?)=(.+)\z/).flatten
261
+ n, v = nvpair.scan(/\A([\w_-]+?)=(.+)\z/).flatten
264
262
  @rye_getenv[n] = v
265
263
  end
266
264
  end
@@ -307,6 +305,7 @@ module Rye
307
305
  # Uses the output of "useradd -D" to determine the default home
308
306
  # directory. This returns a GUESS rather than the a user's real
309
307
  # home directory. Currently used only by authorize_keys_remote.
308
+ # Only useful before you've logged in. Otherwise check $HOME
310
309
  def guess_user_home(other_user=nil)
311
310
  this_user = other_user || opts[:user]
312
311
  @rye_guessed_homes ||= {}
@@ -321,7 +320,7 @@ module Rye
321
320
  # /etc/default/useradd, HOME=/home OR useradd -D
322
321
  # /etc/adduser.config, DHOME=/home OR ??
323
322
  user_defaults = {}
324
- raw = self.useradd(:D) rescue ["HOME=/home"]
323
+ raw = self.quietly { useradd(:D) } rescue ["HOME=/home"]
325
324
  ostmp = self.ostype
326
325
  raw.each do |nv|
327
326
 
@@ -697,8 +696,7 @@ module Rye
697
696
  ## raise Rye::CommandNotFound unless self.can?(cmd)
698
697
 
699
698
  begin
700
- info "COMMAND: #{cmd_clean}"
701
- debug "Executing: #{cmd_internal}"
699
+ info "COMMAND: #{cmd_internal}"
702
700
 
703
701
  if !@rye_quiet && @rye_pre_command_hook.is_a?(Proc)
704
702
  @rye_pre_command_hook.call(cmd_clean, user, host, nickname)
@@ -870,15 +868,26 @@ module Rye
870
868
 
871
869
  # We allow a single file to be downloaded into a StringIO object
872
870
  # but only when no target has been specified.
873
- if direction == :download && files.size == 1
874
- debug "Created StringIO for download"
875
- other = StringIO.new
876
- else
877
- other = files.pop
878
- end
879
-
880
- if direction == :upload && other.is_a?(StringIO)
881
- raise "Cannot upload to a StringIO object"
871
+ if direction == :download
872
+ if files.size == 1
873
+ debug "Created StringIO for download"
874
+ target = StringIO.new
875
+ else
876
+ target = files.pop # The last path is the download target.
877
+ end
878
+
879
+ elsif direction == :upload
880
+ raise "Cannot upload to a StringIO object" if target.is_a?(StringIO)
881
+ if files.size == 1
882
+ target = self.getenv['HOME'] || guess_user_home
883
+ debug "Assuming upload to #{target}"
884
+ else
885
+ target = files.pop
886
+ end
887
+
888
+ # Expand fileglobs (e.g. path/*.rb becomes [path/1.rb, path/2.rb]).
889
+ # This should happen after checking files.size to determine the target
890
+ files = files.collect { |file| Dir.glob file }.flatten unless @rye_safe
882
891
  end
883
892
 
884
893
  # Fail early. We check whether the StringIO object is available to read
@@ -891,21 +900,21 @@ module Rye
891
900
  end
892
901
  end
893
902
 
894
- debug "#{direction.to_s.upcase} TO: #{other}"
903
+ info "#{direction.to_s.upcase} TO: #{target}"
895
904
  debug "FILES: " << files.join(', ')
896
905
 
897
906
  # Make sure the remote directory exists. We can do this only when
898
- # there's more than one file because "other" could be a file name
899
- if files.size > 1 && !other.is_a?(StringIO)
900
- debug "CREATING TARGET DIRECTORY: #{other}"
901
- self.mkdir(:p, other) unless self.file_exists?(other)
907
+ # there's more than one file because "target" could be a file name
908
+ if files.size > 1 && !target.is_a?(StringIO)
909
+ debug "CREATING TARGET DIRECTORY: #{target}"
910
+ self.mkdir(:p, target) unless self.file_exists?(target)
902
911
  end
903
912
 
904
913
  Net::SCP.start(@rye_host, @rye_opts[:user], @rye_opts || {}) do |scp|
905
914
  transfers = []
906
915
  files.each do |file|
907
916
  debug file.to_s
908
- transfers << scp.send(direction, file, other) do |ch, n, s, t|
917
+ transfers << scp.send(direction, file, target) do |ch, n, s, t|
909
918
  pinfo "#{n}: #{s}/#{t}b\r" # update line: "file: sent/total"
910
919
  @rye_info.flush if @rye_info # make sure every line is printed
911
920
  end
@@ -914,7 +923,7 @@ module Rye
914
923
  info $/
915
924
  end
916
925
 
917
- other.is_a?(StringIO) ? other : nil
926
+ target.is_a?(StringIO) ? target : nil
918
927
  end
919
928
 
920
929
 
@@ -36,6 +36,7 @@ module Rye;
36
36
  def du(*args); cmd('du', args); end
37
37
 
38
38
  def env; cmd "env"; end
39
+ def rye(*args); cmd "rye", args; end
39
40
  def pwd(*args); cmd "pwd", args; end
40
41
  def svn(*args); cmd('svn', args); end
41
42
  def cvs(*args); cmd('cvs', args); end
@@ -50,6 +51,7 @@ module Rye;
50
51
  def grep(*args); cmd('grep', args); end
51
52
  def date(*args); cmd('date', args); end
52
53
  def ruby(*args); cmd('ruby', args); end
54
+ def rudy(*args); cmd('rudy', args); end
53
55
  def perl(*args); cmd('perl', args); end
54
56
  def bash(*args); cmd('bash', args); end
55
57
  def echo(*args); cmd('echo', args); end
@@ -77,8 +79,11 @@ module Rye;
77
79
  def bunzip2(*args); cmd('bunzip2', args); end
78
80
  def getconf(*args); cmd('getconf', args); end
79
81
  def history(*args); cmd('history', args); end
82
+ def rudy_s3(*args); cmd('rudy-s3', args); end
80
83
  def printenv(*args); cmd('printenv', args); end
81
84
  def hostname(*args); cmd('hostname', args); end
85
+ def rudy_ec2(*args); cmd('rudy-ec2', args); end
86
+ def rudy_edb(*args); cmd('rudy-sdb', args); end
82
87
  def configure(*args); cmd('./configure', args); end
83
88
 
84
89
  # Transfer files to a machine via Net::SCP.
@@ -1,7 +1,7 @@
1
1
  @spec = Gem::Specification.new do |s|
2
2
  s.name = "rye"
3
3
  s.rubyforge_project = "rye"
4
- s.version = "0.8.0"
4
+ s.version = "0.8.1"
5
5
  s.summary = "Rye: Safely run SSH commands on a bunch of machines at the same time (from Ruby)."
6
6
  s.description = s.summary
7
7
  s.author = "Delano Mandelbaum"
@@ -35,7 +35,9 @@
35
35
  LICENSE.txt
36
36
  README.rdoc
37
37
  Rakefile
38
+ Rudyfile
38
39
  bin/rye
40
+ bin/try
39
41
  lib/esc.rb
40
42
  lib/rye.rb
41
43
  lib/rye/box.rb
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rye
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -86,7 +86,9 @@ files:
86
86
  - LICENSE.txt
87
87
  - README.rdoc
88
88
  - Rakefile
89
+ - Rudyfile
89
90
  - bin/rye
91
+ - bin/try
90
92
  - lib/esc.rb
91
93
  - lib/rye.rb
92
94
  - lib/rye/box.rb