1
// TortoiseGit - a Windows shell extension for easy version control
3 // External Cache Copyright (C) 2005-2006,2008,2014 - TortoiseSVN
4 // Copyright (C) 2008-2014, 2016-2017, 2019, 2023 - TortoiseGit
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.
21 #include "StatusCacheEntry.h"
22 #include "GitStatus.h"
23 #include "CacheInterface.h"
28 ULONGLONG cachetimeout
= static_cast<ULONGLONG
>(CRegStdDWORD(L
"Software\\TortoiseGit\\Cachetimeout", LONG_MAX
));
30 CStatusCacheEntry::CStatusCacheEntry()
35 CStatusCacheEntry::CStatusCacheEntry(const git_wc_status_kind status
)
37 , m_highestPriorityLocalStatus(status
)
39 m_GitStatus
.status
= status
;
40 m_GitStatus
.assumeValid
= m_GitStatus
.skipWorktree
= false;
41 m_discardAtTime
= GetTickCount64() + cachetimeout
;
44 CStatusCacheEntry::CStatusCacheEntry(const git_wc_status2_t
* pGitStatus
, __int64 lastWriteTime
, LONGLONG validuntil
/* = 0*/)
45 : m_lastWriteTime(lastWriteTime
)
47 SetStatus(pGitStatus
);
49 m_discardAtTime
= validuntil
;
51 m_discardAtTime
= GetTickCount64() + cachetimeout
;
54 bool CStatusCacheEntry::SaveToDisk(FILE* pFile
) const
56 #define WRITEVALUETOFILE(x) if (fwrite(&x, sizeof(x), 1, pFile)!=1) return false;
57 #define WRITESTRINGTOFILE(x) if (x.IsEmpty()) {value=0;WRITEVALUETOFILE(value);}else{value=x.GetLength();WRITEVALUETOFILE(value);if (fwrite(static_cast<LPCSTR>(x), sizeof(char), value, pFile)!=value) return false;}
59 unsigned int value
= CACHEVERION
;
60 WRITEVALUETOFILE(value
); // 'version' of this save-format
61 WRITEVALUETOFILE(m_highestPriorityLocalStatus
);
62 WRITEVALUETOFILE(m_lastWriteTime
);
63 WRITEVALUETOFILE(m_bSet
);
65 // now save the status struct (without the entry field, because we don't use that)
66 WRITEVALUETOFILE(m_GitStatus
.status
);
67 WRITEVALUETOFILE(m_GitStatus
.assumeValid
);
68 WRITEVALUETOFILE(m_GitStatus
.skipWorktree
);
72 bool CStatusCacheEntry::LoadFromDisk(FILE * pFile
)
74 #define LOADVALUEFROMFILE(x) if (fread(&x, sizeof(x), 1, pFile)!=1) return false;
77 unsigned int value
= 0;
78 LOADVALUEFROMFILE(value
);
79 if (value
!= CACHEVERION
)
80 return false; // not the correct version
81 LOADVALUEFROMFILE(m_highestPriorityLocalStatus
);
82 LOADVALUEFROMFILE(m_lastWriteTime
);
83 LOADVALUEFROMFILE(m_bSet
);
84 SecureZeroMemory(&m_GitStatus
, sizeof(m_GitStatus
));
85 LOADVALUEFROMFILE(m_GitStatus
.status
);
86 LOADVALUEFROMFILE(m_GitStatus
.assumeValid
);
87 LOADVALUEFROMFILE(m_GitStatus
.skipWorktree
);
88 m_discardAtTime
= GetTickCount64() + cachetimeout
;
90 catch ( CAtlException
)
97 void CStatusCacheEntry::SetStatus(const git_wc_status2_t
* pGitStatus
)
105 m_highestPriorityLocalStatus
= pGitStatus
->status
;
106 m_GitStatus
= *pGitStatus
;
107 m_bAssumeValid
= pGitStatus
->assumeValid
;
108 m_bSkipWorktree
= pGitStatus
->skipWorktree
;
110 m_discardAtTime
= GetTickCount64() + cachetimeout
;
115 void CStatusCacheEntry::SetAsUnversioned()
117 SecureZeroMemory(&m_GitStatus
, sizeof(m_GitStatus
));
118 m_discardAtTime
= GetTickCount64() + cachetimeout
;
119 git_wc_status_kind status
= git_wc_status_none
;
120 if (m_highestPriorityLocalStatus
== git_wc_status_unversioned
)
121 status
= git_wc_status_unversioned
;
122 m_highestPriorityLocalStatus
= status
;
123 m_GitStatus
.status
= git_wc_status_none
;
125 m_bAssumeValid
= false;
126 m_bSkipWorktree
= false;
129 bool CStatusCacheEntry::HasExpired(LONGLONG now
) const
131 return m_discardAtTime
!= 0 && (now
- m_discardAtTime
) >= 0;
134 void CStatusCacheEntry::BuildCacheResponse(TGITCacheResponse
& response
, DWORD
& responseLength
) const
136 SecureZeroMemory(&response
, sizeof(response
));
137 response
.m_status
= static_cast<INT8
>(m_GitStatus
.status
);
138 response
.m_bAssumeValid
= m_bAssumeValid
;
139 response
.m_bSkipWorktree
= m_bSkipWorktree
;
140 responseLength
= sizeof(response
);
143 bool CStatusCacheEntry::IsVersioned() const
145 return m_highestPriorityLocalStatus
> git_wc_status_unversioned
;
148 bool CStatusCacheEntry::DoesFileTimeMatch(__int64 testTime
) const
150 return m_lastWriteTime
== testTime
;
154 bool CStatusCacheEntry::ForceStatus(git_wc_status_kind forcedStatus
)
156 git_wc_status_kind newStatus
= forcedStatus
;
158 if(newStatus
!= m_highestPriorityLocalStatus
)
160 // We've had a status change
161 m_highestPriorityLocalStatus
= newStatus
;
162 m_GitStatus
.status
= newStatus
;
163 m_discardAtTime
= GetTickCount64() + cachetimeout
;
170 CStatusCacheEntry::HasBeenSet() const
175 void CStatusCacheEntry::Invalidate()