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