@@ -12,10 +12,12 @@ CONFIG_ABBREV_COMMANDS="addfiles.abbreviateCommands"
12
12
FILENAME=" ADD_FILES"
13
13
14
14
CMD_ADD=" add"
15
+ CMD_WIP=" wip"
15
16
CMD_STAGED=" staged"
16
17
CMD_HALFSTAGED=" halfstaged"
17
18
18
19
SHORT_CMD_ADD=" a"
20
+ SHORT_CMD_WIP=" w"
19
21
SHORT_CMD_STAGED=" s"
20
22
SHORT_CMD_HALFSTAGED=" h"
21
23
@@ -26,6 +28,8 @@ INFO_MSG="\
26
28
# delete \" $CMD_HALFSTAGED \" (noop) lines to un-stage partially-staged files.
27
29
# change \" $CMD_HALFSTAGED \" (noop) to \" $CMD_ADD \" to stage partially-staged files.
28
30
#
31
+ # \" wip\" is noop, cached in .git/add-files/wip
32
+ #
29
33
# all commands have a single-char shortcut.
30
34
# empty lines and lines starting with '#' will be ignored.
31
35
# to abort, exit with non-0 code (e.g. :cq in vim).
@@ -75,7 +79,13 @@ git_add_files() {
75
79
76
80
repodir=" $( git rev-parse --show-toplevel) "
77
81
gitdir=" $( git rev-parse --git-dir) "
82
+
83
+ FILE_STORE=" $gitdir /add-files"
78
84
file=" $gitdir /$FILENAME "
85
+ FILE_WIP=" $FILE_STORE /wip"
86
+
87
+ mkdir -p " $FILE_STORE "
88
+ touch " $FILE_WIP "
79
89
80
90
COMMENT_REGEX=" \s*#.*$"
81
91
@@ -95,17 +105,24 @@ git_add_files() {
95
105
printf " %s" " $1 " | sed " s@^@$2 @g"
96
106
}
97
107
108
+ ADD_WITHOUT_WIP=" $( printf " %b" " $ADD " | { grep -vFf " $FILE_WIP " || : ; }) "
109
+ WIP=" $( printf " %b" " $ADD " | { grep -Ff " $FILE_WIP " || : ; }) "
110
+
98
111
if test " $( git config " $CONFIG_ABBREV_COMMANDS " ) " = " true" ; then
99
- ADD_READY=" $( inject_prefix_into " $ADD " " $SHORT_CMD_ADD " ) "
112
+ ADD_READY=" $( inject_prefix_into " $ADD_WITHOUT_WIP " " $SHORT_CMD_ADD " ) "
113
+ WIP_READY=" $( inject_prefix_into " $WIP " " $SHORT_CMD_WIP " ) "
100
114
STAGED_READY=" $( inject_prefix_into " $STAGED " " $SHORT_CMD_STAGED " ) "
101
115
else
102
- ADD_READY=" $( inject_prefix_into " $ADD " " $CMD_ADD " ) "
116
+ ADD_READY=" $( inject_prefix_into " $ADD_WITHOUT_WIP " " $CMD_ADD " ) "
117
+ WIP_READY=" $( inject_prefix_into " $WIP " " $CMD_WIP " ) "
103
118
STAGED_READY=" $( inject_prefix_into " $STAGED " " $CMD_STAGED " ) "
104
119
fi
105
120
106
- sep=" "
107
- test -n " $ADD_READY " && test -n " $STAGED_READY " && sep=" \n\n"
108
- printf " %s%b%s\n%s" " $ADD_READY " " $sep " " $STAGED_READY " > " $file "
121
+ sep1=" "
122
+ sep2=" "
123
+ test -n " $ADD_READY " && test -n " $WIP_READY " && sep1=" \n\n"
124
+ test -n " $WIP_READY " && test -n " $STAGED_READY " && sep2=" \n\n"
125
+ printf " %s%b%s%b%s\n%s" " $ADD_READY " " $sep1 " " $WIP_READY " " $sep2 " " $STAGED_READY " > " $file "
109
126
110
127
test " $( git config " $CONFIG_DISABLE_INFO " ) " ! = " true" && {
111
128
printf " \n%s" " $INFO_MSG " >> " $file "
@@ -136,15 +153,22 @@ git_add_files() {
136
153
}
137
154
validate_file () {
138
155
# TODO handle deletions
139
- test -f " $1 " || msg " file does not exit '$1 '"
156
+
157
+ # TODO handle submodule "files" which are directories,
158
+ # and cannot be added if include uncommitted changes.
159
+
160
+ test -f " $1 " || test -d " $1 " || msg " file does not exit '$1 '\n"
140
161
}
141
162
142
163
marked_added=" /tmp/marked_added"
143
164
marked_staged=" /tmp/marked_staged"
165
+ marked_wip=" /tmp/marked_wip"
144
166
test -f " $marked_added " && mv -f " $marked_added " " $marked_added .prev"
145
167
test -f " $marked_staged " && mv -f " $marked_staged " " $marked_staged .prev"
168
+ test -f " $marked_wip " && mv -f " $marked_wip " " $marked_wip .prev"
146
169
touch " $marked_added "
147
170
touch " $marked_staged "
171
+ touch " $marked_wip "
148
172
had_adds=0
149
173
150
174
# process & validate lines, group filepaths.
@@ -158,17 +182,26 @@ git_add_files() {
158
182
159
183
validate_file " $filepath "
160
184
161
- printf " %s\n" " $filepath " >> " $marked_added "
185
+ printf " %s\n" " $file " >> " $marked_added "
162
186
had_adds=1
163
187
;;
188
+ " $CMD_WIP " |" $SHORT_CMD_WIP " * )
189
+ rest=" $( line_tail " $line " ) "
190
+ file=" $( line_head " $rest " ) "
191
+ filepath=" $( realpath " $repodir /$file " ) "
192
+
193
+ validate_file " $filepath "
194
+
195
+ printf " %s\n" " $file " >> " $marked_wip "
196
+ ;;
164
197
" $CMD_STAGED " |" $SHORT_CMD_STAGED " * )
165
198
rest=" $( line_tail " $line " ) "
166
199
file=" $( line_head " $rest " ) "
167
200
filepath=" $( realpath " $repodir /$file " ) "
168
201
169
202
validate_file " $filepath "
170
203
171
- printf " %s\n" " $filepath " >> " $marked_staged "
204
+ printf " %s\n" " $file " >> " $marked_staged "
172
205
;;
173
206
" $CMD_HALFSTAGED " |" $SHORT_CMD_HALFSTAGED " * )
174
207
# noop
@@ -181,13 +214,16 @@ git_add_files() {
181
214
182
215
# add all lines that were kept as "add"
183
216
184
- test " $had_adds " -eq 0 || git add --pathspec-from-file=" $marked_added "
217
+ # TODO refactor abs
218
+ var_marked_added=" $( inject_prefix_into " $( cat " $marked_added " ) " " $repodir /" ) "
219
+ marked_added_abs=" /tmp/marked_added_abs"
220
+ printf " %s" " $var_marked_added " > " $marked_added_abs "
221
+ test " $had_adds " -eq 0 || git add --pathspec-from-file=" $marked_added_abs "
185
222
186
223
# unstage if any "staged" lines were removed
187
224
188
- staged_fullpaths=" $( inject_prefix_into " $STAGED " " $repodir /" ) "
189
225
were_staged=" /tmp/were_staged"
190
- printf " %s\n" " $staged_fullpaths " > " $were_staged "
226
+ printf " %s\n" " $STAGED " > " $were_staged "
191
227
192
228
delta_staged=" /tmp/delta_staged"
193
229
diff --minimal " $were_staged " " $marked_staged " > " $delta_staged " || {
@@ -198,7 +234,28 @@ git_add_files() {
198
234
unmarked_staged=" /tmp/unmarked_staged"
199
235
grep " ^<" " $delta_staged " | sed ' s@^< @@g' > " $unmarked_staged "
200
236
201
- git reset --pathspec-from-file=" $unmarked_staged " HEAD
237
+ # convert to absolute filepaths,
238
+ # for --pathspec-from-file to work
239
+ # TODO refactor abs
240
+ var_unmarked_staged=" $( cat " $unmarked_staged " ) "
241
+ var_unmarked_staged_abs=" $( inject_prefix_into " $var_unmarked_staged " " $repodir /" ) "
242
+ unmarked_staged_abs=" /tmp/unmarked_staged_abs"
243
+ printf " %s" " $var_unmarked_staged_abs " > " $unmarked_staged_abs "
244
+
245
+ git reset --pathspec-from-file=" $unmarked_staged_abs " HEAD
246
+ }
247
+
248
+ # mark all lines as "wip" that have removed "add"
249
+
250
+ were_to_be_added=" /tmp/were_to_be_added"
251
+ printf " %s\n" " $ADD " > " $were_to_be_added "
252
+
253
+ delta_add=" /tmp/delta_add"
254
+ diff --minimal " $were_to_be_added " " $marked_added " > " $delta_add " || {
255
+ unmarked_add=" /tmp/unmarked_add"
256
+ grep " ^<" " $delta_add " | sed ' s@^< @@g' > " $unmarked_add "
257
+
258
+ cat " $unmarked_add " " $marked_wip " | sort | uniq > " $FILE_WIP "
202
259
}
203
260
}
204
261
0 commit comments