]> git.ipfire.org Git - thirdparty/git.git/blame - refs.c
Store peeled refs in packed-refs file.
[thirdparty/git.git] / refs.c
CommitLineData
95fc7512
DB
1#include "refs.h"
2#include "cache.h"
cf0adba7
JH
3#include "object.h"
4#include "tag.h"
95fc7512
DB
5
6#include <errno.h>
7
e1e22e37
LT
8struct ref_list {
9 struct ref_list *next;
cf0adba7 10 unsigned char flag; /* ISSYMREF? ISPACKED? ISPEELED? */
e1e22e37
LT
11 unsigned char sha1[20];
12 char name[FLEX_ARRAY];
13};
14
cf0adba7 15static const char *parse_ref_line(char *line, unsigned char *sha1, int *flag)
e1e22e37
LT
16{
17 /*
18 * 42: the answer to everything.
19 *
20 * In this case, it happens to be the answer to
21 * 40 (length of sha1 hex representation)
22 * +1 (space in between hex and name)
23 * +1 (newline at the end of the line)
24 */
25 int len = strlen(line) - 42;
cf0adba7 26 int peeled = 0;
e1e22e37
LT
27
28 if (len <= 0)
29 return NULL;
30 if (get_sha1_hex(line, sha1) < 0)
31 return NULL;
32 if (!isspace(line[40]))
33 return NULL;
34 line += 41;
cf0adba7
JH
35
36 if (isspace(*line)) {
37 /* "SHA-1 SP SP refs/tags/tagname^{} LF"? */
38 line++;
39 len--;
40 peeled = 1;
41 }
e1e22e37
LT
42 if (line[len] != '\n')
43 return NULL;
44 line[len] = 0;
cf0adba7
JH
45
46 if (peeled && (len < 3 || strcmp(line + len - 3, "^{}")))
47 return NULL;
48
49 if (!peeled)
50 *flag &= ~REF_ISPEELED;
51 else
52 *flag |= REF_ISPEELED;
e1e22e37
LT
53 return line;
54}
55
8da19775
JH
56static struct ref_list *add_ref(const char *name, const unsigned char *sha1,
57 int flag, struct ref_list *list)
e1e22e37
LT
58{
59 int len;
60 struct ref_list **p = &list, *entry;
61
62 /* Find the place to insert the ref into.. */
63 while ((entry = *p) != NULL) {
64 int cmp = strcmp(entry->name, name);
65 if (cmp > 0)
66 break;
67
68 /* Same as existing entry? */
69 if (!cmp)
70 return list;
71 p = &entry->next;
72 }
73
74 /* Allocate it and add it in.. */
75 len = strlen(name) + 1;
76 entry = xmalloc(sizeof(struct ref_list) + len);
77 hashcpy(entry->sha1, sha1);
78 memcpy(entry->name, name, len);
8da19775 79 entry->flag = flag;
e1e22e37
LT
80 entry->next = *p;
81 *p = entry;
82 return list;
83}
84
5e290ff7
JH
85/*
86 * Future: need to be in "struct repository"
87 * when doing a full libification.
88 */
89struct cached_refs {
90 char did_loose;
91 char did_packed;
92 struct ref_list *loose;
93 struct ref_list *packed;
94} cached_refs;
95
96static void free_ref_list(struct ref_list *list)
97{
98 struct ref_list *next;
99 for ( ; list; list = next) {
100 next = list->next;
101 free(list);
102 }
103}
104
105static void invalidate_cached_refs(void)
e1e22e37 106{
5e290ff7
JH
107 struct cached_refs *ca = &cached_refs;
108
109 if (ca->did_loose && ca->loose)
110 free_ref_list(ca->loose);
111 if (ca->did_packed && ca->packed)
112 free_ref_list(ca->packed);
113 ca->loose = ca->packed = NULL;
114 ca->did_loose = ca->did_packed = 0;
115}
e1e22e37 116
5e290ff7
JH
117static struct ref_list *get_packed_refs(void)
118{
119 if (!cached_refs.did_packed) {
120 struct ref_list *refs = NULL;
e1e22e37
LT
121 FILE *f = fopen(git_path("packed-refs"), "r");
122 if (f) {
123 struct ref_list *list = NULL;
124 char refline[PATH_MAX];
125 while (fgets(refline, sizeof(refline), f)) {
126 unsigned char sha1[20];
cf0adba7
JH
127 int flag = REF_ISPACKED;
128 const char *name =
129 parse_ref_line(refline, sha1, &flag);
e1e22e37
LT
130 if (!name)
131 continue;
cf0adba7 132 list = add_ref(name, sha1, flag, list);
e1e22e37
LT
133 }
134 fclose(f);
135 refs = list;
136 }
5e290ff7
JH
137 cached_refs.packed = refs;
138 cached_refs.did_packed = 1;
e1e22e37 139 }
5e290ff7 140 return cached_refs.packed;
e1e22e37
LT
141}
142
143static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
144{
145 DIR *dir = opendir(git_path("%s", base));
146
147 if (dir) {
148 struct dirent *de;
149 int baselen = strlen(base);
ed378ec7 150 char *ref = xmalloc(baselen + 257);
e1e22e37 151
ed378ec7 152 memcpy(ref, base, baselen);
e1e22e37 153 if (baselen && base[baselen-1] != '/')
ed378ec7 154 ref[baselen++] = '/';
e1e22e37
LT
155
156 while ((de = readdir(dir)) != NULL) {
157 unsigned char sha1[20];
158 struct stat st;
8da19775 159 int flag;
e1e22e37
LT
160 int namelen;
161
162 if (de->d_name[0] == '.')
163 continue;
164 namelen = strlen(de->d_name);
165 if (namelen > 255)
166 continue;
167 if (has_extension(de->d_name, ".lock"))
168 continue;
ed378ec7
LT
169 memcpy(ref + baselen, de->d_name, namelen+1);
170 if (stat(git_path("%s", ref), &st) < 0)
e1e22e37
LT
171 continue;
172 if (S_ISDIR(st.st_mode)) {
ed378ec7 173 list = get_ref_dir(ref, list);
e1e22e37
LT
174 continue;
175 }
8da19775 176 if (!resolve_ref(ref, sha1, 1, &flag)) {
ed378ec7 177 error("%s points nowhere!", ref);
e1e22e37
LT
178 continue;
179 }
8da19775 180 list = add_ref(ref, sha1, flag, list);
e1e22e37 181 }
ed378ec7 182 free(ref);
e1e22e37
LT
183 closedir(dir);
184 }
185 return list;
186}
187
188static struct ref_list *get_loose_refs(void)
189{
5e290ff7
JH
190 if (!cached_refs.did_loose) {
191 cached_refs.loose = get_ref_dir("refs", NULL);
192 cached_refs.did_loose = 1;
e1e22e37 193 }
5e290ff7 194 return cached_refs.loose;
e1e22e37
LT
195}
196
ca8db142
LT
197/* We allow "recursive" symbolic refs. Only within reason, though */
198#define MAXDEPTH 5
199
8da19775 200const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
8a65ff76 201{
a876ed83
JH
202 int depth = MAXDEPTH, len;
203 char buffer[256];
ed378ec7 204 static char ref_buffer[256];
ca8db142 205
8da19775
JH
206 if (flag)
207 *flag = 0;
208
a876ed83 209 for (;;) {
ed378ec7 210 const char *path = git_path("%s", ref);
a876ed83
JH
211 struct stat st;
212 char *buf;
213 int fd;
8a65ff76 214
a876ed83
JH
215 if (--depth < 0)
216 return NULL;
ca8db142 217
a876ed83
JH
218 /* Special case: non-existing file.
219 * Not having the refs/heads/new-branch is OK
220 * if we are writing into it, so is .git/HEAD
221 * that points at refs/heads/master still to be
222 * born. It is NOT OK if we are resolving for
223 * reading.
224 */
225 if (lstat(path, &st) < 0) {
434cd0cd
LT
226 struct ref_list *list = get_packed_refs();
227 while (list) {
cf0adba7
JH
228 if (!(list->flag & REF_ISPEELED) &&
229 !strcmp(ref, list->name)) {
434cd0cd 230 hashcpy(sha1, list->sha1);
8da19775
JH
231 if (flag)
232 *flag |= REF_ISPACKED;
434cd0cd
LT
233 return ref;
234 }
235 list = list->next;
236 }
a876ed83
JH
237 if (reading || errno != ENOENT)
238 return NULL;
e702496e 239 hashclr(sha1);
ed378ec7 240 return ref;
a876ed83 241 }
ca8db142 242
a876ed83
JH
243 /* Follow "normalized" - ie "refs/.." symlinks by hand */
244 if (S_ISLNK(st.st_mode)) {
245 len = readlink(path, buffer, sizeof(buffer)-1);
246 if (len >= 5 && !memcmp("refs/", buffer, 5)) {
ed378ec7
LT
247 buffer[len] = 0;
248 strcpy(ref_buffer, buffer);
249 ref = ref_buffer;
8da19775
JH
250 if (flag)
251 *flag |= REF_ISSYMREF;
a876ed83
JH
252 continue;
253 }
ca8db142 254 }
a876ed83 255
7a21632f
DS
256 /* Is it a directory? */
257 if (S_ISDIR(st.st_mode)) {
258 errno = EISDIR;
259 return NULL;
260 }
261
a876ed83
JH
262 /*
263 * Anything else, just open it and try to use it as
264 * a ref
265 */
266 fd = open(path, O_RDONLY);
267 if (fd < 0)
268 return NULL;
269 len = read(fd, buffer, sizeof(buffer)-1);
270 close(fd);
271
272 /*
273 * Is it a symbolic ref?
274 */
275 if (len < 4 || memcmp("ref:", buffer, 4))
276 break;
277 buf = buffer + 4;
278 len -= 4;
279 while (len && isspace(*buf))
280 buf++, len--;
281 while (len && isspace(buf[len-1]))
ed378ec7
LT
282 len--;
283 buf[len] = 0;
284 memcpy(ref_buffer, buf, len + 1);
285 ref = ref_buffer;
8da19775
JH
286 if (flag)
287 *flag |= REF_ISSYMREF;
8a65ff76 288 }
a876ed83
JH
289 if (len < 40 || get_sha1_hex(buffer, sha1))
290 return NULL;
ed378ec7 291 return ref;
a876ed83
JH
292}
293
ed378ec7 294int create_symref(const char *ref_target, const char *refs_heads_master)
8098a178 295{
8098a178
JH
296 const char *lockpath;
297 char ref[1000];
298 int fd, len, written;
ed378ec7 299 const char *git_HEAD = git_path("%s", ref_target);
8098a178 300
9f0bb90d
JH
301#ifndef NO_SYMLINK_HEAD
302 if (prefer_symlink_refs) {
f8348be3
JS
303 unlink(git_HEAD);
304 if (!symlink(refs_heads_master, git_HEAD))
305 return 0;
306 fprintf(stderr, "no symlink - falling back to symbolic ref\n");
307 }
303958dc
JS
308#endif
309
8098a178
JH
310 len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
311 if (sizeof(ref) <= len) {
312 error("refname too long: %s", refs_heads_master);
313 return -1;
314 }
315 lockpath = mkpath("%s.lock", git_HEAD);
316 fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
317 written = write(fd, ref, len);
318 close(fd);
319 if (written != len) {
320 unlink(lockpath);
321 error("Unable to write to %s", lockpath);
322 return -2;
323 }
324 if (rename(lockpath, git_HEAD) < 0) {
325 unlink(lockpath);
326 error("Unable to create %s", git_HEAD);
327 return -3;
328 }
138086a7
JH
329 if (adjust_shared_perm(git_HEAD)) {
330 unlink(lockpath);
331 error("Unable to fix permissions on %s", lockpath);
332 return -4;
333 }
8098a178 334 return 0;
8098a178
JH
335}
336
ed378ec7 337int read_ref(const char *ref, unsigned char *sha1)
a876ed83 338{
8da19775 339 if (resolve_ref(ref, sha1, 1, NULL))
a876ed83
JH
340 return 0;
341 return -1;
8a65ff76
LT
342}
343
ef06b918
JH
344static int do_one_ref(const char *base, each_ref_fn fn, int trim,
345 void *cb_data, struct ref_list *entry)
346{
347 if (strncmp(base, entry->name, trim))
348 return 0;
349 if (is_null_sha1(entry->sha1))
350 return 0;
cf0adba7
JH
351 if (entry->flag & REF_ISPEELED)
352 return 0;
ef06b918
JH
353 if (!has_sha1_file(entry->sha1)) {
354 error("%s does not point to a valid object!", entry->name);
355 return 0;
356 }
357 return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
358}
359
cf0adba7
JH
360int peel_ref(const char *ref, unsigned char *sha1)
361{
362 int flag;
363 unsigned char base[20];
364 struct object *o;
365
366 if (!resolve_ref(ref, base, 1, &flag))
367 return -1;
368
369 if ((flag & REF_ISPACKED)) {
370 struct ref_list *list = get_packed_refs();
371 int len = strlen(ref);
372
373 while (list) {
374 if ((list->flag & REF_ISPEELED) &&
375 !strncmp(list->name, ref, len) &&
376 strlen(list->name) == len + 3 &&
377 !strcmp(list->name + len, "^{}")) {
378 hashcpy(sha1, list->sha1);
379 return 0;
380 }
381 list = list->next;
382 }
383 /* older pack-refs did not leave peeled ones in */
384 }
385
386 /* otherwise ... */
387 o = parse_object(base);
388 if (o->type == OBJ_TAG) {
389 o = deref_tag(o, ref, 0);
390 if (o) {
391 hashcpy(sha1, o->sha1);
392 return 0;
393 }
394 }
395 return -1;
396}
397
8da19775
JH
398static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
399 void *cb_data)
8a65ff76 400{
e1e22e37
LT
401 int retval;
402 struct ref_list *packed = get_packed_refs();
403 struct ref_list *loose = get_loose_refs();
8a65ff76 404
e1e22e37
LT
405 while (packed && loose) {
406 struct ref_list *entry;
407 int cmp = strcmp(packed->name, loose->name);
408 if (!cmp) {
409 packed = packed->next;
410 continue;
6cada6a9 411 }
e1e22e37
LT
412 if (cmp > 0) {
413 entry = loose;
414 loose = loose->next;
415 } else {
416 entry = packed;
417 packed = packed->next;
418 }
ef06b918 419 retval = do_one_ref(base, fn, trim, cb_data, entry);
e1e22e37
LT
420 if (retval)
421 return retval;
422 }
8a65ff76 423
ef06b918
JH
424 for (packed = packed ? packed : loose; packed; packed = packed->next) {
425 retval = do_one_ref(base, fn, trim, cb_data, packed);
426 if (retval)
427 return retval;
8a65ff76 428 }
e1e22e37 429 return 0;
8a65ff76
LT
430}
431
cb5d709f 432int head_ref(each_ref_fn fn, void *cb_data)
723c31fe
LT
433{
434 unsigned char sha1[20];
8da19775
JH
435 int flag;
436
437 if (resolve_ref("HEAD", sha1, 1, &flag))
438 return fn("HEAD", sha1, flag, cb_data);
2f34ba32 439 return 0;
723c31fe
LT
440}
441
cb5d709f 442int for_each_ref(each_ref_fn fn, void *cb_data)
8a65ff76 443{
cb5d709f 444 return do_for_each_ref("refs/", fn, 0, cb_data);
a62be77f
SE
445}
446
cb5d709f 447int for_each_tag_ref(each_ref_fn fn, void *cb_data)
a62be77f 448{
cb5d709f 449 return do_for_each_ref("refs/tags/", fn, 10, cb_data);
a62be77f
SE
450}
451
cb5d709f 452int for_each_branch_ref(each_ref_fn fn, void *cb_data)
a62be77f 453{
cb5d709f 454 return do_for_each_ref("refs/heads/", fn, 11, cb_data);
a62be77f
SE
455}
456
cb5d709f 457int for_each_remote_ref(each_ref_fn fn, void *cb_data)
a62be77f 458{
cb5d709f 459 return do_for_each_ref("refs/remotes/", fn, 13, cb_data);
8a65ff76
LT
460}
461
cb5d709f
JH
462/* NEEDSWORK: This is only used by ssh-upload and it should go; the
463 * caller should do resolve_ref or read_ref like everybody else. Or
464 * maybe everybody else should use get_ref_sha1() instead of doing
465 * read_ref().
466 */
95fc7512
DB
467int get_ref_sha1(const char *ref, unsigned char *sha1)
468{
95fc7512
DB
469 if (check_ref_format(ref))
470 return -1;
ed378ec7 471 return read_ref(mkpath("refs/%s", ref), sha1);
95fc7512
DB
472}
473
03feddd6
JH
474/*
475 * Make sure "ref" is something reasonable to have under ".git/refs/";
476 * We do not like it if:
477 *
478 * - any path component of it begins with ".", or
479 * - it has double dots "..", or
480 * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
481 * - it ends with a "/".
482 */
483
484static inline int bad_ref_char(int ch)
485{
486 return (((unsigned) ch) <= ' ' ||
68283999
JH
487 ch == '~' || ch == '^' || ch == ':' ||
488 /* 2.13 Pattern Matching Notation */
489 ch == '?' || ch == '*' || ch == '[');
03feddd6
JH
490}
491
95fc7512
DB
492int check_ref_format(const char *ref)
493{
03feddd6
JH
494 int ch, level;
495 const char *cp = ref;
496
497 level = 0;
498 while (1) {
499 while ((ch = *cp++) == '/')
500 ; /* tolerate duplicated slashes */
501 if (!ch)
502 return -1; /* should not end with slashes */
503
504 /* we are at the beginning of the path component */
505 if (ch == '.' || bad_ref_char(ch))
506 return -1;
507
508 /* scan the rest of the path component */
509 while ((ch = *cp++) != 0) {
510 if (bad_ref_char(ch))
511 return -1;
512 if (ch == '/')
513 break;
514 if (ch == '.' && *cp == '.')
515 return -1;
516 }
517 level++;
518 if (!ch) {
519 if (level < 2)
520 return -1; /* at least of form "heads/blah" */
521 return 0;
522 }
523 }
95fc7512
DB
524}
525
e5f38ec3 526static struct ref_lock *verify_lock(struct ref_lock *lock,
4bd18c43
SP
527 const unsigned char *old_sha1, int mustexist)
528{
8da19775 529 if (!resolve_ref(lock->ref_name, lock->old_sha1, mustexist, NULL)) {
434cd0cd 530 error("Can't verify ref %s", lock->ref_name);
4bd18c43
SP
531 unlock_ref(lock);
532 return NULL;
533 }
a89fccd2 534 if (hashcmp(lock->old_sha1, old_sha1)) {
434cd0cd 535 error("Ref %s is at %s but expected %s", lock->ref_name,
4bd18c43
SP
536 sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1));
537 unlock_ref(lock);
538 return NULL;
539 }
540 return lock;
541}
542
bc7127ef
JH
543static int remove_empty_dir_recursive(char *path, int len)
544{
545 DIR *dir = opendir(path);
546 struct dirent *e;
547 int ret = 0;
548
549 if (!dir)
550 return -1;
551 if (path[len-1] != '/')
552 path[len++] = '/';
553 while ((e = readdir(dir)) != NULL) {
554 struct stat st;
555 int namlen;
556 if ((e->d_name[0] == '.') &&
557 ((e->d_name[1] == 0) ||
558 ((e->d_name[1] == '.') && e->d_name[2] == 0)))
559 continue; /* "." and ".." */
560
561 namlen = strlen(e->d_name);
562 if ((len + namlen < PATH_MAX) &&
563 strcpy(path + len, e->d_name) &&
564 !lstat(path, &st) &&
565 S_ISDIR(st.st_mode) &&
28bed6ea 566 !remove_empty_dir_recursive(path, len + namlen))
bc7127ef
JH
567 continue; /* happy */
568
569 /* path too long, stat fails, or non-directory still exists */
570 ret = -1;
571 break;
572 }
573 closedir(dir);
574 if (!ret) {
575 path[len] = 0;
576 ret = rmdir(path);
577 }
578 return ret;
579}
580
581static int remove_empty_directories(char *file)
582{
583 /* we want to create a file but there is a directory there;
584 * if that is an empty directory (or a directory that contains
585 * only empty directories), remove them.
586 */
587 char path[PATH_MAX];
588 int len = strlen(file);
589
590 if (len >= PATH_MAX) /* path too long ;-) */
591 return -1;
592 strcpy(path, file);
593 return remove_empty_dir_recursive(path, len);
594}
595
c0277d15 596static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int *flag)
4bd18c43 597{
434cd0cd 598 char *ref_file;
ed378ec7 599 const char *orig_ref = ref;
4bd18c43 600 struct ref_lock *lock;
732232a1 601 struct stat st;
5cc3cef9 602 int last_errno = 0;
4431fcc4 603 int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
4bd18c43
SP
604
605 lock = xcalloc(1, sizeof(struct ref_lock));
606 lock->lock_fd = -1;
607
c0277d15 608 ref = resolve_ref(ref, lock->old_sha1, mustexist, flag);
bc7127ef
JH
609 if (!ref && errno == EISDIR) {
610 /* we are trying to lock foo but we used to
611 * have foo/bar which now does not exist;
612 * it is normal for the empty directory 'foo'
613 * to remain.
614 */
615 ref_file = git_path("%s", orig_ref);
5cc3cef9
JH
616 if (remove_empty_directories(ref_file)) {
617 last_errno = errno;
618 error("there are still refs under '%s'", orig_ref);
619 goto error_return;
620 }
c0277d15 621 ref = resolve_ref(orig_ref, lock->old_sha1, mustexist, flag);
bc7127ef 622 }
ed378ec7 623 if (!ref) {
5cc3cef9 624 last_errno = errno;
818f477c 625 error("unable to resolve reference %s: %s",
ed378ec7 626 orig_ref, strerror(errno));
5cc3cef9 627 goto error_return;
4bd18c43 628 }
22a3844e
JH
629 if (is_null_sha1(lock->old_sha1)) {
630 /* The ref did not exist and we are creating it.
631 * Make sure there is no existing ref that is packed
632 * whose name begins with our refname, nor a ref whose
633 * name is a proper prefix of our refname.
634 */
635 int namlen = strlen(ref); /* e.g. 'foo/bar' */
636 struct ref_list *list = get_packed_refs();
637 while (list) {
638 /* list->name could be 'foo' or 'foo/bar/baz' */
639 int len = strlen(list->name);
640 int cmplen = (namlen < len) ? namlen : len;
641 const char *lead = (namlen < len) ? list->name : ref;
642
643 if (!strncmp(ref, list->name, cmplen) &&
644 lead[cmplen] == '/') {
645 error("'%s' exists; cannot create '%s'",
646 list->name, ref);
647 goto error_return;
648 }
649 list = list->next;
650 }
651 }
652
c33d5174 653 lock->lk = xcalloc(1, sizeof(struct lock_file));
4bd18c43 654
434cd0cd 655 lock->ref_name = xstrdup(ref);
ed378ec7 656 lock->log_file = xstrdup(git_path("logs/%s", ref));
7c1a278d 657 ref_file = git_path("%s", ref);
434cd0cd 658 lock->force_write = lstat(ref_file, &st) && errno == ENOENT;
4bd18c43 659
5cc3cef9
JH
660 if (safe_create_leading_directories(ref_file)) {
661 last_errno = errno;
662 error("unable to create directory for %s", ref_file);
663 goto error_return;
664 }
434cd0cd 665 lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
4bd18c43
SP
666
667 return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
5cc3cef9
JH
668
669 error_return:
670 unlock_ref(lock);
671 errno = last_errno;
672 return NULL;
4bd18c43
SP
673}
674
4431fcc4 675struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1)
95fc7512 676{
53cce84c 677 char refpath[PATH_MAX];
95fc7512 678 if (check_ref_format(ref))
4bd18c43 679 return NULL;
53cce84c 680 strcpy(refpath, mkpath("refs/%s", ref));
c0277d15 681 return lock_ref_sha1_basic(refpath, old_sha1, NULL);
4bd18c43
SP
682}
683
4431fcc4 684struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1)
4bd18c43 685{
c0277d15
JH
686 return lock_ref_sha1_basic(ref, old_sha1, NULL);
687}
688
26a063a1
JH
689static struct lock_file packlock;
690
c0277d15
JH
691static int repack_without_ref(const char *refname)
692{
693 struct ref_list *list, *packed_ref_list;
694 int fd;
695 int found = 0;
c0277d15
JH
696
697 packed_ref_list = get_packed_refs();
698 for (list = packed_ref_list; list; list = list->next) {
699 if (!strcmp(refname, list->name)) {
700 found = 1;
701 break;
702 }
703 }
704 if (!found)
705 return 0;
706 memset(&packlock, 0, sizeof(packlock));
707 fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
708 if (fd < 0)
709 return error("cannot delete '%s' from packed refs", refname);
710
711 for (list = packed_ref_list; list; list = list->next) {
712 char line[PATH_MAX + 100];
713 int len;
714
715 if (!strcmp(refname, list->name))
716 continue;
717 len = snprintf(line, sizeof(line), "%s %s\n",
718 sha1_to_hex(list->sha1), list->name);
719 /* this should not happen but just being defensive */
720 if (len > sizeof(line))
721 die("too long a refname '%s'", list->name);
722 write_or_die(fd, line, len);
723 }
724 return commit_lock_file(&packlock);
725}
726
727int delete_ref(const char *refname, unsigned char *sha1)
728{
729 struct ref_lock *lock;
730 int err, i, ret = 0, flag = 0;
731
732 lock = lock_ref_sha1_basic(refname, sha1, &flag);
733 if (!lock)
734 return 1;
735 if (!(flag & REF_ISPACKED)) {
736 /* loose */
737 i = strlen(lock->lk->filename) - 5; /* .lock */
738 lock->lk->filename[i] = 0;
739 err = unlink(lock->lk->filename);
740 if (err) {
741 ret = 1;
742 error("unlink(%s) failed: %s",
743 lock->lk->filename, strerror(errno));
744 }
745 lock->lk->filename[i] = '.';
746 }
747 /* removing the loose one could have resurrected an earlier
748 * packed one. Also, if it was not loose we need to repack
749 * without it.
750 */
751 ret |= repack_without_ref(refname);
752
753 err = unlink(lock->log_file);
754 if (err && errno != ENOENT)
755 fprintf(stderr, "warning: unlink(%s) failed: %s",
756 lock->log_file, strerror(errno));
757 invalidate_cached_refs();
758 unlock_ref(lock);
759 return ret;
4bd18c43
SP
760}
761
e5f38ec3 762void unlock_ref(struct ref_lock *lock)
4bd18c43
SP
763{
764 if (lock->lock_fd >= 0) {
765 close(lock->lock_fd);
c33d5174
JH
766 /* Do not free lock->lk -- atexit() still looks at them */
767 if (lock->lk)
768 rollback_lock_file(lock->lk);
4bd18c43 769 }
434cd0cd 770 free(lock->ref_name);
4cac42b1 771 free(lock->log_file);
4bd18c43
SP
772 free(lock);
773}
774
6de08ae6
SP
775static int log_ref_write(struct ref_lock *lock,
776 const unsigned char *sha1, const char *msg)
777{
778 int logfd, written, oflags = O_APPEND | O_WRONLY;
779 unsigned maxlen, len;
780 char *logrec;
ff4c8485 781 const char *committer;
6de08ae6 782
4057deb5
JH
783 if (log_all_ref_updates &&
784 !strncmp(lock->ref_name, "refs/heads/", 11)) {
6de08ae6
SP
785 if (safe_create_leading_directories(lock->log_file) < 0)
786 return error("unable to create directory for %s",
787 lock->log_file);
788 oflags |= O_CREAT;
789 }
790
791 logfd = open(lock->log_file, oflags, 0666);
792 if (logfd < 0) {
1974bf62 793 if (!(oflags & O_CREAT) && errno == ENOENT)
6de08ae6 794 return 0;
3b463c3f
JH
795
796 if ((oflags & O_CREAT) && errno == EISDIR) {
797 if (remove_empty_directories(lock->log_file)) {
798 return error("There are still logs under '%s'",
799 lock->log_file);
800 }
801 logfd = open(lock->log_file, oflags, 0666);
802 }
803
804 if (logfd < 0)
805 return error("Unable to append to %s: %s",
806 lock->log_file, strerror(errno));
6de08ae6
SP
807 }
808
ff4c8485 809 committer = git_committer_info(1);
6de08ae6 810 if (msg) {
ff4c8485 811 maxlen = strlen(committer) + strlen(msg) + 2*40 + 5;
6de08ae6
SP
812 logrec = xmalloc(maxlen);
813 len = snprintf(logrec, maxlen, "%s %s %s\t%s\n",
814 sha1_to_hex(lock->old_sha1),
815 sha1_to_hex(sha1),
ff4c8485 816 committer,
6de08ae6 817 msg);
e5f38ec3
JH
818 }
819 else {
ff4c8485 820 maxlen = strlen(committer) + 2*40 + 4;
6de08ae6
SP
821 logrec = xmalloc(maxlen);
822 len = snprintf(logrec, maxlen, "%s %s %s\n",
823 sha1_to_hex(lock->old_sha1),
824 sha1_to_hex(sha1),
ff4c8485 825 committer);
6de08ae6
SP
826 }
827 written = len <= maxlen ? write(logfd, logrec, len) : -1;
828 free(logrec);
829 close(logfd);
830 if (written != len)
831 return error("Unable to append to %s", lock->log_file);
832 return 0;
833}
834
4bd18c43
SP
835int write_ref_sha1(struct ref_lock *lock,
836 const unsigned char *sha1, const char *logmsg)
837{
838 static char term = '\n';
839
840 if (!lock)
95fc7512 841 return -1;
a89fccd2 842 if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
4bd18c43
SP
843 unlock_ref(lock);
844 return 0;
95fc7512 845 }
4bd18c43
SP
846 if (write(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
847 write(lock->lock_fd, &term, 1) != 1
848 || close(lock->lock_fd) < 0) {
c33d5174 849 error("Couldn't write %s", lock->lk->filename);
4bd18c43
SP
850 unlock_ref(lock);
851 return -1;
852 }
5e290ff7 853 invalidate_cached_refs();
6de08ae6
SP
854 if (log_ref_write(lock, sha1, logmsg) < 0) {
855 unlock_ref(lock);
856 return -1;
857 }
c33d5174 858 if (commit_lock_file(lock->lk)) {
434cd0cd 859 error("Couldn't set %s", lock->ref_name);
4bd18c43
SP
860 unlock_ref(lock);
861 return -1;
862 }
863 lock->lock_fd = -1;
864 unlock_ref(lock);
865 return 0;
95fc7512 866}
d556fae2 867
ab2a1a32 868int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1)
d556fae2 869{
e5229042 870 const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
d556fae2
SP
871 char *tz_c;
872 int logfd, tz;
873 struct stat st;
874 unsigned long date;
e5229042 875 unsigned char logged_sha1[20];
d556fae2
SP
876
877 logfile = git_path("logs/%s", ref);
878 logfd = open(logfile, O_RDONLY, 0);
879 if (logfd < 0)
880 die("Unable to read log %s: %s", logfile, strerror(errno));
881 fstat(logfd, &st);
882 if (!st.st_size)
883 die("Log %s is empty.", logfile);
884 logdata = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
885 close(logfd);
886
e5229042 887 lastrec = NULL;
d556fae2
SP
888 rec = logend = logdata + st.st_size;
889 while (logdata < rec) {
890 if (logdata < rec && *(rec-1) == '\n')
891 rec--;
e5229042
SP
892 lastgt = NULL;
893 while (logdata < rec && *(rec-1) != '\n') {
d556fae2 894 rec--;
e5229042
SP
895 if (*rec == '>')
896 lastgt = rec;
897 }
898 if (!lastgt)
d556fae2 899 die("Log %s is corrupt.", logfile);
e5229042 900 date = strtoul(lastgt + 1, &tz_c, 10);
ab2a1a32 901 if (date <= at_time || cnt == 0) {
e5229042
SP
902 if (lastrec) {
903 if (get_sha1_hex(lastrec, logged_sha1))
904 die("Log %s is corrupt.", logfile);
905 if (get_sha1_hex(rec + 41, sha1))
906 die("Log %s is corrupt.", logfile);
a89fccd2 907 if (hashcmp(logged_sha1, sha1)) {
e5229042
SP
908 tz = strtoul(tz_c, NULL, 10);
909 fprintf(stderr,
910 "warning: Log %s has gap after %s.\n",
911 logfile, show_rfc2822_date(date, tz));
912 }
e5f38ec3
JH
913 }
914 else if (date == at_time) {
e5229042
SP
915 if (get_sha1_hex(rec + 41, sha1))
916 die("Log %s is corrupt.", logfile);
e5f38ec3
JH
917 }
918 else {
e5229042
SP
919 if (get_sha1_hex(rec + 41, logged_sha1))
920 die("Log %s is corrupt.", logfile);
a89fccd2 921 if (hashcmp(logged_sha1, sha1)) {
e5229042
SP
922 tz = strtoul(tz_c, NULL, 10);
923 fprintf(stderr,
924 "warning: Log %s unexpectedly ended on %s.\n",
925 logfile, show_rfc2822_date(date, tz));
926 }
927 }
d556fae2
SP
928 munmap((void*)logdata, st.st_size);
929 return 0;
930 }
e5229042 931 lastrec = rec;
ab2a1a32
JH
932 if (cnt > 0)
933 cnt--;
d556fae2
SP
934 }
935
e5229042
SP
936 rec = logdata;
937 while (rec < logend && *rec != '>' && *rec != '\n')
938 rec++;
939 if (rec == logend || *rec == '\n')
d556fae2 940 die("Log %s is corrupt.", logfile);
e5229042 941 date = strtoul(rec + 1, &tz_c, 10);
d556fae2
SP
942 tz = strtoul(tz_c, NULL, 10);
943 if (get_sha1_hex(logdata, sha1))
944 die("Log %s is corrupt.", logfile);
945 munmap((void*)logdata, st.st_size);
946 fprintf(stderr, "warning: Log %s only goes back to %s.\n",
947 logfile, show_rfc2822_date(date, tz));
948 return 0;
949}