2
0

svn2cl.pp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. {$mode objfpc}
  2. {$h+}
  3. uses
  4. sysutils,classes,dom,xmlread;
  5. procedure error(const s : string);
  6. begin
  7. writeln('Error: ',s);
  8. halt(1);
  9. end;
  10. var
  11. doc : txmldocument;
  12. root : TDomNode;
  13. entry,
  14. currentpath,
  15. currentinfo : TDomNode;
  16. hs,
  17. dirprefix,
  18. newlineprefix,
  19. currentmsg,
  20. currentauthor,
  21. currentdate,
  22. pathtemp,
  23. currentrevision : string;
  24. paths : tstringlist;
  25. pathprefixes : tstringlist;
  26. i,j,maxequal : integer;
  27. firstpath : boolean;
  28. begin
  29. paths:=tstringlist.create;
  30. paths.sorted:=true;
  31. pathprefixes:=tstringlist.create;
  32. pathprefixes.sorted:=true;
  33. ReadXMLFile(doc,paramstr(1));
  34. root:=doc.DocumentElement;
  35. if root.haschildnodes and
  36. (root.NodeName='log') then
  37. begin
  38. entry:=root.firstchild;
  39. while assigned(entry) do
  40. begin
  41. if entry.NodeName<>'logentry' then
  42. error('Only log entry entries supported, but '+entry.NodeName+' found.');
  43. currentmsg:='';
  44. currentauthor:='';
  45. currentdate:='';
  46. { get revision }
  47. with entry as tdomelement do
  48. currentrevision:=AttribStrings['revision'];
  49. if entry.haschildnodes then
  50. begin
  51. currentinfo:=entry.firstchild;
  52. while assigned(currentinfo) do
  53. begin
  54. if currentinfo.NodeName='author' then
  55. begin
  56. if currentinfo.haschildnodes and
  57. (currentinfo.firstchild is TDOMText) then
  58. currentauthor:=(currentinfo.firstchild as TDOMText).Data
  59. else
  60. error('Malformed author node');
  61. end
  62. else if currentinfo.NodeName='msg' then
  63. begin
  64. if currentinfo.haschildnodes then
  65. begin
  66. if (currentinfo.firstchild is TDOMText) then
  67. currentmsg:=(currentinfo.firstchild as TDOMText).Data
  68. else
  69. error('Malformed msg node');
  70. end
  71. else
  72. currentmsg:='<empty log message>';
  73. end
  74. else if currentinfo.NodeName='date' then
  75. begin
  76. if currentinfo.haschildnodes and
  77. (currentinfo.firstchild is TDOMText) then
  78. currentdate:=(currentinfo.firstchild as TDOMText).Data
  79. else
  80. error('Malformed date node');
  81. end
  82. else if currentinfo.NodeName='paths' then
  83. begin
  84. currentpath:=currentinfo.firstchild;
  85. paths.clear;
  86. pathprefixes.clear;
  87. while assigned(currentpath) do
  88. begin
  89. if currentpath.NodeName<>'path' then
  90. error('Path node expected');
  91. if currentpath.haschildnodes and
  92. (currentpath.firstchild is TDOMText) then
  93. begin
  94. paths.add((currentpath.firstchild as TDOMText).Data);
  95. hs:=ExtractFilePath((currentpath.firstchild as TDOMText).Data);
  96. if not pathprefixes.Find(hs,i) then
  97. pathprefixes.add(hs);
  98. end
  99. else
  100. error('Malformed date node');
  101. currentpath:=currentpath.NextSibling;
  102. end;
  103. end
  104. else
  105. error('Unknown logentry child '+currentinfo.NodeName+' found');
  106. currentinfo:=currentinfo.nextsibling;
  107. end;
  108. currentdate:=copy(currentdate,1,16);
  109. { replaced T }
  110. currentdate[11]:=' ';
  111. write(currentdate,' ',currentauthor);
  112. if currentrevision<>'' then
  113. writeln(' r',currentrevision)
  114. else
  115. writeln;
  116. writeln;
  117. { search for common pathprefix }
  118. if pathprefixes.Count>1 then
  119. begin
  120. maxequal:=65535;
  121. for i:=1 to pathprefixes.Count-1 do
  122. begin
  123. j:=1;
  124. while (pathprefixes[0][j]=pathprefixes[i][j]) and (j<=maxequal) do
  125. inc(j);
  126. dec(j);
  127. if j<maxequal then
  128. maxequal:=j;
  129. end;
  130. { test/p1.pas test/p2.pas should use the prefix test/ instead of test/p }
  131. if maxequal<65535 then
  132. while (maxequal>0) and (pathprefixes[0][maxequal]<>'/') do
  133. dec(maxequal);
  134. Writeln(' '+Copy(pathprefixes[0],1,maxequal)+': ');
  135. dirprefix:=' ';
  136. newlineprefix:=' ';
  137. end
  138. else
  139. begin
  140. maxequal:=0;
  141. dirprefix:=' ';
  142. newlineprefix:=' ';
  143. end;
  144. for i:=0 to pathprefixes.Count-1 do
  145. begin
  146. pathtemp:=dirprefix;
  147. if maxequal+1<length(pathprefixes[i]) then
  148. pathtemp:=pathtemp+Copy(pathprefixes[i],maxequal+1,65535)+': ';
  149. firstpath:=true;
  150. j:=0;
  151. while (j<paths.Count) do
  152. begin
  153. if ExtractFilePath(paths[j])=pathprefixes[i] then
  154. begin
  155. hs:=copy(paths[j],length(pathprefixes[i])+1,65535);
  156. if (length(pathtemp)+length(hs)>=78) and
  157. (pathtemp<>newlineprefix) then
  158. begin
  159. writeln(pathtemp+',');
  160. pathtemp:=newlineprefix;
  161. firstpath:=true;
  162. end;
  163. { non empty path but not first? }
  164. if firstpath then
  165. firstpath:=false
  166. else
  167. pathtemp:=pathtemp+', ';
  168. pathtemp:=pathtemp+hs;
  169. { delete already processed paths for performance }
  170. paths.delete(j);
  171. end
  172. else
  173. inc(j);
  174. end;
  175. if pathtemp<>newlineprefix then
  176. writeln(pathtemp);
  177. end;
  178. { truncate trailing spaces and new lines from log message }
  179. i:=length(currentmsg);
  180. while (i>0) and (currentmsg[i] in [#13,#10,#9,' ']) do
  181. dec(i);
  182. delete(currentmsg,i+1,length(currentmsg)-i);
  183. { Pretty print message starting with at least 2 spaces each line }
  184. writeln;
  185. i:=0;
  186. hs:=currentmsg;
  187. while (hs<>'') do
  188. begin
  189. newlineprefix:=' ';
  190. i:=0;
  191. while (i<length(hs)) and not(hs[i+1] in [#13,#10]) do
  192. inc(i);
  193. j:=1;
  194. while (j<length(hs)) and
  195. (j<length(newlineprefix)) and
  196. (hs[j] in [' ']) do
  197. inc(j);
  198. writeln(newlineprefix,copy(hs,j,i-j+1));
  199. { remove eol and add additional empty lines }
  200. j:=0;
  201. while (i<length(hs)) and (hs[i+1] in [#13,#10]) do
  202. begin
  203. if hs[i+1]=#10 then
  204. begin
  205. inc(j);
  206. if j>2 then
  207. writeln;
  208. end;
  209. inc(i);
  210. end;
  211. delete(hs,1,i);
  212. end;
  213. writeln;
  214. end
  215. else
  216. error('Empty log entry found');
  217. entry:=entry.nextsibling;
  218. end;
  219. end
  220. else
  221. error('log element not found/wrong xml format');
  222. end.