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:
Johannes Schindelin 2006-07-28 17:46:11 +02:00 committed by Junio C Hamano
parent 2941cab99c
commit e5a94313c0
2 changed files with 77 additions and 12 deletions

View File

@ -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) {

View File

@ -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