source: trunk/lib/Trac.cc @ 295

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

refs #180 support milestone:0.6

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.4 KB
Line 
1// $Id: Trac.cc 295 2007-05-08 18:47:00Z 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      hs_ << *first;
130      ++first;
131    }
132  }
133
134
135  bool Trac::comment(std::string::const_iterator& first, 
136                     const std::string::const_iterator& last)
137  {
138    if (first==last)
139      return false;
140
141    const std::string::const_iterator first_orig(first);
142    if (match(first, last, Str("comment:ticket:")).empty()){
143      first = first_orig;
144      return false;
145    }
146     
147    std::string ticket = match(first, last, Digit());
148    if (ticket.empty() || first == last || *first != ':') {
149      first = first_orig;
150      return false;
151    }
152    ++first;
153    std::string comment = match(first, last, Digit());
154    if (comment.empty() ) {
155      first = first_orig;
156      return false;
157    }
158    std::string href(Configuration::instance().trac_root()+"ticket/"+ticket+
159                     "#comment:"+comment);
160    std::string str(first_orig, first);
161    hs_.stream() << anchor(href, str); 
162    return true;
163
164
165    const Configuration& conf = Configuration::instance();
166    hs_.stream() << anchor(conf.trac_root()+"ticket/"+ticket,"#"+ticket); 
167    return true;
168
169  }
170
171
172  bool Trac::milestone(std::string::const_iterator& first, 
173                       const std::string::const_iterator& last)
174  {
175    if (first==last)
176      return false;
177
178    const std::string::const_iterator first_orig(first);
179
180    if (match(first, last, Str("milestone:")).empty()){
181      first = first_orig;
182      return false;
183    }
184
185    const std::string::const_iterator milestone_begin;
186
187    // find the last alphanumerical char before next space (or last)
188    for (std::string::const_iterator i(first); i!=last && *i!=' '; ++i)
189      if (isalnum(*i)) 
190        first = i;
191
192    std::string milestone(milestone_begin, first);
193    if (milestone.empty()){
194      first = first_orig;
195      return false;
196    }
197
198    const Configuration& conf = Configuration::instance();
199    hs_.stream() << anchor(conf.trac_root()+"milestone/"+milestone,
200                           std::string(first_orig, first)); 
201    return true;
202  }
203
204
205  bool Trac::ticket(std::string::const_iterator& first, 
206                    const std::string::const_iterator& last)
207  {
208    if (ticket1(first, last))
209      return true;
210    if (ticket2(first, last))
211      return true;
212    return false;
213  }
214
215
216  bool Trac::ticket1(std::string::const_iterator& first, 
217                     const std::string::const_iterator& last)
218  {
219    if (first==last)
220      return false;
221
222    const std::string::const_iterator first_orig(first);
223    if (*first != '#')
224      return false;
225    ++first;
226    std::string ticket = match(first, last, Digit());
227
228    if (ticket.empty()) {
229      first = first_orig;
230      return false;
231    }
232
233    const Configuration& conf = Configuration::instance();
234    hs_.stream() << anchor(conf.trac_root()+"ticket/"+ticket,
235                           std::string(first_orig, first)); 
236    return true;
237  }
238
239
240  bool Trac::ticket2(std::string::const_iterator& first, 
241                     const std::string::const_iterator& last)
242  {
243    if (first==last)
244      return false;
245
246    const std::string::const_iterator first_orig(first);
247
248    if (match(first, last, Str("ticket:")).empty()){
249      first = first_orig;
250      return false;
251    }
252     
253    std::string ticket = match(first, last, Digit());
254
255    const Configuration& conf = Configuration::instance();
256    hs_.stream() << anchor(conf.trac_root()+"ticket/"+ticket,"#"+ticket); 
257    return true;
258  }
259
260
261  bool Trac::diff(std::string::const_iterator& first, 
262                  const std::string::const_iterator& last)
263  {
264    if (diff1(first, last))
265      return true;
266    if (diff3(first, last))
267      return true;
268    if (diff2(first, last))
269      return true;
270    return false;
271  }
272
273
274  bool Trac::diff1(std::string::const_iterator& first, 
275                   const std::string::const_iterator& last)
276  {
277    if (first==last)
278      return false;
279
280    const std::string::const_iterator first_orig(first);
281    if (match(first, last, Str("diff:")).empty()){
282      first = first_orig;
283      return false;
284    }
285    std::string node = match(first, last, notChar('@'));
286    if (first==last){
287      first = first_orig;
288      return false;
289    }
290    ++first; 
291    std::string old_rev = match(first, last, Digit());
292    if (old_rev.empty() || first == last || *first != ':') {
293      first = first_orig;
294      return false;
295    }
296    ++first;
297    std::string new_rev = match(first, last, Digit());
298    if (new_rev.empty() ) {
299      first = first_orig;
300      return false;
301    }
302    std::string href;
303    if (node.empty())
304      href = std::string(Configuration::instance().trac_root()+
305                         "changeset?new="+new_rev+"&old="+old_rev);
306    else
307      href = std::string(Configuration::instance().trac_root()+
308                         "changeset?new="+new_rev+"&new_path="+node+"&old="+
309                         old_rev+"&oldpath="+node);
310    hs_.stream() << anchor(href, std::string(first_orig, first)); 
311    return true;
312  }
313
314
315  bool Trac::diff2(std::string::const_iterator& first, 
316                   const std::string::const_iterator& last)
317  {
318    if (first==last)
319      return false;
320
321    const std::string::const_iterator first_orig(first);
322    if (match(first, last, Str("diff:")).empty()){
323      first = first_orig;
324      return false;
325    }
326    std::string old_path(match(first, last, not2Str("//", " ")));
327    std::string new_path;
328    if (first==last || *first==' ')
329      new_path = old_path;
330    else {
331      first += 2;
332      new_path = match(first, last, notChar(' '));
333    }
334    if (new_path.empty() || old_path.empty()){
335      first = first_orig;
336      return false;
337    }
338    std::string href(Configuration::instance().trac_root()+
339                     "changeset?new_path="+new_path+"&old_path="+old_path);
340    hs_.stream() << anchor(href, std::string(first_orig, first)); 
341    return true;
342  }
343
344
345  bool Trac::diff3(std::string::const_iterator& first, 
346                   const std::string::const_iterator& last)
347  {
348    if (first==last)
349      return false;
350
351    const std::string::const_iterator first_orig(first);
352    if (match(first, last, Str("diff:")).empty()){
353      first = first_orig;
354      return false;
355    }
356    std::string old_path(match(first, last, not2Char('@', ' ')));
357    if (*first!='@'){
358      first = first_orig;
359      return false;
360    }
361    ++first;
362    std::string old_rev(match(first, last, Digit()));
363    if (!match_begin(first, first+1, std::string("//"))) {
364      first = first_orig;
365      return false;
366    }
367    first+2;
368    std::string new_path = match(first, last, not2Char('@', ' '));
369    if (*first!='@'){
370      first = first_orig;
371      return false;
372    }
373    ++first;
374    std::string new_rev(match(first, last, Digit()));
375    if (new_rev.empty()){
376      first = first_orig;
377      return false;
378    }
379   
380    std::string href(Configuration::instance().trac_root()+
381                     "changeset?new="+new_rev+"&new_path="+new_path+
382                     "&old="+old_rev+"&old_path="+old_path);
383    hs_.stream() << anchor(href, std::string(first_orig, first)); 
384    return true;
385  }
386
387
388  bool Trac::log(std::string::const_iterator& first, 
389                 const std::string::const_iterator& last)
390  {
391    if (log1(first, last))
392      return true;
393    if (log2(first, last))
394      return true;
395    if (log3(first, last))
396      return true;
397    return false;
398  }
399
400
401  bool Trac::log1(std::string::const_iterator& first, 
402                     const std::string::const_iterator& last)
403  {
404    if (first==last)
405      return false;
406
407    const std::string::const_iterator first_orig(first);
408    if (*first != 'r')
409      return false;
410    ++first;
411
412    std::string stop_rev = match(first, last, Digit());
413    if (stop_rev.empty() || first == last || *first != ':') {
414      first = first_orig;
415      return false;
416    }
417    ++first;
418    std::string rev = match(first, last, Digit());
419    if (rev.empty() ) {
420      first = first_orig;
421      return false;
422    }
423    std::string href(Configuration::instance().trac_root()+"log/?rev="+
424                     rev+"&stop_rev="+stop_rev);
425    hs_.stream() << anchor(href, std::string(first_orig, first)); 
426    return true;
427  }
428
429
430  bool Trac::log2(std::string::const_iterator& first, 
431                     const std::string::const_iterator& last)
432  {
433    if (first==last)
434      return false;
435
436    const std::string::const_iterator first_orig(first);
437    if (*first != '[')
438      return false;
439    ++first;
440
441    std::string stop_rev = match(first, last, Digit());
442    if (stop_rev.empty() || first == last || *first != ':') {
443      first = first_orig;
444      return false;
445    }
446    ++first;
447    std::string rev = match(first, last, Digit());
448    if (rev.empty() || first == last || *first != ']') {
449      first = first_orig;
450      return false;
451    }
452    std::string href(Configuration::instance().trac_root()+"log/?rev="+
453                     rev+"&stop_rev="+stop_rev);
454    hs_.stream() << anchor(href, std::string(first_orig, first)); 
455    return true;
456  }
457
458
459  bool Trac::log3(std::string::const_iterator& first, 
460                  const std::string::const_iterator& last)
461  {
462    if (first==last)
463      return false;
464
465    const std::string::const_iterator first_orig(first);
466
467    const std::string log_str("log:"); 
468    if (!match_begin(first, last, log_str)) {
469      first = first_orig;
470      return false;
471    }
472    first += log_str.size();
473    std::string node = match(first, last, not2Char('#', '@'));
474    ++first;
475    std::string stop_rev = match(first, last, Digit());
476    if (stop_rev.empty() || first == last || *first != ':') {
477      first = first_orig;
478      return false;
479    }
480    ++first;
481    std::string rev = match(first, last, Digit());
482    if (rev.empty() ) {
483      first = first_orig;
484      return false;
485    }
486    std::string href;
487    if (!node.empty() && node[0]=='/')
488      href = std::string(Configuration::instance().trac_root()+"log"+node+
489                         "?rev="+rev+"&stop_rev="+stop_rev);
490    else
491      href = std::string(Configuration::instance().trac_root()+"log/"+node+
492                         "?rev="+rev+"&stop_rev="+stop_rev);
493     
494    hs_.stream() << anchor(href, std::string(first_orig, first)); 
495    return true;
496  }
497
498}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.