Merge branch 'lt/apply' into next
* lt/apply: Clean up sha1 file writing Builtin git-cat-file apply: force matching at the beginning. Add a test-case for git-apply trying to add an ending line apply: treat EOF as proper context.
This commit is contained in:
commit
63bccad38a
6
Makefile
6
Makefile
@ -149,7 +149,6 @@ SIMPLE_PROGRAMS = \
|
|||||||
|
|
||||||
# ... and all the rest that could be moved out of bindir to gitexecdir
|
# ... and all the rest that could be moved out of bindir to gitexecdir
|
||||||
PROGRAMS = \
|
PROGRAMS = \
|
||||||
git-cat-file$X \
|
|
||||||
git-checkout-index$X git-clone-pack$X \
|
git-checkout-index$X git-clone-pack$X \
|
||||||
git-convert-objects$X git-fetch-pack$X git-fsck-objects$X \
|
git-convert-objects$X git-fetch-pack$X git-fsck-objects$X \
|
||||||
git-hash-object$X git-index-pack$X git-local-fetch$X \
|
git-hash-object$X git-index-pack$X git-local-fetch$X \
|
||||||
@ -174,7 +173,7 @@ BUILT_INS = git-log$X git-whatchanged$X git-show$X \
|
|||||||
git-ls-files$X git-ls-tree$X \
|
git-ls-files$X git-ls-tree$X \
|
||||||
git-read-tree$X git-commit-tree$X \
|
git-read-tree$X git-commit-tree$X \
|
||||||
git-apply$X git-show-branch$X git-diff-files$X \
|
git-apply$X git-show-branch$X git-diff-files$X \
|
||||||
git-diff-index$X git-diff-stages$X git-diff-tree$X
|
git-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X
|
||||||
|
|
||||||
# what 'all' will build and 'install' will install, in gitexecdir
|
# what 'all' will build and 'install' will install, in gitexecdir
|
||||||
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
|
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
|
||||||
@ -228,7 +227,8 @@ BUILTIN_OBJS = \
|
|||||||
builtin-ls-files.o builtin-ls-tree.o \
|
builtin-ls-files.o builtin-ls-tree.o \
|
||||||
builtin-read-tree.o builtin-commit-tree.o \
|
builtin-read-tree.o builtin-commit-tree.o \
|
||||||
builtin-apply.o builtin-show-branch.o builtin-diff-files.o \
|
builtin-apply.o builtin-show-branch.o builtin-diff-files.o \
|
||||||
builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o
|
builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \
|
||||||
|
builtin-cat-file.o
|
||||||
|
|
||||||
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
|
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
|
||||||
LIBS = $(GITLIBS) -lz
|
LIBS = $(GITLIBS) -lz
|
||||||
|
@ -1335,6 +1335,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 match_beginning, match_end;
|
||||||
char *buf = desc->buffer;
|
char *buf = desc->buffer;
|
||||||
const char *patch = frag->patch;
|
const char *patch = frag->patch;
|
||||||
int offset, size = frag->size;
|
int offset, size = frag->size;
|
||||||
@ -1397,10 +1398,22 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
|
|||||||
newlines = new;
|
newlines = new;
|
||||||
leading = frag->leading;
|
leading = frag->leading;
|
||||||
trailing = frag->trailing;
|
trailing = frag->trailing;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we don't have any leading/trailing data in the patch,
|
||||||
|
* we want it to match at the beginning/end of the file.
|
||||||
|
*/
|
||||||
|
match_beginning = !leading && (frag->oldpos == 1);
|
||||||
|
match_end = !trailing;
|
||||||
|
|
||||||
lines = 0;
|
lines = 0;
|
||||||
pos = frag->newpos;
|
pos = frag->newpos;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
offset = find_offset(buf, desc->size, oldlines, oldsize, pos, &lines);
|
offset = find_offset(buf, desc->size, oldlines, oldsize, pos, &lines);
|
||||||
|
if (match_end && offset + oldsize != desc->size)
|
||||||
|
offset = -1;
|
||||||
|
if (match_beginning && offset)
|
||||||
|
offset = -1;
|
||||||
if (offset >= 0) {
|
if (offset >= 0) {
|
||||||
int diff = newsize - oldsize;
|
int diff = newsize - oldsize;
|
||||||
unsigned long size = desc->size + diff;
|
unsigned long size = desc->size + diff;
|
||||||
@ -1430,6 +1443,10 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
|
|||||||
/* Am I at my context limits? */
|
/* Am I at my context limits? */
|
||||||
if ((leading <= p_context) && (trailing <= p_context))
|
if ((leading <= p_context) && (trailing <= p_context))
|
||||||
break;
|
break;
|
||||||
|
if (match_beginning || match_end) {
|
||||||
|
match_beginning = match_end = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* Reduce the number of context lines
|
/* Reduce the number of context lines
|
||||||
* Reduce both leading and trailing if they are equal
|
* Reduce both leading and trailing if they are equal
|
||||||
* otherwise just reduce the larger context.
|
* otherwise just reduce the larger context.
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "exec_cmd.h"
|
#include "exec_cmd.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
#include "builtin.h"
|
||||||
|
|
||||||
static void flush_buffer(const char *buf, unsigned long size)
|
static void flush_buffer(const char *buf, unsigned long size)
|
||||||
{
|
{
|
||||||
@ -93,7 +94,7 @@ static int pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int cmd_cat_file(int argc, const char **argv, char **envp)
|
||||||
{
|
{
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
char type[20];
|
char type[20];
|
@ -42,5 +42,6 @@ extern int cmd_diff_files(int argc, const char **argv, char **envp);
|
|||||||
extern int cmd_diff_index(int argc, const char **argv, char **envp);
|
extern int cmd_diff_index(int argc, const char **argv, char **envp);
|
||||||
extern int cmd_diff_stages(int argc, const char **argv, char **envp);
|
extern int cmd_diff_stages(int argc, const char **argv, char **envp);
|
||||||
extern int cmd_diff_tree(int argc, const char **argv, char **envp);
|
extern int cmd_diff_tree(int argc, const char **argv, char **envp);
|
||||||
|
extern int cmd_cat_file(int argc, const char **argv, char **envp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
3
git.c
3
git.c
@ -68,7 +68,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
|
|||||||
{ "diff-files", cmd_diff_files },
|
{ "diff-files", cmd_diff_files },
|
||||||
{ "diff-index", cmd_diff_index },
|
{ "diff-index", cmd_diff_index },
|
||||||
{ "diff-stages", cmd_diff_stages },
|
{ "diff-stages", cmd_diff_stages },
|
||||||
{ "diff-tree", cmd_diff_tree }
|
{ "diff-tree", cmd_diff_tree },
|
||||||
|
{ "cat-file", cmd_cat_file }
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep)
|
|||||||
diff_unique_abbrev(commit->object.sha1, abbrev_commit));
|
diff_unique_abbrev(commit->object.sha1, abbrev_commit));
|
||||||
if (opt->parents)
|
if (opt->parents)
|
||||||
show_parents(commit, abbrev_commit);
|
show_parents(commit, abbrev_commit);
|
||||||
if (parent)
|
if (parent)
|
||||||
printf(" (from %s)",
|
printf(" (from %s)",
|
||||||
diff_unique_abbrev(parent->object.sha1,
|
diff_unique_abbrev(parent->object.sha1,
|
||||||
abbrev_commit));
|
abbrev_commit));
|
||||||
|
145
sha1_file.c
145
sha1_file.c
@ -1399,6 +1399,25 @@ int move_temp_to_file(const char *tmpfile, char *filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int write_buffer(int fd, const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
while (len) {
|
||||||
|
ssize_t size;
|
||||||
|
|
||||||
|
size = write(fd, buf, len);
|
||||||
|
if (!size)
|
||||||
|
return error("file write: disk full");
|
||||||
|
if (size < 0) {
|
||||||
|
if (errno == EINTR || errno == EAGAIN)
|
||||||
|
continue;
|
||||||
|
return error("file write error (%s)", strerror(errno));
|
||||||
|
}
|
||||||
|
len -= size;
|
||||||
|
buf += size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
|
int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
@ -1465,8 +1484,8 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
|
|||||||
deflateEnd(&stream);
|
deflateEnd(&stream);
|
||||||
size = stream.total_out;
|
size = stream.total_out;
|
||||||
|
|
||||||
if (write(fd, compressed, size) != size)
|
if (write_buffer(fd, compressed, size) < 0)
|
||||||
die("unable to write file");
|
die("unable to write sha1 file");
|
||||||
fchmod(fd, 0444);
|
fchmod(fd, 0444);
|
||||||
close(fd);
|
close(fd);
|
||||||
free(compressed);
|
free(compressed);
|
||||||
@ -1474,73 +1493,70 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
|
|||||||
return move_temp_to_file(tmpfile, filename);
|
return move_temp_to_file(tmpfile, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to unpack and recompress the object for writing
|
||||||
|
* it out to a different file.
|
||||||
|
*/
|
||||||
|
static void *repack_object(const unsigned char *sha1, unsigned long *objsize)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
z_stream stream;
|
||||||
|
unsigned char *unpacked;
|
||||||
|
unsigned long len;
|
||||||
|
char type[20];
|
||||||
|
char hdr[50];
|
||||||
|
int hdrlen;
|
||||||
|
void *buf;
|
||||||
|
|
||||||
|
// need to unpack and recompress it by itself
|
||||||
|
unpacked = read_packed_sha1(sha1, type, &len);
|
||||||
|
|
||||||
|
hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
|
||||||
|
|
||||||
|
/* Set it up */
|
||||||
|
memset(&stream, 0, sizeof(stream));
|
||||||
|
deflateInit(&stream, Z_BEST_COMPRESSION);
|
||||||
|
size = deflateBound(&stream, len + hdrlen);
|
||||||
|
buf = xmalloc(size);
|
||||||
|
|
||||||
|
/* Compress it */
|
||||||
|
stream.next_out = buf;
|
||||||
|
stream.avail_out = size;
|
||||||
|
|
||||||
|
/* First header.. */
|
||||||
|
stream.next_in = (void *)hdr;
|
||||||
|
stream.avail_in = hdrlen;
|
||||||
|
while (deflate(&stream, 0) == Z_OK)
|
||||||
|
/* nothing */;
|
||||||
|
|
||||||
|
/* Then the data itself.. */
|
||||||
|
stream.next_in = unpacked;
|
||||||
|
stream.avail_in = len;
|
||||||
|
while (deflate(&stream, Z_FINISH) == Z_OK)
|
||||||
|
/* nothing */;
|
||||||
|
deflateEnd(&stream);
|
||||||
|
free(unpacked);
|
||||||
|
|
||||||
|
*objsize = stream.total_out;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
int write_sha1_to_fd(int fd, const unsigned char *sha1)
|
int write_sha1_to_fd(int fd, const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
ssize_t size;
|
int retval;
|
||||||
unsigned long objsize;
|
unsigned long objsize;
|
||||||
int posn = 0;
|
void *buf = map_sha1_file_internal(sha1, &objsize);
|
||||||
void *map = map_sha1_file_internal(sha1, &objsize);
|
|
||||||
void *buf = map;
|
|
||||||
void *temp_obj = NULL;
|
|
||||||
z_stream stream;
|
|
||||||
|
|
||||||
if (!buf) {
|
if (buf) {
|
||||||
unsigned char *unpacked;
|
retval = write_buffer(fd, buf, objsize);
|
||||||
unsigned long len;
|
munmap(buf, objsize);
|
||||||
char type[20];
|
return retval;
|
||||||
char hdr[50];
|
|
||||||
int hdrlen;
|
|
||||||
// need to unpack and recompress it by itself
|
|
||||||
unpacked = read_packed_sha1(sha1, type, &len);
|
|
||||||
|
|
||||||
hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
|
|
||||||
|
|
||||||
/* Set it up */
|
|
||||||
memset(&stream, 0, sizeof(stream));
|
|
||||||
deflateInit(&stream, Z_BEST_COMPRESSION);
|
|
||||||
size = deflateBound(&stream, len + hdrlen);
|
|
||||||
temp_obj = buf = xmalloc(size);
|
|
||||||
|
|
||||||
/* Compress it */
|
|
||||||
stream.next_out = buf;
|
|
||||||
stream.avail_out = size;
|
|
||||||
|
|
||||||
/* First header.. */
|
|
||||||
stream.next_in = (void *)hdr;
|
|
||||||
stream.avail_in = hdrlen;
|
|
||||||
while (deflate(&stream, 0) == Z_OK)
|
|
||||||
/* nothing */;
|
|
||||||
|
|
||||||
/* Then the data itself.. */
|
|
||||||
stream.next_in = unpacked;
|
|
||||||
stream.avail_in = len;
|
|
||||||
while (deflate(&stream, Z_FINISH) == Z_OK)
|
|
||||||
/* nothing */;
|
|
||||||
deflateEnd(&stream);
|
|
||||||
free(unpacked);
|
|
||||||
|
|
||||||
objsize = stream.total_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
buf = repack_object(sha1, &objsize);
|
||||||
size = write(fd, buf + posn, objsize - posn);
|
retval = write_buffer(fd, buf, objsize);
|
||||||
if (size <= 0) {
|
free(buf);
|
||||||
if (!size) {
|
return retval;
|
||||||
fprintf(stderr, "write closed\n");
|
|
||||||
} else {
|
|
||||||
perror("write ");
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
posn += size;
|
|
||||||
} while (posn < objsize);
|
|
||||||
|
|
||||||
if (map)
|
|
||||||
munmap(map, objsize);
|
|
||||||
if (temp_obj)
|
|
||||||
free(temp_obj);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
|
int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
|
||||||
@ -1579,7 +1595,8 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
|
|||||||
SHA1_Update(&c, discard, sizeof(discard) -
|
SHA1_Update(&c, discard, sizeof(discard) -
|
||||||
stream.avail_out);
|
stream.avail_out);
|
||||||
} while (stream.avail_in && ret == Z_OK);
|
} while (stream.avail_in && ret == Z_OK);
|
||||||
write(local, buffer, *bufposn - stream.avail_in);
|
if (write_buffer(local, buffer, *bufposn - stream.avail_in) < 0)
|
||||||
|
die("unable to write sha1 file");
|
||||||
memmove(buffer, buffer + *bufposn - stream.avail_in,
|
memmove(buffer, buffer + *bufposn - stream.avail_in,
|
||||||
stream.avail_in);
|
stream.avail_in);
|
||||||
*bufposn = stream.avail_in;
|
*bufposn = stream.avail_in;
|
||||||
|
53
t/t4113-apply-ending.sh
Executable file
53
t/t4113-apply-ending.sh
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006 Catalin Marinas
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='git-apply trying to add an ending line.
|
||||||
|
|
||||||
|
'
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
# setup
|
||||||
|
|
||||||
|
cat >test-patch <<\EOF
|
||||||
|
diff --git a/file b/file
|
||||||
|
--- a/file
|
||||||
|
+++ b/file
|
||||||
|
@@ -1,2 +1,3 @@
|
||||||
|
a
|
||||||
|
b
|
||||||
|
+c
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo 'a' >file
|
||||||
|
echo 'b' >>file
|
||||||
|
echo 'c' >>file
|
||||||
|
|
||||||
|
test_expect_success setup \
|
||||||
|
'git-update-index --add file'
|
||||||
|
|
||||||
|
# test
|
||||||
|
|
||||||
|
test_expect_failure 'apply at the end' \
|
||||||
|
'git-apply --index test-patch'
|
||||||
|
|
||||||
|
cat >test-patch <<\EOF
|
||||||
|
diff a/file b/file
|
||||||
|
--- a/file
|
||||||
|
+++ b/file
|
||||||
|
@@ -1,2 +1,3 @@
|
||||||
|
+a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo >file 'a
|
||||||
|
b
|
||||||
|
c'
|
||||||
|
git-update-index file
|
||||||
|
|
||||||
|
test_expect_failure 'apply at the beginning' \
|
||||||
|
'git-apply --index test-patch'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user