1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008,2012 - TortoiseSVN
4 // Copyright (C) 2008-2012 - 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.
23 #include "PreserveChdir.h"
24 //#include "SVNProperties.h"
25 #include "UnicodeUtils.h"
26 #include "GitStatus.h"
27 #include "PathUtils.h"
28 #include "..\TGitCache\CacheInterface.h"
31 const static int ColumnFlags
= SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
;
33 // Defines that revision numbers occupy at most MAX_REV_STRING_LEN characters.
34 // There are Perforce repositories out there that have several 100,000 revs.
35 // So, don't be too restrictive by limiting this to 6 digits + 1 separator,
38 // Because shorter strings will be extended to have exactly MAX_REV_STRING_LEN
39 // characters, large numbers will produce large strings. These, in turn, will
40 // affect column auto sizing. This setting is a reasonable compromise.
42 STDMETHODIMP
CShellExt::GetColumnInfo(DWORD dwIndex
, SHCOLUMNINFO
*psci
)
46 return GetColumnInfo_Wrap(dwIndex
, psci
);
48 __except(CCrashReport::Instance().SendReport(GetExceptionInformation()))
54 // IColumnProvider members
55 STDMETHODIMP
CShellExt::GetColumnInfo_Wrap(DWORD dwIndex
, SHCOLUMNINFO
*psci
)
60 PreserveChdir preserveChdir
;
61 if (dwIndex
> 0) // TODO: keep for now to be able to hide unimplemented columns
64 ShellCache::CacheType cachetype
= g_ShellCache
.GetCacheType();
65 if (cachetype
== ShellCache::none
)
72 GetColumnInfo(dwIndex
, psci
, 15, IDS_COLTITLESTATUS
, IDS_COLDESCSTATUS
);
74 case 1: // Git Revision
75 GetColumnInfo(dwIndex
, psci
, 40, IDS_COLTITLEREV
, IDS_COLDESCREV
);
78 GetColumnInfo(dwIndex
, psci
, 30, IDS_COLTITLEURL
, IDS_COLDESCURL
);
80 case 3: // Git Short Url
81 GetColumnInfo(dwIndex
, psci
, 30, IDS_COLTITLESHORTURL
, IDS_COLDESCSHORTURL
);
83 case 4: // Author and Git Author
84 psci
->scid
.fmtid
= FMTID_SummaryInformation
; // predefined FMTID
85 psci
->scid
.pid
= PIDSI_AUTHOR
; // Predefined - author
86 psci
->vt
= VT_LPSTR
; // We'll return the data as a string
87 psci
->fmt
= LVCFMT_LEFT
; // Text will be left-aligned in the column
88 psci
->csFlags
= SHCOLSTATE_TYPE_STR
; // Data should be sorted as strings
89 psci
->cChars
= 32; // Default col width in chars
90 MAKESTRING(IDS_COLTITLEAUTHOR
);
91 lstrcpynW(psci
->wszTitle
, stringtablebuffer
, MAX_COLUMN_NAME_LEN
);
92 MAKESTRING(IDS_COLDESCAUTHOR
);
93 lstrcpynW(psci
->wszDescription
, stringtablebuffer
, MAX_COLUMN_DESC_LEN
);
102 void CShellExt::GetColumnInfo(DWORD dwIndex
, SHCOLUMNINFO
*psci
, UINT characterCount
, UINT title
, UINT description
)
104 psci
->scid
.fmtid
= CLSID_Tortoisegit_UPTODATE
;
105 psci
->scid
.pid
= dwIndex
;
107 psci
->fmt
= LVCFMT_LEFT
;
108 psci
->cChars
= characterCount
;
109 psci
->csFlags
= ColumnFlags
;
112 lstrcpynW(psci
->wszTitle
, stringtablebuffer
, MAX_COLUMN_NAME_LEN
);
113 MAKESTRING(description
);
114 lstrcpynW(psci
->wszDescription
, stringtablebuffer
, MAX_COLUMN_DESC_LEN
);
117 STDMETHODIMP
CShellExt::GetItemData(LPCSHCOLUMNID pscid
, LPCSHCOLUMNDATA pscd
, VARIANT
*pvarData
)
121 return GetItemData_Wrap(pscid
, pscd
, pvarData
);
123 __except(CCrashReport::Instance().SendReport(GetExceptionInformation()))
129 STDMETHODIMP
CShellExt::GetItemData_Wrap(LPCSHCOLUMNID pscid
, LPCSHCOLUMNDATA pscd
, VARIANT
*pvarData
)
131 if ((pscid
== 0) || (pscd
== 0))
136 PreserveChdir preserveChdir
;
137 if (!g_ShellCache
.IsPathAllowed((TCHAR
*)pscd
->wszFile
))
142 ShellCache::CacheType cachetype
= g_ShellCache
.GetCacheType();
143 if (pscid
->fmtid
== CLSID_Tortoisegit_UPTODATE
)
146 const TCHAR
* path
= (TCHAR
*)pscd
->wszFile
;
148 // reserve for the path + trailing \0
150 TCHAR buf
[MAX_STATUS_STRING_LENGTH
+1];
151 SecureZeroMemory(buf
, MAX_STATUS_STRING_LENGTH
);
154 case 0: // Git Status
155 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
156 GitStatus::GetStatusString(g_hResInst
, filestatus
, buf
, _countof(buf
), (WORD
)CRegStdDWORD(_T("Software\\TortoiseGit\\LanguageID"), MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
)));
159 case 1: // Git Revision
161 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
164 V_VT(pvarData
) = VT_I4
;
165 V_I4(pvarData
) = columnrev
;
171 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
174 case 3: // Git Short Url
175 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
176 szInfo
= itemshorturl
;
181 const WCHAR
* wsInfo
= szInfo
.c_str();
182 V_VT(pvarData
) = VT_BSTR
;
183 V_BSTR(pvarData
) = SysAllocString(wsInfo
);
186 if (pscid
->fmtid
== FMTID_SummaryInformation
)
189 const TCHAR
* path
= pscd
->wszFile
;
191 if (cachetype
== ShellCache::none
)
195 case PIDSI_AUTHOR
: // Author and Git Author
196 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
197 szInfo
= columnauthor
;
202 wide_string wsInfo
= szInfo
;
203 V_VT(pvarData
) = VT_BSTR
;
204 V_BSTR(pvarData
) = SysAllocString(wsInfo
.c_str());
211 STDMETHODIMP
CShellExt::Initialize(LPCSHCOLUMNINIT psci
)
215 return Initialize_Wrap(psci
);
217 __except(CCrashReport::Instance().SendReport(GetExceptionInformation()))
223 STDMETHODIMP
CShellExt::Initialize_Wrap(LPCSHCOLUMNINIT psci
)
227 // psci->wszFolder (WCHAR) holds the path to the folder to be displayed
228 // Should check to see if its a "SVN" folder and if not return E_FAIL
230 PreserveChdir preserveChdir
;
231 if (g_ShellCache
.IsColumnsEveryWhere())
233 std::wstring path
= psci
->wszFolder
;
236 if (! g_ShellCache
.HasGITAdminDir(path
.c_str(), TRUE
))
239 columnfilepath
= _T("");
243 void CShellExt::GetColumnStatus(const TCHAR
* path
, BOOL bIsDir
)
245 PreserveChdir preserveChdir
;
246 if (_tcscmp(path
, columnfilepath
.c_str())==0)
249 columnfilepath
= path
;
250 const FileStatusCacheEntry
* status
= NULL
;
251 TGITCacheResponse itemStatus
;
252 ShellCache::CacheType t
= ShellCache::exe
;
253 AutoLocker
lock(g_csGlobalCOMGuard
);
254 t
= g_ShellCache
.GetCacheType();
258 case ShellCache::exe
:
260 SecureZeroMemory(&itemStatus
, sizeof(itemStatus
));
261 if(m_remoteCacheLink
.GetStatusFromRemoteCache(CTGitPath(path
), &itemStatus
, true))
263 filestatus
= GitStatus::GetMoreImportant(itemStatus
.m_status
.text_status
, itemStatus
.m_status
.prop_status
);
267 filestatus
= git_wc_status_none
;
268 columnauthor
.clear();
269 columnrev
= GIT_INVALID_REVNUM
;
271 itemshorturl
.clear();
276 case ShellCache::dll
:
277 case ShellCache::dllFull
:
279 status
= m_CachedStatus
.GetFullStatus(CTGitPath(path
), bIsDir
, TRUE
);
280 filestatus
= status
->status
;
284 case ShellCache::none
:
286 if (g_ShellCache
.HasGITAdminDir(path
, bIsDir
))
287 filestatus
= git_wc_status_normal
;
289 filestatus
= git_wc_status_none
;
290 columnauthor
.clear();
291 columnrev
= GIT_INVALID_REVNUM
;
293 itemshorturl
.clear();