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