Skip to content

Commit

Permalink
Rewrite script/add-grammar as a plain shell-script (github-linguist…
Browse files Browse the repository at this point in the history
  • Loading branch information
Alhadis authored Sep 2, 2021
1 parent bc04fea commit 8b3c18c
Show file tree
Hide file tree
Showing 3 changed files with 281 additions and 123 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ trim_trailing_whitespace = false
indent_style = tab
indent_size = 8

[{Dockerfile,Makefile,*.go}]
[{Dockerfile,Makefile,*.go,script/add-grammar}]
indent_style = tab
indent_size = 4

Expand Down
259 changes: 137 additions & 122 deletions script/add-grammar
Original file line number Diff line number Diff line change
@@ -1,124 +1,139 @@
#!/usr/bin/env ruby

require "optparse"
require "open3"

ROOT = File.expand_path("../../", __FILE__)


# Break a repository URL into its separate components
def parse_url(input)
hosts = "github\.com|bitbucket\.org|gitlab\.com"

# HTTPS/HTTP link pointing to recognised hosts
if input =~ /^(?:https?:\/\/)?(?:[^.@]+@)?(?:www\.)?(#{hosts})\/([^\/]+)\/([^\/]+)/i
{ host: $1.downcase(), user: $2, repo: $3.sub(/\.git$/, "") }
# SSH
elsif input =~ /^git@(#{hosts}):([^\/]+)\/([^\/]+)\.git$/i
{ host: $1.downcase(), user: $2, repo: $3 }
# provider:user/repo
elsif input =~ /^(github|bitbucket|gitlab):\/?([^\/]+)\/([^\/]+)\/?$/i
{ host: $1.downcase(), user: $2, repo: $3 }
# user/repo - Common GitHub shorthand
elsif input =~ /^\/?([^\/]+)\/([^\/]+)\/?$/
{ host: "github.com", user: $1, repo: $2 }
else
raise "Unsupported URL: #{input}"
end
end

# Isolate the vendor-name component of a submodule path
def parse_submodule(name)
name =~ /^(?:.*(?:vendor\/)?grammars\/)?([^\/]+)/i
path = "vendor/grammars/#{$1}"
unless File.exist?("#{ROOT}/" + path)
warn "Submodule '#{path}' does not exist. Aborting."
exit 1
end
path
end

# Print debugging feedback to STDOUT if not running with --quiet
def log(msg)
puts msg if $verbose
end

def command(*args, hide_warnings: false)
log "$ #{args.join(' ')}"
stdout, stderr, status = Open3.capture3(*args)
unless status.success?
output = stdout.strip + "\n" + stderr.strip
output.each_line do |line|
log " > #{line}"
end
warn "Command failed. Aborting."
exit 1
end
return if stderr.empty?

unless hide_warnings
stderr.each_line do |line|
log " > #{line}"
end
end
end

usage = """Usage:
#{$0} [-q|--quiet] [--replace grammar] url
Examples:
#{$0} https://github.com/Alhadis/language-roff
#{$0} --replace sublime-apl https://github.com/Alhadis/language-apl
"""

$replace = nil
$verbose = true

OptionParser.new do |opts|
opts.banner = usage
opts.on("-q", "--quiet", "Do not print output unless there's a failure") do
$verbose = false
end
opts.on("-rSUBMODULE", "--replace=SUBMODDULE", "Replace an existing grammar submodule.") do |name|
$replace = name
end
end.parse!


$url = ARGV[0]

# No URL? Print a usage message and bail.
unless $url
warn usage
exit 1;
end

# Exit early if docker isn't installed or running.
log "Checking docker is installed and running"
command('docker', 'ps')
#!/bin/sh
# shellcheck disable=SC2006,SC2021
set -e

usage="${0##*/} [-q|--quiet] [--replace submodule] url"
unset replace quiet

# Print non-essential feedback
log()([ "$quiet" ] || printf '%s\n' "$@")

# Print an error message
warn()(printf '%s: %s\n' "${0##*/}" "$@")

# Display a shortened help summary and bail with an error code
bad_invocation(){
printf '%s\n' "$usage" >&2
exit 2
}


# Parse options
while [ -n "$1" ]; do case $1 in

# Print an unabridged usage summary, then exit
-h|--help|-\?)
cat <<-HELP
Usage:
$usage
Options:
-q, --quiet Do not print output unless there's a failure.
-r, --replace SUBMODDULE Replace an existing grammar submodule.
Examples:
$0 https://github.com/Alhadis/language-roff
$0 --replace sublime-apl https://github.com/Alhadis/language-apl
HELP
exit ;;

# Hide non-essential feedback
-q | --quiet)
quiet=1
break ;;

# Replace an existing submodule
-r* | --replace | --replace=*)
case $1 in
-r|--replace) replace=$2; shift ;; # -r [module], --replace [module]
-r*) replace=${1#??} ;; # -r[module]
--replace=*) replace=${1#*=} ;; # --replace=[module]
esac ;;

# Double-dash: Terminate option parsing
--)
shift
break ;;

# Invalid option: abort
--* | -?*)
warn 'invalid option: "%s"' "${0##*/}" "$1" >&2
bad_invocation ;;

# Argument not prefixed with a dash
*) break ;;

esac; shift
done


# Don't proceed any further if we don't have a URL
[ "$1" ] || bad_invocation


# Check upfront that executables we depend on are available
for cmd in docker git sed ruby bundle; do
command -v "$cmd" >/dev/null 2>&1 || {
warn "Required command '$cmd' not found"
warn 'See CONTRIBUTING.md for help on getting started: https://git.io/J0eqy'
exit 1
}
done

# Make sure Docker's running
log 'Checking Docker is installed and running'
docker ps >/dev/null

# Make sure we're running from checkout directory
root=`git rev-parse --git-dir`
root="${root%/.git}"
# shellcheck disable=SC3013
if [ ! "$root" = .git ] && [ -d "$root" ] && ! [ . -ef "$root" ] >/dev/null 2>&1; then
log "Switching directory to $root"
cd "$root"
fi

# Ensure the given URL is an HTTPS link
parts = parse_url $url
https = "https://#{parts[:host]}/#{parts[:user]}/#{parts[:repo]}"
repo_new = "vendor/grammars/#{parts[:repo]}"
repo_old = parse_submodule($replace) if $replace

Dir.chdir(ROOT)

if repo_old
log "Deregistering: #{repo_old}"
command('git', 'submodule', 'deinit', repo_old)
command('git', 'rm', '-rf', repo_old)
command('script/grammar-compiler', 'update', '-f', hide_warnings: true)
end

log "Registering new submodule: #{repo_new}"
command('git', 'submodule', 'add', '-f', https, repo_new)
command('script/grammar-compiler', 'add', repo_new)

log "Caching grammar license"
command("bundle", "exec", "licensed", "cache", "-c", "vendor/licenses/config.yml")

log "Updating grammar documentation in vendor/README.md"
command('bundle', 'exec', 'rake', 'samples', hide_warnings: true)
command('script/sort-submodules')
command('script/list-grammars')
url=`script/normalise-url --protocol=https "$1"`

# Make sure it's not already registered
path="vendor/grammars/${url##*/}"
path="${path%.git}"
if [ -e "$path" ]; then
warn "Submodule '$path' already exists. Did you forget the '--replace' option?"
warn "Run '$0 --help' for invocation advice"
exit 1
fi

# Remove the old submodule if we're `--replace`ing one
if [ "$replace" ]; then

# Normalise submodule reference
replace=`printf %s "$replace" \
| tr '[A-Z]' '[a-z]' \
| sed 's/^\(.*\/\)\{0,1\}vendor\///; s/^grammars\///'`
replace=`git config --list \
| grep -Fi -m1 "submodule.vendor/grammars/$replace.url=" \
| sed 's/\.url=.*//; s/^submodule\.//' || :`
[ "$replace" ] || {
warn "Submodule '$replace' does not exist. Aborting."
exit 1
}

log "Deregistering submodule: $replace"
git submodule deinit "$replace"
git rm -rf "$replace"
script/grammar-compiler update -f >/dev/null 2>&1
fi

log "Registering new submodule: $url"
git submodule add -f "$url" "$path"
script/grammar-compiler add "$path"

log 'Caching grammar license'
bundle exec licensed cache -c vendor/licenses/config.yml

log 'Updating grammar documentation in vendor/README.md'
bundle exec rake samples >/dev/null 2>&1
script/sort-submodules
script/list-grammars
Loading

0 comments on commit 8b3c18c

Please sign in to comment.