Use libgit2 for GetOneFile
[TortoiseGit.git] / src / Git / Git.h
blob8bf12205d50b0cfba758c8572172e9d5967428e7
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 class CFilterData
30 public:
31 CFilterData()
33 m_From=m_To=-1;
34 m_IsRegex=1;
36 __time64_t m_From;
37 __time64_t m_To;
38 CString m_Author;
39 CString m_Committer;
40 CString m_MessageFilter;
41 BOOL m_IsRegex;
44 class CGitCall
46 public:
47 CGitCall(){}
48 CGitCall(CString cmd):m_Cmd(cmd){}
50 CString GetCmd()const{return m_Cmd;}
51 void SetCmd(CString cmd){m_Cmd=cmd;}
53 //This function is called when command output data is available.
54 //When this function returns 'true' the git command should be aborted.
55 //This behavior is not implemented yet.
56 virtual bool OnOutputData(const BYTE* data, size_t size)=0;
57 virtual bool OnOutputErrData(const BYTE* data, size_t size)=0;
58 virtual void OnEnd(){}
60 private:
61 CString m_Cmd;
64 typedef std::function<void (const CStringA&)> GitReceiverFunc;
66 class CTGitPath;
67 class CEnvironment:public std::vector<TCHAR>
69 public:
70 void CopyProcessEnvironment();
71 CString GetEnv(const TCHAR *name);
72 void SetEnv(const TCHAR* name, const TCHAR* value);
74 class CGit
76 private:
77 GitAdminDir m_GitDir;
78 CString gitLastErr;
79 protected:
80 bool m_IsGitDllInited;
81 GIT_DIFF m_GitDiff;
82 GIT_DIFF m_GitSimpleListDiff;
83 public:
84 CComCriticalSection m_critGitDllSec;
85 bool m_IsUseGitDLL;
86 bool m_IsUseLibGit2;
87 DWORD m_IsUseLibGit2_mask;
89 CEnvironment m_Environment;
91 static BOOL GitPathFileExists(const CString &path)
93 if(path[0] == _T('\\') && path[1] == _T('\\'))
94 //it is netshare \\server\sharefoldername
95 // \\server\.git will create smb error log.
97 int length = path.GetLength();
99 if(length<2)
100 return false;
102 int start = path.Find(_T('\\'),2);
103 if(start<0)
104 return false;
106 start = path.Find(_T('\\'),start+1);
107 if(start<0)
108 return false;
110 return PathFileExists(path);
113 else
114 return PathFileExists(path);
116 void CheckAndInitDll()
118 if(!m_IsGitDllInited)
120 git_init();
121 m_IsGitDllInited=true;
125 GIT_DIFF GetGitDiff()
127 if(m_GitDiff)
128 return m_GitDiff;
129 else
131 git_open_diff(&m_GitDiff,"-C -M -r");
132 return m_GitDiff;
136 GIT_DIFF GetGitSimpleListDiff()
138 if(m_GitSimpleListDiff)
139 return m_GitSimpleListDiff;
140 else
142 git_open_diff(&m_GitSimpleListDiff,"-r -r");
143 return m_GitSimpleListDiff;
147 BOOL CheckMsysGitDir(BOOL bFallback = TRUE);
148 BOOL m_bInitialized;
150 typedef enum
152 GIT_CMD_CLONE,
153 GIT_CMD_FETCH,
154 GIT_CMD_COMMIT_UPDATE_INDEX,
155 GIT_CMD_DIFF,
156 GIT_CMD_RESET,
157 GIT_CMD_REVERT,
158 GIT_CMD_MERGE_BASE,
159 GIT_CMD_DELETETAGBRANCH,
160 GIT_CMD_GETONEFILE,
161 } LIBGIT2_CMD;
162 bool UsingLibGit2(LIBGIT2_CMD cmd);
164 CString GetHomeDirectory();
165 CString GetGitLocalConfig();
166 CString GetGitGlobalConfig();
167 CString GetGitGlobalXDGConfigPath();
168 CString GetGitGlobalXDGConfig();
169 CString GetGitSystemConfig();
170 static CStringA GetGitPathStringA(const CString &path);
171 static CString ms_LastMsysGitDir; // the last msysgitdir added to the path, blank if none
172 static int ms_LastMsysGitVersion;
173 static int m_LogEncode;
174 static bool IsBranchNameValid(const CString& branchname);
175 bool IsBranchTagNameUnique(const CString& name);
176 bool BranchTagExists(const CString& name, bool isBranch = true);
177 unsigned int Hash2int(const CGitHash &hash);
179 PROCESS_INFORMATION m_CurrentGitPi;
181 CGit(void);
182 ~CGit(void);
184 int Run(CString cmd, CString* output, int code);
185 int Run(CString cmd, CString* output, CString* outputErr, int code);
186 int Run(CString cmd, BYTE_VECTOR *byte_array, BYTE_VECTOR *byte_arrayErr = NULL);
187 int Run(CGitCall* pcall);
188 int Run(CString cmd, const GitReceiverFunc& recv);
190 private:
191 static DWORD WINAPI AsyncReadStdErrThread(LPVOID lpParam);
192 typedef struct AsyncReadStdErrThreadArguments
194 HANDLE fileHandle;
195 CGitCall* pcall;
196 } ASYNCREADSTDERRTHREADARGS, *PASYNCREADSTDERRTHREADARGS;
197 CString GetUnifiedDiffCmd(const CTGitPath& path, const git_revnum_t& rev1, const git_revnum_t& rev2, bool bMerge, bool bCombine, int diffContext);
199 public:
200 int RunAsync(CString cmd, PROCESS_INFORMATION *pi, HANDLE* hRead, HANDLE *hErrReadOut, CString *StdioFile = NULL);
201 int RunLogFile(CString cmd, const CString &filename, CString *stdErr);
203 int GetDiffPath(CTGitPathList *PathList, CGitHash *hash1, CGitHash *hash2, char *arg=NULL);
205 int GetGitEncode(TCHAR* configkey);
207 bool IsFastForward(const CString &from, const CString &to, CGitHash * commonAncestor = NULL);
208 CString GetConfigValue(const CString& name, int encoding = CP_UTF8, BOOL RemoveCR = TRUE);
209 bool GetConfigValueBool(const CString& name);
211 int SetConfigValue(const CString& key, const CString& value, CONFIG_TYPE type = CONFIG_LOCAL, int encoding = CP_UTF8);
212 int UnsetConfigValue(const CString& key, CONFIG_TYPE type = CONFIG_LOCAL, int encoding = CP_UTF8);
214 CString GetUserName(void);
215 CString GetUserEmail(void);
216 CString GetCurrentBranch(bool fallback = false);
217 CString GetSymbolicRef(const wchar_t* symbolicRefName = L"HEAD", bool bStripRefsHeads = true);
218 // read current branch name from HEAD file, returns 0 on success, -1 on failure, 1 detached (branch name "HEAD" returned)
219 static int GetCurrentBranchFromFile(const CString &sProjectRoot, CString &sBranchOut, bool fallback = false);
220 BOOL CheckCleanWorkTree();
221 int Revert(const CString& commit, const CTGitPathList &list, bool keep=true);
222 int Revert(const CString& commit, const CTGitPath &path);
223 int DeleteRef(const CString& reference);
224 CString GetGitLastErr(const CString& msg);
225 CString GetGitLastErr(const CString& msg, LIBGIT2_CMD cmd);
226 static CString GetLibGit2LastErr();
227 static CString GetLibGit2LastErr(const CString& msg);
228 bool SetCurrentDir(CString path, bool submodule = false)
230 bool b = m_GitDir.HasAdminDir(path, submodule ? false : !!PathIsDirectory(path), &m_CurrentDir);
231 if (!b && g_GitAdminDir.IsBareRepo(path))
233 m_CurrentDir = path;
234 b = true;
236 if(m_CurrentDir.GetLength() == 2 && m_CurrentDir[1] == _T(':')) //C: D:
238 m_CurrentDir += _T('\\');
240 return b;
242 CString m_CurrentDir;
244 enum
246 LOG_ORDER_CHRONOLOGIALREVERSED,
247 LOG_ORDER_TOPOORDER,
248 LOG_ORDER_DATEORDER,
251 typedef enum
253 BRANCH_LOCAL = 0x1,
254 BRANCH_REMOTE = 0x2,
255 BRANCH_FETCH_HEAD = 0x4,
256 BRANCH_LOCAL_F = BRANCH_LOCAL | BRANCH_FETCH_HEAD,
257 BRANCH_ALL = BRANCH_LOCAL | BRANCH_REMOTE,
258 BRANCH_ALL_F = BRANCH_ALL | BRANCH_FETCH_HEAD,
259 }BRANCH_TYPE;
261 typedef enum
263 LOG_INFO_STAT=0x1,
264 LOG_INFO_FILESTATE=0x2,
265 LOG_INFO_PATCH=0x4,
266 LOG_INFO_FULLHISTORY=0x8,
267 LOG_INFO_BOUNDARY=0x10,
268 LOG_INFO_ALL_BRANCH=0x20,
269 LOG_INFO_ONLY_HASH=0x40,
270 LOG_INFO_DETECT_RENAME=0x80,
271 LOG_INFO_DETECT_COPYRENAME=0x100,
272 LOG_INFO_FIRST_PARENT = 0x200,
273 LOG_INFO_NO_MERGE = 0x400,
274 LOG_INFO_FOLLOW = 0x800,
275 LOG_INFO_SHOW_MERGEDFILE=0x1000,
276 LOG_INFO_FULL_DIFF = 0x2000,
277 LOG_INFO_SIMPILFY_BY_DECORATION = 0x4000,
278 LOG_INFO_LOCAL_BRANCHES = 0x8000,
279 }LOG_INFO_MASK;
281 typedef enum
283 LOCAL_BRANCH,
284 REMOTE_BRANCH,
285 TAG,
286 STASH,
287 BISECT_GOOD,
288 BISECT_BAD,
289 NOTES,
290 UNKNOWN,
292 }REF_TYPE;
294 int GetRemoteList(STRING_VECTOR &list);
295 int GetBranchList(STRING_VECTOR &list, int *Current,BRANCH_TYPE type=BRANCH_LOCAL);
296 int GetTagList(STRING_VECTOR &list);
297 int GetRemoteTags(const CString& remote, STRING_VECTOR &list);
298 int GetMapHashToFriendName(MAP_HASH_NAME &map);
300 CString DerefFetchHead();
302 // FixBranchName():
303 // When branchName == FETCH_HEAD, derefrence it.
304 // A selected branch name got from GetBranchList(), with flag BRANCH_FETCH_HEAD enabled,
305 // should go through this function before it is used.
306 CString FixBranchName_Mod(CString& branchName);
307 CString FixBranchName(const CString& branchName);
309 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);
311 int GetHash(CGitHash &hash, const CString& friendname);
313 int BuildOutputFormat(CString &format,bool IsFull=TRUE);
314 static void StringAppend(CString *str, const BYTE *p, int code = CP_UTF8, int length = -1);
316 BOOL CanParseRev(CString ref);
317 BOOL IsInitRepos();
318 int ListConflictFile(CTGitPathList &list, const CTGitPath *path = nullptr);
319 int GetRefList(STRING_VECTOR &list);
321 int RefreshGitIndex();
322 int GetOneFile(const CString &Refname, const CTGitPath &path, const CString &outputfile);
324 //Example: master -> refs/heads/master
325 CString GetFullRefName(const CString& shortRefName);
326 //Removes 'refs/heads/' or just 'refs'. Example: refs/heads/master -> master
327 static CString StripRefName(CString refName);
329 int GetCommitDiffList(const CString &rev1, const CString &rev2, CTGitPathList &outpathlist, bool ignoreSpaceAtEol = false, bool ignoreSpaceChange = false, bool ignoreAllSpace = false, bool ignoreBlankLines = false);
330 int GetInitAddList(CTGitPathList &outpathlist);
332 __int64 filetime_to_time_t(const FILETIME *ft)
334 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
335 winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
336 winTime /= 10000000; /* Nano to seconds resolution */
337 return (time_t)winTime;
340 int GetFileModifyTime(LPCTSTR filename, __int64 *time, bool * isDir=NULL)
342 WIN32_FILE_ATTRIBUTE_DATA fdata;
343 if (GetFileAttributesEx(filename, GetFileExInfoStandard, &fdata))
345 if(time)
346 *time = filetime_to_time_t(&fdata.ftLastWriteTime);
348 if(isDir)
349 *isDir = !!( fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
351 return 0;
353 return -1;
356 int GetShortHASHLength();
358 static BOOL GetShortName(CString ref, CString &shortname, CString prefix)
360 //TRACE(_T("%s %s\r\n"),ref,prefix);
361 if (ref.Left(prefix.GetLength()) == prefix)
363 shortname = ref.Right(ref.GetLength() - prefix.GetLength());
364 if (shortname.Right(3) == _T("^{}"))
365 shortname=shortname.Left(shortname.GetLength() - 3);
366 return TRUE;
368 return FALSE;
371 static CString GetShortName(const CString& ref, REF_TYPE *type);
373 int GetUnifiedDiff(const CTGitPath& path, const git_revnum_t& rev1, const git_revnum_t& rev2, CString patchfile, bool bMerge, bool bCombine, int diffContext);
374 int GetUnifiedDiff(const CTGitPath& path, const git_revnum_t& rev1, const git_revnum_t& rev2, CStringA * buffer, bool bMerge, bool bCombine, int diffContext);
376 int GitRevert(int parent, const CGitHash &hash);
378 extern void GetTempPath(CString &path);
379 extern CString GetTempFile();
380 extern DWORD GetTortoiseGitTempPath(DWORD nBufferLength, LPTSTR lpBuffer);
382 extern CGit g_Git;