From b38dd9e7151f118b989f8c9851bc38a8a8733eaf Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 13 Dec 2019 08:08:00 +0000 Subject: [PATCH] strbuf: add a helper function to call the editor "on an strbuf" This helper supports the scenario where Git has a populated `strbuf` and wants to let the user edit it interactively. In `git add -p`, we will use this to allow interactive hunk editing: the diff hunks are already in memory, but we need to write them out to a file so that an editor can be launched, then read everything back once the user is done editing. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- strbuf.c | 28 ++++++++++++++++++++++++++++ strbuf.h | 11 +++++++++++ 2 files changed, 39 insertions(+) diff --git a/strbuf.c b/strbuf.c index aa48d179a9..f19da55b07 100644 --- a/strbuf.c +++ b/strbuf.c @@ -1125,3 +1125,31 @@ int strbuf_normalize_path(struct strbuf *src) strbuf_release(&dst); return 0; } + +int strbuf_edit_interactively(struct strbuf *buffer, const char *path, + const char *const *env) +{ + char *path2 = NULL; + int fd, res = 0; + + if (!is_absolute_path(path)) + path = path2 = xstrdup(git_path("%s", path)); + + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + res = error_errno(_("could not open '%s' for writing"), path); + else if (write_in_full(fd, buffer->buf, buffer->len) < 0) { + res = error_errno(_("could not write to '%s'"), path); + close(fd); + } else if (close(fd) < 0) + res = error_errno(_("could not close '%s'"), path); + else { + strbuf_reset(buffer); + if (launch_editor(path, buffer, env) < 0) + res = error_errno(_("could not edit '%s'"), path); + unlink(path); + } + + free(path2); + return res; +} diff --git a/strbuf.h b/strbuf.h index 84cf969721..bfa66569a4 100644 --- a/strbuf.h +++ b/strbuf.h @@ -621,6 +621,17 @@ int launch_editor(const char *path, struct strbuf *buffer, int launch_sequence_editor(const char *path, struct strbuf *buffer, const char *const *env); +/* + * In contrast to `launch_editor()`, this function writes out the contents + * of the specified file first, then clears the `buffer`, then launches + * the editor and reads back in the file contents into the `buffer`. + * Finally, it deletes the temporary file. + * + * If `path` is relative, it refers to a file in the `.git` directory. + */ +int strbuf_edit_interactively(struct strbuf *buffer, const char *path, + const char *const *env); + void strbuf_add_lines(struct strbuf *sb, const char *prefix, const char *buf,