Commit c7f4312fa3469fb36fb0cc087ca64846744a5533

Stefan Sperling 2019-02-05T17:46:58

make 'got status' work in subdirectories of a work tree

diff --git a/got/got.c b/got/got.c
index 7634022..97264cf 100644
--- a/got/got.c
+++ b/got/got.c
@@ -1429,7 +1429,8 @@ cmd_status(int argc, char *argv[])
 	if (error != NULL)
 		goto done;
 
-	error = apply_unveil(got_repo_get_path(repo), worktree_path);
+	error = apply_unveil(got_repo_get_path(repo),
+	    got_worktree_get_root_path(worktree));
 	if (error)
 		goto done;
 
diff --git a/include/got_worktree.h b/include/got_worktree.h
index eb06c1c..768ca6a 100644
--- a/include/got_worktree.h
+++ b/include/got_worktree.h
@@ -48,6 +48,11 @@ const struct got_error *got_worktree_open(struct got_worktree **, const char *);
 void got_worktree_close(struct got_worktree *);
 
 /*
+ * Get the path to the root directory of a worktree.
+ */
+const char *got_worktree_get_root_path(struct got_worktree *);
+
+/*
  * Get the path to the repository associated with a worktree.
  */
 const char *got_worktree_get_repo_path(struct got_worktree *);
diff --git a/lib/fileindex.c b/lib/fileindex.c
index 77ab90b..b5a1c93 100644
--- a/lib/fileindex.c
+++ b/lib/fileindex.c
@@ -694,35 +694,46 @@ got_fileindex_diff_tree(struct got_fileindex *fileindex,
 
 static const struct got_error *
 diff_fileindex_dir(struct got_fileindex *, struct got_fileindex_entry **, DIR *,
-    const char *, struct got_repository *, struct got_fileindex_diff_dir_cb *,
-    void *);
+    const char *, const char *, struct got_repository *,
+    struct got_fileindex_diff_dir_cb *, void *);
 
 static const struct got_error *
 walk_dir(struct got_pathlist_entry **next, struct got_fileindex *fileindex,
     struct got_fileindex_entry **ie, struct got_pathlist_entry *dle,
-    const char *path, DIR *dir, struct got_repository *repo,
-    struct got_fileindex_diff_dir_cb *cb, void *cb_arg)
+    const char *path, DIR *dir, const char *rootpath,
+    struct got_repository *repo, struct got_fileindex_diff_dir_cb *cb,
+    void *cb_arg)
 {
 	const struct got_error *err = NULL;
 	struct dirent *de = dle->data;
 
 	if (de->d_type == DT_DIR) {
 		char *subpath;
+		char *subdirpath;
 		DIR *subdir;
 
 		if (asprintf(&subpath, "%s%s%s", path,
 		    path[0] == '\0' ? "" : "/", de->d_name) == -1)
 			return got_error_from_errno();
 
-		subdir = opendir(subpath);
+		if (asprintf(&subdirpath, "%s/%s", rootpath, subpath) == -1) {
+			free(subpath);
+			return got_error_from_errno();
+		}
+
+		subdir = opendir(subdirpath);
 		if (subdir == NULL) {
+			#if 0
 			free(subpath);
+			free(subdirpath);
+			#endif
 			return got_error_from_errno();
 		}
 
-		err = diff_fileindex_dir(fileindex, ie, subdir, subpath, repo,
-		    cb, cb_arg);
+		err = diff_fileindex_dir(fileindex, ie, subdir, rootpath,
+		    subpath, repo, cb, cb_arg);
 		free(subpath);
+		free(subdirpath);
 		closedir(subdir);
 		if (err)
 			return err;
@@ -734,9 +745,9 @@ walk_dir(struct got_pathlist_entry **next, struct got_fileindex *fileindex,
 
 static const struct got_error *
 diff_fileindex_dir(struct got_fileindex *fileindex,
-    struct got_fileindex_entry **ie, DIR *dir, const char *path,
-    struct got_repository *repo, struct got_fileindex_diff_dir_cb *cb,
-    void *cb_arg)
+    struct got_fileindex_entry **ie, DIR *dir, const char *rootpath,
+    const char *path, struct got_repository *repo,
+    struct got_fileindex_diff_dir_cb *cb, void *cb_arg)
 {
 	const struct got_error *err = NULL;
 	struct dirent *de = NULL;
@@ -797,7 +808,7 @@ diff_fileindex_dir(struct got_fileindex *fileindex,
 					break;
 				*ie = walk_fileindex(fileindex, *ie);
 				err = walk_dir(&dle, fileindex, ie, dle, path,
-				    dir, repo, cb, cb_arg);
+				    dir, rootpath, repo, cb, cb_arg);
 			} else if (cmp < 0 ) {
 				next = walk_fileindex(fileindex, *ie);
 				err = cb->diff_old(cb_arg, *ie, path);
@@ -809,7 +820,7 @@ diff_fileindex_dir(struct got_fileindex *fileindex,
 				if (err)
 					break;
 				err = walk_dir(&dle, fileindex, ie, dle, path,
-				    dir, repo, cb, cb_arg);
+				    dir, rootpath, repo, cb, cb_arg);
 			}
 			if (err)
 				break;
@@ -825,7 +836,7 @@ diff_fileindex_dir(struct got_fileindex *fileindex,
 			if (err)
 				break;
 			err = walk_dir(&dle, fileindex, ie, dle, path, dir,
-			    repo, cb, cb_arg);
+			    rootpath, repo, cb, cb_arg);
 			if (err)
 				break;
 		}
@@ -838,13 +849,14 @@ done:
 }
 
 const struct got_error *
-got_fileindex_diff_dir(struct got_fileindex *fileindex, DIR *dir,
-    struct got_repository *repo, struct got_fileindex_diff_dir_cb *cb,
-    void *cb_arg)
+got_fileindex_diff_dir(struct got_fileindex *fileindex, DIR *rootdir,
+    const char *rootpath, struct got_repository *repo,
+    struct got_fileindex_diff_dir_cb *cb, void *cb_arg)
 {
 	struct got_fileindex_entry *min;
 	min = RB_MIN(got_fileindex_tree, &fileindex->entries);
-	return diff_fileindex_dir(fileindex, &min, dir, "", repo, cb, cb_arg);
+	return diff_fileindex_dir(fileindex, &min, rootdir, rootpath, "",
+	    repo, cb, cb_arg);
 }
 
 RB_GENERATE(got_fileindex_tree, got_fileindex_entry, entry, got_fileindex_cmp);
diff --git a/lib/got_lib_fileindex.h b/lib/got_lib_fileindex.h
index f0befaf..64bfc70 100644
--- a/lib/got_lib_fileindex.h
+++ b/lib/got_lib_fileindex.h
@@ -141,4 +141,5 @@ struct got_fileindex_diff_dir_cb {
 	got_fileindex_diff_dir_new_cb diff_new;
 };
 const struct got_error *got_fileindex_diff_dir(struct got_fileindex *, DIR *,
-    struct got_repository *, struct got_fileindex_diff_dir_cb *, void *);
+    const char *, struct got_repository *, struct got_fileindex_diff_dir_cb *,
+    void *);
diff --git a/lib/worktree.c b/lib/worktree.c
index 66bb12d..f4d98f7 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -423,6 +423,12 @@ got_worktree_close(struct got_worktree *worktree)
 }
 
 const char *
+got_worktree_get_root_path(struct got_worktree *worktree)
+{
+	return worktree->root_path;
+}
+
+const char *
 got_worktree_get_repo_path(struct got_worktree *worktree)
 {
 	return worktree->repo_path;
@@ -1121,7 +1127,8 @@ got_worktree_status(struct got_worktree *worktree,
 	arg.status_arg = status_arg;
 	arg.cancel_cb = cancel_cb;
 	arg.cancel_arg = cancel_arg;
-	err = got_fileindex_diff_dir(fileindex, workdir, repo, &fdiff_cb, &arg);
+	err = got_fileindex_diff_dir(fileindex, workdir, worktree->root_path,
+	    repo, &fdiff_cb, &arg);
 done:
 	if (workdir)
 		closedir(workdir);