branch.con commit Merge branch 'jk/contrib-subtree-make-all' (49feda6)
   1#include "git-compat-util.h"
   2#include "cache.h"
   3#include "branch.h"
   4#include "refs.h"
   5#include "remote.h"
   6#include "commit.h"
   7
   8struct tracking {
   9        struct refspec spec;
  10        char *src;
  11        const char *remote;
  12        int matches;
  13};
  14
  15static int find_tracked_branch(struct remote *remote, void *priv)
  16{
  17        struct tracking *tracking = priv;
  18
  19        if (!remote_find_tracking(remote, &tracking->spec)) {
  20                if (++tracking->matches == 1) {
  21                        tracking->src = tracking->spec.src;
  22                        tracking->remote = remote->name;
  23                } else {
  24                        free(tracking->spec.src);
  25                        if (tracking->src) {
  26                                free(tracking->src);
  27                                tracking->src = NULL;
  28                        }
  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
  51void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
  52{
  53        const char *shortname = NULL;
  54        struct strbuf key = STRBUF_INIT;
  55        int rebasing = should_setup_rebase(origin);
  56
  57        if (skip_prefix(remote, "refs/heads/", &shortname)
  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 (shortname) {
  81                        if (origin)
  82                                printf_ln(rebasing ?
  83                                          _("Branch %s set up to track remote branch %s from %s by rebasing.") :
  84                                          _("Branch %s set up to track remote branch %s from %s."),
  85                                          local, shortname, origin);
  86                        else
  87                                printf_ln(rebasing ?
  88                                          _("Branch %s set up to track local branch %s by rebasing.") :
  89                                          _("Branch %s set up to track local branch %s."),
  90                                          local, shortname);
  91                } else {
  92                        if (origin)
  93                                printf_ln(rebasing ?
  94                                          _("Branch %s set up to track remote ref %s by rebasing.") :
  95                                          _("Branch %s set up to track remote ref %s."),
  96                                          local, remote);
  97                        else
  98                                printf_ln(rebasing ?
  99                                          _("Branch %s set up to track local ref %s by rebasing.") :
 100                                          _("Branch %s set up to track local ref %s."),
 101                                          local, remote);
 102                }
 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        memset(&tracking, 0, sizeof(tracking));
 118        tracking.spec.dst = (char *)orig_ref;
 119        if (for_each_remote(find_tracked_branch, &tracking))
 120                return 1;
 121
 122        if (!tracking.matches)
 123                switch (track) {
 124                case BRANCH_TRACK_ALWAYS:
 125                case BRANCH_TRACK_EXPLICIT:
 126                case BRANCH_TRACK_OVERRIDE:
 127                        break;
 128                default:
 129                        return 1;
 130                }
 131
 132        if (tracking.matches > 1)
 133                return error(_("Not tracking: ambiguous information for ref %s"),
 134                                orig_ref);
 135
 136        install_branch_config(config_flags, new_ref, tracking.remote,
 137                              tracking.src ? tracking.src : orig_ref);
 138
 139        free(tracking.src);
 140        return 0;
 141}
 142
 143int read_branch_desc(struct strbuf *buf, const char *branch_name)
 144{
 145        char *v = NULL;
 146        struct strbuf name = STRBUF_INIT;
 147        strbuf_addf(&name, "branch.%s.description", branch_name);
 148        if (git_config_get_string(name.buf, &v)) {
 149                strbuf_release(&name);
 150                return -1;
 151        }
 152        strbuf_addstr(buf, v);
 153        free(v);
 154        strbuf_release(&name);
 155        return 0;
 156}
 157
 158int validate_new_branchname(const char *name, struct strbuf *ref,
 159                            int force, int attr_only)
 160{
 161        if (strbuf_check_branch_ref(ref, name))
 162                die(_("'%s' is not a valid branch name."), name);
 163
 164        if (!ref_exists(ref->buf))
 165                return 0;
 166        else if (!force && !attr_only)
 167                die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
 168
 169        if (!attr_only) {
 170                const char *head;
 171                unsigned char sha1[20];
 172
 173                head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
 174                if (!is_bare_repository() && head && !strcmp(head, ref->buf))
 175                        die(_("Cannot force update the current branch."));
 176        }
 177        return 1;
 178}
 179
 180static int check_tracking_branch(struct remote *remote, void *cb_data)
 181{
 182        char *tracking_branch = cb_data;
 183        struct refspec query;
 184        memset(&query, 0, sizeof(struct refspec));
 185        query.dst = tracking_branch;
 186        return !remote_find_tracking(remote, &query);
 187}
 188
 189static int validate_remote_tracking_branch(char *ref)
 190{
 191        return !for_each_remote(check_tracking_branch, ref);
 192}
 193
 194static const char upstream_not_branch[] =
 195N_("Cannot setup tracking information; starting point '%s' is not a branch.");
 196static const char upstream_missing[] =
 197N_("the requested upstream branch '%s' does not exist");
 198static const char upstream_advice[] =
 199N_("\n"
 200"If you are planning on basing your work on an upstream\n"
 201"branch that already exists at the remote, you may need to\n"
 202"run \"git fetch\" to retrieve it.\n"
 203"\n"
 204"If you are planning to push out a new local branch that\n"
 205"will track its remote counterpart, you may want to use\n"
 206"\"git push -u\" to set the upstream config as you push.");
 207
 208void create_branch(const char *head,
 209                   const char *name, const char *start_name,
 210                   int force, int reflog, int clobber_head,
 211                   int quiet, enum branch_track track)
 212{
 213        struct ref_lock *lock = NULL;
 214        struct commit *commit;
 215        unsigned char sha1[20];
 216        char *real_ref, msg[PATH_MAX + 20];
 217        struct strbuf ref = STRBUF_INIT;
 218        int forcing = 0;
 219        int dont_change_ref = 0;
 220        int explicit_tracking = 0;
 221
 222        if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
 223                explicit_tracking = 1;
 224
 225        if (validate_new_branchname(name, &ref, force,
 226                                    track == BRANCH_TRACK_OVERRIDE ||
 227                                    clobber_head)) {
 228                if (!force)
 229                        dont_change_ref = 1;
 230                else
 231                        forcing = 1;
 232        }
 233
 234        real_ref = NULL;
 235        if (get_sha1(start_name, sha1)) {
 236                if (explicit_tracking) {
 237                        if (advice_set_upstream_failure) {
 238                                error(_(upstream_missing), start_name);
 239                                advise(_(upstream_advice));
 240                                exit(1);
 241                        }
 242                        die(_(upstream_missing), start_name);
 243                }
 244                die(_("Not a valid object name: '%s'."), start_name);
 245        }
 246
 247        switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
 248        case 0:
 249                /* Not branching from any existing branch */
 250                if (explicit_tracking)
 251                        die(_(upstream_not_branch), start_name);
 252                break;
 253        case 1:
 254                /* Unique completion -- good, only if it is a real branch */
 255                if (!starts_with(real_ref, "refs/heads/") &&
 256                    validate_remote_tracking_branch(real_ref)) {
 257                        if (explicit_tracking)
 258                                die(_(upstream_not_branch), start_name);
 259                        else
 260                                real_ref = NULL;
 261                }
 262                break;
 263        default:
 264                die(_("Ambiguous object name: '%s'."), start_name);
 265                break;
 266        }
 267
 268        if ((commit = lookup_commit_reference(sha1)) == NULL)
 269                die(_("Not a valid branch point: '%s'."), start_name);
 270        hashcpy(sha1, commit->object.sha1);
 271
 272        if (!dont_change_ref) {
 273                lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL);
 274                if (!lock)
 275                        die_errno(_("Failed to lock ref for update"));
 276        }
 277
 278        if (reflog)
 279                log_all_ref_updates = 1;
 280
 281        if (forcing)
 282                snprintf(msg, sizeof msg, "branch: Reset to %s",
 283                         start_name);
 284        else if (!dont_change_ref)
 285                snprintf(msg, sizeof msg, "branch: Created from %s",
 286                         start_name);
 287
 288        if (real_ref && track)
 289                setup_tracking(ref.buf + 11, real_ref, track, quiet);
 290
 291        if (!dont_change_ref)
 292                if (write_ref_sha1(lock, sha1, msg) < 0)
 293                        die_errno(_("Failed to write ref"));
 294
 295        strbuf_release(&ref);
 296        free(real_ref);
 297}
 298
 299void remove_branch_state(void)
 300{
 301        unlink(git_path("CHERRY_PICK_HEAD"));
 302        unlink(git_path("REVERT_HEAD"));
 303        unlink(git_path("MERGE_HEAD"));
 304        unlink(git_path("MERGE_RR"));
 305        unlink(git_path("MERGE_MSG"));
 306        unlink(git_path("MERGE_MODE"));
 307        unlink(git_path("SQUASH_MSG"));
 308}