Merge pull request #530 from jjlin/master
[tig.git] / src / blob.c
blobf1c4da5f03f2f6d608509987d750099e0c7f7a76
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/refdb.h"
15 #include "tig/parse.h"
16 #include "tig/repo.h"
17 #include "tig/display.h"
18 #include "tig/draw.h"
19 #include "tig/ui.h"
20 #include "tig/pager.h"
21 #include "tig/tree.h"
22 #include "tig/blob.h"
24 struct blob_state {
25 char commit[SIZEOF_REF];
26 const char *file;
29 void
30 open_blob_view(struct view *prev, enum open_flags flags)
32 struct view *view = &blob_view;
33 bool in_blob_view = prev == view;
34 bool has_blob_selection = view->env->blob[0] || view->env->file[0];
36 if (!in_blob_view && (view->lines || has_blob_selection)) {
37 open_view(prev, view, flags);
39 } else {
40 const char *file = open_file_finder(view->env->commit);
42 if (file) {
43 clear_position(&view->pos);
44 string_ncopy(view->env->file, file, strlen(file));
45 view->env->blob[0] = 0;
46 open_view(prev, view, OPEN_RELOAD);
51 static bool
52 blob_open(struct view *view, enum open_flags flags)
54 struct blob_state *state = view->private;
55 static const char *blob_argv[] = {
56 "git", "cat-file", "blob", "%(blob)", NULL
58 const char **argv = (flags & (OPEN_PREPARED | OPEN_REFRESH)) ? view->argv : blob_argv;
60 if (argv != blob_argv) {
61 state->file = get_path(view->env->file);
62 state->commit[0] = 0;
65 if (!state->file && !view->env->blob[0] && view->env->file[0]) {
66 const char *commit = view->env->commit[0] && !string_rev_is_null(view->env->commit)
67 ? view->env->commit : "HEAD";
68 char blob_spec[SIZEOF_STR];
69 const char *rev_parse_argv[] = {
70 "git", "rev-parse", blob_spec, NULL
73 if (!string_format(blob_spec, "%s:%s", commit, view->env->file) ||
74 !io_run_buf(rev_parse_argv, view->env->blob, sizeof(view->env->blob), false)) {
75 report("Failed to resolve blob from file name");
76 return false;
79 string_ncopy(state->commit, commit, strlen(commit));
82 if (!state->file && !view->env->blob[0]) {
83 report("No file chosen, press %s to open tree view",
84 get_view_key(view, REQ_VIEW_TREE));
85 return false;
88 view->encoding = get_path_encoding(view->env->file, default_encoding);
90 if (*view->env->file)
91 string_copy(view->ref, view->env->file);
92 else
93 string_copy_rev(view->ref, view->ops->id);
95 return begin_update(view, NULL, argv, flags);
98 static bool
99 blob_read(struct view *view, struct buffer *buf, bool force_stop)
101 if (!buf) {
102 if (view->env->goto_lineno > 0) {
103 select_view_line(view, view->env->goto_lineno);
104 view->env->goto_lineno = 0;
106 return true;
109 return pager_common_read(view, buf->data, LINE_DEFAULT, NULL);
112 static void
113 blob_select(struct view *view, struct line *line)
115 struct blob_state *state = view->private;
117 if (state->file)
118 string_format(view->env->file, "%s", state->file);
119 view->env->lineno = view->pos.lineno + 1;
122 static enum request
123 blob_request(struct view *view, enum request request, struct line *line)
125 struct blob_state *state = view->private;
127 switch (request) {
128 case REQ_REFRESH:
129 if (!state->file) {
130 report("Cannot reload immutable blob");
131 } else {
132 string_ncopy(view->env->file, state->file, strlen(state->file));
133 refresh_view(view);
135 return REQ_NONE;
137 case REQ_VIEW_BLAME:
138 string_ncopy(view->env->ref, state->commit, strlen(state->commit));
139 view->env->goto_lineno = line - view->line;
140 return request;
142 case REQ_EDIT:
143 if (state->file)
144 open_editor(state->file, (line - view->line) + 1);
145 else
146 open_blob_editor(view->vid, NULL, (line - view->line) + 1);
147 return REQ_NONE;
149 default:
150 return pager_request(view, request, line);
154 static struct view_ops blob_ops = {
155 "line",
156 argv_env.blob,
157 VIEW_NO_FLAGS | VIEW_REFRESH,
158 sizeof(struct blob_state),
159 blob_open,
160 blob_read,
161 view_column_draw,
162 blob_request,
163 view_column_grep,
164 blob_select,
165 NULL,
166 view_column_bit(LINE_NUMBER) | view_column_bit(TEXT),
167 pager_get_column_data,
170 DEFINE_VIEW(blob);
172 /* vim: set ts=8 sw=8 noexpandtab: */