submodule-config.con commit Sync with 2.15.3 (424aac6)
   1#include "cache.h"
   2#include "repository.h"
   3#include "config.h"
   4#include "submodule-config.h"
   5#include "submodule.h"
   6#include "strbuf.h"
   7#include "parse-options.h"
   8
   9/*
  10 * submodule cache lookup structure
  11 * There is one shared set of 'struct submodule' entries which can be
  12 * looked up by their sha1 blob id of the .gitmodules file and either
  13 * using path or name as key.
  14 * for_path stores submodule entries with path as key
  15 * for_name stores submodule entries with name as key
  16 */
  17struct submodule_cache {
  18        struct hashmap for_path;
  19        struct hashmap for_name;
  20        unsigned initialized:1;
  21        unsigned gitmodules_read:1;
  22};
  23
  24/*
  25 * thin wrapper struct needed to insert 'struct submodule' entries to
  26 * the hashmap
  27 */
  28struct submodule_entry {
  29        struct hashmap_entry ent;
  30        struct submodule *config;
  31};
  32
  33enum lookup_type {
  34        lookup_name,
  35        lookup_path
  36};
  37
  38static int config_path_cmp(const void *unused_cmp_data,
  39                           const void *entry,
  40                           const void *entry_or_key,
  41                           const void *unused_keydata)
  42{
  43        const struct submodule_entry *a = entry;
  44        const struct submodule_entry *b = entry_or_key;
  45
  46        return strcmp(a->config->path, b->config->path) ||
  47               hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
  48}
  49
  50static int config_name_cmp(const void *unused_cmp_data,
  51                           const void *entry,
  52                           const void *entry_or_key,
  53                           const void *unused_keydata)
  54{
  55        const struct submodule_entry *a = entry;
  56        const struct submodule_entry *b = entry_or_key;
  57
  58        return strcmp(a->config->name, b->config->name) ||
  59               hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);
  60}
  61
  62static struct submodule_cache *submodule_cache_alloc(void)
  63{
  64        return xcalloc(1, sizeof(struct submodule_cache));
  65}
  66
  67static void submodule_cache_init(struct submodule_cache *cache)
  68{
  69        hashmap_init(&cache->for_path, config_path_cmp, NULL, 0);
  70        hashmap_init(&cache->for_name, config_name_cmp, NULL, 0);
  71        cache->initialized = 1;
  72}
  73
  74static void free_one_config(struct submodule_entry *entry)
  75{
  76        free((void *) entry->config->path);
  77        free((void *) entry->config->name);
  78        free((void *) entry->config->branch);
  79        free((void *) entry->config->update_strategy.command);
  80        free(entry->config);
  81}
  82
  83static void submodule_cache_clear(struct submodule_cache *cache)
  84{
  85        struct hashmap_iter iter;
  86        struct submodule_entry *entry;
  87
  88        if (!cache->initialized)
  89                return;
  90
  91        /*
  92         * We iterate over the name hash here to be symmetric with the
  93         * allocation of struct submodule entries. Each is allocated by
  94         * their .gitmodules blob sha1 and submodule name.
  95         */
  96        hashmap_iter_init(&cache->for_name, &iter);
  97        while ((entry = hashmap_iter_next(&iter)))
  98                free_one_config(entry);
  99
 100        hashmap_free(&cache->for_path, 1);
 101        hashmap_free(&cache->for_name, 1);
 102        cache->initialized = 0;
 103        cache->gitmodules_read = 0;
 104}
 105
 106void submodule_cache_free(struct submodule_cache *cache)
 107{
 108        submodule_cache_clear(cache);
 109        free(cache);
 110}
 111
 112static unsigned int hash_sha1_string(const unsigned char *sha1,
 113                                     const char *string)
 114{
 115        return memhash(sha1, 20) + strhash(string);
 116}
 117
 118static void cache_put_path(struct submodule_cache *cache,
 119                           struct submodule *submodule)
 120{
 121        unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
 122                                             submodule->path);
 123        struct submodule_entry *e = xmalloc(sizeof(*e));
 124        hashmap_entry_init(e, hash);
 125        e->config = submodule;
 126        hashmap_put(&cache->for_path, e);
 127}
 128
 129static void cache_remove_path(struct submodule_cache *cache,
 130                              struct submodule *submodule)
 131{
 132        unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
 133                                             submodule->path);
 134        struct submodule_entry e;
 135        struct submodule_entry *removed;
 136        hashmap_entry_init(&e, hash);
 137        e.config = submodule;
 138        removed = hashmap_remove(&cache->for_path, &e, NULL);
 139        free(removed);
 140}
 141
 142static void cache_add(struct submodule_cache *cache,
 143                      struct submodule *submodule)
 144{
 145        unsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,
 146                                             submodule->name);
 147        struct submodule_entry *e = xmalloc(sizeof(*e));
 148        hashmap_entry_init(e, hash);
 149        e->config = submodule;
 150        hashmap_add(&cache->for_name, e);
 151}
 152
 153static const struct submodule *cache_lookup_path(struct submodule_cache *cache,
 154                const unsigned char *gitmodules_sha1, const char *path)
 155{
 156        struct submodule_entry *entry;
 157        unsigned int hash = hash_sha1_string(gitmodules_sha1, path);
 158        struct submodule_entry key;
 159        struct submodule key_config;
 160
 161        hashcpy(key_config.gitmodules_sha1, gitmodules_sha1);
 162        key_config.path = path;
 163
 164        hashmap_entry_init(&key, hash);
 165        key.config = &key_config;
 166
 167        entry = hashmap_get(&cache->for_path, &key, NULL);
 168        if (entry)
 169                return entry->config;
 170        return NULL;
 171}
 172
 173static struct submodule *cache_lookup_name(struct submodule_cache *cache,
 174                const unsigned char *gitmodules_sha1, const char *name)
 175{
 176        struct submodule_entry *entry;
 177        unsigned int hash = hash_sha1_string(gitmodules_sha1, name);
 178        struct submodule_entry key;
 179        struct submodule key_config;
 180
 181        hashcpy(key_config.gitmodules_sha1, gitmodules_sha1);
 182        key_config.name = name;
 183
 184        hashmap_entry_init(&key, hash);
 185        key.config = &key_config;
 186
 187        entry = hashmap_get(&cache->for_name, &key, NULL);
 188        if (entry)
 189                return entry->config;
 190        return NULL;
 191}
 192
 193int check_submodule_name(const char *name)
 194{
 195        /* Disallow empty names */
 196        if (!*name)
 197                return -1;
 198
 199        /*
 200         * Look for '..' as a path component. Check both '/' and '\\' as
 201         * separators rather than is_dir_sep(), because we want the name rules
 202         * to be consistent across platforms.
 203         */
 204        goto in_component; /* always start inside component */
 205        while (*name) {
 206                char c = *name++;
 207                if (c == '/' || c == '\\') {
 208in_component:
 209                        if (name[0] == '.' && name[1] == '.' &&
 210                            (!name[2] || name[2] == '/' || name[2] == '\\'))
 211                                return -1;
 212                }
 213        }
 214
 215        return 0;
 216}
 217
 218static int name_and_item_from_var(const char *var, struct strbuf *name,
 219                                  struct strbuf *item)
 220{
 221        const char *subsection, *key;
 222        int subsection_len, parse;
 223        parse = parse_config_key(var, "submodule", &subsection,
 224                        &subsection_len, &key);
 225        if (parse < 0 || !subsection)
 226                return 0;
 227
 228        strbuf_add(name, subsection, subsection_len);
 229        if (check_submodule_name(name->buf) < 0) {
 230                warning(_("ignoring suspicious submodule name: %s"), name->buf);
 231                strbuf_release(name);
 232                return 0;
 233        }
 234
 235        strbuf_addstr(item, key);
 236
 237        return 1;
 238}
 239
 240static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,
 241                const unsigned char *gitmodules_sha1, const char *name)
 242{
 243        struct submodule *submodule;
 244        struct strbuf name_buf = STRBUF_INIT;
 245
 246        submodule = cache_lookup_name(cache, gitmodules_sha1, name);
 247        if (submodule)
 248                return submodule;
 249
 250        submodule = xmalloc(sizeof(*submodule));
 251
 252        strbuf_addstr(&name_buf, name);
 253        submodule->name = strbuf_detach(&name_buf, NULL);
 254
 255        submodule->path = NULL;
 256        submodule->url = NULL;
 257        submodule->update_strategy.type = SM_UPDATE_UNSPECIFIED;
 258        submodule->update_strategy.command = NULL;
 259        submodule->fetch_recurse = RECURSE_SUBMODULES_NONE;
 260        submodule->ignore = NULL;
 261        submodule->branch = NULL;
 262        submodule->recommend_shallow = -1;
 263
 264        hashcpy(submodule->gitmodules_sha1, gitmodules_sha1);
 265
 266        cache_add(cache, submodule);
 267
 268        return submodule;
 269}
 270
 271static int parse_fetch_recurse(const char *opt, const char *arg,
 272                               int die_on_error)
 273{
 274        switch (git_parse_maybe_bool(arg)) {
 275        case 1:
 276                return RECURSE_SUBMODULES_ON;
 277        case 0:
 278                return RECURSE_SUBMODULES_OFF;
 279        default:
 280                if (!strcmp(arg, "on-demand"))
 281                        return RECURSE_SUBMODULES_ON_DEMAND;
 282
 283                if (die_on_error)
 284                        die("bad %s argument: %s", opt, arg);
 285                else
 286                        return RECURSE_SUBMODULES_ERROR;
 287        }
 288}
 289
 290int parse_submodule_fetchjobs(const char *var, const char *value)
 291{
 292        int fetchjobs = git_config_int(var, value);
 293        if (fetchjobs < 0)
 294                die(_("negative values not allowed for submodule.fetchjobs"));
 295        return fetchjobs;
 296}
 297
 298int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
 299{
 300        return parse_fetch_recurse(opt, arg, 1);
 301}
 302
 303int option_fetch_parse_recurse_submodules(const struct option *opt,
 304                                          const char *arg, int unset)
 305{
 306        int *v;
 307
 308        if (!opt->value)
 309                return -1;
 310
 311        v = opt->value;
 312
 313        if (unset) {
 314                *v = RECURSE_SUBMODULES_OFF;
 315        } else {
 316                if (arg)
 317                        *v = parse_fetch_recurse_submodules_arg(opt->long_name, arg);
 318                else
 319                        *v = RECURSE_SUBMODULES_ON;
 320        }
 321        return 0;
 322}
 323
 324static int parse_update_recurse(const char *opt, const char *arg,
 325                                int die_on_error)
 326{
 327        switch (git_parse_maybe_bool(arg)) {
 328        case 1:
 329                return RECURSE_SUBMODULES_ON;
 330        case 0:
 331                return RECURSE_SUBMODULES_OFF;
 332        default:
 333                if (die_on_error)
 334                        die("bad %s argument: %s", opt, arg);
 335                return RECURSE_SUBMODULES_ERROR;
 336        }
 337}
 338
 339int parse_update_recurse_submodules_arg(const char *opt, const char *arg)
 340{
 341        return parse_update_recurse(opt, arg, 1);
 342}
 343
 344static int parse_push_recurse(const char *opt, const char *arg,
 345                               int die_on_error)
 346{
 347        switch (git_parse_maybe_bool(arg)) {
 348        case 1:
 349                /* There's no simple "on" value when pushing */
 350                if (die_on_error)
 351                        die("bad %s argument: %s", opt, arg);
 352                else
 353                        return RECURSE_SUBMODULES_ERROR;
 354        case 0:
 355                return RECURSE_SUBMODULES_OFF;
 356        default:
 357                if (!strcmp(arg, "on-demand"))
 358                        return RECURSE_SUBMODULES_ON_DEMAND;
 359                else if (!strcmp(arg, "check"))
 360                        return RECURSE_SUBMODULES_CHECK;
 361                else if (!strcmp(arg, "only"))
 362                        return RECURSE_SUBMODULES_ONLY;
 363                else if (die_on_error)
 364                        die("bad %s argument: %s", opt, arg);
 365                else
 366                        return RECURSE_SUBMODULES_ERROR;
 367        }
 368}
 369
 370int parse_push_recurse_submodules_arg(const char *opt, const char *arg)
 371{
 372        return parse_push_recurse(opt, arg, 1);
 373}
 374
 375static void warn_multiple_config(const unsigned char *treeish_name,
 376                                 const char *name, const char *option)
 377{
 378        const char *commit_string = "WORKTREE";
 379        if (treeish_name)
 380                commit_string = sha1_to_hex(treeish_name);
 381        warning("%s:.gitmodules, multiple configurations found for "
 382                        "'submodule.%s.%s'. Skipping second one!",
 383                        commit_string, name, option);
 384}
 385
 386static void warn_command_line_option(const char *var, const char *value)
 387{
 388        warning(_("ignoring '%s' which may be interpreted as"
 389                  " a command-line option: %s"), var, value);
 390}
 391
 392struct parse_config_parameter {
 393        struct submodule_cache *cache;
 394        const unsigned char *treeish_name;
 395        const unsigned char *gitmodules_sha1;
 396        int overwrite;
 397};
 398
 399static int parse_config(const char *var, const char *value, void *data)
 400{
 401        struct parse_config_parameter *me = data;
 402        struct submodule *submodule;
 403        struct strbuf name = STRBUF_INIT, item = STRBUF_INIT;
 404        int ret = 0;
 405
 406        /* this also ensures that we only parse submodule entries */
 407        if (!name_and_item_from_var(var, &name, &item))
 408                return 0;
 409
 410        submodule = lookup_or_create_by_name(me->cache,
 411                                             me->gitmodules_sha1,
 412                                             name.buf);
 413
 414        if (!strcmp(item.buf, "path")) {
 415                if (!value)
 416                        ret = config_error_nonbool(var);
 417                else if (looks_like_command_line_option(value))
 418                        warn_command_line_option(var, value);
 419                else if (!me->overwrite && submodule->path)
 420                        warn_multiple_config(me->treeish_name, submodule->name,
 421                                        "path");
 422                else {
 423                        if (submodule->path)
 424                                cache_remove_path(me->cache, submodule);
 425                        free((void *) submodule->path);
 426                        submodule->path = xstrdup(value);
 427                        cache_put_path(me->cache, submodule);
 428                }
 429        } else if (!strcmp(item.buf, "fetchrecursesubmodules")) {
 430                /* when parsing worktree configurations we can die early */
 431                int die_on_error = is_null_sha1(me->gitmodules_sha1);
 432                if (!me->overwrite &&
 433                    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE)
 434                        warn_multiple_config(me->treeish_name, submodule->name,
 435                                        "fetchrecursesubmodules");
 436                else
 437                        submodule->fetch_recurse = parse_fetch_recurse(
 438                                                                var, value,
 439                                                                die_on_error);
 440        } else if (!strcmp(item.buf, "ignore")) {
 441                if (!value)
 442                        ret = config_error_nonbool(var);
 443                else if (!me->overwrite && submodule->ignore)
 444                        warn_multiple_config(me->treeish_name, submodule->name,
 445                                        "ignore");
 446                else if (strcmp(value, "untracked") &&
 447                         strcmp(value, "dirty") &&
 448                         strcmp(value, "all") &&
 449                         strcmp(value, "none"))
 450                        warning("Invalid parameter '%s' for config option "
 451                                        "'submodule.%s.ignore'", value, name.buf);
 452                else {
 453                        free((void *) submodule->ignore);
 454                        submodule->ignore = xstrdup(value);
 455                }
 456        } else if (!strcmp(item.buf, "url")) {
 457                if (!value) {
 458                        ret = config_error_nonbool(var);
 459                } else if (looks_like_command_line_option(value)) {
 460                        warn_command_line_option(var, value);
 461                } else if (!me->overwrite && submodule->url) {
 462                        warn_multiple_config(me->treeish_name, submodule->name,
 463                                        "url");
 464                } else {
 465                        free((void *) submodule->url);
 466                        submodule->url = xstrdup(value);
 467                }
 468        } else if (!strcmp(item.buf, "update")) {
 469                if (!value)
 470                        ret = config_error_nonbool(var);
 471                else if (!me->overwrite &&
 472                         submodule->update_strategy.type != SM_UPDATE_UNSPECIFIED)
 473                        warn_multiple_config(me->treeish_name, submodule->name,
 474                                             "update");
 475                else if (parse_submodule_update_strategy(value,
 476                         &submodule->update_strategy) < 0)
 477                                die(_("invalid value for %s"), var);
 478        } else if (!strcmp(item.buf, "shallow")) {
 479                if (!me->overwrite && submodule->recommend_shallow != -1)
 480                        warn_multiple_config(me->treeish_name, submodule->name,
 481                                             "shallow");
 482                else
 483                        submodule->recommend_shallow =
 484                                git_config_bool(var, value);
 485        } else if (!strcmp(item.buf, "branch")) {
 486                if (!me->overwrite && submodule->branch)
 487                        warn_multiple_config(me->treeish_name, submodule->name,
 488                                             "branch");
 489                else {
 490                        free((void *)submodule->branch);
 491                        submodule->branch = xstrdup(value);
 492                }
 493        }
 494
 495        strbuf_release(&name);
 496        strbuf_release(&item);
 497
 498        return ret;
 499}
 500
 501static int gitmodule_oid_from_commit(const struct object_id *treeish_name,
 502                                     struct object_id *gitmodules_oid,
 503                                     struct strbuf *rev)
 504{
 505        int ret = 0;
 506
 507        if (is_null_oid(treeish_name)) {
 508                oidclr(gitmodules_oid);
 509                return 1;
 510        }
 511
 512        strbuf_addf(rev, "%s:.gitmodules", oid_to_hex(treeish_name));
 513        if (get_oid(rev->buf, gitmodules_oid) >= 0)
 514                ret = 1;
 515
 516        return ret;
 517}
 518
 519/* This does a lookup of a submodule configuration by name or by path
 520 * (key) with on-demand reading of the appropriate .gitmodules from
 521 * revisions.
 522 */
 523static const struct submodule *config_from(struct submodule_cache *cache,
 524                const struct object_id *treeish_name, const char *key,
 525                enum lookup_type lookup_type)
 526{
 527        struct strbuf rev = STRBUF_INIT;
 528        unsigned long config_size;
 529        char *config = NULL;
 530        struct object_id oid;
 531        enum object_type type;
 532        const struct submodule *submodule = NULL;
 533        struct parse_config_parameter parameter;
 534
 535        /*
 536         * If any parameter except the cache is a NULL pointer just
 537         * return the first submodule. Can be used to check whether
 538         * there are any submodules parsed.
 539         */
 540        if (!treeish_name || !key) {
 541                struct hashmap_iter iter;
 542                struct submodule_entry *entry;
 543
 544                entry = hashmap_iter_first(&cache->for_name, &iter);
 545                if (!entry)
 546                        return NULL;
 547                return entry->config;
 548        }
 549
 550        if (!gitmodule_oid_from_commit(treeish_name, &oid, &rev))
 551                goto out;
 552
 553        switch (lookup_type) {
 554        case lookup_name:
 555                submodule = cache_lookup_name(cache, oid.hash, key);
 556                break;
 557        case lookup_path:
 558                submodule = cache_lookup_path(cache, oid.hash, key);
 559                break;
 560        }
 561        if (submodule)
 562                goto out;
 563
 564        config = read_sha1_file(oid.hash, &type, &config_size);
 565        if (!config || type != OBJ_BLOB)
 566                goto out;
 567
 568        /* fill the submodule config into the cache */
 569        parameter.cache = cache;
 570        parameter.treeish_name = treeish_name->hash;
 571        parameter.gitmodules_sha1 = oid.hash;
 572        parameter.overwrite = 0;
 573        git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
 574                        config, config_size, &parameter);
 575        strbuf_release(&rev);
 576        free(config);
 577
 578        switch (lookup_type) {
 579        case lookup_name:
 580                return cache_lookup_name(cache, oid.hash, key);
 581        case lookup_path:
 582                return cache_lookup_path(cache, oid.hash, key);
 583        default:
 584                return NULL;
 585        }
 586
 587out:
 588        strbuf_release(&rev);
 589        free(config);
 590        return submodule;
 591}
 592
 593static void submodule_cache_check_init(struct repository *repo)
 594{
 595        if (repo->submodule_cache && repo->submodule_cache->initialized)
 596                return;
 597
 598        if (!repo->submodule_cache)
 599                repo->submodule_cache = submodule_cache_alloc();
 600
 601        submodule_cache_init(repo->submodule_cache);
 602}
 603
 604static int gitmodules_cb(const char *var, const char *value, void *data)
 605{
 606        struct repository *repo = data;
 607        struct parse_config_parameter parameter;
 608
 609        parameter.cache = repo->submodule_cache;
 610        parameter.treeish_name = NULL;
 611        parameter.gitmodules_sha1 = null_sha1;
 612        parameter.overwrite = 1;
 613
 614        return parse_config(var, value, &parameter);
 615}
 616
 617void repo_read_gitmodules(struct repository *repo)
 618{
 619        submodule_cache_check_init(repo);
 620
 621        if (repo->worktree) {
 622                char *gitmodules;
 623
 624                if (repo_read_index(repo) < 0)
 625                        return;
 626
 627                gitmodules = repo_worktree_path(repo, GITMODULES_FILE);
 628
 629                if (!is_gitmodules_unmerged(repo->index))
 630                        git_config_from_file(gitmodules_cb, gitmodules, repo);
 631
 632                free(gitmodules);
 633        }
 634
 635        repo->submodule_cache->gitmodules_read = 1;
 636}
 637
 638void gitmodules_config_oid(const struct object_id *commit_oid)
 639{
 640        struct strbuf rev = STRBUF_INIT;
 641        struct object_id oid;
 642
 643        submodule_cache_check_init(the_repository);
 644
 645        if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) {
 646                git_config_from_blob_oid(gitmodules_cb, rev.buf,
 647                                         &oid, the_repository);
 648        }
 649        strbuf_release(&rev);
 650
 651        the_repository->submodule_cache->gitmodules_read = 1;
 652}
 653
 654static void gitmodules_read_check(struct repository *repo)
 655{
 656        submodule_cache_check_init(repo);
 657
 658        /* read the repo's .gitmodules file if it hasn't been already */
 659        if (!repo->submodule_cache->gitmodules_read)
 660                repo_read_gitmodules(repo);
 661}
 662
 663const struct submodule *submodule_from_name(const struct object_id *treeish_name,
 664                const char *name)
 665{
 666        gitmodules_read_check(the_repository);
 667        return config_from(the_repository->submodule_cache, treeish_name, name, lookup_name);
 668}
 669
 670const struct submodule *submodule_from_path(const struct object_id *treeish_name,
 671                const char *path)
 672{
 673        gitmodules_read_check(the_repository);
 674        return config_from(the_repository->submodule_cache, treeish_name, path, lookup_path);
 675}
 676
 677const struct submodule *submodule_from_cache(struct repository *repo,
 678                                             const struct object_id *treeish_name,
 679                                             const char *key)
 680{
 681        gitmodules_read_check(repo);
 682        return config_from(repo->submodule_cache, treeish_name,
 683                           key, lookup_path);
 684}
 685
 686void submodule_free(void)
 687{
 688        if (the_repository->submodule_cache)
 689                submodule_cache_clear(the_repository->submodule_cache);
 690}