git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 13/19] strbuf: add a helper function to call the editor "on an strbuf"

From
Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com>
Date
Dec 13, 2019, 08:08 UTC
Message-ID
<18c008fbe119036700faf2a82711c2b0f453df6a.1576224486.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.173.git.1576224486.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>

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 <johannes.schindelin@gmx.de>
---
 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,
-- 
gitgitgadget
Previous: Johannes Schindelin via GitGitGadgetNext: Johannes Schindelin via GitGitGadget
Message 9 of 20 in “Implement the git add --patch backend in C”
  1. 00/19 Implement the git add --patch backend in CJohannes Schindelin via GitGitGadget, Dec 13, 2019
  2. 02/19 built-in add -i: wire up the new C code for the `patch` commandJohannes Schindelin via GitGitGadget, Dec 13, 2019
  3. 01/19 built-in add -i: start implementing the `patch` functionality in CJohannes Schindelin via GitGitGadget, Dec 13, 2019
  4. 03/19 built-in add -p: show colored hunks by defaultJohannes Schindelin via GitGitGadget, Dec 13, 2019
  5. 07/19 built-in add -p: support multi-file diffsJohannes Schindelin via GitGitGadget, Dec 13, 2019
  6. 06/19 built-in add -p: offer a helpful error message when hunk navigation failedJohannes Schindelin via GitGitGadget, Dec 13, 2019
  7. 10/19 built-in add -p: show different prompts for mode changes and deletionsJohannes Schindelin via GitGitGadget, Dec 13, 2019
  8. 09/19 built-in app -p: allow selecting a mode change as a "hunk"Johannes Schindelin via GitGitGadget, Dec 13, 2019
  9. 13/19 strbuf: add a helper function to call the editor "on an strbuf"Johannes Schindelin via GitGitGadget, Dec 13, 2019
  10. 12/19 built-in add -p: coalesce hunks after splitting themJohannes Schindelin via GitGitGadget, Dec 13, 2019
  11. 15/19 built-in add -p: implement the 'g' ("goto") commandJohannes Schindelin via GitGitGadget, Dec 13, 2019
  12. 14/19 built-in add -p: implement hunk editingJohannes Schindelin via GitGitGadget, Dec 13, 2019
  13. 11/19 built-in add -p: implement the hunk splitting featureJohannes Schindelin via GitGitGadget, Dec 13, 2019
  14. 19/19 built-in add -p: show helpful hint when nothing can be stagedJohannes Schindelin via GitGitGadget, Dec 13, 2019
  15. 18/19 built-in add -p: only show the applicable parts of the help textJohannes Schindelin via GitGitGadget, Dec 13, 2019
  16. 16/19 built-in add -p: implement the '/' ("search regex") commandJohannes Schindelin via GitGitGadget, Dec 13, 2019
  17. 17/19 built-in add -p: implement the 'q' ("quit") commandJohannes Schindelin via GitGitGadget, Dec 13, 2019
  18. 08/19 built-in add -p: handle deleted empty filesJohannes Schindelin via GitGitGadget, Dec 13, 2019
  19. 04/19 built-in add -p: adjust hunk headers as neededJohannes Schindelin via GitGitGadget, Dec 13, 2019
  20. 05/19 built-in add -p: color the prompt and the help textJohannes Schindelin via GitGitGadget, Dec 13, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.