ditz-str 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +24 -0
- data/LICENSE +674 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/README.txt +143 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/bin/ditz-str +189 -0
- data/bugs/issue-02615b8c3dd0382c92f350ce2158ecfe94d11ef8.yaml +22 -0
- data/bugs/issue-06a3bbf35a60c4da2d8ea0fdc86164263126d6b2.yaml +22 -0
- data/bugs/issue-0c00c1d7fdffaad304e62d79d9b3d5e92547055b.yaml +38 -0
- data/bugs/issue-20dad4b4533d6d76d496fe5970098f1eb8efd561.yaml +26 -0
- data/bugs/issue-360ae6529dbc66358fde6b532cbea79ece37a670.yaml +22 -0
- data/bugs/issue-5177d61bf3c2783f71ef63e6e2c5e720247ef699.yaml +18 -0
- data/bugs/issue-695b564c210da1965a2bb38eef782178aead6952.yaml +26 -0
- data/bugs/issue-7d0ce6429a9fb5fa09ce3376a8921a5ecb7ecfe5.yaml +34 -0
- data/bugs/issue-a04462fa22ab6e1b02cfdd052d1f6c6f491f08f5.yaml +22 -0
- data/bugs/issue-bca54ca5107eabc3b281701041cc36ea0641cbdd.yaml +26 -0
- data/bugs/issue-d0c7d04b014d705c5fd865e4d487b5e5b6983c33.yaml +26 -0
- data/bugs/issue-f94b879842aa0274aa74fc2833252d4a06ec65cc.yaml +22 -0
- data/bugs/project.yaml +18 -0
- data/data/ditz-str/blue-check.png +0 -0
- data/data/ditz-str/close.rhtml +39 -0
- data/data/ditz-str/component.rhtml +38 -0
- data/data/ditz-str/dropdown.css +11 -0
- data/data/ditz-str/dropdown.js +58 -0
- data/data/ditz-str/edit_issue.rhtml +53 -0
- data/data/ditz-str/green-bar.png +0 -0
- data/data/ditz-str/green-check.png +0 -0
- data/data/ditz-str/header.gif +0 -0
- data/data/ditz-str/header_over.gif +0 -0
- data/data/ditz-str/index.rhtml +148 -0
- data/data/ditz-str/issue.rhtml +152 -0
- data/data/ditz-str/issue_table.rhtml +28 -0
- data/data/ditz-str/new_component.rhtml +28 -0
- data/data/ditz-str/new_issue.rhtml +57 -0
- data/data/ditz-str/new_release.rhtml +29 -0
- data/data/ditz-str/plugins/git-sync.rb +83 -0
- data/data/ditz-str/plugins/git.rb +153 -0
- data/data/ditz-str/plugins/issue-claiming.rb +174 -0
- data/data/ditz-str/red-check.png +0 -0
- data/data/ditz-str/release.rhtml +111 -0
- data/data/ditz-str/style.css +236 -0
- data/data/ditz-str/unassigned.rhtml +37 -0
- data/data/ditz-str/yellow-bar.png +0 -0
- data/ditz-str.gemspec +121 -0
- data/lib/ditzstr/brick.rb +251 -0
- data/lib/ditzstr/file-storage.rb +54 -0
- data/lib/ditzstr/hook.rb +67 -0
- data/lib/ditzstr/html.rb +104 -0
- data/lib/ditzstr/lowline.rb +201 -0
- data/lib/ditzstr/model-objects.rb +346 -0
- data/lib/ditzstr/model.rb +265 -0
- data/lib/ditzstr/operator.rb +593 -0
- data/lib/ditzstr/trollop.rb +614 -0
- data/lib/ditzstr/util.rb +61 -0
- data/lib/ditzstr/view.rb +16 -0
- data/lib/ditzstr/views.rb +157 -0
- data/lib/ditzstr.rb +69 -0
- data/man/ditz.1 +38 -0
- data/test/helper.rb +18 -0
- data/test/test_ditz-str.rb +7 -0
- metadata +219 -0
@@ -0,0 +1,236 @@
|
|
1
|
+
body {
|
2
|
+
font-family: "lucida grande", "sans serif";
|
3
|
+
color: #333;
|
4
|
+
width: 60em;
|
5
|
+
margin: auto;
|
6
|
+
}
|
7
|
+
|
8
|
+
div.main {
|
9
|
+
padding: 20px;
|
10
|
+
margin: auto;
|
11
|
+
padding-top: 0;
|
12
|
+
margin-top: 1em;
|
13
|
+
background-color: #fcfcfc;
|
14
|
+
}
|
15
|
+
|
16
|
+
.person {
|
17
|
+
font-family: courier;
|
18
|
+
}
|
19
|
+
|
20
|
+
a, a:visited {
|
21
|
+
background: inherit;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
a {
|
26
|
+
color: #003d41;
|
27
|
+
}
|
28
|
+
|
29
|
+
a:visited {
|
30
|
+
color: #553d41;
|
31
|
+
}
|
32
|
+
|
33
|
+
ul {
|
34
|
+
list-style-type: none;
|
35
|
+
padding: 0;
|
36
|
+
}
|
37
|
+
|
38
|
+
p {
|
39
|
+
width: 40em;
|
40
|
+
}
|
41
|
+
|
42
|
+
.inline-status-image {
|
43
|
+
position: relative;
|
44
|
+
top: 0.2em;
|
45
|
+
}
|
46
|
+
|
47
|
+
.dimmed {
|
48
|
+
color: #bbb;
|
49
|
+
}
|
50
|
+
|
51
|
+
table {
|
52
|
+
border-style: none;
|
53
|
+
border-spacing: 0;
|
54
|
+
}
|
55
|
+
|
56
|
+
table.log {
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
td {
|
61
|
+
border-width: 0;
|
62
|
+
border-style: none;
|
63
|
+
padding-right: 0.5em;
|
64
|
+
padding-left: 0.5em;
|
65
|
+
}
|
66
|
+
|
67
|
+
tr {
|
68
|
+
vertical-align: top;
|
69
|
+
}
|
70
|
+
|
71
|
+
h1 {
|
72
|
+
padding: 0.5em;
|
73
|
+
margin-left: -20px;
|
74
|
+
margin-right: -20px;
|
75
|
+
background-color: #305275;
|
76
|
+
margin-top: 0;
|
77
|
+
margin-bottom: 0;
|
78
|
+
color: #fff;
|
79
|
+
}
|
80
|
+
|
81
|
+
h2 {
|
82
|
+
text-transform: uppercase;
|
83
|
+
font-size: smaller;
|
84
|
+
margin-top: 1em;
|
85
|
+
margin-left: -0.5em;
|
86
|
+
width: 100%;
|
87
|
+
/*background: #fffbce;*/
|
88
|
+
/*background: #628a0d;*/
|
89
|
+
padding: 5px;
|
90
|
+
color: #305275;
|
91
|
+
}
|
92
|
+
|
93
|
+
.attrname {
|
94
|
+
text-align: right;
|
95
|
+
font-size: smaller;
|
96
|
+
}
|
97
|
+
|
98
|
+
.attrval {
|
99
|
+
color: #222;
|
100
|
+
}
|
101
|
+
|
102
|
+
.issue-closed-fixed {
|
103
|
+
background-image: "green-check.png";
|
104
|
+
}
|
105
|
+
|
106
|
+
.issue-closed-wontfix {
|
107
|
+
background-image: "red-check.png";
|
108
|
+
}
|
109
|
+
|
110
|
+
.issue-closed-reorg {
|
111
|
+
background-image: "blue-check.png";
|
112
|
+
}
|
113
|
+
|
114
|
+
.inline-issue-link {
|
115
|
+
text-decoration: underline;
|
116
|
+
}
|
117
|
+
|
118
|
+
img {
|
119
|
+
border: 0;
|
120
|
+
}
|
121
|
+
|
122
|
+
/*
|
123
|
+
.issuestatus_closed {
|
124
|
+
background-color: #f2fff2;
|
125
|
+
text-align: center;
|
126
|
+
}
|
127
|
+
|
128
|
+
.issuestatus_in_progress {
|
129
|
+
background-color: #fffff2;
|
130
|
+
text-align: center;
|
131
|
+
}
|
132
|
+
|
133
|
+
.issuestatus_paused {
|
134
|
+
background-color: #fffff2;
|
135
|
+
text-align: center;
|
136
|
+
}
|
137
|
+
|
138
|
+
.issuestatus_unstarted {
|
139
|
+
background-color: #fff2f2;
|
140
|
+
text-align: center;
|
141
|
+
}
|
142
|
+
|
143
|
+
.issuestatus_closed a {
|
144
|
+
color: #202020;
|
145
|
+
}
|
146
|
+
|
147
|
+
.issuestatus_in_progress a {
|
148
|
+
color: #202020;
|
149
|
+
}
|
150
|
+
|
151
|
+
.issuestatus_paused a {
|
152
|
+
color: #202020;
|
153
|
+
}
|
154
|
+
|
155
|
+
.issuestatus_unstarted a {
|
156
|
+
color: #202020;
|
157
|
+
}
|
158
|
+
*/
|
159
|
+
|
160
|
+
div.footer {
|
161
|
+
font-size: small;
|
162
|
+
padding-left: 20px;
|
163
|
+
padding-right: 20px;
|
164
|
+
padding-top: 5px;
|
165
|
+
padding-bottom: 5px;
|
166
|
+
margin: auto;
|
167
|
+
background: #305275;
|
168
|
+
color: #fffee7;
|
169
|
+
}
|
170
|
+
|
171
|
+
.footer a {
|
172
|
+
color: #508d91;
|
173
|
+
}
|
174
|
+
|
175
|
+
.even-row {
|
176
|
+
font-size: smaller;
|
177
|
+
background-color: #f2f2f2;
|
178
|
+
}
|
179
|
+
|
180
|
+
.odd-row {
|
181
|
+
font-size: smaller;
|
182
|
+
background-color: #f2f2f2;
|
183
|
+
}
|
184
|
+
|
185
|
+
.menu {
|
186
|
+
padding: 0.5em;
|
187
|
+
margin-left: -20px;
|
188
|
+
margin-right: -20px;
|
189
|
+
background-color: #305275;
|
190
|
+
margin-top: 0;
|
191
|
+
margin-bottom: 0;
|
192
|
+
color: #fff;
|
193
|
+
}
|
194
|
+
|
195
|
+
.backptr {
|
196
|
+
font-size: smaller;
|
197
|
+
width: 100%;
|
198
|
+
text-align: left;
|
199
|
+
padding-bottom: 1em;
|
200
|
+
margin-top: 0;
|
201
|
+
}
|
202
|
+
|
203
|
+
.logcomment {
|
204
|
+
padding-left: 4em;
|
205
|
+
font-size: smaller;
|
206
|
+
}
|
207
|
+
|
208
|
+
.id {
|
209
|
+
font-family: courier;
|
210
|
+
}
|
211
|
+
|
212
|
+
.description {
|
213
|
+
background: #f2f2f2;
|
214
|
+
padding-left: 1em;
|
215
|
+
padding-right: 1em;
|
216
|
+
padding-top: 0.5em;
|
217
|
+
padding-bottom: 0.5em;
|
218
|
+
}
|
219
|
+
|
220
|
+
.message {
|
221
|
+
}
|
222
|
+
|
223
|
+
.littledate {
|
224
|
+
font-size: smaller;
|
225
|
+
}
|
226
|
+
|
227
|
+
.progress-meter-done {
|
228
|
+
background-color: #03af00;
|
229
|
+
}
|
230
|
+
|
231
|
+
.progress-meter-undone {
|
232
|
+
background-color: #ddd;
|
233
|
+
}
|
234
|
+
|
235
|
+
.progress-meter {
|
236
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
3
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
4
|
+
|
5
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
6
|
+
<head>
|
7
|
+
<title>Issues not assigned to any release</title>
|
8
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
9
|
+
<link rel="stylesheet" href="style.css" type="text/css" />
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
|
13
|
+
<div class="main">
|
14
|
+
<h1>Issues not assigned to any release</h1>
|
15
|
+
<div class="backptr"><%= link_to "index", "« #{project.name} project page" %></div>
|
16
|
+
|
17
|
+
<h2>All issues</h2>
|
18
|
+
<%= render "issue_table", :show_component => false, :show_release => true %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<% if (not brickargs.empty?) && (not brickars[:actions].empty?) %>
|
22
|
+
<h2>Actions</h2><br>
|
23
|
+
<% firstitem = true %>
|
24
|
+
<% brickargs[:actions].each do |actionlink| %>
|
25
|
+
<% if firstitem %>
|
26
|
+
<%= "<a href=\"#{actionlink[1]}\">#{actionlink[0]}</a>" %>
|
27
|
+
<% firstitem = false %>
|
28
|
+
<% else %>
|
29
|
+
<%= " | <a href=\"#{actionlink[1]}\">#{actionlink[0]}</a>" %>
|
30
|
+
<% end %>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
33
|
+
|
34
|
+
<div class="footer">Generated by <a href="http://ditz.rubyforge.org/">ditz</a>.</div>
|
35
|
+
|
36
|
+
</body>
|
37
|
+
</html>
|
Binary file
|
data/ditz-str.gemspec
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ditz-str}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Nils F. Sandell"]
|
12
|
+
s.date = %q{2011-12-03}
|
13
|
+
s.description = %q{Modification of the ditz issue tracking originally created by William Morgan. First new feature is a portable web server for interacting with the issue system.}
|
14
|
+
s.email = %q{nils.sandell@systemstechnologyresearch.com}
|
15
|
+
s.executables = ["ditz-str"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE",
|
18
|
+
"LICENSE.txt",
|
19
|
+
"README.rdoc",
|
20
|
+
"README.txt"
|
21
|
+
]
|
22
|
+
s.files = [
|
23
|
+
".document",
|
24
|
+
"Gemfile",
|
25
|
+
"Gemfile.lock",
|
26
|
+
"LICENSE",
|
27
|
+
"LICENSE.txt",
|
28
|
+
"README.rdoc",
|
29
|
+
"README.txt",
|
30
|
+
"Rakefile",
|
31
|
+
"VERSION",
|
32
|
+
"bin/ditz-str",
|
33
|
+
"bugs/issue-02615b8c3dd0382c92f350ce2158ecfe94d11ef8.yaml",
|
34
|
+
"bugs/issue-06a3bbf35a60c4da2d8ea0fdc86164263126d6b2.yaml",
|
35
|
+
"bugs/issue-0c00c1d7fdffaad304e62d79d9b3d5e92547055b.yaml",
|
36
|
+
"bugs/issue-20dad4b4533d6d76d496fe5970098f1eb8efd561.yaml",
|
37
|
+
"bugs/issue-360ae6529dbc66358fde6b532cbea79ece37a670.yaml",
|
38
|
+
"bugs/issue-5177d61bf3c2783f71ef63e6e2c5e720247ef699.yaml",
|
39
|
+
"bugs/issue-695b564c210da1965a2bb38eef782178aead6952.yaml",
|
40
|
+
"bugs/issue-7d0ce6429a9fb5fa09ce3376a8921a5ecb7ecfe5.yaml",
|
41
|
+
"bugs/issue-a04462fa22ab6e1b02cfdd052d1f6c6f491f08f5.yaml",
|
42
|
+
"bugs/issue-bca54ca5107eabc3b281701041cc36ea0641cbdd.yaml",
|
43
|
+
"bugs/issue-d0c7d04b014d705c5fd865e4d487b5e5b6983c33.yaml",
|
44
|
+
"bugs/issue-f94b879842aa0274aa74fc2833252d4a06ec65cc.yaml",
|
45
|
+
"bugs/project.yaml",
|
46
|
+
"data/ditz-str/blue-check.png",
|
47
|
+
"data/ditz-str/close.rhtml",
|
48
|
+
"data/ditz-str/component.rhtml",
|
49
|
+
"data/ditz-str/dropdown.css",
|
50
|
+
"data/ditz-str/dropdown.js",
|
51
|
+
"data/ditz-str/edit_issue.rhtml",
|
52
|
+
"data/ditz-str/green-bar.png",
|
53
|
+
"data/ditz-str/green-check.png",
|
54
|
+
"data/ditz-str/header.gif",
|
55
|
+
"data/ditz-str/header_over.gif",
|
56
|
+
"data/ditz-str/index.rhtml",
|
57
|
+
"data/ditz-str/issue.rhtml",
|
58
|
+
"data/ditz-str/issue_table.rhtml",
|
59
|
+
"data/ditz-str/new_component.rhtml",
|
60
|
+
"data/ditz-str/new_issue.rhtml",
|
61
|
+
"data/ditz-str/new_release.rhtml",
|
62
|
+
"data/ditz-str/plugins/git-sync.rb",
|
63
|
+
"data/ditz-str/plugins/git.rb",
|
64
|
+
"data/ditz-str/plugins/issue-claiming.rb",
|
65
|
+
"data/ditz-str/red-check.png",
|
66
|
+
"data/ditz-str/release.rhtml",
|
67
|
+
"data/ditz-str/style.css",
|
68
|
+
"data/ditz-str/unassigned.rhtml",
|
69
|
+
"data/ditz-str/yellow-bar.png",
|
70
|
+
"ditz-str.gemspec",
|
71
|
+
"lib/ditzstr.rb",
|
72
|
+
"lib/ditzstr/brick.rb",
|
73
|
+
"lib/ditzstr/file-storage.rb",
|
74
|
+
"lib/ditzstr/hook.rb",
|
75
|
+
"lib/ditzstr/html.rb",
|
76
|
+
"lib/ditzstr/lowline.rb",
|
77
|
+
"lib/ditzstr/model-objects.rb",
|
78
|
+
"lib/ditzstr/model.rb",
|
79
|
+
"lib/ditzstr/operator.rb",
|
80
|
+
"lib/ditzstr/trollop.rb",
|
81
|
+
"lib/ditzstr/util.rb",
|
82
|
+
"lib/ditzstr/view.rb",
|
83
|
+
"lib/ditzstr/views.rb",
|
84
|
+
"man/ditz.1",
|
85
|
+
"test/helper.rb",
|
86
|
+
"test/test_ditz-str.rb"
|
87
|
+
]
|
88
|
+
s.homepage = %q{http://github.com/nsandell/ditz-str}
|
89
|
+
s.licenses = ["GPL"]
|
90
|
+
s.require_paths = ["lib"]
|
91
|
+
s.rubygems_version = %q{1.7.2}
|
92
|
+
s.summary = %q{Customized STR version of ditz issue tracking system (original by William Morgan).}
|
93
|
+
|
94
|
+
if s.respond_to? :specification_version then
|
95
|
+
s.specification_version = 3
|
96
|
+
|
97
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
98
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
99
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
100
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
101
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
102
|
+
s.add_development_dependency(%q<rdoc>, [">= 0"])
|
103
|
+
s.add_runtime_dependency(%q<trollop>, [">= 1.9"])
|
104
|
+
else
|
105
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
106
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
107
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
108
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
109
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
110
|
+
s.add_dependency(%q<trollop>, [">= 1.9"])
|
111
|
+
end
|
112
|
+
else
|
113
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
114
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
115
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
116
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
117
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
118
|
+
s.add_dependency(%q<trollop>, [">= 1.9"])
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
@@ -0,0 +1,251 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
require 'erb'
|
3
|
+
include WEBrick
|
4
|
+
|
5
|
+
module DitzStr
|
6
|
+
|
7
|
+
class BrickView < HtmlView
|
8
|
+
|
9
|
+
def initialize project, config, dir
|
10
|
+
super project, config, dir
|
11
|
+
end
|
12
|
+
|
13
|
+
def link_to name, text
|
14
|
+
links = generate_links
|
15
|
+
return "<a href=\"#{links[name]}\">#{text}</a>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def edit_issue issuename, changes
|
19
|
+
if changes[:description] != nil
|
20
|
+
end
|
21
|
+
if changes[:reporter] != nil
|
22
|
+
end
|
23
|
+
if changes[:title] != nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def comment_on_issue issuename, comment
|
28
|
+
|
29
|
+
issue_res = get_issue_by_name issuename
|
30
|
+
|
31
|
+
if issue_res[0]
|
32
|
+
iss = issue_res[1]
|
33
|
+
iss.log "commented", @config.user, comment
|
34
|
+
return "<html><head><meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=/issue-#{issuename}.html\"></head><body>Redirecting...</body></html>"
|
35
|
+
else
|
36
|
+
return issue_res[1]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_edit_issue issue_id
|
41
|
+
end
|
42
|
+
|
43
|
+
def generate_close_issue issue_id, disposition
|
44
|
+
|
45
|
+
issue_res = get_issue_by_name issue_id
|
46
|
+
|
47
|
+
if issue_res[0]
|
48
|
+
issue = issue_res[1]
|
49
|
+
erb = ERB.new IO.read(File.join(@template_dir, "close.rhtml"))
|
50
|
+
return erb.result binding()
|
51
|
+
else
|
52
|
+
return issue_res[1]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def generate_new_issue options
|
57
|
+
past_rels, upcoming_rels = @project.releases.partition { |r| r.released? }
|
58
|
+
erb = ERB.new IO.read(File.join(@template_dir, "new_issue.rhtml"))
|
59
|
+
return erb.result binding()
|
60
|
+
end
|
61
|
+
|
62
|
+
def generate_new_component
|
63
|
+
erb = ERB.new IO.read(File.join(@template_dir, "new_component.rhtml"))
|
64
|
+
return erb.result binding()
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_new_release
|
68
|
+
erb = ERB.new IO.read(File.join(@template_dir,"new_release.rhtml"))
|
69
|
+
return erb.result binding()
|
70
|
+
end
|
71
|
+
|
72
|
+
def generate_index
|
73
|
+
links = generate_links
|
74
|
+
generate_index_html_str links, {:brick=>true}
|
75
|
+
end
|
76
|
+
|
77
|
+
def generate_release relname
|
78
|
+
|
79
|
+
issue_link = "/new_issue.html?release=#{relname}"
|
80
|
+
#TODO Actions
|
81
|
+
|
82
|
+
links = generate_links
|
83
|
+
r = @project.release_for relname
|
84
|
+
generate_release_html_str links, r, {:brick=>true}
|
85
|
+
end
|
86
|
+
|
87
|
+
def generate_component comp_name
|
88
|
+
|
89
|
+
#TODO Actions
|
90
|
+
issue_link = "/new_issue.html?component=#{comp_name}"
|
91
|
+
|
92
|
+
links = generate_links
|
93
|
+
c = @project.component_for comp_name
|
94
|
+
generate_component_html_str links, c, {:brick=>true}
|
95
|
+
end
|
96
|
+
|
97
|
+
def generate_issue issuename
|
98
|
+
|
99
|
+
links = generate_links
|
100
|
+
|
101
|
+
issue_res = get_issue_by_name issuename
|
102
|
+
|
103
|
+
if issue_res[0]
|
104
|
+
return generate_issue_html_str links, issue_res[1], {:brick=>true}
|
105
|
+
else
|
106
|
+
return issue_res[1]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_issue_by_name issuename
|
111
|
+
issues_vec = @project.issues_for issuename
|
112
|
+
|
113
|
+
case issues_vec.size
|
114
|
+
when 0;
|
115
|
+
return [false,"<html><body>No such issue found...</body></html>"];
|
116
|
+
when 1;
|
117
|
+
return [true,issues_vec.first]
|
118
|
+
else
|
119
|
+
return [false,"<html><body>Multiple issues found...</body></html>"];
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class DitzStrServlet < HTTPServlet::AbstractServlet
|
125
|
+
|
126
|
+
def initialize(server, options)
|
127
|
+
super(server)
|
128
|
+
@project = options[:project]
|
129
|
+
@config = options[:config]
|
130
|
+
@brickview = options[:brickview]
|
131
|
+
@sharedir = options[:dir]
|
132
|
+
@user = options[:user]
|
133
|
+
end
|
134
|
+
|
135
|
+
def do_GET(req,resp)
|
136
|
+
if req.path=="/index.html" or req.path=="/"
|
137
|
+
#puts req.query['wee']
|
138
|
+
resp['content-type'] = 'text/html'
|
139
|
+
resp.body = @brickview.generate_index
|
140
|
+
elsif req.path.start_with? '/release-'
|
141
|
+
relname = req.path.sub('/release-','').sub('.html','')
|
142
|
+
resp['content-type'] = 'text/html'
|
143
|
+
resp.body = @brickview.generate_release relname
|
144
|
+
elsif req.path.start_with? '/component-'
|
145
|
+
compname = req.path.sub('/component-','').sub('.html','')
|
146
|
+
resp['content-type'] = 'text/html'
|
147
|
+
resp.body = @brickview.generate_component compname
|
148
|
+
elsif req.path.start_with? '/issue-'
|
149
|
+
issuename = req.path.sub('/issue-','').sub('.html','')
|
150
|
+
resp['content-type'] = 'text/html'
|
151
|
+
resp.body = @brickview.generate_issue issuename
|
152
|
+
elsif req.path=='/new_issue.html'
|
153
|
+
options = {}
|
154
|
+
if req.query['component']!=nil
|
155
|
+
options[:component] = req.query['component']
|
156
|
+
end
|
157
|
+
if req.query['release']!=nil
|
158
|
+
options[:release] = req.query['release']
|
159
|
+
end
|
160
|
+
options[:creator] = @user
|
161
|
+
resp['content-type'] = 'text/html'
|
162
|
+
resp.body = @brickview.generate_new_issue options
|
163
|
+
elsif req.path=='/new_component.html'
|
164
|
+
resp['content-type'] = 'text/html'
|
165
|
+
resp.body = @brickview.generate_new_component
|
166
|
+
elsif req.path=='/new_release.html'
|
167
|
+
resp['content-type'] = 'text/html'
|
168
|
+
resp.body = @brickview.generate_new_release
|
169
|
+
elsif req.path=='/close.html'
|
170
|
+
resp['content-type'] = 'text/html'
|
171
|
+
if req.query['issue']==nil
|
172
|
+
resp.body = 'Error, no such issue found.'
|
173
|
+
else
|
174
|
+
resp.body = @brickview.generate_close_issue req.query['issue'], req.query['disposition']
|
175
|
+
end
|
176
|
+
else
|
177
|
+
HTTPServlet::FileHandler.new(@server,@sharedir).do_GET(req,resp)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def do_POST(req,resp)
|
182
|
+
resp['content-type'] = 'text/html'
|
183
|
+
|
184
|
+
if req.path.start_with? '/new_issue.html'
|
185
|
+
issue = Issue.create({:project => @project, :config=> @config},{:title => req.query['title'], :desc => req.query['description'], :type => req.query['type'],
|
186
|
+
:component => req.query['component'], :release => req.query['release'], :reporter => 'poop', :comments => req.query['comments']});
|
187
|
+
issue.log "created", @config.user, req.query['comments']
|
188
|
+
resp.body = "<html><head><meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=/component-#{req.query['component']}.html\"></head><body>Redirecting...</body></html>"
|
189
|
+
@project.add_issue issue
|
190
|
+
@project.assign_issue_names!
|
191
|
+
elsif req.path.start_with? '/edit_issue.html'
|
192
|
+
|
193
|
+
elsif req.path.start_with? '/new_component.html'
|
194
|
+
component = Component.create({:project => @project, :config=>@config},{:name => req.query['name']});
|
195
|
+
@project.add_component component
|
196
|
+
resp.body = "<html><head><meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=/index.html\"></head><body>Redirecting...</body></html>"
|
197
|
+
elsif req.path.start_with? '/new_release.html'
|
198
|
+
release = Release.create({:project => @project, :config=>@config},{:name => req.query['name']})
|
199
|
+
release.log "created", @config.user, req.query['comments']
|
200
|
+
@project.add_release release
|
201
|
+
resp.body = "<html><head><meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=/index.html\"></head><body>Redirecting...</body></html>"
|
202
|
+
elsif req.path.start_with? '/issue-'
|
203
|
+
|
204
|
+
issue = "#{req.path}"
|
205
|
+
issue = issue.gsub('/issue-','')
|
206
|
+
issue = issue.gsub('.html','')
|
207
|
+
resp.body = @brickview.comment_on_issue issue, req.query['comment']
|
208
|
+
elsif req.path.start_with? '/close.html'
|
209
|
+
issue_id = req.query['issue']
|
210
|
+
comment = req.query['comment']
|
211
|
+
closer = req.query['closer']
|
212
|
+
disp = req.query['disposition']
|
213
|
+
|
214
|
+
issue_res = @brickview.get_issue_by_name issue_id
|
215
|
+
|
216
|
+
if issue_res[0]
|
217
|
+
iss = issue_res[1]
|
218
|
+
iss.close disp.to_sym, closer, comment
|
219
|
+
resp.body = "<html><head><meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=/issue-#{issue_id}.html\"></head><body>Redirecting...</body></html>"
|
220
|
+
else
|
221
|
+
return issue_res[1]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
class Operator
|
228
|
+
|
229
|
+
def start_webrick(config = {})
|
230
|
+
config.update(:Port => 8080)
|
231
|
+
server = HTTPServer.new(config)
|
232
|
+
yield server if block_given?
|
233
|
+
['INT', 'TERM'].each {|signal|
|
234
|
+
trap(signal) {server.shutdown}
|
235
|
+
}
|
236
|
+
server.start
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
operation :brick, "Start brick web server for issue management.", :maybe_dir
|
241
|
+
def brick project, config, dir
|
242
|
+
brickview = BrickView.new(project,config, dir)
|
243
|
+
sharedir = File.dirname DitzStr::find_ditz_file("index.rhtml")
|
244
|
+
start_webrick { |server|
|
245
|
+
imgdir = File.dirname DitzStr::find_ditz_file("index.rhtml")
|
246
|
+
server.mount('/', DitzStrServlet, {:brickview => brickview, :dir =>sharedir, :user=>config.user, :project=>project, :config=>config })
|
247
|
+
}
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module DitzStr
|
2
|
+
|
3
|
+
## stores ditz database on disk
|
4
|
+
class FileStorage
|
5
|
+
PROJECT_FN = "project.yaml"
|
6
|
+
ISSUE_FN_GLOB = "issue-*.yaml"
|
7
|
+
|
8
|
+
def ISSUE_TO_FN i; "issue-#{i.id}.yaml" end
|
9
|
+
|
10
|
+
def initialize base_dir
|
11
|
+
@base_dir = base_dir
|
12
|
+
@project_fn = File.join @base_dir, PROJECT_FN
|
13
|
+
end
|
14
|
+
|
15
|
+
def load
|
16
|
+
DitzStr::debug "loading project from #{@project_fn}"
|
17
|
+
project = Project.from @project_fn
|
18
|
+
|
19
|
+
fn = File.join @base_dir, ISSUE_FN_GLOB
|
20
|
+
DitzStr::debug "loading issues from #{fn}"
|
21
|
+
project.issues = Dir[fn].map { |fn| Issue.from fn }
|
22
|
+
DitzStr::debug "found #{project.issues.size} issues"
|
23
|
+
|
24
|
+
project.issues.each { |i| i.project = project }
|
25
|
+
project
|
26
|
+
end
|
27
|
+
|
28
|
+
def save project
|
29
|
+
dirty = false
|
30
|
+
dirty = project.each_modelobject { |o| break true if o.changed? }
|
31
|
+
if dirty
|
32
|
+
DitzStr::debug "project is dirty, saving #{@project_fn}"
|
33
|
+
project.save! @project_fn
|
34
|
+
end
|
35
|
+
|
36
|
+
changed_issues = project.issues.select { |i| i.changed? }
|
37
|
+
changed_issues.each do |i|
|
38
|
+
fn = filename_for_issue i
|
39
|
+
DitzStr::debug "issue #{i.name} is dirty, saving #{fn}"
|
40
|
+
i.save! fn
|
41
|
+
end
|
42
|
+
|
43
|
+
project.deleted_issues.each do |i|
|
44
|
+
fn = filename_for_issue i
|
45
|
+
DitzStr::debug "issue #{i.name} has been deleted, deleting #{fn}"
|
46
|
+
FileUtils.rm fn
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def filename_for_issue i; File.join @base_dir, ISSUE_TO_FN(i) end
|
51
|
+
def filename_for_project; @project_fn end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|