gitwakatime 0.2.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +22 -0
- data/.gitignore +1 -0
- data/.travis.yml +2 -1
- data/README.md +7 -5
- data/Rakefile +9 -3
- data/bin/gitwakatime +1 -2
- data/gitwakatime.gemspec +2 -8
- data/lib/gitwakatime.rb +9 -3
- data/lib/gitwakatime/cli.rb +14 -2
- data/lib/gitwakatime/commit.rb +7 -3
- data/lib/gitwakatime/commited_file.rb +6 -5
- data/lib/gitwakatime/controller.rb +10 -7
- data/lib/gitwakatime/durations_calculator.rb +42 -0
- data/lib/gitwakatime/mapper.rb +8 -7
- data/lib/gitwakatime/query.rb +29 -57
- data/lib/gitwakatime/request.rb +24 -0
- data/lib/gitwakatime/request_builder.rb +36 -0
- data/lib/gitwakatime/timer.rb +8 -19
- data/lib/gitwakatime/version.rb +1 -1
- data/spec/cli_spec.rb +12 -4
- data/spec/commited_file_spec.rb +0 -1
- data/spec/durations_spec.rb +1 -15
- data/spec/fixtures/heartbeats.json +4222 -4516
- data/spec/fixtures/wakatime.yml +3 -0
- data/spec/mapper_spec.rb +2 -2
- data/spec/query_spec.rb +29 -13
- data/spec/request_builder_spec.rb +21 -0
- data/spec/spec_helper.rb +10 -24
- data/spec/timer_spec.rb +30 -14
- metadata +14 -24
- data/lib/gitwakatime/durations.rb +0 -96
data/spec/mapper_spec.rb
CHANGED
@@ -26,9 +26,9 @@ describe 'description' do
|
|
26
26
|
|
27
27
|
it 'maps files dependent commits' do
|
28
28
|
expect(
|
29
|
-
GitWakaTime::Commit.all.
|
29
|
+
GitWakaTime::Commit.all.find do |c|
|
30
30
|
c.sha == 'dcd748bd06b8a0f239d779bee4f1eaf1f4aa500d'
|
31
|
-
end.
|
31
|
+
end.commited_files.first.dependent_sha
|
32
32
|
).to eq '2254dd56976b5f32a2289438842e42a35a18ff86'
|
33
33
|
end
|
34
34
|
end
|
data/spec/query_spec.rb
CHANGED
@@ -1,35 +1,51 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe GitWakaTime::Query do
|
4
4
|
|
5
5
|
before(:each) do
|
6
6
|
GitWakaTime.config.git = Git.open(@wdir)
|
7
7
|
GitWakaTime::Mapper.new(start_at: Date.new(2015, 1, 24))
|
8
|
-
@commits = GitWakaTime::Commit
|
9
|
-
@files = GitWakaTime::CommitedFile
|
10
|
-
@query = GitWakaTime::Query.new(@commits, @files, File.basename(@wdir))
|
11
8
|
end
|
12
9
|
|
10
|
+
let(:start_at) { Date.new(2015, 1, 24) }
|
11
|
+
let(:end_at) { Date.new(2015, 2, 24) }
|
12
|
+
subject(:subject) { described_class.new(start_at, end_at, File.basename(@wdir)) }
|
13
|
+
|
13
14
|
before do
|
14
|
-
stub_request(:get,
|
15
|
-
.with(query: hash_including(:
|
15
|
+
stub_request(:get, /.*wakatime.com\/api\/v1\/users\/current\/heartbeats/)
|
16
|
+
.with(query: hash_including(:date))
|
16
17
|
.to_return(body: File.read('./spec/fixtures/heartbeats.json'), status: 200)
|
17
18
|
end
|
18
19
|
|
19
|
-
it '
|
20
|
-
heartbeats =
|
20
|
+
it 'will return an array of heartbeats' do
|
21
|
+
heartbeats = subject.call
|
21
22
|
|
22
23
|
expect(heartbeats).to be_a Array
|
23
24
|
expect(heartbeats.size).to eq 9 # 10ths is lonely
|
24
25
|
expect(heartbeats.last).to be_a GitWakaTime::Heartbeat
|
25
26
|
expect(heartbeats.last.branch).to eq 'master'
|
26
27
|
end
|
27
|
-
it 'produces valid search for api' do
|
28
28
|
|
29
|
-
|
29
|
+
describe 'caching' do
|
30
|
+
it 'when heartbeats after query date return true ' do
|
31
|
+
expect(GitWakaTime::Heartbeat).to receive(:max).with(:time)
|
32
|
+
.and_return(Time.now.to_s)
|
33
|
+
expect(subject.cached?(1.month.ago)).to eq(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'when heartbeats after query date are the same ' do
|
37
|
+
expect(GitWakaTime::Heartbeat).to receive(:max).with(:time)
|
38
|
+
.and_return(Time.now.to_s)
|
39
|
+
|
40
|
+
expect(subject.cached?(Date.today)).to eq(false)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'when no heartbeats present' do
|
44
|
+
expect(GitWakaTime::Heartbeat).to receive(:max).with(:time)
|
45
|
+
.and_return(nil)
|
46
|
+
|
47
|
+
expect(subject.cached?(Date.today)).to eq(false)
|
48
|
+
end
|
30
49
|
|
31
|
-
expect(heartbeats).to be_a Array
|
32
|
-
expect(heartbeats.first[:start].to_date).to eq Date.new(2015, 01, 29)
|
33
|
-
expect(heartbeats.first[:end].to_date).to eq Date.new(2015, 03, 05)
|
34
50
|
end
|
35
51
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GitWakaTime::RequestBuilder do
|
4
|
+
subject(:subject) { described_class.new(3.days.ago, Time.now).call }
|
5
|
+
|
6
|
+
it 'returns a array of hashes' do
|
7
|
+
expect(subject).to be_a(Array)
|
8
|
+
expect(subject.first).to be_a(Hash)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'has a hash per day' do
|
12
|
+
expect(subject.size).to eq(4)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'has a first hash will be for 3 days ago' do
|
16
|
+
expect(subject.first).to eq(
|
17
|
+
date: 3.days.ago.to_date,
|
18
|
+
show: 'file,branch,project,time,id'
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -6,7 +6,11 @@
|
|
6
6
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
7
|
ENV['thor_env'] = 'test'
|
8
8
|
ENV['waka_log'] = 'false'
|
9
|
+
require 'codeclimate-test-reporter'
|
10
|
+
CodeClimate::TestReporter.start
|
9
11
|
|
12
|
+
require 'webmock/rspec'
|
13
|
+
WebMock.disable_net_connect!(allow: 'codeclimate.com')
|
10
14
|
require 'gitwakatime'
|
11
15
|
|
12
16
|
RSpec.configure do |config|
|
@@ -21,38 +25,20 @@ RSpec.configure do |config|
|
|
21
25
|
GitWakaTime::Heartbeat.new.columns
|
22
26
|
end
|
23
27
|
|
24
|
-
config.
|
25
|
-
|
26
|
-
|
27
|
-
GitWakaTime::Heartbeat.truncate
|
28
|
+
config.around(:each) do |example|
|
29
|
+
DB.transaction(rollback: :always, auto_savepoint: true) { example.run }
|
30
|
+
end
|
28
31
|
|
29
|
-
|
32
|
+
config.before(:each) do
|
33
|
+
allow(
|
30
34
|
GitWakaTime.config
|
31
|
-
).to receive('user_name').and_return('Russell Osborne')
|
35
|
+
).to receive('user_name').and_return('Russell Osborne')
|
32
36
|
end
|
33
37
|
|
34
38
|
config.after(:all) do
|
35
39
|
FileUtils.rm_r(File.dirname(@wdir))
|
36
40
|
end
|
37
41
|
end
|
38
|
-
require 'codeclimate-test-reporter'
|
39
|
-
CodeClimate::TestReporter.start
|
40
|
-
require 'webmock/rspec'
|
41
|
-
|
42
|
-
WebMock.disable_net_connect!(allow: 'codeclimate.com')
|
43
|
-
|
44
|
-
def capture(stream)
|
45
|
-
begin
|
46
|
-
stream = stream.to_s
|
47
|
-
eval "$#{stream} = StringIO.new"
|
48
|
-
yield
|
49
|
-
result = eval("$#{stream}").string
|
50
|
-
ensure
|
51
|
-
eval("$#{stream} = #{stream.upcase}")
|
52
|
-
end
|
53
|
-
|
54
|
-
result
|
55
|
-
end
|
56
42
|
|
57
43
|
def set_file_paths
|
58
44
|
@test_dir = File.join(File.dirname(__FILE__))
|
data/spec/timer_spec.rb
CHANGED
@@ -2,29 +2,45 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'description' do
|
4
4
|
let(:git) { Git.open(@wdir) }
|
5
|
+
let(:heartbeat) { double(:heartbeat, sum: 1) }
|
6
|
+
let(:heartbeats) { double(:heartbeats, grep: [heartbeat, heartbeat]) }
|
5
7
|
|
6
8
|
before do
|
7
|
-
stub_request(:get,
|
8
|
-
|
9
|
-
|
9
|
+
stub_request(:get, /.*wakatime.com\/api\/v1\/heartbeats/)
|
10
|
+
.with(query: hash_including(:date))
|
11
|
+
.to_return(body: File.read('./spec/fixtures/heartbeats.json'), status: 200)
|
12
|
+
|
13
|
+
# Prevent any callbacks to git.
|
14
|
+
# TODO: Refactor callbacks.
|
15
|
+
GitWakaTime.config.git = nil
|
10
16
|
end
|
11
17
|
|
12
|
-
it 'can be run on dummy' do
|
13
|
-
GitWakaTime.config.git = git
|
14
|
-
GitWakaTime::Mapper.new(start_at: Date.new(2015, 1, 24))
|
15
|
-
heartbeats = GitWakaTime::Query.new(
|
16
|
-
GitWakaTime::Commit, GitWakaTime::CommitedFile, File.basename(@wdir)
|
17
|
-
).get
|
18
|
+
it 'can be run on dummy with no heartbeats' do
|
18
19
|
timer = GitWakaTime::Timer.new(
|
19
|
-
GitWakaTime::Commit.all,
|
20
|
+
GitWakaTime::Commit.all, GitWakaTime::Heartbeat
|
20
21
|
).process
|
21
22
|
|
22
23
|
# # UTC breaks heartbeats of 1 day
|
23
24
|
# expect(timer.size).to eq 1
|
24
25
|
# With 7 relevant commits
|
25
|
-
expect(timer
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
expect(timer).to eq Hash.new
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can be run on dummy with no heartbeats' do
|
30
|
+
c1 = GitWakaTime::Commit.create(sha: 'e493d6f2ab2a702fa7f9c168b852a3b44c524f08', parent_sha: '4c1ea35f9a811a0ef79da15ec85f25fce4c446ba', project: 'dummy', time_in_seconds: 0, date: Time.parse('2015-01-30 03:26:12 UTC'), message: 'conflicting commit on master.', author: 'Russell Osborne')
|
31
|
+
c2 = GitWakaTime::Commit.create(sha: 'd642b3c04c3025655a9c33e32b9d530696dcf7cc', parent_sha: '4c1ea35f9a811a0ef79da15ec85f25fce4c446ba', project: 'dummy', time_in_seconds: 0, date: Time.parse('2015-01-30 03:26:05 UTC'), message: 'another commit on dev.', author: 'Russell Osborne')
|
32
|
+
GitWakaTime::CommitedFile.create(commit_id: c1.id, dependent_sha: '4c1ea35f9a811a0ef79da15ec85f25fce4c446ba', dependent_date: Time.parse('2015-01-30 01:00:00 UTC'), time_in_seconds: 0, sha: 'd642b3c04c3025655a9c33e32b9d530696dcf7cc', name: '/dummy/spec/commit_spec.rb', entity: nil, project: 'dummy')
|
33
|
+
GitWakaTime::CommitedFile.create(commit_id: c2.id, dependent_sha: '4c1ea35f9a811a0ef79da15ec85f25fce4c446ba', dependent_date: Time.parse('2015-01-30 02:00:00 UTC'), time_in_seconds: 0, sha: 'd642b3c04c3025655a9c33e32b9d530696dcf7cc', name: '/dummy/lib/dummy/timer.rb', entity: nil, project: 'dummy')
|
34
|
+
GitWakaTime::Heartbeat.create(time: Time.parse('2015-01-30 02:33:00 UTC'), duration: 500, entity: '/dummy/spec/commit_spec.rb', type: 'file', branch: 'master', project: 'dummy')
|
35
|
+
GitWakaTime::Heartbeat.create(time: Time.parse('2015-01-30 02:31:54 UTC'), duration: 333, entity: '/dummy/lib/dummy/timer.rb', type: 'file', branch: 'master', project: 'dummy')
|
36
|
+
|
37
|
+
timer = GitWakaTime::Timer.new(
|
38
|
+
GitWakaTime::Commit.all, GitWakaTime::Heartbeat
|
39
|
+
).process
|
40
|
+
|
41
|
+
# One hash key per day
|
42
|
+
expect(timer.size).to eq 1
|
43
|
+
expect(timer[Date.new(2015, 1, 30)]).to be_a(Array)
|
44
|
+
expect(timer[Date.new(2015, 1, 30)].map(&:time_in_seconds).compact.reduce(&:+)).to eq(500 + 333)
|
29
45
|
end
|
30
46
|
end
|
metadata
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitwakatime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
- Jonas Arvidsson
|
9
|
-
- Yuji Nakayama
|
7
|
+
- Russell Osborne
|
10
8
|
autorequire:
|
11
9
|
bindir: bin
|
12
10
|
cert_chain: []
|
13
|
-
date: 2015-
|
11
|
+
date: 2015-12-18 00:00:00.000000000 Z
|
14
12
|
dependencies:
|
15
13
|
- !ruby/object:Gem::Dependency
|
16
14
|
name: git
|
@@ -40,20 +38,6 @@ dependencies:
|
|
40
38
|
- - ">="
|
41
39
|
- !ruby/object:Gem::Version
|
42
40
|
version: 0.0.2
|
43
|
-
- !ruby/object:Gem::Dependency
|
44
|
-
name: logger
|
45
|
-
requirement: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - ">="
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '0'
|
50
|
-
type: :runtime
|
51
|
-
prerelease: false
|
52
|
-
version_requirements: !ruby/object:Gem::Requirement
|
53
|
-
requirements:
|
54
|
-
- - ">="
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: '0'
|
57
41
|
- !ruby/object:Gem::Dependency
|
58
42
|
name: thor
|
59
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -208,9 +192,8 @@ dependencies:
|
|
208
192
|
- - ">="
|
209
193
|
- !ruby/object:Gem::Version
|
210
194
|
version: '0'
|
211
|
-
description:
|
212
|
-
|
213
|
-
Aims to enforce the community-driven Ruby Style Guide.
|
195
|
+
description: "A Tool that will compile git data with wakatime\n data
|
196
|
+
to establish time per commit "
|
214
197
|
email:
|
215
198
|
- russosborn@gmail.com
|
216
199
|
executables:
|
@@ -218,6 +201,7 @@ executables:
|
|
218
201
|
extensions: []
|
219
202
|
extra_rdoc_files: []
|
220
203
|
files:
|
204
|
+
- ".codeclimate.yml"
|
221
205
|
- ".gitignore"
|
222
206
|
- ".rspec"
|
223
207
|
- ".travis.yml"
|
@@ -232,11 +216,13 @@ files:
|
|
232
216
|
- lib/gitwakatime/commit.rb
|
233
217
|
- lib/gitwakatime/commited_file.rb
|
234
218
|
- lib/gitwakatime/controller.rb
|
235
|
-
- lib/gitwakatime/
|
219
|
+
- lib/gitwakatime/durations_calculator.rb
|
236
220
|
- lib/gitwakatime/heartbeat.rb
|
237
221
|
- lib/gitwakatime/log.rb
|
238
222
|
- lib/gitwakatime/mapper.rb
|
239
223
|
- lib/gitwakatime/query.rb
|
224
|
+
- lib/gitwakatime/request.rb
|
225
|
+
- lib/gitwakatime/request_builder.rb
|
240
226
|
- lib/gitwakatime/timer.rb
|
241
227
|
- lib/gitwakatime/version.rb
|
242
228
|
- spec/cli_spec.rb
|
@@ -292,8 +278,10 @@ files:
|
|
292
278
|
- spec/dummy/readme
|
293
279
|
- spec/durations_spec.rb
|
294
280
|
- spec/fixtures/heartbeats.json
|
281
|
+
- spec/fixtures/wakatime.yml
|
295
282
|
- spec/mapper_spec.rb
|
296
283
|
- spec/query_spec.rb
|
284
|
+
- spec/request_builder_spec.rb
|
297
285
|
- spec/spec_helper.rb
|
298
286
|
- spec/timer_spec.rb
|
299
287
|
homepage: ''
|
@@ -316,7 +304,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
316
304
|
version: '0'
|
317
305
|
requirements: []
|
318
306
|
rubyforge_project:
|
319
|
-
rubygems_version: 2.
|
307
|
+
rubygems_version: 2.4.5.1
|
320
308
|
signing_key:
|
321
309
|
specification_version: 4
|
322
310
|
summary: A Tool that will compile git data with wakatime data to establish time per
|
@@ -375,7 +363,9 @@ test_files:
|
|
375
363
|
- spec/dummy/readme
|
376
364
|
- spec/durations_spec.rb
|
377
365
|
- spec/fixtures/heartbeats.json
|
366
|
+
- spec/fixtures/wakatime.yml
|
378
367
|
- spec/mapper_spec.rb
|
379
368
|
- spec/query_spec.rb
|
369
|
+
- spec/request_builder_spec.rb
|
380
370
|
- spec/spec_helper.rb
|
381
371
|
- spec/timer_spec.rb
|
@@ -1,96 +0,0 @@
|
|
1
|
-
module GitWakaTime
|
2
|
-
# Extract Duration Data from Heartbeats for the WAKATIME API
|
3
|
-
class Durations
|
4
|
-
attr_accessor :heartbeats
|
5
|
-
def initialize(args)
|
6
|
-
return @heartbeats = args[:heartbeats] if args[:heartbeats]
|
7
|
-
fail if args[:project].nil?
|
8
|
-
@project = args[:project]
|
9
|
-
@args = args
|
10
|
-
@session = Wakatime::Session.new(api_key: GitWakaTime.config.api_key)
|
11
|
-
@client = Wakatime::Client.new(@session)
|
12
|
-
@heartbeats = []
|
13
|
-
end
|
14
|
-
|
15
|
-
def load_heartbeats
|
16
|
-
unless cached?
|
17
|
-
|
18
|
-
Log.new "querying WakaTime heartbeats for #{@project}"
|
19
|
-
time = Benchmark.realtime do
|
20
|
-
@heartbeats = @client.heartbeats(@args)
|
21
|
-
|
22
|
-
# remove returned heartbeats that do not have the project we want
|
23
|
-
@heartbeats = @heartbeats.keep_if do |a|
|
24
|
-
a['project'] == @project
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
Log.new "API took #{time}s"
|
29
|
-
persist_heartbeats_localy(@heartbeats)
|
30
|
-
end
|
31
|
-
true
|
32
|
-
end
|
33
|
-
|
34
|
-
def persist_heartbeats_localy(heartbeats)
|
35
|
-
heartbeats.map do |heartbeat|
|
36
|
-
heartbeat['uuid'] = heartbeat['id']
|
37
|
-
heartbeat['time'] = Time.at(heartbeat['time'])
|
38
|
-
heartbeat.delete('id')
|
39
|
-
Heartbeat.find_or_create(uuid: heartbeat['uuid']) do |a|
|
40
|
-
a.update(heartbeat)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def cached?
|
46
|
-
# Check to see if this date range might be stale?
|
47
|
-
if cached_heartbeats.count > 0
|
48
|
-
max_local_timetamp = (
|
49
|
-
Time.parse(cached_heartbeats.max(:time)) + 15.day
|
50
|
-
).to_date
|
51
|
-
!(
|
52
|
-
@args[:start].to_date..@args[:end].to_date
|
53
|
-
).include?(max_local_timetamp)
|
54
|
-
else
|
55
|
-
false
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def cached_heartbeats
|
60
|
-
Heartbeat.where('time >= ?', @args[:end]).where(project: @project)
|
61
|
-
end
|
62
|
-
|
63
|
-
def heartbeats_to_durations(_project = nil, timeout = 15)
|
64
|
-
durations = []
|
65
|
-
current = nil
|
66
|
-
|
67
|
-
@heartbeats.each do | heartbeat |
|
68
|
-
# the first heartbeat just sets state and does nothing
|
69
|
-
unless current.nil?
|
70
|
-
|
71
|
-
# get duration since last heartbeat
|
72
|
-
duration = heartbeat.time.round - current.time.round
|
73
|
-
|
74
|
-
duration = 0.0 if duration < 0
|
75
|
-
|
76
|
-
# duration not logged if greater than the timeout
|
77
|
-
if duration < timeout * 60
|
78
|
-
|
79
|
-
# add duration to current heartbeat
|
80
|
-
current.duration = duration
|
81
|
-
|
82
|
-
# save to local db
|
83
|
-
current.save
|
84
|
-
|
85
|
-
# log current heartbeat as a duration
|
86
|
-
durations << current
|
87
|
-
end
|
88
|
-
end
|
89
|
-
# set state (re-start the clock)
|
90
|
-
current = heartbeat
|
91
|
-
|
92
|
-
end
|
93
|
-
durations
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|