return 0;
}
- char buf[PATH_MAX];
+ struct push_info {
+ char *dest;
+ int forced;
+ enum {
+ PUSH_STATUS_CREATE = 0,
+ PUSH_STATUS_DELETE,
+ PUSH_STATUS_UPTODATE,
+ PUSH_STATUS_FASTFORWARD,
+ PUSH_STATUS_OUTOFDATE,
+ PUSH_STATUS_NOTQUERIED,
+ } status;
+ };
+
+ static int get_push_ref_states(const struct ref *remote_refs,
+ struct ref_states *states)
+ {
+ struct remote *remote = states->remote;
+ struct ref *ref, *local_refs, *push_map, **push_tail;
+ if (remote->mirror)
+ return 0;
+
+ local_refs = get_local_heads();
+ ref = push_map = copy_ref_list(remote_refs);
+ while (ref->next)
+ ref = ref->next;
+ push_tail = &ref->next;
+
+ match_refs(local_refs, push_map, &push_tail, remote->push_refspec_nr,
+ remote->push_refspec, MATCH_REFS_NONE);
+
+ states->push.strdup_strings = 1;
+ for (ref = push_map; ref; ref = ref->next) {
+ struct string_list_item *item;
+ struct push_info *info;
+
+ if (!ref->peer_ref)
+ continue;
+ hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
+
+ item = string_list_append(abbrev_branch(ref->peer_ref->name),
+ &states->push);
+ item->util = xcalloc(sizeof(struct push_info), 1);
+ info = item->util;
+ info->forced = ref->force;
+ info->dest = xstrdup(abbrev_branch(ref->name));
+
+ if (is_null_sha1(ref->new_sha1)) {
+ info->status = PUSH_STATUS_DELETE;
+ } else if (!hashcmp(ref->old_sha1, ref->new_sha1))
+ info->status = PUSH_STATUS_UPTODATE;
+ else if (is_null_sha1(ref->old_sha1))
+ info->status = PUSH_STATUS_CREATE;
+ else if (has_sha1_file(ref->old_sha1) &&
+ ref_newer(ref->new_sha1, ref->old_sha1))
+ info->status = PUSH_STATUS_FASTFORWARD;
+ else
+ info->status = PUSH_STATUS_OUTOFDATE;
+ }
+ free_refs(local_refs);
+ free_refs(push_map);
+ return 0;
+ }
+
+ static int get_push_ref_states_noquery(struct ref_states *states)
+ {
+ int i;
+ struct remote *remote = states->remote;
+ struct string_list_item *item;
+ struct push_info *info;
+
+ if (remote->mirror)
+ return 0;
+
+ states->push.strdup_strings = 1;
+ if (!remote->push_refspec_nr) {
+ item = string_list_append("(matching)", &states->push);
+ info = item->util = xcalloc(sizeof(struct push_info), 1);
+ info->status = PUSH_STATUS_NOTQUERIED;
+ info->dest = xstrdup(item->string);
+ }
+ for (i = 0; i < remote->push_refspec_nr; i++) {
+ struct refspec *spec = remote->push + i;
- 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))
+ if (spec->matching)
+ item = string_list_append("(matching)", &states->push);
- if (spec->pattern)
- info->dest = xstrdup(buf);
- else
- info->dest = xstrdup(spec->dst ? spec->dst : item->string);
++ 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;
- refspec.src = refspec.dst = "refs/heads/";
++ info->dest = xstrdup(spec->dst ? spec->dst : item->string);
+ }
+ return 0;
+ }
+
+ static int get_head_names(const struct ref *remote_refs, struct ref_states *states)
+ {
+ struct ref *ref, *matches;
+ struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
+ struct refspec refspec;
+
+ refspec.force = 0;
+ refspec.pattern = 1;
++ 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"),
+ fetch_map, 1);
+ for(ref = matches; ref; ref = ref->next)
+ string_list_append(abbrev_branch(ref->name), &states->heads);
+
+ free_refs(fetch_map);
+ free_refs(matches);
+
+ return 0;
+ }
+
struct known_remote {
struct known_remote *next;
struct remote *remote;