Browse Source
ADDED: Git integration support
ADDED: Git integration support
Adds support for project-based git integration, branch support, commit, revert and updates Fixes https://gitlab.com/kicad/code/kicad/issues/10441newinvert
196 changed files with 13121 additions and 38 deletions
-
12CMakeLists.txt
-
38cmake/Findlibgit2.cmake
-
29common/CMakeLists.txt
-
6common/advanced_config.cpp
-
14common/bitmap_info.cpp
-
96common/dialogs/git/dialog_git_auth.cpp
-
59common/dialogs/git/dialog_git_auth.h
-
204common/dialogs/git/dialog_git_commit.cpp
-
62common/dialogs/git/dialog_git_commit.h
-
49common/dialogs/git/dialog_git_progress.cpp
-
448common/dialogs/git/dialog_git_repository.cpp
-
124common/dialogs/git/dialog_git_repository.h
-
172common/dialogs/git/dialog_git_repository_base.cpp
-
1335common/dialogs/git/dialog_git_repository_base.fbp
-
82common/dialogs/git/dialog_git_repository_base.h
-
288common/dialogs/git/dialog_git_switch.cpp
-
79common/dialogs/git/dialog_git_switch.h
-
377common/dialogs/git/panel_git_repos.cpp
-
59common/dialogs/git/panel_git_repos.h
-
167common/dialogs/git/panel_git_repos_base.cpp
-
73common/dialogs/git/panel_git_repos_base.h
-
953common/dialogs/git/panel_git_repositories_base.fbp
-
11common/eda_base_frame.cpp
-
123common/eda_shape.cpp
-
61common/eda_text.cpp
-
50common/gestfich.cpp
-
108common/git/git_add_to_index_handler.cpp
-
50common/git/git_add_to_index_handler.h
-
82common/git/git_clone_handler.cpp
-
56common/git/git_clone_handler.h
-
49common/git/git_commit_handler.cpp
-
58common/git/git_commit_handler.h
-
0common/git/git_compare_handler.cpp
-
0common/git/git_compare_handler.h
-
72common/git/git_progress.h
-
343common/git/git_pull_handler.cpp
-
100common/git/git_pull_handler.h
-
79common/git/git_push_handler.cpp
-
57common/git/git_push_handler.h
-
98common/git/git_remove_from_index_handler.cpp
-
50common/git/git_remove_from_index_handler.h
-
0common/git/git_remove_vcs_handler.cpp
-
0common/git/git_remove_vcs_handler.h
-
39common/git/git_resolve_conflict_handler.cpp
-
43common/git/git_resolve_conflict_handler.h
-
108common/git/git_revert_handler.cpp
-
54common/git/git_revert_handler.h
-
0common/git/git_switch_branch_handler.cpp
-
0common/git/git_switch_branch_handler.h
-
44common/git/git_sync_handler.cpp
-
43common/git/git_sync_handler.h
-
97common/git/kicad_git_blob_reader.h
-
541common/git/kicad_git_common.cpp
-
145common/git/kicad_git_common.h
-
66common/git/kicad_git_errors.cpp
-
81common/git/kicad_git_errors.h
-
12common/project/project_local_settings.cpp
-
55common/settings/common_settings.cpp
-
7common/single_top.cpp
-
52eeschema/lib_field.cpp
-
4eeschema/lib_field.h
-
2eeschema/lib_item.cpp
-
31eeschema/lib_item.h
-
117eeschema/lib_pin.cpp
-
11eeschema/lib_pin.h
-
27eeschema/lib_shape.cpp
-
4eeschema/lib_shape.h
-
136eeschema/lib_symbol.cpp
-
13eeschema/lib_symbol.h
-
27eeschema/lib_text.cpp
-
4eeschema/lib_text.h
-
29eeschema/lib_textbox.cpp
-
4eeschema/lib_textbox.h
-
42eeschema/sch_bitmap.cpp
-
4eeschema/sch_bitmap.h
-
39eeschema/sch_bus_entry.cpp
-
4eeschema/sch_bus_entry.h
-
68eeschema/sch_field.cpp
-
4eeschema/sch_field.h
-
9eeschema/sch_item.h
-
45eeschema/sch_junction.cpp
-
4eeschema/sch_junction.h
-
63eeschema/sch_label.cpp
-
4eeschema/sch_label.h
-
63eeschema/sch_line.cpp
-
4eeschema/sch_line.h
-
10eeschema/sch_marker.h
-
31eeschema/sch_no_connect.cpp
-
4eeschema/sch_no_connect.h
-
37eeschema/sch_pin.cpp
-
4eeschema/sch_pin.h
-
24eeschema/sch_shape.cpp
-
4eeschema/sch_shape.h
-
49eeschema/sch_sheet.cpp
-
4eeschema/sch_sheet.h
-
10eeschema/sch_sheet_path.cpp
-
33eeschema/sch_sheet_pin.cpp
-
4eeschema/sch_sheet_pin.h
-
55eeschema/sch_symbol.cpp
-
4eeschema/sch_symbol.h
@ -0,0 +1,38 @@ |
|||
# SPDX-FileCopyrightText: 2014 Dan Leinir Turthra Jensen <admin@leinir.dk |
|||
# |
|||
# Redistribution and use is allowed according to the terms of the BSD license. |
|||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file. |
|||
|
|||
# - Try to find the libgit2 library |
|||
# Once done this will define |
|||
# |
|||
# LIBGIT2_FOUND - System has libgit2 |
|||
# LIBGIT2_INCLUDE_DIR - The libgit2 include directory |
|||
# LIBGIT2_LIBRARIES - The libraries needed to use libgit2 |
|||
# LIBGIT2_DEFINITIONS - Compiler switches required for using libgit2 |
|||
|
|||
|
|||
# use pkg-config to get the directories and then use these values |
|||
# in the FIND_PATH() and FIND_LIBRARY() calls |
|||
find_package(PkgConfig) |
|||
pkg_search_module(PC_LIBGIT2 libgit2) |
|||
|
|||
set(LIBGIT2_DEFINITIONS ${PC_LIBGIT2_CFLAGS_OTHER}) |
|||
|
|||
find_path(LIBGIT2_INCLUDE_DIR NAMES git2.h |
|||
HINTS |
|||
${PC_LIBGIT2_INCLUDEDIR} |
|||
${PC_LIBGIT2_INCLUDE_DIRS} |
|||
) |
|||
|
|||
find_library(LIBGIT2_LIBRARIES NAMES git2 |
|||
HINTS |
|||
${PC_LIBGIT2_LIBDIR} |
|||
${PC_LIBGIT2_LIBRARY_DIRS} |
|||
) |
|||
|
|||
|
|||
include(FindPackageHandleStandardArgs) |
|||
find_package_handle_standard_args(libgit2 DEFAULT_MSG LIBGIT2_LIBRARIES LIBGIT2_INCLUDE_DIR) |
|||
|
|||
mark_as_advanced(LIBGIT2_INCLUDE_DIR LIBGIT2_LIBRARIES) |
@ -0,0 +1,96 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "dialog_git_auth.h"
|
|||
|
|||
DIALOG_GIT_AUTH::DIALOG_GIT_AUTH(wxWindow* parent) |
|||
: DIALOG_SHIM(parent, wxID_ANY, _("Connection"), wxDefaultPosition, wxSize(400, 300)) |
|||
{ |
|||
CreateControls(); |
|||
Centre(); |
|||
} |
|||
|
|||
DIALOG_GIT_AUTH::~DIALOG_GIT_AUTH() |
|||
{ |
|||
} |
|||
|
|||
void DIALOG_GIT_AUTH::CreateControls() |
|||
{ |
|||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL); |
|||
this->SetSizer(mainSizer); |
|||
|
|||
m_NameTextCtrl = new wxTextCtrl(this, wxID_ANY); |
|||
m_UrlTextCtrl = new wxTextCtrl(this, wxID_ANY); |
|||
m_AuthChoice = new wxChoice(this, wxID_ANY); |
|||
m_AuthChoice->Append(_("Basic")); |
|||
m_AuthChoice->Append(_("SSH")); |
|||
m_UserNameTextCtrl = new wxTextCtrl(this, wxID_ANY); |
|||
m_PasswordTextCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD); |
|||
m_PublicKeyPicker = new wxFilePickerCtrl(this, wxID_ANY); |
|||
m_PublicKeyPicker->Hide(); |
|||
|
|||
m_TestButton = new wxButton(this, wxID_ANY, _("Test")); |
|||
m_OkButton = new wxButton(this, wxID_OK, _("OK")); |
|||
m_CancelButton = new wxButton(this, wxID_CANCEL, _("Cancel")); |
|||
|
|||
mainSizer->Add(new wxStaticText(this, wxID_ANY, _("Name")), 0, wxALL, 10); |
|||
mainSizer->Add(m_NameTextCtrl, 0, wxEXPAND | wxALL, 10); |
|||
mainSizer->Add(new wxStaticText(this, wxID_ANY, _("Url")), 0, wxALL, 10); |
|||
mainSizer->Add(m_UrlTextCtrl, 0, wxEXPAND | wxALL, 10); |
|||
mainSizer->Add(new wxStaticText(this, wxID_ANY, _("Authentication")), 0, wxALL, 10); |
|||
mainSizer->Add(m_AuthChoice, 0, wxEXPAND | wxALL, 10); |
|||
mainSizer->Add(new wxStaticText(this, wxID_ANY, _("User Name")), 0, wxALL, 10); |
|||
mainSizer->Add(m_UserNameTextCtrl, 0, wxEXPAND | wxALL, 10); |
|||
mainSizer->Add(new wxStaticText(this, wxID_ANY, _("Password")), 0, wxALL, 10); |
|||
mainSizer->Add(m_PasswordTextCtrl, 0, wxEXPAND | wxALL, 10); |
|||
mainSizer->Add(m_PublicKeyPicker, 0, wxEXPAND | wxALL, 10); |
|||
|
|||
|
|||
wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL); |
|||
buttonSizer->Add(m_TestButton, 1, wxALL, 10); |
|||
buttonSizer->Add(m_OkButton, 1, wxALL, 10); |
|||
buttonSizer->Add(m_CancelButton, 1, wxALL, 10); |
|||
mainSizer->Add(buttonSizer, 0, wxALIGN_RIGHT); |
|||
|
|||
mainSizer->Layout(); |
|||
|
|||
// Bind event for authentication method choice change
|
|||
m_AuthChoice->Bind(wxEVT_CHOICE, &DIALOG_GIT_AUTH::onAuthChoiceChanged, this); |
|||
m_TestButton->Bind(wxEVT_BUTTON, &DIALOG_GIT_AUTH::onTestClick, this ); |
|||
} |
|||
|
|||
void DIALOG_GIT_AUTH::onAuthChoiceChanged(wxCommandEvent& event) |
|||
{ |
|||
if (m_AuthChoice->GetStringSelection() == "SSH") |
|||
{ |
|||
m_PasswordTextCtrl->Hide(); |
|||
m_PublicKeyPicker->Show(); |
|||
} |
|||
else |
|||
{ |
|||
m_PasswordTextCtrl->Show(); |
|||
m_PublicKeyPicker->Hide(); |
|||
} |
|||
|
|||
Layout(); // Re-arrange the controls
|
|||
} |
@ -0,0 +1,59 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_REPOSITORY_DIALOG_H |
|||
#define GIT_REPOSITORY_DIALOG_H |
|||
|
|||
#include <wx/button.h> |
|||
#include <wx/choice.h> |
|||
#include <wx/filepicker.h> |
|||
#include <wx/textctrl.h> |
|||
#include <wx/wx.h> |
|||
|
|||
#include <dialog_shim.h> |
|||
|
|||
class DIALOG_GIT_AUTH : public DIALOG_SHIM |
|||
{ |
|||
public: |
|||
DIALOG_GIT_AUTH( wxWindow* parent ); |
|||
virtual ~DIALOG_GIT_AUTH(); |
|||
|
|||
private: |
|||
void CreateControls(); |
|||
void onAuthChoiceChanged( wxCommandEvent& event ); |
|||
void onTestClick( wxCommandEvent& aEvent ); |
|||
void onOKClick( wxCommandEvent& aEvent ); |
|||
void onCancelClick( wxCommandEvent& aEvent ); |
|||
|
|||
wxTextCtrl* m_NameTextCtrl; |
|||
wxTextCtrl* m_UrlTextCtrl; |
|||
wxChoice* m_AuthChoice; |
|||
wxTextCtrl* m_UserNameTextCtrl; |
|||
wxTextCtrl* m_PasswordTextCtrl; |
|||
wxButton* m_TestButton; |
|||
wxButton* m_OkButton; |
|||
wxButton* m_CancelButton; |
|||
wxFilePickerCtrl* m_PublicKeyPicker; |
|||
}; |
|||
|
|||
#endif // GIT_REPOSITORY_DIALOG_H |
@ -0,0 +1,204 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "dialog_git_commit.h"
|
|||
|
|||
#include <bitmaps/bitmaps_list.h>
|
|||
#include <bitmaps/bitmap_types.h>
|
|||
#include <git/kicad_git_common.h>
|
|||
|
|||
#include <wx/button.h>
|
|||
#include <wx/checkbox.h>
|
|||
#include <wx/listctrl.h>
|
|||
#include <wx/sizer.h>
|
|||
#include <wx/stattext.h>
|
|||
#include <wx/textctrl.h>
|
|||
|
|||
DIALOG_GIT_COMMIT::DIALOG_GIT_COMMIT( wxWindow* parent, git_repository* repo, |
|||
const wxString& defaultAuthorName, |
|||
const wxString& defaultAuthorEmail, |
|||
const std::map<wxString, int>& filesToCommit ) : |
|||
DIALOG_SHIM( parent, wxID_ANY, "Commit Changes" ) |
|||
{ |
|||
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); |
|||
|
|||
|
|||
// List Control for files to commit
|
|||
m_listCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, |
|||
wxLC_REPORT | wxLC_SINGLE_SEL ); |
|||
|
|||
// Set up columns
|
|||
m_listCtrl->EnableCheckBoxes(); |
|||
m_listCtrl->AppendColumn( "Filename" ); |
|||
m_listCtrl->AppendColumn( "Placeholder" ); |
|||
|
|||
// Set column widths
|
|||
m_listCtrl->SetColumnWidth(0, 200); |
|||
m_listCtrl->SetColumnWidth(1, 200); |
|||
|
|||
// Set up image list for icons
|
|||
wxImageList* imageList = new wxImageList( 16, 16, true, |
|||
static_cast<int>( KIGIT_COMMON::GIT_STATUS::GIT_STATUS_LAST ) ); |
|||
|
|||
imageList->Add( KiBitmap( BITMAPS::git_good_check ) ); // PLACEHOLDER
|
|||
imageList->Add( KiBitmap( BITMAPS::git_good_check ) ); // GIT_STATUS_CURRENT
|
|||
imageList->Add( KiBitmap( BITMAPS::git_modified ) ); // GIT_STATUS_MODIFIED
|
|||
imageList->Add( KiBitmap( BITMAPS::git_add ) ); // GIT_STATUS_ADDED
|
|||
imageList->Add( KiBitmap( BITMAPS::git_delete ) ); // GIT_STATUS_DELETED
|
|||
imageList->Add( KiBitmap( BITMAPS::git_out_of_date ) ); // GIT_STATUS_BEHIND
|
|||
imageList->Add( KiBitmap( BITMAPS::git_changed_ahead ) );// GIT_STATUS_AHEAD
|
|||
imageList->Add( KiBitmap( BITMAPS::git_conflict ) ); // GIT_STATUS_CONFLICTED
|
|||
|
|||
// Assign the image list to the list control
|
|||
m_listCtrl->SetImageList(imageList, wxIMAGE_LIST_SMALL); |
|||
|
|||
// Populate list control with items
|
|||
for ( auto& [filename, status] : filesToCommit ) |
|||
{ |
|||
int i = m_listCtrl->GetItemCount(); |
|||
m_listCtrl->InsertItem(i, filename ); |
|||
|
|||
if( status & ( GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_NEW ) ) |
|||
{ |
|||
m_listCtrl->SetItem( i, 1, "New" ); |
|||
m_listCtrl->SetItemImage(i, static_cast<int>( KIGIT_COMMON::GIT_STATUS::GIT_STATUS_ADDED ) ); |
|||
} |
|||
else if( status & ( GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED ) ) |
|||
{ |
|||
m_listCtrl->SetItem( i, 1, "Modified" ); |
|||
m_listCtrl->SetItemImage(i, static_cast<int>( KIGIT_COMMON::GIT_STATUS::GIT_STATUS_MODIFIED ) ); |
|||
} |
|||
else if( status & ( GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_DELETED ) ) |
|||
{ |
|||
m_listCtrl->SetItem( i, 1, "Deleted" ); |
|||
m_listCtrl->SetItemImage(i, static_cast<int>( KIGIT_COMMON::GIT_STATUS::GIT_STATUS_DELETED ) ); |
|||
} |
|||
else |
|||
{ |
|||
printf(" Unknown status: %d\n", status ); |
|||
} |
|||
} |
|||
|
|||
sizer->Add(m_listCtrl, 1, wxEXPAND | wxALL, 5); |
|||
|
|||
// Commit Message Text Control
|
|||
wxStaticText* commitMessageLabel = new wxStaticText( this, wxID_ANY, _( "Commit Message:" ) ); |
|||
m_commitMessageTextCtrl = |
|||
new wxTextCtrl( this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE ); |
|||
sizer->Add( commitMessageLabel, 0, wxALL, 5 ); |
|||
sizer->Add( m_commitMessageTextCtrl, 1, wxEXPAND | wxALL, 5 ); |
|||
|
|||
// Author Name and Email Text Control
|
|||
wxStaticText* authorLabel = new wxStaticText( this, wxID_ANY, _( "Author:" ) ); |
|||
wxString defaultAuthor = defaultAuthorName + " <" + defaultAuthorEmail + ">"; |
|||
m_authorTextCtrl = |
|||
new wxTextCtrl( this, wxID_ANY, defaultAuthor, wxDefaultPosition, wxDefaultSize, 0 ); |
|||
sizer->Add( authorLabel, 0, wxALL, 5 ); |
|||
sizer->Add( m_authorTextCtrl, 0, wxEXPAND | wxALL, 5 ); |
|||
|
|||
// OK and Cancel Buttons
|
|||
|
|||
wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer(); |
|||
|
|||
m_okButton = new wxButton( this, wxID_OK, _( "OK" ) ); |
|||
wxButton* cancelButton = new wxButton( this, wxID_CANCEL, _( "Cancel" ) ); |
|||
buttonSizer->Add( cancelButton, 0, wxALL, 5 ); |
|||
buttonSizer->Add( m_okButton, 0, wxALL, 5 ); |
|||
buttonSizer->Realize(); |
|||
|
|||
sizer->Add( buttonSizer, 0, wxALIGN_RIGHT | wxALL, 5 ); |
|||
|
|||
SetSizerAndFit( sizer ); |
|||
|
|||
SetupStandardButtons( { { wxID_OK, _( "C&ommit" ) } } ); |
|||
|
|||
// Bind events
|
|||
Bind( wxEVT_TEXT, &DIALOG_GIT_COMMIT::OnTextChanged, this, m_commitMessageTextCtrl->GetId() ); |
|||
|
|||
// Set the repository and defaults
|
|||
m_repo = repo; |
|||
m_defaultAuthorName = defaultAuthorName; |
|||
m_defaultAuthorEmail = defaultAuthorEmail; |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_COMMIT::OnTextChanged( wxCommandEvent& aEvent ) |
|||
{ |
|||
if( m_commitMessageTextCtrl->GetValue().IsEmpty() ) |
|||
{ |
|||
m_okButton->Disable(); |
|||
m_okButton->SetToolTip( _( "Commit message cannot be empty" ) ); |
|||
} |
|||
else |
|||
{ |
|||
m_okButton->Enable(); |
|||
m_okButton->SetToolTip( wxEmptyString ); |
|||
} |
|||
} |
|||
|
|||
|
|||
wxString DIALOG_GIT_COMMIT::GetCommitMessage() const |
|||
{ |
|||
return m_commitMessageTextCtrl->GetValue(); |
|||
} |
|||
|
|||
|
|||
wxString DIALOG_GIT_COMMIT::GetAuthorName() const |
|||
{ |
|||
wxString authorText = m_authorTextCtrl->GetValue(); |
|||
size_t pos = authorText.find( '<' ); |
|||
|
|||
if( pos != wxString::npos ) |
|||
return authorText.substr( 0, pos ).Trim(); |
|||
|
|||
return wxEmptyString; |
|||
} |
|||
|
|||
|
|||
wxString DIALOG_GIT_COMMIT::GetAuthorEmail() const |
|||
{ |
|||
wxString authorText = m_authorTextCtrl->GetValue(); |
|||
size_t startPos = authorText.find( '<' ); |
|||
size_t endPos = authorText.find( '>' ); |
|||
|
|||
if( startPos != wxString::npos && endPos != wxString::npos && startPos < endPos ) |
|||
return authorText.substr( startPos + 1, endPos - startPos - 1 ).Trim(); |
|||
|
|||
return wxEmptyString; |
|||
} |
|||
|
|||
|
|||
std::vector<wxString> DIALOG_GIT_COMMIT::GetSelectedFiles() const |
|||
{ |
|||
std::vector<wxString> selectedFiles; |
|||
|
|||
long item = -1; |
|||
while( ( item = m_listCtrl->GetNextItem( item, wxLIST_NEXT_ALL ) ) |
|||
!= -1 ) |
|||
{ |
|||
if( m_listCtrl->IsItemChecked( item ) ) |
|||
selectedFiles.push_back( m_listCtrl->GetItemText( item ) ); |
|||
} |
|||
|
|||
return selectedFiles; |
|||
} |
@ -0,0 +1,62 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef DIALOG_GIT_COMMIT_H |
|||
#define DIALOG_GIT_COMMIT_H |
|||
|
|||
#include <dialog_shim.h> |
|||
#include <git2.h> |
|||
|
|||
class wxCheckBox; |
|||
class wxListCtrl; |
|||
class DIALOG_GIT_COMMIT : public DIALOG_SHIM |
|||
{ |
|||
public: |
|||
DIALOG_GIT_COMMIT( wxWindow* parent, git_repository* repo, |
|||
const wxString& defaultAuthorName, |
|||
const wxString& defaultAuthorEmail, |
|||
const std::map<wxString, int>& filesToCommit ); |
|||
|
|||
wxString GetCommitMessage() const; |
|||
|
|||
wxString GetAuthorName() const; |
|||
|
|||
wxString GetAuthorEmail() const; |
|||
|
|||
std::vector<wxString> GetSelectedFiles() const; |
|||
|
|||
void OnTextChanged( wxCommandEvent& event ); |
|||
|
|||
private: |
|||
wxTextCtrl* m_commitMessageTextCtrl; |
|||
wxTextCtrl* m_authorTextCtrl; |
|||
wxListCtrl* m_listCtrl; |
|||
wxButton* m_okButton; |
|||
|
|||
git_repository* m_repo; |
|||
wxString m_defaultAuthorName; |
|||
wxString m_defaultAuthorEmail; |
|||
std::vector<wxString> m_filesToCommit; |
|||
}; |
|||
|
|||
#endif // DIALOG_GIT_COMMIT_H |
@ -0,0 +1,49 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
|
|||
#include <wx/progdlg.h>
|
|||
#include <wx/statusbr.h>
|
|||
|
|||
#include <dialog_shim.h>
|
|||
|
|||
class GIT_PROGRESS : public DIALOG_SHIM { |
|||
public: |
|||
GIT_PROGRESS(wxWindow* aParent, int aMaxValue1, int aMaxValue2); |
|||
~GIT_PROGRESS(); |
|||
|
|||
void SetStatusText(const wxString& aText); |
|||
bool UpdateProgressBar1(int aValue); |
|||
bool UpdateProgressBar2(int aValue); |
|||
|
|||
private: |
|||
void OnCancel(wxCommandEvent& aEvent); |
|||
|
|||
wxGauge* m_progBar1; |
|||
wxGauge* m_progBar2; |
|||
wxButton* m_cancelBtn; |
|||
wxStatusBar* m_statusBar; |
|||
bool m_cancelled; |
|||
|
|||
DECLARE_EVENT_TABLE() |
|||
}; |
@ -0,0 +1,448 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "dialog_git_repository.h"
|
|||
#include <confirm.h>
|
|||
|
|||
#include <git2.h>
|
|||
#include <gestfich.h>
|
|||
|
|||
#include <cerrno>
|
|||
#include <cstring>
|
|||
#include <fstream>
|
|||
#include <openssl/err.h>
|
|||
#include <openssl/evp.h>
|
|||
#include <openssl/pem.h>
|
|||
|
|||
#include <wx/clipbrd.h>
|
|||
#include <wx/msgdlg.h>
|
|||
#include <wx/regex.h>
|
|||
#include <wx/stdpaths.h>
|
|||
|
|||
|
|||
DIALOG_GIT_REPOSITORY::DIALOG_GIT_REPOSITORY( wxWindow* aParent, git_repository* aRepository, wxString aURL ) : |
|||
DIALOG_GIT_REPOSITORY_BASE( aParent ), m_repository( aRepository ), m_prevFile( wxEmptyString ), |
|||
m_tested( 0 ), m_failedTest( false ), m_testError( wxEmptyString ), m_tempRepo( false ), |
|||
m_repoType( KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_LOCAL ) |
|||
{ |
|||
m_txtName->SetFocus(); |
|||
|
|||
if( !m_repository ) |
|||
{ |
|||
// Make a temporary repository to test the connection
|
|||
m_tempRepo = true; |
|||
m_tempPath = wxFileName::CreateTempFileName( "kicadtestrepo" ); |
|||
|
|||
git_repository_init_options options = GIT_REPOSITORY_INIT_OPTIONS_INIT; |
|||
options.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_NO_REINIT; |
|||
git_repository_init_ext( &m_repository, m_tempPath.ToStdString().c_str(), &options ); |
|||
} |
|||
|
|||
if( !aURL.empty() ) |
|||
m_txtURL->SetValue( aURL ); |
|||
else |
|||
extractClipboardData(); |
|||
|
|||
if( !m_txtURL->GetValue().IsEmpty() ) |
|||
updateURLData(); |
|||
|
|||
SetupStandardButtons(); |
|||
updateAuthControls(); |
|||
} |
|||
|
|||
DIALOG_GIT_REPOSITORY::~DIALOG_GIT_REPOSITORY() |
|||
{ |
|||
if( m_tempRepo ) |
|||
{ |
|||
git_repository_free( m_repository ); |
|||
RmDirRecursive( m_tempPath ); |
|||
} |
|||
} |
|||
|
|||
|
|||
bool DIALOG_GIT_REPOSITORY::extractClipboardData() |
|||
{ |
|||
if( wxTheClipboard->Open() && wxTheClipboard->IsSupported( wxDF_TEXT ) ) |
|||
{ |
|||
wxString clipboardText; |
|||
wxTextDataObject textData; |
|||
|
|||
if( wxTheClipboard->GetData( textData ) && !( clipboardText = textData.GetText() ).empty() ) |
|||
{ |
|||
if( std::get<0>( isValidHTTPS( clipboardText ) ) |
|||
|| std::get<0>( isValidSSH( clipboardText ) ) ) |
|||
m_txtURL->SetValue( clipboardText ); |
|||
} |
|||
|
|||
wxTheClipboard->Close(); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::setDefaultSSHKey() |
|||
{ |
|||
wxFileName sshKey; |
|||
sshKey.SetPath( wxGetUserHome() ); |
|||
wxString retval; |
|||
|
|||
sshKey.AppendDir( ".ssh" ); |
|||
sshKey.SetFullName( "id_rsa" ); |
|||
|
|||
if( sshKey.FileExists() ) |
|||
{ |
|||
retval = sshKey.GetFullPath(); |
|||
} |
|||
else if( sshKey.SetFullName( "id_dsa" ); sshKey.FileExists() ) |
|||
{ |
|||
retval = sshKey.GetFullPath(); |
|||
} |
|||
else if( sshKey.SetFullName( "id_ecdsa" ); sshKey.FileExists() ) |
|||
{ |
|||
retval = sshKey.GetFullPath(); |
|||
} |
|||
|
|||
if( !retval.empty() ) |
|||
{ |
|||
m_fpSSHKey->SetFileName( retval ); |
|||
wxFileDirPickerEvent evt; |
|||
evt.SetPath( retval ); |
|||
OnFileUpdated( evt ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::OnUpdateUI( wxUpdateUIEvent& event ) |
|||
{ |
|||
// event.Enable( !m_txtName->GetValue().IsEmpty() && !m_txtURL->GetValue().IsEmpty() );
|
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::SetEncrypted( bool aEncrypted ) |
|||
{ |
|||
if( aEncrypted ) |
|||
{ |
|||
m_txtPassword->Enable(); |
|||
m_txtPassword->SetToolTip( _( "Enter the password for the SSH key" ) ); |
|||
} |
|||
else |
|||
{ |
|||
m_txtPassword->SetValue( wxEmptyString ); |
|||
m_txtPassword->SetToolTip( wxEmptyString ); |
|||
m_txtPassword->Disable(); |
|||
} |
|||
} |
|||
|
|||
std::tuple<bool,wxString,wxString,wxString> DIALOG_GIT_REPOSITORY::isValidHTTPS( const wxString& url ) |
|||
{ |
|||
wxRegEx regex( R"((https?:\/\/)(([^:]+)(:([^@]+))?@)?([^\/]+\/[^\s]+))" ); |
|||
|
|||
if( regex.Matches( url ) ) |
|||
{ |
|||
wxString username = regex.GetMatch( url, 3 ); |
|||
wxString password = regex.GetMatch( url, 5 ); |
|||
wxString repoAddress = regex.GetMatch( url, 1 ) + regex.GetMatch( url, 6 ); |
|||
return std::make_tuple( true, username, password, repoAddress ); |
|||
} |
|||
|
|||
return std::make_tuple( false, "", "", "" ); |
|||
} |
|||
|
|||
|
|||
std::tuple<bool,wxString, wxString> DIALOG_GIT_REPOSITORY::isValidSSH( const wxString& url ) |
|||
{ |
|||
wxRegEx regex( R"((?:ssh:\/\/)?([^@]+)@([^\/]+\/[^\s]+))" ); |
|||
|
|||
if( regex.Matches( url ) ) |
|||
{ |
|||
wxString username = regex.GetMatch( url, 1 ); |
|||
wxString repoAddress = regex.GetMatch( url, 2 ); |
|||
return std::make_tuple( true, username, repoAddress ); |
|||
} |
|||
|
|||
return std::make_tuple( false, "", "" ); |
|||
} |
|||
|
|||
|
|||
static wxString get_repo_name( wxString& aRepoAddr ) |
|||
{ |
|||
wxString retval; |
|||
size_t last_slash = aRepoAddr.find_last_of( '/' ); |
|||
bool ends_with_dot_git = aRepoAddr.EndsWith( ".git" ); |
|||
|
|||
if( ends_with_dot_git ) |
|||
retval = aRepoAddr.substr( last_slash + 1, aRepoAddr.size() - last_slash - 5 ); |
|||
else |
|||
retval = aRepoAddr.substr( last_slash + 1, aRepoAddr.size() - last_slash ); |
|||
|
|||
return retval; |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::OnLocationExit( wxFocusEvent& event ) |
|||
{ |
|||
updateURLData(); |
|||
updateAuthControls(); |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::updateURLData() |
|||
{ |
|||
wxString url = m_txtURL->GetValue(); |
|||
|
|||
if( url.IsEmpty() ) |
|||
return; |
|||
|
|||
if( url.Contains( "https://" ) || url.Contains( "http://" ) ) |
|||
{ |
|||
auto [valid, username, password, repoAddress] = isValidHTTPS( url ); |
|||
|
|||
if( valid ) |
|||
{ |
|||
m_ConnType->SetSelection( static_cast<int>( KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_HTTPS ) ); |
|||
SetUsername( username ); |
|||
SetPassword( password ); |
|||
m_txtURL->SetValue( repoAddress ); |
|||
|
|||
if( m_txtName->GetValue().IsEmpty() ) |
|||
m_txtName->SetValue( get_repo_name( repoAddress ) ); |
|||
|
|||
} |
|||
} |
|||
else if( url.Contains( "ssh://" ) || url.Contains( "git@" ) ) |
|||
{ |
|||
auto [valid, username, repoAddress] = isValidSSH( url ); |
|||
|
|||
if( valid ) |
|||
{ |
|||
m_ConnType->SetSelection( static_cast<int>( KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH ) ); |
|||
m_txtUsername->SetValue( username ); |
|||
m_txtURL->SetValue( repoAddress ); |
|||
|
|||
if( m_txtName->GetValue().IsEmpty() ) |
|||
m_txtName->SetValue( get_repo_name( repoAddress ) ); |
|||
|
|||
setDefaultSSHKey(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::OnTestClick( wxCommandEvent& event ) |
|||
{ |
|||
git_remote* remote = nullptr; |
|||
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; |
|||
|
|||
// We track if we have already tried to connect.
|
|||
// If we have, the server may come back to offer another connection
|
|||
// type, so we need to keep track of how many times we have tried.
|
|||
m_tested = 0; |
|||
|
|||
callbacks.credentials = []( git_cred** aOut, const char* aUrl, const char* aUsername, |
|||
unsigned int aAllowedTypes, void* aPayload ) -> int |
|||
{ |
|||
DIALOG_GIT_REPOSITORY* dialog = static_cast<DIALOG_GIT_REPOSITORY*>( aPayload ); |
|||
|
|||
if( dialog->GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_LOCAL ) |
|||
return GIT_PASSTHROUGH; |
|||
|
|||
if( aAllowedTypes & GIT_CREDENTIAL_USERNAME |
|||
&& !( dialog->GetTested() & GIT_CREDTYPE_USERNAME ) ) |
|||
{ |
|||
wxString username = dialog->GetUsername().Trim().Trim( false ); |
|||
git_cred_username_new( aOut, username.ToStdString().c_str() ); |
|||
dialog->GetTested() |= GIT_CREDTYPE_USERNAME; |
|||
} |
|||
else if( dialog->GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_HTTPS |
|||
&& ( aAllowedTypes & GIT_CREDENTIAL_USERPASS_PLAINTEXT ) |
|||
&& !( dialog->GetTested() & GIT_CREDTYPE_USERPASS_PLAINTEXT ) ) |
|||
{ |
|||
wxString username = dialog->GetUsername().Trim().Trim( false ); |
|||
wxString password = dialog->GetPassword().Trim().Trim( false ); |
|||
|
|||
git_cred_userpass_plaintext_new( aOut, username.ToStdString().c_str(), |
|||
password.ToStdString().c_str() ); |
|||
dialog->GetTested() |= GIT_CREDTYPE_USERPASS_PLAINTEXT; |
|||
} |
|||
else if( dialog->GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH |
|||
&& ( aAllowedTypes & GIT_CREDENTIAL_SSH_KEY ) |
|||
&& !( dialog->GetTested() & GIT_CREDTYPE_SSH_KEY ) ) |
|||
{ |
|||
// SSH key authentication
|
|||
wxString sshKey = dialog->GetRepoSSHPath(); |
|||
wxString sshPubKey = sshKey + ".pub"; |
|||
wxString username = dialog->GetUsername().Trim().Trim( false ); |
|||
wxString password = dialog->GetPassword().Trim().Trim( false ); |
|||
|
|||
git_cred_ssh_key_new( aOut, username.ToStdString().c_str(), |
|||
sshPubKey.ToStdString().c_str(), sshKey.ToStdString().c_str(), |
|||
password.ToStdString().c_str() ); |
|||
dialog->GetTested() |= GIT_CREDTYPE_SSH_KEY; |
|||
} |
|||
else |
|||
{ |
|||
return GIT_PASSTHROUGH; |
|||
} |
|||
|
|||
return GIT_OK; |
|||
}; |
|||
|
|||
callbacks.payload = this; |
|||
|
|||
git_remote_create_with_fetchspec( &remote, m_repository, "origin", m_txtURL->GetValue(), |
|||
"+refs/heads/*:refs/remotes/origin/*" ); |
|||
|
|||
if( git_remote_connect( remote, GIT_DIRECTION_FETCH, &callbacks, nullptr, nullptr ) != GIT_OK ) |
|||
SetTestResult( true, git_error_last()->message ); |
|||
else |
|||
SetTestResult( false, wxEmptyString ); |
|||
|
|||
git_remote_disconnect( remote ); |
|||
git_remote_free( remote ); |
|||
|
|||
auto dlg = wxMessageDialog( this, wxEmptyString, _( "Test connection" ), wxOK | wxICON_INFORMATION ); |
|||
|
|||
if( !m_failedTest ) |
|||
{ |
|||
dlg.SetMessage( _( "Connection successful" ) ); |
|||
} |
|||
else |
|||
{ |
|||
dlg.SetMessage( wxString::Format( _( "Could not connect to '%s' " ), m_txtURL->GetValue() ) ); |
|||
dlg.SetExtendedMessage( m_testError ); |
|||
} |
|||
|
|||
dlg.ShowModal(); |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::OnFileUpdated( wxFileDirPickerEvent& aEvent ) |
|||
{ |
|||
wxString file = aEvent.GetPath(); |
|||
|
|||
if( file.ends_with( ".pub" ) ) |
|||
file = file.Left( file.size() - 4 ); |
|||
|
|||
std::ifstream ifs( file.ToStdString() ); |
|||
|
|||
if( !ifs.good() || !ifs.is_open() ) |
|||
{ |
|||
DisplayErrorMessage( this, wxString::Format( _( "Could not open private key '%s'" ), file ), |
|||
wxString::Format( "%s: %d", std::strerror( errno ), errno ) ); |
|||
return; |
|||
} |
|||
|
|||
std::string line; |
|||
std::getline( ifs, line ); |
|||
|
|||
bool isValid = ( line.find( "PRIVATE KEY" ) != std::string::npos ); |
|||
bool isEncrypted = ( line.find( "ENCRYPTED" ) != std::string::npos ); |
|||
|
|||
if( !isValid ) |
|||
{ |
|||
DisplayErrorMessage( this, _( "Invalid SSH Key" ), _( "The selected file is not a valid SSH private key" ) ); |
|||
CallAfter( [this] { SetRepoSSHPath( m_prevFile ); } ); |
|||
return; |
|||
} |
|||
|
|||
if( isEncrypted ) |
|||
{ |
|||
m_txtPassword->Enable(); |
|||
m_txtPassword->SetToolTip( _( "Enter the password for the SSH key" ) ); |
|||
} |
|||
else |
|||
{ |
|||
m_txtPassword->SetValue( wxEmptyString ); |
|||
m_txtPassword->SetToolTip( wxEmptyString ); |
|||
m_txtPassword->Disable(); |
|||
} |
|||
|
|||
ifs.close(); |
|||
|
|||
std::ifstream pubIfs( file + ".pub" ); |
|||
|
|||
if( !pubIfs.good() || !pubIfs.is_open() ) |
|||
{ |
|||
DisplayErrorMessage( this, wxString::Format( _( "Could not open public key '%s'" ), file + ".pub" ), |
|||
wxString::Format( "%s: %d", std::strerror( errno ), errno ) ); |
|||
aEvent.SetPath( wxEmptyString ); |
|||
CallAfter( [this] { SetRepoSSHPath( m_prevFile ); } ); |
|||
return; |
|||
} |
|||
|
|||
m_prevFile = file; |
|||
pubIfs.close(); |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::OnOKClick( wxCommandEvent& event ) |
|||
{ |
|||
// Save the repository details
|
|||
|
|||
if( m_txtName->GetValue().IsEmpty() ) |
|||
{ |
|||
DisplayErrorMessage( this, _( "Missing information" ), _( "Please enter a name for the repository" ) ); |
|||
return; |
|||
} |
|||
|
|||
if( m_txtURL->GetValue().IsEmpty() ) |
|||
{ |
|||
DisplayErrorMessage( this, _( "Missing information" ), _( "Please enter a URL for the repository" ) ); |
|||
return; |
|||
} |
|||
|
|||
EndModal( wxID_OK ); |
|||
} |
|||
|
|||
void DIALOG_GIT_REPOSITORY::updateAuthControls() |
|||
{ |
|||
if( m_ConnType->GetSelection() == static_cast<int>( KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_LOCAL ) ) |
|||
{ |
|||
m_panelAuth->Show( false ); |
|||
} |
|||
else |
|||
{ |
|||
m_panelAuth->Show( true ); |
|||
|
|||
if( m_ConnType->GetSelection() == static_cast<int>( KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH ) ) |
|||
{ |
|||
m_fpSSHKey->Show( true ); |
|||
m_labelSSH->Show( true ); |
|||
m_labelPass1->SetLabel( _( "SSH Key Password" ) ); |
|||
} |
|||
else |
|||
{ |
|||
m_fpSSHKey->Show( false ); |
|||
m_labelSSH->Show( false ); |
|||
m_labelPass1->SetLabel( _( "Password" ) ); |
|||
setDefaultSSHKey(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_REPOSITORY::OnSelectConnType( wxCommandEvent& event ) |
|||
{ |
|||
updateAuthControls(); |
|||
} |
@ -0,0 +1,124 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef DIALOG_GIT_REPOSITORY_H_ |
|||
#define DIALOG_GIT_REPOSITORY_H_ |
|||
|
|||
#include "dialog_git_repository_base.h" |
|||
|
|||
#include <git/kicad_git_common.h> |
|||
#include <git2.h> |
|||
|
|||
class DIALOG_GIT_REPOSITORY : public DIALOG_GIT_REPOSITORY_BASE |
|||
{ |
|||
public: |
|||
DIALOG_GIT_REPOSITORY( wxWindow* aParent, git_repository* aRepository, wxString aURL = wxEmptyString ); |
|||
~DIALOG_GIT_REPOSITORY() override; |
|||
|
|||
void SetTestResult( bool aFailed, const wxString& aError ) |
|||
{ |
|||
m_failedTest = aFailed; |
|||
m_testError = aError; |
|||
} |
|||
|
|||
void SetRepoType( KIGIT_COMMON::GIT_CONN_TYPE aType ) |
|||
{ |
|||
m_ConnType->SetSelection( static_cast<int>( aType ) ); |
|||
updateAuthControls(); |
|||
} |
|||
|
|||
KIGIT_COMMON::GIT_CONN_TYPE GetRepoType() const { return static_cast<KIGIT_COMMON::GIT_CONN_TYPE>( m_ConnType->GetSelection() ); } |
|||
|
|||
void SetRepoName( const wxString& aName ) { m_txtName->SetValue( aName ); } |
|||
wxString GetRepoName() const { return m_txtName->GetValue(); } |
|||
|
|||
void SetRepoURL( const wxString& aURL ) { m_txtURL->SetValue( aURL ); } |
|||
wxString GetRepoURL() const { return m_txtURL->GetValue(); } |
|||
|
|||
/** |
|||
* @brief Get the Bare Repo U R L object |
|||
* |
|||
* @return wxString without the protocol |
|||
*/ |
|||
wxString GetBareRepoURL() const |
|||
{ |
|||
wxString url = m_txtURL->GetValue(); |
|||
|
|||
if( url.StartsWith( "https://" ) ) |
|||
url = url.Mid( 8 ); |
|||
else if( url.StartsWith( "http://" ) ) |
|||
url = url.Mid( 7 ); |
|||
else if( url.StartsWith( "ssh://" ) ) |
|||
url = url.Mid( 6 ); |
|||
|
|||
return url; |
|||
} |
|||
|
|||
void SetUsername( const wxString& aUsername ) { m_txtUsername->SetValue( aUsername ); } |
|||
wxString GetUsername() const { return m_txtUsername->GetValue(); } |
|||
|
|||
void SetPassword( const wxString& aPassword ) { m_txtPassword->SetValue( aPassword ); } |
|||
wxString GetPassword() const { return m_txtPassword->GetValue(); } |
|||
|
|||
void SetRepoSSHPath( const wxString& aPath ) { m_fpSSHKey->SetFileName( aPath ); m_prevFile = aPath; } |
|||
wxString GetRepoSSHPath() const { return m_fpSSHKey->GetFileName().GetFullPath(); } |
|||
|
|||
unsigned& GetTested() { return m_tested; } |
|||
|
|||
void SetEncrypted( bool aEncrypted = true ); |
|||
|
|||
private: |
|||
void OnUpdateUI( wxUpdateUIEvent& event ) override; |
|||
void OnLocationExit( wxFocusEvent& event ) override; |
|||
void OnOKClick( wxCommandEvent& event ) override; |
|||
|
|||
void OnSelectConnType( wxCommandEvent& event ) override; |
|||
void OnTestClick( wxCommandEvent& event ) override; |
|||
|
|||
void OnFileUpdated( wxFileDirPickerEvent& event ) override; |
|||
|
|||
void setDefaultSSHKey(); |
|||
|
|||
void updateAuthControls(); |
|||
void updateURLData(); |
|||
bool extractClipboardData(); |
|||
|
|||
std::tuple<bool,wxString,wxString,wxString> isValidHTTPS( const wxString& url ); |
|||
std::tuple<bool,wxString, wxString> isValidSSH( const wxString& url ); |
|||
|
|||
git_repository* m_repository; |
|||
|
|||
wxString m_prevFile; |
|||
|
|||
unsigned m_tested; |
|||
bool m_failedTest; |
|||
wxString m_testError; |
|||
|
|||
bool m_tempRepo; |
|||
wxString m_tempPath; |
|||
|
|||
KIGIT_COMMON::GIT_CONN_TYPE m_repoType; |
|||
|
|||
}; |
|||
|
|||
#endif /* DIALOG_GIT_REPOSITORY_H_ */ |
@ -0,0 +1,172 @@ |
|||
///////////////////////////////////////////////////////////////////////////
|
|||
// C++ code generated with wxFormBuilder (version 3.10.1-254-gc2ef7767)
|
|||
// http://www.wxformbuilder.org/
|
|||
//
|
|||
// PLEASE DO *NOT* EDIT THIS FILE!
|
|||
///////////////////////////////////////////////////////////////////////////
|
|||
|
|||
#include "dialog_git_repository_base.h"
|
|||
|
|||
///////////////////////////////////////////////////////////////////////////
|
|||
|
|||
DIALOG_GIT_REPOSITORY_BASE::DIALOG_GIT_REPOSITORY_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) |
|||
{ |
|||
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); |
|||
|
|||
wxBoxSizer* bSizerMain; |
|||
bSizerMain = new wxBoxSizer( wxVERTICAL ); |
|||
|
|||
m_staticText1 = new wxStaticText( this, wxID_ANY, _("Connection"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_staticText1->Wrap( -1 ); |
|||
bSizerMain->Add( m_staticText1, 0, wxLEFT|wxTOP, 10 ); |
|||
|
|||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); |
|||
bSizerMain->Add( m_staticline1, 0, wxEXPAND|wxTOP, 5 ); |
|||
|
|||
wxFlexGridSizer* fgSizer2; |
|||
fgSizer2 = new wxFlexGridSizer( 0, 2, 0, 0 ); |
|||
fgSizer2->AddGrowableCol( 1 ); |
|||
fgSizer2->SetFlexibleDirection( wxBOTH ); |
|||
fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); |
|||
|
|||
m_staticText3 = new wxStaticText( this, wxID_ANY, _("Name"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_staticText3->Wrap( -1 ); |
|||
fgSizer2->Add( m_staticText3, 0, wxALL, 5 ); |
|||
|
|||
m_txtName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); |
|||
fgSizer2->Add( m_txtName, 0, wxALL|wxEXPAND, 5 ); |
|||
|
|||
m_staticText4 = new wxStaticText( this, wxID_ANY, _("Location"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_staticText4->Wrap( -1 ); |
|||
fgSizer2->Add( m_staticText4, 0, wxALL, 5 ); |
|||
|
|||
m_txtURL = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); |
|||
fgSizer2->Add( m_txtURL, 0, wxALL|wxEXPAND, 5 ); |
|||
|
|||
m_staticText9 = new wxStaticText( this, wxID_ANY, _("Connection Type"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_staticText9->Wrap( -1 ); |
|||
fgSizer2->Add( m_staticText9, 0, wxALL, 5 ); |
|||
|
|||
wxBoxSizer* bSizer3; |
|||
bSizer3 = new wxBoxSizer( wxHORIZONTAL ); |
|||
|
|||
wxString m_ConnTypeChoices[] = { _("HTTPS"), _("SSH"), _("Local") }; |
|||
int m_ConnTypeNChoices = sizeof( m_ConnTypeChoices ) / sizeof( wxString ); |
|||
m_ConnType = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_ConnTypeNChoices, m_ConnTypeChoices, 0 ); |
|||
m_ConnType->SetSelection( 0 ); |
|||
bSizer3->Add( m_ConnType, 1, wxEXPAND|wxLEFT|wxRIGHT, 5 ); |
|||
|
|||
|
|||
bSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); |
|||
|
|||
|
|||
fgSizer2->Add( bSizer3, 1, wxEXPAND, 5 ); |
|||
|
|||
|
|||
bSizerMain->Add( fgSizer2, 1, wxEXPAND, 5 ); |
|||
|
|||
m_panelAuth = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); |
|||
wxBoxSizer* m_szAuth; |
|||
m_szAuth = new wxBoxSizer( wxVERTICAL ); |
|||
|
|||
|
|||
m_szAuth->Add( 0, 0, 1, wxEXPAND, 5 ); |
|||
|
|||
wxBoxSizer* bSizer11; |
|||
bSizer11 = new wxBoxSizer( wxHORIZONTAL ); |
|||
|
|||
m_staticText2 = new wxStaticText( m_panelAuth, wxID_ANY, _("Authentication"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_staticText2->Wrap( -1 ); |
|||
bSizer11->Add( m_staticText2, 0, wxLEFT|wxTOP, 10 ); |
|||
|
|||
|
|||
bSizer11->Add( 0, 0, 1, wxEXPAND, 5 ); |
|||
|
|||
|
|||
m_szAuth->Add( bSizer11, 0, wxEXPAND, 5 ); |
|||
|
|||
m_staticline2 = new wxStaticLine( m_panelAuth, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); |
|||
m_szAuth->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 ); |
|||
|
|||
wxFlexGridSizer* fgSshSizer; |
|||
fgSshSizer = new wxFlexGridSizer( 0, 2, 0, 0 ); |
|||
fgSshSizer->AddGrowableCol( 1 ); |
|||
fgSshSizer->SetFlexibleDirection( wxBOTH ); |
|||
fgSshSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); |
|||
|
|||
m_labelSSH = new wxStaticText( m_panelAuth, wxID_ANY, _("SSH Private Key"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_labelSSH->Wrap( -1 ); |
|||
fgSshSizer->Add( m_labelSSH, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxRESERVE_SPACE_EVEN_IF_HIDDEN, 5 ); |
|||
|
|||
wxBoxSizer* bSizer41; |
|||
bSizer41 = new wxBoxSizer( wxHORIZONTAL ); |
|||
|
|||
m_fpSSHKey = new wxFilePickerCtrl( m_panelAuth, wxID_ANY, wxEmptyString, _("Select SSH private key file"), _("*"), wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN ); |
|||
bSizer41->Add( m_fpSSHKey, 1, wxEXPAND|wxLEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN|wxRIGHT, 5 ); |
|||
|
|||
m_btnTest = new wxButton( m_panelAuth, wxID_ANY, _("Test"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
bSizer41->Add( m_btnTest, 0, wxLEFT|wxRIGHT, 5 ); |
|||
|
|||
|
|||
fgSshSizer->Add( bSizer41, 1, wxEXPAND, 5 ); |
|||
|
|||
m_staticText11 = new wxStaticText( m_panelAuth, wxID_ANY, _("Username"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_staticText11->Wrap( -1 ); |
|||
fgSshSizer->Add( m_staticText11, 0, wxALL, 5 ); |
|||
|
|||
m_txtUsername = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); |
|||
fgSshSizer->Add( m_txtUsername, 0, wxALL|wxEXPAND, 5 ); |
|||
|
|||
m_labelPass1 = new wxStaticText( m_panelAuth, wxID_ANY, _("SSH Key Password"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_labelPass1->Wrap( -1 ); |
|||
fgSshSizer->Add( m_labelPass1, 0, wxALL, 5 ); |
|||
|
|||
m_txtPassword = new wxTextCtrl( m_panelAuth, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); |
|||
fgSshSizer->Add( m_txtPassword, 0, wxALL|wxEXPAND, 5 ); |
|||
|
|||
|
|||
m_szAuth->Add( fgSshSizer, 1, wxEXPAND, 5 ); |
|||
|
|||
|
|||
m_panelAuth->SetSizer( m_szAuth ); |
|||
m_panelAuth->Layout(); |
|||
m_szAuth->Fit( m_panelAuth ); |
|||
bSizerMain->Add( m_panelAuth, 1, wxALL|wxEXPAND|wxRESERVE_SPACE_EVEN_IF_HIDDEN, 0 ); |
|||
|
|||
m_sdbSizer = new wxStdDialogButtonSizer(); |
|||
m_sdbSizerOK = new wxButton( this, wxID_OK ); |
|||
m_sdbSizer->AddButton( m_sdbSizerOK ); |
|||
m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); |
|||
m_sdbSizer->AddButton( m_sdbSizerCancel ); |
|||
m_sdbSizer->Realize(); |
|||
|
|||
bSizerMain->Add( m_sdbSizer, 0, wxALL|wxEXPAND, 5 ); |
|||
|
|||
|
|||
this->SetSizer( bSizerMain ); |
|||
this->Layout(); |
|||
|
|||
this->Centre( wxBOTH ); |
|||
|
|||
// Connect Events
|
|||
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnClose ) ); |
|||
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnUpdateUI ) ); |
|||
m_txtURL->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnLocationExit ), NULL, this ); |
|||
m_ConnType->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnSelectConnType ), NULL, this ); |
|||
m_fpSSHKey->Connect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnFileUpdated ), NULL, this ); |
|||
m_btnTest->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnTestClick ), NULL, this ); |
|||
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnOKClick ), NULL, this ); |
|||
} |
|||
|
|||
DIALOG_GIT_REPOSITORY_BASE::~DIALOG_GIT_REPOSITORY_BASE() |
|||
{ |
|||
// Disconnect Events
|
|||
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnClose ) ); |
|||
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnUpdateUI ) ); |
|||
m_txtURL->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnLocationExit ), NULL, this ); |
|||
m_ConnType->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnSelectConnType ), NULL, this ); |
|||
m_fpSSHKey->Disconnect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnFileUpdated ), NULL, this ); |
|||
m_btnTest->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnTestClick ), NULL, this ); |
|||
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GIT_REPOSITORY_BASE::OnOKClick ), NULL, this ); |
|||
|
|||
} |
1335
common/dialogs/git/dialog_git_repository_base.fbp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,82 @@ |
|||
/////////////////////////////////////////////////////////////////////////// |
|||
// C++ code generated with wxFormBuilder (version 3.10.1-254-gc2ef7767) |
|||
// http://www.wxformbuilder.org/ |
|||
// |
|||
// PLEASE DO *NOT* EDIT THIS FILE! |
|||
/////////////////////////////////////////////////////////////////////////// |
|||
|
|||
#pragma once |
|||
|
|||
#include <wx/artprov.h> |
|||
#include <wx/xrc/xmlres.h> |
|||
#include <wx/intl.h> |
|||
#include "dialog_shim.h" |
|||
#include <wx/string.h> |
|||
#include <wx/stattext.h> |
|||
#include <wx/gdicmn.h> |
|||
#include <wx/font.h> |
|||
#include <wx/colour.h> |
|||
#include <wx/settings.h> |
|||
#include <wx/statline.h> |
|||
#include <wx/textctrl.h> |
|||
#include <wx/choice.h> |
|||
#include <wx/sizer.h> |
|||
#include <wx/filepicker.h> |
|||
#include <wx/button.h> |
|||
#include <wx/bitmap.h> |
|||
#include <wx/image.h> |
|||
#include <wx/icon.h> |
|||
#include <wx/panel.h> |
|||
#include <wx/dialog.h> |
|||
|
|||
/////////////////////////////////////////////////////////////////////////// |
|||
|
|||
|
|||
/////////////////////////////////////////////////////////////////////////////// |
|||
/// Class DIALOG_GIT_REPOSITORY_BASE |
|||
/////////////////////////////////////////////////////////////////////////////// |
|||
class DIALOG_GIT_REPOSITORY_BASE : public DIALOG_SHIM |
|||
{ |
|||
private: |
|||
|
|||
protected: |
|||
wxStaticText* m_staticText1; |
|||
wxStaticLine* m_staticline1; |
|||
wxStaticText* m_staticText3; |
|||
wxTextCtrl* m_txtName; |
|||
wxStaticText* m_staticText4; |
|||
wxTextCtrl* m_txtURL; |
|||
wxStaticText* m_staticText9; |
|||
wxChoice* m_ConnType; |
|||
wxPanel* m_panelAuth; |
|||
wxStaticText* m_staticText2; |
|||
wxStaticLine* m_staticline2; |
|||
wxStaticText* m_labelSSH; |
|||
wxFilePickerCtrl* m_fpSSHKey; |
|||
wxButton* m_btnTest; |
|||
wxStaticText* m_staticText11; |
|||
wxTextCtrl* m_txtUsername; |
|||
wxStaticText* m_labelPass1; |
|||
wxTextCtrl* m_txtPassword; |
|||
wxStdDialogButtonSizer* m_sdbSizer; |
|||
wxButton* m_sdbSizerOK; |
|||
wxButton* m_sdbSizerCancel; |
|||
|
|||
// Virtual event handlers, override them in your derived class |
|||
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } |
|||
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); } |
|||
virtual void OnLocationExit( wxFocusEvent& event ) { event.Skip(); } |
|||
virtual void OnSelectConnType( wxCommandEvent& event ) { event.Skip(); } |
|||
virtual void OnFileUpdated( wxFileDirPickerEvent& event ) { event.Skip(); } |
|||
virtual void OnTestClick( wxCommandEvent& event ) { event.Skip(); } |
|||
virtual void OnOKClick( wxCommandEvent& event ) { event.Skip(); } |
|||
|
|||
|
|||
public: |
|||
|
|||
DIALOG_GIT_REPOSITORY_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Git Repository"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 682,598 ), long style = wxCAPTION|wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); |
|||
|
|||
~DIALOG_GIT_REPOSITORY_BASE(); |
|||
|
|||
}; |
|||
|
@ -0,0 +1,288 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
|
|||
#include "dialog_git_switch.h"
|
|||
|
|||
#include <wx/button.h>
|
|||
#include <wx/checkbox.h>
|
|||
#include <wx/listctrl.h>
|
|||
#include <wx/event.h>
|
|||
#include <wx/sizer.h>
|
|||
#include <wx/stattext.h>
|
|||
#include <wx/textctrl.h>
|
|||
|
|||
#include <git2.h>
|
|||
|
|||
|
|||
DIALOG_GIT_SWITCH::DIALOG_GIT_SWITCH( wxWindow* aParent, git_repository* aRepository ) : |
|||
DIALOG_SHIM( aParent, wxID_ANY, _( "Git Branch Switch" ), wxDefaultPosition, wxDefaultSize, |
|||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ), |
|||
m_timer( this ), m_repository( aRepository ) |
|||
{ |
|||
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); |
|||
|
|||
// Add explanation text
|
|||
wxStaticText* explanationText = |
|||
new wxStaticText( this, wxID_ANY, _( "Select or enter a branch name:" ) ); |
|||
sizer->Add( explanationText, 0, wxALL, 10 ); |
|||
|
|||
// Add branch list with three columns
|
|||
m_branchList = new wxListView( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, |
|||
wxLC_REPORT | wxLC_SINGLE_SEL ); |
|||
m_branchList->InsertColumn( 0, _( "Branch" ) ); |
|||
m_branchList->InsertColumn( 1, _( "Last Commit" ) ); |
|||
m_branchList->InsertColumn( 2, _( "Last Updated" ) ); |
|||
sizer->Add( m_branchList, 1, wxALL | wxEXPAND, 10 ); |
|||
|
|||
// Add branch name text box
|
|||
m_branchNameText = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, |
|||
wxDefaultSize, wxTE_PROCESS_ENTER ); |
|||
sizer->Add( m_branchNameText, 0, wxALL | wxEXPAND, 10 ); |
|||
|
|||
// Add buttons
|
|||
wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer(); |
|||
m_switchButton = new wxButton( this, wxID_OK, _( "Switch" ) ); |
|||
buttonSizer->AddButton( m_switchButton ); |
|||
m_switchButton->Disable(); |
|||
wxButton* cancelButton = new wxButton( this, wxID_CANCEL, _( "Cancel" ) ); |
|||
buttonSizer->AddButton( cancelButton ); |
|||
buttonSizer->Realize(); |
|||
sizer->Add( buttonSizer, 0, wxALIGN_RIGHT | wxALL, 10 ); |
|||
|
|||
// Bind events
|
|||
Bind( wxEVT_LIST_ITEM_SELECTED, &DIALOG_GIT_SWITCH::OnBranchListSelection, this, m_branchList->GetId() ); |
|||
Bind( wxEVT_LIST_ITEM_ACTIVATED, &DIALOG_GIT_SWITCH::OnBranchListDClick, this, m_branchList->GetId() ); |
|||
Bind( wxEVT_BUTTON, &DIALOG_GIT_SWITCH::OnSwitchButton, this, m_switchButton->GetId() ); |
|||
Bind( wxEVT_BUTTON, &DIALOG_GIT_SWITCH::OnCancelButton, this, cancelButton->GetId() ); |
|||
Bind( wxEVT_TEXT, &DIALOG_GIT_SWITCH::OnTextChanged, this, m_branchNameText->GetId() ); |
|||
Bind( wxEVT_TIMER, &DIALOG_GIT_SWITCH::OnTimer, this, m_timer.GetId() ); |
|||
|
|||
// Populate branch list
|
|||
PopulateBranchList(); |
|||
|
|||
// Set sizer for the dialog
|
|||
SetSizerAndFit( sizer ); |
|||
|
|||
finishDialogSettings(); |
|||
|
|||
m_existingBranch = false; |
|||
} |
|||
|
|||
DIALOG_GIT_SWITCH::~DIALOG_GIT_SWITCH() |
|||
{ |
|||
StopTimer(); |
|||
Unbind( wxEVT_TIMER, &DIALOG_GIT_SWITCH::OnTimer, this, m_timer.GetId() ); |
|||
} |
|||
|
|||
void DIALOG_GIT_SWITCH::PopulateBranchList() |
|||
{ |
|||
m_branchList->DeleteAllItems(); |
|||
|
|||
// Get the branches
|
|||
GetBranches(); |
|||
|
|||
// Populate the list
|
|||
for( auto& [ name, data ] : m_branches ) |
|||
{ |
|||
wxDateTime lastUpdated( data.lastUpdated ); |
|||
wxString lastUpdatedString = lastUpdated.Format(); |
|||
|
|||
long itemIndex = m_branchList->InsertItem( m_branchList->GetItemCount(), name ); |
|||
m_branchList->SetItem( itemIndex, 1, data.commitString ); |
|||
m_branchList->SetItem( itemIndex, 2, lastUpdatedString ); |
|||
} |
|||
|
|||
m_branchList->SetColumnWidth( 0, wxLIST_AUTOSIZE ); |
|||
m_branchList->SetColumnWidth( 1, wxLIST_AUTOSIZE ); |
|||
m_branchList->SetColumnWidth( 2, wxLIST_AUTOSIZE ); |
|||
|
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_SWITCH::OnBranchListDClick( wxListEvent& aEvent ) |
|||
{ |
|||
int selection = aEvent.GetIndex(); |
|||
|
|||
if( selection != wxNOT_FOUND ) |
|||
{ |
|||
wxString branchName = m_branchList->GetItemText( selection ); |
|||
m_branchNameText->SetValue( branchName ); |
|||
|
|||
if( branchName != m_currentBranch ) |
|||
EndModal( wxID_OK ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_SWITCH::OnBranchListSelection( wxListEvent& aEvent ) |
|||
{ |
|||
int selection = aEvent.GetIndex(); |
|||
|
|||
if( selection != wxNOT_FOUND ) |
|||
{ |
|||
wxString branchName = m_branchList->GetItemText( selection ); |
|||
m_branchNameText->SetValue( branchName ); |
|||
m_switchButton->SetLabel( _( "Switch" ) ); |
|||
m_switchButton->Enable( branchName != m_currentBranch ); |
|||
} |
|||
else |
|||
{ |
|||
// Deselect all elements in the list
|
|||
for( int ii = 0; ii < m_branchList->GetItemCount(); ++ii ) |
|||
m_branchList->SetItemState( ii, 0, 0 ); |
|||
} |
|||
} |
|||
|
|||
void DIALOG_GIT_SWITCH::OnSwitchButton(wxCommandEvent& aEvent) |
|||
{ |
|||
wxString branchName = m_branchNameText->GetValue(); |
|||
|
|||
// Check if the branch name exists
|
|||
bool branchExists = m_branches.count(branchName); |
|||
|
|||
if (branchExists) |
|||
{ |
|||
EndModal(wxID_OK); // Return Switch code
|
|||
} |
|||
else |
|||
{ |
|||
EndModal(wxID_ADD); // Return Add code
|
|||
} |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_SWITCH::OnCancelButton(wxCommandEvent& aEvent) |
|||
{ |
|||
EndModal(wxID_CANCEL); // Return Cancel code
|
|||
} |
|||
|
|||
|
|||
wxString DIALOG_GIT_SWITCH::GetBranchName() const |
|||
{ |
|||
return m_branchNameText->GetValue(); |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_SWITCH::StartTimer() |
|||
{ |
|||
m_timer.Start( 500, true ); |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_SWITCH::StopTimer() |
|||
{ |
|||
m_timer.Stop(); |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_SWITCH::OnTimer( wxTimerEvent& aEvt ) |
|||
{ |
|||
wxString branchName = m_branchNameText->GetValue(); |
|||
|
|||
if( branchName == m_lastEnteredText ) |
|||
return; |
|||
|
|||
m_lastEnteredText = branchName; |
|||
|
|||
// Check if the branch name exists
|
|||
bool branchExists = m_branches.count( branchName ); |
|||
|
|||
if( branchExists ) |
|||
{ |
|||
m_switchButton->SetLabel( _( "Switch" ) ); |
|||
m_switchButton->Enable( branchName != m_currentBranch ); |
|||
} |
|||
else |
|||
{ |
|||
m_switchButton->SetLabel( _( "Add" ) ); |
|||
m_switchButton->Enable(); |
|||
} |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_SWITCH::OnTextChanged( wxCommandEvent& aEvt ) |
|||
{ |
|||
StartTimer(); |
|||
} |
|||
|
|||
|
|||
void DIALOG_GIT_SWITCH::GetBranches() |
|||
{ |
|||
// Clear the branch list
|
|||
m_branches.clear(); |
|||
|
|||
git_branch_iterator* branchIterator = nullptr; |
|||
git_branch_t branchType; |
|||
|
|||
// Get Current Branch
|
|||
git_reference* currentBranchReference = nullptr; |
|||
git_repository_head( ¤tBranchReference, m_repository ); |
|||
|
|||
// Get the current branch name
|
|||
if( currentBranchReference ) |
|||
{ |
|||
m_currentBranch = git_reference_shorthand( currentBranchReference ); |
|||
git_reference_free( currentBranchReference ); |
|||
} |
|||
|
|||
// Initialize branch iterator
|
|||
git_branch_iterator_new( &branchIterator, m_repository, GIT_BRANCH_ALL ); |
|||
|
|||
// Iterate over local branches
|
|||
git_reference* branchReference = nullptr; |
|||
while( git_branch_next( &branchReference, &branchType, branchIterator ) == 0 ) |
|||
{ |
|||
// Get the branch OID
|
|||
const git_oid* branchOid = git_reference_target( branchReference ); |
|||
|
|||
// Skip this branch if it doesn't have an OID
|
|||
if( !branchOid ) |
|||
{ |
|||
git_reference_free( branchReference ); |
|||
continue; |
|||
} |
|||
|
|||
git_commit* commit = nullptr; |
|||
|
|||
if( git_commit_lookup( &commit, m_repository, branchOid ) ) |
|||
{ |
|||
// Skip this branch if it doesn't have a commit
|
|||
git_reference_free( branchReference ); |
|||
continue; |
|||
} |
|||
|
|||
// Retrieve commit details
|
|||
BranchData branchData; |
|||
branchData.commitString = git_commit_message( commit ); |
|||
branchData.lastUpdated = static_cast<time_t>( git_commit_time( commit ) ); |
|||
branchData.isRemote = branchType == GIT_BRANCH_REMOTE; |
|||
|
|||
m_branches[git_reference_shorthand( branchReference )] = branchData; |
|||
|
|||
git_commit_free( commit ); |
|||
git_reference_free( branchReference ); |
|||
} |
|||
|
|||
git_branch_iterator_free( branchIterator ); |
|||
} |
@ -0,0 +1,79 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
|
|||
#ifndef DIALOG_GIT_SWITCH_H |
|||
#define DIALOG_GIT_SWITCH_H |
|||
|
|||
#include <dialog_shim.h> |
|||
#include <git2.h> |
|||
|
|||
class wxButton; |
|||
class wxListView; |
|||
class wxTextCtrl; |
|||
class wxTimer; |
|||
class wxListEvent; |
|||
|
|||
struct BranchData |
|||
{ |
|||
wxString commitString; |
|||
time_t lastUpdated; |
|||
bool isRemote; |
|||
}; |
|||
|
|||
class DIALOG_GIT_SWITCH : public DIALOG_SHIM |
|||
{ |
|||
public: |
|||
DIALOG_GIT_SWITCH(wxWindow* aParent, git_repository* aRepository); |
|||
virtual ~DIALOG_GIT_SWITCH(); |
|||
|
|||
wxString GetBranchName() const; |
|||
|
|||
private: |
|||
void PopulateBranchList(); |
|||
void OnBranchListSelection(wxListEvent& event); |
|||
void OnBranchListDClick(wxListEvent& event); |
|||
void OnSwitchButton(wxCommandEvent& event); |
|||
void OnCancelButton(wxCommandEvent& event); |
|||
void OnTextChanged(wxCommandEvent& event); |
|||
void OnTimer(wxTimerEvent& event); |
|||
void GetBranches(); |
|||
|
|||
wxListView* m_branchList; |
|||
wxTextCtrl* m_branchNameText; |
|||
wxButton* m_switchButton; |
|||
wxTimer m_timer; |
|||
|
|||
wxString m_currentBranch; |
|||
|
|||
git_repository* m_repository; |
|||
wxString m_lastEnteredText; |
|||
bool m_existingBranch; |
|||
|
|||
std::map<wxString, BranchData> m_branches; |
|||
|
|||
void StartTimer(); |
|||
void StopTimer(); |
|||
}; |
|||
|
|||
#endif // DIALOG_GIT_SWITCH_H |
@ -0,0 +1,377 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include "panel_git_repos.h"
|
|||
|
|||
#include <bitmaps.h>
|
|||
#include <dialogs/git/dialog_git_repository.h>
|
|||
#include <kiplatform/secrets.h>
|
|||
#include <pgm_base.h>
|
|||
#include <settings/common_settings.h>
|
|||
#include <widgets/std_bitmap_button.h>
|
|||
#include <widgets/wx_grid.h>
|
|||
|
|||
#include <git2.h>
|
|||
#include <wx/bmpbuttn.h>
|
|||
#include <wx/button.h>
|
|||
#include <wx/checkbox.h>
|
|||
|
|||
|
|||
PANEL_GIT_REPOS::PANEL_GIT_REPOS( wxWindow* aParent ) : PANEL_GIT_REPOS_BASE( aParent) |
|||
{ |
|||
|
|||
m_btnAddRepo->SetBitmap( KiBitmap( BITMAPS::small_plus ) ); |
|||
m_btnEditRepo->SetBitmap( KiBitmap( BITMAPS::small_edit ) ); |
|||
m_btnDelete->SetBitmap( KiBitmap( BITMAPS::small_trash ) ); |
|||
|
|||
} |
|||
|
|||
PANEL_GIT_REPOS::~PANEL_GIT_REPOS() |
|||
{ |
|||
} |
|||
|
|||
|
|||
void PANEL_GIT_REPOS::ResetPanel() |
|||
{ |
|||
m_grid->ClearGrid(); |
|||
m_cbDefault->SetValue( true ); |
|||
m_author->SetValue( wxEmptyString ); |
|||
m_authorEmail->SetValue( wxEmptyString ); |
|||
} |
|||
|
|||
static std::pair<wxString, wxString> getDefaultAuthorEmail() |
|||
{ |
|||
wxString name; |
|||
wxString email; |
|||
git_config_entry* name_c = nullptr; |
|||
git_config_entry* email_c = nullptr; |
|||
|
|||
git_config* config = nullptr; |
|||
|
|||
if( git_config_open_default( &config ) != 0 ) |
|||
{ |
|||
printf( "Failed to open default Git config: %s\n", giterr_last()->message ); |
|||
return std::make_pair( name, email ); |
|||
} |
|||
|
|||
if( git_config_get_entry( &name_c, config, "user.name" ) != 0 ) |
|||
{ |
|||
printf( "Failed to get user.name from Git config: %s\n", giterr_last()->message ); |
|||
} |
|||
if( git_config_get_entry( &email_c, config, "user.email" ) != 0 ) |
|||
{ |
|||
printf( "Failed to get user.email from Git config: %s\n", giterr_last()->message ); |
|||
} |
|||
|
|||
if( name_c ) |
|||
name = name_c->value; |
|||
|
|||
if( email_c ) |
|||
email = email_c->value; |
|||
|
|||
git_config_entry_free( name_c ); |
|||
git_config_entry_free( email_c ); |
|||
git_config_free( config ); |
|||
|
|||
return std::make_pair( name, email ); |
|||
} |
|||
|
|||
bool PANEL_GIT_REPOS::TransferDataFromWindow() |
|||
{ |
|||
COMMON_SETTINGS* settings = Pgm().GetCommonSettings(); |
|||
auto& repos = settings->m_Git.repositories; |
|||
|
|||
repos.clear(); |
|||
|
|||
for( int row = 0; row < m_grid->GetNumberRows(); row++ ) |
|||
{ |
|||
COMMON_SETTINGS::GIT_REPOSITORY repo; |
|||
|
|||
repo.active = m_grid->GetCellValue( row, COL_ACTIVE ) == "1"; |
|||
repo.name = m_grid->GetCellValue( row, COL_NAME ); |
|||
repo.path = m_grid->GetCellValue( row, COL_PATH ); |
|||
repo.authType = m_grid->GetCellValue( row, COL_AUTH_TYPE ); |
|||
repo.username = m_grid->GetCellValue( row, COL_USERNAME ); |
|||
|
|||
KIPLATFORM::SECRETS::StoreSecret( repo.path, repo.username, m_grid->GetCellValue( row, COL_PASSWORD ) ); |
|||
repo.ssh_path = m_grid->GetCellValue( row, COL_SSH_PATH ); |
|||
repos.push_back( repo ); |
|||
} |
|||
|
|||
settings->m_Git.useDefaultAuthor = m_cbDefault->GetValue(); |
|||
settings->m_Git.authorName = m_author->GetValue(); |
|||
settings->m_Git.authorEmail = m_authorEmail->GetValue(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
static bool testRepositoryConnection( COMMON_SETTINGS::GIT_REPOSITORY& repository) |
|||
{ |
|||
git_libgit2_init(); |
|||
|
|||
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; |
|||
|
|||
typedef struct |
|||
{ |
|||
COMMON_SETTINGS::GIT_REPOSITORY* repo; |
|||
bool success; |
|||
} callbacksPayload; |
|||
|
|||
callbacksPayload cb_data( { &repository, true } ); // If we don't need authentication, then, we are successful
|
|||
callbacks.payload = &cb_data; |
|||
callbacks.credentials = [](git_cred** out, const char* url, const char* username, unsigned int allowed_types, void* payload) -> int { |
|||
|
|||
// If we are asking for credentials, then, we need authentication
|
|||
|
|||
callbacksPayload* data = static_cast<callbacksPayload*>(payload); |
|||
|
|||
data->success = false; |
|||
|
|||
if( allowed_types & GIT_CREDTYPE_USERNAME ) |
|||
{ |
|||
data->success = true; |
|||
} |
|||
else if( data->repo->authType == "ssh" && ( allowed_types & GIT_CREDTYPE_SSH_KEY ) ) |
|||
{ |
|||
wxString sshKeyPath = data->repo->ssh_path; |
|||
|
|||
// Check if the SSH key exists and is readable
|
|||
if( wxFileExists( sshKeyPath ) && wxFile::Access( sshKeyPath, wxFile::read ) ) |
|||
data->success = true; |
|||
} |
|||
else if( data->repo->authType == "password" ) |
|||
{ |
|||
data->success = ( allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT ); |
|||
} |
|||
|
|||
return 0; |
|||
}; |
|||
|
|||
// Create a temporary directory to initialize the Git repository
|
|||
wxString tempDirPath = wxFileName::CreateTempFileName(wxT("kigit_temp")); |
|||
wxMkDir(tempDirPath, wxS_DIR_DEFAULT ); |
|||
|
|||
// Initialize the Git repository
|
|||
git_repository* repo = nullptr; |
|||
int result = git_repository_init(&repo, tempDirPath.mb_str(wxConvUTF8), 0); |
|||
if (result != 0) { |
|||
git_repository_free(repo); |
|||
git_libgit2_shutdown(); |
|||
wxRmdir(tempDirPath); |
|||
return false; |
|||
} |
|||
|
|||
git_remote* remote = nullptr; |
|||
result = git_remote_create_anonymous(&remote, repo, tempDirPath.mb_str(wxConvUTF8)); |
|||
if (result != 0) { |
|||
git_remote_free(remote); |
|||
git_repository_free(repo); |
|||
git_libgit2_shutdown(); |
|||
wxRmdir(tempDirPath); |
|||
return false; |
|||
} |
|||
|
|||
// We don't really care about the result of this call, the authentication callback
|
|||
// will set the return values we need
|
|||
git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, nullptr, nullptr); |
|||
|
|||
git_remote_disconnect(remote); |
|||
git_remote_free(remote); |
|||
git_repository_free(repo); |
|||
|
|||
git_libgit2_shutdown(); |
|||
|
|||
// Clean up the temporary directory
|
|||
wxRmdir(tempDirPath); |
|||
|
|||
return cb_data.success; |
|||
} |
|||
|
|||
bool PANEL_GIT_REPOS::TransferDataToWindow() |
|||
{ |
|||
COMMON_SETTINGS* settings = Pgm().GetCommonSettings(); |
|||
|
|||
m_grid->ClearGrid(); |
|||
|
|||
for( COMMON_SETTINGS::GIT_REPOSITORY& repo : settings->m_Git.repositories ) |
|||
{ |
|||
if( repo.name.IsEmpty() || repo.path.IsEmpty() ) |
|||
continue; |
|||
|
|||
int row = m_grid->GetNumberRows(); |
|||
m_grid->AppendRows( 1 ); |
|||
|
|||
m_grid->SetCellRenderer( row, COL_ACTIVE, new wxGridCellBoolRenderer() ); |
|||
m_grid->SetCellEditor( row, COL_ACTIVE, new wxGridCellBoolEditor() ); |
|||
m_grid->SetCellValue( row, COL_ACTIVE, repo.active ? "1" : "0" ); |
|||
|
|||
m_grid->SetCellValue( row, COL_NAME, repo.name ); |
|||
m_grid->SetCellValue( row, COL_PATH, repo.path ); |
|||
m_grid->SetCellValue( row, COL_AUTH_TYPE, repo.authType ); |
|||
m_grid->SetCellValue( row, COL_USERNAME, repo.username ); |
|||
|
|||
wxString password; |
|||
KIPLATFORM::SECRETS::GetSecret( repo.path, repo.username, password ); |
|||
m_grid->SetCellValue( row, COL_PASSWORD, password ); |
|||
m_grid->SetCellValue( row, COL_SSH_PATH, repo.ssh_path ); |
|||
|
|||
if( repo.active ) |
|||
m_grid->SetCellValue( row, 3, testRepositoryConnection( repo ) ? "C" : "NC" ); |
|||
|
|||
} |
|||
|
|||
m_cbDefault->SetValue( settings->m_Git.useDefaultAuthor ); |
|||
|
|||
if( settings->m_Git.useDefaultAuthor ) |
|||
{ |
|||
auto defaultAuthor = getDefaultAuthorEmail(); |
|||
m_author->SetValue( defaultAuthor.first ); |
|||
m_authorEmail->SetValue( defaultAuthor.second ); |
|||
m_author->Disable(); |
|||
m_authorEmail->Disable(); |
|||
} |
|||
else |
|||
{ |
|||
m_author->SetValue( settings->m_Git.authorName ); |
|||
m_authorEmail->SetValue( settings->m_Git.authorEmail ); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
void PANEL_GIT_REPOS::onDefaultClick( wxCommandEvent& event ) |
|||
{ |
|||
m_author->Enable( !m_cbDefault->GetValue() ); |
|||
m_authorEmail->Enable( !m_cbDefault->GetValue() ); |
|||
m_authorLabel->Enable( !m_cbDefault->GetValue() ); |
|||
m_authorEmailLabel->Enable( !m_cbDefault->GetValue() ); |
|||
} |
|||
|
|||
|
|||
void PANEL_GIT_REPOS::onGridDClick( wxGridEvent& event ) |
|||
{ |
|||
if( m_grid->GetNumberRows() <= 0 ) |
|||
{ |
|||
wxCommandEvent evt; |
|||
onAddClick( evt ); |
|||
return; |
|||
} |
|||
|
|||
int row = event.GetRow(); |
|||
|
|||
if( row < 0 || row >= m_grid->GetNumberRows() ) |
|||
return; |
|||
|
|||
DIALOG_GIT_REPOSITORY dialog( this, nullptr ); |
|||
|
|||
dialog.SetRepoName( m_grid->GetCellValue( row, COL_NAME ) ); |
|||
dialog.SetRepoURL( m_grid->GetCellValue( row, COL_PATH ) ); |
|||
dialog.SetUsername( m_grid->GetCellValue( row, COL_USERNAME ) ); |
|||
dialog.SetRepoSSHPath( m_grid->GetCellValue( row, COL_SSH_PATH ) ); |
|||
dialog.SetPassword( m_grid->GetCellValue( row, COL_PASSWORD ) ); |
|||
|
|||
wxString type = m_grid->GetCellValue( row, COL_AUTH_TYPE ); |
|||
|
|||
if( type == "password" ) |
|||
dialog.SetRepoType( KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_HTTPS ); |
|||
else if( type == "ssh" ) |
|||
dialog.SetRepoType( KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH ); |
|||
else |
|||
dialog.SetRepoType( KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_LOCAL); |
|||
|
|||
if( dialog.ShowModal() == wxID_OK ) |
|||
{ |
|||
m_grid->SetCellValue( row, COL_NAME, dialog.GetRepoName() ); |
|||
m_grid->SetCellValue( row, COL_PATH, dialog.GetRepoURL() ); |
|||
m_grid->SetCellValue( row, COL_USERNAME, dialog.GetUsername() ); |
|||
m_grid->SetCellValue( row, COL_SSH_PATH, dialog.GetRepoSSHPath() ); |
|||
m_grid->SetCellValue( row, COL_PASSWORD, dialog.GetPassword() ); |
|||
|
|||
if( dialog.GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_HTTPS ) |
|||
{ |
|||
m_grid->SetCellValue( row, COL_AUTH_TYPE, "password" ); |
|||
} |
|||
else if( dialog.GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH ) |
|||
{ |
|||
m_grid->SetCellValue( row, COL_AUTH_TYPE, "ssh" ); |
|||
} |
|||
else |
|||
{ |
|||
m_grid->SetCellValue( row, COL_AUTH_TYPE, "none" ); |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
void PANEL_GIT_REPOS::onAddClick( wxCommandEvent& event ) |
|||
{ |
|||
|
|||
DIALOG_GIT_REPOSITORY dialog( m_parent, nullptr ); |
|||
|
|||
if( dialog.ShowModal() == wxID_OK ) |
|||
{ |
|||
int row = m_grid->GetNumberRows(); |
|||
m_grid->AppendRows( 1 ); |
|||
|
|||
m_grid->SetCellValue( row, COL_NAME, dialog.GetRepoName() ); |
|||
m_grid->SetCellValue( row, COL_PATH, dialog.GetRepoURL() ); |
|||
m_grid->SetCellValue( row, COL_USERNAME, dialog.GetUsername() ); |
|||
m_grid->SetCellValue( row, COL_SSH_PATH, dialog.GetRepoSSHPath() ); |
|||
m_grid->SetCellValue( row, COL_PASSWORD, dialog.GetPassword() ); |
|||
|
|||
if( dialog.GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_HTTPS ) |
|||
{ |
|||
m_grid->SetCellValue( row, COL_AUTH_TYPE, "password" ); |
|||
} |
|||
else if( dialog.GetRepoType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH ) |
|||
{ |
|||
m_grid->SetCellValue( row, COL_AUTH_TYPE, "ssh" ); |
|||
} |
|||
else |
|||
{ |
|||
m_grid->SetCellValue( row, COL_AUTH_TYPE, "none" ); |
|||
} |
|||
|
|||
m_grid->MakeCellVisible( row, 0 ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void PANEL_GIT_REPOS::onEditClick( wxCommandEvent& event ) |
|||
{ |
|||
wxGridEvent evt( m_grid->GetId(), wxEVT_GRID_CELL_LEFT_DCLICK, m_grid, |
|||
m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() ); |
|||
onGridDClick( evt ); |
|||
} |
|||
|
|||
|
|||
void PANEL_GIT_REPOS::onDeleteClick( wxCommandEvent& event ) |
|||
{ |
|||
if( !m_grid->CommitPendingChanges() || m_grid->GetNumberRows() <= 0 ) |
|||
return; |
|||
|
|||
int curRow = m_grid->GetGridCursorRow(); |
|||
|
|||
m_grid->DeleteRows( curRow ); |
|||
|
|||
curRow = std::max( 0, curRow - 1 ); |
|||
m_grid->MakeCellVisible( curRow, m_grid->GetGridCursorCol() ); |
|||
m_grid->SetGridCursor( curRow, m_grid->GetGridCursorCol() ); |
|||
} |
@ -0,0 +1,59 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
#ifndef PANEL_GIT_REPOS_H |
|||
#define PANEL_GIT_REPOS_H |
|||
|
|||
#include <git/panel_git_repos_base.h> |
|||
#include <widgets/wx_grid.h> |
|||
|
|||
class PANEL_GIT_REPOS : public PANEL_GIT_REPOS_BASE |
|||
{ |
|||
public: |
|||
PANEL_GIT_REPOS( wxWindow* parent ); |
|||
~PANEL_GIT_REPOS() override; |
|||
|
|||
void ResetPanel() override; |
|||
|
|||
bool TransferDataFromWindow() override; |
|||
bool TransferDataToWindow() override; |
|||
|
|||
enum COLS |
|||
{ |
|||
COL_ACTIVE = 0, |
|||
COL_NAME, |
|||
COL_PATH, |
|||
COL_STATUS, |
|||
COL_AUTH_TYPE, |
|||
COL_USERNAME, |
|||
COL_PASSWORD, |
|||
COL_SSH_KEY, |
|||
COL_SSH_PATH |
|||
}; |
|||
|
|||
private: |
|||
void onDefaultClick( wxCommandEvent& event ) override; |
|||
void onGridDClick( wxGridEvent& event ) override; |
|||
void onAddClick( wxCommandEvent& event ) override; |
|||
void onEditClick( wxCommandEvent& event ) override; |
|||
void onDeleteClick( wxCommandEvent& event ) override; |
|||
|
|||
}; |
|||
|
|||
#endif // PANEL_GIT_REPOS_H |
@ -0,0 +1,167 @@ |
|||
///////////////////////////////////////////////////////////////////////////
|
|||
// C++ code generated with wxFormBuilder (version 3.10.1-254-gc2ef7767)
|
|||
// http://www.wxformbuilder.org/
|
|||
//
|
|||
// PLEASE DO *NOT* EDIT THIS FILE!
|
|||
///////////////////////////////////////////////////////////////////////////
|
|||
|
|||
#include "widgets/std_bitmap_button.h"
|
|||
#include "widgets/wx_grid.h"
|
|||
|
|||
#include "panel_git_repos_base.h"
|
|||
|
|||
///////////////////////////////////////////////////////////////////////////
|
|||
|
|||
PANEL_GIT_REPOS_BASE::PANEL_GIT_REPOS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : RESETTABLE_PANEL( parent, id, pos, size, style, name ) |
|||
{ |
|||
wxBoxSizer* bPanelSizer; |
|||
bPanelSizer = new wxBoxSizer( wxHORIZONTAL ); |
|||
|
|||
wxBoxSizer* bLeftSizer; |
|||
bLeftSizer = new wxBoxSizer( wxVERTICAL ); |
|||
|
|||
m_staticText12 = new wxStaticText( this, wxID_ANY, _("Git Commit Data"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_staticText12->Wrap( -1 ); |
|||
bLeftSizer->Add( m_staticText12, 0, wxEXPAND|wxLEFT|wxTOP, 10 ); |
|||
|
|||
wxFlexGridSizer* fgSizer1; |
|||
fgSizer1 = new wxFlexGridSizer( 0, 2, 0, 0 ); |
|||
fgSizer1->AddGrowableCol( 1 ); |
|||
fgSizer1->SetFlexibleDirection( wxBOTH ); |
|||
fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); |
|||
|
|||
m_cbDefault = new wxCheckBox( this, wxID_ANY, _("Use default values"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_cbDefault->SetValue(true); |
|||
fgSizer1->Add( m_cbDefault, 0, wxALL, 5 ); |
|||
|
|||
|
|||
fgSizer1->Add( 0, 0, 0, wxEXPAND, 5 ); |
|||
|
|||
m_authorLabel = new wxStaticText( this, wxID_ANY, _("Author name:"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_authorLabel->Wrap( -1 ); |
|||
m_authorLabel->Enable( false ); |
|||
|
|||
fgSizer1->Add( m_authorLabel, 0, wxALL, 5 ); |
|||
|
|||
m_author = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_author->Enable( false ); |
|||
|
|||
fgSizer1->Add( m_author, 0, wxALL|wxEXPAND, 5 ); |
|||
|
|||
m_authorEmailLabel = new wxStaticText( this, wxID_ANY, _("Author e-mail:"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_authorEmailLabel->Wrap( -1 ); |
|||
m_authorEmailLabel->Enable( false ); |
|||
|
|||
fgSizer1->Add( m_authorEmailLabel, 0, wxALL, 5 ); |
|||
|
|||
m_authorEmail = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_authorEmail->Enable( false ); |
|||
|
|||
fgSizer1->Add( m_authorEmail, 0, wxALL|wxEXPAND, 5 ); |
|||
|
|||
|
|||
bLeftSizer->Add( fgSizer1, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxTOP, 13 ); |
|||
|
|||
m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); |
|||
bLeftSizer->Add( m_staticline3, 0, wxEXPAND|wxBOTTOM, 5 ); |
|||
|
|||
m_staticText20 = new wxStaticText( this, wxID_ANY, _("Git Repositories"), wxDefaultPosition, wxDefaultSize, 0 ); |
|||
m_staticText20->Wrap( -1 ); |
|||
bLeftSizer->Add( m_staticText20, 0, wxEXPAND|wxLEFT|wxRIGHT, 13 ); |
|||
|
|||
wxBoxSizer* bAntialiasingSizer; |
|||
bAntialiasingSizer = new wxBoxSizer( wxVERTICAL ); |
|||
|
|||
m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxSize( 820,200 ), 0 ); |
|||
|
|||
// Grid
|
|||
m_grid->CreateGrid( 0, 10 ); |
|||
m_grid->EnableEditing( false ); |
|||
m_grid->EnableGridLines( true ); |
|||
m_grid->EnableDragGridSize( false ); |
|||
m_grid->SetMargins( 0, 0 ); |
|||
|
|||
// Columns
|
|||
m_grid->SetColSize( 0, 60 ); |
|||
m_grid->SetColSize( 1, 200 ); |
|||
m_grid->SetColSize( 2, 500 ); |
|||
m_grid->SetColSize( 3, 60 ); |
|||
m_grid->SetColSize( 4, 0 ); |
|||
m_grid->SetColSize( 5, 0 ); |
|||
m_grid->SetColSize( 6, 0 ); |
|||
m_grid->SetColSize( 7, 0 ); |
|||
m_grid->SetColSize( 8, 0 ); |
|||
m_grid->SetColSize( 9, 0 ); |
|||
m_grid->EnableDragColMove( false ); |
|||
m_grid->EnableDragColSize( true ); |
|||
m_grid->SetColLabelValue( 0, _("Active") ); |
|||
m_grid->SetColLabelValue( 1, _("Name") ); |
|||
m_grid->SetColLabelValue( 2, _("Path") ); |
|||
m_grid->SetColLabelValue( 3, _("Status") ); |
|||
m_grid->SetColLabelSize( 22 ); |
|||
m_grid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); |
|||
|
|||
// Rows
|
|||
m_grid->EnableDragRowSize( true ); |
|||
m_grid->SetRowLabelSize( 0 ); |
|||
m_grid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER ); |
|||
|
|||
// Label Appearance
|
|||
|
|||
// Cell Defaults
|
|||
m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); |
|||
bAntialiasingSizer->Add( m_grid, 5, wxALL|wxEXPAND, 5 ); |
|||
|
|||
|
|||
bLeftSizer->Add( bAntialiasingSizer, 0, wxEXPAND|wxLEFT|wxTOP, 5 ); |
|||
|
|||
wxBoxSizer* bButtonsSizer; |
|||
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL ); |
|||
|
|||
m_btnAddRepo = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); |
|||
m_btnAddRepo->SetToolTip( _("Add new repository") ); |
|||
|
|||
bButtonsSizer->Add( m_btnAddRepo, 0, wxALL, 5 ); |
|||
|
|||
m_btnEditRepo = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); |
|||
m_btnEditRepo->SetToolTip( _("Edit repository properties") ); |
|||
|
|||
bButtonsSizer->Add( m_btnEditRepo, 0, wxALL, 5 ); |
|||
|
|||
|
|||
bButtonsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); |
|||
|
|||
m_btnDelete = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); |
|||
m_btnDelete->SetToolTip( _("Remove Git Repository") ); |
|||
|
|||
bButtonsSizer->Add( m_btnDelete, 0, wxBOTTOM|wxRIGHT|wxTOP, 5 ); |
|||
|
|||
|
|||
bLeftSizer->Add( bButtonsSizer, 1, wxALL|wxEXPAND, 5 ); |
|||
|
|||
|
|||
bPanelSizer->Add( bLeftSizer, 0, wxRIGHT, 20 ); |
|||
|
|||
|
|||
this->SetSizer( bPanelSizer ); |
|||
this->Layout(); |
|||
bPanelSizer->Fit( this ); |
|||
|
|||
// Connect Events
|
|||
m_cbDefault->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_GIT_REPOS_BASE::onDefaultClick ), NULL, this ); |
|||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( PANEL_GIT_REPOS_BASE::onGridDClick ), NULL, this ); |
|||
m_btnAddRepo->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_GIT_REPOS_BASE::onAddClick ), NULL, this ); |
|||
m_btnEditRepo->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_GIT_REPOS_BASE::onEditClick ), NULL, this ); |
|||
m_btnDelete->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_GIT_REPOS_BASE::onDeleteClick ), NULL, this ); |
|||
} |
|||
|
|||
PANEL_GIT_REPOS_BASE::~PANEL_GIT_REPOS_BASE() |
|||
{ |
|||
// Disconnect Events
|
|||
m_cbDefault->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_GIT_REPOS_BASE::onDefaultClick ), NULL, this ); |
|||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( PANEL_GIT_REPOS_BASE::onGridDClick ), NULL, this ); |
|||
m_btnAddRepo->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_GIT_REPOS_BASE::onAddClick ), NULL, this ); |
|||
m_btnEditRepo->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_GIT_REPOS_BASE::onEditClick ), NULL, this ); |
|||
m_btnDelete->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_GIT_REPOS_BASE::onDeleteClick ), NULL, this ); |
|||
|
|||
} |
@ -0,0 +1,73 @@ |
|||
/////////////////////////////////////////////////////////////////////////// |
|||
// C++ code generated with wxFormBuilder (version 3.10.1-254-gc2ef7767) |
|||
// http://www.wxformbuilder.org/ |
|||
// |
|||
// PLEASE DO *NOT* EDIT THIS FILE! |
|||
/////////////////////////////////////////////////////////////////////////// |
|||
|
|||
#pragma once |
|||
|
|||
#include <wx/artprov.h> |
|||
#include <wx/xrc/xmlres.h> |
|||
#include <wx/intl.h> |
|||
class STD_BITMAP_BUTTON; |
|||
class WX_GRID; |
|||
|
|||
#include "widgets/resettable_panel.h" |
|||
#include <wx/string.h> |
|||
#include <wx/stattext.h> |
|||
#include <wx/gdicmn.h> |
|||
#include <wx/font.h> |
|||
#include <wx/colour.h> |
|||
#include <wx/settings.h> |
|||
#include <wx/checkbox.h> |
|||
#include <wx/textctrl.h> |
|||
#include <wx/sizer.h> |
|||
#include <wx/statline.h> |
|||
#include <wx/grid.h> |
|||
#include <wx/bmpbuttn.h> |
|||
#include <wx/bitmap.h> |
|||
#include <wx/image.h> |
|||
#include <wx/icon.h> |
|||
#include <wx/button.h> |
|||
#include <wx/panel.h> |
|||
|
|||
/////////////////////////////////////////////////////////////////////////// |
|||
|
|||
/////////////////////////////////////////////////////////////////////////////// |
|||
/// Class PANEL_GIT_REPOS_BASE |
|||
/////////////////////////////////////////////////////////////////////////////// |
|||
class PANEL_GIT_REPOS_BASE : public RESETTABLE_PANEL |
|||
{ |
|||
private: |
|||
|
|||
protected: |
|||
wxStaticText* m_staticText12; |
|||
wxCheckBox* m_cbDefault; |
|||
wxStaticText* m_authorLabel; |
|||
wxTextCtrl* m_author; |
|||
wxStaticText* m_authorEmailLabel; |
|||
wxTextCtrl* m_authorEmail; |
|||
wxStaticLine* m_staticline3; |
|||
wxStaticText* m_staticText20; |
|||
WX_GRID* m_grid; |
|||
STD_BITMAP_BUTTON* m_btnAddRepo; |
|||
STD_BITMAP_BUTTON* m_btnEditRepo; |
|||
STD_BITMAP_BUTTON* m_btnDelete; |
|||
|
|||
// Virtual event handlers, override them in your derived class |
|||
virtual void onDefaultClick( wxCommandEvent& event ) { event.Skip(); } |
|||
virtual void onGridDClick( wxGridEvent& event ) { event.Skip(); } |
|||
virtual void onAddClick( wxCommandEvent& event ) { event.Skip(); } |
|||
virtual void onEditClick( wxCommandEvent& event ) { event.Skip(); } |
|||
virtual void onDeleteClick( wxCommandEvent& event ) { event.Skip(); } |
|||
|
|||
|
|||
public: |
|||
|
|||
PANEL_GIT_REPOS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); |
|||
|
|||
~PANEL_GIT_REPOS_BASE(); |
|||
|
|||
}; |
|||
|
@ -0,0 +1,953 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> |
|||
<wxFormBuilder_Project> |
|||
<FileVersion major="1" minor="16" /> |
|||
<object class="Project" expanded="1"> |
|||
<property name="class_decoration"></property> |
|||
<property name="code_generation">C++</property> |
|||
<property name="disconnect_events">1</property> |
|||
<property name="disconnect_mode">source_name</property> |
|||
<property name="disconnect_php_events">0</property> |
|||
<property name="disconnect_python_events">0</property> |
|||
<property name="embedded_files_path">res</property> |
|||
<property name="encoding">UTF-8</property> |
|||
<property name="event_generation">connect</property> |
|||
<property name="file">panel_git_repos_base</property> |
|||
<property name="first_id">1000</property> |
|||
<property name="help_provider">none</property> |
|||
<property name="image_path_wrapper_function_name"></property> |
|||
<property name="indent_with_spaces"></property> |
|||
<property name="internationalize">1</property> |
|||
<property name="name">PanelGitRepos</property> |
|||
<property name="namespace"></property> |
|||
<property name="path">.</property> |
|||
<property name="precompiled_header"></property> |
|||
<property name="relative_path">1</property> |
|||
<property name="skip_lua_events">1</property> |
|||
<property name="skip_php_events">1</property> |
|||
<property name="skip_python_events">1</property> |
|||
<property name="ui_table">UI</property> |
|||
<property name="use_array_enum">0</property> |
|||
<property name="use_enum">1</property> |
|||
<property name="use_microsoft_bom">0</property> |
|||
<object class="Panel" expanded="1"> |
|||
<property name="aui_managed">0</property> |
|||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> |
|||
<property name="bg"></property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="event_handler">impl_virtual</property> |
|||
<property name="fg"></property> |
|||
<property name="font"></property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">PANEL_GIT_REPOS_BASE</property> |
|||
<property name="pos"></property> |
|||
<property name="size">-1,-1</property> |
|||
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property> |
|||
<property name="tooltip"></property> |
|||
<property name="two_step_creation">0</property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style">wxTAB_TRAVERSAL</property> |
|||
<object class="wxBoxSizer" expanded="1"> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">bPanelSizer</property> |
|||
<property name="orient">wxHORIZONTAL</property> |
|||
<property name="permission">none</property> |
|||
<object class="sizeritem" expanded="1"> |
|||
<property name="border">20</property> |
|||
<property name="flag">wxRIGHT</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxBoxSizer" expanded="1"> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">bLeftSizer</property> |
|||
<property name="orient">wxVERTICAL</property> |
|||
<property name="permission">none</property> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">10</property> |
|||
<property name="flag">wxEXPAND|wxLEFT|wxTOP</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStaticText" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">Git Commit Data</property> |
|||
<property name="markup">0</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_staticText12</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<property name="wrap">-1</property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="1"> |
|||
<property name="border">13</property> |
|||
<property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxTOP</property> |
|||
<property name="proportion">1</property> |
|||
<object class="wxFlexGridSizer" expanded="1"> |
|||
<property name="cols">2</property> |
|||
<property name="flexible_direction">wxBOTH</property> |
|||
<property name="growablecols">1</property> |
|||
<property name="growablerows"></property> |
|||
<property name="hgap">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">fgSizer1</property> |
|||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property> |
|||
<property name="permission">none</property> |
|||
<property name="rows">0</property> |
|||
<property name="vgap">0</property> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxCheckBox" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="checked">1</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">Use default values</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_cbDefault</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="validator_data_type"></property> |
|||
<property name="validator_style">wxFILTER_NONE</property> |
|||
<property name="validator_type">wxDefaultValidator</property> |
|||
<property name="validator_variable"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<event name="OnCheckBox">onDefaultClick</event> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxEXPAND</property> |
|||
<property name="proportion">0</property> |
|||
<object class="spacer" expanded="0"> |
|||
<property name="height">0</property> |
|||
<property name="permission">protected</property> |
|||
<property name="width">0</property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStaticText" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">0</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">Author name:</property> |
|||
<property name="markup">0</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_authorLabel</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<property name="wrap">-1</property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL|wxEXPAND</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxTextCtrl" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">0</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="maxlength"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_author</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="validator_data_type"></property> |
|||
<property name="validator_style">wxFILTER_NONE</property> |
|||
<property name="validator_type">wxDefaultValidator</property> |
|||
<property name="validator_variable"></property> |
|||
<property name="value"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStaticText" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">0</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">Author e-mail:</property> |
|||
<property name="markup">0</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_authorEmailLabel</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<property name="wrap">-1</property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL|wxEXPAND</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxTextCtrl" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">0</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="maxlength"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_authorEmail</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="validator_data_type"></property> |
|||
<property name="validator_style">wxFILTER_NONE</property> |
|||
<property name="validator_type">wxDefaultValidator</property> |
|||
<property name="validator_variable"></property> |
|||
<property name="value"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxEXPAND|wxBOTTOM</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStaticLine" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_staticline3</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style">wxLI_HORIZONTAL</property> |
|||
<property name="subclass">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">13</property> |
|||
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxStaticText" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">Git Repositories</property> |
|||
<property name="markup">0</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_staticText20</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">; ; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<property name="wrap">-1</property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="1"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxEXPAND|wxLEFT|wxTOP</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxBoxSizer" expanded="1"> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">bAntialiasingSizer</property> |
|||
<property name="orient">wxVERTICAL</property> |
|||
<property name="permission">none</property> |
|||
<object class="sizeritem" expanded="0"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL|wxEXPAND</property> |
|||
<property name="proportion">5</property> |
|||
<object class="wxGrid" expanded="0"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="autosize_cols">0</property> |
|||
<property name="autosize_rows">0</property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="cell_bg"></property> |
|||
<property name="cell_font"></property> |
|||
<property name="cell_horiz_alignment">wxALIGN_LEFT</property> |
|||
<property name="cell_text"></property> |
|||
<property name="cell_vert_alignment">wxALIGN_TOP</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property> |
|||
<property name="col_label_size">22</property> |
|||
<property name="col_label_values">"Active" "Name" "Path" "Status"</property> |
|||
<property name="col_label_vert_alignment">wxALIGN_CENTER</property> |
|||
<property name="cols">10</property> |
|||
<property name="column_sizes">60,200,500,60,0,0,0,0,0,0</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="drag_col_move">0</property> |
|||
<property name="drag_col_size">1</property> |
|||
<property name="drag_grid_size">0</property> |
|||
<property name="drag_row_size">1</property> |
|||
<property name="editing">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="font"></property> |
|||
<property name="grid_line_color"></property> |
|||
<property name="grid_lines">1</property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label_bg"></property> |
|||
<property name="label_font"></property> |
|||
<property name="label_text"></property> |
|||
<property name="margin_height">0</property> |
|||
<property name="margin_width">0</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_grid</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="row_label_horiz_alignment">wxALIGN_CENTER</property> |
|||
<property name="row_label_size">0</property> |
|||
<property name="row_label_values"></property> |
|||
<property name="row_label_vert_alignment">wxALIGN_CENTER</property> |
|||
<property name="row_sizes"></property> |
|||
<property name="rows">0</property> |
|||
<property name="show">1</property> |
|||
<property name="size">820,200</property> |
|||
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<event name="OnGridCellLeftDClick">onGridDClick</event> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="1"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL|wxEXPAND</property> |
|||
<property name="proportion">1</property> |
|||
<object class="wxBoxSizer" expanded="1"> |
|||
<property name="minimum_size"></property> |
|||
<property name="name">bButtonsSizer</property> |
|||
<property name="orient">wxHORIZONTAL</property> |
|||
<property name="permission">none</property> |
|||
<object class="sizeritem" expanded="1"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxBitmapButton" expanded="1"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="auth_needed">0</property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="bitmap"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="current"></property> |
|||
<property name="default">0</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="disabled"></property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="focus"></property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">MyButton</property> |
|||
<property name="margins"></property> |
|||
<property name="markup">0</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_btnAddRepo</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="position"></property> |
|||
<property name="pressed"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip">Add new repository</property> |
|||
<property name="validator_data_type"></property> |
|||
<property name="validator_style">wxFILTER_NONE</property> |
|||
<property name="validator_type">wxDefaultValidator</property> |
|||
<property name="validator_variable"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<event name="OnButtonClick">onAddClick</event> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="1"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxALL</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxBitmapButton" expanded="1"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="auth_needed">0</property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="bitmap"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="current"></property> |
|||
<property name="default">0</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="disabled"></property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="focus"></property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">MyButton</property> |
|||
<property name="margins"></property> |
|||
<property name="markup">0</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_btnEditRepo</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="position"></property> |
|||
<property name="pressed"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip">Edit repository properties</property> |
|||
<property name="validator_data_type"></property> |
|||
<property name="validator_style">wxFILTER_NONE</property> |
|||
<property name="validator_type">wxDefaultValidator</property> |
|||
<property name="validator_variable"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<event name="OnButtonClick">onEditClick</event> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="1"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxEXPAND</property> |
|||
<property name="proportion">1</property> |
|||
<object class="spacer" expanded="1"> |
|||
<property name="height">0</property> |
|||
<property name="permission">protected</property> |
|||
<property name="width">0</property> |
|||
</object> |
|||
</object> |
|||
<object class="sizeritem" expanded="1"> |
|||
<property name="border">5</property> |
|||
<property name="flag">wxBOTTOM|wxRIGHT|wxTOP</property> |
|||
<property name="proportion">0</property> |
|||
<object class="wxBitmapButton" expanded="1"> |
|||
<property name="BottomDockable">1</property> |
|||
<property name="LeftDockable">1</property> |
|||
<property name="RightDockable">1</property> |
|||
<property name="TopDockable">1</property> |
|||
<property name="aui_layer"></property> |
|||
<property name="aui_name"></property> |
|||
<property name="aui_position"></property> |
|||
<property name="aui_row"></property> |
|||
<property name="auth_needed">0</property> |
|||
<property name="best_size"></property> |
|||
<property name="bg"></property> |
|||
<property name="bitmap"></property> |
|||
<property name="caption"></property> |
|||
<property name="caption_visible">1</property> |
|||
<property name="center_pane">0</property> |
|||
<property name="close_button">1</property> |
|||
<property name="context_help"></property> |
|||
<property name="context_menu">1</property> |
|||
<property name="current"></property> |
|||
<property name="default">0</property> |
|||
<property name="default_pane">0</property> |
|||
<property name="disabled"></property> |
|||
<property name="dock">Dock</property> |
|||
<property name="dock_fixed">0</property> |
|||
<property name="docking">Left</property> |
|||
<property name="drag_accept_files">0</property> |
|||
<property name="enabled">1</property> |
|||
<property name="fg"></property> |
|||
<property name="floatable">1</property> |
|||
<property name="focus"></property> |
|||
<property name="font"></property> |
|||
<property name="gripper">0</property> |
|||
<property name="hidden">0</property> |
|||
<property name="id">wxID_ANY</property> |
|||
<property name="label">MyButton</property> |
|||
<property name="margins"></property> |
|||
<property name="markup">0</property> |
|||
<property name="max_size"></property> |
|||
<property name="maximize_button">0</property> |
|||
<property name="maximum_size"></property> |
|||
<property name="min_size"></property> |
|||
<property name="minimize_button">0</property> |
|||
<property name="minimum_size"></property> |
|||
<property name="moveable">1</property> |
|||
<property name="name">m_btnDelete</property> |
|||
<property name="pane_border">1</property> |
|||
<property name="pane_position"></property> |
|||
<property name="pane_size"></property> |
|||
<property name="permission">protected</property> |
|||
<property name="pin_button">1</property> |
|||
<property name="pos"></property> |
|||
<property name="position"></property> |
|||
<property name="pressed"></property> |
|||
<property name="resize">Resizable</property> |
|||
<property name="show">1</property> |
|||
<property name="size"></property> |
|||
<property name="style"></property> |
|||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property> |
|||
<property name="toolbar_pane">0</property> |
|||
<property name="tooltip">Remove Git Repository</property> |
|||
<property name="validator_data_type"></property> |
|||
<property name="validator_style">wxFILTER_NONE</property> |
|||
<property name="validator_type">wxDefaultValidator</property> |
|||
<property name="validator_variable"></property> |
|||
<property name="window_extra_style"></property> |
|||
<property name="window_name"></property> |
|||
<property name="window_style"></property> |
|||
<event name="OnButtonClick">onDeleteClick</event> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</object> |
|||
</wxFormBuilder_Project> |
@ -0,0 +1,108 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "git_add_to_index_handler.h"
|
|||
|
|||
|
|||
#include <wx/string.h>
|
|||
#include <wx/log.h>
|
|||
|
|||
GIT_ADD_TO_INDEX_HANDLER::GIT_ADD_TO_INDEX_HANDLER( git_repository* aRepository ) |
|||
{ |
|||
m_repository = aRepository; |
|||
m_filesToAdd.clear(); |
|||
} |
|||
|
|||
GIT_ADD_TO_INDEX_HANDLER::~GIT_ADD_TO_INDEX_HANDLER() |
|||
{ |
|||
} |
|||
|
|||
|
|||
bool GIT_ADD_TO_INDEX_HANDLER::AddToIndex( const wxString& aFilePath ) |
|||
{ |
|||
// Test if file is currently in the index
|
|||
|
|||
git_index* index = nullptr; |
|||
size_t at_pos = 0; |
|||
|
|||
if( git_repository_index( &index, m_repository ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to get repository index" ); |
|||
return false; |
|||
} |
|||
|
|||
git_index_find( &at_pos, index, aFilePath.ToUTF8().data() ); |
|||
|
|||
if( at_pos >= 0) |
|||
{ |
|||
git_index_free( index ); |
|||
wxLogError( "%s already in index", aFilePath ); |
|||
return false; |
|||
} |
|||
|
|||
git_index_free( index ); |
|||
|
|||
// Add file to index if not already there
|
|||
m_filesToAdd.push_back( aFilePath ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
bool GIT_ADD_TO_INDEX_HANDLER::PerformAddToIndex() |
|||
{ |
|||
git_index* index = nullptr; |
|||
|
|||
m_filesFailedToAdd.clear(); |
|||
|
|||
if( git_repository_index( &index, m_repository ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to get repository index" ); |
|||
std::copy( m_filesToAdd.begin(), m_filesToAdd.end(), std::back_inserter( m_filesFailedToAdd ) ); |
|||
return false; |
|||
} |
|||
|
|||
for( auto& file : m_filesToAdd ) |
|||
{ |
|||
if( git_index_add_bypath( index, file.ToUTF8().data() ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to add %s to index", file ); |
|||
m_filesFailedToAdd.push_back( file ); |
|||
continue; |
|||
} |
|||
} |
|||
|
|||
|
|||
if( git_index_write( index ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to write index" ); |
|||
m_filesFailedToAdd.clear(); |
|||
std::copy( m_filesToAdd.begin(), m_filesToAdd.end(), std::back_inserter( m_filesFailedToAdd ) ); |
|||
git_index_free( index ); |
|||
return false; |
|||
} |
|||
|
|||
git_index_free( index ); |
|||
|
|||
return true; |
|||
} |
@ -0,0 +1,50 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_ADD_TO_INDEX_HANDLER_H_ |
|||
#define GIT_ADD_TO_INDEX_HANDLER_H_ |
|||
|
|||
#include <git2.h> |
|||
#include <vector> |
|||
|
|||
class wxString; |
|||
|
|||
class GIT_ADD_TO_INDEX_HANDLER |
|||
{ |
|||
public: |
|||
GIT_ADD_TO_INDEX_HANDLER( git_repository* aRepository ); |
|||
virtual ~GIT_ADD_TO_INDEX_HANDLER(); |
|||
|
|||
bool AddToIndex( const wxString& aFilePath ); |
|||
|
|||
bool PerformAddToIndex(); |
|||
|
|||
private: |
|||
|
|||
git_repository* m_repository; |
|||
|
|||
std::vector<wxString> m_filesToAdd; |
|||
std::vector<wxString> m_filesFailedToAdd; |
|||
}; |
|||
|
|||
#endif /* GIT_ADD_TO_INDEX_HANDLER_H_ */ |
@ -0,0 +1,82 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "git_clone_handler.h"
|
|||
|
|||
#include <git/kicad_git_common.h>
|
|||
|
|||
#include <git2.h>
|
|||
#include <wx/filename.h>
|
|||
|
|||
GIT_CLONE_HANDLER::GIT_CLONE_HANDLER() : KIGIT_COMMON( nullptr ) |
|||
{} |
|||
|
|||
GIT_CLONE_HANDLER::~GIT_CLONE_HANDLER() |
|||
{ |
|||
if( m_repo ) |
|||
git_repository_free( m_repo ); |
|||
} |
|||
|
|||
|
|||
bool GIT_CLONE_HANDLER::PerformClone() |
|||
{ |
|||
wxFileName clonePath( m_clonePath ); |
|||
|
|||
if( !clonePath.DirExists() ) |
|||
{ |
|||
if( !clonePath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) ) |
|||
{ |
|||
AddErrorString( wxString::Format( _( "Could not create directory '%s'" ), m_clonePath ) ); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
git_clone_options cloneOptions = GIT_CLONE_OPTIONS_INIT; |
|||
cloneOptions.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; |
|||
cloneOptions.checkout_opts.progress_cb = clone_progress_cb; |
|||
cloneOptions.checkout_opts.progress_payload = this; |
|||
cloneOptions.fetch_opts.callbacks.transfer_progress = transfer_progress_cb; |
|||
cloneOptions.fetch_opts.callbacks.credentials = credentials_cb; |
|||
cloneOptions.fetch_opts.callbacks.payload = this; |
|||
|
|||
m_testedTypes = 0; |
|||
|
|||
if( git_clone( &m_repo, m_URL.ToStdString().c_str(), m_clonePath.ToStdString().c_str(), &cloneOptions ) != 0 ) |
|||
{ |
|||
AddErrorString( wxString::Format( _( "Could not clone repository '%s'" ), m_URL ) ); |
|||
return false; |
|||
} |
|||
|
|||
if( m_progressReporter ) |
|||
m_progressReporter->Hide(); |
|||
|
|||
m_previousProgress = 0; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
void GIT_CLONE_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) |
|||
{ |
|||
ReportProgress( aCurrent, aTotal, aMessage ); |
|||
} |
@ -0,0 +1,56 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_CLONE_HANDLER_H_ |
|||
#define GIT_CLONE_HANDLER_H_ |
|||
|
|||
#include <git/kicad_git_common.h> |
|||
#include <git/git_progress.h> |
|||
class GIT_CLONE_HANDLER : public KIGIT_COMMON, public GIT_PROGRESS |
|||
{ |
|||
public: |
|||
GIT_CLONE_HANDLER(); |
|||
~GIT_CLONE_HANDLER(); |
|||
|
|||
bool PerformClone(); |
|||
|
|||
void SetURL( const wxString& aURL ) { m_URL = aURL; } |
|||
wxString GetURL() const { return m_URL; } |
|||
|
|||
void SetBranch( const wxString& aBranch ) { m_branch = aBranch; } |
|||
wxString GetBranch() const { return m_branch; } |
|||
|
|||
void SetClonePath( const wxString& aPath ) { m_clonePath = aPath; } |
|||
wxString GetClonePath() const { return m_clonePath; } |
|||
|
|||
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override; |
|||
|
|||
private: |
|||
|
|||
wxString m_URL; |
|||
wxString m_branch; |
|||
wxString m_clonePath; |
|||
}; |
|||
|
|||
|
|||
#endif |
@ -0,0 +1,49 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "git_commit_handler.h"
|
|||
|
|||
GIT_COMMIT_HANDLER::GIT_COMMIT_HANDLER( git_repository* aRepo ) : |
|||
KIGIT_COMMON( aRepo ) |
|||
{} |
|||
|
|||
GIT_COMMIT_HANDLER::~GIT_COMMIT_HANDLER() |
|||
{} |
|||
|
|||
|
|||
GIT_COMMIT_HANDLER::CommitResult GIT_COMMIT_HANDLER::PerformCommit( const std::vector<std::string>& aFilesToCommit ) |
|||
{ |
|||
|
|||
return CommitResult::Success; |
|||
} |
|||
|
|||
std::string GIT_COMMIT_HANDLER::GetErrorString() const |
|||
{ |
|||
return m_errorString; |
|||
} |
|||
|
|||
void GIT_COMMIT_HANDLER::AddErrorString( const std::string& aErrorString ) |
|||
{ |
|||
m_errorString += aErrorString; |
|||
} |
|||
|
@ -0,0 +1,58 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_COMMIT_HANDLER_H |
|||
#define GIT_COMMIT_HANDLER_H |
|||
|
|||
// Define a class to handle git commit operations |
|||
|
|||
#include <git/kicad_git_common.h> |
|||
#include <git2.h> |
|||
|
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
class GIT_COMMIT_HANDLER : public KIGIT_COMMON |
|||
{ |
|||
public: |
|||
GIT_COMMIT_HANDLER( git_repository* aRepo ); |
|||
virtual ~GIT_COMMIT_HANDLER(); |
|||
|
|||
enum class CommitResult |
|||
{ |
|||
Success, |
|||
Error, |
|||
Cancelled |
|||
}; |
|||
|
|||
CommitResult PerformCommit( const std::vector<std::string>& aFilesToCommit ); |
|||
|
|||
std::string GetErrorString() const; |
|||
|
|||
private: |
|||
void AddErrorString( const std::string& aErrorString ); |
|||
|
|||
std::string m_errorString; |
|||
}; |
|||
|
|||
#endif // GIT_COMMIT_HANDLER_H |
@ -0,0 +1,72 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_PROGRESS_H_ |
|||
#define GIT_PROGRESS_H_ |
|||
|
|||
#include <widgets/wx_progress_reporters.h> |
|||
|
|||
#include <memory> |
|||
|
|||
class GIT_PROGRESS |
|||
{ |
|||
public: |
|||
GIT_PROGRESS() : m_previousProgress( 0 ) |
|||
{ |
|||
m_progressReporter.reset(); |
|||
} |
|||
|
|||
|
|||
void SetProgressReporter( std::unique_ptr<WX_PROGRESS_REPORTER> aProgressReporter ) |
|||
{ |
|||
m_progressReporter = std::move( aProgressReporter ); |
|||
} |
|||
|
|||
void ReportProgress( int aCurrent, int aTotal, const wxString& aMessage ) |
|||
{ |
|||
|
|||
if( m_progressReporter ) |
|||
{ |
|||
if( aCurrent == m_previousProgress || aTotal == 0 ) |
|||
{ |
|||
m_progressReporter->Pulse( aMessage ); |
|||
} |
|||
else |
|||
{ |
|||
m_progressReporter->SetCurrentProgress( static_cast<double>( aCurrent ) / aTotal ); |
|||
m_progressReporter->Report( aMessage ); |
|||
} |
|||
|
|||
m_previousProgress = aCurrent; |
|||
m_progressReporter->KeepRefreshing(); |
|||
} |
|||
} |
|||
|
|||
|
|||
protected: |
|||
int m_previousProgress; |
|||
|
|||
std::unique_ptr<WX_PROGRESS_REPORTER> m_progressReporter; |
|||
}; |
|||
|
|||
#endif // GIT_PROGRESS_H__ |
@ -0,0 +1,343 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "git_pull_handler.h"
|
|||
#include <git/kicad_git_common.h>
|
|||
|
|||
#include <iostream>
|
|||
|
|||
GIT_PULL_HANDLER::GIT_PULL_HANDLER( git_repository* aRepo ) : KIGIT_COMMON( aRepo ) |
|||
{} |
|||
|
|||
GIT_PULL_HANDLER::~GIT_PULL_HANDLER() |
|||
{} |
|||
|
|||
|
|||
bool GIT_PULL_HANDLER::PerformFetch() |
|||
{ |
|||
// Fetch updates from remote repository
|
|||
git_remote* remote = nullptr; |
|||
|
|||
if( git_remote_lookup( &remote, m_repo, "origin" ) != 0 ) |
|||
{ |
|||
AddErrorString( wxString::Format( _( "Could not lookup remote '%s'" ), "origin" ).ToStdString() ); |
|||
return false; |
|||
} |
|||
|
|||
git_remote_callbacks remoteCallbacks = GIT_REMOTE_CALLBACKS_INIT; |
|||
remoteCallbacks.sideband_progress = progress_cb; |
|||
remoteCallbacks.transfer_progress = transfer_progress_cb; |
|||
remoteCallbacks.credentials = credentials_cb; |
|||
remoteCallbacks.payload = this; |
|||
|
|||
if( git_remote_connect( remote, GIT_DIRECTION_FETCH, &remoteCallbacks, nullptr, nullptr ) ) |
|||
{ |
|||
git_remote_free( remote ); |
|||
AddErrorString( wxString::Format( _( "Could not connect to remote '%s'" ), "origin" ).ToStdString() ); |
|||
return false; |
|||
} |
|||
|
|||
git_fetch_options fetchOptions = GIT_FETCH_OPTIONS_INIT; |
|||
fetchOptions.callbacks = remoteCallbacks; |
|||
|
|||
if( git_remote_fetch( remote, nullptr, &fetchOptions, nullptr ) ) |
|||
{ |
|||
git_remote_free( remote ); |
|||
AddErrorString( wxString::Format( _( "Could not fetch data from remote '%s'" ), "origin" ) ); |
|||
return false; |
|||
} |
|||
|
|||
git_remote_free( remote ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
PullResult GIT_PULL_HANDLER::PerformPull() |
|||
{ |
|||
PullResult result = PullResult::Success; |
|||
|
|||
if( !PerformFetch() ) |
|||
return PullResult::Error; |
|||
|
|||
git_oid pull_merge_oid = {}; |
|||
|
|||
if( git_repository_fetchhead_foreach( m_repo, fetchhead_foreach_cb, &pull_merge_oid ) ) |
|||
{ |
|||
AddErrorString( _( "Could not read 'FETCH_HEAD'" ) ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
git_annotated_commit* fetchhead_commit; |
|||
|
|||
if( git_annotated_commit_lookup( &fetchhead_commit, m_repo, &pull_merge_oid ) ) |
|||
{ |
|||
AddErrorString( _( "Could not lookup commit" ) ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
const git_annotated_commit* merge_commits[] = { fetchhead_commit }; |
|||
git_merge_analysis_t merge_analysis; |
|||
git_merge_preference_t merge_preference = GIT_MERGE_PREFERENCE_NONE; |
|||
|
|||
if( git_merge_analysis( &merge_analysis, &merge_preference, m_repo, merge_commits, 1 ) ) |
|||
{ |
|||
AddErrorString( _( "Could not analyze merge" ) ); |
|||
git_annotated_commit_free( fetchhead_commit ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
if( !( merge_analysis & GIT_MERGE_ANALYSIS_NORMAL ) ) |
|||
git_annotated_commit_free( fetchhead_commit ); |
|||
|
|||
if( merge_analysis & GIT_MERGE_ANALYSIS_UNBORN ) |
|||
{ |
|||
AddErrorString( _( "Invalid HEAD. Cannot merge." ) ); |
|||
return PullResult::MergeFailed; |
|||
} |
|||
|
|||
// Nothing to do if the repository is up to date
|
|||
if( merge_analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE ) |
|||
{ |
|||
git_repository_state_cleanup( m_repo ); |
|||
return PullResult::UpToDate; |
|||
} |
|||
|
|||
// Fast-forward is easy, just update the local reference
|
|||
if( merge_analysis & GIT_MERGE_ANALYSIS_FASTFORWARD ) |
|||
{ |
|||
return handleFastForward(); |
|||
} |
|||
|
|||
if( merge_analysis & GIT_MERGE_ANALYSIS_NORMAL ) |
|||
{ |
|||
PullResult ret = handleMerge( merge_commits, 1 ); |
|||
git_annotated_commit_free( fetchhead_commit ); |
|||
return ret; |
|||
} |
|||
|
|||
//TODO: handle merges when they need to be resolved
|
|||
|
|||
return result; |
|||
} |
|||
|
|||
const std::vector<std::pair<std::string, std::vector<CommitDetails>>>& GIT_PULL_HANDLER::GetFetchResults() const { |
|||
return m_fetchResults; |
|||
} |
|||
|
|||
std::string GIT_PULL_HANDLER::getFirstLineFromCommitMessage( const std::string& aMessage ) |
|||
{ |
|||
size_t firstLineEnd = aMessage.find_first_of( '\n' ); |
|||
|
|||
if( firstLineEnd != std::string::npos ) |
|||
return aMessage.substr( 0, firstLineEnd ); |
|||
|
|||
return aMessage; |
|||
} |
|||
|
|||
std::string GIT_PULL_HANDLER::getFormattedCommitDate( const git_time& aTime ) |
|||
{ |
|||
char dateBuffer[64]; |
|||
strftime( dateBuffer, sizeof( dateBuffer ), "%Y-%b-%d %H:%M:%S", gmtime( &aTime.time ) ); |
|||
return dateBuffer; |
|||
} |
|||
|
|||
|
|||
PullResult GIT_PULL_HANDLER::handleFastForward() |
|||
{ |
|||
// Update local references with fetched data
|
|||
git_reference* updatedRef = nullptr; |
|||
|
|||
if( git_repository_head( &updatedRef, m_repo ) ) |
|||
{ |
|||
AddErrorString( _( "Could not get repository head" ) ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
const char* updatedRefName = git_reference_name( updatedRef ); |
|||
git_reference_free( updatedRef ); |
|||
|
|||
git_oid updatedRefOid; |
|||
if( git_reference_name_to_id( &updatedRefOid, m_repo, updatedRefName ) ) |
|||
{ |
|||
AddErrorString( wxString::Format( _( "Could not get reference OID for reference '%s'" ), updatedRefName ) ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
git_checkout_options checkoutOptions = GIT_CHECKOUT_OPTIONS_INIT; |
|||
checkoutOptions.checkout_strategy = GIT_CHECKOUT_SAFE; |
|||
if( git_checkout_head( m_repo, &checkoutOptions ) ) |
|||
{ |
|||
AddErrorString( _( "Failed to perform checkout operation." ) ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
// Collect commit details for updated references
|
|||
git_revwalk* revWalker = nullptr; |
|||
git_revwalk_new( &revWalker, m_repo ); |
|||
git_revwalk_sorting( revWalker, GIT_SORT_TIME ); |
|||
git_revwalk_push_glob( revWalker, updatedRefName ); |
|||
|
|||
git_oid commitOid; |
|||
while( git_revwalk_next( &commitOid, revWalker ) == 0 ) |
|||
{ |
|||
git_commit* commit = nullptr; |
|||
|
|||
if( git_commit_lookup( &commit, m_repo, &commitOid ) ) |
|||
{ |
|||
AddErrorString( wxString::Format( _( "Could not lookup commit '{}'" ), git_oid_tostr_s( &commitOid ) ) ); |
|||
git_revwalk_free( revWalker ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
CommitDetails details; |
|||
details.m_sha = git_oid_tostr_s( &commitOid ); |
|||
details.m_firstLine = getFirstLineFromCommitMessage( git_commit_message( commit ) ); |
|||
details.m_author = git_commit_author( commit )->name; |
|||
details.m_date = getFormattedCommitDate( git_commit_author( commit )->when ); |
|||
|
|||
std::pair<std::string, std::vector<CommitDetails>>& branchCommits = |
|||
m_fetchResults.emplace_back(); |
|||
branchCommits.first = updatedRefName; |
|||
branchCommits.second.push_back( details ); |
|||
|
|||
//TODO: log these to the parent
|
|||
git_commit_free( commit ); |
|||
} |
|||
|
|||
git_revwalk_free( revWalker ); |
|||
|
|||
git_repository_state_cleanup( m_repo ); |
|||
return PullResult::FastForward; |
|||
} |
|||
|
|||
|
|||
PullResult GIT_PULL_HANDLER::handleMerge( const git_annotated_commit** aMergeHeads, |
|||
size_t aMergeHeadsCount ) |
|||
{ |
|||
git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; |
|||
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; |
|||
|
|||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; |
|||
|
|||
if( git_merge( m_repo, aMergeHeads, aMergeHeadsCount, &merge_opts, &checkout_opts ) ) |
|||
{ |
|||
AddErrorString( _( "Could not merge commits" ) ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
// Get the repository index
|
|||
git_index* index; |
|||
if( git_repository_index( &index, m_repo ) ) |
|||
{ |
|||
AddErrorString( _( "Could not get repository index" ) ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
// Check for conflicts
|
|||
git_index_conflict_iterator* conflicts; |
|||
if( git_index_conflict_iterator_new( &conflicts, index ) ) |
|||
{ |
|||
AddErrorString( _( "Could not get conflict iterator" ) ); |
|||
return PullResult::Error; |
|||
} |
|||
|
|||
const git_index_entry* ancestor; |
|||
const git_index_entry* our; |
|||
const git_index_entry* their; |
|||
std::vector<ConflictData> conflict_data; |
|||
|
|||
while( git_index_conflict_next( &ancestor, &our, &their, conflicts ) == 0 ) |
|||
{ |
|||
// Case 3: Both files have changed
|
|||
if( ancestor && our && their ) |
|||
{ |
|||
ConflictData conflict_datum; |
|||
conflict_datum.filename = our->path; |
|||
conflict_datum.our_oid = our->id; |
|||
conflict_datum.their_oid = their->id; |
|||
conflict_datum.our_commit_time = our->mtime.seconds; |
|||
conflict_datum.their_commit_time = their->mtime.seconds; |
|||
conflict_datum.our_status = _( "Changed" ); |
|||
conflict_datum.their_status = _( "Changed" ); |
|||
|
|||
conflict_data.push_back( conflict_datum ); |
|||
} |
|||
// Case 4: File added in both ours and theirs
|
|||
else if( !ancestor && our && their ) |
|||
{ |
|||
ConflictData conflict_datum; |
|||
conflict_datum.filename = our->path; |
|||
conflict_datum.our_oid = our->id; |
|||
conflict_datum.their_oid = their->id; |
|||
conflict_datum.our_commit_time = our->mtime.seconds; |
|||
conflict_datum.their_commit_time = their->mtime.seconds; |
|||
conflict_datum.our_status = _( "Added" ); |
|||
conflict_datum.their_status = _( "Added" ); |
|||
|
|||
conflict_data.push_back( conflict_datum ); |
|||
} |
|||
// Case 1: Remote file has changed or been added, local file has not
|
|||
else if( their && !our ) |
|||
{ |
|||
// Accept their changes
|
|||
git_index_add( index, their ); |
|||
} |
|||
// Case 2: Local file has changed or been added, remote file has not
|
|||
else if( our && !their ) |
|||
{ |
|||
// Accept our changes
|
|||
git_index_add( index, our ); |
|||
} |
|||
else |
|||
{ |
|||
ConflictData conflict_datum; |
|||
conflict_datum.filename = our->path; |
|||
conflict_datum.our_oid = our->id; |
|||
conflict_datum.their_oid = their->id; |
|||
conflict_datum.our_commit_time = our->mtime.seconds; |
|||
conflict_datum.their_commit_time = their->mtime.seconds; |
|||
conflict_datum.our_status = _( "Other" ); |
|||
conflict_datum.their_status = _( "Other" ); |
|||
|
|||
conflict_data.push_back( conflict_datum ); |
|||
} |
|||
} |
|||
|
|||
if( conflict_data.empty() ) |
|||
{ |
|||
git_index_conflict_cleanup( index ); |
|||
git_index_write( index ); |
|||
} |
|||
|
|||
git_index_conflict_iterator_free( conflicts ); |
|||
git_index_free( index ); |
|||
|
|||
return conflict_data.empty() ? PullResult::Success : PullResult::MergeFailed; |
|||
} |
|||
|
|||
|
|||
void GIT_PULL_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) |
|||
{ |
|||
ReportProgress( aCurrent, aTotal, aMessage ); |
|||
} |
@ -0,0 +1,100 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GITPULLHANDLER_HPP |
|||
#define GITPULLHANDLER_HPP |
|||
|
|||
#include <git2.h> |
|||
#include <functional> |
|||
#include <vector> |
|||
#include <string> |
|||
|
|||
#include "kicad_git_common.h" |
|||
|
|||
#include <git/git_progress.h> |
|||
|
|||
// Structure to store commit details |
|||
struct CommitDetails |
|||
{ |
|||
std::string m_sha; |
|||
std::string m_firstLine; |
|||
std::string m_author; |
|||
std::string m_date; |
|||
}; |
|||
|
|||
// Enum for result codes |
|||
enum class PullResult |
|||
{ |
|||
Success, |
|||
Error, |
|||
UpToDate, |
|||
FastForward, |
|||
MergeFailed |
|||
}; |
|||
|
|||
struct ConflictData |
|||
{ |
|||
std::string filename; |
|||
std::string our_status; |
|||
std::string their_status; |
|||
git_oid our_oid; |
|||
git_oid their_oid; |
|||
git_time_t our_commit_time; |
|||
git_time_t their_commit_time; |
|||
bool use_ours; // Flag indicating user's choice (true = ours, false = theirs) |
|||
}; |
|||
|
|||
|
|||
class GIT_PULL_HANDLER : public KIGIT_COMMON, public GIT_PROGRESS |
|||
{ |
|||
public: |
|||
GIT_PULL_HANDLER( git_repository* aRepo ); |
|||
~GIT_PULL_HANDLER(); |
|||
|
|||
PullResult PerformPull(); |
|||
|
|||
bool PerformFetch(); |
|||
|
|||
const std::vector<std::pair<std::string, std::vector<CommitDetails>>>& GetFetchResults() const; |
|||
|
|||
// Set the callback function for conflict resolution |
|||
void SetConflictCallback( |
|||
std::function<int( std::vector<ConflictData>& aConflicts )> aCallback ) |
|||
{ |
|||
m_conflictCallback = aCallback; |
|||
} |
|||
|
|||
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override; |
|||
|
|||
private: |
|||
std::string getFirstLineFromCommitMessage( const std::string& aMessage ); |
|||
std::string getFormattedCommitDate( const git_time& aTime );private: |
|||
|
|||
PullResult handleFastForward(); |
|||
PullResult handleMerge( const git_annotated_commit** aMergeHeads, size_t aMergeHeadsCount); |
|||
|
|||
std::vector<std::pair<std::string, std::vector<CommitDetails>>> m_fetchResults; |
|||
std::function<int( std::vector<ConflictData>& aConflicts )> m_conflictCallback; |
|||
}; |
|||
|
|||
#endif // GITPULLHANDLER_HPP |
@ -0,0 +1,79 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "git_push_handler.h"
|
|||
#include <git/kicad_git_common.h>
|
|||
|
|||
#include <iostream>
|
|||
|
|||
GIT_PUSH_HANDLER::GIT_PUSH_HANDLER( git_repository* aRepo ) : KIGIT_COMMON( aRepo ) |
|||
{} |
|||
|
|||
GIT_PUSH_HANDLER::~GIT_PUSH_HANDLER() |
|||
{} |
|||
|
|||
PushResult GIT_PUSH_HANDLER::PerformPush() |
|||
{ |
|||
PushResult result = PushResult::Success; |
|||
|
|||
// Fetch updates from remote repository
|
|||
git_remote* remote = nullptr; |
|||
|
|||
if( git_remote_lookup( &remote, m_repo, "origin" ) != 0 ) |
|||
{ |
|||
AddErrorString( _( "Could not lookup remote" ) ); |
|||
return PushResult::Error; |
|||
} |
|||
|
|||
git_remote_callbacks remoteCallbacks = GIT_REMOTE_CALLBACKS_INIT; |
|||
remoteCallbacks.sideband_progress = progress_cb; |
|||
remoteCallbacks.transfer_progress = transfer_progress_cb; |
|||
remoteCallbacks.update_tips = update_cb; |
|||
remoteCallbacks.push_transfer_progress = push_transfer_progress_cb; |
|||
remoteCallbacks.payload = this; |
|||
|
|||
if( git_remote_connect( remote, GIT_DIRECTION_PUSH, &remoteCallbacks, nullptr, nullptr ) ) |
|||
{ |
|||
git_remote_free( remote ); |
|||
AddErrorString( _( "Could not connect to remote" ) ); |
|||
return PushResult::Error; |
|||
} |
|||
|
|||
git_push_options pushOptions = GIT_PUSH_OPTIONS_INIT; |
|||
pushOptions.callbacks = remoteCallbacks; |
|||
|
|||
if( git_remote_push( remote, nullptr, &pushOptions ) ) |
|||
{ |
|||
git_remote_free( remote ); |
|||
AddErrorString( _( "Could not push to remote" ) ); |
|||
return PushResult::Error; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
|
|||
void GIT_PUSH_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) |
|||
{ |
|||
ReportProgress( aCurrent, aTotal, aMessage ); |
|||
} |
@ -0,0 +1,57 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GITPUSHHANDLER_HPP |
|||
#define GITPUSHHANDLER_HPP |
|||
|
|||
#include <git2.h> |
|||
#include <functional> |
|||
#include <vector> |
|||
#include <string> |
|||
|
|||
#include "kicad_git_common.h" |
|||
#include <git/git_progress.h> |
|||
|
|||
// Enum for result codes |
|||
enum class PushResult |
|||
{ |
|||
Success, |
|||
Error, |
|||
UpToDate |
|||
}; |
|||
|
|||
class GIT_PUSH_HANDLER : public KIGIT_COMMON, public GIT_PROGRESS |
|||
{ |
|||
public: |
|||
GIT_PUSH_HANDLER( git_repository* aRepo ); |
|||
~GIT_PUSH_HANDLER(); |
|||
|
|||
PushResult PerformPush(); |
|||
|
|||
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override; |
|||
|
|||
private: |
|||
|
|||
}; |
|||
|
|||
#endif // GITPUSHHANDLER_HPP |
@ -0,0 +1,98 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <wx/string.h>
|
|||
#include <wx/log.h>
|
|||
|
|||
#include "git_remove_from_index_handler.h"
|
|||
|
|||
GIT_REMOVE_FROM_INDEX_HANDLER::GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository ) |
|||
{ |
|||
m_repository = aRepository; |
|||
m_filesToRemove.clear(); |
|||
} |
|||
|
|||
GIT_REMOVE_FROM_INDEX_HANDLER::~GIT_REMOVE_FROM_INDEX_HANDLER() |
|||
{ |
|||
} |
|||
|
|||
bool GIT_REMOVE_FROM_INDEX_HANDLER::RemoveFromIndex( const wxString& aFilePath ) |
|||
{ |
|||
// Test if file is currently in the index
|
|||
|
|||
git_index* index = nullptr; |
|||
size_t at_pos = 0; |
|||
|
|||
if( git_repository_index( &index, m_repository ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to get repository index" ); |
|||
return false; |
|||
} |
|||
|
|||
if( git_index_find( &at_pos, index, aFilePath.ToUTF8().data() ) != 0 ) |
|||
{ |
|||
git_index_free( index ); |
|||
wxLogError( "Failed to find index entry for %s", aFilePath ); |
|||
return false; |
|||
} |
|||
|
|||
git_index_free( index ); |
|||
|
|||
m_filesToRemove.push_back( aFilePath ); |
|||
return true; |
|||
} |
|||
|
|||
void GIT_REMOVE_FROM_INDEX_HANDLER::PerformRemoveFromIndex() |
|||
{ |
|||
for( auto& file : m_filesToRemove ) |
|||
{ |
|||
git_index* index = nullptr; |
|||
git_oid oid; |
|||
|
|||
if( git_repository_index( &index, m_repository ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to get repository index" ); |
|||
return; |
|||
} |
|||
|
|||
if( git_index_remove_bypath( index, file.ToUTF8().data() ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to remove index entry for %s", file ); |
|||
return; |
|||
} |
|||
|
|||
if( git_index_write( index ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to write index" ); |
|||
return; |
|||
} |
|||
|
|||
if( git_index_write_tree( &oid, index ) != 0 ) |
|||
{ |
|||
wxLogError( "Failed to write index tree" ); |
|||
return; |
|||
} |
|||
|
|||
git_index_free( index ); |
|||
} |
|||
} |
@ -0,0 +1,50 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_REMOVE_FROM_INDEX_HANDLER_H_ |
|||
#define GIT_REMOVE_FROM_INDEX_HANDLER_H_ |
|||
|
|||
#include <git2.h> |
|||
#include <vector> |
|||
|
|||
class wxString; |
|||
|
|||
class GIT_REMOVE_FROM_INDEX_HANDLER |
|||
{ |
|||
public: |
|||
GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository ); |
|||
virtual ~GIT_REMOVE_FROM_INDEX_HANDLER(); |
|||
|
|||
bool RemoveFromIndex( const wxString& aFilePath ); |
|||
|
|||
void PerformRemoveFromIndex(); |
|||
|
|||
private: |
|||
|
|||
git_repository* m_repository; |
|||
|
|||
std::vector<wxString> m_filesToRemove; |
|||
}; |
|||
|
|||
|
|||
#endif /* GIT_REMOVE_FROM_INDEX_HANDLER_H_ */ |
@ -0,0 +1,39 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "git_resolve_conflict_handler.h"
|
|||
|
|||
GIT_RESOLVE_CONFLICT_HANDLER::GIT_RESOLVE_CONFLICT_HANDLER( git_repository* aRepository ) |
|||
{ |
|||
m_repository = aRepository; |
|||
} |
|||
|
|||
GIT_RESOLVE_CONFLICT_HANDLER::~GIT_RESOLVE_CONFLICT_HANDLER() |
|||
{ |
|||
} |
|||
|
|||
bool GIT_RESOLVE_CONFLICT_HANDLER::PerformResolveConflict() |
|||
{ |
|||
return true; |
|||
} |
|||
|
@ -0,0 +1,43 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_RESOLVE_CONFLICT_HANDLER_H |
|||
#define GIT_RESOLVE_CONFLICT_HANDLER_H |
|||
|
|||
#include <git2.h> |
|||
|
|||
class wxString; |
|||
|
|||
class GIT_RESOLVE_CONFLICT_HANDLER |
|||
{ |
|||
public: |
|||
GIT_RESOLVE_CONFLICT_HANDLER( git_repository* aRepository ); |
|||
virtual ~GIT_RESOLVE_CONFLICT_HANDLER(); |
|||
|
|||
bool PerformResolveConflict(); |
|||
|
|||
private: |
|||
git_repository* m_repository; |
|||
}; |
|||
|
|||
#endif // GIT_RESOLVE_CONFLICT_HANDLER_H |
@ -0,0 +1,108 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "git_revert_handler.h"
|
|||
|
|||
#include <wx/log.h>
|
|||
#include <wx/string.h>
|
|||
|
|||
GIT_REVERT_HANDLER::GIT_REVERT_HANDLER( git_repository* aRepository ) |
|||
{ |
|||
m_repository = aRepository; |
|||
} |
|||
|
|||
GIT_REVERT_HANDLER::~GIT_REVERT_HANDLER() |
|||
{ |
|||
} |
|||
|
|||
bool GIT_REVERT_HANDLER::Revert( const wxString& aFilePath ) |
|||
{ |
|||
m_filesToRevert.push_back( aFilePath ); |
|||
return true; |
|||
} |
|||
|
|||
static void checkout_progress_cb(const char *path, size_t cur, size_t tot, void *payload) |
|||
{ |
|||
wxLogDebug( "checkout_progress_cb: %s %zu/%zu", path, cur, tot ); |
|||
} |
|||
|
|||
|
|||
static int checkout_notify_cb(git_checkout_notify_t why, const char *path, |
|||
const git_diff_file *baseline, |
|||
const git_diff_file *target, |
|||
const git_diff_file *workdir, void *payload) |
|||
{ |
|||
GIT_REVERT_HANDLER* handler = static_cast<GIT_REVERT_HANDLER*>(payload); |
|||
|
|||
if( why & ( GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_IGNORED | GIT_CHECKOUT_NOTIFY_UPDATED ) ) |
|||
handler->PushFailedFile( path ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void GIT_REVERT_HANDLER::PerformRevert() |
|||
{ |
|||
git_object* head_commit = NULL; |
|||
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; |
|||
|
|||
// Get the HEAD commit
|
|||
if (git_revparse_single(&head_commit, m_repository, "HEAD") != 0) { |
|||
// Handle error. If we cannot get the HEAD, then there's no point proceeding.
|
|||
return; |
|||
} |
|||
|
|||
opts.checkout_strategy = GIT_CHECKOUT_FORCE; |
|||
char** paths = new char*[m_filesToRevert.size()]; |
|||
|
|||
for( size_t ii = 0; ii < m_filesToRevert.size(); ii++ ) |
|||
{ |
|||
// Set paths to the specific file
|
|||
paths[ii] = wxStrdup( m_filesToRevert[ii].ToUTF8() ); |
|||
} |
|||
|
|||
git_strarray arr = { paths, m_filesToRevert.size() }; |
|||
|
|||
opts.paths = arr; |
|||
opts.progress_cb = checkout_progress_cb; |
|||
opts.notify_cb = checkout_notify_cb; |
|||
opts.notify_payload = static_cast<void*>(this); |
|||
|
|||
// Attempt to checkout the file(s)
|
|||
if (git_checkout_tree(m_repository, head_commit, &opts) != 0) |
|||
{ |
|||
const git_error *e = git_error_last(); |
|||
if (e) |
|||
{ |
|||
wxLogError( "Checkout failed: %d: %s", e->klass, e->message ); |
|||
} |
|||
} |
|||
|
|||
// Free the HEAD commit
|
|||
for( size_t ii = 0; ii < m_filesToRevert.size(); ii++ ) |
|||
delete( paths[ii] ); |
|||
|
|||
delete[] paths; |
|||
|
|||
git_object_free(head_commit); |
|||
} |
|||
|
@ -0,0 +1,54 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_REVERT_HANDLER_H_ |
|||
#define GIT_REVERT_HANDLER_H_ |
|||
|
|||
#include <git2.h> |
|||
#include <vector> |
|||
|
|||
class wxString; |
|||
|
|||
class GIT_REVERT_HANDLER |
|||
{ |
|||
public: |
|||
GIT_REVERT_HANDLER( git_repository* aRepository ); |
|||
virtual ~GIT_REVERT_HANDLER(); |
|||
|
|||
bool Revert( const wxString& aFilePath ); |
|||
|
|||
void PerformRevert(); |
|||
|
|||
void PushFailedFile( const wxString& aFilePath ) |
|||
{ |
|||
m_filesFailedToRevert.push_back( aFilePath ); |
|||
} |
|||
|
|||
private: |
|||
git_repository* m_repository; |
|||
|
|||
std::vector<wxString> m_filesToRevert; |
|||
std::vector<wxString> m_filesFailedToRevert; |
|||
}; |
|||
|
|||
#endif /* GIT_REVERT_HANDLER_H_ */ |
@ -0,0 +1,44 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "git_sync_handler.h"
|
|||
|
|||
#include <wx/string.h>
|
|||
|
|||
#include <git2.h>
|
|||
|
|||
GIT_SYNC_HANDLER::GIT_SYNC_HANDLER( git_repository* aRepository ) |
|||
{ |
|||
m_repository = aRepository; |
|||
} |
|||
|
|||
|
|||
GIT_SYNC_HANDLER::~GIT_SYNC_HANDLER() |
|||
{ |
|||
} |
|||
|
|||
|
|||
bool GIT_SYNC_HANDLER::PerformSync() |
|||
{ |
|||
return true; |
|||
} |
@ -0,0 +1,43 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef GIT_SYNC_HANDLER_H_ |
|||
#define GIT_SYNC_HANDLER_H_ |
|||
|
|||
#include <git2.h> |
|||
|
|||
class wxString; |
|||
|
|||
class GIT_SYNC_HANDLER |
|||
{ |
|||
public: |
|||
GIT_SYNC_HANDLER( git_repository* aRepository ); |
|||
virtual ~GIT_SYNC_HANDLER(); |
|||
|
|||
bool PerformSync(); |
|||
|
|||
private: |
|||
git_repository* m_repository; |
|||
}; |
|||
|
|||
#endif /* GIT_SYNC_HANDLER_H_ */ |
@ -0,0 +1,97 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <streambuf> |
|||
#include <istream> |
|||
#include <string> |
|||
#include <git2.h> |
|||
|
|||
#include <richio.h> |
|||
|
|||
|
|||
class BLOB_BUFFER_STREAM : public std::streambuf |
|||
{ |
|||
public: |
|||
BLOB_BUFFER_STREAM( git_blob* aBlob ) |
|||
{ |
|||
// Yay C++ |
|||
setg( const_cast<char*>( static_cast<const char*>( git_blob_rawcontent( aBlob ) ) ), |
|||
const_cast<char*>( static_cast<const char*>( git_blob_rawcontent( aBlob ) ) ), |
|||
const_cast<char*>( static_cast<const char*>( git_blob_rawcontent( aBlob ) ) ) + git_blob_rawsize( aBlob ) ); |
|||
} |
|||
|
|||
~BLOB_BUFFER_STREAM() override |
|||
{ |
|||
} |
|||
|
|||
int overflow( int c ) override |
|||
{ |
|||
return traits_type::eof(); |
|||
} |
|||
|
|||
std::streamsize xsputn( const char* s, std::streamsize n ) override |
|||
{ |
|||
return 0; |
|||
} |
|||
}; |
|||
|
|||
// Build a class that implements LINE_READER for git_blobs |
|||
class BLOB_READER : public LINE_READER |
|||
{ |
|||
public: |
|||
BLOB_READER( git_blob* aBlob ) : m_blob( aBlob ) |
|||
{ |
|||
m_stream = new BLOB_BUFFER_STREAM( m_blob ); |
|||
m_istream = new std::istream( m_stream ); |
|||
m_line = nullptr; |
|||
m_lineNum = 0; |
|||
} |
|||
|
|||
~BLOB_READER() override |
|||
{ |
|||
delete m_istream; |
|||
delete m_stream; |
|||
} |
|||
|
|||
char* ReadLine() override |
|||
{ |
|||
getline( *m_istream, m_buffer ); |
|||
|
|||
m_buffer.append( 1, '\n' ); |
|||
|
|||
m_length = m_buffer.size(); |
|||
m_line = (char*) m_buffer.data(); //ew why no const?? |
|||
|
|||
// lineNum is incremented even if there was no line read, because this |
|||
// leads to better error reporting when we hit an end of file. |
|||
++m_lineNum; |
|||
|
|||
return m_istream->eof() ? nullptr : m_line; |
|||
} |
|||
|
|||
private: |
|||
git_blob* m_blob; |
|||
BLOB_BUFFER_STREAM* m_stream; |
|||
std::istream* m_istream; |
|||
std::string m_buffer; |
|||
}; |
@ -0,0 +1,541 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "kicad_git_common.h"
|
|||
|
|||
#include <wx/filename.h>
|
|||
#include <wx/log.h>
|
|||
#include <map>
|
|||
#include <vector>
|
|||
|
|||
KIGIT_COMMON::KIGIT_COMMON( git_repository* aRepo ) : m_repo( aRepo ) |
|||
{} |
|||
|
|||
KIGIT_COMMON::~KIGIT_COMMON() |
|||
{} |
|||
|
|||
git_repository* KIGIT_COMMON::GetRepo() const |
|||
{ |
|||
return m_repo; |
|||
} |
|||
|
|||
wxString KIGIT_COMMON::GetCurrentBranchName() const |
|||
{ |
|||
git_reference* head = nullptr; |
|||
|
|||
int retval = git_repository_head( &head, m_repo ); |
|||
|
|||
if( retval && retval != GIT_EUNBORNBRANCH && retval != GIT_ENOTFOUND ) |
|||
return wxEmptyString; |
|||
|
|||
git_reference *branch; |
|||
|
|||
if( git_reference_resolve( &branch, head ) ) |
|||
{ |
|||
git_reference_free( head ); |
|||
return wxEmptyString; |
|||
} |
|||
|
|||
git_reference_free( head ); |
|||
const char* branchName = ""; |
|||
|
|||
if( git_branch_name( &branchName, branch ) ) |
|||
{ |
|||
git_reference_free( branch ); |
|||
return wxEmptyString; |
|||
} |
|||
|
|||
git_reference_free( branch ); |
|||
|
|||
return branchName; |
|||
} |
|||
|
|||
|
|||
std::vector<wxString> KIGIT_COMMON::GetBranchNames() const |
|||
{ |
|||
std::vector<wxString> branchNames; |
|||
std::map<git_time_t, wxString> branchNamesMap; |
|||
wxString firstName; |
|||
|
|||
git_branch_iterator* branchIterator = nullptr; |
|||
|
|||
if( git_branch_iterator_new( &branchIterator, m_repo, GIT_BRANCH_LOCAL ) ) |
|||
return branchNames; |
|||
|
|||
git_reference* branchReference = nullptr; |
|||
git_branch_t branchType; |
|||
|
|||
while( git_branch_next( &branchReference, &branchType, branchIterator ) != GIT_ITEROVER ) |
|||
{ |
|||
const char* branchName = ""; |
|||
|
|||
if( git_branch_name( &branchName, branchReference ) ) |
|||
continue; |
|||
|
|||
const git_oid* commitId = git_reference_target( branchReference ); |
|||
|
|||
git_commit* commit = nullptr; |
|||
|
|||
if( git_commit_lookup( &commit, m_repo, commitId ) ) |
|||
continue; |
|||
|
|||
git_time_t commitTime = git_commit_time( commit ); |
|||
|
|||
if( git_branch_is_head( branchReference ) ) |
|||
firstName = branchName; |
|||
else |
|||
branchNamesMap.emplace( commitTime, branchName ); |
|||
|
|||
git_commit_free( commit ); |
|||
git_reference_free( branchReference ); |
|||
} |
|||
|
|||
git_branch_iterator_free( branchIterator ); |
|||
|
|||
// Add the current branch to the top of the list
|
|||
if( !firstName.IsEmpty() ) |
|||
branchNames.push_back( firstName ); |
|||
|
|||
// Add the remaining branches in order from newest to oldest
|
|||
for( auto rit = branchNamesMap.rbegin(); rit != branchNamesMap.rend(); ++rit ) |
|||
branchNames.push_back( rit->second ); |
|||
|
|||
return branchNames; |
|||
} |
|||
|
|||
|
|||
std::vector<wxString> KIGIT_COMMON::GetProjectDirs() |
|||
{ |
|||
std::vector<wxString> projDirs; |
|||
|
|||
git_oid oid; |
|||
git_commit* commit; |
|||
git_tree *tree; |
|||
|
|||
if( git_reference_name_to_id( &oid, m_repo, "HEAD" ) != GIT_OK ) |
|||
{ |
|||
wxLogError( "An error occurred: %s", git_error_last()->message ); |
|||
return projDirs; |
|||
} |
|||
|
|||
if( git_commit_lookup( &commit, m_repo, &oid ) != GIT_OK ) |
|||
{ |
|||
wxLogError( "An error occurred: %s", git_error_last()->message ); |
|||
return projDirs; |
|||
} |
|||
|
|||
if( git_commit_tree( &tree, commit ) != GIT_OK ) |
|||
{ |
|||
wxLogError( "An error occurred: %s", git_error_last()->message ); |
|||
return projDirs; |
|||
} |
|||
|
|||
// Define callback
|
|||
git_tree_walk( |
|||
tree, GIT_TREEWALK_PRE, |
|||
[]( const char* root, const git_tree_entry* entry, void* payload ) |
|||
{ |
|||
std::vector<wxString>* prjs = static_cast<std::vector<wxString>*>( payload ); |
|||
wxFileName root_fn( git_tree_entry_name( entry ) ); |
|||
|
|||
root_fn.SetPath( root ); |
|||
|
|||
if( git_tree_entry_type( entry ) == GIT_OBJECT_BLOB |
|||
&& ( ( root_fn.GetExt() == "kicad_pro" ) || ( root_fn.GetExt() == "pro" ) ) ) |
|||
{ |
|||
prjs->push_back( root_fn.GetFullPath() ); |
|||
} |
|||
|
|||
return 0; // continue walking
|
|||
}, |
|||
&projDirs ); |
|||
|
|||
git_tree_free( tree ); |
|||
git_commit_free( commit ); |
|||
|
|||
std::sort( projDirs.begin(), projDirs.end(), |
|||
[]( const wxString& a, const wxString& b ) |
|||
{ |
|||
int a_freq = a.Freq( wxFileName::GetPathSeparator() ); |
|||
int b_freq = b.Freq( wxFileName::GetPathSeparator() ); |
|||
|
|||
if( a_freq == b_freq ) |
|||
return a < b; |
|||
else |
|||
return a_freq < b_freq; |
|||
|
|||
} ); |
|||
|
|||
return projDirs; |
|||
} |
|||
|
|||
|
|||
std::pair<std::set<wxString>,std::set<wxString>> KIGIT_COMMON::GetDifferentFiles() const |
|||
{ |
|||
auto get_modified_files = [&]( git_oid* from_oid, git_oid* to_oid ) -> std::set<wxString> |
|||
{ |
|||
std::set<wxString> modified_set; |
|||
git_revwalk* walker = nullptr; |
|||
|
|||
if( git_revwalk_new( &walker, m_repo ) != GIT_OK ) |
|||
return modified_set; |
|||
|
|||
if( ( git_revwalk_push( walker, from_oid ) != GIT_OK ) |
|||
|| ( git_revwalk_hide( walker, to_oid ) != GIT_OK ) ) |
|||
{ |
|||
git_revwalk_free( walker ); |
|||
return modified_set; |
|||
} |
|||
|
|||
git_oid oid; |
|||
git_commit* commit; |
|||
|
|||
// iterate over all local commits not in remote
|
|||
while( git_revwalk_next( &oid, walker ) == GIT_OK ) |
|||
{ |
|||
if( git_commit_lookup( &commit, m_repo, &oid ) != GIT_OK ) |
|||
continue; |
|||
|
|||
git_tree *tree, *parent_tree = nullptr; |
|||
if( git_commit_tree( &tree, commit ) != GIT_OK ) |
|||
{ |
|||
git_commit_free( commit ); |
|||
continue; |
|||
} |
|||
|
|||
// get parent commit tree to diff against
|
|||
if( !git_commit_parentcount( commit ) ) |
|||
{ |
|||
git_tree_free( tree ); |
|||
git_commit_free( commit ); |
|||
continue; |
|||
} |
|||
|
|||
|
|||
git_commit* parent; |
|||
if( git_commit_parent( &parent, commit, 0 ) != GIT_OK ) |
|||
{ |
|||
git_tree_free( tree ); |
|||
git_commit_free( commit ); |
|||
continue; |
|||
} |
|||
|
|||
|
|||
if( git_commit_tree( &parent_tree, parent ) != GIT_OK ) |
|||
{ |
|||
git_tree_free( tree ); |
|||
git_commit_free( commit ); |
|||
git_commit_free( parent ); |
|||
continue; |
|||
} |
|||
|
|||
|
|||
git_diff* diff; |
|||
git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; |
|||
|
|||
if( git_diff_tree_to_tree( &diff, m_repo, parent_tree, tree, &diff_opts ) == GIT_OK ) |
|||
{ |
|||
size_t num_deltas = git_diff_num_deltas( diff ); |
|||
|
|||
for( size_t i = 0; i < num_deltas; ++i ) |
|||
{ |
|||
const git_diff_delta* delta = git_diff_get_delta( diff, i ); |
|||
modified_set.insert( delta->new_file.path ); |
|||
} |
|||
|
|||
git_diff_free( diff ); |
|||
} |
|||
|
|||
git_tree_free( parent_tree ); |
|||
git_commit_free( parent ); |
|||
git_tree_free( tree ); |
|||
git_commit_free( commit ); |
|||
} |
|||
|
|||
git_revwalk_free( walker ); |
|||
|
|||
return modified_set; |
|||
}; |
|||
|
|||
std::pair<std::set<wxString>,std::set<wxString>> modified_files; |
|||
|
|||
if( !m_repo ) |
|||
return modified_files; |
|||
|
|||
git_reference* head = nullptr; |
|||
git_reference* remote_head = nullptr; |
|||
|
|||
if( git_repository_head( &head, m_repo ) != GIT_OK ) |
|||
return modified_files; |
|||
|
|||
if( git_branch_upstream( &remote_head, head ) != GIT_OK ) |
|||
{ |
|||
git_reference_free( head ); |
|||
return modified_files; |
|||
} |
|||
|
|||
git_oid head_oid = *git_reference_target( head ); |
|||
git_oid remote_oid = *git_reference_target( remote_head ); |
|||
|
|||
git_reference_free( head ); |
|||
git_reference_free( remote_head ); |
|||
|
|||
modified_files.first = get_modified_files( &head_oid, &remote_oid ); |
|||
modified_files.second = get_modified_files( &remote_oid, &head_oid ); |
|||
|
|||
return modified_files; |
|||
} |
|||
|
|||
|
|||
bool KIGIT_COMMON::HasLocalCommits() const |
|||
{ |
|||
if( !m_repo ) |
|||
return false; |
|||
|
|||
git_reference* head = nullptr; |
|||
git_reference* remote_head = nullptr; |
|||
|
|||
if( git_repository_head( &head, m_repo ) != GIT_OK ) |
|||
return false; |
|||
|
|||
if( git_branch_upstream( &remote_head, head ) != GIT_OK ) |
|||
{ |
|||
git_reference_free( head ); |
|||
return false; |
|||
} |
|||
|
|||
git_oid head_oid = *git_reference_target( head ); |
|||
git_oid remote_oid = *git_reference_target( remote_head ); |
|||
|
|||
git_reference_free( head ); |
|||
git_reference_free( remote_head ); |
|||
|
|||
git_revwalk* walker = nullptr; |
|||
|
|||
if( git_revwalk_new( &walker, m_repo ) != GIT_OK ) |
|||
return false; |
|||
|
|||
if( ( git_revwalk_push( walker, &head_oid ) != GIT_OK ) |
|||
|| ( git_revwalk_hide( walker, &remote_oid ) != GIT_OK ) ) |
|||
{ |
|||
git_revwalk_free( walker ); |
|||
return false; |
|||
} |
|||
|
|||
git_oid oid; |
|||
|
|||
// If we can't walk to the next commit, then we are at or behind the remote
|
|||
if( git_revwalk_next( &oid, walker ) != GIT_OK ) |
|||
{ |
|||
git_revwalk_free( walker ); |
|||
return false; |
|||
} |
|||
|
|||
git_revwalk_free( walker ); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
bool KIGIT_COMMON::HasPushAndPullRemote() const |
|||
{ |
|||
git_remote* remote = nullptr; |
|||
|
|||
if( git_remote_lookup( &remote, m_repo, "origin" ) != GIT_OK ) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// Get the URLs associated with the remote
|
|||
const char* fetch_url = git_remote_url( remote ); |
|||
const char* push_url = git_remote_pushurl( remote ); |
|||
|
|||
// If no push URL is set, libgit2 defaults to using the fetch URL for pushing
|
|||
if( !push_url ) |
|||
{ |
|||
push_url = fetch_url; |
|||
} |
|||
|
|||
// Clean up the remote object
|
|||
git_remote_free( remote ); |
|||
|
|||
// Check if both URLs are valid (i.e., not NULL)
|
|||
return fetch_url && push_url; |
|||
} |
|||
|
|||
|
|||
extern "C" int fetchhead_foreach_cb( const char*, const char*, |
|||
const git_oid* aOID, unsigned int aIsMerge, void* aPayload ) |
|||
{ |
|||
if( aIsMerge ) |
|||
git_oid_cpy( (git_oid*) aPayload, aOID ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
extern "C" void clone_progress_cb( const char* aStr, size_t aLen, size_t aTotal, void* data ) |
|||
{ |
|||
KIGIT_COMMON* parent = (KIGIT_COMMON*) data; |
|||
|
|||
wxString progressMessage( aStr ); |
|||
parent->UpdateProgress( aLen, aTotal, progressMessage ); |
|||
} |
|||
|
|||
|
|||
extern "C" int progress_cb( const char* str, int len, void* data ) |
|||
{ |
|||
KIGIT_COMMON* parent = (KIGIT_COMMON*) data; |
|||
|
|||
wxString progressMessage( str, len ); |
|||
parent->UpdateProgress( 0, 0, progressMessage ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
extern "C" int transfer_progress_cb( const git_transfer_progress* aStats, void* aPayload ) |
|||
{ |
|||
KIGIT_COMMON* parent = (KIGIT_COMMON*) aPayload; |
|||
wxString progressMessage = wxString::Format( _( "Received %u of %u objects" ), |
|||
aStats->received_objects, aStats->total_objects ); |
|||
|
|||
parent->UpdateProgress( aStats->received_objects, aStats->total_objects, progressMessage ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
extern "C" int update_cb( const char* aRefname, const git_oid* aFirst, const git_oid* aSecond, |
|||
void* aPayload ) |
|||
{ |
|||
constexpr int cstring_len = 8; |
|||
char a_str[cstring_len + 1]; |
|||
char b_str[cstring_len + 1]; |
|||
|
|||
KIGIT_COMMON* parent = (KIGIT_COMMON*) aPayload; |
|||
wxString status; |
|||
|
|||
git_oid_tostr( b_str, cstring_len, aSecond ); |
|||
|
|||
if( !git_oid_is_zero( aFirst ) ) |
|||
{ |
|||
git_oid_tostr( a_str, cstring_len, aFirst ); |
|||
status = wxString::Format( _( "* [updated] %s..%s %s" ), a_str, b_str, aRefname ); |
|||
} |
|||
else |
|||
{ |
|||
status = wxString::Format( _( "* [new] %s %s" ), b_str, aRefname ); |
|||
} |
|||
|
|||
parent->UpdateProgress( 0, 0, status ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
extern "C" int push_transfer_progress_cb( unsigned int aCurrent, unsigned int aTotal, size_t aBytes, |
|||
void* aPayload ) |
|||
{ |
|||
int64_t progress = 100; |
|||
KIGIT_COMMON* parent = (KIGIT_COMMON*) aPayload; |
|||
|
|||
if( aTotal != 0 ) |
|||
{ |
|||
progress = ( aCurrent * 100 ) / aTotal; |
|||
} |
|||
|
|||
wxString progressMessage = wxString::Format( _( "Writing objects: %d%% (%d/%d), %d bytes" ), |
|||
progress, aCurrent, aTotal, aBytes ); |
|||
parent->UpdateProgress( aCurrent, aTotal, progressMessage ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
extern "C" int push_update_reference_cb( const char* aRefname, const char* aStatus, void* aPayload ) |
|||
{ |
|||
KIGIT_COMMON* parent = (KIGIT_COMMON*) aPayload; |
|||
wxString status( aStatus ); |
|||
|
|||
if( !status.IsEmpty() ) |
|||
{ |
|||
wxString statusMessage = wxString::Format( _( "* [rejected] %s (%s)" ), aRefname, aStatus ); |
|||
parent->UpdateProgress( 0, 0, statusMessage ); |
|||
} |
|||
else |
|||
{ |
|||
wxString statusMessage = wxString::Format( _( "[updated] %s" ), aRefname ); |
|||
parent->UpdateProgress( 0, 0, statusMessage ); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
extern "C" int credentials_cb( git_cred** aOut, const char* aUrl, const char* aUsername, |
|||
unsigned int aAllowedTypes, void* aPayload ) |
|||
{ |
|||
KIGIT_COMMON* parent = static_cast<KIGIT_COMMON*>( aPayload ); |
|||
|
|||
if( parent->GetConnType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_LOCAL ) |
|||
return GIT_PASSTHROUGH; |
|||
|
|||
if( aAllowedTypes & GIT_CREDENTIAL_USERNAME |
|||
&& !( parent->TestedTypes() & GIT_CREDTYPE_USERNAME ) ) |
|||
{ |
|||
wxString username = parent->GetUsername().Trim().Trim( false ); |
|||
git_cred_username_new( aOut, username.ToStdString().c_str() ); |
|||
parent->TestedTypes() |= GIT_CREDTYPE_USERNAME; |
|||
} |
|||
else if( parent->GetConnType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_HTTPS |
|||
&& ( aAllowedTypes & GIT_CREDENTIAL_USERPASS_PLAINTEXT ) |
|||
&& !( parent->TestedTypes() & GIT_CREDTYPE_USERPASS_PLAINTEXT ) ) |
|||
{ |
|||
wxString username = parent->GetUsername().Trim().Trim( false ); |
|||
wxString password = parent->GetPassword().Trim().Trim( false ); |
|||
|
|||
git_cred_userpass_plaintext_new( aOut, username.ToStdString().c_str(), |
|||
password.ToStdString().c_str() ); |
|||
parent->TestedTypes() |= GIT_CREDTYPE_USERPASS_PLAINTEXT; |
|||
} |
|||
else if( parent->GetConnType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH |
|||
&& ( aAllowedTypes & GIT_CREDENTIAL_SSH_KEY ) |
|||
&& !( parent->TestedTypes() & GIT_CREDTYPE_SSH_KEY ) ) |
|||
{ |
|||
// SSH key authentication
|
|||
wxString sshKey = parent->GetSSHKey(); |
|||
wxString sshPubKey = sshKey + ".pub"; |
|||
wxString username = parent->GetUsername().Trim().Trim( false ); |
|||
wxString password = parent->GetPassword().Trim().Trim( false ); |
|||
|
|||
git_cred_ssh_key_new( aOut, username.ToStdString().c_str(), |
|||
sshPubKey.ToStdString().c_str(), |
|||
sshKey.ToStdString().c_str(), |
|||
password.ToStdString().c_str() ); |
|||
parent->TestedTypes() |= GIT_CREDTYPE_SSH_KEY; |
|||
} |
|||
else |
|||
{ |
|||
return GIT_PASSTHROUGH; |
|||
} |
|||
|
|||
return GIT_OK; |
|||
}; |
@ -0,0 +1,145 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef _GIT_COMMON_H_ |
|||
#define _GIT_COMMON_H_ |
|||
|
|||
#include <git/kicad_git_errors.h> |
|||
|
|||
#include <git2.h> |
|||
#include <set> |
|||
|
|||
#include <wx/string.h> |
|||
|
|||
class KIGIT_COMMON : public KIGIT_ERRORS |
|||
{ |
|||
|
|||
public: |
|||
KIGIT_COMMON( git_repository* aRepo ); |
|||
~KIGIT_COMMON(); |
|||
|
|||
git_repository* GetRepo() const; |
|||
|
|||
void SetRepo( git_repository* aRepo ) |
|||
{ |
|||
m_repo = aRepo; |
|||
} |
|||
|
|||
wxString GetCurrentBranchName() const; |
|||
|
|||
std::vector<wxString> GetBranchNames() const; |
|||
|
|||
virtual void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) {}; |
|||
|
|||
/** |
|||
* Return a vector of project files in the repository. Sorted by the depth of |
|||
* the project file in the directory tree |
|||
* |
|||
* @return std::vector<wxString> of project files |
|||
*/ |
|||
std::vector<wxString> GetProjectDirs(); |
|||
|
|||
/** |
|||
* Return a pair of sets of files that differ locally from the remote repository |
|||
* The first set is files that have been committed locally but not pushed |
|||
* The second set is files that have been committed remotely but not pulled |
|||
*/ |
|||
std::pair<std::set<wxString>,std::set<wxString>> GetDifferentFiles() const; |
|||
|
|||
enum class GIT_STATUS |
|||
{ |
|||
GIT_STATUS_UNTRACKED, |
|||
GIT_STATUS_CURRENT, |
|||
GIT_STATUS_MODIFIED, // File changed but not committed to local repository |
|||
GIT_STATUS_ADDED, |
|||
GIT_STATUS_DELETED, |
|||
GIT_STATUS_BEHIND, // File changed in remote repository but not in local |
|||
GIT_STATUS_AHEAD, // File changed in local repository but not in remote |
|||
GIT_STATUS_CONFLICTED, |
|||
GIT_STATUS_LAST |
|||
}; |
|||
|
|||
enum class GIT_CONN_TYPE |
|||
{ |
|||
GIT_CONN_HTTPS = 0, |
|||
GIT_CONN_SSH, |
|||
GIT_CONN_LOCAL, |
|||
GIT_CONN_LAST |
|||
}; |
|||
|
|||
wxString GetUsername() const { return m_username; } |
|||
wxString GetPassword() const { return m_password; } |
|||
wxString GetSSHKey() const { return m_sshKey; } |
|||
GIT_CONN_TYPE GetConnType() const { return m_connType; } |
|||
|
|||
void SetUsername( const wxString& aUsername ) { m_username = aUsername; } |
|||
void SetPassword( const wxString& aPassword ) { m_password = aPassword; } |
|||
void SetSSHKey( const wxString& aSSHKey ) { m_sshKey = aSSHKey; } |
|||
|
|||
void SetConnType( GIT_CONN_TYPE aConnType ) { m_connType = aConnType; } |
|||
void SetConnType( unsigned aConnType ) |
|||
{ |
|||
if( aConnType < static_cast<unsigned>( GIT_CONN_TYPE::GIT_CONN_LAST ) ) |
|||
m_connType = static_cast<GIT_CONN_TYPE>( aConnType ); |
|||
} |
|||
|
|||
// Holds a temporary variable that can be used by the authentication callback |
|||
// to remember which types of authentication have been tested so that we |
|||
// don't loop forever. |
|||
unsigned& TestedTypes() { return m_testedTypes; } |
|||
|
|||
// Returns true if the repository has local commits that have not been pushed |
|||
bool HasLocalCommits() const; |
|||
|
|||
// Returns true if the repository has a remote that can be pushed to pulled from |
|||
bool HasPushAndPullRemote() const; |
|||
|
|||
protected: |
|||
git_repository* m_repo; |
|||
|
|||
GIT_CONN_TYPE m_connType; |
|||
wxString m_username; |
|||
wxString m_password; |
|||
wxString m_sshKey; |
|||
|
|||
unsigned m_testedTypes; |
|||
|
|||
}; |
|||
|
|||
|
|||
extern "C" int progress_cb( const char* str, int len, void* data ); |
|||
extern "C" void clone_progress_cb( const char* str, size_t len, size_t total, void* data ); |
|||
extern "C" int transfer_progress_cb( const git_transfer_progress* aStats, void* aPayload ); |
|||
extern "C" int update_cb( const char* aRefname, const git_oid* aFirst, const git_oid* aSecond, |
|||
void* aPayload ); |
|||
extern "C" int push_transfer_progress_cb( unsigned int aCurrent, unsigned int aTotal, |
|||
size_t aBytes, void* aPayload ); |
|||
extern "C" int push_update_reference_cb( const char* aRefname, const char* aStatus, |
|||
void* aPayload ); |
|||
|
|||
extern "C" int fetchhead_foreach_cb( const char*, const char*, |
|||
const git_oid* aOID, unsigned int aIsMerge, void* aPayload ); |
|||
extern "C" int credentials_cb( git_cred** aOut, const char* aUrl, const char* aUsername, |
|||
unsigned int aAllowedTypes, void* aPayload ); |
|||
|
|||
#endif // _GIT_COMMON_H_ |
@ -0,0 +1,66 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 3 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
namespace KIGIT_ERROR |
|||
{ |
|||
#undef _
|
|||
#define _(a) a
|
|||
|
|||
// General errors
|
|||
const char* const kInvalidRepository = _("Invalid repository."); |
|||
const char* const kCommitFailed = _("Failed to commit changes."); |
|||
const char* const kMergeFailed = _("Failed to merge branches."); |
|||
|
|||
// Clone errors
|
|||
const char* const kCloneFailed = _("Failed to clone repository."); |
|||
const char* const kRemoteNotFound = _("Remote repository not found."); |
|||
const char* const kAuthenticationFailed = _("Authentication failed for remote repository."); |
|||
|
|||
// Branch errors
|
|||
const char* const kBranchNotFound = _("Branch not found."); |
|||
const char* const kBranchCreationFailed = _("Failed to create branch."); |
|||
const char* const kBranchDeletionFailed = _("Failed to delete branch."); |
|||
|
|||
// Checkout errors
|
|||
const char* const kCheckoutFailed = _("Failed to perform checkout operation."); |
|||
const char* const kFileNotFoundInCheckout = _("File not found during checkout operation."); |
|||
|
|||
// Conflict errors
|
|||
const char* const kMergeConflict = _("Merge conflict encountered."); |
|||
const char* const kRebaseConflict = _("Rebase conflict encountered."); |
|||
|
|||
// Pull/Push errors
|
|||
const char* const kPullFailed = _("Failed to pull changes from remote repository."); |
|||
const char* const kPushFailed = _("Failed to push changes to remote repository."); |
|||
const char* const kNoUpstreamBranch = _("No upstream branch configured."); |
|||
const char* const kRemoteConnectionError = _("Failed to establish connection with remote repository."); |
|||
|
|||
// Tag errors
|
|||
const char* const kTagNotFound = _("Tag not found."); |
|||
const char* const kTagCreationFailed = _("Failed to create tag."); |
|||
const char* const kTagDeletionFailed = _("Failed to delete tag."); |
|||
|
|||
const char* const kUnknownError = _("Unknown error."); |
|||
const char* const kNoError = _("No error."); |
|||
|
|||
} |
@ -0,0 +1,81 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 3 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/gpl-3.0.html |
|||
* or you may search the http://www.gnu.org website for the version 3 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef KICAD_GIT_ERRORS_H |
|||
#define KICAD_GIT_ERRORS_H |
|||
|
|||
#include <vector> |
|||
|
|||
#include <wx/translation.h> |
|||
|
|||
class KIGIT_ERRORS |
|||
{ |
|||
public: |
|||
|
|||
KIGIT_ERRORS() = default; |
|||
|
|||
const std::vector<wxString>& GetErrorStrings() const |
|||
{ |
|||
return m_errorStrings; |
|||
} |
|||
|
|||
const wxString& PeekErrorString() const |
|||
{ |
|||
if( m_errorStrings.empty() ) |
|||
return _( "No error" ); |
|||
else |
|||
return m_errorStrings.back(); |
|||
} |
|||
|
|||
wxString GetErrorString() |
|||
{ |
|||
if( m_errorStrings.empty() ) |
|||
return _( "No error" ); |
|||
|
|||
const wxString errorString( m_errorStrings.back() ); |
|||
m_errorStrings.pop_back(); |
|||
return errorString; |
|||
} |
|||
|
|||
void AddErrorString( const wxString aErrorString ) |
|||
{ |
|||
m_errorStrings.emplace_back( aErrorString ); |
|||
} |
|||
|
|||
void AddErrorString( const std::string aErrorString ) |
|||
{ |
|||
m_errorStrings.emplace_back( aErrorString ); |
|||
} |
|||
|
|||
void ClearErrorStrings() |
|||
{ |
|||
m_errorStrings.clear(); |
|||
} |
|||
|
|||
private: |
|||
|
|||
std::vector<wxString> m_errorStrings; |
|||
|
|||
}; |
|||
|
|||
#endif // KICAD_GIT_ERRORS_H |
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue