wlog 1.1.7 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +100 -39
- data/lib/wlog/commands/bootstrap_templates.rb +5 -0
- data/lib/wlog/commands/delete_attachment.rb +17 -0
- data/lib/wlog/commands/fetch_git_commits.rb +45 -0
- data/lib/wlog/commands/fetch_git_commits_standard.rb +29 -0
- data/lib/wlog/commands/innit_db.rb +3 -2
- data/lib/wlog/commands/write_template.rb +22 -0
- data/lib/wlog/domain/attachment.rb +26 -54
- data/lib/wlog/domain/git_commit.rb +11 -0
- data/lib/wlog/domain/issue.rb +14 -1
- data/lib/wlog/domain/key_value.rb +1 -1
- data/lib/wlog/domain/template_helper.rb +21 -0
- data/lib/wlog/migrations/fix_attachments_polymorphic_table.rb +15 -0
- data/lib/wlog/migrations/make_standard_tables.rb +0 -13
- data/lib/wlog/tech/git_commit_parser.rb +48 -0
- data/lib/wlog/tech/git_commit_printer.rb +19 -0
- data/lib/wlog/tech/uncolored_string.rb +1 -1
- data/lib/wlog/ui/bootstrap.rb +1 -0
- data/lib/wlog/ui/cli_interface.rb +2 -58
- data/lib/wlog/ui/edit_handler.rb +7 -0
- data/lib/wlog/ui/git_ui.rb +47 -0
- data/lib/wlog/ui/invoice_ui.rb +53 -36
- data/lib/wlog/ui/issue_ui.rb +57 -5
- data/lib/wlog/ui/template_ui.rb +2 -2
- data/lib/wlog/version.rb +1 -1
- data/spec/domain/attachment_spec.rb +49 -55
- data/spec/domain/commands/concat_desc_spec.rb +1 -0
- data/spec/domain/commands/new_entry_spec.rb +1 -0
- data/spec/domain/commands/replace_pattern_spec.rb +1 -0
- data/spec/domain/git_commits_spec.rb +85 -0
- data/spec/domain/invoice_spec.rb +35 -0
- data/spec/domain/issue_spec.rb +1 -0
- data/spec/domain/key_value_spec.rb +1 -0
- data/spec/domain/log_entry_spec.rb +1 -0
- data/spec/domain/sys_config_spec.rb +1 -0
- data/spec/spec_helper.rb +31 -0
- data/wlog.gemspec +3 -1
- metadata +40 -18
- data/lib/wlog/domain/session.rb +0 -17
- data/lib/wlog/domain/sql_modules/polymorphic_attachments_sql.rb +0 -24
- data/lib/wlog/domain/template_engine.rb +0 -55
- data/lib/wlog/sql/mono/1.sql +0 -50
- data/lib/wlog/sql/seq/.gitkeep +0 -0
- data/lib/wlog/sql/seq/2.sql +0 -4
- data/lib/wlog/sql/seq/3.sql +0 -3
- data/lib/wlog/ui/commands/ui_command.rb +0 -9
data/lib/wlog/domain/issue.rb
CHANGED
@@ -12,6 +12,7 @@ module Wlog
|
|
12
12
|
class Issue < ActiveRecord::Base
|
13
13
|
|
14
14
|
has_many :log_entries, dependent: :delete_all
|
15
|
+
has_many :attachments, as: :attachable
|
15
16
|
|
16
17
|
StatusNew = 0
|
17
18
|
StatusStarted = 1
|
@@ -40,7 +41,9 @@ class Issue < ActiveRecord::Base
|
|
40
41
|
"#{@strmaker.yellow('Summary')} #{$/}"\
|
41
42
|
" #{description}#{$/ + $/}"\
|
42
43
|
"#{@strmaker.yellow('Description')} #{$/}"\
|
43
|
-
" #{Helpers.break_string(long_description, 80)}#{$/ + $/}"
|
44
|
+
" #{Helpers.break_string(long_description, 80)}#{$/ + $/}"\
|
45
|
+
"#{@strmaker.yellow('Files')}#{$/}"\
|
46
|
+
"#{attachments_s}"
|
44
47
|
end
|
45
48
|
|
46
49
|
# Mark issue as started
|
@@ -65,6 +68,16 @@ private
|
|
65
68
|
StatusFinished => "finished",
|
66
69
|
StatusArchived => "archived"}
|
67
70
|
|
71
|
+
# Stringify attachments for terminal output
|
72
|
+
def attachments_s
|
73
|
+
str = ''
|
74
|
+
self.attachments.each do |att|
|
75
|
+
str.concat(att.to_s)
|
76
|
+
end
|
77
|
+
str = @strmaker.red(" N/A#{$/}") if str == '' # no attachments
|
78
|
+
str.concat($/)
|
79
|
+
str end
|
80
|
+
|
68
81
|
private_class_method
|
69
82
|
|
70
83
|
end # class Issue
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'wlog/domain/key_value'
|
2
|
+
require 'wlog/domain/static_configurations'
|
3
|
+
|
4
|
+
module Wlog
|
5
|
+
# Bunlde helper functions for templates here
|
6
|
+
# @author Simon Symeonidis
|
7
|
+
class TemplateHelper
|
8
|
+
include StaticConfigurations
|
9
|
+
# @return absolute path to the template the user has set
|
10
|
+
def self.template_file
|
11
|
+
num = KeyValue.get('template') || 1
|
12
|
+
Dir[TemplateDir + '*'][num.to_i - 1]
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return template contents of the current selected template
|
16
|
+
def self.template_s
|
17
|
+
File.read(TemplateHelper.template_file)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Wlog
|
4
|
+
# Add type, id polymorphic fields
|
5
|
+
# @author Simon Symeonidis
|
6
|
+
# @date Sun Oct 5 22:43:12 EDT 2014
|
7
|
+
class FixAttachmentsPolymorphicTable < ActiveRecord::Migration
|
8
|
+
|
9
|
+
def change
|
10
|
+
add_column :attachments, :attachable_id, :integer
|
11
|
+
add_column :attachments, :attachable_type, :text
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -44,16 +44,3 @@ class MakeStandardTables < ActiveRecord::Migration
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
=begin
|
49
|
-
TODO
|
50
|
-
-- A polymorphic relationship for attachments. So pretty much anything that
|
51
|
-
-- wants to have something attached, uses the discriminator in order to
|
52
|
-
-- specify itself, as well as its id.
|
53
|
-
CREATE TABLE polymorphic_attachments (
|
54
|
-
discriminator TEXT,
|
55
|
-
discriminator_id INTEGER,
|
56
|
-
attachment_id INTEGER
|
57
|
-
);
|
58
|
-
|
59
|
-
=end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'wlog/domain/git_commit'
|
2
|
+
module Wlog
|
3
|
+
# Parses git text from a `git log` command invocation
|
4
|
+
# @author Simon Symeonidis
|
5
|
+
class GitCommitParser
|
6
|
+
# @param log_s is the string obtained from running a `git log` command
|
7
|
+
# @return a list of GitCommit objects
|
8
|
+
def self.parse(log_s)
|
9
|
+
cur = nil
|
10
|
+
inmessage = false
|
11
|
+
gitlogs = []
|
12
|
+
|
13
|
+
log_s.lines.each do |line|
|
14
|
+
case line
|
15
|
+
when /^commit/i
|
16
|
+
inmessage = false
|
17
|
+
gitlogs.push cur if cur
|
18
|
+
cur = GitCommit.new
|
19
|
+
cur.commit = line.split[1].strip
|
20
|
+
|
21
|
+
when /^author/i
|
22
|
+
next unless cur
|
23
|
+
cur.author = line.split[1].strip
|
24
|
+
|
25
|
+
when /^date/i, /^\n$/
|
26
|
+
next
|
27
|
+
|
28
|
+
else
|
29
|
+
next unless cur
|
30
|
+
if inmessage
|
31
|
+
cur.message.concat(line)
|
32
|
+
cur.message.strip!
|
33
|
+
else
|
34
|
+
cur.shortlog = line
|
35
|
+
cur.shortlog.strip!
|
36
|
+
inmessage = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# if commits have no hash, discard them
|
43
|
+
gitlogs.reject! { |e| e.commit == "" }
|
44
|
+
gitlogs.push cur if cur
|
45
|
+
gitlogs end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'wlog/domain/sys_config'
|
2
|
+
module Wlog
|
3
|
+
# Cute printer for git commit logs
|
4
|
+
# @author Simon Symeonidis
|
5
|
+
module GitCommitPrinter
|
6
|
+
|
7
|
+
def print_git_commits(commit_a)
|
8
|
+
sm = SysConfig.string_decorator
|
9
|
+
|
10
|
+
commit_a.each do |commit|
|
11
|
+
print ' '
|
12
|
+
print sm.blue(commit.commit)
|
13
|
+
print ' '
|
14
|
+
puts sm.green(commit.shortlog[0..50] + ' ...')
|
15
|
+
end
|
16
|
+
nil end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/wlog/ui/bootstrap.rb
CHANGED
@@ -2,7 +2,6 @@ require 'readline'
|
|
2
2
|
require 'wlog/domain/issue'
|
3
3
|
require 'wlog/domain/static_configurations'
|
4
4
|
require 'wlog/domain/sys_config'
|
5
|
-
require 'wlog/domain/attachment'
|
6
5
|
require 'wlog/domain/helpers'
|
7
6
|
|
8
7
|
require 'wlog/commands/create_issue'
|
@@ -14,6 +13,7 @@ require 'wlog/commands/delete_issue'
|
|
14
13
|
require 'wlog/ui/issue_ui'
|
15
14
|
require 'wlog/ui/template_ui'
|
16
15
|
require 'wlog/ui/invoice_ui'
|
16
|
+
require 'wlog/ui/git_ui'
|
17
17
|
|
18
18
|
module Wlog
|
19
19
|
# @author Simon Symeonidis
|
@@ -38,9 +38,6 @@ class CliInterface
|
|
38
38
|
|
39
39
|
case cmd
|
40
40
|
when /^archive/ then archive cmd
|
41
|
-
when /^showattach/ then show_attach
|
42
|
-
when /^outattach/ then output_attach
|
43
|
-
when /^attach/ then attach
|
44
41
|
when /^focus/ then focus(cmd)
|
45
42
|
when /new/ then new_issue
|
46
43
|
when /^(ls|show)/ then show_issues
|
@@ -49,6 +46,7 @@ class CliInterface
|
|
49
46
|
when /^help/ then print_help
|
50
47
|
when /^search/ then search
|
51
48
|
when /^config/ then config
|
49
|
+
when /^git/ then GitUi.new.run
|
52
50
|
when /^templates/ then TemplateUi.new.run
|
53
51
|
when /^invoices/ then InvoiceUi.new.run
|
54
52
|
end
|
@@ -93,32 +91,6 @@ private
|
|
93
91
|
|
94
92
|
puts "No such issue" unless dcmd.deleted?
|
95
93
|
end
|
96
|
-
|
97
|
-
# Wriet out the data contained in the database of the attachment
|
98
|
-
def output_attach
|
99
|
-
puts "Migration of implementation pending"
|
100
|
-
return
|
101
|
-
|
102
|
-
att_id = Readline.readline('Which attachment to output? : ').to_i
|
103
|
-
loc = Readline.readline('Output where (abs dir) ? : ')
|
104
|
-
loc.chomp!
|
105
|
-
att = Attachment.find(@db, Issue.name, att_id)
|
106
|
-
|
107
|
-
fh = File.open("#{loc}/#{att.filename}", 'w')
|
108
|
-
fh.write(att.data)
|
109
|
-
fh.close
|
110
|
-
end
|
111
|
-
|
112
|
-
def show_attach
|
113
|
-
puts "Migration of implementation pending"
|
114
|
-
return
|
115
|
-
issue_id = Readline.readline('Which issue id? : ').to_i
|
116
|
-
atts = Attachment.find_all_by_discriminator(@db, Issue.name, issue_id)
|
117
|
-
atts.each do |att|
|
118
|
-
printf "[%d] - %s (alias: %s)\n", att.id, att.filename, att.given_name
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
94
|
# Archive means set status to 3 (arhive status) to the listed issues
|
123
95
|
def archive(cmd)
|
124
96
|
args = cmd.split[1..-1]
|
@@ -139,32 +111,6 @@ private
|
|
139
111
|
end
|
140
112
|
end
|
141
113
|
|
142
|
-
def attach
|
143
|
-
puts "Migration of implementation pending"
|
144
|
-
return
|
145
|
-
|
146
|
-
issue_id = Readline.readline('Attach to issue id: ').to_i
|
147
|
-
loc = Readline.readline('Absolute file location: ')
|
148
|
-
loc.strip!
|
149
|
-
name_alias = Readline.readline('Alias name for file (optional): ')
|
150
|
-
name_alias.strip!
|
151
|
-
|
152
|
-
unless loc.nil?
|
153
|
-
fh = File.open(loc, "r")
|
154
|
-
data = fh.read
|
155
|
-
fh.close
|
156
|
-
|
157
|
-
att = Attachment.new(@db, Issue.name, issue_id)
|
158
|
-
att.data = data
|
159
|
-
att.filename = loc.split('/').last
|
160
|
-
att.given_name = name_alias
|
161
|
-
att.insert
|
162
|
-
puts 'Attached file.'
|
163
|
-
else
|
164
|
-
puts 'You need to provide a proper path.'
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
114
|
# Focus on an issue to log work etc
|
169
115
|
def focus(cmd)
|
170
116
|
issue_id = cmd.split[1]
|
@@ -200,8 +146,6 @@ private
|
|
200
146
|
'end', 'Exit the progam',
|
201
147
|
'delete', 'Remove the issue with a given id',
|
202
148
|
'archive', 'Archive a file into a specific issue',
|
203
|
-
'showattach', 'Show what files have been attached to an issue',
|
204
|
-
'outattach', 'Extract a file from the database',
|
205
149
|
'invoices', 'Go to invoices interface',
|
206
150
|
'templates', 'Go to template interface, and set templates',
|
207
151
|
'focus', 'Focus on a particular ',
|
data/lib/wlog/ui/edit_handler.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'wlog/domain/sys_config'
|
2
2
|
|
3
3
|
module Wlog
|
4
|
+
# Provides a bunch of edit helping functions for altering already inserted
|
5
|
+
# information about issues.
|
4
6
|
# @author Simon Symeonidis
|
5
7
|
class EditHandler
|
6
8
|
|
@@ -36,7 +38,9 @@ class EditHandler
|
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
41
|
+
# Small helper to parse the due date when editing the dates of issues.
|
39
42
|
# @param time is the date-time in string format (eg Oct 28)
|
43
|
+
# @return nothing - we're just setting if the data format is ok
|
40
44
|
def edit_time(time)
|
41
45
|
date_time = time_handle(time)
|
42
46
|
@issue.update(:due_date => date_time)
|
@@ -46,6 +50,9 @@ class EditHandler
|
|
46
50
|
"Invalid date/time format. Try format like 'Oct 28'"
|
47
51
|
end
|
48
52
|
|
53
|
+
# Edit the reported date of an issue, given a date string in the format of
|
54
|
+
# 'Oct 28'.
|
55
|
+
# @param time_str is the time in string format
|
49
56
|
def edit_reported_time(time_str)
|
50
57
|
date_time = time_handle(time_str)
|
51
58
|
@issue.reported_date = date_time.to_time
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'wlog/domain/sys_config'
|
2
|
+
module Wlog
|
3
|
+
# Interface to setup git stuff.
|
4
|
+
# @author Simon Symeonidis
|
5
|
+
class GitUi
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@strmaker = SysConfig.string_decorator
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
cmd = "default"
|
13
|
+
|
14
|
+
until cmd == "end" do
|
15
|
+
cmd = Readline.readline("[#{@strmaker.blue('git')}] ")
|
16
|
+
|
17
|
+
case cmd
|
18
|
+
when /^set/
|
19
|
+
path = Readline.readline("Path to git repo (eg: project/.git/): ")
|
20
|
+
|
21
|
+
unless File.directory? path
|
22
|
+
puts @strmaker.red("That doesn't look like a git repo. Nothing done")
|
23
|
+
next
|
24
|
+
end
|
25
|
+
|
26
|
+
author = Readline.readline("git author: ")
|
27
|
+
|
28
|
+
# Set the git repo in the db (so one git repo per db)
|
29
|
+
KeyValue.put!("git", path)
|
30
|
+
KeyValue.put!("author", author)
|
31
|
+
|
32
|
+
when /^unset/
|
33
|
+
KeyValue.put!("git", "")
|
34
|
+
|
35
|
+
when /^(ls|show)/
|
36
|
+
print ' repo: '
|
37
|
+
puts @strmaker.green(KeyValue.get("git"))
|
38
|
+
print ' auth: '
|
39
|
+
puts @strmaker.yellow(KeyValue.get("author"))
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
data/lib/wlog/ui/invoice_ui.rb
CHANGED
@@ -2,6 +2,11 @@ require 'readline'
|
|
2
2
|
require 'wlog/domain/invoice'
|
3
3
|
require 'wlog/domain/sys_config'
|
4
4
|
require 'wlog/domain/static_configurations'
|
5
|
+
require 'wlog/domain/template_helper'
|
6
|
+
require 'wlog/commands/write_template'
|
7
|
+
require 'wlog/commands/fetch_git_commits'
|
8
|
+
require 'wlog/commands/fetch_git_commits_standard'
|
9
|
+
require 'wlog/tech/git_commit_printer'
|
5
10
|
require 'erb'
|
6
11
|
|
7
12
|
module Wlog
|
@@ -9,6 +14,7 @@ module Wlog
|
|
9
14
|
# @author Simon Symeonidis
|
10
15
|
class InvoiceUi
|
11
16
|
include StaticConfigurations
|
17
|
+
include GitCommitPrinter
|
12
18
|
|
13
19
|
def initialize
|
14
20
|
@strmaker = SysConfig.string_decorator
|
@@ -24,6 +30,8 @@ class InvoiceUi
|
|
24
30
|
when /^(ls|show)/ then ls
|
25
31
|
when /^delete/ then delete(cmd.split.drop 1)
|
26
32
|
when /^generate/ then generate(cmd.split.drop 1)
|
33
|
+
when /^commits/ then commits(cmd.split.drop 1)
|
34
|
+
when 'help' then print_help
|
27
35
|
when /^end/ then next
|
28
36
|
else
|
29
37
|
puts "type 'help' for a list of options"
|
@@ -36,25 +44,19 @@ private
|
|
36
44
|
# TODO maybe separate this in the future for better testing.
|
37
45
|
def generate(rest)
|
38
46
|
num = rest.first || 1
|
47
|
+
|
39
48
|
@invoice = Invoice.find(num.to_i)
|
40
|
-
|
41
|
-
|
42
|
-
@les = @invoice.log_entries_within_dates
|
43
|
-
@issues = [Issue.find(*(@les.collect(&:issue_id).uniq))].compact.flatten
|
44
|
-
|
45
|
-
# Get the template
|
46
|
-
num = SysConfig.get_config('template') || 1
|
47
|
-
tpath = Dir[TemplateDir + '*'][num.to_i - 1]
|
48
|
-
template_s = File.read(tpath)
|
49
|
+
cmd = FetchGitCommitsStandard.new(@invoice.from, @invoice.to)
|
50
|
+
cmd.execute
|
49
51
|
|
50
|
-
|
52
|
+
@log_entries = @invoice.log_entries_within_dates
|
53
|
+
@issues = [Issue.find(*(@log_entries.collect(&:issue_id).uniq))].compact.flatten
|
54
|
+
@commits = cmd.commits
|
55
|
+
|
56
|
+
renderer = ERB.new(TemplateHelper.template_s)
|
51
57
|
output = renderer.result(binding)
|
52
58
|
|
53
|
-
|
54
|
-
template_ext = tpath.split(File::SEPARATOR).last.split('.').last
|
55
|
-
filename = TemplateOutputDir + "#{@invoice.id}-invoice.#{template_ext}"
|
56
|
-
|
57
|
-
File.write(filename, output)
|
59
|
+
WriteTemplate.new(output, @invoice).execute
|
58
60
|
|
59
61
|
rescue ActiveRecord::RecordNotFound
|
60
62
|
puts 'No such invoice'
|
@@ -105,29 +107,44 @@ private
|
|
105
107
|
# TODO: this would have to be factored out at some point. Also I think the
|
106
108
|
# implementation is crappy. I have to recheck at some point.
|
107
109
|
def longtext
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
count = 0
|
122
|
-
end
|
123
|
-
else
|
124
|
-
# reset blank line count. The user will have to hammer enter a few times
|
125
|
-
# to escape from this menu
|
126
|
-
count = 0
|
127
|
-
end
|
128
|
-
end
|
110
|
+
count = 0
|
111
|
+
status = nil
|
112
|
+
str = ""
|
113
|
+
|
114
|
+
until status == :end_text do
|
115
|
+
line = Readline.readline(@strmaker.blue('> ')).strip
|
116
|
+
count += 1 if line == ""
|
117
|
+
count = 0 if line != ""
|
118
|
+
|
119
|
+
str.concat(line).concat($/)
|
120
|
+
|
121
|
+
status = :end_text and next if count == 2
|
122
|
+
end
|
129
123
|
str end
|
130
124
|
|
125
|
+
def commits(invoice_id)
|
126
|
+
inv = Invoice.find_by_id(invoice_id)
|
127
|
+
repo = KeyValue.get('git')
|
128
|
+
author = KeyValue.get('author')
|
129
|
+
|
130
|
+
unless repo
|
131
|
+
puts @strmaker.red("You need to set a git repo first")
|
132
|
+
return
|
133
|
+
end
|
134
|
+
|
135
|
+
command = FetchGitCommits.new(inv.from, inv.to, repo, author)
|
136
|
+
command.execute
|
137
|
+
|
138
|
+
puts
|
139
|
+
print ' '
|
140
|
+
puts "git commits for #{@strmaker.yellow(author)}"
|
141
|
+
puts
|
142
|
+
print_git_commits(command.commits)
|
143
|
+
|
144
|
+
rescue ActiveRecord::RecordNotFound
|
145
|
+
puts @strmaker.red("No such invoice")
|
146
|
+
end
|
147
|
+
|
131
148
|
end
|
132
149
|
end
|
133
150
|
|