Permalink
Browse files

Pushing to GitHub, squash all previous messy commits.

  • Loading branch information...
0 parents commit da6f07ff537b96da0bbc99423a64770bd9de2003 @pauldowman committed Nov 9, 2010
@@ -0,0 +1,5 @@
+README.rdoc
+lib/**/*.rb
+bin/*
+features/**/*.feature
+LICENSE
@@ -0,0 +1,7 @@
+*.gem
+.DS_Store
+.bundle
+.gitmodel-data
+coverage
+pkg
+rdoc
1 .rspec
@@ -0,0 +1 @@
+--colour
1 .rvmrc
@@ -0,0 +1 @@
+rvm use ruby-1.9.2@gitmodel
@@ -0,0 +1,5 @@
+# Edit this Gemfile to bundle your application's dependencies.
+source :rubygems
+
+gemspec
+
@@ -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)
20 LICENSE
@@ -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.
109 README.md
@@ -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.
+
+
@@ -0,0 +1,3 @@
+require 'bundler'
+Bundler::GemHelper.install_tasks
+
@@ -0,0 +1 @@
+Autotest.add_discovery { "rspec2" }
@@ -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 = 'paul@pauldowman.com'
+ 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
+
@@ -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
@@ -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.

6 comments on commit da6f07f

gf3 replied Nov 10, 2010

Why did you decide to squash?

Owner

pauldowman replied Nov 10, 2010

Why not? There were lots of small partially-working commits that just clutter up the history.

Squashing is bad.

Owner

pauldowman replied Nov 23, 2010

But trolls are worse.

That they are.

Owner

pauldowman replied Nov 23, 2010

                               _____________________ 
                              |                     |
                   /|  /| |   |      SQUASHING      |
                   ||__|| |   |        MAKES        |
                  /   O O\__  |     BABY JESUS      |
                 /          \ |        CRY          |
                /      \     \|_____________________|
               /   _    \     \      ||              
              /    |\____\     \     ||              
             /     | | | |\____/     ||              
            /       \|_|_|/   |     _||              
           /  /  \            |____| ||              
          /   |   |           |      --|             
          |   |   |           |____  --|             
   * _    |  |_|_|_|          |     \-/              
*-- _--\ _ \                  |      ||              
  /  _     \\        |        /      `               
*  /   \_ /- |       |       |                       
  *      ___ c_c_c_C/ \C_c_c_c____________           

Seriously though, I think an initial working state plus atomic commits with no broken tests and well-written messages is what you want publicly. Privately I work on topic branches and want to commit frequently without requiring working tests or interrupting my workflow by worrying about the quality of my commit messages.

Please sign in to comment.