gisture 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 03e7d1d1abd295d696f903a9017625ef7f4523f0
4
- data.tar.gz: 4e7d8c8ddb6570ff3b8c1f366f791701e0640bdc
3
+ metadata.gz: 3bdea019b5a0fbb8b6ae761da872e410309450ed
4
+ data.tar.gz: a2e957a0da22cfda85e7b10376fe0895a90ca1c2
5
5
  SHA512:
6
- metadata.gz: f1e213b93a08f3c3a552e28e8fb9900a7f504c5bdd1de7265901a8480dd8d869a85f2f6132bcf42cdd1ec88a85013c69d50da5f0fa91bc311a7f30e579990dc5
7
- data.tar.gz: 8f9244489caba893887c4ecac9352b881e75f1b241c9a7c858cf3d41e8ad0a439dbf926d2dc3eaf7d8352e111b1148c7ae22549e1c2bf443432d796524cba5ea
6
+ metadata.gz: 69d3b4ec1d28e33326d7b79452bc90b9aea5011f237f7154e89209ac54be2d565284c9076424b34cf4907249988cdcf8fb900eb25e444a7feb7d48c37f52c2e4
7
+ data.tar.gz: 1038a6294c4eeffb1dfc24c6f2ba3528f2b974050a39681fda8d4654675f5b32c9bc103a40715ca0fd19586883ab1d34d6668724598c5e32e6ddb14fa5ac0b99
@@ -0,0 +1,7 @@
1
+ module Gisture
2
+ class OwnerBlacklisted < StandardError
3
+ def initialize(owner)
4
+ super("Gists from '#{owner}' have not been whitelisted for execution. Add them to the 'owners' configuration option.")
5
+ end
6
+ end
7
+ end
data/lib/gisture/file.rb CHANGED
@@ -2,7 +2,13 @@ require 'tempfile'
2
2
 
3
3
  module Gisture
4
4
  class File
5
- attr_reader :file, :basename
5
+ attr_reader :file, :basename, :strategy
6
+
7
+ STRATEGIES = [:eval, :load, :require]
8
+
9
+ def run!(&block)
10
+ send "#{strategy}!".to_sym, &block
11
+ end
6
12
 
7
13
  def require!(&block)
8
14
  required = require tempfile.path
@@ -17,17 +23,22 @@ module Gisture
17
23
  end
18
24
 
19
25
  def eval!(&block)
20
- clean_room = Evaluator.new(content)
26
+ clean_room = Evaluator.new(file.content)
21
27
  clean_room.instance_eval &block if block_given?
22
28
  clean_room
23
29
  end
24
30
 
31
+ def strategy=(strat)
32
+ raise ArgumentError, "Invalid strategy '#{strat}'. Must be one of #{STRATEGIES.join(', ')}" unless STRATEGIES.include?(strat.to_sym)
33
+ @strategy = strat.to_sym
34
+ end
35
+
25
36
  def tempfile
26
37
  @tempfile ||= begin
27
- file = Tempfile.new([basename, filename, ::File.extname(filename)].compact, Gisture.configuration.tmpdir)
28
- file.write(content)
29
- file.close
30
- file
38
+ tmpfile = Tempfile.new([basename, file.filename, ::File.extname(file.filename)].compact, Gisture.configuration.tmpdir)
39
+ tmpfile.write(file.content)
40
+ tmpfile.close
41
+ tmpfile
31
42
  end
32
43
  end
33
44
 
@@ -47,9 +58,10 @@ module Gisture
47
58
 
48
59
  protected
49
60
 
50
- def initialize(file, basename=nil)
61
+ def initialize(file, basename: nil, strategy: nil)
51
62
  @file = file
52
63
  @basename = basename
64
+ self.strategy = strategy || Gisture.configuration.strategy
53
65
  end
54
66
  end
55
67
  end
data/lib/gisture/gist.rb CHANGED
@@ -36,22 +36,23 @@ module Gisture
36
36
  def gist
37
37
  @gist ||= begin
38
38
  if @version.nil?
39
- github.gists.get(gist_id)
39
+ g = github.gists.get(gist_id)
40
40
  else
41
- github.gists.version(gist_id, @version)
41
+ g = github.gists.version(gist_id, @version)
42
42
  end
43
+ raise OwnerBlacklisted.new(g.owner.login) unless Gisture.configuration.whitelisted?(g.owner.login)
44
+ g
43
45
  end
44
46
  end
45
47
 
46
48
  def file
47
49
  return @file unless @file.nil?
48
50
 
49
- if gist.files.count > 1
50
- raise ArgumentError, "You must specify a filename if your gist contains more than one file" if filename.nil?
51
- @file = Gisture::File.new(gist.files[filename], gist_id)
51
+ if gist.files.count > 1 && !filename.nil?
52
+ @file = Gisture::File.new(gist.files[filename], basename: gist_id, strategy: strategy)
52
53
  raise ArgumentError, "The filename '#{filename}' was not found in the list of files for the gist '#{gist_id}'" if @file.nil?
53
54
  else
54
- @file = Gisture::File.new(gist.files.first[1], gist_id)
55
+ @file = Gisture::File.new(gist.files.first[1], basename: gist_id, strategy: strategy)
55
56
  end
56
57
 
57
58
  @file
@@ -0,0 +1,62 @@
1
+ module Gisture
2
+ class Repo
3
+ attr_reader :owner, :project
4
+ REPO_URL_REGEX = /\A((http[s]?:\/\/)?github\.com\/)?([a-z0-9_\-\.]*)\/([a-z0-9_\-\.]*)\/?\Z/i
5
+ FILE_URL_REGEX = /\A((http[s]?:\/\/)?github\.com\/)?(([a-z0-9_\-\.]*)\/([a-z0-9_\-\.]*))(\/[a-z0-9_\-\.\/]+)\Z/i
6
+
7
+ class << self
8
+ def file(path, strategy: nil)
9
+ repo, file = parse_file_url(path)
10
+ new(repo).file(file, strategy: strategy)
11
+ end
12
+
13
+ def run!(path, strategy: nil, &block)
14
+ file(path, strategy: strategy).run!(&block)
15
+ end
16
+
17
+ def parse_repo_url(repo_url)
18
+ matched = repo_url.match(REPO_URL_REGEX)
19
+ raise ArgumentError, "Invalid argument: '#{repo_url}' is not a valid repo URL." if matched.nil?
20
+ [matched[3], matched[4]]
21
+ end
22
+
23
+ def parse_file_url(file_url)
24
+ matched = file_url.match(FILE_URL_REGEX)
25
+ raise ArgumentError, "Invalid argument: '#{file_url}' is not a valid file path." if matched.nil?
26
+ [matched[3], matched[6]]
27
+ end
28
+ end
29
+
30
+ def github
31
+ @github ||= begin
32
+ Github.new(github_config)
33
+ end
34
+ end
35
+
36
+ def repo
37
+ @repo ||= github.repos.get user: owner, repo: project
38
+ end
39
+
40
+ def file(path, strategy: nil)
41
+ file = github.repos.contents.get(user: owner, repo: project, path: path).body
42
+ file['filename'] = ::File.basename(file['path'])
43
+ file['content'] = Base64.decode64(file['content'])
44
+ Gisture::File.new(file, basename: "#{owner}-#{project}", strategy: strategy)
45
+ end
46
+
47
+ def run!(path, strategy: nil, &block)
48
+ file(path, strategy: strategy).run!(&block)
49
+ end
50
+
51
+ protected
52
+
53
+ def initialize(repo)
54
+ @owner, @project = self.class.parse_repo_url(repo)
55
+ raise OwnerBlacklisted.new(owner) unless Gisture.configuration.whitelisted?(owner)
56
+ end
57
+
58
+ def github_config
59
+ github_config = Hash[Gisture::GITHUB_CONFIG_OPTS.map { |key| [key, Gisture.configuration.send(key)] }]
60
+ end
61
+ end
62
+ end
@@ -1,3 +1,3 @@
1
1
  module Gisture
2
- VERSION = '0.0.6'
2
+ VERSION = '0.0.7'
3
3
  end
data/lib/gisture.rb CHANGED
@@ -2,9 +2,11 @@ require 'canfig'
2
2
  require 'github_api'
3
3
  require 'gisture/github_api/client/gists'
4
4
  require 'gisture/version'
5
+ require 'gisture/errors'
5
6
  require 'gisture/evaluator'
6
7
  require 'gisture/file'
7
8
  require 'gisture/gist'
9
+ require 'gisture/repo'
8
10
  require 'gisture/railtie' if defined?(Rails)
9
11
 
10
12
  module Gisture
@@ -23,13 +25,30 @@ module Gisture
23
25
 
24
26
  config.strategy = :eval # default execution strategy
25
27
  config.tmpdir = Dir.tmpdir # location to store gist tempfiles
28
+ config.owners = nil # only allow gists/repos/etc. from whitelisted owners (str/sym/arr)
29
+
30
+ def whitelisted?(owner)
31
+ owners.nil? || owners.empty? || [owners].flatten.map(&:to_s).include?(owner)
32
+ end
26
33
  end
27
34
 
28
35
  def self.new(gist, strategy: nil, filename: nil, version: nil)
29
36
  Gisture::Gist.new(gist, strategy: strategy, filename: filename, version: version)
30
37
  end
31
38
 
39
+ def self.gist(gist, strategy: nil, filename: nil, version: nil)
40
+ new(gist, strategy, filename, version)
41
+ end
42
+
32
43
  def self.run(gist, strategy: nil, filename: nil, version: nil, &block)
33
44
  new(gist, strategy, filename, version).run!(&block)
34
45
  end
46
+
47
+ def self.repo(repo)
48
+ Gisture::Repo.new(repo)
49
+ end
50
+
51
+ def self.file(path, strategy: nil)
52
+ Gisture::Repo.file(path, strategy: strategy)
53
+ end
35
54
  end
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe Gisture::Gist do
4
- subject { Gisture::File.new(Gisture::Gist.new(TEST_GIST_ID).gist.files.first[1], TEST_GIST_ID) }
3
+ RSpec.describe Gisture::File do
4
+ subject { Gisture::File.new(Gisture::Gist.new(TEST_GIST_ID).gist.files.first[1], basename: TEST_GIST_ID) }
5
5
 
6
6
  it "delegates missing methods to the file hash" do
7
7
  expect(subject.respond_to?(:content)).to be_true
@@ -63,6 +63,24 @@ RSpec.describe Gisture::Gist do
63
63
  end
64
64
  end
65
65
 
66
+ context "when not passing a strategy" do
67
+ it "uses the default configured strategy" do
68
+ begin
69
+ Gisture.configure do |config|
70
+ config.strategy = :load
71
+ end
72
+
73
+ expect(Gisture::Gist.new(TEST_GIST_ID).strategy).to eql(:load)
74
+ rescue => e
75
+ raise e
76
+ ensure
77
+ Gisture.configure do |config|
78
+ config.strategy = :eval
79
+ end
80
+ end
81
+ end
82
+ end
83
+
66
84
  describe "#github" do
67
85
  subject { Gisture::Gist.new(TEST_GIST_ID) }
68
86
 
@@ -77,6 +95,44 @@ RSpec.describe Gisture::Gist do
77
95
  it "is the gist that was requested" do
78
96
  expect(subject.gist.id).to eql(TEST_GIST_ID)
79
97
  end
98
+
99
+ context "when whitelisted owners have been configured" do
100
+ context "and the gist owner is whitelisted" do
101
+ it "does not raise an error" do
102
+ begin
103
+ Gisture.configure do |config|
104
+ config.owners = [:markrebec]
105
+ end
106
+
107
+ expect { Gisture::Gist.new(TEST_GIST_ID).gist }.to_not raise_exception
108
+ rescue => e
109
+ raise e
110
+ ensure
111
+ Gisture.configure do |config|
112
+ config.owners = nil
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ context "and the gist owner is not whitelisted" do
119
+ it "raises a OwnerBlacklisted error" do
120
+ begin
121
+ Gisture.configure do |config|
122
+ config.owners = [:tester]
123
+ end
124
+
125
+ expect { Gisture::Gist.new(TEST_GIST_ID).gist }.to raise_exception(Gisture::OwnerBlacklisted)
126
+ rescue => e
127
+ raise e
128
+ ensure
129
+ Gisture.configure do |config|
130
+ config.owners = nil
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
80
136
  end
81
137
 
82
138
  describe "#file" do
@@ -102,8 +158,8 @@ RSpec.describe Gisture::Gist do
102
158
  context "and no filename is present" do
103
159
  subject { Gisture::Gist.new(MULTI_FILE_TEST_GIST_ID) }
104
160
 
105
- it "raises an ArgumentError" do
106
- expect { subject.file }.to raise_exception(ArgumentError)
161
+ it "uses the first file in the gist" do
162
+ expect(subject.file.filename).to eql(MULTI_FILE_TEST_GIST_FILENAMES.first)
107
163
  end
108
164
  end
109
165
  end
@@ -0,0 +1,94 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Gisture::Repo do
4
+ context "when passed a valid repo slug" do
5
+ subject { Gisture::Repo.new('markrebec/gisture') }
6
+
7
+ it "sets the owner and project correctly" do
8
+ end
9
+ end
10
+
11
+ context "when passed a valid repo URL" do
12
+ subject { Gisture::Repo.new('https://github.com/markrebec/gisture') }
13
+
14
+ it "sets the owner and project correctly" do
15
+ end
16
+ end
17
+
18
+ context "when passed an invalid repo" do
19
+ it "raises an ArgumentError" do
20
+ expect { Gisture::Repo.new('foo') }.to raise_exception(ArgumentError)
21
+ expect { Gisture::Repo.new('markrebec/foo/bar') }.to raise_exception(ArgumentError)
22
+ expect { Gisture::Repo.new('http://github.com') }.to raise_exception(ArgumentError)
23
+ end
24
+ end
25
+
26
+ context "when whitelisted owners have been configured" do
27
+ context "and the repo owner is whitelisted" do
28
+ it "does not raise an error" do
29
+ begin
30
+ Gisture.configure do |config|
31
+ config.owners = [:markrebec]
32
+ end
33
+
34
+ expect { Gisture::Repo.new('markrebec/gisture') }.to_not raise_exception
35
+ rescue => e
36
+ raise e
37
+ ensure
38
+ Gisture.configure do |config|
39
+ config.owners = nil
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ context "and the gist owner is not whitelisted" do
46
+ it "raises a OwnerBlacklisted error" do
47
+ begin
48
+ Gisture.configure do |config|
49
+ config.owners = [:tester]
50
+ end
51
+
52
+ expect { Gisture::Repo.new('markrebec/gisture') }.to raise_exception(Gisture::OwnerBlacklisted)
53
+ rescue => e
54
+ raise e
55
+ ensure
56
+ Gisture.configure do |config|
57
+ config.owners = nil
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#github" do
65
+ subject { Gisture::Repo.new('markrebec/gisture') }
66
+
67
+ it "is a github_api client object" do
68
+ expect(subject.github).to be_a(Github::Client)
69
+ end
70
+ end
71
+
72
+ # TODO stub out Github::Client::Repos
73
+ describe '#repo' do
74
+ context "when the repo doesn't exist" do
75
+ end
76
+ end
77
+
78
+ # TODO stub out Github::Client::Repos::Contents
79
+ describe '#file' do
80
+ context "when the repo doesn't exist" do
81
+ end
82
+
83
+ context "when the file doesn't exist" do
84
+ end
85
+ end
86
+
87
+ describe '.file' do
88
+ context "when the repo doesn't exist" do
89
+ end
90
+
91
+ context "when the file doesn't exist" do
92
+ end
93
+ end
94
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gisture
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Rebec
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-09 00:00:00.000000000 Z
11
+ date: 2015-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: canfig
@@ -74,11 +74,13 @@ extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - lib/gisture.rb
77
+ - lib/gisture/errors.rb
77
78
  - lib/gisture/evaluator.rb
78
79
  - lib/gisture/file.rb
79
80
  - lib/gisture/gist.rb
80
81
  - lib/gisture/github_api/client/gists.rb
81
82
  - lib/gisture/railtie.rb
83
+ - lib/gisture/repo.rb
82
84
  - lib/gisture/version.rb
83
85
  - lib/tasks/gisture.rake
84
86
  - spec/gists/called_class.rb
@@ -89,6 +91,7 @@ files:
89
91
  - spec/gisture/evaluator_spec.rb
90
92
  - spec/gisture/file_spec.rb
91
93
  - spec/gisture/gist_spec.rb
94
+ - spec/gisture/repo_spec.rb
92
95
  - spec/gisture_spec.rb
93
96
  - spec/spec_helper.rb
94
97
  - spec/support/gists.rb
@@ -125,6 +128,7 @@ test_files:
125
128
  - spec/gisture/evaluator_spec.rb
126
129
  - spec/gisture/file_spec.rb
127
130
  - spec/gisture/gist_spec.rb
131
+ - spec/gisture/repo_spec.rb
128
132
  - spec/gisture_spec.rb
129
133
  - spec/spec_helper.rb
130
134
  - spec/support/gists.rb