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.
- data/LICENSE.txt +1 -1
- data/README.md +31 -6
- data/bin/dircat +5 -1
- data/bin/scat +9 -0
- data/dircat.gemspec +48 -15
- data/examples/example.rb +2 -1
- data/lib/dircat.rb +29 -34
- data/lib/dircat/cat_on_sqlite/cat_on_sqlite.rb +177 -0
- data/lib/dircat/cat_on_sqlite/directory_visitor.rb +106 -0
- data/lib/dircat/cat_on_sqlite/migration/00_create_dircat_properties.rb +13 -0
- data/lib/dircat/cat_on_sqlite/migration/01_create_categories.rb +12 -0
- data/lib/dircat/cat_on_sqlite/migration/02_create_images.rb +16 -0
- data/lib/dircat/cat_on_sqlite/migration/03_create_items.rb +23 -0
- data/lib/dircat/cat_on_sqlite/migration/04_create_taggings.rb +13 -0
- data/lib/dircat/cat_on_sqlite/migration/05_create_tags.rb +13 -0
- data/lib/dircat/cat_on_sqlite/model/category.rb +16 -0
- data/lib/dircat/cat_on_sqlite/model/image.rb +24 -0
- data/lib/dircat/cat_on_sqlite/model/item.rb +19 -0
- data/lib/dircat/cat_on_sqlite/model/tag.rb +58 -0
- data/lib/dircat/cat_on_sqlite/model/tagging.rb +9 -0
- data/lib/dircat/cat_on_sqlite/simple_cataloger_error.rb +9 -0
- data/lib/dircat/cat_on_sqlite_cli/cli_cat.rb +25 -0
- data/lib/dircat/cat_on_sqlite_cli/cli_server.rb +65 -0
- data/lib/dircat/cat_on_sqlite_cli/cmd_create.rb +56 -0
- data/lib/dircat/cat_on_sqlite_cli/cmd_list.rb +72 -0
- data/lib/dircat/cat_on_sqlite_cli/cmd_server.rb +62 -0
- data/lib/dircat/cat_on_sqlite_cli/cmd_update.rb +49 -0
- data/lib/dircat/{cat.rb → cat_on_yaml/cat_on_yaml.rb} +22 -10
- data/lib/dircat/cat_on_yaml/entry.rb +64 -0
- data/lib/dircat/{cli → cat_on_yaml_cli}/cli_dircat.rb +0 -0
- data/lib/dircat/{cli → cat_on_yaml_cli}/command_build.rb +53 -12
- data/lib/dircat/{cli → cat_on_yaml_cli}/command_diff.rb +4 -4
- data/lib/dircat/{cli → cat_on_yaml_cli}/command_query.rb +16 -2
- data/lib/dircat/config.rb +25 -0
- data/lib/dircat/extensions.rb +26 -0
- data/lib/dircat/server/helpers.rb +60 -0
- data/lib/dircat/server/my_static.rb +40 -0
- data/lib/dircat/server/web_server.rb +176 -0
- data/lib/dircat/version.rb +2 -1
- data/lib/dircat_on_sqlite.rb +31 -0
- data/lib/dircat_on_sqlite_cli.rb +37 -0
- data/lib/simple_cataloger_dm/cli.rb +32 -0
- data/lib/simple_cataloger_dm/core.rb +43 -0
- data/lib/simple_cataloger_dm/core/catalog.rb +141 -0
- data/lib/simple_cataloger_dm/core/directory_visitor.rb +107 -0
- data/lib/simple_cataloger_dm/core/extensions.rb +26 -0
- data/lib/simple_cataloger_dm/core/simple_cataloger_error.rb +9 -0
- data/lib/simple_cataloger_dm/models/category.rb +21 -0
- data/lib/simple_cataloger_dm/models/image.rb +30 -0
- data/lib/simple_cataloger_dm/models/item.rb +24 -0
- data/lib/simple_cataloger_dm/models/tag.rb +62 -0
- data/lib/simple_cataloger_dm/models/tagging.rb +11 -0
- data/lib/simple_cataloger_dm/server/helpers.rb +60 -0
- data/lib/simple_cataloger_dm/server/my_static.rb +40 -0
- data/lib/simple_cataloger_dm/server/web_server.rb +171 -0
- data/spec/dircat/cat_on_sqlite/cat_on_sqlite_spec.rb +41 -0
- data/spec/dircat/cat_on_sqlite_web/web_server_spec.rb +30 -0
- data/spec/dircat/{cat_spec.rb → cat_on_yaml/cat_on_yaml_spec.rb} +20 -14
- data/spec/dircat/{cli → cat_on_yaml_cli}/cli_dircat_spec.rb +0 -0
- data/spec/dircat/{cli → cat_on_yaml_cli}/command_build_spec.rb +4 -4
- data/spec/dircat/{cli → cat_on_yaml_cli}/command_diff_spec.rb +0 -0
- data/spec/dircat/{cli → cat_on_yaml_cli}/command_query_spec.rb +1 -1
- data/spec/fixtures/certified_output/cat_dir1_20120811.yaml +25 -0
- data/spec/fixtures/certified_output/cat_dir2_20120811.yaml +34 -0
- data/spec/fixtures/certified_output/{dircat1.yaml → dircat1_version_0.1.yaml} +0 -0
- data/spec/fixtures/certified_output/{dircat2.yaml → dircat2_version_0.1.yaml} +0 -0
- data/spec/fixtures/dir4/file1.txt +1 -0
- data/spec/fixtures/dir4/file2.txt +1 -0
- data/spec/fixtures/dir4/subdir/file3.txt +1 -0
- data/spec/fixtures/films/A-Z/A/Arancia meccanica [Stanley Kubrick][1971]/folder.jpg +0 -0
- data/spec/fixtures/films/A-Z/P/Plan 9 [Edward Wood][1959]/folder.jpg +0 -0
- data/spec/fixtures/films/Directors/[Akira Kurosawa]/[1940] Dersu Uzala [5]/folder.jpg +0 -0
- data/spec/fixtures/films/Directors/[Akira Kurosawa]/[1965] Barbarossa [Toshiro Mifune][4]/folder.jpg +0 -0
- data/spec/fixtures/films/Directors/[Federico Fellini]/[1963] 8 e mezzo [Marcello Mastroianni][Claudia Cardinale][5]/folder.jpg +0 -0
- data/spec/fixtures/films/Directors/[Woody Allen]/[1977] Annie Hall [Diane Keaton][5]/folder.jpg +0 -0
- data/{.gemtest → spec/fixtures/readme.txt} +0 -0
- data/spec/fixtures/tmp/test_ar.sqlite3 +0 -0
- data/spec/fixtures/tmp/test_ar.yml +7 -0
- data/spec/generate_directories_to_catalog.rb +80 -0
- data/spec/generate_mysql_catalog.rb +124 -0
- data/spec/spec_helper.rb +29 -0
- data/tasks/rspec.rake +0 -2
- metadata +390 -112
- data/lib/dircat/entry.rb +0 -61
- data/lib/dircat/extension_md5.rb +0 -25
- data/lib/dircat/extension_numeric.rb +0 -15
- data/spec/dircat/md5_spec.rb +0 -8
- data/spec/dircat/numeric_spec.rb +0 -13
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
class CreateDircatProperties < ActiveRecord::Migration
|
|
3
|
+
def self.up
|
|
4
|
+
create_table :dircat_properties do |t|
|
|
5
|
+
t.string :name, :null => false
|
|
6
|
+
t.string :value, :null => false
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.down
|
|
11
|
+
drop_table :dircat_properties
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
class CreateImages < ActiveRecord::Migration
|
|
3
|
+
def self.up
|
|
4
|
+
create_table :images do |t|
|
|
5
|
+
t.string :path, :null => false
|
|
6
|
+
t.string :path_from_catalog_root, :null => false
|
|
7
|
+
|
|
8
|
+
t.integer :tag_id
|
|
9
|
+
t.integer :item_id
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.down
|
|
14
|
+
drop_table :images
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
class CreateItems < ActiveRecord::Migration
|
|
3
|
+
def self.up
|
|
4
|
+
create_table :items do |t|
|
|
5
|
+
|
|
6
|
+
t.string :md5
|
|
7
|
+
|
|
8
|
+
t.string :name, :null => false
|
|
9
|
+
t.string :path, :null => false
|
|
10
|
+
t.string :path_from_catalog_root, :null => false
|
|
11
|
+
t.integer :size, :null => false
|
|
12
|
+
|
|
13
|
+
t.date :added_at, :null => false
|
|
14
|
+
|
|
15
|
+
t.integer :rating
|
|
16
|
+
t.date :flagged_at
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.down
|
|
21
|
+
drop_table :items
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
|
|
4
|
+
class Category < ActiveRecord::Base
|
|
5
|
+
scope :order_by_name, order("name")
|
|
6
|
+
has_many :tags, :order => "name"
|
|
7
|
+
|
|
8
|
+
# tried following but it didn't work
|
|
9
|
+
# has_many :items, :through => :tags
|
|
10
|
+
#
|
|
11
|
+
def items
|
|
12
|
+
tags.collect { |t| t.items }.flatten
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
|
|
4
|
+
class Image < ActiveRecord::Base
|
|
5
|
+
belongs_to :item # :required => false
|
|
6
|
+
belongs_to :tag # :required => false
|
|
7
|
+
|
|
8
|
+
def to_json(*a)
|
|
9
|
+
{ :item => if item then
|
|
10
|
+
item.name
|
|
11
|
+
else
|
|
12
|
+
nil
|
|
13
|
+
end,
|
|
14
|
+
:tag => if tag then
|
|
15
|
+
tag.name
|
|
16
|
+
else
|
|
17
|
+
nil
|
|
18
|
+
end,
|
|
19
|
+
:src => path_from_catalog_root }.to_json(*a)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
|
|
4
|
+
class Tag < ActiveRecord::Base
|
|
5
|
+
belongs_to :category
|
|
6
|
+
|
|
7
|
+
has_many :taggings
|
|
8
|
+
has_many :items, :through => :taggings, :order => "name"
|
|
9
|
+
has_many :images
|
|
10
|
+
|
|
11
|
+
##################################################
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
RE_TAG = /\[([^\]]+)\]/
|
|
15
|
+
|
|
16
|
+
# extracts tags from directory or file name
|
|
17
|
+
def self.extract_tags(dir_or_file_name)
|
|
18
|
+
tags = []
|
|
19
|
+
match_data = dir_or_file_name.match(RE_TAG)
|
|
20
|
+
while match_data
|
|
21
|
+
tags << match_data[1]
|
|
22
|
+
match_data = dir_or_file_name.match(RE_TAG, match_data.end(0))
|
|
23
|
+
end
|
|
24
|
+
tags
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.extract_name(dir_or_file_name)
|
|
28
|
+
dir_or_file_name.gsub(Tag::RE_TAG, '').strip
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
RE_RATING = /^\d$/
|
|
32
|
+
RE_YEAR = /^\d\d\d\d$/
|
|
33
|
+
|
|
34
|
+
MATCHES = [
|
|
35
|
+
[RE_RATING, "rating", proc { |tag_name| tag_name.to_i }],
|
|
36
|
+
[RE_YEAR, "year", proc { |tag_name| tag_name.to_i }]
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# decode standard tags
|
|
41
|
+
#
|
|
42
|
+
def self.match_category(tag_name)
|
|
43
|
+
MATCHES.each do |re, category_name, convert|
|
|
44
|
+
if re.match tag_name
|
|
45
|
+
category = Category.find_or_create_by_name(category_name)
|
|
46
|
+
tag = Tag.find_or_create_by_name_and_category_id(
|
|
47
|
+
convert.call(tag_name),
|
|
48
|
+
category.id
|
|
49
|
+
)
|
|
50
|
+
return category
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end # class Tag
|
|
57
|
+
|
|
58
|
+
end # module SimpleCatalog
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
class CliCat < OptParseCommand::CliMain
|
|
3
|
+
|
|
4
|
+
def self.command
|
|
5
|
+
"simple_cataloger"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.description
|
|
9
|
+
"description"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.version
|
|
13
|
+
SimpleCataloger::VERSION
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# def defaults(options)
|
|
17
|
+
# OpenStruct.new(
|
|
18
|
+
# )
|
|
19
|
+
# end
|
|
20
|
+
|
|
21
|
+
# def option_parser(options)
|
|
22
|
+
# super(options)
|
|
23
|
+
# end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
#
|
|
4
|
+
# Build a catalogue starting from a directory
|
|
5
|
+
#
|
|
6
|
+
class CliServer
|
|
7
|
+
|
|
8
|
+
def self.run
|
|
9
|
+
return self.new.parse_args( ARGV )
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def parse_args( argv )
|
|
13
|
+
options = { :verbose => true, :force => false }
|
|
14
|
+
opts = OptionParser.new
|
|
15
|
+
opts.banner << " <catalog name>\n"
|
|
16
|
+
opts.banner << "launch a webs server to browse the content of <catalog name>\n";
|
|
17
|
+
opts.banner << "\n"
|
|
18
|
+
|
|
19
|
+
opts.on("-h", "--help", "Print this message") do
|
|
20
|
+
puts opts
|
|
21
|
+
return 0
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
opts.on("--version", "show the simple catalog version") do
|
|
25
|
+
puts "simple catalog version #{SimpleCatalog::version}"
|
|
26
|
+
return 0
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
|
30
|
+
options[:verbose] = v
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
rest = opts.parse(argv)
|
|
34
|
+
|
|
35
|
+
if rest.length < 1
|
|
36
|
+
puts "too few arguments"
|
|
37
|
+
puts "-h to print help"
|
|
38
|
+
return 0
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
catalog_name = rest[0]
|
|
42
|
+
cat_opts = {}
|
|
43
|
+
|
|
44
|
+
#
|
|
45
|
+
# option verbose
|
|
46
|
+
#
|
|
47
|
+
|
|
48
|
+
if options.has_key?(:verbose)
|
|
49
|
+
if options[:verbose]
|
|
50
|
+
cat_opts[:verbose_level] = 1
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# main
|
|
56
|
+
#
|
|
57
|
+
|
|
58
|
+
catalog = CatOnSqlite.new(catalog_name)
|
|
59
|
+
WebServer.run! :host => 'localhost', :port => 9091, :catalog => catalog
|
|
60
|
+
|
|
61
|
+
0
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
class CmdCreate < OptParseCommand::Command
|
|
4
|
+
|
|
5
|
+
CliCat.register_command(self)
|
|
6
|
+
|
|
7
|
+
def self.command
|
|
8
|
+
"create"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.description
|
|
12
|
+
"create a catalog"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.usage
|
|
16
|
+
"#{command} <catalog name> <directory>\n" +
|
|
17
|
+
"Create a catalog with name <catalog name> starting from structure of <directory>"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def defaults(options)
|
|
21
|
+
options.force = false
|
|
22
|
+
options
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def option_parser(options)
|
|
26
|
+
parser = super(options)
|
|
27
|
+
parser
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def exec(main, options, rest)
|
|
31
|
+
if rest.length < 2
|
|
32
|
+
puts "too few arguments"
|
|
33
|
+
puts "-h to print help"
|
|
34
|
+
return 0
|
|
35
|
+
end
|
|
36
|
+
catalog_name = rest[0]
|
|
37
|
+
catalog_dirname = rest[1]
|
|
38
|
+
catalog_dirname = File.expand_path(catalog_dirname)
|
|
39
|
+
|
|
40
|
+
if not FileTest.directory?(catalog_dirname)
|
|
41
|
+
puts "'#{catalog_dirname}' not exists or is not a directory"
|
|
42
|
+
return 0
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
catalog = SimpleCataloger::CatOnSqlite.new(catalog_name)
|
|
47
|
+
catalog.create(catalog_dirname)
|
|
48
|
+
catalog.update
|
|
49
|
+
rescue SimpleCataloger::SimpleCatalogerError => e
|
|
50
|
+
puts e.message
|
|
51
|
+
end
|
|
52
|
+
0
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
class CmdList < OptParseCommand::Command
|
|
4
|
+
|
|
5
|
+
CliCat.register_command(self)
|
|
6
|
+
|
|
7
|
+
def self.command
|
|
8
|
+
"list"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.description
|
|
12
|
+
"list items in catalog"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.usage
|
|
16
|
+
"#{command} <catalog name> <directory>\n" +
|
|
17
|
+
"Create a catalog with name <catalog name> starting from structure of <directory>"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def defaults(options)
|
|
21
|
+
options.force = false
|
|
22
|
+
options
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def option_parser(options)
|
|
26
|
+
parser = super(options)
|
|
27
|
+
parser
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def exec(main, options, rest)
|
|
31
|
+
if rest.length < 1
|
|
32
|
+
puts "too few arguments"
|
|
33
|
+
puts "-h to print help"
|
|
34
|
+
return 0
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
catalog_name = rest[0]
|
|
38
|
+
cat_opts = {}
|
|
39
|
+
|
|
40
|
+
# begin
|
|
41
|
+
catalog = CatOnSqlite.new(catalog_name).open
|
|
42
|
+
puts "contains of '#{catalog.name}'"
|
|
43
|
+
puts "categories"
|
|
44
|
+
Category.all.each do |c|
|
|
45
|
+
puts "\t #{c.name}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Category.find_by_name("Actor").items.each do |i|
|
|
49
|
+
# pp i
|
|
50
|
+
# end
|
|
51
|
+
|
|
52
|
+
#
|
|
53
|
+
# Tags
|
|
54
|
+
#
|
|
55
|
+
puts "tags"
|
|
56
|
+
Tag.all.each do |t|
|
|
57
|
+
puts "\t #{t.name} (category: #{t.category.name})"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
puts "items"
|
|
61
|
+
Item.all.each do |f|
|
|
62
|
+
puts "\t #{f.name}"
|
|
63
|
+
end
|
|
64
|
+
# rescue e
|
|
65
|
+
# puts e.message
|
|
66
|
+
# end
|
|
67
|
+
|
|
68
|
+
0
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|