summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--cgit.c2
-rw-r--r--cgit.h1
-rw-r--r--cgitrc.5.txt6
-rw-r--r--scan-tree.c42
4 files changed, 45 insertions, 6 deletions
diff --git a/cgit.c b/cgit.c
index 04cef23..e1d2216 100644
--- a/cgit.c
+++ b/cgit.c
@@ -184,24 +184,26 @@ void config_cb(const char *name, const char *value)
184 else if (!strcmp(name, "max-commit-count")) 184 else if (!strcmp(name, "max-commit-count"))
185 ctx.cfg.max_commit_count = atoi(value); 185 ctx.cfg.max_commit_count = atoi(value);
186 else if (!strcmp(name, "project-list")) 186 else if (!strcmp(name, "project-list"))
187 ctx.cfg.project_list = xstrdup(expand_macros(value)); 187 ctx.cfg.project_list = xstrdup(expand_macros(value));
188 else if (!strcmp(name, "scan-path")) 188 else if (!strcmp(name, "scan-path"))
189 if (!ctx.cfg.nocache && ctx.cfg.cache_size) 189 if (!ctx.cfg.nocache && ctx.cfg.cache_size)
190 process_cached_repolist(expand_macros(value)); 190 process_cached_repolist(expand_macros(value));
191 else if (ctx.cfg.project_list) 191 else if (ctx.cfg.project_list)
192 scan_projects(expand_macros(value), 192 scan_projects(expand_macros(value),
193 ctx.cfg.project_list, repo_config); 193 ctx.cfg.project_list, repo_config);
194 else 194 else
195 scan_tree(expand_macros(value), repo_config); 195 scan_tree(expand_macros(value), repo_config);
196 else if (!strcmp(name, "section-from-path"))
197 ctx.cfg.section_from_path = atoi(value);
196 else if (!strcmp(name, "source-filter")) 198 else if (!strcmp(name, "source-filter"))
197 ctx.cfg.source_filter = new_filter(value, 1); 199 ctx.cfg.source_filter = new_filter(value, 1);
198 else if (!strcmp(name, "summary-log")) 200 else if (!strcmp(name, "summary-log"))
199 ctx.cfg.summary_log = atoi(value); 201 ctx.cfg.summary_log = atoi(value);
200 else if (!strcmp(name, "summary-branches")) 202 else if (!strcmp(name, "summary-branches"))
201 ctx.cfg.summary_branches = atoi(value); 203 ctx.cfg.summary_branches = atoi(value);
202 else if (!strcmp(name, "summary-tags")) 204 else if (!strcmp(name, "summary-tags"))
203 ctx.cfg.summary_tags = atoi(value); 205 ctx.cfg.summary_tags = atoi(value);
204 else if (!strcmp(name, "side-by-side-diffs")) 206 else if (!strcmp(name, "side-by-side-diffs"))
205 ctx.cfg.ssdiff = atoi(value); 207 ctx.cfg.ssdiff = atoi(value);
206 else if (!strcmp(name, "agefile")) 208 else if (!strcmp(name, "agefile"))
207 ctx.cfg.agefile = xstrdup(value); 209 ctx.cfg.agefile = xstrdup(value);
diff --git a/cgit.h b/cgit.h
index 72fb1c7..f8076c5 100644
--- a/cgit.h
+++ b/cgit.h
@@ -197,24 +197,25 @@ struct cgit_config {
197 int max_repo_count; 197 int max_repo_count;
198 int max_commit_count; 198 int max_commit_count;
199 int max_lock_attempts; 199 int max_lock_attempts;
200 int max_msg_len; 200 int max_msg_len;
201 int max_repodesc_len; 201 int max_repodesc_len;
202 int max_blob_size; 202 int max_blob_size;
203 int max_stats; 203 int max_stats;
204 int nocache; 204 int nocache;
205 int noplainemail; 205 int noplainemail;
206 int noheader; 206 int noheader;
207 int renamelimit; 207 int renamelimit;
208 int remove_suffix; 208 int remove_suffix;
209 int section_from_path;
209 int snapshots; 210 int snapshots;
210 int summary_branches; 211 int summary_branches;
211 int summary_log; 212 int summary_log;
212 int summary_tags; 213 int summary_tags;
213 int ssdiff; 214 int ssdiff;
214 struct string_list mimetypes; 215 struct string_list mimetypes;
215 struct cgit_filter *about_filter; 216 struct cgit_filter *about_filter;
216 struct cgit_filter *commit_filter; 217 struct cgit_filter *commit_filter;
217 struct cgit_filter *source_filter; 218 struct cgit_filter *source_filter;
218}; 219};
219 220
220struct cgit_page { 221struct cgit_page {
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 187031a..ce78d41 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -273,24 +273,30 @@ scan-path::
273 A path which will be scanned for repositories. If caching is enabled, 273 A path which will be scanned for repositories. If caching is enabled,
274 the result will be cached as a cgitrc include-file in the cache 274 the result will be cached as a cgitrc include-file in the cache
275 directory. If project-list has been defined prior to scan-path, 275 directory. If project-list has been defined prior to scan-path,
276 scan-path loads only the directories listed in the file pointed to by 276 scan-path loads only the directories listed in the file pointed to by
277 project-list. Default value: none. See also: cache-scanrc-ttl, 277 project-list. Default value: none. See also: cache-scanrc-ttl,
278 project-list. 278 project-list.
279 279
280section:: 280section::
281 The name of the current repository section - all repositories defined 281 The name of the current repository section - all repositories defined
282 after this option will inherit the current section name. Default value: 282 after this option will inherit the current section name. Default value:
283 none. 283 none.
284 284
285section-from-path::
286 A number which, if specified before scan-path, specifies how many
287 path elements from each repo path to use as a default section name.
288 If negative, cgit will discard the specified number of path elements
289 above the repo directory. Default value: 0.
290
285side-by-side-diffs:: 291side-by-side-diffs::
286 If set to "1" shows side-by-side diffs instead of unidiffs per 292 If set to "1" shows side-by-side diffs instead of unidiffs per
287 default. Default value: "0". 293 default. Default value: "0".
288 294
289snapshots:: 295snapshots::
290 Text which specifies the default set of snapshot formats generated by 296 Text which specifies the default set of snapshot formats generated by
291 cgit. The value is a space-separated list of zero or more of the 297 cgit. The value is a space-separated list of zero or more of the
292 values "tar", "tar.gz", "tar.bz2" and "zip". Default value: none. 298 values "tar", "tar.gz", "tar.bz2" and "zip". Default value: none.
293 299
294source-filter:: 300source-filter::
295 Specifies a command which will be invoked to format plaintext blobs 301 Specifies a command which will be invoked to format plaintext blobs
296 in the tree view. The command will get the blob content on its STDIN 302 in the tree view. The command will get the blob content on its STDIN
diff --git a/scan-tree.c b/scan-tree.c
index 780d405..b5b50f3 100644
--- a/scan-tree.c
+++ b/scan-tree.c
@@ -52,51 +52,59 @@ char *owner;
52static void repo_config(const char *name, const char *value) 52static void repo_config(const char *name, const char *value)
53{ 53{
54 config_fn(repo, name, value); 54 config_fn(repo, name, value);
55} 55}
56 56
57static int git_owner_config(const char *key, const char *value, void *cb) 57static int git_owner_config(const char *key, const char *value, void *cb)
58{ 58{
59 if (!strcmp(key, "gitweb.owner")) 59 if (!strcmp(key, "gitweb.owner"))
60 owner = xstrdup(value); 60 owner = xstrdup(value);
61 return 0; 61 return 0;
62} 62}
63 63
64static char *xstrrchr(char *s, char *from, int c)
65{
66 while (from >= s && *from != c)
67 from--;
68 return from < s ? NULL : from;
69}
70
64static void add_repo(const char *base, const char *path, repo_config_fn fn) 71static void add_repo(const char *base, const char *path, repo_config_fn fn)
65{ 72{
66 struct stat st; 73 struct stat st;
67 struct passwd *pwd; 74 struct passwd *pwd;
68 char *p; 75 char *rel, *p, *slash;
76 int n;
69 size_t size; 77 size_t size;
70 78
71 if (stat(path, &st)) { 79 if (stat(path, &st)) {
72 fprintf(stderr, "Error accessing %s: %s (%d)\n", 80 fprintf(stderr, "Error accessing %s: %s (%d)\n",
73 path, strerror(errno), errno); 81 path, strerror(errno), errno);
74 return; 82 return;
75 } 83 }
76 if (!stat(fmt("%s/noweb", path), &st)) 84 if (!stat(fmt("%s/noweb", path), &st))
77 return; 85 return;
78 86
79 owner = NULL; 87 owner = NULL;
80 if (ctx.cfg.enable_gitweb_owner) 88 if (ctx.cfg.enable_gitweb_owner)
81 git_config_from_file(git_owner_config, fmt("%s/config", path), NULL); 89 git_config_from_file(git_owner_config, fmt("%s/config", path), NULL);
82 if (base == path) 90 if (base == path)
83 p = fmt("%s", path); 91 rel = xstrdup(fmt("%s", path));
84 else 92 else
85 p = fmt("%s", path + strlen(base) + 1); 93 rel = xstrdup(fmt("%s", path + strlen(base) + 1));
86 94
87 if (!strcmp(p + strlen(p) - 5, "/.git")) 95 if (!strcmp(rel + strlen(rel) - 5, "/.git"))
88 p[strlen(p) - 5] = '\0'; 96 rel[strlen(rel) - 5] = '\0';
89 97
90 repo = cgit_add_repo(xstrdup(p)); 98 repo = cgit_add_repo(rel);
91 if (ctx.cfg.remove_suffix) 99 if (ctx.cfg.remove_suffix)
92 if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git")) 100 if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git"))
93 *p = '\0'; 101 *p = '\0';
94 repo->name = repo->url; 102 repo->name = repo->url;
95 repo->path = xstrdup(path); 103 repo->path = xstrdup(path);
96 while (!owner) { 104 while (!owner) {
97 if ((pwd = getpwuid(st.st_uid)) == NULL) { 105 if ((pwd = getpwuid(st.st_uid)) == NULL) {
98 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", 106 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n",
99 path, strerror(errno), errno); 107 path, strerror(errno), errno);
100 break; 108 break;
101 } 109 }
102 if (pwd->pw_gecos) 110 if (pwd->pw_gecos)
@@ -106,24 +114,46 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn)
106 } 114 }
107 repo->owner = owner; 115 repo->owner = owner;
108 116
109 p = fmt("%s/description", path); 117 p = fmt("%s/description", path);
110 if (!stat(p, &st)) 118 if (!stat(p, &st))
111 readfile(p, &repo->desc, &size); 119 readfile(p, &repo->desc, &size);
112 120
113 if (!repo->readme) { 121 if (!repo->readme) {
114 p = fmt("%s/README.html", path); 122 p = fmt("%s/README.html", path);
115 if (!stat(p, &st)) 123 if (!stat(p, &st))
116 repo->readme = "README.html"; 124 repo->readme = "README.html";
117 } 125 }
126 if (ctx.cfg.section_from_path) {
127 n = ctx.cfg.section_from_path;
128 if (n > 0) {
129 slash = rel;
130 while (slash && n && (slash = strchr(slash, '/')))
131 n--;
132 } else {
133 slash = rel + strlen(rel);
134 while (slash && n && (slash = xstrrchr(rel, slash, '/')))
135 n++;
136 }
137 if (slash && !n) {
138 *slash = '\0';
139 repo->section = xstrdup(rel);
140 *slash = '/';
141 if (!prefixcmp(repo->name, repo->section)) {
142 repo->name += strlen(repo->section);
143 if (*repo->name == '/')
144 repo->name++;
145 }
146 }
147 }
118 148
119 p = fmt("%s/cgitrc", path); 149 p = fmt("%s/cgitrc", path);
120 if (!stat(p, &st)) { 150 if (!stat(p, &st)) {
121 config_fn = fn; 151 config_fn = fn;
122 parse_configfile(xstrdup(p), &repo_config); 152 parse_configfile(xstrdup(p), &repo_config);
123 } 153 }
124} 154}
125 155
126static void scan_path(const char *base, const char *path, repo_config_fn fn) 156static void scan_path(const char *base, const char *path, repo_config_fn fn)
127{ 157{
128 DIR *dir; 158 DIR *dir;
129 struct dirent *ent; 159 struct dirent *ent;