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 //Declaration name in C language
236 enum
237 {
238 	GIT_CHECKOUT_NONE = .git_checkout_strategy_t.GIT_CHECKOUT_NONE,
239 	GIT_CHECKOUT_SAFE = .git_checkout_strategy_t.GIT_CHECKOUT_SAFE,
240 	GIT_CHECKOUT_FORCE = .git_checkout_strategy_t.GIT_CHECKOUT_FORCE,
241 	GIT_CHECKOUT_RECREATE_MISSING = .git_checkout_strategy_t.GIT_CHECKOUT_RECREATE_MISSING,
242 	GIT_CHECKOUT_ALLOW_CONFLICTS = .git_checkout_strategy_t.GIT_CHECKOUT_ALLOW_CONFLICTS,
243 	GIT_CHECKOUT_REMOVE_UNTRACKED = .git_checkout_strategy_t.GIT_CHECKOUT_REMOVE_UNTRACKED,
244 	GIT_CHECKOUT_REMOVE_IGNORED = .git_checkout_strategy_t.GIT_CHECKOUT_REMOVE_IGNORED,
245 	GIT_CHECKOUT_UPDATE_ONLY = .git_checkout_strategy_t.GIT_CHECKOUT_UPDATE_ONLY,
246 	GIT_CHECKOUT_DONT_UPDATE_INDEX = .git_checkout_strategy_t.GIT_CHECKOUT_DONT_UPDATE_INDEX,
247 	GIT_CHECKOUT_NO_REFRESH = .git_checkout_strategy_t.GIT_CHECKOUT_NO_REFRESH,
248 	GIT_CHECKOUT_SKIP_UNMERGED = .git_checkout_strategy_t.GIT_CHECKOUT_SKIP_UNMERGED,
249 	GIT_CHECKOUT_USE_OURS = .git_checkout_strategy_t.GIT_CHECKOUT_USE_OURS,
250 	GIT_CHECKOUT_USE_THEIRS = .git_checkout_strategy_t.GIT_CHECKOUT_USE_THEIRS,
251 	GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = .git_checkout_strategy_t.GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH,
252 	GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = .git_checkout_strategy_t.GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES,
253 	GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = .git_checkout_strategy_t.GIT_CHECKOUT_DONT_OVERWRITE_IGNORED,
254 	GIT_CHECKOUT_CONFLICT_STYLE_MERGE = .git_checkout_strategy_t.GIT_CHECKOUT_CONFLICT_STYLE_MERGE,
255 	GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = .git_checkout_strategy_t.GIT_CHECKOUT_CONFLICT_STYLE_DIFF3,
256 	GIT_CHECKOUT_DONT_REMOVE_EXISTING = .git_checkout_strategy_t.GIT_CHECKOUT_DONT_REMOVE_EXISTING,
257 	GIT_CHECKOUT_DONT_WRITE_INDEX = .git_checkout_strategy_t.GIT_CHECKOUT_DONT_WRITE_INDEX,
258 	GIT_CHECKOUT_UPDATE_SUBMODULES = .git_checkout_strategy_t.GIT_CHECKOUT_UPDATE_SUBMODULES,
259 	GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = .git_checkout_strategy_t.GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED,
260 }
261 
262 /**
263  * Checkout notification flags
264  *
265  * Checkout will invoke an options notification callback (`notify_cb`) for
266  * certain cases - you pick which ones via `notify_flags`:
267  *
268  * - GIT_CHECKOUT_NOTIFY_CONFLICT invokes checkout on conflicting paths.
269  *
270  * - GIT_CHECKOUT_NOTIFY_DIRTY notifies about "dirty" files, i.e. those that
271  *   do not need an update but no longer match the baseline.  Core git
272  *   displays these files when checkout runs, but won't stop the checkout.
273  *
274  * - GIT_CHECKOUT_NOTIFY_UPDATED sends notification for any file changed.
275  *
276  * - GIT_CHECKOUT_NOTIFY_UNTRACKED notifies about untracked files.
277  *
278  * - GIT_CHECKOUT_NOTIFY_IGNORED notifies about ignored files.
279  *
280  * Returning a non-zero value from this callback will cancel the checkout.
281  * The non-zero return value will be propagated back and returned by the
282  * git_checkout_... call.
283  *
284  * Notification callbacks are made prior to modifying any files on disk,
285  * so canceling on any notification will still happen prior to any files
286  * being modified.
287  */
288 enum git_checkout_notify_t
289 {
290 	GIT_CHECKOUT_NOTIFY_NONE = 0,
291 	GIT_CHECKOUT_NOTIFY_CONFLICT = 1u << 0,
292 	GIT_CHECKOUT_NOTIFY_DIRTY = 1u << 1,
293 	GIT_CHECKOUT_NOTIFY_UPDATED = 1u << 2,
294 	GIT_CHECKOUT_NOTIFY_UNTRACKED = 1u << 3,
295 	GIT_CHECKOUT_NOTIFY_IGNORED = 1u << 4,
296 
297 	GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu,
298 }
299 
300 //Declaration name in C language
301 enum
302 {
303 	GIT_CHECKOUT_NOTIFY_NONE = .git_checkout_notify_t.GIT_CHECKOUT_NOTIFY_NONE,
304 	GIT_CHECKOUT_NOTIFY_CONFLICT = .git_checkout_notify_t.GIT_CHECKOUT_NOTIFY_CONFLICT,
305 	GIT_CHECKOUT_NOTIFY_DIRTY = .git_checkout_notify_t.GIT_CHECKOUT_NOTIFY_DIRTY,
306 	GIT_CHECKOUT_NOTIFY_UPDATED = .git_checkout_notify_t.GIT_CHECKOUT_NOTIFY_UPDATED,
307 	GIT_CHECKOUT_NOTIFY_UNTRACKED = .git_checkout_notify_t.GIT_CHECKOUT_NOTIFY_UNTRACKED,
308 	GIT_CHECKOUT_NOTIFY_IGNORED = .git_checkout_notify_t.GIT_CHECKOUT_NOTIFY_IGNORED,
309 
310 	GIT_CHECKOUT_NOTIFY_ALL = .git_checkout_notify_t.GIT_CHECKOUT_NOTIFY_ALL,
311 }
312 
313 /**
314  * Checkout performance-reporting structure
315  */
316 struct git_checkout_perfdata
317 {
318 	size_t mkdir_calls;
319 	size_t stat_calls;
320 	size_t chmod_calls;
321 }
322 
323 /**
324  * Checkout notification callback function
325  */
326 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);
327 
328 /**
329  * Checkout progress notification function
330  */
331 alias git_checkout_progress_cb = void function(const (char)* path, size_t completed_steps, size_t total_steps, void* payload);
332 
333 /**
334  * Checkout perfdata notification function
335  */
336 alias git_checkout_perfdata_cb = void function(const (.git_checkout_perfdata)* perfdata, void* payload);
337 
338 /**
339  * Checkout options structure
340  *
341  * Initialize with `GIT_CHECKOUT_OPTIONS_INIT`. Alternatively, you can
342  * use `git_checkout_options_init`.
343  */
344 struct git_checkout_options
345 {
346 	/**
347 	 * The version
348 	 */
349 	uint version_;
350 
351 	/**
352 	 * default will be a safe checkout
353 	 */
354 	uint checkout_strategy;
355 
356 	/**
357 	 * don't apply filters like CRLF conversion
358 	 */
359 	int disable_filters;
360 
361 	/**
362 	 * default is 0755
363 	 */
364 	uint dir_mode;
365 
366 	/**
367 	 * default is 0644 or 0755 as dictated by blob
368 	 */
369 	uint file_mode;
370 
371 	/**
372 	 * default is O_CREAT | O_TRUNC | O_WRONLY
373 	 */
374 	int file_open_flags;
375 
376 	/**
377 	 * see `git_checkout_notify_t` above
378 	 */
379 	uint notify_flags;
380 
381 	/**
382 	 * Optional callback to get notifications on specific file states.
383 	 * @see git_checkout_notify_t
384 	 */
385 	.git_checkout_notify_cb notify_cb;
386 
387 	/**
388 	 * Payload passed to notify_cb
389 	 */
390 	void* notify_payload;
391 
392 	/**
393 	 * Optional callback to notify the consumer of checkout progress.
394 	 */
395 	.git_checkout_progress_cb progress_cb;
396 
397 	/**
398 	 * Payload passed to progress_cb
399 	 */
400 	void* progress_payload;
401 
402 	/**
403 	 * A list of wildmatch patterns or paths.
404 	 *
405 	 * By default, all paths are processed. If you pass an array of wildmatch
406 	 * patterns, those will be used to filter which paths should be taken into
407 	 * account.
408 	 *
409 	 * Use git_checkout_strategy_t.GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH to treat as a simple list.
410 	 */
411 	libgit2_d.strarray.git_strarray paths;
412 
413 	/**
414 	 * The expected content of the working directory; defaults to HEAD.
415 	 *
416 	 * If the working directory does not match this baseline information,
417 	 * that will produce a checkout conflict.
418 	 */
419 	libgit2_d.types.git_tree* baseline;
420 
421 	/**
422 	 * Like `baseline` above, though expressed as an index.  This
423 	 * option overrides `baseline`.
424 	 */
425 	libgit2_d.types.git_index* baseline_index; 
426 
427 	/**
428 	 * alternative checkout path to workdir
429 	 */
430 	const (char)* target_directory;
431 
432 	/**
433 	 * the name of the common ancestor side of conflicts
434 	 */
435 	const (char)* ancestor_label;
436 
437 	/**
438 	 * the name of the "our" side of conflicts
439 	 */
440 	const (char)* our_label;
441 
442 	/**
443 	 * the name of the "their" side of conflicts
444 	 */
445 	const (char)* their_label;
446 
447 	/**
448 	 * Optional callback to notify the consumer of performance data.
449 	 */
450 	.git_checkout_perfdata_cb perfdata_cb;
451 
452 	/**
453 	 * Payload passed to perfdata_cb
454 	 */
455 	void* perfdata_payload;
456 }
457 
458 enum GIT_CHECKOUT_OPTIONS_VERSION = 1;
459 
460 pragma(inline, true)
461 pure nothrow @safe @nogc
462 .git_checkout_options GIT_CHECKOUT_OPTIONS_INIT()
463 
464 	do
465 	{
466 		.git_checkout_options OUTPUT =
467 		{
468 			version_: .GIT_CHECKOUT_OPTIONS_VERSION,
469 			checkout_strategy: .git_checkout_strategy_t.GIT_CHECKOUT_SAFE,
470 		};
471 
472 		return OUTPUT;
473 	}
474 
475 /**
476  * Initialize git_checkout_options structure
477  *
478  * Initializes a `git_checkout_options` with default values. Equivalent to creating
479  * an instance with GIT_CHECKOUT_OPTIONS_INIT.
480  *
481  * Params:
482  *      opts = The `git_checkout_options` struct to initialize.
483  *      version = The struct version; pass `GIT_CHECKOUT_OPTIONS_VERSION`.
484  *
485  * Returns: Zero on success; -1 on failure.
486  */
487 //GIT_EXTERN
488 int git_checkout_options_init(.git_checkout_options* opts, uint version_);
489 
490 /**
491  * Updates files in the index and the working tree to match the content of
492  * the commit pointed at by HEAD.
493  *
494  * Note that this is _not_ the correct mechanism used to switch branches;
495  * do not change your `HEAD` and then call this method, that would leave
496  * you with checkout conflicts since your working directory would then
497  * appear to be dirty.  Instead, checkout the target of the branch and
498  * then update `HEAD` using `git_repository_set_head` to point to the
499  * branch you checked out.
500  *
501  * Params:
502  *      repo = repository to check out (must be non-bare)
503  *      opts = specifies checkout options (may be null)
504  *
505  * Returns: 0 on success, git_error_code.GIT_EUNBORNBRANCH if HEAD points to a non existing branch, non-zero value returned by `notify_cb`, or other error code < 0 (use git_error_last for error details)
506  */
507 //GIT_EXTERN
508 int git_checkout_head(libgit2_d.types.git_repository* repo, const (.git_checkout_options)* opts);
509 
510 /**
511  * Updates files in the working tree to match the content of the index.
512  *
513  * Params:
514  *      repo = repository into which to check out (must be non-bare)
515  *      index = index to be checked out (or null to use repository index)
516  *      opts = specifies checkout options (may be null)
517  *
518  * Returns: 0 on success, non-zero return value from `notify_cb`, or error code < 0 (use git_error_last for error details)
519  */
520 //GIT_EXTERN
521 int git_checkout_index(libgit2_d.types.git_repository* repo, libgit2_d.types.git_index* index, const (.git_checkout_options)* opts);
522 
523 /**
524  * Updates files in the index and working tree to match the content of the
525  * tree pointed at by the treeish.
526  *
527  * Params:
528  *      repo = repository to check out (must be non-bare)
529  *      treeish = a commit, tag or tree which content will be used to update the working directory (or null to use HEAD)
530  *      opts = specifies checkout options (may be null)
531  *
532  * Returns: 0 on success, non-zero return value from `notify_cb`, or error code < 0 (use git_error_last for error details)
533  */
534 //GIT_EXTERN
535 int git_checkout_tree(libgit2_d.types.git_repository* repo, const (libgit2_d.types.git_object)* treeish, const (.git_checkout_options)* opts);
536 
537 /** @} */