{"thread":{"id":"13294","subject":"[PATCH 7/8] Provide API access to init_db()","startedAt":"2008-04-27T17:39:27Z","lastAt":"2008-04-27T22:01:21Z","messageCount":2,"participants":["Daniel Barkalow","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"75315","messageId":"alpine.LNX.1.00.0804271305000.19665@iabervon.org","threadId":"13294","inReplyTo":null,"subject":"[PATCH 7/8] Provide API access to init_db()","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-04-27T17:39:27Z","receivedAt":"2008-04-27T17:39:27Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"The caller first calls set_git_dir() to specify the GIT_DIR, and then\ncalls init_db() to initialize it. This also cleans up various parts of\nthe code to account for the fact that everything is done with GIT_DIR\nset, so it's unnecessary to pass the specified directory around.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n---\nRebased onto current origin/master.\n\n builtin-init-db.c |  201 ++++++++++++++++++++++++++++-------------------------\n cache.h           |    4 +\n 2 files changed, 110 insertions(+), 95 deletions(-)\n\ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex a76f5d3..1ea8bb2 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -104,12 +104,14 @@ static void copy_templates_1(char *path, int baselen,\n \t}\n }\n \n-static void copy_templates(const char *git_dir, int len, const char *template_dir)\n+static void copy_templates(const char *template_dir)\n {\n \tchar path[PATH_MAX];\n \tchar template_path[PATH_MAX];\n \tint template_len;\n \tDIR *dir;\n+\tconst char *git_dir = get_git_dir();\n+\tint len = strlen(git_dir);\n \n \tif (!template_dir)\n \t\ttemplate_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);\n@@ -156,6 +158,8 @@ static void copy_templates(const char *git_dir, int len, const char *template_di\n \t}\n \n \tmemcpy(path, git_dir, len);\n+\tif (len && path[len - 1] != '/')\n+\t\tpath[len++] = '/';\n \tpath[len] = 0;\n \tcopy_templates_1(path, len,\n \t\t\t template_path, template_len,\n@@ -163,8 +167,9 @@ static void copy_templates(const char *git_dir, int len, const char *template_di\n \tclosedir(dir);\n }\n \n-static int create_default_files(const char *git_dir, const char *template_path)\n+static int create_default_files(const char *template_path)\n {\n+\tconst char *git_dir = get_git_dir();\n \tunsigned len = strlen(git_dir);\n \tstatic char path[PATH_MAX];\n \tstruct stat st1;\n@@ -183,19 +188,15 @@ static int create_default_files(const char *git_dir, const char *template_path)\n \t/*\n \t * Create .git/refs/{heads,tags}\n \t */\n-\tstrcpy(path + len, \"refs\");\n-\tsafe_create_dir(path, 1);\n-\tstrcpy(path + len, \"refs/heads\");\n-\tsafe_create_dir(path, 1);\n-\tstrcpy(path + len, \"refs/tags\");\n-\tsafe_create_dir(path, 1);\n+\tsafe_create_dir(git_path(\"refs\"), 1);\n+\tsafe_create_dir(git_path(\"refs/heads\"), 1);\n+\tsafe_create_dir(git_path(\"refs/tags\"), 1);\n \n \t/* First copy the templates -- we might have the default\n \t * config file there, in which case we would want to read\n \t * from it after installing.\n \t */\n-\tpath[len] = 0;\n-\tcopy_templates(path, len, template_path);\n+\tcopy_templates(template_path);\n \n \tgit_config(git_default_config);\n \n@@ -204,14 +205,10 @@ static int create_default_files(const char *git_dir, const char *template_path)\n \t * shared-repository settings, we would need to fix them up.\n \t */\n \tif (shared_repository) {\n-\t\tpath[len] = 0;\n-\t\tadjust_shared_perm(path);\n-\t\tstrcpy(path + len, \"refs\");\n-\t\tadjust_shared_perm(path);\n-\t\tstrcpy(path + len, \"refs/heads\");\n-\t\tadjust_shared_perm(path);\n-\t\tstrcpy(path + len, \"refs/tags\");\n-\t\tadjust_shared_perm(path);\n+\t\tadjust_shared_perm(get_git_dir());\n+\t\tadjust_shared_perm(git_path(\"refs\"));\n+\t\tadjust_shared_perm(git_path(\"refs/heads\"));\n+\t\tadjust_shared_perm(git_path(\"refs/tags\"));\n \t}\n \n \t/*\n@@ -251,8 +248,10 @@ static int create_default_files(const char *git_dir, const char *template_path)\n \t\t/* allow template config file to override the default */\n \t\tif (log_all_ref_updates == -1)\n \t\t    git_config_set(\"core.logallrefupdates\", \"true\");\n-\t\tif (work_tree != git_work_tree_cfg)\n+\t\tif (prefixcmp(git_dir, work_tree) ||\n+\t\t    strcmp(git_dir + strlen(work_tree), \"/.git\")) {\n \t\t\tgit_config_set(\"core.worktree\", work_tree);\n+\t\t}\n \t}\n \n \t/* Check if symlink is supported in the work tree */\n@@ -272,42 +271,92 @@ static int create_default_files(const char *git_dir, const char *template_path)\n \treturn reinit;\n }\n \n-static void guess_repository_type(const char *git_dir)\n+int init_db(const char *template_dir, unsigned int flags)\n+{\n+\tconst char *sha1_dir;\n+\tchar *path;\n+\tint len, reinit;\n+\n+\tsafe_create_dir(get_git_dir(), 0);\n+\n+\t/* Check to see if the repository version is right.\n+\t * Note that a newly created repository does not have\n+\t * config file, so this will not fail.  What we are catching\n+\t * is an attempt to reinitialize new repository with an old tool.\n+\t */\n+\tcheck_repository_format();\n+\n+\treinit = create_default_files(template_dir);\n+\n+\tsha1_dir = get_object_directory();\n+\tlen = strlen(sha1_dir);\n+\tpath = xmalloc(len + 40);\n+\tmemcpy(path, sha1_dir, len);\n+\n+\tsafe_create_dir(sha1_dir, 1);\n+\tstrcpy(path+len, \"/pack\");\n+\tsafe_create_dir(path, 1);\n+\tstrcpy(path+len, \"/info\");\n+\tsafe_create_dir(path, 1);\n+\n+\tif (shared_repository) {\n+\t\tchar buf[10];\n+\t\t/* We do not spell \"group\" and such, so that\n+\t\t * the configuration can be read by older version\n+\t\t * of git. Note, we use octal numbers for new share modes,\n+\t\t * and compatibility values for PERM_GROUP and\n+\t\t * PERM_EVERYBODY.\n+\t\t */\n+\t\tsprintf(buf, \"%d\", shared_repository);\n+\t\tif (shared_repository == PERM_GROUP)\n+\t\t\tsprintf(buf, \"%d\", OLD_PERM_GROUP);\n+\t\telse if (shared_repository == PERM_EVERYBODY)\n+\t\t\tsprintf(buf, \"%d\", OLD_PERM_EVERYBODY);\n+\t\telse\n+\t\t\tsprintf(buf, \"0%o\", shared_repository);\n+\n+\t\tgit_config_set(\"core.sharedrepository\", buf);\n+\t\tgit_config_set(\"receive.denyNonFastforwards\", \"true\");\n+\t}\n+\n+\tif (!(flags & INIT_DB_QUIET))\n+\t\tprintf(\"%s%s Git repository in %s/\\n\",\n+\t\t       reinit ? \"Reinitialized existing\" : \"Initialized empty\",\n+\t\t       shared_repository ? \" shared\" : \"\",\n+\t\t       get_git_dir());\n+\n+\treturn 0;\n+}\n+\n+static int guess_repository_type(const char *git_dir)\n {\n \tchar cwd[PATH_MAX];\n \tconst char *slash;\n \n-\tif (0 <= is_bare_repository_cfg)\n-\t\treturn;\n-\tif (!git_dir)\n-\t\treturn;\n-\n \t/*\n \t * \"GIT_DIR=. git init\" is always bare.\n \t * \"GIT_DIR=`pwd` git init\" too.\n \t */\n \tif (!strcmp(\".\", git_dir))\n-\t\tgoto force_bare;\n+\t\treturn 1;\n \tif (!getcwd(cwd, sizeof(cwd)))\n \t\tdie(\"cannot tell cwd\");\n \tif (!strcmp(git_dir, cwd))\n-\t\tgoto force_bare;\n+\t\treturn 1;\n \t/*\n \t * \"GIT_DIR=.git or GIT_DIR=something/.git is usually not.\n \t */\n \tif (!strcmp(git_dir, \".git\"))\n-\t\treturn;\n+\t\treturn 0;\n \tslash = strrchr(git_dir, '/');\n \tif (slash && !strcmp(slash, \"/.git\"))\n-\t\treturn;\n+\t\treturn 0;\n \n \t/*\n \t * Otherwise it is often bare.  At this point\n \t * we are just guessing.\n \t */\n- force_bare:\n-\tis_bare_repository_cfg = 1;\n-\treturn;\n+\treturn 1;\n }\n \n static const char init_db_usage[] =\n@@ -322,11 +371,9 @@ static const char init_db_usage[] =\n int cmd_init_db(int argc, const char **argv, const char *prefix)\n {\n \tconst char *git_dir;\n-\tconst char *sha1_dir;\n \tconst char *template_dir = NULL;\n-\tchar *path;\n-\tint len, i, reinit;\n-\tint quiet = 0;\n+\tunsigned int flags = 0;\n+\tint i;\n \n \tfor (i = 1; i < argc; i++, argv++) {\n \t\tconst char *arg = argv[1];\n@@ -337,7 +384,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \t\telse if (!prefixcmp(arg, \"--shared=\"))\n \t\t\tshared_repository = git_config_perm(\"arg\", arg+9);\n \t\telse if (!strcmp(arg, \"-q\") || !strcmp(arg, \"--quiet\"))\n-\t\t        quiet = 1;\n+\t\t\tflags |= INIT_DB_QUIET;\n \t\telse\n \t\t\tusage(init_db_usage);\n \t}\n@@ -354,71 +401,35 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \t\t    GIT_WORK_TREE_ENVIRONMENT,\n \t\t    GIT_DIR_ENVIRONMENT);\n \n-\tguess_repository_type(git_dir);\n-\n-\tif (is_bare_repository_cfg <= 0) {\n-\t\tgit_work_tree_cfg = xcalloc(PATH_MAX, 1);\n-\t\tif (!getcwd(git_work_tree_cfg, PATH_MAX))\n-\t\t\tdie (\"Cannot access current working directory.\");\n-\t\tif (access(get_git_work_tree(), X_OK))\n-\t\t\tdie (\"Cannot access work tree '%s'\",\n-\t\t\t     get_git_work_tree());\n-\t}\n-\n \t/*\n \t * Set up the default .git directory contents\n \t */\n-\tgit_dir = getenv(GIT_DIR_ENVIRONMENT);\n \tif (!git_dir)\n \t\tgit_dir = DEFAULT_GIT_DIR_ENVIRONMENT;\n-\tsafe_create_dir(git_dir, 0);\n-\n-\t/* Check to see if the repository version is right.\n-\t * Note that a newly created repository does not have\n-\t * config file, so this will not fail.  What we are catching\n-\t * is an attempt to reinitialize new repository with an old tool.\n-\t */\n-\tcheck_repository_format();\n-\n-\treinit = create_default_files(git_dir, template_dir);\n \n-\t/*\n-\t * And set up the object store.\n-\t */\n-\tsha1_dir = get_object_directory();\n-\tlen = strlen(sha1_dir);\n-\tpath = xmalloc(len + 40);\n-\tmemcpy(path, sha1_dir, len);\n-\n-\tsafe_create_dir(sha1_dir, 1);\n-\tstrcpy(path+len, \"/pack\");\n-\tsafe_create_dir(path, 1);\n-\tstrcpy(path+len, \"/info\");\n-\tsafe_create_dir(path, 1);\n-\n-\tif (shared_repository) {\n-\t\tchar buf[10];\n-\t\t/* We do not spell \"group\" and such, so that\n-\t\t * the configuration can be read by older version\n-\t\t * of git. Note, we use octal numbers for new share modes,\n-\t\t * and compatibility values for PERM_GROUP and\n-\t\t * PERM_EVERYBODY.\n-\t\t */\n-\t\tif (shared_repository == PERM_GROUP)\n-\t\t\tsprintf(buf, \"%d\", OLD_PERM_GROUP);\n-\t\telse if (shared_repository == PERM_EVERYBODY)\n-\t\t\tsprintf(buf, \"%d\", OLD_PERM_EVERYBODY);\n-\t\telse\n-\t\t\tsprintf(buf, \"0%o\", shared_repository);\n-\t\tgit_config_set(\"core.sharedrepository\", buf);\n-\t\tgit_config_set(\"receive.denyNonFastforwards\", \"true\");\n+\tif (is_bare_repository_cfg < 0)\n+\t\tis_bare_repository_cfg = guess_repository_type(git_dir);\n+\n+\tif (!is_bare_repository_cfg) {\n+\t\tif (git_dir) {\n+\t\t\tconst char *git_dir_parent = strrchr(git_dir, '/');\n+\t\t\tif (git_dir_parent) {\n+\t\t\t\tchar *rel = xstrndup(git_dir, git_dir_parent - git_dir);\n+\t\t\t\tgit_work_tree_cfg = xstrdup(make_absolute_path(rel));\n+\t\t\t\tfree(rel);\n+\t\t\t}\n+\t\t}\n+\t\tif (!git_work_tree_cfg) {\n+\t\t\tgit_work_tree_cfg = xcalloc(PATH_MAX, 1);\n+\t\t\tif (!getcwd(git_work_tree_cfg, PATH_MAX))\n+\t\t\t\tdie (\"Cannot access current working directory.\");\n+\t\t}\n+\t\tif (access(get_git_work_tree(), X_OK))\n+\t\t\tdie (\"Cannot access work tree '%s'\",\n+\t\t\t     get_git_work_tree());\n \t}\n \n-\tif (!quiet)\n-\t\tprintf(\"%s%s Git repository in %s/\\n\",\n-\t\t       reinit ? \"Reinitialized existing\" : \"Initialized empty\",\n-\t\t       shared_repository ? \" shared\" : \"\",\n-\t\t       git_dir);\n+\tset_git_dir(make_absolute_path(git_dir));\n \n-\treturn 0;\n+\treturn init_db(template_dir, flags);\n }\ndiff --git a/cache.h b/cache.h\nindex b337b3d..2fdd463 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -324,6 +324,10 @@ extern const char *prefix_filename(const char *prefix, int len, const char *path\n extern void verify_filename(const char *prefix, const char *name);\n extern void verify_non_filename(const char *prefix, const char *name);\n \n+#define INIT_DB_QUIET 0x0001\n+\n+extern int init_db(const char *template_dir, unsigned int flags);\n+\n #define alloc_nr(x) (((x)+16)*3/2)\n \n /*\n-- \n1.5.4.3.610.gea6cd\n"},{"id":"75334","messageId":"7vr6crdkjy.fsf@gitster.siamese.dyndns.org","threadId":"13294","inReplyTo":"alpine.LNX.1.00.0804271305000.19665@iabervon.org","subject":"Re: [PATCH 7/8] Provide API access to init_db()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-04-27T22:01:21Z","receivedAt":"2008-04-27T22:01:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Barkalow <barkalow@iabervon.org> writes:\n\n> ...\n> +\t\t * PERM_EVERYBODY.\n> +\t\t */\n> +\t\tsprintf(buf, \"%d\", shared_repository);\n\nThis line is superfluous (no need to send amended patch).\n\n> +\t\tif (shared_repository == PERM_GROUP)\n> +\t\t\tsprintf(buf, \"%d\", OLD_PERM_GROUP);\n> ...\n\n\n> +\tif (is_bare_repository_cfg < 0)\n> +\t\tis_bare_repository_cfg = guess_repository_type(git_dir);\n> +\n> +\tif (!is_bare_repository_cfg) {\n> +\t\tif (git_dir) {\n> +\t\t\tconst char *git_dir_parent = strrchr(git_dir, '/');\n> +\t\t\tif (git_dir_parent) {\n> +\t\t\t\tchar *rel = xstrndup(git_dir, git_dir_parent - git_dir);\n> +\t\t\t\tgit_work_tree_cfg = xstrdup(make_absolute_path(rel));\n> +\t\t\t\tfree(rel);\n\nGood change to plug a leak and make the code easier to read..\n"}]}