Can't change branch name when branch is not default name
[TortoiseGit.git] / src / Git / GitStatus.h
blob2816b6519a30f5868076bb05e61fae63650b1e1b
1 #pragma once
3 #ifdef _MFC_VER
4 //# include "SVNPrompt.h"
5 #endif
6 #include "TGitPath.h"
8 #pragma warning (push,1)
9 typedef std::basic_string<wchar_t> wide_string;
10 #ifdef UNICODE
11 # define stdstring wide_string
12 #else
13 # define stdstring std::string
14 #endif
15 #pragma warning (pop)
17 #include "TGitPath.h"
18 #include "GitHash.h"
20 typedef enum type_git_wc_status_kind
22 git_wc_status_none,
23 git_wc_status_unversioned,
24 git_wc_status_ignored,
25 git_wc_status_normal,
26 git_wc_status_external,
27 git_wc_status_incomplete,
28 git_wc_status_missing,
29 git_wc_status_deleted,
30 git_wc_status_replaced,
31 git_wc_status_modified,
32 git_wc_status_merged,
33 git_wc_status_added,
34 git_wc_status_conflicted,
35 git_wc_status_obstructed,
37 }git_wc_status_kind;
39 typedef enum
41 git_depth_empty,
42 git_depth_infinity,
43 git_depth_unknown,
44 git_depth_files,
45 git_depth_immediates,
46 }git_depth_t;
49 #define GIT_REV_ZERO _T("0000000000000000000000000000000000000000")
50 #define GIT_INVALID_REVNUM _T("")
51 typedef CString git_revnum_t;
52 typedef int git_error_t;
54 typedef struct git_wc_entry_t
56 // url in repository
57 const char *url;
59 TCHAR cmt_rev[41];
60 } git_wc_entry_t;
63 typedef struct git_wc_status2_t
65 /** The status of the entries text. */
66 git_wc_status_kind text_status;
68 /** The status of the entries properties. */
69 git_wc_status_kind prop_status;
71 //git_wc_entry_t *entry;
72 }git_wc_status2;
74 #define MAX_STATUS_STRING_LENGTH 256
77 /////////////////////////////////////////////////////////////////////
78 // WINGIT API (replaced by commandline tool, but defs and data types kept so old code still works)
80 // Flags for wgEnumFiles
81 enum WGENUMFILEFLAGS
83 WGEFF_NoRecurse = (1<<0), // only enumerate files directly in the specified path
84 WGEFF_FullPath = (1<<1), // enumerated filenames are specified with full path (instead of relative to proj root)
85 WGEFF_DirStatusDelta= (1<<2), // include directories, in enumeration, that have a recursive status != WGFS_Normal (may have a slightly better performance than WGEFF_DirStatusAll)
86 WGEFF_DirStatusAll = (1<<3), // include directories, in enumeration, with recursive status
87 WGEFF_EmptyAsNormal = (1<<4), // report sub-directories, with no versioned files, as WGFS_Normal instead of WGFS_Empty
88 WGEFF_SingleFile = (1<<5) // indicates that the status of a single file or dir, specified by pszSubPath, is wanted
91 // File status
92 enum WGFILESTATUS
94 WGFS_Normal,
95 WGFS_Modified,
96 WGFS_Staged,
97 WGFS_Added,
98 WGFS_Conflicted,
99 WGFS_Deleted,
101 WGFS_Ignored = -1,
102 WGFS_Unversioned = -2,
103 WGFS_Empty = -3,
104 WGFS_Unknown = -4
107 // File flags
108 enum WGFILEFLAGS
110 WGFF_Directory = (1<<0) // enumerated file is a directory
113 struct wgFile_s
115 LPCTSTR sFileName; // filename or directory relative to project root (using forward slashes)
116 int nStatus; // the WGFILESTATUS of the file
117 int nFlags; // a combination of WGFILEFLAGS
119 const BYTE* sha1; // points to the BYTE[20] sha1 (NULL for directories, WGFF_Directory)
122 // Application-defined callback function for wgEnumFiles, returns TRUE to abort enumeration
123 // NOTE: do NOT store the pFile pointer or any pointers in wgFile_s for later use, the data is only valid for a single callback call
124 typedef BOOL (__cdecl WGENUMFILECB)(const struct wgFile_s *pFile, void *pUserData);
127 /////////////////////////////////////////////////////////////////////
130 // convert wingit.dll status to git_wc_status_kind
131 inline static git_wc_status_kind GitStatusFromWingit(int nStatus)
133 switch (nStatus)
135 case WGFS_Normal: return git_wc_status_normal;
136 case WGFS_Modified: return git_wc_status_modified;
137 case WGFS_Staged: return git_wc_status_merged;
138 case WGFS_Added: return git_wc_status_added;
139 case WGFS_Conflicted: return git_wc_status_conflicted;
140 case WGFS_Deleted: return git_wc_status_deleted;
142 case WGFS_Ignored: return git_wc_status_ignored;
143 case WGFS_Unversioned: return git_wc_status_unversioned;
144 case WGFS_Empty: return git_wc_status_unversioned;
147 return git_wc_status_none;
150 // convert 20 byte sha1 hash to the git_revnum_t type
151 inline static git_revnum_t ConvertHashToRevnum(const BYTE *sha1)
153 if (!sha1)
154 return GIT_INVALID_REVNUM;
156 char s[41];
157 char *p = s;
158 for (int i=0; i<20; i++)
160 #pragma warning(push)
161 #pragma warning(disable: 4996)
162 sprintf(p, "%02x", (UINT)*sha1);
163 #pragma warning(pop)
164 p += 2;
165 sha1++;
168 return CString(s);
171 typedef BOOL (*FIll_STATUS_CALLBACK)(CString &path,git_wc_status_kind status,bool isDir, void *pdata);
174 * \ingroup Git
175 * Handles Subversion status of working copies.
177 class GitStatus
179 public:
181 #define GIT_MODE_INDEX 0x1
182 #define GIT_MODE_HEAD 0x2
183 #define GIT_MODE_IGNORE 0x4
184 #define GIT_MODE_ALL (GIT_MODE_INDEX|GIT_MODE_HEAD|GIT_MODE_IGNORE)
186 static int GetFileStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false, BOOL isIgnore=true, FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL);
187 static int GetDirStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false, BOOL isIgnore=true, FIll_STATUS_CALLBACK callback=NULL, void *pData=NULL);
188 static int EnumDirStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false, BOOL isIgnore=true, FIll_STATUS_CALLBACK callback=NULL, void *pData=NULL);
189 static bool IsGitReposChanged(CString &gitdir, CString &subpaths, int mode=GIT_MODE_ALL);
190 static int LoadIgnoreFile(CString &gitdir, CString &subpaths);
191 static int IsUnderVersionControl(CString &gitdir, CString &path, bool isDir,bool *isVersion);
192 static int IsIgnore(CString &gitdir, CString &path, bool *isIgnore);
193 static __int64 GetIndexFileTime(CString &gitdir);
194 static bool IsExistIndexLockFile(CString &gitdir);
195 static int GetIgnoreFileChangeTimeList(CString &path, std::vector<__int64> &timelist);
197 static int GetHeadHash(CString &gitdir, CGitHash &hash);
199 public:
200 GitStatus(bool * pbCanceled = NULL);
201 ~GitStatus(void);
205 * Reads the Subversion status of the working copy entry. No
206 * recurse is done, even if the entry is a directory.
207 * If the status of the text and property part are different
208 * then the more important status is returned.
210 static git_wc_status_kind GetAllStatus(const CTGitPath& path, git_depth_t depth = git_depth_empty);
213 * Reads the Subversion status of the working copy entry and all its
214 * subitems. The resulting status is determined by using priorities for
215 * each status. The status with the highest priority is then returned.
216 * If the status of the text and property part are different then
217 * the more important status is returned.
219 static git_wc_status_kind GetAllStatusRecursive(const CTGitPath& path);
222 * Returns the status which is more "important" of the two statuses specified.
223 * This is used for the "recursive" status functions on folders - i.e. which status
224 * should be returned for a folder which has several files with different statuses
225 * in it.
227 static git_wc_status_kind GetMoreImportant(git_wc_status_kind status1, git_wc_status_kind status2);
230 * Checks if a status is "important", i.e. if the status indicates that the user should know about it.
231 * E.g. a "normal" status is not important, but "modified" is.
232 * \param status the status to check
234 static BOOL IsImportant(git_wc_status_kind status) {return (GetMoreImportant(git_wc_status_added, status)==status);}
237 * Reads the Subversion text status of the working copy entry. No
238 * recurse is done, even if the entry is a directory.
239 * The result is stored in the public member variable status.
240 * Use this method if you need detailed information about a file/folder, not just the raw status (like "normal", "modified").
242 * \param path the pathname of the entry
243 * \param update true if the status should be updated with the repository. Default is false.
244 * \return If update is set to true the HEAD revision of the repository is returned. If update is false then -1 is returned.
245 * \remark If the return value is -2 then the status could not be obtained.
247 git_revnum_t GetStatus(const CTGitPath& path, bool update = false, bool noignore = false, bool noexternals = false);
250 * Returns a string representation of a Subversion status.
251 * \param status the status enum
252 * \param string a string representation
254 static void GetStatusString(git_wc_status_kind status, size_t buflen, TCHAR * string);
255 static void GetStatusString(HINSTANCE hInst, git_wc_status_kind status, TCHAR * string, int size, WORD lang);
258 * Returns the string representation of a depth.
260 #ifdef _MFC_VER
261 static CString GetDepthString(git_depth_t depth);
262 #endif
263 static void GetDepthString(HINSTANCE hInst, git_depth_t depth, TCHAR * string, int size, WORD lang);
266 * Returns the status of the first file of the given path. Use GetNextFileStatus() to obtain
267 * the status of the next file in the list.
268 * \param path the path of the folder from where the status list should be obtained
269 * \param retPath the path of the file for which the status was returned
270 * \param update set this to true if you want the status to be updated with the repository (needs network access)
271 * \param recurse true to fetch the status recursively
272 * \param bNoIgnore true to not fetch the ignored files
273 * \param bNoExternals true to not fetch the status of included Git:externals
274 * \return the status
276 git_wc_status2_t * GetFirstFileStatus(const CTGitPath& path, CTGitPath& retPath, bool update = false, git_depth_t depth = git_depth_infinity, bool bNoIgnore = true, bool bNoExternals = false);
277 unsigned int GetFileCount() const {return /*apr_hash_count(m_statushash);*/0;}
278 unsigned int GetVersionedCount() const;
280 * Returns the status of the next file in the file list. If no more files are in the list then NULL is returned.
281 * See GetFirstFileStatus() for details.
283 git_wc_status2_t * GetNextFileStatus(CTGitPath& retPath);
285 * Checks if a path is an external folder.
286 * This is necessary since Subversion returns two entries for external folders: one with the status Git_wc_status_external
287 * and one with the 'real' status of that folder. GetFirstFileStatus() and GetNextFileStatus() only return the 'real'
288 * status, so with this method it's possible to check if the status also is Git_wc_status_external.
290 bool IsExternal(const CTGitPath& path) const;
292 * Checks if a path is in an external folder.
294 bool IsInExternal(const CTGitPath& path) const;
297 * Clears the memory pool.
299 void ClearPool();
302 * This member variable hold the status of the last call to GetStatus().
304 git_wc_status2_t * status; ///< the status result of GetStatus()
306 git_revnum_t headrev; ///< the head revision fetched with GetFirstStatus()
308 bool * m_pbCanceled;
309 #ifdef _MFC_VER
310 friend class Git; // So that Git can get to our m_err
312 * Returns the last error message as a CString object.
314 CString GetLastErrorMsg() const;
316 /**
317 * Set a list of paths which will be considered when calling GetFirstFileStatus.
318 * If a filter is set, then GetFirstFileStatus/GetNextFileStatus will only return items which are in the filter list
320 void SetFilter(const CTGitPathList& fileList);
321 void ClearFilter();
323 #else
325 * Returns the last error message as a CString object.
327 stdstring GetLastErrorMsg() const;
328 #endif
331 protected:
332 // apr_pool_t * m_pool; ///< the memory pool
333 private:
334 typedef struct sort_item
336 const void *key;
337 // apr_ssize_t klen;
338 void *value;
339 } sort_item;
341 typedef struct hashbaton_t
343 GitStatus* pThis;
344 // apr_hash_t * hash;
345 // apr_hash_t * exthash;
346 } hash_baton_t;
348 // git_client_ctx_t * ctx;
349 git_wc_status_kind m_allstatus; ///< used by GetAllStatus and GetAllStatusRecursive
350 // git_error_t * m_err; ///< Subversion error baton
351 git_error_t m_err;
353 git_wc_status2_t m_status; // used for GetStatus
355 #ifdef _MFC_VER
356 // GitPrompt m_prompt;
357 #endif
360 * Returns a numeric value indicating the importance of a status.
361 * A higher number indicates a more important status.
363 static int GetStatusRanking(git_wc_status_kind status);
366 * Callback function which collects the raw status from a Git_client_status() function call
368 //static git_error_t * getallstatus (void *baton, const char *path, git_wc_status2_t *status, apr_pool_t *pool);
369 static BOOL getallstatus(const struct wgFile_s *pFile, void *pUserData);
370 static BOOL getstatus(const struct wgFile_s *pFile, void *pUserData);
373 * Callback function which stores the raw status from a Git_client_status() function call
374 * in a hash table.
376 // static git_error_t * getstatushash (void *baton, const char *path, git_wc_status2_t *status, apr_pool_t *pool);
379 * helper function to sort a hash to an array
381 // static apr_array_header_t * sort_hash (apr_hash_t *ht, int (*comparison_func) (const sort_item *,
382 // const sort_item *), apr_pool_t *pool);
385 * Callback function used by qsort() which does the comparison of two elements
387 static int __cdecl sort_compare_items_as_paths (const sort_item *a, const sort_item *b);
389 //for GetFirstFileStatus and GetNextFileStatus
390 // apr_hash_t * m_statushash;
391 // apr_array_header_t * m_statusarray;
392 unsigned int m_statushashindex;
393 // apr_hash_t * m_externalhash;
395 #pragma warning(push)
396 #pragma warning(disable: 4200)
397 struct STRINGRESOURCEIMAGE
399 WORD nLength;
400 WCHAR achString[];
402 #pragma warning(pop) // C4200
404 static int LoadStringEx(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax, WORD wLanguage);
405 static git_error_t* cancel(void *baton);
407 // A sorted list of filenames (in Git format, in lowercase)
408 // when this list is set, we only pick-up files during a GetStatus which are found in this list
409 typedef std::vector<std::string> StdStrAVector;
410 StdStrAVector m_filterFileList;