Gracefuly handle spaces around the equal sign in the Authors file.
[parsecvs.git] / tree.c
blobe2a041cba16bef3604090527b6cd949151aafbe6
1 #include "cvs.h"
2 #include "cache.h"
3 #include "cache-tree.h"
5 typedef struct _entry {
6 char *cvs_name;
7 struct _entry *next;
8 char *name;
9 size_t len;
10 struct cache_entry *ce;
11 } Hash_entry;
13 static Hash_entry *table[4096];
15 static int strip;
17 static int name_hash(char *name)
19 uintptr_t l = (uintptr_t)name;
20 int res = 0;
21 while (l) {
22 res ^= l;
23 l >>= 12;
25 return res & 4095;
28 static char *convert(char *name)
30 static char path[PATH_MAX + 1];
31 char *end, *p, *q;
32 const int attic_len = strlen("Attic");
33 size_t len = strlen(name);
35 if (len >= PATH_MAX + strip)
36 return NULL;
38 len -= strip;
39 memcpy(path, name + strip, len + 1);
40 end = path + len;
42 p = strrchr(path, '/');
44 if (len > 2 && end[-2] == ',' && end[-1] == 'v') {
45 end[-2] = '\0';
46 end -= 2;
49 if (!p || p < path + attic_len)
50 return path;
52 q = p - attic_len;
53 p++;
54 if (memcmp(q, "Attic", attic_len) != 0)
55 return path;
57 if (q == path || q[-1] == '/') {
58 while ((*q++ = *p++) != '\0')
61 return path;
64 static Hash_entry *find_node(rev_commit *c)
66 char *name = c->file ? c->file->name : NULL;
67 char *real_name;
68 Hash_entry *entry;
69 size_t len;
70 int hash;
72 if (!name)
73 return NULL;
75 hash = name_hash(name);
76 for (entry = table[hash]; entry; entry = entry->next)
77 if (entry->cvs_name == name)
78 return entry;
80 real_name = convert(name);
81 if (!real_name)
82 return NULL;
84 entry = xcalloc(1, sizeof(Hash_entry));
85 entry->cvs_name = name;
87 len = strlen(real_name);
89 entry->len = len;
90 entry->name = xmalloc(len + 1);
91 memcpy(entry->name, real_name, len + 1);
93 entry->ce = xcalloc(1, cache_entry_size(len));
94 memcpy(entry->ce->name, real_name, len);
95 entry->ce->ce_flags = create_ce_flags(len, 0);
97 entry->next = table[hash];
98 table[hash] = entry;
99 return entry;
102 static int cache_broken;
104 static void delete_file(Hash_entry *entry)
106 remove_file_from_cache(entry->name);
107 cache_tree_invalidate_path(active_cache_tree, entry->name);
110 static int set_file(Hash_entry *entry, rev_file *file)
112 int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE;
114 if (get_sha1_hex(file->sha1, entry->ce->sha1))
115 die("corrupt sha1: %s\n", file->sha1);
117 entry->ce->ce_mode = create_ce_mode(file->mode);
118 if (add_cache_entry(entry->ce, options))
119 return error("can't add %s\n", entry->name);
121 cache_tree_invalidate_path(active_cache_tree, entry->name);
123 return 0;
126 void delete_commit(rev_commit *c)
128 Hash_entry *entry = find_node(c);
129 if (entry && !cache_broken)
130 delete_file(entry);
133 void set_commit(rev_commit *c)
135 if (!cache_broken) {
136 Hash_entry *entry = find_node(c);
137 if (entry)
138 cache_broken = set_file(entry, c->file);
142 void reset_commits(rev_commit **commits, int ncommits)
144 discard_cache();
145 active_cache_tree = cache_tree();
146 cache_broken = 0;
147 while (ncommits-- && !cache_broken) {
148 rev_commit *c = *commits++;
149 if (c) {
150 Hash_entry *entry = find_node(c);
151 if (entry)
152 cache_broken = set_file(entry, c->file);
157 rev_commit *create_tree(rev_commit *leader)
159 rev_commit *commit = xcalloc(1, sizeof (rev_commit));
161 commit->date = leader->date;
162 commit->commitid = leader->commitid;
163 commit->log = leader->log;
164 commit->author = leader->author;
166 if (!cache_broken) {
167 if (cache_tree_update(active_cache_tree, active_cache,
168 active_nr, 0, 0))
169 cache_broken = error("writing tree");
172 if (!cache_broken)
173 commit->sha1 = atom(sha1_to_hex(active_cache_tree->sha1));
175 return commit;
178 void init_tree(int n)
180 git_config(git_default_config, NULL);
181 strip = n;
184 void discard_tree(void)
186 int i;
187 discard_cache();
188 for (i = 0; i < 4096; i++) {
189 Hash_entry *entry = table[i];
190 while (entry) {
191 Hash_entry *next = entry->next;
192 free(entry->ce);
193 free(entry->name);
194 free(entry);
195 entry = next;