Skip to content

Commit

Permalink
Make "read-tree" read the tree into the current directory cache.
Browse files Browse the repository at this point in the history
It will no longer update the actual working directory, just the
cache. To update the working directory, you need to use "checkout-cache".
  • Loading branch information
Linus Torvalds committed Apr 9, 2005
1 parent 197ee8c commit 83adac3
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 50 deletions.
30 changes: 29 additions & 1 deletion checkout-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,34 @@

static int force = 0, quiet = 0;

static void create_directories(const char *path)
{
int len = strlen(path);
char *buf = malloc(len + 1);
const char *slash = path;

while ((slash = strchr(slash+1, '/')) != NULL) {
len = slash - path;
memcpy(buf, path, len);
buf[len] = 0;
mkdir(buf, 0700);
}
}

static int create_file(const char *path, unsigned int mode)
{
int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
if (fd < 0) {
if (errno == ENOENT) {
create_directories(path);
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
}
}
if (fd >= 0)
fchmod(fd, mode);
return fd;
}

static int write_entry(struct cache_entry *ce)
{
int fd;
Expand All @@ -50,7 +78,7 @@ static int write_entry(struct cache_entry *ce)
ce->name, sha1_to_hex(ce->sha1));
return -1;
}
fd = open(ce->name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
fd = create_file(ce->name, ce->st_mode);
if (fd < 0) {
fprintf(stderr, "checkout-cache: unable to create %s (%s)\n",
ce->name, strerror(errno));
Expand Down
102 changes: 53 additions & 49 deletions read-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,83 +5,87 @@
*/
#include "cache.h"

static void create_directories(const char *path)
static int read_one_entry(unsigned char *sha1, const char *pathname, unsigned mode)
{
int len = strlen(path);
char *buf = malloc(len + 1);
const char *slash = path;
int len = strlen(pathname);
unsigned int size = cache_entry_size(len);
struct cache_entry *ce = malloc(size);

while ((slash = strchr(slash+1, '/')) != NULL) {
len = slash - path;
memcpy(buf, path, len);
buf[len] = 0;
mkdir(buf, 0700);
}
}
memset(ce, 0, size);

static int create_file(const char *path)
{
int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
if (fd < 0) {
if (errno == ENOENT) {
create_directories(path);
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
}
}
return fd;
ce->st_mode = mode;
ce->namelen = len;
memcpy(ce->name, pathname, len+1);
memcpy(ce->sha1, sha1, 20);
return add_cache_entry(ce);
}

static int unpack(unsigned char *sha1)
static int read_tree(unsigned char *sha1)
{
void *buffer;
unsigned long size;
char type[20];

buffer = read_sha1_file(sha1, type, &size);
if (!buffer)
usage("unable to read sha1 file");
return -1;
if (strcmp(type, "tree"))
usage("expected a 'tree' node");
return -1;
while (size) {
int len = strlen(buffer)+1;
unsigned char *sha1 = buffer + len;
char *path = strchr(buffer, ' ')+1;
char *data;
unsigned long filesize;
unsigned int mode;
int fd;

if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1)
usage("corrupt 'tree' file");
return -1;

buffer = sha1 + 20;
size -= len + 20;
data = read_sha1_file(sha1, type, &filesize);
if (!data || strcmp(type, "blob"))
usage("tree file refers to bad file data");
fd = create_file(path);
if (fd < 0)
usage("unable to create file");
if (write(fd, data, filesize) != filesize)
usage("unable to write file");
fchmod(fd, mode);
close(fd);
free(data);

if (read_one_entry(sha1, path, mode) < 0)
return -1;
}
return 0;
}

int main(int argc, char **argv)
{
int i, newfd;
unsigned char sha1[20];

if (argc != 2)
usage("read-tree <key>");
if (get_sha1_hex(argv[1], sha1) < 0)
usage("read-tree <key>");
sha1_file_directory = getenv(DB_ENVIRONMENT);
if (!sha1_file_directory)
sha1_file_directory = DEFAULT_DB_ENVIRONMENT;
if (unpack(sha1) < 0)
usage("unpack failed");
return 0;
newfd = open(".dircache/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600);
if (newfd < 0)
usage("unable to create new cachefile");

for (i = 1; i < argc; i++) {
const char *arg = argv[i];

/* "-m" stands for "merge" current directory cache */
if (!strcmp(arg, "-m")) {
if (active_cache) {
fprintf(stderr, "read-tree: cannot merge old cache on top of new\n");
goto out;
}
if (read_cache() < 0) {
fprintf(stderr, "read-tree: corrupt directory cache\n");
goto out;
}
continue;
}
if (get_sha1_hex(arg, sha1) < 0) {
fprintf(stderr, "read-tree [-m] <sha1>\n");
goto out;
}
if (read_tree(sha1) < 0) {
fprintf(stderr, "failed to unpack tree object %s\n", arg);
goto out;
}
}
if (!write_cache(newfd, active_cache, active_nr) && !rename(".dircache/index.lock", ".dircache/index"))
return 0;

out:
unlink(".dircache/index.lock");
exit(1);
}

0 comments on commit 83adac3

Please sign in to comment.