Store peeled refs in packed-refs file.
[git/git.git] / refs.c
1 #include "refs.h"
2 #include "cache.h"
3 #include "object.h"
4 #include "tag.h"
5
6 #include <errno.h>
7
8 struct ref_list {
9 struct ref_list *next;
10 unsigned char flag; /* ISSYMREF? ISPACKED? ISPEELED? */
11 unsigned char sha1[20];
12 char name[FLEX_ARRAY];
13 };
14
15 static const char *parse_ref_line(char *line, unsigned char *sha1, int *flag)
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;
26 int peeled = 0;
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;
35
36 if (isspace(*line)) {
37 /* "SHA-1 SP SP refs/tags/tagname^{} LF"? */
38 line++;
39 len--;
40 peeled = 1;
41 }
42 if (line[len] != '\n')
43 return NULL;
44 line[len] = 0;
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;
53 return line;
54 }
55
56 static struct ref_list *add_ref(const char *name, const unsigned char *sha1,
57 int flag, struct ref_list *list)
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);
79 entry->flag = flag;
80 entry->next = *p;
81 *p = entry;
82 return list;
83 }
84
85 /*
86 * Future: need to be in "struct repository"
87 * when doing a full libification.
88 */
89 struct cached_refs {
90 char did_loose;
91 char did_packed;
92 struct ref_list *loose;
93 struct ref_list *packed;
94 } cached_refs;
95
96 static 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
105 static void invalidate_cached_refs(void)
106 {
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 }
116
117 static struct ref_list *get_packed_refs(void)
118 {
119 if (!cached_refs.did_packed) {
120 struct ref_list *refs = NULL;
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];
127 int flag = REF_ISPACKED;
128 const char *name =
129 parse_ref_line(refline, sha1, &flag);
130 if (!name)
131 continue;
132 list = add_ref(name, sha1, flag, list);
133 }
134 fclose(f);
135 refs = list;
136 }
137 cached_refs.packed = refs;
138 cached_refs.did_packed = 1;
139 }
140 return cached_refs.packed;
141 }
142
143 static 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);
150 char *ref = xmalloc(baselen + 257);
151
152 memcpy(ref, base, baselen);
153 if (baselen && base[baselen-1] != '/')
154 ref[baselen++] = '/';
155
156 while ((de = readdir(dir)) != NULL) {
157 unsigned char sha1[20];
158 struct stat st;
159 int flag;
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;
169 memcpy(ref + baselen, de->d_name, namelen+1);
170 if (stat(git_path("%s", ref), &st) < 0)
171 continue;
172 if (S_ISDIR(st.st_mode)) {
173 list = get_ref_dir(ref, list);
174 continue;
175 }
176 if (!resolve_ref(ref, sha1, 1, &flag)) {
177 error("%s points nowhere!", ref);
178 continue;
179 }
180 list = add_ref(ref, sha1, flag, list);
181 }
182 free(ref);
183 closedir(dir);
184 }
185 return list;
186 }
187
188 static struct ref_list *get_loose_refs(void)
189 {
190 if (!cached_refs.did_loose) {
191 cached_refs.loose = get_ref_dir("refs", NULL);
192 cached_refs.did_loose = 1;
193 }
194 return cached_refs.loose;
195 }
196
197 /* We allow "recursive" symbolic refs. Only within reason, though */
198 #define MAXDEPTH 5
199
200 const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
201 {
202 int depth = MAXDEPTH, len;
203 char buffer[256];
204 static char ref_buffer[256];
205
206 if (flag)
207 *flag = 0;
208
209 for (;;) {
210 const char *path = git_path("%s", ref);
211 struct stat st;
212 char *buf;
213 int fd;
214
215 if (--depth < 0)
216 return NULL;
217
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) {
226 struct ref_list *list = get_packed_refs();
227 while (list) {
228 if (!(list->flag & REF_ISPEELED) &&
229 !strcmp(ref, list->name)) {
230 hashcpy(sha1, list->sha1);
231 if (flag)
232 *flag |= REF_ISPACKED;
233 return ref;
234 }
235 list = list->next;
236 }
237 if (reading || errno != ENOENT)
238 return NULL;
239 hashclr(sha1);
240 return ref;
241 }
242
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)) {
247 buffer[len] = 0;
248 strcpy(ref_buffer, buffer);
249 ref = ref_buffer;
250 if (flag)
251 *flag |= REF_ISSYMREF;
252 continue;
253 }
254 }
255
256 /* Is it a directory? */
257 if (S_ISDIR(st.st_mode)) {
258 errno = EISDIR;
259 return NULL;
260 }
261
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]))
282 len--;
283 buf[len] = 0;
284 memcpy(ref_buffer, buf, len + 1);
285 ref = ref_buffer;
286 if (flag)
287 *flag |= REF_ISSYMREF;
288 }
289 if (len < 40 || get_sha1_hex(buffer, sha1))
290 return NULL;
291 return ref;
292 }
293
294 int create_symref(const char *ref_target, const char *refs_heads_master)
295 {
296 const char *lockpath;
297 char ref[1000];
298 int fd, len, written;
299 const char *git_HEAD = git_path("%s", ref_target);
300
301 #ifndef NO_SYMLINK_HEAD
302 if (prefer_symlink_refs) {
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 }
308 #endif
309
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 }
329 if (adjust_shared_perm(git_HEAD)) {
330 unlink(lockpath);
331 error("Unable to fix permissions on %s", lockpath);
332 return -4;
333 }
334 return 0;
335 }
336
337 int read_ref(const char *ref, unsigned char *sha1)
338 {
339 if (resolve_ref(ref, sha1, 1, NULL))
340 return 0;
341 return -1;
342 }
343
344 static 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;
351 if (entry->flag & REF_ISPEELED)
352 return 0;
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
360 int 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
398 static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
399 void *cb_data)
400 {
401 int retval;
402 struct ref_list *packed = get_packed_refs();
403 struct ref_list *loose = get_loose_refs();
404
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;
411 }
412 if (cmp > 0) {
413 entry = loose;
414 loose = loose->next;
415 } else {
416 entry = packed;
417 packed = packed->next;
418 }
419 retval = do_one_ref(base, fn, trim, cb_data, entry);
420 if (retval)
421 return retval;
422 }
423
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;
428 }
429 return 0;
430 }
431
432 int head_ref(each_ref_fn fn, void *cb_data)
433 {
434 unsigned char sha1[20];
435 int flag;
436
437 if (resolve_ref("HEAD", sha1, 1, &flag))
438 return fn("HEAD", sha1, flag, cb_data);
439 return 0;
440 }
441
442 int for_each_ref(each_ref_fn fn, void *cb_data)
443 {
444 return do_for_each_ref("refs/", fn, 0, cb_data);
445 }
446
447 int for_each_tag_ref(each_ref_fn fn, void *cb_data)
448 {
449 return do_for_each_ref("refs/tags/", fn, 10, cb_data);
450 }
451
452 int for_each_branch_ref(each_ref_fn fn, void *cb_data)
453 {
454 return do_for_each_ref("refs/heads/", fn, 11, cb_data);
455 }
456
457 int for_each_remote_ref(each_ref_fn fn, void *cb_data)
458 {
459 return do_for_each_ref("refs/remotes/", fn, 13, cb_data);
460 }
461
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 */
467 int get_ref_sha1(const char *ref, unsigned char *sha1)
468 {
469 if (check_ref_format(ref))
470 return -1;
471 return read_ref(mkpath("refs/%s", ref), sha1);
472 }
473
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
484 static inline int bad_ref_char(int ch)
485 {
486 return (((unsigned) ch) <= ' ' ||
487 ch == '~' || ch == '^' || ch == ':' ||
488 /* 2.13 Pattern Matching Notation */
489 ch == '?' || ch == '*' || ch == '[');
490 }
491
492 int check_ref_format(const char *ref)
493 {
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 }
524 }
525
526 static struct ref_lock *verify_lock(struct ref_lock *lock,
527 const unsigned char *old_sha1, int mustexist)
528 {
529 if (!resolve_ref(lock->ref_name, lock->old_sha1, mustexist, NULL)) {
530 error("Can't verify ref %s", lock->ref_name);
531 unlock_ref(lock);
532 return NULL;
533 }
534 if (hashcmp(lock->old_sha1, old_sha1)) {
535 error("Ref %s is at %s but expected %s", lock->ref_name,
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
543 static 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) &&
566 !remove_empty_dir_recursive(path, len + namlen))
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
581 static 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
596 static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int *flag)
597 {
598 char *ref_file;
599 const char *orig_ref = ref;
600 struct ref_lock *lock;
601 struct stat st;
602 int last_errno = 0;
603 int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
604
605 lock = xcalloc(1, sizeof(struct ref_lock));
606 lock->lock_fd = -1;
607
608 ref = resolve_ref(ref, lock->old_sha1, mustexist, flag);
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);
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 }
621 ref = resolve_ref(orig_ref, lock->old_sha1, mustexist, flag);
622 }
623 if (!ref) {
624 last_errno = errno;
625 error("unable to resolve reference %s: %s",
626 orig_ref, strerror(errno));
627 goto error_return;
628 }
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
653 lock->lk = xcalloc(1, sizeof(struct lock_file));
654
655 lock->ref_name = xstrdup(ref);
656 lock->log_file = xstrdup(git_path("logs/%s", ref));
657 ref_file = git_path("%s", ref);
658 lock->force_write = lstat(ref_file, &st) && errno == ENOENT;
659
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 }
665 lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
666
667 return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
668
669 error_return:
670 unlock_ref(lock);
671 errno = last_errno;
672 return NULL;
673 }
674
675 struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1)
676 {
677 char refpath[PATH_MAX];
678 if (check_ref_format(ref))
679 return NULL;
680 strcpy(refpath, mkpath("refs/%s", ref));
681 return lock_ref_sha1_basic(refpath, old_sha1, NULL);
682 }
683
684 struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1)
685 {
686 return lock_ref_sha1_basic(ref, old_sha1, NULL);
687 }
688
689 static struct lock_file packlock;
690
691 static int repack_without_ref(const char *refname)
692 {
693 struct ref_list *list, *packed_ref_list;
694 int fd;
695 int found = 0;
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
727 int 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;
760 }
761
762 void unlock_ref(struct ref_lock *lock)
763 {
764 if (lock->lock_fd >= 0) {
765 close(lock->lock_fd);
766 /* Do not free lock->lk -- atexit() still looks at them */
767 if (lock->lk)
768 rollback_lock_file(lock->lk);
769 }
770 free(lock->ref_name);
771 free(lock->log_file);
772 free(lock);
773 }
774
775 static 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;
781 const char *committer;
782
783 if (log_all_ref_updates &&
784 !strncmp(lock->ref_name, "refs/heads/", 11)) {
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) {
793 if (!(oflags & O_CREAT) && errno == ENOENT)
794 return 0;
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));
807 }
808
809 committer = git_committer_info(1);
810 if (msg) {
811 maxlen = strlen(committer) + strlen(msg) + 2*40 + 5;
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),
816 committer,
817 msg);
818 }
819 else {
820 maxlen = strlen(committer) + 2*40 + 4;
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),
825 committer);
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
835 int 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)
841 return -1;
842 if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
843 unlock_ref(lock);
844 return 0;
845 }
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) {
849 error("Couldn't write %s", lock->lk->filename);
850 unlock_ref(lock);
851 return -1;
852 }
853 invalidate_cached_refs();
854 if (log_ref_write(lock, sha1, logmsg) < 0) {
855 unlock_ref(lock);
856 return -1;
857 }
858 if (commit_lock_file(lock->lk)) {
859 error("Couldn't set %s", lock->ref_name);
860 unlock_ref(lock);
861 return -1;
862 }
863 lock->lock_fd = -1;
864 unlock_ref(lock);
865 return 0;
866 }
867
868 int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1)
869 {
870 const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
871 char *tz_c;
872 int logfd, tz;
873 struct stat st;
874 unsigned long date;
875 unsigned char logged_sha1[20];
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
887 lastrec = NULL;
888 rec = logend = logdata + st.st_size;
889 while (logdata < rec) {
890 if (logdata < rec && *(rec-1) == '\n')
891 rec--;
892 lastgt = NULL;
893 while (logdata < rec && *(rec-1) != '\n') {
894 rec--;
895 if (*rec == '>')
896 lastgt = rec;
897 }
898 if (!lastgt)
899 die("Log %s is corrupt.", logfile);
900 date = strtoul(lastgt + 1, &tz_c, 10);
901 if (date <= at_time || cnt == 0) {
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);
907 if (hashcmp(logged_sha1, sha1)) {
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 }
913 }
914 else if (date == at_time) {
915 if (get_sha1_hex(rec + 41, sha1))
916 die("Log %s is corrupt.", logfile);
917 }
918 else {
919 if (get_sha1_hex(rec + 41, logged_sha1))
920 die("Log %s is corrupt.", logfile);
921 if (hashcmp(logged_sha1, sha1)) {
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 }
928 munmap((void*)logdata, st.st_size);
929 return 0;
930 }
931 lastrec = rec;
932 if (cnt > 0)
933 cnt--;
934 }
935
936 rec = logdata;
937 while (rec < logend && *rec != '>' && *rec != '\n')
938 rec++;
939 if (rec == logend || *rec == '\n')
940 die("Log %s is corrupt.", logfile);
941 date = strtoul(rec + 1, &tz_c, 10);
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 }