handle_revision_arg: add handle_dotdot() helper
[gitweb.git] / fetch-pack.c
index e0f5d5ce875acad79b5ddcfc4e24b6ff8bc33df9..afb8b05024823981be9bedfaa70f7301c6f7076c 100644 (file)
@@ -276,6 +276,8 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1)
                        return ACK;
                }
        }
+       if (skip_prefix(line, "ERR ", &arg))
+               die(_("remote error: %s"), arg);
        die(_("git fetch-pack: expected ACK/NAK, got '%s'"), line);
 }
 
@@ -614,7 +616,7 @@ 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++;
                        }
@@ -634,22 +636,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;
@@ -800,8 +804,8 @@ static int get_pack(struct fetch_pack_args *args,
                if (args->use_thin_pack)
                        argv_array_push(&cmd.args, "--fix-thin");
                if (args->lock_pack || unpack_limit) {
-                       char hostname[256];
-                       if (gethostname(hostname, sizeof(hostname)))
+                       char hostname[HOST_NAME_MAX + 1];
+                       if (xgethostname(hostname, sizeof(hostname)))
                                xsnprintf(hostname, sizeof(hostname), "localhost");
                        argv_array_pushf(&cmd.args,
                                        "--keep=fetch-pack %"PRIuMAX " on %s",
@@ -1013,7 +1017,7 @@ static void update_shallow(struct fetch_pack_args *args,
                           struct ref **sought, int nr_sought,
                           struct shallow_info *si)
 {
-       struct sha1_array ref = SHA1_ARRAY_INIT;
+       struct oid_array ref = OID_ARRAY_INIT;
        int *status;
        int i;
 
@@ -1036,18 +1040,18 @@ static void update_shallow(struct fetch_pack_args *args,
                 * shallow points that exist in the pack (iow in repo
                 * after get_pack() and reprepare_packed_git())
                 */
-               struct sha1_array extra = SHA1_ARRAY_INIT;
-               unsigned char (*sha1)[20] = si->shallow->sha1;
+               struct oid_array extra = OID_ARRAY_INIT;
+               struct object_id *oid = si->shallow->oid;
                for (i = 0; i < si->shallow->nr; i++)
-                       if (has_sha1_file(sha1[i]))
-                               sha1_array_append(&extra, sha1[i]);
+                       if (has_object_file(&oid[i]))
+                               oid_array_append(&extra, &oid[i]);
                if (extra.nr) {
                        setup_alternate_shallow(&shallow_lock,
                                                &alternate_shallow_file,
                                                &extra);
                        commit_lock_file(&shallow_lock);
                }
-               sha1_array_clear(&extra);
+               oid_array_clear(&extra);
                return;
        }
 
@@ -1058,7 +1062,7 @@ static void update_shallow(struct fetch_pack_args *args,
        if (!si->nr_ours && !si->nr_theirs)
                return;
        for (i = 0; i < nr_sought; i++)
-               sha1_array_append(&ref, sought[i]->old_oid.hash);
+               oid_array_append(&ref, &sought[i]->old_oid);
        si->ref = &ref;
 
        if (args->update_shallow) {
@@ -1068,23 +1072,23 @@ static void update_shallow(struct fetch_pack_args *args,
                 * shallow roots that are actually reachable from new
                 * refs.
                 */
-               struct sha1_array extra = SHA1_ARRAY_INIT;
-               unsigned char (*sha1)[20] = si->shallow->sha1;
+               struct oid_array extra = OID_ARRAY_INIT;
+               struct object_id *oid = si->shallow->oid;
                assign_shallow_commits_to_refs(si, NULL, NULL);
                if (!si->nr_ours && !si->nr_theirs) {
-                       sha1_array_clear(&ref);
+                       oid_array_clear(&ref);
                        return;
                }
                for (i = 0; i < si->nr_ours; i++)
-                       sha1_array_append(&extra, sha1[si->ours[i]]);
+                       oid_array_append(&extra, &oid[si->ours[i]]);
                for (i = 0; i < si->nr_theirs; i++)
-                       sha1_array_append(&extra, sha1[si->theirs[i]]);
+                       oid_array_append(&extra, &oid[si->theirs[i]]);
                setup_alternate_shallow(&shallow_lock,
                                        &alternate_shallow_file,
                                        &extra);
                commit_lock_file(&shallow_lock);
-               sha1_array_clear(&extra);
-               sha1_array_clear(&ref);
+               oid_array_clear(&extra);
+               oid_array_clear(&ref);
                return;
        }
 
@@ -1100,7 +1104,7 @@ static void update_shallow(struct fetch_pack_args *args,
                                sought[i]->status = REF_STATUS_REJECT_SHALLOW;
        }
        free(status);
-       sha1_array_clear(&ref);
+       oid_array_clear(&ref);
 }
 
 struct ref *fetch_pack(struct fetch_pack_args *args,
@@ -1108,7 +1112,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
                       const struct ref *ref,
                       const char *dest,
                       struct ref **sought, int nr_sought,
-                      struct sha1_array *shallow,
+                      struct oid_array *shallow,
                       char **pack_lockfile)
 {
        struct ref *ref_cpy;
@@ -1130,3 +1134,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;
+}