static void setup_default_push_refspecs(struct remote *remote) { struct branch *branch = branch_get(NULL); int triangular = is_workflow_triangular(remote); switch (push_default) { default: case PUSH_DEFAULT_MATCHING: add_refspec(":"); break; case PUSH_DEFAULT_UNSPECIFIED: case PUSH_DEFAULT_SIMPLE: if (triangular) setup_push_current(remote, branch); else setup_push_upstream(remote, branch, triangular, 1); break; case PUSH_DEFAULT_UPSTREAM: setup_push_upstream(remote, branch, triangular, 0); break; case PUSH_DEFAULT_CURRENT: setup_push_current(remote, branch); break; case PUSH_DEFAULT_NOTHING: die(_("You didn't specify any refspecs to push, and " "push.default is \"nothing\".")); break; } }
static void set_refspecs(const char **refs, int nr) { int i; for (i = 0; i < nr; i++) { const char *ref = refs[i]; if (!strcmp("tag", ref)) { char *tag; int len; if (nr <= ++i) die(_("tag shorthand without <tag>")); len = strlen(refs[i]) + 11; if (deleterefs) { tag = xmalloc(len+1); strcpy(tag, ":refs/tags/"); } else { tag = xmalloc(len); strcpy(tag, "refs/tags/"); } strcat(tag, refs[i]); ref = tag; } else if (deleterefs && !strchr(ref, ':')) { char *delref; int len = strlen(ref)+1; delref = xmalloc(len+1); strcpy(delref, ":"); strcat(delref, ref); ref = delref; } else if (deleterefs) die(_("--delete only accepts plain target ref names")); add_refspec(ref); } }
static void setup_push_upstream(struct remote *remote, struct branch *branch, int triangular, int simple) { struct strbuf refspec = STRBUF_INIT; if (!branch) die(_(message_detached_head_die), remote->name); if (!branch->merge_nr || !branch->merge || !branch->remote_name) die(_("The current branch %s has no upstream branch.\n" "To push the current branch and set the remote as upstream, use\n" "\n" " git push --set-upstream %s %s\n"), branch->name, remote->name, branch->name); if (branch->merge_nr != 1) die(_("The current branch %s has multiple upstream branches, " "refusing to push."), branch->name); if (triangular) die(_("You are pushing to remote '%s', which is not the upstream of\n" "your current branch '%s', without telling me what to push\n" "to update which remote branch."), remote->name, branch->name); if (simple) { /* Additional safety */ if (strcmp(branch->refname, branch->merge[0]->src)) die_push_simple(branch, remote); } strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src); add_refspec(refspec.buf); }
static void set_refspecs(const char **refs, int nr, const char *repo) { struct remote *remote = NULL; struct ref *local_refs = NULL; int i; for (i = 0; i < nr; i++) { const char *ref = refs[i]; if (!strcmp("tag", ref)) { struct strbuf tagref = STRBUF_INIT; if (nr <= ++i) die(_("tag shorthand without <tag>")); ref = refs[i]; if (deleterefs) strbuf_addf(&tagref, ":refs/tags/%s", ref); else strbuf_addf(&tagref, "refs/tags/%s", ref); ref = strbuf_detach(&tagref, NULL); } else if (deleterefs) { struct strbuf delref = STRBUF_INIT; if (strchr(ref, ':')) die(_("--delete only accepts plain target ref names")); strbuf_addf(&delref, ":%s", ref); ref = strbuf_detach(&delref, NULL); } else if (!strchr(ref, ':')) { if (!remote) { /* lazily grab remote and local_refs */ remote = remote_get(repo); local_refs = get_local_heads(); } ref = map_refspec(ref, remote, local_refs); } add_refspec(ref); } }
static void setup_push_upstream(struct remote *remote, int simple) { struct strbuf refspec = STRBUF_INIT; struct branch *branch = branch_get(NULL); if (!branch) die(_("You are not currently on a branch.\n" "To push the history leading to the current (detached HEAD)\n" "state now, use\n" "\n" " git push %s HEAD:<name-of-remote-branch>\n"), remote->name); if (!branch->merge_nr || !branch->merge || !branch->remote_name) die(_("The current branch %s has no upstream branch.\n" "To push the current branch and set the remote as upstream, use\n" "\n" " git push --set-upstream %s %s\n"), branch->name, remote->name, branch->name); if (branch->merge_nr != 1) die(_("The current branch %s has multiple upstream branches, " "refusing to push."), branch->name); if (strcmp(branch->remote_name, remote->name)) die(_("You are pushing to remote '%s', which is not the upstream of\n" "your current branch '%s', without telling me what to push\n" "to update which remote branch."), remote->name, branch->name); if (simple && strcmp(branch->refname, branch->merge[0]->src)) die_push_simple(branch, remote); strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src); add_refspec(refspec.buf); }
static void setup_push_upstream(struct remote *remote) { struct strbuf refspec = STRBUF_INIT; struct branch *branch = branch_get(NULL); if (!branch) die(_("You are not currently on a branch.\n" "To push the history leading to the current (detached HEAD)\n" "state now, use\n" "\n" " git push %s HEAD:<name-of-remote-branch>\n"), remote->name); if (!branch->merge_nr || !branch->merge) die(_("The current branch %s has no upstream branch.\n" "To push the current branch and set the remote as upstream, use\n" "\n" " git push --set-upstream %s %s\n"), branch->name, remote->name, branch->name); if (branch->merge_nr != 1) die(_("The current branch %s has multiple upstream branches, " "refusing to push."), branch->name); strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src); add_refspec(refspec.buf); }
static void setup_push_current(struct remote *remote, struct branch *branch) { struct strbuf refspec = STRBUF_INIT; if (!branch) die(_(message_detached_head_die), remote->name); strbuf_addf(&refspec, "%s:%s", branch->refname, branch->refname); add_refspec(refspec.buf); }
int cmd_push(int argc, const char **argv, const char *prefix) { int flags = 0; int tags = 0; int rc; const char *repo = NULL; /* default repository */ struct option options[] = { OPT__VERBOSITY(&verbosity), OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")), OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL), OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"), (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), OPT_BOOLEAN( 0, "delete", &deleterefs, N_("delete refs")), OPT_BOOLEAN( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")), OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN), OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN), OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE), { OPTION_CALLBACK, 0, "recurse-submodules", &flags, N_("check"), N_("control recursive pushing of submodules"), PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOLEAN( 0 , "thin", &thin, N_("use thin pack")), OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")), OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")), OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"), TRANSPORT_PUSH_SET_UPSTREAM), OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"), TRANSPORT_PUSH_PRUNE), OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK), OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"), TRANSPORT_PUSH_FOLLOW_TAGS), OPT_END() }; packet_trace_identity("push"); git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, push_usage, 0); if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR)))) die(_("--delete is incompatible with --all, --mirror and --tags")); if (deleterefs && argc < 2) die(_("--delete doesn't make sense without any refs")); if (tags) add_refspec("refs/tags/*"); if (argc > 0) { repo = argv[0]; set_refspecs(argv + 1, argc - 1); } rc = do_push(repo, flags); if (rc == -1) usage_with_options(push_usage, options); else return rc; }
static void setup_default_push_refspecs(struct remote *remote) { switch (push_default) { default: case PUSH_DEFAULT_MATCHING: add_refspec(":"); break; case PUSH_DEFAULT_UPSTREAM: setup_push_upstream(remote); break; case PUSH_DEFAULT_CURRENT: add_refspec("HEAD"); break; case PUSH_DEFAULT_NOTHING: die(_("You didn't specify any refspecs to push, and " "push.default is \"nothing\".")); break; } }
static void setup_push_simple(struct remote *remote, struct branch *branch, int triangular) { if (branch->push_name) { struct strbuf refspec = STRBUF_INIT; strbuf_addf(&refspec, "%s:%s", branch->name, branch->push_name); add_refspec(refspec.buf); } else if (triangular) { setup_push_current(remote, branch); } else { setup_push_upstream(remote, branch, triangular); } }
int cmd_push(int argc, const char **argv, const char *prefix) { int flags = 0; int all = 0; int mirror = 0; int dry_run = 0; int force = 0; int tags = 0; int rc; const char *repo = NULL; /* default repository */ struct option options[] = { OPT__VERBOSE(&verbose), OPT_STRING( 0 , "repo", &repo, "repository", "repository"), OPT_BOOLEAN( 0 , "all", &all, "push all refs"), OPT_BOOLEAN( 0 , "mirror", &mirror, "mirror all refs"), OPT_BOOLEAN( 0 , "tags", &tags, "push tags"), OPT_BOOLEAN( 0 , "dry-run", &dry_run, "dry run"), OPT_BOOLEAN('f', "force", &force, "force updates"), OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"), OPT_END() }; argc = parse_options(argc, argv, options, push_usage, 0); if (force) flags |= TRANSPORT_PUSH_FORCE; if (dry_run) flags |= TRANSPORT_PUSH_DRY_RUN; if (verbose) flags |= TRANSPORT_PUSH_VERBOSE; if (tags) add_refspec("refs/tags/*"); if (all) flags |= TRANSPORT_PUSH_ALL; if (mirror) flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE); if (argc > 0) { repo = argv[0]; set_refspecs(argv + 1, argc - 1); } rc = do_push(repo, flags); if (rc == -1) usage_with_options(push_usage, options); else return rc; }
static void setup_default_push_refspecs(void) { git_config(git_default_config, NULL); switch (push_default) { default: case PUSH_DEFAULT_MATCHING: add_refspec(":"); break; case PUSH_DEFAULT_TRACKING: setup_push_tracking(); break; case PUSH_DEFAULT_CURRENT: add_refspec("HEAD"); break; case PUSH_DEFAULT_NOTHING: die("You didn't specify any refspecs to push, and " "push.default is \"nothing\"."); break; } }
static void setup_push_tracking(void) { struct strbuf refspec = STRBUF_INIT; struct branch *branch = branch_get(NULL); if (!branch) die("You are not currently on a branch."); if (!branch->merge_nr) die("The current branch %s is not tracking anything.", branch->name); if (branch->merge_nr != 1) die("The current branch %s is tracking multiple branches, " "refusing to push.", branch->name); strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src); add_refspec(refspec.buf); }
static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) { git_remote *remote; git_buf fetchbuf = GIT_BUF_INIT; int error = -1; /* name is optional */ assert(out && repo && url); remote = git__calloc(1, sizeof(git_remote)); GITERR_CHECK_ALLOC(remote); remote->repo = repo; remote->update_fetchhead = 1; if (get_check_cert(&remote->check_cert, repo) < 0) goto on_error; if (git_vector_init(&remote->refs, 32, NULL) < 0) goto on_error; remote->url = git__strdup(url); GITERR_CHECK_ALLOC(remote->url); if (name != NULL) { remote->name = git__strdup(name); GITERR_CHECK_ALLOC(remote->name); } if (fetch != NULL) { if (add_refspec(remote, fetch, true) < 0) goto on_error; } if (!name) /* A remote without a name doesn't download tags */ remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE; *out = remote; git_buf_free(&fetchbuf); return 0; on_error: git_remote_free(remote); git_buf_free(&fetchbuf); return error; }
static void set_refspecs(const char **refs, int nr) { int i; for (i = 0; i < nr; i++) { const char *ref = refs[i]; if (!strcmp("tag", ref)) { char *tag; int len; if (nr <= ++i) die("tag shorthand without <tag>"); len = strlen(refs[i]) + 11; tag = xmalloc(len); strcpy(tag, "refs/tags/"); strcat(tag, refs[i]); ref = tag; } add_refspec(ref); } }
int cmd_push(int argc, const char **argv, const char *prefix) { int flags = 0; int tags = 0; int rc; const char *repo = NULL; /* default repository */ struct option options[] = { OPT_BIT('q', "quiet", &flags, "be quiet", TRANSPORT_PUSH_QUIET), OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE), OPT_STRING( 0 , "repo", &repo, "repository", "repository"), OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL), OPT_BIT( 0 , "mirror", &flags, "mirror all refs", (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), OPT_BOOLEAN( 0 , "tags", &tags, "push tags"), OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN), OPT_BIT( 0, "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN), OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE), OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"), OPT_END() }; argc = parse_options(argc, argv, prefix, options, push_usage, 0); if (tags) add_refspec("refs/tags/*"); if (argc > 0) { repo = argv[0]; set_refspecs(argv + 1, argc - 1); } rc = do_push(repo, flags); if (rc == -1) usage_with_options(push_usage, options); else return rc; }
static void setup_push_current(struct remote *remote, struct branch *branch) { add_refspec(branch->name); }
static void setup_push_current(struct remote *remote, struct branch *branch) { if (!branch) die(_(message_detached_head_die), remote->name); add_refspec(branch->name); }
int cmd_push(int argc, const char **argv, const char *prefix) { int flags = 0; int tags = 0; int push_cert = -1; int rc; const char *repo = NULL; /* default repository */ struct option options[] = { OPT__VERBOSITY(&verbosity), OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")), OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL), OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"), (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")), OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")), OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN), OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN), OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE), { OPTION_CALLBACK, 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"), N_("require old value of ref to be at this value"), PARSE_OPT_OPTARG, parseopt_push_cas_option }, { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "check|on-demand|no", N_("control recursive pushing of submodules"), PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")), OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")), OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")), OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"), TRANSPORT_PUSH_SET_UPSTREAM), OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"), TRANSPORT_PUSH_PRUNE), OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK), OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"), TRANSPORT_PUSH_FOLLOW_TAGS), { OPTION_CALLBACK, 0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"), PARSE_OPT_OPTARG, option_parse_push_signed }, OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC), OPT_END() }; packet_trace_identity("push"); git_config(git_push_config, &flags); argc = parse_options(argc, argv, prefix, options, push_usage, 0); set_push_cert_flags(&flags, push_cert); if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR)))) die(_("--delete is incompatible with --all, --mirror and --tags")); if (deleterefs && argc < 2) die(_("--delete doesn't make sense without any refs")); if (recurse_submodules == RECURSE_SUBMODULES_CHECK) flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK; else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND; if (tags) add_refspec("refs/tags/*"); if (argc > 0) { repo = argv[0]; set_refspecs(argv + 1, argc - 1, repo); } rc = do_push(repo, flags); if (rc == -1) usage_with_options(push_usage, options); else return rc; }
static int do_push(const char *repo, int flags) { int i, errs; struct remote *remote = pushremote_get(repo); const char **url; int url_nr; if (!remote) { if (repo) die(_("bad repository '%s'"), repo); die(_("No configured push destination.\n" "Either specify the URL from the command-line or configure a remote repository using\n" "\n" " git remote add <name> <url>\n" "\n" "and then push using the remote name\n" "\n" " git push <name>\n")); } if (remote->mirror) flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE); if ((flags & TRANSPORT_PUSH_ALL) && refspec) { if (!strcmp(*refspec, "refs/tags/*")) return error(_("--all and --tags are incompatible")); return error(_("--all can't be combined with refspecs")); } if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) { if (!strcmp(*refspec, "refs/tags/*")) return error(_("--mirror and --tags are incompatible")); return error(_("--mirror can't be combined with refspecs")); } if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) == (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) { return error(_("--all and --mirror are incompatible")); } if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) { struct branch *branch = branch_get(NULL); /* Is there a publish branch */ if (branch && branch->pushremote_name && !strcmp(remote->name, branch->pushremote_name) && branch->push_name) { struct strbuf refspec = STRBUF_INIT; strbuf_addf(&refspec, "%s:%s", branch->name, branch->push_name); add_refspec(refspec.buf); } else if (remote->push_refspec_nr) { refspec = remote->push_refspec; refspec_nr = remote->push_refspec_nr; } else if (!(flags & TRANSPORT_PUSH_MIRROR)) setup_default_push_refspecs(remote); } errs = 0; url_nr = push_url_of_remote(remote, &url); if (url_nr) { for (i = 0; i < url_nr; i++) { struct transport *transport = transport_get(remote, url[i]); if (push_with_options(transport, flags)) errs++; } } else { struct transport *transport = transport_get(remote, NULL); if (push_with_options(transport, flags)) errs++; } return !!errs; }
static int refspec_cb(const git_config_entry *entry, void *payload) { struct refspec_cb_data *data = (struct refspec_cb_data *)payload; return add_refspec(data->remote, entry->value, data->fetch); }