Merge branch 'master' into lt/logopt
* master: pager: do not fork a pager if PAGER is set to empty. diff-options: add --patch-with-stat diff-files --stat: do not dump core with unmerged index. Support "git cmd --help" syntax diff --stat: do not do its own three-dashes. diff-tree: typefix. GIT v1.3.0-rc4 xdiff: post-process hunks to make them consistent.maint
commit
b2934926dd
|
@ -10,6 +10,9 @@
|
||||||
--stat::
|
--stat::
|
||||||
Generate a diffstat instead of a patch.
|
Generate a diffstat instead of a patch.
|
||||||
|
|
||||||
|
--patch-with-stat::
|
||||||
|
Generate patch and prepend its diffstat.
|
||||||
|
|
||||||
-z::
|
-z::
|
||||||
\0 line termination on output
|
\0 line termination on output
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
GVF=GIT-VERSION-FILE
|
GVF=GIT-VERSION-FILE
|
||||||
DEF_VER=v1.3-rc3.GIT
|
DEF_VER=v1.3-rc4.GIT
|
||||||
|
|
||||||
# First try git-describe, then see if there is a version file
|
# First try git-describe, then see if there is a version file
|
||||||
# (included in release tarballs), then default
|
# (included in release tarballs), then default
|
||||||
|
|
40
diff.c
40
diff.c
|
@ -202,6 +202,8 @@ struct diffstat_t {
|
||||||
int alloc;
|
int alloc;
|
||||||
struct diffstat_file {
|
struct diffstat_file {
|
||||||
char *name;
|
char *name;
|
||||||
|
unsigned is_unmerged:1;
|
||||||
|
unsigned is_binary:1;
|
||||||
unsigned int added, deleted;
|
unsigned int added, deleted;
|
||||||
} **files;
|
} **files;
|
||||||
};
|
};
|
||||||
|
@ -245,11 +247,11 @@ static void show_stats(struct diffstat_t* data)
|
||||||
if (data->nr == 0)
|
if (data->nr == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("---\n");
|
|
||||||
|
|
||||||
for (i = 0; i < data->nr; i++) {
|
for (i = 0; i < data->nr; i++) {
|
||||||
struct diffstat_file *file = data->files[i];
|
struct diffstat_file *file = data->files[i];
|
||||||
|
|
||||||
|
if (file->is_binary || file->is_unmerged)
|
||||||
|
continue;
|
||||||
if (max_change < file->added + file->deleted)
|
if (max_change < file->added + file->deleted)
|
||||||
max_change = file->added + file->deleted;
|
max_change = file->added + file->deleted;
|
||||||
len = strlen(file->name);
|
len = strlen(file->name);
|
||||||
|
@ -294,11 +296,15 @@ static void show_stats(struct diffstat_t* data)
|
||||||
if (max + len > 70)
|
if (max + len > 70)
|
||||||
max = 70 - len;
|
max = 70 - len;
|
||||||
|
|
||||||
if (added < 0) {
|
if (data->files[i]->is_binary) {
|
||||||
/* binary file */
|
|
||||||
printf(" %s%-*s | Bin\n", prefix, len, name);
|
printf(" %s%-*s | Bin\n", prefix, len, name);
|
||||||
goto free_diffstat_file;
|
goto free_diffstat_file;
|
||||||
} else if (added + deleted == 0) {
|
}
|
||||||
|
else if (data->files[i]->is_unmerged) {
|
||||||
|
printf(" %s%-*s | Unmerged\n", prefix, len, name);
|
||||||
|
goto free_diffstat_file;
|
||||||
|
}
|
||||||
|
else if (added + deleted == 0) {
|
||||||
total_files--;
|
total_files--;
|
||||||
goto free_diffstat_file;
|
goto free_diffstat_file;
|
||||||
}
|
}
|
||||||
|
@ -426,11 +432,16 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
|
||||||
|
|
||||||
data = diffstat_add(diffstat, name_a ? name_a : name_b);
|
data = diffstat_add(diffstat, name_a ? name_a : name_b);
|
||||||
|
|
||||||
|
if (!one || !two) {
|
||||||
|
data->is_unmerged = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
|
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
|
||||||
die("unable to read files to diff");
|
die("unable to read files to diff");
|
||||||
|
|
||||||
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
|
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
|
||||||
data->added = -1;
|
data->is_binary = 1;
|
||||||
else {
|
else {
|
||||||
/* Crazy xdl interfaces.. */
|
/* Crazy xdl interfaces.. */
|
||||||
xpparam_t xpp;
|
xpparam_t xpp;
|
||||||
|
@ -1049,6 +1060,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||||
}
|
}
|
||||||
else if (!strcmp(arg, "--stat"))
|
else if (!strcmp(arg, "--stat"))
|
||||||
options->output_format = DIFF_FORMAT_DIFFSTAT;
|
options->output_format = DIFF_FORMAT_DIFFSTAT;
|
||||||
|
else if (!strcmp(arg, "--patch-with-stat")) {
|
||||||
|
options->output_format = DIFF_FORMAT_PATCH;
|
||||||
|
options->with_stat = 1;
|
||||||
|
}
|
||||||
else if (!strcmp(arg, "-z"))
|
else if (!strcmp(arg, "-z"))
|
||||||
options->line_termination = 0;
|
options->line_termination = 0;
|
||||||
else if (!strncmp(arg, "-l", 2))
|
else if (!strncmp(arg, "-l", 2))
|
||||||
|
@ -1518,7 +1533,7 @@ void diff_flush(struct diff_options *options)
|
||||||
int diff_output_format = options->output_format;
|
int diff_output_format = options->output_format;
|
||||||
struct diffstat_t *diffstat = NULL;
|
struct diffstat_t *diffstat = NULL;
|
||||||
|
|
||||||
if (diff_output_format == DIFF_FORMAT_DIFFSTAT) {
|
if (diff_output_format == DIFF_FORMAT_DIFFSTAT || options->with_stat) {
|
||||||
diffstat = xcalloc(sizeof (struct diffstat_t), 1);
|
diffstat = xcalloc(sizeof (struct diffstat_t), 1);
|
||||||
diffstat->xm.consume = diffstat_consume;
|
diffstat->xm.consume = diffstat_consume;
|
||||||
}
|
}
|
||||||
|
@ -1530,6 +1545,17 @@ void diff_flush(struct diff_options *options)
|
||||||
}
|
}
|
||||||
putchar(options->line_termination);
|
putchar(options->line_termination);
|
||||||
}
|
}
|
||||||
|
if (options->with_stat) {
|
||||||
|
for (i = 0; i < q->nr; i++) {
|
||||||
|
struct diff_filepair *p = q->queue[i];
|
||||||
|
flush_one_pair(p, DIFF_FORMAT_DIFFSTAT, options,
|
||||||
|
diffstat);
|
||||||
|
}
|
||||||
|
show_stats(diffstat);
|
||||||
|
free(diffstat);
|
||||||
|
diffstat = NULL;
|
||||||
|
putchar(options->line_termination);
|
||||||
|
}
|
||||||
for (i = 0; i < q->nr; i++) {
|
for (i = 0; i < q->nr; i++) {
|
||||||
struct diff_filepair *p = q->queue[i];
|
struct diff_filepair *p = q->queue[i];
|
||||||
flush_one_pair(p, diff_output_format, options, diffstat);
|
flush_one_pair(p, diff_output_format, options, diffstat);
|
||||||
|
|
3
diff.h
3
diff.h
|
@ -25,6 +25,7 @@ struct diff_options {
|
||||||
const char *pickaxe;
|
const char *pickaxe;
|
||||||
unsigned recursive:1,
|
unsigned recursive:1,
|
||||||
with_raw:1,
|
with_raw:1,
|
||||||
|
with_stat:1,
|
||||||
tree_in_recursive:1,
|
tree_in_recursive:1,
|
||||||
full_index:1;
|
full_index:1;
|
||||||
int break_opt;
|
int break_opt;
|
||||||
|
@ -120,6 +121,8 @@ extern void diffcore_std_no_resolve(struct diff_options *);
|
||||||
" --patch-with-raw\n" \
|
" --patch-with-raw\n" \
|
||||||
" output both a patch and the diff-raw format.\n" \
|
" output both a patch and the diff-raw format.\n" \
|
||||||
" --stat show diffstat instead of patch.\n" \
|
" --stat show diffstat instead of patch.\n" \
|
||||||
|
" --patch-with-stat\n" \
|
||||||
|
" output a patch and prepend its diffstat.\n" \
|
||||||
" --name-only show only names of changed files.\n" \
|
" --name-only show only names of changed files.\n" \
|
||||||
" --name-status show names and status of changed files.\n" \
|
" --name-status show names and status of changed files.\n" \
|
||||||
" --full-index show full object name on index lines.\n" \
|
" --full-index show full object name on index lines.\n" \
|
||||||
|
|
10
git.c
10
git.c
|
@ -330,8 +330,10 @@ static int cmd_log_wc(int argc, const char **argv, char **envp,
|
||||||
pretty_print_commit(rev->commit_format, commit, ~0, buf,
|
pretty_print_commit(rev->commit_format, commit, ~0, buf,
|
||||||
LOGSIZE, rev->abbrev);
|
LOGSIZE, rev->abbrev);
|
||||||
printf("%s\n", buf);
|
printf("%s\n", buf);
|
||||||
if (rev->diff)
|
if (rev->diff) {
|
||||||
|
printf("---\n");
|
||||||
log_tree_commit(rev, commit);
|
log_tree_commit(rev, commit);
|
||||||
|
}
|
||||||
shown = 1;
|
shown = 1;
|
||||||
free(commit->buffer);
|
free(commit->buffer);
|
||||||
commit->buffer = NULL;
|
commit->buffer = NULL;
|
||||||
|
@ -398,6 +400,12 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Turn "git cmd --help" into "git help cmd" */
|
||||||
|
if (argc > 1 && !strcmp(argv[1], "--help")) {
|
||||||
|
argv[1] = argv[0];
|
||||||
|
argv[0] = cmd = "help";
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(commands); i++) {
|
for (i = 0; i < ARRAY_SIZE(commands); i++) {
|
||||||
struct cmd_struct *p = commands+i;
|
struct cmd_struct *p = commands+i;
|
||||||
if (strcmp(p->cmd, cmd))
|
if (strcmp(p->cmd, cmd))
|
||||||
|
|
17
pager.c
17
pager.c
|
@ -5,22 +5,24 @@
|
||||||
* something different on Windows, for example.
|
* something different on Windows, for example.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void run_pager(void)
|
static void run_pager(const char *pager)
|
||||||
{
|
{
|
||||||
const char *prog = getenv("PAGER");
|
execlp(pager, pager, NULL);
|
||||||
if (!prog)
|
|
||||||
prog = "less";
|
|
||||||
setenv("LESS", "-S", 0);
|
|
||||||
execlp(prog, prog, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_pager(void)
|
void setup_pager(void)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int fd[2];
|
int fd[2];
|
||||||
|
const char *pager = getenv("PAGER");
|
||||||
|
|
||||||
if (!isatty(1))
|
if (!isatty(1))
|
||||||
return;
|
return;
|
||||||
|
if (!pager)
|
||||||
|
pager = "less";
|
||||||
|
else if (!*pager)
|
||||||
|
return;
|
||||||
|
|
||||||
if (pipe(fd) < 0)
|
if (pipe(fd) < 0)
|
||||||
return;
|
return;
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
@ -43,6 +45,7 @@ void setup_pager(void)
|
||||||
close(fd[0]);
|
close(fd[0]);
|
||||||
close(fd[1]);
|
close(fd[1]);
|
||||||
|
|
||||||
run_pager();
|
setenv("LESS", "-S", 0);
|
||||||
|
run_pager(pager);
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
|
|
114
xdiff/xdiffi.c
114
xdiff/xdiffi.c
|
@ -45,6 +45,8 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
|
||||||
long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl,
|
long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl,
|
||||||
xdalgoenv_t *xenv);
|
xdalgoenv_t *xenv);
|
||||||
static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2);
|
static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2);
|
||||||
|
static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -395,6 +397,110 @@ static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) {
|
||||||
|
long ix, ixo, ixs, ixref, grpsiz, nrec = xdf->nrec;
|
||||||
|
char *rchg = xdf->rchg, *rchgo = xdfo->rchg;
|
||||||
|
xrecord_t **recs = xdf->recs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the same of what GNU diff does. Move back and forward
|
||||||
|
* change groups for a consistent and pretty diff output. This also
|
||||||
|
* helps in finding joineable change groups and reduce the diff size.
|
||||||
|
*/
|
||||||
|
for (ix = ixo = 0;;) {
|
||||||
|
/*
|
||||||
|
* Find the first changed line in the to-be-compacted file.
|
||||||
|
* We need to keep track of both indexes, so if we find a
|
||||||
|
* changed lines group on the other file, while scanning the
|
||||||
|
* to-be-compacted file, we need to skip it properly. Note
|
||||||
|
* that loops that are testing for changed lines on rchg* do
|
||||||
|
* not need index bounding since the array is prepared with
|
||||||
|
* a zero at position -1 and N.
|
||||||
|
*/
|
||||||
|
for (; ix < nrec && !rchg[ix]; ix++)
|
||||||
|
while (rchgo[ixo++]);
|
||||||
|
if (ix == nrec)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record the start of a changed-group in the to-be-compacted file
|
||||||
|
* and find the end of it, on both to-be-compacted and other file
|
||||||
|
* indexes (ix and ixo).
|
||||||
|
*/
|
||||||
|
ixs = ix;
|
||||||
|
for (ix++; rchg[ix]; ix++);
|
||||||
|
for (; rchgo[ixo]; ixo++);
|
||||||
|
|
||||||
|
do {
|
||||||
|
grpsiz = ix - ixs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the line before the current change group, is equal to
|
||||||
|
* the last line of the current change group, shift backward
|
||||||
|
* the group.
|
||||||
|
*/
|
||||||
|
while (ixs > 0 && recs[ixs - 1]->ha == recs[ix - 1]->ha &&
|
||||||
|
XDL_RECMATCH(recs[ixs - 1], recs[ix - 1])) {
|
||||||
|
rchg[--ixs] = 1;
|
||||||
|
rchg[--ix] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This change might have joined two change groups,
|
||||||
|
* so we try to take this scenario in account by moving
|
||||||
|
* the start index accordingly (and so the other-file
|
||||||
|
* end-of-group index).
|
||||||
|
*/
|
||||||
|
for (; rchg[ixs - 1]; ixs--);
|
||||||
|
while (rchgo[--ixo]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record the end-of-group position in case we are matched
|
||||||
|
* with a group of changes in the other file (that is, the
|
||||||
|
* change record before the enf-of-group index in the other
|
||||||
|
* file is set).
|
||||||
|
*/
|
||||||
|
ixref = rchgo[ixo - 1] ? ix: nrec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the first line of the current change group, is equal to
|
||||||
|
* the line next of the current change group, shift forward
|
||||||
|
* the group.
|
||||||
|
*/
|
||||||
|
while (ix < nrec && recs[ixs]->ha == recs[ix]->ha &&
|
||||||
|
XDL_RECMATCH(recs[ixs], recs[ix])) {
|
||||||
|
rchg[ixs++] = 0;
|
||||||
|
rchg[ix++] = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This change might have joined two change groups,
|
||||||
|
* so we try to take this scenario in account by moving
|
||||||
|
* the start index accordingly (and so the other-file
|
||||||
|
* end-of-group index). Keep tracking the reference
|
||||||
|
* index in case we are shifting together with a
|
||||||
|
* corresponding group of changes in the other file.
|
||||||
|
*/
|
||||||
|
for (; rchg[ix]; ix++);
|
||||||
|
while (rchgo[++ixo])
|
||||||
|
ixref = ix;
|
||||||
|
}
|
||||||
|
} while (grpsiz != ix - ixs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to move back the possibly merged group of changes, to match
|
||||||
|
* the recorded postion in the other file.
|
||||||
|
*/
|
||||||
|
while (ixref < ix) {
|
||||||
|
rchg[--ixs] = 1;
|
||||||
|
rchg[--ix] = 0;
|
||||||
|
while (rchgo[--ixo]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr) {
|
int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr) {
|
||||||
xdchange_t *cscr = NULL, *xch;
|
xdchange_t *cscr = NULL, *xch;
|
||||||
char *rchg1 = xe->xdf1.rchg, *rchg2 = xe->xdf2.rchg;
|
char *rchg1 = xe->xdf1.rchg, *rchg2 = xe->xdf2.rchg;
|
||||||
|
@ -440,13 +546,13 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (xdl_change_compact(&xe.xdf1, &xe.xdf2) < 0 ||
|
||||||
if (xdl_build_script(&xe, &xscr) < 0) {
|
xdl_change_compact(&xe.xdf2, &xe.xdf1) < 0 ||
|
||||||
|
xdl_build_script(&xe, &xscr) < 0) {
|
||||||
|
|
||||||
xdl_free_env(&xe);
|
xdl_free_env(&xe);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xscr) {
|
if (xscr) {
|
||||||
if (xdl_emit_diff(&xe, xscr, ecb, xecfg) < 0) {
|
if (xdl_emit_diff(&xe, xscr, ecb, xecfg) < 0) {
|
||||||
|
|
||||||
|
@ -454,10 +560,8 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
xdl_free_env(&xe);
|
xdl_free_env(&xe);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
xdl_free_script(xscr);
|
xdl_free_script(xscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
xdl_free_env(&xe);
|
xdl_free_env(&xe);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
|
#define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
|
||||||
#define XDL_HASHLONG(v, b) (((unsigned long)(v) * GR_PRIME) >> ((CHAR_BIT * sizeof(unsigned long)) - (b)))
|
#define XDL_HASHLONG(v, b) (((unsigned long)(v) * GR_PRIME) >> ((CHAR_BIT * sizeof(unsigned long)) - (b)))
|
||||||
#define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0)
|
#define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0)
|
||||||
|
#define XDL_RECMATCH(r1, r2) ((r1)->size == (r2)->size && memcmp((r1)->ptr, (r2)->ptr, (r1)->size) == 0)
|
||||||
#define XDL_LE32_PUT(p, v) \
|
#define XDL_LE32_PUT(p, v) \
|
||||||
do { \
|
do { \
|
||||||
unsigned char *__p = (unsigned char *) (p); \
|
unsigned char *__p = (unsigned char *) (p); \
|
||||||
|
|
Loading…
Reference in New Issue