Make "write_cache()" and friends available as generic routines.
[git/git.git] / read-tree.c
CommitLineData
8bc9a0c7
LT
1/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
e83c5163
LT
6#include "cache.h"
7
e497ea2a
LT
8static void create_directories(const char *path)
9{
10 int len = strlen(path);
11 char *buf = malloc(len + 1);
12 const char *slash = path;
13
14 while ((slash = strchr(slash+1, '/')) != NULL) {
15 len = slash - path;
16 memcpy(buf, path, len);
17 buf[len] = 0;
18 mkdir(buf, 0700);
19 }
20}
21
22static int create_file(const char *path)
23{
24 int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
25 if (fd < 0) {
26 if (errno == ENOENT) {
27 create_directories(path);
28 fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
29 }
30 }
31 return fd;
32}
33
e83c5163
LT
34static int unpack(unsigned char *sha1)
35{
36 void *buffer;
37 unsigned long size;
38 char type[20];
39
40 buffer = read_sha1_file(sha1, type, &size);
41 if (!buffer)
42 usage("unable to read sha1 file");
43 if (strcmp(type, "tree"))
44 usage("expected a 'tree' node");
45 while (size) {
46 int len = strlen(buffer)+1;
47 unsigned char *sha1 = buffer + len;
48 char *path = strchr(buffer, ' ')+1;
e497ea2a
LT
49 char *data;
50 unsigned long filesize;
e83c5163 51 unsigned int mode;
e497ea2a
LT
52 int fd;
53
e83c5163
LT
54 if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1)
55 usage("corrupt 'tree' file");
56 buffer = sha1 + 20;
57 size -= len + 20;
e497ea2a
LT
58 data = read_sha1_file(sha1, type, &filesize);
59 if (!data || strcmp(type, "blob"))
60 usage("tree file refers to bad file data");
61 fd = create_file(path);
62 if (fd < 0)
63 usage("unable to create file");
64 if (write(fd, data, filesize) != filesize)
65 usage("unable to write file");
66 fchmod(fd, mode);
67 close(fd);
68 free(data);
e83c5163
LT
69 }
70 return 0;
71}
72
73int main(int argc, char **argv)
74{
e83c5163
LT
75 unsigned char sha1[20];
76
77 if (argc != 2)
78 usage("read-tree <key>");
79 if (get_sha1_hex(argv[1], sha1) < 0)
80 usage("read-tree <key>");
81 sha1_file_directory = getenv(DB_ENVIRONMENT);
82 if (!sha1_file_directory)
83 sha1_file_directory = DEFAULT_DB_ENVIRONMENT;
84 if (unpack(sha1) < 0)
85 usage("unpack failed");
86 return 0;
87}