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/storage/disk.rb
CHANGED
@@ -1,331 +1,331 @@
|
|
1
1
|
|
2
2
|
class Tlog::Storage::Disk
|
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
|
-
|
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
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
4
|
+
attr_accessor :git
|
5
|
+
attr_accessor :tlog_dir
|
6
|
+
attr_accessor :tlog_working
|
7
|
+
attr_accessor :tlog_index
|
8
|
+
attr_accessor :working_dir
|
9
|
+
|
10
|
+
def initialize(git_dir)
|
11
|
+
@git = Git.open(find_repo(git_dir))
|
12
|
+
proj_path = @git.dir.path.downcase.gsub(/[^a-z0-9]+/i, '-')
|
13
|
+
|
14
|
+
@tlog_dir = '~/.tlog'
|
15
|
+
@tlog_working = File.expand_path(File.join(@tlog_dir, proj_path, 'working'))
|
16
|
+
@tlog_index = File.expand_path(File.join(@tlog_dir, proj_path, 'index'))
|
17
|
+
|
18
|
+
bs = git.lib.branches_all.map{|b| b.first}
|
19
|
+
|
20
|
+
unless(bs.include?('tlog') && File.directory?(@tlog_working))
|
21
|
+
init_tlog_branch(bs.include?('tlog'))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def checkout_log(log)
|
26
|
+
File.open(checkout_path, 'w'){|f| f.write(log.name)}
|
27
|
+
git.add
|
28
|
+
git.commit("Checking out time log '#{log.name}'")
|
29
|
+
end
|
30
|
+
|
31
|
+
def checkout_value
|
32
|
+
read_file(checkout_path) if File.exists?(checkout_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_log(log, options = {})
|
36
|
+
log.path = log_path(log.name)
|
37
|
+
options[:owner] = cur_user
|
38
|
+
if log.create(options)
|
39
|
+
git.add
|
40
|
+
git.commit("Created log '#{log.name}'")
|
41
|
+
true
|
42
|
+
else
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def push_logs
|
48
|
+
git.push('origin', 'tlog:tlog')
|
49
|
+
end
|
50
|
+
|
51
|
+
def pull_logs
|
52
|
+
git.pull('origin', 'origin/tlog')
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete_log(log)
|
56
|
+
log.path = log_path(log.name)
|
57
|
+
log.delete
|
58
|
+
delete_current(log.name)
|
59
|
+
delete_checkout(log.name)
|
60
|
+
|
61
|
+
# Recursively removes the directory that stores the time log
|
62
|
+
git.remove(log.path, {:recursive => "-r"})
|
63
|
+
git.commit("Deleted log '#{log.name}'")
|
64
|
+
end
|
65
|
+
|
66
|
+
def require_log(log_name)
|
67
|
+
decode_log_path(Pathname.new(log_path(log_name))) if logs_path
|
68
|
+
end
|
69
|
+
|
70
|
+
def start_log(log, entry_description)
|
71
|
+
entry_description = '(no description)' unless entry_description
|
72
|
+
if update_current(log.name, entry_description)
|
73
|
+
create_log(log) # Creates directory if it has not already been created
|
74
|
+
git.add
|
75
|
+
git.commit("Started log '#{log.name}'")
|
76
|
+
true
|
77
|
+
else
|
78
|
+
false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def stop_log(log)
|
83
|
+
if Dir.exists?(current_path) and log.name == checkout_value
|
84
|
+
current_hash = {
|
85
|
+
:name => current_log_name,
|
86
|
+
:start_time => current_start_time,
|
87
|
+
:description => current_entry_description,
|
88
|
+
}
|
89
|
+
delete_current(current_hash[:name])
|
90
|
+
log.add_entry(current_hash)
|
91
|
+
|
92
|
+
git.add
|
93
|
+
git.commit("Stopped log '#{log.name}'")
|
94
|
+
true
|
95
|
+
else
|
96
|
+
false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def change_log_state(log, new_state)
|
101
|
+
log.path = log_path(log.name)
|
102
|
+
log.update_state(new_state)
|
103
|
+
|
104
|
+
git.add
|
105
|
+
git.commit("Changed state for time log #{log.name}")
|
106
|
+
end
|
107
|
+
|
108
|
+
def change_log_points(log, new_points_value)
|
109
|
+
log.path = log_path(log.name)
|
110
|
+
log.update_points(new_points_value)
|
111
|
+
|
112
|
+
git.add
|
113
|
+
git.commit("Changed points value for time log #{log.name}")
|
114
|
+
end
|
115
|
+
|
116
|
+
def change_log_owner(log, new_owner)
|
117
|
+
log.path = log_path(log.name)
|
118
|
+
log.update_owner(new_owner)
|
119
|
+
|
120
|
+
git.add
|
121
|
+
git.commit("Changed owner for time log #{log.name}")
|
122
|
+
end
|
123
|
+
|
124
|
+
def log_duration(log_name)
|
125
|
+
duration = 0
|
126
|
+
if current_log_name == log_name
|
127
|
+
duration += time_since_start
|
128
|
+
end
|
129
|
+
log_entries(log_name).each do |entry| # should just be able to do log.entries.each
|
130
|
+
duration += entry.length
|
131
|
+
end
|
132
|
+
duration
|
133
|
+
end
|
134
|
+
|
135
|
+
def find_repo(dir)
|
136
|
+
full = File.expand_path(dir)
|
137
|
+
ENV["GIT_WORKING_DIR"] || loop do
|
138
|
+
return full if File.directory?(File.join(full, ".git"))
|
139
|
+
raise "No Repo Found" if full == full=File.dirname(full)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def start_time_string
|
144
|
+
current_start_time
|
145
|
+
end
|
146
|
+
|
147
|
+
def cur_user
|
148
|
+
git.config["user.email"].split('@').first rescue ''
|
149
|
+
end
|
150
|
+
|
151
|
+
def time_since_start
|
152
|
+
if Dir.exists?(current_path)
|
153
|
+
difference = Time.now - Time.parse(current_start_time)
|
154
|
+
difference.to_i
|
155
|
+
else
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def cur_start_time
|
161
|
+
Time.parse(current_start_time) if current_start_path
|
162
|
+
end
|
163
|
+
|
164
|
+
def cur_entry_description
|
165
|
+
current_entry_description
|
166
|
+
end
|
167
|
+
|
168
|
+
def current_log_name
|
169
|
+
name_contents = File.read(current_name_path) if File.exists?(current_name_path)
|
170
|
+
name_contents.strip if name_contents
|
171
|
+
end
|
172
|
+
|
173
|
+
def get_current_start_time
|
174
|
+
current_start_time
|
175
|
+
end
|
176
|
+
|
177
|
+
def all_log_dirs
|
178
|
+
Pathname.new(logs_path).children.select { |c| c.directory? } if Dir.exists?(logs_path)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Code from 'ticgit', temporarily switches to tlog branch
|
182
|
+
def in_branch(branch_exists = true)
|
183
|
+
unless File.directory?(@tlog_working)
|
184
|
+
FileUtils.mkdir_p(@tlog_working)
|
185
|
+
end
|
186
|
+
|
187
|
+
old_current = git.lib.branch_current
|
188
|
+
begin
|
189
|
+
git.lib.change_head_branch('tlog')
|
190
|
+
git.with_index(@tlog_index) do
|
191
|
+
git.with_working(@tlog_working) do |wd|
|
192
|
+
git.lib.checkout('tlog') if branch_exists
|
193
|
+
yield wd
|
194
|
+
end
|
195
|
+
end
|
196
|
+
ensure
|
197
|
+
git.lib.change_head_branch(old_current)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
private
|
202
|
+
|
203
|
+
def decode_log_path(log_path)
|
204
|
+
if Dir.exists?(log_path)
|
205
|
+
log = Tlog::Entity::Log.new(log_path)
|
206
|
+
#log_storage.log_path = log_path # add this to the log class...i think task_store may not be neccessary
|
207
|
+
#lgolog.entries = log_storage.entries
|
208
|
+
end
|
209
|
+
return log
|
210
|
+
end
|
211
|
+
|
212
|
+
def init_tlog_branch(tlog_branch = false)
|
213
|
+
in_branch(tlog_branch) do
|
214
|
+
File.open('.hold', 'w+'){|f| f.puts('hold')}
|
215
|
+
unless tlog_branch
|
216
|
+
git.add
|
217
|
+
git.commit('creating the tlog branch')
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def update_current(log_name, entry_description)
|
223
|
+
unless Dir.exists?(current_path)
|
224
|
+
FileUtils.mkdir_p(current_path)
|
225
|
+
write_to_current(log_name, entry_description)
|
226
|
+
true
|
227
|
+
else
|
228
|
+
false
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def delete_current(log_name)
|
233
|
+
if Dir.exists?(current_path)
|
234
|
+
if current_log_name == log_name
|
235
|
+
FileUtils.rm_rf(current_path)
|
236
|
+
git.remove(current_path, {:recursive => 'r'})
|
237
|
+
end
|
238
|
+
else
|
239
|
+
false
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def delete_checkout(log_name)
|
244
|
+
if File.exists?(checkout_path)
|
245
|
+
if checkout_value == log_name
|
246
|
+
FileUtils.rm(checkout_path)
|
247
|
+
end
|
248
|
+
else
|
249
|
+
fals
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def write_to_current(log_name, entry_description)
|
254
|
+
# Create a current object, with a "read" method
|
255
|
+
File.open(current_name_path, 'w'){ |f| f.write(log_name)}
|
256
|
+
File.open(current_description_path, 'w'){ |f| f.write(entry_description)} if entry_description
|
257
|
+
File.open(current_start_path, 'w'){ |f| f.write(Time.now.to_s)}
|
258
|
+
end
|
259
|
+
|
260
|
+
def current_exists?
|
261
|
+
Dir.exists?(current_path)
|
262
|
+
end
|
263
|
+
|
264
|
+
def stop_current
|
265
|
+
if Dir.exists?(current_path)
|
266
|
+
create_log_entry(current_log_name, current_start_time, current_entry_description) # CURRENT Dictionary?!
|
267
|
+
true
|
268
|
+
else
|
269
|
+
false
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
#Eventually want to take this out and just create the entry on start
|
274
|
+
def current_start_time
|
275
|
+
read_file(current_start_path)
|
276
|
+
end
|
277
|
+
|
278
|
+
def current_entry_description
|
279
|
+
read_file(current_description_path)
|
280
|
+
end
|
281
|
+
|
282
|
+
def current_log_length
|
283
|
+
read_file(current_length_path)
|
284
|
+
end
|
285
|
+
|
286
|
+
def read_file(path)
|
287
|
+
if File.exists?(path)
|
288
|
+
contents = File.read(path)
|
289
|
+
contents.strip
|
290
|
+
else
|
291
|
+
nil
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def log_path(log_name)
|
296
|
+
File.join(logs_path, log_name)
|
297
|
+
end
|
298
|
+
|
299
|
+
def goal_path(log_name)
|
300
|
+
File.join(log_path(log_name), 'GOAL')
|
301
|
+
end
|
302
|
+
|
303
|
+
def logs_path
|
304
|
+
File.expand_path(File.join('tasks'))
|
305
|
+
end
|
306
|
+
|
307
|
+
def checkout_path
|
308
|
+
File.join(logs_path, 'CHECKOUT');
|
309
|
+
end
|
310
|
+
|
311
|
+
def current_path
|
312
|
+
File.expand_path(File.join('current'))
|
313
|
+
end
|
314
|
+
|
315
|
+
def current_name_path
|
316
|
+
File.join(current_path, 'NAME')
|
317
|
+
end
|
318
|
+
|
319
|
+
def current_start_path
|
320
|
+
File.join(current_path, 'START')
|
321
|
+
end
|
322
|
+
|
323
|
+
def current_length_path
|
324
|
+
File.join(current_path, 'LENGTH')
|
325
|
+
end
|
326
|
+
|
327
|
+
def current_description_path
|
328
|
+
File.join(current_path, 'DESCRIPTION')
|
329
|
+
end
|
330
330
|
|
331
331
|
end
|