Commit 1451e70d409660e581616fe32e56a7ad79b8b5a2

Stefan Sperling 2018-03-10T16:51:30

stamp worktrees with a format number

diff --git a/lib/got_worktree_priv.h b/lib/got_worktree_priv.h
index 97fb6c8..f49af44 100644
--- a/lib/got_worktree_priv.h
+++ b/lib/got_worktree_priv.h
@@ -22,3 +22,6 @@ struct got_worktree {
 #define GOT_WORKTREE_GOT_DIR	".got"
 #define GOT_WORKTREE_FILE_INDEX	"fileindex"
 #define GOT_WORKTREE_REPOSITORY	"repository"
+#define GOT_WORKTREE_FORMAT	"format"
+
+#define GOT_WORKTREE_FORMAT_VERSION	1
diff --git a/lib/worktree.c b/lib/worktree.c
index f655715..b1ad87e 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -42,8 +42,10 @@ got_worktree_init(const char *path, struct got_reference *head_ref,
 	char *indexpath = NULL;
 	char *headpath = NULL;
 	char *repopath = NULL;
+	char *formatpath = NULL;
 	char *refstr = NULL;
 	char *path_repos = NULL;
+	char *formatstr = NULL;
 	char buf[4];
 	ssize_t n;
 	int fd;
@@ -143,7 +145,7 @@ got_worktree_init(const char *path, struct got_reference *head_ref,
 		goto done;
 	}
 
-	/* Store path to repository. */ 
+	/* Store path to repository. */
 	if (asprintf(&repopath, "%s/%s", gotpath, GOT_WORKTREE_REPOSITORY)
 	    == -1) {
 		err = got_error(GOT_ERR_NO_MEM);
@@ -184,6 +186,40 @@ got_worktree_init(const char *path, struct got_reference *head_ref,
 		goto done;
 	}
 
+	/* Stamp repository with format file. */
+	if (asprintf(&formatpath, "%s/%s", gotpath, GOT_WORKTREE_FORMAT)
+	    == -1) {
+		err = got_error(GOT_ERR_NO_MEM);
+		goto done;
+	}
+	if (asprintf(&formatstr, "%d", GOT_WORKTREE_FORMAT_VERSION) == -1) {
+		err = got_error(GOT_ERR_NO_MEM);
+		goto done;
+	}
+	fd = open(formatpath, O_RDWR | O_CREAT | O_EXCL | O_EXLOCK | O_NOFOLLOW,
+	    GOT_DEFAULT_FILE_MODE);
+	if (fd == -1) {
+		err = got_error_from_errno();
+		goto done;
+	}
+	n = read(fd, buf, sizeof(buf));
+	if (n != 0) {
+		err = (n == -1 ? got_error_from_errno() :
+		    got_error(GOT_ERR_WORKTREE_EXISTS));
+		close(fd);
+		goto done;
+	}
+	n = dprintf(fd, "%s\n", formatstr);
+	if (n != strlen(formatstr) + 1) {
+		err = got_error_from_errno();
+		close(fd);
+		goto done;
+	}
+	if (close(fd) == -1) {
+		err = got_error_from_errno();
+		goto done;
+	}
+
 done:
 	free(abspath);
 	free(normpath);
@@ -191,6 +227,8 @@ done:
 	free(indexpath);
 	free(headpath);
 	free(repopath);
+	free(formatpath);
+	free(formatstr);
 	free(refstr);
 	free(path_repos);
 	return err;
diff --git a/regress/worktree/worktree_test.c b/regress/worktree/worktree_test.c
index e9f6cee..cad1391 100644
--- a/regress/worktree/worktree_test.c
+++ b/regress/worktree/worktree_test.c
@@ -83,6 +83,7 @@ remove_workdir(const char *worktree_path)
 	remove_meta_file(worktree_path, GOT_REF_HEAD);
 	remove_meta_file(worktree_path, GOT_WORKTREE_FILE_INDEX);
 	remove_meta_file(worktree_path, GOT_WORKTREE_REPOSITORY);
+	remove_meta_file(worktree_path, GOT_WORKTREE_FORMAT);
 	remove_got_dir(worktree_path);
 	rmdir(worktree_path);
 }
@@ -135,6 +136,8 @@ worktree_init(const char *repo_path)
 		goto done;
 	if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_REPOSITORY))
 		goto done;
+	if (!check_meta_file_exists(worktree_path, GOT_WORKTREE_FORMAT))
+		goto done;
 	ok = 1;
 	remove_workdir(worktree_path);
 done:
@@ -224,15 +227,23 @@ worktree_init_exists(const char *repo_path)
 	unlink(path);
 	free(path);
 
+	if (!obstruct_meta_file(&path, worktree_path, GOT_WORKTREE_FORMAT))
+		goto done;
+	err = got_worktree_init(worktree_path, head_ref, repo);
+	if (err != NULL && err->code == GOT_ERR_ERRNO && errno == EEXIST)
+		ok++;
+	unlink(path);
+	free(path);
+
 done:
 	if (head_ref)
 		got_ref_close(head_ref);
 	if (repo)
 		got_repo_close(repo);
 	free(gotpath);
-	if (ok == 3)
+	if (ok == 4)
 		remove_workdir(worktree_path);
-	return (ok == 3);
+	return (ok == 4);
 }
 
 #define RUN_TEST(expr, name) \