Code

75cbc0e7ef32c384daafb4e8b8c27f8d1fd40538
[git.git] / refs.c
1 #include "refs.h"
2 #include "cache.h"
3 #include "object.h"
4 #include "tag.h"
6 #include <errno.h>
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 };
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;
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;
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;
46         if (peeled && (len < 3 || strcmp(line + len - 3, "^{}")))
47                 return NULL;
49         if (!peeled)
50                 *flag &= ~REF_ISPEELED;
51         else
52                 *flag |= REF_ISPEELED;
53         return line;
54 }
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;
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;
68                 /* Same as existing entry? */
69                 if (!cmp)
70                         return list;
71                 p = &entry->next;
72         }
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 }
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;
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         }
105 static void invalidate_cached_refs(void)
107         struct cached_refs *ca = &cached_refs;
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;
117 static struct ref_list *get_packed_refs(void)
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;
143 static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
145         DIR *dir = opendir(git_path("%s", base));
147         if (dir) {
148                 struct dirent *de;
149                 int baselen = strlen(base);
150                 char *ref = xmalloc(baselen + 257);
152                 memcpy(ref, base, baselen);
153                 if (baselen && base[baselen-1] != '/')
154                         ref[baselen++] = '/';
156                 while ((de = readdir(dir)) != NULL) {
157                         unsigned char sha1[20];
158                         struct stat st;
159                         int flag;
160                         int namelen;
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;
188 static struct ref_list *get_loose_refs(void)
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;
197 /* We allow "recursive" symbolic refs. Only within reason, though */
198 #define MAXDEPTH 5
200 const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
202         int depth = MAXDEPTH, len;
203         char buffer[256];
204         static char ref_buffer[256];
206         if (flag)
207                 *flag = 0;
209         for (;;) {
210                 const char *path = git_path("%s", ref);
211                 struct stat st;
212                 char *buf;
213                 int fd;
215                 if (--depth < 0)
216                         return NULL;
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                 }
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                 }
256                 /* Is it a directory? */
257                 if (S_ISDIR(st.st_mode)) {
258                         errno = EISDIR;
259                         return NULL;
260                 }
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);
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;
294 int create_symref(const char *ref_target, const char *refs_heads_master)
296         const char *lockpath;
297         char ref[1000];
298         int fd, len, written;
299         const char *git_HEAD = git_path("%s", ref_target);
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
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;
337 int read_ref(const char *ref, unsigned char *sha1)
339         if (resolve_ref(ref, sha1, 1, NULL))
340                 return 0;
341         return -1;
344 static int do_one_ref(const char *base, each_ref_fn fn, int trim,
345                       void *cb_data, struct ref_list *entry)
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);
360 int peel_ref(const char *ref, unsigned char *sha1)
362         int flag;
363         unsigned char base[20];
364         struct object *o;
366         if (!resolve_ref(ref, base, 1, &flag))
367                 return -1;
369         if ((flag & REF_ISPACKED)) {
370                 struct ref_list *list = get_packed_refs();
371                 int len = strlen(ref);
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         }
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;
398 static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
399                            void *cb_data)
401         int retval;
402         struct ref_list *packed = get_packed_refs();
403         struct ref_list *loose = get_loose_refs();
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         }
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;
432 int head_ref(each_ref_fn fn, void *cb_data)
434         unsigned char sha1[20];
435         int flag;
437         if (resolve_ref("HEAD", sha1, 1, &flag))
438                 return fn("HEAD", sha1, flag, cb_data);
439         return 0;
442 int for_each_ref(each_ref_fn fn, void *cb_data)
444         return do_for_each_ref("refs/", fn, 0, cb_data);
447 int for_each_tag_ref(each_ref_fn fn, void *cb_data)
449         return do_for_each_ref("refs/tags/", fn, 10, cb_data);
452 int for_each_branch_ref(each_ref_fn fn, void *cb_data)
454         return do_for_each_ref("refs/heads/", fn, 11, cb_data);
457 int for_each_remote_ref(each_ref_fn fn, void *cb_data)
459         return do_for_each_ref("refs/remotes/", fn, 13, cb_data);
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)
469         if (check_ref_format(ref))
470                 return -1;
471         return read_ref(mkpath("refs/%s", ref), sha1);
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  */
484 static inline int bad_ref_char(int ch)
486         return (((unsigned) ch) <= ' ' ||
487                 ch == '~' || ch == '^' || ch == ':' ||
488                 /* 2.13 Pattern Matching Notation */
489                 ch == '?' || ch == '*' || ch == '[');
492 int check_ref_format(const char *ref)
494         int ch, level;
495         const char *cp = ref;
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 */
504                 /* we are at the beginning of the path component */
505                 if (ch == '.' || bad_ref_char(ch))
506                         return -1;
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         }
526 static struct ref_lock *verify_lock(struct ref_lock *lock,
527         const unsigned char *old_sha1, int mustexist)
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;
543 static int remove_empty_dir_recursive(char *path, int len)
545         DIR *dir = opendir(path);
546         struct dirent *e;
547         int ret = 0;
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 ".." */
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 */
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;
581 static int remove_empty_directories(char *file)
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);
590         if (len >= PATH_MAX) /* path too long ;-) */
591                 return -1;
592         strcpy(path, file);
593         return remove_empty_dir_recursive(path, len);
596 static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int *flag)
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));
605         lock = xcalloc(1, sizeof(struct ref_lock));
606         lock->lock_fd = -1;
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;
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         }
653         lock->lk = xcalloc(1, sizeof(struct lock_file));
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;
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);
667         return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
669  error_return:
670         unlock_ref(lock);
671         errno = last_errno;
672         return NULL;
675 struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1)
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);
684 struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1)
686         return lock_ref_sha1_basic(ref, old_sha1, NULL);
689 static struct lock_file packlock;
691 static int repack_without_ref(const char *refname)
693         struct ref_list *list, *packed_ref_list;
694         int fd;
695         int found = 0;
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);
711         for (list = packed_ref_list; list; list = list->next) {
712                 char line[PATH_MAX + 100];
713                 int len;
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);
727 int delete_ref(const char *refname, unsigned char *sha1)
729         struct ref_lock *lock;
730         int err, i, ret = 0, flag = 0;
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);
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;
762 void unlock_ref(struct ref_lock *lock)
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);
775 static int log_ref_write(struct ref_lock *lock,
776         const unsigned char *sha1, const char *msg)
778         int logfd, written, oflags = O_APPEND | O_WRONLY;
779         unsigned maxlen, len;
780         char *logrec;
781         const char *committer;
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         }
791         logfd = open(lock->log_file, oflags, 0666);
792         if (logfd < 0) {
793                 if (!(oflags & O_CREAT) && errno == ENOENT)
794                         return 0;
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                 }
804                 if (logfd < 0)
805                         return error("Unable to append to %s: %s",
806                                      lock->log_file, strerror(errno));
807         }
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;
835 int write_ref_sha1(struct ref_lock *lock,
836         const unsigned char *sha1, const char *logmsg)
838         static char term = '\n';
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;
868 int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1)
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];
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);
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         }
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;