jmoses-couchbase 1.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/.gitignore +15 -0
  2. data/.travis.yml +22 -0
  3. data/.yardopts +5 -0
  4. data/CONTRIBUTING.markdown +75 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +201 -0
  7. data/Makefile +3 -0
  8. data/README.markdown +665 -0
  9. data/RELEASE_NOTES.markdown +819 -0
  10. data/Rakefile +20 -0
  11. data/couchbase.gemspec +49 -0
  12. data/examples/chat-em/Gemfile +7 -0
  13. data/examples/chat-em/README.markdown +45 -0
  14. data/examples/chat-em/server.rb +82 -0
  15. data/examples/chat-goliath-grape/Gemfile +5 -0
  16. data/examples/chat-goliath-grape/README.markdown +50 -0
  17. data/examples/chat-goliath-grape/app.rb +67 -0
  18. data/examples/chat-goliath-grape/config/app.rb +20 -0
  19. data/examples/transcoders/Gemfile +3 -0
  20. data/examples/transcoders/README.markdown +59 -0
  21. data/examples/transcoders/cb-zcat +40 -0
  22. data/examples/transcoders/cb-zcp +45 -0
  23. data/examples/transcoders/gzip_transcoder.rb +49 -0
  24. data/examples/transcoders/options.rb +54 -0
  25. data/ext/couchbase_ext/.gitignore +4 -0
  26. data/ext/couchbase_ext/arguments.c +956 -0
  27. data/ext/couchbase_ext/arithmetic.c +316 -0
  28. data/ext/couchbase_ext/bucket.c +1373 -0
  29. data/ext/couchbase_ext/context.c +65 -0
  30. data/ext/couchbase_ext/couchbase_ext.c +1364 -0
  31. data/ext/couchbase_ext/couchbase_ext.h +644 -0
  32. data/ext/couchbase_ext/delete.c +163 -0
  33. data/ext/couchbase_ext/eventmachine_plugin.c +452 -0
  34. data/ext/couchbase_ext/extconf.rb +169 -0
  35. data/ext/couchbase_ext/get.c +316 -0
  36. data/ext/couchbase_ext/gethrtime.c +129 -0
  37. data/ext/couchbase_ext/http.c +432 -0
  38. data/ext/couchbase_ext/multithread_plugin.c +1090 -0
  39. data/ext/couchbase_ext/observe.c +171 -0
  40. data/ext/couchbase_ext/plugin_common.c +171 -0
  41. data/ext/couchbase_ext/result.c +129 -0
  42. data/ext/couchbase_ext/stats.c +163 -0
  43. data/ext/couchbase_ext/store.c +542 -0
  44. data/ext/couchbase_ext/timer.c +192 -0
  45. data/ext/couchbase_ext/touch.c +186 -0
  46. data/ext/couchbase_ext/unlock.c +176 -0
  47. data/ext/couchbase_ext/utils.c +551 -0
  48. data/ext/couchbase_ext/version.c +142 -0
  49. data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
  50. data/lib/active_support/cache/couchbase_store.rb +430 -0
  51. data/lib/couchbase.rb +155 -0
  52. data/lib/couchbase/bucket.rb +457 -0
  53. data/lib/couchbase/cluster.rb +119 -0
  54. data/lib/couchbase/connection_pool.rb +58 -0
  55. data/lib/couchbase/constants.rb +12 -0
  56. data/lib/couchbase/result.rb +26 -0
  57. data/lib/couchbase/transcoder.rb +120 -0
  58. data/lib/couchbase/utils.rb +62 -0
  59. data/lib/couchbase/version.rb +21 -0
  60. data/lib/couchbase/view.rb +506 -0
  61. data/lib/couchbase/view_row.rb +272 -0
  62. data/lib/ext/multi_json_fix.rb +56 -0
  63. data/lib/rack/session/couchbase.rb +108 -0
  64. data/tasks/benchmark.rake +6 -0
  65. data/tasks/compile.rake +160 -0
  66. data/tasks/test.rake +100 -0
  67. data/tasks/util.rake +21 -0
  68. data/test/profile/.gitignore +1 -0
  69. data/test/profile/Gemfile +6 -0
  70. data/test/profile/benchmark.rb +195 -0
  71. data/test/setup.rb +178 -0
  72. data/test/test_arithmetic.rb +185 -0
  73. data/test/test_async.rb +316 -0
  74. data/test/test_bucket.rb +276 -0
  75. data/test/test_cas.rb +235 -0
  76. data/test/test_couchbase.rb +77 -0
  77. data/test/test_couchbase_connection_pool.rb +77 -0
  78. data/test/test_couchbase_rails_cache_store.rb +361 -0
  79. data/test/test_delete.rb +120 -0
  80. data/test/test_errors.rb +82 -0
  81. data/test/test_eventmachine.rb +70 -0
  82. data/test/test_format.rb +164 -0
  83. data/test/test_get.rb +407 -0
  84. data/test/test_stats.rb +57 -0
  85. data/test/test_store.rb +216 -0
  86. data/test/test_timer.rb +42 -0
  87. data/test/test_touch.rb +97 -0
  88. data/test/test_unlock.rb +119 -0
  89. data/test/test_utils.rb +58 -0
  90. data/test/test_version.rb +52 -0
  91. metadata +353 -0
@@ -0,0 +1,272 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011-2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ module Couchbase
19
+ # This class encapsulates structured JSON document
20
+ #
21
+ # @since 1.2.0
22
+ #
23
+ # It behaves like Hash for document included into row, and has access methods to row data as well.
24
+ #
25
+ # @see http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-datastore.html
26
+ class ViewRow
27
+ include Constants
28
+
29
+ # Undefine as much methods as we can to free names for views
30
+ instance_methods.each do |m|
31
+ undef_method(m) if m.to_s !~ /(?:^__|^nil\?$|^send$|^object_id$|^class$|)/
32
+ end
33
+
34
+ # The hash built from JSON document.
35
+ #
36
+ # @since 1.2.0
37
+ #
38
+ # This is complete response from the Couchbase
39
+ #
40
+ # @return [Hash]
41
+ attr_accessor :data
42
+
43
+ # The key which was emitted by map function
44
+ #
45
+ # @since 1.2.0
46
+ #
47
+ # @see http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-writing-map.html
48
+ #
49
+ # Usually it is String (the object +_id+) but it could be also any
50
+ # compount JSON value.
51
+ #
52
+ # @return [Object]
53
+ attr_accessor :key
54
+
55
+ # The value which was emitted by map function
56
+ #
57
+ # @since 1.2.0
58
+ #
59
+ # @see http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-writing-map.html
60
+ #
61
+ # @return [Object]
62
+ attr_accessor :value
63
+
64
+ # The document hash.
65
+ #
66
+ # @since 1.2.0
67
+ #
68
+ # It usually available when view executed with +:include_doc+ argument.
69
+ #
70
+ # @return [Hash]
71
+ attr_accessor :doc
72
+
73
+ # The identificator of the document
74
+ #
75
+ # @since 1.2.0
76
+ #
77
+ # @return [String]
78
+ attr_accessor :id
79
+
80
+ # The meta data linked to the document
81
+ #
82
+ # @since 1.2.0
83
+ #
84
+ # @return [Hash]
85
+ attr_accessor :meta
86
+
87
+ # Initialize the document instance
88
+ #
89
+ # @since 1.2.0
90
+ #
91
+ # It takes reference to the bucket, data hash.
92
+ #
93
+ # @param [Couchbase::Bucket] bucket the reference to connection
94
+ # @param [Hash] data the data hash, which was built from JSON document
95
+ # representation
96
+ def initialize(bucket, data)
97
+ @bucket = bucket
98
+ @data = data
99
+ @key = data[S_KEY]
100
+ @value = data[S_VALUE]
101
+ if data[S_DOC]
102
+ @meta = data[S_DOC][S_META]
103
+ @doc = data[S_DOC][S_VALUE]
104
+ end
105
+ @id = data[S_ID] || @meta && @meta[S_ID]
106
+ @last = data.delete(S_IS_LAST) || false
107
+ end
108
+
109
+ # Wraps data hash into ViewRow instance
110
+ #
111
+ # @since 1.2.0
112
+ #
113
+ # @see ViewRow#initialize
114
+ #
115
+ # @param [Couchbase::Bucket] bucket the reference to connection
116
+ # @param [Hash] data the data hash, which was built from JSON document
117
+ # representation
118
+ #
119
+ # @return [ViewRow]
120
+ def self.wrap(bucket, data)
121
+ self.new(bucket, data)
122
+ end
123
+
124
+ # Get attribute of the document
125
+ #
126
+ # @since 1.2.0
127
+ #
128
+ # Fetches attribute from underlying document hash
129
+ #
130
+ # @param [String] key the attribute name
131
+ #
132
+ # @return [Object] property value or nil
133
+ def [](key)
134
+ @doc[key]
135
+ end
136
+
137
+ # Check attribute existence
138
+ #
139
+ # @since 1.2.0
140
+ #
141
+ # @param [String] key the attribute name
142
+ #
143
+ # @return [true, false] +true+ if the given attribute is present in in
144
+ # the document.
145
+ def has_key?(key)
146
+ @doc.has_key?(key)
147
+ end
148
+
149
+ # Set document attribute
150
+ #
151
+ # @since 1.2.0
152
+ #
153
+ # Set or update the attribute in the document hash
154
+ #
155
+ # @param [String] key the attribute name
156
+ # @param [Object] value the attribute value
157
+ #
158
+ # @return [Object] the value
159
+ def []=(key, value)
160
+ @doc[key] = value
161
+ end
162
+
163
+ # Signals if this row is last in a stream
164
+ #
165
+ # @since 1.2.1
166
+ #
167
+ # @return [true, false] +true+ if this row is last in a stream
168
+ def last?
169
+ @last
170
+ end
171
+
172
+ def inspect
173
+ desc = "#<#{self.class.name}:#{self.object_id}"
174
+ [:@id, :@key, :@value, :@doc, :@meta].each do |iv|
175
+ desc << " #{iv}=#{instance_variable_get(iv).inspect}"
176
+ end
177
+ desc << ">"
178
+ desc
179
+ end
180
+ end
181
+
182
+ # This class encapsulates information about design docs
183
+ #
184
+ # @since 1.2.1
185
+ #
186
+ # It is subclass of ViewRow, but also gives access to view creation through method_missing
187
+ #
188
+ # @see http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-datastore.html
189
+ class DesignDoc < ViewRow
190
+ # It isn't allowed to change design document ID after
191
+ # initialization
192
+ undef id=
193
+
194
+ # Initialize the design doc instance
195
+ #
196
+ # @since 1.2.1
197
+ #
198
+ # It takes reference to the bucket, data hash. It will define view
199
+ # methods if the data object looks like design document.
200
+ #
201
+ # @param [Couchbase::Bucket] bucket the reference to connection
202
+ # @param [Hash] data the data hash, which was built from JSON document
203
+ # representation
204
+ def initialize(bucket, data)
205
+ super
206
+ @all_views = {}
207
+ @views = @doc.has_key?('views') ? @doc['views'].keys : []
208
+ @spatial = @doc.has_key?('spatial') ? @doc['spatial'].keys : []
209
+ @views.each{|name| @all_views[name] = "#{@id}/_view/#{name}"}
210
+ @spatial.each{|name| @all_views[name] = "#{@id}/_spatial/#{name}"}
211
+ end
212
+
213
+ def method_missing(meth, *args)
214
+ if path = @all_views[meth.to_s]
215
+ View.new(@bucket, path, *args)
216
+ else
217
+ super
218
+ end
219
+ end
220
+
221
+ def respond_to?(meth, *args)
222
+ if @all_views[meth.to_s]
223
+ true
224
+ else
225
+ super
226
+ end
227
+ end
228
+
229
+ def method(meth, *args)
230
+ if path = @all_views[meth.to_s]
231
+ lambda{|*p| View.new(@bucket, path, *p)}
232
+ else
233
+ super
234
+ end
235
+ end
236
+
237
+ # The list of views defined or empty array
238
+ #
239
+ # @since 1.2.1
240
+ #
241
+ # @return [Array<View>]
242
+ attr_accessor :views
243
+
244
+ # The list of spatial views defined or empty array
245
+ #
246
+ # @since 1.2.1
247
+ #
248
+ # @return [Array<View>]
249
+ attr_accessor :spatial
250
+
251
+ # Check if the document has views defines
252
+ #
253
+ # @since 1.2.1
254
+ #
255
+ # @see DesignDoc#views
256
+ #
257
+ # @return [true, false] +true+ if the document have views
258
+ def has_views?
259
+ !@views.empty?
260
+ end
261
+
262
+ def inspect
263
+ desc = "#<#{self.class.name}:#{self.object_id}"
264
+ [:@id, :@views, :@spatial].each do |iv|
265
+ desc << " #{iv}=#{instance_variable_get(iv).inspect}"
266
+ end
267
+ desc << ">"
268
+ desc
269
+ end
270
+
271
+ end
272
+ end
@@ -0,0 +1,56 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ # This patch fixing loading primitives like strings, numbers and booleans
19
+ # using json_gem. It amends behaviour of MultiJson::Engines::JsonGem#load
20
+ # when it receives JSON string which neither Array nor Object.
21
+
22
+ if MultiJson.respond_to?(:engine)
23
+ multi_json_engine = MultiJson.send(:engine)
24
+ else
25
+ multi_json_engine = MultiJson.send(:adapter)
26
+ end
27
+
28
+ # Patch for MultiJson versions < 1.3.3
29
+ require 'multi_json/version'
30
+ version = begin
31
+ MultiJson::VERSION
32
+ rescue NameError
33
+ MultiJson::Version.to_s
34
+ end.dup # because Gem::Version modifies it
35
+ if Gem::Version.new(version) < Gem::Version.new('1.3.3')
36
+ class << MultiJson
37
+ alias :dump :encode
38
+ alias :load :decode
39
+ end
40
+ end
41
+
42
+ if multi_json_engine.name =~ /JsonGem$/
43
+ class << multi_json_engine
44
+ alias _load_object load
45
+ def load(string, options = {})
46
+ if string.respond_to?(:read)
47
+ string = string.read
48
+ end
49
+ if string =~ /\A\s*[{\[]/
50
+ _load_object(string, options)
51
+ else
52
+ _load_object("[#{string}]", options)[0]
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,108 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'rack/session/abstract/id'
19
+ require 'couchbase'
20
+ require 'thread'
21
+
22
+ module Rack
23
+ module Session
24
+
25
+ # This is Couchbase-powered session store for rack applications
26
+ #
27
+ # To use it just load it as usual middleware in your `config.ru` file
28
+ #
29
+ # require 'rack/session/couchbase'
30
+ # use Rack::Session::Couchbase
31
+ #
32
+ # You can also pass additional options:
33
+ #
34
+ # require 'rack/session/couchbase'
35
+ # use Rack::Session::Couchbase, :expire_after => 5.minutes,
36
+ # :couchbase => {:bucket => "sessions", :default_format => :document}
37
+ #
38
+ # By default sessions will be serialized using Marshal class. But
39
+ # you can store them as JSON (+:default_format => :document+), to
40
+ # allow analyse them using Map/Reduce. In this case you should
41
+ # care about serialization of all custom objects like
42
+ # ActionDispatch::Flash::FlashHash
43
+ #
44
+ class Couchbase < Abstract::ID
45
+ attr_reader :mutex, :pool
46
+
47
+ DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge(
48
+ :couchbase => {:quiet => true, :default_format => :marshal,
49
+ :key_prefix => 'rack:session:'})
50
+
51
+ def initialize(app, options = {})
52
+ # Support old :expires option
53
+ options[:expire_after] ||= options[:expires]
54
+ super
55
+
56
+ @default_options[:couchbase][:default_ttl] ||= options[:expire_after]
57
+ @default_options[:couchbase][:key_prefix] ||= options[:namespace]
58
+ @namespace = @default_options[:couchbase][:key_prefix]
59
+ @mutex = Mutex.new
60
+ @pool = ::Couchbase.connect(@default_options[:couchbase])
61
+ end
62
+
63
+ def generate_sid
64
+ while true
65
+ sid = super
66
+ break sid unless @pool.get(sid)
67
+ end
68
+ end
69
+
70
+ def get_session(env, sid)
71
+ with_lock(env, [nil, {}]) do
72
+ unless sid and session = @pool.get(sid)
73
+ sid, session = generate_sid, {}
74
+ @pool.set(sid, session)
75
+ end
76
+ [sid, session]
77
+ end
78
+ end
79
+
80
+ def set_session(env, session_id, new_session, options)
81
+ with_lock(env, false) do
82
+ @pool.set(session_id, new_session, options)
83
+ session_id
84
+ end
85
+ end
86
+
87
+ def destroy_session(env, session_id, options)
88
+ with_lock(env) do
89
+ @pool.delete(session_id)
90
+ generate_sid unless options[:drop]
91
+ end
92
+ end
93
+
94
+ def with_lock(env, default = nil)
95
+ @mutex.lock if env['rack.multithread']
96
+ yield
97
+ rescue ::Couchbase::Error::Connect, ::Couchbase::Error::Timeout
98
+ if $VERBOSE
99
+ warn "#{self} is unable to find Couchbase server."
100
+ warn $!.inspect
101
+ end
102
+ default
103
+ ensure
104
+ @mutex.unlock if @mutex.locked?
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,6 @@
1
+ desc 'Run benchmarks and compare them to memcached and dalli gems'
2
+ task :benchmark => [:clean, :compile] do
3
+ cd File.expand_path(File.join(__FILE__, '..', '..', 'test', 'profile')) do
4
+ sh "bundle install && bundle exec ruby benchmark.rb | tee benchmark-#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}.log"
5
+ end
6
+ end
@@ -0,0 +1,160 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ gem 'rake-compiler', '>= 0.7.5'
19
+ require "rake/extensiontask"
20
+
21
+ def gemspec
22
+ @clean_gemspec ||= eval(File.read(File.expand_path('../../couchbase.gemspec', __FILE__)))
23
+ end
24
+
25
+ version_router = lambda do |t|
26
+ File.open(t.name, 'wb') do |f|
27
+ f.write <<-RUBY
28
+ require "couchbase/\#{RUBY_VERSION.sub(/\\.\\d+$/, '')}/couchbase_ext"
29
+ RUBY
30
+ end
31
+ end
32
+
33
+ class Platform
34
+ attr_reader :name, :host, :versions
35
+
36
+ def initialize(params)
37
+ @name = params[:name]
38
+ @host = params[:host]
39
+ @versions = params[:versions]
40
+ end
41
+
42
+ def each_version
43
+ @versions.each do |v|
44
+ yield(v, v[/\d\.\d\.\d/])
45
+ end
46
+ end
47
+
48
+ def short_versions
49
+ res = []
50
+ each_version do |long, short|
51
+ res << short
52
+ end
53
+ res
54
+ end
55
+ end
56
+
57
+ recent = "2.0.0-p353"
58
+ CROSS_PLATFORMS = [
59
+ Platform.new(:name => 'x64-mingw32', :host => 'x86_64-w64-mingw32', :versions => %w(1.9.3-p484 2.0.0-p353 2.1.0)),
60
+ Platform.new(:name => 'x86-mingw32', :host => 'i686-w64-mingw32', :versions => %w(1.8.7-p374 1.9.3-p484 2.0.0-p353 2.1.0)),
61
+ ]
62
+
63
+ # Setup compile tasks. Configuration can be passed via ENV.
64
+ # Example:
65
+ # rake compile with_libcouchbase_include=/opt/couchbase/include
66
+ # with_libcouchbase_lib=/opt/couchbase/lib
67
+ #
68
+ # or
69
+ #
70
+ # rake compile with_libcouchbase_dir=/opt/couchbase
71
+ #
72
+ Rake::ExtensionTask.new("couchbase_ext", gemspec) do |ext|
73
+ ext.cross_compile = true
74
+ ext.cross_platform = ENV['TARGET']
75
+ if ENV['RUBY_CC_VERSION']
76
+ ext.lib_dir = "lib/couchbase"
77
+ end
78
+ ext.cross_compiling do |spec|
79
+ spec.files.delete("lib/couchbase/couchbase_ext.so")
80
+ spec.files.push("lib/couchbase_ext.rb", Dir["lib/couchbase/*/couchbase_ext.so"])
81
+ spec.files.push(Dir["lib/couchbase/*/couchbase_ext.so"])
82
+ file "#{ext.tmp_dir}/#{ext.cross_platform}/stage/lib/couchbase_ext.rb", &version_router
83
+ end
84
+
85
+ CLEAN.include "#{ext.lib_dir}/*.#{RbConfig::CONFIG['DLEXT']}"
86
+
87
+ ENV.each do |key, val|
88
+ next unless key =~ /\Awith_(\w+)\z/i
89
+ opt = $1.downcase.tr('_', '-')
90
+ if File.directory?(path = File.expand_path(val))
91
+ ext.config_options << "--with-#{opt}=#{path}"
92
+ else
93
+ warn "No such directory: #{opt}: #{path}"
94
+ end
95
+ end
96
+ end
97
+
98
+ require 'rubygems/package_task'
99
+ Gem::PackageTask.new(gemspec) do |pkg|
100
+ pkg.need_tar = pkg.need_zip = false
101
+ end
102
+
103
+ require 'mini_portile'
104
+ require 'rake/extensioncompiler'
105
+
106
+ class MiniPortile
107
+ alias :cook_without_checkpoint :cook
108
+ def cook
109
+ checkpoint = "ports/.#{name}-#{version}-#{host}.installed"
110
+ unless File.exist?(checkpoint)
111
+ cook_without_checkpoint
112
+ FileUtils.touch(checkpoint)
113
+ end
114
+ end
115
+ end
116
+
117
+ file "lib/couchbase_ext.rb", &version_router
118
+
119
+ desc "Package gem for windows"
120
+ task "package:windows" => ["package", "lib/couchbase_ext.rb"] do
121
+ vars = [
122
+ 'CC',
123
+ 'CFLAGS',
124
+ 'CPATH',
125
+ 'CPP',
126
+ 'CPPFLAGS',
127
+ 'LDFLAGS',
128
+ 'LIBRARY_PATH',
129
+ 'PATH'
130
+ ].reduce({}) do |h, v|
131
+ h[v] = ENV[v]
132
+ h
133
+ end
134
+ ENV['LDFLAGS'] = '-static-libgcc'
135
+
136
+ CROSS_PLATFORMS.each do |platform|
137
+ ENV['TARGET'] = platform.name
138
+ rm_rf("tmp/ ports/")
139
+ mkdir_p("ports")
140
+ recipe = MiniPortile.new("libcouchbase", "2.2.0_30_gc87bec4")
141
+ recipe.host = platform.host
142
+ recipe.files << "http://packages.couchbase.com/clients/c/libcouchbase-#{recipe.version}.tar.gz"
143
+ recipe.configure_options.push("--disable-debug",
144
+ "--disable-dependency-tracking",
145
+ "--disable-couchbasemock",
146
+ "--disable-cxx",
147
+ "--disable-plugins",
148
+ "--disable-examples",
149
+ "--disable-tools")
150
+ recipe.cook
151
+ recipe.activate
152
+ platform.each_version do |long, short|
153
+ sh("env RUBY_CC_VERSION=#{short} RBENV_VERSION=#{long} rbenv exec rake cross compile")
154
+ end
155
+ vars.each do |k, v|
156
+ ENV[k] = v
157
+ end
158
+ sh("env RUBY_CC_VERSION=#{platform.short_versions.join(":")} RBENV_VERSION=#{recent} rbenv exec rake cross native gem")
159
+ end
160
+ end