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;
256 git_diff_init_options( &diff_opts, GIT_DIFF_OPTIONS_VERSION );
258 if( git_diff_tree_to_tree( &diff,
m_repo, parent_tree, tree, &diff_opts ) == GIT_OK )
260 size_t num_deltas = git_diff_num_deltas( diff );
262 for(
size_t i = 0; i < num_deltas; ++i )
264 const git_diff_delta*
delta = git_diff_get_delta( diff, i );
265 modified_set.insert(
delta->new_file.path );
268 git_diff_free( diff );
271 git_tree_free( parent_tree );
272 git_commit_free( parent );
273 git_tree_free( tree );
274 git_commit_free( commit );
277 git_revwalk_free( walker );
282 std::pair<std::set<wxString>,std::set<wxString>> modified_files;
285 return modified_files;
287 git_reference* head =
nullptr;
288 git_reference* remote_head =
nullptr;
290 if( git_repository_head( &head,
m_repo ) != GIT_OK )
291 return modified_files;
293 if( git_branch_upstream( &remote_head, head ) != GIT_OK )
295 git_reference_free( head );
296 return modified_files;
299 git_oid head_oid = *git_reference_target( head );
300 git_oid remote_oid = *git_reference_target( remote_head );
302 git_reference_free( head );
303 git_reference_free( remote_head );
305 modified_files.first = get_modified_files( &head_oid, &remote_oid );
306 modified_files.second = get_modified_files( &remote_oid, &head_oid );
308 return modified_files;
317 git_reference* head =
nullptr;
318 git_reference* remote_head =
nullptr;
320 if( git_repository_head( &head,
m_repo ) != GIT_OK )
323 if( git_branch_upstream( &remote_head, head ) != GIT_OK )
325 git_reference_free( head );
329 git_oid head_oid = *git_reference_target( head );
330 git_oid remote_oid = *git_reference_target( remote_head );
332 git_reference_free( head );
333 git_reference_free( remote_head );
335 git_revwalk* walker =
nullptr;
337 if( git_revwalk_new( &walker,
m_repo ) != GIT_OK )
340 if( ( git_revwalk_push( walker, &head_oid ) != GIT_OK )
341 || ( git_revwalk_hide( walker, &remote_oid ) != GIT_OK ) )
343 git_revwalk_free( walker );
350 if( git_revwalk_next( &oid, walker ) != GIT_OK )
352 git_revwalk_free( walker );
356 git_revwalk_free( walker );
363 git_remote* remote =
nullptr;
365 if( git_remote_lookup( &remote,
m_repo,
"origin" ) != GIT_OK )
371 const char* fetch_url = git_remote_url( remote );
372 const char* push_url = git_remote_pushurl( remote );
377 push_url = fetch_url;
381 git_remote_free( remote );
384 return fetch_url && push_url;
389 const git_oid* aOID,
unsigned int aIsMerge,
void* aPayload )
392 git_oid_cpy( (git_oid*) aPayload, aOID );
402 wxString progressMessage( aStr );
411 wxString progressMessage( str, len );
420 wxString progressMessage = wxString::Format(
_(
"Received %u of %u objects" ),
421 aStats->received_objects, aStats->total_objects );
423 parent->
UpdateProgress( aStats->received_objects, aStats->total_objects, progressMessage );
428extern "C" int update_cb(
const char* aRefname,
const git_oid* aFirst,
const git_oid* aSecond,
431 constexpr int cstring_len = 8;
432 char a_str[cstring_len + 1];
433 char b_str[cstring_len + 1];
438 git_oid_tostr( b_str, cstring_len, aSecond );
440#if ( LIBGIT2_VER_MAJOR >= 1 ) || ( LIBGIT2_VER_MINOR >= 99 )
441 if( !git_oid_is_zero( aFirst ) )
443 if( !git_oid_iszero( aFirst ) )
446 git_oid_tostr( a_str, cstring_len, aFirst );
447 status = wxString::Format(
_(
"* [updated] %s..%s %s" ), a_str, b_str, aRefname );
451 status = wxString::Format(
_(
"* [new] %s %s" ), b_str, aRefname );
463 int64_t progress = 100;
468 progress = ( aCurrent * 100 ) / aTotal;
471 wxString progressMessage = wxString::Format(
_(
"Writing objects: %d%% (%d/%d), %d bytes" ),
472 progress, aCurrent, aTotal, aBytes );
482 wxString status( aStatus );
484 if( !status.IsEmpty() )
486 wxString statusMessage = wxString::Format(
_(
"* [rejected] %s (%s)" ), aRefname, aStatus );
491 wxString statusMessage = wxString::Format(
_(
"[updated] %s" ), aRefname );
499extern "C" int credentials_cb( git_cred** aOut,
const char* aUrl,
const char* aUsername,
500 unsigned int aAllowedTypes,
void* aPayload )
505 return GIT_PASSTHROUGH;
507 if( aAllowedTypes & GIT_CREDTYPE_USERNAME
508 && !( parent->
TestedTypes() & GIT_CREDTYPE_USERNAME ) )
510 wxString username = parent->
GetUsername().Trim().Trim(
false );
511 git_cred_username_new( aOut, username.ToStdString().c_str() );
515 && ( aAllowedTypes & GIT_CREDTYPE_USERPASS_PLAINTEXT )
516 && !( parent->
TestedTypes() & GIT_CREDTYPE_USERPASS_PLAINTEXT ) )
518 wxString username = parent->
GetUsername().Trim().Trim(
false );
519 wxString password = parent->
GetPassword().Trim().Trim(
false );
521 git_cred_userpass_plaintext_new( aOut, username.ToStdString().c_str(),
522 password.ToStdString().c_str() );
523 parent->
TestedTypes() |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
526 && ( aAllowedTypes & GIT_CREDTYPE_SSH_KEY )
527 && !( parent->
TestedTypes() & GIT_CREDTYPE_SSH_KEY ) )
531 wxString sshPubKey = sshKey +
".pub";
532 wxString username = parent->
GetUsername().Trim().Trim(
false );
533 wxString password = parent->
GetPassword().Trim().Trim(
false );
535 git_cred_ssh_key_new( aOut, username.ToStdString().c_str(),
536 sshPubKey.ToStdString().c_str(),
537 sshKey.ToStdString().c_str(),
538 password.ToStdString().c_str() );
543 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)