Fixed issue #2495: "Show Reflog" dialog shows empty action for "push" entries
[TortoiseGit.git] / src / TGitCache / StatusCacheEntry.cpp
blob20de41d736b2b668a5b2207b363e5c6203d7728d
1 // TortoiseGit - a Windows shell extension for easy version control
3 // External Cache Copyright (C) 2005-2006,2008 - TortoiseSVN
4 // Copyright (C) 2008-2013 - 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.
20 #include "stdafx.h"
21 #include "StatusCacheEntry.h"
22 #include "GitStatus.h"
23 #include "CacheInterface.h"
24 #include "registry.h"
26 #define CACHEVERION 7
28 DWORD cachetimeout = (DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\Cachetimeout"), CACHETIMEOUT);
30 CStatusCacheEntry::CStatusCacheEntry()
31 : m_bSet(false)
32 , m_kind(git_node_unknown)
33 , m_highestPriorityLocalStatus(git_wc_status_none)
34 , m_bAssumeValid(false)
35 , m_bSkipWorktree(false)
37 SetAsUnversioned();
40 CStatusCacheEntry::CStatusCacheEntry(const git_wc_status_kind status)
41 : m_bSet(true)
42 , m_kind(git_node_unknown)
43 , m_highestPriorityLocalStatus(status)
44 , m_bAssumeValid(false)
45 , m_bSkipWorktree(false)
46 , m_lastWriteTime(0)
48 m_GitStatus.prop_status=m_GitStatus.text_status = status;
49 m_GitStatus.assumeValid = m_GitStatus.skipWorktree = false;
50 m_discardAtTime = GetTickCount()+cachetimeout;
53 CStatusCacheEntry::CStatusCacheEntry(const git_wc_status2_t* pGitStatus, __int64 lastWriteTime, bool /*bReadOnly*/, DWORD validuntil /* = 0*/)
54 : m_bSet(false)
55 , m_kind(git_node_unknown)
56 , m_highestPriorityLocalStatus(git_wc_status_none)
58 SetStatus(pGitStatus);
59 m_lastWriteTime = lastWriteTime;
60 if (validuntil)
61 m_discardAtTime = validuntil;
62 else
63 m_discardAtTime = GetTickCount()+cachetimeout;
66 bool CStatusCacheEntry::SaveToDisk(FILE * pFile)
68 #define WRITEVALUETOFILE(x) if (fwrite(&x, sizeof(x), 1, pFile)!=1) return false;
69 #define WRITESTRINGTOFILE(x) if (x.IsEmpty()) {value=0;WRITEVALUETOFILE(value);}else{value=x.GetLength();WRITEVALUETOFILE(value);if (fwrite((LPCSTR)x, sizeof(char), value, pFile)!=value) return false;}
71 unsigned int value = CACHEVERION;
72 WRITEVALUETOFILE(value); // 'version' of this save-format
73 WRITEVALUETOFILE(m_highestPriorityLocalStatus);
74 WRITEVALUETOFILE(m_lastWriteTime);
75 WRITEVALUETOFILE(m_bSet);
76 WRITEVALUETOFILE(m_kind);
78 // now save the status struct (without the entry field, because we don't use that)
79 WRITEVALUETOFILE(m_GitStatus.prop_status);
80 // WRITEVALUETOFILE(m_GitStatus.repos_prop_status);
81 // WRITEVALUETOFILE(m_GitStatus.repos_text_status);
82 WRITEVALUETOFILE(m_GitStatus.text_status);
83 WRITEVALUETOFILE(m_GitStatus.assumeValid);
84 WRITEVALUETOFILE(m_GitStatus.skipWorktree);
85 return true;
88 bool CStatusCacheEntry::LoadFromDisk(FILE * pFile)
90 #define LOADVALUEFROMFILE(x) if (fread(&x, sizeof(x), 1, pFile)!=1) return false;
91 try
93 unsigned int value = 0;
94 LOADVALUEFROMFILE(value);
95 if (value != CACHEVERION)
96 return false; // not the correct version
97 LOADVALUEFROMFILE(m_highestPriorityLocalStatus);
98 LOADVALUEFROMFILE(m_lastWriteTime);
99 LOADVALUEFROMFILE(m_bSet);
100 LOADVALUEFROMFILE(m_kind);
101 SecureZeroMemory(&m_GitStatus, sizeof(m_GitStatus));
102 LOADVALUEFROMFILE(m_GitStatus.prop_status);
103 // LOADVALUEFROMFILE(m_GitStatus.repos_prop_status);
104 // LOADVALUEFROMFILE(m_GitStatus.repos_text_status);
105 LOADVALUEFROMFILE(m_GitStatus.text_status);
106 LOADVALUEFROMFILE(m_GitStatus.assumeValid);
107 LOADVALUEFROMFILE(m_GitStatus.skipWorktree);
108 // m_GitStatus.entry = NULL;
109 m_discardAtTime = GetTickCount()+cachetimeout;
111 catch ( CAtlException )
113 return false;
115 return true;
118 void CStatusCacheEntry::SetStatus(const git_wc_status2_t* pGitStatus)
120 if(pGitStatus == NULL)
122 SetAsUnversioned();
124 else
126 m_highestPriorityLocalStatus = GitStatus::GetMoreImportant(pGitStatus->prop_status, pGitStatus->text_status);
127 m_GitStatus = *pGitStatus;
128 if (m_kind != git_node_dir)
130 m_bAssumeValid = pGitStatus->assumeValid;
131 m_bSkipWorktree = pGitStatus->skipWorktree;
134 m_discardAtTime = GetTickCount()+cachetimeout;
135 m_bSet = true;
139 void CStatusCacheEntry::SetAsUnversioned()
141 SecureZeroMemory(&m_GitStatus, sizeof(m_GitStatus));
142 m_discardAtTime = GetTickCount()+cachetimeout;
143 git_wc_status_kind status = git_wc_status_none;
144 if (m_highestPriorityLocalStatus == git_wc_status_missing)
145 status = git_wc_status_missing;
146 if (m_highestPriorityLocalStatus == git_wc_status_unversioned)
147 status = git_wc_status_unversioned;
148 m_highestPriorityLocalStatus = status;
149 m_GitStatus.prop_status = git_wc_status_none;
150 m_GitStatus.text_status = status;
151 m_lastWriteTime = 0;
152 m_bAssumeValid = false;
155 bool CStatusCacheEntry::HasExpired(long now) const
157 return m_discardAtTime != 0 && (now - m_discardAtTime) >= 0;
160 void CStatusCacheEntry::BuildCacheResponse(TGITCacheResponse& response, DWORD& responseLength) const
162 SecureZeroMemory(&response, sizeof(response));
163 response.m_status = m_GitStatus;
164 response.m_bAssumeValid = m_bAssumeValid;
165 response.m_bSkipWorktree = m_bSkipWorktree;
166 responseLength = sizeof(response);
168 // directories that are empty or only contain unversioned files will be git_wc_status_incomplete, report as unversioned
169 if (response.m_status.text_status == git_wc_status_incomplete)
171 response.m_status.text_status = response.m_status.prop_status = git_wc_status_unversioned;
175 bool CStatusCacheEntry::IsVersioned() const
177 return m_highestPriorityLocalStatus > git_wc_status_unversioned;
180 bool CStatusCacheEntry::DoesFileTimeMatch(__int64 testTime) const
182 return m_lastWriteTime == testTime;
186 bool CStatusCacheEntry::ForceStatus(git_wc_status_kind forcedStatus)
188 git_wc_status_kind newStatus = forcedStatus;
190 if(newStatus != m_highestPriorityLocalStatus)
192 // We've had a status change
193 m_highestPriorityLocalStatus = newStatus;
194 m_GitStatus.text_status = newStatus;
195 m_GitStatus.prop_status = newStatus;
196 m_discardAtTime = GetTickCount()+cachetimeout;
197 return true;
199 return false;
202 bool
203 CStatusCacheEntry::HasBeenSet() const
205 return m_bSet;
208 void CStatusCacheEntry::Invalidate()
210 m_bSet = false;