43#include <wx/filename.h>
53 if( aMessage.empty() )
56 size_t firstLineEnd = aMessage.find_first_of(
'\n' );
58 if( firstLineEnd != std::string::npos )
59 return aMessage.substr( 0, firstLineEnd );
67 time_t time =
static_cast<time_t
>( aTime.time );
70 localtime_s( &timeInfo, &time );
72 gmtime_r( &time, &timeInfo );
74 strftime( dateBuffer,
sizeof( dateBuffer ),
"%Y-%b-%d %H:%M:%S", &timeInfo );
85 git_libgit2_shutdown();
90#if ( LIBGIT2_VER_MAJOR >= 1 ) || ( LIBGIT2_VER_MINOR >= 99 )
91 int major = 0, minor = 0, rev = 0;
92 return git_libgit2_version( &major, &minor, &rev ) == GIT_OK;
102 std::unique_lock<std::mutex> lock( common->
m_gitActionMutex, std::try_to_lock );
104 if( !lock.owns_lock() )
106 wxLogTrace(
traceGit,
"GIT_CLONE_HANDLER::PerformClone() could not lock" );
112 if( !clonePath.DirExists() )
114 if( !clonePath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
116 aHandler->
AddErrorString( wxString::Format(
_(
"Could not create directory '%s'" ),
122 git_clone_options cloneOptions;
123 git_clone_init_options( &cloneOptions, GIT_CLONE_OPTIONS_VERSION );
124 cloneOptions.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
126 cloneOptions.checkout_opts.progress_payload = aHandler;
129 cloneOptions.fetch_opts.callbacks.payload = aHandler;
133 git_repository* newRepo =
nullptr;
136 if( git_clone( &newRepo, remote.mbc_str(), aHandler->
GetClonePath().mbc_str(),
137 &cloneOptions ) != 0 )
139 aHandler->
AddErrorString( wxString::Format(
_(
"Could not clone repository '%s'" ), remote ) );
149 const std::vector<wxString>& aFiles,
150 const wxString& aMessage,
151 const wxString& aAuthorName,
152 const wxString& aAuthorEmail )
154 git_repository* repo = aHandler->
GetRepo();
159 git_index* index =
nullptr;
161 if( git_repository_index( &index, repo ) != 0 )
163 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to get repository index: %s" ),
170 for(
const wxString& file : aFiles )
172 if( git_index_add_bypath( index, file.mb_str() ) != 0 )
174 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to add file to index: %s" ),
180 if( git_index_write( index ) != 0 )
182 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to write index: %s" ),
189 if( git_index_write_tree( &tree_id, index ) != 0 )
191 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to write tree: %s" ),
196 git_tree* tree =
nullptr;
198 if( git_tree_lookup( &tree, repo, &tree_id ) != 0 )
200 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to lookup tree: %s" ),
206 git_commit* parent =
nullptr;
208 if( git_repository_head_unborn( repo ) == 0 )
210 git_reference* headRef =
nullptr;
212 if( git_repository_head( &headRef, repo ) != 0 )
214 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to get HEAD reference: %s" ),
221 if( git_reference_peel( (git_object**) &parent, headRef, GIT_OBJECT_COMMIT ) != 0 )
223 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to get commit: %s" ),
231 git_signature* author =
nullptr;
233 if( git_signature_now( &author, aAuthorName.mb_str(), aAuthorEmail.mb_str() ) != 0 )
235 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to create author signature: %s" ),
242 size_t parentsCount = parent ? 1 : 0;
243#if( LIBGIT2_VER_MAJOR == 1 && LIBGIT2_VER_MINOR == 8 \
244 && ( LIBGIT2_VER_REVISION < 2 || LIBGIT2_VER_REVISION == 3 ) )
245 git_commit*
const parents[1] = { parent };
246 git_commit**
const parentsPtr = parent ? parents :
nullptr;
248 const git_commit* parents[1] = { parent };
249 const git_commit** parentsPtr = parent ? parents :
nullptr;
254 if( git_commit_create( &oid, repo,
"HEAD", author, author,
nullptr,
255 aMessage.mb_str(), tree, parentsCount, parentsPtr ) != 0 )
257 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to create commit: %s" ),
268 std::unique_lock<std::mutex> lock( common->
m_gitActionMutex, std::try_to_lock );
270 if(!lock.owns_lock())
272 wxLogTrace(
traceGit,
"GIT_PUSH_HANDLER::PerformPush: Could not lock mutex");
278 git_remote* remote =
nullptr;
280 if(git_remote_lookup(&remote, aHandler->
GetRepo(),
"origin") != 0)
288 git_remote_callbacks remoteCallbacks;
289 git_remote_init_callbacks(&remoteCallbacks, GIT_REMOTE_CALLBACKS_VERSION);
295 remoteCallbacks.payload = aHandler;
301 if( git_remote_connect( remote, GIT_DIRECTION_PUSH, &remoteCallbacks,
nullptr,
nullptr ) )
303 aHandler->
AddErrorString( wxString::Format(
_(
"Could not connect to remote: %s" ),
308 git_push_options pushOptions;
309 git_push_init_options( &pushOptions, GIT_PUSH_OPTIONS_VERSION );
310 pushOptions.callbacks = remoteCallbacks;
312 git_reference* head =
nullptr;
314 if( git_repository_head( &head, aHandler->
GetRepo() ) != 0 )
316 git_remote_disconnect( remote );
324 refs[0] = git_reference_name( head );
325 const git_strarray refspecs = { (
char**) refs, 1 };
327 if( git_remote_push( remote, &refspecs, &pushOptions ) )
329 aHandler->
AddErrorString( wxString::Format(
_(
"Could not push to remote: %s" ),
331 git_remote_disconnect( remote );
335 git_remote_disconnect( remote );
342 git_repository* repo = aHandler->
GetRepo();
347 git_status_options opts;
348 git_status_init_options( &opts, GIT_STATUS_OPTIONS_VERSION );
350 opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
351 opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
352 | GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;
354 git_status_list* status_list =
nullptr;
356 if( git_status_list_new( &status_list, repo, &opts ) != GIT_OK )
363 bool hasChanges = ( git_status_list_entrycount( status_list ) > 0 );
369 const wxString& aPathspec )
371 std::map<wxString, FileStatus> fileStatusMap;
372 git_repository* repo = aHandler->
GetRepo();
375 return fileStatusMap;
377 git_status_options status_options;
378 git_status_init_options( &status_options, GIT_STATUS_OPTIONS_VERSION );
379 status_options.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
380 status_options.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
382 std::string pathspec_str;
383 std::vector<const char*> pathspec_ptrs;
385 if( !aPathspec.IsEmpty() )
387 pathspec_str = aPathspec.ToStdString();
388 pathspec_ptrs.push_back( pathspec_str.c_str() );
390 status_options.pathspec.strings =
const_cast<char**
>( pathspec_ptrs.data() );
391 status_options.pathspec.count = pathspec_ptrs.size();
394 git_status_list* status_list =
nullptr;
396 if( git_status_list_new( &status_list, repo, &status_options ) != GIT_OK )
399 return fileStatusMap;
404 size_t count = git_status_list_entrycount( status_list );
405 wxString repoWorkDir( git_repository_workdir( repo ) );
407 for(
size_t ii = 0; ii < count; ++ii )
409 const git_status_entry* entry = git_status_byindex( status_list, ii );
410 std::string
path( entry->head_to_index ? entry->head_to_index->old_file.path
411 : entry->index_to_workdir->old_file.path );
413 wxString absPath = repoWorkDir +
path;
420 fileStatusMap[absPath] = fileStatus;
423 return fileStatusMap;
428 git_repository* repo = aHandler->
GetRepo();
431 return wxEmptyString;
433 git_reference* currentBranchReference =
nullptr;
434 int rc = git_repository_head( ¤tBranchReference, repo );
437 if( currentBranchReference )
439 return git_reference_shorthand( currentBranchReference );
441 else if( rc == GIT_EUNBORNBRANCH )
443 return wxEmptyString;
448 return wxEmptyString;
453 const std::set<wxString>& aLocalChanges,
454 const std::set<wxString>& aRemoteChanges,
455 std::map<wxString, FileStatus>& aFileStatus )
457 git_repository* repo = aHandler->
GetRepo();
462 wxString repoWorkDir( git_repository_workdir( repo ) );
464 for(
auto& [absPath, fileStatus] : aFileStatus )
466 wxString relativePath = absPath;
467 if( relativePath.StartsWith( repoWorkDir ) )
469 relativePath = relativePath.Mid( repoWorkDir.length() );
471 relativePath.Replace( wxS(
"\\" ), wxS(
"/" ) );
475 std::string relativePathStd = relativePath.ToStdString();
479 if( aLocalChanges.count( relativePathStd ) )
483 else if( aRemoteChanges.count( relativePathStd ) )
493 git_repository* repo = aHandler->
GetRepo();
496 return wxEmptyString;
498 const char* workdir = git_repository_workdir( repo );
501 return wxEmptyString;
503 return wxString( workdir );
508 git_repository* repo = aHandler->
GetRepo();
511 return wxEmptyString;
513 const char* workdir = git_repository_workdir( repo );
516 return wxEmptyString;
518 return wxString( workdir );
524 git_repository* repo = aHandler->
GetRepo();
529 git_config*
config =
nullptr;
531 if( git_repository_config( &
config, repo ) != GIT_OK )
539 git_config_entry* entry =
nullptr;
540 int result = git_config_get_entry( &entry,
config, aKey.mb_str() );
543 if(
result != GIT_OK || entry ==
nullptr )
545 wxLogTrace(
traceGit,
"Config key '%s' not found", aKey );
549 aValue = wxString( entry->value );
555 git_repository* repo =
nullptr;
556 int error = git_repository_open( &repo, aPath.mb_str() );
560 git_repository_free( repo );
574 git_repository* repo =
nullptr;
576 if( git_repository_init( &repo, aPath.mb_str(), 0 ) != GIT_OK )
579 git_repository_free( repo );
581 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to initialize Git repository: %s" ),
588 wxLogTrace(
traceGit,
"Successfully initialized Git repository at %s", aPath );
594 if( aConfig.
url.IsEmpty() )
597 git_repository* repo = aHandler->
GetRepo();
601 aHandler->
AddErrorString(
_(
"No repository available to set up remote" ) );
609 git_remote* remote =
nullptr;
618 fullURL = aConfig.
url.StartsWith(
"https" ) ?
"https://" :
"http://";
626 fullURL.append( wxS(
":" ) );
630 fullURL.append( wxS(
"@" ) );
633 wxString bareURL = aConfig.
url;
634 if( bareURL.StartsWith(
"https://" ) )
635 bareURL = bareURL.Mid( 8 );
636 else if( bareURL.StartsWith(
"http://" ) )
637 bareURL = bareURL.Mid( 7 );
639 fullURL.append( bareURL );
643 fullURL = aConfig.
url;
646 int error = git_remote_create_with_fetchspec( &remote, repo,
"origin",
647 fullURL.ToStdString().c_str(),
648 "+refs/heads/*:refs/remotes/origin/*" );
652 if( error != GIT_OK )
654 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to create remote: %s" ),
659 wxLogTrace(
traceGit,
"Successfully set up remote origin" );
664 git_reference** aReference )
666 if( git_reference_lookup( aReference, repo, aBranchName.mb_str() ) == GIT_OK )
669 if( git_reference_dwim( aReference, repo, aBranchName.mb_str() ) == GIT_OK )
677 git_repository* repo = aHandler->
GetRepo();
685 git_reference* branchRef =
nullptr;
689 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to lookup branch '%s': %s" ),
695 const char* branchRefName = git_reference_name( branchRef );
696 git_object* branchObj =
nullptr;
698 if( git_revparse_single( &branchObj, repo, aBranchName.mb_str() ) != GIT_OK )
700 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to find branch head for '%s': %s" ),
707 if( git_checkout_tree( repo, branchObj,
nullptr ) != GIT_OK )
709 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to switch to branch '%s': %s" ),
714 if( git_repository_set_head( repo, branchRefName ) != GIT_OK )
716 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to update HEAD reference for branch '%s': %s" ),
721 wxLogTrace(
traceGit,
"Successfully switched to branch '%s'", aBranchName );
727 git_repository* repo = aHandler->
GetRepo();
732 git_reference* branchRef =
nullptr;
736 git_reference_free( branchRef );
747 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformFetch() - No repository found" );
753 if( !aSkipLock && !lock.owns_lock() )
755 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformFetch() - Could not lock mutex" );
759 git_remote* remote =
nullptr;
761 if( git_remote_lookup( &remote, aHandler->
GetRepo(),
"origin" ) != 0 )
763 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformFetch() - Failed to lookup remote 'origin'" );
764 aHandler->
AddErrorString( wxString::Format(
_(
"Could not lookup remote '%s'" ),
"origin" ) );
770 git_remote_callbacks remoteCallbacks;
771 git_remote_init_callbacks( &remoteCallbacks, GIT_REMOTE_CALLBACKS_VERSION );
775 remoteCallbacks.payload = aHandler;
781 if( git_remote_connect( remote, GIT_DIRECTION_FETCH, &remoteCallbacks,
nullptr,
nullptr ) )
784 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformFetch() - Failed to connect to remote: %s", errorMsg );
785 aHandler->
AddErrorString( wxString::Format(
_(
"Could not connect to remote '%s': %s" ),
"origin", errorMsg ) );
789 git_fetch_options fetchOptions;
790 git_fetch_init_options( &fetchOptions, GIT_FETCH_OPTIONS_VERSION );
791 fetchOptions.callbacks = remoteCallbacks;
793 if( git_remote_fetch( remote,
nullptr, &fetchOptions,
nullptr ) )
796 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformFetch() - Failed to fetch from remote: %s", errorMsg );
797 aHandler->
AddErrorString( wxString::Format(
_(
"Could not fetch data from remote '%s': %s" ),
"origin", errorMsg ) );
801 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformFetch() - Fetch completed successfully" );
810 if( !lock.owns_lock() )
812 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformPull() - Could not lock mutex" );
819 git_oid pull_merge_oid = {};
828 git_annotated_commit* fetchhead_commit;
830 if( git_annotated_commit_lookup( &fetchhead_commit, aHandler->
GetRepo(), &pull_merge_oid ) )
837 const git_annotated_commit* merge_commits[] = { fetchhead_commit };
838 git_merge_analysis_t merge_analysis;
839 git_merge_preference_t merge_preference = GIT_MERGE_PREFERENCE_NONE;
841 if( git_merge_analysis( &merge_analysis, &merge_preference, aHandler->
GetRepo(), merge_commits, 1 ) )
847 if( merge_analysis & GIT_MERGE_ANALYSIS_UNBORN )
853 if( merge_analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE )
855 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformPull() - Repository is up to date" );
856 git_repository_state_cleanup( aHandler->
GetRepo() );
860 if( merge_analysis & GIT_MERGE_ANALYSIS_FASTFORWARD )
862 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformPull() - Fast-forward merge" );
866 if( merge_analysis & GIT_MERGE_ANALYSIS_NORMAL )
868 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformPull() - Normal merge" );
870 git_config*
config =
nullptr;
872 if( git_repository_config( &
config, aHandler->
GetRepo() ) != GIT_OK )
874 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformPull() - Failed to get repository config" );
875 aHandler->
AddErrorString(
_(
"Could not access repository configuration" ) );
881 int rebase_value = 0;
882 int ret = git_config_get_bool( &rebase_value,
config,
"pull.rebase" );
884 if( ret == GIT_OK && rebase_value )
886 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformPull() - Using rebase based on config" );
890 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformPull() - Using merge based on config" );
894 wxLogTrace(
traceGit,
"GIT_PULL_HANDLER::PerformPull() - Merge needs resolution" );
900 git_reference* rawRef =
nullptr;
902 if( git_repository_head( &rawRef, aHandler->
GetRepo() ) )
910 git_oid updatedRefOid;
911 const char* currentBranchName = git_reference_name( rawRef );
912 const char* branch_shorthand = git_reference_shorthand( rawRef );
914 wxString remoteBranchName = wxString::Format(
"refs/remotes/%s/%s", remote_name, branch_shorthand );
916 if( git_reference_name_to_id( &updatedRefOid, aHandler->
GetRepo(), remoteBranchName.c_str() ) != GIT_OK )
918 aHandler->
AddErrorString( wxString::Format(
_(
"Could not get reference OID for reference '%s'" ),
919 remoteBranchName ) );
923 git_commit* targetCommit =
nullptr;
925 if( git_commit_lookup( &targetCommit, aHandler->
GetRepo(), &updatedRefOid ) != GIT_OK )
933 git_tree* targetTree =
nullptr;
935 if( git_commit_tree( &targetTree, targetCommit ) != GIT_OK )
937 git_commit_free( targetCommit );
938 aHandler->
AddErrorString(
_(
"Could not get tree from target commit" ) );
944 git_checkout_options checkoutOptions;
945 git_checkout_init_options( &checkoutOptions, GIT_CHECKOUT_OPTIONS_VERSION );
946 auto notify_cb = []( git_checkout_notify_t why,
const char*
path,
const git_diff_file* baseline,
947 const git_diff_file* target,
const git_diff_file* workdir,
void* payload ) ->
int
951 case GIT_CHECKOUT_NOTIFY_CONFLICT:
954 case GIT_CHECKOUT_NOTIFY_DIRTY:
957 case GIT_CHECKOUT_NOTIFY_UPDATED:
960 case GIT_CHECKOUT_NOTIFY_UNTRACKED:
963 case GIT_CHECKOUT_NOTIFY_IGNORED:
973 checkoutOptions.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS;
974 checkoutOptions.notify_flags = GIT_CHECKOUT_NOTIFY_ALL;
975 checkoutOptions.notify_cb = notify_cb;
977 if( git_checkout_tree( aHandler->
GetRepo(),
reinterpret_cast<git_object*
>( targetTree ), &checkoutOptions ) != GIT_OK )
979 aHandler->
AddErrorString(
_(
"Failed to perform checkout operation." ) );
983 git_reference* updatedRef =
nullptr;
985 if( git_reference_set_target( &updatedRef, rawRef, &updatedRefOid,
nullptr ) != GIT_OK )
987 aHandler->
AddErrorString( wxString::Format(
_(
"Failed to update reference '%s' to point to '%s'" ),
988 currentBranchName, git_oid_tostr_s( &updatedRefOid ) ) );
994 if( git_repository_state_cleanup( aHandler->
GetRepo() ) != GIT_OK )
996 aHandler->
AddErrorString(
_(
"Failed to clean up repository state after fast-forward." ) );
1000 git_revwalk* revWalker =
nullptr;
1002 if( git_revwalk_new( &revWalker, aHandler->
GetRepo() ) != GIT_OK )
1004 aHandler->
AddErrorString(
_(
"Failed to initialize revision walker." ) );
1009 git_revwalk_sorting( revWalker, GIT_SORT_TIME );
1011 if( git_revwalk_push_glob( revWalker, currentBranchName ) != GIT_OK )
1013 aHandler->
AddErrorString(
_(
"Failed to push reference to revision walker." ) );
1017 std::pair<std::string, std::vector<CommitDetails>>& branchCommits =
1019 branchCommits.first = currentBranchName;
1023 while( git_revwalk_next( &commitOid, revWalker ) == GIT_OK )
1025 git_commit* commit =
nullptr;
1027 if( git_commit_lookup( &commit, aHandler->
GetRepo(), &commitOid ) )
1029 aHandler->
AddErrorString( wxString::Format(
_(
"Could not lookup commit '%s'" ),
1030 git_oid_tostr_s( &commitOid ) ) );
1037 details.
m_sha = git_oid_tostr_s( &commitOid );
1039 details.
m_author = git_commit_author( commit )->name;
1042 branchCommits.second.push_back( details );
1049 const git_annotated_commit** aMergeHeads,
1050 size_t aMergeHeadsCount )
1052 if( git_merge( aHandler->
GetRepo(), aMergeHeads, aMergeHeadsCount,
nullptr,
nullptr ) )
1062 const git_annotated_commit** aMergeHeads,
1063 size_t aMergeHeadsCount )
1065 git_rebase_options rebase_opts;
1066 git_rebase_init_options( &rebase_opts, GIT_REBASE_OPTIONS_VERSION );
1068 git_rebase* rebase =
nullptr;
1070 if( git_rebase_init( &rebase, aHandler->
GetRepo(),
nullptr, aMergeHeads[0],
nullptr, &rebase_opts ) )
1080 git_rebase_operation* op =
nullptr;
1081 if( git_rebase_next( &op, rebase ) != 0 )
1084 if( git_rebase_commit(
nullptr, rebase,
nullptr,
nullptr,
nullptr,
nullptr ) )
1091 if( git_rebase_finish( rebase,
nullptr ) )
1102 git_object* head_commit = NULL;
1103 git_checkout_options opts;
1104 git_checkout_init_options( &opts, GIT_CHECKOUT_OPTIONS_VERSION );
1106 if( git_revparse_single( &head_commit, aHandler->
m_repository,
"HEAD" ) != 0 )
1111 opts.checkout_strategy = GIT_CHECKOUT_FORCE;
1122 opts.progress_cb =
nullptr;
1123 opts.notify_cb =
nullptr;
1124 opts.notify_payload =
static_cast<void*
>( aHandler );
1126 if( git_checkout_tree( aHandler->
m_repository, head_commit, &opts ) != 0 )
1128 const git_error* e = git_error_last();
1132 wxLogTrace(
traceGit, wxS(
"Checkout failed: %d: %s" ), e->klass, e->message );
1137 delete( paths[ii] );
1141 git_object_free( head_commit );
1146 git_repository* repo =
nullptr;
1149 if( git_repository_discover( &repo_path, aFilename, 0,
nullptr ) != GIT_OK )
1151 wxLogTrace(
traceGit,
"Can't repo discover %s: %s", aFilename,
1158 if( git_repository_open( &repo, repo_path.ptr ) != GIT_OK )
1160 wxLogTrace(
traceGit,
"Can't open repo for %s: %s", repo_path.ptr,
1172 if(
int error = git_reference_name_to_id( &head_oid, aRepo,
"HEAD" ); error != GIT_OK )
1174 wxLogTrace(
traceGit,
"Failed to lookup HEAD reference: %s",
1179 git_commit* commit =
nullptr;
1181 if(
int error = git_commit_lookup( &commit, aRepo, &head_oid ); error != GIT_OK )
1183 wxLogTrace(
traceGit,
"Failed to lookup commit: %s",
1189 git_reference* branchRef =
nullptr;
1191 if(
int error = git_branch_create( &branchRef, aRepo, aBranchName.mb_str(), commit, 0 ); error != GIT_OK )
1193 wxLogTrace(
traceGit,
"Failed to create branch: %s",
1198 git_reference_free( branchRef );
1203 bool aRemoveGitDir, wxString* aErrors )
1207 git_repository_free( aRepo );
1213 wxFileName gitDir( aProjectPath, wxEmptyString );
1214 gitDir.AppendDir(
".git" );
1216 if( gitDir.DirExists() )
1224 wxLogTrace(
traceGit,
"Failed to remove .git directory: %s", errors );
1230 wxLogTrace(
traceGit,
"Successfully removed VCS from project" );
1236 git_repository* repo = aHandler->
GetRepo();
1238 git_index* index =
nullptr;
1241 if( git_repository_index( &index, repo ) != 0 )
1243 wxLogError(
"Failed to get repository index" );
1249 if( git_index_find( &at_pos, index, aFilePath.ToUTF8().data() ) == GIT_OK )
1251 wxLogError(
"%s already in index", aFilePath );
1261 git_repository* repo = aHandler->
GetRepo();
1262 git_index* index =
nullptr;
1266 if( git_repository_index( &index, repo ) != 0 )
1268 wxLogError(
"Failed to get repository index" );
1278 if( git_index_add_bypath( index, file.ToUTF8().data() ) != 0 )
1280 wxLogError(
"Failed to add %s to index", file );
1286 if( git_index_write( index ) != 0 )
1288 wxLogError(
"Failed to write index" );
1299 const wxString& aFilePath )
1301 git_repository* repo = aHandler->
GetRepo();
1302 git_index* index =
nullptr;
1305 if( git_repository_index( &index, repo ) != 0 )
1307 wxLogError(
"Failed to get repository index" );
1313 if( git_index_find( &at_pos, index, aFilePath.ToUTF8().data() ) != 0 )
1315 wxLogError(
"Failed to find index entry for %s", aFilePath );
1325 git_repository* repo = aHandler->
GetRepo();
1329 git_index* index =
nullptr;
1332 if( git_repository_index( &index, repo ) != 0 )
1334 wxLogError(
"Failed to get repository index" );
1340 if( git_index_remove_bypath( index, file.ToUTF8().data() ) != 0 )
1342 wxLogError(
"Failed to remove index entry for %s", file );
1346 if( git_index_write( index ) != 0 )
1348 wxLogError(
"Failed to write index" );
1352 if( git_index_write_tree( &oid, index ) != 0 )
1354 wxLogError(
"Failed to write index tree" );
std::vector< wxString > m_filesToAdd
std::vector< wxString > m_filesFailedToAdd
wxString GetClonePath() const
void AddErrorString(const wxString &aErrorString)
std::vector< std::pair< std::string, std::vector< CommitDetails > > > m_fetchResults
std::vector< wxString > m_filesToRemove
std::vector< wxString > m_filesToRevert
git_repository * m_repository
KIGIT_COMMON::GIT_STATUS ConvertStatus(unsigned int aGitStatus)
Convert git status flags to KIGIT_COMMON::GIT_STATUS.
std::mutex m_gitActionMutex
static wxString GetLastGitError()
void SetSSHKey(const wxString &aSSHKey)
void SetUsername(const wxString &aUsername)
git_repository * GetRepo() const
void SetCancelled(bool aCancel)
void SetPassword(const wxString &aPassword)
void SetRepo(git_repository *aRepo)
void AddErrorString(const wxString aErrorString)
git_repository * GetRepo() const
Get a pointer to the git repository.
unsigned & TestedTypes()
Return the connection types that have been tested for authentication.
KIGIT_COMMON * GetCommon() const
Get the common object.
wxString GetRemotename() const
Get the remote name.
void ResetNextKey()
Reset the next public key to test.
bool PerformAddToIndex(GIT_ADD_TO_INDEX_HANDLER *aHandler) override
void PerformRevert(GIT_REVERT_HANDLER *aHandler) override
PullResult handleMerge(GIT_PULL_HANDLER *aHandler, const git_annotated_commit **aMergeHeads, size_t aMergeHeadsCount)
bool PerformFetch(GIT_PULL_HANDLER *aHandler, bool aSkipLock) override
bool Clone(GIT_CLONE_HANDLER *aHandler) override
PullResult handleRebase(GIT_PULL_HANDLER *aHandler, const git_annotated_commit **aMergeHeads, size_t aMergeHeadsCount)
void PerformRemoveFromIndex(GIT_REMOVE_FROM_INDEX_HANDLER *aHandler) override
bool RemoveVCS(git_repository *&aRepo, const wxString &aProjectPath, bool aRemoveGitDir, wxString *aErrors) override
bool RemoveFromIndex(GIT_REMOVE_FROM_INDEX_HANDLER *aHandler, const wxString &aFilePath) override
BranchResult SwitchToBranch(GIT_BRANCH_HANDLER *aHandler, const wxString &aBranchName) override
PullResult handleFastForward(GIT_PULL_HANDLER *aHandler)
CommitResult Commit(GIT_COMMIT_HANDLER *aHandler, const std::vector< wxString > &aFiles, const wxString &aMessage, const wxString &aAuthorName, const wxString &aAuthorEmail) override
std::map< wxString, FileStatus > GetFileStatus(GIT_STATUS_HANDLER *aHandler, const wxString &aPathspec) override
bool HasChangedFiles(GIT_STATUS_HANDLER *aHandler) override
void UpdateRemoteStatus(GIT_STATUS_HANDLER *aHandler, const std::set< wxString > &aLocalChanges, const std::set< wxString > &aRemoteChanges, std::map< wxString, FileStatus > &aFileStatus) override
wxString GetCurrentBranchName(GIT_STATUS_HANDLER *aHandler) override
PushResult Push(GIT_PUSH_HANDLER *aHandler) override
bool GetConfigString(GIT_CONFIG_HANDLER *aHandler, const wxString &aKey, wxString &aValue) override
git_repository * GetRepositoryForFile(const char *aFilename) override
bool AddToIndex(GIT_ADD_TO_INDEX_HANDLER *aHandler, const wxString &aFilePath) override
bool SetupRemote(GIT_INIT_HANDLER *aHandler, const RemoteConfig &aConfig) override
bool IsRepository(GIT_INIT_HANDLER *aHandler, const wxString &aPath) override
bool IsLibraryAvailable() override
wxString GetWorkingDirectory(GIT_STATUS_HANDLER *aHandler) override
bool BranchExists(GIT_BRANCH_HANDLER *aHandler, const wxString &aBranchName) override
InitResult InitializeRepository(GIT_INIT_HANDLER *aHandler, const wxString &aPath) override
PullResult PerformPull(GIT_PULL_HANDLER *aHandler) override
int CreateBranch(git_repository *aRepo, const wxString &aBranchName) override
bool RmDirRecursive(const wxString &aFileName, wxString *aErrors)
Remove the directory aDirName and all its contents including subdirectories and their files.
const wxChar *const traceGit
Flag to enable Git debugging output.
int fetchhead_foreach_cb(const char *, const char *, const git_oid *aOID, unsigned int aIsMerge, void *aPayload)
int progress_cb(const char *str, int len, 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)
void clone_progress_cb(const char *aStr, size_t aLen, size_t aTotal, void *aPayload)
int push_transfer_progress_cb(unsigned int aCurrent, unsigned int aTotal, size_t aBytes, void *aPayload)
static bool lookup_branch_reference(git_repository *repo, const wxString &aBranchName, git_reference **aReference)
static std::string getFormattedCommitDate(const git_time &aTime)
static std::string getFirstLineFromCommitMessage(const std::string &aMessage)
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_revwalk, decltype([](git_revwalk *aWalker) { git_revwalk_free(aWalker); })> GitRevWalkPtr
A unique pointer for git_revwalk 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_annotated_commit, decltype([](git_annotated_commit *aCommit) { git_annotated_commit_free(aCommit); })> GitAnnotatedCommitPtr
A unique pointer for git_annotated_commit 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_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.
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_signature, decltype([](git_signature *aSignature) { git_signature_free(aSignature); })> GitSignaturePtr
A unique pointer for git_signature objects with automatic cleanup.
std::unique_ptr< git_rebase, decltype([](git_rebase *aRebase) { git_rebase_free(aRebase); })> GitRebasePtr
A unique pointer for git_rebase 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_object, decltype([](git_object *aObject) { git_object_free(aObject); })> GitObjectPtr
A unique pointer for git_object objects with automatic cleanup.
std::unique_ptr< git_remote, decltype([](git_remote *aRemote) { git_remote_free(aRemote); })> GitRemotePtr
A unique pointer for git_remote objects with automatic cleanup.
KIGIT_COMMON::GIT_STATUS status
KIGIT_COMMON::GIT_CONN_TYPE connType
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.