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