promisor-remote.con commit remote: add promisor and partial clone config to the doc (75de085)
   1#include "cache.h"
   2#include "object-store.h"
   3#include "promisor-remote.h"
   4#include "config.h"
   5#include "fetch-object.h"
   6
   7static struct promisor_remote *promisors;
   8static struct promisor_remote **promisors_tail = &promisors;
   9
  10static struct promisor_remote *promisor_remote_new(const char *remote_name)
  11{
  12        struct promisor_remote *r;
  13
  14        if (*remote_name == '/') {
  15                warning(_("promisor remote name cannot begin with '/': %s"),
  16                        remote_name);
  17                return NULL;
  18        }
  19
  20        FLEX_ALLOC_STR(r, name, remote_name);
  21
  22        *promisors_tail = r;
  23        promisors_tail = &r->next;
  24
  25        return r;
  26}
  27
  28static struct promisor_remote *promisor_remote_lookup(const char *remote_name,
  29                                                      struct promisor_remote **previous)
  30{
  31        struct promisor_remote *r, *p;
  32
  33        for (p = NULL, r = promisors; r; p = r, r = r->next)
  34                if (!strcmp(r->name, remote_name)) {
  35                        if (previous)
  36                                *previous = p;
  37                        return r;
  38                }
  39
  40        return NULL;
  41}
  42
  43static void promisor_remote_move_to_tail(struct promisor_remote *r,
  44                                         struct promisor_remote *previous)
  45{
  46        if (previous)
  47                previous->next = r->next;
  48        else
  49                promisors = r->next ? r->next : r;
  50        r->next = NULL;
  51        *promisors_tail = r;
  52        promisors_tail = &r->next;
  53}
  54
  55static int promisor_remote_config(const char *var, const char *value, void *data)
  56{
  57        const char *name;
  58        int namelen;
  59        const char *subkey;
  60
  61        if (parse_config_key(var, "remote", &name, &namelen, &subkey) < 0)
  62                return 0;
  63
  64        if (!strcmp(subkey, "promisor")) {
  65                char *remote_name;
  66
  67                if (!git_config_bool(var, value))
  68                        return 0;
  69
  70                remote_name = xmemdupz(name, namelen);
  71
  72                if (!promisor_remote_lookup(remote_name, NULL))
  73                        promisor_remote_new(remote_name);
  74
  75                free(remote_name);
  76                return 0;
  77        }
  78        if (!strcmp(subkey, "partialclonefilter")) {
  79                struct promisor_remote *r;
  80                char *remote_name = xmemdupz(name, namelen);
  81
  82                r = promisor_remote_lookup(remote_name, NULL);
  83                if (!r)
  84                        r = promisor_remote_new(remote_name);
  85
  86                free(remote_name);
  87
  88                if (!r)
  89                        return 0;
  90
  91                return git_config_string(&r->partial_clone_filter, var, value);
  92        }
  93
  94        return 0;
  95}
  96
  97static int initialized;
  98
  99static void promisor_remote_init(void)
 100{
 101        if (initialized)
 102                return;
 103        initialized = 1;
 104
 105        git_config(promisor_remote_config, NULL);
 106
 107        if (repository_format_partial_clone) {
 108                struct promisor_remote *o, *previous;
 109
 110                o = promisor_remote_lookup(repository_format_partial_clone,
 111                                           &previous);
 112                if (o)
 113                        promisor_remote_move_to_tail(o, previous);
 114                else
 115                        promisor_remote_new(repository_format_partial_clone);
 116        }
 117}
 118
 119static void promisor_remote_clear(void)
 120{
 121        while (promisors) {
 122                struct promisor_remote *r = promisors;
 123                promisors = promisors->next;
 124                free(r);
 125        }
 126
 127        promisors_tail = &promisors;
 128}
 129
 130void promisor_remote_reinit(void)
 131{
 132        initialized = 0;
 133        promisor_remote_clear();
 134        promisor_remote_init();
 135}
 136
 137struct promisor_remote *promisor_remote_find(const char *remote_name)
 138{
 139        promisor_remote_init();
 140
 141        if (!remote_name)
 142                return promisors;
 143
 144        return promisor_remote_lookup(remote_name, NULL);
 145}
 146
 147int has_promisor_remote(void)
 148{
 149        return !!promisor_remote_find(NULL);
 150}
 151
 152static int remove_fetched_oids(struct repository *repo,
 153                               struct object_id **oids,
 154                               int oid_nr, int to_free)
 155{
 156        int i, remaining_nr = 0;
 157        int *remaining = xcalloc(oid_nr, sizeof(*remaining));
 158        struct object_id *old_oids = *oids;
 159        struct object_id *new_oids;
 160
 161        for (i = 0; i < oid_nr; i++)
 162                if (oid_object_info_extended(repo, &old_oids[i], NULL,
 163                                             OBJECT_INFO_SKIP_FETCH_OBJECT)) {
 164                        remaining[i] = 1;
 165                        remaining_nr++;
 166                }
 167
 168        if (remaining_nr) {
 169                int j = 0;
 170                new_oids = xcalloc(remaining_nr, sizeof(*new_oids));
 171                for (i = 0; i < oid_nr; i++)
 172                        if (remaining[i])
 173                                oidcpy(&new_oids[j++], &old_oids[i]);
 174                *oids = new_oids;
 175                if (to_free)
 176                        free(old_oids);
 177        }
 178
 179        free(remaining);
 180
 181        return remaining_nr;
 182}
 183
 184int promisor_remote_get_direct(struct repository *repo,
 185                               const struct object_id *oids,
 186                               int oid_nr)
 187{
 188        struct promisor_remote *r;
 189        struct object_id *remaining_oids = (struct object_id *)oids;
 190        int remaining_nr = oid_nr;
 191        int to_free = 0;
 192        int res = -1;
 193
 194        promisor_remote_init();
 195
 196        for (r = promisors; r; r = r->next) {
 197                if (fetch_objects(r->name, remaining_oids, remaining_nr) < 0) {
 198                        if (remaining_nr == 1)
 199                                continue;
 200                        remaining_nr = remove_fetched_oids(repo, &remaining_oids,
 201                                                         remaining_nr, to_free);
 202                        if (remaining_nr) {
 203                                to_free = 1;
 204                                continue;
 205                        }
 206                }
 207                res = 0;
 208                break;
 209        }
 210
 211        if (to_free)
 212                free(remaining_oids);
 213
 214        return res;
 215}