GitAdminDir: Don't check for \\COMPUTERNAME\.git
[TortoiseGit.git] / src / Git / GitAdminDir.cpp
blob8b1dbab21bce9fe8565860ac007829b6b49626ea
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2015 - TortoiseGit
4 // Copyright (C) 2003-2008 - TortoiseSVN
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 2
9 // of the License, or (at your option) any later version.
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.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "UnicodeUtils.h"
22 #include "GitAdminDir.h"
23 #include "Git.h"
24 #include <memory>
26 GitAdminDir g_GitAdminDir;
28 GitAdminDir::GitAdminDir()
32 GitAdminDir::~GitAdminDir()
36 CString GitAdminDir::GetSuperProjectRoot(const CString& path)
38 CString projectroot=path;
42 if (CGit::GitPathFileExists(projectroot + _T("\\.git")))
44 if (CGit::GitPathFileExists(projectroot + _T("\\.gitmodules")))
45 return projectroot;
46 else
47 return _T("");
50 projectroot = projectroot.Left(projectroot.ReverseFind('\\'));
52 // don't check for \\COMPUTERNAME\.git
53 if (projectroot[0] == _T('\\') && projectroot[1] == _T('\\') && projectroot.Find(_T('\\'), 2) < 0)
54 return _T("");
55 }while(projectroot.ReverseFind('\\')>0);
57 return _T("");
61 CString GitAdminDir::GetGitTopDir(const CString& path)
63 CString str;
64 HasAdminDir(path,!!PathIsDirectory(path),&str);
65 return str;
68 bool GitAdminDir::HasAdminDir(const CString& path) const
70 return HasAdminDir(path, !!PathIsDirectory(path));
73 bool GitAdminDir::HasAdminDir(const CString& path,CString *ProjectTopDir) const
75 return HasAdminDir(path, !!PathIsDirectory(path),ProjectTopDir);
78 bool GitAdminDir::HasAdminDir(const CString& path, bool bDir,CString *ProjectTopDir) const
80 if (path.IsEmpty())
81 return false;
82 CString sDirName = path;
83 if (!bDir)
85 // e.g "C:\"
86 if (path.GetLength() <= 3)
87 return false;
88 sDirName = path.Left(path.ReverseFind(_T('\\')));
91 // a .git dir or anything inside it should be left out, only interested in working copy files -- Myagi
93 int n = 0;
94 for (;;)
96 n = sDirName.Find(_T("\\.git"), n);
97 if (n < 0)
99 break;
102 // check for actual .git dir (and not .gitignore or something else), continue search if false match
103 n += 5;
104 if (sDirName[n] == _T('\\') || sDirName[n] == 0)
106 return false;
111 for (;;)
113 if(CGit::GitPathFileExists(sDirName + _T("\\.git")))
115 if(ProjectTopDir)
117 *ProjectTopDir=sDirName;
118 // Make sure to add the trailing slash to root paths such as 'C:'
119 if (sDirName.GetLength() == 2 && sDirName[1] == _T(':'))
120 (*ProjectTopDir) += _T("\\");
122 return true;
124 else if (IsBareRepo(sDirName))
125 return false;
127 int x = sDirName.ReverseFind(_T('\\'));
128 if (x < 2)
129 break;
131 sDirName = sDirName.Left(x);
132 // don't check for \\COMPUTERNAME\.git
133 if (sDirName[0] == _T('\\') && sDirName[1] == _T('\\') && sDirName.Find(_T('\\'), 2) < 0)
134 break;
137 return false;
141 * Returns the .git-path (if .git is a file, read the repository path and return it)
142 * adminDir always ends with "\"
144 bool GitAdminDir::GetAdminDirPath(const CString &projectTopDir, CString &adminDir) const
146 if (IsBareRepo(projectTopDir))
148 adminDir = projectTopDir;
149 adminDir.TrimRight('\\');
150 adminDir.Append(_T("\\"));
151 return true;
154 CString sDotGitPath = projectTopDir + _T("\\") + g_GitAdminDir.GetAdminDirName();
155 if (CTGitPath(sDotGitPath).IsDirectory())
157 sDotGitPath.TrimRight('\\');
158 sDotGitPath.Append(_T("\\"));
159 adminDir = sDotGitPath;
160 return true;
162 else
164 FILE *pFile;
165 _tfopen_s(&pFile, sDotGitPath, _T("r"));
167 if (!pFile)
168 return false;
170 int size = 65536;
171 std::unique_ptr<char[]> buffer(new char[size]);
172 int length = (int)fread(buffer.get(), sizeof(char), size, pFile);
173 fclose(pFile);
174 CStringA gitPathA(buffer.get(), length);
175 if (length < 8 || gitPathA.Left(8) != "gitdir: ")
176 return false;
177 CString gitPath = CUnicodeUtils::GetUnicode(gitPathA.Trim().Mid(8)); // 8 = len("gitdir: ")
178 gitPath.Replace('/', '\\');
179 gitPath.TrimRight('\\');
180 gitPath.Append(_T("\\"));
181 if (gitPath.GetLength() > 0 && gitPath[0] == _T('.'))
183 gitPath = projectTopDir + _T("\\") + gitPath;
184 PathCanonicalize(adminDir.GetBuffer(MAX_PATH), gitPath.GetBuffer());
185 adminDir.ReleaseBuffer();
186 gitPath.ReleaseBuffer();
187 return true;
189 adminDir = gitPath;
190 return true;
194 bool GitAdminDir::IsAdminDirPath(const CString& path) const
196 if (path.IsEmpty())
197 return false;
198 bool bIsAdminDir = false;
199 CString lowerpath = path;
200 lowerpath.MakeLower();
201 int ind1 = 0;
202 while ((ind1 = lowerpath.Find(_T("\\.git"), ind1))>=0)
204 int ind = ind1++;
205 if (ind == (lowerpath.GetLength() - 5))
207 bIsAdminDir = true;
208 break;
210 else if (lowerpath.Find(_T("\\.git\\"), ind)>=0)
212 bIsAdminDir = true;
213 break;
217 return bIsAdminDir;
220 bool GitAdminDir::IsBareRepo(const CString& path) const
222 if (path.IsEmpty())
223 return false;
225 if (IsAdminDirPath(path))
226 return false;
228 // don't check for \\COMPUTERNAME\HEAD
229 if (path[0] == _T('\\') && path[1] == _T('\\'))
231 if (path.Find(_T('\\'), 2) < 0)
232 return false;
235 if (!PathFileExists(path + _T("\\HEAD")) || !PathFileExists(path + _T("\\config")))
236 return false;
238 if (!PathFileExists(path + _T("\\objects\\")) || !PathFileExists(path + _T("\\refs\\")))
239 return false;
241 return true;