/* * Builtin "git pull" * * Based on git-pull.sh by Junio C Hamano * * Fetch one or more remote refs and merge it/them into the current HEAD. */ #define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" #include "gettext.h" #include "hex.h" #include "merge.h" #include "object-name.h" #include "parse-options.h" #include "run-command.h" #include "oid-array.h" #include "remote.h" #include "dir.h" #include "path.h" #include "read-cache-ll.h" #include "rebase.h" #include "refs.h" #include "refspec.h" #include "submodule.h" #include "submodule-config.h" #include "wt-status.h" #include "commit-reach.h" #include "sequencer.h" /** * Parses the value of --rebase. If value is a false value, returns * REBASE_FALSE. If value is a true value, returns REBASE_TRUE. If value is * "merges", returns REBASE_MERGES. If value is a invalid value, dies with * a fatal error if fatal is true, otherwise returns REBASE_INVALID. */ static enum rebase_type parse_config_rebase(const char *key, const char *value, int fatal) { … } /** * Callback for --rebase, which parses arg with parse_config_rebase(). */ static int parse_opt_rebase(const struct option *opt, const char *arg, int unset) { … } static const char * const pull_usage[] = …; /* Shared options */ static int opt_verbosity; static const char *opt_progress; static int recurse_submodules = …; static int recurse_submodules_cli = …; /* Options passed to git-merge or git-rebase */ static enum rebase_type opt_rebase = …; static const char *opt_diffstat; static const char *opt_log; static const char *opt_signoff; static const char *opt_squash; static const char *opt_commit; static const char *opt_edit; static const char *cleanup_arg; static char *opt_ff; static const char *opt_verify_signatures; static const char *opt_verify; static int opt_autostash = …; static int config_autostash; static int check_trust_level = …; static struct strvec opt_strategies = …; static struct strvec opt_strategy_opts = …; static const char *opt_gpg_sign; static int opt_allow_unrelated_histories; /* Options passed to git-fetch */ static const char *opt_all; static const char *opt_append; static const char *opt_upload_pack; static int opt_force; static const char *opt_tags; static const char *opt_prune; static const char *max_children; static int opt_dry_run; static const char *opt_keep; static const char *opt_depth; static const char *opt_unshallow; static const char *opt_update_shallow; static const char *opt_refmap; static const char *opt_ipv4; static const char *opt_ipv6; static int opt_show_forced_updates = …; static const char *set_upstream; static struct strvec opt_fetch = …; static struct option pull_options[] = …; /** * Pushes "-q" or "-v" switches into arr to match the opt_verbosity level. */ static void argv_push_verbosity(struct strvec *arr) { … } /** * Pushes "-f" switches into arr to match the opt_force level. */ static void argv_push_force(struct strvec *arr) { … } /** * Sets the GIT_REFLOG_ACTION environment variable to the concatenation of argv */ static void set_reflog_message(int argc, const char **argv) { … } /** * If pull.ff is unset, returns NULL. If pull.ff is "true", returns "--ff". If * pull.ff is "false", returns "--no-ff". If pull.ff is "only", returns * "--ff-only". Otherwise, if pull.ff is set to an invalid value, die with an * error. */ static const char *config_get_ff(void) { … } /** * Returns the default configured value for --rebase. It first looks for the * value of "branch.$curr_branch.rebase", where $curr_branch is the current * branch, and if HEAD is detached or the configuration key does not exist, * looks for the value of "pull.rebase". If both configuration keys do not * exist, returns REBASE_FALSE. */ static enum rebase_type config_get_rebase(int *rebase_unspecified) { … } /** * Read config variables. */ static int git_pull_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { … } /** * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge * into merge_heads. */ static void get_merge_heads(struct oid_array *merge_heads) { … } /** * Used by die_no_merge_candidates() as a for_each_remote() callback to * retrieve the name of the remote if the repository only has one remote. */ static int get_only_remote(struct remote *remote, void *cb_data) { … } /** * Dies with the appropriate reason for why there are no merge candidates: * * 1. We fetched from a specific remote, and a refspec was given, but it ended * up not fetching anything. This is usually because the user provided a * wildcard refspec which had no matches on the remote end. * * 2. We fetched from a non-default remote, but didn't specify a branch to * merge. We can't use the configured one because it applies to the default * remote, thus the user must specify the branches to merge. * * 3. We fetched from the branch's or repo's default remote, but: * * a. We are not on a branch, so there will never be a configured branch to * merge with. * * b. We are on a branch, but there is no configured branch to merge with. * * 4. We fetched from the branch's or repo's default remote, but the configured * branch to merge didn't get fetched. (Either it doesn't exist, or wasn't * part of the configured fetch refspec.) */ static void NORETURN die_no_merge_candidates(const char *repo, const char **refspecs) { … } /** * Parses argv into [<repo> [<refspecs>...]], returning their values in `repo` * as a string and `refspecs` as a null-terminated array of strings. If `repo` * is not provided in argv, it is set to NULL. */ static void parse_repo_refspecs(int argc, const char **argv, const char **repo, const char ***refspecs) { … } /** * Runs git-fetch, returning its exit status. `repo` and `refspecs` are the * repository and refspecs to fetch, or NULL if they are not provided. */ static int run_fetch(const char *repo, const char **refspecs) { … } /** * "Pulls into void" by branching off merge_head. */ static int pull_into_void(const struct object_id *merge_head, const struct object_id *curr_head) { … } static int rebase_submodules(void) { … } static int update_submodules(void) { … } /** * Runs git-merge, returning its exit status. */ static int run_merge(void) { … } /** * Returns remote's upstream branch for the current branch. If remote is NULL, * the current branch's configured default remote is used. Returns NULL if * `remote` does not name a valid remote, HEAD does not point to a branch, * remote is not the branch's configured remote or the branch does not have any * configured upstream branch. */ static const char *get_upstream_branch(const char *remote) { … } /** * Derives the remote-tracking branch from the remote and refspec. * * FIXME: The current implementation assumes the default mapping of * refs/heads/<branch_name> to refs/remotes/<remote_name>/<branch_name>. */ static const char *get_tracking_branch(const char *remote, const char *refspec) { … } /** * Given the repo and refspecs, sets fork_point to the point at which the * current branch forked from its remote-tracking branch. Returns 0 on success, * -1 on failure. */ static int get_rebase_fork_point(struct object_id *fork_point, const char *repo, const char *refspec) { … } /** * Sets merge_base to the octopus merge base of curr_head, merge_head and * fork_point. Returns 0 if a merge base is found, 1 otherwise. */ static int get_octopus_merge_base(struct object_id *merge_base, const struct object_id *curr_head, const struct object_id *merge_head, const struct object_id *fork_point) { … } /** * Given the current HEAD oid, the merge head returned from git-fetch and the * fork point calculated by get_rebase_fork_point(), compute the <newbase> and * <upstream> arguments to use for the upcoming git-rebase invocation. */ static int get_rebase_newbase_and_upstream(struct object_id *newbase, struct object_id *upstream, const struct object_id *curr_head, const struct object_id *merge_head, const struct object_id *fork_point) { … } /** * Given the <newbase> and <upstream> calculated by * get_rebase_newbase_and_upstream(), runs git-rebase with the * appropriate arguments and returns its exit status. */ static int run_rebase(const struct object_id *newbase, const struct object_id *upstream) { … } static int get_can_ff(struct object_id *orig_head, struct oid_array *merge_heads) { … } /* * Is orig_head a descendant of _all_ merge_heads? * Unfortunately is_descendant_of() cannot be used as it asks * if orig_head is a descendant of at least one of them. */ static int already_up_to_date(struct object_id *orig_head, struct oid_array *merge_heads) { … } static void show_advice_pull_non_ff(void) { … } int cmd_pull(int argc, const char **argv, const char *prefix, struct repository *repository UNUSED) { … }