Merge branch 'gb/apply-ignore-whitespace'
* gb/apply-ignore-whitespace: git apply: option to ignore whitespace differences
This commit is contained in:
commit
5e092b5bce
@ -461,6 +461,14 @@ it will be treated as a shell command. For example, defining
|
|||||||
executed from the top-level directory of a repository, which may
|
executed from the top-level directory of a repository, which may
|
||||||
not necessarily be the current directory.
|
not necessarily be the current directory.
|
||||||
|
|
||||||
|
apply.ignorewhitespace::
|
||||||
|
When set to 'change', tells 'git-apply' to ignore changes in
|
||||||
|
whitespace, in the same way as the '--ignore-space-change'
|
||||||
|
option.
|
||||||
|
When set to one of: no, none, never, false tells 'git-apply' to
|
||||||
|
respect all whitespace differences.
|
||||||
|
See linkgit:git-apply[1].
|
||||||
|
|
||||||
apply.whitespace::
|
apply.whitespace::
|
||||||
Tells 'git-apply' how to handle whitespaces, in the same way
|
Tells 'git-apply' how to handle whitespaces, in the same way
|
||||||
as the '--whitespace' option. See linkgit:git-apply[1].
|
as the '--whitespace' option. See linkgit:git-apply[1].
|
||||||
|
@ -11,7 +11,7 @@ SYNOPSIS
|
|||||||
[verse]
|
[verse]
|
||||||
'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
|
'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
|
||||||
[--3way] [--interactive] [--committer-date-is-author-date]
|
[--3way] [--interactive] [--committer-date-is-author-date]
|
||||||
[--ignore-date]
|
[--ignore-date] [--ignore-space-change | --ignore-whitespace]
|
||||||
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
||||||
[--reject] [-q | --quiet]
|
[--reject] [-q | --quiet]
|
||||||
[<mbox> | <Maildir>...]
|
[<mbox> | <Maildir>...]
|
||||||
@ -65,6 +65,9 @@ default. You can use `--no-utf8` to override this.
|
|||||||
it is supposed to apply to and we have those blobs
|
it is supposed to apply to and we have those blobs
|
||||||
available locally.
|
available locally.
|
||||||
|
|
||||||
|
--ignore-date::
|
||||||
|
--ignore-space-change::
|
||||||
|
--ignore-whitespace::
|
||||||
--whitespace=<option>::
|
--whitespace=<option>::
|
||||||
-C<n>::
|
-C<n>::
|
||||||
-p<n>::
|
-p<n>::
|
||||||
|
@ -13,6 +13,7 @@ SYNOPSIS
|
|||||||
[--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
|
[--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
|
||||||
[--allow-binary-replacement | --binary] [--reject] [-z]
|
[--allow-binary-replacement | --binary] [--reject] [-z]
|
||||||
[-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
|
[-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
|
||||||
|
[--ignore-space-change | --ignore-whitespace ]
|
||||||
[--whitespace=<nowarn|warn|fix|error|error-all>]
|
[--whitespace=<nowarn|warn|fix|error|error-all>]
|
||||||
[--exclude=PATH] [--include=PATH] [--directory=<root>]
|
[--exclude=PATH] [--include=PATH] [--directory=<root>]
|
||||||
[--verbose] [<patch>...]
|
[--verbose] [<patch>...]
|
||||||
@ -149,6 +150,14 @@ patch to each path is used. A patch to a path that does not match any
|
|||||||
include/exclude pattern is used by default if there is no include pattern
|
include/exclude pattern is used by default if there is no include pattern
|
||||||
on the command line, and ignored if there is any include pattern.
|
on the command line, and ignored if there is any include pattern.
|
||||||
|
|
||||||
|
--ignore-space-change::
|
||||||
|
--ignore-whitespace::
|
||||||
|
When applying a patch, ignore changes in whitespace in context
|
||||||
|
lines if necessary.
|
||||||
|
Context lines will preserve their whitespace, and they will not
|
||||||
|
undergo whitespace fixing regardless of the value of the
|
||||||
|
`--whitespace` option. New lines will still be fixed, though.
|
||||||
|
|
||||||
--whitespace=<action>::
|
--whitespace=<action>::
|
||||||
When applying a patch, detect a new or modified line that has
|
When applying a patch, detect a new or modified line that has
|
||||||
whitespace errors. What are considered whitespace errors is
|
whitespace errors. What are considered whitespace errors is
|
||||||
@ -205,6 +214,10 @@ running `git apply --directory=modules/git-gui`.
|
|||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
apply.ignorewhitespace::
|
||||||
|
Set to 'change' if you want changes in whitespace to be ignored by default.
|
||||||
|
Set to one of: no, none, never, false if you want changes in
|
||||||
|
whitespace to be significant.
|
||||||
apply.whitespace::
|
apply.whitespace::
|
||||||
When no `--whitespace` flag is given from the command
|
When no `--whitespace` flag is given from the command
|
||||||
line, this configuration item is used as the default.
|
line, this configuration item is used as the default.
|
||||||
|
@ -268,8 +268,9 @@ OPTIONS
|
|||||||
exit with the message "Current branch is up to date" in such a
|
exit with the message "Current branch is up to date" in such a
|
||||||
situation.
|
situation.
|
||||||
|
|
||||||
|
--ignore-whitespace::
|
||||||
--whitespace=<option>::
|
--whitespace=<option>::
|
||||||
This flag is passed to the 'git-apply' program
|
These flag are passed to the 'git-apply' program
|
||||||
(see linkgit:git-apply[1]) that applies the patch.
|
(see linkgit:git-apply[1]) that applies the patch.
|
||||||
Incompatible with the --interactive option.
|
Incompatible with the --interactive option.
|
||||||
|
|
||||||
|
173
builtin-apply.c
173
builtin-apply.c
@ -61,6 +61,13 @@ static enum ws_error_action {
|
|||||||
static int whitespace_error;
|
static int whitespace_error;
|
||||||
static int squelch_whitespace_errors = 5;
|
static int squelch_whitespace_errors = 5;
|
||||||
static int applied_after_fixing_ws;
|
static int applied_after_fixing_ws;
|
||||||
|
|
||||||
|
static enum ws_ignore {
|
||||||
|
ignore_ws_none,
|
||||||
|
ignore_ws_change,
|
||||||
|
} ws_ignore_action = ignore_ws_none;
|
||||||
|
|
||||||
|
|
||||||
static const char *patch_input_file;
|
static const char *patch_input_file;
|
||||||
static const char *root;
|
static const char *root;
|
||||||
static int root_len;
|
static int root_len;
|
||||||
@ -97,6 +104,21 @@ static void parse_whitespace_option(const char *option)
|
|||||||
die("unrecognized whitespace option '%s'", option);
|
die("unrecognized whitespace option '%s'", option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_ignorewhitespace_option(const char *option)
|
||||||
|
{
|
||||||
|
if (!option || !strcmp(option, "no") ||
|
||||||
|
!strcmp(option, "false") || !strcmp(option, "never") ||
|
||||||
|
!strcmp(option, "none")) {
|
||||||
|
ws_ignore_action = ignore_ws_none;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!strcmp(option, "change")) {
|
||||||
|
ws_ignore_action = ignore_ws_change;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
die("unrecognized whitespace ignore option '%s'", option);
|
||||||
|
}
|
||||||
|
|
||||||
static void set_default_whitespace_mode(const char *whitespace_option)
|
static void set_default_whitespace_mode(const char *whitespace_option)
|
||||||
{
|
{
|
||||||
if (!whitespace_option && !apply_default_whitespace)
|
if (!whitespace_option && !apply_default_whitespace)
|
||||||
@ -214,6 +236,62 @@ static uint32_t hash_line(const char *cp, size_t len)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare lines s1 of length n1 and s2 of length n2, ignoring
|
||||||
|
* whitespace difference. Returns 1 if they match, 0 otherwise
|
||||||
|
*/
|
||||||
|
static int fuzzy_matchlines(const char *s1, size_t n1,
|
||||||
|
const char *s2, size_t n2)
|
||||||
|
{
|
||||||
|
const char *last1 = s1 + n1 - 1;
|
||||||
|
const char *last2 = s2 + n2 - 1;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (n1 < 0 || n2 < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* ignore line endings */
|
||||||
|
while ((*last1 == '\r') || (*last1 == '\n'))
|
||||||
|
last1--;
|
||||||
|
while ((*last2 == '\r') || (*last2 == '\n'))
|
||||||
|
last2--;
|
||||||
|
|
||||||
|
/* skip leading whitespace */
|
||||||
|
while (isspace(*s1) && (s1 <= last1))
|
||||||
|
s1++;
|
||||||
|
while (isspace(*s2) && (s2 <= last2))
|
||||||
|
s2++;
|
||||||
|
/* early return if both lines are empty */
|
||||||
|
if ((s1 > last1) && (s2 > last2))
|
||||||
|
return 1;
|
||||||
|
while (!result) {
|
||||||
|
result = *s1++ - *s2++;
|
||||||
|
/*
|
||||||
|
* Skip whitespace inside. We check for whitespace on
|
||||||
|
* both buffers because we don't want "a b" to match
|
||||||
|
* "ab"
|
||||||
|
*/
|
||||||
|
if (isspace(*s1) && isspace(*s2)) {
|
||||||
|
while (isspace(*s1) && s1 <= last1)
|
||||||
|
s1++;
|
||||||
|
while (isspace(*s2) && s2 <= last2)
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If we reached the end on one side only,
|
||||||
|
* lines don't match
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
((s2 > last2) && (s1 <= last1)) ||
|
||||||
|
((s1 > last1) && (s2 <= last2)))
|
||||||
|
return 0;
|
||||||
|
if ((s1 > last1) && (s2 > last2))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !result;
|
||||||
|
}
|
||||||
|
|
||||||
static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag)
|
static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag)
|
||||||
{
|
{
|
||||||
ALLOC_GROW(img->line_allocated, img->nr + 1, img->alloc);
|
ALLOC_GROW(img->line_allocated, img->nr + 1, img->alloc);
|
||||||
@ -1672,10 +1750,17 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the preimage, and the common lines in postimage,
|
||||||
|
* from buffer buf of length len. If postlen is 0 the postimage
|
||||||
|
* is updated in place, otherwise it's updated on a new buffer
|
||||||
|
* of length postlen
|
||||||
|
*/
|
||||||
|
|
||||||
static void update_pre_post_images(struct image *preimage,
|
static void update_pre_post_images(struct image *preimage,
|
||||||
struct image *postimage,
|
struct image *postimage,
|
||||||
char *buf,
|
char *buf,
|
||||||
size_t len)
|
size_t len, size_t postlen)
|
||||||
{
|
{
|
||||||
int i, ctx;
|
int i, ctx;
|
||||||
char *new, *old, *fixed;
|
char *new, *old, *fixed;
|
||||||
@ -1694,11 +1779,19 @@ static void update_pre_post_images(struct image *preimage,
|
|||||||
*preimage = fixed_preimage;
|
*preimage = fixed_preimage;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust the common context lines in postimage, in place.
|
* Adjust the common context lines in postimage. This can be
|
||||||
* This is possible because whitespace fixing does not make
|
* done in-place when we are just doing whitespace fixing,
|
||||||
* the string grow.
|
* which does not make the string grow, but needs a new buffer
|
||||||
|
* when ignoring whitespace causes the update, since in this case
|
||||||
|
* we could have e.g. tabs converted to multiple spaces.
|
||||||
|
* We trust the caller to tell us if the update can be done
|
||||||
|
* in place (postlen==0) or not.
|
||||||
*/
|
*/
|
||||||
new = old = postimage->buf;
|
old = postimage->buf;
|
||||||
|
if (postlen)
|
||||||
|
new = postimage->buf = xmalloc(postlen);
|
||||||
|
else
|
||||||
|
new = old;
|
||||||
fixed = preimage->buf;
|
fixed = preimage->buf;
|
||||||
for (i = ctx = 0; i < postimage->nr; i++) {
|
for (i = ctx = 0; i < postimage->nr; i++) {
|
||||||
size_t len = postimage->line[i].len;
|
size_t len = postimage->line[i].len;
|
||||||
@ -1773,12 +1866,58 @@ static int match_fragment(struct image *img,
|
|||||||
!memcmp(img->buf + try, preimage->buf, preimage->len))
|
!memcmp(img->buf + try, preimage->buf, preimage->len))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No exact match. If we are ignoring whitespace, run a line-by-line
|
||||||
|
* fuzzy matching. We collect all the line length information because
|
||||||
|
* we need it to adjust whitespace if we match.
|
||||||
|
*/
|
||||||
|
if (ws_ignore_action == ignore_ws_change) {
|
||||||
|
size_t imgoff = 0;
|
||||||
|
size_t preoff = 0;
|
||||||
|
size_t postlen = postimage->len;
|
||||||
|
size_t imglen[preimage->nr];
|
||||||
|
for (i = 0; i < preimage->nr; i++) {
|
||||||
|
size_t prelen = preimage->line[i].len;
|
||||||
|
|
||||||
|
imglen[i] = img->line[try_lno+i].len;
|
||||||
|
if (!fuzzy_matchlines(
|
||||||
|
img->buf + try + imgoff, imglen[i],
|
||||||
|
preimage->buf + preoff, prelen))
|
||||||
|
return 0;
|
||||||
|
if (preimage->line[i].flag & LINE_COMMON)
|
||||||
|
postlen += imglen[i] - prelen;
|
||||||
|
imgoff += imglen[i];
|
||||||
|
preoff += prelen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ok, the preimage matches with whitespace fuzz. Update it and
|
||||||
|
* the common postimage lines to use the same whitespace as the
|
||||||
|
* target. imgoff now holds the true length of the target that
|
||||||
|
* matches the preimage, and we need to update the line lengths
|
||||||
|
* of the preimage to match the target ones.
|
||||||
|
*/
|
||||||
|
fixed_buf = xmalloc(imgoff);
|
||||||
|
memcpy(fixed_buf, img->buf + try, imgoff);
|
||||||
|
for (i = 0; i < preimage->nr; i++)
|
||||||
|
preimage->line[i].len = imglen[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the preimage buffer and the postimage context lines.
|
||||||
|
*/
|
||||||
|
update_pre_post_images(preimage, postimage,
|
||||||
|
fixed_buf, imgoff, postlen);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ws_error_action != correct_ws_error)
|
if (ws_error_action != correct_ws_error)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The hunk does not apply byte-by-byte, but the hash says
|
* The hunk does not apply byte-by-byte, but the hash says
|
||||||
* it might with whitespace fuzz.
|
* it might with whitespace fuzz. We haven't been asked to
|
||||||
|
* ignore whitespace, we were asked to correct whitespace
|
||||||
|
* errors, so let's try matching after whitespace correction.
|
||||||
*/
|
*/
|
||||||
fixed_buf = xmalloc(preimage->len + 1);
|
fixed_buf = xmalloc(preimage->len + 1);
|
||||||
buf = fixed_buf;
|
buf = fixed_buf;
|
||||||
@ -1830,7 +1969,7 @@ static int match_fragment(struct image *img,
|
|||||||
* hunk match. Update the context lines in the postimage.
|
* hunk match. Update the context lines in the postimage.
|
||||||
*/
|
*/
|
||||||
update_pre_post_images(preimage, postimage,
|
update_pre_post_images(preimage, postimage,
|
||||||
fixed_buf, buf - fixed_buf);
|
fixed_buf, buf - fixed_buf, 0);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
unmatch_exit:
|
unmatch_exit:
|
||||||
@ -3272,6 +3411,8 @@ static int git_apply_config(const char *var, const char *value, void *cb)
|
|||||||
{
|
{
|
||||||
if (!strcmp(var, "apply.whitespace"))
|
if (!strcmp(var, "apply.whitespace"))
|
||||||
return git_config_string(&apply_default_whitespace, var, value);
|
return git_config_string(&apply_default_whitespace, var, value);
|
||||||
|
else if (!strcmp(var, "apply.ignorewhitespace"))
|
||||||
|
return git_config_string(&apply_default_ignorewhitespace, var, value);
|
||||||
return git_default_config(var, value, cb);
|
return git_default_config(var, value, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3308,6 +3449,16 @@ static int option_parse_z(const struct option *opt,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int option_parse_space_change(const struct option *opt,
|
||||||
|
const char *arg, int unset)
|
||||||
|
{
|
||||||
|
if (unset)
|
||||||
|
ws_ignore_action = ignore_ws_none;
|
||||||
|
else
|
||||||
|
ws_ignore_action = ignore_ws_change;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int option_parse_whitespace(const struct option *opt,
|
static int option_parse_whitespace(const struct option *opt,
|
||||||
const char *arg, int unset)
|
const char *arg, int unset)
|
||||||
{
|
{
|
||||||
@ -3384,6 +3535,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
|||||||
{ OPTION_CALLBACK, 0, "whitespace", &whitespace_option, "action",
|
{ OPTION_CALLBACK, 0, "whitespace", &whitespace_option, "action",
|
||||||
"detect new or modified lines that have whitespace errors",
|
"detect new or modified lines that have whitespace errors",
|
||||||
0, option_parse_whitespace },
|
0, option_parse_whitespace },
|
||||||
|
{ OPTION_CALLBACK, 0, "ignore-space-change", NULL, NULL,
|
||||||
|
"ignore changes in whitespace when finding context",
|
||||||
|
PARSE_OPT_NOARG, option_parse_space_change },
|
||||||
|
{ OPTION_CALLBACK, 0, "ignore-whitespace", NULL, NULL,
|
||||||
|
"ignore changes in whitespace when finding context",
|
||||||
|
PARSE_OPT_NOARG, option_parse_space_change },
|
||||||
OPT_BOOLEAN('R', "reverse", &apply_in_reverse,
|
OPT_BOOLEAN('R', "reverse", &apply_in_reverse,
|
||||||
"apply the patch in reverse"),
|
"apply the patch in reverse"),
|
||||||
OPT_BOOLEAN(0, "unidiff-zero", &unidiff_zero,
|
OPT_BOOLEAN(0, "unidiff-zero", &unidiff_zero,
|
||||||
@ -3408,6 +3565,8 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
|||||||
git_config(git_apply_config, NULL);
|
git_config(git_apply_config, NULL);
|
||||||
if (apply_default_whitespace)
|
if (apply_default_whitespace)
|
||||||
parse_whitespace_option(apply_default_whitespace);
|
parse_whitespace_option(apply_default_whitespace);
|
||||||
|
if (apply_default_ignorewhitespace)
|
||||||
|
parse_ignorewhitespace_option(apply_default_ignorewhitespace);
|
||||||
|
|
||||||
argc = parse_options(argc, argv, prefix, builtin_apply_options,
|
argc = parse_options(argc, argv, prefix, builtin_apply_options,
|
||||||
apply_usage, 0);
|
apply_usage, 0);
|
||||||
|
1
cache.h
1
cache.h
@ -512,6 +512,7 @@ extern int log_all_ref_updates;
|
|||||||
extern int warn_ambiguous_refs;
|
extern int warn_ambiguous_refs;
|
||||||
extern int shared_repository;
|
extern int shared_repository;
|
||||||
extern const char *apply_default_whitespace;
|
extern const char *apply_default_whitespace;
|
||||||
|
extern const char *apply_default_ignorewhitespace;
|
||||||
extern int zlib_compression_level;
|
extern int zlib_compression_level;
|
||||||
extern int core_compression_level;
|
extern int core_compression_level;
|
||||||
extern int core_compression_seen;
|
extern int core_compression_seen;
|
||||||
|
@ -674,6 +674,7 @@ _git_am ()
|
|||||||
--*)
|
--*)
|
||||||
__gitcomp "
|
__gitcomp "
|
||||||
--3way --committer-date-is-author-date --ignore-date
|
--3way --committer-date-is-author-date --ignore-date
|
||||||
|
--ignore-whitespace --ignore-space-change
|
||||||
--interactive --keep --no-utf8 --signoff --utf8
|
--interactive --keep --no-utf8 --signoff --utf8
|
||||||
--whitespace=
|
--whitespace=
|
||||||
"
|
"
|
||||||
@ -695,6 +696,7 @@ _git_apply ()
|
|||||||
--stat --numstat --summary --check --index
|
--stat --numstat --summary --check --index
|
||||||
--cached --index-info --reverse --reject --unidiff-zero
|
--cached --index-info --reverse --reject --unidiff-zero
|
||||||
--apply --no-add --exclude=
|
--apply --no-add --exclude=
|
||||||
|
--ignore-whitespace --ignore-space-change
|
||||||
--whitespace= --inaccurate-eof --verbose
|
--whitespace= --inaccurate-eof --verbose
|
||||||
"
|
"
|
||||||
return
|
return
|
||||||
@ -1537,6 +1539,7 @@ _git_config ()
|
|||||||
__gitcomp "
|
__gitcomp "
|
||||||
add.ignore-errors
|
add.ignore-errors
|
||||||
alias.
|
alias.
|
||||||
|
apply.ignorewhitespace
|
||||||
apply.whitespace
|
apply.whitespace
|
||||||
branch.autosetupmerge
|
branch.autosetupmerge
|
||||||
branch.autosetuprebase
|
branch.autosetuprebase
|
||||||
|
@ -26,6 +26,7 @@ const char *git_commit_encoding;
|
|||||||
const char *git_log_output_encoding;
|
const char *git_log_output_encoding;
|
||||||
int shared_repository = PERM_UMASK;
|
int shared_repository = PERM_UMASK;
|
||||||
const char *apply_default_whitespace;
|
const char *apply_default_whitespace;
|
||||||
|
const char *apply_default_ignorewhitespace;
|
||||||
int zlib_compression_level = Z_BEST_SPEED;
|
int zlib_compression_level = Z_BEST_SPEED;
|
||||||
int core_compression_level;
|
int core_compression_level;
|
||||||
int core_compression_seen;
|
int core_compression_seen;
|
||||||
|
@ -16,6 +16,8 @@ s,signoff add a Signed-off-by line to the commit message
|
|||||||
u,utf8 recode into utf8 (default)
|
u,utf8 recode into utf8 (default)
|
||||||
k,keep pass -k flag to git-mailinfo
|
k,keep pass -k flag to git-mailinfo
|
||||||
whitespace= pass it through git-apply
|
whitespace= pass it through git-apply
|
||||||
|
ignore-space-change pass it through git-apply
|
||||||
|
ignore-whitespace pass it through git-apply
|
||||||
directory= pass it through git-apply
|
directory= pass it through git-apply
|
||||||
C= pass it through git-apply
|
C= pass it through git-apply
|
||||||
p= pass it through git-apply
|
p= pass it through git-apply
|
||||||
@ -327,7 +329,7 @@ do
|
|||||||
git_apply_opt="$git_apply_opt $(sq "$1$2")"; shift ;;
|
git_apply_opt="$git_apply_opt $(sq "$1$2")"; shift ;;
|
||||||
--patch-format)
|
--patch-format)
|
||||||
shift ; patch_format="$1" ;;
|
shift ; patch_format="$1" ;;
|
||||||
--reject)
|
--reject|--ignore-whitespace|--ignore-space-change)
|
||||||
git_apply_opt="$git_apply_opt $1" ;;
|
git_apply_opt="$git_apply_opt $1" ;;
|
||||||
--committer-date-is-author-date)
|
--committer-date-is-author-date)
|
||||||
committer_date_is_author_date=t ;;
|
committer_date_is_author_date=t ;;
|
||||||
|
@ -333,6 +333,9 @@ do
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
--ignore-whitespace)
|
||||||
|
git_am_opt="$git_am_opt $1"
|
||||||
|
;;
|
||||||
--committer-date-is-author-date|--ignore-date)
|
--committer-date-is-author-date|--ignore-date)
|
||||||
git_am_opt="$git_am_opt $1"
|
git_am_opt="$git_am_opt $1"
|
||||||
force_rebase=t
|
force_rebase=t
|
||||||
|
185
t/t4107-apply-ignore-whitespace.sh
Executable file
185
t/t4107-apply-ignore-whitespace.sh
Executable file
@ -0,0 +1,185 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009 Giuseppe Bilotta
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='git-apply --ignore-whitespace.
|
||||||
|
|
||||||
|
'
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
# This primes main.c file that indents without using HT at all.
|
||||||
|
# Various patches with HT and other spaces are attempted in the test.
|
||||||
|
|
||||||
|
cat > patch1.patch <<\EOF
|
||||||
|
diff --git a/main.c b/main.c
|
||||||
|
new file mode 100644
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/main.c
|
||||||
|
@@ -0,0 +1,22 @@
|
||||||
|
+#include <stdio.h>
|
||||||
|
+
|
||||||
|
+void print_int(int num);
|
||||||
|
+int func(int num);
|
||||||
|
+
|
||||||
|
+int main() {
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < 10; i++) {
|
||||||
|
+ print_int(func(i)); /* stuff */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int func(int num) {
|
||||||
|
+ return num * num;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void print_int(int num) {
|
||||||
|
+ printf("%d", num);
|
||||||
|
+}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Since whitespace is very significant and we want to prevent whitespace
|
||||||
|
# mangling when creating this test from a patch, we protect 'fixable'
|
||||||
|
# whitespace by replacing spaces with Z and replacing them at patch
|
||||||
|
# creation time, hence the sed trick.
|
||||||
|
|
||||||
|
# This patch will fail unless whitespace differences are being ignored
|
||||||
|
|
||||||
|
sed -e 's/Z/ /g' > patch2.patch <<\EOF
|
||||||
|
diff --git a/main.c b/main.c
|
||||||
|
--- a/main.c
|
||||||
|
+++ b/main.c
|
||||||
|
@@ -10,6 +10,8 @@
|
||||||
|
Z print_int(func(i)); /* stuff */
|
||||||
|
Z }
|
||||||
|
Z
|
||||||
|
+ printf("\n");
|
||||||
|
+
|
||||||
|
Z return 0;
|
||||||
|
Z}
|
||||||
|
Z
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# This patch will fail even if whitespace differences are being ignored,
|
||||||
|
# because of the missing string at EOL. TODO: this testcase should be
|
||||||
|
# improved by creating a line that has the same hash with and without
|
||||||
|
# the final string.
|
||||||
|
|
||||||
|
sed -e 's/Z/ /g' > patch3.patch <<\EOF
|
||||||
|
diff --git a/main.c b/main.c
|
||||||
|
--- a/main.c
|
||||||
|
+++ b/main.c
|
||||||
|
@@ -10,3 +10,4 @@
|
||||||
|
Z for (i = 0; i < 10; i++) {
|
||||||
|
Z print_int(func(i));Z
|
||||||
|
+ /* stuff */
|
||||||
|
Z }
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# This patch will fail even if whitespace differences are being ignored,
|
||||||
|
# because of the missing EOL at EOF.
|
||||||
|
|
||||||
|
sed -e 's/Z/ /g' > patch4.patch <<\EOF
|
||||||
|
diff --git a/main.c b/main.c
|
||||||
|
--- a/main.c
|
||||||
|
+++ b/main.c
|
||||||
|
@@ -21,1 +21,1 @@
|
||||||
|
- };Z
|
||||||
|
\ No newline at end of file
|
||||||
|
+ };
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# This patch will fail unless whitespace differences are being ignored.
|
||||||
|
|
||||||
|
sed -e 's/Z/ /g' > patch5.patch <<\EOF
|
||||||
|
diff --git a/main.c b/main.c
|
||||||
|
--- a/main.c
|
||||||
|
+++ b/main.c
|
||||||
|
@@ -2,2 +2,3 @@
|
||||||
|
Z void print_int(int num);
|
||||||
|
+ /* a comment */
|
||||||
|
Z int func(int num);
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# And this is how the final output should be. Patches introduce
|
||||||
|
# HTs but the original SP indents are mostly kept.
|
||||||
|
|
||||||
|
sed -e 's/T/ /g' > main.c.final <<\EOF
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void print_int(int num);
|
||||||
|
T/* a comment */
|
||||||
|
int func(int num);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
print_int(func(i)); /* stuff */
|
||||||
|
}
|
||||||
|
|
||||||
|
Tprintf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int func(int num) {
|
||||||
|
return num * num;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_int(int num) {
|
||||||
|
printf("%d", num);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'file creation' '
|
||||||
|
git-apply patch1.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'patch2 fails (retab)' '
|
||||||
|
test_must_fail git-apply patch2.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'patch2 applies with --ignore-whitespace' '
|
||||||
|
git-apply --ignore-whitespace patch2.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'patch2 reverse applies with --ignore-space-change' '
|
||||||
|
git-apply -R --ignore-space-change patch2.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
git config apply.ignorewhitespace change
|
||||||
|
|
||||||
|
test_expect_success 'patch2 applies (apply.ignorewhitespace = change)' '
|
||||||
|
git-apply patch2.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'patch3 fails (missing string at EOL)' '
|
||||||
|
test_must_fail git-apply patch3.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'patch4 fails (missing EOL at EOF)' '
|
||||||
|
test_must_fail git-apply patch4.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'patch5 applies (leading whitespace)' '
|
||||||
|
git-apply patch5.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'patches do not mangle whitespace' '
|
||||||
|
test_cmp main.c main.c.final
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 're-create file (with --ignore-whitespace)' '
|
||||||
|
rm -f main.c &&
|
||||||
|
git-apply patch1.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'patch5 fails (--no-ignore-whitespace)' '
|
||||||
|
test_must_fail git-apply --no-ignore-whitespace patch5.patch
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user