Refactor: Drop try catch
[TortoiseGit.git] / src / Git / GitStatus.cpp
blob9f91c4ab3f172525ca7d54ca8f093691cd936bb3
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2015 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "registry.h"
22 #include "..\TortoiseShell\resource.h"
23 #include "GitStatus.h"
24 #include "UnicodeUtils.h"
25 #include "Git.h"
26 #include "gitindex.h"
27 #include "ShellCache.h"
28 #include "SysInfo.h"
30 extern CGitAdminDirMap g_AdminDirMap;
31 extern CGitIndexFileMap g_IndexFileMap;
32 CGitHeadFileMap g_HeadFileMap;
33 CGitIgnoreList g_IgnoreList;
35 GitStatus::GitStatus()
36 : status(NULL)
38 m_status.assumeValid = m_status.skipWorktree = false;
39 m_status.prop_status = m_status.text_status = git_wc_status_none;
42 GitStatus::~GitStatus(void)
46 // static method
47 #ifndef TGITCACHE
48 git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t depth, bool * assumeValid, bool * skipWorktree)
50 git_wc_status_kind statuskind;
51 BOOL err;
52 BOOL isDir;
53 CString sProjectRoot;
55 isDir = path.IsDirectory();
56 if (!path.HasAdminDir(&sProjectRoot))
57 return git_wc_status_none;
59 // rev.kind = git_opt_revision_unspecified;
60 statuskind = git_wc_status_none;
62 const BOOL bIsRecursive = (depth == git_depth_infinity || depth == git_depth_unknown); // taken from SVN source
64 CString sSubPath;
65 CString s = path.GetWinPathString();
66 if (s.GetLength() > sProjectRoot.GetLength())
68 if (sProjectRoot.GetLength() == 3 && sProjectRoot[1] == _T(':'))
69 sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength());
70 else
71 sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/);
74 bool isfull = ((DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\CacheType"),
75 GetSystemMetrics(SM_REMOTESESSION) ? ShellCache::dll : ShellCache::exe) == ShellCache::dllFull);
77 if(isDir)
79 err = GetDirStatus(sProjectRoot, sSubPath, &statuskind, isfull, bIsRecursive, isfull);
80 // folders must not be displayed as added or deleted only as modified (this is for Shell Overlay-Modes)
81 if (statuskind == git_wc_status_unversioned && sSubPath.IsEmpty())
82 statuskind = git_wc_status_normal;
83 else if (statuskind == git_wc_status_deleted || statuskind == git_wc_status_added)
84 statuskind = git_wc_status_modified;
86 else
88 err = GetFileStatus(sProjectRoot, sSubPath, &statuskind, isfull, false, isfull, NULL, NULL, assumeValid, skipWorktree);
91 return statuskind;
93 #endif
95 // static method
96 git_wc_status_kind GitStatus::GetMoreImportant(git_wc_status_kind status1, git_wc_status_kind status2)
98 if (GetStatusRanking(status1) >= GetStatusRanking(status2))
99 return status1;
100 return status2;
102 // static private method
103 int GitStatus::GetStatusRanking(git_wc_status_kind status)
105 switch (status)
107 case git_wc_status_none:
108 return 0;
109 case git_wc_status_unversioned:
110 return 1;
111 case git_wc_status_ignored:
112 return 2;
113 case git_wc_status_incomplete:
114 return 4;
115 case git_wc_status_normal:
116 case git_wc_status_external:
117 return 5;
118 case git_wc_status_added:
119 return 6;
120 case git_wc_status_missing:
121 return 7;
122 case git_wc_status_deleted:
123 return 8;
124 case git_wc_status_replaced:
125 return 9;
126 case git_wc_status_modified:
127 return 10;
128 case git_wc_status_merged:
129 return 11;
130 case git_wc_status_conflicted:
131 return 12;
132 case git_wc_status_obstructed:
133 return 13;
135 return 0;
138 #ifndef TGITCACHE
139 void GitStatus::GetStatus(const CTGitPath& path, bool /*update*/ /* = false */, bool noignore /* = false */, bool /*noexternals*/ /* = false */)
141 // NOTE: unlike the SVN version this one does not cache the enumerated files, because in practice no code in all of
142 // Tortoise uses this, all places that call GetStatus create a temp GitStatus object which gets destroyed right
143 // after the call again
145 CString sProjectRoot;
146 if ( !path.HasAdminDir(&sProjectRoot) )
147 return;
149 bool isfull = ((DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\CacheType"),
150 GetSystemMetrics(SM_REMOTESESSION) ? ShellCache::dll : ShellCache::exe) == ShellCache::dllFull);
152 int err = 0;
154 LPCTSTR lpszSubPath = NULL;
155 CString sSubPath;
156 CString s = path.GetWinPathString();
157 if (s.GetLength() > sProjectRoot.GetLength())
159 sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength());
160 lpszSubPath = sSubPath;
161 // skip initial slash if necessary
162 if (*lpszSubPath == _T('\\'))
163 ++lpszSubPath;
166 m_status.prop_status = m_status.text_status = git_wc_status_none;
167 m_status.assumeValid = false;
168 m_status.skipWorktree = false;
170 if (path.IsDirectory())
172 err = GetDirStatus(sProjectRoot, lpszSubPath, &m_status.text_status, isfull, false, !noignore);
173 if (m_status.text_status == git_wc_status_added || m_status.text_status == git_wc_status_deleted) // fix for issue #1769; a folder is either modified, conflicted or normal
174 m_status.text_status = git_wc_status_modified;
176 else
177 err = GetFileStatus(sProjectRoot, lpszSubPath, &m_status.text_status, isfull, false, !noignore, nullptr, nullptr, &m_status.assumeValid, &m_status.skipWorktree);
179 // Error present if function is not under version control
180 if (err)
182 status = NULL;
183 return;
186 status = &m_status;
188 #endif
190 typedef CComCritSecLock<CComCriticalSection> CAutoLocker;
192 int GitStatus::GetFileStatus(const CString &gitdir, const CString &pathParam, git_wc_status_kind * status,BOOL IsFull, BOOL /*IsRecursive*/,BOOL IsIgnore, FILL_STATUS_CALLBACK callback, void *pData, bool * assumeValid, bool * skipWorktree)
194 if (!status)
195 return 0;
197 CString path = pathParam;
199 path.Replace(_T('\\'), _T('/'));
201 CString lowcasepath = path;
202 lowcasepath.MakeLower();
204 git_wc_status_kind st = git_wc_status_none;
205 CGitHash hash;
207 g_IndexFileMap.GetFileStatus(gitdir, path, &st, IsFull, false, callback, pData, &hash, true, assumeValid, skipWorktree);
209 if (st == git_wc_status_conflicted)
211 *status = st;
212 if (callback && assumeValid && skipWorktree)
213 callback(CombinePath(gitdir, path), st, false, pData, *assumeValid, *skipWorktree);
214 return 0;
217 if (st == git_wc_status_unversioned)
219 if (!IsIgnore)
221 *status = git_wc_status_unversioned;
222 if (callback && assumeValid && skipWorktree)
223 callback(CombinePath(gitdir, path), *status, false, pData, *assumeValid, *skipWorktree);
224 return 0;
227 if (g_IgnoreList.CheckIgnoreChanged(gitdir, path, false))
228 g_IgnoreList.LoadAllIgnoreFile(gitdir, path, false);
229 if (g_IgnoreList.IsIgnore(path, gitdir, false))
230 st = git_wc_status_ignored;
232 *status = st;
233 if (callback && assumeValid && skipWorktree)
234 callback(CombinePath(gitdir, path), st, false, pData, *assumeValid, *skipWorktree);
236 return 0;
239 if ((st == git_wc_status_normal || st == git_wc_status_modified) && IsFull)
241 g_HeadFileMap.CheckHeadAndUpdate(gitdir);
243 // Check Head Tree Hash
244 SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir);
246 //add item
247 int start = SearchInSortVector(*treeptr, lowcasepath, -1);
248 if (start < 0)
250 *status = st = git_wc_status_added;
251 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": File miss in head tree %s"), (LPCTSTR)path);
252 if (callback && assumeValid && skipWorktree)
253 callback(CombinePath(gitdir, path), st, false, pData, *assumeValid, *skipWorktree);
254 return 0;
257 // staged and not commit
258 if (treeptr->at(start).m_Hash != hash)
260 *status = st = git_wc_status_modified;
261 if (callback && assumeValid && skipWorktree)
262 callback(CombinePath(gitdir, path), st, false, pData, *assumeValid, *skipWorktree);
263 return 0;
266 *status = st;
267 if (callback && assumeValid && skipWorktree)
268 callback(CombinePath(gitdir, path), st, false, pData, *assumeValid, *skipWorktree);
269 return 0;
272 #ifdef TGITCACHE
273 bool GitStatus::HasIgnoreFilesChanged(const CString &gitdir, const CString &subpaths, bool isDir)
275 return g_IgnoreList.CheckIgnoreChanged(gitdir, subpaths, isDir);
278 int GitStatus::LoadIgnoreFile(const CString &gitdir, const CString &subpaths, bool isDir)
280 return g_IgnoreList.LoadAllIgnoreFile(gitdir, subpaths, isDir);
282 int GitStatus::IsUnderVersionControl(const CString &gitdir, const CString &path, bool isDir,bool *isVersion)
284 if (g_IndexFileMap.IsUnderVersionControl(gitdir, path, isDir, isVersion))
285 return 1;
286 if (!*isVersion)
287 return g_HeadFileMap.IsUnderVersionControl(gitdir, path, isDir, isVersion);
288 return 0;
291 int GitStatus::IsIgnore(const CString &gitdir, const CString &path, bool *isIgnore, bool isDir)
293 if (g_IgnoreList.CheckIgnoreChanged(gitdir, path, isDir))
294 g_IgnoreList.LoadAllIgnoreFile(gitdir, path, isDir);
296 *isIgnore = g_IgnoreList.IsIgnore(path, gitdir, isDir);
298 return 0;
301 int GitStatus::GetFileList(CString path, std::vector<CGitFileName> &list)
303 path += _T("\\*.*");
304 WIN32_FIND_DATA data;
305 HANDLE handle = ::FindFirstFileEx(path, SysInfo::Instance().IsWin7OrLater() ? FindExInfoBasic : FindExInfoStandard, &data, FindExSearchNameMatch, nullptr, SysInfo::Instance().IsWin7OrLater() ? FIND_FIRST_EX_LARGE_FETCH : 0);
308 if(_tcscmp(data.cFileName, _T(".git")) == 0)
309 continue;
311 if(_tcscmp(data.cFileName, _T(".")) == 0)
312 continue;
314 if(_tcscmp(data.cFileName, _T("..")) == 0)
315 continue;
317 CGitFileName filename;
319 filename.m_CaseFileName = filename.m_FileName = data.cFileName;
320 filename.m_FileName.MakeLower();
322 if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
324 filename.m_FileName += _T('/');
327 list.push_back(filename);
329 }while(::FindNextFile(handle, &data));
331 FindClose(handle);
333 std::sort(list.begin(), list.end(), SortCGitFileName);
334 return 0;
337 int GitStatus::EnumDirStatus(const CString &gitdir, const CString &subpath, git_wc_status_kind * status,BOOL IsFul, BOOL IsRecursive, BOOL IsIgnore, FILL_STATUS_CALLBACK callback, void *pData)
339 if (!status)
340 return 0;
342 CString path = subpath;
344 path.Replace(_T('\\'), _T('/'));
345 if (!path.IsEmpty() && path[path.GetLength() - 1] != _T('/'))
346 path += _T('/'); // Add trail / to show it is directory, not file name.
348 std::vector<CGitFileName> filelist;
349 GetFileList(CombinePath(gitdir, subpath), filelist);
351 g_IndexFileMap.CheckAndUpdate(gitdir,true);
353 g_HeadFileMap.CheckHeadAndUpdate(gitdir);
355 SHARED_INDEX_PTR indexptr = g_IndexFileMap.SafeGet(gitdir);
356 SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir);
358 // new git working tree has no index file
359 if (!indexptr.get())
361 for (auto it = filelist.cbegin(); it != filelist.cend(); ++it)
363 CString casepath = path;
364 casepath += it->m_CaseFileName;
366 bool bIsDir = false;
367 if (it->m_FileName.GetLength() > 0 && it->m_FileName[it->m_FileName.GetLength() - 1] == _T('/'))
368 bIsDir = true;
370 if (IsIgnore)
372 if (g_IgnoreList.CheckIgnoreChanged(gitdir, casepath, bIsDir))
373 g_IgnoreList.LoadAllIgnoreFile(gitdir, casepath, bIsDir);
375 if (g_IgnoreList.IsIgnore(casepath, gitdir, bIsDir))
376 *status = git_wc_status_ignored;
377 else if (bIsDir)
378 continue;
379 else
380 *status = git_wc_status_unversioned;
382 else if (bIsDir)
383 continue;
384 else
385 *status = git_wc_status_unversioned;
387 if (callback)
388 callback(CombinePath(gitdir, casepath), *status, bIsDir, pData, false, false);
390 return 0;
393 CString lowcasepath = path;
394 lowcasepath.MakeLower();
396 CString onepath;
397 CString casepath;
398 for (auto it = filelist.cbegin(), itend = filelist.cend(); it != itend; ++it)
400 casepath = onepath = lowcasepath;
401 onepath += it->m_FileName;
402 casepath += it->m_CaseFileName;
404 bool bIsDir = false;
405 if (!onepath.IsEmpty() && onepath[onepath.GetLength() - 1] == _T('/'))
406 bIsDir = true;
408 int matchLength = -1;
409 if (bIsDir)
410 matchLength = onepath.GetLength();
411 int pos = SearchInSortVector(*indexptr, onepath, matchLength);
412 int posintree = SearchInSortVector(*treeptr, onepath, matchLength);
414 if (pos < 0 && posintree < 0)
416 if (onepath.IsEmpty())
417 continue;
419 if (!IsIgnore)
421 *status = git_wc_status_unversioned;
422 if (callback)
423 callback(CombinePath(gitdir, casepath), *status, bIsDir, pData, false, false);
424 continue;
427 if (g_IgnoreList.CheckIgnoreChanged(gitdir, casepath, bIsDir))
428 g_IgnoreList.LoadAllIgnoreFile(gitdir, casepath, bIsDir);
430 if (g_IgnoreList.IsIgnore(casepath, gitdir, bIsDir))
431 *status = git_wc_status_ignored;
432 else
433 *status = git_wc_status_unversioned;
435 if (callback)
436 callback(CombinePath(gitdir, casepath), *status, bIsDir, pData, false, false);
438 else if (pos < 0 && posintree >= 0) /* check if file delete in index */
440 *status = git_wc_status_deleted;
441 if (callback)
442 callback(CombinePath(gitdir, casepath), *status, bIsDir, pData, false, false);
444 else if (pos >= 0 && posintree < 0) /* Check if file added */
446 *status = git_wc_status_added;
447 if (indexptr->at(pos).m_Flags & GIT_IDXENTRY_STAGEMASK)
448 *status = git_wc_status_conflicted;
449 if (callback)
450 callback(CombinePath(gitdir, casepath), *status, bIsDir, pData, false, false);
452 else
454 if (onepath.IsEmpty())
455 continue;
457 if (bIsDir)
459 *status = git_wc_status_normal;
460 if (callback)
461 callback(CombinePath(gitdir, casepath), *status, bIsDir, pData, false, false);
463 else
465 bool assumeValid = false;
466 bool skipWorktree = false;
467 git_wc_status_kind filestatus;
468 GetFileStatus(gitdir, casepath, &filestatus, IsFul, IsRecursive, IsIgnore, callback, pData, &assumeValid, &skipWorktree);
471 }/*End of For*/
473 /* Check deleted file in system */
474 int start = 0, end = 0;
475 int pos = SearchInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength()); // match path prefix, (sub)folders end with slash
476 std::map<CString, bool> skipWorktreeMap;
478 if (GetRangeInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength(), &start, &end, pos) == 0)
480 CString oldstring;
481 for (auto it = indexptr->cbegin() + start, itlast = indexptr->cbegin() + end; it <= itlast; ++it)
483 int commonPrefixLength = lowcasepath.GetLength();
484 int index = (*it).m_FileName.Find(_T('/'), commonPrefixLength);
485 if (index < 0)
486 index = (*it).m_FileName.GetLength();
487 else
488 ++index; // include slash at the end for subfolders, so that we do not match files by mistake
490 CString filename = (*it).m_FileName.Mid(commonPrefixLength, index - commonPrefixLength);
491 if (oldstring != filename)
493 oldstring = filename;
494 if (SearchInSortVector(filelist, filename, filename.GetLength()) < 0)
496 bool skipWorktree = false;
497 *status = git_wc_status_deleted;
498 if (((*it).m_Flags & GIT_IDXENTRY_SKIP_WORKTREE) != 0)
500 skipWorktreeMap[filename] = true;
501 skipWorktree = true;
502 *status = git_wc_status_normal;
504 if (callback)
505 callback(CombinePath(gitdir, (*it).m_FileName), *status, false, pData, false, skipWorktree);
511 start = end = 0;
512 pos = SearchInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength()); // match path prefix, (sub)folders end with slash
513 if (GetRangeInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength(), &start, &end, pos) == 0)
515 CString oldstring;
516 for (auto it = treeptr->cbegin() + start, itlast = treeptr->cbegin() + end; it <= itlast; ++it)
518 int commonPrefixLength = lowcasepath.GetLength();
519 int index = (*it).m_FileName.Find(_T('/'), commonPrefixLength);
520 if (index < 0)
521 index = (*it).m_FileName.GetLength();
522 else
523 ++index; // include slash at the end for subfolders, so that we do not match files by mistake
525 CString filename = (*it).m_FileName.Mid(commonPrefixLength, index - commonPrefixLength);
526 if (oldstring != filename && skipWorktreeMap[filename] != true)
528 oldstring = filename;
529 if (SearchInSortVector(filelist, filename, filename.GetLength()) < 0)
531 *status = git_wc_status_deleted;
532 if (callback)
533 callback(CombinePath(gitdir, (*it).m_FileName), *status, false, pData, false, false);
538 return 0;
540 #endif
542 #ifndef TGITCACHE
543 int GitStatus::GetDirStatus(const CString& gitdir, const CString& subpath, git_wc_status_kind* status, BOOL IsFul, BOOL IsRecursive, BOOL IsIgnore)
545 if (!status)
546 return 0;
548 CString path = subpath;
550 path.Replace(_T('\\'), _T('/'));
551 if (!path.IsEmpty() && path[path.GetLength() - 1] != _T('/'))
552 path += _T('/'); //Add trail / to show it is directory, not file name.
554 g_IndexFileMap.CheckAndUpdate(gitdir, true);
556 SHARED_INDEX_PTR indexptr = g_IndexFileMap.SafeGet(gitdir);
558 if (!indexptr)
560 *status = git_wc_status_unversioned;
561 return 0;
564 CString lowcasepath = path;
565 lowcasepath.MakeLower();
567 int pos = SearchInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength());
569 // Not In Version Contorl
570 if (pos < 0)
572 if (!IsIgnore)
574 *status = git_wc_status_unversioned;
575 return 0;
578 // Check ignore always.
579 if (g_IgnoreList.CheckIgnoreChanged(gitdir, path, true))
580 g_IgnoreList.LoadAllIgnoreFile(gitdir, path, true);
582 if (g_IgnoreList.IsIgnore(path, gitdir, true))
583 *status = git_wc_status_ignored;
584 else
585 *status = git_wc_status_unversioned;
587 g_HeadFileMap.CheckHeadAndUpdate(gitdir);
589 SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir);
590 // Check init repository
591 if (treeptr->HeadIsEmpty() && path.IsEmpty())
592 *status = git_wc_status_normal;
593 // check if only one file in repository is deleted in index
594 else if (path.IsEmpty() && !treeptr->empty())
595 *status = git_wc_status_deleted;
597 return 0;
600 // In version control
601 *status = git_wc_status_normal;
603 int start = 0;
604 int end = 0;
605 if (path.IsEmpty())
606 end = (int)indexptr->size() - 1;
608 GetRangeInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength(), &start, &end, pos);
610 // Check Conflict;
611 for (auto it = indexptr->cbegin() + start, itlast = indexptr->cbegin() + end; it <= itlast; ++it)
613 if (((*it).m_Flags & GIT_IDXENTRY_STAGEMASK) != 0)
615 *status = git_wc_status_conflicted;
616 break;
620 if (IsFul && (*status != git_wc_status_conflicted))
622 *status = git_wc_status_normal;
624 g_HeadFileMap.CheckHeadAndUpdate(gitdir);
626 // Check Add
628 // Check if new init repository
629 SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir);
631 if (!treeptr->empty() || treeptr->HeadIsEmpty())
633 for (auto it = indexptr->cbegin() + start, itlast = indexptr->cbegin() + end; it <= itlast; ++it)
635 pos = SearchInSortVector(*treeptr, (*it).m_FileName, -1);
637 if (pos < 0)
639 *status = max(git_wc_status_added, *status); // added file found
640 break;
643 if (pos >= 0 && treeptr->at(pos).m_Hash != (*it).m_IndexHash)
645 *status = max(git_wc_status_modified, *status); // modified file found
646 break;
650 // Check Delete
651 if (*status == git_wc_status_normal)
653 pos = SearchInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength());
654 if (pos < 0)
655 *status = max(git_wc_status_added, *status); // added file found
656 else
658 int hstart, hend;
659 GetRangeInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength(), &hstart, &hend, pos);
660 for (auto hit = treeptr->cbegin() + hstart, lastElement = treeptr->cbegin() + hend; hit <= lastElement; ++hit)
662 if (SearchInSortVector(*indexptr, (*hit).m_FileName, -1) < 0)
664 *status = max(git_wc_status_deleted, *status); // deleted file found
665 break;
671 } /* End lock*/
674 // When status == git_wc_status_conflicted, needn't check each file status
675 // because git_wc_status_conflicted is highest.s
676 if (*status == git_wc_status_conflicted)
677 return 0;
679 for (auto it = indexptr->cbegin() + start, itlast = indexptr->cbegin() + end; it <= itlast; ++it)
681 //skip child directory
682 if (!IsRecursive && (*it).m_FileName.Find(_T('/'), path.GetLength()) > 0)
683 continue;
685 git_wc_status_kind filestatus = git_wc_status_none;
686 bool assumeValid = false;
687 bool skipWorktree = false;
688 GetFileStatus(gitdir, (*it).m_FileName, &filestatus, IsFul, IsRecursive, IsIgnore, nullptr, nullptr, &assumeValid, &skipWorktree);
689 switch (filestatus)
691 case git_wc_status_added:
692 case git_wc_status_modified:
693 case git_wc_status_deleted:
694 case git_wc_status_conflicted:
695 *status = GetMoreImportant(filestatus, *status);
699 return 0;
701 #endif
703 #ifdef TGITCACHE
704 bool GitStatus::IsExistIndexLockFile(const CString &gitdir)
706 CString sDirName= gitdir;
708 if (!PathIsDirectory(sDirName))
710 int x = sDirName.ReverseFind(_T('\\'));
711 if (x < 2)
712 return false;
714 sDirName = sDirName.Left(x);
717 for (;;)
719 if(PathFileExists(sDirName + _T("\\.git")))
721 if(PathFileExists(g_AdminDirMap.GetAdminDir(sDirName) + _T("index.lock")))
722 return true;
724 return false;
727 int x = sDirName.ReverseFind(_T('\\'));
728 if (x < 2)
729 return false;
731 sDirName = sDirName.Left(x);
734 #endif
736 bool GitStatus::ReleasePath(const CString &gitdir)
738 g_IndexFileMap.SafeClear(gitdir);
739 return true;
742 bool GitStatus::ReleasePathsRecursively(const CString &rootpath)
744 g_IndexFileMap.SafeClearRecursively(rootpath);
745 return true;