mordor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ gemspec
data/README ADDED
@@ -0,0 +1,13 @@
1
+ Small library to add DataMapper style resources for MongoDB.
2
+
3
+ class ExampleResource
4
+ include Mordor::Resource
5
+
6
+ attribute :first
7
+ attribute :second
8
+ attribute :third, :finder_method => :find_by_third_attribute
9
+ end
10
+
11
+ This adds attr_accessors to the ExampleResource for each attribute, plus adds finder methods of the form
12
+ find_by_{attribute}. The naming convention can be overridden by using the optional :finder_method option,
13
+ as can be seen with the third attribute.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ load('tasks/github-gem.rake')
2
+
3
+ # Register the gem release tasks in the gem namespace
4
+ GithubGem::RakeTasks.new(:gem) do |config|
5
+
6
+ # Note that the following values are all default values and can
7
+ # therefore be omitted if they are not changed.
8
+
9
+ config.gemspec_file = GithubGem.detect_gemspec_file
10
+ config.main_include = GithubGem.detect_main_include
11
+ config.root_dir = Dir.pwd
12
+ config.test_pattern = 'test/**/*_test.rb'
13
+ config.spec_pattern = 'spec/**/*_spec.rb'
14
+ config.local_branch = 'master'
15
+ config.remote = 'origin'
16
+ config.remote_branch = 'master'
17
+ end
data/lib/mordor.rb ADDED
@@ -0,0 +1,97 @@
1
+ require 'rubygems'
2
+ require 'mongo'
3
+ require 'extlib'
4
+ require 'mordor/version'
5
+ require 'mordor/collection'
6
+ require 'mordor/resource'
7
+
8
+ unless Object.const_defined?('BigDecimal')
9
+ BigDecimal = Float
10
+ end
11
+
12
+ class Date
13
+ def to_time(form = :utc)
14
+ Time.send("#{form}", year, month, day)
15
+ end
16
+
17
+ def to_gm
18
+ Time.gm(year, month, day).to_datetime
19
+ end
20
+
21
+ def to_local
22
+ Time.local(year, month, day).to_datetime
23
+ end
24
+
25
+ def to_datetime
26
+ DateTime.civil(self.year, self.mon, self.day)
27
+ end
28
+
29
+ def show(format = nil)
30
+ case format
31
+ when :human
32
+ strftime("%d-%m-%Y")
33
+ else
34
+ to_s
35
+ end
36
+ end
37
+
38
+ def full_string
39
+ strftime("%A %d %B %Y")
40
+ end
41
+ end
42
+
43
+ class DateTime
44
+ def to_datetime
45
+ self
46
+ end
47
+
48
+ def to_date
49
+ Date.civil(self.year, self.mon, self.day)
50
+ end
51
+
52
+ def show(format = nil)
53
+ case format
54
+ when :human
55
+ strftime("%d-%m-%Y %H:%M")
56
+ when :full
57
+ strftime("%d-%m-%Y %H:%M:%S")
58
+ else
59
+ to_s
60
+ end
61
+ end
62
+ end
63
+
64
+ class Time
65
+
66
+ def to_date
67
+ Date.civil(year, month, day)
68
+ end if RUBY_VERSION < '1.8.6'
69
+
70
+ def show(format = nil)
71
+ return self.to_date.show(format) if [hour,min] == [0,0]
72
+ case format
73
+ when :human
74
+ strftime("%d-%m-%Y %H:%m")
75
+ when :full
76
+ strftime("%d-%m-%Y %H:%M:%S")
77
+ else
78
+ to_s
79
+ end
80
+ end
81
+ end
82
+
83
+ module Mordor
84
+ CONFIG = {
85
+ :hostname => 'localhost',
86
+ :port => 27017,
87
+ :database => 'development'
88
+ }
89
+
90
+ def connection
91
+ @connection ||= Mongo::Connection.new(CONFIG[:hostname], CONFIG[:port])
92
+ @connection.autenticate(CONFIG[:username], CONFIG[:password]) if CONFIG[:username]
93
+ @connection.db(CONFIG[:database])
94
+ end
95
+ module_function :connection
96
+
97
+ end
@@ -0,0 +1,38 @@
1
+ module Mordor
2
+ class Collection
3
+ include Enumerable
4
+
5
+ def initialize(klass, cursor)
6
+ @klass = klass
7
+ @cursor = cursor
8
+ end
9
+
10
+ def each
11
+ @cursor.each do |element|
12
+ if element
13
+ yield @klass.new(element)
14
+ else
15
+ next
16
+ end
17
+ end
18
+ end
19
+
20
+ def first
21
+ result = @cursor.first
22
+ @cursor.rewind!
23
+ result ? @klass.new(result) : nil
24
+ end
25
+
26
+ def size
27
+ @cursor.count
28
+ end
29
+
30
+ def method_missing(method, *args, &block)
31
+ if @cursor.respond_to?(method)
32
+ self.class.new(@klass, @cursor.__send__(method, *args, &block))
33
+ else
34
+ super
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,136 @@
1
+ module Mordor
2
+ module Resource
3
+ attr_accessor :_id
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ def initialize(attributes = {})
10
+ attributes.each do |k,v|
11
+ self.send("#{k}=", v)
12
+ end
13
+ end
14
+
15
+ def replace_params(params = {})
16
+ result = {}
17
+ return result unless params
18
+ params.each do |key, value|
19
+ value = replace_type(value)
20
+ key = key.to_s.gsub(/\W|\./, "_")
21
+ result[key] = value
22
+ end
23
+ result
24
+ end
25
+
26
+ def replace_type(value)
27
+ case value
28
+ when Hash
29
+ value = replace_params(value)
30
+ when Date, DateTime
31
+ value = value.to_time
32
+ when BigDecimal
33
+ value = value.to_f
34
+ when Array
35
+ value = value.map do |val|
36
+ replace_type(val)
37
+ end
38
+ when Integer
39
+ else
40
+ value = value.to_s
41
+ end
42
+ value
43
+ end
44
+
45
+ def save
46
+ unless self._id
47
+ insert_id = self.class.collection.insert(self.to_hash)
48
+ self._id = insert_id
49
+ else
50
+ insert_id = self.update
51
+ end
52
+ insert_id != nil
53
+ end
54
+
55
+ def update
56
+ insert_id = self.class.collection.update({:_id => self._id}, self.to_hash)
57
+ insert_id
58
+ end
59
+
60
+ def collection
61
+ self.class.collection
62
+ end
63
+
64
+ def to_hash
65
+ attributes = self.class.instance_variable_get(:@attributes)
66
+ result = {}
67
+ return result unless attributes
68
+ attributes.each do |attribute_name|
69
+ result[attribute_name] = replace_type(self.send(attribute_name))
70
+ end
71
+ result
72
+ end
73
+
74
+ module ClassMethods
75
+ def collection
76
+ connection.collection(self.collection_name)
77
+ end
78
+
79
+ def collection_name
80
+ klassname = self.to_s.downcase.gsub(/[\/|.|::]/, '_')
81
+ "#{klassname}s"
82
+ end
83
+
84
+ def get(id)
85
+ if id.is_a?(String)
86
+ id = BSON::ObjectId.from_string(id)
87
+ end
88
+ if attributes = collection.find_one(:_id => id)
89
+ new(attributes)
90
+ else
91
+ nil
92
+ end
93
+ end
94
+
95
+ def connection
96
+ @connection ||= Mordor.connection
97
+ end
98
+
99
+ def find_by_id(id)
100
+ get(id)
101
+ end
102
+
103
+ def find_by_day(day)
104
+ case day
105
+ when DateTime
106
+ start = day.to_date.to_time
107
+ end_of_day = (day.to_date + 1).to_time
108
+ when Date
109
+ start = day.to_time
110
+ end_of_day = (day + 1).to_time
111
+ when Time
112
+ start = day.to_datetime.to_date.to_time
113
+ end_of_day = (day.to_date + 1).to_datetime.to_date.to_time
114
+ end
115
+ cursor = collection.find(:at => {'$gte' => start, '$lt' => end_of_day})
116
+ Collection.new(self, cursor)
117
+ end
118
+
119
+ def attribute(name, options = {})
120
+ @attributes ||= []
121
+ @attributes << name unless @attributes.include?(name)
122
+
123
+ method_name = options.key?(:finder_method) ? options[:finder_method] : "find_by_#{name}"
124
+
125
+
126
+ class_eval <<-EOS, __FILE__, __LINE__
127
+ attr_accessor name
128
+
129
+ def self.#{method_name}(value)
130
+ Collection.new(self, collection.find(:#{name} => value))
131
+ end
132
+ EOS
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,3 @@
1
+ module Mordor
2
+ VERSION = "0.0.1"
3
+ end
data/mordor.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "mordor"
3
+
4
+ # Do not set the version and date field manually, this is done by the release script
5
+ s.version = "0.1.0"
6
+ s.date = "2011-11-08"
7
+
8
+ s.summary = "mordor"
9
+ s.description = <<-eos
10
+ Small gem to add MongoDB Resources, resources have attributes that translate into document fields. When an attribute is declared, finders for the attribute are added to the Resource automatically
11
+ eos
12
+
13
+ s.add_development_dependency('rake')
14
+ s.add_development_dependency('ruby-debug')
15
+ s.add_development_dependency('rspec', '~> 2.0')
16
+
17
+ s.add_development_dependency('extlib')
18
+ s.add_development_dependency('mongo')
19
+ s.add_development_dependency('bson_ext')
20
+
21
+ s.add_runtime_dependency('extlib')
22
+ s.add_runtime_dependency('mongo')
23
+ s.add_runtime_dependency('bson_ext')
24
+
25
+ s.authors = ['Jan-Willem Koelewijn', 'Dirkjan Bussink']
26
+ s.email = ['janwillem.koelewijn@nedap.com', 'dirkjan.bussink@nedap.com']
27
+ s.homepage = 'http://www.nedap.com'
28
+
29
+ # The files and test_files directives are set automatically by the release script.
30
+ # Do not change them by hand, but make sure to add the files to the git repository.
31
+ s.files = %w(.gitignore Gemfile README Rakefile lib/mordor.rb lib/mordor/collection.rb lib/mordor/resource.rb lib/mordor/version.rb mordor.gemspec spec/mordor/connection_spec.rb spec/mordor/resource_spec.rb spec/spec.opts spec/spec_helper.rb tasks/github-gem.rake)
32
+ end
33
+
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/spec_helper.rb')
2
+
3
+ describe "connecting to mongo" do
4
+
5
+ before :each do
6
+ clean_sheet
7
+ end
8
+
9
+ it "should have a connection to mongo" do
10
+ @connection.should be_instance_of(Mongo::Connection)
11
+ end
12
+
13
+ it "should select the correct database" do
14
+ @db.name.should == Mordor::CONFIG[:database]
15
+ end
16
+ end
@@ -0,0 +1,140 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/spec_helper.rb')
2
+
3
+ describe "with respect to resources" do
4
+ class TestResource
5
+ include Mordor::Resource
6
+
7
+ attribute :first
8
+ attribute :second
9
+ attribute :third, :finder_method => :find_by_third_attribute
10
+ end
11
+
12
+ it "should create accessor methods for all attributes" do
13
+ ["first", "first=", "second", "second="].each{ |v| TestResource.public_instance_methods.should include(v) }
14
+ end
15
+
16
+ it "should create class level finder methods for all attributes" do
17
+ ["find_by_first", "find_by_second"].each do |finder_method|
18
+ TestResource.methods.should include(finder_method)
19
+ end
20
+ end
21
+
22
+ it "should create finder methods with the supplied finder method name" do
23
+ TestResource.methods.should include "find_by_third_attribute"
24
+ end
25
+
26
+ context "with respect to replacing params" do
27
+ before :each do
28
+ clean_sheet
29
+ end
30
+
31
+ it "should correctly substitute non-alphanumeric characters in keys with underscores" do
32
+ options = {
33
+ "o*p#t>i_o@n)s" => "test"
34
+ }
35
+ result = TestResource.new.replace_params(options)
36
+ result.keys.first.should eql "o_p_t_i_o_n_s"
37
+ end
38
+
39
+ it "should correctly replace Date and DateTimes" do
40
+ options = {
41
+ "option" => Date.today,
42
+ "another" => DateTime.now
43
+ }
44
+ result = TestResource.new.replace_params(options)
45
+ result.each do |k, v|
46
+ v.should be_a Time
47
+ end
48
+ end
49
+
50
+ it "should correctly replace BigDecimals" do
51
+ options = {
52
+ "option" => BigDecimal.new("1.00")
53
+ }
54
+ result = TestResource.new.replace_params(options)
55
+ result.each do |k,v|
56
+ v.should be_a Float
57
+ end
58
+ end
59
+
60
+ it "should correctly respond to to_hash" do
61
+ resource = TestResource.new({:first => "first", :second => "second", :third => "third"})
62
+ hash = resource.to_hash
63
+ hash.size.should == 3
64
+ hash[:first].should == "first"
65
+ hash[:second].should == "second"
66
+ hash[:third].should == "third"
67
+ end
68
+ end
69
+
70
+ context "with respect to saving and retrieving" do
71
+ before :each do
72
+ clean_sheet
73
+ end
74
+
75
+ it "should correctly save resources" do
76
+ resource = TestResource.new({:first => "first", :second => "second"})
77
+ resource.save.should be_true
78
+ resource._id.should_not be_nil
79
+ resource.collection.count.should == 1
80
+ resource.collection.find_one['_id'].should == resource._id
81
+ end
82
+
83
+ it "should correctly update resources" do
84
+ resource = TestResource.new({:first => "first", :second => "second"})
85
+ resource.save.should be_true
86
+ resource._id.should_not be_nil
87
+
88
+ original_id = resource._id
89
+
90
+ resource.collection.count.should == 1
91
+ resource.collection.find_one['_id'].should == resource._id
92
+
93
+ resource.first = "third"
94
+ resource.save.should be_true
95
+ resource._id.should == original_id
96
+ resource.collection.find_one['first'].should == resource.first
97
+ end
98
+
99
+ it "should be able to find resources by their ids" do
100
+ resource = TestResource.new({:first => "first", :second => "second"})
101
+ resource.save.should be_true
102
+ res = TestResource.find_by_id(resource._id)
103
+ res._id.should == resource._id
104
+ res.first.should == resource.first
105
+ res.second.should == resource.second
106
+ end
107
+
108
+ it "should be able to find resources by their ids as strings" do
109
+ resource = TestResource.new({:first => "first", :second => "second"})
110
+ resource.save.should be_true
111
+ res = TestResource.find_by_id(resource._id.to_s)
112
+ res._id.should == resource._id
113
+ res.first.should == resource.first
114
+ res.second.should == resource.second
115
+ end
116
+ end
117
+
118
+ context "with respect to collections" do
119
+ it "should correctly return a collection name" do
120
+ TestResource.collection_name.should == "testresources"
121
+ end
122
+
123
+ it "should correctly create a connection" do
124
+ TestResource.connection.should_not be_nil
125
+ end
126
+ end
127
+
128
+ context "with respect to not finding something" do
129
+ it "should just return an empty collection when a collection query doesn't return results" do
130
+ col = TestResource.find_by_day(DateTime.civil(2011, 11, 8))
131
+ col.size.should == 0
132
+ end
133
+
134
+ it "should return nil when an non existing id is queried" do
135
+ clean_sheet
136
+ resource = TestResource.find_by_id('4eb8f3570e02e10cce000002')
137
+ resource.should be_nil
138
+ end
139
+ end
140
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'mongo'
3
+
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
+ require 'mordor'
6
+
7
+ module Auditing
8
+ CONFIG = {
9
+ :hostname => 'localhost',
10
+ :port => 27017,
11
+ :database => 'test'
12
+ }
13
+ end
14
+
15
+ def clean_sheet
16
+ @connection ||= Mongo::Connection.new(Mordor::CONFIG[:hostname], Mordor::CONFIG[:port])
17
+ @db ||= @connection[Mordor::CONFIG[:database]]
18
+ if Object.const_defined?('TestResource')
19
+ @db[TestResource.collection_name].drop
20
+ end
21
+ end
22
+
@@ -0,0 +1,368 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/tasklib'
4
+ require 'date'
5
+ require 'set'
6
+
7
+ module GithubGem
8
+
9
+ # Detects the gemspc file of this project using heuristics.
10
+ def self.detect_gemspec_file
11
+ FileList['*.gemspec'].first
12
+ end
13
+
14
+ # Detects the main include file of this project using heuristics
15
+ def self.detect_main_include
16
+ if File.exist?(File.expand_path("../lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb", detect_gemspec_file))
17
+ "lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb"
18
+ elsif FileList['lib/*.rb'].length == 1
19
+ FileList['lib/*.rb'].first
20
+ else
21
+ nil
22
+ end
23
+ end
24
+
25
+ class RakeTasks
26
+
27
+ include Rake::DSL if Rake.const_defined?('DSL')
28
+
29
+ attr_reader :gemspec, :modified_files
30
+ attr_accessor :gemspec_file, :task_namespace, :main_include, :root_dir, :spec_pattern, :test_pattern, :remote, :remote_branch, :local_branch
31
+
32
+ # Initializes the settings, yields itself for configuration
33
+ # and defines the rake tasks based on the gemspec file.
34
+ def initialize(task_namespace = :gem)
35
+ @gemspec_file = GithubGem.detect_gemspec_file
36
+ @task_namespace = task_namespace
37
+ @main_include = GithubGem.detect_main_include
38
+ @modified_files = Set.new
39
+ @root_dir = Dir.pwd
40
+ @test_pattern = 'test/**/*_test.rb'
41
+ @spec_pattern = 'spec/**/*_spec.rb'
42
+ @local_branch = 'master'
43
+ @remote = 'origin'
44
+ @remote_branch = 'master'
45
+
46
+ yield(self) if block_given?
47
+
48
+ load_gemspec!
49
+ define_tasks!
50
+ end
51
+
52
+ protected
53
+
54
+ def git
55
+ @git ||= ENV['GIT'] || 'git'
56
+ end
57
+
58
+ # Define Unit test tasks
59
+ def define_test_tasks!
60
+ require 'rake/testtask'
61
+
62
+ namespace(:test) do
63
+ Rake::TestTask.new(:basic) do |t|
64
+ t.pattern = test_pattern
65
+ t.verbose = true
66
+ t.libs << 'test'
67
+ end
68
+ end
69
+
70
+ desc "Run all unit tests for #{gemspec.name}"
71
+ task(:test => ['test:basic'])
72
+ end
73
+
74
+ # Defines RSpec tasks
75
+ def define_rspec_tasks!
76
+ require 'rspec/core/rake_task'
77
+
78
+ namespace(:spec) do
79
+ desc "Verify all RSpec examples for #{gemspec.name}"
80
+ RSpec::Core::RakeTask.new(:basic) do |t|
81
+ t.pattern = spec_pattern
82
+ end
83
+
84
+ desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
85
+ RSpec::Core::RakeTask.new(:specdoc) do |t|
86
+ t.pattern = spec_pattern
87
+ t.rspec_opts = ['--format', 'documentation', '--color']
88
+ end
89
+
90
+ desc "Run RCov on specs for #{gemspec.name}"
91
+ RSpec::Core::RakeTask.new(:rcov) do |t|
92
+ t.pattern = spec_pattern
93
+ t.rcov = true
94
+ t.rcov_opts = ['--exclude', '"spec/*,gems/*"', '--rails']
95
+ end
96
+ end
97
+
98
+ desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
99
+ task(:spec => ['spec:specdoc'])
100
+ end
101
+
102
+ # Defines the rake tasks
103
+ def define_tasks!
104
+
105
+ define_test_tasks! if has_tests?
106
+ define_rspec_tasks! if has_specs?
107
+
108
+ namespace(@task_namespace) do
109
+ desc "Updates the filelist in the gemspec file"
110
+ task(:manifest) { manifest_task }
111
+
112
+ desc "Builds the .gem package"
113
+ task(:build => :manifest) { build_task }
114
+
115
+ desc "Sets the version of the gem in the gemspec"
116
+ task(:set_version => [:check_version, :check_current_branch]) { version_task }
117
+ task(:check_version => :fetch_origin) { check_version_task }
118
+
119
+ task(:fetch_origin) { fetch_origin_task }
120
+ task(:check_current_branch) { check_current_branch_task }
121
+ task(:check_clean_status) { check_clean_status_task }
122
+ task(:check_not_diverged => :fetch_origin) { check_not_diverged_task }
123
+
124
+ #checks = [:check_current_branch, :check_clean_status, :check_not_diverged, :check_version]
125
+ checks = [:check_current_branch, :check_clean_status]
126
+ checks.unshift('spec:basic') if has_specs?
127
+ checks.unshift('test:basic') if has_tests?
128
+ # checks.push << [:check_rubyforge] if gemspec.rubyforge_project
129
+
130
+ desc "Perform all checks that would occur before a release"
131
+ task(:release_checks => checks)
132
+
133
+ release_tasks = [:release_checks, :set_version, :build, :github_release, :gemcutter_release]
134
+ # release_tasks << [:rubyforge_release] if gemspec.rubyforge_project
135
+
136
+ desc "Release a new version of the gem using the VERSION environment variable"
137
+ task(:release => release_tasks) { release_task }
138
+
139
+ namespace(:release) do
140
+ desc "Release the next version of the gem, by incrementing the last version segment by 1"
141
+ task(:next => [:next_version] + release_tasks) { release_task }
142
+
143
+ desc "Release the next version of the gem, using a patch increment (0.0.1)"
144
+ task(:patch => [:next_patch_version] + release_tasks) { release_task }
145
+
146
+ desc "Release the next version of the gem, using a minor increment (0.1.0)"
147
+ task(:minor => [:next_minor_version] + release_tasks) { release_task }
148
+
149
+ desc "Release the next version of the gem, using a major increment (1.0.0)"
150
+ task(:major => [:next_major_version] + release_tasks) { release_task }
151
+ end
152
+
153
+ # task(:check_rubyforge) { check_rubyforge_task }
154
+ # task(:rubyforge_release) { rubyforge_release_task }
155
+ task(:gemcutter_release) { gemcutter_release_task }
156
+ task(:github_release => [:commit_modified_files, :tag_version]) { github_release_task }
157
+ task(:tag_version) { tag_version_task }
158
+ task(:commit_modified_files) { commit_modified_files_task }
159
+
160
+ task(:next_version) { next_version_task }
161
+ task(:next_patch_version) { next_version_task(:patch) }
162
+ task(:next_minor_version) { next_version_task(:minor) }
163
+ task(:next_major_version) { next_version_task(:major) }
164
+
165
+ desc "Updates the gem release tasks with the latest version on Github"
166
+ task(:update_tasks) { update_tasks_task }
167
+ end
168
+ end
169
+
170
+ # Updates the files list and test_files list in the gemspec file using the list of files
171
+ # in the repository and the spec/test file pattern.
172
+ def manifest_task
173
+ # Load all the gem's files using "git ls-files"
174
+ repository_files = `#{git} ls-files`.split("\n")
175
+ test_files = Dir[test_pattern] + Dir[spec_pattern]
176
+
177
+ update_gemspec(:files, repository_files)
178
+ update_gemspec(:test_files, repository_files & test_files)
179
+ end
180
+
181
+ # Builds the gem
182
+ def build_task
183
+ sh "gem build -q #{gemspec_file}"
184
+ Dir.mkdir('pkg') unless File.exist?('pkg')
185
+ sh "mv #{gemspec.name}-#{gemspec.version}.gem pkg/#{gemspec.name}-#{gemspec.version}.gem"
186
+ end
187
+
188
+ def newest_version
189
+ `#{git} tag`.split("\n").map { |tag| tag.split('-').last }.compact.map { |v| Gem::Version.new(v) }.max || Gem::Version.new('0.0.0')
190
+ end
191
+
192
+ def next_version(increment = nil)
193
+ next_version = newest_version.segments
194
+ increment_index = case increment
195
+ when :micro then 3
196
+ when :patch then 2
197
+ when :minor then 1
198
+ when :major then 0
199
+ else next_version.length - 1
200
+ end
201
+
202
+ next_version[increment_index] ||= 0
203
+ next_version[increment_index] = next_version[increment_index].succ
204
+ ((increment_index + 1)...next_version.length).each { |i| next_version[i] = 0 }
205
+
206
+ Gem::Version.new(next_version.join('.'))
207
+ end
208
+
209
+ def next_version_task(increment = nil)
210
+ ENV['VERSION'] = next_version(increment).version
211
+ puts "Releasing version #{ENV['VERSION']}..."
212
+ end
213
+
214
+ # Updates the version number in the gemspec file, the VERSION constant in the main
215
+ # include file and the contents of the VERSION file.
216
+ def version_task
217
+ update_gemspec(:version, ENV['VERSION']) if ENV['VERSION']
218
+ update_gemspec(:date, Date.today)
219
+
220
+ update_version_file(gemspec.version)
221
+ update_version_constant(gemspec.version)
222
+ end
223
+
224
+ def check_version_task
225
+ raise "#{ENV['VERSION']} is not a valid version number!" if ENV['VERSION'] && !Gem::Version.correct?(ENV['VERSION'])
226
+ proposed_version = Gem::Version.new((ENV['VERSION'] || gemspec.version).dup)
227
+ raise "This version (#{proposed_version}) is not higher than the highest tagged version (#{newest_version})" if newest_version >= proposed_version
228
+ end
229
+
230
+ # Checks whether the current branch is not diverged from the remote branch
231
+ def check_not_diverged_task
232
+ raise "The current branch is diverged from the remote branch!" if `#{git} rev-list HEAD..#{remote}/#{remote_branch}`.split("\n").any?
233
+ end
234
+
235
+ # Checks whether the repository status ic clean
236
+ def check_clean_status_task
237
+ raise "The current working copy contains modifications" if `#{git} ls-files -m`.split("\n").any?
238
+ end
239
+
240
+ # Checks whether the current branch is correct
241
+ def check_current_branch_task
242
+ raise "Currently not on #{local_branch} branch!" unless `#{git} branch`.split("\n").detect { |b| /^\* / =~ b } == "* #{local_branch}"
243
+ end
244
+
245
+ # Fetches the latest updates from Github
246
+ def fetch_origin_task
247
+ sh git, 'fetch', remote
248
+ end
249
+
250
+ # Commits every file that has been changed by the release task.
251
+ def commit_modified_files_task
252
+ really_modified = `#{git} ls-files -m #{modified_files.entries.join(' ')}`.split("\n")
253
+ if really_modified.any?
254
+ really_modified.each { |file| sh git, 'add', file }
255
+ sh git, 'commit', '-m', "Released #{gemspec.name} gem version #{gemspec.version}."
256
+ end
257
+ end
258
+
259
+ # Adds a tag for the released version
260
+ def tag_version_task
261
+ sh git, 'tag', '-a', "#{gemspec.name}-#{gemspec.version}", '-m', "Released #{gemspec.name} gem version #{gemspec.version}."
262
+ end
263
+
264
+ # Pushes the changes and tag to github
265
+ def github_release_task
266
+ sh git, 'push', '--tags', remote, remote_branch
267
+ end
268
+
269
+ def gemcutter_release_task
270
+ sh "gem", 'push', "pkg/#{gemspec.name}-#{gemspec.version}.gem"
271
+ end
272
+
273
+ # Gem release task.
274
+ # All work is done by the task's dependencies, so just display a release completed message.
275
+ def release_task
276
+ puts
277
+ puts "Release successful."
278
+ end
279
+
280
+ private
281
+
282
+ # Checks whether this project has any RSpec files
283
+ def has_specs?
284
+ FileList[spec_pattern].any?
285
+ end
286
+
287
+ # Checks whether this project has any unit test files
288
+ def has_tests?
289
+ FileList[test_pattern].any?
290
+ end
291
+
292
+ # Loads the gemspec file
293
+ def load_gemspec!
294
+ @gemspec = eval(File.read(@gemspec_file))
295
+ end
296
+
297
+ # Updates the VERSION file with the new version
298
+ def update_version_file(version)
299
+ if File.exists?('VERSION')
300
+ File.open('VERSION', 'w') { |f| f << version.to_s }
301
+ modified_files << 'VERSION'
302
+ end
303
+ end
304
+
305
+ # Updates the VERSION constant in the main include file if it exists
306
+ def update_version_constant(version)
307
+ if main_include && File.exist?(main_include)
308
+ file_contents = File.read(main_include)
309
+ if file_contents.sub!(/^(\s+VERSION\s*=\s*)[^\s].*$/) { $1 + version.to_s.inspect }
310
+ File.open(main_include, 'w') { |f| f << file_contents }
311
+ modified_files << main_include
312
+ end
313
+ end
314
+ end
315
+
316
+ # Updates an attribute of the gemspec file.
317
+ # This function will open the file, and search/replace the attribute using a regular expression.
318
+ def update_gemspec(attribute, new_value, literal = false)
319
+
320
+ unless literal
321
+ new_value = case new_value
322
+ when Array then "%w(#{new_value.join(' ')})"
323
+ when Hash, String then new_value.inspect
324
+ when Date then new_value.strftime('%Y-%m-%d').inspect
325
+ else raise "Cannot write value #{new_value.inspect} to gemspec file!"
326
+ end
327
+ end
328
+
329
+ spec = File.read(gemspec_file)
330
+ regexp = Regexp.new('^(\s+\w+\.' + Regexp.quote(attribute.to_s) + '\s*=\s*)[^\s].*$')
331
+ if spec.sub!(regexp) { $1 + new_value }
332
+ File.open(gemspec_file, 'w') { |f| f << spec }
333
+ modified_files << gemspec_file
334
+
335
+ # Reload the gemspec so the changes are incorporated
336
+ load_gemspec!
337
+
338
+ # Also mark the Gemfile.lock file as changed because of the new version.
339
+ modified_files << 'Gemfile.lock' if File.exist?(File.join(root_dir, 'Gemfile.lock'))
340
+ end
341
+ end
342
+
343
+ # Updates the tasks file using the latest file found on Github
344
+ def update_tasks_task
345
+ require 'net/https'
346
+ require 'uri'
347
+
348
+ uri = URI.parse('https://raw.github.com/wvanbergen/github-gem/master/tasks/github-gem.rake')
349
+ http = Net::HTTP.new(uri.host, uri.port)
350
+ http.use_ssl = true
351
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
352
+ response = http.request(Net::HTTP::Get.new(uri.path))
353
+
354
+ if Net::HTTPSuccess === response
355
+ open(__FILE__, "w") { |file| file.write(response.body) }
356
+ relative_file = File.expand_path(__FILE__).sub(%r[^#{@root_dir}/], '')
357
+ if `#{git} ls-files -m #{relative_file}`.split("\n").any?
358
+ sh git, 'add', relative_file
359
+ sh git, 'commit', '-m', "Updated to latest gem release management tasks."
360
+ else
361
+ puts "Release managament tasks already are at the latest version."
362
+ end
363
+ else
364
+ raise "Download failed with HTTP status #{response.code}!"
365
+ end
366
+ end
367
+ end
368
+ end
metadata ADDED
@@ -0,0 +1,209 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mordor
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Jan-Willem Koelewijn
14
+ - Dirkjan Bussink
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-11-08 00:00:00 +01:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rake
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: ruby-debug
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :development
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 2
61
+ - 0
62
+ version: "2.0"
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: extlib
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ type: :development
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: mongo
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ name: bson_ext
95
+ prerelease: false
96
+ requirement: &id006 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ type: :development
106
+ version_requirements: *id006
107
+ - !ruby/object:Gem::Dependency
108
+ name: extlib
109
+ prerelease: false
110
+ requirement: &id007 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ type: :runtime
120
+ version_requirements: *id007
121
+ - !ruby/object:Gem::Dependency
122
+ name: mongo
123
+ prerelease: false
124
+ requirement: &id008 !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ type: :runtime
134
+ version_requirements: *id008
135
+ - !ruby/object:Gem::Dependency
136
+ name: bson_ext
137
+ prerelease: false
138
+ requirement: &id009 !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 3
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ type: :runtime
148
+ version_requirements: *id009
149
+ description: " Small gem to add MongoDB Resources, resources have attributes that translate into document fields. When an attribute is declared, finders for the attribute are added to the Resource automatically\n"
150
+ email:
151
+ - janwillem.koelewijn@nedap.com
152
+ - dirkjan.bussink@nedap.com
153
+ executables: []
154
+
155
+ extensions: []
156
+
157
+ extra_rdoc_files: []
158
+
159
+ files:
160
+ - .gitignore
161
+ - Gemfile
162
+ - README
163
+ - Rakefile
164
+ - lib/mordor.rb
165
+ - lib/mordor/collection.rb
166
+ - lib/mordor/resource.rb
167
+ - lib/mordor/version.rb
168
+ - mordor.gemspec
169
+ - spec/mordor/connection_spec.rb
170
+ - spec/mordor/resource_spec.rb
171
+ - spec/spec.opts
172
+ - spec/spec_helper.rb
173
+ - tasks/github-gem.rake
174
+ has_rdoc: true
175
+ homepage: http://www.nedap.com
176
+ licenses: []
177
+
178
+ post_install_message:
179
+ rdoc_options: []
180
+
181
+ require_paths:
182
+ - lib
183
+ required_ruby_version: !ruby/object:Gem::Requirement
184
+ none: false
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ hash: 3
189
+ segments:
190
+ - 0
191
+ version: "0"
192
+ required_rubygems_version: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ hash: 3
198
+ segments:
199
+ - 0
200
+ version: "0"
201
+ requirements: []
202
+
203
+ rubyforge_project:
204
+ rubygems_version: 1.3.7
205
+ signing_key:
206
+ specification_version: 3
207
+ summary: mordor
208
+ test_files: []
209
+