git-p4: add read_pipe_text() internal function
[gitweb.git] / fetch-pack.c
index 413937e7404d163883d5d0456ebefc4e1504cd87..f12bfcdbb12c0bde9271ba45e5d8b6941439efc1 100644 (file)
@@ -21,6 +21,8 @@ static int fetch_unpack_limit = -1;
 static int unpack_limit = 100;
 static int prefer_ofs_delta = 1;
 static int no_done;
+static int deepen_since_ok;
+static int deepen_not_ok;
 static int fetch_fsck_objects = -1;
 static int transfer_fsck_objects = -1;
 static int agent_supported;
@@ -50,6 +52,21 @@ static int non_common_revs, multi_ack, use_sideband;
 #define ALLOW_REACHABLE_SHA1   02
 static unsigned int allow_unadvertised_object_request;
 
+__attribute__((format (printf, 2, 3)))
+static inline void print_verbose(const struct fetch_pack_args *args,
+                                const char *fmt, ...)
+{
+       va_list params;
+
+       if (!args->verbose)
+               return;
+
+       va_start(params, fmt);
+       vfprintf(stderr, fmt, params);
+       va_end(params);
+       fputc('\n', stderr);
+}
+
 static void rev_list_push(struct commit *commit, int mark)
 {
        if (!(commit->object.flags & mark)) {
@@ -182,7 +199,7 @@ enum ack_type {
 
 static void consume_shallow_list(struct fetch_pack_args *args, int fd)
 {
-       if (args->stateless_rpc && args->depth > 0) {
+       if (args->stateless_rpc && args->deepen) {
                /* If we sent a depth we will get back "duplicate"
                 * shallow and unshallow commands every time there
                 * is a block of have lines exchanged.
@@ -193,7 +210,7 @@ static void consume_shallow_list(struct fetch_pack_args *args, int fd)
                                continue;
                        if (starts_with(line, "unshallow "))
                                continue;
-                       die("git fetch-pack: expected shallow list");
+                       die(_("git fetch-pack: expected shallow list"));
                }
        }
 }
@@ -205,7 +222,7 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1)
        const char *arg;
 
        if (!len)
-               die("git fetch-pack: expected ACK/NAK, got EOF");
+               die(_("git fetch-pack: expected ACK/NAK, got EOF"));
        if (!strcmp(line, "NAK"))
                return NAK;
        if (skip_prefix(line, "ACK ", &arg)) {
@@ -223,7 +240,7 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1)
                        return ACK;
                }
        }
-       die("git fetch_pack: expected ACK/NAK, got '%s'", line);
+       die(_("git fetch-pack: expected ACK/NAK, got '%s'"), line);
 }
 
 static void send_request(struct fetch_pack_args *args,
@@ -275,7 +292,7 @@ static int find_common(struct fetch_pack_args *args,
        size_t state_len = 0;
 
        if (args->stateless_rpc && multi_ack == 1)
-               die("--stateless-rpc requires multi_ack_detailed");
+               die(_("--stateless-rpc requires multi_ack_detailed"));
        if (marked)
                for_each_ref(clear_marks, NULL);
        marked = 1;
@@ -312,10 +329,13 @@ static int find_common(struct fetch_pack_args *args,
                        if (no_done)            strbuf_addstr(&c, " no-done");
                        if (use_sideband == 2)  strbuf_addstr(&c, " side-band-64k");
                        if (use_sideband == 1)  strbuf_addstr(&c, " side-band");
+                       if (args->deepen_relative) strbuf_addstr(&c, " deepen-relative");
                        if (args->use_thin_pack) strbuf_addstr(&c, " thin-pack");
                        if (args->no_progress)   strbuf_addstr(&c, " no-progress");
                        if (args->include_tag)   strbuf_addstr(&c, " include-tag");
                        if (prefer_ofs_delta)   strbuf_addstr(&c, " ofs-delta");
+                       if (deepen_since_ok)    strbuf_addstr(&c, " deepen-since");
+                       if (deepen_not_ok)      strbuf_addstr(&c, " deepen-not");
                        if (agent_supported)    strbuf_addf(&c, " agent=%s",
                                                            git_user_agent_sanitized());
                        packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
@@ -335,10 +355,21 @@ static int find_common(struct fetch_pack_args *args,
                write_shallow_commits(&req_buf, 1, NULL);
        if (args->depth > 0)
                packet_buf_write(&req_buf, "deepen %d", args->depth);
+       if (args->deepen_since) {
+               unsigned long max_age = approxidate(args->deepen_since);
+               packet_buf_write(&req_buf, "deepen-since %lu", max_age);
+       }
+       if (args->deepen_not) {
+               int i;
+               for (i = 0; i < args->deepen_not->nr; i++) {
+                       struct string_list_item *s = args->deepen_not->items + i;
+                       packet_buf_write(&req_buf, "deepen-not %s", s->string);
+               }
+       }
        packet_buf_flush(&req_buf);
        state_len = req_buf.len;
 
-       if (args->depth > 0) {
+       if (args->deepen) {
                char *line;
                const char *arg;
                unsigned char sha1[20];
@@ -347,23 +378,23 @@ static int find_common(struct fetch_pack_args *args,
                while ((line = packet_read_line(fd[0], NULL))) {
                        if (skip_prefix(line, "shallow ", &arg)) {
                                if (get_sha1_hex(arg, sha1))
-                                       die("invalid shallow line: %s", line);
+                                       die(_("invalid shallow line: %s"), line);
                                register_shallow(sha1);
                                continue;
                        }
                        if (skip_prefix(line, "unshallow ", &arg)) {
                                if (get_sha1_hex(arg, sha1))
-                                       die("invalid unshallow line: %s", line);
+                                       die(_("invalid unshallow line: %s"), line);
                                if (!lookup_object(sha1))
-                                       die("object not found: %s", line);
+                                       die(_("object not found: %s"), line);
                                /* make sure that it is parsed as shallow */
                                if (!parse_object(sha1))
-                                       die("error in object: %s", line);
+                                       die(_("error in object: %s"), line);
                                if (unregister_shallow(sha1))
-                                       die("no shallow found: %s", line);
+                                       die(_("no shallow found: %s"), line);
                                continue;
                        }
-                       die("expected shallow/unshallow, got %s", line);
+                       die(_("expected shallow/unshallow, got %s"), line);
                }
        } else if (!args->stateless_rpc)
                send_request(args, fd[1], &req_buf);
@@ -380,8 +411,7 @@ static int find_common(struct fetch_pack_args *args,
        retval = -1;
        while ((sha1 = get_rev())) {
                packet_buf_write(&req_buf, "have %s\n", sha1_to_hex(sha1));
-               if (args->verbose)
-                       fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
+               print_verbose(args, "have %s", sha1_to_hex(sha1));
                in_vain++;
                if (flush_at <= ++count) {
                        int ack;
@@ -402,9 +432,9 @@ static int find_common(struct fetch_pack_args *args,
                        consume_shallow_list(args, fd[0]);
                        do {
                                ack = get_ack(fd[0], result_sha1);
-                               if (args->verbose && ack)
-                                       fprintf(stderr, "got ack %d %s\n", ack,
-                                                       sha1_to_hex(result_sha1));
+                               if (ack)
+                                       print_verbose(args, _("got %s %d %s"), "ack",
+                                                     ack, sha1_to_hex(result_sha1));
                                switch (ack) {
                                case ACK:
                                        flushes = 0;
@@ -417,7 +447,7 @@ static int find_common(struct fetch_pack_args *args,
                                        struct commit *commit =
                                                lookup_commit(result_sha1);
                                        if (!commit)
-                                               die("invalid commit %s", sha1_to_hex(result_sha1));
+                                               die(_("invalid commit %s"), sha1_to_hex(result_sha1));
                                        if (args->stateless_rpc
                                         && ack == ACK_common
                                         && !(commit->object.flags & COMMON)) {
@@ -450,8 +480,7 @@ static int find_common(struct fetch_pack_args *args,
                        } while (ack);
                        flushes--;
                        if (got_continue && MAX_IN_VAIN < in_vain) {
-                               if (args->verbose)
-                                       fprintf(stderr, "giving up\n");
+                               print_verbose(args, _("giving up"));
                                break; /* give up */
                        }
                }
@@ -461,8 +490,7 @@ static int find_common(struct fetch_pack_args *args,
                packet_buf_write(&req_buf, "done\n");
                send_request(args, fd[1], &req_buf);
        }
-       if (args->verbose)
-               fprintf(stderr, "done\n");
+       print_verbose(args, _("done"));
        if (retval != 0) {
                multi_ack = 0;
                flushes++;
@@ -474,9 +502,8 @@ static int find_common(struct fetch_pack_args *args,
        while (flushes || multi_ack) {
                int ack = get_ack(fd[0], result_sha1);
                if (ack) {
-                       if (args->verbose)
-                               fprintf(stderr, "got ack (%d) %s\n", ack,
-                                       sha1_to_hex(result_sha1));
+                       print_verbose(args, _("got %s (%d) %s"), "ack",
+                                     ack, sha1_to_hex(result_sha1));
                        if (ack == ACK)
                                return 0;
                        multi_ack = 1;
@@ -521,9 +548,8 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args,
                                         unsigned long cutoff)
 {
        while (complete && cutoff <= complete->item->date) {
-               if (args->verbose)
-                       fprintf(stderr, "Marking %s as complete\n",
-                               oid_to_hex(&complete->item->object.oid));
+               print_verbose(args, _("Marking %s as complete"),
+                             oid_to_hex(&complete->item->object.oid));
                pop_most_recent_commit(&complete, COMPLETE);
        }
 }
@@ -552,14 +578,14 @@ static void filter_refs(struct fetch_pack_args *args,
                                        break; /* definitely do not have it */
                                else if (cmp == 0) {
                                        keep = 1; /* definitely have it */
-                                       sought[i]->matched = 1;
+                                       sought[i]->match_status = REF_MATCHED;
                                }
                                i++;
                        }
                }
 
                if (!keep && args->fetch_all &&
-                   (!args->depth || !starts_with(ref->name, "refs/tags/")))
+                   (!args->deepen || !starts_with(ref->name, "refs/tags/")))
                        keep = 1;
 
                if (keep) {
@@ -572,22 +598,24 @@ static void filter_refs(struct fetch_pack_args *args,
        }
 
        /* Append unmatched requests to the list */
-       if ((allow_unadvertised_object_request &
-           (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
-               for (i = 0; i < nr_sought; i++) {
-                       unsigned char sha1[20];
+       for (i = 0; i < nr_sought; i++) {
+               unsigned char sha1[20];
 
-                       ref = sought[i];
-                       if (ref->matched)
-                               continue;
-                       if (get_sha1_hex(ref->name, sha1) ||
-                           ref->name[40] != '\0' ||
-                           hashcmp(sha1, ref->old_oid.hash))
-                               continue;
+               ref = sought[i];
+               if (ref->match_status != REF_NOT_MATCHED)
+                       continue;
+               if (get_sha1_hex(ref->name, sha1) ||
+                   ref->name[40] != '\0' ||
+                   hashcmp(sha1, ref->old_oid.hash))
+                       continue;
 
-                       ref->matched = 1;
+               if ((allow_unadvertised_object_request &
+                   (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
+                       ref->match_status = REF_MATCHED;
                        *newtail = copy_ref(ref);
                        newtail = &(*newtail)->next;
+               } else {
+                       ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
                }
        }
        *refs = newlist;
@@ -629,7 +657,7 @@ static int everything_local(struct fetch_pack_args *args,
                }
        }
 
-       if (!args->depth) {
+       if (!args->deepen) {
                for_each_ref(mark_complete_oid, NULL);
                for_each_alternate_ref(mark_alternate_complete, NULL);
                commit_list_sort_by_date(&complete);
@@ -664,18 +692,12 @@ static int everything_local(struct fetch_pack_args *args,
                o = lookup_object(remote);
                if (!o || !(o->flags & COMPLETE)) {
                        retval = 0;
-                       if (!args->verbose)
-                               continue;
-                       fprintf(stderr,
-                               "want %s (%s)\n", sha1_to_hex(remote),
-                               ref->name);
+                       print_verbose(args, "want %s (%s)", sha1_to_hex(remote),
+                                     ref->name);
                        continue;
                }
-               if (!args->verbose)
-                       continue;
-               fprintf(stderr,
-                       "already have %s (%s)\n", sha1_to_hex(remote),
-                       ref->name);
+               print_verbose(args, _("already have %s (%s)"), sha1_to_hex(remote),
+                             ref->name);
        }
        return retval;
 }
@@ -712,8 +734,7 @@ static int get_pack(struct fetch_pack_args *args,
                demux.out = -1;
                demux.isolate_sigpipe = 1;
                if (start_async(&demux))
-                       die("fetch-pack: unable to fork off sideband"
-                           " demultiplexer");
+                       die(_("fetch-pack: unable to fork off sideband demultiplexer"));
        }
        else
                demux.out = xd[0];
@@ -721,7 +742,7 @@ static int get_pack(struct fetch_pack_args *args,
        if (!args->keep_pack && unpack_limit) {
 
                if (read_pack_header(demux.out, &header))
-                       die("protocol error: bad pack header");
+                       die(_("protocol error: bad pack header"));
                pass_header = 1;
                if (ntohl(header.hdr_entries) < unpack_limit)
                        do_keep = 0;
@@ -777,7 +798,7 @@ static int get_pack(struct fetch_pack_args *args,
        cmd.in = demux.out;
        cmd.git_cmd = 1;
        if (start_command(&cmd))
-               die("fetch-pack: unable to fork off %s", cmd_name);
+               die(_("fetch-pack: unable to fork off %s"), cmd_name);
        if (do_keep && pack_lockfile) {
                *pack_lockfile = index_pack_lockfile(cmd.out);
                close(cmd.out);
@@ -793,9 +814,9 @@ static int get_pack(struct fetch_pack_args *args,
                        args->check_self_contained_and_connected &&
                        ret == 0;
        else
-               die("%s failed", cmd_name);
+               die(_("%s failed"), cmd_name);
        if (use_sideband && finish_async(&demux))
-               die("error in sideband demultiplexer");
+               die(_("error in sideband demultiplexer"));
        return 0;
 }
 
@@ -819,44 +840,39 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        int agent_len;
 
        sort_ref_list(&ref, ref_compare_name);
-       qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name);
+       QSORT(sought, nr_sought, cmp_ref_by_name);
 
        if ((args->depth > 0 || is_repository_shallow()) && !server_supports("shallow"))
-               die("Server does not support shallow clients");
+               die(_("Server does not support shallow clients"));
+       if (args->depth > 0 || args->deepen_since || args->deepen_not)
+               args->deepen = 1;
        if (server_supports("multi_ack_detailed")) {
-               if (args->verbose)
-                       fprintf(stderr, "Server supports multi_ack_detailed\n");
+               print_verbose(args, _("Server supports multi_ack_detailed"));
                multi_ack = 2;
                if (server_supports("no-done")) {
-                       if (args->verbose)
-                               fprintf(stderr, "Server supports no-done\n");
+                       print_verbose(args, _("Server supports no-done"));
                        if (args->stateless_rpc)
                                no_done = 1;
                }
        }
        else if (server_supports("multi_ack")) {
-               if (args->verbose)
-                       fprintf(stderr, "Server supports multi_ack\n");
+               print_verbose(args, _("Server supports multi_ack"));
                multi_ack = 1;
        }
        if (server_supports("side-band-64k")) {
-               if (args->verbose)
-                       fprintf(stderr, "Server supports side-band-64k\n");
+               print_verbose(args, _("Server supports side-band-64k"));
                use_sideband = 2;
        }
        else if (server_supports("side-band")) {
-               if (args->verbose)
-                       fprintf(stderr, "Server supports side-band\n");
+               print_verbose(args, _("Server supports side-band"));
                use_sideband = 1;
        }
        if (server_supports("allow-tip-sha1-in-want")) {
-               if (args->verbose)
-                       fprintf(stderr, "Server supports allow-tip-sha1-in-want\n");
+               print_verbose(args, _("Server supports allow-tip-sha1-in-want"));
                allow_unadvertised_object_request |= ALLOW_TIP_SHA1;
        }
        if (server_supports("allow-reachable-sha1-in-want")) {
-               if (args->verbose)
-                       fprintf(stderr, "Server supports allow-reachable-sha1-in-want\n");
+               print_verbose(args, _("Server supports allow-reachable-sha1-in-want"));
                allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1;
        }
        if (!server_supports("thin-pack"))
@@ -865,18 +881,27 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
                args->no_progress = 0;
        if (!server_supports("include-tag"))
                args->include_tag = 0;
-       if (server_supports("ofs-delta")) {
-               if (args->verbose)
-                       fprintf(stderr, "Server supports ofs-delta\n");
-       } else
+       if (server_supports("ofs-delta"))
+               print_verbose(args, _("Server supports ofs-delta"));
+       else
                prefer_ofs_delta = 0;
 
        if ((agent_feature = server_feature_value("agent", &agent_len))) {
                agent_supported = 1;
-               if (args->verbose && agent_len)
-                       fprintf(stderr, "Server version is %.*s\n",
-                               agent_len, agent_feature);
+               if (agent_len)
+                       print_verbose(args, _("Server version is %.*s"),
+                                     agent_len, agent_feature);
        }
+       if (server_supports("deepen-since"))
+               deepen_since_ok = 1;
+       else if (args->deepen_since)
+               die(_("Server does not support --shallow-since"));
+       if (server_supports("deepen-not"))
+               deepen_not_ok = 1;
+       else if (args->deepen_not)
+               die(_("Server does not support --shallow-exclude"));
+       if (!server_supports("deepen-relative") && args->deepen_relative)
+               die(_("Server does not support --deepen"));
 
        if (everything_local(args, &ref, sought, nr_sought)) {
                packet_flush(fd[1]);
@@ -887,11 +912,11 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
                        /* When cloning, it is not unusual to have
                         * no common commit.
                         */
-                       warning("no common commits");
+                       warning(_("no common commits"));
 
        if (args->stateless_rpc)
                packet_flush(fd[1]);
-       if (args->depth > 0)
+       if (args->deepen)
                setup_alternate_shallow(&shallow_lock, &alternate_shallow_file,
                                        NULL);
        else if (si->nr_ours || si->nr_theirs)
@@ -899,7 +924,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        else
                alternate_shallow_file = NULL;
        if (get_pack(args, fd, pack_lockfile))
-               die("git fetch-pack: fetch failed.");
+               die(_("git fetch-pack: fetch failed."));
 
  all_done:
        return ref;
@@ -958,7 +983,7 @@ static void update_shallow(struct fetch_pack_args *args,
        int *status;
        int i;
 
-       if (args->depth > 0 && alternate_shallow_file) {
+       if (args->deepen && alternate_shallow_file) {
                if (*alternate_shallow_file == '\0') { /* --unshallow */
                        unlink_or_warn(git_path_shallow());
                        rollback_lock_file(&shallow_lock);
@@ -1061,7 +1086,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
 
        if (!ref) {
                packet_flush(fd[1]);
-               die("no matching remote head");
+               die(_("no matching remote head"));
        }
        prepare_shallow_info(&si, shallow);
        ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
@@ -1071,3 +1096,26 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
        clear_shallow_info(&si);
        return ref_cpy;
 }
+
+int report_unmatched_refs(struct ref **sought, int nr_sought)
+{
+       int i, ret = 0;
+
+       for (i = 0; i < nr_sought; i++) {
+               if (!sought[i])
+                       continue;
+               switch (sought[i]->match_status) {
+               case REF_MATCHED:
+                       continue;
+               case REF_NOT_MATCHED:
+                       error(_("no such remote ref %s"), sought[i]->name);
+                       break;
+               case REF_UNADVERTISED_NOT_ALLOWED:
+                       error(_("Server does not allow request for unadvertised object %s"),
+                             sought[i]->name);
+                       break;
+               }
+               ret = 1;
+       }
+       return ret;
+}