Make "read-tree" read the tree into the current directory cache.
[git.git] / read-tree.c
1 /*
2  * GIT - The information manager from hell
3  *
4  * Copyright (C) Linus Torvalds, 2005
5  */
6 #include "cache.h"
7
8 static int read_one_entry(unsigned char *sha1, const char *pathname, unsigned mode)
9 {
10         int len = strlen(pathname);
11         unsigned int size = cache_entry_size(len);
12         struct cache_entry *ce = malloc(size);
13
14         memset(ce, 0, size);
15
16         ce->st_mode = mode;
17         ce->namelen = len;
18         memcpy(ce->name, pathname, len+1);
19         memcpy(ce->sha1, sha1, 20);
20         return add_cache_entry(ce);
21 }
22
23 static int read_tree(unsigned char *sha1)
24 {
25         void *buffer;
26         unsigned long size;
27         char type[20];
28
29         buffer = read_sha1_file(sha1, type, &size);
30         if (!buffer)
31                 return -1;
32         if (strcmp(type, "tree"))
33                 return -1;
34         while (size) {
35                 int len = strlen(buffer)+1;
36                 unsigned char *sha1 = buffer + len;
37                 char *path = strchr(buffer, ' ')+1;
38                 unsigned int mode;
39
40                 if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1)
41                         return -1;
42
43                 buffer = sha1 + 20;
44                 size -= len + 20;
45
46                 if (read_one_entry(sha1, path, mode) < 0)
47                         return -1;
48         }
49         return 0;
50 }
51
52 int main(int argc, char **argv)
53 {
54         int i, newfd;
55         unsigned char sha1[20];
56
57         newfd = open(".dircache/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600);
58         if (newfd < 0)
59                 usage("unable to create new cachefile");
60
61         for (i = 1; i < argc; i++) {
62                 const char *arg = argv[i];
63
64                 /* "-m" stands for "merge" current directory cache */
65                 if (!strcmp(arg, "-m")) {
66                         if (active_cache) {
67                                 fprintf(stderr, "read-tree: cannot merge old cache on top of new\n");
68                                 goto out;
69                         }
70                         if (read_cache() < 0) {
71                                 fprintf(stderr, "read-tree: corrupt directory cache\n");
72                                 goto out;
73                         }
74                         continue;
75                 }
76                 if (get_sha1_hex(arg, sha1) < 0) {
77                         fprintf(stderr, "read-tree [-m] <sha1>\n");
78                         goto out;
79                 }
80                 if (read_tree(sha1) < 0) {
81                         fprintf(stderr, "failed to unpack tree object %s\n", arg);
82                         goto out;
83                 }
84         }
85         if (!write_cache(newfd, active_cache, active_nr) && !rename(".dircache/index.lock", ".dircache/index"))
86                 return 0;
87
88 out:
89         unlink(".dircache/index.lock");
90         exit(1);
91 }