threads / patch / 1531

patchSupport packs in local-pull

Subject: [PATCH] Support packs in local-pull

## tl;dr

3 messages between Aug 16, 2005 and Aug 16, 2005. Diffs are folded; open one to read it.

replies: 2people: 1as markdown or json

Daniel Barkalow· Aug 16, 2005, 04:09 UTC · lore

[PATCH 0/2] Fix local-pull on packed repository

This adds essentially the same logic to local-pull that http-pull has, with the exception that it reads the index out of the source directory, rather than copying it. This, in turn, requires the ability to use an index file in some other directory.

 1: Use index file in another directory
 2: Copy/link/symlink pack files as appropriate
	-Daniel
*This .sig left intentionally blank*
Daniel Barkalow· Aug 16, 2005, 04:10 UTC · re: Daniel Barkalow · lore

[PATCH] Add function to read an index file from an arbitrary filename.

Note that the pack file has to be in the usual location if it gets installed later.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
 cache.h     |    2 ++
 sha1_file.c |   10 ++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)
59e5c6d163edae5da6136560d48a4750cceacdc6
Show changes to 2 files +10 −2

cache.h, sha1_file.c

diff --git a/cache.h b/cache.h
--- a/cache.h
+++ b/cache.h
@@ -319,6 +319,8 @@ extern int get_ack(int fd, unsigned char
 extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match);
 
 extern struct packed_git *parse_pack_index(unsigned char *sha1);
+extern struct packed_git *parse_pack_index_file(unsigned char *sha1, 
+						char *idx_path);
 
 extern void prepare_packed_git(void);
 extern void install_packed_git(struct packed_git *pack);
diff --git a/sha1_file.c b/sha1_file.c
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -476,12 +476,18 @@ struct packed_git *add_packed_git(char *
 
 struct packed_git *parse_pack_index(unsigned char *sha1)
 {
+	char *path = sha1_pack_index_name(sha1);
+	return parse_pack_index_file(sha1, path);
+}
+
+struct packed_git *parse_pack_index_file(unsigned char *sha1, char *idx_path)
+{
 	struct packed_git *p;
 	unsigned long idx_size;
 	void *idx_map;
-	char *path = sha1_pack_index_name(sha1);
+	char *path;
 
-	if (check_packed_git_idx(path, &idx_size, &idx_map))
+	if (check_packed_git_idx(idx_path, &idx_size, &idx_map))
 		return NULL;
 
 	path = sha1_pack_name(sha1);
Daniel Barkalow· Aug 16, 2005, 04:10 UTC · re: Daniel Barkalow · lore

If it doesn't find an object, it looks for an index that contains it and uses the same methods on that instead.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
 local-pull.c |  112 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 91 insertions(+), 21 deletions(-)
aafbc7fb9ae059b9c9afa42e8d2c0548ea960f9f
Show changes to local-pull.c +91 −21
diff --git a/local-pull.c b/local-pull.c
--- a/local-pull.c
+++ b/local-pull.c
@@ -15,34 +15,54 @@ void prefetch(unsigned char *sha1)
 {
 }
 
-int fetch(unsigned char *sha1)
+static struct packed_git *packs = NULL;
+
+void setup_index(unsigned char *sha1)
 {
-	static int object_name_start = -1;
-	static char filename[PATH_MAX];
-	char *hex = sha1_to_hex(sha1);
-	const char *dest_filename = sha1_file_name(sha1);
+	struct packed_git *new_pack;
+	char filename[PATH_MAX];
+	strcpy(filename, path);
+	strcat(filename, "/objects/pack/pack-");
+	strcat(filename, sha1_to_hex(sha1));
+	strcat(filename, ".idx");
+	new_pack = parse_pack_index_file(sha1, filename);
+	new_pack->next = packs;
+	packs = new_pack;
+}
 
-	if (object_name_start < 0) {
-		strcpy(filename, path); /* e.g. git.git */
-		strcat(filename, "/objects/");
-		object_name_start = strlen(filename);
+int setup_indices()
+{
+	DIR *dir;
+	struct dirent *de;
+	char filename[PATH_MAX];
+	unsigned char sha1[20];
+	sprintf(filename, "%s/objects/pack/", path);
+	dir = opendir(filename);
+	while ((de = readdir(dir)) != NULL) {
+		int namelen = strlen(de->d_name);
+		if (namelen != 50 || 
+		    strcmp(de->d_name + namelen - 5, ".pack"))
+			continue;
+		get_sha1_hex(sha1, de->d_name + 5);
+		setup_index(sha1);
 	}
-	filename[object_name_start+0] = hex[0];
-	filename[object_name_start+1] = hex[1];
-	filename[object_name_start+2] = '/';
-	strcpy(filename + object_name_start + 3, hex + 2);
+	return 0;
+}
+
+int copy_file(const char *source, const char *dest, const char *hex)
+{
 	if (use_link) {
-		if (!link(filename, dest_filename)) {
+		if (!link(source, dest)) {
 			pull_say("link %s\n", hex);
 			return 0;
 		}
 		/* If we got ENOENT there is no point continuing. */
 		if (errno == ENOENT) {
-			fprintf(stderr, "does not exist %s\n", filename);
+			fprintf(stderr, "does not exist %s\n", source);
 			return -1;
 		}
 	}
-	if (use_symlink && !symlink(filename, dest_filename)) {
+	if (use_symlink && !symlink(source, dest)) {
 		pull_say("symlink %s\n", hex);
 		return 0;
 	}
@@ -50,25 +70,25 @@ int fetch(unsigned char *sha1)
 		int ifd, ofd, status;
 		struct stat st;
 		void *map;
-		ifd = open(filename, O_RDONLY);
+		ifd = open(source, O_RDONLY);
 		if (ifd < 0 || fstat(ifd, &st) < 0) {
 			close(ifd);
-			fprintf(stderr, "cannot open %s\n", filename);
+			fprintf(stderr, "cannot open %s\n", source);
 			return -1;
 		}
 		map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, ifd, 0);
 		close(ifd);
 		if (map == MAP_FAILED) {
-			fprintf(stderr, "cannot mmap %s\n", filename);
+			fprintf(stderr, "cannot mmap %s\n", source);
 			return -1;
 		}
-		ofd = open(dest_filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
+		ofd = open(dest, O_WRONLY | O_CREAT | O_EXCL, 0666);
 		status = ((ofd < 0) ||
 			  (write(ofd, map, st.st_size) != st.st_size));
 		munmap(map, st.st_size);
 		close(ofd);
 		if (status)
-			fprintf(stderr, "cannot write %s\n", dest_filename);
+			fprintf(stderr, "cannot write %s\n", dest);
 		else
 			pull_say("copy %s\n", hex);
 		return status;
@@ -77,6 +97,56 @@ int fetch(unsigned char *sha1)
 	return -1;
 }
 
+int fetch_pack(unsigned char *sha1)
+{
+	struct packed_git *target;
+	char filename[PATH_MAX];
+	if (setup_indices())
+		return -1;
+	target = find_sha1_pack(sha1, packs);
+	if (!target)
+		return error("Couldn't find %s: not separate or in any pack", 
+			     sha1_to_hex(sha1));
+	if (get_verbosely) {
+		fprintf(stderr, "Getting pack %s\n",
+			sha1_to_hex(target->sha1));
+		fprintf(stderr, " which contains %s\n",
+			sha1_to_hex(sha1));
+	}
+	sprintf(filename, "%s/objects/pack/pack-%s.pack", 
+		path, sha1_to_hex(sha1));
+	copy_file(filename, sha1_pack_name(sha1), sha1_to_hex(sha1));
+	sprintf(filename, "%s/objects/pack/pack-%s.idx", 
+		path, sha1_to_hex(sha1));
+	copy_file(filename, sha1_pack_index_name(sha1), sha1_to_hex(sha1));
+	install_packed_git(target);
+	return 0;
+}
+
+int fetch_file(unsigned char *sha1)
+{
+	static int object_name_start = -1;
+	static char filename[PATH_MAX];
+	char *hex = sha1_to_hex(sha1);
+	const char *dest_filename = sha1_file_name(sha1);
+
+ 	if (object_name_start < 0) {
+		strcpy(filename, path); /* e.g. git.git */
+		strcat(filename, "/objects/");
+		object_name_start = strlen(filename);
+	}
+	filename[object_name_start+0] = hex[0];
+	filename[object_name_start+1] = hex[1];
+	filename[object_name_start+2] = '/';
+	strcpy(filename + object_name_start + 3, hex + 2);
+	return copy_file(filename, dest_filename, hex);
+}
+
+int fetch(unsigned char *sha1)
+{
+	return fetch_file(sha1) && fetch_pack(sha1);
+}
+
 int fetch_ref(char *ref, unsigned char *sha1)
 {
 	static int ref_name_start = -1;

← back to recent threads