tig-2.2
[tig.git] / src / refs.c
blob142ad1378b036e60f68c353529c8a511c01c543c
1 /* Copyright (c) 2006-2015 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.
14 #include "tig/io.h"
15 #include "tig/options.h"
16 #include "tig/parse.h"
17 #include "tig/display.h"
18 #include "tig/view.h"
19 #include "tig/draw.h"
20 #include "tig/git.h"
21 #include "tig/main.h"
24 * Branch backend
27 struct reference {
28 const struct ident *author; /* Author of the last commit. */
29 struct time time; /* Date of the last activity. */
30 char title[128]; /* First line of the commit message. */
31 const struct ref *ref; /* Name and commit ID information. */
34 static const struct ref *refs_all;
35 #define REFS_ALL_NAME "All references"
36 #define refs_is_all(reference) ((reference)->ref == refs_all)
38 static bool
39 refs_get_column_data(struct view *view, const struct line *line, struct view_column_data *column_data)
41 const struct reference *reference = line->data;
43 column_data->author = reference->author;
44 column_data->date = &reference->time;
45 column_data->id = reference->ref->id;
46 column_data->ref = reference->ref;
47 column_data->commit_title = reference->title;
49 return true;
52 static enum request
53 refs_request(struct view *view, enum request request, struct line *line)
55 struct reference *reference = line->data;
57 switch (request) {
58 case REQ_REFRESH:
59 load_refs(true);
60 refresh_view(view);
61 return REQ_NONE;
63 case REQ_ENTER:
65 const struct ref *ref = reference->ref;
66 const char *all_references_argv[] = {
67 GIT_MAIN_LOG(encoding_arg, commit_order_arg(),
68 "%(mainargs)", "",
69 refs_is_all(reference) ? "--all" : ref->name, "",
70 log_custom_pretty_arg())
73 if (!argv_format(main_view.env, &main_view.argv, all_references_argv, false, false))
74 report("Failed to format argument");
75 else
76 open_view(view, &main_view, OPEN_SPLIT | OPEN_PREPARED);
77 return REQ_NONE;
79 default:
80 return request;
84 static bool
85 refs_read(struct view *view, struct buffer *buf, bool force_stop)
87 struct reference template = {0};
88 char *author;
89 char *title;
90 size_t i;
92 if (!buf)
93 return true;
95 if (!*buf->data)
96 return false;
98 author = io_memchr(buf, buf->data, 0);
99 title = io_memchr(buf, author, 0);
101 if (author)
102 parse_author_line(author, &template.author, &template.time);
104 for (i = 0; i < view->lines; i++) {
105 struct reference *reference = view->line[i].data;
107 if (strcmp(reference->ref->id, buf->data))
108 continue;
110 reference->author = template.author;
111 reference->time = template.time;
113 if (title)
114 string_expand(reference->title, sizeof(reference->title), title, strlen(title), 1);
116 view->line[i].dirty = true;
117 view_column_info_update(view, &view->line[i]);
120 return true;
123 static bool
124 refs_open_visitor(void *data, const struct ref *ref)
126 struct view *view = data;
127 struct reference *reference;
128 bool is_all = ref == refs_all;
129 struct line *line;
131 line = add_line_alloc(view, &reference, LINE_DEFAULT, 0, is_all);
132 if (!line)
133 return false;
135 reference->ref = ref;
136 view_column_info_update(view, line);
138 return true;
141 static bool
142 refs_open(struct view *view, enum open_flags flags)
144 const char *refs_log[] = {
145 "git", "log", encoding_arg, "--no-color", "--date=raw",
146 opt_mailmap ? "--pretty=format:%H%x00%aN <%aE> %ad%x00%s"
147 : "--pretty=format:%H%x00%an <%ae> %ad%x00%s",
148 "--all", "--simplify-by-decoration", NULL
151 if (!refs_all) {
152 struct ref *ref = calloc(1, sizeof(*refs_all) + strlen(REFS_ALL_NAME));
154 if (ref) {
155 strncpy(ref->name, REFS_ALL_NAME, strlen(REFS_ALL_NAME));
156 refs_all = ref;
160 if (!refs_all || !begin_update(view, NULL, refs_log, OPEN_RELOAD)) {
161 report("Failed to load reference data");
162 return false;
165 if (!view->lines)
166 view->sort.current = get_view_column(view, VIEW_COLUMN_REF);
167 refs_open_visitor(view, refs_all);
168 foreach_ref(refs_open_visitor, view);
169 resort_view(view, true);
171 watch_register(&view->watch, WATCH_HEAD | WATCH_REFS);
173 return true;
176 static void
177 refs_select(struct view *view, struct line *line)
179 struct reference *reference = line->data;
181 if (refs_is_all(reference)) {
182 string_copy(view->ref, REFS_ALL_NAME);
183 return;
185 string_copy_rev(view->ref, reference->ref->id);
186 string_copy_rev(view->env->head, reference->ref->id);
187 string_ncopy(view->env->ref, reference->ref->name, strlen(reference->ref->name));
188 ref_update_env(view->env, reference->ref, false);
191 static struct view_ops refs_ops = {
192 "reference",
193 argv_env.head,
194 VIEW_REFRESH | VIEW_SORTABLE,
196 refs_open,
197 refs_read,
198 view_column_draw,
199 refs_request,
200 view_column_grep,
201 refs_select,
202 NULL,
203 view_column_bit(AUTHOR) | view_column_bit(COMMIT_TITLE) |
204 view_column_bit(DATE) | view_column_bit(ID) |
205 view_column_bit(LINE_NUMBER) | view_column_bit(REF),
206 refs_get_column_data,
209 DEFINE_VIEW(refs);
211 /* vim: set ts=8 sw=8 noexpandtab: */