summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2023-02-20 08:08:13 -0800
committerEdward Thomson <ethomson@edwardthomson.com>2023-02-20 09:29:08 -0800
commitbe3a78cc933169bab12dccdfcbb173cb48261103 (patch)
tree88502891803a2a23ce65a33e045a142202115278
parent1be70649432afc0dbac4fdd7d3d50d4881f3c634 (diff)
downloadlibgit2-be3a78cc933169bab12dccdfcbb173cb48261103.tar.gz
repo: support safe.directory with %(prefix)/
Git for Windows does some truly bizarre things with paths that start with a forward slash; and expects you to escape that with `%(prefix)`. This syntax generally means to add the prefix that Git was installed to -- eg `/usr/local` -- unless it's an absolute path, in which case the leading `%(prefix)/` is just removed. And Git for Windows expects you to use this syntax for absolute Unix-style paths (in "Git Bash" or Windows Subsystem for Linux). Worse, the behavior used to be that a leading `/` was not absolute. It would indicate that Git for Windows should add the prefix. So `//` is required for absolute Unix-style paths. Yes, this is truly horrifying. Emulate that behavior, I guess, but only for absolute paths. We won't deal with the Git install prefix. Also, give WSL users an escape hatch where they don't have to think about this and can use the literal path that the filesystem APIs provide (`//wsl.localhost/...`).
-rw-r--r--src/libgit2/repository.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c
index c02662bda..186b3d4ec 100644
--- a/src/libgit2/repository.c
+++ b/src/libgit2/repository.c
@@ -496,14 +496,47 @@ static int validate_ownership_cb(const git_config_entry *entry, void *payload)
{
validate_ownership_data *data = payload;
- if (strcmp(entry->value, "") == 0)
+ if (strcmp(entry->value, "") == 0) {
*data->is_safe = false;
-
- if (strcmp(entry->value, "*") == 0)
- *data->is_safe = true;
- else if (git_fs_path_prettify_dir(&data->tmp, entry->value, NULL) == 0 &&
- strcmp(data->tmp.ptr, data->repo_path) == 0)
+ } else if (strcmp(entry->value, "*") == 0) {
*data->is_safe = true;
+ } else {
+ const char *test_path = entry->value;
+
+#ifdef GIT_WIN32
+ /*
+ * Git for Windows does some truly bizarre things with
+ * paths that start with a forward slash; and expects you
+ * to escape that with `%(prefix)`. This syntax generally
+ * means to add the prefix that Git was installed to -- eg
+ * `/usr/local` -- unless it's an absolute path, in which
+ * case the leading `%(prefix)/` is just removed. And Git
+ * for Windows expects you to use this syntax for absolute
+ * Unix-style paths (in "Git Bash" or Windows Subsystem for
+ * Linux).
+ *
+ * Worse, the behavior used to be that a leading `/` was
+ * not absolute. It would indicate that Git for Windows
+ * should add the prefix. So `//` is required for absolute
+ * Unix-style paths. Yes, this is truly horrifying.
+ *
+ * Emulate that behavior, I guess, but only for absolute
+ * paths. We won't deal with the Git install prefix. Also,
+ * give WSL users an escape hatch where they don't have to
+ * think about this and can use the literal path that the
+ * filesystem APIs provide (`//wsl.localhost/...`).
+ */
+ if (strncmp(test_path, "%(prefix)//", strlen("%(prefix)//")) == 0)
+ test_path += strlen("%(prefix)/");
+ else if (strncmp(test_path, "//", 2) == 0 &&
+ strncmp(test_path, "//wsl.localhost/", strlen("//wsl.localhost/")) != 0)
+ test_path++;
+#endif
+
+ if (git_fs_path_prettify_dir(&data->tmp, test_path, NULL) == 0 &&
+ strcmp(data->tmp.ptr, data->repo_path) == 0)
+ *data->is_safe = true;
+ }
return 0;
}