зеркало из https://github.com/microsoft/git.git
Introduce SHA1_FILE_DIRECTORIES to support multiple object databases.
SHA1_FILE_DIRECTORIES environment variable is a colon separated paths used when looking for SHA1 files not found in the usual place for reading. Creating a new SHA1 file does not use this alternate object database location mechanism. This is useful to archive older, rarely used objects into separate directories. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Родитель
e7d3dd248f
Коммит
ace1534d6f
1
cache.h
1
cache.h
|
@ -101,6 +101,7 @@ unsigned int active_nr, active_alloc, active_cache_changed;
|
||||||
|
|
||||||
#define DB_ENVIRONMENT "SHA1_FILE_DIRECTORY"
|
#define DB_ENVIRONMENT "SHA1_FILE_DIRECTORY"
|
||||||
#define DEFAULT_DB_ENVIRONMENT ".git/objects"
|
#define DEFAULT_DB_ENVIRONMENT ".git/objects"
|
||||||
|
#define ALTERNATE_DB_ENVIRONMENT "SHA1_FILE_DIRECTORIES"
|
||||||
|
|
||||||
#define get_object_directory() (getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT)
|
#define get_object_directory() (getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT)
|
||||||
|
|
||||||
|
|
|
@ -306,7 +306,7 @@ int main(int argc, char **argv)
|
||||||
usage("fsck-cache [--tags] [[--unreachable] [--cache] <head-sha1>*]");
|
usage("fsck-cache [--tags] [[--unreachable] [--cache] <head-sha1>*]");
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1_dir = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT;
|
sha1_dir = get_object_directory();
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 256; i++) {
|
||||||
static char dir[4096];
|
static char dir[4096];
|
||||||
sprintf(dir, "%s/%02x", sha1_dir, i);
|
sprintf(dir, "%s/%02x", sha1_dir, i);
|
||||||
|
|
110
sha1_file.c
110
sha1_file.c
|
@ -100,18 +100,34 @@ char * sha1_to_hex(const unsigned char *sha1)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 20; i++) {
|
||||||
|
static char hex[] = "0123456789abcdef";
|
||||||
|
unsigned int val = sha1[i];
|
||||||
|
char *pos = pathbuf + i*2 + (i > 0);
|
||||||
|
*pos++ = hex[val >> 4];
|
||||||
|
*pos = hex[val & 0xf];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE! This returns a statically allocated buffer, so you have to be
|
* NOTE! This returns a statically allocated buffer, so you have to be
|
||||||
* careful about using it. Do a "strdup()" if you need to save the
|
* careful about using it. Do a "strdup()" if you need to save the
|
||||||
* filename.
|
* filename.
|
||||||
|
*
|
||||||
|
* Also note that this returns the location for creating. Reading
|
||||||
|
* SHA1 file can happen from any alternate directory listed in the
|
||||||
|
* SHA1_FILE_DIRECTORIES environment variable if it is not found in
|
||||||
|
* the primary object database.
|
||||||
*/
|
*/
|
||||||
char *sha1_file_name(const unsigned char *sha1)
|
char *sha1_file_name(const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
static char *name, *base;
|
static char *name, *base;
|
||||||
|
|
||||||
if (!base) {
|
if (!base) {
|
||||||
char *sha1_file_directory = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT;
|
char *sha1_file_directory = get_object_directory();
|
||||||
int len = strlen(sha1_file_directory);
|
int len = strlen(sha1_file_directory);
|
||||||
base = xmalloc(len + 60);
|
base = xmalloc(len + 60);
|
||||||
memcpy(base, sha1_file_directory, len);
|
memcpy(base, sha1_file_directory, len);
|
||||||
|
@ -120,16 +136,74 @@ char *sha1_file_name(const unsigned char *sha1)
|
||||||
base[len+3] = '/';
|
base[len+3] = '/';
|
||||||
name = base + len + 1;
|
name = base + len + 1;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 20; i++) {
|
fill_sha1_path(name, sha1);
|
||||||
static char hex[] = "0123456789abcdef";
|
|
||||||
unsigned int val = sha1[i];
|
|
||||||
char *pos = name + i*2 + (i > 0);
|
|
||||||
*pos++ = hex[val >> 4];
|
|
||||||
*pos = hex[val & 0xf];
|
|
||||||
}
|
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct alternate_object_database
|
||||||
|
{
|
||||||
|
char *base;
|
||||||
|
char *name;
|
||||||
|
} *alt_odb;
|
||||||
|
|
||||||
|
static void prepare_alt_odb(void)
|
||||||
|
{
|
||||||
|
int pass, totlen, i;
|
||||||
|
void *buf;
|
||||||
|
const char *cp, *last;
|
||||||
|
char *op = 0;
|
||||||
|
const char *alt = getenv(ALTERNATE_DB_ENVIRONMENT) ? : "";
|
||||||
|
|
||||||
|
for (totlen = pass = 0; pass < 2; pass++) {
|
||||||
|
last = alt;
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
cp = strchr(last, ':') ? : last + strlen(last);
|
||||||
|
if (last != cp) {
|
||||||
|
/* 43 = 40-byte + 2 '/' + terminating NUL */
|
||||||
|
int pfxlen = cp - last;
|
||||||
|
int entlen = pfxlen + 43;
|
||||||
|
if (pass == 0)
|
||||||
|
totlen += entlen;
|
||||||
|
else {
|
||||||
|
alt_odb[i].base = op;
|
||||||
|
alt_odb[i].name = op + pfxlen + 1;
|
||||||
|
memcpy(op, last, pfxlen);
|
||||||
|
op[pfxlen] = op[pfxlen + 3] = '/';
|
||||||
|
op[entlen-1] = 0;
|
||||||
|
op += entlen;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (*cp && *cp == ':')
|
||||||
|
cp++;
|
||||||
|
last = cp;
|
||||||
|
} while (*cp);
|
||||||
|
if (pass)
|
||||||
|
break;
|
||||||
|
alt_odb = buf = xmalloc(sizeof(*alt_odb) * (i + 1) + totlen);
|
||||||
|
alt_odb[i].base = alt_odb[i].name = 0;
|
||||||
|
op = (char*)(&alt_odb[i+1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *find_sha1_file(const unsigned char *sha1, struct stat *st)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *name = sha1_file_name(sha1);
|
||||||
|
|
||||||
|
if (!stat(name, st))
|
||||||
|
return name;
|
||||||
|
if (!alt_odb)
|
||||||
|
prepare_alt_odb();
|
||||||
|
for (i = 0; (name = alt_odb[i].name) != NULL; i++) {
|
||||||
|
fill_sha1_path(name, sha1);
|
||||||
|
if (!stat(alt_odb[i].base, st))
|
||||||
|
return alt_odb[i].base;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int check_sha1_signature(unsigned char *sha1, void *map, unsigned long size, const char *type)
|
int check_sha1_signature(unsigned char *sha1, void *map, unsigned long size, const char *type)
|
||||||
{
|
{
|
||||||
char header[100];
|
char header[100];
|
||||||
|
@ -145,10 +219,15 @@ int check_sha1_signature(unsigned char *sha1, void *map, unsigned long size, con
|
||||||
|
|
||||||
void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
|
void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
|
||||||
{
|
{
|
||||||
char *filename = sha1_file_name(sha1);
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
void *map;
|
void *map;
|
||||||
int fd;
|
int fd;
|
||||||
|
char *filename = find_sha1_file(sha1, &st);
|
||||||
|
|
||||||
|
if (!filename) {
|
||||||
|
error("cannot map sha1 file %s", sha1_to_hex(sha1));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY | sha1_file_open_flag);
|
fd = open(filename, O_RDONLY | sha1_file_open_flag);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -167,10 +246,6 @@ void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
|
||||||
/* If it failed once, it will probably fail again. Stop using O_NOATIME */
|
/* If it failed once, it will probably fail again. Stop using O_NOATIME */
|
||||||
sha1_file_open_flag = 0;
|
sha1_file_open_flag = 0;
|
||||||
}
|
}
|
||||||
if (fstat(fd, &st) < 0) {
|
|
||||||
close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
close(fd);
|
close(fd);
|
||||||
if (-1 == (int)(long)map)
|
if (-1 == (int)(long)map)
|
||||||
|
@ -315,6 +390,7 @@ int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned cha
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory());
|
snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory());
|
||||||
|
|
||||||
fd = mkstemp(tmpfile);
|
fd = mkstemp(tmpfile);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "unable to create temporary sha1 filename %s: %s", tmpfile, strerror(errno));
|
fprintf(stderr, "unable to create temporary sha1 filename %s: %s", tmpfile, strerror(errno));
|
||||||
|
@ -442,12 +518,8 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd)
|
||||||
|
|
||||||
int has_sha1_file(const unsigned char *sha1)
|
int has_sha1_file(const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
char *filename = sha1_file_name(sha1);
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
return !!find_sha1_file(sha1, &st);
|
||||||
if (!stat(filename, &st))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int index_fd(unsigned char *sha1, int fd, struct stat *st)
|
int index_fd(unsigned char *sha1, int fd, struct stat *st)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче