/components/lazsvnpkg/svnstatusform.pas

http://github.com/graemeg/lazarus · Pascal · 455 lines · 360 code · 52 blank · 43 comment · 29 complexity · fdb0323a75d6add33057d6ca5f6036cc MD5 · raw file

  1. { Copyright (C) 2008 Darius Blaszijk
  2. This source is free software; you can redistribute it and/or modify it under
  3. the terms of the GNU General Public License as published by the Free
  4. Software Foundation; either version 2 of the License, or (at your option)
  5. any later version.
  6. This code is distributed in the hope that it will be useful, but WITHOUT ANY
  7. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  9. details.
  10. A copy of the GNU General Public License is available on the World Wide Web
  11. at <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing
  12. to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  13. MA 02111-1307, USA.
  14. }
  15. unit SVNStatusForm;
  16. {$mode objfpc}{$H+}
  17. interface
  18. uses
  19. Classes, SysUtils, Process, LCLProc,
  20. Forms, Controls, Dialogs, ComCtrls, StdCtrls, ButtonPanel, ExtCtrls, Menus,
  21. // LazUtils
  22. FileUtil, LazFileUtils, LazConfigStorage, UTF8Process,
  23. // IDEIntf
  24. LazIDEIntf, BaseIDEIntf,
  25. // LazSvn
  26. SVNClasses;
  27. type
  28. { TSVNStatusFrm }
  29. TSVNStatusFrm = class(TForm)
  30. ButtonPanel: TButtonPanel;
  31. CommitMsgHistoryLabel: TLabel;
  32. CommitMsgLabel: TLabel;
  33. Panel1: TPanel;
  34. ImageList: TImageList;
  35. mnuOpen: TMenuItem;
  36. mnuRemove: TMenuItem;
  37. mnuAdd: TMenuItem;
  38. mnuRevert: TMenuItem;
  39. mnuShowDiff: TMenuItem;
  40. PopupMenu1: TPopupMenu;
  41. Splitter: TSplitter;
  42. SVNCommitMsgHistoryComboBox: TComboBox;
  43. SVNCommitMsgMemo: TMemo;
  44. SVNFileListView: TListView;
  45. procedure CancelButtonClick(Sender: TObject);
  46. procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  47. procedure FormCreate(Sender: TObject);
  48. procedure FormDestroy(Sender: TObject);
  49. procedure FormShow(Sender: TObject);
  50. procedure mnuAddClick(Sender: TObject);
  51. procedure mnuOpenClick(Sender: TObject);
  52. procedure mnuRemoveClick(Sender: TObject);
  53. procedure mnuRevertClick(Sender: TObject);
  54. procedure mnuShowDiffClick(Sender: TObject);
  55. procedure OKButtonClick(Sender: TObject);
  56. procedure PatchButtonClick(Sender: TObject);
  57. procedure PopupMenu1Popup(Sender: TObject);
  58. procedure SVNCommitMsgHistoryComboBoxChange(Sender: TObject);
  59. procedure SVNFileListViewColumnClick(Sender: TObject; Column: TListColumn);
  60. private
  61. FRepositoryPath: string;
  62. SVNStatus: TSVNStatus;
  63. procedure Initialize({%H-}Data: PtrInt);
  64. procedure ExecuteSvnCommand(ACommand: String; AFile: String);
  65. procedure UpdateFilesListView;
  66. procedure ChangeCursor(ACursor: TCursor);
  67. procedure UpdateCheckedStatus;
  68. public
  69. {path the root of the local working copy}
  70. property RepositoryPath: string read FRepositoryPath write FRepositoryPath;
  71. end;
  72. procedure ShowSVNStatusFrm(ARepoPath: string);
  73. var
  74. SVNStatusFrm: TSVNStatusFrm;
  75. implementation
  76. {$R *.lfm}
  77. uses
  78. SVNDiffForm, SVNCommitForm;
  79. procedure ShowSVNStatusFrm(ARepoPath: string);
  80. begin
  81. if not Assigned(SVNStatusFrm) then
  82. SVNStatusFrm := TSVNStatusFrm.Create(nil);
  83. SVNStatusFrm.ChangeCursor(crHourGlass);
  84. SVNStatusFrm.RepositoryPath:=ARepoPath;
  85. SVNStatusFrm.Show;
  86. end;
  87. { TSVNStatusFrm }
  88. procedure TSVNStatusFrm.FormShow(Sender: TObject);
  89. begin
  90. Caption := Format('%s - %s ...', [RepositoryPath, rsLazarusSVNCommit]);
  91. CommitMsgHistoryLabel.Caption:=rsCommitMsgHistory;
  92. CommitMsgLabel.Caption:=rsCommitMsg;
  93. Application.QueueAsyncCall(@Initialize, 0);
  94. end;
  95. procedure TSVNStatusFrm.Initialize(Data: PtrInt);
  96. begin
  97. SVNStatus := TSVNStatus.Create(RepositoryPath, false);
  98. SVNStatus.Sort(siChecked, sdAscending);
  99. UpdateFilesListView;
  100. ChangeCursor(crDefault);
  101. end;
  102. procedure TSVNStatusFrm.mnuRevertClick(Sender: TObject);
  103. begin
  104. if Assigned(SVNFileListView.Selected) then
  105. begin
  106. ExecuteSvnCommand('revert', SVNFileListView.Selected.SubItems[0]);
  107. //now delete the entry from the list
  108. SVNStatus.List.Delete(SVNFileListView.Selected.Index);
  109. //update the listview again
  110. UpdateFilesListView;
  111. end;
  112. end;
  113. procedure TSVNStatusFrm.mnuAddClick(Sender: TObject);
  114. begin
  115. if Assigned(SVNFileListView.Selected) then
  116. begin
  117. ExecuteSvnCommand('add', SVNFileListView.Selected.SubItems[0]);
  118. // completely re-read the status
  119. SVNStatus.Free;
  120. SVNStatus := TSVNStatus.Create(RepositoryPath, false);
  121. SVNStatus.Sort(siChecked, sdAscending);
  122. UpdateFilesListView;
  123. end;
  124. end;
  125. procedure TSVNStatusFrm.mnuOpenClick(Sender: TObject);
  126. var
  127. FileName: String;
  128. begin
  129. if Assigned(SVNFileListView.Selected) then
  130. begin
  131. FileName := CreateAbsolutePath(SVNFileListView.Selected.SubItems[0], RepositoryPath);
  132. LazarusIDE.DoOpenEditorFile(FileName, -1, -1, [ofOnlyIfExists]);
  133. end;
  134. end;
  135. procedure TSVNStatusFrm.mnuRemoveClick(Sender: TObject);
  136. begin
  137. if Assigned(SVNFileListView.Selected) then
  138. begin
  139. ExecuteSvnCommand('remove --keep-local', SVNFileListView.Selected.SubItems[0]);
  140. // completely re-read the status
  141. SVNStatus.Free;
  142. SVNStatus := TSVNStatus.Create(RepositoryPath, false);
  143. SVNStatus.Sort(siChecked, sdAscending);
  144. UpdateFilesListView;
  145. end;
  146. end;
  147. procedure TSVNStatusFrm.ExecuteSvnCommand(ACommand: String; AFile: String);
  148. var
  149. AProcess: TProcessUTF8;
  150. begin
  151. AProcess := TProcessUTF8.Create(nil);
  152. if pos(RepositoryPath, AFile) <> 0 then
  153. AProcess.CommandLine := SVNExecutable + ' ' + ACommand + ' "' + AFile + '"'
  154. else
  155. AProcess.CommandLine := SVNExecutable + ' ' + ACommand + ' "' + AppendPathDelim(RepositoryPath) + AFile + '"';
  156. debugln('TSVNStatusFrm.ExecuteSvnCommand commandline=', AProcess.CommandLine);
  157. AProcess.Options := AProcess.Options + [poWaitOnExit];
  158. AProcess.ShowWindow := swoHIDE;
  159. AProcess.Execute;
  160. AProcess.Free;
  161. end;
  162. procedure TSVNStatusFrm.mnuShowDiffClick(Sender: TObject);
  163. begin
  164. if Assigned(SVNFileListView.Selected) then
  165. begin
  166. debugln('TSVNStatusFrm.mnuShowDiffClick Path=' ,SVNFileListView.Selected.SubItems[0]);
  167. if pos(RepositoryPath,SVNFileListView.Selected.SubItems[0]) <> 0 then
  168. ShowSVNDiffFrm('-r BASE', SVNFileListView.Selected.SubItems[0])
  169. else
  170. ShowSVNDiffFrm('-r BASE', AppendPathDelim(RepositoryPath) + SVNFileListView.Selected.SubItems[0]);
  171. end;
  172. end;
  173. procedure TSVNStatusFrm.OKButtonClick(Sender: TObject);
  174. var
  175. i: integer;
  176. CmdLine: string;
  177. StatusItem : TSVNStatusItem;
  178. FileName: string;
  179. begin
  180. UpdateCheckedStatus;
  181. if SVNCommitMsgMemo.Text = '' then
  182. if MessageDlg ('No message set.', 'Do you wish to continue?', mtConfirmation,
  183. [mbYes, mbNo],0) <> mrYes then
  184. exit;
  185. //commit the checked files
  186. CmdLine := SVNExecutable + ' commit --non-interactive --force-log ';
  187. for i := 0 to SVNStatus.List.Count - 1 do
  188. begin
  189. StatusItem := SVNStatus.List[i];
  190. if StatusItem.Checked then
  191. if pos(RepositoryPath,StatusItem.Path) = 0 then
  192. CmdLine := CmdLine + ' "' + AppendPathDelim(RepositoryPath) + StatusItem.Path + '"'
  193. else
  194. CmdLine := CmdLine + ' "' + StatusItem.Path + '"';
  195. end;
  196. FileName := GetTempFileNameUTF8('','');
  197. SVNCommitMsgMemo.Lines.SaveToFile(FileName);
  198. CmdLine := CmdLine + ' --file ' + FileName;
  199. ShowSVNCommitFrm(CmdLine);
  200. DeleteFile(FileName);
  201. Close;
  202. end;
  203. procedure TSVNStatusFrm.PatchButtonClick(Sender: TObject);
  204. var
  205. i: Integer;
  206. StatusItem: TSVNStatusItem;
  207. FileNames: TStringList;
  208. begin
  209. UpdateCheckedStatus;
  210. Filenames := TStringList.Create;
  211. FileNames.Sorted := True;
  212. for i := 0 to SVNStatus.List.Count - 1 do
  213. begin
  214. StatusItem := SVNStatus.List.Items[i];
  215. if StatusItem.Checked then
  216. if pos(RepositoryPath,StatusItem.Path) = 0 then
  217. FileNames.Append(AppendPathDelim(RepositoryPath) + StatusItem.Path)
  218. else
  219. FileNames.Append(StatusItem.Path);
  220. end;
  221. ShowSVNDiffFrm('-r BASE', FileNames);
  222. end;
  223. procedure TSVNStatusFrm.PopupMenu1Popup(Sender: TObject);
  224. var
  225. P: TPoint;
  226. LI: TListItem;
  227. begin
  228. // make sure the row under the mouse is selected
  229. P := SVNFileListView.ScreenToControl(Mouse.CursorPos);
  230. LI := SVNFileListView.GetItemAt(P.X, P.Y);
  231. if LI <> nil then begin
  232. SVNFileListView.Selected := LI;
  233. {$note: using hardcoded column index!}
  234. if LI.SubItems[2] = 'unversioned' then
  235. mnuRevert.Enabled := False
  236. else
  237. mnuRevert.Enabled := True;
  238. if (LI.SubItems[2] = 'unversioned') or (LI.SubItems[2] = 'deleted') then begin
  239. mnuShowDiff.Enabled := False;
  240. mnuRemove.Enabled := False;
  241. mnuAdd.Enabled := True;
  242. end else begin
  243. mnuShowDiff.Enabled := True;
  244. mnuRemove.Enabled := True;
  245. mnuAdd.Enabled := False;
  246. end;
  247. end;
  248. end;
  249. procedure TSVNStatusFrm.SVNCommitMsgHistoryComboBoxChange(Sender: TObject);
  250. begin
  251. with SVNCommitMsgHistoryComboBox do
  252. if ItemIndex > -1 then
  253. SVNCommitMsgMemo.Text := Items[ItemIndex];
  254. end;
  255. procedure TSVNStatusFrm.SVNFileListViewColumnClick(Sender: TObject;
  256. Column: TListColumn);
  257. begin
  258. case Column.Index of
  259. 0: SVNStatus.ReverseSort(siChecked);
  260. 1: SVNStatus.ReverseSort(siPath);
  261. 2: SVNStatus.ReverseSort(siExtension);
  262. 3: SVNStatus.ReverseSort(siItemStatus);
  263. 4: SVNStatus.ReverseSort(siPropStatus);
  264. 5: SVNStatus.ReverseSort(siAuthor);
  265. 6: SVNStatus.ReverseSort(siRevision);
  266. 7: SVNStatus.ReverseSort(siCommitRevision);
  267. 8: SVNStatus.ReverseSort(siDate);
  268. end;
  269. UpdateFilesListView;
  270. end;
  271. procedure TSVNStatusFrm.UpdateFilesListView;
  272. var
  273. i: integer;
  274. StatusItem : TSVNStatusItem;
  275. Path: string;
  276. begin
  277. SVNFileListView.BeginUpdate;
  278. SVNFileListView.Clear;
  279. for i := 0 to SVNStatus.List.Count - 1 do
  280. begin
  281. with SVNFileListView.Items.Add do
  282. begin
  283. StatusItem := SVNStatus.List.Items[i];
  284. //checkboxes
  285. Caption := '';
  286. Checked := StatusItem.Checked;
  287. //path
  288. Path := StatusItem.Path;
  289. if pos(RepositoryPath, Path) = 1 then
  290. path := CreateRelativePath(path, RepositoryPath, false);
  291. SubItems.Add(Path);
  292. //extension
  293. SubItems.Add(StatusItem.Extension);
  294. //file status
  295. SubItems.Add(StatusItem.ItemStatus);
  296. //property status
  297. SubItems.Add(StatusItem.PropStatus);
  298. //check if file is versioned
  299. if (LowerCase(StatusItem.ItemStatus) <> 'unversioned') and
  300. (LowerCase(StatusItem.ItemStatus) <> 'added') then
  301. begin
  302. //revision
  303. SubItems.Add(IntToStr(StatusItem.Revision));
  304. //commit revision
  305. SubItems.Add(IntToStr(StatusItem.CommitRevision));
  306. //author
  307. SubItems.Add(StatusItem.Author);
  308. //date
  309. SubItems.Add(DateTimeToStr(StatusItem.Date));
  310. end;
  311. end;
  312. end;
  313. SVNFileListView.EndUpdate;
  314. end;
  315. procedure TSVNStatusFrm.ChangeCursor(ACursor: TCursor);
  316. begin
  317. Cursor := ACursor;
  318. SVNCommitMsgMemo.Cursor := ACursor;
  319. SVNFileListView.Cursor := ACursor;
  320. Self.Cursor := ACursor;
  321. Application.ProcessMessages;
  322. end;
  323. procedure TSVNStatusFrm.UpdateCheckedStatus;
  324. var
  325. i : Integer;
  326. begin
  327. for i := 0 to SVNFileListView.Items.Count - 1 do
  328. with SVNFileListView.Items[i] do
  329. SVNStatus.List[Index].Checked := Checked;
  330. end;
  331. procedure TSVNStatusFrm.FormCreate(Sender: TObject);
  332. var
  333. Config: TConfigStorage;
  334. count: integer;
  335. i: integer;
  336. s: string;
  337. begin
  338. mnuShowDiff.Caption := rsShowDiff;
  339. mnuOpen.Caption := rsOpenFileInEditor;
  340. mnuRevert.Caption := rsRevert;
  341. mnuAdd.Caption := rsAdd;
  342. mnuRemove.Caption := rsRemove;
  343. ButtonPanel.HelpButton.Caption:=rsCreatePatchFile;
  344. ButtonPanel.OKButton.Caption:=rsCommit;
  345. ButtonPanel.OKButton.OnClick:=@OKButtonClick;
  346. SetColumn(SVNFileListView, 0, 25, '', False);
  347. SetColumn(SVNFileListView, 1, 300, rsPath, False);
  348. SetColumn(SVNFileListView, 2, 75, rsExtension, True);
  349. SetColumn(SVNFileListView, 3, 100, rsFileStatus, True);
  350. SetColumn(SVNFileListView, 4, 125, rsPropertyStatus, True);
  351. SetColumn(SVNFileListView, 5, 75, rsRevision, True);
  352. SetColumn(SVNFileListView, 6, 75, rsCommitRevision, True);
  353. SetColumn(SVNFileListView, 7, 75, rsAuthor, True);
  354. SetColumn(SVNFileListView, 8, 75, rsDate, True);
  355. ImageList.AddResourceName(HInstance, 'menu_svn_diff');
  356. ImageList.AddResourceName(HInstance, 'menu_svn_revert');
  357. try
  358. Config := GetIDEConfigStorage('lazsvnpkg.xml', true);
  359. count := Config.GetValue('HistoryCount', 0);
  360. //limit to 100 entries
  361. if count > 100 then
  362. count := 100;
  363. for i := count downto 0 do
  364. begin
  365. s := Config.GetValue('Msg' + IntToStr(i), '');
  366. if s <> '' then
  367. SVNCommitMsgHistoryComboBox.Items.Add(s);
  368. end;
  369. finally
  370. Config.Free;
  371. end;
  372. end;
  373. procedure TSVNStatusFrm.FormDestroy(Sender: TObject);
  374. begin
  375. SVNStatusFrm := nil;
  376. end;
  377. procedure TSVNStatusFrm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  378. var
  379. Config: TConfigStorage;
  380. count: integer;
  381. begin
  382. if SVNCommitMsgMemo.Text <> '' then
  383. begin
  384. try
  385. Config := GetIDEConfigStorage('lazsvnpkg.xml', true);
  386. count := Config.GetValue('HistoryCount', 0);
  387. Config.SetValue('HistoryCount', count + 1);
  388. Config.SetValue('Msg' + IntToStr(count + 1), SVNCommitMsgMemo.Text);
  389. finally
  390. Config.Free;
  391. end;
  392. end;
  393. SVNStatus.Free;
  394. CloseAction := caFree;
  395. end;
  396. procedure TSVNStatusFrm.CancelButtonClick(Sender: TObject);
  397. begin
  398. Close;
  399. end;
  400. end.