1 /* Copyright (c) 2006-2014 Jonas Fonseca <jonas.fonseca@gmail.com>
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include "tig/options.h"
16 #include "tig/parse.h"
17 #include "tig/display.h"
27 const struct ident
*author
; /* Author of the last commit. */
28 struct time time
; /* Date of the last activity. */
29 char title
[128]; /* First line of the commit message. */
30 const struct ref
*ref
; /* Name and commit ID information. */
33 static const struct ref branch_all
;
34 #define BRANCH_ALL_NAME "All branches"
35 #define branch_is_all(branch) ((branch)->ref == &branch_all)
37 static const enum sort_field branch_sort_fields
[] = {
38 SORT_FIELD_NAME
, SORT_FIELD_DATE
, SORT_FIELD_AUTHOR
41 static struct sort_state branch_sort_state
= SORT_STATE(branch_sort_fields
);
45 size_t max_ref_length
;
49 branch_compare(const void *l1
, const void *l2
)
51 const struct branch
*branch1
= ((const struct line
*) l1
)->data
;
52 const struct branch
*branch2
= ((const struct line
*) l2
)->data
;
54 if (branch_is_all(branch1
))
56 else if (branch_is_all(branch2
))
59 switch (get_sort_field(branch_sort_state
)) {
61 return sort_order(branch_sort_state
, timecmp(&branch1
->time
, &branch2
->time
));
63 case SORT_FIELD_AUTHOR
:
64 return sort_order(branch_sort_state
, ident_compare(branch1
->author
, branch2
->author
));
68 return sort_order(branch_sort_state
, strcmp(branch1
->ref
->name
, branch2
->ref
->name
));
72 static struct sortable branch_sortable
= { &branch_sort_state
, branch_compare
};
75 branch_draw(struct view
*view
, struct line
*line
, unsigned int lineno
)
77 struct branch_state
*state
= view
->private;
78 struct branch
*branch
= line
->data
;
79 enum line_type type
= branch_is_all(branch
) ? LINE_DEFAULT
: get_line_type_from_ref(branch
->ref
);
80 const char *branch_name
= branch_is_all(branch
) ? BRANCH_ALL_NAME
: branch
->ref
->name
;
82 if (draw_lineno(view
, lineno
))
85 if (draw_date(view
, &branch
->time
))
88 if (draw_author(view
, branch
->author
))
91 if (draw_field(view
, type
, branch_name
, state
->max_ref_length
, ALIGN_LEFT
, FALSE
))
94 if (draw_id(view
, branch
->ref
->id
))
97 draw_text(view
, LINE_DEFAULT
, branch
->title
);
102 branch_request(struct view
*view
, enum request request
, struct line
*line
)
104 struct branch
*branch
= line
->data
;
114 const struct ref
*ref
= branch
->ref
;
115 const char *all_branches_argv
[] = {
116 GIT_MAIN_LOG(encoding_arg
, commit_order_arg(), "", branch_is_all(branch
) ? "--all" : ref
->name
, "")
118 struct view
*main_view
= VIEW(REQ_VIEW_MAIN
);
120 open_argv(view
, main_view
, all_branches_argv
, NULL
, OPEN_SPLIT
);
123 case REQ_JUMP_COMMIT
:
127 for (lineno
= 0; lineno
< view
->lines
; lineno
++) {
128 struct branch
*branch
= view
->line
[lineno
].data
;
130 if (!strncasecmp(branch
->ref
->id
, view
->env
->search
, strlen(view
->env
->search
))) {
131 select_view_line(view
, lineno
);
143 branch_read(struct view
*view
, char *line
)
145 struct branch_state
*state
= view
->private;
146 const char *title
= NULL
;
147 const struct ident
*author
= NULL
;
148 struct time time
= {};
154 switch (get_line_type(line
)) {
156 string_copy_rev_from_commit_line(state
->id
, line
);
160 parse_author_line(line
+ STRING_SIZE("author "), &author
, &time
);
164 title
= line
+ STRING_SIZE("title ");
167 for (i
= 0; i
< view
->lines
; i
++) {
168 struct branch
*branch
= view
->line
[i
].data
;
170 if (strcmp(branch
->ref
->id
, state
->id
))
174 branch
->author
= author
;
179 string_expand(branch
->title
, sizeof(branch
->title
), title
, 1);
181 view
->line
[i
].dirty
= TRUE
;
188 branch_open_visitor(void *data
, const struct ref
*ref
)
190 struct view
*view
= data
;
191 struct branch_state
*state
= view
->private;
192 struct branch
*branch
;
193 bool is_all
= ref
== &branch_all
;
196 if (ref
->tag
|| ref
->ltag
)
199 if (!add_line_alloc(view
, &branch
, LINE_DEFAULT
, 0, is_all
))
202 ref_length
= is_all
? STRING_SIZE(BRANCH_ALL_NAME
) : strlen(ref
->name
);
203 if (ref_length
> state
->max_ref_length
)
204 state
->max_ref_length
= ref_length
;
211 branch_open(struct view
*view
, enum open_flags flags
)
213 const char *branch_log
[] = {
214 "git", "log", encoding_arg
, "--no-color", "--date=raw",
215 "--pretty=format:commit %H%nauthor %an <%ae> %ad%ntitle %s",
216 "--all", "--simplify-by-decoration", NULL
219 if (!begin_update(view
, NULL
, branch_log
, OPEN_RELOAD
)) {
220 report("Failed to load branch data");
224 branch_open_visitor(view
, &branch_all
);
225 foreach_ref(branch_open_visitor
, view
);
231 branch_grep(struct view
*view
, struct line
*line
)
233 struct branch
*branch
= line
->data
;
234 const char *text
[] = {
236 mkauthor(branch
->author
, opt_author_width
, opt_show_author
),
240 return grep_text(view
, text
);
244 branch_select(struct view
*view
, struct line
*line
)
246 struct branch
*branch
= line
->data
;
248 if (branch_is_all(branch
)) {
249 string_copy(view
->ref
, BRANCH_ALL_NAME
);
252 string_copy_rev(view
->ref
, branch
->ref
->id
);
253 string_copy_rev(view
->env
->commit
, branch
->ref
->id
);
254 string_copy_rev(view
->env
->head
, branch
->ref
->id
);
255 string_copy_rev(view
->env
->branch
, branch
->ref
->name
);
258 struct view_ops branch_ops
= {
263 sizeof(struct branch_state
),
274 /* vim: set ts=8 sw=8 noexpandtab: */