tlog 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +172 -30
- data/TODO +1 -0
- data/lib/tlog/application.rb +56 -56
- data/lib/tlog/command/active.rb +48 -48
- data/lib/tlog/command/checkout.rb +31 -31
- data/lib/tlog/command/create.rb +40 -40
- data/lib/tlog/command/delete.rb +21 -21
- data/lib/tlog/command/display.rb +195 -148
- data/lib/tlog/command/help.rb +33 -33
- data/lib/tlog/command/owner.rb +25 -25
- data/lib/tlog/command/points.rb +25 -25
- data/lib/tlog/command/pull.rb +18 -18
- data/lib/tlog/command/push.rb +18 -18
- data/lib/tlog/command/start.rb +35 -35
- data/lib/tlog/command/state.rb +25 -25
- data/lib/tlog/command/stop.rb +26 -26
- data/lib/tlog/command.rb +9 -8
- data/lib/tlog/command_suite.rb +29 -29
- data/lib/tlog/entity/active_log.rb +8 -8
- data/lib/tlog/entity/entry.rb +77 -77
- data/lib/tlog/entity/log.rb +161 -161
- data/lib/tlog/error.rb +3 -0
- data/lib/tlog/format/date_time.rb +4 -3
- data/lib/tlog/format/seconds.rb +10 -9
- data/lib/tlog/input.rb +6 -6
- data/lib/tlog/output.rb +28 -28
- data/lib/tlog/storage/disk.rb +326 -326
- data/lib/tlog.rb +1 -1
- metadata +2 -4
- data/lib/tlog/command/init.rb +0 -38
- data/lib/tlog/version.rb +0 -3
data/lib/tlog/command/delete.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
class Tlog::Command::Delete < Tlog::Command
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
def name
|
4
|
+
"delete"
|
5
|
+
end
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def description
|
8
|
+
"deletes a time log"
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def execute(input, output)
|
12
|
+
raise Tlog::Error::CommandInvalid, "Task does not exist" unless delete(input.args[0])
|
13
|
+
output.line("Deleted log '#{input.args[0]}'")
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def options(parser, options)
|
17
|
+
parser.banner = "usage: tlog delete <tlog_name>"
|
18
|
+
end
|
19
19
|
|
20
|
-
|
20
|
+
private
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
def delete(log_name)
|
23
|
+
storage.in_branch do |wd|
|
24
|
+
log = storage.require_log(log_name)
|
25
|
+
raise Tlog::Error::TimeLogNotFound, "Time log '#{log_name}' does not exist" unless log
|
26
|
+
storage.delete_log(log)
|
27
|
+
end
|
28
|
+
end
|
29
29
|
|
30
30
|
end
|
data/lib/tlog/command/display.rb
CHANGED
@@ -1,152 +1,199 @@
|
|
1
1
|
|
2
|
-
# I will forever love whoever re-writes this class
|
2
|
+
# I will forever love whoever re-writes this class
|
3
3
|
class Tlog::Command::Display < Tlog::Command
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
5
|
+
def name
|
6
|
+
"display"
|
7
|
+
end
|
8
|
+
|
9
|
+
def description
|
10
|
+
"displays information about time logs. command options contrain which time logs are displayed"
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute(input, output)
|
14
|
+
display(input.args[0], input.options, output)
|
15
|
+
end
|
16
|
+
|
17
|
+
def options(parser, options)
|
18
|
+
parser.banner = "usage: tlog display #{$0} [options]"
|
19
|
+
|
20
|
+
parser.on("-g", "--goal <goal_threshold>") do |goal|
|
21
|
+
options[:goal] = goal
|
22
|
+
end
|
23
|
+
|
24
|
+
parser.on("-o", "--owner a,b,c", Array, "Array of owners to display") do |owners|
|
25
|
+
options[:owners] = owners
|
26
|
+
end
|
27
|
+
|
28
|
+
parser.on("-p", "--points <points_threshold>") do |points|
|
29
|
+
options[:points] = points.to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
parser.on("-s", "--state a,b,c", Array, "Array of states to display") do |states|
|
33
|
+
options[:states] = states
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
# Methods that filter which logs should be displayed
|
39
|
+
|
40
|
+
def log_goal_valid(log, thresholds)
|
41
|
+
goal_threshold = thresholds[:goal]
|
42
|
+
goal_threshold = ChronicDuration.parse(goal_threshold)
|
43
|
+
return false unless log.goal
|
44
|
+
goal_threshold >= log.goal ? valid = true : valid = false
|
45
|
+
valid
|
46
|
+
end
|
47
|
+
|
48
|
+
def log_owners_valid(log, thresholds)
|
49
|
+
owners = thresholds[:owners]
|
50
|
+
owners.each do |owner|
|
51
|
+
return true if log.owner == owner
|
52
|
+
end
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def log_points_valid(log, thresholds)
|
57
|
+
points_value = thresholds[:points]
|
58
|
+
log.points >= points_value ? valid = true : valid = false
|
59
|
+
valid
|
60
|
+
end
|
61
|
+
|
62
|
+
def log_states_valid(log, thresholds)
|
63
|
+
states = thresholds[:states]
|
64
|
+
states.each do |state|
|
65
|
+
return true if log.state.downcase == state.downcase
|
66
|
+
end
|
67
|
+
false
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def display(log_name, options, output)
|
73
|
+
storage.in_branch do |wd|
|
74
|
+
if storage.all_log_dirs
|
75
|
+
if log_name
|
76
|
+
display_log(log_name, options, output)
|
77
|
+
else
|
78
|
+
display_all(options, output)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
output.line("No time logs yet");
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def display_log(log_name, options, output)
|
87
|
+
log = storage.require_log(log_name)
|
88
|
+
raise Tlog::Error::CommandInvalid, "Time log '#{log_name}' does not exist" unless log
|
89
|
+
|
90
|
+
log_length = log.goal_length
|
91
|
+
entries = log.entries
|
92
|
+
if storage.start_time_string && is_current_log_name?(log_name)
|
93
|
+
start_time = Time.parse(storage.start_time_string)
|
94
|
+
end
|
95
|
+
return unless log_valid?(log, options)
|
96
|
+
|
97
|
+
# Print out time log information
|
98
|
+
print_log_info(log, output)
|
99
|
+
print_header(output)
|
100
|
+
print_current(log_name, log_length, start_time, output)
|
101
|
+
display_entries(entries, output) if entries
|
102
|
+
print_footer(log, log_length, output)
|
103
|
+
end
|
104
|
+
|
105
|
+
def display_all(options, output)
|
106
|
+
storage.all_log_dirs.each do |log_path|
|
107
|
+
log_basename = log_path.basename.to_s
|
108
|
+
display_log(log_basename, options, output)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def log_valid?(log, thresholds = {})
|
113
|
+
thresholds.each do |key, value|
|
114
|
+
attribute_value = key.to_s
|
115
|
+
log_valid_method = "log_#{attribute_value}_valid"
|
116
|
+
if respond_to?(log_valid_method)
|
117
|
+
return false unless self.send(log_valid_method, log, thresholds)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
true
|
121
|
+
end
|
122
|
+
|
123
|
+
def display_entries(entries, output)
|
124
|
+
if entries.size > 0
|
125
|
+
entries.each do |entry|
|
126
|
+
out_str = "\t%-4s %16s %14s %s" % [
|
127
|
+
date_time_format.timestamp(entry.time[:start]),
|
128
|
+
date_time_format.timestamp(entry.time[:end]),
|
129
|
+
seconds_format.duration(entry.length.to_s),
|
130
|
+
entry.description,
|
131
|
+
]
|
132
|
+
output.line(out_str)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def print_footer(log, log_length, output)
|
138
|
+
output.line "-" * 100
|
139
|
+
print_total(log, output)
|
140
|
+
print_time_left(log, output)
|
141
|
+
end
|
142
|
+
|
143
|
+
def print_header(output)
|
144
|
+
output.line("\tStart End Duration Description")
|
145
|
+
end
|
146
|
+
|
147
|
+
def print_total(log, output)
|
148
|
+
#output.line("-") * 52
|
149
|
+
duration = log.duration
|
150
|
+
if storage.current_log_name == log.name
|
151
|
+
duration += storage.time_since_start
|
152
|
+
end
|
153
|
+
output.line("\tTotal%45s " % seconds_format.duration(duration))
|
154
|
+
end
|
155
|
+
|
156
|
+
def print_log_info(log, output)
|
157
|
+
out_str = "Log: #{log.name}\nState: #{log.state}\nPoints: #{log.points}\nOwner: #{log.owner}"
|
158
|
+
output.line_yellow(out_str)
|
159
|
+
end
|
160
|
+
|
161
|
+
def print_time_left(log, output)
|
162
|
+
if log.goal
|
163
|
+
log_goal = log.goal
|
164
|
+
if (storage.current_log_name == log.name)
|
165
|
+
current_time = Time.now - storage.cur_start_time
|
166
|
+
log_goal -= current_time.to_i
|
167
|
+
end
|
168
|
+
log_goal = 0 if log_goal < 0
|
169
|
+
output.line_red("\tTime left: %39s" % seconds_format.duration(log_goal))
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
#should be added to entries array, not its own seperate thing
|
174
|
+
def print_current(log_name, log_length, current_start_time, output)
|
175
|
+
if is_current_log_name?(log_name)
|
176
|
+
formatted_length = seconds_format.duration storage.time_since_start
|
177
|
+
out_str = out_str = "\t%-4s %16s %14s %s" % [
|
178
|
+
date_time_format.timestamp(current_start_time),
|
179
|
+
nil,
|
180
|
+
formatted_length,
|
181
|
+
storage.cur_entry_description,
|
182
|
+
]
|
183
|
+
output.line(out_str)
|
184
|
+
storage.time_since_start
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def update_log_length(log_length)
|
189
|
+
log_length - storage.time_since_start if log_length
|
190
|
+
end
|
191
|
+
|
192
|
+
def is_current_log_name?(log_name)
|
193
|
+
if storage.current_log_name == log_name
|
194
|
+
true
|
195
|
+
else
|
196
|
+
false
|
197
|
+
end
|
198
|
+
end
|
152
199
|
end
|
data/lib/tlog/command/help.rb
CHANGED
@@ -1,38 +1,38 @@
|
|
1
1
|
|
2
2
|
class Tlog::Command::Help < Tlog::Command
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
4
|
+
def name
|
5
|
+
"help"
|
6
|
+
end
|
7
|
+
|
8
|
+
def description
|
9
|
+
"outputs lists of commands and their descriptions"
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(input, output)
|
13
|
+
commands = Tlog::Command_Suite.commands
|
14
|
+
commands.sort! {|a,b| a.name <=> b.name}
|
15
|
+
max_name_length = 0
|
16
|
+
|
17
|
+
commands.each do |command|
|
18
|
+
name_length = command.name.length
|
19
|
+
max_name_length = name_length if name_length > max_name_length
|
20
|
+
end
|
21
|
+
|
22
|
+
output.line("usage: tlog <command>")
|
23
|
+
output.line(nil)
|
24
|
+
|
25
|
+
commands.each do |command|
|
26
|
+
line = sprintf("%-#{max_name_length}s %s", command.name, command.description)
|
27
|
+
output.line(line)
|
28
|
+
end
|
29
|
+
|
30
|
+
output.line(nil)
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
|
34
|
+
def options(parser, options)
|
35
|
+
parser.banner = "usage: tlog help"
|
36
|
+
end
|
37
37
|
|
38
38
|
end
|
data/lib/tlog/command/owner.rb
CHANGED
@@ -1,34 +1,34 @@
|
|
1
1
|
|
2
2
|
class Tlog::Command::Owner < Tlog::Command
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def name
|
5
|
+
"owner"
|
6
|
+
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def description
|
9
|
+
"changes the owner of the checked-out time log"
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def execute(input, output)
|
13
|
+
new_owner = input.args[0]
|
14
|
+
updated_log = change_owner(new_owner)
|
15
|
+
output.line("Changed owner of '#{updated_log.name}' to #{new_owner}")
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def options(parser, options)
|
19
|
+
parser.banner = "usage: tlog owner <new_owner>"
|
20
|
+
end
|
21
21
|
|
22
|
-
|
22
|
+
private
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
def change_owner(new_owner)
|
25
|
+
storage.in_branch do |wd|
|
26
|
+
checked_out_log = storage.checkout_value
|
27
|
+
raise Tlog::Error::CheckoutInvalid, "No time log is checked out" unless checked_out_log
|
28
|
+
log = storage.require_log(checked_out_log)
|
29
|
+
raise Tlog::Error::TimeLogNotFound, "Time log '#{checked_out_log}' does not exist" unless log
|
30
|
+
storage.change_log_owner(log, new_owner)
|
31
|
+
log
|
32
|
+
end
|
33
|
+
end
|
34
34
|
end
|
data/lib/tlog/command/points.rb
CHANGED
@@ -1,34 +1,34 @@
|
|
1
1
|
|
2
2
|
class Tlog::Command::Points < Tlog::Command
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def name
|
5
|
+
"points"
|
6
|
+
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def description
|
9
|
+
"changes the point value of the checked-out time log"
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def execute(input, output)
|
13
|
+
new_points_value = input.args[0]
|
14
|
+
update_log = change_state(new_points_value)
|
15
|
+
output.line("Changed points of '#{updated_log.name}' to #{new_points_value}")
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def options(parser, options)
|
19
|
+
parser.banner = "usage: tlog points <new_points_value>"
|
20
|
+
end
|
21
21
|
|
22
|
-
|
22
|
+
private
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
def change_state(points)
|
25
|
+
storage.in_branch do |wd|
|
26
|
+
checked_out_log = storage.checkout_value
|
27
|
+
raise Tlog::Error::CheckoutInvalid, "No time log is checked out" unless checked_out_log
|
28
|
+
log = storage.require_log(checked_out_log)
|
29
|
+
raise Tlog::Error::TimeLogNotFound, "Time log '#{checked_out_log}' does not exist" unless log
|
30
|
+
storage.change_log_points(log, points)
|
31
|
+
log
|
32
|
+
end
|
33
|
+
end
|
34
34
|
end
|
data/lib/tlog/command/pull.rb
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
|
2
2
|
class Tlog::Command::Pull < Tlog::Command
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def name
|
5
|
+
"pull"
|
6
|
+
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def description
|
9
|
+
"pulls time logs from upstream"
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
def execute(input, output)
|
13
|
+
pull_logs
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def options(parser, options)
|
17
|
+
parser.banner = "usage: tlog pull"
|
18
|
+
end
|
19
19
|
|
20
|
-
|
20
|
+
private
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
def pull_logs
|
23
|
+
storage.in_branch do |wd|
|
24
|
+
storage.pull_logs
|
25
|
+
end
|
26
|
+
end
|
27
27
|
end
|