Skip to content

Commit 8fd2cb4

Browse files
dschoJunio C Hamano
authored andcommitted
Extract helper bits from c-merge-recursive work
This backports the pieces that are not uncooked from the merge-recursive WIP we have seen earlier, to be used in git-mv rewritten in C. Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 24cf6e5 commit 8fd2cb4

File tree

4 files changed

+172
-45
lines changed

4 files changed

+172
-45
lines changed

cache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ static inline unsigned int create_ce_mode(unsigned int mode)
115115
extern struct cache_entry **active_cache;
116116
extern unsigned int active_nr, active_alloc, active_cache_changed;
117117
extern struct cache_tree *active_cache_tree;
118+
extern int cache_errno;
118119

119120
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
120121
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
@@ -142,13 +143,15 @@ extern void verify_non_filename(const char *prefix, const char *name);
142143

143144
/* Initialize and use the cache information */
144145
extern int read_cache(void);
146+
extern int read_cache_from(const char *path);
145147
extern int write_cache(int newfd, struct cache_entry **cache, int entries);
146148
extern int verify_path(const char *path);
147149
extern int cache_name_pos(const char *name, int namelen);
148150
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
149151
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
150152
#define ADD_CACHE_SKIP_DFCHECK 4 /* Ok to skip DF conflict checks */
151153
extern int add_cache_entry(struct cache_entry *ce, int option);
154+
extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
152155
extern int remove_cache_entry_at(int pos);
153156
extern int remove_file_from_cache(const char *path);
154157
extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);

path-list.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#include <stdio.h>
2+
#include "cache.h"
3+
#include "path-list.h"
4+
5+
/* if there is no exact match, point to the index where the entry could be
6+
* inserted */
7+
static int get_entry_index(const struct path_list *list, const char *path,
8+
int *exact_match)
9+
{
10+
int left = -1, right = list->nr;
11+
12+
while (left + 1 < right) {
13+
int middle = (left + right) / 2;
14+
int compare = strcmp(path, list->items[middle].path);
15+
if (compare < 0)
16+
right = middle;
17+
else if (compare > 0)
18+
left = middle;
19+
else {
20+
*exact_match = 1;
21+
return middle;
22+
}
23+
}
24+
25+
*exact_match = 0;
26+
return right;
27+
}
28+
29+
/* returns -1-index if already exists */
30+
static int add_entry(struct path_list *list, const char *path)
31+
{
32+
int exact_match;
33+
int index = get_entry_index(list, path, &exact_match);
34+
35+
if (exact_match)
36+
return -1 - index;
37+
38+
if (list->nr + 1 >= list->alloc) {
39+
list->alloc += 32;
40+
list->items = xrealloc(list->items, list->alloc
41+
* sizeof(struct path_list_item));
42+
}
43+
if (index < list->nr)
44+
memmove(list->items + index + 1, list->items + index,
45+
(list->nr - index)
46+
* sizeof(struct path_list_item));
47+
list->items[index].path = list->strdup_paths ?
48+
strdup(path) : (char *)path;
49+
list->items[index].util = NULL;
50+
list->nr++;
51+
52+
return index;
53+
}
54+
55+
struct path_list_item *path_list_insert(const char *path, struct path_list *list)
56+
{
57+
int index = add_entry(list, path);
58+
59+
if (index < 0)
60+
index = 1 - index;
61+
62+
return list->items + index;
63+
}
64+
65+
int path_list_has_path(const struct path_list *list, const char *path)
66+
{
67+
int exact_match;
68+
get_entry_index(list, path, &exact_match);
69+
return exact_match;
70+
}
71+
72+
struct path_list_item *path_list_lookup(const char *path, struct path_list *list)
73+
{
74+
int exact_match, i = get_entry_index(list, path, &exact_match);
75+
if (!exact_match)
76+
return NULL;
77+
return list->items + i;
78+
}
79+
80+
void path_list_clear(struct path_list *list, int free_items)
81+
{
82+
if (list->items) {
83+
int i;
84+
if (free_items)
85+
for (i = 0; i < list->nr; i++) {
86+
if (list->strdup_paths)
87+
free(list->items[i].path);
88+
if (list->items[i].util)
89+
free(list->items[i].util);
90+
}
91+
free(list->items);
92+
}
93+
list->items = NULL;
94+
list->nr = list->alloc = 0;
95+
}
96+
97+
void print_path_list(const char *text, const struct path_list *p)
98+
{
99+
int i;
100+
if ( text )
101+
printf("%s\n", text);
102+
for (i = 0; i < p->nr; i++)
103+
printf("%s:%p\n", p->items[i].path, p->items[i].util);
104+
}
105+

path-list.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef _PATH_LIST_H_
2+
#define _PATH_LIST_H_
3+
4+
struct path_list_item {
5+
char *path;
6+
void *util;
7+
};
8+
struct path_list
9+
{
10+
struct path_list_item *items;
11+
unsigned int nr, alloc;
12+
unsigned int strdup_paths:1;
13+
};
14+
15+
void print_path_list(const char *text, const struct path_list *p);
16+
17+
int path_list_has_path(const struct path_list *list, const char *path);
18+
void path_list_clear(struct path_list *list, int free_items);
19+
struct path_list_item *path_list_insert(const char *path, struct path_list *list);
20+
struct path_list_item *path_list_lookup(const char *path, struct path_list *list);
21+
22+
#endif /* _PATH_LIST_H_ */

read-cache.c

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;
2424

2525
struct cache_tree *active_cache_tree = NULL;
2626

27+
int cache_errno = 0;
28+
29+
static void *cache_mmap = NULL;
30+
static size_t cache_mmap_size = 0;
31+
2732
/*
2833
* This only updates the "non-critical" parts of the directory
2934
* cache, ie the parts that aren't tracked by GIT, and only used
@@ -577,22 +582,6 @@ int add_cache_entry(struct cache_entry *ce, int option)
577582
return 0;
578583
}
579584

580-
/* Three functions to allow overloaded pointer return; see linux/err.h */
581-
static inline void *ERR_PTR(long error)
582-
{
583-
return (void *) error;
584-
}
585-
586-
static inline long PTR_ERR(const void *ptr)
587-
{
588-
return (long) ptr;
589-
}
590-
591-
static inline long IS_ERR(const void *ptr)
592-
{
593-
return (unsigned long)ptr > (unsigned long)-1000L;
594-
}
595-
596585
/*
597586
* "refresh" does not calculate a new sha1 file or bring the
598587
* cache up-to-date for mode/content changes. But what it
@@ -604,26 +593,30 @@ static inline long IS_ERR(const void *ptr)
604593
* For example, you'd want to do this after doing a "git-read-tree",
605594
* to link up the stat cache details with the proper files.
606595
*/
607-
static struct cache_entry *refresh_entry(struct cache_entry *ce, int really)
596+
struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
608597
{
609598
struct stat st;
610599
struct cache_entry *updated;
611600
int changed, size;
612601

613-
if (lstat(ce->name, &st) < 0)
614-
return ERR_PTR(-errno);
602+
if (lstat(ce->name, &st) < 0) {
603+
cache_errno = errno;
604+
return NULL;
605+
}
615606

616607
changed = ce_match_stat(ce, &st, really);
617608
if (!changed) {
618609
if (really && assume_unchanged &&
619610
!(ce->ce_flags & htons(CE_VALID)))
620611
; /* mark this one VALID again */
621612
else
622-
return NULL;
613+
return ce;
623614
}
624615

625-
if (ce_modified(ce, &st, really))
626-
return ERR_PTR(-EINVAL);
616+
if (ce_modified(ce, &st, really)) {
617+
cache_errno = EINVAL;
618+
return NULL;
619+
}
627620

628621
size = ce_size(ce);
629622
updated = xmalloc(size);
@@ -666,13 +659,13 @@ int refresh_cache(unsigned int flags)
666659
continue;
667660
}
668661

669-
new = refresh_entry(ce, really);
670-
if (!new)
662+
new = refresh_cache_entry(ce, really);
663+
if (new == ce)
671664
continue;
672-
if (IS_ERR(new)) {
673-
if (not_new && PTR_ERR(new) == -ENOENT)
665+
if (!new) {
666+
if (not_new && cache_errno == ENOENT)
674667
continue;
675-
if (really && PTR_ERR(new) == -EINVAL) {
668+
if (really && cache_errno == EINVAL) {
676669
/* If we are doing --really-refresh that
677670
* means the index is not valid anymore.
678671
*/
@@ -728,40 +721,44 @@ static int read_index_extension(const char *ext, void *data, unsigned long sz)
728721
}
729722

730723
int read_cache(void)
724+
{
725+
return read_cache_from(get_index_file());
726+
}
727+
728+
/* remember to discard_cache() before reading a different cache! */
729+
int read_cache_from(const char *path)
731730
{
732731
int fd, i;
733732
struct stat st;
734-
unsigned long size, offset;
735-
void *map;
733+
unsigned long offset;
736734
struct cache_header *hdr;
737735

738736
errno = EBUSY;
739-
if (active_cache)
737+
if (cache_mmap)
740738
return active_nr;
741739

742740
errno = ENOENT;
743741
index_file_timestamp = 0;
744-
fd = open(get_index_file(), O_RDONLY);
742+
fd = open(path, O_RDONLY);
745743
if (fd < 0) {
746744
if (errno == ENOENT)
747745
return 0;
748746
die("index file open failed (%s)", strerror(errno));
749747
}
750748

751-
size = 0; /* avoid gcc warning */
752-
map = MAP_FAILED;
749+
cache_mmap = MAP_FAILED;
753750
if (!fstat(fd, &st)) {
754-
size = st.st_size;
751+
cache_mmap_size = st.st_size;
755752
errno = EINVAL;
756-
if (size >= sizeof(struct cache_header) + 20)
757-
map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
753+
if (cache_mmap_size >= sizeof(struct cache_header) + 20)
754+
cache_mmap = mmap(NULL, cache_mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
758755
}
759756
close(fd);
760-
if (map == MAP_FAILED)
757+
if (cache_mmap == MAP_FAILED)
761758
die("index file mmap failed (%s)", strerror(errno));
762759

763-
hdr = map;
764-
if (verify_hdr(hdr, size) < 0)
760+
hdr = cache_mmap;
761+
if (verify_hdr(hdr, cache_mmap_size) < 0)
765762
goto unmap;
766763

767764
active_nr = ntohl(hdr->hdr_entries);
@@ -770,23 +767,23 @@ int read_cache(void)
770767

771768
offset = sizeof(*hdr);
772769
for (i = 0; i < active_nr; i++) {
773-
struct cache_entry *ce = (struct cache_entry *) ((char *) map + offset);
770+
struct cache_entry *ce = (struct cache_entry *) ((char *) cache_mmap + offset);
774771
offset = offset + ce_size(ce);
775772
active_cache[i] = ce;
776773
}
777774
index_file_timestamp = st.st_mtime;
778-
while (offset <= size - 20 - 8) {
775+
while (offset <= cache_mmap_size - 20 - 8) {
779776
/* After an array of active_nr index entries,
780777
* there can be arbitrary number of extended
781778
* sections, each of which is prefixed with
782779
* extension name (4-byte) and section length
783780
* in 4-byte network byte order.
784781
*/
785782
unsigned long extsize;
786-
memcpy(&extsize, (char *) map + offset + 4, 4);
783+
memcpy(&extsize, (char *) cache_mmap + offset + 4, 4);
787784
extsize = ntohl(extsize);
788-
if (read_index_extension(((const char *) map) + offset,
789-
(char *) map + offset + 8,
785+
if (read_index_extension(((const char *) cache_mmap) + offset,
786+
(char *) cache_mmap + offset + 8,
790787
extsize) < 0)
791788
goto unmap;
792789
offset += 8;
@@ -795,7 +792,7 @@ int read_cache(void)
795792
return active_nr;
796793

797794
unmap:
798-
munmap(map, size);
795+
munmap(cache_mmap, cache_mmap_size);
799796
errno = EINVAL;
800797
die("index file corrupt");
801798
}

0 commit comments

Comments
 (0)