]>
Commit | Line | Data |
---|---|---|
84fb5b46 MKG |
1 | =head1 Development of RT |
2 | ||
3 | RT's source code is stored in a C<git> repository. If you are not | |
4 | familiar with git, see L</git quickstart>, below, for a short tutorial | |
5 | which will give you enough information to get started submitting patches | |
6 | to RT. | |
7 | ||
8 | The rest of this document details conventions and tips surrounding the | |
9 | organization of RT's version control, source code conventions, and how | |
10 | to submit patches. | |
11 | ||
12 | ||
13 | ||
14 | =head1 Organization of rt.git | |
15 | ||
16 | The RT source repository is available via git from GitHub; you can | |
17 | browse it at L<http://github.com/bestpractical/rt/> or obtain a local | |
18 | copy via: | |
19 | ||
20 | git clone git://github.com/bestpractical/rt.git | |
21 | ||
22 | The bleeding-edge development happens in the C<master> branch. When a | |
23 | major release is anticipated, a "trunk" branch will be branched from | |
24 | this -- for example, C<4.0-trunk>. This will allow the trunk to | |
25 | stabilize while feature development continues on C<master>. | |
26 | Additionally, as a release is impending for a particular series, a | |
27 | release engineering branch will be created, named, for example | |
28 | C<4.0.0-releng>. | |
29 | ||
30 | New feature development should always be based off of the C<master> | |
31 | branch. Branches to fix bugs should be based off of whichever trunk the | |
32 | bug was first found in. If you found the bug in your RT 4.0.0 install, | |
33 | you'd branch from 4.0-trunk. | |
34 | ||
35 | Branches should be named based on the trunk they are branched | |
36 | from -- which is to say, the earliest branch they might be merged into. | |
37 | For example, a bugfix branched from C<4.0-trunk> might be named | |
38 | C<4.0/fail-taint-mode-early>. A feature branched from C<master> when | |
39 | there exists a C<4.0-trunk> but no C<4.2-trunk> might be named | |
40 | C<4.2/rename-LogToScreen>. For consistency, branches should use dashes, | |
403d7b0b MKG |
41 | not underscores, to separate words. Branches which are destined for |
42 | 4.2, but which are branched from 4.0 (to provide for easy extraction as | |
43 | a 4.0 extension) should be named 4.2-on-4.0/branch-name. | |
84fb5b46 MKG |
44 | |
45 | Branches should be reviewed by another developer before being merged. | |
46 | Reviewers should make sure that the branch accomplishes what it claims | |
47 | to, and does not introduce any unwanted behavior in doing so. Commit | |
48 | messages explain the B<why> as much as the B<what> of each commit, and | |
49 | not include extranous changes. | |
50 | ||
51 | ||
52 | =head1 Code conventions | |
53 | ||
54 | The RT codebase is more than ten years old; as such, there are sections | |
55 | which do not (yet) conform to the guidelines below. Please attempt to | |
56 | follow the guidelines, even if the code surrounding your changes does | |
57 | not yet. | |
58 | ||
59 | RT also includes a F<.perltidyrc> in its top-level which encodes many of | |
60 | the conventions. | |
61 | ||
62 | =over | |
63 | ||
64 | =item Indentation | |
65 | ||
66 | Each level of indentation should be four spaces; tabs should never be | |
67 | used for indentation. | |
68 | ||
69 | =back | |
70 | ||
71 | =head1 Internationalization | |
72 | ||
73 | RT has been translated into several dozen languages. We use Launchpad | |
74 | ( https://translations.launchpad.net/rt ) to crowdsource our | |
75 | translations into C<po> files. RT uses L<Locale::Maketext> to | |
76 | localize its user interface. | |
77 | ||
78 | Your first stop on this magical journey of internationalization | |
79 | is L<Locale::Maketext::TPJ13>, which explains the whys of | |
80 | L<Locale::Maketext>. RT uses most of the features developed in that | |
81 | article. | |
82 | ||
83 | Strings that are displayed to users should be passed through the | |
84 | C<loc("...")> function or the C<< <&|/l&>...</&> >> Mason template. | |
85 | C<loc> and C</l> both take parameters, which are used in place of | |
86 | string interpolation (much like C<sprintf>). It's acceptable to use | |
87 | HTML in C</l> calls, especially for bold and emphasis. However, you | |
88 | should limit the amount of HTML that translators must keep exactly | |
89 | correct, which means avoid including tags that wrap the entire | |
90 | translatable string, especially C<< <p> >>. | |
91 | ||
92 | <p><&|/l, $button &>Do <em>not</em> click [_1]</&></p> # ok | |
93 | ||
94 | <&|/l, $button &><p>Do <em>not</em> click [_1]</p></&> # not ok | |
95 | ||
96 | In a few places in RT we also pass HTML as parameters to C<loc()> | |
97 | so that translators do not have to reproduce it exactly, and we can | |
98 | also change it more freely. For example: | |
99 | ||
100 | <&|/l, | |
101 | '<a href="http://www.gnu.org/licenses/gpl-2.0.html">', | |
102 | '</a>', | |
103 | &>Distributed under [_1]version 2 of the GNU GPL[_2].</&> | |
104 | ||
105 | F<devel/tools/extract-message-catalog> looks for C<loc("...")> and | |
106 | C<< <&|/l&>...</&> >> in our source code to pick out translatable | |
107 | strings, clean them up, and put them into F<share/po> files. We use | |
108 | our C<.po> files not only to populate L<Locale::Maketext>'s lexicons, | |
109 | but also to sync new translatable strings and translations with | |
110 | Launchpad. This Launchpad sync is typically done early during the | |
111 | freeze of RC releases to give our volunteer translators time to | |
112 | translate all the new strings which, because of the RC freeze, won't | |
113 | continue changing. | |
114 | ||
115 | Because C<loc()> and C</l> are used to generate strings for human | |
116 | eyes, they generally must be used "close to the browser". These are | |
117 | directly in Mason templates, or in functions that return text that | |
118 | will be passed through Mason. However, in many places in RT we have | |
119 | hardcoded strings which need translations. For example, the C<$RIGHTS> | |
120 | hash in F<lib/RT/Queue.pm> maps rights' names (which must be | |
121 | translatable) to their descriptions (which also must be translatable). | |
122 | However, when we're declaring such structures, we do not want to | |
123 | translate them straight away. RT uses English internally, including | |
124 | in its web forms, so we do not want to localize rights' names except | |
125 | for display, otherwise things might break weirdly when you check | |
126 | if a user has the "Superusuario" right. Furthermore, when we're | |
127 | declaring such data structures at compile time, there is no current | |
128 | user to select which language to use for localization. Thus, we | |
129 | cannot call C<loc()> when declaring C<$RIGHTS> and other similar | |
130 | places. | |
131 | ||
132 | For this reason, F<devel/tools/extract-message-catalog> lets you | |
133 | denote translatable strings with comments. That's what the C<#loc_pair> | |
134 | comments in the C<$RIGHTS> hash in F<lib/RT/Queue.pm> indicate. | |
135 | Since we have those comments, our toolchain will put the rights' | |
136 | names and descriptions into F<share/po> files, which enables | |
137 | translation by our lovely volunteers. Later on, when RT displays | |
138 | information about rights in the web UI, we'll pass the right's name | |
139 | through C<loc>, and L<Locale::Maketext> will then be able to find | |
140 | our "Superusuario". So although we never used a literal | |
141 | C<loc("SuperUser")>, we still get its effects thanks to the | |
142 | C<#loc_pair> comments and using C<loc($RightName)>. | |
143 | ||
144 | C<#loc_pair> is used for declaring that the both the key and value | |
145 | of a particular C<< key => value >> pair are translatable. There | |
146 | are other markers that you can use. | |
147 | ||
148 | C<#loc> is used for declaring that a particular string is translatable. | |
149 | Its parsing is pretty strict so you can use it to declare that only | |
150 | the value of a particular C<< key => value >> pair is translatable. | |
151 | ||
152 | C<#loc_left_pair> is used for declaring that the I<key> of a | |
153 | particular C<< key => value >> pair is translatable. This is of | |
154 | very limited usefulness. | |
155 | ||
c33a4027 MKG |
156 | C<#loc_right_pair> does NOT exist. C<#loc> works in such cases since its |
157 | parser does not extend beyond the string at the end of a line. However, | |
158 | if the string is I<not> at the end of the line, C<#loc{word}> declares | |
159 | that the value associated with the key I<word> (earlier on the same | |
160 | line) is to be loc'd. This is useful for inline hashes: | |
161 | ||
162 | # Note the string "baz" is to be loc'd | |
163 | foo => { bar => "baz", troz => "zort" }, # loc{bar} | |
84fb5b46 MKG |
164 | |
165 | =head1 Development tips | |
166 | ||
167 | =head2 Setting up a development environment | |
168 | ||
169 | =head2 Test suite | |
170 | ||
171 | RT also comes with a fairly complete test suite. To run it, you will | |
172 | need to set environment variables to a database user and password which | |
173 | can create and drop databases: | |
174 | ||
175 | export RT_DBA_USER=root | |
176 | export RT_DBA_PASSWORD= | |
177 | ||
178 | You'll need to configure RT and make sure you have all the dependencies | |
179 | before running tests. To do this in place without installing: | |
180 | ||
af59614d | 181 | ./configure.ac --with-my-user-group --enable-layout=inplace --enable-developer |
84fb5b46 MKG |
182 | make testdeps |
183 | make fixdeps | |
184 | ||
185 | Adjust the relevant database options as necessary if you want to test on | |
186 | Postgres, Oracle, or SQLite. The default is MySQL. | |
187 | ||
188 | To run the test suite: | |
189 | ||
190 | make test | |
191 | ||
192 | If you have multiple processors, you can run the test suite in parallel, | |
193 | which will be significantly faster: | |
194 | ||
195 | make test-parallel | |
196 | ||
b5747ff2 MKG |
197 | The C<*-trunk> and C<master> branches are expected to always be passing |
198 | all tests. While it is acceptable to break tests in an intermediate | |
199 | commit, a branch which does not pass tests will not be merged. Ideally, | |
200 | commits which fix a bug should also include a testcase which fails | |
201 | before the fix and succeeds after. | |
84fb5b46 MKG |
202 | |
203 | ||
204 | ||
205 | =head1 git quickstart | |
206 | ||
207 | =over | |
208 | ||
209 | =item 1. | |
210 | ||
211 | You will first need to obtain a copy of git; this is accomplished via | |
212 | C<sudo yum install git> in RedHat and derivatives, or C<sudo apt-get | |
213 | install git> for Debian or Ubuntu. | |
214 | ||
215 | =item 2. | |
216 | ||
217 | Next, obtain a copy of the RT source from git: | |
218 | ||
219 | git clone git://github.com/bestpractical/rt.git | |
220 | cd rt | |
221 | ||
222 | =item 3. | |
223 | ||
224 | Configure git to know your name and email address; git uses these when | |
225 | it makes commits. | |
226 | ||
227 | git config user.email your.email@example.com | |
228 | git config user.name Examp L. Name | |
229 | ||
230 | =item 4. | |
231 | ||
232 | Switch to the appropriate point to base your work on; this is generally | |
233 | C<origin/> followed by the major version, followed by C<-trunk>. For | |
234 | example, if your bug was observed in version 3.8.9, you would choose | |
235 | C<origin/3.8-trunk>; if it was in 4.0.0, you would choose | |
236 | C<origin/4.0-trunk>. New features should be based on C<origin/master>. | |
237 | ||
238 | git checkout --track origin/4.0-trunk | |
239 | ||
240 | =item 5. | |
241 | ||
242 | Give your branch a name based on what you are attempting to accomplish. | |
243 | We suggest that branch names be lower-case and separate words with | |
244 | dashes, but this branch name is purely for your own reference. | |
245 | ||
246 | git branch -m gnupg-encryption | |
247 | ||
248 | =item 6. | |
249 | ||
250 | Edit the source tree to make your changes. A few commands you may find | |
251 | useful in doing so are listed below. | |
252 | ||
253 | To see what files you have changed: | |
254 | ||
255 | git status | |
256 | ||
257 | To see a line-by-line list of changes: | |
258 | ||
259 | git diff | |
260 | ||
261 | To revert a file to the original version: | |
262 | ||
263 | git checkout path/to/file | |
264 | ||
265 | To revert only individual parts of a file: | |
266 | ||
267 | git checkout -p path/to/file | |
268 | ||
269 | See L</Development tips> for more tips for working with the RT codebase. | |
270 | ||
271 | =item 7. | |
272 | ||
273 | Check that you have no extraneous changes using C<git diff>, then commit | |
274 | your changes: | |
275 | ||
276 | git commit -a | |
277 | ||
278 | You will be prompted to type your commit message. The first line should | |
279 | be a short (E<lt> 80 character) summary of the changes, followed by a | |
280 | blank line, followed by a longer description, if necessary. The commit | |
281 | message should not simply restate the diff of which lines were added and | |
282 | subtracted, but should rather explain B<what> those changes accomplish, | |
283 | and B<why> they are desired. | |
284 | ||
285 | If your changes are easily split into multiple components, you may wish | |
286 | to split your changes into more than one commit; simply return to step 6 | |
287 | and repeat the with the next related change. If your changes are B<not> | |
288 | related to each other, you should submit them separately; finish step 9, | |
289 | then start over from step 4. | |
290 | ||
291 | =item 8. | |
292 | ||
293 | Save your commits to patch files: | |
294 | ||
295 | git format-patch @{u} | |
296 | ||
297 | This will print out the names of the files as it creates them. | |
298 | ||
299 | =item 9. | |
300 | ||
301 | Attach these files to an email using your standard email client, and | |
302 | send it to C<rt-devel@bestpractical.com>. | |
303 | ||
304 | =back | |
305 | ||
306 | If you have another bug or feature to implement, simply restart the | |
307 | process at step 4. | |
308 | ||
309 | =cut |