33#include <wx/clipbrd.h>
36#include <wx/stdpaths.h>
53 m_tempPath = wxFileName::CreateTempFileName(
"kicadtestrepo" );
55 git_repository_init_options options;
56 git_repository_init_init_options( &options, GIT_REPOSITORY_INIT_OPTIONS_VERSION );
57 options.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_NO_REINIT;
66 [
this]( wxCommandEvent& aEvent )
87 wxClipboardLocker lock;
91 if( !wxTheClipboard->IsSupported( wxDF_TEXT ) )
94 wxTextDataObject textData;
95 if( !wxTheClipboard->GetData( textData ) )
98 wxString clipboardText = textData.GetText();
99 if( clipboardText.empty() )
103 || std::get<0>(
isValidSSH( clipboardText ) ) )
105 m_txtURL->SetValue( clipboardText );
116 sshKey.SetPath( wxGetUserHome() );
119 sshKey.AppendDir(
".ssh" );
120 sshKey.SetFullName(
"id_rsa" );
122 if( sshKey.FileExists() )
124 retval = sshKey.GetFullPath();
126 else if( sshKey.SetFullName(
"id_dsa" ); sshKey.FileExists() )
128 retval = sshKey.GetFullPath();
130 else if( sshKey.SetFullName(
"id_ecdsa" ); sshKey.FileExists() )
132 retval = sshKey.GetFullPath();
135 if( !retval.empty() )
138 wxFileDirPickerEvent evt;
139 evt.SetPath( retval );
163 m_txtPassword->SetToolTip(
_(
"Enter the password for the SSH key" ) );
176 wxRegEx regex( R
"((https?:\/\/)(([^:]+)(:([^@]+))?@)?([^\/]+\/[^\s]+))" );
178 if( regex.Matches( url ) )
180 wxString username = regex.GetMatch( url, 3 );
181 wxString password = regex.GetMatch( url, 5 );
182 wxString repoAddress = regex.GetMatch( url, 1 ) + regex.GetMatch( url, 6 );
183 return std::make_tuple(
true, username, password, repoAddress );
186 return std::make_tuple(
false,
"",
"",
"" );
192 wxRegEx regex( R
"((?:ssh:\/\/)?([^@]+)@([^\/]+\/[^\s]+))" );
194 if( regex.Matches( url ) )
196 wxString username = regex.GetMatch( url, 1 );
197 wxString repoAddress = regex.GetMatch( url, 2 );
198 return std::make_tuple(
true, username, repoAddress );
201 return std::make_tuple(
false,
"",
"" );
207 wxString addr = aRepoAddr;
212 static wxRegEx webSuffix(
213 R
"((/-)?/(tree|blob|commits?|raw|releases|tags|branches|pulls|pull|issues|merge_requests|wiki|actions)/.*$)",
216 webSuffix.ReplaceAll( &addr, wxEmptyString );
218 while( addr.EndsWith(
"/" ) )
221 if( addr.EndsWith(
".git" ) )
222 addr.RemoveLast( 4 );
224 size_t last_slash = addr.find_last_of(
'/' );
226 if( last_slash == wxString::npos )
229 return addr.substr( last_slash + 1 );
243 wxString url =
m_txtURL->GetValue();
248 if( url.Contains(
"https://" ) || url.Contains(
"http://" ) )
250 auto [valid, username, password, repoAddress] =
isValidHTTPS( url );
257 if( !username.IsEmpty() )
260 if( !password.IsEmpty() )
263 m_txtURL->ChangeValue( repoAddress );
267 else if( url.Contains(
"ssh://" ) || url.Contains(
"git@" ) )
269 auto [valid, username, repoAddress] =
isValidSSH( url );
276 m_txtURL->ChangeValue( repoAddress );
290 size_t colonPos = url.find(
':' );
291 size_t slashPos = url.find(
'/' );
293 if( colonPos != wxString::npos && ( slashPos == wxString::npos || colonPos < slashPos ) )
306 if(
m_txtURL->GetValue().Trim().Trim(
false ).IsEmpty() )
310 bool success =
false;
311 git_remote* remote =
nullptr;
312 git_remote_callbacks callbacks;
313 git_remote_init_callbacks( &callbacks, GIT_REMOTE_CALLBACKS_VERSION );
328 callbacks.payload = &repoMixin;
331 git_proxy_options proxyOpts;
332 git_proxy_init_options( &proxyOpts, GIT_PROXY_OPTIONS_VERSION );
333 proxyOpts.type = GIT_PROXY_AUTO;
336 git_remote_create_anonymous( &remote,
m_repository, fullURL.mbc_str() );
339 if( git_remote_connect( remote, GIT_DIRECTION_FETCH, &callbacks, &proxyOpts,
nullptr ) == GIT_OK )
344 git_remote_disconnect( remote );
347 wxOK | wxICON_INFORMATION );
351 dlg.SetMessage(
_(
"Connection successful" ) );
355 dlg.SetMessage( wxString::Format(
_(
"Could not connect to '%s' " ),
357 dlg.SetExtendedMessage( error );
366 wxString file = aEvent.GetPath();
368 if( file.ends_with( wxS(
".pub" ) ) )
369 file = file.Left( file.size() - 4 );
371 std::ifstream ifs( file.fn_str() );
373 if( !ifs.good() || !ifs.is_open() )
376 wxString::Format(
"%s: %d", std::strerror( errno ), errno ) );
381 std::getline( ifs, line );
383 bool isValid = ( line.find(
"PRIVATE KEY" ) != std::string::npos );
384 bool isEncrypted = ( line.find(
"ENCRYPTED" ) != std::string::npos );
389 _(
"The selected file is not a valid SSH private key" ) );
397 m_txtPassword->SetToolTip(
_(
"Enter the password for the SSH key" ) );
408 wxString pubFile = file + wxS(
".pub" );
409 std::ifstream pubIfs( pubFile.fn_str() );
411 if( !pubIfs.good() || !pubIfs.is_open() )
415 wxString::Format(
"%s: %d", std::strerror( errno ), errno ) );
416 aEvent.SetPath( wxEmptyString );
430 if(
m_txtURL->GetValue().IsEmpty() )
433 _(
"Please enter a URL for the repository" ) );
483 if( !
m_txtURL->GetValue().IsEmpty() )
DIALOG_GIT_REPOSITORY_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Git Repository"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxCAPTION|wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxTextCtrl * m_txtPassword
wxStaticText * m_labelPass1
wxTextCtrl * m_txtUsername
wxFilePickerCtrl * m_fpSSHKey
void OnSelectConnType(wxCommandEvent &event) override
std::tuple< bool, wxString, wxString > isValidSSH(const wxString &url)
void SetRepoSSHPath(const wxString &aPath)
void OnFileUpdated(wxFileDirPickerEvent &event) override
void SetPassword(const wxString &aPassword)
void onCbCustom(wxCommandEvent &event) override
~DIALOG_GIT_REPOSITORY() override
void SetEncrypted(bool aEncrypted=true)
void OnLocationExit(wxFocusEvent &event) override
DIALOG_GIT_REPOSITORY(wxWindow *aParent, git_repository *aRepository, wxString aURL=wxEmptyString)
void OnTestClick(wxCommandEvent &event) override
void OnOKClick(wxCommandEvent &event) override
void SetUsername(const wxString &aUsername)
std::tuple< bool, wxString, wxString, wxString > isValidHTTPS(const wxString &url)
virtual bool TransferDataToWindow() override
void updateAuthControls()
bool extractClipboardData()
void OnUpdateUI(wxUpdateUIEvent &event) override
git_repository * m_repository
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
static wxString GetLastGitError()
void SetSSHKey(const wxString &aSSHKey)
void SetUsername(const wxString &aUsername)
void SetPassword(const wxString &aPassword)
void SetRemote(const wxString &aRemote)
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
#define KICAD_MESSAGE_DIALOG
static wxString get_repo_name(wxString &aRepoAddr)
bool RmDirRecursive(const wxString &aFileName, wxString *aErrors)
Remove the directory aDirName and all its contents including subdirectories and their files.
int credentials_cb(git_cred **aOut, const char *aUrl, const char *aUsername, unsigned int aAllowedTypes, void *aPayload)
std::unique_ptr< git_remote, decltype([](git_remote *aRemote) { git_remote_free(aRemote); })> GitRemotePtr
A unique pointer for git_remote objects with automatic cleanup.