source: trunk/lib/Trac.cc @ 301

Last change on this file since 301 was 301, checked in by Peter Johansson, 14 years ago

fixes #187 and another bug in comment

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.6 KB
Line 
1// $Id: Trac.cc 301 2007-05-10 18:46:36Z peter $
2
3/*
4  Copyright (C) 2007 Peter Johansson
5
6  This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest
7
8  svndigest is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  svndigest is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21  02111-1307, USA.
22*/
23
24#include "Trac.h"
25
26#include "Configuration.h"
27#include "HtmlStream.h"
28#include "html_utility.h"
29#include "utility.h"
30
31namespace theplu{
32namespace svndigest{
33
34  Trac::Trac(HtmlStream& hs)
35    : hs_(hs) 
36  {}
37
38  bool Trac::changeset(std::string::const_iterator& first, 
39                       const std::string::const_iterator& last)
40  {
41    if (changeset1(first, last))
42      return true;
43    if (changeset2(first, last))
44      return true;
45    if (changeset3(first, last))
46      return true;
47    return false;
48  }
49
50
51  bool Trac::changeset1(std::string::const_iterator& first, 
52                        const std::string::const_iterator& last)
53  {
54    if (first==last)
55      return false;
56    if (*first != 'r')
57      return false;
58    const std::string::const_iterator first_orig(first);
59    ++first;
60    std::string rev = match(first, last, Digit());
61    if (rev.empty()){
62      first = first_orig;
63      return false;
64    }
65    std::string href(Configuration::instance().trac_root()+"changeset/"+rev);
66    hs_.stream() << anchor(href, std::string(first_orig,first)); 
67    return true;
68  }
69
70
71  bool Trac::changeset2(std::string::const_iterator& first, 
72                        const std::string::const_iterator& last)
73  {
74    if (first==last)
75      return false;
76    if (*first != '[')
77      return false;
78    const std::string::const_iterator first_orig(first);
79    ++first;
80    std::string rev = match(first, last, Digit());
81    if (rev.empty() || first==last || *first!=']'){
82      first = first_orig;
83      return false;
84    }
85    ++first;
86    std::string href(Configuration::instance().trac_root()+"changeset/"+rev);
87    hs_.stream() << anchor(href, std::string(first_orig,first)); 
88    return true;
89  }
90
91
92  bool Trac::changeset3(std::string::const_iterator& first, 
93                        const std::string::const_iterator& last)
94  {
95    if (first==last)
96      return false;
97    const std::string::const_iterator first_orig(first);
98    if (match(first, last, Str("changeset:")).empty()){
99      first = first_orig;
100      return false;
101    }
102    std::string rev = match(first, last, Digit());
103    if (rev.empty()){
104      first = first_orig;
105      return false;
106    }
107    std::string href(Configuration::instance().trac_root()+"changeset/"+rev);
108    hs_.stream() << anchor(href, std::string(first_orig,first)); 
109    return true;
110  }
111
112
113  void Trac::print(std::string str)
114  {
115    std::string::const_iterator first(str.begin());
116    while (first!=str.end()) {
117      if (log(first, str.end()))
118        continue;
119      if (ticket(first, str.end()))
120        continue;
121      if (comment(first, str.end()))
122        continue;
123      if (changeset(first, str.end()))
124        continue;
125      if (diff(first, str.end()))
126        continue;
127      if (milestone(first, str.end()))
128        continue;
129      if (source(first, str.end()))
130        continue;
131      hs_ << *first;
132      ++first;
133    }
134  }
135
136
137  bool Trac::comment(std::string::const_iterator& first, 
138                     const std::string::const_iterator& last)
139  {
140    if (first==last)
141      return false;
142
143    const std::string::const_iterator first_orig(first);
144    if (match(first, last, Str("comment:ticket:")).empty()){
145      first = first_orig;
146      return false;
147    }
148     
149    std::string ticket = match(first, last, Digit());
150    if (ticket.empty() || first == last || *first != ':') {
151      first = first_orig;
152      return false;
153    }
154    ++first;
155    std::string comment = match(first, last, Digit());
156    if (comment.empty() ) {
157      first = first_orig;
158      return false;
159    }
160    std::string href(Configuration::instance().trac_root()+"ticket/"+ticket+
161                     "#comment:"+comment);
162    std::string str(first_orig, first);
163    hs_.stream() << anchor(href, str); 
164    return true;
165
166
167    const Configuration& conf = Configuration::instance();
168    hs_.stream() << anchor(conf.trac_root()+"ticket/"+ticket+
169                           "#comment:"+comment,
170                           std::string(first_orig, first)); 
171    return true;
172
173  }
174
175
176  bool Trac::milestone(std::string::const_iterator& first, 
177                       const std::string::const_iterator& last)
178  {
179    if (first==last)
180      return false;
181
182    const std::string::const_iterator first_orig(first);
183
184    if (match(first, last, Str("milestone:")).empty()){
185      first = first_orig;
186      return false;
187    }
188
189    const std::string::const_iterator milestone_begin(first);
190
191    // find the last alphanumerical char before next space (or last)
192    for (std::string::const_iterator i(first); i!=last && *i!=' '; ++i)
193      if (isalnum(*i)) 
194        first = i+1;
195
196    std::cerr << "BUG HERE because of above non-initialization" << std::endl;
197    std::string milestone(milestone_begin, first);
198    if (milestone.empty()){
199      first = first_orig;
200      return false;
201    }
202
203    const Configuration& conf = Configuration::instance();
204    hs_.stream() << anchor(conf.trac_root()+"milestone/"+milestone,
205                           std::string(first_orig, first)); 
206    return true;
207  }
208
209
210  bool Trac::source(std::string::const_iterator& first, 
211                    const std::string::const_iterator& last)
212  {
213    if (first==last)
214      return false;
215
216    const std::string::const_iterator first_orig(first);
217
218    if (match(first, last, Str("source:")).empty()){
219      first = first_orig;
220      return false;
221    }
222
223    std::string node;
224    std::string rev;
225    std::string line;
226    const std::string::const_iterator node_begin(first);
227
228    node = match(first, last, not2Char('@', ' '));
229    if (!node.empty() && node[0]=='/')
230      node = node.substr(1, node.size()-1); 
231 
232    if (*first == '@'){
233      ++first;
234      rev = match(first, last, Digit());
235      if (*first == '#') {
236        ++first;
237        line = match(first, last, notChar(' '));
238      }
239    }
240
241    const Configuration& conf = Configuration::instance();
242    std::string href(conf.trac_root()+node);
243    if (!rev.empty()) {
244      href += "@"+rev;
245      if (!line.empty())
246        href += "#"+line;
247    }
248    hs_.stream() << anchor(href, std::string(first_orig, first)); 
249    return true;
250  }
251
252
253  bool Trac::ticket(std::string::const_iterator& first, 
254                    const std::string::const_iterator& last)
255  {
256    if (ticket1(first, last))
257      return true;
258    if (ticket2(first, last))
259      return true;
260    return false;
261  }
262
263
264  bool Trac::ticket1(std::string::const_iterator& first, 
265                     const std::string::const_iterator& last)
266  {
267    if (first==last)
268      return false;
269
270    const std::string::const_iterator first_orig(first);
271    if (*first != '#')
272      return false;
273    ++first;
274    std::string ticket = match(first, last, Digit());
275
276    if (ticket.empty()) {
277      first = first_orig;
278      return false;
279    }
280
281    const Configuration& conf = Configuration::instance();
282    hs_.stream() << anchor(conf.trac_root()+"ticket/"+ticket,
283                           std::string(first_orig, first)); 
284    return true;
285  }
286
287
288  bool Trac::ticket2(std::string::const_iterator& first, 
289                     const std::string::const_iterator& last)
290  {
291    if (first==last)
292      return false;
293
294    const std::string::const_iterator first_orig(first);
295
296    if (match(first, last, Str("ticket:")).empty()){
297      first = first_orig;
298      return false;
299    }
300     
301    std::string ticket = match(first, last, Digit());
302
303    const Configuration& conf = Configuration::instance();
304    hs_.stream() << anchor(conf.trac_root()+"ticket/"+ticket,"#"+ticket); 
305    return true;
306  }
307
308
309  bool Trac::diff(std::string::const_iterator& first, 
310                  const std::string::const_iterator& last)
311  {
312    if (diff1(first, last))
313      return true;
314    if (diff3(first, last))
315      return true;
316    if (diff2(first, last))
317      return true;
318    return false;
319  }
320
321
322  bool Trac::diff1(std::string::const_iterator& first, 
323                   const std::string::const_iterator& last)
324  {
325    if (first==last)
326      return false;
327
328    const std::string::const_iterator first_orig(first);
329    if (match(first, last, Str("diff:")).empty()){
330      first = first_orig;
331      return false;
332    }
333    std::string node = match(first, last, notChar('@'));
334    if (first==last){
335      first = first_orig;
336      return false;
337    }
338    ++first; 
339    std::string old_rev = match(first, last, Digit());
340    if (old_rev.empty() || first == last || *first != ':') {
341      first = first_orig;
342      return false;
343    }
344    ++first;
345    std::string new_rev = match(first, last, Digit());
346    if (new_rev.empty() ) {
347      first = first_orig;
348      return false;
349    }
350    std::string href;
351    if (node.empty())
352      href = std::string(Configuration::instance().trac_root()+
353                         "changeset?new="+new_rev+"&old="+old_rev);
354    else
355      href = std::string(Configuration::instance().trac_root()+
356                         "changeset?new="+new_rev+"&new_path="+node+"&old="+
357                         old_rev+"&oldpath="+node);
358    hs_.stream() << anchor(href, std::string(first_orig, first)); 
359    return true;
360  }
361
362
363  bool Trac::diff2(std::string::const_iterator& first, 
364                   const std::string::const_iterator& last)
365  {
366    if (first==last)
367      return false;
368
369    const std::string::const_iterator first_orig(first);
370    if (match(first, last, Str("diff:")).empty()){
371      first = first_orig;
372      return false;
373    }
374    std::string old_path(match(first, last, not2Str("//", " ")));
375    std::string new_path;
376    if (first==last || *first==' ')
377      new_path = old_path;
378    else {
379      first += 2;
380      new_path = match(first, last, notChar(' '));
381    }
382    if (new_path.empty() || old_path.empty()){
383      first = first_orig;
384      return false;
385    }
386    std::string href(Configuration::instance().trac_root()+
387                     "changeset?new_path="+new_path+"&old_path="+old_path);
388    hs_.stream() << anchor(href, std::string(first_orig, first)); 
389    return true;
390  }
391
392
393  bool Trac::diff3(std::string::const_iterator& first, 
394                   const std::string::const_iterator& last)
395  {
396    if (first==last)
397      return false;
398
399    const std::string::const_iterator first_orig(first);
400    if (match(first, last, Str("diff:")).empty()){
401      first = first_orig;
402      return false;
403    }
404    std::string old_path(match(first, last, not2Char('@', ' ')));
405    if (*first!='@'){
406      first = first_orig;
407      return false;
408    }
409    ++first;
410    std::string old_rev(match(first, last, Digit()));
411    if (!match_begin(first, first+1, std::string("//"))) {
412      first = first_orig;
413      return false;
414    }
415    first+2;
416    std::string new_path = match(first, last, not2Char('@', ' '));
417    if (*first!='@'){
418      first = first_orig;
419      return false;
420    }
421    ++first;
422    std::string new_rev(match(first, last, Digit()));
423    if (new_rev.empty()){
424      first = first_orig;
425      return false;
426    }
427   
428    std::string href(Configuration::instance().trac_root()+
429                     "changeset?new="+new_rev+"&new_path="+new_path+
430                     "&old="+old_rev+"&old_path="+old_path);
431    hs_.stream() << anchor(href, std::string(first_orig, first)); 
432    return true;
433  }
434
435
436  bool Trac::log(std::string::const_iterator& first, 
437                 const std::string::const_iterator& last)
438  {
439    if (log1(first, last))
440      return true;
441    if (log2(first, last))
442      return true;
443    if (log3(first, last))
444      return true;
445    return false;
446  }
447
448
449  bool Trac::log1(std::string::const_iterator& first, 
450                     const std::string::const_iterator& last)
451  {
452    if (first==last)
453      return false;
454
455    const std::string::const_iterator first_orig(first);
456    if (*first != 'r')
457      return false;
458    ++first;
459
460    std::string stop_rev = match(first, last, Digit());
461    if (stop_rev.empty() || first == last || *first != ':') {
462      first = first_orig;
463      return false;
464    }
465    ++first;
466    std::string rev = match(first, last, Digit());
467    if (rev.empty() ) {
468      first = first_orig;
469      return false;
470    }
471    std::string href(Configuration::instance().trac_root()+"log/?rev="+
472                     rev+"&stop_rev="+stop_rev);
473    hs_.stream() << anchor(href, std::string(first_orig, first)); 
474    return true;
475  }
476
477
478  bool Trac::log2(std::string::const_iterator& first, 
479                     const std::string::const_iterator& last)
480  {
481    if (first==last)
482      return false;
483
484    const std::string::const_iterator first_orig(first);
485    if (*first != '[')
486      return false;
487    ++first;
488
489    std::string stop_rev = match(first, last, Digit());
490    if (stop_rev.empty() || first == last || *first != ':') {
491      first = first_orig;
492      return false;
493    }
494    ++first;
495    std::string rev = match(first, last, Digit());
496    if (rev.empty() || first == last || *first != ']') {
497      first = first_orig;
498      return false;
499    }
500    std::string href(Configuration::instance().trac_root()+"log/?rev="+
501                     rev+"&stop_rev="+stop_rev);
502    hs_.stream() << anchor(href, std::string(first_orig, first)); 
503    return true;
504  }
505
506
507  bool Trac::log3(std::string::const_iterator& first, 
508                  const std::string::const_iterator& last)
509  {
510    if (first==last)
511      return false;
512
513    const std::string::const_iterator first_orig(first);
514
515    const std::string log_str("log:"); 
516    if (!match_begin(first, last, log_str)) {
517      first = first_orig;
518      return false;
519    }
520    first += log_str.size();
521    std::string node = match(first, last, not2Char('#', '@'));
522    ++first;
523    std::string stop_rev = match(first, last, Digit());
524    if (stop_rev.empty() || first == last || *first != ':') {
525      first = first_orig;
526      return false;
527    }
528    ++first;
529    std::string rev = match(first, last, Digit());
530    if (rev.empty() ) {
531      first = first_orig;
532      return false;
533    }
534    std::string href;
535    if (!node.empty() && node[0]=='/')
536      href = std::string(Configuration::instance().trac_root()+"log"+node+
537                         "?rev="+rev+"&stop_rev="+stop_rev);
538    else
539      href = std::string(Configuration::instance().trac_root()+"log/"+node+
540                         "?rev="+rev+"&stop_rev="+stop_rev);
541     
542    hs_.stream() << anchor(href, std::string(first_orig, first)); 
543    return true;
544  }
545
546}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.