"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Omar Polo <op@omarpolo.com>
Subject:
got/cvg info: print work tree version
To:
gameoftrees@openbsd.org
Date:
Tue, 13 Aug 2024 12:08:05 +0200

Download raw body.

Thread
I'm extending got_worktree_path_info() to resemble what we do in other
cases: have a prepare() routine that opens the fileindex and a complete
one that frees it.  These two also take care of locking[0].

This way, we can open the fileindex only once, and this allows to expose
a (misnamed but couldn't come up with something better)
got_worktree_path_info_version() that returns the fileindex version.

Here's how it looks:

    % got info
    work tree: /home/op/w/got
    work tree base commit: 4775b069530ea249dcfbc877685bf55700ca6423
    work tree path prefix: /
    work tree branch reference: refs/heads/main
    work tree UUID: 4c4c2b26-415d-4f9f-b9aa-9b584d0ec64c
    file index version: 3
    repository: /home/op/git/got.git

disclaimer: haven't teste `cvg info' at all, but it compiles :>

diff /home/op/w/got
commit - 4775b069530ea249dcfbc877685bf55700ca6423
path + /home/op/w/got
blob - 938a41dbea74cf93fa15f11168f273f6f1b3b594
file + cvg/cvg.c
--- cvg/cvg.c
+++ cvg/cvg.c
@@ -9023,6 +9023,7 @@ cmd_info(int argc, char *argv[])
 	const struct got_error *error = NULL;
 	struct got_repository *repo = NULL;
 	struct got_worktree *worktree = NULL;
+	struct got_fileindex *fileindex = NULL;
 	char *cwd = NULL, *id_str = NULL;
 	struct got_pathlist_head paths;
 	char *uuidstr = NULL;
@@ -9087,6 +9088,10 @@ cmd_info(int argc, char *argv[])
 		show_files = 1;
 	}
 
+	error = got_worktree_prepare_path_info(&fileindex, worktree, repo);
+	if (error)
+		goto done;
+
 	error = got_object_id_str(&id_str,
 	    got_worktree_get_base_commit_id(worktree));
 	if (error)
@@ -9103,6 +9108,8 @@ cmd_info(int argc, char *argv[])
 	printf("work tree branch reference: %s\n",
 	    got_worktree_get_head_ref_name(worktree));
 	printf("work tree UUID: %s\n", uuidstr);
+	printf("file index version: %u\n",
+	    got_worktree_path_info_version(fileindex));
 	printf("repository: %s\n", got_worktree_get_repo_path(worktree));
 
 	if (show_files) {
@@ -9116,7 +9123,7 @@ cmd_info(int argc, char *argv[])
 			 */
 			pe->data = (void *)got_error(GOT_ERR_BAD_PATH);
 		}
-		error = got_worktree_path_info(worktree, repo, &paths,
+		error = got_worktree_path_info(worktree, fileindex, &paths,
 		    print_path_info, &paths, check_cancelled, NULL);
 		if (error)
 			goto done;
@@ -9131,8 +9138,14 @@ cmd_info(int argc, char *argv[])
 		}
 	}
 done:
-	if (worktree)
+	if (worktree) {
+		const struct got_error *cerr;
+
+		cerr = got_worktree_path_info_complete(fileindex, worktree);
+		if (error == NULL)
+			error = cerr;
 		got_worktree_close(worktree);
+	}
 	if (repo) {
 		const struct got_error *close_err = got_repo_close(repo);
 		if (error == NULL)
blob - 8cf938cd11b24a93a1118ddaed1d6725dbe666e2
file + got/got.c
--- got/got.c
+++ got/got.c
@@ -14620,6 +14620,7 @@ cmd_info(int argc, char *argv[])
 	const struct got_error *error = NULL;
 	struct got_repository *repo = NULL;
 	struct got_worktree *worktree = NULL;
+	struct got_fileindex *fileindex = NULL;
 	char *cwd = NULL, *id_str = NULL;
 	struct got_pathlist_head paths;
 	char *uuidstr = NULL;
@@ -14684,6 +14685,10 @@ cmd_info(int argc, char *argv[])
 		show_files = 1;
 	}
 
+	error = got_worktree_prepare_path_info(&fileindex, worktree, repo);
+	if (error)
+		goto done;
+
 	error = got_object_id_str(&id_str,
 	    got_worktree_get_base_commit_id(worktree));
 	if (error)
@@ -14700,6 +14705,8 @@ cmd_info(int argc, char *argv[])
 	printf("work tree branch reference: %s\n",
 	    got_worktree_get_head_ref_name(worktree));
 	printf("work tree UUID: %s\n", uuidstr);
+	printf("file index version: %u\n",
+	    got_worktree_path_info_version(fileindex));
 	printf("repository: %s\n", got_worktree_get_repo_path(worktree));
 
 	if (show_files) {
@@ -14713,7 +14720,7 @@ cmd_info(int argc, char *argv[])
 			 */
 			pe->data = (void *)got_error(GOT_ERR_BAD_PATH);
 		}
-		error = got_worktree_path_info(worktree, repo, &paths,
+		error = got_worktree_path_info(worktree, fileindex, &paths,
 		    print_path_info, &paths, check_cancelled, NULL);
 		if (error)
 			goto done;
@@ -14728,8 +14735,14 @@ cmd_info(int argc, char *argv[])
 		}
 	}
 done:
-	if (worktree)
+	if (worktree) {
+		const struct got_error *cerr;
+
+		cerr = got_worktree_path_info_complete(fileindex, worktree);
+		if (error == NULL)
+			error = cerr;
 		got_worktree_close(worktree);
+	}
 	if (repo) {
 		const struct got_error *close_err = got_repo_close(repo);
 		if (error == NULL)
blob - 4ad750063163bd75fcdbccf958d5b7b7a72278fb
file + include/got_worktree.h
--- include/got_worktree.h
+++ include/got_worktree.h
@@ -578,6 +578,21 @@ const struct got_error *got_worktree_unstage(struct go
     struct got_pathlist_head *, got_worktree_checkout_cb, void *,
     got_worktree_patch_cb, void *, struct got_repository *);
 
+/*
+ * Prepare for getting meta data for paths in the work tree.  This
+ * function also returns a poniter to a fileindex wihch must be passed
+ * back to other path_info-related functions.
+ */
+const struct got_error *
+got_worktree_prepare_path_info(struct got_fileindex **,
+    struct got_worktree *, struct got_repository *);
+
+/*
+ * Get the file-index version.
+ */
+uint32_t
+got_worktree_path_info_version(struct got_fileindex *);
+
 /* A callback function which is invoked with per-path info. */
 typedef const struct got_error *(*got_worktree_path_info_cb)(void *,
     const char *path, mode_t mode, time_t mtime,
@@ -590,10 +605,16 @@ typedef const struct got_error *(*got_worktree_path_in
  * a path, and meta-data arguments (see got_worktree_path_info_cb).
  */
 const struct got_error *
-got_worktree_path_info(struct got_worktree *, struct got_repository *,
+got_worktree_path_info(struct got_worktree *, struct got_fileindex *,
     struct got_pathlist_head *, got_worktree_path_info_cb, void *,
     got_cancel_cb , void *);
 
+/*
+ * Complete the current path_info operation.
+ */
+const struct got_error *
+got_worktree_path_info_complete(struct got_fileindex *, struct got_worktree *);
+
 /* References pointing at pre-rebase commit backups. */
 #define GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX "refs/got/backup/rebase"
 
blob - 25b4a291714dfe97961ac61b9f0ac9b1954c8d05
file + lib/fileindex.c
--- lib/fileindex.c
+++ lib/fileindex.c
@@ -53,6 +53,7 @@
 
 struct got_fileindex {
 	struct got_fileindex_tree entries;
+	uint32_t version;
 	int nentries; /* Does not include entries marked for removal. */
 #define GOT_FILEIDX_MAX_ENTRIES INT32_MAX
 	enum got_hash_algorithm algo;
@@ -341,6 +342,7 @@ got_fileindex_alloc(enum got_hash_algorithm algo)
 	if (fileindex == NULL)
 		return NULL;
 
+	fileindex->version = GOT_FILE_INDEX_VERSION;
 	fileindex->algo = algo;
 	RB_INIT(&fileindex->entries);
 	return fileindex;
@@ -776,6 +778,7 @@ got_fileindex_read(struct got_fileindex *fileindex, FI
 	if (hdr.version > GOT_FILE_INDEX_VERSION)
 		return got_error(GOT_ERR_FILEIDX_VER);
 
+	fileindex->version = version;
 	fileindex->algo = algo;
 	for (i = 0; i < hdr.nentries; i++) {
 		err = read_fileindex_entry(&ie, &ctx, infile,
@@ -799,6 +802,12 @@ got_fileindex_read(struct got_fileindex *fileindex, FI
 	return NULL;
 }
 
+uint32_t
+got_fileindex_version(struct got_fileindex *fileindex)
+{
+	return fileindex->version;
+}
+
 static struct got_fileindex_entry *
 walk_fileindex(struct got_fileindex *fileindex, struct got_fileindex_entry *ie)
 {
blob - 7c7b47e3dc574a93a12fc50b094d200ba5622572
file + lib/got_lib_fileindex.h
--- lib/got_lib_fileindex.h
+++ lib/got_lib_fileindex.h
@@ -137,6 +137,7 @@ struct got_fileindex_entry *got_fileindex_entry_get(st
     const char *, size_t);
 const struct got_error *got_fileindex_read(struct got_fileindex *, FILE *,
 	enum got_hash_algorithm);
+uint32_t got_fileindex_version(struct got_fileindex *);
 typedef const struct got_error *(*got_fileindex_cb)(void *,
     struct got_fileindex_entry *);
 const struct got_error *got_fileindex_for_each_entry_safe(
blob - fd153d0cb67184bad0ac6b9dbd7ac36cf9866fe9
file + lib/worktree.c
--- lib/worktree.c
+++ lib/worktree.c
@@ -10010,43 +10010,55 @@ report_file_info(void *arg, struct got_fileindex_entry
 }
 
 const struct got_error *
+got_worktree_prepare_path_info(struct got_fileindex **fileindex,
+    struct got_worktree *worktree, struct got_repository *repo)
+{
+	const struct got_error *err;
+	char *fileindex_path;
+
+	err = lock_worktree(worktree, LOCK_SH);
+	if (err)
+		return err;
+
+	err = open_fileindex(fileindex, &fileindex_path, worktree,
+	    got_repo_get_object_format(repo));
+	free(fileindex_path);
+	return err;
+}
+
+uint32_t
+got_worktree_path_info_version(struct got_fileindex *fileindex)
+{
+	return got_fileindex_version(fileindex);
+}
+
+const struct got_error *
 got_worktree_path_info(struct got_worktree *worktree,
-    struct got_repository *repo,
+    struct got_fileindex *fileindex,
     struct got_pathlist_head *paths,
     got_worktree_path_info_cb info_cb, void *info_arg,
     got_cancel_cb cancel_cb, void *cancel_arg)
 
 {
-	const struct got_error *err = NULL, *unlockerr;
-	struct got_fileindex *fileindex = NULL;
-	char *fileindex_path = NULL;
 	struct report_file_info_arg arg;
 
-	err = lock_worktree(worktree, LOCK_SH);
-	if (err)
-		return err;
-
-	err = open_fileindex(&fileindex, &fileindex_path, worktree,
-	    got_repo_get_object_format(repo));
-	if (err)
-		goto done;
-
 	arg.worktree = worktree;
 	arg.info_cb = info_cb;
 	arg.info_arg = info_arg;
 	arg.paths = paths;
 	arg.cancel_cb = cancel_cb;
 	arg.cancel_arg = cancel_arg;
-	err = got_fileindex_for_each_entry_safe(fileindex, report_file_info,
+	return got_fileindex_for_each_entry_safe(fileindex, report_file_info,
 	    &arg);
-done:
-	free(fileindex_path);
+}
+
+const struct got_error *
+got_worktree_path_info_complete(struct got_fileindex *fileindex,
+    struct got_worktree *worktree)
+{
 	if (fileindex)
 		got_fileindex_free(fileindex);
-	unlockerr = lock_worktree(worktree, LOCK_UN);
-	if (unlockerr && err == NULL)
-		err = unlockerr;
-	return err;
+	return lock_worktree(worktree, LOCK_UN);
 }
 
 static const struct got_error *