commit - 60ca2a50c4fa6806752129de244576f0d289ffa0
commit + 20b7abb3fa8e5b46bacd07df9f85cfd7edc5a4c9
blob - 0f3e07a914451fb4ee60661753010efd60284036
blob + 5fa8ffa0d2de4c2d61942eb2eed66a240149f6d0
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_PARSE_CONFIG 127
#define GOT_ERR_NO_CONFIG_FILE 128
#define GOT_ERR_BAD_SYMLINK 129
+#define GOT_ERR_GIT_REPO_EXT 130
static const struct got_error {
int code;
{ GOT_ERR_NO_CONFIG_FILE, "configuration file doesn't exit" },
{ GOT_ERR_BAD_SYMLINK, "symbolic link points outside of paths under "
"version control" },
+ { GOT_ERR_GIT_REPO_EXT, "unsupported repository format extension" },
};
/*
blob - 6c638e9d018fe07c5b7e6949507b353ea5495e3e
blob + f4815b5fc99e9f8665fd85b9326c64f18b176d04
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
/* Messages related to gitconfig files. */
GOT_IMSG_GITCONFIG_PARSE_REQUEST,
GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST,
+ GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST,
GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST,
GOT_IMSG_GITCONFIG_AUTHOR_EMAIL_REQUEST,
GOT_IMSG_GITCONFIG_REMOTES_REQUEST,
int);
const struct got_error *
got_privsep_send_gitconfig_repository_format_version_req(struct imsgbuf *);
+const struct got_error *got_privsep_send_gitconfig_repository_extensions_req(
+ struct imsgbuf *);
const struct got_error *got_privsep_send_gitconfig_author_name_req(
struct imsgbuf *);
const struct got_error *got_privsep_send_gitconfig_author_email_req(
blob - 87f25580cb957d598ce95524a992a2d67f95d9ad
blob + d2a6b78c48d166aadf6645f719cb29e4663cd851
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
int ngitconfig_remotes;
struct got_remote_repo *gitconfig_remotes;
char *gitconfig_owner;
+ char **extensions;
+ int nextensions;
/* Settings read from got.conf. */
struct got_gotconfig *gotconfig;
blob - d15fdd1c19625c14f12b9ef6c2f0a764fc43a0da
blob + 55eb3a41d0b6ef47b2e286aa578da8cb73c0e2f7
--- lib/privsep.c
+++ lib/privsep.c
}
const struct got_error *
+got_privsep_send_gitconfig_repository_extensions_req(struct imsgbuf *ibuf)
+{
+ if (imsg_compose(ibuf,
+ GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST, 0, 0, -1,
+ NULL, 0) == -1)
+ return got_error_from_errno("imsg_compose "
+ "GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST");
+
+ return flush_imsg(ibuf);
+}
+
+
+const struct got_error *
got_privsep_send_gitconfig_author_name_req(struct imsgbuf *ibuf)
{
if (imsg_compose(ibuf,
blob - 036305e904556fd6910f4e907610f8973a3b2e8a
blob + 3c8f844ad272da6c878fec6aac3e13d424e13af1
--- lib/repository.c
+++ lib/repository.c
parse_gitconfig_file(int *gitconfig_repository_format_version,
char **gitconfig_author_name, char **gitconfig_author_email,
struct got_remote_repo **remotes, int *nremotes,
- char **gitconfig_owner,
+ char **gitconfig_owner, char ***extensions, int *nextensions,
const char *gitconfig_path)
{
const struct got_error *err = NULL, *child_err = NULL;
struct imsgbuf *ibuf;
*gitconfig_repository_format_version = 0;
+ if (extensions)
+ *extensions = NULL;
+ if (nextensions)
+ *nextensions = 0;
*gitconfig_author_name = NULL;
*gitconfig_author_email = NULL;
if (remotes)
if (err)
goto done;
+ if (extensions && nextensions) {
+ err = got_privsep_send_gitconfig_repository_extensions_req(
+ ibuf);
+ if (err)
+ goto done;
+ err = got_privsep_recv_gitconfig_int(nextensions, ibuf);
+ if (err)
+ goto done;
+ if (*nextensions > 0) {
+ int i;
+ *extensions = calloc(*nextensions, sizeof(char *));
+ if (*extensions == NULL) {
+ err = got_error_from_errno("calloc");
+ goto done;
+ }
+ for (i = 0; i < *nextensions; i++) {
+ char *ext;
+ err = got_privsep_recv_gitconfig_str(&ext,
+ ibuf);
+ if (err)
+ goto done;
+ (*extensions)[i] = ext;
+ }
+ }
+ }
+
err = got_privsep_send_gitconfig_author_name_req(ibuf);
if (err)
goto done;
err = parse_gitconfig_file(&dummy_repo_version,
&repo->global_gitconfig_author_name,
&repo->global_gitconfig_author_email,
- NULL, NULL, NULL, global_gitconfig_path);
+ NULL, NULL, NULL, NULL, NULL, global_gitconfig_path);
if (err)
return err;
}
err = parse_gitconfig_file(&repo->gitconfig_repository_format_version,
&repo->gitconfig_author_name, &repo->gitconfig_author_email,
&repo->gitconfig_remotes, &repo->ngitconfig_remotes,
- &repo->gitconfig_owner, repo_gitconfig_path);
+ &repo->gitconfig_owner, &repo->extensions, &repo->nextensions,
+ repo_gitconfig_path);
if (err)
goto done;
done:
return err;
}
+/* Supported repository format extensions. */
+static const char *repo_extensions[] = {
+ "noop", /* Got supports repository format version 1. */
+ "preciousObjects", /* Got has no garbage collection yet. */
+ "worktreeConfig", /* Got does not care about Git work trees. */
+};
+
const struct got_error *
got_repo_open(struct got_repository **repop, const char *path,
const char *global_gitconfig_path)
goto done;
if (repo->gitconfig_repository_format_version != 0)
err = got_error_path(path, GOT_ERR_GIT_REPO_FORMAT);
+ for (i = 0; i < repo->nextensions; i++) {
+ char *ext = repo->extensions[i];
+ int j, supported = 0;
+ for (j = 0; j < nitems(repo_extensions); j++) {
+ if (strcmp(ext, repo_extensions[j]) == 0) {
+ supported = 1;
+ break;
+ }
+ }
+ if (!supported) {
+ err = got_error_path(ext, GOT_ERR_GIT_REPO_EXT);
+ goto done;
+ }
+ }
done:
if (err)
got_repo_close(repo);
for (i = 0; i < repo->ngitconfig_remotes; i++)
got_repo_free_remote_repo_data(&repo->gitconfig_remotes[i]);
free(repo->gitconfig_remotes);
+ for (i = 0; i < repo->nextensions; i++)
+ free(repo->extensions[i]);
+ free(repo->extensions);
free(repo);
return err;
blob - e24545d20956871d467322bef47e09dbcb3c46ed
blob + b0457c7fd3f8239ee5f52338976899dd8ccaefee
--- libexec/got-read-gitconfig/got-read-gitconfig.c
+++ libexec/got-read-gitconfig/got-read-gitconfig.c
return NULL;
}
+static int
+get_boolean_val(char *val)
+{
+ return (strcasecmp(val, "true") == 0 ||
+ strcasecmp(val, "on") == 0 ||
+ strcasecmp(val, "yes") == 0 ||
+ strcmp(val, "1") == 0);
+}
static const struct got_error *
gitconfig_remotes_request(struct imsgbuf *ibuf, struct got_gitconfig *gitconfig)
remotes[i].mirror_references = 0;
mirror = got_gitconfig_get_str(gitconfig, node->field,
"mirror");
- if (mirror != NULL &&
- (strcasecmp(mirror, "true") == 0 ||
- strcasecmp(mirror, "on") == 0 ||
- strcasecmp(mirror, "yes") == 0 ||
- strcmp(mirror, "1") == 0))
+ if (mirror != NULL && get_boolean_val(mirror))
remotes[i].mirror_references = 1;
i++;
return send_gitconfig_str(ibuf, value);
}
+static const struct got_error *
+gitconfig_extensions_request(struct imsgbuf *ibuf,
+ struct got_gitconfig *gitconfig)
+{
+ const struct got_error *err = NULL;
+ struct got_gitconfig_list *tags;
+ struct got_gitconfig_list_node *node;
+ int nextensions = 0;
+ char *val;
+
+ if (gitconfig == NULL)
+ return got_error(GOT_ERR_PRIVSEP_MSG);
+
+ tags = got_gitconfig_get_tag_list(gitconfig, "extensions");
+ if (tags == NULL)
+ return send_gitconfig_int(ibuf, 0);
+
+ TAILQ_FOREACH(node, &tags->fields, link) {
+ val = got_gitconfig_get_str(gitconfig, "extensions",
+ node->field);
+ if (get_boolean_val(val))
+ nextensions++;
+ }
+
+ err = send_gitconfig_int(ibuf, nextensions);
+ if (err)
+ goto done;
+
+ TAILQ_FOREACH(node, &tags->fields, link) {
+ val = got_gitconfig_get_str(gitconfig, "extensions",
+ node->field);
+ if (get_boolean_val(val)) {
+ err = send_gitconfig_str(ibuf, node->field);
+ if (err)
+ goto done;
+ }
+ }
+done:
+ got_gitconfig_free_list(tags);
+ return err;
+}
+
int
main(int argc, char *argv[])
{
err = gitconfig_num_request(&ibuf, gitconfig, "core",
"repositoryformatversion", 0);
break;
+ case GOT_IMSG_GITCONFIG_REPOSITORY_EXTENSIONS_REQUEST:
+ err = gitconfig_extensions_request(&ibuf, gitconfig);
+ break;
case GOT_IMSG_GITCONFIG_AUTHOR_NAME_REQUEST:
err = gitconfig_str_request(&ibuf, gitconfig, "user",
"name");
blob - 5e018f600067c84e853f29b8bdc2f18470f40437
blob + 0db983c06c5b5b41c77198725d7029c5e5ba451a
--- regress/cmdline/checkout.sh
+++ regress/cmdline/checkout.sh
fi
test_done "$testroot" "$ret"
}
+
+test_checkout_repo_with_unknown_extension() {
+ local testroot=`test_init checkout_repo_with_unknown_extension`
+
+ (cd $testroot/repo &&
+ git config --add extensions.badExtension true)
+ (cd $testroot/repo &&
+ git config --add extensions.otherBadExtension 0)
+ echo "got: badExtension: unsupported repository format extension" \
+ > $testroot/stderr.expected
+ got checkout $testroot/repo $testroot/wt \
+ > $testroot/stdout 2> $testroot/stderr
+
+ ret="$?"
+ if [ "$ret" == "0" ]; then
+ echo "got checkout command succeeded unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ fi
+ test_done "$testroot" "$ret"
+}
+
test_parseargs "$@"
run_test test_checkout_basic
run_test test_checkout_dir_exists
run_test test_checkout_into_nonempty_dir
run_test test_checkout_symlink
run_test test_checkout_symlink_relative_wtpath
+run_test test_checkout_repo_with_unknown_extension