branch.con commit Merge branch 'jk/cat-file-regression-fix' (604ada4)
   1#include "cache.h"
   2#include "branch.h"
   3#include "refs.h"
   4#include "remote.h"
   5#include "commit.h"
   6
   7struct tracking {
   8        struct refspec spec;
   9        char *src;
  10        const char *remote;
  11        int matches;
  12};
  13
  14static int find_tracked_branch(struct remote *remote, void *priv)
  15{
  16        struct tracking *tracking = priv;
  17
  18        if (!remote_find_tracking(remote, &tracking->spec)) {
  19                if (++tracking->matches == 1) {
  20                        tracking->src = tracking->spec.src;
  21                        tracking->remote = remote->name;
  22                } else {
  23                        free(tracking->spec.src);
  24                        if (tracking->src) {
  25                                free(tracking->src);
  26                                tracking->src = NULL;
  27                        }
  28                }
  29                tracking->spec.src = NULL;
  30        }
  31
  32        return 0;
  33}
  34
  35static int should_setup_rebase(const char *origin)
  36{
  37        switch (autorebase) {
  38        case AUTOREBASE_NEVER:
  39                return 0;
  40        case AUTOREBASE_LOCAL:
  41                return origin == NULL;
  42        case AUTOREBASE_REMOTE:
  43                return origin != NULL;
  44        case AUTOREBASE_ALWAYS:
  45                return 1;
  46        }
  47        return 0;
  48}
  49
  50void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
  51{
  52        const char *shortname = remote + 11;
  53        int remote_is_branch = starts_with(remote, "refs/heads/");
  54        struct strbuf key = STRBUF_INIT;
  55        int rebasing = should_setup_rebase(origin);
  56
  57        if (remote_is_branch
  58            && !strcmp(local, shortname)
  59            && !origin) {
  60                warning(_("Not setting branch %s as its own upstream."),
  61                        local);
  62                return;
  63        }
  64
  65        strbuf_addf(&key, "branch.%s.remote", local);
  66        git_config_set(key.buf, origin ? origin : ".");
  67
  68        strbuf_reset(&key);
  69        strbuf_addf(&key, "branch.%s.merge", local);
  70        git_config_set(key.buf, remote);
  71
  72        if (rebasing) {
  73                strbuf_reset(&key);
  74                strbuf_addf(&key, "branch.%s.rebase", local);
  75                git_config_set(key.buf, "true");
  76        }
  77        strbuf_release(&key);
  78
  79        if (flag & BRANCH_CONFIG_VERBOSE) {
  80                if (remote_is_branch && origin)
  81                        printf_ln(rebasing ?
  82                                  _("Branch %s set up to track remote branch %s from %s by rebasing.") :
  83                                  _("Branch %s set up to track remote branch %s from %s."),
  84                                  local, shortname, origin);
  85                else if (remote_is_branch && !origin)
  86                        printf_ln(rebasing ?
  87                                  _("Branch %s set up to track local branch %s by rebasing.") :
  88                                  _("Branch %s set up to track local branch %s."),
  89                                  local, shortname);
  90                else if (!remote_is_branch && origin)
  91                        printf_ln(rebasing ?
  92                                  _("Branch %s set up to track remote ref %s by rebasing.") :
  93                                  _("Branch %s set up to track remote ref %s."),
  94                                  local, remote);
  95                else if (!remote_is_branch && !origin)
  96                        printf_ln(rebasing ?
  97                                  _("Branch %s set up to track local ref %s by rebasing.") :
  98                                  _("Branch %s set up to track local ref %s."),
  99                                  local, remote);
 100                else
 101                        die("BUG: impossible combination of %d and %p",
 102                            remote_is_branch, origin);
 103        }
 104}
 105
 106/*
 107 * This is called when new_ref is branched off of orig_ref, and tries
 108 * to infer the settings for branch.<new_ref>.{remote,merge} from the
 109 * config.
 110 */
 111static int setup_tracking(const char *new_ref, const char *orig_ref,
 112                          enum branch_track track, int quiet)
 113{
 114        struct tracking tracking;
 115        int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
 116
 117        if (strlen(new_ref) > 1024 - 7 - 7 - 1)
 118                return error(_("Tracking not set up: name too long: %s"),
 119                                new_ref);
 120
 121        memset(&tracking, 0, sizeof(tracking));
 122        tracking.spec.dst = (char *)orig_ref;
 123        if (for_each_remote(find_tracked_branch, &tracking))
 124                return 1;
 125
 126        if (!tracking.matches)
 127                switch (track) {
 128                case BRANCH_TRACK_ALWAYS:
 129                case BRANCH_TRACK_EXPLICIT:
 130                case BRANCH_TRACK_OVERRIDE:
 131                        break;
 132                default:
 133                        return 1;
 134                }
 135
 136        if (tracking.matches > 1)
 137                return error(_("Not tracking: ambiguous information for ref %s"),
 138                                orig_ref);
 139
 140        install_branch_config(config_flags, new_ref, tracking.remote,
 141                              tracking.src ? tracking.src : orig_ref);
 142
 143        free(tracking.src);
 144        return 0;
 145}
 146
 147struct branch_desc_cb {
 148        const char *config_name;
 149        const char *value;
 150};
 151
 152static int read_branch_desc_cb(const char *var, const char *value, void *cb)
 153{
 154        struct branch_desc_cb *desc = cb;
 155        if (strcmp(desc->config_name, var))
 156                return 0;
 157        free((char *)desc->value);
 158        return git_config_string(&desc->value, var, value);
 159}
 160
 161int read_branch_desc(struct strbuf *buf, const char *branch_name)
 162{
 163        struct branch_desc_cb cb;
 164        struct strbuf name = STRBUF_INIT;
 165        strbuf_addf(&name, "branch.%s.description", branch_name);
 166        cb.config_name = name.buf;
 167        cb.value = NULL;
 168        if (git_config(read_branch_desc_cb, &cb) < 0) {
 169                strbuf_release(&name);
 170                return -1;
 171        }
 172        if (cb.value)
 173                strbuf_addstr(buf, cb.value);
 174        strbuf_release(&name);
 175        return 0;
 176}
 177
 178int validate_new_branchname(const char *name, struct strbuf *ref,
 179                            int force, int attr_only)
 180{
 181        if (strbuf_check_branch_ref(ref, name))
 182                die(_("'%s' is not a valid branch name."), name);
 183
 184        if (!ref_exists(ref->buf))
 185                return 0;
 186        else if (!force && !attr_only)
 187                die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
 188
 189        if (!attr_only) {
 190                const char *head;
 191                unsigned char sha1[20];
 192
 193                head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
 194                if (!is_bare_repository() && head && !strcmp(head, ref->buf))
 195                        die(_("Cannot force update the current branch."));
 196        }
 197        return 1;
 198}
 199
 200static int check_tracking_branch(struct remote *remote, void *cb_data)
 201{
 202        char *tracking_branch = cb_data;
 203        struct refspec query;
 204        memset(&query, 0, sizeof(struct refspec));
 205        query.dst = tracking_branch;
 206        return !remote_find_tracking(remote, &query);
 207}
 208
 209static int validate_remote_tracking_branch(char *ref)
 210{
 211        return !for_each_remote(check_tracking_branch, ref);
 212}
 213
 214static const char upstream_not_branch[] =
 215N_("Cannot setup tracking information; starting point '%s' is not a branch.");
 216static const char upstream_missing[] =
 217N_("the requested upstream branch '%s' does not exist");
 218static const char upstream_advice[] =
 219N_("\n"
 220"If you are planning on basing your work on an upstream\n"
 221"branch that already exists at the remote, you may need to\n"
 222"run \"git fetch\" to retrieve it.\n"
 223"\n"
 224"If you are planning to push out a new local branch that\n"
 225"will track its remote counterpart, you may want to use\n"
 226"\"git push -u\" to set the upstream config as you push.");
 227
 228void create_branch(const char *head,
 229                   const char *name, const char *start_name,
 230                   int force, int reflog, int clobber_head,
 231                   int quiet, enum branch_track track)
 232{
 233        struct ref_lock *lock = NULL;
 234        struct commit *commit;
 235        unsigned char sha1[20];
 236        char *real_ref, msg[PATH_MAX + 20];
 237        struct strbuf ref = STRBUF_INIT;
 238        int forcing = 0;
 239        int dont_change_ref = 0;
 240        int explicit_tracking = 0;
 241
 242        if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
 243                explicit_tracking = 1;
 244
 245        if (validate_new_branchname(name, &ref, force,
 246                                    track == BRANCH_TRACK_OVERRIDE ||
 247                                    clobber_head)) {
 248                if (!force)
 249                        dont_change_ref = 1;
 250                else
 251                        forcing = 1;
 252        }
 253
 254        real_ref = NULL;
 255        if (get_sha1(start_name, sha1)) {
 256                if (explicit_tracking) {
 257                        if (advice_set_upstream_failure) {
 258                                error(_(upstream_missing), start_name);
 259                                advise(_(upstream_advice));
 260                                exit(1);
 261                        }
 262                        die(_(upstream_missing), start_name);
 263                }
 264                die(_("Not a valid object name: '%s'."), start_name);
 265        }
 266
 267        switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
 268        case 0:
 269                /* Not branching from any existing branch */
 270                if (explicit_tracking)
 271                        die(_(upstream_not_branch), start_name);
 272                break;
 273        case 1:
 274                /* Unique completion -- good, only if it is a real branch */
 275                if (!starts_with(real_ref, "refs/heads/") &&
 276                    validate_remote_tracking_branch(real_ref)) {
 277                        if (explicit_tracking)
 278                                die(_(upstream_not_branch), start_name);
 279                        else
 280                                real_ref = NULL;
 281                }
 282                break;
 283        default:
 284                die(_("Ambiguous object name: '%s'."), start_name);
 285                break;
 286        }
 287
 288        if ((commit = lookup_commit_reference(sha1)) == NULL)
 289                die(_("Not a valid branch point: '%s'."), start_name);
 290        hashcpy(sha1, commit->object.sha1);
 291
 292        if (!dont_change_ref) {
 293                lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL);
 294                if (!lock)
 295                        die_errno(_("Failed to lock ref for update"));
 296        }
 297
 298        if (reflog)
 299                log_all_ref_updates = 1;
 300
 301        if (forcing)
 302                snprintf(msg, sizeof msg, "branch: Reset to %s",
 303                         start_name);
 304        else if (!dont_change_ref)
 305                snprintf(msg, sizeof msg, "branch: Created from %s",
 306                         start_name);
 307
 308        if (real_ref && track)
 309                setup_tracking(ref.buf + 11, real_ref, track, quiet);
 310
 311        if (!dont_change_ref)
 312                if (write_ref_sha1(lock, sha1, msg) < 0)
 313                        die_errno(_("Failed to write ref"));
 314
 315        strbuf_release(&ref);
 316        free(real_ref);
 317}
 318
 319void remove_branch_state(void)
 320{
 321        unlink(git_path("CHERRY_PICK_HEAD"));
 322        unlink(git_path("REVERT_HEAD"));
 323        unlink(git_path("MERGE_HEAD"));
 324        unlink(git_path("MERGE_RR"));
 325        unlink(git_path("MERGE_MSG"));
 326        unlink(git_path("MERGE_MODE"));
 327        unlink(git_path("SQUASH_MSG"));
 328}