Teach git-apply about '-R'
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
2941cab99c
commit
e5a94313c0
@ -120,7 +120,7 @@ struct fragment {
|
|||||||
struct patch {
|
struct patch {
|
||||||
char *new_name, *old_name, *def_name;
|
char *new_name, *old_name, *def_name;
|
||||||
unsigned int old_mode, new_mode;
|
unsigned int old_mode, new_mode;
|
||||||
int is_rename, is_copy, is_new, is_delete, is_binary;
|
int is_rename, is_copy, is_new, is_delete, is_binary, is_reverse;
|
||||||
#define BINARY_DELTA_DEFLATED 1
|
#define BINARY_DELTA_DEFLATED 1
|
||||||
#define BINARY_LITERAL_DEFLATED 2
|
#define BINARY_LITERAL_DEFLATED 2
|
||||||
unsigned long deflate_origlen;
|
unsigned long deflate_origlen;
|
||||||
@ -1119,6 +1119,34 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
|
|||||||
return offset + hdrsize + patchsize;
|
return offset + hdrsize + patchsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define swap(a,b) myswap((a),(b),sizeof(a))
|
||||||
|
|
||||||
|
#define myswap(a, b, size) do { \
|
||||||
|
unsigned char mytmp[size]; \
|
||||||
|
memcpy(mytmp, &a, size); \
|
||||||
|
memcpy(&a, &b, size); \
|
||||||
|
memcpy(&b, mytmp, size); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static void reverse_patches(struct patch *p)
|
||||||
|
{
|
||||||
|
for (; p; p = p->next) {
|
||||||
|
struct fragment *frag = p->fragments;
|
||||||
|
|
||||||
|
swap(p->new_name, p->old_name);
|
||||||
|
swap(p->new_mode, p->old_mode);
|
||||||
|
swap(p->is_new, p->is_delete);
|
||||||
|
swap(p->lines_added, p->lines_deleted);
|
||||||
|
swap(p->old_sha1_prefix, p->new_sha1_prefix);
|
||||||
|
|
||||||
|
for (; frag; frag = frag->next) {
|
||||||
|
swap(frag->newpos, frag->oldpos);
|
||||||
|
swap(frag->newlines, frag->oldlines);
|
||||||
|
}
|
||||||
|
p->is_reverse = !p->is_reverse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
|
static const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
|
||||||
static const char minuses[]= "----------------------------------------------------------------------";
|
static const char minuses[]= "----------------------------------------------------------------------";
|
||||||
|
|
||||||
@ -1336,7 +1364,7 @@ static int apply_line(char *output, const char *patch, int plen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag,
|
static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag,
|
||||||
int inaccurate_eof)
|
int reverse, int inaccurate_eof)
|
||||||
{
|
{
|
||||||
int match_beginning, match_end;
|
int match_beginning, match_end;
|
||||||
char *buf = desc->buffer;
|
char *buf = desc->buffer;
|
||||||
@ -1350,6 +1378,7 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag,
|
|||||||
int pos, lines;
|
int pos, lines;
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
|
char first;
|
||||||
int len = linelen(patch, size);
|
int len = linelen(patch, size);
|
||||||
int plen;
|
int plen;
|
||||||
|
|
||||||
@ -1366,16 +1395,23 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag,
|
|||||||
plen = len-1;
|
plen = len-1;
|
||||||
if (len < size && patch[len] == '\\')
|
if (len < size && patch[len] == '\\')
|
||||||
plen--;
|
plen--;
|
||||||
switch (*patch) {
|
first = *patch;
|
||||||
|
if (reverse) {
|
||||||
|
if (first == '-')
|
||||||
|
first = '+';
|
||||||
|
else if (first == '+')
|
||||||
|
first = '-';
|
||||||
|
}
|
||||||
|
switch (first) {
|
||||||
case ' ':
|
case ' ':
|
||||||
case '-':
|
case '-':
|
||||||
memcpy(old + oldsize, patch + 1, plen);
|
memcpy(old + oldsize, patch + 1, plen);
|
||||||
oldsize += plen;
|
oldsize += plen;
|
||||||
if (*patch == '-')
|
if (first == '-')
|
||||||
break;
|
break;
|
||||||
/* Fall-through for ' ' */
|
/* Fall-through for ' ' */
|
||||||
case '+':
|
case '+':
|
||||||
if (*patch != '+' || !no_add)
|
if (first != '+' || !no_add)
|
||||||
newsize += apply_line(new + newsize, patch,
|
newsize += apply_line(new + newsize, patch,
|
||||||
plen);
|
plen);
|
||||||
break;
|
break;
|
||||||
@ -1615,7 +1651,8 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
|
|||||||
return apply_binary(desc, patch);
|
return apply_binary(desc, patch);
|
||||||
|
|
||||||
while (frag) {
|
while (frag) {
|
||||||
if (apply_one_fragment(desc, frag, patch->inaccurate_eof) < 0)
|
if (apply_one_fragment(desc, frag, patch->is_reverse,
|
||||||
|
patch->inaccurate_eof) < 0)
|
||||||
return error("patch failed: %s:%ld",
|
return error("patch failed: %s:%ld",
|
||||||
name, frag->oldpos);
|
name, frag->oldpos);
|
||||||
frag = frag->next;
|
frag = frag->next;
|
||||||
@ -2142,7 +2179,8 @@ static int use_patch(struct patch *p)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int apply_patch(int fd, const char *filename, int inaccurate_eof)
|
static int apply_patch(int fd, const char *filename,
|
||||||
|
int reverse, int inaccurate_eof)
|
||||||
{
|
{
|
||||||
unsigned long offset, size;
|
unsigned long offset, size;
|
||||||
char *buffer = read_patch_file(fd, &size);
|
char *buffer = read_patch_file(fd, &size);
|
||||||
@ -2162,6 +2200,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
|
|||||||
nr = parse_chunk(buffer + offset, size, patch);
|
nr = parse_chunk(buffer + offset, size, patch);
|
||||||
if (nr < 0)
|
if (nr < 0)
|
||||||
break;
|
break;
|
||||||
|
if (reverse)
|
||||||
|
reverse_patches(patch);
|
||||||
if (use_patch(patch)) {
|
if (use_patch(patch)) {
|
||||||
patch_stats(patch);
|
patch_stats(patch);
|
||||||
*listp = patch;
|
*listp = patch;
|
||||||
@ -2226,6 +2266,7 @@ int cmd_apply(int argc, const char **argv, char **envp)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int read_stdin = 1;
|
int read_stdin = 1;
|
||||||
|
int reverse = 0;
|
||||||
int inaccurate_eof = 0;
|
int inaccurate_eof = 0;
|
||||||
|
|
||||||
const char *whitespace_option = NULL;
|
const char *whitespace_option = NULL;
|
||||||
@ -2236,7 +2277,7 @@ int cmd_apply(int argc, const char **argv, char **envp)
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (!strcmp(arg, "-")) {
|
if (!strcmp(arg, "-")) {
|
||||||
apply_patch(0, "<stdin>", inaccurate_eof);
|
apply_patch(0, "<stdin>", reverse, inaccurate_eof);
|
||||||
read_stdin = 0;
|
read_stdin = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2313,6 +2354,10 @@ int cmd_apply(int argc, const char **argv, char **envp)
|
|||||||
parse_whitespace_option(arg + 13);
|
parse_whitespace_option(arg + 13);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "-R") || !strcmp(arg, "--reverse")) {
|
||||||
|
reverse = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "--inaccurate-eof")) {
|
if (!strcmp(arg, "--inaccurate-eof")) {
|
||||||
inaccurate_eof = 1;
|
inaccurate_eof = 1;
|
||||||
continue;
|
continue;
|
||||||
@ -2333,12 +2378,12 @@ int cmd_apply(int argc, const char **argv, char **envp)
|
|||||||
usage(apply_usage);
|
usage(apply_usage);
|
||||||
read_stdin = 0;
|
read_stdin = 0;
|
||||||
set_default_whitespace_mode(whitespace_option);
|
set_default_whitespace_mode(whitespace_option);
|
||||||
apply_patch(fd, arg, inaccurate_eof);
|
apply_patch(fd, arg, reverse, inaccurate_eof);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
set_default_whitespace_mode(whitespace_option);
|
set_default_whitespace_mode(whitespace_option);
|
||||||
if (read_stdin)
|
if (read_stdin)
|
||||||
apply_patch(0, "<stdin>", inaccurate_eof);
|
apply_patch(0, "<stdin>", reverse, inaccurate_eof);
|
||||||
if (whitespace_error) {
|
if (whitespace_error) {
|
||||||
if (squelch_whitespace_errors &&
|
if (squelch_whitespace_errors &&
|
||||||
squelch_whitespace_errors < whitespace_error) {
|
squelch_whitespace_errors < whitespace_error) {
|
||||||
|
@ -13,8 +13,8 @@ test_description='git-apply handling copy/rename patch.
|
|||||||
cat >test-patch <<\EOF
|
cat >test-patch <<\EOF
|
||||||
diff --git a/foo b/bar
|
diff --git a/foo b/bar
|
||||||
similarity index 47%
|
similarity index 47%
|
||||||
copy from foo
|
rename from foo
|
||||||
copy to bar
|
rename to bar
|
||||||
--- a/foo
|
--- a/foo
|
||||||
+++ b/bar
|
+++ b/bar
|
||||||
@@ -1 +1 @@
|
@@ -1 +1 @@
|
||||||
@ -39,4 +39,24 @@ else
|
|||||||
'test -f bar && ls -l bar | grep "^-..x......"'
|
'test -f bar && ls -l bar | grep "^-..x......"'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
test_expect_success 'apply reverse' \
|
||||||
|
'git-apply -R --index --stat --summary --apply test-patch &&
|
||||||
|
test "$(cat foo)" = "This is foo"'
|
||||||
|
|
||||||
|
cat >test-patch <<\EOF
|
||||||
|
diff --git a/foo b/bar
|
||||||
|
similarity index 47%
|
||||||
|
copy from foo
|
||||||
|
copy to bar
|
||||||
|
--- a/foo
|
||||||
|
+++ b/bar
|
||||||
|
@@ -1 +1 @@
|
||||||
|
-This is foo
|
||||||
|
+This is bar
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'apply copy' \
|
||||||
|
'git-apply --index --stat --summary --apply test-patch &&
|
||||||
|
test "$(cat bar)" = "This is bar" -a "$(cat foo)" = "This is foo"'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user