summaryrefslogtreecommitdiff
path: root/builtin/pull.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/pull.c')
-rw-r--r--builtin/pull.c104
1 files changed, 80 insertions, 24 deletions
diff --git a/builtin/pull.c b/builtin/pull.c
index 318c273eb3..7fe281414e 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -6,6 +6,7 @@
* Fetch one or more remote refs and merge it/them into the current HEAD.
*/
#include "cache.h"
+#include "config.h"
#include "builtin.h"
#include "parse-options.h"
#include "exec_cmd.h"
@@ -15,6 +16,8 @@
#include "dir.h"
#include "refs.h"
#include "revision.h"
+#include "submodule.h"
+#include "submodule-config.h"
#include "tempfile.h"
#include "lockfile.h"
#include "wt-status.h"
@@ -36,7 +39,7 @@ enum rebase_type {
static enum rebase_type parse_config_rebase(const char *key, const char *value,
int fatal)
{
- int v = git_config_maybe_bool("pull.rebase", value);
+ int v = git_parse_maybe_bool(value);
if (!v)
return REBASE_FALSE;
@@ -77,6 +80,7 @@ static const char * const pull_usage[] = {
/* Shared options */
static int opt_verbosity;
static char *opt_progress;
+static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
/* Options passed to git-merge or git-rebase */
static enum rebase_type opt_rebase = -1;
@@ -101,7 +105,6 @@ static char *opt_upload_pack;
static int opt_force;
static char *opt_tags;
static char *opt_prune;
-static char *opt_recurse_submodules;
static char *max_children;
static int opt_dry_run;
static char *opt_keep;
@@ -116,6 +119,10 @@ static struct option pull_options[] = {
OPT_PASSTHRU(0, "progress", &opt_progress, NULL,
N_("force progress reporting"),
PARSE_OPT_NOARG),
+ { OPTION_CALLBACK, 0, "recurse-submodules",
+ &recurse_submodules, N_("on-demand"),
+ N_("control for recursive fetching of submodules"),
+ PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules },
/* Options passed to git-merge or git-rebase */
OPT_GROUP(N_("Options related to merging")),
@@ -187,10 +194,6 @@ static struct option pull_options[] = {
OPT_PASSTHRU('p', "prune", &opt_prune, NULL,
N_("prune remote-tracking branches no longer on remote"),
PARSE_OPT_NOARG),
- OPT_PASSTHRU(0, "recurse-submodules", &opt_recurse_submodules,
- N_("on-demand"),
- N_("control recursive fetching of submodules"),
- PARSE_OPT_OPTARG),
OPT_PASSTHRU('j', "jobs", &max_children, N_("n"),
N_("number of submodules pulled in parallel"),
PARSE_OPT_OPTARG),
@@ -271,7 +274,7 @@ static const char *config_get_ff(void)
if (git_config_get_value("pull.ff", &value))
return NULL;
- switch (git_config_maybe_bool("pull.ff", value)) {
+ switch (git_parse_maybe_bool(value)) {
case 0:
return "--no-ff";
case 1:
@@ -337,8 +340,7 @@ static void get_merge_heads(struct oid_array *merge_heads)
struct strbuf sb = STRBUF_INIT;
struct object_id oid;
- if (!(fp = fopen(filename, "r")))
- die_errno(_("could not open '%s' for reading"), filename);
+ fp = xfopen(filename, "r");
while (strbuf_getline_lf(&sb, fp) != EOF) {
if (get_oid_hex(sb.buf, &oid))
continue; /* invalid line: does not start with SHA1 */
@@ -484,8 +486,20 @@ static int run_fetch(const char *repo, const char **refspecs)
argv_array_push(&args, opt_tags);
if (opt_prune)
argv_array_push(&args, opt_prune);
- if (opt_recurse_submodules)
- argv_array_push(&args, opt_recurse_submodules);
+ if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
+ switch (recurse_submodules) {
+ case RECURSE_SUBMODULES_ON:
+ argv_array_push(&args, "--recurse-submodules=on");
+ break;
+ case RECURSE_SUBMODULES_OFF:
+ argv_array_push(&args, "--recurse-submodules=no");
+ break;
+ case RECURSE_SUBMODULES_ON_DEMAND:
+ argv_array_push(&args, "--recurse-submodules=on-demand");
+ break;
+ default:
+ BUG("submodule recursion option not understood");
+ }
if (max_children)
argv_array_push(&args, max_children);
if (opt_dry_run)
@@ -532,6 +546,30 @@ static int pull_into_void(const struct object_id *merge_head,
return 0;
}
+static int rebase_submodules(void)
+{
+ struct child_process cp = CHILD_PROCESS_INIT;
+
+ cp.git_cmd = 1;
+ cp.no_stdin = 1;
+ argv_array_pushl(&cp.args, "submodule", "update",
+ "--recursive", "--rebase", NULL);
+
+ return run_command(&cp);
+}
+
+static int update_submodules(void)
+{
+ struct child_process cp = CHILD_PROCESS_INIT;
+
+ cp.git_cmd = 1;
+ cp.no_stdin = 1;
+ argv_array_pushl(&cp.args, "submodule", "update",
+ "--recursive", "--checkout", NULL);
+
+ return run_command(&cp);
+}
+
/**
* Runs git-merge, returning its exit status.
*/
@@ -772,6 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
struct oid_array merge_heads = OID_ARRAY_INIT;
struct object_id orig_head, curr_head;
struct object_id rebase_fork_point;
+ int autostash;
if (!getenv("GIT_REFLOG_ACTION"))
set_reflog_message(argc, argv);
@@ -800,8 +839,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
if (!opt_rebase && opt_autostash != -1)
die(_("--[no-]autostash option is only valid with --rebase."));
+ autostash = config_autostash;
if (opt_rebase) {
- int autostash = config_autostash;
if (opt_autostash != -1)
autostash = opt_autostash;
@@ -862,19 +901,36 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
die(_("Cannot rebase onto multiple branches."));
if (opt_rebase) {
- struct commit_list *list = NULL;
- struct commit *merge_head, *head;
-
- head = lookup_commit_reference(&orig_head);
- commit_list_insert(head, &list);
- merge_head = lookup_commit_reference(&merge_heads.oid[0]);
- if (is_descendant_of(merge_head, list)) {
- /* we can fast-forward this without invoking rebase */
- opt_ff = "--ff-only";
- return run_merge();
+ int ret = 0;
+ if ((recurse_submodules == RECURSE_SUBMODULES_ON ||
+ recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) &&
+ submodule_touches_in_range(&rebase_fork_point, &curr_head))
+ die(_("cannot rebase with locally recorded submodule modifications"));
+ if (!autostash) {
+ struct commit_list *list = NULL;
+ struct commit *merge_head, *head;
+
+ head = lookup_commit_reference(&orig_head);
+ commit_list_insert(head, &list);
+ merge_head = lookup_commit_reference(&merge_heads.oid[0]);
+ if (is_descendant_of(merge_head, list)) {
+ /* we can fast-forward this without invoking rebase */
+ opt_ff = "--ff-only";
+ ret = run_merge();
+ }
}
- return run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point);
+ ret = run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point);
+
+ if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
+ recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
+ ret = rebase_submodules();
+
+ return ret;
} else {
- return run_merge();
+ int ret = run_merge();
+ if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
+ recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
+ ret = update_submodules();
+ return ret;
}
}