summaryrefslogtreecommitdiff
path: root/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'setup.c')
-rw-r--r--setup.c108
1 files changed, 72 insertions, 36 deletions
diff --git a/setup.c b/setup.c
index a17c51e61d..de1a2a7ea5 100644
--- a/setup.c
+++ b/setup.c
@@ -5,6 +5,7 @@
static int inside_git_dir = -1;
static int inside_work_tree = -1;
static int work_tree_config_is_bogus;
+static struct string_list unknown_extensions = STRING_LIST_INIT_DUP;
/*
* The input parameter must contain an absolute path, and it must already be
@@ -87,7 +88,7 @@ char *prefix_path_gently(const char *prefix, int len,
const char *orig = path;
char *sanitized;
if (is_absolute_path(orig)) {
- sanitized = xmalloc(strlen(path) + 1);
+ sanitized = xmallocz(strlen(path));
if (remaining_prefix)
*remaining_prefix = 0;
if (normalize_path_copy_len(sanitized, path, remaining_prefix)) {
@@ -99,10 +100,7 @@ char *prefix_path_gently(const char *prefix, int len,
return NULL;
}
} else {
- sanitized = xmalloc(len + strlen(path) + 1);
- if (len)
- memcpy(sanitized, prefix, len);
- strcpy(sanitized + len, path);
+ sanitized = xstrfmt("%.*s%s", len, prefix, path);
if (remaining_prefix)
*remaining_prefix = len;
if (normalize_path_copy_len(sanitized, sanitized, remaining_prefix)) {
@@ -141,9 +139,7 @@ int check_filename(const char *prefix, const char *arg)
if (arg[2] == '\0') /* ":/" is root dir, always exists */
return 1;
name = arg + 2;
- } else if (!no_wildcard(arg))
- return 1;
- else if (prefix)
+ } else if (prefix)
name = prefix_filename(prefix, strlen(prefix), arg);
else
name = arg;
@@ -204,7 +200,7 @@ void verify_filename(const char *prefix,
{
if (*arg == '-')
die("bad flag '%s' used after filename", arg);
- if (check_filename(prefix, arg))
+ if (check_filename(prefix, arg) || !no_wildcard(arg))
return;
die_verify_filename(prefix, arg, diagnose_misspelt_rev);
}
@@ -229,14 +225,21 @@ void verify_non_filename(const char *prefix, const char *arg)
int get_common_dir(struct strbuf *sb, const char *gitdir)
{
+ const char *git_env_common_dir = getenv(GIT_COMMON_DIR_ENVIRONMENT);
+ if (git_env_common_dir) {
+ strbuf_addstr(sb, git_env_common_dir);
+ return 1;
+ } else {
+ return get_common_dir_noenv(sb, gitdir);
+ }
+}
+
+int get_common_dir_noenv(struct strbuf *sb, const char *gitdir)
+{
struct strbuf data = STRBUF_INIT;
struct strbuf path = STRBUF_INIT;
- const char *git_common_dir = getenv(GIT_COMMON_DIR_ENVIRONMENT);
int ret = 0;
- if (git_common_dir) {
- strbuf_addstr(sb, git_common_dir);
- return 1;
- }
+
strbuf_addf(&path, "%s/commondir", gitdir);
if (file_exists(path.buf)) {
if (strbuf_read_file(&data, path.buf, 0) <= 0)
@@ -307,6 +310,23 @@ done:
return ret;
}
+int is_nonbare_repository_dir(struct strbuf *path)
+{
+ int ret = 0;
+ int gitfile_error;
+ size_t orig_path_len = path->len;
+ assert(orig_path_len != 0);
+ strbuf_complete(path, '/');
+ strbuf_addstr(path, ".git");
+ if (read_gitfile_gently(path->buf, &gitfile_error) || is_git_directory(path->buf))
+ ret = 1;
+ if (gitfile_error == READ_GITFILE_ERR_OPEN_FAILED ||
+ gitfile_error == READ_GITFILE_ERR_READ_FAILED)
+ ret = 1;
+ strbuf_setlen(path, orig_path_len);
+ return ret;
+}
+
int is_inside_git_dir(void)
{
if (inside_git_dir < 0)
@@ -352,10 +372,25 @@ void setup_work_tree(void)
static int check_repo_format(const char *var, const char *value, void *cb)
{
+ const char *ext;
+
if (strcmp(var, "core.repositoryformatversion") == 0)
repository_format_version = git_config_int(var, value);
else if (strcmp(var, "core.sharedrepository") == 0)
shared_repository = git_config_perm(var, value);
+ else if (skip_prefix(var, "extensions.", &ext)) {
+ /*
+ * record any known extensions here; otherwise,
+ * we fall through to recording it as unknown, and
+ * check_repository_format will complain
+ */
+ if (!strcmp(ext, "noop"))
+ ;
+ else if (!strcmp(ext, "preciousobjects"))
+ repository_format_precious_objects = git_config_bool(var, value);
+ else
+ string_list_append(&unknown_extensions, ext);
+ }
return 0;
}
@@ -366,6 +401,8 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
config_fn_t fn;
int ret = 0;
+ string_list_clear(&unknown_extensions, 0);
+
if (get_common_dir(&sb, gitdir))
fn = check_repo_format;
else
@@ -383,29 +420,33 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
* is a good one.
*/
git_config_early(fn, NULL, repo_config);
- if (GIT_REPO_VERSION < repository_format_version) {
+ if (GIT_REPO_VERSION_READ < repository_format_version) {
if (!nongit_ok)
die ("Expected git repo version <= %d, found %d",
- GIT_REPO_VERSION, repository_format_version);
+ GIT_REPO_VERSION_READ, repository_format_version);
warning("Expected git repo version <= %d, found %d",
- GIT_REPO_VERSION, repository_format_version);
+ GIT_REPO_VERSION_READ, repository_format_version);
warning("Please upgrade Git");
*nongit_ok = -1;
ret = -1;
}
- strbuf_release(&sb);
- return ret;
-}
-static void update_linked_gitdir(const char *gitfile, const char *gitdir)
-{
- struct strbuf path = STRBUF_INIT;
- struct stat st;
+ if (repository_format_version >= 1 && unknown_extensions.nr) {
+ int i;
- strbuf_addf(&path, "%s/gitdir", gitdir);
- if (stat(path.buf, &st) || st.st_mtime + 24 * 3600 < time(NULL))
- write_file(path.buf, "%s", gitfile);
- strbuf_release(&path);
+ if (!nongit_ok)
+ die("unknown repository extension: %s",
+ unknown_extensions.items[0].string);
+
+ for (i = 0; i < unknown_extensions.nr; i++)
+ warning("unknown repository extension: %s",
+ unknown_extensions.items[i].string);
+ *nongit_ok = -1;
+ ret = -1;
+ }
+
+ strbuf_release(&sb);
+ return ret;
}
/*
@@ -445,14 +486,13 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
error_code = READ_GITFILE_ERR_OPEN_FAILED;
goto cleanup_return;
}
- buf = xmalloc(st.st_size + 1);
+ buf = xmallocz(st.st_size);
len = read_in_full(fd, buf, st.st_size);
close(fd);
if (len != st.st_size) {
error_code = READ_GITFILE_ERR_READ_FAILED;
goto cleanup_return;
}
- buf[len] = '\0';
if (!starts_with(buf, "gitdir: ")) {
error_code = READ_GITFILE_ERR_INVALID_FORMAT;
goto cleanup_return;
@@ -468,11 +508,8 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
if (!is_absolute_path(dir) && (slash = strrchr(path, '/'))) {
size_t pathlen = slash+1 - path;
- size_t dirlen = pathlen + len - 8;
- dir = xmalloc(dirlen + 1);
- strncpy(dir, path, pathlen);
- strncpy(dir + pathlen, buf + 8, len - 8);
- dir[dirlen] = '\0';
+ dir = xstrfmt("%.*s%.*s", (int)pathlen, path,
+ (int)(len - 8), buf + 8);
free(buf);
buf = dir;
}
@@ -480,7 +517,6 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
error_code = READ_GITFILE_ERR_NOT_A_REPO;
goto cleanup_return;
}
- update_linked_gitdir(path, dir);
path = real_path(dir);
cleanup_return: