int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix) { int entries, was_valid, newfd; struct lock_file *lock_file; /* * We can't free this memory, it becomes part of a linked list * parsed atexit() */ lock_file = xcalloc(1, sizeof(struct lock_file)); newfd = hold_locked_index(lock_file, 1); entries = read_cache(); if (entries < 0) return WRITE_TREE_UNREADABLE_INDEX; if (flags & WRITE_TREE_IGNORE_CACHE_TREE) cache_tree_free(&(active_cache_tree)); if (!active_cache_tree) active_cache_tree = cache_tree(); was_valid = cache_tree_fully_valid(active_cache_tree); if (!was_valid) { int missing_ok = flags & WRITE_TREE_MISSING_OK; if (cache_tree_update(active_cache_tree, active_cache, active_nr, missing_ok, 0) < 0) return WRITE_TREE_UNMERGED_INDEX; if (0 <= newfd) { if (!write_cache(newfd, active_cache, active_nr) && !commit_lock_file(lock_file)) newfd = -1; } /* Not being able to write is fine -- we are only interested * in updating the cache-tree part, and if the next caller * ends up using the old index with unupdated cache-tree part * it misses the work we did here, but that is just a * performance penalty and not a big deal. */ } if (prefix) { struct cache_tree *subtree = cache_tree_find(active_cache_tree, prefix); if (!subtree) return WRITE_TREE_PREFIX_ERROR; hashcpy(sha1, subtree->sha1); } else hashcpy(sha1, active_cache_tree->sha1); if (0 <= newfd) rollback_lock_file(lock_file); return 0; }
/* * find the cache_tree that corresponds to the current level without * exploding the full path into textual form. The root of the * cache tree is given as "root", and our current level is "info". * (1) When at root level, info->prev is NULL, so it is "root" itself. * (2) Otherwise, find the cache_tree that corresponds to one level * above us, and find ourselves in there. */ static struct cache_tree *find_cache_tree_from_traversal(struct cache_tree *root, struct traverse_info *info) { struct cache_tree *our_parent; if (!info->prev) return root; our_parent = find_cache_tree_from_traversal(root, info->prev); return cache_tree_find(our_parent, info->name.path); }
int cache_tree_matches_traversal(struct cache_tree *root, struct name_entry *ent, struct traverse_info *info) { struct cache_tree *it; it = find_cache_tree_from_traversal(root, info); it = cache_tree_find(it, ent->path); if (it && it->entry_count > 0 && !hashcmp(ent->sha1, it->sha1)) return it->entry_count; return 0; }
int write_index_as_tree(unsigned char *sha1, struct index_state *index_state, const char *index_path, int flags, const char *prefix) { int entries, was_valid, newfd; struct lock_file *lock_file; /* * We can't free this memory, it becomes part of a linked list * parsed atexit() */ lock_file = xcalloc(1, sizeof(struct lock_file)); newfd = hold_lock_file_for_update(lock_file, index_path, LOCK_DIE_ON_ERROR); entries = read_index_from(index_state, index_path); if (entries < 0) return WRITE_TREE_UNREADABLE_INDEX; if (flags & WRITE_TREE_IGNORE_CACHE_TREE) cache_tree_free(&index_state->cache_tree); if (!index_state->cache_tree) index_state->cache_tree = cache_tree(); was_valid = cache_tree_fully_valid(index_state->cache_tree); if (!was_valid) { if (cache_tree_update(index_state, flags) < 0) return WRITE_TREE_UNMERGED_INDEX; if (0 <= newfd) { if (!write_locked_index(index_state, lock_file, COMMIT_LOCK)) newfd = -1; } /* Not being able to write is fine -- we are only interested * in updating the cache-tree part, and if the next caller * ends up using the old index with unupdated cache-tree part * it misses the work we did here, but that is just a * performance penalty and not a big deal. */ } if (prefix) { struct cache_tree *subtree; subtree = cache_tree_find(index_state->cache_tree, prefix); if (!subtree) return WRITE_TREE_PREFIX_ERROR; hashcpy(sha1, subtree->sha1); } else hashcpy(sha1, index_state->cache_tree->sha1); if (0 <= newfd) rollback_lock_file(lock_file); return 0; }
int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix) { int entries, was_valid; struct lock_file lock_file = LOCK_INIT; int ret = 0; hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR); entries = read_index_from(index_state, index_path, get_git_dir()); if (entries < 0) { ret = WRITE_TREE_UNREADABLE_INDEX; goto out; } if (flags & WRITE_TREE_IGNORE_CACHE_TREE) cache_tree_free(&index_state->cache_tree); if (!index_state->cache_tree) index_state->cache_tree = cache_tree(); was_valid = cache_tree_fully_valid(index_state->cache_tree); if (!was_valid) { if (cache_tree_update(index_state, flags) < 0) { ret = WRITE_TREE_UNMERGED_INDEX; goto out; } write_locked_index(index_state, &lock_file, COMMIT_LOCK); /* Not being able to write is fine -- we are only interested * in updating the cache-tree part, and if the next caller * ends up using the old index with unupdated cache-tree part * it misses the work we did here, but that is just a * performance penalty and not a big deal. */ } if (prefix) { struct cache_tree *subtree; subtree = cache_tree_find(index_state->cache_tree, prefix); if (!subtree) { ret = WRITE_TREE_PREFIX_ERROR; goto out; } oidcpy(oid, &subtree->oid); } else oidcpy(oid, &index_state->cache_tree->oid); out: rollback_lock_file(&lock_file); return ret; }