branch.con commit change `git_config()` return value to void (aace438)
   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
 143struct branch_desc_cb {
 144        const char *config_name;
 145        const char *value;
 146};
 147
 148static int read_branch_desc_cb(const char *var, const char *value, void *cb)
 149{
 150        struct branch_desc_cb *desc = cb;
 151        if (strcmp(desc->config_name, var))
 152                return 0;
 153        free((char *)desc->value);
 154        return git_config_string(&desc->value, var, value);
 155}
 156
 157int read_branch_desc(struct strbuf *buf, const char *branch_name)
 158{
 159        struct branch_desc_cb cb;
 160        struct strbuf name = STRBUF_INIT;
 161        strbuf_addf(&name, "branch.%s.description", branch_name);
 162        cb.config_name = name.buf;
 163        cb.value = NULL;
 164        git_config(read_branch_desc_cb, &cb);
 165        if (cb.value)
 166                strbuf_addstr(buf, cb.value);
 167        strbuf_release(&name);
 168        return 0;
 169}
 170
 171int validate_new_branchname(const char *name, struct strbuf *ref,
 172                            int force, int attr_only)
 173{
 174        if (strbuf_check_branch_ref(ref, name))
 175                die(_("'%s' is not a valid branch name."), name);
 176
 177        if (!ref_exists(ref->buf))
 178                return 0;
 179        else if (!force && !attr_only)
 180                die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
 181
 182        if (!attr_only) {
 183                const char *head;
 184                unsigned char sha1[20];
 185
 186                head = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
 187                if (!is_bare_repository() && head && !strcmp(head, ref->buf))
 188                        die(_("Cannot force update the current branch."));
 189        }
 190        return 1;
 191}
 192
 193static int check_tracking_branch(struct remote *remote, void *cb_data)
 194{
 195        char *tracking_branch = cb_data;
 196        struct refspec query;
 197        memset(&query, 0, sizeof(struct refspec));
 198        query.dst = tracking_branch;
 199        return !remote_find_tracking(remote, &query);
 200}
 201
 202static int validate_remote_tracking_branch(char *ref)
 203{
 204        return !for_each_remote(check_tracking_branch, ref);
 205}
 206
 207static const char upstream_not_branch[] =
 208N_("Cannot setup tracking information; starting point '%s' is not a branch.");
 209static const char upstream_missing[] =
 210N_("the requested upstream branch '%s' does not exist");
 211static const char upstream_advice[] =
 212N_("\n"
 213"If you are planning on basing your work on an upstream\n"
 214"branch that already exists at the remote, you may need to\n"
 215"run \"git fetch\" to retrieve it.\n"
 216"\n"
 217"If you are planning to push out a new local branch that\n"
 218"will track its remote counterpart, you may want to use\n"
 219"\"git push -u\" to set the upstream config as you push.");
 220
 221void create_branch(const char *head,
 222                   const char *name, const char *start_name,
 223                   int force, int reflog, int clobber_head,
 224                   int quiet, enum branch_track track)
 225{
 226        struct ref_lock *lock = NULL;
 227        struct commit *commit;
 228        unsigned char sha1[20];
 229        char *real_ref, msg[PATH_MAX + 20];
 230        struct strbuf ref = STRBUF_INIT;
 231        int forcing = 0;
 232        int dont_change_ref = 0;
 233        int explicit_tracking = 0;
 234
 235        if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
 236                explicit_tracking = 1;
 237
 238        if (validate_new_branchname(name, &ref, force,
 239                                    track == BRANCH_TRACK_OVERRIDE ||
 240                                    clobber_head)) {
 241                if (!force)
 242                        dont_change_ref = 1;
 243                else
 244                        forcing = 1;
 245        }
 246
 247        real_ref = NULL;
 248        if (get_sha1(start_name, sha1)) {
 249                if (explicit_tracking) {
 250                        if (advice_set_upstream_failure) {
 251                                error(_(upstream_missing), start_name);
 252                                advise(_(upstream_advice));
 253                                exit(1);
 254                        }
 255                        die(_(upstream_missing), start_name);
 256                }
 257                die(_("Not a valid object name: '%s'."), start_name);
 258        }
 259
 260        switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
 261        case 0:
 262                /* Not branching from any existing branch */
 263                if (explicit_tracking)
 264                        die(_(upstream_not_branch), start_name);
 265                break;
 266        case 1:
 267                /* Unique completion -- good, only if it is a real branch */
 268                if (!starts_with(real_ref, "refs/heads/") &&
 269                    validate_remote_tracking_branch(real_ref)) {
 270                        if (explicit_tracking)
 271                                die(_(upstream_not_branch), start_name);
 272                        else
 273                                real_ref = NULL;
 274                }
 275                break;
 276        default:
 277                die(_("Ambiguous object name: '%s'."), start_name);
 278                break;
 279        }
 280
 281        if ((commit = lookup_commit_reference(sha1)) == NULL)
 282                die(_("Not a valid branch point: '%s'."), start_name);
 283        hashcpy(sha1, commit->object.sha1);
 284
 285        if (!dont_change_ref) {
 286                lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL);
 287                if (!lock)
 288                        die_errno(_("Failed to lock ref for update"));
 289        }
 290
 291        if (reflog)
 292                log_all_ref_updates = 1;
 293
 294        if (forcing)
 295                snprintf(msg, sizeof msg, "branch: Reset to %s",
 296                         start_name);
 297        else if (!dont_change_ref)
 298                snprintf(msg, sizeof msg, "branch: Created from %s",
 299                         start_name);
 300
 301        if (real_ref && track)
 302                setup_tracking(ref.buf + 11, real_ref, track, quiet);
 303
 304        if (!dont_change_ref)
 305                if (write_ref_sha1(lock, sha1, msg) < 0)
 306                        die_errno(_("Failed to write ref"));
 307
 308        strbuf_release(&ref);
 309        free(real_ref);
 310}
 311
 312void remove_branch_state(void)
 313{
 314        unlink(git_path("CHERRY_PICK_HEAD"));
 315        unlink(git_path("REVERT_HEAD"));
 316        unlink(git_path("MERGE_HEAD"));
 317        unlink(git_path("MERGE_RR"));
 318        unlink(git_path("MERGE_MSG"));
 319        unlink(git_path("MERGE_MODE"));
 320        unlink(git_path("SQUASH_MSG"));
 321}