gisture 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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