* Re: Darcs-git: a few notes for Git hackers
[not found] ` <Pine.LNX.4.44.0505141851340.2136-200000@bellevue.puremagic.com>
@ 2005-05-15 9:11 ` Brad Roberts
2005-05-15 11:48 ` Petr Baudis
1 sibling, 0 replies; 21+ messages in thread
From: Brad Roberts @ 2005-05-15 9:11 UTC (permalink / raw)
To: git, Petr Baudis; +Cc: Juliusz Chroboczek
[-- Attachment #1: Type: TEXT/PLAIN, Size: 2652 bytes --]
Resending, I left off the mailing list on the to list last time.
> > I wasn't able to finish redoing these against linus tip, but I got most of
> > it done (patches 1-14 of the original 19):
> >
> > http://gameboy2.puremagic.com:8090/
> > rsync://gameboy2.puremagic.com/git/
> >
> > The second, third, and forth to last changes need a careful review,
> > they're direct applications of the original patches which were lightly
> > tested during the first round and nothing other than compile tested in
> > this round.
> >
> > I suspect the remaining parts of the original patch series will go in
> > fairly smoothly. If no one gets to them before tonight I'll finish
> > it up after work.
> >
> > Later,
> > Brad
>
> I've completed the re-merge, and moved to tip of git-pb.git rather than
> tip of git.git. Unfortunatly that merge was also somewhat intrusive and
> my individual diffs along the way are somewhat useless now. The entire
> history is available about the above locations still. Attached is the
> full diff vs git-pb @ 902b92e00e491a60d55c4b2bce122903b8347f34.
>
> The unit tests that are being added are a wonderful thing, thanks so much
> for doing them Junio.
>
> These changes feel rough to me still. Some areas to discuss / think
> about:
>
> 1) The hunks that change the merge routines from pointer based to index
> based could have been left much less intruded upon by adding a
> get_cache_entry_array(cache) api.
>
> 2) Should the index changing areas be constructing a new index instead of
> shuffling bits within the current index?
>
> 3) The vocabulary and code is inconsistent between cache and index.
>
> 4) read-cache.c does much more than reading.
>
> 5) Like before, cleaning up memory for the cache is a rarity, preferring
> to let the end of the process garbage collect everything.
>
> cache.h | 52 ++++++-------
> check-files.c | 12 +--
> checkout-cache.c | 26 +++---
> diff-cache.c | 60 ++++++++-------
> diff-files.c | 31 ++++---
> diff-helper.c | 6 -
> diff-tree.c | 50 ++++++------
> diff.c | 36 +++++----
> diff.h | 11 +-
> fsck-cache.c | 6 -
> local-pull.c | 2
> ls-files.c | 47 ++++++-----
> merge-cache.c | 29 +++----
> read-cache.c | 217 ++++++++++++++++++++++++++++++++++---------------------
> read-tree.c | 65 +++++++++-------
> sha1_file.c | 4 -
> tree.c | 15 ++-
> update-cache.c | 45 +++++------
> write-tree.c | 29 ++++---
> 19 files changed, 416 insertions(+), 327 deletions(-)
>
> Signed-off-by: Brad Roberts <braddr@puremagic.com>
>
>
[-- Attachment #2: diff-vs-git-pb --]
[-- Type: TEXT/PLAIN, Size: 63306 bytes --]
Index: cache.h
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/cache.h (mode:100644)
+++ uncommitted/cache.h (mode:100644)
@@ -40,19 +40,8 @@
/*
* Basic data structures for the directory cache
- *
- * NOTE NOTE NOTE! This is all in the native CPU byte format. It's
- * not even trying to be portable. It's trying to be efficient. It's
- * just a cache, after all.
*/
-#define CACHE_SIGNATURE 0x44495243 /* "DIRC" */
-struct cache_header {
- unsigned int hdr_signature;
- unsigned int hdr_version;
- unsigned int hdr_entries;
-};
-
/*
* The "cache_time" is just the low 32 bits of the
* time. It doesn't matter if it overflows - we only
@@ -89,6 +78,9 @@
#define CE_STAGEMASK (0x3000)
#define CE_STAGESHIFT 12
+extern int ce_match_stat(struct cache_entry *ce, struct stat *st);
+extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
+
#define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT))
#define ce_namelen(ce) (CE_NAMEMASK & ntohs((ce)->ce_flags))
#define ce_size(ce) cache_entry_size(ce_namelen(ce))
@@ -104,9 +96,6 @@
#define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)
-extern struct cache_entry **active_cache;
-extern unsigned int active_nr, active_alloc, active_cache_changed;
-
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
@@ -120,17 +109,19 @@
#define alloc_nr(x) (((x)+16)*3/2)
/* Initialize and use the cache information */
-extern int read_cache(void);
-extern int write_cache(int newfd, struct cache_entry **cache, int entries);
-extern int cache_name_pos(const char *name, int namelen);
+extern struct cache *new_cache(void);
+extern struct cache *read_cache(void);
+extern int write_cache(struct cache *cache, int newfd);
+extern void free_cache(struct cache *cache);
+extern int cache_name_pos(struct cache *cache, const char *name, int namelen);
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
-extern int add_cache_entry(struct cache_entry *ce, int option);
-extern int remove_entry_at(int pos);
-extern int remove_file_from_cache(char *path);
-extern int same_name(struct cache_entry *a, struct cache_entry *b);
-extern int cache_match_stat(struct cache_entry *ce, struct stat *st);
-extern int index_fd(unsigned char *sha1, int fd, struct stat *st);
+extern int add_cache_entry(struct cache *cache, struct cache_entry *ce, int option);
+extern int remove_file_from_cache(struct cache *cache, char *path);
+extern int get_num_cache_entries(struct cache *cache);
+extern struct cache_entry *get_cache_entry(struct cache *cache, int pos);
+extern void set_cache_entry(struct cache *cache, struct cache_entry *ce, int pos);
+extern int remove_cache_entry_at(struct cache *cache, int pos);
#define MTIME_CHANGED 0x0001
#define CTIME_CHANGED 0x0002
@@ -148,11 +139,12 @@
extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);
extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
extern int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned char *return_sha1);
+extern int index_fd(unsigned char *sha1, int fd, struct stat *st);
extern int check_sha1_signature(unsigned char *sha1, void *buf, unsigned long size, const char *type);
/* Read a tree into the cache */
-extern int read_tree(void *buffer, unsigned long size, int stage);
+extern int read_tree(struct cache *cache, void *buffer, unsigned long size, int stage);
extern int write_sha1_from_fd(const unsigned char *sha1, int fd);
@@ -179,7 +171,7 @@
void parse_date(char *date, char *buf, int bufsize);
void datestamp(char *buf, int bufsize);
-static inline void *xmalloc(int size)
+static inline void *xmalloc(size_t size)
{
void *ret = malloc(size);
if (!ret)
@@ -187,7 +179,7 @@
return ret;
}
-static inline void *xrealloc(void *ptr, int size)
+static inline void *xrealloc(void *ptr, size_t size)
{
void *ret = realloc(ptr, size);
if (!ret)
@@ -195,4 +187,12 @@
return ret;
}
+static inline void *xcalloc(size_t nmemb, size_t size)
+{
+ void *ret = calloc(nmemb, size);
+ if (!ret)
+ die("Out of memory, calloc failed");
+ return ret;
+}
+
#endif /* CACHE_H */
Index: check-files.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/check-files.c (mode:100644)
+++ uncommitted/check-files.c (mode:100644)
@@ -8,7 +8,7 @@
*/
#include "cache.h"
-static void check_file(const char *path)
+static void check_file(struct cache *cache, const char *path)
{
int fd = open(path, O_RDONLY);
struct cache_entry *ce;
@@ -23,15 +23,15 @@
}
/* Exists but is not in the cache is not fine */
- pos = cache_name_pos(path, strlen(path));
+ pos = cache_name_pos(cache, path, strlen(path));
if (pos < 0)
die("preparing to update existing file '%s' not in cache", path);
- ce = active_cache[pos];
+ ce = get_cache_entry(cache, pos);
if (lstat(path, &st) < 0)
die("lstat(%s): %s", path, strerror(errno));
- changed = cache_match_stat(ce, &st);
+ changed = ce_match_stat(ce, &st);
if (changed)
die("preparing to update file '%s' not uptodate in cache", path);
}
@@ -39,9 +39,9 @@
int main(int argc, char **argv)
{
int i;
+ struct cache *cache = read_cache();
- read_cache();
for (i = 1; i < argc ; i++)
- check_file(argv[i]);
+ check_file(cache, argv[i]);
return 0;
}
Index: checkout-cache.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/checkout-cache.c (mode:100644)
+++ uncommitted/checkout-cache.c (mode:100644)
@@ -167,7 +167,7 @@
strcpy(path + len, ce->name);
if (!lstat(path, &st)) {
- unsigned changed = cache_match_stat(ce, &st);
+ unsigned changed = ce_match_stat(ce, &st);
if (!changed)
return 0;
if (!force) {
@@ -188,30 +188,30 @@
return write_entry(ce, path);
}
-static int checkout_file(const char *name, const char *base_dir)
+static int checkout_file(struct cache *cache, const char *name, const char *base_dir)
{
- int pos = cache_name_pos(name, strlen(name));
+ int pos = cache_name_pos(cache, name, strlen(name));
if (pos < 0) {
if (!quiet) {
pos = -pos - 1;
fprintf(stderr,
"checkout-cache: %s is %s.\n",
name,
- (pos < active_nr &&
- !strcmp(active_cache[pos]->name, name)) ?
+ (pos < get_num_cache_entries(cache) &&
+ !strcmp(get_cache_entry(cache, pos)->name, name)) ?
"unmerged" : "not in the cache");
}
return -1;
}
- return checkout_entry(active_cache[pos], base_dir);
+ return checkout_entry(get_cache_entry(cache, pos), base_dir);
}
-static int checkout_all(const char *base_dir)
+static int checkout_all(struct cache *cache, const char *base_dir)
{
int i;
- for (i = 0; i < active_nr ; i++) {
- struct cache_entry *ce = active_cache[i];
+ for (i = 0; i < get_num_cache_entries(cache) ; i++) {
+ struct cache_entry *ce = get_cache_entry(cache, i);
if (ce_stage(ce))
continue;
if (checkout_entry(ce, base_dir) < 0)
@@ -225,15 +225,15 @@
int i, force_filename = 0;
const char *base_dir = "";
- if (read_cache() < 0) {
+ struct cache *cache = read_cache();
+ if (!cache)
die("invalid cache");
- }
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!force_filename) {
if (!strcmp(arg, "-a")) {
- checkout_all(base_dir);
+ checkout_all(cache, base_dir);
continue;
}
if (!strcmp(arg, "--")) {
@@ -257,7 +257,7 @@
continue;
}
}
- checkout_file(arg, base_dir);
+ checkout_file(cache, arg, base_dir);
}
return 0;
}
Index: diff-cache.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff-cache.c (mode:100644)
+++ uncommitted/diff-cache.c (mode:100644)
@@ -7,10 +7,10 @@
static int line_termination = '\n';
/* A file entry went away or appeared */
-static void show_file(const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode)
+static void show_file(struct cache *cache, const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode)
{
if (generate_patch)
- diff_addremove(prefix[0], ntohl(mode), sha1, ce->name, NULL);
+ diff_addremove(cache, prefix[0], ntohl(mode), sha1, ce->name, NULL);
else
printf("%s%06o\tblob\t%s\t%s%c", prefix, ntohl(mode),
sha1_to_hex(sha1), ce->name, line_termination);
@@ -33,7 +33,7 @@
}
return -1;
}
- changed = cache_match_stat(ce, &st);
+ changed = ce_match_stat(ce, &st);
if (changed) {
mode = create_ce_mode(st.st_mode);
sha1 = no_sha1;
@@ -45,7 +45,7 @@
return 0;
}
-static void show_new_file(struct cache_entry *new)
+static void show_new_file(struct cache *cache, struct cache_entry *new)
{
unsigned char *sha1;
unsigned int mode;
@@ -54,10 +54,11 @@
if (get_stat_data(new, &sha1, &mode) < 0)
return;
- show_file("+", new, sha1, mode);
+ show_file(cache, "+", new, sha1, mode);
}
-static int show_modified(struct cache_entry *old,
+static int show_modified(struct cache *cache,
+ struct cache_entry *old,
struct cache_entry *new,
int report_missing)
{
@@ -67,7 +68,7 @@
if (get_stat_data(new, &sha1, &mode) < 0) {
if (report_missing)
- show_file("-", old, old->sha1, old->ce_mode);
+ show_file(cache, "-", old, old->sha1, old->ce_mode);
return -1;
}
@@ -79,7 +80,7 @@
oldmode = ntohl(oldmode);
if (generate_patch)
- diff_change(oldmode, mode,
+ diff_change(cache, oldmode, mode,
old->sha1, sha1, old->name, NULL);
else {
strcpy(old_sha1_hex, sha1_to_hex(old->sha1));
@@ -90,30 +91,34 @@
return 0;
}
-static int diff_cache(struct cache_entry **ac, int entries)
+static int diff_cache(struct cache *cache)
{
- while (entries) {
- struct cache_entry *ce = *ac;
- int same = (entries > 1) && same_name(ce, ac[1]);
+ int pos = 0, num = get_num_cache_entries(cache);
+
+ while (pos < num) {
+ struct cache_entry *ce = get_cache_entry(cache, pos);
+ struct cache_entry *ce_next = ((pos+1) < num) ?
+ get_cache_entry(cache, pos+1) : NULL;
+ int same = ce_next && ce_same_name(ce, ce_next);
switch (ce_stage(ce)) {
case 0:
/* No stage 1 entry? That means it's a new file */
if (!same) {
- show_new_file(ce);
+ show_new_file(cache, ce);
break;
}
/* Show difference between old and new */
- show_modified(ac[1], ce, 1);
+ show_modified(cache, ce_next, ce, 1);
break;
case 1:
/* No stage 3 (merge) entry? That means it's been deleted */
if (!same) {
- show_file("-", ce, ce->sha1, ce->ce_mode);
+ show_file(cache, "-", ce, ce->sha1, ce->ce_mode);
break;
}
/* We come here with ce pointing at stage 1
- * (original tree) and ac[1] pointing at stage
+ * (original tree) and ce_next pointing at stage
* 3 (unmerged). show-modified with
* report-mising set to false does not say the
* file is deleted but reports true if work
@@ -122,12 +127,12 @@
* Otherwise, we show the differences between
* the original tree and the work tree.
*/
- if (!cached_only && !show_modified(ce, ac[1], 0))
+ if (!cached_only && !show_modified(cache, ce, ce_next, 0))
break;
/* fallthru */
case 3:
if (generate_patch)
- diff_unmerge(ce->name);
+ diff_unmerge(cache, ce->name);
else
printf("U %s%c", ce->name, line_termination);
break;
@@ -141,9 +146,8 @@
* we've handled the relevant cases now.
*/
do {
- ac++;
- entries--;
- } while (entries && same_name(ce, ac[0]));
+ pos++;
+ } while (pos < num && ce_same_name(ce, get_cache_entry(cache, pos)));
}
return 0;
}
@@ -153,11 +157,11 @@
* when we read in the new tree (into "stage 1"), we won't lose sight
* of the fact that we had unmerged entries.
*/
-static void mark_merge_entries(void)
+static void mark_merge_entries(struct cache *cache)
{
int i;
- for (i = 0; i < active_nr; i++) {
- struct cache_entry *ce = active_cache[i];
+ for (i = 0; i < get_num_cache_entries(cache); i++) {
+ struct cache_entry *ce = get_cache_entry(cache, i);
if (!ce_stage(ce))
continue;
ce->ce_flags |= htons(CE_STAGEMASK);
@@ -172,8 +176,8 @@
unsigned char tree_sha1[20];
void *tree;
unsigned long size;
+ struct cache * cache = read_cache();
- read_cache();
while (argc > 2) {
char *arg = argv[1];
argv++;
@@ -204,13 +208,13 @@
if (argc != 2 || get_sha1(argv[1], tree_sha1))
usage(diff_cache_usage);
- mark_merge_entries();
+ mark_merge_entries(cache);
tree = read_object_with_reference(tree_sha1, "tree", &size, 0);
if (!tree)
die("bad tree object %s", argv[1]);
- if (read_tree(tree, size, 1))
+ if (read_tree(cache, tree, size, 1))
die("unable to read tree object %s", argv[1]);
- return diff_cache(active_cache, active_nr);
+ return diff_cache(cache);
}
Index: diff-files.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff-files.c (mode:100644)
+++ uncommitted/diff-files.c (mode:100644)
@@ -28,18 +28,18 @@
return 0;
}
-static void show_unmerge(const char *path)
+static void show_unmerge(struct cache *cache, const char *path)
{
if (generate_patch)
- diff_unmerge(path);
+ diff_unmerge(cache, path);
else
printf("U %s%c", path, line_termination);
}
-static void show_file(int pfx, struct cache_entry *ce)
+static void show_file(struct cache *cache, int pfx, struct cache_entry *ce)
{
if (generate_patch)
- diff_addremove(pfx, ntohl(ce->ce_mode), ce->sha1,
+ diff_addremove(cache, pfx, ntohl(ce->ce_mode), ce->sha1,
ce->name, NULL);
else
printf("%c%06o\t%s\t%s\t%s%c",
@@ -47,7 +47,7 @@
sha1_to_hex(ce->sha1), ce->name, line_termination);
}
-static void show_modified(int oldmode, int mode,
+static void show_modified(struct cache *cache, int oldmode, int mode,
const char *old_sha1, const char *sha1,
char *path)
{
@@ -55,7 +55,7 @@
strcpy(old_sha1_hex, sha1_to_hex(old_sha1));
if (generate_patch)
- diff_change(oldmode, mode, old_sha1, sha1, path, NULL);
+ diff_change(cache, oldmode, mode, old_sha1, sha1, path, NULL);
else
printf("*%06o->%06o\tblob\t%s->%s\t%s%c",
oldmode, mode, old_sha1_hex, sha1_to_hex(sha1), path,
@@ -65,7 +65,8 @@
int main(int argc, char **argv)
{
static const char null_sha1[20] = { 0, };
- int entries = read_cache();
+ struct cache *cache = read_cache();
+ int entries;
int i;
while (1 < argc && argv[1][0] == '-') {
@@ -87,15 +88,17 @@
/* At this point, if argc == 1, then we are doing everything.
* Otherwise argv[1] .. argv[argc-1] have the explicit paths.
*/
- if (entries < 0) {
+ if (!cache) {
perror("read_cache");
exit(1);
}
+ entries = get_num_cache_entries(cache);
+
for (i = 0; i < entries; i++) {
struct stat st;
unsigned int oldmode, mode;
- struct cache_entry *ce = active_cache[i];
+ struct cache_entry *ce = get_cache_entry(cache, i);
int changed;
if (1 < argc &&
@@ -103,9 +106,9 @@
continue;
if (ce_stage(ce)) {
- show_unmerge(ce->name);
+ show_unmerge(cache, ce->name);
while (i < entries &&
- !strcmp(ce->name, active_cache[i]->name))
+ !strcmp(ce->name, get_cache_entry(cache, i)->name))
i++;
i--; /* compensate for loop control increments */
continue;
@@ -118,10 +121,10 @@
}
if (silent)
continue;
- show_file('-', ce);
+ show_file(cache, '-', ce);
continue;
}
- changed = cache_match_stat(ce, &st);
+ changed = ce_match_stat(ce, &st);
if (!changed)
continue;
@@ -129,7 +132,7 @@
mode = (S_ISLNK(st.st_mode) ? S_IFLNK :
S_IFREG | ce_permissions(st.st_mode));
- show_modified(oldmode, mode, ce->sha1, null_sha1,
+ show_modified(cache, oldmode, mode, ce->sha1, null_sha1,
ce->name);
}
return 0;
Index: diff-helper.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff-helper.c (mode:100644)
+++ uncommitted/diff-helper.c (mode:100644)
@@ -56,7 +56,7 @@
switch (*cp++) {
case 'U':
if (!cnt || matches_pathspec(cp + 1, spec, cnt))
- diff_unmerge(cp + 1);
+ diff_unmerge(NULL, cp + 1);
return 0;
case '+':
old.file_valid = 0;
@@ -102,9 +102,9 @@
}
if (!cnt || matches_pathspec(path, spec, cnt)) {
if (reverse)
- run_external_diff(path, &new, &old);
+ run_external_diff(NULL, path, &new, &old);
else
- run_external_diff(path, &old, &new);
+ run_external_diff(NULL, path, &old, &new);
}
return 0;
}
Index: diff-tree.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff-tree.c (mode:100644)
+++ uncommitted/diff-tree.c (mode:100644)
@@ -17,7 +17,7 @@
static char **paths = NULL;
static int *pathlens = NULL;
-static int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base);
+static int diff_tree_sha1(struct cache *cache, const unsigned char *old, const unsigned char *new, const char *base);
static void update_tree_entry(void **bufp, unsigned long *sizep)
{
@@ -53,19 +53,19 @@
return newbase;
}
-static void show_file(const char *prefix, void *tree, unsigned long size, const char *base);
+static void show_file(struct cache *cache, const char *prefix, void *tree, unsigned long size, const char *base);
/* A whole sub-tree went away or appeared */
-static void show_tree(const char *prefix, void *tree, unsigned long size, const char *base)
+static void show_tree(struct cache *cache, const char *prefix, void *tree, unsigned long size, const char *base)
{
while (size) {
- show_file(prefix, tree, size, base);
+ show_file(cache, prefix, tree, size, base);
update_tree_entry(&tree, &size);
}
}
/* A file entry went away or appeared */
-static void show_file(const char *prefix, void *tree, unsigned long size, const char *base)
+static void show_file(struct cache *cache, const char *prefix, void *tree, unsigned long size, const char *base)
{
unsigned mode;
const char *path;
@@ -89,7 +89,7 @@
if (!tree || strcmp(type, "tree"))
die("corrupt tree sha %s", sha1_to_hex(sha1));
- show_tree(prefix, tree, size, newbase);
+ show_tree(cache, prefix, tree, size, newbase);
free(tree);
free(newbase);
@@ -98,7 +98,7 @@
if (generate_patch) {
if (!S_ISDIR(mode))
- diff_addremove(prefix[0], mode, sha1, base, path);
+ diff_addremove(cache, prefix[0], mode, sha1, base, path);
}
else
printf("%s%06o\t%s\t%s\t%s%s%c", prefix, mode,
@@ -107,7 +107,7 @@
line_termination);
}
-static int compare_tree_entry(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)
+static int compare_tree_entry(struct cache *cache, void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)
{
unsigned mode1, mode2;
const char *path1, *path2;
@@ -122,11 +122,11 @@
pathlen2 = strlen(path2);
cmp = cache_name_compare(path1, pathlen1, path2, pathlen2);
if (cmp < 0) {
- show_file("-", tree1, size1, base);
+ show_file(cache, "-", tree1, size1, base);
return -1;
}
if (cmp > 0) {
- show_file("+", tree2, size2, base);
+ show_file(cache, "+", tree2, size2, base);
return 1;
}
if (!memcmp(sha1, sha2, 20) && mode1 == mode2)
@@ -137,15 +137,15 @@
* file, we need to consider it a remove and an add.
*/
if (S_ISDIR(mode1) != S_ISDIR(mode2)) {
- show_file("-", tree1, size1, base);
- show_file("+", tree2, size2, base);
+ show_file(cache, "-", tree1, size1, base);
+ show_file(cache, "+", tree2, size2, base);
return 0;
}
if (recursive && S_ISDIR(mode1)) {
int retval;
char *newbase = malloc_base(base, path1, pathlen1);
- retval = diff_tree_sha1(sha1, sha2, newbase);
+ retval = diff_tree_sha1(cache, sha1, sha2, newbase);
free(newbase);
return retval;
}
@@ -159,7 +159,7 @@
if (generate_patch) {
if (!S_ISDIR(mode1))
- diff_change(mode1, mode2, sha1, sha2, base, path1);
+ diff_change(cache, mode1, mode2, sha1, sha2, base, path1);
}
else {
strcpy(old_sha1_hex, sha1_to_hex(sha1));
@@ -217,7 +217,7 @@
return 0; /* No matches */
}
-static int diff_tree(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)
+static int diff_tree(struct cache *cache, void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)
{
while (size1 | size2) {
if (nr_paths && size1 && !interesting(tree1, size1, base)) {
@@ -229,16 +229,16 @@
continue;
}
if (!size1) {
- show_file("+", tree2, size2, base);
+ show_file(cache, "+", tree2, size2, base);
update_tree_entry(&tree2, &size2);
continue;
}
if (!size2) {
- show_file("-", tree1, size1, base);
+ show_file(cache, "-", tree1, size1, base);
update_tree_entry(&tree1, &size1);
continue;
}
- switch (compare_tree_entry(tree1, size1, tree2, size2, base)) {
+ switch (compare_tree_entry(cache, tree1, size1, tree2, size2, base)) {
case -1:
update_tree_entry(&tree1, &size1);
continue;
@@ -254,7 +254,7 @@
return 0;
}
-static int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base)
+static int diff_tree_sha1(struct cache *cache, const unsigned char *old, const unsigned char *new, const char *base)
{
void *tree1, *tree2;
unsigned long size1, size2;
@@ -266,7 +266,7 @@
tree2 = read_object_with_reference(new, "tree", &size2, 0);
if (!tree2)
die("unable to read destination tree (%s)", sha1_to_hex(new));
- retval = diff_tree(tree1, size1, tree2, size2, base);
+ retval = diff_tree(cache, tree1, size1, tree2, size2, base);
free(tree1);
free(tree2);
return retval;
@@ -342,7 +342,7 @@
return this_header;
}
-static int diff_tree_stdin(char *line)
+static int diff_tree_stdin(struct cache *cache, char *line)
{
int len = strlen(line);
unsigned char commit[20], parent[20];
@@ -360,7 +360,7 @@
line[81] = 0;
sprintf(this_header, "%s (from %s)\n", line, line+41);
header = this_header;
- return diff_tree_sha1(parent, commit, "");
+ return diff_tree_sha1(cache, parent, commit, "");
}
buf = read_object_with_reference(commit, "commit", &size, NULL);
if (!buf)
@@ -378,7 +378,7 @@
if (get_sha1_hex(buf + offset + 7, parent))
return -1;
header = generate_header(line, sha1_to_hex(parent), buf, size);
- diff_tree_sha1(parent, commit, "");
+ diff_tree_sha1(cache, parent, commit, "");
if (!header && verbose_header)
header_prefix = "\ndiff-tree ";
offset += 48;
@@ -458,10 +458,10 @@
}
if (!read_stdin)
- return diff_tree_sha1(old, new, "");
+ return diff_tree_sha1(NULL, old, new, "");
while (fgets(line, sizeof(line), stdin))
- diff_tree_stdin(line);
+ diff_tree_stdin(NULL, line);
return 0;
}
Index: diff.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff.c (mode:100644)
+++ uncommitted/diff.c (mode:100644)
@@ -147,7 +147,7 @@
* the work tree has that object contents, return true, so that
* prepare_temp_file() does not have to inflate and extract.
*/
-static int work_tree_matches(const char *name, const unsigned char *sha1)
+static int work_tree_matches(struct cache *cache, const char *name, const unsigned char *sha1)
{
struct cache_entry *ce;
struct stat st;
@@ -165,17 +165,17 @@
* by diff-cache --cached, which does read the cache before
* calling us.
*/
- if (!active_cache)
+ if (!get_num_cache_entries(cache))
return 0;
len = strlen(name);
- pos = cache_name_pos(name, len);
+ pos = cache_name_pos(cache, name, len);
if (pos < 0)
return 0;
- ce = active_cache[pos];
+ ce = get_cache_entry(cache, pos);
if ((lstat(name, &st) < 0) ||
!S_ISREG(st.st_mode) ||
- cache_match_stat(ce, &st) ||
+ ce_match_stat(ce, &st) ||
memcmp(sha1, ce->sha1, 20))
return 0;
return 1;
@@ -202,7 +202,8 @@
sprintf(temp->mode, "%06o", mode);
}
-static void prepare_temp_file(const char *name,
+static void prepare_temp_file(struct cache *cache,
+ const char *name,
struct diff_tempfile *temp,
struct diff_spec *one)
{
@@ -222,7 +223,7 @@
if (one->sha1_valid &&
(!memcmp(one->blob_sha1, null_sha1, sizeof(null_sha1)) ||
- work_tree_matches(name, one->blob_sha1)))
+ work_tree_matches(cache, name, one->blob_sha1)))
use_work_tree = 1;
if (!one->sha1_valid || use_work_tree) {
@@ -293,7 +294,8 @@
* infile2 infile2-sha1 infile2-mode.
*
*/
-void run_external_diff(const char *name,
+void run_external_diff(struct cache *cache,
+ const char *name,
struct diff_spec *one,
struct diff_spec *two)
{
@@ -303,8 +305,8 @@
static int atexit_asked = 0;
if (one && two) {
- prepare_temp_file(name, &temp[0], one);
- prepare_temp_file(name, &temp[1], two);
+ prepare_temp_file(cache, name, &temp[0], one);
+ prepare_temp_file(cache, name, &temp[1], two);
if (! atexit_asked &&
(temp[0].name == temp[0].tmp_path ||
temp[1].name == temp[1].tmp_path)) {
@@ -357,7 +359,8 @@
remove_tempfile();
}
-void diff_addremove(int addremove, unsigned mode,
+void diff_addremove(struct cache *cache,
+ int addremove, unsigned mode,
const unsigned char *sha1,
const char *base, const char *path)
{
@@ -379,10 +382,11 @@
strcpy(concatpath, base);
strcat(concatpath, path);
}
- run_external_diff(path ? concatpath : base, one, two);
+ run_external_diff(cache, path ? concatpath : base, one, two);
}
-void diff_change(unsigned old_mode, unsigned new_mode,
+void diff_change(struct cache *cache,
+ unsigned old_mode, unsigned new_mode,
const unsigned char *old_sha1,
const unsigned char *new_sha1,
const char *base, const char *path) {
@@ -400,10 +404,10 @@
strcpy(concatpath, base);
strcat(concatpath, path);
}
- run_external_diff(path ? concatpath : base, &spec[0], &spec[1]);
+ run_external_diff(cache, path ? concatpath : base, &spec[0], &spec[1]);
}
-void diff_unmerge(const char *path)
+void diff_unmerge(struct cache *cache, const char *path)
{
- run_external_diff(path, NULL, NULL);
+ run_external_diff(cache, path, NULL, NULL);
}
Index: diff.h
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/diff.h (mode:100644)
+++ uncommitted/diff.h (mode:100644)
@@ -4,18 +4,20 @@
#ifndef DIFF_H
#define DIFF_H
-extern void diff_addremove(int addremove,
+extern void diff_addremove(struct cache *cache,
+ int addremove,
unsigned mode,
const unsigned char *sha1,
const char *base,
const char *path);
-extern void diff_change(unsigned mode1, unsigned mode2,
+extern void diff_change(struct cache *cache,
+ unsigned mode1, unsigned mode2,
const unsigned char *sha1,
const unsigned char *sha2,
const char *base, const char *path);
-extern void diff_unmerge(const char *path);
+extern void diff_unmerge(struct cache *cache, const char *path);
/* These are for diff-helper */
@@ -31,7 +33,8 @@
unsigned file_valid : 1; /* if false the file does not even exist */
};
-extern void run_external_diff(const char *name,
+extern void run_external_diff(struct cache *cache,
+ const char *name,
struct diff_spec *, struct diff_spec *);
#endif /* DIFF_H */
Index: fsck-cache.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/fsck-cache.c (mode:100644)
+++ uncommitted/fsck-cache.c (mode:100644)
@@ -356,9 +356,9 @@
if (keep_cache_objects) {
int i;
- read_cache();
- for (i = 0; i < active_nr; i++) {
- struct blob *blob = lookup_blob(active_cache[i]->sha1);
+ struct cache *cache = read_cache();
+ for (i = 0; i < get_num_cache_entries(cache); i++) {
+ struct blob *blob = lookup_blob(get_cache_entry(cache, i)->sha1);
struct object *obj;
if (!blob)
continue;
Index: local-pull.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/local-pull.c (mode:100644)
+++ uncommitted/local-pull.c (mode:100644)
@@ -61,7 +61,7 @@
}
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, ifd, 0);
close(ifd);
- if (-1 == (int)(long)map) {
+ if (MAP_FAILED == map) {
fprintf(stderr, "cannot mmap %s\n", filename);
return -1;
}
Index: ls-files.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/ls-files.c (mode:100644)
+++ uncommitted/ls-files.c (mode:100644)
@@ -98,11 +98,11 @@
static int nr_dir;
static int dir_alloc;
-static void add_name(const char *pathname, int len)
+static void add_name(struct cache *cache, const char *pathname, int len)
{
struct nond_on_fs *ent;
- if (cache_name_pos(pathname, len) >= 0)
+ if (cache_name_pos(cache, pathname, len) >= 0)
return;
if (nr_dir == dir_alloc) {
@@ -124,7 +124,7 @@
* Also, we currently ignore all names starting with a dot.
* That likely will not change.
*/
-static void read_directory(const char *path, const char *base, int baselen)
+static void read_directory(struct cache *cache, const char *path, const char *base, int baselen)
{
DIR *dir = opendir(path);
@@ -157,14 +157,14 @@
/* fallthrough */
case DT_DIR:
memcpy(fullname + baselen + len, "/", 2);
- read_directory(fullname, fullname,
+ read_directory(cache, fullname, fullname,
baselen + len + 1);
continue;
case DT_REG:
case DT_LNK:
break;
}
- add_name(fullname, baselen + len);
+ add_name(cache, fullname, baselen + len);
}
closedir(dir);
}
@@ -179,7 +179,7 @@
e2->name, e2->len);
}
-static void show_killed_files()
+static void show_killed_files(struct cache *cache)
{
int i;
for (i = 0; i < nr_dir; i++) {
@@ -193,28 +193,28 @@
/* If ent->name is prefix of an entry in the
* cache, it will be killed.
*/
- pos = cache_name_pos(ent->name, ent->len);
+ pos = cache_name_pos(cache, ent->name, ent->len);
if (0 <= pos)
die("bug in show-killed-files");
pos = -pos - 1;
- while (pos < active_nr &&
- ce_stage(active_cache[pos]))
+ while (pos < get_num_cache_entries(cache) &&
+ ce_stage(get_cache_entry(cache, pos)))
pos++; /* skip unmerged */
- if (active_nr <= pos)
+ if (get_num_cache_entries(cache) <= pos)
break;
/* pos points at a name immediately after
* ent->name in the cache. Does it expect
* ent->name to be a directory?
*/
- len = ce_namelen(active_cache[pos]);
+ len = ce_namelen(get_cache_entry(cache, pos));
if ((ent->len < len) &&
- !strncmp(active_cache[pos]->name,
+ !strncmp(get_cache_entry(cache, pos)->name,
ent->name, ent->len) &&
- active_cache[pos]->name[ent->len] == '/')
+ get_cache_entry(cache, pos)->name[ent->len] == '/')
killed = 1;
break;
}
- if (0 <= cache_name_pos(ent->name, sp - ent->name)) {
+ if (0 <= cache_name_pos(cache, ent->name, sp - ent->name)) {
/* If any of the leading directories in
* ent->name is registered in the cache,
* ent->name will be killed.
@@ -230,13 +230,13 @@
}
}
-static void show_files(void)
+static void show_files(struct cache *cache)
{
int i;
/* For cached/deleted files we don't need to even do the readdir */
if (show_others || show_killed) {
- read_directory(".", "", 0);
+ read_directory(cache, ".", "", 0);
qsort(dir, nr_dir, sizeof(struct nond_on_fs *), cmp_name);
if (show_others)
for (i = 0; i < nr_dir; i++)
@@ -244,11 +244,11 @@
dir[i]->len, dir[i]->name,
line_terminator);
if (show_killed)
- show_killed_files();
+ show_killed_files(cache);
}
if (show_cached | show_stage) {
- for (i = 0; i < active_nr; i++) {
- struct cache_entry *ce = active_cache[i];
+ for (i = 0; i < get_num_cache_entries(cache); i++) {
+ struct cache_entry *ce = get_cache_entry(cache, i);
if (excluded(ce->name) != show_ignored)
continue;
if (show_unmerged && !ce_stage(ce))
@@ -269,8 +269,8 @@
}
}
if (show_deleted) {
- for (i = 0; i < active_nr; i++) {
- struct cache_entry *ce = active_cache[i];
+ for (i = 0; i < get_num_cache_entries(cache); i++) {
+ struct cache_entry *ce = get_cache_entry(cache, i);
struct stat st;
if (excluded(ce->name) != show_ignored)
continue;
@@ -289,6 +289,7 @@
int main(int argc, char **argv)
{
int i;
+ struct cache *cache;
for (i = 1; i < argc; i++) {
char *arg = argv[i];
@@ -341,7 +342,7 @@
if (!(show_stage | show_deleted | show_others | show_unmerged | show_killed))
show_cached = 1;
- read_cache();
- show_files();
+ cache = read_cache();
+ show_files(cache);
return 0;
}
Index: merge-cache.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/merge-cache.c (mode:100644)
+++ uncommitted/merge-cache.c (mode:100644)
@@ -34,11 +34,11 @@
}
}
-static int merge_entry(int pos, const char *path)
+static int merge_entry(struct cache *cache, int pos, const char *path)
{
int found;
- if (pos >= active_nr)
+ if (pos >= get_num_cache_entries(cache))
die("merge-cache: %s not in the cache", path);
arguments[0] = pgm;
arguments[1] = "";
@@ -52,7 +52,7 @@
do {
static char hexbuf[4][60];
static char ownbuf[4][60];
- struct cache_entry *ce = active_cache[pos];
+ struct cache_entry *ce = get_cache_entry(cache, pos);
int stage = ce_stage(ce);
if (strcmp(ce->name, path))
@@ -62,44 +62,45 @@
sprintf(ownbuf[stage], "%o", ntohl(ce->ce_mode) & (~S_IFMT));
arguments[stage] = hexbuf[stage];
arguments[stage + 4] = ownbuf[stage];
- } while (++pos < active_nr);
+ } while (++pos < get_num_cache_entries(cache));
if (!found)
die("merge-cache: %s not in the cache", path);
run_program();
return found;
}
-static void merge_file(const char *path)
+static void merge_file(struct cache *cache, const char *path)
{
- int pos = cache_name_pos(path, strlen(path));
+ int pos = cache_name_pos(cache, path, strlen(path));
/*
* If it already exists in the cache as stage0, it's
* already merged and there is nothing to do.
*/
if (pos < 0)
- merge_entry(-pos-1, path);
+ merge_entry(cache, -pos-1, path);
}
-static void merge_all(void)
+static void merge_all(struct cache *cache)
{
int i;
- for (i = 0; i < active_nr; i++) {
- struct cache_entry *ce = active_cache[i];
+ for (i = 0; i < get_num_cache_entries(cache); i++) {
+ struct cache_entry *ce = get_cache_entry(cache, i);
if (!ce_stage(ce))
continue;
- i += merge_entry(i, ce->name)-1;
+ i += merge_entry(cache, i, ce->name)-1;
}
}
int main(int argc, char **argv)
{
int i, force_file = 0;
+ struct cache *cache;
if (argc < 3)
usage("merge-cache [-o] <merge-program> (-a | <filename>*)");
- read_cache();
+ cache = read_cache();
i = 1;
if (!strcmp(argv[1], "-o")) {
@@ -115,12 +116,12 @@
continue;
}
if (!strcmp(arg, "-a")) {
- merge_all();
+ merge_all(cache);
continue;
}
die("merge-cache: unknown option %s", arg);
}
- merge_file(arg);
+ merge_file(cache, arg);
}
if (err)
die("merge program failed");
Index: read-cache.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/read-cache.c (mode:100644)
+++ uncommitted/read-cache.c (mode:100644)
@@ -6,10 +6,49 @@
#include <stdarg.h>
#include "cache.h"
-struct cache_entry **active_cache = NULL;
-unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;
+/*
+ * Basic data structures for the directory cache
+ */
+
+#define CACHE_SIGNATURE 0x44495243 /* "DIRC" */
+struct cache_header {
+ unsigned int hdr_signature;
+ unsigned int hdr_version;
+ unsigned int hdr_entries;
+};
+
+struct mmap_holder {
+ void * ptr;
+ size_t size;
+};
+
+struct cache {
+ struct mmap_holder map;
+ struct cache_header *header;
+ struct cache_entry **entries;
+ unsigned int num_entries;
+ unsigned int allocated_entries;
+ unsigned int active_cache_changed;
+};
+
+struct cache * new_cache()
+{
+ struct cache *cache = xcalloc(1, sizeof(struct cache));
+
+ cache->map.ptr = MAP_FAILED;
+
+ return cache;
+}
+
+void free_cache(struct cache *cache)
+{
+ if (cache->map.ptr != MAP_FAILED)
+ munmap(cache->map.ptr, cache->map.size);
+
+ free(cache);
+}
-int cache_match_stat(struct cache_entry *ce, struct stat *st)
+int ce_match_stat(struct cache_entry *ce, struct stat *st)
{
unsigned int changed = 0;
@@ -75,15 +114,15 @@
return 0;
}
-int cache_name_pos(const char *name, int namelen)
+int cache_name_pos(struct cache *cache, const char *name, int namelen)
{
int first, last;
first = 0;
- last = active_nr;
+ last = cache->num_entries;
while (last > first) {
int next = (last + first) >> 1;
- struct cache_entry *ce = active_cache[next];
+ struct cache_entry *ce = get_cache_entry(cache, next);
int cmp = cache_name_compare(name, namelen, ce->name, htons(ce->ce_flags));
if (!cmp)
return next;
@@ -97,27 +136,27 @@
}
/* Remove entry, return true if there are more entries to go.. */
-int remove_entry_at(int pos)
+int remove_cache_entry_at(struct cache *cache, int pos)
{
- active_cache_changed = 1;
- active_nr--;
- if (pos >= active_nr)
+ cache->active_cache_changed = 1;
+ cache->num_entries--;
+ if (pos >= cache->num_entries)
return 0;
- memmove(active_cache + pos, active_cache + pos + 1, (active_nr - pos) * sizeof(struct cache_entry *));
+ memmove(cache->entries + pos, cache->entries + pos + 1, (cache->num_entries - pos) * sizeof(struct cache_entry *));
return 1;
}
-int remove_file_from_cache(char *path)
+int remove_file_from_cache(struct cache *cache, char *path)
{
- int pos = cache_name_pos(path, strlen(path));
+ int pos = cache_name_pos(cache, path, strlen(path));
if (pos < 0)
pos = -pos-1;
- while (pos < active_nr && !strcmp(active_cache[pos]->name, path))
- remove_entry_at(pos);
+ while (pos < get_num_cache_entries(cache) && !strcmp(get_cache_entry(cache, pos)->name, path))
+ remove_cache_entry_at(cache, pos);
return 0;
}
-int same_name(struct cache_entry *a, struct cache_entry *b)
+int ce_same_name(struct cache_entry *a, struct cache_entry *b)
{
int len = ce_namelen(a);
return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
@@ -132,7 +171,8 @@
* from the cache so the caller should recompute the insert position.
* When this happens, we return non-zero.
*/
-static int check_file_directory_conflict(const struct cache_entry *ce,
+static int check_file_directory_conflict(struct cache *cache,
+ const struct cache_entry *ce,
int ok_to_replace)
{
int pos, replaced = 0;
@@ -155,7 +195,7 @@
if (!ep)
break;
*ep = 0; /* first cut it at slash */
- pos = cache_name_pos(pathbuf,
+ pos = cache_name_pos(cache, pathbuf,
htons(create_ce_flags(ep-cp, stage)));
if (0 <= pos) {
/* Our leading path component is registered as a file,
@@ -167,7 +207,7 @@
return -1;
}
fprintf(stderr, "removing file '%s' to replace it with a directory to create '%s'.\n", pathbuf, path);
- remove_entry_at(pos);
+ remove_cache_entry_at(cache, pos);
replaced = 1;
}
*ep = '/'; /* then restore it and go downwards */
@@ -179,7 +219,7 @@
* of it? That is, are we creating a file where they already expect
* a directory there?
*/
- pos = cache_name_pos(path,
+ pos = cache_name_pos(cache, path,
htons(create_ce_flags(namelen, stage)));
/* (0 <= pos) cannot happen because add_cache_entry()
@@ -206,8 +246,8 @@
* path of an existing entry anymore.
*/
- while (pos < active_nr) {
- struct cache_entry *other = active_cache[pos];
+ while (pos < get_num_cache_entries(cache)) {
+ struct cache_entry *other = get_cache_entry(cache, pos);
if (strncmp(other->name, path, namelen))
break; /* it is not our "subdirectory" anymore */
if ((ce_stage(other) == stage) &&
@@ -215,7 +255,7 @@
if (!ok_to_replace)
return -1;
fprintf(stderr, "removing file '%s' under '%s' to be replaced with a file\n", other->name, path);
- remove_entry_at(pos);
+ remove_cache_entry_at(cache, pos);
replaced = 1;
continue; /* cycle without updating pos */
}
@@ -224,17 +264,35 @@
return replaced;
}
-int add_cache_entry(struct cache_entry *ce, int option)
+void set_cache_entry(struct cache *cache, struct cache_entry *ce, int pos)
+{
+ cache->active_cache_changed = 1;
+ cache->entries[pos] = ce;
+}
+
+int get_num_cache_entries(struct cache *cache)
+{
+ return cache->num_entries;
+}
+
+struct cache_entry *get_cache_entry(struct cache *cache, int pos)
+{
+ /* You can NOT just free cache->entries[pos] here, since it
+ * might not be necessarily malloc()ed but can also come
+ * from mmap(). */
+ return cache->entries[pos];
+}
+
+int add_cache_entry(struct cache *cache, struct cache_entry *ce, int option)
{
int pos;
int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
- pos = cache_name_pos(ce->name, htons(ce->ce_flags));
+ pos = cache_name_pos(cache, ce->name, htons(ce->ce_flags));
/* existing match? Just replace it */
if (pos >= 0) {
- active_cache_changed = 1;
- active_cache[pos] = ce;
+ set_cache_entry(cache, ce, pos);
return 0;
}
pos = -pos-1;
@@ -243,10 +301,10 @@
* Inserting a merged entry ("stage 0") into the index
* will always replace all non-merged entries..
*/
- if (pos < active_nr && ce_stage(ce) == 0) {
- while (same_name(active_cache[pos], ce)) {
+ if (pos < get_num_cache_entries(cache) && ce_stage(ce) == 0) {
+ while (ce_same_name(get_cache_entry(cache, pos), ce)) {
ok_to_add = 1;
- if (!remove_entry_at(pos))
+ if (!remove_cache_entry_at(cache, pos))
break;
}
}
@@ -254,25 +312,24 @@
if (!ok_to_add)
return -1;
- if (check_file_directory_conflict(ce, ok_to_replace)) {
+ if (check_file_directory_conflict(cache, ce, ok_to_replace)) {
if (!ok_to_replace)
return -1;
- pos = cache_name_pos(ce->name, htons(ce->ce_flags));
+ pos = cache_name_pos(cache, ce->name, htons(ce->ce_flags));
pos = -pos-1;
}
/* Make sure the array is big enough .. */
- if (active_nr == active_alloc) {
- active_alloc = alloc_nr(active_alloc);
- active_cache = xrealloc(active_cache, active_alloc * sizeof(struct cache_entry *));
+ if (cache->num_entries == cache->allocated_entries) {
+ cache->allocated_entries = alloc_nr(cache->allocated_entries);
+ cache->entries = xrealloc(cache->entries, cache->allocated_entries * sizeof(struct cache_entry *));
}
/* Add it in.. */
- active_nr++;
- if (active_nr > pos)
- memmove(active_cache + pos + 1, active_cache + pos, (active_nr - pos - 1) * sizeof(ce));
- active_cache[pos] = ce;
- active_cache_changed = 1;
+ cache->num_entries++;
+ if (cache->num_entries > pos)
+ memmove(cache->entries + pos + 1, cache->entries + pos, (cache->num_entries - pos - 1) * sizeof(ce));
+ set_cache_entry(cache, ce, pos);
return 0;
}
@@ -293,54 +350,56 @@
return 0;
}
-int read_cache(void)
+struct cache *read_cache(void)
{
int fd, i;
struct stat st;
- unsigned long size, offset;
- void *map;
- struct cache_header *hdr;
-
- errno = EBUSY;
- if (active_cache)
- return error("more than one cachefile");
+ unsigned long offset;
+ struct cache *cache = new_cache();
+
errno = ENOENT;
fd = open(get_index_file(), O_RDONLY);
- if (fd < 0)
- return (errno == ENOENT) ? 0 : error("open failed");
+ if (fd < 0) {
+ if (errno == ENOENT)
+ return cache;
+ else {
+ free_cache(cache);
+ return NULL;
+ }
+ }
- size = 0; // avoid gcc warning
- map = (void *)-1;
if (!fstat(fd, &st)) {
- size = st.st_size;
+ cache->map.size = st.st_size;
errno = EINVAL;
- if (size >= sizeof(struct cache_header) + 20)
- map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (cache->map.size >= sizeof(struct cache_header) + 20)
+ cache->map.ptr = mmap(NULL, cache->map.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
}
close(fd);
- if (-1 == (int)(long)map)
- return error("mmap failed");
+ if (MAP_FAILED == cache->map.ptr) {
+ error("mmap failed");
+ free_cache(cache);
+ return NULL;
+ }
- hdr = map;
- if (verify_hdr(hdr, size) < 0)
- goto unmap;
-
- active_nr = ntohl(hdr->hdr_entries);
- active_alloc = alloc_nr(active_nr);
- active_cache = calloc(active_alloc, sizeof(struct cache_entry *));
-
- offset = sizeof(*hdr);
- for (i = 0; i < active_nr; i++) {
- struct cache_entry *ce = map + offset;
- offset = offset + ce_size(ce);
- active_cache[i] = ce;
+ cache->header = cache->map.ptr;
+ if (verify_hdr(cache->header, cache->map.size) < 0) {
+ free_cache(cache);
+ errno = EINVAL;
+ error("verify header failed");
+ return NULL;
}
- return active_nr;
-unmap:
- munmap(map, size);
- errno = EINVAL;
- return error("verify header failed");
+ cache->num_entries = ntohl(cache->header->hdr_entries);
+ cache->allocated_entries = alloc_nr(cache->num_entries);
+ cache->entries = xcalloc(cache->allocated_entries, sizeof(struct cache_entry *));
+
+ offset = sizeof(*cache->header);
+ for (i = 0; i < cache->num_entries; i++) {
+ struct cache_entry *ce = cache->map.ptr + offset;
+ offset = offset + ce_size(ce);
+ cache->entries[i] = ce;
+ }
+ return cache;
}
#define WRITE_BUFFER_SIZE 8192
@@ -386,7 +445,7 @@
return 0;
}
-int write_cache(int newfd, struct cache_entry **cache, int entries)
+int write_cache(struct cache *cache, int newfd)
{
SHA_CTX c;
struct cache_header hdr;
@@ -394,14 +453,14 @@
hdr.hdr_signature = htonl(CACHE_SIGNATURE);
hdr.hdr_version = htonl(2);
- hdr.hdr_entries = htonl(entries);
+ hdr.hdr_entries = htonl(get_num_cache_entries(cache));
SHA1_Init(&c);
if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
return -1;
- for (i = 0; i < entries; i++) {
- struct cache_entry *ce = cache[i];
+ for (i = 0; i < get_num_cache_entries(cache); i++) {
+ struct cache_entry *ce = get_cache_entry(cache, i);
if (ce_write(&c, newfd, ce, ce_size(ce)) < 0)
return -1;
}
Index: read-tree.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/read-tree.c (mode:100644)
+++ uncommitted/read-tree.c (mode:100644)
@@ -7,7 +7,7 @@
static int stage = 0;
-static int unpack_tree(unsigned char *sha1)
+static int unpack_tree(struct cache *cache, unsigned char *sha1)
{
void *buffer;
unsigned long size;
@@ -16,7 +16,7 @@
buffer = read_object_with_reference(sha1, "tree", &size, 0);
if (!buffer)
return -1;
- ret = read_tree(buffer, size, stage);
+ ret = read_tree(cache, buffer, size, stage);
free(buffer);
return ret;
}
@@ -93,26 +93,30 @@
return NULL;
}
-static void trivially_merge_cache(struct cache_entry **src, int nr)
+/* rather than doing the 'right' thing of deleting entries as we merge,
+ * walk dst through the cache, overwriting entries as we go and at the
+ * end truncate the size of the cache */
+static void trivially_merge_cache(struct cache *cache)
{
static struct cache_entry null_entry;
- struct cache_entry **dst = src;
struct cache_entry *old = &null_entry;
+ int src = 0, dst = 0, nr = get_num_cache_entries(cache);
- while (nr) {
+ while (src < nr) {
struct cache_entry *ce, *result;
- ce = src[0];
+ ce = get_cache_entry(cache, src);
/* We throw away original cache entries except for the stat information */
if (!ce_stage(ce)) {
old = ce;
src++;
- nr--;
- active_nr--;
continue;
}
- if (nr > 2 && (result = merge_entries(ce, src[1], src[2])) != NULL) {
+ if ((src < (nr - 2)) &&
+ (result = merge_entries(ce,
+ get_cache_entry(cache, src + 1),
+ get_cache_entry(cache, src + 2))) != NULL) {
/*
* See if we can re-use the old CE directly?
* That way we get the uptodate stat info.
@@ -122,40 +126,46 @@
ce = result;
ce->ce_flags &= ~htons(CE_STAGEMASK);
src += 2;
- nr -= 2;
- active_nr -= 2;
}
- *dst++ = ce;
+ set_cache_entry(cache, ce, dst);
+ dst++;
src++;
+ }
+ /* this could be replaced by a truncate api */
+ while (nr > dst) {
nr--;
+ remove_cache_entry_at(cache, nr);
}
}
-static void merge_stat_info(struct cache_entry **src, int nr)
+static void merge_stat_info(struct cache *cache)
{
static struct cache_entry null_entry;
- struct cache_entry **dst = src;
struct cache_entry *old = &null_entry;
+ int src = 0, dst = 0, nr = get_num_cache_entries(cache);
- while (nr) {
+ while (src < nr) {
struct cache_entry *ce;
- ce = src[0];
+ ce = get_cache_entry(cache, src);
/* We throw away original cache entries except for the stat information */
if (!ce_stage(ce)) {
old = ce;
src++;
- nr--;
- active_nr--;
continue;
}
if (path_matches(ce, old) && same(ce, old))
*ce = *old;
ce->ce_flags &= ~htons(CE_STAGEMASK);
- *dst++ = ce;
+ set_cache_entry(cache, ce, dst);
+ dst++;
src++;
+ }
+ /* this could be replaced by a truncate api */
+ while (nr > dst) {
nr--;
+ remove_cache_entry_at(cache, nr);
}
}
@@ -167,6 +177,7 @@
unsigned char sha1[20];
static char lockfile[MAXPATHLEN+1];
const char *indexfile = get_index_file();
+ struct cache *cache = NULL;
snprintf(lockfile, sizeof(lockfile), "%s.lock", indexfile);
@@ -185,9 +196,9 @@
int i;
if (stage)
die("-m needs to come first");
- read_cache();
- for (i = 0; i < active_nr; i++) {
- if (ce_stage(active_cache[i]))
+ cache = read_cache();
+ for (i = 0; i < get_num_cache_entries(cache); i++) {
+ if (ce_stage(get_cache_entry(cache, i)))
die("you need to resolve your current index first");
}
stage = 1;
@@ -198,23 +209,25 @@
usage(read_tree_usage);
if (stage > 3)
usage(read_tree_usage);
- if (unpack_tree(sha1) < 0)
+ if (!cache)
+ cache = new_cache();
+ if (unpack_tree(cache, sha1) < 0)
die("failed to unpack tree object %s", arg);
stage++;
}
if (merge) {
switch (stage) {
case 4: /* Three-way merge */
- trivially_merge_cache(active_cache, active_nr);
+ trivially_merge_cache(cache);
break;
case 2: /* Just read a tree, merge with old cache contents */
- merge_stat_info(active_cache, active_nr);
+ merge_stat_info(cache);
break;
default:
die("just how do you expect me to merge %d trees?", stage-1);
}
}
- if (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile))
+ if (write_cache(cache, newfd) || rename(lockfile, indexfile))
die("unable to write new index file");
lockfile_name = NULL;
return 0;
Index: sha1_file.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/sha1_file.c (mode:100644)
+++ uncommitted/sha1_file.c (mode:100644)
@@ -302,7 +302,7 @@
}
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- if (-1 == (int)(long)map)
+ if (MAP_FAILED == map)
return NULL;
*size = st.st_size;
return map;
@@ -587,7 +587,7 @@
if (size)
buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- if ((int)(long)buf == -1)
+ if (buf == MAP_FAILED)
return -1;
ret = write_sha1_file(buf, size, "blob", sha1);
Index: tree.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/tree.c (mode:100644)
+++ uncommitted/tree.c (mode:100644)
@@ -5,7 +5,8 @@
const char *tree_type = "tree";
-static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int read_one_entry(struct cache *cache, unsigned char *sha1, const char *base,
+ int baselen, const char *pathname, unsigned mode, int stage)
{
int len = strlen(pathname);
unsigned int size = cache_entry_size(baselen + len);
@@ -18,10 +19,10 @@
memcpy(ce->name, base, baselen);
memcpy(ce->name + baselen, pathname, len+1);
memcpy(ce->sha1, sha1, 20);
- return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD);
+ return add_cache_entry(cache, ce, ADD_CACHE_OK_TO_ADD);
}
-static int read_tree_recursive(void *buffer, unsigned long size,
+static int read_tree_recursive(struct cache* cache, void *buffer, unsigned long size,
const char *base, int baselen, int stage)
{
while (size) {
@@ -53,7 +54,7 @@
memcpy(newbase, base, baselen);
memcpy(newbase + baselen, path, pathlen);
newbase[baselen + pathlen] = '/';
- retval = read_tree_recursive(eltbuf, eltsize,
+ retval = read_tree_recursive(cache, eltbuf, eltsize,
newbase,
baselen + pathlen + 1, stage);
free(eltbuf);
@@ -62,15 +63,15 @@
return -1;
continue;
}
- if (read_one_entry(sha1, base, baselen, path, mode, stage) < 0)
+ if (read_one_entry(cache, sha1, base, baselen, path, mode, stage) < 0)
return -1;
}
return 0;
}
-int read_tree(void *buffer, unsigned long size, int stage)
+int read_tree(struct cache *cache, void *buffer, unsigned long size, int stage)
{
- return read_tree_recursive(buffer, size, "", 0, stage);
+ return read_tree_recursive(cache, buffer, size, "", 0, stage);
}
struct tree *lookup_tree(unsigned char *sha1)
Index: update-cache.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/update-cache.c (mode:100644)
+++ uncommitted/update-cache.c (mode:100644)
@@ -51,7 +51,7 @@
ce->ce_size = htonl(st->st_size);
}
-static int add_file_to_cache(char *path)
+static int add_file_to_cache(struct cache *cache, char *path)
{
int size, namelen, option, status;
struct cache_entry *ce;
@@ -71,7 +71,7 @@
*/
if (status == 0 || (errno == ENOENT || errno == ENOTDIR)) {
if (allow_remove)
- return remove_file_from_cache(path);
+ return remove_file_from_cache(cache, path);
}
return error("open(\"%s\"): %s", path, strerror(errno));
}
@@ -106,7 +106,7 @@
}
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
- return add_cache_entry(ce, option);
+ return add_cache_entry(cache, ce, option);
}
static int match_data(int fd, void *buffer, unsigned long size)
@@ -191,7 +191,7 @@
if (lstat(ce->name, &st) < 0)
return ERR_PTR(-errno);
- changed = cache_match_stat(ce, &st);
+ changed = ce_match_stat(ce, &st);
if (!changed)
return ce;
@@ -222,19 +222,19 @@
return updated;
}
-static int refresh_cache(void)
+static int refresh_cache(struct cache *cache)
{
int i;
int has_errors = 0;
- for (i = 0; i < active_nr; i++) {
+ for (i = 0; i < get_num_cache_entries(cache); i++) {
struct cache_entry *ce, *new;
- ce = active_cache[i];
+ ce = get_cache_entry(cache, i);
if (ce_stage(ce)) {
printf("%s: needs merge\n", ce->name);
has_errors = 1;
- while ((i < active_nr) &&
- ! strcmp(active_cache[i]->name, ce->name))
+ while ((i < get_num_cache_entries(cache)) &&
+ ! strcmp(get_cache_entry(cache, i)->name, ce->name))
i++;
i--;
continue;
@@ -248,11 +248,7 @@
}
continue;
}
- active_cache_changed = 1;
- /* You can NOT just free active_cache[i] here, since it
- * might not be necessarily malloc()ed but can also come
- * from mmap(). */
- active_cache[i] = new;
+ set_cache_entry(cache, new, i);
}
return has_errors;
}
@@ -285,7 +281,7 @@
}
}
-static int add_cacheinfo(char *arg1, char *arg2, char *arg3)
+static int add_cacheinfo(struct cache *cache, char *arg1, char *arg2, char *arg3)
{
int size, len, option;
unsigned int mode;
@@ -310,7 +306,7 @@
ce->ce_mode = create_ce_mode(mode);
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
- return add_cache_entry(ce, option);
+ return add_cache_entry(cache, ce, option);
}
static const char *lockfile_name = NULL;
@@ -328,10 +324,11 @@
int main(int argc, char **argv)
{
- int i, newfd, entries, has_errors = 0;
+ int i, newfd, has_errors = 0;
int allow_options = 1;
static char lockfile[MAXPATHLEN+1];
const char *indexfile = get_index_file();
+ struct cache *cache = NULL;
snprintf(lockfile, sizeof(lockfile), "%s.lock", indexfile);
@@ -343,8 +340,8 @@
atexit(remove_lock_file);
lockfile_name = lockfile;
- entries = read_cache();
- if (entries < 0)
+ cache = read_cache();
+ if (!cache)
die("cache corrupted");
for (i = 1 ; i < argc; i++) {
@@ -368,13 +365,13 @@
continue;
}
if (!strcmp(path, "--refresh")) {
- has_errors |= refresh_cache();
+ has_errors |= refresh_cache(cache);
continue;
}
if (!strcmp(path, "--cacheinfo")) {
if (i+3 >= argc)
die("update-cache: --cacheinfo <mode> <sha1> <path>");
- if (add_cacheinfo(argv[i+1], argv[i+2], argv[i+3]))
+ if (add_cacheinfo(cache, argv[i+1], argv[i+2], argv[i+3]))
die("update-cache: --cacheinfo cannot add %s", argv[i+3]);
i += 3;
continue;
@@ -382,7 +379,7 @@
if (!strcmp(path, "--force-remove")) {
if (argc <= i + 1)
die("update-cache: --force-remove <path>");
- if (remove_file_from_cache(argv[i+1]))
+ if (remove_file_from_cache(cache, argv[i+1]))
die("update-cache: --force-remove cannot remove %s", argv[i+1]);
i++;
continue;
@@ -398,10 +395,10 @@
fprintf(stderr, "Ignoring path %s\n", argv[i]);
continue;
}
- if (add_file_to_cache(path))
+ if (add_file_to_cache(cache, path))
die("Unable to add %s to database", path);
}
- if (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile))
+ if (write_cache(cache, newfd) || rename(lockfile, indexfile))
die("Unable to write new cachefile");
lockfile_name = NULL;
Index: write-tree.c
===================================================================
--- c8c77f67ea85ee65a0f055f2cb76e6059eaa0776/write-tree.c (mode:100644)
+++ uncommitted/write-tree.c (mode:100644)
@@ -17,7 +17,7 @@
return ret;
}
-static int write_tree(struct cache_entry **cachep, int maxentries, const char *base, int baselen, unsigned char *returnsha1)
+static int write_tree(struct cache *cache, int start_pos, const char *base, int baselen, unsigned char *returnsha1)
{
unsigned char subdir_sha1[20];
unsigned long size, offset;
@@ -30,8 +30,8 @@
offset = 0;
nr = 0;
- while (nr < maxentries) {
- struct cache_entry *ce = cachep[nr];
+ while ((start_pos + nr) < get_num_cache_entries(cache)) {
+ struct cache_entry *ce = get_cache_entry(cache, start_pos + nr);
const char *pathname = ce->name, *filename, *dirname;
int pathlen = ce_namelen(ce), entrylen;
unsigned char *sha1;
@@ -41,16 +41,13 @@
if (baselen >= pathlen || memcmp(base, pathname, baselen))
break;
- sha1 = ce->sha1;
- mode = ntohl(ce->ce_mode);
-
/* Do we have _further_ subdirectories? */
filename = pathname + baselen;
dirname = strchr(filename, '/');
if (dirname) {
int subdir_written;
- subdir_written = write_tree(cachep + nr, maxentries - nr, pathname, dirname-pathname+1, subdir_sha1);
+ subdir_written = write_tree(cache, start_pos + nr, pathname, dirname-pathname+1, subdir_sha1);
nr += subdir_written;
/* Now we need to write out the directory entry into this tree.. */
@@ -60,6 +57,9 @@
/* ..but the directory entry doesn't count towards the total count */
nr--;
sha1 = subdir_sha1;
+ } else {
+ sha1 = ce->sha1;
+ mode = ntohl(ce->ce_mode);
}
if (check_valid_sha1(sha1) < 0)
@@ -85,16 +85,19 @@
int main(int argc, char **argv)
{
int i, funny;
- int entries = read_cache();
+ struct cache *cache = read_cache();
+ int entries;
unsigned char sha1[20];
- if (entries < 0)
+ if (!cache)
die("write-tree: error reading cache");
+ entries = get_num_cache_entries(cache);
+
/* Verify that the tree is merged */
funny = 0;
for (i = 0; i < entries; i++) {
- struct cache_entry *ce = active_cache[i];
+ struct cache_entry *ce = get_cache_entry(cache, i);
if (ntohs(ce->ce_flags) & ~CE_NAMEMASK) {
if (10 < ++funny) {
fprintf(stderr, "...\n");
@@ -116,8 +119,8 @@
* the cache is sorted. Also path can appear only once,
* which means conflicting one would immediately follow.
*/
- const char *this_name = active_cache[i]->name;
- const char *next_name = active_cache[i+1]->name;
+ const char *this_name = get_cache_entry(cache, i)->name;
+ const char *next_name = get_cache_entry(cache, i+1)->name;
int this_len = strlen(this_name);
if (this_len < strlen(next_name) &&
strncmp(this_name, next_name, this_len) == 0 &&
@@ -134,7 +137,7 @@
die("write-tree: not able to write tree");
/* Ok, write it out */
- if (write_tree(active_cache, entries, "", 0, sha1) != entries)
+ if (write_tree(cache, 0, "", 0, sha1) != entries)
die("write-tree: internal error");
printf("%s\n", sha1_to_hex(sha1));
return 0;
^ permalink raw reply [flat|nested] 21+ messages in thread