-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' of github.com:cloud66/alterant
# Conflicts: # README.md
- Loading branch information
Showing
33 changed files
with
705 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
alterant |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ruby-2.5.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"cSpell.words": [ | ||
"fqin" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
source 'https://rubygems.org' | ||
gemspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
PATH | ||
remote: . | ||
specs: | ||
alterant (0.0.1) | ||
colorize (~> 0.8) | ||
diffy (~> 3.2) | ||
json (~> 1.4) | ||
jsonpath (~> 0.9) | ||
mini_racer (~> 0.2) | ||
thor (~> 0.20) | ||
|
||
GEM | ||
remote: https://rubygems.org/ | ||
specs: | ||
colorize (0.8.1) | ||
diffy (3.2.1) | ||
ffi (1.9.25) | ||
json (1.8.6) | ||
jsonpath (0.9.4) | ||
multi_json | ||
to_regexp (~> 0.2.1) | ||
libv8 (6.7.288.46.1) | ||
listen (3.1.5) | ||
rb-fsevent (~> 0.9, >= 0.9.4) | ||
rb-inotify (~> 0.9, >= 0.9.7) | ||
ruby_dep (~> 1.2) | ||
mini_racer (0.2.3) | ||
libv8 (>= 6.3) | ||
multi_json (1.13.1) | ||
rake (10.5.0) | ||
rb-fsevent (0.10.3) | ||
rb-inotify (0.9.10) | ||
ffi (>= 0.5.0, < 2) | ||
rerun (0.13.0) | ||
listen (~> 3.0) | ||
ruby_dep (1.5.0) | ||
thor (0.20.0) | ||
to_regexp (0.2.1) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
alterant! | ||
bundler (~> 1.14) | ||
rake (~> 10.0) | ||
rerun (~> 0.13) | ||
|
||
BUNDLED WITH | ||
1.16.6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
require "bundler/gem_tasks" | ||
task :default => :spec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
|
||
# coding: utf-8 | ||
lib = File.expand_path('../lib', __FILE__) | ||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) | ||
|
||
require 'alterant/version' | ||
|
||
Gem::Specification.new do |spec| | ||
spec.name = "alterant" | ||
spec.version = Alterant::VERSION | ||
spec.authors = ["Khash Sajadi"] | ||
spec.email = ["khash@cloud66.com"] | ||
|
||
spec.summary = %q{Alterant gem and command line} | ||
spec.description = %q{Alterant is a tool to alter configuration files} | ||
spec.homepage = "https://github.com/cloud66/alterant" | ||
spec.license = 'Nonstandard' | ||
|
||
spec.files = Dir.glob("{bin,lib}/**/*") + %w(README.md) | ||
spec.bindir = "bin" | ||
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } | ||
spec.require_paths = ["lib"] | ||
|
||
spec.add_development_dependency "bundler", "~> 1.14" | ||
spec.add_development_dependency "rake", "~> 10.0" | ||
spec.add_development_dependency "rerun", "~> 0.13" | ||
|
||
spec.add_dependency 'jsonpath', '~>0.9' | ||
spec.add_dependency 'json', '~> 1.4' | ||
spec.add_dependency 'thor', '~> 0.20' | ||
spec.add_dependency 'mini_racer', '~> 0.2' | ||
spec.add_dependency 'colorize', '~> 0.8' | ||
spec.add_dependency 'diffy', '~> 3.2' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
#!/usr/bin/env ruby | ||
require 'thor' | ||
require 'yaml' | ||
require 'colorize' | ||
require_relative '../lib/alterant' | ||
|
||
module Alterant | ||
class AlterantCLI < Thor | ||
package_name "alterant" | ||
|
||
desc "version", "Show Alterant version" | ||
def version | ||
say "#{::Alterant::APP_NAME} #{::Alterant::VERSION}\n#{::Alterant::COPYRIGHT_MESSAGE}" | ||
end | ||
|
||
desc "update", "Update Alterant to the latest version" | ||
option :version, type: :string, desc: "Force a specific version" | ||
def update | ||
say "Updating Alterant..." | ||
unless options[:version] | ||
say `gem install alterant --no-ri --no-rdoc` | ||
else | ||
say `gem install alterant -v #{options[:version]} --no-ri --no-rdoc` | ||
end | ||
end | ||
|
||
desc "modify", "Runs the given script against a file" | ||
option :modifier, type: :string, desc: "Alterant JS script" | ||
option :in, type: :string, desc: "Input configuration file" | ||
option :out, type: :string, desc: "Output configuration file" | ||
option :output_format, type: :string, enum: ['yaml', 'json'], default: 'yaml', desc: "Output format" | ||
option :diff, type: :boolean, default: false, desc: "Return the diff instead of the output itself" | ||
option :debug, type: :boolean, default: false | ||
option :input_format, type: :string, enum: ['yaml', 'json'], default: 'yaml', desc: "Input format if it's based on a stream and not a file" | ||
option :overwrite, type: :boolean, default: false | ||
def modify | ||
$debug = options[:debug] || false | ||
overwrite = options[:overwrite] | ||
diff = options[:diff] | ||
output_format = options[:output_format] | ||
input_format = options[:input_format] | ||
|
||
in_file = options[:in] | ||
if !in_file | ||
STDERR.puts "No input file provided. Use --in option".red | ||
exit(1) | ||
end | ||
if in_file != '-' | ||
unless File.exists?(in_file) | ||
STDERR.puts "Input file #{in_file} not found".red | ||
exit(1) | ||
end | ||
# detect the type | ||
input_ext = File.extname(in_file) | ||
unless ['.yaml', '.yml', '.json'].include? input_ext | ||
STDERR.puts "Only yaml and json files are supported for input".red | ||
exit(1) | ||
end | ||
if ['.yaml', '.yml'].include?(input_ext) | ||
input_format = 'yaml' | ||
else | ||
input_format = 'json' | ||
end | ||
|
||
output_format = input_format if !output_format | ||
end | ||
|
||
modifier_file = options[:modifier] | ||
if !modifier_file | ||
STDERR.puts "No script file provided. Use --modifier option".red | ||
exit(1) | ||
end | ||
unless File.exists?(modifier_file) | ||
STDERR.puts "Modifier file #{modifier_file} not found".red | ||
exit(1) | ||
end | ||
|
||
out_file = options[:out] | ||
if out_file | ||
if !overwrite && File.exists?(out_file) | ||
STDERR.puts "Output file #{out_file} already exists. Use --overwrite flag to overwrite it".red | ||
exit(1) | ||
end | ||
else | ||
out_file = '-' # output to stdout | ||
end | ||
|
||
|
||
data = [] | ||
if in_file == '-' | ||
input_text = STDIN.read | ||
else | ||
input_text = File.read(in_file) | ||
end | ||
|
||
if input_format == 'yaml' | ||
if input_text.empty? | ||
STDERR.puts "Empty input file".red | ||
exit(2) | ||
end | ||
|
||
input_text.split('---').each_with_index do |part, idx| | ||
part_data = YAML.load(part) | ||
data << part_data | ||
end | ||
|
||
else | ||
file_data = JSON.parse(input_text) | ||
if file_data.is_a? Array | ||
data = file_data | ||
else | ||
data = [file_data] | ||
end | ||
end | ||
|
||
run_context = {} | ||
modifier = File.read(modifier_file) | ||
if in_file != '-' | ||
run_context[:basedir] = File.dirname(in_file) | ||
end | ||
|
||
run_context[:js_preload] = ::Alterant::Classes.LoadClasses | ||
alter = ::Alterant::Alterant.new(input: data, modifier: modifier, filename: modifier_file, options: run_context) | ||
results = alter.execute(timeout: 500) | ||
|
||
if results.nil? | ||
STDERR.puts "Aborting".red | ||
exit(2) | ||
end | ||
|
||
if output_format == 'yaml' || output_format == 'yml' | ||
converted_as_text = results.map { |r| r.to_yaml }.join("\n") | ||
input = data.map { |r| r.to_yaml }.join("\n") | ||
elsif output_format == 'json' | ||
converted_as_text = JSON.pretty_generate(results) | ||
input = JSON.pretty_generate(data) | ||
end | ||
|
||
if diff | ||
output_as_text = Diffy::Diff.new(input, converted_as_text) | ||
else | ||
output_as_text = converted_as_text | ||
end | ||
|
||
if out_file == "-" | ||
puts output_as_text | ||
else | ||
File.open(out_file, 'w') do |file| | ||
file.write(output_as_text) | ||
end | ||
end | ||
return true | ||
rescue ::Alterant::ParseError => exc | ||
STDERR.puts "Syntax error: #{exc.message}".red | ||
return false | ||
rescue ::Alterant::RuntimeError => exc | ||
STDERR.puts "Runtime error: #{exc.message}".red | ||
return false | ||
rescue => exc | ||
if $debug | ||
raise | ||
else | ||
STDERR.puts exc | ||
end | ||
return false | ||
end | ||
end | ||
|
||
AlterantCLI.start | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/usr/bin/env ruby | ||
|
||
require "bundler/setup" | ||
require "alterant" | ||
|
||
# You can add fixtures and/or initialization code here to make experimenting | ||
# with your gem easier. You can also use a different console, if you like. | ||
|
||
# (If you use this, don't forget to add pry to your Gemfile!) | ||
# require "pry" | ||
# Pry.start | ||
|
||
require "irb" | ||
IRB.start(__FILE__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/usr/bin/env bash | ||
set -euo pipefail | ||
IFS=$'\n\t' | ||
set -vx | ||
|
||
bundle install | ||
|
||
# Do any other automated setup that you need to do here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require_relative 'alterant/version' | ||
require_relative 'alterant/utils' | ||
require_relative 'alterant/loader' | ||
|
||
module Alterant | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
module Alterant | ||
class Alterant | ||
attr_reader :basedir | ||
|
||
# input is a hash | ||
# filename is the modifier filename use for the backtrace | ||
# modifier is the script in string | ||
def initialize(input:, modifier:, filename:, options: {}) | ||
@modifier = modifier | ||
@filename = filename | ||
@input = input | ||
@basedir = options[:basedir] | ||
@js_preload = options[:js_preload] || [] | ||
end | ||
|
||
# timeout is in ms | ||
# returns a hash | ||
def execute(timeout: 500, max_memory: 5000000) | ||
jpath = ::Alterant::Helpers::Jpath.new | ||
|
||
result = [] | ||
snapshot = MiniRacer::Snapshot.new("$$ = #{@input.to_json};\n" + @js_preload.join("\n")) # this is more efficient but we lose debug info (filename) of helper classes | ||
|
||
isolate = MiniRacer::Isolate.new(snapshot) | ||
@input.each_with_index do |input, idx| | ||
ctx = ::MiniRacer::Context.new(isolate: isolate, timeout: timeout, max_memory: max_memory) | ||
ctx.eval("$ = #{input.to_json}") | ||
ctx.eval("$['fetch'] = function(key) { return jpath.fetch(JSON.stringify($), key); }") | ||
ctx.attach('jpath.fetch', proc{|x, y| jpath.fetch(x, y)}) | ||
ctx.attach('console.log', proc{|x| STDERR.puts("DEBUG: #{x.inspect}") if $debug }) | ||
ctx.attach('console.exception', proc{|x| raise ::Alterant::RuntimeError, x }) | ||
ctx.attach('$$.push', proc{|x| result << x }) | ||
ctx.attach('$.index', proc{ idx }) | ||
ctx.attach('YamlReader', ::Alterant::Classes::YamlReader.new(self, ctx)) | ||
ctx.attach('JsonReader', ::Alterant::Classes::JsonReader.new(self, ctx)) | ||
|
||
ctx.eval(@modifier, filename: @filename) | ||
pre_convert = ctx.eval("JSON.stringify($)") | ||
converted = JSON.parse(pre_convert) | ||
result << converted | ||
|
||
ctx.dispose | ||
isolate.idle_notification(100) | ||
rescue ::MiniRacer::RuntimeError => exc | ||
if $debug | ||
raise | ||
else | ||
raise ::Alterant::ParseError, "part: #{idx} - #{exc.message}, #{exc.backtrace.first}" | ||
end | ||
rescue ::Alterant::AlterantError => exc | ||
STDERR.puts exc.message.red | ||
return nil | ||
end | ||
|
||
return result | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module Alterant | ||
module Classes | ||
CLASSES = {} | ||
|
||
def self.LoadClasses | ||
# ::Alterant::Classes.constants.map(&::Alterant::Classes.method(:const_get)).grep(Class) do |c| | ||
# name = c.name.split('::').last | ||
# ::Alterant::Classes::CLASSES[name] = c | ||
# end | ||
|
||
# load all JS files in the classes dir and construct a long text | ||
js_preload = [] | ||
Dir["#{__dir__}/*.js"].each do |f| | ||
js_preload << File.read(f) | ||
end | ||
|
||
return js_preload | ||
end | ||
end | ||
end |
Oops, something went wrong.