contributors_stats 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.travis.yml +11 -0
- data/Gemfile +5 -0
- data/LICENSE.md +14 -0
- data/README.md +43 -0
- data/Rakefile +28 -0
- data/contributors_stats.gemspec +24 -0
- data/lib/contributors_stats.rb +28 -0
- data/lib/contributors_stats/base.rb +29 -0
- data/lib/contributors_stats/calculator.rb +50 -0
- data/lib/contributors_stats/formatter.rb +57 -0
- data/lib/contributors_stats/json_helper.rb +49 -0
- data/lib/contributors_stats/reader.rb +52 -0
- data/lib/contributors_stats/version.rb +4 -0
- data/lib/example_data.rb +58 -0
- data/lib/plugins/contributors_stats/formatter/html.rb +26 -0
- data/lib/plugins/contributors_stats/reader/gh_org.rb +21 -0
- data/lib/plugins/contributors_stats/reader/gh_repo.rb +19 -0
- data/lib/plugins/contributors_stats/updater/html.rb +36 -0
- data/lib/plugins/contributors_stats/user_data/fetch.rb +16 -0
- data/lib/plugins/contributors_stats/user_data/simple.rb +23 -0
- data/test/contributors_stats/base_test.rb +36 -0
- data/test/contributors_stats/calculator_test.rb +70 -0
- data/test/contributors_stats/formatter_test.rb +77 -0
- data/test/contributors_stats/json_helper_test.rb +76 -0
- data/test/contributors_stats/reader_test.rb +59 -0
- data/test/contributors_stats_test.rb +13 -0
- data/test/fixtures-gh/orgs/railsinstaller/repos.json +269 -0
- data/test/fixtures-gh/repos/mpapis/rubygems-bundler/contributors.json +173 -0
- data/test/fixtures-gh/repos/railsinstaller/railsinstaller-nix/contributors.json +40 -0
- data/test/fixtures-gh/repos/railsinstaller/railsinstaller-windows/contributors.json +116 -0
- data/test/fixtures-gh/repos/railsinstaller/website/contributors.json +192 -0
- data/test/fixtures-gh/repos/rvm/pluginator/contributors.json +40 -0
- data/test/fixtures-gh/users/acco.json +31 -0
- data/test/fixtures-gh/users/alexch.json +31 -0
- data/test/fixtures-gh/users/biow0lf.json +31 -0
- data/test/fixtures-gh/users/drnic.json +31 -0
- data/test/fixtures-gh/users/ebertech.json +31 -0
- data/test/fixtures-gh/users/edwardchiu38.json +31 -0
- data/test/fixtures-gh/users/emachnic.json +31 -0
- data/test/fixtures-gh/users/envygeeks.json +31 -0
- data/test/fixtures-gh/users/gpxl.json +31 -0
- data/test/fixtures-gh/users/jc00ke.json +31 -0
- data/test/fixtures-gh/users/joshbuddy.json +31 -0
- data/test/fixtures-gh/users/luigidr.json +31 -0
- data/test/fixtures-gh/users/luislavena.json +31 -0
- data/test/fixtures-gh/users/metaskills.json +31 -0
- data/test/fixtures-gh/users/mpapis.json +31 -0
- data/test/fixtures-gh/users/parndt.json +31 -0
- data/test/fixtures-gh/users/pw.json +31 -0
- data/test/fixtures-gh/users/tjouan.json +31 -0
- data/test/fixtures-gh/users/veganstraightedge.json +31 -0
- data/test/fixtures-gh/users/wayneeseguin.json +31 -0
- data/test/fixtures-gh/users/whitequark.json +31 -0
- data/test/plugins/formatter/html_test.rb +28 -0
- data/test/plugins/reader/gh_org_test.rb +32 -0
- data/test/plugins/reader/gh_repo_test.rb +31 -0
- data/test/plugins/updater/html_test.rb +55 -0
- data/test/plugins/user_data/fetch_test.rb +16 -0
- data/test/plugins/user_data/simple_test.rb +18 -0
- data/test/test_helper.rb +27 -0
- metadata +229 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8c726ad0986d83954b3b2bddde135824e1421dc2
|
4
|
+
data.tar.gz: 676fca44931563548b82c5abeb09cf34ae94de8b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 83969f2f0da917ba5d1a5a0ce2c43785e8a7e90073a7b140c98493252fb97228c68017330cdd1bccd3f0d1427cfdfd1ba0bb715793c5d0123262290c2895c39a
|
7
|
+
data.tar.gz: acd9a3de698b3903ab65f6950e3c6bb930fcf1f2f6ca736cd806b0245e614d23b88503bbfe4695aad04882018b0ecab61063d97a511649095f832949f9541deb
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright (c) 2009-2011 Wayne E. Seguin
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Contributors stats
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/mpapis/contributors_stats.png?branch=master)](https://travis-ci.org/mpapis/contributors_stats)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/mpapis/contributors_stats.png)](https://codeclimate.com/github/mpapis/contributors_stats)
|
5
|
+
[![Dependency Status](https://gemnasium.com/mpapis/contributors_stats.png)](https://gemnasium.com/mpapis/contributors_stats)
|
6
|
+
|
7
|
+
Update static files with contributors statistics.
|
8
|
+
|
9
|
+
* Static content update of contributors statistics.
|
10
|
+
* Plugable:
|
11
|
+
** backends to load data
|
12
|
+
** user details calculation
|
13
|
+
** output fomratters
|
14
|
+
** target files updating
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
Contributors stats consists on two basic parts and few plugins.
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
calculator = ContributorsStats.load(<options>)
|
22
|
+
calculator.load(:<type> => '<name>')
|
23
|
+
calculator.user_data_type = :<user_data_type>
|
24
|
+
formatter = calculator.format(:<format>)
|
25
|
+
formatter.save('<file>', ...)
|
26
|
+
formatter.update('<file>', ..., options: <options>)
|
27
|
+
puts formatter.content
|
28
|
+
```
|
29
|
+
|
30
|
+
Plugins are loaded automatically, for example `calculator.user_data_type = :fetch`
|
31
|
+
will load `plugins/contributors_stats/user_data/fetch.rb` and use
|
32
|
+
`ContributorsStats::UserData::Fetch` and use it to process user details calculation.
|
33
|
+
|
34
|
+
## Examples
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
ContributorsStats.load(gh_org: 'railsisntaller').format(:markdown).save('public/contributors.md')
|
38
|
+
ContributorsStats.load(gh_repo: 'railsisntaller/website').format.update('public/index.html')
|
39
|
+
```
|
40
|
+
|
41
|
+
```shell
|
42
|
+
ruby -I lib:lib/plugins -rcontributors_stats -e "puts ContributorsStats.load(:gh_org => 'rvm', :gh_repo => ['wayneeseguin/rvm', 'wayneeseguin/rvm-capistrano'], :user_data => :fetch).format(:html).content"
|
43
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "rake/testtask"
|
2
|
+
require "yard"
|
3
|
+
require "yard/rake/yardoc_task"
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.verbose = true
|
7
|
+
t.libs.push("test")
|
8
|
+
t.pattern = "test/**/*_test.rb"
|
9
|
+
end
|
10
|
+
|
11
|
+
YARD::Rake::YardocTask.new do |t|
|
12
|
+
t.before = Proc.new do
|
13
|
+
puts "\n[YARD] Generating documentation\n\n"
|
14
|
+
end
|
15
|
+
t.files = ['lib/**/*.rb']
|
16
|
+
# --quiet / --verbose =>
|
17
|
+
t.options = ['--quiet', '--list-undoc', '--compact', '--verbose']
|
18
|
+
end
|
19
|
+
|
20
|
+
task :default => [:test, :yard]
|
21
|
+
|
22
|
+
task :example_data do
|
23
|
+
require "example_data"
|
24
|
+
example = ExampleData.new
|
25
|
+
example.parse_org( example.url_builder("orgs/railsinstaller/repos") )
|
26
|
+
example.parse_repo( example.url_builder("repos/rvm/pluginator/contributors") )
|
27
|
+
example.parse_repo( example.url_builder("repos/mpapis/rubygems-bundler/contributors") )
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path("../lib/contributors_stats/version.rb", __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "contributors_stats"
|
7
|
+
spec.version = ContributorsStats::VERSION
|
8
|
+
spec.license = 'Apache'
|
9
|
+
spec.author = "Michal Papis"
|
10
|
+
spec.email = "mpapis@gmail.com"
|
11
|
+
spec.homepage = "https://github.com/mpapis/contributors_stats"
|
12
|
+
spec.summary = %q{Calculate statics for multiple project contributoions.}
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split("\n")
|
15
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
|
17
|
+
spec.required_ruby_version = ">= 2.0.0"
|
18
|
+
|
19
|
+
spec.add_dependency "pluginator"
|
20
|
+
|
21
|
+
%w{rake simplecov coveralls yard redcarpet}.each do |name|
|
22
|
+
spec.add_development_dependency(name)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#/usr/bin/env ruby
|
2
|
+
|
3
|
+
##
|
4
|
+
# static content update for speed and avoiding GH limits
|
5
|
+
# read GitHub contributions, transform to urls and update files
|
6
|
+
# all public methods return self for easy chaining
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# ContributorsStats.load(org: 'railsisntaller').format.update('public/contributors.html')
|
11
|
+
# contributors = ContributorsStats.load(repo: 'railsisntaller/website')
|
12
|
+
# contributors.format(:html).update('public/index.html', 'public/contributors.html')
|
13
|
+
# contributors.format(:markdown).save('public/contriutors.md')
|
14
|
+
#
|
15
|
+
|
16
|
+
require 'pluginator'
|
17
|
+
require 'contributors_stats/calculator'
|
18
|
+
|
19
|
+
# Calculate contribution statistics for projects,
|
20
|
+
# by default supports github organizations and repositories,
|
21
|
+
# but is easily extendible with plugins.
|
22
|
+
module ContributorsStats
|
23
|
+
# Initialize ContributorsStats
|
24
|
+
# @see ContributorsStats::Calculator.new
|
25
|
+
def self.load(options = {})
|
26
|
+
ContributorsStats::Calculator.new(options)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ContributorsStats
|
2
|
+
|
3
|
+
# Basis for ContributorsStats, includes logging and plugins support
|
4
|
+
class Base
|
5
|
+
attr_accessor :logger, :options
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@logger = $stdout
|
9
|
+
@logger = options.delete(:logger) if options[:logger]
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def filter_options(type)
|
16
|
+
@options.select do |key, value|
|
17
|
+
plugins.class_exist?(type, key)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def plugins
|
22
|
+
@plugins ||= Pluginator.find("contributors_stats", extends: %i{first_class class_exist})
|
23
|
+
end
|
24
|
+
|
25
|
+
def log(text)
|
26
|
+
logger.respond_to?(:info) ? logger.info(text) : logger.puts(text)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'contributors_stats/reader'
|
2
|
+
require 'contributors_stats/formatter'
|
3
|
+
|
4
|
+
module ContributorsStats
|
5
|
+
|
6
|
+
# Placeholder for user details resolution plugins
|
7
|
+
module UserData
|
8
|
+
end
|
9
|
+
|
10
|
+
# Calculates statistics gathered from multiple sources
|
11
|
+
class Calculator < Reader
|
12
|
+
attr_accessor :user_data_type
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
@user_data_type = options.delete(:user_data) if options[:user_data]
|
16
|
+
super(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# transform calculated data into asked format
|
20
|
+
# @param type [String] name of plugin to use for formatting
|
21
|
+
# @param options [Hash] list of options for the plugin to use
|
22
|
+
# @return [ContributorsStats::Formatter]
|
23
|
+
def format(type = :html, options = {})
|
24
|
+
ContributorsStats::Formatter.new(calculated_data, type, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# group data, calculate contributions, sort by contributions
|
30
|
+
def calculated_data
|
31
|
+
@data ||= @raw_data.group_by { |contributor|
|
32
|
+
contributor['login']
|
33
|
+
}.map {|login, data|
|
34
|
+
log "user: #{login}"
|
35
|
+
[login, user_data(login, data)]
|
36
|
+
}.sort_by{|login, data|
|
37
|
+
[1000000/data['contributions'], login]
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def contributions(data)
|
42
|
+
data.map{|repo| repo['contributions'].to_i}.inject(&:+)
|
43
|
+
end
|
44
|
+
|
45
|
+
def user_data(login, data)
|
46
|
+
@user_data_plugin ||= plugins.first_class!("user_data", user_data_type || :simple)
|
47
|
+
@user_data_plugin.load(login, data.first, contributions(data))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module ContributorsStats
|
2
|
+
|
3
|
+
# Placeholder for updater plugins
|
4
|
+
module Updater
|
5
|
+
end
|
6
|
+
|
7
|
+
# Takes care of formatting data and saving it
|
8
|
+
class Formatter
|
9
|
+
attr_reader :content
|
10
|
+
|
11
|
+
def initialize(data, type = :html, options = {})
|
12
|
+
format(data, type, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
# overwrite target with the formatted content
|
16
|
+
# @param targets [Array] list of files to overwrite
|
17
|
+
def save(*targets)
|
18
|
+
targets.flatten.each do |file|
|
19
|
+
File.open(file, 'w') { |f| f.write(content * "\n") }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# update target with the formatted content
|
24
|
+
# @param targets [Array] list of files to update
|
25
|
+
# @param options [Hash] options are passed to updater plugin, check
|
26
|
+
def update(*targets, options: {})
|
27
|
+
targets.flatten.each do |file|
|
28
|
+
plugin = plugins.first_ask!("updater", :handles?, file)
|
29
|
+
update_file(file) do |file_content|
|
30
|
+
plugin.update(file_content, content, options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def plugins
|
38
|
+
@plugins ||= Pluginator.find("contributors_stats", extends: %i{first_ask first_class})
|
39
|
+
end
|
40
|
+
|
41
|
+
def format(data, type = :html, options = {})
|
42
|
+
formatter_plugin = plugins.first_class!("formatter", type).new(options)
|
43
|
+
@content = data.map do |login, user_data|
|
44
|
+
formatter_plugin.format(login, user_data)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Allow editing file text in a block
|
49
|
+
# @example
|
50
|
+
# update_file('some.txt'){|text| text.gsub(/bla/,'ble')}
|
51
|
+
def update_file(file)
|
52
|
+
text = File.read(file)
|
53
|
+
text = yield text
|
54
|
+
File.open(file, 'w') { |f| f.write(text) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module ContributorsStats
|
5
|
+
|
6
|
+
# Support code for loading json urls/files
|
7
|
+
module JsonHelper
|
8
|
+
|
9
|
+
# Build full path to resource to use
|
10
|
+
def url_builder(path)
|
11
|
+
"#{self.path_prefix}#{path}#{self.path_suffix}"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Load json from url, fallback to prefix
|
15
|
+
def load_json(url)
|
16
|
+
open(url){ |json| JSON.load(json) }
|
17
|
+
rescue Exception => e
|
18
|
+
if File.exist?("#{self.path_prefix}#{url}")
|
19
|
+
open("#{self.path_prefix}#{url}"){ |json| JSON.load(json) }
|
20
|
+
elsif File.exist?("#{self.path_prefix}#{url}#{self.path_suffix}")
|
21
|
+
open("#{self.path_prefix}#{url}#{self.path_suffix}"){ |json| JSON.load(json) }
|
22
|
+
else
|
23
|
+
raise e
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# get prefix, sets the default if empty, makes sure it's ending with '/'
|
28
|
+
def path_prefix
|
29
|
+
@path_prefix ||= "https://api.github.com"
|
30
|
+
@path_prefix+="/" if @path_prefix != "" && @path_prefix[-1] != "/"
|
31
|
+
@path_prefix
|
32
|
+
end
|
33
|
+
|
34
|
+
# get suffix, sets the default if empty, makes sure it's starts with '.'
|
35
|
+
def path_suffix
|
36
|
+
@path_suffix ||= ""
|
37
|
+
@path_suffix = ".#{@path_suffix}" if @path_suffix != "" && @path_suffix[0] != "."
|
38
|
+
@path_suffix
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def configure_path(prefix, suffix)
|
44
|
+
@path_prefix = prefix
|
45
|
+
@path_suffix = suffix
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'contributors_stats/base'
|
2
|
+
require 'contributors_stats/json_helper'
|
3
|
+
|
4
|
+
module ContributorsStats
|
5
|
+
|
6
|
+
# Base for reading ContributorsStats data
|
7
|
+
class Reader < Base
|
8
|
+
include ContributorsStats::JsonHelper
|
9
|
+
|
10
|
+
attr_reader :data, :raw_data
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
configure_path(*options.delete(:configure_path)) if options[:configure_path]
|
14
|
+
super(options)
|
15
|
+
@raw_data = []
|
16
|
+
@data = nil
|
17
|
+
parse_readers(filter_options("reader"))
|
18
|
+
end
|
19
|
+
|
20
|
+
# load data using given plugin
|
21
|
+
# @param type [String] plugin to use
|
22
|
+
# @param name [String] name to pass to the plugin
|
23
|
+
def load(type, name)
|
24
|
+
reader_plugin(type).load(name) do |data, name|
|
25
|
+
log "repository: #{name}"
|
26
|
+
@raw_data += data
|
27
|
+
end
|
28
|
+
@data = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def reader_plugin(type)
|
34
|
+
plugin = plugins.first_class!("reader", type)
|
35
|
+
if plugin.kind_of?(ContributorsStats::JsonHelper)
|
36
|
+
plugin.send(:configure_path, path_prefix, path_suffix)
|
37
|
+
end
|
38
|
+
plugin
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_readers(options = {})
|
42
|
+
options.each do |type, name|
|
43
|
+
if name.kind_of?(Array)
|
44
|
+
name.each{|n| load(type,n)}
|
45
|
+
else
|
46
|
+
load(type, name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
data/lib/example_data.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'contributors_stats/json_helper'
|
2
|
+
|
3
|
+
# Dump some test data from github, rather one time, but who knows ;)
|
4
|
+
class ExampleData
|
5
|
+
include ContributorsStats::JsonHelper
|
6
|
+
|
7
|
+
# setup proper context for dumping data
|
8
|
+
def initialize(target_path = "../../test/fixtures-gh")
|
9
|
+
target_path = File.expand_path( target_path, __FILE__ ) unless Dir.exist?(target_path)
|
10
|
+
Dir.chdir(target_path)
|
11
|
+
`rm -rf *` # clean
|
12
|
+
end
|
13
|
+
|
14
|
+
# parse organization data from given url, parses also repositories
|
15
|
+
# @see .parse_repo
|
16
|
+
def parse_org(org_url)
|
17
|
+
puts "reading: #{org_url}"
|
18
|
+
org_data = load_json(org_url)
|
19
|
+
write(org_url, org_data)
|
20
|
+
org_data.each do |repo|
|
21
|
+
parse_repo(repo['contributors_url'], " ")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# parse repository data from given url, parses also users
|
26
|
+
# @see .parse_repo
|
27
|
+
def parse_repo(contributors_url, str_prefix="")
|
28
|
+
puts "#{str_prefix}reading: #{contributors_url}"
|
29
|
+
contributors_data = load_json(contributors_url)
|
30
|
+
write(contributors_url, contributors_data)
|
31
|
+
contributors_data.each do |contributor|
|
32
|
+
parse_user(contributor['url'], str_prefix+" ")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# parse user data from given url
|
37
|
+
def parse_user(user_url, str_prefix="")
|
38
|
+
puts "#{str_prefix}reading: #{user_url}"
|
39
|
+
user_data = load_json(user_url)
|
40
|
+
write(user_url, user_data)
|
41
|
+
end
|
42
|
+
|
43
|
+
# saves content to path corresponding to the given file url
|
44
|
+
def write(file, content)
|
45
|
+
file = remove_prefix(file)
|
46
|
+
return if File.exist?(file)
|
47
|
+
`mkdir -p #{File.dirname(file)}`
|
48
|
+
File.open(file, "w+") { |f|
|
49
|
+
f.write(remove_prefix(JSON.pretty_generate(content)))
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
# remove prefix from all urls in the given content
|
54
|
+
def remove_prefix(conten)
|
55
|
+
conten.gsub(/#{path_prefix}([^"]*)/, "\\1.json")
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|