Add support for cloning over http
This patch implements basic support for cloning over http, based on the work on git-http-backend by Shawn O. Pearce. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
This commit is contained in:
		
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @@ -56,6 +56,7 @@ OBJECTS += html.o | |||||||
| OBJECTS += parsing.o | OBJECTS += parsing.o | ||||||
| OBJECTS += shared.o | OBJECTS += shared.o | ||||||
| OBJECTS += ui-blob.o | OBJECTS += ui-blob.o | ||||||
|  | OBJECTS += ui-clone.o | ||||||
| OBJECTS += ui-commit.o | OBJECTS += ui-commit.o | ||||||
| OBJECTS += ui-diff.o | OBJECTS += ui-diff.o | ||||||
| OBJECTS += ui-log.o | OBJECTS += ui-log.o | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								cmd.c
									
									
									
									
									
								
							| @@ -11,6 +11,7 @@ | |||||||
| #include "cache.h" | #include "cache.h" | ||||||
| #include "ui-shared.h" | #include "ui-shared.h" | ||||||
| #include "ui-blob.h" | #include "ui-blob.h" | ||||||
|  | #include "ui-clone.h" | ||||||
| #include "ui-commit.h" | #include "ui-commit.h" | ||||||
| #include "ui-diff.h" | #include "ui-diff.h" | ||||||
| #include "ui-log.h" | #include "ui-log.h" | ||||||
| @@ -22,6 +23,11 @@ | |||||||
| #include "ui-tag.h" | #include "ui-tag.h" | ||||||
| #include "ui-tree.h" | #include "ui-tree.h" | ||||||
|  |  | ||||||
|  | static void HEAD_fn(struct cgit_context *ctx) | ||||||
|  | { | ||||||
|  | 	cgit_clone_head(ctx); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void about_fn(struct cgit_context *ctx) | static void about_fn(struct cgit_context *ctx) | ||||||
| { | { | ||||||
| 	if (ctx->repo) | 	if (ctx->repo) | ||||||
| @@ -45,6 +51,11 @@ static void diff_fn(struct cgit_context *ctx) | |||||||
| 	cgit_print_diff(ctx->qry.sha1, ctx->qry.sha2, ctx->qry.path); | 	cgit_print_diff(ctx->qry.sha1, ctx->qry.sha2, ctx->qry.path); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void info_fn(struct cgit_context *ctx) | ||||||
|  | { | ||||||
|  | 	cgit_clone_info(ctx); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void log_fn(struct cgit_context *ctx) | static void log_fn(struct cgit_context *ctx) | ||||||
| { | { | ||||||
| 	cgit_print_log(ctx->qry.sha1, ctx->qry.ofs, ctx->cfg.max_commit_count, | 	cgit_print_log(ctx->qry.sha1, ctx->qry.ofs, ctx->cfg.max_commit_count, | ||||||
| @@ -59,6 +70,11 @@ static void ls_cache_fn(struct cgit_context *ctx) | |||||||
| 	cache_ls(ctx->cfg.cache_root); | 	cache_ls(ctx->cfg.cache_root); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void objects_fn(struct cgit_context *ctx) | ||||||
|  | { | ||||||
|  | 	cgit_clone_objects(ctx); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void repolist_fn(struct cgit_context *ctx) | static void repolist_fn(struct cgit_context *ctx) | ||||||
| { | { | ||||||
| 	cgit_print_repolist(); | 	cgit_print_repolist(); | ||||||
| @@ -102,12 +118,15 @@ static void tree_fn(struct cgit_context *ctx) | |||||||
| struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx) | struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx) | ||||||
| { | { | ||||||
| 	static struct cgit_cmd cmds[] = { | 	static struct cgit_cmd cmds[] = { | ||||||
|  | 		def_cmd(HEAD, 1, 0), | ||||||
| 		def_cmd(about, 0, 1), | 		def_cmd(about, 0, 1), | ||||||
| 		def_cmd(blob, 1, 0), | 		def_cmd(blob, 1, 0), | ||||||
| 		def_cmd(commit, 1, 1), | 		def_cmd(commit, 1, 1), | ||||||
| 		def_cmd(diff, 1, 1), | 		def_cmd(diff, 1, 1), | ||||||
|  | 		def_cmd(info, 1, 0), | ||||||
| 		def_cmd(log, 1, 1), | 		def_cmd(log, 1, 1), | ||||||
| 		def_cmd(ls_cache, 0, 0), | 		def_cmd(ls_cache, 0, 0), | ||||||
|  | 		def_cmd(objects, 1, 0), | ||||||
| 		def_cmd(patch, 1, 0), | 		def_cmd(patch, 1, 0), | ||||||
| 		def_cmd(refs, 1, 1), | 		def_cmd(refs, 1, 1), | ||||||
| 		def_cmd(repolist, 0, 0), | 		def_cmd(repolist, 0, 0), | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								html.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								html.c
									
									
									
									
									
								
							| @@ -51,6 +51,13 @@ void htmlf(const char *format, ...) | |||||||
| 	html(buf); | 	html(buf); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void html_status(int code, int more_headers) | ||||||
|  | { | ||||||
|  | 	htmlf("Status: %d\n", code); | ||||||
|  | 	if (!more_headers) | ||||||
|  | 		html("\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
| void html_txt(char *txt) | void html_txt(char *txt) | ||||||
| { | { | ||||||
| 	char *t = txt; | 	char *t = txt; | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								html.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								html.h
									
									
									
									
									
								
							| @@ -5,6 +5,7 @@ extern int htmlfd; | |||||||
|  |  | ||||||
| extern void html(const char *txt); | extern void html(const char *txt); | ||||||
| extern void htmlf(const char *format,...); | extern void htmlf(const char *format,...); | ||||||
|  | extern void html_status(int code, int more_headers); | ||||||
| extern void html_txt(char *txt); | extern void html_txt(char *txt); | ||||||
| extern void html_ntxt(int len, char *txt); | extern void html_ntxt(int len, char *txt); | ||||||
| extern void html_attr(char *txt); | extern void html_attr(char *txt); | ||||||
|   | |||||||
							
								
								
									
										104
									
								
								ui-clone.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								ui-clone.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | |||||||
|  | /* ui-clone.c: functions for http cloning, based on | ||||||
|  |  * git's http-backend.c by Shawn O. Pearce | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2008 Lars Hjemli | ||||||
|  |  * | ||||||
|  |  * Licensed under GNU General Public License v2 | ||||||
|  |  *   (see COPYING for full license text) | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "cgit.h" | ||||||
|  | #include "html.h" | ||||||
|  | #include "ui-shared.h" | ||||||
|  |  | ||||||
|  | static int print_ref_info(const char *refname, const unsigned char *sha1, | ||||||
|  |                           int flags, void *cb_data) | ||||||
|  | { | ||||||
|  | 	struct object *obj; | ||||||
|  |  | ||||||
|  | 	if (!(obj = parse_object(sha1))) | ||||||
|  | 		return 0; | ||||||
|  |  | ||||||
|  | 	if (!strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/")) | ||||||
|  | 		htmlf("%s\t%s\n", sha1_to_hex(sha1), refname); | ||||||
|  | 	else if (!prefixcmp(refname, "refs/tags") && obj->type == OBJ_TAG) { | ||||||
|  | 		if (!(obj = deref_tag(obj, refname, 0))) | ||||||
|  | 			return 0; | ||||||
|  | 		htmlf("%s\t%s\n", sha1_to_hex(sha1), refname); | ||||||
|  | 		htmlf("%s\t%s^{}\n", sha1_to_hex(obj->sha1), refname); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void print_pack_info(struct cgit_context *ctx) | ||||||
|  | { | ||||||
|  | 	struct packed_git *pack; | ||||||
|  | 	int ofs; | ||||||
|  |  | ||||||
|  | 	ctx->page.mimetype = "text/plain"; | ||||||
|  | 	ctx->page.filename = "objects/info/packs"; | ||||||
|  | 	cgit_print_http_headers(ctx); | ||||||
|  | 	ofs = strlen(ctx->repo->path) + strlen("/objects/pack/"); | ||||||
|  | 	prepare_packed_git(); | ||||||
|  | 	for (pack = packed_git; pack; pack = pack->next) | ||||||
|  | 		if (pack->pack_local) | ||||||
|  | 			htmlf("P %s\n", pack->pack_name + ofs); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void send_file(struct cgit_context *ctx, char *path) | ||||||
|  | { | ||||||
|  | 	struct stat st; | ||||||
|  | 	int err; | ||||||
|  |  | ||||||
|  | 	if (stat(path, &st)) { | ||||||
|  | 		switch (errno) { | ||||||
|  | 		case ENOENT: | ||||||
|  | 			err = 404; | ||||||
|  | 			break; | ||||||
|  | 		case EACCES: | ||||||
|  | 			err = 403; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			err = 400; | ||||||
|  | 		} | ||||||
|  | 		html_status(err, 0); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	ctx->page.mimetype = "application/octet-stream"; | ||||||
|  | 	ctx->page.filename = path; | ||||||
|  | 	if (prefixcmp(ctx->repo->path, path)) | ||||||
|  | 		ctx->page.filename += strlen(ctx->repo->path) + 1; | ||||||
|  | 	cgit_print_http_headers(ctx); | ||||||
|  | 	html_include(path); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void cgit_clone_info(struct cgit_context *ctx) | ||||||
|  | { | ||||||
|  | 	if (!ctx->qry.path || strcmp(ctx->qry.path, "refs")) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	ctx->page.mimetype = "text/plain"; | ||||||
|  | 	ctx->page.filename = "info/refs"; | ||||||
|  | 	cgit_print_http_headers(ctx); | ||||||
|  | 	for_each_ref(print_ref_info, ctx); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void cgit_clone_objects(struct cgit_context *ctx) | ||||||
|  | { | ||||||
|  | 	if (!ctx->qry.path) { | ||||||
|  | 		html_status(400, 0); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!strcmp(ctx->qry.path, "info/packs")) { | ||||||
|  | 		print_pack_info(ctx); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	send_file(ctx, git_path("objects/%s", ctx->qry.path)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void cgit_clone_head(struct cgit_context *ctx) | ||||||
|  | { | ||||||
|  | 	send_file(ctx, git_path("%s", "HEAD")); | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								ui-clone.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ui-clone.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | #ifndef UI_CLONE_H | ||||||
|  | #define UI_CLONE_H | ||||||
|  |  | ||||||
|  | void cgit_clone_info(struct cgit_context *ctx); | ||||||
|  | void cgit_clone_objects(struct cgit_context *ctx); | ||||||
|  | void cgit_clone_head(struct cgit_context *ctx); | ||||||
|  |  | ||||||
|  | #endif /* UI_CLONE_H */ | ||||||
		Reference in New Issue
	
	Block a user
	 Lars Hjemli
					Lars Hjemli