summaryrefslogtreecommitdiffabout
path: root/scan-tree.c
authorJason A. Donenfeld <Jason@zx2c4.com>2010-07-29 15:52:29 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2010-08-04 01:09:32 (UTC)
commit3516502aa0df95ecc241caa30161741f59e4e600 (patch) (unidiff)
tree345978808d18796444729f74eb139c8289bcb1c2 /scan-tree.c
parentf9143171267e39f66a02ad2ecb0da2e8cc7f4142 (diff)
downloadcgit-3516502aa0df95ecc241caa30161741f59e4e600.zip
cgit-3516502aa0df95ecc241caa30161741f59e4e600.tar.gz
cgit-3516502aa0df95ecc241caa30161741f59e4e600.tar.bz2
Add support for 'project-list' option
This option specifies the location of a projectlist file as used by gitweb - when 'scan-tree' is later specified, only the projects listed in the projectlist file will be added. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'scan-tree.c') (more/less context) (ignore whitespace changes)
-rw-r--r--scan-tree.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/scan-tree.c b/scan-tree.c
index 1e18f3c..9bf9b38 100644
--- a/scan-tree.c
+++ b/scan-tree.c
@@ -1,148 +1,185 @@
1/* scan-tree.c
2 *
3 * Copyright (C) 2008-2009 Lars Hjemli
4 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com>
5 *
6 * Licensed under GNU General Public License v2
7 * (see COPYING for full license text)
8 */
9
1#include "cgit.h" 10#include "cgit.h"
2#include "configfile.h" 11#include "configfile.h"
3#include "html.h" 12#include "html.h"
4 13
5#define MAX_PATH 4096 14#define MAX_PATH 4096
6 15
7/* return 1 if path contains a objects/ directory and a HEAD file */ 16/* return 1 if path contains a objects/ directory and a HEAD file */
8static int is_git_dir(const char *path) 17static int is_git_dir(const char *path)
9{ 18{
10 struct stat st; 19 struct stat st;
11 static char buf[MAX_PATH]; 20 static char buf[MAX_PATH];
12 21
13 if (snprintf(buf, MAX_PATH, "%s/objects", path) >= MAX_PATH) { 22 if (snprintf(buf, MAX_PATH, "%s/objects", path) >= MAX_PATH) {
14 fprintf(stderr, "Insanely long path: %s\n", path); 23 fprintf(stderr, "Insanely long path: %s\n", path);
15 return 0; 24 return 0;
16 } 25 }
17 if (stat(buf, &st)) { 26 if (stat(buf, &st)) {
18 if (errno != ENOENT) 27 if (errno != ENOENT)
19 fprintf(stderr, "Error checking path %s: %s (%d)\n", 28 fprintf(stderr, "Error checking path %s: %s (%d)\n",
20 path, strerror(errno), errno); 29 path, strerror(errno), errno);
21 return 0; 30 return 0;
22 } 31 }
23 if (!S_ISDIR(st.st_mode)) 32 if (!S_ISDIR(st.st_mode))
24 return 0; 33 return 0;
25 34
26 sprintf(buf, "%s/HEAD", path); 35 sprintf(buf, "%s/HEAD", path);
27 if (stat(buf, &st)) { 36 if (stat(buf, &st)) {
28 if (errno != ENOENT) 37 if (errno != ENOENT)
29 fprintf(stderr, "Error checking path %s: %s (%d)\n", 38 fprintf(stderr, "Error checking path %s: %s (%d)\n",
30 path, strerror(errno), errno); 39 path, strerror(errno), errno);
31 return 0; 40 return 0;
32 } 41 }
33 if (!S_ISREG(st.st_mode)) 42 if (!S_ISREG(st.st_mode))
34 return 0; 43 return 0;
35 44
36 return 1; 45 return 1;
37} 46}
38 47
39struct cgit_repo *repo; 48struct cgit_repo *repo;
40repo_config_fn config_fn; 49repo_config_fn config_fn;
41 50
42static void repo_config(const char *name, const char *value) 51static void repo_config(const char *name, const char *value)
43{ 52{
44 config_fn(repo, name, value); 53 config_fn(repo, name, value);
45} 54}
46 55
47static void add_repo(const char *base, const char *path, repo_config_fn fn) 56static void add_repo(const char *base, const char *path, repo_config_fn fn)
48{ 57{
49 struct stat st; 58 struct stat st;
50 struct passwd *pwd; 59 struct passwd *pwd;
51 char *p; 60 char *p;
52 size_t size; 61 size_t size;
53 62
54 if (stat(path, &st)) { 63 if (stat(path, &st)) {
55 fprintf(stderr, "Error accessing %s: %s (%d)\n", 64 fprintf(stderr, "Error accessing %s: %s (%d)\n",
56 path, strerror(errno), errno); 65 path, strerror(errno), errno);
57 return; 66 return;
58 } 67 }
59 if (!stat(fmt("%s/noweb", path), &st)) 68 if (!stat(fmt("%s/noweb", path), &st))
60 return; 69 return;
61 if ((pwd = getpwuid(st.st_uid)) == NULL) { 70 if ((pwd = getpwuid(st.st_uid)) == NULL) {
62 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", 71 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n",
63 path, strerror(errno), errno); 72 path, strerror(errno), errno);
64 return; 73 return;
65 } 74 }
66 if (base == path) 75 if (base == path)
67 p = fmt("%s", path); 76 p = fmt("%s", path);
68 else 77 else
69 p = fmt("%s", path + strlen(base) + 1); 78 p = fmt("%s", path + strlen(base) + 1);
70 79
71 if (!strcmp(p + strlen(p) - 5, "/.git")) 80 if (!strcmp(p + strlen(p) - 5, "/.git"))
72 p[strlen(p) - 5] = '\0'; 81 p[strlen(p) - 5] = '\0';
73 82
74 repo = cgit_add_repo(xstrdup(p)); 83 repo = cgit_add_repo(xstrdup(p));
75 repo->name = repo->url; 84 repo->name = repo->url;
76 repo->path = xstrdup(path); 85 repo->path = xstrdup(path);
77 p = (pwd && pwd->pw_gecos) ? strchr(pwd->pw_gecos, ',') : NULL; 86 p = (pwd && pwd->pw_gecos) ? strchr(pwd->pw_gecos, ',') : NULL;
78 if (p) 87 if (p)
79 *p = '\0'; 88 *p = '\0';
80 repo->owner = (pwd ? xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name) : ""); 89 repo->owner = (pwd ? xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name) : "");
81 90
82 p = fmt("%s/description", path); 91 p = fmt("%s/description", path);
83 if (!stat(p, &st)) 92 if (!stat(p, &st))
84 readfile(p, &repo->desc, &size); 93 readfile(p, &repo->desc, &size);
85 94
86 p = fmt("%s/README.html", path); 95 p = fmt("%s/README.html", path);
87 if (!stat(p, &st)) 96 if (!stat(p, &st))
88 repo->readme = "README.html"; 97 repo->readme = "README.html";
89 98
90 p = fmt("%s/cgitrc", path); 99 p = fmt("%s/cgitrc", path);
91 if (!stat(p, &st)) { 100 if (!stat(p, &st)) {
92 config_fn = fn; 101 config_fn = fn;
93 parse_configfile(xstrdup(p), &repo_config); 102 parse_configfile(xstrdup(p), &repo_config);
94 } 103 }
95} 104}
96 105
97static void scan_path(const char *base, const char *path, repo_config_fn fn) 106static void scan_path(const char *base, const char *path, repo_config_fn fn)
98{ 107{
99 DIR *dir; 108 DIR *dir;
100 struct dirent *ent; 109 struct dirent *ent;
101 char *buf; 110 char *buf;
102 struct stat st; 111 struct stat st;
103 112
104 if (is_git_dir(path)) { 113 if (is_git_dir(path)) {
105 add_repo(base, path, fn); 114 add_repo(base, path, fn);
106 return; 115 return;
107 } 116 }
108 if (is_git_dir(fmt("%s/.git", path))) { 117 if (is_git_dir(fmt("%s/.git", path))) {
109 add_repo(base, fmt("%s/.git", path), fn); 118 add_repo(base, fmt("%s/.git", path), fn);
110 return; 119 return;
111 } 120 }
112 dir = opendir(path); 121 dir = opendir(path);
113 if (!dir) { 122 if (!dir) {
114 fprintf(stderr, "Error opening directory %s: %s (%d)\n", 123 fprintf(stderr, "Error opening directory %s: %s (%d)\n",
115 path, strerror(errno), errno); 124 path, strerror(errno), errno);
116 return; 125 return;
117 } 126 }
118 while((ent = readdir(dir)) != NULL) { 127 while((ent = readdir(dir)) != NULL) {
119 if (ent->d_name[0] == '.') { 128 if (ent->d_name[0] == '.') {
120 if (ent->d_name[1] == '\0') 129 if (ent->d_name[1] == '\0')
121 continue; 130 continue;
122 if (ent->d_name[1] == '.' && ent->d_name[2] == '\0') 131 if (ent->d_name[1] == '.' && ent->d_name[2] == '\0')
123 continue; 132 continue;
124 } 133 }
125 buf = malloc(strlen(path) + strlen(ent->d_name) + 2); 134 buf = malloc(strlen(path) + strlen(ent->d_name) + 2);
126 if (!buf) { 135 if (!buf) {
127 fprintf(stderr, "Alloc error on %s: %s (%d)\n", 136 fprintf(stderr, "Alloc error on %s: %s (%d)\n",
128 path, strerror(errno), errno); 137 path, strerror(errno), errno);
129 exit(1); 138 exit(1);
130 } 139 }
131 sprintf(buf, "%s/%s", path, ent->d_name); 140 sprintf(buf, "%s/%s", path, ent->d_name);
132 if (stat(buf, &st)) { 141 if (stat(buf, &st)) {
133 fprintf(stderr, "Error checking path %s: %s (%d)\n", 142 fprintf(stderr, "Error checking path %s: %s (%d)\n",
134 buf, strerror(errno), errno); 143 buf, strerror(errno), errno);
135 free(buf); 144 free(buf);
136 continue; 145 continue;
137 } 146 }
138 if (S_ISDIR(st.st_mode)) 147 if (S_ISDIR(st.st_mode))
139 scan_path(base, buf, fn); 148 scan_path(base, buf, fn);
140 free(buf); 149 free(buf);
141 } 150 }
142 closedir(dir); 151 closedir(dir);
143} 152}
144 153
154#define lastc(s) s[strlen(s) - 1]
155
156void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn)
157{
158 char line[MAX_PATH * 2], *z;
159 FILE *projects;
160 int err;
161
162 projects = fopen(projectsfile, "r");
163 if (!projects) {
164 fprintf(stderr, "Error opening projectsfile %s: %s (%d)\n",
165 projectsfile, strerror(errno), errno);
166 }
167 while (fgets(line, sizeof(line), projects) != NULL) {
168 for (z = &lastc(line);
169 strlen(line) && strchr("\n\r", *z);
170 z = &lastc(line))
171 *z = '\0';
172 if (strlen(line))
173 scan_path(path, fmt("%s/%s", path, line), fn);
174 }
175 if ((err = ferror(projects))) {
176 fprintf(stderr, "Error reading from projectsfile %s: %s (%d)\n",
177 projectsfile, strerror(err), err);
178 }
179 fclose(projects);
180}
181
145void scan_tree(const char *path, repo_config_fn fn) 182void scan_tree(const char *path, repo_config_fn fn)
146{ 183{
147 scan_path(path, path, fn); 184 scan_path(path, path, fn);
148} 185}