} cached_refs;
static struct ref_list *current_ref;
+static struct ref_list *extra_refs;
+
static void free_ref_list(struct ref_list *list)
{
struct ref_list *next;
cached_refs->packed = sort_ref_list(list);
}
+void add_extra_ref(const char *name, const unsigned char *sha1, int flag)
+{
+ extra_refs = add_ref(name, sha1, flag, extra_refs, NULL);
+}
+
+void clear_extra_refs(void)
+{
+ free_ref_list(extra_refs);
+ extra_refs = NULL;
+}
+
static struct ref_list *get_packed_refs(void)
{
if (!cached_refs.did_packed) {
return retval;
}
+/*
+ * If the "reading" argument is set, this function finds out what _object_
+ * the ref points at by "reading" the ref. The ref, if it is not symbolic,
+ * has to exist, and if it is symbolic, it has to point at an existing ref,
+ * because the "read" goes through the symref to the ref it points at.
+ *
+ * The access that is not "reading" may often be "writing", but does not
+ * have to; it can be merely checking _where it leads to_. If it is a
+ * prelude to "writing" to the ref, a write to a symref that points at
+ * yet-to-be-born ref will create the real ref pointed by the symref.
+ * reading=0 allows the caller to check where such a symref leads to.
+ */
const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
{
int depth = MAXDEPTH;
if (--depth < 0)
return NULL;
- /* Special case: non-existing file.
- * Not having the refs/heads/new-branch is OK
- * if we are writing into it, so is .git/HEAD
- * that points at refs/heads/master still to be
- * born. It is NOT OK if we are resolving for
- * reading.
- */
+ /* Special case: non-existing file. */
if (lstat(path, &st) < 0) {
struct ref_list *list = get_packed_refs();
while (list) {
struct ref_list *packed = get_packed_refs();
struct ref_list *loose = get_loose_refs();
+ struct ref_list *extra;
+
+ for (extra = extra_refs; extra; extra = extra->next)
+ retval = do_one_ref(base, fn, trim, cb_data, extra);
+
while (packed && loose) {
struct ref_list *entry;
int cmp = strcmp(packed->name, loose->name);
i = strlen(lock->lk->filename) - 5; /* .lock */
lock->lk->filename[i] = 0;
err = unlink(lock->lk->filename);
- if (err) {
+ if (err && errno != ENOENT) {
ret = 1;
error("unlink(%s) failed: %s",
lock->lk->filename, strerror(errno));
tz = strtoul(tz_c, NULL, 10);
if (get_sha1_hex(logdata, sha1))
die("Log %s is corrupt.", logfile);
+ if (is_null_sha1(sha1)) {
+ if (get_sha1_hex(logdata + 41, sha1))
+ die("Log %s is corrupt.", logfile);
+ }
if (msg)
*msg = ref_msg(logdata, logend);
munmap(log_mapped, mapsz);