Fix git status icons not showing when project opened via symlink
When a project is opened through a symlinked path, libgit2's git_repository_workdir() returns the canonical path with symlinks resolved. This caused a path mismatch between the tree cache (which uses the user-provided symlinked path) and git status results (which used canonical paths), preventing status icons from being displayed. The fix introduces SetProjectDir()/GetProjectDir() methods to KIGIT_COMMON to store and use the user-provided project path. A helper function computeSymlinkPreservingWorkDir() computes the git working directory path while preserving symlinks from the original user path. Fixes https://gitlab.com/kicad/code/kicad/-/issues/21092
This commit is contained in:
@@ -24,9 +24,15 @@
|
||||
#include "project_git_utils.h"
|
||||
#include "git_backend.h"
|
||||
|
||||
#include <wx/filename.h>
|
||||
#include <wx/string.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
namespace KIGIT
|
||||
{
|
||||
|
||||
@@ -76,4 +82,79 @@ wxString PROJECT_GIT_UTILS::GetCurrentHash( const wxString& aProjectFile, bool a
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
wxString PROJECT_GIT_UTILS::ComputeSymlinkPreservingWorkDir( const wxString& aUserProjectPath,
|
||||
const wxString& aCanonicalWorkDir )
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
return aCanonicalWorkDir;
|
||||
#else
|
||||
if( aUserProjectPath.IsEmpty() || aCanonicalWorkDir.IsEmpty() )
|
||||
return aCanonicalWorkDir;
|
||||
|
||||
char resolvedPath[PATH_MAX];
|
||||
|
||||
if( realpath( aUserProjectPath.mb_str(), resolvedPath ) == nullptr )
|
||||
return aCanonicalWorkDir;
|
||||
|
||||
wxString canonicalUserPath = wxString::FromUTF8( resolvedPath );
|
||||
|
||||
if( !canonicalUserPath.EndsWith( wxFileName::GetPathSeparator() ) )
|
||||
canonicalUserPath += wxFileName::GetPathSeparator();
|
||||
|
||||
wxString canonicalWorkDirNorm = aCanonicalWorkDir;
|
||||
|
||||
if( !canonicalWorkDirNorm.EndsWith( wxFileName::GetPathSeparator() ) )
|
||||
canonicalWorkDirNorm += wxFileName::GetPathSeparator();
|
||||
|
||||
// The workdir could be at or above the project directory
|
||||
if( canonicalUserPath.StartsWith( canonicalWorkDirNorm ) )
|
||||
{
|
||||
return aUserProjectPath.EndsWith( wxFileName::GetPathSeparator() )
|
||||
? aUserProjectPath
|
||||
: aUserProjectPath + wxFileName::GetPathSeparator();
|
||||
}
|
||||
|
||||
// The workdir is above the user path - find the portion that corresponds to the workdir
|
||||
wxFileName userFn( aUserProjectPath );
|
||||
wxFileName workDirFn( aCanonicalWorkDir );
|
||||
wxArrayString workDirParts = workDirFn.GetDirs();
|
||||
size_t workDirDepth = workDirParts.GetCount();
|
||||
|
||||
wxFileName canonicalUserFn( canonicalUserPath );
|
||||
wxArrayString canonicalUserParts = canonicalUserFn.GetDirs();
|
||||
|
||||
if( canonicalUserParts.GetCount() < workDirDepth )
|
||||
return aCanonicalWorkDir;
|
||||
|
||||
wxArrayString canonicalWorkDirParts = workDirFn.GetDirs();
|
||||
|
||||
for( size_t i = 0; i < workDirDepth; ++i )
|
||||
{
|
||||
if( canonicalUserParts[i] != canonicalWorkDirParts[i] )
|
||||
return aCanonicalWorkDir;
|
||||
}
|
||||
|
||||
wxArrayString userParts = userFn.GetDirs();
|
||||
|
||||
if( userParts.GetCount() < workDirDepth )
|
||||
return aCanonicalWorkDir;
|
||||
|
||||
wxString result = userFn.GetVolume();
|
||||
|
||||
if( !result.IsEmpty() )
|
||||
result += wxFileName::GetVolumeSeparator();
|
||||
|
||||
result += wxFileName::GetPathSeparator();
|
||||
|
||||
for( size_t i = 0; i < workDirDepth; ++i )
|
||||
{
|
||||
result += userParts[i];
|
||||
result += wxFileName::GetPathSeparator();
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace KIGIT
|
||||
|
||||
Reference in New Issue
Block a user