gitdocs 0.5.0 → 0.6.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.
- checksums.yaml +6 -14
- data/.codeclimate.yml +26 -0
- data/.rubocop.yml +8 -2
- data/.travis.yml +8 -0
- data/CHANGELOG +13 -0
- data/Gemfile +1 -1
- data/README.md +7 -6
- data/Rakefile +31 -5
- data/bin/gitdocs +1 -0
- data/config.ru +6 -4
- data/gitdocs.gemspec +22 -19
- data/lib/gitdocs.rb +54 -16
- data/lib/gitdocs/browser_app.rb +34 -41
- data/lib/gitdocs/cli.rb +41 -32
- data/lib/gitdocs/configuration.rb +40 -101
- data/lib/gitdocs/git_notifier.rb +111 -0
- data/lib/gitdocs/initializer.rb +83 -0
- data/lib/gitdocs/manager.rb +90 -60
- data/lib/gitdocs/migration/004_add_index_for_path.rb +1 -1
- data/lib/gitdocs/notifier.rb +70 -104
- data/lib/gitdocs/rendering_helper.rb +3 -0
- data/lib/gitdocs/repository.rb +324 -307
- data/lib/gitdocs/repository/committer.rb +77 -0
- data/lib/gitdocs/repository/path.rb +157 -140
- data/lib/gitdocs/search.rb +40 -25
- data/lib/gitdocs/settings_app.rb +5 -3
- data/lib/gitdocs/share.rb +64 -0
- data/lib/gitdocs/synchronizer.rb +40 -0
- data/lib/gitdocs/version.rb +1 -1
- data/lib/gitdocs/views/_header.haml +2 -2
- data/lib/gitdocs/views/dir.haml +3 -3
- data/lib/gitdocs/views/edit.haml +1 -1
- data/lib/gitdocs/views/file.haml +1 -1
- data/lib/gitdocs/views/home.haml +3 -3
- data/lib/gitdocs/views/layout.haml +13 -13
- data/lib/gitdocs/views/revisions.haml +3 -3
- data/lib/gitdocs/views/search.haml +1 -1
- data/lib/gitdocs/views/settings.haml +6 -6
- data/test/integration/cli/full_sync_test.rb +83 -0
- data/test/integration/cli/share_management_test.rb +29 -0
- data/test/integration/cli/status_test.rb +14 -0
- data/test/integration/test_helper.rb +185 -151
- data/test/integration/{browse_test.rb → web/browse_test.rb} +11 -29
- data/test/integration/web/share_management_test.rb +46 -0
- data/test/support/git_factory.rb +276 -0
- data/test/unit/browser_app_test.rb +346 -0
- data/test/unit/configuration_test.rb +8 -70
- data/test/unit/git_notifier_test.rb +116 -0
- data/test/unit/gitdocs_test.rb +90 -0
- data/test/unit/manager_test.rb +36 -0
- data/test/unit/notifier_test.rb +60 -124
- data/test/unit/repository_committer_test.rb +111 -0
- data/test/unit/repository_path_test.rb +92 -76
- data/test/unit/repository_test.rb +243 -356
- data/test/unit/search_test.rb +15 -0
- data/test/unit/settings_app_test.rb +80 -0
- data/test/unit/share_test.rb +97 -0
- data/test/unit/test_helper.rb +17 -3
- metadata +114 -108
- data/lib/gitdocs/runner.rb +0 -108
- data/lib/gitdocs/server.rb +0 -62
- data/test/integration/full_sync_test.rb +0 -66
- data/test/integration/share_management_test.rb +0 -95
- data/test/integration/status_test.rb +0 -21
- data/test/unit/runner_test.rb +0 -122
data/lib/gitdocs/runner.rb
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
|
3
|
-
module Gitdocs
|
4
|
-
class Runner
|
5
|
-
def self.start_all(shares)
|
6
|
-
runners = shares.map { |share| Runner.new(share) }
|
7
|
-
runners.each(&:run)
|
8
|
-
runners
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize(share)
|
12
|
-
@share = share
|
13
|
-
@polling_interval = share.polling_interval
|
14
|
-
@notifier = Gitdocs::Notifier.new(@share.notification)
|
15
|
-
@repository = Gitdocs::Repository.new(share)
|
16
|
-
end
|
17
|
-
|
18
|
-
def root
|
19
|
-
@repository.root
|
20
|
-
end
|
21
|
-
|
22
|
-
def run
|
23
|
-
return false unless @repository.valid?
|
24
|
-
|
25
|
-
@last_synced_revision = @repository.current_oid
|
26
|
-
|
27
|
-
mutex = Mutex.new
|
28
|
-
|
29
|
-
@notifier.info('Running gitdocs!', "Running gitdocs in '#{root}'")
|
30
|
-
|
31
|
-
# Pull changes from remote repository
|
32
|
-
syncer = proc do
|
33
|
-
EM.defer(proc do
|
34
|
-
mutex.synchronize { sync_changes }
|
35
|
-
end, proc do
|
36
|
-
EM.add_timer(@polling_interval) do
|
37
|
-
syncer.call
|
38
|
-
end
|
39
|
-
end)
|
40
|
-
end
|
41
|
-
syncer.call
|
42
|
-
# Listen for changes in local repository
|
43
|
-
|
44
|
-
EM.defer(proc do
|
45
|
-
listener = Guard::Listener.select_and_init(
|
46
|
-
root, watch_all_modifications: true
|
47
|
-
)
|
48
|
-
listener.on_change do |directories|
|
49
|
-
directories.uniq!
|
50
|
-
directories.delete_if { |d| d =~ /\/\.git/ }
|
51
|
-
unless directories.empty?
|
52
|
-
EM.next_tick do
|
53
|
-
EM.defer(proc do
|
54
|
-
mutex.synchronize { sync_changes }
|
55
|
-
end, proc {})
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
listener.start
|
60
|
-
end, proc { EM.stop_reactor })
|
61
|
-
end
|
62
|
-
|
63
|
-
def clear_state
|
64
|
-
@state = nil
|
65
|
-
end
|
66
|
-
|
67
|
-
def sync_changes
|
68
|
-
# Commit #################################################################
|
69
|
-
@repository.commit if @share.sync_type == 'full'
|
70
|
-
|
71
|
-
# Fetch ##################################################################
|
72
|
-
fetch_result = @repository.fetch
|
73
|
-
return unless fetch_result == :ok
|
74
|
-
return if @share.sync_type == 'fetch'
|
75
|
-
|
76
|
-
# Merge ##################################################################
|
77
|
-
merge_result = @repository.merge
|
78
|
-
merge_result = latest_author_count if merge_result == :ok
|
79
|
-
@notifier.merge_notification(merge_result, root)
|
80
|
-
return if merge_result.is_a?(String)
|
81
|
-
|
82
|
-
# Push ###################################################################
|
83
|
-
result = @repository.push
|
84
|
-
result = latest_author_count if result == :ok
|
85
|
-
@notifier.push_notification(result, root)
|
86
|
-
rescue => e
|
87
|
-
# Rescue any standard exceptions which come from the push related
|
88
|
-
# commands. This will prevent problems on a single share from killing
|
89
|
-
# the entire daemon.
|
90
|
-
@notifier.error("Unexpected error syncing changes in #{root}", "#{e}")
|
91
|
-
end
|
92
|
-
|
93
|
-
############################################################################
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
# Update the author count for the last synced changes, and then update the
|
98
|
-
# last synced revision id.
|
99
|
-
#
|
100
|
-
# @return [Hash<String,Int>]
|
101
|
-
def latest_author_count
|
102
|
-
last_oid = @last_synced_revision
|
103
|
-
@last_synced_revision = @repository.current_oid
|
104
|
-
|
105
|
-
@repository.author_count(last_oid)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
data/lib/gitdocs/server.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
|
3
|
-
require 'thin'
|
4
|
-
require 'gitdocs/browser_app'
|
5
|
-
require 'gitdocs/settings_app'
|
6
|
-
|
7
|
-
module Gitdocs
|
8
|
-
class Server
|
9
|
-
def initialize(manager, port = 8888, repositories)
|
10
|
-
@manager = manager
|
11
|
-
@port = port.to_i
|
12
|
-
@repositories = repositories
|
13
|
-
@search = Gitdocs::Search.new(repositories)
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.start_and_wait(manager, override_port, repositories)
|
17
|
-
return false unless manager.start_web_frontend
|
18
|
-
|
19
|
-
web_port = override_port || manager.web_frontend_port
|
20
|
-
server = Server.new(manager, web_port, repositories)
|
21
|
-
server.start
|
22
|
-
server.wait_for_start
|
23
|
-
true
|
24
|
-
end
|
25
|
-
|
26
|
-
def start
|
27
|
-
Gitdocs::SettingsApp.set :manager, @manager
|
28
|
-
Gitdocs::BrowserApp.set :repositories, @repositories
|
29
|
-
|
30
|
-
Thin::Logging.debug = @manager.debug
|
31
|
-
Thin::Server.start('127.0.0.1', @port) do
|
32
|
-
use Rack::Static,
|
33
|
-
urls: %w(/css /js /img /doc),
|
34
|
-
root: File.expand_path('../public', __FILE__)
|
35
|
-
use Rack::MethodOverride
|
36
|
-
|
37
|
-
map('/settings') { run Gitdocs::SettingsApp }
|
38
|
-
map('/') { run Gitdocs::BrowserApp }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def wait_for_start
|
43
|
-
wait_for_web_server = proc do
|
44
|
-
i = 0
|
45
|
-
begin
|
46
|
-
TCPSocket.open('127.0.0.1', @port).close
|
47
|
-
@manager.log('Web server running!')
|
48
|
-
rescue Errno::ECONNREFUSED
|
49
|
-
sleep 0.2
|
50
|
-
i += 1
|
51
|
-
if i <= 20
|
52
|
-
@manager.log('Retrying web server loop...')
|
53
|
-
retry
|
54
|
-
else
|
55
|
-
@manager.log('Web server failed to start')
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
EM.defer(wait_for_web_server)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
|
3
|
-
require File.expand_path('../test_helper', __FILE__)
|
4
|
-
|
5
|
-
describe 'fully synchronizing repositories' do
|
6
|
-
before do
|
7
|
-
git_clone_and_gitdocs_add(git_init_remote, 'clone1', 'clone2', 'clone3')
|
8
|
-
start_daemon
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'should sync new files' do
|
12
|
-
write_file('clone1/newfile', 'testing')
|
13
|
-
wait_for_clean_workdir('clone1')
|
14
|
-
|
15
|
-
wait_for_exact_file_content('clone1/newfile', 'testing')
|
16
|
-
wait_for_exact_file_content('clone2/newfile', 'testing')
|
17
|
-
wait_for_exact_file_content('clone3/newfile', 'testing')
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'should sync changes to an existing file' do
|
21
|
-
write_file('clone1/file', 'testing')
|
22
|
-
wait_for_clean_workdir('clone1')
|
23
|
-
|
24
|
-
wait_for_exact_file_content('clone3/file', 'testing')
|
25
|
-
append_to_file('clone3/file', "\nfoobar")
|
26
|
-
wait_for_clean_workdir('clone3')
|
27
|
-
|
28
|
-
wait_for_exact_file_content('clone1/file', "testing\nfoobar")
|
29
|
-
wait_for_exact_file_content('clone2/file', "testing\nfoobar")
|
30
|
-
wait_for_exact_file_content('clone3/file', "testing\nfoobar")
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'should sync empty directories' do
|
34
|
-
in_current_dir { _mkdir('clone1/empty_dir') }
|
35
|
-
wait_for_clean_workdir('clone1')
|
36
|
-
|
37
|
-
wait_for_directory('clone1/empty_dir')
|
38
|
-
wait_for_directory('clone2/empty_dir')
|
39
|
-
wait_for_directory('clone3/empty_dir')
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should mark unresolvable conflicts' do
|
43
|
-
write_file('clone1/file', 'testing')
|
44
|
-
wait_for_clean_workdir('clone1')
|
45
|
-
|
46
|
-
append_to_file('clone2/file', 'foobar')
|
47
|
-
append_to_file('clone3/file', 'deadbeef')
|
48
|
-
wait_for_clean_workdir('clone2')
|
49
|
-
wait_for_clean_workdir('clone3')
|
50
|
-
|
51
|
-
# HACK: Leaving in the sleep and standard checks.
|
52
|
-
# Trying to wait for the conflicts to be resolved does not seem to
|
53
|
-
# be working consistently when run on TravisCI. Hopefully this will.
|
54
|
-
sleep(6)
|
55
|
-
in_current_dir do
|
56
|
-
# Remember expected file counts include '.', '..', and '.git'
|
57
|
-
assert_includes(5..6, Dir.entries('clone1').count)
|
58
|
-
assert_includes(5..6, Dir.entries('clone2').count)
|
59
|
-
assert_includes(5..6, Dir.entries('clone3').count)
|
60
|
-
end
|
61
|
-
# TODO: Want to convert to these methods in the future
|
62
|
-
# wait_for_conflict_markers('clone1/file')
|
63
|
-
# wait_for_conflict_markers('clone2/file')
|
64
|
-
# wait_for_conflict_markers('clone3/file')
|
65
|
-
end
|
66
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
|
3
|
-
require File.expand_path('../test_helper', __FILE__)
|
4
|
-
|
5
|
-
describe 'Manage which shares are being watched' do
|
6
|
-
it 'should add a local repository' do
|
7
|
-
git_init_local
|
8
|
-
gitdocs_add
|
9
|
-
gitdocs_status
|
10
|
-
assert_gitdocs_status_contains(abs_current_dir('local'))
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'should add a remote repository' do
|
14
|
-
git_init_remote
|
15
|
-
abs_remote_path = abs_current_dir('remote')
|
16
|
-
cmd = "gitdocs create local #{abs_remote_path} --pid=gitdocs.pid"
|
17
|
-
run_simple(cmd, true, 15)
|
18
|
-
assert_success(true)
|
19
|
-
assert_partial_output('Added path local to doc list', output_from(cmd))
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should update a share through the UI' do
|
23
|
-
git_init_local
|
24
|
-
gitdocs_add
|
25
|
-
start_daemon
|
26
|
-
visit('http://localhost:7777/')
|
27
|
-
click_link('Settings')
|
28
|
-
|
29
|
-
within('#settings') do
|
30
|
-
within('#share-0') do
|
31
|
-
fill_in('share[0][polling_interval]', with: '0.2')
|
32
|
-
select('Fetch only', from: 'share[0][sync_type]')
|
33
|
-
end
|
34
|
-
click_button('Save')
|
35
|
-
end
|
36
|
-
|
37
|
-
# Allow the asynchronous portion of the update finish before checking
|
38
|
-
# the result.
|
39
|
-
sleep(1)
|
40
|
-
|
41
|
-
click_link('Settings')
|
42
|
-
within('#settings') do
|
43
|
-
within('#share-0') do
|
44
|
-
page.must_have_field('share[0][polling_interval]', with: '0.2')
|
45
|
-
page.must_have_field('share[0][sync_type]', with: 'fetch')
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe 'remove a share' do
|
51
|
-
before do
|
52
|
-
git_init_local
|
53
|
-
gitdocs_add
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'through CLI' do
|
57
|
-
cmd = 'gitdocs rm local --pid=gitdocs.pid'
|
58
|
-
run_simple(cmd, true, 15)
|
59
|
-
assert_success(true)
|
60
|
-
assert_partial_output('Removed path local from doc list', output_from(cmd))
|
61
|
-
|
62
|
-
gitdocs_status
|
63
|
-
assert_gitdocs_status_not_contain(abs_current_dir('local'))
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'through UI' do
|
67
|
-
start_daemon
|
68
|
-
visit('http://localhost:7777/')
|
69
|
-
click_link('Settings')
|
70
|
-
|
71
|
-
within('#settings') do
|
72
|
-
within('#share-0') { click_link('Delete') }
|
73
|
-
|
74
|
-
page.must_have_css('.share', count: 0)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'should clear all existing shares' do
|
80
|
-
%w(local1 local2 local3).each do |path|
|
81
|
-
git_init_local(path)
|
82
|
-
gitdocs_add(path)
|
83
|
-
end
|
84
|
-
|
85
|
-
cmd = 'gitdocs clear --pid=gitdocs.pid'
|
86
|
-
run_simple(cmd, true, 15)
|
87
|
-
assert_success(true)
|
88
|
-
assert_partial_output('Cleared paths from gitdocs', output_from(cmd))
|
89
|
-
|
90
|
-
gitdocs_status
|
91
|
-
assert_gitdocs_status_not_contain(abs_current_dir('local1'))
|
92
|
-
assert_gitdocs_status_not_contain(abs_current_dir('local2'))
|
93
|
-
assert_gitdocs_status_not_contain(abs_current_dir('local3'))
|
94
|
-
end
|
95
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
|
3
|
-
require File.expand_path('../test_helper', __FILE__)
|
4
|
-
|
5
|
-
describe 'CLI with display daemon and share status' do
|
6
|
-
it 'should display information about the daemon' do
|
7
|
-
gitdocs_status
|
8
|
-
assert_gitdocs_status_contains(Gitdocs::VERSION)
|
9
|
-
assert_gitdocs_status_contains('Running: false')
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should display information about the shares' do
|
13
|
-
git_clone_and_gitdocs_add(git_init_remote, 'clone1', 'clone2', 'clone3')
|
14
|
-
|
15
|
-
gitdocs_status
|
16
|
-
|
17
|
-
assert_gitdocs_status_contains(abs_current_dir('clone1'))
|
18
|
-
assert_gitdocs_status_contains(abs_current_dir('clone2'))
|
19
|
-
assert_gitdocs_status_contains(abs_current_dir('clone3'))
|
20
|
-
end
|
21
|
-
end
|
data/test/unit/runner_test.rb
DELETED
@@ -1,122 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
|
3
|
-
require File.expand_path('../test_helper', __FILE__)
|
4
|
-
|
5
|
-
describe 'gitdocs runner' do
|
6
|
-
let(:runner) { Gitdocs::Runner.new(share) }
|
7
|
-
|
8
|
-
let(:share) { stub(polling_interval: 1, notification: true) }
|
9
|
-
let(:notifier) { stub }
|
10
|
-
let(:repository) { stub(root: 'root_path') }
|
11
|
-
before do
|
12
|
-
Gitdocs::Notifier.stubs(:new).with(true).returns(notifier)
|
13
|
-
Gitdocs::Repository.stubs(:new).with(share).returns(repository)
|
14
|
-
end
|
15
|
-
|
16
|
-
describe '#root' do
|
17
|
-
subject { runner.root }
|
18
|
-
it { subject.must_equal 'root_path' }
|
19
|
-
end
|
20
|
-
|
21
|
-
describe '#sync_changes' do
|
22
|
-
subject { runner.sync_changes }
|
23
|
-
|
24
|
-
describe 'fetch sync' do
|
25
|
-
before do
|
26
|
-
share.stubs(:sync_type).returns('fetch')
|
27
|
-
repository.expects(:fetch).returns(fetch_result)
|
28
|
-
end
|
29
|
-
|
30
|
-
describe('fetch failure') { let(:fetch_result) { :not_ok } ; it { subject } }
|
31
|
-
describe('fetch success') { let(:fetch_result) { :ok } ; it { subject } }
|
32
|
-
end
|
33
|
-
|
34
|
-
describe 'full sync' do
|
35
|
-
before do
|
36
|
-
share.stubs(:sync_type).returns('full')
|
37
|
-
repository.expects(:commit)
|
38
|
-
repository.expects(:fetch).returns(fetch_result)
|
39
|
-
end
|
40
|
-
|
41
|
-
describe 'fetch failure' do
|
42
|
-
let(:fetch_result) { :not_ok }
|
43
|
-
it { subject }
|
44
|
-
end
|
45
|
-
|
46
|
-
describe 'when merge error' do
|
47
|
-
let(:fetch_result) { :ok }
|
48
|
-
before do
|
49
|
-
repository.expects(:merge).returns('error')
|
50
|
-
notifier.expects(:merge_notification).with('error', 'root_path')
|
51
|
-
end
|
52
|
-
it { subject }
|
53
|
-
end
|
54
|
-
|
55
|
-
describe 'when merge not_ok' do
|
56
|
-
let(:fetch_result) { :ok }
|
57
|
-
before do
|
58
|
-
repository.expects(:merge).returns(:not_ok)
|
59
|
-
notifier.expects(:merge_notification).with(:not_ok, 'root_path')
|
60
|
-
repository.expects(:push).returns(push_result)
|
61
|
-
end
|
62
|
-
|
63
|
-
describe 'and push is not_ok' do
|
64
|
-
let(:push_result) { :not_ok }
|
65
|
-
before { notifier.expects(:push_notification).with(:not_ok, 'root_path') }
|
66
|
-
it { subject }
|
67
|
-
end
|
68
|
-
|
69
|
-
describe 'and push is ok' do
|
70
|
-
let(:push_result) { :ok }
|
71
|
-
before do
|
72
|
-
runner.instance_variable_set(:@last_synced_revision, :oid)
|
73
|
-
repository.stubs(:current_oid).returns(:next_oid)
|
74
|
-
changes = { 'Alice' => 1, 'Bob' => 2 }
|
75
|
-
repository.stubs(:author_count).with(:oid).returns(changes)
|
76
|
-
notifier.expects(:push_notification).with(changes, 'root_path')
|
77
|
-
|
78
|
-
subject
|
79
|
-
end
|
80
|
-
it { runner.instance_variable_get(:@last_synced_revision).must_equal :next_oid }
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
describe 'merge ok' do
|
85
|
-
let(:fetch_result) { :ok }
|
86
|
-
|
87
|
-
before do
|
88
|
-
repository.stubs(:current_oid).returns(:merge_oid, :push_oid)
|
89
|
-
|
90
|
-
repository.expects(:merge).returns(:ok)
|
91
|
-
runner.instance_variable_set(:@last_synced_revision, :oid)
|
92
|
-
changes = { 'Alice' => 1, 'Bob' => 3 }
|
93
|
-
repository.stubs(:author_count).with(:oid).returns(changes)
|
94
|
-
notifier.expects(:merge_notification).with(changes, 'root_path')
|
95
|
-
repository.expects(:push).returns(push_result)
|
96
|
-
end
|
97
|
-
|
98
|
-
describe 'and push is not_ok' do
|
99
|
-
let(:push_result) { :not_ok }
|
100
|
-
before do
|
101
|
-
notifier.expects(:push_notification).with(:not_ok, 'root_path')
|
102
|
-
|
103
|
-
subject
|
104
|
-
end
|
105
|
-
it { runner.instance_variable_get(:@last_synced_revision).must_equal :merge_oid }
|
106
|
-
end
|
107
|
-
|
108
|
-
describe 'and push is ok' do
|
109
|
-
let(:push_result) { :ok }
|
110
|
-
before do
|
111
|
-
changes = { 'Charlie' => 5, 'Dan' => 7 }
|
112
|
-
repository.stubs(:author_count).with(:merge_oid).returns(changes)
|
113
|
-
notifier.expects(:push_notification).with(changes, 'root_path')
|
114
|
-
|
115
|
-
subject
|
116
|
-
end
|
117
|
-
it { runner.instance_variable_get(:@last_synced_revision).must_equal :push_oid }
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|