This adds a command to pull a commit and dependant objects from an HTTP server.
Signed-Off-By: Daniel Barkalow <[EMAIL PROTECTED]> Index: Makefile =================================================================== --- 50afb5dd4184842d8da1da8dcb9ca6a591dfc5b0/Makefile (mode:100644 sha1:803f1d49c436efa570d779db6d350efbceb29ddd) +++ f7f62e0d2a822ad0937fd98a826f65ac7f938217/Makefile (mode:100644 sha1:a3d26213c085e8b6bbc1ec352df0996e558e7c38) @@ -15,7 +15,7 @@ PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ - check-files ls-tree merge-base merge-cache unpack-file + check-files ls-tree merge-base merge-cache unpack-file http-pull all: $(PROG) @@ -81,6 +81,11 @@ unpack-file: unpack-file.o $(LIB_FILE) $(CC) $(CFLAGS) -o unpack-file unpack-file.o $(LIBS) +http-pull: LIBS += -lcurl + +http-pull: http-pull.o $(LIB_FILE) + $(CC) $(CFLAGS) -o http-pull http-pull.o $(LIBS) + blob.o: $(LIB_H) cat-file.o: $(LIB_H) check-files.o: $(LIB_H) @@ -105,6 +110,7 @@ usage.o: $(LIB_H) unpack-file.o: $(LIB_H) write-tree.o: $(LIB_H) +http-pull.o: $(LIB_H) clean: rm -f *.o $(PROG) $(LIB_FILE) Index: http-pull.c =================================================================== --- /dev/null (tree:50afb5dd4184842d8da1da8dcb9ca6a591dfc5b0) +++ f7f62e0d2a822ad0937fd98a826f65ac7f938217/http-pull.c (mode:100644 sha1:bd251f9e0748784bbd2cd5cf720f126d852fe888) @@ -0,0 +1,170 @@ +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include "cache.h" +#include "commit.h" +#include <errno.h> +#include <stdio.h> + +#include <curl/curl.h> +#include <curl/easy.h> + +static CURL *curl; + +static char *base; + +static int tree = 0; +static int commits = 0; +static int all = 0; + +static int has(unsigned char *sha1) +{ + char *filename = sha1_file_name(sha1); + struct stat st; + + if (!stat(filename, &st)) + return 1; + return 0; +} + +static int fetch(unsigned char *sha1) +{ + char *hex = sha1_to_hex(sha1); + char *filename = sha1_file_name(sha1); + + char *url; + char *posn; + FILE *local; + struct stat st; + + if (!stat(filename, &st)) { + return 0; + } + + local = fopen(filename, "w"); + + if (!local) + return error("Couldn't open %s\n", filename); + + curl_easy_setopt(curl, CURLOPT_FILE, local); + + url = malloc(strlen(base) + 50); + strcpy(url, base); + posn = url + strlen(base); + strcpy(posn, "objects/"); + posn += 8; + memcpy(posn, hex, 2); + posn += 2; + *(posn++) = '/'; + strcpy(posn, hex + 2); + + curl_easy_setopt(curl, CURLOPT_URL, url); + + printf("Getting %s\n", hex); + + if (curl_easy_perform(curl)) + return error("Couldn't get %s for %s\n", url, hex); + + fclose(local); + + return 0; +} + +static int process_tree(unsigned char *sha1) +{ + struct tree *tree = lookup_tree(sha1); + struct tree_entry_list *entries; + + if (parse_tree(tree)) + return -1; + + for (entries = tree->entries; entries; entries = entries->next) { + if (fetch(entries->item.tree->object.sha1)) + return -1; + if (entries->directory) { + if (process_tree(entries->item.tree->object.sha1)) + return -1; + } + } + return 0; +} + +static int process_commit(unsigned char *sha1) +{ + struct commit *obj = lookup_commit(sha1); + + if (fetch(sha1)) + return -1; + + if (parse_commit(obj)) + return -1; + + if (tree) { + if (fetch(obj->tree->object.sha1)) + return -1; + if (process_tree(obj->tree->object.sha1)) + return -1; + if (!all) + tree = 0; + } + if (commits) { + struct commit_list *parents = obj->parents; + for (; parents; parents = parents->next) { + if (has(parents->item->object.sha1)) + continue; + if (fetch(parents->item->object.sha1)) { + /* The server might not have it, and + * we don't mind. + */ + continue; + } + if (process_commit(parents->item->object.sha1)) + return -1; + } + } + return 0; +} + +int main(int argc, char **argv) +{ + char *commit_id; + char *url; + int arg = 1; + unsigned char sha1[20]; + + while (arg < argc && argv[arg][0] == '-') { + if (argv[arg][1] == 't') { + tree = 1; + } else if (argv[arg][1] == 'c') { + commits = 1; + } else if (argv[arg][1] == 'a') { + all = 1; + tree = 1; + commits = 1; + } + arg++; + } + if (argc < arg + 2) { + usage("http-pull [-c] [-t] [-a] commit-id url"); + return 1; + } + commit_id = argv[arg]; + url = argv[arg + 1]; + + get_sha1_hex(commit_id, sha1); + + curl_global_init(CURL_GLOBAL_ALL); + + curl = curl_easy_init(); + + base = url; + + if (fetch(sha1)) + return 1; + if (process_commit(sha1)) + return 1; + + curl_global_cleanup(); + return 0; +} - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html