gitdocs 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +6 -14
  2. data/.codeclimate.yml +26 -0
  3. data/.rubocop.yml +8 -2
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG +13 -0
  6. data/Gemfile +1 -1
  7. data/README.md +7 -6
  8. data/Rakefile +31 -5
  9. data/bin/gitdocs +1 -0
  10. data/config.ru +6 -4
  11. data/gitdocs.gemspec +22 -19
  12. data/lib/gitdocs.rb +54 -16
  13. data/lib/gitdocs/browser_app.rb +34 -41
  14. data/lib/gitdocs/cli.rb +41 -32
  15. data/lib/gitdocs/configuration.rb +40 -101
  16. data/lib/gitdocs/git_notifier.rb +111 -0
  17. data/lib/gitdocs/initializer.rb +83 -0
  18. data/lib/gitdocs/manager.rb +90 -60
  19. data/lib/gitdocs/migration/004_add_index_for_path.rb +1 -1
  20. data/lib/gitdocs/notifier.rb +70 -104
  21. data/lib/gitdocs/rendering_helper.rb +3 -0
  22. data/lib/gitdocs/repository.rb +324 -307
  23. data/lib/gitdocs/repository/committer.rb +77 -0
  24. data/lib/gitdocs/repository/path.rb +157 -140
  25. data/lib/gitdocs/search.rb +40 -25
  26. data/lib/gitdocs/settings_app.rb +5 -3
  27. data/lib/gitdocs/share.rb +64 -0
  28. data/lib/gitdocs/synchronizer.rb +40 -0
  29. data/lib/gitdocs/version.rb +1 -1
  30. data/lib/gitdocs/views/_header.haml +2 -2
  31. data/lib/gitdocs/views/dir.haml +3 -3
  32. data/lib/gitdocs/views/edit.haml +1 -1
  33. data/lib/gitdocs/views/file.haml +1 -1
  34. data/lib/gitdocs/views/home.haml +3 -3
  35. data/lib/gitdocs/views/layout.haml +13 -13
  36. data/lib/gitdocs/views/revisions.haml +3 -3
  37. data/lib/gitdocs/views/search.haml +1 -1
  38. data/lib/gitdocs/views/settings.haml +6 -6
  39. data/test/integration/cli/full_sync_test.rb +83 -0
  40. data/test/integration/cli/share_management_test.rb +29 -0
  41. data/test/integration/cli/status_test.rb +14 -0
  42. data/test/integration/test_helper.rb +185 -151
  43. data/test/integration/{browse_test.rb → web/browse_test.rb} +11 -29
  44. data/test/integration/web/share_management_test.rb +46 -0
  45. data/test/support/git_factory.rb +276 -0
  46. data/test/unit/browser_app_test.rb +346 -0
  47. data/test/unit/configuration_test.rb +8 -70
  48. data/test/unit/git_notifier_test.rb +116 -0
  49. data/test/unit/gitdocs_test.rb +90 -0
  50. data/test/unit/manager_test.rb +36 -0
  51. data/test/unit/notifier_test.rb +60 -124
  52. data/test/unit/repository_committer_test.rb +111 -0
  53. data/test/unit/repository_path_test.rb +92 -76
  54. data/test/unit/repository_test.rb +243 -356
  55. data/test/unit/search_test.rb +15 -0
  56. data/test/unit/settings_app_test.rb +80 -0
  57. data/test/unit/share_test.rb +97 -0
  58. data/test/unit/test_helper.rb +17 -3
  59. metadata +114 -108
  60. data/lib/gitdocs/runner.rb +0 -108
  61. data/lib/gitdocs/server.rb +0 -62
  62. data/test/integration/full_sync_test.rb +0 -66
  63. data/test/integration/share_management_test.rb +0 -95
  64. data/test/integration/status_test.rb +0 -21
  65. data/test/unit/runner_test.rb +0 -122
@@ -2,56 +2,57 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'minitest/autorun'
5
- $LOAD_PATH.unshift File.expand_path('../../lib')
6
- require 'gitdocs'
7
5
  require 'aruba'
8
6
  require 'aruba/api'
9
7
  require 'timeout'
10
8
  require 'capybara'
11
9
  require 'capybara_minitest_spec'
10
+ require 'capybara/dsl'
12
11
  require 'capybara/poltergeist'
12
+ require 'find'
13
+ require 'gitdocs/version'
14
+ Dir.glob(File.expand_path('../../support/**/*.rb', __FILE__)).each do |filename|
15
+ require_relative filename
16
+ end
13
17
 
14
- Capybara.app_host = 'http://localhost:7777/'
15
- Capybara.default_driver = :poltergeist
16
- Capybara.run_server = false
17
- Capybara.default_wait_time = 20
18
+ Capybara.app_host = 'http://localhost:7777/'
19
+ Capybara.default_driver = :poltergeist
20
+ Capybara.run_server = false
21
+ Capybara.default_max_wait_time = ENV['TRAVIS'] ? 120 : 30
18
22
 
19
23
  Capybara.register_driver :poltergeist do |app|
20
- Capybara::Poltergeist::Driver.new(app, timeout: 20)
24
+ Capybara::Poltergeist::Driver.new(
25
+ app,
26
+ timeout: Capybara.default_max_wait_time,
27
+ # Disable catching javascript errors because of the possibility of errors
28
+ # from the Ace code.
29
+ js_errors: false
30
+ )
21
31
  end
22
32
 
23
- module MiniTest::Aruba
24
- class ArubaApiWrapper
25
- include Aruba::Api
26
- end
33
+ PID_FILE = File.expand_path('../../../tmp/gitdocs.pid', __FILE__)
27
34
 
28
- def aruba
29
- @aruba ||= ArubaApiWrapper.new
30
- end
31
-
32
- def run(*args)
33
- if args.length == 0
34
- super
35
- else
36
- aruba.run(*args)
35
+ module MiniTest
36
+ module Aruba
37
+ class ArubaApiWrapper
38
+ include ::Aruba::Api
37
39
  end
38
- end
39
40
 
40
- def method_missing(method, *args, &block)
41
- aruba.send(method, *args, &block)
42
- end
41
+ def aruba
42
+ @aruba ||= ArubaApiWrapper.new
43
+ end
43
44
 
44
- def before_setup
45
- super
46
- original = (ENV['PATH'] || '').split(File::PATH_SEPARATOR)
47
- set_env('PATH', ([File.expand_path('bin')] + original).join(File::PATH_SEPARATOR))
48
- FileUtils.rm_rf(current_dir)
49
- end
45
+ def run(*args)
46
+ if args.empty?
47
+ super
48
+ else
49
+ aruba.run(*args)
50
+ end
51
+ end
50
52
 
51
- def after_teardown
52
- super
53
- restore_env
54
- processes.clear
53
+ def method_missing(method, *args, &block)
54
+ aruba.send(method, *args, &block)
55
+ end
55
56
  end
56
57
  end
57
58
 
@@ -61,9 +62,30 @@ module Helper
61
62
  include Capybara::RSpecMatchers
62
63
 
63
64
  def before_setup
64
- super
65
+ clean_current_dir
66
+
67
+ # HACK: In order to ensure that rugged/libgit2 see the expected HOME
68
+ # directory we must set it before requiring rugged. This seems to occur
69
+ # because libgit2 reads HOME only one the initial load.
65
70
  set_env('HOME', abs_current_dir)
66
- ENV['TEST'] = nil
71
+ require 'rugged'
72
+
73
+ # Make sure that we are not accidentally overwriting an existing gitconfig.
74
+ if Rugged::Config.global['user.name'] || Rugged::Config.global['user.name']
75
+ puts <<-EOS.gsub(/^\s{8}/, '')
76
+ Unexpected git config:
77
+ user.name = #{Rugged::Config.global['user.name']}
78
+ user.email = #{Rugged::Config.global['user.email']}
79
+ Something went wrong when setting the HOME directory and the test
80
+ will not execute in isolation.'
81
+ EXITING
82
+ EOS
83
+ exit
84
+ end
85
+
86
+ GitFactory.working_directory = abs_current_dir
87
+ Rugged::Config.global['user.name'] = GitFactory.users[0][:name]
88
+ Rugged::Config.global['user.email'] = GitFactory.users[0][:email]
67
89
  end
68
90
 
69
91
  def teardown
@@ -72,33 +94,85 @@ module Helper
72
94
  end
73
95
 
74
96
  def after_teardown
75
- super
97
+ restore_env
98
+ processes.clear
76
99
 
77
100
  terminate_processes!
78
101
  prep_for_fs_check do
79
- next unless File.exist?('gitdocs.pid')
102
+ next unless File.exist?(PID_FILE)
103
+
104
+ pid = IO.read(PID_FILE).to_i
105
+ begin
106
+ Process.kill('KILL', pid)
107
+ rescue Errno::ESRCH # rubocop:disable Lint/HandleExceptions
108
+ # Nothing to do since the process is already gone.
109
+ end
80
110
 
81
- pid = IO.read('gitdocs.pid').to_i
82
- Process.kill('KILL', pid)
83
111
  begin
84
112
  Process.wait(pid)
85
113
  rescue SystemCallError # rubocop:disable Lint/HandleExceptions
86
114
  # This means that the process is already gone.
87
115
  # Nothing to do.
88
116
  end
117
+ FileUtils.rm_rf(PID_FILE)
118
+ end
119
+
120
+ return if passed?
121
+
122
+ # Report gitdocs execution details on failure
123
+ puts "\n\n----------------------------------"
124
+ puts "Aruba details for failure: #{name}"
125
+ puts failures.inspect.to_s
126
+
127
+ log_filename = File.join(abs_current_dir, '.gitdocs', 'log')
128
+ if File.exist?(log_filename)
129
+ puts '----------------------------------'
130
+ puts "Log file: #{log_filename}"
131
+ puts File.read(log_filename)
132
+ end
133
+
134
+ if Dir.exist?(abs_current_dir)
135
+ puts '----------------------------------'
136
+ puts 'Aruba current directory file list:'
137
+ Find.find(abs_current_dir) do |path|
138
+ Find.prune if path =~ %r{.git/?$}
139
+ puts " #{path}"
140
+ end
89
141
  end
142
+
143
+ puts "----------------------------------\n\n"
90
144
  end
91
145
 
92
- def start_daemon
93
- configuration = Gitdocs::Configuration.new
94
- configuration.shares.each do |share|
146
+ # @param [String] method pass to the CLI
147
+ # @param [String] arguments which will be passed to the CLI in addition
148
+ # @param [String] expected_output that the CLI should return
149
+ #
150
+ # @return [String] full text of the command being executed
151
+ def gitdocs_command(method, arguments, expected_output)
152
+ binary_path = File.expand_path('../../../bin/gitdocs', __FILE__)
153
+ full_command = "#{binary_path} #{method} #{arguments} --pid=#{PID_FILE}"
154
+
155
+ run(full_command, Capybara.default_max_wait_time)
156
+ assert_success(true)
157
+ assert_partial_output(expected_output, output_from(full_command))
158
+
159
+ full_command
160
+ end
161
+
162
+ # @return [void]
163
+ def gitdocs_start
164
+ # FIXME: Calling internal funcations directly because we cannot currently
165
+ # set polling or notification on the CLI. After that has been added this
166
+ # should be removed. [ASC 2015-10-26]
167
+ require 'gitdocs/initializer'
168
+ require 'gitdocs/share'
169
+ Gitdocs::Initializer.initialize_database
170
+ Gitdocs::Share.all.each do |share|
95
171
  share.update_attributes(polling_interval: 0.1, notification: false)
96
172
  end
97
173
 
98
- start_cmd = 'gitdocs start --debug --pid=gitdocs.pid --port 7777'
99
- run(start_cmd, 15)
100
- assert_success(true)
101
- assert_partial_output('Started gitdocs', output_from(start_cmd))
174
+ FileUtils.rm_rf(PID_FILE)
175
+ gitdocs_command('start', '--verbose --port=7777', 'Started gitdocs')
102
176
  end
103
177
 
104
178
  # @overload abs_current_dir
@@ -111,128 +185,88 @@ module Helper
111
185
  File.absolute_path(File.join(current_dir, relative_path))
112
186
  end
113
187
 
114
- # @return [String] the absolute path for the repository
115
- def git_init_local(path = 'local')
116
- abs_path = abs_current_dir(path)
117
- Rugged::Repository.init_at(abs_path)
118
- abs_path
188
+ # @param [String] path
189
+ #
190
+ # @return [#gitdocs_command]
191
+ def gitdocs_add(path)
192
+ GitFactory.init(path)
193
+ gitdocs_command('add', path, "Added path #{path} to doc list")
119
194
  end
120
195
 
121
- # @return [String] the absolute path for the repository
122
- def git_init_remote(path = 'remote')
123
- abs_path = abs_current_dir(path)
124
- Rugged::Repository.init_at(abs_path, :bare)
125
- abs_path
126
- end
127
-
128
- def wait_for_clean_workdir(path)
129
- dirty = true
130
- Timeout.timeout(20) do
131
- while dirty
132
- begin
133
- sleep(0.1)
134
- rugged = Rugged::Repository.new(abs_current_dir(path))
135
- dirty = !rugged.diff_workdir(rugged.head.target, include_untracked: true).deltas.empty?
136
- rescue Rugged::ReferenceError
137
- nil
138
- rescue Rugged::InvalidError
139
- nil
140
- rescue Rugged::RepositoryError
141
- nil
142
- end
143
- end
196
+ # @param [Array<String>] destination_paths
197
+ #
198
+ # @return [void]
199
+ def gitdocs_create_from_remote(*destination_paths)
200
+ full_destination_paths = destination_paths.map { |x| GitFactory.expand_path(x) }
201
+ remote_repository_path = GitFactory.init_bare(:remote)
202
+
203
+ full_destination_paths.each do |destination_path|
204
+ gitdocs_command(
205
+ 'create',
206
+ "#{destination_path} #{remote_repository_path}",
207
+ "Added path #{destination_path} to doc list"
208
+ )
144
209
  end
145
- rescue Timeout::Error
146
- assert(false, "#{path} workdir is still dirty")
147
210
  end
148
211
 
149
- def wait_for_exact_file_content(file, exact_content)
150
- in_current_dir do
151
- begin
152
- Timeout.timeout(20) do
153
- sleep(0.1) until File.exist?(file) && IO.read(file) == exact_content
154
- end
155
- rescue Timeout::Error
156
- nil
157
- end
158
-
159
- assert(File.exist?(file), "Missing #{file}")
160
- actual_content = IO.read(file)
161
- assert(
162
- actual_content == exact_content,
163
- "Expected #{file} content: #{exact_content}\nActual content #{actual_content}"
164
- )
212
+ # @param [Array<String>] expected_outputs
213
+ #
214
+ # @return [void]
215
+ def gitdocs_assert_status_contains(*expected_outputs)
216
+ command = gitdocs_command('status', '', Gitdocs::VERSION)
217
+ expected_outputs.each do |expected_output|
218
+ assert_partial_output(expected_output, output_from(command))
165
219
  end
166
220
  end
167
221
 
168
- def wait_for_directory(path)
169
- in_current_dir do
170
- begin
171
- Timeout.timeout(20) { sleep(0.1) until Dir.exist?(path) }
172
- rescue Timeout::Error
173
- nil
174
- end
175
-
176
- assert(Dir.exist?(path), "Missing #{path}")
222
+ # @param [Array<String>] not_expected_outputs
223
+ #
224
+ # @return [void]
225
+ def gitdocs_assert_status_not_contain(*not_expected_outputs)
226
+ command = gitdocs_command('status', '', Gitdocs::VERSION)
227
+ not_expected_outputs.each do |not_expected_output|
228
+ assert_no_partial_output(not_expected_output, output_from(command))
177
229
  end
178
230
  end
179
231
 
180
- def wait_for_conflict_markers(path)
181
- in_current_dir do
232
+ # @overload wait_for_assert
233
+ # @yield to a block which executes Minitest assertion
234
+ #
235
+ # @overload wait_for_assert(interval)
236
+ # @param [Float] interval
237
+ # @yield to a block which executes Minitest assertion
238
+ #
239
+ # @raise [Minitest::Assertion]
240
+ #
241
+ # @return [void]
242
+ def wait_for_assert(interval = 0.1)
243
+ Timeout.timeout(Capybara.default_max_wait_time) do
182
244
  begin
183
- Timeout.timeout(20) { sleep(0.1) if File.exist?(path) }
184
- rescue Timeout::Error
185
- nil
186
- ensure
187
- assert(!File.exist?(path), "#{path} should have been removed")
188
- end
189
-
190
- begin
191
- Timeout.timeout(20) { sleep(0.1) if Dir.glob("#{path} (*)").empty? }
192
- rescue Timeout::Error
193
- nil
194
- ensure
195
- assert(!Dir.glob("#{path} (*)").empty?, "#{path} conflict marks should have been created")
245
+ yield
246
+ rescue Minitest::Assertion, Capybara::Poltergeist::Error
247
+ sleep(interval)
248
+ retry
196
249
  end
197
250
  end
251
+ rescue Timeout::Error
252
+ yield
198
253
  end
199
254
 
200
- def gitdocs_add(path = 'local')
201
- add_cmd = "gitdocs add #{path} --pid=gitdocs.pid"
202
- run_simple(add_cmd, true, 15)
203
- assert_success(true)
204
- assert_partial_output("Added path #{path} to doc list", output_from(add_cmd))
205
- end
206
-
207
- def git_clone_and_gitdocs_add(remote_path, *clone_paths)
208
- clone_paths.each do |clone_path|
209
- abs_clone_path = abs_current_dir(clone_path)
210
- FileUtils.rm_rf(abs_clone_path)
211
- repo = Rugged::Repository.clone_at(
212
- "file://#{remote_path}",
213
- abs_clone_path
214
- )
215
- repo.config['user.email'] = 'afish@example.com'
216
- repo.config['user.name'] = 'Art T. Fish'
217
- gitdocs_add(clone_path)
255
+ # @param [String] locator
256
+ #
257
+ # @raise [Minitest::Assertion]
258
+ #
259
+ # @return [void]
260
+ def visit_and_click_link(locator)
261
+ wait_for_assert(1) do
262
+ visit('http://localhost:7777/')
263
+ click_link(locator)
218
264
  end
219
265
  end
220
-
221
- def gitdocs_status
222
- @status_cmd = 'gitdocs status --pid=gitdocs.pid'
223
- run(@status_cmd, 15)
224
- assert_success(true)
225
- end
226
-
227
- def assert_gitdocs_status_contains(expected)
228
- assert_partial_output(expected, output_from(@status_cmd))
229
- end
230
-
231
- def assert_gitdocs_status_not_contain(expected)
232
- assert_no_partial_output(expected, output_from(@status_cmd))
233
- end
234
266
  end
235
267
 
236
- class MiniTest::Spec
237
- include Helper
268
+ module MiniTest
269
+ class Spec
270
+ include Helper
271
+ end
238
272
  end
@@ -1,32 +1,22 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- require File.expand_path('../test_helper', __FILE__)
3
+ require File.expand_path('../../test_helper', __FILE__)
4
4
 
5
5
  describe 'browse and edit repository file through the UI' do
6
6
  before do
7
- git_init_local('repo1')
8
7
  gitdocs_add('repo1')
9
-
10
- git_init_local
11
- gitdocs_add
8
+ gitdocs_add('local')
12
9
 
13
10
  # Create the various commits, to be able to see revisions.
14
- repository = Gitdocs::Repository.new(abs_current_dir('local'))
15
- write_file('local/file1', 'fbadbeef')
16
- repository.commit
17
- write_file('local/file1', 'foobar')
18
- repository.commit
19
- write_file('local/file1', 'deadbeef')
20
- repository.commit
21
- write_file('local/file2', 'A5A5A5A5')
22
- repository.commit
23
- write_file('local/README.md', 'hello i am a README')
24
- repository.commit
25
-
26
- start_daemon
27
-
28
- visit 'http://localhost:7777/'
29
- click_link('Home')
11
+ GitFactory.commit(:local, 'file1', 'fbadbeef')
12
+ GitFactory.commit(:local, 'file1', 'foobar')
13
+ GitFactory.commit(:local, 'file1', 'deadbeef')
14
+ GitFactory.commit(:local, 'file2', 'A5A5A5A5')
15
+ GitFactory.commit(:local, 'README.md', 'hello i am a README')
16
+
17
+ gitdocs_start
18
+ visit_and_click_link('Home')
19
+
30
20
  within('table#shares') do
31
21
  within('tbody') do
32
22
  click_link(abs_current_dir('local'))
@@ -59,10 +49,6 @@ describe 'browse and edit repository file through the UI' do
59
49
  end
60
50
 
61
51
  it 'should be able to browser a file revision' do
62
- # FIXME: This test is failing on TravisCI, but succeeding locally so skip
63
- # it for now and revisit in the future.
64
- next if ENV['TRAVIS']
65
-
66
52
  within('table#revisions') do
67
53
  within('tbody') do
68
54
  page.must_have_css('tr', count: 2)
@@ -77,10 +63,6 @@ describe 'browse and edit repository file through the UI' do
77
63
  end
78
64
 
79
65
  it 'should allow file revert' do
80
- # FIXME: This test is failing on TravisCI, but succeeding locally so skip
81
- # it for now and revisit in the future.
82
- next if ENV['TRAVIS']
83
-
84
66
  within('table#revisions') do
85
67
  within('tbody') do
86
68
  page.must_have_css('tr', count: 2)