TicGit-ng 1.0.2.4 → 1.0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.mkd +8 -13
- data/lib/ticgit-ng/base.rb +3 -5
- data/lib/ticgit-ng/cli.rb +1 -1
- data/lib/ticgit-ng/command.rb +5 -2
- data/lib/ticgit-ng/ticket.rb_ +258 -0
- data/lib/ticgit-ng/version.rb +1 -1
- metadata +5 -5
- data/lib/ticgit-ng.rb_ +0 -35
data/README.mkd
CHANGED
@@ -29,13 +29,9 @@ Required Ruby Gems: git
|
|
29
29
|
|
30
30
|
To install these packages on a Debian system, or a Debian based system like Ubuntu, do
|
31
31
|
|
32
|
-
sudo
|
32
|
+
sudo aptitude install git ruby rubygems
|
33
33
|
sudo gem install git
|
34
34
|
|
35
|
-
After installing Gems it is necessary to update the PATH environment variable so that the scripts can be found. Issue the following command to the end of your .bachrc file or equivalent.
|
36
|
-
|
37
|
-
PATH=$PATH:/var/lib/gems/1.8/bin
|
38
|
-
|
39
35
|
**ticgitweb**
|
40
36
|
|
41
37
|
Required Packages: git, ruby, rubygems
|
@@ -44,9 +40,11 @@ Required Ruby Gems: git, sinatra, haml, sass
|
|
44
40
|
|
45
41
|
To install these packages on a Debian system, or a Debian based system like Ubuntu, do
|
46
42
|
|
47
|
-
sudo
|
48
|
-
sudo gem install git sinatra haml
|
49
|
-
|
43
|
+
sudo aptitude install git ruby rubygems
|
44
|
+
sudo gem install git sinatra haml sass
|
45
|
+
|
46
|
+
|
47
|
+
|
50
48
|
|
51
49
|
**A Note about rubygems**
|
52
50
|
|
@@ -62,22 +60,19 @@ The git gem requires a git version of 1.6.0.0 or later, but on Debian stable, gi
|
|
62
60
|
|
63
61
|
If these annoy you as they do me and you've set up [apt](http://jaqque.sbih.org/kplug/apt-pinning.html) [pinning](http://jeffwelling.github.com//2010/09/05/Apt-Pinning.html), you can do
|
64
62
|
|
65
|
-
sudo
|
63
|
+
$ sudo aptitude -t testing install git-core
|
66
64
|
|
67
65
|
And those notices should go away.
|
68
66
|
|
69
|
-
**A Note about Ubuntu**
|
70
67
|
|
71
|
-
NB At the time of writing (Ver 1.0.2.3) there are additional problems with TigGitWeb Ubuntu. The workaround is to add `/var/lib/gems/1.8/gems/TicGit-ng-1.0.2.3/bin` to start of PATH. viz
|
72
68
|
|
73
|
-
PATH=/var/lib/gems/1.8/gems/TicGit-ng-1.0.2.3/bin:$PATH
|
74
69
|
|
75
70
|
### Installing ##
|
76
71
|
Installation on a Debian stable system. Note that the command line interface for TicGit-ng can be run from Debian stable, but some of the gems required for the web interface may require you to use [apt](http://jaqque.sbih.org/kplug/apt-pinning.html) [pinning](http://jeffwelling.github.com//2010/09/05/Apt-Pinning.html) to run without errors. See below
|
77
72
|
|
78
73
|
To install TicGit-ng on your system, you can go one of two ways,
|
79
74
|
|
80
|
-
$
|
75
|
+
$ gem install TicGit-ng
|
81
76
|
|
82
77
|
or, you can install it from source by downloading this repository building your own gem (see below).
|
83
78
|
|
data/lib/ticgit-ng/base.rb
CHANGED
@@ -206,11 +206,9 @@ module TicGitNG
|
|
206
206
|
if ticket_id
|
207
207
|
ticket_id = ticket_id.strip
|
208
208
|
|
209
|
-
if /^[0-9]*$/ =~ ticket_id
|
210
|
-
|
211
|
-
|
212
|
-
end
|
213
|
-
else # partial or full sha
|
209
|
+
if /^[0-9]*$/ =~ ticket_id && (t = @last_tickets[ticket_id.to_i - 1])
|
210
|
+
return t
|
211
|
+
elsif ticket_id.length > 4 # partial (5 characters or greater to be considered unique enough) or full sha
|
214
212
|
regex = /^#{Regexp.escape(ticket_id)}/
|
215
213
|
ch = tickets.select{|name, t|
|
216
214
|
t['files'].assoc('TICKET_ID')[1] =~ regex }
|
data/lib/ticgit-ng/cli.rb
CHANGED
@@ -20,10 +20,10 @@ module TicGitNG
|
|
20
20
|
attr_accessor :out
|
21
21
|
|
22
22
|
def initialize(args, path = '.', out = $stdout)
|
23
|
-
@out = out
|
24
23
|
@args = args.dup
|
25
24
|
@tic = TicGitNG.open(path, :keep_state => true)
|
26
25
|
@options = OpenStruct.new
|
26
|
+
@out = out
|
27
27
|
|
28
28
|
@out.sync = true # so that Net::SSH prompts show up
|
29
29
|
rescue NoRepoFound
|
data/lib/ticgit-ng/command.rb
CHANGED
@@ -9,7 +9,7 @@ module TicGitNG
|
|
9
9
|
commands.each{|cmd| COMMANDS[cmd] = mod_name }
|
10
10
|
end
|
11
11
|
|
12
|
-
register 'Assign', '
|
12
|
+
register 'Assign', 'Assings a ticket to someone', 'assign'
|
13
13
|
register 'Attach', 'Attach file to ticket', 'attach'
|
14
14
|
register 'Checkout', 'Checkout a ticket', 'checkout', 'co'
|
15
15
|
register 'Comment', 'Comment on a ticket', 'comment'
|
@@ -40,7 +40,10 @@ module TicGitNG
|
|
40
40
|
o.top.append ' ', nil, nil
|
41
41
|
o.top.append 'The available ticgit commands are:', nil, nil
|
42
42
|
|
43
|
-
DOC.
|
43
|
+
sorted_doc = DOC.sort_by do |cmds, doc|
|
44
|
+
cmds.sort_by{|cmd| cmd.size }.last
|
45
|
+
end
|
46
|
+
sorted_doc.each do |commands, doc|
|
44
47
|
# get the longest version
|
45
48
|
command = commands.sort_by{|cmd| cmd.size }.last
|
46
49
|
o.top.append(" %-32s %s" % [command, doc], nil, nil)
|
@@ -0,0 +1,258 @@
|
|
1
|
+
module TicGitNG
|
2
|
+
class Ticket
|
3
|
+
|
4
|
+
attr_reader :base, :opts
|
5
|
+
attr_accessor :ticket_id, :ticket_name
|
6
|
+
attr_accessor :title, :state, :milestone, :assigned, :opened, :points
|
7
|
+
attr_accessor :comments, :tags, :attachments # arrays
|
8
|
+
|
9
|
+
def initialize(base, options = {})
|
10
|
+
# FIXME: what/where/who/how changed config to hash?
|
11
|
+
if (cfg = base.git.config).is_a? Hash
|
12
|
+
options[:user_name] ||= cfg["user.name"]
|
13
|
+
options[:user_email] ||= cfg["user.email"]
|
14
|
+
else
|
15
|
+
options[:user_name] ||= cfg("user.name")
|
16
|
+
options[:user_email] ||= cfg("user.email")
|
17
|
+
end
|
18
|
+
|
19
|
+
@base = base
|
20
|
+
@opts = options || {}
|
21
|
+
|
22
|
+
@state = 'open' # by default
|
23
|
+
@comments = []
|
24
|
+
@tags = []
|
25
|
+
@attachments = []
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.create(base, title, options = {})
|
29
|
+
t = Ticket.new(base, options)
|
30
|
+
t.title = title
|
31
|
+
t.ticket_name = self.create_ticket_name(title)
|
32
|
+
t.save_new
|
33
|
+
t
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.open(base, ticket_name, ticket_hash, options = {})
|
37
|
+
tid = nil
|
38
|
+
|
39
|
+
t = Ticket.new(base, options)
|
40
|
+
t.ticket_name = ticket_name
|
41
|
+
|
42
|
+
title, date = self.parse_ticket_name(ticket_name)
|
43
|
+
t.opened = date
|
44
|
+
|
45
|
+
ticket_hash['files'].each do |fname, value|
|
46
|
+
if fname == 'TICKET_ID'
|
47
|
+
tid = value
|
48
|
+
elsif fname == 'TICKET_TITLE'
|
49
|
+
t.title = base.git.gblob(value).contents
|
50
|
+
else
|
51
|
+
# matching
|
52
|
+
data = fname.split('_')
|
53
|
+
|
54
|
+
case data[0]
|
55
|
+
when 'ASSIGNED'
|
56
|
+
t.assigned = data[1]
|
57
|
+
when 'ATTACHMENT'
|
58
|
+
t.attachments << TicGitNG::Attachment.new(base, fname, value)
|
59
|
+
when 'COMMENT'
|
60
|
+
t.comments << TicGitNG::Comment.new(base, fname, value)
|
61
|
+
when 'POINTS'
|
62
|
+
t.points = base.git.gblob(value).contents.to_i
|
63
|
+
when 'STATE'
|
64
|
+
t.state = data[1]
|
65
|
+
when 'TAG'
|
66
|
+
t.tags << data[1]
|
67
|
+
when 'TITLE'
|
68
|
+
t.title = base.git.gblob(value).contents
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
t.ticket_id = tid
|
74
|
+
t
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def self.parse_ticket_name(name)
|
79
|
+
epoch, title, rand = name.split('_')
|
80
|
+
title = title.gsub('-', ' ')
|
81
|
+
return [title, Time.at(epoch.to_i)]
|
82
|
+
end
|
83
|
+
|
84
|
+
# write this ticket to the git database
|
85
|
+
def save_new
|
86
|
+
base.in_branch do |wd|
|
87
|
+
files=[]
|
88
|
+
t=nil
|
89
|
+
base.logger.info "saving #{ticket_name}"
|
90
|
+
|
91
|
+
Dir.mkdir(ticket_name)
|
92
|
+
Dir.chdir(ticket_name) do
|
93
|
+
base.new_file('TICKET_ID', ticket_name)
|
94
|
+
files << File.join( ticket_name, 'TICKET_ID' )
|
95
|
+
base.new_file('TICKET_TITLE', title)
|
96
|
+
files << File.join( ticket_name, 'TICKET_TITLE' )
|
97
|
+
base.new_file( (t='ASSIGNED_'+email) , email)
|
98
|
+
files << File.join( ticket_name, t )
|
99
|
+
base.new_file( (t='STATE_'+state) , state)
|
100
|
+
files << File.join( ticket_name, t )
|
101
|
+
base.new_file('TITLE', title)
|
102
|
+
files << File.join( ticket_name, 'TITLE' )
|
103
|
+
|
104
|
+
# add initial comment
|
105
|
+
#COMMENT_080315060503045__schacon_at_gmail
|
106
|
+
if opts[:comment]
|
107
|
+
base.new_file(t=comment_name(email), opts[:comment])
|
108
|
+
files << File.join( ticket_name, t )
|
109
|
+
end
|
110
|
+
|
111
|
+
# add initial tags
|
112
|
+
if opts[:tags] && opts[:tags].size > 0
|
113
|
+
opts[:tags] = opts[:tags].map { |t| t.strip }.compact
|
114
|
+
opts[:tags].each do |tag|
|
115
|
+
if tag.size > 0
|
116
|
+
tag_filename = 'TAG_' + Ticket.clean_string(tag)
|
117
|
+
if !File.exists?(tag_filename)
|
118
|
+
base.new_file(tag_filename, tag_filename)
|
119
|
+
files << File.join( ticket_name, tag_filename )
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
files.each {|file|
|
126
|
+
base.git.add file
|
127
|
+
}
|
128
|
+
base.git.commit("added ticket #{ticket_name}")
|
129
|
+
end
|
130
|
+
# ticket_id
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.clean_string(string)
|
134
|
+
string.downcase.gsub(/[^a-z0-9]+/i, '-')
|
135
|
+
end
|
136
|
+
|
137
|
+
def add_comment(comment)
|
138
|
+
return false if !comment
|
139
|
+
base.in_branch do |wd|
|
140
|
+
t=nil
|
141
|
+
Dir.chdir(ticket_name) do
|
142
|
+
base.new_file(t=comment_name(email), comment)
|
143
|
+
end
|
144
|
+
base.git.add File.join(ticket_name, t)
|
145
|
+
base.git.commit("added comment to ticket #{ticket_name}")
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def change_state(new_state)
|
150
|
+
return false if !new_state
|
151
|
+
return false if new_state == state
|
152
|
+
|
153
|
+
base.in_branch do |wd|
|
154
|
+
Dir.chdir(ticket_name) do
|
155
|
+
base.new_file(t='STATE_' + new_state, new_state)
|
156
|
+
end
|
157
|
+
base.git.remove(File.join(ticket_name,'STATE_' + state))
|
158
|
+
base.git.add File.join(ticket_name, t)
|
159
|
+
base.git.commit("added state (#{new_state}) to ticket #{ticket_name}")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def change_assigned(new_assigned)
|
164
|
+
new_assigned ||= email
|
165
|
+
old_assigned= assigned || ''
|
166
|
+
return false if new_assigned == old_assigned
|
167
|
+
|
168
|
+
base.in_branch do |wd|
|
169
|
+
t=nil
|
170
|
+
Dir.chdir(ticket_name) do
|
171
|
+
base.new_file(t='ASSIGNED_' + new_assigned, new_assigned)
|
172
|
+
end
|
173
|
+
base.git.remove(File.join(ticket_name,'ASSIGNED_' + old_assigned))
|
174
|
+
base.git.add File.join(ticket_name,t)
|
175
|
+
base.git.commit("assigned #{new_assigned} to ticket #{ticket_name}")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def change_points(new_points)
|
180
|
+
return false if new_points == points
|
181
|
+
|
182
|
+
base.in_branch do |wd|
|
183
|
+
Dir.chdir(ticket_name) do
|
184
|
+
base.new_file('POINTS', new_points)
|
185
|
+
end
|
186
|
+
base.git.add File.join(ticket_name, 'POINTS')
|
187
|
+
base.git.commit("set points to #{new_points} for ticket #{ticket_name}")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def add_tag(tag)
|
192
|
+
return false if !tag
|
193
|
+
files=[]
|
194
|
+
added = false
|
195
|
+
tags = tag.split(',').map { |t| t.strip }
|
196
|
+
base.in_branch do |wd|
|
197
|
+
Dir.chdir(ticket_name) do
|
198
|
+
tags.each do |add_tag|
|
199
|
+
if add_tag.size > 0
|
200
|
+
tag_filename = 'TAG_' + Ticket.clean_string(add_tag)
|
201
|
+
if !File.exists?(tag_filename)
|
202
|
+
base.new_file(tag_filename, tag_filename)
|
203
|
+
files << File.join( ticket_name, tag_filename )
|
204
|
+
added = true
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
if added
|
210
|
+
files.each {|file|
|
211
|
+
base.git.add file
|
212
|
+
}
|
213
|
+
base.git.commit("added tags (#{tag}) to ticket #{ticket_name}")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def remove_tag(tag)
|
219
|
+
return false if !tag
|
220
|
+
removed = false
|
221
|
+
tags = tag.split(',').map { |t| t.strip }
|
222
|
+
base.in_branch do |wd|
|
223
|
+
tags.each do |add_tag|
|
224
|
+
tag_filename = File.join(ticket_name, 'TAG_' + Ticket.clean_string(add_tag))
|
225
|
+
if File.exists?(tag_filename)
|
226
|
+
base.git.remove(tag_filename)
|
227
|
+
removed = true
|
228
|
+
end
|
229
|
+
end
|
230
|
+
if removed
|
231
|
+
base.git.commit("removed tags (#{tag}) from ticket #{ticket_name}")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def path
|
237
|
+
File.join(state, ticket_name)
|
238
|
+
end
|
239
|
+
|
240
|
+
def comment_name(email)
|
241
|
+
'COMMENT_' + Time.now.to_i.to_s + '_' + email
|
242
|
+
end
|
243
|
+
|
244
|
+
def email
|
245
|
+
opts[:user_email] || 'anon'
|
246
|
+
end
|
247
|
+
|
248
|
+
def assigned_name
|
249
|
+
assigned.split('@').first rescue ''
|
250
|
+
end
|
251
|
+
|
252
|
+
def self.create_ticket_name(title)
|
253
|
+
[Time.now.to_i.to_s, Ticket.clean_string(title), rand(999).to_i.to_s].join('_')
|
254
|
+
end
|
255
|
+
|
256
|
+
|
257
|
+
end
|
258
|
+
end
|
data/lib/ticgit-ng/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: TicGit-ng
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 93
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
9
|
- 2
|
10
|
-
-
|
11
|
-
version: 1.0.2.
|
10
|
+
- 5
|
11
|
+
version: 1.0.2.5
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Scott Chacon
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-
|
20
|
+
date: 2011-05-26 00:00:00 -04:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -61,10 +61,10 @@ extra_rdoc_files: []
|
|
61
61
|
files:
|
62
62
|
- bin/ti
|
63
63
|
- bin/ticgitweb
|
64
|
-
- lib/ticgit-ng.rb_
|
65
64
|
- lib/ticgit-ng.rb
|
66
65
|
- lib/ticgit-ng/base.rb
|
67
66
|
- lib/ticgit-ng/ticket.rb
|
67
|
+
- lib/ticgit-ng/ticket.rb_
|
68
68
|
- lib/ticgit-ng/cli.rb
|
69
69
|
- lib/ticgit-ng/version.rb
|
70
70
|
- lib/ticgit-ng/command/assign.rb
|
data/lib/ticgit-ng.rb_
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'logger'
|
3
|
-
require 'optparse'
|
4
|
-
require 'ostruct'
|
5
|
-
require 'set'
|
6
|
-
require 'yaml'
|
7
|
-
|
8
|
-
# Add the directory containing this file to the start of the load path if it
|
9
|
-
# isn't there already.
|
10
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
11
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
12
|
-
|
13
|
-
require 'rubygems'
|
14
|
-
# requires git >= 1.0.5
|
15
|
-
require 'git'
|
16
|
-
require 'ticgit-ng/base'
|
17
|
-
require 'ticgit-ng/cli'
|
18
|
-
|
19
|
-
module TicGitNG
|
20
|
-
autoload :VERSION, 'ticgit-ng/version'
|
21
|
-
autoload :Comment, 'ticgit-ng/comment'
|
22
|
-
autoload :Ticket, 'ticgit-ng/ticket'
|
23
|
-
|
24
|
-
# options
|
25
|
-
# :logger => Logger.new(STDOUT)
|
26
|
-
def self.open(git_dir, options = {})
|
27
|
-
Base.new(git_dir, options)
|
28
|
-
end
|
29
|
-
|
30
|
-
class OpenStruct < ::OpenStruct
|
31
|
-
def to_hash
|
32
|
-
@table.dup
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|