me 0.0.1 → 1.0.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +2 -0
  5. data/README.md +4 -2
  6. data/bin/me +6 -0
  7. data/lib/me/activation.rb +39 -0
  8. data/lib/me/activation_view_model.rb +5 -0
  9. data/lib/me/cli/activate_command.rb +30 -0
  10. data/lib/me/cli/activation_view.rb +23 -0
  11. data/lib/me/cli/active_identity_view.rb +11 -0
  12. data/lib/me/cli/git_config_command.rb +23 -0
  13. data/lib/me/cli/git_config_view.rb +11 -0
  14. data/lib/me/cli/git_not_configured_view.rb +9 -0
  15. data/lib/me/cli/new_active_identity_view.rb +11 -0
  16. data/lib/me/cli/ssh_config_command.rb +23 -0
  17. data/lib/me/cli/ssh_config_view.rb +17 -0
  18. data/lib/me/cli/ssh_not_configured_view.rb +9 -0
  19. data/lib/me/cli/switch_command.rb +45 -0
  20. data/lib/me/cli/whoami_command.rb +18 -0
  21. data/lib/me/cli.rb +86 -0
  22. data/lib/me/error_presenter.rb +36 -0
  23. data/lib/me/errors.rb +32 -0
  24. data/lib/me/executor.rb +15 -0
  25. data/lib/me/git_activation.rb +30 -0
  26. data/lib/me/git_config.rb +71 -0
  27. data/lib/me/git_config_view_model.rb +5 -0
  28. data/lib/me/identity.rb +64 -0
  29. data/lib/me/identity_view_model.rb +5 -0
  30. data/lib/me/mappers/git_config_store2.rb +65 -0
  31. data/lib/me/mappers/identity_store2.rb +40 -0
  32. data/lib/me/mappers/ssh_config_store2.rb +68 -0
  33. data/lib/me/registry.rb +54 -0
  34. data/lib/me/ssh_activation.rb +28 -0
  35. data/lib/me/ssh_config.rb +65 -0
  36. data/lib/me/ssh_config_view_model.rb +5 -0
  37. data/lib/me/store2.rb +147 -0
  38. data/lib/me/thread_scope.rb +29 -0
  39. data/lib/me/version.rb +1 -1
  40. data/lib/me/view.rb +15 -0
  41. data/me.gemspec +2 -0
  42. data/spec/me/activation_spec.rb +22 -0
  43. data/spec/me/cli/activate_command_spec.rb +56 -0
  44. data/spec/me/cli/git_config_command_spec.rb +53 -0
  45. data/spec/me/cli/ssh_config_command_spec.rb +54 -0
  46. data/spec/me/cli/switch_command_spec.rb +64 -0
  47. data/spec/me/cli/whoami_command_spec.rb +26 -0
  48. data/spec/me/executor_spec.rb +23 -0
  49. data/spec/me/git_config_spec.rb +150 -0
  50. data/spec/me/identity_spec.rb +101 -0
  51. data/spec/me/mappers/git_config_store2_spec.rb +71 -0
  52. data/spec/me/mappers/identity_store2_spec.rb +37 -0
  53. data/spec/me/mappers/ssh_config_store2_spec.rb +65 -0
  54. data/spec/me/ssh_config_spec.rb +125 -0
  55. data/spec/me/store2_spec.rb +151 -0
  56. data/spec/spec_helper.rb +38 -0
  57. data/test.sh +38 -0
  58. metadata +85 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6dc2e30046623703ded0046efb01019766efdbca
4
- data.tar.gz: d9d335b371db6548d811a35c97ee86ba063c249c
3
+ metadata.gz: 304856b9ef39cde35ad5b81e881b5e6b0a96bd0c
4
+ data.tar.gz: b9905fe65fefbe6454414c6870a547b01a1185a6
5
5
  SHA512:
6
- metadata.gz: 07cf3d9335eda20d2b9832fbb92ffd2d64b913376c899ae4cab7b92cd755695b8ac24d49e98d15482d0e5ff28efd7648cac8c484f5aee5cc42080b1b982ec456
7
- data.tar.gz: e79ffe3a20da6ec0668ac43e31143404ccd7998a0a79d9fa5d3d89779db2f9b651a0780acd01b1e84cc4b1509bed4d4803921ac9d9d4a319a8369e583e217306
6
+ metadata.gz: eebb9092782e75ff680c6f3c8cf9e0f4129ba134922b30cf4b6caa32afcfcdc09a04c1dc2d12b9e0a032cf21343f01f1c5fcb3eb8f8b2e8dc9b4f5f028f7f4fe
7
+ data.tar.gz: 9090e74963e7d8f783847419cba4f9b355da5dc1be7f42513edb38dbfa4e6f61b20492ab07dca6f66f5108abcf42bb8aaf596a04d7eb88f293ad4a4ff0ccf4b3
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ tests.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in me.gemspec
4
4
  gemspec
5
+
6
+ gem "rspec"
data/README.md CHANGED
@@ -16,6 +16,8 @@ me --help
16
16
 
17
17
  ### Switching identity
18
18
 
19
+ Switching identity automatically activates its configuration
20
+
19
21
  ```
20
22
  me switch NAME
21
23
 
@@ -27,9 +29,9 @@ me switch work
27
29
  ### Checking which identity is active
28
30
 
29
31
  ```
30
- me
32
+ me # This will actually activate all configuration (alias for `me activate`)
31
33
  # or
32
- me whoami
34
+ me whoami # This will not activate configuration
33
35
  ```
34
36
 
35
37
  ### Configuring git identity
data/bin/me ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path(File.join(__FILE__, "..", "..", "lib")))
4
+ require "me/cli"
5
+
6
+ Me::Cli::App.start(ARGV)
@@ -0,0 +1,39 @@
1
+ require "me/registry"
2
+
3
+ module Me
4
+ class Activation
5
+ def build_view(view_factory)
6
+ view_factory.new(commands: commands)
7
+ end
8
+
9
+ def call
10
+ fail
11
+ end
12
+
13
+ def ==(other)
14
+ return false unless other.is_a?(Activation)
15
+ self.commands == other.commands
16
+ end
17
+
18
+ def _with_commands(commands)
19
+ @_commands = commands
20
+ self
21
+ end
22
+
23
+ protected
24
+
25
+ def commands
26
+ @_commands ||= []
27
+ end
28
+
29
+ private
30
+
31
+ def execute
32
+ commands.each(&executor.method(:call))
33
+ end
34
+
35
+ def executor
36
+ @_executor ||= Registry.executor_factory.new
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,5 @@
1
+ require "me/view"
2
+
3
+ module Me
4
+ ActivationViewModel = View.new(:commands)
5
+ end
@@ -0,0 +1,30 @@
1
+ require "forwardable"
2
+
3
+ require "me/cli/activation_view"
4
+
5
+ module Me
6
+ module Cli
7
+ class ActivateCommand
8
+ extend Forwardable
9
+
10
+ def call
11
+ build_views([
12
+ git_config.activate,
13
+ ssh_config.activate,
14
+ ])
15
+ end
16
+
17
+ private
18
+
19
+ delegate [:ssh_config, :git_config] => :identity
20
+
21
+ def identity
22
+ @_identity ||= Identity.active
23
+ end
24
+
25
+ def build_views(activations)
26
+ activations.map { |a| a.build_view(ActivationView) }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ require "me/activation_view_model"
2
+
3
+ module Me
4
+ module Cli
5
+ class ActivationView < ActivationViewModel
6
+ def to_s
7
+ "Executed:\n#{command_list}"
8
+ end
9
+
10
+ private
11
+
12
+ def command_list
13
+ commands
14
+ .map(&method(:command_representation))
15
+ .join("\n")
16
+ end
17
+
18
+ def command_representation(command)
19
+ "- " + command.join(" ")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ require "me/identity_view_model"
2
+
3
+ module Me
4
+ module Cli
5
+ class ActiveIdentityView < IdentityViewModel
6
+ def to_s
7
+ "Active identity: #{name}"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require "me/git_config"
2
+ require "me/cli/git_config_view"
3
+
4
+ module Me
5
+ module Cli
6
+ class GitConfigCommand < Struct.new(:identity_name, :name, :email)
7
+ def call
8
+ git_config.configure
9
+ current_git_config.build_view(GitConfigView)
10
+ end
11
+
12
+ private
13
+
14
+ def git_config
15
+ Registry.git_config_mapper_factory.new(name, email, identity_name).find
16
+ end
17
+
18
+ def current_git_config
19
+ GitConfig.for_identity(identity_name)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ require "me/git_config_view_model"
2
+
3
+ module Me
4
+ module Cli
5
+ class GitConfigView < GitConfigViewModel
6
+ def to_s
7
+ "name: #{name}\nemail: #{email}"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Me
2
+ module Cli
3
+ class GitNotConfiguredView < Struct.new(:cause, :identity)
4
+ def to_s
5
+ "Error '#{cause}' occurred. Details: Looks like git is not configured for '#{identity}' identity."
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require "me/identity_view_model"
2
+
3
+ module Me
4
+ module Cli
5
+ class NewActiveIdentityView < IdentityViewModel
6
+ def to_s
7
+ "New active identity: #{name}"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require "me/ssh_config"
2
+ require "me/cli/ssh_config_view"
3
+
4
+ module Me
5
+ module Cli
6
+ class SshConfigCommand < Struct.new(:identity_name, :keys)
7
+ def call
8
+ ssh_config.configure
9
+ current_ssh_config.build_view(SshConfigView)
10
+ end
11
+
12
+ private
13
+
14
+ def ssh_config
15
+ Registry.ssh_config_mapper_factory.new(keys, identity_name).find
16
+ end
17
+
18
+ def current_ssh_config
19
+ SshConfig.for_identity(identity_name)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ require "me/ssh_config_view_model"
2
+
3
+ module Me
4
+ module Cli
5
+ class SshConfigView < SshConfigViewModel
6
+ def to_s
7
+ "keys:\n#{key_list}"
8
+ end
9
+
10
+ private
11
+
12
+ def key_list
13
+ keys.map { |x| "- #{x}" }.join("\n")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module Me
2
+ module Cli
3
+ class SshNotConfiguredView < Struct.new(:cause, :identity)
4
+ def to_s
5
+ "Error '#{cause}' occurred. Details: Looks like ssh is not configured for '#{identity}' identity."
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ require "me/identity"
2
+ require "me/cli/new_active_identity_view"
3
+ require "me/cli/activate_command"
4
+
5
+ module Me
6
+ module Cli
7
+ class SwitchCommand < Struct.new(:name)
8
+ def call
9
+ identity.activate
10
+ activate_configuration
11
+ views
12
+ end
13
+
14
+ protected
15
+
16
+ attr_reader :activation_views
17
+
18
+ private
19
+
20
+ def views
21
+ active_identity_views + activation_views
22
+ end
23
+
24
+ def activate_command
25
+ @_activate_command ||= ActivateCommand.new
26
+ end
27
+
28
+ def activate_configuration
29
+ @activation_views ||= Array(activate_command.call)
30
+ end
31
+
32
+ def active_identity
33
+ Identity.active
34
+ end
35
+
36
+ def active_identity_views
37
+ [active_identity.build_view(NewActiveIdentityView)]
38
+ end
39
+
40
+ def identity
41
+ Registry.identity_mapper_factory.new(name).find
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ require "me/identity"
2
+ require "me/cli/active_identity_view"
3
+
4
+ module Me
5
+ module Cli
6
+ class WhoamiCommand
7
+ def call
8
+ active_identity.build_view(ActiveIdentityView)
9
+ end
10
+
11
+ private
12
+
13
+ def active_identity
14
+ Identity.active
15
+ end
16
+ end
17
+ end
18
+ end
data/lib/me/cli.rb ADDED
@@ -0,0 +1,86 @@
1
+ require "thor"
2
+
3
+ # common
4
+ require "me/registry"
5
+ require "me/executor"
6
+ require "me/errors"
7
+ require "me/error_presenter"
8
+
9
+ # mappers
10
+ require "me/mappers/identity_store2"
11
+ require "me/mappers/git_config_store2"
12
+ require "me/mappers/ssh_config_store2"
13
+
14
+ # commands
15
+ require "me/cli/whoami_command"
16
+ require "me/cli/switch_command"
17
+ require "me/cli/activate_command"
18
+ require "me/cli/git_config_command"
19
+ require "me/cli/ssh_config_command"
20
+
21
+ # views
22
+ require "me/cli/git_not_configured_view"
23
+ require "me/cli/ssh_not_configured_view"
24
+
25
+ module Me
26
+ module Cli
27
+ ERROR_VIEW_FACTORIES = {
28
+ "Me::Errors::GitNotConfigured" => GitNotConfiguredView,
29
+ "Me::Errors::SshNotConfigured" => SshNotConfiguredView,
30
+ }
31
+
32
+ Registry.register_kernel(Kernel)
33
+ Registry.register_executor_factory(Executor)
34
+ Registry.register_error_view_factories(ERROR_VIEW_FACTORIES)
35
+ Registry.register_identity_mapper_factory(Me::Mappers::IdentityStore2)
36
+ Registry.register_git_config_mapper_factory(Me::Mappers::GitConfigStore2)
37
+ Registry.register_ssh_config_mapper_factory(Me::Mappers::SshConfigStore2)
38
+
39
+ class BaseApp < Thor
40
+ private
41
+
42
+ def render(&blk)
43
+ _render(ErrorPresenter.new.call(&blk))
44
+ end
45
+
46
+ def _render(views)
47
+ return _render([views]) unless views.is_a?(Array)
48
+ views.map { |v| puts v.to_s }
49
+ end
50
+ end
51
+
52
+ class Config < BaseApp
53
+ desc "git NAME [GIT_NAME GIT_EMAIL]", "Configure corresponding git config options. Omit optional params to show current configuration"
54
+ def git(identity, name=nil, email=nil)
55
+ render { GitConfigCommand[identity, name, email].call }
56
+ end
57
+
58
+ desc "ssh NAME [SSH_KEYS]", "Configure ssh-agent to use provided ssh keys. Omit optional params to show current configuration"
59
+ def ssh(identity, *keys)
60
+ render { SshConfigCommand[identity, keys].call }
61
+ end
62
+ end
63
+
64
+ class App < BaseApp
65
+ desc "whoami", "Show current identity"
66
+ def whoami
67
+ render { WhoamiCommand.new.call }
68
+ end
69
+
70
+ desc "switch NAME", "Switch to specified identity"
71
+ def switch(identity)
72
+ render { SwitchCommand[identity].call }
73
+ end
74
+
75
+ desc "activate", "Activates configuration for current identity"
76
+ def activate
77
+ render { ActivateCommand.new.call }
78
+ end
79
+
80
+ default_task :activate
81
+
82
+ desc "config CONFIG_NAME", "Configure identities"
83
+ subcommand "config", Config
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,36 @@
1
+ require "me/errors"
2
+ require "me/registry"
3
+
4
+ module Me
5
+ class ErrorPresenter
6
+ def call
7
+ yield
8
+ rescue Errors::Base => error
9
+ Incident[error].view
10
+ end
11
+
12
+ private
13
+
14
+ class Incident < Struct.new(:error)
15
+ def view
16
+ error.build_view(view_factory)
17
+ end
18
+
19
+ private
20
+
21
+ def view_factory
22
+ error_view_factories.fetch(error.name, ReRaise)
23
+ end
24
+
25
+ def error_view_factories
26
+ Registry.error_view_factories
27
+ end
28
+ end
29
+
30
+ module ReRaise
31
+ def self.new(error, *)
32
+ raise error
33
+ end
34
+ end
35
+ end
36
+ end
data/lib/me/errors.rb ADDED
@@ -0,0 +1,32 @@
1
+ module Me
2
+ module Errors
3
+ class Base < RuntimeError
4
+ def name
5
+ self.class.name
6
+ end
7
+
8
+ def build_view(view_factory)
9
+ view_factory.new(self)
10
+ end
11
+ end
12
+
13
+ class HasIdentity < Base
14
+ def initialize(identity)
15
+ @identity = identity
16
+ end
17
+
18
+ def build_view(view_factory)
19
+ view_factory.new(self, identity)
20
+ end
21
+
22
+ protected
23
+
24
+ attr_reader :identity
25
+ end
26
+
27
+ class GitNotConfigured < HasIdentity; end
28
+ class SshNotConfigured < HasIdentity; end
29
+
30
+ class NoActiveIdentity < Base; end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ require "me/registry"
2
+
3
+ module Me
4
+ class Executor
5
+ def call(command)
6
+ kernel.system(*command)
7
+ end
8
+
9
+ private
10
+
11
+ def kernel
12
+ Registry.kernel
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ require "me/activation"
2
+
3
+ module Me
4
+ class GitActivation < Activation
5
+ def initialize(name, email)
6
+ @name = name
7
+ @email = email
8
+ end
9
+
10
+ def call
11
+ activate_name
12
+ activate_email
13
+ execute
14
+ end
15
+
16
+ protected
17
+
18
+ attr_reader :name, :email
19
+
20
+ private
21
+
22
+ def activate_name
23
+ commands << ["git", "config", "--global", "user.name", name]
24
+ end
25
+
26
+ def activate_email
27
+ commands << ["git", "config", "--global", "user.email", email]
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,71 @@
1
+ require "me/registry"
2
+ require "me/git_activation"
3
+
4
+ module Me
5
+ # Represents piece of personalised git configuration
6
+ class GitConfig
7
+ def initialize(name, email, identity_name)
8
+ @name = name
9
+ @email = email
10
+ @identity_name = identity_name
11
+ end
12
+
13
+ def with_mapper(mapper)
14
+ @mapper = mapper
15
+ self
16
+ end
17
+
18
+ def ==(other)
19
+ return false unless other.is_a?(GitConfig)
20
+ self.equality_fields == other.equality_fields
21
+ end
22
+
23
+ def configure
24
+ return unless name && email
25
+ mapper.update(name: name, email: email)
26
+ end
27
+
28
+ def activate
29
+ activation.call
30
+ activation
31
+ end
32
+
33
+ def build_view(view_factory)
34
+ view_factory.new(name: name, email: email)
35
+ end
36
+
37
+ protected
38
+
39
+ attr_reader :name, :email, :identity_name, :mapper
40
+
41
+ def equality_fields
42
+ [name, email]
43
+ end
44
+
45
+ private
46
+
47
+ def activation
48
+ @_activation ||= GitActivation.new(name, email)
49
+ end
50
+ end
51
+
52
+ class << GitConfig
53
+ def for_identity(identity_name)
54
+ Registry.git_config_mapper_factory.find_by_identity(identity_name)
55
+ end
56
+ end
57
+
58
+ class GitConfig::Mapper
59
+ def self.find_by_identity(identity_name)
60
+ end
61
+
62
+ def initialize(name, email, identity_name)
63
+ end
64
+
65
+ def find
66
+ end
67
+
68
+ def update(name: nil, email: nil)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ require "me/view"
2
+
3
+ module Me
4
+ GitConfigViewModel = View.new(:name, :email)
5
+ end