diff options
author | Junio C Hamano <gitster@pobox.com> | 2018-08-02 15:30:41 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-08-02 15:30:41 -0700 |
commit | 50858edd1aa063d3ee2ecb48672c43630cea9070 (patch) | |
tree | 16e42089e479d0776ff94fa9621daf6f815a6668 /checkout.c | |
parent | a81575aa91a015535374bb5b1e0e6dc2a81c74ab (diff) | |
parent | 8d7b558baebe3abbbad4973ce1e1f87a7da17f47 (diff) | |
download | git-50858edd1aa063d3ee2ecb48672c43630cea9070.tar.gz |
Merge branch 'ab/checkout-default-remote'
"git checkout" and "git worktree add" learned to honor
checkout.defaultRemote when auto-vivifying a local branch out of a
remote tracking branch in a repository with multiple remotes that
have tracking branches that share the same names.
* ab/checkout-default-remote:
checkout & worktree: introduce checkout.defaultRemote
checkout: add advice for ambiguous "checkout <branch>"
builtin/checkout.c: use "ret" variable for return
checkout: pass the "num_matches" up to callers
checkout.c: change "unique" member to "num_matches"
checkout.c: introduce an *_INIT macro
checkout.h: wrap the arguments to unique_tracking_name()
checkout tests: index should be clean after dwim checkout
Diffstat (limited to 'checkout.c')
-rw-r--r-- | checkout.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/checkout.c b/checkout.c index bdefc888ba..c72e9f9773 100644 --- a/checkout.c +++ b/checkout.c @@ -2,14 +2,20 @@ #include "remote.h" #include "refspec.h" #include "checkout.h" +#include "config.h" struct tracking_name_data { /* const */ char *src_ref; char *dst_ref; struct object_id *dst_oid; - int unique; + int num_matches; + const char *default_remote; + char *default_dst_ref; + struct object_id *default_dst_oid; }; +#define TRACKING_NAME_DATA_INIT { NULL, NULL, NULL, 0, NULL, NULL, NULL } + static int check_tracking_name(struct remote *remote, void *cb_data) { struct tracking_name_data *cb = cb_data; @@ -21,24 +27,45 @@ static int check_tracking_name(struct remote *remote, void *cb_data) free(query.dst); return 0; } + cb->num_matches++; + if (cb->default_remote && !strcmp(remote->name, cb->default_remote)) { + struct object_id *dst = xmalloc(sizeof(*cb->default_dst_oid)); + cb->default_dst_ref = xstrdup(query.dst); + oidcpy(dst, cb->dst_oid); + cb->default_dst_oid = dst; + } if (cb->dst_ref) { free(query.dst); - cb->unique = 0; return 0; } cb->dst_ref = query.dst; return 0; } -const char *unique_tracking_name(const char *name, struct object_id *oid) +const char *unique_tracking_name(const char *name, struct object_id *oid, + int *dwim_remotes_matched) { - struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 }; + struct tracking_name_data cb_data = TRACKING_NAME_DATA_INIT; + const char *default_remote = NULL; + if (!git_config_get_string_const("checkout.defaultremote", &default_remote)) + cb_data.default_remote = default_remote; cb_data.src_ref = xstrfmt("refs/heads/%s", name); cb_data.dst_oid = oid; for_each_remote(check_tracking_name, &cb_data); + if (dwim_remotes_matched) + *dwim_remotes_matched = cb_data.num_matches; free(cb_data.src_ref); - if (cb_data.unique) + free((char *)default_remote); + if (cb_data.num_matches == 1) { + free(cb_data.default_dst_ref); + free(cb_data.default_dst_oid); return cb_data.dst_ref; + } free(cb_data.dst_ref); + if (cb_data.default_dst_ref) { + oidcpy(oid, cb_data.default_dst_oid); + free(cb_data.default_dst_oid); + return cb_data.default_dst_ref; + } return NULL; } |