diff --git a/Gemfile b/Gemfile index 3f5a96a..51f4ee7 100644 --- a/Gemfile +++ b/Gemfile @@ -12,6 +12,7 @@ gem 'concurrent-ruby' gem 'open-uri-cached' gem 'rouge' gem 'rubocop' +gem 'rugged' gem 'slim' gem 'tilt' diff --git a/Gemfile.lock b/Gemfile.lock index 6352d82..c805b42 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -73,6 +73,7 @@ GEM sorbet-runtime syntax_tree (>= 6, < 7) ruby-progressbar (1.13.0) + rugged (1.6.3) slim (5.1.0) temple (~> 0.10.0) tilt (>= 2.0.6, < 2.2) @@ -100,8 +101,9 @@ DEPENDENCIES rouge rubocop ruby-lsp + rugged slim tilt BUNDLED WITH - 2.3.7 + 2.4.6 diff --git a/bin/create-patches-for-content-workspace.rb b/bin/create-patches-for-content-workspace.rb new file mode 100644 index 0000000..6329f9f --- /dev/null +++ b/bin/create-patches-for-content-workspace.rb @@ -0,0 +1,100 @@ +#!/usr/bin/env nix-shell +#! nix-shell -i ruby -p "ruby.withPackages (ps: with ps; [ rugged ])" coreutils fzf + +# frozen_string_literal: true + +# A script that recreates `git format-patch` subcommand but with a few more +# specific use case for this project. +require 'fileutils' +require 'logger' +require 'optparse' +require 'rugged' + +def to_kebab_case(string) + string.gsub(/\s+/, '-') # Replace all spaces with dashes. + .gsub(/[^a-zA-Z0-9-]/, '') # Remove all non-alphanumerical (and dashes) characters. + .gsub(/-+/, '-') # Reduce all dashes into only one. + .gsub(/^-|-+$/, '') # Remove all leading and trailing dashes. + .downcase +end + +CONTENT_DIRECTORY = 'content' +PATCHES_SUBDIRECTORY = 'assets/patches' +options = { + 'current-branch': false, + 'prefix': 'posts/', + 'repo': '.' +} + +logger = Logger.new($stdout) +logger.level = Logger::WARN + +OptionParser.new do |opts| + opts.on('-c', '--current-branch', 'Select the current branch.') do + options['current-branch'] = true + end + + opts.on('-p', '--prefix PREFIX', + <<~HELP + Sets the prefix corresponding to a subdirectory inside + the content directory. + HELP + ) do |prefix| + options['prefix'] = prefix + end + + opts.on('--repo REPO', String, 'Select the Git repository of the workspace') do |repo| + options['repo'] = repo + end + + opts.on('-v', '--[no-]verbose', 'Make the program print results') do |v| + options['verbose'] = v + end +end.parse! + +logger.level = Logger::INFO if options['verbose'] + +code_workspace = Rugged::Repository.discover(options['repo']) +if options['current-branch'] + selected_branch = code_workspace.branches[code_workspace.head.name].name + raise %(Current branch is not a '#{options['prefix']}' subbranch.) unless selected_branch.start_with? options[:prefix] +else + branches = code_workspace.branches + .each_name(:local) + .select { |branch| branch.start_with? options[:prefix] } + .sort + + raise "No branches with the prefix '#{options['prefix']}'" if branches.empty? + + selected_branch = `echo -e "#{branches.join '\n'}" | fzf`.strip +end + +selected_branch_object = code_workspace.branches[selected_branch] + +repo_walker = Rugged::Walker.new(code_workspace) +repo_walker.push(selected_branch_object.target_id) +repo_walker.sorting(Rugged::SORT_DATE | Rugged::SORT_REVERSE) + +# Delete the patches directory. This makes it completely dangerous. +patches_dir = File.expand_path("#{selected_branch}/#{PATCHES_SUBDIRECTORY}", CONTENT_DIRECTORY) + +FileUtils.rmtree(patches_dir, secure: true) +logger.info "Removing '#{patches_dir}'" + +FileUtils.mkdir_p(patches_dir) +logger.info "Creating directory '#{patches_dir}'" + +repo_walker.each_with_index do |commit, index| + commit_message = to_kebab_case commit.message + commit_index = (index + 1).to_s.rjust(4, '0') + + patchfile = File.expand_path( + "#{commit_index}-#{commit_message}.patch", + patches_dir + ) + + File.open(patchfile, 'w') do |f| + logger.info "Creating patch file '#{patchfile}' from commit '#{commit.tree_id}'" + f.write commit.diff.patch + end +end diff --git a/gemset.nix b/gemset.nix index 4f014dd..c10f01f 100644 --- a/gemset.nix +++ b/gemset.nix @@ -374,6 +374,18 @@ targets = []; version = "1.13.0"; }; + rugged = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "016bawsahkhxx7p8azxirpl7y2y7i8a027pj8910gwf6ipg329in"; + target = "ruby"; + type = "gem"; + }; + targets = []; + version = "1.6.3"; + }; slim = { dependencies = ["temple" "tilt"]; groups = ["default"];