Merge branch 'ph/strbuf' into kh/commit
* ph/strbuf: 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.
This commit is contained in:
commit
a17ba31b0b
@ -238,15 +238,14 @@ static int write_tar_entry(const unsigned char *sha1,
|
|||||||
const char *filename, unsigned mode, int stage)
|
const char *filename, unsigned mode, int stage)
|
||||||
{
|
{
|
||||||
static struct strbuf path = STRBUF_INIT;
|
static struct strbuf path = STRBUF_INIT;
|
||||||
int filenamelen = strlen(filename);
|
|
||||||
void *buffer;
|
void *buffer;
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
|
||||||
strbuf_grow(&path, MAX(PATH_MAX, baselen + filenamelen + 1));
|
|
||||||
strbuf_reset(&path);
|
strbuf_reset(&path);
|
||||||
|
strbuf_grow(&path, PATH_MAX);
|
||||||
strbuf_add(&path, base, baselen);
|
strbuf_add(&path, base, baselen);
|
||||||
strbuf_add(&path, filename, filenamelen);
|
strbuf_addstr(&path, filename);
|
||||||
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
|
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
|
||||||
strbuf_addch(&path, '/');
|
strbuf_addch(&path, '/');
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
|
198
builtin-apply.c
198
builtin-apply.c
@ -163,15 +163,14 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c
|
|||||||
fputs(pre, output);
|
fputs(pre, output);
|
||||||
if (patch->old_name && patch->new_name &&
|
if (patch->old_name && patch->new_name &&
|
||||||
strcmp(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);
|
fputs(" => ", output);
|
||||||
write_name_quoted(NULL, 0, patch->new_name, 1, output);
|
quote_c_style(patch->new_name, NULL, output, 0);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
const char *n = patch->new_name;
|
const char *n = patch->new_name;
|
||||||
if (!n)
|
if (!n)
|
||||||
n = patch->old_name;
|
n = patch->old_name;
|
||||||
write_name_quoted(NULL, 0, n, 1, output);
|
quote_c_style(n, NULL, output, 0);
|
||||||
}
|
}
|
||||||
fputs(post, output);
|
fputs(post, output);
|
||||||
}
|
}
|
||||||
@ -231,35 +230,33 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
const char *start = line;
|
const char *start = line;
|
||||||
char *name;
|
|
||||||
|
|
||||||
if (*line == '"') {
|
if (*line == '"') {
|
||||||
|
struct strbuf name;
|
||||||
|
|
||||||
/* Proposed "new-style" GNU patch/diff format; see
|
/* Proposed "new-style" GNU patch/diff format; see
|
||||||
* http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
|
* http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
|
||||||
*/
|
*/
|
||||||
name = unquote_c_style(line, NULL);
|
strbuf_init(&name, 0);
|
||||||
if (name) {
|
if (!unquote_c_style(&name, line, NULL)) {
|
||||||
char *cp = name;
|
char *cp;
|
||||||
while (p_value) {
|
|
||||||
|
for (cp = name.buf; p_value; p_value--) {
|
||||||
cp = strchr(cp, '/');
|
cp = strchr(cp, '/');
|
||||||
if (!cp)
|
if (!cp)
|
||||||
break;
|
break;
|
||||||
cp++;
|
cp++;
|
||||||
p_value--;
|
|
||||||
}
|
}
|
||||||
if (cp) {
|
if (cp) {
|
||||||
/* name can later be freed, so we need
|
/* name can later be freed, so we need
|
||||||
* to memmove, not just return cp
|
* to memmove, not just return cp
|
||||||
*/
|
*/
|
||||||
memmove(name, cp, strlen(cp) + 1);
|
strbuf_remove(&name, 0, cp - name.buf);
|
||||||
free(def);
|
free(def);
|
||||||
return name;
|
return name.buf;
|
||||||
}
|
|
||||||
else {
|
|
||||||
free(name);
|
|
||||||
name = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
strbuf_release(&name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -567,29 +564,30 @@ static const char *stop_at_slash(const char *line, int llen)
|
|||||||
*/
|
*/
|
||||||
static char *git_header_name(char *line, int llen)
|
static char *git_header_name(char *line, int llen)
|
||||||
{
|
{
|
||||||
int len;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *second = NULL;
|
const char *second = NULL;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
line += strlen("diff --git ");
|
line += strlen("diff --git ");
|
||||||
llen -= strlen("diff --git ");
|
llen -= strlen("diff --git ");
|
||||||
|
|
||||||
if (*line == '"') {
|
if (*line == '"') {
|
||||||
const char *cp;
|
const char *cp;
|
||||||
char *first = unquote_c_style(line, &second);
|
struct strbuf first;
|
||||||
if (!first)
|
struct strbuf sp;
|
||||||
return NULL;
|
|
||||||
|
strbuf_init(&first, 0);
|
||||||
|
strbuf_init(&sp, 0);
|
||||||
|
|
||||||
|
if (unquote_c_style(&first, line, &second))
|
||||||
|
goto free_and_fail1;
|
||||||
|
|
||||||
/* advance to the first slash */
|
/* advance to the first slash */
|
||||||
cp = stop_at_slash(first, strlen(first));
|
cp = stop_at_slash(first.buf, first.len);
|
||||||
if (!cp || cp == first) {
|
/* we do not accept absolute paths */
|
||||||
/* we do not accept absolute paths */
|
if (!cp || cp == first.buf)
|
||||||
free_first_and_fail:
|
goto free_and_fail1;
|
||||||
free(first);
|
strbuf_remove(&first, 0, cp + 1 - first.buf);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
len = strlen(cp+1);
|
|
||||||
memmove(first, cp+1, len+1); /* including NUL */
|
|
||||||
|
|
||||||
/* second points at one past closing dq of name.
|
/* second points at one past closing dq of name.
|
||||||
* find the second name.
|
* find the second name.
|
||||||
@ -598,40 +596,40 @@ static char *git_header_name(char *line, int llen)
|
|||||||
second++;
|
second++;
|
||||||
|
|
||||||
if (line + llen <= second)
|
if (line + llen <= second)
|
||||||
goto free_first_and_fail;
|
goto free_and_fail1;
|
||||||
if (*second == '"') {
|
if (*second == '"') {
|
||||||
char *sp = unquote_c_style(second, NULL);
|
if (unquote_c_style(&sp, second, NULL))
|
||||||
if (!sp)
|
goto free_and_fail1;
|
||||||
goto free_first_and_fail;
|
cp = stop_at_slash(sp.buf, sp.len);
|
||||||
cp = stop_at_slash(sp, strlen(sp));
|
if (!cp || cp == sp.buf)
|
||||||
if (!cp || cp == sp) {
|
goto free_and_fail1;
|
||||||
free_both_and_fail:
|
|
||||||
free(sp);
|
|
||||||
goto free_first_and_fail;
|
|
||||||
}
|
|
||||||
/* They must match, otherwise ignore */
|
/* They must match, otherwise ignore */
|
||||||
if (strcmp(cp+1, first))
|
if (strcmp(cp + 1, first.buf))
|
||||||
goto free_both_and_fail;
|
goto free_and_fail1;
|
||||||
free(sp);
|
strbuf_release(&sp);
|
||||||
return first;
|
return first.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unquoted second */
|
/* unquoted second */
|
||||||
cp = stop_at_slash(second, line + llen - second);
|
cp = stop_at_slash(second, line + llen - second);
|
||||||
if (!cp || cp == second)
|
if (!cp || cp == second)
|
||||||
goto free_first_and_fail;
|
goto free_and_fail1;
|
||||||
cp++;
|
cp++;
|
||||||
if (line + llen - cp != len + 1 ||
|
if (line + llen - cp != first.len + 1 ||
|
||||||
memcmp(first, cp, len))
|
memcmp(first.buf, cp, first.len))
|
||||||
goto free_first_and_fail;
|
goto free_and_fail1;
|
||||||
return first;
|
return first.buf;
|
||||||
|
|
||||||
|
free_and_fail1:
|
||||||
|
strbuf_release(&first);
|
||||||
|
strbuf_release(&sp);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unquoted first name */
|
/* unquoted first name */
|
||||||
name = stop_at_slash(line, llen);
|
name = stop_at_slash(line, llen);
|
||||||
if (!name || name == line)
|
if (!name || name == line)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
name++;
|
name++;
|
||||||
|
|
||||||
/* since the first name is unquoted, a dq if exists must be
|
/* since the first name is unquoted, a dq if exists must be
|
||||||
@ -639,28 +637,30 @@ static char *git_header_name(char *line, int llen)
|
|||||||
*/
|
*/
|
||||||
for (second = name; second < line + llen; second++) {
|
for (second = name; second < line + llen; second++) {
|
||||||
if (*second == '"') {
|
if (*second == '"') {
|
||||||
const char *cp = second;
|
struct strbuf sp;
|
||||||
const char *np;
|
const char *np;
|
||||||
char *sp = unquote_c_style(second, NULL);
|
|
||||||
|
|
||||||
if (!sp)
|
strbuf_init(&sp, 0);
|
||||||
return NULL;
|
if (unquote_c_style(&sp, second, NULL))
|
||||||
np = stop_at_slash(sp, strlen(sp));
|
goto free_and_fail2;
|
||||||
if (!np || np == sp) {
|
|
||||||
free_second_and_fail:
|
np = stop_at_slash(sp.buf, sp.len);
|
||||||
free(sp);
|
if (!np || np == sp.buf)
|
||||||
return NULL;
|
goto free_and_fail2;
|
||||||
}
|
|
||||||
np++;
|
np++;
|
||||||
len = strlen(np);
|
|
||||||
if (len < cp - name &&
|
len = sp.buf + sp.len - np;
|
||||||
|
if (len < second - name &&
|
||||||
!strncmp(np, name, len) &&
|
!strncmp(np, name, len) &&
|
||||||
isspace(name[len])) {
|
isspace(name[len])) {
|
||||||
/* Good */
|
/* Good */
|
||||||
memmove(sp, np, len + 1);
|
strbuf_remove(&sp, 0, np - sp.buf);
|
||||||
return sp;
|
return sp.buf;
|
||||||
}
|
}
|
||||||
goto free_second_and_fail;
|
|
||||||
|
free_and_fail2:
|
||||||
|
strbuf_release(&sp);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1378,61 +1378,50 @@ static const char minuses[]= "--------------------------------------------------
|
|||||||
|
|
||||||
static void show_stats(struct patch *patch)
|
static void show_stats(struct patch *patch)
|
||||||
{
|
{
|
||||||
const char *prefix = "";
|
struct strbuf qname;
|
||||||
char *name = patch->new_name;
|
char *cp = patch->new_name ? patch->new_name : patch->old_name;
|
||||||
char *qname = NULL;
|
int max, add, del;
|
||||||
int len, max, add, del, total;
|
|
||||||
|
|
||||||
if (!name)
|
strbuf_init(&qname, 0);
|
||||||
name = patch->old_name;
|
quote_c_style(cp, &qname, NULL, 0);
|
||||||
|
|
||||||
if (0 < (len = quote_c_style(name, NULL, NULL, 0))) {
|
|
||||||
qname = xmalloc(len + 1);
|
|
||||||
quote_c_style(name, qname, NULL, 0);
|
|
||||||
name = qname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "scale" the filename
|
* "scale" the filename
|
||||||
*/
|
*/
|
||||||
len = strlen(name);
|
|
||||||
max = max_len;
|
max = max_len;
|
||||||
if (max > 50)
|
if (max > 50)
|
||||||
max = 50;
|
max = 50;
|
||||||
if (len > max) {
|
|
||||||
char *slash;
|
if (qname.len > max) {
|
||||||
prefix = "...";
|
cp = strchr(qname.buf + qname.len + 3 - max, '/');
|
||||||
max -= 3;
|
if (!cp)
|
||||||
name += len - max;
|
cp = qname.buf + qname.len + 3 - max;
|
||||||
slash = strchr(name, '/');
|
strbuf_splice(&qname, 0, cp - qname.buf, "...", 3);
|
||||||
if (slash)
|
|
||||||
name = slash;
|
|
||||||
}
|
}
|
||||||
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
|
* scale the add/delete
|
||||||
*/
|
*/
|
||||||
max = max_change;
|
max = max + max_change > 70 ? 70 - max : max_change;
|
||||||
if (max + len > 70)
|
|
||||||
max = 70 - len;
|
|
||||||
|
|
||||||
add = patch->lines_added;
|
add = patch->lines_added;
|
||||||
del = patch->lines_deleted;
|
del = patch->lines_deleted;
|
||||||
total = add + del;
|
|
||||||
|
|
||||||
if (max_change > 0) {
|
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;
|
add = (add * max + max_change / 2) / max_change;
|
||||||
del = total - add;
|
del = total - add;
|
||||||
}
|
}
|
||||||
if (patch->is_binary)
|
printf("%5d %.*s%.*s\n", patch->lines_added + patch->lines_deleted,
|
||||||
printf(" %s%-*s | Bin\n", prefix, len, name);
|
add, pluses, del, minuses);
|
||||||
else
|
|
||||||
printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
|
|
||||||
len, name, patch->lines_added + patch->lines_deleted,
|
|
||||||
add, pluses, del, minuses);
|
|
||||||
free(qname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
|
static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
|
||||||
@ -2227,13 +2216,8 @@ static void numstat_patch_list(struct patch *patch)
|
|||||||
if (patch->is_binary)
|
if (patch->is_binary)
|
||||||
printf("-\t-\t");
|
printf("-\t-\t");
|
||||||
else
|
else
|
||||||
printf("%d\t%d\t",
|
printf("%d\t%d\t", patch->lines_added, patch->lines_deleted);
|
||||||
patch->lines_added, patch->lines_deleted);
|
write_name_quoted(name, stdout, line_termination);
|
||||||
if (line_termination && quote_c_style(name, NULL, NULL, 0))
|
|
||||||
quote_c_style(name, NULL, stdout, 0);
|
|
||||||
else
|
|
||||||
fputs(name, stdout);
|
|
||||||
putchar(line_termination);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1430,8 +1430,7 @@ static void get_commit_info(struct commit *commit,
|
|||||||
static void write_filename_info(const char *path)
|
static void write_filename_info(const char *path)
|
||||||
{
|
{
|
||||||
printf("filename ");
|
printf("filename ");
|
||||||
write_name_quoted(NULL, 0, path, 1, stdout);
|
write_name_quoted(path, stdout, '\n');
|
||||||
putchar('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -56,7 +56,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
|
|||||||
else if (ATTR_UNSET(value))
|
else if (ATTR_UNSET(value))
|
||||||
value = "unspecified";
|
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);
|
printf(": %s: %s\n", argv[j+1], value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,9 +66,7 @@ static void write_tempfile_record(const char *name, int prefix_length)
|
|||||||
fputs(topath[checkout_stage], stdout);
|
fputs(topath[checkout_stage], stdout);
|
||||||
|
|
||||||
putchar('\t');
|
putchar('\t');
|
||||||
write_name_quoted("", 0, name + prefix_length,
|
write_name_quoted(name + prefix_length, stdout, line_termination);
|
||||||
line_termination, stdout);
|
|
||||||
putchar(line_termination);
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
topath[i][0] = 0;
|
topath[i][0] = 0;
|
||||||
@ -270,26 +268,27 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (read_from_stdin) {
|
if (read_from_stdin) {
|
||||||
struct strbuf buf;
|
struct strbuf buf, nbuf;
|
||||||
|
|
||||||
if (all)
|
if (all)
|
||||||
die("git-checkout-index: don't mix '--all' and '--stdin'");
|
die("git-checkout-index: don't mix '--all' and '--stdin'");
|
||||||
|
|
||||||
strbuf_init(&buf, 0);
|
strbuf_init(&buf, 0);
|
||||||
while (1) {
|
strbuf_init(&nbuf, 0);
|
||||||
char *path_name;
|
while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
|
||||||
const char *p;
|
const char *p;
|
||||||
if (strbuf_getline(&buf, stdin, line_termination) == EOF)
|
if (line_termination && buf.buf[0] == '"') {
|
||||||
break;
|
strbuf_reset(&nbuf);
|
||||||
if (line_termination && buf.buf[0] == '"')
|
if (unquote_c_style(&nbuf, buf.buf, NULL))
|
||||||
path_name = unquote_c_style(buf.buf, NULL);
|
die("line is badly quoted");
|
||||||
else
|
strbuf_swap(&buf, &nbuf);
|
||||||
path_name = buf.buf;
|
}
|
||||||
p = prefix_path(prefix, prefix_length, path_name);
|
p = prefix_path(prefix, prefix_length, buf.buf);
|
||||||
checkout_file(p, prefix_length);
|
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);
|
free((char *)p);
|
||||||
if (path_name != buf.buf)
|
|
||||||
free(path_name);
|
|
||||||
}
|
}
|
||||||
|
strbuf_release(&nbuf);
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +84,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fputs(tag, stdout);
|
fputs(tag, stdout);
|
||||||
write_name_quoted("", 0, ent->name + offset, line_terminator, stdout);
|
write_name_quoted(ent->name + offset, stdout, line_terminator);
|
||||||
putchar(line_terminator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_other_files(struct dir_struct *dir)
|
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) {
|
if (!show_stage) {
|
||||||
fputs(tag, stdout);
|
fputs(tag, stdout);
|
||||||
write_name_quoted("", 0, ce->name + offset,
|
} else {
|
||||||
line_terminator, stdout);
|
|
||||||
putchar(line_terminator);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("%s%06o %s %d\t",
|
printf("%s%06o %s %d\t",
|
||||||
tag,
|
tag,
|
||||||
ntohl(ce->ce_mode),
|
ntohl(ce->ce_mode),
|
||||||
abbrev ? find_unique_abbrev(ce->sha1,abbrev)
|
abbrev ? find_unique_abbrev(ce->sha1,abbrev)
|
||||||
: sha1_to_hex(ce->sha1),
|
: sha1_to_hex(ce->sha1),
|
||||||
ce_stage(ce));
|
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)
|
static void show_files(struct dir_struct *dir, const char *prefix)
|
||||||
|
@ -112,10 +112,8 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
|
|||||||
abbrev ? find_unique_abbrev(sha1, abbrev)
|
abbrev ? find_unique_abbrev(sha1, abbrev)
|
||||||
: sha1_to_hex(sha1));
|
: sha1_to_hex(sha1));
|
||||||
}
|
}
|
||||||
write_name_quoted(base + chomp_prefix, baselen - chomp_prefix,
|
write_name_quotedpfx(base + chomp_prefix, baselen - chomp_prefix,
|
||||||
pathname,
|
pathname, stdout, line_termination);
|
||||||
line_termination, stdout);
|
|
||||||
putchar(line_termination);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,13 +72,9 @@ static int handle_file(const char *path,
|
|||||||
SHA_CTX ctx;
|
SHA_CTX ctx;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int hunk = 0, hunk_no = 0;
|
int hunk = 0, hunk_no = 0;
|
||||||
struct strbuf minus, plus;
|
struct strbuf one, two;
|
||||||
struct strbuf *one = &minus, *two = +
|
|
||||||
FILE *f = fopen(path, "r");
|
FILE *f = fopen(path, "r");
|
||||||
FILE *out;
|
FILE *out = NULL;
|
||||||
|
|
||||||
strbuf_init(&minus, 0);
|
|
||||||
strbuf_init(&plus, 0);
|
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
return error("Could not open %s", path);
|
return error("Could not open %s", path);
|
||||||
@ -89,51 +85,50 @@ static int handle_file(const char *path,
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
return error("Could not write %s", output);
|
return error("Could not write %s", output);
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
out = NULL;
|
|
||||||
|
|
||||||
if (sha1)
|
if (sha1)
|
||||||
SHA1_Init(&ctx);
|
SHA1_Init(&ctx);
|
||||||
|
|
||||||
|
strbuf_init(&one, 0);
|
||||||
|
strbuf_init(&two, 0);
|
||||||
while (fgets(buf, sizeof(buf), f)) {
|
while (fgets(buf, sizeof(buf), f)) {
|
||||||
if (!prefixcmp(buf, "<<<<<<< "))
|
if (!prefixcmp(buf, "<<<<<<< "))
|
||||||
hunk = 1;
|
hunk = 1;
|
||||||
else if (!prefixcmp(buf, "======="))
|
else if (!prefixcmp(buf, "======="))
|
||||||
hunk = 2;
|
hunk = 2;
|
||||||
else if (!prefixcmp(buf, ">>>>>>> ")) {
|
else if (!prefixcmp(buf, ">>>>>>> ")) {
|
||||||
int one_is_longer = (one->len > two->len);
|
int cmp = strbuf_cmp(&one, &two);
|
||||||
int common_len = one_is_longer ? two->len : one->len;
|
|
||||||
int cmp = memcmp(one->buf, two->buf, common_len);
|
|
||||||
|
|
||||||
hunk_no++;
|
hunk_no++;
|
||||||
hunk = 0;
|
hunk = 0;
|
||||||
if ((cmp > 0) || ((cmp == 0) && one_is_longer)) {
|
if (cmp > 0) {
|
||||||
struct strbuf *swap = one;
|
strbuf_swap(&one, &two);
|
||||||
one = two;
|
|
||||||
two = swap;
|
|
||||||
}
|
}
|
||||||
if (out) {
|
if (out) {
|
||||||
fputs("<<<<<<<\n", out);
|
fputs("<<<<<<<\n", out);
|
||||||
fwrite(one->buf, one->len, 1, out);
|
fwrite(one.buf, one.len, 1, out);
|
||||||
fputs("=======\n", out);
|
fputs("=======\n", out);
|
||||||
fwrite(two->buf, two->len, 1, out);
|
fwrite(two.buf, two.len, 1, out);
|
||||||
fputs(">>>>>>>\n", out);
|
fputs(">>>>>>>\n", out);
|
||||||
}
|
}
|
||||||
if (sha1) {
|
if (sha1) {
|
||||||
SHA1_Update(&ctx, one->buf, one->len);
|
SHA1_Update(&ctx, one.buf ? one.buf : "",
|
||||||
SHA1_Update(&ctx, "\0", 1);
|
one.len + 1);
|
||||||
SHA1_Update(&ctx, two->buf, two->len);
|
SHA1_Update(&ctx, two.buf ? two.buf : "",
|
||||||
SHA1_Update(&ctx, "\0", 1);
|
two.len + 1);
|
||||||
}
|
}
|
||||||
strbuf_release(one);
|
strbuf_reset(&one);
|
||||||
strbuf_release(two);
|
strbuf_reset(&two);
|
||||||
} else if (hunk == 1)
|
} else if (hunk == 1)
|
||||||
strbuf_addstr(one, buf);
|
strbuf_addstr(&one, buf);
|
||||||
else if (hunk == 2)
|
else if (hunk == 2)
|
||||||
strbuf_addstr(two, buf);
|
strbuf_addstr(&two, buf);
|
||||||
else if (out)
|
else if (out)
|
||||||
fputs(buf, out);
|
fputs(buf, out);
|
||||||
}
|
}
|
||||||
|
strbuf_release(&one);
|
||||||
|
strbuf_release(&two);
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (out)
|
if (out)
|
||||||
|
@ -8,17 +8,13 @@
|
|||||||
*/
|
*/
|
||||||
static size_t cleanup(char *line, size_t len)
|
static size_t cleanup(char *line, size_t len)
|
||||||
{
|
{
|
||||||
if (len) {
|
while (len) {
|
||||||
if (line[len - 1] == '\n')
|
unsigned char c = line[len - 1];
|
||||||
len--;
|
if (!isspace(c))
|
||||||
|
break;
|
||||||
while (len) {
|
len--;
|
||||||
unsigned char c = line[len - 1];
|
|
||||||
if (!isspace(c))
|
|
||||||
break;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,42 +30,42 @@ static size_t cleanup(char *line, size_t len)
|
|||||||
* If the input has only empty lines and spaces,
|
* If the input has only empty lines and spaces,
|
||||||
* no output will be produced.
|
* 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 "#".
|
* 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;
|
size_t i, j, len, newlen;
|
||||||
char *eol;
|
char *eol;
|
||||||
|
|
||||||
for (i = j = 0; i < length; i += len, j += newlen) {
|
/* We may have to add a newline. */
|
||||||
eol = memchr(buffer + i, '\n', length - i);
|
strbuf_grow(sb, 1);
|
||||||
len = eol ? eol - (buffer + i) + 1 : length - i;
|
|
||||||
|
|
||||||
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;
|
newlen = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
newlen = cleanup(buffer + i, len);
|
newlen = cleanup(sb->buf + i, len);
|
||||||
|
|
||||||
/* Not just an empty line? */
|
/* Not just an empty line? */
|
||||||
if (newlen) {
|
if (newlen) {
|
||||||
if (empties != -1)
|
if (empties > 0 && j > 0)
|
||||||
buffer[j++] = '\n';
|
sb->buf[j++] = '\n';
|
||||||
if (empties > 0)
|
|
||||||
buffer[j++] = '\n';
|
|
||||||
empties = 0;
|
empties = 0;
|
||||||
memmove(buffer + j, buffer + i, newlen);
|
memmove(sb->buf + j, sb->buf + i, newlen);
|
||||||
continue;
|
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)
|
int cmd_stripspace(int argc, const char **argv, const char *prefix)
|
||||||
@ -85,9 +81,7 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix)
|
|||||||
if (strbuf_read(&buf, 0, 1024) < 0)
|
if (strbuf_read(&buf, 0, 1024) < 0)
|
||||||
die("could not read the input");
|
die("could not read the input");
|
||||||
|
|
||||||
strbuf_setlen(&buf, stripspace(buf.buf, buf.len, strip_comments));
|
stripspace(&buf, strip_comments);
|
||||||
if (buf.len)
|
|
||||||
strbuf_addch(&buf, '\n');
|
|
||||||
|
|
||||||
write_or_die(1, buf.buf, buf.len);
|
write_or_die(1, buf.buf, buf.len);
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
|
@ -22,7 +22,6 @@ static void launch_editor(const char *path, struct strbuf *buffer)
|
|||||||
const char *editor, *terminal;
|
const char *editor, *terminal;
|
||||||
struct child_process child;
|
struct child_process child;
|
||||||
const char *args[3];
|
const char *args[3];
|
||||||
int fd;
|
|
||||||
|
|
||||||
editor = getenv("GIT_EDITOR");
|
editor = getenv("GIT_EDITOR");
|
||||||
if (!editor && editor_program)
|
if (!editor && editor_program)
|
||||||
@ -52,13 +51,9 @@ static void launch_editor(const char *path, struct strbuf *buffer)
|
|||||||
if (run_command(&child))
|
if (run_command(&child))
|
||||||
die("There was a problem with the editor %s.", editor);
|
die("There was a problem with the editor %s.", editor);
|
||||||
|
|
||||||
fd = open(path, O_RDONLY);
|
if (strbuf_read_file(buffer, path) < 0)
|
||||||
if (fd < 0)
|
die("could not read message file '%s': %s",
|
||||||
die("could not open '%s': %s", path, strerror(errno));
|
path, strerror(errno));
|
||||||
if (strbuf_read(buffer, fd, 0) < 0) {
|
|
||||||
die("could not read message file '%s': %s", path, strerror(errno));
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tag_filter {
|
struct tag_filter {
|
||||||
@ -296,14 +291,11 @@ static void create_tag(const unsigned char *object, const char *tag,
|
|||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_setlen(buf, stripspace(buf->buf, buf->len, 1));
|
stripspace(buf, 1);
|
||||||
|
|
||||||
if (!message && !buf->len)
|
if (!message && !buf->len)
|
||||||
die("no tag message?");
|
die("no tag message?");
|
||||||
|
|
||||||
/* insert the header and add the '\n' if needed: */
|
|
||||||
if (buf->len)
|
|
||||||
strbuf_addch(buf, '\n');
|
|
||||||
strbuf_insert(buf, 0, header_buf, header_len);
|
strbuf_insert(buf, 0, header_buf, header_len);
|
||||||
|
|
||||||
if (sign && do_sign(buf) < 0)
|
if (sign && do_sign(buf) < 0)
|
||||||
|
@ -295,8 +295,11 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
|
|||||||
static void read_index_info(int line_termination)
|
static void read_index_info(int line_termination)
|
||||||
{
|
{
|
||||||
struct strbuf buf;
|
struct strbuf buf;
|
||||||
|
struct strbuf uq;
|
||||||
|
|
||||||
strbuf_init(&buf, 0);
|
strbuf_init(&buf, 0);
|
||||||
while (1) {
|
strbuf_init(&uq, 0);
|
||||||
|
while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
|
||||||
char *ptr, *tab;
|
char *ptr, *tab;
|
||||||
char *path_name;
|
char *path_name;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
@ -320,9 +323,6 @@ static void read_index_info(int line_termination)
|
|||||||
* This format is to put higher order stages into the
|
* This format is to put higher order stages into the
|
||||||
* index file and matches git-ls-files --stage output.
|
* index file and matches git-ls-files --stage output.
|
||||||
*/
|
*/
|
||||||
if (strbuf_getline(&buf, stdin, line_termination) == EOF)
|
|
||||||
break;
|
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
ul = strtoul(buf.buf, &ptr, 8);
|
ul = strtoul(buf.buf, &ptr, 8);
|
||||||
if (ptr == buf.buf || *ptr != ' '
|
if (ptr == buf.buf || *ptr != ' '
|
||||||
@ -347,15 +347,17 @@ static void read_index_info(int line_termination)
|
|||||||
if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
|
if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
|
||||||
goto bad_line;
|
goto bad_line;
|
||||||
|
|
||||||
if (line_termination && ptr[0] == '"')
|
path_name = ptr;
|
||||||
path_name = unquote_c_style(ptr, NULL);
|
if (line_termination && path_name[0] == '"') {
|
||||||
else
|
strbuf_reset(&uq);
|
||||||
path_name = ptr;
|
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)) {
|
if (!verify_path(path_name)) {
|
||||||
fprintf(stderr, "Ignoring path %s\n", path_name);
|
fprintf(stderr, "Ignoring path %s\n", path_name);
|
||||||
if (path_name != ptr)
|
|
||||||
free(path_name);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,6 +385,7 @@ static void read_index_info(int line_termination)
|
|||||||
die("malformed index info %s", buf.buf);
|
die("malformed index info %s", buf.buf);
|
||||||
}
|
}
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
|
strbuf_release(&uq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char update_index_usage[] =
|
static const char update_index_usage[] =
|
||||||
@ -705,26 +708,26 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
|
|||||||
free((char*)p);
|
free((char*)p);
|
||||||
}
|
}
|
||||||
if (read_from_stdin) {
|
if (read_from_stdin) {
|
||||||
struct strbuf buf;
|
struct strbuf buf, nbuf;
|
||||||
|
|
||||||
strbuf_init(&buf, 0);
|
strbuf_init(&buf, 0);
|
||||||
while (1) {
|
strbuf_init(&nbuf, 0);
|
||||||
char *path_name;
|
while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
|
||||||
const char *p;
|
const char *p;
|
||||||
if (strbuf_getline(&buf, stdin, line_termination) == EOF)
|
if (line_termination && buf.buf[0] == '"') {
|
||||||
break;
|
strbuf_reset(&nbuf);
|
||||||
if (line_termination && buf.buf[0] == '"')
|
if (unquote_c_style(&nbuf, buf.buf, NULL))
|
||||||
path_name = unquote_c_style(buf.buf, NULL);
|
die("line is badly quoted");
|
||||||
else
|
strbuf_swap(&buf, &nbuf);
|
||||||
path_name = buf.buf;
|
}
|
||||||
p = prefix_path(prefix, prefix_length, path_name);
|
p = prefix_path(prefix, prefix_length, buf.buf);
|
||||||
update_one(p, NULL, 0);
|
update_one(p, NULL, 0);
|
||||||
if (set_executable_bit)
|
if (set_executable_bit)
|
||||||
chmod_path(set_executable_bit, p);
|
chmod_path(set_executable_bit, p);
|
||||||
if (p < path_name || p > path_name + strlen(path_name))
|
if (p < buf.buf || p > buf.buf + buf.len)
|
||||||
free((char*) p);
|
free((char *)p);
|
||||||
if (path_name != buf.buf)
|
|
||||||
free(path_name);
|
|
||||||
}
|
}
|
||||||
|
strbuf_release(&nbuf);
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ extern const char git_version_string[];
|
|||||||
extern const char git_usage_string[];
|
extern const char git_usage_string[];
|
||||||
|
|
||||||
extern void help_unknown_cmd(const char *cmd);
|
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 int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
|
||||||
extern void prune_packed_objects(int);
|
extern void prune_packed_objects(int);
|
||||||
|
|
||||||
|
19
cache-tree.c
19
cache-tree.c
@ -369,10 +369,8 @@ int cache_tree_update(struct cache_tree *it,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_one(struct cache_tree *it,
|
static void write_one(struct strbuf *buffer, struct cache_tree *it,
|
||||||
char *path,
|
const char *path, int pathlen)
|
||||||
int pathlen,
|
|
||||||
struct strbuf *buffer)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -407,20 +405,13 @@ static void write_one(struct cache_tree *it,
|
|||||||
prev->name, prev->namelen) <= 0)
|
prev->name, prev->namelen) <= 0)
|
||||||
die("fatal - unsorted cache subtree");
|
die("fatal - unsorted cache subtree");
|
||||||
}
|
}
|
||||||
write_one(down->cache_tree, down->name, down->namelen, buffer);
|
write_one(buffer, down->cache_tree, down->name, down->namelen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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];
|
write_one(sb, root, "", 0);
|
||||||
struct strbuf buffer;
|
|
||||||
|
|
||||||
path[0] = 0;
|
|
||||||
strbuf_init(&buffer, 0);
|
|
||||||
write_one(root, path, 0, &buffer);
|
|
||||||
*size_p = buffer.len;
|
|
||||||
return strbuf_detach(&buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)
|
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 *);
|
void cache_tree_invalidate_path(struct cache_tree *, const char *);
|
||||||
struct cache_tree_sub *cache_tree_sub(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);
|
struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
|
||||||
|
|
||||||
int cache_tree_fully_valid(struct cache_tree *);
|
int cache_tree_fully_valid(struct cache_tree *);
|
||||||
|
2
cache.h
2
cache.h
@ -585,8 +585,6 @@ extern void *alloc_object_node(void);
|
|||||||
extern void alloc_report(void);
|
extern void alloc_report(void);
|
||||||
|
|
||||||
/* trace.c */
|
/* 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_printf(const char *format, ...);
|
||||||
extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
|
extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
|
||||||
|
|
||||||
|
@ -650,10 +650,7 @@ static void dump_quoted_path(const char *prefix, const char *path,
|
|||||||
const char *c_meta, const char *c_reset)
|
const char *c_meta, const char *c_reset)
|
||||||
{
|
{
|
||||||
printf("%s%s", c_meta, prefix);
|
printf("%s%s", c_meta, prefix);
|
||||||
if (quote_c_style(path, NULL, NULL, 0))
|
quote_c_style(path, NULL, stdout, 0);
|
||||||
quote_c_style(path, NULL, stdout, 0);
|
|
||||||
else
|
|
||||||
printf("%s", path);
|
|
||||||
printf("%s\n", c_reset);
|
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);
|
putchar(inter_name_termination);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line_termination) {
|
write_name_quoted(p->path, stdout, 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_combined_diff(struct combine_diff_path *p,
|
void show_combined_diff(struct combine_diff_path *p,
|
||||||
|
2
commit.c
2
commit.c
@ -656,7 +656,7 @@ static char *replace_encoding_header(char *buf, const char *encoding)
|
|||||||
strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1);
|
strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1);
|
||||||
if (is_encoding_utf8(encoding)) {
|
if (is_encoding_utf8(encoding)) {
|
||||||
/* we have re-coded to UTF-8; drop the header */
|
/* we have re-coded to UTF-8; drop the header */
|
||||||
strbuf_splice(&tmp, start, len, NULL, 0);
|
strbuf_remove(&tmp, start, len);
|
||||||
} else {
|
} else {
|
||||||
/* just replaces XXXX in 'encoding XXXX\n' */
|
/* just replaces XXXX in 'encoding XXXX\n' */
|
||||||
strbuf_splice(&tmp, start + strlen("encoding "),
|
strbuf_splice(&tmp, start + strlen("encoding "),
|
||||||
|
21
connect.c
21
connect.c
@ -577,16 +577,13 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
|
|||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
die("unable to fork");
|
die("unable to fork");
|
||||||
if (!pid) {
|
if (!pid) {
|
||||||
char command[MAX_CMD_LEN];
|
struct strbuf cmd;
|
||||||
char *posn = command;
|
|
||||||
int size = MAX_CMD_LEN;
|
|
||||||
int of = 0;
|
|
||||||
|
|
||||||
of |= add_to_string(&posn, &size, prog, 0);
|
strbuf_init(&cmd, MAX_CMD_LEN);
|
||||||
of |= add_to_string(&posn, &size, " ", 0);
|
strbuf_addstr(&cmd, prog);
|
||||||
of |= add_to_string(&posn, &size, path, 1);
|
strbuf_addch(&cmd, ' ');
|
||||||
|
sq_quote_buf(&cmd, path);
|
||||||
if (of)
|
if (cmd.len >= MAX_CMD_LEN)
|
||||||
die("command line too long");
|
die("command line too long");
|
||||||
|
|
||||||
dup2(pipefd[1][0], 0);
|
dup2(pipefd[1][0], 0);
|
||||||
@ -606,10 +603,10 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
|
|||||||
ssh_basename++;
|
ssh_basename++;
|
||||||
|
|
||||||
if (!port)
|
if (!port)
|
||||||
execlp(ssh, ssh_basename, host, command, NULL);
|
execlp(ssh, ssh_basename, host, cmd.buf, NULL);
|
||||||
else
|
else
|
||||||
execlp(ssh, ssh_basename, "-p", port, host,
|
execlp(ssh, ssh_basename, "-p", port, host,
|
||||||
command, NULL);
|
cmd.buf, NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unsetenv(ALTERNATE_DB_ENVIRONMENT);
|
unsetenv(ALTERNATE_DB_ENVIRONMENT);
|
||||||
@ -618,7 +615,7 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
|
|||||||
unsetenv(GIT_WORK_TREE_ENVIRONMENT);
|
unsetenv(GIT_WORK_TREE_ENVIRONMENT);
|
||||||
unsetenv(GRAFT_ENVIRONMENT);
|
unsetenv(GRAFT_ENVIRONMENT);
|
||||||
unsetenv(INDEX_ENVIRONMENT);
|
unsetenv(INDEX_ENVIRONMENT);
|
||||||
execlp("sh", "sh", "-c", command, NULL);
|
execlp("sh", "sh", "-c", cmd.buf, NULL);
|
||||||
}
|
}
|
||||||
die("exec failed");
|
die("exec failed");
|
||||||
}
|
}
|
||||||
|
303
diff.c
303
diff.c
@ -181,44 +181,23 @@ int git_diff_ui_config(const char *var, const char *value)
|
|||||||
return git_default_config(var, 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)
|
static char *quote_two(const char *one, const char *two)
|
||||||
{
|
{
|
||||||
int need_one = quote_c_style(one, NULL, NULL, 1);
|
int need_one = quote_c_style(one, NULL, NULL, 1);
|
||||||
int need_two = quote_c_style(two, 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_two) {
|
||||||
if (!need_one) need_one = strlen(one);
|
strbuf_addch(&res, '"');
|
||||||
if (!need_two) need_one = strlen(two);
|
quote_c_style(one, &res, NULL, 1);
|
||||||
|
quote_c_style(two, &res, NULL, 1);
|
||||||
xp = xmalloc(need_one + need_two + 3);
|
strbuf_addch(&res, '"');
|
||||||
xp[0] = '"';
|
} else {
|
||||||
quote_c_style(one, xp + 1, NULL, 1);
|
strbuf_addstr(&res, one);
|
||||||
quote_c_style(two, xp + need_one + 1, NULL, 1);
|
strbuf_addstr(&res, two);
|
||||||
strcpy(xp + need_one + need_two + 1, "\"");
|
|
||||||
return xp;
|
|
||||||
}
|
}
|
||||||
need_one = strlen(one);
|
return res.buf;
|
||||||
need_two = strlen(two);
|
|
||||||
xp = xmalloc(need_one + need_two + 1);
|
|
||||||
strcpy(xp, one);
|
|
||||||
strcpy(xp + need_one, two);
|
|
||||||
return xp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *external_diff(void)
|
static const char *external_diff(void)
|
||||||
@ -670,27 +649,20 @@ static char *pprint_rename(const char *a, const char *b)
|
|||||||
{
|
{
|
||||||
const char *old = a;
|
const char *old = a;
|
||||||
const char *new = b;
|
const char *new = b;
|
||||||
char *name = NULL;
|
struct strbuf name;
|
||||||
int pfx_length, sfx_length;
|
int pfx_length, sfx_length;
|
||||||
int len_a = strlen(a);
|
int len_a = strlen(a);
|
||||||
int len_b = strlen(b);
|
int len_b = strlen(b);
|
||||||
|
int a_midlen, b_midlen;
|
||||||
int qlen_a = quote_c_style(a, NULL, NULL, 0);
|
int qlen_a = quote_c_style(a, NULL, NULL, 0);
|
||||||
int qlen_b = quote_c_style(b, 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 || qlen_b) {
|
||||||
if (qlen_a) len_a = qlen_a;
|
quote_c_style(a, &name, NULL, 0);
|
||||||
if (qlen_b) len_b = qlen_b;
|
strbuf_addstr(&name, " => ");
|
||||||
name = xmalloc( len_a + len_b + 5 );
|
quote_c_style(b, &name, NULL, 0);
|
||||||
if (qlen_a)
|
return name.buf;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find common prefix */
|
/* Find common prefix */
|
||||||
@ -719,24 +691,26 @@ static char *pprint_rename(const char *a, const char *b)
|
|||||||
* pfx{sfx-a => sfx-b}
|
* pfx{sfx-a => sfx-b}
|
||||||
* name-a => name-b
|
* name-a => name-b
|
||||||
*/
|
*/
|
||||||
if (pfx_length + sfx_length) {
|
a_midlen = len_a - pfx_length - sfx_length;
|
||||||
int a_midlen = len_a - pfx_length - sfx_length;
|
b_midlen = len_b - pfx_length - sfx_length;
|
||||||
int b_midlen = len_b - pfx_length - sfx_length;
|
if (a_midlen < 0)
|
||||||
if (a_midlen < 0) a_midlen = 0;
|
a_midlen = 0;
|
||||||
if (b_midlen < 0) b_midlen = 0;
|
if (b_midlen < 0)
|
||||||
|
b_midlen = 0;
|
||||||
|
|
||||||
name = xmalloc(pfx_length + a_midlen + b_midlen + sfx_length + 7);
|
strbuf_grow(&name, pfx_length + a_midlen + b_midlen + sfx_length + 7);
|
||||||
sprintf(name, "%.*s{%.*s => %.*s}%s",
|
if (pfx_length + sfx_length) {
|
||||||
pfx_length, a,
|
strbuf_add(&name, a, pfx_length);
|
||||||
a_midlen, a + pfx_length,
|
strbuf_addch(&name, '{');
|
||||||
b_midlen, b + pfx_length,
|
|
||||||
a + len_a - sfx_length);
|
|
||||||
}
|
}
|
||||||
else {
|
strbuf_add(&name, a + pfx_length, a_midlen);
|
||||||
name = xmalloc(len_a + len_b + 5);
|
strbuf_addstr(&name, " => ");
|
||||||
sprintf(name, "%s => %s", a, b);
|
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 name.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct diffstat_t {
|
struct diffstat_t {
|
||||||
@ -849,12 +823,13 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
|
|||||||
int change = file->added + file->deleted;
|
int change = file->added + file->deleted;
|
||||||
|
|
||||||
if (!file->is_renamed) { /* renames are already quoted by pprint_rename */
|
if (!file->is_renamed) { /* renames are already quoted by pprint_rename */
|
||||||
len = quote_c_style(file->name, NULL, NULL, 0);
|
struct strbuf buf;
|
||||||
if (len) {
|
strbuf_init(&buf, 0);
|
||||||
char *qname = xmalloc(len + 1);
|
if (quote_c_style(file->name, &buf, NULL, 0)) {
|
||||||
quote_c_style(file->name, qname, NULL, 0);
|
|
||||||
free(file->name);
|
free(file->name);
|
||||||
file->name = qname;
|
file->name = buf.buf;
|
||||||
|
} else {
|
||||||
|
strbuf_release(&buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,12 +967,12 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options)
|
|||||||
printf("-\t-\t");
|
printf("-\t-\t");
|
||||||
else
|
else
|
||||||
printf("%d\t%d\t", file->added, file->deleted);
|
printf("%d\t%d\t", file->added, file->deleted);
|
||||||
if (options->line_termination && !file->is_renamed &&
|
if (!file->is_renamed) {
|
||||||
quote_c_style(file->name, NULL, NULL, 0))
|
write_name_quoted(file->name, stdout, options->line_termination);
|
||||||
quote_c_style(file->name, NULL, stdout, 0);
|
} else {
|
||||||
else
|
|
||||||
fputs(file->name, stdout);
|
fputs(file->name, stdout);
|
||||||
putchar(options->line_termination);
|
putchar(options->line_termination);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1941,50 +1916,46 @@ static int similarity_index(struct diff_filepair *p)
|
|||||||
static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||||
{
|
{
|
||||||
const char *pgm = external_diff();
|
const char *pgm = external_diff();
|
||||||
char msg[PATH_MAX*2+300], *xfrm_msg;
|
struct strbuf msg;
|
||||||
struct diff_filespec *one;
|
char *xfrm_msg;
|
||||||
struct diff_filespec *two;
|
struct diff_filespec *one = p->one;
|
||||||
|
struct diff_filespec *two = p->two;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *other;
|
const char *other;
|
||||||
char *name_munged, *other_munged;
|
|
||||||
int complete_rewrite = 0;
|
int complete_rewrite = 0;
|
||||||
int len;
|
|
||||||
|
|
||||||
if (DIFF_PAIR_UNMERGED(p)) {
|
if (DIFF_PAIR_UNMERGED(p)) {
|
||||||
/* unmerged */
|
|
||||||
run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, o, 0);
|
run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, o, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = p->one->path;
|
name = p->one->path;
|
||||||
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
|
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(one);
|
||||||
diff_fill_sha1_info(two);
|
diff_fill_sha1_info(two);
|
||||||
|
|
||||||
len = 0;
|
strbuf_init(&msg, PATH_MAX * 2 + 300);
|
||||||
switch (p->status) {
|
switch (p->status) {
|
||||||
case DIFF_STATUS_COPIED:
|
case DIFF_STATUS_COPIED:
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
strbuf_addf(&msg, "similarity index %d%%", similarity_index(p));
|
||||||
"similarity index %d%%\n"
|
strbuf_addstr(&msg, "\ncopy from ");
|
||||||
"copy from %s\n"
|
quote_c_style(name, &msg, NULL, 0);
|
||||||
"copy to %s\n",
|
strbuf_addstr(&msg, "\ncopy to ");
|
||||||
similarity_index(p), name_munged, other_munged);
|
quote_c_style(other, &msg, NULL, 0);
|
||||||
|
strbuf_addch(&msg, '\n');
|
||||||
break;
|
break;
|
||||||
case DIFF_STATUS_RENAMED:
|
case DIFF_STATUS_RENAMED:
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
strbuf_addf(&msg, "similarity index %d%%", similarity_index(p));
|
||||||
"similarity index %d%%\n"
|
strbuf_addstr(&msg, "\nrename from ");
|
||||||
"rename from %s\n"
|
quote_c_style(name, &msg, NULL, 0);
|
||||||
"rename to %s\n",
|
strbuf_addstr(&msg, "\nrename to ");
|
||||||
similarity_index(p), name_munged, other_munged);
|
quote_c_style(other, &msg, NULL, 0);
|
||||||
|
strbuf_addch(&msg, '\n');
|
||||||
break;
|
break;
|
||||||
case DIFF_STATUS_MODIFIED:
|
case DIFF_STATUS_MODIFIED:
|
||||||
if (p->score) {
|
if (p->score) {
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
strbuf_addf(&msg, "dissimilarity index %d%%\n",
|
||||||
"dissimilarity index %d%%\n",
|
|
||||||
similarity_index(p));
|
similarity_index(p));
|
||||||
complete_rewrite = 1;
|
complete_rewrite = 1;
|
||||||
break;
|
break;
|
||||||
@ -2004,19 +1975,17 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
|||||||
(!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
|
(!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
|
||||||
abbrev = 40;
|
abbrev = 40;
|
||||||
}
|
}
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
strbuf_addf(&msg, "index %.*s..%.*s",
|
||||||
"index %.*s..%.*s",
|
|
||||||
abbrev, sha1_to_hex(one->sha1),
|
abbrev, sha1_to_hex(one->sha1),
|
||||||
abbrev, sha1_to_hex(two->sha1));
|
abbrev, sha1_to_hex(two->sha1));
|
||||||
if (one->mode == two->mode)
|
if (one->mode == two->mode)
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
strbuf_addf(&msg, " %06o", one->mode);
|
||||||
" %06o", one->mode);
|
strbuf_addch(&msg, '\n');
|
||||||
len += snprintf(msg + len, sizeof(msg) - len, "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len)
|
if (msg.len)
|
||||||
msg[--len] = 0;
|
strbuf_setlen(&msg, msg.len - 1);
|
||||||
xfrm_msg = len ? msg : NULL;
|
xfrm_msg = msg.len ? msg.buf : NULL;
|
||||||
|
|
||||||
if (!pgm &&
|
if (!pgm &&
|
||||||
DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
|
DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
|
||||||
@ -2035,8 +2004,7 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
|||||||
run_diff_cmd(pgm, name, other, one, two, xfrm_msg, o,
|
run_diff_cmd(pgm, name, other, one, two, xfrm_msg, o,
|
||||||
complete_rewrite);
|
complete_rewrite);
|
||||||
|
|
||||||
free(name_munged);
|
strbuf_release(&msg);
|
||||||
free(other_munged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
|
static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
|
||||||
@ -2492,72 +2460,30 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len)
|
|||||||
return sha1_to_hex(sha1);
|
return sha1_to_hex(sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diff_flush_raw(struct diff_filepair *p,
|
static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt)
|
||||||
struct diff_options *options)
|
|
||||||
{
|
{
|
||||||
int two_paths;
|
int line_termination = opt->line_termination;
|
||||||
char status[10];
|
int inter_name_termination = line_termination ? '\t' : '\0';
|
||||||
int abbrev = options->abbrev;
|
|
||||||
const char *path_one, *path_two;
|
|
||||||
int inter_name_termination = '\t';
|
|
||||||
int line_termination = options->line_termination;
|
|
||||||
|
|
||||||
if (!line_termination)
|
if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) {
|
||||||
inter_name_termination = 0;
|
printf(":%06o %06o %s ", p->one->mode, p->two->mode,
|
||||||
|
diff_unique_abbrev(p->one->sha1, opt->abbrev));
|
||||||
path_one = p->one->path;
|
printf("%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev));
|
||||||
path_two = p->two->path;
|
}
|
||||||
if (line_termination) {
|
if (p->score) {
|
||||||
path_one = quote_one(path_one);
|
printf("%c%03d%c", p->status, similarity_index(p),
|
||||||
path_two = quote_one(path_two);
|
inter_name_termination);
|
||||||
|
} else {
|
||||||
|
printf("%c%c", p->status, inter_name_termination);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->score)
|
if (p->status == DIFF_STATUS_COPIED || p->status == DIFF_STATUS_RENAMED) {
|
||||||
sprintf(status, "%c%03d", p->status, similarity_index(p));
|
write_name_quoted(p->one->path, stdout, inter_name_termination);
|
||||||
else {
|
write_name_quoted(p->two->path, stdout, line_termination);
|
||||||
status[0] = p->status;
|
} else {
|
||||||
status[1] = 0;
|
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)
|
int diff_unmodified_pair(struct diff_filepair *p)
|
||||||
@ -2567,14 +2493,11 @@ int diff_unmodified_pair(struct diff_filepair *p)
|
|||||||
* let transformers to produce diff_filepairs any way they want,
|
* let transformers to produce diff_filepairs any way they want,
|
||||||
* and filter and clean them up here before producing the output.
|
* 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))
|
if (DIFF_PAIR_UNMERGED(p))
|
||||||
return 0; /* unmerged is interesting */
|
return 0; /* unmerged is interesting */
|
||||||
|
|
||||||
one = p->one;
|
|
||||||
two = p->two;
|
|
||||||
|
|
||||||
/* deletion, addition, mode or type change
|
/* deletion, addition, mode or type change
|
||||||
* and rename are all interesting.
|
* and rename are all interesting.
|
||||||
*/
|
*/
|
||||||
@ -2763,32 +2686,27 @@ static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
|
|||||||
else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS))
|
else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS))
|
||||||
diff_flush_raw(p, opt);
|
diff_flush_raw(p, opt);
|
||||||
else if (fmt & DIFF_FORMAT_NAME)
|
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)
|
static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs)
|
||||||
{
|
{
|
||||||
char *name = quote_one(fs->path);
|
|
||||||
if (fs->mode)
|
if (fs->mode)
|
||||||
printf(" %s mode %06o %s\n", newdelete, fs->mode, name);
|
printf(" %s mode %06o ", newdelete, fs->mode);
|
||||||
else
|
else
|
||||||
printf(" %s %s\n", newdelete, name);
|
printf(" %s ", newdelete);
|
||||||
free(name);
|
write_name_quoted(fs->path, stdout, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void show_mode_change(struct diff_filepair *p, int show_name)
|
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) {
|
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) {
|
if (show_name) {
|
||||||
char *name = quote_one(p->two->path);
|
write_name_quoted(p->two->path, stdout, '\n');
|
||||||
printf(" mode change %06o => %06o %s\n",
|
|
||||||
p->one->mode, p->two->mode, name);
|
|
||||||
free(name);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
printf(" mode change %06o => %06o\n",
|
|
||||||
p->one->mode, p->two->mode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2818,12 +2736,11 @@ static void diff_summary(struct diff_filepair *p)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (p->score) {
|
if (p->score) {
|
||||||
char *name = quote_one(p->two->path);
|
puts(" rewrite ");
|
||||||
printf(" rewrite %s (%d%%)\n", name,
|
write_name_quoted(p->two->path, stdout, ' ');
|
||||||
similarity_index(p));
|
printf("(%d%%)\n", similarity_index(p));
|
||||||
free(name);
|
}
|
||||||
show_mode_change(p, 0);
|
show_mode_change(p, !p->score);
|
||||||
} else show_mode_change(p, 1);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2837,14 +2754,14 @@ struct patch_id_t {
|
|||||||
static int remove_space(char *line, int len)
|
static int remove_space(char *line, int len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *dst = line;
|
char *dst = line;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
if (!isspace((c = line[i])))
|
if (!isspace((c = line[i])))
|
||||||
*dst++ = c;
|
*dst++ = c;
|
||||||
|
|
||||||
return dst - line;
|
return dst - line;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void patch_id_consume(void *priv, char *line, unsigned long len)
|
static void patch_id_consume(void *priv, char *line, unsigned long len)
|
||||||
|
@ -1111,9 +1111,7 @@ static int store_object(
|
|||||||
if (last->no_swap) {
|
if (last->no_swap) {
|
||||||
last->data = *dat;
|
last->data = *dat;
|
||||||
} else {
|
} else {
|
||||||
struct strbuf tmp = *dat;
|
strbuf_swap(&last->data, dat);
|
||||||
*dat = last->data;
|
|
||||||
last->data = tmp;
|
|
||||||
}
|
}
|
||||||
last->offset = e->offset;
|
last->offset = e->offset;
|
||||||
}
|
}
|
||||||
@ -1761,7 +1759,7 @@ static void load_branch(struct branch *b)
|
|||||||
static void file_change_m(struct branch *b)
|
static void file_change_m(struct branch *b)
|
||||||
{
|
{
|
||||||
const char *p = command_buf.buf + 2;
|
const char *p = command_buf.buf + 2;
|
||||||
char *p_uq;
|
static struct strbuf uq = STRBUF_INIT;
|
||||||
const char *endp;
|
const char *endp;
|
||||||
struct object_entry *oe = oe;
|
struct object_entry *oe = oe;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
@ -1799,18 +1797,20 @@ static void file_change_m(struct branch *b)
|
|||||||
if (*p++ != ' ')
|
if (*p++ != ' ')
|
||||||
die("Missing space after SHA1: %s", command_buf.buf);
|
die("Missing space after SHA1: %s", command_buf.buf);
|
||||||
|
|
||||||
p_uq = unquote_c_style(p, &endp);
|
strbuf_reset(&uq);
|
||||||
if (p_uq) {
|
if (!unquote_c_style(&uq, p, &endp)) {
|
||||||
if (*endp)
|
if (*endp)
|
||||||
die("Garbage after path in: %s", command_buf.buf);
|
die("Garbage after path in: %s", command_buf.buf);
|
||||||
p = p_uq;
|
p = uq.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inline_data) {
|
if (inline_data) {
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
static struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
if (!p_uq)
|
if (p != uq.buf) {
|
||||||
p = p_uq = xstrdup(p);
|
strbuf_addstr(&uq, p);
|
||||||
|
p = uq.buf;
|
||||||
|
}
|
||||||
read_next_command();
|
read_next_command();
|
||||||
cmd_data(&buf);
|
cmd_data(&buf);
|
||||||
store_object(OBJ_BLOB, &buf, &last_blob, sha1, 0);
|
store_object(OBJ_BLOB, &buf, &last_blob, sha1, 0);
|
||||||
@ -1828,56 +1828,54 @@ static void file_change_m(struct branch *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode, NULL);
|
tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode, NULL);
|
||||||
free(p_uq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_change_d(struct branch *b)
|
static void file_change_d(struct branch *b)
|
||||||
{
|
{
|
||||||
const char *p = command_buf.buf + 2;
|
const char *p = command_buf.buf + 2;
|
||||||
char *p_uq;
|
static struct strbuf uq = STRBUF_INIT;
|
||||||
const char *endp;
|
const char *endp;
|
||||||
|
|
||||||
p_uq = unquote_c_style(p, &endp);
|
strbuf_reset(&uq);
|
||||||
if (p_uq) {
|
if (!unquote_c_style(&uq, p, &endp)) {
|
||||||
if (*endp)
|
if (*endp)
|
||||||
die("Garbage after path in: %s", command_buf.buf);
|
die("Garbage after path in: %s", command_buf.buf);
|
||||||
p = p_uq;
|
p = uq.buf;
|
||||||
}
|
}
|
||||||
tree_content_remove(&b->branch_tree, p, NULL);
|
tree_content_remove(&b->branch_tree, p, NULL);
|
||||||
free(p_uq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_change_cr(struct branch *b, int rename)
|
static void file_change_cr(struct branch *b, int rename)
|
||||||
{
|
{
|
||||||
const char *s, *d;
|
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;
|
const char *endp;
|
||||||
struct tree_entry leaf;
|
struct tree_entry leaf;
|
||||||
|
|
||||||
s = command_buf.buf + 2;
|
s = command_buf.buf + 2;
|
||||||
s_uq = unquote_c_style(s, &endp);
|
strbuf_reset(&s_uq);
|
||||||
if (s_uq) {
|
if (!unquote_c_style(&s_uq, s, &endp)) {
|
||||||
if (*endp != ' ')
|
if (*endp != ' ')
|
||||||
die("Missing space after source: %s", command_buf.buf);
|
die("Missing space after source: %s", command_buf.buf);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
endp = strchr(s, ' ');
|
endp = strchr(s, ' ');
|
||||||
if (!endp)
|
if (!endp)
|
||||||
die("Missing space after source: %s", command_buf.buf);
|
die("Missing space after source: %s", command_buf.buf);
|
||||||
s_uq = xmemdupz(s, endp - s);
|
strbuf_add(&s_uq, s, endp - s);
|
||||||
}
|
}
|
||||||
s = s_uq;
|
s = s_uq.buf;
|
||||||
|
|
||||||
endp++;
|
endp++;
|
||||||
if (!*endp)
|
if (!*endp)
|
||||||
die("Missing dest: %s", command_buf.buf);
|
die("Missing dest: %s", command_buf.buf);
|
||||||
|
|
||||||
d = endp;
|
d = endp;
|
||||||
d_uq = unquote_c_style(d, &endp);
|
strbuf_reset(&d_uq);
|
||||||
if (d_uq) {
|
if (!unquote_c_style(&d_uq, d, &endp)) {
|
||||||
if (*endp)
|
if (*endp)
|
||||||
die("Garbage after dest in: %s", command_buf.buf);
|
die("Garbage after dest in: %s", command_buf.buf);
|
||||||
d = d_uq;
|
d = d_uq.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&leaf, 0, sizeof(leaf));
|
memset(&leaf, 0, sizeof(leaf));
|
||||||
@ -1891,9 +1889,6 @@ static void file_change_cr(struct branch *b, int rename)
|
|||||||
leaf.versions[1].sha1,
|
leaf.versions[1].sha1,
|
||||||
leaf.versions[1].mode,
|
leaf.versions[1].mode,
|
||||||
leaf.tree);
|
leaf.tree);
|
||||||
|
|
||||||
free(s_uq);
|
|
||||||
free(d_uq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_change_deleteall(struct branch *b)
|
static void file_change_deleteall(struct branch *b)
|
||||||
|
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) {
|
||||||
if (alias_string[0] == '!') {
|
if (alias_string[0] == '!') {
|
||||||
if (*argcp > 1) {
|
if (*argcp > 1) {
|
||||||
int i, sz = PATH_MAX;
|
struct strbuf buf;
|
||||||
char *s = xmalloc(sz), *new_alias = s;
|
|
||||||
|
|
||||||
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);
|
free(alias_string);
|
||||||
alias_string = new_alias;
|
alias_string = buf.buf;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
trace_printf("trace: alias to shell cmd: %s => %s\n",
|
trace_printf("trace: alias to shell cmd: %s => %s\n",
|
||||||
alias_command, alias_string + 1);
|
alias_command, alias_string + 1);
|
||||||
|
13
imap-send.c
13
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 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 void arc4_init( void );
|
||||||
static unsigned char arc4_getbyte( void );
|
static unsigned char arc4_getbyte( void );
|
||||||
|
@ -85,63 +85,58 @@ struct stage_data
|
|||||||
unsigned processed:1;
|
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_file_set = {NULL, 0, 0, 1};
|
||||||
static struct path_list current_directory_set = {NULL, 0, 0, 1};
|
static struct path_list current_directory_set = {NULL, 0, 0, 1};
|
||||||
|
|
||||||
static int call_depth = 0;
|
static int call_depth = 0;
|
||||||
static int verbosity = 2;
|
static int verbosity = 2;
|
||||||
static int buffer_output = 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;
|
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)
|
static void flush_output(void)
|
||||||
{
|
{
|
||||||
struct output_buffer *b, *n;
|
if (obuf.len) {
|
||||||
for (b = output_list; b; b = n) {
|
fputs(obuf.buf, stdout);
|
||||||
int i;
|
strbuf_reset(&obuf);
|
||||||
for (i = call_depth; i--;)
|
|
||||||
fputs(" ", stdout);
|
|
||||||
fputs(b->str, stdout);
|
|
||||||
fputc('\n', stdout);
|
|
||||||
n = b->next;
|
|
||||||
free(b->str);
|
|
||||||
free(b);
|
|
||||||
}
|
}
|
||||||
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)
|
static void output_commit_title(struct commit *commit)
|
||||||
|
25
mktree.c
25
mktree.c
@ -66,6 +66,7 @@ static const char mktree_usage[] = "git-mktree [-z]";
|
|||||||
int main(int ac, char **av)
|
int main(int ac, char **av)
|
||||||
{
|
{
|
||||||
struct strbuf sb;
|
struct strbuf sb;
|
||||||
|
struct strbuf p_uq;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
int line_termination = '\n';
|
int line_termination = '\n';
|
||||||
|
|
||||||
@ -82,14 +83,13 @@ int main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
|
|
||||||
strbuf_init(&sb, 0);
|
strbuf_init(&sb, 0);
|
||||||
while (1) {
|
strbuf_init(&p_uq, 0);
|
||||||
|
while (strbuf_getline(&sb, stdin, line_termination) != EOF) {
|
||||||
char *ptr, *ntr;
|
char *ptr, *ntr;
|
||||||
unsigned mode;
|
unsigned mode;
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (strbuf_getline(&sb, stdin, line_termination) == EOF)
|
|
||||||
break;
|
|
||||||
ptr = sb.buf;
|
ptr = sb.buf;
|
||||||
/* Input is non-recursive ls-tree output format
|
/* Input is non-recursive ls-tree output format
|
||||||
* mode SP type SP sha1 TAB name
|
* mode SP type SP sha1 TAB name
|
||||||
@ -109,18 +109,21 @@ int main(int ac, char **av)
|
|||||||
*ntr++ = 0; /* now at the beginning of SHA1 */
|
*ntr++ = 0; /* now at the beginning of SHA1 */
|
||||||
if (type != type_from_string(ptr))
|
if (type != type_from_string(ptr))
|
||||||
die("object type %s mismatch (%s)", ptr, typename(type));
|
die("object type %s mismatch (%s)", ptr, typename(type));
|
||||||
ntr += 41; /* at the beginning of name */
|
|
||||||
if (line_termination && ntr[0] == '"')
|
path = ntr + 41; /* at the beginning of name */
|
||||||
path = unquote_c_style(ntr, NULL);
|
if (line_termination && path[0] == '"') {
|
||||||
else
|
strbuf_reset(&p_uq);
|
||||||
path = ntr;
|
if (unquote_c_style(&p_uq, path, NULL)) {
|
||||||
|
die("invalid quoting");
|
||||||
|
}
|
||||||
|
path = p_uq.buf;
|
||||||
|
}
|
||||||
|
|
||||||
append_to_tree(mode, sha1, path);
|
append_to_tree(mode, sha1, path);
|
||||||
|
|
||||||
if (path != ntr)
|
|
||||||
free(path);
|
|
||||||
}
|
}
|
||||||
|
strbuf_release(&p_uq);
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
|
|
||||||
write_tree(sha1);
|
write_tree(sha1);
|
||||||
puts(sha1_to_hex(sha1));
|
puts(sha1_to_hex(sha1));
|
||||||
exit(0);
|
exit(0);
|
||||||
|
399
quote.c
399
quote.c
@ -12,37 +12,31 @@
|
|||||||
* a'b ==> a'\''b ==> 'a'\''b'
|
* a'b ==> a'\''b ==> 'a'\''b'
|
||||||
* 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)
|
static inline int need_bs_quote(char c)
|
||||||
{
|
{
|
||||||
return (c == '\'' || 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 *to_free = NULL;
|
||||||
char *bp = dst;
|
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
EMIT('\'');
|
if (dst->buf == src)
|
||||||
while ((c = *src++)) {
|
to_free = strbuf_detach(dst);
|
||||||
if (need_bs_quote(c)) {
|
|
||||||
EMIT('\'');
|
strbuf_addch(dst, '\'');
|
||||||
EMIT('\\');
|
while (*src) {
|
||||||
EMIT(c);
|
size_t len = strcspn(src, "'\\");
|
||||||
EMIT('\'');
|
strbuf_add(dst, src, len);
|
||||||
} else {
|
src += len;
|
||||||
EMIT(c);
|
while (need_bs_quote(*src)) {
|
||||||
|
strbuf_addstr(dst, "'\\");
|
||||||
|
strbuf_addch(dst, *src++);
|
||||||
|
strbuf_addch(dst, '\'');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EMIT('\'');
|
strbuf_addch(dst, '\'');
|
||||||
|
free(to_free);
|
||||||
if ( n )
|
|
||||||
*bp = 0;
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sq_quote_print(FILE *stream, const char *src)
|
void sq_quote_print(FILE *stream, const char *src)
|
||||||
@ -62,11 +56,10 @@ void sq_quote_print(FILE *stream, const char *src)
|
|||||||
fputc('\'', stream);
|
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;
|
int i;
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
/* Count argv if needed. */
|
/* Count argv if needed. */
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
@ -74,53 +67,14 @@ char *sq_quote_argv(const char** argv, int count)
|
|||||||
; /* just counting */
|
; /* 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. */
|
/* Copy into destination buffer. */
|
||||||
|
strbuf_grow(dst, 32 * count);
|
||||||
for (i = 0; i < count; ++i) {
|
for (i = 0; i < count; ++i) {
|
||||||
*to++ = ' ';
|
strbuf_addch(dst, ' ');
|
||||||
to += sq_quote_buf(to, len, argv[i]);
|
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)
|
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.
|
* 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
|
* (2) if sb or fp are not NULL, it emits the c_style quoted version
|
||||||
* counts the number of bytes that are needed to hold c_style
|
* of name, enclosed with double quotes if asked and needed only.
|
||||||
* quoted version of name, counting the double quotes around
|
* Return value is the same as in (1).
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
|
||||||
static int quote_c_style_counted(const char *name, int namelen,
|
struct strbuf *sb, FILE *fp, int no_dq)
|
||||||
char *outbuf, FILE *outfp, int no_dq)
|
|
||||||
{
|
{
|
||||||
#undef EMIT
|
#undef EMIT
|
||||||
#define EMIT(c) \
|
#define EMIT(c) \
|
||||||
(outbuf ? (*outbuf++ = (c)) : outfp ? fputc(c, outfp) : (count++))
|
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;
|
for (;;) {
|
||||||
unsigned char ch;
|
int ch;
|
||||||
int count = 0, needquote = 0;
|
|
||||||
|
|
||||||
if (!no_dq)
|
len = next_quote_pos(p, maxlen);
|
||||||
EMIT('"');
|
if (len == maxlen || !p[len])
|
||||||
for (sp = name; sp < name + namelen; sp++) {
|
|
||||||
ch = *sp;
|
|
||||||
if (!ch)
|
|
||||||
break;
|
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 */
|
if (!no_dq && p == name)
|
||||||
case '"': EMITQ(); break;
|
EMIT('"');
|
||||||
default:
|
|
||||||
/* octal */
|
EMITBUF(p, len);
|
||||||
EMITQ();
|
EMIT('\\');
|
||||||
EMIT(((ch >> 6) & 03) + '0');
|
p += len;
|
||||||
EMIT(((ch >> 3) & 07) + '0');
|
ch = (unsigned char)*p++;
|
||||||
ch = (ch & 07) + '0';
|
if (sq_lookup[ch] >= ' ') {
|
||||||
break;
|
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)
|
if (!no_dq)
|
||||||
EMIT('"');
|
EMIT('"');
|
||||||
if (outbuf)
|
return count;
|
||||||
*outbuf = 0;
|
|
||||||
|
|
||||||
return needquote ? count : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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, -1, sb, fp, nodq);
|
||||||
return quote_c_style_counted(name, cnt, outbuf, outfp, no_dq);
|
}
|
||||||
|
|
||||||
|
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.
|
* C-style name unquoting.
|
||||||
*
|
*
|
||||||
* Quoted should point at the opening double quote. Returns
|
* Quoted should point at the opening double quote.
|
||||||
* an allocated memory that holds unquoted name, which the caller
|
* + Returns 0 if it was able to unquote the string properly, and appends the
|
||||||
* should free when done. Updates endp pointer to point at
|
* result in the strbuf `sb'.
|
||||||
* one past the ending double quote if given.
|
* + 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.
|
||||||
*/
|
*/
|
||||||
|
int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp)
|
||||||
char *unquote_c_style(const char *quoted, const char **endp)
|
|
||||||
{
|
{
|
||||||
const char *sp;
|
size_t oldlen = sb->len, len;
|
||||||
char *name = NULL, *outp = NULL;
|
int ch, ac;
|
||||||
int count = 0, ch, ac;
|
|
||||||
|
|
||||||
#undef EMIT
|
|
||||||
#define EMIT(c) (outp ? (*outp++ = (c)) : (count++))
|
|
||||||
|
|
||||||
if (*quoted++ != '"')
|
if (*quoted++ != '"')
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
while (1) {
|
for (;;) {
|
||||||
/* first pass counts and allocates, second pass fills */
|
len = strcspn(quoted, "\"\\");
|
||||||
for (sp = quoted; (ch = *sp++) != '"'; ) {
|
strbuf_add(sb, quoted, len);
|
||||||
if (ch == '\\') {
|
quoted += len;
|
||||||
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;
|
|
||||||
|
|
||||||
case '\\': case '"':
|
switch (*quoted++) {
|
||||||
break; /* verbatim */
|
case '"':
|
||||||
|
if (endp)
|
||||||
|
*endp = quoted + 1;
|
||||||
|
return 0;
|
||||||
|
case '\\':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
case '0':
|
switch ((ch = *quoted++)) {
|
||||||
case '1':
|
case 'a': ch = '\a'; break;
|
||||||
case '2':
|
case 'b': ch = '\b'; break;
|
||||||
case '3':
|
case 'f': ch = '\f'; break;
|
||||||
case '4':
|
case 'n': ch = '\n'; break;
|
||||||
case '5':
|
case 'r': ch = '\r'; break;
|
||||||
case '6':
|
case 't': ch = '\t'; break;
|
||||||
case '7':
|
case 'v': ch = '\v'; break;
|
||||||
/* octal */
|
|
||||||
|
case '\\': case '"':
|
||||||
|
break; /* verbatim */
|
||||||
|
|
||||||
|
/* octal values with first digit over 4 overflow */
|
||||||
|
case '0': case '1': case '2': case '3':
|
||||||
ac = ((ch - '0') << 6);
|
ac = ((ch - '0') << 6);
|
||||||
if ((ch = *sp++) < '0' || '7' < ch)
|
if ((ch = *quoted++) < '0' || '7' < ch)
|
||||||
return NULL;
|
goto error;
|
||||||
ac |= ((ch - '0') << 3);
|
ac |= ((ch - '0') << 3);
|
||||||
if ((ch = *sp++) < '0' || '7' < ch)
|
if ((ch = *quoted++) < '0' || '7' < ch)
|
||||||
return NULL;
|
goto error;
|
||||||
ac |= (ch - '0');
|
ac |= (ch - '0');
|
||||||
ch = ac;
|
ch = ac;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return NULL; /* malformed */
|
goto error;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EMIT(ch);
|
strbuf_addch(sb, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name) {
|
error:
|
||||||
*outp = 0;
|
strbuf_setlen(sb, oldlen);
|
||||||
if (endp)
|
return -1;
|
||||||
*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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* quoting as a string literal for other languages */
|
/* 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 void sq_quote_print(FILE *stream, const char *src);
|
||||||
extern char *sq_quote_argv(const char** argv, int count);
|
|
||||||
|
|
||||||
/*
|
extern void sq_quote_buf(struct strbuf *, const char *src);
|
||||||
* Append a string to a string buffer, with or without shell quoting.
|
extern void sq_quote_argv(struct strbuf *, const char **argv, int count,
|
||||||
* Return true if the buffer overflowed.
|
size_t maxlen);
|
||||||
*/
|
|
||||||
extern int add_to_string(char **ptrp, int *sizep, const char *str, int quote);
|
|
||||||
|
|
||||||
/* This unwraps what sq_quote() produces in place, but returns
|
/* This unwraps what sq_quote() produces in place, but returns
|
||||||
* NULL if the input does not look like what sq_quote would have
|
* 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 char *sq_dequote(char *);
|
||||||
|
|
||||||
extern int quote_c_style(const char *name, char *outbuf, FILE *outfp,
|
extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
|
||||||
int nodq);
|
extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
|
||||||
extern char *unquote_c_style(const char *quoted, const char **endp);
|
|
||||||
|
|
||||||
extern void write_name_quoted(const char *prefix, int prefix_len,
|
extern void write_name_quoted(const char *name, FILE *, int terminator);
|
||||||
const char *name, int quote, FILE *out);
|
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 */
|
/* quoting as a string literal for other languages */
|
||||||
extern void perl_quote_print(FILE *stream, const char *src);
|
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;
|
SHA_CTX c;
|
||||||
struct cache_header hdr;
|
struct cache_header hdr;
|
||||||
int i, removed;
|
int i, err, removed;
|
||||||
struct cache_entry **cache = istate->cache;
|
struct cache_entry **cache = istate->cache;
|
||||||
int entries = istate->cache_nr;
|
int entries = istate->cache_nr;
|
||||||
|
|
||||||
@ -1165,16 +1165,15 @@ int write_index(struct index_state *istate, int newfd)
|
|||||||
|
|
||||||
/* Write extension data here */
|
/* Write extension data here */
|
||||||
if (istate->cache_tree) {
|
if (istate->cache_tree) {
|
||||||
unsigned long sz;
|
struct strbuf sb;
|
||||||
void *data = cache_tree_write(istate->cache_tree, &sz);
|
|
||||||
if (data &&
|
strbuf_init(&sb, 0);
|
||||||
!write_index_ext_header(&c, newfd, CACHE_EXT_TREE, sz) &&
|
cache_tree_write(&sb, istate->cache_tree);
|
||||||
!ce_write(&c, newfd, data, sz))
|
err = write_index_ext_header(&c, newfd, CACHE_EXT_TREE, sb.len) < 0
|
||||||
free(data);
|
|| ce_write(&c, newfd, sb.buf, sb.len) < 0;
|
||||||
else {
|
strbuf_release(&sb);
|
||||||
free(data);
|
if (err)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ce_flush(&c, newfd);
|
return ce_flush(&c, newfd);
|
||||||
}
|
}
|
||||||
|
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 *host;
|
||||||
char *path;
|
char *path;
|
||||||
int sv[2];
|
int sv[2];
|
||||||
char command[COMMAND_SIZE];
|
|
||||||
char *posn;
|
|
||||||
int sizen;
|
|
||||||
int of;
|
|
||||||
int i;
|
int i;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
struct strbuf cmd;
|
||||||
|
|
||||||
if (!strcmp(url, "-")) {
|
if (!strcmp(url, "-")) {
|
||||||
*fd_in = 0;
|
*fd_in = 0;
|
||||||
@ -36,24 +33,23 @@ int setup_connection(int *fd_in, int *fd_out, const char *remote_prog,
|
|||||||
if (!path) {
|
if (!path) {
|
||||||
return error("Bad URL: %s", url);
|
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++ ) {
|
/* $GIT_RSH <host> "env GIT_DIR=<path> <remote_prog> <args...>" */
|
||||||
of |= add_to_string(&posn, &sizen, " ", 0);
|
strbuf_init(&cmd, COMMAND_SIZE);
|
||||||
of |= add_to_string(&posn, &sizen, rmt_argv[i], 1);
|
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");
|
return error("Command line too long");
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
|
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]);
|
close(sv[1]);
|
||||||
dup2(sv[0], 0);
|
dup2(sv[0], 0);
|
||||||
dup2(sv[0], 1);
|
dup2(sv[0], 1);
|
||||||
execlp(ssh, ssh_basename, host, command, NULL);
|
execlp(ssh, ssh_basename, host, cmd.buf, NULL);
|
||||||
}
|
}
|
||||||
close(sv[0]);
|
close(sv[0]);
|
||||||
*fd_in = sv[1];
|
*fd_in = sv[1];
|
||||||
|
41
strbuf.c
41
strbuf.c
@ -50,14 +50,16 @@ void strbuf_rtrim(struct strbuf *sb)
|
|||||||
sb->buf[sb->len] = '\0';
|
sb->buf[sb->len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
|
int strbuf_cmp(struct strbuf *a, struct strbuf *b)
|
||||||
{
|
{
|
||||||
strbuf_grow(sb, len);
|
int cmp;
|
||||||
if (pos > sb->len)
|
if (a->len < b->len) {
|
||||||
die("`pos' is too far after the end of the buffer");
|
cmp = memcmp(a->buf, b->buf, a->len);
|
||||||
memmove(sb->buf + pos + len, sb->buf + pos, sb->len - pos);
|
return cmp ? cmp : -1;
|
||||||
memcpy(sb->buf + pos, data, len);
|
} else {
|
||||||
strbuf_setlen(sb, sb->len + len);
|
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,
|
void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
|
||||||
@ -79,6 +81,16 @@ void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
|
|||||||
strbuf_setlen(sb, sb->len + dlen - len);
|
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)
|
void strbuf_add(struct strbuf *sb, const void *data, size_t len)
|
||||||
{
|
{
|
||||||
strbuf_grow(sb, len);
|
strbuf_grow(sb, len);
|
||||||
@ -165,3 +177,18 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
|
|||||||
sb->buf[sb->len] = '\0';
|
sb->buf[sb->len] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int strbuf_read_file(struct strbuf *sb, const char *path)
|
||||||
|
{
|
||||||
|
int fd, len;
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
len = strbuf_read(sb, fd, 0);
|
||||||
|
close(fd);
|
||||||
|
if (len < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
28
strbuf.h
28
strbuf.h
@ -55,21 +55,30 @@ extern void strbuf_release(struct strbuf *);
|
|||||||
extern void strbuf_reset(struct strbuf *);
|
extern void strbuf_reset(struct strbuf *);
|
||||||
extern char *strbuf_detach(struct strbuf *);
|
extern char *strbuf_detach(struct strbuf *);
|
||||||
extern void strbuf_attach(struct strbuf *, void *, size_t, 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 -----*/
|
/*----- strbuf size related -----*/
|
||||||
static inline size_t strbuf_avail(struct strbuf *sb) {
|
static inline size_t strbuf_avail(struct strbuf *sb) {
|
||||||
return sb->alloc ? sb->alloc - sb->len - 1 : 0;
|
return sb->alloc ? sb->alloc - sb->len - 1 : 0;
|
||||||
}
|
|
||||||
static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
|
|
||||||
assert (len < sb->alloc);
|
|
||||||
sb->len = len;
|
|
||||||
sb->buf[len] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void strbuf_grow(struct strbuf *, size_t);
|
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';
|
||||||
|
}
|
||||||
|
|
||||||
/*----- content related -----*/
|
/*----- content related -----*/
|
||||||
extern void strbuf_rtrim(struct strbuf *);
|
extern void strbuf_rtrim(struct strbuf *);
|
||||||
|
extern int strbuf_cmp(struct strbuf *, struct strbuf *);
|
||||||
|
|
||||||
/*----- add data in your buffer -----*/
|
/*----- add data in your buffer -----*/
|
||||||
static inline void strbuf_addch(struct strbuf *sb, int c) {
|
static inline void strbuf_addch(struct strbuf *sb, int c) {
|
||||||
@ -78,12 +87,12 @@ static inline void strbuf_addch(struct strbuf *sb, int c) {
|
|||||||
sb->buf[sb->len] = '\0';
|
sb->buf[sb->len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* inserts after pos, or appends if pos >= sb->len */
|
|
||||||
extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t);
|
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 */
|
/* splice pos..pos+len with given data */
|
||||||
extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,
|
extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,
|
||||||
const void *, size_t);
|
const void *, size_t);
|
||||||
|
|
||||||
extern void strbuf_add(struct strbuf *, 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) {
|
static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
|
||||||
@ -99,7 +108,10 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
|
|||||||
extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
|
extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
|
||||||
/* XXX: if read fails, any partial read is undone */
|
/* XXX: if read fails, any partial read is undone */
|
||||||
extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
|
extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
|
||||||
|
extern int strbuf_read_file(struct strbuf *sb, const char *path);
|
||||||
|
|
||||||
extern int strbuf_getline(struct strbuf *, FILE *, int);
|
extern int strbuf_getline(struct strbuf *, FILE *, int);
|
||||||
|
|
||||||
|
extern void stripspace(struct strbuf *buf, int skip_comments);
|
||||||
|
|
||||||
#endif /* STRBUF_H */
|
#endif /* STRBUF_H */
|
||||||
|
109
trace.c
109
trace.c
@ -25,33 +25,6 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "quote.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. */
|
/* Get a trace file descriptor from GIT_TRACE env variable. */
|
||||||
static int get_trace_fd(int *need_close)
|
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 "
|
static const char err_msg[] = "Could not trace into fd given by "
|
||||||
"GIT_TRACE environment variable";
|
"GIT_TRACE environment variable";
|
||||||
|
|
||||||
void trace_printf(const char *format, ...)
|
void trace_printf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char *trace_str;
|
struct strbuf buf;
|
||||||
va_list rest;
|
va_list ap;
|
||||||
int need_close = 0;
|
int fd, len, need_close = 0;
|
||||||
int fd = get_trace_fd(&need_close);
|
|
||||||
|
|
||||||
|
fd = get_trace_fd(&need_close);
|
||||||
if (!fd)
|
if (!fd)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_start(rest, format);
|
strbuf_init(&buf, 0);
|
||||||
nfvasprintf(&trace_str, format, rest);
|
va_start(ap, fmt);
|
||||||
va_end(rest);
|
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);
|
write_or_whine_pipe(fd, buf.buf, buf.len, err_msg);
|
||||||
|
strbuf_release(&buf);
|
||||||
free(trace_str);
|
|
||||||
|
|
||||||
if (need_close)
|
if (need_close)
|
||||||
close(fd);
|
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;
|
struct strbuf buf;
|
||||||
size_t argv_len, format_len, trace_len;
|
va_list ap;
|
||||||
va_list rest;
|
int fd, len, need_close = 0;
|
||||||
int need_close = 0;
|
|
||||||
int fd = get_trace_fd(&need_close);
|
|
||||||
|
|
||||||
|
fd = get_trace_fd(&need_close);
|
||||||
if (!fd)
|
if (!fd)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Get the argv string. */
|
strbuf_init(&buf, 0);
|
||||||
argv_str = sq_quote_argv(argv, count);
|
va_start(ap, fmt);
|
||||||
argv_len = strlen(argv_str);
|
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. */
|
sq_quote_argv(&buf, argv, count, 0);
|
||||||
va_start(rest, format);
|
strbuf_addch(&buf, '\n');
|
||||||
nfvasprintf(&format_str, format, rest);
|
write_or_whine_pipe(fd, buf.buf, buf.len, err_msg);
|
||||||
va_end(rest);
|
strbuf_release(&buf);
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
if (need_close)
|
if (need_close)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
Loading…
Reference in New Issue
Block a user