331a45688a9b9642e721b7c0c9f92f3571f1f432
commit 331a45688a9b9642e721b7c0c9f92f3571f1f432
Author: spesk1 <spesk@pm.me>
Date: Fri Jun 21 13:38:10 2019 -0400

Base, nothing functional

diff --git a/README.md b/README.md
index 44af08f..3b9f638 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,12 @@
# git-site-gen #

-Placeholder repo right now as code is not ready to be public.
-Tracking features/TODO's in this README.
+* Tool used to generate a static website from information availble in a git project dir. See: https://spwbk.site/git.
+ * Also provides some tools for managing your git server.

-## Features/Plans/TODO ##
+* Inspired by the much better/full-featured https://git.suckless.org.
+* Not sure if this will be widely useful, mostly written for learning purposes.
+
+## Features ##

* Generate top level index with links to all projects - POC DONE
* Generate project specific index with links to git log/diffs and file content of repo - POC DONE
@@ -11,12 +14,17 @@ Tracking features/TODO's in this README.
* Line numbers for file browsing
* README.md markdown renderer/parser / display in project index
* Figure out way to expose clone/merge/etc interface
+* (Stretch GoaL) HTML based syntax highlighting for files

## Framework Plans ##
* gsg -- Perl script to generate the site, uses modules below
-* Shellex.pm -- lib to handle shell calls (can likely split Shellex from simply-git project into it's own repo and maintain it there for both things)
-* GitGather.pm -- module to assemble data structures from git trees that need to be obtained as part of generating the site
-* Html.pm -- probably a bad name, used for writing HTML files and/or editing text in other data structures with html content
-* MdParse.pm -- module for parsing markdown. Likely a fools errand to be writing this myself but I'd like to try
-* GsgConfigParse.pm -- module to parse gsg config, might be overkill to have it's own module
+* Gsg::Gather.pm -- module to assemble data structures from git trees that need to be obtained as part of generating the site
+* Gsg::Html.pm -- probably a bad name, used for writing HTML files and/or editing text in other data structures with html content
+* Gsg::MdParse.pm -- module for parsing markdown. Likely a fools errand to be writing this myself but I'd like to try
+* Gsg::ConfigParse.pm -- module to parse gsg config, might be overkill to have it's own module
* gsg.config -- Config file that gsg reads to inform behavior (git repos dir, what to include/exclude, etc)
+
+## Deps ##
+* Shellex.pm ( https://spwbk.site/git/projects/perl-shellex.git/index.html )
+* git
+* Log4Perl
diff --git a/gen_page.pl b/gen_page.pl
new file mode 100755
index 0000000..beadefe
--- /dev/null
+++ b/gen_page.pl
@@ -0,0 +1,135 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my $top_level_dir = "/var/www/html/git/";
+my $projects_dir = $top_level_dir . "projects/";
+my $index = $top_level_dir . "index.html";
+
+my @ignore_dirs = ( "finance-perl.git/","misc-scripts.git/","git-site-gen.git/" );
+my @git_project_dirs;
+foreach my $dir ( split("\n",`ls -d */`) ) {
+ chomp $dir;
+ if ( grep( /^$dir$/, @ignore_dirs ) ) {
+ print "Skipping $dir\n";
+ next;
+ }
+ if ( $dir =~ /.git\/$/ ) {
+ push(@git_project_dirs,$dir);
+ }
+}
+
+my $write = sub {
+ my $content = shift;
+ my $path = shift;
+ open(my $fh, ">", $path) or die "Couldnt open $path\n";
+ print $fh "$content";
+ close $fh;
+};
+
+my $append = sub {
+ my $content = shift;
+ my $path = shift;
+ open(my $fh, ">>", $path) or die "Couldnt open $path\n";
+ print $fh "$content";
+ close $fh;
+};
+
+$write->("",$index);
+foreach my $dir ( split("\n", `cd $projects_dir ; ls -d */; cd /home/git`) ) {
+ if ( ! grep( /^$dir$/, @git_project_dirs ) ) {
+ print "Found $dir in webroot but not in git root, removing...\n";
+ my $rmdir = $projects_dir . $dir;
+ print "Removing $rmdir\n";
+ system("rm -rf $rmdir") == 0 or die "Couldnt rm $dir\n";
+ }
+}
+
+# Write index
+$append->("<html><body><b>Git Projects</b><br><head><META NAME=\"ROBOTS\" CONTENT=\"NOINDEX, NOFOLLOW\"></head>\n",$index);
+$append->("<small><i>Statically generated web root for browsing my git projects</i></small><br>",$index);
+$append->("<small><i>This is a read-only site and does not provide a merge/clone interface</i></small><hr/>",$index);
+foreach my $project ( @git_project_dirs ) {
+ $append->("<table><div id=\"cotent\"><table id=\"index\"><tbody>",$index);
+ $append->("<tr><td><a href=\"projects/$project/index.html\">$project</a></td>",$index);
+ #$append->("<a href=\"projects/$project/index.html\">$project</a><br>",$index);
+ system("mkdir -p $projects_dir$project") == 0 or die "Couldnt create $projects_dir/$project";
+}
+$append->("</tr></tbody></table></div></body></html>",$index);
+
+# Write files
+foreach my $project ( @git_project_dirs ) {
+ my $spec_project_dir = $projects_dir . $project . "/";
+ my $project_index = $spec_project_dir . "/index.html";
+ $write->("",$project_index);
+ $append->("<html><a href=\"../../../index.html\">Return to index</a></b><hr/>",$project_index);
+ $append->("<b>Files for $project</b><br>",$project_index);
+ $append->("<hr/>",$project_index);
+ my %fileTree;
+ foreach my $file ( split("\n", `cd $project ; git ls-tree --full-tree -r HEAD; cd ..`) ) {
+ chomp $file;
+ $file =~ /([a-z0-9]{40})\t(.*)$/;
+ # Name - commit hash
+ $fileTree{$2} = $1;
+ }
+
+ my %fileContent;
+ foreach my $filename ( keys %fileTree ) {
+ my $content = `cd $project ; git show $fileTree{$filename} ; cd ..`;
+ chomp $content;
+ $fileContent{$filename} = $content;
+ }
+
+ $append->("<table><div id=\"cotent\"><table id=\"index\"><thead><tr><td><b>File</b></td><td><b>Commit</b></td></tr></thead><tbody>",$project_index);
+ foreach my $filename ( sort keys %fileContent ) {
+ my $browserVersion = $filename . ".txt";
+ if ( $filename =~ m/\// ) {
+ my $copy = $filename;
+ $copy =~ s/\//_/g;
+ $browserVersion = $copy . ".txt";
+ }
+ #$append->("$fileTree{$filename} - <a href=\"$browserVersion\">$filename</a><br>",$project_index);
+ $append->("<tr><td><a href=\"$browserVersion\">$filename</a></td><td>$fileTree{$filename}</td>",$project_index);
+ $write->("$fileContent{$filename}",$spec_project_dir . $browserVersion);
+ }
+
+ $append->("</tr></tbody></table></div></body>",$project_index);
+ $append->("<br>", $project_index);
+
+}
+
+# Get logs hash and write out logs page
+foreach my $project ( @git_project_dirs ) {
+ my $spec_project_dir = $projects_dir . $project . "/";
+ my $project_index = $spec_project_dir . "/index.html";
+ my @commit_ids;
+ foreach my $log_line ( split("\n",`cd $project; git log ; cd ..`) ) {
+ if ( $log_line =~ m/commit\ ([a-z0-9]{40})/ ) {
+ push(@commit_ids,$1);
+ }
+ }
+
+ # Key: commit SHA, value commit info (git show)
+ my %commits;
+ foreach my $commit_id ( @commit_ids ) {
+ my $commit_info = `cd $project; git show $commit_id; cd ..`;
+ chomp $commit_info;
+ $commits{$commit_id} = $commit_info;
+ }
+
+ $append->("<html><b>Logs for $project</b><br>",$project_index);
+ $append->("<table><div id=\"cotent\"><table id=\"index\"><tbody>",$project_index);
+ $append->("<hr/>",$project_index);
+ # iterate over array to keep ordering
+ foreach my $commit_id ( @commit_ids ) {
+ my $filename = $commit_id . ".txt";
+ #$append->("<a href=\"$filename\">$commit_id</a><br>",$project_index);
+ $append->("<tr><td><a href=\"$filename\">$filename</a></td>",$project_index);
+ $write->($commits{$commit_id},$spec_project_dir . $filename);
+ }
+ $append->("</tr></tbody></table></div></body>",$project_index);
+ $append->("</html>",$project_index);
+}
+
+print "Done\n";
diff --git a/lib/Gsg/ConfigParse.pm b/lib/Gsg/ConfigParse.pm
new file mode 100644
index 0000000..89278c3
--- /dev/null
+++ b/lib/Gsg/ConfigParse.pm
@@ -0,0 +1,46 @@
+package Gsg::ConfigParse;
+use strict;
+use warnings;
+use Log::Log4perl qw(:easy);
+use lib "/usr/local/lib";
+use Shellex::Shellex qw(shellex findBin);
+use Exporter qw(import);
+our @EXPORT_OK = qw();
+
+# https://perlmaven.com/trim
+sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
+
+sub parseGsgConfig($$) {
+
+ my $configPath = shift;
+ my $logger = shift;
+ if ( ! -e $config ) {
+ $logger->error("$config doesn't look like a regular file, exiting...");
+ exit 1;
+ }
+ my $catCmd = findBin("cat",$logger);
+ my @configLines = split("\n",shellex("$catCmd $config",$logger));
+ my %configHash;
+ foreach my $line ( @configLines ) {
+ chomp $line;
+ if ( $line =~ m/^(.*)\ =\ "(.*)"$/ ) {
+ $configHash{$1} = $2;
+ }
+
+ if ( $line =~ m/^(.*)\ =\ \[(.*)\]/ ) {
+ my @trimmedPorts;
+ my @ports = split(",",$2);
+ foreach my $port (@ports) {
+ $port =~ /(\d{1,5})/;
+ push(@trimmedPorts,trim($1));
+ }
+ $configHash{$1} = \@trimmedPorts;
+ }
+ }
+
+ return %configHash;
+
+}
+
+1;
+
diff --git a/lib/Gsg/Gather.pm b/lib/Gsg/Gather.pm
new file mode 100644
index 0000000..6aae46f
--- /dev/null
+++ b/lib/Gsg/Gather.pm
@@ -0,0 +1,8 @@
+package Gsg::Gather;
+use strict;
+use warnings;
+use Log::Log4perl qw(:easy);
+use Exporter qw(import);
+our @EXPORT_OK = qw();
+
+1;
diff --git a/lib/Gsg/Html.pm b/lib/Gsg/Html.pm
new file mode 100644
index 0000000..b92cf0c
--- /dev/null
+++ b/lib/Gsg/Html.pm
@@ -0,0 +1,8 @@
+package Gsg::Html;
+use strict;
+use warnings;
+use Log::Log4perl qw(:easy);
+use Exporter qw(import);
+our @EXPORT_OK = qw();
+
+1;
diff --git a/lib/Gsg/MdParse.pm b/lib/Gsg/MdParse.pm
new file mode 100644
index 0000000..2b0a28a
--- /dev/null
+++ b/lib/Gsg/MdParse.pm
@@ -0,0 +1,9 @@
+package Gsg::MdParse;
+use strict;
+use warnings;
+use Log::Log4perl qw(:easy);
+use Exporter qw(import);
+our @EXPORT_OK = qw();
+
+1;
+
diff --git a/tools/mkproject.sh b/tools/mkproject.sh
new file mode 100755
index 0000000..845a914
--- /dev/null
+++ b/tools/mkproject.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+NAME=$1;
+if [ "$NAME" == "" ]; then
+ echo "Need to pass a project name"
+ exit 1
+fi
+TLD=$PWD
+GIT_HOME="/home/git/"
+PROJECT_SUFFIX=".git"
+PROJECT_DIR="$GIT_HOME/$NAME$PROJECT_SUFFIX"
+
+mkdir $PROJECT_DIR || echo "Couldn't mkdir $PROJECT_DIR"
+cd $PROJECT_DIR || echo "Couldn't cd to $PROJECT_DIR"
+$(which git) init --bare || echo "Couldn't init git in $PROJECT_DIR"
+cd $TLD || echo "Couldnt cd back up to $TLD"