branch.con commit coccinelle: polish FREE_AND_NULL rules (76d8d45)
   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#include "worktree.h"
   8
   9struct tracking {
  10        struct refspec spec;
  11        char *src;
  12        const char *remote;
  13        int matches;
  14};
  15
  16static int find_tracked_branch(struct remote *remote, void *priv)
  17{
  18        struct tracking *tracking = priv;
  19
  20        if (!remote_find_tracking(remote, &tracking->spec)) {
  21                if (++tracking->matches == 1) {
  22                        tracking->src = tracking->spec.src;
  23                        tracking->remote = remote->name;
  24                } else {
  25                        free(tracking->spec.src);
  26                        if (tracking->src) {
  27                                FREE_AND_NULL(tracking->src);
  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
  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
 180int validate_new_branchname(const char *name, struct strbuf *ref,
 181                            int force, int attr_only)
 182{
 183        if (strbuf_check_branch_ref(ref, name))
 184                die(_("'%s' is not a valid branch name."), name);
 185
 186        if (!ref_exists(ref->buf))
 187                return 0;
 188        else if (!force && !attr_only)
 189                die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
 190
 191        if (!attr_only) {
 192                const char *head;
 193                struct object_id oid;
 194
 195                head = resolve_ref_unsafe("HEAD", 0, oid.hash, NULL);
 196                if (!is_bare_repository() && head && !strcmp(head, ref->buf))
 197                        die(_("Cannot force update the current branch."));
 198        }
 199        return 1;
 200}
 201
 202static int check_tracking_branch(struct remote *remote, void *cb_data)
 203{
 204        char *tracking_branch = cb_data;
 205        struct refspec query;
 206        memset(&query, 0, sizeof(struct refspec));
 207        query.dst = tracking_branch;
 208        return !remote_find_tracking(remote, &query);
 209}
 210
 211static int validate_remote_tracking_branch(char *ref)
 212{
 213        return !for_each_remote(check_tracking_branch, ref);
 214}
 215
 216static const char upstream_not_branch[] =
 217N_("Cannot setup tracking information; starting point '%s' is not a branch.");
 218static const char upstream_missing[] =
 219N_("the requested upstream branch '%s' does not exist");
 220static const char upstream_advice[] =
 221N_("\n"
 222"If you are planning on basing your work on an upstream\n"
 223"branch that already exists at the remote, you may need to\n"
 224"run \"git fetch\" to retrieve it.\n"
 225"\n"
 226"If you are planning to push out a new local branch that\n"
 227"will track its remote counterpart, you may want to use\n"
 228"\"git push -u\" to set the upstream config as you push.");
 229
 230void create_branch(const char *name, const char *start_name,
 231                   int force, int reflog, int clobber_head,
 232                   int quiet, enum branch_track track)
 233{
 234        struct commit *commit;
 235        struct object_id oid;
 236        char *real_ref;
 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_oid(start_name, &oid)) {
 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), oid.hash, &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(&oid)) == NULL)
 289                die(_("Not a valid branch point: '%s'."), start_name);
 290        oidcpy(&oid, &commit->object.oid);
 291
 292        if (reflog)
 293                log_all_ref_updates = LOG_REFS_NORMAL;
 294
 295        if (!dont_change_ref) {
 296                struct ref_transaction *transaction;
 297                struct strbuf err = STRBUF_INIT;
 298                char *msg;
 299
 300                if (forcing)
 301                        msg = xstrfmt("branch: Reset to %s", start_name);
 302                else
 303                        msg = xstrfmt("branch: Created from %s", start_name);
 304
 305                transaction = ref_transaction_begin(&err);
 306                if (!transaction ||
 307                    ref_transaction_update(transaction, ref.buf,
 308                                           oid.hash, forcing ? NULL : null_sha1,
 309                                           0, msg, &err) ||
 310                    ref_transaction_commit(transaction, &err))
 311                        die("%s", err.buf);
 312                ref_transaction_free(transaction);
 313                strbuf_release(&err);
 314                free(msg);
 315        }
 316
 317        if (real_ref && track)
 318                setup_tracking(ref.buf + 11, real_ref, track, quiet);
 319
 320        strbuf_release(&ref);
 321        free(real_ref);
 322}
 323
 324void remove_branch_state(void)
 325{
 326        unlink(git_path_cherry_pick_head());
 327        unlink(git_path_revert_head());
 328        unlink(git_path_merge_head());
 329        unlink(git_path_merge_rr());
 330        unlink(git_path_merge_msg());
 331        unlink(git_path_merge_mode());
 332        unlink(git_path_squash_msg());
 333}
 334
 335void die_if_checked_out(const char *branch, int ignore_current_worktree)
 336{
 337        const struct worktree *wt;
 338
 339        wt = find_shared_symref("HEAD", branch);
 340        if (!wt || (ignore_current_worktree && wt->is_current))
 341                return;
 342        skip_prefix(branch, "refs/heads/", &branch);
 343        die(_("'%s' is already checked out at '%s'"),
 344            branch, wt->path);
 345}
 346
 347int replace_each_worktree_head_symref(const char *oldref, const char *newref,
 348                                      const char *logmsg)
 349{
 350        int ret = 0;
 351        struct worktree **worktrees = get_worktrees(0);
 352        int i;
 353
 354        for (i = 0; worktrees[i]; i++) {
 355                struct ref_store *refs;
 356
 357                if (worktrees[i]->is_detached)
 358                        continue;
 359                if (worktrees[i]->head_ref &&
 360                    strcmp(oldref, worktrees[i]->head_ref))
 361                        continue;
 362
 363                refs = get_worktree_ref_store(worktrees[i]);
 364                if (refs_create_symref(refs, "HEAD", newref, logmsg))
 365                        ret = error(_("HEAD of working tree %s is not updated"),
 366                                    worktrees[i]->path);
 367        }
 368
 369        free_worktrees(worktrees);
 370        return ret;
 371}