From 5ccd96525835b314c8615738d533d9d0b54a630c Mon Sep 17 00:00:00 2001 From: John Keeping Date: Thu, 24 Nov 2016 18:59:42 +0000 Subject: git: update to v2.10.2 again The submodule was accidentally downgraded in commit 8e9ddd21 (Bump version, 2016-11-23). Restore v2.10.2 so it matches the makefile again. Signed-off-by: John Keeping --- git | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git b/git index 6406bdc..ac84098 160000 --- a/git +++ b/git @@ -1 +1 @@ -Subproject commit 6406bdc0b95715a087fdeeb0f6adf3deb80a25b8 +Subproject commit ac84098b7e32406a982ac01cc76a663d5605224b -- cgit v1.2.3-24-g4f1b From 2b993402c7ed5849606a5bf4d3c7cb212f491b06 Mon Sep 17 00:00:00 2001 From: Peter Colberg Date: Fri, 25 Nov 2016 15:57:11 -0500 Subject: Link with -ldl on GNU Hurd Debian GNU/Hurd uses the GNU C library. Signed-off-by: Peter Colberg --- cgit.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgit.mk b/cgit.mk index 8d4f5e0..90a2346 100644 --- a/cgit.mk +++ b/cgit.mk @@ -54,7 +54,7 @@ endif endif # Add -ldl to linker flags on systems that commonly use GNU libc. -ifneq (,$(filter $(uname_S),Linux GNU/kFreeBSD)) +ifneq (,$(filter $(uname_S),Linux GNU GNU/kFreeBSD)) CGIT_LIBS += -ldl endif -- cgit v1.2.3-24-g4f1b From 91153fd02e62f2eaca8e6c140baa4f2abf39c40e Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 30 Nov 2016 10:43:08 +0100 Subject: git: update to v2.11.0 Update to git version v2.11.0. Function write_archive() dropped argument (int setup_prefix). --- Makefile | 2 +- git | 2 +- ui-snapshot.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1ab2905..fe6cc98 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ htmldir = $(docdir) pdfdir = $(docdir) mandir = $(prefix)/share/man SHA1_HEADER = -GIT_VER = 2.10.2 +GIT_VER = 2.11.0 GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.gz INSTALL = install COPYTREE = cp -r diff --git a/git b/git index ac84098..454cb6b 160000 --- a/git +++ b/git @@ -1 +1 @@ -Subproject commit ac84098b7e32406a982ac01cc76a663d5605224b +Subproject commit 454cb6bd52a4de614a3633e4f547af03d5c3b640 diff --git a/ui-snapshot.c b/ui-snapshot.c index 08c6e80..9b8cddd 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c @@ -37,7 +37,7 @@ static int write_archive_type(const char *format, const char *hex, const char *p /* argv_array guarantees a trailing NULL entry. */ memcpy(nargv, argv.argv, sizeof(char *) * (argv.argc + 1)); - result = write_archive(argv.argc, nargv, NULL, 1, NULL, 0); + result = write_archive(argv.argc, nargv, NULL, NULL, 0); argv_array_clear(&argv); free(nargv); return result; -- cgit v1.2.3-24-g4f1b From 5564a5d06678b3f9b0725bc4b2383ea1b7eb5515 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 22 Jan 2017 12:44:44 +0100 Subject: syntax-highlighting: replace invalid unicode with ? --- filters/syntax-highlighting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/filters/syntax-highlighting.py b/filters/syntax-highlighting.py index 1ca4108..5888b50 100755 --- a/filters/syntax-highlighting.py +++ b/filters/syntax-highlighting.py @@ -30,8 +30,8 @@ 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') +sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8', errors='replace') +sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') data = sys.stdin.read() filename = sys.argv[1] formatter = HtmlFormatter(style='pastie') -- cgit v1.2.3-24-g4f1b From be39d22328f841536b8e44e8aaeed80a74ebb353 Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Thu, 24 Nov 2016 20:14:54 +0100 Subject: ui-patch: fix crash when using path limit The array passed to setup_revisions() must be NULL-terminated. Fixes a regression introduced in 455b598 (ui-patch.c: Use log_tree_commit() to generate diffs, 2013-08-20). Reported-by: Florian Pritz Signed-off-by: Lukas Fleischer --- ui-patch.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ui-patch.c b/ui-patch.c index ec7f352..047e2f9 100644 --- a/ui-patch.c +++ b/ui-patch.c @@ -18,8 +18,8 @@ void cgit_print_patch(const char *new_rev, const char *old_rev, struct commit *commit; struct object_id new_rev_oid, old_rev_oid; char rev_range[2 * 40 + 3]; - const char *rev_argv[] = { NULL, "--reverse", "--format=email", rev_range, "--", prefix }; - int rev_argc = ARRAY_SIZE(rev_argv); + const char *rev_argv[] = { NULL, "--reverse", "--format=email", rev_range, "--", prefix, NULL }; + int rev_argc = ARRAY_SIZE(rev_argv) - 1; char *patchname; if (!prefix) @@ -85,8 +85,7 @@ void cgit_print_patch(const char *new_rev, const char *old_rev, DIFF_FORMAT_PATCH | DIFF_FORMAT_SUMMARY; if (prefix) rev.diffopt.stat_sep = fmt("(limited to '%s')\n\n", prefix); - setup_revisions(ARRAY_SIZE(rev_argv), rev_argv, &rev, - NULL); + setup_revisions(rev_argc, rev_argv, &rev, NULL); prepare_revision_walk(&rev); while ((commit = get_revision(&rev)) != NULL) { -- cgit v1.2.3-24-g4f1b From 87c47488d02fcace4da0d468cd9ddd1651b7949e Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 30 Mar 2017 13:19:50 +0200 Subject: ui-repolist: properly sort by age When empty repos exist, comparing them against an existing repo with a good mtime might, with particular qsort implementations, not sort correctly, because of this brokenness: if (get_repo_modtime(r1, &t) && get_repo_modtime(r2, &t)) However, sorting by the age column works as expected, so anyway, to tidy things up, we simply reuse that function. Signed-off-by: Jason A. Donenfeld --- ui-repolist.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/ui-repolist.c b/ui-repolist.c index b57ea60..20a4f56 100644 --- a/ui-repolist.c +++ b/ui-repolist.c @@ -184,27 +184,6 @@ static int cmp(const char *s1, const char *s2) return 0; } -static int sort_section(const void *a, const void *b) -{ - const struct cgit_repo *r1 = a; - const struct cgit_repo *r2 = b; - int result; - time_t t; - - result = cmp(r1->section, r2->section); - if (!result) { - if (!strcmp(ctx.cfg.repository_sort, "age")) { - // get_repo_modtime caches the value in r->mtime, so we don't - // have to worry about inefficiencies here. - if (get_repo_modtime(r1, &t) && get_repo_modtime(r2, &t)) - result = r2->mtime - r1->mtime; - } - if (!result) - result = cmp(r1->name, r2->name); - } - return result; -} - static int sort_name(const void *a, const void *b) { const struct cgit_repo *r1 = a; @@ -241,6 +220,23 @@ static int sort_idle(const void *a, const void *b) return t2 - t1; } +static int sort_section(const void *a, const void *b) +{ + const struct cgit_repo *r1 = a; + const struct cgit_repo *r2 = b; + int result; + time_t t; + + result = cmp(r1->section, r2->section); + if (!result) { + if (!strcmp(ctx.cfg.repository_sort, "age")) + result = sort_idle(r1, r2); + if (!result) + result = cmp(r1->name, r2->name); + } + return result; +} + struct sortcolumn { const char *name; int (*fn)(const void *a, const void *b); -- cgit v1.2.3-24-g4f1b From 7ebdb30fdf91d1f63b4fb07e54b089136de5507b Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Wed, 5 Apr 2017 06:38:27 +0200 Subject: Remove unused variable from sort_section() Signed-off-by: Lukas Fleischer --- ui-repolist.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ui-repolist.c b/ui-repolist.c index 20a4f56..7272e87 100644 --- a/ui-repolist.c +++ b/ui-repolist.c @@ -225,7 +225,6 @@ static int sort_section(const void *a, const void *b) const struct cgit_repo *r1 = a; const struct cgit_repo *r2 = b; int result; - time_t t; result = cmp(r1->section, r2->section); if (!result) { -- cgit v1.2.3-24-g4f1b From 7ce19ba550ff0d32359b9fb35eeb6282747524b9 Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Thu, 27 Jul 2017 16:20:15 +0200 Subject: Update .mailmap with my new email address Signed-off-by: Lukas Fleischer --- .mailmap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index ca6b57e..03b5479 100644 --- a/.mailmap +++ b/.mailmap @@ -5,6 +5,6 @@ Lars Hjemli Lars Hjemli Lars Hjemli Lars Hjemli -Lukas Fleischer -Lukas Fleischer +Lukas Fleischer +Lukas Fleischer Stefan Bühler -- cgit v1.2.3-24-g4f1b From 3d33b46df24d4dee140d0aafb1eba5fffa314cf0 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Mon, 24 Jul 2017 17:22:52 +0200 Subject: git: update to v2.13.4 Update to git version v2.13.4: With commit 8aee769f (pathspec: copy and free owned memory) the definition of struct pathspec_item has changed with the expectation that pathspecs will be managed dynamically. We work around this a bit by setting up a static structure, but let's allocate the match string to avoid needing to cast away const. Updated a patch from John Keeping for git v2.12.1. --- Makefile | 2 +- git | 2 +- shared.c | 4 +++- ui-blob.c | 9 ++++++--- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index fe6cc98..3d792ce 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ htmldir = $(docdir) pdfdir = $(docdir) mandir = $(prefix)/share/man SHA1_HEADER = -GIT_VER = 2.11.0 +GIT_VER = 2.13.4 GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.gz INSTALL = install COPYTREE = cp -r diff --git a/git b/git index 454cb6b..cf8899d 160000 --- a/git +++ b/git @@ -1 +1 @@ -Subproject commit 454cb6bd52a4de614a3633e4f547af03d5c3b640 +Subproject commit cf8899d285d2648013040ec7196ffd3de0606664 diff --git a/shared.c b/shared.c index c63f1e3..13a65a9 100644 --- a/shared.c +++ b/shared.c @@ -352,7 +352,7 @@ void cgit_diff_tree(const struct object_id *old_oid, opt.format_callback = cgit_diff_tree_cb; opt.format_callback_data = fn; if (prefix) { - item.match = prefix; + item.match = xstrdup(prefix); item.len = strlen(prefix); opt.pathspec.nr = 1; opt.pathspec.items = &item; @@ -365,6 +365,8 @@ void cgit_diff_tree(const struct object_id *old_oid, diff_root_tree_sha1(new_oid->hash, "", &opt); diffcore_std(&opt); diff_flush(&opt); + + free(item.match); } void cgit_diff_commit(struct commit *commit, filepair_fn fn, const char *prefix) diff --git a/ui-blob.c b/ui-blob.c index 5f30de7..793817f 100644 --- a/ui-blob.c +++ b/ui-blob.c @@ -38,7 +38,7 @@ int cgit_ref_path_exists(const char *path, const char *ref, int file_only) struct object_id oid; unsigned long size; struct pathspec_item path_items = { - .match = path, + .match = xstrdup(path), .len = strlen(path) }; struct pathspec paths = { @@ -53,10 +53,13 @@ int cgit_ref_path_exists(const char *path, const char *ref, int file_only) }; if (get_oid(ref, &oid)) - return 0; + goto done; if (sha1_object_info(oid.hash, &size) != OBJ_COMMIT) - return 0; + goto done; read_tree_recursive(lookup_commit_reference(oid.hash)->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); + +done: + free(path_items.match); return walk_tree_ctx.found_path; } -- cgit v1.2.3-24-g4f1b From 86a6d358f7a6c2432fde86b9e3c5011a656f20e4 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Wed, 9 Aug 2017 19:02:56 -0500 Subject: git: update to v2.14 Numerous changes were made to git functions to use an object_id structure rather than sending sha1 hashes as raw unsigned character arrays. The functions that affect cgit are: parse_object, lookup_commit_reference, lookup_tag, lookup_tree, parse_tree_indirect, diff_root_tree_sha1, diff_tree_sha1, and format_display_notes. Commit b2141fc (config: don't include config.h by default) made it necessary to that config.h be explicitly included when needed. Commit 07a3d41 (grep: remove regflags from the public grep_opt API) removed one way of specifying the ignore-case grep option. Signed-off-by: Jeff Smith --- Makefile | 2 +- git | 2 +- scan-tree.c | 5 +++-- shared.c | 6 +++--- ui-blob.c | 6 +++--- ui-clone.c | 2 +- ui-commit.c | 6 +++--- ui-diff.c | 18 +++++++++--------- ui-log.c | 10 +++++----- ui-patch.c | 4 ++-- ui-plain.c | 2 +- ui-snapshot.c | 2 +- ui-tag.c | 4 ++-- ui-tree.c | 18 +++++++++--------- 14 files changed, 44 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index 3d792ce..f3ee84c 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ htmldir = $(docdir) pdfdir = $(docdir) mandir = $(prefix)/share/man SHA1_HEADER = -GIT_VER = 2.13.4 +GIT_VER = 2.14.0 GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.gz INSTALL = install COPYTREE = cp -r diff --git a/git b/git index cf8899d..4384e3c 160000 --- a/git +++ b/git @@ -1 +1 @@ -Subproject commit cf8899d285d2648013040ec7196ffd3de0606664 +Subproject commit 4384e3cde2ce8ecd194202e171ae16333d241326 diff --git a/scan-tree.c b/scan-tree.c index 08f3f1d..6a2f65a 100644 --- a/scan-tree.c +++ b/scan-tree.c @@ -10,6 +10,7 @@ #include "scan-tree.h" #include "configfile.h" #include "html.h" +#include /* return 1 if path contains a objects/ directory and a HEAD file */ static int is_git_dir(const char *path) @@ -48,7 +49,7 @@ out: static struct cgit_repo *repo; static repo_config_fn config_fn; -static void repo_config(const char *name, const char *value) +static void scan_tree_repo_config(const char *name, const char *value) { config_fn(repo, name, value); } @@ -178,7 +179,7 @@ static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) strbuf_addstr(path, "cgitrc"); if (!stat(path->buf, &st)) - parse_configfile(path->buf, &repo_config); + parse_configfile(path->buf, &scan_tree_repo_config); strbuf_release(&rel); } diff --git a/shared.c b/shared.c index 13a65a9..df3f611 100644 --- a/shared.c +++ b/shared.c @@ -160,7 +160,7 @@ static struct refinfo *cgit_mk_refinfo(const char *refname, const struct object_ ref = xmalloc(sizeof (struct refinfo)); ref->refname = xstrdup(refname); - ref->object = parse_object(oid->hash); + ref->object = parse_object(oid); switch (ref->object->type) { case OBJ_TAG: ref->tag = cgit_parse_tag((struct tag *)ref->object); @@ -360,9 +360,9 @@ void cgit_diff_tree(const struct object_id *old_oid, diff_setup_done(&opt); if (old_oid && !is_null_oid(old_oid)) - diff_tree_sha1(old_oid->hash, new_oid->hash, "", &opt); + diff_tree_oid(old_oid, new_oid, "", &opt); else - diff_root_tree_sha1(new_oid->hash, "", &opt); + diff_root_tree_oid(new_oid, "", &opt); diffcore_std(&opt); diff_flush(&opt); diff --git a/ui-blob.c b/ui-blob.c index 793817f..761e886 100644 --- a/ui-blob.c +++ b/ui-blob.c @@ -56,7 +56,7 @@ int cgit_ref_path_exists(const char *path, const char *ref, int file_only) goto done; if (sha1_object_info(oid.hash, &size) != OBJ_COMMIT) goto done; - read_tree_recursive(lookup_commit_reference(oid.hash)->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); + read_tree_recursive(lookup_commit_reference(&oid)->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); done: free(path_items.match); @@ -89,7 +89,7 @@ int cgit_print_file(char *path, const char *head, int file_only) return -1; type = sha1_object_info(oid.hash, &size); if (type == OBJ_COMMIT) { - commit = lookup_commit_reference(oid.hash); + commit = lookup_commit_reference(&oid); read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); if (!walk_tree_ctx.found_path) return -1; @@ -145,7 +145,7 @@ void cgit_print_blob(const char *hex, char *path, const char *head, int file_onl type = sha1_object_info(oid.hash, &size); if ((!hex) && type == OBJ_COMMIT && path) { - commit = lookup_commit_reference(oid.hash); + commit = lookup_commit_reference(&oid); read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); type = sha1_object_info(oid.hash, &size); } diff --git a/ui-clone.c b/ui-clone.c index 5f6606a..0d11672 100644 --- a/ui-clone.c +++ b/ui-clone.c @@ -17,7 +17,7 @@ static int print_ref_info(const char *refname, const struct object_id *oid, { struct object *obj; - if (!(obj = parse_object(oid->hash))) + if (!(obj = parse_object(oid))) return 0; htmlf("%s\t%s\n", oid_to_hex(oid), refname); diff --git a/ui-commit.c b/ui-commit.c index db69d54..586fea0 100644 --- a/ui-commit.c +++ b/ui-commit.c @@ -31,7 +31,7 @@ void cgit_print_commit(char *hex, const char *prefix) "Bad object id: %s", hex); return; } - commit = lookup_commit_reference(oid.hash); + commit = lookup_commit_reference(&oid); if (!commit) { cgit_print_error_page(404, "Not found", "Bad commit reference: %s", hex); @@ -39,7 +39,7 @@ void cgit_print_commit(char *hex, const char *prefix) } info = cgit_parse_commit(commit); - format_display_notes(oid.hash, ¬es, PAGE_ENCODING, 0); + format_display_notes(&oid, ¬es, PAGE_ENCODING, 0); load_ref_decorations(DECORATE_FULL_REFS); @@ -87,7 +87,7 @@ void cgit_print_commit(char *hex, const char *prefix) free(tmp); html("\n"); for (p = commit->parents; p; p = p->next) { - parent = lookup_commit_reference(p->item->object.oid.hash); + parent = lookup_commit_reference(&p->item->object.oid); if (!parent) { html(""); cgit_print_error("Error reading parent commit"); diff --git a/ui-diff.c b/ui-diff.c index 173d351..c7fb49b 100644 --- a/ui-diff.c +++ b/ui-diff.c @@ -385,7 +385,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix, int show_ctrls, int raw) { struct commit *commit, *commit2; - const unsigned char *old_tree_sha1, *new_tree_sha1; + const struct object_id *old_tree_oid, *new_tree_oid; diff_type difftype; /* @@ -407,13 +407,13 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, "Bad object name: %s", new_rev); return; } - commit = lookup_commit_reference(new_rev_oid->hash); + commit = lookup_commit_reference(new_rev_oid); if (!commit || parse_commit(commit)) { cgit_print_error_page(404, "Not found", "Bad commit: %s", oid_to_hex(new_rev_oid)); return; } - new_tree_sha1 = commit->tree->object.oid.hash; + new_tree_oid = &commit->tree->object.oid; if (old_rev) { if (get_oid(old_rev, old_rev_oid)) { @@ -428,15 +428,15 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, } if (!is_null_oid(old_rev_oid)) { - commit2 = lookup_commit_reference(old_rev_oid->hash); + commit2 = lookup_commit_reference(old_rev_oid); if (!commit2 || parse_commit(commit2)) { cgit_print_error_page(404, "Not found", "Bad commit: %s", oid_to_hex(old_rev_oid)); return; } - old_tree_sha1 = commit2->tree->object.oid.hash; + old_tree_oid = &commit2->tree->object.oid; } else { - old_tree_sha1 = NULL; + old_tree_oid = NULL; } if (raw) { @@ -449,11 +449,11 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, ctx.page.mimetype = "text/plain"; cgit_print_http_headers(); - if (old_tree_sha1) { - diff_tree_sha1(old_tree_sha1, new_tree_sha1, "", + if (old_tree_oid) { + diff_tree_oid(old_tree_oid, new_tree_oid, "", &diffopt); } else { - diff_root_tree_sha1(new_tree_sha1, "", &diffopt); + diff_root_tree_oid(new_tree_oid, "", &diffopt); } diffcore_std(&diffopt); diff_flush(&diffopt); diff --git a/ui-log.c b/ui-log.c index 3220fd9..2d2bb31 100644 --- a/ui-log.c +++ b/ui-log.c @@ -150,9 +150,9 @@ static int show_commit(struct commit *commit, struct rev_info *revs) rem_lines = 0; DIFF_OPT_SET(&revs->diffopt, RECURSIVE); - diff_tree_sha1(parent->tree->object.oid.hash, - commit->tree->object.oid.hash, - "", &revs->diffopt); + diff_tree_oid(&parent->tree->object.oid, + &commit->tree->object.oid, + "", &revs->diffopt); diffcore_std(&revs->diffopt); found = !diff_queue_is_empty(); @@ -273,7 +273,7 @@ static void print_commit(struct commit *commit, struct rev_info *revs) strbuf_addstr(&msgbuf, info->msg); strbuf_addch(&msgbuf, '\n'); } - format_display_notes(commit->object.oid.hash, + format_display_notes(&commit->object.oid, &msgbuf, PAGE_ENCODING, 0); strbuf_addch(&msgbuf, '\n'); strbuf_ltrim(&msgbuf); @@ -436,7 +436,7 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern setup_revisions(rev_argv.argc, rev_argv.argv, &rev, NULL); load_ref_decorations(DECORATE_FULL_REFS); rev.show_decorations = 1; - rev.grep_filter.regflags |= REG_ICASE; + rev.grep_filter.ignore_case = 1; rev.diffopt.detect_rename = 1; rev.diffopt.rename_limit = ctx.cfg.renamelimit; diff --git a/ui-patch.c b/ui-patch.c index 047e2f9..69aa4a8 100644 --- a/ui-patch.c +++ b/ui-patch.c @@ -33,7 +33,7 @@ void cgit_print_patch(const char *new_rev, const char *old_rev, "Bad object id: %s", new_rev); return; } - commit = lookup_commit_reference(new_rev_oid.hash); + commit = lookup_commit_reference(&new_rev_oid); if (!commit) { cgit_print_error_page(404, "Not found", "Bad commit reference: %s", new_rev); @@ -46,7 +46,7 @@ void cgit_print_patch(const char *new_rev, const char *old_rev, "Bad object id: %s", old_rev); return; } - if (!lookup_commit_reference(old_rev_oid.hash)) { + if (!lookup_commit_reference(&old_rev_oid)) { cgit_print_error_page(404, "Not found", "Bad commit reference: %s", old_rev); return; diff --git a/ui-plain.c b/ui-plain.c index 8d541e3..e45d553 100644 --- a/ui-plain.c +++ b/ui-plain.c @@ -185,7 +185,7 @@ void cgit_print_plain(void) cgit_print_error_page(404, "Not found", "Not found"); return; } - commit = lookup_commit_reference(oid.hash); + commit = lookup_commit_reference(&oid); if (!commit || parse_commit(commit)) { cgit_print_error_page(404, "Not found", "Not found"); return; diff --git a/ui-snapshot.c b/ui-snapshot.c index 9b8cddd..b2d95f7 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c @@ -116,7 +116,7 @@ static int make_snapshot(const struct cgit_snapshot_format *format, "Bad object id: %s", hex); return 1; } - if (!lookup_commit_reference(oid.hash)) { + if (!lookup_commit_reference(&oid)) { cgit_print_error_page(400, "Bad request", "Not a commit reference: %s", hex); return 1; diff --git a/ui-tag.c b/ui-tag.c index afd7d61..909cde0 100644 --- a/ui-tag.c +++ b/ui-tag.c @@ -54,7 +54,7 @@ void cgit_print_tag(char *revname) "Bad tag reference: %s", revname); goto cleanup; } - obj = parse_object(oid.hash); + obj = parse_object(&oid); if (!obj) { cgit_print_error_page(500, "Internal server error", "Bad object id: %s", oid_to_hex(&oid)); @@ -64,7 +64,7 @@ void cgit_print_tag(char *revname) struct tag *tag; struct taginfo *info; - tag = lookup_tag(oid.hash); + tag = lookup_tag(&oid); if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) { cgit_print_error_page(500, "Internal server error", "Bad tag object: %s", revname); diff --git a/ui-tree.c b/ui-tree.c index b310242..ca24a03 100644 --- a/ui-tree.c +++ b/ui-tree.c @@ -157,7 +157,7 @@ static void print_object(const unsigned char *sha1, char *path, const char *base struct single_tree_ctx { struct strbuf *path; - unsigned char sha1[GIT_SHA1_RAWSZ]; + struct object_id oid; char *name; size_t count; }; @@ -177,7 +177,7 @@ static int single_tree_cb(const unsigned char *sha1, struct strbuf *base, } ctx->name = xstrdup(pathname); - hashcpy(ctx->sha1, sha1); + hashcpy(ctx->oid.hash, sha1); strbuf_addf(ctx->path, "/%s", pathname); return 0; } @@ -195,13 +195,13 @@ static void write_tree_link(const unsigned char *sha1, char *name, .nr = 0 }; - hashcpy(tree_ctx.sha1, sha1); + hashcpy(tree_ctx.oid.hash, sha1); while (tree_ctx.count == 1) { cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, rev, fullpath->buf); - tree = lookup_tree(tree_ctx.sha1); + tree = lookup_tree(&tree_ctx.oid); if (!tree) return; @@ -300,17 +300,17 @@ static void ls_tail(void) cgit_print_layout_end(); } -static void ls_tree(const unsigned char *sha1, char *path, struct walk_tree_context *walk_tree_ctx) +static void ls_tree(const struct object_id *oid, char *path, struct walk_tree_context *walk_tree_ctx) { struct tree *tree; struct pathspec paths = { .nr = 0 }; - tree = parse_tree_indirect(sha1); + tree = parse_tree_indirect(oid); if (!tree) { cgit_print_error_page(404, "Not found", - "Not a tree object: %s", sha1_to_hex(sha1)); + "Not a tree object: %s", sha1_to_hex(oid->hash)); return; } @@ -380,7 +380,7 @@ void cgit_print_tree(const char *rev, char *path) "Invalid revision name: %s", rev); return; } - commit = lookup_commit_reference(oid.hash); + commit = lookup_commit_reference(&oid); if (!commit || parse_commit(commit)) { cgit_print_error_page(404, "Not found", "Invalid commit reference: %s", rev); @@ -390,7 +390,7 @@ void cgit_print_tree(const char *rev, char *path) walk_tree_ctx.curr_rev = xstrdup(rev); if (path == NULL) { - ls_tree(commit->tree->object.oid.hash, NULL, &walk_tree_ctx); + ls_tree(&commit->tree->object.oid, NULL, &walk_tree_ctx); goto cleanup; } -- cgit v1.2.3-24-g4f1b From 6d3c8bc37f6124c2193d66587079975d381aa435 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Sun, 15 Jan 2017 12:29:38 +0000 Subject: ui-atom: properly escape delimiter in page link If the delimiter here is '&' then it needs to be escaped for inclusion in an attribute. Use html_attrf() to ensure that this happens (we know that hex won't need escaping, but this makes it clearer what's happening. Signed-off-by: John Keeping --- ui-atom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-atom.c b/ui-atom.c index 41838d3..3866823 100644 --- a/ui-atom.c +++ b/ui-atom.c @@ -63,7 +63,7 @@ static void add_entry(struct commit *commit, const char *host) html_attr(pageurl); if (ctx.cfg.virtual_root) delim = '?'; - htmlf("%cid=%s", delim, hex); + html_attrf("%cid=%s", delim, hex); html("'/>\n"); free(pageurl); } -- cgit v1.2.3-24-g4f1b From 1b4ef6783a71962f8b5da3a23f2830f0f0f55ea0 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Sun, 19 Feb 2017 12:27:48 +0000 Subject: ui-shared: don't print path crumbs without a repo cgit_print_path_crumbs() can call repolink() which assumes that ctx.repo is non-null. Currently we don't have any commands that set want_vpath without also setting want_repo so it shouldn't be possible to fail this test, but the check in cgit.c is in the wrong order so it is possible to specify a query string like "?p=log&path=foo/bar" to end up here without a valid repository. This was found by American fuzzy lop [0]. [0] http://lcamtuf.coredump.cx/afl/ Signed-off-by: John Keeping --- ui-shared.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-shared.c b/ui-shared.c index 2e4fcd9..e5c9a02 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -1039,7 +1039,7 @@ void cgit_print_pageheader(void) free(currenturl); } html("\n"); - if (ctx.env.authenticated && ctx.qry.vpath) { + if (ctx.env.authenticated && ctx.repo && ctx.qry.vpath) { html("
"); html("path: "); cgit_print_path_crumbs(ctx.qry.vpath); -- cgit v1.2.3-24-g4f1b From c699866699411346c5dba406457581013f85a873 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Sun, 19 Feb 2017 12:17:05 +0000 Subject: parsing: clear query path before starting By specifying the "url" query parameter multiple times it is possible to end up with ctx.qry.vpath set while ctx.repo is null, which triggers an invalid code path from cgit_print_pageheader() while printing path crumbs, resulting in a null dereference. The previous patch fixed this segfault, but it makes no sense for us to clear ctx.repo while leaving ctx.qry.path set to the previous value, so let's just clear it here so that the last "url" parameter given takes full effect rather than partially overriding the effect of the previous value. Signed-off-by: John Keeping --- parsing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parsing.c b/parsing.c index 9dacb16..b8d7f10 100644 --- a/parsing.c +++ b/parsing.c @@ -21,6 +21,7 @@ void cgit_parse_url(const char *url) struct cgit_repo *repo; ctx.repo = NULL; + ctx.qry.page = NULL; if (!url || url[0] == '\0') return; @@ -53,7 +54,6 @@ void cgit_parse_url(const char *url) } if (cmd[1]) ctx.qry.page = xstrdup(cmd + 1); - return; } } -- cgit v1.2.3-24-g4f1b From 113f4b85886bc5eb6b319fd048623b8d43b7bce0 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Sun, 19 Feb 2017 12:02:37 +0000 Subject: cgit: don't set vpath unless repo is set After the previous two patches, this can be classified as a tidy up rather than a bug fix, but I think it makes sense to group all of the tests together before setting up the environment for the command to execute. Signed-off-by: John Keeping --- cgit.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cgit.c b/cgit.c index 1075753..1dae4b8 100644 --- a/cgit.c +++ b/cgit.c @@ -726,18 +726,18 @@ static void process_request(void) return; } - /* If cmd->want_vpath is set, assume ctx.qry.path contains a "virtual" - * in-project path limit to be made available at ctx.qry.vpath. - * Otherwise, no path limit is in effect (ctx.qry.vpath = NULL). - */ - ctx.qry.vpath = cmd->want_vpath ? ctx.qry.path : NULL; - if (cmd->want_repo && !ctx.repo) { cgit_print_error_page(400, "Bad request", "No repository selected"); return; } + /* If cmd->want_vpath is set, assume ctx.qry.path contains a "virtual" + * in-project path limit to be made available at ctx.qry.vpath. + * Otherwise, no path limit is in effect (ctx.qry.vpath = NULL). + */ + ctx.qry.vpath = cmd->want_vpath ? ctx.qry.path : NULL; + if (ctx.repo && prepare_repo_cmd()) return; -- cgit v1.2.3-24-g4f1b From 51cc456b773a3bb7253fad2146c1a0d2b0fa98cb Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 6 Mar 2017 23:27:23 +0000 Subject: ui-plain: print symlink content We currently ignore symlinks in ui-plain, leading to a 404. In ui-tree we print the content of the blob (that is, the path to the target of the link), so it makes sense to do the same here. Signed-off-by: John Keeping --- ui-plain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-plain.c b/ui-plain.c index e45d553..cfdbf73 100644 --- a/ui-plain.c +++ b/ui-plain.c @@ -135,7 +135,7 @@ static int walk_tree(const unsigned char *sha1, struct strbuf *base, struct walk_tree_context *walk_tree_ctx = cbdata; if (base->len == walk_tree_ctx->match_baselen) { - if (S_ISREG(mode)) { + if (S_ISREG(mode) || S_ISLNK(mode)) { if (print_object(sha1, pathname)) walk_tree_ctx->match = 1; } else if (S_ISDIR(mode)) { -- cgit v1.2.3-24-g4f1b From de297883385030f4bdcd2f5c3839d1187611b949 Mon Sep 17 00:00:00 2001 From: "Daniel M. Weeks" Date: Wed, 20 Sep 2017 11:17:29 -0400 Subject: Use https for submodule The git protocol provides no transport security. https does provide transport security and should be preferred by default. https is also more likely than git to be permitted by firewalls in restricted environments. Signed-off-by: Daniel M. Weeks --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 1daea94..5c6ecb4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "git"] - url = git://git.kernel.org/pub/scm/git/git.git + url = https://git.kernel.org/pub/scm/git/git.git path = git -- cgit v1.2.3-24-g4f1b From 3b485cc5422f800d142c7023295e82c0a1c10b19 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 24 Apr 2017 19:38:34 +0100 Subject: cache: flush stdio before restoring FDs As described in commit 2efb59e (ui-patch: Flush stdout after outputting data, 2014-06-11), we need to ensure that stdout is flushed before restoring the file descriptor when writing to the cache. It turns out that it's not just ui-patch that is affected by this but also raw diff which writes to stdout internally. Let's avoid risking more places doing this by ensuring that stdout is flushed after writing in fill_slot(). Signed-off-by: John Keeping --- cache.c | 6 ++++++ ui-patch.c | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cache.c b/cache.c index 6736a01..2ccdc4e 100644 --- a/cache.c +++ b/cache.c @@ -224,6 +224,12 @@ static int fill_slot(struct cache_slot *slot) /* Generate cache content */ slot->fn(); + /* Make sure any buffered data is flushed to the file */ + if (fflush(stdout)) { + close(tmp); + return errno; + } + /* update stat info */ if (fstat(slot->lock_fd, &slot->cache_st)) { close(tmp); diff --git a/ui-patch.c b/ui-patch.c index 69aa4a8..8007a11 100644 --- a/ui-patch.c +++ b/ui-patch.c @@ -92,6 +92,4 @@ void cgit_print_patch(const char *new_rev, const char *old_rev, log_tree_commit(&rev, commit); printf("-- \ncgit %s\n\n", cgit_version); } - - fflush(stdout); } -- cgit v1.2.3-24-g4f1b From 70787254b270b1505aa8427813f64131be5df86c Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Sun, 1 Oct 2017 23:39:05 -0500 Subject: html: html_ntxt with no ellipsis For implementing a ui-blame page, there is need for a function that outputs a selection from a block of text, transformed for HTML output, but with no further modifications or additions. Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- html.c | 32 +++++++++++--------------------- html.h | 2 +- ui-repolist.c | 3 ++- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/html.c b/html.c index e7e6e07..7f81965 100644 --- a/html.c +++ b/html.c @@ -124,29 +124,20 @@ void html_vtxtf(const char *format, va_list ap) void html_txt(const char *txt) { - const char *t = txt; - while (t && *t) { - int c = *t; - if (c == '<' || c == '>' || c == '&') { - html_raw(txt, t - txt); - if (c == '>') - html(">"); - else if (c == '<') - html("<"); - else if (c == '&') - html("&"); - txt = t + 1; - } - t++; - } - if (t != txt) - html(txt); + if (txt) + html_ntxt(txt, strlen(txt)); } -void html_ntxt(int len, const char *txt) +ssize_t html_ntxt(const char *txt, size_t len) { const char *t = txt; - while (t && *t && len--) { + ssize_t slen; + + if (len > SSIZE_MAX) + return -1; + + slen = (ssize_t) len; + while (t && *t && slen--) { int c = *t; if (c == '<' || c == '>' || c == '&') { html_raw(txt, t - txt); @@ -162,8 +153,7 @@ void html_ntxt(int len, const char *txt) } if (t != txt) html_raw(txt, t - txt); - if (len < 0) - html("..."); + return slen; } void html_attrf(const char *fmt, ...) diff --git a/html.h b/html.h index 1b24e55..fa4de77 100644 --- a/html.h +++ b/html.h @@ -19,7 +19,7 @@ __attribute__((format (printf,1,2))) extern void html_attrf(const char *format,...); extern void html_txt(const char *txt); -extern void html_ntxt(int len, const char *txt); +extern ssize_t html_ntxt(const char *txt, size_t len); extern void html_attr(const char *txt); extern void html_url_path(const char *txt); extern void html_url_arg(const char *txt); diff --git a/ui-repolist.c b/ui-repolist.c index 7272e87..af52f9b 100644 --- a/ui-repolist.c +++ b/ui-repolist.c @@ -329,7 +329,8 @@ void cgit_print_repolist(void) repourl = cgit_repourl(ctx.repo->url); html_link_open(repourl, NULL, NULL); free(repourl); - html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc); + if (html_ntxt(ctx.repo->desc, ctx.cfg.max_repodesc_len) < 0) + html("..."); html_link_close(); html(""); if (ctx.cfg.enable_index_owner) { -- cgit v1.2.3-24-g4f1b From 9337c7ee83221d48d02c3c7b5c9dcbaca23ad92f Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Sun, 1 Oct 2017 23:39:06 -0500 Subject: ui-tree: move set_title_from_path to ui-shared The ui-blame code will also need to call set_title_from_path, so go ahead and move it to ui-shared. Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- ui-shared.c | 31 +++++++++++++++++++++++++++++++ ui-shared.h | 2 ++ ui-tree.c | 35 ++--------------------------------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/ui-shared.c b/ui-shared.c index e5c9a02..2547e43 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -1111,3 +1111,34 @@ void cgit_print_snapshot_links(const char *repo, const char *head, } strbuf_release(&filename); } + +void cgit_set_title_from_path(const char *path) +{ + size_t path_len, path_index, path_last_end; + char *new_title; + + if (!path) + return; + + path_len = strlen(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, " - "); + strcat(new_title, ctx.page.title); + ctx.page.title = new_title; +} diff --git a/ui-shared.h b/ui-shared.h index 87799f1..40f6207 100644 --- a/ui-shared.h +++ b/ui-shared.h @@ -77,4 +77,6 @@ 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_set_title_from_path(const char *path); #endif /* UI_SHARED_H */ diff --git a/ui-tree.c b/ui-tree.c index ca24a03..3925809 100644 --- a/ui-tree.c +++ b/ui-tree.c @@ -84,37 +84,6 @@ static void print_binary_buffer(char *buf, unsigned long size) html("\n"); } -static void set_title_from_path(const char *path) -{ - size_t path_len, path_index, path_last_end; - char *new_title; - - if (!path) - return; - - path_len = strlen(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, " - "); - strcat(new_title, ctx.page.title); - ctx.page.title = new_title; -} - static void print_object(const unsigned char *sha1, char *path, const char *basename, const char *rev) { enum object_type type; @@ -135,7 +104,7 @@ static void print_object(const unsigned char *sha1, char *path, const char *base return; } - set_title_from_path(path); + cgit_set_title_from_path(path); cgit_print_layout_start(); htmlf("blob: %s (", sha1_to_hex(sha1)); @@ -335,7 +304,7 @@ 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.buf); + cgit_set_title_from_path(buffer.buf); strbuf_release(&buffer); ls_head(); return READ_TREE_RECURSIVE; -- cgit v1.2.3-24-g4f1b From f6ffe40d1a2c985494e48dc2d36663ffde1e6044 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Sun, 1 Oct 2017 23:39:07 -0500 Subject: ui-shared: make a char* parameter const All cgit_xxx_link functions take const char* for the 'name' parameter, except for cgit_commit_link, which takes a char* and subsequently modifies the contents. Avoiding the content changes, and making it const char* will avoid the need to make copies of const char* strings being passed to cgit_commit_link. Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- ui-shared.c | 19 ++++++++----------- ui-shared.h | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/ui-shared.c b/ui-shared.c index 2547e43..315dedb 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -347,18 +347,11 @@ void cgit_log_link(const char *name, const char *title, const char *class, html(""); } -void cgit_commit_link(char *name, const char *title, const char *class, +void cgit_commit_link(const char *name, const char *title, const char *class, const char *head, const char *rev, const char *path) { char *delim; - if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) { - name[ctx.cfg.max_msg_len] = '\0'; - name[ctx.cfg.max_msg_len - 1] = '.'; - name[ctx.cfg.max_msg_len - 2] = '.'; - name[ctx.cfg.max_msg_len - 3] = '.'; - } - delim = repolink(title, class, "commit", head, path); if (rev && ctx.qry.head && strcmp(rev, ctx.qry.head)) { html(delim); @@ -387,9 +380,13 @@ void cgit_commit_link(char *name, const char *title, const char *class, html("follow=1"); } html("'>"); - if (name[0] != '\0') - html_txt(name); - else + if (name[0] != '\0') { + if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) { + html_ntxt(name, ctx.cfg.max_msg_len - 3); + html("..."); + } else + html_txt(name); + } else html_txt("(no commit message)"); html(""); } diff --git a/ui-shared.h b/ui-shared.h index 40f6207..2cd7ac9 100644 --- a/ui-shared.h +++ b/ui-shared.h @@ -30,7 +30,7 @@ extern void cgit_log_link(const char *name, const char *title, const char *class, const char *head, const char *rev, const char *path, int ofs, const char *grep, const char *pattern, int showmsg, int follow); -extern void cgit_commit_link(char *name, const char *title, +extern void cgit_commit_link(const 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, -- cgit v1.2.3-24-g4f1b From c1cd290d1f83d3d1c2d081d734e8d213f12cc06b Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Sun, 1 Oct 2017 23:39:08 -0500 Subject: ui-blame: add blame UI Implement a page which provides the blame view of a specified file. This feature is controlled by a new config variable, "enable-blame", which is disabled by default. Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- cgit.c | 2 + cgit.css | 8 +++ cgit.h | 1 + cgit.mk | 1 + cgitrc.5.txt | 9 +++ cmd.c | 12 +++- ui-blame.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ui-blame.h | 6 ++ 8 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 ui-blame.c create mode 100644 ui-blame.h diff --git a/cgit.c b/cgit.c index 1dae4b8..972a67e 100644 --- a/cgit.c +++ b/cgit.c @@ -167,6 +167,8 @@ static void config_cb(const char *name, const char *value) ctx.cfg.enable_index_links = atoi(value); else if (!strcmp(name, "enable-index-owner")) ctx.cfg.enable_index_owner = atoi(value); + else if (!strcmp(name, "enable-blame")) + ctx.cfg.enable_blame = atoi(value); else if (!strcmp(name, "enable-commit-graph")) ctx.cfg.enable_commit_graph = atoi(value); else if (!strcmp(name, "enable-log-filecount")) diff --git a/cgit.css b/cgit.css index 1dc2c11..836f8ae 100644 --- a/cgit.css +++ b/cgit.css @@ -329,6 +329,14 @@ div#cgit table.ssdiff td.lineno a:hover { color: black; } +div#cgit table.blame tr:nth-child(even) { + background: #eee; +} + +div#cgit table.blame tr:nth-child(odd) { + background: white; +} + div#cgit table.bin-blob { margin-top: 0.5em; border: solid 1px black; diff --git a/cgit.h b/cgit.h index fbc6c6a..0b88dcd 100644 --- a/cgit.h +++ b/cgit.h @@ -228,6 +228,7 @@ struct cgit_config { int enable_http_clone; int enable_index_links; int enable_index_owner; + int enable_blame; int enable_commit_graph; int enable_log_filecount; int enable_log_linecount; diff --git a/cgit.mk b/cgit.mk index 90a2346..3fcc1ca 100644 --- a/cgit.mk +++ b/cgit.mk @@ -77,6 +77,7 @@ CGIT_OBJ_NAMES += parsing.o CGIT_OBJ_NAMES += scan-tree.o CGIT_OBJ_NAMES += shared.o CGIT_OBJ_NAMES += ui-atom.o +CGIT_OBJ_NAMES += ui-blame.o CGIT_OBJ_NAMES += ui-blob.o CGIT_OBJ_NAMES += ui-clone.o CGIT_OBJ_NAMES += ui-commit.o diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 9fcf445..4da166c 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -141,6 +141,11 @@ embedded:: suitable for embedding in other html pages. Default value: none. See also: "noheader". +enable-blame:: + Flag which, when set to "1", will allow cgit to provide a "blame" page + for files, and will make it generate links to that page in appropriate + places. Default value: "0". + enable-commit-graph:: Flag which, when set to "1", will make cgit print an ASCII-art commit history graph to the left of the commit messages in the repository @@ -799,6 +804,10 @@ enable-http-clone=1 enable-index-links=1 +# Enable blame page and create links to it from tree page +enable-blame=1 + + # Enable ASCII art commit history graph on the log pages enable-commit-graph=1 diff --git a/cmd.c b/cmd.c index d280e95..63f0ae5 100644 --- a/cmd.c +++ b/cmd.c @@ -1,6 +1,6 @@ /* cmd.c: the cgit command dispatcher * - * Copyright (C) 2006-2014 cgit Development Team + * Copyright (C) 2006-2017 cgit Development Team * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -11,6 +11,7 @@ #include "cache.h" #include "ui-shared.h" #include "ui-atom.h" +#include "ui-blame.h" #include "ui-blob.h" #include "ui-clone.h" #include "ui-commit.h" @@ -63,6 +64,14 @@ static void about_fn(void) cgit_print_site_readme(); } +static void blame_fn(void) +{ + if (ctx.cfg.enable_blame) + cgit_print_blame(); + else + cgit_print_error_page(403, "Forbidden", "Blame is disabled"); +} + static void blob_fn(void) { cgit_print_blob(ctx.qry.sha1, ctx.qry.path, ctx.qry.head, 0); @@ -164,6 +173,7 @@ struct cgit_cmd *cgit_get_cmd(void) def_cmd(HEAD, 1, 0, 1), def_cmd(atom, 1, 0, 0), def_cmd(about, 0, 0, 0), + def_cmd(blame, 1, 1, 0), def_cmd(blob, 1, 0, 0), def_cmd(commit, 1, 1, 0), def_cmd(diff, 1, 1, 0), diff --git a/ui-blame.c b/ui-blame.c new file mode 100644 index 0000000..62cf431 --- /dev/null +++ b/ui-blame.c @@ -0,0 +1,227 @@ +/* ui-blame.c: functions for blame output + * + * Copyright (C) 2006-2017 cgit Development Team + * + * Licensed under GNU General Public License v2 + * (see COPYING for full license text) + */ + +#include "cgit.h" +#include "ui-blame.h" +#include "html.h" +#include "ui-shared.h" +#include "argv-array.h" +#include "blame.h" + + +static char *emit_suspect_detail(struct blame_origin *suspect) +{ + struct commitinfo *info; + struct strbuf detail = STRBUF_INIT; + + info = cgit_parse_commit(suspect->commit); + + strbuf_addf(&detail, "author %s", info->author); + if (!ctx.cfg.noplainemail) + strbuf_addf(&detail, " %s", info->author_email); + strbuf_addf(&detail, " %s\n", + show_date(info->author_date, info->author_tz, + cgit_date_mode(DATE_ISO8601))); + + strbuf_addf(&detail, "committer %s", info->committer); + if (!ctx.cfg.noplainemail) + strbuf_addf(&detail, " %s", info->committer_email); + strbuf_addf(&detail, " %s\n\n", + show_date(info->committer_date, info->committer_tz, + cgit_date_mode(DATE_ISO8601))); + + strbuf_addstr(&detail, info->subject); + + cgit_free_commitinfo(info); + return strbuf_detach(&detail, NULL); +} + +static void emit_blame_entry(struct blame_scoreboard *sb, + struct blame_entry *ent) +{ + struct blame_origin *suspect = ent->suspect; + struct object_id *oid = &suspect->commit->object.oid; + const char *numberfmt = "%1$d\n"; + const char *cp, *cpend; + + char *detail = emit_suspect_detail(suspect); + + html(""); + cgit_commit_link(find_unique_abbrev(oid->hash, DEFAULT_ABBREV), detail, + NULL, ctx.qry.head, oid_to_hex(oid), suspect->path); + html("\n"); + + free(detail); + + if (ctx.cfg.enable_tree_linenumbers) { + unsigned long lineno = ent->lno; + html("
");
+		while (lineno < ent->lno + ent->num_lines)
+			htmlf(numberfmt, ++lineno);
+		html("
\n"); + } + + cp = blame_nth_line(sb, ent->lno); + cpend = blame_nth_line(sb, ent->lno + ent->num_lines); + + html("
");
+	html_ntxt(cp, cpend - cp);
+	html("
\n"); +} + +struct walk_tree_context { + char *curr_rev; + int match_baselen; + int state; +}; + +static void print_object(const unsigned char *sha1, const char *path, + const char *basename, const char *rev) +{ + enum object_type type; + unsigned long size; + struct argv_array rev_argv = ARGV_ARRAY_INIT; + struct rev_info revs; + struct blame_scoreboard sb; + struct blame_origin *o; + struct blame_entry *ent = NULL; + + type = sha1_object_info(sha1, &size); + if (type == OBJ_BAD) { + cgit_print_error_page(404, "Not found", "Bad object name: %s", + sha1_to_hex(sha1)); + return; + } + + argv_array_push(&rev_argv, "blame"); + argv_array_push(&rev_argv, rev); + init_revisions(&revs, NULL); + DIFF_OPT_SET(&revs.diffopt, ALLOW_TEXTCONV); + setup_revisions(rev_argv.argc, rev_argv.argv, &revs, NULL); + init_scoreboard(&sb); + sb.revs = &revs; + setup_scoreboard(&sb, path, &o); + o->suspects = blame_entry_prepend(NULL, 0, sb.num_lines, o); + prio_queue_put(&sb.commits, o->commit); + blame_origin_decref(o); + sb.ent = NULL; + sb.path = path; + assign_blame(&sb, 0); + blame_sort_final(&sb); + blame_coalesce(&sb); + + cgit_set_title_from_path(path); + + cgit_print_layout_start(); + htmlf("blob: %s (", sha1_to_hex(sha1)); + cgit_plain_link("plain", NULL, NULL, ctx.qry.head, rev, path); + html(") ("); + cgit_tree_link("tree", NULL, NULL, ctx.qry.head, rev, path); + html(")\n"); + + if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) { + htmlf("
blob size (%ldKB)" + " exceeds display size limit (%dKB).
", + size / 1024, ctx.cfg.max_blob_size); + return; + } + + html(""); + for (ent = sb.ent; ent; ) { + struct blame_entry *e = ent->next; + emit_blame_entry(&sb, ent); + free(ent); + ent = e; + } + html("
\n"); + free((void *)sb.final_buf); + + cgit_print_layout_end(); +} + +static int walk_tree(const unsigned char *sha1, struct strbuf *base, + const char *pathname, unsigned mode, int stage, + void *cbdata) +{ + struct walk_tree_context *walk_tree_ctx = cbdata; + + if (base->len == walk_tree_ctx->match_baselen) { + if (S_ISREG(mode)) { + struct strbuf buffer = STRBUF_INIT; + strbuf_addbuf(&buffer, base); + strbuf_addstr(&buffer, pathname); + print_object(sha1, buffer.buf, pathname, + walk_tree_ctx->curr_rev); + strbuf_release(&buffer); + walk_tree_ctx->state = 1; + } else if (S_ISDIR(mode)) { + walk_tree_ctx->state = 2; + } + } else if (base->len < INT_MAX + && (int)base->len > walk_tree_ctx->match_baselen) { + walk_tree_ctx->state = 2; + } else if (S_ISDIR(mode)) { + return READ_TREE_RECURSIVE; + } + return 0; +} + +static int basedir_len(const char *path) +{ + char *p = strrchr(path, '/'); + if (p) + return p - path + 1; + return 0; +} + +void cgit_print_blame(void) +{ + const char *rev = ctx.qry.sha1; + struct object_id oid; + struct commit *commit; + struct pathspec_item path_items = { + .match = ctx.qry.path, + .len = ctx.qry.path ? strlen(ctx.qry.path) : 0 + }; + struct pathspec paths = { + .nr = 1, + .items = &path_items + }; + struct walk_tree_context walk_tree_ctx = { + .state = 0 + }; + + if (!rev) + rev = ctx.qry.head; + + if (get_oid(rev, &oid)) { + cgit_print_error_page(404, "Not found", + "Invalid revision name: %s", rev); + return; + } + commit = lookup_commit_reference(&oid); + if (!commit || parse_commit(commit)) { + cgit_print_error_page(404, "Not found", + "Invalid commit reference: %s", rev); + return; + } + + walk_tree_ctx.curr_rev = xstrdup(rev); + walk_tree_ctx.match_baselen = (path_items.match) ? + basedir_len(path_items.match) : -1; + + read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, + &walk_tree_ctx); + if (!walk_tree_ctx.state) + cgit_print_error_page(404, "Not found", "Not found"); + else if (walk_tree_ctx.state == 2) + cgit_print_error_page(404, "No blame for folders", + "Blame is not available for folders."); + + free(walk_tree_ctx.curr_rev); +} diff --git a/ui-blame.h b/ui-blame.h new file mode 100644 index 0000000..5b97e03 --- /dev/null +++ b/ui-blame.h @@ -0,0 +1,6 @@ +#ifndef UI_BLAME_H +#define UI_BLAME_H + +extern void cgit_print_blame(void); + +#endif /* UI_BLAME_H */ -- cgit v1.2.3-24-g4f1b From 1649afdc9b2febe9ab7e1abe1956c5dcaff93aa1 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Sun, 1 Oct 2017 23:39:09 -0500 Subject: ui-tree: link to blame UI if enabled Create links to the blame page. Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- ui-shared.c | 20 +++++++++++++++++--- ui-shared.h | 3 +++ ui-tree.c | 10 +++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/ui-shared.c b/ui-shared.c index 315dedb..07c78a5 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -1,6 +1,6 @@ /* ui-shared.c: common web output functions * - * Copyright (C) 2006-2014 cgit Development Team + * Copyright (C) 2006-2017 cgit Development Team * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -304,6 +304,12 @@ void cgit_plain_link(const char *name, const char *title, const char *class, reporevlink("plain", name, title, class, head, rev, path); } +void cgit_blame_link(const char *name, const char *title, const char *class, + const char *head, const char *rev, const char *path) +{ + reporevlink("blame", name, title, class, head, rev, path); +} + void cgit_log_link(const char *name, const char *title, const char *class, const char *head, const char *rev, const char *path, int ofs, const char *grep, const char *pattern, int showmsg, @@ -478,6 +484,10 @@ static void cgit_self_link(char *name, const char *title, const char *class) cgit_plain_link(name, title, class, ctx.qry.head, ctx.qry.has_sha1 ? ctx.qry.sha1 : NULL, ctx.qry.path); + else if (!strcmp(ctx.qry.page, "blame")) + cgit_blame_link(name, title, class, ctx.qry.head, + ctx.qry.has_sha1 ? ctx.qry.sha1 : NULL, + ctx.qry.path); else if (!strcmp(ctx.qry.page, "log")) cgit_log_link(name, title, class, ctx.qry.head, ctx.qry.has_sha1 ? ctx.qry.sha1 : NULL, @@ -983,8 +993,12 @@ void cgit_print_pageheader(void) cgit_log_link("log", NULL, hc("log"), ctx.qry.head, NULL, ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg, ctx.qry.follow); - cgit_tree_link("tree", NULL, hc("tree"), ctx.qry.head, - ctx.qry.sha1, ctx.qry.vpath); + if (ctx.qry.page && !strcmp(ctx.qry.page, "blame")) + cgit_blame_link("blame", NULL, hc("blame"), ctx.qry.head, + ctx.qry.sha1, ctx.qry.vpath); + else + cgit_tree_link("tree", NULL, hc("tree"), ctx.qry.head, + ctx.qry.sha1, ctx.qry.vpath); cgit_commit_link("commit", NULL, hc("commit"), ctx.qry.head, ctx.qry.sha1, ctx.qry.vpath); cgit_diff_link("diff", NULL, hc("diff"), ctx.qry.head, diff --git a/ui-shared.h b/ui-shared.h index 2cd7ac9..b760a17 100644 --- a/ui-shared.h +++ b/ui-shared.h @@ -26,6 +26,9 @@ extern void cgit_tree_link(const char *name, const char *title, extern void cgit_plain_link(const char *name, const char *title, const char *class, const char *head, const char *rev, const char *path); +extern void cgit_blame_link(const char *name, const char *title, + const char *class, const char *head, + const char *rev, const char *path); extern void cgit_log_link(const char *name, const char *title, const char *class, const char *head, const char *rev, const char *path, int ofs, const char *grep, diff --git a/ui-tree.c b/ui-tree.c index 3925809..67fd1bc 100644 --- a/ui-tree.c +++ b/ui-tree.c @@ -1,6 +1,6 @@ /* ui-tree.c: functions for tree output * - * Copyright (C) 2006-2014 cgit Development Team + * Copyright (C) 2006-2017 cgit Development Team * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -110,6 +110,11 @@ static void print_object(const unsigned char *sha1, char *path, const char *base htmlf("blob: %s (", sha1_to_hex(sha1)); cgit_plain_link("plain", NULL, NULL, ctx.qry.head, rev, path); + if (ctx.cfg.enable_blame) { + html(") ("); + cgit_blame_link("blame", NULL, NULL, ctx.qry.head, + rev, path); + } html(")\n"); if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) { @@ -244,6 +249,9 @@ static int ls_item(const unsigned char *sha1, struct strbuf *base, if (!S_ISGITLINK(mode)) cgit_plain_link("plain", NULL, "button", ctx.qry.head, walk_tree_ctx->curr_rev, fullpath.buf); + if (!S_ISDIR(mode) && ctx.cfg.enable_blame) + cgit_blame_link("blame", NULL, "button", ctx.qry.head, + walk_tree_ctx->curr_rev, fullpath.buf); html("\n"); free(name); strbuf_release(&fullpath); -- cgit v1.2.3-24-g4f1b From 9d751e7eec4f4bc7292be46f2af774fe1adf336a Mon Sep 17 00:00:00 2001 From: John Keeping Date: Sat, 14 Oct 2017 13:02:53 +0100 Subject: parsing: don't clear existing state with empty input Since commit c699866 (parsing: clear query path before starting, 2017-02-19), we clear the "page" variable simply by calling cgit_parse_url() even if the URL is empty. This breaks a URL like: .../cgit?p=about which is generated when using the "root-readme" configuration option. This happens because "page" is set to "about" when parsing the query string before we handle the path (which is empty, but non-null). It turns out that this is not the only case which is broken, but specifying repository and page via query options has been broken since before the commit mentioned above, for example: .../cgit?r=git&p=log Fix both of these by allowing the previous state to persist if PATH_INFO is empty, falling back to the query parameters if no path has been requested. Reported-by: Tom Ryder Signed-off-by: John Keeping --- parsing.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/parsing.c b/parsing.c index b8d7f10..fd1ea99 100644 --- a/parsing.c +++ b/parsing.c @@ -20,11 +20,10 @@ void cgit_parse_url(const char *url) char *c, *cmd, *p; struct cgit_repo *repo; - ctx.repo = NULL; - ctx.qry.page = NULL; if (!url || url[0] == '\0') return; + ctx.qry.page = NULL; ctx.repo = cgit_get_repoinfo(url); if (ctx.repo) { ctx.qry.repo = ctx.repo->url; -- cgit v1.2.3-24-g4f1b From fd069b4ca08cb46eb335a1434330b21fbaf84b9c Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 14 Oct 2017 16:13:07 +0200 Subject: filter: pipe_fh should be local Signed-off-by: Jason A. Donenfeld --- cgit.h | 1 - filter.c | 13 +++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cgit.h b/cgit.h index 0b88dcd..005ae63 100644 --- a/cgit.h +++ b/cgit.h @@ -71,7 +71,6 @@ struct cgit_exec_filter { char *cmd; char **argv; int old_stdout; - int pipe_fh[2]; int pid; }; diff --git a/filter.c b/filter.c index 949c931..70f5b74 100644 --- a/filter.c +++ b/filter.c @@ -42,6 +42,7 @@ void cgit_cleanup_filters(void) static int open_exec_filter(struct cgit_filter *base, va_list ap) { struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base; + int pipe_fh[2]; int i; for (i = 0; i < filter->base.argument_count; i++) @@ -49,19 +50,19 @@ static int open_exec_filter(struct cgit_filter *base, va_list ap) filter->old_stdout = chk_positive(dup(STDOUT_FILENO), "Unable to duplicate STDOUT"); - chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess"); + chk_zero(pipe(pipe_fh), "Unable to create pipe to subprocess"); filter->pid = chk_non_negative(fork(), "Unable to create subprocess"); if (filter->pid == 0) { - close(filter->pipe_fh[1]); - chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), + close(pipe_fh[1]); + chk_non_negative(dup2(pipe_fh[0], STDIN_FILENO), "Unable to use pipe as STDIN"); execvp(filter->cmd, filter->argv); die_errno("Unable to exec subprocess %s", filter->cmd); } - close(filter->pipe_fh[0]); - chk_non_negative(dup2(filter->pipe_fh[1], STDOUT_FILENO), + close(pipe_fh[0]); + chk_non_negative(dup2(pipe_fh[1], STDOUT_FILENO), "Unable to use pipe as STDOUT"); - close(filter->pipe_fh[1]); + close(pipe_fh[1]); return 0; } -- cgit v1.2.3-24-g4f1b From 98abe5bb9e6297a5dcbae206e00352c8630d922e Mon Sep 17 00:00:00 2001 From: Ville Skyttä Date: Sat, 14 Oct 2017 22:02:16 +0300 Subject: ui-shared: use type='search' for the search box MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Skyttä --- ui-shared.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-shared.c b/ui-shared.c index 07c78a5..9d8f66b 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -1027,7 +1027,7 @@ void cgit_print_pageheader(void) html_option("committer", "committer", ctx.qry.grep); html_option("range", "range", ctx.qry.grep); html("\n"); - html("\n"); html("\n"); @@ -1042,7 +1042,7 @@ void cgit_print_pageheader(void) html("
\n"); - html("\n"); html("\n"); -- cgit v1.2.3-24-g4f1b From 67d0f870506e3bc3703ae3cb2cb00e19691ce967 Mon Sep 17 00:00:00 2001 From: Ville Skyttä Date: Sat, 14 Oct 2017 22:05:51 +0300 Subject: global: spelling fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Skyttä --- cache.c | 2 +- cache.h | 2 +- filters/syntax-highlighting.sh | 2 +- tests/t0109-gitconfig.sh | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cache.c b/cache.c index 2ccdc4e..0901e6e 100644 --- a/cache.c +++ b/cache.c @@ -318,7 +318,7 @@ static int process_slot(struct cache_slot *slot) /* If the cache slot does not exist (or its key doesn't match the * current key), lets try to create a new cache slot for this * request. If this fails (for whatever reason), lets just generate - * the content without caching it and fool the caller to belive + * the content without caching it and fool the caller to believe * everything worked out (but print a warning on stdout). */ diff --git a/cache.h b/cache.h index 9392836..470da4f 100644 --- a/cache.h +++ b/cache.h @@ -19,7 +19,7 @@ typedef void (*cache_fill_fn)(void); * fn content generator function for this key * * Return value - * 0 indicates success, everyting else is an error + * 0 indicates success, everything else is an error */ extern int cache_process(int size, const char *path, const char *key, int ttl, cache_fill_fn fn); diff --git a/filters/syntax-highlighting.sh b/filters/syntax-highlighting.sh index 4fa7928..840bc34 100755 --- a/filters/syntax-highlighting.sh +++ b/filters/syntax-highlighting.sh @@ -1,6 +1,6 @@ #!/bin/sh # This script can be used to implement syntax highlighting in the cgit -# tree-view by refering to this file with the source-filter or repo.source- +# tree-view by referring to this file with the source-filter or repo.source- # filter options in cgitrc. # # This script requires a shell supporting the ${var##pattern} syntax. diff --git a/tests/t0109-gitconfig.sh b/tests/t0109-gitconfig.sh index 5a84258..3ba6684 100755 --- a/tests/t0109-gitconfig.sh +++ b/tests/t0109-gitconfig.sh @@ -10,16 +10,16 @@ test -n "$(which strace 2>/dev/null)" || { } test_no_home_access () { - non_existant_path="/path/to/some/place/that/does/not/possibly/exist" - while test -d "$non_existant_path"; do - non_existant_path="$non_existant_path/$(date +%N)" + non_existent_path="/path/to/some/place/that/does/not/possibly/exist" + while test -d "$non_existent_path"; do + non_existent_path="$non_existent_path/$(date +%N)" done && strace \ - -E HOME="$non_existant_path" \ + -E HOME="$non_existent_path" \ -E CGIT_CONFIG="$PWD/cgitrc" \ -E QUERY_STRING="url=$1" \ -e access -f -o strace.out cgit && - test_must_fail grep "$non_existant_path" strace.out + test_must_fail grep "$non_existent_path" strace.out } test_no_home_access_success() { -- cgit v1.2.3-24-g4f1b From 5d947ba3f06ec2c7200aab8c22170e7f2bf55a7c Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 29 Nov 2017 22:25:42 +0100 Subject: git: update to v2.15.1 Update to git version v2.15.1: With commit 0abe14f6 prepare_packed_git() moved to packfile.[ch]. Signed-off-by: Christian Hesse Reviewed-by: John Keeping --- Makefile | 2 +- git | 2 +- ui-clone.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f3ee84c..274f37e 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ htmldir = $(docdir) pdfdir = $(docdir) mandir = $(prefix)/share/man SHA1_HEADER = -GIT_VER = 2.14.0 +GIT_VER = 2.15.1 GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.gz INSTALL = install COPYTREE = cp -r diff --git a/git b/git index 4384e3c..9b185be 160000 --- a/git +++ b/git @@ -1 +1 @@ -Subproject commit 4384e3cde2ce8ecd194202e171ae16333d241326 +Subproject commit 9b185bef0c15cec1ea8753ce091e42ea041f2c31 diff --git a/ui-clone.c b/ui-clone.c index 0d11672..bc98980 100644 --- a/ui-clone.c +++ b/ui-clone.c @@ -11,6 +11,7 @@ #include "ui-clone.h" #include "html.h" #include "ui-shared.h" +#include "packfile.h" static int print_ref_info(const char *refname, const struct object_id *oid, int flags, void *cb_data) -- cgit v1.2.3-24-g4f1b From 1dd53e3a2ffec730ec27ebe15b3d63e0b417a544 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 18 Jan 2018 09:19:31 +0100 Subject: git: update to v2.16.0 Update to git version v2.16.0: * refs: convert resolve_ref_unsafe to struct object_id (49e61479be913f67e66bb3fdf8de9475c41b58bd) * diff: remove DIFF_OPT_SET macro (23dcf77f48feb49c54bad09210f093a799816334) * log: add option to choose which refs to decorate (65516f586b69307f977cd67cc45513a296cabc25) * diff: convert flags to be stored in bitfields (02f2f56bc377c287c411947d0e1482aac888f8db) Signed-off-by: Christian Hesse --- Makefile | 2 +- cgit.c | 2 +- git | 2 +- shared.c | 2 +- ui-blame.c | 2 +- ui-commit.c | 2 +- ui-diff.c | 2 +- ui-log.c | 7 +++---- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 274f37e..8321ecc 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ htmldir = $(docdir) pdfdir = $(docdir) mandir = $(prefix)/share/man SHA1_HEADER = -GIT_VER = 2.15.1 +GIT_VER = 2.16.0 GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.gz INSTALL = install COPYTREE = cp -r diff --git a/cgit.c b/cgit.c index 972a67e..a3702c2 100644 --- a/cgit.c +++ b/cgit.c @@ -478,7 +478,7 @@ static char *guess_defbranch(void) const char *ref, *refname; struct object_id oid; - ref = resolve_ref_unsafe("HEAD", 0, oid.hash, NULL); + ref = resolve_ref_unsafe("HEAD", 0, &oid, NULL); if (!ref || !skip_prefix(ref, "refs/heads/", &refname)) return "master"; return xstrdup(refname); diff --git a/git b/git index 9b185be..2512f15 160000 --- a/git +++ b/git @@ -1 +1 @@ -Subproject commit 9b185bef0c15cec1ea8753ce091e42ea041f2c31 +Subproject commit 2512f15446149235156528dafbe75930c712b29e diff --git a/shared.c b/shared.c index df3f611..21ac8f4 100644 --- a/shared.c +++ b/shared.c @@ -346,7 +346,7 @@ void cgit_diff_tree(const struct object_id *old_oid, opt.output_format = DIFF_FORMAT_CALLBACK; opt.detect_rename = 1; opt.rename_limit = ctx.cfg.renamelimit; - DIFF_OPT_SET(&opt, RECURSIVE); + opt.flags.recursive = 1; if (ignorews) DIFF_XDL_SET(&opt, IGNORE_WHITESPACE); opt.format_callback = cgit_diff_tree_cb; diff --git a/ui-blame.c b/ui-blame.c index 62cf431..d4a4534 100644 --- a/ui-blame.c +++ b/ui-blame.c @@ -101,7 +101,7 @@ static void print_object(const unsigned char *sha1, const char *path, argv_array_push(&rev_argv, "blame"); argv_array_push(&rev_argv, rev); init_revisions(&revs, NULL); - DIFF_OPT_SET(&revs.diffopt, ALLOW_TEXTCONV); + revs.diffopt.flags.allow_textconv = 1; setup_revisions(rev_argv.argc, rev_argv.argv, &revs, NULL); init_scoreboard(&sb); sb.revs = &revs; diff --git a/ui-commit.c b/ui-commit.c index 586fea0..abf58f6 100644 --- a/ui-commit.c +++ b/ui-commit.c @@ -41,7 +41,7 @@ void cgit_print_commit(char *hex, const char *prefix) format_display_notes(&oid, ¬es, PAGE_ENCODING, 0); - load_ref_decorations(DECORATE_FULL_REFS); + load_ref_decorations(NULL, DECORATE_FULL_REFS); cgit_print_layout_start(); cgit_print_diff_ctrls(); diff --git a/ui-diff.c b/ui-diff.c index c7fb49b..a10ce8a 100644 --- a/ui-diff.c +++ b/ui-diff.c @@ -444,7 +444,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, diff_setup(&diffopt); diffopt.output_format = DIFF_FORMAT_PATCH; - DIFF_OPT_SET(&diffopt, RECURSIVE); + diffopt.flags.recursive = 1; diff_setup_done(&diffopt); ctx.page.mimetype = "text/plain"; diff --git a/ui-log.c b/ui-log.c index 2d2bb31..8e36fba 100644 --- a/ui-log.c +++ b/ui-log.c @@ -119,8 +119,7 @@ static int show_commit(struct commit *commit, struct rev_info *revs) struct commit_list *parents = commit->parents; struct commit *parent; int found = 0, saved_fmt; - unsigned saved_flags = revs->diffopt.flags; - + struct diff_flags saved_flags = revs->diffopt.flags; /* Always show if we're not in "follow" mode with a single file. */ if (!ctx.qry.follow) @@ -149,7 +148,7 @@ static int show_commit(struct commit *commit, struct rev_info *revs) add_lines = 0; rem_lines = 0; - DIFF_OPT_SET(&revs->diffopt, RECURSIVE); + revs->diffopt.flags.recursive = 1; diff_tree_oid(&parent->tree->object.oid, &commit->tree->object.oid, "", &revs->diffopt); @@ -434,7 +433,7 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern rev.ignore_missing = 1; rev.simplify_history = 1; setup_revisions(rev_argv.argc, rev_argv.argv, &rev, NULL); - load_ref_decorations(DECORATE_FULL_REFS); + load_ref_decorations(NULL, DECORATE_FULL_REFS); rev.show_decorations = 1; rev.grep_filter.ignore_case = 1; -- cgit v1.2.3-24-g4f1b From 6b5b655f6d2449fe33d8f48f6e98d5e421bf3ff9 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Tue, 17 Oct 2017 23:17:32 -0500 Subject: ui-blame: Distinguish hashes column from lines column Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- cgit.css | 1 + ui-blame.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cgit.css b/cgit.css index 836f8ae..893ebeb 100644 --- a/cgit.css +++ b/cgit.css @@ -300,6 +300,7 @@ div#cgit table.blob { border-top: solid 1px black; } +div#cgit table.blob td.hashes, div#cgit table.blob td.lines { margin: 0; padding: 0 0 0 0.5em; vertical-align: top; diff --git a/ui-blame.c b/ui-blame.c index d4a4534..62647a8 100644 --- a/ui-blame.c +++ b/ui-blame.c @@ -51,7 +51,7 @@ static void emit_blame_entry(struct blame_scoreboard *sb, char *detail = emit_suspect_detail(suspect); - html(""); + html(""); cgit_commit_link(find_unique_abbrev(oid->hash, DEFAULT_ABBREV), detail, NULL, ctx.qry.head, oid_to_hex(oid), suspect->path); html("\n"); -- cgit v1.2.3-24-g4f1b From 2b95c9d49c8581e2b19efca1613ada292f56bf08 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Tue, 17 Oct 2017 23:17:33 -0500 Subject: ui-blame: Break out emit_blame_entry into component methods Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- ui-blame.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/ui-blame.c b/ui-blame.c index 62647a8..bbaad1c 100644 --- a/ui-blame.c +++ b/ui-blame.c @@ -41,36 +41,52 @@ static char *emit_suspect_detail(struct blame_origin *suspect) return strbuf_detach(&detail, NULL); } -static void emit_blame_entry(struct blame_scoreboard *sb, - struct blame_entry *ent) +static void emit_blame_entry_hash(struct blame_entry *ent) { struct blame_origin *suspect = ent->suspect; struct object_id *oid = &suspect->commit->object.oid; + + char *detail = emit_suspect_detail(suspect); + cgit_commit_link(find_unique_abbrev(oid->hash, DEFAULT_ABBREV), detail, + NULL, ctx.qry.head, oid_to_hex(oid), suspect->path); + free(detail); +} + +static void emit_blame_entry_linenumber(struct blame_entry *ent) +{ const char *numberfmt = "%1$d\n"; + + unsigned long lineno = ent->lno; + while (lineno < ent->lno + ent->num_lines) + htmlf(numberfmt, ++lineno); +} + +static void emit_blame_entry_line(struct blame_scoreboard *sb, + struct blame_entry *ent) +{ const char *cp, *cpend; - char *detail = emit_suspect_detail(suspect); + cp = blame_nth_line(sb, ent->lno); + cpend = blame_nth_line(sb, ent->lno + ent->num_lines); + + html_ntxt(cp, cpend - cp); +} +static void emit_blame_entry(struct blame_scoreboard *sb, + struct blame_entry *ent) +{ html(""); - cgit_commit_link(find_unique_abbrev(oid->hash, DEFAULT_ABBREV), detail, - NULL, ctx.qry.head, oid_to_hex(oid), suspect->path); + emit_blame_entry_hash(ent); html("\n"); - free(detail); - if (ctx.cfg.enable_tree_linenumbers) { - unsigned long lineno = ent->lno; html("
");
-		while (lineno < ent->lno + ent->num_lines)
-			htmlf(numberfmt, ++lineno);
+		emit_blame_entry_linenumber(ent);
 		html("
\n"); } - cp = blame_nth_line(sb, ent->lno); - cpend = blame_nth_line(sb, ent->lno + ent->num_lines); - html("
");
-	html_ntxt(cp, cpend - cp);
+	emit_blame_entry_line(sb, ent);
 	html("
\n"); } -- cgit v1.2.3-24-g4f1b From aafc42d8089437db5105feb12d540c33fe9f9e16 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Tue, 17 Oct 2017 23:17:34 -0500 Subject: ui-blame: Make each column into a single table cell Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- cgit.css | 19 +++++++++++++++++-- ui-blame.c | 58 +++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 54 insertions(+), 23 deletions(-) diff --git a/cgit.css b/cgit.css index 893ebeb..20b7e86 100644 --- a/cgit.css +++ b/cgit.css @@ -330,11 +330,26 @@ div#cgit table.ssdiff td.lineno a:hover { color: black; } -div#cgit table.blame tr:nth-child(even) { +div#cgit table.blame td.hashes, +div#cgit table.blame td.lines, +div#cgit table.blame td.linenumbers { + padding: 0; +} + +div#cgit table.blame td.hashes div.alt, +div#cgit table.blame td.lines div.alt { + padding: 0 0.5em 0 0.5em; +} + +div#cgit table.blame td.linenumbers div.alt { + padding: 0 0.5em 0 0; +} + +div#cgit table.blame div.alt:nth-child(even) { background: #eee; } -div#cgit table.blame tr:nth-child(odd) { +div#cgit table.blame div.alt:nth-child(odd) { background: white; } diff --git a/ui-blame.c b/ui-blame.c index bbaad1c..d565fff 100644 --- a/ui-blame.c +++ b/ui-blame.c @@ -45,11 +45,17 @@ static void emit_blame_entry_hash(struct blame_entry *ent) { struct blame_origin *suspect = ent->suspect; struct object_id *oid = &suspect->commit->object.oid; + unsigned long line = 0; char *detail = emit_suspect_detail(suspect); + html(""); cgit_commit_link(find_unique_abbrev(oid->hash, DEFAULT_ABBREV), detail, NULL, ctx.qry.head, oid_to_hex(oid), suspect->path); + html(""); free(detail); + + while (line++ < ent->num_lines) + html("\n"); } static void emit_blame_entry_linenumber(struct blame_entry *ent) @@ -72,24 +78,6 @@ static void emit_blame_entry_line(struct blame_scoreboard *sb, html_ntxt(cp, cpend - cp); } -static void emit_blame_entry(struct blame_scoreboard *sb, - struct blame_entry *ent) -{ - html(""); - emit_blame_entry_hash(ent); - html("\n"); - - if (ctx.cfg.enable_tree_linenumbers) { - html("
");
-		emit_blame_entry_linenumber(ent);
-		html("
\n"); - } - - html("
");
-	emit_blame_entry_line(sb, ent);
-	html("
\n"); -} - struct walk_tree_context { char *curr_rev; int match_baselen; @@ -147,16 +135,44 @@ static void print_object(const unsigned char *sha1, const char *path, return; } - html(""); + html("
\n\n"); + + /* Commit hashes */ + html("\n"); + + /* Line numbers */ + if (ctx.cfg.enable_tree_linenumbers) { + html("\n"); + } + + /* Lines */ + html("
"); + for (ent = sb.ent; ent; ent = ent->next) { + html("
");
+		emit_blame_entry_hash(ent);
+		html("
"); + } + html("
"); + for (ent = sb.ent; ent; ent = ent->next) { + html("
");
+			emit_blame_entry_linenumber(ent);
+			html("
"); + } + html("
"); for (ent = sb.ent; ent; ) { struct blame_entry *e = ent->next; - emit_blame_entry(&sb, ent); + html("
");
+		emit_blame_entry_line(&sb, ent);
+		html("
"); free(ent); ent = e; } - html("
\n"); + html("\n"); + free((void *)sb.final_buf); + html("\n\n"); + cgit_print_layout_end(); } -- cgit v1.2.3-24-g4f1b From dbaee2672be14374acb17266477c19294c6155f3 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Sat, 28 Oct 2017 21:43:26 -0500 Subject: ui-blame: Allow syntax highlighting Place file contents into a single block so that syntax highlighting can be applied in the usual fashion. Place the alternating color bars behind the file contents. Force the default syntax highlighting background to transparent. Signed-off-by: Jeff Smith Reviewed-by: John Keeping --- cgit.css | 10 +++++++ filters/syntax-highlighting.py | 2 +- ui-blame.c | 63 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/cgit.css b/cgit.css index 20b7e86..217a05a 100644 --- a/cgit.css +++ b/cgit.css @@ -353,6 +353,16 @@ div#cgit table.blame div.alt:nth-child(odd) { background: white; } +div#cgit table.blame td.lines > div { + position: relative; +} + +div#cgit table.blame td.lines > div > pre { + padding: 0 0 0 0.5em; + position: absolute; + top: 0; +} + div#cgit table.bin-blob { margin-top: 0.5em; border: solid 1px black; diff --git a/filters/syntax-highlighting.py b/filters/syntax-highlighting.py index 5888b50..e912594 100755 --- a/filters/syntax-highlighting.py +++ b/filters/syntax-highlighting.py @@ -34,7 +34,7 @@ sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8', errors='replace sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') data = sys.stdin.read() filename = sys.argv[1] -formatter = HtmlFormatter(style='pastie') +formatter = HtmlFormatter(style='pastie', nobackground=True) try: lexer = guess_lexer_for_filename(filename, data) diff --git a/ui-blame.c b/ui-blame.c index d565fff..17e2d60 100644 --- a/ui-blame.c +++ b/ui-blame.c @@ -67,15 +67,29 @@ static void emit_blame_entry_linenumber(struct blame_entry *ent) htmlf(numberfmt, ++lineno); } -static void emit_blame_entry_line(struct blame_scoreboard *sb, - struct blame_entry *ent) +static void emit_blame_entry_line_background(struct blame_scoreboard *sb, + struct blame_entry *ent) { - const char *cp, *cpend; + unsigned long line; + size_t len, maxlen = 2; + const char* pos, *endpos; - cp = blame_nth_line(sb, ent->lno); - cpend = blame_nth_line(sb, ent->lno + ent->num_lines); + for (line = ent->lno; line < ent->lno + ent->num_lines; line++) { + html("\n"); + pos = blame_nth_line(sb, line); + endpos = blame_nth_line(sb, line + 1); + len = 0; + while (pos < endpos) { + len++; + if (*pos++ == '\t') + len = (len + 7) & ~7; + } + if (len > maxlen) + maxlen = len; + } - html_ntxt(cp, cpend - cp); + for (len = 0; len < maxlen - 1; len++) + html(" "); } struct walk_tree_context { @@ -88,6 +102,7 @@ static void print_object(const unsigned char *sha1, const char *path, const char *basename, const char *rev) { enum object_type type; + char *buf; unsigned long size; struct argv_array rev_argv = ARGV_ARRAY_INIT; struct rev_info revs; @@ -102,6 +117,13 @@ static void print_object(const unsigned char *sha1, const char *path, return; } + buf = read_sha1_file(sha1, &type, &size); + if (!buf) { + cgit_print_error_page(500, "Internal server error", + "Error reading object %s", sha1_to_hex(sha1)); + return; + } + argv_array_push(&rev_argv, "blame"); argv_array_push(&rev_argv, rev); init_revisions(&revs, NULL); @@ -157,20 +179,37 @@ static void print_object(const unsigned char *sha1, const char *path, html("\n"); } - /* Lines */ - html(""); + html("
"); + + /* Colored bars behind lines */ + html("
"); for (ent = sb.ent; ent; ) { struct blame_entry *e = ent->next; - html("
");
-		emit_blame_entry_line(&sb, ent);
-		html("
"); + html("
");
+		emit_blame_entry_line_background(&sb, ent);
+		html("
"); free(ent); ent = e; } - html("\n"); + html("
"); free((void *)sb.final_buf); + /* Lines */ + html("
");
+	if (ctx.repo->source_filter) {
+		char *filter_arg = xstrdup(basename);
+		cgit_open_filter(ctx.repo->source_filter, filter_arg);
+		html_raw(buf, size);
+		cgit_close_filter(ctx.repo->source_filter);
+		free(filter_arg);
+	} else {
+		html_txt(buf);
+	}
+	html("
"); + + html("
\n"); + html("\n\n"); cgit_print_layout_end(); -- cgit v1.2.3-24-g4f1b From 03f6e34bb9d683723cfc4fe58ee5bb983b95e173 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 12 Feb 2018 23:23:47 +0100 Subject: cgit: prepare repo before error pages This fixes a crash when showing a list of all heads in the