Skip to content
This repository was archived by the owner on May 3, 2021. It is now read-only.

Commit b2d9aa2

Browse files
committed
Initial commit
0 parents  commit b2d9aa2

13 files changed

+296
-0
lines changed

.editorconfig

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[*.cr]
2+
charset = utf-8
3+
end_of_line = lf
4+
insert_final_newline = true
5+
indent_style = space
6+
indent_size = 2
7+
trim_trailing_whitespace = true

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/doc/
2+
/lib/
3+
/bin/
4+
/.shards/

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
language: crystal

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2018 Omar Roth
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# marpa_cr
2+
3+
TODO: Write a description here
4+
5+
## Installation
6+
7+
TODO: Write installation instructions here
8+
9+
## Usage
10+
11+
TODO: Write usage instructions here
12+
13+
## Development
14+
15+
TODO: Write development instructions here
16+
17+
## Contributing
18+
19+
1. Fork it ( https://github.com/[your-github-name]/marpa_cr/fork )
20+
2. Create your feature branch (git checkout -b my-new-feature)
21+
3. Commit your changes (git commit -am 'Add some feature')
22+
4. Push to the branch (git push origin my-new-feature)
23+
5. Create a new Pull Request
24+
25+
## Contributors
26+
27+
- [[your-github-name]](https://github.com/[your-github-name]) Omar Roth - creator, maintainer

dev/sentry.cr

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
module Sentry
2+
FILE_TIMESTAMPS = {} of String => String # {file => timestamp}
3+
4+
class ProcessRunner
5+
getter app_process : (Nil | Process) = nil
6+
property process_name : String
7+
property should_build = true
8+
property files = [] of String
9+
10+
def initialize(
11+
@process_name : String,
12+
@build_command : String,
13+
@run_command : String,
14+
@build_args : Array(String) = [] of String,
15+
@run_args : Array(String) = [] of String,
16+
files = [] of String,
17+
should_build = true
18+
)
19+
@files = files
20+
@should_build = should_build
21+
@should_kill = false
22+
@app_built = false
23+
end
24+
25+
private def build_app_process
26+
puts "🤖 compiling #{process_name}..."
27+
build_args = @build_args
28+
if build_args.size > 0
29+
Process.run(@build_command, build_args, shell: true, output: Process::Redirect::Inherit, error: Process::Redirect::Inherit)
30+
else
31+
Process.run(@build_command, shell: true, output: Process::Redirect::Inherit, error: Process::Redirect::Inherit)
32+
end
33+
end
34+
35+
private def create_app_process
36+
app_process = @app_process
37+
if app_process.is_a? Process
38+
unless app_process.terminated?
39+
puts "🤖 killing #{process_name}..."
40+
app_process.kill
41+
end
42+
end
43+
44+
puts "🤖 starting #{process_name}..."
45+
run_args = @run_args
46+
if run_args.size > 0
47+
@app_process = Process.new(@run_command, run_args, output: Process::Redirect::Inherit, error: Process::Redirect::Inherit)
48+
else
49+
@app_process = Process.new(@run_command, output: Process::Redirect::Inherit, error: Process::Redirect::Inherit)
50+
end
51+
end
52+
53+
private def get_timestamp(file : String)
54+
File.stat(file).mtime.to_s("%Y%m%d%H%M%S")
55+
end
56+
57+
# Compiles and starts the application
58+
#
59+
def start_app
60+
return create_app_process unless @should_build
61+
build_result = build_app_process()
62+
if build_result && build_result.success?
63+
@app_built = true
64+
create_app_process()
65+
elsif !@app_built # if build fails on first time compiling, then exit
66+
puts "🤖 Compile time errors detected. SentryBot shutting down..."
67+
exit 1
68+
end
69+
end
70+
71+
# Scans all of the `@files`
72+
#
73+
def scan_files
74+
file_changed = false
75+
app_process = @app_process
76+
files = @files
77+
Dir.glob(files) do |file|
78+
timestamp = get_timestamp(file)
79+
if FILE_TIMESTAMPS[file]? && FILE_TIMESTAMPS[file] != timestamp
80+
FILE_TIMESTAMPS[file] = timestamp
81+
file_changed = true
82+
puts "🤖 #{file}"
83+
elsif FILE_TIMESTAMPS[file]?.nil?
84+
puts "🤖 watching file: #{file}"
85+
FILE_TIMESTAMPS[file] = timestamp
86+
file_changed = true if (app_process && !app_process.terminated?)
87+
end
88+
end
89+
90+
start_app() if (file_changed || app_process.nil?)
91+
end
92+
93+
def run
94+
puts "🤖 Your SentryBot is vigilant. beep-boop..."
95+
96+
loop do
97+
if @should_kill
98+
puts "🤖 Powering down your SentryBot..."
99+
break
100+
end
101+
scan_files
102+
sleep 1
103+
end
104+
end
105+
106+
def kill
107+
@should_kill = true
108+
end
109+
end
110+
end

dev/sentry_cli.cr

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
require "option_parser"
2+
require "yaml"
3+
require "./sentry"
4+
5+
process_name = nil
6+
7+
begin
8+
shard_yml = YAML.parse File.read("shard.yml")
9+
name = shard_yml["name"]?
10+
process_name = name.as_s if name
11+
rescue e
12+
end
13+
14+
build_args = [] of String
15+
build_command = "crystal build ./src/#{process_name}.cr"
16+
run_args = [] of String
17+
run_command = "./#{process_name}"
18+
files = ["./src/**/*.cr", "./src/**/*.ecr"]
19+
files_cleared = false
20+
show_help = false
21+
should_build = true
22+
23+
OptionParser.parse! do |parser|
24+
parser.banner = "Usage: ./sentry [options]"
25+
parser.on(
26+
"-n NAME",
27+
"--name=NAME",
28+
"Sets the name of the app process (current name: #{process_name})") { |name| process_name = name }
29+
parser.on(
30+
"-b COMMAND",
31+
"--build=COMMAND",
32+
"Overrides the default build command") { |command| build_command = command }
33+
parser.on(
34+
"--build-args=ARGS",
35+
"Specifies arguments for the build command") do |args|
36+
args_arr = args.strip.split(" ")
37+
build_args = args_arr if args_arr.size > 0
38+
end
39+
parser.on(
40+
"--no-build",
41+
"Skips the build step") { should_build = false }
42+
parser.on(
43+
"-r COMMAND",
44+
"--run=COMMAND",
45+
"Overrides the default run command") { |command| run_command = command }
46+
parser.on(
47+
"--run-args=ARGS",
48+
"Specifies arguments for the run command") do |args|
49+
args_arr = args.strip.split(" ")
50+
run_args = args_arr if args_arr.size > 0
51+
end
52+
parser.on(
53+
"-w FILE",
54+
"--watch=FILE",
55+
"Overrides default files and appends to list of watched files") do |file|
56+
unless files_cleared
57+
files.clear
58+
files_cleared = true
59+
end
60+
files << file
61+
end
62+
parser.on(
63+
"-i",
64+
"--info",
65+
"Shows the values for build/run commands, build/run args, and watched files") do
66+
puts "
67+
name: #{process_name}
68+
build: #{build_command}
69+
build args: #{build_args}
70+
run: #{run_command}
71+
run args: #{run_args}
72+
files: #{files}
73+
"
74+
end
75+
parser.on(
76+
"-h",
77+
"--help",
78+
"Show this help") do
79+
puts parser
80+
exit 0
81+
end
82+
end
83+
84+
if process_name
85+
process_runner = Sentry::ProcessRunner.new(
86+
process_name: process_name.as(String),
87+
build_command: build_command,
88+
run_command: run_command,
89+
build_args: build_args,
90+
run_args: run_args,
91+
should_build: should_build,
92+
files: files
93+
)
94+
95+
process_runner.run
96+
else
97+
puts "🤖 Sentry error: 'name' not given and not found in shard.yml"
98+
exit 1
99+
end

marpa_cr

856 KB
Binary file not shown.

sentry

754 KB
Binary file not shown.

shard.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: marpa_cr
2+
version: 0.1.0
3+
4+
authors:
5+
- Omar Roth <[email protected]>
6+
7+
targets:
8+
marpa_cr:
9+
main: src/marpa_cr.cr
10+
11+
crystal: 0.24.1
12+
13+
license: MIT

spec/marpa_cr_spec.cr

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
require "./spec_helper"
2+
3+
describe MarpaCr do
4+
# TODO: Write tests
5+
6+
it "works" do
7+
false.should eq(true)
8+
end
9+
end

spec/spec_helper.cr

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require "spec"
2+
require "../src/marpa_cr"

src/marpa_cr.cr

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@[Link("marpa")]
2+
lib LibMarpa
3+
end

0 commit comments

Comments
 (0)