yadecli 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +7 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +172 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +43 -0
  11. data/Rakefile +13 -0
  12. data/bin/yadecli +10 -0
  13. data/config-example.yml +14 -0
  14. data/lib/.DS_Store +0 -0
  15. data/lib/yadecli/.DS_Store +0 -0
  16. data/lib/yadecli/cli/application.rb +40 -0
  17. data/lib/yadecli/cli/composer.rb +68 -0
  18. data/lib/yadecli/cli/host.rb +28 -0
  19. data/lib/yadecli/cli/module.rb +24 -0
  20. data/lib/yadecli/cli/project.rb +42 -0
  21. data/lib/yadecli/cli/task.rb +21 -0
  22. data/lib/yadecli/client/authentication_client.rb +24 -0
  23. data/lib/yadecli/client/base_client.rb +78 -0
  24. data/lib/yadecli/client/composer_container_client.rb +27 -0
  25. data/lib/yadecli/client/composer_project_client.rb +27 -0
  26. data/lib/yadecli/client/composer_service_client.rb +27 -0
  27. data/lib/yadecli/client/domain_client.rb +23 -0
  28. data/lib/yadecli/client/host_client.rb +45 -0
  29. data/lib/yadecli/client/maven_build_step_client.rb +23 -0
  30. data/lib/yadecli/client/maven_build_task_client.rb +23 -0
  31. data/lib/yadecli/client/nvm_runtime_client.rb +23 -0
  32. data/lib/yadecli/client/project_client.rb +28 -0
  33. data/lib/yadecli/client/project_module_client.rb +35 -0
  34. data/lib/yadecli/client/pyenv_runtime_client.rb +23 -0
  35. data/lib/yadecli/client/role_client.rb +23 -0
  36. data/lib/yadecli/client/rvm_runtime_client.rb +23 -0
  37. data/lib/yadecli/client/sdk_package_client.rb +28 -0
  38. data/lib/yadecli/client/vcs_client.rb +23 -0
  39. data/lib/yadecli/config/app_config.rb +69 -0
  40. data/lib/yadecli/io/user_input.rb +21 -0
  41. data/lib/yadecli/model/composer_container.rb +19 -0
  42. data/lib/yadecli/model/composer_project.rb +30 -0
  43. data/lib/yadecli/model/composer_service.rb +19 -0
  44. data/lib/yadecli/model/domain.rb +24 -0
  45. data/lib/yadecli/model/git_status.rb +8 -0
  46. data/lib/yadecli/model/host.rb +24 -0
  47. data/lib/yadecli/model/ide_type.rb +7 -0
  48. data/lib/yadecli/model/installation_status.rb +7 -0
  49. data/lib/yadecli/model/maven_build_step.rb +19 -0
  50. data/lib/yadecli/model/maven_build_task.rb +19 -0
  51. data/lib/yadecli/model/nvm_runtime.rb +18 -0
  52. data/lib/yadecli/model/project.rb +26 -0
  53. data/lib/yadecli/model/project_module.rb +29 -0
  54. data/lib/yadecli/model/pyenv_runtime.rb +18 -0
  55. data/lib/yadecli/model/role.rb +24 -0
  56. data/lib/yadecli/model/rvm_runtime.rb +18 -0
  57. data/lib/yadecli/model/sdk_package.rb +18 -0
  58. data/lib/yadecli/model/vcs.rb +19 -0
  59. data/lib/yadecli/service/authentication_service.rb +31 -0
  60. data/lib/yadecli/service/build_step_service.rb +24 -0
  61. data/lib/yadecli/service/build_task_service.rb +70 -0
  62. data/lib/yadecli/service/composer_service.rb +395 -0
  63. data/lib/yadecli/service/connect_service.rb +19 -0
  64. data/lib/yadecli/service/host_service.rb +191 -0
  65. data/lib/yadecli/service/module_service.rb +78 -0
  66. data/lib/yadecli/service/project_service.rb +198 -0
  67. data/lib/yadecli/util/cli_util.rb +22 -0
  68. data/lib/yadecli/util/file_util.rb +46 -0
  69. data/lib/yadecli/util/nvm_util.rb +14 -0
  70. data/lib/yadecli/util/pyenv_util.rb +14 -0
  71. data/lib/yadecli/util/rvm_util.rb +38 -0
  72. data/lib/yadecli/util/sdk_util.rb +23 -0
  73. data/lib/yadecli/util/system_util.rb +22 -0
  74. data/lib/yadecli/version.rb +3 -0
  75. data/lib/yadecli.rb +69 -0
  76. data/scripts/nvm-install-node.sh +6 -0
  77. data/scripts/rvm-gemset-import.sh +8 -0
  78. data/scripts/rvm-install-ruby.sh +6 -0
  79. data/scripts/sdk-install-candidate.sh +6 -0
  80. data/scripts/setup-terminal.sh +3 -0
  81. data/scripts/start-ide.sh +3 -0
  82. data/yadecli.gemspec +55 -0
  83. metadata +379 -0
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # yadecli cli
4
+ module Yadecli
5
+ module Client
6
+
7
+ # base client
8
+ class BaseClient
9
+
10
+ # initialize
11
+ # prepare options hash with authorization header for httpparty requests
12
+ def initialize(microservice, resource_name)
13
+ @microservice = microservice
14
+ @resource_name = resource_name
15
+
16
+ expiration_time = Time.parse(AppConfig['expiration_time'].to_s)
17
+
18
+ access_token = AppConfig['access_token']
19
+
20
+ if Time.now > expiration_time
21
+ @authentication_client = Yadecli::Client::AuthenticationClient.new
22
+
23
+ response = @authentication_client.request_token AppConfig['auth_url'], AppConfig['username'], AppConfig['password']
24
+
25
+ AppConfig['access_token'] = response['access_token']
26
+ AppConfig['refresh_token'] = response['refresh_token']
27
+ AppConfig['expiration_time'] = Time.now + response['expires_in']
28
+
29
+ AppConfig.write!
30
+
31
+ access_token = response['access_token']
32
+ end
33
+
34
+ @options = { headers: { Authorization: "Bearer #{access_token}", 'Content-Type' => 'application/json' } }
35
+ end
36
+
37
+ # list all
38
+ def list
39
+ response = self.class.get(base_path, @options)
40
+
41
+ response.parsed_response.map do |p|
42
+ create_instance.new(p)
43
+ end
44
+ end
45
+
46
+ # get by id
47
+ def get(id)
48
+ response = get_request("#{id}")
49
+
50
+ create_instance.new(response.parsed_response)
51
+ end
52
+
53
+ def base_path
54
+ if @resource_name.end_with? 's'
55
+ "/#{@microservice}/api/#{@resource_name}"
56
+ else
57
+ "/#{@microservice}/api/#{@resource_name}s"
58
+ end
59
+ end
60
+
61
+ def get_request(path = nil)
62
+ full_path = base_path
63
+
64
+ full_path += "/#{path}" if path != nil
65
+
66
+ self.class.get(full_path, @options)
67
+ end
68
+
69
+ private
70
+
71
+ def create_instance
72
+ class_name = @resource_name.split('-').map!(&:capitalize).join
73
+
74
+ Object.const_get(class_name)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # project client
12
+ class ComposerContainerClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadecomposer', 'composer-container')
20
+ end
21
+
22
+ def get_by_composer_service_id(composer_service_id)
23
+ list.select { |composer_container| composer_container.composerServiceId == composer_service_id }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # project client
12
+ class ComposerProjectClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadecomposer', 'composer-project')
20
+ end
21
+
22
+ def get_by_name(name)
23
+ list.select { |composer_project| composer_project.name == name }.first
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # project client
12
+ class ComposerServiceClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadecomposer', 'composer-service')
20
+ end
21
+
22
+ def get_by_composer_project_id(composer_project_id)
23
+ list.select { |composer_service| composer_service.composerProjectId == composer_project_id }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # domain client
12
+ class DomainClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadedomain', 'domain')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # host client
12
+ class HostClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadedomain', 'host')
20
+ end
21
+
22
+ # get master host
23
+ def master
24
+ list.select(&:isMaster).first
25
+ end
26
+
27
+ # get host by fqdn
28
+ def host_by_fqdn(host_fqdn)
29
+ splitted = host_fqdn.split('.')
30
+
31
+ hostname = splitted.first
32
+ fqdn = splitted.last(splitted.size - 1).join('.')
33
+
34
+ all_hosts_with_name = list.select { |h| h.name == hostname }
35
+
36
+ domain_client = Yadecli::Client::DomainClient.new
37
+
38
+ all_hosts_with_name.each do |h|
39
+ domain = domain_client.get(h.domainId)
40
+ return h if domain.name == fqdn
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # maven build step client
12
+ class MavenBuildStepClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'maven-build-step')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # maven build task client
12
+ class MavenBuildTaskClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'maven-build-task')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # rvm runtime client
12
+ class NvmRuntimeClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'nvm-runtime')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # project client
12
+ class ProjectClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'project')
20
+ end
21
+
22
+ # get project by name
23
+ def project_by_name(project_name)
24
+ list.select { |p| p.name == project_name }.first
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # authentication client
12
+ class ProjectModuleClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :info
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'project-module')
20
+ end
21
+
22
+ # get modules for project with id
23
+ def modules_for_project(project_id)
24
+ list.select { |m| m.projectId == project_id }
25
+ end
26
+
27
+ # get module by name from project with id
28
+ def module_for_project(project_id, module_name)
29
+ modules = modules_for_project(project_id)
30
+
31
+ modules.select { |m| m.name == module_name }.first
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # pyenv runtime client
12
+ class PyenvRuntimeClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'pyenv-runtime')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # role client
12
+ class RoleClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadedomain', 'role')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # rvm runtime client
12
+ class RvmRuntimeClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'rvm-runtime')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # domain client
12
+ class SdkPackageClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'sdk-package')
20
+ end
21
+
22
+ # get sdk packages for project with id
23
+ def sdk_packages_for_project(project_id)
24
+ list.select { |sdk_package| sdk_package.projectId == project_id }
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'logger'
5
+ require 'yadecli/client/base_client'
6
+
7
+ # yadecli cli
8
+ module Yadecli
9
+ module Client
10
+
11
+ # vcs client
12
+ class VcsClient < BaseClient
13
+ include HTTParty
14
+ #logger ::Logger.new(STDOUT), :debug
15
+
16
+ base_uri AppConfig[:url]
17
+
18
+ def initialize
19
+ super('yadeproject', 'vcs')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'settingslogic'
4
+
5
+ class AppConfig < Settingslogic
6
+
7
+ @@yade_home = File.join(File.expand_path('~'), '.yade')
8
+ @@config_path = File.join(@@yade_home, 'config.yml')
9
+
10
+ @@composer_home = File.join(File.expand_path('~'), 'yade', 'composer')
11
+
12
+ source File.join(@@config_path)
13
+
14
+ class << self
15
+ attr_accessor :yade_home, :config_path, :composer_home
16
+ end
17
+
18
+ def self.load!
19
+ if no_config_file?
20
+ $stderr.puts <<-HELP
21
+ ******** You haven't set up your Yade settings file. **********
22
+ Please do the following:
23
+ 1. Create the yade base directory and download the application.yml example:
24
+ mkdir -p ~/.yade
25
+ cd ~/.yade
26
+ curl --header 'PRIVATE-TOKEN: <your token>' \
27
+ 'http://gitlab.dzbw.de/client/v4/projects/366/repository/files/application%2Eyml%2Eexample/raw?ref=master' \
28
+ -o config.yml
29
+ 2. Have a look at the settings in that file and change it according to your needs.
30
+ HELP
31
+ Process.exit(1)
32
+ end
33
+
34
+ super
35
+
36
+ end
37
+
38
+ # no config
39
+ def self.no_config_file?
40
+ !File.exists?(@source)
41
+ end
42
+
43
+ load!
44
+
45
+ def self.[](key)
46
+ return @@yade_home if key == :yade_home
47
+ return @@config_path if key == :config_path
48
+ return @@composer_home if key == :composer_home
49
+ super
50
+ end
51
+
52
+ def self.write!
53
+ d = YAML.load_file(@@config_path)
54
+
55
+ d['url'] = self.url
56
+ d['auth_url'] = self.auth_url
57
+ d['username'] = self.username
58
+ d['password'] = self.password
59
+ d['access_token'] = self.access_token
60
+ d['refresh_token'] = self.refresh_token
61
+ d['expiration_time'] = self.expiration_time
62
+ d['git_username'] = self.git_username
63
+ d['git_password'] = self.git_password
64
+ d['git_token'] = self.git_token
65
+
66
+ File.open(@@config_path, 'w') { |f| f.write d.to_yaml }
67
+ end
68
+
69
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-prompt'
4
+
5
+ # User Input
6
+ class UserInput
7
+
8
+ def self.ask(message, config_key)
9
+ prompt = TTY::Prompt.new
10
+
11
+ prompt.ask(message, default: AppConfig[config_key] ||= '')
12
+ end
13
+
14
+ # def self.select_branch(project_name)
15
+ # prompt = TTY::Prompt.new
16
+ #
17
+ # available_branches = GitlabApi.new.branches_of_project(project_name)
18
+ #
19
+ # prompt.select('Select the branch you want to clone', available_branches.map { |b| b.to_hash['name'] })
20
+ # end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+
5
+ # Project
6
+ class ComposerContainer
7
+ include ActiveModel::Model
8
+ include ActiveModel::Validations
9
+ include ActiveModel::Serializers::JSON
10
+
11
+ attr_accessor :id, :name, :composerServiceId
12
+
13
+ validates_presence_of 'id', 'name', 'composerServiceId'
14
+
15
+ def attributes
16
+ instance_values
17
+ end
18
+
19
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+
5
+ # Project
6
+ class ComposerProject
7
+ include ActiveModel::Model
8
+ include ActiveModel::Validations
9
+ include ActiveModel::Serializers::JSON
10
+
11
+ attr_accessor :id, :name, :gitUrl
12
+
13
+ validates_presence_of 'id', 'name', 'gitUrl'
14
+
15
+ def attributes
16
+ instance_values
17
+ end
18
+
19
+ def install_dir
20
+ "#{AppConfig[:composer_home]}/#{name}"
21
+ end
22
+
23
+ def installed?
24
+ File.directory?("#{AppConfig[:composer_home]}/#{name}")
25
+ end
26
+
27
+ def uninstall
28
+ FileUtils.rm_rf("#{AppConfig[:composer_home]}/#{name}")
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+
5
+ # Project
6
+ class ComposerService
7
+ include ActiveModel::Model
8
+ include ActiveModel::Validations
9
+ include ActiveModel::Serializers::JSON
10
+
11
+ attr_accessor :id, :name, :title, :enabled, :requiredEnvs, :composerProjectId
12
+
13
+ validates_presence_of 'id', 'name', 'title', 'composerProjectId'
14
+
15
+ def attributes
16
+ instance_values
17
+ end
18
+
19
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+
5
+ # Domain
6
+ class Domain
7
+ include ActiveModel::Model
8
+ include ActiveModel::Validations
9
+ include ActiveModel::Serializers::JSON
10
+
11
+ attr_accessor :id, :name
12
+
13
+ validates_presence_of 'id', 'name'
14
+
15
+ def attributes=(hash)
16
+ hash.each do |key, value|
17
+ send("#{key}=", value)
18
+ end
19
+ end
20
+
21
+ def attributes
22
+ instance_values
23
+ end
24
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # git status
4
+ class GitStatus
5
+ NEEDS_PUSH = '⬆'
6
+ NEEDS_PULL = '⬇'
7
+ UP_TO_DATE = '✔'
8
+ end