git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Patrick Steinhardt <ps@pks.im>
To: git@vger.kernel.org
Cc: Karthik Nayak <karthik.188@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	Eric Sunshine <sunshine@sunshineco.com>
Subject: [PATCH v3 00/12] Introduce `refStorage` extension
Date: Fri, 29 Dec 2023 08:26:22 +0100	[thread overview]
Message-ID: <cover.1703833818.git.ps@pks.im> (raw)
In-Reply-To: <cover.1703067989.git.ps@pks.im>

[-- Attachment #1: Type: text/plain, Size: 15642 bytes --]

Hi,

this is the third version of my patch series that introduces the new
`refStorage` extension. This extension will be used for the upcoming
reftable backend.

Changes compared to v3:

  - The `ref_storage_format` is now tracked as an `unsigned int`,
    proposed by Junio.

  - Reworded the commit message in patch 2, proposed by Eric.

  - Added a NEEDSWORK comment to `get_worktrees_internal()`, propose by
    Eric.

Thanks for your reviews!

Patrick

Patrick Steinhardt (12):
  t: introduce DEFAULT_REPO_FORMAT prereq
  worktree: skip reading HEAD when repairing worktrees
  refs: refactor logic to look up storage backends
  setup: start tracking ref storage format
  setup: set repository's formats on init
  setup: introduce "extensions.refStorage" extension
  setup: introduce GIT_DEFAULT_REF_FORMAT envvar
  t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar
  builtin/rev-parse: introduce `--show-ref-format` flag
  builtin/init: introduce `--ref-format=` value flag
  builtin/clone: introduce `--ref-format=` value flag
  t9500: write "extensions.refstorage" into config

 Documentation/config/extensions.txt           | 11 +++
 Documentation/git-clone.txt                   |  6 ++
 Documentation/git-init.txt                    |  7 ++
 Documentation/git-rev-parse.txt               |  3 +
 Documentation/git.txt                         |  5 ++
 Documentation/ref-storage-format.txt          |  1 +
 .../technical/repository-version.txt          |  5 ++
 builtin/clone.c                               | 17 ++++-
 builtin/init-db.c                             | 15 +++-
 builtin/rev-parse.c                           |  4 ++
 refs.c                                        | 34 ++++++---
 refs.h                                        |  3 +
 refs/debug.c                                  |  1 -
 refs/files-backend.c                          |  1 -
 refs/packed-backend.c                         |  1 -
 refs/refs-internal.h                          |  1 -
 repository.c                                  |  6 ++
 repository.h                                  |  7 ++
 setup.c                                       | 66 +++++++++++++++--
 setup.h                                       | 10 ++-
 t/README                                      |  3 +
 t/t0001-init.sh                               | 70 +++++++++++++++++++
 t/t1500-rev-parse.sh                          | 17 +++++
 t/t3200-branch.sh                             |  2 +-
 t/t5601-clone.sh                              | 17 +++++
 t/t9500-gitweb-standalone-no-errors.sh        |  5 ++
 t/test-lib-functions.sh                       |  5 ++
 t/test-lib.sh                                 | 15 +++-
 worktree.c                                    | 31 +++++---
 29 files changed, 334 insertions(+), 35 deletions(-)
 create mode 100644 Documentation/ref-storage-format.txt

Range-diff against v2:
 1:  3613439cb7 =  1:  578deaabcf t: introduce DEFAULT_REPO_FORMAT prereq
 2:  ecf4f1ddee !  2:  77c7213c66 worktree: skip reading HEAD when repairing worktrees
    @@ Commit message
         is logic that we resolve their respective worktree HEADs, even though
         that information may not actually be needed in the end by all callers.
     
    -    In the context of git-init(1) this is about to become a problem, because
    -    we do not have a repository that was set up via `setup_git_directory()`
    -    or friends. Consequentially, it is not yet fully initialized at the time
    -    of calling `repair_worktrees()`, and properly setting up all parts of
    -    the repository in `init_db()` before we repair worktrees is not an easy
    -    thing to do. While this is okay right now where we only have a single
    -    reference backend in Git, once we gain a second one we would be trying
    -    to look up the worktree HEADs before we have figured out the reference
    -    format, which does not work.
    +    Although not a problem presently with the file-based reference backend,
    +    it will become a problem with the upcoming reftable backend. In the
    +    context of git-init(1) we do not have a fully-initialized repository set
    +    up via `setup_git_directory()` or friends. Consequently, we do not know
    +    about the repository format when `repair_worktrees()` is called, and
    +    properly setting up all parts of the repositroy in `init_db()` before we
    +    try to repair worktrees is not an easy task. With the introduction of
    +    the reftable backend, we would ultimately try to look up the worktree
    +    HEADs before we have figured out the reference format, which does not
    +    work.
     
         We do not require the worktree HEADs at all to repair worktrees. So
         let's fix this issue by skipping over the step that reads them.
    @@ worktree.c: static void mark_current_worktree(struct worktree **worktrees)
      }
      
     -struct worktree **get_worktrees(void)
    ++/*
    ++ * NEEDSWORK: This function exists so that we can look up metadata of a
    ++ * worktree without trying to access any of its internals like the refdb. It
    ++ * would be preferable to instead have a corruption-tolerant function for
    ++ * retrieving worktree metadata that could be used when the worktree is known
    ++ * to not be in a healthy state, e.g. when creating or repairing it.
    ++ */
     +static struct worktree **get_worktrees_internal(int skip_reading_head)
      {
      	struct worktree **list = NULL;
 3:  12329b99b7 !  3:  47649570bf refs: refactor logic to look up storage backends
    @@ refs.c
     +};
      
     -static struct ref_storage_be *find_ref_storage_backend(const char *name)
    -+static const struct ref_storage_be *find_ref_storage_backend(int ref_storage_format)
    ++static const struct ref_storage_be *find_ref_storage_backend(unsigned int ref_storage_format)
      {
     -	struct ref_storage_be *be;
     -	for (be = refs_backends; be; be = be->next)
    @@ refs.c
      	return NULL;
      }
      
    -+int ref_storage_format_by_name(const char *name)
    ++unsigned int ref_storage_format_by_name(const char *name)
     +{
    -+	for (int i = 0; i < ARRAY_SIZE(refs_backends); i++)
    ++	for (unsigned int i = 0; i < ARRAY_SIZE(refs_backends); i++)
     +		if (refs_backends[i] && !strcmp(refs_backends[i]->name, name))
     +			return i;
     +	return REF_STORAGE_FORMAT_UNKNOWN;
     +}
     +
    -+const char *ref_storage_format_to_name(int ref_storage_format)
    ++const char *ref_storage_format_to_name(unsigned int ref_storage_format)
     +{
     +	const struct ref_storage_be *be = find_ref_storage_backend(ref_storage_format);
     +	if (!be)
    @@ refs.c: static struct ref_store *ref_store_init(struct repository *repo,
      {
     -	const char *be_name = "files";
     -	struct ref_storage_be *be = find_ref_storage_backend(be_name);
    -+	int format = REF_STORAGE_FORMAT_FILES;
    ++	unsigned int format = REF_STORAGE_FORMAT_FILES;
     +	const struct ref_storage_be *be = find_ref_storage_backend(format);
      	struct ref_store *refs;
      
    @@ refs.h: struct string_list;
      struct string_list_item;
      struct worktree;
      
    -+int ref_storage_format_by_name(const char *name);
    -+const char *ref_storage_format_to_name(int ref_storage_format);
    ++unsigned int ref_storage_format_by_name(const char *name);
    ++const char *ref_storage_format_to_name(unsigned int ref_storage_format);
     +
      /*
       * Resolve a reference, recursively following symbolic refererences.
 4:  ddd099fbaf !  4:  837764d0b5 setup: start tracking ref storage format
    @@ refs.c: static struct ref_store *ref_store_init(struct repository *repo,
      					const char *gitdir,
      					unsigned int flags)
      {
    --	int format = REF_STORAGE_FORMAT_FILES;
    +-	unsigned int format = REF_STORAGE_FORMAT_FILES;
     -	const struct ref_storage_be *be = find_ref_storage_backend(format);
     +	const struct ref_storage_be *be;
      	struct ref_store *refs;
    @@ repository.c: void repo_set_hash_algo(struct repository *repo, int hash_algo)
      	repo->hash_algo = &hash_algos[hash_algo];
      }
      
    -+void repo_set_ref_storage_format(struct repository *repo, int format)
    ++void repo_set_ref_storage_format(struct repository *repo, unsigned int format)
     +{
     +	repo->ref_storage_format = format;
     +}
    @@ repository.h: struct repository {
      	const struct git_hash_algo *hash_algo;
      
     +	/* Repository's reference storage format, as serialized on disk. */
    -+	int ref_storage_format;
    ++	unsigned int ref_storage_format;
     +
      	/* A unique-id for tracing purposes. */
      	int trace2_repo_id;
    @@ repository.h: void repo_set_gitdir(struct repository *repo, const char *root,
      		     const struct set_gitdir_args *extra_args);
      void repo_set_worktree(struct repository *repo, const char *path);
      void repo_set_hash_algo(struct repository *repo, int algo);
    -+void repo_set_ref_storage_format(struct repository *repo, int format);
    ++void repo_set_ref_storage_format(struct repository *repo, unsigned int format);
      void initialize_the_repository(void);
      RESULT_MUST_BE_USED
      int repo_init(struct repository *r, const char *gitdir, const char *worktree);
    @@ setup.c: static int is_reinit(void)
      }
      
     -void create_reference_database(const char *initial_branch, int quiet)
    -+void create_reference_database(int ref_storage_format,
    ++void create_reference_database(unsigned int ref_storage_format,
     +			       const char *initial_branch, int quiet)
      {
      	struct strbuf err = STRBUF_INIT;
    @@ setup.c: static void validate_hash_algorithm(struct repository_format *repo_fmt,
      	}
      }
      
    -+static void validate_ref_storage_format(struct repository_format *repo_fmt, int format)
    ++static void validate_ref_storage_format(struct repository_format *repo_fmt,
    ++					unsigned int format)
     +{
     +	if (repo_fmt->version >= 0 &&
     +	    format != REF_STORAGE_FORMAT_UNKNOWN &&
    @@ setup.c: static void validate_hash_algorithm(struct repository_format *repo_fmt,
      int init_db(const char *git_dir, const char *real_git_dir,
     -	    const char *template_dir, int hash, const char *initial_branch,
     +	    const char *template_dir, int hash,
    -+	    int ref_storage_format, const char *initial_branch,
    ++	    unsigned int ref_storage_format,
    ++	    const char *initial_branch,
      	    int init_shared_repository, unsigned int flags)
      {
      	int reinit;
    @@ setup.h: struct repository_format {
      	int worktree_config;
      	int is_bare;
      	int hash_algo;
    -+	int ref_storage_format;
    ++	unsigned int ref_storage_format;
      	int sparse_index;
      	char *work_tree;
      	struct string_list unknown_extensions;
    @@ setup.h: void check_repository_format(struct repository_format *fmt);
      
      int init_db(const char *git_dir, const char *real_git_dir,
      	    const char *template_dir, int hash_algo,
    -+	    int ref_storage_format,
    ++	    unsigned int ref_storage_format,
      	    const char *initial_branch, int init_shared_repository,
      	    unsigned int flags);
      void initialize_repository_version(int hash_algo, int reinit);
     -void create_reference_database(const char *initial_branch, int quiet);
    -+void create_reference_database(int ref_storage_format,
    ++void create_reference_database(unsigned int ref_storage_format,
     +			       const char *initial_branch, int quiet);
      
      /*
 5:  01a1e58a97 =  5:  a51da56d9b setup: set repository's formats on init
 6:  0a586fa648 !  6:  a1e03e4392 setup: introduce "extensions.refStorage" extension
    @@ setup.c: static enum extension_result handle_extension(const char *var,
      		data->hash_algo = format;
      		return EXTENSION_OK;
     +	} else if (!strcmp(ext, "refstorage")) {
    -+		int format;
    ++		unsigned int format;
     +
     +		if (!value)
     +			return config_error_nonbool(var);
    @@ setup.c: static int needs_work_tree_config(const char *git_dir, const char *work
      }
      
     -void initialize_repository_version(int hash_algo, int reinit)
    -+void initialize_repository_version(int hash_algo, int ref_storage_format,
    ++void initialize_repository_version(int hash_algo,
    ++				   unsigned int ref_storage_format,
     +				   int reinit)
      {
      	char repo_version_string[10];
    @@ setup.c: static int create_default_files(const char *template_path,
     
      ## setup.h ##
     @@ setup.h: int init_db(const char *git_dir, const char *real_git_dir,
    - 	    int ref_storage_format,
    + 	    unsigned int ref_storage_format,
      	    const char *initial_branch, int init_shared_repository,
      	    unsigned int flags);
     -void initialize_repository_version(int hash_algo, int reinit);
    -+void initialize_repository_version(int hash_algo, int ref_storage_format,
    ++void initialize_repository_version(int hash_algo,
    ++				   unsigned int ref_storage_format,
     +				   int reinit);
    - void create_reference_database(int ref_storage_format,
    + void create_reference_database(unsigned int ref_storage_format,
      			       const char *initial_branch, int quiet);
      
     
 7:  6d8754f73a !  7:  5ffc70e9be setup: introduce GIT_DEFAULT_REF_FORMAT envvar
    @@ Documentation/git.txt: double-quotes and respecting backslash escapes. E.g., the
     
      ## setup.c ##
     @@ setup.c: static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
    - 
    - static void validate_ref_storage_format(struct repository_format *repo_fmt, int format)
    + static void validate_ref_storage_format(struct repository_format *repo_fmt,
    + 					unsigned int format)
      {
     +	const char *name = getenv("GIT_DEFAULT_REF_FORMAT");
     +
 8:  c645932f3d =  8:  13c074acdf t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar
 9:  761d647770 =  9:  4ee3c9a2d1 builtin/rev-parse: introduce `--show-ref-format` flag
10:  e382b5bf08 ! 10:  25773e3560 builtin/init: introduce `--ref-format=` value flag
    @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref
     +	const char *ref_format = NULL;
      	const char *initial_branch = NULL;
      	int hash_algo = GIT_HASH_UNKNOWN;
    -+	int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
    ++	unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
      	int init_shared_repository = -1;
      	const struct option init_db_options[] = {
      		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
11:  257233658d ! 11:  3f1cb6b9e5 builtin/clone: introduce `--ref-format=` value flag
    @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
      	int submodule_progress;
      	int filter_submodules = 0;
      	int hash_algo;
    -+	int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
    ++	unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
      	const int do_not_override_repo_unix_permissions = -1;
      
      	struct transport_ls_refs_options transport_ls_refs_options =
12:  b8cd06ec53 = 12:  2e7682b2f3 t9500: write "extensions.refstorage" into config

base-commit: e79552d19784ee7f4bbce278fe25f93fbda196fa
-- 
2.43.GIT


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  parent reply	other threads:[~2023-12-29  7:26 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-20 10:54 [PATCH 00/12] Introduce `refStorage` extension Patrick Steinhardt
2023-12-20 10:54 ` [PATCH 01/12] t: introduce DEFAULT_REPO_FORMAT prereq Patrick Steinhardt
2023-12-22 11:41   ` Karthik Nayak
2023-12-28  8:55     ` Patrick Steinhardt
2023-12-20 10:54 ` [PATCH 02/12] worktree: skip reading HEAD when repairing worktrees Patrick Steinhardt
2023-12-22 12:23   ` Karthik Nayak
2023-12-20 10:55 ` [PATCH 03/12] refs: refactor logic to look up storage backends Patrick Steinhardt
2023-12-22 12:38   ` Karthik Nayak
2023-12-28  8:56     ` Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 04/12] setup: start tracking ref storage format when Patrick Steinhardt
2023-12-20 18:30   ` Junio C Hamano
2023-12-28  8:56     ` Patrick Steinhardt
2023-12-28 17:15       ` Junio C Hamano
2023-12-28 20:01         ` Patrick Steinhardt
2023-12-22 13:09   ` Karthik Nayak
2023-12-28  8:56     ` Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 05/12] setup: set repository's formats on init Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 06/12] setup: introduce "extensions.refStorage" extension Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 07/12] setup: introduce GIT_DEFAULT_REF_FORMAT envvar Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 08/12] t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 09/12] builtin/rev-parse: introduce `--show-ref-format` flag Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 10/12] builtin/init: introduce `--ref-format=` value flag Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 11/12] builtin/clone: " Patrick Steinhardt
2023-12-20 10:55 ` [PATCH 12/12] t9500: write "extensions.refstorage" into config Patrick Steinhardt
2023-12-22 13:43   ` Karthik Nayak
2023-12-22 13:43 ` [PATCH 00/12] Introduce `refStorage` extension Karthik Nayak
2023-12-26 20:56   ` Junio C Hamano
2023-12-28  9:57 ` [PATCH v2 " Patrick Steinhardt
2023-12-28  9:57   ` [PATCH v2 01/12] t: introduce DEFAULT_REPO_FORMAT prereq Patrick Steinhardt
2023-12-28  9:57   ` [PATCH v2 02/12] worktree: skip reading HEAD when repairing worktrees Patrick Steinhardt
2023-12-28 18:08     ` Eric Sunshine
2023-12-28 18:13       ` Eric Sunshine
2023-12-28 20:18         ` Patrick Steinhardt
2023-12-28  9:57   ` [PATCH v2 03/12] refs: refactor logic to look up storage backends Patrick Steinhardt
2023-12-28 17:25     ` Junio C Hamano
2023-12-28 20:11       ` Patrick Steinhardt
2023-12-28 20:42         ` Junio C Hamano
2023-12-28  9:57   ` [PATCH v2 04/12] setup: start tracking ref storage format Patrick Steinhardt
2023-12-28  9:57   ` [PATCH v2 05/12] setup: set repository's formats on init Patrick Steinhardt
2023-12-28  9:57   ` [PATCH v2 06/12] setup: introduce "extensions.refStorage" extension Patrick Steinhardt
2023-12-28  9:57   ` [PATCH v2 07/12] setup: introduce GIT_DEFAULT_REF_FORMAT envvar Patrick Steinhardt
2023-12-28  9:57   ` [PATCH v2 08/12] t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar Patrick Steinhardt
2023-12-28  9:58   ` [PATCH v2 09/12] builtin/rev-parse: introduce `--show-ref-format` flag Patrick Steinhardt
2023-12-28  9:58   ` [PATCH v2 10/12] builtin/init: introduce `--ref-format=` value flag Patrick Steinhardt
2023-12-28  9:58   ` [PATCH v2 11/12] builtin/clone: " Patrick Steinhardt
2023-12-28  9:58   ` [PATCH v2 12/12] t9500: write "extensions.refstorage" into config Patrick Steinhardt
2023-12-29  7:26 ` Patrick Steinhardt [this message]
2023-12-29  7:26   ` [PATCH v3 01/12] t: introduce DEFAULT_REPO_FORMAT prereq Patrick Steinhardt
2023-12-29  7:26   ` [PATCH v3 02/12] worktree: skip reading HEAD when repairing worktrees Patrick Steinhardt
2023-12-29  7:26   ` [PATCH v3 03/12] refs: refactor logic to look up storage backends Patrick Steinhardt
2023-12-29  7:26   ` [PATCH v3 04/12] setup: start tracking ref storage format Patrick Steinhardt
2023-12-29  7:26   ` [PATCH v3 05/12] setup: set repository's formats on init Patrick Steinhardt
2023-12-29  7:26   ` [PATCH v3 06/12] setup: introduce "extensions.refStorage" extension Patrick Steinhardt
2023-12-29  7:26   ` [PATCH v3 07/12] setup: introduce GIT_DEFAULT_REF_FORMAT envvar Patrick Steinhardt
2023-12-29  7:26   ` [PATCH v3 08/12] t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar Patrick Steinhardt
2023-12-29  7:27   ` [PATCH v3 09/12] builtin/rev-parse: introduce `--show-ref-format` flag Patrick Steinhardt
2023-12-29  7:27   ` [PATCH v3 10/12] builtin/init: introduce `--ref-format=` value flag Patrick Steinhardt
2023-12-29  7:27   ` [PATCH v3 11/12] builtin/clone: " Patrick Steinhardt
2023-12-29  7:27   ` [PATCH v3 12/12] t9500: write "extensions.refstorage" into config Patrick Steinhardt
2023-12-29  8:44   ` [PATCH v3 00/12] Introduce `refStorage` extension Eric Sunshine

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cover.1703833818.git.ps@pks.im \
    --to=ps@pks.im \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=karthik.188@gmail.com \
    --cc=sunshine@sunshineco.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).