Fix typos
[TortoiseGit.git] / src / Utils / Hooks.h
blob5cb636967f129f82552d5fc69e6b7ce1fed7b514
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2011-2019, 2021, 2023 - TortoiseGit
4 // Copyright (C) 2006-2008, 2015 - TortoiseSVN
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 #pragma once
21 #include "registry.h"
22 #include "TGitPath.h"
23 #include "ProjectProperties.h"
25 /**
26 * \ingroup TortoiseProc
27 * enumeration of all client hook types
29 enum class HookType
31 unknown_hook,
32 start_commit_hook,
33 pre_commit_hook,
34 post_commit_hook,
35 issue_tracker_hook,
36 pre_push_hook,
37 post_push_hook,
38 pre_rebase_hook,
41 /**
42 * \ingroup TortoiseProc
43 * helper class, used as the key to the std::map we store
44 * the data for the client hook scripts in.
46 class hookkey
48 public:
49 HookType htype = HookType::unknown_hook;
50 CTGitPath path;
51 bool local = false;
53 bool operator < (const hookkey& hk) const
55 if (htype == hk.htype)
57 if (local != hk.local)
58 return local < hk.local;
60 return (path < hk.path);
62 else
63 return htype < hk.htype;
67 /**
68 * \ingroup TortoiseProc
69 * helper struct, used as the value to the std::map we
70 * store the data for the client hook scripts in.
72 struct hookcmd
74 CString commandline;
75 bool bWait = true;
76 bool bShow = true;
77 bool bEnabled = false;
78 bool bLocal = false;
79 bool bApproved = false; ///< user explicitly approved
80 bool bStored = false; ///< use decision is stored in reg
81 CString sRegKey;
84 using hookiterator = std::map<hookkey, hookcmd>::iterator;
85 using const_hookiterator = std::map<hookkey, hookcmd>::const_iterator;
87 /**
88 * \ingroup TortoiseProc
89 * Singleton class which deals with the client hook scripts.
91 class CHooks : private std::map<hookkey, hookcmd>
93 private:
94 CHooks();
95 ~CHooks();
96 // prevent cloning
97 CHooks(const CHooks&) = delete;
98 CHooks& operator=(const CHooks&) = delete;
100 static void AddPathParam(CString& sCmd, const CTGitPathList& pathList);
101 static void AddCWDParam(CString& sCmd, const CString& workingTree);
102 static void AddErrorParam(CString& sCmd, const CString& error);
103 static void AddParam(CString& sCmd, const CString& param);
104 static CTGitPath AddMessageFileParam(CString& sCmd, const CString& message);
105 public:
106 /// Create the singleton. Call this at the start of the program.
107 static bool Create();
108 /// Returns the singleton instance
109 static CHooks& Instance();
110 /// Destroys the singleton object. Call this at the end of the program.
111 static void Destroy();
113 using std::map<hookkey, hookcmd>::begin;
114 using std::map<hookkey, hookcmd>::end;
115 using std::map<hookkey, hookcmd>::empty;
117 public:
118 /// Saves the hook script information to the registry.
119 bool Save();
121 * Removes the hook script identified by \c key. To make the change persistent
122 * call Save().
124 bool Remove(const hookkey &key);
126 * Adds a new hook script. To make the change persistent, call Save().
128 void Add(HookType ht, const CTGitPath& Path, LPCWSTR szCmd,
129 bool bWait, bool bShow, bool bEnabled, bool bLocal);
132 * Toggles the hook script identified by \c key. Returns whether the status has changed.
133 * To make the change persistent call Save().
135 bool SetEnabled(const hookkey& key, bool bEnabled);
137 /// returns the string representation of the hook type.
138 static CString GetHookTypeString(HookType t);
139 /// returns the hooktype from a string representation of the same.
140 static HookType GetHookType(const CString& s);
142 /// Add hook script data from project properties
143 void SetProjectProperties(const CTGitPath& Path, const ProjectProperties& pp);
146 * Executes the Start-Commit-Hook that first matches the path in
147 * \c workingTree.
148 * \param workingTree working tree root directory
149 * \param pathList a list of paths to look for the hook scripts
150 * \param message a commit message
151 * \param exitcode on return, contains the exit code of the hook script
152 * \param error the data the hook script outputs to stderr
153 * \remark the string "%PATHS% in the command line of the hook script is
154 * replaced with the path to a temporary file which contains a list of files
155 * in \c pathList, separated by newlines. The hook script can parse this
156 * file to get all the paths the commit is about to be done on.
157 * The string %MESSAGEFILE% is replaced with path to temporary file containing
158 * \c message. If the script finishes successfully, contents of this file
159 * is read back into \c message parameter.
161 bool StartCommit(HWND hWnd, const CString& workingTree, const CTGitPathList& pathList, CString& message,
162 DWORD& exitcode, CString& error);
164 * Executes the Pre-Commit-Hook that first matches the path in
165 * \c workingTree.
166 * \param workingTree working tree root directory
167 * \param pathList a list of paths to look for the hook scripts
168 * \param message the commit message
169 * \param exitcode on return, contains the exit code of the hook script
170 * \param error the data the hook script outputs to stderr
171 * \remark the string "%PATHS% in the command line of the hook script is
172 * replaced with the path to a temporary file which contains a list of files
173 * in \c pathList, separated by newlines. The hook script can parse this
174 * file to get all the paths the update is about to be done on.
175 * If the script finishes successfully, contents of this file is read back
176 * into \c message parameter.
178 bool PreCommit(HWND hWnd, const CString& workingTree, const CTGitPathList& pathList,
179 CString& message, DWORD& exitcode,
180 CString& error);
182 * Executes the Post-Commit-Hook that first matches the path in
183 * \c workingTree.
184 * \param workingTree working tree root directory
185 * \param amend commit was amend
187 bool PostCommit(HWND hWnd, const CString& workingTree, bool amend, DWORD& exitcode, CString& error);
189 bool PrePush(HWND hWnd, const CString& workingTree, DWORD& exitcode, CString& error);
190 bool PostPush(HWND hWnd, const CString& workingTree, DWORD& exitcode, CString& error);
192 bool PreRebase(HWND hWnd, const CString& workingTree, const CString& upstream, const CString& rebasedBranch, DWORD& exitcode, CString& error);
194 bool IsHookPresent(HookType t, const CString& workingTree);
196 private:
198 * Starts a new process, specified in \c cmd.
199 * \param error the data the process writes to stderr
200 * \param bWait if true, then this method waits until the created process has finished. If false, then the return
201 * value will always be 0 and \c error will be an empty string.
202 * \param bShow set to true if the process should be started visible.
203 * \return the exit code of the process if \c bWait is true, zero otherwise.
205 static DWORD RunScript(CString cmd, LPCWSTR currentDir, CString& error, bool bWait, bool bShow);
207 * Find the hook script information for the hook type \c t which matches the
208 * path in \c workingTree.
210 hookiterator FindItem(HookType t, const CString& workingTree);
212 static void ParseHookString(CString strhooks, bool bLocal);
215 * Checks whether the hook script has been validated already and
216 * if not, asks the user to validate it.
218 bool ApproveHook(HWND hWnd, hookiterator it, DWORD& exitcode);
220 static CHooks * m_pInstance;
221 static CTGitPath m_RootPath;