dircat 0.1.12 → 0.2.0

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 (88) hide show
  1. data/LICENSE.txt +1 -1
  2. data/README.md +31 -6
  3. data/bin/dircat +5 -1
  4. data/bin/scat +9 -0
  5. data/dircat.gemspec +48 -15
  6. data/examples/example.rb +2 -1
  7. data/lib/dircat.rb +29 -34
  8. data/lib/dircat/cat_on_sqlite/cat_on_sqlite.rb +177 -0
  9. data/lib/dircat/cat_on_sqlite/directory_visitor.rb +106 -0
  10. data/lib/dircat/cat_on_sqlite/migration/00_create_dircat_properties.rb +13 -0
  11. data/lib/dircat/cat_on_sqlite/migration/01_create_categories.rb +12 -0
  12. data/lib/dircat/cat_on_sqlite/migration/02_create_images.rb +16 -0
  13. data/lib/dircat/cat_on_sqlite/migration/03_create_items.rb +23 -0
  14. data/lib/dircat/cat_on_sqlite/migration/04_create_taggings.rb +13 -0
  15. data/lib/dircat/cat_on_sqlite/migration/05_create_tags.rb +13 -0
  16. data/lib/dircat/cat_on_sqlite/model/category.rb +16 -0
  17. data/lib/dircat/cat_on_sqlite/model/image.rb +24 -0
  18. data/lib/dircat/cat_on_sqlite/model/item.rb +19 -0
  19. data/lib/dircat/cat_on_sqlite/model/tag.rb +58 -0
  20. data/lib/dircat/cat_on_sqlite/model/tagging.rb +9 -0
  21. data/lib/dircat/cat_on_sqlite/simple_cataloger_error.rb +9 -0
  22. data/lib/dircat/cat_on_sqlite_cli/cli_cat.rb +25 -0
  23. data/lib/dircat/cat_on_sqlite_cli/cli_server.rb +65 -0
  24. data/lib/dircat/cat_on_sqlite_cli/cmd_create.rb +56 -0
  25. data/lib/dircat/cat_on_sqlite_cli/cmd_list.rb +72 -0
  26. data/lib/dircat/cat_on_sqlite_cli/cmd_server.rb +62 -0
  27. data/lib/dircat/cat_on_sqlite_cli/cmd_update.rb +49 -0
  28. data/lib/dircat/{cat.rb → cat_on_yaml/cat_on_yaml.rb} +22 -10
  29. data/lib/dircat/cat_on_yaml/entry.rb +64 -0
  30. data/lib/dircat/{cli → cat_on_yaml_cli}/cli_dircat.rb +0 -0
  31. data/lib/dircat/{cli → cat_on_yaml_cli}/command_build.rb +53 -12
  32. data/lib/dircat/{cli → cat_on_yaml_cli}/command_diff.rb +4 -4
  33. data/lib/dircat/{cli → cat_on_yaml_cli}/command_query.rb +16 -2
  34. data/lib/dircat/config.rb +25 -0
  35. data/lib/dircat/extensions.rb +26 -0
  36. data/lib/dircat/server/helpers.rb +60 -0
  37. data/lib/dircat/server/my_static.rb +40 -0
  38. data/lib/dircat/server/web_server.rb +176 -0
  39. data/lib/dircat/version.rb +2 -1
  40. data/lib/dircat_on_sqlite.rb +31 -0
  41. data/lib/dircat_on_sqlite_cli.rb +37 -0
  42. data/lib/simple_cataloger_dm/cli.rb +32 -0
  43. data/lib/simple_cataloger_dm/core.rb +43 -0
  44. data/lib/simple_cataloger_dm/core/catalog.rb +141 -0
  45. data/lib/simple_cataloger_dm/core/directory_visitor.rb +107 -0
  46. data/lib/simple_cataloger_dm/core/extensions.rb +26 -0
  47. data/lib/simple_cataloger_dm/core/simple_cataloger_error.rb +9 -0
  48. data/lib/simple_cataloger_dm/models/category.rb +21 -0
  49. data/lib/simple_cataloger_dm/models/image.rb +30 -0
  50. data/lib/simple_cataloger_dm/models/item.rb +24 -0
  51. data/lib/simple_cataloger_dm/models/tag.rb +62 -0
  52. data/lib/simple_cataloger_dm/models/tagging.rb +11 -0
  53. data/lib/simple_cataloger_dm/server/helpers.rb +60 -0
  54. data/lib/simple_cataloger_dm/server/my_static.rb +40 -0
  55. data/lib/simple_cataloger_dm/server/web_server.rb +171 -0
  56. data/spec/dircat/cat_on_sqlite/cat_on_sqlite_spec.rb +41 -0
  57. data/spec/dircat/cat_on_sqlite_web/web_server_spec.rb +30 -0
  58. data/spec/dircat/{cat_spec.rb → cat_on_yaml/cat_on_yaml_spec.rb} +20 -14
  59. data/spec/dircat/{cli → cat_on_yaml_cli}/cli_dircat_spec.rb +0 -0
  60. data/spec/dircat/{cli → cat_on_yaml_cli}/command_build_spec.rb +4 -4
  61. data/spec/dircat/{cli → cat_on_yaml_cli}/command_diff_spec.rb +0 -0
  62. data/spec/dircat/{cli → cat_on_yaml_cli}/command_query_spec.rb +1 -1
  63. data/spec/fixtures/certified_output/cat_dir1_20120811.yaml +25 -0
  64. data/spec/fixtures/certified_output/cat_dir2_20120811.yaml +34 -0
  65. data/spec/fixtures/certified_output/{dircat1.yaml → dircat1_version_0.1.yaml} +0 -0
  66. data/spec/fixtures/certified_output/{dircat2.yaml → dircat2_version_0.1.yaml} +0 -0
  67. data/spec/fixtures/dir4/file1.txt +1 -0
  68. data/spec/fixtures/dir4/file2.txt +1 -0
  69. data/spec/fixtures/dir4/subdir/file3.txt +1 -0
  70. data/spec/fixtures/films/A-Z/A/Arancia meccanica [Stanley Kubrick][1971]/folder.jpg +0 -0
  71. data/spec/fixtures/films/A-Z/P/Plan 9 [Edward Wood][1959]/folder.jpg +0 -0
  72. data/spec/fixtures/films/Directors/[Akira Kurosawa]/[1940] Dersu Uzala [5]/folder.jpg +0 -0
  73. data/spec/fixtures/films/Directors/[Akira Kurosawa]/[1965] Barbarossa [Toshiro Mifune][4]/folder.jpg +0 -0
  74. data/spec/fixtures/films/Directors/[Federico Fellini]/[1963] 8 e mezzo [Marcello Mastroianni][Claudia Cardinale][5]/folder.jpg +0 -0
  75. data/spec/fixtures/films/Directors/[Woody Allen]/[1977] Annie Hall [Diane Keaton][5]/folder.jpg +0 -0
  76. data/{.gemtest → spec/fixtures/readme.txt} +0 -0
  77. data/spec/fixtures/tmp/test_ar.sqlite3 +0 -0
  78. data/spec/fixtures/tmp/test_ar.yml +7 -0
  79. data/spec/generate_directories_to_catalog.rb +80 -0
  80. data/spec/generate_mysql_catalog.rb +124 -0
  81. data/spec/spec_helper.rb +29 -0
  82. data/tasks/rspec.rake +0 -2
  83. metadata +390 -112
  84. data/lib/dircat/entry.rb +0 -61
  85. data/lib/dircat/extension_md5.rb +0 -25
  86. data/lib/dircat/extension_numeric.rb +0 -15
  87. data/spec/dircat/md5_spec.rb +0 -8
  88. data/spec/dircat/numeric_spec.rb +0 -13
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+ module SimpleCataloger
3
+
4
+ class Tagging
5
+ include DataMapper::Resource
6
+ property :id, Serial
7
+ belongs_to :item
8
+ belongs_to :tag
9
+ end
10
+
11
+ end # module
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+ module SimpleCataloger
3
+ module Helpers
4
+
5
+ def partial(template, *args)
6
+ options = args.extract_options!
7
+ options.merge!(:layout => false)
8
+ if collection = options.delete(:collection) then
9
+ collection.inject([]) do |buffer, member|
10
+ buffer << haml(template, options.merge(
11
+ :layout => false,
12
+ :locals => {template.to_sym => member}
13
+ )
14
+ )
15
+ end.join("\n")
16
+ else
17
+ haml(template, options)
18
+ end
19
+ end
20
+
21
+ def partial_erb(template)
22
+ erb template
23
+ end
24
+
25
+ def base_url
26
+ if Sinatra::Application.port == 80
27
+ "http://#{Sinatra::Application.host}/"
28
+ else
29
+ "http://#{Sinatra::Application.host}:#{Sinatra::Application.port}/"
30
+ end
31
+ end
32
+
33
+ def when_updated(time)
34
+ days = (Time.now - time) / (60 * 60 * 24)
35
+ case days.to_i
36
+ when 0
37
+ "today"
38
+ when 1
39
+ "yesterday"
40
+ else
41
+ "#{sprintf("%i", days) } days ago"
42
+ end
43
+ end
44
+
45
+ def gen_url(field, visible_field = nil)
46
+ visible_field ||= field
47
+ pos = request.env['REQUEST_URI'].index "?"
48
+ url = if pos
49
+ request.env['REQUEST_URI'][0...pos]
50
+ else
51
+ request.env['REQUEST_URI']
52
+ end
53
+ "<a href='#{url}?order=#{field}'>#{visible_field}</a>"
54
+ end
55
+
56
+ def rfc_3339(timestamp)
57
+ timestamp.strftime("%Y-%m-%dT%H:%M:%SZ")
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,40 @@
1
+ module Rack
2
+
3
+ # The Rack::Static middleware intercepts requests for static files
4
+ # (javascript files, images, stylesheets, etc) based on the url prefixes
5
+ # passed in the options, and serves them using a Rack::File object. This
6
+ # allows a Rack stack to serve both static and dynamic content.
7
+ #
8
+ # Examples:
9
+ # use Rack::Static, :urls => ["/media"]
10
+ # will serve all requests beginning with /media from the "media" folder
11
+ # located in the current directory (ie media/*).
12
+ #
13
+ # use Rack::Static, :urls => ["/css", "/images"], :root => "public"
14
+ # will serve all requests beginning with /css or /images from the folder
15
+ # "public" in the current directory (ie public/css/* and public/images/*)
16
+
17
+ class MyStatic
18
+
19
+ def initialize(app, options={})
20
+ @app = app
21
+ @urls = options[:urls] || ["/favicon.ico"]
22
+ root = options[:root] || Dir.pwd
23
+ @file_server = Rack::File.new(root)
24
+ end
25
+
26
+ def call(env)
27
+ path = env["PATH_INFO"]
28
+ puts "mystatic #{path} #{URI.decode(path)}"
29
+ path = URI.decode(path)
30
+ can_serve = @urls.any? { |url| path.index(url) == 0 }
31
+
32
+ if can_serve
33
+ @file_server.call(env)
34
+ else
35
+ @app.call(env)
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,171 @@
1
+ # -*- coding: utf-8 -*-
2
+ module SimpleCataloger
3
+
4
+ class WebServer < Sinatra::Base
5
+
6
+ def self.run!(*args)
7
+ options = args.last.is_a?(::Hash) ? args.last : {}
8
+ catalog = options[:catalog]
9
+
10
+ catalog.roots.each do |root|
11
+ use Rack::MyStatic,
12
+ :urls => ["/#{File.basename(root)}"],
13
+ :root => File.dirname(root)
14
+ puts "mount #{File.basename(root)} -> #{File.dirname(root)}"
15
+ end
16
+
17
+ define_method :catalog do
18
+ catalog
19
+ end
20
+ super(*args)
21
+ end
22
+
23
+ # turns on static file serving for Sinatra::Base apps
24
+ enable :static
25
+
26
+ server_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'web'))
27
+ set :public, File.join(server_dir, 'public')
28
+ set :views, File.join(server_dir, 'views')
29
+
30
+ helpers do
31
+ include Rack::Utils
32
+ alias_method :h, :escape_html
33
+ end
34
+
35
+ helpers Sinatra::GroupItems
36
+ helpers Helpers
37
+
38
+ get '/app.css' do
39
+ content_type 'text/css', :charset => 'utf-8'
40
+ sass :app
41
+ end
42
+
43
+ get "/js/tooltips/tooltips.css" do
44
+ content_type 'text/css', :charset => 'utf-8'
45
+ sass "/js/tooltips/tooltips".to_sym
46
+ end
47
+
48
+ get '/' do
49
+ @catalog = catalog
50
+ @items = Item.all
51
+ order = params[:o] || "alpha"
52
+
53
+ @render = proc { |item|
54
+ "<a href=\"/item/#{item.id}\" rel=\"#{item.id}\">#{item.name}</a>" +
55
+ if item.rating then
56
+ " (r:#{item.rating})"
57
+ else
58
+ " (r:unrated)"
59
+ end
60
+ }
61
+
62
+ case order
63
+ when "alpha"
64
+ @grouped_items = group_items(@items, :group_size => 5)
65
+ @title = "Films in alphabetical order (c:#{@items.length})"
66
+ when "time"
67
+ @grouped_items = group_items(@items, :group_size => 1, :header => proc { |film| film.added_at })
68
+ @title = "Films in time added order (c:#{@items.length})"
69
+ end
70
+ haml :items
71
+ end
72
+
73
+ get '/item/:id' do
74
+ @catalog = catalog
75
+ @item = Item.get(params[:id])
76
+ @grouped_items = group_items(@item.tags, :group_size => 1, :header => proc { |tag| tag.category.name })
77
+ haml :item
78
+ end
79
+
80
+ get '/categories' do
81
+ @catalog = catalog
82
+ @categories = Category.all
83
+ haml :categories
84
+ end
85
+
86
+ get "/category/:id" do
87
+ @catalog = catalog
88
+ @category = Category.get(params[:id])
89
+ haml :category
90
+ end
91
+
92
+ get "/tag/:id" do
93
+ @catalog = catalog
94
+ @tag = Tag.get(params[:id])
95
+ haml :tag
96
+ end
97
+
98
+ get "/random" do
99
+ max_peso = Item.inject.each do |f|
100
+ f.peso
101
+ end
102
+ Random.new.rand(0..maxpeso)
103
+ end
104
+
105
+ #######################################################################################
106
+ # Ajax
107
+
108
+ get '/ajax/ajax_item/:id' do
109
+ @item = Item.get(params[:id])
110
+ haml 'ajax/ajax_item'.to_sym, :layout => false
111
+ end
112
+
113
+ post '/ajax/open_folder' do
114
+ dir = params[:dir] || "/"
115
+ system("nautilus", dir)
116
+ "ok"
117
+ end
118
+
119
+ post "/ajax/set-category" do
120
+ id = params[:tag_id]
121
+ category_name = params[:category_name]
122
+ tag = Tag.get(id.to_i)
123
+ category = Category.first_or_create(:name => category_name)
124
+ tag.category = category
125
+ tag.save
126
+ catalog.update_categories
127
+ catalog.write_config
128
+ "ok"
129
+ end
130
+
131
+ get '/ajax/ajax_set_flag/:id' do
132
+ @film = Item.get(params[:id])
133
+ if (params[:checked] == "true")
134
+ @film.flagged_at = Time.new
135
+ else
136
+ @film.flagged_at = nil
137
+ end
138
+ @film.save
139
+ "ok"
140
+ end
141
+
142
+ #######################################################################################
143
+ # Tests
144
+
145
+ get "/test/resize" do
146
+ @catalog = catalog
147
+ haml "/test/resize".to_sym
148
+ end
149
+
150
+ get "/test/jquery" do
151
+ @catalog = catalog
152
+ haml "/test/jquery".to_sym
153
+ end
154
+
155
+ get "/test/lightbox" do
156
+ @catalog = catalog
157
+ haml "/test/lightbox".to_sym
158
+ end
159
+
160
+ get "/test/select" do
161
+ @catalog = catalog
162
+ haml "/test/select".to_sym
163
+ end
164
+
165
+ get "/test/protovis" do
166
+ @catalog = catalog
167
+ haml "/test/protovis".to_sym
168
+ end
169
+ end
170
+
171
+ end
@@ -0,0 +1,41 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
3
+ include SimpleCataloger
4
+
5
+ describe CatOnSqlite do
6
+ it "should write and read catalog" do
7
+
8
+ TestCatalogHelper.create_test_catalog
9
+ filename = File.join(TMP_DIR, "test_ar")
10
+ CatOnSqlite.new(filename).open
11
+
12
+ Category.all.map(&:name).should == %w(Actor Director)
13
+
14
+
15
+ Category.find_by_name("Actor").tags.map(&:name).should == ["Diane Keaton", "Mia Farrow"]
16
+ Category.find_by_name("Director").tags.map(&:name).should == ["Fellini", "Kurosawa", "Woody Allen"]
17
+ Tag.all.map(&:name).should == ["Mia Farrow", "Diane Keaton", "Woody Allen", "Fellini", "Kurosawa"]
18
+
19
+
20
+ Tag.find_by_name("Woody Allen").category.name == "Director"
21
+ Tag.find_by_name("Mia Farrow").category.name == "Actor"
22
+ Tag.find_by_name("Woody Allen").items.map(&:name).should == ["Annie Hall", "Play It Again, Sam"]
23
+
24
+ Item.find_by_name("Annie Hall").images.map(&:path).should == ['path']
25
+ Item.find_by_name("Annie Hall").images.first.to_json.should == "{\"item\":\"Annie Hall\",\"tag\":null,\"src\":\"path from root\"}"
26
+ end
27
+
28
+ it "should extract tag from directory name" do
29
+
30
+ TestCatalogHelper.create_test_catalog
31
+ filename = File.join(TMP_DIR, "test_ar")
32
+ CatOnSqlite.new(filename).open
33
+
34
+ dir_name = "Broadway Danny Rose [Woody Allen][Mia Farrow][1984]"
35
+ Tag.extract_tags(dir_name).should == ['Woody Allen', 'Mia Farrow', '1984']
36
+ Tag.extract_name(dir_name).should == "Broadway Danny Rose"
37
+ Tag.match_category("1984").name.should == "year"
38
+ Tag.match_category("1985").name.should == "year"
39
+ end
40
+
41
+ end
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
3
+
4
+ module SimpleCataloger
5
+ describe WebServer do
6
+
7
+ include Rack::Test::Methods
8
+
9
+ def app
10
+ @app ||= WebServer
11
+ end
12
+
13
+ it "should respond to /" do
14
+ pending "need integrate all code"
15
+ get '/'
16
+ # pp last_response
17
+ last_response.should be_ok
18
+ end
19
+
20
+
21
+ # before(:each) do
22
+ # @web_server = WebServer.new
23
+ # end
24
+ #
25
+ # it "should desc" do
26
+ # # TODO
27
+ # end
28
+ end
29
+
30
+ end
@@ -1,6 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
-
3
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
4
3
 
5
4
  #
6
5
  # dir1 contains 2 files
@@ -9,35 +8,35 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
9
8
  #
10
9
  # dir3 contains two duplicated files
11
10
 
12
- describe Cat do
11
+ describe CatOnYaml do
13
12
 
14
13
  before do
15
14
  @data_dir = TEST_DIR
16
15
  end
17
16
 
18
17
  it "should build catalog from dir1" do
19
- cat1 = Cat.from_dir(File.join(@data_dir, "dir1"))
18
+ cat1 = CatOnYaml.from_dir(File.join(@data_dir, "dir1"))
20
19
  cat1.size.should == 2
21
20
  cat1.bytes.should == 4
22
21
  end
23
22
 
24
23
  it "should load catalog from dir2" do
25
- cat2 = Cat.from_dir(File.join(@data_dir, "dir2"))
24
+ cat2 = CatOnYaml.from_dir(File.join(@data_dir, "dir2"))
26
25
  cat2.size.should == 3
27
26
  cat2.bytes.should == 6
28
27
  end
29
28
 
30
29
  it "(dir1 - dir2): the difference from dir1 and dir2 is empty" do
31
- cat1 = Cat.from_dir(File.join(@data_dir, "dir1"))
32
- cat2 = Cat.from_dir(File.join(@data_dir, "dir2"))
30
+ cat1 = CatOnYaml.from_dir(File.join(@data_dir, "dir1"))
31
+ cat2 = CatOnYaml.from_dir(File.join(@data_dir, "dir2"))
33
32
  # dir1 contains all the files in dir2
34
33
  cat_diff = cat1 - cat2
35
34
  cat_diff.size.should == 0
36
35
  end
37
36
 
38
37
  it "(dir2 - dir1): the difference from dir2 and dir1 is a file" do
39
- cat1 = Cat.from_dir(File.join(@data_dir, "dir1"))
40
- cat2 = Cat.from_dir(File.join(@data_dir, "dir2"))
38
+ cat1 = CatOnYaml.from_dir(File.join(@data_dir, "dir1"))
39
+ cat2 = CatOnYaml.from_dir(File.join(@data_dir, "dir2"))
41
40
 
42
41
  # dir2 contains one file more than dir1
43
42
  cat_diff = cat2 - cat1
@@ -45,10 +44,17 @@ describe Cat do
45
44
  end
46
45
 
47
46
  it "should detect duplicates" do
48
- cat1 = Cat.from_dir(File.join(@data_dir, "dir3"))
47
+ cat1 = CatOnYaml.from_dir(File.join(@data_dir, "dir3"))
49
48
  cat1.duplicates.should have(1).files
50
49
  end
51
50
 
51
+ # dir4 has an broken symlink, otherwise is identical to dir1
52
+ it "should build catalog from dir4" do
53
+ cat1 = CatOnYaml.from_dir(File.join(@data_dir, "dir4"))
54
+ cat1.size.should == 3
55
+ cat1.bytes.should == 20
56
+ end
57
+
52
58
  context "save to a file" do
53
59
  before do
54
60
  @tmp_file = File.join(Dir.tmpdir, "dircat1.yaml")
@@ -59,23 +65,23 @@ describe Cat do
59
65
  end
60
66
 
61
67
  it "saving to a file" do
62
- cat1 = Cat.from_dir(File.join(@data_dir, "dir1"))
68
+ cat1 = CatOnYaml.from_dir(File.join(@data_dir, "dir1"))
63
69
  cat1.save_to(@tmp_file)
64
70
 
65
- dircat1_bis = Cat.from_file(@tmp_file)
71
+ dircat1_bis = CatOnYaml.from_file(@tmp_file)
66
72
  (cat1 - dircat1_bis).size.should == 0
67
73
  (dircat1_bis - cat1).size.should == 0
68
74
  end
69
75
 
70
76
  it "saving to an non-existent file should raise an exception" do
71
- cat1 = Cat.from_dir(File.join(@data_dir, "dir1"))
77
+ cat1 = CatOnYaml.from_dir(File.join(@data_dir, "dir1"))
72
78
  not_existent_file = File.join(Dir.tmpdir, "not_existent", "dircat1.yaml")
73
79
  lambda { cat1.save_to(not_existent_file) }.should raise_exception(DirCatException)
74
80
  end
75
81
  end
76
82
 
77
83
  it "should print a report" do
78
- cat1 = Cat.from_dir(File.join(@data_dir, "dir1"))
84
+ cat1 = CatOnYaml.from_dir(File.join(@data_dir, "dir1"))
79
85
  cat1.size.should == 2
80
86
  cat1.bytes.should == 4
81
87