Compare commits

...
Sign in to create a new pull request.

18 commits

Author SHA1 Message Date
1787404b6a Merge branch 'master' into lookshe/master
Conflicts:
	filters/html-converters/md2html
2016-07-12 09:22:30 +02:00
2209fe5157 highlight flyspray-links in log and refs (FS#144)
plus a bit more cleaner code
2016-02-27 00:20:13 +01:00
98c3bb0e3b check for flyspray-links in summary/refs-page 2016-02-26 10:59:52 +01:00
4d7d10dba5 skip FS# not followed by number correctly 2016-02-26 10:56:11 +01:00
1c1f2a00d2 implementation to link FS#[0-9]+ to flyspray (FS#141) 2016-02-26 10:35:57 +01:00
335423fb9d normal path in title 2016-02-09 22:03:33 +01:00
5aa2eb8047 normalized indenting 2016-02-08 14:17:38 +01:00
70d357f239 reverted changes to run under python 2.6 2016-02-08 14:03:18 +01:00
a4d069bbd9 Merge branch 'master' into flatten_tree 2016-02-08 13:55:06 +01:00
1ca2305975 call read_tree_recursive two times with different context to list directories first 2016-02-02 15:12:42 +01:00
25eb0a096f identify head to use a bit prettier 2016-02-01 14:48:18 +01:00
95be399ab4 author link with correct branches 2016-02-01 14:16:35 +01:00
fbcdeeb500 escaped author link 2016-02-01 13:36:03 +01:00
36a1d663a6 added link to author (similar to gitweb) 2016-02-01 13:26:29 +01:00
86ff85e75a reverted to use old perl markdown converter 2016-01-14 23:56:50 +01:00
2a5c1abeea set ignore whitespace as default 2016-01-14 23:26:34 +01:00
87dca2dd53 reverted syntax-hightling.py to python2 2016-01-14 20:34:09 +01:00
69bb0352e4 flatten tree for more direct links like github 2016-01-14 20:21:36 +01:00
15 changed files with 1993 additions and 332 deletions

2
cgit.c
View file

@ -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");

View file

@ -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
View file

@ -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 */

View file

@ -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"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
%(stylesheet)s
%(body_pre_docinfo)s
%(docinfo)s
%(body)s

View file

@ -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)

View file

@ -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;
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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);

View file

@ -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&amp;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>");
}

View file

@ -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 */

View file

@ -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
View file

@ -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();