Commit 247140b28268236ea5c77457b01d6dec936ffb51

Stefan Sperling 2019-02-05T17:15:54

make got_worktree_open() crawl upwards

diff --git a/include/got_error.h b/include/got_error.h
index 266c845..3c5386e 100644
--- a/include/got_error.h
+++ b/include/got_error.h
@@ -73,6 +73,7 @@
 #define GOT_ERR_BAD_REF_DATA	57
 #define GOT_ERR_TREE_DUP_ENTRY	58
 #define GOT_ERR_DIR_DUP_ENTRY	59
+#define GOT_ERR_NOT_WORKTREE	60
 
 static const struct got_error {
 	int code;
@@ -136,6 +137,7 @@ static const struct got_error {
 	{ GOT_ERR_BAD_REF_DATA,	"could not parse reference data" },
 	{ GOT_ERR_TREE_DUP_ENTRY,"duplicate entry in tree object" },
 	{ GOT_ERR_DIR_DUP_ENTRY,"duplicate entry in directory" },
+	{ GOT_ERR_NOT_WORKTREE, "no got work tree found" },
 };
 
 /*
diff --git a/include/got_worktree.h b/include/got_worktree.h
index 879b57c..eb06c1c 100644
--- a/include/got_worktree.h
+++ b/include/got_worktree.h
@@ -39,7 +39,7 @@ const struct got_error *got_worktree_init(const char *, struct got_reference *,
     const char *, struct got_repository *);
 
 /*
- * Attempt to open a worktree at the specified path.
+ * Attempt to open a worktree at or above the specified path.
  * The caller must dispose of it with got_worktree_close().
  */
 const struct got_error *got_worktree_open(struct got_worktree **, const char *);
diff --git a/lib/worktree.c b/lib/worktree.c
index c5cad3c..66bb12d 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -283,8 +283,8 @@ done:
 	return err;
 }
 
-const struct got_error *
-got_worktree_open(struct got_worktree **worktree, const char *path)
+static const struct got_error *
+open_worktree(struct got_worktree **worktree, const char *path)
 {
 	const struct got_error *err = NULL;
 	char *path_got;
@@ -391,6 +391,23 @@ done:
 	return err;
 }
 
+const struct got_error *
+got_worktree_open(struct got_worktree **worktree, const char *path)
+{
+	const struct got_error *err = NULL;
+
+	do {
+		err = open_worktree(worktree, path);
+		if (err && (err->code != GOT_ERR_ERRNO && errno != ENOENT))
+			return err;
+		if (*worktree)
+			return NULL;
+		path = dirname(path);
+	} while (path && !(path[0] == '.' && path[1] == '\0'));
+
+	return got_error(GOT_ERR_NOT_WORKTREE);
+}
+
 void
 got_worktree_close(struct got_worktree *worktree)
 {