1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2011 - 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.
23 //# include "SVNPrompt.h"
29 #pragma warning (push,1)
30 typedef std::basic_string
<wchar_t> wide_string
;
32 # define stdstring wide_string
34 # define stdstring std::string
41 typedef enum type_git_wc_status_kind
44 git_wc_status_unversioned
,
45 git_wc_status_ignored
,
47 git_wc_status_external
,
48 git_wc_status_incomplete
,
49 git_wc_status_missing
,
50 git_wc_status_deleted
,
51 git_wc_status_replaced
,
52 git_wc_status_modified
,
55 git_wc_status_conflicted
,
56 git_wc_status_obstructed
,
57 git_wc_status_unknown
,
71 #define GIT_REV_ZERO _T("0000000000000000000000000000000000000000")
72 #define GIT_INVALID_REVNUM _T("")
73 typedef CString git_revnum_t
;
74 typedef int git_error_t
;
76 typedef struct git_wc_entry_t
85 typedef struct git_wc_status2_t
87 /** The status of the entries text. */
88 git_wc_status_kind text_status
;
90 /** The status of the entries properties. */
91 git_wc_status_kind prop_status
;
93 //git_wc_entry_t *entry;
96 #define MAX_STATUS_STRING_LENGTH 256
99 /////////////////////////////////////////////////////////////////////
100 // WINGIT API (replaced by commandline tool, but defs and data types kept so old code still works)
102 // Flags for wgEnumFiles
105 WGEFF_NoRecurse
= (1<<0), // only enumerate files directly in the specified path
106 WGEFF_FullPath
= (1<<1), // enumerated filenames are specified with full path (instead of relative to proj root)
107 WGEFF_DirStatusDelta
= (1<<2), // include directories, in enumeration, that have a recursive status != WGFS_Normal (may have a slightly better performance than WGEFF_DirStatusAll)
108 WGEFF_DirStatusAll
= (1<<3), // include directories, in enumeration, with recursive status
109 WGEFF_EmptyAsNormal
= (1<<4), // report sub-directories, with no versioned files, as WGFS_Normal instead of WGFS_Empty
110 WGEFF_SingleFile
= (1<<5) // indicates that the status of a single file or dir, specified by pszSubPath, is wanted
124 WGFS_Unversioned
= -2,
132 WGFF_Directory
= (1<<0) // enumerated file is a directory
137 LPCTSTR sFileName
; // filename or directory relative to project root (using forward slashes)
138 int nStatus
; // the WGFILESTATUS of the file
139 int nFlags
; // a combination of WGFILEFLAGS
141 const BYTE
* sha1
; // points to the BYTE[20] sha1 (NULL for directories, WGFF_Directory)
144 // Application-defined callback function for wgEnumFiles, returns TRUE to abort enumeration
145 // 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
146 typedef BOOL (__cdecl WGENUMFILECB
)(const struct wgFile_s
*pFile
, void *pUserData
);
149 /////////////////////////////////////////////////////////////////////
152 // convert wingit.dll status to git_wc_status_kind
153 inline static git_wc_status_kind
GitStatusFromWingit(int nStatus
)
157 case WGFS_Normal
: return git_wc_status_normal
;
158 case WGFS_Modified
: return git_wc_status_modified
;
159 case WGFS_Staged
: return git_wc_status_merged
;
160 case WGFS_Added
: return git_wc_status_added
;
161 case WGFS_Conflicted
: return git_wc_status_conflicted
;
162 case WGFS_Deleted
: return git_wc_status_deleted
;
164 case WGFS_Ignored
: return git_wc_status_ignored
;
165 case WGFS_Unversioned
: return git_wc_status_unversioned
;
166 case WGFS_Empty
: return git_wc_status_unversioned
;
169 return git_wc_status_none
;
172 // convert 20 byte sha1 hash to the git_revnum_t type
173 inline static git_revnum_t
ConvertHashToRevnum(const BYTE
*sha1
)
176 return GIT_INVALID_REVNUM
;
180 for (int i
=0; i
<20; i
++)
182 #pragma warning(push)
183 #pragma warning(disable: 4996)
184 sprintf(p
, "%02x", (UINT
)*sha1
);
193 typedef BOOL (*FIll_STATUS_CALLBACK
)(const CString
&path
,git_wc_status_kind status
,bool isDir
, void *pdata
);
197 * Handles Subversion status of working copies.
203 #define GIT_MODE_INDEX 0x1
204 #define GIT_MODE_HEAD 0x2
205 #define GIT_MODE_IGNORE 0x4
206 #define GIT_MODE_ALL (GIT_MODE_INDEX|GIT_MODE_HEAD|GIT_MODE_IGNORE)
208 static int GetFileStatus(const CString
&gitdir
,const CString
&path
,git_wc_status_kind
* status
,BOOL IsFull
=false, BOOL IsRecursive
=false, BOOL isIgnore
=true, FIll_STATUS_CALLBACK callback
=NULL
,void *pData
=NULL
);
209 static int GetDirStatus(const CString
&gitdir
,const CString
&path
,git_wc_status_kind
* status
,BOOL IsFull
=false, BOOL IsRecursive
=false, BOOL isIgnore
=true, FIll_STATUS_CALLBACK callback
=NULL
, void *pData
=NULL
);
210 static int EnumDirStatus(const CString
&gitdir
,const CString
&path
,git_wc_status_kind
* status
,BOOL IsFull
=false, BOOL IsRecursive
=false, BOOL isIgnore
=true, FIll_STATUS_CALLBACK callback
=NULL
, void *pData
=NULL
);
211 static int GetFileList(const CString
&gitdir
, const CString
&path
, std::vector
<CGitFileName
> &list
);
212 static bool IsGitReposChanged(const CString
&gitdir
, const CString
&subpaths
, int mode
=GIT_MODE_ALL
);
213 static int LoadIgnoreFile(const CString
&gitdir
, const CString
&subpaths
);
214 static int IsUnderVersionControl(const CString
&gitdir
, const CString
&path
, bool isDir
,bool *isVersion
);
215 static int IsIgnore(const CString
&gitdir
, const CString
&path
, bool *isIgnore
);
216 static __int64
GetIndexFileTime(const CString
&gitdir
);
217 static bool IsExistIndexLockFile(const CString
&gitdir
);
218 static int GetIgnoreFileChangeTimeList(const CString
&path
, std::vector
<__int64
> &timelist
);
220 static int GetHeadHash(const CString
&gitdir
, CGitHash
&hash
);
223 GitStatus(bool * pbCanceled
= NULL
);
228 * Reads the Subversion status of the working copy entry. No
229 * recurse is done, even if the entry is a directory.
230 * If the status of the text and property part are different
231 * then the more important status is returned.
233 static git_wc_status_kind
GetAllStatus(const CTGitPath
& path
, git_depth_t depth
= git_depth_empty
);
236 * Reads the Subversion status of the working copy entry and all its
237 * subitems. The resulting status is determined by using priorities for
238 * each status. The status with the highest priority is then returned.
239 * If the status of the text and property part are different then
240 * the more important status is returned.
242 static git_wc_status_kind
GetAllStatusRecursive(const CTGitPath
& path
);
245 * Returns the status which is more "important" of the two statuses specified.
246 * This is used for the "recursive" status functions on folders - i.e. which status
247 * should be returned for a folder which has several files with different statuses
250 static git_wc_status_kind
GetMoreImportant(git_wc_status_kind status1
, git_wc_status_kind status2
);
253 * Checks if a status is "important", i.e. if the status indicates that the user should know about it.
254 * E.g. a "normal" status is not important, but "modified" is.
255 * \param status the status to check
257 static BOOL
IsImportant(git_wc_status_kind status
) {return (GetMoreImportant(git_wc_status_added
, status
)==status
);}
260 * Reads the Subversion text status of the working copy entry. No
261 * recurse is done, even if the entry is a directory.
262 * The result is stored in the public member variable status.
263 * Use this method if you need detailed information about a file/folder, not just the raw status (like "normal", "modified").
265 * \param path the pathname of the entry
266 * \param update true if the status should be updated with the repository. Default is false.
267 * \return If update is set to true the HEAD revision of the repository is returned. If update is false then -1 is returned.
268 * \remark If the return value is -2 then the status could not be obtained.
270 git_revnum_t
GetStatus(const CTGitPath
& path
, bool update
= false, bool noignore
= false, bool noexternals
= false);
273 * Returns a string representation of a Subversion status.
274 * \param status the status enum
275 * \param string a string representation
277 static void GetStatusString(git_wc_status_kind status
, size_t buflen
, TCHAR
* string
);
278 static void GetStatusString(HINSTANCE hInst
, git_wc_status_kind status
, TCHAR
* string
, int size
, WORD lang
);
281 * Returns the string representation of a depth.
284 static CString
GetDepthString(git_depth_t depth
);
286 static void GetDepthString(HINSTANCE hInst
, git_depth_t depth
, TCHAR
* string
, int size
, WORD lang
);
289 * Returns the status of the first file of the given path. Use GetNextFileStatus() to obtain
290 * the status of the next file in the list.
291 * \param path the path of the folder from where the status list should be obtained
292 * \param retPath the path of the file for which the status was returned
293 * \param update set this to true if you want the status to be updated with the repository (needs network access)
294 * \param recurse true to fetch the status recursively
295 * \param bNoIgnore true to not fetch the ignored files
296 * \param bNoExternals true to not fetch the status of included Git:externals
299 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);
300 unsigned int GetFileCount() const {return /*apr_hash_count(m_statushash);*/0;}
301 unsigned int GetVersionedCount() const;
303 * Returns the status of the next file in the file list. If no more files are in the list then NULL is returned.
304 * See GetFirstFileStatus() for details.
306 git_wc_status2_t
* GetNextFileStatus(CTGitPath
& retPath
);
308 * Checks if a path is an external folder.
309 * This is necessary since Subversion returns two entries for external folders: one with the status Git_wc_status_external
310 * and one with the 'real' status of that folder. GetFirstFileStatus() and GetNextFileStatus() only return the 'real'
311 * status, so with this method it's possible to check if the status also is Git_wc_status_external.
313 bool IsExternal(const CTGitPath
& path
) const;
315 * Checks if a path is in an external folder.
317 bool IsInExternal(const CTGitPath
& path
) const;
320 * Clears the memory pool.
325 * This member variable hold the status of the last call to GetStatus().
327 git_wc_status2_t
* status
; ///< the status result of GetStatus()
329 git_revnum_t headrev
; ///< the head revision fetched with GetFirstStatus()
333 friend class Git
; // So that Git can get to our m_err
335 * Returns the last error message as a CString object.
337 CString
GetLastErrorMsg() const;
340 * Set a list of paths which will be considered when calling GetFirstFileStatus.
341 * If a filter is set, then GetFirstFileStatus/GetNextFileStatus will only return items which are in the filter list
343 void SetFilter(const CTGitPathList
& fileList
);
348 * Returns the last error message as a CString object.
350 stdstring
GetLastErrorMsg() const;
355 // apr_pool_t * m_pool; ///< the memory pool
357 typedef struct sort_item
364 typedef struct hashbaton_t
367 // apr_hash_t * hash;
368 // apr_hash_t * exthash;
371 // git_client_ctx_t * ctx;
372 git_wc_status_kind m_allstatus
; ///< used by GetAllStatus and GetAllStatusRecursive
373 // git_error_t * m_err; ///< Subversion error baton
376 git_wc_status2_t m_status
; // used for GetStatus
379 // GitPrompt m_prompt;
383 * Returns a numeric value indicating the importance of a status.
384 * A higher number indicates a more important status.
386 static int GetStatusRanking(git_wc_status_kind status
);
389 * Callback function which collects the raw status from a Git_client_status() function call
391 //static git_error_t * getallstatus (void *baton, const char *path, git_wc_status2_t *status, apr_pool_t *pool);
392 static BOOL
getallstatus(const struct wgFile_s
*pFile
, void *pUserData
);
393 static BOOL
getstatus(const struct wgFile_s
*pFile
, void *pUserData
);
396 * Callback function which stores the raw status from a Git_client_status() function call
399 // static git_error_t * getstatushash (void *baton, const char *path, git_wc_status2_t *status, apr_pool_t *pool);
402 * helper function to sort a hash to an array
404 // static apr_array_header_t * sort_hash (apr_hash_t *ht, int (*comparison_func) (const sort_item *,
405 // const sort_item *), apr_pool_t *pool);
408 * Callback function used by qsort() which does the comparison of two elements
410 static int __cdecl
sort_compare_items_as_paths (const sort_item
*a
, const sort_item
*b
);
412 //for GetFirstFileStatus and GetNextFileStatus
413 // apr_hash_t * m_statushash;
414 // apr_array_header_t * m_statusarray;
415 unsigned int m_statushashindex
;
416 // apr_hash_t * m_externalhash;
418 #pragma warning(push)
419 #pragma warning(disable: 4200)
420 struct STRINGRESOURCEIMAGE
425 #pragma warning(pop) // C4200
427 static int LoadStringEx(HINSTANCE hInstance
, UINT uID
, LPTSTR lpBuffer
, int nBufferMax
, WORD wLanguage
);
428 static git_error_t
* cancel(void *baton
);
430 // A sorted list of filenames (in Git format, in lowercase)
431 // when this list is set, we only pick-up files during a GetStatus which are found in this list
432 typedef std::vector
<std::string
> StdStrAVector
;
433 StdStrAVector m_filterFileList
;