1 | unit USubversion;
|
---|
2 |
|
---|
3 | {$mode delphi}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, SysUtils, UVCS, UBackend, XMLRead, DOM, UXMLUtils;
|
---|
9 |
|
---|
10 | type
|
---|
11 |
|
---|
12 | { TBackendSubversion }
|
---|
13 |
|
---|
14 | TBackendSubversion = class(TBackend)
|
---|
15 | constructor Create;
|
---|
16 | function IsWorkingCopy(Directory: string): Boolean; override;
|
---|
17 | end;
|
---|
18 |
|
---|
19 |
|
---|
20 | { TSubversion }
|
---|
21 |
|
---|
22 | TSubversion = class(TWorkingCopy)
|
---|
23 | protected
|
---|
24 | procedure Execute(Parameters: array of string);
|
---|
25 | public
|
---|
26 | procedure Checkout; override;
|
---|
27 | procedure Update; override;
|
---|
28 | procedure CleanUp; override;
|
---|
29 | procedure Commit(Message: TStrings); override;
|
---|
30 | procedure Move(Source, Dest: string); override;
|
---|
31 | procedure Merge; override;
|
---|
32 | procedure Add(FileName: string); override;
|
---|
33 | procedure Remove(FileName: string); override;
|
---|
34 | procedure GetLog(FileName: string; Log: TLogList); override;
|
---|
35 | procedure GetStatus(FileName: string; Status: TFileStatusList); override;
|
---|
36 | end;
|
---|
37 |
|
---|
38 | { TRepositorySubversion }
|
---|
39 |
|
---|
40 | TRepositorySubversion = class(TRepository)
|
---|
41 | protected
|
---|
42 | procedure Execute(Parameters: array of string);
|
---|
43 | public
|
---|
44 | procedure Init; override;
|
---|
45 | end;
|
---|
46 |
|
---|
47 | implementation
|
---|
48 |
|
---|
49 | { TRepositorySubversion }
|
---|
50 |
|
---|
51 | procedure TRepositorySubversion.Execute(Parameters: array of string);
|
---|
52 | var
|
---|
53 | ToolPath: string;
|
---|
54 | begin
|
---|
55 | {$IFDEF Linux}
|
---|
56 | ToolPath := '/usr/bin/svnadmin';
|
---|
57 | {$ENDIF}
|
---|
58 | {$IFDEF Windows}
|
---|
59 | ToolPath := 'c:\Program Files\Subversion\bin\svnadmin.exe';
|
---|
60 | if not FileExists(ToolPath) then
|
---|
61 | ToolPath := 'C:\Program Files\TortoiseSVN\bin\svnadmin.exe';
|
---|
62 | {$ENDIF}
|
---|
63 | ExecuteProcess(ToolPath, Parameters);
|
---|
64 | end;
|
---|
65 |
|
---|
66 | procedure TRepositorySubversion.Init;
|
---|
67 | begin
|
---|
68 | Execute(['create', Path]);
|
---|
69 | end;
|
---|
70 |
|
---|
71 | { TBackendSubversion }
|
---|
72 |
|
---|
73 | constructor TBackendSubversion.Create;
|
---|
74 | begin
|
---|
75 | Name := 'Subversion';
|
---|
76 | HomePage := 'https://subversion.apache.org/';
|
---|
77 | WorkingCopyClass := TSubversion;
|
---|
78 | RepositoryClass := TRepositorySubversion;
|
---|
79 | end;
|
---|
80 |
|
---|
81 | function TBackendSubversion.IsWorkingCopy(Directory: string): Boolean;
|
---|
82 | begin
|
---|
83 | Result := DirectoryExists(Directory + DirectorySeparator + '.svn') and
|
---|
84 | FileExists(Directory + DirectorySeparator + '.svn' + DirectorySeparator + 'wc.db');
|
---|
85 | end;
|
---|
86 |
|
---|
87 | { TSubversion }
|
---|
88 |
|
---|
89 | procedure TSubversion.Execute(Parameters: array of string);
|
---|
90 | var
|
---|
91 | ToolPath: string;
|
---|
92 | begin
|
---|
93 | {$IFDEF Linux}
|
---|
94 | ToolPath := '/usr/bin/svn';
|
---|
95 | {$ENDIF}
|
---|
96 | {$IFDEF Windows}
|
---|
97 | ToolPath := 'c:\Program Files\Subversion\bin\svn.exe';
|
---|
98 | if not FileExists(ToolPath) then
|
---|
99 | ToolPath := 'C:\Program Files\TortoiseSVN\bin\svn.exe';
|
---|
100 | {$ENDIF}
|
---|
101 | ExecuteProcess(ToolPath, Parameters);
|
---|
102 | end;
|
---|
103 |
|
---|
104 | procedure TSubversion.Checkout;
|
---|
105 | begin
|
---|
106 | Execute(['checkout', RepositoryURL, Path]);
|
---|
107 | end;
|
---|
108 |
|
---|
109 | procedure TSubversion.Update;
|
---|
110 | begin
|
---|
111 | Execute(['update']);
|
---|
112 | end;
|
---|
113 |
|
---|
114 | procedure TSubversion.CleanUp;
|
---|
115 | begin
|
---|
116 | Execute(['cleanup']);
|
---|
117 | end;
|
---|
118 |
|
---|
119 | procedure TSubversion.Commit(Message: TStrings);
|
---|
120 | begin
|
---|
121 | Execute(['commit', '-m "' + Message.Text + '"']);
|
---|
122 | end;
|
---|
123 |
|
---|
124 | procedure TSubversion.Move(Source, Dest: string);
|
---|
125 | begin
|
---|
126 | Execute(['move', Source, Dest]);
|
---|
127 | end;
|
---|
128 |
|
---|
129 | procedure TSubversion.Merge;
|
---|
130 | begin
|
---|
131 | Execute(['merge']);
|
---|
132 | end;
|
---|
133 |
|
---|
134 | procedure TSubversion.Add(FileName: string);
|
---|
135 | begin
|
---|
136 | Execute(['add', FileName]);
|
---|
137 | end;
|
---|
138 |
|
---|
139 | procedure TSubversion.Remove(FileName: string);
|
---|
140 | begin
|
---|
141 | Execute(['remove', FileName]);
|
---|
142 | end;
|
---|
143 |
|
---|
144 | procedure TSubversion.GetLog(FileName: string; Log: TLogList);
|
---|
145 | var
|
---|
146 | NewItem: TLogItem;
|
---|
147 | I: Integer;
|
---|
148 | Line: string;
|
---|
149 | ChangedFiles: Boolean;
|
---|
150 | Action: string;
|
---|
151 | begin
|
---|
152 | NewItem := nil;
|
---|
153 | Log.Clear;
|
---|
154 | SilentExecution := True;
|
---|
155 | Execute(['log', FileName, '-v']);
|
---|
156 | SilentExecution := False;
|
---|
157 | for I := 0 to ExecutionOutput.Count - 1 do begin
|
---|
158 | Line := Trim(ExecutionOutput[I]);
|
---|
159 | if Line = '------------------------------------------------------------------------' then begin
|
---|
160 | if Assigned(NewItem) then Log.Add(NewItem);
|
---|
161 | NewItem := TLogItem.Create;
|
---|
162 | end else
|
---|
163 | if Pos('|', Line) > 0 then begin
|
---|
164 | NewItem.Revision := Trim(GetNext(Line, '|'));
|
---|
165 | NewItem.Author := Trim(GetNext(Line, '|'));
|
---|
166 | GetNext(Line, '|');
|
---|
167 | //NewItem.Time := StrToDateTime(Trim(GetNext(Line, '|')));
|
---|
168 | end else
|
---|
169 | if Line = 'Changed paths:' then begin
|
---|
170 | ChangedFiles := True;
|
---|
171 | end else
|
---|
172 | if ChangedFiles then begin
|
---|
173 | if (Line <> '') and (Copy(ExecutionOutput[I], 1, 3) = ' ') then begin
|
---|
174 | Action := GetNext(Line, ' ');
|
---|
175 | NewItem.Actions := NewItem.Actions + Action;
|
---|
176 | NewItem.ChangedFiles.Add(Line);
|
---|
177 | end else
|
---|
178 | if Line = '' then begin
|
---|
179 | ChangedFiles := False;
|
---|
180 | end;
|
---|
181 | end else
|
---|
182 | NewItem.Messages.Add(Line);
|
---|
183 | end;
|
---|
184 | if Assigned(NewItem) then Log.Add(NewItem);
|
---|
185 | end;
|
---|
186 |
|
---|
187 | procedure TSubversion.GetStatus(FileName: string; Status: TFileStatusList);
|
---|
188 | var
|
---|
189 | Doc: TXMLDocument;
|
---|
190 | S: TStringStream;
|
---|
191 | Node: TDOMNode;
|
---|
192 | Node2: TDOMNode;
|
---|
193 | RootNode: TDOMNode;
|
---|
194 | TargetNode: TDOMNode;
|
---|
195 | StatusNode: TDOMNode;
|
---|
196 | StatusItem: TFileStatus;
|
---|
197 | CommitNode: TDOMNode;
|
---|
198 | ItemState: string;
|
---|
199 | begin
|
---|
200 | Status.Clear;
|
---|
201 | SilentExecution := True;
|
---|
202 | Execute(['status', '--xml', '-v']);
|
---|
203 | SilentExecution := False;
|
---|
204 | S := TStringStream.Create(ExecutionOutput.Text);
|
---|
205 | try
|
---|
206 | // Read complete XML document
|
---|
207 | ReadXMLFile(Doc, S);
|
---|
208 | RootNode := Doc.DocumentElement;
|
---|
209 | if RootNode.NodeName = 'status' then begin
|
---|
210 | TargetNode := RootNode.FindNode('target');
|
---|
211 | if Assigned(TargetNode) then begin
|
---|
212 | Node := TargetNode.FirstChild;
|
---|
213 | while Assigned(Node) do begin
|
---|
214 | if Node.NodeName = 'entry' then begin
|
---|
215 | StatusItem := TFileStatus.Create;
|
---|
216 | StatusItem.FileName := TDOMElement(Node).GetAttribute('path');
|
---|
217 | StatusNode := Node.FindNode('wc-status');
|
---|
218 | if Assigned(StatusNode) then begin
|
---|
219 | ItemState := TDOMElement(StatusNode).GetAttribute('item');
|
---|
220 | if ItemState = 'normal' then StatusItem.State := fssNotModified;
|
---|
221 | if ItemState = 'modified' then StatusItem.State := fssModified;
|
---|
222 | if ItemState = 'deleted' then StatusItem.State := fssRemoved;
|
---|
223 | if ItemState = 'added' then StatusItem.State := fssAdded;
|
---|
224 |
|
---|
225 | CommitNode := StatusNode.FindNode('commit');
|
---|
226 | if Assigned(CommitNode) then begin
|
---|
227 | StatusItem.Version := TDOMElement(CommitNode).GetAttribute('revision');
|
---|
228 | StatusItem.Author := ReadString(CommitNode, 'author', '');
|
---|
229 | StatusItem.Time := ReadDateTime(CommitNode, 'date', 0);
|
---|
230 | end;
|
---|
231 | end;
|
---|
232 | Status.Add(StatusItem);
|
---|
233 | end;
|
---|
234 | Node := Node.NextSibling;
|
---|
235 | end;
|
---|
236 | end;
|
---|
237 | end;
|
---|
238 | finally
|
---|
239 | Doc.Free;
|
---|
240 | S.Free;
|
---|
241 | end;
|
---|
242 | end;
|
---|
243 |
|
---|
244 | end.
|
---|
245 |
|
---|