simple_gas 0.1.9

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Fredrik Wallgren
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
20
+
data/README.textile ADDED
@@ -0,0 +1,53 @@
1
+ h1. gas - manage your git author accounts
2
+
3
+ "!http://travis-ci.org/walle/gas.png!":http://travis-ci.org/walle/gas
4
+
5
+ h2. Description
6
+
7
+ Gas is a mighty utility that helps you keep track of your multiple git authors. Add them to gas and switch between them instantly! Great if you use one author at work and one at home or if you are doing pair programming.
8
+
9
+ h2. Installation
10
+
11
+ The best way to install gas is with RubyGems:
12
+
13
+ bc. $ [sudo] gem install gas
14
+
15
+ You can install from source:
16
+
17
+ bc. $ cd gas/
18
+ $ bundle
19
+ $ rake install
20
+
21
+ h2. Running
22
+
23
+ The default task is to list authors
24
+
25
+ bc. $ gas
26
+
27
+ bc. $ gas list
28
+
29
+ This lists the authors that are set up in the ~/.gas/gas.authors file.
30
+
31
+ You can import your current user by giving it a nickname
32
+
33
+ bc. $ gas import current_user
34
+
35
+ To add an author use, add
36
+
37
+ bc. $ gas add walle "Fredrik Wallgren" fredrik.wallgren@gmail.com
38
+
39
+ And the main usage, use
40
+
41
+ bc. $ gas use walle
42
+
43
+ To delete it again use, delete
44
+
45
+ bc. $ gas delete walle
46
+
47
+ Gas can also juggle your id_rsa ssh keys, which is helpful for uploading to github between multiple accounts. Indespensible for teachers who need to instruct their students on how to use github!
48
+
49
+ bc. $ gas add Njax NotarySojac no@mail.com
50
+ Do you want gas to handle switching rsa keys for this user?
51
+ [y/n]
52
+
53
+ View @gas -h@ to see all options.
data/bin/gas ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'thor'
4
+ require 'gas'
5
+
6
+ class GasRunner < Thor
7
+
8
+ default_task :list
9
+
10
+ desc "list", "Lists your authors"
11
+ def list
12
+ Gas.list
13
+ end
14
+
15
+ desc "show", "Shows your current user"
16
+ def show
17
+ Gas.show
18
+ end
19
+
20
+ desc "use AUTHOR", "Uses author"
21
+ def use(nickname)
22
+ Gas.use nickname
23
+ end
24
+
25
+ desc "add NICKNAME NAME EMAIL", "Adds author to gasconfig"
26
+ def add(nickname, name, email)
27
+ Gas.add nickname, name, email
28
+ end
29
+
30
+ desc "import NICKNAME", "Imports current user to gasconfig"
31
+ def import(nickname)
32
+ Gas.import nickname
33
+ end
34
+
35
+ desc "delete AUTHOR", "Deletes author"
36
+ def delete(nickname)
37
+ Gas.delete nickname
38
+ end
39
+
40
+ desc "ssh", "Creates a new ssh key for an existing gas author"
41
+ def ssh(nickname=nil)
42
+ Gas.ssh nickname
43
+ end
44
+
45
+ desc "version", "Prints Gas's version"
46
+ def version
47
+ Gas.version
48
+ end
49
+ map %w(-v --version) => :version
50
+
51
+ end
52
+
53
+ GasRunner.start
data/lib/gas/config.rb ADDED
@@ -0,0 +1,123 @@
1
+ require 'fileutils'
2
+
3
+ module Gas
4
+
5
+ # Class that keeps track of users
6
+ class Config
7
+ attr_reader :users
8
+
9
+ # Initializes the object. If no users are supplied we look for a config file, if none then create it, and parse it to load users
10
+ # @param [Array<User>] users The override users
11
+ # @param [String] config The override config
12
+ def initialize(users = nil, config = nil)
13
+ @config_file = "#{GAS_DIRECTORY}/gas.authors"
14
+ @gas_dir = GAS_DIRECTORY
15
+ @config = ''
16
+
17
+ if config.nil?
18
+ if !File.exists? @config_file
19
+ Dir::mkdir(@gas_dir)
20
+ FileUtils.touch @config_file
21
+ end
22
+
23
+ @config = File.read(@config_file)
24
+ else
25
+ @config = config
26
+ end
27
+
28
+ if users.nil?
29
+ @users = []
30
+ @config.scan(/\[(.+)\]\s+name = (.+)\s+email = (.+)/) do |nickname, name, email|
31
+ @users << User.new(name, email, nickname)
32
+ end
33
+ else
34
+ @users = users
35
+ end
36
+ end
37
+
38
+ # Checks if a user with _nickname_ exists
39
+ # @param [String] nickname
40
+ # @return [Boolean]
41
+ def exists?(nickname)
42
+ @users.each do |user|
43
+ if user.nickname == nickname
44
+ return true;
45
+ end
46
+ end
47
+
48
+ false
49
+ end
50
+
51
+ # Returns the user with nickname nil if no such user exists
52
+ # @param [String|Symbol] nickname
53
+ # @return [User|nil]
54
+ def get(nickname)
55
+ @users.each do |user|
56
+ if user.nickname == nickname.to_s
57
+ return user
58
+ end
59
+ end
60
+
61
+ nil
62
+ end
63
+
64
+ # Override [] to get hash style acces to users
65
+ # @param [String|Symbol] nickname
66
+ # @return [User|nil]
67
+ def [](nickname)
68
+ get nickname
69
+ end
70
+
71
+ # Adds a user
72
+ # @param [User]
73
+ def add(user)
74
+ @users << user
75
+ end
76
+
77
+ # Deletes a user by nickname
78
+ # @param [String] nickname The nickname of the user to delete
79
+ def delete(nickname)
80
+ @users.delete_if do |user|
81
+ user.nickname == nickname
82
+ end
83
+ end
84
+
85
+ # Saves the current users to the config file
86
+ def save!
87
+ File.open @config_file, 'w' do |file|
88
+ file.write self
89
+ end
90
+ end
91
+
92
+
93
+ # Override to_s to output correct format
94
+ def to_s
95
+ gc = Gitconfig.new
96
+
97
+ users = @users.map do |user|
98
+ if is_current_user(gc.current_user_object[:name], gc.current_user_object[:email], user.to_s)
99
+ " ==>" + user.to_s[5,user.to_s.length]
100
+ else
101
+ user.to_s
102
+ end
103
+ end.join("\n")
104
+
105
+ return users
106
+ end
107
+
108
+
109
+ # Scans the @users (a string containing info formatted identical to the gas.author file)
110
+ # ...and checks to see if it's name and email match what you're looking for
111
+ def is_current_user(name, email, object)
112
+ object.scan(/\[(.+)\]\s+name = (.+)\s+email = (.+)/) do |nicknamec, namec, emailc|
113
+ if namec == name and emailc == email
114
+ # check if ssh is active
115
+ # TODO: Check if its SSH key is setup, and indicate SSH ACTIVE
116
+ return true
117
+ end
118
+ end
119
+ return false # could not get a current user's nickname
120
+ end
121
+
122
+ end
123
+ end
@@ -0,0 +1,46 @@
1
+ module Gas
2
+
3
+ # Class that class that interacts with the git config
4
+ class Gitconfig
5
+ @@nickname = ''
6
+ # Parse out the current user from the gitconfig
7
+ # @param [String] gitconfig The git configuration
8
+ # @return [User] The current user or nil if not present
9
+ def current_user
10
+ name = `git config --global --get user.name`
11
+ email = `git config --global --get user.email`
12
+
13
+ return nil if name.nil? && email.nil?
14
+
15
+ User.new name.delete("\n"), email.delete("\n"), @@nickname # git cli returns the name and email with \n at the end
16
+ end
17
+
18
+ # Get current user
19
+ def current_user_object
20
+ name = `git config --global --get user.name`
21
+ email = `git config --global --get user.email`
22
+
23
+ return nil if name.nil? && email.nil?
24
+
25
+ return {:name => name.strip, :email => email.strip}
26
+ end
27
+
28
+ # Changes the user
29
+ # @param [String] name The new name
30
+ # @param [String] email The new email
31
+ def change_user(user)
32
+ nickname = user.nickname
33
+ @@nickname = nickname # maybe we should make nickname a class variable?
34
+ name = user.name
35
+ email = user.email
36
+
37
+ `git config --global user.name "#{name}"`
38
+ `git config --global user.email "#{email}"`
39
+
40
+ # confirm that this user has an ssh and if so, swap it in safely
41
+ Ssh.swap_in_rsa nickname
42
+ end
43
+
44
+ end
45
+ end
46
+
@@ -0,0 +1,219 @@
1
+ module Gas
2
+ # A beautiful class that makes working with the github API an enjoyable experience
3
+ class GithubSpeaker
4
+ attr_reader :user, :account_name, :password, :keys, :status
5
+ attr_accessor :server
6
+
7
+ def keys
8
+ refresh_keys if @keys.nil?
9
+ @keys
10
+ end
11
+
12
+ def initialize(user, account_name=nil, password=nil, server = 'api.github.com')
13
+ @user = user
14
+ @server = server
15
+ @keys = nil
16
+
17
+ # sort out username and password... Make it's own function?
18
+ if account_name.nil? and password.nil?
19
+ # Prompt for username and password
20
+ credentials = get_username_and_password_diligently
21
+ @account_name = credentials[:account_name] # this overwrite happens twice to make testing easier... Stub on get_username, kekeke
22
+ @password = credentials[:password]
23
+ else
24
+ @account_name = account_name
25
+ @password = password
26
+ authenticate
27
+ end
28
+
29
+ end
30
+
31
+
32
+ def post_key!(rsa)
33
+ refresh_keys if @keys.nil?
34
+
35
+ puts "Posting key to GitHub.com..."
36
+
37
+ # find key...
38
+ if has_key(rsa)
39
+ puts "Key already installed."
40
+ return false
41
+ end
42
+ title = "GAS: #{@user.nickname}"
43
+ result = install_key(rsa)
44
+
45
+ if result != false
46
+ @keys << result
47
+ return true
48
+ end
49
+ end
50
+
51
+
52
+ def refresh_keys
53
+ raise "Attempted to update keys when unable to authenticate credentials with github" if @status != :authenticated
54
+
55
+ path = '/user/keys'
56
+
57
+ http = Net::HTTP.new(@server,443)
58
+ req = Net::HTTP::Get.new(path)
59
+ http.use_ssl = true
60
+ req.basic_auth @account_name, @password
61
+ response = http.request(req)
62
+
63
+ @keys = JSON.parse(response.body)
64
+ end
65
+
66
+
67
+ # Cycles through github, looking to see if rsa exists as a public key, then deletes it if it does
68
+ def remove_key!(rsa)
69
+ refresh_keys
70
+
71
+ # loop through arrays checking against 'key'
72
+ @keys.each do |key|
73
+ if key["key"] == rsa
74
+ return remove_key_by_id!(key["id"])
75
+ end
76
+ end
77
+
78
+ return false # key not found
79
+ end
80
+
81
+
82
+ private
83
+ def authenticate
84
+ path = '/user'
85
+
86
+ http = Net::HTTP.new(@server,443)
87
+ http.use_ssl = true
88
+
89
+ req = Net::HTTP::Get.new(path)
90
+ req.basic_auth @account_name, @password
91
+ response = http.request(req)
92
+
93
+ result = JSON.parse(response.body)["message"]
94
+
95
+ if result == "Bad credentials"
96
+ @status = :bad_credentials
97
+ return false
98
+ else
99
+ @status = :authenticated
100
+ return true
101
+ end
102
+ end
103
+
104
+ def get_username_and_password_and_authenticate
105
+ puts "Type your github.com user name:"
106
+ print "User: "
107
+ account_name = STDIN.gets.strip
108
+
109
+ puts "Type your github password:"
110
+ password = ask("Password: ") { |q| q.echo = false }
111
+ puts
112
+
113
+ credentials = {:account_name => account_name, :password => password}
114
+ #p credentials
115
+ @account_name = account_name
116
+ @password = password
117
+
118
+ if authenticate
119
+ return credentials
120
+ else
121
+ return false
122
+ end
123
+ end
124
+
125
+ # Get's the username and password from the user, then authenticates. If it fails, it asks them if they'd like to try again.
126
+ # Returns false if aborted
127
+ def get_username_and_password_diligently
128
+ while true
129
+ credentials = get_username_and_password_and_authenticate
130
+ if credentials == false
131
+ puts "Could not authenticate, try again?"
132
+ puts "y/n"
133
+
134
+ again = STDIN.gets.strip
135
+ case again.downcase
136
+ when "y"
137
+ when "n"
138
+ return false
139
+ end
140
+ else
141
+ return credentials
142
+ end
143
+ end
144
+ end
145
+
146
+ def install_key(rsa)
147
+ require "socket"
148
+ host_name = Socket.gethostname
149
+
150
+ title = "GAS: #{@user.nickname} \-#{host_name}"
151
+
152
+ path = '/user/keys'
153
+
154
+ http = Net::HTTP.new(@server, 443) # 443 for ssl
155
+ http.use_ssl = true
156
+
157
+ req = Net::HTTP::Post.new(path)
158
+ req.basic_auth @account_name, @password
159
+ req.body = "{\"title\":\"#{title}\", \"key\":\"#{rsa}\"}"
160
+
161
+ response = http.start {|m_http| m_http.request(req) }
162
+ the_code = response.code
163
+
164
+ key_json = JSON.parse(response.body)
165
+
166
+ return key_json if the_code == "201"
167
+
168
+ puts "The key you are trying to use already exists in another github user's account. You need to use another key." if the_code == "already_exists"
169
+
170
+ # currently.. I think it always returns "already_exists" even if successful. API bug.
171
+ puts "Something may have gone wrong. Either github changed their API, or your key couldn't be installed." if the_code != "already_exists"
172
+
173
+ #return true if my_hash.key?("errors") # this doesn't work due to it being a buggy API atm # false change me to false when they fix their API
174
+ puts "Server Response: #{response.body}"
175
+ return false
176
+ end
177
+
178
+ # Cycles through github, looking to see if rsa exists as a public key, then deletes it if it does
179
+ def has_key(rsa)
180
+ refresh_keys if @keys.nil?
181
+ return false if @keys.empty?
182
+
183
+ # loop through arrays checking against 'key'
184
+ @keys.each do |key|
185
+ return true if key["key"] == rsa
186
+ end
187
+
188
+ return false # key not found
189
+ end
190
+
191
+ def remove_key_by_id!(id)
192
+ path = "/user/keys/#{id}"
193
+
194
+ http = Net::HTTP.new(@server,443)
195
+ http.use_ssl = true
196
+ req = Net::HTTP::Delete.new(path)
197
+ req.basic_auth @account_name, @password
198
+
199
+ response = http.request(req)
200
+
201
+ if response.body.nil?
202
+ #@keys = nil # lame hack! sooo lazy of me. I should learn how to remove the proper key from the @keys hash...
203
+ remove_key_from_keys id
204
+ return true
205
+ end
206
+ end
207
+
208
+
209
+ def remove_key_from_keys(id_to_delete)
210
+ @keys.each.with_index do |key, i|
211
+ @keys.delete_at(i) if key['id'].to_i == id_to_delete.to_i
212
+ end
213
+ end
214
+
215
+
216
+
217
+
218
+ end
219
+ end
@@ -0,0 +1,169 @@
1
+ module Gas
2
+ module Prompter
3
+ @invalid_input_response_with_default = "Please use 'y' or 'n' or enter for default."
4
+ # If the user says 'f', the system will
5
+ # report that there isn't an id_rsa already in gas. This causes a new key to overwrite automatically down the road.
6
+ # This is for checking if a .gas/rsa file already exists for a nickname which is being registered
7
+ # If the rsa exists, then we're goona need to ask if we should use it, or if we should delete it
8
+ #
9
+ # Returns true to indicate that the user would like to use the rsa file already in .gas ()
10
+ # Returns false when there are no naming conflicts.
11
+ def self.user_wants_to_use_key_already_in_gas?(uid = '')
12
+ puts "Gas has detected a key in its archive directory ~/.gas/#{uid}_id_rsa. Should gas use this key or overwrite this key with a brand new one?"
13
+ puts "Keep current key? [y/n]"
14
+
15
+ while true
16
+ keep_current_file = clean_gets
17
+
18
+ case keep_current_file
19
+
20
+ when "y"
21
+ return true # keep the files already in .gas, skip making key.
22
+ when "n"
23
+ return false
24
+ else
25
+ puts "please respond 'y' or 'n'"
26
+ end
27
+ end
28
+ end
29
+
30
+ # Checks if the ~/.ssh directroy contains id_rsa and id_rsa.pub
31
+ # if it does, it asks the user if they would like to use that as their ssh key, instead of generating a new key pair.
32
+ #
33
+ def self.user_wants_to_use_key_already_in_ssh?
34
+ puts "Generate a brand new ssh key pair? (Choose 'n' to use key in ~/.ssh/id_rsa)"
35
+ puts "Default: 'y'"
36
+ puts "[Y/n]"
37
+
38
+ while true
39
+ generate_new_rsa = clean_gets.downcase
40
+ case generate_new_rsa
41
+ when "y", ""
42
+ return false
43
+ when "n"
44
+ return true # return true if we aren't generating a new key
45
+ else
46
+ puts @invalid_input_response_with_default
47
+ end
48
+ end
49
+ end
50
+
51
+ def self.user_wants_gas_to_handle_rsa_keys?
52
+ puts
53
+ puts "Do you want gas to handle switching rsa keys for this user?"
54
+ puts "[Y/n]"
55
+
56
+ while true
57
+ handle_rsa = clean_gets
58
+
59
+ case handle_rsa
60
+ when "y", ""
61
+ return true
62
+ when "n"
63
+ return false
64
+ else
65
+ puts "Please use 'y' or 'n'"
66
+ end
67
+ end
68
+ end
69
+
70
+ def self.user_wants_to_remove_the_keys_that_already_exist_for_this_user?(uid)
71
+ puts
72
+ puts "Well... there's already a ~/.gas/#{uid}_id_rsa configured and ready to go. Are you sure you don't want gas to handle rsa switching? (Clicking no will delete the key from the gas directory)"
73
+ puts "Just let gas handle ssh key for this user? [y/n]"
74
+
75
+ while true
76
+ keep_file = clean_gets
77
+
78
+ case keep_file
79
+ when "n"
80
+ return true
81
+ when "y"
82
+ puts "Excelent! Gas will handle rsa keys for this user."
83
+ return false
84
+ else
85
+ puts @invalid_input_response_with_default
86
+ end
87
+ end
88
+ end
89
+
90
+ # This is another prompt function, but it returns a more complicated lexicon
91
+ #
92
+ # returns "a", "l", "g", or "n"
93
+ def self.user_wants_to_delete_all_ssh_data?
94
+ puts "Would you like to remove all of this user's ssh keys too!?!"
95
+ puts "(github account keys can be removed as well!)"
96
+ puts
97
+ puts "a: All, the local copy, and checks github too."
98
+ puts "l: Remove local key only."
99
+ puts "g: Removes key from github.com only."
100
+ puts "n: Don't remove this user's keys."
101
+ puts "Default: l"
102
+
103
+ while true
104
+ delete_all_keys = clean_gets
105
+
106
+ case delete_all_keys.downcase
107
+ when "a"
108
+ return "a"
109
+ when "l", ""
110
+ return "l"
111
+ when "g"
112
+ return "g"
113
+ when "n"
114
+ return "n"
115
+ else
116
+ puts "please use 'a', 'l', 'g' or 'n' for NONE."
117
+ end
118
+ end
119
+ end
120
+
121
+ def self.user_wants_to_install_key_to_github?
122
+ puts "Gas can automatically install this ssh key into the github account of your choice. Would you like gas to do this for you? (Requires inputting github username and password)"
123
+ puts "[Y/n]"
124
+
125
+ while true
126
+ upload_key = clean_gets.downcase
127
+ case upload_key
128
+ when "y", ""
129
+ return true
130
+ when "n"
131
+ return false
132
+ else
133
+ puts @invalid_input_response_with_default
134
+ end
135
+ end
136
+ end
137
+
138
+ def self.user_wants_to_overwrite_existing_rsa_key?
139
+ puts "~/.ssh/id_rsa already exists. Overwrite?"
140
+ puts "[y/n]"
141
+
142
+ while true
143
+ overwrite = clean_gets
144
+ case overwrite
145
+ when "y"
146
+ return true
147
+ when "n"
148
+ return false
149
+ else
150
+ puts "please respond 'y' or 'n'"
151
+ end
152
+ end
153
+ end
154
+
155
+ # If the user hits ctrl+c with this, it will exit cleanly
156
+ def self.clean_gets
157
+ begin
158
+ getit = STDIN.gets.strip
159
+ rescue SystemExit, Interrupt # catch if they hit ctrl+c
160
+ puts
161
+ puts "Safely aborting operation..." # reassure user that ctrl+c is fine to use.
162
+ exit
163
+ end
164
+
165
+ return getit
166
+ end
167
+
168
+ end
169
+ end