31#include <wx/stdpaths.h>
34#include <wx/textdlg.h>
55#include <wx/dcclient.h>
56#include <wx/settings.h>
103 wxT(
"^.*\\.kicad_pro$" ),
106 wxT(
"^.*\\.kicad_sch$" ),
107 wxT(
"^[^$].*\\.brd$" ),
108 wxT(
"^[^$].*\\.kicad_pcb$" ),
109 wxT(
"^[^$].*\\.kicad_dru$" ),
110 wxT(
"^[^$].*\\.kicad_wks$" ),
111 wxT(
"^[^$].*\\.kicad_mod$" ),
115 wxT(
"^.*\\.kicad_sym$" ),
120 wxT(
"^.*\\.gbrjob$" ),
121 wxT(
"^.*\\.gb[alops]$" ),
122 wxT(
"^.*\\.gt[alops]$" ),
123 wxT(
"^.*\\.g[0-9]{1,2}$" ),
124 wxT(
"^.*\\.gm[0-9]{1,2}$" ),
128 wxT(
"^.*\\.html$" ),
139 wxT(
"^.*\\.kicad_jobset" ),
188 wxSashLayoutWindow( parent,
ID_LEFT_FRAME, wxDefaultPosition, wxDefaultSize,
189 wxNO_BORDER | wxTAB_TRAVERSAL )
192 m_TreeProject =
nullptr;
193 m_isRenaming =
false;
194 m_selectedItem =
nullptr;
195 m_watcherNeedReset =
false;
196 m_gitLastError = GIT_ERROR_NONE;
198 m_gitIconsInitialized =
false;
200 Bind( wxEVT_FSWATCHER,
203 Bind( wxEVT_SYS_COLOUR_CHANGED,
206 m_gitSyncTimer.SetOwner(
this );
207 m_gitStatusTimer.SetOwner(
this );
217 m_filters.emplace_back( wxT(
"^no KiCad files found" ) );
225 Unbind( wxEVT_FSWATCHER,
227 Unbind( wxEVT_SYS_COLOUR_CHANGED,
256 if( tree_data.size() != 1 )
259 wxString prj_filename = tree_data[0]->GetFileName();
273 wxString curr_dir = item_data->GetDir();
275 if( curr_dir.IsEmpty() )
281 if( curr_dir.IsEmpty() || !wxFileName::DirExists( curr_dir ) )
284 if( !curr_dir.IsEmpty() )
285 curr_dir += wxFileName::GetPathSeparator();
303 wxString curr_dir = item_data->GetDir();
305 if( curr_dir.IsEmpty() )
308 wxString new_dir = wxGetTextFromUser(
_(
"Directory name:" ),
_(
"Create New Directory" ) );
310 if( new_dir.IsEmpty() )
313 wxString full_dirname = curr_dir + wxFileName::GetPathSeparator() + new_dir;
315 if( !wxMkdir( full_dirname ) )
345 case TREE_FILE_TYPE::DRILL_NC:
return "nc";
346 case TREE_FILE_TYPE::DRILL_XNC:
return "xnc";
356 case TREE_FILE_TYPE::ROOT:
357 case TREE_FILE_TYPE::UNKNOWN:
358 case TREE_FILE_TYPE::MAX:
359 case TREE_FILE_TYPE::DIRECTORY:
break;
362 return wxEmptyString;
368 std::vector<wxString> projects;
369 wxString dir_filename;
370 bool haveFile = dir.GetFirst( &dir_filename );
374 wxFileName file( dir_filename );
378 projects.push_back( file.GetName() );
380 haveFile = dir.GetNext( &dir_filename );
389 git_repository* repo =
nullptr;
393 if( git_repository_discover( &repo_path, filename, 0, NULL ) != GIT_OK )
401 if( git_repository_open( &repo, repo_path.ptr ) != GIT_OK )
412 const wxTreeItemId& aParent,
413 std::vector<wxString>* aProjectNames,
417 wxFileName fn( aName );
420 return wxTreeItemId();
422 if( wxDirExists( aName ) )
424 type = TREE_FILE_TYPE::DIRECTORY;
430 bool addFile =
false;
432 for(
const wxString& m_filter :
m_filters )
434 wxCHECK2_MSG( reg.Compile( m_filter, wxRE_ICASE ),
continue,
435 wxString::Format(
"Regex %s failed to compile.", m_filter ) );
437 if( reg.Matches( aName ) )
445 return wxTreeItemId();
447 for(
int i =
static_cast<int>( TREE_FILE_TYPE::LEGACY_PROJECT );
448 i < static_cast<int>( TREE_FILE_TYPE::MAX ); i++ )
452 if( ext == wxT(
"" ) )
455 if( reg.Compile( wxString::FromAscii(
"^.*\\." ) + ext + wxString::FromAscii(
"$" ),
456 wxRE_ICASE ) && reg.Matches( aName ) )
464 wxString file = wxFileNameFromPath( aName );
465 wxFileName currfile( file );
469 if( ( type == TREE_FILE_TYPE::LEGACY_PROJECT )
470 && ( currfile.GetName().CmpNoCase(
project.GetName() ) == 0 ) )
472 return wxTreeItemId();
475 if( currfile.GetExt() ==
GetFileExt( TREE_FILE_TYPE::LEGACY_SCHEMATIC )
476 || currfile.GetExt() ==
GetFileExt( TREE_FILE_TYPE::SEXPR_SCHEMATIC ) )
481 return wxTreeItemId();
486 wxDir parentDir( parentTreeItem->
GetDir() );
487 std::vector<wxString> projects =
getProjects( parentDir );
490 return wxTreeItemId();
495 wxTreeItemIdValue cookie;
496 wxTreeItemId kid =
m_TreeProject->GetFirstChild( aParent, cookie );
503 return itemData->GetId();
509 if( type == TREE_FILE_TYPE::LEGACY_PROJECT || type == TREE_FILE_TYPE::JSON_PROJECT
510 || type == TREE_FILE_TYPE::LEGACY_SCHEMATIC || type == TREE_FILE_TYPE::SEXPR_SCHEMATIC )
522 if( fname.GetName().CmpNoCase( currfile.GetName() ) == 0 )
526 case TREE_FILE_TYPE::LEGACY_PROJECT:
527 if( itemData->
GetType() == TREE_FILE_TYPE::JSON_PROJECT )
528 return wxTreeItemId();
532 case TREE_FILE_TYPE::LEGACY_SCHEMATIC:
533 if( itemData->
GetType() == TREE_FILE_TYPE::SEXPR_SCHEMATIC )
534 return wxTreeItemId();
538 case TREE_FILE_TYPE::JSON_PROJECT:
539 if( itemData->
GetType() == TREE_FILE_TYPE::LEGACY_PROJECT )
544 case TREE_FILE_TYPE::SEXPR_SCHEMATIC:
545 if( itemData->
GetType() == TREE_FILE_TYPE::LEGACY_SCHEMATIC )
561 wxTreeItemId newItemId =
m_TreeProject->AppendItem( aParent, file );
568 wxString fileName = currfile.GetName().Lower();
569 wxString projName =
project.GetName().Lower();
571 if( fileName == projName || fileName.StartsWith( projName +
"-" ) )
575 bool subdir_populated =
false;
580 if( TREE_FILE_TYPE::DIRECTORY == type && aRecurse )
586 std::vector<wxString> projects =
getProjects( dir );
587 wxString dir_filename;
588 bool haveFile = dir.GetFirst( &dir_filename );
593 subdir_populated = aRecurse;
599 wxString
path = aName + wxFileName::GetPathSeparator() + dir_filename;
602 haveFile = dir.GetNext( &dir_filename );
611 if( subdir_populated )
648 wxFileName fn = pro_dir;
649 bool prjReset =
false;
660 bool prjOpened = fn.FileExists();
663 if(
Pgm().GetCommonSettings()->m_Git.enableGit )
677 if( !prjOpened && !prjReset )
680 prjOpened = fn.FileExists();
687 m_root =
m_TreeProject->AddRoot( fn.GetFullName(),
static_cast<int>( TREE_FILE_TYPE::ROOT ),
688 static_cast<int>( TREE_FILE_TYPE::ROOT ) );
701 wxDir dir( pro_dir );
705 std::vector<wxString> projects =
getProjects( dir );
707 bool haveFile = dir.GetFirst( &filename );
711 if( filename != fn.GetFullName() )
713 wxString
name = dir.GetName() + wxFileName::GetPathSeparator() + filename;
720 haveFile = dir.GetNext( &filename );
736 wxLogTrace(
traceGit,
"PROJECT_TREE_PANE::ReCreateTreePrj: starting timers" );
750 git_status_options opts;
751 git_status_init_options( &opts, GIT_STATUS_OPTIONS_VERSION );
753 opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
754 opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
755 | GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;
757 git_status_list* status_list =
nullptr;
759 if( git_status_list_new( &status_list, repo, &opts ) != GIT_OK )
766 return ( git_status_list_entrycount( status_list ) > 0 );
772 wxTreeItemId curr_item = Event.GetItem();
779 wxFileName prj_dir(
Prj().GetProjectPath(), wxEmptyString );
781 prj_dir.Normalize( wxPATH_NORM_ABSOLUTE | wxPATH_NORM_CASE | wxPATH_NORM_DOTS
782 | wxPATH_NORM_ENV_VARS | wxPATH_NORM_TILDE );
783 git_dir.Normalize( wxPATH_NORM_ABSOLUTE | wxPATH_NORM_CASE | wxPATH_NORM_DOTS
784 | wxPATH_NORM_ENV_VARS | wxPATH_NORM_TILDE );
785 wxString prj_name = prj_dir.GetFullPath();
786 wxString git_name = git_dir.GetFullPath();
788 bool can_switch_to_project =
true;
789 bool can_create_new_directory =
true;
790 bool can_open_this_directory =
true;
791 bool can_edit =
true;
792 bool can_rename =
true;
793 bool can_delete =
true;
794 bool run_jobs =
false;
798 bool vcs_can_init = !vcs_has_repo;
799 bool vcs_can_remove = vcs_has_repo && git_name.StartsWith( prj_name );
802 bool vcs_can_pull = vcs_can_fetch;
803 bool vcs_can_switch = vcs_has_repo;
807#if ( LIBGIT2_VER_MAJOR >= 1 ) || ( LIBGIT2_VER_MINOR >= 99 )
808 int major, minor, rev;
809 bool libgit_init = ( git_libgit2_version( &major, &minor, &rev ) == GIT_OK );
812 bool libgit_init =
true;
815 vcs_menu &= libgit_init;
817 if( selection.size() == 0 )
821 if( selection.size() != 1 )
823 can_switch_to_project =
false;
824 can_create_new_directory =
false;
833 can_switch_to_project =
false;
839 can_delete = item->CanDelete();
840 can_rename = item->CanRename();
842 switch( item->GetType() )
844 case TREE_FILE_TYPE::JSON_PROJECT:
845 case TREE_FILE_TYPE::LEGACY_PROJECT:
850 can_switch_to_project =
false;
854 can_create_new_directory =
false;
855 can_open_this_directory =
false;
859 case TREE_FILE_TYPE::DIRECTORY:
860 can_switch_to_project =
false;
864 case TREE_FILE_TYPE::ZIP_ARCHIVE:
865 case TREE_FILE_TYPE::PDF:
867 can_switch_to_project =
false;
868 can_create_new_directory =
false;
869 can_open_this_directory =
false;
872 case TREE_FILE_TYPE::JOBSET_FILE:
877 case TREE_FILE_TYPE::SEXPR_SCHEMATIC:
878 case TREE_FILE_TYPE::SEXPR_PCB:
882 can_switch_to_project =
false;
883 can_create_new_directory =
false;
884 can_open_this_directory =
false;
894 if( can_switch_to_project )
897 _(
"Close all editors, and switch to the selected project" ),
898 KiBitmap( BITMAPS::open_project ) );
899 popup_menu.AppendSeparator();
902 if( can_create_new_directory )
905 _(
"Create a New Directory" ),
KiBitmap( BITMAPS::directory ) );
908 if( can_open_this_directory )
910 if( selection.size() == 1 )
913 text =
_(
"Reveal in Finder" );
914 help_text =
_(
"Reveals the directory in a Finder window" );
916 text =
_(
"Open Directory in File Explorer" );
917 help_text =
_(
"Opens the directory in the default system file manager" );
923 text =
_(
"Reveal in Finder" );
924 help_text =
_(
"Reveals the directories in a Finder window" );
926 text =
_(
"Open Directories in File Explorer" );
927 help_text =
_(
"Opens the directories in the default system file manager" );
932 KiBitmap( BITMAPS::directory_browser ) );
937 if( selection.size() == 1 )
938 help_text =
_(
"Open the file in a Text Editor" );
940 help_text =
_(
"Open files in a Text Editor" );
946 if( run_jobs && selection.size() == 1 )
954 if( selection.size() == 1 )
956 text =
_(
"Rename File..." );
957 help_text =
_(
"Rename file" );
961 text =
_(
"Rename Files..." );
962 help_text =
_(
"Rename files" );
971 if( selection.size() == 1 )
972 help_text =
_(
"Delete the file and its content" );
974 help_text =
_(
"Delete the files and their contents" );
976 if( can_switch_to_project
977 || can_create_new_directory
978 || can_open_this_directory
982 popup_menu.AppendSeparator();
996 wxMenu* vcs_submenu =
new wxMenu();
997 wxMenu* branch_submenu =
new wxMenu();
998 wxMenuItem* vcs_menuitem =
nullptr;
1001 _(
"Add Project to Version Control..." ),
1002 _(
"Initialize a new repository" ) );
1003 vcs_menuitem->Enable( vcs_can_init );
1007 _(
"Commit changes to the local repository" ) );
1008 vcs_menuitem->Enable( vcs_can_commit );
1010 vcs_menuitem = vcs_submenu->Append(
ID_GIT_PUSH,
_(
"Push" ),
1011 _(
"Push committed local changes to remote repository" ) );
1012 vcs_menuitem->Enable( vcs_can_push );
1014 vcs_menuitem = vcs_submenu->Append(
ID_GIT_PULL,
_(
"Pull" ),
1015 _(
"Pull changes from remote repository into local" ) );
1016 vcs_menuitem->Enable( vcs_can_pull );
1018 vcs_submenu->AppendSeparator();
1021 _(
"Commit changes to the local repository" ) );
1022 vcs_menuitem->Enable( vcs_can_commit );
1024 vcs_submenu->AppendSeparator();
1033 for(
size_t ii = 1; ii < branchNames.size() && ii < 6; ++ii )
1035 wxString msg =
_(
"Switch to branch " ) + branchNames[ii];
1037 vcs_menuitem->Enable( vcs_can_switch );
1041 _(
"Switch to a different branch" ) );
1042 vcs_menuitem->Enable( vcs_can_switch );
1046 vcs_submenu->AppendSeparator();
1048 vcs_menuitem = vcs_submenu->Append(
ID_GIT_REMOVE_VCS,
_(
"Remove Version Control" ),
1049 _(
"Delete all version control files from the project directory." ) );
1050 vcs_menuitem->Enable( vcs_can_remove );
1052 popup_menu.AppendSeparator();
1053 popup_menu.AppendSubMenu( vcs_submenu,
_(
"Version Control" ) );
1056 if( popup_menu.GetMenuItemCount() > 0 )
1057 PopupMenu( &popup_menu );
1065 if( editorname.IsEmpty() )
1067 wxMessageBox(
_(
"No text editor selected in KiCad. Please choose one." ) );
1075 wxString fullFileName = item_data->GetFileName();
1077 if( !fullFileName.IsEmpty() )
1079 ExecuteFile( editorname, fullFileName.wc_str(),
nullptr,
false );
1090 item_data->Delete();
1100 if( tree_data.size() != 1 )
1104 wxString msg = wxString::Format(
_(
"Change filename: '%s'" ),
1105 tree_data[0]->GetFileName() );
1106 wxTextEntryDialog dlg( wxGetTopLevelParent(
this ), msg,
_(
"Change filename" ), buffer );
1108 if( dlg.ShowModal() != wxID_OK )
1111 buffer = dlg.GetValue();
1112 buffer.Trim(
true );
1113 buffer.Trim(
false );
1115 if( buffer.IsEmpty() )
1118 tree_data[0]->Rename( buffer,
true );
1127 if( tree_data.size() != 1 )
1161 wxTreeItemId itemId = Event.GetItem();
1167 if( tree_data->
GetType() != TREE_FILE_TYPE::DIRECTORY )
1171 wxTreeItemIdValue cookie;
1172 wxTreeItemId kid =
m_TreeProject->GetFirstChild( itemId, cookie );
1175 bool subdir_populated =
false;
1178 for( ; kid.IsOk(); kid =
m_TreeProject->GetNextChild( itemId, cookie ) )
1182 if( !itemData || itemData->
GetType() != TREE_FILE_TYPE::DIRECTORY )
1189 wxDir dir( fileName );
1191 if( dir.IsOpened() )
1193 std::vector<wxString> projects =
getProjects( dir );
1194 wxString dir_filename;
1195 bool haveFile = dir.GetFirst( &dir_filename );
1200 wxString
name = fileName + wxFileName::GetPathSeparator() + dir_filename;
1203 haveFile = dir.GetNext( &dir_filename );
1209 subdir_populated =
true;
1218 if( subdir_populated )
1226 wxArrayTreeItemIds selection;
1227 std::vector<PROJECT_TREE_ITEM*> data;
1231 for(
auto it = selection.begin(); it != selection.end(); it++ )
1237 wxLogTrace(
traceGit, wxS(
"Null tree item returned for selection, dynamic_cast "
1242 data.push_back( item );
1261 if( prj_dir == aSubDir )
1265 wxTreeItemIdValue cookie;
1266 wxTreeItemId root_id =
m_root;
1267 std::stack<wxTreeItemId> subdirs_id;
1269 wxTreeItemId child =
m_TreeProject->GetFirstChild( root_id, cookie );
1273 if( ! child.IsOk() )
1275 if( subdirs_id.empty() )
1282 root_id = subdirs_id.top();
1293 if( itemData && ( itemData->
GetType() == TREE_FILE_TYPE::DIRECTORY ) )
1303 subdirs_id.push( child );
1321 if( !( event.GetChangeType() & ( wxFSW_EVENT_CREATE |
1322 wxFSW_EVENT_DELETE |
1323 wxFSW_EVENT_RENAME |
1324 wxFSW_EVENT_MODIFY ) ) )
1329 const wxFileName& pathModified =
event.GetPath();
1330 wxString subdir = pathModified.GetPath();
1331 wxString fn = pathModified.GetFullPath();
1334 if( pathModified.GetFullName().IsEmpty() )
1336 subdir = subdir.BeforeLast(
'/' );
1337 fn = fn.BeforeLast(
'/' );
1342 if( !root_id.IsOk() )
1345 CallAfter( [
this] ()
1347 wxLogTrace(
traceGit, wxS(
"File system event detected, updating tree cache" ) );
1351 wxTreeItemIdValue cookie;
1352 wxTreeItemId kid =
m_TreeProject->GetFirstChild( root_id, cookie );
1354 switch( event.GetChangeType() )
1356 case wxFSW_EVENT_CREATE:
1371 case wxFSW_EVENT_DELETE:
1385 case wxFSW_EVENT_RENAME :
1387 const wxFileName& newpath =
event.GetNewPath();
1388 wxString newdir = newpath.GetPath();
1389 wxString newfn = newpath.GetFullPath();
1413 if( rootData && newpath.Exists() && ( newfn != rootData->
GetFileName() ) )
1419 if( newitem.IsOk() )
1442#if defined( _WIN32 )
1475 fn.AssignDir( prj_dir );
1476 fn.DontFollowLink();
1490 TO_UTF8( fn.GetFullPath() ) );
1498 TO_UTF8( fn.GetFullPath() ) );
1503 if( m_TreeProject->IsEmpty() )
1507 wxTreeItemIdValue cookie;
1508 wxTreeItemId root_id = m_root;
1510 std::stack < wxTreeItemId > subdirs_id;
1512 wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie );
1513 int total_watch_count = 0;
1519 if( subdirs_id.empty() )
1525 root_id = subdirs_id.top();
1527 kid = m_TreeProject->GetFirstChild( root_id, cookie );
1543 if( wxFileName::IsDirReadable(
path ) )
1548 fn.AssignDir(
path );
1549 m_watcher->Add( fn );
1550 total_watch_count++;
1554 if( itemData->
IsPopulated() && m_TreeProject->GetChildrenCount( kid ) )
1555 subdirs_id.push( kid );
1559 kid = m_TreeProject->GetNextChild( root_id, cookie );
1566#if defined(DEBUG) && 1
1567 wxArrayString paths;
1568 m_watcher->GetWatchedPaths( &paths );
1571 for(
unsigned ii = 0; ii < paths.GetCount(); ii++ )
1605 wxRect rect( wxPoint( 0, 0 ), GetClientSize() );
1606 wxPaintDC dc(
this );
1608 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
1609 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ), 1 ) );
1611 dc.DrawLine( rect.GetLeft(), rect.GetTop(), rect.GetLeft(), rect.GetBottom() );
1612 dc.DrawLine( rect.GetRight(), rect.GetTop(), rect.GetRight(), rect.GetBottom() );
1626 wxString dir = tree_data->
GetDir();
1630 wxLogError(
"Failed to initialize git project: project directory is empty." );
1635 git_repository* repo =
nullptr;
1636 int error = git_repository_open( &repo, dir.mb_str() );
1641 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
1644 _(
"The selected directory is already a Git project." ) );
1645 git_repository_free( repo );
1652 dlg.SetTitle(
_(
"Set default remote" ) );
1658 if( git_repository_init( &repo, dir.mb_str(), 0 ) != GIT_OK )
1680 git_remote* remote =
nullptr;
1689 fullURL = dlg.
GetRepoURL().StartsWith(
"https" ) ?
"https://" :
"http://";
1697 fullURL.append( wxS(
":" ) );
1701 fullURL.append( wxS(
"@" ) );
1712 error = git_remote_create_with_fetchspec( &remote, repo,
"origin",
1713 fullURL.ToStdString().c_str(),
1714 "+refs/heads/*:refs/remotes/origin/*" );
1716 if( error != GIT_OK )
1733 _(
"Fetching Remote" ),
1767 _(
"Fetching Remote" ),
1791 _(
"Fetching Remote" ),
1794 if( handler.
PerformPush() != PushResult::Success )
1809 if(
int error = git_reference_name_to_id( &head_oid, aRepo,
"HEAD" ) != GIT_OK )
1816 git_commit* commit =
nullptr;
1818 if(
int error = git_commit_lookup( &commit, aRepo, &head_oid ) != GIT_OK )
1825 git_reference* branchRef =
nullptr;
1827 if(
int error = git_branch_create( &branchRef, aRepo, aBranchName.mb_str(), commit, 0 ) != GIT_OK )
1833 git_reference_free( branchRef );
1846 wxString branchName;
1855 if( retval == wxID_ADD )
1857 else if( retval != wxID_OK )
1865 if( branchIndex < 0 ||
static_cast<size_t>( branchIndex ) >= branches.size() )
1868 branchName = branches[branchIndex];
1872 git_reference* branchRef =
nullptr;
1874 if( git_reference_lookup( &branchRef, repo, branchName.mb_str() ) != GIT_OK &&
1875 git_reference_dwim( &branchRef, repo, branchName.mb_str() ) != GIT_OK )
1877 wxString errorMessage = wxString::Format(
_(
"Failed to lookup branch '%s': %s" ),
1884 const char* branchRefName = git_reference_name( branchRef );
1885 git_object* branchObj =
nullptr;
1887 if( git_revparse_single( &branchObj, repo, branchName.mb_str() ) != 0 )
1889 wxString errorMessage =
1890 wxString::Format(
_(
"Failed to find branch head for '%s'" ), branchName );
1898 if( git_checkout_tree( repo, branchObj,
nullptr ) != 0 )
1900 wxString errorMessage =
1901 wxString::Format(
_(
"Failed to switch to branch '%s'" ), branchName );
1907 if( git_repository_set_head( repo, branchRefName ) != 0 )
1909 wxString errorMessage = wxString::Format(
1910 _(
"Failed to update HEAD reference for branch '%s'" ), branchName );
1922 || !
IsOK( wxGetTopLevelParent(
this ),
1923 _(
"Are you sure you want to remove Git tracking from this project?" ) ) )
1929 git_repository_free( repo );
1934 fn.AppendDir(
".git" );
1944 std::stack<wxTreeItemId> items;
1947 while( !items.empty() )
1949 wxTreeItemId current = items.top();
1953 m_TreeProject->SetItemState( current, wxTREE_ITEMSTATE_NONE );
1955 wxTreeItemIdValue cookie;
1956 wxTreeItemId child =
m_TreeProject->GetFirstChild( current, cookie );
1958 while( child.IsOk() )
1960 items.push( child );
1969 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Updating git status icons" ) );
1972 if( !lock.owns_lock() )
1974 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Failed to acquire lock for git status icon update" ) );
1981 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Git is disabled or tree control is null" ) );
1985 std::stack<wxTreeItemId> items;
1988 while( !items.empty() )
1990 wxTreeItemId current = items.top();
1995 wxTreeItemIdValue cookie;
1996 wxTreeItemId child =
m_TreeProject->GetFirstChild( current, cookie );
1998 while( child.IsOk() )
2000 items.push( child );
2004 m_TreeProject->SetItemState( child,
static_cast<int>( it->second ) );
2016 wxString filename = wxFileNameFromPath( rootItem->
GetFileName() );
2021 wxLogTrace(
traceGit, wxS(
"updateGitStatusIcons: Git status icons updated" ) );
2027 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Updating tree cache" ) );
2031 if( !lock.owns_lock() )
2033 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Failed to acquire lock for tree cache update" ) );
2039 wxLogTrace(
traceGit, wxS(
"updateTreeCache: Tree control is null" ) );
2050 std::stack<wxTreeItemId> items;
2053 while( !items.empty() )
2062 gitAbsPath.Replace( wxS(
"\\" ), wxS(
"/" ) );
2066 wxTreeItemIdValue cookie;
2067 wxTreeItemId child =
m_TreeProject->GetFirstChild( kid, cookie );
2069 while( child.IsOk() )
2071 items.push( child );
2080 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Updating git status icons" ) );
2081#if defined( _WIN32 )
2104 if( !lock1.owns_lock() || !lock2.owns_lock() )
2106 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Failed to acquire locks for git status icon update" ) );
2114 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: No git repository found" ) );
2120 wxFileName rootFilename( rootItem->
GetFileName() );
2121 wxString repoWorkDir( git_repository_workdir( repo ) );
2123 wxFileName relative = rootFilename;
2124 relative.MakeRelativeTo( repoWorkDir );
2125 wxString pathspecStr = relative.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
2128 pathspecStr.Replace( wxS(
"\\" ), wxS(
"/" ) );
2131 const char* pathspec[] = { pathspecStr.c_str().AsChar() };
2133 git_status_options status_options;
2134 git_status_init_options( &status_options, GIT_STATUS_OPTIONS_VERSION );
2135 status_options.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
2136 status_options.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
2137 status_options.pathspec = { (
char**) pathspec, 1 };
2139 git_index* index =
nullptr;
2141 if( git_repository_index( &index, repo ) != GIT_OK )
2149 git_status_list* status_list =
nullptr;
2151 if( git_status_list_new( &status_list, repo, &status_options ) != GIT_OK )
2160 size_t count = git_status_list_entrycount( status_list );
2161 bool updated =
false;
2163 for(
size_t ii = 0; ii < count; ++ii )
2165 const git_status_entry* entry = git_status_byindex( status_list, ii );
2166 std::string
path( entry->head_to_index? entry->head_to_index->old_file.path
2167 : entry->index_to_workdir->old_file.path );
2169 wxString absPath = repoWorkDir;
2176 wxLogTrace(
traceGit, wxS(
"File '%s' not found in tree cache" ), absPath );
2183 if( entry->status & GIT_STATUS_IGNORED )
2185 wxLogTrace(
traceGit, wxS(
"File '%s' is ignored" ), absPath );
2194 else if( entry->status & ( GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED ) )
2196 wxLogTrace(
traceGit, wxS(
"File '%s' is modified in %s" ),
2197 absPath, ( entry->status & GIT_STATUS_INDEX_MODIFIED )?
"index" :
"working tree" );
2206 else if( entry->status & ( GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_NEW ) )
2208 wxLogTrace(
traceGit, wxS(
"File '%s' is new in %s" ),
2209 absPath, ( entry->status & GIT_STATUS_INDEX_NEW )?
"index" :
"working tree" );
2218 else if( entry->status & ( GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_DELETED ) )
2220 wxLogTrace(
traceGit, wxS(
"File '%s' is deleted in %s" ),
2221 absPath, ( entry->status & GIT_STATUS_INDEX_DELETED )?
"index" :
"working tree" );
2230 else if( localChanges.count(
path ) )
2232 wxLogTrace(
traceGit, wxS(
"File '%s' is ahead of remote" ), absPath );
2241 else if( remoteChanges.count(
path ) )
2243 wxLogTrace(
traceGit, wxS(
"File '%s' is behind remote" ), absPath );
2265 git_reference* currentBranchReference =
nullptr;
2266 int rc = git_repository_head( ¤tBranchReference, repo );
2270 if( currentBranchReference )
2274 else if( rc == GIT_EUNBORNBRANCH )
2287 wxLogTrace(
traceGit, wxS(
"updateGitStatusIconMap: Updated git status icons" ) );
2306 if( repo ==
nullptr )
2308 wxMessageBox(
_(
"The selected directory is not a Git project." ) );
2312 git_config*
config =
nullptr;
2313 git_repository_config( &
config, repo );
2317 wxString authorName;
2318 wxString authorEmail;
2321 git_config_entry* name_c =
nullptr;
2322 git_config_entry* email_c =
nullptr;
2323 int authorNameError = git_config_get_entry( &name_c,
config,
"user.name" );
2326 if( authorNameError != 0 || name_c ==
nullptr )
2332 authorName = name_c->value;
2336 int authorEmailError = git_config_get_entry( &email_c,
config,
"user.email" );
2338 if( authorEmailError != 0 || email_c ==
nullptr )
2344 authorEmail = email_c->value;
2348 git_status_options status_options;
2349 git_status_init_options( &status_options, GIT_STATUS_OPTIONS_VERSION );
2350 status_options.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
2351 status_options.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED;
2353 git_status_list* status_list =
nullptr;
2354 git_status_list_new( &status_list, repo, &status_options );
2357 std::map<wxString, int> modifiedFiles;
2359 size_t count = git_status_list_entrycount( status_list );
2361 std::set<wxString> selected_files;
2365 if( item->GetType() != TREE_FILE_TYPE::DIRECTORY )
2366 selected_files.emplace( item->GetFileName() );
2369 for(
size_t i = 0; i < count; ++i )
2371 const git_status_entry* entry = git_status_byindex( status_list, i );
2374 if( entry->status == GIT_STATUS_CURRENT
2375 || ( entry->status & ( GIT_STATUS_CONFLICTED | GIT_STATUS_IGNORED ) ) )
2386 if( entry->index_to_workdir )
2388 fn.Assign( entry->index_to_workdir->old_file.path );
2389 fn.MakeAbsolute( git_repository_workdir( repo ) );
2390 filePath = wxString( entry->index_to_workdir->old_file.path, wxConvUTF8 );
2392 else if( entry->head_to_index )
2394 fn.Assign( entry->head_to_index->old_file.path );
2395 fn.MakeAbsolute( git_repository_workdir( repo ) );
2396 filePath = wxString( entry->head_to_index->old_file.path, wxConvUTF8 );
2400 wxCHECK2_MSG(
false,
continue,
"File status with neither git_status_entry set!" );
2405 wxString fileName = fn.GetFullPath();
2407 if( !fileName.StartsWith( projectPath ) )
2423 if( fn.GetPath().Contains(
Prj().GetProjectName() + wxT(
"-backups" ) ) )
2428 modifiedFiles.emplace( filePath, entry->status );
2430 else if( selected_files.count( fn.GetFullPath() ) )
2432 modifiedFiles.emplace( filePath, entry->status );
2437 DIALOG_GIT_COMMIT dlg( wxGetTopLevelParent(
this ), repo, authorName, authorEmail,
2441 if( ret != wxID_OK )
2446 git_tree* tree =
nullptr;
2447 git_commit* parent =
nullptr;
2448 git_index* index =
nullptr;
2454 wxMessageBox(
_(
"Discarding commit due to empty commit message." ) );
2460 wxMessageBox(
_(
"Discarding commit due to empty file selection." ) );
2464 if( git_repository_index( &index, repo ) != 0 )
2466 wxLogTrace(
traceGit, wxString::Format(
_(
"Failed to get repository index: %s" ),
2473 for( wxString& file : files )
2475 if( git_index_add_bypath( index, file.mb_str() ) != 0 )
2477 wxMessageBox( wxString::Format(
_(
"Failed to add file to index: %s" ),
2483 if( git_index_write( index ) != 0 )
2485 wxLogTrace(
traceGit, wxString::Format(
_(
"Failed to write index: %s" ),
2490 if( git_index_write_tree( &tree_id, index ) != 0)
2492 wxLogTrace(
traceGit, wxString::Format(
_(
"Failed to write tree: %s" ),
2497 if( git_tree_lookup( &tree, repo, &tree_id ) != 0 )
2499 wxLogTrace(
traceGit, wxString::Format(
_(
"Failed to lookup tree: %s" ),
2505 git_reference* headRef =
nullptr;
2507 if( git_repository_head_unborn( repo ) == 0 )
2509 if( git_repository_head( &headRef, repo ) != 0 )
2511 wxLogTrace(
traceGit, wxString::Format(
_(
"Failed to get HEAD reference: %s" ),
2518 if( git_reference_peel( (git_object**) &parent, headRef, GIT_OBJECT_COMMIT ) != 0 )
2520 wxLogTrace(
traceGit, wxString::Format(
_(
"Failed to get commit: %s" ),
2531 git_signature* author =
nullptr;
2533 if( git_signature_now( &author, author_name.mb_str(), author_email.mb_str() ) != 0 )
2535 wxLogTrace(
traceGit, wxString::Format(
_(
"Failed to create author signature: %s" ),
2543#if( LIBGIT2_VER_MAJOR == 1 && LIBGIT2_VER_MINOR == 8 \
2544 && ( LIBGIT2_VER_REVISION < 2 || LIBGIT2_VER_REVISION == 3 ) )
2563 git_commit*
const parents[1] = { parent };
2566 const git_commit* parents[1] = { parent };
2569 if( git_commit_create( &oid, repo,
"HEAD", author, author,
nullptr, commit_msg.mb_str(), tree,
2572 wxMessageBox( wxString::Format(
_(
"Failed to create commit: %s" ),
2577 wxLogTrace(
traceGit, wxString::Format(
_(
"Created commit with id: %s" ),
2578 git_oid_tostr_s( &oid ) ) );
2600 if( git_repository_index( &index, repo ) != 0 )
2609 if( git_index_find( &entry_pos, index, aFile.mb_str() ) == 0 )
2611 wxLogTrace(
traceGit,
"File already in index: %s", aFile );
2621 wxLogTrace(
traceGit,
"Syncing project" );
2626 wxLogTrace(
traceGit,
"sync: No git repository found" );
2693 wxLogTrace(
traceGit,
"onGitSyncTimer" );
2701 tp.push_task( [
this]()
2707 wxLogTrace(
traceGit,
"onGitSyncTimer: No git repository found" );
2722 wxLogTrace(
traceGit,
"onGitSyncTimer: Restarting git sync timer" );
2743 wxLogTrace(
traceGit,
"onGitStatusTimer" );
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
BITMAP_STORE * GetBitmapStore()
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void ThemeChanged()
Notifies the store that the icon theme has been changed by the user, so caches must be invalidated.
wxString GetCommitMessage() const
wxString GetAuthorEmail() const
std::vector< wxString > GetSelectedFiles() const
wxString GetAuthorName() const
KIGIT_COMMON::GIT_CONN_TYPE GetRepoType() const
wxString GetBareRepoURL() const
Get the Bare Repo U R L object.
wxString GetRepoSSHPath() const
wxString GetRepoURL() const
wxString GetUsername() const
wxString GetPassword() const
wxString GetBranchName() const
void SetProgressReporter(std::unique_ptr< WX_PROGRESS_REPORTER > aProgressReporter)
bool PerformFetch(bool aSkipLock=false)
void PerformRemoveFromIndex()
bool PerformResolveConflict()
The main KiCad project manager frame.
wxString m_FileWatcherInfo
PROJECT_TREE_PANE * m_leftWin
const wxString GetProjectFileName() const
void OnChangeWatchedPaths(wxCommandEvent &aEvent)
Called by sending a event with id = ID_INIT_WATCHED_PATHS rebuild the list of watched paths.
void LoadProject(const wxFileName &aProjectFileName)
std::vector< wxString > GetBranchNames() const
static wxString GetLastGitError()
wxString GetGitRootDirectory() const
void SetSSHKey(const wxString &aSSHKey)
void SetUsername(const wxString &aUsername)
std::pair< std::set< wxString >, std::set< wxString > > GetDifferentFiles() const
Return a pair of sets of files that differ locally from the remote repository The first set is files ...
bool HasPushAndPullRemote() const
void UpdateCurrentBranchInfo()
bool HasLocalCommits() const
void SetPassword(const wxString &aPassword)
wxString GetErrorString()
KISTATUSBAR is a wxStatusBar suitable for Kicad manager.
void SetEllipsedTextField(const wxString &aText, int aFieldId)
Set the text in a field using wxELLIPSIZE_MIDDLE option to adjust the text size to the field size.
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
virtual COMMON_SETTINGS * GetCommonSettings() const
virtual const wxString & GetTextEditor(bool aCanShowFileChooser=true)
Return the path to the preferred text editor application.
wxString m_GitRepoUsername
Handle one item (a file or a directory name) for the tree file.
void SetRootFile(bool aValue)
const wxString & GetFileName() const
void SetPopulated(bool aValue)
TREE_FILE_TYPE GetType() const
const wxString GetDir() const
void Activate(PROJECT_TREE_PANE *aTreePrjFrame)
PROJECT_TREE_PANE Window to display the tree files.
PROJECT_TREE_ITEM * m_selectedItem
std::unordered_map< wxString, wxTreeItemId > m_gitTreeCache
void onGitFetch(wxCommandEvent &event)
Fetch the latest changes from the git repository.
std::map< wxTreeItemId, KIGIT_COMMON::GIT_STATUS > m_gitStatusIcons
void onGitInitializeProject(wxCommandEvent &event)
Initialize a new git repository in the current project directory.
void onGitSyncProject(wxCommandEvent &event)
Sync the current project with the git repository.
void onDeleteFile(wxCommandEvent &event)
Function onDeleteFile Delete the selected file or directory in the tree project.
void onGitRemoveVCS(wxCommandEvent &event)
Remove the git repository from the current project directory.
void EmptyTreePrj()
Delete all m_TreeProject entries.
void FileWatcherReset()
Reinit the watched paths Should be called after opening a new project to rebuild the list of watched ...
wxString m_gitCurrentBranchName
std::vector< PROJECT_TREE_ITEM * > GetSelectedData()
Function GetSelectedData return the item data from item currently selected (highlighted) Note this is...
void onOpenDirectory(wxCommandEvent &event)
Function onOpenDirectory Handles the right-click menu for opening a directory in the current system f...
void onGitResolveConflict(wxCommandEvent &event)
Resolve conflicts in the git repository.
void onFileSystemEvent(wxFileSystemWatcherEvent &event)
called when a file or directory is modified/created/deleted The tree project is modified when a file ...
wxFileSystemWatcher * m_watcher
void onRight(wxTreeEvent &Event)
Called on a right click on an item.
void onGitCommit(wxCommandEvent &event)
Commit the current project saved changes to the git repository.
void onSelect(wxTreeEvent &Event)
Called on a double click on an item.
PROJECT_TREE * m_TreeProject
KICAD_MANAGER_FRAME * m_Parent
void onExpand(wxTreeEvent &Event)
Called on a click on the + or - button of an item with children.
void onGitSyncTimer(wxTimerEvent &event)
void onIdle(wxIdleEvent &aEvent)
Idle event handler, used process the selected items at a point in time when all other events have bee...
void updateTreeCache()
Updates the map of the wxtreeitemid to the name of each file for use in the thread.
void gitStatusTimerHandler()
std::mutex m_gitStatusMutex
void onGitRevertLocal(wxCommandEvent &event)
Revert the local repository to the last commit.
void onGitPullProject(wxCommandEvent &event)
Pull the latest changes from the git repository.
static wxString GetFileExt(TREE_FILE_TYPE type)
friend class PROJECT_TREE_ITEM
void onGitRemoveFromIndex(wxCommandEvent &event)
Remove a file from the git index.
wxTreeItemId findSubdirTreeItem(const wxString &aSubDir)
Function findSubdirTreeItem searches for the item in tree project which is the node of the subdirecto...
void ReCreateTreePrj()
Create or modify the tree showing project file names.
void onThemeChanged(wxSysColourChangedEvent &aEvent)
void onRunSelectedJobsFile(wxCommandEvent &event)
Run a selected jobs file.
void onGitCompare(wxCommandEvent &event)
Compare the current project to a different branch in the git repository.
void onGitStatusTimer(wxTimerEvent &event)
void shutdownFileWatcher()
Shutdown the file watcher.
std::mutex m_gitTreeCacheMutex
wxTreeItemId addItemToProjectTree(const wxString &aName, const wxTreeItemId &aParent, std::vector< wxString > *aProjectNames, bool aRecurse)
Function addItemToProjectTree.
bool hasChangedFiles()
Returns true if the current project has any uncommitted changes.
void onOpenSelectedFileWithTextEditor(wxCommandEvent &event)
Function onOpenSelectedFileWithTextEditor Call the text editor to open the selected file in the tree ...
void onGitAddToIndex(wxCommandEvent &event)
Add a file to the git index.
void updateGitStatusIcons()
Updates the icons shown in the tree project to reflect the current git status.
bool m_gitIconsInitialized
void updateGitStatusIconMap()
This is a threaded call that will change the map of git status icons for use in the main thread.
PROJECT_TREE_ITEM * GetItemIdData(wxTreeItemId aId)
Function GetItemIdData return the item data corresponding to a wxTreeItemId identifier.
void onGitSwitchBranch(wxCommandEvent &event)
Switch to a different branch in the git repository.
void onCreateNewDirectory(wxCommandEvent &event)
Function onCreateNewDirectory Creates a new subdirectory inside the current kicad project directory t...
void onSwitchToSelectedProject(wxCommandEvent &event)
Switch to a other project selected from the tree project (by selecting an other .pro file inside the ...
void onPaint(wxPaintEvent &aEvent)
We don't have uniform borders so we have to draw them ourselves.
void onRenameFile(wxCommandEvent &event)
Function onRenameFile Rename the selected file or directory in the tree project.
void onGitPushProject(wxCommandEvent &event)
Push the current project changes to the git repository.
bool canFileBeAddedToVCS(const wxString &aFilePath)
Returns true if the file has already been added to the repository or false if it has not been added y...
std::vector< wxString > m_filters
PROJECT_TREE This is the class to show (as a tree) the files in the project directory.
git_repository * GetGitRepo() const
KIGIT_COMMON * GitCommon() const
void SetGitRepo(git_repository *aRepo)
virtual const wxString GetProjectPath() const
Return the full path of the project.
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
This file is part of the common library.
EVT_MENU_RANGE(ID_GERBVIEW_DRILL_FILE1, ID_GERBVIEW_DRILL_FILEMAX, GERBVIEW_FRAME::OnDrlFileHistory) EVT_MENU_RANGE(ID_GERBVIEW_ZIP_FILE1
int ExecuteFile(const wxString &aEditorName, const wxString &aFileName, wxProcess *aCallback, bool aFileForKicad)
Call the executable file aEditorName with the parameter aFileName.
bool RmDirRecursive(const wxString &aFileName, wxString *aErrors)
Remove the directory aDirName and all its contents including subdirectories and their files.
int m_GitIconRefreshInterval
The interval in milliseconds to refresh the git icons in the project tree.
static const std::string LegacySchematicFileExtension
static const std::string HtmlFileExtension
static const wxString GerberFileExtensionsRegex
static const std::string NetlistFileExtension
static const std::string GerberJobFileExtension
static const std::string ReportFileExtension
static const std::string LockFileExtension
static const std::string ProjectFileExtension
static const std::string FootprintPlaceFileExtension
static const std::string LegacyPcbFileExtension
static const std::string LegacyProjectFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string LegacySymbolLibFileExtension
static const std::string LockFilePrefix
static const std::string KiCadSymbolLibFileExtension
static const std::string SpiceFileExtension
static const std::string PdfFileExtension
static const std::string TextFileExtension
static const std::string DrawingSheetFileExtension
static const std::string BackupFileSuffix
static const std::string AutoSaveFilePrefix
static const std::string KiCadJobSetFileExtension
static const std::string FootprintAssignmentFileExtension
static const std::string SVGFileExtension
static const std::string DrillFileExtension
static const std::string DesignRulesFileExtension
static const std::string MarkdownFileExtension
static const std::string KiCadFootprintFileExtension
static const std::string ArchiveFileExtension
static const std::string KiCadPcbFileExtension
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
const wxChar *const traceGit
Flag to enable Git debugging output.
IDs used in KiCad main frame foe menuitems and tools.
@ ID_PROJECT_SWITCH_TO_OTHER
@ ID_GIT_REMOVE_FROM_INDEX
@ ID_GIT_RESOLVE_CONFLICT
@ ID_GIT_INITIALIZE_PROJECT
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
std::unique_ptr< git_object, decltype([](git_object *aObject) { git_object_free(aObject) GitObjectPtr
A unique pointer for git_object objects with automatic cleanup.
std::unique_ptr< git_status_list, decltype([](git_status_list *aList) { git_status_list_free(aList) GitStatusListPtr
A unique pointer for git_status_list objects with automatic cleanup.
std::unique_ptr< git_commit, decltype([](git_commit *aCommit) { git_commit_free(aCommit) GitCommitPtr
A unique pointer for git_commit objects with automatic cleanup.
std::unique_ptr< git_buf, decltype([](git_buf *aBuf) { git_buf_free(aBuf) GitBufPtr
A unique pointer for git_buf objects with automatic cleanup.
std::unique_ptr< git_tree, decltype([](git_tree *aTree) { git_tree_free(aTree) GitTreePtr
A unique pointer for git_tree objects with automatic cleanup.
std::unique_ptr< git_config_entry, decltype([](git_config_entry *aEntry) { git_config_entry_free(aEntry) GitConfigEntryPtr
A unique pointer for git_config_entry objects with automatic cleanup.
std::unique_ptr< git_index, decltype([](git_index *aIndex) { git_index_free(aIndex) GitIndexPtr
A unique pointer for git_index objects with automatic cleanup.
std::unique_ptr< git_signature, decltype([](git_signature *aSignature) { git_signature_free(aSignature) GitSignaturePtr
A unique pointer for git_signature objects with automatic cleanup.
std::unique_ptr< git_repository, decltype([](git_repository *aRepo) { git_repository_free(aRepo) GitRepositoryPtr
A unique pointer for git_repository objects with automatic cleanup.
std::unique_ptr< git_config, decltype([](git_config *aConfig) { git_config_free(aConfig) GitConfigPtr
A unique pointer for git_config objects with automatic cleanup.
std::unique_ptr< git_reference, decltype([](git_reference *aRef) { git_reference_free(aRef) GitReferencePtr
A unique pointer for git_reference objects with automatic cleanup.
KICOMMON_API wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmapBundle &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
PGM_BASE & Pgm()
The global program "get" accessor.
#define NAMELESS_PROJECT
default name for nameless projects
std::vector< wxString > getProjects(const wxDir &dir)
static git_repository * get_git_repository_for_file(const char *filename)
static const wxChar * s_allowedExtensionsToList[]
static int git_create_branch(git_repository *aRepo, wxString &aBranchName)
wxDECLARE_EVENT(UPDATE_ICONS, wxCommandEvent)
The frame that shows the tree list of files and subdirectories inside the working directory.
#define wxFileSystemWatcher
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::thread_pool thread_pool
wxLogTrace helper definitions.
Definition of file extensions used in Kicad.