git-svn: fix some potential bugs with --follow-parent
[git/dscho.git] / builtin-init-db.c
blob4df9fd0fad7bbc3fd0cde1e6e57b902fbd277608
1 /*
2  * GIT - The information manager from hell
3  *
4  * Copyright (C) Linus Torvalds, 2005
5  */
6 #include "cache.h"
7 #include "builtin.h"
9 #ifndef DEFAULT_GIT_TEMPLATE_DIR
10 #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/"
11 #endif
13 #ifdef NO_TRUSTABLE_FILEMODE
14 #define TEST_FILEMODE 0
15 #else
16 #define TEST_FILEMODE 1
17 #endif
19 static void safe_create_dir(const char *dir, int share)
21         if (mkdir(dir, 0777) < 0) {
22                 if (errno != EEXIST) {
23                         perror(dir);
24                         exit(1);
25                 }
26         }
27         else if (share && adjust_shared_perm(dir))
28                 die("Could not make %s writable by group\n", dir);
31 static int copy_file(const char *dst, const char *src, int mode)
33         int fdi, fdo, status;
35         mode = (mode & 0111) ? 0777 : 0666;
36         if ((fdi = open(src, O_RDONLY)) < 0)
37                 return fdi;
38         if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {
39                 close(fdi);
40                 return fdo;
41         }
42         status = copy_fd(fdi, fdo);
43         close(fdo);
45         if (!status && adjust_shared_perm(dst))
46                 return -1;
48         return status;
51 static void copy_templates_1(char *path, int baselen,
52                              char *template, int template_baselen,
53                              DIR *dir)
55         struct dirent *de;
57         /* Note: if ".git/hooks" file exists in the repository being
58          * re-initialized, /etc/core-git/templates/hooks/update would
59          * cause git-init to fail here.  I think this is sane but
60          * it means that the set of templates we ship by default, along
61          * with the way the namespace under .git/ is organized, should
62          * be really carefully chosen.
63          */
64         safe_create_dir(path, 1);
65         while ((de = readdir(dir)) != NULL) {
66                 struct stat st_git, st_template;
67                 int namelen;
68                 int exists = 0;
70                 if (de->d_name[0] == '.')
71                         continue;
72                 namelen = strlen(de->d_name);
73                 if ((PATH_MAX <= baselen + namelen) ||
74                     (PATH_MAX <= template_baselen + namelen))
75                         die("insanely long template name %s", de->d_name);
76                 memcpy(path + baselen, de->d_name, namelen+1);
77                 memcpy(template + template_baselen, de->d_name, namelen+1);
78                 if (lstat(path, &st_git)) {
79                         if (errno != ENOENT)
80                                 die("cannot stat %s", path);
81                 }
82                 else
83                         exists = 1;
85                 if (lstat(template, &st_template))
86                         die("cannot stat template %s", template);
88                 if (S_ISDIR(st_template.st_mode)) {
89                         DIR *subdir = opendir(template);
90                         int baselen_sub = baselen + namelen;
91                         int template_baselen_sub = template_baselen + namelen;
92                         if (!subdir)
93                                 die("cannot opendir %s", template);
94                         path[baselen_sub++] =
95                                 template[template_baselen_sub++] = '/';
96                         path[baselen_sub] =
97                                 template[template_baselen_sub] = 0;
98                         copy_templates_1(path, baselen_sub,
99                                          template, template_baselen_sub,
100                                          subdir);
101                         closedir(subdir);
102                 }
103                 else if (exists)
104                         continue;
105                 else if (S_ISLNK(st_template.st_mode)) {
106                         char lnk[256];
107                         int len;
108                         len = readlink(template, lnk, sizeof(lnk));
109                         if (len < 0)
110                                 die("cannot readlink %s", template);
111                         if (sizeof(lnk) <= len)
112                                 die("insanely long symlink %s", template);
113                         lnk[len] = 0;
114                         if (symlink(lnk, path))
115                                 die("cannot symlink %s %s", lnk, path);
116                 }
117                 else if (S_ISREG(st_template.st_mode)) {
118                         if (copy_file(path, template, st_template.st_mode))
119                                 die("cannot copy %s to %s", template, path);
120                 }
121                 else
122                         error("ignoring template %s", template);
123         }
126 static void copy_templates(const char *git_dir, int len, const char *template_dir)
128         char path[PATH_MAX];
129         char template_path[PATH_MAX];
130         int template_len;
131         DIR *dir;
133         if (!template_dir) {
134                 template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
135                 if (!template_dir)
136                         template_dir = DEFAULT_GIT_TEMPLATE_DIR;
137         }
138         strcpy(template_path, template_dir);
139         template_len = strlen(template_path);
140         if (template_path[template_len-1] != '/') {
141                 template_path[template_len++] = '/';
142                 template_path[template_len] = 0;
143         }
144         dir = opendir(template_path);
145         if (!dir) {
146                 fprintf(stderr, "warning: templates not found %s\n",
147                         template_dir);
148                 return;
149         }
151         /* Make sure that template is from the correct vintage */
152         strcpy(template_path + template_len, "config");
153         repository_format_version = 0;
154         git_config_from_file(check_repository_format_version,
155                              template_path);
156         template_path[template_len] = 0;
158         if (repository_format_version &&
159             repository_format_version != GIT_REPO_VERSION) {
160                 fprintf(stderr, "warning: not copying templates of "
161                         "a wrong format version %d from '%s'\n",
162                         repository_format_version,
163                         template_dir);
164                 closedir(dir);
165                 return;
166         }
168         memcpy(path, git_dir, len);
169         path[len] = 0;
170         copy_templates_1(path, len,
171                          template_path, template_len,
172                          dir);
173         closedir(dir);
176 static int create_default_files(const char *git_dir, const char *template_path)
178         unsigned len = strlen(git_dir);
179         static char path[PATH_MAX];
180         unsigned char sha1[20];
181         struct stat st1;
182         char repo_version_string[10];
183         int reinit;
184         int filemode;
186         if (len > sizeof(path)-50)
187                 die("insane git directory %s", git_dir);
188         memcpy(path, git_dir, len);
190         if (len && path[len-1] != '/')
191                 path[len++] = '/';
193         /*
194          * Create .git/refs/{heads,tags}
195          */
196         strcpy(path + len, "refs");
197         safe_create_dir(path, 1);
198         strcpy(path + len, "refs/heads");
199         safe_create_dir(path, 1);
200         strcpy(path + len, "refs/tags");
201         safe_create_dir(path, 1);
203         /* First copy the templates -- we might have the default
204          * config file there, in which case we would want to read
205          * from it after installing.
206          */
207         path[len] = 0;
208         copy_templates(path, len, template_path);
210         git_config(git_default_config);
212         /*
213          * We would have created the above under user's umask -- under
214          * shared-repository settings, we would need to fix them up.
215          */
216         if (shared_repository) {
217                 path[len] = 0;
218                 adjust_shared_perm(path);
219                 strcpy(path + len, "refs");
220                 adjust_shared_perm(path);
221                 strcpy(path + len, "refs/heads");
222                 adjust_shared_perm(path);
223                 strcpy(path + len, "refs/tags");
224                 adjust_shared_perm(path);
225         }
227         /*
228          * Create the default symlink from ".git/HEAD" to the "master"
229          * branch, if it does not exist yet.
230          */
231         strcpy(path + len, "HEAD");
232         reinit = !read_ref("HEAD", sha1);
233         if (!reinit) {
234                 if (create_symref("HEAD", "refs/heads/master", NULL) < 0)
235                         exit(1);
236         }
238         /* This forces creation of new config file */
239         sprintf(repo_version_string, "%d", GIT_REPO_VERSION);
240         git_config_set("core.repositoryformatversion", repo_version_string);
242         path[len] = 0;
243         strcpy(path + len, "config");
245         /* Check filemode trustability */
246         filemode = TEST_FILEMODE;
247         if (TEST_FILEMODE && !lstat(path, &st1)) {
248                 struct stat st2;
249                 filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
250                                 !lstat(path, &st2) &&
251                                 st1.st_mode != st2.st_mode);
252         }
253         git_config_set("core.filemode", filemode ? "true" : "false");
255         if (is_bare_repository()) {
256                 git_config_set("core.bare", "true");
257         }
258         else {
259                 git_config_set("core.bare", "false");
260                 /* allow template config file to override the default */
261                 if (log_all_ref_updates == -1)
262                     git_config_set("core.logallrefupdates", "true");
263         }
264         return reinit;
267 static const char init_db_usage[] =
268 "git-init [--template=<template-directory>] [--shared]";
271  * If you want to, you can share the DB area with any number of branches.
272  * That has advantages: you can save space by sharing all the SHA1 objects.
273  * On the other hand, it might just make lookup slower and messier. You
274  * be the judge.  The default case is to have one DB per managed directory.
275  */
276 int cmd_init_db(int argc, const char **argv, const char *prefix)
278         const char *git_dir;
279         const char *sha1_dir;
280         const char *template_dir = NULL;
281         char *path;
282         int len, i, reinit;
284         for (i = 1; i < argc; i++, argv++) {
285                 const char *arg = argv[1];
286                 if (!prefixcmp(arg, "--template="))
287                         template_dir = arg+11;
288                 else if (!strcmp(arg, "--shared"))
289                         shared_repository = PERM_GROUP;
290                 else if (!prefixcmp(arg, "--shared="))
291                         shared_repository = git_config_perm("arg", arg+9);
292                 else
293                         usage(init_db_usage);
294         }
296         /*
297          * Set up the default .git directory contents
298          */
299         git_dir = getenv(GIT_DIR_ENVIRONMENT);
300         if (!git_dir)
301                 git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
302         safe_create_dir(git_dir, 0);
304         /* Check to see if the repository version is right.
305          * Note that a newly created repository does not have
306          * config file, so this will not fail.  What we are catching
307          * is an attempt to reinitialize new repository with an old tool.
308          */
309         check_repository_format();
311         reinit = create_default_files(git_dir, template_dir);
313         /*
314          * And set up the object store.
315          */
316         sha1_dir = get_object_directory();
317         len = strlen(sha1_dir);
318         path = xmalloc(len + 40);
319         memcpy(path, sha1_dir, len);
321         safe_create_dir(sha1_dir, 1);
322         strcpy(path+len, "/pack");
323         safe_create_dir(path, 1);
324         strcpy(path+len, "/info");
325         safe_create_dir(path, 1);
327         if (shared_repository) {
328                 char buf[10];
329                 /* We do not spell "group" and such, so that
330                  * the configuration can be read by older version
331                  * of git.
332                  */
333                 sprintf(buf, "%d", shared_repository);
334                 git_config_set("core.sharedrepository", buf);
335                 git_config_set("receive.denyNonFastforwards", "true");
336         }
338         printf("%s%s Git repository in %s/\n",
339                 reinit ? "Reinitialized existing" : "Initialized empty",
340                 shared_repository ? " shared" : "",
341                 git_dir);
343         return 0;