index b404f56f1d51a8bac32a814ee43302046f46afc9..0390b3a00276a2ce4060daf9bd323aedd45e6f04 100644 (file)
--- a/tig.c
+++ b/tig.c
-/* Copyright (c) 2006 Jonas Fonseca <fonseca@diku.dk>
+/* Copyright (c) 2006-2007 Jonas Fonseca <fonseca@diku.dk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* GNU General Public License for more details.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#ifndef TIG_VERSION
#define TIG_VERSION "unknown-version"
#endif
#include <curses.h>
-#include "config.h"
-
#if __GNUC__ >= 3
#define __NORETURN __attribute__((__noreturn__))
#else
#define SCALE_SPLIT_VIEW(height) ((height) * 2 / 3)
#ifndef GIT_CONFIG
-#define "git config"
+#define GIT_CONFIG "git config"
#endif
#define TIG_LS_REMOTE \
LINE(MAIN_REF, "", COLOR_CYAN, COLOR_DEFAULT, A_BOLD), \
LINE(TREE_DIR, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \
LINE(TREE_FILE, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \
-LINE(STAT_SECTION, "", COLOR_DEFAULT, COLOR_BLUE, A_BOLD), \
+LINE(STAT_SECTION, "", COLOR_CYAN, COLOR_DEFAULT, 0), \
LINE(STAT_NONE, "", COLOR_DEFAULT, COLOR_DEFAULT, 0), \
-LINE(STAT_STAGED, "", COLOR_CYAN, COLOR_DEFAULT, 0), \
-LINE(STAT_UNSTAGED,"", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(STAT_STAGED, "", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
+LINE(STAT_UNSTAGED,"", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
LINE(STAT_UNTRACKED,"", COLOR_MAGENTA, COLOR_DEFAULT, 0)
enum line_type {
line[linelen - 1] = 0;
if (opt_iconv != ICONV_NONE) {
- ICONV_INBUF_TYPE inbuf = line;
+ ICONV_CONST char *inbuf = line;
size_t inlen = linelen;
char *outbuf = out_buffer;
static bool
blob_read(struct view *view, char *line)
{
- return add_line_text(view, line, LINE_DEFAULT);
+ return add_line_text(view, line, LINE_DEFAULT) != NULL;
}
static struct view_ops blob_ops = {
char name[SIZEOF_STR];
};
+static struct status stage_status;
+static enum line_type stage_line_type;
+
/* Get fields from the diff line:
* :100644 100644 06a5d6ae9eca55be2e0e585a152e6b1336f2b20e 0000000000000000000000000000000000000000 M
*/
open_view(view, REQ_VIEW_STAGE, OPEN_RELOAD | OPEN_SPLIT);
if (view_is_displayed(VIEW(REQ_VIEW_STAGE))) {
- string_format(VIEW(REQ_VIEW_STAGE)->ref, info, status->name);
+ if (status) {
+ stage_status = *status;
+ } else {
+ memset(&stage_status, 0, sizeof(stage_status));
+ }
+
+ stage_line_type = line->type;
+ string_format(VIEW(REQ_VIEW_STAGE)->ref, info, stage_status.name);
}
return REQ_NONE;
status_select,
};
+
+static bool
+stage_diff_line(FILE *pipe, struct line *line)
+{
+ char *buf = line->data;
+ size_t bufsize = strlen(buf);
+ size_t written = 0;
+
+ while (!ferror(pipe) && written < bufsize) {
+ written += fwrite(buf + written, 1, bufsize - written, pipe);
+ }
+
+ fputc('\n', pipe);
+
+ return written == bufsize;
+}
+
+static struct line *
+stage_diff_hdr(struct view *view, struct line *line)
+{
+ int diff_hdr_dir = line->type == LINE_DIFF_CHUNK ? -1 : 1;
+ struct line *diff_hdr;
+
+ if (line->type == LINE_DIFF_CHUNK)
+ diff_hdr = line - 1;
+ else
+ diff_hdr = view->line + 1;
+
+ while (diff_hdr > view->line && diff_hdr < view->line + view->lines) {
+ if (diff_hdr->type == LINE_DIFF_HEADER)
+ return diff_hdr;
+
+ diff_hdr += diff_hdr_dir;
+ }
+
+ return NULL;
+}
+
+static bool
+stage_update_chunk(struct view *view, struct line *line)
+{
+ char cmd[SIZEOF_STR];
+ size_t cmdsize = 0;
+ struct line *diff_hdr, *diff_chunk, *diff_end;
+ FILE *pipe;
+
+ diff_hdr = stage_diff_hdr(view, line);
+ if (!diff_hdr)
+ return FALSE;
+
+ if (opt_cdup[0] &&
+ !string_format_from(cmd, &cmdsize, "cd %s;", opt_cdup))
+ return FALSE;
+
+ if (!string_format_from(cmd, &cmdsize,
+ "git apply --cached %s - && "
+ "git update-index -q --unmerged --refresh 2>/dev/null",
+ stage_line_type == LINE_STAT_STAGED ? "-R" : ""))
+ return FALSE;
+
+ pipe = popen(cmd, "w");
+ if (!pipe)
+ return FALSE;
+
+ diff_end = view->line + view->lines;
+ if (line->type != LINE_DIFF_CHUNK) {
+ diff_chunk = diff_hdr;
+
+ } else {
+ for (diff_chunk = line + 1; diff_chunk < diff_end; diff_chunk++)
+ if (diff_chunk->type == LINE_DIFF_CHUNK ||
+ diff_chunk->type == LINE_DIFF_HEADER)
+ diff_end = diff_chunk;
+
+ diff_chunk = line;
+
+ while (diff_hdr->type != LINE_DIFF_CHUNK) {
+ switch (diff_hdr->type) {
+ case LINE_DIFF_HEADER:
+ case LINE_DIFF_INDEX:
+ case LINE_DIFF_ADD:
+ case LINE_DIFF_DEL:
+ break;
+
+ default:
+ diff_hdr++;
+ continue;
+ }
+
+ if (!stage_diff_line(pipe, diff_hdr++)) {
+ pclose(pipe);
+ return FALSE;
+ }
+ }
+ }
+
+ while (diff_chunk < diff_end && stage_diff_line(pipe, diff_chunk))
+ diff_chunk++;
+
+ pclose(pipe);
+
+ if (diff_chunk != diff_end)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+stage_update(struct view *view, struct line *line)
+{
+ if (stage_line_type != LINE_STAT_UNTRACKED &&
+ (line->type == LINE_DIFF_CHUNK || !stage_status.status)) {
+ if (!stage_update_chunk(view, line)) {
+ report("Failed to apply chunk");
+ return;
+ }
+
+ } else if (!status_update_file(view, &stage_status, stage_line_type)) {
+ report("Failed to update file");
+ return;
+ }
+
+ open_view(view, REQ_VIEW_STATUS, OPEN_RELOAD);
+
+ view = VIEW(REQ_VIEW_STATUS);
+ if (view_is_displayed(view))
+ status_enter(view, &view->line[view->lineno]);
+}
+
+static enum request
+stage_request(struct view *view, enum request request, struct line *line)
+{
+ switch (request) {
+ case REQ_STATUS_UPDATE:
+ stage_update(view, line);
+ break;
+
+ case REQ_EDIT:
+ if (!stage_status.name[0])
+ return request;
+
+ open_editor(view, stage_status.name);
+ break;
+
+ case REQ_ENTER:
+ pager_request(view, request, line);
+ break;
+
+ default:
+ return request;
+ }
+
+ return REQ_NONE;
+}
+
static struct view_ops stage_ops = {
"line",
NULL,
pager_read,
pager_draw,
- pager_request,
+ stage_request,
pager_grep,
pager_select,
};
+
/*
* Revision graph
*/