26#include <wx/filename.h>
32 m_repo( aRepo ), m_connType(
GIT_CONN_TYPE::GIT_CONN_LOCAL ), m_testedTypes( 0 )
45 git_reference* head =
nullptr;
47 int retval = git_repository_head( &head,
m_repo );
49 if( retval && retval != GIT_EUNBORNBRANCH && retval != GIT_ENOTFOUND )
52 git_reference *branch;
54 if( git_reference_resolve( &branch, head ) )
56 git_reference_free( head );
60 git_reference_free( head );
61 const char* branchName =
"";
63 if( git_branch_name( &branchName, branch ) )
65 git_reference_free( branch );
69 git_reference_free( branch );
77 std::vector<wxString> branchNames;
78 std::map<git_time_t, wxString> branchNamesMap;
81 git_branch_iterator* branchIterator =
nullptr;
83 if( git_branch_iterator_new( &branchIterator,
m_repo, GIT_BRANCH_LOCAL ) )
86 git_reference* branchReference =
nullptr;
87 git_branch_t branchType;
89 while( git_branch_next( &branchReference, &branchType, branchIterator ) != GIT_ITEROVER )
91 const char* branchName =
"";
93 if( git_branch_name( &branchName, branchReference ) )
96 const git_oid* commitId = git_reference_target( branchReference );
98 git_commit* commit =
nullptr;
100 if( git_commit_lookup( &commit,
m_repo, commitId ) )
103 git_time_t commitTime = git_commit_time( commit );
105 if( git_branch_is_head( branchReference ) )
106 firstName = branchName;
108 branchNamesMap.emplace( commitTime, branchName );
110 git_commit_free( commit );
111 git_reference_free( branchReference );
114 git_branch_iterator_free( branchIterator );
117 if( !firstName.IsEmpty() )
118 branchNames.push_back( firstName );
121 for(
auto rit = branchNamesMap.rbegin(); rit != branchNamesMap.rend(); ++rit )
122 branchNames.push_back( rit->second );
130 std::vector<wxString> projDirs;
136 if( git_reference_name_to_id( &oid,
m_repo,
"HEAD" ) != GIT_OK )
138 wxLogError(
"An error occurred: %s", git_error_last()->message );
142 if( git_commit_lookup( &commit,
m_repo, &oid ) != GIT_OK )
144 wxLogError(
"An error occurred: %s", git_error_last()->message );
148 if( git_commit_tree( &tree, commit ) != GIT_OK )
150 wxLogError(
"An error occurred: %s", git_error_last()->message );
156 tree, GIT_TREEWALK_PRE,
157 [](
const char* root,
const git_tree_entry* entry,
void* payload )
159 std::vector<wxString>* prjs =
static_cast<std::vector<wxString>*
>( payload );
160 wxFileName root_fn( git_tree_entry_name( entry ) );
162 root_fn.SetPath( root );
164 if( git_tree_entry_type( entry ) == GIT_OBJECT_BLOB
165 && ( ( root_fn.GetExt() ==
"kicad_pro" ) || ( root_fn.GetExt() ==
"pro" ) ) )
167 prjs->push_back( root_fn.GetFullPath() );
174 git_tree_free( tree );
175 git_commit_free( commit );
177 std::sort( projDirs.begin(), projDirs.end(),
178 [](
const wxString& a,
const wxString& b )
180 int a_freq = a.Freq( wxFileName::GetPathSeparator() );
181 int b_freq = b.Freq( wxFileName::GetPathSeparator() );
183 if( a_freq == b_freq )
186 return a_freq < b_freq;
196 auto get_modified_files = [&]( git_oid* from_oid, git_oid* to_oid ) -> std::set<wxString>
198 std::set<wxString> modified_set;
199 git_revwalk* walker =
nullptr;
201 if( git_revwalk_new( &walker,
m_repo ) != GIT_OK )
204 if( ( git_revwalk_push( walker, from_oid ) != GIT_OK )
205 || ( git_revwalk_hide( walker, to_oid ) != GIT_OK ) )
207 git_revwalk_free( walker );
215 while( git_revwalk_next( &oid, walker ) == GIT_OK )
217 if( git_commit_lookup( &commit,
m_repo, &oid ) != GIT_OK )
220 git_tree *tree, *parent_tree =
nullptr;
221 if( git_commit_tree( &tree, commit ) != GIT_OK )
223 git_commit_free( commit );
228 if( !git_commit_parentcount( commit ) )
230 git_tree_free( tree );
231 git_commit_free( commit );
237 if( git_commit_parent( &parent, commit, 0 ) != GIT_OK )
239 git_tree_free( tree );
240 git_commit_free( commit );
245 if( git_commit_tree( &parent_tree, parent ) != GIT_OK )
247 git_tree_free( tree );
248 git_commit_free( commit );
249 git_commit_free( parent );
255 git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
257 if( git_diff_tree_to_tree( &diff,
m_repo, parent_tree, tree, &diff_opts ) == GIT_OK )
259 size_t num_deltas = git_diff_num_deltas( diff );
261 for(
size_t i = 0; i < num_deltas; ++i )
263 const git_diff_delta*
delta = git_diff_get_delta( diff, i );
264 modified_set.insert(
delta->new_file.path );
267 git_diff_free( diff );
270 git_tree_free( parent_tree );
271 git_commit_free( parent );
272 git_tree_free( tree );
273 git_commit_free( commit );
276 git_revwalk_free( walker );
281 std::pair<std::set<wxString>,std::set<wxString>> modified_files;
284 return modified_files;
286 git_reference* head =
nullptr;
287 git_reference* remote_head =
nullptr;
289 if( git_repository_head( &head,
m_repo ) != GIT_OK )
290 return modified_files;
292 if( git_branch_upstream( &remote_head, head ) != GIT_OK )
294 git_reference_free( head );
295 return modified_files;
298 git_oid head_oid = *git_reference_target( head );
299 git_oid remote_oid = *git_reference_target( remote_head );
301 git_reference_free( head );
302 git_reference_free( remote_head );
304 modified_files.first = get_modified_files( &head_oid, &remote_oid );
305 modified_files.second = get_modified_files( &remote_oid, &head_oid );
307 return modified_files;
316 git_reference* head =
nullptr;
317 git_reference* remote_head =
nullptr;
319 if( git_repository_head( &head,
m_repo ) != GIT_OK )
322 if( git_branch_upstream( &remote_head, head ) != GIT_OK )
324 git_reference_free( head );
328 git_oid head_oid = *git_reference_target( head );
329 git_oid remote_oid = *git_reference_target( remote_head );
331 git_reference_free( head );
332 git_reference_free( remote_head );
334 git_revwalk* walker =
nullptr;
336 if( git_revwalk_new( &walker,
m_repo ) != GIT_OK )
339 if( ( git_revwalk_push( walker, &head_oid ) != GIT_OK )
340 || ( git_revwalk_hide( walker, &remote_oid ) != GIT_OK ) )
342 git_revwalk_free( walker );
349 if( git_revwalk_next( &oid, walker ) != GIT_OK )
351 git_revwalk_free( walker );
355 git_revwalk_free( walker );
362 git_remote* remote =
nullptr;
364 if( git_remote_lookup( &remote,
m_repo,
"origin" ) != GIT_OK )
370 const char* fetch_url = git_remote_url( remote );
371 const char* push_url = git_remote_pushurl( remote );
376 push_url = fetch_url;
380 git_remote_free( remote );
383 return fetch_url && push_url;
388 const git_oid* aOID,
unsigned int aIsMerge,
void* aPayload )
391 git_oid_cpy( (git_oid*) aPayload, aOID );
401 wxString progressMessage( aStr );
410 wxString progressMessage( str, len );
419 wxString progressMessage = wxString::Format(
_(
"Received %u of %u objects" ),
420 aStats->received_objects, aStats->total_objects );
422 parent->
UpdateProgress( aStats->received_objects, aStats->total_objects, progressMessage );
427extern "C" int update_cb(
const char* aRefname,
const git_oid* aFirst,
const git_oid* aSecond,
430 constexpr int cstring_len = 8;
431 char a_str[cstring_len + 1];
432 char b_str[cstring_len + 1];
437 git_oid_tostr( b_str, cstring_len, aSecond );
439#if ( LIBGIT2_VER_MAJOR >= 1 ) || ( LIBGIT2_VER_MINOR >= 99 )
440 if( !git_oid_is_zero( aFirst ) )
442 if( !git_oid_iszero( aFirst ) )
445 git_oid_tostr( a_str, cstring_len, aFirst );
446 status = wxString::Format(
_(
"* [updated] %s..%s %s" ), a_str, b_str, aRefname );
450 status = wxString::Format(
_(
"* [new] %s %s" ), b_str, aRefname );
462 int64_t progress = 100;
467 progress = ( aCurrent * 100 ) / aTotal;
470 wxString progressMessage = wxString::Format(
_(
"Writing objects: %d%% (%d/%d), %d bytes" ),
471 progress, aCurrent, aTotal, aBytes );
481 wxString status( aStatus );
483 if( !status.IsEmpty() )
485 wxString statusMessage = wxString::Format(
_(
"* [rejected] %s (%s)" ), aRefname, aStatus );
490 wxString statusMessage = wxString::Format(
_(
"[updated] %s" ), aRefname );
498extern "C" int credentials_cb( git_cred** aOut,
const char* aUrl,
const char* aUsername,
499 unsigned int aAllowedTypes,
void* aPayload )
504 return GIT_PASSTHROUGH;
506 if( aAllowedTypes & GIT_CREDTYPE_USERNAME
507 && !( parent->
TestedTypes() & GIT_CREDTYPE_USERNAME ) )
509 wxString username = parent->
GetUsername().Trim().Trim(
false );
510 git_cred_username_new( aOut, username.ToStdString().c_str() );
514 && ( aAllowedTypes & GIT_CREDTYPE_USERPASS_PLAINTEXT )
515 && !( parent->
TestedTypes() & GIT_CREDTYPE_USERPASS_PLAINTEXT ) )
517 wxString username = parent->
GetUsername().Trim().Trim(
false );
518 wxString password = parent->
GetPassword().Trim().Trim(
false );
520 git_cred_userpass_plaintext_new( aOut, username.ToStdString().c_str(),
521 password.ToStdString().c_str() );
522 parent->
TestedTypes() |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
525 && ( aAllowedTypes & GIT_CREDTYPE_SSH_KEY )
526 && !( parent->
TestedTypes() & GIT_CREDTYPE_SSH_KEY ) )
530 wxString sshPubKey = sshKey +
".pub";
531 wxString username = parent->
GetUsername().Trim().Trim(
false );
532 wxString password = parent->
GetPassword().Trim().Trim(
false );
534 git_cred_ssh_key_new( aOut, username.ToStdString().c_str(),
535 sshPubKey.ToStdString().c_str(),
536 sshKey.ToStdString().c_str(),
537 password.ToStdString().c_str() );
542 return GIT_PASSTHROUGH;
std::vector< wxString > GetBranchNames() const
wxString GetCurrentBranchName() const
wxString GetSSHKey() const
std::vector< wxString > GetProjectDirs()
Return a vector of project files in the repository.
GIT_CONN_TYPE GetConnType() const
wxString GetPassword() const
git_repository * GetRepo() const
KIGIT_COMMON(git_repository *aRepo)
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
wxString GetUsername() const
bool HasLocalCommits() const
virtual void UpdateProgress(int aCurrent, int aTotal, const wxString &aMessage)
void clone_progress_cb(const char *aStr, size_t aLen, size_t aTotal, void *data)
int fetchhead_foreach_cb(const char *, const char *, const git_oid *aOID, unsigned int aIsMerge, void *aPayload)
int push_update_reference_cb(const char *aRefname, const char *aStatus, void *aPayload)
int update_cb(const char *aRefname, const git_oid *aFirst, const git_oid *aSecond, void *aPayload)
int transfer_progress_cb(const git_transfer_progress *aStats, void *aPayload)
int credentials_cb(git_cred **aOut, const char *aUrl, const char *aUsername, unsigned int aAllowedTypes, void *aPayload)
int push_transfer_progress_cb(unsigned int aCurrent, unsigned int aTotal, size_t aBytes, void *aPayload)
int progress_cb(const char *str, int len, void *data)