1 #----------------------------------------------------------------------------
3 # Purpose: Subversion Service for pydocview
9 # Copyright: (c) 2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
18 import sys
# for errors
19 import traceback
# for errors
22 import pysvn
# python-subversion integration
30 #----------------------------------------------------------------------------
32 #----------------------------------------------------------------------------
33 SVN_CONFIG_DIR
= "SVNConfigDir"
34 SVN_REPOSITORY_URL
= "SVNRepositoryURL"
40 #----------------------------------------------------------------------------
42 #----------------------------------------------------------------------------
44 class SVNService(wx
.lib
.pydocview
.DocService
):
45 SVN_UPDATE_ID
= wx
.NewId()
46 SVN_CHECKIN_ID
= wx
.NewId()
47 SVN_CHECKOUT_ID
= wx
.NewId()
48 SVN_REVERT_ID
= wx
.NewId()
49 SVN_ADD_ID
= wx
.NewId()
50 SVN_DELETE_ID
= wx
.NewId()
51 SVN_COMMAND_LIST
= [SVN_UPDATE_ID
, SVN_CHECKIN_ID
, SVN_CHECKOUT_ID
, SVN_REVERT_ID
, SVN_ADD_ID
, SVN_DELETE_ID
]
55 self
._defaultURL
= "svn://"
59 config
= wx
.ConfigBase_Get()
60 configDir
= config
.Read(SVN_CONFIG_DIR
, "")
62 self
._client
= pysvn
.Client(configDir
)
64 self
._defaultURL
= self
._client
.info('.').url
67 self
._client
.callback_cancel
= self
.IfCancel
68 self
._client
.callback_notify
= self
.UpdateStatus
69 self
._client
.callback_get_log_message
= self
.GetLogMessage
70 self
._client
.callback_get_login
= self
.GetLogin
71 self
._client
.callback_ssl_server_trust_prompt
= self
.GetSSLServerTrust
72 self
._client
.callback_ssl_client_cert_password_prompt
= self
.SSLClientPassword
73 self
._client
.callback_ssl_client_cert_prompt
= self
.SSLClientCert
74 self
._client
.callback_ssl_server_prompt
= self
.SSLServerPrompt
76 #----------------------------------------------------------------------------
77 # pysvn.Client() Callback Methods
78 #----------------------------------------------------------------------------
81 """ return True if user wants to cancel current command """
85 def UpdateStatus(self
, eventDict
):
86 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
87 messageService
.ShowWindow()
89 view
= messageService
.GetView()
90 view
.AddLines(_("%s %s\n") % (eventDict
['action'], eventDict
['path']))
93 def GetLogMessage(self
):
94 dlg
= wx
.TextEntryDialog(wx
.GetApp().GetTopWindow(),
98 if dlg
.ShowModal() == wx
.ID_OK
:
100 message
= dlg
.GetValue()
103 message
= _("Cancel Action")
107 return retcode
, message
110 def GetLogin(self
, realm
, username
, maySave
):
111 dlg
= wx
.Dialog(wx
.GetApp().GetTopWindow(), -1, _("SVN Login"))
113 sizer
= wx
.FlexGridSizer(cols
= 2, hgap
= 5, vgap
= 5)
114 sizer
.Add(wx
.StaticText(dlg
, -1, _("Username:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
115 usernameTxt
= wx
.TextCtrl(dlg
, -1, username
, size
= (200, -1))
116 sizer
.Add(usernameTxt
, 0, wx
.ALIGN_CENTER_VERTICAL
)
117 sizer
.Add(wx
.StaticText(dlg
, -1, _("Password:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
118 passwordTxt
= wx
.TextCtrl(dlg
, -1, size
=(200, -1), style
=wx
.TE_PASSWORD
)
119 sizer
.Add(passwordTxt
, 0, wx
.ALIGN_CENTER_VERTICAL
)
121 savePasswordCheckbox
= wx
.CheckBox(dlg
, -1, _("Remember Username and Password"))
123 savePasswordCheckbox
.Enable(False)
125 buttonSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
126 okBtn
= wx
.Button(dlg
, wx
.ID_OK
)
128 buttonSizer
.Add(okBtn
, 0, wx
.RIGHT
, HALF_SPACE
)
129 buttonSizer
.Add(wx
.Button(dlg
, wx
.ID_CANCEL
), 0)
131 contentSizer
= wx
.BoxSizer(wx
.VERTICAL
)
132 contentSizer
.Add(sizer
, 0, wx
.LEFT|wx
.TOP|wx
.RIGHT
, SPACE
)
133 contentSizer
.Add(savePasswordCheckbox
, 0, wx
.TOP|wx
.LEFT|wx
.BOTTOM
, SPACE
)
134 contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
)
136 dlg
.SetSizer(contentSizer
)
140 if dlg
.ShowModal() == wx
.ID_OK
:
142 username
= usernameTxt
.GetValue().strip()
143 password
= passwordTxt
.GetValue()
144 save
= savePasswordCheckBox
.IsChecked()
152 return retcode
, username
, password
, save
155 def SSLServerPrompt(self
):
156 """ Not implemented, as per pysvn documentation """
160 def GetSSLServerTrust(self
, trustDict
):
161 dlg
= wx
.Dialog(wx
.GetApp().GetTopWindow(), -1, _("SSL Server Certificate"))
163 sizer
= wx
.FlexGridSizer(cols
= 2, hgap
= 5, vgap
= 5)
164 for k
in ['hostname', 'valid_from', 'valid_to', 'issuer_dname', 'realm']:
165 if trustDict
.has_key(k
):
166 sizer
.Add(wx
.StaticText(dlg
, -1, "%s:" % k
), 0, wx
.ALIGN_CENTER_VERTICAL
)
167 sizer
.Add(wx
.StaticText(dlg
, -1, "%s" % trustDict
[k
]), 0, wx
.ALIGN_CENTER_VERTICAL
)
169 box
= wx
.StaticBoxSizer(wx
.StaticBox(dlg
, -1, _("Certificate Info")), wx
.VERTICAL
)
170 box
.Add(sizer
, 0, wx
.EXPAND
)
172 certRadio
= wx
.RadioBox(dlg
, -1, _("Certificate"), choices
=[_("Accept Always"), _("Accept Once"), _("Reject")], majorDimension
=1, style
=wx
.RA_SPECIFY_COLS
)
174 buttonSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
175 okBtn
= wx
.Button(dlg
, wx
.ID_OK
)
177 buttonSizer
.Add(okBtn
, 0, wx
.RIGHT
, HALF_SPACE
)
178 buttonSizer
.Add(wx
.Button(dlg
, wx
.ID_CANCEL
), 0)
180 contentSizer
= wx
.BoxSizer(wx
.VERTICAL
)
181 contentSizer
.Add(box
, 0, wx
.TOP|wx
.LEFT|wx
.RIGHT|wx
.EXPAND
, SPACE
)
182 contentSizer
.Add(certRadio
, 0, wx
.TOP|wx
.LEFT|wx
.RIGHT|wx
.BOTTOM|wx
.EXPAND
, SPACE
)
183 contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
)
185 dlg
.SetSizer(contentSizer
)
189 # default values for reject
194 if dlg
.ShowModal() == wx
.ID_OK
:
195 cert
= certRadio
.GetStringSelection()
196 if cert
== _("Accept Always"):
198 acceptedFailures
= trustDict
.get('failures')
200 elif cert
== _("Accept Once"):
202 acceptedFailures
= trustDict
.get('failures')
205 return retcode
, acceptedFailures
, save
208 def SSLClientPassword(self
, realm
, maySave
):
209 dlg
= wx
.Dialog(wx
.GetApp().GetTopWindow(), -1, _("SSL Client Certificate Login"))
211 sizer
= wx
.FlexGridSizer(cols
= 2, hgap
= 5, vgap
= 5)
212 sizer
.Add(wx
.StaticText(dlg
, -1, _("Realm:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
213 sizer
.Add(wx
.StaticText(dlg
, -1, realm
), 0, wx
.ALIGN_CENTER_VERTICAL
)
214 sizer
.Add(wx
.StaticText(dlg
, -1, _("Password:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
215 passwordTxt
= wx
.TextCtrl(dlg
, -1, size
=(200, -1), style
=wx
.TE_PASSWORD
)
216 sizer
.Add(passwordTxt
, 0, wx
.ALIGN_CENTER_VERTICAL
)
218 savePasswordCheckbox
= wx
.CheckBox(dlg
, -1, _("Remember Password"))
220 savePasswordCheckbox
.Enable(False)
222 buttonSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
223 okBtn
= wx
.Button(dlg
, wx
.ID_OK
)
225 buttonSizer
.Add(okBtn
, 0, wx
.RIGHT
, HALF_SPACE
)
226 buttonSizer
.Add(wx
.Button(dlg
, wx
.ID_CANCEL
), 0)
228 contentSizer
= wx
.BoxSizer(wx
.VERTICAL
)
229 contentSizer
.Add(sizer
, 0, wx
.LEFT|wx
.TOP|wx
.RIGHT
, SPACE
)
230 contentSizer
.Add(savePasswordCheckbox
, 0, wx
.TOP|wx
.LEFT|wx
.BOTTOM
, SPACE
)
231 contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
)
233 dlg
.SetSizer(contentSizer
)
237 if dlg
.ShowModal() == wx
.ID_OK
:
239 password
= passwordTxt
.GetValue()
240 save
= savePasswordCheckBox
.IsChecked()
247 return retcode
, password
, save
250 def SSLClientCert(self
):
251 dlg
= wx
.FileDialog(wx
.GetApp().GetTopWindow(),
252 message
="Choose certificate", defaultDir
=os
.getcwd(),
253 style
=wx
.OPEN|wx
.CHANGE_DIR
256 if dlg
.ShowModal() == wx
.ID_OK
:
258 certfile
= dlg
.GetPath()
264 return retcode
, certfile
268 #----------------------------------------------------------------------------
270 #----------------------------------------------------------------------------
272 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
273 menu
= menuBar
.GetMenu(menuBar
.FindMenu(_("Project")))
275 menu
.AppendSeparator()
277 wx
.EVT_MENU(frame
, SVNService
.SVN_UPDATE_ID
, self
.ProcessEvent
)
278 wx
.EVT_UPDATE_UI(frame
, SVNService
.SVN_UPDATE_ID
, self
.ProcessUpdateUIEvent
)
279 menu
.Append(SVNService
.SVN_UPDATE_ID
, _("SVN Update"), _("Update file from Subversion"))
280 wx
.EVT_MENU(frame
, SVNService
.SVN_CHECKIN_ID
, self
.ProcessEvent
)
281 wx
.EVT_UPDATE_UI(frame
, SVNService
.SVN_CHECKIN_ID
, self
.ProcessUpdateUIEvent
)
282 menu
.Append(SVNService
.SVN_CHECKIN_ID
, _("SVN Commit..."), _("Commit file changes to Subversion"))
283 wx
.EVT_MENU(frame
, SVNService
.SVN_CHECKOUT_ID
, self
.ProcessEvent
)
284 wx
.EVT_UPDATE_UI(frame
, SVNService
.SVN_CHECKOUT_ID
, self
.ProcessUpdateUIEvent
)
285 menu
.Append(SVNService
.SVN_CHECKOUT_ID
, _("SVN Checkout..."), _("Checkout file from Subversion"))
286 wx
.EVT_MENU(frame
, SVNService
.SVN_REVERT_ID
, self
.ProcessEvent
)
287 wx
.EVT_UPDATE_UI(frame
, SVNService
.SVN_REVERT_ID
, self
.ProcessUpdateUIEvent
)
288 menu
.Append(SVNService
.SVN_REVERT_ID
, _("SVN Revert"), _("Revert file from Subversion"))
290 menu
.AppendSeparator()
292 wx
.EVT_MENU(frame
, SVNService
.SVN_ADD_ID
, self
.ProcessEvent
)
293 wx
.EVT_UPDATE_UI(frame
, SVNService
.SVN_ADD_ID
, self
.ProcessUpdateUIEvent
)
294 menu
.Append(SVNService
.SVN_ADD_ID
, _("SVN Add"), _("Add file to Subversion"))
295 wx
.EVT_MENU(frame
, SVNService
.SVN_DELETE_ID
, self
.ProcessEvent
)
296 wx
.EVT_UPDATE_UI(frame
, SVNService
.SVN_DELETE_ID
, self
.ProcessUpdateUIEvent
)
297 menu
.Append(SVNService
.SVN_DELETE_ID
, _("SVN Delete"), _("Delete file from Subversion"))
300 def ProcessEvent(self
, event
):
304 if not SVN_INSTALLED
:
305 if id in SVNService
.SVN_COMMAND_LIST
:
306 wx
.MessageBox(_("pysvn not found. Please install pysvn"), _("Python Subversion"))
311 if id == SVNService
.SVN_UPDATE_ID
:
312 filenames
= self
.GetCurrentDocuments()
314 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
316 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
317 messageService
.ShowWindow()
319 view
= messageService
.GetView()
321 view
.AddLines(_("SVN Update:\n"))
323 for filename
in filenames
:
324 view
.AddLines("%s\n" % filename
)
326 status
= self
._client
.update(filename
)
328 if status
.number
> 0:
329 view
.AddLines(_("Updated to revision %s\n") % status
.number
)
331 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
333 if doc
.GetFilename() == filename
:
334 yesNoMsg
= wx
.MessageDialog(wx
.GetApp().GetTopWindow(),
335 _("Updated file '%s' is currently open. Close it?") % os
.path
.basename(filename
),
337 wx
.YES_NO|wx
.ICON_QUESTION
)
338 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
342 view
.AddLines(_("Update failed.\n"))
344 except pysvn
.ClientError
, e
:
345 view
.AddLines("%s\n" % str(e
))
346 wx
.MessageBox(str(e
), _("SVN Update"), wx
.OK | wx
.ICON_EXCLAMATION
)
348 extype
, ex
, tb
= sys
.exc_info()
349 view
.AddLines("Update failed: (%s) %s\n" % (extype
, str(ex
)))
350 for line
in traceback
.format_tb(tb
):
353 wx
.MessageBox(_("Update failed."), _("SVN Update"), wx
.OK | wx
.ICON_EXCLAMATION
)
355 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
359 elif id == SVNService
.SVN_CHECKIN_ID
:
360 filenames
= self
.GetCurrentDocuments()
362 # ask user if dirty files should be saved first
363 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
364 for filename
in filenames
:
366 if doc
.GetFilename() == filename
and doc
.IsModified():
367 yesNoMsg
= wx
.MessageDialog(wx
.GetApp().GetTopWindow(),
368 _("'%s' has unsaved modifications. Save it before commit?") % os
.path
.basename(filename
),
370 wx
.YES_NO|wx
.CANCEL|wx
.ICON_QUESTION
)
371 status
= yesNoMsg
.ShowModal()
372 if status
== wx
.ID_YES
:
374 elif status
== wx
.ID_NO
:
376 else: # elif status == wx.CANCEL:
381 for i
, filename
in enumerate(filenames
):
382 shortFilename
= os
.path
.basename(filename
)
383 shortFilenames
.append(shortFilename
)
385 dlg
= wx
.Dialog(wx
.GetApp().GetTopWindow(), -1, _("SVN Commit"))
387 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
388 sizer
.Add(wx
.StaticText(dlg
, -1, _("Comment:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
389 commentText
= wx
.TextCtrl(dlg
, -1, size
=(250,-1), style
=wx
.TE_MULTILINE
)
390 sizer
.Add(commentText
, 1, wx
.EXPAND|wx
.TOP
, HALF_SPACE
)
392 sizer
.Add(wx
.StaticText(dlg
, -1, _("Files:")), 0, wx
.ALIGN_CENTER_VERTICAL|wx
.TOP
, SPACE
)
393 fileList
= wx
.CheckListBox(dlg
, -1, choices
= shortFilenames
)
394 for i
in range(fileList
.GetCount()):
395 fileList
.Check(i
, True)
396 sizer
.Add(fileList
, 0, wx
.EXPAND|wx
.TOP
, HALF_SPACE
)
398 buttonSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
399 okBtn
= wx
.Button(dlg
, wx
.ID_OK
)
401 buttonSizer
.Add(okBtn
, 0, wx
.RIGHT
, HALF_SPACE
)
402 buttonSizer
.Add(wx
.Button(dlg
, wx
.ID_CANCEL
), 0)
404 contentSizer
= wx
.BoxSizer(wx
.VERTICAL
)
405 contentSizer
.Add(sizer
, 0, wx
.ALL
, SPACE
)
406 contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
)
408 dlg
.SetSizer(contentSizer
)
412 if dlg
.ShowModal() == wx
.ID_OK
:
413 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
415 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
416 messageService
.ShowWindow()
418 view
= messageService
.GetView()
420 view
.AddLines(_("SVN Commit:\n"))
424 for i
in range(fileList
.GetCount()):
425 if fileList
.IsChecked(i
):
426 selFilenames
.append(filenames
[i
])
427 view
.AddLines("%s\n" % filenames
[i
])
429 if len(selFilenames
):
430 comment
= commentText
.GetValue()
431 status
= self
._client
.checkin(selFilenames
, comment
)
434 view
.AddLines(_("Nothing to commit.\n"))
435 elif status
.number
> 0:
436 view
.AddLines(_("Committed as revision %s.\n") % status
.number
)
438 view
.AddLines(_("Commit failed.\n"))
440 except pysvn
.ClientError
, e
:
441 view
.AddLines("%s\n" % str(e
))
442 wx
.MessageBox(str(e
), _("SVN Commit"), wx
.OK | wx
.ICON_EXCLAMATION
)
444 extype
, ex
, tb
= sys
.exc_info()
445 view
.AddLines("Commit failed: (%s) %s\n" % (extype
, str(ex
)))
446 for line
in traceback
.format_tb(tb
):
448 wx
.MessageBox(_("Commit failed."), _("SVN Commit"), wx
.OK | wx
.ICON_EXCLAMATION
)
450 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
454 elif id == SVNService
.SVN_CHECKOUT_ID
:
455 config
= wx
.ConfigBase_Get()
456 svnUrl
= config
.Read(SVN_REPOSITORY_URL
, self
._defaultURL
)
458 dlg
= wx
.Dialog(wx
.GetApp().GetTopWindow(), -1, _("SVN Checkout"))
460 gridSizer
= wx
.FlexGridSizer(cols
= 2, hgap
= 5, vgap
= 5)
461 gridSizer
.Add(wx
.StaticText(dlg
, -1, _("Repository URL:")), 0, wx
.ALIGN_CENTER_VERTICAL|wx
.RIGHT|wx
.TOP
, HALF_SPACE
)
462 svnURLText
= wx
.TextCtrl(dlg
, -1, svnUrl
, size
= (200, -1))
463 svnURLText
.SetToolTipString(svnUrl
)
464 gridSizer
.Add(svnURLText
, 0)
466 gridSizer
.Add(wx
.StaticText(dlg
, -1, _("Checkout to dir:")), 0, wx
.ALIGN_CENTER_VERTICAL|wx
.RIGHT|wx
.TOP
, HALF_SPACE
)
467 localPath
= wx
.TextCtrl(dlg
, -1, size
= (200, -1))
468 localPath
.SetToolTipString(_("Path in local file system where files will be located."))
469 findDirButton
= wx
.Button(dlg
, -1, _("Browse..."))
471 def OnBrowseButton(event
):
472 dirDlg
= wx
.DirDialog(wx
.GetApp().GetTopWindow(), _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
)
473 dir = localPath
.GetValue()
476 if dirDlg
.ShowModal() == wx
.ID_OK
:
477 localPath
.SetValue(dirDlg
.GetPath())
478 localPath
.SetToolTipString(localPath
.GetValue())
479 localPath
.SetInsertionPointEnd()
482 wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
)
484 sizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
485 sizer
.Add(localPath
, 1, wx
.EXPAND
)
486 sizer
.Add(findDirButton
, 0, wx
.LEFT
, HALF_SPACE
)
487 gridSizer
.Add(sizer
, 0)
489 buttonSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
490 okBtn
= wx
.Button(dlg
, wx
.ID_OK
)
492 buttonSizer
.Add(okBtn
, 0, wx
.RIGHT
, HALF_SPACE
)
493 buttonSizer
.Add(wx
.Button(dlg
, wx
.ID_CANCEL
), 0)
495 contentSizer
= wx
.BoxSizer(wx
.VERTICAL
)
496 contentSizer
.Add(gridSizer
, 0, wx
.ALL
, SPACE
)
497 contentSizer
.Add(buttonSizer
, 0, wx
.ALL|wx
.ALIGN_RIGHT
, SPACE
)
499 dlg
.SetSizer(contentSizer
)
503 if dlg
.ShowModal() == wx
.ID_OK
:
504 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
506 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
507 messageService
.ShowWindow()
509 view
= messageService
.GetView()
511 view
.AddLines(_("SVN Checkout:\n"))
513 svnUrl
= svnURLText
.GetValue()
514 toLocation
= localPath
.GetValue()
516 self
._client
.checkout(svnUrl
, toLocation
)
517 view
.AddLines(_("Checkout completed.\n"))
518 except pysvn
.ClientError
, e
:
519 view
.AddLines(_("Checkout failed. %s\n") % str(e
))
520 wx
.MessageBox(_("Checkout failed. %s") % str(e
), _("SVN Checkout"), wx
.OK | wx
.ICON_EXCLAMATION
)
522 extype
, ex
, tb
= sys
.exc_info()
523 view
.AddLines("Checkout failed: (%s) %s\n" % (extype
, str(ex
)))
524 for line
in traceback
.format_tb(tb
):
526 wx
.MessageBox(_("Checkout failed."), _("SVN Checkout"), wx
.OK | wx
.ICON_EXCLAMATION
)
528 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
532 elif id == SVNService
.SVN_REVERT_ID
:
533 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
535 filenames
= self
.GetCurrentDocuments()
537 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
538 messageService
.ShowWindow()
540 view
= messageService
.GetView()
542 view
.AddLines(_("SVN Revert:\n"))
543 for filename
in filenames
:
544 view
.AddLines("%s\n" % filename
)
547 self
._client
.revert(filenames
)
548 view
.AddLines(_("Revert completed.\n"))
550 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
551 for doc
in openDocs
[:]: # need to make a copy of the list otherwise ordinality changes as we close the files
552 if doc
.GetFilename() in filenames
:
553 yesNoMsg
= wx
.MessageDialog(wx
.GetApp().GetTopWindow(),
554 _("Reverted file '%s' is currently open. Close it?") % os
.path
.basename(doc
.GetFilename()),
556 wx
.YES_NO|wx
.ICON_QUESTION
)
557 if yesNoMsg
.ShowModal() == wx
.ID_YES
:
560 except pysvn
.ClientError
, e
:
561 view
.AddLines("%s\n" % str(e
))
562 wx
.MessageBox(str(e
), _("SVN Revert"), wx
.OK | wx
.ICON_EXCLAMATION
)
564 extype
, ex
, tb
= sys
.exc_info()
565 view
.AddLines("Revert failed: (%s) %s\n" % (extype
, str(ex
)))
566 for line
in traceback
.format_tb(tb
):
568 wx
.MessageBox(_("Revert failed."), _("SVN Revert"), wx
.OK | wx
.ICON_EXCLAMATION
)
570 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
573 elif id == SVNService
.SVN_ADD_ID
:
574 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
576 filenames
= self
.GetCurrentDocuments()
578 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
579 messageService
.ShowWindow()
581 view
= messageService
.GetView()
583 view
.AddLines(_("SVN Add:\n"))
584 for filename
in filenames
:
585 view
.AddLines("%s\n" % filename
)
588 self
._client
.add(filenames
)
589 view
.AddLines(_("Add completed.\n"))
590 except pysvn
.ClientError
, e
:
591 view
.AddLines("%s\n" % str(e
))
592 wx
.MessageBox(str(e
), _("SVN Add"), wx
.OK | wx
.ICON_EXCLAMATION
)
594 extype
, ex
, tb
= sys
.exc_info()
595 view
.AddLines("Add failed: (%s) %s\n" % (extype
, str(ex
)))
596 for line
in traceback
.format_tb(tb
):
598 wx
.MessageBox(_("Add failed."), _("SVN Add"), wx
.OK | wx
.ICON_EXCLAMATION
)
600 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
603 elif id == SVNService
.SVN_DELETE_ID
:
604 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
606 filenames
= self
.GetCurrentDocuments()
608 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
609 messageService
.ShowWindow()
611 view
= messageService
.GetView()
613 view
.AddLines(_("SVN Delete:\n"))
614 for filename
in filenames
:
615 view
.AddLines("%s\n" % filename
)
618 self
._client
.remove(filenames
)
619 view
.AddLines(_("Delete completed.\n"))
620 except pysvn
.ClientError
, e
:
621 view
.AddLines("%s\n" % str(e
))
622 wx
.MessageBox(str(e
), _("SVN Delete"), wx
.OK | wx
.ICON_EXCLAMATION
)
624 extype
, ex
, tb
= sys
.exc_info()
625 view
.AddLines("Delete failed: (%s) %s\n" % (extype
, str(ex
)))
626 for line
in traceback
.format_tb(tb
):
628 wx
.MessageBox(_("Delete failed."), _("SVN Delete"), wx
.OK | wx
.ICON_EXCLAMATION
)
630 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
636 def ProcessUpdateUIEvent(self
, event
):
639 if id in [SVNService
.SVN_UPDATE_ID
,
640 SVNService
.SVN_CHECKIN_ID
,
641 SVNService
.SVN_REVERT_ID
,
642 SVNService
.SVN_ADD_ID
,
643 SVNService
.SVN_DELETE_ID
]:
644 if self
.GetCurrentDocuments():
650 elif id == SVNService
.SVN_CHECKOUT_ID
:
657 def GetCurrentDocuments(self
):
659 projectService
= wx
.GetApp().GetService(ProjectEditor
.ProjectService
)
661 projView
= projectService
.GetView()
663 if projView
.HasFocus():
664 filenames
= projView
.GetSelectedFiles()
670 doc
= wx
.GetApp().GetTopWindow().GetDocumentManager().GetCurrentDocument()
672 filenames
= [doc
.GetFilename()]
679 class SVNOptionsPanel(wx
.Panel
):
682 def __init__(self
, parent
, id):
683 wx
.Panel
.__init
__(self
, parent
, id)
685 config
= wx
.ConfigBase_Get()
686 svnService
= wx
.GetApp().GetService(SVNService
)
687 svnUrl
= config
.Read(SVN_REPOSITORY_URL
, svnService
._defaultURL
)
688 configDir
= config
.Read(SVN_CONFIG_DIR
, "")
690 borderSizer
= wx
.BoxSizer(wx
.VERTICAL
)
691 sizer
= wx
.FlexGridSizer(cols
= 2, hgap
= 5, vgap
= 5)
693 sizer
.Add(wx
.StaticText(self
, -1, _("SVN Config Dir:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
695 self
._svnConfigDir
= wx
.TextCtrl(self
, -1, configDir
, size
= (200, -1))
697 self
._svnConfigDir
.SetToolTipString(_("Path Subversion configuration directory."))
699 self
._svnConfigDir
.SetToolTipString(configDir
)
701 findDirButton
= wx
.Button(self
, -1, _("Browse..."))
703 def OnBrowseButton(event
):
704 dirDlg
= wx
.DirDialog(self
, _("Choose a directory:"), style
=wx
.DD_DEFAULT_STYLE
)
705 dir = self
._svnConfigDir
.GetValue()
708 if dirDlg
.ShowModal() == wx
.ID_OK
:
709 self
._svnConfigDir
.SetValue(dirDlg
.GetPath())
710 self
._svnConfigDir
.SetToolTipString(self
._svnConfigDir
.GetValue())
711 self
._svnConfigDir
.SetInsertionPointEnd()
714 wx
.EVT_BUTTON(findDirButton
, -1, OnBrowseButton
)
716 hsizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
717 hsizer
.Add(self
._svnConfigDir
, 1, wx
.EXPAND
)
718 hsizer
.Add(findDirButton
, 0, wx
.LEFT
, HALF_SPACE
)
721 sizer
.Add(wx
.StaticText(self
, -1, _("SVN URL:")), 0, wx
.ALIGN_CENTER_VERTICAL
)
722 self
._svnURLText
= wx
.TextCtrl(self
, -1, svnUrl
, size
= (200, -1))
723 self
._svnURLText
.SetToolTipString(svnUrl
)
724 sizer
.Add(self
._svnURLText
, 0)
726 borderSizer
.Add(sizer
, 0, wx
.ALL
, SPACE
)
727 self
.SetSizer(borderSizer
)
729 parent
.AddPage(self
, _("SVN"))
732 def OnOK(self
, optionsDialog
):
733 config
= wx
.ConfigBase_Get()
734 config
.Write(SVN_CONFIG_DIR
, self
._svnConfigDir
.GetValue())
735 config
.Write(SVN_REPOSITORY_URL
, self
._svnURLText
.GetValue())