rip 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.gitignore +4 -0
  2. data/LICENSE +20 -0
  3. data/README.markdown +306 -0
  4. data/Rakefile +51 -0
  5. data/bin/rip +6 -0
  6. data/examples/debug.rb +13 -0
  7. data/examples/reverse.rb +21 -0
  8. data/ext/extconf.rb +11 -0
  9. data/lib/rip.rb +53 -0
  10. data/lib/rip/commands.rb +113 -0
  11. data/lib/rip/commands/build.rb +23 -0
  12. data/lib/rip/commands/core.rb +82 -0
  13. data/lib/rip/commands/install.rb +37 -0
  14. data/lib/rip/commands/uninstall.rb +43 -0
  15. data/lib/rip/env.rb +128 -0
  16. data/lib/rip/installer.rb +130 -0
  17. data/lib/rip/memoize.rb +111 -0
  18. data/lib/rip/package.rb +126 -0
  19. data/lib/rip/package_api.rb +94 -0
  20. data/lib/rip/package_manager.rb +175 -0
  21. data/lib/rip/packages/dir_package.rb +34 -0
  22. data/lib/rip/packages/file_package.rb +60 -0
  23. data/lib/rip/packages/gem_package.rb +44 -0
  24. data/lib/rip/packages/git_package.rb +62 -0
  25. data/lib/rip/packages/http_package.rb +46 -0
  26. data/lib/rip/packages/remote_gem_package.rb +64 -0
  27. data/lib/rip/packages/ripfile_package.rb +46 -0
  28. data/lib/rip/setup.rb +205 -0
  29. data/lib/rip/sh/git.rb +35 -0
  30. data/lib/rip/ui.rb +24 -0
  31. data/lib/rip/version.rb +9 -0
  32. data/setup.rb +27 -0
  33. data/test/commands_test.rb +15 -0
  34. data/test/dev.rip +2 -0
  35. data/test/dir_test.rb +25 -0
  36. data/test/env_test.rb +173 -0
  37. data/test/git_test.rb +36 -0
  38. data/test/mock_git.rb +51 -0
  39. data/test/repos/simple_c/dot_git/HEAD +1 -0
  40. data/test/repos/simple_c/dot_git/config +6 -0
  41. data/test/repos/simple_c/dot_git/description +1 -0
  42. data/test/repos/simple_c/dot_git/hooks/applypatch-msg.sample +15 -0
  43. data/test/repos/simple_c/dot_git/hooks/commit-msg.sample +24 -0
  44. data/test/repos/simple_c/dot_git/hooks/post-commit.sample +8 -0
  45. data/test/repos/simple_c/dot_git/hooks/post-receive.sample +15 -0
  46. data/test/repos/simple_c/dot_git/hooks/post-update.sample +8 -0
  47. data/test/repos/simple_c/dot_git/hooks/pre-applypatch.sample +14 -0
  48. data/test/repos/simple_c/dot_git/hooks/pre-commit.sample +18 -0
  49. data/test/repos/simple_c/dot_git/hooks/pre-rebase.sample +169 -0
  50. data/test/repos/simple_c/dot_git/hooks/prepare-commit-msg.sample +36 -0
  51. data/test/repos/simple_c/dot_git/hooks/update.sample +107 -0
  52. data/test/repos/simple_c/dot_git/index +0 -0
  53. data/test/repos/simple_c/dot_git/info/exclude +6 -0
  54. data/test/repos/simple_c/dot_git/logs/HEAD +1 -0
  55. data/test/repos/simple_c/dot_git/logs/refs/heads/master +1 -0
  56. data/test/repos/simple_c/dot_git/objects/2d/94227280db3ac66875f52592c6a736b4526084 +0 -0
  57. data/test/repos/simple_c/dot_git/objects/3f/1d6dacdedf75058e9edf23f48de03fa451f7ce +1 -0
  58. data/test/repos/simple_c/dot_git/objects/53/23e9a7ff897fe7bfc3357d9274775b67f9ade4 +0 -0
  59. data/test/repos/simple_c/dot_git/objects/55/31db58bd71148661c400dc48815bf06b366128 +0 -0
  60. data/test/repos/simple_c/dot_git/objects/d7/55c6f119520808609a8d79bac1a8dbe0c57424 +0 -0
  61. data/test/repos/simple_c/dot_git/objects/d7/58739ea968ac8e8fe0cbbf1f6451af47f04964 +0 -0
  62. data/test/repos/simple_c/dot_git/objects/e6/7b81a24f0ce4bff84c3599b5c9ba7093f554d8 +0 -0
  63. data/test/repos/simple_c/dot_git/objects/ec/be0a80dc841c16beb2c733bbdd320b45565d89 +0 -0
  64. data/test/repos/simple_c/dot_git/refs/heads/master +1 -0
  65. data/test/repos/simple_c/ext/simp/extconf.rb +6 -0
  66. data/test/repos/simple_c/ext/simp/simp.c +17 -0
  67. data/test/repos/simple_c/lib/simple_c.rb +1 -0
  68. data/test/repos/simple_d-1.2.3/lib/simple_d.rb +1 -0
  69. data/test/rip_test.rb +8 -0
  70. data/test/test_helper.rb +79 -0
  71. data/test/ui_test.rb +36 -0
  72. metadata +149 -0
@@ -0,0 +1,4 @@
1
+ _site
2
+ dip
3
+ reset
4
+ irb
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Chris Wanstrath
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,306 @@
1
+ Rip: Ruby's Intelligent Packaging
2
+ =================================
3
+
4
+ Rip is an attempt to create an intelligent packaging system
5
+ for Ruby.
6
+
7
+ For more thorough documentation please see the Rip site:
8
+
9
+ [http://hellorip.com/](http://hellorip.com/)
10
+
11
+ Introduction
12
+ ------------
13
+
14
+ Let's get right to it then, shall we?
15
+
16
+ First we install rip.
17
+
18
+ $ sudo gem install rip
19
+
20
+ Did that work?
21
+
22
+ $ rip check
23
+ All systems go.
24
+
25
+ Yep. Let's see what libraries rip knows about.
26
+
27
+ $ rip list
28
+ ripenv: base
29
+
30
+ nothing installed
31
+
32
+ None. Really? Let's try to require Grit.
33
+
34
+ $ ruby -r grit -e 'puts Grit'
35
+ ruby: no such file to load -- grit (LoadError)
36
+
37
+ Whoops. Not found. Let's install the latest using rip.
38
+
39
+ $ rip install git://github.com/mojombo/grit.git v1.1.1
40
+ Successfully installed grit v1.1.1
41
+ $ rip list
42
+ ripenv: base
43
+
44
+ diff-lcs (5621f02)
45
+ grit (v1.1.1)
46
+ mime-types (0fd8958)
47
+
48
+ Great, now we have Grit and all its dependencies.
49
+
50
+ $ ruby -r grit -e 'puts Grit'
51
+ Grit
52
+ $ ruby -r grit -e 'puts MIME::Types'
53
+ MIME::Types
54
+
55
+ And we don't need any magical `require` statements to use them!
56
+
57
+ If we'd like, we can now move between rip environments to mix
58
+ and match libraries.
59
+
60
+ $ rip env create my_fresh_env
61
+ ripenv: created my_fresh_env
62
+ $ ruby -r grit -e 'puts Grit'
63
+ ruby: no such file to load -- grit (LoadError)
64
+
65
+ And so much more.
66
+
67
+ Overview
68
+ --------
69
+
70
+ Inspired by Python's [virtualenv][1] and [pip][2], Rip aims to be a
71
+ simple and powerful way to install and manage Ruby packages.
72
+
73
+ ### Multiple Package Support
74
+
75
+ Rip can install from a variety of sources: directories, single files,
76
+ git repositories - even Rubygems.
77
+
78
+ Adding a new package is [easy](/packages.html) and we expect Rip to
79
+ support more formats in the future.
80
+
81
+ ### Virtual Environments
82
+
83
+ Virtual environments ("ripenvs") can be created so multiple versions of
84
+ a package may be installed and used by different applications concurrently.
85
+
86
+ ripenvs are easy to create, copy, delete, and share. Recipes for creating
87
+ ripenvs are trivial to generate and publish.
88
+
89
+ ### Install-time Dependency Resolution
90
+
91
+ Dependency checking happens when Rip packages are installed, not
92
+ when packages run.
93
+
94
+ A dependency graph is constructed for the entire virtual environment,
95
+ making it easy to debug leaf-node transitive dependency issues.
96
+
97
+ ### Clear Error Messages
98
+
99
+ Installation and dependency errors should be clear and give as much
100
+ information as possible in order to help you fix the problem.
101
+
102
+ ### Few Dependencies
103
+
104
+ Rip itself should work without anything but the Ruby standard
105
+ library, for maximum portability.
106
+
107
+ Rip vs RubyGems
108
+ ---------------
109
+
110
+ ### No building
111
+
112
+ Rip's support for a variety of package types means there is nothing to
113
+ build and distribute.
114
+
115
+ Tag your Git repository and publicize the latest version, or just pass
116
+ around Gists. Rip does not care.
117
+
118
+ Rip dependencies are listed as separate lines in a plaintext file and
119
+ can reference any package type. As a result, Rip packages can depend
120
+ on existing Rubygems that aren't available from any other source.
121
+
122
+ This means projects unaware of Rip can be installed by Rip and managed by
123
+ ripenvs. Adding the dependencies yourself is easy.
124
+
125
+ ### Multiple Environments
126
+
127
+ Rip makes it easy to have multiple environments with different
128
+ versions of libraries.
129
+
130
+ You could even clone a ripenv then upgrade a single library to test its impact
131
+ on the environment as a whole. Installation not go smoothly? Delete the new
132
+ ripenev then continue using the stable one.
133
+
134
+ ### Dependency Conflict Resolution
135
+
136
+ With Rip, version conflicts in dependencies are simpler to resolve: you
137
+ know exactly what version of which libraries are requesting which versions
138
+ of the same library at installation time. As a result conflicts are resolved
139
+ when you're thinking about installing your code, not later on when you're
140
+ thinking about running it.
141
+
142
+ ### Hands off
143
+
144
+ Rip requires no changes to your code, only an optional `deps.rip` file added
145
+ to the root of your project. As a result you do not force Rip on anyone else
146
+ and individuals are free to re-package your code using other systems.
147
+
148
+ ### Distributed
149
+
150
+ There is no canonical server for Rip packages, which may be good or bad.
151
+
152
+ Installing Packages
153
+ -------------------
154
+
155
+ Each Rip package optionally contains at the root a `deps.rip` file
156
+ identifying it as a Rip package and listing its dependencies.
157
+
158
+ Let's take the [ambition][3] project as an example. This is its
159
+ `deps.rip` in full:
160
+
161
+ git://github.com/drnic/rubigen.git REL-1.3.0
162
+ git://github.com/seattlerb/ruby2ruby.git e3cf57559 # 1.1.8
163
+ git://github.com/seattlerb/parsetree.git 480ede9d9 # 2.1.1
164
+
165
+ If you were to run `rip install git://github.com/defunkt/ambition`
166
+ the following steps would occur:
167
+
168
+ * The source would be fetched and unpacked as `ambition` in the cwd
169
+ * The source of each dependency in `deps.rip` would be fetched
170
+ * Each dependency would be unpacked into the current ripenv at the revision or tag specified
171
+ * Each dependency's `deps.rip` would be fetched and unpacked into the ripenv, etc
172
+
173
+ As this process unfolds, a mapping of libraries and versions is kept
174
+ in memory. When a library is declared multiple times at different
175
+ versions the process is halted and the error reported.
176
+
177
+ If you've cloned `ambition` on your own you can still install the
178
+ dependencies using `rip install deps.rip`
179
+
180
+ Uninstalling Packages
181
+ ---------------------
182
+
183
+ The easiest way to mass uninstall packages is to delete your ripenv
184
+ and create a new one. Otherwise, `rip uninstall package` will do the trick.
185
+
186
+ Rip will complain if you attempt to uninstall a package that others depend
187
+ on. To remove the package anyway, use `-y`. To remove the package and the
188
+ dependents, use `-d` (for dependents).
189
+
190
+ Extensions
191
+ ----------
192
+
193
+ Installing a package that is not Rip aware but needs an extension
194
+ built? Use `rip build`.
195
+
196
+ Rip will attempt to run `rake rip:install` in your library if a
197
+ Rakefile is found. If you need to compile your C extension or do
198
+ any other work, this is the place.
199
+
200
+ Rip Directory Structure
201
+ -----------------------
202
+
203
+ Rip is currently user-specific.
204
+
205
+ Here is a typical directory structure for Rip:
206
+
207
+ rip/
208
+ - rip-packages/
209
+ - active/
210
+ - bin/
211
+ - lib/
212
+ - base/
213
+ - bin/
214
+ - lib/
215
+ - base.ripenv
216
+ - cheat/
217
+ - bin/
218
+ - lib/
219
+ - cheat.ripenv
220
+ - thunderhorse/
221
+ - bin/
222
+ - lib/
223
+ - thunderhorse.ripenv
224
+
225
+ The above contains three ripenvs: `base`, `cheat`, and `thunderhose`. Each
226
+ ripenv contains directories for executable binaries and Ruby source files.
227
+ They also include a generated `.ripenv` file containing metadata about
228
+ the ripenev and its packages.
229
+
230
+ This individual may use `base` for general tomfoolery (it's the
231
+ default), `cheat` for developing their Cheat application, and
232
+ `thunderhorse` for working on their new Thunderhose project.
233
+
234
+ `active` is a symlink to the current, active ripenv. We also see a
235
+ `rip-packages` directory. This is where Rip stores the raw repositories.
236
+
237
+ Let us focus on the `cheat` ripenv:
238
+
239
+ rip/
240
+ - cheat/
241
+ - bin/
242
+ - camping
243
+ - lib/
244
+ - markaby/
245
+ - builder.rb
246
+ - cssproxy.rb
247
+ - metaid.rb
248
+ - rails.rb
249
+ - tags.rb
250
+ - template.rb
251
+ - markaby.rb
252
+ - camping/
253
+ - db.rb
254
+ - fastcgi.rb
255
+ - reloader.rb
256
+ - session.rb
257
+ - webrick.rb
258
+ - camping-unabridged.rb
259
+ - camping.rb
260
+ - cheat.ripenv
261
+
262
+ When using the `cheat` ripenv, a `camping` binary will be in our `PATH`.
263
+
264
+ When running Ruby scripts, or even executing the `camping` binary,
265
+ `rip/cheat/lib` will be in our $LOAD_PATH. Therefor we may, for instance,
266
+ `require "markaby"` in a Ruby script and it will succeed.
267
+
268
+ In any other ripenv, the `cheat` ripenv's binaries and libraries are as
269
+ good as non-existant.
270
+
271
+ Deployment
272
+ ----------
273
+
274
+ Want to get a copy of your local environment on your deployment
275
+ server? Generate a `.rip` file with `rip freeze` then upload and
276
+ install it.
277
+
278
+ Shortcomings
279
+ ------------
280
+
281
+ Currently it's UNIX-only. This is because Rip needs to manipulate the RUBYLIB
282
+ and PATH environment variables so that Ruby knows where to find installed Rip
283
+ packages.
284
+
285
+ As a result, the setup script expects you to be running bash or zshell.
286
+
287
+ Contributors
288
+ ------------
289
+
290
+ * Chris Wanstrath (that's me!)
291
+ * Jeff Hodges
292
+ * Tom Preston-Werner
293
+ * John Barnette
294
+ * Blake Mizerany
295
+ * Ryan Tomayko
296
+ * Pat Nakajima
297
+
298
+ Special Thanks
299
+ --------------
300
+
301
+ * Coda Hale for the phrase "leaf-node transitive dependency issues"
302
+ * GitHub for sponsoring development
303
+
304
+ [1]: http://pypi.python.org/pypi/virtualenv
305
+ [2]: http://pypi.python.org/pypi/pip
306
+ [3]: http://github.com/defunkt/ambition
@@ -0,0 +1,51 @@
1
+ require "rake/testtask"
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << "test"
5
+ t.test_files = FileList["test/**/*_test.rb"]
6
+ t.verbose = true
7
+ end
8
+
9
+ task :default => :test
10
+
11
+ begin
12
+ require 'jeweler'
13
+
14
+ # We're not putting VERSION or VERSION.yml in the root,
15
+ # so we have to help Jeweler find our version.
16
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
17
+ require 'rip/version'
18
+ require 'rip/setup'
19
+
20
+ Rip::Version.instance_eval do
21
+ def refresh
22
+ end
23
+ end
24
+
25
+ class Jeweler
26
+ def version_helper
27
+ Rip::Version
28
+ end
29
+
30
+ def version_exists?
31
+ true
32
+ end
33
+ end
34
+
35
+ Jeweler::Tasks.new do |gemspec|
36
+ gemspec.name = "rip"
37
+ gemspec.summary = "Rip: Ruby's Intelligent Packaging"
38
+ gemspec.email = "chris@ozmm.org"
39
+ gemspec.homepage = "http://hellorip.com"
40
+ gemspec.description = "Rip: Ruby's Intelligent Packaging"
41
+ gemspec.authors = ["Chris Wanstrath"]
42
+ gemspec.extensions = ["ext/extconf.rb"]
43
+ gemspec.executables = ['']
44
+ gemspec.has_rdoc = false
45
+ gemspec.extra_rdoc_files = ['']
46
+ gemspec.post_install_message = Rip::Setup.finish_setup_banner
47
+ end
48
+ rescue LoadError
49
+ puts "Jeweler not available."
50
+ puts "Install it with: rip install technicalpickles-jeweler"
51
+ end
data/bin/rip ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rip'
4
+ require 'rip/commands'
5
+
6
+ Rip::Commands.invoke(ARGV)
@@ -0,0 +1,13 @@
1
+ # file:lib/rip/commands/debug.rb
2
+ #
3
+ # This file would normally live in lib/rip/commands or ~/.rip/rip-commands
4
+ #
5
+ # See the `Plugins` section of the README for more information.
6
+ #
7
+
8
+ module Rip::Commands
9
+ def debug(options, *args)
10
+ puts "options: #{options.inspect}"
11
+ puts "args: #{args.inspect}"
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # file:lib/rip/commands/reverse.rb
2
+ #
3
+ # This file would normally live in lib/rip/commands or ~/.rip/rip-commands
4
+ #
5
+ # See the `Plugins` section of the README for more information.
6
+ #
7
+
8
+ module Rip
9
+ module Commands
10
+ def reverse(options = {}, package = nil, *args)
11
+ puts "ripenv: #{Rip::Env.active}", ''
12
+ if package
13
+ puts package.reverse
14
+ else
15
+ manager.packages.each do |package|
16
+ puts package.to_s.reverse
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ #
2
+ # rip needs some magic to get working.
3
+ # this is, as they say, where the magic happens.
4
+ #
5
+
6
+ __DIR__ = File.expand_path(File.dirname(__FILE__))
7
+ $LOAD_PATH.unshift File.join(__DIR__, '..')
8
+
9
+ File.open('Makefile', 'w') { |f| f.puts("install:\n\t$(echo ok)") }
10
+
11
+ require 'setup'
@@ -0,0 +1,53 @@
1
+ require 'fileutils'
2
+
3
+ module Rip
4
+ def self.dir
5
+ return @dir if @dir
6
+
7
+ dir = ENV['RIPDIR'].to_s
8
+
9
+ if dir.empty?
10
+ abort "RIPDIR env variable not found. did you run setup.rb?"
11
+ end
12
+
13
+ dir = File.expand_path(dir)
14
+ FileUtils.mkdir_p dir unless File.exists? dir
15
+ @dir = dir
16
+ end
17
+
18
+ def self.dir=(dir)
19
+ @dir = dir
20
+ end
21
+
22
+ def self.ui
23
+ @ui ||= Rip::UI.new(STDOUT)
24
+ end
25
+
26
+ def self.ui=(io)
27
+ @ui = Rip::UI.new(io)
28
+ end
29
+ end
30
+
31
+ # load rip files
32
+
33
+ require 'rip/ui'
34
+ require 'rip/version'
35
+ require 'rip/env'
36
+ require 'rip/memoize'
37
+ require 'rip/installer'
38
+ require 'rip/package_api'
39
+ require 'rip/package'
40
+ require 'rip/package_manager'
41
+ require 'rip/setup'
42
+ require 'rip/sh/git'
43
+
44
+
45
+ # load rip packages - order is important
46
+
47
+ require 'rip/packages/ripfile_package'
48
+ require 'rip/packages/git_package'
49
+ require 'rip/packages/http_package'
50
+ require 'rip/packages/gem_package'
51
+ require 'rip/packages/dir_package'
52
+ require 'rip/packages/file_package'
53
+ require 'rip/packages/remote_gem_package'