1 /*
2  * Copyright (C) the libgit2 contributors. All rights reserved.
3  *
4  * This file is part of libgit2, distributed under the GNU GPL v2 with
5  * a Linking Exception. For full terms see the included COPYING file.
6  */
7 module libgit2_d.checkout;
8 
9 
10 private static import libgit2_d.diff;
11 private static import libgit2_d.strarray;
12 private static import libgit2_d.types;
13 
14 /**
15  * @file git2/checkout.h
16  * @brief Git checkout routines
17  * @defgroup git_checkout Git checkout routines
18  * @ingroup Git
19  * @{
20  */
21 extern (C):
22 nothrow @nogc:
23 public:
24 
25 /**
26  * Checkout behavior flags
27  *
28  * In libgit2, checkout is used to update the working directory and index
29  * to match a target tree.  Unlike git checkout, it does not move the HEAD
30  * commit for you - use `git_repository_set_head` or the like to do that.
31  *
32  * Checkout looks at (up to) four things: the "target" tree you want to
33  * check out, the "baseline" tree of what was checked out previously, the
34  * working directory for actual files, and the index for staged changes.
35  *
36  * You give checkout one of three strategies for update:
37  *
38  * - `GIT_CHECKOUT_NONE` is a dry-run strategy that checks for conflicts,
39  *   etc., but doesn't make any actual changes.
40  *
41  * - `GIT_CHECKOUT_FORCE` is at the opposite extreme, taking any action to
42  *   make the working directory match the target (including potentially
43  *   discarding modified files).
44  *
45  * - `GIT_CHECKOUT_SAFE` is between these two options, it will only make
46  *   modifications that will not lose changes.
47  *
48  *                         |  target == baseline   |  target != baseline  |
49  *    ---------------------|-----------------------|----------------------|
50  *     workdir == baseline |       no action       |  create, update, or  |
51  *                         |                       |     delete file      |
52  *    ---------------------|-----------------------|----------------------|
53  *     workdir exists and  |       no action       |   conflict (notify   |
54  *       is != baseline    | notify dirty MODIFIED | and cancel checkout) |
55  *    ---------------------|-----------------------|----------------------|
56  *      workdir missing,   | notify dirty DELETED  |     create file      |
57  *      baseline present   |                       |                      |
58  *    ---------------------|-----------------------|----------------------|
59  *
60  * To emulate `git checkout`, use `GIT_CHECKOUT_SAFE` with a checkout
61  * notification callback (see below) that displays information about dirty
62  * files.  The default behavior will cancel checkout on conflicts.
63  *
64  * To emulate `git checkout-index`, use `GIT_CHECKOUT_SAFE` with a
65  * notification callback that cancels the operation if a dirty-but-existing
66  * file is found in the working directory.  This core git command isn't
67  * quite "force" but is sensitive about some types of changes.
68  *
69  * To emulate `git checkout -f`, use `GIT_CHECKOUT_FORCE`.
70  *
71  *
72  * There are some additional flags to modify the behavior of checkout:
73  *
74  * - GIT_CHECKOUT_ALLOW_CONFLICTS makes SAFE mode apply safe file updates
75  *   even if there are conflicts (instead of cancelling the checkout).
76  *
77  * - GIT_CHECKOUT_REMOVE_UNTRACKED means remove untracked files (i.e. not
78  *   in target, baseline, or index, and not ignored) from the working dir.
79  *
80  * - GIT_CHECKOUT_REMOVE_IGNORED means remove ignored files (that are also
81  *   untracked) from the working directory as well.
82  *
83  * - GIT_CHECKOUT_UPDATE_ONLY means to only update the content of files that
84  *   already exist.  Files will not be created nor deleted.  This just skips
85  *   applying adds, deletes, and typechanges.
86  *
87  * - GIT_CHECKOUT_DONT_UPDATE_INDEX prevents checkout from writing the
88  *   updated files' information to the index.
89  *
90  * - Normally, checkout will reload the index and git attributes from disk
91  *   before any operations.  GIT_CHECKOUT_NO_REFRESH prevents this reload.
92  *
93  * - Unmerged index entries are conflicts.  GIT_CHECKOUT_SKIP_UNMERGED skips
94  *   files with unmerged index entries instead.  GIT_CHECKOUT_USE_OURS and
95  *   GIT_CHECKOUT_USE_THEIRS to proceed with the checkout using either the
96  *   stage 2 ("ours") or stage 3 ("theirs") version of files in the index.
97  *
98  * - GIT_CHECKOUT_DONT_OVERWRITE_IGNORED prevents ignored files from being
99  *   overwritten.  Normally, files that are ignored in the working directory
100  *   are not considered "precious" and may be overwritten if the checkout
101  *   target contains that file.
102  *
103  * - GIT_CHECKOUT_DONT_REMOVE_EXISTING prevents checkout from removing
104  *   files or folders that fold to the same name on case insensitive
105  *   filesystems.  This can cause files to retain their existing names
106  *   and write through existing symbolic links.
107  */
108 enum git_checkout_strategy_t
109 {
110 	/**
111 	 * default is a dry run, no actual updates
112 	 */
113 	GIT_CHECKOUT_NONE = 0,
114 
115 	/**
116 	 * Allow safe updates that cannot overwrite uncommitted data.
117 	 * If the uncommitted changes don't conflict with the checked out files,
118 	 * the checkout will still proceed, leaving the changes intact.
119 	 *
120 	 * Mutually exclusive with GIT_CHECKOUT_FORCE.
121 	 * GIT_CHECKOUT_FORCE takes precedence over GIT_CHECKOUT_SAFE.
122 	 */
123 	GIT_CHECKOUT_SAFE = 1u << 0,
124 
125 	/**
126 	 * Allow all updates to force working directory to look like index.
127 	 *
128 	 * Mutually exclusive with GIT_CHECKOUT_SAFE.
129 	 * GIT_CHECKOUT_FORCE takes precedence over GIT_CHECKOUT_SAFE.
130 	 */
131 	GIT_CHECKOUT_FORCE = 1u << 1,
132 
133 	/**
134 	 * Allow checkout to recreate missing files
135 	 */
136 	GIT_CHECKOUT_RECREATE_MISSING = 1u << 2,
137 
138 	/**
139 	 * Allow checkout to make safe updates even if conflicts are found
140 	 */
141 	GIT_CHECKOUT_ALLOW_CONFLICTS = 1u << 4,
142 
143 	/**
144 	 * Remove untracked files not in index (that are not ignored)
145 	 */
146 	GIT_CHECKOUT_REMOVE_UNTRACKED = 1u << 5,
147 
148 	/**
149 	 * Remove ignored files not in index
150 	 */
151 	GIT_CHECKOUT_REMOVE_IGNORED = 1u << 6,
152 
153 	/**
154 	 * Only update existing files, don't create new ones
155 	 */
156 	GIT_CHECKOUT_UPDATE_ONLY = 1u << 7,
157 
158 	/**
159 	 * Normally checkout updates index entries as it goes; this stops that.
160 	 * Implies `GIT_CHECKOUT_DONT_WRITE_INDEX`.
161 	 */
162 	GIT_CHECKOUT_DONT_UPDATE_INDEX = 1u << 8,
163 
164 	/**
165 	 * Don't refresh index/config/etc before doing checkout
166 	 */
167 	GIT_CHECKOUT_NO_REFRESH = 1u << 9,
168 
169 	/**
170 	 * Allow checkout to skip unmerged files
171 	 */
172 	GIT_CHECKOUT_SKIP_UNMERGED = 1u << 10,
173 
174 	/**
175 	 * For unmerged files, checkout stage 2 from index
176 	 */
177 	GIT_CHECKOUT_USE_OURS = 1u << 11,
178 
179 	/**
180 	 * For unmerged files, checkout stage 3 from index
181 	 */
182 	GIT_CHECKOUT_USE_THEIRS = 1u << 12,
183 
184 	/**
185 	 * Treat pathspec as simple list of exact match file paths
186 	 */
187 	GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = 1u << 13,
188 
189 	/**
190 	 * Ignore directories in use, they will be left empty
191 	 */
192 	GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = 1u << 18,
193 
194 	/**
195 	 * Don't overwrite ignored files that exist in the checkout target
196 	 */
197 	GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = 1u << 19,
198 
199 	/**
200 	 * Write normal merge files for conflicts
201 	 */
202 	GIT_CHECKOUT_CONFLICT_STYLE_MERGE = 1u << 20,
203 
204 	/**
205 	 * Include common ancestor data in diff3 format files for conflicts
206 	 */
207 	GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = 1u << 21,
208 
209 	/**
210 	 * Don't overwrite existing files or folders
211 	 */
212 	GIT_CHECKOUT_DONT_REMOVE_EXISTING = 1u << 22,
213 
214 	/**
215 	 * Normally checkout writes the index upon completion; this prevents that.
216 	 */
217 	GIT_CHECKOUT_DONT_WRITE_INDEX = 1u << 23,
218 
219 	/**
220 	 * THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
221 	 */
222 
223 	/**
224 	 * Recursively checkout submodules with same options (NOT IMPLEMENTED)
225 	 */
226 	GIT_CHECKOUT_UPDATE_SUBMODULES = 1u << 16,
227 
228 	/**
229 	 * Recursively checkout submodules if HEAD moved in super repo (NOT
230 	 * IMPLEMENTED)
231 	 */
232 	GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = 1u << 17,
233 }
234 
235 /**
236  * Checkout notification flags
237  *
238  * Checkout will invoke an options notification callback (`notify_cb`) for
239  * certain cases - you pick which ones via `notify_flags`:
240  *
241  * - GIT_CHECKOUT_NOTIFY_CONFLICT invokes checkout on conflicting paths.
242  *
243  * - GIT_CHECKOUT_NOTIFY_DIRTY notifies about "dirty" files, i.e. those that
244  *   do not need an update but no longer match the baseline.  Core git
245  *   displays these files when checkout runs, but won't stop the checkout.
246  *
247  * - GIT_CHECKOUT_NOTIFY_UPDATED sends notification for any file changed.
248  *
249  * - GIT_CHECKOUT_NOTIFY_UNTRACKED notifies about untracked files.
250  *
251  * - GIT_CHECKOUT_NOTIFY_IGNORED notifies about ignored files.
252  *
253  * Returning a non-zero value from this callback will cancel the checkout.
254  * The non-zero return value will be propagated back and returned by the
255  * git_checkout_... call.
256  *
257  * Notification callbacks are made prior to modifying any files on disk,
258  * so canceling on any notification will still happen prior to any files
259  * being modified.
260  */
261 enum git_checkout_notify_t
262 {
263 	GIT_CHECKOUT_NOTIFY_NONE = 0,
264 	GIT_CHECKOUT_NOTIFY_CONFLICT = 1u << 0,
265 	GIT_CHECKOUT_NOTIFY_DIRTY = 1u << 1,
266 	GIT_CHECKOUT_NOTIFY_UPDATED = 1u << 2,
267 	GIT_CHECKOUT_NOTIFY_UNTRACKED = 1u << 3,
268 	GIT_CHECKOUT_NOTIFY_IGNORED = 1u << 4,
269 
270 	GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu,
271 }
272 
273 /**
274  * Checkout performance-reporting structure
275  */
276 struct git_checkout_perfdata
277 {
278 	size_t mkdir_calls;
279 	size_t stat_calls;
280 	size_t chmod_calls;
281 }
282 
283 /**
284  * Checkout notification callback function
285  */
286 alias git_checkout_notify_cb = int function(.git_checkout_notify_t why, const (char)* path, const (libgit2_d.diff.git_diff_file)* baseline, const (libgit2_d.diff.git_diff_file)* target, const (libgit2_d.diff.git_diff_file)* workdir, void* payload);
287 
288 /**
289  * Checkout progress notification function
290  */
291 alias git_checkout_progress_cb = void function(const (char)* path, size_t completed_steps, size_t total_steps, void* payload);
292 
293 /**
294  * Checkout perfdata notification function
295  */
296 alias git_checkout_perfdata_cb = void function(const (.git_checkout_perfdata)* perfdata, void* payload);
297 
298 /**
299  * Checkout options structure
300  *
301  * Initialize with `GIT_CHECKOUT_OPTIONS_INIT`. Alternatively, you can
302  * use `git_checkout_options_init`.
303  */
304 struct git_checkout_options
305 {
306 	/**
307 	 * The version
308 	 */
309 	uint version_;
310 
311 	/**
312 	 * default will be a safe checkout
313 	 */
314 	uint checkout_strategy;
315 
316 	/**
317 	 * don't apply filters like CRLF conversion
318 	 */
319 	int disable_filters;
320 
321 	/**
322 	 * default is 0755
323 	 */
324 	uint dir_mode;
325 
326 	/**
327 	 * default is 0644 or 0755 as dictated by blob
328 	 */
329 	uint file_mode;
330 
331 	/**
332 	 * default is O_CREAT | O_TRUNC | O_WRONLY
333 	 */
334 	int file_open_flags;
335 
336 	/**
337 	 * see `git_checkout_notify_t` above
338 	 */
339 	uint notify_flags;
340 
341 	/**
342 	 * Optional callback to get notifications on specific file states.
343 	 * @see git_checkout_notify_t
344 	 */
345 	.git_checkout_notify_cb notify_cb;
346 
347 	/**
348 	 * Payload passed to notify_cb
349 	 */
350 	void* notify_payload;
351 
352 	/**
353 	 * Optional callback to notify the consumer of checkout progress.
354 	 */
355 	.git_checkout_progress_cb progress_cb;
356 
357 	/**
358 	 * Payload passed to progress_cb
359 	 */
360 	void* progress_payload;
361 
362 	/**
363 	 * A list of wildmatch patterns or paths.
364 	 *
365 	 * By default, all paths are processed. If you pass an array of wildmatch
366 	 * patterns, those will be used to filter which paths should be taken into
367 	 * account.
368 	 *
369 	 * Use git_checkout_strategy_t.GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH to treat as a simple list.
370 	 */
371 	libgit2_d.strarray.git_strarray paths;
372 
373 	/**
374 	 * The expected content of the working directory; defaults to HEAD.
375 	 *
376 	 * If the working directory does not match this baseline information,
377 	 * that will produce a checkout conflict.
378 	 */
379 	libgit2_d.types.git_tree* baseline;
380 
381 	/**
382 	 * Like `baseline` above, though expressed as an index.  This
383 	 * option overrides `baseline`.
384 	 */
385 	libgit2_d.types.git_index* baseline_index; 
386 
387 	/**
388 	 * alternative checkout path to workdir
389 	 */
390 	const (char)* target_directory;
391 
392 	/**
393 	 * the name of the common ancestor side of conflicts
394 	 */
395 	const (char)* ancestor_label;
396 
397 	/**
398 	 * the name of the "our" side of conflicts
399 	 */
400 	const (char)* our_label;
401 
402 	/**
403 	 * the name of the "their" side of conflicts
404 	 */
405 	const (char)* their_label;
406 
407 	/**
408 	 * Optional callback to notify the consumer of performance data.
409 	 */
410 	.git_checkout_perfdata_cb perfdata_cb;
411 
412 	/**
413 	 * Payload passed to perfdata_cb
414 	 */
415 	void* perfdata_payload;
416 }
417 
418 enum GIT_CHECKOUT_OPTIONS_VERSION = 1;
419 
420 pragma(inline, true)
421 pure nothrow @safe @nogc
422 .git_checkout_options GIT_CHECKOUT_OPTIONS_INIT()
423 
424 	do
425 	{
426 		.git_checkout_options OUTPUT =
427 		{
428 			version_: .GIT_CHECKOUT_OPTIONS_VERSION,
429 			checkout_strategy: .git_checkout_strategy_t.GIT_CHECKOUT_SAFE,
430 		};
431 
432 		return OUTPUT;
433 	}
434 
435 /**
436  * Initialize git_checkout_options structure
437  *
438  * Initializes a `git_checkout_options` with default values. Equivalent to creating
439  * an instance with GIT_CHECKOUT_OPTIONS_INIT.
440  *
441  * @param opts The `git_checkout_options` struct to initialize.
442  * @param version The struct version; pass `GIT_CHECKOUT_OPTIONS_VERSION`.
443  * @return Zero on success; -1 on failure.
444  */
445 //GIT_EXTERN
446 int git_checkout_options_init(.git_checkout_options* opts, uint version_);
447 
448 /**
449  * Updates files in the index and the working tree to match the content of
450  * the commit pointed at by HEAD.
451  *
452  * Note that this is _not_ the correct mechanism used to switch branches;
453  * do not change your `HEAD` and then call this method, that would leave
454  * you with checkout conflicts since your working directory would then
455  * appear to be dirty.  Instead, checkout the target of the branch and
456  * then update `HEAD` using `git_repository_set_head` to point to the
457  * branch you checked out.
458  *
459  * @param repo repository to check out (must be non-bare)
460  * @param opts specifies checkout options (may be null)
461  * @return 0 on success, git_error_code.GIT_EUNBORNBRANCH if HEAD points to a non
462  *         existing branch, non-zero value returned by `notify_cb`, or
463  *         other error code < 0 (use git_error_last for error details)
464  */
465 //GIT_EXTERN
466 int git_checkout_head(libgit2_d.types.git_repository* repo, const (.git_checkout_options)* opts);
467 
468 /**
469  * Updates files in the working tree to match the content of the index.
470  *
471  * @param repo repository into which to check out (must be non-bare)
472  * @param index index to be checked out (or null to use repository index)
473  * @param opts specifies checkout options (may be null)
474  * @return 0 on success, non-zero return value from `notify_cb`, or error
475  *         code < 0 (use git_error_last for error details)
476  */
477 //GIT_EXTERN
478 int git_checkout_index(libgit2_d.types.git_repository* repo, libgit2_d.types.git_index* index, const (.git_checkout_options)* opts);
479 
480 /**
481  * Updates files in the index and working tree to match the content of the
482  * tree pointed at by the treeish.
483  *
484  * @param repo repository to check out (must be non-bare)
485  * @param treeish a commit, tag or tree which content will be used to update
486  * the working directory (or null to use HEAD)
487  * @param opts specifies checkout options (may be null)
488  * @return 0 on success, non-zero return value from `notify_cb`, or error
489  *         code < 0 (use git_error_last for error details)
490  */
491 //GIT_EXTERN
492 int git_checkout_tree(libgit2_d.types.git_repository* repo, const (libgit2_d.types.git_object)* treeish, const (.git_checkout_options)* opts);
493 
494 /** @} */