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 /** @} */