Commit | Line | Data |
---|---|---|
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 | ||
f768846e | 8 | static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode) |
e497ea2a | 9 | { |
83adac3c | 10 | int len = strlen(pathname); |
f768846e | 11 | unsigned int size = cache_entry_size(baselen + len); |
83adac3c | 12 | struct cache_entry *ce = malloc(size); |
e497ea2a | 13 | |
83adac3c | 14 | memset(ce, 0, size); |
e497ea2a | 15 | |
ccc4feb5 LT |
16 | ce->ce_mode = htonl(mode); |
17 | ce->ce_namelen = htons(baselen + len); | |
f768846e LT |
18 | memcpy(ce->name, base, baselen); |
19 | memcpy(ce->name + baselen, pathname, len+1); | |
83adac3c | 20 | memcpy(ce->sha1, sha1, 20); |
121481ab | 21 | return add_cache_entry(ce, 1); |
e497ea2a LT |
22 | } |
23 | ||
f768846e | 24 | static int read_tree(unsigned char *sha1, const char *base, int baselen) |
e83c5163 LT |
25 | { |
26 | void *buffer; | |
27 | unsigned long size; | |
28 | char type[20]; | |
29 | ||
30 | buffer = read_sha1_file(sha1, type, &size); | |
31 | if (!buffer) | |
83adac3c | 32 | return -1; |
e83c5163 | 33 | if (strcmp(type, "tree")) |
83adac3c | 34 | return -1; |
e83c5163 LT |
35 | while (size) { |
36 | int len = strlen(buffer)+1; | |
37 | unsigned char *sha1 = buffer + len; | |
38 | char *path = strchr(buffer, ' ')+1; | |
39 | unsigned int mode; | |
e497ea2a | 40 | |
e83c5163 | 41 | if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1) |
83adac3c LT |
42 | return -1; |
43 | ||
e83c5163 LT |
44 | buffer = sha1 + 20; |
45 | size -= len + 20; | |
83adac3c | 46 | |
f768846e LT |
47 | if (S_ISDIR(mode)) { |
48 | int retval; | |
49 | int pathlen = strlen(path); | |
50 | char *newbase = malloc(baselen + 1 + pathlen); | |
51 | memcpy(newbase, base, baselen); | |
52 | memcpy(newbase + baselen, path, pathlen); | |
53 | newbase[baselen + pathlen] = '/'; | |
54 | retval = read_tree(sha1, newbase, baselen + pathlen + 1); | |
55 | free(newbase); | |
56 | if (retval) | |
57 | return -1; | |
58 | continue; | |
59 | } | |
60 | if (read_one_entry(sha1, base, baselen, path, mode) < 0) | |
83adac3c | 61 | return -1; |
e83c5163 LT |
62 | } |
63 | return 0; | |
64 | } | |
65 | ||
9614b8dc LT |
66 | static int remove_lock = 0; |
67 | ||
68 | static void remove_lock_file(void) | |
69 | { | |
70 | if (remove_lock) | |
4bb04f21 | 71 | unlink(".git/index.lock"); |
9614b8dc LT |
72 | } |
73 | ||
e83c5163 LT |
74 | int main(int argc, char **argv) |
75 | { | |
83adac3c | 76 | int i, newfd; |
e83c5163 LT |
77 | unsigned char sha1[20]; |
78 | ||
4bb04f21 | 79 | newfd = open(".git/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600); |
83adac3c | 80 | if (newfd < 0) |
2de381f9 | 81 | die("unable to create new cachefile"); |
9614b8dc LT |
82 | atexit(remove_lock_file); |
83 | remove_lock = 1; | |
83adac3c LT |
84 | |
85 | for (i = 1; i < argc; i++) { | |
86 | const char *arg = argv[i]; | |
87 | ||
88 | /* "-m" stands for "merge" current directory cache */ | |
89 | if (!strcmp(arg, "-m")) { | |
9614b8dc | 90 | if (active_cache) |
2de381f9 | 91 | die("read-tree: cannot merge old cache on top of new"); |
9614b8dc | 92 | if (read_cache() < 0) |
2de381f9 | 93 | die("read-tree: corrupt directory cache"); |
83adac3c LT |
94 | continue; |
95 | } | |
9614b8dc LT |
96 | if (get_sha1_hex(arg, sha1) < 0) |
97 | usage("read-tree [-m] <sha1>"); | |
98 | if (read_tree(sha1, "", 0) < 0) | |
2de381f9 | 99 | die("failed to unpack tree object %s", arg); |
83adac3c | 100 | } |
9614b8dc | 101 | if (write_cache(newfd, active_cache, active_nr) || |
4bb04f21 | 102 | rename(".git/index.lock", ".git/index")) |
2de381f9 | 103 | die("unable to write new index file"); |
9614b8dc LT |
104 | remove_lock = 0; |
105 | return 0; | |
e83c5163 | 106 | } |