diff options
Diffstat (limited to 'builtin/remote.c')
-rw-r--r-- | builtin/remote.c | 203 |
1 files changed, 117 insertions, 86 deletions
diff --git a/builtin/remote.c b/builtin/remote.c index c9102e8fe9..6694cf20ef 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -10,14 +10,15 @@ static const char * const builtin_remote_usage[] = { N_("git remote [-v | --verbose]"), - N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>"), + N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>"), N_("git remote rename <old> <new>"), N_("git remote remove <name>"), - N_("git remote set-head <name> (-a | --auto | -d | --delete |<branch>)"), + N_("git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"), N_("git remote [-v | --verbose] show [-n] <name>"), N_("git remote prune [-n | --dry-run] <name>"), N_("git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"), N_("git remote set-branches [--add] <name> <branch>..."), + N_("git remote get-url [--push] [--all] <name>"), N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"), N_("git remote set-url --add <name> <newurl>"), N_("git remote set-url --delete <name> <url>"), @@ -65,6 +66,11 @@ static const char * const builtin_remote_update_usage[] = { NULL }; +static const char * const builtin_remote_geturl_usage[] = { + N_("git remote get-url [--push] [--all] <name>"), + NULL +}; + static const char * const builtin_remote_seturl_usage[] = { N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"), N_("git remote set-url --add <name> <newurl>"), @@ -180,7 +186,9 @@ static int add(int argc, const char **argv) url = argv[1]; remote = remote_get(name); - if (remote && (remote->url_nr > 1 || strcmp(name, remote->url[0]) || + if (remote && (remote->url_nr > 1 || + (strcmp(name, remote->url[0]) && + strcmp(url, remote->url[0])) || remote->fetch_refspec_nr)) die(_("remote %s already exists."), name); @@ -250,9 +258,7 @@ static struct string_list branch_list; static const char *abbrev_ref(const char *name, const char *prefix) { - const char *abbrev = skip_prefix(name, prefix); - if (abbrev) - return abbrev; + skip_prefix(name, prefix, &name); return name; } #define abbrev_branch(name) abbrev_ref((name), "refs/heads/") @@ -265,16 +271,17 @@ static int config_read_branches(const char *key, const char *value, void *cb) struct string_list_item *item; struct branch_info *info; enum { REMOTE, MERGE, REBASE } type; + size_t key_len; key += 7; - if (ends_with(key, ".remote")) { - name = xstrndup(key, strlen(key) - 7); + if (strip_suffix(key, ".remote", &key_len)) { + name = xmemdupz(key, key_len); type = REMOTE; - } else if (ends_with(key, ".merge")) { - name = xstrndup(key, strlen(key) - 6); + } else if (strip_suffix(key, ".merge", &key_len)) { + name = xmemdupz(key, key_len); type = MERGE; - } else if (ends_with(key, ".rebase")) { - name = xstrndup(key, strlen(key) - 7); + } else if (strip_suffix(key, ".rebase", &key_len)) { + name = xmemdupz(key, key_len); type = REBASE; } else return 0; @@ -353,9 +360,9 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat free_refs(stale_refs); free_refs(fetch_map); - sort_string_list(&states->new); - sort_string_list(&states->tracked); - sort_string_list(&states->stale); + string_list_sort(&states->new); + string_list_sort(&states->tracked); + string_list_sort(&states->stale); return 0; } @@ -394,7 +401,7 @@ static int get_push_ref_states(const struct ref *remote_refs, if (!ref->peer_ref) continue; - hashcpy(ref->new_sha1, ref->peer_ref->new_sha1); + oidcpy(&ref->new_oid, &ref->peer_ref->new_oid); item = string_list_append(&states->push, abbrev_branch(ref->peer_ref->name)); @@ -403,14 +410,14 @@ static int get_push_ref_states(const struct ref *remote_refs, info->forced = ref->force; info->dest = xstrdup(abbrev_branch(ref->name)); - if (is_null_sha1(ref->new_sha1)) { + if (is_null_oid(&ref->new_oid)) { info->status = PUSH_STATUS_DELETE; - } else if (!hashcmp(ref->old_sha1, ref->new_sha1)) + } else if (!oidcmp(&ref->old_oid, &ref->new_oid)) info->status = PUSH_STATUS_UPTODATE; - else if (is_null_sha1(ref->old_sha1)) + else if (is_null_oid(&ref->old_oid)) info->status = PUSH_STATUS_CREATE; - else if (has_sha1_file(ref->old_sha1) && - ref_newer(ref->new_sha1, ref->old_sha1)) + else if (has_object_file(&ref->old_oid) && + ref_newer(&ref->new_oid, &ref->old_oid)) info->status = PUSH_STATUS_FASTFORWARD; else info->status = PUSH_STATUS_OUTOFDATE; @@ -508,11 +515,10 @@ struct branches_for_remote { }; static int add_branch_for_removal(const char *refname, - const unsigned char *sha1, int flags, void *cb_data) + const struct object_id *oid, int flags, void *cb_data) { struct branches_for_remote *branches = cb_data; struct refspec refspec; - struct string_list_item *item; struct known_remote *kr; memset(&refspec, 0, sizeof(refspec)); @@ -542,9 +548,7 @@ static int add_branch_for_removal(const char *refname, if (flags & REF_ISSYMREF) return unlink(git_path("%s", refname)); - item = string_list_append(branches->branches, refname); - item->util = xmalloc(20); - hashcpy(item->util, sha1); + string_list_append(branches->branches, refname); return 0; } @@ -556,19 +560,20 @@ struct rename_info { }; static int read_remote_branches(const char *refname, - const unsigned char *sha1, int flags, void *cb_data) + const struct object_id *oid, int flags, void *cb_data) { struct rename_info *rename = cb_data; struct strbuf buf = STRBUF_INIT; struct string_list_item *item; int flag; - unsigned char orig_sha1[20]; + struct object_id orig_oid; const char *symref; strbuf_addf(&buf, "refs/remotes/%s/", rename->old); if (starts_with(refname, buf.buf)) { item = string_list_append(rename->remote_branches, xstrdup(refname)); - symref = resolve_ref_unsafe(refname, orig_sha1, 1, &flag); + symref = resolve_ref_unsafe(refname, RESOLVE_REF_READING, + orig_oid.hash, &flag); if (flag & REF_ISSYMREF) item->util = xstrdup(symref); else @@ -582,7 +587,6 @@ static int migrate_file(struct remote *remote) { struct strbuf buf = STRBUF_INIT; int i; - char *path = NULL; strbuf_addf(&buf, "remote.%s.url", remote->name); for (i = 0; i < remote->url_nr; i++) @@ -602,11 +606,9 @@ static int migrate_file(struct remote *remote) return error(_("Could not append '%s' to '%s'"), remote->fetch_refspec[i], buf.buf); if (remote->origin == REMOTE_REMOTES) - path = git_path("remotes/%s", remote->name); + unlink_or_warn(git_path("remotes/%s", remote->name)); else if (remote->origin == REMOTE_BRANCHES) - path = git_path("branches/%s", remote->name); - if (path) - unlink_or_warn(path); + unlink_or_warn(git_path("branches/%s", remote->name)); return 0; } @@ -702,9 +704,9 @@ static int mv(int argc, const char **argv) for (i = 0; i < remote_branches.nr; i++) { struct string_list_item *item = remote_branches.items + i; int flag = 0; - unsigned char sha1[20]; + struct object_id oid; - read_ref_full(item->string, sha1, 1, &flag); + read_ref_full(item->string, RESOLVE_REF_READING, oid.hash, &flag); if (!(flag & REF_ISSYMREF)) continue; if (delete_ref(item->string, NULL, REF_NODEREF)) @@ -747,28 +749,6 @@ static int mv(int argc, const char **argv) return 0; } -static int remove_branches(struct string_list *branches) -{ - const char **branch_names; - int i, result = 0; - - branch_names = xmalloc(branches->nr * sizeof(*branch_names)); - for (i = 0; i < branches->nr; i++) - branch_names[i] = branches->items[i].string; - result |= repack_without_refs(branch_names, branches->nr); - free(branch_names); - - for (i = 0; i < branches->nr; i++) { - struct string_list_item *item = branches->items + i; - const char *refname = item->string; - - if (delete_ref(refname, NULL, 0)) - result |= error(_("Could not remove branch %s"), refname); - } - - return result; -} - static int rm(int argc, const char **argv) { struct option options[] = { @@ -825,8 +805,8 @@ static int rm(int argc, const char **argv) strbuf_release(&buf); if (!result) - result = remove_branches(&branches); - string_list_clear(&branches, 1); + result = delete_refs(&branches); + string_list_clear(&branches, 0); if (skipped.nr) { fprintf_ln(stderr, @@ -867,7 +847,7 @@ static void free_remote_ref_states(struct ref_states *states) } static int append_ref_to_tracked_list(const char *refname, - const unsigned char *sha1, int flags, void *cb_data) + const struct object_id *oid, int flags, void *cb_data) { struct ref_states *states = cb_data; struct refspec refspec; @@ -911,7 +891,7 @@ static int get_remote_ref_states(const char *name, get_push_ref_states(remote_refs, states); } else { for_each_ref(append_ref_to_tracked_list, states); - sort_string_list(&states->tracked); + string_list_sort(&states->tracked); get_push_ref_states_noquery(states); } @@ -1130,7 +1110,7 @@ static int show_all(void) if (!result) { int i; - sort_string_list(&list); + string_list_sort(&list); for (i = 0; i < list.nr; i++) { struct string_list_item *item = list.items + i; if (verbose) @@ -1311,10 +1291,10 @@ static int set_head(int argc, const char **argv) static int prune_remote(const char *remote, int dry_run) { - int result = 0, i; + int result = 0; struct ref_states states; - struct string_list delete_refs_list = STRING_LIST_INIT_NODUP; - const char **delete_refs; + struct string_list refs_to_prune = STRING_LIST_INIT_NODUP; + struct string_list_item *item; const char *dangling_msg = dry_run ? _(" %s will become dangling!") : _(" %s has become dangling!"); @@ -1322,28 +1302,26 @@ static int prune_remote(const char *remote, int dry_run) memset(&states, 0, sizeof(states)); get_remote_ref_states(remote, &states, GET_REF_STATES); - if (states.stale.nr) { - printf_ln(_("Pruning %s"), remote); - printf_ln(_("URL: %s"), - states.remote->url_nr - ? states.remote->url[0] - : _("(no URL)")); - - delete_refs = xmalloc(states.stale.nr * sizeof(*delete_refs)); - for (i = 0; i < states.stale.nr; i++) - delete_refs[i] = states.stale.items[i].util; - if (!dry_run) - result |= repack_without_refs(delete_refs, states.stale.nr); - free(delete_refs); + if (!states.stale.nr) { + free_remote_ref_states(&states); + return 0; } - for (i = 0; i < states.stale.nr; i++) { - const char *refname = states.stale.items[i].util; + printf_ln(_("Pruning %s"), remote); + printf_ln(_("URL: %s"), + states.remote->url_nr + ? states.remote->url[0] + : _("(no URL)")); + + for_each_string_list_item(item, &states.stale) + string_list_append(&refs_to_prune, item->util); + string_list_sort(&refs_to_prune); - string_list_insert(&delete_refs_list, refname); + if (!dry_run) + result |= delete_refs(&refs_to_prune); - if (!dry_run) - result |= delete_ref(refname, NULL, 0); + for_each_string_list_item(item, &states.stale) { + const char *refname = item->util; if (dry_run) printf_ln(_(" * [would prune] %s"), @@ -1353,9 +1331,9 @@ static int prune_remote(const char *remote, int dry_run) abbrev_ref(refname, "refs/remotes/")); } - warn_dangling_symrefs(stdout, dangling_msg, &delete_refs_list); - string_list_clear(&delete_refs_list, 0); + warn_dangling_symrefs(stdout, dangling_msg, &refs_to_prune); + string_list_clear(&refs_to_prune, 0); free_remote_ref_states(&states); return result; } @@ -1495,6 +1473,57 @@ static int set_branches(int argc, const char **argv) return set_remote_branches(argv[0], argv + 1, add_mode); } +static int get_url(int argc, const char **argv) +{ + int i, push_mode = 0, all_mode = 0; + const char *remotename = NULL; + struct remote *remote; + const char **url; + int url_nr; + struct option options[] = { + OPT_BOOL('\0', "push", &push_mode, + N_("query push URLs rather than fetch URLs")), + OPT_BOOL('\0', "all", &all_mode, + N_("return all URLs")), + OPT_END() + }; + argc = parse_options(argc, argv, NULL, options, builtin_remote_geturl_usage, 0); + + if (argc != 1) + usage_with_options(builtin_remote_geturl_usage, options); + + remotename = argv[0]; + + if (!remote_is_configured(remotename)) + die(_("No such remote '%s'"), remotename); + remote = remote_get(remotename); + + url_nr = 0; + if (push_mode) { + url = remote->pushurl; + url_nr = remote->pushurl_nr; + } + /* else fetch mode */ + + /* Use the fetch URL when no push URLs were found or requested. */ + if (!url_nr) { + url = remote->url; + url_nr = remote->url_nr; + } + + if (!url_nr) + die(_("no URLs configured for remote '%s'"), remotename); + + if (all_mode) { + for (i = 0; i < url_nr; i++) + printf_ln("%s", url[i]); + } else { + printf_ln("%s", *url); + } + + return 0; +} + static int set_url(int argc, const char **argv) { int i, push_mode = 0, add_mode = 0, delete_mode = 0; @@ -1604,6 +1633,8 @@ int cmd_remote(int argc, const char **argv, const char *prefix) result = set_head(argc, argv); else if (!strcmp(argv[0], "set-branches")) result = set_branches(argc, argv); + else if (!strcmp(argv[0], "get-url")) + result = get_url(argc, argv); else if (!strcmp(argv[0], "set-url")) result = set_url(argc, argv); else if (!strcmp(argv[0], "show")) |