streaming: make streaming-write-entry to be more reusable
The static function in entry.c takes a cache entry and streams its blob contents to a file in the working tree. Refactor the logic to a new API function stream_blob_to_fd() that takes an object name and an open file descriptor, so that it can be reused by other callers. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
2980b0de1b
commit
47a02ff2ca
53
entry.c
53
entry.c
@ -120,58 +120,15 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
|
|||||||
const struct checkout *state, int to_tempfile,
|
const struct checkout *state, int to_tempfile,
|
||||||
int *fstat_done, struct stat *statbuf)
|
int *fstat_done, struct stat *statbuf)
|
||||||
{
|
{
|
||||||
struct git_istream *st;
|
|
||||||
enum object_type type;
|
|
||||||
unsigned long sz;
|
|
||||||
int result = -1;
|
int result = -1;
|
||||||
ssize_t kept = 0;
|
int fd;
|
||||||
int fd = -1;
|
|
||||||
|
|
||||||
st = open_istream(ce->sha1, &type, &sz, filter);
|
|
||||||
if (!st)
|
|
||||||
return -1;
|
|
||||||
if (type != OBJ_BLOB)
|
|
||||||
goto close_and_exit;
|
|
||||||
|
|
||||||
fd = open_output_fd(path, ce, to_tempfile);
|
fd = open_output_fd(path, ce, to_tempfile);
|
||||||
if (fd < 0)
|
if (0 <= fd) {
|
||||||
goto close_and_exit;
|
result = stream_blob_to_fd(fd, ce->sha1, filter, 1);
|
||||||
|
*fstat_done = fstat_output(fd, state, statbuf);
|
||||||
for (;;) {
|
|
||||||
char buf[1024 * 16];
|
|
||||||
ssize_t wrote, holeto;
|
|
||||||
ssize_t readlen = read_istream(st, buf, sizeof(buf));
|
|
||||||
|
|
||||||
if (!readlen)
|
|
||||||
break;
|
|
||||||
if (sizeof(buf) == readlen) {
|
|
||||||
for (holeto = 0; holeto < readlen; holeto++)
|
|
||||||
if (buf[holeto])
|
|
||||||
break;
|
|
||||||
if (readlen == holeto) {
|
|
||||||
kept += holeto;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kept && lseek(fd, kept, SEEK_CUR) == (off_t) -1)
|
|
||||||
goto close_and_exit;
|
|
||||||
else
|
|
||||||
kept = 0;
|
|
||||||
wrote = write_in_full(fd, buf, readlen);
|
|
||||||
|
|
||||||
if (wrote != readlen)
|
|
||||||
goto close_and_exit;
|
|
||||||
}
|
|
||||||
if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||
|
|
||||||
write(fd, "", 1) != 1))
|
|
||||||
goto close_and_exit;
|
|
||||||
*fstat_done = fstat_output(fd, state, statbuf);
|
|
||||||
|
|
||||||
close_and_exit:
|
|
||||||
close_istream(st);
|
|
||||||
if (0 <= fd)
|
|
||||||
result = close(fd);
|
result = close(fd);
|
||||||
|
}
|
||||||
if (result && 0 <= fd)
|
if (result && 0 <= fd)
|
||||||
unlink(path);
|
unlink(path);
|
||||||
return result;
|
return result;
|
||||||
|
55
streaming.c
55
streaming.c
@ -489,3 +489,58 @@ static open_method_decl(incore)
|
|||||||
|
|
||||||
return st->u.incore.buf ? 0 : -1;
|
return st->u.incore.buf ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
* Users of streaming interface
|
||||||
|
****************************************************************/
|
||||||
|
|
||||||
|
int stream_blob_to_fd(int fd, unsigned const char *sha1, struct stream_filter *filter,
|
||||||
|
int can_seek)
|
||||||
|
{
|
||||||
|
struct git_istream *st;
|
||||||
|
enum object_type type;
|
||||||
|
unsigned long sz;
|
||||||
|
ssize_t kept = 0;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
st = open_istream(sha1, &type, &sz, filter);
|
||||||
|
if (!st)
|
||||||
|
return result;
|
||||||
|
if (type != OBJ_BLOB)
|
||||||
|
goto close_and_exit;
|
||||||
|
for (;;) {
|
||||||
|
char buf[1024 * 16];
|
||||||
|
ssize_t wrote, holeto;
|
||||||
|
ssize_t readlen = read_istream(st, buf, sizeof(buf));
|
||||||
|
|
||||||
|
if (!readlen)
|
||||||
|
break;
|
||||||
|
if (can_seek && sizeof(buf) == readlen) {
|
||||||
|
for (holeto = 0; holeto < readlen; holeto++)
|
||||||
|
if (buf[holeto])
|
||||||
|
break;
|
||||||
|
if (readlen == holeto) {
|
||||||
|
kept += holeto;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kept && lseek(fd, kept, SEEK_CUR) == (off_t) -1)
|
||||||
|
goto close_and_exit;
|
||||||
|
else
|
||||||
|
kept = 0;
|
||||||
|
wrote = write_in_full(fd, buf, readlen);
|
||||||
|
|
||||||
|
if (wrote != readlen)
|
||||||
|
goto close_and_exit;
|
||||||
|
}
|
||||||
|
if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||
|
||||||
|
write(fd, "", 1) != 1))
|
||||||
|
goto close_and_exit;
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
close_and_exit:
|
||||||
|
close_istream(st);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -12,4 +12,6 @@ extern struct git_istream *open_istream(const unsigned char *, enum object_type
|
|||||||
extern int close_istream(struct git_istream *);
|
extern int close_istream(struct git_istream *);
|
||||||
extern ssize_t read_istream(struct git_istream *, char *, size_t);
|
extern ssize_t read_istream(struct git_istream *, char *, size_t);
|
||||||
|
|
||||||
|
extern int stream_blob_to_fd(int fd, const unsigned char *, struct stream_filter *, int can_seek);
|
||||||
|
|
||||||
#endif /* STREAMING_H */
|
#endif /* STREAMING_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user