source: branches/0.6-stable/lib/Trac.cc @ 451

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

changing lev.thep.lu.se to trac.thep.lu.se

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