]> Pileus Git - ~andy/git/blobdiff - transport.c
fetch: add --update-shallow to accept refs that update .git/shallow
[~andy/git] / transport.c
index de255880a41248857990380d7622512fd18160b0..a09fdb6df2a7a4a9b5ad1b381c8cafb4dfcc9972 100644 (file)
@@ -3,6 +3,8 @@
 #include "run-command.h"
 #include "pkt-line.h"
 #include "fetch-pack.h"
+#include "remote.h"
+#include "connect.h"
 #include "send-pack.h"
 #include "walker.h"
 #include "bundle.h"
@@ -12,6 +14,7 @@
 #include "url.h"
 #include "submodule.h"
 #include "string-list.h"
+#include "sha1-array.h"
 
 /* rsync support */
 
@@ -452,7 +455,8 @@ struct git_transport_data {
        struct child_process *conn;
        int fd[2];
        unsigned got_remote_heads : 1;
-       struct extra_have_objects extra_have;
+       struct sha1_array extra_have;
+       struct sha1_array shallow;
 };
 
 static int set_git_option(struct git_transport_options *opts,
@@ -473,6 +477,9 @@ static int set_git_option(struct git_transport_options *opts,
        } else if (!strcmp(name, TRANS_OPT_KEEP)) {
                opts->keep = !!value;
                return 0;
+       } else if (!strcmp(name, TRANS_OPT_UPDATE_SHALLOW)) {
+               opts->update_shallow = !!value;
+               return 0;
        } else if (!strcmp(name, TRANS_OPT_DEPTH)) {
                if (!value)
                        opts->depth = 0;
@@ -509,7 +516,9 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
 
        connect_setup(transport, for_push, 0);
        get_remote_heads(data->fd[0], NULL, 0, &refs,
-                        for_push ? REF_NORMAL : 0, &data->extra_have);
+                        for_push ? REF_NORMAL : 0,
+                        &data->extra_have,
+                        &data->shallow);
        data->got_remote_heads = 1;
 
        return refs;
@@ -536,16 +545,19 @@ static int fetch_refs_via_pack(struct transport *transport,
        args.depth = data->options.depth;
        args.check_self_contained_and_connected =
                data->options.check_self_contained_and_connected;
+       args.cloning = transport->cloning;
+       args.update_shallow = data->options.update_shallow;
 
        if (!data->got_remote_heads) {
                connect_setup(transport, 0, 0);
-               get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0, NULL);
+               get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0,
+                                NULL, &data->shallow);
                data->got_remote_heads = 1;
        }
 
        refs = fetch_pack(&args, data->fd, data->conn,
                          refs_tmp ? refs_tmp : transport->remote_refs,
-                         dest, to_fetch, nr_heads,
+                         dest, to_fetch, nr_heads, &data->shallow,
                          &transport->pack_lockfile);
        close(data->fd[0]);
        close(data->fd[1]);
@@ -707,6 +719,14 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
                print_ref_status('!', "[rejected]", ref, ref->peer_ref,
                                                 "needs force", porcelain);
                break;
+       case REF_STATUS_REJECT_STALE:
+               print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+                                                "stale info", porcelain);
+               break;
+       case REF_STATUS_REJECT_SHALLOW:
+               print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+                                                "new shallow roots not allowed", porcelain);
+               break;
        case REF_STATUS_REMOTE_REJECT:
                print_ref_status('!', "[remote rejected]", ref,
                                                 ref->deletion ? NULL : ref->peer_ref,
@@ -799,9 +819,11 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
                struct ref *tmp_refs;
                connect_setup(transport, 1, 0);
 
-               get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL, NULL);
+               get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL, NULL, NULL);
                data->got_remote_heads = 1;
        }
+       if (data->shallow.nr)
+               die("pushing to a shallow repository is not supported");
 
        memset(&args, 0, sizeof(args));
        args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
@@ -1078,6 +1100,7 @@ static int run_pre_push_hook(struct transport *transport,
        for (r = remote_refs; r; r = r->next) {
                if (!r->peer_ref) continue;
                if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue;
+               if (r->status == REF_STATUS_REJECT_STALE) continue;
                if (r->status == REF_STATUS_UPTODATE) continue;
 
                strbuf_reset(&buf);
@@ -1142,6 +1165,12 @@ int transport_push(struct transport *transport,
                        return -1;
                }
 
+               if (transport->smart_options &&
+                   transport->smart_options->cas &&
+                   !is_empty_cas(transport->smart_options->cas))
+                       apply_push_cas(transport->smart_options->cas,
+                                      transport->remote, remote_refs);
+
                set_ref_status_for_push(remote_refs,
                        flags & TRANSPORT_PUSH_MIRROR,
                        flags & TRANSPORT_PUSH_FORCE);