tempo-cli 0.2.6 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile.lock +64 -39
- data/README.md +16 -7
- data/Rakefile +3 -3
- data/bin/tempo +28 -0
- data/features/step_definitions/tempo_steps.rb +14 -14
- data/features/support/env.rb +1 -1
- data/lib/file_record/directory.rb +104 -1
- data/lib/file_record/file_utility.rb +50 -8
- data/lib/file_record/record.rb +11 -10
- data/lib/tempo/controllers/end_controller.rb +1 -1
- data/lib/tempo/controllers/projects_controller.rb +1 -1
- data/lib/tempo/controllers/records_controller.rb +56 -4
- data/lib/tempo/controllers/report_controller.rb +1 -1
- data/lib/tempo/controllers/start_controller.rb +2 -2
- data/lib/tempo/exceptions.rb +11 -0
- data/lib/tempo/models/log.rb +20 -3
- data/lib/tempo/models/time_record.rb +7 -1
- data/lib/tempo/version.rb +1 -1
- data/lib/tempo/views/base.rb +3 -3
- data/lib/tempo/views/formatters/interactive.rb +44 -0
- data/lib/tempo/views/formatters/screen.rb +9 -10
- data/lib/tempo/views/interactive.rb +32 -0
- data/lib/tempo/views/reporter.rb +15 -0
- data/lib/tempo/views/view_records/base.rb +24 -0
- data/lib/tempo/views/view_records/time_record.rb +1 -1
- data/tempo-cli.gemspec +6 -8
- data/test/lib/file_record/directory_test.rb +17 -14
- data/test/lib/file_record/record_test.rb +11 -8
- data/test/lib/tempo/models/base_test.rb +3 -3
- data/test/lib/tempo/models/composite_test.rb +2 -2
- data/test/lib/tempo/models/log_test.rb +17 -7
- data/test/lib/tempo/models/project_test.rb +1 -1
- data/test/lib/tempo/models/time_record_test.rb +4 -4
- data/test/lib/tempo/views/formatters/console_test.rb +32 -0
- data/test/lib/tempo/views/reporter_test.rb +7 -1
- data/test/support/factories.rb +9 -17
- metadata +25 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4630648caa1ae6432140a0e621d276836a3a26a248ae7ab80cd8eb2a147af837
|
4
|
+
data.tar.gz: cb6ecc56d1cf069b75ff8a3bd54e3de81703dc20ea59b1cf85d36789bedb5254
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c846d66d6f427e7b8610c298dbb89ae9542adcb1e61eaaaefb7f1bf0479a6be21533e14d0db1c47536339f14ee96e3f98a040418255ab6366235940d64fd883
|
7
|
+
data.tar.gz: 1ab3da83905ef323f6edb24d6c581e5d988d50b313d991c568a7c150ad967172f6d0625465d05c87452251dcd9703d49e38e575f27fb92d901060a2c2008f63b
|
data/Gemfile.lock
CHANGED
@@ -1,56 +1,81 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tempo-cli (0.
|
5
|
-
chronic (~> 0.10)
|
6
|
-
gli (
|
4
|
+
tempo-cli (1.0.1)
|
5
|
+
chronic (~> 0.10.2)
|
6
|
+
gli (>= 2.21.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
ansi (1.
|
12
|
-
aruba (
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
ansi (1.5.0)
|
12
|
+
aruba (2.2.0)
|
13
|
+
bundler (>= 1.17, < 3.0)
|
14
|
+
contracts (>= 0.16.0, < 0.18.0)
|
15
|
+
cucumber (>= 8.0, < 10.0)
|
16
|
+
rspec-expectations (~> 3.4)
|
17
|
+
thor (~> 1.0)
|
18
|
+
bigdecimal (3.1.7)
|
19
|
+
builder (3.2.4)
|
19
20
|
chronic (0.10.2)
|
20
|
-
coderay (1.
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
21
|
+
coderay (1.1.3)
|
22
|
+
contracts (0.17)
|
23
|
+
cucumber (9.2.0)
|
24
|
+
builder (~> 3.2)
|
25
|
+
cucumber-ci-environment (> 9, < 11)
|
26
|
+
cucumber-core (> 13, < 14)
|
27
|
+
cucumber-cucumber-expressions (~> 17.0)
|
28
|
+
cucumber-gherkin (> 24, < 28)
|
29
|
+
cucumber-html-formatter (> 20.3, < 22)
|
30
|
+
cucumber-messages (> 19, < 25)
|
31
|
+
diff-lcs (~> 1.5)
|
32
|
+
mini_mime (~> 1.1)
|
33
|
+
multi_test (~> 1.1)
|
34
|
+
sys-uname (~> 1.2)
|
35
|
+
cucumber-ci-environment (10.0.1)
|
36
|
+
cucumber-core (13.0.2)
|
37
|
+
cucumber-gherkin (>= 27, < 28)
|
38
|
+
cucumber-messages (>= 20, < 23)
|
39
|
+
cucumber-tag-expressions (> 5, < 7)
|
40
|
+
cucumber-cucumber-expressions (17.1.0)
|
41
|
+
bigdecimal
|
42
|
+
cucumber-gherkin (27.0.0)
|
43
|
+
cucumber-messages (>= 19.1.4, < 23)
|
44
|
+
cucumber-html-formatter (21.3.1)
|
45
|
+
cucumber-messages (> 19, < 25)
|
46
|
+
cucumber-messages (22.0.0)
|
47
|
+
cucumber-tag-expressions (6.1.0)
|
48
|
+
diff-lcs (1.5.1)
|
49
|
+
ffi (1.16.3)
|
50
|
+
gli (2.21.1)
|
51
|
+
method_source (1.0.0)
|
52
|
+
mini_mime (1.1.5)
|
53
|
+
minitest (4.7.5)
|
54
|
+
multi_test (1.1.0)
|
55
|
+
pry (0.14.2)
|
56
|
+
coderay (~> 1.1)
|
57
|
+
method_source (~> 1.0)
|
38
58
|
rake (10.3.2)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
59
|
+
rspec-expectations (3.13.0)
|
60
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
61
|
+
rspec-support (~> 3.13.0)
|
62
|
+
rspec-support (3.13.1)
|
63
|
+
sys-uname (1.2.3)
|
64
|
+
ffi (~> 1.1)
|
65
|
+
thor (1.3.1)
|
66
|
+
turn (0.9.7)
|
45
67
|
ansi
|
68
|
+
minitest (~> 4)
|
46
69
|
|
47
70
|
PLATFORMS
|
48
71
|
ruby
|
49
72
|
|
50
73
|
DEPENDENCIES
|
51
|
-
aruba (~>
|
52
|
-
pry (~> 0.
|
74
|
+
aruba (~> 2.2)
|
75
|
+
pry (~> 0.14.2)
|
53
76
|
rake (~> 10.3)
|
54
|
-
rdoc (~> 4.1)
|
55
77
|
tempo-cli!
|
56
|
-
turn (~> 0.9)
|
78
|
+
turn (~> 0.9.7)
|
79
|
+
|
80
|
+
BUNDLED WITH
|
81
|
+
2.4.20
|
data/README.md
CHANGED
@@ -2,9 +2,16 @@
|
|
2
2
|
|
3
3
|
A command line interface for time tracking by project.
|
4
4
|
|
5
|
+
## A note on Version 1.0
|
6
|
+
|
7
|
+
If you are updatging from version ~> 0.2.6 to 1.0, there is a new structure to the time records - time records are now kept in sub-folders by year.
|
8
|
+
|
9
|
+
Run `tempo clean` to make a backup of your old directory, move files into the proper folders, and check all earlier records for errors.
|
10
|
+
|
11
|
+
|
5
12
|
## Installation
|
6
13
|
|
7
|
-
gem install tempo-cli
|
14
|
+
gem install tempo-cli
|
8
15
|
|
9
16
|
### binary
|
10
17
|
|
@@ -18,11 +25,9 @@ Tempo cli runs with the binary `tempo`, but you can alias a shorter binary for y
|
|
18
25
|
|
19
26
|
Tempo tracks time against projects. Projects can be nested, and tagged, and each time entry can have an additional description. Time reports are produced by day.
|
20
27
|
|
21
|
-
Future enhancements will include reports by project and time totals by day or by project.
|
22
|
-
|
23
28
|
### Records
|
24
29
|
|
25
|
-
All records are produced in YAML files. These
|
30
|
+
All records are produced in YAML files. These records can be edited by hand, but keep in mind that any invalid data could cause problems when it is read back into the app. Make sure time formatting is valid and that they don't overlap, and that all ids are unique per page.
|
26
31
|
|
27
32
|
Each day's time records are designed to work independently. When adding or updating time records, only the records for the days in question are loaded into the app. The most recent day's records will also always be read in, to assure no running records are created earlier than existing records.
|
28
33
|
|
@@ -235,8 +240,9 @@ The description, if passed in, will be used to replace the existing description.
|
|
235
240
|
|
236
241
|
##### command options
|
237
242
|
|
238
|
-
--from=time
|
239
|
-
--
|
243
|
+
-f, --from=time - begin time records on this date
|
244
|
+
-o, --order=[project, date] - order reports by date or project
|
245
|
+
-t, --to=time - end time records on this date
|
240
246
|
|
241
247
|
Reports time entries for a day or a period of days. By default, lists the last recorded day's entries. To list a different day, supply a day as the args. To list a series of records, include a --from and --to value
|
242
248
|
|
@@ -254,6 +260,9 @@ The description, if passed in, will be used to replace the existing description.
|
|
254
260
|
# report a period of days
|
255
261
|
$ tempo report -f 'last monday' -t 'last friday'
|
256
262
|
|
263
|
+
# organize reports as bullet lists under each project
|
264
|
+
$ tempo report --o p
|
265
|
+
|
257
266
|
## Assumptions and Limitations
|
258
267
|
|
259
268
|
Before you begin using tempo, you must have at least one project. Projects can be tagged, and organized as sub-projects. See project in the commands section below, for more information. To view your projects file, look at ~/tempo/tempo_projects.yaml
|
@@ -336,7 +345,7 @@ You can cleanup the testing directories with `bundle exec rake clean`
|
|
336
345
|
|
337
346
|
This is a very opinionated time tracking app, you may find others that suit your working method better:
|
338
347
|
|
339
|
-
If you would prefer to keep your data in a database, or run
|
348
|
+
If you would prefer to keep your data in a database, or run independent time sheets by project, here is a utility that uses SQLite:
|
340
349
|
|
341
350
|
[timetrap](https://github.com/samg/timetrap)
|
342
351
|
|
data/Rakefile
CHANGED
@@ -39,15 +39,15 @@ task :cucumber => :features
|
|
39
39
|
task :tests_setup do
|
40
40
|
@ORIGINAL_HOME = ENV['HOME']
|
41
41
|
ENV['HOME'] = ENV['HOME'] + "/testing"
|
42
|
-
Dir.mkdir(ENV['HOME'], 0700) unless File.
|
42
|
+
Dir.mkdir(ENV['HOME'], 0700) unless File.exist?(ENV['HOME'])
|
43
43
|
dir = File.join(Dir.home,"tempo")
|
44
|
-
Dir.mkdir(dir, 0700) unless File.
|
44
|
+
Dir.mkdir(dir, 0700) unless File.exist?(dir)
|
45
45
|
end
|
46
46
|
|
47
47
|
task :tests_teardown do
|
48
48
|
ENV['HOME'] = @ORIGINAL_HOME
|
49
49
|
dir = File.join(Dir.home, "testing")
|
50
|
-
FileUtils.rm_r dir if File.
|
50
|
+
FileUtils.rm_r dir if File.exist?(dir)
|
51
51
|
end
|
52
52
|
|
53
53
|
require 'rake/testtask'
|
data/bin/tempo
CHANGED
@@ -464,6 +464,34 @@ command [:update, :u] do |c|
|
|
464
464
|
end
|
465
465
|
end
|
466
466
|
|
467
|
+
# COMMAND: CLEAN
|
468
|
+
|
469
|
+
desc 'Clean the tempo file structure'
|
470
|
+
long_desc "Creates a backup of the existing tempo directory,
|
471
|
+
and then clean all files in the current directory.
|
472
|
+
|
473
|
+
Cleaning the projects assures that:
|
474
|
+
|
475
|
+
1. All projects that have been renamed have been updated in the files.
|
476
|
+
|
477
|
+
2. Any files with time record conflicts are caught and can be corrected."
|
478
|
+
|
479
|
+
command [:clean] do |c|
|
480
|
+
require 'readline'
|
481
|
+
c.action do |global_options, options, args|
|
482
|
+
controller = Tempo::Controllers::Records
|
483
|
+
|
484
|
+
confirm = Tempo::Views::interactive_confirm_clean
|
485
|
+
|
486
|
+
if confirm.positive_response?
|
487
|
+
controller.backup_records options, args
|
488
|
+
controller.clean_records options, args
|
489
|
+
else
|
490
|
+
Tempo::Views::message "Cancelling clean"
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
467
495
|
pre do |global,command,options,args|
|
468
496
|
|
469
497
|
# add reporting of all arguments
|
@@ -5,16 +5,16 @@ end
|
|
5
5
|
|
6
6
|
Given /^a clean installation$/ do
|
7
7
|
@testing_env = File.join(ENV['HOME'], 'tempo')
|
8
|
-
FileUtils.rm_r(@testing_env) if File.
|
8
|
+
FileUtils.rm_r(@testing_env) if File.exist?(@testing_env)
|
9
9
|
|
10
10
|
# Testing global --directory argument in /alt_dir
|
11
11
|
@alt_dir = File.join(ENV['HOME'], 'alt_dir')
|
12
|
-
FileUtils.rm_r(@alt_dir) if File.
|
12
|
+
FileUtils.rm_r(@alt_dir) if File.exist?(@alt_dir)
|
13
13
|
end
|
14
14
|
|
15
15
|
Given /^an existing project file$/ do
|
16
16
|
@testing_env = File.join(ENV['HOME'], 'tempo')
|
17
|
-
FileUtils.rm_r(@testing_env) if File.
|
17
|
+
FileUtils.rm_r(@testing_env) if File.exist?(@testing_env)
|
18
18
|
Dir.mkdir(@testing_env, 0700)
|
19
19
|
projects_file = File.join(@testing_env, 'tempo_projects.yaml')
|
20
20
|
|
@@ -34,7 +34,7 @@ end
|
|
34
34
|
|
35
35
|
Given /^an alternate directory and an existing project file$/ do
|
36
36
|
@testing_env = File.join(ENV['HOME'], 'alt_dir', 'tempo')
|
37
|
-
FileUtils.rm_r(@testing_env) if File.
|
37
|
+
FileUtils.rm_r(@testing_env) if File.exist?(@testing_env)
|
38
38
|
FileUtils.mkdir_p(@testing_env)
|
39
39
|
projects_file = File.join(@testing_env, 'tempo_projects.yaml')
|
40
40
|
|
@@ -53,9 +53,9 @@ Given /^an alternate directory and an existing project file$/ do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
Given /^an existing time record file$/ do
|
56
|
-
@records_directory = File.join(ENV['HOME'], 'tempo/tempo_time_records')
|
57
|
-
FileUtils.rm_r(@records_directory) if File.
|
58
|
-
|
56
|
+
@records_directory = File.join(ENV['HOME'], 'tempo/tempo_time_records', '2014')
|
57
|
+
FileUtils.rm_r(@records_directory) if File.exist?(@records_directory)
|
58
|
+
FileUtils.mkdir_p @records_directory
|
59
59
|
projects_file = File.join(@records_directory, '20140101.yaml')
|
60
60
|
|
61
61
|
File.open(projects_file,'w') do |f|
|
@@ -107,7 +107,7 @@ end
|
|
107
107
|
|
108
108
|
|
109
109
|
Then /^the time record (.*?) should contain "(.*?)" at line (\d+)$/ do |arg1, arg2, arg3|
|
110
|
-
file = File.join(ENV['HOME'], 'tempo/tempo_time_records', "#{arg1}.yaml")
|
110
|
+
file = File.join(ENV['HOME'], 'tempo/tempo_time_records', "#{arg1[0..3]}", "#{arg1}.yaml")
|
111
111
|
contents = []
|
112
112
|
File.open(file, "r") do |f|
|
113
113
|
f.readlines.each do |line|
|
@@ -118,7 +118,7 @@ Then /^the time record (.*?) should contain "(.*?)" at line (\d+)$/ do |arg1, ar
|
|
118
118
|
end
|
119
119
|
|
120
120
|
Then /^the time record (.*?) should not contain "(.*?)"$/ do |arg1, arg2|
|
121
|
-
file = File.join(ENV['HOME'], 'tempo/tempo_time_records', "#{arg1}.yaml")
|
121
|
+
file = File.join(ENV['HOME'], 'tempo/tempo_time_records', "#{arg1[0..3]}", "#{arg1}.yaml")
|
122
122
|
contents = []
|
123
123
|
File.open(file, "r") do |f|
|
124
124
|
f.readlines.each do |line|
|
@@ -129,8 +129,8 @@ Then /^the time record (.*?) should not contain "(.*?)"$/ do |arg1, arg2|
|
|
129
129
|
end
|
130
130
|
|
131
131
|
Then /^the time record (.*?) should not exist$/ do |arg1|
|
132
|
-
file = File.join(ENV['HOME'], 'tempo/tempo_time_records', "#{arg1}.yaml")
|
133
|
-
File.
|
132
|
+
file = File.join(ENV['HOME'], 'tempo/tempo_time_records', "#{arg1[0..3]}", "#{arg1}.yaml")
|
133
|
+
File.exist?(file).should == false
|
134
134
|
end
|
135
135
|
|
136
136
|
Then /^the (\S*) file should contain "(.*?)" at line (\d+)$/ do |arg1, arg2, arg3|
|
@@ -200,7 +200,7 @@ Then /^the alternate directory (.*?) file should not contain "(.*?)"$/ do |arg1,
|
|
200
200
|
end
|
201
201
|
|
202
202
|
Then /^the alternate directory time record (\d+) should contain "(.*?)" at line (\d+)$/ do |arg1, arg2, arg3|
|
203
|
-
file = File.join(ENV['HOME'], 'alt_dir', 'tempo', 'tempo_time_records', "#{arg1}.yaml")
|
203
|
+
file = File.join(ENV['HOME'], 'alt_dir', 'tempo', 'tempo_time_records', "#{arg1[0..3]}", "#{arg1}.yaml")
|
204
204
|
contents = []
|
205
205
|
File.open(file, "r") do |f|
|
206
206
|
f.readlines.each do |line|
|
@@ -211,7 +211,7 @@ Then /^the alternate directory time record (\d+) should contain "(.*?)" at line
|
|
211
211
|
end
|
212
212
|
|
213
213
|
Then /^the alternate directory time record (.*?) should not exist$/ do |arg1|
|
214
|
-
file = File.join(ENV['HOME'], 'alt_dir', 'tempo/tempo_time_records', "#{arg1}.yaml")
|
215
|
-
File.
|
214
|
+
file = File.join(ENV['HOME'], 'alt_dir', 'tempo/tempo_time_records', "#{arg1[0..3]}", "#{arg1}.yaml")
|
215
|
+
File.exist?(file).should == false
|
216
216
|
end
|
217
217
|
|
data/features/support/env.rb
CHANGED
@@ -16,7 +16,7 @@ Before do
|
|
16
16
|
@real_home = ENV['HOME']
|
17
17
|
@testing_env = File.join(ENV['HOME'], 'testing_features')
|
18
18
|
#FileUtils.rm_rf @testing_env, :secure => true
|
19
|
-
Dir.mkdir(@testing_env, 0700) unless File.
|
19
|
+
Dir.mkdir(@testing_env, 0700) unless File.exist?(@testing_env)
|
20
20
|
ENV['HOME'] = @testing_env
|
21
21
|
end
|
22
22
|
|
@@ -1,3 +1,9 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'rubygems/package'
|
3
|
+
require 'rubygems/package'
|
4
|
+
require 'zlib'
|
5
|
+
|
6
|
+
|
1
7
|
module FileRecord
|
2
8
|
class Directory
|
3
9
|
|
@@ -14,7 +20,7 @@ module FileRecord
|
|
14
20
|
|
15
21
|
def create_new(options={})
|
16
22
|
|
17
|
-
directory = options.fetch(
|
23
|
+
directory = options.fetch(:directory, Dir.home)
|
18
24
|
cwd = File.expand_path File.dirname(__FILE__)
|
19
25
|
source = File.join(cwd, "directory_structure/tempo")
|
20
26
|
if ! Dir.exists? directory
|
@@ -22,6 +28,103 @@ module FileRecord
|
|
22
28
|
end
|
23
29
|
FileUtils.cp_r source, directory
|
24
30
|
end
|
31
|
+
|
32
|
+
# Backup the tempo directory to tempo_backup/tempo_backup_20140101_HrMnS.tar.gz
|
33
|
+
# pass in an optional directory (see create_new)
|
34
|
+
# Pass in a timestamp, or default to 20140101_120000
|
35
|
+
def backup(options={})
|
36
|
+
directory = options.fetch(:directory, Dir.home)
|
37
|
+
timestamp = options.fetch(:timestamp, Time.new.strftime("%Y%m%d_%H%M%S"))
|
38
|
+
source = File.join(directory, "tempo")
|
39
|
+
dest = File.join(directory, "tempo_backups")
|
40
|
+
Dir.mkdir dest unless Dir.exists? dest
|
41
|
+
destination = File.join(directory, "tempo_backups", "tempo_backup_#{timestamp}.tar.gz")
|
42
|
+
|
43
|
+
io = tar(source)
|
44
|
+
gz = gzip(io)
|
45
|
+
|
46
|
+
File.open(destination,"w") do |file|
|
47
|
+
file.binmode
|
48
|
+
file.write gz.read
|
49
|
+
end
|
50
|
+
|
51
|
+
# return the new directory name
|
52
|
+
destination
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# COMPRESSION / DECOMPRESSION
|
58
|
+
# From: https://gist.github.com/sinisterchipmunk/1335041
|
59
|
+
|
60
|
+
# Creates a tar file in memory recursively
|
61
|
+
# from the given dir.
|
62
|
+
#
|
63
|
+
# Returns a StringIO whose underlying String
|
64
|
+
# is the contents of the tar file.
|
65
|
+
def tar(dir)
|
66
|
+
tarfile = StringIO.new("")
|
67
|
+
Gem::Package::TarWriter.new(tarfile) do |tar|
|
68
|
+
Dir[File.join(dir, "**/*")].each do |file|
|
69
|
+
mode = File.stat(file).mode
|
70
|
+
relative_file = file.sub /^#{Regexp::escape dir}\/?/, ''
|
71
|
+
|
72
|
+
if File.directory?(file)
|
73
|
+
tar.mkdir relative_file, mode
|
74
|
+
else
|
75
|
+
tar.add_file relative_file, mode do |tf|
|
76
|
+
File.open(file, "rb") { |f| tf.write f.read }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
tarfile.rewind
|
83
|
+
tarfile
|
84
|
+
end
|
85
|
+
|
86
|
+
# gzips the underlying string in the given StringIO,
|
87
|
+
# returning a new StringIO representing the
|
88
|
+
# compressed file.
|
89
|
+
def gzip(tarfile)
|
90
|
+
gz = StringIO.new("")
|
91
|
+
z = Zlib::GzipWriter.new(gz)
|
92
|
+
z.write tarfile.string
|
93
|
+
z.close # this is necessary!
|
94
|
+
|
95
|
+
# z was closed to write the gzip footer, so
|
96
|
+
# now we need a new StringIO
|
97
|
+
StringIO.new gz.string
|
98
|
+
end
|
99
|
+
|
100
|
+
# un-gzips the given IO, returning the
|
101
|
+
# decompressed version as a StringIO
|
102
|
+
def ungzip(tarfile)
|
103
|
+
z = Zlib::GzipReader.new(tarfile)
|
104
|
+
unzipped = StringIO.new(z.read)
|
105
|
+
z.close
|
106
|
+
unzipped
|
107
|
+
end
|
108
|
+
|
109
|
+
# untars the given IO into the specified
|
110
|
+
# directory
|
111
|
+
def untar(io, destination)
|
112
|
+
Gem::Package::TarReader.new io do |tar|
|
113
|
+
tar.each do |tarfile|
|
114
|
+
destination_file = File.join destination, tarfile.full_name
|
115
|
+
|
116
|
+
if tarfile.directory?
|
117
|
+
FileUtils.mkdir_p destination_file
|
118
|
+
else
|
119
|
+
destination_directory = File.dirname(destination_file)
|
120
|
+
FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
|
121
|
+
File.open destination_file, "wb" do |f|
|
122
|
+
f.print tarfile.read
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
25
128
|
end
|
26
129
|
end
|
27
130
|
end
|
@@ -73,14 +73,28 @@ module FileRecord
|
|
73
73
|
"#{sn[0]}_#{sn[-1]}s"
|
74
74
|
end
|
75
75
|
|
76
|
-
|
76
|
+
|
77
|
+
def log_year_directory
|
78
|
+
if @time.kind_of? Time
|
79
|
+
@time.strftime("%Y")
|
80
|
+
else
|
81
|
+
@time[0..3]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Tempo::Model::Log -> Users/usrname/(alternate_directory/)tempo/tempo_logs'
|
77
86
|
# Will also create the directory if not found
|
78
|
-
|
79
|
-
def log_directory_path
|
87
|
+
def log_main_directory_path
|
80
88
|
dir = File.join(@directory, module_name, log_directory)
|
89
|
+
end
|
81
90
|
|
82
|
-
|
83
|
-
|
91
|
+
# Tempo::Model::Log -> Users/usrname/(alternate_directory/)tempo/tempo_logs/20XX
|
92
|
+
# Will also create the directory if not found
|
93
|
+
def log_directory_path
|
94
|
+
dir = File.join(log_main_directory_path, log_year_directory)
|
95
|
+
|
96
|
+
if @create and !File.exist?(dir)
|
97
|
+
FileUtils.mkdir_p dir
|
84
98
|
end
|
85
99
|
|
86
100
|
dir
|
@@ -97,22 +111,50 @@ module FileRecord
|
|
97
111
|
|
98
112
|
dir = File.join(@directory, module_name)
|
99
113
|
|
100
|
-
if @create and !File.
|
114
|
+
if @create and !File.exist?(dir)
|
101
115
|
Dir.mkdir(dir, 0700)
|
102
116
|
end
|
103
117
|
|
104
118
|
clean_path File.join(dir, filename)
|
105
119
|
end
|
106
120
|
|
121
|
+
def old_style_log_records_exists?
|
122
|
+
return false if !File.exist?(log_main_directory_path)
|
123
|
+
Pathname.new(log_main_directory_path).children.each do |c|
|
124
|
+
return true if c.to_s.match(/\.yaml/)
|
125
|
+
end
|
126
|
+
false
|
127
|
+
end
|
128
|
+
|
129
|
+
def move_old_records
|
130
|
+
return false if !File.exist?(log_main_directory_path)
|
131
|
+
puts "moving files in #{log_main_directory_path}"
|
132
|
+
Pathname.new(log_main_directory_path).children.each do |c|
|
133
|
+
if c.to_s.match(/\.yaml/)
|
134
|
+
year = File.basename(c).match(/(^\d{4})/)[1]
|
135
|
+
raise Tempo::DuplicateRecordError.new(File.join(log_main_directory_path,year,File.basename(c))) if File.exist?(File.join(log_main_directory_path,year,File.basename(c)))
|
136
|
+
FileUtils.mkdir_p File.join(log_main_directory_path,year) if !File.exist? File.join(log_main_directory_path,year)
|
137
|
+
FileUtils.cp c, File.join(log_main_directory_path,year,File.basename(c))
|
138
|
+
FileUtils.rm c
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
107
143
|
# Returns the list of log records from a log directory
|
108
144
|
def log_records
|
109
|
-
|
145
|
+
records = []
|
146
|
+
return records if !File.exist?(log_main_directory_path)
|
147
|
+
years = Pathname.new(log_main_directory_path).children.select { |c| c.directory? }
|
148
|
+
years.each do |dir|
|
149
|
+
records = records | Dir[dir.to_s + "/*.yaml"]
|
150
|
+
end
|
151
|
+
records.sort!
|
110
152
|
end
|
111
153
|
|
112
154
|
# remove existing file when passed destroy:true in options
|
113
155
|
def clean_path(file_path)
|
114
156
|
|
115
|
-
if @destroy and File.
|
157
|
+
if @destroy and File.exist?(file_path)
|
116
158
|
File.delete(file_path)
|
117
159
|
end
|
118
160
|
|
data/lib/file_record/record.rb
CHANGED
@@ -42,15 +42,6 @@ module FileRecord
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
# Used by read_model and read_log to load all instances from a file
|
46
|
-
#
|
47
|
-
def read_instances( model, file, options={} )
|
48
|
-
instances = YAML::load_stream( File.open( file ) )
|
49
|
-
instances.each do |i|
|
50
|
-
model.new( i )
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
45
|
# Read in all models instances from the model file
|
55
46
|
def read_model( model, options={} )
|
56
47
|
|
@@ -64,10 +55,20 @@ module FileRecord
|
|
64
55
|
options[:time] = time
|
65
56
|
file_path = FileUtility.new(model, options).file_path
|
66
57
|
|
67
|
-
if File.
|
58
|
+
if File.exist? file_path
|
68
59
|
read_instances model, file_path
|
69
60
|
end
|
70
61
|
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
# Used by read_model and read_log to load all instances from a file
|
66
|
+
def read_instances( model, file, options={} )
|
67
|
+
instances = YAML::load_stream( File.open( file ) )
|
68
|
+
instances.each do |i|
|
69
|
+
model.new( i )
|
70
|
+
end
|
71
|
+
end
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|