KiCad PCB EDA Suite
Loading...
Searching...
No Matches
project_git_utils.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "project_git_utils.h"
21#include "git_backend.h"
22
23#include <wx/filename.h>
24#include <wx/string.h>
25#include <string_utils.h>
26
27#ifndef __WINDOWS__
28#include <climits>
29#include <cstdlib>
30#endif
31
32namespace KIGIT
33{
34
35git_repository* PROJECT_GIT_UTILS::GetRepositoryForFile( const char* aFilename )
36{
37 GIT_BACKEND* backend = GetGitBackend();
38
39 if( !backend )
40 return nullptr;
41
42 return backend->GetRepositoryForFile( aFilename );
43}
44
45
46int PROJECT_GIT_UTILS::CreateBranch( git_repository* aRepo, const wxString& aBranchName )
47{
48 GIT_BACKEND* backend = GetGitBackend();
49
50 if( !backend )
51 return -1;
52
53 return backend->CreateBranch( aRepo, aBranchName );
54}
55
56
57bool PROJECT_GIT_UTILS::RemoveVCS( git_repository*& aRepo, const wxString& aProjectPath,
58 bool aRemoveGitDir, wxString* aErrors )
59{
60 GIT_BACKEND* backend = GetGitBackend();
61
62 if( !backend )
63 return false;
64
65 return backend->RemoveVCS( aRepo, aProjectPath, aRemoveGitDir, aErrors );
66}
67
68
69wxString PROJECT_GIT_UTILS::GetCurrentHash( const wxString& aProjectFile, bool aShort )
70{
71 wxString result = wxT( "no hash" );
72 git_repository* repo = PROJECT_GIT_UTILS::GetRepositoryForFile( TO_UTF8( aProjectFile ) );
73
74 if( repo )
75 {
76 git_reference* head = nullptr;
77
78 if( git_repository_head( &head, repo ) == 0 )
79 {
80 const git_oid* oid = git_reference_target( head );
81
82 if( oid )
83 {
84 char buf[GIT_OID_HEXSZ + 1];
85 size_t len = aShort ? 9 : GIT_OID_HEXSZ + 1; // 8 chars + null terminator
86 git_oid_tostr( buf, len, oid );
87 result = wxString::FromUTF8( buf );
88 }
89
90 git_reference_free( head );
91 }
92
93 git_repository_free( repo );
94 }
95
96 return result;
97}
98
99
100wxString PROJECT_GIT_UTILS::ComputeSymlinkPreservingWorkDir( const wxString& aUserProjectPath,
101 const wxString& aCanonicalWorkDir )
102{
103#ifdef __WINDOWS__
104 return aCanonicalWorkDir;
105#else
106 if( aUserProjectPath.IsEmpty() || aCanonicalWorkDir.IsEmpty() )
107 return aCanonicalWorkDir;
108
109 char resolvedPath[PATH_MAX];
110
111 if( realpath( aUserProjectPath.mb_str(), resolvedPath ) == nullptr )
112 return aCanonicalWorkDir;
113
114 wxString canonicalUserPath = wxString::FromUTF8( resolvedPath );
115
116 if( !canonicalUserPath.EndsWith( wxFileName::GetPathSeparator() ) )
117 canonicalUserPath += wxFileName::GetPathSeparator();
118
119 wxString canonicalWorkDirNorm = aCanonicalWorkDir;
120
121 if( !canonicalWorkDirNorm.EndsWith( wxFileName::GetPathSeparator() ) )
122 canonicalWorkDirNorm += wxFileName::GetPathSeparator();
123
124 // The user project path resolves to the same directory as the git workdir (e.g., the
125 // project is at the repo root but opened via a symlinked path). Return the user path
126 // to preserve symlinks. When the project is in a subdirectory of the workdir, the
127 // paths will differ and we fall through to extract only the workdir portion below.
128 if( canonicalUserPath == canonicalWorkDirNorm )
129 {
130 return aUserProjectPath.EndsWith( wxFileName::GetPathSeparator() )
131 ? aUserProjectPath
132 : aUserProjectPath + wxFileName::GetPathSeparator();
133 }
134
135 // Walk both paths upward in lockstep until the canonical user path matches the canonical
136 // workdir. This correctly handles symlinks that compress multiple canonical path
137 // components into fewer visible components (e.g. /work/repo -> /real/deep/path/root).
138 wxFileName userFn;
139 userFn.AssignDir( aUserProjectPath );
140
141 wxFileName canonicalUserFn;
142 canonicalUserFn.AssignDir( canonicalUserPath );
143
144 wxFileName canonicalWorkDirFn;
145 canonicalWorkDirFn.AssignDir( canonicalWorkDirNorm );
146
147 while( canonicalUserFn.GetFullPath() != canonicalWorkDirFn.GetFullPath() )
148 {
149 if( canonicalUserFn.GetDirCount() == 0 || userFn.GetDirCount() == 0 )
150 return aCanonicalWorkDir;
151
152 canonicalUserFn.RemoveLastDir();
153 userFn.RemoveLastDir();
154 }
155
156 return userFn.GetPathWithSep();
157#endif
158}
159
160} // namespace KIGIT
virtual int CreateBranch(git_repository *aRepo, const wxString &aBranchName)=0
virtual bool RemoveVCS(git_repository *&aRepo, const wxString &aProjectPath, bool aRemoveGitDir, wxString *aErrors)=0
virtual git_repository * GetRepositoryForFile(const char *aFilename)=0
static wxString GetCurrentHash(const wxString &aProjectFile, bool aShort)
Return the current HEAD commit hash for the repository containing aProjectFile.
static git_repository * GetRepositoryForFile(const char *aFilename)
Discover and open the repository that contains the given file.
static wxString ComputeSymlinkPreservingWorkDir(const wxString &aUserProjectPath, const wxString &aCanonicalWorkDir)
Compute a working directory path that preserves symlinks from the user's project path.
static bool RemoveVCS(git_repository *&aRepo, const wxString &aProjectPath=wxEmptyString, bool aRemoveGitDir=false, wxString *aErrors=nullptr)
Remove version control from a directory by freeing the repository and optionally removing the ....
static int CreateBranch(git_repository *aRepo, const wxString &aBranchName)
Create a new branch based on HEAD.
GIT_BACKEND * GetGitBackend()
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
wxString result
Test unit parsing edge cases and error handling.