| /* |
| * Copyright (C) the libgit2 contributors. All rights reserved. |
| * |
| * This file is part of libgit2, distributed under the GNU GPL v2 with |
| * a Linking Exception. For full terms see the included COPYING file. |
| */ |
| #ifndef INCLUDE_git_checkout_h__ |
| #define INCLUDE_git_checkout_h__ |
| |
| #include "common.h" |
| #include "types.h" |
| #include "diff.h" |
| |
| /** |
| * @file git2/checkout.h |
| * @brief Git checkout routines |
| * @defgroup git_checkout Git checkout routines |
| * @ingroup Git |
| * @{ |
| */ |
| GIT_BEGIN_DECL |
| |
| /** |
| * Checkout behavior flags |
| * |
| * In libgit2, checkout is used to update the working directory and index |
| * to match a target tree. Unlike git checkout, it does not move the HEAD |
| * commit for you - use `git_repository_set_head` or the like to do that. |
| * |
| * Checkout looks at (up to) four things: the "target" tree you want to |
| * check out, the "baseline" tree of what was checked out previously, the |
| * working directory for actual files, and the index for staged changes. |
| * |
| * You give checkout one of three strategies for update: |
| * |
| * - `GIT_CHECKOUT_NONE` is a dry-run strategy that checks for conflicts, |
| * etc., but doesn't make any actual changes. |
| * |
| * - `GIT_CHECKOUT_FORCE` is at the opposite extreme, taking any action to |
| * make the working directory match the target (including potentially |
| * discarding modified files). |
| * |
| * - `GIT_CHECKOUT_SAFE` is between these two options, it will only make |
| * modifications that will not lose changes. |
| * |
| * | target == baseline | target != baseline | |
| * ---------------------|-----------------------|----------------------| |
| * workdir == baseline | no action | create, update, or | |
| * | | delete file | |
| * ---------------------|-----------------------|----------------------| |
| * workdir exists and | no action | conflict (notify | |
| * is != baseline | notify dirty MODIFIED | and cancel checkout) | |
| * ---------------------|-----------------------|----------------------| |
| * workdir missing, | notify dirty DELETED | create file | |
| * baseline present | | | |
| * ---------------------|-----------------------|----------------------| |
| * |
| * To emulate `git checkout`, use `GIT_CHECKOUT_SAFE` with a checkout |
| * notification callback (see below) that displays information about dirty |
| * files. The default behavior will cancel checkout on conflicts. |
| * |
| * To emulate `git checkout-index`, use `GIT_CHECKOUT_SAFE` with a |
| * notification callback that cancels the operation if a dirty-but-existing |
| * file is found in the working directory. This core git command isn't |
| * quite "force" but is sensitive about some types of changes. |
| * |
| * To emulate `git checkout -f`, use `GIT_CHECKOUT_FORCE`. |
| * |
| * |
| * There are some additional flags to modify the behavior of checkout: |
| * |
| * - GIT_CHECKOUT_ALLOW_CONFLICTS makes SAFE mode apply safe file updates |
| * even if there are conflicts (instead of cancelling the checkout). |
| * |
| * - GIT_CHECKOUT_REMOVE_UNTRACKED means remove untracked files (i.e. not |
| * in target, baseline, or index, and not ignored) from the working dir. |
| * |
| * - GIT_CHECKOUT_REMOVE_IGNORED means remove ignored files (that are also |
| * untracked) from the working directory as well. |
| * |
| * - GIT_CHECKOUT_UPDATE_ONLY means to only update the content of files that |
| * already exist. Files will not be created nor deleted. This just skips |
| * applying adds, deletes, and typechanges. |
| * |
| * - GIT_CHECKOUT_DONT_UPDATE_INDEX prevents checkout from writing the |
| * updated files' information to the index. |
| * |
| * - Normally, checkout will reload the index and git attributes from disk |
| * before any operations. GIT_CHECKOUT_NO_REFRESH prevents this reload. |
| * |
| * - Unmerged index entries are conflicts. GIT_CHECKOUT_SKIP_UNMERGED skips |
| * files with unmerged index entries instead. GIT_CHECKOUT_USE_OURS and |
| * GIT_CHECKOUT_USE_THEIRS to proceed with the checkout using either the |
| * stage 2 ("ours") or stage 3 ("theirs") version of files in the index. |
| * |
| * - GIT_CHECKOUT_DONT_OVERWRITE_IGNORED prevents ignored files from being |
| * overwritten. Normally, files that are ignored in the working directory |
| * are not considered "precious" and may be overwritten if the checkout |
| * target contains that file. |
| * |
| * - GIT_CHECKOUT_DONT_REMOVE_EXISTING prevents checkout from removing |
| * files or folders that fold to the same name on case insensitive |
| * filesystems. This can cause files to retain their existing names |
| * and write through existing symbolic links. |
| */ |
| typedef enum { |
| GIT_CHECKOUT_NONE = 0, /**< default is a dry run, no actual updates */ |
| |
| /** Allow safe updates that cannot overwrite uncommitted data */ |
| GIT_CHECKOUT_SAFE = (1u << 0), |
| |
| /** Allow all updates to force working directory to look like index */ |
| GIT_CHECKOUT_FORCE = (1u << 1), |
| |
| |
| /** Allow checkout to recreate missing files */ |
| GIT_CHECKOUT_RECREATE_MISSING = (1u << 2), |
| |
| /** Allow checkout to make safe updates even if conflicts are found */ |
| GIT_CHECKOUT_ALLOW_CONFLICTS = (1u << 4), |
| |
| /** Remove untracked files not in index (that are not ignored) */ |
| GIT_CHECKOUT_REMOVE_UNTRACKED = (1u << 5), |
| |
| /** Remove ignored files not in index */ |
| GIT_CHECKOUT_REMOVE_IGNORED = (1u << 6), |
| |
| /** Only update existing files, don't create new ones */ |
| GIT_CHECKOUT_UPDATE_ONLY = (1u << 7), |
| |
| /** |
| * Normally checkout updates index entries as it goes; this stops that. |
| * Implies `GIT_CHECKOUT_DONT_WRITE_INDEX`. |
| */ |
| GIT_CHECKOUT_DONT_UPDATE_INDEX = (1u << 8), |
| |
| /** Don't refresh index/config/etc before doing checkout */ |
| GIT_CHECKOUT_NO_REFRESH = (1u << 9), |
| |
| /** Allow checkout to skip unmerged files */ |
| GIT_CHECKOUT_SKIP_UNMERGED = (1u << 10), |
| /** For unmerged files, checkout stage 2 from index */ |
| GIT_CHECKOUT_USE_OURS = (1u << 11), |
| /** For unmerged files, checkout stage 3 from index */ |
| GIT_CHECKOUT_USE_THEIRS = (1u << 12), |
| |
| /** Treat pathspec as simple list of exact match file paths */ |
| GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = (1u << 13), |
| |
| /** Ignore directories in use, they will be left empty */ |
| GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = (1u << 18), |
| |
| /** Don't overwrite ignored files that exist in the checkout target */ |
| GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = (1u << 19), |
| |
| /** Write normal merge files for conflicts */ |
| GIT_CHECKOUT_CONFLICT_STYLE_MERGE = (1u << 20), |
| |
| /** Include common ancestor data in diff3 format files for conflicts */ |
| GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = (1u << 21), |
| |
| /** Don't overwrite existing files or folders */ |
| GIT_CHECKOUT_DONT_REMOVE_EXISTING = (1u << 22), |
| |
| /** Normally checkout writes the index upon completion; this prevents that. */ |
| GIT_CHECKOUT_DONT_WRITE_INDEX = (1u << 23), |
| |
| /** |
| * THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED |
| */ |
| |
| /** Recursively checkout submodules with same options (NOT IMPLEMENTED) */ |
| GIT_CHECKOUT_UPDATE_SUBMODULES = (1u << 16), |
| /** Recursively checkout submodules if HEAD moved in super repo (NOT IMPLEMENTED) */ |
| GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = (1u << 17), |
| |
| } git_checkout_strategy_t; |
| |
| /** |
| * Checkout notification flags |
| * |
| * Checkout will invoke an options notification callback (`notify_cb`) for |
| * certain cases - you pick which ones via `notify_flags`: |
| * |
| * - GIT_CHECKOUT_NOTIFY_CONFLICT invokes checkout on conflicting paths. |
| * |
| * - GIT_CHECKOUT_NOTIFY_DIRTY notifies about "dirty" files, i.e. those that |
| * do not need an update but no longer match the baseline. Core git |
| * displays these files when checkout runs, but won't stop the checkout. |
| * |
| * - GIT_CHECKOUT_NOTIFY_UPDATED sends notification for any file changed. |
| * |
| * - GIT_CHECKOUT_NOTIFY_UNTRACKED notifies about untracked files. |
| * |
| * - GIT_CHECKOUT_NOTIFY_IGNORED notifies about ignored files. |
| * |
| * Returning a non-zero value from this callback will cancel the checkout. |
| * The non-zero return value will be propagated back and returned by the |
| * git_checkout_... call. |
| * |
| * Notification callbacks are made prior to modifying any files on disk, |
| * so canceling on any notification will still happen prior to any files |
| * being modified. |
| */ |
| typedef enum { |
| GIT_CHECKOUT_NOTIFY_NONE = 0, |
| GIT_CHECKOUT_NOTIFY_CONFLICT = (1u << 0), |
| GIT_CHECKOUT_NOTIFY_DIRTY = (1u << 1), |
| GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2), |
| GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3), |
| GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4), |
| |
| GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu |
| } git_checkout_notify_t; |
| |
| typedef struct { |
| size_t mkdir_calls; |
| size_t stat_calls; |
| size_t chmod_calls; |
| } git_checkout_perfdata; |
| |
| /** Checkout notification callback function */ |
| typedef int GIT_CALLBACK(git_checkout_notify_cb)( |
| git_checkout_notify_t why, |
| const char *path, |
| const git_diff_file *baseline, |
| const git_diff_file *target, |
| const git_diff_file *workdir, |
| void *payload); |
| |
| /** Checkout progress notification function */ |
| typedef void GIT_CALLBACK(git_checkout_progress_cb)( |
| const char *path, |
| size_t completed_steps, |
| size_t total_steps, |
| void *payload); |
| |
| /** Checkout perfdata notification function */ |
| typedef void GIT_CALLBACK(git_checkout_perfdata_cb)( |
| const git_checkout_perfdata *perfdata, |
| void *payload); |
| |
| /** |
| * Checkout options structure |
| * |
| * Initialize with `GIT_CHECKOUT_OPTIONS_INIT`. Alternatively, you can |
| * use `git_checkout_init_options`. |
| * |
| */ |
| typedef struct git_checkout_options { |
| unsigned int version; |
| |
| unsigned int checkout_strategy; /**< default will be a safe checkout */ |
| |
| int disable_filters; /**< don't apply filters like CRLF conversion */ |
| unsigned int dir_mode; /**< default is 0755 */ |
| unsigned int file_mode; /**< default is 0644 or 0755 as dictated by blob */ |
| int file_open_flags; /**< default is O_CREAT | O_TRUNC | O_WRONLY */ |
| |
| unsigned int notify_flags; /**< see `git_checkout_notify_t` above */ |
| git_checkout_notify_cb notify_cb; |
| void *notify_payload; |
| |
| /** Optional callback to notify the consumer of checkout progress. */ |
| git_checkout_progress_cb progress_cb; |
| void *progress_payload; |
| |
| /** When not zeroed out, array of fnmatch patterns specifying which |
| * paths should be taken into account, otherwise all files. Use |
| * GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH to treat as simple list. |
| */ |
| git_strarray paths; |
| |
| /** The expected content of the working directory; defaults to HEAD. |
| * If the working directory does not match this baseline information, |
| * that will produce a checkout conflict. |
| */ |
| git_tree *baseline; |
| |
| /** Like `baseline` above, though expressed as an index. This |
| * option overrides `baseline`. |
| */ |
| git_index *baseline_index; /**< expected content of workdir, expressed as an index. */ |
| |
| const char *target_directory; /**< alternative checkout path to workdir */ |
| |
| const char *ancestor_label; /**< the name of the common ancestor side of conflicts */ |
| const char *our_label; /**< the name of the "our" side of conflicts */ |
| const char *their_label; /**< the name of the "their" side of conflicts */ |
| |
| /** Optional callback to notify the consumer of performance data. */ |
| git_checkout_perfdata_cb perfdata_cb; |
| void *perfdata_payload; |
| } git_checkout_options; |
| |
| #define GIT_CHECKOUT_OPTIONS_VERSION 1 |
| #define GIT_CHECKOUT_OPTIONS_INIT {GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE} |
| |
| /** |
| * Initialize git_checkout_options structure |
| * |
| * Initializes a `git_checkout_options` with default values. Equivalent to creating |
| * an instance with GIT_CHECKOUT_OPTIONS_INIT. |
| * |
| * @param opts The `git_checkout_options` struct to initialize. |
| * @param version The struct version; pass `GIT_CHECKOUT_OPTIONS_VERSION`. |
| * @return Zero on success; -1 on failure. |
| */ |
| GIT_EXTERN(int) git_checkout_init_options( |
| git_checkout_options *opts, |
| unsigned int version); |
| |
| /** |
| * Updates files in the index and the working tree to match the content of |
| * the commit pointed at by HEAD. |
| * |
| * Note that this is _not_ the correct mechanism used to switch branches; |
| * do not change your `HEAD` and then call this method, that would leave |
| * you with checkout conflicts since your working directory would then |
| * appear to be dirty. Instead, checkout the target of the branch and |
| * then update `HEAD` using `git_repository_set_head` to point to the |
| * branch you checked out. |
| * |
| * @param repo repository to check out (must be non-bare) |
| * @param opts specifies checkout options (may be NULL) |
| * @return 0 on success, 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) |
| */ |
| GIT_EXTERN(int) git_checkout_head( |
| git_repository *repo, |
| const git_checkout_options *opts); |
| |
| /** |
| * Updates files in the working tree to match the content of the index. |
| * |
| * @param repo repository into which to check out (must be non-bare) |
| * @param index index to be checked out (or NULL to use repository index) |
| * @param opts specifies checkout options (may be NULL) |
| * @return 0 on success, non-zero return value from `notify_cb`, or error |
| * code < 0 (use git_error_last for error details) |
| */ |
| GIT_EXTERN(int) git_checkout_index( |
| git_repository *repo, |
| git_index *index, |
| const git_checkout_options *opts); |
| |
| /** |
| * Updates files in the index and working tree to match the content of the |
| * tree pointed at by the treeish. |
| * |
| * @param repo repository to check out (must be non-bare) |
| * @param treeish a commit, tag or tree which content will be used to update |
| * the working directory (or NULL to use HEAD) |
| * @param opts specifies checkout options (may be NULL) |
| * @return 0 on success, non-zero return value from `notify_cb`, or error |
| * code < 0 (use git_error_last for error details) |
| */ |
| GIT_EXTERN(int) git_checkout_tree( |
| git_repository *repo, |
| const git_object *treeish, |
| const git_checkout_options *opts); |
| |
| /** @} */ |
| GIT_END_DECL |
| #endif |