stickyflag 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 (76) hide show
  1. data/.gitignore +7 -0
  2. data/.rspec +4 -0
  3. data/.simplecov +9 -0
  4. data/.travis.yml +13 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE.md +7 -0
  7. data/README.md +49 -0
  8. data/Rakefile +19 -0
  9. data/TODO.md +3 -0
  10. data/bin/stickyflag +6 -0
  11. data/features/clear.feature +14 -0
  12. data/features/clear_quietly.feature +23 -0
  13. data/features/configuration.feature +14 -0
  14. data/features/get.feature +14 -0
  15. data/features/get_quietly.feature +23 -0
  16. data/features/set.feature +14 -0
  17. data/features/set_quietly.feature +22 -0
  18. data/features/step_definitions/configuration_steps.rb +31 -0
  19. data/features/step_definitions/database_steps.rb +41 -0
  20. data/features/step_definitions/pending_steps.rb +5 -0
  21. data/features/step_definitions/tag_steps.rb +62 -0
  22. data/features/support/cukegem.rb +82 -0
  23. data/features/support/env.rb +37 -0
  24. data/features/tags.feature +18 -0
  25. data/features/unset.feature +14 -0
  26. data/features/unset_quietly.feature +23 -0
  27. data/lib/stickyflag/configuration.rb +66 -0
  28. data/lib/stickyflag/database.rb +162 -0
  29. data/lib/stickyflag/external_cmds.rb +64 -0
  30. data/lib/stickyflag/patches/tempfile_encoding.rb +22 -0
  31. data/lib/stickyflag/patches/tmpnam.rb +38 -0
  32. data/lib/stickyflag/paths.rb +47 -0
  33. data/lib/stickyflag/tag_factory.rb +108 -0
  34. data/lib/stickyflag/tags/c.rb +25 -0
  35. data/lib/stickyflag/tags/mmd.rb +168 -0
  36. data/lib/stickyflag/tags/pdf.rb +119 -0
  37. data/lib/stickyflag/tags/png.rb +61 -0
  38. data/lib/stickyflag/tags/source_code.rb +99 -0
  39. data/lib/stickyflag/tags/tex.rb +25 -0
  40. data/lib/stickyflag/version.rb +12 -0
  41. data/lib/stickyflag.rb +253 -0
  42. data/spec/spec_helper.rb +22 -0
  43. data/spec/stickyflag/configuration_spec.rb +132 -0
  44. data/spec/stickyflag/database_spec.rb +331 -0
  45. data/spec/stickyflag/external_cmds_spec.rb +175 -0
  46. data/spec/stickyflag/patches/tempfile_encoding_spec.rb +26 -0
  47. data/spec/stickyflag/patches/tmpnam_spec.rb +35 -0
  48. data/spec/stickyflag/paths_spec.rb +29 -0
  49. data/spec/stickyflag/tag_factory_spec.rb +185 -0
  50. data/spec/stickyflag/tags/c_spec.rb +14 -0
  51. data/spec/stickyflag/tags/mmd_spec.rb +40 -0
  52. data/spec/stickyflag/tags/pdf_spec.rb +39 -0
  53. data/spec/stickyflag/tags/png_spec.rb +6 -0
  54. data/spec/stickyflag/tags/tex_spec.rb +6 -0
  55. data/spec/stickyflag_spec.rb +482 -0
  56. data/spec/support/examples/c_all_comments.c +3 -0
  57. data/spec/support/examples/c_no_tags.c +5 -0
  58. data/spec/support/examples/c_with_tag.c +6 -0
  59. data/spec/support/examples/mmd_all_meta.mmd +6 -0
  60. data/spec/support/examples/mmd_crazy_keys.mmd +8 -0
  61. data/spec/support/examples/mmd_crazy_tags.mmd +9 -0
  62. data/spec/support/examples/mmd_no_tags.mmd +1 -0
  63. data/spec/support/examples/mmd_with_tag.mmd +3 -0
  64. data/spec/support/examples/pdf_no_tags.pdf +0 -0
  65. data/spec/support/examples/pdf_with_tag.pdf +0 -0
  66. data/spec/support/examples/png_no_tags.png +0 -0
  67. data/spec/support/examples/png_with_tag.png +0 -0
  68. data/spec/support/examples/tex_no_tags.tex +10 -0
  69. data/spec/support/examples/tex_with_tag.tex +11 -0
  70. data/spec/support/examples/untaggable.txt +0 -0
  71. data/spec/support/examples.rb +32 -0
  72. data/spec/support/run_with_args.rb +36 -0
  73. data/spec/support/silence_stream.rb +12 -0
  74. data/spec/support/tag_handler_behavior.rb +125 -0
  75. data/stickyflag.gemspec +48 -0
  76. metadata +399 -0
@@ -0,0 +1,29 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'stickyflag/paths'
3
+
4
+ class PathsTester
5
+ include StickyFlag::Paths
6
+ end
7
+
8
+ describe 'StickyFlag::Paths' do
9
+ describe '.config_path' do
10
+ it 'includes the config.yml file name' do
11
+ PathsTester.new.config_path.should include('config.yml')
12
+ end
13
+
14
+ it "doesn't include any tildes" do
15
+ PathsTester.new.config_path.should_not include('~')
16
+ end
17
+ end
18
+
19
+ describe '.database_path' do
20
+ it 'includes the db.sqlite file name' do
21
+ PathsTester.new.database_path.should include('db.sqlite')
22
+ end
23
+
24
+ it "doesn't include any tildes" do
25
+ PathsTester.new.database_path.should_not include('~')
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,185 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'thor'
3
+ require 'stickyflag/patches/tempfile_encoding'
4
+ require 'stickyflag/paths'
5
+ require 'stickyflag/configuration'
6
+ require 'stickyflag/tag_factory'
7
+ require 'stickyflag/external_cmds'
8
+ require 'stickyflag/database'
9
+
10
+ class TagFactoryTester < Thor
11
+ include StickyFlag::Paths
12
+ include StickyFlag::Configuration
13
+ include StickyFlag::TagFactory
14
+ include StickyFlag::ExternalCmds
15
+ include StickyFlag::Database
16
+ end
17
+
18
+ describe 'StickyFlag::TagFactory' do
19
+ before(:each) do
20
+ @obj = TagFactoryTester.new
21
+
22
+ @obj.stub(:load_config!) { }
23
+ @obj.stub(:save_config!) { }
24
+
25
+ @obj.stub(:load_database) { }
26
+ @obj.stub(:update_database_from_files) { }
27
+ @obj.stub(:set_database_tag) { }
28
+ @obj.stub(:unset_database_tag) { }
29
+ @obj.stub(:clear_database_tags) { }
30
+ @obj.stub(:files_for_tags) { [] }
31
+
32
+ @obj.find_external_cmds
33
+ end
34
+
35
+ describe '.available_tagging_extensions' do
36
+ # Some extensions require the presence of actual, good files, not
37
+ # just empty shells, so we can't test them in this way. Skip those.
38
+ CANNOT_TEST = [ '.pdf', '.png' ]
39
+
40
+ it 'should call get for every good extension' do
41
+ (@obj.available_tagging_extensions - CANNOT_TEST).each do |ext|
42
+ file = Tempfile.new_with_encoding(['ext', ext])
43
+ file.puts('test')
44
+ file.close
45
+
46
+ expect { @obj.get_tags_for(file.path) }.to_not raise_error
47
+ file.unlink
48
+ end
49
+ end
50
+
51
+ it 'should call get for other extensions' do
52
+ CANNOT_TEST.each do |ext|
53
+ path = copy_example "#{ext[1..-1]}_with_tag#{ext}"
54
+ expect { @obj.clear_tags_for(path) }.to_not raise_error
55
+ File.unlink(path)
56
+ end
57
+ end
58
+
59
+ it 'should call set/unset for every good extension' do
60
+ (@obj.available_tagging_extensions - CANNOT_TEST).each do |ext|
61
+ file = Tempfile.new_with_encoding(['ext', ext])
62
+ file.puts('test')
63
+ file.close
64
+
65
+ expect {
66
+ @obj.set_tag_for(file.path, 'test')
67
+ @obj.unset_tag_for(file.path, 'test')
68
+ }.to_not raise_error
69
+ file.unlink
70
+ end
71
+ end
72
+
73
+ it 'should call set/unset for other extensions' do
74
+ CANNOT_TEST.each do |ext|
75
+ path = copy_example "#{ext[1..-1]}_with_tag#{ext}"
76
+ expect {
77
+ @obj.set_tag_for(path, 'test2')
78
+ @obj.unset_tag_for(path, 'test2')
79
+ }.to_not raise_error
80
+ File.unlink(path)
81
+ end
82
+ end
83
+
84
+ it 'should call clear for every good extension' do
85
+ (@obj.available_tagging_extensions - CANNOT_TEST).each do |ext|
86
+ file = Tempfile.new_with_encoding(['ext', ext])
87
+ file.puts('test')
88
+ file.close
89
+
90
+ expect { @obj.clear_tags_for(file.path) }.to_not raise_error
91
+ file.unlink
92
+ end
93
+ end
94
+
95
+ it 'should call clear for other extensions' do
96
+ CANNOT_TEST.each do |ext|
97
+ path = copy_example "#{ext[1..-1]}_with_tag#{ext}"
98
+ expect { @obj.clear_tags_for(path) }.to_not raise_error
99
+ File.unlink(path)
100
+ end
101
+ end
102
+ end
103
+
104
+ describe '.get_tags_for' do
105
+ it 'should delegate to PDF' do
106
+ path = example_path('pdf_no_tags.pdf')
107
+
108
+ StickyFlag::Tags::PDF.should_receive(:get).with(path, kind_of(String))
109
+ @obj.get_tags_for(path)
110
+ end
111
+
112
+ it 'should raise error for unknown extensions' do
113
+ expect {
114
+ @obj.get_tags_for('asdf.zzy')
115
+ }.to raise_error(Thor::Error)
116
+ end
117
+ end
118
+
119
+ describe '.set_tag_for' do
120
+ it 'should delegate to PDF' do
121
+ path = example_path('pdf_no_tags.pdf')
122
+
123
+ StickyFlag::Tags::PDF.should_receive(:set).with(path, 'lol', kind_of(String))
124
+ @obj.set_tag_for(path, 'lol')
125
+ end
126
+
127
+ it 'should not call through if the tag is already set' do
128
+ path = example_path('pdf_with_tag.pdf')
129
+
130
+ StickyFlag::Tags::PDF.should_not_receive(:set)
131
+ @obj.set_tag_for(path, 'test')
132
+ end
133
+
134
+ it 'should raise error for unknown extensions' do
135
+ @obj.stub(:get_tags_for) { [] }
136
+ expect {
137
+ @obj.set_tag_for('asdf.zzy', 'lol')
138
+ }.to raise_error(Thor::Error)
139
+ end
140
+ end
141
+
142
+ describe '.unset_tag_for' do
143
+ it 'should delegate to PDF' do
144
+ path = copy_example('pdf_with_tag.pdf')
145
+
146
+ StickyFlag::Tags::PDF.should_receive(:unset).with(path, 'test', kind_of(String))
147
+ @obj.unset_tag_for(path, 'test')
148
+
149
+ File.delete(path)
150
+ end
151
+
152
+ it 'should not call through if the tag is not set' do
153
+ path = example_path('pdf_no_tags.pdf')
154
+
155
+ StickyFlag::Tags::PDF.should_not_receive(:unset)
156
+ expect {
157
+ @obj.unset_tag_for(path, 'test')
158
+ }.to raise_error(Thor::Error)
159
+ end
160
+
161
+ it 'should raise error for unknown extensions' do
162
+ @obj.stub(:get_tags_for) { [ 'lol' ] }
163
+ expect {
164
+ @obj.unset_tag_for('asdf.zzy', 'lol')
165
+ }.to raise_error(Thor::Error)
166
+ end
167
+ end
168
+
169
+ describe '.clear_tags_for' do
170
+ it 'should delegate to PDF' do
171
+ path = copy_example('pdf_with_tag.pdf')
172
+
173
+ StickyFlag::Tags::PDF.should_receive(:clear).with(path, kind_of(String))
174
+ @obj.clear_tags_for(path)
175
+
176
+ File.delete(path)
177
+ end
178
+
179
+ it 'should raise error for unknown extensions' do
180
+ expect {
181
+ @obj.clear_tags_for('asdf.zzy')
182
+ }.to raise_error(Thor::Error)
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,14 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'stickyflag/tags/c'
3
+
4
+ describe StickyFlag::Tags::C do
5
+ it_behaves_like 'a tag handler'
6
+
7
+ it 'can open a file with all comments and no tags' do
8
+ ret = nil
9
+ expect {
10
+ ret = StickyFlag::Tags::C.get(example_path('c_all_comments.c'))
11
+ }.to_not raise_error
12
+ ret.should be_empty
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'stickyflag/tags/mmd'
3
+
4
+ describe StickyFlag::Tags::MMD do
5
+ it_behaves_like 'a tag handler'
6
+
7
+ it 'handles multiline metadata documents' do
8
+ StickyFlag::Tags::MMD.get(example_path('mmd_crazy_keys.mmd')).should include('test')
9
+ end
10
+
11
+ it 'handles multiline tag documents' do
12
+ StickyFlag::Tags::MMD.get(example_path('mmd_crazy_tags.mmd')).should include('sdfg')
13
+ end
14
+
15
+ it 'handles all-metadata documents' do
16
+ StickyFlag::Tags::MMD.get(example_path('mmd_all_meta.mmd')).should be_empty
17
+ end
18
+
19
+ it 'can edit multiline metadata documents' do
20
+ path = copy_example('mmd_crazy_keys.mmd')
21
+
22
+ StickyFlag::Tags::MMD.set(path, 'test2')
23
+ StickyFlag::Tags::MMD.get(path).should include('test2')
24
+
25
+ File.open(path, 'r:UTF-8').each_line.to_a.should include("Tags: test, test2 \n")
26
+
27
+ File.delete path
28
+ end
29
+
30
+ it 'can edit multiline tag documents' do
31
+ path = copy_example('mmd_crazy_tags.mmd')
32
+
33
+ StickyFlag::Tags::MMD.set(path, 'test2')
34
+ StickyFlag::Tags::MMD.get(path).should include('test2')
35
+
36
+ File.open(path, 'r:UTF-8').each_line.to_a.should include("Tags: asdf, sdfg, dfgh, fghj, qwer, test2 \n")
37
+
38
+ File.delete path
39
+ end
40
+ end
@@ -0,0 +1,39 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'stickyflag/tags/pdf'
3
+ require 'stickyflag/paths'
4
+ require 'stickyflag/configuration'
5
+ require 'stickyflag/external_cmds'
6
+
7
+ class GetConfiguration
8
+ include StickyFlag::Paths
9
+ include StickyFlag::Configuration
10
+ include StickyFlag::ExternalCmds
11
+ end
12
+
13
+ describe StickyFlag::Tags::PDF do
14
+ it_behaves_like 'a tag handler' do
15
+ let(:params) {
16
+ config = GetConfiguration.new
17
+ config.stub(:load_config!) { }
18
+ config.stub(:save_config!) { }
19
+
20
+ config.find_external_cmds
21
+
22
+ [ config.get_config(:pdftk_path) ]
23
+ }
24
+ end
25
+
26
+ context 'with a bad pdftk path' do
27
+ it 'raises errors for everything' do
28
+ expect { StickyFlag::Tags::PDF.get(example_path("pdf_with_tag.pdf"), '/wut/bad') }.to raise_error(Thor::Error)
29
+ expect { StickyFlag::Tags::PDF.clear(example_path("pdf_with_tag.pdf"), '/wut/bad') }.to raise_error(Thor::Error)
30
+
31
+ # If get doesn't succeed, we won't get all the way into set or unset
32
+ # with the bad pdftk path.
33
+ StickyFlag::Tags::PDF.stub(:get) { [ 'test' ] }
34
+ expect { StickyFlag::Tags::PDF.set(example_path("pdf_with_tag.pdf"), 'test2', '/wut/bad') }.to raise_error(Thor::Error)
35
+ expect { StickyFlag::Tags::PDF.unset(example_path("pdf_with_tag.pdf"), 'test', '/wut/bad') }.to raise_error(Thor::Error)
36
+ StickyFlag::Tags::PDF.unstub(:get)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'stickyflag/tags/png'
3
+
4
+ describe StickyFlag::Tags::PNG do
5
+ it_behaves_like 'a tag handler'
6
+ end
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'stickyflag/tags/tex'
3
+
4
+ describe StickyFlag::Tags::TeX do
5
+ it_behaves_like 'a tag handler'
6
+ end