From 0f9b11cad17e2b9ca5cefe2dd4e053edf35d6e26 Mon Sep 17 00:00:00 2001 From: Stefan Imhoff Date: Thu, 9 Jan 2025 12:29:41 +0100 Subject: [PATCH] refactor: rewrite script in Node.js --- bin/gource-gravatars | 119 +++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 43 deletions(-) diff --git a/bin/gource-gravatars b/bin/gource-gravatars index 2dd94e5..7f492d7 100755 --- a/bin/gource-gravatars +++ b/bin/gource-gravatars @@ -1,48 +1,81 @@ -#!/usr/bin/perl -# Fetch Gravatars +#!/usr/bin/env node -use strict; -use warnings; +const fs = require("fs"); +const path = require("path"); +const { spawn } = require("child_process"); +const https = require("https"); +const crypto = require("crypto"); -use LWP::Simple; -use Digest::MD5 qw(md5_hex); +const size = 256; +const outputDir = ".git/avatar"; -my $size = 90; -my $output_dir = '.git/avatar'; - -die("no .git/ directory found in current path\n") unless -d '.git'; - -mkdir($output_dir) unless -d $output_dir; - -open(GITLOG, q/git log --pretty=format:"%ae|%an" |/) or die("failed to read git-log: $!\n"); - -my %processed_authors; - -while() { - chomp; - my($email, $author) = split(/\|/, $_); - - next if $processed_authors{$author}++; - - my $author_image_file = $output_dir . '/' . $author . '.png'; - - #skip images we have - next if -e $author_image_file; - - #try and fetch image - - my $grav_url = "http://www.gravatar.com/avatar/".md5_hex(lc $email)."?d=404&size=".$size; - - warn "fetching image for '$author' $email ($grav_url)...\n"; - - my $rc = getstore($grav_url, $author_image_file); - - sleep(1); - - if($rc != 200) { - unlink($author_image_file); - next; - } +if (!fs.existsSync(".git")) { + console.error("No .git/ directory found in current path"); + process.exit(1); } -close GITLOG; +if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); +} + +const processedAuthors = new Set(); + +const gitLogCommand = "git"; +const gitLogArgs = ["log", "--pretty=format:%ae|%an"]; + +const gitLog = spawn(gitLogCommand, gitLogArgs); + +gitLog.stdout.on("data", (data) => { + const lines = data.toString().trim().split("\n"); + + lines.forEach((line) => { + const [email, author] = line.split("|"); + + if (processedAuthors.has(author)) { + return; + } + processedAuthors.add(author); + + const authorImageFile = path.join(outputDir, `${author}.png`); + console.log(`Author image file: ${authorImageFile}`); + + if (fs.existsSync(authorImageFile)) { + return; + } + + const emailHash = crypto + .createHash("md5") + .update(email.toLowerCase()) + .digest("hex"); + const gravUrl = `https://www.gravatar.com/avatar/${emailHash}?s=${size}`; + console.log(`Gravatar URL: ${gravUrl}`); + + https + .get(gravUrl, (response) => { + if (response.statusCode === 200) { + const writer = fs.createWriteStream(authorImageFile); + response.pipe(writer); + console.log("Image saved successfully"); + } else { + console.error( + `Failed to save image: ${response.statusCode} ${response.statusMessage}`, + ); + fs.unlinkSync(authorImageFile); + } + }) + .on("error", (error) => { + console.error(`Failed to save image: ${error.message}`); + fs.unlinkSync(authorImageFile); + }); + }); +}); + +gitLog.stderr.on("data", (data) => { + console.error(`Error executing git log: ${data}`); +}); + +gitLog.on("close", (code) => { + if (code !== 0) { + console.error(`git log process exited with code ${code}`); + } +});