maguro 0.0.1
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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +102 -0
- data/LICENSE.txt +22 -0
- data/README.md +77 -0
- data/Rakefile +2 -0
- data/bin/maguro +18 -0
- data/lib/maguro.rb +9 -0
- data/lib/maguro/app_generator.rb +113 -0
- data/lib/maguro/bitbucket.rb +185 -0
- data/lib/maguro/cli.rb +10 -0
- data/lib/maguro/features.rb +389 -0
- data/lib/maguro/gemfile.rb +14 -0
- data/lib/maguro/github.rb +23 -0
- data/lib/maguro/heroku.rb +45 -0
- data/lib/maguro/keychain.rb +53 -0
- data/lib/maguro/version.rb +7 -0
- data/maguro.gemspec +27 -0
- data/spec/maguro/app_generator_spec.rb +46 -0
- data/spec/maguro/bitbucket_spec.rb +46 -0
- data/spec/spec_helper.rb +89 -0
- data/templates/home_controller.rb +4 -0
- data/templates/home_index.html.erb +2 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ddeb4fe9eb84bdeb224b00749cd640703f104dd4
|
4
|
+
data.tar.gz: 5912a8b3ad6fa2f659dc7eb0ed4c380914f677d2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 007ce4f75281f70fe5c536cb3513259243a2119edd518ed665614b65312530fbe05c6ef7671ef3d498de67545056a171f3c9a0eb288acdea1f4faaefe433fd81
|
7
|
+
data.tar.gz: e148cb85c274c7f13d0f42c0839ab88c71d2648da655dc297d5ff1f508e9f249545faab453ef438aca1eca05afd97951cb0dd9199f83e9679af110d1de1fcee0
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
magurogemset
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.0
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
maguro (0.0.1)
|
5
|
+
rails (= 4.1.8)
|
6
|
+
thor (~> 0.19)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (4.1.8)
|
12
|
+
actionpack (= 4.1.8)
|
13
|
+
actionview (= 4.1.8)
|
14
|
+
mail (~> 2.5, >= 2.5.4)
|
15
|
+
actionpack (4.1.8)
|
16
|
+
actionview (= 4.1.8)
|
17
|
+
activesupport (= 4.1.8)
|
18
|
+
rack (~> 1.5.2)
|
19
|
+
rack-test (~> 0.6.2)
|
20
|
+
actionview (4.1.8)
|
21
|
+
activesupport (= 4.1.8)
|
22
|
+
builder (~> 3.1)
|
23
|
+
erubis (~> 2.7.0)
|
24
|
+
activemodel (4.1.8)
|
25
|
+
activesupport (= 4.1.8)
|
26
|
+
builder (~> 3.1)
|
27
|
+
activerecord (4.1.8)
|
28
|
+
activemodel (= 4.1.8)
|
29
|
+
activesupport (= 4.1.8)
|
30
|
+
arel (~> 5.0.0)
|
31
|
+
activesupport (4.1.8)
|
32
|
+
i18n (~> 0.6, >= 0.6.9)
|
33
|
+
json (~> 1.7, >= 1.7.7)
|
34
|
+
minitest (~> 5.1)
|
35
|
+
thread_safe (~> 0.1)
|
36
|
+
tzinfo (~> 1.1)
|
37
|
+
arel (5.0.1.20140414130214)
|
38
|
+
builder (3.2.2)
|
39
|
+
diff-lcs (1.2.5)
|
40
|
+
erubis (2.7.0)
|
41
|
+
hike (1.2.3)
|
42
|
+
i18n (0.6.11)
|
43
|
+
json (1.8.1)
|
44
|
+
mail (2.6.3)
|
45
|
+
mime-types (>= 1.16, < 3)
|
46
|
+
mime-types (2.4.3)
|
47
|
+
minitest (5.4.3)
|
48
|
+
multi_json (1.10.1)
|
49
|
+
rack (1.5.2)
|
50
|
+
rack-test (0.6.2)
|
51
|
+
rack (>= 1.0)
|
52
|
+
rails (4.1.8)
|
53
|
+
actionmailer (= 4.1.8)
|
54
|
+
actionpack (= 4.1.8)
|
55
|
+
actionview (= 4.1.8)
|
56
|
+
activemodel (= 4.1.8)
|
57
|
+
activerecord (= 4.1.8)
|
58
|
+
activesupport (= 4.1.8)
|
59
|
+
bundler (>= 1.3.0, < 2.0)
|
60
|
+
railties (= 4.1.8)
|
61
|
+
sprockets-rails (~> 2.0)
|
62
|
+
railties (4.1.8)
|
63
|
+
actionpack (= 4.1.8)
|
64
|
+
activesupport (= 4.1.8)
|
65
|
+
rake (>= 0.8.7)
|
66
|
+
thor (>= 0.18.1, < 2.0)
|
67
|
+
rake (10.3.2)
|
68
|
+
rspec (3.1.0)
|
69
|
+
rspec-core (~> 3.1.0)
|
70
|
+
rspec-expectations (~> 3.1.0)
|
71
|
+
rspec-mocks (~> 3.1.0)
|
72
|
+
rspec-core (3.1.7)
|
73
|
+
rspec-support (~> 3.1.0)
|
74
|
+
rspec-expectations (3.1.2)
|
75
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
76
|
+
rspec-support (~> 3.1.0)
|
77
|
+
rspec-mocks (3.1.3)
|
78
|
+
rspec-support (~> 3.1.0)
|
79
|
+
rspec-support (3.1.2)
|
80
|
+
sprockets (2.11.3)
|
81
|
+
hike (~> 1.2)
|
82
|
+
multi_json (~> 1.0)
|
83
|
+
rack (~> 1.0)
|
84
|
+
tilt (~> 1.1, != 1.3.0)
|
85
|
+
sprockets-rails (2.2.1)
|
86
|
+
actionpack (>= 3.0)
|
87
|
+
activesupport (>= 3.0)
|
88
|
+
sprockets (>= 2.8, < 4.0)
|
89
|
+
thor (0.19.1)
|
90
|
+
thread_safe (0.3.4)
|
91
|
+
tilt (1.4.1)
|
92
|
+
tzinfo (1.2.2)
|
93
|
+
thread_safe (~> 0.1)
|
94
|
+
|
95
|
+
PLATFORMS
|
96
|
+
ruby
|
97
|
+
|
98
|
+
DEPENDENCIES
|
99
|
+
bundler (~> 1.6)
|
100
|
+
maguro!
|
101
|
+
rake
|
102
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Haji Furukawa
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Maguro
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
Maguro is the base Rails application used at [Bottega8](http://www.bottega8.com/).
|
6
|
+
|
7
|
+
It's goal is to do all the boring configuration of setting up a new project for you automatically,
|
8
|
+
so you can get to the fun development part in seconds instead of hours.
|
9
|
+
|
10
|
+
## What does the template do?
|
11
|
+
|
12
|
+
Maguro will create a basic Rails project that is optimized for Bottega8's workflow by:
|
13
|
+
|
14
|
+
1. Saving RVM configuration files
|
15
|
+
1. Creating a basic README.md
|
16
|
+
1. Setting up local git repository, gitinit file, and development branch
|
17
|
+
1. Generating app_environment_variables.rb for custom environment variables
|
18
|
+
1. Removing Turbolinks
|
19
|
+
1. Including RSpec, capybara, database_cleaner, factory_girl, and other gems for testing
|
20
|
+
1. Using PostgreSQL as the database and generating database.yml
|
21
|
+
|
22
|
+
Optionally, Maguro can also
|
23
|
+
|
24
|
+
1. Create a Heroku application for staging and production environments
|
25
|
+
1. Create a Git repository on Github.com, and pushing the newly-created Rails project to it
|
26
|
+
1. Create a Git repository on BitBucket.org, and pushing the newly-created Rails project to it
|
27
|
+
1. Securely store BitBucket.org credentials in the OS X keychain for convenience
|
28
|
+
1. Create a local postgres database for the project
|
29
|
+
|
30
|
+
## Gem Prerequisites
|
31
|
+
|
32
|
+
Before running Maguro:
|
33
|
+
|
34
|
+
1. Install [PostgreSQL for OS X](http://www.postgresql.org/download/macosx/)
|
35
|
+
1. Install Ruby. We recommend using the [Ruby Version Manager](http://rvm.io/rvm/install)
|
36
|
+
|
37
|
+
|
38
|
+
Optional:
|
39
|
+
|
40
|
+
1. [Heroku toolbelt](https://toolbelt.heroku.com/) if you want to automatically deploy to heroku.
|
41
|
+
1. [Hub](https://github.com/github/hub) if you want to create a remote repository on github.
|
42
|
+
`brew install hub` with [homebrew](http://brew.sh/).
|
43
|
+
1. OSX Keychain if you want to save your bitbucket credentials.
|
44
|
+
|
45
|
+
## Gem Usage
|
46
|
+
|
47
|
+
Install the gem:
|
48
|
+
|
49
|
+
`gem install maguro`
|
50
|
+
|
51
|
+
Create a new app:
|
52
|
+
|
53
|
+
`maguro new $APP_NAME`
|
54
|
+
|
55
|
+
### Detailed Usage
|
56
|
+
|
57
|
+
1. Switch to directory where new project will live. E.g. `cd ~/Desktop/projects`
|
58
|
+
1. Install the maguro gem `gem install maguro`
|
59
|
+
1. Generate the new project: `maguro new $APP_NAME`
|
60
|
+
1. Open config/database.yml and replace `username` with the same username when setting up Postgres
|
61
|
+
1. Run `rake db:create db:migrate`
|
62
|
+
|
63
|
+
|
64
|
+
## Development and testing steps
|
65
|
+
|
66
|
+
To make local changes to this gem, clone this repository then:
|
67
|
+
|
68
|
+
1. Clone this repository
|
69
|
+
1. Run `bundle install` to install development dependencies
|
70
|
+
1. Develop/modify the source code
|
71
|
+
1. Run unit and integration tests with `rspec`
|
72
|
+
1. Build the gem `gem build maguro.gemspec`
|
73
|
+
1. Switch to the directory where you want to create a new project. E.g. `cd ~/Desktop/projects`
|
74
|
+
1. Install the gem `gem install ./maguro-0.0.1.gem`
|
75
|
+
1. Follow instructions in the section `Gem Usage`, i.e. `maguro new [APP_NAME]`
|
76
|
+
|
77
|
+
|
data/Rakefile
ADDED
data/bin/maguro
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
|
4
|
+
# read about this someplace on stackoverflow so that we cna run this file directly and debug
|
5
|
+
# instead of having to rebuild and run the gem.
|
6
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
7
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
8
|
+
|
9
|
+
require 'maguro'
|
10
|
+
|
11
|
+
# required to set our custom AppGenerator source_path to the Rail's AppGenerator
|
12
|
+
# so it can find all default the template files.
|
13
|
+
templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__))
|
14
|
+
Maguro::AppGenerator.source_root templates_root
|
15
|
+
Maguro::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root
|
16
|
+
|
17
|
+
#Start our custom CLI
|
18
|
+
Maguro::Cli.start(ARGV)
|
data/lib/maguro.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/rails/app/app_generator'
|
3
|
+
|
4
|
+
module Maguro
|
5
|
+
class AppGenerator < Rails::Generators::AppGenerator
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
class_option :heroku, type: :boolean, aliases: '--hh',
|
10
|
+
desc: 'Create a production and staging heroku application'
|
11
|
+
|
12
|
+
class_option :bitbucket, type: :boolean, aliases: '--bb',
|
13
|
+
desc: 'Create a bitbucket project and push to it.'
|
14
|
+
|
15
|
+
class_option :github, type: :boolean, aliases: '--gh',
|
16
|
+
desc: 'Create a github project and push to it.'
|
17
|
+
|
18
|
+
class_option :organization, type: :string, aliases: '-o',
|
19
|
+
desc: 'Pass in your organization name to be used by heroku and bitbucket'
|
20
|
+
|
21
|
+
class_option :'database-username', type: :string, aliases: '--du',
|
22
|
+
desc: 'Add a database username'
|
23
|
+
|
24
|
+
class_option :'database-password', type: :string, aliases: '--dp',
|
25
|
+
desc: 'Add a database password'
|
26
|
+
|
27
|
+
# Overriding Rails::Generators::AppGenerator#finish_template.
|
28
|
+
# Allows maguro to do stuff before the default rails generator is run.
|
29
|
+
#
|
30
|
+
def initialize(*args)
|
31
|
+
super
|
32
|
+
|
33
|
+
check_ruby_version
|
34
|
+
|
35
|
+
# Thor's option hash is frozen. Unfreeze so we can update our own variables on it.
|
36
|
+
# Risk: Don't accidentally modify options you didn't mean to!
|
37
|
+
self.options = options.dup
|
38
|
+
|
39
|
+
set_custom_options
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# Overriding Rails::Generators::AppGenerator#finish_template.
|
44
|
+
# This will run our maguro customizations after all of the default rails customizations.
|
45
|
+
def finish_template
|
46
|
+
Maguro::Features.new(builder).run_all_updates
|
47
|
+
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
def check_ruby_version
|
54
|
+
if ::RUBY_VERSION != Maguro::RUBY_VERSION
|
55
|
+
raise Thor::Error, "You are using ruby version #{::RUBY_VERSION}. Maguro requires ruby version #{Maguro::RUBY_VERSION}. (e.g. rvm use #{Maguro::RUBY_VERSION})."
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_custom_options
|
60
|
+
|
61
|
+
#skip heroku and bitbucket if --pretend is passed.
|
62
|
+
if options[:pretend]
|
63
|
+
options[:heroku] = false
|
64
|
+
options[:bitbucket] = false
|
65
|
+
options[:github] = false
|
66
|
+
else
|
67
|
+
# Prompt user if they haven't passed in a value for heroku, bitbucket options.
|
68
|
+
if options[:heroku].nil?
|
69
|
+
options[:heroku] = builder.yes?('Setup Heroku (y/n)?')
|
70
|
+
end
|
71
|
+
if options[:bitbucket].nil?
|
72
|
+
options[:bitbucket] = builder.yes?('Setup BitBucket repo (y/n)?')
|
73
|
+
end
|
74
|
+
if options[:github].nil?
|
75
|
+
options[:github] = builder.yes?('Setup Github repo (y/n)?')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
if options[:bitbucket] && options[:github]
|
80
|
+
raise Thor::Error, "Can't set up both bitbucket and github :p. (Select one)"
|
81
|
+
end
|
82
|
+
|
83
|
+
# only worry about setting organization if we are using heroku or bitbucket
|
84
|
+
if options[:heroku] || options[:bitbucket] || options[:github]
|
85
|
+
set_organization
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
KEYCHAIN_ORGANIZATION='organization'
|
91
|
+
|
92
|
+
def set_organization
|
93
|
+
saved_organization = Keychain.retrieve_account(KEYCHAIN_ORGANIZATION)
|
94
|
+
saved_organization = saved_organization[:password] if saved_organization
|
95
|
+
|
96
|
+
if options[:organization]
|
97
|
+
org_output = saved_organization ? saved_organization : "<none>"
|
98
|
+
|
99
|
+
if yes?("Save organization '#{options[:organization]}' as default (y/n)? (current default: #{org_output})")
|
100
|
+
Keychain.add_account(KEYCHAIN_ORGANIZATION, KEYCHAIN_ORGANIZATION, options[:organization])
|
101
|
+
end
|
102
|
+
elsif saved_organization
|
103
|
+
if yes?("Use saved organization, #{saved_organization} (y/n)?")
|
104
|
+
options[:organization] = saved_organization
|
105
|
+
else
|
106
|
+
raise Thor::InvocationError, "Organization was not set. Please set organization with '-o ORGANIZATION'"
|
107
|
+
end
|
108
|
+
else
|
109
|
+
raise Thor::InvocationError, "Organization was not set. Please set organization with '-o ORGANIZATION'"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module Maguro
|
7
|
+
class Bitbucket
|
8
|
+
protected
|
9
|
+
attr_accessor :username, :password
|
10
|
+
|
11
|
+
public
|
12
|
+
attr_reader :builder, :app_name, :organization
|
13
|
+
|
14
|
+
BITBUCKET = "bitbucket.org"
|
15
|
+
API_BASE = "https://api.bitbucket.org/2.0"
|
16
|
+
|
17
|
+
def initialize(builder, app_name, organization)
|
18
|
+
@builder = builder
|
19
|
+
@app_name = app_name
|
20
|
+
@organization = organization
|
21
|
+
self.username = nil
|
22
|
+
self.password = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def git_url
|
26
|
+
if @git_url.nil?
|
27
|
+
path = "#{API_BASE}/repositories/#{organization}/#{app_name}"
|
28
|
+
response = bitbucket_api(path, Net::HTTP::Get)
|
29
|
+
|
30
|
+
if response.code == "200"
|
31
|
+
@git_url = JSON.parse(response.body)["links"]["clone"].find{|i| i["name"] == "https"}["href"]
|
32
|
+
else
|
33
|
+
raise "Could not retrieve Git url for project #{app_name}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
@git_url
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_repo
|
40
|
+
options = {
|
41
|
+
scm: 'git',
|
42
|
+
name: app_name,
|
43
|
+
is_private: true,
|
44
|
+
fork_policy: 'no_public_forks',
|
45
|
+
language: 'ruby'
|
46
|
+
}
|
47
|
+
|
48
|
+
path = "#{API_BASE}/repositories/#{organization}/#{app_name}"
|
49
|
+
response = bitbucket_api(path, Net::HTTP::Post, options)
|
50
|
+
|
51
|
+
if response.code == "200"
|
52
|
+
# Success
|
53
|
+
puts "Successfully created repository for #{app_name}"
|
54
|
+
else
|
55
|
+
raise "Could not create Git repository for project #{app_name}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_repo
|
60
|
+
path = "#{API_BASE}/repositories/#{organization}/#{app_name}"
|
61
|
+
success_code = 204
|
62
|
+
response = bitbucket_api(path, Net::HTTP::Delete, {}, success_code)
|
63
|
+
raise "Could not delete repository." if response.code != success_code.to_s
|
64
|
+
puts "Successfully deleted repository: '#{app_name}'"
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_repo
|
68
|
+
path = "#{API_BASE}/repositories/#{organization}/#{app_name}"
|
69
|
+
response = bitbucket_api(path, Net::HTTP::Get)
|
70
|
+
|
71
|
+
# Do not raise on error, so that this method can be used
|
72
|
+
# to query the existence of a repository
|
73
|
+
return nil if response.code != "200"
|
74
|
+
|
75
|
+
JSON.parse(response.body)
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
private
|
80
|
+
def bitbucket_api(path, method, options = {}, expected_http_code = 200)
|
81
|
+
puts "Making request to API at: #{path} via #{method} with options: #{options}"
|
82
|
+
|
83
|
+
# TODO: Doug: do we want to enable this?
|
84
|
+
# First, try to read the username and password from the OS X Keychain,
|
85
|
+
# as stored by git credential-oskeychain
|
86
|
+
# if username.nil? || password.nil?
|
87
|
+
# output = %x[printf protocol=https\\\\nhost=#{BITBUCKET}\\\\n\\\\n | git credential-osxkeychain get]
|
88
|
+
# m = output.match("password=(.*)\n")
|
89
|
+
# self.password = m[1] if !m.nil?
|
90
|
+
# m = output.match("username=(.*)\n")
|
91
|
+
# self.username = m[1] if !m.nil?
|
92
|
+
# end
|
93
|
+
|
94
|
+
# Try to retrieve username and password directly from the OS X Keychain
|
95
|
+
did_get_password_from_keychain = false
|
96
|
+
if username.nil? || password.nil?
|
97
|
+
credentials = Keychain.retrieve_account(BITBUCKET)
|
98
|
+
if !credentials.nil?
|
99
|
+
self.username = credentials[:username]
|
100
|
+
self.password = credentials[:password]
|
101
|
+
did_get_password_from_keychain = true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
tries = 0
|
106
|
+
response = nil
|
107
|
+
should_store_in_keychain = false
|
108
|
+
|
109
|
+
loop do
|
110
|
+
|
111
|
+
tries += 1
|
112
|
+
|
113
|
+
if username.nil? || password.nil?
|
114
|
+
|
115
|
+
# Prompt the user for password
|
116
|
+
puts ""
|
117
|
+
self.username = builder.ask "What is your BitBucket username?"
|
118
|
+
puts ""
|
119
|
+
# password = $stdin.noecho do
|
120
|
+
# ask "BitBucket password?"
|
121
|
+
# end
|
122
|
+
self.password = builder.ask "What is your BitBucket password?", :echo => false
|
123
|
+
puts ""
|
124
|
+
puts ""
|
125
|
+
|
126
|
+
if did_get_password_from_keychain || (builder.yes? "Do you want to store this BitBucket login info into the Keychain? (y/n)")
|
127
|
+
should_store_in_keychain = true
|
128
|
+
end
|
129
|
+
puts ""
|
130
|
+
end
|
131
|
+
|
132
|
+
url = URI.parse(path)
|
133
|
+
http = Net::HTTP.new(url.host, url.port)
|
134
|
+
http.use_ssl = (url.scheme == 'https')
|
135
|
+
|
136
|
+
request = method.new(url.path)
|
137
|
+
if !options.empty?
|
138
|
+
request["content-type"] = "application/json"
|
139
|
+
request.body = options.to_json
|
140
|
+
end
|
141
|
+
|
142
|
+
request.basic_auth username, password
|
143
|
+
|
144
|
+
response = http.request(request)
|
145
|
+
|
146
|
+
response_code = response.code.to_i
|
147
|
+
|
148
|
+
# Most REST calls return HTTP 200 on success.
|
149
|
+
# Some calls return another status code on success,
|
150
|
+
# E.g. DELETE returns 204
|
151
|
+
if response_code == expected_http_code # Success
|
152
|
+
Keychain.add_account(BITBUCKET, username, password) if should_store_in_keychain
|
153
|
+
return response
|
154
|
+
end
|
155
|
+
|
156
|
+
puts "Response code: #{response_code} message: #{response.message}"
|
157
|
+
if !response.body.empty?
|
158
|
+
message = JSON.parse(response.body)["error"]["message"]
|
159
|
+
detail = JSON.parse(response.body)["error"]["detail"]
|
160
|
+
puts "Error message: #{message}"
|
161
|
+
puts "Error detail: #{detail}" if !detail.nil?
|
162
|
+
end
|
163
|
+
|
164
|
+
break if tries >= 3 # Try no more than three times
|
165
|
+
break if response_code != 401 # Only retry when the username/password is incorrect
|
166
|
+
|
167
|
+
# Clear password, so the next iteration of the loop will prompt the user
|
168
|
+
if response_code == 401
|
169
|
+
self.username = nil
|
170
|
+
self.password = nil
|
171
|
+
|
172
|
+
if did_get_password_from_keychain
|
173
|
+
# If we got credentials from the Keychain, and authentication fails,
|
174
|
+
# clear the credentials from the keychain
|
175
|
+
Keychain.delete_account(BITBUCKET)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# The request was unsuccessful
|
181
|
+
response
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|