forked from pauldowman/gitmodel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pushing to GitHub, squash all previous messy commits.
- Loading branch information
0 parents
commit da6f07f
Showing
20 changed files
with
1,230 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
README.rdoc | ||
lib/**/*.rb | ||
bin/* | ||
features/**/*.feature | ||
LICENSE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
*.gem | ||
.DS_Store | ||
.bundle | ||
.gitmodel-data | ||
coverage | ||
pkg | ||
rdoc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
--colour |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
rvm use ruby-1.9.2@gitmodel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Edit this Gemfile to bundle your application's dependencies. | ||
source :rubygems | ||
|
||
gemspec | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
PATH | ||
remote: . | ||
specs: | ||
gitmodel (0.0.0) | ||
activemodel (>= 3.0.1) | ||
activesupport (>= 3.0.1) | ||
grit (>= 2.3.0) | ||
lockfile (>= 1.4.3) | ||
|
||
GEM | ||
remote: http://rubygems.org/ | ||
specs: | ||
ZenTest (4.4.0) | ||
activemodel (3.0.1) | ||
activesupport (= 3.0.1) | ||
builder (~> 2.1.2) | ||
i18n (~> 0.4.1) | ||
activesupport (3.0.1) | ||
autotest (4.4.1) | ||
autotest-fsevent (0.2.3) | ||
sys-uname | ||
builder (2.1.2) | ||
diff-lcs (1.1.2) | ||
grit (2.3.0) | ||
diff-lcs (~> 1.1) | ||
mime-types (~> 1.15) | ||
i18n (0.4.1) | ||
lockfile (1.4.3) | ||
mime-types (1.16) | ||
rspec (2.0.1) | ||
rspec-core (~> 2.0.1) | ||
rspec-expectations (~> 2.0.1) | ||
rspec-mocks (~> 2.0.1) | ||
rspec-core (2.0.1) | ||
rspec-expectations (2.0.1) | ||
diff-lcs (>= 1.1.2) | ||
rspec-mocks (2.0.1) | ||
rspec-core (~> 2.0.1) | ||
rspec-expectations (~> 2.0.1) | ||
sys-uname (0.8.4) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
ZenTest (>= 4.4.0) | ||
activemodel (>= 3.0.1) | ||
activesupport (>= 3.0.1) | ||
autotest (>= 4.4.1) | ||
autotest-fsevent (>= 0.2.3) | ||
gitmodel! | ||
grit (>= 2.3.0) | ||
lockfile (>= 1.4.3) | ||
rspec (>= 2.0.1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Copyright (c) 2009 Paul Dowman | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
GitModel: distributed, versioned NoSQL for Ruby | ||
--------------------------------------------------- | ||
|
||
GitModel is an | ||
[ActiveModel](http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/)-compliant | ||
persistence framework for Ruby that uses [Git](http://git-scm.com/) for | ||
versioning and remote syncing. | ||
|
||
GitModel persists Ruby objects using Git as a data storage engine. It's an | ||
ActiveModel implementation so it works stand-alone or in Rails 3 as a drop-in | ||
replacement for ActiveRecord or DataMapper. | ||
|
||
Because the database is a Git repository it can be synced across multiple | ||
machines, manipulated with standard Git client tools, can be branched and | ||
merged, and of course keeps the history of all changes. | ||
|
||
|
||
Status | ||
------ | ||
|
||
_It is nowhere near production ready but I'm working on it. Please feel free to | ||
contribute tests and/or code to help!_ | ||
|
||
|
||
Why it's awesome | ||
---------------- | ||
|
||
* Schema-less NoSQL data store | ||
* Each record is a normal Ruby object, attributes are any Ruby type or large | ||
chunks of binary data | ||
* Never lose data, history is kept forever and can be restored simply using | ||
standard Git tools | ||
* Branch and merge your production data | ||
* GitModel can actually work with different branches | ||
* Branch or tag snapshots of your data | ||
* Experiment on production data using branches, for example to test a | ||
migration | ||
* Distributed (synced using standard Git push/pull) | ||
* Transactions | ||
* Metadata for all database changes (Git commit messages, date & time, etc.) | ||
* The database is simply files and directores stored in a Git repository. | ||
GitModel uses the Git repo directly (rather than Git's checked-out "working | ||
copy") but you can do a "git checkout" to view and manipulate the database | ||
contents, and then "git commit" | ||
* Test-driven development and excellent test coverage | ||
* Clean and easy-to-use API | ||
|
||
|
||
Database file structure | ||
----------------------- | ||
|
||
Each type of object is stored in a top-level directory (this is analogous to | ||
ActiveRecord tables), and each object is stored in a subdirectory which is | ||
named using the object's id (i.e. the primary key). Attributes that are Ruby | ||
types (strings, numbers, hashes, arrays, whatever) are stored in a file named | ||
attributes.json and large binary attributes ("blobs") are stored in their own | ||
files. | ||
|
||
For example, a database for a blogging app with three Post objects and five | ||
Comment objects might have a directory structure that looks like this: | ||
|
||
* db-root | ||
* comments | ||
* 2010-01-03-328 | ||
* _attributes.json_ | ||
* 2010-05-29-742 | ||
* _attributes.json_ | ||
* 2010-10-09-934 | ||
* _attributes.json_ | ||
* 2010-10-12-132 | ||
* _attributes.json_ | ||
* 2010-10-12-665 | ||
* _attributes.json_ | ||
* posts | ||
* hotdog-eating-contest | ||
* _attributes.json_ | ||
* _hotdogs.jpg_ | ||
* _the-aftermath.jpg_ | ||
* lessons-learned | ||
* _attributes.json_ | ||
* _summary.xls_ | ||
* running-with-scissors | ||
* _attributes.json_ | ||
* _oops.jpg_ | ||
* _speedy.jpg_ | ||
|
||
In the above example _attributes.json_ holds the attributes which are | ||
represented by Ruby types, and binary data "blobs" are stored in files. | ||
|
||
To Do | ||
----- | ||
|
||
* Querying | ||
* Use AREL? | ||
* Transactions | ||
* allow blocks to execute within a transaction so multiple changes occur in | ||
one Git commit | ||
* Finish some pending specs | ||
* Associations | ||
* API documentation | ||
* Rails integration | ||
* rake tasks | ||
* generators | ||
* Performance | ||
* Haven't optimized for performance yet. | ||
* Some places where we do blatently stupid things have been marked with | ||
PERFORMANCE comments. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
require 'bundler' | ||
Bundler::GemHelper.install_tasks | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Autotest.add_discovery { "rspec2" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
Gem::Specification.new do |s| | ||
s.name = 'gitmodel' | ||
s.version = '0.0.0' | ||
s.platform = Gem::Platform::RUBY | ||
|
||
s.authors = ["Paul Dowman"] | ||
s.email = '[email protected]' | ||
s.homepage = 'http://github.com/pauldowman/gitmodel' | ||
|
||
s.summary = %q{An ActiveModel-compliant persistence framework for Ruby that uses Git for versioning and remote syncing.} | ||
s.description = <<-DESC.strip.gsub(/\n\s+/, " ") | ||
GitModel persists Ruby objects using Git as a data storage engine. It's an | ||
ActiveModel implementation so it works stand-alone or in Rails 3 as a drop-in | ||
replacement for ActiveRecord or DataMapper. Because the database is a Git | ||
repository it can be synced across multiple machines, manipulated with standard | ||
Git client tools, can be branched and merged, and of course keeps the history | ||
of all changes. | ||
DESC | ||
|
||
s.add_dependency 'activemodel', '>= 3.0.1' | ||
s.add_dependency 'activesupport', '>= 3.0.1' | ||
s.add_dependency 'grit', '>= 2.3.0' | ||
s.add_dependency 'lockfile', '>= 1.4.3' | ||
|
||
s.add_development_dependency 'ZenTest', '>= 4.4.0' | ||
s.add_development_dependency 'autotest', '>= 4.4.1' | ||
s.add_development_dependency 'autotest-fsevent', '>= 0.2.3' if RUBY_PLATFORM.downcase.include?("darwin") # OS X only | ||
s.add_development_dependency 'rspec', '>= 2.0.1' | ||
|
||
s.files = `git ls-files`.split("\n") | ||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") | ||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } | ||
s.require_paths = ["lib"] | ||
|
||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
require 'rubygems' | ||
require 'bundler/setup' | ||
|
||
require 'active_model' | ||
require 'active_support/all' # TODO we don't really want all here, clean this up | ||
require 'grit' | ||
require 'json' | ||
require 'lockfile' | ||
require 'pp' | ||
|
||
$:.unshift(File.dirname(__FILE__)) | ||
require 'gitmodel/errors' | ||
require 'gitmodel/persistable' | ||
require 'gitmodel/transaction' | ||
|
||
module GitModel | ||
|
||
# db_root must be an existing git repo. (It can be created with create_db!) | ||
# Bare repositories aren't supported yet, it must be a normal git repo with a | ||
# working directory and a '.git' subdirectory. | ||
mattr_accessor :db_root | ||
self.db_root = './gitmodel-data' | ||
|
||
mattr_accessor :default_branch | ||
self.default_branch = 'master' | ||
|
||
mattr_accessor :logger | ||
self.logger = ::Logger.new(STDERR) | ||
self.logger.level = ::Logger::WARN | ||
|
||
mattr_accessor :git_user_name | ||
mattr_accessor :git_user_email | ||
|
||
def self.repo | ||
@@repo = Grit::Repo.new(GitModel.db_root) | ||
end | ||
|
||
# Create the database defined in db_root. Raises an exception if it exists. | ||
def self.create_db! | ||
raise "Database #{db_root} already exists!" if File.exist? db_root | ||
if db_root =~ /.+\.git/ | ||
#logger.info "Creating database (bare): #{db_root}" | ||
#Grit::Repo.init_bare db_root | ||
logger.error "Bare repositories aren't supported yet" | ||
else | ||
logger.info "Creating database: #{db_root}" | ||
Grit::Repo.init db_root | ||
end | ||
end | ||
|
||
# Delete and re-create the database defined in db_root. Dangerous! | ||
def self.recreate_db! | ||
logger.info "Deleting database #{db_root}!!" | ||
FileUtils.rm_rf db_root | ||
create_db! | ||
end | ||
|
||
def self.last_commit(branch = nil) | ||
branch ||= default_branch | ||
# PERFORMANCE Cache this somewhere and update it on commit? | ||
# (Need separate instance per branch) | ||
|
||
return nil unless repo.commits(branch).any? | ||
|
||
# We should be able to use just repo.commits(branch).first here but | ||
# this is a workaround for this bug: | ||
# http://github.com/mojombo/grit/issues/issue/38 | ||
GitModel.repo.commits("#{branch}^..#{branch}").first || GitModel.repo.commits(branch).first | ||
end | ||
|
||
def self.current_tree(branch = nil) | ||
c = last_commit(branch) | ||
c ? c.tree : nil | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module GitModel | ||
|
||
# Generic GitModel exception class. | ||
class GitModelError < StandardError | ||
end | ||
|
||
# Raised when GitModel cannot find record by given id or set of ids. | ||
class RecordNotFound < GitModelError | ||
end | ||
|
||
# Raised by GitModel::Persistable.save! and GitModel::Persistable.create! methods when record cannot be | ||
# saved because record is invalid. | ||
class RecordNotSaved < GitModelError | ||
end | ||
|
||
class RecordExists < GitModelError | ||
end | ||
|
||
class RecordDoesntExist < GitModelError | ||
end | ||
|
||
class NullId < GitModelError | ||
end | ||
|
||
end |
Oops, something went wrong.