razor.c
changeset 56 9c00581c71be
parent 54 9e3907688d78
child 57 016c61ca11e2
     1.1 --- a/razor.c	Tue Oct 23 01:57:39 2007 -0400
     1.2 +++ b/razor.c	Wed Oct 24 00:05:42 2007 -0400
     1.3 @@ -35,20 +35,22 @@
     1.4  #define RAZOR_MAGIC 0x7a7a7a7a
     1.5  #define RAZOR_VERSION 1
     1.6  
     1.7 -#define RAZOR_PACKAGES 0
     1.8 -#define RAZOR_REQUIRES 1
     1.9 -#define RAZOR_PROVIDES 2
    1.10 -#define RAZOR_STRING_POOL 3
    1.11 -#define RAZOR_PACKAGE_POOL 4
    1.12 -#define RAZOR_REQUIRES_POOL 5
    1.13 -#define RAZOR_PROVIDES_POOL 6
    1.14 -#define RAZOR_FILE_TREE 7
    1.15 +#define RAZOR_STRING_POOL 0
    1.16 +#define RAZOR_PACKAGES 1
    1.17 +#define RAZOR_REQUIRES 2
    1.18 +#define RAZOR_PROVIDES 3
    1.19 +#define RAZOR_FILES 4
    1.20 +#define RAZOR_PACKAGE_POOL 5
    1.21 +#define RAZOR_REQUIRES_POOL 6
    1.22 +#define RAZOR_PROVIDES_POOL 7
    1.23 +#define RAZOR_FILE_POOL 8
    1.24  
    1.25  struct razor_package {
    1.26  	unsigned long name;
    1.27  	unsigned long version;
    1.28  	unsigned long requires;
    1.29  	unsigned long provides;
    1.30 +	unsigned long files;
    1.31  };
    1.32  
    1.33  struct razor_property {
    1.34 @@ -59,7 +61,6 @@
    1.35  
    1.36  struct razor_entry {
    1.37  	unsigned long name;
    1.38 -	unsigned long count;
    1.39  	unsigned long start;
    1.40  	unsigned long packages;
    1.41  };
    1.42 @@ -67,12 +68,13 @@
    1.43  struct razor_set {
    1.44  	struct array string_pool;
    1.45   	struct array packages;
    1.46 -	struct array package_pool;
    1.47   	struct array requires;
    1.48   	struct array provides;
    1.49 + 	struct array files;
    1.50 +	struct array package_pool;
    1.51   	struct array requires_pool;
    1.52   	struct array provides_pool;
    1.53 - 	struct array file_tree;
    1.54 + 	struct array file_pool;
    1.55  	struct razor_set_header *header;
    1.56  };
    1.57  
    1.58 @@ -170,14 +172,15 @@
    1.59  }
    1.60  
    1.61  struct razor_set_section razor_sections[] = {
    1.62 +	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
    1.63  	{ RAZOR_PACKAGES,	offsetof(struct razor_set, packages) },
    1.64  	{ RAZOR_REQUIRES,	offsetof(struct razor_set, requires) },
    1.65  	{ RAZOR_PROVIDES,	offsetof(struct razor_set, provides) },
    1.66 -	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
    1.67 +	{ RAZOR_FILES,		offsetof(struct razor_set, files) },
    1.68  	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
    1.69  	{ RAZOR_REQUIRES_POOL,	offsetof(struct razor_set, requires_pool) },
    1.70  	{ RAZOR_PROVIDES_POOL,	offsetof(struct razor_set, provides_pool) },
    1.71 -	{ RAZOR_FILE_TREE,	offsetof(struct razor_set, file_tree) },
    1.72 +	{ RAZOR_FILE_POOL,	offsetof(struct razor_set, file_pool) },
    1.73  };
    1.74  
    1.75  struct razor_set *
    1.76 @@ -737,12 +740,15 @@
    1.77  	}		
    1.78  }
    1.79  
    1.80 +#define RAZOR_ENTRY_LAST 0x80000000ul
    1.81 +#define RAZOR_ENTRY_MASK 0x00fffffful
    1.82 +
    1.83  static void
    1.84  serialize_files(struct razor_set *set,
    1.85  		struct import_directory *d, struct array *array)
    1.86  {
    1.87  	struct import_directory *p, *end;
    1.88 -	struct razor_entry *e;
    1.89 +	struct razor_entry *e = NULL;
    1.90  	unsigned long s;
    1.91  
    1.92  	p = d->files.data;
    1.93 @@ -751,14 +757,15 @@
    1.94  	while (p < end) {
    1.95  		e = array_add(array, sizeof *e);
    1.96  		e->name = p->name;
    1.97 -		e->count = p->files.size / sizeof *p;
    1.98 -		e->start = s;
    1.99 +		e->start = p->count > 0 ? s : 0;
   1.100  		s += p->count;
   1.101  		e->packages = add_to_property_pool(&set->package_pool,
   1.102  						   &p->packages);
   1.103  		array_release(&p->packages);
   1.104  		p++;
   1.105  	}		
   1.106 +	if (e != NULL)
   1.107 +		e->name |= RAZOR_ENTRY_LAST;
   1.108  
   1.109  	p = d->files.data;
   1.110  	end = d->files.data + d->files.size;
   1.111 @@ -823,108 +830,48 @@
   1.112  	}
   1.113  
   1.114  	count_entries(&root);
   1.115 -	array_init(&importer->set->file_tree);
   1.116 +	array_init(&importer->set->files);
   1.117  
   1.118 -	e = array_add(&importer->set->file_tree, sizeof *e);
   1.119 -	e->name = root.name;
   1.120 -	e->count = root.files.size / sizeof *d;
   1.121 +	e = array_add(&importer->set->files, sizeof *e);
   1.122 +	e->name = root.name | RAZOR_ENTRY_LAST;
   1.123  	e->start = 1;
   1.124 +	e->packages = 0;
   1.125  
   1.126 -	serialize_files(importer->set, &root, &importer->set->file_tree);
   1.127 +	serialize_files(importer->set, &root, &importer->set->files);
   1.128  
   1.129  	array_release(&importer->files);
   1.130  }
   1.131  
   1.132 -static const char *
   1.133 -find_dir(struct razor_set *set, struct razor_entry **dir, const char *pattern)
   1.134 +static void
   1.135 +build_package_file_lists(struct razor_set *set)
   1.136  {
   1.137 +	struct razor_package *p, *packages;
   1.138 +	struct array *pkgs;
   1.139  	struct razor_entry *e, *end;
   1.140 -	const char *n, *pool = set->string_pool.data;
   1.141 -	int len;
   1.142 +	unsigned long *r, *q;
   1.143 +	int i, count;
   1.144  
   1.145 -	e = (struct razor_entry *) set->file_tree.data + (*dir)->start;
   1.146 -	end = e + (*dir)->count;
   1.147 +	count = set->packages.size / sizeof *p;
   1.148 +	pkgs = zalloc(count * sizeof *pkgs);
   1.149  
   1.150 +	e = set->files.data;
   1.151 +	end = set->files.data + set->files.size;
   1.152  	while (e < end) {
   1.153 -		n = pool + e->name;
   1.154 -		len = strlen(n);
   1.155 -		if (len == 0) {
   1.156 -			/* FIXME: Shouldn't have 0-length entries... */
   1.157 -			e++;
   1.158 -			continue;
   1.159 -		}
   1.160 -			
   1.161 -		if (strncmp(pattern + 1, n, len) == 0 &&
   1.162 -		    pattern[len + 1] == '/') {
   1.163 -			*dir = e;
   1.164 -			return find_dir(set, dir, pattern + len + 1);
   1.165 +		r = (unsigned long *) set->package_pool.data + e->packages;
   1.166 +		while (~*r) {
   1.167 +			q = array_add(&pkgs[*r++], sizeof *q);
   1.168 +			*q = e - (struct razor_entry *) set->files.data;
   1.169  		}
   1.170  		e++;
   1.171  	}
   1.172  
   1.173 -	return pattern + 1;
   1.174 -}
   1.175 -
   1.176 -static void
   1.177 -list_dir(struct razor_set *set, struct razor_entry *dir,
   1.178 -	 const char *pattern, const char *base)
   1.179 -{
   1.180 -	struct razor_entry *e, *end;
   1.181 -	char *pool = set->string_pool.data;
   1.182 -
   1.183 -	e = (struct razor_entry *) set->file_tree.data + dir->start;
   1.184 -	end = e + dir->count;
   1.185 -
   1.186 -	for ( ; e < end; e++) {
   1.187 -		if (base && base[0] && fnmatch(base, &pool[e->name], 0) != 0)
   1.188 -			continue;
   1.189 -		if (base && pattern)
   1.190 -			printf("%.*s%s%s\n",
   1.191 -			       base - pattern, pattern, pool + e->name,
   1.192 -			       e->count > 0 ? "/" : "");
   1.193 -		else
   1.194 -			printf("%s%s\n", pool + e->name,
   1.195 -			       e->count > 0 ? "/" : "");
   1.196 -		
   1.197 +	packages = set->packages.data;
   1.198 +	for (i = 0; i < count; i++) {
   1.199 +		packages[i].files =
   1.200 +			add_to_property_pool(&set->file_pool, &pkgs[i]);
   1.201 +		array_release(&pkgs[i]);
   1.202  	}
   1.203 -}
   1.204 -
   1.205 -void
   1.206 -razor_set_list_files(struct razor_set *set, const char *pattern)
   1.207 -{
   1.208 -	struct razor_entry *e;
   1.209 -	const char *base;
   1.210 -
   1.211 -	if (pattern == NULL)
   1.212 -		pattern = "/";
   1.213 -
   1.214 -	e = set->file_tree.data;
   1.215 -	base = find_dir(set, &e, pattern);
   1.216 -	if (base == NULL)
   1.217 -		return;
   1.218 -	list_dir(set, e, pattern, base);
   1.219 -}
   1.220 -
   1.221 -void
   1.222 -razor_set_list_file_packages(struct razor_set *set, const char *filename)
   1.223 -{
   1.224 -	struct razor_entry *e;
   1.225 -	struct razor_package *packages, *p;
   1.226 -	const char *pool, *base;
   1.227 -	unsigned long *r;
   1.228 -
   1.229 -	e = set->file_tree.data;
   1.230 -	base = find_dir(set, &e, filename);
   1.231 -	if (base == NULL)
   1.232 -		return;
   1.233 -	
   1.234 -	r = (unsigned long *) set->package_pool.data + e->packages;
   1.235 -	packages = set->packages.data;
   1.236 -	pool = set->string_pool.data;
   1.237 -	while (~*r) {
   1.238 -		p = &packages[*r++];
   1.239 -		printf("%s %s\n", &pool[p->name], &pool[p->version]);
   1.240 -	}
   1.241 +	free(pkgs);
   1.242  }
   1.243  
   1.244  struct razor_set *
   1.245 @@ -958,6 +905,8 @@
   1.246  	remap_links(&importer->set->package_pool, rmap);
   1.247  	free(rmap);
   1.248  
   1.249 +	build_package_file_lists(importer->set);
   1.250 +
   1.251  	set = importer->set;
   1.252  	array_release(&importer->buckets);
   1.253  	free(importer);
   1.254 @@ -1141,6 +1090,167 @@
   1.255  	razor_set_list_property_packages(set, &set->provides, name, version);
   1.256  }
   1.257  
   1.258 +static struct razor_entry *
   1.259 +find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
   1.260 +{
   1.261 +	struct razor_entry *e;
   1.262 +	const char *n, *pool = set->string_pool.data;
   1.263 +	int len;
   1.264 +
   1.265 +	e = (struct razor_entry *) set->files.data + dir->start;
   1.266 +	do {
   1.267 +		n = pool + (e->name & RAZOR_ENTRY_MASK);
   1.268 +		len = strlen(n);
   1.269 +		if (len == 0)
   1.270 +			/* FIXME: Shouldn't have 0-length entries... */
   1.271 +			continue;
   1.272 +			
   1.273 +		if (strcmp(pattern + 1, n) == 0)
   1.274 +			return e;
   1.275 +		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
   1.276 +		    pattern[len + 1] == '/') {
   1.277 +			return find_entry(set, e, pattern + len + 1);
   1.278 +		}
   1.279 +	} while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
   1.280 +
   1.281 +	return NULL;
   1.282 +}
   1.283 +
   1.284 +static void
   1.285 +list_dir(struct razor_set *set, struct razor_entry *dir,
   1.286 +	 const char *prefix, const char *pattern)
   1.287 +{
   1.288 +	struct razor_entry *e;
   1.289 +	const char *n, *pool = set->string_pool.data;
   1.290 +
   1.291 +	e = (struct razor_entry *) set->files.data + dir->start;
   1.292 +	do {
   1.293 +		n = pool + (e->name & RAZOR_ENTRY_MASK);
   1.294 +		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
   1.295 +			continue;
   1.296 +		printf("%s/%s%s\n", prefix, n, e->start > 0 ? "/" : "");
   1.297 +	} while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
   1.298 +}
   1.299 +
   1.300 +void
   1.301 +razor_set_list_files(struct razor_set *set, const char *pattern)
   1.302 +{
   1.303 +	struct razor_entry *e;
   1.304 +	char buffer[512], *p, *base;
   1.305 +
   1.306 +	if (pattern == NULL)
   1.307 +		pattern = "/";
   1.308 +
   1.309 +	strcpy(buffer, pattern);
   1.310 +	e = find_entry(set, set->files.data, buffer);
   1.311 +	if (e && e->start > 0) {
   1.312 +		base = NULL;
   1.313 +	} else {
   1.314 +		p = strrchr(buffer, '/');
   1.315 +		if (p) {
   1.316 +			*p = '\0';
   1.317 +			base = p + 1;
   1.318 +		} else {
   1.319 +			base = NULL;
   1.320 +		}
   1.321 +	}
   1.322 +	e = find_entry(set, set->files.data, buffer);
   1.323 +	if (e->start != 0)
   1.324 +		list_dir(set, e, buffer, base);
   1.325 +}
   1.326 +
   1.327 +void
   1.328 +razor_set_list_file_packages(struct razor_set *set, const char *filename)
   1.329 +{
   1.330 +	struct razor_entry *e;
   1.331 +	struct razor_package *packages, *p;
   1.332 +	const char *pool;
   1.333 +	unsigned long *r;
   1.334 +
   1.335 +	e = find_entry(set, set->files.data, filename);
   1.336 +	if (e == NULL)
   1.337 +		return;
   1.338 +	
   1.339 +	r = (unsigned long *) set->package_pool.data + e->packages;
   1.340 +	packages = set->packages.data;
   1.341 +	pool = set->string_pool.data;
   1.342 +	while (~*r) {
   1.343 +		p = &packages[*r++];
   1.344 +		printf("%s %s\n", &pool[p->name], &pool[p->version]);
   1.345 +	}
   1.346 +}
   1.347 +
   1.348 +static unsigned long *
   1.349 +list_package_files(struct razor_set *set, unsigned long *r,
   1.350 +		   struct razor_entry *dir, unsigned long end,
   1.351 +		   char *prefix)
   1.352 +{
   1.353 +	struct razor_entry *e, *f, *entries;
   1.354 +	unsigned long next;
   1.355 +	char *pool;
   1.356 +	int len;
   1.357 +	
   1.358 +	entries = (struct razor_entry *) set->files.data;
   1.359 +	pool = set->string_pool.data;
   1.360 +
   1.361 +	e = entries + dir->start;
   1.362 +	do {
   1.363 +		if (entries + *r == e) {
   1.364 +			printf("%s/%s\n", prefix,
   1.365 +			       pool + (e->name & RAZOR_ENTRY_MASK));
   1.366 +			r++;
   1.367 +			if (*r >= end)
   1.368 +				break;
   1.369 +		}
   1.370 +	} while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
   1.371 +
   1.372 +	e = entries + dir->start;
   1.373 +	do {
   1.374 +		if (e->start == 0)
   1.375 +			continue;
   1.376 +
   1.377 +		if (e->name & RAZOR_ENTRY_LAST)
   1.378 +			next = end;
   1.379 +		else {
   1.380 +			f = e + 1; 
   1.381 +			while (f->start == 0 && !(f->name & RAZOR_ENTRY_LAST))
   1.382 +				f++;
   1.383 +			if (f->start == 0)
   1.384 +				next = end;
   1.385 +			else
   1.386 +				next = f->start;
   1.387 +		}
   1.388 +
   1.389 +		if (e->start <= *r && *r < next) {
   1.390 +			len = strlen(prefix);
   1.391 +			prefix[len] = '/';
   1.392 +			strcpy(prefix + len + 1,
   1.393 +			       pool + (e->name & RAZOR_ENTRY_MASK));
   1.394 +			r = list_package_files(set, r, e, next, prefix);
   1.395 +			prefix[len] = '\0';
   1.396 +			if (*r >= end)
   1.397 +				break;
   1.398 +		}
   1.399 +	} while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
   1.400 +
   1.401 +	return r;
   1.402 +}
   1.403 +
   1.404 +void
   1.405 +razor_set_list_package_files(struct razor_set *set, const char *name)
   1.406 +{
   1.407 +	struct razor_package *package;
   1.408 +	unsigned long *r, end;
   1.409 +	char buffer[512];
   1.410 +
   1.411 +	package = razor_set_get_package(set, name);
   1.412 +
   1.413 +	r = (unsigned long *) set->file_pool.data + package->files;
   1.414 +	end = set->files.size / sizeof (struct razor_entry);
   1.415 +	buffer[0] = '\0';
   1.416 +	list_package_files(set, r, set->files.data, end, buffer);
   1.417 +}
   1.418 +
   1.419  static void
   1.420  razor_set_validate(struct razor_set *set, struct array *unsatisfied)
   1.421  {