Skip to content

Commit

Permalink
Git models as trees
Browse files Browse the repository at this point in the history
  • Loading branch information
SpartanJ committed Jan 14, 2024
1 parent 9e764c8 commit f79d49e
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 42 deletions.
19 changes: 11 additions & 8 deletions src/tools/ecode/featureshealth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ class HealthModel : public Model {
}

virtual Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const {
static const char* SUCCESS = "theme-success";
static const char* ERROR = "theme-error";
static const char* NONE = "theme-none";

eeASSERT( index.row() < (Int64)mData.size() );
static std::string none;
static UIIcon* icon = nullptr;
Expand Down Expand Up @@ -302,25 +306,24 @@ class HealthModel : public Model {
case ModelRole::Class: {
switch ( index.column() ) {
case 1:
return Variant( "theme-success" );
return Variant( SUCCESS );
case 2:
if ( !lang.lsp.name.empty() )
return Variant( lang.lsp.found ? "theme-success" : "theme-error" );
return Variant( lang.lsp.found ? SUCCESS : ERROR );
else
return Variant( "theme-none" );
return Variant( NONE );
break;
case 3:
if ( !lang.linter.name.empty() )
return Variant( lang.linter.found ? "theme-success" : "theme-error" );
return Variant( lang.linter.found ? SUCCESS : ERROR );
else
return Variant( "theme-none" );
return Variant( NONE );
break;
case 4:
if ( !lang.formatter.name.empty() )
return Variant( lang.formatter.found ? "theme-success"
: "theme-error" );
return Variant( lang.formatter.found ? SUCCESS : ERROR );
else
return Variant( "theme-none" );
return Variant( NONE );
break;
default: {
}
Expand Down
112 changes: 91 additions & 21 deletions src/tools/ecode/plugins/git/git.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ int Git::git( const std::string& args, const std::string& projectDir, std::strin
p.readAllStdOut( buf );
int retCode;
p.join( &retCode );
if ( mLastProjectPath != projectDir ) {
const_cast<Git*>( this )->mLastProjectPath = projectDir;
const_cast<Git*>( this )->mSubModulesUpdated = false;
}
return retCode;
}

Expand Down Expand Up @@ -205,23 +209,65 @@ std::vector<Git::Branch> Git::getAllBranchesAndTags( RefType ref, const std::str
return branches;
}

static void readAllLines( const std::string_view& buf,
std::function<void( const std::string_view& )> onLineRead ) {
auto lastNL = 0;
auto nextNL = buf.find_first_of( '\n' );
while ( nextNL != std::string_view::npos ) {
onLineRead( buf.substr( lastNL, nextNL - lastNL ) );
lastNL = nextNL;
nextNL = buf.find_first_of( '\n', nextNL + 1 );
}
}

std::vector<std::string> Git::fetchSubModules( const std::string& projectDir ) {
std::vector<std::string> submodules;
std::string buf;
FileSystem::fileGet( ( !projectDir.empty() ? projectDir : mProjectPath ) + ".gitmodules", buf );
LuaPattern pattern( "^%s*path%s*=%s*(.+)" );
readAllLines( buf, [&pattern, &submodules]( const std::string_view& line ) {
LuaPattern::Range matches[2];
if ( pattern.matches( line.data(), 0, matches, line.size() ) ) {
submodules.emplace_back(
line.substr( matches[1].start, matches[1].end - matches[1].start ) );
}
} );
return submodules;
}

std::vector<std::string> Git::getSubModules( const std::string& projectDir ) {
if ( !mSubModulesUpdated ) {
mSubModules = fetchSubModules( projectDir );
mSubModulesUpdated = true;
}
return mSubModules;
}

bool Git::hasSubmodules( const std::string& projectDir ) {
return ( !projectDir.empty() && FileSystem::fileExists( projectDir + ".gitmodules" ) ) ||
( !mProjectPath.empty() && FileSystem::fileExists( mProjectPath + ".gitmodules" ) );
}

std::string Git::inSubModule( const std::string& file, const std::string& projectDir ) {
for ( const auto& subRepo : mSubModules ) {
if ( String::startsWith( file, subRepo ) )
return subRepo;
}
return FileSystem::fileNameFromPath( !projectDir.empty() ? projectDir : mProjectPath );
}

Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir ) {
static constexpr auto DIFF_CMD = "diff --numstat";
static constexpr auto STATUS_CMD = "-c color.status=never status -b -u -s";
Status s;
std::string buf;
if ( EXIT_SUCCESS != git( DIFF_CMD, projectDir, buf ) )
return s;
auto parseNumStat = [&s, &buf]() {
auto parseNumStat = [&s, &buf, &projectDir, this]() {
auto lastNL = 0;
auto nextNL = buf.find_first_of( '\n' );
LuaPattern pattern( "(%d+)%s+(%d+)%s+(.+)" );
while ( nextNL != std::string_view::npos ) {
LuaPattern pattern( "(%d+)%s+(%d+)%s+(.+)" );
LuaPattern::Range matches[4];
if ( pattern.matches( buf.c_str(), lastNL, matches, nextNL ) ) {
auto inserted = buf.substr( matches[1].start, matches[1].end - matches[1].start );
Expand All @@ -231,13 +277,22 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
int deletes;
if ( String::fromString( inserts, inserted ) &&
String::fromString( deletes, deleted ) ) {
auto fileIt = s.files.find( file );
if ( fileIt != s.files.end() ) {
fileIt->second.file = std::move( file );
fileIt->second.inserts = inserts;
fileIt->second.deletes = deletes;
auto repo = inSubModule( file, projectDir );
auto repoIt = s.files.find( repo );
if ( repoIt != s.files.end() ) {
bool found = false;
for ( auto& fileIt : repoIt->second ) {
if ( fileIt.file == file ) {
fileIt.inserts = inserts;
fileIt.deletes = deletes;
found = true;
break;
}
}
if ( !found )
s.files[repo].push_back( { std::move( file ), inserts, deletes } );
} else {
s.files.insert( { file, { file, inserts, deletes } } );
s.files.insert( { repo, { { std::move( file ), inserts, deletes } } } );
}
s.totalInserts += inserts;
s.totalDeletions += deletes;
Expand All @@ -257,12 +312,14 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
parseNumStat();
}

getSubModules( projectDir );

bool modifiedSubmodule = false;
auto parseStatus = [&s, &buf, &modifiedSubmodule]() {
auto parseStatus = [&s, &buf, &modifiedSubmodule, &projectDir, this]() {
auto lastNL = 0;
auto nextNL = buf.find_first_of( '\n' );
LuaPattern pattern( "\n([%sA?][MARTUD?%s])%s(.*)" );
while ( nextNL != std::string_view::npos ) {
LuaPattern pattern( "\n([%sA?][MARTUD?%s])%s(.*)" );
LuaPattern::Range matches[3];
if ( pattern.matches( buf.c_str(), lastNL, matches, nextNL ) ) {
auto status = buf.substr( matches[1].start, matches[1].end - matches[1].start );
Expand Down Expand Up @@ -290,11 +347,22 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
if ( rstatus == FileStatus::ModifiedSubmodule )
modifiedSubmodule = true;
else {
auto fileIt = s.files.find( file );
if ( fileIt != s.files.end() )
fileIt->second.status = rstatus;
else
s.files.insert( { file, { file, 0, 0, rstatus } } );
auto repo = inSubModule( file, projectDir );
auto repoIt = s.files.find( repo );
if ( repoIt != s.files.end() ) {
bool found = false;
for ( auto& fileIt : repoIt->second ) {
if ( fileIt.file == file ) {
fileIt.status = rstatus;
found = true;
break;
}
}
if ( !found )
s.files[repo].push_back( { std::move( file ), 0, 0, rstatus } );
} else {
s.files.insert( { file, { { file, 0, 0, rstatus } } } );
}
}
}
}
Expand All @@ -311,12 +379,14 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
parseStatus();
}

for ( auto& [_, val] : s.files ) {
if ( val.status == FileStatus::Added && val.inserts == 0 ) {
std::string fileText;
FileSystem::fileGet( ( projectDir.empty() ? mProjectPath : projectDir ) + val.file,
fileText );
val.inserts = countLines( fileText );
for ( auto& [_, repo] : s.files ) {
for ( auto& val : repo ) {
if ( val.status == FileStatus::Added && val.inserts == 0 ) {
std::string fileText;
FileSystem::fileGet( ( projectDir.empty() ? mProjectPath : projectDir ) + val.file,
fileText );
val.inserts = countLines( fileText );
}
}
}

Expand Down
12 changes: 11 additions & 1 deletion src/tools/ecode/plugins/git/git.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class Git {
}
};

using FilesStatus = std::map<std::string, DiffFile>;
using RepositoryName = std::string;
using FilesStatus = std::map<RepositoryName, std::vector<DiffFile>>;

struct Status {
int totalInserts{ 0 };
Expand Down Expand Up @@ -147,12 +148,21 @@ class Git {
std::vector<Branch> getAllBranchesAndTags( RefType ref = RefType::All,
const std::string& projectDir = "" );

std::vector<std::string> fetchSubModules( const std::string& projectDir );

std::vector<std::string> getSubModules( const std::string& projectDir = "" );

protected:
std::string mGitPath;
std::string mProjectPath;
std::string mGitFolder;
std::string mLastProjectPath;
std::vector<std::string> mSubModules;
bool mSubModulesUpdated{ false };

bool hasSubmodules( const std::string& projectDir );

std::string inSubModule( const std::string& file, const std::string& projectDir );
};

} // namespace ecode
Loading

0 comments on commit f79d49e

Please sign in to comment.