34#include <wx/clipbrd.h>
37#include <wx/stdpaths.h>
43 m_repository( aRepository ),
44 m_prevFile( wxEmptyString ),
46 m_failedTest( false ),
47 m_testError( wxEmptyString ),
56 m_tempPath = wxFileName::CreateTempFileName(
"kicadtestrepo" );
58 git_repository_init_options options;
59 git_repository_init_init_options( &options, GIT_REPOSITORY_INIT_OPTIONS_VERSION );
60 options.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_NO_REINIT;
69 if( !
m_txtURL->GetValue().IsEmpty() )
90 if( wxTheClipboard->Open() && wxTheClipboard->IsSupported( wxDF_TEXT ) )
92 wxString clipboardText;
93 wxTextDataObject textData;
95 if( wxTheClipboard->GetData( textData ) && !( clipboardText = textData.GetText() ).empty() )
98 || std::get<0>(
isValidSSH( clipboardText ) ) )
100 m_txtURL->SetValue( clipboardText );
104 wxTheClipboard->Close();
114 sshKey.SetPath( wxGetUserHome() );
117 sshKey.AppendDir(
".ssh" );
118 sshKey.SetFullName(
"id_rsa" );
120 if( sshKey.FileExists() )
122 retval = sshKey.GetFullPath();
124 else if( sshKey.SetFullName(
"id_dsa" ); sshKey.FileExists() )
126 retval = sshKey.GetFullPath();
128 else if( sshKey.SetFullName(
"id_ecdsa" ); sshKey.FileExists() )
130 retval = sshKey.GetFullPath();
133 if( !retval.empty() )
136 wxFileDirPickerEvent evt;
137 evt.SetPath( retval );
154 m_txtPassword->SetToolTip(
_(
"Enter the password for the SSH key" ) );
166 wxRegEx regex( R
"((https?:\/\/)(([^:]+)(:([^@]+))?@)?([^\/]+\/[^\s]+))" );
168 if( regex.Matches( url ) )
170 wxString username = regex.GetMatch( url, 3 );
171 wxString password = regex.GetMatch( url, 5 );
172 wxString repoAddress = regex.GetMatch( url, 1 ) + regex.GetMatch( url, 6 );
173 return std::make_tuple(
true, username, password, repoAddress );
176 return std::make_tuple(
false,
"",
"",
"" );
182 wxRegEx regex( R
"((?:ssh:\/\/)?([^@]+)@([^\/]+\/[^\s]+))" );
184 if( regex.Matches( url ) )
186 wxString username = regex.GetMatch( url, 1 );
187 wxString repoAddress = regex.GetMatch( url, 2 );
188 return std::make_tuple(
true, username, repoAddress );
191 return std::make_tuple(
false,
"",
"" );
198 size_t last_slash = aRepoAddr.find_last_of(
'/' );
199 bool ends_with_dot_git = aRepoAddr.EndsWith(
".git" );
201 if( ends_with_dot_git )
202 retval = aRepoAddr.substr( last_slash + 1, aRepoAddr.size() - last_slash - 5 );
204 retval = aRepoAddr.substr( last_slash + 1, aRepoAddr.size() - last_slash );
220 wxString url =
m_txtURL->GetValue();
225 if( url.Contains(
"https://" ) || url.Contains(
"http://" ) )
227 auto [valid, username, password, repoAddress] =
isValidHTTPS( url );
241 else if( url.Contains(
"ssh://" ) || url.Contains(
"git@" ) )
243 auto [valid, username, repoAddress] =
isValidSSH( url );
262 git_remote* remote =
nullptr;
263 git_remote_callbacks callbacks;
264 git_remote_init_callbacks( &callbacks, GIT_REMOTE_CALLBACKS_VERSION );
271 callbacks.credentials = []( git_cred** aOut,
const char* aUrl,
const char* aUsername,
272 unsigned int aAllowedTypes,
void* aPayload ) ->
int
277 return GIT_PASSTHROUGH;
279 if( aAllowedTypes & GIT_CREDTYPE_USERNAME
280 && !( dialog->
GetTested() & GIT_CREDTYPE_USERNAME ) )
282 wxString username = dialog->
GetUsername().Trim().Trim(
false );
283 git_cred_username_new( aOut, username.ToStdString().c_str() );
284 dialog->
GetTested() |= GIT_CREDTYPE_USERNAME;
287 && ( aAllowedTypes & GIT_CREDTYPE_USERPASS_PLAINTEXT )
288 && !( dialog->
GetTested() & GIT_CREDTYPE_USERPASS_PLAINTEXT ) )
290 wxString username = dialog->
GetUsername().Trim().Trim(
false );
291 wxString password = dialog->
GetPassword().Trim().Trim(
false );
293 git_cred_userpass_plaintext_new( aOut, username.ToStdString().c_str(),
294 password.ToStdString().c_str() );
295 dialog->
GetTested() |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
298 && ( aAllowedTypes & GIT_CREDTYPE_SSH_KEY )
299 && !( dialog->
GetTested() & GIT_CREDTYPE_SSH_KEY ) )
303 wxString sshPubKey = sshKey +
".pub";
304 wxString username = dialog->
GetUsername().Trim().Trim(
false );
305 wxString password = dialog->
GetPassword().Trim().Trim(
false );
307 git_cred_ssh_key_new( aOut, username.ToStdString().c_str(),
308 sshPubKey.ToStdString().c_str(), sshKey.ToStdString().c_str(),
309 password.ToStdString().c_str() );
310 dialog->
GetTested() |= GIT_CREDTYPE_SSH_KEY;
314 return GIT_PASSTHROUGH;
320 callbacks.payload =
this;
322 wxString txtURL =
m_txtURL->GetValue();
323 git_remote_create_with_fetchspec( &remote,
m_repository,
"origin", txtURL.ToStdString().c_str(),
324 "+refs/heads/*:refs/remotes/origin/*" );
326 if( git_remote_connect( remote, GIT_DIRECTION_FETCH, &callbacks,
nullptr,
nullptr ) != GIT_OK )
331 git_remote_disconnect( remote );
332 git_remote_free( remote );
334 auto dlg = wxMessageDialog(
this, wxEmptyString,
_(
"Test connection" ), wxOK | wxICON_INFORMATION );
338 dlg.SetMessage(
_(
"Connection successful" ) );
342 dlg.SetMessage( wxString::Format(
_(
"Could not connect to '%s' " ),
m_txtURL->GetValue() ) );
352 wxString file = aEvent.GetPath();
354 if( file.ends_with( wxS(
".pub" ) ) )
355 file = file.Left( file.size() - 4 );
357 std::ifstream ifs( file.fn_str() );
359 if( !ifs.good() || !ifs.is_open() )
362 wxString::Format(
"%s: %d", std::strerror( errno ), errno ) );
367 std::getline( ifs, line );
369 bool isValid = ( line.find(
"PRIVATE KEY" ) != std::string::npos );
370 bool isEncrypted = ( line.find(
"ENCRYPTED" ) != std::string::npos );
375 _(
"The selected file is not a valid SSH private key" ) );
383 m_txtPassword->SetToolTip(
_(
"Enter the password for the SSH key" ) );
394 wxString pubFile = file + wxS(
".pub" );
395 std::ifstream pubIfs( pubFile.fn_str() );
397 if( !pubIfs.good() || !pubIfs.is_open() )
401 wxString::Format(
"%s: %d", std::strerror( errno ), errno ) );
402 aEvent.SetPath( wxEmptyString );
419 _(
"Please enter a name for the repository" ) );
423 if(
m_txtURL->GetValue().IsEmpty() )
426 _(
"Please enter a URL for the repository" ) );
Class DIALOG_GIT_REPOSITORY_BASE.
wxTextCtrl * m_txtPassword
wxStaticText * m_labelSSH
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)
KIGIT_COMMON::GIT_CONN_TYPE GetRepoType() const
void OnFileUpdated(wxFileDirPickerEvent &event) override
void SetPassword(const wxString &aPassword)
wxString GetRepoSSHPath() const
void SetTestResult(bool aFailed, const wxString &aError)
~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
wxString GetUsername() const
void OnOKClick(wxCommandEvent &event) override
void SetUsername(const wxString &aUsername)
std::tuple< bool, wxString, wxString, wxString > isValidHTTPS(const wxString &url)
void updateAuthControls()
bool extractClipboardData()
void OnUpdateUI(wxUpdateUIEvent &event) override
wxString GetPassword() const
git_repository * m_repository
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
static wxString get_repo_name(wxString &aRepoAddr)
bool RmDirRecursive(const wxString &aFileName, wxString *aErrors)
Removes the directory aDirName and all its contents including subdirectories and their files.