pack: move open_pack_index(), parse_pack_index()

alloc_packed_git() in packfile.c is duplicated from sha1_file.c. In a subsequent commit, alloc_packed_git() will be removed from sha1_file.c. Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Tan committed Aug 18, 2017 at 15:20 UTC 0317f45576a0b48c90c4b023fa572a000633946c
10 files changed +163 -148
builtin/count-objects.c
+1
@@ -10,6 +10,7 @@
10 #include "builtin.h"
11 #include "parse-options.h"
12 #include "quote.h"
13 +#include "packfile.h"
14
15 static unsigned long garbage;
16 static off_t size_garbage;
builtin/fsck.c
+1
@@ -15,6 +15,7 @@
15 #include "progress.h"
16 #include "streaming.h"
17 #include "decorate.h"
18 +#include "packfile.h"
19
20 #define REACHABLE 0x0001
21 #define SEEN 0x0002
builtin/pack-objects.c
+1
@@ -25,6 +25,7 @@
25 #include "sha1-array.h"
26 #include "argv-array.h"
27 #include "mru.h"
28 +#include "packfile.h"
29
30 static const char *pack_usage[] = {
31 N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"),
cache.h
-8
@@ -1605,8 +1605,6 @@ struct pack_entry {
1605 struct packed_git *p;
1606 };
1607
1608 -extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
1609 -
1608 /* A hook to report invalid files in pack directory */
1609 #define PACKDIR_FILE_PACK 1
1610 #define PACKDIR_FILE_IDX 2
@@ -1641,12 +1639,6 @@ extern int odb_mkstemp(struct strbuf *template, const char *pattern);
1639 */
1640 extern int odb_pack_keep(const char *name);
1641
1644 -/*
1645 - * mmap the index file for the specified packfile (if it is not
1646 - * already mmapped). Return 0 on success.
1647 - */
1648 -extern int open_pack_index(struct packed_git *);
1649 -
1642 /*
1643 * munmap the index file for the specified packfile (if it is
1644 * currently mmapped).
pack-bitmap.c
+1
@@ -9,6 +9,7 @@
9 #include "pack-bitmap.h"
10 #include "pack-revindex.h"
11 #include "pack-objects.h"
12 +#include "packfile.h"
13
14 /*
15 * An entry on the bitmap index, representing the bitmap for a given
pack-check.c
+1
@@ -2,6 +2,7 @@
2 #include "pack.h"
3 #include "pack-revindex.h"
4 #include "progress.h"
5 +#include "packfile.h"
6
7 struct idx_entry {
8 off_t offset;
packfile.c
+149
@@ -1,5 +1,6 @@
1 #include "cache.h"
2 #include "mru.h"
3 +#include "pack.h"
4
5 char *odb_pack_name(struct strbuf *buf,
6 const unsigned char *sha1,
@@ -59,3 +60,151 @@ void pack_report(void)
60 pack_open_windows, peak_pack_open_windows,
61 sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped));
62 }
63 +
64 +/*
65 + * Open and mmap the index file at path, perform a couple of
66 + * consistency checks, then record its information to p. Return 0 on
67 + * success.
68 + */
69 +static int check_packed_git_idx(const char *path, struct packed_git *p)
70 +{
71 + void *idx_map;
72 + struct pack_idx_header *hdr;
73 + size_t idx_size;
74 + uint32_t version, nr, i, *index;
75 + int fd = git_open(path);
76 + struct stat st;
77 +
78 + if (fd < 0)
79 + return -1;
80 + if (fstat(fd, &st)) {
81 + close(fd);
82 + return -1;
83 + }
84 + idx_size = xsize_t(st.st_size);
85 + if (idx_size < 4 * 256 + 20 + 20) {
86 + close(fd);
87 + return error("index file %s is too small", path);
88 + }
89 + idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
90 + close(fd);
91 +
92 + hdr = idx_map;
93 + if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
94 + version = ntohl(hdr->idx_version);
95 + if (version < 2 || version > 2) {
96 + munmap(idx_map, idx_size);
97 + return error("index file %s is version %"PRIu32
98 + " and is not supported by this binary"
99 + " (try upgrading GIT to a newer version)",
100 + path, version);
101 + }
102 + } else
103 + version = 1;
104 +
105 + nr = 0;
106 + index = idx_map;
107 + if (version > 1)
108 + index += 2; /* skip index header */
109 + for (i = 0; i < 256; i++) {
110 + uint32_t n = ntohl(index[i]);
111 + if (n < nr) {
112 + munmap(idx_map, idx_size);
113 + return error("non-monotonic index %s", path);
114 + }
115 + nr = n;
116 + }
117 +
118 + if (version == 1) {
119 + /*
120 + * Total size:
121 + * - 256 index entries 4 bytes each
122 + * - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
123 + * - 20-byte SHA1 of the packfile
124 + * - 20-byte SHA1 file checksum
125 + */
126 + if (idx_size != 4*256 + nr * 24 + 20 + 20) {
127 + munmap(idx_map, idx_size);
128 + return error("wrong index v1 file size in %s", path);
129 + }
130 + } else if (version == 2) {
131 + /*
132 + * Minimum size:
133 + * - 8 bytes of header
134 + * - 256 index entries 4 bytes each
135 + * - 20-byte sha1 entry * nr
136 + * - 4-byte crc entry * nr
137 + * - 4-byte offset entry * nr
138 + * - 20-byte SHA1 of the packfile
139 + * - 20-byte SHA1 file checksum
140 + * And after the 4-byte offset table might be a
141 + * variable sized table containing 8-byte entries
142 + * for offsets larger than 2^31.
143 + */
144 + unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
145 + unsigned long max_size = min_size;
146 + if (nr)
147 + max_size += (nr - 1)*8;
148 + if (idx_size < min_size || idx_size > max_size) {
149 + munmap(idx_map, idx_size);
150 + return error("wrong index v2 file size in %s", path);
151 + }
152 + if (idx_size != min_size &&
153 + /*
154 + * make sure we can deal with large pack offsets.
155 + * 31-bit signed offset won't be enough, neither
156 + * 32-bit unsigned one will be.
157 + */
158 + (sizeof(off_t) <= 4)) {
159 + munmap(idx_map, idx_size);
160 + return error("pack too large for current definition of off_t in %s", path);
161 + }
162 + }
163 +
164 + p->index_version = version;
165 + p->index_data = idx_map;
166 + p->index_size = idx_size;
167 + p->num_objects = nr;
168 + return 0;
169 +}
170 +
171 +int open_pack_index(struct packed_git *p)
172 +{
173 + char *idx_name;
174 + size_t len;
175 + int ret;
176 +
177 + if (p->index_data)
178 + return 0;
179 +
180 + if (!strip_suffix(p->pack_name, ".pack", &len))
181 + die("BUG: pack_name does not end in .pack");
182 + idx_name = xstrfmt("%.*s.idx", (int)len, p->pack_name);
183 + ret = check_packed_git_idx(idx_name, p);
184 + free(idx_name);
185 + return ret;
186 +}
187 +
188 +static struct packed_git *alloc_packed_git(int extra)
189 +{
190 + struct packed_git *p = xmalloc(st_add(sizeof(*p), extra));
191 + memset(p, 0, sizeof(*p));
192 + p->pack_fd = -1;
193 + return p;
194 +}
195 +
196 +struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
197 +{
198 + const char *path = sha1_pack_name(sha1);
199 + size_t alloc = st_add(strlen(path), 1);
200 + struct packed_git *p = alloc_packed_git(alloc);
201 +
202 + memcpy(p->pack_name, path, alloc); /* includes NUL */
203 + hashcpy(p->sha1, sha1);
204 + if (check_packed_git_idx(idx_path, p)) {
205 + free(p);
206 + return NULL;
207 + }
208 +
209 + return p;
210 +}
packfile.h
+8
@@ -33,6 +33,14 @@ extern unsigned int pack_max_fds;
33 extern size_t peak_pack_mapped;
34 extern size_t pack_mapped;
35
36 +extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
37 +
38 extern void pack_report(void);
39
40 +/*
41 + * mmap the index file for the specified packfile (if it is not
42 + * already mmapped). Return 0 on success.
43 + */
44 +extern int open_pack_index(struct packed_git *);
45 +
46 #endif
sha1_file.c
-140
@@ -681,130 +681,6 @@ static int has_loose_object(const unsigned char *sha1)
681 return check_and_freshen(sha1, 0);
682 }
683
684 -/*
685 - * Open and mmap the index file at path, perform a couple of
686 - * consistency checks, then record its information to p. Return 0 on
687 - * success.
688 - */
689 -static int check_packed_git_idx(const char *path, struct packed_git *p)
690 -{
691 - void *idx_map;
692 - struct pack_idx_header *hdr;
693 - size_t idx_size;
694 - uint32_t version, nr, i, *index;
695 - int fd = git_open(path);
696 - struct stat st;
697 -
698 - if (fd < 0)
699 - return -1;
700 - if (fstat(fd, &st)) {
701 - close(fd);
702 - return -1;
703 - }
704 - idx_size = xsize_t(st.st_size);
705 - if (idx_size < 4 * 256 + 20 + 20) {
706 - close(fd);
707 - return error("index file %s is too small", path);
708 - }
709 - idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
710 - close(fd);
711 -
712 - hdr = idx_map;
713 - if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
714 - version = ntohl(hdr->idx_version);
715 - if (version < 2 || version > 2) {
716 - munmap(idx_map, idx_size);
717 - return error("index file %s is version %"PRIu32
718 - " and is not supported by this binary"
719 - " (try upgrading GIT to a newer version)",
720 - path, version);
721 - }
722 - } else
723 - version = 1;
724 -
725 - nr = 0;
726 - index = idx_map;
727 - if (version > 1)
728 - index += 2; /* skip index header */
729 - for (i = 0; i < 256; i++) {
730 - uint32_t n = ntohl(index[i]);
731 - if (n < nr) {
732 - munmap(idx_map, idx_size);
733 - return error("non-monotonic index %s", path);
734 - }
735 - nr = n;
736 - }
737 -
738 - if (version == 1) {
739 - /*
740 - * Total size:
741 - * - 256 index entries 4 bytes each
742 - * - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
743 - * - 20-byte SHA1 of the packfile
744 - * - 20-byte SHA1 file checksum
745 - */
746 - if (idx_size != 4*256 + nr * 24 + 20 + 20) {
747 - munmap(idx_map, idx_size);
748 - return error("wrong index v1 file size in %s", path);
749 - }
750 - } else if (version == 2) {
751 - /*
752 - * Minimum size:
753 - * - 8 bytes of header
754 - * - 256 index entries 4 bytes each
755 - * - 20-byte sha1 entry * nr
756 - * - 4-byte crc entry * nr
757 - * - 4-byte offset entry * nr
758 - * - 20-byte SHA1 of the packfile
759 - * - 20-byte SHA1 file checksum
760 - * And after the 4-byte offset table might be a
761 - * variable sized table containing 8-byte entries
762 - * for offsets larger than 2^31.
763 - */
764 - unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
765 - unsigned long max_size = min_size;
766 - if (nr)
767 - max_size += (nr - 1)*8;
768 - if (idx_size < min_size || idx_size > max_size) {
769 - munmap(idx_map, idx_size);
770 - return error("wrong index v2 file size in %s", path);
771 - }
772 - if (idx_size != min_size &&
773 - /*
774 - * make sure we can deal with large pack offsets.
775 - * 31-bit signed offset won't be enough, neither
776 - * 32-bit unsigned one will be.
777 - */
778 - (sizeof(off_t) <= 4)) {
779 - munmap(idx_map, idx_size);
780 - return error("pack too large for current definition of off_t in %s", path);
781 - }
782 - }
783 -
784 - p->index_version = version;
785 - p->index_data = idx_map;
786 - p->index_size = idx_size;
787 - p->num_objects = nr;
788 - return 0;
789 -}
790 -
791 -int open_pack_index(struct packed_git *p)
792 -{
793 - char *idx_name;
794 - size_t len;
795 - int ret;
796 -
797 - if (p->index_data)
798 - return 0;
799 -
800 - if (!strip_suffix(p->pack_name, ".pack", &len))
801 - die("BUG: pack_name does not end in .pack");
802 - idx_name = xstrfmt("%.*s.idx", (int)len, p->pack_name);
803 - ret = check_packed_git_idx(idx_name, p);
804 - free(idx_name);
805 - return ret;
806 -}
807 -
684 static void scan_windows(struct packed_git *p,
685 struct packed_git **lru_p,
686 struct pack_window **lru_w,
@@ -1302,22 +1178,6 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local)
1178 return p;
1179 }
1180
1305 -struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
1306 -{
1307 - const char *path = sha1_pack_name(sha1);
1308 - size_t alloc = st_add(strlen(path), 1);
1309 - struct packed_git *p = alloc_packed_git(alloc);
1310 -
1311 - memcpy(p->pack_name, path, alloc); /* includes NUL */
1312 - hashcpy(p->sha1, sha1);
1313 - if (check_packed_git_idx(idx_path, p)) {
1314 - free(p);
1315 - return NULL;
1316 - }
1317 -
1318 - return p;
1319 -}
1320 -
1181 void install_packed_git(struct packed_git *pack)
1182 {
1183 if (pack->pack_fd != -1)
sha1_name.c
+1
@@ -9,6 +9,7 @@
9 #include "remote.h"
10 #include "dir.h"
11 #include "sha1-array.h"
12 +#include "packfile.h"
13
14 static int get_oid_oneline(const char *, struct object_id *, struct commit_list *);
15