ttrack 0.1.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.
- data/bin/ttrack +23 -0
- data/lib/ttrack/datastore.rb +137 -0
- data/lib/ttrack.rb +164 -0
- metadata +59 -0
data/bin/ttrack
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/Users/alex/.rvm/rubies/ruby-1.9.2-p290/bin/ruby -w
|
2
|
+
require 'ttrack'
|
3
|
+
|
4
|
+
tt = TTrack.new
|
5
|
+
case ARGV[0]
|
6
|
+
when 'start' then
|
7
|
+
tt.start ARGV[1], ARGV[2]
|
8
|
+
when 'stop' then
|
9
|
+
tt.stop
|
10
|
+
when 'status' then
|
11
|
+
tt.status ARGV[1]
|
12
|
+
when 'init' then
|
13
|
+
tt.init
|
14
|
+
when 'report' then
|
15
|
+
tt.report ARGV[1]
|
16
|
+
when 'beguin' then
|
17
|
+
timestamp = ARGV[3] ? "%s %s" % ARGV[2..3] : ARGV[2]
|
18
|
+
tt.setstart ARGV[1], timestamp
|
19
|
+
when 'end' then
|
20
|
+
timestamp = ARGV[3] ? "%s %s" % ARGV[2..3] : ARGV[2]
|
21
|
+
tt.setstop ARGV[1], timestamp
|
22
|
+
else tt.usage
|
23
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'sqlite3'
|
3
|
+
|
4
|
+
class TTrack::DataStore
|
5
|
+
|
6
|
+
def initialize dbname=".timetrackerdb", timezone="+02:00", version='v0.1.0', verbosity=0
|
7
|
+
@dbname = dbname
|
8
|
+
@timezone = timezone
|
9
|
+
@version = version
|
10
|
+
@verbosity = verbosity
|
11
|
+
|
12
|
+
if FileTest.zero?(dbname) or not FileTest.file?(dbname)
|
13
|
+
@db = SQLite3::Database.new( dbname )
|
14
|
+
createschema
|
15
|
+
init(timezone, version, verbosity)
|
16
|
+
else
|
17
|
+
@db = SQLite3::Database.open( dbname )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def createschema
|
23
|
+
@db.execute <<-SQL
|
24
|
+
CREATE TABLE system (
|
25
|
+
current,
|
26
|
+
latest,
|
27
|
+
timezone NOT NULL,
|
28
|
+
version INTEGER NOT NULL,
|
29
|
+
verbosity NOT NULL,
|
30
|
+
redmine
|
31
|
+
)
|
32
|
+
SQL
|
33
|
+
|
34
|
+
@db.execute <<-SQL
|
35
|
+
CREATE TABLE timesheet (
|
36
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
37
|
+
name,
|
38
|
+
tstart DEFAULT CURRENT_TIMESTAMP,
|
39
|
+
tstop,
|
40
|
+
synced DEFAULT 'false',
|
41
|
+
notes
|
42
|
+
)
|
43
|
+
SQL
|
44
|
+
end
|
45
|
+
|
46
|
+
def init timezone, version, verbosity
|
47
|
+
@db.execute 'INSERT INTO system ( timezone, version, verbosity ) VALUES ( "%s", "%s", "%s" )' %
|
48
|
+
[timezone, version, verbosity]
|
49
|
+
end
|
50
|
+
|
51
|
+
def droptables
|
52
|
+
for table in ['system', 'timesheet']
|
53
|
+
@db.execute 'DROP TABLE IF EXISTS %s' % table
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def setcurrent issueid
|
58
|
+
oldcurrent = @db.execute 'SELECT current, latest FROM system'
|
59
|
+
@db.execute "UPDATE system SET current = '%d', latest = '%s'" %
|
60
|
+
[issueid, oldcurrent[0][0] != '' ? oldcurrent[0][0] : oldcurrent[0][1]]
|
61
|
+
end
|
62
|
+
|
63
|
+
public
|
64
|
+
def getcurrent
|
65
|
+
current = @db.execute "SELECT current FROM system"
|
66
|
+
current[0][0] == "" ? nil : current[0][0]
|
67
|
+
end
|
68
|
+
|
69
|
+
def getstatus
|
70
|
+
current = getcurrent
|
71
|
+
if current
|
72
|
+
status = @db.execute "SELECT id,name FROM timesheet WHERE id=%d" % current
|
73
|
+
status[0]
|
74
|
+
else
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def startnew issuename, notes=''
|
80
|
+
@db.execute "INSERT INTO timesheet ( name, notes ) VALUES ( '%s', '%s' )" %
|
81
|
+
[issuename, notes]
|
82
|
+
latest = @db.execute "SELECT id FROM timesheet ORDER BY id DESC LIMIT 1"
|
83
|
+
setcurrent latest[0][0]
|
84
|
+
end
|
85
|
+
|
86
|
+
def stoprunning
|
87
|
+
current = getcurrent
|
88
|
+
if current
|
89
|
+
@db.execute "UPDATE timesheet set tstop = datetime('now') WHERE id = %d" % current
|
90
|
+
@db.execute "UPDATE system SET current = '', latest = '%d'" % current
|
91
|
+
else
|
92
|
+
p "Not tracking"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def gettime issueid=false
|
97
|
+
issueid = issueid ? issueid : getcurrent
|
98
|
+
if issueid
|
99
|
+
time = @db.execute "SELECT tstart,tstop FROM timesheet WHERE id=%d" % issueid
|
100
|
+
time[0]
|
101
|
+
else
|
102
|
+
false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def gettimesbyissuename issuename
|
107
|
+
@db.execute "SELECT tstart,tstop FROM timesheet WHERE name='%s'" % issuename
|
108
|
+
end
|
109
|
+
|
110
|
+
def getissuesandtimesbyname issuename
|
111
|
+
@db.execute "SELECT tstart,tstop FROM timesheet WHERE name='%s'" % issuename
|
112
|
+
end
|
113
|
+
|
114
|
+
def getissuesidsbyname issuename
|
115
|
+
@db.execute "SELECT id,tstart,tstop,notes FROM timesheet WHERE name='%s'" % issuename
|
116
|
+
end
|
117
|
+
|
118
|
+
def settstart id, tstart
|
119
|
+
@db.execute "UPDATE timesheet SET tstart=datetime('%s') WHERE id=%d" % [tstart, id]
|
120
|
+
end
|
121
|
+
|
122
|
+
def settstop id, tstop
|
123
|
+
@db.execute "UPDATE timesheet SET tstop=datetime('%s') WHERE id=%d" % [tstop, id]
|
124
|
+
end
|
125
|
+
|
126
|
+
def isissue? id
|
127
|
+
r = @db.execute "SELECT id from timesheet WHERE id=%d" % id
|
128
|
+
r[0].nil? ? false : true
|
129
|
+
end
|
130
|
+
|
131
|
+
def cleanup
|
132
|
+
droptables
|
133
|
+
createschema
|
134
|
+
init(@timezone, @version, @verbosity)
|
135
|
+
end
|
136
|
+
|
137
|
+
end # End DataStore class
|
data/lib/ttrack.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
class TTrack
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@db = DataStore.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def start issuename, notes
|
9
|
+
unless issuename.nil?
|
10
|
+
if @db.getcurrent
|
11
|
+
@db.stoprunning
|
12
|
+
end
|
13
|
+
@db.startnew issuename, notes
|
14
|
+
else
|
15
|
+
usage
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def stop
|
20
|
+
@db.stoprunning
|
21
|
+
end
|
22
|
+
|
23
|
+
def status issuename
|
24
|
+
unless issuename
|
25
|
+
status = @db.getstatus
|
26
|
+
if status
|
27
|
+
delta = Time.now - gettstart(@db.getcurrent)
|
28
|
+
puts "Task '%s' run time: %d seconds (%.2f hours)" % [status[1], delta, delta / 3600]
|
29
|
+
else
|
30
|
+
puts "Not tracking"
|
31
|
+
end
|
32
|
+
else
|
33
|
+
total = gettotalissueduration(issuename)
|
34
|
+
unless total == 0
|
35
|
+
puts "Total seconds for task %s: %d (%.2f hours)" %
|
36
|
+
[
|
37
|
+
issuename,
|
38
|
+
total,
|
39
|
+
total / 3600
|
40
|
+
]
|
41
|
+
else
|
42
|
+
puts "No entry for issue '%s'" % issuename
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def report issuename
|
48
|
+
r = @db.getissuesidsbyname issuename
|
49
|
+
unless r[0].nil?
|
50
|
+
puts "id | tstart | tstop | notes"
|
51
|
+
r.each do |x|
|
52
|
+
puts "%s | %s | %s | %s" % x
|
53
|
+
end
|
54
|
+
else
|
55
|
+
usage
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def setstart issueid, timestamp
|
60
|
+
if validateissueid issueid
|
61
|
+
t = validatetimestamp timestamp
|
62
|
+
@db.settstart issueid, t
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def setstop issueid, timestamp
|
67
|
+
if validateissueid issueid
|
68
|
+
t = validatetimestamp timestamp
|
69
|
+
@db.settstop issueid, t
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def init
|
74
|
+
@db.cleanup
|
75
|
+
end
|
76
|
+
|
77
|
+
def usage
|
78
|
+
puts "Usage: ttrack [start|stop|status|init|report|begin|end] issue_name"
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
def gettimeobject timestamp
|
83
|
+
if timestamp
|
84
|
+
Time.utc(
|
85
|
+
timestamp[0..3],
|
86
|
+
timestamp[5..6],
|
87
|
+
timestamp[8..9],
|
88
|
+
timestamp[11..12],
|
89
|
+
timestamp[14..15],
|
90
|
+
timestamp[17..18]
|
91
|
+
)
|
92
|
+
else
|
93
|
+
Time.now
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def validatetimestamp timestamp
|
98
|
+
t = Time.utc(
|
99
|
+
timestamp[0..3],
|
100
|
+
timestamp[5..6],
|
101
|
+
timestamp[8..9],
|
102
|
+
timestamp[11..12],
|
103
|
+
timestamp[14..15],
|
104
|
+
timestamp[17..18]
|
105
|
+
)
|
106
|
+
"%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % [
|
107
|
+
t.year,
|
108
|
+
t.month,
|
109
|
+
t.day,
|
110
|
+
t.hour,
|
111
|
+
t.min,
|
112
|
+
t.sec
|
113
|
+
]
|
114
|
+
end
|
115
|
+
|
116
|
+
def validateissueid issueid
|
117
|
+
unless @db.isissue? issueid
|
118
|
+
puts "Issueid invalid"
|
119
|
+
false
|
120
|
+
else
|
121
|
+
true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def gettotalissueduration issuename
|
126
|
+
r = @db.getissuesandtimesbyname(issuename)
|
127
|
+
total = 0
|
128
|
+
r.each do |timestamps|
|
129
|
+
if timestamps[0]
|
130
|
+
t0, t1 = gettimeobject(timestamps[0]), gettimeobject(timestamps[1])
|
131
|
+
total = total + (t1 - t0)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
total
|
135
|
+
end
|
136
|
+
|
137
|
+
def getissueduration issueid
|
138
|
+
timestamps = @db.gettime issueid
|
139
|
+
if timestamps and timestamps[1]
|
140
|
+
t0, t1 = gettimeobject(timestamps[0]), gettimeobject(timestamps[1])
|
141
|
+
t1 - t0
|
142
|
+
else
|
143
|
+
false
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def gettstart issueid
|
148
|
+
timestamps = @db.gettime issueid
|
149
|
+
unless timestamps[0].nil?
|
150
|
+
gettimeobject timestamps[0]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def gettstop issueid
|
155
|
+
timestamps = @db.gettime issueid
|
156
|
+
unless timestamps[1].nil?
|
157
|
+
gettimeobject timestamps[1]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end # End TTrack class
|
162
|
+
|
163
|
+
require 'ttrack/datastore'
|
164
|
+
# TODO: add support for timezone
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ttrack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexander Fortin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-30 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sqlite3
|
16
|
+
requirement: &70137978508080 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.3.6
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70137978508080
|
25
|
+
description: A simple CLI time tracker
|
26
|
+
email: alexander.fortin@gmail.com
|
27
|
+
executables:
|
28
|
+
- ttrack
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- lib/ttrack.rb
|
33
|
+
- lib/ttrack/datastore.rb
|
34
|
+
- bin/ttrack
|
35
|
+
homepage: https://rubygems.org/gems/ttrack
|
36
|
+
licenses: []
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.8.10
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: Time Tracker
|
59
|
+
test_files: []
|