summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--cache.h3
-rw-r--r--combine-diff.c2
-rw-r--r--diff-files.c4
-rw-r--r--diff.c2
-rw-r--r--diff.h12
-rw-r--r--merge-tree.c96
-rw-r--r--pack-objects.c2
-rw-r--r--rev-list.c2
-rw-r--r--tar-tree.c2
-rw-r--r--tree-diff.c28
-rw-r--r--tree-walk.c116
-rw-r--r--tree-walk.h25
13 files changed, 156 insertions, 143 deletions
diff --git a/Makefile b/Makefile
index d945546eb8..d78298ae62 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 255e6b5cc7..69801b02d5 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 a23894d869..f17aab33f1 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 b1c05b325a..3e7f5f105b 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 8b37477afc..e496905bad 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 8fac465a9d..a268d16ff7 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 768d83a7c2..50528d5e43 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 <base-tree> <branch1> <branch2>";
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 49357c6735..ccfaa5f609 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 <sys/time.h>
#include <signal.h>
diff --git a/rev-list.c b/rev-list.c
index f3a989cced..ee88f567a7 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 8d9e31c206..705b8fa1c7 100644
--- a/tar-tree.c
+++ b/tar-tree.c
@@ -3,7 +3,7 @@
*/
#include <time.h>
#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 d978428910..7bb6109111 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 0000000000..0735f4046d
--- /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 0000000000..76893e36c3
--- /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