index a442024168dbf6d692e62437db4fab308f3173ac..222b3698de6bcc60395ab74519b4c9048e2e5ed6 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -114,10 +114,6 @@ static size_t utf8_length(const char **string, size_t col, int *width, size_t ma
#define S_ISGITLINK(mode) (((mode) & S_IFMT) == 0160000)
#define S_ISGITLINK(mode) (((mode) & S_IFMT) == 0160000)
-#ifndef GIT_CONFIG
-#define GIT_CONFIG "config"
-#endif
-
/* Some ASCII-shorthands fitted into the ncurses namespace. */
#define KEY_TAB '\t'
#define KEY_RETURN '\r'
/* Some ASCII-shorthands fitted into the ncurses namespace. */
#define KEY_TAB '\t'
#define KEY_RETURN '\r'
}
static bool
}
static bool
-io_open(struct io *io, const char *name)
+io_open(struct io *io, const char *fmt, ...)
{
{
+ char name[SIZEOF_STR] = "";
+ bool fits;
+ va_list args;
+
init_io(io, NULL, IO_FD);
init_io(io, NULL, IO_FD);
+
+ va_start(args, fmt);
+ fits = vsnprintf(name, sizeof(name), fmt, args) < sizeof(name);
+ va_end(args);
+
+ if (!fits) {
+ io->error = ENAMETOOLONG;
+ return FALSE;
+ }
io->pipe = *name ? open(name, O_RDONLY) : STDIN_FILENO;
if (io->pipe == -1)
io->error = errno;
io->pipe = *name ? open(name, O_RDONLY) : STDIN_FILENO;
if (io->pipe == -1)
io->error = errno;
}
static bool
}
static bool
-run_io_rd(struct io *io, const char **argv, enum format_flags flags)
+run_io_rd(struct io *io, const char **argv, const char *dir, enum format_flags flags)
{
{
- return init_io_rd(io, argv, NULL, flags) && start_io(io);
+ return init_io_rd(io, argv, dir, flags) && start_io(io);
}
static bool
}
static bool
{
struct io io = {};
{
struct io io = {};
- return run_io_rd(&io, argv, FORMAT_NONE) && io_read_buf(&io, buf, bufsize);
+ return run_io_rd(&io, argv, NULL, FORMAT_NONE)
+ && io_read_buf(&io, buf, bufsize);
}
static int
}
static int
struct io io = {};
/* It's OK that the file doesn't exist. */
struct io io = {};
/* It's OK that the file doesn't exist. */
- if (!io_open(&io, path))
+ if (!io_open(&io, "%s", path))
return;
config_lineno = 0;
return;
config_lineno = 0;
bool (*grep)(struct view *view, struct line *line);
/* Select line */
void (*select)(struct view *view, struct line *line);
bool (*grep)(struct view *view, struct line *line);
/* Select line */
void (*select)(struct view *view, struct line *line);
+ /* Prepare view for loading */
+ bool (*prepare)(struct view *view);
};
static struct view_ops blame_ops;
};
static struct view_ops blame_ops;
@@ -2149,7 +2161,7 @@ draw_field(struct view *view, enum line_type type, const char *text, int len, bo
static bool
draw_date(struct view *view, time_t *time)
{
static bool
draw_date(struct view *view, time_t *time)
{
- const char *date = mkdate(time);
+ const char *date = time ? mkdate(time) : "";
int cols = opt_date == DATE_SHORT ? DATE_SHORT_COLS : DATE_COLS;
return draw_field(view, LINE_DATE, date, cols, FALSE);
int cols = opt_date == DATE_SHORT ? DATE_SHORT_COLS : DATE_COLS;
return draw_field(view, LINE_DATE, date, cols, FALSE);
{
if (view->pipe)
end_update(view, TRUE);
{
if (view->pipe)
end_update(view, TRUE);
- return io_open(&view->io, name);
+ return io_open(&view->io, "%s", name);
}
static bool
}
static bool
if (view->pipe)
end_update(view, TRUE);
if (view->pipe)
end_update(view, TRUE);
- if (refresh) {
- if (!start_io(&view->io))
- return FALSE;
-
- } else {
- if (view == VIEW(REQ_VIEW_TREE) && strcmp(view->vid, view->id))
- opt_path[0] = 0;
-
- if (!run_io_rd(&view->io, view->ops->argv, FORMAT_ALL))
+ if (!refresh) {
+ if (view->ops->prepare) {
+ if (!view->ops->prepare(view))
+ return FALSE;
+ } else if (!init_io_rd(&view->io, view->ops->argv, NULL, FORMAT_ALL)) {
return FALSE;
return FALSE;
+ }
/* Put the current ref_* value to the view title ref
* member. This is needed by the blob view. Most other
/* Put the current ref_* value to the view title ref
* member. This is needed by the blob view. Most other
string_copy_rev(view->ref, view->id);
}
string_copy_rev(view->ref, view->id);
}
+ if (!start_io(&view->io))
+ return FALSE;
+
setup_update(view, view->id);
return TRUE;
setup_update(view, view->id);
return TRUE;
display[current_view] = view;
}
display[current_view] = view;
}
+ /* No parent signals that this is the first loaded view. */
+ if (prev && view != prev) {
+ view->parent = prev;
+ }
+
/* Resize the view when switching between split- and full-screen,
* or when switching between two different full-screen views. */
if (nviews != displayed_views() ||
/* Resize the view when switching between split- and full-screen,
* or when switching between two different full-screen views. */
if (nviews != displayed_views() ||
/* "Blur" the previous view. */
update_view_title(prev);
}
/* "Blur" the previous view. */
update_view_title(prev);
}
-
- view->parent = prev;
}
if (view->pipe && view->lines == 0) {
}
if (view->pipe && view->lines == 0) {
return TRUE;
}
return TRUE;
}
- if (!run_io_rd(&io, log_file, FORMAT_NONE)) {
+ if (!run_io_rd(&io, log_file, opt_cdup, FORMAT_NONE)) {
report("Failed to load tree data");
return TRUE;
}
report("Failed to load tree data");
return TRUE;
}
if (!pos)
return TRUE;
text = pos + 1;
if (!pos)
return TRUE;
text = pos + 1;
- if (*opt_prefix && !strncmp(text, opt_prefix, strlen(opt_prefix)))
- text += strlen(opt_prefix);
if (*opt_path && !strncmp(text, opt_path, strlen(opt_path)))
text += strlen(opt_path);
pos = strchr(text, '/');
if (*opt_path && !strncmp(text, opt_path, strlen(opt_path)))
text += strlen(opt_path);
pos = strchr(text, '/');
string_copy_rev(view->ref, entry->id);
}
string_copy_rev(view->ref, entry->id);
}
+static bool
+tree_prepare(struct view *view)
+{
+ if (view->lines == 0 && opt_prefix[0]) {
+ char *pos = opt_prefix;
+
+ while (pos && *pos) {
+ char *end = strchr(pos, '/');
+
+ if (end)
+ *end = 0;
+ push_tree_stack_entry(pos, 0);
+ pos = end;
+ if (end) {
+ *end = '/';
+ pos++;
+ }
+ }
+
+ } else if (strcmp(view->vid, view->id)) {
+ opt_path[0] = 0;
+ }
+
+ return init_io_rd(&view->io, view->ops->argv, opt_cdup, FORMAT_ALL);
+}
+
static const char *tree_argv[SIZEOF_ARG] = {
"git", "ls-tree", "%(commit)", "%(directory)", NULL
};
static const char *tree_argv[SIZEOF_ARG] = {
"git", "ls-tree", "%(commit)", "%(directory)", NULL
};
tree_request,
tree_grep,
tree_select,
tree_request,
tree_grep,
tree_select,
+ tree_prepare,
};
static bool
};
static bool
static bool
blame_open(struct view *view)
{
static bool
blame_open(struct view *view)
{
- if (*opt_ref || !io_open(&view->io, opt_file)) {
- if (!run_io_rd(&view->io, blame_cat_file_argv, FORMAT_ALL))
+ char path[SIZEOF_STR];
+
+ if (!view->parent && *opt_prefix) {
+ string_copy(path, opt_file);
+ if (!string_format(opt_file, "%s%s", opt_prefix, path))
+ return FALSE;
+ }
+
+ if (*opt_ref || !io_open(&view->io, "%s%s", opt_cdup, opt_file)) {
+ if (!run_io_rd(&view->io, blame_cat_file_argv, opt_cdup, FORMAT_ALL))
return FALSE;
}
return FALSE;
}
if (view->lines == 0 && !view->parent)
die("No blame exist for %s", view->vid);
if (view->lines == 0 && !view->parent)
die("No blame exist for %s", view->vid);
- if (view->lines == 0 || !run_io_rd(&io, argv, FORMAT_ALL)) {
+ if (view->lines == 0 || !run_io_rd(&io, argv, opt_cdup, FORMAT_ALL)) {
report("Failed to load blame data");
return TRUE;
}
report("Failed to load blame data");
return TRUE;
}
"--simplify-by-decoration", "--all", NULL
};
"--simplify-by-decoration", "--all", NULL
};
- if (!run_io_rd(&view->io, branch_log, FORMAT_NONE)) {
+ if (!run_io_rd(&view->io, branch_log, NULL, FORMAT_NONE)) {
report("Failed to load branch data");
return TRUE;
}
report("Failed to load branch data");
return TRUE;
}
if (!*opt_head) {
struct io io = {};
if (!*opt_head) {
struct io io = {};
- if (string_format(buf, "%s/rebase-merge/head-name", opt_git_dir) &&
- io_open(&io, buf) &&
+ if (io_open(&io, "%s/rebase-merge/head-name", opt_git_dir) &&
io_read_buf(&io, buf, sizeof(buf))) {
head = buf;
if (!prefixcmp(head, "refs/heads/"))
io_read_buf(&io, buf, sizeof(buf))) {
head = buf;
if (!prefixcmp(head, "refs/heads/"))
} else {
report("Cannot revert changes to multiple files");
}
} else {
report("Cannot revert changes to multiple files");
}
- return FALSE;
- } else {
+ } else if (prompt_yesno("Are you sure you want to revert changes?")) {
char mode[10] = "100644";
const char *reset_argv[] = {
"git", "update-index", "--cacheinfo", mode,
char mode[10] = "100644";
const char *reset_argv[] = {
"git", "update-index", "--cacheinfo", mode,
"git", "checkout", "--", status->old.name, NULL
};
"git", "checkout", "--", status->old.name, NULL
};
- if (!prompt_yesno("Are you sure you want to overwrite any changes?"))
- return FALSE;
- string_format(mode, "%o", status->old.mode);
- return (status->status != 'U' || run_io_fg(reset_argv, opt_cdup)) &&
- run_io_fg(checkout_argv, opt_cdup);
+ if (status->status == 'U') {
+ string_format(mode, "%5o", status->old.mode);
+
+ if (status->old.mode == 0 && status->new.mode == 0) {
+ reset_argv[2] = "--force-remove";
+ reset_argv[3] = status->old.name;
+ reset_argv[4] = NULL;
+ }
+
+ if (!run_io_fg(reset_argv, opt_cdup))
+ return FALSE;
+ if (status->old.mode == 0 && status->new.mode == 0)
+ return TRUE;
+ }
+
+ return run_io_fg(checkout_argv, opt_cdup);
}
}
+
+ return FALSE;
}
static enum request
}
static enum request
@@ -7419,7 +7478,7 @@ read_repo_config_option(char *name, size_t namelen, char *value, size_t valuelen
static int
load_git_config(void)
{
static int
load_git_config(void)
{
- const char *config_list_argv[] = { "git", GIT_CONFIG, "--list", NULL };
+ const char *config_list_argv[] = { "git", "config", "--list", NULL };
return run_io_load(config_list_argv, "=", read_repo_config_option);
}
return run_io_load(config_list_argv, "=", read_repo_config_option);
}