logaling-command 0.2.0 → 0.2.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.
- data/CHANGES +3 -0
- data/lib/logaling/command/application.rb +33 -31
- data/lib/logaling/command/version.rb +1 -1
- data/lib/logaling/glossary.rb +18 -6
- data/lib/logaling/glossary_db.rb +17 -10
- data/lib/logaling/glossary_sources/base.rb +6 -18
- data/lib/logaling/glossary_sources/glossary_csv_source.rb +1 -1
- data/lib/logaling/glossary_sources/glossary_tsv_source.rb +1 -1
- data/lib/logaling/glossary_sources/glossary_yaml_source.rb +6 -6
- data/lib/logaling/project.rb +66 -27
- data/lib/logaling/repository.rb +37 -15
- data/spec/logaling/command_spec.rb +35 -2
- data/spec/logaling/glossary_db_spec.rb +75 -0
- data/spec/logaling/glossary_spec.rb +12 -9
- data/spec/logaling/repository_spec.rb +48 -7
- metadata +4 -2
data/CHANGES
CHANGED
@@ -52,6 +52,7 @@ module Logaling::Command
|
|
52
52
|
'-n' => :new,
|
53
53
|
'-r' => :register,
|
54
54
|
'-U' => :unregister,
|
55
|
+
'-I' => :index,
|
55
56
|
'-L' => :list,
|
56
57
|
'-s' => :show,
|
57
58
|
'-v' => :version,
|
@@ -80,7 +81,7 @@ module Logaling::Command
|
|
80
81
|
@dotfile_path = options["logaling-config"] || Logaling::Project.find_dotfile
|
81
82
|
@project_config_path = File.join(@dotfile_path, 'config')
|
82
83
|
@config.load(@project_config_path)
|
83
|
-
|
84
|
+
@repository.register(@dotfile_path, @config.glossary)
|
84
85
|
end
|
85
86
|
say "Successfully created #{logaling_config_path}"
|
86
87
|
else
|
@@ -89,7 +90,7 @@ module Logaling::Command
|
|
89
90
|
else
|
90
91
|
raise Logaling::CommandFailed, "[TARGET-LANGUAGE] is required when you use '--personal'" unless target_language
|
91
92
|
personal_project = @repository.create_personal_project(project_name, source_language, target_language)
|
92
|
-
say "Successfully created #{personal_project.
|
93
|
+
say "Successfully created #{personal_project.absolute_path}"
|
93
94
|
end
|
94
95
|
rescue Logaling::CommandFailed => e
|
95
96
|
say e.message
|
@@ -114,10 +115,8 @@ module Logaling::Command
|
|
114
115
|
end
|
115
116
|
glossary = Logaling::Glossary.new(args[0], args[2], args[3])
|
116
117
|
@repository.import_tmx(Logaling::ExternalGlossary.get(external_glossary), glossary, url)
|
117
|
-
@repository.index
|
118
118
|
else
|
119
119
|
@repository.import(Logaling::ExternalGlossary.get(external_glossary))
|
120
|
-
@repository.index
|
121
120
|
end
|
122
121
|
end
|
123
122
|
rescue Logaling::CommandFailed => e
|
@@ -135,7 +134,7 @@ module Logaling::Command
|
|
135
134
|
@config.check_required_option("glossary" => "Do 'loga register' at project directory.")
|
136
135
|
raise Logaling::CommandFailed, "Try 'loga new' first." unless File.exist?(@dotfile_path)
|
137
136
|
|
138
|
-
|
137
|
+
@repository.register(@dotfile_path, @config.glossary)
|
139
138
|
say "#{@config.glossary} is now registered to logaling."
|
140
139
|
rescue Logaling::CommandFailed => e
|
141
140
|
say e.message
|
@@ -150,7 +149,6 @@ module Logaling::Command
|
|
150
149
|
|
151
150
|
project = @repository.find_project(@config.glossary)
|
152
151
|
@repository.unregister(project)
|
153
|
-
@repository.index
|
154
152
|
say "#{@config.glossary} is now unregistered."
|
155
153
|
rescue Logaling::CommandFailed => e
|
156
154
|
say e.message
|
@@ -158,25 +156,35 @@ module Logaling::Command
|
|
158
156
|
say "#{@config.glossary} is not yet registered."
|
159
157
|
end
|
160
158
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
159
|
+
desc 'index', 'Index glossaries'
|
160
|
+
def index
|
161
|
+
check_logaling_home_exists
|
162
|
+
|
163
|
+
@repository.index
|
164
|
+
say 'Complete index.'
|
165
|
+
rescue Logaling::CommandFailed => e
|
166
|
+
say e.message
|
167
|
+
end
|
168
|
+
|
169
|
+
desc 'config [KEY] [VALUE] [--global(optional)]', 'Set config.'
|
170
|
+
method_option "global", type: :boolean, default: false
|
171
|
+
def config(key, value)
|
172
|
+
if options["global"]
|
173
|
+
unless File.exist?(@logaling_home)
|
174
|
+
FileUtils.mkdir_p(@logaling_home) rescue raise Logaling::CommandFailed, "Input existing directory as logaling-home."
|
175
|
+
end
|
176
|
+
config_path = File.join(@logaling_home, "config")
|
177
|
+
else
|
178
|
+
raise Logaling::CommandFailed, "Can't found .logaling" unless @project_config_path
|
179
|
+
config_path = @project_config_path
|
180
|
+
end
|
181
|
+
config = Logaling::Config.load(config_path)
|
182
|
+
config.add(key, value)
|
183
|
+
config.save(config_path)
|
184
|
+
say "Successfully set config."
|
185
|
+
rescue Logaling::CommandFailed => e
|
186
|
+
say e.message
|
187
|
+
end
|
180
188
|
|
181
189
|
desc 'add [SOURCE TERM] [TARGET TERM] [NOTE(optional)]', 'Add term to glossary.'
|
182
190
|
def add(source_term, target_term, note='')
|
@@ -265,7 +273,6 @@ module Logaling::Command
|
|
265
273
|
method_option "fixed", type: :boolean, default: false
|
266
274
|
def lookup(source_term)
|
267
275
|
check_logaling_home_exists
|
268
|
-
@repository.index
|
269
276
|
if @config.glossary
|
270
277
|
project = @repository.find_project(@config.glossary)
|
271
278
|
raise Logaling::ProjectNotFound unless project
|
@@ -408,10 +415,5 @@ module Logaling::Command
|
|
408
415
|
raise Logaling::CommandFailed, "Do 'loga import tmx <glossary name> <url or path>'"
|
409
416
|
end
|
410
417
|
end
|
411
|
-
|
412
|
-
def register_and_index
|
413
|
-
@repository.register(@dotfile_path, @config.glossary)
|
414
|
-
@repository.index
|
415
|
-
end
|
416
418
|
end
|
417
419
|
end
|
data/lib/logaling/glossary.rb
CHANGED
@@ -19,7 +19,7 @@ module Logaling
|
|
19
19
|
SUPPORTED_FILE_TYPE = %w(yml tsv csv)
|
20
20
|
SUPPORTED_ANNOTATION = %w(wip)
|
21
21
|
|
22
|
-
attr_reader :name, :source_language, :target_language
|
22
|
+
attr_reader :name, :source_language, :target_language, :project
|
23
23
|
|
24
24
|
def initialize(name, source_language, target_language, project=nil)
|
25
25
|
@name = name
|
@@ -56,6 +56,7 @@ module Logaling
|
|
56
56
|
def add(source_term, target_term, note)
|
57
57
|
raise Logaling::TermError if bilingual_pair_exists?(source_term, target_term)
|
58
58
|
glossary_source.add(source_term, target_term, note)
|
59
|
+
index!
|
59
60
|
end
|
60
61
|
|
61
62
|
def update(source_term, target_term, new_target_term, note)
|
@@ -64,25 +65,28 @@ module Logaling
|
|
64
65
|
end
|
65
66
|
|
66
67
|
glossary_source.update(source_term, target_term, new_target_term, note)
|
68
|
+
index!
|
67
69
|
end
|
68
70
|
|
69
71
|
def delete(source_term, target_term)
|
70
72
|
raise Logaling::TermError unless bilingual_pair_exists?(source_term, target_term)
|
71
73
|
glossary_source.delete(source_term, target_term)
|
74
|
+
index!
|
72
75
|
end
|
73
76
|
|
74
77
|
def delete_all(source_term, force=false)
|
75
78
|
glossary_source.delete_all(source_term, force)
|
79
|
+
index!
|
76
80
|
end
|
77
81
|
|
78
82
|
def glossary_source
|
79
83
|
if @glossary_source
|
80
84
|
@glossary_source
|
81
85
|
else
|
86
|
+
FileUtils.mkdir_p(@project.source_directory_path)
|
87
|
+
|
82
88
|
file_name = [@name, @source_language, @target_language, 'yml'].join('.')
|
83
|
-
|
84
|
-
FileUtils.mkdir_p(source_dir)
|
85
|
-
source_path = File.join(source_dir, file_name)
|
89
|
+
source_path = @project.relative_path(file_name)
|
86
90
|
@glossary_source = Logaling::GlossarySource.create(source_path, self)
|
87
91
|
end
|
88
92
|
end
|
@@ -122,13 +126,21 @@ module Logaling
|
|
122
126
|
end
|
123
127
|
end
|
124
128
|
|
129
|
+
def same?(glossary)
|
130
|
+
name == glossary.name
|
131
|
+
end
|
132
|
+
|
125
133
|
private
|
126
134
|
def glossary_sources
|
127
135
|
glob_condition = SUPPORTED_FILE_TYPE.map do |type|
|
128
136
|
file_name = [self.to_s, type].join('.')
|
129
|
-
File.join(@project.
|
137
|
+
File.join(@project.source_directory_path, file_name)
|
138
|
+
end
|
139
|
+
Dir.glob(glob_condition).map do |source_path|
|
140
|
+
file_name = File.basename(source_path)
|
141
|
+
source_path = @project.relative_path(file_name)
|
142
|
+
GlossarySource.create(source_path, self)
|
130
143
|
end
|
131
|
-
Dir.glob(glob_condition).map {|source_path| GlossarySource.create(source_path, self)}
|
132
144
|
end
|
133
145
|
end
|
134
146
|
end
|
data/lib/logaling/glossary_db.rb
CHANGED
@@ -20,7 +20,7 @@ require 'cgi'
|
|
20
20
|
|
21
21
|
module Logaling
|
22
22
|
class GlossaryDB
|
23
|
-
VERSION =
|
23
|
+
VERSION = 3
|
24
24
|
|
25
25
|
def self.open(base_path, encoding, &blk)
|
26
26
|
blk ? GlossaryDB.new.open(base_path, encoding, &blk) : GlossaryDB.new.open(base_path, encoding)
|
@@ -229,10 +229,11 @@ module Logaling
|
|
229
229
|
def get_all_glossary_sources
|
230
230
|
source_paths = Groonga["glossary_sources"].sort([
|
231
231
|
{:key=>"_key", :order=>'ascending'}
|
232
|
-
]).map{|record| record.key}
|
233
|
-
source_paths.map do |source_path|
|
232
|
+
]).map{|record| [record.key, record.project_type]}
|
233
|
+
source_paths.map do |source_path, project_type|
|
234
234
|
glossary_name, source_language, target_language = File.basename(source_path).split(/\./)
|
235
|
-
|
235
|
+
project = Logaling.const_get(project_type).new(Logaling::Project.find_path(source_path))
|
236
|
+
glossary = Glossary.new(glossary_name, source_language, target_language, project)
|
236
237
|
GlossarySource.create(source_path, glossary)
|
237
238
|
end
|
238
239
|
end
|
@@ -262,7 +263,10 @@ module Logaling
|
|
262
263
|
end
|
263
264
|
|
264
265
|
def add_glossary_source(glossary_source)
|
265
|
-
Groonga["glossary_sources"].add(
|
266
|
+
Groonga["glossary_sources"].add(
|
267
|
+
glossary_source.source_path, {
|
268
|
+
:indexed_at => glossary_source.mtime,
|
269
|
+
:project_type => glossary_source.glossary.project.type})
|
266
270
|
end
|
267
271
|
|
268
272
|
def delete_glossary(glossary_name)
|
@@ -341,6 +345,7 @@ module Logaling
|
|
341
345
|
:type => :hash,
|
342
346
|
:key_type => "ShortText") do |table|
|
343
347
|
table.time("indexed_at")
|
348
|
+
table.short_text("project_type")
|
344
349
|
end
|
345
350
|
|
346
351
|
schema.create_table("glossaries",
|
@@ -441,16 +446,18 @@ module Logaling
|
|
441
446
|
end
|
442
447
|
|
443
448
|
def glossary_source_of_the_same_project_exist?(glossary_source)
|
449
|
+
project = glossary_source.glossary.project
|
444
450
|
glossary_source_num = 0
|
445
451
|
get_all_glossary_sources.each do |glossary_source_taken|
|
446
|
-
|
447
|
-
|
452
|
+
project_taken = glossary_source_taken.glossary.project
|
453
|
+
if project.personal? && project_taken.personal?
|
454
|
+
if glossary_source.glossary.same?(glossary_source_taken.glossary)
|
448
455
|
glossary_source_num = 1
|
449
456
|
break
|
450
457
|
end
|
451
|
-
elsif
|
452
|
-
if
|
453
|
-
glossary_source.
|
458
|
+
elsif project.normal_project? && project_taken.normal_project?
|
459
|
+
if project.same?(project_taken) &&
|
460
|
+
glossary_source.glossary.same?(glossary_source_taken.glossary)
|
454
461
|
glossary_source_num = 1
|
455
462
|
break
|
456
463
|
end
|
@@ -20,14 +20,14 @@ module Logaling
|
|
20
20
|
class Base
|
21
21
|
attr_reader :source_path, :glossary
|
22
22
|
|
23
|
-
def initialize(
|
24
|
-
@source_path =
|
23
|
+
def initialize(relative_source_path, glossary)
|
24
|
+
@source_path = relative_source_path
|
25
25
|
@glossary = glossary
|
26
26
|
end
|
27
27
|
|
28
28
|
def eql?(other)
|
29
29
|
return false unless self.class == other.class
|
30
|
-
|
30
|
+
source_path == other.source_path
|
31
31
|
end
|
32
32
|
|
33
33
|
def hash
|
@@ -35,23 +35,11 @@ module Logaling
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def mtime
|
38
|
-
File.mtime(
|
38
|
+
File.mtime(absolute_path)
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
@source_path
|
43
|
-
end
|
44
|
-
|
45
|
-
def belongs_to_project?
|
46
|
-
@source_path =~ /.+\/projects\/.+/ ? true : false
|
47
|
-
end
|
48
|
-
|
49
|
-
def glossary_name
|
50
|
-
File.basename(@source_path).split(".", 2)[0]
|
51
|
-
end
|
52
|
-
|
53
|
-
def project_name
|
54
|
-
@source_path =~ /.+\/projects\/([^\/]+).+/ ? $1 : nil
|
41
|
+
def absolute_path
|
42
|
+
@glossary.project.repository.expand_path(@source_path)
|
55
43
|
end
|
56
44
|
end
|
57
45
|
end
|
@@ -22,7 +22,7 @@ module Logaling::GlossarySources
|
|
22
22
|
class GlossaryCsvSource < Base
|
23
23
|
def load
|
24
24
|
glossary_source = []
|
25
|
-
CSV.open(
|
25
|
+
CSV.open(absolute_path, "r:utf-8", {:col_sep => ','}) do |csv|
|
26
26
|
csv.each do |row|
|
27
27
|
glossary_source << {"source_term" => row[0], "target_term" => row[1], "note" => ""} if row.size >= 2
|
28
28
|
end
|
@@ -22,7 +22,7 @@ module Logaling::GlossarySources
|
|
22
22
|
class GlossaryTsvSource < Base
|
23
23
|
def load
|
24
24
|
glossary_source = []
|
25
|
-
CSV.open(
|
25
|
+
CSV.open(absolute_path, "r:utf-8", {:col_sep => "\t"}) do |tsv|
|
26
26
|
tsv.each do |row|
|
27
27
|
glossary_source << {"source_term" => row[0], "target_term" => row[1], "note" => ""} if row.size >= 2
|
28
28
|
end
|
@@ -28,13 +28,13 @@ require "fileutils"
|
|
28
28
|
module Logaling::GlossarySources
|
29
29
|
class GlossaryYamlSource < Base
|
30
30
|
def load
|
31
|
-
YAML::load_file(
|
31
|
+
YAML::load_file(absolute_path) || []
|
32
32
|
rescue TypeError
|
33
33
|
[]
|
34
34
|
end
|
35
35
|
|
36
36
|
def add(source_term, target_term, note)
|
37
|
-
initialize_source unless File.exist?(
|
37
|
+
initialize_source unless File.exist?(absolute_path)
|
38
38
|
|
39
39
|
glossary_source = self.load
|
40
40
|
glossary_source << build_term(source_term, target_term, note)
|
@@ -44,7 +44,7 @@ module Logaling::GlossarySources
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def update(source_term, target_term, new_target_term, note)
|
47
|
-
raise Logaling::GlossaryNotFound unless File.exist?(
|
47
|
+
raise Logaling::GlossaryNotFound unless File.exist?(absolute_path)
|
48
48
|
|
49
49
|
glossary_source = self.load
|
50
50
|
target_index = find_term_index(glossary_source, source_term, target_term)
|
@@ -57,7 +57,7 @@ module Logaling::GlossarySources
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def delete(source_term, target_term)
|
60
|
-
raise Logaling::GlossaryNotFound unless File.exist?(
|
60
|
+
raise Logaling::GlossaryNotFound unless File.exist?(absolute_path)
|
61
61
|
|
62
62
|
glossary_source = self.load
|
63
63
|
target_index = find_term_index(glossary_source, source_term, target_term)
|
@@ -70,7 +70,7 @@ module Logaling::GlossarySources
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def delete_all(source_term, force=false)
|
73
|
-
raise Logaling::GlossaryNotFound unless File.exist?(
|
73
|
+
raise Logaling::GlossaryNotFound unless File.exist?(absolute_path)
|
74
74
|
|
75
75
|
glossary_source = self.load
|
76
76
|
delete_candidates = target_terms(glossary_source, source_term)
|
@@ -121,7 +121,7 @@ module Logaling::GlossarySources
|
|
121
121
|
end
|
122
122
|
|
123
123
|
def dump_glossary_source(glossary_source)
|
124
|
-
File.open(
|
124
|
+
File.open(absolute_path, "w") do |f|
|
125
125
|
f << YAML.dump(glossary_source)
|
126
126
|
end
|
127
127
|
end
|
data/lib/logaling/project.rb
CHANGED
@@ -33,11 +33,19 @@ module Logaling
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
def find_path(source_path)
|
38
|
+
if source_path =~ /(.+\/projects\/[^\/]+).+/
|
39
|
+
$1
|
40
|
+
else
|
41
|
+
source_path
|
42
|
+
end
|
43
|
+
end
|
36
44
|
end
|
37
45
|
attr_reader :path, :repository
|
38
46
|
|
39
|
-
def initialize(
|
40
|
-
@path =
|
47
|
+
def initialize(relative_path, repository=nil)
|
48
|
+
@path = relative_path
|
41
49
|
@repository = repository
|
42
50
|
end
|
43
51
|
|
@@ -50,7 +58,14 @@ module Logaling
|
|
50
58
|
end
|
51
59
|
|
52
60
|
def glossary_source_path
|
53
|
-
File.join(@path, "glossary")
|
61
|
+
File.join(@repository.expand_path(@path), "glossary")
|
62
|
+
end
|
63
|
+
alias_method :source_directory_path, :glossary_source_path
|
64
|
+
|
65
|
+
# relative_path_from_logaling_home みたいな名前でGlossarySourceにある方が良いかも...
|
66
|
+
def relative_path(glossary_source_file_name)
|
67
|
+
source_path = File.join(source_directory_path, glossary_source_file_name)
|
68
|
+
@repository.relative_path(source_path)
|
54
69
|
end
|
55
70
|
|
56
71
|
def glossary_db_path
|
@@ -66,8 +81,9 @@ module Logaling
|
|
66
81
|
end
|
67
82
|
|
68
83
|
def glossary_sources
|
69
|
-
all_glossary_source_path.map do |
|
70
|
-
name, source_language, target_language, type = File.basename(
|
84
|
+
all_glossary_source_path.map do |source_path_full|
|
85
|
+
name, source_language, target_language, type = File.basename(source_path_full).split(/\./)
|
86
|
+
source_path = @repository.relative_path(source_path_full)
|
71
87
|
GlossarySource.create(source_path, glossary(source_language, target_language))
|
72
88
|
end
|
73
89
|
end
|
@@ -80,13 +96,29 @@ module Logaling
|
|
80
96
|
false
|
81
97
|
end
|
82
98
|
|
99
|
+
def personal?
|
100
|
+
false
|
101
|
+
end
|
102
|
+
|
103
|
+
def normal_project?
|
104
|
+
true
|
105
|
+
end
|
106
|
+
|
107
|
+
def type
|
108
|
+
self.class.to_s.sub('Logaling::', '')
|
109
|
+
end
|
110
|
+
|
111
|
+
def same?(project)
|
112
|
+
name == project.name
|
113
|
+
end
|
114
|
+
|
83
115
|
private
|
84
116
|
def all_glossary_source_path
|
85
117
|
Dir.glob(File.join(glossary_source_path, "*"))
|
86
118
|
end
|
87
119
|
end
|
88
120
|
|
89
|
-
class
|
121
|
+
class FileBasedProject < Project
|
90
122
|
def name
|
91
123
|
File.basename(@path).split(/\./).first
|
92
124
|
end
|
@@ -96,49 +128,56 @@ module Logaling
|
|
96
128
|
[GlossarySource.create(@path, glossary(source_language, target_language))]
|
97
129
|
end
|
98
130
|
|
99
|
-
def
|
100
|
-
File.
|
131
|
+
def has_glossary?(source_language, target_language)
|
132
|
+
glossary_source_language, glossary_target_language = File.basename(@path).split(/\./)[1..2]
|
133
|
+
glossary_source_language == source_language && glossary_target_language == target_language
|
101
134
|
end
|
102
135
|
|
136
|
+
def absolute_path
|
137
|
+
@repository.expand_path(@path)
|
138
|
+
end
|
139
|
+
alias_method :glossary_source_path, :absolute_path
|
140
|
+
|
141
|
+
def normal_project?
|
142
|
+
false
|
143
|
+
end
|
144
|
+
|
145
|
+
def source_directory_path
|
146
|
+
File.dirname(glossary_source_path)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class ImportedProject < FileBasedProject
|
103
151
|
def imported?
|
104
152
|
true
|
105
153
|
end
|
106
154
|
end
|
107
155
|
|
108
|
-
class PersonalProject <
|
156
|
+
class PersonalProject < FileBasedProject
|
109
157
|
class << self
|
110
|
-
def create(
|
158
|
+
def create(relative_root_path, glossary_name, source_language, target_language, repository=nil)
|
111
159
|
project_name = [glossary_name, source_language, target_language, 'yml'].join('.')
|
112
|
-
project_path = File.join(
|
160
|
+
project_path = File.join(relative_root_path, project_name)
|
113
161
|
project = PersonalProject.new(project_path, repository)
|
114
162
|
project.initialize_glossary(source_language, target_language)
|
115
163
|
project
|
116
164
|
end
|
117
165
|
|
118
|
-
def remove(
|
166
|
+
def remove(relative_root_path, glossary_name, source_language, target_language, repository)
|
119
167
|
project_name = [glossary_name, source_language, target_language, 'yml'].join('.')
|
120
|
-
project_path = File.join(
|
168
|
+
project_path = File.join(relative_root_path, project_name)
|
121
169
|
project = PersonalProject.new(project_path, repository)
|
122
|
-
FileUtils.rm_rf(project_path, :secure => true)
|
170
|
+
FileUtils.rm_rf(repository.expand_path(project_path), :secure => true)
|
123
171
|
project
|
124
172
|
end
|
125
173
|
end
|
126
174
|
|
127
|
-
def name
|
128
|
-
File.basename(@path).split(/\./).first
|
129
|
-
end
|
130
|
-
|
131
|
-
def glossary_sources
|
132
|
-
name, source_language, target_language, type = File.basename(@path).split(/\./)
|
133
|
-
[GlossarySource.create(@path, glossary(source_language, target_language))]
|
134
|
-
end
|
135
|
-
|
136
|
-
def glossary_source_path
|
137
|
-
File.dirname(@path)
|
138
|
-
end
|
139
|
-
|
140
175
|
def initialize_glossary(source_language, target_language)
|
141
176
|
glossary(source_language, target_language).initialize_glossary_source
|
142
177
|
end
|
178
|
+
|
179
|
+
def personal?
|
180
|
+
true
|
181
|
+
end
|
143
182
|
end
|
144
183
|
end
|
data/lib/logaling/repository.rb
CHANGED
@@ -33,6 +33,7 @@ module Logaling
|
|
33
33
|
else
|
34
34
|
raise Logaling::GlossaryAlreadyRegistered, register_name
|
35
35
|
end
|
36
|
+
index
|
36
37
|
rescue Logaling::GlossaryAlreadyRegistered => e
|
37
38
|
raise e
|
38
39
|
rescue
|
@@ -41,21 +42,25 @@ module Logaling
|
|
41
42
|
|
42
43
|
def unregister(project)
|
43
44
|
raise Logaling::ProjectNotFound unless project
|
44
|
-
FileUtils.rm_rf(project.path, :secure => true)
|
45
|
+
FileUtils.rm_rf(expand_path(project.path), :secure => true)
|
46
|
+
index
|
45
47
|
end
|
46
48
|
|
47
49
|
def create_personal_project(project_name, source_language, target_language)
|
48
50
|
if glossary_exists?(project_name, source_language, target_language)
|
49
51
|
raise Logaling::GlossaryAlreadyRegistered, "The glossary '#{project_name}' already exists."
|
50
52
|
end
|
51
|
-
|
53
|
+
personal_project_path = relative_path(personal_glossary_root_path)
|
54
|
+
PersonalProject.create(personal_project_path, project_name, source_language, target_language, self)
|
52
55
|
end
|
53
56
|
|
54
57
|
def remove_personal_project(project_name, source_language, target_language)
|
55
58
|
unless glossary_exists?(project_name, source_language, target_language)
|
56
59
|
raise Logaling::GlossaryNotFound, "The glossary '#{project_name}' not found."
|
57
60
|
end
|
58
|
-
|
61
|
+
personal_project_path = relative_path(personal_glossary_root_path)
|
62
|
+
PersonalProject.remove(personal_project_path, project_name, source_language, target_language, self)
|
63
|
+
index
|
59
64
|
rescue Logaling::GlossaryNotFound => e
|
60
65
|
raise e
|
61
66
|
rescue
|
@@ -67,6 +72,7 @@ module Logaling
|
|
67
72
|
Dir.chdir(cache_path) do
|
68
73
|
glossary_source.import
|
69
74
|
end
|
75
|
+
index
|
70
76
|
rescue
|
71
77
|
raise Logaling::CommandFailed, "Failed import #{glossary_source.class.name} to #{cache_path}."
|
72
78
|
end
|
@@ -76,6 +82,7 @@ module Logaling
|
|
76
82
|
Dir.chdir(cache_path) do
|
77
83
|
glossary_source.import(glossary, url)
|
78
84
|
end
|
85
|
+
index
|
79
86
|
rescue Logaling::GlossaryNotFound => e
|
80
87
|
raise e
|
81
88
|
rescue
|
@@ -105,13 +112,13 @@ module Logaling
|
|
105
112
|
|
106
113
|
def projects
|
107
114
|
projects = registered_project_paths.map do |project_path|
|
108
|
-
Logaling::Project.new(project_path, self)
|
115
|
+
Logaling::Project.new(relative_path(project_path), self)
|
109
116
|
end
|
110
117
|
projects += personal_glossary_paths.map do |personal_glossary_path|
|
111
|
-
Logaling::PersonalProject.new(personal_glossary_path, self)
|
118
|
+
Logaling::PersonalProject.new(relative_path(personal_glossary_path), self)
|
112
119
|
end
|
113
120
|
projects += imported_glossary_paths.map do |imported_project_path|
|
114
|
-
Logaling::ImportedProject.new(imported_project_path, self)
|
121
|
+
Logaling::ImportedProject.new(relative_path(imported_project_path), self)
|
115
122
|
end
|
116
123
|
projects.sort_by(&:path)
|
117
124
|
end
|
@@ -140,11 +147,6 @@ module Logaling
|
|
140
147
|
[registered_project_paths, imported_glossary_paths].map(&:size).inject(&:+)
|
141
148
|
end
|
142
149
|
|
143
|
-
def config_path
|
144
|
-
path = File.join(@path, "config")
|
145
|
-
File.exist?(path) ? path : nil
|
146
|
-
end
|
147
|
-
|
148
150
|
def find_project(project_name)
|
149
151
|
projects.detect {|project| project.name == project_name }
|
150
152
|
end
|
@@ -156,21 +158,41 @@ module Logaling
|
|
156
158
|
project ? project.glossary(source_language, target_language) : nil
|
157
159
|
end
|
158
160
|
|
161
|
+
def config_path
|
162
|
+
path = File.join(logaling_home, "config")
|
163
|
+
File.exist?(path) ? path : nil
|
164
|
+
end
|
165
|
+
|
159
166
|
def logaling_db_home
|
160
|
-
File.join(
|
167
|
+
File.join(logaling_home, "db")
|
168
|
+
end
|
169
|
+
|
170
|
+
def expand_path(relative_path)
|
171
|
+
File.expand_path(File.join(logaling_home, relative_path))
|
172
|
+
end
|
173
|
+
|
174
|
+
def relative_path(full_path)
|
175
|
+
require 'pathname'
|
176
|
+
path = Pathname.new(full_path)
|
177
|
+
base = Pathname.new(logaling_home)
|
178
|
+
path.relative_path_from(base).to_s
|
161
179
|
end
|
162
180
|
|
163
181
|
private
|
182
|
+
def logaling_home
|
183
|
+
@path
|
184
|
+
end
|
185
|
+
|
164
186
|
def logaling_projects_path
|
165
|
-
File.join(
|
187
|
+
File.join(logaling_home, "projects")
|
166
188
|
end
|
167
189
|
|
168
190
|
def personal_glossary_root_path
|
169
|
-
File.join(
|
191
|
+
File.join(logaling_home, "personal")
|
170
192
|
end
|
171
193
|
|
172
194
|
def cache_path
|
173
|
-
File.join(
|
195
|
+
File.join(logaling_home, "cache")
|
174
196
|
end
|
175
197
|
|
176
198
|
def registered_project_paths
|
@@ -25,7 +25,7 @@ describe Logaling::Command::Application do
|
|
25
25
|
let(:target_project_path) { File.join(logaling_home, "projects", "spec") }
|
26
26
|
let(:repository) { Logaling::Repository.new(logaling_home) }
|
27
27
|
let(:glossary) { repository.find_project('spec').glossary('en', 'ja') }
|
28
|
-
let(:glossary_source_path) { glossary.glossary_source.
|
28
|
+
let(:glossary_source_path) { glossary.glossary_source.absolute_path }
|
29
29
|
|
30
30
|
before do
|
31
31
|
FileUtils.rm_rf(File.join(logaling_home, 'projects', 'spec'))
|
@@ -83,7 +83,6 @@ describe Logaling::Command::Application do
|
|
83
83
|
|
84
84
|
describe '#register' do
|
85
85
|
before do
|
86
|
-
sleep(1)
|
87
86
|
@n_projects = Dir[File.join(logaling_home, "projects", "*")].size
|
88
87
|
end
|
89
88
|
|
@@ -178,6 +177,40 @@ describe Logaling::Command::Application do
|
|
178
177
|
end
|
179
178
|
end
|
180
179
|
|
180
|
+
describe '#index' do
|
181
|
+
before do
|
182
|
+
command.options = base_options.merge("output" => "terminal", "no-pager" => true)
|
183
|
+
command.new('spec', 'en', 'ja')
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'when new term added' do
|
187
|
+
before do
|
188
|
+
command.add("spec", "スペック", "備考")
|
189
|
+
command.index
|
190
|
+
@stdout = capture(:stdout) { command.lookup("spec") }
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should be indexed' do
|
194
|
+
@stdout.should include "spec"
|
195
|
+
@stdout.should include "スペック"
|
196
|
+
@stdout.should include "# 備考"
|
197
|
+
@stdout.should_not include "now index spec..."
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'when logaling_home does not exists' do
|
202
|
+
before do
|
203
|
+
command.add("spec", "スペック", "備考")
|
204
|
+
FileUtils.rm_rf(logaling_home)
|
205
|
+
@stdout = capture(:stdout) { command.index }
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should print message and failed index' do
|
209
|
+
@stdout.should include "Input existing directory as logaling-home."
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
181
214
|
describe '#config' do
|
182
215
|
let(:project_config) { File.join(logaling_config, 'config') }
|
183
216
|
let(:global_config) { File.join(logaling_home, 'config') }
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Miho SUZUKI
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
19
|
+
#require "fileutils"
|
20
|
+
|
21
|
+
module Logaling
|
22
|
+
describe Project do
|
23
|
+
let(:logaling_home) { @logaling_home }
|
24
|
+
let(:logaling_db_home) { File.join(@logaling_home, 'db') }
|
25
|
+
let(:logaling_config) { File.join(File.dirname(__FILE__), "..", "tmp", ".logaling") }
|
26
|
+
let(:base_options) { {"glossary"=>"spec", "source-language"=>"en", "target-language"=>"ja", "logaling-config" => logaling_config} }
|
27
|
+
let(:command) { Logaling::Command::Application.new([], base_options) }
|
28
|
+
let(:project_path) { File.join(logaling_home, 'projects') }
|
29
|
+
let(:cache_path) { File.join(logaling_home, 'cache') }
|
30
|
+
let(:personal_path) { File.join(logaling_home, 'personal') }
|
31
|
+
|
32
|
+
before do
|
33
|
+
FileUtils.rm_rf(File.join(project_path, 'spec'))
|
34
|
+
FileUtils.mkdir_p(cache_path)
|
35
|
+
FileUtils.mkdir_p(personal_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#get_all_glossary_sources" do
|
39
|
+
before do
|
40
|
+
command.new('spec', 'en', 'fr')
|
41
|
+
command.add('spec', 'スペック')
|
42
|
+
command.copy('spec', 'en', 'fr', 'personal_spec', 'en', 'ja')
|
43
|
+
csv_path = File.join(cache_path, 'imported_spec.en.ja.csv')
|
44
|
+
FileUtils.touch(csv_path)
|
45
|
+
File.open(csv_path, "w"){|f| f.puts "test_logaling,テストろがりん"}
|
46
|
+
command.index
|
47
|
+
|
48
|
+
Logaling::GlossaryDB.open(logaling_db_home, "utf8") do |db|
|
49
|
+
db.recreate_table
|
50
|
+
@glossary_sources = db.get_all_glossary_sources
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should be set project correctly" do
|
55
|
+
methods = ['personal?', 'normal_project?', 'imported?']
|
56
|
+
methods.each do |method|
|
57
|
+
project_get = nil
|
58
|
+
@glossary_sources.each do |glossary_source|
|
59
|
+
if glossary_source.glossary.project.send(method)
|
60
|
+
project_get = glossary_source.glossary.project
|
61
|
+
end
|
62
|
+
end
|
63
|
+
project_get.should_not be nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
after do
|
69
|
+
FileUtils.rm_rf(File.join(project_path, 'spec'))
|
70
|
+
FileUtils.rm_rf(cache_path)
|
71
|
+
FileUtils.rm_rf(personal_path)
|
72
|
+
FileUtils.rm_rf(logaling_config)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -21,13 +21,20 @@ require "fileutils"
|
|
21
21
|
module Logaling
|
22
22
|
describe Glossary do
|
23
23
|
let(:logaling_home) { @logaling_home }
|
24
|
+
let(:logaling_db_home) { File.join(logaling_home, 'db') }
|
24
25
|
let(:repository) { Logaling::Repository.new(logaling_home) }
|
25
26
|
let(:glossary) { repository.find_project('spec').glossary('en', 'ja') }
|
26
27
|
let(:glossary_source_path) { glossary.glossary_source.source_path }
|
28
|
+
let(:glossary_source_absolute_path) { glossary.glossary_source.absolute_path }
|
27
29
|
|
28
30
|
before do
|
31
|
+
# clear directories and files
|
29
32
|
FileUtils.rm_rf(File.join(logaling_home, 'projects', 'spec'), :secure => true)
|
30
|
-
FileUtils.mkdir_p(File.join(logaling_home, 'projects', 'spec'))
|
33
|
+
FileUtils.mkdir_p(File.join(logaling_home, 'projects', 'spec', 'glossary'))
|
34
|
+
FileUtils.touch(glossary_source_absolute_path)
|
35
|
+
File.open(glossary_source_absolute_path, "w") {|f| f << YAML.dump([]) }
|
36
|
+
# and clear db too
|
37
|
+
glossary.index!
|
31
38
|
end
|
32
39
|
|
33
40
|
describe '#add' do
|
@@ -37,7 +44,7 @@ module Logaling
|
|
37
44
|
end
|
38
45
|
|
39
46
|
it 'glossary yaml should have that bilingual pair' do
|
40
|
-
yaml = YAML::load_file(
|
47
|
+
yaml = YAML::load_file(glossary_source_absolute_path)
|
41
48
|
term = yaml.index({"source_term"=>"spec", "target_term"=>"スペック", "note"=>"テストスペック"})
|
42
49
|
term.should_not be_nil
|
43
50
|
end
|
@@ -49,7 +56,7 @@ module Logaling
|
|
49
56
|
end
|
50
57
|
|
51
58
|
it "should create the glossary and add term" do
|
52
|
-
yaml = YAML::load_file(
|
59
|
+
yaml = YAML::load_file(glossary_source_absolute_path)
|
53
60
|
term = yaml.index({"source_term"=>"test", "target_term"=>"テスト", "note"=>"テスト"})
|
54
61
|
term.should_not be_nil
|
55
62
|
end
|
@@ -85,7 +92,7 @@ module Logaling
|
|
85
92
|
end
|
86
93
|
|
87
94
|
it 'should clear note' do
|
88
|
-
yaml = YAML::load_file(
|
95
|
+
yaml = YAML::load_file(glossary_source_absolute_path)
|
89
96
|
term = yaml.index({"source_term"=>"user", "target_term"=>"ユーザ", "note"=>""})
|
90
97
|
term.should_not be_nil
|
91
98
|
end
|
@@ -97,7 +104,7 @@ module Logaling
|
|
97
104
|
end
|
98
105
|
|
99
106
|
it {
|
100
|
-
-> { glossary.update("user", "
|
107
|
+
-> { glossary.update("user", "ゆーざ", "ユーザ", "") }.should raise_error(Logaling::TermError)
|
101
108
|
}
|
102
109
|
end
|
103
110
|
end
|
@@ -107,10 +114,7 @@ module Logaling
|
|
107
114
|
before do
|
108
115
|
glossary.add("delete_logaling", "てすと1", "備考")
|
109
116
|
glossary.add("delete_logaling", "てすと2", "備考")
|
110
|
-
# in order to index certainly
|
111
|
-
sleep(1)
|
112
117
|
glossary.delete("delete_logaling", "てすと1")
|
113
|
-
repository.index
|
114
118
|
@result = repository.lookup("delete_logaling", glossary)
|
115
119
|
end
|
116
120
|
|
@@ -147,7 +151,6 @@ module Logaling
|
|
147
151
|
before do
|
148
152
|
glossary.add("user_logaling", "ユーザ", "備考")
|
149
153
|
glossary.delete_all("user_logaling")
|
150
|
-
repository.index
|
151
154
|
@result = repository.lookup("user_logaling", glossary)
|
152
155
|
end
|
153
156
|
|
@@ -25,10 +25,12 @@ module Logaling
|
|
25
25
|
let(:repository) { Logaling::Repository.new(logaling_home) }
|
26
26
|
let(:glossary) { repository.find_project('spec').glossary('en', 'ja') }
|
27
27
|
let(:glossary_source_path) { glossary.glossary_source.source_path }
|
28
|
+
let(:glossary_source_absolute_path) { glossary.glossary_source.absolute_path }
|
28
29
|
|
29
30
|
before do
|
30
31
|
FileUtils.rm_rf(File.join(logaling_home, 'projects', 'spec'), :secure => true)
|
31
32
|
FileUtils.mkdir_p(File.join(logaling_home, 'projects', 'spec'))
|
33
|
+
repository.index
|
32
34
|
end
|
33
35
|
|
34
36
|
describe '#lookup' do
|
@@ -117,7 +119,7 @@ module Logaling
|
|
117
119
|
end
|
118
120
|
|
119
121
|
context 'when tsv file as glossary exists' do
|
120
|
-
let(:tsv_path) {
|
122
|
+
let(:tsv_path) { glossary_source_absolute_path.sub(/yml$/, 'tsv') }
|
121
123
|
|
122
124
|
before do
|
123
125
|
FileUtils.touch(tsv_path)
|
@@ -137,16 +139,14 @@ module Logaling
|
|
137
139
|
end
|
138
140
|
|
139
141
|
describe '#index' do
|
140
|
-
let(:tsv_path) { File.join(File.dirname(
|
141
|
-
let(:csv_path) { File.join(File.dirname(
|
142
|
+
let(:tsv_path) { File.join(File.dirname(glossary_source_absolute_path), "spec.en.ja.tsv") }
|
143
|
+
let(:csv_path) { File.join(File.dirname(glossary_source_absolute_path), "spec.en.ja.csv") }
|
142
144
|
|
143
145
|
context 'when yml file as glossary exists' do
|
144
146
|
before do
|
145
|
-
File.open(
|
147
|
+
File.open(glossary_source_absolute_path, 'w') do |f|
|
146
148
|
YAML.dump([], f)
|
147
149
|
end
|
148
|
-
# in order to index certainly
|
149
|
-
sleep(1)
|
150
150
|
glossary.add("spec_logaling", "スペック", "備考")
|
151
151
|
repository.index
|
152
152
|
@terms = repository.lookup("spec_logaling", glossary)
|
@@ -157,7 +157,7 @@ module Logaling
|
|
157
157
|
end
|
158
158
|
|
159
159
|
after do
|
160
|
-
FileUtils.rm_rf(
|
160
|
+
FileUtils.rm_rf(glossary_source_absolute_path, :secure => true)
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
@@ -196,6 +196,46 @@ module Logaling
|
|
196
196
|
end
|
197
197
|
end
|
198
198
|
|
199
|
+
describe "#create_personal_repository" do
|
200
|
+
let(:glossary_name) { "personal_project" }
|
201
|
+
let(:source_language) { "en" }
|
202
|
+
let(:target_language) { "ja" }
|
203
|
+
before do
|
204
|
+
FileUtils.rm_rf(File.join(logaling_home, 'personal'), :secure => true)
|
205
|
+
repository.create_personal_project(glossary_name, source_language, target_language)
|
206
|
+
end
|
207
|
+
|
208
|
+
context "when just create personal project" do
|
209
|
+
before do
|
210
|
+
glossary = repository.find_glossary(glossary_name, source_language, target_language)
|
211
|
+
Logaling::GlossaryDB.open(repository.logaling_db_home, "utf8") do |db|
|
212
|
+
@ret = db.glossary_source_exist?(glossary.glossary_source)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should not be indexed on db" do
|
217
|
+
@ret.should be_false
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context "when create personal project and index" do
|
222
|
+
before do
|
223
|
+
glossary = repository.find_glossary(glossary_name, source_language, target_language)
|
224
|
+
glossary.index!
|
225
|
+
Logaling::GlossaryDB.open(repository.logaling_db_home, "utf8") do |db|
|
226
|
+
@ret = db.glossary_source_exist?(glossary.glossary_source)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should be indexed on db" do
|
231
|
+
@ret.should be_true
|
232
|
+
end
|
233
|
+
end
|
234
|
+
after do
|
235
|
+
repository.remove_personal_project(glossary_name, source_language, target_language)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
199
239
|
describe "#remove_personal_project" do
|
200
240
|
let(:rm_glossary_name) { "rm_personal_project" }
|
201
241
|
let(:rm_source_language) { "en" }
|
@@ -203,6 +243,7 @@ module Logaling
|
|
203
243
|
before do
|
204
244
|
FileUtils.rm_rf(File.join(logaling_home, 'personal'), :secure => true)
|
205
245
|
repository.create_personal_project(rm_glossary_name, rm_source_language, rm_target_language)
|
246
|
+
repository.index
|
206
247
|
end
|
207
248
|
|
208
249
|
context "when target personal project exists" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logaling-command
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2012-
|
16
|
+
date: 2012-11-29 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: thor
|
@@ -193,6 +193,7 @@ files:
|
|
193
193
|
- lib/logaling/repository.rb
|
194
194
|
- logaling-command.gemspec
|
195
195
|
- spec/logaling/command_spec.rb
|
196
|
+
- spec/logaling/glossary_db_spec.rb
|
196
197
|
- spec/logaling/glossary_spec.rb
|
197
198
|
- spec/logaling/project_spec.rb
|
198
199
|
- spec/logaling/repository_spec.rb
|
@@ -223,6 +224,7 @@ specification_version: 3
|
|
223
224
|
summary: A command line interface for logaling.
|
224
225
|
test_files:
|
225
226
|
- spec/logaling/command_spec.rb
|
227
|
+
- spec/logaling/glossary_db_spec.rb
|
226
228
|
- spec/logaling/glossary_spec.rb
|
227
229
|
- spec/logaling/project_spec.rb
|
228
230
|
- spec/logaling/repository_spec.rb
|