Merge branch 'jk/check-connected-with-alternates'
authorJunio C Hamano <gitster@pobox.com>
Fri, 19 Jul 2019 18:30:21 +0000 (11:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Jul 2019 18:30:21 +0000 (11:30 -0700)
The tips of refs from the alternate object store can be used as
starting point for reachability computation now.

* jk/check-connected-with-alternates:
check_everything_connected: assume alternate ref tips are valid
object-store.h: move for_each_alternate_ref() from transport.h

1  2 
Documentation/rev-list-options.txt
builtin/receive-pack.c
object-store.h
revision.c
sha1-file.c
index 286fc163f14256f4f7ff4be7fba57cef963d2f75,90a2c027ea64fcc16ca4f270830628050ec542a1..bb1251c0364dc71880f6e63db7c6116ed859b90f
@@@ -182,6 -182,14 +182,14 @@@ explicitly
        Pretend as if all objects mentioned by reflogs are listed on the
        command line as `<commit>`.
  
+ --alternate-refs::
+       Pretend as if all objects mentioned as ref tips of alternate
+       repositories were listed on the command line. An alternate
+       repository is any repository whose object directory is specified
+       in `objects/info/alternates`.  The set of included objects may
+       be modified by `core.alternateRefsCommand`, etc. See
+       linkgit:git-config[1].
  --single-worktree::
        By default, all working trees will be examined by the
        following options when there are more than one (see
@@@ -708,16 -716,6 +716,16 @@@ ifdef::git-rev-list[
        Only useful with `--objects`; print the object IDs that are not
        in packs.
  
 +--object-names::
 +      Only useful with `--objects`; print the names of the object IDs
 +      that are found. This is the default behavior.
 +
 +--no-object-names::
 +      Only useful with `--objects`; does not print the names of the object
 +      IDs that are found. This inverts `--object-names`. This flag allows
 +      the output to be more easily parsed by commands such as
 +      linkgit:git-cat-file[1].
 +
  --filter=<filter-spec>::
        Only useful with one of the `--objects*`; omits objects (usually
        blobs) from the list of printed objects.  The '<filter-spec>'
diff --combined builtin/receive-pack.c
index 610eadf5f092a651fe3d04b07528f40f6adddafe,4ab6dc1037e174382d53b77d25bdb411353ed006..dcf385511f07dcd8efb5079077823b9df9d0d850
@@@ -12,7 -12,6 +12,6 @@@
  #include "object.h"
  #include "remote.h"
  #include "connect.h"
- #include "transport.h"
  #include "string-list.h"
  #include "sha1-array.h"
  #include "connected.h"
@@@ -1809,7 -1808,8 +1808,7 @@@ static const char *unpack_with_sideband
        return ret;
  }
  
 -static void prepare_shallow_update(struct command *commands,
 -                                 struct shallow_info *si)
 +static void prepare_shallow_update(struct shallow_info *si)
  {
        int i, j, k, bitmap_size = DIV_ROUND_UP(si->ref->nr, 32);
  
@@@ -1875,7 -1875,7 +1874,7 @@@ static void update_shallow_info(struct 
        si->ref = ref;
  
        if (shallow_update) {
 -              prepare_shallow_update(commands, si);
 +              prepare_shallow_update(si);
                return;
        }
  
@@@ -2042,7 -2042,7 +2041,7 @@@ int cmd_receive_pack(int argc, const ch
                        proc.git_cmd = 1;
                        proc.argv = argv_gc_auto;
  
 -                      close_all_packs(the_repository->objects);
 +                      close_object_store(the_repository->objects);
                        if (!start_command(&proc)) {
                                if (use_sideband)
                                        copy_to_sideband(proc.err, -1, NULL);
diff --combined object-store.h
index 49f56ab8d9608919808ecebe71b9deb30c53980b,74d6860a9f0be4cc56b1975226d62bafcdaa2dc2..7f7b3cdd806b756eefb86c7d116ba9a9a6c62558
@@@ -33,6 -33,8 +33,8 @@@ void prepare_alt_odb(struct repository 
  char *compute_alternate_path(const char *path, struct strbuf *err);
  typedef int alt_odb_fn(struct object_directory *, void *);
  int foreach_alt_odb(alt_odb_fn, void*);
+ typedef void alternate_ref_fn(const struct object_id *oid, void *);
+ void for_each_alternate_ref(alternate_ref_fn, void *);
  
  /*
   * Add the directory to the on-disk alternates file; the new entry will also
@@@ -277,14 -279,10 +279,14 @@@ struct object_info 
  #define OBJECT_INFO_IGNORE_LOOSE 16
  /*
   * Do not attempt to fetch the object if missing (even if fetch_is_missing is
 - * nonzero). This is meant for bulk prefetching of missing blobs in a partial
 - * clone. Implies OBJECT_INFO_QUICK.
 + * nonzero).
   */
 -#define OBJECT_INFO_FOR_PREFETCH (32 + OBJECT_INFO_QUICK)
 +#define OBJECT_INFO_SKIP_FETCH_OBJECT 32
 +/*
 + * This is meant for bulk prefetching of missing blobs in a partial
 + * clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK
 + */
 +#define OBJECT_INFO_FOR_PREFETCH (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK)
  
  int oid_object_info_extended(struct repository *r,
                             const struct object_id *,
diff --combined revision.c
index 621feb9df716400f32d016e1d36fc368b6a884fb,0d1a30a7d71bf6a8867103430c0ac4ce492769ca..07412297f0248aae886eeb77c3a1cab13c93039c
@@@ -436,9 -436,7 +436,9 @@@ static struct commit *handle_commit(str
                        die("unable to parse commit %s", name);
                if (flags & UNINTERESTING) {
                        mark_parents_uninteresting(commit);
 -                      revs->limited = 1;
 +
 +                      if (!revs->topo_order || !generation_numbers_enabled(the_repository))
 +                              revs->limited = 1;
                }
                if (revs->sources) {
                        char **slot = revision_sources_at(revs->sources, commit);
@@@ -1554,6 -1552,32 +1554,32 @@@ void add_index_objects_to_pending(struc
        free_worktrees(worktrees);
  }
  
+ struct add_alternate_refs_data {
+       struct rev_info *revs;
+       unsigned int flags;
+ };
+ static void add_one_alternate_ref(const struct object_id *oid,
+                                 void *vdata)
+ {
+       const char *name = ".alternate";
+       struct add_alternate_refs_data *data = vdata;
+       struct object *obj;
+       obj = get_reference(data->revs, name, oid, data->flags);
+       add_rev_cmdline(data->revs, obj, name, REV_CMD_REV, data->flags);
+       add_pending_object(data->revs, obj, name);
+ }
+ static void add_alternate_refs_to_pending(struct rev_info *revs,
+                                         unsigned int flags)
+ {
+       struct add_alternate_refs_data data;
+       data.revs = revs;
+       data.flags = flags;
+       for_each_alternate_ref(add_one_alternate_ref, &data);
+ }
  static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,
                            int exclude_parent)
  {
@@@ -1956,6 -1980,7 +1982,7 @@@ static int handle_revision_opt(struct r
            !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk") ||
            !strcmp(arg, "--bisect") || starts_with(arg, "--glob=") ||
            !strcmp(arg, "--indexed-objects") ||
+           !strcmp(arg, "--alternate-refs") ||
            starts_with(arg, "--exclude=") ||
            starts_with(arg, "--branches=") || starts_with(arg, "--tags=") ||
            starts_with(arg, "--remotes=") || starts_with(arg, "--no-walk="))
@@@ -2442,6 -2467,8 +2469,8 @@@ static int handle_revision_pseudo_opt(c
                add_reflogs_to_pending(revs, *flags);
        } else if (!strcmp(arg, "--indexed-objects")) {
                add_index_objects_to_pending(revs, *flags);
+       } else if (!strcmp(arg, "--alternate-refs")) {
+               add_alternate_refs_to_pending(revs, *flags);
        } else if (!strcmp(arg, "--not")) {
                *flags ^= UNINTERESTING | BOTTOM;
        } else if (!strcmp(arg, "--no-walk")) {
@@@ -3265,9 -3292,6 +3294,9 @@@ static void expand_topo_walk(struct rev
                struct commit *parent = p->item;
                int *pi;
  
 +              if (parent->object.flags & UNINTERESTING)
 +                      continue;
 +
                if (parse_commit_gently(parent, 1) < 0)
                        continue;
  
diff --combined sha1-file.c
index 59b2e40cf3e05897ee67d2de56c19c48dc49fcc9,ccd5bf30bd545d2e26ef9663a4163667c4500a1e..84fd02f107602411f3ceb460e4fe5b41c212bdec
@@@ -743,6 -743,103 +743,103 @@@ out
        return ref_git;
  }
  
+ static void fill_alternate_refs_command(struct child_process *cmd,
+                                       const char *repo_path)
+ {
+       const char *value;
+       if (!git_config_get_value("core.alternateRefsCommand", &value)) {
+               cmd->use_shell = 1;
+               argv_array_push(&cmd->args, value);
+               argv_array_push(&cmd->args, repo_path);
+       } else {
+               cmd->git_cmd = 1;
+               argv_array_pushf(&cmd->args, "--git-dir=%s", repo_path);
+               argv_array_push(&cmd->args, "for-each-ref");
+               argv_array_push(&cmd->args, "--format=%(objectname)");
+               if (!git_config_get_value("core.alternateRefsPrefixes", &value)) {
+                       argv_array_push(&cmd->args, "--");
+                       argv_array_split(&cmd->args, value);
+               }
+       }
+       cmd->env = local_repo_env;
+       cmd->out = -1;
+ }
+ static void read_alternate_refs(const char *path,
+                               alternate_ref_fn *cb,
+                               void *data)
+ {
+       struct child_process cmd = CHILD_PROCESS_INIT;
+       struct strbuf line = STRBUF_INIT;
+       FILE *fh;
+       fill_alternate_refs_command(&cmd, path);
+       if (start_command(&cmd))
+               return;
+       fh = xfdopen(cmd.out, "r");
+       while (strbuf_getline_lf(&line, fh) != EOF) {
+               struct object_id oid;
+               const char *p;
+               if (parse_oid_hex(line.buf, &oid, &p) || *p) {
+                       warning(_("invalid line while parsing alternate refs: %s"),
+                               line.buf);
+                       break;
+               }
+               cb(&oid, data);
+       }
+       fclose(fh);
+       finish_command(&cmd);
+ }
+ struct alternate_refs_data {
+       alternate_ref_fn *fn;
+       void *data;
+ };
+ static int refs_from_alternate_cb(struct object_directory *e,
+                                 void *data)
+ {
+       struct strbuf path = STRBUF_INIT;
+       size_t base_len;
+       struct alternate_refs_data *cb = data;
+       if (!strbuf_realpath(&path, e->path, 0))
+               goto out;
+       if (!strbuf_strip_suffix(&path, "/objects"))
+               goto out;
+       base_len = path.len;
+       /* Is this a git repository with refs? */
+       strbuf_addstr(&path, "/refs");
+       if (!is_directory(path.buf))
+               goto out;
+       strbuf_setlen(&path, base_len);
+       read_alternate_refs(path.buf, cb->fn, cb->data);
+ out:
+       strbuf_release(&path);
+       return 0;
+ }
+ void for_each_alternate_ref(alternate_ref_fn fn, void *data)
+ {
+       struct alternate_refs_data cb;
+       cb.fn = fn;
+       cb.data = data;
+       foreach_alt_odb(refs_from_alternate_cb, &cb);
+ }
  int foreach_alt_odb(alt_odb_fn fn, void *cb)
  {
        struct object_directory *ent;
@@@ -1379,7 -1476,7 +1476,7 @@@ int oid_object_info_extended(struct rep
                /* Check if it is a missing object */
                if (fetch_if_missing && repository_format_partial_clone &&
                    !already_retried && r == the_repository &&
 -                  !(flags & OBJECT_INFO_FOR_PREFETCH)) {
 +                  !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) {
                        /*
                         * TODO Investigate having fetch_object() return
                         * TODO error/success and stopping the music here.
@@@ -1505,8 -1602,7 +1602,8 @@@ void *read_object_file_extended(struct 
        return NULL;
  }
  
 -void *read_object_with_reference(const struct object_id *oid,
 +void *read_object_with_reference(struct repository *r,
 +                               const struct object_id *oid,
                                 const char *required_type_name,
                                 unsigned long *size,
                                 struct object_id *actual_oid_return)
                int ref_length = -1;
                const char *ref_type = NULL;
  
 -              buffer = read_object_file(&actual_oid, &type, &isize);
 +              buffer = repo_read_object_file(r, &actual_oid, &type, &isize);
                if (!buffer)
                        return NULL;
                if (type == required_type) {