Skip to content

Commit b413b77

Browse files
committed
Merge branch 'interactive-rebase'
This series of branches introduces the git-rebase--helper, a builtin helping to accelerate the interactive rebase dramatically. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents c3132b2 + 12c469e commit b413b77

23 files changed

+3598
-828
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
/git-read-tree
115115
/git-rebase
116116
/git-rebase--am
117+
/git-rebase--helper
117118
/git-rebase--interactive
118119
/git-rebase--merge
119120
/git-receive-pack

Documentation/git-status.txt

Lines changed: 127 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ OPTIONS
3232
--branch::
3333
Show the branch and tracking info even in short-format.
3434

35-
--porcelain::
35+
--porcelain[=<version>]::
3636
Give the output in an easy-to-parse format for scripts.
3737
This is similar to the short output, but will remain stable
3838
across Git versions and regardless of user configuration. See
3939
below for details.
40+
+
41+
The version parameter is used to specify the format version.
42+
This is optional and defaults to the original version 'v1' format.
4043

4144
--long::
4245
Give the output in the long-format. This is the default.
@@ -96,7 +99,7 @@ configuration variable documented in linkgit:git-config[1].
9699

97100
-z::
98101
Terminate entries with NUL, instead of LF. This implies
99-
the `--porcelain` output format if no other format is given.
102+
the `--porcelain=v1` output format if no other format is given.
100103

101104
--column[=<options>]::
102105
--no-column::
@@ -185,12 +188,12 @@ in which case `XY` are `!!`.
185188

186189
If -b is used the short-format status is preceded by a line
187190

188-
## branchname tracking info
191+
## branchname tracking info
189192

190-
Porcelain Format
191-
~~~~~~~~~~~~~~~~
193+
Porcelain Format Version 1
194+
~~~~~~~~~~~~~~~~~~~~~~~~~~
192195

193-
The porcelain format is similar to the short format, but is guaranteed
196+
Version 1 porcelain format is similar to the short format, but is guaranteed
194197
not to change in a backwards-incompatible way between Git versions or
195198
based on user configuration. This makes it ideal for parsing by scripts.
196199
The description of the short format above also describes the porcelain
@@ -212,6 +215,124 @@ field from the first filename). Third, filenames containing special
212215
characters are not specially formatted; no quoting or
213216
backslash-escaping is performed.
214217

218+
Porcelain Format Version 2
219+
~~~~~~~~~~~~~~~~~~~~~~~~~~
220+
221+
Version 2 format adds more detailed information about the state of
222+
the worktree and changed items. Version 2 also defines an extensible
223+
set of easy to parse optional headers.
224+
225+
Header lines start with "#" and are added in response to specific
226+
command line arguments. Parsers should ignore headers they
227+
don't recognize.
228+
229+
### Branch Headers
230+
231+
If `--branch` is given, a series of header lines are printed with
232+
information about the current branch.
233+
234+
Line Notes
235+
------------------------------------------------------------
236+
# branch.oid <commit> | (initial) Current commit.
237+
# branch.head <branch> | (detached) Current branch.
238+
# branch.upstream <upstream_branch> If upstream is set.
239+
# branch.ab +<ahead> -<behind> If upstream is set and
240+
the commit is present.
241+
------------------------------------------------------------
242+
243+
### Changed Tracked Entries
244+
245+
Following the headers, a series of lines are printed for tracked
246+
entries. One of three different line formats may be used to describe
247+
an entry depending on the type of change. Tracked entries are printed
248+
in an undefined order; parsers should allow for a mixture of the 3
249+
line types in any order.
250+
251+
Ordinary changed entries have the following format:
252+
253+
1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
254+
255+
Renamed or copied entries have the following format:
256+
257+
2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><sep><origPath>
258+
259+
Field Meaning
260+
--------------------------------------------------------
261+
<XY> A 2 character field containing the staged and
262+
unstaged XY values described in the short format,
263+
with unchanged indicated by a "." rather than
264+
a space.
265+
<sub> A 4 character field describing the submodule state.
266+
"N..." when the entry is not a submodule.
267+
"S<c><m><u>" when the entry is a submodule.
268+
<c> is "C" if the commit changed; otherwise ".".
269+
<m> is "M" if it has tracked changes; otherwise ".".
270+
<u> is "U" if there are untracked changes; otherwise ".".
271+
<mH> The octal file mode in HEAD.
272+
<mI> The octal file mode in the index.
273+
<mW> The octal file mode in the worktree.
274+
<hH> The object name in HEAD.
275+
<hI> The object name in the index.
276+
<X><score> The rename or copy score (denoting the percentage
277+
of similarity between the source and target of the
278+
move or copy). For example "R100" or "C75".
279+
<path> The pathname. In a renamed/copied entry, this
280+
is the path in the index and in the working tree.
281+
<sep> When the `-z` option is used, the 2 pathnames are separated
282+
with a NUL (ASCII 0x00) byte; otherwise, a tab (ASCII 0x09)
283+
byte separates them.
284+
<origPath> The pathname in the commit at HEAD. This is only
285+
present in a renamed/copied entry, and tells
286+
where the renamed/copied contents came from.
287+
--------------------------------------------------------
288+
289+
Unmerged entries have the following format; the first character is
290+
a "u" to distinguish from ordinary changed entries.
291+
292+
u <xy> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
293+
294+
Field Meaning
295+
--------------------------------------------------------
296+
<XY> A 2 character field describing the conflict type
297+
as described in the short format.
298+
<sub> A 4 character field describing the submodule state
299+
as described above.
300+
<m1> The octal file mode in stage 1.
301+
<m2> The octal file mode in stage 2.
302+
<m3> The octal file mode in stage 3.
303+
<mW> The octal file mode in the worktree.
304+
<h1> The object name in stage 1.
305+
<h2> The object name in stage 2.
306+
<h3> The object name in stage 3.
307+
<path> The pathname.
308+
--------------------------------------------------------
309+
310+
### Other Items
311+
312+
Following the tracked entries (and if requested), a series of
313+
lines will be printed for untracked and then ignored items
314+
found in the worktree.
315+
316+
Untracked items have the following format:
317+
318+
? <path>
319+
320+
Ignored items have the following format:
321+
322+
! <path>
323+
324+
### Pathname Format Notes and -z
325+
326+
When the `-z` option is given, pathnames are printed as is and
327+
without any quoting and lines are terminated with a NUL (ASCII 0x00)
328+
byte.
329+
330+
Otherwise, all pathnames will be "C-quoted" if they contain any tab,
331+
linefeed, double quote, or backslash characters. In C-quoting, these
332+
characters will be replaced with the corresponding C-style escape
333+
sequences and the resulting pathname will be double quoted.
334+
335+
215336
CONFIGURATION
216337
-------------
217338

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,7 @@ BUILTIN_OBJS += builtin/prune.o
925925
BUILTIN_OBJS += builtin/pull.o
926926
BUILTIN_OBJS += builtin/push.o
927927
BUILTIN_OBJS += builtin/read-tree.o
928+
BUILTIN_OBJS += builtin/rebase--helper.o
928929
BUILTIN_OBJS += builtin/receive-pack.o
929930
BUILTIN_OBJS += builtin/reflog.o
930931
BUILTIN_OBJS += builtin/remote.o

builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
102102
extern int cmd_pull(int argc, const char **argv, const char *prefix);
103103
extern int cmd_push(int argc, const char **argv, const char *prefix);
104104
extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
105+
extern int cmd_rebase__helper(int argc, const char **argv, const char *prefix);
105106
extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);
106107
extern int cmd_reflog(int argc, const char **argv, const char *prefix);
107108
extern int cmd_remote(int argc, const char **argv, const char *prefix);

builtin/commit.c

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,24 @@ static int show_ignored_in_status, have_option_m;
142142
static const char *only_include_assumed;
143143
static struct strbuf message = STRBUF_INIT;
144144

145-
static enum status_format {
146-
STATUS_FORMAT_NONE = 0,
147-
STATUS_FORMAT_LONG,
148-
STATUS_FORMAT_SHORT,
149-
STATUS_FORMAT_PORCELAIN,
145+
static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
150146

151-
STATUS_FORMAT_UNSPECIFIED
152-
} status_format = STATUS_FORMAT_UNSPECIFIED;
147+
static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)
148+
{
149+
enum wt_status_format *value = (enum wt_status_format *)opt->value;
150+
if (unset)
151+
*value = STATUS_FORMAT_NONE;
152+
else if (!arg)
153+
*value = STATUS_FORMAT_PORCELAIN;
154+
else if (!strcmp(arg, "v1") || !strcmp(arg, "1"))
155+
*value = STATUS_FORMAT_PORCELAIN;
156+
else if (!strcmp(arg, "v2") || !strcmp(arg, "2"))
157+
*value = STATUS_FORMAT_PORCELAIN_V2;
158+
else
159+
die("unsupported porcelain version '%s'", arg);
160+
161+
return 0;
162+
}
153163

154164
static int opt_parse_m(const struct option *opt, const char *arg, int unset)
155165
{
@@ -173,7 +183,7 @@ static void determine_whence(struct wt_status *s)
173183
whence = FROM_MERGE;
174184
else if (file_exists(git_path_cherry_pick_head())) {
175185
whence = FROM_CHERRY_PICK;
176-
if (file_exists(git_path(SEQ_DIR)))
186+
if (file_exists(git_path_seq_dir()))
177187
sequencer_in_use = 1;
178188
}
179189
else
@@ -500,24 +510,13 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
500510
s->fp = fp;
501511
s->nowarn = nowarn;
502512
s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0;
513+
if (!s->is_initial)
514+
hashcpy(s->sha1_commit, sha1);
515+
s->status_format = status_format;
516+
s->ignore_submodule_arg = ignore_submodule_arg;
503517

504518
wt_status_collect(s);
505-
506-
switch (status_format) {
507-
case STATUS_FORMAT_SHORT:
508-
wt_shortstatus_print(s);
509-
break;
510-
case STATUS_FORMAT_PORCELAIN:
511-
wt_porcelain_print(s);
512-
break;
513-
case STATUS_FORMAT_UNSPECIFIED:
514-
die("BUG: finalize_deferred_config() should have been called");
515-
break;
516-
case STATUS_FORMAT_NONE:
517-
case STATUS_FORMAT_LONG:
518-
wt_status_print(s);
519-
break;
520-
}
519+
wt_status_print(s);
521520

522521
return s->commitable;
523522
}
@@ -1099,7 +1098,7 @@ static const char *read_commit_message(const char *name)
10991098
* is not in effect here.
11001099
*/
11011100
static struct status_deferred_config {
1102-
enum status_format status_format;
1101+
enum wt_status_format status_format;
11031102
int show_branch;
11041103
} status_deferred_config = {
11051104
STATUS_FORMAT_UNSPECIFIED,
@@ -1109,6 +1108,7 @@ static struct status_deferred_config {
11091108
static void finalize_deferred_config(struct wt_status *s)
11101109
{
11111110
int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN &&
1111+
status_format != STATUS_FORMAT_PORCELAIN_V2 &&
11121112
!s->null_termination);
11131113

11141114
if (s->null_termination) {
@@ -1337,9 +1337,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
13371337
N_("show status concisely"), STATUS_FORMAT_SHORT),
13381338
OPT_BOOL('b', "branch", &s.show_branch,
13391339
N_("show branch information")),
1340-
OPT_SET_INT(0, "porcelain", &status_format,
1341-
N_("machine-readable output"),
1342-
STATUS_FORMAT_PORCELAIN),
1340+
{ OPTION_CALLBACK, 0, "porcelain", &status_format,
1341+
N_("version"), N_("machine-readable output"),
1342+
PARSE_OPT_OPTARG, opt_parse_porcelain },
13431343
OPT_SET_INT(0, "long", &status_format,
13441344
N_("show status in long format (default)"),
13451345
STATUS_FORMAT_LONG),
@@ -1384,7 +1384,13 @@ int cmd_status(int argc, const char **argv, const char *prefix)
13841384
fd = no_lock_index ? -1 : hold_locked_index(&index_lock, 0);
13851385

13861386
s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
1387+
if (!s.is_initial)
1388+
hashcpy(s.sha1_commit, sha1);
1389+
13871390
s.ignore_submodule_arg = ignore_submodule_arg;
1391+
s.status_format = status_format;
1392+
s.verbose = verbose;
1393+
13881394
wt_status_collect(&s);
13891395

13901396
if (0 <= fd)
@@ -1393,23 +1399,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
13931399
if (s.relative_paths)
13941400
s.prefix = prefix;
13951401

1396-
switch (status_format) {
1397-
case STATUS_FORMAT_SHORT:
1398-
wt_shortstatus_print(&s);
1399-
break;
1400-
case STATUS_FORMAT_PORCELAIN:
1401-
wt_porcelain_print(&s);
1402-
break;
1403-
case STATUS_FORMAT_UNSPECIFIED:
1404-
die("BUG: finalize_deferred_config() should have been called");
1405-
break;
1406-
case STATUS_FORMAT_NONE:
1407-
case STATUS_FORMAT_LONG:
1408-
s.verbose = verbose;
1409-
s.ignore_submodule_arg = ignore_submodule_arg;
1410-
wt_status_print(&s);
1411-
break;
1412-
}
1402+
wt_status_print(&s);
14131403
return 0;
14141404
}
14151405

0 commit comments

Comments
 (0)