]> gitweb.ps.run Git - ps-cgit/blob - ui-clone.c
CGIT 0.8.3.2
[ps-cgit] / ui-clone.c
1 /* ui-clone.c: functions for http cloning, based on
2  * git's http-backend.c by Shawn O. Pearce
3  *
4  * Copyright (C) 2008 Lars Hjemli
5  *
6  * Licensed under GNU General Public License v2
7  *   (see COPYING for full license text)
8  */
9
10 #include "cgit.h"
11 #include "html.h"
12 #include "ui-shared.h"
13
14 static int print_ref_info(const char *refname, const unsigned char *sha1,
15                           int flags, void *cb_data)
16 {
17         struct object *obj;
18
19         if (!(obj = parse_object(sha1)))
20                 return 0;
21
22         if (!strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/"))
23                 htmlf("%s\t%s\n", sha1_to_hex(sha1), refname);
24         else if (!prefixcmp(refname, "refs/tags") && obj->type == OBJ_TAG) {
25                 if (!(obj = deref_tag(obj, refname, 0)))
26                         return 0;
27                 htmlf("%s\t%s\n", sha1_to_hex(sha1), refname);
28                 htmlf("%s\t%s^{}\n", sha1_to_hex(obj->sha1), refname);
29         }
30         return 0;
31 }
32
33 static void print_pack_info(struct cgit_context *ctx)
34 {
35         struct packed_git *pack;
36         int ofs;
37
38         ctx->page.mimetype = "text/plain";
39         ctx->page.filename = "objects/info/packs";
40         cgit_print_http_headers(ctx);
41         ofs = strlen(ctx->repo->path) + strlen("/objects/pack/");
42         prepare_packed_git();
43         for (pack = packed_git; pack; pack = pack->next)
44                 if (pack->pack_local)
45                         htmlf("P %s\n", pack->pack_name + ofs);
46 }
47
48 static void send_file(struct cgit_context *ctx, char *path)
49 {
50         struct stat st;
51
52         if (stat(path, &st)) {
53                 switch (errno) {
54                 case ENOENT:
55                         html_status(404, "Not found", 0);
56                         break;
57                 case EACCES:
58                         html_status(403, "Forbidden", 0);
59                         break;
60                 default:
61                         html_status(400, "Bad request", 0);
62                 }
63                 return;
64         }
65         ctx->page.mimetype = "application/octet-stream";
66         ctx->page.filename = path;
67         if (prefixcmp(ctx->repo->path, path))
68                 ctx->page.filename += strlen(ctx->repo->path) + 1;
69         cgit_print_http_headers(ctx);
70         html_include(path);
71 }
72
73 void cgit_clone_info(struct cgit_context *ctx)
74 {
75         if (!ctx->qry.path || strcmp(ctx->qry.path, "refs"))
76                 return;
77
78         ctx->page.mimetype = "text/plain";
79         ctx->page.filename = "info/refs";
80         cgit_print_http_headers(ctx);
81         for_each_ref(print_ref_info, ctx);
82 }
83
84 void cgit_clone_objects(struct cgit_context *ctx)
85 {
86         if (!ctx->qry.path) {
87                 html_status(400, "Bad request", 0);
88                 return;
89         }
90
91         if (!strcmp(ctx->qry.path, "info/packs")) {
92                 print_pack_info(ctx);
93                 return;
94         }
95
96         send_file(ctx, git_path("objects/%s", ctx->qry.path));
97 }
98
99 void cgit_clone_head(struct cgit_context *ctx)
100 {
101         send_file(ctx, git_path("%s", "HEAD"));
102 }