{"thread":{"id":"12588","subject":"[PATCH 09/11] Provide API access to init_db()","startedAt":"2008-03-08T23:04:21Z","lastAt":"2008-03-09T20:43:46Z","messageCount":4,"participants":["Daniel Barkalow","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":11},"messages":[{"id":"71461","messageId":"alpine.LNX.1.00.0803081804200.19665@iabervon.org","threadId":"12588","inReplyTo":null,"subject":"[PATCH 09/11] Provide API access to init_db()","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-03-08T23:04:21Z","receivedAt":"2008-03-08T23:04:21Z","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---\n builtin-init-db.c |  183 +++++++++++++++++++++++++++--------------------------\n cache.h           |    4 +\n 2 files changed, 98 insertions(+), 89 deletions(-)\n\ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex 79eaf8d..4f93d03 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 \tunsigned char sha1[20];\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,21 +205,16 @@ 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+ \n \t/*\n \t * Create the default symlink from \".git/HEAD\" to the \"master\"\n \t * branch, if it does not exist yet.\n \t */\n-\tstrcpy(path + len, \"HEAD\");\n \treinit = !read_ref(\"HEAD\", sha1);\n \tif (!reinit) {\n \t\tif (create_symref(\"HEAD\", \"refs/heads/master\", NULL) < 0)\n@@ -250,8 +246,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@@ -271,42 +269,83 @@ 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.\n+\t\t */\n+\t\tsprintf(buf, \"%d\", shared_repository);\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@@ -321,11 +360,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@@ -336,7 +373,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@@ -353,64 +390,32 @@ 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+\tif (is_bare_repository_cfg < 0)\n+\t\tis_bare_repository_cfg = guess_repository_type(git_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.\n-\t\t */\n-\t\tsprintf(buf, \"%d\", shared_repository);\n-\t\tgit_config_set(\"core.sharedrepository\", buf);\n-\t\tgit_config_set(\"receive.denyNonFastforwards\", \"true\");\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\tgit_work_tree_cfg = strdup(make_absolute_path(xstrndup(git_dir, git_dir_parent - git_dir)));\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 32e8746..59805b8 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.327.g614d7.dirty\n\n"},{"id":"71477","messageId":"alpine.LSU.1.00.0803090026170.3975@racer.site","threadId":"12588","inReplyTo":"alpine.LNX.1.00.0803081804200.19665@iabervon.org","subject":"Re: [PATCH 09/11] Provide API access to init_db()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-08T23:27:31Z","receivedAt":"2008-03-08T23:27:31Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 8 Mar 2008, Daniel Barkalow wrote:\n\n> The caller first calls set_git_dir() to specify the GIT_DIR, and then \n> calls init_db() to initialize it. This also cleans up various parts of \n> the code to account for the fact that everything is done with GIT_DIR \n> set, so it's unnecessary to pass the specified directory around.\n\nI think the most controversial part is that you change the way it is \ndetermined if the repository is a bare one.  It might have the same \nresult (I do not have time to check it...), but the computation is \nperformed differently.\n\nCiao,\nDscho\n"},{"id":"71483","messageId":"alpine.LNX.1.00.0803081840070.19665@iabervon.org","threadId":"12588","inReplyTo":"alpine.LSU.1.00.0803090026170.3975@racer.site","subject":"Re: [PATCH 09/11] Provide API access to init_db()","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-03-08T23:55:29Z","receivedAt":"2008-03-08T23:55:29Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sun, 9 Mar 2008, Johannes Schindelin wrote:\n\n> On Sat, 8 Mar 2008, Daniel Barkalow wrote:\n> \n> > The caller first calls set_git_dir() to specify the GIT_DIR, and then \n> > calls init_db() to initialize it. This also cleans up various parts of \n> > the code to account for the fact that everything is done with GIT_DIR \n> > set, so it's unnecessary to pass the specified directory around.\n> \n> I think the most controversial part is that you change the way it is \n> determined if the repository is a bare one.  It might have the same \n> result (I do not have time to check it...), but the computation is \n> performed differently.\n\nIt's actually doing the same computation; the difference is how the result \nis reported. Mine commits to the repo being non-bare if it doesn't think \nit's bare, which the current code leaves as \"we don't know, assume \nnon-bare\". But since we actually create a work tree if we guess it's \nnon-bare, it really is non-bare. So then the later code can assume it's \neither 0 or 1, and not worry about -1 being equivalent to 0.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"71522","messageId":"alpine.LSU.1.00.0803092143370.3975@racer.site","threadId":"12588","inReplyTo":"alpine.LNX.1.00.0803081840070.19665@iabervon.org","subject":"Re: [PATCH 09/11] Provide API access to init_db()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-09T20:43:46Z","receivedAt":"2008-03-09T20:43:46Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 8 Mar 2008, Daniel Barkalow wrote:\n\n> On Sun, 9 Mar 2008, Johannes Schindelin wrote:\n> \n> > On Sat, 8 Mar 2008, Daniel Barkalow wrote:\n> > \n> > > The caller first calls set_git_dir() to specify the GIT_DIR, and then \n> > > calls init_db() to initialize it. This also cleans up various parts of \n> > > the code to account for the fact that everything is done with GIT_DIR \n> > > set, so it's unnecessary to pass the specified directory around.\n> > \n> > I think the most controversial part is that you change the way it is \n> > determined if the repository is a bare one.  It might have the same \n> > result (I do not have time to check it...), but the computation is \n> > performed differently.\n> \n> It's actually doing the same computation; the difference is how the result \n> is reported. Mine commits to the repo being non-bare if it doesn't think \n> it's bare, which the current code leaves as \"we don't know, assume \n> non-bare\". But since we actually create a work tree if we guess it's \n> non-bare, it really is non-bare. So then the later code can assume it's \n> either 0 or 1, and not worry about -1 being equivalent to 0.\n\nOkay.\n\nThanks,\nDscho\n"}]}