achoo 0.3 → 0.4.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.
- data/CHANGES +12 -0
- data/README.rdoc +26 -30
- data/Rakefile +3 -0
- data/bin/achoo +2 -2
- data/lib/achoo.rb +1 -139
- data/lib/achoo/achievo.rb +13 -0
- data/lib/achoo/achievo/form.rb +22 -0
- data/lib/achoo/achievo/hour_administration_form.rb +91 -0
- data/lib/achoo/achievo/hour_registration_form.rb +230 -0
- data/lib/achoo/achievo/hour_registration_form_ranged.rb +49 -0
- data/lib/achoo/achievo/lock_month_form.rb +44 -0
- data/lib/achoo/achievo/login_form.rb +27 -0
- data/lib/achoo/achievo/table.rb +30 -0
- data/lib/achoo/app.rb +153 -0
- data/lib/achoo/awake.rb +86 -100
- data/lib/achoo/extensions.rb +24 -0
- data/lib/achoo/ical.rb +47 -40
- data/lib/achoo/rc_loader.rb +42 -42
- data/lib/achoo/system.rb +8 -3
- data/lib/achoo/system/cstruct.rb +67 -0
- data/lib/achoo/system/log_entry.rb +24 -0
- data/lib/achoo/system/pm_suspend.rb +17 -20
- data/lib/achoo/system/utmp_record.rb +64 -0
- data/lib/achoo/system/wtmp.rb +14 -10
- data/lib/achoo/temporal.rb +8 -0
- data/lib/achoo/temporal/open_timespan.rb +16 -0
- data/lib/achoo/temporal/timespan.rb +122 -0
- data/lib/achoo/term.rb +58 -56
- data/lib/achoo/term/menu.rb +2 -2
- data/lib/achoo/term/table.rb +59 -60
- data/lib/achoo/ui.rb +13 -9
- data/lib/achoo/ui/commands.rb +60 -38
- data/lib/achoo/ui/common.rb +10 -7
- data/lib/achoo/ui/date_chooser.rb +69 -65
- data/lib/achoo/ui/date_choosers.rb +15 -14
- data/lib/achoo/ui/exception_handling.rb +14 -12
- data/lib/achoo/ui/month_chooser.rb +37 -24
- data/lib/achoo/ui/optionally_ranged_date_chooser.rb +29 -25
- data/lib/achoo/ui/register_hours.rb +116 -114
- data/lib/achoo/vcs.rb +32 -30
- data/lib/achoo/vcs/git.rb +18 -14
- data/lib/achoo/vcs/subversion.rb +25 -23
- metadata +30 -24
- data/lib/achoo/binary.rb +0 -7
- data/lib/achoo/binary/cstruct.rb +0 -60
- data/lib/achoo/binary/utmp_record.rb +0 -59
- data/lib/achoo/form.rb +0 -18
- data/lib/achoo/hour_administration_form.rb +0 -131
- data/lib/achoo/hour_registration_form.rb +0 -227
- data/lib/achoo/hour_registration_form_ranged.rb +0 -45
- data/lib/achoo/lock_month_form.rb +0 -40
- data/lib/achoo/open_timespan.rb +0 -13
- data/lib/achoo/timespan.rb +0 -119
@@ -1,137 +1,139 @@
|
|
1
|
+
require 'achoo/achievo'
|
1
2
|
require 'achoo/awake'
|
2
|
-
require 'achoo/hour_registration_form'
|
3
|
-
require 'achoo/hour_registration_form_ranged'
|
4
3
|
require 'achoo/ical'
|
5
4
|
require 'achoo/term'
|
6
5
|
require 'achoo/ui'
|
7
6
|
require 'achoo/vcs'
|
8
|
-
require 'stringio'
|
9
|
-
|
10
|
-
module Achoo::UI::RegisterHours
|
11
|
-
|
12
|
-
include Achoo::UI::DateChoosers
|
13
|
-
include Achoo::UI::ExceptionHandling
|
14
|
-
|
15
|
-
def register_hours(agent)
|
16
|
-
date = optionally_ranged_date_chooser
|
17
|
-
|
18
|
-
puts "Fetching data ..."
|
19
|
-
form = if date.class == Date
|
20
|
-
Achoo::HourRegistrationForm
|
21
|
-
else
|
22
|
-
Achoo::HourRegistrationFormRanged
|
23
|
-
end.new(agent)
|
24
|
-
|
25
|
-
form.date = date
|
26
|
-
form.project = project_chooser(form)
|
27
|
-
form.phase = phase_chooser(form)
|
28
|
-
print_remark_help(date) if date.class == Date
|
29
|
-
form.remark = remark_chooser
|
30
|
-
print_hours_help(date) if date.class == Date
|
31
|
-
form.hours = hours_chooser
|
32
|
-
|
33
|
-
answer = Achoo::Term.ask("Do you want to change the defaults for worktime period and/or billing percentage? [N/y]").downcase
|
34
|
-
if answer == 'y'
|
35
|
-
form.workperiod = workperiod_chooser(form)
|
36
|
-
form.billing = billing_chooser(form)
|
37
|
-
end
|
38
7
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
8
|
+
module Achoo
|
9
|
+
module UI
|
10
|
+
module RegisterHours
|
11
|
+
|
12
|
+
include DateChoosers
|
13
|
+
include ExceptionHandling
|
14
|
+
|
15
|
+
def register_hours(agent)
|
16
|
+
date = optionally_ranged_date_chooser
|
17
|
+
|
18
|
+
puts "Fetching data ..."
|
19
|
+
form = if date.class == Array
|
20
|
+
Achievo::HourRegistrationFormRanged
|
21
|
+
else
|
22
|
+
Achievo::HourRegistrationForm
|
23
|
+
end.new(agent)
|
24
|
+
|
25
|
+
form.date = date
|
26
|
+
form.project = project_chooser(form)
|
27
|
+
form.phase = phase_chooser(form)
|
28
|
+
print_remark_help(date) unless date.class == Array
|
29
|
+
form.remark = remark_chooser
|
30
|
+
print_hours_help(date) unless date.class == Array
|
31
|
+
form.hours = hours_chooser
|
32
|
+
|
33
|
+
answer = Term.ask("Do you want to change the defaults for worktime period and/or billing percentage? [N/y]").downcase
|
34
|
+
if answer == 'y'
|
35
|
+
form.workperiod = workperiod_chooser(form)
|
36
|
+
form.billing = billing_chooser(form)
|
37
|
+
end
|
38
|
+
|
39
|
+
form.print_values
|
40
|
+
if confirm
|
41
|
+
puts "Submitting ..."
|
42
|
+
form.submit
|
43
|
+
else
|
44
|
+
puts "Cancelled"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
47
48
|
|
49
|
+
def phase_chooser(form)
|
50
|
+
phases = form.phases_for_selected_project
|
51
|
+
puts "Phases"
|
52
|
+
answer = Term.choose('Phase', phases.collect {|p| p[1] })
|
53
|
+
phases[answer.to_i-1][0]
|
54
|
+
end
|
48
55
|
|
49
|
-
def phase_chooser(form)
|
50
|
-
phases = form.phases_for_selected_project
|
51
|
-
puts "Phases"
|
52
|
-
answer = Achoo::Term.choose('Phase', phases.collect {|p| p[1] })
|
53
|
-
phases[answer.to_i-1][0]
|
54
|
-
end
|
55
56
|
|
57
|
+
def workperiod_chooser(form)
|
58
|
+
periods = form.worktime_periods
|
59
|
+
puts "Worktime periods"
|
60
|
+
answer = Term.choose('Period [1]', periods.collect {|p| p[1] }, nil, [''])
|
61
|
+
answer = '1' if answer.empty?
|
62
|
+
periods[answer.to_i-1][0]
|
63
|
+
end
|
56
64
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
65
|
+
def billing_chooser(form)
|
66
|
+
options = form.billing_options
|
67
|
+
puts "Billing options"
|
68
|
+
answer = Term.choose('Billing [1]', options.collect {|p| p[1] }, nil, [''])
|
69
|
+
answer = '1' if answer.empty?
|
70
|
+
options[answer.to_i-1][0]
|
71
|
+
end
|
64
72
|
|
65
|
-
def billing_chooser(form)
|
66
|
-
options = form.billing_options
|
67
|
-
puts "Billing options"
|
68
|
-
answer = Achoo::Term.choose('Billing [1]', options.collect {|p| p[1] }, nil, [''])
|
69
|
-
answer = '1' if answer.empty?
|
70
|
-
options[answer.to_i-1][0]
|
71
|
-
end
|
72
73
|
|
74
|
+
def print_hours_help(date)
|
75
|
+
puts "Awake log:"
|
76
|
+
begin
|
77
|
+
awake = Awake.new
|
78
|
+
awake.at(date)
|
79
|
+
puts
|
80
|
+
rescue Exception => e
|
81
|
+
print handle_exception("Failed to retrieve awake log.", e)
|
82
|
+
end
|
83
|
+
end
|
73
84
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
awake.at(date)
|
79
|
-
puts
|
80
|
-
rescue Exception => e
|
81
|
-
print handle_exception("Failed to retrieve awake log.", e)
|
82
|
-
end
|
83
|
-
end
|
85
|
+
def hours_chooser
|
86
|
+
answer = Term::ask 'Hours [7:30]'
|
87
|
+
return answer == '' ? '7.5' : answer
|
88
|
+
end
|
84
89
|
|
85
|
-
def hours_chooser
|
86
|
-
answer = Achoo::Term::ask 'Hours [7:30]'
|
87
|
-
return answer == '' ? '7.5' : answer
|
88
|
-
end
|
89
90
|
|
91
|
+
def print_remark_help(date)
|
92
|
+
puts "VCS logs for #{date}:"
|
93
|
+
begin
|
94
|
+
VCS.print_logs_for(date, RC[:vcs_dirs])
|
95
|
+
rescue Exception => e
|
96
|
+
puts handle_exception("Failed to retrieve VCS logs.", e)
|
97
|
+
end
|
98
|
+
puts '-' * 80
|
99
|
+
puts "Calendar events for #{date}:"
|
100
|
+
puts '---'
|
101
|
+
begin
|
102
|
+
RC[:ical].each do |config|
|
103
|
+
ICal.from_http_request(config).print_events(date)
|
104
|
+
end
|
105
|
+
rescue Exception => e
|
106
|
+
puts handle_exception("Failed to retrieve calendar events.", e)
|
107
|
+
end
|
108
|
+
end
|
90
109
|
|
91
|
-
|
92
|
-
|
93
|
-
begin
|
94
|
-
Achoo::VCS.print_logs_for(date, RC[:vcs_dirs])
|
95
|
-
rescue Exception => e
|
96
|
-
puts handle_exception("Failed to retrieve VCS logs.", e)
|
97
|
-
end
|
98
|
-
puts '-' * 80
|
99
|
-
puts "Calendar events for #{date}:"
|
100
|
-
puts '---'
|
101
|
-
begin
|
102
|
-
RC[:ical].each do |config|
|
103
|
-
Achoo::ICal.from_http_request(config).print_events(date)
|
110
|
+
def remark_chooser
|
111
|
+
Term::ask 'Remark'
|
104
112
|
end
|
105
|
-
rescue Exception => e
|
106
|
-
puts handle_exception("Failed to retrieve calendar events.", e)
|
107
|
-
end
|
108
|
-
end
|
109
113
|
|
110
|
-
def remark_chooser
|
111
|
-
Achoo::Term::ask 'Remark'
|
112
|
-
end
|
113
114
|
|
115
|
+
def project_chooser(form)
|
116
|
+
puts 'Recently used projects'
|
117
|
+
projects = form.recent_projects
|
118
|
+
answer = Term.choose('Project [1]', projects.collect { |p| p[1] },
|
119
|
+
'Other', [''])
|
120
|
+
case answer
|
121
|
+
when ''
|
122
|
+
projects[0][0]
|
123
|
+
when '0'
|
124
|
+
return all_projects_chooser(form)
|
125
|
+
else
|
126
|
+
return projects[answer.to_i-1][0]
|
127
|
+
end
|
128
|
+
end
|
114
129
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
projects[0][0]
|
123
|
-
when '0'
|
124
|
-
return all_projects_chooser(form)
|
125
|
-
else
|
126
|
-
return projects[answer.to_i-1][0]
|
130
|
+
|
131
|
+
def all_projects_chooser(form)
|
132
|
+
projects = form.all_projects
|
133
|
+
answer = Term.choose('Project', projects.collect { |p| p[1] })
|
134
|
+
projects[answer.to_i-1][0]
|
135
|
+
end
|
136
|
+
|
127
137
|
end
|
128
138
|
end
|
129
|
-
|
130
|
-
|
131
|
-
def all_projects_chooser(form)
|
132
|
-
projects = form.all_projects
|
133
|
-
answer = Achoo::Term.choose('Project', projects.collect { |p| p[1] })
|
134
|
-
projects[answer.to_i-1][0]
|
135
|
-
end
|
136
|
-
|
137
139
|
end
|
data/lib/achoo/vcs.rb
CHANGED
@@ -1,43 +1,45 @@
|
|
1
|
-
|
1
|
+
require 'achoo'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module Achoo
|
4
|
+
class VCS
|
5
5
|
|
6
|
-
|
6
|
+
autoload :Git, 'achoo/vcs/git'
|
7
|
+
autoload :Subversion, 'achoo/vcs/subversion'
|
8
|
+
|
9
|
+
LINE_LENGTH = 80
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def self.factory(dir)
|
12
|
+
klass = [Git, Subversion].find do |k|
|
13
|
+
k.repository?(dir)
|
14
|
+
end
|
15
|
+
return nil if klass.nil?
|
16
|
+
klass.new(dir)
|
13
17
|
end
|
14
|
-
return nil if klass.nil?
|
15
|
-
klass.new(dir)
|
16
|
-
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def self.print_logs_for(date, vcs_dirs, io=$stdout)
|
20
|
+
vcs_dirs.each do |dir|
|
21
|
+
Dir.glob("#{dir}/*/").each do |dir|
|
22
|
+
vcs = factory(dir)
|
23
|
+
next if vcs.nil?
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
log = vcs.log_for(date)
|
26
|
+
print_log(log, dir, io)
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
+
private
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
def self.print_log(log, dir, io)
|
34
|
+
return if log.empty?
|
35
|
+
io.puts header(dir)
|
36
|
+
io.puts log.chomp
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
def self.header(dir)
|
40
|
+
project = "<( #{File.basename(dir).upcase} )>"
|
41
|
+
dashes = '-' * ((LINE_LENGTH - project.length) / 2)
|
42
|
+
dashes + project + dashes
|
43
|
+
end
|
42
44
|
end
|
43
45
|
end
|
data/lib/achoo/vcs/git.rb
CHANGED
@@ -1,20 +1,24 @@
|
|
1
|
-
|
1
|
+
require 'achoo/vcs'
|
2
2
|
|
3
|
-
|
3
|
+
module Achoo
|
4
|
+
class VCS
|
5
|
+
class Git
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
def self.repository?(dir)
|
8
|
+
File.exists?("#{dir}/.git")
|
9
|
+
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
def initialize(dir)
|
12
|
+
@dir = dir
|
13
|
+
end
|
14
|
+
|
15
|
+
def log_for(date)
|
16
|
+
today = date.strftime('%Y-%m-%d')
|
17
|
+
tomorrow = date.next.strftime('%Y-%m-%d')
|
18
|
+
|
19
|
+
`cd #@dir; git log --author=#{ENV['USER']} --oneline --after=#{today} --before=#{tomorrow} | cut -d ' ' -f 2-`
|
20
|
+
end
|
12
21
|
|
13
|
-
|
14
|
-
today = date.strftime('%Y-%m-%d')
|
15
|
-
tomorrow = date.next.strftime('%Y-%m-%d')
|
16
|
-
|
17
|
-
`cd #@dir; git log --author=#{ENV['USER']} --oneline --after=#{today} --before=#{tomorrow} | cut -d ' ' -f 2-`
|
22
|
+
end
|
18
23
|
end
|
19
|
-
|
20
24
|
end
|
data/lib/achoo/vcs/subversion.rb
CHANGED
@@ -1,32 +1,34 @@
|
|
1
|
+
require 'achoo/vcs'
|
1
2
|
require 'nokogiri'
|
2
3
|
|
3
|
-
|
4
|
+
module Achoo
|
5
|
+
class VCS
|
6
|
+
class Subversion
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
File.exist?("#{dir}/.svn")
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize(dir)
|
12
|
-
@dir = dir
|
13
|
-
end
|
8
|
+
def self.repository?(dir)
|
9
|
+
File.exist?("#{dir}/.svn")
|
10
|
+
end
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
logentries = xml.xpath("/log/logentry/author[contains(., \"#{ENV['USER']}\")]/parent::*")
|
12
|
+
def initialize(dir)
|
13
|
+
@dir = dir
|
14
|
+
end
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
16
|
+
def log_for(date)
|
17
|
+
date = date.strftime("%F")
|
18
|
+
xml = Nokogiri::XML(`cd #@dir; svn log --xml`)
|
19
|
+
logentries = xml.xpath("/log/logentry/author[contains(., \"#{ENV['USER']}\")]/parent::*")
|
20
|
+
|
21
|
+
# FIX are the dates in the xml local time, or do they need to be
|
22
|
+
# converted?
|
23
|
+
log = ""
|
24
|
+
logentries.each do |e|
|
25
|
+
if e.css('date').text.start_with?(date)
|
26
|
+
log << e.css('msg').text.strip << "\n"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
log
|
26
30
|
end
|
31
|
+
|
27
32
|
end
|
28
|
-
log
|
29
33
|
end
|
30
|
-
|
31
|
-
|
32
34
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: achoo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Kjell-Magne \xC3\x98ierud"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-04-
|
12
|
+
date: 2010-04-20 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -45,41 +45,47 @@ extra_rdoc_files: []
|
|
45
45
|
|
46
46
|
files:
|
47
47
|
- bin/awake
|
48
|
+
- bin/ical
|
48
49
|
- bin/achoo
|
49
50
|
- bin/vcs_commits
|
50
|
-
-
|
51
|
-
- lib/achoo/hour_administration_form.rb
|
52
|
-
- lib/achoo/vcs/git.rb
|
53
|
-
- lib/achoo/vcs/subversion.rb
|
54
|
-
- lib/achoo/ui.rb
|
55
|
-
- lib/achoo/term.rb
|
56
|
-
- lib/achoo/system.rb
|
57
|
-
- lib/achoo/open_timespan.rb
|
58
|
-
- lib/achoo/lock_month_form.rb
|
59
|
-
- lib/achoo/hour_registration_form.rb
|
51
|
+
- lib/achoo.rb
|
60
52
|
- lib/achoo/vcs.rb
|
61
|
-
- lib/achoo/ui/date_chooser.rb
|
62
|
-
- lib/achoo/ui/exception_handling.rb
|
63
53
|
- lib/achoo/ui/month_chooser.rb
|
54
|
+
- lib/achoo/ui/common.rb
|
64
55
|
- lib/achoo/ui/commands.rb
|
56
|
+
- lib/achoo/ui/date_chooser.rb
|
57
|
+
- lib/achoo/ui/exception_handling.rb
|
65
58
|
- lib/achoo/ui/optionally_ranged_date_chooser.rb
|
66
|
-
- lib/achoo/ui/common.rb
|
67
59
|
- lib/achoo/ui/date_choosers.rb
|
68
60
|
- lib/achoo/ui/register_hours.rb
|
69
|
-
- lib/achoo/
|
70
|
-
- lib/achoo/
|
71
|
-
- lib/achoo/
|
61
|
+
- lib/achoo/achievo/form.rb
|
62
|
+
- lib/achoo/achievo/lock_month_form.rb
|
63
|
+
- lib/achoo/achievo/login_form.rb
|
64
|
+
- lib/achoo/achievo/hour_registration_form.rb
|
65
|
+
- lib/achoo/achievo/hour_administration_form.rb
|
66
|
+
- lib/achoo/achievo/hour_registration_form_ranged.rb
|
67
|
+
- lib/achoo/achievo/table.rb
|
68
|
+
- lib/achoo/system.rb
|
69
|
+
- lib/achoo/system/log_entry.rb
|
72
70
|
- lib/achoo/system/wtmp.rb
|
71
|
+
- lib/achoo/system/utmp_record.rb
|
73
72
|
- lib/achoo/system/pm_suspend.rb
|
74
|
-
- lib/achoo/
|
75
|
-
- lib/achoo/
|
73
|
+
- lib/achoo/system/cstruct.rb
|
74
|
+
- lib/achoo/vcs/subversion.rb
|
75
|
+
- lib/achoo/vcs/git.rb
|
76
76
|
- lib/achoo/awake.rb
|
77
|
-
- lib/achoo/
|
78
|
-
- lib/achoo/
|
79
|
-
- lib/achoo/form.rb
|
77
|
+
- lib/achoo/term.rb
|
78
|
+
- lib/achoo/app.rb
|
80
79
|
- lib/achoo/term/menu.rb
|
81
80
|
- lib/achoo/term/table.rb
|
82
|
-
- lib/achoo.rb
|
81
|
+
- lib/achoo/extensions.rb
|
82
|
+
- lib/achoo/temporal/open_timespan.rb
|
83
|
+
- lib/achoo/temporal/timespan.rb
|
84
|
+
- lib/achoo/achievo.rb
|
85
|
+
- lib/achoo/temporal.rb
|
86
|
+
- lib/achoo/rc_loader.rb
|
87
|
+
- lib/achoo/ui.rb
|
88
|
+
- lib/achoo/ical.rb
|
83
89
|
- Rakefile
|
84
90
|
- README.rdoc
|
85
91
|
- CHANGES
|