1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - 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 // IColumnProvider members
43 STDMETHODIMP
CShellExt::GetColumnInfo(DWORD dwIndex
, SHCOLUMNINFO
*psci
)
45 PreserveChdir preserveChdir
;
46 if (dwIndex
> 0) // TODO: keep for now to be able to hide unimplemented columns
49 ShellCache::CacheType cachetype
= g_ShellCache
.GetCacheType();
50 if (cachetype
== ShellCache::none
)
57 GetColumnInfo(dwIndex
, psci
, 15, IDS_COLTITLESTATUS
, IDS_COLDESCSTATUS
);
59 case 1: // Git Revision
60 GetColumnInfo(dwIndex
, psci
, 40, IDS_COLTITLEREV
, IDS_COLDESCREV
);
63 GetColumnInfo(dwIndex
, psci
, 30, IDS_COLTITLEURL
, IDS_COLDESCURL
);
65 case 3: // Git Short Url
66 GetColumnInfo(dwIndex
, psci
, 30, IDS_COLTITLESHORTURL
, IDS_COLDESCSHORTURL
);
68 case 4: // Author and Git Author
69 psci
->scid
.fmtid
= FMTID_SummaryInformation
; // predefined FMTID
70 psci
->scid
.pid
= PIDSI_AUTHOR
; // Predefined - author
71 psci
->vt
= VT_LPSTR
; // We'll return the data as a string
72 psci
->fmt
= LVCFMT_LEFT
; // Text will be left-aligned in the column
73 psci
->csFlags
= SHCOLSTATE_TYPE_STR
; // Data should be sorted as strings
74 psci
->cChars
= 32; // Default col width in chars
75 MAKESTRING(IDS_COLTITLEAUTHOR
);
76 lstrcpynW(psci
->wszTitle
, stringtablebuffer
, MAX_COLUMN_NAME_LEN
);
77 MAKESTRING(IDS_COLDESCAUTHOR
);
78 lstrcpynW(psci
->wszDescription
, stringtablebuffer
, MAX_COLUMN_DESC_LEN
);
80 case 5: // SVN eol-style
81 GetColumnInfo(dwIndex
, psci
, 30, IDS_COLTITLEEOLSTYLE
, IDS_COLDESCEOLSTYLE
);
90 void CShellExt::GetColumnInfo(DWORD dwIndex
, SHCOLUMNINFO
*psci
, UINT characterCount
, UINT title
, UINT description
)
92 psci
->scid
.fmtid
= CLSID_Tortoisegit_UPTODATE
;
93 psci
->scid
.pid
= dwIndex
;
95 psci
->fmt
= LVCFMT_LEFT
;
96 psci
->cChars
= characterCount
;
97 psci
->csFlags
= ColumnFlags
;
100 lstrcpynW(psci
->wszTitle
, stringtablebuffer
, MAX_COLUMN_NAME_LEN
);
101 MAKESTRING(description
);
102 lstrcpynW(psci
->wszDescription
, stringtablebuffer
, MAX_COLUMN_DESC_LEN
);
105 STDMETHODIMP
CShellExt::GetItemData(LPCSHCOLUMNID pscid
, LPCSHCOLUMNDATA pscd
, VARIANT
*pvarData
)
107 PreserveChdir preserveChdir
;
108 if (!g_ShellCache
.IsPathAllowed((TCHAR
*)pscd
->wszFile
))
113 ShellCache::CacheType cachetype
= g_ShellCache
.GetCacheType();
114 if (pscid
->fmtid
== CLSID_Tortoisegit_UPTODATE
)
117 const TCHAR
* path
= (TCHAR
*)pscd
->wszFile
;
119 // reserve for the path + trailing \0
121 TCHAR buf
[MAX_STATUS_STRING_LENGTH
+1];
122 SecureZeroMemory(buf
, MAX_STATUS_STRING_LENGTH
);
125 case 0: // Git Status
126 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
127 GitStatus::GetStatusString(g_hResInst
, filestatus
, buf
, _countof(buf
), (WORD
)CRegStdDWORD(_T("Software\\TortoiseGit\\LanguageID"), MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
)));
130 case 1: // Git Revision
132 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
135 V_VT(pvarData
) = VT_I4
;
136 V_I4(pvarData
) = columnrev
;
142 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
145 case 3: // Git Short Url
146 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
147 szInfo
= itemshorturl
;
149 case 5: // Git eol-style
151 if (cachetype
== ShellCache::none
)
153 if (g_ShellCache
.IsPathAllowed(path
))
155 SVNProperties props
= SVNProperties(CTSVNPath(path
), false);
156 for (int i
=0; i
<props
.GetCount(); i
++)
158 if (props
.GetItemName(i
).compare(_T("svn:eol-style"))==0)
160 szInfo
= MultibyteToWide((char *)props
.GetItemValue(i
).c_str());
169 const WCHAR
* wsInfo
= szInfo
.c_str();
170 V_VT(pvarData
) = VT_BSTR
;
171 V_BSTR(pvarData
) = SysAllocString(wsInfo
);
174 if (pscid
->fmtid
== FMTID_SummaryInformation
)
177 const TCHAR
* path
= pscd
->wszFile
;
179 if (cachetype
== ShellCache::none
)
183 case PIDSI_AUTHOR
: // Author and Git Author
184 GetColumnStatus(path
, pscd
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
185 szInfo
= columnauthor
;
190 wide_string wsInfo
= szInfo
;
191 V_VT(pvarData
) = VT_BSTR
;
192 V_BSTR(pvarData
) = SysAllocString(wsInfo
.c_str());
199 STDMETHODIMP
CShellExt::Initialize(LPCSHCOLUMNINIT psci
)
201 // psci->wszFolder (WCHAR) holds the path to the folder to be displayed
202 // Should check to see if its a "SVN" folder and if not return E_FAIL
204 PreserveChdir preserveChdir
;
205 if (g_ShellCache
.IsColumnsEveryWhere())
207 std::wstring path
= psci
->wszFolder
;
210 if (! g_ShellCache
.HasGITAdminDir(path
.c_str(), TRUE
))
213 columnfilepath
= _T("");
217 void CShellExt::GetColumnStatus(const TCHAR
* path
, BOOL bIsDir
)
219 PreserveChdir preserveChdir
;
220 if (_tcscmp(path
, columnfilepath
.c_str())==0)
223 columnfilepath
= path
;
224 const FileStatusCacheEntry
* status
= NULL
;
225 TGITCacheResponse itemStatus
;
226 ShellCache::CacheType t
= ShellCache::exe
;
227 AutoLocker
lock(g_csGlobalCOMGuard
);
228 t
= g_ShellCache
.GetCacheType();
232 case ShellCache::exe
:
234 SecureZeroMemory(&itemStatus
, sizeof(itemStatus
));
235 if(m_remoteCacheLink
.GetStatusFromRemoteCache(CTGitPath(path
), &itemStatus
, true))
237 filestatus
= GitStatus::GetMoreImportant(itemStatus
.m_status
.text_status
, itemStatus
.m_status
.prop_status
);
241 filestatus
= git_wc_status_none
;
242 columnauthor
.clear();
243 columnrev
= GIT_INVALID_REVNUM
;
245 itemshorturl
.clear();
251 case ShellCache::dll
:
252 case ShellCache::dllFull
:
254 status
= m_CachedStatus
.GetFullStatus(CTGitPath(path
), bIsDir
, TRUE
);
255 filestatus
= status
->status
;
259 case ShellCache::none
:
261 if (g_ShellCache
.HasGITAdminDir(path
, bIsDir
))
262 filestatus
= git_wc_status_normal
;
264 filestatus
= git_wc_status_none
;
265 columnauthor
.clear();
266 columnrev
= GIT_INVALID_REVNUM
;
268 itemshorturl
.clear();
275 if (t
== ShellCache::exe
)
277 columnrev
= itemStatus
.m_entry
.cmt_rev
;
283 columnrev
= status
->rev
;