Files
linguist/script/add-grammar

147 lines
3.8 KiB
Ruby
Executable File

#!/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 running with --verbose
def log(msg)
puts msg if $verbose
end
def command(*args)
log "$ #{args.join(' ')}"
output, status = Open3.capture2e(*args)
if !status.success?
warn "Command failed. Aborting."
error.output = output.each_line { |line| " > #{line}" }
raise { output: output, status: status }
end
end
usage = <<~EOH
Usage:
#{$0} [-v|--verbose] [--replace grammar] url
Examples:
#{$0} https://github.com/Alhadis/language-roff
#{$0} --replace sublime-apl https://github.com/Alhadis/language-apl
EOH
$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
# Flags to track which changes should be reverted on an error
$gitmodules = File.read("#{ROOT}/.gitmodules")
$git_config = File.read("#{ROOT}/.git/config")
$vendor_list = File.read("#{ROOT}/vendor/README.md")
def restore_configs
File.write("#{ROOT}/.gitmodules", $gitmodules)
File.write("#{ROOT}/.git/config", $git_config)
end
begin
# Exit early if Docker isn't installed or running.
log "Checking Docker is installed and running"
command('docker', 'ps')
# 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')
end
log "Registering new submodule: #{repo_new}"
command('git', 'submodule', 'add', '-f', https, repo_new)
command('script/grammar-compiler', 'add', repo_new)
log "Confirming license"
if repo_old
command('script/licensed')
else
command('script/licensed', '--module', repo_new)
end
log "Updating grammar documentation in vendor/README.md"
command('bundle', 'exec', 'rake', 'samples')
command('script/sort-submodules')
command('script/list-grammars')
rescue => ex
if repo_new
`git submodule deinit #{repo_new}`
`rm -rf #{repo_new}`
`rm -rf .git/modules/#{repo_new}/`
restore_configs()
end
if repo_old
`rm -rf #{repo_old}`
`git submodule add -f "#{https}", "#{repo_old}"`
restore_configs()
end
File.write("#{ROOT}/vendor/README.md", $vendor_list)
exit 1
end