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