make got_worktree_open() crawl upwards
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
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)
{