aboutsummaryrefslogtreecommitdiffstats
path: root/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'setup.c')
-rw-r--r--setup.c97
1 files changed, 80 insertions, 17 deletions
diff --git a/setup.c b/setup.c
index b49ee3e95f..20f380825b 100644
--- a/setup.c
+++ b/setup.c
@@ -4,6 +4,7 @@
#include "environment.h"
#include "exec-cmd.h"
#include "gettext.h"
+#include "hex.h"
#include "object-name.h"
#include "refs.h"
#include "repository.h"
@@ -342,6 +343,58 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir)
return ret;
}
+static int validate_headref(const char *path)
+{
+ struct stat st;
+ char buffer[256];
+ const char *refname;
+ struct object_id oid;
+ int fd;
+ ssize_t len;
+
+ if (lstat(path, &st) < 0)
+ return -1;
+
+ /* Make sure it is a "refs/.." symlink */
+ if (S_ISLNK(st.st_mode)) {
+ len = readlink(path, buffer, sizeof(buffer)-1);
+ if (len >= 5 && !memcmp("refs/", buffer, 5))
+ return 0;
+ return -1;
+ }
+
+ /*
+ * Anything else, just open it and try to see if it is a symbolic ref.
+ */
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ len = read_in_full(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ if (len < 0)
+ return -1;
+ buffer[len] = '\0';
+
+ /*
+ * Is it a symbolic ref?
+ */
+ if (skip_prefix(buffer, "ref:", &refname)) {
+ while (isspace(*refname))
+ refname++;
+ if (starts_with(refname, "refs/"))
+ return 0;
+ }
+
+ /*
+ * Is this a detached HEAD?
+ */
+ if (get_oid_hex_any(buffer, &oid) != GIT_HASH_UNKNOWN)
+ return 0;
+
+ return -1;
+}
+
/*
* Test if it looks like we're at a git directory.
* We want to see:
@@ -1177,13 +1230,20 @@ static int safe_directory_cb(const char *key, const char *value,
} else if (!strcmp(value, "*")) {
data->is_safe = 1;
} else {
- const char *interpolated = NULL;
-
- if (!git_config_pathname(&interpolated, key, value) &&
- !fspathcmp(data->path, interpolated ? interpolated : value))
- data->is_safe = 1;
-
- free((char *)interpolated);
+ char *allowed = NULL;
+
+ if (!git_config_pathname(&allowed, key, value)) {
+ const char *check = allowed ? allowed : value;
+ if (ends_with(check, "/*")) {
+ size_t len = strlen(check);
+ if (!fspathncmp(check, data->path, len - 1))
+ data->is_safe = 1;
+ } else if (!fspathcmp(data->path, check)) {
+ data->is_safe = 1;
+ }
+ }
+ if (allowed != value)
+ free(allowed);
}
return 0;
@@ -1822,7 +1882,7 @@ static int template_dir_cb(const char *key, const char *value,
char *path = NULL;
FREE_AND_NULL(data->path);
- if (!git_config_pathname((const char **)&path, key, value))
+ if (!git_config_pathname(&path, key, value))
data->path = path ? path : xstrdup(value);
}
@@ -2291,12 +2351,6 @@ int init_db(const char *git_dir, const char *real_git_dir,
}
startup_info->have_repository = 1;
- /* Ensure `core.hidedotfiles` is processed */
- git_config(platform_core_config, NULL);
-
- safe_create_dir(git_dir, 0);
-
-
/* Check to see if the repository version is right.
* Note that a newly created repository does not have
* config file, so this will not fail. What we are catching
@@ -2307,9 +2361,6 @@ int init_db(const char *git_dir, const char *real_git_dir,
validate_hash_algorithm(&repo_fmt, hash);
validate_ref_storage_format(&repo_fmt, ref_storage_format);
- reinit = create_default_files(template_dir, original_git_dir,
- &repo_fmt, init_shared_repository);
-
/*
* Now that we have set up both the hash algorithm and the ref storage
* format we can update the repository's settings accordingly.
@@ -2317,6 +2368,18 @@ int init_db(const char *git_dir, const char *real_git_dir,
repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
repo_set_ref_storage_format(the_repository, repo_fmt.ref_storage_format);
+ /*
+ * Ensure `core.hidedotfiles` is processed. This must happen after we
+ * have set up the repository format such that we can evaluate
+ * includeIf conditions correctly in the case of re-initialization.
+ */
+ git_config(platform_core_config, NULL);
+
+ safe_create_dir(git_dir, 0);
+
+ reinit = create_default_files(template_dir, original_git_dir,
+ &repo_fmt, init_shared_repository);
+
if (!(flags & INIT_DB_SKIP_REFDB))
create_reference_database(repo_fmt.ref_storage_format,
initial_branch, flags & INIT_DB_QUIET);