]> git.ipfire.org Git - thirdparty/git.git/blobdiff - builtin/fetch.c
Merge branch 'so/separate-field-for-m-and-diff-merges'
[thirdparty/git.git] / builtin / fetch.c
index 0f23dd4b8ce942dae6b9a5a0ee6352b225b99e43..a6d326866112758f62b50d7b36eab1314bda5e6f 100644 (file)
@@ -80,6 +80,7 @@ static struct list_objects_filter_options filter_options;
 static struct string_list server_options = STRING_LIST_INIT_DUP;
 static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
 static int fetch_write_commit_graph = -1;
+static int stdin_refspecs = 0;
 
 static int git_fetch_config(const char *k, const char *v, void *cb)
 {
@@ -205,6 +206,8 @@ static struct option builtin_fetch_options[] = {
                 N_("check for forced-updates on all updated branches")),
        OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph,
                 N_("write the commit-graph after fetching")),
+       OPT_BOOL(0, "stdin", &stdin_refspecs,
+                N_("accept refspecs from stdin")),
        OPT_END()
 };
 
@@ -442,6 +445,7 @@ static struct ref *get_ref_map(struct remote *remote,
        struct ref *orefs = NULL, **oref_tail = &orefs;
 
        struct hashmap existing_refs;
+       int existing_refs_populated = 0;
 
        if (rs->nr) {
                struct refspec *fetch_refspec;
@@ -535,15 +539,18 @@ static struct ref *get_ref_map(struct remote *remote,
 
        ref_map = ref_remove_duplicates(ref_map);
 
-       refname_hash_init(&existing_refs);
-       for_each_ref(add_one_refname, &existing_refs);
-
        for (rm = ref_map; rm; rm = rm->next) {
                if (rm->peer_ref) {
                        const char *refname = rm->peer_ref->name;
                        struct refname_hash_entry *peer_item;
                        unsigned int hash = strhash(refname);
 
+                       if (!existing_refs_populated) {
+                               refname_hash_init(&existing_refs);
+                               for_each_ref(add_one_refname, &existing_refs);
+                               existing_refs_populated = 1;
+                       }
+
                        peer_item = hashmap_get_entry_from_hash(&existing_refs,
                                                hash, refname,
                                                struct refname_hash_entry, ent);
@@ -553,7 +560,8 @@ static struct ref *get_ref_map(struct remote *remote,
                        }
                }
        }
-       hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
+       if (existing_refs_populated)
+               hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
 
        return ref_map;
 }
@@ -1015,11 +1023,17 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
                                rc |= update_local_ref(ref, what, rm, &note,
                                                       summary_width);
                                free(ref);
-                       } else
+                       } else if (write_fetch_head || dry_run) {
+                               /*
+                                * Display fetches written to FETCH_HEAD (or
+                                * would be written to FETCH_HEAD, if --dry-run
+                                * is set).
+                                */
                                format_display(&note, '*',
                                               *kind ? kind : "branch", NULL,
                                               *what ? what : "HEAD",
                                               "FETCH_HEAD", summary_width);
+                       }
                        if (note.len) {
                                if (verbosity >= 0 && !shown_url) {
                                        fprintf(stderr, _("From %.*s\n"),
@@ -1680,7 +1694,8 @@ static inline void fetch_one_setup_partial(struct remote *remote)
        return;
 }
 
-static int fetch_one(struct remote *remote, int argc, const char **argv, int prune_tags_ok)
+static int fetch_one(struct remote *remote, int argc, const char **argv,
+                    int prune_tags_ok, int use_stdin_refspecs)
 {
        struct refspec rs = REFSPEC_INIT_FETCH;
        int i;
@@ -1737,6 +1752,13 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, int pru
                }
        }
 
+       if (use_stdin_refspecs) {
+               struct strbuf line = STRBUF_INIT;
+               while (strbuf_getline_lf(&line, stdin) != EOF)
+                       refspec_append(&rs, line.buf);
+               strbuf_release(&line);
+       }
+
        if (server_options.nr)
                gtransport->server_options = &server_options;
 
@@ -1771,12 +1793,18 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                free(anon);
        }
 
-       fetch_config_from_gitmodules(&submodule_fetch_jobs_config,
-                                    &recurse_submodules);
        git_config(git_fetch_config, NULL);
 
        argc = parse_options(argc, argv, prefix,
                             builtin_fetch_options, builtin_fetch_usage, 0);
+       if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
+               int *sfjc = submodule_fetch_jobs_config == -1
+                           ? &submodule_fetch_jobs_config : NULL;
+               int *rs = recurse_submodules == RECURSE_SUBMODULES_DEFAULT
+                         ? &recurse_submodules : NULL;
+
+               fetch_config_from_gitmodules(sfjc, rs);
+       }
 
        if (deepen_relative) {
                if (deepen_relative < 0)
@@ -1837,7 +1865,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        if (remote) {
                if (filter_options.choice || has_promisor_remote())
                        fetch_one_setup_partial(remote);
-               result = fetch_one(remote, argc, argv, prune_tags_ok);
+               result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs);
        } else {
                int max_children = max_jobs;
 
@@ -1845,6 +1873,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                        die(_("--filter can only be used with the remote "
                              "configured in extensions.partialclone"));
 
+               if (stdin_refspecs)
+                       die(_("--stdin can only be used when fetching "
+                             "from one remote"));
+
                if (max_children < 0)
                        max_children = fetch_parallel_config;