summaryrefslogtreecommitdiff
path: root/include/git2/checkout.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/git2/checkout.h')
-rw-r--r--include/git2/checkout.h155
1 files changed, 126 insertions, 29 deletions
diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index 390d2f215..a9314c2cb 100644
--- a/include/git2/checkout.h
+++ b/include/git2/checkout.h
@@ -25,20 +25,117 @@ GIT_BEGIN_DECL
* Checkout behavior flags
*
* These flags control what checkout does with files. Pass in a
- * combination of these values OR'ed together.
+ * combination of these values OR'ed together. If you just pass zero
+ * (i.e. no flags), then you are effectively doing a "dry run" where no
+ * files will be modified.
+ *
+ * Checkout groups the working directory content into 3 classes of files:
+ * (1) files that don't need a change, and files that do need a change
+ * that either (2) we are allowed to modifed or (3) we are not. The flags
+ * you pass in will decide which files we are allowed to modify.
+ *
+ * By default, checkout is not allowed to modify any files. Anything
+ * needing a change would be considered a conflict.
+ *
+ * GIT_CHECKOUT_UPDATE_UNMODIFIED means that checkout is allowed to update
+ * any file where the working directory content matches the HEAD
+ * (e.g. either the files match or the file is absent in both places).
+ *
+ * GIT_CHECKOUT_UPDATE_MISSING means checkout can create a missing file
+ * that exists in the index and does not exist in the working directory.
+ * This is usually desirable for initial checkout, etc. Technically, the
+ * missing file differs from the HEAD, which is why this is separate.
+ *
+ * GIT_CHECKOUT_UPDATE_MODIFIED means checkout is allowed to update files
+ * where the working directory does not match the HEAD so long as the file
+ * actually exists in the HEAD. This option implies UPDATE_UNMODIFIED.
+ *
+ * GIT_CHECKOUT_UPDATE_UNTRACKED means checkout is allowed to update files
+ * even if there is a working directory version that does not exist in the
+ * HEAD (i.e. the file was independently created in the workdir). This
+ * implies UPDATE_UNMODIFIED | UPDATE_MISSING (but *not* UPDATE_MODIFIED).
+ *
+ *
+ * On top of these three basic strategies, there are some modifiers
+ * options that can be applied:
+ *
+ * If any files need update but are disallowed by the strategy, normally
+ * checkout calls the conflict callback (if given) and then aborts.
+ * GIT_CHECKOUT_ALLOW_CONFLICTS means it is okay to update the files that
+ * are allowed by the strategy even if there are conflicts. The conflict
+ * callbacks are still made, but non-conflicting files will be updated.
+ *
+ * Any unmerged entries in the index are automatically considered conflicts.
+ * If you want to proceed anyhow and just skip unmerged entries, you can use
+ * GIT_CHECKOUT_SKIP_UNMERGED which is less dangerous than just allowing all
+ * conflicts. Alternatively, use GIT_CHECKOUT_USE_OURS to proceed and
+ * checkout the stage 2 ("ours") version. GIT_CHECKOUT_USE_THEIRS means to
+ * proceed and use the stage 3 ("theirs") version.
+ *
+ * GIT_CHECKOUT_UPDATE_ONLY means that update is not allowed to create new
+ * files or delete old ones, only update existing content. With this
+ * flag, files that needs to be created or deleted are not conflicts -
+ * they are just skipped. This also skips typechanges to existing files
+ * (because the old would have to be removed).
+ *
+ * GIT_CHECKOUT_REMOVE_UNTRACKED means that files in the working directory
+ * that are untracked (and not ignored) will be removed altogether. These
+ * untracked files (that do not shadow index entries) are not considered
+ * conflicts and would normally be ignored.
+ *
+ *
+ * Checkout is "semi-atomic" as in it will go through the work to be done
+ * before making any changes and if may decide to abort if there are
+ * conflicts, or you can use the conflict callback to explicitly abort the
+ * action before any updates are made. Despite this, if a second process
+ * is modifying the filesystem while checkout is running, it can't
+ * guarantee that the choices is makes while initially examining the
+ * filesystem are still going to be correct as it applies them.
*/
typedef enum {
- /** Checkout does not update any files in the working directory. */
- GIT_CHECKOUT_DEFAULT = (1 << 0),
+ GIT_CHECKOUT_DEFAULT = 0, /** default is a dry run, no actual updates */
+
+ /** Allow update of entries where working dir matches HEAD. */
+ GIT_CHECKOUT_UPDATE_UNMODIFIED = (1u << 0),
+
+ /** Allow update of entries where working dir does not have file. */
+ GIT_CHECKOUT_UPDATE_MISSING = (1u << 1),
+
+ /** Allow safe updates that cannot overwrite uncommited data */
+ GIT_CHECKOUT_SAFE =
+ (GIT_CHECKOUT_UPDATE_UNMODIFIED | GIT_CHECKOUT_UPDATE_MISSING),
+
+ /** Allow update of entries in working dir that are modified from HEAD. */
+ GIT_CHECKOUT_UPDATE_MODIFIED = (1u << 2),
+
+ /** Update existing untracked files that are now present in the index. */
+ GIT_CHECKOUT_UPDATE_UNTRACKED = (1u << 3),
- /** When a file exists and is modified, replace it with new version. */
- GIT_CHECKOUT_OVERWRITE_MODIFIED = (1 << 1),
+ /** Allow all updates to force working directory to look like index */
+ GIT_CHECKOUT_FORCE =
+ (GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_MODIFIED | GIT_CHECKOUT_UPDATE_UNTRACKED),
- /** When a file does not exist in the working directory, create it. */
- GIT_CHECKOUT_CREATE_MISSING = (1 << 2),
+ /** Allow checkout to make 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),
+
+ /** Only update existing files, don't create new ones */
+ GIT_CHECKOUT_UPDATE_ONLY = (1u << 6),
+
+ /** 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),
+
+ /** Recursively checkout submodule with same options */
+ GIT_CHECKOUT_UPDATE_SUBMODULES = (1u << 16),
+ /** Recursively checkout submodules only if HEAD moved in super repo */
+ GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = (1u << 17),
- /** If an untracked file in found in the working dir, delete it. */
- GIT_CHECKOUT_REMOVE_UNTRACKED = (1 << 3),
} git_checkout_strategy_t;
/**
@@ -47,38 +144,38 @@ typedef enum {
* Use zeros to indicate default settings.
*/
typedef struct git_checkout_opts {
- unsigned int checkout_strategy; /** default: GIT_CHECKOUT_DEFAULT */
+ unsigned int checkout_strategy; /** default will be a dry run */
+
int disable_filters; /** don't apply filters like CRLF conversion */
int dir_mode; /** default is 0755 */
int file_mode; /** default is 0644 or 0755 as dictated by blob */
int file_open_flags; /** default is O_CREAT | O_TRUNC | O_WRONLY */
- /** Optional callback to notify the consumer of files that
- * haven't be checked out because a modified version of them
- * exist in the working directory.
- *
- * When provided, this callback will be invoked when the flag
- * GIT_CHECKOUT_OVERWRITE_MODIFIED isn't part of the checkout strategy.
+ /** Optional callback made on files where the index differs from the
+ * working directory but the rules do not allow update. Return a
+ * non-zero value to abort the checkout. All such callbacks will be
+ * made before any changes are made to the working directory.
*/
- int (* skipped_notify_cb)(
- const char *skipped_file,
- const git_oid *blob_oid,
- int file_mode,
+ int (*conflict_cb)(
+ const char *conflicting_path,
+ const git_oid *index_oid,
+ unsigned int index_mode,
+ unsigned int wd_mode,
void *payload);
- void *notify_payload;
+ void *conflict_payload;
/* Optional callback to notify the consumer of checkout progress. */
- void (* progress_cb)(
- const char *path,
- size_t completed_steps,
- size_t total_steps,
- void *payload);
+ void (*progress_cb)(
+ const char *path,
+ size_t completed_steps,
+ size_t total_steps,
+ void *payload);
void *progress_payload;
- /** When not NULL, array of fnmatch patterns specifying
- * which paths should be taken into account
+ /** When not zeroed out, array of fnmatch patterns specifying which
+ * paths should be taken into account, otherwise all files.
*/
- git_strarray paths;
+ git_strarray paths;
} git_checkout_opts;
/**