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