Parse git status

This commit is contained in:
Martín Lucas Golini
2024-01-03 00:06:59 -03:00
parent ffbd2c92df
commit fa3b08a1bd
3 changed files with 93 additions and 11 deletions

View File

@@ -1290,6 +1290,10 @@
../../src/tools/ecode/notificationcenter.cpp
../../src/tools/ecode/notificationcenter.hpp
../../src/tools/ecode/pathhelper.hpp
../../src/tools/ecode/plugins/git/git.cpp
../../src/tools/ecode/plugins/git/git.hpp
../../src/tools/ecode/plugins/git/gitplugin.cpp
../../src/tools/ecode/plugins/git/gitplugin.hpp
../../src/tools/ecode/plugins/linter/linterplugin.cpp
../../src/tools/ecode/plugins/linter/linterplugin.hpp
../../src/tools/ecode/plugins/lsp/lspclientplugin.cpp
@@ -1302,6 +1306,8 @@
../../src/tools/ecode/plugins/lsp/lspdocumentclient.cpp
../../src/tools/ecode/plugins/lsp/lspdocumentclient.hpp
../../src/tools/ecode/plugins/lsp/lspprotocol.hpp
../../src/tools/ecode/plugins/plugin.cpp
../../src/tools/ecode/plugins/plugin.hpp
../../src/tools/ecode/plugins/pluginmanager.cpp
../../src/tools/ecode/plugins/pluginmanager.hpp
../../src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp

View File

@@ -42,6 +42,11 @@ void Git::git( const std::string& args, const std::string& projectDir, std::stri
p.readAllStdOut( buf );
}
void Git::gitSubmodules( const std::string& args, const std::string& projectDir,
std::string& buf ) {
git( String::format( "submodule foreach \"git %s\"", args.c_str() ), projectDir, buf );
}
std::string Git::branch( const std::string& projectDir ) {
std::string buf;
git( "rev-parse --abbrev-ref HEAD", projectDir, buf );
@@ -83,11 +88,18 @@ const std::string& Git::getGitFolder() const {
return mGitFolder;
}
bool Git::hasSubmodules( const std::string& projectDir ) {
return ( !projectDir.empty() && FileSystem::fileExists( projectDir + ".gitmodules" ) ) ||
( !mProjectPath.empty() && FileSystem::fileExists( mProjectPath + ".gitmodules" ) );
}
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;
git( "diff --numstat", projectDir, buf );
auto parseStatus = [&s, &buf]() {
git( DIFF_CMD, projectDir, buf );
auto parseNumStat = [&s, &buf]() {
auto lastNL = 0;
auto nextNL = buf.find_first_of( '\n' );
while ( nextNL != std::string_view::npos ) {
@@ -111,16 +123,62 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
}
};
parseNumStat();
bool submodules = hasSubmodules( projectDir );
if ( recurseSubmodules && submodules ) {
gitSubmodules( DIFF_CMD, projectDir, buf );
parseNumStat();
}
bool modifiedSubmodule = false;
auto parseStatus = [&s, &buf, &modifiedSubmodule]() {
auto lastNL = 0;
auto nextNL = buf.find_first_of( '\n' );
while ( nextNL != std::string_view::npos ) {
LuaPattern pattern( "\n([%s?][MARTUD?])%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 );
String::trimInPlace( status );
auto file = buf.substr( matches[2].start, matches[2].end - matches[2].start );
FileStatus rstatus = FileStatus::Unidentified;
if ( "??" == status )
rstatus = FileStatus::Untracked;
else if ( "M" == status )
rstatus = FileStatus::Modified;
else if ( "A" == status )
rstatus = FileStatus::Added;
else if ( "D" == status )
rstatus = FileStatus::Deleted;
else if ( "R" == status )
rstatus = FileStatus::Renamed;
else if ( "T" == status )
rstatus = FileStatus::TypeChanged;
else if ( "U" == status )
rstatus = FileStatus::UpdatedUnmerged;
else if ( "m" == status )
rstatus = FileStatus::ModifiedSubmodule;
if ( rstatus != FileStatus::Unidentified ) {
if ( rstatus != FileStatus::ModifiedSubmodule )
modifiedSubmodule = true;
else
s.files.insert( { std::move( file ), rstatus } );
}
}
lastNL = nextNL;
nextNL = buf.find_first_of( '\n', nextNL + 1 );
}
};
git( STATUS_CMD, projectDir, buf );
parseStatus();
if ( recurseSubmodules ) {
bool hasSubmodules =
( !projectDir.empty() && FileSystem::fileExists( projectDir + ".gitmodules" ) ) ||
( !mProjectPath.empty() && FileSystem::fileExists( mProjectPath + ".gitmodules" ) );
if ( hasSubmodules ) {
git( "submodule foreach \"git diff --numstat\"", projectDir, buf );
parseStatus();
}
if ( modifiedSubmodule && submodules ) {
gitSubmodules( STATUS_CMD, projectDir, buf );
parseStatus();
}
return s;

View File

@@ -1,3 +1,4 @@
#include <map>
#include <string>
#include <vector>
@@ -32,14 +33,27 @@ class Git {
}
};
enum FileStatus {
Unidentified,
Modified = 'M',
Added = 'A',
Renamed = 'R',
TypeChanged = 'T',
UpdatedUnmerged = 'U',
Deleted = 'D',
Untracked = '?',
ModifiedSubmodule = 'm',
};
struct Status {
std::vector<DiffFile> modified;
int totalInserts{ 0 };
int totalDeletions{ 0 };
std::map<std::string, FileStatus> files;
bool operator==( const Status& other ) const {
return totalInserts == other.totalInserts && totalDeletions == other.totalDeletions &&
modified == other.modified;
modified == other.modified && files == other.files;
}
};
@@ -47,6 +61,8 @@ class Git {
void git( const std::string& args, const std::string& projectDir, std::string& buf ) const;
void gitSubmodules( const std::string& args, const std::string& projectDir, std::string& buf );
Blame blame( const std::string& filepath, std::size_t line ) const;
std::string branch( const std::string& projectDir = "" );
@@ -65,6 +81,8 @@ class Git {
std::string mGitPath;
std::string mProjectPath;
std::string mGitFolder;
bool hasSubmodules( const std::string& projectDir );
};
} // namespace ecode