Merge branch 'jk/clone-post-checkout'
[gitweb.git] / builtin-fetch.c
index 97fdc51e3188143e0546512f59be9d2542dcac9a..1e4a3d9c516c88d701819b7f4b73c722412d540f 100644 (file)
@@ -5,14 +5,15 @@
 #include "refs.h"
 #include "commit.h"
 #include "builtin.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "remote.h"
 #include "transport.h"
 #include "run-command.h"
 #include "parse-options.h"
+#include "sigchain.h"
 
 static const char * const builtin_fetch_usage[] = {
-       "git-fetch [options] [<repository> <refspec>...]",
+       "git fetch [options] [<repository> <refspec>...]",
        NULL
 };
 
@@ -22,7 +23,7 @@ enum {
        TAGS_SET = 2
 };
 
-static int append, force, keep, update_head_ok, verbose, quiet;
+static int append, force, keep, update_head_ok, verbosity;
 static int tags = TAGS_DEFAULT;
 static const char *depth;
 static const char *upload_pack;
@@ -30,8 +31,7 @@ static struct strbuf default_rla = STRBUF_INIT;
 static struct transport *transport;
 
 static struct option builtin_fetch_options[] = {
-       OPT__QUIET(&quiet),
-       OPT__VERBOSE(&verbose),
+       OPT__VERBOSITY(&verbosity),
        OPT_BOOLEAN('a', "append", &append,
                    "append to .git/FETCH_HEAD instead of overwriting"),
        OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
@@ -59,7 +59,7 @@ static void unlock_pack(void)
 static void unlock_pack_on_signal(int signo)
 {
        unlock_pack();
-       signal(SIGINT, SIG_DFL);
+       sigchain_pop(signo);
        raise(signo);
 }
 
@@ -86,10 +86,10 @@ static void add_merge_config(struct ref **head,
                /*
                 * Not fetched to a tracking branch?  We need to fetch
                 * it anyway to allow this branch's "branch.$name.merge"
-                * to be honored by git-pull, but we do not have to
+                * to be honored by 'git pull', but we do not have to
                 * fail if branch.$name.merge is misconfigured to point
                 * at a nonexisting branch.  If we were indeed called by
-                * git-pull, it will notice the misconfiguration because
+                * 'git pull', it will notice the misconfiguration because
                 * there is no entry in the resulting FETCH_HEAD marked
                 * for merging.
                 */
@@ -192,7 +192,6 @@ static int s_update_ref(const char *action,
 
 static int update_local_ref(struct ref *ref,
                            const char *remote,
-                           int verbose,
                            char *display)
 {
        struct commit *current = NULL, *updated;
@@ -210,7 +209,7 @@ static int update_local_ref(struct ref *ref,
                die("object %s not found", sha1_to_hex(ref->new_sha1));
 
        if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
-               if (verbose)
+               if (verbosity > 0)
                        sprintf(display, "= %-*s %-*s -> %s", SUMMARY_WIDTH,
                                "[up to date]", REFCOL_WIDTH, remote,
                                pretty_ref);
@@ -366,18 +365,19 @@ static int store_updated_refs(const char *url, const char *remote_name,
                        note);
 
                if (ref)
-                       rc |= update_local_ref(ref, what, verbose, note);
+                       rc |= update_local_ref(ref, what, note);
                else
                        sprintf(note, "* %-*s %-*s -> FETCH_HEAD",
                                SUMMARY_WIDTH, *kind ? kind : "branch",
                                 REFCOL_WIDTH, *what ? what : "HEAD");
                if (*note) {
-                       if (!shown_url) {
+                       if (verbosity >= 0 && !shown_url) {
                                fprintf(stderr, "From %.*s\n",
                                                url_len, url);
                                shown_url = 1;
                        }
-                       fprintf(stderr, " %s\n", note);
+                       if (verbosity >= 0)
+                               fprintf(stderr, " %s\n", note);
                }
        }
        fclose(fp);
@@ -396,7 +396,7 @@ static int store_updated_refs(const char *url, const char *remote_name,
  * The refs we are going to fetch are in to_fetch (nr_heads in
  * total).  If running
  *
- *  $ git-rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
+ *  $ git rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
  *
  * does not error out, that means everything reachable from the
  * refs we are going to fetch exists and is connected to some of
@@ -465,8 +465,8 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
 static int add_existing(const char *refname, const unsigned char *sha1,
                        int flag, void *cbdata)
 {
-       struct path_list *list = (struct path_list *)cbdata;
-       path_list_insert(refname, list);
+       struct string_list *list = (struct string_list *)cbdata;
+       string_list_insert(refname, list);
        return 0;
 }
 
@@ -485,8 +485,8 @@ static void find_non_local_tags(struct transport *transport,
                        struct ref **head,
                        struct ref ***tail)
 {
-       struct path_list existing_refs = { NULL, 0, 0, 0 };
-       struct path_list new_refs = { NULL, 0, 0, 1 };
+       struct string_list existing_refs = { NULL, 0, 0, 0 };
+       struct string_list new_refs = { NULL, 0, 0, 1 };
        char *ref_name;
        int ref_name_len;
        const unsigned char *ref_sha1;
@@ -515,14 +515,14 @@ static void find_non_local_tags(struct transport *transport,
                        }
                }
 
-               if (!path_list_has_path(&existing_refs, ref_name) &&
-                   !path_list_has_path(&new_refs, ref_name) &&
+               if (!string_list_has_string(&existing_refs, ref_name) &&
+                   !string_list_has_string(&new_refs, ref_name) &&
                    (has_sha1_file(ref->old_sha1) ||
                     will_fetch(head, ref->old_sha1))) {
-                       path_list_insert(ref_name, &new_refs);
+                       string_list_insert(ref_name, &new_refs);
 
-                       rm = alloc_ref_from_str(ref_name);
-                       rm->peer_ref = alloc_ref_from_str(ref_name);
+                       rm = alloc_ref(ref_name);
+                       rm->peer_ref = alloc_ref(ref_name);
                        hashcpy(rm->old_sha1, ref_sha1);
 
                        **tail = rm;
@@ -530,8 +530,21 @@ static void find_non_local_tags(struct transport *transport,
                }
                free(ref_name);
        }
-       path_list_clear(&existing_refs, 0);
-       path_list_clear(&new_refs, 0);
+       string_list_clear(&existing_refs, 0);
+       string_list_clear(&new_refs, 0);
+}
+
+static void check_not_current_branch(struct ref *ref_map)
+{
+       struct branch *current_branch = branch_get(NULL);
+
+       if (is_bare_repository() || !current_branch)
+               return;
+
+       for (; ref_map; ref_map = ref_map->next)
+               if (ref_map->peer_ref && !strcmp(current_branch->refname,
+                                       ref_map->peer_ref->name))
+                       die("Refusing to fetch into current branch");
 }
 
 static int do_fetch(struct transport *transport,
@@ -558,6 +571,8 @@ static int do_fetch(struct transport *transport,
        }
 
        ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags);
+       if (!update_head_ok)
+               check_not_current_branch(ref_map);
 
        for (rm = ref_map; rm; rm = rm->next) {
                if (rm->peer_ref)
@@ -593,7 +608,7 @@ static void set_option(const char *name, const char *value)
 {
        int r = transport_set_option(transport, name, value);
        if (r < 0)
-               die("Option \"%s\" value \"%s\" is not valid for %s\n",
+               die("Option \"%s\" value \"%s\" is not valid for %s",
                        name, value, transport->url);
        if (r > 0)
                warning("Option \"%s\" is ignored for %s\n",
@@ -622,9 +637,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                remote = remote_get(argv[0]);
 
        transport = transport_get(remote, remote->url[0]);
-       if (verbose >= 2)
+       if (verbosity >= 2)
                transport->verbose = 1;
-       if (quiet)
+       if (verbosity < 0)
                transport->verbose = -1;
        if (upload_pack)
                set_option(TRANS_OPT_UPLOADPACK, upload_pack);
@@ -658,7 +673,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                ref_nr = j;
        }
 
-       signal(SIGINT, unlock_pack_on_signal);
+       sigchain_push_common(unlock_pack_on_signal);
        atexit(unlock_pack);
        exit_code = do_fetch(transport,
                        parse_fetch_refspec(ref_nr, refs), ref_nr);