From 1b0c7174a17de801051402ed35ac085ebd91e88c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 29 Mar 2006 22:55:43 -0800 Subject: tree/diff header cleanup. Introduce tree-walk.[ch] and move "struct tree_desc" and associated functions from various places. Rename DIFF_FILE_CANON_MODE(mode) macro to canon_mode(mode) and move it to cache.h. This macro returns the canonicalized st_mode value in the host byte order for files, symlinks and directories -- to be compared with a tree_desc entry. create_ce_mode(mode) in cache.h is similar but is intended to be used for index entries (so it does not work for directories) and returns the value in the network byte order. Signed-off-by: Junio C Hamano diff --git a/Makefile b/Makefile index d945546..d78298a 100644 --- a/Makefile +++ b/Makefile @@ -193,7 +193,8 @@ XDIFF_LIB=xdiff/lib.a LIB_H = \ blob.h cache.h commit.h csum-file.h delta.h \ diff.h object.h pack.h pkt-line.h quote.h refs.h \ - run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h + run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \ + tree-walk.h DIFF_OBJS = \ diff.o diffcore-break.o diffcore-order.o diffcore-pathspec.o \ @@ -207,7 +208,7 @@ LIB_OBJS = \ quote.o read-cache.o refs.o run-command.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ - fetch-clone.o revision.o pager.o \ + fetch-clone.o revision.o pager.o tree-walk.o \ $(DIFF_OBJS) GITLIBS = $(LIB_FILE) $(XDIFF_LIB) diff --git a/cache.h b/cache.h index 255e6b5..69801b0 100644 --- a/cache.h +++ b/cache.h @@ -106,6 +106,9 @@ static inline unsigned int create_ce_mode(unsigned int mode) return htonl(S_IFLNK); return htonl(S_IFREG | ce_permissions(mode)); } +#define canon_mode(mode) \ + (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ + S_ISLNK(mode) ? S_IFLNK : S_IFDIR) #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7) diff --git a/combine-diff.c b/combine-diff.c index a23894d..f17aab3 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -649,7 +649,7 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent, int len = st.st_size; int cnt = 0; - elem->mode = DIFF_FILE_CANON_MODE(st.st_mode); + elem->mode = canon_mode(st.st_mode); size = len; result = xmalloc(len + 1); while (cnt < len) { diff --git a/diff-files.c b/diff-files.c index b1c05b3..3e7f5f1 100644 --- a/diff-files.c +++ b/diff-files.c @@ -149,7 +149,7 @@ int main(int argc, const char **argv) memcpy(combine.p.parent[stage-2].sha1, nce->sha1, 20); combine.p.parent[stage-2].mode = - DIFF_FILE_CANON_MODE(mode); + canon_mode(mode); combine.p.parent[stage-2].status = DIFF_STATUS_MODIFIED; } @@ -198,7 +198,7 @@ int main(int argc, const char **argv) continue; oldmode = ntohl(ce->ce_mode); - newmode = DIFF_FILE_CANON_MODE(st.st_mode); + newmode = canon_mode(st.st_mode); if (!trust_executable_bit && S_ISREG(newmode) && S_ISREG(oldmode) && ((newmode ^ oldmode) == 0111)) diff --git a/diff.c b/diff.c index 8b37477..e496905 100644 --- a/diff.c +++ b/diff.c @@ -300,7 +300,7 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, unsigned short mode) { if (mode) { - spec->mode = DIFF_FILE_CANON_MODE(mode); + spec->mode = canon_mode(mode); memcpy(spec->sha1, sha1, 20); spec->sha1_valid = !!memcmp(sha1, null_sha1, 20); } diff --git a/diff.h b/diff.h index 8fac465..a268d16 100644 --- a/diff.h +++ b/diff.h @@ -4,17 +4,7 @@ #ifndef DIFF_H #define DIFF_H -#define DIFF_FILE_CANON_MODE(mode) \ - (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ - S_ISLNK(mode) ? S_IFLNK : S_IFDIR) - -struct tree_desc { - void *buf; - unsigned long size; -}; - -extern void update_tree_entry(struct tree_desc *); -extern const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *); +#include "tree-walk.h" struct diff_options; diff --git a/merge-tree.c b/merge-tree.c index 768d83a..50528d5 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -1,51 +1,11 @@ #include "cache.h" -#include "diff.h" +#include "tree-walk.h" static const char merge_tree_usage[] = "git-merge-tree "; static int resolve_directories = 1; static void merge_trees(struct tree_desc t[3], const char *base); -static void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1) -{ - unsigned long size = 0; - void *buf = NULL; - - if (sha1) { - buf = read_object_with_reference(sha1, "tree", &size, NULL); - if (!buf) - die("unable to read tree %s", sha1_to_hex(sha1)); - } - desc->size = size; - desc->buf = buf; - return buf; -} - -struct name_entry { - const unsigned char *sha1; - const char *path; - unsigned int mode; - int pathlen; -}; - -static void entry_clear(struct name_entry *a) -{ - memset(a, 0, sizeof(*a)); -} - -static int entry_compare(struct name_entry *a, struct name_entry *b) -{ - return base_name_compare( - a->path, a->pathlen, a->mode, - b->path, b->pathlen, b->mode); -} - -static void entry_extract(struct tree_desc *t, struct name_entry *a) -{ - a->sha1 = tree_entry_extract(t, &a->path, &a->mode); - a->pathlen = strlen(a->path); -} - /* An empty entry never compares same, not even to another empty entry */ static int same_entry(struct name_entry *a, struct name_entry *b) { @@ -125,60 +85,6 @@ static void unresolved(const char *base, struct name_entry n[3]) printf("3 %06o %s %s%s\n", n[2].mode, sha1_to_hex(n[2].sha1), base, n[2].path); } -typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, const char *base); - -static void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callback_t callback) -{ - struct name_entry *entry = xmalloc(n*sizeof(*entry)); - - for (;;) { - struct name_entry entry[3]; - unsigned long mask = 0; - int i, last; - - last = -1; - for (i = 0; i < n; i++) { - if (!t[i].size) - continue; - entry_extract(t+i, entry+i); - if (last >= 0) { - int cmp = entry_compare(entry+i, entry+last); - - /* - * Is the new name bigger than the old one? - * Ignore it - */ - if (cmp > 0) - continue; - /* - * Is the new name smaller than the old one? - * Ignore all old ones - */ - if (cmp < 0) - mask = 0; - } - mask |= 1ul << i; - last = i; - } - if (!mask) - break; - - /* - * Update the tree entries we've walked, and clear - * all the unused name-entries. - */ - for (i = 0; i < n; i++) { - if (mask & (1ul << i)) { - update_tree_entry(t+i); - continue; - } - entry_clear(entry + i); - } - callback(n, mask, entry, base); - } - free(entry); -} - /* * Merge two trees together (t[1] and t[2]), using a common base (t[0]) * as the origin. diff --git a/pack-objects.c b/pack-objects.c index 49357c6..ccfaa5f 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -3,7 +3,7 @@ #include "delta.h" #include "pack.h" #include "csum-file.h" -#include "diff.h" +#include "tree-walk.h" #include #include diff --git a/rev-list.c b/rev-list.c index f3a989c..ee88f56 100644 --- a/rev-list.c +++ b/rev-list.c @@ -4,7 +4,7 @@ #include "commit.h" #include "tree.h" #include "blob.h" -#include "diff.h" +#include "tree-walk.h" #include "revision.h" /* bits #0-5 in revision.h */ diff --git a/tar-tree.c b/tar-tree.c index 8d9e31c..705b8fa 100644 --- a/tar-tree.c +++ b/tar-tree.c @@ -3,7 +3,7 @@ */ #include #include "cache.h" -#include "diff.h" +#include "tree-walk.h" #include "commit.h" #include "strbuf.h" #include "tar.h" diff --git a/tree-diff.c b/tree-diff.c index d978428..7bb6109 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -9,34 +9,6 @@ static int nr_paths = 0; static const char **paths = NULL; static int *pathlens = NULL; -void update_tree_entry(struct tree_desc *desc) -{ - void *buf = desc->buf; - unsigned long size = desc->size; - int len = strlen(buf) + 1 + 20; - - if (size < len) - die("corrupt tree file"); - desc->buf = buf + len; - desc->size = size - len; -} - -const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep) -{ - void *tree = desc->buf; - unsigned long size = desc->size; - int len = strlen(tree)+1; - const unsigned char *sha1 = tree + len; - const char *path = strchr(tree, ' '); - unsigned int mode; - - if (!path || size < len + 20 || sscanf(tree, "%o", &mode) != 1) - die("corrupt tree file"); - *pathp = path+1; - *modep = DIFF_FILE_CANON_MODE(mode); - return sha1; -} - static char *malloc_base(const char *base, const char *path, int pathlen) { int baselen = strlen(base); diff --git a/tree-walk.c b/tree-walk.c new file mode 100644 index 0000000..0735f40 --- /dev/null +++ b/tree-walk.c @@ -0,0 +1,116 @@ +#include "cache.h" +#include "tree-walk.h" + +void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1) +{ + unsigned long size = 0; + void *buf = NULL; + + if (sha1) { + buf = read_object_with_reference(sha1, "tree", &size, NULL); + if (!buf) + die("unable to read tree %s", sha1_to_hex(sha1)); + } + desc->size = size; + desc->buf = buf; + return buf; +} + +static int entry_compare(struct name_entry *a, struct name_entry *b) +{ + return base_name_compare( + a->path, a->pathlen, a->mode, + b->path, b->pathlen, b->mode); +} + +static void entry_clear(struct name_entry *a) +{ + memset(a, 0, sizeof(*a)); +} + +static void entry_extract(struct tree_desc *t, struct name_entry *a) +{ + a->sha1 = tree_entry_extract(t, &a->path, &a->mode); + a->pathlen = strlen(a->path); +} + +void update_tree_entry(struct tree_desc *desc) +{ + void *buf = desc->buf; + unsigned long size = desc->size; + int len = strlen(buf) + 1 + 20; + + if (size < len) + die("corrupt tree file"); + desc->buf = buf + len; + desc->size = size - len; +} + +const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep) +{ + void *tree = desc->buf; + unsigned long size = desc->size; + int len = strlen(tree)+1; + const unsigned char *sha1 = tree + len; + const char *path = strchr(tree, ' '); + unsigned int mode; + + if (!path || size < len + 20 || sscanf(tree, "%o", &mode) != 1) + die("corrupt tree file"); + *pathp = path+1; + *modep = canon_mode(mode); + return sha1; +} + +void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callback_t callback) +{ + struct name_entry *entry = xmalloc(n*sizeof(*entry)); + + for (;;) { + struct name_entry entry[3]; + unsigned long mask = 0; + int i, last; + + last = -1; + for (i = 0; i < n; i++) { + if (!t[i].size) + continue; + entry_extract(t+i, entry+i); + if (last >= 0) { + int cmp = entry_compare(entry+i, entry+last); + + /* + * Is the new name bigger than the old one? + * Ignore it + */ + if (cmp > 0) + continue; + /* + * Is the new name smaller than the old one? + * Ignore all old ones + */ + if (cmp < 0) + mask = 0; + } + mask |= 1ul << i; + last = i; + } + if (!mask) + break; + + /* + * Update the tree entries we've walked, and clear + * all the unused name-entries. + */ + for (i = 0; i < n; i++) { + if (mask & (1ul << i)) { + update_tree_entry(t+i); + continue; + } + entry_clear(entry + i); + } + callback(n, mask, entry, base); + } + free(entry); +} + diff --git a/tree-walk.h b/tree-walk.h new file mode 100644 index 0000000..76893e3 --- /dev/null +++ b/tree-walk.h @@ -0,0 +1,25 @@ +#ifndef TREE_WALK_H +#define TREE_WALK_H + +struct tree_desc { + void *buf; + unsigned long size; +}; + +struct name_entry { + const unsigned char *sha1; + const char *path; + unsigned int mode; + int pathlen; +}; + +void update_tree_entry(struct tree_desc *); +const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *); + +void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1); + +typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, const char *base); + +void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callback_t callback); + +#endif -- cgit v0.10.2-6-g49f6