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, you may find one here:
18 * http://www.gnu.org/licenses/gpl-3.0.html
19 * or you may search the http://www.gnu.org website for the version 3 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include "project_git_utils.h"
25#include "git_backend.h"
26
27#include <wx/filename.h>
28#include <wx/string.h>
29#include <string_utils.h>
30
31#ifndef __WINDOWS__
32#include <climits>
33#include <cstdlib>
34#endif
35
36namespace KIGIT
37{
38
39git_repository* PROJECT_GIT_UTILS::GetRepositoryForFile( const char* aFilename )
40{
41 GIT_BACKEND* backend = GetGitBackend();
42
43 if( !backend )
44 return nullptr;
45
46 return backend->GetRepositoryForFile( aFilename );
47}
48
49
50int PROJECT_GIT_UTILS::CreateBranch( git_repository* aRepo, const wxString& aBranchName )
51{
52 GIT_BACKEND* backend = GetGitBackend();
53
54 if( !backend )
55 return -1;
56
57 return backend->CreateBranch( aRepo, aBranchName );
58}
59
60
61bool PROJECT_GIT_UTILS::RemoveVCS( git_repository*& aRepo, const wxString& aProjectPath,
62 bool aRemoveGitDir, wxString* aErrors )
63{
64 GIT_BACKEND* backend = GetGitBackend();
65
66 if( !backend )
67 return false;
68
69 return backend->RemoveVCS( aRepo, aProjectPath, aRemoveGitDir, aErrors );
70}
71
72
73wxString PROJECT_GIT_UTILS::GetCurrentHash( const wxString& aProjectFile, bool aShort )
74{
75 wxString result = wxT( "no hash" );
76 git_repository* repo = PROJECT_GIT_UTILS::GetRepositoryForFile( TO_UTF8( aProjectFile ) );
77
78 if( repo )
79 {
80 git_reference* head = nullptr;
81
82 if( git_repository_head( &head, repo ) == 0 )
83 {
84 const git_oid* oid = git_reference_target( head );
85
86 if( oid )
87 {
88 char buf[GIT_OID_HEXSZ + 1];
89 size_t len = aShort ? 9 : GIT_OID_HEXSZ + 1; // 8 chars + null terminator
90 git_oid_tostr( buf, len, oid );
91 result = wxString::FromUTF8( buf );
92 }
93
94 git_reference_free( head );
95 }
96
97 git_repository_free( repo );
98 }
99
100 return result;
101}
102
103
104wxString PROJECT_GIT_UTILS::ComputeSymlinkPreservingWorkDir( const wxString& aUserProjectPath,
105 const wxString& aCanonicalWorkDir )
106{
107#ifdef __WINDOWS__
108 return aCanonicalWorkDir;
109#else
110 if( aUserProjectPath.IsEmpty() || aCanonicalWorkDir.IsEmpty() )
111 return aCanonicalWorkDir;
112
113 char resolvedPath[PATH_MAX];
114
115 if( realpath( aUserProjectPath.mb_str(), resolvedPath ) == nullptr )
116 return aCanonicalWorkDir;
117
118 wxString canonicalUserPath = wxString::FromUTF8( resolvedPath );
119
120 if( !canonicalUserPath.EndsWith( wxFileName::GetPathSeparator() ) )
121 canonicalUserPath += wxFileName::GetPathSeparator();
122
123 wxString canonicalWorkDirNorm = aCanonicalWorkDir;
124
125 if( !canonicalWorkDirNorm.EndsWith( wxFileName::GetPathSeparator() ) )
126 canonicalWorkDirNorm += wxFileName::GetPathSeparator();
127
128 // The workdir could be at or above the project directory
129 if( canonicalUserPath.StartsWith( canonicalWorkDirNorm ) )
130 {
131 return aUserProjectPath.EndsWith( wxFileName::GetPathSeparator() )
132 ? aUserProjectPath
133 : aUserProjectPath + wxFileName::GetPathSeparator();
134 }
135
136 // The workdir is above the user path - find the portion that corresponds to the workdir
137 wxFileName userFn( aUserProjectPath );
138 wxFileName workDirFn( aCanonicalWorkDir );
139 wxArrayString workDirParts = workDirFn.GetDirs();
140 size_t workDirDepth = workDirParts.GetCount();
141
142 wxFileName canonicalUserFn( canonicalUserPath );
143 wxArrayString canonicalUserParts = canonicalUserFn.GetDirs();
144
145 if( canonicalUserParts.GetCount() < workDirDepth )
146 return aCanonicalWorkDir;
147
148 wxArrayString canonicalWorkDirParts = workDirFn.GetDirs();
149
150 for( size_t i = 0; i < workDirDepth; ++i )
151 {
152 if( canonicalUserParts[i] != canonicalWorkDirParts[i] )
153 return aCanonicalWorkDir;
154 }
155
156 wxArrayString userParts = userFn.GetDirs();
157
158 if( userParts.GetCount() < workDirDepth )
159 return aCanonicalWorkDir;
160
161 wxString result = userFn.GetVolume();
162
163 if( !result.IsEmpty() )
164 result += wxFileName::GetVolumeSeparator();
165
166 result += wxFileName::GetPathSeparator();
167
168 for( size_t i = 0; i < workDirDepth; ++i )
169 {
170 result += userParts[i];
171 result += wxFileName::GetPathSeparator();
172 }
173
174 return result;
175#endif
176}
177
178} // 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.