summaryrefslogtreecommitdiff
path: root/utils/svn2cl.pp
blob: aaadce06252f626d4b13935ba11bd25d89d3f0aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
{$mode objfpc}
{$h+}
uses
  sysutils,classes,dom,xmlread;

procedure error(const s : string);
  begin
    writeln('Error: ',s);
    halt(1);
  end;

var
  doc : txmldocument;
  root : TDomNode;
  entry,
  currentpath,
  currentinfo : TDomNode;
  hs,
  dirprefix,
  newlineprefix,
  currentmsg,
  currentauthor,
  currentdate,
  pathtemp,
  currentrevision : string;
  paths : tstringlist;
  pathprefixes : tstringlist;
  i,j,maxequal : integer;
  firstpath : boolean;

begin
  paths:=tstringlist.create;
  paths.sorted:=true;
  pathprefixes:=tstringlist.create;
  pathprefixes.sorted:=true;
  ReadXMLFile(doc,paramstr(1));
  root:=doc.DocumentElement;
  if root.haschildnodes and
    (root.NodeName='log') then
    begin
      entry:=root.firstchild;
      while assigned(entry) do
        begin
          if entry.NodeName<>'logentry' then
            error('Only log entry entries supported, but '+entry.NodeName+' found.');
          currentmsg:='';
          currentauthor:='';
          currentdate:='';
          { get revision }
          with entry as tdomelement do
            currentrevision:=AttribStrings['revision'];
          if entry.haschildnodes then
            begin
              currentinfo:=entry.firstchild;
              while assigned(currentinfo) do
                begin
                  if currentinfo.NodeName='author' then
                    begin
                      if currentinfo.haschildnodes and
                        (currentinfo.firstchild is TDOMText) then
                        currentauthor:=(currentinfo.firstchild as TDOMText).Data
                      else
                        error('Malformed author node');
                    end
                  else if currentinfo.NodeName='msg' then
                    begin
                      if currentinfo.haschildnodes then
                        begin
                          if (currentinfo.firstchild is TDOMText) then
                            currentmsg:=(currentinfo.firstchild as TDOMText).Data
                          else
                            error('Malformed msg node');
                        end
                      else
                        currentmsg:='<empty log message>';
                    end
                  else if currentinfo.NodeName='date' then
                    begin
                      if currentinfo.haschildnodes and
                        (currentinfo.firstchild is TDOMText) then
                        currentdate:=(currentinfo.firstchild as TDOMText).Data
                      else
                        error('Malformed date node');
                    end
                  else if currentinfo.NodeName='paths' then
                    begin
                      currentpath:=currentinfo.firstchild;
                      paths.clear;
                      pathprefixes.clear;
                      while assigned(currentpath) do
                        begin
                          if currentpath.NodeName<>'path' then
                            error('Path node expected');
                          if currentpath.haschildnodes and
                            (currentpath.firstchild is TDOMText) then
                            begin
                              paths.add((currentpath.firstchild as TDOMText).Data);
                              hs:=ExtractFilePath((currentpath.firstchild as TDOMText).Data);
                              if not pathprefixes.Find(hs,i) then
                                pathprefixes.add(hs);
                            end
                          else
                            error('Malformed date node');

                          currentpath:=currentpath.NextSibling;
                        end;
                    end
                  else
                    error('Unknown logentry child '+currentinfo.NodeName+' found');
                  currentinfo:=currentinfo.nextsibling;
                end;
              currentdate:=copy(currentdate,1,16);
              { replaced T }
              currentdate[11]:=' ';
              write(currentdate,' ',currentauthor);
              if currentrevision<>'' then
                writeln(' r',currentrevision)
              else
                writeln;
              writeln;

              { search for common pathprefix }
              if pathprefixes.Count>1 then
                begin
                  maxequal:=65535;
                  for i:=1 to pathprefixes.Count-1 do
                    begin
                      j:=1;
                      while (pathprefixes[0][j]=pathprefixes[i][j]) and (j<=maxequal) do
                        inc(j);
                      dec(j);
                      if j<maxequal then
                        maxequal:=j;
                    end;

                  { test/p1.pas test/p2.pas should use the prefix test/ instead of test/p }
                  if maxequal<65535 then
                    while (maxequal>0) and (pathprefixes[0][maxequal]<>'/') do
                      dec(maxequal);
                  Writeln('  '+Copy(pathprefixes[0],1,maxequal)+': ');
                  dirprefix:='    ';
                  newlineprefix:='      ';
                end
              else
                begin
                  maxequal:=0;
                  dirprefix:='  ';
                  newlineprefix:='    ';
                end;

              for i:=0 to pathprefixes.Count-1 do
                begin
                  pathtemp:=dirprefix;
                  if maxequal+1<length(pathprefixes[i]) then
                    pathtemp:=pathtemp+Copy(pathprefixes[i],maxequal+1,65535)+': ';
                  firstpath:=true;
                  j:=0;
                  while (j<paths.Count) do
                    begin
                      if ExtractFilePath(paths[j])=pathprefixes[i] then
                        begin
                          hs:=copy(paths[j],length(pathprefixes[i])+1,65535);
                          if (length(pathtemp)+length(hs)>=78) and
                             (pathtemp<>newlineprefix) then
                            begin
                              writeln(pathtemp+',');
                              pathtemp:=newlineprefix;
                              firstpath:=true;
                            end;
                          { non empty path but not first? }
                          if firstpath then
                            firstpath:=false
                          else
                            pathtemp:=pathtemp+', ';
                          pathtemp:=pathtemp+hs;
                          { delete already processed paths for performance }
                          paths.delete(j);
                        end
                      else
                        inc(j);
                    end;
                  if pathtemp<>newlineprefix then
                    writeln(pathtemp);
                end;

              { truncate trailing spaces and new lines from log message }
              i:=length(currentmsg);
              while (i>0) and (currentmsg[i] in [#13,#10,#9,' ']) do
                dec(i);
              delete(currentmsg,i+1,length(currentmsg)-i);

              { Pretty print message starting with at least 2 spaces each line }
              writeln;
              i:=0;
              hs:=currentmsg;
              while (hs<>'') do
                begin
                  newlineprefix:='  ';
                  i:=0;
                  while (i<length(hs)) and not(hs[i+1] in [#13,#10]) do
                    inc(i);
                  j:=1;
                  while (j<length(hs)) and
                        (j<length(newlineprefix)) and
                        (hs[j] in [' ']) do
                    inc(j);
                  writeln(newlineprefix,copy(hs,j,i-j+1));
                  { remove eol and add additional empty lines }
                  j:=0;
                  while (i<length(hs)) and (hs[i+1] in [#13,#10]) do
                    begin
                      if hs[i+1]=#10 then
                        begin
                          inc(j);
                          if j>2 then
                            writeln;
                        end;
                      inc(i);
                    end;
                  delete(hs,1,i);
                end;
              writeln;
            end
          else
            error('Empty log entry found');
          entry:=entry.nextsibling;
        end;
    end
  else
    error('log element not found/wrong xml format');
end.