source: trunk/Backends/Subversion/USubversion.pas

Last change on this file was 18, checked in by chronos, 7 years ago
  • Fixed: Build with newer Lazarus version.
  • Fixed: Creation of application configuration file.
  • Fixed: Wrong decimal point used for XML datetime decode.
  • Added: Detect Subversion exe files from TortoiseSVN directory on Windows.
File size: 6.3 KB
Line 
1unit USubversion;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, UVCS, UBackend, XMLRead, DOM, UXMLUtils;
9
10type
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
47implementation
48
49{ TRepositorySubversion }
50
51procedure TRepositorySubversion.Execute(Parameters: array of string);
52var
53 ToolPath: string;
54begin
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);
64end;
65
66procedure TRepositorySubversion.Init;
67begin
68 Execute(['create', Path]);
69end;
70
71{ TBackendSubversion }
72
73constructor TBackendSubversion.Create;
74begin
75 Name := 'Subversion';
76 HomePage := 'https://subversion.apache.org/';
77 WorkingCopyClass := TSubversion;
78 RepositoryClass := TRepositorySubversion;
79end;
80
81function TBackendSubversion.IsWorkingCopy(Directory: string): Boolean;
82begin
83 Result := DirectoryExists(Directory + DirectorySeparator + '.svn') and
84 FileExists(Directory + DirectorySeparator + '.svn' + DirectorySeparator + 'wc.db');
85end;
86
87{ TSubversion }
88
89procedure TSubversion.Execute(Parameters: array of string);
90var
91 ToolPath: string;
92begin
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);
102end;
103
104procedure TSubversion.Checkout;
105begin
106 Execute(['checkout', RepositoryURL, Path]);
107end;
108
109procedure TSubversion.Update;
110begin
111 Execute(['update']);
112end;
113
114procedure TSubversion.CleanUp;
115begin
116 Execute(['cleanup']);
117end;
118
119procedure TSubversion.Commit(Message: TStrings);
120begin
121 Execute(['commit', '-m "' + Message.Text + '"']);
122end;
123
124procedure TSubversion.Move(Source, Dest: string);
125begin
126 Execute(['move', Source, Dest]);
127end;
128
129procedure TSubversion.Merge;
130begin
131 Execute(['merge']);
132end;
133
134procedure TSubversion.Add(FileName: string);
135begin
136 Execute(['add', FileName]);
137end;
138
139procedure TSubversion.Remove(FileName: string);
140begin
141 Execute(['remove', FileName]);
142end;
143
144procedure TSubversion.GetLog(FileName: string; Log: TLogList);
145var
146 NewItem: TLogItem;
147 I: Integer;
148 Line: string;
149 ChangedFiles: Boolean;
150 Action: string;
151begin
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);
185end;
186
187procedure TSubversion.GetStatus(FileName: string; Status: TFileStatusList);
188var
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;
199begin
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;
242end;
243
244end.
245
Note: See TracBrowser for help on using the repository browser.