mirror of
https://github.com/git/git
synced 2024-11-04 16:17:49 +00:00
Merge branch 'ps/refs-without-the-repository-updates'
Further clean-up the refs subsystem to stop relying on the_repository, and instead use the repository associated to the ref_store object. * ps/refs-without-the-repository-updates: refs/packed: remove references to `the_hash_algo` refs/files: remove references to `the_hash_algo` refs/files: use correct repository refs: remove `dwim_log()` refs: drop `git_default_branch_name()` refs: pass repo when peeling objects refs: move object peeling into "object.c" refs: pass ref store when detecting dangling symrefs refs: convert iteration over replace refs to accept ref store refs: retrieve worktree ref stores via associated repository refs: refactor `resolve_gitlink_ref()` to accept a repository refs: pass repo when retrieving submodule ref store refs: track ref stores via strmap refs: implement releasing ref storages refs: rename `init_db` callback to avoid confusion refs: adjust names for `init` and `init_db` callbacks
This commit is contained in:
commit
988499e295
52 changed files with 408 additions and 392 deletions
3
attr.c
3
attr.c
|
@ -1301,7 +1301,8 @@ static const char *builtin_object_mode_attr(struct index_state *istate, const ch
|
|||
if (pos >= 0) {
|
||||
if (S_ISGITLINK(istate->cache[pos]->ce_mode))
|
||||
mode = istate->cache[pos]->ce_mode;
|
||||
} else if (resolve_gitlink_ref(path, "HEAD", &oid) == 0) {
|
||||
} else if (repo_resolve_gitlink_ref(the_repository, path,
|
||||
"HEAD", &oid) == 0) {
|
||||
mode = S_IFGITLINK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1468,6 +1468,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||
} else if (remote_head) {
|
||||
our_head_points_at = NULL;
|
||||
} else {
|
||||
char *to_free = NULL;
|
||||
const char *branch;
|
||||
|
||||
if (!mapped_refs) {
|
||||
|
@ -1480,7 +1481,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||
"refs/heads/", &branch)) {
|
||||
unborn_head = xstrdup(transport_ls_refs_options.unborn_head_target);
|
||||
} else {
|
||||
branch = git_default_branch_name(0);
|
||||
branch = to_free = repo_default_branch_name(the_repository, 0);
|
||||
unborn_head = xstrfmt("refs/heads/%s", branch);
|
||||
}
|
||||
|
||||
|
@ -1496,6 +1497,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||
* a match.
|
||||
*/
|
||||
our_head_points_at = find_remote_branch(mapped_refs, branch);
|
||||
|
||||
free(to_free);
|
||||
}
|
||||
|
||||
write_refspec_config(src_ref_prefix, our_head_points_at,
|
||||
|
|
|
@ -200,7 +200,7 @@ static int get_name(const char *path, const struct object_id *oid,
|
|||
}
|
||||
|
||||
/* Is it annotated? */
|
||||
if (!peel_iterated_oid(oid, &peeled)) {
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled)) {
|
||||
is_annotated = !oideq(oid, &peeled);
|
||||
} else {
|
||||
oidcpy(&peeled, oid);
|
||||
|
|
|
@ -1412,7 +1412,8 @@ static int prune_refs(struct display_state *display_state,
|
|||
_("(none)"), ref->name,
|
||||
&ref->new_oid, &ref->old_oid,
|
||||
summary_width);
|
||||
warn_dangling_symref(stderr, dangling_msg, ref->name);
|
||||
refs_warn_dangling_symref(get_main_ref_store(the_repository),
|
||||
stderr, dangling_msg, ref->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -846,7 +846,7 @@ static int dfs_on_ref(const char *refname UNUSED,
|
|||
struct commit_list *stack = NULL;
|
||||
struct commit *commit;
|
||||
|
||||
if (!peel_iterated_oid(oid, &peeled))
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled))
|
||||
oid = &peeled;
|
||||
if (oid_object_info(the_repository, oid, NULL) != OBJ_COMMIT)
|
||||
return 0;
|
||||
|
|
|
@ -779,7 +779,7 @@ static int mark_tagged(const char *path UNUSED, const struct object_id *oid,
|
|||
|
||||
if (entry)
|
||||
entry->tagged = 1;
|
||||
if (!peel_iterated_oid(oid, &peeled)) {
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled)) {
|
||||
entry = packlist_find(&to_pack, &peeled);
|
||||
if (entry)
|
||||
entry->tagged = 1;
|
||||
|
@ -3132,7 +3132,7 @@ static int add_ref_tag(const char *tag UNUSED, const struct object_id *oid,
|
|||
{
|
||||
struct object_id peeled;
|
||||
|
||||
if (!peel_iterated_oid(oid, &peeled) && obj_is_packed(&peeled))
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled) && obj_is_packed(&peeled))
|
||||
add_tag_chain(oid);
|
||||
return 0;
|
||||
}
|
||||
|
@ -4081,7 +4081,7 @@ static int mark_bitmap_preferred_tip(const char *refname,
|
|||
struct object_id peeled;
|
||||
struct object *object;
|
||||
|
||||
if (!peel_iterated_oid(oid, &peeled))
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled))
|
||||
oid = &peeled;
|
||||
|
||||
object = parse_object_or_die(oid, refname);
|
||||
|
|
|
@ -378,7 +378,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
|
|||
char *ref;
|
||||
struct expire_reflog_policy_cb cb = { .cmd = cmd };
|
||||
|
||||
if (!dwim_log(argv[i], strlen(argv[i]), NULL, &ref)) {
|
||||
if (!repo_dwim_log(the_repository, argv[i], strlen(argv[i]), NULL, &ref)) {
|
||||
status |= error(_("%s points nowhere!"), argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1477,7 +1477,8 @@ static int prune_remote(const char *remote, int dry_run)
|
|||
abbrev_ref(refname, "refs/remotes/"));
|
||||
}
|
||||
|
||||
warn_dangling_symrefs(stdout, dangling_msg, &refs_to_prune);
|
||||
refs_warn_dangling_symrefs(get_main_ref_store(the_repository),
|
||||
stdout, dangling_msg, &refs_to_prune);
|
||||
|
||||
string_list_clear(&refs_to_prune, 0);
|
||||
free_remote_ref_states(&states);
|
||||
|
|
|
@ -673,7 +673,7 @@ static int midx_snapshot_ref_one(const char *refname UNUSED,
|
|||
struct midx_snapshot_ref_data *data = _data;
|
||||
struct object_id peeled;
|
||||
|
||||
if (!peel_iterated_oid(oid, &peeled))
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled))
|
||||
oid = &peeled;
|
||||
|
||||
if (oidset_insert(&data->seen, oid))
|
||||
|
|
|
@ -43,11 +43,12 @@ enum replace_format {
|
|||
};
|
||||
|
||||
struct show_data {
|
||||
struct repository *repo;
|
||||
const char *pattern;
|
||||
enum replace_format format;
|
||||
};
|
||||
|
||||
static int show_reference(struct repository *r, const char *refname,
|
||||
static int show_reference(const char *refname,
|
||||
const struct object_id *oid,
|
||||
int flag UNUSED, void *cb_data)
|
||||
{
|
||||
|
@ -62,11 +63,11 @@ static int show_reference(struct repository *r, const char *refname,
|
|||
struct object_id object;
|
||||
enum object_type obj_type, repl_type;
|
||||
|
||||
if (repo_get_oid(r, refname, &object))
|
||||
if (repo_get_oid(data->repo, refname, &object))
|
||||
return error(_("failed to resolve '%s' as a valid ref"), refname);
|
||||
|
||||
obj_type = oid_object_info(r, &object, NULL);
|
||||
repl_type = oid_object_info(r, oid, NULL);
|
||||
obj_type = oid_object_info(data->repo, &object, NULL);
|
||||
repl_type = oid_object_info(data->repo, oid, NULL);
|
||||
|
||||
printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type),
|
||||
oid_to_hex(oid), type_name(repl_type));
|
||||
|
@ -80,6 +81,7 @@ static int list_replace_refs(const char *pattern, const char *format)
|
|||
{
|
||||
struct show_data data;
|
||||
|
||||
data.repo = the_repository;
|
||||
if (!pattern)
|
||||
pattern = "*";
|
||||
data.pattern = pattern;
|
||||
|
@ -99,7 +101,8 @@ static int list_replace_refs(const char *pattern, const char *format)
|
|||
"valid formats are 'short', 'medium' and 'long'"),
|
||||
format);
|
||||
|
||||
for_each_replace_ref(the_repository, show_reference, (void *)&data);
|
||||
refs_for_each_replace_ref(get_main_ref_store(the_repository),
|
||||
show_reference, (void *)&data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ static void show_one(const struct show_one_options *opts,
|
|||
if (!opts->deref_tags)
|
||||
return;
|
||||
|
||||
if (!peel_iterated_oid(oid, &peeled)) {
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled)) {
|
||||
hex = repo_find_unique_abbrev(the_repository, &peeled, opts->abbrev);
|
||||
printf("%s %s^{}\n", hex, refname);
|
||||
}
|
||||
|
|
|
@ -679,7 +679,8 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
|
|||
displaypath);
|
||||
} else if (!(flags & OPT_CACHED)) {
|
||||
struct object_id oid;
|
||||
struct ref_store *refs = get_submodule_ref_store(path);
|
||||
struct ref_store *refs = repo_get_submodule_ref_store(the_repository,
|
||||
path);
|
||||
|
||||
if (!refs) {
|
||||
print_status(flags, '-', path, ce_oid, displaypath);
|
||||
|
@ -903,7 +904,8 @@ static void generate_submodule_summary(struct summary_cb *info,
|
|||
|
||||
if (!info->cached && oideq(&p->oid_dst, null_oid())) {
|
||||
if (S_ISGITLINK(p->mod_dst)) {
|
||||
struct ref_store *refs = get_submodule_ref_store(p->sm_path);
|
||||
struct ref_store *refs = repo_get_submodule_ref_store(the_repository,
|
||||
p->sm_path);
|
||||
|
||||
if (refs)
|
||||
refs_head_ref(refs, handle_submodule_head_ref, &p->oid_dst);
|
||||
|
@ -2598,7 +2600,8 @@ static int update_submodule(struct update_data *update_data)
|
|||
|
||||
if (update_data->just_cloned)
|
||||
oidcpy(&update_data->suboid, null_oid());
|
||||
else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid))
|
||||
else if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path,
|
||||
"HEAD", &update_data->suboid))
|
||||
return die_message(_("Unable to find current revision in submodule path '%s'"),
|
||||
update_data->displaypath);
|
||||
|
||||
|
@ -2625,7 +2628,8 @@ static int update_submodule(struct update_data *update_data)
|
|||
update_data->sm_path);
|
||||
}
|
||||
|
||||
if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid))
|
||||
if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path,
|
||||
remote_ref, &update_data->oid))
|
||||
return die_message(_("Unable to find %s revision in submodule path '%s'"),
|
||||
remote_ref, update_data->sm_path);
|
||||
|
||||
|
@ -3355,7 +3359,7 @@ static void die_on_repo_without_commits(const char *path)
|
|||
strbuf_addstr(&sb, path);
|
||||
if (is_nonbare_repository_dir(&sb)) {
|
||||
struct object_id oid;
|
||||
if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
|
||||
if (repo_resolve_gitlink_ref(the_repository, path, "HEAD", &oid) < 0)
|
||||
die(_("'%s' does not have a commit checked out"), path);
|
||||
}
|
||||
strbuf_release(&sb);
|
||||
|
|
|
@ -349,7 +349,8 @@ static int process_directory(const char *path, int len, struct stat *st)
|
|||
if (S_ISGITLINK(ce->ce_mode)) {
|
||||
|
||||
/* Do nothing to the index if there is no HEAD! */
|
||||
if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
|
||||
if (repo_resolve_gitlink_ref(the_repository, path,
|
||||
"HEAD", &oid) < 0)
|
||||
return 0;
|
||||
|
||||
return add_one_path(ce, path, len, st);
|
||||
|
@ -375,7 +376,7 @@ static int process_directory(const char *path, int len, struct stat *st)
|
|||
}
|
||||
|
||||
/* No match - should we add it as a gitlink? */
|
||||
if (!resolve_gitlink_ref(path, "HEAD", &oid))
|
||||
if (!repo_resolve_gitlink_ref(the_repository, path, "HEAD", &oid))
|
||||
return add_one_path(NULL, path, len, st);
|
||||
|
||||
/* Error out. */
|
||||
|
|
|
@ -46,7 +46,7 @@ static char *pager(int ident_flag UNUSED)
|
|||
|
||||
static char *default_branch(int ident_flag UNUSED)
|
||||
{
|
||||
return xstrdup_or_null(git_default_branch_name(1));
|
||||
return repo_default_branch_name(the_repository, 1);
|
||||
}
|
||||
|
||||
static char *shell_path(int ident_flag UNUSED)
|
||||
|
|
|
@ -509,7 +509,7 @@ static int add_worktree(const char *path, const char *refname,
|
|||
}
|
||||
wt_refs = get_worktree_ref_store(wt);
|
||||
|
||||
ret = refs_init_db(wt_refs, REFS_INIT_DB_IS_WORKTREE, &sb);
|
||||
ret = ref_store_create_on_disk(wt_refs, REF_STORE_CREATE_ON_DISK_IS_WORKTREE, &sb);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
|
|
@ -1066,7 +1066,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
|
|||
elem->mode = canon_mode(st.st_mode);
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
struct object_id oid;
|
||||
if (resolve_gitlink_ref(elem->path, "HEAD", &oid) < 0)
|
||||
if (repo_resolve_gitlink_ref(the_repository, elem->path,
|
||||
"HEAD", &oid) < 0)
|
||||
result = grab_blob(opt->repo, &elem->oid,
|
||||
elem->mode, &result_size,
|
||||
NULL, NULL);
|
||||
|
|
|
@ -1821,7 +1821,7 @@ static int add_ref_to_set(const char *refname UNUSED,
|
|||
struct object_id peeled;
|
||||
struct refs_cb_data *data = (struct refs_cb_data *)cb_data;
|
||||
|
||||
if (!peel_iterated_oid(oid, &peeled))
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled))
|
||||
oid = &peeled;
|
||||
if (oid_object_info(the_repository, oid, NULL) == OBJ_COMMIT)
|
||||
oidset_insert(data->commits, oid);
|
||||
|
|
|
@ -66,7 +66,8 @@ static int check_removed(const struct cache_entry *ce, struct stat *st)
|
|||
* a directory --- the blob was removed!
|
||||
*/
|
||||
if (!S_ISGITLINK(ce->ce_mode) &&
|
||||
resolve_gitlink_ref(ce->name, "HEAD", &sub))
|
||||
repo_resolve_gitlink_ref(the_repository, ce->name,
|
||||
"HEAD", &sub))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
3
dir.c
3
dir.c
|
@ -3318,7 +3318,8 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
|
|||
struct object_id submodule_head;
|
||||
|
||||
if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
|
||||
!resolve_gitlink_ref(path->buf, "HEAD", &submodule_head)) {
|
||||
!repo_resolve_gitlink_ref(the_repository, path->buf,
|
||||
"HEAD", &submodule_head)) {
|
||||
/* Do not descend and nuke a nested git work tree. */
|
||||
if (kept_up)
|
||||
*kept_up = 1;
|
||||
|
|
|
@ -110,7 +110,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
|
|||
|
||||
if (data->peel && oid) {
|
||||
struct object_id peeled;
|
||||
if (!peel_iterated_oid(oid, &peeled))
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled))
|
||||
strbuf_addf(&data->buf, " peeled:%s", oid_to_hex(&peeled));
|
||||
}
|
||||
|
||||
|
|
|
@ -664,7 +664,7 @@ static int add_ref_to_pending(const char *refname,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!peel_iterated_oid(oid, &peeled))
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled))
|
||||
oid = &peeled;
|
||||
|
||||
object = parse_object_or_die(oid, refname);
|
||||
|
|
|
@ -2669,7 +2669,7 @@ int index_path(struct index_state *istate, struct object_id *oid,
|
|||
strbuf_release(&sb);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
return resolve_gitlink_ref(path, "HEAD", oid);
|
||||
return repo_resolve_gitlink_ref(the_repository, path, "HEAD", oid);
|
||||
default:
|
||||
return error(_("%s: unsupported file type"), path);
|
||||
}
|
||||
|
|
23
object.c
23
object.c
|
@ -207,6 +207,29 @@ struct object *lookup_object_by_type(struct repository *r,
|
|||
}
|
||||
}
|
||||
|
||||
enum peel_status peel_object(struct repository *r,
|
||||
const struct object_id *name,
|
||||
struct object_id *oid)
|
||||
{
|
||||
struct object *o = lookup_unknown_object(r, name);
|
||||
|
||||
if (o->type == OBJ_NONE) {
|
||||
int type = oid_object_info(r, name, NULL);
|
||||
if (type < 0 || !object_as_type(o, type, 0))
|
||||
return PEEL_INVALID;
|
||||
}
|
||||
|
||||
if (o->type != OBJ_TAG)
|
||||
return PEEL_NON_TAG;
|
||||
|
||||
o = deref_tag_noverify(r, o);
|
||||
if (!o)
|
||||
return PEEL_INVALID;
|
||||
|
||||
oidcpy(oid, &o->oid);
|
||||
return PEEL_PEELED;
|
||||
}
|
||||
|
||||
struct object *parse_object_buffer(struct repository *r, const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p)
|
||||
{
|
||||
struct object *obj;
|
||||
|
|
35
object.h
35
object.h
|
@ -257,6 +257,41 @@ struct object *lookup_unknown_object(struct repository *r, const struct object_i
|
|||
struct object *lookup_object_by_type(struct repository *r, const struct object_id *oid,
|
||||
enum object_type type);
|
||||
|
||||
enum peel_status {
|
||||
/* object was peeled successfully: */
|
||||
PEEL_PEELED = 0,
|
||||
|
||||
/*
|
||||
* object cannot be peeled because the named object (or an
|
||||
* object referred to by a tag in the peel chain), does not
|
||||
* exist.
|
||||
*/
|
||||
PEEL_INVALID = -1,
|
||||
|
||||
/* object cannot be peeled because it is not a tag: */
|
||||
PEEL_NON_TAG = -2,
|
||||
|
||||
/* ref_entry contains no peeled value because it is a symref: */
|
||||
PEEL_IS_SYMREF = -3,
|
||||
|
||||
/*
|
||||
* ref_entry cannot be peeled because it is broken (i.e., the
|
||||
* symbolic reference cannot even be resolved to an object
|
||||
* name):
|
||||
*/
|
||||
PEEL_BROKEN = -4
|
||||
};
|
||||
|
||||
/*
|
||||
* Peel the named object; i.e., if the object is a tag, resolve the
|
||||
* tag recursively until a non-tag is found. If successful, store the
|
||||
* result to oid and return PEEL_PEELED. If the object is not a tag
|
||||
* or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively,
|
||||
* and leave oid unchanged.
|
||||
*/
|
||||
enum peel_status peel_object(struct repository *r,
|
||||
const struct object_id *name, struct object_id *oid);
|
||||
|
||||
struct object_list *object_list_insert(struct object *item,
|
||||
struct object_list **list_p);
|
||||
|
||||
|
|
|
@ -271,7 +271,8 @@ static int ce_compare_gitlink(const struct cache_entry *ce)
|
|||
*
|
||||
* If so, we consider it always to match.
|
||||
*/
|
||||
if (resolve_gitlink_ref(ce->name, "HEAD", &oid) < 0)
|
||||
if (repo_resolve_gitlink_ref(the_repository, ce->name,
|
||||
"HEAD", &oid) < 0)
|
||||
return 0;
|
||||
return !oideq(&oid, &ce->oid);
|
||||
}
|
||||
|
@ -711,7 +712,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
|
|||
|
||||
namelen = strlen(path);
|
||||
if (S_ISDIR(st_mode)) {
|
||||
if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
|
||||
if (repo_resolve_gitlink_ref(the_repository, path, "HEAD", &oid) < 0)
|
||||
return error(_("'%s' does not have a commit checked out"), path);
|
||||
while (namelen && path[namelen-1] == '/')
|
||||
namelen--;
|
||||
|
|
|
@ -2520,7 +2520,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
|||
* If it is a tag object, see if we use the peeled value. If we do,
|
||||
* grab the peeled OID.
|
||||
*/
|
||||
if (need_tagged && peel_iterated_oid(&obj->oid, &oi_deref.oid))
|
||||
if (need_tagged && peel_iterated_oid(the_repository, &obj->oid, &oi_deref.oid))
|
||||
die("bad tag");
|
||||
|
||||
return get_object(ref, 1, &obj, &oi_deref, err);
|
||||
|
|
|
@ -191,7 +191,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
|
|||
reflogs = read_complete_reflog(branch);
|
||||
if (!reflogs || reflogs->nr == 0) {
|
||||
char *b;
|
||||
int ret = dwim_log(branch, strlen(branch),
|
||||
int ret = repo_dwim_log(the_repository, branch, strlen(branch),
|
||||
NULL, &b);
|
||||
if (ret > 1)
|
||||
free(b);
|
||||
|
|
2
reflog.c
2
reflog.c
|
@ -409,7 +409,7 @@ int reflog_delete(const char *rev, enum expire_reflog_flags flags, int verbose)
|
|||
if (!spec)
|
||||
return error(_("not a reflog: %s"), rev);
|
||||
|
||||
if (!dwim_log(rev, spec - rev, NULL, &ref)) {
|
||||
if (!repo_dwim_log(the_repository, rev, spec - rev, NULL, &ref)) {
|
||||
status |= error(_("no reflog for '%s'"), rev);
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
260
refs.c
260
refs.c
|
@ -6,7 +6,7 @@
|
|||
#include "advice.h"
|
||||
#include "config.h"
|
||||
#include "environment.h"
|
||||
#include "hashmap.h"
|
||||
#include "strmap.h"
|
||||
#include "gettext.h"
|
||||
#include "hex.h"
|
||||
#include "lockfile.h"
|
||||
|
@ -19,7 +19,6 @@
|
|||
#include "object-store-ll.h"
|
||||
#include "object.h"
|
||||
#include "path.h"
|
||||
#include "tag.h"
|
||||
#include "submodule.h"
|
||||
#include "worktree.h"
|
||||
#include "strvec.h"
|
||||
|
@ -425,28 +424,8 @@ static int for_each_filter_refs(const char *refname,
|
|||
return filter->fn(refname, oid, flags, filter->cb_data);
|
||||
}
|
||||
|
||||
enum peel_status peel_object(const struct object_id *name, struct object_id *oid)
|
||||
{
|
||||
struct object *o = lookup_unknown_object(the_repository, name);
|
||||
|
||||
if (o->type == OBJ_NONE) {
|
||||
int type = oid_object_info(the_repository, name, NULL);
|
||||
if (type < 0 || !object_as_type(o, type, 0))
|
||||
return PEEL_INVALID;
|
||||
}
|
||||
|
||||
if (o->type != OBJ_TAG)
|
||||
return PEEL_NON_TAG;
|
||||
|
||||
o = deref_tag_noverify(o);
|
||||
if (!o)
|
||||
return PEEL_INVALID;
|
||||
|
||||
oidcpy(oid, &o->oid);
|
||||
return PEEL_PEELED;
|
||||
}
|
||||
|
||||
struct warn_if_dangling_data {
|
||||
struct ref_store *refs;
|
||||
FILE *fp;
|
||||
const char *refname;
|
||||
const struct string_list *refnames;
|
||||
|
@ -463,8 +442,7 @@ static int warn_if_dangling_symref(const char *refname,
|
|||
if (!(flags & REF_ISSYMREF))
|
||||
return 0;
|
||||
|
||||
resolves_to = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
|
||||
refname, 0, NULL, NULL);
|
||||
resolves_to = refs_resolve_ref_unsafe(d->refs, refname, 0, NULL, NULL);
|
||||
if (!resolves_to
|
||||
|| (d->refname
|
||||
? strcmp(resolves_to, d->refname)
|
||||
|
@ -477,28 +455,28 @@ static int warn_if_dangling_symref(const char *refname,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
|
||||
void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp,
|
||||
const char *msg_fmt, const char *refname)
|
||||
{
|
||||
struct warn_if_dangling_data data;
|
||||
|
||||
data.fp = fp;
|
||||
data.refname = refname;
|
||||
data.refnames = NULL;
|
||||
data.msg_fmt = msg_fmt;
|
||||
refs_for_each_rawref(get_main_ref_store(the_repository),
|
||||
warn_if_dangling_symref, &data);
|
||||
struct warn_if_dangling_data data = {
|
||||
.refs = refs,
|
||||
.fp = fp,
|
||||
.refname = refname,
|
||||
.msg_fmt = msg_fmt,
|
||||
};
|
||||
refs_for_each_rawref(refs, warn_if_dangling_symref, &data);
|
||||
}
|
||||
|
||||
void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
|
||||
void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp,
|
||||
const char *msg_fmt, const struct string_list *refnames)
|
||||
{
|
||||
struct warn_if_dangling_data data;
|
||||
|
||||
data.fp = fp;
|
||||
data.refname = NULL;
|
||||
data.refnames = refnames;
|
||||
data.msg_fmt = msg_fmt;
|
||||
refs_for_each_rawref(get_main_ref_store(the_repository),
|
||||
warn_if_dangling_symref, &data);
|
||||
struct warn_if_dangling_data data = {
|
||||
.refs = refs,
|
||||
.fp = fp,
|
||||
.refnames = refnames,
|
||||
.msg_fmt = msg_fmt,
|
||||
};
|
||||
refs_for_each_rawref(refs, warn_if_dangling_symref, &data);
|
||||
}
|
||||
|
||||
int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
|
@ -686,16 +664,6 @@ char *repo_default_branch_name(struct repository *r, int quiet)
|
|||
return ret;
|
||||
}
|
||||
|
||||
const char *git_default_branch_name(int quiet)
|
||||
{
|
||||
static char *ret;
|
||||
|
||||
if (!ret)
|
||||
ret = repo_default_branch_name(the_repository, quiet);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* *string and *len will only be substituted, and *string returned (for
|
||||
* later free()ing) if the string passed in is a magic short-hand form
|
||||
|
@ -807,11 +775,6 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
|
|||
return logs_found;
|
||||
}
|
||||
|
||||
int dwim_log(const char *str, int len, struct object_id *oid, char **log)
|
||||
{
|
||||
return repo_dwim_log(the_repository, str, len, oid, log);
|
||||
}
|
||||
|
||||
int is_per_worktree_ref(const char *refname)
|
||||
{
|
||||
return starts_with(refname, "refs/worktree/") ||
|
||||
|
@ -1597,53 +1560,12 @@ struct ref_iterator *refs_ref_iterator_begin(
|
|||
return iter;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call fn for each reference in the specified submodule for which the
|
||||
* refname begins with prefix. If trim is non-zero, then trim that
|
||||
* many characters off the beginning of each refname before passing
|
||||
* the refname to fn. flags can be DO_FOR_EACH_INCLUDE_BROKEN to
|
||||
* include broken references in the iteration. If fn ever returns a
|
||||
* non-zero value, stop the iteration and return that value;
|
||||
* otherwise, return 0.
|
||||
*/
|
||||
static int do_for_each_repo_ref(struct repository *r, const char *prefix,
|
||||
each_repo_ref_fn fn, int trim, int flags,
|
||||
void *cb_data)
|
||||
{
|
||||
struct ref_iterator *iter;
|
||||
struct ref_store *refs = get_main_ref_store(r);
|
||||
|
||||
if (!refs)
|
||||
return 0;
|
||||
|
||||
iter = refs_ref_iterator_begin(refs, prefix, NULL, trim, flags);
|
||||
|
||||
return do_for_each_repo_ref_iterator(r, iter, fn, cb_data);
|
||||
}
|
||||
|
||||
struct do_for_each_ref_help {
|
||||
each_ref_fn *fn;
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
static int do_for_each_ref_helper(struct repository *r UNUSED,
|
||||
const char *refname,
|
||||
const struct object_id *oid,
|
||||
int flags,
|
||||
void *cb_data)
|
||||
{
|
||||
struct do_for_each_ref_help *hp = cb_data;
|
||||
|
||||
return hp->fn(refname, oid, flags, hp->cb_data);
|
||||
}
|
||||
|
||||
static int do_for_each_ref(struct ref_store *refs, const char *prefix,
|
||||
const char **exclude_patterns,
|
||||
each_ref_fn fn, int trim,
|
||||
enum do_for_each_ref_flags flags, void *cb_data)
|
||||
{
|
||||
struct ref_iterator *iter;
|
||||
struct do_for_each_ref_help hp = { fn, cb_data };
|
||||
|
||||
if (!refs)
|
||||
return 0;
|
||||
|
@ -1651,8 +1573,7 @@ static int do_for_each_ref(struct ref_store *refs, const char *prefix,
|
|||
iter = refs_ref_iterator_begin(refs, prefix, exclude_patterns, trim,
|
||||
flags);
|
||||
|
||||
return do_for_each_repo_ref_iterator(the_repository, iter,
|
||||
do_for_each_ref_helper, &hp);
|
||||
return do_for_each_ref_iterator(iter, fn, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
|
@ -1673,10 +1594,10 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
|
|||
return do_for_each_ref(refs, prefix, exclude_patterns, fn, 0, 0, cb_data);
|
||||
}
|
||||
|
||||
int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_replace_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
|
||||
return do_for_each_repo_ref(r, git_replace_ref_base, fn,
|
||||
return do_for_each_ref(refs, git_replace_ref_base, NULL, fn,
|
||||
strlen(git_replace_ref_base),
|
||||
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
|
||||
}
|
||||
|
@ -1928,19 +1849,19 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
|
|||
}
|
||||
|
||||
/* backend functions */
|
||||
int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err)
|
||||
int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *err)
|
||||
{
|
||||
return refs->be->init_db(refs, flags, err);
|
||||
return refs->be->create_on_disk(refs, flags, err);
|
||||
}
|
||||
|
||||
int resolve_gitlink_ref(const char *submodule, const char *refname,
|
||||
int repo_resolve_gitlink_ref(struct repository *r,
|
||||
const char *submodule, const char *refname,
|
||||
struct object_id *oid)
|
||||
{
|
||||
struct ref_store *refs;
|
||||
int flags;
|
||||
|
||||
refs = get_submodule_ref_store(submodule);
|
||||
|
||||
refs = repo_get_submodule_ref_store(r, submodule);
|
||||
if (!refs)
|
||||
return -1;
|
||||
|
||||
|
@ -1950,66 +1871,21 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct ref_store_hash_entry
|
||||
{
|
||||
struct hashmap_entry ent;
|
||||
|
||||
struct ref_store *refs;
|
||||
|
||||
/* NUL-terminated identifier of the ref store: */
|
||||
char name[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
static int ref_store_hash_cmp(const void *cmp_data UNUSED,
|
||||
const struct hashmap_entry *eptr,
|
||||
const struct hashmap_entry *entry_or_key,
|
||||
const void *keydata)
|
||||
{
|
||||
const struct ref_store_hash_entry *e1, *e2;
|
||||
const char *name;
|
||||
|
||||
e1 = container_of(eptr, const struct ref_store_hash_entry, ent);
|
||||
e2 = container_of(entry_or_key, const struct ref_store_hash_entry, ent);
|
||||
name = keydata ? keydata : e2->name;
|
||||
|
||||
return strcmp(e1->name, name);
|
||||
}
|
||||
|
||||
static struct ref_store_hash_entry *alloc_ref_store_hash_entry(
|
||||
const char *name, struct ref_store *refs)
|
||||
{
|
||||
struct ref_store_hash_entry *entry;
|
||||
|
||||
FLEX_ALLOC_STR(entry, name, name);
|
||||
hashmap_entry_init(&entry->ent, strhash(name));
|
||||
entry->refs = refs;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* A hashmap of ref_stores, stored by submodule name: */
|
||||
static struct hashmap submodule_ref_stores;
|
||||
|
||||
/* A hashmap of ref_stores, stored by worktree id: */
|
||||
static struct hashmap worktree_ref_stores;
|
||||
|
||||
/*
|
||||
* Look up a ref store by name. If that ref_store hasn't been
|
||||
* registered yet, return NULL.
|
||||
*/
|
||||
static struct ref_store *lookup_ref_store_map(struct hashmap *map,
|
||||
static struct ref_store *lookup_ref_store_map(struct strmap *map,
|
||||
const char *name)
|
||||
{
|
||||
struct ref_store_hash_entry *entry;
|
||||
unsigned int hash;
|
||||
struct strmap_entry *entry;
|
||||
|
||||
if (!map->tablesize)
|
||||
if (!map->map.tablesize)
|
||||
/* It's initialized on demand in register_ref_store(). */
|
||||
return NULL;
|
||||
|
||||
hash = strhash(name);
|
||||
entry = hashmap_get_entry_from_hash(map, hash, name,
|
||||
struct ref_store_hash_entry, ent);
|
||||
return entry ? entry->refs : NULL;
|
||||
entry = strmap_get_entry(map, name);
|
||||
return entry ? entry->value : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2031,6 +1907,12 @@ static struct ref_store *ref_store_init(struct repository *repo,
|
|||
return refs;
|
||||
}
|
||||
|
||||
void ref_store_release(struct ref_store *ref_store)
|
||||
{
|
||||
ref_store->be->release(ref_store);
|
||||
free(ref_store->gitdir);
|
||||
}
|
||||
|
||||
struct ref_store *get_main_ref_store(struct repository *r)
|
||||
{
|
||||
if (r->refs_private)
|
||||
|
@ -2048,22 +1930,19 @@ struct ref_store *get_main_ref_store(struct repository *r)
|
|||
* Associate a ref store with a name. It is a fatal error to call this
|
||||
* function twice for the same name.
|
||||
*/
|
||||
static void register_ref_store_map(struct hashmap *map,
|
||||
static void register_ref_store_map(struct strmap *map,
|
||||
const char *type,
|
||||
struct ref_store *refs,
|
||||
const char *name)
|
||||
{
|
||||
struct ref_store_hash_entry *entry;
|
||||
|
||||
if (!map->tablesize)
|
||||
hashmap_init(map, ref_store_hash_cmp, NULL, 0);
|
||||
|
||||
entry = alloc_ref_store_hash_entry(name, refs);
|
||||
if (hashmap_put(map, &entry->ent))
|
||||
if (!map->map.tablesize)
|
||||
strmap_init(map);
|
||||
if (strmap_put(map, name, refs))
|
||||
BUG("%s ref_store '%s' initialized twice", type, name);
|
||||
}
|
||||
|
||||
struct ref_store *get_submodule_ref_store(const char *submodule)
|
||||
struct ref_store *repo_get_submodule_ref_store(struct repository *repo,
|
||||
const char *submodule)
|
||||
{
|
||||
struct strbuf submodule_sb = STRBUF_INIT;
|
||||
struct ref_store *refs;
|
||||
|
@ -2084,7 +1963,7 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
|
|||
/* We need to strip off one or more trailing slashes */
|
||||
submodule = to_free = xmemdupz(submodule, len);
|
||||
|
||||
refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
|
||||
refs = lookup_ref_store_map(&repo->submodule_ref_stores, submodule);
|
||||
if (refs)
|
||||
goto done;
|
||||
|
||||
|
@ -2096,20 +1975,15 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
|
|||
goto done;
|
||||
|
||||
subrepo = xmalloc(sizeof(*subrepo));
|
||||
/*
|
||||
* NEEDSWORK: Make get_submodule_ref_store() work with arbitrary
|
||||
* superprojects other than the_repository. This probably should be
|
||||
* done by making it take a struct repository * parameter instead of a
|
||||
* submodule path.
|
||||
*/
|
||||
if (repo_submodule_init(subrepo, the_repository, submodule,
|
||||
|
||||
if (repo_submodule_init(subrepo, repo, submodule,
|
||||
null_oid())) {
|
||||
free(subrepo);
|
||||
goto done;
|
||||
}
|
||||
refs = ref_store_init(subrepo, submodule_sb.buf,
|
||||
REF_STORE_READ | REF_STORE_ODB);
|
||||
register_ref_store_map(&submodule_ref_stores, "submodule",
|
||||
register_ref_store_map(&repo->submodule_ref_stores, "submodule",
|
||||
refs, submodule);
|
||||
|
||||
done:
|
||||
|
@ -2125,25 +1999,29 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt)
|
|||
const char *id;
|
||||
|
||||
if (wt->is_current)
|
||||
return get_main_ref_store(the_repository);
|
||||
return get_main_ref_store(wt->repo);
|
||||
|
||||
id = wt->id ? wt->id : "/";
|
||||
refs = lookup_ref_store_map(&worktree_ref_stores, id);
|
||||
refs = lookup_ref_store_map(&wt->repo->worktree_ref_stores, id);
|
||||
if (refs)
|
||||
return refs;
|
||||
|
||||
if (wt->id)
|
||||
refs = ref_store_init(the_repository,
|
||||
git_common_path("worktrees/%s", wt->id),
|
||||
if (wt->id) {
|
||||
struct strbuf common_path = STRBUF_INIT;
|
||||
strbuf_git_common_path(&common_path, wt->repo,
|
||||
"worktrees/%s", wt->id);
|
||||
refs = ref_store_init(wt->repo, common_path.buf,
|
||||
REF_STORE_ALL_CAPS);
|
||||
else
|
||||
refs = ref_store_init(the_repository,
|
||||
get_git_common_dir(),
|
||||
strbuf_release(&common_path);
|
||||
} else {
|
||||
refs = ref_store_init(wt->repo, wt->repo->commondir,
|
||||
REF_STORE_ALL_CAPS);
|
||||
}
|
||||
|
||||
if (refs)
|
||||
register_ref_store_map(&worktree_ref_stores, "worktree",
|
||||
refs, id);
|
||||
register_ref_store_map(&wt->repo->worktree_ref_stores,
|
||||
"worktree", refs, id);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
|
@ -2161,14 +2039,14 @@ int refs_pack_refs(struct ref_store *refs, struct pack_refs_opts *opts)
|
|||
return refs->be->pack_refs(refs, opts);
|
||||
}
|
||||
|
||||
int peel_iterated_oid(const struct object_id *base, struct object_id *peeled)
|
||||
int peel_iterated_oid(struct repository *r, const struct object_id *base, struct object_id *peeled)
|
||||
{
|
||||
if (current_ref_iter &&
|
||||
(current_ref_iter->oid == base ||
|
||||
oideq(current_ref_iter->oid, base)))
|
||||
return ref_iterator_peel(current_ref_iter, peeled);
|
||||
|
||||
return peel_object(base, peeled) ? -1 : 0;
|
||||
return peel_object(r, base, peeled) ? -1 : 0;
|
||||
}
|
||||
|
||||
int refs_update_symref(struct ref_store *refs, const char *ref,
|
||||
|
@ -2478,8 +2356,7 @@ struct do_for_each_reflog_help {
|
|||
void *cb_data;
|
||||
};
|
||||
|
||||
static int do_for_each_reflog_helper(struct repository *r UNUSED,
|
||||
const char *refname,
|
||||
static int do_for_each_reflog_helper(const char *refname,
|
||||
const struct object_id *oid UNUSED,
|
||||
int flags,
|
||||
void *cb_data)
|
||||
|
@ -2495,8 +2372,7 @@ int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_dat
|
|||
|
||||
iter = refs->be->reflog_iterator_begin(refs);
|
||||
|
||||
return do_for_each_repo_ref_iterator(the_repository, iter,
|
||||
do_for_each_reflog_helper, &hp);
|
||||
return do_for_each_ref_iterator(iter, do_for_each_reflog_helper, &hp);
|
||||
}
|
||||
|
||||
int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
|
||||
|
|
49
refs.h
49
refs.h
|
@ -114,21 +114,27 @@ int should_autocreate_reflog(const char *refname);
|
|||
|
||||
int is_branch(const char *refname);
|
||||
|
||||
#define REFS_INIT_DB_IS_WORKTREE (1 << 0)
|
||||
#define REF_STORE_CREATE_ON_DISK_IS_WORKTREE (1 << 0)
|
||||
|
||||
int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err);
|
||||
int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *err);
|
||||
|
||||
/*
|
||||
* Release all memory and resources associated with the ref store.
|
||||
*/
|
||||
void ref_store_release(struct ref_store *ref_store);
|
||||
|
||||
/*
|
||||
* Return the peeled value of the oid currently being iterated via
|
||||
* for_each_ref(), etc. This is equivalent to calling:
|
||||
*
|
||||
* peel_object(oid, &peeled);
|
||||
* peel_object(r, oid, &peeled);
|
||||
*
|
||||
* with the "oid" value given to the each_ref_fn callback, except
|
||||
* that some ref storage may be able to answer the query without
|
||||
* actually loading the object in memory.
|
||||
*/
|
||||
int peel_iterated_oid(const struct object_id *base, struct object_id *peeled);
|
||||
int peel_iterated_oid(struct repository *r,
|
||||
const struct object_id *base, struct object_id *peeled);
|
||||
|
||||
/**
|
||||
* Resolve refname in the nested "gitlink" repository in the specified
|
||||
|
@ -136,7 +142,8 @@ int peel_iterated_oid(const struct object_id *base, struct object_id *peeled);
|
|||
* successful, return 0 and set oid to the name of the object;
|
||||
* otherwise, return a non-zero value.
|
||||
*/
|
||||
int resolve_gitlink_ref(const char *submodule, const char *refname,
|
||||
int repo_resolve_gitlink_ref(struct repository *r,
|
||||
const char *submodule, const char *refname,
|
||||
struct object_id *oid);
|
||||
|
||||
/*
|
||||
|
@ -157,15 +164,12 @@ int expand_ref(struct repository *r, const char *str, int len, struct object_id
|
|||
int repo_dwim_ref(struct repository *r, const char *str, int len,
|
||||
struct object_id *oid, char **ref, int nonfatal_dangling_mark);
|
||||
int repo_dwim_log(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
|
||||
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
|
||||
|
||||
/*
|
||||
* Retrieves the default branch name for newly-initialized repositories.
|
||||
*
|
||||
* The return value of `repo_default_branch_name()` is an allocated string. The
|
||||
* return value of `git_default_branch_name()` is a singleton.
|
||||
* The return value is an allocated string.
|
||||
*/
|
||||
const char *git_default_branch_name(int quiet);
|
||||
char *repo_default_branch_name(struct repository *r, int quiet);
|
||||
|
||||
/*
|
||||
|
@ -292,16 +296,6 @@ struct ref_transaction;
|
|||
typedef int each_ref_fn(const char *refname,
|
||||
const struct object_id *oid, int flags, void *cb_data);
|
||||
|
||||
/*
|
||||
* The same as each_ref_fn, but also with a repository argument that
|
||||
* contains the repository associated with the callback.
|
||||
*/
|
||||
typedef int each_repo_ref_fn(struct repository *r,
|
||||
const char *refname,
|
||||
const struct object_id *oid,
|
||||
int flags,
|
||||
void *cb_data);
|
||||
|
||||
/*
|
||||
* The following functions invoke the specified callback function for
|
||||
* each reference indicated. If the function ever returns a nonzero
|
||||
|
@ -323,6 +317,8 @@ int refs_for_each_branch_ref(struct ref_store *refs,
|
|||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_remote_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_replace_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
/*
|
||||
* references matching any pattern in "exclude_patterns" are omitted from the
|
||||
|
@ -347,11 +343,6 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *refs,
|
|||
const char **exclude_patterns,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
/**
|
||||
* iterate refs from the respective area.
|
||||
*/
|
||||
int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data);
|
||||
|
||||
/* iterates all refs that match the specified glob pattern. */
|
||||
int refs_for_each_glob_ref(struct ref_store *refs, each_ref_fn fn,
|
||||
const char *pattern, void *cb_data);
|
||||
|
@ -395,9 +386,10 @@ static inline const char *has_glob_specials(const char *pattern)
|
|||
return strpbrk(pattern, "?*[");
|
||||
}
|
||||
|
||||
void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname);
|
||||
void warn_dangling_symrefs(FILE *fp, const char *msg_fmt,
|
||||
const struct string_list *refnames);
|
||||
void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp,
|
||||
const char *msg_fmt, const char *refname);
|
||||
void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp,
|
||||
const char *msg_fmt, const struct string_list *refnames);
|
||||
|
||||
/*
|
||||
* Flags for controlling behaviour of pack_refs()
|
||||
|
@ -965,7 +957,8 @@ struct ref_store *get_main_ref_store(struct repository *r);
|
|||
* For backwards compatibility, submodule=="" is treated the same as
|
||||
* submodule==NULL.
|
||||
*/
|
||||
struct ref_store *get_submodule_ref_store(const char *submodule);
|
||||
struct ref_store *repo_get_submodule_ref_store(struct repository *repo,
|
||||
const char *submodule);
|
||||
struct ref_store *get_worktree_ref_store(const struct worktree *wt);
|
||||
|
||||
/*
|
||||
|
|
16
refs/debug.c
16
refs/debug.c
|
@ -33,11 +33,18 @@ struct ref_store *maybe_debug_wrap_ref_store(const char *gitdir, struct ref_stor
|
|||
return (struct ref_store *)res;
|
||||
}
|
||||
|
||||
static int debug_init_db(struct ref_store *refs, int flags, struct strbuf *err)
|
||||
static void debug_release(struct ref_store *refs)
|
||||
{
|
||||
struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
|
||||
int res = drefs->refs->be->init_db(drefs->refs, flags, err);
|
||||
trace_printf_key(&trace_refs, "init_db: %d\n", res);
|
||||
drefs->refs->be->release(drefs->refs);
|
||||
trace_printf_key(&trace_refs, "release\n");
|
||||
}
|
||||
|
||||
static int debug_create_on_disk(struct ref_store *refs, int flags, struct strbuf *err)
|
||||
{
|
||||
struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
|
||||
int res = drefs->refs->be->create_on_disk(drefs->refs, flags, err);
|
||||
trace_printf_key(&trace_refs, "create_on_disk: %d\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -415,7 +422,8 @@ static int debug_reflog_expire(struct ref_store *ref_store, const char *refname,
|
|||
struct ref_storage_be refs_be_debug = {
|
||||
.name = "debug",
|
||||
.init = NULL,
|
||||
.init_db = debug_init_db,
|
||||
.release = debug_release,
|
||||
.create_on_disk = debug_create_on_disk,
|
||||
|
||||
/*
|
||||
* None of these should be NULL. If the "files" backend (in
|
||||
|
|
|
@ -89,7 +89,7 @@ static void clear_loose_ref_cache(struct files_ref_store *refs)
|
|||
* Create a new submodule ref cache and add it to the internal
|
||||
* set of caches.
|
||||
*/
|
||||
static struct ref_store *files_ref_store_create(struct repository *repo,
|
||||
static struct ref_store *files_ref_store_init(struct repository *repo,
|
||||
const char *gitdir,
|
||||
unsigned int flags)
|
||||
{
|
||||
|
@ -102,7 +102,7 @@ static struct ref_store *files_ref_store_create(struct repository *repo,
|
|||
get_common_dir_noenv(&sb, gitdir);
|
||||
refs->gitcommondir = strbuf_detach(&sb, NULL);
|
||||
refs->packed_ref_store =
|
||||
packed_ref_store_create(repo, refs->gitcommondir, flags);
|
||||
packed_ref_store_init(repo, refs->gitcommondir, flags);
|
||||
|
||||
chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
|
||||
chdir_notify_reparent("files-backend $GIT_COMMONDIR",
|
||||
|
@ -149,6 +149,14 @@ static struct files_ref_store *files_downcast(struct ref_store *ref_store,
|
|||
return refs;
|
||||
}
|
||||
|
||||
static void files_ref_store_release(struct ref_store *ref_store)
|
||||
{
|
||||
struct files_ref_store *refs = files_downcast(ref_store, 0, "release");
|
||||
free_ref_cache(refs->loose);
|
||||
free(refs->gitcommondir);
|
||||
ref_store_release(refs->packed_ref_store);
|
||||
}
|
||||
|
||||
static void files_reflog_path(struct files_ref_store *refs,
|
||||
struct strbuf *sb,
|
||||
const char *refname)
|
||||
|
@ -1230,7 +1238,8 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_
|
|||
/*
|
||||
* Return true if the specified reference should be packed.
|
||||
*/
|
||||
static int should_pack_ref(const char *refname,
|
||||
static int should_pack_ref(struct files_ref_store *refs,
|
||||
const char *refname,
|
||||
const struct object_id *oid, unsigned int ref_flags,
|
||||
struct pack_refs_opts *opts)
|
||||
{
|
||||
|
@ -1246,7 +1255,7 @@ static int should_pack_ref(const char *refname,
|
|||
return 0;
|
||||
|
||||
/* Do not pack broken refs: */
|
||||
if (!ref_resolves_to_object(refname, the_repository, oid, ref_flags))
|
||||
if (!ref_resolves_to_object(refname, refs->base.repo, oid, ref_flags))
|
||||
return 0;
|
||||
|
||||
if (ref_excluded(opts->exclusions, refname))
|
||||
|
@ -1278,14 +1287,14 @@ static int files_pack_refs(struct ref_store *ref_store,
|
|||
packed_refs_lock(refs->packed_ref_store, LOCK_DIE_ON_ERROR, &err);
|
||||
|
||||
iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, 0), NULL,
|
||||
the_repository, 0);
|
||||
refs->base.repo, 0);
|
||||
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
|
||||
/*
|
||||
* If the loose reference can be packed, add an entry
|
||||
* in the packed ref cache. If the reference should be
|
||||
* pruned, also add it to refs_to_prune.
|
||||
*/
|
||||
if (!should_pack_ref(iter->refname, iter->oid, iter->flags, opts))
|
||||
if (!should_pack_ref(refs, iter->refname, iter->oid, iter->flags, opts))
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
@ -1382,7 +1391,8 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int write_ref_to_lockfile(struct ref_lock *lock,
|
||||
static int write_ref_to_lockfile(struct files_ref_store *refs,
|
||||
struct ref_lock *lock,
|
||||
const struct object_id *oid,
|
||||
int skip_oid_verification, struct strbuf *err);
|
||||
static int commit_ref_update(struct files_ref_store *refs,
|
||||
|
@ -1530,7 +1540,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
|
|||
}
|
||||
oidcpy(&lock->old_oid, &orig_oid);
|
||||
|
||||
if (write_ref_to_lockfile(lock, &orig_oid, 0, &err) ||
|
||||
if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||
|
||||
commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) {
|
||||
error("unable to write current sha1 into %s: %s", newrefname, err.buf);
|
||||
strbuf_release(&err);
|
||||
|
@ -1550,7 +1560,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
|
|||
|
||||
flag = log_all_ref_updates;
|
||||
log_all_ref_updates = LOG_REFS_NONE;
|
||||
if (write_ref_to_lockfile(lock, &orig_oid, 0, &err) ||
|
||||
if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||
|
||||
commit_ref_update(refs, lock, &orig_oid, NULL, &err)) {
|
||||
error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
|
||||
strbuf_release(&err);
|
||||
|
@ -1784,7 +1794,8 @@ static int files_log_ref_write(struct files_ref_store *refs,
|
|||
* Write oid into the open lockfile, then close the lockfile. On
|
||||
* errors, rollback the lockfile, fill in *err and return -1.
|
||||
*/
|
||||
static int write_ref_to_lockfile(struct ref_lock *lock,
|
||||
static int write_ref_to_lockfile(struct files_ref_store *refs,
|
||||
struct ref_lock *lock,
|
||||
const struct object_id *oid,
|
||||
int skip_oid_verification, struct strbuf *err)
|
||||
{
|
||||
|
@ -1793,7 +1804,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
|
|||
int fd;
|
||||
|
||||
if (!skip_oid_verification) {
|
||||
o = parse_object(the_repository, oid);
|
||||
o = parse_object(refs->base.repo, oid);
|
||||
if (!o) {
|
||||
strbuf_addf(
|
||||
err,
|
||||
|
@ -1812,7 +1823,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
|
|||
}
|
||||
}
|
||||
fd = get_lock_file_fd(&lock->lk);
|
||||
if (write_in_full(fd, oid_to_hex(oid), the_hash_algo->hexsz) < 0 ||
|
||||
if (write_in_full(fd, oid_to_hex(oid), refs->base.repo->hash_algo->hexsz) < 0 ||
|
||||
write_in_full(fd, &term, 1) < 0 ||
|
||||
fsync_component(FSYNC_COMPONENT_REFERENCE, get_lock_file_fd(&lock->lk)) < 0 ||
|
||||
close_ref_gently(lock) < 0) {
|
||||
|
@ -2547,7 +2558,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
|
|||
* value, so we don't need to write it.
|
||||
*/
|
||||
} else if (write_ref_to_lockfile(
|
||||
lock, &update->new_oid,
|
||||
refs, lock, &update->new_oid,
|
||||
update->flags & REF_SKIP_OID_VERIFICATION,
|
||||
err)) {
|
||||
char *write_err = strbuf_detach(err, NULL);
|
||||
|
@ -3230,7 +3241,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
|
|||
rollback_lock_file(&reflog_lock);
|
||||
} else if (update &&
|
||||
(write_in_full(get_lock_file_fd(&lock->lk),
|
||||
oid_to_hex(&cb.last_kept_oid), the_hash_algo->hexsz) < 0 ||
|
||||
oid_to_hex(&cb.last_kept_oid), refs->base.repo->hash_algo->hexsz) < 0 ||
|
||||
write_str_in_full(get_lock_file_fd(&lock->lk), "\n") < 0 ||
|
||||
close_ref_gently(lock) < 0)) {
|
||||
status |= error("couldn't write %s",
|
||||
|
@ -3254,12 +3265,12 @@ static int files_reflog_expire(struct ref_store *ref_store,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int files_init_db(struct ref_store *ref_store,
|
||||
static int files_ref_store_create_on_disk(struct ref_store *ref_store,
|
||||
int flags,
|
||||
struct strbuf *err UNUSED)
|
||||
{
|
||||
struct files_ref_store *refs =
|
||||
files_downcast(ref_store, REF_STORE_WRITE, "init_db");
|
||||
files_downcast(ref_store, REF_STORE_WRITE, "create");
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
/*
|
||||
|
@ -3282,7 +3293,7 @@ static int files_init_db(struct ref_store *ref_store,
|
|||
* There is no need to create directories for common refs when creating
|
||||
* a worktree ref store.
|
||||
*/
|
||||
if (!(flags & REFS_INIT_DB_IS_WORKTREE)) {
|
||||
if (!(flags & REF_STORE_CREATE_ON_DISK_IS_WORKTREE)) {
|
||||
/*
|
||||
* Create .git/refs/{heads,tags}
|
||||
*/
|
||||
|
@ -3301,8 +3312,10 @@ static int files_init_db(struct ref_store *ref_store,
|
|||
|
||||
struct ref_storage_be refs_be_files = {
|
||||
.name = "files",
|
||||
.init = files_ref_store_create,
|
||||
.init_db = files_init_db,
|
||||
.init = files_ref_store_init,
|
||||
.release = files_ref_store_release,
|
||||
.create_on_disk = files_ref_store_create_on_disk,
|
||||
|
||||
.transaction_prepare = files_transaction_prepare,
|
||||
.transaction_finish = files_transaction_finish,
|
||||
.transaction_abort = files_transaction_abort,
|
||||
|
|
|
@ -440,15 +440,15 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
|
|||
|
||||
struct ref_iterator *current_ref_iter = NULL;
|
||||
|
||||
int do_for_each_repo_ref_iterator(struct repository *r, struct ref_iterator *iter,
|
||||
each_repo_ref_fn fn, void *cb_data)
|
||||
int do_for_each_ref_iterator(struct ref_iterator *iter,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
int retval = 0, ok;
|
||||
struct ref_iterator *old_ref_iter = current_ref_iter;
|
||||
|
||||
current_ref_iter = iter;
|
||||
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
|
||||
retval = fn(r, iter->refname, iter->oid, iter->flags, cb_data);
|
||||
retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
|
||||
if (retval) {
|
||||
/*
|
||||
* If ref_iterator_abort() returns ITER_ERROR,
|
||||
|
|
|
@ -200,7 +200,12 @@ static int release_snapshot(struct snapshot *snapshot)
|
|||
}
|
||||
}
|
||||
|
||||
struct ref_store *packed_ref_store_create(struct repository *repo,
|
||||
static size_t snapshot_hexsz(const struct snapshot *snapshot)
|
||||
{
|
||||
return snapshot->refs->base.repo->hash_algo->hexsz;
|
||||
}
|
||||
|
||||
struct ref_store *packed_ref_store_init(struct repository *repo,
|
||||
const char *gitdir,
|
||||
unsigned int store_flags)
|
||||
{
|
||||
|
@ -252,6 +257,15 @@ static void clear_snapshot(struct packed_ref_store *refs)
|
|||
}
|
||||
}
|
||||
|
||||
static void packed_ref_store_release(struct ref_store *ref_store)
|
||||
{
|
||||
struct packed_ref_store *refs = packed_downcast(ref_store, 0, "release");
|
||||
clear_snapshot(refs);
|
||||
rollback_lock_file(&refs->lock);
|
||||
delete_tempfile(&refs->tempfile);
|
||||
free(refs->path);
|
||||
}
|
||||
|
||||
static NORETURN void die_unterminated_line(const char *path,
|
||||
const char *p, size_t len)
|
||||
{
|
||||
|
@ -280,11 +294,13 @@ struct snapshot_record {
|
|||
size_t len;
|
||||
};
|
||||
|
||||
static int cmp_packed_ref_records(const void *v1, const void *v2)
|
||||
static int cmp_packed_ref_records(const void *v1, const void *v2,
|
||||
void *cb_data)
|
||||
{
|
||||
const struct snapshot *snapshot = cb_data;
|
||||
const struct snapshot_record *e1 = v1, *e2 = v2;
|
||||
const char *r1 = e1->start + the_hash_algo->hexsz + 1;
|
||||
const char *r2 = e2->start + the_hash_algo->hexsz + 1;
|
||||
const char *r1 = e1->start + snapshot_hexsz(snapshot) + 1;
|
||||
const char *r2 = e2->start + snapshot_hexsz(snapshot) + 1;
|
||||
|
||||
while (1) {
|
||||
if (*r1 == '\n')
|
||||
|
@ -305,9 +321,9 @@ static int cmp_packed_ref_records(const void *v1, const void *v2)
|
|||
* refname.
|
||||
*/
|
||||
static int cmp_record_to_refname(const char *rec, const char *refname,
|
||||
int start)
|
||||
int start, const struct snapshot *snapshot)
|
||||
{
|
||||
const char *r1 = rec + the_hash_algo->hexsz + 1;
|
||||
const char *r1 = rec + snapshot_hexsz(snapshot) + 1;
|
||||
const char *r2 = refname;
|
||||
|
||||
while (1) {
|
||||
|
@ -354,7 +370,7 @@ static void sort_snapshot(struct snapshot *snapshot)
|
|||
if (!eol)
|
||||
/* The safety check should prevent this. */
|
||||
BUG("unterminated line found in packed-refs");
|
||||
if (eol - pos < the_hash_algo->hexsz + 2)
|
||||
if (eol - pos < snapshot_hexsz(snapshot) + 2)
|
||||
die_invalid_line(snapshot->refs->path,
|
||||
pos, eof - pos);
|
||||
eol++;
|
||||
|
@ -380,7 +396,7 @@ static void sort_snapshot(struct snapshot *snapshot)
|
|||
if (sorted &&
|
||||
nr > 1 &&
|
||||
cmp_packed_ref_records(&records[nr - 2],
|
||||
&records[nr - 1]) >= 0)
|
||||
&records[nr - 1], snapshot) >= 0)
|
||||
sorted = 0;
|
||||
|
||||
pos = eol;
|
||||
|
@ -390,7 +406,7 @@ static void sort_snapshot(struct snapshot *snapshot)
|
|||
goto cleanup;
|
||||
|
||||
/* We need to sort the memory. First we sort the records array: */
|
||||
QSORT(records, nr, cmp_packed_ref_records);
|
||||
QSORT_S(records, nr, cmp_packed_ref_records, snapshot);
|
||||
|
||||
/*
|
||||
* Allocate a new chunk of memory, and copy the old memory to
|
||||
|
@ -466,7 +482,8 @@ static void verify_buffer_safe(struct snapshot *snapshot)
|
|||
return;
|
||||
|
||||
last_line = find_start_of_record(start, eof - 1);
|
||||
if (*(eof - 1) != '\n' || eof - last_line < the_hash_algo->hexsz + 2)
|
||||
if (*(eof - 1) != '\n' ||
|
||||
eof - last_line < snapshot_hexsz(snapshot) + 2)
|
||||
die_invalid_line(snapshot->refs->path,
|
||||
last_line, eof - last_line);
|
||||
}
|
||||
|
@ -561,7 +578,7 @@ static const char *find_reference_location_1(struct snapshot *snapshot,
|
|||
|
||||
mid = lo + (hi - lo) / 2;
|
||||
rec = find_start_of_record(lo, mid);
|
||||
cmp = cmp_record_to_refname(rec, refname, start);
|
||||
cmp = cmp_record_to_refname(rec, refname, start, snapshot);
|
||||
if (cmp < 0) {
|
||||
lo = find_end_of_record(mid, hi);
|
||||
} else if (cmp > 0) {
|
||||
|
@ -858,7 +875,7 @@ static int next_record(struct packed_ref_iterator *iter)
|
|||
iter->base.flags = REF_ISPACKED;
|
||||
p = iter->pos;
|
||||
|
||||
if (iter->eof - p < the_hash_algo->hexsz + 2 ||
|
||||
if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 2 ||
|
||||
parse_oid_hex(p, &iter->oid, &p) ||
|
||||
!isspace(*p++))
|
||||
die_invalid_line(iter->snapshot->refs->path,
|
||||
|
@ -888,7 +905,7 @@ static int next_record(struct packed_ref_iterator *iter)
|
|||
|
||||
if (iter->pos < iter->eof && *iter->pos == '^') {
|
||||
p = iter->pos + 1;
|
||||
if (iter->eof - p < the_hash_algo->hexsz + 1 ||
|
||||
if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 1 ||
|
||||
parse_oid_hex(p, &iter->peeled, &p) ||
|
||||
*p++ != '\n')
|
||||
die_invalid_line(iter->snapshot->refs->path,
|
||||
|
@ -944,16 +961,13 @@ static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
struct packed_ref_iterator *iter =
|
||||
(struct packed_ref_iterator *)ref_iterator;
|
||||
|
||||
if (iter->repo != the_repository)
|
||||
BUG("peeling for non-the_repository is not supported");
|
||||
|
||||
if ((iter->base.flags & REF_KNOWS_PEELED)) {
|
||||
oidcpy(peeled, &iter->peeled);
|
||||
return is_null_oid(&iter->peeled) ? -1 : 0;
|
||||
} else if ((iter->base.flags & (REF_ISBROKEN | REF_ISSYMREF))) {
|
||||
return -1;
|
||||
} else {
|
||||
return peel_object(&iter->oid, peeled) ? -1 : 0;
|
||||
return peel_object(iter->repo, &iter->oid, peeled) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1244,7 +1258,7 @@ int packed_refs_is_locked(struct ref_store *ref_store)
|
|||
static const char PACKED_REFS_HEADER[] =
|
||||
"# pack-refs with: peeled fully-peeled sorted \n";
|
||||
|
||||
static int packed_init_db(struct ref_store *ref_store UNUSED,
|
||||
static int packed_ref_store_create_on_disk(struct ref_store *ref_store UNUSED,
|
||||
int flags UNUSED,
|
||||
struct strbuf *err UNUSED)
|
||||
{
|
||||
|
@ -1412,7 +1426,8 @@ static int write_with_updates(struct packed_ref_store *refs,
|
|||
i++;
|
||||
} else {
|
||||
struct object_id peeled;
|
||||
int peel_error = peel_object(&update->new_oid,
|
||||
int peel_error = peel_object(refs->base.repo,
|
||||
&update->new_oid,
|
||||
&peeled);
|
||||
|
||||
if (write_packed_entry(out, update->refname,
|
||||
|
@ -1706,8 +1721,10 @@ static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_s
|
|||
|
||||
struct ref_storage_be refs_be_packed = {
|
||||
.name = "packed",
|
||||
.init = packed_ref_store_create,
|
||||
.init_db = packed_init_db,
|
||||
.init = packed_ref_store_init,
|
||||
.release = packed_ref_store_release,
|
||||
.create_on_disk = packed_ref_store_create_on_disk,
|
||||
|
||||
.transaction_prepare = packed_transaction_prepare,
|
||||
.transaction_finish = packed_transaction_finish,
|
||||
.transaction_abort = packed_transaction_abort,
|
||||
|
|
|
@ -13,7 +13,7 @@ struct ref_transaction;
|
|||
* even among packed refs.
|
||||
*/
|
||||
|
||||
struct ref_store *packed_ref_store_create(struct repository *repo,
|
||||
struct ref_store *packed_ref_store_init(struct repository *repo,
|
||||
const char *gitdir,
|
||||
unsigned int store_flags);
|
||||
|
||||
|
|
|
@ -441,10 +441,7 @@ static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
{
|
||||
struct cache_ref_iterator *iter =
|
||||
(struct cache_ref_iterator *)ref_iterator;
|
||||
|
||||
if (iter->repo != the_repository)
|
||||
BUG("peeling for non-the_repository is not supported");
|
||||
return peel_object(ref_iterator->oid, peeled) ? -1 : 0;
|
||||
return peel_object(iter->repo, ref_iterator->oid, peeled) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int cache_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
|
|
|
@ -69,40 +69,6 @@ int ref_resolves_to_object(const char *refname,
|
|||
const struct object_id *oid,
|
||||
unsigned int flags);
|
||||
|
||||
enum peel_status {
|
||||
/* object was peeled successfully: */
|
||||
PEEL_PEELED = 0,
|
||||
|
||||
/*
|
||||
* object cannot be peeled because the named object (or an
|
||||
* object referred to by a tag in the peel chain), does not
|
||||
* exist.
|
||||
*/
|
||||
PEEL_INVALID = -1,
|
||||
|
||||
/* object cannot be peeled because it is not a tag: */
|
||||
PEEL_NON_TAG = -2,
|
||||
|
||||
/* ref_entry contains no peeled value because it is a symref: */
|
||||
PEEL_IS_SYMREF = -3,
|
||||
|
||||
/*
|
||||
* ref_entry cannot be peeled because it is broken (i.e., the
|
||||
* symbolic reference cannot even be resolved to an object
|
||||
* name):
|
||||
*/
|
||||
PEEL_BROKEN = -4
|
||||
};
|
||||
|
||||
/*
|
||||
* Peel the named object; i.e., if the object is a tag, resolve the
|
||||
* tag recursively until a non-tag is found. If successful, store the
|
||||
* result to oid and return PEEL_PEELED. If the object is not a tag
|
||||
* or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively,
|
||||
* and leave oid unchanged.
|
||||
*/
|
||||
enum peel_status peel_object(const struct object_id *name, struct object_id *oid);
|
||||
|
||||
/**
|
||||
* Information needed for a single ref update. Set new_oid to the new
|
||||
* value or to null_oid to delete the ref. To check the old value
|
||||
|
@ -517,9 +483,8 @@ extern struct ref_iterator *current_ref_iter;
|
|||
* adapter between the callback style of reference iteration and the
|
||||
* iterator style.
|
||||
*/
|
||||
int do_for_each_repo_ref_iterator(struct repository *r,
|
||||
struct ref_iterator *iter,
|
||||
each_repo_ref_fn fn, void *cb_data);
|
||||
int do_for_each_ref_iterator(struct ref_iterator *iter,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
struct ref_store;
|
||||
|
||||
|
@ -543,8 +508,12 @@ struct ref_store;
|
|||
typedef struct ref_store *ref_store_init_fn(struct repository *repo,
|
||||
const char *gitdir,
|
||||
unsigned int flags);
|
||||
/*
|
||||
* Release all memory and resources associated with the ref store.
|
||||
*/
|
||||
typedef void ref_store_release_fn(struct ref_store *refs);
|
||||
|
||||
typedef int ref_init_db_fn(struct ref_store *refs,
|
||||
typedef int ref_store_create_on_disk_fn(struct ref_store *refs,
|
||||
int flags,
|
||||
struct strbuf *err);
|
||||
|
||||
|
@ -678,7 +647,8 @@ typedef int read_symbolic_ref_fn(struct ref_store *ref_store, const char *refnam
|
|||
struct ref_storage_be {
|
||||
const char *name;
|
||||
ref_store_init_fn *init;
|
||||
ref_init_db_fn *init_db;
|
||||
ref_store_release_fn *release;
|
||||
ref_store_create_on_disk_fn *create_on_disk;
|
||||
|
||||
ref_transaction_prepare_fn *transaction_prepare;
|
||||
ref_transaction_finish_fn *transaction_finish;
|
||||
|
@ -709,7 +679,7 @@ extern struct ref_storage_be refs_be_packed;
|
|||
/*
|
||||
* A representation of the reference store for the main repository or
|
||||
* a submodule. The ref_store instances for submodules are kept in a
|
||||
* hash map; see get_submodule_ref_store() for more info.
|
||||
* hash map; see repo_get_submodule_ref_store() for more info.
|
||||
*/
|
||||
struct ref_store {
|
||||
/* The backend describing this ref_store's storage scheme: */
|
||||
|
|
|
@ -333,12 +333,33 @@ static struct ref_store *reftable_be_init(struct repository *repo,
|
|||
return &refs->base;
|
||||
}
|
||||
|
||||
static int reftable_be_init_db(struct ref_store *ref_store,
|
||||
static void reftable_be_release(struct ref_store *ref_store)
|
||||
{
|
||||
struct reftable_ref_store *refs = reftable_be_downcast(ref_store, 0, "release");
|
||||
struct strmap_entry *entry;
|
||||
struct hashmap_iter iter;
|
||||
|
||||
if (refs->main_stack) {
|
||||
reftable_stack_destroy(refs->main_stack);
|
||||
refs->main_stack = NULL;
|
||||
}
|
||||
|
||||
if (refs->worktree_stack) {
|
||||
reftable_stack_destroy(refs->worktree_stack);
|
||||
refs->worktree_stack = NULL;
|
||||
}
|
||||
|
||||
strmap_for_each_entry(&refs->worktree_stacks, &iter, entry)
|
||||
reftable_stack_destroy(entry->value);
|
||||
strmap_clear(&refs->worktree_stacks, 0);
|
||||
}
|
||||
|
||||
static int reftable_be_create_on_disk(struct ref_store *ref_store,
|
||||
int flags UNUSED,
|
||||
struct strbuf *err UNUSED)
|
||||
{
|
||||
struct reftable_ref_store *refs =
|
||||
reftable_be_downcast(ref_store, REF_STORE_WRITE, "init_db");
|
||||
reftable_be_downcast(ref_store, REF_STORE_WRITE, "create");
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
strbuf_addf(&sb, "%s/reftable", refs->base.gitdir);
|
||||
|
@ -1187,7 +1208,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
|
|||
ref.refname = (char *)u->refname;
|
||||
ref.update_index = ts;
|
||||
|
||||
peel_error = peel_object(&u->new_oid, &peeled);
|
||||
peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled);
|
||||
if (!peel_error) {
|
||||
ref.value_type = REFTABLE_REF_VAL2;
|
||||
memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
|
||||
|
@ -1980,6 +2001,7 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store,
|
|||
}
|
||||
|
||||
struct reflog_expiry_arg {
|
||||
struct reftable_ref_store *refs;
|
||||
struct reftable_stack *stack;
|
||||
struct reftable_log_record *records;
|
||||
struct object_id update_oid;
|
||||
|
@ -2008,7 +2030,7 @@ static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_da
|
|||
ref.refname = (char *)arg->refname;
|
||||
ref.update_index = ts;
|
||||
|
||||
if (!peel_object(&arg->update_oid, &peeled)) {
|
||||
if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled)) {
|
||||
ref.value_type = REFTABLE_REF_VAL2;
|
||||
memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
|
||||
memcpy(ref.value.val2.value, arg->update_oid.hash, GIT_MAX_RAWSZ);
|
||||
|
@ -2171,6 +2193,7 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
|
|||
reftable_ref_record_val1(&ref_record))
|
||||
oidread(&arg.update_oid, last_hash);
|
||||
|
||||
arg.refs = refs;
|
||||
arg.records = rewritten;
|
||||
arg.len = logs_nr;
|
||||
arg.stack = stack,
|
||||
|
@ -2205,7 +2228,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
|
|||
struct ref_storage_be refs_be_reftable = {
|
||||
.name = "reftable",
|
||||
.init = reftable_be_init,
|
||||
.init_db = reftable_be_init_db,
|
||||
.release = reftable_be_release,
|
||||
.create_on_disk = reftable_be_create_on_disk,
|
||||
|
||||
.transaction_prepare = reftable_be_transaction_prepare,
|
||||
.transaction_finish = reftable_be_transaction_finish,
|
||||
.transaction_abort = reftable_be_transaction_abort,
|
||||
|
|
12
remote.c
12
remote.c
|
@ -305,7 +305,7 @@ static void read_remotes_file(struct remote_state *remote_state,
|
|||
static void read_branches_file(struct remote_state *remote_state,
|
||||
struct remote *remote)
|
||||
{
|
||||
char *frag;
|
||||
char *frag, *to_free = NULL;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
|
||||
|
||||
|
@ -333,7 +333,7 @@ static void read_branches_file(struct remote_state *remote_state,
|
|||
if (frag)
|
||||
*(frag++) = '\0';
|
||||
else
|
||||
frag = (char *)git_default_branch_name(0);
|
||||
frag = to_free = repo_default_branch_name(the_repository, 0);
|
||||
|
||||
add_url_alias(remote_state, remote, strbuf_detach(&buf, NULL));
|
||||
refspec_appendf(&remote->fetch, "refs/heads/%s:refs/heads/%s",
|
||||
|
@ -345,6 +345,8 @@ static void read_branches_file(struct remote_state *remote_state,
|
|||
*/
|
||||
refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag);
|
||||
remote->fetch_tags = 1; /* always auto-follow */
|
||||
|
||||
free(to_free);
|
||||
}
|
||||
|
||||
static int handle_config(const char *key, const char *value,
|
||||
|
@ -2388,11 +2390,13 @@ struct ref *guess_remote_head(const struct ref *head,
|
|||
|
||||
/* If a remote branch exists with the default branch name, let's use it. */
|
||||
if (!all) {
|
||||
char *ref = xstrfmt("refs/heads/%s",
|
||||
git_default_branch_name(0));
|
||||
char *default_branch = repo_default_branch_name(the_repository, 0);
|
||||
char *ref = xstrfmt("refs/heads/%s", default_branch);
|
||||
|
||||
r = find_ref_by_name(refs, ref);
|
||||
free(ref);
|
||||
free(default_branch);
|
||||
|
||||
if (r && oideq(&r->old_oid, &head->old_oid))
|
||||
return copy_ref(r);
|
||||
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
#include "repository.h"
|
||||
#include "commit.h"
|
||||
|
||||
static int register_replace_ref(struct repository *r,
|
||||
const char *refname,
|
||||
static int register_replace_ref(const char *refname,
|
||||
const struct object_id *oid,
|
||||
int flag UNUSED,
|
||||
void *cb_data UNUSED)
|
||||
void *cb_data)
|
||||
{
|
||||
struct repository *r = cb_data;
|
||||
|
||||
/* Get sha1 from refname */
|
||||
const char *slash = strrchr(refname, '/');
|
||||
const char *hash = slash ? slash + 1 : refname;
|
||||
|
@ -50,7 +51,8 @@ void prepare_replace_object(struct repository *r)
|
|||
xmalloc(sizeof(*r->objects->replace_map));
|
||||
oidmap_init(r->objects->replace_map, 0);
|
||||
|
||||
for_each_replace_ref(r, register_replace_ref, NULL);
|
||||
refs_for_each_replace_ref(get_main_ref_store(r),
|
||||
register_replace_ref, r);
|
||||
r->objects->replace_map_initialized = 1;
|
||||
|
||||
pthread_mutex_unlock(&r->objects->replace_mutex);
|
||||
|
|
12
repository.c
12
repository.c
|
@ -14,6 +14,7 @@
|
|||
#include "sparse-index.h"
|
||||
#include "trace2.h"
|
||||
#include "promisor-remote.h"
|
||||
#include "refs.h"
|
||||
|
||||
/* The main repository */
|
||||
static struct repository the_repo;
|
||||
|
@ -269,6 +270,9 @@ static void repo_clear_path_cache(struct repo_path_cache *cache)
|
|||
|
||||
void repo_clear(struct repository *repo)
|
||||
{
|
||||
struct hashmap_iter iter;
|
||||
struct strmap_entry *e;
|
||||
|
||||
FREE_AND_NULL(repo->gitdir);
|
||||
FREE_AND_NULL(repo->commondir);
|
||||
FREE_AND_NULL(repo->graft_file);
|
||||
|
@ -309,6 +313,14 @@ void repo_clear(struct repository *repo)
|
|||
FREE_AND_NULL(repo->remote_state);
|
||||
}
|
||||
|
||||
strmap_for_each_entry(&repo->submodule_ref_stores, &iter, e)
|
||||
ref_store_release(e->value);
|
||||
strmap_clear(&repo->submodule_ref_stores, 1);
|
||||
|
||||
strmap_for_each_entry(&repo->worktree_ref_stores, &iter, e)
|
||||
ref_store_release(e->value);
|
||||
strmap_clear(&repo->worktree_ref_stores, 1);
|
||||
|
||||
repo_clear_path_cache(&repo->cached_paths);
|
||||
}
|
||||
|
||||
|
|
14
repository.h
14
repository.h
|
@ -1,6 +1,8 @@
|
|||
#ifndef REPOSITORY_H
|
||||
#define REPOSITORY_H
|
||||
|
||||
#include "strmap.h"
|
||||
|
||||
struct config_set;
|
||||
struct fsmonitor_settings;
|
||||
struct git_hash_algo;
|
||||
|
@ -108,6 +110,18 @@ struct repository {
|
|||
*/
|
||||
struct ref_store *refs_private;
|
||||
|
||||
/*
|
||||
* A strmap of ref_stores, stored by submodule name, accessible via
|
||||
* `repo_get_submodule_ref_store()`.
|
||||
*/
|
||||
struct strmap submodule_ref_stores;
|
||||
|
||||
/*
|
||||
* A strmap of ref_stores, stored by worktree id, accessible via
|
||||
* `get_worktree_ref_store()`.
|
||||
*/
|
||||
struct strmap worktree_ref_stores;
|
||||
|
||||
/*
|
||||
* Contains path to often used file names.
|
||||
*/
|
||||
|
|
7
setup.c
7
setup.c
|
@ -2099,10 +2099,11 @@ void create_reference_database(unsigned int ref_storage_format,
|
|||
const char *initial_branch, int quiet)
|
||||
{
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
char *to_free = NULL;
|
||||
int reinit = is_reinit();
|
||||
|
||||
repo_set_ref_storage_format(the_repository, ref_storage_format);
|
||||
if (refs_init_db(get_main_ref_store(the_repository), 0, &err))
|
||||
if (ref_store_create_on_disk(get_main_ref_store(the_repository), 0, &err))
|
||||
die("failed to set up refs db: %s", err.buf);
|
||||
|
||||
/*
|
||||
|
@ -2113,7 +2114,8 @@ void create_reference_database(unsigned int ref_storage_format,
|
|||
char *ref;
|
||||
|
||||
if (!initial_branch)
|
||||
initial_branch = git_default_branch_name(quiet);
|
||||
initial_branch = to_free =
|
||||
repo_default_branch_name(the_repository, quiet);
|
||||
|
||||
ref = xstrfmt("refs/heads/%s", initial_branch);
|
||||
if (check_refname_format(ref, 0) < 0)
|
||||
|
@ -2130,6 +2132,7 @@ void create_reference_database(unsigned int ref_storage_format,
|
|||
initial_branch);
|
||||
|
||||
strbuf_release(&err);
|
||||
free(to_free);
|
||||
}
|
||||
|
||||
static int create_default_files(const char *template_path,
|
||||
|
|
|
@ -99,7 +99,8 @@ int is_staging_gitmodules_ok(struct index_state *istate)
|
|||
static int for_each_remote_ref_submodule(const char *submodule,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
|
||||
return refs_for_each_remote_ref(repo_get_submodule_ref_store(the_repository,
|
||||
submodule),
|
||||
fn, cb_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ int cmd__reach(int ac, const char **av)
|
|||
die("failed to resolve %s", buf.buf + 2);
|
||||
|
||||
orig = parse_object(r, &oid);
|
||||
peeled = deref_tag_noverify(orig);
|
||||
peeled = deref_tag_noverify(the_repository, orig);
|
||||
|
||||
if (!peeled)
|
||||
die("failed to load commit for input %s resulting in oid %s\n",
|
||||
|
|
|
@ -82,7 +82,7 @@ static const char **get_store(const char **argv, struct ref_store **refs)
|
|||
add_to_alternates_memory(sb.buf);
|
||||
strbuf_release(&sb);
|
||||
|
||||
*refs = get_submodule_ref_store(gitdir);
|
||||
*refs = repo_get_submodule_ref_store(the_repository, gitdir);
|
||||
} else if (skip_prefix(argv[0], "worktree:", &gitdir)) {
|
||||
struct worktree **p, **worktrees = get_worktrees();
|
||||
|
||||
|
|
4
tag.c
4
tag.c
|
@ -91,10 +91,10 @@ struct object *deref_tag(struct repository *r, struct object *o, const char *war
|
|||
return o;
|
||||
}
|
||||
|
||||
struct object *deref_tag_noverify(struct object *o)
|
||||
struct object *deref_tag_noverify(struct repository *r, struct object *o)
|
||||
{
|
||||
while (o && o->type == OBJ_TAG) {
|
||||
o = parse_object(the_repository, &o->oid);
|
||||
o = parse_object(r, &o->oid);
|
||||
if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged)
|
||||
o = ((struct tag *)o)->tagged;
|
||||
else
|
||||
|
|
2
tag.h
2
tag.h
|
@ -16,7 +16,7 @@ int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, u
|
|||
int parse_tag(struct tag *item);
|
||||
void release_tag_memory(struct tag *t);
|
||||
struct object *deref_tag(struct repository *r, struct object *, const char *, int);
|
||||
struct object *deref_tag_noverify(struct object *);
|
||||
struct object *deref_tag_noverify(struct repository *r, struct object *);
|
||||
int gpg_verify_tag(const struct object_id *oid,
|
||||
const char *name_to_report, unsigned flags);
|
||||
struct object_id *get_tagged_oid(struct tag *tag);
|
||||
|
|
|
@ -2318,7 +2318,8 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
|
|||
|
||||
if (S_ISGITLINK(ce->ce_mode)) {
|
||||
struct object_id oid;
|
||||
int sub_head = resolve_gitlink_ref(ce->name, "HEAD", &oid);
|
||||
int sub_head = repo_resolve_gitlink_ref(the_repository, ce->name,
|
||||
"HEAD", &oid);
|
||||
/*
|
||||
* If we are not going to update the submodule, then
|
||||
* we don't care.
|
||||
|
|
|
@ -1269,7 +1269,7 @@ static void write_v0_ref(struct upload_pack_data *data,
|
|||
packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
|
||||
}
|
||||
capabilities = NULL;
|
||||
if (!peel_iterated_oid(oid, &peeled))
|
||||
if (!peel_iterated_oid(the_repository, oid, &peeled))
|
||||
packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)
|
|||
strbuf_strip_suffix(&worktree_path, "/.git");
|
||||
|
||||
CALLOC_ARRAY(worktree, 1);
|
||||
worktree->repo = the_repository;
|
||||
worktree->path = strbuf_detach(&worktree_path, NULL);
|
||||
/*
|
||||
* NEEDSWORK: If this function is called from a secondary worktree and
|
||||
|
@ -98,6 +99,7 @@ struct worktree *get_linked_worktree(const char *id,
|
|||
strbuf_strip_suffix(&worktree_path, "/.git");
|
||||
|
||||
CALLOC_ARRAY(worktree, 1);
|
||||
worktree->repo = the_repository;
|
||||
worktree->path = strbuf_detach(&worktree_path, NULL);
|
||||
worktree->id = xstrdup(id);
|
||||
if (!skip_reading_head)
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
struct strbuf;
|
||||
|
||||
struct worktree {
|
||||
/* The repository this worktree belongs to. */
|
||||
struct repository *repo;
|
||||
char *path;
|
||||
char *id;
|
||||
char *head_ref; /* NULL if HEAD is broken or detached */
|
||||
|
|
Loading…
Reference in a new issue