mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 10:40:20 +03:00
More fixes in Git plugin.
This commit is contained in:
@@ -108,15 +108,15 @@ bool MemoryManager::removePointer( void* data, const char* file, const size_t& l
|
||||
|
||||
AllocatedPointerMapIt it = sMapPointers.find( data );
|
||||
|
||||
if ( it->second.mTrack )
|
||||
eePRINTL( "Deleting pointer %p at '%s' %d", data, file, line );
|
||||
|
||||
if ( it == sMapPointers.end() ) {
|
||||
eePRINTL( "Trying to delete pointer %p created that does not exist!", data );
|
||||
|
||||
eeASSERT( false );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( it->second.mTrack )
|
||||
eePRINTL( "Deleting pointer %p at '%s' %d", data, file, line );
|
||||
|
||||
sTotalMemoryUsage -= it->second.mMemory;
|
||||
|
||||
sMapPointers.erase( it );
|
||||
|
||||
@@ -727,6 +727,10 @@ String UIListBox::getItemSelectedText() const {
|
||||
return tstr;
|
||||
}
|
||||
|
||||
const std::vector<String>& UIListBox::getItemsText() const {
|
||||
return mTexts;
|
||||
}
|
||||
|
||||
std::vector<Uint32> UIListBox::getItemsSelectedIndex() const {
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "git.hpp"
|
||||
#include <eepp/system/clock.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/lock.hpp>
|
||||
#include <eepp/system/log.hpp>
|
||||
#include <eepp/system/luapattern.hpp>
|
||||
#include <eepp/system/process.hpp>
|
||||
@@ -107,6 +108,8 @@ bool Git::setProjectPath( const std::string& projectPath ) {
|
||||
auto lastProjectPath = mProjectPath;
|
||||
mProjectPath = "";
|
||||
mGitFolder = "";
|
||||
mSubModules = {};
|
||||
mSubModulesUpdated = true;
|
||||
FileInfo f( projectPath );
|
||||
if ( !f.isDirectory() )
|
||||
return false;
|
||||
@@ -233,7 +236,7 @@ Git::Result Git::deleteBranch( const std::string& branch, const std::string& pro
|
||||
return gitSimple( String::format( "branch -D %s", branch ), projectDir );
|
||||
}
|
||||
|
||||
Git::Result Git::commit( const std::string& commitMsg, bool ammend,
|
||||
Git::Result Git::commit( const std::string& commitMsg, bool ammend, bool byPassCommitHook,
|
||||
const std::string& projectDir ) {
|
||||
auto tmpPath = Sys::getTempPath() + ".ecode-git-commit-" + String::randString( 16 );
|
||||
if ( !FileSystem::fileWrite( tmpPath, commitMsg ) ) {
|
||||
@@ -243,9 +246,16 @@ Git::Result Git::commit( const std::string& commitMsg, bool ammend,
|
||||
return res;
|
||||
}
|
||||
std::string buf;
|
||||
int retCode = git( String::format( "commit %s --cleanup=whitespace --allow-empty --file=%s",
|
||||
ammend ? "--ammend" : "", tmpPath ),
|
||||
projectDir, buf );
|
||||
std::string opts;
|
||||
if ( ammend )
|
||||
opts += " --ammend";
|
||||
|
||||
if ( byPassCommitHook )
|
||||
opts += " --no-verify";
|
||||
|
||||
int retCode = git(
|
||||
String::format( "commit %s --cleanup=whitespace --allow-empty --file=%s", opts, tmpPath ),
|
||||
projectDir, buf );
|
||||
FileSystem::fileRemove( tmpPath );
|
||||
Git::Result res;
|
||||
res.returnCode = retCode;
|
||||
@@ -439,6 +449,7 @@ std::vector<std::string> Git::fetchSubModules( const std::string& projectDir ) {
|
||||
}
|
||||
|
||||
std::vector<std::string> Git::getSubModules( const std::string& projectDir ) {
|
||||
Lock l( mSubModulesMutex );
|
||||
if ( !mSubModulesUpdated ) {
|
||||
mSubModules = fetchSubModules( projectDir );
|
||||
mSubModulesUpdated = true;
|
||||
@@ -451,9 +462,11 @@ bool Git::hasSubmodules( const std::string& projectDir ) {
|
||||
( !mProjectPath.empty() && FileSystem::fileExists( mProjectPath + ".gitmodules" ) );
|
||||
}
|
||||
|
||||
std::string Git::repoName( const std::string& file, const std::string& projectDir ) {
|
||||
std::string Git::repoName( const std::string& file, bool allowExactMatch,
|
||||
const std::string& projectDir ) {
|
||||
for ( const auto& subRepo : mSubModules ) {
|
||||
if ( String::startsWith( file, subRepo ) && file.size() != subRepo.size() )
|
||||
if ( String::startsWith( file, subRepo ) &&
|
||||
( allowExactMatch || file.size() != subRepo.size() ) )
|
||||
return subRepo;
|
||||
}
|
||||
return FileSystem::fileNameFromPath( !projectDir.empty() ? projectDir : mProjectPath );
|
||||
@@ -523,7 +536,7 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
|
||||
status.type == GitStatusType::Staged && statusStr[1] != ' ';
|
||||
|
||||
auto filePath = subModulePath + file;
|
||||
auto repo = repoName( filePath, projectDir );
|
||||
auto repo = repoName( filePath, false, projectDir );
|
||||
auto repoIt = s.files.find( repo );
|
||||
bool found = false;
|
||||
if ( repoIt != s.files.end() ) {
|
||||
@@ -576,7 +589,7 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
|
||||
if ( String::fromString( inserts, inserted ) &&
|
||||
String::fromString( deletes, deleted ) && ( inserts || deletes ) ) {
|
||||
auto filePath = subModulePath + file;
|
||||
auto repo = repoName( filePath, projectDir );
|
||||
auto repo = repoName( filePath, false, projectDir );
|
||||
auto repoIt = s.files.find( repo );
|
||||
GitStatusReport status = { GitStatus::NotSet, GitStatusType::Untracked,
|
||||
GitStatusChar::Untracked };
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <eepp/system/mutex.hpp>
|
||||
|
||||
using namespace EE::System;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
#define git_xy( x, y ) ( ( (uint16_t)x ) << 8 | y )
|
||||
@@ -137,6 +141,19 @@ class Git {
|
||||
return totalInserts == other.totalInserts && totalDeletions == other.totalDeletions &&
|
||||
files == other.files;
|
||||
}
|
||||
|
||||
bool empty() { return totalInserts == 0 && totalDeletions == 0 && files.empty(); }
|
||||
|
||||
bool hasStagedChanges( const std::string& repoName ) {
|
||||
auto found = files.find( repoName );
|
||||
if ( found != files.end() ) {
|
||||
for ( const auto& file : found->second ) {
|
||||
if ( file.report.type == GitStatusType::Staged )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct Result {
|
||||
@@ -228,7 +245,8 @@ class Git {
|
||||
|
||||
Result deleteBranch( const std::string& branch, const std::string& projectDir = "" );
|
||||
|
||||
Result commit( const std::string& commitMsg, bool ammend, const std::string& projectDir = "" );
|
||||
Result commit( const std::string& commitMsg, bool ammend, bool byPassCommitHook,
|
||||
const std::string& projectDir = "" );
|
||||
|
||||
Result fetch( const std::string& projectDir = "" );
|
||||
|
||||
@@ -284,7 +302,8 @@ class Git {
|
||||
|
||||
std::vector<std::string> getSubModules( const std::string& projectDir = "" );
|
||||
|
||||
std::string repoName( const std::string& file, const std::string& projectDir = "" );
|
||||
std::string repoName( const std::string& file, bool allowExactMatch = false,
|
||||
const std::string& projectDir = "" );
|
||||
|
||||
std::string repoPath( const std::string& file );
|
||||
|
||||
@@ -299,6 +318,7 @@ class Git {
|
||||
std::string mProjectPath;
|
||||
std::string mGitFolder;
|
||||
std::vector<std::string> mSubModules;
|
||||
Mutex mSubModulesMutex;
|
||||
bool mSubModulesUpdated{ false };
|
||||
};
|
||||
|
||||
|
||||
@@ -216,6 +216,8 @@ void GitPlugin::updateStatusBarSync() {
|
||||
mStatusTree->setModel( GitStatusModel::asModel( mGitStatus.files, this ) );
|
||||
}
|
||||
mStatusTree->expandAll();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !mStatusBarDisplayBranch )
|
||||
@@ -295,8 +297,10 @@ void GitPlugin::updateStatus( bool force ) {
|
||||
mRunningUpdateStatus++;
|
||||
mThreadPool->run(
|
||||
[this, force] {
|
||||
if ( !mGit || mGit->getGitFolder().empty() )
|
||||
if ( !mGit || mGit->getGitFolder().empty() ) {
|
||||
getUISceneNode()->runOnMainThread( [this] { updateStatusBarSync(); } );
|
||||
return;
|
||||
}
|
||||
|
||||
auto prevBranch = updateReposBranches();
|
||||
Git::Status prevGitStatus;
|
||||
@@ -323,11 +327,21 @@ PluginRequestHandle GitPlugin::processMessage( const PluginMessage& msg ) {
|
||||
if ( mGit ) {
|
||||
mGit->setProjectPath( msg.asJSON()["folder"] );
|
||||
|
||||
{
|
||||
Lock l( mGitBranchMutex );
|
||||
mGitBranches.clear();
|
||||
}
|
||||
|
||||
{
|
||||
Lock l( mRepoMutex );
|
||||
mProjectPath = mRepoSelected = mGit->getProjectPath();
|
||||
}
|
||||
|
||||
{
|
||||
Lock l( mReposMutex );
|
||||
mRepos.clear();
|
||||
}
|
||||
|
||||
updateUINow( true );
|
||||
mInitialized = true;
|
||||
}
|
||||
@@ -626,45 +640,66 @@ void GitPlugin::branchCreate() {
|
||||
}
|
||||
|
||||
void GitPlugin::commit( const std::string& repoPath ) {
|
||||
if ( !mGitStatus.hasStagedChanges( mGit->repoName( repoPath, true ) ) ) {
|
||||
UIMessageBox* msgBox = UIMessageBox::New(
|
||||
UIMessageBox::OK, i18n( "git_nothing_to_commit", "Nothing to Commit" ) );
|
||||
msgBox->setCloseShortcut( { KEY_ESCAPE, KEYMOD_NONE } );
|
||||
msgBox->setTitle( i18n( "git_nothing_to_commit", "Nothing to Commit" ) );
|
||||
msgBox->center();
|
||||
msgBox->showWhenReady();
|
||||
return;
|
||||
}
|
||||
|
||||
UIMessageBox* msgBox = UIMessageBox::New( UIMessageBox::TEXT_EDIT,
|
||||
i18n( "git_commit_message", "Commit Message:" ) );
|
||||
|
||||
UICheckBox* chkBox = UICheckBox::New();
|
||||
chkBox->setLayoutMargin( Rectf( 0, 8, 0, 0 ) )
|
||||
UICheckBox* chkAmmend = UICheckBox::New();
|
||||
chkAmmend->setLayoutMargin( Rectf( 0, 8, 0, 0 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent )
|
||||
->setLayoutGravity( UI_HALIGN_LEFT | UI_VALIGN_CENTER )
|
||||
->setClipType( ClipType::None )
|
||||
->setParent( msgBox->getLayoutCont()->getFirstChild() )
|
||||
->setId( "git-ammend" );
|
||||
chkBox->setText( i18n( "git_ammend", "Ammend last commit" ) );
|
||||
chkBox->toPosition( 2 );
|
||||
chkAmmend->setText( i18n( "git_ammend", "Ammend last commit" ) );
|
||||
chkAmmend->toPosition( 2 );
|
||||
|
||||
UICheckBox* chkBypassHook = UICheckBox::New();
|
||||
chkBypassHook->setLayoutMargin( Rectf( 0, 8, 0, 0 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent )
|
||||
->setLayoutGravity( UI_HALIGN_LEFT | UI_VALIGN_CENTER )
|
||||
->setClipType( ClipType::None )
|
||||
->setParent( msgBox->getLayoutCont()->getFirstChild() )
|
||||
->setId( "git-bypass-hook" );
|
||||
chkBypassHook->setText( i18n( "git_bypass_hook", "Bypass commit hook" ) );
|
||||
chkBypassHook->toPosition( 3 );
|
||||
|
||||
if ( !repoPath.empty() ) {
|
||||
auto branchName = mGitBranches[repoPath];
|
||||
if ( !branchName.empty() ) {
|
||||
if ( repoPath != repoSelected() || mBranchesTree->getModel() == nullptr ) {
|
||||
|
||||
if ( repoPath != repoSelected() || !mBranchesTree->getModel() ) {
|
||||
auto branch = mGit->getAllBranchesAndTags( Git::RefType::All,
|
||||
"refs/heads/" + branchName, repoPath );
|
||||
if ( !branch.empty() )
|
||||
chkBox->setEnabled( branch.front().ahead > 0 );
|
||||
|
||||
chkAmmend->setEnabled( branch.front().ahead > 0 );
|
||||
} else {
|
||||
auto model = static_cast<const GitBranchModel*>( mBranchesTree->getModel() );
|
||||
auto branch = model->branch( branchName );
|
||||
if ( !branch.name.empty() )
|
||||
chkBox->setEnabled( branch.ahead > 0 );
|
||||
chkAmmend->setEnabled( branch.ahead > 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msgBox->on( Event::OnConfirm, [this, msgBox, chkBox]( const Event* ) {
|
||||
msgBox->on( Event::OnConfirm, [this, msgBox, chkAmmend, chkBypassHook]( const Event* ) {
|
||||
std::string msg( msgBox->getTextEdit()->getText().toUtf8() );
|
||||
if ( msg.empty() )
|
||||
return;
|
||||
bool ammend = chkAmmend->isChecked();
|
||||
bool bypassHook = chkBypassHook->isChecked();
|
||||
msgBox->closeWindow();
|
||||
runAsync( [this, msg, chkBox]() { return mGit->commit( msg, chkBox->isChecked() ); }, true,
|
||||
true );
|
||||
runAsync(
|
||||
[this, msg, ammend, bypassHook]() { return mGit->commit( msg, ammend, bypassHook ); },
|
||||
true, true );
|
||||
} );
|
||||
|
||||
msgBox->setCloseShortcut( { KEY_ESCAPE, KEYMOD_NONE } );
|
||||
@@ -859,15 +894,17 @@ void GitPlugin::updateBranches( bool force ) {
|
||||
mRunningUpdateBranches++;
|
||||
mThreadPool->run(
|
||||
[this] {
|
||||
if ( !mGit || mGit->getGitFolder().empty() )
|
||||
if ( !mGit || mGit->getGitFolder().empty() ) {
|
||||
getUISceneNode()->runOnMainThread( [this] { updateBranchesUI( nullptr ); } );
|
||||
return;
|
||||
}
|
||||
|
||||
auto prevBranch = updateReposBranches();
|
||||
auto branches = mGit->getAllBranchesAndTags( Git::RefType::All, {}, repoSelected() );
|
||||
auto hash = GitBranchModel::hashBranches( branches );
|
||||
auto model = GitBranchModel::asModel( std::move( branches ), hash, this );
|
||||
|
||||
if ( mBranchesTree &&
|
||||
if ( mBranchesTree && mBranchesTree->getModel() &&
|
||||
static_cast<GitBranchModel*>( mBranchesTree->getModel() )->getHash() == hash ) {
|
||||
if ( prevBranch != mGitBranches )
|
||||
mBranchesTree->getModel()->invalidate( Model::DontInvalidateIndexes );
|
||||
@@ -903,17 +940,38 @@ void GitPlugin::updateRepos() {
|
||||
|
||||
void GitPlugin::updateBranchesUI( std::shared_ptr<GitBranchModel> model ) {
|
||||
buildSidePanelTab();
|
||||
mBranchesTree->setModel( model );
|
||||
mBranchesTree->setColumnsVisible( { GitBranchModel::Name } );
|
||||
mBranchesTree->expandAll();
|
||||
|
||||
if ( !model ) {
|
||||
mBranchesTree->setModel( model );
|
||||
} else {
|
||||
mBranchesTree->setModel( model );
|
||||
mBranchesTree->setColumnsVisible( { GitBranchModel::Name } );
|
||||
mBranchesTree->expandAll();
|
||||
}
|
||||
|
||||
updateRepos();
|
||||
|
||||
std::vector<String> items;
|
||||
for ( const auto& repo : mRepos )
|
||||
std::unordered_map<std::string, std::string> repos;
|
||||
{
|
||||
Lock l( mReposMutex );
|
||||
repos = mRepos;
|
||||
}
|
||||
|
||||
for ( const auto& repo : repos )
|
||||
items.push_back( repo.second );
|
||||
|
||||
mRepoDropDown->getListBox()->clear();
|
||||
mRepoDropDown->getListBox()->addListBoxItems( items );
|
||||
mRepoDropDown->getListBox()->setSelected( mRepos[repoSelected()] );
|
||||
if ( repos.empty() || ( repos.size() == 1 && repos.begin()->second == "" ) ) {
|
||||
if ( !mRepoDropDown->getListBox()->isEmpty() )
|
||||
mRepoDropDown->getListBox()->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mRepoDropDown->getListBox()->getItemsText() != items ) {
|
||||
mRepoDropDown->getListBox()->clear();
|
||||
mRepoDropDown->getListBox()->addListBoxItems( items );
|
||||
mRepoDropDown->getListBox()->setSelected( mRepos[repoSelected()] );
|
||||
}
|
||||
}
|
||||
|
||||
void GitPlugin::buildSidePanelTab() {
|
||||
@@ -998,7 +1056,7 @@ void GitPlugin::buildSidePanelTab() {
|
||||
mBranchesTree->on( Event::KeyDown, [this]( const Event* event ) {
|
||||
const KeyEvent* keyEvent = event->asKeyEvent();
|
||||
ModelIndex modelIndex = mBranchesTree->getSelection().first();
|
||||
if ( !modelIndex.isValid() || modelIndex.internalId() == -1 )
|
||||
if ( !modelIndex.isValid() || modelIndex.internalId() == -1 || !mBranchesTree->getModel() )
|
||||
return;
|
||||
Git::Branch branch =
|
||||
static_cast<const GitBranchModel*>( mBranchesTree->getModel() )->branch( modelIndex );
|
||||
@@ -1224,7 +1282,7 @@ void GitPlugin::runAsync( std::function<Git::Result()> fn, bool _updateStatus, b
|
||||
mLoader->setVisible( true );
|
||||
mThreadPool->run( [this, fn, _updateStatus, _updateBranches, displaySuccessMsg] {
|
||||
auto res = fn();
|
||||
getUISceneNode()->runOnMainThread( [this] { mLoader->setVisible( false ); } );
|
||||
mLoader->runOnMainThread( [this] { mLoader->setVisible( false ); } );
|
||||
if ( res.fail() || displaySuccessMsg ) {
|
||||
showMessage( LSPMessageType::Warning, res.result );
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user