PageRenderTime 33ms CodeModel.GetById 15ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 1ms

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