1/*
2* GIT - The information manager from hell
3*
4* Copyright (C) Linus Torvalds, 2005
5*/
6#include "cache.h"
78
static void safe_create_dir(const char *dir)
9{
10if (mkdir(dir, 0777) < 0) {
11if (errno != EEXIST) {
12perror(dir);
13exit(1);
14}
15}
16}
1718
static int copy_file(const char *dst, const char *src, int mode)
19{
20int fdi, fdo;
2122
mode = (mode & 0111) ? 0777 : 0666;
23if ((fdi = open(src, O_RDONLY)) < 0)
24return fdi;
25if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {
26close(fdi);
27return fdo;
28}
29while (1) {
30char buf[BUFSIZ];
31ssize_t leni, leno, ofs;
32leni = read(fdi, buf, sizeof(buf));
33if (leni < 0) {
34error_return:
35close(fdo);
36close(fdi);
37return -1;
38}
39if (!leni)
40break;
41ofs = 0;
42do {
43leno = write(fdo, buf+ofs, leni);
44if (leno < 0)
45goto error_return;
46leni -= leno;
47ofs += leno;
48} while (0 < leni);
49}
50close(fdo);
51close(fdi);
52return 0;
53}
5455
static void copy_templates_1(char *path, int baselen,
56char *template, int template_baselen,
57DIR *dir)
58{
59struct dirent *de;
6061
/* Note: if ".git/hooks" file exists in the repository being
62* re-initialized, /etc/core-git/templates/hooks/update would
63* cause git-init-db to fail here. I think this is sane but
64* it means that the set of templates we ship by default, along
65* with the way the namespace under .git/ is organized, should
66* be really carefully chosen.
67*/
68safe_create_dir(path);
69while ((de = readdir(dir)) != NULL) {
70struct stat st_git, st_template;
71int namelen;
72int exists = 0;
7374
if (de->d_name[0] == '.')
75continue;
76namelen = strlen(de->d_name);
77if ((PATH_MAX <= baselen + namelen) ||
78(PATH_MAX <= template_baselen + namelen))
79die("insanely long template name %s", de->d_name);
80memcpy(path + baselen, de->d_name, namelen+1);
81memcpy(template + template_baselen, de->d_name, namelen+1);
82if (lstat(path, &st_git)) {
83if (errno != ENOENT)
84die("cannot stat %s", path);
85}
86else
87exists = 1;
8889
if (lstat(template, &st_template))
90die("cannot stat template %s", template);
9192
if (S_ISDIR(st_template.st_mode)) {
93DIR *subdir = opendir(template);
94int baselen_sub = baselen + namelen;
95int template_baselen_sub = template_baselen + namelen;
96if (!subdir)
97die("cannot opendir %s", template);
98path[baselen_sub++] =
99template[template_baselen_sub++] = '/';
100path[baselen_sub] =
101template[template_baselen_sub] = 0;
102copy_templates_1(path, baselen_sub,
103template, template_baselen_sub,
104subdir);
105closedir(subdir);
106}
107else if (exists)
108continue;
109else if (S_ISLNK(st_template.st_mode)) {
110char lnk[256];
111int len;
112len = readlink(template, lnk, sizeof(lnk));
113if (len < 0)
114die("cannot readlink %s", template);
115if (sizeof(lnk) <= len)
116die("insanely long symlink %s", template);
117lnk[len] = 0;
118if (symlink(lnk, path))
119die("cannot symlink %s %s", lnk, path);
120}
121else if (S_ISREG(st_template.st_mode)) {
122if (copy_file(path, template, st_template.st_mode))
123die("cannot copy %s to %s", template, path);
124}
125else
126error("ignoring template %s", template);
127}
128}
129130
static void copy_templates(const char *git_dir)
131{
132char path[PATH_MAX];
133char template_path[PATH_MAX];
134char *template_dir;
135int len, template_len;
136DIR *dir;
137138
strcpy(path, git_dir);
139len = strlen(path);
140template_dir = gitenv(TEMPLATE_DIR_ENVIRONMENT);
141if (!template_dir)
142template_dir = DEFAULT_GIT_TEMPLATE_ENVIRONMENT;
143strcpy(template_path, template_dir);
144template_len = strlen(template_path);
145if (template_path[template_len-1] != '/') {
146template_path[template_len++] = '/';
147template_path[template_len] = 0;
148}
149150
dir = opendir(template_path);
151if (!dir)
152return;
153copy_templates_1(path, len,
154template_path, template_len,
155dir);
156closedir(dir);
157}
158159
static void create_default_files(const char *git_dir)
160{
161unsigned len = strlen(git_dir);
162static char path[PATH_MAX];
163164
if (len > sizeof(path)-50)
165die("insane git directory %s", git_dir);
166memcpy(path, git_dir, len);
167168
if (len && path[len-1] != '/')
169path[len++] = '/';
170171
/*
172* Create .git/refs/{heads,tags}
173*/
174strcpy(path + len, "refs");
175safe_create_dir(path);
176strcpy(path + len, "refs/heads");
177safe_create_dir(path);
178strcpy(path + len, "refs/tags");
179safe_create_dir(path);
180181
/*
182* Create the default symlink from ".git/HEAD" to the "master"
183* branch
184*/
185strcpy(path + len, "HEAD");
186if (symlink("refs/heads/master", path) < 0) {
187if (errno != EEXIST) {
188perror(path);
189exit(1);
190}
191}
192path[len] = 0;
193copy_templates(path);
194}
195196
/*
197* If you want to, you can share the DB area with any number of branches.
198* That has advantages: you can save space by sharing all the SHA1 objects.
199* On the other hand, it might just make lookup slower and messier. You
200* be the judge. The default case is to have one DB per managed directory.
201*/
202int main(int argc, char **argv)
203{
204const char *git_dir;
205const char *sha1_dir;
206char *path;
207int len, i;
208209
/*
210* Set up the default .git directory contents
211*/
212git_dir = gitenv(GIT_DIR_ENVIRONMENT);
213if (!git_dir) {
214git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
215fprintf(stderr, "defaulting to local storage area\n");
216}
217safe_create_dir(git_dir);
218create_default_files(git_dir);
219220
/*
221* And set up the object store.
222*/
223sha1_dir = get_object_directory();
224len = strlen(sha1_dir);
225path = xmalloc(len + 40);
226memcpy(path, sha1_dir, len);
227228
safe_create_dir(sha1_dir);
229for (i = 0; i < 256; i++) {
230sprintf(path+len, "/%02x", i);
231safe_create_dir(path);
232}
233strcpy(path+len, "/pack");
234safe_create_dir(path);
235return 0;
236}