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