8 static FILE *info_ref_fp
;
10 static int add_info_ref(const char *path
, const unsigned char *sha1
)
12 struct object
*o
= parse_object(sha1
);
14 fprintf(info_ref_fp
, "%s %s\n", sha1_to_hex(sha1
), path
);
15 if (o
->type
== tag_type
) {
16 o
= deref_tag(o
, path
, 0);
18 fprintf(info_ref_fp
, "%s %s^{}\n",
19 sha1_to_hex(o
->sha1
), path
);
24 static int update_info_refs(int force
)
26 char *path0
= strdup(git_path("info/refs"));
27 int len
= strlen(path0
);
28 char *path1
= xmalloc(len
+ 2);
31 strcpy(path1
+ len
, "+");
33 safe_create_leading_directories(path0
);
34 info_ref_fp
= fopen(path1
, "w");
36 return error("unable to update %s", path0
);
37 for_each_ref(add_info_ref
);
46 static struct pack_info
{
53 unsigned char (*head
)[20];
56 static const char *objdir
;
59 static struct object
*parse_object_cheap(const unsigned char *sha1
)
63 if ((o
= parse_object(sha1
)) == NULL
)
65 if (o
->type
== commit_type
) {
66 struct commit
*commit
= (struct commit
*)o
;
68 commit
->buffer
= NULL
;
69 } else if (o
->type
== tree_type
) {
70 struct tree
*tree
= (struct tree
*)o
;
71 struct tree_entry_list
*e
, *n
;
72 for (e
= tree
->entries
; e
; e
= n
) {
83 static struct pack_info
*find_pack_by_name(const char *name
)
86 for (i
= 0; i
< num_pack
; i
++) {
87 struct packed_git
*p
= info
[i
]->p
;
88 /* skip "/pack/" after ".git/objects" */
89 if (!strcmp(p
->pack_name
+ objdirlen
+ 6, name
))
95 static struct pack_info
*find_pack_by_old_num(int old_num
)
98 for (i
= 0; i
< num_pack
; i
++)
99 if (info
[i
]->old_num
== old_num
)
104 static int add_head_def(struct pack_info
*this, unsigned char *sha1
)
106 if (this->nr_alloc
<= this->nr_heads
) {
107 this->nr_alloc
= alloc_nr(this->nr_alloc
);
108 this->head
= xrealloc(this->head
, this->nr_alloc
* 20);
110 memcpy(this->head
[this->nr_heads
++], sha1
, 20);
114 /* Returns non-zero when we detect that the info in the
115 * old file is useless.
117 static int parse_pack_def(const char *line
, int old_cnt
)
119 struct pack_info
*i
= find_pack_by_name(line
+ 2);
121 i
->old_num
= old_cnt
;
125 /* The file describes a pack that is no longer here */
130 /* Returns non-zero when we detect that the info in the old file is useless.
132 static int parse_head_def(char *line
)
134 unsigned char sha1
[20];
137 struct pack_info
*this;
141 num
= strtoul(cp
, &ep
, 10);
142 if (ep
== cp
|| *ep
++ != ' ')
143 return error("invalid input ix %s", line
);
144 this = find_pack_by_old_num(num
);
146 return 1; /* You know the drill. */
147 if (get_sha1_hex(ep
, sha1
) || ep
[40] != ' ')
148 return error("invalid input sha1 %s (%s)", line
, ep
);
149 if ((o
= parse_object_cheap(sha1
)) == NULL
)
150 return error("no such object: %s", line
);
151 return add_head_def(this, sha1
);
154 /* Returns non-zero when we detect that the info in the
155 * old file is useless.
157 static int read_pack_info_file(const char *infofile
)
163 fp
= fopen(infofile
, "r");
165 return 1; /* nonexisting is not an error. */
167 while (fgets(line
, sizeof(line
), fp
)) {
168 int len
= strlen(line
);
169 if (line
[len
-1] == '\n')
173 case 'P': /* P name */
174 if (parse_pack_def(line
, old_cnt
++))
177 case 'D': /* we used to emit D but that was misguided. */
180 case 'T': /* T ix sha1 type */
181 if (parse_head_def(line
))
185 error("unrecognized: %s", line
);
196 /* We sort the packs according to the date of the latest commit. That
197 * in turn indicates how young the pack is, and in general we would
198 * want to depend on younger packs.
200 static unsigned long get_latest_commit_date(struct packed_git
*p
)
202 unsigned char sha1
[20];
204 int num
= num_packed_objects(p
);
206 unsigned long latest
= 0;
208 for (i
= 0; i
< num
; i
++) {
209 if (nth_packed_object_sha1(p
, i
, sha1
))
210 die("corrupt pack file %s?", p
->pack_name
);
211 if ((o
= parse_object_cheap(sha1
)) == NULL
)
212 die("cannot parse %s", sha1_to_hex(sha1
));
213 if (o
->type
== commit_type
) {
214 struct commit
*commit
= (struct commit
*)o
;
215 if (latest
< commit
->date
)
216 latest
= commit
->date
;
222 static int compare_info(const void *a_
, const void *b_
)
224 struct pack_info
* const* a
= a_
;
225 struct pack_info
* const* b
= b_
;
227 if (0 <= (*a
)->old_num
&& 0 <= (*b
)->old_num
)
228 /* Keep the order in the original */
229 return (*a
)->old_num
- (*b
)->old_num
;
230 else if (0 <= (*a
)->old_num
)
231 /* Only A existed in the original so B is obviously newer */
233 else if (0 <= (*b
)->old_num
)
234 /* The other way around. */
237 if ((*a
)->latest
< (*b
)->latest
)
239 else if ((*a
)->latest
== (*b
)->latest
)
245 static void init_pack_info(const char *infofile
, int force
)
247 struct packed_git
*p
;
251 objdir
= get_object_directory();
252 objdirlen
= strlen(objdir
);
254 prepare_packed_git();
255 for (p
= packed_git
; p
; p
= p
->next
) {
256 /* we ignore things on alternate path since they are
257 * not available to the pullers in general.
259 if (strncmp(p
->pack_name
, objdir
, objdirlen
) ||
260 strncmp(p
->pack_name
+ objdirlen
, "/pack/", 6))
265 info
= xcalloc(num_pack
, sizeof(struct pack_info
*));
266 for (i
= 0, p
= packed_git
; p
; p
= p
->next
) {
267 if (strncmp(p
->pack_name
, objdir
, objdirlen
) ||
268 p
->pack_name
[objdirlen
] != '/')
270 info
[i
] = xcalloc(1, sizeof(struct pack_info
));
272 info
[i
]->old_num
= -1;
276 if (infofile
&& !force
)
277 stale
= read_pack_info_file(infofile
);
281 for (i
= 0; i
< num_pack
; i
++) {
283 info
[i
]->old_num
= -1;
284 info
[i
]->nr_heads
= 0;
286 if (info
[i
]->old_num
< 0)
287 info
[i
]->latest
= get_latest_commit_date(info
[i
]->p
);
291 qsort(info
, num_pack
, sizeof(info
[0]), compare_info
);
292 for (i
= 0; i
< num_pack
; i
++)
293 info
[i
]->new_num
= i
;
296 static void write_pack_info_file(FILE *fp
)
299 for (i
= 0; i
< num_pack
; i
++)
300 fprintf(fp
, "P %s\n", info
[i
]->p
->pack_name
+ objdirlen
+ 6);
301 for (i
= 0; i
< num_pack
; i
++) {
302 struct pack_info
*this = info
[i
];
303 for (j
= 0; j
< this->nr_heads
; j
++) {
304 struct object
*o
= lookup_object(this->head
[j
]);
305 fprintf(fp
, "T %1d %s %s\n",
306 i
, sha1_to_hex(this->head
[j
]), o
->type
);
312 #define REFERENCED 01
315 static void show(struct object
*o
, int pack_ix
)
318 * We are interested in objects that are not referenced,
320 if (o
->flags
& EMITTED
)
323 if (!(o
->flags
& REFERENCED
))
324 add_head_def(info
[pack_ix
], o
->sha1
);
328 static void find_pack_info_one(int pack_ix
)
330 unsigned char sha1
[20];
333 struct packed_git
*p
= info
[pack_ix
]->p
;
334 int num
= num_packed_objects(p
);
336 /* Scan objects, clear flags from all the edge ones and
337 * internal ones, possibly marked in the previous round.
339 for (i
= 0; i
< num
; i
++) {
340 if (nth_packed_object_sha1(p
, i
, sha1
))
341 die("corrupt pack file %s?", p
->pack_name
);
342 if ((o
= lookup_object(sha1
)) == NULL
)
343 die("cannot parse %s", sha1_to_hex(sha1
));
345 struct object_refs
*refs
= o
->refs
;
347 for (j
= 0; j
< refs
->count
; j
++)
348 refs
->ref
[j
]->flags
= 0;
353 /* Mark all the referenced ones */
354 for (i
= 0; i
< num
; i
++) {
355 if (nth_packed_object_sha1(p
, i
, sha1
))
356 die("corrupt pack file %s?", p
->pack_name
);
357 if ((o
= lookup_object(sha1
)) == NULL
)
358 die("cannot find %s", sha1_to_hex(sha1
));
360 struct object_refs
*refs
= o
->refs
;
362 for (j
= 0; j
< refs
->count
; j
++)
363 refs
->ref
[j
]->flags
|= REFERENCED
;
367 for (i
= 0; i
< num
; i
++) {
368 if (nth_packed_object_sha1(p
, i
, sha1
))
369 die("corrupt pack file %s?", p
->pack_name
);
370 if ((o
= lookup_object(sha1
)) == NULL
)
371 die("cannot find %s", sha1_to_hex(sha1
));
377 static void find_pack_info(void)
380 for (i
= 0; i
< num_pack
; i
++) {
381 /* The packed objects are cast in stone, and a head
382 * in a pack will stay as head, so is the set of missing
383 * objects. If the repo has been reorganized and we
384 * are missing some packs available back then, we have
385 * already discarded the info read from the file, so
386 * we will find (old_num < 0) in that case.
388 if (0 <= info
[i
]->old_num
)
390 find_pack_info_one(i
);
394 static int update_info_packs(int force
)
396 char infofile
[PATH_MAX
];
401 namelen
= sprintf(infofile
, "%s/info/packs", get_object_directory());
402 strcpy(name
, infofile
);
403 strcpy(name
+ namelen
, "+");
405 init_pack_info(infofile
, force
);
408 safe_create_leading_directories(name
);
409 fp
= fopen(name
, "w");
411 return error("cannot open %s", name
);
412 write_pack_info_file(fp
);
414 rename(name
, infofile
);
419 int update_server_info(int force
)
421 /* We would add more dumb-server support files later,
422 * including index of available pack files and their
423 * intended audiences.
427 errs
= errs
| update_info_refs(force
);
428 errs
= errs
| update_info_packs(force
);
430 /* remove leftover rev-cache file if there is any */
431 unlink(git_path("info/rev-cache"));