hastie 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +9 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/Gemfile +10 -0
- data/LICENSE +21 -0
- data/README.textile +136 -0
- data/Rakefile +1 -0
- data/bin/hastie +64 -0
- data/hastie.gemspec +31 -0
- data/lib/hastie/config_file.rb +42 -0
- data/lib/hastie/config_generator.rb +37 -0
- data/lib/hastie/constants.rb +25 -0
- data/lib/hastie/report_generator.rb +118 -0
- data/lib/hastie/report_publisher.rb +162 -0
- data/lib/hastie/report_updater.rb +40 -0
- data/lib/hastie/report_watcher.rb +65 -0
- data/lib/hastie/server_generator.rb +47 -0
- data/lib/hastie/server_reader.rb +81 -0
- data/lib/hastie/templates/hastie_config.tt +6 -0
- data/lib/hastie/templates/report.markdown.tt +19 -0
- data/lib/hastie/templates/report.textile.tt +19 -0
- data/lib/hastie/templates/report_index.html.tt +8 -0
- data/lib/hastie/templates/server/.gitignore +1 -0
- data/lib/hastie/templates/server/_config.yml +25 -0
- data/lib/hastie/templates/server/_includes/.gitignore +0 -0
- data/lib/hastie/templates/server/_layouts/.gitignore +0 -0
- data/lib/hastie/templates/server/_plugins/.gitignore +0 -0
- data/lib/hastie/templates/server/_posts/.gitignore +0 -0
- data/lib/hastie/templates/server/_reports.yml +0 -0
- data/lib/hastie/templates/server/_server_config.yml +15 -0
- data/lib/hastie/templates/server/css/.gitignore +0 -0
- data/lib/hastie/templates/server/data/.gitignore +0 -0
- data/lib/hastie/templates/server/imgs/.gitignore +0 -0
- data/lib/hastie/templates/server/index.html +0 -0
- data/lib/hastie/templates/server/js/.gitignore +0 -0
- data/lib/hastie/version.rb +3 -0
- data/lib/hastie.rb +15 -0
- data/spec/config_generator_spec.rb +124 -0
- data/spec/fakefs_helper.rb +67 -0
- data/spec/fixtures/config.ru +29 -0
- data/spec/fixtures/hastie_config +2 -0
- data/spec/fixtures/report/2110-12-16-report.textile +19 -0
- data/spec/fixtures/report/_config.yml +9 -0
- data/spec/fixtures/report/data/report/.gitignore +0 -0
- data/spec/fixtures/report/imgs/report/.gitignore +0 -0
- data/spec/fixtures/report/js/.gitignore +0 -0
- data/spec/fixtures/report/report.yml +23 -0
- data/spec/fixtures/server/_config.yml +10 -0
- data/spec/fixtures/server/_posts/2011-11-11-jfv_mak_snp_analysis.textile +0 -0
- data/spec/fixtures/server/_reports.yml +1 -0
- data/spec/fixtures/server/css/style.css +126 -0
- data/spec/fixtures/server/data/jfv_mak_snp_analysis/.gitignore +0 -0
- data/spec/fixtures/server/imgs/favicon.ico +0 -0
- data/spec/fixtures/server/imgs/subset_images/.gitignore +0 -0
- data/spec/fixtures/server/js/.gitignore +0 -0
- data/spec/report_generator_spec.rb +168 -0
- data/spec/report_publisher_spec.rb +148 -0
- data/spec/report_updater_spec.rb +54 -0
- data/spec/report_watcher_spec.rb +99 -0
- data/spec/server_generator_spec.rb +68 -0
- data/spec/server_reader_spec.rb +120 -0
- data/spec/spec_helper.rb +52 -0
- metadata +234 -0
data/.autotest
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Autotest.add_hook :initialize do |at|
|
2
|
+
at.clear_mappings
|
3
|
+
at.add_exception(/\.git/)
|
4
|
+
at.add_exception(/coverage/)
|
5
|
+
at.add_exception(/spec\/sandbox/)
|
6
|
+
at.add_mapping(%r{^spec/.*_spec}) {|filename,_| at.files_matching %r{#{filename}}}
|
7
|
+
at.add_mapping(%r{}) {|_,_| at.files_matching %r{spec/.*_spec}}
|
8
|
+
end
|
9
|
+
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2011 Jim Vallandingham
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.textile
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
h1. Hastie
|
2
|
+
|
3
|
+
A tool to extend Jekyll for use in report creation.
|
4
|
+
|
5
|
+
h2. Using Hastie
|
6
|
+
|
7
|
+
Assuming you have hastie installed, what are the steps to start using it? These steps also assume you have a compatible jekyll installed as well as a jekyll blog framework, such as bioreports. See below for more info on jekyll and bioreports.
|
8
|
+
|
9
|
+
h3. hastie config
|
10
|
+
|
11
|
+
First, setup your @.hastie@ config file to point to your bioreports path
|
12
|
+
|
13
|
+
<pre>
|
14
|
+
hastie config /path/to/bioreports/source -a jfv -t textile
|
15
|
+
</pre>
|
16
|
+
|
17
|
+
This creates a @.hastie@ file in your home directory. The @-a@ flag indicates the analyst (your username) to set. The @-t@ flag tells hastie to generate textile documents for your reports.
|
18
|
+
|
19
|
+
h3. hastie create
|
20
|
+
|
21
|
+
Now you are ready to generate a new report. Navigate to the directory that you would like the report to be created in, and create it with @hastie create@:
|
22
|
+
|
23
|
+
<pre>
|
24
|
+
cd /path/to/report/base
|
25
|
+
hastie create analysis_of_sample_x -r ada -p hym
|
26
|
+
</pre>
|
27
|
+
|
28
|
+
This will create a new directory called @report@ with your new report inside. The flags set meta data about the report. @-r@ for the researcher this report is for and @-p@ for the PI or lead researcher of the researcher specified by @-r@. These flags are optional. This data can be easily added later to your report if you forget.
|
29
|
+
|
30
|
+
Inside your report directory will be a number of files and sub-directories to get your report started. Many of these files are copied directly from the server you supplied in your config file.
|
31
|
+
|
32
|
+
h3. hastie watch
|
33
|
+
|
34
|
+
Now start editing your report. It will be inside your @report@ directory, and be named @date_report_name.textile@. Watch changes to your report as you modify this file using @hastie watch@:
|
35
|
+
|
36
|
+
<pre>
|
37
|
+
cd report
|
38
|
+
vim 2011-02-04_analysis_of_sample_x.textile
|
39
|
+
hastie watch
|
40
|
+
</pre>
|
41
|
+
|
42
|
+
Hastie watch really just starts jekyll and builds your report locally. But this helps so that you don't have to remember any new commands.
|
43
|
+
|
44
|
+
h3. hastie publish
|
45
|
+
|
46
|
+
Now you have some info in your report, and you would like to publish it to the main server. That's where @hastie publish@ comes in:
|
47
|
+
|
48
|
+
<pre>
|
49
|
+
# ctrl-c to kill hastie watch
|
50
|
+
hastie publish
|
51
|
+
</pre>
|
52
|
+
|
53
|
+
This will copy your important files to the server in your @.hastie@ file and then run jekyll there. It will also check in this change to your server's git repository.
|
54
|
+
|
55
|
+
And that's all there is to creating a new report! @create@, @watch@, and @publish@.
|
56
|
+
|
57
|
+
h3. NOTE
|
58
|
+
|
59
|
+
Users may get an error in @read_yaml@ about an *invalid byte sequence*. To fix this, modify your @.bashrc@ to include:
|
60
|
+
|
61
|
+
<pre>
|
62
|
+
export LC_ALL=en_US.UTF-8
|
63
|
+
export LANG=en_US.UTF-8
|
64
|
+
</pre>
|
65
|
+
|
66
|
+
This is "documented in a jekyll issue":https://github.com/mojombo/jekyll/issues/188
|
67
|
+
|
68
|
+
h2. What is Hastie?
|
69
|
+
|
70
|
+
Hastie works with "Jekyll":https://github.com/metalhelix/jekyll to create a powerful and flexible system by which reports can be created by different individuals and uploaded to a central 'server'.
|
71
|
+
|
72
|
+
h2. Why Hastie?
|
73
|
+
|
74
|
+
Say you work in an office that generates data, and reports about that data, for clients (so, for example, a core Bioinformatics facility providing results to various research labs).
|
75
|
+
|
76
|
+
The reports you generate typically come as a mix of Word documents, Excel spreadsheets, and external data files. Everyone in your office creates these reports differently. They are stored in various locations, in various folders on networked drives. They have different levels of information, and generally are a hassle to create and update.
|
77
|
+
|
78
|
+
Consumers of these reports (i.e. the researchers you generated them for) have to navigate confusing and disparate network paths to find these reports. They have to have Word, Excel, and whatever other programs you have (and the right versions of these programs) installed on the computer they are using, and have to have them all open at the same time to see their report and data.
|
79
|
+
|
80
|
+
In short, there is a high cost for both encoding and decoding this information. Its a lose lose situation.
|
81
|
+
|
82
|
+
Hastie is a component of a small suite of tools to facilitate faster encoding and decoding of this data. Attempting to lower the requirements of producing and consuming reports - so producers (analysts) can generate bigger, better, reports faster and more consistent with their co-workers, and consumers (researchers) can get to their data with less hand-holding and fewer hoops to jump through.
|
83
|
+
|
84
|
+
|
85
|
+
h2. What part does Hastie play?
|
86
|
+
|
87
|
+
Hastie serves as a simple interface between the creators of the reports and the report system itself. It takes care of all the back-end silliness, and lets you create and publish reports quickly and easily.
|
88
|
+
|
89
|
+
Hastie is a command-line tool that communicates with the report server (really just a jekyll source directory). It creates a framework for building up a report, allows you to develop this report locally, with whatever tools you are most comfortable with, and then easily publish this report so that it can be shared with others.
|
90
|
+
|
91
|
+
h2. Hastie's associates
|
92
|
+
|
93
|
+
Hastie is one piece of the puzzle for better, faster, more consistent reports. You also need:
|
94
|
+
* "Jekyll":https://github.com/metalhelix/jekyll - a static site generator that has lots of power behind it to allow customization galore. Jekyll is built for blogs - but with Hastie's help, it makes a mighty fine report system as well.
|
95
|
+
** Hastie requires a custom build of Jekyll that includes some missing features to be fully functional.
|
96
|
+
** Hopefully in the future, these features will be integrated back into Jekyll proper.
|
97
|
+
* A Jekyll site framework. Jekyll allows for plugins and layouts and other components. Hastie also expects some additional files present in its 'Jekyll Sever' to work.
|
98
|
+
** Check out "bioreports":https://github.com/metalhexlix/bioreports for an example of such a site framework.
|
99
|
+
|
100
|
+
|
101
|
+
h2. Hastie features
|
102
|
+
|
103
|
+
<pre>
|
104
|
+
Usage: hastie [COMMAND] <OPTIONS>
|
105
|
+
|
106
|
+
Hastie Commands:
|
107
|
+
version - Print version number and exit
|
108
|
+
help - Print this help and exit
|
109
|
+
create - Create new report directory framework with given name
|
110
|
+
watch - Monitor current directory for changes.
|
111
|
+
Updates local copy of report
|
112
|
+
publish - Send report to server. Update published reports
|
113
|
+
update - Update local report directory with changes from report server
|
114
|
+
config - Create new hastie config file for communicating with server
|
115
|
+
create_server - Create new server directory framework with given name
|
116
|
+
|
117
|
+
create options:
|
118
|
+
Use 'hastie create -h' for more information on start options
|
119
|
+
|
120
|
+
publish options:
|
121
|
+
Use 'hastie publish -h' for more information on publish options
|
122
|
+
|
123
|
+
update options:
|
124
|
+
Use 'hastie update -h' for more information on publish options
|
125
|
+
|
126
|
+
config options:
|
127
|
+
Use 'hastie config -h' for more information on publish options
|
128
|
+
|
129
|
+
create_server options:
|
130
|
+
Use 'hastie create_server -h' for more information on publish options
|
131
|
+
</pre>
|
132
|
+
|
133
|
+
|
134
|
+
h2. Whats in a name?
|
135
|
+
|
136
|
+
In Strange Case of Dr. Jekyll and Mr. Hyde, "Dr. Hastie Lanyon":http://en.wikipedia.org/wiki/Strange_Case_of_Dr_Jekyll_and_Mr_Hyde#Dr_Hastie_Lanyon finds Jekyll's ideas *too fanciful*.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/hastie
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby -*-
|
3
|
+
|
4
|
+
require 'hastie'
|
5
|
+
|
6
|
+
module Hastie
|
7
|
+
module Executable
|
8
|
+
HELP = <<-HELP
|
9
|
+
Usage: hastie [COMMAND] <OPTIONS>
|
10
|
+
|
11
|
+
Hastie Commands:
|
12
|
+
version - Print version number and exit
|
13
|
+
help - Print this help and exit
|
14
|
+
create - Create new report directory framework with given name
|
15
|
+
watch - Monitor current directory for changes.
|
16
|
+
Updates local copy of report
|
17
|
+
publish - Send report to server. Update published reports
|
18
|
+
update - Update local report directory with changes from report server
|
19
|
+
config - Create new hastie config file for communicating with server
|
20
|
+
create_server - Create new server directory framework with given name
|
21
|
+
|
22
|
+
create options:
|
23
|
+
Use 'hastie create -h' for more information on start options
|
24
|
+
|
25
|
+
publish options:
|
26
|
+
Use 'hastie publish -h' for more information on publish options
|
27
|
+
|
28
|
+
update options:
|
29
|
+
Use 'hastie update -h' for more information on publish options
|
30
|
+
|
31
|
+
config options:
|
32
|
+
Use 'hastie config -h' for more information on publish options
|
33
|
+
|
34
|
+
create_server options:
|
35
|
+
Use 'hastie create_server -h' for more information on publish options
|
36
|
+
|
37
|
+
HELP
|
38
|
+
|
39
|
+
def self.execute(command, args)
|
40
|
+
case command
|
41
|
+
when "version"
|
42
|
+
require 'hastie/version'
|
43
|
+
puts Hastie::VERSION
|
44
|
+
when "create", "start"
|
45
|
+
Hastie::ReportGenerator.start ARGV
|
46
|
+
when "watch", "monitor"
|
47
|
+
Hastie::ReportWatcher.start ARGV
|
48
|
+
when "publish"
|
49
|
+
Hastie::ReportPublisher.start ARGV
|
50
|
+
when "update"
|
51
|
+
Hastie::ReportUpdater.start ARGV
|
52
|
+
when "config"
|
53
|
+
Hastie::ConfigGenerator.start ARGV
|
54
|
+
when "create_server","server_start"
|
55
|
+
Hastie::ServerGenerator.start ARGV
|
56
|
+
else
|
57
|
+
puts Hastie::Executable::HELP
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
command = ARGV.shift
|
64
|
+
Hastie::Executable.execute command, ARGV
|
data/hastie.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/hastie/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.add_dependency "thor", "~> 0.14.6"
|
6
|
+
s.add_dependency "grit", "~> 2.4.1"
|
7
|
+
s.add_dependency "sinatra", "~> 1.3.2"
|
8
|
+
s.add_dependency "thin", "~> 1.3.1"
|
9
|
+
s.add_development_dependency "bundler", "~> 1.0"
|
10
|
+
s.add_development_dependency "rdoc", "~> 3.9"
|
11
|
+
s.add_development_dependency "rspec", "~> 2.3"
|
12
|
+
s.add_development_dependency "simplecov", "~> 0.4"
|
13
|
+
s.add_development_dependency "ZenTest", "~> 4.5.0"
|
14
|
+
# s.add_development_dependency "autotest-fsevent", "~> 0.2.5"
|
15
|
+
# s.add_development_dependency "autotest-growl", "~> 0.2.9"
|
16
|
+
s.authors = ['Jim Vallandingham']
|
17
|
+
s.description = %q{}
|
18
|
+
s.email = 'none@none.com'
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
|
20
|
+
s.extra_rdoc_files = ['LICENSE', 'README.textile']
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.homepage = 'http://github.com/vlandham/hastie'
|
23
|
+
s.name = 'hastie'
|
24
|
+
s.rdoc_options = ['--charset=UTF-8']
|
25
|
+
s.require_paths = ['lib']
|
26
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 1.3.6')
|
27
|
+
s.summary = s.description
|
28
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
29
|
+
s.version = Hastie::VERSION.dup
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'thor/core_ext/hash_with_indifferent_access'
|
3
|
+
|
4
|
+
module Hastie
|
5
|
+
class ConfigFile
|
6
|
+
|
7
|
+
# takes yaml filename
|
8
|
+
# outputs thor's hash with indifferent access of content
|
9
|
+
# if input file cannot be read, empty thor hash is returned
|
10
|
+
def self.load filename, root = nil
|
11
|
+
if !File.exists? filename
|
12
|
+
return
|
13
|
+
end
|
14
|
+
output = Thor::CoreExt::HashWithIndifferentAccess.new()
|
15
|
+
config = YAML.load(File.read(filename))
|
16
|
+
if config
|
17
|
+
if root
|
18
|
+
config = {root => config}
|
19
|
+
end
|
20
|
+
output = Thor::CoreExt::HashWithIndifferentAccess.new(config)
|
21
|
+
end
|
22
|
+
output
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.write filename, data
|
26
|
+
output_data = data.to_hash.to_yaml
|
27
|
+
File.open(filename, 'w') {|file| file.puts output_data}
|
28
|
+
end
|
29
|
+
|
30
|
+
# very lazy. very limited
|
31
|
+
# only use for _reports.yml
|
32
|
+
def self.append filename, data
|
33
|
+
if !File.exists? filename
|
34
|
+
puts "ERROR: #{filename} not found"
|
35
|
+
return
|
36
|
+
end
|
37
|
+
File.open(filename, 'a') do |file|
|
38
|
+
file.puts "- #{data}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'thor/group'
|
3
|
+
require 'hastie/constants'
|
4
|
+
module Hastie
|
5
|
+
class ConfigGenerator < Thor::Group
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
def self.banner
|
9
|
+
"hastie config [SERVER_ROOT] <OPTIONS>"
|
10
|
+
end
|
11
|
+
|
12
|
+
argument :server_root, :type => :string, :desc => "Root path of server location"
|
13
|
+
class_option :path, :aliases => "-p", :desc => "Root directory of where the config file will be written to", :default => File.expand_path("~")
|
14
|
+
class_option :name, :aliases => "-n", :desc => "Name of the config file", :default => ".hastie"
|
15
|
+
class_option :analyst, :aliases => "-a", :desc => "Analyst for reports generated with this config file"
|
16
|
+
class_option :type, :aliases => "-t", :desc => "Default format of reports to generate", :default => "textile"
|
17
|
+
|
18
|
+
def self.source_root
|
19
|
+
File.dirname(__FILE__)
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def check_server_root
|
24
|
+
if !File.directory? server_root
|
25
|
+
say_status "error", "#{server_root} is not a directory", :red
|
26
|
+
say_status "error", "Please use full path to server directory", :red
|
27
|
+
exit(1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_config_file
|
32
|
+
output_file = File.join(options[:path], options[:name])
|
33
|
+
template "templates/hastie_config.tt", output_file
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Hastie
|
2
|
+
CONFIG_FILE = File.expand_path(File.join("~", ".hastie"))
|
3
|
+
SERVER_REPORTS_FILE = "_reports.yml"
|
4
|
+
SERVER_CONFIG_FILE = "_config.yml"
|
5
|
+
SERVER_PUBLISH_CONFIG_FILE = "_server_config.yml"
|
6
|
+
|
7
|
+
DATA_ROOT = "data"
|
8
|
+
REPORT_CONFIG_FILE = "report.yml"
|
9
|
+
|
10
|
+
def self.config_file
|
11
|
+
CONFIG_FILE
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.report_config_name
|
15
|
+
REPORT_CONFIG_FILE
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.watch_config_file
|
19
|
+
SERVER_CONFIG_FILE
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.publish_config_file
|
23
|
+
SERVER_PUBLISH_CONFIG_FILE
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'hastie/config_file'
|
3
|
+
require 'hastie/constants'
|
4
|
+
require 'hastie/server_reader'
|
5
|
+
|
6
|
+
module Hastie
|
7
|
+
class ReportGenerator < ServerReader
|
8
|
+
def self.banner
|
9
|
+
"hastie create [NAME] <OPTIONS>"
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :report_id, :title, :analyst, :researcher, :pi
|
13
|
+
|
14
|
+
desc "Creates framework for new report"
|
15
|
+
argument :name, :type => :string, :desc => "The name of the new report. no spaces"
|
16
|
+
class_option :type, :aliases => "-t", :desc => "Type of report to generate"
|
17
|
+
class_option :analyst, :aliases => "-a", :desc => "Analyst generating the report"
|
18
|
+
class_option :researcher, :aliases => "-r", :desc => "Researcher the report is for"
|
19
|
+
class_option :pi, :aliases => "-p", :desc => "PI the researcher is under"
|
20
|
+
class_option :date, :aliases => "-d", :desc => "Date to use in report filename. Ex: 2011-11-29", :default => "#{Time.now.strftime('%Y-%m-%d')}"
|
21
|
+
class_option :output, :aliases => "-o", :desc => "Output Directory for report", :default => File.join(".", "report")
|
22
|
+
|
23
|
+
def setup_variables
|
24
|
+
options[:type] ||= "textile"
|
25
|
+
options[:date] ||= "#{Time.now.strftime('%Y-%m-%d')}"
|
26
|
+
options[:name] = File.basename(name)
|
27
|
+
self.title = options[:name].gsub("_", " ").capitalize
|
28
|
+
options[:title] = self.title
|
29
|
+
# report_id will be used internally in case the name turns
|
30
|
+
# out to be too loose to use
|
31
|
+
self.report_id = File.basename(name)
|
32
|
+
options[:report_id] = self.report_id
|
33
|
+
self.destination_root = options[:output]
|
34
|
+
say_status "note", "root: #{self.destination_root}"
|
35
|
+
|
36
|
+
options[:analyst] ||= "unknown"
|
37
|
+
self.analyst = options[:analyst] || "unknown"
|
38
|
+
options[:researcher] ||= "unknown"
|
39
|
+
options[:pi] ||= "unknown"
|
40
|
+
options[:data_dir] ||= data_dir
|
41
|
+
end
|
42
|
+
|
43
|
+
def check_name_availible
|
44
|
+
if options[:published_reports] and options[:published_reports].include? report_id
|
45
|
+
say_status "error", "Sorry, the #{report_id} is already a published report", :red
|
46
|
+
say_status "error", "Please run again with a different name", :red
|
47
|
+
exit(1)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_destination
|
52
|
+
if File.exists? self.destination_root
|
53
|
+
say_status "error", "#{self.destination_root} already exists.", :red
|
54
|
+
say_status "error", "please choose different output directory", :red
|
55
|
+
exit(1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_report_file
|
60
|
+
say_status "create", "report: #{options[:report_id]}"
|
61
|
+
extension = determine_extension(options[:type])
|
62
|
+
options[:extension] = extension
|
63
|
+
template_file = "templates/report.#{extension}.tt"
|
64
|
+
report_filename = "#{options[:date]}-#{report_id}.#{extension}"
|
65
|
+
say_status "note", "report file: #{report_filename}"
|
66
|
+
template template_file, report_filename
|
67
|
+
options[:report_file] = report_filename
|
68
|
+
options[:report_file_generated] = File.basename(report_filename, File.extname(report_filename)) + ".html"
|
69
|
+
end
|
70
|
+
|
71
|
+
def create_index_file
|
72
|
+
template_file = "templates/report_index.html.tt"
|
73
|
+
template template_file, "index.html"
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_data_dir
|
77
|
+
create_file File.join(data_dir, ".gitignore"), :verbose => true
|
78
|
+
end
|
79
|
+
|
80
|
+
def fetch_static_files
|
81
|
+
options[:server]["static"] ||= []
|
82
|
+
options[:server]["static"].each do |static_file|
|
83
|
+
static_path = File.join(options[:server_root], static_file)
|
84
|
+
if File.exists? static_path
|
85
|
+
say_status "copy", "#{static_path} to #{File.basename(destination_root)}"
|
86
|
+
FileUtils.cp_r static_path, self.destination_root
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def write_config_file
|
92
|
+
output_config_file = File.join(self.destination_root, Hastie.report_config_name)
|
93
|
+
say_status "write", "#{File.basename(output_config_file)}"
|
94
|
+
ConfigFile.write(output_config_file, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
no_tasks do
|
98
|
+
def determine_extension report_type
|
99
|
+
extension = case report_type.to_sym
|
100
|
+
when :markdown,:md
|
101
|
+
"markdown"
|
102
|
+
when :textile
|
103
|
+
"textile"
|
104
|
+
when :html,:htm
|
105
|
+
"html"
|
106
|
+
else
|
107
|
+
say "WARNING: #{report_type} not a valid type. Defaulting to textile"
|
108
|
+
"textile"
|
109
|
+
end
|
110
|
+
extension
|
111
|
+
end
|
112
|
+
|
113
|
+
def data_dir
|
114
|
+
File.join(DATA_ROOT, options[:report_id])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'hastie/config_file'
|
3
|
+
require 'hastie/constants'
|
4
|
+
require 'hastie/server_reader'
|
5
|
+
|
6
|
+
module Hastie
|
7
|
+
class ReportPublisher < ServerReader
|
8
|
+
def self.banner
|
9
|
+
"hastie publish <REPORT_DIR> <OPTIONS>"
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :report_dir
|
13
|
+
desc "Publishes report to server"
|
14
|
+
argument :name, :type => :string, :default => ".", :desc => "The name report directory"
|
15
|
+
|
16
|
+
def read_report_file
|
17
|
+
self.report_dir = File.expand_path(name)
|
18
|
+
report_config_file = File.join(report_dir, Hastie.report_config_name)
|
19
|
+
if !File.exists? report_config_file
|
20
|
+
say "Cannot locate #{Hastie.report_config_name}."
|
21
|
+
say "Current directory is not a report."
|
22
|
+
exit(1)
|
23
|
+
end
|
24
|
+
# we get the report filename from this config file
|
25
|
+
local_config = ConfigFile.load(report_config_file, :local)
|
26
|
+
self.options = local_config.merge(self.options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_options
|
30
|
+
all_valid = true
|
31
|
+
required_server_options = ["reports_dir"]
|
32
|
+
required_server_options.each do |option|
|
33
|
+
if !options[:server] or !options[:server][option]
|
34
|
+
say_status "error", "Missing #{option} option from server config", :red
|
35
|
+
all_valid = false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
required_local_options = ["report_file", "report_id"]
|
40
|
+
required_local_options.each do |option|
|
41
|
+
if !options[:local] or !options[:local][option]
|
42
|
+
say_status "error", "Missing #{option} option from local config", :red
|
43
|
+
all_valid = false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if !all_valid
|
48
|
+
exit(1)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_destination_directory
|
53
|
+
self.destination_root = File.join(options[:server_root])
|
54
|
+
say_status "note", "root: #{self.destination_root}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def copy_report_file
|
58
|
+
report_filename = options[:local]["report_file"]
|
59
|
+
local_report = File.join(report_dir, report_filename)
|
60
|
+
destination_report = File.join(options[:server_root], options[:server]["reports_dir"], report_filename)
|
61
|
+
|
62
|
+
if File.exists? destination_report
|
63
|
+
say_status "removing", destination_report, :yellow
|
64
|
+
command = "rm -f #{destination_report}"
|
65
|
+
pid = Process.fork do
|
66
|
+
exec(command)
|
67
|
+
end
|
68
|
+
Process.waitpid(pid)
|
69
|
+
end
|
70
|
+
|
71
|
+
if File.exists? local_report
|
72
|
+
say_status "publishing", report_filename
|
73
|
+
# command = "cp #{local_report} #{destination_report}"
|
74
|
+
# pid = Process.fork do
|
75
|
+
# exec(command)
|
76
|
+
# end
|
77
|
+
# Process.waitpid(pid)
|
78
|
+
FileUtils.cp local_report, destination_report
|
79
|
+
else
|
80
|
+
say_status "error", "Report file not found: #{report_filename}", :red
|
81
|
+
exit(1)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def copy_data_directory
|
86
|
+
data_dir = File.join(report_dir, DATA_ROOT, options[:local]["report_id"])
|
87
|
+
destination_dir = File.join(options[:server_root], DATA_ROOT)
|
88
|
+
|
89
|
+
existing_destination_dir = File.join(destination_dir, options[:local]["report_id"])
|
90
|
+
|
91
|
+
if File.exists? existing_destination_dir
|
92
|
+
say_status "removing", existing_destination_dir, :yellow
|
93
|
+
command = "rm -rf #{existing_destination_dir}"
|
94
|
+
pid = Process.fork do
|
95
|
+
exec(command)
|
96
|
+
end
|
97
|
+
Process.waitpid(pid)
|
98
|
+
end
|
99
|
+
|
100
|
+
if File.exists? data_dir
|
101
|
+
say_status "publishing", data_dir
|
102
|
+
# command = "cp -r #{data_dir} #{destination_dir}"
|
103
|
+
# pid = Process.fork do
|
104
|
+
# exec(command)
|
105
|
+
# end
|
106
|
+
# Process.waitpid(pid)
|
107
|
+
FileUtils.cp_r data_dir, destination_dir
|
108
|
+
else
|
109
|
+
say_status "warning", "report data directory not found #{data_dir}", :yellow
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def add_to_reports_file
|
114
|
+
in_root do
|
115
|
+
say_status "note", "modifying #{SERVER_REPORTS_FILE}"
|
116
|
+
say_status "note", " to include #{options[:local]["report_id"]}"
|
117
|
+
server_report_file = SERVER_REPORTS_FILE
|
118
|
+
if !File.exists? server_report_file
|
119
|
+
say_status "error", "Cannot find #{SERVER_REPORTS_FILE} file in server directory:", :red
|
120
|
+
end
|
121
|
+
ConfigFile.append(server_report_file, options[:local]["report_id"])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def update_git_repo
|
126
|
+
in_root do
|
127
|
+
say_status "note", "updating git repository"
|
128
|
+
Grit::Git.git_timeout = 25
|
129
|
+
repo = Grit::Repo.new(".")
|
130
|
+
# ensure we are on the server branch
|
131
|
+
repo.git.native :checkout, {}, 'server'
|
132
|
+
repo = Grit::Repo.new(".")
|
133
|
+
if repo.head.name != "server"
|
134
|
+
say_status "error", "Remote git not on server branch", :red
|
135
|
+
say_status "error", "Please git checkout server", :red
|
136
|
+
say_status "error", "Current branch: #{repo.head.name}", :red
|
137
|
+
exit(1)
|
138
|
+
end
|
139
|
+
all_files = Dir.glob("./**")
|
140
|
+
repo.add(all_files)
|
141
|
+
repo.commit_all("update with report: #{options[:local]["report_id"]}")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def publish_with_jekyll
|
146
|
+
in_root do
|
147
|
+
say_status "publishing", "updating server reports", :yellow
|
148
|
+
config_file = File.expand_path(File.join(FileUtils.getwd, Hastie.watch_config_file))
|
149
|
+
server_config_file = File.expand_path(File.join(FileUtils.getwd, Hastie.publish_config_file))
|
150
|
+
if File.exists?(server_config_file)
|
151
|
+
config_file = server_config_file
|
152
|
+
end
|
153
|
+
say_status "config", config_file, :yellow
|
154
|
+
command = "jekyll --config #{config_file}"
|
155
|
+
pid = Process.fork do
|
156
|
+
exec(command)
|
157
|
+
end
|
158
|
+
Process.waitpid(pid)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|