tlog 0.2.0 → 0.2.1
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 +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
|