chillfile 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. data/.rspec +1 -0
  2. data/Gemfile +18 -0
  3. data/Gemfile.lock +88 -0
  4. data/LICENSE +22 -0
  5. data/README.md +11 -0
  6. data/Rakefile +21 -0
  7. data/autotest/discover.rb +1 -0
  8. data/bin/chillfile +8 -0
  9. data/chillfile.gemspec +113 -0
  10. data/lib/chillfile/cli.rb +63 -0
  11. data/lib/chillfile/config.rb +40 -0
  12. data/lib/chillfile/database_server.rb +11 -0
  13. data/lib/chillfile/model/base.rb +3 -0
  14. data/lib/chillfile/model/sync_file.rb +28 -0
  15. data/lib/chillfile/model.rb +20 -0
  16. data/lib/chillfile/sync.rb +118 -0
  17. data/lib/chillfile.rb +56 -0
  18. data/spec/filesystem_after/bar.1.moved.untouched +1 -0
  19. data/spec/filesystem_after/bar.2.moved.copy +1 -0
  20. data/spec/filesystem_after/bar.3.moved.copy +0 -0
  21. data/spec/filesystem_after/foo.fx.copy +1 -0
  22. data/spec/filesystem_after/foo.untouched +1 -0
  23. data/spec/filesystem_after/moo.new +1 -0
  24. data/spec/filesystem_after/subdir_b/bar.4.moved.copy +1 -0
  25. data/spec/filesystem_before/bar.0.moved.deleted +1 -0
  26. data/spec/filesystem_before/bar.1.moved.untouched +0 -0
  27. data/spec/filesystem_before/foo.untouched +1 -0
  28. data/spec/filesystem_before/subdir/mii.deleted +3 -0
  29. data/spec/filesystem_before/wuu.deleted +3 -0
  30. data/spec/fixtures/filesystem_after.json +1 -0
  31. data/spec/fixtures/filesystem_before.json +1 -0
  32. data/spec/lib/chillfile/model/sync_file_spec.rb +18 -0
  33. data/spec/lib/chillfile_spec.rb +37 -0
  34. data/spec/spec_helper.rb +15 -0
  35. data/spec/support/db_helper.rb +10 -0
  36. data/spec/support/fixtures_helper.rb +10 -0
  37. data/spec/support/fs_helper.rb +10 -0
  38. data/spec/support/list_helper.rb +5 -0
  39. data/version.yml +5 -0
  40. metadata +235 -0
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'http://rubygems.org'
2
+ source 'http://rubygems.org'
3
+
4
+ group :default do
5
+ gem "couchrest"
6
+ gem 'couchrest_model', :git => 'git://github.com/couchrest/couchrest_model.git'
7
+ gem "treedisha", "~> 0.0.2", :git => 'git://github.com/dpree/treedisha.git'
8
+ gem "json"
9
+ gem "thor"
10
+ end
11
+
12
+ group :test do
13
+ gem "rspec"
14
+ end
15
+
16
+ group :gem do
17
+ gem "jeweler"
18
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,88 @@
1
+ GIT
2
+ remote: git://github.com/couchrest/couchrest_model.git
3
+ revision: 958616025db74bdea252e3108112c0afa439b439
4
+ specs:
5
+ couchrest_model (1.0.0.beta8)
6
+ activemodel (~> 3.0.0.rc)
7
+ couchrest (~> 1.0.1)
8
+ mime-types (~> 1.15)
9
+ railties (~> 3.0.0.rc)
10
+ tzinfo (~> 0.3.22)
11
+
12
+ GIT
13
+ remote: git://github.com/dpree/treedisha.git
14
+ revision: 926c6bb92b24972da1cad1b8cf27c32c13096674
15
+ specs:
16
+ treedisha (0.0.1)
17
+
18
+ GEM
19
+ remote: http://rubygems.org/
20
+ remote: http://rubygems.org/
21
+ specs:
22
+ abstract (1.0.0)
23
+ actionpack (3.0.3)
24
+ activemodel (= 3.0.3)
25
+ activesupport (= 3.0.3)
26
+ builder (~> 2.1.2)
27
+ erubis (~> 2.6.6)
28
+ i18n (~> 0.4)
29
+ rack (~> 1.2.1)
30
+ rack-mount (~> 0.6.13)
31
+ rack-test (~> 0.5.6)
32
+ tzinfo (~> 0.3.23)
33
+ activemodel (3.0.3)
34
+ activesupport (= 3.0.3)
35
+ builder (~> 2.1.2)
36
+ i18n (~> 0.4)
37
+ activesupport (3.0.3)
38
+ builder (2.1.2)
39
+ couchrest (1.0.1)
40
+ json (>= 1.4.6)
41
+ mime-types (>= 1.15)
42
+ rest-client (>= 1.5.1)
43
+ diff-lcs (1.1.2)
44
+ erubis (2.6.6)
45
+ abstract (>= 1.0.0)
46
+ git (1.2.5)
47
+ i18n (0.5.0)
48
+ jeweler (1.5.1)
49
+ bundler (~> 1.0.0)
50
+ git (>= 1.2.5)
51
+ rake
52
+ json (1.4.6)
53
+ mime-types (1.16)
54
+ rack (1.2.1)
55
+ rack-mount (0.6.13)
56
+ rack (>= 1.0.0)
57
+ rack-test (0.5.6)
58
+ rack (>= 1.0)
59
+ railties (3.0.3)
60
+ actionpack (= 3.0.3)
61
+ activesupport (= 3.0.3)
62
+ rake (>= 0.8.7)
63
+ thor (~> 0.14.4)
64
+ rake (0.8.7)
65
+ rest-client (1.6.1)
66
+ mime-types (>= 1.16)
67
+ rspec (2.3.0)
68
+ rspec-core (~> 2.3.0)
69
+ rspec-expectations (~> 2.3.0)
70
+ rspec-mocks (~> 2.3.0)
71
+ rspec-core (2.3.0)
72
+ rspec-expectations (2.3.0)
73
+ diff-lcs (~> 1.1.2)
74
+ rspec-mocks (2.3.0)
75
+ thor (0.14.6)
76
+ tzinfo (0.3.23)
77
+
78
+ PLATFORMS
79
+ ruby
80
+
81
+ DEPENDENCIES
82
+ couchrest
83
+ couchrest_model!
84
+ jeweler
85
+ json
86
+ rspec
87
+ thor
88
+ treedisha!
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 dpree
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # Chillfile
2
+
3
+ sync your files with a couchdb
4
+
5
+ ## Description
6
+
7
+ Upload the latest changes you made on the filesystem into a couchdb
8
+
9
+ ## License
10
+
11
+ Chillfile is covered by the MIT License. See LICENSE for more information.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "chillfile"
5
+ gemspec.summary = "Tiny tool to sync filesystem with couchdb"
6
+ gemspec.description = "Let your files chill on the couch"
7
+ gemspec.email = "whiterabbit.init@gmail.com"
8
+ gemspec.homepage = "http://github.com/dpree/chillfile"
9
+ gemspec.authors = ["dpree"]
10
+ gemspec.add_dependency("thor", "~> 0.14.6")
11
+ gemspec.add_dependency("couchrest", "~> 1.0.1")
12
+ #gemspec.add_dependency("couchrest_model", "~> 1.0.0.beta8") # currently you have to clone, build and install it yourself from HEAD
13
+ gemspec.add_dependency("treedisha", "~> 0.0.2")
14
+ gemspec.add_development_dependency('rspec', '~> 2.0.0')
15
+ gemspec.date = Time.now.strftime("%Y-%m-%d")
16
+ gemspec.executables = ["chillfile"]
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
21
+ end
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { "rspec2" }
data/bin/chillfile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "chillfile"
5
+
6
+ #require File.join(File.dirname(__FILE__), "../lib/chillfile")
7
+
8
+ Chillfile::CLI.start
data/chillfile.gemspec ADDED
@@ -0,0 +1,113 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{chillfile}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["dpree"]
12
+ s.date = %q{2010-12-08}
13
+ s.default_executable = %q{chillfile}
14
+ s.description = %q{Let your files chill on the couch}
15
+ s.email = %q{whiterabbit.init@gmail.com}
16
+ s.executables = ["chillfile"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".rspec",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE",
26
+ "README.md",
27
+ "Rakefile",
28
+ "autotest/discover.rb",
29
+ "bin/chillfile",
30
+ "chillfile.gemspec",
31
+ "lib/chillfile.rb",
32
+ "lib/chillfile/cli.rb",
33
+ "lib/chillfile/config.rb",
34
+ "lib/chillfile/database_server.rb",
35
+ "lib/chillfile/model.rb",
36
+ "lib/chillfile/model/base.rb",
37
+ "lib/chillfile/model/sync_file.rb",
38
+ "lib/chillfile/sync.rb",
39
+ "spec/filesystem_after/bar.1.moved.untouched",
40
+ "spec/filesystem_after/bar.2.moved.copy",
41
+ "spec/filesystem_after/bar.3.moved.copy",
42
+ "spec/filesystem_after/foo.fx.copy",
43
+ "spec/filesystem_after/foo.untouched",
44
+ "spec/filesystem_after/moo.new",
45
+ "spec/filesystem_after/subdir_b/bar.4.moved.copy",
46
+ "spec/filesystem_before/bar.0.moved.deleted",
47
+ "spec/filesystem_before/bar.1.moved.untouched",
48
+ "spec/filesystem_before/foo.untouched",
49
+ "spec/filesystem_before/subdir/mii.deleted",
50
+ "spec/filesystem_before/wuu.deleted",
51
+ "spec/fixtures/filesystem_after.json",
52
+ "spec/fixtures/filesystem_before.json",
53
+ "spec/lib/chillfile/model/sync_file_spec.rb",
54
+ "spec/lib/chillfile_spec.rb",
55
+ "spec/spec_helper.rb",
56
+ "spec/support/db_helper.rb",
57
+ "spec/support/fixtures_helper.rb",
58
+ "spec/support/fs_helper.rb",
59
+ "spec/support/list_helper.rb",
60
+ "version.yml"
61
+ ]
62
+ s.homepage = %q{http://github.com/dpree/chillfile}
63
+ s.require_paths = ["lib"]
64
+ s.rubygems_version = %q{1.3.7}
65
+ s.summary = %q{Tiny tool to sync filesystem with couchdb}
66
+ s.test_files = [
67
+ "spec/lib/chillfile/model/sync_file_spec.rb",
68
+ "spec/lib/chillfile_spec.rb",
69
+ "spec/spec_helper.rb",
70
+ "spec/support/db_helper.rb",
71
+ "spec/support/fixtures_helper.rb",
72
+ "spec/support/fs_helper.rb",
73
+ "spec/support/list_helper.rb"
74
+ ]
75
+
76
+ if s.respond_to? :specification_version then
77
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
78
+ s.specification_version = 3
79
+
80
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
81
+ s.add_runtime_dependency(%q<couchrest>, [">= 0"])
82
+ s.add_runtime_dependency(%q<couchrest_model>, [">= 0"])
83
+ s.add_runtime_dependency(%q<treedisha>, ["~> 0.0.2"])
84
+ s.add_runtime_dependency(%q<json>, [">= 0"])
85
+ s.add_runtime_dependency(%q<thor>, [">= 0"])
86
+ s.add_runtime_dependency(%q<thor>, ["~> 0.14.6"])
87
+ s.add_runtime_dependency(%q<couchrest>, ["~> 1.0.1"])
88
+ s.add_runtime_dependency(%q<treedisha>, ["~> 0.0.2"])
89
+ s.add_development_dependency(%q<rspec>, ["~> 2.0.0"])
90
+ else
91
+ s.add_dependency(%q<couchrest>, [">= 0"])
92
+ s.add_dependency(%q<couchrest_model>, [">= 0"])
93
+ s.add_dependency(%q<treedisha>, ["~> 0.0.2"])
94
+ s.add_dependency(%q<json>, [">= 0"])
95
+ s.add_dependency(%q<thor>, [">= 0"])
96
+ s.add_dependency(%q<thor>, ["~> 0.14.6"])
97
+ s.add_dependency(%q<couchrest>, ["~> 1.0.1"])
98
+ s.add_dependency(%q<treedisha>, ["~> 0.0.2"])
99
+ s.add_dependency(%q<rspec>, ["~> 2.0.0"])
100
+ end
101
+ else
102
+ s.add_dependency(%q<couchrest>, [">= 0"])
103
+ s.add_dependency(%q<couchrest_model>, [">= 0"])
104
+ s.add_dependency(%q<treedisha>, ["~> 0.0.2"])
105
+ s.add_dependency(%q<json>, [">= 0"])
106
+ s.add_dependency(%q<thor>, [">= 0"])
107
+ s.add_dependency(%q<thor>, ["~> 0.14.6"])
108
+ s.add_dependency(%q<couchrest>, ["~> 1.0.1"])
109
+ s.add_dependency(%q<treedisha>, ["~> 0.0.2"])
110
+ s.add_dependency(%q<rspec>, ["~> 2.0.0"])
111
+ end
112
+ end
113
+
@@ -0,0 +1,63 @@
1
+ module Chillfile
2
+ # CLI handles the command line interface for the `chillfile` binary. It is a `Thor` application.
3
+ class CLI < ::Thor
4
+
5
+ class_option "path",
6
+ :default => ".",
7
+ :aliases => '-p',
8
+ :banner => "Path to files"
9
+
10
+ class_option "couchdb_server",
11
+ :default => "http://localhost:5984",
12
+ :aliases => '-s',
13
+ :banner => "CouchDB Server URL"
14
+
15
+ class_option "couchdb_database",
16
+ :default => "chillfile",
17
+ :aliases => '-db',
18
+ :banner => "CouchDB Database name"
19
+
20
+ class_option "couchdb_type_key",
21
+ :default => "type",
22
+ :aliases => '-tk',
23
+ :banner => "Attribute name of a CouchDB doc to describe its type"
24
+
25
+ class_option "version",
26
+ :type => :boolean,
27
+ :aliases => '-v',
28
+ :banner => "print version and exit"
29
+
30
+ # create a new instance with the args passed from the command line i.e. ARGV
31
+ def initialize(*)
32
+ super
33
+
34
+ cfg = {}
35
+ cfg["path"] = options[:path]
36
+ cfg["couchdb_server"] = options[:couchdb_server]
37
+ cfg["couchdb_database"] = options[:couchdb_database]
38
+ cfg["couchdb_type_key"] = options[:couchdb_type_key]
39
+
40
+ Chillfile.boot!(cfg)
41
+
42
+ if options[:version]
43
+ say "chillfile v#{Chillfile::VERSION}", :red
44
+ exit
45
+ end
46
+ end
47
+
48
+ desc 'sync', 'sync filesystem into db'
49
+ def sync
50
+ Chillfile.sync!
51
+ end
52
+
53
+ desc 'fslist', 'json list of files in the filesystem'
54
+ def fslist
55
+ say Chillfile.fs_list
56
+ end
57
+
58
+ desc 'dblist', 'json list of files in the couchdb'
59
+ def dblist
60
+ say Chillfile.db_list
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,40 @@
1
+ module Chillfile
2
+ class Config
3
+ CONFIG_FILE = ".chillfile"
4
+
5
+ DEFAULTS = {
6
+ "path" => ".",
7
+ "couchdb_server" => "http://localhost:5984",
8
+ "couchdb_database" => "chillfile",
9
+ "couchdb_type_key" => "type"
10
+ }.freeze
11
+
12
+ def initialize(options = {})
13
+ @config = {}.merge(DEFAULTS)
14
+ if File.exists?(CONFIG_FILE)
15
+ file = File.read(CONFIG_FILE)
16
+ @config.merge(JSON.parse(file))
17
+ else
18
+ #TODO use a logger
19
+ #TODO only show the following line in debug loglevel
20
+ #puts "no config file ('#{CONFIG_FILE}') found => using defaults"
21
+ end
22
+ @config.merge!(options) if options
23
+ @config.freeze
24
+ end
25
+
26
+ def [](key)
27
+ if @config.has_key? key
28
+ @config[key]
29
+ else
30
+ false
31
+ end
32
+ end
33
+
34
+ def with_path
35
+ Dir.chdir self["path"] do
36
+ yield
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,11 @@
1
+ module Chillfile
2
+ module DatabaseServer
3
+ class << self
4
+ def new
5
+ server = CouchRest.new Chillfile.config["couchdb_server"]
6
+ server.default_database = Chillfile.config["couchdb_database"]
7
+ server
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ class Chillfile::Model::Base < CouchRest::Model::Base
2
+ use_database Chillfile.db
3
+ end
@@ -0,0 +1,28 @@
1
+ class Chillfile::Model::SyncFile < Chillfile::Model::Base
2
+ timestamps!
3
+ property :checksum, String
4
+ property :paths, [String]
5
+
6
+ # alternative to paths.empty?
7
+ property :deleted, TrueClass, :default => false
8
+
9
+ validates_uniqueness_of :checksum
10
+
11
+ view_by :checksum
12
+
13
+ view_by :filesystem, :map => "
14
+ function(doc) {
15
+ if (doc['type'] == 'Chillfile::Model::SyncFile') {
16
+ for (var i = 0; i < doc['paths'].length; i++) {
17
+ emit(null, [doc['checksum'], doc['paths'][i]]);
18
+ }
19
+ }
20
+ }
21
+ "
22
+
23
+ def self.by_filesystem_raw
24
+ self.by_filesystem(:include_docs => false)["rows"].map do |f|
25
+ f["value"]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ module Chillfile
2
+ module Model
3
+ def self.load!
4
+ configure!
5
+
6
+ # all models
7
+ require File.join(File.dirname(__FILE__), "model/base")
8
+ require File.join(File.dirname(__FILE__), "model/sync_file")
9
+ end
10
+
11
+ private
12
+
13
+ def self.configure!
14
+ CouchRest::Model::Base.configure do |config|
15
+ config.mass_assign_any_attribute = true
16
+ config.model_type_key = Chillfile.config["couchdb_type_key"]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,118 @@
1
+ module Chillfile
2
+ module Sync
3
+ class << self
4
+ def process!(comparator)
5
+
6
+ # created files
7
+ comparator.created.each do |checksum, path|
8
+ for_doc_with(checksum) do |doc|
9
+ if doc
10
+ update_doc_add_path(doc, path)
11
+ else
12
+ create_doc(checksum, path)
13
+ end
14
+ end
15
+ end
16
+
17
+ # moved files
18
+ comparator.moved.each do |checksum, paths|
19
+ for_doc_with(checksum) do |doc|
20
+ update_doc_paths(doc, paths[:old_paths], paths[:new_paths])
21
+ end
22
+ end
23
+
24
+ # modified files
25
+ comparator.modified.each do |path, checksums|
26
+ for_doc_with(checksums[:old_checksum]) do |doc|
27
+
28
+ # split it up if there is more than one path
29
+ if doc.paths.size > 1
30
+ base_doc = update_doc_paths(doc, [path]),
31
+ forked_doc = create_doc(checksums[:new_checksum], path)
32
+
33
+ [base_doc, forked_doc]
34
+ else
35
+ update_doc_attachment(doc)
36
+ end
37
+ end
38
+ end
39
+
40
+ # deleted
41
+ comparator.deleted.each do |checksum, path|
42
+ for_doc_with(checksum) do |doc|
43
+ if doc.paths.size > 1
44
+ update_doc_paths(doc, [path])
45
+ else
46
+ delete_doc(doc)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ # CREATED
55
+ def create_doc(checksum, path)
56
+ doc = Chillfile::Model::SyncFile.new(:checksum => checksum, :paths => [path])
57
+ doc.save
58
+ begin
59
+ file = File.open(path)
60
+ doc.create_attachment(:file => file, :name => "master")
61
+ ensure
62
+ file.close
63
+ end
64
+ doc
65
+ end
66
+
67
+ # COPIED
68
+ def update_doc_add_path(doc, path)
69
+ doc.paths << path
70
+
71
+ doc
72
+ end
73
+
74
+ # MOVED
75
+ def update_doc_paths(doc, del_paths = [], add_paths = [])
76
+ # del old paths
77
+ del_paths.each do |path|
78
+ doc.paths.delete(path)
79
+ end
80
+
81
+ # add new paths
82
+ doc.paths = doc.paths + add_paths
83
+
84
+ doc
85
+ end
86
+
87
+ # MODIFIED
88
+ def update_doc_attachment(doc)
89
+ doc.checksum = checksums[:new_checksum]
90
+ begin
91
+ file = File.open(doc.paths.first)
92
+ doc.update_attachment(:file => file, :name => "master")
93
+ ensure
94
+ file.close
95
+ end
96
+ doc
97
+ end
98
+
99
+ # DELETED
100
+ def delete_doc(doc)
101
+ doc.deleted = true
102
+ doc.paths = []
103
+ doc
104
+ end
105
+
106
+ # wrapper
107
+ def for_doc_with(checksum, &block)
108
+ old_doc = Chillfile::Model::SyncFile.by_checksum(:key => checksum).first
109
+ new_doc_or_docs = block.call(old_doc)
110
+ if new_doc_or_docs.is_a? Array
111
+ new_doc_or_docs.each{|d| d.save}
112
+ else
113
+ new_doc_or_docs.save
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
data/lib/chillfile.rb ADDED
@@ -0,0 +1,56 @@
1
+ require "yaml"
2
+
3
+ require 'rubygems'
4
+ require "couchrest"
5
+ require 'couchrest_model'
6
+ require "treedisha"
7
+ require "json"
8
+ require "thor"
9
+
10
+ require File.join(File.dirname(__FILE__), "chillfile/config")
11
+ require File.join(File.dirname(__FILE__), "chillfile/cli")
12
+ require File.join(File.dirname(__FILE__), "chillfile/database_server")
13
+ require File.join(File.dirname(__FILE__), "chillfile/sync")
14
+ require File.join(File.dirname(__FILE__), "chillfile/model")
15
+
16
+ module Chillfile
17
+ get_version = lambda do
18
+ v = YAML.parse_file(File.join(File.dirname(__FILE__), "../version.yml"))
19
+ "#{v[:major].value}.#{v[:minor].value}.#{v[:patch].value}"
20
+ end
21
+ VERSION = get_version.call
22
+
23
+ class << self
24
+ def boot!(config = {})
25
+ @@config = Chillfile::Config.new(config)
26
+ @@dbserver = Chillfile::DatabaseServer.new
27
+ Chillfile::Model.load!
28
+ true
29
+ end
30
+
31
+ def config
32
+ @@config
33
+ end
34
+ def db
35
+ @@dbserver.default_database
36
+ end
37
+
38
+ def sync!
39
+ fs = fs_list
40
+ db = db_list
41
+ comparator = Treedisha::Comparator.new(fs_list, db_list)
42
+
43
+ Chillfile::Sync.process!(comparator)
44
+ end
45
+
46
+ # filesystem
47
+ def fs_list
48
+ Treedisha::Filesystem.all_files_with_sha1(config["path"])
49
+ end
50
+
51
+ # databse
52
+ def db_list
53
+ Chillfile::Model::SyncFile.by_filesystem_raw
54
+ end
55
+ end
56
+ end
@@ -0,0 +1 @@
1
+ i moved using this special code: 1337
@@ -0,0 +1 @@
1
+ i moved using this special code: 1337
File without changes
@@ -0,0 +1 @@
1
+ foo :D
@@ -0,0 +1 @@
1
+ foo :D
@@ -0,0 +1 @@
1
+ i am a new file :D
@@ -0,0 +1 @@
1
+ i moved using this special code: 1337
@@ -0,0 +1 @@
1
+ i moved using this special code: 1337
File without changes
@@ -0,0 +1 @@
1
+ foo :D
@@ -0,0 +1,3 @@
1
+ i was another deleted file :'(
2
+
3
+ just sooo sad..
@@ -0,0 +1,3 @@
1
+ i will be deleted :/
2
+
3
+ stop staring at me!!! stfu!
@@ -0,0 +1 @@
1
+ [["ab4b262b83ad979d10a2c3c633242bb222ba74e7", "./bar.1.moved.untouched"], ["ab4b262b83ad979d10a2c3c633242bb222ba74e7", "./bar.2.moved.copy"], ["da39a3ee5e6b4b0d3255bfef95601890afd80709", "./bar.3.moved.copy"], ["83a4f6db0964dd03480be5f781eec6c5c2f7f5f2", "./foo.fx.copy"], ["83a4f6db0964dd03480be5f781eec6c5c2f7f5f2", "./foo.untouched"], ["cd84598b6fcb747a2b1954934b964e5a5c27836e", "./moo.new"], ["ab4b262b83ad979d10a2c3c633242bb222ba74e7", "./subdir_b/bar.4.moved.copy"]]
@@ -0,0 +1 @@
1
+ [["ab4b262b83ad979d10a2c3c633242bb222ba74e7", "./bar.0.moved.deleted"], ["da39a3ee5e6b4b0d3255bfef95601890afd80709", "./bar.1.moved.untouched"], ["83a4f6db0964dd03480be5f781eec6c5c2f7f5f2", "./foo.untouched"], ["5ab7aa2b4aaa458fd89089ce4384102a33bf7765", "./subdir/mii.deleted"], ["c0ae0100acd4b0063535dd8fbbdf87919741e320", "./wuu.deleted"]]
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe Chillfile::Model::SyncFile do
4
+ include DbHelper
5
+
6
+ before(:each) do
7
+ reset_db!
8
+ end
9
+
10
+ it "should be possible create a file" do
11
+ Chillfile::Model::SyncFile.new(:paths => ["./foo/bar.baz"], :checksum => "13123f6casdd03480be5f781ee12312asdasd232").save.persisted?.should be_true
12
+ end
13
+
14
+ it "should be possible to find using a checksum" do
15
+ Chillfile::Model::SyncFile.new(:paths => ["./foo/bar.baz", "./woo_lands"], :checksum => "13123f6casdd03480be5f781ee12312asdasd232").save
16
+ Chillfile::Model::SyncFile.by_checksum(:key => "13123f6casdd03480be5f781ee12312asdasd232").first[:paths].should == ["./foo/bar.baz", "./woo_lands"]
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+
3
+ describe Chillfile do
4
+ include ListHelper
5
+ include FsHelper
6
+ include DbHelper
7
+
8
+ before(:each) do
9
+ @before_list = sort_by_path(FixturesHelper.parse_json_file("filesystem_before.json"))
10
+ @after_list = sort_by_path(FixturesHelper.parse_json_file("filesystem_after.json"))
11
+ reset_db!
12
+ switch_fs!
13
+ end
14
+
15
+ it "should be possible to list from different fs" do
16
+ @before_list.should_not == @after_list
17
+ Chillfile.fs_list.should == @before_list
18
+
19
+ switch_fs!(:after)
20
+ Chillfile.fs_list.should == @after_list
21
+ end
22
+
23
+ it "should be possible to list from db" do
24
+ Chillfile::Model::SyncFile.new(:paths => ["./foo/bar.baz"], :checksum => "13123f6casdd03480be5f781ee12312asdasd232").save
25
+ Chillfile.db_list.should == [["13123f6casdd03480be5f781ee12312asdasd232", "./foo/bar.baz"]]
26
+ end
27
+
28
+ it "should be possible to sync from fs to db" do
29
+ Chillfile.sync!
30
+ sort_by_path(Chillfile.db_list).should == @before_list
31
+
32
+ switch_fs!(:after)
33
+
34
+ Chillfile.sync!
35
+ sort_by_path(Chillfile.db_list).should == @after_list
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ require "rubygems"
2
+ require "rspec"
3
+
4
+ require File.join(File.dirname(__FILE__), "../lib/chillfile")
5
+
6
+ require File.join(File.dirname(__FILE__), "support/fixtures_helper")
7
+ require File.join(File.dirname(__FILE__), "support/list_helper")
8
+ require File.join(File.dirname(__FILE__), "support/db_helper")
9
+ require File.join(File.dirname(__FILE__), "support/fs_helper")
10
+
11
+ FsHelper.switch_fs!
12
+
13
+ Chillfile.boot!("couchdb_database" => "chillfile-tests")
14
+
15
+ DbHelper.reset_db!
@@ -0,0 +1,10 @@
1
+ module DbHelper
2
+ def self.reset_db!
3
+ Chillfile.db.recreate!
4
+ end
5
+
6
+ # alias
7
+ def reset_db!
8
+ DbHelper.reset_db!
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module FixturesHelper
2
+ def self.read_file(filename)
3
+ path = File.join(File.dirname(__FILE__), "..", "fixtures", filename)
4
+ File.read(path)
5
+ end
6
+
7
+ def self.parse_json_file(filename)
8
+ JSON.parse(read_file(filename))
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module FsHelper
2
+ def self.switch_fs!(state = :before)
3
+ Dir.chdir(File.join(File.dirname(__FILE__), "../filesystem_#{state}"))
4
+ end
5
+
6
+ # alias
7
+ def switch_fs!(*args)
8
+ FsHelper.switch_fs!(*args)
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module ListHelper
2
+ def sort_by_path(list)
3
+ list.sort!{|a,b| a.last <=> b.last}
4
+ end
5
+ end
data/version.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 1
5
+ :build:
metadata ADDED
@@ -0,0 +1,235 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chillfile
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - dpree
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-08 00:00:00 +01:00
18
+ default_executable: chillfile
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: couchrest
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: couchrest_model
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: treedisha
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ - 0
56
+ - 2
57
+ version: 0.0.2
58
+ type: :runtime
59
+ prerelease: false
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: json
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: *id004
74
+ - !ruby/object:Gem::Dependency
75
+ name: thor
76
+ requirement: &id005 !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ segments:
82
+ - 0
83
+ version: "0"
84
+ type: :runtime
85
+ prerelease: false
86
+ version_requirements: *id005
87
+ - !ruby/object:Gem::Dependency
88
+ name: thor
89
+ requirement: &id006 !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ segments:
95
+ - 0
96
+ - 14
97
+ - 6
98
+ version: 0.14.6
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *id006
102
+ - !ruby/object:Gem::Dependency
103
+ name: couchrest
104
+ requirement: &id007 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 1
111
+ - 0
112
+ - 1
113
+ version: 1.0.1
114
+ type: :runtime
115
+ prerelease: false
116
+ version_requirements: *id007
117
+ - !ruby/object:Gem::Dependency
118
+ name: treedisha
119
+ requirement: &id008 !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ segments:
125
+ - 0
126
+ - 0
127
+ - 2
128
+ version: 0.0.2
129
+ type: :runtime
130
+ prerelease: false
131
+ version_requirements: *id008
132
+ - !ruby/object:Gem::Dependency
133
+ name: rspec
134
+ requirement: &id009 !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ~>
138
+ - !ruby/object:Gem::Version
139
+ segments:
140
+ - 2
141
+ - 0
142
+ - 0
143
+ version: 2.0.0
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: *id009
147
+ description: Let your files chill on the couch
148
+ email: whiterabbit.init@gmail.com
149
+ executables:
150
+ - chillfile
151
+ extensions: []
152
+
153
+ extra_rdoc_files:
154
+ - LICENSE
155
+ - README.md
156
+ files:
157
+ - .rspec
158
+ - Gemfile
159
+ - Gemfile.lock
160
+ - LICENSE
161
+ - README.md
162
+ - Rakefile
163
+ - autotest/discover.rb
164
+ - bin/chillfile
165
+ - chillfile.gemspec
166
+ - lib/chillfile.rb
167
+ - lib/chillfile/cli.rb
168
+ - lib/chillfile/config.rb
169
+ - lib/chillfile/database_server.rb
170
+ - lib/chillfile/model.rb
171
+ - lib/chillfile/model/base.rb
172
+ - lib/chillfile/model/sync_file.rb
173
+ - lib/chillfile/sync.rb
174
+ - spec/filesystem_after/bar.1.moved.untouched
175
+ - spec/filesystem_after/bar.2.moved.copy
176
+ - spec/filesystem_after/bar.3.moved.copy
177
+ - spec/filesystem_after/foo.fx.copy
178
+ - spec/filesystem_after/foo.untouched
179
+ - spec/filesystem_after/moo.new
180
+ - spec/filesystem_after/subdir_b/bar.4.moved.copy
181
+ - spec/filesystem_before/bar.0.moved.deleted
182
+ - spec/filesystem_before/bar.1.moved.untouched
183
+ - spec/filesystem_before/foo.untouched
184
+ - spec/filesystem_before/subdir/mii.deleted
185
+ - spec/filesystem_before/wuu.deleted
186
+ - spec/fixtures/filesystem_after.json
187
+ - spec/fixtures/filesystem_before.json
188
+ - spec/lib/chillfile/model/sync_file_spec.rb
189
+ - spec/lib/chillfile_spec.rb
190
+ - spec/spec_helper.rb
191
+ - spec/support/db_helper.rb
192
+ - spec/support/fixtures_helper.rb
193
+ - spec/support/fs_helper.rb
194
+ - spec/support/list_helper.rb
195
+ - version.yml
196
+ has_rdoc: true
197
+ homepage: http://github.com/dpree/chillfile
198
+ licenses: []
199
+
200
+ post_install_message:
201
+ rdoc_options: []
202
+
203
+ require_paths:
204
+ - lib
205
+ required_ruby_version: !ruby/object:Gem::Requirement
206
+ none: false
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ segments:
211
+ - 0
212
+ version: "0"
213
+ required_rubygems_version: !ruby/object:Gem::Requirement
214
+ none: false
215
+ requirements:
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ segments:
219
+ - 0
220
+ version: "0"
221
+ requirements: []
222
+
223
+ rubyforge_project:
224
+ rubygems_version: 1.3.7
225
+ signing_key:
226
+ specification_version: 3
227
+ summary: Tiny tool to sync filesystem with couchdb
228
+ test_files:
229
+ - spec/lib/chillfile/model/sync_file_spec.rb
230
+ - spec/lib/chillfile_spec.rb
231
+ - spec/spec_helper.rb
232
+ - spec/support/db_helper.rb
233
+ - spec/support/fixtures_helper.rb
234
+ - spec/support/fs_helper.rb
235
+ - spec/support/list_helper.rb