mirror of
https://github.com/git/git.git
synced 2024-11-05 16:52:59 +01:00
Merge branch 'lt/apply'
* lt/apply: git-am: --whitespace=x option. git-apply: war on whitespace -- finishing touches. git-apply --whitespace=nowarn apply --whitespace: configuration option. apply: squelch excessive errors and --whitespace=error-all apply --whitespace fixes and enhancements. The war on trailing whitespace
This commit is contained in:
commit
145c9a60ad
4 changed files with 161 additions and 13 deletions
158
apply.c
158
apply.c
|
@ -34,6 +34,56 @@ static int line_termination = '\n';
|
|||
static const char apply_usage[] =
|
||||
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] <patch>...";
|
||||
|
||||
static enum whitespace_eol {
|
||||
nowarn_whitespace,
|
||||
warn_on_whitespace,
|
||||
error_on_whitespace,
|
||||
strip_whitespace,
|
||||
} new_whitespace = warn_on_whitespace;
|
||||
static int whitespace_error = 0;
|
||||
static int squelch_whitespace_errors = 5;
|
||||
static int applied_after_stripping = 0;
|
||||
static const char *patch_input_file = NULL;
|
||||
|
||||
static void parse_whitespace_option(const char *option)
|
||||
{
|
||||
if (!option) {
|
||||
new_whitespace = warn_on_whitespace;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(option, "warn")) {
|
||||
new_whitespace = warn_on_whitespace;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(option, "nowarn")) {
|
||||
new_whitespace = nowarn_whitespace;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(option, "error")) {
|
||||
new_whitespace = error_on_whitespace;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(option, "error-all")) {
|
||||
new_whitespace = error_on_whitespace;
|
||||
squelch_whitespace_errors = 0;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(option, "strip")) {
|
||||
new_whitespace = strip_whitespace;
|
||||
return;
|
||||
}
|
||||
die("unrecognized whitespace option '%s'", option);
|
||||
}
|
||||
|
||||
static void set_default_whitespace_mode(const char *whitespace_option)
|
||||
{
|
||||
if (!whitespace_option && !apply_default_whitespace) {
|
||||
new_whitespace = (apply
|
||||
? warn_on_whitespace
|
||||
: nowarn_whitespace);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For "diff-stat" like behaviour, we keep track of the biggest change
|
||||
* we've seen, and the longest filename. That allows us to do simple
|
||||
|
@ -815,6 +865,25 @@ static int parse_fragment(char *line, unsigned long size, struct patch *patch, s
|
|||
oldlines--;
|
||||
break;
|
||||
case '+':
|
||||
/*
|
||||
* We know len is at least two, since we have a '+' and
|
||||
* we checked that the last character was a '\n' above.
|
||||
* That is, an addition of an empty line would check
|
||||
* the '+' here. Sneaky...
|
||||
*/
|
||||
if ((new_whitespace != nowarn_whitespace) &&
|
||||
isspace(line[len-2])) {
|
||||
whitespace_error++;
|
||||
if (squelch_whitespace_errors &&
|
||||
squelch_whitespace_errors <
|
||||
whitespace_error)
|
||||
;
|
||||
else {
|
||||
fprintf(stderr, "Adds trailing whitespace.\n%s:%d:%.*s\n",
|
||||
patch_input_file,
|
||||
linenr, len-2, line+1);
|
||||
}
|
||||
}
|
||||
added++;
|
||||
newlines--;
|
||||
break;
|
||||
|
@ -1092,6 +1161,28 @@ struct buffer_desc {
|
|||
unsigned long alloc;
|
||||
};
|
||||
|
||||
static int apply_line(char *output, const char *patch, int plen)
|
||||
{
|
||||
/* plen is number of bytes to be copied from patch,
|
||||
* starting at patch+1 (patch[0] is '+'). Typically
|
||||
* patch[plen] is '\n'.
|
||||
*/
|
||||
int add_nl_to_tail = 0;
|
||||
if ((new_whitespace == strip_whitespace) &&
|
||||
1 < plen && isspace(patch[plen-1])) {
|
||||
if (patch[plen] == '\n')
|
||||
add_nl_to_tail = 1;
|
||||
plen--;
|
||||
while (0 < plen && isspace(patch[plen]))
|
||||
plen--;
|
||||
applied_after_stripping++;
|
||||
}
|
||||
memcpy(output, patch + 1, plen);
|
||||
if (add_nl_to_tail)
|
||||
output[plen++] = '\n';
|
||||
return plen;
|
||||
}
|
||||
|
||||
static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
|
||||
{
|
||||
char *buf = desc->buffer;
|
||||
|
@ -1127,10 +1218,9 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
|
|||
break;
|
||||
/* Fall-through for ' ' */
|
||||
case '+':
|
||||
if (*patch != '+' || !no_add) {
|
||||
memcpy(new + newsize, patch + 1, plen);
|
||||
newsize += plen;
|
||||
}
|
||||
if (*patch != '+' || !no_add)
|
||||
newsize += apply_line(new + newsize, patch,
|
||||
plen);
|
||||
break;
|
||||
case '@': case '\\':
|
||||
/* Ignore it, we already handled it */
|
||||
|
@ -1699,7 +1789,7 @@ static int use_patch(struct patch *p)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int apply_patch(int fd)
|
||||
static int apply_patch(int fd, const char *filename)
|
||||
{
|
||||
int newfd;
|
||||
unsigned long offset, size;
|
||||
|
@ -1707,6 +1797,7 @@ static int apply_patch(int fd)
|
|||
struct patch *list = NULL, **listp = &list;
|
||||
int skipped_patch = 0;
|
||||
|
||||
patch_input_file = filename;
|
||||
if (!buffer)
|
||||
return -1;
|
||||
offset = 0;
|
||||
|
@ -1733,6 +1824,9 @@ static int apply_patch(int fd)
|
|||
}
|
||||
|
||||
newfd = -1;
|
||||
if (whitespace_error && (new_whitespace == error_on_whitespace))
|
||||
apply = 0;
|
||||
|
||||
write_index = check_index && apply;
|
||||
if (write_index)
|
||||
newfd = hold_index_file_for_update(&cache_file, get_index_file());
|
||||
|
@ -1769,17 +1863,28 @@ static int apply_patch(int fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int git_apply_config(const char *var, const char *value)
|
||||
{
|
||||
if (!strcmp(var, "apply.whitespace")) {
|
||||
apply_default_whitespace = strdup(value);
|
||||
return 0;
|
||||
}
|
||||
return git_default_config(var, value);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int read_stdin = 1;
|
||||
const char *whitespace_option = NULL;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
int fd;
|
||||
|
||||
if (!strcmp(arg, "-")) {
|
||||
apply_patch(0);
|
||||
apply_patch(0, "<stdin>");
|
||||
read_stdin = 0;
|
||||
continue;
|
||||
}
|
||||
|
@ -1839,11 +1944,18 @@ int main(int argc, char **argv)
|
|||
line_termination = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(arg, "--whitespace=", 13)) {
|
||||
whitespace_option = arg + 13;
|
||||
parse_whitespace_option(arg + 13);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (check_index && prefix_length < 0) {
|
||||
prefix = setup_git_directory();
|
||||
prefix_length = prefix ? strlen(prefix) : 0;
|
||||
git_config(git_default_config);
|
||||
git_config(git_apply_config);
|
||||
if (!whitespace_option && apply_default_whitespace)
|
||||
parse_whitespace_option(apply_default_whitespace);
|
||||
}
|
||||
if (0 < prefix_length)
|
||||
arg = prefix_filename(prefix, prefix_length, arg);
|
||||
|
@ -1852,10 +1964,38 @@ int main(int argc, char **argv)
|
|||
if (fd < 0)
|
||||
usage(apply_usage);
|
||||
read_stdin = 0;
|
||||
apply_patch(fd);
|
||||
set_default_whitespace_mode(whitespace_option);
|
||||
apply_patch(fd, arg);
|
||||
close(fd);
|
||||
}
|
||||
set_default_whitespace_mode(whitespace_option);
|
||||
if (read_stdin)
|
||||
apply_patch(0);
|
||||
apply_patch(0, "<stdin>");
|
||||
if (whitespace_error) {
|
||||
if (squelch_whitespace_errors &&
|
||||
squelch_whitespace_errors < whitespace_error) {
|
||||
int squelched =
|
||||
whitespace_error - squelch_whitespace_errors;
|
||||
fprintf(stderr, "warning: squelched %d whitespace error%s\n",
|
||||
squelched,
|
||||
squelched == 1 ? "" : "s");
|
||||
}
|
||||
if (new_whitespace == error_on_whitespace)
|
||||
die("%d line%s add%s trailing whitespaces.",
|
||||
whitespace_error,
|
||||
whitespace_error == 1 ? "" : "s",
|
||||
whitespace_error == 1 ? "s" : "");
|
||||
if (applied_after_stripping)
|
||||
fprintf(stderr, "warning: %d line%s applied after"
|
||||
" stripping trailing whitespaces.\n",
|
||||
applied_after_stripping,
|
||||
applied_after_stripping == 1 ? "" : "s");
|
||||
else if (whitespace_error)
|
||||
fprintf(stderr, "warning: %d line%s add%s trailing"
|
||||
" whitespaces.\n",
|
||||
whitespace_error,
|
||||
whitespace_error == 1 ? "" : "s",
|
||||
whitespace_error == 1 ? "s" : "");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
2
cache.h
2
cache.h
|
@ -161,11 +161,13 @@ extern int hold_index_file_for_update(struct cache_file *, const char *path);
|
|||
extern int commit_index_file(struct cache_file *);
|
||||
extern void rollback_index_file(struct cache_file *);
|
||||
|
||||
/* Environment bits from configuration mechanism */
|
||||
extern int trust_executable_bit;
|
||||
extern int assume_unchanged;
|
||||
extern int only_use_symrefs;
|
||||
extern int diff_rename_limit_default;
|
||||
extern int shared_repository;
|
||||
extern const char *apply_default_whitespace;
|
||||
|
||||
#define GIT_REPO_VERSION 0
|
||||
extern int repository_format_version;
|
||||
|
|
|
@ -17,6 +17,7 @@ int only_use_symrefs = 0;
|
|||
int repository_format_version = 0;
|
||||
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
|
||||
int shared_repository = 0;
|
||||
const char *apply_default_whitespace = NULL;
|
||||
|
||||
static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
|
||||
*git_graft_file;
|
||||
|
|
13
git-am.sh
13
git-am.sh
|
@ -100,7 +100,7 @@ fall_back_3way () {
|
|||
}
|
||||
|
||||
prec=4
|
||||
dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary=
|
||||
dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary= ws=
|
||||
|
||||
while case "$#" in 0) break;; esac
|
||||
do
|
||||
|
@ -133,6 +133,9 @@ do
|
|||
--sk|--ski|--skip)
|
||||
skip=t; shift ;;
|
||||
|
||||
--whitespace=*)
|
||||
ws=$1; shift ;;
|
||||
|
||||
--)
|
||||
shift; break ;;
|
||||
-*)
|
||||
|
@ -171,10 +174,11 @@ else
|
|||
exit 1
|
||||
}
|
||||
|
||||
# -b, -s, -u and -k flags are kept for the resuming session after
|
||||
# a patch failure.
|
||||
# -b, -s, -u, -k and --whitespace flags are kept for the
|
||||
# resuming session after a patch failure.
|
||||
# -3 and -i can and must be given when resuming.
|
||||
echo "$binary" >"$dotest/binary"
|
||||
echo " $ws" >"$dotest/whitespace"
|
||||
echo "$sign" >"$dotest/sign"
|
||||
echo "$utf8" >"$dotest/utf8"
|
||||
echo "$keep" >"$dotest/keep"
|
||||
|
@ -202,6 +206,7 @@ if test "$(cat "$dotest/keep")" = t
|
|||
then
|
||||
keep=-k
|
||||
fi
|
||||
ws=`cat "$dotest/whitespace"`
|
||||
if test "$(cat "$dotest/sign")" = t
|
||||
then
|
||||
SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '
|
||||
|
@ -355,7 +360,7 @@ do
|
|||
|
||||
case "$resolved" in
|
||||
'')
|
||||
git-apply $binary --index "$dotest/patch"
|
||||
git-apply $binary --index $ws "$dotest/patch"
|
||||
apply_status=$?
|
||||
;;
|
||||
t)
|
||||
|
|
Loading…
Reference in a new issue