Code

Minor cleanups
[tig.git] / tig.c
diff --git a/tig.c b/tig.c
index 0a86490272750de255b7d99a530eba9d39fcf12c..2431f66e56df34624c43345214f014a9a14082a4 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -59,8 +59,12 @@ static size_t utf8_length(const char *string, size_t max_width, int *coloffset,
 
 #define SIZEOF_STR     1024    /* Default string size. */
 #define SIZEOF_REF     256     /* Size of symbolic or SHA1 ID. */
+#define SIZEOF_REV     41      /* Holds a SHA-1 and an ending NUL */
 #define SIZEOF_REVGRAPH        19      /* Size of revision ancestry graphics. */
 
+/* Size of rev graph with no  "padding" columns */
+#define SIZEOF_REVITEMS        (SIZEOF_REVGRAPH - (SIZEOF_REVGRAPH / 2))
+
 /* This color name can be used to refer to the default term colors. */
 #define COLOR_DEFAULT  (-1)
 
@@ -109,7 +113,7 @@ static size_t utf8_length(const char *string, size_t max_width, int *coloffset,
 
 struct ref {
        char *name;             /* Ref name; tag or head names are shortened. */
-       char id[41];            /* Commit SHA1 ID */
+       char id[SIZEOF_REV];    /* Commit SHA1 ID */
        unsigned int tag:1;     /* Is it a tag? */
        unsigned int next:1;    /* For ref lists: are there more refs? */
 };
@@ -2447,7 +2451,7 @@ static struct view_ops pager_ops = {
  * Tree backend
  */
 
-/* Parse output from git ls-tree:
+/* Parse output from git-ls-tree(1):
  *
  * 100644 blob fb0e31ea6cc679b7379631188190e975f5789c26        Makefile
  * 100644 blob 5304ca4260aaddaee6498f9630e7d471b8591ea6        README
@@ -2558,7 +2562,6 @@ static bool
 tree_enter(struct view *view, struct line *line)
 {
        enum open_flags flags = display[0] == view ? OPEN_SPLIT : OPEN_DEFAULT;
-       char *data = line->data;
        enum request request;
 
        switch (line->type) {
@@ -2577,6 +2580,7 @@ tree_enter(struct view *view, struct line *line)
                } else {
                        size_t pathlen = strlen(opt_path);
                        size_t origlen = pathlen;
+                       char *data = line->data;
                        char *basename = data + SIZEOF_TREE_ATTR;
 
                        if (!string_format_from(opt_path, &pathlen, "%s/", basename)) {
@@ -2659,7 +2663,7 @@ static struct view_ops blob_ops = {
  */
 
 struct commit {
-       char id[41];                    /* SHA1 ID. */
+       char id[SIZEOF_REV];            /* SHA1 ID. */
        char title[75];                 /* First line of the commit message. */
        char author[75];                /* Author of the commit. */
        struct tm time;                 /* Date from the author ident. */
@@ -2775,6 +2779,89 @@ main_draw(struct view *view, struct line *line, unsigned int lineno, bool select
        return TRUE;
 }
 
+
+struct rev_stack {
+       char rev[SIZEOF_REVITEMS][SIZEOF_REV];
+       size_t size;
+};
+
+/* The current stack of revisions on the graph. */
+static struct rev_stack graph_stacks[2];
+static unsigned int graph_stack_no;
+
+/* Parents of the commit being visualized. */
+static struct rev_stack graph_parents;
+
+static void
+push_rev_stack(struct rev_stack *stack, char *parent)
+{
+       fprintf(stderr, " (%s)", parent);
+
+       /* Combine duplicate parents lines. */
+       if (stack->size > 0 &&
+           !strncmp(stack->rev[stack->size - 1], parent, SIZEOF_REV))
+               return;
+
+       if (stack->size < SIZEOF_REVITEMS) {
+               string_ncopy(stack->rev[stack->size++], parent, SIZEOF_REV);
+       }
+}
+
+void
+update_rev_graph(struct commit *commit)
+{
+       struct rev_stack *stack = &graph_stacks[graph_stack_no++ & 1];
+       struct rev_stack *graph = &graph_stacks[graph_stack_no & 1];
+       chtype symbol;
+       size_t stackpos = 0;
+       size_t i;
+
+       // FIXME: Initial commit ... assert(rev_graph_commit == commit);
+       fprintf(stderr, "\n%p <%s> ", graph, commit->id);
+
+       /* First traverse all lines of revisions up to the active one. */
+       for (stackpos = 0; stackpos < stack->size; stackpos++) {
+               if (!strcmp(stack->rev[stackpos], commit->id)) {
+                       while (stackpos + 1 < stack->size &&
+                              !strcmp(stack->rev[stackpos + 1], commit->id))
+                               stackpos++;
+                       break;
+               }
+
+               push_rev_stack(graph, stack->rev[stackpos]);
+               commit->graph[commit->graph_size++] = ACS_VLINE;
+               commit->graph[commit->graph_size++] = ' ';
+       }
+
+       assert(commit->graph_size < ARRAY_SIZE(commit->graph));
+
+       for (i = 0; i < graph_parents.size; i++)
+               push_rev_stack(graph, graph_parents.rev[i]);
+
+       /* Place the symbol for this commit. */
+       if (graph_parents.size == 0)
+               symbol = 'I';
+       else if (graph_parents.size > 1)
+               symbol = 'M';
+       else if (stackpos >= stack->size)
+               symbol = '+';
+       else
+               symbol = '*';
+
+       commit->graph[commit->graph_size++] = symbol;
+
+       stackpos++;
+
+       /* FIXME: Moving branches left and right when collapsing a branch. */
+       while (stackpos < stack->size) {
+               push_rev_stack(graph, stack->rev[stackpos++]);
+               commit->graph[commit->graph_size++] = ' ';
+               commit->graph[commit->graph_size++] = ACS_VLINE;
+       }
+
+       stack->size = graph_parents.size = 0;
+}
+
 /* Reads git log --pretty=raw output and parses it into the commit struct. */
 static bool
 main_read(struct view *view, char *line)
@@ -2794,7 +2881,14 @@ main_read(struct view *view, char *line)
                view->line[view->lines++].data = commit;
                string_copy(commit->id, line);
                commit->refs = get_refs(commit->id);
-               commit->graph[commit->graph_size++] = ACS_LTEE;
+               fprintf(stderr, "\n%p [%s]", &graph_stacks[graph_stack_no], commit->id);
+               break;
+
+       case LINE_PARENT:
+               if (commit) {
+                       line += STRING_SIZE("parent ");
+                       push_rev_stack(&graph_parents, line);
+               }
                break;
 
        case LINE_AUTHOR:
@@ -2805,6 +2899,8 @@ main_read(struct view *view, char *line)
                if (!commit)
                        break;
 
+               update_rev_graph(commit);
+
                if (end) {
                        char *email = end + 1;