зеркало из 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 DEFAULT_DB_ENVIRONMENT ".git/objects"
|
||||
#define ALTERNATE_DB_ENVIRONMENT "SHA1_FILE_DIRECTORIES"
|
||||
|
||||
#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>*]");
|
||||
}
|
||||
|
||||
sha1_dir = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT;
|
||||
sha1_dir = get_object_directory();
|
||||
for (i = 0; i < 256; i++) {
|
||||
static char dir[4096];
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
* careful about using it. Do a "strdup()" if you need to save the
|
||||
* 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)
|
||||
{
|
||||
int i;
|
||||
static char *name, *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);
|
||||
base = xmalloc(len + 60);
|
||||
memcpy(base, sha1_file_directory, len);
|
||||
|
@ -120,16 +136,74 @@ char *sha1_file_name(const unsigned char *sha1)
|
|||
base[len+3] = '/';
|
||||
name = base + len + 1;
|
||||
}
|
||||
for (i = 0; i < 20; i++) {
|
||||
static char hex[] = "0123456789abcdef";
|
||||
unsigned int val = sha1[i];
|
||||
char *pos = name + i*2 + (i > 0);
|
||||
*pos++ = hex[val >> 4];
|
||||
*pos = hex[val & 0xf];
|
||||
}
|
||||
fill_sha1_path(name, sha1);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
char *filename = sha1_file_name(sha1);
|
||||
struct stat st;
|
||||
void *map;
|
||||
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);
|
||||
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 */
|
||||
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);
|
||||
close(fd);
|
||||
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());
|
||||
|
||||
fd = mkstemp(tmpfile);
|
||||
if (fd < 0) {
|
||||
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)
|
||||
{
|
||||
char *filename = sha1_file_name(sha1);
|
||||
struct stat st;
|
||||
|
||||
if (!stat(filename, &st))
|
||||
return 1;
|
||||
return 0;
|
||||
return !!find_sha1_file(sha1, &st);
|
||||
}
|
||||
|
||||
int index_fd(unsigned char *sha1, int fd, struct stat *st)
|
||||
|
|
Загрузка…
Ссылка в новой задаче