#include "trailer.h"
#include "wt-status.h"
#include "commit-slab.h"
+#include "commit-graph.h"
static struct ref_msg {
const char *gone;
char color[COLOR_MAXLEN];
struct align align;
struct {
- enum { RR_REF, RR_TRACK, RR_TRACKSHORT } option;
+ enum {
+ RR_REF, RR_TRACK, RR_TRACKSHORT, RR_REMOTE_NAME, RR_REMOTE_REF
+ } option;
struct refname_atom refname;
- unsigned int nobracket : 1;
+ unsigned int nobracket : 1, push : 1, push_remote : 1;
} remote_ref;
struct {
enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option;
struct string_list params = STRING_LIST_INIT_DUP;
int i;
+ if (!strcmp(atom->name, "push") || starts_with(atom->name, "push:"))
+ atom->u.remote_ref.push = 1;
+
if (!arg) {
atom->u.remote_ref.option = RR_REF;
refname_atom_parser_internal(&atom->u.remote_ref.refname,
atom->u.remote_ref.option = RR_TRACKSHORT;
else if (!strcmp(s, "nobracket"))
atom->u.remote_ref.nobracket = 1;
- else {
+ else if (!strcmp(s, "remotename")) {
+ atom->u.remote_ref.option = RR_REMOTE_NAME;
+ atom->u.remote_ref.push_remote = 1;
+ } else if (!strcmp(s, "remoteref")) {
+ atom->u.remote_ref.option = RR_REMOTE_REF;
+ atom->u.remote_ref.push_remote = 1;
+ } else {
atom->u.remote_ref.option = RR_REF;
refname_atom_parser_internal(&atom->u.remote_ref.refname,
arg, atom->name);
static void align_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state)
{
- struct ref_formatting_stack *new;
+ struct ref_formatting_stack *new_stack;
push_stack_element(&state->stack);
- new = state->stack;
- new->at_end = end_align_handler;
- new->at_end_data = &atomv->atom->u.align;
+ new_stack = state->stack;
+ new_stack->at_end = end_align_handler;
+ new_stack->at_end_data = &atomv->atom->u.align;
}
static void if_then_else_handler(struct ref_formatting_stack **stack)
static void if_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state)
{
- struct ref_formatting_stack *new;
+ struct ref_formatting_stack *new_stack;
struct if_then_else *if_then_else = xcalloc(sizeof(struct if_then_else), 1);
if_then_else->str = atomv->atom->u.if_then_else.str;
if_then_else->cmp_status = atomv->atom->u.if_then_else.cmp_status;
push_stack_element(&state->stack);
- new = state->stack;
- new->at_end = if_then_else_handler;
- new->at_end_data = if_then_else;
+ new_stack = state->stack;
+ new_stack->at_end = if_then_else_handler;
+ new_stack->at_end_data = if_then_else;
}
static int is_empty(const char *s)
if (deref)
name++;
if (!strcmp(name, "objecttype"))
- v->s = typename(obj->type);
+ v->s = type_name(obj->type);
else if (!strcmp(name, "objectsize")) {
v->value = sz;
v->s = xstrfmt("%lu", sz);
if (!strcmp(name, "tag"))
v->s = tag->tag;
else if (!strcmp(name, "type") && tag->tagged)
- v->s = typename(tag->tagged->type);
+ v->s = type_name(tag->tagged->type);
else if (!strcmp(name, "object") && tag->tagged)
v->s = xstrdup(oid_to_hex(&tag->tagged->oid));
}
if (deref)
name++;
if (!strcmp(name, "tree")) {
- v->s = xstrdup(oid_to_hex(&commit->tree->object.oid));
+ v->s = xstrdup(oid_to_hex(get_commit_tree_oid(commit)));
}
else if (!strcmp(name, "numparent")) {
v->value = commit_list_count(commit->parents);
*s = ">";
else
*s = "<>";
+ } else if (atom->u.remote_ref.option == RR_REMOTE_NAME) {
+ int explicit;
+ const char *remote = atom->u.remote_ref.push ?
+ pushremote_for_branch(branch, &explicit) :
+ remote_for_branch(branch, &explicit);
+ if (explicit)
+ *s = xstrdup(remote);
+ else
+ *s = "";
+ } else if (atom->u.remote_ref.option == RR_REMOTE_REF) {
+ int explicit;
+ const char *merge;
+
+ merge = remote_ref_for_branch(branch, atom->u.remote_ref.push,
+ &explicit);
+ if (explicit)
+ *s = xstrdup(merge);
+ else
+ *s = "";
} else
die("BUG: unhandled RR_* enum");
}
if (refname)
fill_remote_ref_details(atom, refname, branch, &v->s);
continue;
- } else if (starts_with(name, "push")) {
+ } else if (atom->u.remote_ref.push) {
const char *branch_name;
if (!skip_prefix(ref->refname, "refs/heads/",
&branch_name))
continue;
branch = branch_get(branch_name);
- refname = branch_get_push(branch, NULL);
- if (!refname)
- continue;
+ if (atom->u.remote_ref.push_remote)
+ refname = NULL;
+ else {
+ refname = branch_get_push(branch, NULL);
+ if (!refname)
+ continue;
+ }
fill_remote_ref_details(atom, refname, branch, &v->s);
continue;
} else if (starts_with(name, "color:")) {
}
/*
- * Test whether the candidate or one of its parents is contained in the list.
+ * Test whether the candidate is contained in the list.
* Do not recurse to find out, though, but return -1 if inconclusive.
*/
static enum contains_result contains_test(struct commit *candidate,
const struct commit_list *want,
- struct contains_cache *cache)
+ struct contains_cache *cache,
+ uint32_t cutoff)
{
enum contains_result *cached = contains_cache_at(cache, candidate);
/* Otherwise, we don't know; prepare to recurse */
parse_commit_or_die(candidate);
+
+ if (candidate->generation < cutoff)
+ return CONTAINS_NO;
+
return CONTAINS_UNKNOWN;
}
struct contains_cache *cache)
{
struct contains_stack contains_stack = { 0, 0, NULL };
- enum contains_result result = contains_test(candidate, want, cache);
+ enum contains_result result;
+ uint32_t cutoff = GENERATION_NUMBER_INFINITY;
+ const struct commit_list *p;
+
+ for (p = want; p; p = p->next) {
+ struct commit *c = p->item;
+ load_commit_graph_info(c);
+ if (c->generation < cutoff)
+ cutoff = c->generation;
+ }
+ result = contains_test(candidate, want, cache, cutoff);
if (result != CONTAINS_UNKNOWN)
return result;
* If we just popped the stack, parents->item has been marked,
* therefore contains_test will return a meaningful yes/no.
*/
- else switch (contains_test(parents->item, want, cache)) {
+ else switch (contains_test(parents->item, want, cache, cutoff)) {
case CONTAINS_YES:
*contains_cache_at(cache, commit) = CONTAINS_YES;
contains_stack.nr--;
}
}
free(contains_stack.contains_stack);
- return contains_test(candidate, want, cache);
+ return contains_test(candidate, want, cache, cutoff);
}
static int commit_contains(struct ref_filter *filter, struct commit *commit,