1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-30 02:06:12 +02:00

tree.c: update read_tree_recursive callback to pass strbuf as base

This allows the callback to use 'base' as a temporary buffer to
quickly assemble full path "without" extra allocation. The callback
has to restore it afterwards of course.

Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2014-11-30 16:05:00 +07:00 committed by Junio C Hamano
parent b260d265e1
commit 6a0b0b6de9
7 changed files with 50 additions and 37 deletions

View File

@ -157,18 +157,26 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
return write_entry(args, sha1, path.buf, path.len, mode); return write_entry(args, sha1, path.buf, path.len, mode);
} }
static int write_archive_entry_buf(const unsigned char *sha1, struct strbuf *base,
const char *filename, unsigned mode, int stage,
void *context)
{
return write_archive_entry(sha1, base->buf, base->len,
filename, mode, stage, context);
}
static void queue_directory(const unsigned char *sha1, static void queue_directory(const unsigned char *sha1,
const char *base, int baselen, const char *filename, struct strbuf *base, const char *filename,
unsigned mode, int stage, struct archiver_context *c) unsigned mode, int stage, struct archiver_context *c)
{ {
struct directory *d; struct directory *d;
d = xmallocz(sizeof(*d) + baselen + 1 + strlen(filename)); d = xmallocz(sizeof(*d) + base->len + 1 + strlen(filename));
d->up = c->bottom; d->up = c->bottom;
d->baselen = baselen; d->baselen = base->len;
d->mode = mode; d->mode = mode;
d->stage = stage; d->stage = stage;
c->bottom = d; c->bottom = d;
d->len = sprintf(d->path, "%.*s%s/", baselen, base, filename); d->len = sprintf(d->path, "%.*s%s/", (int)base->len, base->buf, filename);
hashcpy(d->sha1, sha1); hashcpy(d->sha1, sha1);
} }
@ -191,28 +199,28 @@ static int write_directory(struct archiver_context *c)
} }
static int queue_or_write_archive_entry(const unsigned char *sha1, static int queue_or_write_archive_entry(const unsigned char *sha1,
const char *base, int baselen, const char *filename, struct strbuf *base, const char *filename,
unsigned mode, int stage, void *context) unsigned mode, int stage, void *context)
{ {
struct archiver_context *c = context; struct archiver_context *c = context;
while (c->bottom && while (c->bottom &&
!(baselen >= c->bottom->len && !(base->len >= c->bottom->len &&
!strncmp(base, c->bottom->path, c->bottom->len))) { !strncmp(base->buf, c->bottom->path, c->bottom->len))) {
struct directory *next = c->bottom->up; struct directory *next = c->bottom->up;
free(c->bottom); free(c->bottom);
c->bottom = next; c->bottom = next;
} }
if (S_ISDIR(mode)) { if (S_ISDIR(mode)) {
queue_directory(sha1, base, baselen, filename, queue_directory(sha1, base, filename,
mode, stage, c); mode, stage, c);
return READ_TREE_RECURSIVE; return READ_TREE_RECURSIVE;
} }
if (write_directory(c)) if (write_directory(c))
return -1; return -1;
return write_archive_entry(sha1, base, baselen, filename, mode, return write_archive_entry(sha1, base->buf, base->len, filename, mode,
stage, context); stage, context);
} }
@ -260,7 +268,7 @@ int write_archive_entries(struct archiver_args *args,
err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec, err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
args->pathspec.has_wildcard ? args->pathspec.has_wildcard ?
queue_or_write_archive_entry : queue_or_write_archive_entry :
write_archive_entry, write_archive_entry_buf,
&context); &context);
if (err == READ_TREE_RECURSIVE) if (err == READ_TREE_RECURSIVE)
err = 0; err = 0;
@ -286,14 +294,14 @@ static const struct archiver *lookup_archiver(const char *name)
return NULL; return NULL;
} }
static int reject_entry(const unsigned char *sha1, const char *base, static int reject_entry(const unsigned char *sha1, struct strbuf *base,
int baselen, const char *filename, unsigned mode, const char *filename, unsigned mode,
int stage, void *context) int stage, void *context)
{ {
int ret = -1; int ret = -1;
if (S_ISDIR(mode)) { if (S_ISDIR(mode)) {
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
strbuf_addstr(&sb, base); strbuf_addbuf(&sb, base);
strbuf_addstr(&sb, filename); strbuf_addstr(&sb, filename);
if (!match_pathspec(context, sb.buf, sb.len, 0, NULL, 1)) if (!match_pathspec(context, sb.buf, sb.len, 0, NULL, 1))
ret = READ_TREE_RECURSIVE; ret = READ_TREE_RECURSIVE;

View File

@ -62,7 +62,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
} }
static int update_some(const unsigned char *sha1, const char *base, int baselen, static int update_some(const unsigned char *sha1, struct strbuf *base,
const char *pathname, unsigned mode, int stage, void *context) const char *pathname, unsigned mode, int stage, void *context)
{ {
int len; int len;
@ -71,11 +71,11 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
if (S_ISDIR(mode)) if (S_ISDIR(mode))
return READ_TREE_RECURSIVE; return READ_TREE_RECURSIVE;
len = baselen + strlen(pathname); len = base->len + strlen(pathname);
ce = xcalloc(1, cache_entry_size(len)); ce = xcalloc(1, cache_entry_size(len));
hashcpy(ce->sha1, sha1); hashcpy(ce->sha1, sha1);
memcpy(ce->name, base, baselen); memcpy(ce->name, base->buf, base->len);
memcpy(ce->name + baselen, pathname, len - baselen); memcpy(ce->name + base->len, pathname, len - base->len);
ce->ce_flags = create_ce_flags(0) | CE_UPDATE; ce->ce_flags = create_ce_flags(0) | CE_UPDATE;
ce->ce_namelen = len; ce->ce_namelen = len;
ce->ce_mode = create_ce_mode(mode); ce->ce_mode = create_ce_mode(mode);

View File

@ -489,7 +489,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev)
} }
static int show_tree_object(const unsigned char *sha1, static int show_tree_object(const unsigned char *sha1,
const char *base, int baselen, struct strbuf *base,
const char *pathname, unsigned mode, int stage, void *context) const char *pathname, unsigned mode, int stage, void *context)
{ {
printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : ""); printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");

View File

@ -61,7 +61,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
} }
} }
static int show_tree(const unsigned char *sha1, const char *base, int baselen, static int show_tree(const unsigned char *sha1, struct strbuf *base,
const char *pathname, unsigned mode, int stage, void *context) const char *pathname, unsigned mode, int stage, void *context)
{ {
int retval = 0; int retval = 0;
@ -79,7 +79,7 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
*/ */
type = commit_type; type = commit_type;
} else if (S_ISDIR(mode)) { } else if (S_ISDIR(mode)) {
if (show_recursive(base, baselen, pathname)) { if (show_recursive(base->buf, base->len, pathname)) {
retval = READ_TREE_RECURSIVE; retval = READ_TREE_RECURSIVE;
if (!(ls_options & LS_SHOW_TREES)) if (!(ls_options & LS_SHOW_TREES))
return retval; return retval;
@ -90,7 +90,8 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
return 0; return 0;
if (chomp_prefix && if (chomp_prefix &&
(baselen < chomp_prefix || memcmp(ls_tree_prefix, base, chomp_prefix))) (base->len < chomp_prefix ||
memcmp(ls_tree_prefix, base->buf, chomp_prefix)))
return 0; return 0;
if (!(ls_options & LS_NAME_ONLY)) { if (!(ls_options & LS_NAME_ONLY)) {
@ -112,7 +113,7 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
printf("%06o %s %s\t", mode, type, printf("%06o %s %s\t", mode, type,
find_unique_abbrev(sha1, abbrev)); find_unique_abbrev(sha1, abbrev));
} }
write_name_quotedpfx(base + chomp_prefix, baselen - chomp_prefix, write_name_quotedpfx(base->buf + chomp_prefix, base->len - chomp_prefix,
pathname, stdout, line_termination); pathname, stdout, line_termination);
return retval; return retval;
} }

View File

@ -275,23 +275,20 @@ struct tree *write_tree_from_memory(struct merge_options *o)
} }
static int save_files_dirs(const unsigned char *sha1, static int save_files_dirs(const unsigned char *sha1,
const char *base, int baselen, const char *path, struct strbuf *base, const char *path,
unsigned int mode, int stage, void *context) unsigned int mode, int stage, void *context)
{ {
int len = strlen(path); int baselen = base->len;
char *newpath = xmalloc(baselen + len + 1);
struct merge_options *o = context; struct merge_options *o = context;
memcpy(newpath, base, baselen); strbuf_addstr(base, path);
memcpy(newpath + baselen, path, len);
newpath[baselen + len] = '\0';
if (S_ISDIR(mode)) if (S_ISDIR(mode))
string_list_insert(&o->current_directory_set, newpath); string_list_insert(&o->current_directory_set, base->buf);
else else
string_list_insert(&o->current_file_set, newpath); string_list_insert(&o->current_file_set, base->buf);
free(newpath);
strbuf_setlen(base, baselen);
return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0); return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
} }

16
tree.c
View File

@ -30,9 +30,12 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b
return add_cache_entry(ce, opt); return add_cache_entry(ce, opt);
} }
static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) static int read_one_entry(const unsigned char *sha1, struct strbuf *base,
const char *pathname, unsigned mode, int stage,
void *context)
{ {
return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, return read_one_entry_opt(sha1, base->buf, base->len, pathname,
mode, stage,
ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
} }
@ -40,9 +43,12 @@ static int read_one_entry(const unsigned char *sha1, const char *base, int basel
* This is used when the caller knows there is no existing entries at * This is used when the caller knows there is no existing entries at
* the stage that will conflict with the entry being added. * the stage that will conflict with the entry being added.
*/ */
static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) static int read_one_entry_quick(const unsigned char *sha1, struct strbuf *base,
const char *pathname, unsigned mode, int stage,
void *context)
{ {
return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, return read_one_entry_opt(sha1, base->buf, base->len, pathname,
mode, stage,
ADD_CACHE_JUST_APPEND); ADD_CACHE_JUST_APPEND);
} }
@ -70,7 +76,7 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
continue; continue;
} }
switch (fn(entry.sha1, base->buf, base->len, switch (fn(entry.sha1, base,
entry.path, entry.mode, stage, context)) { entry.path, entry.mode, stage, context)) {
case 0: case 0:
continue; continue;

3
tree.h
View File

@ -4,6 +4,7 @@
#include "object.h" #include "object.h"
extern const char *tree_type; extern const char *tree_type;
struct strbuf;
struct tree { struct tree {
struct object object; struct object object;
@ -22,7 +23,7 @@ void free_tree_buffer(struct tree *tree);
struct tree *parse_tree_indirect(const unsigned char *sha1); struct tree *parse_tree_indirect(const unsigned char *sha1);
#define READ_TREE_RECURSIVE 1 #define READ_TREE_RECURSIVE 1
typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int, void *); typedef int (*read_tree_fn_t)(const unsigned char *, struct strbuf *, const char *, unsigned int, int, void *);
extern int read_tree_recursive(struct tree *tree, extern int read_tree_recursive(struct tree *tree,
const char *base, int baselen, const char *base, int baselen,