>From Junio C Hamano, Tue 03 Mar 2020 at 10:21:31 (-0800) : > Mental note: this function was moved down, the main part of the > logic extracted to a new branch_get_push_remoteref() helper, which > in addition got extended. Exactly. > That's a fairly expensive way to write > if (remote->push.nr) > return apply_refspecs(&remote->push, branch->refname); > one-liner. You anticipated the question I asked afterwards :) > > + case PUSH_DEFAULT_UPSTREAM: > > + { > > + if (!branch || !branch->merge || > > + !branch->merge[0] || !branch->merge[0]->dst) > > + return NULL; > > + > > + return branch->merge[0]->src; > > + } > > This is strangely indented and somewhat unreadable. Why isn't this > more like: Sorry I missed the indentation for the return NULL. > case PUSH_DEFAULT_UPSTREAM: > if (branch && branch->merge && branch->merge[0] && > branch->merge[0]->dst) > return branch->merge[0]->src; > break; > > and have "return NULL" after the switch() statement before we leave > the function? We could, I agree this is more readable. If we return NULL after the switch, we need to put the > > + BUG("unhandled push situation") in a default clause a you say. The reason I wrote the code as above is to be as close as possible to `branch_get_push_1`. If we make the changes you suggest, I'll probably need a preliminary patch to change `branch_get_push_1` accordingly. > > + case PUSH_DEFAULT_UNSPECIFIED: > > + case PUSH_DEFAULT_SIMPLE: > > + { > > + const char *up, *cur; > > + > > + up = branch_get_upstream(branch, NULL); > > + if (!up) > > + return NULL; > > + cur = tracking_for_push_dest(remote, branch->refname, NULL); > > + if (!cur) > > + return NULL; > > + if (strcmp(cur, up)) > > + return NULL; > > This is probably not all that performance critical, so > up = branch_get_upstream(branch, NULL); > current = tracking_for_push_dest(remote, branch->refname, NULL); > if (!up || !current || strcmp(current, up)) > return NULL; > might be easier to follow. I don't mind but likewise in this case we should probably change branch_get_push_1 too. > By the way, I have a bit higher-level question. > > All of the above logic that decides what should happen in "git push" > MUST have existing code we already use to implement "git push", no? Yes. > Why do we need to reinvent it here, instead of reusing the existing > code? Is it because the interface into the functions that implement > the existing logic is very different from what this function wants? Mostly yes. The logic of git push is to massage the refspecs directly, for instance: case PUSH_DEFAULT_MATCHING: refspec_append(&rs, ":"); case PUSH_DEFAULT_CURRENT: ... strbuf_addf(&refspec, "%s:%s", branch->refname, branch->refname); case PUSH_DEFAULT_UPSTREAM: ... strbuf_addf(&refspec, "%s:%s", branch->refname, branch->merge[0]->src); And the error messages are also not the same, and to give a good error message we need to parse the different cases. It may be possible to refactorize all this, but not in an obvious way and it would be a lot more work than this patch series. -- Damien Robert http://www.normalesup.org/~robert/pro