blob: bd988db2c405bdab2dda40acf1562ba9a4efa68f [file] [log] [blame]
/*
* Copyright (C) 2012 the libgit2 contributors
*
* 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 "indexer.h"
#include "strarray.h"
/**
* @file git2/checkout.h
* @brief Git checkout routines
* @defgroup git_checkout Git checkout routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Checkout behavior flags
*
* These flags control what checkout does with files. Pass in a
* 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 {
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),
/** 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),
/** 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),
/**
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
*/
/** Allow checkout to skip unmerged files (NOT IMPLEMENTED) */
GIT_CHECKOUT_SKIP_UNMERGED = (1u << 10),
/** For unmerged files, checkout stage 2 from index (NOT IMPLEMENTED) */
GIT_CHECKOUT_USE_OURS = (1u << 11),
/** For unmerged files, checkout stage 3 from index (NOT IMPLEMENTED) */
GIT_CHECKOUT_USE_THEIRS = (1u << 12),
/** 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 options structure
*
* Use zeros to indicate default settings.
* This needs to be initialized with the `GIT_CHECKOUT_OPTS_INIT` macro:
*
* git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
*/
typedef struct git_checkout_opts {
unsigned int version;
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 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 (*conflict_cb)(
const char *conflicting_path,
const git_oid *index_oid,
unsigned int index_mode,
unsigned int wd_mode,
void *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_payload;
/** When not zeroed out, array of fnmatch patterns specifying which
* paths should be taken into account, otherwise all files.
*/
git_strarray paths;
} git_checkout_opts;
#define GIT_CHECKOUT_OPTS_INIT {1, 0}
/**
* Updates files in the index and the working tree to match the content of the
* commit pointed at by HEAD.
*
* @param repo repository to check out (must be non-bare)
* @param opts specifies checkout options (may be NULL)
* @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing
* branch, GIT_ERROR otherwise (use giterr_last for information
* about the error)
*/
GIT_EXTERN(int) git_checkout_head(
git_repository *repo,
git_checkout_opts *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, GIT_ERROR otherwise (use giterr_last for information
* about the error)
*/
GIT_EXTERN(int) git_checkout_index(
git_repository *repo,
git_index *index,
git_checkout_opts *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
* @param opts specifies checkout options (may be NULL)
* @return 0 on success, GIT_ERROR otherwise (use giterr_last for information
* about the error)
*/
GIT_EXTERN(int) git_checkout_tree(
git_repository *repo,
const git_object *treeish,
git_checkout_opts *opts);
/** @} */
GIT_END_DECL
#endif