Remove `the_repository` global variable in favor of the repository argument that gets passed in builtin commands. These sets of commands are commands that use only RUN_SETUP macro in "git.c". Basically, When `-h` is passed to any of this command outside a Git repository, the `run_builtin()` will call the `cmd_x()` function (where `x` is any of the command from the sets of builtin commands that `the_repository` is removed from) with `repo` set to NULL and then early in the function, `parse_options()` or show_usage_with_options_if_asked() call will give the options help and exit. Some, functions also uses `the_repository` global internally, so, let's let's refactor them and pass `struct repo` as one of the argument. As the `repo` value can be NULL if a builtin command is run outside any repository. The current implementation of `repo_config()` will fail if `repo` is NULL. If the `repo` is NULL, the `repo_config()` can ignore the repository configuration but it should read the other configuration sources like the system-side configuration instead of failing. Teach the `repo_config()` to allow `repo` to be NULL by calling the `read_very_early_config()` which read config but only enumerate system and global settings. This make it possible for us to savely replace `git_config()` with `repo_config()`. Changes since v2 ================ - Remove preparatory patches that move the `git_config()` below the `usage_with_options()`. - Add a new preparatory patch that teach the `repo_config()` to accept NULL value for `repo` variable. - Add tests to each of the builtin function in this commit to ensure `repo_config()` works as expected. - Make changes to the commit messages. Usman Akinyemi (8): config: teach repo_config to allow `repo` to be NULL builtin/verify-tag: stop using `the_repository` builtin/verify-commit: stop using `the_repository` builtin/send-pack: stop using `the_repository` builtin/pack-refs: stop using `the_repository` builtin/ls-files: stop using `the_repository` builtin/for-each-ref: stop using `the_repository` builtin/checkout-index: stop using `the_repository` builtin/checkout-index.c | 43 ++++++++++++++++----------------- builtin/for-each-ref.c | 5 ++-- builtin/ls-files.c | 32 ++++++++++++------------ builtin/pack-refs.c | 8 +++--- builtin/send-pack.c | 7 +++--- builtin/verify-commit.c | 13 +++++----- builtin/verify-tag.c | 7 +++--- config.c | 4 +++ config.h | 3 +++ t/t0610-reftable-basics.sh | 7 ++++++ t/t2006-checkout-index-basic.sh | 7 ++++++ t/t3004-ls-files-basic.sh | 7 ++++++ t/t5400-send-pack.sh | 7 ++++++ t/t6300-for-each-ref.sh | 7 ++++++ t/t7030-verify-tag.sh | 7 ++++++ t/t7510-signed-commit.sh | 7 ++++++ 16 files changed, 110 insertions(+), 61 deletions(-) Range-diff versus v2: 1: a313f9afb7 < -: ---------- builtin/verify-tag: refactor `cmd_verify_tag()` -: ---------- > 1: a5c69f3753 config: teach repo_config to allow `repo` to be NULL 2: f993160d90 ! 2: dfa0da4061 builtin/verify-tag: stop using `the_repository` @@ Commit message When `-h` is passed to the command outside a Git repository, the `run_builtin()` will call the `cmd_verify_tag()` function with `repo` set to NULL and then early in the function, `parse_options()` call will give - the options help and exit, without having to consult much of the - configuration file. + the options help and exit. Mentored-by: Christian Couder <chriscool@xxxxxxxxxxxxx> Signed-off-by: Usman Akinyemi <usmanakinyemi202@xxxxxxxxx> @@ builtin/verify-tag.c: static const char * const verify_tag_usage[] = { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ builtin/verify-tag.c: int cmd_verify_tag(int argc, - flags |= GPG_VERIFY_OMIT_STATUS; - } + OPT_END() + }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); - while (i < argc) { + argc = parse_options(argc, argv, prefix, verify_tag_options, + verify_tag_usage, PARSE_OPT_KEEP_ARGV0); +@@ builtin/verify-tag.c: int cmd_verify_tag(int argc, struct object_id oid; const char *name = argv[i++]; @@ builtin/verify-tag.c: int cmd_verify_tag(int argc, had_error = !!error("tag '%s' not found.", name); continue; } + + ## t/t7030-verify-tag.sh ## +@@ t/t7030-verify-tag.sh: export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + . ./test-lib.sh + . "$TEST_DIRECTORY/lib-gpg.sh" + ++test_expect_success GPG 'verify-tag does not crash with -h' ' ++ test_expect_code 129 git verify-tag -h >usage && ++ test_grep "[Uu]sage: git verify-tag " usage && ++ test_expect_code 129 nongit git verify-tag -h >usage && ++ test_grep "[Uu]sage: git verify-tag " usage ++' ++ + test_expect_success GPG 'create signed tags' ' + echo 1 >file && git add file && + test_tick && git commit -m initial && 3: f2f785190d < -: ---------- builtin/verify-commit: refactor `cmd_verify_commit()` 4: 5f8dc0c0ec ! 3: ade2d026cb builtin/verify-commit: stop using `the_repository` @@ Commit message When `-h` is passed to the command outside a Git repository, the `run_builtin()` will call the `cmd_verify_commit()` function with `repo` set to NULL and then early in the function, `parse_options()` call will - give the options help and exit, without having to consult much of the - configuration file. + give the options help and exit. Pass the repository available in the calling context to `verify_commit()` to remove it's dependency on the global `the_repository` variable. @@ builtin/verify-commit.c: static int verify_commit(const char *name, unsigned fla int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ builtin/verify-commit.c: int cmd_verify_commit(int argc, - if (verbose) - flags |= GPG_VERIFY_VERBOSE; + OPT_END() + }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); - /* sometimes the program was terminated because this signal + argc = parse_options(argc, argv, prefix, verify_commit_options, + verify_commit_usage, PARSE_OPT_KEEP_ARGV0); +@@ builtin/verify-commit.c: int cmd_verify_commit(int argc, * was received in the process of writing the gpg input: */ signal(SIGPIPE, SIG_IGN); while (i < argc) @@ builtin/verify-commit.c: int cmd_verify_commit(int argc, had_error = 1; return had_error; } + + ## t/t7510-signed-commit.sh ## +@@ t/t7510-signed-commit.sh: export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + GNUPGHOME_NOT_USED=$GNUPGHOME + . "$TEST_DIRECTORY/lib-gpg.sh" + ++test_expect_success GPG 'verify-commit does not crash with -h' ' ++ test_expect_code 129 git verify-commit -h >usage && ++ test_grep "[Uu]sage: git verify-commit " usage && ++ test_expect_code 129 nongit git verify-commit -h >usage && ++ test_grep "[Uu]sage: git verify-commit " usage ++' ++ + test_expect_success GPG 'create signed commits' ' + test_oid_cache <<-\EOF && + header sha1:gpgsig 5: d79c3fc1ee < -: ---------- builtin/send-pack: refactor `cmd_send_pack()` 6: f280a9c387 ! 4: e3b58bc6cf builtin/send-pack: stop using `the_repository` @@ Commit message When `-h` is passed to the command outside a Git repository, the `run_builtin()` will call the `cmd_send_pack()` function with `repo` set to NULL and then early in the function, `parse_options()` call will give - the options help and exit, without having to consult much of the - configuration file. + the options help and exit. Mentored-by: Christian Couder <chriscool@xxxxxxxxxxxxx> Signed-off-by: Usman Akinyemi <usmanakinyemi202@xxxxxxxxx> @@ builtin/send-pack.c: static int send_pack_config(const char *k, const char *v, struct refspec rs = REFSPEC_INIT_PUSH; const char *remote_name = NULL; @@ builtin/send-pack.c: int cmd_send_pack(int argc, - if (!dest) - usage_with_options(send_pack_usage, options); + OPT_END() + }; - git_config(send_pack_config, NULL); + repo_config(repo, send_pack_config, NULL); - - args.verbose = verbose; - args.dry_run = dry_run; + argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0); + if (argc > 0) { + dest = argv[0]; @@ builtin/send-pack.c: int cmd_send_pack(int argc, set_ref_status_for_push(remote_refs, args.send_mirror, args.force_update); @@ builtin/send-pack.c: int cmd_send_pack(int argc, if (helper_status) print_helper_status(remote_refs); + + ## t/t5400-send-pack.sh ## +@@ t/t5400-send-pack.sh: test_expect_success setup ' + echo Rebase && + git log' + ++test_expect_success 'send-pack does not crash with -h' ' ++ test_expect_code 129 git send-pack -h >usage && ++ test_grep "[Uu]sage: git send-pack " usage && ++ test_expect_code 129 nongit git send-pack -h >usage && ++ test_grep "[Uu]sage: git send-pack " usage ++' ++ + test_expect_success 'pack the source repository' ' + git repack -a -d && + git prune 7: df192a1b2c < -: ---------- builtin/pack-refs: refactor `cmd_pack_refs()` 8: 845cd1ea7c ! 5: b11e99627c builtin/pack-refs: stop using `the_repository` @@ Commit message When `-h` is passed to the command outside a Git repository, the `run_builtin()` will call the `cmd_pack_refs()` function with `repo` set to NULL and then early in the function, `parse_options()` call will give - the options help and exit, without having to consult much of the - configuration file. + the options help and exit. Mentored-by: Christian Couder <chriscool@xxxxxxxxxxxxx> Signed-off-by: Usman Akinyemi <usmanakinyemi202@xxxxxxxxx> @@ builtin/pack-refs.c: static char const * const pack_refs_usage[] = { struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; struct string_list included_refs = STRING_LIST_INIT_NODUP; @@ builtin/pack-refs.c: int cmd_pack_refs(int argc, - if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) - usage_with_options(pack_refs_usage, opts); - + N_("references to exclude")), + OPT_END(), + }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); - for_each_string_list_item(item, &option_excluded_refs) - add_ref_exclusion(pack_refs_opts.exclusions, item->string); + if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) + usage_with_options(pack_refs_usage, opts); @@ builtin/pack-refs.c: int cmd_pack_refs(int argc, if (!pack_refs_opts.includes->nr) @@ builtin/pack-refs.c: int cmd_pack_refs(int argc, clear_ref_exclusions(&excludes); string_list_clear(&included_refs, 0); + + ## t/t0610-reftable-basics.sh ## +@@ t/t0610-reftable-basics.sh: export GIT_TEST_DEFAULT_REF_FORMAT + + INVALID_OID=$(test_oid 001) + ++test_expect_success 'pack-refs does not crash with -h' ' ++ test_expect_code 129 git pack-refs -h >usage && ++ test_grep "[Uu]sage: git pack-refs " usage && ++ test_expect_code 129 nongit git pack-refs -h >usage && ++ test_grep "[Uu]sage: git pack-refs " usage ++' ++ + test_expect_success 'init: creates basic reftable structures' ' + test_when_finished "rm -rf repo" && + git init repo && 9: 2aff17b09c ! 6: 51c80f9273 builtin/ls-files: stop using `the_repository` @@ Commit message When `-h` is passed to the command outside a Git repository, the `run_builtin()` will call the `cmd_ls_files()` function with `repo` set to NULL and then early in the function, `show_usage_with_options_if_asked()` - call will give the options help and exit, without having to consult much - of the configuration file. + call will give the options help and exit. Pass the repository available in the calling context to both `expand_objectsize()` and `show_ru_info()` to remove their @@ builtin/ls-files.c: int cmd_ls_files(int argc, if (ps_matched && report_path_error(ps_matched, &pathspec)) { fprintf(stderr, "Did you forget to 'git add'?\n"); + + ## t/t3004-ls-files-basic.sh ## +@@ t/t3004-ls-files-basic.sh: test_expect_success 'ls-files -h in corrupt repository' ' + test_grep "[Uu]sage: git ls-files " broken/usage + ' + ++test_expect_success 'ls-files does not crash with -h' ' ++ test_expect_code 129 git ls-files -h >usage && ++ test_grep "[Uu]sage: git ls-files " usage && ++ test_expect_code 129 nongit git ls-files -h >usage && ++ test_grep "[Uu]sage: git ls-files " usage ++' ++ + test_expect_success SYMLINKS 'ls-files with absolute paths to symlinks' ' + mkdir subs && + ln -s nosuch link && 10: 4cc9a4935a < -: ---------- builtin/for-each-ref: refactor `cmd_for_each_ref()` 11: 42c1a7ae74 ! 7: 63bb89291f builtin/for-each-ref: stop using `the_repository` @@ Commit message When `-h` is passed to the command outside a Git repository, the `run_builtin()` will call the `cmd_for_each_ref()` function with `repo` set to NULL and then early in the function, `parse_options()` call will - give the options help and exit, without having to consult much of the - configuration file. + give the options help and exit. Mentored-by: Christian Couder <chriscool@xxxxxxxxxxxxx> Signed-off-by: Usman Akinyemi <usmanakinyemi202@xxxxxxxxx> @@ builtin/for-each-ref.c: static char const * const for_each_ref_usage[] = { struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; @@ builtin/for-each-ref.c: int cmd_for_each_ref(int argc, - if (verify_ref_format(&format)) - usage_with_options(for_each_ref_usage, opts); + + format.format = "%(objectname) %(objecttype)\t%(refname)"; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); - sorting = ref_sorting_options(&sorting_options); - ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase); - filter.ignore_case = icase; + + /* Set default (refname) sorting */ + string_list_append(&sorting_options, "refname"); + + ## t/t6300-for-each-ref.sh ## +@@ t/t6300-for-each-ref.sh: test_expect_success 'Check invalid atoms names are errors' ' + test_must_fail git for-each-ref --format="%(INVALID)" refs/heads + ' + ++test_expect_success 'for-each-ref does not crash with -h' ' ++ test_expect_code 129 git for-each-ref -h >usage && ++ test_grep "[Uu]sage: git for-each-ref " usage && ++ test_expect_code 129 nongit git for-each-ref -h >usage && ++ test_grep "[Uu]sage: git for-each-ref " usage ++' ++ + test_expect_success 'Check format specifiers are ignored in naming date atoms' ' + git for-each-ref --format="%(authordate)" refs/heads && + git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads && 12: 232cbef160 ! 8: 8dfe6b40c8 builtin/checkout-index: stop using `the_repository` @@ Commit message When `-h` is passed to the command outside a Git repository, the `run_builtin()` will call the `cmd_checkout_index()` function with `repo` set to NULL and then early in the function, `show_usage_with_options_if_asked()` - call will give the options help and exit, without having to consult much - of the configuration file. + call will give the options help and exit. Pass the repository available in the calling context to both `checkout_all()` and `checkout_file()` to remove their dependency on the global @@ builtin/checkout-index.c: int cmd_checkout_index(int argc, die("Unable to write new index file"); return 0; } + + ## t/t2006-checkout-index-basic.sh ## +@@ t/t2006-checkout-index-basic.sh: test_expect_success 'checkout-index -h in broken repository' ' + test_grep "[Uu]sage" broken/usage + ' + ++test_expect_success 'checkout-index does not crash with -h' ' ++ test_expect_code 129 git checkout-index -h >usage && ++ test_grep "[Uu]sage: git checkout-index " usage && ++ test_expect_code 129 nongit git checkout-index -h >usage && ++ test_grep "[Uu]sage: git checkout-index " usage ++' ++ + test_expect_success 'checkout-index reports errors (cmdline)' ' + test_must_fail git checkout-index -- does-not-exist 2>stderr && + test_grep not.in.the.cache stderr -- 2.48.1