35#include <wx/clipbrd.h>
38#include <wx/stdpaths.h>
57 m_tempPath = wxFileName::CreateTempFileName(
"kicadtestrepo" );
59 git_repository_init_options options;
60 git_repository_init_init_options( &options, GIT_REPOSITORY_INIT_OPTIONS_VERSION );
61 options.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_NO_REINIT;
70 [
this]( wxCommandEvent& aEvent )
91 wxClipboardLocker lock;
95 if( !wxTheClipboard->IsSupported( wxDF_TEXT ) )
98 wxTextDataObject textData;
99 if( !wxTheClipboard->GetData( textData ) )
102 wxString clipboardText = textData.GetText();
103 if( clipboardText.empty() )
109 && clipboardText.find_first_of(
" \t\r\n" ) == wxString::npos )
111 m_txtURL->SetValue( clipboardText );
130 wxFileDirPickerEvent evt;
131 evt.SetPath( keys.front() );
154 m_txtPassword->SetToolTip(
_(
"Enter the password for the SSH key" ) );
167 wxString addr = aRepoAddr;
172 static wxRegEx webSuffix(
173 R
"((/-)?/(tree|blob|commits?|raw|releases|tags|branches|pulls|pull|issues|merge_requests|wiki|actions)/.*$)",
176 webSuffix.ReplaceAll( &addr, wxEmptyString );
178 while( addr.EndsWith(
"/" ) )
181 if( addr.EndsWith(
".git" ) )
182 addr.RemoveLast( 4 );
184 size_t last_slash = addr.find_last_of(
"/\\" );
186 if( last_slash == wxString::npos )
187 return addr.AfterLast(
':' );
189 return addr.substr( last_slash + 1 );
203 wxString url =
m_txtURL->GetValue();
222 if( parsed.
url != url )
233 if( wxString( url ).Trim().Trim(
false ).IsEmpty() )
238 bool success =
false;
239 git_remote* remote =
nullptr;
240 git_remote_callbacks callbacks;
241 git_remote_init_callbacks( &callbacks, GIT_REMOTE_CALLBACKS_VERSION );
257 callbacks.payload = &repoMixin;
261 git_proxy_options proxyOpts;
262 git_proxy_init_options( &proxyOpts, GIT_PROXY_OPTIONS_VERSION );
263 proxyOpts.type = GIT_PROXY_AUTO;
272 if(
const char* remoteUrl = git_remote_url( remote ) )
275 bool retriedAfterTrust =
false;
280 result = git_remote_connect( remote, GIT_DIRECTION_FETCH, &callbacks, &proxyOpts,
nullptr );
284 git_remote_disconnect( remote );
291 git_remote_disconnect( remote );
304 retriedAfterTrust =
true;
326 wxOK | wxICON_INFORMATION );
333 wxString file = aEvent.GetPath();
335 if( file.ends_with( wxS(
".pub" ) ) )
336 file = file.Left( file.size() - 4 );
338 std::ifstream ifs( file.fn_str() );
340 if( !ifs.good() || !ifs.is_open() )
343 wxString::Format(
"%s: %d", std::strerror( errno ), errno ) );
347 std::string keyText( ( std::istreambuf_iterator<char>( ifs ) ), std::istreambuf_iterator<char>() );
351 wxString key = wxString::FromUTF8( keyText );
353 if( !key.BeforeFirst(
'\n' ).Contains( wxS(
"PRIVATE KEY" ) ) )
356 _(
"The selected file is not a valid SSH private key" ) );
363 wxString pubFile = file + wxS(
".pub" );
364 std::ifstream pubIfs( pubFile.fn_str() );
366 if( !pubIfs.good() || !pubIfs.is_open() )
370 wxString::Format(
"%s: %d", std::strerror( errno ), errno ) );
371 aEvent.SetPath( wxEmptyString );
385 if(
m_txtURL->GetValue().IsEmpty() )
388 _(
"Please enter a URL for the repository" ) );
441 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
void SetRepoSSHPath(const wxString &aPath)
KIGIT_COMMON::GIT_CONN_TYPE GetRepoType() const
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 setDefaultSSHKey(const wxString &aHost)
void OnTestClick(wxCommandEvent &event) override
wxString GetRepoURL() const
wxString GetUsername() const
void OnOKClick(wxCommandEvent &event) override
void SetUsername(const wxString &aUsername)
virtual bool TransferDataToWindow() override
void updateAuthControls()
bool extractClipboardData()
void OnUpdateUI(wxUpdateUIEvent &event) override
git_repository * m_repository
void OptOut(wxWindow *aWindow)
Opt out of control state saving.
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...
The project's git session.
void FollowRewrittenUrl(const wxString &aRawUrl)
Bind the session to a URL that url.insteadOf rewrote, keeping the username, password and key entered ...
void SetSSHKey(const wxString &aSSHKey)
void SetUsername(const wxString &aUsername)
static KIGIT_ERROR_INFO GetLastGitErrorInfo(int aCode)
The error libgit2 holds for a call that returned aCode.
static REMOTE_URL ParseRemoteURL(const wxString &aURL)
void SetPassword(const wxString &aPassword)
void SetRemote(const wxString &aRemote)
std::optional< KIGIT::HOST_KEY_FAILURE > GetHostKeyFailure() const
The host key this operation's transfer refused, for the UI to offer to trust or to report.
KIGIT_FAILURE_REPORT ReportTransferFailure(const KIGIT_ERROR_INFO &aError, KIGIT_OPERATION aOperation, const wxString &aRemoteName)
Classify a failed libgit2 transfer call and queue its summary and details.
void ResetTransferState()
Start a transfer with nothing left from an earlier one on this handler or session: no keys or methods...
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(const wxString &aRepoAddr)
bool RmDirRecursive(const wxString &aFileName, wxString *aErrors)
Remove the directory aDirName and all its contents including subdirectories and their files.
int certificate_check_cb(git_cert *aCert, int aValid, const char *aHost, void *aPayload)
Check an SSH host key against known_hosts, which decides alone.
int credentials_cb(git_cred **aOut, const char *aUrl, const char *aUsername, unsigned int aAllowedTypes, void *aPayload)
bool IsPrivateKeyEncrypted(const wxString &aKeyText)
Report whether an SSH private key is protected by a passphrase.
bool PromptToTrustHost(wxWindow *aParent, const HOST_KEY_FAILURE &aFailure, bool aRetriedAfterTrust)
Ask whether to trust a server seen for the first time, and remember its key when the user agrees.
APIEXPORT wxString HomeDir()
The user's home folder, where ssh looks for its config and default keys.
APIEXPORT KIGIT_FAILURE_REPORT DescribeGitFailure(const KIGIT_ERROR_INFO &aError, const KIGIT_AUTH_ATTEMPT &aAuth, const KIGIT_FAILURE_CONTEXT &aContext)
Turn a failed transfer into a message the user can act on.
std::unique_ptr< git_remote, decltype([](git_remote *aRemote) { git_remote_free(aRemote); })> GitRemotePtr
A unique pointer for git_remote objects with automatic cleanup.
APIEXPORT std::vector< wxString > DefaultSSHKeyCandidates(const wxString &aHomeDir, const wxString &aHost)
Private keys to offer aHost, best first.
A transport address with any embedded credentials extracted.
wxString url
Keeps the SSH username, scheme and port, but never a password.
What the failed operation was doing, as far as the message needs it.
KIGIT_OPERATION operation
wxString url
The address connected to. Messages show only its host and its stripped form.
wxString summary
What happened and what to do next, in the user's terms. Never raw text.
wxString details
The raw error, the server's text and the address without its password.
wxString result
Test unit parsing edge cases and error handling.