Tabify
[TortoiseGit.git] / src / Git / Git.h
blob75dff2327df8dadf14c747cfd50b23942c842e02
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2014 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #pragma once
21 #include "GitType.h"
22 #include "GitRev.h"
23 #include "GitStatus.h"
24 #include "GitAdminDir.h"
25 #include "gitdll.h"
26 #include <functional>
28 #define REG_MSYSGIT_PATH _T("Software\\TortoiseGit\\MSysGit")
29 #define REG_MSYSGIT_EXTRA_PATH _T("Software\\TortoiseGit\\MSysGitExtra")
31 struct git_repository;
33 class CFilterData
35 public:
36 CFilterData()
38 m_From=m_To=-1;
39 m_IsRegex=1;
41 __time64_t m_From;
42 __time64_t m_To;
43 CString m_Author;
44 CString m_Committer;
45 CString m_MessageFilter;
46 BOOL m_IsRegex;
49 class CGitCall
51 public:
52 CGitCall(){}
53 CGitCall(CString cmd):m_Cmd(cmd){}
55 CString GetCmd()const{return m_Cmd;}
56 void SetCmd(CString cmd){m_Cmd=cmd;}
58 //This function is called when command output data is available.
59 //When this function returns 'true' the git command should be aborted.
60 //This behavior is not implemented yet.
61 virtual bool OnOutputData(const BYTE* data, size_t size)=0;
62 virtual bool OnOutputErrData(const BYTE* data, size_t size)=0;
63 virtual void OnEnd(){}
65 private:
66 CString m_Cmd;
69 typedef std::function<void (const CStringA&)> GitReceiverFunc;
71 class CTGitPath;
72 class CEnvironment:public std::vector<TCHAR>
74 public:
75 void CopyProcessEnvironment();
76 CString GetEnv(const TCHAR *name);
77 void SetEnv(const TCHAR* name, const TCHAR* value);
79 class CGit
81 private:
82 GitAdminDir m_GitDir;
83 CString gitLastErr;
84 protected:
85 bool m_IsGitDllInited;
86 GIT_DIFF m_GitDiff;
87 GIT_DIFF m_GitSimpleListDiff;
88 public:
89 CComCriticalSection m_critGitDllSec;
90 bool m_IsUseGitDLL;
91 bool m_IsUseLibGit2;
92 DWORD m_IsUseLibGit2_mask;
94 CEnvironment m_Environment;
96 static BOOL GitPathFileExists(const CString &path)
98 if(path[0] == _T('\\') && path[1] == _T('\\'))
99 //it is netshare \\server\sharefoldername
100 // \\server\.git will create smb error log.
102 int length = path.GetLength();
104 if(length<2)
105 return false;
107 int start = path.Find(_T('\\'),2);
108 if(start<0)
109 return false;
111 start = path.Find(_T('\\'),start+1);
112 if(start<0)
113 return false;
115 return PathFileExists(path);
118 else
119 return PathFileExists(path);
121 void CheckAndInitDll()
123 if(!m_IsGitDllInited)
125 git_init();
126 m_IsGitDllInited=true;
130 GIT_DIFF GetGitDiff()
132 if(m_GitDiff)
133 return m_GitDiff;
134 else
136 git_open_diff(&m_GitDiff,"-C -M -r");
137 return m_GitDiff;
141 GIT_DIFF GetGitSimpleListDiff()
143 if(m_GitSimpleListDiff)
144 return m_GitSimpleListDiff;
145 else
147 git_open_diff(&m_GitSimpleListDiff,"-r -r");
148 return m_GitSimpleListDiff;
152 BOOL CheckMsysGitDir(BOOL bFallback = TRUE);
153 BOOL m_bInitialized;
155 typedef enum
157 GIT_CMD_CLONE,
158 GIT_CMD_FETCH,
159 GIT_CMD_COMMIT_UPDATE_INDEX,
160 GIT_CMD_DIFF,
161 GIT_CMD_RESET,
162 GIT_CMD_REVERT,
163 GIT_CMD_MERGE_BASE,
164 GIT_CMD_DELETETAGBRANCH,
165 GIT_CMD_GETONEFILE,
166 GIT_CMD_ADD,
167 } LIBGIT2_CMD;
168 bool UsingLibGit2(LIBGIT2_CMD cmd) const;
170 CString GetHomeDirectory() const;
171 CString GetGitLocalConfig() const;
172 CString GetGitGlobalConfig() const;
173 CString GetGitGlobalXDGConfigPath() const;
174 CString GetGitGlobalXDGConfig() const;
175 CString GetGitSystemConfig() const;
176 git_repository * GetGitRepository() const;
177 static CStringA GetGitPathStringA(const CString &path);
178 static CString ms_LastMsysGitDir; // the last msysgitdir added to the path, blank if none
179 static int ms_LastMsysGitVersion;
180 static int m_LogEncode;
181 static bool IsBranchNameValid(const CString& branchname);
182 bool IsBranchTagNameUnique(const CString& name);
184 * Checks if a branch or tag with the given name exists
185 *isBranch is true -> branch, tag otherwise
187 bool BranchTagExists(const CString& name, bool isBranch = true);
188 unsigned int Hash2int(const CGitHash &hash);
190 PROCESS_INFORMATION m_CurrentGitPi;
192 CGit(void);
193 ~CGit(void);
195 int Run(CString cmd, CString* output, int code);
196 int Run(CString cmd, CString* output, CString* outputErr, int code);
197 int Run(CString cmd, BYTE_VECTOR *byte_array, BYTE_VECTOR *byte_arrayErr = NULL);
198 int Run(CGitCall* pcall);
199 int Run(CString cmd, const GitReceiverFunc& recv);
201 private:
202 static DWORD WINAPI AsyncReadStdErrThread(LPVOID lpParam);
203 typedef struct AsyncReadStdErrThreadArguments
205 HANDLE fileHandle;
206 CGitCall* pcall;
207 } ASYNCREADSTDERRTHREADARGS, *PASYNCREADSTDERRTHREADARGS;
208 CString GetUnifiedDiffCmd(const CTGitPath& path, const git_revnum_t& rev1, const git_revnum_t& rev2, bool bMerge, bool bCombine, int diffContext);
210 public:
211 int RunAsync(CString cmd, PROCESS_INFORMATION *pi, HANDLE* hRead, HANDLE *hErrReadOut, CString *StdioFile = NULL);
212 int RunLogFile(CString cmd, const CString &filename, CString *stdErr);
214 int GetDiffPath(CTGitPathList *PathList, CGitHash *hash1, CGitHash *hash2, char *arg=NULL);
216 int GetGitEncode(TCHAR* configkey);
218 bool IsFastForward(const CString &from, const CString &to, CGitHash * commonAncestor = NULL);
219 CString GetConfigValue(const CString& name);
220 bool GetConfigValueBool(const CString& name);
221 int GetConfigValueInt32(const CString& name, int def = 0);
223 int SetConfigValue(const CString& key, const CString& value, CONFIG_TYPE type = CONFIG_LOCAL);
224 int UnsetConfigValue(const CString& key, CONFIG_TYPE type = CONFIG_LOCAL);
226 CString GetUserName(void);
227 CString GetUserEmail(void);
228 CString GetCurrentBranch(bool fallback = false);
229 void GetRemoteTrackedBranch(const CString& localBranch, CString& remote, CString& branch);
230 void GetRemoteTrackedBranchForHEAD(CString& remote, CString& branch);
231 // read current branch name from HEAD file, returns 0 on success, -1 on failure, 1 detached (branch name "HEAD" returned)
232 static int GetCurrentBranchFromFile(const CString &sProjectRoot, CString &sBranchOut, bool fallback = false);
233 BOOL CheckCleanWorkTree();
234 int Revert(const CString& commit, const CTGitPathList &list, CString& err);
235 int Revert(const CString& commit, const CTGitPath &path, CString& err);
236 int DeleteRef(const CString& reference);
238 Use this method only if m_IsUseLibGit2 is used for fallbacks.
239 If you directly use libgit2 methods, use GetLibGit2LastErr instead.
241 CString GetGitLastErr(const CString& msg);
242 CString GetGitLastErr(const CString& msg, LIBGIT2_CMD cmd);
243 static CString GetLibGit2LastErr();
244 static CString GetLibGit2LastErr(const CString& msg);
245 bool SetCurrentDir(CString path, bool submodule = false)
247 bool b = m_GitDir.HasAdminDir(path, submodule ? false : !!PathIsDirectory(path), &m_CurrentDir);
248 if (!b && g_GitAdminDir.IsBareRepo(path))
250 m_CurrentDir = path;
251 b = true;
253 if(m_CurrentDir.GetLength() == 2 && m_CurrentDir[1] == _T(':')) //C: D:
255 m_CurrentDir += _T('\\');
257 return b;
259 CString m_CurrentDir;
261 enum
263 LOG_ORDER_CHRONOLOGIALREVERSED,
264 LOG_ORDER_TOPOORDER,
265 LOG_ORDER_DATEORDER,
268 typedef enum
270 BRANCH_LOCAL = 0x1,
271 BRANCH_REMOTE = 0x2,
272 BRANCH_FETCH_HEAD = 0x4,
273 BRANCH_LOCAL_F = BRANCH_LOCAL | BRANCH_FETCH_HEAD,
274 BRANCH_ALL = BRANCH_LOCAL | BRANCH_REMOTE,
275 BRANCH_ALL_F = BRANCH_ALL | BRANCH_FETCH_HEAD,
276 }BRANCH_TYPE;
278 typedef enum
280 LOG_INFO_STAT=0x1,
281 LOG_INFO_FILESTATE=0x2,
282 LOG_INFO_PATCH=0x4,
283 LOG_INFO_FULLHISTORY=0x8,
284 LOG_INFO_BOUNDARY=0x10,
285 LOG_INFO_ALL_BRANCH=0x20,
286 LOG_INFO_ONLY_HASH=0x40,
287 LOG_INFO_DETECT_RENAME=0x80,
288 LOG_INFO_DETECT_COPYRENAME=0x100,
289 LOG_INFO_FIRST_PARENT = 0x200,
290 LOG_INFO_NO_MERGE = 0x400,
291 LOG_INFO_FOLLOW = 0x800,
292 LOG_INFO_SHOW_MERGEDFILE=0x1000,
293 LOG_INFO_FULL_DIFF = 0x2000,
294 LOG_INFO_SIMPILFY_BY_DECORATION = 0x4000,
295 LOG_INFO_LOCAL_BRANCHES = 0x8000,
296 }LOG_INFO_MASK;
298 typedef enum
300 LOCAL_BRANCH,
301 REMOTE_BRANCH,
302 TAG,
303 STASH,
304 BISECT_GOOD,
305 BISECT_BAD,
306 NOTES,
307 UNKNOWN,
309 }REF_TYPE;
311 int GetRemoteList(STRING_VECTOR &list);
312 int GetBranchList(STRING_VECTOR &list, int *Current,BRANCH_TYPE type=BRANCH_LOCAL);
313 int GetTagList(STRING_VECTOR &list);
314 int GetRemoteTags(const CString& remote, STRING_VECTOR &list);
315 int GetMapHashToFriendName(MAP_HASH_NAME &map);
316 static int GetMapHashToFriendName(git_repository* repo, MAP_HASH_NAME &map);
318 CString DerefFetchHead();
320 // FixBranchName():
321 // When branchName == FETCH_HEAD, derefrence it.
322 // A selected branch name got from GetBranchList(), with flag BRANCH_FETCH_HEAD enabled,
323 // should go through this function before it is used.
324 CString FixBranchName_Mod(CString& branchName);
325 CString FixBranchName(const CString& branchName);
327 CString GetLogCmd(const CString &range, const CTGitPath *path = NULL, int count=-1, int InfoMask = LOG_INFO_FULL_DIFF|LOG_INFO_STAT|LOG_INFO_FILESTATE|LOG_INFO_BOUNDARY|LOG_INFO_DETECT_COPYRENAME|LOG_INFO_SHOW_MERGEDFILE, bool paramonly=false, CFilterData * filter =NULL);
329 int GetHash(CGitHash &hash, const CString& friendname);
330 static int GetHash(git_repository * repo, CGitHash &hash, const CString& friendname, bool skipFastCheck = false);
332 int BuildOutputFormat(CString &format,bool IsFull=TRUE);
333 static void StringAppend(CString *str, const BYTE *p, int code = CP_UTF8, int length = -1);
335 BOOL CanParseRev(CString ref);
336 BOOL IsInitRepos();
337 int ListConflictFile(CTGitPathList &list, const CTGitPath *path = nullptr);
338 int GetRefList(STRING_VECTOR &list);
340 int RefreshGitIndex();
341 int GetOneFile(const CString &Refname, const CTGitPath &path, const CString &outputfile);
343 //Example: master -> refs/heads/master
344 CString GetFullRefName(const CString& shortRefName);
345 //Removes 'refs/heads/' or just 'refs'. Example: refs/heads/master -> master
346 static CString StripRefName(CString refName);
348 int GetCommitDiffList(const CString &rev1, const CString &rev2, CTGitPathList &outpathlist, bool ignoreSpaceAtEol = false, bool ignoreSpaceChange = false, bool ignoreAllSpace = false, bool ignoreBlankLines = false);
349 int GetInitAddList(CTGitPathList &outpathlist);
351 __int64 filetime_to_time_t(const FILETIME *ft)
353 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
354 winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
355 winTime /= 10000000; /* Nano to seconds resolution */
356 return (time_t)winTime;
359 int GetFileModifyTime(LPCTSTR filename, __int64 *time, bool * isDir=NULL)
361 WIN32_FILE_ATTRIBUTE_DATA fdata;
362 if (GetFileAttributesEx(filename, GetFileExInfoStandard, &fdata))
364 if(time)
365 *time = filetime_to_time_t(&fdata.ftLastWriteTime);
367 if(isDir)
368 *isDir = !!( fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
370 return 0;
372 return -1;
375 int GetShortHASHLength() const;
377 static BOOL GetShortName(CString ref, CString &shortname, CString prefix)
379 //TRACE(_T("%s %s\r\n"),ref,prefix);
380 if (ref.Left(prefix.GetLength()) == prefix)
382 shortname = ref.Right(ref.GetLength() - prefix.GetLength());
383 if (shortname.Right(3) == _T("^{}"))
384 shortname=shortname.Left(shortname.GetLength() - 3);
385 return TRUE;
387 return FALSE;
390 static CString GetShortName(const CString& ref, REF_TYPE *type);
392 static bool LoadTextFile(const CString &filename, CString &msg);
394 int GetUnifiedDiff(const CTGitPath& path, const git_revnum_t& rev1, const git_revnum_t& rev2, CString patchfile, bool bMerge, bool bCombine, int diffContext);
395 int GetUnifiedDiff(const CTGitPath& path, const git_revnum_t& rev1, const git_revnum_t& rev2, CStringA * buffer, bool bMerge, bool bCombine, int diffContext);
397 int GitRevert(int parent, const CGitHash &hash);
399 CString CombinePath(const CString &path) const
401 if (path.IsEmpty())
402 return m_CurrentDir;
403 if (m_CurrentDir.IsEmpty())
404 return path;
405 return m_CurrentDir + (m_CurrentDir.Right(1) == _T("\\") ? _T("") : _T("\\")) + path;
408 CString CombinePath(const CTGitPath &path) const
410 return CombinePath(path.GetWinPath());
413 CString CombinePath(const CTGitPath *path) const
415 ATLASSERT(path);
416 return CombinePath(path->GetWinPath());
419 extern void GetTempPath(CString &path);
420 extern CString GetTempFile();
421 extern DWORD GetTortoiseGitTempPath(DWORD nBufferLength, LPTSTR lpBuffer);
423 extern CGit g_Git;