Compare commits
18 commits
master
...
lookshe/ma
Author | SHA1 | Date | |
---|---|---|---|
1787404b6a | |||
2209fe5157 | |||
98c3bb0e3b | |||
4d7d10dba5 | |||
1c1f2a00d2 | |||
335423fb9d | |||
5aa2eb8047 | |||
70d357f239 | |||
a4d069bbd9 | |||
1ca2305975 | |||
25eb0a096f | |||
95be399ab4 | |||
fbcdeeb500 | |||
36a1d663a6 | |||
86ff85e75a | |||
2a5c1abeea | |||
87dca2dd53 | |||
69bb0352e4 |
15 changed files with 1993 additions and 332 deletions
2
cgit.c
2
cgit.c
|
@ -347,6 +347,7 @@ static void querystring_cb(const char *name, const char *value)
|
|||
static void prepare_context(void)
|
||||
{
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.qry.ignorews = 1;
|
||||
ctx.cfg.agefile = "info/web/last-modified";
|
||||
ctx.cfg.nocache = 0;
|
||||
ctx.cfg.cache_size = 0;
|
||||
|
@ -393,6 +394,7 @@ static void prepare_context(void)
|
|||
ctx.cfg.summary_tags = 10;
|
||||
ctx.cfg.max_atom_items = 10;
|
||||
ctx.cfg.difftype = DIFF_UNIFIED;
|
||||
ctx.cfg.issue_link = "https://bugs.thedevstack.de/task/";
|
||||
ctx.env.cgit_config = getenv("CGIT_CONFIG");
|
||||
ctx.env.http_host = getenv("HTTP_HOST");
|
||||
ctx.env.https = getenv("HTTPS");
|
||||
|
|
4
cgit.css
4
cgit.css
|
@ -201,6 +201,10 @@ div#cgit table.list td a {
|
|||
color: black;
|
||||
}
|
||||
|
||||
div#cgit table.list td a.FS-link {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
div#cgit table.list td a.ls-dir {
|
||||
font-weight: bold;
|
||||
color: #00f;
|
||||
|
|
3
cgit.h
3
cgit.h
|
@ -267,6 +267,7 @@ struct cgit_config {
|
|||
struct cgit_filter *email_filter;
|
||||
struct cgit_filter *owner_filter;
|
||||
struct cgit_filter *auth_filter;
|
||||
char* issue_link;
|
||||
};
|
||||
|
||||
struct cgit_page {
|
||||
|
@ -391,4 +392,6 @@ extern char *expand_macros(const char *txt);
|
|||
|
||||
extern char *get_mimetype_for_filename(const char *filename);
|
||||
|
||||
extern char *sub_str(const char* text, int begin, int end);
|
||||
|
||||
#endif /* CGIT_H */
|
||||
|
|
|
@ -1,294 +1,2 @@
|
|||
#!/usr/bin/env python3
|
||||
import markdown
|
||||
import sys
|
||||
import io
|
||||
from pygments.formatters import HtmlFormatter
|
||||
sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8')
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||||
sys.stdout.write('''
|
||||
<style>
|
||||
.markdown-body {
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
overflow: hidden;
|
||||
}
|
||||
.markdown-body>*:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.markdown-body>*:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.markdown-body a.absent {
|
||||
color: #c00;
|
||||
}
|
||||
.markdown-body a.anchor {
|
||||
display: block;
|
||||
padding-left: 30px;
|
||||
margin-left: -30px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 {
|
||||
margin: 20px 0 10px;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
cursor: text;
|
||||
position: relative;
|
||||
}
|
||||
.markdown-body h1 .mini-icon-link, .markdown-body h2 .mini-icon-link, .markdown-body h3 .mini-icon-link, .markdown-body h4 .mini-icon-link, .markdown-body h5 .mini-icon-link, .markdown-body h6 .mini-icon-link {
|
||||
display: none;
|
||||
color: #000;
|
||||
}
|
||||
.markdown-body h1:hover a.anchor, .markdown-body h2:hover a.anchor, .markdown-body h3:hover a.anchor, .markdown-body h4:hover a.anchor, .markdown-body h5:hover a.anchor, .markdown-body h6:hover a.anchor {
|
||||
text-decoration: none;
|
||||
line-height: 1;
|
||||
padding-left: 0;
|
||||
margin-left: -22px;
|
||||
top: 15%}
|
||||
.markdown-body h1:hover a.anchor .mini-icon-link, .markdown-body h2:hover a.anchor .mini-icon-link, .markdown-body h3:hover a.anchor .mini-icon-link, .markdown-body h4:hover a.anchor .mini-icon-link, .markdown-body h5:hover a.anchor .mini-icon-link, .markdown-body h6:hover a.anchor .mini-icon-link {
|
||||
display: inline-block;
|
||||
}
|
||||
.markdown-body h1 tt, .markdown-body h1 code, .markdown-body h2 tt, .markdown-body h2 code, .markdown-body h3 tt, .markdown-body h3 code, .markdown-body h4 tt, .markdown-body h4 code, .markdown-body h5 tt, .markdown-body h5 code, .markdown-body h6 tt, .markdown-body h6 code {
|
||||
font-size: inherit;
|
||||
}
|
||||
.markdown-body h1 {
|
||||
font-size: 28px;
|
||||
color: #000;
|
||||
}
|
||||
.markdown-body h2 {
|
||||
font-size: 24px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
color: #000;
|
||||
}
|
||||
.markdown-body h3 {
|
||||
font-size: 18px;
|
||||
}
|
||||
.markdown-body h4 {
|
||||
font-size: 16px;
|
||||
}
|
||||
.markdown-body h5 {
|
||||
font-size: 14px;
|
||||
}
|
||||
.markdown-body h6 {
|
||||
color: #777;
|
||||
font-size: 14px;
|
||||
}
|
||||
.markdown-body p, .markdown-body blockquote, .markdown-body ul, .markdown-body ol, .markdown-body dl, .markdown-body table, .markdown-body pre {
|
||||
margin: 15px 0;
|
||||
}
|
||||
.markdown-body hr {
|
||||
background: transparent url("/dirty-shade.png") repeat-x 0 0;
|
||||
border: 0 none;
|
||||
color: #ccc;
|
||||
height: 4px;
|
||||
padding: 0;
|
||||
}
|
||||
.markdown-body>h2:first-child, .markdown-body>h1:first-child, .markdown-body>h1:first-child+h2, .markdown-body>h3:first-child, .markdown-body>h4:first-child, .markdown-body>h5:first-child, .markdown-body>h6:first-child {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
.markdown-body a:first-child h1, .markdown-body a:first-child h2, .markdown-body a:first-child h3, .markdown-body a:first-child h4, .markdown-body a:first-child h5, .markdown-body a:first-child h6 {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
.markdown-body h1+p, .markdown-body h2+p, .markdown-body h3+p, .markdown-body h4+p, .markdown-body h5+p, .markdown-body h6+p {
|
||||
margin-top: 0;
|
||||
}
|
||||
.markdown-body li p.first {
|
||||
display: inline-block;
|
||||
}
|
||||
.markdown-body ul, .markdown-body ol {
|
||||
padding-left: 30px;
|
||||
}
|
||||
.markdown-body ul.no-list, .markdown-body ol.no-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
.markdown-body ul li>:first-child, .markdown-body ul li ul:first-of-type, .markdown-body ul li ol:first-of-type, .markdown-body ol li>:first-child, .markdown-body ol li ul:first-of-type, .markdown-body ol li ol:first-of-type {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.markdown-body ul li p:last-of-type, .markdown-body ol li p:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.markdown-body ul ul, .markdown-body ul ol, .markdown-body ol ol, .markdown-body ol ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.markdown-body dl {
|
||||
padding: 0;
|
||||
}
|
||||
.markdown-body dl dt {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
padding: 0;
|
||||
margin: 15px 0 5px;
|
||||
}
|
||||
.markdown-body dl dt:first-child {
|
||||
padding: 0;
|
||||
}
|
||||
.markdown-body dl dt>:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.markdown-body dl dt>:last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.markdown-body dl dd {
|
||||
margin: 0 0 15px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
.markdown-body dl dd>:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.markdown-body dl dd>:last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.markdown-body blockquote {
|
||||
border-left: 4px solid #DDD;
|
||||
padding: 0 15px;
|
||||
color: #777;
|
||||
}
|
||||
.markdown-body blockquote>:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.markdown-body blockquote>:last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.markdown-body table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
.markdown-body table th, .markdown-body table td {
|
||||
border: 1px solid #ccc;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
.markdown-body table tr {
|
||||
border-top: 1px solid #ccc;
|
||||
background-color: #fff;
|
||||
}
|
||||
.markdown-body table tr:nth-child(2n) {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
.markdown-body img {
|
||||
max-width: 100%;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.markdown-body span.frame {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
.markdown-body span.frame>span {
|
||||
border: 1px solid #ddd;
|
||||
display: block;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
margin: 13px 0 0;
|
||||
padding: 7px;
|
||||
width: auto;
|
||||
}
|
||||
.markdown-body span.frame span img {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
.markdown-body span.frame span span {
|
||||
clear: both;
|
||||
color: #333;
|
||||
display: block;
|
||||
padding: 5px 0 0;
|
||||
}
|
||||
.markdown-body span.align-center {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
.markdown-body span.align-center>span {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 13px auto 0;
|
||||
text-align: center;
|
||||
}
|
||||
.markdown-body span.align-center span img {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
.markdown-body span.align-right {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
.markdown-body span.align-right>span {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 13px 0 0;
|
||||
text-align: right;
|
||||
}
|
||||
.markdown-body span.align-right span img {
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
}
|
||||
.markdown-body span.float-left {
|
||||
display: block;
|
||||
margin-right: 13px;
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
}
|
||||
.markdown-body span.float-left span {
|
||||
margin: 13px 0 0;
|
||||
}
|
||||
.markdown-body span.float-right {
|
||||
display: block;
|
||||
margin-left: 13px;
|
||||
overflow: hidden;
|
||||
float: right;
|
||||
}
|
||||
.markdown-body span.float-right>span {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 13px auto 0;
|
||||
text-align: right;
|
||||
}
|
||||
.markdown-body code, .markdown-body tt {
|
||||
margin: 0 2px;
|
||||
padding: 0px 5px;
|
||||
border: 1px solid #eaeaea;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.markdown-body code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.markdown-body pre>code {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
white-space: pre;
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
.markdown-body .highlight pre, .markdown-body pre {
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #ccc;
|
||||
font-size: 13px;
|
||||
line-height: 19px;
|
||||
overflow: auto;
|
||||
padding: 6px 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.markdown-body pre code, .markdown-body pre tt {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
''')
|
||||
sys.stdout.write(HtmlFormatter(style='pastie').get_style_defs('.highlight'))
|
||||
sys.stdout.write('''
|
||||
</style>
|
||||
''')
|
||||
sys.stdout.write("<div class='markdown-body'>")
|
||||
sys.stdout.flush()
|
||||
# Note: you may want to run this through bleach for sanitization
|
||||
markdown.markdownFromFile(output_format="html5", extensions=["markdown.extensions.fenced_code", "markdown.extensions.codehilite", "markdown.extensions.tables"], extension_configs={"markdown.extensions.codehilite":{"css_class":"highlight"}})
|
||||
sys.stdout.write("</div>")
|
||||
#!/bin/sh
|
||||
exec "$(dirname "$0")/resources/markdown.pl"
|
||||
|
|
1731
filters/html-converters/resources/markdown.pl
Executable file
1731
filters/html-converters/resources/markdown.pl
Executable file
File diff suppressed because it is too large
Load diff
4
filters/html-converters/resources/rst-template.txt
Normal file
4
filters/html-converters/resources/rst-template.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
%(stylesheet)s
|
||||
%(body_pre_docinfo)s
|
||||
%(docinfo)s
|
||||
%(body)s
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python2
|
||||
|
||||
# This script uses Pygments and Python3. You must have both installed
|
||||
# This script uses Pygments and Python2. You must have both installed
|
||||
# for this to work.
|
||||
#
|
||||
# http://pygments.org/
|
||||
|
@ -21,7 +21,6 @@
|
|||
|
||||
|
||||
import sys
|
||||
import io
|
||||
from pygments import highlight
|
||||
from pygments.util import ClassNotFound
|
||||
from pygments.lexers import TextLexer
|
||||
|
@ -30,26 +29,25 @@ from pygments.lexers import guess_lexer_for_filename
|
|||
from pygments.formatters import HtmlFormatter
|
||||
|
||||
|
||||
sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8')
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||||
data = sys.stdin.read()
|
||||
# read stdin and decode to utf-8. ignore any unkown signs.
|
||||
data = sys.stdin.read().decode(encoding='utf-8', errors='ignore')
|
||||
filename = sys.argv[1]
|
||||
formatter = HtmlFormatter(style='pastie')
|
||||
formatter = HtmlFormatter(encoding='utf-8', style='pastie')
|
||||
|
||||
try:
|
||||
lexer = guess_lexer_for_filename(filename, data)
|
||||
lexer = guess_lexer_for_filename(filename, data, encoding='utf-8')
|
||||
except ClassNotFound:
|
||||
# check if there is any shebang
|
||||
if data[0:2] == '#!':
|
||||
lexer = guess_lexer(data)
|
||||
lexer = guess_lexer(data, encoding='utf-8')
|
||||
else:
|
||||
lexer = TextLexer()
|
||||
lexer = TextLexer(encoding='utf-8')
|
||||
except TypeError:
|
||||
lexer = TextLexer()
|
||||
lexer = TextLexer(encoding='utf-8')
|
||||
|
||||
# highlight! :-)
|
||||
# printout pygments' css definitions as well
|
||||
sys.stdout.write('<style>')
|
||||
sys.stdout.write(formatter.get_style_defs('.highlight'))
|
||||
sys.stdout.write('</style>')
|
||||
sys.stdout.write(highlight(data, lexer, formatter, outfile=None))
|
||||
highlight(data, lexer, formatter, outfile=sys.stdout)
|
||||
|
|
8
shared.c
8
shared.c
|
@ -601,3 +601,11 @@ char *get_mimetype_for_filename(const char *filename)
|
|||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* sub_str(const char* text, int begin, int end)
|
||||
{
|
||||
char* sub = (char*) malloc(sizeof(char) * ((end - begin) + 1));
|
||||
strncpy(sub, text + begin, end - begin);
|
||||
sub[end - begin] = '\0';
|
||||
return sub;
|
||||
}
|
||||
|
|
|
@ -117,13 +117,13 @@ void cgit_print_commit(char *hex, const char *prefix)
|
|||
html("</table>\n");
|
||||
html("<div class='commit-subject'>");
|
||||
cgit_open_filter(ctx.repo->commit_filter);
|
||||
html_txt(info->subject);
|
||||
cgit_check_text_for_issue_link(info->subject);
|
||||
cgit_close_filter(ctx.repo->commit_filter);
|
||||
show_commit_decorations(commit);
|
||||
html("</div>");
|
||||
html("<div class='commit-msg'>");
|
||||
cgit_open_filter(ctx.repo->commit_filter);
|
||||
html_txt(info->msg);
|
||||
cgit_check_text_for_issue_link(info->msg);
|
||||
cgit_close_filter(ctx.repo->commit_filter);
|
||||
html("</div>");
|
||||
if (notes.len != 0) {
|
||||
|
|
6
ui-log.c
6
ui-log.c
|
@ -234,12 +234,12 @@ static void print_commit(struct commit *commit, struct rev_info *revs)
|
|||
strcpy(info->subject + i, wrap_symbol);
|
||||
}
|
||||
}
|
||||
cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
|
||||
oid_to_hex(&commit->object.oid), ctx.qry.vpath);
|
||||
cgit_commit_link2(info->subject, NULL, NULL, ctx.qry.head,
|
||||
oid_to_hex(&commit->object.oid), ctx.qry.vpath, true);
|
||||
show_commit_decorations(commit);
|
||||
html("</td><td>");
|
||||
cgit_open_filter(ctx.repo->email_filter, info->author_email, "log");
|
||||
html_txt(info->author);
|
||||
cgit_author_link(info->author, NULL);
|
||||
cgit_close_filter(ctx.repo->email_filter);
|
||||
|
||||
if (revs->graph) {
|
||||
|
|
|
@ -67,10 +67,10 @@ static int print_branch(struct refinfo *ref)
|
|||
html("</td><td>");
|
||||
|
||||
if (ref->object->type == OBJ_COMMIT) {
|
||||
cgit_commit_link(info->subject, NULL, NULL, name, NULL, NULL);
|
||||
cgit_commit_link2(info->subject, NULL, NULL, name, NULL, NULL, true);
|
||||
html("</td><td>");
|
||||
cgit_open_filter(ctx.repo->email_filter, info->author_email, "refs");
|
||||
html_txt(info->author);
|
||||
cgit_author_link(info->author, name);
|
||||
cgit_close_filter(ctx.repo->email_filter);
|
||||
html("</td><td colspan='2'>");
|
||||
cgit_print_age(info->committer_date, info->committer_tz, -1);
|
||||
|
|
118
ui-shared.c
118
ui-shared.c
|
@ -348,6 +348,12 @@ void cgit_log_link(const char *name, const char *title, const char *class,
|
|||
|
||||
void cgit_commit_link(char *name, const char *title, const char *class,
|
||||
const char *head, const char *rev, const char *path)
|
||||
{
|
||||
cgit_commit_link2(name, title, class, head, rev, path, false);
|
||||
}
|
||||
|
||||
void cgit_commit_link2(char *name, const char *title, const char *class,
|
||||
const char *head, const char *rev, const char *path, bool checkForIssueLink)
|
||||
{
|
||||
if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) {
|
||||
name[ctx.cfg.max_msg_len] = '\0';
|
||||
|
@ -355,7 +361,49 @@ void cgit_commit_link(char *name, const char *title, const char *class,
|
|||
name[ctx.cfg.max_msg_len - 2] = '.';
|
||||
name[ctx.cfg.max_msg_len - 3] = '.';
|
||||
}
|
||||
if (checkForIssueLink) {
|
||||
int last_match = 0;
|
||||
int offset = 0;
|
||||
for (;;) {
|
||||
const char* sub = strstr(name + last_match + offset, ISSUE_MARKER);
|
||||
if (sub) {
|
||||
int found_pos = (sub - (name + last_match));
|
||||
sub += STRLEN_ISSUE_MARKER;
|
||||
int numbercount = 0;
|
||||
while (*sub >= '0' && *sub <= '9') {
|
||||
numbercount++;
|
||||
sub++;
|
||||
}
|
||||
if (!numbercount) {
|
||||
offset = found_pos + STRLEN_ISSUE_MARKER;
|
||||
continue;
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
if (found_pos > 0) {
|
||||
char* left_part = sub_str(name, last_match, last_match + found_pos);
|
||||
cgit_commit_link3(left_part, title, class, head, rev, path);
|
||||
free(left_part);
|
||||
}
|
||||
char* issue_part = sub_str(name, last_match + found_pos, last_match + found_pos + STRLEN_ISSUE_MARKER + numbercount);
|
||||
cgit_issue_link(issue_part, "FS-link");
|
||||
free(issue_part);
|
||||
last_match += found_pos + STRLEN_ISSUE_MARKER + numbercount;
|
||||
} else {
|
||||
if (strlen(name + last_match)) {
|
||||
cgit_commit_link3(name + last_match, title, class, head, rev, path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cgit_commit_link3(name, title, class, head, rev, path);
|
||||
}
|
||||
}
|
||||
|
||||
void cgit_commit_link3(char *name, const char *title, const char *class,
|
||||
const char *head, const char *rev, const char *path)
|
||||
{
|
||||
char *delim;
|
||||
|
||||
delim = repolink(title, class, "commit", head, path);
|
||||
|
@ -1109,3 +1157,73 @@ void cgit_print_snapshot_links(const char *repo, const char *head,
|
|||
}
|
||||
strbuf_release(&filename);
|
||||
}
|
||||
|
||||
extern void cgit_author_link(const char *author, const char *head)
|
||||
{
|
||||
char *delim;
|
||||
|
||||
delim = repolink(NULL, NULL, "log", head ? head : ctx.qry.head, NULL);
|
||||
html(delim);
|
||||
html("qt=author&q=");
|
||||
html_url_arg(author);
|
||||
html("'>");
|
||||
html_txt(author);
|
||||
html("</a>");
|
||||
}
|
||||
|
||||
extern void cgit_check_text_for_issue_link(const char* text)
|
||||
{
|
||||
int last_match = 0;
|
||||
int offset = 0;
|
||||
for (;;) {
|
||||
const char* sub = strstr(text + last_match + offset, ISSUE_MARKER);
|
||||
if(sub) {
|
||||
int found_pos = (sub - (text + last_match));
|
||||
sub += STRLEN_ISSUE_MARKER;
|
||||
int numbercount = 0;
|
||||
while (*sub >= '0' && *sub <= '9') {
|
||||
numbercount++;
|
||||
sub++;
|
||||
}
|
||||
if (!numbercount) {
|
||||
offset = found_pos + STRLEN_ISSUE_MARKER;
|
||||
continue;
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
if (found_pos > 0) {
|
||||
char* left_part = sub_str(text, last_match, last_match + found_pos);
|
||||
html_txt(left_part);
|
||||
free(left_part);
|
||||
}
|
||||
char* issue_part = sub_str(text, last_match + found_pos, last_match + found_pos + STRLEN_ISSUE_MARKER + numbercount);
|
||||
cgit_issue_link(issue_part, NULL);
|
||||
free(issue_part);
|
||||
last_match += found_pos + STRLEN_ISSUE_MARKER + numbercount;
|
||||
} else {
|
||||
if (strlen(text + last_match)) {
|
||||
html_txt(text + last_match);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern void cgit_issue_link(const char* issue, const char* class)
|
||||
{
|
||||
html("<a href='");
|
||||
htmlf(ctx.cfg.issue_link);
|
||||
if (strlen(issue) > 3) {
|
||||
html(issue + 3);
|
||||
}
|
||||
html("'");
|
||||
if (class) {
|
||||
html(" class='");
|
||||
html(class);
|
||||
html("'");
|
||||
}
|
||||
html(" target='_blank'");
|
||||
html(">");
|
||||
html_txt(issue);
|
||||
html("</a>");
|
||||
}
|
||||
|
|
12
ui-shared.h
12
ui-shared.h
|
@ -1,6 +1,9 @@
|
|||
#ifndef UI_SHARED_H
|
||||
#define UI_SHARED_H
|
||||
|
||||
#define ISSUE_MARKER "FS#"
|
||||
#define STRLEN_ISSUE_MARKER 3
|
||||
|
||||
extern const char *cgit_httpscheme(void);
|
||||
extern char *cgit_hosturl(void);
|
||||
extern const char *cgit_rooturl(void);
|
||||
|
@ -33,6 +36,12 @@ extern void cgit_log_link(const char *name, const char *title,
|
|||
extern void cgit_commit_link(char *name, const char *title,
|
||||
const char *class, const char *head,
|
||||
const char *rev, const char *path);
|
||||
extern void cgit_commit_link2(char *name, const char *title,
|
||||
const char *class, const char *head,
|
||||
const char *rev, const char *path, bool checkForIssueLink);
|
||||
extern void cgit_commit_link3(char *name, const char *title,
|
||||
const char *class, const char *head,
|
||||
const char *rev, const char *path);
|
||||
extern void cgit_patch_link(const char *name, const char *title,
|
||||
const char *class, const char *head,
|
||||
const char *rev, const char *path);
|
||||
|
@ -77,4 +86,7 @@ extern void cgit_print_snapshot_links(const char *repo, const char *head,
|
|||
const char *hex, int snapshots);
|
||||
extern void cgit_add_hidden_formfields(int incl_head, int incl_search,
|
||||
const char *page);
|
||||
extern void cgit_author_link(const char *author, const char *head);
|
||||
extern void cgit_check_text_for_issue_link(const char* text);
|
||||
extern void cgit_issue_link(const char* issue, const char* class);
|
||||
#endif /* UI_SHARED_H */
|
||||
|
|
|
@ -323,7 +323,7 @@ static void print_authors(struct string_list *authors, int top,
|
|||
for (i = 0; i < top; i++) {
|
||||
author = &authors->items[i];
|
||||
html("<tr><td class='left'>");
|
||||
html_txt(author->string);
|
||||
cgit_author_link(author->string, NULL);
|
||||
html("</td>");
|
||||
authorstat = author->util;
|
||||
items = &authorstat->list;
|
||||
|
|
109
ui-tree.c
109
ui-tree.c
|
@ -15,6 +15,15 @@ struct walk_tree_context {
|
|||
char *curr_rev;
|
||||
char *match_path;
|
||||
int state;
|
||||
bool dir_mode;
|
||||
};
|
||||
|
||||
struct flatten_walk_tree_context {
|
||||
int counter;
|
||||
int path_added;
|
||||
unsigned char last_sha1[20];
|
||||
char* path;
|
||||
char* last_path;
|
||||
};
|
||||
|
||||
static void print_text_buffer(const char *name, char *buf, unsigned long size)
|
||||
|
@ -86,7 +95,7 @@ static void print_binary_buffer(char *buf, unsigned long size)
|
|||
|
||||
static void set_title_from_path(const char *path)
|
||||
{
|
||||
size_t path_len, path_index, path_last_end;
|
||||
size_t path_len;
|
||||
char *new_title;
|
||||
|
||||
if (!path)
|
||||
|
@ -96,20 +105,7 @@ static void set_title_from_path(const char *path)
|
|||
new_title = xmalloc(path_len + 3 + strlen(ctx.page.title) + 1);
|
||||
new_title[0] = '\0';
|
||||
|
||||
for (path_index = path_len, path_last_end = path_len; path_index-- > 0;) {
|
||||
if (path[path_index] == '/') {
|
||||
if (path_index == path_len - 1) {
|
||||
path_last_end = path_index - 1;
|
||||
continue;
|
||||
}
|
||||
strncat(new_title, &path[path_index + 1], path_last_end - path_index - 1);
|
||||
strcat(new_title, "\\");
|
||||
path_last_end = path_index;
|
||||
}
|
||||
}
|
||||
if (path_last_end)
|
||||
strncat(new_title, path, path_last_end);
|
||||
|
||||
strcat(new_title, path);
|
||||
strcat(new_title, " - ");
|
||||
strcat(new_title, ctx.page.title);
|
||||
ctx.page.title = new_title;
|
||||
|
@ -155,6 +151,38 @@ static void print_object(const unsigned char *sha1, char *path, const char *base
|
|||
print_text_buffer(basename, buf, size);
|
||||
}
|
||||
|
||||
static int flatten_tree_item(const unsigned char *sha1, struct strbuf *base,
|
||||
const char *pathname, unsigned mode, int stage, void *cbdata)
|
||||
{
|
||||
struct flatten_walk_tree_context* fwt_ctx = cbdata;
|
||||
// increment counter of child elements
|
||||
fwt_ctx->counter++;
|
||||
if (!S_ISDIR(mode) || fwt_ctx->counter > 1) {
|
||||
if (fwt_ctx->counter > 1) {
|
||||
// if the first child element was a directory we have to use the path before
|
||||
free(fwt_ctx->path);
|
||||
fwt_ctx->path = xstrdup(fwt_ctx->last_path);
|
||||
}
|
||||
// flag that we ended
|
||||
fwt_ctx->counter = -1;
|
||||
// -1 to break read_tree_recursive
|
||||
return -1;
|
||||
}
|
||||
// save last path and concatenate new one
|
||||
char* tmp = xstrdup(fwt_ctx->path);
|
||||
free(fwt_ctx->path);
|
||||
free(fwt_ctx->last_path);
|
||||
fwt_ctx->last_path = xstrdup(tmp);
|
||||
fwt_ctx->path = (char*) malloc(sizeof(char) * (2 + strlen(tmp) + strlen(pathname)));
|
||||
strcpy(fwt_ctx->path, tmp);
|
||||
strcat(fwt_ctx->path, "/");
|
||||
strcat(fwt_ctx->path, pathname);
|
||||
free(tmp);
|
||||
fwt_ctx->path_added++;
|
||||
// save hash of found element
|
||||
hashcpy(fwt_ctx->last_sha1, sha1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ls_item(const unsigned char *sha1, struct strbuf *base,
|
||||
const char *pathname, unsigned mode, int stage, void *cbdata)
|
||||
|
@ -166,6 +194,10 @@ static int ls_item(const unsigned char *sha1, struct strbuf *base,
|
|||
enum object_type type;
|
||||
unsigned long size = 0;
|
||||
|
||||
if ((!S_ISDIR(mode) && walk_tree_ctx->dir_mode) || (S_ISDIR(mode) && !walk_tree_ctx->dir_mode)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = xstrdup(pathname);
|
||||
strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "",
|
||||
ctx.qry.path ? "/" : "", name);
|
||||
|
@ -187,6 +219,36 @@ static int ls_item(const unsigned char *sha1, struct strbuf *base,
|
|||
if (S_ISGITLINK(mode)) {
|
||||
cgit_submodule_link("ls-mod", fullpath.buf, sha1_to_hex(sha1));
|
||||
} else if (S_ISDIR(mode)) {
|
||||
struct flatten_walk_tree_context fwt_ctx;
|
||||
// initialize paths
|
||||
fwt_ctx.path = (char*) malloc(sizeof(char) * 1);
|
||||
strcpy(fwt_ctx.path, "");
|
||||
fwt_ctx.last_path = (char*) malloc(sizeof(char) * 1);
|
||||
strcpy(fwt_ctx.last_path, "");
|
||||
// start at actual position
|
||||
hashcpy(fwt_ctx.last_sha1, sha1);
|
||||
do {
|
||||
fwt_ctx.counter = 0;
|
||||
struct tree* tree;
|
||||
struct pathspec path = {
|
||||
.nr = 0
|
||||
};
|
||||
tree = parse_tree_indirect(fwt_ctx.last_sha1);
|
||||
read_tree_recursive(tree, "", 0, 1, &path, flatten_tree_item, &fwt_ctx);
|
||||
} while (fwt_ctx.counter != -1);
|
||||
if (fwt_ctx.path_added) {
|
||||
// append found path to fullpath and name
|
||||
strbuf_addf(&fullpath, "%s", fwt_ctx.path);
|
||||
char* tmp = xstrdup(name);
|
||||
free(name);
|
||||
name = (char*) malloc(sizeof(char) * (1 + strlen(tmp) + strlen(fwt_ctx.path)));
|
||||
strcpy(name, tmp);
|
||||
strcat(name, fwt_ctx.path);
|
||||
free(tmp);
|
||||
}
|
||||
// cleanup
|
||||
free(fwt_ctx.path);
|
||||
free(fwt_ctx.last_path);
|
||||
cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
|
||||
walk_tree_ctx->curr_rev, fullpath.buf);
|
||||
} else {
|
||||
|
@ -249,6 +311,9 @@ static void ls_tree(const unsigned char *sha1, char *path, struct walk_tree_cont
|
|||
}
|
||||
|
||||
ls_head();
|
||||
walk_tree_ctx->dir_mode = true;
|
||||
read_tree_recursive(tree, "", 0, 1, &paths, ls_item, walk_tree_ctx);
|
||||
walk_tree_ctx->dir_mode = false;
|
||||
read_tree_recursive(tree, "", 0, 1, &paths, ls_item, walk_tree_ctx);
|
||||
ls_tail();
|
||||
}
|
||||
|
@ -268,12 +333,16 @@ static int walk_tree(const unsigned char *sha1, struct strbuf *base,
|
|||
|
||||
if (S_ISDIR(mode)) {
|
||||
walk_tree_ctx->state = 1;
|
||||
set_title_from_path(buffer);
|
||||
ls_head();
|
||||
if (walk_tree_ctx->dir_mode) {
|
||||
set_title_from_path(buffer);
|
||||
ls_head();
|
||||
}
|
||||
return READ_TREE_RECURSIVE;
|
||||
} else {
|
||||
walk_tree_ctx->state = 2;
|
||||
print_object(sha1, buffer, pathname, walk_tree_ctx->curr_rev);
|
||||
if (walk_tree_ctx->dir_mode) {
|
||||
print_object(sha1, buffer, pathname, walk_tree_ctx->curr_rev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -325,6 +394,10 @@ void cgit_print_tree(const char *rev, char *path)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
walk_tree_ctx.dir_mode = true;
|
||||
read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
|
||||
walk_tree_ctx.state = 0;
|
||||
walk_tree_ctx.dir_mode = false;
|
||||
read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
|
||||
if (walk_tree_ctx.state == 1)
|
||||
ls_tail();
|
||||
|
|
Loading…
Add table
Reference in a new issue