~ubuntu-branches/ubuntu/intrepid/git-core/intrepid-updates

« back to all changes in this revision

Viewing changes to refs.c

  • Committer: Package Import Robot
  • Author(s): Gerrit Pape
  • Date: 2007-04-22 13:31:05 UTC
  • mfrom: (1.1.14)
  • Revision ID: package-import@ubuntu.com-20070422133105-tkmhz328g2p0epz1
Tags: 1:1.5.1.2-1
* new upstream point release.
* debian/changelog.upstream: upstream changes taken from mailing list
  announcement.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "cache.h"
1
2
#include "refs.h"
2
 
#include "cache.h"
 
3
#include "object.h"
 
4
#include "tag.h"
3
5
 
4
 
#include <errno.h>
 
6
/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
 
7
#define REF_KNOWS_PEELED 04
5
8
 
6
9
struct ref_list {
7
10
        struct ref_list *next;
8
11
        unsigned char flag; /* ISSYMREF? ISPACKED? */
9
12
        unsigned char sha1[20];
 
13
        unsigned char peeled[20];
10
14
        char name[FLEX_ARRAY];
11
15
};
12
16
 
34
38
        if (line[len] != '\n')
35
39
                return NULL;
36
40
        line[len] = 0;
 
41
 
37
42
        return line;
38
43
}
39
44
 
40
45
static struct ref_list *add_ref(const char *name, const unsigned char *sha1,
41
 
                                int flag, struct ref_list *list)
 
46
                                int flag, struct ref_list *list,
 
47
                                struct ref_list **new_entry)
42
48
{
43
49
        int len;
44
50
        struct ref_list **p = &list, *entry;
50
56
                        break;
51
57
 
52
58
                /* Same as existing entry? */
53
 
                if (!cmp)
 
59
                if (!cmp) {
 
60
                        if (new_entry)
 
61
                                *new_entry = entry;
54
62
                        return list;
 
63
                }
55
64
                p = &entry->next;
56
65
        }
57
66
 
59
68
        len = strlen(name) + 1;
60
69
        entry = xmalloc(sizeof(struct ref_list) + len);
61
70
        hashcpy(entry->sha1, sha1);
 
71
        hashclr(entry->peeled);
62
72
        memcpy(entry->name, name, len);
63
73
        entry->flag = flag;
64
74
        entry->next = *p;
65
75
        *p = entry;
 
76
        if (new_entry)
 
77
                *new_entry = entry;
66
78
        return list;
67
79
}
68
80
 
98
110
        ca->did_loose = ca->did_packed = 0;
99
111
}
100
112
 
 
113
static void read_packed_refs(FILE *f, struct cached_refs *cached_refs)
 
114
{
 
115
        struct ref_list *list = NULL;
 
116
        struct ref_list *last = NULL;
 
117
        char refline[PATH_MAX];
 
118
        int flag = REF_ISPACKED;
 
119
 
 
120
        while (fgets(refline, sizeof(refline), f)) {
 
121
                unsigned char sha1[20];
 
122
                const char *name;
 
123
                static const char header[] = "# pack-refs with:";
 
124
 
 
125
                if (!strncmp(refline, header, sizeof(header)-1)) {
 
126
                        const char *traits = refline + sizeof(header) - 1;
 
127
                        if (strstr(traits, " peeled "))
 
128
                                flag |= REF_KNOWS_PEELED;
 
129
                        /* perhaps other traits later as well */
 
130
                        continue;
 
131
                }
 
132
 
 
133
                name = parse_ref_line(refline, sha1);
 
134
                if (name) {
 
135
                        list = add_ref(name, sha1, flag, list, &last);
 
136
                        continue;
 
137
                }
 
138
                if (last &&
 
139
                    refline[0] == '^' &&
 
140
                    strlen(refline) == 42 &&
 
141
                    refline[41] == '\n' &&
 
142
                    !get_sha1_hex(refline + 1, sha1))
 
143
                        hashcpy(last->peeled, sha1);
 
144
        }
 
145
        cached_refs->packed = list;
 
146
}
 
147
 
101
148
static struct ref_list *get_packed_refs(void)
102
149
{
103
150
        if (!cached_refs.did_packed) {
104
 
                struct ref_list *refs = NULL;
105
151
                FILE *f = fopen(git_path("packed-refs"), "r");
 
152
                cached_refs.packed = NULL;
106
153
                if (f) {
107
 
                        struct ref_list *list = NULL;
108
 
                        char refline[PATH_MAX];
109
 
                        while (fgets(refline, sizeof(refline), f)) {
110
 
                                unsigned char sha1[20];
111
 
                                const char *name = parse_ref_line(refline, sha1);
112
 
                                if (!name)
113
 
                                        continue;
114
 
                                list = add_ref(name, sha1, REF_ISPACKED, list);
115
 
                        }
 
154
                        read_packed_refs(f, &cached_refs);
116
155
                        fclose(f);
117
 
                        refs = list;
118
156
                }
119
 
                cached_refs.packed = refs;
120
157
                cached_refs.did_packed = 1;
121
158
        }
122
159
        return cached_refs.packed;
159
196
                                error("%s points nowhere!", ref);
160
197
                                continue;
161
198
                        }
162
 
                        list = add_ref(ref, sha1, flag, list);
 
199
                        list = add_ref(ref, sha1, flag, list, NULL);
163
200
                }
164
201
                free(ref);
165
202
                closedir(dir);
247
284
                fd = open(path, O_RDONLY);
248
285
                if (fd < 0)
249
286
                        return NULL;
250
 
                len = read(fd, buffer, sizeof(buffer)-1);
 
287
                len = read_in_full(fd, buffer, sizeof(buffer)-1);
251
288
                close(fd);
252
289
 
253
290
                /*
272
309
        return ref;
273
310
}
274
311
 
275
 
int create_symref(const char *ref_target, const char *refs_heads_master)
276
 
{
277
 
        const char *lockpath;
278
 
        char ref[1000];
279
 
        int fd, len, written;
280
 
        const char *git_HEAD = git_path("%s", ref_target);
281
 
 
282
 
#ifndef NO_SYMLINK_HEAD
283
 
        if (prefer_symlink_refs) {
284
 
                unlink(git_HEAD);
285
 
                if (!symlink(refs_heads_master, git_HEAD))
286
 
                        return 0;
287
 
                fprintf(stderr, "no symlink - falling back to symbolic ref\n");
288
 
        }
289
 
#endif
290
 
 
291
 
        len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
292
 
        if (sizeof(ref) <= len) {
293
 
                error("refname too long: %s", refs_heads_master);
294
 
                return -1;
295
 
        }
296
 
        lockpath = mkpath("%s.lock", git_HEAD);
297
 
        fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666); 
298
 
        written = write(fd, ref, len);
299
 
        close(fd);
300
 
        if (written != len) {
301
 
                unlink(lockpath);
302
 
                error("Unable to write to %s", lockpath);
303
 
                return -2;
304
 
        }
305
 
        if (rename(lockpath, git_HEAD) < 0) {
306
 
                unlink(lockpath);
307
 
                error("Unable to create %s", git_HEAD);
308
 
                return -3;
309
 
        }
310
 
        if (adjust_shared_perm(git_HEAD)) {
311
 
                unlink(lockpath);
312
 
                error("Unable to fix permissions on %s", lockpath);
313
 
                return -4;
314
 
        }
315
 
        return 0;
316
 
}
317
 
 
318
312
int read_ref(const char *ref, unsigned char *sha1)
319
313
{
320
314
        if (resolve_ref(ref, sha1, 1, NULL))
336
330
        return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
337
331
}
338
332
 
 
333
int peel_ref(const char *ref, unsigned char *sha1)
 
334
{
 
335
        int flag;
 
336
        unsigned char base[20];
 
337
        struct object *o;
 
338
 
 
339
        if (!resolve_ref(ref, base, 1, &flag))
 
340
                return -1;
 
341
 
 
342
        if ((flag & REF_ISPACKED)) {
 
343
                struct ref_list *list = get_packed_refs();
 
344
 
 
345
                while (list) {
 
346
                        if (!strcmp(list->name, ref)) {
 
347
                                if (list->flag & REF_KNOWS_PEELED) {
 
348
                                        hashcpy(sha1, list->peeled);
 
349
                                        return 0;
 
350
                                }
 
351
                                /* older pack-refs did not leave peeled ones */
 
352
                                break;
 
353
                        }
 
354
                        list = list->next;
 
355
                }
 
356
        }
 
357
 
 
358
        /* fallback - callers should not call this for unpacked refs */
 
359
        o = parse_object(base);
 
360
        if (o->type == OBJ_TAG) {
 
361
                o = deref_tag(o, ref, 0);
 
362
                if (o) {
 
363
                        hashcpy(sha1, o->sha1);
 
364
                        return 0;
 
365
                }
 
366
        }
 
367
        return -1;
 
368
}
 
369
 
339
370
static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
340
371
                           void *cb_data)
341
372
{
458
489
                level++;
459
490
                if (!ch) {
460
491
                        if (level < 2)
461
 
                                return -1; /* at least of form "heads/blah" */
 
492
                                return -2; /* at least of form "heads/blah" */
462
493
                        return 0;
463
494
                }
464
495
        }
534
565
        return remove_empty_dir_recursive(path, len);
535
566
}
536
567
 
 
568
static int is_refname_available(const char *ref, const char *oldref,
 
569
                                struct ref_list *list, int quiet)
 
570
{
 
571
        int namlen = strlen(ref); /* e.g. 'foo/bar' */
 
572
        while (list) {
 
573
                /* list->name could be 'foo' or 'foo/bar/baz' */
 
574
                if (!oldref || strcmp(oldref, list->name)) {
 
575
                        int len = strlen(list->name);
 
576
                        int cmplen = (namlen < len) ? namlen : len;
 
577
                        const char *lead = (namlen < len) ? list->name : ref;
 
578
                        if (!strncmp(ref, list->name, cmplen) &&
 
579
                            lead[cmplen] == '/') {
 
580
                                if (!quiet)
 
581
                                        error("'%s' exists; cannot create '%s'",
 
582
                                              list->name, ref);
 
583
                                return 0;
 
584
                        }
 
585
                }
 
586
                list = list->next;
 
587
        }
 
588
        return 1;
 
589
}
 
590
 
537
591
static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int *flag)
538
592
{
539
593
        char *ref_file;
567
621
                        orig_ref, strerror(errno));
568
622
                goto error_return;
569
623
        }
570
 
        if (is_null_sha1(lock->old_sha1)) {
571
 
                /* The ref did not exist and we are creating it.
572
 
                 * Make sure there is no existing ref that is packed
573
 
                 * whose name begins with our refname, nor a ref whose
574
 
                 * name is a proper prefix of our refname.
575
 
                 */
576
 
                int namlen = strlen(ref); /* e.g. 'foo/bar' */
577
 
                struct ref_list *list = get_packed_refs();
578
 
                while (list) {
579
 
                        /* list->name could be 'foo' or 'foo/bar/baz' */
580
 
                        int len = strlen(list->name);
581
 
                        int cmplen = (namlen < len) ? namlen : len;
582
 
                        const char *lead = (namlen < len) ? list->name : ref;
583
 
 
584
 
                        if (!strncmp(ref, list->name, cmplen) &&
585
 
                            lead[cmplen] == '/') {
586
 
                                error("'%s' exists; cannot create '%s'",
587
 
                                      list->name, ref);
588
 
                                goto error_return;
589
 
                        }
590
 
                        list = list->next;
591
 
                }
592
 
        }
 
624
        /* When the ref did not exist and we are creating it,
 
625
         * make sure there is no existing ref that is packed
 
626
         * whose name begins with our refname, nor a ref whose
 
627
         * name is a proper prefix of our refname.
 
628
         */
 
629
        if (is_null_sha1(lock->old_sha1) &&
 
630
            !is_refname_available(ref, NULL, get_packed_refs(), 0))
 
631
                goto error_return;
593
632
 
594
633
        lock->lk = xcalloc(1, sizeof(struct lock_file));
595
634
 
596
635
        lock->ref_name = xstrdup(ref);
597
 
        lock->log_file = xstrdup(git_path("logs/%s", ref));
 
636
        lock->orig_ref_name = xstrdup(orig_ref);
598
637
        ref_file = git_path("%s", ref);
599
638
        lock->force_write = lstat(ref_file, &st) && errno == ENOENT;
600
639
 
624
663
 
625
664
struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1)
626
665
{
 
666
        if (check_ref_format(ref) == -1)
 
667
                return NULL;
627
668
        return lock_ref_sha1_basic(ref, old_sha1, NULL);
628
669
}
629
670
 
644
685
        }
645
686
        if (!found)
646
687
                return 0;
647
 
        memset(&packlock, 0, sizeof(packlock));
648
688
        fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
649
689
        if (fd < 0)
650
690
                return error("cannot delete '%s' from packed refs", refname);
665
705
        return commit_lock_file(&packlock);
666
706
}
667
707
 
668
 
int delete_ref(const char *refname, unsigned char *sha1)
 
708
int delete_ref(const char *refname, const unsigned char *sha1)
669
709
{
670
710
        struct ref_lock *lock;
671
711
        int err, i, ret = 0, flag = 0;
691
731
         */
692
732
        ret |= repack_without_ref(refname);
693
733
 
694
 
        err = unlink(lock->log_file);
 
734
        err = unlink(git_path("logs/%s", lock->ref_name));
695
735
        if (err && errno != ENOENT)
696
736
                fprintf(stderr, "warning: unlink(%s) failed: %s",
697
 
                        lock->log_file, strerror(errno));
 
737
                        git_path("logs/%s", lock->ref_name), strerror(errno));
698
738
        invalidate_cached_refs();
699
739
        unlock_ref(lock);
700
740
        return ret;
701
741
}
702
742
 
 
743
int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 
744
{
 
745
        static const char renamed_ref[] = "RENAMED-REF";
 
746
        unsigned char sha1[20], orig_sha1[20];
 
747
        int flag = 0, logmoved = 0;
 
748
        struct ref_lock *lock;
 
749
        struct stat loginfo;
 
750
        int log = !lstat(git_path("logs/%s", oldref), &loginfo);
 
751
 
 
752
        if (S_ISLNK(loginfo.st_mode))
 
753
                return error("reflog for %s is a symlink", oldref);
 
754
 
 
755
        if (!resolve_ref(oldref, orig_sha1, 1, &flag))
 
756
                return error("refname %s not found", oldref);
 
757
 
 
758
        if (!is_refname_available(newref, oldref, get_packed_refs(), 0))
 
759
                return 1;
 
760
 
 
761
        if (!is_refname_available(newref, oldref, get_loose_refs(), 0))
 
762
                return 1;
 
763
 
 
764
        lock = lock_ref_sha1_basic(renamed_ref, NULL, NULL);
 
765
        if (!lock)
 
766
                return error("unable to lock %s", renamed_ref);
 
767
        lock->force_write = 1;
 
768
        if (write_ref_sha1(lock, orig_sha1, logmsg))
 
769
                return error("unable to save current sha1 in %s", renamed_ref);
 
770
 
 
771
        if (log && rename(git_path("logs/%s", oldref), git_path("tmp-renamed-log")))
 
772
                return error("unable to move logfile logs/%s to tmp-renamed-log: %s",
 
773
                        oldref, strerror(errno));
 
774
 
 
775
        if (delete_ref(oldref, orig_sha1)) {
 
776
                error("unable to delete old %s", oldref);
 
777
                goto rollback;
 
778
        }
 
779
 
 
780
        if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1)) {
 
781
                if (errno==EISDIR) {
 
782
                        if (remove_empty_directories(git_path("%s", newref))) {
 
783
                                error("Directory not empty: %s", newref);
 
784
                                goto rollback;
 
785
                        }
 
786
                } else {
 
787
                        error("unable to delete existing %s", newref);
 
788
                        goto rollback;
 
789
                }
 
790
        }
 
791
 
 
792
        if (log && safe_create_leading_directories(git_path("logs/%s", newref))) {
 
793
                error("unable to create directory for %s", newref);
 
794
                goto rollback;
 
795
        }
 
796
 
 
797
 retry:
 
798
        if (log && rename(git_path("tmp-renamed-log"), git_path("logs/%s", newref))) {
 
799
                if (errno==EISDIR || errno==ENOTDIR) {
 
800
                        /*
 
801
                         * rename(a, b) when b is an existing
 
802
                         * directory ought to result in ISDIR, but
 
803
                         * Solaris 5.8 gives ENOTDIR.  Sheesh.
 
804
                         */
 
805
                        if (remove_empty_directories(git_path("logs/%s", newref))) {
 
806
                                error("Directory not empty: logs/%s", newref);
 
807
                                goto rollback;
 
808
                        }
 
809
                        goto retry;
 
810
                } else {
 
811
                        error("unable to move logfile tmp-renamed-log to logs/%s: %s",
 
812
                                newref, strerror(errno));
 
813
                        goto rollback;
 
814
                }
 
815
        }
 
816
        logmoved = log;
 
817
 
 
818
        lock = lock_ref_sha1_basic(newref, NULL, NULL);
 
819
        if (!lock) {
 
820
                error("unable to lock %s for update", newref);
 
821
                goto rollback;
 
822
        }
 
823
 
 
824
        lock->force_write = 1;
 
825
        hashcpy(lock->old_sha1, orig_sha1);
 
826
        if (write_ref_sha1(lock, orig_sha1, logmsg)) {
 
827
                error("unable to write current sha1 into %s", newref);
 
828
                goto rollback;
 
829
        }
 
830
 
 
831
        return 0;
 
832
 
 
833
 rollback:
 
834
        lock = lock_ref_sha1_basic(oldref, NULL, NULL);
 
835
        if (!lock) {
 
836
                error("unable to lock %s for rollback", oldref);
 
837
                goto rollbacklog;
 
838
        }
 
839
 
 
840
        lock->force_write = 1;
 
841
        flag = log_all_ref_updates;
 
842
        log_all_ref_updates = 0;
 
843
        if (write_ref_sha1(lock, orig_sha1, NULL))
 
844
                error("unable to write current sha1 into %s", oldref);
 
845
        log_all_ref_updates = flag;
 
846
 
 
847
 rollbacklog:
 
848
        if (logmoved && rename(git_path("logs/%s", newref), git_path("logs/%s", oldref)))
 
849
                error("unable to restore logfile %s from %s: %s",
 
850
                        oldref, newref, strerror(errno));
 
851
        if (!logmoved && log &&
 
852
            rename(git_path("tmp-renamed-log"), git_path("logs/%s", oldref)))
 
853
                error("unable to restore logfile %s from tmp-renamed-log: %s",
 
854
                        oldref, strerror(errno));
 
855
 
 
856
        return 1;
 
857
}
 
858
 
703
859
void unlock_ref(struct ref_lock *lock)
704
860
{
705
861
        if (lock->lock_fd >= 0) {
709
865
                        rollback_lock_file(lock->lk);
710
866
        }
711
867
        free(lock->ref_name);
712
 
        free(lock->log_file);
 
868
        free(lock->orig_ref_name);
713
869
        free(lock);
714
870
}
715
871
 
716
 
static int log_ref_write(struct ref_lock *lock,
717
 
        const unsigned char *sha1, const char *msg)
 
872
static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
 
873
                         const unsigned char *new_sha1, const char *msg)
718
874
{
719
875
        int logfd, written, oflags = O_APPEND | O_WRONLY;
720
876
        unsigned maxlen, len;
721
 
        char *logrec;
 
877
        int msglen;
 
878
        char *log_file, *logrec;
722
879
        const char *committer;
723
880
 
 
881
        if (log_all_ref_updates < 0)
 
882
                log_all_ref_updates = !is_bare_repository();
 
883
 
 
884
        log_file = git_path("logs/%s", ref_name);
 
885
 
724
886
        if (log_all_ref_updates &&
725
 
            !strncmp(lock->ref_name, "refs/heads/", 11)) {
726
 
                if (safe_create_leading_directories(lock->log_file) < 0)
 
887
            (!prefixcmp(ref_name, "refs/heads/") ||
 
888
             !prefixcmp(ref_name, "refs/remotes/") ||
 
889
             !strcmp(ref_name, "HEAD"))) {
 
890
                if (safe_create_leading_directories(log_file) < 0)
727
891
                        return error("unable to create directory for %s",
728
 
                                lock->log_file);
 
892
                                     log_file);
729
893
                oflags |= O_CREAT;
730
894
        }
731
895
 
732
 
        logfd = open(lock->log_file, oflags, 0666);
 
896
        logfd = open(log_file, oflags, 0666);
733
897
        if (logfd < 0) {
734
898
                if (!(oflags & O_CREAT) && errno == ENOENT)
735
899
                        return 0;
736
900
 
737
901
                if ((oflags & O_CREAT) && errno == EISDIR) {
738
 
                        if (remove_empty_directories(lock->log_file)) {
 
902
                        if (remove_empty_directories(log_file)) {
739
903
                                return error("There are still logs under '%s'",
740
 
                                             lock->log_file);
 
904
                                             log_file);
741
905
                        }
742
 
                        logfd = open(lock->log_file, oflags, 0666);
 
906
                        logfd = open(log_file, oflags, 0666);
743
907
                }
744
908
 
745
909
                if (logfd < 0)
746
910
                        return error("Unable to append to %s: %s",
747
 
                                     lock->log_file, strerror(errno));
 
911
                                     log_file, strerror(errno));
748
912
        }
749
913
 
750
 
        committer = git_committer_info(1);
 
914
        adjust_shared_perm(log_file);
 
915
 
 
916
        msglen = 0;
751
917
        if (msg) {
752
 
                maxlen = strlen(committer) + strlen(msg) + 2*40 + 5;
753
 
                logrec = xmalloc(maxlen);
754
 
                len = snprintf(logrec, maxlen, "%s %s %s\t%s\n",
755
 
                        sha1_to_hex(lock->old_sha1),
756
 
                        sha1_to_hex(sha1),
757
 
                        committer,
758
 
                        msg);
759
 
        }
760
 
        else {
761
 
                maxlen = strlen(committer) + 2*40 + 4;
762
 
                logrec = xmalloc(maxlen);
763
 
                len = snprintf(logrec, maxlen, "%s %s %s\n",
764
 
                        sha1_to_hex(lock->old_sha1),
765
 
                        sha1_to_hex(sha1),
766
 
                        committer);
767
 
        }
768
 
        written = len <= maxlen ? write(logfd, logrec, len) : -1;
 
918
                /* clean up the message and make sure it is a single line */
 
919
                for ( ; *msg; msg++)
 
920
                        if (!isspace(*msg))
 
921
                                break;
 
922
                if (*msg) {
 
923
                        const char *ep = strchr(msg, '\n');
 
924
                        if (ep)
 
925
                                msglen = ep - msg;
 
926
                        else
 
927
                                msglen = strlen(msg);
 
928
                }
 
929
        }
 
930
 
 
931
        committer = git_committer_info(-1);
 
932
        maxlen = strlen(committer) + msglen + 100;
 
933
        logrec = xmalloc(maxlen);
 
934
        len = sprintf(logrec, "%s %s %s\n",
 
935
                      sha1_to_hex(old_sha1),
 
936
                      sha1_to_hex(new_sha1),
 
937
                      committer);
 
938
        if (msglen)
 
939
                len += sprintf(logrec + len - 1, "\t%.*s\n", msglen, msg) - 1;
 
940
        written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1;
769
941
        free(logrec);
770
942
        close(logfd);
771
943
        if (written != len)
772
 
                return error("Unable to append to %s", lock->log_file);
 
944
                return error("Unable to append to %s", log_file);
773
945
        return 0;
774
946
}
775
947
 
784
956
                unlock_ref(lock);
785
957
                return 0;
786
958
        }
787
 
        if (write(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
788
 
            write(lock->lock_fd, &term, 1) != 1
 
959
        if (write_in_full(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
 
960
            write_in_full(lock->lock_fd, &term, 1) != 1
789
961
                || close(lock->lock_fd) < 0) {
790
962
                error("Couldn't write %s", lock->lk->filename);
791
963
                unlock_ref(lock);
792
964
                return -1;
793
965
        }
794
966
        invalidate_cached_refs();
795
 
        if (log_ref_write(lock, sha1, logmsg) < 0) {
 
967
        if (log_ref_write(lock->ref_name, lock->old_sha1, sha1, logmsg) < 0 ||
 
968
            (strcmp(lock->ref_name, lock->orig_ref_name) &&
 
969
             log_ref_write(lock->orig_ref_name, lock->old_sha1, sha1, logmsg) < 0)) {
796
970
                unlock_ref(lock);
797
971
                return -1;
798
972
        }
 
973
        if (strcmp(lock->orig_ref_name, "HEAD") != 0) {
 
974
                /*
 
975
                 * Special hack: If a branch is updated directly and HEAD
 
976
                 * points to it (may happen on the remote side of a push
 
977
                 * for example) then logically the HEAD reflog should be
 
978
                 * updated too.
 
979
                 * A generic solution implies reverse symref information,
 
980
                 * but finding all symrefs pointing to the given branch
 
981
                 * would be rather costly for this rare event (the direct
 
982
                 * update of a branch) to be worth it.  So let's cheat and
 
983
                 * check with HEAD only which should cover 99% of all usage
 
984
                 * scenarios (even 100% of the default ones).
 
985
                 */
 
986
                unsigned char head_sha1[20];
 
987
                int head_flag;
 
988
                const char *head_ref;
 
989
                head_ref = resolve_ref("HEAD", head_sha1, 1, &head_flag);
 
990
                if (head_ref && (head_flag & REF_ISSYMREF) &&
 
991
                    !strcmp(head_ref, lock->ref_name))
 
992
                        log_ref_write("HEAD", lock->old_sha1, sha1, logmsg);
 
993
        }
799
994
        if (commit_lock_file(lock->lk)) {
800
995
                error("Couldn't set %s", lock->ref_name);
801
996
                unlock_ref(lock);
806
1001
        return 0;
807
1002
}
808
1003
 
809
 
int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1)
 
1004
int create_symref(const char *ref_target, const char *refs_heads_master,
 
1005
                  const char *logmsg)
 
1006
{
 
1007
        const char *lockpath;
 
1008
        char ref[1000];
 
1009
        int fd, len, written;
 
1010
        char *git_HEAD = xstrdup(git_path("%s", ref_target));
 
1011
        unsigned char old_sha1[20], new_sha1[20];
 
1012
 
 
1013
        if (logmsg && read_ref(ref_target, old_sha1))
 
1014
                hashclr(old_sha1);
 
1015
 
 
1016
        if (safe_create_leading_directories(git_HEAD) < 0)
 
1017
                return error("unable to create directory for %s", git_HEAD);
 
1018
 
 
1019
#ifndef NO_SYMLINK_HEAD
 
1020
        if (prefer_symlink_refs) {
 
1021
                unlink(git_HEAD);
 
1022
                if (!symlink(refs_heads_master, git_HEAD))
 
1023
                        goto done;
 
1024
                fprintf(stderr, "no symlink - falling back to symbolic ref\n");
 
1025
        }
 
1026
#endif
 
1027
 
 
1028
        len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
 
1029
        if (sizeof(ref) <= len) {
 
1030
                error("refname too long: %s", refs_heads_master);
 
1031
                goto error_free_return;
 
1032
        }
 
1033
        lockpath = mkpath("%s.lock", git_HEAD);
 
1034
        fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
 
1035
        if (fd < 0) {
 
1036
                error("Unable to open %s for writing", lockpath);
 
1037
                goto error_free_return;
 
1038
        }
 
1039
        written = write_in_full(fd, ref, len);
 
1040
        close(fd);
 
1041
        if (written != len) {
 
1042
                error("Unable to write to %s", lockpath);
 
1043
                goto error_unlink_return;
 
1044
        }
 
1045
        if (rename(lockpath, git_HEAD) < 0) {
 
1046
                error("Unable to create %s", git_HEAD);
 
1047
                goto error_unlink_return;
 
1048
        }
 
1049
        if (adjust_shared_perm(git_HEAD)) {
 
1050
                error("Unable to fix permissions on %s", lockpath);
 
1051
        error_unlink_return:
 
1052
                unlink(lockpath);
 
1053
        error_free_return:
 
1054
                free(git_HEAD);
 
1055
                return -1;
 
1056
        }
 
1057
 
 
1058
#ifndef NO_SYMLINK_HEAD
 
1059
        done:
 
1060
#endif
 
1061
        if (logmsg && !read_ref(refs_heads_master, new_sha1))
 
1062
                log_ref_write(ref_target, old_sha1, new_sha1, logmsg);
 
1063
 
 
1064
        free(git_HEAD);
 
1065
        return 0;
 
1066
}
 
1067
 
 
1068
static char *ref_msg(const char *line, const char *endp)
 
1069
{
 
1070
        const char *ep;
 
1071
        char *msg;
 
1072
 
 
1073
        line += 82;
 
1074
        for (ep = line; ep < endp && *ep != '\n'; ep++)
 
1075
                ;
 
1076
        msg = xmalloc(ep - line + 1);
 
1077
        memcpy(msg, line, ep - line);
 
1078
        msg[ep - line] = 0;
 
1079
        return msg;
 
1080
}
 
1081
 
 
1082
int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
810
1083
{
811
1084
        const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
812
1085
        char *tz_c;
813
 
        int logfd, tz;
 
1086
        int logfd, tz, reccnt = 0;
814
1087
        struct stat st;
815
1088
        unsigned long date;
816
1089
        unsigned char logged_sha1[20];
 
1090
        void *log_mapped;
 
1091
        size_t mapsz;
817
1092
 
818
1093
        logfile = git_path("logs/%s", ref);
819
1094
        logfd = open(logfile, O_RDONLY, 0);
822
1097
        fstat(logfd, &st);
823
1098
        if (!st.st_size)
824
1099
                die("Log %s is empty.", logfile);
825
 
        logdata = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
 
1100
        mapsz = xsize_t(st.st_size);
 
1101
        log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);
 
1102
        logdata = log_mapped;
826
1103
        close(logfd);
827
1104
 
828
1105
        lastrec = NULL;
829
1106
        rec = logend = logdata + st.st_size;
830
1107
        while (logdata < rec) {
 
1108
                reccnt++;
831
1109
                if (logdata < rec && *(rec-1) == '\n')
832
1110
                        rec--;
833
1111
                lastgt = NULL;
840
1118
                        die("Log %s is corrupt.", logfile);
841
1119
                date = strtoul(lastgt + 1, &tz_c, 10);
842
1120
                if (date <= at_time || cnt == 0) {
 
1121
                        tz = strtoul(tz_c, NULL, 10);
 
1122
                        if (msg)
 
1123
                                *msg = ref_msg(rec, logend);
 
1124
                        if (cutoff_time)
 
1125
                                *cutoff_time = date;
 
1126
                        if (cutoff_tz)
 
1127
                                *cutoff_tz = tz;
 
1128
                        if (cutoff_cnt)
 
1129
                                *cutoff_cnt = reccnt - 1;
843
1130
                        if (lastrec) {
844
1131
                                if (get_sha1_hex(lastrec, logged_sha1))
845
1132
                                        die("Log %s is corrupt.", logfile);
846
1133
                                if (get_sha1_hex(rec + 41, sha1))
847
1134
                                        die("Log %s is corrupt.", logfile);
848
1135
                                if (hashcmp(logged_sha1, sha1)) {
849
 
                                        tz = strtoul(tz_c, NULL, 10);
850
1136
                                        fprintf(stderr,
851
1137
                                                "warning: Log %s has gap after %s.\n",
852
1138
                                                logfile, show_rfc2822_date(date, tz));
860
1146
                                if (get_sha1_hex(rec + 41, logged_sha1))
861
1147
                                        die("Log %s is corrupt.", logfile);
862
1148
                                if (hashcmp(logged_sha1, sha1)) {
863
 
                                        tz = strtoul(tz_c, NULL, 10);
864
1149
                                        fprintf(stderr,
865
1150
                                                "warning: Log %s unexpectedly ended on %s.\n",
866
1151
                                                logfile, show_rfc2822_date(date, tz));
867
1152
                                }
868
1153
                        }
869
 
                        munmap((void*)logdata, st.st_size);
 
1154
                        munmap(log_mapped, mapsz);
870
1155
                        return 0;
871
1156
                }
872
1157
                lastrec = rec;
883
1168
        tz = strtoul(tz_c, NULL, 10);
884
1169
        if (get_sha1_hex(logdata, sha1))
885
1170
                die("Log %s is corrupt.", logfile);
886
 
        munmap((void*)logdata, st.st_size);
887
 
        fprintf(stderr, "warning: Log %s only goes back to %s.\n",
888
 
                logfile, show_rfc2822_date(date, tz));
889
 
        return 0;
 
1171
        if (msg)
 
1172
                *msg = ref_msg(logdata, logend);
 
1173
        munmap(log_mapped, mapsz);
 
1174
 
 
1175
        if (cutoff_time)
 
1176
                *cutoff_time = date;
 
1177
        if (cutoff_tz)
 
1178
                *cutoff_tz = tz;
 
1179
        if (cutoff_cnt)
 
1180
                *cutoff_cnt = reccnt;
 
1181
        return 1;
 
1182
}
 
1183
 
 
1184
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
 
1185
{
 
1186
        const char *logfile;
 
1187
        FILE *logfp;
 
1188
        char buf[1024];
 
1189
        int ret = 0;
 
1190
 
 
1191
        logfile = git_path("logs/%s", ref);
 
1192
        logfp = fopen(logfile, "r");
 
1193
        if (!logfp)
 
1194
                return -1;
 
1195
        while (fgets(buf, sizeof(buf), logfp)) {
 
1196
                unsigned char osha1[20], nsha1[20];
 
1197
                char *email_end, *message;
 
1198
                unsigned long timestamp;
 
1199
                int len, tz;
 
1200
 
 
1201
                /* old SP new SP name <email> SP time TAB msg LF */
 
1202
                len = strlen(buf);
 
1203
                if (len < 83 || buf[len-1] != '\n' ||
 
1204
                    get_sha1_hex(buf, osha1) || buf[40] != ' ' ||
 
1205
                    get_sha1_hex(buf + 41, nsha1) || buf[81] != ' ' ||
 
1206
                    !(email_end = strchr(buf + 82, '>')) ||
 
1207
                    email_end[1] != ' ' ||
 
1208
                    !(timestamp = strtoul(email_end + 2, &message, 10)) ||
 
1209
                    !message || message[0] != ' ' ||
 
1210
                    (message[1] != '+' && message[1] != '-') ||
 
1211
                    !isdigit(message[2]) || !isdigit(message[3]) ||
 
1212
                    !isdigit(message[4]) || !isdigit(message[5]))
 
1213
                        continue; /* corrupt? */
 
1214
                email_end[1] = '\0';
 
1215
                tz = strtol(message + 1, NULL, 10);
 
1216
                if (message[6] != '\t')
 
1217
                        message += 6;
 
1218
                else
 
1219
                        message += 7;
 
1220
                ret = fn(osha1, nsha1, buf+82, timestamp, tz, message, cb_data);
 
1221
                if (ret)
 
1222
                        break;
 
1223
        }
 
1224
        fclose(logfp);
 
1225
        return ret;
 
1226
}
 
1227
 
 
1228
static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
 
1229
{
 
1230
        DIR *dir = opendir(git_path("logs/%s", base));
 
1231
        int retval = 0;
 
1232
 
 
1233
        if (dir) {
 
1234
                struct dirent *de;
 
1235
                int baselen = strlen(base);
 
1236
                char *log = xmalloc(baselen + 257);
 
1237
 
 
1238
                memcpy(log, base, baselen);
 
1239
                if (baselen && base[baselen-1] != '/')
 
1240
                        log[baselen++] = '/';
 
1241
 
 
1242
                while ((de = readdir(dir)) != NULL) {
 
1243
                        struct stat st;
 
1244
                        int namelen;
 
1245
 
 
1246
                        if (de->d_name[0] == '.')
 
1247
                                continue;
 
1248
                        namelen = strlen(de->d_name);
 
1249
                        if (namelen > 255)
 
1250
                                continue;
 
1251
                        if (has_extension(de->d_name, ".lock"))
 
1252
                                continue;
 
1253
                        memcpy(log + baselen, de->d_name, namelen+1);
 
1254
                        if (stat(git_path("logs/%s", log), &st) < 0)
 
1255
                                continue;
 
1256
                        if (S_ISDIR(st.st_mode)) {
 
1257
                                retval = do_for_each_reflog(log, fn, cb_data);
 
1258
                        } else {
 
1259
                                unsigned char sha1[20];
 
1260
                                if (!resolve_ref(log, sha1, 0, NULL))
 
1261
                                        retval = error("bad ref for %s", log);
 
1262
                                else
 
1263
                                        retval = fn(log, sha1, 0, cb_data);
 
1264
                        }
 
1265
                        if (retval)
 
1266
                                break;
 
1267
                }
 
1268
                free(log);
 
1269
                closedir(dir);
 
1270
        }
 
1271
        else if (*base)
 
1272
                return errno;
 
1273
        return retval;
 
1274
}
 
1275
 
 
1276
int for_each_reflog(each_ref_fn fn, void *cb_data)
 
1277
{
 
1278
        return do_for_each_reflog("", fn, cb_data);
890
1279
}