{ "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
{ "then", SOURCE_NONE },
{ "else", SOURCE_NONE },
+ /*
+ * Please update $__git_ref_fieldlist in git-completion.bash
+ * when you add new atoms
+ */
};
#define REF_FORMATTING_STATE_INIT { 0, NULL }
}
/* See grab_values */
-static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_tag_values(struct atom_value *val, int deref, struct object *obj)
{
int i;
struct tag *tag = (struct tag *) obj;
}
/* See grab_values */
-static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_commit_values(struct atom_value *val, int deref, struct object *obj)
{
int i;
struct commit *commit = (struct commit *) obj;
}
}
-static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz)
+static const char *find_wholine(const char *who, int wholen, const char *buf)
{
const char *eol;
while (*buf) {
}
/* See grab_values */
-static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_person(const char *who, struct atom_value *val, int deref, void *buf)
{
int i;
int wholen = strlen(who);
!starts_with(name + wholen, "date"))
continue;
if (!wholine)
- wholine = find_wholine(who, wholen, buf, sz);
+ wholine = find_wholine(who, wholen, buf);
if (!wholine)
return; /* no point looking for it */
if (name[wholen] == 0)
if (strcmp(who, "tagger") && strcmp(who, "committer"))
return; /* "author" for commit object is not wanted */
if (!wholine)
- wholine = find_wholine(who, wholen, buf, sz);
+ wholine = find_wholine(who, wholen, buf);
if (!wholine)
return;
for (i = 0; i < used_atom_cnt; i++) {
}
}
-static void find_subpos(const char *buf, unsigned long sz,
+static void find_subpos(const char *buf,
const char **sub, unsigned long *sublen,
const char **body, unsigned long *bodylen,
unsigned long *nonsiglen,
}
/* See grab_values */
-static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
{
int i;
const char *subpos = NULL, *bodypos = NULL, *sigpos = NULL;
!starts_with(name, "contents"))
continue;
if (!subpos)
- find_subpos(buf, sz,
+ find_subpos(buf,
&subpos, &sublen,
&bodypos, &bodylen, &nonsiglen,
&sigpos, &siglen);
* pointed at by the ref itself; otherwise it is the object the
* ref (which is a tag) refers to.
*/
-static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf)
{
switch (obj->type) {
case OBJ_TAG:
- grab_tag_values(val, deref, obj, buf, sz);
- grab_sub_body_contents(val, deref, obj, buf, sz);
- grab_person("tagger", val, deref, obj, buf, sz);
+ grab_tag_values(val, deref, obj);
+ grab_sub_body_contents(val, deref, buf);
+ grab_person("tagger", val, deref, buf);
break;
case OBJ_COMMIT:
- grab_commit_values(val, deref, obj, buf, sz);
- grab_sub_body_contents(val, deref, obj, buf, sz);
- grab_person("author", val, deref, obj, buf, sz);
- grab_person("committer", val, deref, obj, buf, sz);
+ grab_commit_values(val, deref, obj);
+ grab_sub_body_contents(val, deref, buf);
+ grab_person("author", val, deref, buf);
+ grab_person("committer", val, deref, buf);
break;
case OBJ_TREE:
/* grab_tree_values(val, deref, obj, buf, sz); */
*s = show_ref(&atom->u.remote_ref.refname, refname);
else if (atom->u.remote_ref.option == RR_TRACK) {
if (stat_tracking_info(branch, &num_ours, &num_theirs,
- NULL, AHEAD_BEHIND_FULL) < 0) {
+ NULL, atom->u.remote_ref.push,
+ AHEAD_BEHIND_FULL) < 0) {
*s = xstrdup(msgs.gone);
} else if (!num_ours && !num_theirs)
*s = xstrdup("");
}
} else if (atom->u.remote_ref.option == RR_TRACKSHORT) {
if (stat_tracking_info(branch, &num_ours, &num_theirs,
- NULL, AHEAD_BEHIND_FULL) < 0) {
+ NULL, atom->u.remote_ref.push,
+ AHEAD_BEHIND_FULL) < 0) {
*s = xstrdup("");
return;
}
return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
oid_to_hex(&oi->oid), ref->refname);
}
- grab_values(ref->value, deref, *obj, oi->content, oi->size);
+ grab_values(ref->value, deref, *obj, oi->content);
}
grab_common_values(ref->value, deref, oi);
int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset)
{
- if (!arg) /* should --no-sort void the list ? */
- return -1;
+ /*
+ * NEEDSWORK: We should probably clear the list in this case, but we've
+ * already munged the global used_atoms list, which would need to be
+ * undone.
+ */
+ BUG_ON_OPT_NEG(unset);
+
parse_ref_sorting(opt->value, arg);
return 0;
}
return ret;
}
-static void free_ref(struct ref *ref)
+void free_one_ref(struct ref *ref)
{
if (!ref)
return;
- free_ref(ref->peer_ref);
+ free_one_ref(ref->peer_ref);
free(ref->remote_status);
free(ref->symref);
free(ref);
struct ref *next;
while (ref) {
next = ref->next;
- free_ref(ref);
+ free_one_ref(ref);
ref = next;
}
}
}
/*
- * Lookup the upstream branch for the given branch and if present, optionally
- * compute the commit ahead/behind values for the pair.
+ * Compute the commit ahead/behind values for the pair branch_name, base.
*
* If abf is AHEAD_BEHIND_FULL, compute the full ahead/behind and return the
* counts in *num_ours and *num_theirs. If abf is AHEAD_BEHIND_QUICK, skip
* the (potentially expensive) a/b computation (*num_ours and *num_theirs are
* set to zero).
*
- * The name of the upstream branch (or NULL if no upstream is defined) is
- * returned via *upstream_name, if it is not itself NULL.
- *
- * Returns -1 if num_ours and num_theirs could not be filled in (e.g., no
- * upstream defined, or ref does not exist). Returns 0 if the commits are
- * identical. Returns 1 if commits are different.
+ * Returns -1 if num_ours and num_theirs could not be filled in (e.g., ref
+ * does not exist). Returns 0 if the commits are identical. Returns 1 if
+ * commits are different.
*/
- int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
- const char **upstream_name, enum ahead_behind_flags abf)
+
+ static int stat_branch_pair(const char *branch_name, const char *base,
+ int *num_ours, int *num_theirs,
+ enum ahead_behind_flags abf)
{
struct object_id oid;
struct commit *ours, *theirs;
struct rev_info revs;
- const char *base;
struct argv_array argv = ARGV_ARRAY_INIT;
- /* Cannot stat unless we are marked to build on top of somebody else. */
- base = branch_get_upstream(branch, NULL);
- if (upstream_name)
- *upstream_name = base;
- if (!base)
- return -1;
-
/* Cannot stat if what we used to build on no longer exists */
if (read_ref(base, &oid))
return -1;
if (!theirs)
return -1;
- if (read_ref(branch->refname, &oid))
+ if (read_ref(branch_name, &oid))
return -1;
ours = lookup_commit_reference(the_repository, &oid);
if (!ours)
if (abf == AHEAD_BEHIND_QUICK)
return 1;
if (abf != AHEAD_BEHIND_FULL)
- BUG("stat_tracking_info: invalid abf '%d'", abf);
+ BUG("stat_branch_pair: invalid abf '%d'", abf);
/* Run "rev-list --left-right ours...theirs" internally... */
argv_array_push(&argv, ""); /* ignored */
return 1;
}
+ /*
+ * Lookup the tracking branch for the given branch and if present, optionally
+ * compute the commit ahead/behind values for the pair.
+ *
+ * If for_push is true, the tracking branch refers to the push branch,
+ * otherwise it refers to the upstream branch.
+ *
+ * The name of the tracking branch (or NULL if it is not defined) is
+ * returned via *tracking_name, if it is not itself NULL.
+ *
+ * If abf is AHEAD_BEHIND_FULL, compute the full ahead/behind and return the
+ * counts in *num_ours and *num_theirs. If abf is AHEAD_BEHIND_QUICK, skip
+ * the (potentially expensive) a/b computation (*num_ours and *num_theirs are
+ * set to zero).
+ *
+ * Returns -1 if num_ours and num_theirs could not be filled in (e.g., no
+ * upstream defined, or ref does not exist). Returns 0 if the commits are
+ * identical. Returns 1 if commits are different.
+ */
+ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
+ const char **tracking_name, int for_push,
+ enum ahead_behind_flags abf)
+ {
+ const char *base;
+
+ /* Cannot stat unless we are marked to build on top of somebody else. */
+ base = for_push ? branch_get_push(branch, NULL) :
+ branch_get_upstream(branch, NULL);
+ if (tracking_name)
+ *tracking_name = base;
+ if (!base)
+ return -1;
+
+ return stat_branch_pair(branch->refname, base, num_ours, num_theirs, abf);
+ }
+
/*
* Return true when there is anything to report, otherwise false.
*/
char *base;
int upstream_is_gone = 0;
- sti = stat_tracking_info(branch, &ours, &theirs, &full_base, abf);
+ sti = stat_tracking_info(branch, &ours, &theirs, &full_base, 0, abf);
if (sti < 0) {
if (!full_base)
return 0;
int check_ref_type(const struct ref *ref, int flags);
/*
- * Frees the entire list and peers of elements.
+ * Free a single ref and its peer, or an entire list of refs and their peers,
+ * respectively.
*/
+void free_one_ref(struct ref *ref);
void free_refs(struct ref *ref);
struct oid_array;
/* Reporting of tracking info */
int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
- const char **upstream_name, enum ahead_behind_flags abf);
+ const char **upstream_name, int for_push,
+ enum ahead_behind_flags abf);
int format_tracking_info(struct branch *branch, struct strbuf *sb,
enum ahead_behind_flags abf);
void wt_status_collect(struct wt_status *s)
{
+ trace2_region_enter("status", "worktrees", s->repo);
wt_status_collect_changes_worktree(s);
- if (s->is_initial)
+ trace2_region_leave("status", "worktrees", s->repo);
+
+ if (s->is_initial) {
+ trace2_region_enter("status", "initial", s->repo);
wt_status_collect_changes_initial(s);
- else
+ trace2_region_leave("status", "initial", s->repo);
+ } else {
+ trace2_region_enter("status", "index", s->repo);
wt_status_collect_changes_index(s);
+ trace2_region_leave("status", "index", s->repo);
+ }
+
+ trace2_region_enter("status", "untracked", s->repo);
wt_status_collect_untracked(s);
+ trace2_region_leave("status", "untracked", s->repo);
wt_status_get_state(s->repo, &s->state, s->branch && !strcmp(s->branch, "HEAD"));
if (s->state.merge_in_progress && !has_unmerged(s))
return len;
}
-void wt_status_add_cut_line(FILE *fp)
+void wt_status_append_cut_line(struct strbuf *buf)
{
const char *explanation = _("Do not modify or remove the line above.\nEverything below it will be ignored.");
+
+ strbuf_commented_addf(buf, "%s", cut_line);
+ strbuf_add_commented_lines(buf, explanation, strlen(explanation));
+}
+
+void wt_status_add_cut_line(FILE *fp)
+{
struct strbuf buf = STRBUF_INIT;
- fprintf(fp, "%c %s", comment_line_char, cut_line);
- strbuf_add_commented_lines(&buf, explanation, strlen(explanation));
+ wt_status_append_cut_line(&buf);
fputs(buf.buf, fp);
strbuf_release(&buf);
}
color_fprintf(s->fp, branch_color_local, "%s", branch_name);
sti = stat_tracking_info(branch, &num_ours, &num_theirs, &base,
- s->ahead_behind_flags);
+ 0, s->ahead_behind_flags);
if (sti < 0) {
if (!base)
goto conclude;
branch = branch_get(branch_name);
base = NULL;
ab_info = stat_tracking_info(branch, &nr_ahead, &nr_behind,
- &base, s->ahead_behind_flags);
+ &base, 0, s->ahead_behind_flags);
if (base) {
base = shorten_unambiguous_ref(base, 0);
fprintf(s->fp, "# branch.upstream %s%c", base, eol);
void wt_status_print(struct wt_status *s)
{
+ trace2_data_intmax("status", s->repo, "count/changed", s->change.nr);
+ trace2_data_intmax("status", s->repo, "count/untracked",
+ s->untracked.nr);
+ trace2_data_intmax("status", s->repo, "count/ignored", s->ignored.nr);
+
+ trace2_region_enter("status", "print", s->repo);
+
switch (s->status_format) {
case STATUS_FORMAT_SHORT:
wt_shortstatus_print(s);
wt_longstatus_print(s);
break;
}
+
+ trace2_region_leave("status", "print", s->repo);
}
/**