CommitDlg: Update index using libgit2 incrementally
[TortoiseGit.git] / src / TGitCache / CacheInterface.cpp
blob7f1ec92766408cda036de371b6ba4af46bb38139
1 // TortoiseGit - a Windows shell extension for easy version control
3 // External Cache Copyright (C) 2007,2009-2012 - 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 "CacheInterface.h"
22 #include "SmartHandle.h"
23 #include <memory>
25 CString GetCachePipeName()
27 return TGIT_CACHE_PIPE_NAME + GetCacheID();
30 CString GetCacheCommandPipeName()
32 return TGIT_CACHE_COMMANDPIPE_NAME + GetCacheID();
35 CString GetCacheMutexName()
37 return TGIT_CACHE_MUTEX_NAME + GetCacheID();
40 CString GetCacheID()
42 CString t;
43 CAutoGeneralHandle token;
44 BOOL result = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, token.GetPointer());
45 if(result)
47 DWORD len = 0;
48 GetTokenInformation(token, TokenStatistics, NULL, 0, &len);
49 if (len >= sizeof (TOKEN_STATISTICS))
51 std::unique_ptr<BYTE[]> data (new BYTE[len]);
52 GetTokenInformation(token, TokenStatistics, data.get(), len, &len);
53 LUID uid = ((PTOKEN_STATISTICS)data.get())->AuthenticationId;
54 t.Format(_T("-%08x%08x"), uid.HighPart, uid.LowPart);
57 return t;
60 bool SendCacheCommand(BYTE command, const WCHAR * path /* = NULL */)
62 int retrycount = 2;
63 CAutoFile hPipe;
66 hPipe = CreateFile(
67 GetCacheCommandPipeName(), // pipe name
68 GENERIC_READ | // read and write access
69 GENERIC_WRITE,
70 0, // no sharing
71 NULL, // default security attributes
72 OPEN_EXISTING, // opens existing pipe
73 FILE_FLAG_OVERLAPPED, // default attributes
74 NULL); // no template file
75 retrycount--;
76 if (!hPipe)
77 Sleep(10);
78 } while ((!hPipe) && (retrycount));
80 if (!hPipe)
82 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Could not connect to pipe\n");
83 return false;
86 // The pipe connected; change to message-read mode.
87 DWORD dwMode = PIPE_READMODE_MESSAGE;
88 if (SetNamedPipeHandleState(
89 hPipe, // pipe handle
90 &dwMode, // new pipe mode
91 NULL, // don't set maximum bytes
92 NULL)) // don't set maximum time
94 DWORD cbWritten;
95 TGITCacheCommand cmd;
96 SecureZeroMemory(&cmd, sizeof(TGITCacheCommand));
97 cmd.command = command;
98 if (path)
99 _tcsncpy_s(cmd.path, path, _TRUNCATE);
101 retrycount = 2;
102 BOOL fSuccess = FALSE;
105 fSuccess = WriteFile(
106 hPipe, // handle to pipe
107 &cmd, // buffer to write from
108 sizeof(cmd), // number of bytes to write
109 &cbWritten, // number of bytes written
110 NULL); // not overlapped I/O
111 retrycount--;
112 if (! fSuccess || sizeof(cmd) != cbWritten)
113 Sleep(10);
114 } while ((retrycount) && (! fSuccess || sizeof(cmd) != cbWritten));
116 if (! fSuccess || sizeof(cmd) != cbWritten)
118 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Could not write to pipe\n");
119 DisconnectNamedPipe(hPipe);
120 return false;
122 // now tell the cache we don't need it's command thread anymore
123 SecureZeroMemory(&cmd, sizeof(TGITCacheCommand));
124 cmd.command = TGITCACHECOMMAND_END;
125 WriteFile(
126 hPipe, // handle to pipe
127 &cmd, // buffer to write from
128 sizeof(cmd), // number of bytes to write
129 &cbWritten, // number of bytes written
130 NULL); // not overlapped I/O
131 DisconnectNamedPipe(hPipe);
133 else
135 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": SetNamedPipeHandleState failed");
136 return false;
139 return true;
142 CBlockCacheForPath::CBlockCacheForPath(const WCHAR * aPath)
144 wcsncpy_s(path, aPath, _countof(path) - 1);
146 SendCacheCommand(TGITCACHECOMMAND_BLOCK, path);
147 // Wait a short while to make sure the cache has
148 // processed this command. Without this, we risk
149 // executing the svn command before the cache has
150 // blocked the path and already gets change notifications.
151 Sleep(20);
154 CBlockCacheForPath::~CBlockCacheForPath()
156 int retry = 3;
157 while (retry-- && !SendCacheCommand(TGITCACHECOMMAND_UNBLOCK, path))
158 Sleep(10);