--- v3
+++ v4
@@ -8,38 +8,45 @@
"git branch --recurse-submodules" in-process but couldn't figure out how to read
the remotes of a submodule.
-v3 tightens up the interface issues discussed previously ([2] and other v2
-discussion) by adding a "struct remote_state" backpointer to "struct branch" and
-"struct remote". The most notable improvement is that we no longer accept
-"struct {remote_state,repository}" and "struct {branch,remote}" parameters at
-the same time, thus it is impossible to pass the wrong (container, contained)
-object pair. This is especially useful for branch_get_push_1(), where we
-take a "struct branch" and need to get a related "struct remote".
-
-The intention is that this backpointer is only meant to be used by the remotes
-subsystem; it is meant to be an opaque implementation detail that no other
-callers should touch.
-
-I attempted the initial suggestion to include a backpointer from branch->repo
-instead of branch->remote_state and uploaded it to a branch in my own fork [3].
-However, this seems to be the wrong abstraction to me. I am not convinced that
-the contained structs (branch, remote) need to (nor will ever need to) interact
-with parts of the repository outside of remote_state. A symptom of this is that
-internal code ends up using "struct repository" parameters instead of "struct
-remote_state" only to use repo->remote_state repeatedly, violating some of the
-nice layering that we have set up.
-
-There is also a small YAGNI benefit of using a backpointer to the remote_state
-instead of repository. If we eventually decide that branches should
-point to their repository, we can make the change with
-s/remote_state/repo->remote_state, even if external callers start to rely on
-branch->remote_state (even though I don't think they shouldn't rely on it!).
-This property does not hold for branch->repo because external callers might be
-using members other than repository->remote_state.
+v4 reverts the backpointer introduced in v3. In authoring v3, I had
+overlooked the fact that branch == NULL (representing detached HEAD) is
+a valid argument to some branch_* functions and as a result, we cannot
+always rely on branch->remote_state to tell us the remote_state of a
+branch. This was not discovered because of a coding mistake in v3 where
+branch was unconditionally dereferenced, even when it was null [2]. v4
+adds a test that checks the relevant behavior.
+
+The resulting interface is similar to v2, but with Junio's proposed
+safety check [3] - when branch + repository are passed as a pair we
+check that the branch belongs to the repository (i.e. it is in the
+repository's remote_state struct). This check is only implemented for
+non-static functions because the probability of misuse is much higher.
+In static functions, this check is wasteful because we frequently
+operate on the remote_state + {branch, remote} pair in order to maintain
+data consistency and the correct remote_state is often obvious from
+context.
+
+In the long run, I believe that there is room for refactoring/interface changes
+as to avoid these internal correctness issues, but I think this is a good enough
+starting point.
[1] https://lore.kernel.org/git/20210921232529.81811-1-chooglen@google.com/
-[2] https://lore.kernel.org/git/xmqq4k9so15i.fsf@gitster.g/
-[3] https://github.com/git/git/commit/9527d9106ff5a41530e7bfa50a316af296144c99
+[2] https://lore.kernel.org/git/xmqqtuhbo2tn.fsf@gitster.g
+[2] https://lore.kernel.org/git/xmqqfssozk8r.fsf@gitster.g
+
+Changes since v3:
+* Add a test case for pushing to a remote in detached HEAD. This test
+ would have caught the segfault that resulted in this reroll.
+* Remove the NEEDSWORK saying that init_remotes_hash() should be moved
+ into remote_state_new() and just do it.
+* Remove the backpointer to remote_state and add a remote_state
+ parameter instead.
+* In patch 4, add more remotes_* functions. These functions were not
+ needed in v3 because of the backpointer.
+* In patch 5, add a function that checks if a branch is in a repo. Add a
+ branch hashmap that makes this operation fast.
+* In patch 6, add more repo_* functions. These functions were not needed
+ in v3 because of the backpointer.
Changes since v2:
* Add .remote_state to struct branch and struct remote, changing the
@@ -53,120 +60,167 @@
"struct repository" away from the remote.c internals.
Changes since v1:
-
* In v1, we moved static variables into the_repository->remote_state in
two steps: static variables > static remote_state >
the_repository->remote_state. In v2, make this change in one step:
static variables > the_repository->remote_state.
* Add more instances of repo_* that were missed.
-Glen Choo (4):
+Glen Choo (6):
+ t5516: add test case for pushing remote refspecs
remote: move static variables into per-repository struct
remote: use remote_state parameter internally
remote: remove the_repository->remote_state from static methods
+ remote: die if branch is not found in repository
remote: add struct repository parameter to external functions
- remote.c | 303 +++++++++++++++++++++++++++++++--------------------
- remote.h | 72 +++++++++++-
- repository.c | 8 ++
- repository.h | 4 +
- 4 files changed, 262 insertions(+), 125 deletions(-)
-
-Range-diff against v2:
-1: 6972ba4dcb ! 1: 1f712c22b4 remote: move static variables into per-repository struct
- @@ remote.h: enum {
- + int instead_of_nr;
- + int instead_of_alloc;
- +};
+ remote.c | 406 +++++++++++++++++++++++++++++-------------
+ remote.h | 118 ++++++++++--
+ repository.c | 8 +
+ repository.h | 4 +
+ t/t5516-fetch-push.sh | 9 +
+ 5 files changed, 404 insertions(+), 141 deletions(-)
+
+Range-diff against v3:
+-: ---------- > 1: 9b29ec27c6 t5516: add test case for pushing remote refspecs
+1: 1f712c22b4 ! 2: ca9b5ab66a remote: move static variables into per-repository struct
+ @@ remote.c: static void add_pushurl(struct remote *remote, const char *pushurl)
+ }
+
+ @@ remote.c: static int remotes_hash_cmp(const void *unused_cmp_data,
+ + return strcmp(a->name, b->name);
+ + }
+
+ - static inline void init_remotes_hash(void)
+ - {
+ +-static inline void init_remotes_hash(void)
+ +-{
+ - if (!remotes_hash.cmpfn)
+ - hashmap_init(&remotes_hash, remotes_hash_cmp, NULL, 0);
+ -+ if (!the_repository->remote_state->remotes_hash.cmpfn)
+ -+ hashmap_init(&the_repository->remote_state->remotes_hash,
+ -+ remotes_hash_cmp, NULL, 0);
+ - }
+ -
+ +-}
+ +-
+ static struct remote *make_remote(const char *name, int len)
+ + {
+ + struct remote *ret;
+ @@ remote.c: static struct remote *make_remote(const char *name, int len)
+ + if (!len)
+ + len = strlen(name);
+ +
+ +- init_remotes_hash();
+ + lookup.str = name;
+ lookup.len = len;
+ hashmap_entry_init(&lookup_entry, memhash(name, len));
+
+ @@ remote.c: void apply_push_cas(struct push_cas_option *cas,
+ + struct remote_state *r = xmalloc(sizeof(*r));
+ +
+ + memset(r, 0, sizeof(*r));
++
- +struct rewrites {
- + struct rewrite **rewrite;
- + int rewrite_alloc;
- @@ remote.h: enum {
- +};
+ ++ hashmap_init(&r->remotes_hash, remotes_hash_cmp, NULL, 0);
+ + return r;
+ +}
+
- +struct remote_state {
- -+ int config_loaded;
- -+
- + struct remote **remotes;
- + int remotes_alloc;
- + int remotes_nr;
- @@ remote.h: enum {
- + struct rewrites rewrites;
- + struct rewrites rewrites_push;
- +};
- ++
- +void remote_state_clear(struct remote_state *remote_state);
- +struct remote_state *remote_state_new(void);
- +
-2: 71b1da4389 ! 2: 467247fa9c remote: use remote_state parameter internally
+2: 467247fa9c ! 3: 5d6a245cae remote: use remote_state parameter internally
@@ Metadata
## Commit message ##
remote: use remote_state parameter internally
- - In internal-facing functions, replace the_repository->remote_state with
- - a struct remote_state parameter, but do not change external-facing
- - functions.
- + Introduce a struct remote_state member to structs that need to
- + 'remember' their remote_state. Without changing external-facing
- + functions, replace the_repository->remote_state internally by using the
- + remote_state member where it is applicable i.e. when a function accepts
- + a struct that depends on the remote_state. If it is not applicable, add
- + a struct remote_state parameter instead.
+ - Introduce a struct remote_state member to structs that need to
+ - 'remember' their remote_state. Without changing external-facing
+ - functions, replace the_repository->remote_state internally by using the
+ - remote_state member where it is applicable i.e. when a function accepts
+ - a struct that depends on the remote_state. If it is not applicable, add
+ - a struct remote_state parameter instead.
+ + Without changing external-facing functions, replace
+ + the_repository->remote_state internally by adding a struct remote_state
+ + parameter.
- - As a result, most static functions no longer reference
- + As a result, external-facing functions are still tied to the_repository,
- + but most static functions no longer reference
- the_repository->remote_state. The exceptions are those that are used in
- a way that depends on external-facing functions e.g. the callbacks to
- remote_get_1().
+ As a result, external-facing functions are still tied to the_repository,
+ but most static functions no longer reference
@@ Commit message
## remote.c ##
@@ remote.c: static void add_pushurl(struct remote *remote, const char *pushurl)
- - remote->pushurl[remote->pushurl_nr++] = pushurl;
- - }
- -
- --static void add_pushurl_alias(struct remote *remote, const char *url)
- -+static void add_pushurl_alias(struct remote_state *remote_state,
- -+ struct remote *remote, const char *url)
- + static void add_pushurl_alias(struct remote *remote, const char *url)
+ - static void add_pushurl_alias(struct remote *remote, const char *url)
+ + remote->pushurl[remote->pushurl_nr++] = pushurl;
+ + }
+ +
+ +-static void add_pushurl_alias(struct remote *remote, const char *url)
+ ++static void add_pushurl_alias(struct remote_state *remote_state,
+ ++ struct remote *remote, const char *url)
{
- -- const char *pushurl =
- + const char *pushurl =
+ - const char *pushurl =
+ +- const char *pushurl =
- alias_url(url, &the_repository->remote_state->rewrites_push);
- -+ const char *pushurl = alias_url(url, &remote_state->rewrites_push);
- ++ alias_url(url, &remote->remote_state->rewrites_push);
+ -+ alias_url(url, &remote->remote_state->rewrites_push);
+ ++ const char *pushurl = alias_url(url, &remote_state->rewrites_push);
if (pushurl != url)
add_pushurl(remote, pushurl);
}
- --static void add_url_alias(struct remote *remote, const char *url)
- -+static void add_url_alias(struct remote_state *remote_state,
- -+ struct remote *remote, const char *url)
- + static void add_url_alias(struct remote *remote, const char *url)
+ - static void add_url_alias(struct remote *remote, const char *url)
+ +-static void add_url_alias(struct remote *remote, const char *url)
+ ++static void add_url_alias(struct remote_state *remote_state,
+ ++ struct remote *remote, const char *url)
{
- add_url(remote,
- alias_url(url, &the_repository->remote_state->rewrites));
- -- add_pushurl_alias(remote, url);
- -+ add_url(remote, alias_url(url, &remote_state->rewrites));
- -+ add_pushurl_alias(remote_state, remote, url);
- ++ add_url(remote, alias_url(url, &remote->remote_state->rewrites));
- + add_pushurl_alias(remote, url);
- }
-
- - struct remotes_hash_key {
+ -+ add_url(remote, alias_url(url, &remote->remote_state->rewrites));
+ - add_pushurl_alias(remote, url);
+ +- add_pushurl_alias(remote, url);
+ ++ add_url(remote, alias_url(url, &remote_state->rewrites));
+ ++ add_pushurl_alias(remote_state, remote, url);
+ }
+
+ + struct remotes_hash_key {
@@ remote.c: static int remotes_hash_cmp(const void *unused_cmp_data,
return strcmp(a->name, b->name);
}
+
+ --static inline void init_remotes_hash(void)
+ -+/**
+ -+ * NEEDSWORK: Now that the hashmap is in a struct, this should probably
+ -+ * just be moved into remote_state_new().
+ -+ */
+ -+static inline void init_remotes_hash(struct remote_state *remote_state)
+ - {
+ -- if (!the_repository->remote_state->remotes_hash.cmpfn)
+ -- hashmap_init(&the_repository->remote_state->remotes_hash,
+ -- remotes_hash_cmp, NULL, 0);
+ -+ if (!remote_state->remotes_hash.cmpfn)
+ -+ hashmap_init(&remote_state->remotes_hash, remotes_hash_cmp,
+ -+ NULL, 0);
+ - }
+ -
+ -static struct remote *make_remote(const char *name, int len)
+ +static struct remote *make_remote(struct remote_state *remote_state,
+ + const char *name, int len)
+ @@ remote.c: static int remotes_hash_cmp(const void *unused_cmp_data,
+ struct remote *ret;
+ struct remotes_hash_key lookup;
+ @@ remote.c: static struct remote *make_remote(const char *name, int len)
+ - if (!len)
+ - len = strlen(name);
+ -
+ -- init_remotes_hash();
+ -+ init_remotes_hash(remote_state);
+ - lookup.str = name;
+ lookup.len = len;
+ hashmap_entry_init(&lookup_entry, memhash(name, len));
+
@@ remote.c: static struct remote *make_remote(const char *name, int len)
return container_of(e, struct remote, ent);
@@ remote.c: static struct remote *make_remote(const char *name, int len)
- + ret->prune = -1; /* unspecified */
- + ret->prune_tags = -1; /* unspecified */
- + ret->name = xstrndup(name, len);
- ++ ret->remote_state = remote_state;
+ - ret->prune = -1; /* unspecified */
+ - ret->prune_tags = -1; /* unspecified */
+ - ret->name = xstrndup(name, len);
+ -+ ret->remote_state = remote_state;
refspec_init(&ret->push, REFSPEC_PUSH);
refspec_init(&ret->fetch, REFSPEC_FETCH);
@@ -174,48 +228,48 @@
+ remote_state->branches[remote_state->branches_nr++] = ret;
ret->name = xstrndup(name, len);
ret->refname = xstrfmt("refs/heads/%s", ret->name);
- ++ ret->remote_state = remote_state;
-
- -@@ remote.c: static const char *skip_spaces(const char *s)
- - return s;
- - }
- -
- --static void read_remotes_file(struct remote *remote)
- -+static void read_remotes_file(struct remote_state *remote_state,
- -+ struct remote *remote)
- - {
- - struct strbuf buf = STRBUF_INIT;
- - FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r");
- -@@ remote.c: static void read_remotes_file(struct remote *remote)
- - strbuf_rtrim(&buf);
- -
- - if (skip_prefix(buf.buf, "URL:", &v))
- -- add_url_alias(remote, xstrdup(skip_spaces(v)));
- -+ add_url_alias(remote_state, remote,
- -+ xstrdup(skip_spaces(v)));
- - else if (skip_prefix(buf.buf, "Push:", &v))
- - refspec_append(&remote->push, skip_spaces(v));
- - else if (skip_prefix(buf.buf, "Pull:", &v))
- -@@ remote.c: static void read_remotes_file(struct remote *remote)
- - fclose(f);
- + return ret;
- }
- -
- --static void read_branches_file(struct remote *remote)
- -+static void read_branches_file(struct remote_state *remote_state,
- -+ struct remote *remote)
- - {
- - char *frag;
- - struct strbuf buf = STRBUF_INIT;
- -@@ remote.c: static void read_branches_file(struct remote *remote)
- - else
- - frag = (char *)git_default_branch_name(0);
- -
- -- add_url_alias(remote, strbuf_detach(&buf, NULL));
- -+ add_url_alias(remote_state, remote, strbuf_detach(&buf, NULL));
- - refspec_appendf(&remote->fetch, "refs/heads/%s:refs/heads/%s",
- - frag, remote->name);
- -
+ -+ ret->remote_state = remote_state;
+
+ - return ret;
+ +@@ remote.c: static const char *skip_spaces(const char *s)
+ + return s;
+ }
+ +
+ +-static void read_remotes_file(struct remote *remote)
+ ++static void read_remotes_file(struct remote_state *remote_state,
+ ++ struct remote *remote)
+ + {
+ + struct strbuf buf = STRBUF_INIT;
+ + FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r");
+ +@@ remote.c: static void read_remotes_file(struct remote *remote)
+ + strbuf_rtrim(&buf);
+ +
+ + if (skip_prefix(buf.buf, "URL:", &v))
+ +- add_url_alias(remote, xstrdup(skip_spaces(v)));
+ ++ add_url_alias(remote_state, remote,
+ ++ xstrdup(skip_spaces(v)));
+ + else if (skip_prefix(buf.buf, "Push:", &v))
+ + refspec_append(&remote->push, skip_spaces(v));
+ + else if (skip_prefix(buf.buf, "Pull:", &v))
+ +@@ remote.c: static void read_remotes_file(struct remote *remote)
+ + fclose(f);
+ + }
+ +
+ +-static void read_branches_file(struct remote *remote)
+ ++static void read_branches_file(struct remote_state *remote_state,
+ ++ struct remote *remote)
+ + {
+ + char *frag;
+ + struct strbuf buf = STRBUF_INIT;
+ +@@ remote.c: static void read_branches_file(struct remote *remote)
+ + else
+ + frag = (char *)git_default_branch_name(0);
+ +
+ +- add_url_alias(remote, strbuf_detach(&buf, NULL));
+ ++ add_url_alias(remote_state, remote, strbuf_detach(&buf, NULL));
+ + refspec_appendf(&remote->fetch, "refs/heads/%s:refs/heads/%s",
+ + frag, remote->name);
+ +
@@ remote.c: static int handle_config(const char *key, const char *value, void *cb)
const char *subkey;
struct remote *remote;
@@ -223,156 +277,82 @@
- ->url[j] = alias_url(
- the_repository->remote_state->remotes[i]->url[j],
- &the_repository->remote_state->rewrites);
- -+ remote_state, remote_state->remotes[i],
- ++ remote_state->remotes[i],
+ -+ remote_state->remotes[i],
+ ++ remote_state, remote_state->remotes[i],
+ remote_state->remotes[i]->url[j]);
+ remote_state->remotes[i]->url[j] =
+ alias_url(remote_state->remotes[i]->url[j],
@@ remote.c: static int handle_config(const char *key, const char *value, void *cb)
}
- -static void read_config(void)
- -+static void read_config(struct remote_state *remote_state)
- ++static void read_config(struct repository *repo)
- {
- - static int loaded;
- +- static int loaded;
- int flag;
- -@@ remote.c: static void read_config(void)
- +
- +- if (loaded)
- ++ if (repo->remote_state->initialized)
- return;
- - loaded = 1;
- +- loaded = 1;
- ++ repo->remote_state->initialized = 1;
-
- - the_repository->remote_state->current_branch = NULL;
- -+ remote_state->current_branch = NULL;
- ++ repo->remote_state->current_branch = NULL;
- if (startup_info->have_repository) {
- - const char *head_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flag);
- +- const char *head_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flag);
- ++ const char *head_ref = refs_resolve_ref_unsafe(
- ++ get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
- if (head_ref && (flag & REF_ISSYMREF) &&
- skip_prefix(head_ref, "refs/heads/", &head_ref)) {
- - the_repository->remote_state->current_branch =
- - make_branch(head_ref, strlen(head_ref));
- -+ remote_state->current_branch = make_branch(
- -+ remote_state, head_ref, strlen(head_ref));
- ++ repo->remote_state->current_branch = make_branch(
- ++ repo->remote_state, head_ref, strlen(head_ref));
- }
- }
- - git_config(handle_config, NULL);
- - alias_all_urls();
- -+ git_config(handle_config, remote_state);
- -+ alias_all_urls(remote_state);
- ++ repo_config(repo, handle_config, repo->remote_state);
- ++ alias_all_urls(repo->remote_state);
- }
-
static int valid_remote_nick(const char *name)
- +@@ remote.c: const char *pushremote_for_branch(struct branch *branch, int *explicit)
- + *explicit = 1;
- + return branch->pushremote_name;
- + }
- +- if (the_repository->remote_state->pushremote_name) {
- ++ if (branch->remote_state->pushremote_name) {
- + if (explicit)
- + *explicit = 1;
- +- return the_repository->remote_state->pushremote_name;
- ++ return branch->remote_state->pushremote_name;
- + }
- + return remote_for_branch(branch, explicit);
- + }
+ -@@ remote.c: const char *pushremote_for_branch(struct branch *branch, int *explicit)
+ - *explicit = 1;
+ - return branch->pushremote_name;
+ - }
+ -- if (the_repository->remote_state->pushremote_name) {
+ -+ if (branch->remote_state->pushremote_name) {
+ - if (explicit)
+ - *explicit = 1;
+ -- return the_repository->remote_state->pushremote_name;
+ -+ return branch->remote_state->pushremote_name;
+ - }
+ - return remote_for_branch(branch, explicit);
+ - }
@@ remote.c: static struct remote *remote_get_1(const char *name,
struct remote *ret;
int name_given = 0;
-
- - read_config();
- -+ read_config(the_repository->remote_state);
- ++ read_config(the_repository);
-
- if (name)
- name_given = 1;
@@ remote.c: static struct remote *remote_get_1(const char *name,
+ ret = make_remote(the_repository->remote_state, name, 0);
if (valid_remote_nick(name) && have_git_dir()) {
if (!valid_remote(ret))
- -- read_remotes_file(ret);
- -+ read_remotes_file(the_repository->remote_state, ret);
- - if (!valid_remote(ret))
- -- read_branches_file(ret);
- -+ read_branches_file(the_repository->remote_state, ret);
- - }
- - if (name_given && !valid_remote(ret))
- -- add_url_alias(ret, name);
- -+ add_url_alias(the_repository->remote_state, ret, name);
- - if (!valid_remote(ret))
- - return NULL;
- - return ret;
- + read_remotes_file(ret);
+ - read_remotes_file(ret);
+ +- read_remotes_file(ret);
+ ++ read_remotes_file(the_repository->remote_state, ret);
+ + if (!valid_remote(ret))
+ +- read_branches_file(ret);
+ ++ read_branches_file(the_repository->remote_state, ret);
+ + }
+ + if (name_given && !valid_remote(ret))
+ +- add_url_alias(ret, name);
+ ++ add_url_alias(the_repository->remote_state, ret, name);
+ + if (!valid_remote(ret))
+ + return NULL;
+ + return ret;
@@ remote.c: int remote_is_configured(struct remote *remote, int in_repo)
int for_each_remote(each_remote_fn fn, void *priv)
{
- int i, result = 0;
- - read_config();
- -+ read_config(the_repository->remote_state);
- ++ read_config(the_repository);
- for (i = 0; i < the_repository->remote_state->remotes_nr && !result;
- i++) {
- struct remote *remote =
- @@ remote.c: struct branch *branch_get(const char *name)
- struct branch *ret;
-
- - read_config();
- -+ read_config(the_repository->remote_state);
- ++ read_config(the_repository);
- if (!name || !*name || !strcmp(name, "HEAD"))
- ret = the_repository->remote_state->current_branch;
- else
- @@ remote.c: struct branch *branch_get(const char *name)
- set_merge(ret);
- return ret;
- }
- +
- + ## remote.h ##
- +@@ remote.h: struct remote_state {
- +
- + struct rewrites rewrites;
- + struct rewrites rewrites_push;
- ++
- ++ int initialized;
- + };
- +
- + void remote_state_clear(struct remote_state *remote_state);
- +@@ remote.h: struct remote {
- +
- + /* The method used for authenticating against `http_proxy`. */
- + char *http_proxy_authmethod;
- ++
- ++ /** The remote_state that this remote belongs to. This is only meant to
- ++ * be used by remote_* functions. */
- ++ struct remote_state *remote_state;
- + };
- +
- + /**
- +@@ remote.h: struct branch {
- + int merge_alloc;
- +
- + const char *push_tracking_ref;
- ++
- ++ /** The remote_state that this branch belongs to. This is only meant to
- ++ * be used by branch_* functions. */
- ++ struct remote_state *remote_state;
- + };
- +
- + struct branch *branch_get(const char *name);
-3: ff12771f06 < -: ---------- remote: add struct repository parameter to external functions
--: ---------- > 3: 10fbb84496 remote: remove the_repository->remote_state from static methods
--: ---------- > 4: 4013f74fd9 remote: add struct repository parameter to external functions
+ @@ remote.h: struct remote_state {
+ };
+
+ void remote_state_clear(struct remote_state *remote_state);
+ -@@ remote.h: struct remote {
+ -
+ - /* The method used for authenticating against `http_proxy`. */
+ - char *http_proxy_authmethod;
+ -+
+ -+ /** The remote_state that this remote belongs to. This is only meant to
+ -+ * be used by remote_* functions. */
+ -+ struct remote_state *remote_state;
+ - };
+ -
+ - /**
+ -@@ remote.h: struct branch {
+ - int merge_alloc;
+ -
+ - const char *push_tracking_ref;
+ -+
+ -+ /** The remote_state that this branch belongs to. This is only meant to
+ -+ * be used by branch_* functions. */
+ -+ struct remote_state *remote_state;
+ - };
+ -
+ - struct branch *branch_get(const char *name);
+3: 10fbb84496 < -: ---------- remote: remove the_repository->remote_state from static methods
+4: 4013f74fd9 < -: ---------- remote: add struct repository parameter to external functions
+-: ---------- > 4: 53f2e31f72 remote: remove the_repository->remote_state from static methods
+-: ---------- > 5: d3281c14eb remote: die if branch is not found in repository
+-: ---------- > 6: 0974994cc6 remote: add struct repository parameter to external functions
--
2.33.GIT