Skip to content

Commit 362724a

Browse files
committed
Merge branch 'js/add-edit'
* js/add-edit: t3702: fix reliance on SHELL_PATH being '/bin/sh' git-add: introduce --edit (to edit the diff vs. the index)
2 parents c16cea7 + 7c8224b commit 362724a

File tree

3 files changed

+187
-4
lines changed

3 files changed

+187
-4
lines changed

Documentation/git-add.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ SYNOPSIS
99
--------
1010
[verse]
1111
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
12-
[--all | [--update | -u]] [--intent-to-add | -N]
12+
[--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
1313
[--refresh] [--ignore-errors] [--] <filepattern>...
1414

1515
DESCRIPTION
@@ -76,6 +76,15 @@ OPTIONS
7676
bypassed and the 'patch' subcommand is invoked using each of
7777
the specified filepatterns before exiting.
7878

79+
-e, \--edit::
80+
Open the diff vs. the index in an editor and let the user
81+
edit it. After the editor was closed, adjust the hunk headers
82+
and apply the patch to the index.
83+
+
84+
*NOTE*: Obviously, if you change anything else than the first character
85+
on lines beginning with a space or a minus, the patch will no longer
86+
apply.
87+
7988
-u::
8089
--update::
8190
Update only files that git already knows about, staging modified

builtin-add.c

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
#include "cache-tree.h"
1111
#include "run-command.h"
1212
#include "parse-options.h"
13+
#include "diff.h"
14+
#include "revision.h"
1315

1416
static const char * const builtin_add_usage[] = {
1517
"git add [options] [--] <filepattern>...",
1618
NULL
1719
};
18-
static int patch_interactive, add_interactive;
20+
static int patch_interactive, add_interactive, edit_interactive;
1921
static int take_worktree_changes;
2022

2123
static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
@@ -187,6 +189,51 @@ int interactive_add(int argc, const char **argv, const char *prefix)
187189
return status;
188190
}
189191

192+
int edit_patch(int argc, const char **argv, const char *prefix)
193+
{
194+
char *file = xstrdup(git_path("ADD_EDIT.patch"));
195+
const char *apply_argv[] = { "apply", "--recount", "--cached",
196+
file, NULL };
197+
struct child_process child;
198+
struct rev_info rev;
199+
int out;
200+
struct stat st;
201+
202+
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
203+
204+
if (read_cache() < 0)
205+
die ("Could not read the index");
206+
207+
init_revisions(&rev, prefix);
208+
rev.diffopt.context = 7;
209+
210+
argc = setup_revisions(argc, argv, &rev, NULL);
211+
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
212+
out = open(file, O_CREAT | O_WRONLY, 0644);
213+
if (out < 0)
214+
die ("Could not open '%s' for writing.", file);
215+
rev.diffopt.file = fdopen(out, "w");
216+
rev.diffopt.close_file = 1;
217+
if (run_diff_files(&rev, 0))
218+
die ("Could not write patch");
219+
220+
launch_editor(file, NULL, NULL);
221+
222+
if (stat(file, &st))
223+
die("Could not stat '%s'", file);
224+
if (!st.st_size)
225+
die("Empty patch. Aborted.");
226+
227+
memset(&child, 0, sizeof(child));
228+
child.git_cmd = 1;
229+
child.argv = apply_argv;
230+
if (run_command(&child))
231+
die ("Could not apply '%s'", file);
232+
233+
unlink(file);
234+
return 0;
235+
}
236+
190237
static struct lock_file lock_file;
191238

192239
static const char ignore_error[] =
@@ -201,6 +248,7 @@ static struct option builtin_add_options[] = {
201248
OPT_GROUP(""),
202249
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
203250
OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
251+
OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"),
204252
OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
205253
OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
206254
OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"),
@@ -251,14 +299,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
251299
int require_pathspec;
252300

253301
argc = parse_options(argc, argv, builtin_add_options,
254-
builtin_add_usage, 0);
302+
builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
255303
if (patch_interactive)
256304
add_interactive = 1;
257305
if (add_interactive)
258-
exit(interactive_add(argc, argv, prefix));
306+
exit(interactive_add(argc - 1, argv + 1, prefix));
259307

260308
git_config(add_config, NULL);
261309

310+
if (edit_interactive)
311+
return(edit_patch(argc, argv, prefix));
312+
argc--;
313+
argv++;
314+
262315
if (addremove && take_worktree_changes)
263316
die("-A and -u are mutually incompatible");
264317
if ((addremove || take_worktree_changes) && !argc) {

t/t3702-add-edit.sh

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2007 Johannes E. Schindelin
4+
#
5+
6+
test_description='add -e basic tests'
7+
. ./test-lib.sh
8+
9+
10+
cat > file << EOF
11+
LO, praise of the prowess of people-kings
12+
of spear-armed Danes, in days long sped,
13+
we have heard, and what honor the athelings won!
14+
Oft Scyld the Scefing from squadroned foes,
15+
from many a tribe, the mead-bench tore,
16+
awing the earls. Since erst he lay
17+
friendless, a foundling, fate repaid him:
18+
for he waxed under welkin, in wealth he throve,
19+
till before him the folk, both far and near,
20+
who house by the whale-path, heard his mandate,
21+
gave him gifts: a good king he!
22+
EOF
23+
24+
cat > second-part << EOF
25+
To him an heir was afterward born,
26+
a son in his halls, whom heaven sent
27+
to favor the folk, feeling their woe
28+
that erst they had lacked an earl for leader
29+
so long a while; the Lord endowed him,
30+
the Wielder of Wonder, with world's renown.
31+
EOF
32+
33+
test_expect_success 'setup' '
34+
35+
git add file &&
36+
test_tick &&
37+
git commit -m initial file
38+
39+
'
40+
41+
cat > expected-patch << EOF
42+
diff --git a/file b/file
43+
index b9834b5..9020acb 100644
44+
--- a/file
45+
+++ b/file
46+
@@ -1,11 +1,6 @@
47+
-LO, praise of the prowess of people-kings
48+
-of spear-armed Danes, in days long sped,
49+
-we have heard, and what honor the athelings won!
50+
-Oft Scyld the Scefing from squadroned foes,
51+
-from many a tribe, the mead-bench tore,
52+
-awing the earls. Since erst he lay
53+
-friendless, a foundling, fate repaid him:
54+
-for he waxed under welkin, in wealth he throve,
55+
-till before him the folk, both far and near,
56+
-who house by the whale-path, heard his mandate,
57+
-gave him gifts: a good king he!
58+
+To him an heir was afterward born,
59+
+a son in his halls, whom heaven sent
60+
+to favor the folk, feeling their woe
61+
+that erst they had lacked an earl for leader
62+
+so long a while; the Lord endowed him,
63+
+the Wielder of Wonder, with world's renown.
64+
EOF
65+
66+
cat > patch << EOF
67+
diff --git a/file b/file
68+
index b9834b5..ef6e94c 100644
69+
--- a/file
70+
+++ b/file
71+
@@ -3,1 +3,333 @@ of spear-armed Danes, in days long sped,
72+
we have heard, and what honor the athelings won!
73+
+
74+
Oft Scyld the Scefing from squadroned foes,
75+
@@ -2,7 +1,5 @@ awing the earls. Since erst he lay
76+
friendless, a foundling, fate repaid him:
77+
+
78+
for he waxed under welkin, in wealth he throve,
79+
EOF
80+
81+
cat > expected << EOF
82+
diff --git a/file b/file
83+
index b9834b5..ef6e94c 100644
84+
--- a/file
85+
+++ b/file
86+
@@ -1,10 +1,12 @@
87+
LO, praise of the prowess of people-kings
88+
of spear-armed Danes, in days long sped,
89+
we have heard, and what honor the athelings won!
90+
+
91+
Oft Scyld the Scefing from squadroned foes,
92+
from many a tribe, the mead-bench tore,
93+
awing the earls. Since erst he lay
94+
friendless, a foundling, fate repaid him:
95+
+
96+
for he waxed under welkin, in wealth he throve,
97+
till before him the folk, both far and near,
98+
who house by the whale-path, heard his mandate,
99+
EOF
100+
101+
echo "#!$SHELL_PATH" >fake-editor.sh
102+
cat >> fake-editor.sh <<\EOF
103+
mv -f "$1" orig-patch &&
104+
mv -f patch "$1"
105+
EOF
106+
107+
test_set_editor "$(pwd)/fake-editor.sh"
108+
chmod a+x fake-editor.sh
109+
110+
test_expect_success 'add -e' '
111+
112+
cp second-part file &&
113+
git add -e &&
114+
test_cmp second-part file &&
115+
test_cmp orig-patch expected-patch &&
116+
git diff --cached > out &&
117+
test_cmp out expected
118+
119+
'
120+
121+
test_done

0 commit comments

Comments
 (0)