commit 3aa55f1085484754656826a13fbb625b01dd06b4 from: Mark Jamsek via: Thomas Adam date: Fri Aug 16 15:31:13 2024 UTC tog: add diff view 'p' keymap to write the diff to file Write the current diff view to a temporary patch file in /tmp and report the pathname to the status line. discussed with naddy input and ok stsp@ commit - 5fd747092ffe82320b62b9558c94e28f899f9c36 commit + 3aa55f1085484754656826a13fbb625b01dd06b4 blob - 0f8f83ded2fa834467a0c0bef5de29b3578ddcaa blob + 6e0e4df78865c58469ef88303ebfa3222886178f --- tog/tog.1 +++ tog/tog.1 @@ -455,6 +455,10 @@ view, move to the Nth next (older) commit. If the diff was opened via the .Cm blame view, move to the Nth next line and load the corresponding commit (default: 1). +.It Cm p +Write the currently viewed diff to a patch file in +.Pa /tmp . +The patch pathname is drawn to the status line. .It Cm / Prompt for a search pattern and start searching for matching lines. The search pattern is an extended regular expression. blob - 0f56f886631ecd1dfdabbe67cf92f044e0cc49c4 blob + 098e4b046181f90210370e992a808076c688abc6 --- tog/tog.c +++ tog/tog.c @@ -340,6 +340,7 @@ get_color_value(const char *envvar) struct tog_diff_view_state { struct got_object_id *id1, *id2; const char *label1, *label2; + char *action; FILE *f, *f1, *f2; int fd1, fd2; int lineno; @@ -589,6 +590,7 @@ struct tog_help_view_state { KEY_("A", "Toggle between Myers and Patience diff algorithm"), \ KEY_("a", "Toggle treatment of file as ASCII irrespective of binary" \ " data"), \ + KEY_("p", "Write diff to a patch file in /tmp"), \ KEY_("(", "Go to the previous file in the diff"), \ KEY_(")", "Go to the next file in the diff"), \ KEY_("{", "Go to the previous hunk in the diff"), \ @@ -1624,10 +1626,13 @@ action_report(struct tog_view *view) /* * Clear action status report. Only clear in blame view * once annotating is complete, otherwise it's too fast. + * In diff view, let its state control view->action lifetime. */ if (view->type == TOG_VIEW_BLAME) { if (view->state.blame.blame_complete) view->action = NULL; + } else if (view->type == TOG_VIEW_DIFF) { + view->action = view->state.diff.action; } else view->action = NULL; } @@ -5615,6 +5620,8 @@ close_diff_view(struct tog_view *view) s->id1 = NULL; free(s->id2); s->id2 = NULL; + free(s->action); + s->action = NULL; if (s->f && fclose(s->f) == EOF) err = got_error_from_errno("fclose"); s->f = NULL; @@ -5810,6 +5817,67 @@ show_diff_view(struct tog_view *view) } static const struct got_error * +diff_write_patch(struct tog_view *view) +{ + const struct got_error *err; + struct tog_diff_view_state *s = &view->state.diff; + FILE *f; + char buf[BUFSIZ]; + char *path; + size_t r; + off_t pos; + + if (s->action != NULL) { + free(s->action); + s->action = NULL; + } + + pos = ftello(s->f); + if (pos == -1) + return got_error_from_errno("ftello"); + if (fseeko(s->f, 0L, SEEK_SET) == -1) + return got_error_from_errno("fseeko"); + + err = got_opentemp_named(&path, &f, GOT_TMPDIR_STR "/tog", ".diff"); + if (err != NULL) + return err; + + while ((r = fread(buf, 1, sizeof(buf), s->f)) > 0) { + if (fwrite(buf, 1, r, f) != r) { + err = got_ferror(f, GOT_ERR_IO); + goto done; + } + } + + if (ferror(s->f)) { + err = got_error_from_errno("fread"); + goto done; + } + if (fseeko(s->f, pos, SEEK_SET) == -1) { + err = got_error_from_errno("fseeko"); + goto done; + } + + if (fflush(f) == EOF) { + err = got_error_from_errno2("fflush", path); + goto done; + } + + if (asprintf(&s->action, "patch file written to %s", path) == -1) { + err = got_error_from_errno("asprintf"); + goto done; + } + + view->action = s->action; + +done: + if (f != NULL && fclose(f) == EOF && err == NULL) + err = got_error_from_errno2("fclose", path); + free(path); + return err; +} + +static const struct got_error * set_selected_commit(struct tog_diff_view_state *s, struct commit_queue_entry *entry) { @@ -5844,6 +5912,10 @@ reset_diff_view(struct tog_view *view) s->first_displayed_line = 1; s->last_displayed_line = view->nlines; s->matched_line = 0; + if (s->action != NULL) { + free(s->action); + s->action = NULL; + } diff_view_indicate_progress(view); return create_diff(s); } @@ -5903,6 +5975,12 @@ input_diff_view(struct tog_view **new_view, struct tog s->lineno = s->first_displayed_line - 1 + s->selected_line; + if (s->action != NULL && ch != ERR) { + free(s->action); + s->action = NULL; + view->action = NULL; + } + switch (ch) { case '0': case '$': @@ -6102,6 +6180,9 @@ input_diff_view(struct tog_view **new_view, struct tog diff_view_indicate_progress(view); err = create_diff(s); + break; + case 'p': + err = diff_write_patch(view); break; default: view->count = 0;