branch.con commit transport.c: extract 'fill_alternate_refs_command' (1e5f31d)
   1#include "git-compat-util.h"
   2#include "cache.h"
   3#include "config.h"
   4#include "branch.h"
   5#include "refs.h"
   6#include "refspec.h"
   7#include "remote.h"
   8#include "commit.h"
   9#include "worktree.h"
  10
  11struct tracking {
  12        struct refspec_item spec;
  13        char *src;
  14        const char *remote;
  15        int matches;
  16};
  17
  18static int find_tracked_branch(struct remote *remote, void *priv)
  19{
  20        struct tracking *tracking = priv;
  21
  22        if (!remote_find_tracking(remote, &tracking->spec)) {
  23                if (++tracking->matches == 1) {
  24                        tracking->src = tracking->spec.src;
  25                        tracking->remote = remote->name;
  26                } else {
  27                        free(tracking->spec.src);
  28                        FREE_AND_NULL(tracking->src);
  29                }
  30                tracking->spec.src = NULL;
  31        }
  32
  33        return 0;
  34}
  35
  36static int should_setup_rebase(const char *origin)
  37{
  38        switch (autorebase) {
  39        case AUTOREBASE_NEVER:
  40                return 0;
  41        case AUTOREBASE_LOCAL:
  42                return origin == NULL;
  43        case AUTOREBASE_REMOTE:
  44                return origin != NULL;
  45        case AUTOREBASE_ALWAYS:
  46                return 1;
  47        }
  48        return 0;
  49}
  50
  51static const char tracking_advice[] =
  52N_("\n"
  53"After fixing the error cause you may try to fix up\n"
  54"the remote tracking information by invoking\n"
  55"\"git branch --set-upstream-to=%s%s%s\".");
  56
  57int install_branch_config(int flag, const char *local, const char *origin, const char *remote)
  58{
  59        const char *shortname = NULL;
  60        struct strbuf key = STRBUF_INIT;
  61        int rebasing = should_setup_rebase(origin);
  62
  63        if (skip_prefix(remote, "refs/heads/", &shortname)
  64            && !strcmp(local, shortname)
  65            && !origin) {
  66                warning(_("Not setting branch %s as its own upstream."),
  67                        local);
  68                return 0;
  69        }
  70
  71        strbuf_addf(&key, "branch.%s.remote", local);
  72        if (git_config_set_gently(key.buf, origin ? origin : ".") < 0)
  73                goto out_err;
  74
  75        strbuf_reset(&key);
  76        strbuf_addf(&key, "branch.%s.merge", local);
  77        if (git_config_set_gently(key.buf, remote) < 0)
  78                goto out_err;
  79
  80        if (rebasing) {
  81                strbuf_reset(&key);
  82                strbuf_addf(&key, "branch.%s.rebase", local);
  83                if (git_config_set_gently(key.buf, "true") < 0)
  84                        goto out_err;
  85        }
  86        strbuf_release(&key);
  87
  88        if (flag & BRANCH_CONFIG_VERBOSE) {
  89                if (shortname) {
  90                        if (origin)
  91                                printf_ln(rebasing ?
  92                                          _("Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.") :
  93                                          _("Branch '%s' set up to track remote branch '%s' from '%s'."),
  94                                          local, shortname, origin);
  95                        else
  96                                printf_ln(rebasing ?
  97                                          _("Branch '%s' set up to track local branch '%s' by rebasing.") :
  98                                          _("Branch '%s' set up to track local branch '%s'."),
  99                                          local, shortname);
 100                } else {
 101                        if (origin)
 102                                printf_ln(rebasing ?
 103                                          _("Branch '%s' set up to track remote ref '%s' by rebasing.") :
 104                                          _("Branch '%s' set up to track remote ref '%s'."),
 105                                          local, remote);
 106                        else
 107                                printf_ln(rebasing ?
 108                                          _("Branch '%s' set up to track local ref '%s' by rebasing.") :
 109                                          _("Branch '%s' set up to track local ref '%s'."),
 110                                          local, remote);
 111                }
 112        }
 113
 114        return 0;
 115
 116out_err:
 117        strbuf_release(&key);
 118        error(_("Unable to write upstream branch configuration"));
 119
 120        advise(_(tracking_advice),
 121               origin ? origin : "",
 122               origin ? "/" : "",
 123               shortname ? shortname : remote);
 124
 125        return -1;
 126}
 127
 128/*
 129 * This is called when new_ref is branched off of orig_ref, and tries
 130 * to infer the settings for branch.<new_ref>.{remote,merge} from the
 131 * config.
 132 */
 133static void setup_tracking(const char *new_ref, const char *orig_ref,
 134                           enum branch_track track, int quiet)
 135{
 136        struct tracking tracking;
 137        int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
 138
 139        memset(&tracking, 0, sizeof(tracking));
 140        tracking.spec.dst = (char *)orig_ref;
 141        if (for_each_remote(find_tracked_branch, &tracking))
 142                return;
 143
 144        if (!tracking.matches)
 145                switch (track) {
 146                case BRANCH_TRACK_ALWAYS:
 147                case BRANCH_TRACK_EXPLICIT:
 148                case BRANCH_TRACK_OVERRIDE:
 149                        break;
 150                default:
 151                        return;
 152                }
 153
 154        if (tracking.matches > 1)
 155                die(_("Not tracking: ambiguous information for ref %s"),
 156                    orig_ref);
 157
 158        if (install_branch_config(config_flags, new_ref, tracking.remote,
 159                              tracking.src ? tracking.src : orig_ref) < 0)
 160                exit(-1);
 161
 162        free(tracking.src);
 163}
 164
 165int read_branch_desc(struct strbuf *buf, const char *branch_name)
 166{
 167        char *v = NULL;
 168        struct strbuf name = STRBUF_INIT;
 169        strbuf_addf(&name, "branch.%s.description", branch_name);
 170        if (git_config_get_string(name.buf, &v)) {
 171                strbuf_release(&name);
 172                return -1;
 173        }
 174        strbuf_addstr(buf, v);
 175        free(v);
 176        strbuf_release(&name);
 177        return 0;
 178}
 179
 180/*
 181 * Check if 'name' can be a valid name for a branch; die otherwise.
 182 * Return 1 if the named branch already exists; return 0 otherwise.
 183 * Fill ref with the full refname for the branch.
 184 */
 185int validate_branchname(const char *name, struct strbuf *ref)
 186{
 187        if (strbuf_check_branch_ref(ref, name))
 188                die(_("'%s' is not a valid branch name."), name);
 189
 190        return ref_exists(ref->buf);
 191}
 192
 193/*
 194 * Check if a branch 'name' can be created as a new branch; die otherwise.
 195 * 'force' can be used when it is OK for the named branch already exists.
 196 * Return 1 if the named branch already exists; return 0 otherwise.
 197 * Fill ref with the full refname for the branch.
 198 */
 199int validate_new_branchname(const char *name, struct strbuf *ref, int force)
 200{
 201        const char *head;
 202
 203        if (!validate_branchname(name, ref))
 204                return 0;
 205
 206        if (!force)
 207                die(_("A branch named '%s' already exists."),
 208                    ref->buf + strlen("refs/heads/"));
 209
 210        head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
 211        if (!is_bare_repository() && head && !strcmp(head, ref->buf))
 212                die(_("Cannot force update the current branch."));
 213
 214        return 1;
 215}
 216
 217static int check_tracking_branch(struct remote *remote, void *cb_data)
 218{
 219        char *tracking_branch = cb_data;
 220        struct refspec_item query;
 221        memset(&query, 0, sizeof(struct refspec_item));
 222        query.dst = tracking_branch;
 223        return !remote_find_tracking(remote, &query);
 224}
 225
 226static int validate_remote_tracking_branch(char *ref)
 227{
 228        return !for_each_remote(check_tracking_branch, ref);
 229}
 230
 231static const char upstream_not_branch[] =
 232N_("Cannot setup tracking information; starting point '%s' is not a branch.");
 233static const char upstream_missing[] =
 234N_("the requested upstream branch '%s' does not exist");
 235static const char upstream_advice[] =
 236N_("\n"
 237"If you are planning on basing your work on an upstream\n"
 238"branch that already exists at the remote, you may need to\n"
 239"run \"git fetch\" to retrieve it.\n"
 240"\n"
 241"If you are planning to push out a new local branch that\n"
 242"will track its remote counterpart, you may want to use\n"
 243"\"git push -u\" to set the upstream config as you push.");
 244
 245void create_branch(const char *name, const char *start_name,
 246                   int force, int clobber_head_ok, int reflog,
 247                   int quiet, enum branch_track track)
 248{
 249        struct commit *commit;
 250        struct object_id oid;
 251        char *real_ref;
 252        struct strbuf ref = STRBUF_INIT;
 253        int forcing = 0;
 254        int dont_change_ref = 0;
 255        int explicit_tracking = 0;
 256
 257        if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
 258                explicit_tracking = 1;
 259
 260        if ((track == BRANCH_TRACK_OVERRIDE || clobber_head_ok)
 261            ? validate_branchname(name, &ref)
 262            : validate_new_branchname(name, &ref, force)) {
 263                if (!force)
 264                        dont_change_ref = 1;
 265                else
 266                        forcing = 1;
 267        }
 268
 269        real_ref = NULL;
 270        if (get_oid(start_name, &oid)) {
 271                if (explicit_tracking) {
 272                        if (advice_set_upstream_failure) {
 273                                error(_(upstream_missing), start_name);
 274                                advise(_(upstream_advice));
 275                                exit(1);
 276                        }
 277                        die(_(upstream_missing), start_name);
 278                }
 279                die(_("Not a valid object name: '%s'."), start_name);
 280        }
 281
 282        switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref)) {
 283        case 0:
 284                /* Not branching from any existing branch */
 285                if (explicit_tracking)
 286                        die(_(upstream_not_branch), start_name);
 287                break;
 288        case 1:
 289                /* Unique completion -- good, only if it is a real branch */
 290                if (!starts_with(real_ref, "refs/heads/") &&
 291                    validate_remote_tracking_branch(real_ref)) {
 292                        if (explicit_tracking)
 293                                die(_(upstream_not_branch), start_name);
 294                        else
 295                                real_ref = NULL;
 296                }
 297                break;
 298        default:
 299                die(_("Ambiguous object name: '%s'."), start_name);
 300                break;
 301        }
 302
 303        if ((commit = lookup_commit_reference(the_repository, &oid)) == NULL)
 304                die(_("Not a valid branch point: '%s'."), start_name);
 305        oidcpy(&oid, &commit->object.oid);
 306
 307        if (reflog)
 308                log_all_ref_updates = LOG_REFS_NORMAL;
 309
 310        if (!dont_change_ref) {
 311                struct ref_transaction *transaction;
 312                struct strbuf err = STRBUF_INIT;
 313                char *msg;
 314
 315                if (forcing)
 316                        msg = xstrfmt("branch: Reset to %s", start_name);
 317                else
 318                        msg = xstrfmt("branch: Created from %s", start_name);
 319
 320                transaction = ref_transaction_begin(&err);
 321                if (!transaction ||
 322                    ref_transaction_update(transaction, ref.buf,
 323                                           &oid, forcing ? NULL : &null_oid,
 324                                           0, msg, &err) ||
 325                    ref_transaction_commit(transaction, &err))
 326                        die("%s", err.buf);
 327                ref_transaction_free(transaction);
 328                strbuf_release(&err);
 329                free(msg);
 330        }
 331
 332        if (real_ref && track)
 333                setup_tracking(ref.buf + 11, real_ref, track, quiet);
 334
 335        strbuf_release(&ref);
 336        free(real_ref);
 337}
 338
 339void remove_branch_state(void)
 340{
 341        unlink(git_path_cherry_pick_head(the_repository));
 342        unlink(git_path_revert_head(the_repository));
 343        unlink(git_path_merge_head(the_repository));
 344        unlink(git_path_merge_rr(the_repository));
 345        unlink(git_path_merge_msg(the_repository));
 346        unlink(git_path_merge_mode(the_repository));
 347        unlink(git_path_squash_msg(the_repository));
 348}
 349
 350void die_if_checked_out(const char *branch, int ignore_current_worktree)
 351{
 352        const struct worktree *wt;
 353
 354        wt = find_shared_symref("HEAD", branch);
 355        if (!wt || (ignore_current_worktree && wt->is_current))
 356                return;
 357        skip_prefix(branch, "refs/heads/", &branch);
 358        die(_("'%s' is already checked out at '%s'"),
 359            branch, wt->path);
 360}
 361
 362int replace_each_worktree_head_symref(const char *oldref, const char *newref,
 363                                      const char *logmsg)
 364{
 365        int ret = 0;
 366        struct worktree **worktrees = get_worktrees(0);
 367        int i;
 368
 369        for (i = 0; worktrees[i]; i++) {
 370                struct ref_store *refs;
 371
 372                if (worktrees[i]->is_detached)
 373                        continue;
 374                if (!worktrees[i]->head_ref)
 375                        continue;
 376                if (strcmp(oldref, worktrees[i]->head_ref))
 377                        continue;
 378
 379                refs = get_worktree_ref_store(worktrees[i]);
 380                if (refs_create_symref(refs, "HEAD", newref, logmsg))
 381                        ret = error(_("HEAD of working tree %s is not updated"),
 382                                    worktrees[i]->path);
 383        }
 384
 385        free_worktrees(worktrees);
 386        return ret;
 387}