"git remote set-head <name> [-a | -d | <branch>]",
"git remote show [-n] <name>",
"git remote prune [-n | --dry-run] <name>",
- "git remote [-v | --verbose] update [group]",
+ "git remote [-v | --verbose] update [-p | --prune] [group]",
NULL
};
static int verbose;
static int show_all(void);
+static int prune_remote(const char *remote, int dry_run);
static inline int postfixcmp(const char *string, const char *postfix)
{
}
for (i = 0; i < remote->push_refspec_nr; i++) {
struct refspec *spec = remote->push + i;
- char buf[PATH_MAX];
if (spec->matching)
item = string_list_append("(matching)", &states->push);
- else if (spec->pattern) {
- snprintf(buf, (sizeof(buf)), "%s*", spec->src);
- item = string_list_append(buf, &states->push);
- snprintf(buf, (sizeof(buf)), "%s*", spec->dst);
- } else if (strlen(spec->src))
+ else if (strlen(spec->src))
item = string_list_append(spec->src, &states->push);
else
item = string_list_append("(delete)", &states->push);
info = item->util = xcalloc(sizeof(struct push_info), 1);
info->forced = spec->force;
info->status = PUSH_STATUS_NOTQUERIED;
- if (spec->pattern)
- info->dest = xstrdup(buf);
- else
- info->dest = xstrdup(spec->dst ? spec->dst : item->string);
+ info->dest = xstrdup(spec->dst ? spec->dst : item->string);
}
return 0;
}
refspec.force = 0;
refspec.pattern = 1;
- refspec.src = refspec.dst = "refs/heads/";
+ refspec.src = refspec.dst = "refs/heads/*";
states->heads.strdup_strings = 1;
get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
struct string_list_item *item = remote_branches.items + i;
int flag = 0;
unsigned char sha1[20];
- const char *symref;
- symref = resolve_ref(item->string, sha1, 1, &flag);
+ resolve_ref(item->string, sha1, 1, &flag);
if (!(flag & REF_ISSYMREF))
continue;
if (delete_ref(item->string, NULL, REF_NODEREF))
return 0;
}
+/*
+ * Sorting comparison for a string list that has push_info
+ * structs in its util field
+ */
+static int cmp_string_with_push(const void *va, const void *vb)
+{
+ const struct string_list_item *a = va;
+ const struct string_list_item *b = vb;
+ const struct push_info *a_push = a->util;
+ const struct push_info *b_push = b->util;
+ int cmp = strcmp(a->string, b->string);
+ return cmp ? cmp : strcmp(a_push->dest, b_push->dest);
+}
+
int show_push_info_item(struct string_list_item *item, void *cb_data)
{
struct show_info *show_info = cb_data;
info.width = info.width2 = 0;
for_each_string_list(add_push_to_show_info, &states.push, &info);
- sort_string_list(info.list);
+ qsort(info.list->items, info.list->nr,
+ sizeof(*info.list->items), cmp_string_with_push);
if (info.list->nr)
printf(" Local ref%s configured for 'git push'%s:\n",
info.list->nr > 1 ? "s" : "",
OPT__DRY_RUN(&dry_run),
OPT_END()
};
- struct ref_states states;
- const char *dangling_msg;
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
if (argc < 1)
usage_with_options(builtin_remote_usage, options);
- dangling_msg = (dry_run
- ? " %s will become dangling!\n"
- : " %s has become dangling!\n");
+ for (; argc; argc--, argv++)
+ result |= prune_remote(*argv, dry_run);
- memset(&states, 0, sizeof(states));
- for (; argc; argc--, argv++) {
- int i;
-
- get_remote_ref_states(*argv, &states, GET_REF_STATES);
+ return result;
+}
- if (states.stale.nr) {
- printf("Pruning %s\n", *argv);
- printf("URL: %s\n",
- states.remote->url_nr
- ? states.remote->url[0]
- : "(no URL)");
- }
+static int prune_remote(const char *remote, int dry_run)
+{
+ int result = 0, i;
+ struct ref_states states;
+ const char *dangling_msg = dry_run
+ ? " %s will become dangling!\n"
+ : " %s has become dangling!\n";
- for (i = 0; i < states.stale.nr; i++) {
- const char *refname = states.stale.items[i].util;
+ memset(&states, 0, sizeof(states));
+ get_remote_ref_states(remote, &states, GET_REF_STATES);
+
+ if (states.stale.nr) {
+ printf("Pruning %s\n", remote);
+ printf("URL: %s\n",
+ states.remote->url_nr
+ ? states.remote->url[0]
+ : "(no URL)");
+ }
- if (!dry_run)
- result |= delete_ref(refname, NULL, 0);
+ for (i = 0; i < states.stale.nr; i++) {
+ const char *refname = states.stale.items[i].util;
- printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
- abbrev_ref(refname, "refs/remotes/"));
- warn_dangling_symref(dangling_msg, refname);
- }
+ if (!dry_run)
+ result |= delete_ref(refname, NULL, 0);
- free_remote_ref_states(&states);
+ printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
+ abbrev_ref(refname, "refs/remotes/"));
+ warn_dangling_symref(dangling_msg, refname);
}
+ free_remote_ref_states(&states);
return result;
}
struct string_list *list;
} remote_group;
-static int get_remote_group(const char *key, const char *value, void *cb)
+static int get_remote_group(const char *key, const char *value, void *num_hits)
{
if (!prefixcmp(key, "remotes.") &&
!strcmp(key + 8, remote_group.name)) {
/* split list by white space */
int space = strcspn(value, " \t\n");
while (*value) {
- if (space > 1)
+ if (space > 1) {
string_list_append(xstrndup(value, space),
remote_group.list);
+ ++*((int *)num_hits);
+ }
value += space + (value[space] != '\0');
space = strcspn(value, " \t\n");
}
static int update(int argc, const char **argv)
{
- int i, result = 0;
+ int i, result = 0, prune = 0;
struct string_list list = { NULL, 0, 0, 0 };
static const char *default_argv[] = { NULL, "default", NULL };
+ struct option options[] = {
+ OPT_GROUP("update specific options"),
+ OPT_BOOLEAN('p', "prune", &prune,
+ "prune remotes after fetching"),
+ OPT_END()
+ };
+ argc = parse_options(argc, argv, options, builtin_remote_usage,
+ PARSE_OPT_KEEP_ARGV0);
if (argc < 2) {
argc = 2;
argv = default_argv;
remote_group.list = &list;
for (i = 1; i < argc; i++) {
+ int groups_found = 0;
remote_group.name = argv[i];
- result = git_config(get_remote_group, NULL);
+ result = git_config(get_remote_group, &groups_found);
+ if (!groups_found && (i != 1 || strcmp(argv[1], "default"))) {
+ struct remote *remote;
+ if (!remote_is_configured(argv[i]))
+ die("No such remote or remote group: %s",
+ argv[i]);
+ remote = remote_get(argv[i]);
+ string_list_append(remote->name, remote_group.list);
+ }
}
if (!result && !list.nr && argc == 2 && !strcmp(argv[1], "default"))
result = for_each_remote(get_one_remote_for_update, &list);
- for (i = 0; i < list.nr; i++)
- result |= fetch_remote(list.items[i].string);
+ for (i = 0; i < list.nr; i++) {
+ int err = fetch_remote(list.items[i].string);
+ result |= err;
+ if (!err && prune)
+ result |= prune_remote(list.items[i].string, 0);
+ }
/* all names were strdup()ed or strndup()ed */
list.strdup_strings = 1;