xcskarel 0.7.1 → 0.8.0

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: 9989b96aa6ff52cf3fc52a82ec381ba4410d62f4
4
- data.tar.gz: cd7fff217976a40c5405f96daf2ff3f043f5a77e
3
+ metadata.gz: b2d2ee90682d97c41330da69045be0e7d247e205
4
+ data.tar.gz: 64564df685430fb56aa6af4e47a402f9fd2e4022
5
5
  SHA512:
6
- metadata.gz: d32ad6a22b710bd163c14a188b4ff804bba907808204efe46fba78867979f86f9918c86307bb2831c9e82504d2f065848645d869fe4fcb256c9d76cf22b12bd9
7
- data.tar.gz: 35443b16521422e86b5f183a22c6ba1689385bf265e3dc13c0e4e096f72de0f20779cacf89e14e4b53b52f280b3cb1dfde6d155ad6d353de2761f42af1ad3aa5
6
+ metadata.gz: 0845f1c391fda33d0e758c4ff1cf742ca63aed8ac2d8a311ca7554ed37b99d51ad6852c1875ab82d4099a066367ae5a5ced67b789b472e483ec9ca833bac9501
7
+ data.tar.gz: df228a2c1a18993371002d6868a8baedac53425c234894a622c1287c53276ac1ba09381d648bb8225063cc9a22baf28aa5299767bc563184e3ce66d5b2d603b3
data/bin/xcskarel CHANGED
@@ -33,6 +33,52 @@ class XCSKarelApplication
33
33
  global_option('--no_pretty', 'Disables output JSON prettification')
34
34
  global_option('--no_filter', 'Prints full JSON payload for objects instead of just filtering the important ones')
35
35
 
36
+ # Managing local xcsconfig folder
37
+
38
+ command :'config list' do |c|
39
+ c.syntax = 'xcskarel config list [options]'
40
+ c.description = 'Lists the Xcode Bot configurations found in this folder'
41
+ c.example 'lists all configurations stored in this folder', 'xcskarel config list'
42
+ c.action do |args, options|
43
+ config_folder = XCSKarel::XCSFile.get_config_folder
44
+ return unless config_folder
45
+ XCSKarel::Application.list_configs(config_folder)
46
+ end
47
+ end
48
+
49
+ command :'config show' do |c|
50
+ c.syntax = 'xcskarel config show [options]'
51
+ c.description = 'Opens the selected config for editing'
52
+ c.example 'opens a config of choice', 'xcskarel config show'
53
+ c.action do |args, options|
54
+ config_folder = XCSKarel::XCSFile.get_config_folder
55
+ return unless config_folder
56
+ XCSKarel::Application.show_config(config_folder)
57
+ end
58
+ end
59
+
60
+ command :'config new' do |c|
61
+ c.syntax = 'xcskarel config new [options]'
62
+ c.description = 'Starts the interactive process of creating a new config from an existing Bot'
63
+ c.example 'starts creating new config from server at 192.168.1.64', 'xcskarel config new --host 192.168.1.64'
64
+ add_xcs_options(c)
65
+ c.action do |args, options|
66
+
67
+ # let user chose a bot from the server
68
+ server = create_server_from_options(options)
69
+ bot = XCSKarel::Application.choose_bot(server)
70
+
71
+ # get our config folder
72
+ config_folder = XCSKarel::XCSFile.get_config_folder
73
+ return unless config_folder
74
+
75
+ # dump the bot into that config folder under a random name
76
+ XCSKarel::Application.save_bot(config_folder, bot, server.api_version)
77
+ end
78
+ end
79
+
80
+ # Talking to Xcode Server API
81
+
36
82
  command :bots do |c|
37
83
  c.syntax = 'xcskarel bots [options]'
38
84
  c.description = 'Fetches all Bots found on the specified server'
@@ -87,6 +133,8 @@ class XCSKarelApplication
87
133
  end
88
134
  end
89
135
 
136
+ # Managing a local Xcode Server
137
+
90
138
  command :'server start' do |c|
91
139
  c.syntax = 'xcskarel server start [options]'
92
140
  c.description = 'Start local Xcode Server'
@@ -137,6 +185,8 @@ class XCSKarelApplication
137
185
  end
138
186
  end
139
187
 
188
+ # Managing Xcode
189
+
140
190
  command :'xcode select' do |c|
141
191
  c.syntax = 'xcskarel xcode select'
142
192
  c.description = 'Interactive xcode-select'
data/lib/xcskarel.rb CHANGED
@@ -4,4 +4,6 @@ require 'xcskarel/version'
4
4
  require 'xcskarel/log'
5
5
  require 'xcskarel/filter'
6
6
  require 'xcskarel/control'
7
- require 'xcskarel/bot'
7
+ require 'xcskarel/config'
8
+ require 'xcskarel/xcsfile'
9
+ require 'xcskarel/application'
@@ -0,0 +1,52 @@
1
+ module XCSKarel
2
+ module Application
3
+ def self.choose_bot(server)
4
+ all_bots = server.get_bots
5
+ bot_names = all_bots.map { |json| "#{json['name']} (#{json['_id']})" }
6
+ puts "Which Bot should be used as a template?"
7
+ choice = choose(*bot_names)
8
+ bot = all_bots[bot_names.index(choice)]
9
+ XCSKarel.log.info "Chose Bot \"#{bot['name']}\""
10
+ return bot
11
+ end
12
+
13
+ def self.save_bot(config_folder, bot, api_version)
14
+ rand_name = XCSKarel::XCSFile.random_name
15
+ config_name = ask("Config name (hit Enter to accept generated name \"" + "#{rand_name}".yellow + "\"): ")
16
+ config_name = rand_name if config_name.length == 0
17
+
18
+ # preprocess the config name first
19
+ require 'uri'
20
+ config_name = URI::escape(config_name.gsub(" ", "_"))
21
+
22
+ real_name = "botconfig_#{config_name}.json"
23
+ new_config_path = XCSKarel::XCSFile.new_config_name(config_folder, real_name)
24
+ new_config = XCSKarel::Config.new(bot, api_version, new_config_path)
25
+ new_config.save
26
+
27
+ XCSKarel.log.info "Saved Bot \"#{new_config.name}\" configuration to #{new_config_path}. Check this into your repository.".green
28
+ system "open \"#{new_config_path}\""
29
+ end
30
+
31
+ def self.list_configs(config_folder)
32
+ configs = XCSKarel::XCSFile.load_configs(config_folder)
33
+ if configs.count == 0
34
+ XCSKarel.log.info "Found no existing configs in #{config_folder}".yellow
35
+ else
36
+ out = "\n" + configs.map { |c| "\"#{c.name}\"".yellow + " [#{File.basename(c.path)}]".yellow + " - from Bot " + "#{c.original_bot_name}".yellow }.join("\n")
37
+ XCSKarel.log.info "Found #{configs.count} configs in \"#{config_folder}\":"
38
+ XCSKarel.log.info out
39
+ end
40
+ end
41
+
42
+ def self.show_config(config_folder)
43
+ configs = XCSKarel::XCSFile.load_configs(config_folder)
44
+ config_names = configs.map { |c| "Config " + "#{c.name}".yellow + " from Bot " + "#{c.original_bot_name}".yellow }
45
+ puts "Which config?"
46
+ choice = choose(*config_names)
47
+ config = configs[config_names.index(choice)]
48
+ XCSKarel.log.info "Editing config \"#{config.name}\""
49
+ system "open \"#{config.path}\""
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,86 @@
1
+ module XCSKarel
2
+ class Config
3
+ attr_reader :json
4
+ attr_reader :path
5
+ attr_reader :api_version
6
+
7
+ def initialize(json, api_version, path)
8
+ @json = json
9
+ @path = path
10
+ @api_version = api_version || (config_json ? config_json['api_version'] : nil)
11
+ end
12
+
13
+ def name
14
+ (config_json['name'] || File.basename(@path).split('.').first).gsub("botconfig_", "")
15
+ end
16
+
17
+ def original_bot_name
18
+ @json['name'] || config_json['original_bot_name']
19
+ end
20
+
21
+ def config_json
22
+ @json['xcsconfig'] || {}
23
+ end
24
+
25
+ def key_paths_for_persistance
26
+ key_paths_for_xcode_server << "xcsconfig"
27
+ end
28
+
29
+ def key_paths_for_xcode_server
30
+ ["configuration"]
31
+ end
32
+
33
+ def format_version
34
+ 1
35
+ end
36
+
37
+ def json_for_persistence
38
+ filtered = XCSKarel::Filter.filter_key_paths(@json, key_paths_for_persistance)
39
+
40
+ # also add xcsconfig metadata
41
+ unless filtered["xcsconfig"]
42
+ filtered["xcsconfig"] = {
43
+ format_version: format_version,
44
+ app_version: XCSKarel::VERSION,
45
+ original_bot_name: @json['name'],
46
+ name: name,
47
+ api_version: @api_version
48
+ }
49
+ end
50
+ return filtered
51
+ end
52
+
53
+ def json_for_xcode_server
54
+ XCSKarel::Filter.filter_key_paths(@json, key_paths_for_xcode_server)
55
+ end
56
+
57
+ def self.from_file(file_path)
58
+ abs_path = File.absolute_path(file_path)
59
+ raise "No file #{abs_path}" unless File.exist?(abs_path)
60
+ config = self.new(JSON.parse(File.read(abs_path)), nil, abs_path)
61
+ unless config.validate_loaded
62
+ XCSKarel.log.warn "Skipping invalid config #{abs_path}".yellow
63
+ return nil
64
+ end
65
+ return config
66
+ end
67
+
68
+ def validate_loaded
69
+ return false unless config_json
70
+ return true
71
+ end
72
+
73
+ def to_file(file_path)
74
+ abs_path = File.absolute_path(file_path)
75
+ raise "File #{abs_path} already exists. Choose a different name.".red if File.exist?(abs_path)
76
+ FileUtils.mkdir_p(File.dirname(abs_path))
77
+ File.open(abs_path, 'w') do |f|
78
+ f.puts JSON.pretty_generate(json_for_persistence) + "\n"
79
+ end
80
+ end
81
+
82
+ def save
83
+ to_file(@path)
84
+ end
85
+ end
86
+ end
@@ -24,7 +24,9 @@ module XCSKarel
24
24
  key.split('.').first == keys.first
25
25
  end.first
26
26
  if match
27
- new_hash[keys.first] = filter_key_paths(v, match.split('.').drop(1))
27
+ child_key_paths = match.split('.').drop(1)
28
+ # if there are no more key paths, we just take everything (whitelisted by default)
29
+ new_hash[keys.first] = child_key_paths.count == 0 ? v : filter_key_paths(v, child_key_paths)
28
30
  end
29
31
  end
30
32
  return new_hash
@@ -11,6 +11,7 @@ module XCSKarel
11
11
  attr_reader :user
12
12
  attr_reader :pass
13
13
  attr_reader :port
14
+ attr_reader :api_version
14
15
 
15
16
  def initialize(host, user=nil, pass=nil, allow_self_signed=true)
16
17
  @port = 20343
@@ -88,7 +89,8 @@ module XCSKarel
88
89
  raise "Failed to validate - #{e}.\nPlease make sure your Xcode Server is up and running at #{host}. Run `xcskarel server start` to start a new local Xcode Server instance.".red
89
90
  else
90
91
  raise "Failed to validate - Endpoint at \"#{url}\" responded with #{response.data[:status_line]}".red if response.status != 204
91
- XCSKarel.log.debug "Validation of host #{@host} succeeded.".green
92
+ @api_version = response.headers['X-XCSAPIVersion'].to_s
93
+ XCSKarel.log.debug "Validation of host #{@host} (API version #{@api_version}) succeeded.".green
92
94
  end
93
95
  end
94
96
  end
@@ -1,3 +1,3 @@
1
1
  module XCSKarel
2
- VERSION = '0.7.1'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -0,0 +1,71 @@
1
+ module XCSKarel
2
+ module XCSFile
3
+ def self.folder_name
4
+ "xcsconfig"
5
+ end
6
+
7
+ def self.file_name
8
+ "xcsfile.json"
9
+ end
10
+
11
+ def self.find_config_folder_in_current_folder
12
+ self.find_config_folder_in_folder(Dir.pwd)
13
+ end
14
+
15
+ def self.find_config_folder_in_folder(folder)
16
+ # look for the xcsconfig folder with an xcsfile inside
17
+ abs_folder = File.absolute_path(folder)
18
+ found_folder = Dir[File.join(abs_folder, "/", "*")].select do |f|
19
+ File.basename(f) == self.folder_name
20
+ end.first
21
+ return found_folder
22
+ end
23
+
24
+ def self.create_config_folder_in_current_folder
25
+ self.create_config_folder_in_folder(Dir.pwd)
26
+ end
27
+
28
+ def self.create_config_folder_in_folder(folder)
29
+ abs_folder = File.absolute_path(folder)
30
+ config_folder = File.join(abs_folder, self.folder_name)
31
+ FileUtils.mkdir_p(config_folder)
32
+ return config_folder
33
+ end
34
+
35
+ def self.get_config_folder
36
+ config_folder = XCSKarel::XCSFile.find_config_folder_in_current_folder
37
+ unless config_folder
38
+ should_create = agree("There is no xcsconfig folder found, should I create one for you? (y/n)".red)
39
+ if should_create
40
+ config_folder = XCSKarel::XCSFile.create_config_folder_in_current_folder unless config_folder
41
+ XCSKarel.log.debug "Folder #{config_folder} created".yellow
42
+ else
43
+ return nil
44
+ end
45
+ end
46
+ # we have a config folder
47
+ XCSKarel.log.debug "Config folder found: #{config_folder}".green
48
+ return config_folder
49
+ end
50
+
51
+ def self.load_configs(folder)
52
+ require 'json'
53
+ Dir[File.join(folder, "/", "botconfig_*.json")].map do |f|
54
+ XCSKarel::Config.from_file(f)
55
+ end.select do |c|
56
+ c != nil
57
+ end
58
+ end
59
+
60
+ def self.random_name
61
+ require 'securerandom'
62
+ "#{SecureRandom.hex(6)}"
63
+ end
64
+
65
+ def self.new_config_name(folder, name)
66
+ name = name.split('.').first + ".json"
67
+ File.join(folder, name)
68
+ end
69
+
70
+ end
71
+ end
data/spec/filter_spec.rb CHANGED
@@ -43,6 +43,25 @@ describe XCSKarel do
43
43
  expect(test(obj, ["oranges.old"])).to eq(exp)
44
44
  end
45
45
 
46
+ it "keeps full values when hashes and key is already whitelisted" do
47
+ obj = {
48
+ "apples" => "green",
49
+ "blackberries" => 12,
50
+ "oranges" => {
51
+ "new" => 2,
52
+ "old" => -2
53
+ }
54
+ }
55
+ exp = {
56
+ "apples" => "green",
57
+ "oranges" => {
58
+ "new" => 2,
59
+ "old" => -2
60
+ }
61
+ }
62
+ expect(test(obj, ["oranges", "apples"])).to eq(exp)
63
+ end
64
+
46
65
  it "handles basic key path with an array without popping the key path" do
47
66
  obj = [
48
67
  "apples",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xcskarel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Honza Dvorsky
@@ -174,12 +174,14 @@ extra_rdoc_files: []
174
174
  files:
175
175
  - bin/xcskarel
176
176
  - lib/xcskarel.rb
177
- - lib/xcskarel/bot.rb
177
+ - lib/xcskarel/application.rb
178
+ - lib/xcskarel/config.rb
178
179
  - lib/xcskarel/control.rb
179
180
  - lib/xcskarel/filter.rb
180
181
  - lib/xcskarel/log.rb
181
182
  - lib/xcskarel/server.rb
182
183
  - lib/xcskarel/version.rb
184
+ - lib/xcskarel/xcsfile.rb
183
185
  - spec/default_spec.rb
184
186
  - spec/filter_spec.rb
185
187
  homepage: http://github.com/czechboy0/xcskarel
data/lib/xcskarel/bot.rb DELETED
@@ -1,23 +0,0 @@
1
- module XCSKarel
2
- class Bot
3
- attr_reader :json
4
- def initialize(json)
5
- @json = json
6
- end
7
-
8
- def self.from_file(file_path)
9
- abs_path = File.absolute_path(file_path)
10
- raise "No file #{abs_path}" unless File.exist?(abs_path)
11
- self.new(File.read(abs_path))
12
- end
13
-
14
- def to_file(file_path="./xcskarel/bot.json")
15
- abs_path = File.absolute_path(file_path)
16
- raise "File #{abs_path} already exists." if File.exist?(abs_path)
17
- FileUtils.mkdir_p(File.dirname(abs_path))
18
- File.open(abs_path, 'w') do |f|
19
- f.puts JSON.pretty_generate(@json) + "\n"
20
- end
21
- end
22
- end
23
- end