]> gitweb.ps.run Git - ps-cgit/commitdiff
Merge branch 'jp/defbranch'
authorLars Hjemli <hjemli@gmail.com>
Sun, 18 Mar 2012 21:00:18 +0000 (21:00 +0000)
committerLars Hjemli <hjemli@gmail.com>
Sun, 18 Mar 2012 21:00:18 +0000 (21:00 +0000)
21 files changed:
Makefile
cgit.c
cgit.css
cgit.h
cgitrc.5.txt
filters/commit-links.sh
filters/syntax-highlighting.sh
html.c
parsing.c
shared.c
tests/setup.sh
tests/t0108-patch.sh
ui-diff.c
ui-log.c
ui-plain.c
ui-repolist.c
ui-shared.c
ui-shared.h
ui-ssdiff.c
ui-ssdiff.h
ui-tree.c

index f6d6968f6e2aa39c8d318c4597a5b1026379a610..eac24add8dbef19b526a999c56b67d435aa0e1f3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CGIT_VERSION = v0.9.0.1
+CGIT_VERSION = v0.9.0.3
 CGIT_SCRIPT_NAME = cgit.cgi
 CGIT_SCRIPT_PATH = /var/www/htdocs/cgit
 CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH)
@@ -13,7 +13,7 @@ pdfdir = $(docdir)
 mandir = $(prefix)/share/man
 SHA1_HEADER = <openssl/sha.h>
 GIT_VER = 1.7.4
-GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2
+GIT_URL = http://hjemli.net/git/git/snapshot/git-$(GIT_VER).tar.bz2
 INSTALL = install
 MAN5_TXT = $(wildcard *.5.txt)
 MAN_TXT  = $(MAN5_TXT)
@@ -198,9 +198,9 @@ install-pdf: doc-pdf
        $(INSTALL) -m 0644 $(DOC_PDF) $(DESTDIR)$(pdfdir)
 
 uninstall:
-       rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
-       rm -f $(CGIT_DATA_PATH)/cgit.css
-       rm -f $(CGIT_DATA_PATH)/cgit.png
+       rm -f $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
+       rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css
+       rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png
 
 uninstall-doc: uninstall-man uninstall-html uninstall-pdf
 
diff --git a/cgit.c b/cgit.c
index 624cb2c1282369be19a283ade86dd8e9fc5837cc..6a75f2706ff0c711e8c3f38ae20d3be867b858bd 100644 (file)
--- a/cgit.c
+++ b/cgit.c
@@ -60,6 +60,8 @@ static void process_cached_repolist(const char *path);
 
 void repo_config(struct cgit_repo *repo, const char *name, const char *value)
 {
+       struct string_list_item *item;
+
        if (!strcmp(name, "name"))
                repo->name = xstrdup(value);
        else if (!strcmp(name, "clone-url"))
@@ -86,7 +88,10 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value)
                repo->max_stats = cgit_find_stats_period(value, NULL);
        else if (!strcmp(name, "module-link"))
                repo->module_link= xstrdup(value);
-       else if (!strcmp(name, "section"))
+       else if (!prefixcmp(name, "module-link.")) {
+               item = string_list_append(&repo->submodules, name + 12);
+               item->util = xstrdup(value);
+       } else if (!strcmp(name, "section"))
                repo->section = xstrdup(value);
        else if (!strcmp(name, "readme") && value != NULL)
                repo->readme = xstrdup(value);
@@ -298,6 +303,7 @@ static void querystring_cb(const char *name, const char *value)
                ctx.qry.period = xstrdup(value);
        } else if (!strcmp(name, "ss")) {
                ctx.qry.ssdiff = atoi(value);
+               ctx.qry.has_ssdiff = 1;
        } else if (!strcmp(name, "all")) {
                ctx.qry.show_all = atoi(value);
        } else if (!strcmp(name, "context")) {
@@ -338,7 +344,6 @@ static void prepare_context(struct cgit_context *ctx)
        ctx->cfg.max_repodesc_len = 80;
        ctx->cfg.max_blob_size = 0;
        ctx->cfg.max_stats = 0;
-       ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
        ctx->cfg.project_list = NULL;
        ctx->cfg.renamelimit = -1;
        ctx->cfg.remove_suffix = 0;
@@ -482,6 +487,7 @@ static int prepare_repo_cmd(struct cgit_context *ctx)
                cgit_print_docend();
                return 1;
        }
+       sort_string_list(&ctx->repo->submodules);
        cgit_prepare_repo_env(ctx->repo);
        return 0;
 }
index 55afa94690c3df2983beced1d4fb19138ccd085b..e06c261e4c11ff8d6c3f710fd8825547adfb6bbb 100644 (file)
--- a/cgit.css
+++ b/cgit.css
@@ -1,4 +1,4 @@
-body, table, form {
+body, div#cgit table, div#cgit form {
        padding: 0em;
        margin: 0em;
 }
@@ -11,39 +11,40 @@ body {
        padding: 4px;
 }
 
-a {
+div#cgit a {
        color: blue;
        text-decoration: none;
 }
 
-a:hover {
+div#cgit a:hover {
        text-decoration: underline;
 }
 
-table {
+div#cgit table {
       border-collapse: collapse;
 }
 
-table#header {
+div#cgit table#header {
        width: 100%;
        margin-bottom: 1em;
 }
 
-table#header td.logo {
+div#cgit table#header td.logo {
        width: 96px;
+       vertical-align: top;
 }
 
-table#header td.main {
+div#cgit table#header td.main {
        font-size: 250%;
        padding-left: 10px;
        white-space: nowrap;
 }
 
-table#header td.main a {
+div#cgit table#header td.main a {
        color: #000;
 }
 
-table#header td.form {
+div#cgit table#header td.form {
        text-align: right;
        vertical-align: bottom;
        padding-right: 1em;
@@ -51,19 +52,19 @@ table#header td.form {
        white-space: nowrap;
 }
 
-table#header td.form form,
-table#header td.form input,
-table#header td.form select {
+div#cgit table#header td.form form,
+div#cgit table#header td.form input,
+div#cgit table#header td.form select {
        font-size: 90%;
 }
 
-table#header td.sub {
+div#cgit table#header td.sub {
        color: #777;
        border-top: solid 1px #ccc;
        padding-left: 10px;
 }
 
-table.tabs {
+div#cgit table.tabs {
        border-bottom: solid 3px #ccc;
        border-collapse: collapse;
        margin-top: 2em;
@@ -71,74 +72,74 @@ table.tabs {
        width: 100%;
 }
 
-table.tabs td {
+div#cgit table.tabs td {
        padding: 0px 1em;
        vertical-align: bottom;
 }
 
-table.tabs td a {
+div#cgit table.tabs td a {
        padding: 2px 0.75em;
        color: #777;
        font-size: 110%;
 }
 
-table.tabs td a.active {
+div#cgit table.tabs td a.active {
        color: #000;
        background-color: #ccc;
 }
 
-table.tabs td.form {
+div#cgit table.tabs td.form {
        text-align: right;
 }
 
-table.tabs td.form form {
+div#cgit table.tabs td.form form {
        padding-bottom: 2px;
        font-size: 90%;
        white-space: nowrap;
 }
 
-table.tabs td.form input,
-table.tabs td.form select {
+div#cgit table.tabs td.form input,
+div#cgit table.tabs td.form select {
        font-size: 90%;
 }
 
-div.path {
+div#cgit div.path {
        margin: 0px;
        padding: 5px 2em 2px 2em;
        color: #000;
        background-color: #eee;
 }
 
-div.content {
+div#cgit div.content {
        margin: 0px;
        padding: 2em;
        border-bottom: solid 3px #ccc;
 }
 
 
-table.list {
+div#cgit table.list {
        width: 100%;
        border: none;
        border-collapse: collapse;
 }
 
-table.list tr {
+div#cgit table.list tr {
        background: white;
 }
 
-table.list tr.logheader {
+div#cgit table.list tr.logheader {
        background: #eee;
 }
 
-table.list tr:hover {
+div#cgit table.list tr:hover {
        background: #eee;
 }
 
-table.list tr.nohover:hover {
+div#cgit table.list tr.nohover:hover {
        background: white;
 }
 
-table.list th {
+div#cgit table.list th {
        font-weight: bold;
        /* color: #888;
        border-top: dashed 1px #888;
@@ -148,93 +149,93 @@ table.list th {
        vertical-align: baseline;
 }
 
-table.list td {
+div#cgit table.list td {
        border: none;
        padding: 0.1em 0.5em 0.1em 0.5em;
 }
 
-table.list td.commitgraph {
+div#cgit table.list td.commitgraph {
        font-family: monospace;
        white-space: pre;
 }
 
-table.list td.commitgraph .column1 {
+div#cgit table.list td.commitgraph .column1 {
        color: #a00;
 }
 
-table.list td.commitgraph .column2 {
+div#cgit table.list td.commitgraph .column2 {
        color: #0a0;
 }
 
-table.list td.commitgraph .column3 {
+div#cgit table.list td.commitgraph .column3 {
        color: #aa0;
 }
 
-table.list td.commitgraph .column4 {
+div#cgit table.list td.commitgraph .column4 {
        color: #00a;
 }
 
-table.list td.commitgraph .column5 {
+div#cgit table.list td.commitgraph .column5 {
        color: #a0a;
 }
 
-table.list td.commitgraph .column6 {
+div#cgit table.list td.commitgraph .column6 {
        color: #0aa;
 }
 
-table.list td.logsubject {
+div#cgit table.list td.logsubject {
        font-family: monospace;
        font-weight: bold;
 }
 
-table.list td.logmsg {
+div#cgit table.list td.logmsg {
        font-family: monospace;
        white-space: pre;
        padding: 0 0.5em;
 }
 
-table.list td a {
+div#cgit table.list td a {
        color: black;
 }
 
-table.list td a.ls-dir {
+div#cgit table.list td a.ls-dir {
        font-weight: bold;
        color: #00f;
 }
 
-table.list td a:hover {
+div#cgit table.list td a:hover {
        color: #00f;
 }
 
-img {
+div#cgit img {
        border: none;
 }
 
-input#switch-btn {
+div#cgit input#switch-btn {
        margin: 2px 0px 0px 0px;
 }
 
-td#sidebar input.txt {
+div#cgit td#sidebar input.txt {
        width: 100%;
        margin: 2px 0px 0px 0px;
 }
 
-table#grid {
+div#cgit table#grid {
        margin: 0px;
 }
 
-td#content {
+div#cgit td#content {
        vertical-align: top;
        padding: 1em 2em 1em 1em;
        border: none;
 }
 
-div#summary {
+div#cgit div#summary {
        vertical-align: top;
        margin-bottom: 1em;
 }
 
-table#downloads {
+div#cgit table#downloads {
        float: right;
        border-collapse: collapse;
        border: solid 1px #777;
@@ -242,152 +243,152 @@ table#downloads {
        margin-bottom: 0.5em;
 }
 
-table#downloads th {
+div#cgit table#downloads th {
        background-color: #ccc;
 }
 
-div#blob {
+div#cgit div#blob {
        border: solid 1px black;
 }
 
-div.error {
+div#cgit div.error {
        color: red;
        font-weight: bold;
        margin: 1em 2em;
 }
 
-a.ls-blob, a.ls-dir, a.ls-mod {
+div#cgit a.ls-blob, div#cgit a.ls-dir, div#cgit a.ls-mod {
        font-family: monospace;
 }
 
-td.ls-size {
+div#cgit td.ls-size {
        text-align: right;
        font-family: monospace;
        width: 10em;
 }
 
-td.ls-mode {
+div#cgit td.ls-mode {
        font-family: monospace;
        width: 10em;
 }
 
-table.blob {
+div#cgit table.blob {
        margin-top: 0.5em;
        border-top: solid 1px black;
 }
 
-table.blob td.lines {
+div#cgit table.blob td.lines {
        margin: 0; padding: 0 0 0 0.5em;
        vertical-align: top;
        color: black;
 }
 
-table.blob td.linenumbers {
+div#cgit table.blob td.linenumbers {
        margin: 0; padding: 0 0.5em 0 0.5em;
        vertical-align: top;
        text-align: right;
        border-right: 1px solid gray;
 }
 
-table.blob pre {
+div#cgit table.blob pre {
        padding: 0; margin: 0;
 }
 
-table.blob a.no, table.ssdiff a.no {
+div#cgit table.blob a.no, div#cgit table.ssdiff a.no {
        color: gray;
        text-align: right;
        text-decoration: none;
 }
 
-table.blob a.no a:hover {
+div#cgit table.blob a.no a:hover {
        color: black;
 }
 
-table.bin-blob {
+div#cgit table.bin-blob {
        margin-top: 0.5em;
        border: solid 1px black;
 }
 
-table.bin-blob th {
+div#cgit table.bin-blob th {
        font-family: monospace;
        white-space: pre;
        border: solid 1px #777;
        padding: 0.5em 1em;
 }
 
-table.bin-blob td {
+div#cgit table.bin-blob td {
        font-family: monospace;
        white-space: pre;
        border-left: solid 1px #777;
        padding: 0em 1em;
 }
 
-table.nowrap td {
+div#cgit table.nowrap td {
        white-space: nowrap;
 }
 
-table.commit-info {
+div#cgit table.commit-info {
        border-collapse: collapse;
        margin-top: 1.5em;
 }
 
-div.cgit-panel {
+div#cgit div.cgit-panel {
        float: right;
        margin-top: 1.5em;
 }
 
-div.cgit-panel table {
+div#cgit div.cgit-panel table {
        border-collapse: collapse;
        border: solid 1px #aaa;
        background-color: #eee;
 }
 
-div.cgit-panel th {
+div#cgit div.cgit-panel th {
        text-align: center;
 }
 
-div.cgit-panel td {
+div#cgit div.cgit-panel td {
        padding: 0.25em 0.5em;
 }
 
-div.cgit-panel td.label {
+div#cgit div.cgit-panel td.label {
        padding-right: 0.5em;
 }
 
-div.cgit-panel td.ctrl {
+div#cgit div.cgit-panel td.ctrl {
        padding-left: 0.5em;
 }
 
-table.commit-info th {
+div#cgit table.commit-info th {
        text-align: left;
        font-weight: normal;
        padding: 0.1em 1em 0.1em 0.1em;
        vertical-align: top;
 }
 
-table.commit-info td {
+div#cgit table.commit-info td {
        font-weight: normal;
        padding: 0.1em 1em 0.1em 0.1em;
 }
 
-div.commit-subject {
+div#cgit div.commit-subject {
        font-weight: bold;
        font-size: 125%;
        margin: 1.5em 0em 0.5em 0em;
        padding: 0em;
 }
 
-div.commit-msg {
+div#cgit div.commit-msg {
        white-space: pre;
        font-family: monospace;
 }
 
-div.notes-header {
+div#cgit div.notes-header {
        font-weight: bold;
        padding-top: 1.5em;
 }
 
-div.notes {
+div#cgit div.notes {
        white-space: pre;
        font-family: monospace;
        border: solid 1px #ee9;
@@ -396,22 +397,22 @@ div.notes {
        float: left;
 }
 
-div.notes-footer {
+div#cgit div.notes-footer {
        clear: left;
 }
 
-div.diffstat-header {
+div#cgit div.diffstat-header {
        font-weight: bold;
        padding-top: 1.5em;
 }
 
-table.diffstat {
+div#cgit table.diffstat {
        border-collapse: collapse;
        border: solid 1px #aaa;
        background-color: #eee;
 }
 
-table.diffstat th {
+div#cgit table.diffstat th {
        font-weight: normal;
        text-align: left;
        text-decoration: underline;
@@ -419,282 +420,286 @@ table.diffstat th {
        font-size: 100%;
 }
 
-table.diffstat td {
+div#cgit table.diffstat td {
        padding: 0.2em 0.2em 0.1em 0.1em;
        font-size: 100%;
        border: none;
 }
 
-table.diffstat td.mode {
+div#cgit table.diffstat td.mode {
        white-space: nowrap;
 }
 
-table.diffstat td span.modechange {
+div#cgit table.diffstat td span.modechange {
        padding-left: 1em;
        color: red;
 }
 
-table.diffstat td.add a {
+div#cgit table.diffstat td.add a {
        color: green;
 }
 
-table.diffstat td.del a {
+div#cgit table.diffstat td.del a {
        color: red;
 }
 
-table.diffstat td.upd a {
+div#cgit table.diffstat td.upd a {
        color: blue;
 }
 
-table.diffstat td.graph {
+div#cgit table.diffstat td.graph {
        width: 500px;
        vertical-align: middle;
 }
 
-table.diffstat td.graph table {
+div#cgit table.diffstat td.graph table {
        border: none;
 }
 
-table.diffstat td.graph td {
+div#cgit table.diffstat td.graph td {
        padding: 0px;
        border: 0px;
        height: 7pt;
 }
 
-table.diffstat td.graph td.add {
+div#cgit table.diffstat td.graph td.add {
        background-color: #5c5;
 }
 
-table.diffstat td.graph td.rem {
+div#cgit table.diffstat td.graph td.rem {
        background-color: #c55;
 }
 
-div.diffstat-summary {
+div#cgit div.diffstat-summary {
        color: #888;
        padding-top: 0.5em;
 }
 
-table.diff {
+div#cgit table.diff {
        width: 100%;
 }
 
-table.diff td {
+div#cgit table.diff td {
        font-family: monospace;
        white-space: pre;
 }
 
-table.diff td div.head {
+div#cgit table.diff td div.head {
        font-weight: bold;
        margin-top: 1em;
        color: black;
 }
 
-table.diff td div.hunk {
+div#cgit table.diff td div.hunk {
        color: #009;
 }
 
-table.diff td div.add {
+div#cgit table.diff td div.add {
        color: green;
 }
 
-table.diff td div.del {
+div#cgit table.diff td div.del {
        color: red;
 }
 
-.sha1 {
+div#cgit .sha1 {
        font-family: monospace;
        font-size: 90%;
 }
 
-.left {
+div#cgit .left {
        text-align: left;
 }
 
-.right {
+div#cgit .right {
        text-align: right;
 }
 
-table.list td.reposection {
+div#cgit table.list td.reposection {
        font-style: italic;
        color: #888;
 }
 
-a.button {
+div#cgit a.button {
        font-size: 80%;
        padding: 0em 0.5em;
 }
 
-a.primary {
+div#cgit a.primary {
        font-size: 100%;
 }
 
-a.secondary {
+div#cgit a.secondary {
        font-size: 90%;
 }
 
-td.toplevel-repo {
+div#cgit td.toplevel-repo {
 
 }
 
-table.list td.sublevel-repo {
+div#cgit table.list td.sublevel-repo {
        padding-left: 1.5em;
 }
 
-div.pager {
+div#cgit div.pager {
        text-align: center;
        margin: 1em 0em 0em 0em;
 }
 
-div.pager a {
+div#cgit div.pager a {
        color: #777;
        margin: 0em 0.5em;
 }
 
-span.age-mins {
+div#cgit span.age-mins {
        font-weight: bold;
        color: #080;
 }
 
-span.age-hours {
+div#cgit span.age-hours {
        color: #080;
 }
 
-span.age-days {
+div#cgit span.age-days {
        color: #040;
 }
 
-span.age-weeks {
+div#cgit span.age-weeks {
        color: #444;
 }
 
-span.age-months {
+div#cgit span.age-months {
        color: #888;
 }
 
-span.age-years {
+div#cgit span.age-years {
        color: #bbb;
 }
-div.footer {
+div#cgit div.footer {
        margin-top: 0.5em;
        text-align: center;
        font-size: 80%;
        color: #ccc;
 }
-a.branch-deco {
+div#cgit a.branch-deco {
+       color: #000;
        margin: 0px 0.5em;
        padding: 0px 0.25em;
        background-color: #88ff88;
        border: solid 1px #007700;
 }
-a.tag-deco {
+div#cgit a.tag-deco {
+       color: #000;
        margin: 0px 0.5em;
        padding: 0px 0.25em;
        background-color: #ffff88;
        border: solid 1px #777700;
 }
-a.remote-deco {
+div#cgit a.remote-deco {
+       color: #000;
        margin: 0px 0.5em;
        padding: 0px 0.25em;
        background-color: #ccccff;
        border: solid 1px #000077;
 }
-a.deco {
+div#cgit a.deco {
+       color: #000;
        margin: 0px 0.5em;
        padding: 0px 0.25em;
        background-color: #ff8888;
        border: solid 1px #770000;
 }
 
-div.commit-subject a.branch-deco,
-div.commit-subject a.tag-deco,
-div.commit-subject a.remote-deco,
-div.commit-subject a.deco {
+div#cgit div.commit-subject a.branch-deco,
+div#cgit div.commit-subject a.tag-deco,
+div#cgit div.commit-subject a.remote-deco,
+div#cgit div.commit-subject a.deco {
        margin-left: 1em;
        font-size: 75%;
 }
 
-table.stats {
+div#cgit table.stats {
        border: solid 1px black;
        border-collapse: collapse;
 }
 
-table.stats th {
+div#cgit table.stats th {
        text-align: left;
        padding: 1px 0.5em;
        background-color: #eee;
        border: solid 1px black;
 }
 
-table.stats td {
+div#cgit table.stats td {
        text-align: right;
        padding: 1px 0.5em;
        border: solid 1px black;
 }
 
-table.stats td.total {
+div#cgit table.stats td.total {
        font-weight: bold;
        text-align: left;
 }
 
-table.stats td.sum {
+div#cgit table.stats td.sum {
        color: #c00;
        font-weight: bold;
 /*     background-color: #eee; */
 }
 
-table.stats td.left {
+div#cgit table.stats td.left {
        text-align: left;
 }
 
-table.vgraph {
+div#cgit table.vgraph {
        border-collapse: separate;
        border: solid 1px black;
        height: 200px;
 }
 
-table.vgraph th {
+div#cgit table.vgraph th {
        background-color: #eee;
        font-weight: bold;
        border: solid 1px white;
        padding: 1px 0.5em;
 }
 
-table.vgraph td {
+div#cgit table.vgraph td {
        vertical-align: bottom;
        padding: 0px 10px;
 }
 
-table.vgraph div.bar {
+div#cgit table.vgraph div.bar {
        background-color: #eee;
 }
 
-table.hgraph {
+div#cgit table.hgraph {
        border: solid 1px black;
        width: 800px;
 }
 
-table.hgraph th {
+div#cgit table.hgraph th {
        background-color: #eee;
        font-weight: bold;
        border: solid 1px black;
        padding: 1px 0.5em;
 }
 
-table.hgraph td {
-       vertical-align: center;
+div#cgit table.hgraph td {
+       vertical-align: middle;
        padding: 2px 2px;
 }
 
-table.hgraph div.bar {
+div#cgit table.hgraph div.bar {
        background-color: #eee;
        height: 1em;
 }
 
-table.ssdiff {
+div#cgit table.ssdiff {
        width: 100%;
 }
 
-table.ssdiff td {
+div#cgit table.ssdiff td {
        font-size: 75%;
        font-family: monospace;
        white-space: pre;
@@ -703,53 +708,53 @@ table.ssdiff td {
        border-right: solid 1px #aaa;
 }
 
-table.ssdiff td.add {
+div#cgit table.ssdiff td.add {
        color: black;
        background: #cfc;
        min-width: 50%;
 }
 
-table.ssdiff td.add_dark {
+div#cgit table.ssdiff td.add_dark {
        color: black;
        background: #aca;
        min-width: 50%;
 }
 
-table.ssdiff span.add {
+div#cgit table.ssdiff span.add {
        background: #cfc;
        font-weight: bold;
 }
 
-table.ssdiff td.del {
+div#cgit table.ssdiff td.del {
        color: black;
        background: #fcc;
        min-width: 50%;
 }
 
-table.ssdiff td.del_dark {
+div#cgit table.ssdiff td.del_dark {
        color: black;
        background: #caa;
        min-width: 50%;
 }
 
-table.ssdiff span.del {
+div#cgit table.ssdiff span.del {
        background: #fcc;
        font-weight: bold;
 }
 
-table.ssdiff td.changed {
+div#cgit table.ssdiff td.changed {
        color: black;
        background: #ffc;
        min-width: 50%;
 }
 
-table.ssdiff td.changed_dark {
+div#cgit table.ssdiff td.changed_dark {
        color: black;
        background: #cca;
        min-width: 50%;
 }
 
-table.ssdiff td.lineno {
+div#cgit table.ssdiff td.lineno {
        color: black;
        background: #eee;
        text-align: right;
@@ -757,48 +762,48 @@ table.ssdiff td.lineno {
        min-width: 3em;
 }
 
-table.ssdiff td.hunk {
-       color: #black;
+div#cgit table.ssdiff td.hunk {
+       color: black;
        background: #ccf;
        border-top: solid 1px #aaa;
        border-bottom: solid 1px #aaa;
 }
 
-table.ssdiff td.head {
+div#cgit table.ssdiff td.head {
        border-top: solid 1px #aaa;
        border-bottom: solid 1px #aaa;
 }
 
-table.ssdiff td.head div.head {
+div#cgit table.ssdiff td.head div.head {
        font-weight: bold;
        color: black;
 }
 
-table.ssdiff td.foot {
+div#cgit table.ssdiff td.foot {
        border-top: solid 1px #aaa;
         border-left: none;
         border-right: none;
         border-bottom: none;
 }
 
-table.ssdiff td.space {
+div#cgit table.ssdiff td.space {
        border: none;
 }
 
-table.ssdiff td.space div {
+div#cgit table.ssdiff td.space div {
        min-height: 3em;
 }
 
 /* Syntax highlighting */
-table.blob .num  { color:#2928ff; }
-table.blob .esc  { color:#ff00ff; }
-table.blob .str  { color:#ff0000; }
-table.blob .dstr { color:#818100; }
-table.blob .slc  { color:#838183; font-style:italic; }
-table.blob .com  { color:#838183; font-style:italic; }
-table.blob .dir  { color:#008200; }
-table.blob .sym  { color:#000000; }
-table.blob .kwa  { color:#000000; font-weight:bold; }
-table.blob .kwb  { color:#830000; }
-table.blob .kwc  { color:#000000; font-weight:bold; }
-table.blob .kwd  { color:#010181; }
+div#cgit table.blob .num  { color:#2928ff; }
+div#cgit table.blob .esc  { color:#ff00ff; }
+div#cgit table.blob .str  { color:#ff0000; }
+div#cgit table.blob .dstr { color:#818100; }
+div#cgit table.blob .slc  { color:#838183; font-style:italic; }
+div#cgit table.blob .com  { color:#838183; font-style:italic; }
+div#cgit table.blob .dir  { color:#008200; }
+div#cgit table.blob .sym  { color:#000000; }
+div#cgit table.blob .kwa  { color:#000000; font-weight:bold; }
+div#cgit table.blob .kwb  { color:#830000; }
+div#cgit table.blob .kwc  { color:#000000; font-weight:bold; }
+div#cgit table.blob .kwd  { color:#010181; }
diff --git a/cgit.h b/cgit.h
index bad66f0e24849d97d2630ac779792b1388c20494..b7c7ac949cbee102faf96de540129a273a4177c8 100644 (file)
--- a/cgit.h
+++ b/cgit.h
@@ -88,6 +88,7 @@ struct cgit_repo {
        struct cgit_filter *about_filter;
        struct cgit_filter *commit_filter;
        struct cgit_filter *source_filter;
+       struct string_list submodules;
 };
 
 typedef void (*repo_config_fn)(struct cgit_repo *repo, const char *name,
@@ -137,6 +138,7 @@ struct reflist {
 struct cgit_query {
        int has_symref;
        int has_sha1;
+       int has_ssdiff;
        char *raw;
        char *repo;
        char *page;
index c2c56800e097fd599a69788c872f72c205b36619..fab0e0a60e5f27d9e15e0b00680906b7fec6e6f8 100644 (file)
@@ -230,7 +230,7 @@ module-link::
        Text which will be used as the formatstring for a hyperlink when a
        submodule is printed in a directory listing. The arguments for the
        formatstring are the path and SHA1 of the submodule commit. Default
-       value: "./?repo=%s&page=commit&id=%s"
+       value: none.
 
 nocache::
        If set to the value "1" caching will be disabled. This settings is
@@ -418,6 +418,12 @@ repo.module-link::
        formatstring are the path and SHA1 of the submodule commit. Default
        value: <module-link>
 
+repo.module-link.<path>::
+       Text which will be used as the formatstring for a hyperlink when a
+       submodule with the specified subdirectory path is printed in a
+       directory listing. The only argument for the formatstring is the SHA1
+       of the submodule commit. Default value: none.
+
 repo.max-stats::
        Override the default maximum statistics period. Valid values are equal
        to the values specified for the global "max-stats" setting. Default
@@ -501,7 +507,7 @@ Also, all filters are handed the following environment variables:
 
 If a setting is not defined for a repository and the corresponding global
 setting is also not defined (if applicable), then the corresponding
-environment variable will be an empty string.
+environment variable will be unset.
 
 
 MACRO EXPANSION
index d2cd2b33f3ff698ee80ccb1656272340d2d36ff3..58819524ced8eb8f99bec05cfd75f730c27307dc 100755 (executable)
 # CGIT_REPO_CLONE_URL  ( = repo.clone-url setting )
 #
 
+regex=''
+
 # This expression generates links to commits referenced by their SHA1.
 regex=$regex'
-s|\b([0-9a-fA-F]{8,40})\b|<a href="./?id=\1">\1</a>|g'
+s|\b([0-9a-fA-F]{7,40})\b|<a href="./?id=\1">\1</a>|g'
+
 # This expression generates links to a fictional bugtracker.
 regex=$regex'
-s| #([0-9]+)\b|<a href="http://bugs.example.com/?bug=\1">#\1</a>|g'
+s|#([0-9]+)\b|<a href="http://bugs.example.com/?bug=\1">#\1</a>|g'
 
 sed -re "$regex"
index 6283ce92efc62e9cf63d2bd20486af43bec7b489..5fcc9c9219137809affece9872ee544b9085b507 100755 (executable)
@@ -42,4 +42,32 @@ EXTENSION="${BASENAME##*.}"
 # map Makefile and Makefile.* to .mk
 [ "${BASENAME%%.*}" == "Makefile" ] && EXTENSION=mk
 
+# highlight versions 2 and 3 have different commandline options. Specifically,
+# the -X option that is used for version 2 is replaced by the -O xhtml option
+# for version 3.
+#
+# Version 2 can be found (for example) on EPEL 5, while version 3 can be
+# found (for example) on EPEL 6.
+#
+# This is for version 2
 exec highlight --force -f -I -X -S $EXTENSION 2>/dev/null
+
+# This is for version 3
+#
+# On CentOS 6.2 (using highlight from EPEL), when highlight doesn't know about
+# an EXTENSION, it outputs a lua error and _no_ text, even when the --force
+# option is used.
+#
+# Also see the bug reports at:
+# http://sourceforge.net/tracker/?func=detail&aid=3490017&group_id=215618&atid=1034391
+# https://bugzilla.redhat.com/show_bug.cgi?id=795567
+#
+# This workaround can be removed when the bug is fixed upstream and the new
+# version is packaged in most distributions.
+#
+# The workaround is to set the extension to 'txt' (plain text) when highlight
+# exits with an error (doesn't know the format).
+#
+#echo "test" | highlight -f -I -O xhtml -S $EXTENSION &>/dev/null
+#[ ${?} -ne 0 ] && EXTENSION="txt"
+#exec highlight --force -f -I -O xhtml -S $EXTENSION 2>/dev/null
diff --git a/html.c b/html.c
index eb1c25db9b84665c2a23e3ab0a74930ffd81d458..8f6e4f6e0358fa7e6a4cc1bc3ae5e5cdfe8ddbae 100644 (file)
--- a/html.c
+++ b/html.c
@@ -162,7 +162,7 @@ void html_url_path(const char *txt)
 {
        const char *t = txt;
        while(t && *t){
-               int c = *t;
+               unsigned char c = *t;
                const char *e = url_escape_table[c];
                if (e && c!='+' && c!='&') {
                        html_raw(txt, t - txt);
@@ -179,7 +179,7 @@ void html_url_arg(const char *txt)
 {
        const char *t = txt;
        while(t && *t){
-               int c = *t;
+               unsigned char c = *t;
                const char *e = url_escape_table[c];
                if (c == ' ')
                        e = "+";
index 151c0fe468c64174ae260ba9b5ddd2d8de52e81e..602e3de799469ebe8900ee3928638fcac7e850df 100644 (file)
--- a/parsing.c
+++ b/parsing.c
@@ -125,7 +125,7 @@ const char *reencode(char **txt, const char *src_enc, const char *dst_enc)
 struct commitinfo *cgit_parse_commit(struct commit *commit)
 {
        struct commitinfo *ret;
-       char *p = commit->buffer, *t = commit->buffer;
+       char *p = commit->buffer, *t;
 
        ret = xmalloc(sizeof(*ret));
        ret->commit = commit;
index 9c839a94d0aee9ee9a9462c1646af52afef7d92d..0a0e22e7255b0db8b9446c496fa85b58d46e24aa 100644 (file)
--- a/shared.c
+++ b/shared.c
@@ -8,7 +8,6 @@
 
 #include "cgit.h"
 #include <stdio.h>
-#include <linux/limits.h>
 
 struct cgit_repolist cgit_repolist;
 struct cgit_context ctx;
@@ -70,6 +69,7 @@ struct cgit_repo *cgit_add_repo(const char *url)
        ret->commit_filter = ctx.cfg.commit_filter;
        ret->source_filter = ctx.cfg.source_filter;
        ret->clone_url = ctx.cfg.clone_url;
+       ret->submodules.strdup_strings = 1;
        return ret;
 }
 
@@ -392,7 +392,7 @@ void cgit_prepare_repo_env(struct cgit_repo * repo)
        p = env_vars;
        q = p + env_var_count;
        for (; p < q; p++)
-               if (setenv(p->name, p->value, 1))
+               if (p->value && setenv(p->name, p->value, 1))
                        fprintf(stderr, warn, p->name, p->value);
 }
 
index 1e061078a2584b0b74eaa6976cf126896851a231..e3c6c17a307ee49863147f4bc96ae1170c42388c 100755 (executable)
 # run_test 'repo index' 'cgit_url "/" | tidy -e'
 # run_test 'repo summary' 'cgit_url "/foo" | tidy -e'
 
+unset CDPATH
 
 mkrepo() {
        name=$1
        count=$2
        dir=$PWD
        test -d "$name" && return
-       printf "Creating testrepo %s\n" $name
+       printf "Creating testrepo %s\n" "$name"
        mkdir -p "$name"
        cd "$name"
        git init
@@ -40,7 +41,7 @@ mkrepo() {
                git commit -m "add a+b"
                git branch "1+2"
        fi
-       cd $dir
+       cd "$dir"
 }
 
 setup_repos()
index e608104733c299340c472eac9ed6e0408b966cd5..6ee70b31f7546ceecf7ab9b1dca1359955f0b8f6 100755 (executable)
@@ -25,7 +25,7 @@ run_test 'find `cgit` signature' '
 '
 
 run_test 'find initial commit' '
-       root=$(git --git-dir=$PWD/trash/repos/foo/.git rev-list HEAD | tail -1)
+       root=$(git --git-dir="$PWD/trash/repos/foo/.git" rev-list HEAD | tail -1)
 '
 
 run_test 'generate patch for initial commit' '
index 868ceec23b813f8dbd39b9eda8249131caa308e3..c6bad6374b0f1074b6cd7d86ea37c9c857365754 100644 (file)
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -97,10 +97,12 @@ static void print_fileinfo(struct fileinfo *info)
        htmlf("</td><td class='%s'>", class);
        cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1,
                       ctx.qry.sha2, info->new_path, 0);
-       if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED)
-               htmlf(" (%s from %s)",
-                     info->status == DIFF_STATUS_COPIED ? "copied" : "renamed",
-                     info->old_path);
+       if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) {
+               htmlf(" (%s from ",
+                     info->status == DIFF_STATUS_COPIED ? "copied" : "renamed");
+               html_txt(info->old_path);
+               html(")");
+       }
        html("</td><td class='right'>");
        if (info->binary) {
                htmlf("bin</td><td class='graph'>%ld -> %ld bytes",
@@ -339,9 +341,7 @@ void cgit_print_diff_ctrls()
        html("<td class='label'>mode:</td>");
        html("<td class='ctrl'>");
        html("<select name='ss' onchange='this.form.submit();'>");
-       curr = ctx.qry.ssdiff;
-       if (!curr && ctx.cfg.ssdiff)
-               curr = 1;
+       curr = ctx.qry.has_ssdiff ? ctx.qry.ssdiff : ctx.cfg.ssdiff;
        html_intoption(0, "unified", curr);
        html_intoption(1, "ssdiff", curr);
        html("</select></td></tr>");
@@ -393,8 +393,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev,
                }
        }
 
-       if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff))
-               use_ssdiff = 1;
+       use_ssdiff = ctx.qry.has_ssdiff ? ctx.qry.ssdiff : ctx.cfg.ssdiff;
 
        if (show_ctrls)
                cgit_print_diff_ctrls();
index 4a295bd4a484bb86ba3373a07a62f3b2ed4b1d35..6b12ca2acb845951be734a964725962f4e67cb93 100644 (file)
--- a/ui-log.c
+++ b/ui-log.c
@@ -76,6 +76,8 @@ void show_commit_decorations(struct commit *commit)
                        cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf);
                }
                else if (!prefixcmp(deco->name, "refs/remotes/")) {
+                       if (!ctx.repo->enable_remote_branches)
+                               goto next;
                        strncpy(buf, deco->name + 13, sizeof(buf) - 1);
                        cgit_log_link(buf, NULL, "remote-deco", NULL,
                                      sha1_to_hex(commit->object.sha1),
@@ -88,6 +90,7 @@ void show_commit_decorations(struct commit *commit)
                                         sha1_to_hex(commit->object.sha1),
                                         ctx.qry.vpath, 0);
                }
+next:
                deco = deco->next;
        }
 }
index 733db4de6758b1b00533a9e2581c2895cc4331c0..2abd210c0f5afd1871b00e6d53eaddb929b39ff0 100644 (file)
@@ -97,11 +97,14 @@ static void print_dir_entry(const unsigned char *sha1, const char *base,
        char *fullpath;
 
        fullpath = buildpath(base, baselen, path);
-       if (!S_ISDIR(mode))
+       if (!S_ISDIR(mode) && !S_ISGITLINK(mode))
                fullpath[strlen(fullpath) - 1] = 0;
        html("  <li>");
-       cgit_plain_link(path, NULL, NULL, ctx.qry.head, ctx.qry.sha1,
-                       fullpath);
+       if (S_ISGITLINK(mode)) {
+               cgit_submodule_link(NULL, fullpath, sha1_to_hex(sha1));
+       } else
+               cgit_plain_link(path, NULL, NULL, ctx.qry.head, ctx.qry.sha1,
+                               fullpath);
        html("</li>\n");
        match = 2;
 }
index f21d28d5bc5b5f41207530bd5111553377735cc0..d946f32cd5354021c45637a0af24e1a7653dff92 100644 (file)
@@ -119,13 +119,13 @@ void print_header(int columns)
 }
 
 
-void print_pager(int items, int pagelen, char *search)
+void print_pager(int items, int pagelen, char *search, char *sort)
 {
        int i;
        html("<div class='pager'>");
        for(i = 0; i * pagelen < items; i++)
                cgit_index_link(fmt("[%d]", i+1), fmt("Page %d", i+1), NULL,
-                               search, i * pagelen);
+                               search, sort, i * pagelen);
        html("</div>");
 }
 
@@ -292,7 +292,7 @@ void cgit_print_repolist()
        if (!hits)
                cgit_print_error("No repositories found");
        else if (hits > ctx.cfg.max_repo_count)
-               print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search);
+               print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search, ctx.qry.sort);
        cgit_print_docend();
 }
 
index 5aa911956aa3cbf344b437e15aad761f5cd11d86..43166af4d568125306ff3f88d2f6f97c54d2405e 100644 (file)
@@ -133,7 +133,7 @@ char *cgit_currurl()
                return fmt("%s/", ctx.cfg.virtual_root);
 }
 
-static void site_url(const char *page, const char *search, int ofs)
+static void site_url(const char *page, const char *search, const char *sort, int ofs)
 {
        char *delim = "?";
 
@@ -154,6 +154,12 @@ static void site_url(const char *page, const char *search, int ofs)
                html_attr(search);
                delim = "&";
        }
+       if (sort) {
+               html(delim);
+               html("s=");
+               html_attr(sort);
+               delim = "&";
+       }
        if (ofs) {
                html(delim);
                htmlf("ofs=%d", ofs);
@@ -161,7 +167,7 @@ static void site_url(const char *page, const char *search, int ofs)
 }
 
 static void site_link(const char *page, const char *name, const char *title,
-                     const char *class, const char *search, int ofs)
+                     const char *class, const char *search, const char *sort, int ofs)
 {
        html("<a");
        if (title) {
@@ -175,16 +181,16 @@ static void site_link(const char *page, const char *name, const char *title,
                html("'");
        }
        html(" href='");
-       site_url(page, search, ofs);
+       site_url(page, search, sort, ofs);
        html("'>");
        html_txt(name);
        html("</a>");
 }
 
 void cgit_index_link(const char *name, const char *title, const char *class,
-                    const char *pattern, int ofs)
+                    const char *pattern, const char *sort, int ofs)
 {
-       site_link(NULL, name, title, class, pattern, ofs);
+       site_link(NULL, name, title, class, pattern, sort, ofs);
 }
 
 static char *repolink(const char *title, const char *class, const char *page,
@@ -288,7 +294,7 @@ void cgit_log_link(const char *name, const char *title, const char *class,
        char *delim;
 
        delim = repolink(title, class, "log", head, path);
-       if (rev && strcmp(rev, ctx.qry.head)) {
+       if (rev && ctx.qry.head && strcmp(rev, ctx.qry.head)) {
                html(delim);
                html("id=");
                html_url_arg(rev);
@@ -332,7 +338,7 @@ void cgit_commit_link(char *name, const char *title, const char *class,
        char *delim;
 
        delim = repolink(title, class, "commit", head, path);
-       if (rev && strcmp(rev, ctx.qry.head)) {
+       if (rev && ctx.qry.head && strcmp(rev, ctx.qry.head)) {
                html(delim);
                html("id=");
                html_url_arg(rev);
@@ -428,7 +434,7 @@ void cgit_self_link(char *name, const char *title, const char *class,
                    struct cgit_context *ctx)
 {
        if (!strcmp(ctx->qry.page, "repolist"))
-               return cgit_index_link(name, title, class, ctx->qry.search,
+               return cgit_index_link(name, title, class, ctx->qry.search, ctx->qry.sort,
                                       ctx->qry.ofs);
        else if (!strcmp(ctx->qry.page, "summary"))
                return cgit_summary_link(name, title, class, ctx->qry.head);
@@ -503,6 +509,62 @@ void cgit_object_link(struct object *obj)
        reporevlink(page, name, NULL, NULL, ctx.qry.head, fullrev, NULL);
 }
 
+struct string_list_item *lookup_path(struct string_list *list,
+                                    const char *path)
+{
+       struct string_list_item *item;
+
+       while (path && path[0]) {
+               if ((item = string_list_lookup(list, path)))
+                       return item;
+               if (!(path = strchr(path, '/')))
+                       break;
+               path++;
+       }
+       return NULL;
+}
+
+void cgit_submodule_link(const char *class, char *path, const char *rev)
+{
+       struct string_list *list;
+       struct string_list_item *item;
+       char tail, *dir;
+       size_t len;
+
+       tail = 0;
+       list = &ctx.repo->submodules;
+       item = lookup_path(list, path);
+       if (!item) {
+               len = strlen(path);
+               tail = path[len - 1];
+               if (tail == '/') {
+                       path[len - 1] = 0;
+                       item = lookup_path(list, path);
+               }
+       }
+       html("<a ");
+       if (class)
+               htmlf("class='%s' ", class);
+       html("href='");
+       if (item) {
+               html_attr(fmt(item->util, rev));
+       } else if (ctx.repo->module_link) {
+               dir = strrchr(path, '/');
+               if (dir)
+                       dir++;
+               else
+                       dir = path;
+               html_attr(fmt(ctx.repo->module_link, dir, rev));
+       } else {
+               html("#");
+       }
+       html("'>");
+       html_txt(path);
+       html("</a>");
+       if (item && tail)
+               path[len - 1] = tail;
+}
+
 void cgit_print_date(time_t secs, const char *format, int local_time)
 {
        char buf[64];
@@ -613,7 +675,7 @@ void cgit_print_docstart(struct cgit_context *ctx)
                html_attr(ctx->cfg.favicon);
                html("'/>\n");
        }
-       if (host && ctx->repo) {
+       if (host && ctx->repo && ctx->qry.head) {
                html("<link rel='alternate' title='Atom feed' href='");
                html(cgit_httpscheme());
                html_attr(cgit_hosturl());
@@ -782,7 +844,7 @@ static void print_header(struct cgit_context *ctx)
 
        html("<td class='main'>");
        if (ctx->repo) {
-               cgit_index_link("index", NULL, NULL, NULL, 0);
+               cgit_index_link("index", NULL, NULL, NULL, NULL, 0);
                html(" : ");
                cgit_summary_link(ctx->repo->name, ctx->repo->name, NULL, NULL);
                html("</td><td class='form'>");
@@ -858,10 +920,10 @@ void cgit_print_pageheader(struct cgit_context *ctx)
                html("<input type='submit' value='search'/>\n");
                html("</form>\n");
        } else {
-               site_link(NULL, "index", NULL, hc(ctx, "repolist"), NULL, 0);
+               site_link(NULL, "index", NULL, hc(ctx, "repolist"), NULL, NULL, 0);
                if (ctx->cfg.root_readme)
                        site_link("about", "about", NULL, hc(ctx, "about"),
-                                 NULL, 0);
+                                 NULL, NULL, 0);
                html("</td><td class='form'>");
                html("<form method='get' action='");
                html_attr(cgit_rooturl());
index 3cc12586dfd77c03cf33fffb8dcf3ed8d4a211d8..87a7dac82f85d5d8f9dc391f5fe9a1ffe940c222 100644 (file)
@@ -11,7 +11,7 @@ extern char *cgit_pageurl(const char *reponame, const char *pagename,
                          const char *query);
 
 extern void cgit_index_link(const char *name, const char *title,
-                           const char *class, const char *pattern, int ofs);
+                           const char *class, const char *pattern, const char *sort, int ofs);
 extern void cgit_summary_link(const char *name, const char *title,
                              const char *class, const char *head);
 extern void cgit_tag_link(const char *name, const char *title,
@@ -51,6 +51,9 @@ extern void cgit_self_link(char *name, const char *title,
                           const char *class, struct cgit_context *ctx);
 extern void cgit_object_link(struct object *obj);
 
+extern void cgit_submodule_link(const char *class, char *path,
+                               const char *rev);
+
 extern void cgit_print_error(const char *msg);
 extern void cgit_print_date(time_t secs, const char *format, int local_time);
 extern void cgit_print_age(time_t t, time_t max_relative, const char *format);
index 2481585fb619966173fcde2e4d35ba1614482093..0cff4b82ed46c8bc41e07c1392dd9c8e9e3ff75a 100644 (file)
@@ -2,10 +2,12 @@
 #include "html.h"
 #include "ui-shared.h"
 #include "ui-diff.h"
+#include "ui-ssdiff.h"
 
 extern int use_ssdiff;
 
 static int current_old_line, current_new_line;
+static int **L = NULL;
 
 struct deferred_lines {
        int line_no;
@@ -16,16 +18,40 @@ struct deferred_lines {
 static struct deferred_lines *deferred_old, *deferred_old_last;
 static struct deferred_lines *deferred_new, *deferred_new_last;
 
+static void create_or_reset_lcs_table()
+{
+       int i;
+
+       if (L != NULL) {
+               memset(*L, 0, sizeof(int) * MAX_SSDIFF_SIZE);
+               return;
+       }
+
+       // xcalloc will die if we ran out of memory;
+       // not very helpful for debugging
+       L = (int**)xcalloc(MAX_SSDIFF_M, sizeof(int *));
+       *L = (int*)xcalloc(MAX_SSDIFF_SIZE, sizeof(int));
+
+       for (i = 1; i < MAX_SSDIFF_M; i++) {
+               L[i] = *L + i * MAX_SSDIFF_N;
+       }
+}
+
 static char *longest_common_subsequence(char *A, char *B)
 {
        int i, j, ri;
        int m = strlen(A);
        int n = strlen(B);
-       int L[m + 1][n + 1];
        int tmp1, tmp2;
        int lcs_length;
        char *result;
 
+       // We bail if the lines are too long
+       if (m >= MAX_SSDIFF_M || n >= MAX_SSDIFF_N)
+               return NULL;
+
+       create_or_reset_lcs_table();
+
        for (i = m; i >= 0; i--) {
                for (j = n; j >= 0; j--) {
                        if (A[i] == '\0' || B[j] == '\0') {
@@ -59,6 +85,7 @@ static char *longest_common_subsequence(char *A, char *B)
                        j += 1;
                }
        }
+
        return result;
 }
 
index 64b4b1215adced788d2145cf9b771ed9d669d464..88627e297c8b2091919e6274010d2bb7812ca067 100644 (file)
@@ -1,6 +1,18 @@
 #ifndef UI_SSDIFF_H
 #define UI_SSDIFF_H
 
+/*
+ * ssdiff line limits
+ */
+#ifndef MAX_SSDIFF_M
+#define MAX_SSDIFF_M 128
+#endif
+
+#ifndef MAX_SSDIFF_N
+#define MAX_SSDIFF_N 128
+#endif
+#define MAX_SSDIFF_SIZE ((MAX_SSDIFF_M) * (MAX_SSDIFF_N))
+
 extern void cgit_ssdiff_print_deferred_lines();
 
 extern void cgit_ssdiff_line_cb(char *line, int len);
index 442b6be53d2c6ba6f7f4c17cd53d12da198c6f5d..b1adcc7b21e5044f489f751c21852400a329f322 100644 (file)
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -150,13 +150,7 @@ static int ls_item(const unsigned char *sha1, const char *base, int baselen,
        cgit_print_filemode(mode);
        html("</td><td>");
        if (S_ISGITLINK(mode)) {
-               htmlf("<a class='ls-mod' href='");
-               html_attr(fmt(ctx.repo->module_link,
-                             name,
-                             sha1_to_hex(sha1)));
-               html("'>");
-               html_txt(name);
-               html("</a>");
+               cgit_submodule_link("ls-mod", fullpath, sha1_to_hex(sha1));
        } else if (S_ISDIR(mode)) {
                cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
                               curr_rev, fullpath);
@@ -177,8 +171,9 @@ static int ls_item(const unsigned char *sha1, const char *base, int baselen,
        if (ctx.repo->max_stats)
                cgit_stats_link("stats", NULL, "button", ctx.qry.head,
                                fullpath);
-       cgit_plain_link("plain", NULL, "button", ctx.qry.head, curr_rev,
-                       fullpath);
+       if (!S_ISGITLINK(mode))
+               cgit_plain_link("plain", NULL, "button", ctx.qry.head, curr_rev,
+                               fullpath);
        html("</td></tr>\n");
        free(name);
        return 0;