mirror of
https://github.com/git/git.git
synced 2024-11-24 02:17:02 +08:00
Merge branch 'ph/strbuf'
* ph/strbuf: (44 commits) Make read_patch_file work on a strbuf. strbuf_read_file enhancement, and use it. strbuf change: be sure ->buf is never ever NULL. double free in builtin-update-index.c Clean up stripspace a bit, use strbuf even more. Add strbuf_read_file(). rerere: Fix use of an empty strbuf.buf Small cache_tree_write refactor. Make builtin-rerere use of strbuf nicer and more efficient. Add strbuf_cmp. strbuf_setlen(): do not barf on setting length of an empty buffer to 0 sq_quote_argv and add_to_string rework with strbuf's. Full rework of quote_c_style and write_name_quoted. Rework unquote_c_style to work on a strbuf. strbuf API additions and enhancements. nfv?asprintf are broken without va_copy, workaround them. Fix the expansion pattern of the pseudo-static path buffer. builtin-for-each-ref.c::copy_name() - do not overstep the buffer. builtin-apply.c: fix a tiny leak introduced during xmemdupz() conversion. Use xmemdupz() in many places. ...
This commit is contained in:
commit
66d4035e10
@ -3,7 +3,6 @@
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "commit.h"
|
||||
#include "strbuf.h"
|
||||
#include "tar.h"
|
||||
#include "builtin.h"
|
||||
#include "archive.h"
|
||||
@ -79,19 +78,6 @@ static void write_trailer(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void strbuf_append_string(struct strbuf *sb, const char *s)
|
||||
{
|
||||
int slen = strlen(s);
|
||||
int total = sb->len + slen;
|
||||
if (total + 1 > sb->alloc) {
|
||||
sb->buf = xrealloc(sb->buf, total + 1);
|
||||
sb->alloc = total + 1;
|
||||
}
|
||||
memcpy(sb->buf + sb->len, s, slen);
|
||||
sb->len = total;
|
||||
sb->buf[total] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* pax extended header records have the format "%u %s=%s\n". %u contains
|
||||
* the size of the whole string (including the %u), the first %s is the
|
||||
@ -101,26 +87,17 @@ static void strbuf_append_string(struct strbuf *sb, const char *s)
|
||||
static void strbuf_append_ext_header(struct strbuf *sb, const char *keyword,
|
||||
const char *value, unsigned int valuelen)
|
||||
{
|
||||
char *p;
|
||||
int len, total, tmp;
|
||||
int len, tmp;
|
||||
|
||||
/* "%u %s=%s\n" */
|
||||
len = 1 + 1 + strlen(keyword) + 1 + valuelen + 1;
|
||||
for (tmp = len; tmp > 9; tmp /= 10)
|
||||
len++;
|
||||
|
||||
total = sb->len + len;
|
||||
if (total > sb->alloc) {
|
||||
sb->buf = xrealloc(sb->buf, total);
|
||||
sb->alloc = total;
|
||||
}
|
||||
|
||||
p = sb->buf;
|
||||
p += sprintf(p, "%u %s=", len, keyword);
|
||||
memcpy(p, value, valuelen);
|
||||
p += valuelen;
|
||||
*p = '\n';
|
||||
sb->len = total;
|
||||
strbuf_grow(sb, len);
|
||||
strbuf_addf(sb, "%u %s=", len, keyword);
|
||||
strbuf_add(sb, value, valuelen);
|
||||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
|
||||
static unsigned int ustar_header_chksum(const struct ustar_header *header)
|
||||
@ -154,8 +131,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
struct strbuf ext_header;
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
ext_header.buf = NULL;
|
||||
ext_header.len = ext_header.alloc = 0;
|
||||
strbuf_init(&ext_header, 0);
|
||||
|
||||
if (!sha1) {
|
||||
*header.typeflag = TYPEFLAG_GLOBAL_HEADER;
|
||||
@ -167,7 +143,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
|
||||
} else {
|
||||
if (verbose)
|
||||
fprintf(stderr, "%.*s\n", path->len, path->buf);
|
||||
fprintf(stderr, "%.*s\n", (int)path->len, path->buf);
|
||||
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
|
||||
*header.typeflag = TYPEFLAG_DIR;
|
||||
mode = (mode | 0777) & ~tar_umask;
|
||||
@ -226,8 +202,8 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
|
||||
if (ext_header.len > 0) {
|
||||
write_entry(sha1, NULL, 0, ext_header.buf, ext_header.len);
|
||||
free(ext_header.buf);
|
||||
}
|
||||
strbuf_release(&ext_header);
|
||||
write_blocked(&header, sizeof(header));
|
||||
if (S_ISREG(mode) && buffer && size > 0)
|
||||
write_blocked(buffer, size);
|
||||
@ -236,11 +212,11 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
static void write_global_extended_header(const unsigned char *sha1)
|
||||
{
|
||||
struct strbuf ext_header;
|
||||
ext_header.buf = NULL;
|
||||
ext_header.len = ext_header.alloc = 0;
|
||||
|
||||
strbuf_init(&ext_header, 0);
|
||||
strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
|
||||
write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len);
|
||||
free(ext_header.buf);
|
||||
strbuf_release(&ext_header);
|
||||
}
|
||||
|
||||
static int git_tar_config(const char *var, const char *value)
|
||||
@ -261,28 +237,17 @@ static int write_tar_entry(const unsigned char *sha1,
|
||||
const char *base, int baselen,
|
||||
const char *filename, unsigned mode, int stage)
|
||||
{
|
||||
static struct strbuf path;
|
||||
int filenamelen = strlen(filename);
|
||||
static struct strbuf path = STRBUF_INIT;
|
||||
void *buffer;
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
|
||||
if (!path.alloc) {
|
||||
path.buf = xmalloc(PATH_MAX);
|
||||
path.alloc = PATH_MAX;
|
||||
path.len = path.eof = 0;
|
||||
}
|
||||
if (path.alloc < baselen + filenamelen + 1) {
|
||||
free(path.buf);
|
||||
path.buf = xmalloc(baselen + filenamelen + 1);
|
||||
path.alloc = baselen + filenamelen + 1;
|
||||
}
|
||||
memcpy(path.buf, base, baselen);
|
||||
memcpy(path.buf + baselen, filename, filenamelen);
|
||||
path.len = baselen + filenamelen;
|
||||
path.buf[path.len] = '\0';
|
||||
strbuf_reset(&path);
|
||||
strbuf_grow(&path, PATH_MAX);
|
||||
strbuf_add(&path, base, baselen);
|
||||
strbuf_addstr(&path, filename);
|
||||
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
|
||||
strbuf_append_string(&path, "/");
|
||||
strbuf_addch(&path, '/');
|
||||
buffer = NULL;
|
||||
size = 0;
|
||||
} else {
|
||||
|
7
attr.c
7
attr.c
@ -160,12 +160,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
|
||||
else if (!equals)
|
||||
e->setto = ATTR__TRUE;
|
||||
else {
|
||||
char *value;
|
||||
int vallen = ep - equals;
|
||||
value = xmalloc(vallen);
|
||||
memcpy(value, equals+1, vallen-1);
|
||||
value[vallen-1] = 0;
|
||||
e->setto = value;
|
||||
e->setto = xmemdupz(equals + 1, ep - equals - 1);
|
||||
}
|
||||
e->attr = git_attr(cp, len);
|
||||
}
|
||||
|
@ -71,12 +71,8 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,
|
||||
baselen = common_prefix(pathspec);
|
||||
path = ".";
|
||||
base = "";
|
||||
if (baselen) {
|
||||
char *common = xmalloc(baselen + 1);
|
||||
memcpy(common, *pathspec, baselen);
|
||||
common[baselen] = 0;
|
||||
path = base = common;
|
||||
}
|
||||
if (baselen)
|
||||
path = base = xmemdupz(*pathspec, baselen);
|
||||
|
||||
/* Read the directory and prune it */
|
||||
read_directory(dir, path, base, baselen, pathspec);
|
||||
|
483
builtin-apply.c
483
builtin-apply.c
@ -163,15 +163,14 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c
|
||||
fputs(pre, output);
|
||||
if (patch->old_name && patch->new_name &&
|
||||
strcmp(patch->old_name, patch->new_name)) {
|
||||
write_name_quoted(NULL, 0, patch->old_name, 1, output);
|
||||
quote_c_style(patch->old_name, NULL, output, 0);
|
||||
fputs(" => ", output);
|
||||
write_name_quoted(NULL, 0, patch->new_name, 1, output);
|
||||
}
|
||||
else {
|
||||
quote_c_style(patch->new_name, NULL, output, 0);
|
||||
} else {
|
||||
const char *n = patch->new_name;
|
||||
if (!n)
|
||||
n = patch->old_name;
|
||||
write_name_quoted(NULL, 0, n, 1, output);
|
||||
quote_c_style(n, NULL, output, 0);
|
||||
}
|
||||
fputs(post, output);
|
||||
}
|
||||
@ -179,36 +178,18 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c
|
||||
#define CHUNKSIZE (8192)
|
||||
#define SLOP (16)
|
||||
|
||||
static void *read_patch_file(int fd, unsigned long *sizep)
|
||||
static void read_patch_file(struct strbuf *sb, int fd)
|
||||
{
|
||||
unsigned long size = 0, alloc = CHUNKSIZE;
|
||||
void *buffer = xmalloc(alloc);
|
||||
|
||||
for (;;) {
|
||||
ssize_t nr = alloc - size;
|
||||
if (nr < 1024) {
|
||||
alloc += CHUNKSIZE;
|
||||
buffer = xrealloc(buffer, alloc);
|
||||
nr = alloc - size;
|
||||
}
|
||||
nr = xread(fd, (char *) buffer + size, nr);
|
||||
if (!nr)
|
||||
break;
|
||||
if (nr < 0)
|
||||
die("git-apply: read returned %s", strerror(errno));
|
||||
size += nr;
|
||||
}
|
||||
*sizep = size;
|
||||
if (strbuf_read(sb, fd, 0) < 0)
|
||||
die("git-apply: read returned %s", strerror(errno));
|
||||
|
||||
/*
|
||||
* Make sure that we have some slop in the buffer
|
||||
* so that we can do speculative "memcmp" etc, and
|
||||
* see to it that it is NUL-filled.
|
||||
*/
|
||||
if (alloc < size + SLOP)
|
||||
buffer = xrealloc(buffer, size + SLOP);
|
||||
memset((char *) buffer + size, 0, SLOP);
|
||||
return buffer;
|
||||
strbuf_grow(sb, SLOP);
|
||||
memset(sb->buf + sb->len, 0, SLOP);
|
||||
}
|
||||
|
||||
static unsigned long linelen(const char *buffer, unsigned long size)
|
||||
@ -244,35 +225,33 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||
{
|
||||
int len;
|
||||
const char *start = line;
|
||||
char *name;
|
||||
|
||||
if (*line == '"') {
|
||||
struct strbuf name;
|
||||
|
||||
/* Proposed "new-style" GNU patch/diff format; see
|
||||
* http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
|
||||
*/
|
||||
name = unquote_c_style(line, NULL);
|
||||
if (name) {
|
||||
char *cp = name;
|
||||
while (p_value) {
|
||||
strbuf_init(&name, 0);
|
||||
if (!unquote_c_style(&name, line, NULL)) {
|
||||
char *cp;
|
||||
|
||||
for (cp = name.buf; p_value; p_value--) {
|
||||
cp = strchr(cp, '/');
|
||||
if (!cp)
|
||||
break;
|
||||
cp++;
|
||||
p_value--;
|
||||
}
|
||||
if (cp) {
|
||||
/* name can later be freed, so we need
|
||||
* to memmove, not just return cp
|
||||
*/
|
||||
memmove(name, cp, strlen(cp) + 1);
|
||||
strbuf_remove(&name, 0, cp - name.buf);
|
||||
free(def);
|
||||
return name;
|
||||
}
|
||||
else {
|
||||
free(name);
|
||||
name = NULL;
|
||||
return strbuf_detach(&name, NULL);
|
||||
}
|
||||
}
|
||||
strbuf_release(&name);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@ -304,13 +283,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||
int deflen = strlen(def);
|
||||
if (deflen < len && !strncmp(start, def, deflen))
|
||||
return def;
|
||||
free(def);
|
||||
}
|
||||
|
||||
name = xmalloc(len + 1);
|
||||
memcpy(name, start, len);
|
||||
name[len] = 0;
|
||||
free(def);
|
||||
return name;
|
||||
return xmemdupz(start, len);
|
||||
}
|
||||
|
||||
static int count_slashes(const char *cp)
|
||||
@ -583,29 +559,30 @@ static const char *stop_at_slash(const char *line, int llen)
|
||||
*/
|
||||
static char *git_header_name(char *line, int llen)
|
||||
{
|
||||
int len;
|
||||
const char *name;
|
||||
const char *second = NULL;
|
||||
size_t len;
|
||||
|
||||
line += strlen("diff --git ");
|
||||
llen -= strlen("diff --git ");
|
||||
|
||||
if (*line == '"') {
|
||||
const char *cp;
|
||||
char *first = unquote_c_style(line, &second);
|
||||
if (!first)
|
||||
return NULL;
|
||||
struct strbuf first;
|
||||
struct strbuf sp;
|
||||
|
||||
strbuf_init(&first, 0);
|
||||
strbuf_init(&sp, 0);
|
||||
|
||||
if (unquote_c_style(&first, line, &second))
|
||||
goto free_and_fail1;
|
||||
|
||||
/* advance to the first slash */
|
||||
cp = stop_at_slash(first, strlen(first));
|
||||
if (!cp || cp == first) {
|
||||
/* we do not accept absolute paths */
|
||||
free_first_and_fail:
|
||||
free(first);
|
||||
return NULL;
|
||||
}
|
||||
len = strlen(cp+1);
|
||||
memmove(first, cp+1, len+1); /* including NUL */
|
||||
cp = stop_at_slash(first.buf, first.len);
|
||||
/* we do not accept absolute paths */
|
||||
if (!cp || cp == first.buf)
|
||||
goto free_and_fail1;
|
||||
strbuf_remove(&first, 0, cp + 1 - first.buf);
|
||||
|
||||
/* second points at one past closing dq of name.
|
||||
* find the second name.
|
||||
@ -614,40 +591,40 @@ static char *git_header_name(char *line, int llen)
|
||||
second++;
|
||||
|
||||
if (line + llen <= second)
|
||||
goto free_first_and_fail;
|
||||
goto free_and_fail1;
|
||||
if (*second == '"') {
|
||||
char *sp = unquote_c_style(second, NULL);
|
||||
if (!sp)
|
||||
goto free_first_and_fail;
|
||||
cp = stop_at_slash(sp, strlen(sp));
|
||||
if (!cp || cp == sp) {
|
||||
free_both_and_fail:
|
||||
free(sp);
|
||||
goto free_first_and_fail;
|
||||
}
|
||||
if (unquote_c_style(&sp, second, NULL))
|
||||
goto free_and_fail1;
|
||||
cp = stop_at_slash(sp.buf, sp.len);
|
||||
if (!cp || cp == sp.buf)
|
||||
goto free_and_fail1;
|
||||
/* They must match, otherwise ignore */
|
||||
if (strcmp(cp+1, first))
|
||||
goto free_both_and_fail;
|
||||
free(sp);
|
||||
return first;
|
||||
if (strcmp(cp + 1, first.buf))
|
||||
goto free_and_fail1;
|
||||
strbuf_release(&sp);
|
||||
return strbuf_detach(&first, NULL);
|
||||
}
|
||||
|
||||
/* unquoted second */
|
||||
cp = stop_at_slash(second, line + llen - second);
|
||||
if (!cp || cp == second)
|
||||
goto free_first_and_fail;
|
||||
goto free_and_fail1;
|
||||
cp++;
|
||||
if (line + llen - cp != len + 1 ||
|
||||
memcmp(first, cp, len))
|
||||
goto free_first_and_fail;
|
||||
return first;
|
||||
if (line + llen - cp != first.len + 1 ||
|
||||
memcmp(first.buf, cp, first.len))
|
||||
goto free_and_fail1;
|
||||
return strbuf_detach(&first, NULL);
|
||||
|
||||
free_and_fail1:
|
||||
strbuf_release(&first);
|
||||
strbuf_release(&sp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* unquoted first name */
|
||||
name = stop_at_slash(line, llen);
|
||||
if (!name || name == line)
|
||||
return NULL;
|
||||
|
||||
name++;
|
||||
|
||||
/* since the first name is unquoted, a dq if exists must be
|
||||
@ -655,28 +632,30 @@ static char *git_header_name(char *line, int llen)
|
||||
*/
|
||||
for (second = name; second < line + llen; second++) {
|
||||
if (*second == '"') {
|
||||
const char *cp = second;
|
||||
struct strbuf sp;
|
||||
const char *np;
|
||||
char *sp = unquote_c_style(second, NULL);
|
||||
|
||||
if (!sp)
|
||||
return NULL;
|
||||
np = stop_at_slash(sp, strlen(sp));
|
||||
if (!np || np == sp) {
|
||||
free_second_and_fail:
|
||||
free(sp);
|
||||
return NULL;
|
||||
}
|
||||
strbuf_init(&sp, 0);
|
||||
if (unquote_c_style(&sp, second, NULL))
|
||||
goto free_and_fail2;
|
||||
|
||||
np = stop_at_slash(sp.buf, sp.len);
|
||||
if (!np || np == sp.buf)
|
||||
goto free_and_fail2;
|
||||
np++;
|
||||
len = strlen(np);
|
||||
if (len < cp - name &&
|
||||
|
||||
len = sp.buf + sp.len - np;
|
||||
if (len < second - name &&
|
||||
!strncmp(np, name, len) &&
|
||||
isspace(name[len])) {
|
||||
/* Good */
|
||||
memmove(sp, np, len + 1);
|
||||
return sp;
|
||||
strbuf_remove(&sp, 0, np - sp.buf);
|
||||
return strbuf_detach(&sp, NULL);
|
||||
}
|
||||
goto free_second_and_fail;
|
||||
|
||||
free_and_fail2:
|
||||
strbuf_release(&sp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,10 +679,7 @@ static char *git_header_name(char *line, int llen)
|
||||
break;
|
||||
}
|
||||
if (second[len] == '\n' && !memcmp(name, second, len)) {
|
||||
char *ret = xmalloc(len + 1);
|
||||
memcpy(ret, name, len);
|
||||
ret[len] = 0;
|
||||
return ret;
|
||||
return xmemdupz(name, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1397,96 +1373,66 @@ static const char minuses[]= "--------------------------------------------------
|
||||
|
||||
static void show_stats(struct patch *patch)
|
||||
{
|
||||
const char *prefix = "";
|
||||
char *name = patch->new_name;
|
||||
char *qname = NULL;
|
||||
int len, max, add, del, total;
|
||||
struct strbuf qname;
|
||||
char *cp = patch->new_name ? patch->new_name : patch->old_name;
|
||||
int max, add, del;
|
||||
|
||||
if (!name)
|
||||
name = patch->old_name;
|
||||
|
||||
if (0 < (len = quote_c_style(name, NULL, NULL, 0))) {
|
||||
qname = xmalloc(len + 1);
|
||||
quote_c_style(name, qname, NULL, 0);
|
||||
name = qname;
|
||||
}
|
||||
strbuf_init(&qname, 0);
|
||||
quote_c_style(cp, &qname, NULL, 0);
|
||||
|
||||
/*
|
||||
* "scale" the filename
|
||||
*/
|
||||
len = strlen(name);
|
||||
max = max_len;
|
||||
if (max > 50)
|
||||
max = 50;
|
||||
if (len > max) {
|
||||
char *slash;
|
||||
prefix = "...";
|
||||
max -= 3;
|
||||
name += len - max;
|
||||
slash = strchr(name, '/');
|
||||
if (slash)
|
||||
name = slash;
|
||||
|
||||
if (qname.len > max) {
|
||||
cp = strchr(qname.buf + qname.len + 3 - max, '/');
|
||||
if (!cp)
|
||||
cp = qname.buf + qname.len + 3 - max;
|
||||
strbuf_splice(&qname, 0, cp - qname.buf, "...", 3);
|
||||
}
|
||||
len = max;
|
||||
|
||||
if (patch->is_binary) {
|
||||
printf(" %-*s | Bin\n", max, qname.buf);
|
||||
strbuf_release(&qname);
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" %-*s |", max, qname.buf);
|
||||
strbuf_release(&qname);
|
||||
|
||||
/*
|
||||
* scale the add/delete
|
||||
*/
|
||||
max = max_change;
|
||||
if (max + len > 70)
|
||||
max = 70 - len;
|
||||
|
||||
max = max + max_change > 70 ? 70 - max : max_change;
|
||||
add = patch->lines_added;
|
||||
del = patch->lines_deleted;
|
||||
total = add + del;
|
||||
|
||||
if (max_change > 0) {
|
||||
total = (total * max + max_change / 2) / max_change;
|
||||
int total = ((add + del) * max + max_change / 2) / max_change;
|
||||
add = (add * max + max_change / 2) / max_change;
|
||||
del = total - add;
|
||||
}
|
||||
if (patch->is_binary)
|
||||
printf(" %s%-*s | Bin\n", prefix, len, name);
|
||||
else
|
||||
printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
|
||||
len, name, patch->lines_added + patch->lines_deleted,
|
||||
add, pluses, del, minuses);
|
||||
free(qname);
|
||||
printf("%5d %.*s%.*s\n", patch->lines_added + patch->lines_deleted,
|
||||
add, pluses, del, minuses);
|
||||
}
|
||||
|
||||
static int read_old_data(struct stat *st, const char *path, char **buf_p, unsigned long *alloc_p, unsigned long *size_p)
|
||||
static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
|
||||
{
|
||||
int fd;
|
||||
unsigned long got;
|
||||
unsigned long nsize;
|
||||
char *nbuf;
|
||||
unsigned long size = *size_p;
|
||||
char *buf = *buf_p;
|
||||
|
||||
switch (st->st_mode & S_IFMT) {
|
||||
case S_IFLNK:
|
||||
return readlink(path, buf, size) != size;
|
||||
strbuf_grow(buf, st->st_size);
|
||||
if (readlink(path, buf->buf, st->st_size) != st->st_size)
|
||||
return -1;
|
||||
strbuf_setlen(buf, st->st_size);
|
||||
return 0;
|
||||
case S_IFREG:
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return error("unable to open %s", path);
|
||||
got = 0;
|
||||
for (;;) {
|
||||
ssize_t ret = xread(fd, buf + got, size - got);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
got += ret;
|
||||
}
|
||||
close(fd);
|
||||
nsize = got;
|
||||
nbuf = convert_to_git(path, buf, &nsize);
|
||||
if (nbuf) {
|
||||
free(buf);
|
||||
*buf_p = nbuf;
|
||||
*alloc_p = nsize;
|
||||
*size_p = nsize;
|
||||
}
|
||||
return got != size;
|
||||
if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
|
||||
return error("unable to open or read %s", path);
|
||||
convert_to_git(path, buf->buf, buf->len, buf);
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -1591,12 +1537,6 @@ static void remove_last_line(const char **rbuf, int *rsize)
|
||||
*rsize = offset + 1;
|
||||
}
|
||||
|
||||
struct buffer_desc {
|
||||
char *buffer;
|
||||
unsigned long size;
|
||||
unsigned long alloc;
|
||||
};
|
||||
|
||||
static int apply_line(char *output, const char *patch, int plen)
|
||||
{
|
||||
/* plen is number of bytes to be copied from patch,
|
||||
@ -1673,10 +1613,9 @@ static int apply_line(char *output, const char *patch, int plen)
|
||||
return output + plen - buf;
|
||||
}
|
||||
|
||||
static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, int inaccurate_eof)
|
||||
static int apply_one_fragment(struct strbuf *buf, struct fragment *frag, int inaccurate_eof)
|
||||
{
|
||||
int match_beginning, match_end;
|
||||
char *buf = desc->buffer;
|
||||
const char *patch = frag->patch;
|
||||
int offset, size = frag->size;
|
||||
char *old = xmalloc(size);
|
||||
@ -1787,24 +1726,17 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i
|
||||
lines = 0;
|
||||
pos = frag->newpos;
|
||||
for (;;) {
|
||||
offset = find_offset(buf, desc->size,
|
||||
offset = find_offset(buf->buf, buf->len,
|
||||
oldlines, oldsize, pos, &lines);
|
||||
if (match_end && offset + oldsize != desc->size)
|
||||
if (match_end && offset + oldsize != buf->len)
|
||||
offset = -1;
|
||||
if (match_beginning && offset)
|
||||
offset = -1;
|
||||
if (offset >= 0) {
|
||||
int diff;
|
||||
unsigned long size, alloc;
|
||||
|
||||
if (new_whitespace == strip_whitespace &&
|
||||
(desc->size - oldsize - offset == 0)) /* end of file? */
|
||||
(buf->len - oldsize - offset == 0)) /* end of file? */
|
||||
newsize -= new_blank_lines_at_end;
|
||||
|
||||
diff = newsize - oldsize;
|
||||
size = desc->size + diff;
|
||||
alloc = desc->alloc;
|
||||
|
||||
/* Warn if it was necessary to reduce the number
|
||||
* of context lines.
|
||||
*/
|
||||
@ -1814,19 +1746,8 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i
|
||||
" to apply fragment at %d\n",
|
||||
leading, trailing, pos + lines);
|
||||
|
||||
if (size > alloc) {
|
||||
alloc = size + 8192;
|
||||
desc->alloc = alloc;
|
||||
buf = xrealloc(buf, alloc);
|
||||
desc->buffer = buf;
|
||||
}
|
||||
desc->size = size;
|
||||
memmove(buf + offset + newsize,
|
||||
buf + offset + oldsize,
|
||||
size - offset - newsize);
|
||||
memcpy(buf + offset, newlines, newsize);
|
||||
strbuf_splice(buf, offset, oldsize, newlines, newsize);
|
||||
offset = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1862,12 +1783,11 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch)
|
||||
static int apply_binary_fragment(struct strbuf *buf, struct patch *patch)
|
||||
{
|
||||
unsigned long dst_size;
|
||||
struct fragment *fragment = patch->fragments;
|
||||
void *data;
|
||||
void *result;
|
||||
unsigned long len;
|
||||
void *dst;
|
||||
|
||||
/* Binary patch is irreversible without the optional second hunk */
|
||||
if (apply_in_reverse) {
|
||||
@ -1878,29 +1798,24 @@ static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch)
|
||||
? patch->new_name : patch->old_name);
|
||||
fragment = fragment->next;
|
||||
}
|
||||
data = (void*) fragment->patch;
|
||||
switch (fragment->binary_patch_method) {
|
||||
case BINARY_DELTA_DEFLATED:
|
||||
result = patch_delta(desc->buffer, desc->size,
|
||||
data,
|
||||
fragment->size,
|
||||
&dst_size);
|
||||
free(desc->buffer);
|
||||
desc->buffer = result;
|
||||
break;
|
||||
dst = patch_delta(buf->buf, buf->len, fragment->patch,
|
||||
fragment->size, &len);
|
||||
if (!dst)
|
||||
return -1;
|
||||
/* XXX patch_delta NUL-terminates */
|
||||
strbuf_attach(buf, dst, len, len + 1);
|
||||
return 0;
|
||||
case BINARY_LITERAL_DEFLATED:
|
||||
free(desc->buffer);
|
||||
desc->buffer = data;
|
||||
dst_size = fragment->size;
|
||||
break;
|
||||
strbuf_reset(buf);
|
||||
strbuf_add(buf, fragment->patch, fragment->size);
|
||||
return 0;
|
||||
}
|
||||
if (!desc->buffer)
|
||||
return -1;
|
||||
desc->size = desc->alloc = dst_size;
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int apply_binary(struct buffer_desc *desc, struct patch *patch)
|
||||
static int apply_binary(struct strbuf *buf, struct patch *patch)
|
||||
{
|
||||
const char *name = patch->old_name ? patch->old_name : patch->new_name;
|
||||
unsigned char sha1[20];
|
||||
@ -1919,7 +1834,7 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch)
|
||||
/* See if the old one matches what the patch
|
||||
* applies to.
|
||||
*/
|
||||
hash_sha1_file(desc->buffer, desc->size, blob_type, sha1);
|
||||
hash_sha1_file(buf->buf, buf->len, blob_type, sha1);
|
||||
if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix))
|
||||
return error("the patch applies to '%s' (%s), "
|
||||
"which does not match the "
|
||||
@ -1928,16 +1843,14 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch)
|
||||
}
|
||||
else {
|
||||
/* Otherwise, the old one must be empty. */
|
||||
if (desc->size)
|
||||
if (buf->len)
|
||||
return error("the patch applies to an empty "
|
||||
"'%s' but it is not empty", name);
|
||||
}
|
||||
|
||||
get_sha1_hex(patch->new_sha1_prefix, sha1);
|
||||
if (is_null_sha1(sha1)) {
|
||||
free(desc->buffer);
|
||||
desc->alloc = desc->size = 0;
|
||||
desc->buffer = NULL;
|
||||
strbuf_release(buf);
|
||||
return 0; /* deletion patch */
|
||||
}
|
||||
|
||||
@ -1945,43 +1858,44 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch)
|
||||
/* We already have the postimage */
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
char *result;
|
||||
|
||||
free(desc->buffer);
|
||||
desc->buffer = read_sha1_file(sha1, &type, &size);
|
||||
if (!desc->buffer)
|
||||
result = read_sha1_file(sha1, &type, &size);
|
||||
if (!result)
|
||||
return error("the necessary postimage %s for "
|
||||
"'%s' cannot be read",
|
||||
patch->new_sha1_prefix, name);
|
||||
desc->alloc = desc->size = size;
|
||||
}
|
||||
else {
|
||||
/* We have verified desc matches the preimage;
|
||||
/* XXX read_sha1_file NUL-terminates */
|
||||
strbuf_attach(buf, result, size, size + 1);
|
||||
} else {
|
||||
/* We have verified buf matches the preimage;
|
||||
* apply the patch data to it, which is stored
|
||||
* in the patch->fragments->{patch,size}.
|
||||
*/
|
||||
if (apply_binary_fragment(desc, patch))
|
||||
if (apply_binary_fragment(buf, patch))
|
||||
return error("binary patch does not apply to '%s'",
|
||||
name);
|
||||
|
||||
/* verify that the result matches */
|
||||
hash_sha1_file(desc->buffer, desc->size, blob_type, sha1);
|
||||
hash_sha1_file(buf->buf, buf->len, blob_type, sha1);
|
||||
if (strcmp(sha1_to_hex(sha1), patch->new_sha1_prefix))
|
||||
return error("binary patch to '%s' creates incorrect result (expecting %s, got %s)", name, patch->new_sha1_prefix, sha1_to_hex(sha1));
|
||||
return error("binary patch to '%s' creates incorrect result (expecting %s, got %s)",
|
||||
name, patch->new_sha1_prefix, sha1_to_hex(sha1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
|
||||
static int apply_fragments(struct strbuf *buf, struct patch *patch)
|
||||
{
|
||||
struct fragment *frag = patch->fragments;
|
||||
const char *name = patch->old_name ? patch->old_name : patch->new_name;
|
||||
|
||||
if (patch->is_binary)
|
||||
return apply_binary(desc, patch);
|
||||
return apply_binary(buf, patch);
|
||||
|
||||
while (frag) {
|
||||
if (apply_one_fragment(desc, frag, patch->inaccurate_eof)) {
|
||||
if (apply_one_fragment(buf, frag, patch->inaccurate_eof)) {
|
||||
error("patch failed: %s:%ld", name, frag->oldpos);
|
||||
if (!apply_with_reject)
|
||||
return -1;
|
||||
@ -1992,76 +1906,56 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_file_or_gitlink(struct cache_entry *ce, char **buf_p,
|
||||
unsigned long *size_p)
|
||||
static int read_file_or_gitlink(struct cache_entry *ce, struct strbuf *buf)
|
||||
{
|
||||
if (!ce)
|
||||
return 0;
|
||||
|
||||
if (S_ISGITLINK(ntohl(ce->ce_mode))) {
|
||||
*buf_p = xmalloc(100);
|
||||
*size_p = snprintf(*buf_p, 100,
|
||||
"Subproject commit %s\n", sha1_to_hex(ce->sha1));
|
||||
strbuf_grow(buf, 100);
|
||||
strbuf_addf(buf, "Subproject commit %s\n", sha1_to_hex(ce->sha1));
|
||||
} else {
|
||||
enum object_type type;
|
||||
*buf_p = read_sha1_file(ce->sha1, &type, size_p);
|
||||
if (!*buf_p)
|
||||
unsigned long sz;
|
||||
char *result;
|
||||
|
||||
result = read_sha1_file(ce->sha1, &type, &sz);
|
||||
if (!result)
|
||||
return -1;
|
||||
/* XXX read_sha1_file NUL-terminates */
|
||||
strbuf_attach(buf, result, sz, sz + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
|
||||
{
|
||||
char *buf;
|
||||
unsigned long size, alloc;
|
||||
struct buffer_desc desc;
|
||||
struct strbuf buf;
|
||||
|
||||
size = 0;
|
||||
alloc = 0;
|
||||
buf = NULL;
|
||||
strbuf_init(&buf, 0);
|
||||
if (cached) {
|
||||
if (read_file_or_gitlink(ce, &buf, &size))
|
||||
if (read_file_or_gitlink(ce, &buf))
|
||||
return error("read of %s failed", patch->old_name);
|
||||
alloc = size;
|
||||
} else if (patch->old_name) {
|
||||
if (S_ISGITLINK(patch->old_mode)) {
|
||||
if (ce)
|
||||
read_file_or_gitlink(ce, &buf, &size);
|
||||
else {
|
||||
if (ce) {
|
||||
read_file_or_gitlink(ce, &buf);
|
||||
} else {
|
||||
/*
|
||||
* There is no way to apply subproject
|
||||
* patch without looking at the index.
|
||||
*/
|
||||
patch->fragments = NULL;
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
size = xsize_t(st->st_size);
|
||||
alloc = size + 8192;
|
||||
buf = xmalloc(alloc);
|
||||
if (read_old_data(st, patch->old_name,
|
||||
&buf, &alloc, &size))
|
||||
return error("read of %s failed",
|
||||
patch->old_name);
|
||||
} else {
|
||||
if (read_old_data(st, patch->old_name, &buf))
|
||||
return error("read of %s failed", patch->old_name);
|
||||
}
|
||||
}
|
||||
|
||||
desc.size = size;
|
||||
desc.alloc = alloc;
|
||||
desc.buffer = buf;
|
||||
|
||||
if (apply_fragments(&desc, patch) < 0)
|
||||
if (apply_fragments(&buf, patch) < 0)
|
||||
return -1; /* note with --reject this succeeds. */
|
||||
|
||||
/* NUL terminate the result */
|
||||
if (desc.alloc <= desc.size)
|
||||
desc.buffer = xrealloc(desc.buffer, desc.size + 1);
|
||||
desc.buffer[desc.size] = 0;
|
||||
|
||||
patch->result = desc.buffer;
|
||||
patch->resultsize = desc.size;
|
||||
patch->result = strbuf_detach(&buf, &patch->resultsize);
|
||||
|
||||
if (0 < patch->is_delete && patch->resultsize)
|
||||
return error("removal patch leaves file contents");
|
||||
@ -2315,13 +2209,8 @@ static void numstat_patch_list(struct patch *patch)
|
||||
if (patch->is_binary)
|
||||
printf("-\t-\t");
|
||||
else
|
||||
printf("%d\t%d\t",
|
||||
patch->lines_added, patch->lines_deleted);
|
||||
if (line_termination && quote_c_style(name, NULL, NULL, 0))
|
||||
quote_c_style(name, NULL, stdout, 0);
|
||||
else
|
||||
fputs(name, stdout);
|
||||
putchar(line_termination);
|
||||
printf("%d\t%d\t", patch->lines_added, patch->lines_deleted);
|
||||
write_name_quoted(name, stdout, line_termination);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2486,7 +2375,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
|
||||
static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
|
||||
{
|
||||
int fd;
|
||||
char *nbuf;
|
||||
struct strbuf nbuf;
|
||||
|
||||
if (S_ISGITLINK(mode)) {
|
||||
struct stat st;
|
||||
@ -2505,23 +2394,16 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
nbuf = convert_to_working_tree(path, buf, &size);
|
||||
if (nbuf)
|
||||
buf = nbuf;
|
||||
|
||||
while (size) {
|
||||
int written = xwrite(fd, buf, size);
|
||||
if (written < 0)
|
||||
die("writing file %s: %s", path, strerror(errno));
|
||||
if (!written)
|
||||
die("out of space writing file %s", path);
|
||||
buf += written;
|
||||
size -= written;
|
||||
strbuf_init(&nbuf, 0);
|
||||
if (convert_to_working_tree(path, buf, size, &nbuf)) {
|
||||
size = nbuf.len;
|
||||
buf = nbuf.buf;
|
||||
}
|
||||
write_or_die(fd, buf, size);
|
||||
strbuf_release(&nbuf);
|
||||
|
||||
if (close(fd) < 0)
|
||||
die("closing file %s: %s", path, strerror(errno));
|
||||
if (nbuf)
|
||||
free(nbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2754,22 +2636,22 @@ static void prefix_patches(struct patch *p)
|
||||
|
||||
static int apply_patch(int fd, const char *filename, int inaccurate_eof)
|
||||
{
|
||||
unsigned long offset, size;
|
||||
char *buffer = read_patch_file(fd, &size);
|
||||
size_t offset;
|
||||
struct strbuf buf;
|
||||
struct patch *list = NULL, **listp = &list;
|
||||
int skipped_patch = 0;
|
||||
|
||||
strbuf_init(&buf, 0);
|
||||
patch_input_file = filename;
|
||||
if (!buffer)
|
||||
return -1;
|
||||
read_patch_file(&buf, fd);
|
||||
offset = 0;
|
||||
while (size > 0) {
|
||||
while (offset < buf.len) {
|
||||
struct patch *patch;
|
||||
int nr;
|
||||
|
||||
patch = xcalloc(1, sizeof(*patch));
|
||||
patch->inaccurate_eof = inaccurate_eof;
|
||||
nr = parse_chunk(buffer + offset, size, patch);
|
||||
nr = parse_chunk(buf.buf + offset, buf.len, patch);
|
||||
if (nr < 0)
|
||||
break;
|
||||
if (apply_in_reverse)
|
||||
@ -2787,7 +2669,6 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
|
||||
skipped_patch++;
|
||||
}
|
||||
offset += nr;
|
||||
size -= nr;
|
||||
}
|
||||
|
||||
if (whitespace_error && (new_whitespace == error_on_whitespace))
|
||||
@ -2822,7 +2703,7 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
|
||||
if (summary)
|
||||
summary_patch_list(list);
|
||||
|
||||
free(buffer);
|
||||
strbuf_release(&buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -81,95 +81,79 @@ static int run_remote_archiver(const char *remote, int argc,
|
||||
return !!rv;
|
||||
}
|
||||
|
||||
static void *format_subst(const struct commit *commit, const char *format,
|
||||
unsigned long *sizep)
|
||||
static void format_subst(const struct commit *commit,
|
||||
const char *src, size_t len,
|
||||
struct strbuf *buf)
|
||||
{
|
||||
unsigned long len = *sizep, result_len = 0;
|
||||
const char *a = format;
|
||||
char *result = NULL;
|
||||
char *to_free = NULL;
|
||||
struct strbuf fmt;
|
||||
|
||||
if (src == buf->buf)
|
||||
to_free = strbuf_detach(buf, NULL);
|
||||
strbuf_init(&fmt, 0);
|
||||
for (;;) {
|
||||
const char *b, *c;
|
||||
char *fmt, *formatted = NULL;
|
||||
unsigned long a_len, fmt_len, formatted_len, allocated = 0;
|
||||
|
||||
b = memmem(a, len, "$Format:", 8);
|
||||
if (!b || a + len < b + 9)
|
||||
b = memmem(src, len, "$Format:", 8);
|
||||
if (!b || src + len < b + 9)
|
||||
break;
|
||||
c = memchr(b + 8, '$', len - 8);
|
||||
if (!c)
|
||||
break;
|
||||
|
||||
a_len = b - a;
|
||||
fmt_len = c - b - 8;
|
||||
fmt = xmalloc(fmt_len + 1);
|
||||
memcpy(fmt, b + 8, fmt_len);
|
||||
fmt[fmt_len] = '\0';
|
||||
strbuf_reset(&fmt);
|
||||
strbuf_add(&fmt, b + 8, c - b - 8);
|
||||
|
||||
formatted_len = format_commit_message(commit, fmt, &formatted,
|
||||
&allocated);
|
||||
free(fmt);
|
||||
result = xrealloc(result, result_len + a_len + formatted_len);
|
||||
memcpy(result + result_len, a, a_len);
|
||||
memcpy(result + result_len + a_len, formatted, formatted_len);
|
||||
result_len += a_len + formatted_len;
|
||||
len -= c + 1 - a;
|
||||
a = c + 1;
|
||||
strbuf_add(buf, src, b - src);
|
||||
format_commit_message(commit, fmt.buf, buf);
|
||||
len -= c + 1 - src;
|
||||
src = c + 1;
|
||||
}
|
||||
|
||||
if (result && len) {
|
||||
result = xrealloc(result, result_len + len);
|
||||
memcpy(result + result_len, a, len);
|
||||
result_len += len;
|
||||
}
|
||||
|
||||
*sizep = result_len;
|
||||
|
||||
return result;
|
||||
strbuf_add(buf, src, len);
|
||||
strbuf_release(&fmt);
|
||||
free(to_free);
|
||||
}
|
||||
|
||||
static void *convert_to_archive(const char *path,
|
||||
const void *src, unsigned long *sizep,
|
||||
const struct commit *commit)
|
||||
static int convert_to_archive(const char *path,
|
||||
const void *src, size_t len,
|
||||
struct strbuf *buf,
|
||||
const struct commit *commit)
|
||||
{
|
||||
static struct git_attr *attr_export_subst;
|
||||
struct git_attr_check check[1];
|
||||
|
||||
if (!commit)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
if (!attr_export_subst)
|
||||
attr_export_subst = git_attr("export-subst", 12);
|
||||
if (!attr_export_subst)
|
||||
attr_export_subst = git_attr("export-subst", 12);
|
||||
|
||||
check[0].attr = attr_export_subst;
|
||||
if (git_checkattr(path, ARRAY_SIZE(check), check))
|
||||
return NULL;
|
||||
return 0;
|
||||
if (!ATTR_TRUE(check[0].value))
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
return format_subst(commit, src, sizep);
|
||||
format_subst(commit, src, len, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
|
||||
unsigned int mode, enum object_type *type,
|
||||
unsigned long *size,
|
||||
unsigned long *sizep,
|
||||
const struct commit *commit)
|
||||
{
|
||||
void *buffer, *converted;
|
||||
void *buffer;
|
||||
|
||||
buffer = read_sha1_file(sha1, type, size);
|
||||
buffer = read_sha1_file(sha1, type, sizep);
|
||||
if (buffer && S_ISREG(mode)) {
|
||||
converted = convert_to_working_tree(path, buffer, size);
|
||||
if (converted) {
|
||||
free(buffer);
|
||||
buffer = converted;
|
||||
}
|
||||
struct strbuf buf;
|
||||
|
||||
converted = convert_to_archive(path, buffer, size, commit);
|
||||
if (converted) {
|
||||
free(buffer);
|
||||
buffer = converted;
|
||||
}
|
||||
strbuf_init(&buf, 0);
|
||||
strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
|
||||
convert_to_working_tree(path, buf.buf, buf.len, &buf);
|
||||
convert_to_archive(path, buf.buf, buf.len, &buf, commit);
|
||||
buffer = strbuf_detach(&buf, sizep);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
|
@ -1430,8 +1430,7 @@ static void get_commit_info(struct commit *commit,
|
||||
static void write_filename_info(const char *path)
|
||||
{
|
||||
printf("filename ");
|
||||
write_name_quoted(NULL, 0, path, 1, stdout);
|
||||
putchar('\n');
|
||||
write_name_quoted(path, stdout, '\n');
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2001,11 +2000,9 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
|
||||
struct commit *commit;
|
||||
struct origin *origin;
|
||||
unsigned char head_sha1[20];
|
||||
char *buf;
|
||||
struct strbuf buf;
|
||||
const char *ident;
|
||||
int fd;
|
||||
time_t now;
|
||||
unsigned long fin_size;
|
||||
int size, len;
|
||||
struct cache_entry *ce;
|
||||
unsigned mode;
|
||||
@ -2023,9 +2020,11 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
|
||||
|
||||
origin = make_origin(commit, path);
|
||||
|
||||
strbuf_init(&buf, 0);
|
||||
if (!contents_from || strcmp("-", contents_from)) {
|
||||
struct stat st;
|
||||
const char *read_from;
|
||||
unsigned long fin_size;
|
||||
|
||||
if (contents_from) {
|
||||
if (stat(contents_from, &st) < 0)
|
||||
@ -2038,19 +2037,16 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
|
||||
read_from = path;
|
||||
}
|
||||
fin_size = xsize_t(st.st_size);
|
||||
buf = xmalloc(fin_size+1);
|
||||
mode = canon_mode(st.st_mode);
|
||||
switch (st.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
fd = open(read_from, O_RDONLY);
|
||||
if (fd < 0)
|
||||
die("cannot open %s", read_from);
|
||||
if (read_in_full(fd, buf, fin_size) != fin_size)
|
||||
die("cannot read %s", read_from);
|
||||
if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
|
||||
die("cannot open or read %s", read_from);
|
||||
break;
|
||||
case S_IFLNK:
|
||||
if (readlink(read_from, buf, fin_size+1) != fin_size)
|
||||
if (readlink(read_from, buf.buf, buf.alloc) != fin_size)
|
||||
die("cannot readlink %s", read_from);
|
||||
buf.len = fin_size;
|
||||
break;
|
||||
default:
|
||||
die("unsupported file type %s", read_from);
|
||||
@ -2059,26 +2055,13 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
|
||||
else {
|
||||
/* Reading from stdin */
|
||||
contents_from = "standard input";
|
||||
buf = NULL;
|
||||
fin_size = 0;
|
||||
mode = 0;
|
||||
while (1) {
|
||||
ssize_t cnt = 8192;
|
||||
buf = xrealloc(buf, fin_size + cnt);
|
||||
cnt = xread(0, buf + fin_size, cnt);
|
||||
if (cnt < 0)
|
||||
die("read error %s from stdin",
|
||||
strerror(errno));
|
||||
if (!cnt)
|
||||
break;
|
||||
fin_size += cnt;
|
||||
}
|
||||
buf = xrealloc(buf, fin_size + 1);
|
||||
if (strbuf_read(&buf, 0, 0) < 0)
|
||||
die("read error %s from stdin", strerror(errno));
|
||||
}
|
||||
buf[fin_size] = 0;
|
||||
origin->file.ptr = buf;
|
||||
origin->file.size = fin_size;
|
||||
pretend_sha1_file(buf, fin_size, OBJ_BLOB, origin->blob_sha1);
|
||||
origin->file.ptr = buf.buf;
|
||||
origin->file.size = buf.len;
|
||||
pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1);
|
||||
commit->util = origin;
|
||||
|
||||
/*
|
||||
|
@ -268,23 +268,22 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
char *subject = NULL;
|
||||
unsigned long subject_len = 0;
|
||||
struct strbuf subject;
|
||||
const char *sub = " **** invalid ref ****";
|
||||
|
||||
strbuf_init(&subject, 0);
|
||||
|
||||
commit = lookup_commit(item->sha1);
|
||||
if (commit && !parse_commit(commit)) {
|
||||
pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
|
||||
&subject, &subject_len, 0,
|
||||
NULL, NULL, 0);
|
||||
sub = subject;
|
||||
pretty_print_commit(CMIT_FMT_ONELINE, commit,
|
||||
&subject, 0, NULL, NULL, 0);
|
||||
sub = subject.buf;
|
||||
}
|
||||
printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
|
||||
maxwidth, item->name,
|
||||
branch_get_color(COLOR_BRANCH_RESET),
|
||||
find_unique_abbrev(item->sha1, abbrev), sub);
|
||||
if (subject)
|
||||
free(subject);
|
||||
strbuf_release(&subject);
|
||||
} else {
|
||||
printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
|
||||
branch_get_color(COLOR_BRANCH_RESET));
|
||||
|
@ -56,7 +56,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
|
||||
else if (ATTR_UNSET(value))
|
||||
value = "unspecified";
|
||||
|
||||
write_name_quoted("", 0, argv[i], 1, stdout);
|
||||
quote_c_style(argv[i], NULL, stdout, 0);
|
||||
printf(": %s: %s\n", argv[j+1], value);
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,6 @@
|
||||
*/
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "strbuf.h"
|
||||
#include "quote.h"
|
||||
#include "cache-tree.h"
|
||||
|
||||
@ -67,9 +66,7 @@ static void write_tempfile_record(const char *name, int prefix_length)
|
||||
fputs(topath[checkout_stage], stdout);
|
||||
|
||||
putchar('\t');
|
||||
write_name_quoted("", 0, name + prefix_length,
|
||||
line_termination, stdout);
|
||||
putchar(line_termination);
|
||||
write_name_quoted(name + prefix_length, stdout, line_termination);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
topath[i][0] = 0;
|
||||
@ -271,28 +268,28 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
|
||||
if (read_from_stdin) {
|
||||
struct strbuf buf;
|
||||
struct strbuf buf, nbuf;
|
||||
|
||||
if (all)
|
||||
die("git-checkout-index: don't mix '--all' and '--stdin'");
|
||||
strbuf_init(&buf);
|
||||
while (1) {
|
||||
char *path_name;
|
||||
const char *p;
|
||||
|
||||
read_line(&buf, stdin, line_termination);
|
||||
if (buf.eof)
|
||||
break;
|
||||
if (line_termination && buf.buf[0] == '"')
|
||||
path_name = unquote_c_style(buf.buf, NULL);
|
||||
else
|
||||
path_name = buf.buf;
|
||||
p = prefix_path(prefix, prefix_length, path_name);
|
||||
strbuf_init(&buf, 0);
|
||||
strbuf_init(&nbuf, 0);
|
||||
while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
|
||||
const char *p;
|
||||
if (line_termination && buf.buf[0] == '"') {
|
||||
strbuf_reset(&nbuf);
|
||||
if (unquote_c_style(&nbuf, buf.buf, NULL))
|
||||
die("line is badly quoted");
|
||||
strbuf_swap(&buf, &nbuf);
|
||||
}
|
||||
p = prefix_path(prefix, prefix_length, buf.buf);
|
||||
checkout_file(p, prefix_length);
|
||||
if (p < path_name || p > path_name + strlen(path_name))
|
||||
if (p < buf.buf || p > buf.buf + buf.len)
|
||||
free((char *)p);
|
||||
if (path_name != buf.buf)
|
||||
free(path_name);
|
||||
}
|
||||
strbuf_release(&nbuf);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
if (all)
|
||||
|
@ -14,36 +14,6 @@
|
||||
/*
|
||||
* FIXME! Share the code with "write-tree.c"
|
||||
*/
|
||||
static void init_buffer(char **bufp, unsigned int *sizep)
|
||||
{
|
||||
*bufp = xmalloc(BLOCKING);
|
||||
*sizep = 0;
|
||||
}
|
||||
|
||||
static void add_buffer(char **bufp, unsigned int *sizep, const char *fmt, ...)
|
||||
{
|
||||
char one_line[2048];
|
||||
va_list args;
|
||||
int len;
|
||||
unsigned long alloc, size, newsize;
|
||||
char *buf;
|
||||
|
||||
va_start(args, fmt);
|
||||
len = vsnprintf(one_line, sizeof(one_line), fmt, args);
|
||||
va_end(args);
|
||||
size = *sizep;
|
||||
newsize = size + len + 1;
|
||||
alloc = (size + 32767) & ~32767;
|
||||
buf = *bufp;
|
||||
if (newsize > alloc) {
|
||||
alloc = (newsize + 32767) & ~32767;
|
||||
buf = xrealloc(buf, alloc);
|
||||
*bufp = buf;
|
||||
}
|
||||
*sizep = newsize - 1;
|
||||
memcpy(buf + size, one_line, len);
|
||||
}
|
||||
|
||||
static void check_valid(unsigned char *sha1, enum object_type expect)
|
||||
{
|
||||
enum object_type type = sha1_object_info(sha1, NULL);
|
||||
@ -87,9 +57,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
|
||||
int parents = 0;
|
||||
unsigned char tree_sha1[20];
|
||||
unsigned char commit_sha1[20];
|
||||
char comment[1000];
|
||||
char *buffer;
|
||||
unsigned int size;
|
||||
struct strbuf buffer;
|
||||
int encoding_is_utf8;
|
||||
|
||||
git_config(git_default_config);
|
||||
@ -118,8 +86,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
|
||||
/* Not having i18n.commitencoding is the same as having utf-8 */
|
||||
encoding_is_utf8 = is_encoding_utf8(git_commit_encoding);
|
||||
|
||||
init_buffer(&buffer, &size);
|
||||
add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1));
|
||||
strbuf_init(&buffer, 8192); /* should avoid reallocs for the headers */
|
||||
strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree_sha1));
|
||||
|
||||
/*
|
||||
* NOTE! This ordering means that the same exact tree merged with a
|
||||
@ -127,26 +95,24 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
|
||||
* if everything else stays the same.
|
||||
*/
|
||||
for (i = 0; i < parents; i++)
|
||||
add_buffer(&buffer, &size, "parent %s\n", sha1_to_hex(parent_sha1[i]));
|
||||
strbuf_addf(&buffer, "parent %s\n", sha1_to_hex(parent_sha1[i]));
|
||||
|
||||
/* Person/date information */
|
||||
add_buffer(&buffer, &size, "author %s\n", git_author_info(1));
|
||||
add_buffer(&buffer, &size, "committer %s\n", git_committer_info(1));
|
||||
strbuf_addf(&buffer, "author %s\n", git_author_info(1));
|
||||
strbuf_addf(&buffer, "committer %s\n", git_committer_info(1));
|
||||
if (!encoding_is_utf8)
|
||||
add_buffer(&buffer, &size,
|
||||
"encoding %s\n", git_commit_encoding);
|
||||
add_buffer(&buffer, &size, "\n");
|
||||
strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding);
|
||||
strbuf_addch(&buffer, '\n');
|
||||
|
||||
/* And add the comment */
|
||||
while (fgets(comment, sizeof(comment), stdin) != NULL)
|
||||
add_buffer(&buffer, &size, "%s", comment);
|
||||
if (strbuf_read(&buffer, 0, 0) < 0)
|
||||
die("git-commit-tree: read returned %s", strerror(errno));
|
||||
|
||||
/* And check the encoding */
|
||||
buffer[size] = '\0';
|
||||
if (encoding_is_utf8 && !is_utf8(buffer))
|
||||
if (encoding_is_utf8 && !is_utf8(buffer.buf))
|
||||
fprintf(stderr, commit_utf8_warn);
|
||||
|
||||
if (!write_sha1_file(buffer, size, commit_type, commit_sha1)) {
|
||||
if (!write_sha1_file(buffer.buf, buffer.len, commit_type, commit_sha1)) {
|
||||
printf("%s\n", sha1_to_hex(commit_sha1));
|
||||
return 0;
|
||||
}
|
||||
|
@ -3,26 +3,14 @@
|
||||
#include "refs.h"
|
||||
#include "commit.h"
|
||||
|
||||
#define CHUNK_SIZE 1024
|
||||
|
||||
static char *get_stdin(void)
|
||||
{
|
||||
size_t offset = 0;
|
||||
char *data = xmalloc(CHUNK_SIZE);
|
||||
|
||||
while (1) {
|
||||
ssize_t cnt = xread(0, data + offset, CHUNK_SIZE);
|
||||
if (cnt < 0)
|
||||
die("error reading standard input: %s",
|
||||
strerror(errno));
|
||||
if (cnt == 0) {
|
||||
data[offset] = 0;
|
||||
break;
|
||||
}
|
||||
offset += cnt;
|
||||
data = xrealloc(data, offset + CHUNK_SIZE);
|
||||
struct strbuf buf;
|
||||
strbuf_init(&buf, 0);
|
||||
if (strbuf_read(&buf, 0, 1024) < 0) {
|
||||
die("error reading standard input: %s", strerror(errno));
|
||||
}
|
||||
return data;
|
||||
return strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
||||
static void show_new(enum object_type type, unsigned char *sha1_new)
|
||||
@ -234,19 +222,15 @@ static char *find_local_name(const char *remote_name, const char *refs,
|
||||
}
|
||||
if (!strncmp(remote_name, ref, len) && ref[len] == ':') {
|
||||
const char *local_part = ref + len + 1;
|
||||
char *ret;
|
||||
int retlen;
|
||||
|
||||
if (!next)
|
||||
retlen = strlen(local_part);
|
||||
else
|
||||
retlen = next - local_part;
|
||||
ret = xmalloc(retlen + 1);
|
||||
memcpy(ret, local_part, retlen);
|
||||
ret[retlen] = 0;
|
||||
*force_p = single_force;
|
||||
*not_for_merge_p = not_for_merge;
|
||||
return ret;
|
||||
return xmemdupz(local_part, retlen);
|
||||
}
|
||||
ref = next;
|
||||
}
|
||||
|
@ -140,12 +140,10 @@ static int handle_line(char *line)
|
||||
if (!strcmp(".", src) || !strcmp(src, origin)) {
|
||||
int len = strlen(origin);
|
||||
if (origin[0] == '\'' && origin[len - 1] == '\'') {
|
||||
char *new_origin = xmalloc(len - 1);
|
||||
memcpy(new_origin, origin + 1, len - 2);
|
||||
new_origin[len - 2] = 0;
|
||||
origin = new_origin;
|
||||
} else
|
||||
origin = xmemdupz(origin + 1, len - 2);
|
||||
} else {
|
||||
origin = xstrdup(origin);
|
||||
}
|
||||
} else {
|
||||
char *new_origin = xmalloc(strlen(origin) + strlen(src) + 5);
|
||||
sprintf(new_origin, "%s of %s", origin, src);
|
||||
@ -211,14 +209,11 @@ static void shortlog(const char *name, unsigned char *sha1,
|
||||
|
||||
bol += 2;
|
||||
eol = strchr(bol, '\n');
|
||||
|
||||
if (eol) {
|
||||
int len = eol - bol;
|
||||
oneline = xmalloc(len + 1);
|
||||
memcpy(oneline, bol, len);
|
||||
oneline[len] = 0;
|
||||
} else
|
||||
oneline = xmemdupz(bol, eol - bol);
|
||||
} else {
|
||||
oneline = xstrdup(bol);
|
||||
}
|
||||
append_to_list(&subjects, oneline, NULL);
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,6 @@ static int used_atom_cnt, sort_atom_limit, need_tagged;
|
||||
static int parse_atom(const char *atom, const char *ep)
|
||||
{
|
||||
const char *sp;
|
||||
char *n;
|
||||
int i, at;
|
||||
|
||||
sp = atom;
|
||||
@ -129,10 +128,7 @@ static int parse_atom(const char *atom, const char *ep)
|
||||
(sizeof *used_atom) * used_atom_cnt);
|
||||
used_atom_type = xrealloc(used_atom_type,
|
||||
(sizeof(*used_atom_type) * used_atom_cnt));
|
||||
n = xmalloc(ep - atom + 1);
|
||||
memcpy(n, atom, ep - atom);
|
||||
n[ep-atom] = 0;
|
||||
used_atom[at] = n;
|
||||
used_atom[at] = xmemdupz(atom, ep - atom);
|
||||
used_atom_type[at] = valid_atom[i].cmp_type;
|
||||
return at;
|
||||
}
|
||||
@ -316,46 +312,28 @@ static const char *find_wholine(const char *who, int wholen, const char *buf, un
|
||||
static const char *copy_line(const char *buf)
|
||||
{
|
||||
const char *eol = strchr(buf, '\n');
|
||||
char *line;
|
||||
int len;
|
||||
if (!eol)
|
||||
return "";
|
||||
len = eol - buf;
|
||||
line = xmalloc(len + 1);
|
||||
memcpy(line, buf, len);
|
||||
line[len] = 0;
|
||||
return line;
|
||||
return xmemdupz(buf, eol - buf);
|
||||
}
|
||||
|
||||
static const char *copy_name(const char *buf)
|
||||
{
|
||||
const char *eol = strchr(buf, '\n');
|
||||
const char *eoname = strstr(buf, " <");
|
||||
char *line;
|
||||
int len;
|
||||
if (!(eoname && eol && eoname < eol))
|
||||
return "";
|
||||
len = eoname - buf;
|
||||
line = xmalloc(len + 1);
|
||||
memcpy(line, buf, len);
|
||||
line[len] = 0;
|
||||
return line;
|
||||
const char *cp;
|
||||
for (cp = buf; *cp && *cp != '\n'; cp++) {
|
||||
if (!strncmp(cp, " <", 2))
|
||||
return xmemdupz(buf, cp - buf);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char *copy_email(const char *buf)
|
||||
{
|
||||
const char *email = strchr(buf, '<');
|
||||
const char *eoemail = strchr(email, '>');
|
||||
char *line;
|
||||
int len;
|
||||
if (!email || !eoemail)
|
||||
return "";
|
||||
eoemail++;
|
||||
len = eoemail - email;
|
||||
line = xmalloc(len + 1);
|
||||
memcpy(line, email, len);
|
||||
line[len] = 0;
|
||||
return line;
|
||||
return xmemdupz(email, eoemail + 1 - email);
|
||||
}
|
||||
|
||||
static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
|
||||
|
@ -441,8 +441,6 @@ static const char *clean_message_id(const char *msg_id)
|
||||
{
|
||||
char ch;
|
||||
const char *a, *z, *m;
|
||||
char *n;
|
||||
size_t len;
|
||||
|
||||
m = msg_id;
|
||||
while ((ch = *m) && (isspace(ch) || (ch == '<')))
|
||||
@ -458,11 +456,7 @@ static const char *clean_message_id(const char *msg_id)
|
||||
die("insane in-reply-to: %s", msg_id);
|
||||
if (++z == m)
|
||||
return a;
|
||||
len = z - a;
|
||||
n = xmalloc(len + 1);
|
||||
memcpy(n, a, len);
|
||||
n[len] = 0;
|
||||
return n;
|
||||
return xmemdupz(a, z - a);
|
||||
}
|
||||
|
||||
int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
@ -541,9 +535,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
endpos = strchr(committer, '>');
|
||||
if (!endpos)
|
||||
die("bogos committer info %s\n", committer);
|
||||
add_signoff = xmalloc(endpos - committer + 2);
|
||||
memcpy(add_signoff, committer, endpos - committer + 1);
|
||||
add_signoff[endpos - committer + 1] = 0;
|
||||
add_signoff = xmemdupz(committer, endpos - committer + 1);
|
||||
}
|
||||
else if (!strcmp(argv[i], "--attach")) {
|
||||
rev.mime_boundary = git_version_string;
|
||||
@ -792,13 +784,13 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
|
||||
sign = '-';
|
||||
|
||||
if (verbose) {
|
||||
char *buf = NULL;
|
||||
unsigned long buflen = 0;
|
||||
pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
|
||||
&buf, &buflen, 0, NULL, NULL, 0);
|
||||
struct strbuf buf;
|
||||
strbuf_init(&buf, 0);
|
||||
pretty_print_commit(CMIT_FMT_ONELINE, commit,
|
||||
&buf, 0, NULL, NULL, 0);
|
||||
printf("%c %s %s\n", sign,
|
||||
sha1_to_hex(commit->object.sha1), buf);
|
||||
free(buf);
|
||||
sha1_to_hex(commit->object.sha1), buf.buf);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
else {
|
||||
printf("%c %s\n", sign,
|
||||
|
@ -84,8 +84,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
|
||||
return;
|
||||
|
||||
fputs(tag, stdout);
|
||||
write_name_quoted("", 0, ent->name + offset, line_terminator, stdout);
|
||||
putchar(line_terminator);
|
||||
write_name_quoted(ent->name + offset, stdout, line_terminator);
|
||||
}
|
||||
|
||||
static void show_other_files(struct dir_struct *dir)
|
||||
@ -208,21 +207,15 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
|
||||
|
||||
if (!show_stage) {
|
||||
fputs(tag, stdout);
|
||||
write_name_quoted("", 0, ce->name + offset,
|
||||
line_terminator, stdout);
|
||||
putchar(line_terminator);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printf("%s%06o %s %d\t",
|
||||
tag,
|
||||
ntohl(ce->ce_mode),
|
||||
abbrev ? find_unique_abbrev(ce->sha1,abbrev)
|
||||
: sha1_to_hex(ce->sha1),
|
||||
ce_stage(ce));
|
||||
write_name_quoted("", 0, ce->name + offset,
|
||||
line_terminator, stdout);
|
||||
putchar(line_terminator);
|
||||
}
|
||||
write_name_quoted(ce->name + offset, stdout, line_terminator);
|
||||
}
|
||||
|
||||
static void show_files(struct dir_struct *dir, const char *prefix)
|
||||
@ -300,7 +293,6 @@ static void prune_cache(const char *prefix)
|
||||
static const char *verify_pathspec(const char *prefix)
|
||||
{
|
||||
const char **p, *n, *prev;
|
||||
char *real_prefix;
|
||||
unsigned long max;
|
||||
|
||||
prev = NULL;
|
||||
@ -327,14 +319,8 @@ static const char *verify_pathspec(const char *prefix)
|
||||
if (prefix_offset > max || memcmp(prev, prefix, prefix_offset))
|
||||
die("git-ls-files: cannot generate relative filenames containing '..'");
|
||||
|
||||
real_prefix = NULL;
|
||||
prefix_len = max;
|
||||
if (max) {
|
||||
real_prefix = xmalloc(max + 1);
|
||||
memcpy(real_prefix, prev, max);
|
||||
real_prefix[max] = 0;
|
||||
}
|
||||
return real_prefix;
|
||||
return max ? xmemdupz(prev, max) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -112,10 +112,8 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
|
||||
abbrev ? find_unique_abbrev(sha1, abbrev)
|
||||
: sha1_to_hex(sha1));
|
||||
}
|
||||
write_name_quoted(base + chomp_prefix, baselen - chomp_prefix,
|
||||
pathname,
|
||||
line_termination, stdout);
|
||||
putchar(line_termination);
|
||||
write_name_quotedpfx(base + chomp_prefix, baselen - chomp_prefix,
|
||||
pathname, stdout, line_termination);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,7 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
|
||||
for (i = 0; i < count; i++) {
|
||||
int length = strlen(result[i]);
|
||||
if (length > 0 && result[i][length - 1] == '/') {
|
||||
char *without_slash = xmalloc(length);
|
||||
memcpy(without_slash, result[i], length - 1);
|
||||
without_slash[length - 1] = '\0';
|
||||
result[i] = without_slash;
|
||||
result[i] = xmemdupz(result[i], length - 1);
|
||||
}
|
||||
if (base_name) {
|
||||
const char *last_slash = strrchr(result[i], '/');
|
||||
|
@ -66,40 +66,15 @@ static int write_rr(struct path_list *rr, int out_fd)
|
||||
return commit_lock_file(&write_lock);
|
||||
}
|
||||
|
||||
struct buffer {
|
||||
char *ptr;
|
||||
int nr, alloc;
|
||||
};
|
||||
|
||||
static void append_line(struct buffer *buffer, const char *line)
|
||||
{
|
||||
int len = strlen(line);
|
||||
|
||||
if (buffer->nr + len > buffer->alloc) {
|
||||
buffer->alloc = alloc_nr(buffer->nr + len);
|
||||
buffer->ptr = xrealloc(buffer->ptr, buffer->alloc);
|
||||
}
|
||||
memcpy(buffer->ptr + buffer->nr, line, len);
|
||||
buffer->nr += len;
|
||||
}
|
||||
|
||||
static void clear_buffer(struct buffer *buffer)
|
||||
{
|
||||
free(buffer->ptr);
|
||||
buffer->ptr = NULL;
|
||||
buffer->nr = buffer->alloc = 0;
|
||||
}
|
||||
|
||||
static int handle_file(const char *path,
|
||||
unsigned char *sha1, const char *output)
|
||||
{
|
||||
SHA_CTX ctx;
|
||||
char buf[1024];
|
||||
int hunk = 0, hunk_no = 0;
|
||||
struct buffer minus = { NULL, 0, 0 }, plus = { NULL, 0, 0 };
|
||||
struct buffer *one = &minus, *two = +
|
||||
struct strbuf one, two;
|
||||
FILE *f = fopen(path, "r");
|
||||
FILE *out;
|
||||
FILE *out = NULL;
|
||||
|
||||
if (!f)
|
||||
return error("Could not open %s", path);
|
||||
@ -110,51 +85,50 @@ static int handle_file(const char *path,
|
||||
fclose(f);
|
||||
return error("Could not write %s", output);
|
||||
}
|
||||
} else
|
||||
out = NULL;
|
||||
}
|
||||
|
||||
if (sha1)
|
||||
SHA1_Init(&ctx);
|
||||
|
||||
strbuf_init(&one, 0);
|
||||
strbuf_init(&two, 0);
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
if (!prefixcmp(buf, "<<<<<<< "))
|
||||
hunk = 1;
|
||||
else if (!prefixcmp(buf, "======="))
|
||||
hunk = 2;
|
||||
else if (!prefixcmp(buf, ">>>>>>> ")) {
|
||||
int one_is_longer = (one->nr > two->nr);
|
||||
int common_len = one_is_longer ? two->nr : one->nr;
|
||||
int cmp = memcmp(one->ptr, two->ptr, common_len);
|
||||
int cmp = strbuf_cmp(&one, &two);
|
||||
|
||||
hunk_no++;
|
||||
hunk = 0;
|
||||
if ((cmp > 0) || ((cmp == 0) && one_is_longer)) {
|
||||
struct buffer *swap = one;
|
||||
one = two;
|
||||
two = swap;
|
||||
if (cmp > 0) {
|
||||
strbuf_swap(&one, &two);
|
||||
}
|
||||
if (out) {
|
||||
fputs("<<<<<<<\n", out);
|
||||
fwrite(one->ptr, one->nr, 1, out);
|
||||
fwrite(one.buf, one.len, 1, out);
|
||||
fputs("=======\n", out);
|
||||
fwrite(two->ptr, two->nr, 1, out);
|
||||
fwrite(two.buf, two.len, 1, out);
|
||||
fputs(">>>>>>>\n", out);
|
||||
}
|
||||
if (sha1) {
|
||||
SHA1_Update(&ctx, one->ptr, one->nr);
|
||||
SHA1_Update(&ctx, "\0", 1);
|
||||
SHA1_Update(&ctx, two->ptr, two->nr);
|
||||
SHA1_Update(&ctx, "\0", 1);
|
||||
SHA1_Update(&ctx, one.buf ? one.buf : "",
|
||||
one.len + 1);
|
||||
SHA1_Update(&ctx, two.buf ? two.buf : "",
|
||||
two.len + 1);
|
||||
}
|
||||
clear_buffer(one);
|
||||
clear_buffer(two);
|
||||
strbuf_reset(&one);
|
||||
strbuf_reset(&two);
|
||||
} else if (hunk == 1)
|
||||
append_line(one, buf);
|
||||
strbuf_addstr(&one, buf);
|
||||
else if (hunk == 2)
|
||||
append_line(two, buf);
|
||||
strbuf_addstr(&two, buf);
|
||||
else if (out)
|
||||
fputs(buf, out);
|
||||
}
|
||||
strbuf_release(&one);
|
||||
strbuf_release(&two);
|
||||
|
||||
fclose(f);
|
||||
if (out)
|
||||
|
@ -80,13 +80,12 @@ static void show_commit(struct commit *commit)
|
||||
putchar('\n');
|
||||
|
||||
if (revs.verbose_header) {
|
||||
char *buf = NULL;
|
||||
unsigned long buflen = 0;
|
||||
pretty_print_commit(revs.commit_format, commit, ~0,
|
||||
&buf, &buflen,
|
||||
revs.abbrev, NULL, NULL, revs.date_mode);
|
||||
printf("%s%c", buf, hdr_termination);
|
||||
free(buf);
|
||||
struct strbuf buf;
|
||||
strbuf_init(&buf, 0);
|
||||
pretty_print_commit(revs.commit_format, commit,
|
||||
&buf, revs.abbrev, NULL, NULL, revs.date_mode);
|
||||
printf("%s%c", buf.buf, hdr_termination);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
if (commit->parents) {
|
||||
|
@ -168,9 +168,7 @@ static void set_author_ident_env(const char *message)
|
||||
char *line, *pend, *email, *timestamp;
|
||||
|
||||
p += 7;
|
||||
line = xmalloc(eol + 1 - p);
|
||||
memcpy(line, p, eol - p);
|
||||
line[eol - p] = '\0';
|
||||
line = xmemdupz(p, eol - p);
|
||||
email = strchr(line, '<');
|
||||
if (!email)
|
||||
die ("Could not extract author email from %s",
|
||||
|
@ -39,10 +39,7 @@ static void insert_author_oneline(struct path_list *list,
|
||||
while (authorlen > 0 && isspace(author[authorlen - 1]))
|
||||
authorlen--;
|
||||
|
||||
buffer = xmalloc(authorlen + 1);
|
||||
memcpy(buffer, author, authorlen);
|
||||
buffer[authorlen] = '\0';
|
||||
|
||||
buffer = xmemdupz(author, authorlen);
|
||||
item = path_list_insert(buffer, list);
|
||||
if (item->util == NULL)
|
||||
item->util = xcalloc(1, sizeof(struct path_list));
|
||||
@ -66,13 +63,9 @@ static void insert_author_oneline(struct path_list *list,
|
||||
oneline++;
|
||||
onelinelen--;
|
||||
}
|
||||
|
||||
while (onelinelen > 0 && isspace(oneline[onelinelen - 1]))
|
||||
onelinelen--;
|
||||
|
||||
buffer = xmalloc(onelinelen + 1);
|
||||
memcpy(buffer, oneline, onelinelen);
|
||||
buffer[onelinelen] = '\0';
|
||||
buffer = xmemdupz(oneline, onelinelen);
|
||||
|
||||
if (dot3) {
|
||||
int dot3len = strlen(dot3);
|
||||
|
@ -259,16 +259,15 @@ static void join_revs(struct commit_list **list_p,
|
||||
|
||||
static void show_one_commit(struct commit *commit, int no_name)
|
||||
{
|
||||
char *pretty = NULL;
|
||||
struct strbuf pretty;
|
||||
const char *pretty_str = "(unavailable)";
|
||||
unsigned long pretty_len = 0;
|
||||
struct commit_name *name = commit->util;
|
||||
|
||||
strbuf_init(&pretty, 0);
|
||||
if (commit->object.parsed) {
|
||||
pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
|
||||
&pretty, &pretty_len,
|
||||
0, NULL, NULL, 0);
|
||||
pretty_str = pretty;
|
||||
pretty_print_commit(CMIT_FMT_ONELINE, commit,
|
||||
&pretty, 0, NULL, NULL, 0);
|
||||
pretty_str = pretty.buf;
|
||||
}
|
||||
if (!prefixcmp(pretty_str, "[PATCH] "))
|
||||
pretty_str += 8;
|
||||
@ -289,7 +288,7 @@ static void show_one_commit(struct commit *commit, int no_name)
|
||||
find_unique_abbrev(commit->object.sha1, 7));
|
||||
}
|
||||
puts(pretty_str);
|
||||
free(pretty);
|
||||
strbuf_release(&pretty);
|
||||
}
|
||||
|
||||
static char *ref_name[MAX_REVS + 1];
|
||||
|
@ -8,17 +8,13 @@
|
||||
*/
|
||||
static size_t cleanup(char *line, size_t len)
|
||||
{
|
||||
if (len) {
|
||||
if (line[len - 1] == '\n')
|
||||
len--;
|
||||
|
||||
while (len) {
|
||||
unsigned char c = line[len - 1];
|
||||
if (!isspace(c))
|
||||
break;
|
||||
len--;
|
||||
}
|
||||
while (len) {
|
||||
unsigned char c = line[len - 1];
|
||||
if (!isspace(c))
|
||||
break;
|
||||
len--;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -34,66 +30,60 @@ static size_t cleanup(char *line, size_t len)
|
||||
* If the input has only empty lines and spaces,
|
||||
* no output will be produced.
|
||||
*
|
||||
* If last line has a newline at the end, it will be removed.
|
||||
* If last line does not have a newline at the end, one is added.
|
||||
*
|
||||
* Enable skip_comments to skip every line starting with "#".
|
||||
*/
|
||||
size_t stripspace(char *buffer, size_t length, int skip_comments)
|
||||
void stripspace(struct strbuf *sb, int skip_comments)
|
||||
{
|
||||
int empties = -1;
|
||||
int empties = 0;
|
||||
size_t i, j, len, newlen;
|
||||
char *eol;
|
||||
|
||||
for (i = j = 0; i < length; i += len, j += newlen) {
|
||||
eol = memchr(buffer + i, '\n', length - i);
|
||||
len = eol ? eol - (buffer + i) + 1 : length - i;
|
||||
/* We may have to add a newline. */
|
||||
strbuf_grow(sb, 1);
|
||||
|
||||
if (skip_comments && len && buffer[i] == '#') {
|
||||
for (i = j = 0; i < sb->len; i += len, j += newlen) {
|
||||
eol = memchr(sb->buf + i, '\n', sb->len - i);
|
||||
len = eol ? eol - (sb->buf + i) + 1 : sb->len - i;
|
||||
|
||||
if (skip_comments && len && sb->buf[i] == '#') {
|
||||
newlen = 0;
|
||||
continue;
|
||||
}
|
||||
newlen = cleanup(buffer + i, len);
|
||||
newlen = cleanup(sb->buf + i, len);
|
||||
|
||||
/* Not just an empty line? */
|
||||
if (newlen) {
|
||||
if (empties != -1)
|
||||
buffer[j++] = '\n';
|
||||
if (empties > 0)
|
||||
buffer[j++] = '\n';
|
||||
if (empties > 0 && j > 0)
|
||||
sb->buf[j++] = '\n';
|
||||
empties = 0;
|
||||
memmove(buffer + j, buffer + i, newlen);
|
||||
continue;
|
||||
memmove(sb->buf + j, sb->buf + i, newlen);
|
||||
sb->buf[newlen + j++] = '\n';
|
||||
} else {
|
||||
empties++;
|
||||
}
|
||||
if (empties < 0)
|
||||
continue;
|
||||
empties++;
|
||||
}
|
||||
|
||||
return j;
|
||||
strbuf_setlen(sb, j);
|
||||
}
|
||||
|
||||
int cmd_stripspace(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
char *buffer;
|
||||
unsigned long size;
|
||||
struct strbuf buf;
|
||||
int strip_comments = 0;
|
||||
|
||||
if (argc > 1 && (!strcmp(argv[1], "-s") ||
|
||||
!strcmp(argv[1], "--strip-comments")))
|
||||
strip_comments = 1;
|
||||
|
||||
size = 1024;
|
||||
buffer = xmalloc(size);
|
||||
if (read_fd(0, &buffer, &size)) {
|
||||
free(buffer);
|
||||
strbuf_init(&buf, 0);
|
||||
if (strbuf_read(&buf, 0, 1024) < 0)
|
||||
die("could not read the input");
|
||||
}
|
||||
|
||||
size = stripspace(buffer, size, strip_comments);
|
||||
write_or_die(1, buffer, size);
|
||||
if (size)
|
||||
putc('\n', stdout);
|
||||
stripspace(&buf, strip_comments);
|
||||
|
||||
free(buffer);
|
||||
write_or_die(1, buf.buf, buf.len);
|
||||
strbuf_release(&buf);
|
||||
return 0;
|
||||
}
|
||||
|
@ -17,12 +17,11 @@ static const char builtin_tag_usage[] =
|
||||
|
||||
static char signingkey[1000];
|
||||
|
||||
static void launch_editor(const char *path, char **buffer, unsigned long *len)
|
||||
static void launch_editor(const char *path, struct strbuf *buffer)
|
||||
{
|
||||
const char *editor, *terminal;
|
||||
struct child_process child;
|
||||
const char *args[3];
|
||||
int fd;
|
||||
|
||||
editor = getenv("GIT_EDITOR");
|
||||
if (!editor && editor_program)
|
||||
@ -52,15 +51,9 @@ static void launch_editor(const char *path, char **buffer, unsigned long *len)
|
||||
if (run_command(&child))
|
||||
die("There was a problem with the editor %s.", editor);
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
die("could not open '%s': %s", path, strerror(errno));
|
||||
if (read_fd(fd, buffer, len)) {
|
||||
free(*buffer);
|
||||
if (strbuf_read_file(buffer, path, 0) < 0)
|
||||
die("could not read message file '%s': %s",
|
||||
path, strerror(errno));
|
||||
}
|
||||
close(fd);
|
||||
path, strerror(errno));
|
||||
}
|
||||
|
||||
struct tag_filter {
|
||||
@ -184,7 +177,7 @@ static int verify_tag(const char *name, const char *ref,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t do_sign(char *buffer, size_t size, size_t max)
|
||||
static int do_sign(struct strbuf *buffer)
|
||||
{
|
||||
struct child_process gpg;
|
||||
const char *args[4];
|
||||
@ -216,22 +209,22 @@ static ssize_t do_sign(char *buffer, size_t size, size_t max)
|
||||
if (start_command(&gpg))
|
||||
return error("could not run gpg.");
|
||||
|
||||
if (write_in_full(gpg.in, buffer, size) != size) {
|
||||
if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {
|
||||
close(gpg.in);
|
||||
finish_command(&gpg);
|
||||
return error("gpg did not accept the tag data");
|
||||
}
|
||||
close(gpg.in);
|
||||
gpg.close_in = 0;
|
||||
len = read_in_full(gpg.out, buffer + size, max - size);
|
||||
len = strbuf_read(buffer, gpg.out, 1024);
|
||||
|
||||
if (finish_command(&gpg) || !len || len < 0)
|
||||
return error("gpg failed to sign the tag");
|
||||
|
||||
if (len == max - size)
|
||||
if (len < 0)
|
||||
return error("could not read the entire signature from gpg.");
|
||||
|
||||
return size + len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char tag_template[] =
|
||||
@ -254,15 +247,13 @@ static int git_tag_config(const char *var, const char *value)
|
||||
return git_default_config(var, value);
|
||||
}
|
||||
|
||||
#define MAX_SIGNATURE_LENGTH 1024
|
||||
/* message must be NULL or allocated, it will be reallocated and freed */
|
||||
static void create_tag(const unsigned char *object, const char *tag,
|
||||
char *message, int sign, unsigned char *result)
|
||||
struct strbuf *buf, int message, int sign,
|
||||
unsigned char *result)
|
||||
{
|
||||
enum object_type type;
|
||||
char header_buf[1024], *buffer = NULL;
|
||||
int header_len, max_size;
|
||||
unsigned long size = 0;
|
||||
char header_buf[1024];
|
||||
int header_len;
|
||||
|
||||
type = sha1_object_info(object, NULL);
|
||||
if (type <= OBJ_NONE)
|
||||
@ -294,53 +285,37 @@ static void create_tag(const unsigned char *object, const char *tag,
|
||||
write_or_die(fd, tag_template, strlen(tag_template));
|
||||
close(fd);
|
||||
|
||||
launch_editor(path, &buffer, &size);
|
||||
launch_editor(path, buf);
|
||||
|
||||
unlink(path);
|
||||
free(path);
|
||||
}
|
||||
else {
|
||||
buffer = message;
|
||||
size = strlen(message);
|
||||
}
|
||||
|
||||
size = stripspace(buffer, size, 1);
|
||||
stripspace(buf, 1);
|
||||
|
||||
if (!message && !size)
|
||||
if (!message && !buf->len)
|
||||
die("no tag message?");
|
||||
|
||||
/* insert the header and add the '\n' if needed: */
|
||||
max_size = header_len + size + (sign ? MAX_SIGNATURE_LENGTH : 0) + 1;
|
||||
buffer = xrealloc(buffer, max_size);
|
||||
if (size)
|
||||
buffer[size++] = '\n';
|
||||
memmove(buffer + header_len, buffer, size);
|
||||
memcpy(buffer, header_buf, header_len);
|
||||
size += header_len;
|
||||
strbuf_insert(buf, 0, header_buf, header_len);
|
||||
|
||||
if (sign) {
|
||||
ssize_t r = do_sign(buffer, size, max_size);
|
||||
if (r < 0)
|
||||
die("unable to sign the tag");
|
||||
size = r;
|
||||
}
|
||||
|
||||
if (write_sha1_file(buffer, size, tag_type, result) < 0)
|
||||
if (sign && do_sign(buf) < 0)
|
||||
die("unable to sign the tag");
|
||||
if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
|
||||
die("unable to write tag file");
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct strbuf buf;
|
||||
unsigned char object[20], prev[20];
|
||||
int annotate = 0, sign = 0, force = 0, lines = 0;
|
||||
char *message = NULL;
|
||||
int annotate = 0, sign = 0, force = 0, lines = 0, message = 0;
|
||||
char ref[PATH_MAX];
|
||||
const char *object_ref, *tag;
|
||||
int i;
|
||||
struct ref_lock *lock;
|
||||
|
||||
git_config(git_tag_config);
|
||||
strbuf_init(&buf, 0);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
@ -376,13 +351,11 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
die("option -m needs an argument.");
|
||||
if (message)
|
||||
die("only one -F or -m option is allowed.");
|
||||
message = xstrdup(argv[i]);
|
||||
strbuf_addstr(&buf, argv[i]);
|
||||
message = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-F")) {
|
||||
unsigned long len;
|
||||
int fd;
|
||||
|
||||
annotate = 1;
|
||||
i++;
|
||||
if (i == argc)
|
||||
@ -390,20 +363,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
if (message)
|
||||
die("only one -F or -m option is allowed.");
|
||||
|
||||
if (!strcmp(argv[i], "-"))
|
||||
fd = 0;
|
||||
else {
|
||||
fd = open(argv[i], O_RDONLY);
|
||||
if (fd < 0)
|
||||
die("could not open '%s': %s",
|
||||
if (!strcmp(argv[i], "-")) {
|
||||
if (strbuf_read(&buf, 0, 1024) < 0)
|
||||
die("cannot read %s", argv[i]);
|
||||
} else {
|
||||
if (strbuf_read_file(&buf, argv[i], 1024) < 0)
|
||||
die("could not open or read '%s': %s",
|
||||
argv[i], strerror(errno));
|
||||
}
|
||||
len = 1024;
|
||||
message = xmalloc(len);
|
||||
if (read_fd(fd, &message, &len)) {
|
||||
free(message);
|
||||
die("cannot read %s", argv[i]);
|
||||
}
|
||||
message = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-u")) {
|
||||
@ -451,7 +419,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
die("tag '%s' already exists", tag);
|
||||
|
||||
if (annotate)
|
||||
create_tag(object, tag, message, sign, object);
|
||||
create_tag(object, tag, &buf, message, sign, object);
|
||||
|
||||
lock = lock_any_ref_for_update(ref, prev, 0);
|
||||
if (!lock)
|
||||
@ -459,5 +427,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
if (write_ref_sha1(lock, object, NULL) < 0)
|
||||
die("%s: cannot update the ref", ref);
|
||||
|
||||
strbuf_release(&buf);
|
||||
return 0;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
* Copyright (C) Linus Torvalds, 2005
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "strbuf.h"
|
||||
#include "quote.h"
|
||||
#include "cache-tree.h"
|
||||
#include "tree-walk.h"
|
||||
@ -296,8 +295,11 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
|
||||
static void read_index_info(int line_termination)
|
||||
{
|
||||
struct strbuf buf;
|
||||
strbuf_init(&buf);
|
||||
while (1) {
|
||||
struct strbuf uq;
|
||||
|
||||
strbuf_init(&buf, 0);
|
||||
strbuf_init(&uq, 0);
|
||||
while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
|
||||
char *ptr, *tab;
|
||||
char *path_name;
|
||||
unsigned char sha1[20];
|
||||
@ -321,10 +323,6 @@ static void read_index_info(int line_termination)
|
||||
* This format is to put higher order stages into the
|
||||
* index file and matches git-ls-files --stage output.
|
||||
*/
|
||||
read_line(&buf, stdin, line_termination);
|
||||
if (buf.eof)
|
||||
break;
|
||||
|
||||
errno = 0;
|
||||
ul = strtoul(buf.buf, &ptr, 8);
|
||||
if (ptr == buf.buf || *ptr != ' '
|
||||
@ -349,15 +347,17 @@ static void read_index_info(int line_termination)
|
||||
if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
|
||||
goto bad_line;
|
||||
|
||||
if (line_termination && ptr[0] == '"')
|
||||
path_name = unquote_c_style(ptr, NULL);
|
||||
else
|
||||
path_name = ptr;
|
||||
path_name = ptr;
|
||||
if (line_termination && path_name[0] == '"') {
|
||||
strbuf_reset(&uq);
|
||||
if (unquote_c_style(&uq, path_name, NULL)) {
|
||||
die("git-update-index: bad quoting of path name");
|
||||
}
|
||||
path_name = uq.buf;
|
||||
}
|
||||
|
||||
if (!verify_path(path_name)) {
|
||||
fprintf(stderr, "Ignoring path %s\n", path_name);
|
||||
if (path_name != ptr)
|
||||
free(path_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -377,13 +377,13 @@ static void read_index_info(int line_termination)
|
||||
die("git-update-index: unable to update %s",
|
||||
path_name);
|
||||
}
|
||||
if (path_name != ptr)
|
||||
free(path_name);
|
||||
continue;
|
||||
|
||||
bad_line:
|
||||
die("malformed index info %s", buf.buf);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
strbuf_release(&uq);
|
||||
}
|
||||
|
||||
static const char update_index_usage[] =
|
||||
@ -706,27 +706,27 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
|
||||
free((char*)p);
|
||||
}
|
||||
if (read_from_stdin) {
|
||||
struct strbuf buf;
|
||||
strbuf_init(&buf);
|
||||
while (1) {
|
||||
char *path_name;
|
||||
struct strbuf buf, nbuf;
|
||||
|
||||
strbuf_init(&buf, 0);
|
||||
strbuf_init(&nbuf, 0);
|
||||
while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
|
||||
const char *p;
|
||||
read_line(&buf, stdin, line_termination);
|
||||
if (buf.eof)
|
||||
break;
|
||||
if (line_termination && buf.buf[0] == '"')
|
||||
path_name = unquote_c_style(buf.buf, NULL);
|
||||
else
|
||||
path_name = buf.buf;
|
||||
p = prefix_path(prefix, prefix_length, path_name);
|
||||
if (line_termination && buf.buf[0] == '"') {
|
||||
strbuf_reset(&nbuf);
|
||||
if (unquote_c_style(&nbuf, buf.buf, NULL))
|
||||
die("line is badly quoted");
|
||||
strbuf_swap(&buf, &nbuf);
|
||||
}
|
||||
p = prefix_path(prefix, prefix_length, buf.buf);
|
||||
update_one(p, NULL, 0);
|
||||
if (set_executable_bit)
|
||||
chmod_path(set_executable_bit, p);
|
||||
if (p < path_name || p > path_name + strlen(path_name))
|
||||
free((char*) p);
|
||||
if (path_name != buf.buf)
|
||||
free(path_name);
|
||||
if (p < buf.buf || p > buf.buf + buf.len)
|
||||
free((char *)p);
|
||||
}
|
||||
strbuf_release(&nbuf);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
@ -7,7 +7,6 @@ extern const char git_version_string[];
|
||||
extern const char git_usage_string[];
|
||||
|
||||
extern void help_unknown_cmd(const char *cmd);
|
||||
extern size_t stripspace(char *buffer, size_t length, int skip_comments);
|
||||
extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
|
||||
extern void prune_packed_objects(int);
|
||||
|
||||
|
60
cache-tree.c
60
cache-tree.c
@ -235,8 +235,7 @@ static int update_one(struct cache_tree *it,
|
||||
int missing_ok,
|
||||
int dryrun)
|
||||
{
|
||||
unsigned long size, offset;
|
||||
char *buffer;
|
||||
struct strbuf buffer;
|
||||
int i;
|
||||
|
||||
if (0 <= it->entry_count && has_sha1_file(it->sha1))
|
||||
@ -293,9 +292,7 @@ static int update_one(struct cache_tree *it,
|
||||
/*
|
||||
* Then write out the tree object for this level.
|
||||
*/
|
||||
size = 8192;
|
||||
buffer = xmalloc(size);
|
||||
offset = 0;
|
||||
strbuf_init(&buffer, 8192);
|
||||
|
||||
for (i = 0; i < entries; i++) {
|
||||
struct cache_entry *ce = cache[i];
|
||||
@ -332,15 +329,9 @@ static int update_one(struct cache_tree *it,
|
||||
if (!ce->ce_mode)
|
||||
continue; /* entry being removed */
|
||||
|
||||
if (size < offset + entlen + 100) {
|
||||
size = alloc_nr(offset + entlen + 100);
|
||||
buffer = xrealloc(buffer, size);
|
||||
}
|
||||
offset += sprintf(buffer + offset,
|
||||
"%o %.*s", mode, entlen, path + baselen);
|
||||
buffer[offset++] = 0;
|
||||
hashcpy((unsigned char*)buffer + offset, sha1);
|
||||
offset += 20;
|
||||
strbuf_grow(&buffer, entlen + 100);
|
||||
strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
|
||||
strbuf_add(&buffer, sha1, 20);
|
||||
|
||||
#if DEBUG
|
||||
fprintf(stderr, "cache-tree update-one %o %.*s\n",
|
||||
@ -349,10 +340,10 @@ static int update_one(struct cache_tree *it,
|
||||
}
|
||||
|
||||
if (dryrun)
|
||||
hash_sha1_file(buffer, offset, tree_type, it->sha1);
|
||||
hash_sha1_file(buffer.buf, buffer.len, tree_type, it->sha1);
|
||||
else
|
||||
write_sha1_file(buffer, offset, tree_type, it->sha1);
|
||||
free(buffer);
|
||||
write_sha1_file(buffer.buf, buffer.len, tree_type, it->sha1);
|
||||
strbuf_release(&buffer);
|
||||
it->entry_count = i;
|
||||
#if DEBUG
|
||||
fprintf(stderr, "cache-tree update-one (%d ent, %d subtree) %s\n",
|
||||
@ -378,12 +369,8 @@ int cache_tree_update(struct cache_tree *it,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *write_one(struct cache_tree *it,
|
||||
char *path,
|
||||
int pathlen,
|
||||
char *buffer,
|
||||
unsigned long *size,
|
||||
unsigned long *offset)
|
||||
static void write_one(struct strbuf *buffer, struct cache_tree *it,
|
||||
const char *path, int pathlen)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -393,13 +380,9 @@ static void *write_one(struct cache_tree *it,
|
||||
* tree-sha1 (missing if invalid)
|
||||
* subtree_nr "cache-tree" entries for subtrees.
|
||||
*/
|
||||
if (*size < *offset + pathlen + 100) {
|
||||
*size = alloc_nr(*offset + pathlen + 100);
|
||||
buffer = xrealloc(buffer, *size);
|
||||
}
|
||||
*offset += sprintf(buffer + *offset, "%.*s%c%d %d\n",
|
||||
pathlen, path, 0,
|
||||
it->entry_count, it->subtree_nr);
|
||||
strbuf_grow(buffer, pathlen + 100);
|
||||
strbuf_add(buffer, path, pathlen);
|
||||
strbuf_addf(buffer, "%c%d %d\n", 0, it->entry_count, it->subtree_nr);
|
||||
|
||||
#if DEBUG
|
||||
if (0 <= it->entry_count)
|
||||
@ -412,8 +395,7 @@ static void *write_one(struct cache_tree *it,
|
||||
#endif
|
||||
|
||||
if (0 <= it->entry_count) {
|
||||
hashcpy((unsigned char*)buffer + *offset, it->sha1);
|
||||
*offset += 20;
|
||||
strbuf_add(buffer, it->sha1, 20);
|
||||
}
|
||||
for (i = 0; i < it->subtree_nr; i++) {
|
||||
struct cache_tree_sub *down = it->down[i];
|
||||
@ -423,21 +405,13 @@ static void *write_one(struct cache_tree *it,
|
||||
prev->name, prev->namelen) <= 0)
|
||||
die("fatal - unsorted cache subtree");
|
||||
}
|
||||
buffer = write_one(down->cache_tree, down->name, down->namelen,
|
||||
buffer, size, offset);
|
||||
write_one(buffer, down->cache_tree, down->name, down->namelen);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void *cache_tree_write(struct cache_tree *root, unsigned long *size_p)
|
||||
void cache_tree_write(struct strbuf *sb, struct cache_tree *root)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
unsigned long size = 8192;
|
||||
char *buffer = xmalloc(size);
|
||||
|
||||
*size_p = 0;
|
||||
path[0] = 0;
|
||||
return write_one(root, path, 0, buffer, &size, size_p);
|
||||
write_one(sb, root, "", 0);
|
||||
}
|
||||
|
||||
static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
|
||||
|
@ -22,7 +22,7 @@ void cache_tree_free(struct cache_tree **);
|
||||
void cache_tree_invalidate_path(struct cache_tree *, const char *);
|
||||
struct cache_tree_sub *cache_tree_sub(struct cache_tree *, const char *);
|
||||
|
||||
void *cache_tree_write(struct cache_tree *root, unsigned long *size_p);
|
||||
void cache_tree_write(struct strbuf *, struct cache_tree *root);
|
||||
struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
|
||||
|
||||
int cache_tree_fully_valid(struct cache_tree *);
|
||||
|
9
cache.h
9
cache.h
@ -2,6 +2,7 @@
|
||||
#define CACHE_H
|
||||
|
||||
#include "git-compat-util.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
#include SHA1_HEADER
|
||||
#include <zlib.h>
|
||||
@ -270,7 +271,6 @@ extern int ie_match_stat(struct index_state *, struct cache_entry *, struct stat
|
||||
extern int ie_modified(struct index_state *, struct cache_entry *, struct stat *, int);
|
||||
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
|
||||
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
|
||||
extern int read_fd(int fd, char **return_buf, unsigned long *return_size);
|
||||
extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
|
||||
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
|
||||
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
|
||||
@ -587,14 +587,13 @@ extern void *alloc_object_node(void);
|
||||
extern void alloc_report(void);
|
||||
|
||||
/* trace.c */
|
||||
extern int nfasprintf(char **str, const char *fmt, ...);
|
||||
extern int nfvasprintf(char **str, const char *fmt, va_list va);
|
||||
extern void trace_printf(const char *format, ...);
|
||||
extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
|
||||
|
||||
/* convert.c */
|
||||
extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep);
|
||||
extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep);
|
||||
/* returns 1 if *dst was used */
|
||||
extern int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst);
|
||||
extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);
|
||||
|
||||
/* diff.c */
|
||||
extern int diff_auto_refresh_index;
|
||||
|
@ -650,10 +650,7 @@ static void dump_quoted_path(const char *prefix, const char *path,
|
||||
const char *c_meta, const char *c_reset)
|
||||
{
|
||||
printf("%s%s", c_meta, prefix);
|
||||
if (quote_c_style(path, NULL, NULL, 0))
|
||||
quote_c_style(path, NULL, stdout, 0);
|
||||
else
|
||||
printf("%s", path);
|
||||
quote_c_style(path, NULL, stdout, 0);
|
||||
printf("%s\n", c_reset);
|
||||
}
|
||||
|
||||
@ -900,16 +897,7 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re
|
||||
putchar(inter_name_termination);
|
||||
}
|
||||
|
||||
if (line_termination) {
|
||||
if (quote_c_style(p->path, NULL, NULL, 0))
|
||||
quote_c_style(p->path, NULL, stdout, 0);
|
||||
else
|
||||
printf("%s", p->path);
|
||||
putchar(line_termination);
|
||||
}
|
||||
else {
|
||||
printf("%s%c", p->path, line_termination);
|
||||
}
|
||||
write_name_quoted(p->path, stdout, line_termination);
|
||||
}
|
||||
|
||||
void show_combined_diff(struct combine_diff_path *p,
|
||||
|
426
commit.c
426
commit.c
@ -458,11 +458,11 @@ void clear_commit_marks(struct commit *commit, unsigned int mark)
|
||||
/*
|
||||
* Generic support for pretty-printing the header
|
||||
*/
|
||||
static int get_one_line(const char *msg, unsigned long len)
|
||||
static int get_one_line(const char *msg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (len--) {
|
||||
for (;;) {
|
||||
char c = *msg++;
|
||||
if (!c)
|
||||
break;
|
||||
@ -485,31 +485,25 @@ static int is_rfc2047_special(char ch)
|
||||
return (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_'));
|
||||
}
|
||||
|
||||
static int add_rfc2047(char *buf, const char *line, int len,
|
||||
static void add_rfc2047(struct strbuf *sb, const char *line, int len,
|
||||
const char *encoding)
|
||||
{
|
||||
char *bp = buf;
|
||||
int i, needquote;
|
||||
char q_encoding[128];
|
||||
const char *q_encoding_fmt = "=?%s?q?";
|
||||
int i, last;
|
||||
|
||||
for (i = needquote = 0; !needquote && i < len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
int ch = line[i];
|
||||
if (non_ascii(ch))
|
||||
needquote++;
|
||||
if ((i + 1 < len) &&
|
||||
(ch == '=' && line[i+1] == '?'))
|
||||
needquote++;
|
||||
goto needquote;
|
||||
if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
|
||||
goto needquote;
|
||||
}
|
||||
if (!needquote)
|
||||
return sprintf(buf, "%.*s", len, line);
|
||||
strbuf_add(sb, line, len);
|
||||
return;
|
||||
|
||||
i = snprintf(q_encoding, sizeof(q_encoding), q_encoding_fmt, encoding);
|
||||
if (sizeof(q_encoding) < i)
|
||||
die("Insanely long encoding name %s", encoding);
|
||||
memcpy(bp, q_encoding, i);
|
||||
bp += i;
|
||||
for (i = 0; i < len; i++) {
|
||||
needquote:
|
||||
strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
|
||||
strbuf_addf(sb, "=?%s?q?", encoding);
|
||||
for (i = last = 0; i < len; i++) {
|
||||
unsigned ch = line[i] & 0xFF;
|
||||
/*
|
||||
* We encode ' ' using '=20' even though rfc2047
|
||||
@ -518,40 +512,30 @@ static int add_rfc2047(char *buf, const char *line, int len,
|
||||
* leave the underscore in place.
|
||||
*/
|
||||
if (is_rfc2047_special(ch) || ch == ' ') {
|
||||
sprintf(bp, "=%02X", ch);
|
||||
bp += 3;
|
||||
strbuf_add(sb, line + last, i - last);
|
||||
strbuf_addf(sb, "=%02X", ch);
|
||||
last = i + 1;
|
||||
}
|
||||
else
|
||||
*bp++ = ch;
|
||||
}
|
||||
memcpy(bp, "?=", 2);
|
||||
bp += 2;
|
||||
return bp - buf;
|
||||
strbuf_add(sb, line + last, len - last);
|
||||
strbuf_addstr(sb, "?=");
|
||||
}
|
||||
|
||||
static unsigned long bound_rfc2047(unsigned long len, const char *encoding)
|
||||
{
|
||||
/* upper bound of q encoded string of length 'len' */
|
||||
unsigned long elen = strlen(encoding);
|
||||
|
||||
return len * 3 + elen + 100;
|
||||
}
|
||||
|
||||
static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf,
|
||||
static void add_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,
|
||||
const char *line, enum date_mode dmode,
|
||||
const char *encoding)
|
||||
{
|
||||
char *date;
|
||||
int namelen;
|
||||
unsigned long time;
|
||||
int tz, ret;
|
||||
int tz;
|
||||
const char *filler = " ";
|
||||
|
||||
if (fmt == CMIT_FMT_ONELINE)
|
||||
return 0;
|
||||
return;
|
||||
date = strchr(line, '>');
|
||||
if (!date)
|
||||
return 0;
|
||||
return;
|
||||
namelen = ++date - line;
|
||||
time = strtoul(date, &date, 10);
|
||||
tz = strtol(date, NULL, 10);
|
||||
@ -560,42 +544,34 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf,
|
||||
char *name_tail = strchr(line, '<');
|
||||
int display_name_length;
|
||||
if (!name_tail)
|
||||
return 0;
|
||||
return;
|
||||
while (line < name_tail && isspace(name_tail[-1]))
|
||||
name_tail--;
|
||||
display_name_length = name_tail - line;
|
||||
filler = "";
|
||||
strcpy(buf, "From: ");
|
||||
ret = strlen(buf);
|
||||
ret += add_rfc2047(buf + ret, line, display_name_length,
|
||||
encoding);
|
||||
memcpy(buf + ret, name_tail, namelen - display_name_length);
|
||||
ret += namelen - display_name_length;
|
||||
buf[ret++] = '\n';
|
||||
}
|
||||
else {
|
||||
ret = sprintf(buf, "%s: %.*s%.*s\n", what,
|
||||
strbuf_addstr(sb, "From: ");
|
||||
add_rfc2047(sb, line, display_name_length, encoding);
|
||||
strbuf_add(sb, name_tail, namelen - display_name_length);
|
||||
strbuf_addch(sb, '\n');
|
||||
} else {
|
||||
strbuf_addf(sb, "%s: %.*s%.*s\n", what,
|
||||
(fmt == CMIT_FMT_FULLER) ? 4 : 0,
|
||||
filler, namelen, line);
|
||||
}
|
||||
switch (fmt) {
|
||||
case CMIT_FMT_MEDIUM:
|
||||
ret += sprintf(buf + ret, "Date: %s\n",
|
||||
show_date(time, tz, dmode));
|
||||
strbuf_addf(sb, "Date: %s\n", show_date(time, tz, dmode));
|
||||
break;
|
||||
case CMIT_FMT_EMAIL:
|
||||
ret += sprintf(buf + ret, "Date: %s\n",
|
||||
show_date(time, tz, DATE_RFC2822));
|
||||
strbuf_addf(sb, "Date: %s\n", show_date(time, tz, DATE_RFC2822));
|
||||
break;
|
||||
case CMIT_FMT_FULLER:
|
||||
ret += sprintf(buf + ret, "%sDate: %s\n", what,
|
||||
show_date(time, tz, dmode));
|
||||
strbuf_addf(sb, "%sDate: %s\n", what, show_date(time, tz, dmode));
|
||||
break;
|
||||
default:
|
||||
/* notin' */
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int is_empty_line(const char *line, int *len_p)
|
||||
@ -607,16 +583,16 @@ static int is_empty_line(const char *line, int *len_p)
|
||||
return !len;
|
||||
}
|
||||
|
||||
static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *commit, int abbrev)
|
||||
static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb,
|
||||
const struct commit *commit, int abbrev)
|
||||
{
|
||||
struct commit_list *parent = commit->parents;
|
||||
int offset;
|
||||
|
||||
if ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) ||
|
||||
!parent || !parent->next)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
offset = sprintf(buf, "Merge:");
|
||||
strbuf_addstr(sb, "Merge:");
|
||||
|
||||
while (parent) {
|
||||
struct commit *p = parent->item;
|
||||
@ -629,10 +605,9 @@ static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *com
|
||||
dots = (abbrev && strlen(hex) != 40) ? "..." : "";
|
||||
parent = parent->next;
|
||||
|
||||
offset += sprintf(buf + offset, " %s%s", hex, dots);
|
||||
strbuf_addf(sb, " %s%s", hex, dots);
|
||||
}
|
||||
buf[offset++] = '\n';
|
||||
return offset;
|
||||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
|
||||
static char *get_header(const struct commit *commit, const char *key)
|
||||
@ -653,11 +628,7 @@ static char *get_header(const struct commit *commit, const char *key)
|
||||
if (eol - line > key_len &&
|
||||
!strncmp(line, key, key_len) &&
|
||||
line[key_len] == ' ') {
|
||||
int len = eol - line - key_len;
|
||||
char *ret = xmalloc(len);
|
||||
memcpy(ret, line + key_len + 1, len - 1);
|
||||
ret[len - 1] = '\0';
|
||||
return ret;
|
||||
return xmemdupz(line + key_len + 1, eol - line - key_len - 1);
|
||||
}
|
||||
line = next;
|
||||
}
|
||||
@ -665,47 +636,34 @@ static char *get_header(const struct commit *commit, const char *key)
|
||||
|
||||
static char *replace_encoding_header(char *buf, const char *encoding)
|
||||
{
|
||||
char *encoding_header = strstr(buf, "\nencoding ");
|
||||
char *header_end = strstr(buf, "\n\n");
|
||||
char *end_of_encoding_header;
|
||||
int encoding_header_pos;
|
||||
int encoding_header_len;
|
||||
int new_len;
|
||||
int need_len;
|
||||
int buflen = strlen(buf) + 1;
|
||||
struct strbuf tmp;
|
||||
size_t start, len;
|
||||
char *cp = buf;
|
||||
|
||||
if (!header_end)
|
||||
header_end = buf + buflen;
|
||||
if (!encoding_header || encoding_header >= header_end)
|
||||
return buf;
|
||||
encoding_header++;
|
||||
end_of_encoding_header = strchr(encoding_header, '\n');
|
||||
if (!end_of_encoding_header)
|
||||
/* guess if there is an encoding header before a \n\n */
|
||||
while (strncmp(cp, "encoding ", strlen("encoding "))) {
|
||||
cp = strchr(cp, '\n');
|
||||
if (!cp || *++cp == '\n')
|
||||
return buf;
|
||||
}
|
||||
start = cp - buf;
|
||||
cp = strchr(cp, '\n');
|
||||
if (!cp)
|
||||
return buf; /* should not happen but be defensive */
|
||||
end_of_encoding_header++;
|
||||
|
||||
encoding_header_len = end_of_encoding_header - encoding_header;
|
||||
encoding_header_pos = encoding_header - buf;
|
||||
len = cp + 1 - (buf + start);
|
||||
|
||||
strbuf_init(&tmp, 0);
|
||||
strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1);
|
||||
if (is_encoding_utf8(encoding)) {
|
||||
/* we have re-coded to UTF-8; drop the header */
|
||||
memmove(encoding_header, end_of_encoding_header,
|
||||
buflen - (encoding_header_pos + encoding_header_len));
|
||||
return buf;
|
||||
strbuf_remove(&tmp, start, len);
|
||||
} else {
|
||||
/* just replaces XXXX in 'encoding XXXX\n' */
|
||||
strbuf_splice(&tmp, start + strlen("encoding "),
|
||||
len - strlen("encoding \n"),
|
||||
encoding, strlen(encoding));
|
||||
}
|
||||
new_len = strlen(encoding);
|
||||
need_len = new_len + strlen("encoding \n");
|
||||
if (encoding_header_len < need_len) {
|
||||
buf = xrealloc(buf, buflen + (need_len - encoding_header_len));
|
||||
encoding_header = buf + encoding_header_pos;
|
||||
end_of_encoding_header = encoding_header + encoding_header_len;
|
||||
}
|
||||
memmove(end_of_encoding_header + (need_len - encoding_header_len),
|
||||
end_of_encoding_header,
|
||||
buflen - (encoding_header_pos + encoding_header_len));
|
||||
memcpy(encoding_header + 9, encoding, strlen(encoding));
|
||||
encoding_header[9 + new_len] = '\n';
|
||||
return buf;
|
||||
return strbuf_detach(&tmp, NULL);
|
||||
}
|
||||
|
||||
static char *logmsg_reencode(const struct commit *commit,
|
||||
@ -747,7 +705,7 @@ static void fill_person(struct interp *table, const char *msg, int len)
|
||||
start = end + 1;
|
||||
while (end > 0 && isspace(msg[end - 1]))
|
||||
end--;
|
||||
table[0].value = xstrndup(msg, end);
|
||||
table[0].value = xmemdupz(msg, end);
|
||||
|
||||
if (start >= len)
|
||||
return;
|
||||
@ -759,7 +717,7 @@ static void fill_person(struct interp *table, const char *msg, int len)
|
||||
if (end >= len)
|
||||
return;
|
||||
|
||||
table[1].value = xstrndup(msg + start, end - start);
|
||||
table[1].value = xmemdupz(msg + start, end - start);
|
||||
|
||||
/* parse date */
|
||||
for (start = end + 1; start < len && isspace(msg[start]); start++)
|
||||
@ -770,7 +728,7 @@ static void fill_person(struct interp *table, const char *msg, int len)
|
||||
if (msg + start == ep)
|
||||
return;
|
||||
|
||||
table[5].value = xstrndup(msg + start, ep - (msg + start));
|
||||
table[5].value = xmemdupz(msg + start, ep - (msg + start));
|
||||
|
||||
/* parse tz */
|
||||
for (start = ep - msg + 1; start < len && isspace(msg[start]); start++)
|
||||
@ -787,8 +745,8 @@ static void fill_person(struct interp *table, const char *msg, int len)
|
||||
interp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601));
|
||||
}
|
||||
|
||||
long format_commit_message(const struct commit *commit, const void *format,
|
||||
char **buf_p, unsigned long *space_p)
|
||||
void format_commit_message(const struct commit *commit,
|
||||
const void *format, struct strbuf *sb)
|
||||
{
|
||||
struct interp table[] = {
|
||||
{ "%H" }, /* commit hash */
|
||||
@ -841,6 +799,7 @@ long format_commit_message(const struct commit *commit, const void *format,
|
||||
};
|
||||
struct commit_list *p;
|
||||
char parents[1024];
|
||||
unsigned long len;
|
||||
int i;
|
||||
enum { HEADER, SUBJECT, BODY } state;
|
||||
const char *msg = commit->buffer;
|
||||
@ -896,7 +855,7 @@ long format_commit_message(const struct commit *commit, const void *format,
|
||||
; /* do nothing */
|
||||
|
||||
if (state == SUBJECT) {
|
||||
table[ISUBJECT].value = xstrndup(msg + i, eol - i);
|
||||
table[ISUBJECT].value = xmemdupz(msg + i, eol - i);
|
||||
i = eol;
|
||||
}
|
||||
if (i == eol) {
|
||||
@ -912,7 +871,7 @@ long format_commit_message(const struct commit *commit, const void *format,
|
||||
msg + i + 10, eol - i - 10);
|
||||
else if (!prefixcmp(msg + i, "encoding "))
|
||||
table[IENCODING].value =
|
||||
xstrndup(msg + i + 9, eol - i - 9);
|
||||
xmemdupz(msg + i + 9, eol - i - 9);
|
||||
i = eol;
|
||||
}
|
||||
if (msg[i])
|
||||
@ -921,21 +880,15 @@ long format_commit_message(const struct commit *commit, const void *format,
|
||||
if (!table[i].value)
|
||||
interp_set_entry(table, i, "<unknown>");
|
||||
|
||||
do {
|
||||
char *buf = *buf_p;
|
||||
unsigned long space = *space_p;
|
||||
|
||||
space = interpolate(buf, space, format,
|
||||
table, ARRAY_SIZE(table));
|
||||
if (!space)
|
||||
break;
|
||||
buf = xrealloc(buf, space);
|
||||
*buf_p = buf;
|
||||
*space_p = space;
|
||||
} while (1);
|
||||
len = interpolate(sb->buf + sb->len, strbuf_avail(sb),
|
||||
format, table, ARRAY_SIZE(table));
|
||||
if (len > strbuf_avail(sb)) {
|
||||
strbuf_grow(sb, len);
|
||||
interpolate(sb->buf + sb->len, strbuf_avail(sb) + 1,
|
||||
format, table, ARRAY_SIZE(table));
|
||||
}
|
||||
strbuf_setlen(sb, sb->len + len);
|
||||
interp_clear_table(table, ARRAY_SIZE(table));
|
||||
|
||||
return strlen(*buf_p);
|
||||
}
|
||||
|
||||
static void pp_header(enum cmit_fmt fmt,
|
||||
@ -944,34 +897,24 @@ static void pp_header(enum cmit_fmt fmt,
|
||||
const char *encoding,
|
||||
const struct commit *commit,
|
||||
const char **msg_p,
|
||||
unsigned long *len_p,
|
||||
unsigned long *ofs_p,
|
||||
char **buf_p,
|
||||
unsigned long *space_p)
|
||||
struct strbuf *sb)
|
||||
{
|
||||
int parents_shown = 0;
|
||||
|
||||
for (;;) {
|
||||
const char *line = *msg_p;
|
||||
char *dst;
|
||||
int linelen = get_one_line(*msg_p, *len_p);
|
||||
unsigned long len;
|
||||
int linelen = get_one_line(*msg_p);
|
||||
|
||||
if (!linelen)
|
||||
return;
|
||||
*msg_p += linelen;
|
||||
*len_p -= linelen;
|
||||
|
||||
if (linelen == 1)
|
||||
/* End of header */
|
||||
return;
|
||||
|
||||
ALLOC_GROW(*buf_p, linelen + *ofs_p + 20, *space_p);
|
||||
dst = *buf_p + *ofs_p;
|
||||
|
||||
if (fmt == CMIT_FMT_RAW) {
|
||||
memcpy(dst, line, linelen);
|
||||
*ofs_p += linelen;
|
||||
strbuf_add(sb, line, linelen);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -989,10 +932,8 @@ static void pp_header(enum cmit_fmt fmt,
|
||||
parent = parent->next, num++)
|
||||
;
|
||||
/* with enough slop */
|
||||
num = *ofs_p + num * 50 + 20;
|
||||
ALLOC_GROW(*buf_p, num, *space_p);
|
||||
dst = *buf_p + *ofs_p;
|
||||
*ofs_p += add_merge_info(fmt, dst, commit, abbrev);
|
||||
strbuf_grow(sb, num * 50 + 20);
|
||||
add_merge_info(fmt, sb, commit, abbrev);
|
||||
parents_shown = 1;
|
||||
}
|
||||
|
||||
@ -1002,129 +943,82 @@ static void pp_header(enum cmit_fmt fmt,
|
||||
* FULLER shows both authors and dates.
|
||||
*/
|
||||
if (!memcmp(line, "author ", 7)) {
|
||||
len = linelen;
|
||||
if (fmt == CMIT_FMT_EMAIL)
|
||||
len = bound_rfc2047(linelen, encoding);
|
||||
ALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p);
|
||||
dst = *buf_p + *ofs_p;
|
||||
*ofs_p += add_user_info("Author", fmt, dst,
|
||||
line + 7, dmode, encoding);
|
||||
strbuf_grow(sb, linelen + 80);
|
||||
add_user_info("Author", fmt, sb, line + 7, dmode, encoding);
|
||||
}
|
||||
|
||||
if (!memcmp(line, "committer ", 10) &&
|
||||
(fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) {
|
||||
len = linelen;
|
||||
if (fmt == CMIT_FMT_EMAIL)
|
||||
len = bound_rfc2047(linelen, encoding);
|
||||
ALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p);
|
||||
dst = *buf_p + *ofs_p;
|
||||
*ofs_p += add_user_info("Commit", fmt, dst,
|
||||
line + 10, dmode, encoding);
|
||||
strbuf_grow(sb, linelen + 80);
|
||||
add_user_info("Commit", fmt, sb, line + 10, dmode, encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pp_title_line(enum cmit_fmt fmt,
|
||||
const char **msg_p,
|
||||
unsigned long *len_p,
|
||||
unsigned long *ofs_p,
|
||||
char **buf_p,
|
||||
unsigned long *space_p,
|
||||
int indent,
|
||||
struct strbuf *sb,
|
||||
const char *subject,
|
||||
const char *after_subject,
|
||||
const char *encoding,
|
||||
int plain_non_ascii)
|
||||
{
|
||||
char *title;
|
||||
unsigned long title_alloc, title_len;
|
||||
unsigned long len;
|
||||
struct strbuf title;
|
||||
|
||||
strbuf_init(&title, 80);
|
||||
|
||||
title_len = 0;
|
||||
title_alloc = 80;
|
||||
title = xmalloc(title_alloc);
|
||||
for (;;) {
|
||||
const char *line = *msg_p;
|
||||
int linelen = get_one_line(line, *len_p);
|
||||
*msg_p += linelen;
|
||||
*len_p -= linelen;
|
||||
int linelen = get_one_line(line);
|
||||
|
||||
*msg_p += linelen;
|
||||
if (!linelen || is_empty_line(line, &linelen))
|
||||
break;
|
||||
|
||||
if (title_alloc <= title_len + linelen + 2) {
|
||||
title_alloc = title_len + linelen + 80;
|
||||
title = xrealloc(title, title_alloc);
|
||||
}
|
||||
len = 0;
|
||||
if (title_len) {
|
||||
strbuf_grow(&title, linelen + 2);
|
||||
if (title.len) {
|
||||
if (fmt == CMIT_FMT_EMAIL) {
|
||||
len++;
|
||||
title[title_len++] = '\n';
|
||||
strbuf_addch(&title, '\n');
|
||||
}
|
||||
len++;
|
||||
title[title_len++] = ' ';
|
||||
strbuf_addch(&title, ' ');
|
||||
}
|
||||
memcpy(title + title_len, line, linelen);
|
||||
title_len += linelen;
|
||||
strbuf_add(&title, line, linelen);
|
||||
}
|
||||
|
||||
/* Enough slop for the MIME header and rfc2047 */
|
||||
len = bound_rfc2047(title_len, encoding)+ 1000;
|
||||
if (subject)
|
||||
len += strlen(subject);
|
||||
if (after_subject)
|
||||
len += strlen(after_subject);
|
||||
if (encoding)
|
||||
len += strlen(encoding);
|
||||
ALLOC_GROW(*buf_p, title_len + *ofs_p + len, *space_p);
|
||||
|
||||
strbuf_grow(sb, title.len + 1024);
|
||||
if (subject) {
|
||||
len = strlen(subject);
|
||||
memcpy(*buf_p + *ofs_p, subject, len);
|
||||
*ofs_p += len;
|
||||
*ofs_p += add_rfc2047(*buf_p + *ofs_p,
|
||||
title, title_len, encoding);
|
||||
strbuf_addstr(sb, subject);
|
||||
add_rfc2047(sb, title.buf, title.len, encoding);
|
||||
} else {
|
||||
memcpy(*buf_p + *ofs_p, title, title_len);
|
||||
*ofs_p += title_len;
|
||||
strbuf_addbuf(sb, &title);
|
||||
}
|
||||
(*buf_p)[(*ofs_p)++] = '\n';
|
||||
strbuf_addch(sb, '\n');
|
||||
|
||||
if (plain_non_ascii) {
|
||||
const char *header_fmt =
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=%s\n"
|
||||
"Content-Transfer-Encoding: 8bit\n";
|
||||
*ofs_p += snprintf(*buf_p + *ofs_p,
|
||||
*space_p - *ofs_p,
|
||||
header_fmt, encoding);
|
||||
strbuf_addf(sb, header_fmt, encoding);
|
||||
}
|
||||
if (after_subject) {
|
||||
len = strlen(after_subject);
|
||||
memcpy(*buf_p + *ofs_p, after_subject, len);
|
||||
*ofs_p += len;
|
||||
strbuf_addstr(sb, after_subject);
|
||||
}
|
||||
free(title);
|
||||
if (fmt == CMIT_FMT_EMAIL) {
|
||||
ALLOC_GROW(*buf_p, *ofs_p + 20, *space_p);
|
||||
(*buf_p)[(*ofs_p)++] = '\n';
|
||||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
strbuf_release(&title);
|
||||
}
|
||||
|
||||
static void pp_remainder(enum cmit_fmt fmt,
|
||||
const char **msg_p,
|
||||
unsigned long *len_p,
|
||||
unsigned long *ofs_p,
|
||||
char **buf_p,
|
||||
unsigned long *space_p,
|
||||
struct strbuf *sb,
|
||||
int indent)
|
||||
{
|
||||
int first = 1;
|
||||
for (;;) {
|
||||
const char *line = *msg_p;
|
||||
int linelen = get_one_line(line, *len_p);
|
||||
int linelen = get_one_line(line);
|
||||
*msg_p += linelen;
|
||||
*len_p -= linelen;
|
||||
|
||||
if (!linelen)
|
||||
break;
|
||||
@ -1137,36 +1031,32 @@ static void pp_remainder(enum cmit_fmt fmt,
|
||||
}
|
||||
first = 0;
|
||||
|
||||
ALLOC_GROW(*buf_p, *ofs_p + linelen + indent + 20, *space_p);
|
||||
strbuf_grow(sb, linelen + indent + 20);
|
||||
if (indent) {
|
||||
memset(*buf_p + *ofs_p, ' ', indent);
|
||||
*ofs_p += indent;
|
||||
memset(sb->buf + sb->len, ' ', indent);
|
||||
strbuf_setlen(sb, sb->len + indent);
|
||||
}
|
||||
memcpy(*buf_p + *ofs_p, line, linelen);
|
||||
*ofs_p += linelen;
|
||||
(*buf_p)[(*ofs_p)++] = '\n';
|
||||
strbuf_add(sb, line, linelen);
|
||||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long pretty_print_commit(enum cmit_fmt fmt,
|
||||
const struct commit *commit,
|
||||
unsigned long len,
|
||||
char **buf_p, unsigned long *space_p,
|
||||
int abbrev, const char *subject,
|
||||
const char *after_subject,
|
||||
void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
|
||||
struct strbuf *sb, int abbrev,
|
||||
const char *subject, const char *after_subject,
|
||||
enum date_mode dmode)
|
||||
{
|
||||
unsigned long offset = 0;
|
||||
unsigned long beginning_of_body;
|
||||
int indent = 4;
|
||||
const char *msg = commit->buffer;
|
||||
int plain_non_ascii = 0;
|
||||
char *reencoded;
|
||||
const char *encoding;
|
||||
char *buf;
|
||||
|
||||
if (fmt == CMIT_FMT_USERFORMAT)
|
||||
return format_commit_message(commit, user_format, buf_p, space_p);
|
||||
if (fmt == CMIT_FMT_USERFORMAT) {
|
||||
format_commit_message(commit, user_format, sb);
|
||||
return;
|
||||
}
|
||||
|
||||
encoding = (git_log_output_encoding
|
||||
? git_log_output_encoding
|
||||
@ -1176,7 +1066,6 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
|
||||
reencoded = logmsg_reencode(commit, encoding);
|
||||
if (reencoded) {
|
||||
msg = reencoded;
|
||||
len = strlen(reencoded);
|
||||
}
|
||||
|
||||
if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
|
||||
@ -1191,14 +1080,13 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
|
||||
if (fmt == CMIT_FMT_EMAIL && !after_subject) {
|
||||
int i, ch, in_body;
|
||||
|
||||
for (in_body = i = 0; (ch = msg[i]) && i < len; i++) {
|
||||
for (in_body = i = 0; (ch = msg[i]); i++) {
|
||||
if (!in_body) {
|
||||
/* author could be non 7-bit ASCII but
|
||||
* the log may be so; skip over the
|
||||
* header part first.
|
||||
*/
|
||||
if (ch == '\n' &&
|
||||
i + 1 < len && msg[i+1] == '\n')
|
||||
if (ch == '\n' && msg[i+1] == '\n')
|
||||
in_body = 1;
|
||||
}
|
||||
else if (non_ascii(ch)) {
|
||||
@ -1208,59 +1096,44 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
|
||||
}
|
||||
}
|
||||
|
||||
pp_header(fmt, abbrev, dmode, encoding,
|
||||
commit, &msg, &len,
|
||||
&offset, buf_p, space_p);
|
||||
pp_header(fmt, abbrev, dmode, encoding, commit, &msg, sb);
|
||||
if (fmt != CMIT_FMT_ONELINE && !subject) {
|
||||
ALLOC_GROW(*buf_p, offset + 20, *space_p);
|
||||
(*buf_p)[offset++] = '\n';
|
||||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
|
||||
/* Skip excess blank lines at the beginning of body, if any... */
|
||||
for (;;) {
|
||||
int linelen = get_one_line(msg, len);
|
||||
int linelen = get_one_line(msg);
|
||||
int ll = linelen;
|
||||
if (!linelen)
|
||||
break;
|
||||
if (!is_empty_line(msg, &ll))
|
||||
break;
|
||||
msg += linelen;
|
||||
len -= linelen;
|
||||
}
|
||||
|
||||
/* These formats treat the title line specially. */
|
||||
if (fmt == CMIT_FMT_ONELINE
|
||||
|| fmt == CMIT_FMT_EMAIL)
|
||||
pp_title_line(fmt, &msg, &len, &offset,
|
||||
buf_p, space_p, indent,
|
||||
subject, after_subject, encoding,
|
||||
plain_non_ascii);
|
||||
if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
|
||||
pp_title_line(fmt, &msg, sb, subject,
|
||||
after_subject, encoding, plain_non_ascii);
|
||||
|
||||
beginning_of_body = offset;
|
||||
beginning_of_body = sb->len;
|
||||
if (fmt != CMIT_FMT_ONELINE)
|
||||
pp_remainder(fmt, &msg, &len, &offset,
|
||||
buf_p, space_p, indent);
|
||||
|
||||
while (offset && isspace((*buf_p)[offset-1]))
|
||||
offset--;
|
||||
|
||||
ALLOC_GROW(*buf_p, offset + 20, *space_p);
|
||||
buf = *buf_p;
|
||||
pp_remainder(fmt, &msg, sb, indent);
|
||||
strbuf_rtrim(sb);
|
||||
|
||||
/* Make sure there is an EOLN for the non-oneline case */
|
||||
if (fmt != CMIT_FMT_ONELINE)
|
||||
buf[offset++] = '\n';
|
||||
strbuf_addch(sb, '\n');
|
||||
|
||||
/*
|
||||
* The caller may append additional body text in e-mail
|
||||
* format. Make sure we did not strip the blank line
|
||||
* between the header and the body.
|
||||
*/
|
||||
if (fmt == CMIT_FMT_EMAIL && offset <= beginning_of_body)
|
||||
buf[offset++] = '\n';
|
||||
buf[offset] = '\0';
|
||||
if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
|
||||
strbuf_addch(sb, '\n');
|
||||
free(reencoded);
|
||||
return offset;
|
||||
}
|
||||
|
||||
struct commit *pop_commit(struct commit_list **stack)
|
||||
@ -1339,12 +1212,12 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
|
||||
next=next->next;
|
||||
}
|
||||
/*
|
||||
* find the tips
|
||||
*
|
||||
* tips are nodes not reachable from any other node in the list
|
||||
*
|
||||
* the tips serve as a starting set for the work queue.
|
||||
*/
|
||||
* find the tips
|
||||
*
|
||||
* tips are nodes not reachable from any other node in the list
|
||||
*
|
||||
* the tips serve as a starting set for the work queue.
|
||||
*/
|
||||
next=*list;
|
||||
insert = &work;
|
||||
while (next) {
|
||||
@ -1371,9 +1244,9 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
|
||||
if (pn) {
|
||||
/*
|
||||
* parents are only enqueued for emission
|
||||
* when all their children have been emitted thereby
|
||||
* guaranteeing topological order.
|
||||
*/
|
||||
* when all their children have been emitted thereby
|
||||
* guaranteeing topological order.
|
||||
*/
|
||||
pn->indegree--;
|
||||
if (!pn->indegree) {
|
||||
if (!lifo)
|
||||
@ -1385,9 +1258,9 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
|
||||
parents=parents->next;
|
||||
}
|
||||
/*
|
||||
* work_item is a commit all of whose children
|
||||
* have already been emitted. we can emit it now.
|
||||
*/
|
||||
* work_item is a commit all of whose children
|
||||
* have already been emitted. we can emit it now.
|
||||
*/
|
||||
*pptr = work_node->list_item;
|
||||
pptr = &(*pptr)->next;
|
||||
*pptr = NULL;
|
||||
@ -1483,8 +1356,7 @@ static struct commit_list *merge_bases(struct commit *one, struct commit *two)
|
||||
}
|
||||
|
||||
struct commit_list *get_merge_bases(struct commit *one,
|
||||
struct commit *two,
|
||||
int cleanup)
|
||||
struct commit *two, int cleanup)
|
||||
{
|
||||
struct commit_list *list;
|
||||
struct commit **rslt;
|
||||
|
9
commit.h
9
commit.h
@ -3,6 +3,7 @@
|
||||
|
||||
#include "object.h"
|
||||
#include "tree.h"
|
||||
#include "strbuf.h"
|
||||
#include "decorate.h"
|
||||
|
||||
struct commit_list {
|
||||
@ -61,8 +62,12 @@ enum cmit_fmt {
|
||||
};
|
||||
|
||||
extern enum cmit_fmt get_commit_format(const char *arg);
|
||||
extern long format_commit_message(const struct commit *commit, const void *template, char **buf_p, unsigned long *space_p);
|
||||
extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode);
|
||||
extern void format_commit_message(const struct commit *commit,
|
||||
const void *format, struct strbuf *sb);
|
||||
extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
|
||||
struct strbuf *,
|
||||
int abbrev, const char *subject,
|
||||
const char *after_subject, enum date_mode);
|
||||
|
||||
/** Removes the first commit from a list sorted by date, and adds all
|
||||
* of its parents.
|
||||
|
25
connect.c
25
connect.c
@ -393,9 +393,7 @@ static int git_proxy_command_options(const char *var, const char *value)
|
||||
if (matchlen == 4 &&
|
||||
!memcmp(value, "none", 4))
|
||||
matchlen = 0;
|
||||
git_proxy_command = xmalloc(matchlen + 1);
|
||||
memcpy(git_proxy_command, value, matchlen);
|
||||
git_proxy_command[matchlen] = 0;
|
||||
git_proxy_command = xmemdupz(value, matchlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -579,16 +577,13 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
|
||||
if (pid < 0)
|
||||
die("unable to fork");
|
||||
if (!pid) {
|
||||
char command[MAX_CMD_LEN];
|
||||
char *posn = command;
|
||||
int size = MAX_CMD_LEN;
|
||||
int of = 0;
|
||||
struct strbuf cmd;
|
||||
|
||||
of |= add_to_string(&posn, &size, prog, 0);
|
||||
of |= add_to_string(&posn, &size, " ", 0);
|
||||
of |= add_to_string(&posn, &size, path, 1);
|
||||
|
||||
if (of)
|
||||
strbuf_init(&cmd, MAX_CMD_LEN);
|
||||
strbuf_addstr(&cmd, prog);
|
||||
strbuf_addch(&cmd, ' ');
|
||||
sq_quote_buf(&cmd, path);
|
||||
if (cmd.len >= MAX_CMD_LEN)
|
||||
die("command line too long");
|
||||
|
||||
dup2(pipefd[1][0], 0);
|
||||
@ -608,10 +603,10 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
|
||||
ssh_basename++;
|
||||
|
||||
if (!port)
|
||||
execlp(ssh, ssh_basename, host, command, NULL);
|
||||
execlp(ssh, ssh_basename, host, cmd.buf, NULL);
|
||||
else
|
||||
execlp(ssh, ssh_basename, "-p", port, host,
|
||||
command, NULL);
|
||||
cmd.buf, NULL);
|
||||
}
|
||||
else {
|
||||
unsetenv(ALTERNATE_DB_ENVIRONMENT);
|
||||
@ -620,7 +615,7 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
|
||||
unsetenv(GIT_WORK_TREE_ENVIRONMENT);
|
||||
unsetenv(GRAFT_ENVIRONMENT);
|
||||
unsetenv(INDEX_ENVIRONMENT);
|
||||
execlp("sh", "sh", "-c", command, NULL);
|
||||
execlp("sh", "sh", "-c", cmd.buf, NULL);
|
||||
}
|
||||
die("exec failed");
|
||||
}
|
||||
|
412
convert.c
412
convert.c
@ -80,24 +80,19 @@ static int is_binary(unsigned long size, struct text_stat *stats)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep, int action)
|
||||
static int crlf_to_git(const char *path, const char *src, size_t len,
|
||||
struct strbuf *buf, int action)
|
||||
{
|
||||
char *buffer, *dst;
|
||||
unsigned long size, nsize;
|
||||
struct text_stat stats;
|
||||
char *dst;
|
||||
|
||||
if ((action == CRLF_BINARY) || !auto_crlf)
|
||||
return NULL;
|
||||
|
||||
size = *sizep;
|
||||
if (!size)
|
||||
return NULL;
|
||||
|
||||
gather_stats(src, size, &stats);
|
||||
if ((action == CRLF_BINARY) || !auto_crlf || !len)
|
||||
return 0;
|
||||
|
||||
gather_stats(src, len, &stats);
|
||||
/* No CR? Nothing to convert, regardless. */
|
||||
if (!stats.cr)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
if (action == CRLF_GUESS) {
|
||||
/*
|
||||
@ -106,24 +101,17 @@ static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep
|
||||
* stuff?
|
||||
*/
|
||||
if (stats.cr != stats.crlf)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* And add some heuristics for binary vs text, of course...
|
||||
*/
|
||||
if (is_binary(size, &stats))
|
||||
return NULL;
|
||||
if (is_binary(len, &stats))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok, allocate a new buffer, fill it in, and return it
|
||||
* to let the caller know that we switched buffers.
|
||||
*/
|
||||
nsize = size - stats.crlf;
|
||||
buffer = xmalloc(nsize);
|
||||
*sizep = nsize;
|
||||
|
||||
dst = buffer;
|
||||
strbuf_grow(buf, len);
|
||||
dst = buf->buf;
|
||||
if (action == CRLF_GUESS) {
|
||||
/*
|
||||
* If we guessed, we already know we rejected a file with
|
||||
@ -134,71 +122,72 @@ static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep
|
||||
unsigned char c = *src++;
|
||||
if (c != '\r')
|
||||
*dst++ = c;
|
||||
} while (--size);
|
||||
} while (--len);
|
||||
} else {
|
||||
do {
|
||||
unsigned char c = *src++;
|
||||
if (! (c == '\r' && (1 < size && *src == '\n')))
|
||||
if (! (c == '\r' && (1 < len && *src == '\n')))
|
||||
*dst++ = c;
|
||||
} while (--size);
|
||||
} while (--len);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
strbuf_setlen(buf, dst - buf->buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *crlf_to_worktree(const char *path, const char *src, unsigned long *sizep, int action)
|
||||
static int crlf_to_worktree(const char *path, const char *src, size_t len,
|
||||
struct strbuf *buf, int action)
|
||||
{
|
||||
char *buffer, *dst;
|
||||
unsigned long size, nsize;
|
||||
char *to_free = NULL;
|
||||
struct text_stat stats;
|
||||
unsigned char last;
|
||||
|
||||
if ((action == CRLF_BINARY) || (action == CRLF_INPUT) ||
|
||||
auto_crlf <= 0)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
size = *sizep;
|
||||
if (!size)
|
||||
return NULL;
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
gather_stats(src, size, &stats);
|
||||
gather_stats(src, len, &stats);
|
||||
|
||||
/* No LF? Nothing to convert, regardless. */
|
||||
if (!stats.lf)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
/* Was it already in CRLF format? */
|
||||
if (stats.lf == stats.crlf)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
if (action == CRLF_GUESS) {
|
||||
/* If we have any bare CR characters, we're not going to touch it */
|
||||
if (stats.cr != stats.crlf)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
if (is_binary(size, &stats))
|
||||
return NULL;
|
||||
if (is_binary(len, &stats))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok, allocate a new buffer, fill it in, and return it
|
||||
* to let the caller know that we switched buffers.
|
||||
*/
|
||||
nsize = size + stats.lf - stats.crlf;
|
||||
buffer = xmalloc(nsize);
|
||||
*sizep = nsize;
|
||||
last = 0;
|
||||
/* are we "faking" in place editing ? */
|
||||
if (src == buf->buf)
|
||||
to_free = strbuf_detach(buf, NULL);
|
||||
|
||||
dst = buffer;
|
||||
do {
|
||||
unsigned char c = *src++;
|
||||
if (c == '\n' && last != '\r')
|
||||
*dst++ = '\r';
|
||||
*dst++ = c;
|
||||
last = c;
|
||||
} while (--size);
|
||||
strbuf_grow(buf, len + stats.lf - stats.crlf);
|
||||
for (;;) {
|
||||
const char *nl = memchr(src, '\n', len);
|
||||
if (!nl)
|
||||
break;
|
||||
if (nl > src && nl[-1] == '\r') {
|
||||
strbuf_add(buf, src, nl + 1 - src);
|
||||
} else {
|
||||
strbuf_add(buf, src, nl - src);
|
||||
strbuf_addstr(buf, "\r\n");
|
||||
}
|
||||
len -= nl + 1 - src;
|
||||
src = nl + 1;
|
||||
}
|
||||
strbuf_add(buf, src, len);
|
||||
|
||||
return buffer;
|
||||
free(to_free);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int filter_buffer(const char *path, const char *src,
|
||||
@ -246,8 +235,8 @@ static int filter_buffer(const char *path, const char *src,
|
||||
return (write_err || status);
|
||||
}
|
||||
|
||||
static char *apply_filter(const char *path, const char *src,
|
||||
unsigned long *sizep, const char *cmd)
|
||||
static int apply_filter(const char *path, const char *src, size_t len,
|
||||
struct strbuf *dst, const char *cmd)
|
||||
{
|
||||
/*
|
||||
* Create a pipeline to have the command filter the buffer's
|
||||
@ -255,21 +244,19 @@ static char *apply_filter(const char *path, const char *src,
|
||||
*
|
||||
* (child --> cmd) --> us
|
||||
*/
|
||||
const int SLOP = 4096;
|
||||
int pipe_feed[2];
|
||||
int status;
|
||||
char *dst;
|
||||
unsigned long dstsize, dstalloc;
|
||||
int status, ret = 1;
|
||||
struct child_process child_process;
|
||||
struct strbuf nbuf;
|
||||
|
||||
if (!cmd)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
memset(&child_process, 0, sizeof(child_process));
|
||||
|
||||
if (pipe(pipe_feed) < 0) {
|
||||
error("cannot create pipe to run external filter %s", cmd);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fflush(NULL);
|
||||
@ -278,54 +265,37 @@ static char *apply_filter(const char *path, const char *src,
|
||||
error("cannot fork to run external filter %s", cmd);
|
||||
close(pipe_feed[0]);
|
||||
close(pipe_feed[1]);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (!child_process.pid) {
|
||||
dup2(pipe_feed[1], 1);
|
||||
close(pipe_feed[0]);
|
||||
close(pipe_feed[1]);
|
||||
exit(filter_buffer(path, src, *sizep, cmd));
|
||||
exit(filter_buffer(path, src, len, cmd));
|
||||
}
|
||||
close(pipe_feed[1]);
|
||||
|
||||
dstalloc = *sizep;
|
||||
dst = xmalloc(dstalloc);
|
||||
dstsize = 0;
|
||||
|
||||
while (1) {
|
||||
ssize_t numread = xread(pipe_feed[0], dst + dstsize,
|
||||
dstalloc - dstsize);
|
||||
|
||||
if (numread <= 0) {
|
||||
if (!numread)
|
||||
break;
|
||||
error("read from external filter %s failed", cmd);
|
||||
free(dst);
|
||||
dst = NULL;
|
||||
break;
|
||||
}
|
||||
dstsize += numread;
|
||||
if (dstalloc <= dstsize + SLOP) {
|
||||
dstalloc = dstsize + SLOP;
|
||||
dst = xrealloc(dst, dstalloc);
|
||||
}
|
||||
strbuf_init(&nbuf, 0);
|
||||
if (strbuf_read(&nbuf, pipe_feed[0], len) < 0) {
|
||||
error("read from external filter %s failed", cmd);
|
||||
ret = 0;
|
||||
}
|
||||
if (close(pipe_feed[0])) {
|
||||
error("read from external filter %s failed", cmd);
|
||||
free(dst);
|
||||
dst = NULL;
|
||||
ret = error("read from external filter %s failed", cmd);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
status = finish_command(&child_process);
|
||||
if (status) {
|
||||
error("external filter %s failed %d", cmd, -status);
|
||||
free(dst);
|
||||
dst = NULL;
|
||||
ret = error("external filter %s failed %d", cmd, -status);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (dst)
|
||||
*sizep = dstsize;
|
||||
return dst;
|
||||
if (ret) {
|
||||
*dst = nbuf;
|
||||
} else {
|
||||
strbuf_release(&nbuf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct convert_driver {
|
||||
@ -353,13 +323,8 @@ static int read_convert_config(const char *var, const char *value)
|
||||
if (!strncmp(drv->name, name, namelen) && !drv->name[namelen])
|
||||
break;
|
||||
if (!drv) {
|
||||
char *namebuf;
|
||||
drv = xcalloc(1, sizeof(struct convert_driver));
|
||||
namebuf = xmalloc(namelen + 1);
|
||||
memcpy(namebuf, name, namelen);
|
||||
namebuf[namelen] = 0;
|
||||
drv->name = namebuf;
|
||||
drv->next = NULL;
|
||||
drv->name = xmemdupz(name, namelen);
|
||||
*user_convert_tail = drv;
|
||||
user_convert_tail = &(drv->next);
|
||||
}
|
||||
@ -449,137 +414,104 @@ static int count_ident(const char *cp, unsigned long size)
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static char *ident_to_git(const char *path, const char *src, unsigned long *sizep, int ident)
|
||||
static int ident_to_git(const char *path, const char *src, size_t len,
|
||||
struct strbuf *buf, int ident)
|
||||
{
|
||||
int cnt;
|
||||
unsigned long size;
|
||||
char *dst, *buf;
|
||||
char *dst, *dollar;
|
||||
|
||||
if (!ident)
|
||||
return NULL;
|
||||
size = *sizep;
|
||||
cnt = count_ident(src, size);
|
||||
if (!cnt)
|
||||
return NULL;
|
||||
buf = xmalloc(size);
|
||||
if (!ident || !count_ident(src, len))
|
||||
return 0;
|
||||
|
||||
for (dst = buf; size; size--) {
|
||||
char ch = *src++;
|
||||
*dst++ = ch;
|
||||
if ((ch == '$') && (3 <= size) &&
|
||||
!memcmp("Id:", src, 3)) {
|
||||
unsigned long rem = size - 3;
|
||||
const char *cp = src + 3;
|
||||
do {
|
||||
ch = *cp++;
|
||||
if (ch == '$')
|
||||
break;
|
||||
rem--;
|
||||
} while (rem);
|
||||
if (!rem)
|
||||
continue;
|
||||
strbuf_grow(buf, len);
|
||||
dst = buf->buf;
|
||||
for (;;) {
|
||||
dollar = memchr(src, '$', len);
|
||||
if (!dollar)
|
||||
break;
|
||||
memcpy(dst, src, dollar + 1 - src);
|
||||
dst += dollar + 1 - src;
|
||||
len -= dollar + 1 - src;
|
||||
src = dollar + 1;
|
||||
|
||||
if (len > 3 && !memcmp(src, "Id:", 3)) {
|
||||
dollar = memchr(src + 3, '$', len - 3);
|
||||
if (!dollar)
|
||||
break;
|
||||
memcpy(dst, "Id$", 3);
|
||||
dst += 3;
|
||||
size -= (cp - src);
|
||||
src = cp;
|
||||
len -= dollar + 1 - src;
|
||||
src = dollar + 1;
|
||||
}
|
||||
}
|
||||
|
||||
*sizep = dst - buf;
|
||||
return buf;
|
||||
memcpy(dst, src, len);
|
||||
strbuf_setlen(buf, dst + len - buf->buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *ident_to_worktree(const char *path, const char *src, unsigned long *sizep, int ident)
|
||||
static int ident_to_worktree(const char *path, const char *src, size_t len,
|
||||
struct strbuf *buf, int ident)
|
||||
{
|
||||
int cnt;
|
||||
unsigned long size;
|
||||
char *dst, *buf;
|
||||
unsigned char sha1[20];
|
||||
char *to_free = NULL, *dollar;
|
||||
int cnt;
|
||||
|
||||
if (!ident)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
size = *sizep;
|
||||
cnt = count_ident(src, size);
|
||||
cnt = count_ident(src, len);
|
||||
if (!cnt)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
hash_sha1_file(src, size, "blob", sha1);
|
||||
buf = xmalloc(size + cnt * 43);
|
||||
/* are we "faking" in place editing ? */
|
||||
if (src == buf->buf)
|
||||
to_free = strbuf_detach(buf, NULL);
|
||||
hash_sha1_file(src, len, "blob", sha1);
|
||||
|
||||
for (dst = buf; size; size--) {
|
||||
const char *cp;
|
||||
/* Fetch next source character, move the pointer on */
|
||||
char ch = *src++;
|
||||
/* Copy the current character to the destination */
|
||||
*dst++ = ch;
|
||||
/* If the current character is "$" or there are less than three
|
||||
* remaining bytes or the two bytes following this one are not
|
||||
* "Id", then simply read the next character */
|
||||
if ((ch != '$') || (size < 3) || memcmp("Id", src, 2))
|
||||
strbuf_grow(buf, len + cnt * 43);
|
||||
for (;;) {
|
||||
/* step 1: run to the next '$' */
|
||||
dollar = memchr(src, '$', len);
|
||||
if (!dollar)
|
||||
break;
|
||||
strbuf_add(buf, src, dollar + 1 - src);
|
||||
len -= dollar + 1 - src;
|
||||
src = dollar + 1;
|
||||
|
||||
/* step 2: does it looks like a bit like Id:xxx$ or Id$ ? */
|
||||
if (len < 3 || memcmp("Id", src, 2))
|
||||
continue;
|
||||
/*
|
||||
* Here when
|
||||
* - There are more than 2 bytes remaining
|
||||
* - The current three bytes are "$Id"
|
||||
* with
|
||||
* - ch == "$"
|
||||
* - src[0] == "I"
|
||||
*/
|
||||
|
||||
/*
|
||||
* It's possible that an expanded Id has crept its way into the
|
||||
* repository, we cope with that by stripping the expansion out
|
||||
*/
|
||||
if (src[2] == ':') {
|
||||
/* Expanded keywords have "$Id:" at the front */
|
||||
|
||||
/* discard up to but not including the closing $ */
|
||||
unsigned long rem = size - 3;
|
||||
/* Point at first byte after the ":" */
|
||||
cp = src + 3;
|
||||
/* step 3: skip over Id$ or Id:xxxxx$ */
|
||||
if (src[2] == '$') {
|
||||
src += 3;
|
||||
len -= 3;
|
||||
} else if (src[2] == ':') {
|
||||
/*
|
||||
* Throw away characters until either
|
||||
* - we reach a "$"
|
||||
* - we run out of bytes (rem == 0)
|
||||
* It's possible that an expanded Id has crept its way into the
|
||||
* repository, we cope with that by stripping the expansion out
|
||||
*/
|
||||
do {
|
||||
ch = *cp;
|
||||
if (ch == '$')
|
||||
break;
|
||||
cp++;
|
||||
rem--;
|
||||
} while (rem);
|
||||
/* If the above finished because it ran out of characters, then
|
||||
* this is an incomplete keyword, so don't run the expansion */
|
||||
if (!rem)
|
||||
continue;
|
||||
} else if (src[2] == '$')
|
||||
cp = src + 2;
|
||||
else
|
||||
/* Anything other than "$Id:XXX$" or $Id$ and we skip the
|
||||
* expansion */
|
||||
dollar = memchr(src + 3, '$', len - 3);
|
||||
if (!dollar) {
|
||||
/* incomplete keyword, no more '$', so just quit the loop */
|
||||
break;
|
||||
}
|
||||
|
||||
len -= dollar + 1 - src;
|
||||
src = dollar + 1;
|
||||
} else {
|
||||
/* it wasn't a "Id$" or "Id:xxxx$" */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* cp is now pointing at the last $ of the keyword */
|
||||
|
||||
memcpy(dst, "Id: ", 4);
|
||||
dst += 4;
|
||||
memcpy(dst, sha1_to_hex(sha1), 40);
|
||||
dst += 40;
|
||||
*dst++ = ' ';
|
||||
|
||||
/* Adjust for the characters we've discarded */
|
||||
size -= (cp - src);
|
||||
src = cp;
|
||||
|
||||
/* Copy the final "$" */
|
||||
*dst++ = *src++;
|
||||
size--;
|
||||
/* step 4: substitute */
|
||||
strbuf_addstr(buf, "Id: ");
|
||||
strbuf_add(buf, sha1_to_hex(sha1), 40);
|
||||
strbuf_addstr(buf, " $");
|
||||
}
|
||||
strbuf_add(buf, src, len);
|
||||
|
||||
*sizep = dst - buf;
|
||||
return buf;
|
||||
free(to_free);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int git_path_check_crlf(const char *path, struct git_attr_check *check)
|
||||
@ -618,13 +550,12 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check)
|
||||
return !!ATTR_TRUE(value);
|
||||
}
|
||||
|
||||
char *convert_to_git(const char *path, const char *src, unsigned long *sizep)
|
||||
int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst)
|
||||
{
|
||||
struct git_attr_check check[3];
|
||||
int crlf = CRLF_GUESS;
|
||||
int ident = 0;
|
||||
int ident = 0, ret = 0;
|
||||
char *filter = NULL;
|
||||
char *buf, *buf2;
|
||||
|
||||
setup_convert_check(check);
|
||||
if (!git_checkattr(path, ARRAY_SIZE(check), check)) {
|
||||
@ -636,30 +567,25 @@ char *convert_to_git(const char *path, const char *src, unsigned long *sizep)
|
||||
filter = drv->clean;
|
||||
}
|
||||
|
||||
buf = apply_filter(path, src, sizep, filter);
|
||||
|
||||
buf2 = crlf_to_git(path, buf ? buf : src, sizep, crlf);
|
||||
if (buf2) {
|
||||
free(buf);
|
||||
buf = buf2;
|
||||
ret |= apply_filter(path, src, len, dst, filter);
|
||||
if (ret) {
|
||||
src = dst->buf;
|
||||
len = dst->len;
|
||||
}
|
||||
|
||||
buf2 = ident_to_git(path, buf ? buf : src, sizep, ident);
|
||||
if (buf2) {
|
||||
free(buf);
|
||||
buf = buf2;
|
||||
ret |= crlf_to_git(path, src, len, dst, crlf);
|
||||
if (ret) {
|
||||
src = dst->buf;
|
||||
len = dst->len;
|
||||
}
|
||||
|
||||
return buf;
|
||||
return ret | ident_to_git(path, src, len, dst, ident);
|
||||
}
|
||||
|
||||
char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep)
|
||||
int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)
|
||||
{
|
||||
struct git_attr_check check[3];
|
||||
int crlf = CRLF_GUESS;
|
||||
int ident = 0;
|
||||
int ident = 0, ret = 0;
|
||||
char *filter = NULL;
|
||||
char *buf, *buf2;
|
||||
|
||||
setup_convert_check(check);
|
||||
if (!git_checkattr(path, ARRAY_SIZE(check), check)) {
|
||||
@ -671,19 +597,15 @@ char *convert_to_working_tree(const char *path, const char *src, unsigned long *
|
||||
filter = drv->smudge;
|
||||
}
|
||||
|
||||
buf = ident_to_worktree(path, src, sizep, ident);
|
||||
|
||||
buf2 = crlf_to_worktree(path, buf ? buf : src, sizep, crlf);
|
||||
if (buf2) {
|
||||
free(buf);
|
||||
buf = buf2;
|
||||
ret |= ident_to_worktree(path, src, len, dst, ident);
|
||||
if (ret) {
|
||||
src = dst->buf;
|
||||
len = dst->len;
|
||||
}
|
||||
|
||||
buf2 = apply_filter(path, buf ? buf : src, sizep, filter);
|
||||
if (buf2) {
|
||||
free(buf);
|
||||
buf = buf2;
|
||||
ret |= crlf_to_worktree(path, src, len, dst, crlf);
|
||||
if (ret) {
|
||||
src = dst->buf;
|
||||
len = dst->len;
|
||||
}
|
||||
|
||||
return buf;
|
||||
return ret | apply_filter(path, src, len, dst, filter);
|
||||
}
|
||||
|
350
diff.c
350
diff.c
@ -83,13 +83,8 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val
|
||||
if (!strncmp(drv->name, name, namelen) && !drv->name[namelen])
|
||||
break;
|
||||
if (!drv) {
|
||||
char *namebuf;
|
||||
drv = xcalloc(1, sizeof(struct ll_diff_driver));
|
||||
namebuf = xmalloc(namelen + 1);
|
||||
memcpy(namebuf, name, namelen);
|
||||
namebuf[namelen] = 0;
|
||||
drv->name = namebuf;
|
||||
drv->next = NULL;
|
||||
drv->name = xmemdupz(name, namelen);
|
||||
if (!user_diff_tail)
|
||||
user_diff_tail = &user_diff;
|
||||
*user_diff_tail = drv;
|
||||
@ -126,12 +121,8 @@ static int parse_funcname_pattern(const char *var, const char *ep, const char *v
|
||||
if (!strncmp(pp->name, name, namelen) && !pp->name[namelen])
|
||||
break;
|
||||
if (!pp) {
|
||||
char *namebuf;
|
||||
pp = xcalloc(1, sizeof(*pp));
|
||||
namebuf = xmalloc(namelen + 1);
|
||||
memcpy(namebuf, name, namelen);
|
||||
namebuf[namelen] = 0;
|
||||
pp->name = namebuf;
|
||||
pp->name = xmemdupz(name, namelen);
|
||||
pp->next = funcname_pattern_list;
|
||||
funcname_pattern_list = pp;
|
||||
}
|
||||
@ -190,44 +181,23 @@ int git_diff_ui_config(const char *var, const char *value)
|
||||
return git_default_config(var, value);
|
||||
}
|
||||
|
||||
static char *quote_one(const char *str)
|
||||
{
|
||||
int needlen;
|
||||
char *xp;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
needlen = quote_c_style(str, NULL, NULL, 0);
|
||||
if (!needlen)
|
||||
return xstrdup(str);
|
||||
xp = xmalloc(needlen + 1);
|
||||
quote_c_style(str, xp, NULL, 0);
|
||||
return xp;
|
||||
}
|
||||
|
||||
static char *quote_two(const char *one, const char *two)
|
||||
{
|
||||
int need_one = quote_c_style(one, NULL, NULL, 1);
|
||||
int need_two = quote_c_style(two, NULL, NULL, 1);
|
||||
char *xp;
|
||||
struct strbuf res;
|
||||
|
||||
strbuf_init(&res, 0);
|
||||
if (need_one + need_two) {
|
||||
if (!need_one) need_one = strlen(one);
|
||||
if (!need_two) need_one = strlen(two);
|
||||
|
||||
xp = xmalloc(need_one + need_two + 3);
|
||||
xp[0] = '"';
|
||||
quote_c_style(one, xp + 1, NULL, 1);
|
||||
quote_c_style(two, xp + need_one + 1, NULL, 1);
|
||||
strcpy(xp + need_one + need_two + 1, "\"");
|
||||
return xp;
|
||||
strbuf_addch(&res, '"');
|
||||
quote_c_style(one, &res, NULL, 1);
|
||||
quote_c_style(two, &res, NULL, 1);
|
||||
strbuf_addch(&res, '"');
|
||||
} else {
|
||||
strbuf_addstr(&res, one);
|
||||
strbuf_addstr(&res, two);
|
||||
}
|
||||
need_one = strlen(one);
|
||||
need_two = strlen(two);
|
||||
xp = xmalloc(need_one + need_two + 1);
|
||||
strcpy(xp, one);
|
||||
strcpy(xp + need_one, two);
|
||||
return xp;
|
||||
return strbuf_detach(&res, NULL);
|
||||
}
|
||||
|
||||
static const char *external_diff(void)
|
||||
@ -679,27 +649,20 @@ static char *pprint_rename(const char *a, const char *b)
|
||||
{
|
||||
const char *old = a;
|
||||
const char *new = b;
|
||||
char *name = NULL;
|
||||
struct strbuf name;
|
||||
int pfx_length, sfx_length;
|
||||
int len_a = strlen(a);
|
||||
int len_b = strlen(b);
|
||||
int a_midlen, b_midlen;
|
||||
int qlen_a = quote_c_style(a, NULL, NULL, 0);
|
||||
int qlen_b = quote_c_style(b, NULL, NULL, 0);
|
||||
|
||||
strbuf_init(&name, 0);
|
||||
if (qlen_a || qlen_b) {
|
||||
if (qlen_a) len_a = qlen_a;
|
||||
if (qlen_b) len_b = qlen_b;
|
||||
name = xmalloc( len_a + len_b + 5 );
|
||||
if (qlen_a)
|
||||
quote_c_style(a, name, NULL, 0);
|
||||
else
|
||||
memcpy(name, a, len_a);
|
||||
memcpy(name + len_a, " => ", 4);
|
||||
if (qlen_b)
|
||||
quote_c_style(b, name + len_a + 4, NULL, 0);
|
||||
else
|
||||
memcpy(name + len_a + 4, b, len_b + 1);
|
||||
return name;
|
||||
quote_c_style(a, &name, NULL, 0);
|
||||
strbuf_addstr(&name, " => ");
|
||||
quote_c_style(b, &name, NULL, 0);
|
||||
return strbuf_detach(&name, NULL);
|
||||
}
|
||||
|
||||
/* Find common prefix */
|
||||
@ -728,24 +691,26 @@ static char *pprint_rename(const char *a, const char *b)
|
||||
* pfx{sfx-a => sfx-b}
|
||||
* name-a => name-b
|
||||
*/
|
||||
if (pfx_length + sfx_length) {
|
||||
int a_midlen = len_a - pfx_length - sfx_length;
|
||||
int b_midlen = len_b - pfx_length - sfx_length;
|
||||
if (a_midlen < 0) a_midlen = 0;
|
||||
if (b_midlen < 0) b_midlen = 0;
|
||||
a_midlen = len_a - pfx_length - sfx_length;
|
||||
b_midlen = len_b - pfx_length - sfx_length;
|
||||
if (a_midlen < 0)
|
||||
a_midlen = 0;
|
||||
if (b_midlen < 0)
|
||||
b_midlen = 0;
|
||||
|
||||
name = xmalloc(pfx_length + a_midlen + b_midlen + sfx_length + 7);
|
||||
sprintf(name, "%.*s{%.*s => %.*s}%s",
|
||||
pfx_length, a,
|
||||
a_midlen, a + pfx_length,
|
||||
b_midlen, b + pfx_length,
|
||||
a + len_a - sfx_length);
|
||||
strbuf_grow(&name, pfx_length + a_midlen + b_midlen + sfx_length + 7);
|
||||
if (pfx_length + sfx_length) {
|
||||
strbuf_add(&name, a, pfx_length);
|
||||
strbuf_addch(&name, '{');
|
||||
}
|
||||
else {
|
||||
name = xmalloc(len_a + len_b + 5);
|
||||
sprintf(name, "%s => %s", a, b);
|
||||
strbuf_add(&name, a + pfx_length, a_midlen);
|
||||
strbuf_addstr(&name, " => ");
|
||||
strbuf_add(&name, b + pfx_length, b_midlen);
|
||||
if (pfx_length + sfx_length) {
|
||||
strbuf_addch(&name, '}');
|
||||
strbuf_add(&name, a + len_a - sfx_length, sfx_length);
|
||||
}
|
||||
return name;
|
||||
return strbuf_detach(&name, NULL);
|
||||
}
|
||||
|
||||
struct diffstat_t {
|
||||
@ -858,12 +823,13 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
|
||||
int change = file->added + file->deleted;
|
||||
|
||||
if (!file->is_renamed) { /* renames are already quoted by pprint_rename */
|
||||
len = quote_c_style(file->name, NULL, NULL, 0);
|
||||
if (len) {
|
||||
char *qname = xmalloc(len + 1);
|
||||
quote_c_style(file->name, qname, NULL, 0);
|
||||
struct strbuf buf;
|
||||
strbuf_init(&buf, 0);
|
||||
if (quote_c_style(file->name, &buf, NULL, 0)) {
|
||||
free(file->name);
|
||||
file->name = qname;
|
||||
file->name = strbuf_detach(&buf, NULL);
|
||||
} else {
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1001,12 +967,12 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options)
|
||||
printf("-\t-\t");
|
||||
else
|
||||
printf("%d\t%d\t", file->added, file->deleted);
|
||||
if (options->line_termination && !file->is_renamed &&
|
||||
quote_c_style(file->name, NULL, NULL, 0))
|
||||
quote_c_style(file->name, NULL, stdout, 0);
|
||||
else
|
||||
if (!file->is_renamed) {
|
||||
write_name_quoted(file->name, stdout, options->line_termination);
|
||||
} else {
|
||||
fputs(file->name, stdout);
|
||||
putchar(options->line_termination);
|
||||
putchar(options->line_termination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1545,26 +1511,15 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
|
||||
|
||||
static int populate_from_stdin(struct diff_filespec *s)
|
||||
{
|
||||
#define INCREMENT 1024
|
||||
char *buf;
|
||||
unsigned long size;
|
||||
ssize_t got;
|
||||
struct strbuf buf;
|
||||
|
||||
size = 0;
|
||||
buf = NULL;
|
||||
while (1) {
|
||||
buf = xrealloc(buf, size + INCREMENT);
|
||||
got = xread(0, buf + size, INCREMENT);
|
||||
if (!got)
|
||||
break; /* EOF */
|
||||
if (got < 0)
|
||||
return error("error while reading from stdin %s",
|
||||
strbuf_init(&buf, 0);
|
||||
if (strbuf_read(&buf, 0, 0) < 0)
|
||||
return error("error while reading from stdin %s",
|
||||
strerror(errno));
|
||||
size += got;
|
||||
}
|
||||
|
||||
s->should_munmap = 0;
|
||||
s->data = buf;
|
||||
s->size = size;
|
||||
s->data = strbuf_detach(&buf, &s->size);
|
||||
s->should_free = 1;
|
||||
return 0;
|
||||
}
|
||||
@ -1609,10 +1564,9 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
|
||||
|
||||
if (!s->sha1_valid ||
|
||||
reuse_worktree_file(s->path, s->sha1, 0)) {
|
||||
struct strbuf buf;
|
||||
struct stat st;
|
||||
int fd;
|
||||
char *buf;
|
||||
unsigned long size;
|
||||
|
||||
if (!strcmp(s->path, "-"))
|
||||
return populate_from_stdin(s);
|
||||
@ -1653,13 +1607,11 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
|
||||
/*
|
||||
* Convert from working tree format to canonical git format
|
||||
*/
|
||||
size = s->size;
|
||||
buf = convert_to_git(s->path, s->data, &size);
|
||||
if (buf) {
|
||||
strbuf_init(&buf, 0);
|
||||
if (convert_to_git(s->path, s->data, s->size, &buf)) {
|
||||
munmap(s->data, s->size);
|
||||
s->should_munmap = 0;
|
||||
s->data = buf;
|
||||
s->size = size;
|
||||
s->data = strbuf_detach(&buf, &s->size);
|
||||
s->should_free = 1;
|
||||
}
|
||||
}
|
||||
@ -1967,50 +1919,46 @@ static int similarity_index(struct diff_filepair *p)
|
||||
static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||
{
|
||||
const char *pgm = external_diff();
|
||||
char msg[PATH_MAX*2+300], *xfrm_msg;
|
||||
struct diff_filespec *one;
|
||||
struct diff_filespec *two;
|
||||
struct strbuf msg;
|
||||
char *xfrm_msg;
|
||||
struct diff_filespec *one = p->one;
|
||||
struct diff_filespec *two = p->two;
|
||||
const char *name;
|
||||
const char *other;
|
||||
char *name_munged, *other_munged;
|
||||
int complete_rewrite = 0;
|
||||
int len;
|
||||
|
||||
|
||||
if (DIFF_PAIR_UNMERGED(p)) {
|
||||
/* unmerged */
|
||||
run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, o, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
name = p->one->path;
|
||||
name = p->one->path;
|
||||
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
|
||||
name_munged = quote_one(name);
|
||||
other_munged = quote_one(other);
|
||||
one = p->one; two = p->two;
|
||||
|
||||
diff_fill_sha1_info(one);
|
||||
diff_fill_sha1_info(two);
|
||||
|
||||
len = 0;
|
||||
strbuf_init(&msg, PATH_MAX * 2 + 300);
|
||||
switch (p->status) {
|
||||
case DIFF_STATUS_COPIED:
|
||||
len += snprintf(msg + len, sizeof(msg) - len,
|
||||
"similarity index %d%%\n"
|
||||
"copy from %s\n"
|
||||
"copy to %s\n",
|
||||
similarity_index(p), name_munged, other_munged);
|
||||
strbuf_addf(&msg, "similarity index %d%%", similarity_index(p));
|
||||
strbuf_addstr(&msg, "\ncopy from ");
|
||||
quote_c_style(name, &msg, NULL, 0);
|
||||
strbuf_addstr(&msg, "\ncopy to ");
|
||||
quote_c_style(other, &msg, NULL, 0);
|
||||
strbuf_addch(&msg, '\n');
|
||||
break;
|
||||
case DIFF_STATUS_RENAMED:
|
||||
len += snprintf(msg + len, sizeof(msg) - len,
|
||||
"similarity index %d%%\n"
|
||||
"rename from %s\n"
|
||||
"rename to %s\n",
|
||||
similarity_index(p), name_munged, other_munged);
|
||||
strbuf_addf(&msg, "similarity index %d%%", similarity_index(p));
|
||||
strbuf_addstr(&msg, "\nrename from ");
|
||||
quote_c_style(name, &msg, NULL, 0);
|
||||
strbuf_addstr(&msg, "\nrename to ");
|
||||
quote_c_style(other, &msg, NULL, 0);
|
||||
strbuf_addch(&msg, '\n');
|
||||
break;
|
||||
case DIFF_STATUS_MODIFIED:
|
||||
if (p->score) {
|
||||
len += snprintf(msg + len, sizeof(msg) - len,
|
||||
"dissimilarity index %d%%\n",
|
||||
strbuf_addf(&msg, "dissimilarity index %d%%\n",
|
||||
similarity_index(p));
|
||||
complete_rewrite = 1;
|
||||
break;
|
||||
@ -2030,19 +1978,17 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||
(!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
|
||||
abbrev = 40;
|
||||
}
|
||||
len += snprintf(msg + len, sizeof(msg) - len,
|
||||
"index %.*s..%.*s",
|
||||
strbuf_addf(&msg, "index %.*s..%.*s",
|
||||
abbrev, sha1_to_hex(one->sha1),
|
||||
abbrev, sha1_to_hex(two->sha1));
|
||||
if (one->mode == two->mode)
|
||||
len += snprintf(msg + len, sizeof(msg) - len,
|
||||
" %06o", one->mode);
|
||||
len += snprintf(msg + len, sizeof(msg) - len, "\n");
|
||||
strbuf_addf(&msg, " %06o", one->mode);
|
||||
strbuf_addch(&msg, '\n');
|
||||
}
|
||||
|
||||
if (len)
|
||||
msg[--len] = 0;
|
||||
xfrm_msg = len ? msg : NULL;
|
||||
if (msg.len)
|
||||
strbuf_setlen(&msg, msg.len - 1);
|
||||
xfrm_msg = msg.len ? msg.buf : NULL;
|
||||
|
||||
if (!pgm &&
|
||||
DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
|
||||
@ -2061,8 +2007,7 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||
run_diff_cmd(pgm, name, other, one, two, xfrm_msg, o,
|
||||
complete_rewrite);
|
||||
|
||||
free(name_munged);
|
||||
free(other_munged);
|
||||
strbuf_release(&msg);
|
||||
}
|
||||
|
||||
static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
|
||||
@ -2518,72 +2463,30 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len)
|
||||
return sha1_to_hex(sha1);
|
||||
}
|
||||
|
||||
static void diff_flush_raw(struct diff_filepair *p,
|
||||
struct diff_options *options)
|
||||
static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt)
|
||||
{
|
||||
int two_paths;
|
||||
char status[10];
|
||||
int abbrev = options->abbrev;
|
||||
const char *path_one, *path_two;
|
||||
int inter_name_termination = '\t';
|
||||
int line_termination = options->line_termination;
|
||||
int line_termination = opt->line_termination;
|
||||
int inter_name_termination = line_termination ? '\t' : '\0';
|
||||
|
||||
if (!line_termination)
|
||||
inter_name_termination = 0;
|
||||
|
||||
path_one = p->one->path;
|
||||
path_two = p->two->path;
|
||||
if (line_termination) {
|
||||
path_one = quote_one(path_one);
|
||||
path_two = quote_one(path_two);
|
||||
if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) {
|
||||
printf(":%06o %06o %s ", p->one->mode, p->two->mode,
|
||||
diff_unique_abbrev(p->one->sha1, opt->abbrev));
|
||||
printf("%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev));
|
||||
}
|
||||
if (p->score) {
|
||||
printf("%c%03d%c", p->status, similarity_index(p),
|
||||
inter_name_termination);
|
||||
} else {
|
||||
printf("%c%c", p->status, inter_name_termination);
|
||||
}
|
||||
|
||||
if (p->score)
|
||||
sprintf(status, "%c%03d", p->status, similarity_index(p));
|
||||
else {
|
||||
status[0] = p->status;
|
||||
status[1] = 0;
|
||||
if (p->status == DIFF_STATUS_COPIED || p->status == DIFF_STATUS_RENAMED) {
|
||||
write_name_quoted(p->one->path, stdout, inter_name_termination);
|
||||
write_name_quoted(p->two->path, stdout, line_termination);
|
||||
} else {
|
||||
const char *path = p->one->mode ? p->one->path : p->two->path;
|
||||
write_name_quoted(path, stdout, line_termination);
|
||||
}
|
||||
switch (p->status) {
|
||||
case DIFF_STATUS_COPIED:
|
||||
case DIFF_STATUS_RENAMED:
|
||||
two_paths = 1;
|
||||
break;
|
||||
case DIFF_STATUS_ADDED:
|
||||
case DIFF_STATUS_DELETED:
|
||||
two_paths = 0;
|
||||
break;
|
||||
default:
|
||||
two_paths = 0;
|
||||
break;
|
||||
}
|
||||
if (!(options->output_format & DIFF_FORMAT_NAME_STATUS)) {
|
||||
printf(":%06o %06o %s ",
|
||||
p->one->mode, p->two->mode,
|
||||
diff_unique_abbrev(p->one->sha1, abbrev));
|
||||
printf("%s ",
|
||||
diff_unique_abbrev(p->two->sha1, abbrev));
|
||||
}
|
||||
printf("%s%c%s", status, inter_name_termination,
|
||||
two_paths || p->one->mode ? path_one : path_two);
|
||||
if (two_paths)
|
||||
printf("%c%s", inter_name_termination, path_two);
|
||||
putchar(line_termination);
|
||||
if (path_one != p->one->path)
|
||||
free((void*)path_one);
|
||||
if (path_two != p->two->path)
|
||||
free((void*)path_two);
|
||||
}
|
||||
|
||||
static void diff_flush_name(struct diff_filepair *p, struct diff_options *opt)
|
||||
{
|
||||
char *path = p->two->path;
|
||||
|
||||
if (opt->line_termination)
|
||||
path = quote_one(p->two->path);
|
||||
printf("%s%c", path, opt->line_termination);
|
||||
if (p->two->path != path)
|
||||
free(path);
|
||||
}
|
||||
|
||||
int diff_unmodified_pair(struct diff_filepair *p)
|
||||
@ -2593,14 +2496,11 @@ int diff_unmodified_pair(struct diff_filepair *p)
|
||||
* let transformers to produce diff_filepairs any way they want,
|
||||
* and filter and clean them up here before producing the output.
|
||||
*/
|
||||
struct diff_filespec *one, *two;
|
||||
struct diff_filespec *one = p->one, *two = p->two;
|
||||
|
||||
if (DIFF_PAIR_UNMERGED(p))
|
||||
return 0; /* unmerged is interesting */
|
||||
|
||||
one = p->one;
|
||||
two = p->two;
|
||||
|
||||
/* deletion, addition, mode or type change
|
||||
* and rename are all interesting.
|
||||
*/
|
||||
@ -2789,32 +2689,27 @@ static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
|
||||
else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS))
|
||||
diff_flush_raw(p, opt);
|
||||
else if (fmt & DIFF_FORMAT_NAME)
|
||||
diff_flush_name(p, opt);
|
||||
write_name_quoted(p->two->path, stdout, opt->line_termination);
|
||||
}
|
||||
|
||||
static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs)
|
||||
{
|
||||
char *name = quote_one(fs->path);
|
||||
if (fs->mode)
|
||||
printf(" %s mode %06o %s\n", newdelete, fs->mode, name);
|
||||
printf(" %s mode %06o ", newdelete, fs->mode);
|
||||
else
|
||||
printf(" %s %s\n", newdelete, name);
|
||||
free(name);
|
||||
printf(" %s ", newdelete);
|
||||
write_name_quoted(fs->path, stdout, '\n');
|
||||
}
|
||||
|
||||
|
||||
static void show_mode_change(struct diff_filepair *p, int show_name)
|
||||
{
|
||||
if (p->one->mode && p->two->mode && p->one->mode != p->two->mode) {
|
||||
printf(" mode change %06o => %06o%c", p->one->mode, p->two->mode,
|
||||
show_name ? ' ' : '\n');
|
||||
if (show_name) {
|
||||
char *name = quote_one(p->two->path);
|
||||
printf(" mode change %06o => %06o %s\n",
|
||||
p->one->mode, p->two->mode, name);
|
||||
free(name);
|
||||
write_name_quoted(p->two->path, stdout, '\n');
|
||||
}
|
||||
else
|
||||
printf(" mode change %06o => %06o\n",
|
||||
p->one->mode, p->two->mode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2844,12 +2739,11 @@ static void diff_summary(struct diff_filepair *p)
|
||||
break;
|
||||
default:
|
||||
if (p->score) {
|
||||
char *name = quote_one(p->two->path);
|
||||
printf(" rewrite %s (%d%%)\n", name,
|
||||
similarity_index(p));
|
||||
free(name);
|
||||
show_mode_change(p, 0);
|
||||
} else show_mode_change(p, 1);
|
||||
puts(" rewrite ");
|
||||
write_name_quoted(p->two->path, stdout, ' ');
|
||||
printf("(%d%%)\n", similarity_index(p));
|
||||
}
|
||||
show_mode_change(p, !p->score);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2863,14 +2757,14 @@ struct patch_id_t {
|
||||
static int remove_space(char *line, int len)
|
||||
{
|
||||
int i;
|
||||
char *dst = line;
|
||||
unsigned char c;
|
||||
char *dst = line;
|
||||
unsigned char c;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (!isspace((c = line[i])))
|
||||
*dst++ = c;
|
||||
for (i = 0; i < len; i++)
|
||||
if (!isspace((c = line[i])))
|
||||
*dst++ = c;
|
||||
|
||||
return dst - line;
|
||||
return dst - line;
|
||||
}
|
||||
|
||||
static void patch_id_consume(void *priv, char *line, unsigned long len)
|
||||
|
@ -48,11 +48,8 @@ static void prepare_order(const char *orderfile)
|
||||
if (*ep == '\n') {
|
||||
*ep = 0;
|
||||
order[cnt] = cp;
|
||||
}
|
||||
else {
|
||||
order[cnt] = xmalloc(ep-cp+1);
|
||||
memcpy(order[cnt], cp, ep-cp);
|
||||
order[cnt][ep-cp] = 0;
|
||||
} else {
|
||||
order[cnt] = xmemdupz(cp, ep - cp);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
|
9
entry.c
9
entry.c
@ -104,7 +104,8 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
|
||||
long wrote;
|
||||
|
||||
switch (ntohl(ce->ce_mode) & S_IFMT) {
|
||||
char *buf, *new;
|
||||
char *new;
|
||||
struct strbuf buf;
|
||||
unsigned long size;
|
||||
|
||||
case S_IFREG:
|
||||
@ -116,10 +117,10 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
|
||||
/*
|
||||
* Convert from git internal format to working tree format
|
||||
*/
|
||||
buf = convert_to_working_tree(ce->name, new, &size);
|
||||
if (buf) {
|
||||
strbuf_init(&buf, 0);
|
||||
if (convert_to_working_tree(ce->name, new, size, &buf)) {
|
||||
free(new);
|
||||
new = buf;
|
||||
new = strbuf_detach(&buf, &size);
|
||||
}
|
||||
|
||||
if (to_tempfile) {
|
||||
|
312
fast-import.c
312
fast-import.c
@ -149,7 +149,6 @@ Format of STDIN stream:
|
||||
#include "pack.h"
|
||||
#include "refs.h"
|
||||
#include "csum-file.h"
|
||||
#include "strbuf.h"
|
||||
#include "quote.h"
|
||||
|
||||
#define PACK_ID_BITS 16
|
||||
@ -183,11 +182,10 @@ struct mark_set
|
||||
|
||||
struct last_object
|
||||
{
|
||||
void *data;
|
||||
unsigned long len;
|
||||
struct strbuf data;
|
||||
uint32_t offset;
|
||||
unsigned int depth;
|
||||
unsigned no_free:1;
|
||||
unsigned no_swap : 1;
|
||||
};
|
||||
|
||||
struct mem_pool
|
||||
@ -251,12 +249,6 @@ struct tag
|
||||
unsigned char sha1[20];
|
||||
};
|
||||
|
||||
struct dbuf
|
||||
{
|
||||
void *buffer;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
struct hash_list
|
||||
{
|
||||
struct hash_list *next;
|
||||
@ -317,15 +309,15 @@ static struct mark_set *marks;
|
||||
static const char* mark_file;
|
||||
|
||||
/* Our last blob */
|
||||
static struct last_object last_blob;
|
||||
static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
|
||||
|
||||
/* Tree management */
|
||||
static unsigned int tree_entry_alloc = 1000;
|
||||
static void *avail_tree_entry;
|
||||
static unsigned int avail_tree_table_sz = 100;
|
||||
static struct avail_tree_content **avail_tree_table;
|
||||
static struct dbuf old_tree;
|
||||
static struct dbuf new_tree;
|
||||
static struct strbuf old_tree = STRBUF_INIT;
|
||||
static struct strbuf new_tree = STRBUF_INIT;
|
||||
|
||||
/* Branch data */
|
||||
static unsigned long max_active_branches = 5;
|
||||
@ -340,14 +332,14 @@ static struct tag *last_tag;
|
||||
|
||||
/* Input stream parsing */
|
||||
static whenspec_type whenspec = WHENSPEC_RAW;
|
||||
static struct strbuf command_buf;
|
||||
static struct strbuf command_buf = STRBUF_INIT;
|
||||
static int unread_command_buf;
|
||||
static struct recent_command cmd_hist = {&cmd_hist, &cmd_hist, NULL};
|
||||
static struct recent_command *cmd_tail = &cmd_hist;
|
||||
static struct recent_command *rc_free;
|
||||
static unsigned int cmd_save = 100;
|
||||
static uintmax_t next_mark;
|
||||
static struct dbuf new_data;
|
||||
static struct strbuf new_data = STRBUF_INIT;
|
||||
|
||||
static void write_branch_report(FILE *rpt, struct branch *b)
|
||||
{
|
||||
@ -567,17 +559,6 @@ static char *pool_strdup(const char *s)
|
||||
return r;
|
||||
}
|
||||
|
||||
static void size_dbuf(struct dbuf *b, size_t maxlen)
|
||||
{
|
||||
if (b->buffer) {
|
||||
if (b->capacity >= maxlen)
|
||||
return;
|
||||
free(b->buffer);
|
||||
}
|
||||
b->capacity = ((maxlen / 1024) + 1) * 1024;
|
||||
b->buffer = xmalloc(b->capacity);
|
||||
}
|
||||
|
||||
static void insert_mark(uintmax_t idnum, struct object_entry *oe)
|
||||
{
|
||||
struct mark_set *s = marks;
|
||||
@ -968,9 +949,7 @@ static void end_packfile(void)
|
||||
free(old_p);
|
||||
|
||||
/* We can't carry a delta across packfiles. */
|
||||
free(last_blob.data);
|
||||
last_blob.data = NULL;
|
||||
last_blob.len = 0;
|
||||
strbuf_release(&last_blob.data);
|
||||
last_blob.offset = 0;
|
||||
last_blob.depth = 0;
|
||||
}
|
||||
@ -1006,8 +985,7 @@ static size_t encode_header(
|
||||
|
||||
static int store_object(
|
||||
enum object_type type,
|
||||
void *dat,
|
||||
size_t datlen,
|
||||
struct strbuf *dat,
|
||||
struct last_object *last,
|
||||
unsigned char *sha1out,
|
||||
uintmax_t mark)
|
||||
@ -1021,10 +999,10 @@ static int store_object(
|
||||
z_stream s;
|
||||
|
||||
hdrlen = sprintf((char*)hdr,"%s %lu", typename(type),
|
||||
(unsigned long)datlen) + 1;
|
||||
(unsigned long)dat->len) + 1;
|
||||
SHA1_Init(&c);
|
||||
SHA1_Update(&c, hdr, hdrlen);
|
||||
SHA1_Update(&c, dat, datlen);
|
||||
SHA1_Update(&c, dat->buf, dat->len);
|
||||
SHA1_Final(sha1, &c);
|
||||
if (sha1out)
|
||||
hashcpy(sha1out, sha1);
|
||||
@ -1043,11 +1021,11 @@ static int store_object(
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (last && last->data && last->depth < max_depth) {
|
||||
delta = diff_delta(last->data, last->len,
|
||||
dat, datlen,
|
||||
if (last && last->data.buf && last->depth < max_depth) {
|
||||
delta = diff_delta(last->data.buf, last->data.len,
|
||||
dat->buf, dat->len,
|
||||
&deltalen, 0);
|
||||
if (delta && deltalen >= datlen) {
|
||||
if (delta && deltalen >= dat->len) {
|
||||
free(delta);
|
||||
delta = NULL;
|
||||
}
|
||||
@ -1060,8 +1038,8 @@ static int store_object(
|
||||
s.next_in = delta;
|
||||
s.avail_in = deltalen;
|
||||
} else {
|
||||
s.next_in = dat;
|
||||
s.avail_in = datlen;
|
||||
s.next_in = (void *)dat->buf;
|
||||
s.avail_in = dat->len;
|
||||
}
|
||||
s.avail_out = deflateBound(&s, s.avail_in);
|
||||
s.next_out = out = xmalloc(s.avail_out);
|
||||
@ -1084,8 +1062,8 @@ static int store_object(
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
deflateInit(&s, zlib_compression_level);
|
||||
s.next_in = dat;
|
||||
s.avail_in = datlen;
|
||||
s.next_in = (void *)dat->buf;
|
||||
s.avail_in = dat->len;
|
||||
s.avail_out = deflateBound(&s, s.avail_in);
|
||||
s.next_out = out = xrealloc(out, s.avail_out);
|
||||
while (deflate(&s, Z_FINISH) == Z_OK)
|
||||
@ -1119,7 +1097,7 @@ static int store_object(
|
||||
} else {
|
||||
if (last)
|
||||
last->depth = 0;
|
||||
hdrlen = encode_header(type, datlen, hdr);
|
||||
hdrlen = encode_header(type, dat->len, hdr);
|
||||
write_or_die(pack_data->pack_fd, hdr, hdrlen);
|
||||
pack_size += hdrlen;
|
||||
}
|
||||
@ -1130,11 +1108,12 @@ static int store_object(
|
||||
free(out);
|
||||
free(delta);
|
||||
if (last) {
|
||||
if (!last->no_free)
|
||||
free(last->data);
|
||||
last->data = dat;
|
||||
if (last->no_swap) {
|
||||
last->data = *dat;
|
||||
} else {
|
||||
strbuf_swap(&last->data, dat);
|
||||
}
|
||||
last->offset = e->offset;
|
||||
last->len = datlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1230,14 +1209,10 @@ static int tecmp1 (const void *_a, const void *_b)
|
||||
b->name->str_dat, b->name->str_len, b->versions[1].mode);
|
||||
}
|
||||
|
||||
static void mktree(struct tree_content *t,
|
||||
int v,
|
||||
unsigned long *szp,
|
||||
struct dbuf *b)
|
||||
static void mktree(struct tree_content *t, int v, struct strbuf *b)
|
||||
{
|
||||
size_t maxlen = 0;
|
||||
unsigned int i;
|
||||
char *c;
|
||||
|
||||
if (!v)
|
||||
qsort(t->entries,t->entry_count,sizeof(t->entries[0]),tecmp0);
|
||||
@ -1249,28 +1224,23 @@ static void mktree(struct tree_content *t,
|
||||
maxlen += t->entries[i]->name->str_len + 34;
|
||||
}
|
||||
|
||||
size_dbuf(b, maxlen);
|
||||
c = b->buffer;
|
||||
strbuf_reset(b);
|
||||
strbuf_grow(b, maxlen);
|
||||
for (i = 0; i < t->entry_count; i++) {
|
||||
struct tree_entry *e = t->entries[i];
|
||||
if (!e->versions[v].mode)
|
||||
continue;
|
||||
c += sprintf(c, "%o", (unsigned int)e->versions[v].mode);
|
||||
*c++ = ' ';
|
||||
strcpy(c, e->name->str_dat);
|
||||
c += e->name->str_len + 1;
|
||||
hashcpy((unsigned char*)c, e->versions[v].sha1);
|
||||
c += 20;
|
||||
strbuf_addf(b, "%o %s%c", (unsigned int)e->versions[v].mode,
|
||||
e->name->str_dat, '\0');
|
||||
strbuf_add(b, e->versions[v].sha1, 20);
|
||||
}
|
||||
*szp = c - (char*)b->buffer;
|
||||
}
|
||||
|
||||
static void store_tree(struct tree_entry *root)
|
||||
{
|
||||
struct tree_content *t = root->tree;
|
||||
unsigned int i, j, del;
|
||||
unsigned long new_len;
|
||||
struct last_object lo;
|
||||
struct last_object lo = { STRBUF_INIT, 0, 0, /* no_swap */ 1 };
|
||||
struct object_entry *le;
|
||||
|
||||
if (!is_null_sha1(root->versions[1].sha1))
|
||||
@ -1282,23 +1252,15 @@ static void store_tree(struct tree_entry *root)
|
||||
}
|
||||
|
||||
le = find_object(root->versions[0].sha1);
|
||||
if (!S_ISDIR(root->versions[0].mode)
|
||||
|| !le
|
||||
|| le->pack_id != pack_id) {
|
||||
lo.data = NULL;
|
||||
lo.depth = 0;
|
||||
lo.no_free = 0;
|
||||
} else {
|
||||
mktree(t, 0, &lo.len, &old_tree);
|
||||
lo.data = old_tree.buffer;
|
||||
if (S_ISDIR(root->versions[0].mode) && le && le->pack_id == pack_id) {
|
||||
mktree(t, 0, &old_tree);
|
||||
lo.data = old_tree;
|
||||
lo.offset = le->offset;
|
||||
lo.depth = t->delta_depth;
|
||||
lo.no_free = 1;
|
||||
}
|
||||
|
||||
mktree(t, 1, &new_len, &new_tree);
|
||||
store_object(OBJ_TREE, new_tree.buffer, new_len,
|
||||
&lo, root->versions[1].sha1, 0);
|
||||
mktree(t, 1, &new_tree);
|
||||
store_object(OBJ_TREE, &new_tree, &lo, root->versions[1].sha1, 0);
|
||||
|
||||
t->delta_depth = lo.depth;
|
||||
for (i = 0, j = 0, del = 0; i < t->entry_count; i++) {
|
||||
@ -1585,20 +1547,25 @@ static void dump_marks(void)
|
||||
mark_file, strerror(errno));
|
||||
}
|
||||
|
||||
static void read_next_command(void)
|
||||
static int read_next_command(void)
|
||||
{
|
||||
static int stdin_eof = 0;
|
||||
|
||||
if (stdin_eof) {
|
||||
unread_command_buf = 0;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
do {
|
||||
if (unread_command_buf) {
|
||||
unread_command_buf = 0;
|
||||
if (command_buf.eof)
|
||||
return;
|
||||
} else {
|
||||
struct recent_command *rc;
|
||||
|
||||
command_buf.buf = NULL;
|
||||
read_line(&command_buf, stdin, '\n');
|
||||
if (command_buf.eof)
|
||||
return;
|
||||
strbuf_detach(&command_buf, NULL);
|
||||
stdin_eof = strbuf_getline(&command_buf, stdin, '\n');
|
||||
if (stdin_eof)
|
||||
return EOF;
|
||||
|
||||
rc = rc_free;
|
||||
if (rc)
|
||||
@ -1617,6 +1584,8 @@ static void read_next_command(void)
|
||||
cmd_tail = rc;
|
||||
}
|
||||
} while (command_buf.buf[0] == '#');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void skip_optional_lf(void)
|
||||
@ -1636,42 +1605,35 @@ static void cmd_mark(void)
|
||||
next_mark = 0;
|
||||
}
|
||||
|
||||
static void *cmd_data (size_t *size)
|
||||
static void cmd_data(struct strbuf *sb)
|
||||
{
|
||||
size_t length;
|
||||
char *buffer;
|
||||
strbuf_reset(sb);
|
||||
|
||||
if (prefixcmp(command_buf.buf, "data "))
|
||||
die("Expected 'data n' command, found: %s", command_buf.buf);
|
||||
|
||||
if (!prefixcmp(command_buf.buf + 5, "<<")) {
|
||||
char *term = xstrdup(command_buf.buf + 5 + 2);
|
||||
size_t sz = 8192, term_len = command_buf.len - 5 - 2;
|
||||
length = 0;
|
||||
buffer = xmalloc(sz);
|
||||
command_buf.buf = NULL;
|
||||
size_t term_len = command_buf.len - 5 - 2;
|
||||
|
||||
for (;;) {
|
||||
read_line(&command_buf, stdin, '\n');
|
||||
if (command_buf.eof)
|
||||
if (strbuf_getline(&command_buf, stdin, '\n') == EOF)
|
||||
die("EOF in data (terminator '%s' not found)", term);
|
||||
if (term_len == command_buf.len
|
||||
&& !strcmp(term, command_buf.buf))
|
||||
break;
|
||||
ALLOC_GROW(buffer, length + command_buf.len, sz);
|
||||
memcpy(buffer + length,
|
||||
command_buf.buf,
|
||||
command_buf.len - 1);
|
||||
length += command_buf.len - 1;
|
||||
buffer[length++] = '\n';
|
||||
strbuf_addbuf(sb, &command_buf);
|
||||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
free(term);
|
||||
}
|
||||
else {
|
||||
size_t n = 0;
|
||||
size_t n = 0, length;
|
||||
|
||||
length = strtoul(command_buf.buf + 5, NULL, 10);
|
||||
buffer = xmalloc(length);
|
||||
|
||||
while (n < length) {
|
||||
size_t s = fread(buffer + n, 1, length - n, stdin);
|
||||
size_t s = strbuf_fread(sb, length - n, stdin);
|
||||
if (!s && feof(stdin))
|
||||
die("EOF in data (%lu bytes remaining)",
|
||||
(unsigned long)(length - n));
|
||||
@ -1680,8 +1642,6 @@ static void *cmd_data (size_t *size)
|
||||
}
|
||||
|
||||
skip_optional_lf();
|
||||
*size = length;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int validate_raw_date(const char *src, char *result, int maxlen)
|
||||
@ -1744,15 +1704,12 @@ static char *parse_ident(const char *buf)
|
||||
|
||||
static void cmd_new_blob(void)
|
||||
{
|
||||
size_t l;
|
||||
void *d;
|
||||
static struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
read_next_command();
|
||||
cmd_mark();
|
||||
d = cmd_data(&l);
|
||||
|
||||
if (store_object(OBJ_BLOB, d, l, &last_blob, NULL, next_mark))
|
||||
free(d);
|
||||
cmd_data(&buf);
|
||||
store_object(OBJ_BLOB, &buf, &last_blob, NULL, next_mark);
|
||||
}
|
||||
|
||||
static void unload_one_branch(void)
|
||||
@ -1802,7 +1759,7 @@ static void load_branch(struct branch *b)
|
||||
static void file_change_m(struct branch *b)
|
||||
{
|
||||
const char *p = command_buf.buf + 2;
|
||||
char *p_uq;
|
||||
static struct strbuf uq = STRBUF_INIT;
|
||||
const char *endp;
|
||||
struct object_entry *oe = oe;
|
||||
unsigned char sha1[20];
|
||||
@ -1840,22 +1797,23 @@ static void file_change_m(struct branch *b)
|
||||
if (*p++ != ' ')
|
||||
die("Missing space after SHA1: %s", command_buf.buf);
|
||||
|
||||
p_uq = unquote_c_style(p, &endp);
|
||||
if (p_uq) {
|
||||
strbuf_reset(&uq);
|
||||
if (!unquote_c_style(&uq, p, &endp)) {
|
||||
if (*endp)
|
||||
die("Garbage after path in: %s", command_buf.buf);
|
||||
p = p_uq;
|
||||
p = uq.buf;
|
||||
}
|
||||
|
||||
if (inline_data) {
|
||||
size_t l;
|
||||
void *d;
|
||||
if (!p_uq)
|
||||
p = p_uq = xstrdup(p);
|
||||
static struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (p != uq.buf) {
|
||||
strbuf_addstr(&uq, p);
|
||||
p = uq.buf;
|
||||
}
|
||||
read_next_command();
|
||||
d = cmd_data(&l);
|
||||
if (store_object(OBJ_BLOB, d, l, &last_blob, sha1, 0))
|
||||
free(d);
|
||||
cmd_data(&buf);
|
||||
store_object(OBJ_BLOB, &buf, &last_blob, sha1, 0);
|
||||
} else if (oe) {
|
||||
if (oe->type != OBJ_BLOB)
|
||||
die("Not a blob (actually a %s): %s",
|
||||
@ -1870,58 +1828,54 @@ static void file_change_m(struct branch *b)
|
||||
}
|
||||
|
||||
tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode, NULL);
|
||||
free(p_uq);
|
||||
}
|
||||
|
||||
static void file_change_d(struct branch *b)
|
||||
{
|
||||
const char *p = command_buf.buf + 2;
|
||||
char *p_uq;
|
||||
static struct strbuf uq = STRBUF_INIT;
|
||||
const char *endp;
|
||||
|
||||
p_uq = unquote_c_style(p, &endp);
|
||||
if (p_uq) {
|
||||
strbuf_reset(&uq);
|
||||
if (!unquote_c_style(&uq, p, &endp)) {
|
||||
if (*endp)
|
||||
die("Garbage after path in: %s", command_buf.buf);
|
||||
p = p_uq;
|
||||
p = uq.buf;
|
||||
}
|
||||
tree_content_remove(&b->branch_tree, p, NULL);
|
||||
free(p_uq);
|
||||
}
|
||||
|
||||
static void file_change_cr(struct branch *b, int rename)
|
||||
{
|
||||
const char *s, *d;
|
||||
char *s_uq, *d_uq;
|
||||
static struct strbuf s_uq = STRBUF_INIT;
|
||||
static struct strbuf d_uq = STRBUF_INIT;
|
||||
const char *endp;
|
||||
struct tree_entry leaf;
|
||||
|
||||
s = command_buf.buf + 2;
|
||||
s_uq = unquote_c_style(s, &endp);
|
||||
if (s_uq) {
|
||||
strbuf_reset(&s_uq);
|
||||
if (!unquote_c_style(&s_uq, s, &endp)) {
|
||||
if (*endp != ' ')
|
||||
die("Missing space after source: %s", command_buf.buf);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
endp = strchr(s, ' ');
|
||||
if (!endp)
|
||||
die("Missing space after source: %s", command_buf.buf);
|
||||
s_uq = xmalloc(endp - s + 1);
|
||||
memcpy(s_uq, s, endp - s);
|
||||
s_uq[endp - s] = 0;
|
||||
strbuf_add(&s_uq, s, endp - s);
|
||||
}
|
||||
s = s_uq;
|
||||
s = s_uq.buf;
|
||||
|
||||
endp++;
|
||||
if (!*endp)
|
||||
die("Missing dest: %s", command_buf.buf);
|
||||
|
||||
d = endp;
|
||||
d_uq = unquote_c_style(d, &endp);
|
||||
if (d_uq) {
|
||||
strbuf_reset(&d_uq);
|
||||
if (!unquote_c_style(&d_uq, d, &endp)) {
|
||||
if (*endp)
|
||||
die("Garbage after dest in: %s", command_buf.buf);
|
||||
d = d_uq;
|
||||
d = d_uq.buf;
|
||||
}
|
||||
|
||||
memset(&leaf, 0, sizeof(leaf));
|
||||
@ -1935,9 +1889,6 @@ static void file_change_cr(struct branch *b, int rename)
|
||||
leaf.versions[1].sha1,
|
||||
leaf.versions[1].mode,
|
||||
leaf.tree);
|
||||
|
||||
free(s_uq);
|
||||
free(d_uq);
|
||||
}
|
||||
|
||||
static void file_change_deleteall(struct branch *b)
|
||||
@ -2062,9 +2013,8 @@ static struct hash_list *cmd_merge(unsigned int *count)
|
||||
|
||||
static void cmd_new_commit(void)
|
||||
{
|
||||
static struct strbuf msg = STRBUF_INIT;
|
||||
struct branch *b;
|
||||
void *msg;
|
||||
size_t msglen;
|
||||
char *sp;
|
||||
char *author = NULL;
|
||||
char *committer = NULL;
|
||||
@ -2089,7 +2039,7 @@ static void cmd_new_commit(void)
|
||||
}
|
||||
if (!committer)
|
||||
die("Expected committer but didn't get one");
|
||||
msg = cmd_data(&msglen);
|
||||
cmd_data(&msg);
|
||||
read_next_command();
|
||||
cmd_from(b);
|
||||
merge_list = cmd_merge(&merge_count);
|
||||
@ -2101,7 +2051,7 @@ static void cmd_new_commit(void)
|
||||
}
|
||||
|
||||
/* file_change* */
|
||||
while (!command_buf.eof && command_buf.len > 1) {
|
||||
while (command_buf.len > 0) {
|
||||
if (!prefixcmp(command_buf.buf, "M "))
|
||||
file_change_m(b);
|
||||
else if (!prefixcmp(command_buf.buf, "D "))
|
||||
@ -2116,53 +2066,47 @@ static void cmd_new_commit(void)
|
||||
unread_command_buf = 1;
|
||||
break;
|
||||
}
|
||||
read_next_command();
|
||||
if (read_next_command() == EOF)
|
||||
break;
|
||||
}
|
||||
|
||||
/* build the tree and the commit */
|
||||
store_tree(&b->branch_tree);
|
||||
hashcpy(b->branch_tree.versions[0].sha1,
|
||||
b->branch_tree.versions[1].sha1);
|
||||
size_dbuf(&new_data, 114 + msglen
|
||||
+ merge_count * 49
|
||||
+ (author
|
||||
? strlen(author) + strlen(committer)
|
||||
: 2 * strlen(committer)));
|
||||
sp = new_data.buffer;
|
||||
sp += sprintf(sp, "tree %s\n",
|
||||
|
||||
strbuf_reset(&new_data);
|
||||
strbuf_addf(&new_data, "tree %s\n",
|
||||
sha1_to_hex(b->branch_tree.versions[1].sha1));
|
||||
if (!is_null_sha1(b->sha1))
|
||||
sp += sprintf(sp, "parent %s\n", sha1_to_hex(b->sha1));
|
||||
strbuf_addf(&new_data, "parent %s\n", sha1_to_hex(b->sha1));
|
||||
while (merge_list) {
|
||||
struct hash_list *next = merge_list->next;
|
||||
sp += sprintf(sp, "parent %s\n", sha1_to_hex(merge_list->sha1));
|
||||
strbuf_addf(&new_data, "parent %s\n", sha1_to_hex(merge_list->sha1));
|
||||
free(merge_list);
|
||||
merge_list = next;
|
||||
}
|
||||
sp += sprintf(sp, "author %s\n", author ? author : committer);
|
||||
sp += sprintf(sp, "committer %s\n", committer);
|
||||
*sp++ = '\n';
|
||||
memcpy(sp, msg, msglen);
|
||||
sp += msglen;
|
||||
strbuf_addf(&new_data,
|
||||
"author %s\n"
|
||||
"committer %s\n"
|
||||
"\n",
|
||||
author ? author : committer, committer);
|
||||
strbuf_addbuf(&new_data, &msg);
|
||||
free(author);
|
||||
free(committer);
|
||||
free(msg);
|
||||
|
||||
if (!store_object(OBJ_COMMIT,
|
||||
new_data.buffer, sp - (char*)new_data.buffer,
|
||||
NULL, b->sha1, next_mark))
|
||||
if (!store_object(OBJ_COMMIT, &new_data, NULL, b->sha1, next_mark))
|
||||
b->pack_id = pack_id;
|
||||
b->last_commit = object_count_by_type[OBJ_COMMIT];
|
||||
}
|
||||
|
||||
static void cmd_new_tag(void)
|
||||
{
|
||||
static struct strbuf msg = STRBUF_INIT;
|
||||
char *sp;
|
||||
const char *from;
|
||||
char *tagger;
|
||||
struct branch *s;
|
||||
void *msg;
|
||||
size_t msglen;
|
||||
struct tag *t;
|
||||
uintmax_t from_mark = 0;
|
||||
unsigned char sha1[20];
|
||||
@ -2213,24 +2157,21 @@ static void cmd_new_tag(void)
|
||||
|
||||
/* tag payload/message */
|
||||
read_next_command();
|
||||
msg = cmd_data(&msglen);
|
||||
cmd_data(&msg);
|
||||
|
||||
/* build the tag object */
|
||||
size_dbuf(&new_data, 67+strlen(t->name)+strlen(tagger)+msglen);
|
||||
sp = new_data.buffer;
|
||||
sp += sprintf(sp, "object %s\n", sha1_to_hex(sha1));
|
||||
sp += sprintf(sp, "type %s\n", commit_type);
|
||||
sp += sprintf(sp, "tag %s\n", t->name);
|
||||
sp += sprintf(sp, "tagger %s\n", tagger);
|
||||
*sp++ = '\n';
|
||||
memcpy(sp, msg, msglen);
|
||||
sp += msglen;
|
||||
strbuf_reset(&new_data);
|
||||
strbuf_addf(&new_data,
|
||||
"object %s\n"
|
||||
"type %s\n"
|
||||
"tag %s\n"
|
||||
"tagger %s\n"
|
||||
"\n",
|
||||
sha1_to_hex(sha1), commit_type, t->name, tagger);
|
||||
strbuf_addbuf(&new_data, &msg);
|
||||
free(tagger);
|
||||
free(msg);
|
||||
|
||||
if (store_object(OBJ_TAG, new_data.buffer,
|
||||
sp - (char*)new_data.buffer,
|
||||
NULL, t->sha1, 0))
|
||||
if (store_object(OBJ_TAG, &new_data, NULL, t->sha1, 0))
|
||||
t->pack_id = MAX_PACK_ID;
|
||||
else
|
||||
t->pack_id = pack_id;
|
||||
@ -2256,7 +2197,7 @@ static void cmd_reset_branch(void)
|
||||
else
|
||||
b = new_branch(sp);
|
||||
read_next_command();
|
||||
if (!cmd_from(b) && command_buf.len > 1)
|
||||
if (!cmd_from(b) && command_buf.len > 0)
|
||||
unread_command_buf = 1;
|
||||
}
|
||||
|
||||
@ -2273,7 +2214,7 @@ static void cmd_checkpoint(void)
|
||||
|
||||
static void cmd_progress(void)
|
||||
{
|
||||
fwrite(command_buf.buf, 1, command_buf.len - 1, stdout);
|
||||
fwrite(command_buf.buf, 1, command_buf.len, stdout);
|
||||
fputc('\n', stdout);
|
||||
fflush(stdout);
|
||||
skip_optional_lf();
|
||||
@ -2323,7 +2264,7 @@ int main(int argc, const char **argv)
|
||||
|
||||
git_config(git_default_config);
|
||||
alloc_objects(object_entry_alloc);
|
||||
strbuf_init(&command_buf);
|
||||
strbuf_init(&command_buf, 0);
|
||||
atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*));
|
||||
branch_table = xcalloc(branch_table_sz, sizeof(struct branch*));
|
||||
avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
|
||||
@ -2381,11 +2322,8 @@ int main(int argc, const char **argv)
|
||||
prepare_packed_git();
|
||||
start_packfile();
|
||||
set_die_routine(die_nicely);
|
||||
for (;;) {
|
||||
read_next_command();
|
||||
if (command_buf.eof)
|
||||
break;
|
||||
else if (!strcmp("blob", command_buf.buf))
|
||||
while (read_next_command() != EOF) {
|
||||
if (!strcmp("blob", command_buf.buf))
|
||||
cmd_new_blob();
|
||||
else if (!prefixcmp(command_buf.buf, "commit "))
|
||||
cmd_new_commit();
|
||||
|
7
fetch.c
7
fetch.c
@ -6,7 +6,6 @@
|
||||
#include "tag.h"
|
||||
#include "blob.h"
|
||||
#include "refs.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
int get_tree = 0;
|
||||
int get_history = 0;
|
||||
@ -218,13 +217,12 @@ int pull_targets_stdin(char ***target, const char ***write_ref)
|
||||
int targets = 0, targets_alloc = 0;
|
||||
struct strbuf buf;
|
||||
*target = NULL; *write_ref = NULL;
|
||||
strbuf_init(&buf);
|
||||
strbuf_init(&buf, 0);
|
||||
while (1) {
|
||||
char *rf_one = NULL;
|
||||
char *tg_one;
|
||||
|
||||
read_line(&buf, stdin, '\n');
|
||||
if (buf.eof)
|
||||
if (strbuf_getline(&buf, stdin, '\n') == EOF)
|
||||
break;
|
||||
tg_one = buf.buf;
|
||||
rf_one = strchr(tg_one, '\t');
|
||||
@ -240,6 +238,7 @@ int pull_targets_stdin(char ***target, const char ***write_ref)
|
||||
(*write_ref)[targets] = rf_one ? xstrdup(rf_one) : NULL;
|
||||
targets++;
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
return targets;
|
||||
}
|
||||
|
||||
|
@ -211,19 +211,20 @@ static inline void *xmalloc(size_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline char *xstrndup(const char *str, size_t len)
|
||||
static inline void *xmemdupz(const void *data, size_t len)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = memchr(str, '\0', len);
|
||||
if (p)
|
||||
len = p - str;
|
||||
p = xmalloc(len + 1);
|
||||
memcpy(p, str, len);
|
||||
char *p = xmalloc(len + 1);
|
||||
memcpy(p, data, len);
|
||||
p[len] = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline char *xstrndup(const char *str, size_t len)
|
||||
{
|
||||
char *p = memchr(str, '\0', len);
|
||||
return xmemdupz(str, p ? p - str : len);
|
||||
}
|
||||
|
||||
static inline void *xrealloc(void *ptr, size_t size)
|
||||
{
|
||||
void *ret = realloc(ptr, size);
|
||||
|
16
git.c
16
git.c
@ -187,19 +187,13 @@ static int handle_alias(int *argcp, const char ***argv)
|
||||
if (alias_string) {
|
||||
if (alias_string[0] == '!') {
|
||||
if (*argcp > 1) {
|
||||
int i, sz = PATH_MAX;
|
||||
char *s = xmalloc(sz), *new_alias = s;
|
||||
struct strbuf buf;
|
||||
|
||||
add_to_string(&s, &sz, alias_string, 0);
|
||||
strbuf_init(&buf, PATH_MAX);
|
||||
strbuf_addstr(&buf, alias_string);
|
||||
sq_quote_argv(&buf, (*argv) + 1, *argcp - 1, PATH_MAX);
|
||||
free(alias_string);
|
||||
alias_string = new_alias;
|
||||
for (i = 1; i < *argcp &&
|
||||
!add_to_string(&s, &sz, " ", 0) &&
|
||||
!add_to_string(&s, &sz, (*argv)[i], 1)
|
||||
; i++)
|
||||
; /* do nothing */
|
||||
if (!sz)
|
||||
die("Too many or long arguments");
|
||||
alias_string = buf.buf;
|
||||
}
|
||||
trace_printf("trace: alias to shell cmd: %s => %s\n",
|
||||
alias_command, alias_string + 1);
|
||||
|
@ -1271,10 +1271,7 @@ xml_cdata(void *userData, const XML_Char *s, int len)
|
||||
{
|
||||
struct xml_ctx *ctx = (struct xml_ctx *)userData;
|
||||
free(ctx->cdata);
|
||||
ctx->cdata = xmalloc(len + 1);
|
||||
/* NB: 's' is not null-terminated, can not use strlcpy here */
|
||||
memcpy(ctx->cdata, s, len);
|
||||
ctx->cdata[len] = '\0';
|
||||
ctx->cdata = xmemdupz(s, len);
|
||||
}
|
||||
|
||||
static struct remote_lock *lock_remote(const char *path, long timeout)
|
||||
@ -2172,9 +2169,7 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
|
||||
|
||||
/* If it's a symref, set the refname; otherwise try for a sha1 */
|
||||
if (!prefixcmp((char *)buffer.buffer, "ref: ")) {
|
||||
*symref = xmalloc(buffer.posn - 5);
|
||||
memcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 6);
|
||||
(*symref)[buffer.posn - 6] = '\0';
|
||||
*symref = xmemdupz((char *)buffer.buffer + 5, buffer.posn - 6);
|
||||
} else {
|
||||
get_sha1_hex(buffer.buffer, sha1);
|
||||
}
|
||||
|
61
imap-send.c
61
imap-send.c
@ -105,6 +105,19 @@ static void free_generic_messages( message_t * );
|
||||
|
||||
static int nfsnprintf( char *buf, int blen, const char *fmt, ... );
|
||||
|
||||
static int nfvasprintf(char **strp, const char *fmt, va_list ap)
|
||||
{
|
||||
int len;
|
||||
char tmp[8192];
|
||||
|
||||
len = vsnprintf(tmp, sizeof(tmp), fmt, ap);
|
||||
if (len < 0)
|
||||
die("Fatal: Out of memory\n");
|
||||
if (len >= sizeof(tmp))
|
||||
die("imap command overflow !\n");
|
||||
*strp = xmemdupz(tmp, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static void arc4_init( void );
|
||||
static unsigned char arc4_getbyte( void );
|
||||
@ -623,9 +636,7 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level )
|
||||
goto bail;
|
||||
cur->len = s - p;
|
||||
s++;
|
||||
cur->val = xmalloc( cur->len + 1 );
|
||||
memcpy( cur->val, p, cur->len );
|
||||
cur->val[cur->len] = 0;
|
||||
cur->val = xmemdupz(p, cur->len);
|
||||
} else {
|
||||
/* atom */
|
||||
p = s;
|
||||
@ -633,12 +644,10 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level )
|
||||
if (level && *s == ')')
|
||||
break;
|
||||
cur->len = s - p;
|
||||
if (cur->len == 3 && !memcmp ("NIL", p, 3))
|
||||
if (cur->len == 3 && !memcmp ("NIL", p, 3)) {
|
||||
cur->val = NIL;
|
||||
else {
|
||||
cur->val = xmalloc( cur->len + 1 );
|
||||
memcpy( cur->val, p, cur->len );
|
||||
cur->val[cur->len] = 0;
|
||||
} else {
|
||||
cur->val = xmemdupz(p, cur->len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1160,28 +1169,18 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
|
||||
static int
|
||||
read_message( FILE *f, msg_data_t *msg )
|
||||
{
|
||||
int len, r;
|
||||
struct strbuf buf;
|
||||
|
||||
memset( msg, 0, sizeof *msg );
|
||||
len = CHUNKSIZE;
|
||||
msg->data = xmalloc( len+1 );
|
||||
msg->data[0] = 0;
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
strbuf_init(&buf, 0);
|
||||
|
||||
while(!feof( f )) {
|
||||
if (msg->len >= len) {
|
||||
void *p;
|
||||
len += CHUNKSIZE;
|
||||
p = xrealloc(msg->data, len+1);
|
||||
if (!p)
|
||||
break;
|
||||
msg->data = p;
|
||||
}
|
||||
r = fread( &msg->data[msg->len], 1, len - msg->len, f );
|
||||
if (r <= 0)
|
||||
do {
|
||||
if (strbuf_fread(&buf, CHUNKSIZE, f) <= 0)
|
||||
break;
|
||||
msg->len += r;
|
||||
}
|
||||
msg->data[msg->len] = 0;
|
||||
} while (!feof(f));
|
||||
|
||||
msg->len = buf.len;
|
||||
msg->data = strbuf_detach(&buf, NULL);
|
||||
return msg->len;
|
||||
}
|
||||
|
||||
@ -1231,13 +1230,7 @@ split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs )
|
||||
if (p)
|
||||
msg->len = &p[1] - data;
|
||||
|
||||
msg->data = xmalloc( msg->len + 1 );
|
||||
if (!msg->data)
|
||||
return 0;
|
||||
|
||||
memcpy( msg->data, data, msg->len );
|
||||
msg->data[ msg->len ] = 0;
|
||||
|
||||
msg->data = xmemdupz(data, msg->len);
|
||||
*ofs += msg->len;
|
||||
return 1;
|
||||
}
|
||||
|
@ -44,9 +44,8 @@ void interp_clear_table(struct interp *table, int ninterps)
|
||||
* { "%%", "%"},
|
||||
* }
|
||||
*
|
||||
* Returns 0 on a successful substitution pass that fits in result,
|
||||
* Returns a number of bytes needed to hold the full substituted
|
||||
* string otherwise.
|
||||
* Returns the length of the substituted string (not including the final \0).
|
||||
* Like with snprintf, if the result is >= reslen, then it overflowed.
|
||||
*/
|
||||
|
||||
unsigned long interpolate(char *result, unsigned long reslen,
|
||||
@ -61,8 +60,6 @@ unsigned long interpolate(char *result, unsigned long reslen,
|
||||
int i;
|
||||
char c;
|
||||
|
||||
memset(result, 0, reslen);
|
||||
|
||||
while ((c = *src)) {
|
||||
if (c == '%') {
|
||||
/* Try to match an interpolation string. */
|
||||
@ -78,9 +75,9 @@ unsigned long interpolate(char *result, unsigned long reslen,
|
||||
value = interps[i].value;
|
||||
valuelen = strlen(value);
|
||||
|
||||
if (newlen + valuelen + 1 < reslen) {
|
||||
if (newlen + valuelen < reslen) {
|
||||
/* Substitute. */
|
||||
strncpy(dest, value, valuelen);
|
||||
memcpy(dest, value, valuelen);
|
||||
dest += valuelen;
|
||||
}
|
||||
newlen += valuelen;
|
||||
@ -95,8 +92,9 @@ unsigned long interpolate(char *result, unsigned long reslen,
|
||||
newlen++;
|
||||
}
|
||||
|
||||
if (newlen + 1 < reslen)
|
||||
return 0;
|
||||
else
|
||||
return newlen + 2;
|
||||
/* XXX: the previous loop always keep room for the ending NUL,
|
||||
we just need to check if there was room for a NUL in the first place */
|
||||
if (reslen > 0)
|
||||
*dest = '\0';
|
||||
return newlen;
|
||||
}
|
||||
|
52
log-tree.c
52
log-tree.c
@ -79,25 +79,14 @@ static int detect_any_signoff(char *letter, int size)
|
||||
return seen_head && seen_name;
|
||||
}
|
||||
|
||||
static unsigned long append_signoff(char **buf_p, unsigned long *buf_sz_p,
|
||||
unsigned long at, const char *signoff)
|
||||
static void append_signoff(struct strbuf *sb, const char *signoff)
|
||||
{
|
||||
static const char signed_off_by[] = "Signed-off-by: ";
|
||||
size_t signoff_len = strlen(signoff);
|
||||
int has_signoff = 0;
|
||||
char *cp;
|
||||
char *buf;
|
||||
unsigned long buf_sz;
|
||||
|
||||
buf = *buf_p;
|
||||
buf_sz = *buf_sz_p;
|
||||
if (buf_sz <= at + strlen(signed_off_by) + signoff_len + 3) {
|
||||
buf_sz += strlen(signed_off_by) + signoff_len + 3;
|
||||
buf = xrealloc(buf, buf_sz);
|
||||
*buf_p = buf;
|
||||
*buf_sz_p = buf_sz;
|
||||
}
|
||||
cp = buf;
|
||||
cp = sb->buf;
|
||||
|
||||
/* First see if we already have the sign-off by the signer */
|
||||
while ((cp = strstr(cp, signed_off_by))) {
|
||||
@ -105,29 +94,25 @@ static unsigned long append_signoff(char **buf_p, unsigned long *buf_sz_p,
|
||||
has_signoff = 1;
|
||||
|
||||
cp += strlen(signed_off_by);
|
||||
if (cp + signoff_len >= buf + at)
|
||||
if (cp + signoff_len >= sb->buf + sb->len)
|
||||
break;
|
||||
if (strncmp(cp, signoff, signoff_len))
|
||||
continue;
|
||||
if (!isspace(cp[signoff_len]))
|
||||
continue;
|
||||
/* we already have him */
|
||||
return at;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!has_signoff)
|
||||
has_signoff = detect_any_signoff(buf, at);
|
||||
has_signoff = detect_any_signoff(sb->buf, sb->len);
|
||||
|
||||
if (!has_signoff)
|
||||
buf[at++] = '\n';
|
||||
strbuf_addch(sb, '\n');
|
||||
|
||||
strcpy(buf + at, signed_off_by);
|
||||
at += strlen(signed_off_by);
|
||||
strcpy(buf + at, signoff);
|
||||
at += signoff_len;
|
||||
buf[at++] = '\n';
|
||||
buf[at] = 0;
|
||||
return at;
|
||||
strbuf_addstr(sb, signed_off_by);
|
||||
strbuf_add(sb, signoff, signoff_len);
|
||||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
|
||||
static unsigned int digits_in_number(unsigned int number)
|
||||
@ -142,14 +127,12 @@ static unsigned int digits_in_number(unsigned int number)
|
||||
|
||||
void show_log(struct rev_info *opt, const char *sep)
|
||||
{
|
||||
char *msgbuf = NULL;
|
||||
unsigned long msgbuf_len = 0;
|
||||
struct strbuf msgbuf;
|
||||
struct log_info *log = opt->loginfo;
|
||||
struct commit *commit = log->commit, *parent = log->parent;
|
||||
int abbrev = opt->diffopt.abbrev;
|
||||
int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40;
|
||||
const char *extra;
|
||||
int len;
|
||||
const char *subject = NULL, *extra_headers = opt->extra_headers;
|
||||
|
||||
opt->loginfo = NULL;
|
||||
@ -288,18 +271,17 @@ void show_log(struct rev_info *opt, const char *sep)
|
||||
/*
|
||||
* And then the pretty-printed message itself
|
||||
*/
|
||||
len = pretty_print_commit(opt->commit_format, commit, ~0u,
|
||||
&msgbuf, &msgbuf_len, abbrev, subject,
|
||||
extra_headers, opt->date_mode);
|
||||
strbuf_init(&msgbuf, 0);
|
||||
pretty_print_commit(opt->commit_format, commit, &msgbuf,
|
||||
abbrev, subject, extra_headers, opt->date_mode);
|
||||
|
||||
if (opt->add_signoff)
|
||||
len = append_signoff(&msgbuf, &msgbuf_len, len,
|
||||
opt->add_signoff);
|
||||
append_signoff(&msgbuf, opt->add_signoff);
|
||||
if (opt->show_log_size)
|
||||
printf("log size %i\n", len);
|
||||
printf("log size %i\n", (int)msgbuf.len);
|
||||
|
||||
printf("%s%s%s", msgbuf, extra, sep);
|
||||
free(msgbuf);
|
||||
printf("%s%s%s", msgbuf.buf, extra, sep);
|
||||
strbuf_release(&msgbuf);
|
||||
}
|
||||
|
||||
int log_tree_diff_flush(struct rev_info *opt)
|
||||
|
@ -85,12 +85,6 @@ struct stage_data
|
||||
unsigned processed:1;
|
||||
};
|
||||
|
||||
struct output_buffer
|
||||
{
|
||||
struct output_buffer *next;
|
||||
char *str;
|
||||
};
|
||||
|
||||
static struct path_list current_file_set = {NULL, 0, 0, 1};
|
||||
static struct path_list current_directory_set = {NULL, 0, 0, 1};
|
||||
|
||||
@ -98,51 +92,52 @@ static int call_depth = 0;
|
||||
static int verbosity = 2;
|
||||
static int rename_limit = -1;
|
||||
static int buffer_output = 1;
|
||||
static struct output_buffer *output_list, *output_end;
|
||||
static struct strbuf obuf = STRBUF_INIT;
|
||||
|
||||
static int show (int v)
|
||||
static int show(int v)
|
||||
{
|
||||
return (!call_depth && verbosity >= v) || verbosity >= 5;
|
||||
}
|
||||
|
||||
static void output(int v, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if (buffer_output && show(v)) {
|
||||
struct output_buffer *b = xmalloc(sizeof(*b));
|
||||
nfvasprintf(&b->str, fmt, args);
|
||||
b->next = NULL;
|
||||
if (output_end)
|
||||
output_end->next = b;
|
||||
else
|
||||
output_list = b;
|
||||
output_end = b;
|
||||
} else if (show(v)) {
|
||||
int i;
|
||||
for (i = call_depth; i--;)
|
||||
fputs(" ", stdout);
|
||||
vfprintf(stdout, fmt, args);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void flush_output(void)
|
||||
{
|
||||
struct output_buffer *b, *n;
|
||||
for (b = output_list; b; b = n) {
|
||||
int i;
|
||||
for (i = call_depth; i--;)
|
||||
fputs(" ", stdout);
|
||||
fputs(b->str, stdout);
|
||||
fputc('\n', stdout);
|
||||
n = b->next;
|
||||
free(b->str);
|
||||
free(b);
|
||||
if (obuf.len) {
|
||||
fputs(obuf.buf, stdout);
|
||||
strbuf_reset(&obuf);
|
||||
}
|
||||
output_list = NULL;
|
||||
output_end = NULL;
|
||||
}
|
||||
|
||||
static void output(int v, const char *fmt, ...)
|
||||
{
|
||||
int len;
|
||||
va_list ap;
|
||||
|
||||
if (!show(v))
|
||||
return;
|
||||
|
||||
strbuf_grow(&obuf, call_depth * 2 + 2);
|
||||
memset(obuf.buf + obuf.len, ' ', call_depth * 2);
|
||||
strbuf_setlen(&obuf, obuf.len + call_depth * 2);
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(obuf.buf + obuf.len, strbuf_avail(&obuf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len >= strbuf_avail(&obuf)) {
|
||||
strbuf_grow(&obuf, len + 2);
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(obuf.buf + obuf.len, strbuf_avail(&obuf), fmt, ap);
|
||||
va_end(ap);
|
||||
if (len >= strbuf_avail(&obuf)) {
|
||||
die("this should not happen, your snprintf is broken");
|
||||
}
|
||||
}
|
||||
strbuf_setlen(&obuf, obuf.len + len);
|
||||
strbuf_add(&obuf, "\n", 1);
|
||||
if (!buffer_output)
|
||||
flush_output();
|
||||
}
|
||||
|
||||
static void output_commit_title(struct commit *commit)
|
||||
@ -434,19 +429,15 @@ static int update_stages(const char *path, struct diff_filespec *o,
|
||||
|
||||
static int remove_path(const char *name)
|
||||
{
|
||||
int ret, len;
|
||||
int ret;
|
||||
char *slash, *dirs;
|
||||
|
||||
ret = unlink(name);
|
||||
if (ret)
|
||||
return ret;
|
||||
len = strlen(name);
|
||||
dirs = xmalloc(len+1);
|
||||
memcpy(dirs, name, len);
|
||||
dirs[len] = '\0';
|
||||
dirs = xstrdup(name);
|
||||
while ((slash = strrchr(name, '/'))) {
|
||||
*slash = '\0';
|
||||
len = slash - name;
|
||||
if (rmdir(name) != 0)
|
||||
break;
|
||||
}
|
||||
@ -580,9 +571,7 @@ static void update_file_flags(const unsigned char *sha,
|
||||
flush_buffer(fd, buf, size);
|
||||
close(fd);
|
||||
} else if (S_ISLNK(mode)) {
|
||||
char *lnk = xmalloc(size + 1);
|
||||
memcpy(lnk, buf, size);
|
||||
lnk[size] = '\0';
|
||||
char *lnk = xmemdupz(buf, size);
|
||||
mkdir_p(path, 0777);
|
||||
unlink(path);
|
||||
symlink(lnk, path);
|
||||
@ -874,14 +863,9 @@ static int read_merge_config(const char *var, const char *value)
|
||||
if (!strncmp(fn->name, name, namelen) && !fn->name[namelen])
|
||||
break;
|
||||
if (!fn) {
|
||||
char *namebuf;
|
||||
fn = xcalloc(1, sizeof(struct ll_merge_driver));
|
||||
namebuf = xmalloc(namelen + 1);
|
||||
memcpy(namebuf, name, namelen);
|
||||
namebuf[namelen] = 0;
|
||||
fn->name = namebuf;
|
||||
fn->name = xmemdupz(name, namelen);
|
||||
fn->fn = ll_ext_merge;
|
||||
fn->next = NULL;
|
||||
*ll_user_merge_tail = fn;
|
||||
ll_user_merge_tail = &(fn->next);
|
||||
}
|
||||
|
14
mktag.c
14
mktag.c
@ -111,8 +111,7 @@ static int verify_tag(char *buffer, unsigned long size)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned long size = 4096;
|
||||
char *buffer = xmalloc(size);
|
||||
struct strbuf buf;
|
||||
unsigned char result_sha1[20];
|
||||
|
||||
if (argc != 1)
|
||||
@ -120,21 +119,20 @@ int main(int argc, char **argv)
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
if (read_fd(0, &buffer, &size)) {
|
||||
free(buffer);
|
||||
strbuf_init(&buf, 0);
|
||||
if (strbuf_read(&buf, 0, 4096) < 0) {
|
||||
die("could not read from stdin");
|
||||
}
|
||||
|
||||
/* Verify it for some basic sanity: it needs to start with
|
||||
"object <sha1>\ntype\ntagger " */
|
||||
if (verify_tag(buffer, size) < 0)
|
||||
if (verify_tag(buf.buf, buf.len) < 0)
|
||||
die("invalid tag signature file");
|
||||
|
||||
if (write_sha1_file(buffer, size, tag_type, result_sha1) < 0)
|
||||
if (write_sha1_file(buf.buf, buf.len, tag_type, result_sha1) < 0)
|
||||
die("unable to write tag file");
|
||||
|
||||
free(buffer);
|
||||
|
||||
strbuf_release(&buf);
|
||||
printf("%s\n", sha1_to_hex(result_sha1));
|
||||
return 0;
|
||||
}
|
||||
|
56
mktree.c
56
mktree.c
@ -4,7 +4,6 @@
|
||||
* Copyright (c) Junio C Hamano, 2006
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "strbuf.h"
|
||||
#include "quote.h"
|
||||
#include "tree.h"
|
||||
|
||||
@ -44,30 +43,22 @@ static int ent_compare(const void *a_, const void *b_)
|
||||
|
||||
static void write_tree(unsigned char *sha1)
|
||||
{
|
||||
char *buffer;
|
||||
unsigned long size, offset;
|
||||
struct strbuf buf;
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
qsort(entries, used, sizeof(*entries), ent_compare);
|
||||
for (size = i = 0; i < used; i++)
|
||||
size += 32 + entries[i]->len;
|
||||
buffer = xmalloc(size);
|
||||
offset = 0;
|
||||
|
||||
strbuf_init(&buf, size);
|
||||
for (i = 0; i < used; i++) {
|
||||
struct treeent *ent = entries[i];
|
||||
|
||||
if (offset + ent->len + 100 < size) {
|
||||
size = alloc_nr(offset + ent->len + 100);
|
||||
buffer = xrealloc(buffer, size);
|
||||
}
|
||||
offset += sprintf(buffer + offset, "%o ", ent->mode);
|
||||
offset += sprintf(buffer + offset, "%s", ent->name);
|
||||
buffer[offset++] = 0;
|
||||
hashcpy((unsigned char*)buffer + offset, ent->sha1);
|
||||
offset += 20;
|
||||
strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
|
||||
strbuf_add(&buf, ent->sha1, 20);
|
||||
}
|
||||
write_sha1_file(buffer, offset, tree_type, sha1);
|
||||
|
||||
write_sha1_file(buf.buf, buf.len, tree_type, sha1);
|
||||
}
|
||||
|
||||
static const char mktree_usage[] = "git-mktree [-z]";
|
||||
@ -75,6 +66,7 @@ static const char mktree_usage[] = "git-mktree [-z]";
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
struct strbuf sb;
|
||||
struct strbuf p_uq;
|
||||
unsigned char sha1[20];
|
||||
int line_termination = '\n';
|
||||
|
||||
@ -90,18 +82,14 @@ int main(int ac, char **av)
|
||||
av++;
|
||||
}
|
||||
|
||||
strbuf_init(&sb);
|
||||
while (1) {
|
||||
int len;
|
||||
strbuf_init(&sb, 0);
|
||||
strbuf_init(&p_uq, 0);
|
||||
while (strbuf_getline(&sb, stdin, line_termination) != EOF) {
|
||||
char *ptr, *ntr;
|
||||
unsigned mode;
|
||||
enum object_type type;
|
||||
char *path;
|
||||
|
||||
read_line(&sb, stdin, line_termination);
|
||||
if (sb.eof)
|
||||
break;
|
||||
len = sb.len;
|
||||
ptr = sb.buf;
|
||||
/* Input is non-recursive ls-tree output format
|
||||
* mode SP type SP sha1 TAB name
|
||||
@ -111,7 +99,7 @@ int main(int ac, char **av)
|
||||
die("input format error: %s", sb.buf);
|
||||
ptr = ntr + 1; /* type */
|
||||
ntr = strchr(ptr, ' ');
|
||||
if (!ntr || sb.buf + len <= ntr + 41 ||
|
||||
if (!ntr || sb.buf + sb.len <= ntr + 40 ||
|
||||
ntr[41] != '\t' ||
|
||||
get_sha1_hex(ntr + 1, sha1))
|
||||
die("input format error: %s", sb.buf);
|
||||
@ -121,17 +109,21 @@ int main(int ac, char **av)
|
||||
*ntr++ = 0; /* now at the beginning of SHA1 */
|
||||
if (type != type_from_string(ptr))
|
||||
die("object type %s mismatch (%s)", ptr, typename(type));
|
||||
ntr += 41; /* at the beginning of name */
|
||||
if (line_termination && ntr[0] == '"')
|
||||
path = unquote_c_style(ntr, NULL);
|
||||
else
|
||||
path = ntr;
|
||||
|
||||
path = ntr + 41; /* at the beginning of name */
|
||||
if (line_termination && path[0] == '"') {
|
||||
strbuf_reset(&p_uq);
|
||||
if (unquote_c_style(&p_uq, path, NULL)) {
|
||||
die("invalid quoting");
|
||||
}
|
||||
path = p_uq.buf;
|
||||
}
|
||||
|
||||
append_to_tree(mode, sha1, path);
|
||||
|
||||
if (path != ntr)
|
||||
free(path);
|
||||
}
|
||||
strbuf_release(&p_uq);
|
||||
strbuf_release(&sb);
|
||||
|
||||
write_tree(sha1);
|
||||
puts(sha1_to_hex(sha1));
|
||||
exit(0);
|
||||
|
399
quote.c
399
quote.c
@ -12,37 +12,31 @@
|
||||
* a'b ==> a'\''b ==> 'a'\''b'
|
||||
* a!b ==> a'\!'b ==> 'a'\!'b'
|
||||
*/
|
||||
#undef EMIT
|
||||
#define EMIT(x) do { if (++len < n) *bp++ = (x); } while(0)
|
||||
|
||||
static inline int need_bs_quote(char c)
|
||||
{
|
||||
return (c == '\'' || c == '!');
|
||||
}
|
||||
|
||||
static size_t sq_quote_buf(char *dst, size_t n, const char *src)
|
||||
void sq_quote_buf(struct strbuf *dst, const char *src)
|
||||
{
|
||||
char c;
|
||||
char *bp = dst;
|
||||
size_t len = 0;
|
||||
char *to_free = NULL;
|
||||
|
||||
EMIT('\'');
|
||||
while ((c = *src++)) {
|
||||
if (need_bs_quote(c)) {
|
||||
EMIT('\'');
|
||||
EMIT('\\');
|
||||
EMIT(c);
|
||||
EMIT('\'');
|
||||
} else {
|
||||
EMIT(c);
|
||||
if (dst->buf == src)
|
||||
to_free = strbuf_detach(dst, NULL);
|
||||
|
||||
strbuf_addch(dst, '\'');
|
||||
while (*src) {
|
||||
size_t len = strcspn(src, "'\\");
|
||||
strbuf_add(dst, src, len);
|
||||
src += len;
|
||||
while (need_bs_quote(*src)) {
|
||||
strbuf_addstr(dst, "'\\");
|
||||
strbuf_addch(dst, *src++);
|
||||
strbuf_addch(dst, '\'');
|
||||
}
|
||||
}
|
||||
EMIT('\'');
|
||||
|
||||
if ( n )
|
||||
*bp = 0;
|
||||
|
||||
return len;
|
||||
strbuf_addch(dst, '\'');
|
||||
free(to_free);
|
||||
}
|
||||
|
||||
void sq_quote_print(FILE *stream, const char *src)
|
||||
@ -62,11 +56,10 @@ void sq_quote_print(FILE *stream, const char *src)
|
||||
fputc('\'', stream);
|
||||
}
|
||||
|
||||
char *sq_quote_argv(const char** argv, int count)
|
||||
void sq_quote_argv(struct strbuf *dst, const char** argv, int count,
|
||||
size_t maxlen)
|
||||
{
|
||||
char *buf, *to;
|
||||
int i;
|
||||
size_t len = 0;
|
||||
|
||||
/* Count argv if needed. */
|
||||
if (count < 0) {
|
||||
@ -74,53 +67,14 @@ char *sq_quote_argv(const char** argv, int count)
|
||||
; /* just counting */
|
||||
}
|
||||
|
||||
/* Special case: no argv. */
|
||||
if (!count)
|
||||
return xcalloc(1,1);
|
||||
|
||||
/* Get destination buffer length. */
|
||||
for (i = 0; i < count; i++)
|
||||
len += sq_quote_buf(NULL, 0, argv[i]) + 1;
|
||||
|
||||
/* Alloc destination buffer. */
|
||||
to = buf = xmalloc(len + 1);
|
||||
|
||||
/* Copy into destination buffer. */
|
||||
strbuf_grow(dst, 32 * count);
|
||||
for (i = 0; i < count; ++i) {
|
||||
*to++ = ' ';
|
||||
to += sq_quote_buf(to, len, argv[i]);
|
||||
strbuf_addch(dst, ' ');
|
||||
sq_quote_buf(dst, argv[i]);
|
||||
if (maxlen && dst->len > maxlen)
|
||||
die("Too many or long arguments");
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a string to a string buffer, with or without shell quoting.
|
||||
* Return true if the buffer overflowed.
|
||||
*/
|
||||
int add_to_string(char **ptrp, int *sizep, const char *str, int quote)
|
||||
{
|
||||
char *p = *ptrp;
|
||||
int size = *sizep;
|
||||
int oc;
|
||||
int err = 0;
|
||||
|
||||
if (quote)
|
||||
oc = sq_quote_buf(p, size, str);
|
||||
else {
|
||||
oc = strlen(str);
|
||||
memcpy(p, str, (size <= oc) ? size - 1 : oc);
|
||||
}
|
||||
|
||||
if (size <= oc) {
|
||||
err = 1;
|
||||
oc = size - 1;
|
||||
}
|
||||
|
||||
*ptrp += oc;
|
||||
**ptrp = '\0';
|
||||
*sizep -= oc;
|
||||
return err;
|
||||
}
|
||||
|
||||
char *sq_dequote(char *arg)
|
||||
@ -157,186 +111,213 @@ char *sq_dequote(char *arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* 1 means: quote as octal
|
||||
* 0 means: quote as octal if (quote_path_fully)
|
||||
* -1 means: never quote
|
||||
* c: quote as "\\c"
|
||||
*/
|
||||
#define X8(x) x, x, x, x, x, x, x, x
|
||||
#define X16(x) X8(x), X8(x)
|
||||
static signed char const sq_lookup[256] = {
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
/* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a',
|
||||
/* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1,
|
||||
/* 0x10 */ X16(1),
|
||||
/* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1,
|
||||
/* 0x28 */ X16(-1), X16(-1), X16(-1),
|
||||
/* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1,
|
||||
/* 0x60 */ X16(-1), X8(-1),
|
||||
/* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1,
|
||||
/* 0x80 */ /* set to 0 */
|
||||
};
|
||||
|
||||
static inline int sq_must_quote(char c) {
|
||||
return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
|
||||
}
|
||||
|
||||
/* returns the longest prefix not needing a quote up to maxlen if positive.
|
||||
This stops at the first \0 because it's marked as a character needing an
|
||||
escape */
|
||||
static size_t next_quote_pos(const char *s, ssize_t maxlen)
|
||||
{
|
||||
size_t len;
|
||||
if (maxlen < 0) {
|
||||
for (len = 0; !sq_must_quote(s[len]); len++);
|
||||
} else {
|
||||
for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* C-style name quoting.
|
||||
*
|
||||
* Does one of three things:
|
||||
* (1) if sb and fp are both NULL, inspect the input name and counts the
|
||||
* number of bytes that are needed to hold c_style quoted version of name,
|
||||
* counting the double quotes around it but not terminating NUL, and
|
||||
* returns it.
|
||||
* However, if name does not need c_style quoting, it returns 0.
|
||||
*
|
||||
* (1) if outbuf and outfp are both NULL, inspect the input name and
|
||||
* counts the number of bytes that are needed to hold c_style
|
||||
* quoted version of name, counting the double quotes around
|
||||
* it but not terminating NUL, and returns it. However, if name
|
||||
* does not need c_style quoting, it returns 0.
|
||||
*
|
||||
* (2) if outbuf is not NULL, it must point at a buffer large enough
|
||||
* to hold the c_style quoted version of name, enclosing double
|
||||
* quotes, and terminating NUL. Fills outbuf with c_style quoted
|
||||
* version of name enclosed in double-quote pair. Return value
|
||||
* is undefined.
|
||||
*
|
||||
* (3) if outfp is not NULL, outputs c_style quoted version of name,
|
||||
* but not enclosed in double-quote pair. Return value is undefined.
|
||||
* (2) if sb or fp are not NULL, it emits the c_style quoted version
|
||||
* of name, enclosed with double quotes if asked and needed only.
|
||||
* Return value is the same as in (1).
|
||||
*/
|
||||
|
||||
static int quote_c_style_counted(const char *name, int namelen,
|
||||
char *outbuf, FILE *outfp, int no_dq)
|
||||
static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
|
||||
struct strbuf *sb, FILE *fp, int no_dq)
|
||||
{
|
||||
#undef EMIT
|
||||
#define EMIT(c) \
|
||||
(outbuf ? (*outbuf++ = (c)) : outfp ? fputc(c, outfp) : (count++))
|
||||
#define EMIT(c) \
|
||||
do { \
|
||||
if (sb) strbuf_addch(sb, (c)); \
|
||||
if (fp) fputc((c), fp); \
|
||||
count++; \
|
||||
} while (0)
|
||||
#define EMITBUF(s, l) \
|
||||
do { \
|
||||
if (sb) strbuf_add(sb, (s), (l)); \
|
||||
if (fp) fwrite((s), (l), 1, fp); \
|
||||
count += (l); \
|
||||
} while (0)
|
||||
|
||||
#define EMITQ() EMIT('\\')
|
||||
size_t len, count = 0;
|
||||
const char *p = name;
|
||||
|
||||
const char *sp;
|
||||
unsigned char ch;
|
||||
int count = 0, needquote = 0;
|
||||
for (;;) {
|
||||
int ch;
|
||||
|
||||
if (!no_dq)
|
||||
EMIT('"');
|
||||
for (sp = name; sp < name + namelen; sp++) {
|
||||
ch = *sp;
|
||||
if (!ch)
|
||||
len = next_quote_pos(p, maxlen);
|
||||
if (len == maxlen || !p[len])
|
||||
break;
|
||||
if ((ch < ' ') || (ch == '"') || (ch == '\\') ||
|
||||
(quote_path_fully && (ch >= 0177))) {
|
||||
needquote = 1;
|
||||
switch (ch) {
|
||||
case '\a': EMITQ(); ch = 'a'; break;
|
||||
case '\b': EMITQ(); ch = 'b'; break;
|
||||
case '\f': EMITQ(); ch = 'f'; break;
|
||||
case '\n': EMITQ(); ch = 'n'; break;
|
||||
case '\r': EMITQ(); ch = 'r'; break;
|
||||
case '\t': EMITQ(); ch = 't'; break;
|
||||
case '\v': EMITQ(); ch = 'v'; break;
|
||||
|
||||
case '\\': /* fallthru */
|
||||
case '"': EMITQ(); break;
|
||||
default:
|
||||
/* octal */
|
||||
EMITQ();
|
||||
EMIT(((ch >> 6) & 03) + '0');
|
||||
EMIT(((ch >> 3) & 07) + '0');
|
||||
ch = (ch & 07) + '0';
|
||||
break;
|
||||
}
|
||||
if (!no_dq && p == name)
|
||||
EMIT('"');
|
||||
|
||||
EMITBUF(p, len);
|
||||
EMIT('\\');
|
||||
p += len;
|
||||
ch = (unsigned char)*p++;
|
||||
if (sq_lookup[ch] >= ' ') {
|
||||
EMIT(sq_lookup[ch]);
|
||||
} else {
|
||||
EMIT(((ch >> 6) & 03) + '0');
|
||||
EMIT(((ch >> 3) & 07) + '0');
|
||||
EMIT(((ch >> 0) & 07) + '0');
|
||||
}
|
||||
EMIT(ch);
|
||||
}
|
||||
|
||||
EMITBUF(p, len);
|
||||
if (p == name) /* no ending quote needed */
|
||||
return 0;
|
||||
|
||||
if (!no_dq)
|
||||
EMIT('"');
|
||||
if (outbuf)
|
||||
*outbuf = 0;
|
||||
|
||||
return needquote ? count : 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
|
||||
size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq)
|
||||
{
|
||||
int cnt = strlen(name);
|
||||
return quote_c_style_counted(name, cnt, outbuf, outfp, no_dq);
|
||||
return quote_c_style_counted(name, -1, sb, fp, nodq);
|
||||
}
|
||||
|
||||
void write_name_quoted(const char *name, FILE *fp, int terminator)
|
||||
{
|
||||
if (terminator) {
|
||||
quote_c_style(name, NULL, fp, 0);
|
||||
} else {
|
||||
fputs(name, fp);
|
||||
}
|
||||
fputc(terminator, fp);
|
||||
}
|
||||
|
||||
extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
|
||||
const char *name, FILE *fp, int terminator)
|
||||
{
|
||||
int needquote = 0;
|
||||
|
||||
if (terminator) {
|
||||
needquote = next_quote_pos(pfx, pfxlen) < pfxlen
|
||||
|| name[next_quote_pos(name, -1)];
|
||||
}
|
||||
if (needquote) {
|
||||
fputc('"', fp);
|
||||
quote_c_style_counted(pfx, pfxlen, NULL, fp, 1);
|
||||
quote_c_style(name, NULL, fp, 1);
|
||||
fputc('"', fp);
|
||||
} else {
|
||||
fwrite(pfx, pfxlen, 1, fp);
|
||||
fputs(name, fp);
|
||||
}
|
||||
fputc(terminator, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* C-style name unquoting.
|
||||
*
|
||||
* Quoted should point at the opening double quote. Returns
|
||||
* an allocated memory that holds unquoted name, which the caller
|
||||
* should free when done. Updates endp pointer to point at
|
||||
* one past the ending double quote if given.
|
||||
* Quoted should point at the opening double quote.
|
||||
* + Returns 0 if it was able to unquote the string properly, and appends the
|
||||
* result in the strbuf `sb'.
|
||||
* + Returns -1 in case of error, and doesn't touch the strbuf. Though note
|
||||
* that this function will allocate memory in the strbuf, so calling
|
||||
* strbuf_release is mandatory whichever result unquote_c_style returns.
|
||||
*
|
||||
* Updates endp pointer to point at one past the ending double quote if given.
|
||||
*/
|
||||
|
||||
char *unquote_c_style(const char *quoted, const char **endp)
|
||||
int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp)
|
||||
{
|
||||
const char *sp;
|
||||
char *name = NULL, *outp = NULL;
|
||||
int count = 0, ch, ac;
|
||||
|
||||
#undef EMIT
|
||||
#define EMIT(c) (outp ? (*outp++ = (c)) : (count++))
|
||||
size_t oldlen = sb->len, len;
|
||||
int ch, ac;
|
||||
|
||||
if (*quoted++ != '"')
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
while (1) {
|
||||
/* first pass counts and allocates, second pass fills */
|
||||
for (sp = quoted; (ch = *sp++) != '"'; ) {
|
||||
if (ch == '\\') {
|
||||
switch (ch = *sp++) {
|
||||
case 'a': ch = '\a'; break;
|
||||
case 'b': ch = '\b'; break;
|
||||
case 'f': ch = '\f'; break;
|
||||
case 'n': ch = '\n'; break;
|
||||
case 'r': ch = '\r'; break;
|
||||
case 't': ch = '\t'; break;
|
||||
case 'v': ch = '\v'; break;
|
||||
for (;;) {
|
||||
len = strcspn(quoted, "\"\\");
|
||||
strbuf_add(sb, quoted, len);
|
||||
quoted += len;
|
||||
|
||||
case '\\': case '"':
|
||||
break; /* verbatim */
|
||||
switch (*quoted++) {
|
||||
case '"':
|
||||
if (endp)
|
||||
*endp = quoted + 1;
|
||||
return 0;
|
||||
case '\\':
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
/* octal */
|
||||
switch ((ch = *quoted++)) {
|
||||
case 'a': ch = '\a'; break;
|
||||
case 'b': ch = '\b'; break;
|
||||
case 'f': ch = '\f'; break;
|
||||
case 'n': ch = '\n'; break;
|
||||
case 'r': ch = '\r'; break;
|
||||
case 't': ch = '\t'; break;
|
||||
case 'v': ch = '\v'; break;
|
||||
|
||||
case '\\': case '"':
|
||||
break; /* verbatim */
|
||||
|
||||
/* octal values with first digit over 4 overflow */
|
||||
case '0': case '1': case '2': case '3':
|
||||
ac = ((ch - '0') << 6);
|
||||
if ((ch = *sp++) < '0' || '7' < ch)
|
||||
return NULL;
|
||||
if ((ch = *quoted++) < '0' || '7' < ch)
|
||||
goto error;
|
||||
ac |= ((ch - '0') << 3);
|
||||
if ((ch = *sp++) < '0' || '7' < ch)
|
||||
return NULL;
|
||||
if ((ch = *quoted++) < '0' || '7' < ch)
|
||||
goto error;
|
||||
ac |= (ch - '0');
|
||||
ch = ac;
|
||||
break;
|
||||
default:
|
||||
return NULL; /* malformed */
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
EMIT(ch);
|
||||
strbuf_addch(sb, ch);
|
||||
}
|
||||
|
||||
if (name) {
|
||||
*outp = 0;
|
||||
if (endp)
|
||||
*endp = sp;
|
||||
return name;
|
||||
}
|
||||
outp = name = xmalloc(count + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void write_name_quoted(const char *prefix, int prefix_len,
|
||||
const char *name, int quote, FILE *out)
|
||||
{
|
||||
int needquote;
|
||||
|
||||
if (!quote) {
|
||||
no_quote:
|
||||
if (prefix_len)
|
||||
fprintf(out, "%.*s", prefix_len, prefix);
|
||||
fputs(name, out);
|
||||
return;
|
||||
}
|
||||
|
||||
needquote = 0;
|
||||
if (prefix_len)
|
||||
needquote = quote_c_style_counted(prefix, prefix_len,
|
||||
NULL, NULL, 0);
|
||||
if (!needquote)
|
||||
needquote = quote_c_style(name, NULL, NULL, 0);
|
||||
if (needquote) {
|
||||
fputc('"', out);
|
||||
if (prefix_len)
|
||||
quote_c_style_counted(prefix, prefix_len,
|
||||
NULL, out, 1);
|
||||
quote_c_style(name, NULL, out, 1);
|
||||
fputc('"', out);
|
||||
}
|
||||
else
|
||||
goto no_quote;
|
||||
error:
|
||||
strbuf_setlen(sb, oldlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* quoting as a string literal for other languages */
|
||||
|
19
quote.h
19
quote.h
@ -29,13 +29,10 @@
|
||||
*/
|
||||
|
||||
extern void sq_quote_print(FILE *stream, const char *src);
|
||||
extern char *sq_quote_argv(const char** argv, int count);
|
||||
|
||||
/*
|
||||
* Append a string to a string buffer, with or without shell quoting.
|
||||
* Return true if the buffer overflowed.
|
||||
*/
|
||||
extern int add_to_string(char **ptrp, int *sizep, const char *str, int quote);
|
||||
extern void sq_quote_buf(struct strbuf *, const char *src);
|
||||
extern void sq_quote_argv(struct strbuf *, const char **argv, int count,
|
||||
size_t maxlen);
|
||||
|
||||
/* This unwraps what sq_quote() produces in place, but returns
|
||||
* NULL if the input does not look like what sq_quote would have
|
||||
@ -43,12 +40,12 @@ extern int add_to_string(char **ptrp, int *sizep, const char *str, int quote);
|
||||
*/
|
||||
extern char *sq_dequote(char *);
|
||||
|
||||
extern int quote_c_style(const char *name, char *outbuf, FILE *outfp,
|
||||
int nodq);
|
||||
extern char *unquote_c_style(const char *quoted, const char **endp);
|
||||
extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
|
||||
extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
|
||||
|
||||
extern void write_name_quoted(const char *prefix, int prefix_len,
|
||||
const char *name, int quote, FILE *out);
|
||||
extern void write_name_quoted(const char *name, FILE *, int terminator);
|
||||
extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
|
||||
const char *name, FILE *, int terminator);
|
||||
|
||||
/* quoting as a string literal for other languages */
|
||||
extern void perl_quote_print(FILE *stream, const char *src);
|
||||
|
19
read-cache.c
19
read-cache.c
@ -1136,7 +1136,7 @@ int write_index(struct index_state *istate, int newfd)
|
||||
{
|
||||
SHA_CTX c;
|
||||
struct cache_header hdr;
|
||||
int i, removed;
|
||||
int i, err, removed;
|
||||
struct cache_entry **cache = istate->cache;
|
||||
int entries = istate->cache_nr;
|
||||
|
||||
@ -1165,16 +1165,15 @@ int write_index(struct index_state *istate, int newfd)
|
||||
|
||||
/* Write extension data here */
|
||||
if (istate->cache_tree) {
|
||||
unsigned long sz;
|
||||
void *data = cache_tree_write(istate->cache_tree, &sz);
|
||||
if (data &&
|
||||
!write_index_ext_header(&c, newfd, CACHE_EXT_TREE, sz) &&
|
||||
!ce_write(&c, newfd, data, sz))
|
||||
free(data);
|
||||
else {
|
||||
free(data);
|
||||
struct strbuf sb;
|
||||
|
||||
strbuf_init(&sb, 0);
|
||||
cache_tree_write(&sb, istate->cache_tree);
|
||||
err = write_index_ext_header(&c, newfd, CACHE_EXT_TREE, sb.len) < 0
|
||||
|| ce_write(&c, newfd, sb.buf, sb.len) < 0;
|
||||
strbuf_release(&sb);
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return ce_flush(&c, newfd);
|
||||
}
|
||||
|
12
refs.c
12
refs.c
@ -1246,15 +1246,11 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
|
||||
static char *ref_msg(const char *line, const char *endp)
|
||||
{
|
||||
const char *ep;
|
||||
char *msg;
|
||||
|
||||
line += 82;
|
||||
for (ep = line; ep < endp && *ep != '\n'; ep++)
|
||||
;
|
||||
msg = xmalloc(ep - line + 1);
|
||||
memcpy(msg, line, ep - line);
|
||||
msg[ep - line] = 0;
|
||||
return msg;
|
||||
ep = memchr(line, '\n', endp - line);
|
||||
if (!ep)
|
||||
ep = endp;
|
||||
return xmemdupz(line, ep - line);
|
||||
}
|
||||
|
||||
int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
|
||||
|
34
rsh.c
34
rsh.c
@ -10,12 +10,9 @@ int setup_connection(int *fd_in, int *fd_out, const char *remote_prog,
|
||||
char *host;
|
||||
char *path;
|
||||
int sv[2];
|
||||
char command[COMMAND_SIZE];
|
||||
char *posn;
|
||||
int sizen;
|
||||
int of;
|
||||
int i;
|
||||
pid_t pid;
|
||||
struct strbuf cmd;
|
||||
|
||||
if (!strcmp(url, "-")) {
|
||||
*fd_in = 0;
|
||||
@ -36,24 +33,23 @@ int setup_connection(int *fd_in, int *fd_out, const char *remote_prog,
|
||||
if (!path) {
|
||||
return error("Bad URL: %s", url);
|
||||
}
|
||||
/* $GIT_RSH <host> "env GIT_DIR=<path> <remote_prog> <args...>" */
|
||||
sizen = COMMAND_SIZE;
|
||||
posn = command;
|
||||
of = 0;
|
||||
of |= add_to_string(&posn, &sizen, "env ", 0);
|
||||
of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT "=", 0);
|
||||
of |= add_to_string(&posn, &sizen, path, 1);
|
||||
of |= add_to_string(&posn, &sizen, " ", 0);
|
||||
of |= add_to_string(&posn, &sizen, remote_prog, 1);
|
||||
|
||||
for ( i = 0 ; i < rmt_argc ; i++ ) {
|
||||
of |= add_to_string(&posn, &sizen, " ", 0);
|
||||
of |= add_to_string(&posn, &sizen, rmt_argv[i], 1);
|
||||
/* $GIT_RSH <host> "env GIT_DIR=<path> <remote_prog> <args...>" */
|
||||
strbuf_init(&cmd, COMMAND_SIZE);
|
||||
strbuf_addstr(&cmd, "env ");
|
||||
strbuf_addstr(&cmd, GIT_DIR_ENVIRONMENT "=");
|
||||
sq_quote_buf(&cmd, path);
|
||||
strbuf_addch(&cmd, ' ');
|
||||
sq_quote_buf(&cmd, remote_prog);
|
||||
|
||||
for (i = 0 ; i < rmt_argc ; i++) {
|
||||
strbuf_addch(&cmd, ' ');
|
||||
sq_quote_buf(&cmd, rmt_argv[i]);
|
||||
}
|
||||
|
||||
of |= add_to_string(&posn, &sizen, " -", 0);
|
||||
strbuf_addstr(&cmd, " -");
|
||||
|
||||
if ( of )
|
||||
if (cmd.len >= COMMAND_SIZE)
|
||||
return error("Command line too long");
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
|
||||
@ -74,7 +70,7 @@ int setup_connection(int *fd_in, int *fd_out, const char *remote_prog,
|
||||
close(sv[1]);
|
||||
dup2(sv[0], 0);
|
||||
dup2(sv[0], 1);
|
||||
execlp(ssh, ssh_basename, host, command, NULL);
|
||||
execlp(ssh, ssh_basename, host, cmd.buf, NULL);
|
||||
}
|
||||
close(sv[0]);
|
||||
*fd_in = sv[1];
|
||||
|
80
sha1_file.c
80
sha1_file.c
@ -1491,11 +1491,8 @@ found_cache_entry:
|
||||
ent->lru.next->prev = ent->lru.prev;
|
||||
ent->lru.prev->next = ent->lru.next;
|
||||
delta_base_cached -= ent->size;
|
||||
}
|
||||
else {
|
||||
ret = xmalloc(ent->size + 1);
|
||||
memcpy(ret, ent->data, ent->size);
|
||||
((char *)ret)[ent->size] = 0;
|
||||
} else {
|
||||
ret = xmemdupz(ent->data, ent->size);
|
||||
}
|
||||
*type = ent->type;
|
||||
*base_size = ent->size;
|
||||
@ -1872,12 +1869,9 @@ void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
|
||||
|
||||
co = find_cached_object(sha1);
|
||||
if (co) {
|
||||
buf = xmalloc(co->size + 1);
|
||||
memcpy(buf, co->buf, co->size);
|
||||
((char*)buf)[co->size] = 0;
|
||||
*type = co->type;
|
||||
*size = co->size;
|
||||
return buf;
|
||||
return xmemdupz(co->buf, co->size);
|
||||
}
|
||||
|
||||
buf = read_packed_sha1(sha1, type, size);
|
||||
@ -2302,68 +2296,25 @@ int has_sha1_file(const unsigned char *sha1)
|
||||
return find_sha1_file(sha1, &st) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* reads from fd as long as possible into a supplied buffer of size bytes.
|
||||
* If necessary the buffer's size is increased using realloc()
|
||||
*
|
||||
* returns 0 if anything went fine and -1 otherwise
|
||||
*
|
||||
* The buffer is always NUL-terminated, not including it in returned size.
|
||||
*
|
||||
* NOTE: both buf and size may change, but even when -1 is returned
|
||||
* you still have to free() it yourself.
|
||||
*/
|
||||
int read_fd(int fd, char **return_buf, unsigned long *return_size)
|
||||
{
|
||||
char *buf = *return_buf;
|
||||
unsigned long size = *return_size;
|
||||
ssize_t iret;
|
||||
unsigned long off = 0;
|
||||
|
||||
if (!buf || size <= 1) {
|
||||
size = 1024;
|
||||
buf = xrealloc(buf, size);
|
||||
}
|
||||
|
||||
do {
|
||||
iret = xread(fd, buf + off, (size - 1) - off);
|
||||
if (iret > 0) {
|
||||
off += iret;
|
||||
if (off == size - 1) {
|
||||
size = alloc_nr(size);
|
||||
buf = xrealloc(buf, size);
|
||||
}
|
||||
}
|
||||
} while (iret > 0);
|
||||
|
||||
buf[off] = '\0';
|
||||
|
||||
*return_buf = buf;
|
||||
*return_size = off;
|
||||
|
||||
if (iret < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object)
|
||||
{
|
||||
unsigned long size = 4096;
|
||||
char *buf = xmalloc(size);
|
||||
struct strbuf buf;
|
||||
int ret;
|
||||
|
||||
if (read_fd(fd, &buf, &size)) {
|
||||
free(buf);
|
||||
strbuf_init(&buf, 0);
|
||||
if (strbuf_read(&buf, fd, 4096) < 0) {
|
||||
strbuf_release(&buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!type)
|
||||
type = blob_type;
|
||||
if (write_object)
|
||||
ret = write_sha1_file(buf, size, type, sha1);
|
||||
ret = write_sha1_file(buf.buf, buf.len, type, sha1);
|
||||
else
|
||||
ret = hash_sha1_file(buf, size, type, sha1);
|
||||
free(buf);
|
||||
ret = hash_sha1_file(buf.buf, buf.len, type, sha1);
|
||||
strbuf_release(&buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2385,12 +2336,11 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
|
||||
* Convert blobs to git internal format
|
||||
*/
|
||||
if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) {
|
||||
unsigned long nsize = size;
|
||||
char *nbuf = convert_to_git(path, buf, &nsize);
|
||||
if (nbuf) {
|
||||
struct strbuf nbuf;
|
||||
strbuf_init(&nbuf, 0);
|
||||
if (convert_to_git(path, buf, size, &nbuf)) {
|
||||
munmap(buf, size);
|
||||
size = nsize;
|
||||
buf = nbuf;
|
||||
buf = strbuf_detach(&nbuf, &size);
|
||||
re_allocated = 1;
|
||||
}
|
||||
}
|
||||
|
211
strbuf.c
211
strbuf.c
@ -1,41 +1,202 @@
|
||||
#include "cache.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
void strbuf_init(struct strbuf *sb) {
|
||||
sb->buf = NULL;
|
||||
sb->eof = sb->alloc = sb->len = 0;
|
||||
/*
|
||||
* Used as the default ->buf value, so that people can always assume
|
||||
* buf is non NULL and ->buf is NUL terminated even for a freshly
|
||||
* initialized strbuf.
|
||||
*/
|
||||
char strbuf_slopbuf[1];
|
||||
|
||||
void strbuf_init(struct strbuf *sb, size_t hint)
|
||||
{
|
||||
sb->alloc = sb->len = 0;
|
||||
sb->buf = strbuf_slopbuf;
|
||||
if (hint)
|
||||
strbuf_grow(sb, hint);
|
||||
}
|
||||
|
||||
static void strbuf_begin(struct strbuf *sb) {
|
||||
free(sb->buf);
|
||||
strbuf_init(sb);
|
||||
}
|
||||
|
||||
static void inline strbuf_add(struct strbuf *sb, int ch) {
|
||||
if (sb->alloc <= sb->len) {
|
||||
sb->alloc = sb->alloc * 3 / 2 + 16;
|
||||
sb->buf = xrealloc(sb->buf, sb->alloc);
|
||||
void strbuf_release(struct strbuf *sb)
|
||||
{
|
||||
if (sb->alloc) {
|
||||
free(sb->buf);
|
||||
strbuf_init(sb, 0);
|
||||
}
|
||||
sb->buf[sb->len++] = ch;
|
||||
}
|
||||
|
||||
static void strbuf_end(struct strbuf *sb) {
|
||||
strbuf_add(sb, 0);
|
||||
char *strbuf_detach(struct strbuf *sb, size_t *sz)
|
||||
{
|
||||
char *res = sb->alloc ? sb->buf : NULL;
|
||||
if (sz)
|
||||
*sz = sb->len;
|
||||
strbuf_init(sb, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
void read_line(struct strbuf *sb, FILE *fp, int term) {
|
||||
void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
|
||||
{
|
||||
strbuf_release(sb);
|
||||
sb->buf = buf;
|
||||
sb->len = len;
|
||||
sb->alloc = alloc;
|
||||
strbuf_grow(sb, 0);
|
||||
sb->buf[sb->len] = '\0';
|
||||
}
|
||||
|
||||
void strbuf_grow(struct strbuf *sb, size_t extra)
|
||||
{
|
||||
if (sb->len + extra + 1 <= sb->len)
|
||||
die("you want to use way too much memory");
|
||||
if (!sb->alloc)
|
||||
sb->buf = NULL;
|
||||
ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
|
||||
}
|
||||
|
||||
void strbuf_rtrim(struct strbuf *sb)
|
||||
{
|
||||
while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
|
||||
sb->len--;
|
||||
sb->buf[sb->len] = '\0';
|
||||
}
|
||||
|
||||
int strbuf_cmp(struct strbuf *a, struct strbuf *b)
|
||||
{
|
||||
int cmp;
|
||||
if (a->len < b->len) {
|
||||
cmp = memcmp(a->buf, b->buf, a->len);
|
||||
return cmp ? cmp : -1;
|
||||
} else {
|
||||
cmp = memcmp(a->buf, b->buf, b->len);
|
||||
return cmp ? cmp : a->len != b->len;
|
||||
}
|
||||
}
|
||||
|
||||
void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
|
||||
const void *data, size_t dlen)
|
||||
{
|
||||
if (pos + len < pos)
|
||||
die("you want to use way too much memory");
|
||||
if (pos > sb->len)
|
||||
die("`pos' is too far after the end of the buffer");
|
||||
if (pos + len > sb->len)
|
||||
die("`pos + len' is too far after the end of the buffer");
|
||||
|
||||
if (dlen >= len)
|
||||
strbuf_grow(sb, dlen - len);
|
||||
memmove(sb->buf + pos + dlen,
|
||||
sb->buf + pos + len,
|
||||
sb->len - pos - len);
|
||||
memcpy(sb->buf + pos, data, dlen);
|
||||
strbuf_setlen(sb, sb->len + dlen - len);
|
||||
}
|
||||
|
||||
void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
|
||||
{
|
||||
strbuf_splice(sb, pos, 0, data, len);
|
||||
}
|
||||
|
||||
void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
|
||||
{
|
||||
strbuf_splice(sb, pos, len, NULL, 0);
|
||||
}
|
||||
|
||||
void strbuf_add(struct strbuf *sb, const void *data, size_t len)
|
||||
{
|
||||
strbuf_grow(sb, len);
|
||||
memcpy(sb->buf + sb->len, data, len);
|
||||
strbuf_setlen(sb, sb->len + len);
|
||||
}
|
||||
|
||||
void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
|
||||
{
|
||||
int len;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
|
||||
va_end(ap);
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
}
|
||||
if (len > strbuf_avail(sb)) {
|
||||
strbuf_grow(sb, len);
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
|
||||
va_end(ap);
|
||||
if (len > strbuf_avail(sb)) {
|
||||
die("this should not happen, your snprintf is broken");
|
||||
}
|
||||
}
|
||||
strbuf_setlen(sb, sb->len + len);
|
||||
}
|
||||
|
||||
size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
|
||||
{
|
||||
size_t res;
|
||||
|
||||
strbuf_grow(sb, size);
|
||||
res = fread(sb->buf + sb->len, 1, size, f);
|
||||
if (res > 0) {
|
||||
strbuf_setlen(sb, sb->len + res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
|
||||
{
|
||||
size_t oldlen = sb->len;
|
||||
|
||||
strbuf_grow(sb, hint ? hint : 8192);
|
||||
for (;;) {
|
||||
ssize_t cnt;
|
||||
|
||||
cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
|
||||
if (cnt < 0) {
|
||||
strbuf_setlen(sb, oldlen);
|
||||
return -1;
|
||||
}
|
||||
if (!cnt)
|
||||
break;
|
||||
sb->len += cnt;
|
||||
strbuf_grow(sb, 8192);
|
||||
}
|
||||
|
||||
sb->buf[sb->len] = '\0';
|
||||
return sb->len - oldlen;
|
||||
}
|
||||
|
||||
int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
|
||||
{
|
||||
int ch;
|
||||
strbuf_begin(sb);
|
||||
if (feof(fp)) {
|
||||
sb->eof = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
strbuf_grow(sb, 0);
|
||||
if (feof(fp))
|
||||
return EOF;
|
||||
|
||||
strbuf_reset(sb);
|
||||
while ((ch = fgetc(fp)) != EOF) {
|
||||
if (ch == term)
|
||||
break;
|
||||
strbuf_add(sb, ch);
|
||||
strbuf_grow(sb, 1);
|
||||
sb->buf[sb->len++] = ch;
|
||||
}
|
||||
if (ch == EOF && sb->len == 0)
|
||||
sb->eof = 1;
|
||||
strbuf_end(sb);
|
||||
return EOF;
|
||||
|
||||
sb->buf[sb->len] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
|
||||
{
|
||||
int fd, len;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
len = strbuf_read(sb, fd, hint);
|
||||
close(fd);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
114
strbuf.h
114
strbuf.h
@ -1,13 +1,117 @@
|
||||
#ifndef STRBUF_H
|
||||
#define STRBUF_H
|
||||
|
||||
/*
|
||||
* Strbuf's can be use in many ways: as a byte array, or to store arbitrary
|
||||
* long, overflow safe strings.
|
||||
*
|
||||
* Strbufs has some invariants that are very important to keep in mind:
|
||||
*
|
||||
* 1. the ->buf member is always malloc-ed, hence strbuf's can be used to
|
||||
* build complex strings/buffers whose final size isn't easily known.
|
||||
*
|
||||
* It is NOT legal to copy the ->buf pointer away.
|
||||
* `strbuf_detach' is the operation that detachs a buffer from its shell
|
||||
* while keeping the shell valid wrt its invariants.
|
||||
*
|
||||
* 2. the ->buf member is a byte array that has at least ->len + 1 bytes
|
||||
* allocated. The extra byte is used to store a '\0', allowing the ->buf
|
||||
* member to be a valid C-string. Every strbuf function ensure this
|
||||
* invariant is preserved.
|
||||
*
|
||||
* Note that it is OK to "play" with the buffer directly if you work it
|
||||
* that way:
|
||||
*
|
||||
* strbuf_grow(sb, SOME_SIZE);
|
||||
* // ... here the memory areay starting at sb->buf, and of length
|
||||
* // sb_avail(sb) is all yours, and you are sure that sb_avail(sb) is at
|
||||
* // least SOME_SIZE
|
||||
* strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE);
|
||||
*
|
||||
* Of course, SOME_OTHER_SIZE must be smaller or equal to sb_avail(sb).
|
||||
*
|
||||
* Doing so is safe, though if it has to be done in many places, adding the
|
||||
* missing API to the strbuf module is the way to go.
|
||||
*
|
||||
* XXX: do _not_ assume that the area that is yours is of size ->alloc - 1
|
||||
* even if it's true in the current implementation. Alloc is somehow a
|
||||
* "private" member that should not be messed with.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
extern char strbuf_slopbuf[];
|
||||
struct strbuf {
|
||||
int alloc;
|
||||
int len;
|
||||
int eof;
|
||||
size_t alloc;
|
||||
size_t len;
|
||||
char *buf;
|
||||
};
|
||||
|
||||
extern void strbuf_init(struct strbuf *);
|
||||
extern void read_line(struct strbuf *, FILE *, int);
|
||||
#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
|
||||
|
||||
/*----- strbuf life cycle -----*/
|
||||
extern void strbuf_init(struct strbuf *, size_t);
|
||||
extern void strbuf_release(struct strbuf *);
|
||||
extern char *strbuf_detach(struct strbuf *, size_t *);
|
||||
extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
|
||||
static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
|
||||
struct strbuf tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
/*----- strbuf size related -----*/
|
||||
static inline size_t strbuf_avail(struct strbuf *sb) {
|
||||
return sb->alloc ? sb->alloc - sb->len - 1 : 0;
|
||||
}
|
||||
|
||||
extern void strbuf_grow(struct strbuf *, size_t);
|
||||
|
||||
static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
|
||||
if (!sb->alloc)
|
||||
strbuf_grow(sb, 0);
|
||||
assert(len < sb->alloc);
|
||||
sb->len = len;
|
||||
sb->buf[len] = '\0';
|
||||
}
|
||||
#define strbuf_reset(sb) strbuf_setlen(sb, 0)
|
||||
|
||||
/*----- content related -----*/
|
||||
extern void strbuf_rtrim(struct strbuf *);
|
||||
extern int strbuf_cmp(struct strbuf *, struct strbuf *);
|
||||
|
||||
/*----- add data in your buffer -----*/
|
||||
static inline void strbuf_addch(struct strbuf *sb, int c) {
|
||||
strbuf_grow(sb, 1);
|
||||
sb->buf[sb->len++] = c;
|
||||
sb->buf[sb->len] = '\0';
|
||||
}
|
||||
|
||||
extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t);
|
||||
extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);
|
||||
|
||||
/* splice pos..pos+len with given data */
|
||||
extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,
|
||||
const void *, size_t);
|
||||
|
||||
extern void strbuf_add(struct strbuf *, const void *, size_t);
|
||||
static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
|
||||
strbuf_add(sb, s, strlen(s));
|
||||
}
|
||||
static inline void strbuf_addbuf(struct strbuf *sb, struct strbuf *sb2) {
|
||||
strbuf_add(sb, sb2->buf, sb2->len);
|
||||
}
|
||||
|
||||
__attribute__((format(printf,2,3)))
|
||||
extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
|
||||
|
||||
extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
|
||||
/* XXX: if read fails, any partial read is undone */
|
||||
extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
|
||||
extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
|
||||
|
||||
extern int strbuf_getline(struct strbuf *, FILE *, int);
|
||||
|
||||
extern void stripspace(struct strbuf *buf, int skip_comments);
|
||||
|
||||
#endif /* STRBUF_H */
|
||||
|
@ -36,7 +36,8 @@ test_expect_success \
|
||||
echo simple textfile >a/a &&
|
||||
mkdir a/bin &&
|
||||
cp /bin/sh a/bin &&
|
||||
printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile &&
|
||||
printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
|
||||
printf "A not substituted O" >a/substfile2 &&
|
||||
ln -s a a/l1 &&
|
||||
(p=long_path_to_a_file && cd a &&
|
||||
for depth in 1 2 3 4 5; do mkdir $p && cd $p; done &&
|
||||
@ -108,20 +109,22 @@ test_expect_success \
|
||||
'diff -r a c/prefix/a'
|
||||
|
||||
test_expect_success \
|
||||
'create an archive with a substfile' \
|
||||
'echo substfile export-subst >a/.gitattributes &&
|
||||
'create an archive with a substfiles' \
|
||||
'echo "substfile?" export-subst >a/.gitattributes &&
|
||||
git archive HEAD >f.tar &&
|
||||
rm a/.gitattributes'
|
||||
|
||||
test_expect_success \
|
||||
'extract substfile' \
|
||||
'extract substfiles' \
|
||||
'(mkdir f && cd f && $TAR xf -) <f.tar'
|
||||
|
||||
test_expect_success \
|
||||
'validate substfile contents' \
|
||||
'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
|
||||
>f/a/substfile.expected &&
|
||||
diff f/a/substfile.expected f/a/substfile'
|
||||
>f/a/substfile1.expected &&
|
||||
diff f/a/substfile1.expected f/a/substfile1 &&
|
||||
diff a/substfile2 f/a/substfile2
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip' \
|
||||
|
4
tag.c
4
tag.c
@ -68,9 +68,7 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
|
||||
memcpy(type, type_line + 5, typelen);
|
||||
type[typelen] = '\0';
|
||||
taglen = sig_line - tag_line - strlen("tag \n");
|
||||
item->tag = xmalloc(taglen + 1);
|
||||
memcpy(item->tag, tag_line + 4, taglen);
|
||||
item->tag[taglen] = '\0';
|
||||
item->tag = xmemdupz(tag_line + 4, taglen);
|
||||
|
||||
if (!strcmp(type, blob_type)) {
|
||||
item->tagged = &lookup_blob(sha1)->object;
|
||||
|
109
trace.c
109
trace.c
@ -25,33 +25,6 @@
|
||||
#include "cache.h"
|
||||
#include "quote.h"
|
||||
|
||||
/* Stolen from "imap-send.c". */
|
||||
int nfvasprintf(char **strp, const char *fmt, va_list ap)
|
||||
{
|
||||
int len;
|
||||
char tmp[1024];
|
||||
|
||||
if ((len = vsnprintf(tmp, sizeof(tmp), fmt, ap)) < 0 ||
|
||||
!(*strp = xmalloc(len + 1)))
|
||||
die("Fatal: Out of memory\n");
|
||||
if (len >= (int)sizeof(tmp))
|
||||
vsprintf(*strp, fmt, ap);
|
||||
else
|
||||
memcpy(*strp, tmp, len + 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
int nfasprintf(char **str, const char *fmt, ...)
|
||||
{
|
||||
int rc;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
rc = nfvasprintf(str, fmt, args);
|
||||
va_end(args);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Get a trace file descriptor from GIT_TRACE env variable. */
|
||||
static int get_trace_fd(int *need_close)
|
||||
{
|
||||
@ -89,63 +62,65 @@ static int get_trace_fd(int *need_close)
|
||||
static const char err_msg[] = "Could not trace into fd given by "
|
||||
"GIT_TRACE environment variable";
|
||||
|
||||
void trace_printf(const char *format, ...)
|
||||
void trace_printf(const char *fmt, ...)
|
||||
{
|
||||
char *trace_str;
|
||||
va_list rest;
|
||||
int need_close = 0;
|
||||
int fd = get_trace_fd(&need_close);
|
||||
struct strbuf buf;
|
||||
va_list ap;
|
||||
int fd, len, need_close = 0;
|
||||
|
||||
fd = get_trace_fd(&need_close);
|
||||
if (!fd)
|
||||
return;
|
||||
|
||||
va_start(rest, format);
|
||||
nfvasprintf(&trace_str, format, rest);
|
||||
va_end(rest);
|
||||
strbuf_init(&buf, 0);
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf.buf, strbuf_avail(&buf), fmt, ap);
|
||||
va_end(ap);
|
||||
if (len >= strbuf_avail(&buf)) {
|
||||
strbuf_grow(&buf, len - strbuf_avail(&buf) + 128);
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf.buf, strbuf_avail(&buf), fmt, ap);
|
||||
va_end(ap);
|
||||
if (len >= strbuf_avail(&buf))
|
||||
die("broken vsnprintf");
|
||||
}
|
||||
strbuf_setlen(&buf, len);
|
||||
|
||||
write_or_whine_pipe(fd, trace_str, strlen(trace_str), err_msg);
|
||||
|
||||
free(trace_str);
|
||||
write_or_whine_pipe(fd, buf.buf, buf.len, err_msg);
|
||||
strbuf_release(&buf);
|
||||
|
||||
if (need_close)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void trace_argv_printf(const char **argv, int count, const char *format, ...)
|
||||
void trace_argv_printf(const char **argv, int count, const char *fmt, ...)
|
||||
{
|
||||
char *argv_str, *format_str, *trace_str;
|
||||
size_t argv_len, format_len, trace_len;
|
||||
va_list rest;
|
||||
int need_close = 0;
|
||||
int fd = get_trace_fd(&need_close);
|
||||
struct strbuf buf;
|
||||
va_list ap;
|
||||
int fd, len, need_close = 0;
|
||||
|
||||
fd = get_trace_fd(&need_close);
|
||||
if (!fd)
|
||||
return;
|
||||
|
||||
/* Get the argv string. */
|
||||
argv_str = sq_quote_argv(argv, count);
|
||||
argv_len = strlen(argv_str);
|
||||
strbuf_init(&buf, 0);
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf.buf, strbuf_avail(&buf), fmt, ap);
|
||||
va_end(ap);
|
||||
if (len >= strbuf_avail(&buf)) {
|
||||
strbuf_grow(&buf, len - strbuf_avail(&buf) + 128);
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf.buf, strbuf_avail(&buf), fmt, ap);
|
||||
va_end(ap);
|
||||
if (len >= strbuf_avail(&buf))
|
||||
die("broken vsnprintf");
|
||||
}
|
||||
strbuf_setlen(&buf, len);
|
||||
|
||||
/* Get the formated string. */
|
||||
va_start(rest, format);
|
||||
nfvasprintf(&format_str, format, rest);
|
||||
va_end(rest);
|
||||
|
||||
/* Allocate buffer for trace string. */
|
||||
format_len = strlen(format_str);
|
||||
trace_len = argv_len + format_len + 1; /* + 1 for \n */
|
||||
trace_str = xmalloc(trace_len + 1);
|
||||
|
||||
/* Copy everything into the trace string. */
|
||||
strncpy(trace_str, format_str, format_len);
|
||||
strncpy(trace_str + format_len, argv_str, argv_len);
|
||||
strcpy(trace_str + trace_len - 1, "\n");
|
||||
|
||||
write_or_whine_pipe(fd, trace_str, trace_len, err_msg);
|
||||
|
||||
free(argv_str);
|
||||
free(format_str);
|
||||
free(trace_str);
|
||||
sq_quote_argv(&buf, argv, count, 0);
|
||||
strbuf_addch(&buf, '\n');
|
||||
write_or_whine_pipe(fd, buf.buf, buf.len, err_msg);
|
||||
strbuf_release(&buf);
|
||||
|
||||
if (need_close)
|
||||
close(fd);
|
||||
|
Loading…
Reference in New Issue
Block a user