commit afbdf128aa6bd65d2cb8ac370a0d9e6c358d6a83 from: Stefan Sperling date: Tue May 13 13:59:35 2025 UTC stop opening the repository when opening a work tree Opening a bunch of files in /tmp for pack temp files and opening the repository just to validate the work tree's base-commit ID is overkill. Simply parse the ID directly. If the commit object no longer exists we will run into another error sooner or later. The commit is already protected by the work tree reference. If it is missing then something has badly gone wrong. Doing less work when opening work trees speeds up 'got status' a bit. As pointed out by Kyle this also avoids running got-read-gitconfig twice when opening both a repository and a work tree. ok by op@ and Kyle Ackerman commit - 86abf691afcfe170d6225c87d8ffed982d0eecec commit + afbdf128aa6bd65d2cb8ac370a0d9e6c358d6a83 blob - 74e2affe2cf926ca05691a6b59ec0592908b3f12 blob + 997d20f28754d7e0afc5af0f4375e2f0d19ed2d2 --- lib/worktree_open.c +++ lib/worktree_open.c @@ -41,6 +41,7 @@ #include "got_lib_worktree.h" #include "got_lib_gotconfig.h" +#include "got_lib_hash.h" #ifndef nitems #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) @@ -124,14 +125,19 @@ open_worktree(struct got_worktree **worktree, const ch char *uuidstr = NULL; char *path_lock = NULL; char *base_commit_id_str = NULL; + struct got_object_id *base_commit_id = NULL; int version, fd = -1; const char *errstr; - struct got_repository *repo = NULL; - int *pack_fds = NULL; uint32_t uuid_status; + enum got_hash_algorithm algo; + int have_algo; *worktree = NULL; + base_commit_id = calloc(1, sizeof(*base_commit_id)); + if (base_commit_id == NULL) + return got_error_from_errno("calloc"); + if (asprintf(&path_meta, "%s/%s", path, meta_dir) == -1) { err = got_error_from_errno("asprintf"); path_meta = NULL; @@ -204,18 +210,30 @@ open_worktree(struct got_worktree **worktree, const ch goto done; } - err = got_repo_pack_fds_open(&pack_fds); - if (err) - goto done; + /* TODO: The base-commit file should indicate the hash algo type. */ + switch (strlen(base_commit_id_str)) { + case SHA1_DIGEST_STRING_LENGTH - 1: + algo = GOT_HASH_SHA1; + have_algo = 1; + break; + case SHA256_DIGEST_STRING_LENGTH - 1: + algo = GOT_HASH_SHA256; + have_algo = 1; + break; + default: + have_algo = 0; + break; + } - err = got_repo_open(&repo, (*worktree)->repo_path, NULL, pack_fds); - if (err) + if (!have_algo || + !got_parse_object_id(base_commit_id, base_commit_id_str, algo)) { + err = got_error_fmt(GOT_ERR_BAD_OBJ_ID_STR, + "%s/%s", meta_dir, GOT_WORKTREE_BASE_COMMIT); goto done; + } - err = got_object_resolve_id_str(&(*worktree)->base_commit_id, repo, - base_commit_id_str); - if (err) - goto done; + (*worktree)->base_commit_id = base_commit_id; + base_commit_id = NULL; err = read_meta_file(&(*worktree)->head_ref_name, path_meta, GOT_WORKTREE_HEAD_REF); @@ -241,20 +259,10 @@ open_worktree(struct got_worktree **worktree, const ch goto done; } done: - if (repo) { - const struct got_error *close_err = got_repo_close(repo); - if (err == NULL) - err = close_err; - } - if (pack_fds) { - const struct got_error *pack_err = - got_repo_pack_fds_close(pack_fds); - if (err == NULL) - err = pack_err; - } free(path_meta); free(path_lock); free(base_commit_id_str); + free(base_commit_id); free(uuidstr); free(formatstr); if (err) {