static int check_repository_format_gently(const char *gitdir, int *nongit_ok) { struct strbuf sb = STRBUF_INIT; const char *repo_config; config_fn_t fn; int ret = 0; string_list_clear(&unknown_extensions, 0); if (get_common_dir(&sb, gitdir)) fn = check_repo_format; else fn = check_repository_format_version; strbuf_addstr(&sb, "/config"); repo_config = sb.buf; /* * git_config() can't be used here because it calls git_pathdup() * to get $GIT_CONFIG/config. That call will make setup_git_env() * set git_dir to ".git". * * We are in gitdir setup, no git dir has been found useable yet. * Use a gentler version of git_config() to check if this repo * is a good one. */ git_config_early(fn, NULL, repo_config); if (GIT_REPO_VERSION_READ < repository_format_version) { if (!nongit_ok) die ("Expected git repo version <= %d, found %d", GIT_REPO_VERSION_READ, repository_format_version); warning("Expected git repo version <= %d, found %d", GIT_REPO_VERSION_READ, repository_format_version); warning("Please upgrade Git"); *nongit_ok = -1; ret = -1; } if (repository_format_version >= 1 && unknown_extensions.nr) { int i; 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; }
static void clone_local(const char *src_repo, const char *dest_repo) { if (option_shared) { struct strbuf alt = STRBUF_INIT; strbuf_addf(&alt, "%s/objects", src_repo); add_to_alternates_file(alt.buf); strbuf_release(&alt); } else { struct strbuf src = STRBUF_INIT; struct strbuf dest = STRBUF_INIT; get_common_dir(&src, src_repo); get_common_dir(&dest, dest_repo); strbuf_addstr(&src, "/objects"); strbuf_addstr(&dest, "/objects"); copy_or_link_directory(&src, &dest, src_repo, src.len); strbuf_release(&src); strbuf_release(&dest); } if (0 <= option_verbosity) fprintf(stderr, _("done.\n")); }
static int check_repository_format_gently(const char *gitdir, int *nongit_ok) { struct strbuf sb = STRBUF_INIT; struct strbuf err = STRBUF_INIT; struct repository_format candidate; int has_common; has_common = get_common_dir(&sb, gitdir); strbuf_addstr(&sb, "/config"); read_repository_format(&candidate, sb.buf); strbuf_release(&sb); /* * For historical use of check_repository_format() in git-init, * we treat a missing config as a silent "ok", even when nongit_ok * is unset. */ if (candidate.version < 0) return 0; if (verify_repository_format(&candidate, &err) < 0) { if (nongit_ok) { warning("%s", err.buf); strbuf_release(&err); *nongit_ok = -1; return -1; } die("%s", err.buf); } repository_format_precious_objects = candidate.precious_objects; string_list_clear(&candidate.unknown_extensions, 0); if (!has_common) { if (candidate.is_bare != -1) { is_bare_repository_cfg = candidate.is_bare; if (is_bare_repository_cfg == 1) inside_work_tree = -1; } if (candidate.work_tree) { free(git_work_tree_cfg); git_work_tree_cfg = candidate.work_tree; inside_work_tree = -1; } } else { free(candidate.work_tree); } return 0; }
static int add_one_reference(struct string_list_item *item, void *cb_data) { char *ref_git; const char *repo; struct strbuf alternate = STRBUF_INIT; /* Beware: read_gitfile(), real_path() and mkpath() return static buffer */ ref_git = xstrdup(real_path(item->string)); repo = read_gitfile(ref_git); if (!repo) repo = read_gitfile(mkpath("%s/.git", ref_git)); if (repo) { free(ref_git); ref_git = xstrdup(repo); } if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) { char *ref_git_git = mkpathdup("%s/.git", ref_git); free(ref_git); ref_git = ref_git_git; } else if (!is_directory(mkpath("%s/objects", ref_git))) { struct strbuf sb = STRBUF_INIT; if (get_common_dir(&sb, ref_git)) die(_("reference repository '%s' as a linked checkout is not supported yet."), item->string); die(_("reference repository '%s' is not a local repository."), item->string); } if (!access(mkpath("%s/shallow", ref_git), F_OK)) die(_("reference repository '%s' is shallow"), item->string); if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) die(_("reference repository '%s' is grafted"), item->string); strbuf_addf(&alternate, "%s/objects", ref_git); add_to_alternates_file(alternate.buf); strbuf_release(&alternate); free(ref_git); return 0; }
/* * Test if it looks like we're at a git directory. * We want to see: * * - either an objects/ directory _or_ the proper * GIT_OBJECT_DIRECTORY environment variable * - a refs/ directory * - either a HEAD symlink or a HEAD file that is formatted as * a proper "ref:", or a regular file HEAD that has a properly * formatted sha1 object name. */ int is_git_directory(const char *suspect) { struct strbuf path = STRBUF_INIT; int ret = 0; size_t len; /* Check worktree-related signatures */ strbuf_addf(&path, "%s/HEAD", suspect); if (validate_headref(path.buf)) goto done; strbuf_reset(&path); get_common_dir(&path, suspect); len = path.len; /* Check non-worktree-related signatures */ if (getenv(DB_ENVIRONMENT)) { if (access(getenv(DB_ENVIRONMENT), X_OK)) goto done; } else { strbuf_setlen(&path, len); strbuf_addstr(&path, "/objects"); if (access(path.buf, X_OK)) goto done; } strbuf_setlen(&path, len); strbuf_addstr(&path, "/refs"); if (access(path.buf, X_OK)) goto done; ret = 1; done: strbuf_release(&path); return ret; }