space 0.0.5 → 0.0.6

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 (47) hide show
  1. data/bin/space +6 -0
  2. data/lib/core_ext/string/deansi.rb +7 -0
  3. data/lib/core_ext/string/demodulize.rb +5 -0
  4. data/lib/space.rb +4 -4
  5. data/lib/space/action.rb +43 -0
  6. data/lib/space/action/builtin.rb +43 -0
  7. data/lib/space/action/development.rb +56 -0
  8. data/lib/space/{app → action}/handler.rb +17 -9
  9. data/lib/space/{app → action}/parser.rb +4 -7
  10. data/lib/space/app.rb +14 -30
  11. data/lib/space/events.rb +27 -20
  12. data/lib/space/events/sources.rb +34 -0
  13. data/lib/space/events/subscription.rb +23 -0
  14. data/lib/space/logger.rb +34 -0
  15. data/lib/space/model.rb +7 -0
  16. data/lib/space/{models → model}/project.rb +4 -10
  17. data/lib/space/{models → model}/project/bundler.rb +7 -8
  18. data/lib/space/model/project/bundler/config.rb +30 -0
  19. data/lib/space/model/repo.rb +38 -0
  20. data/lib/space/{models → model}/repo/bundle.rb +6 -7
  21. data/lib/space/{models → model}/repo/dependency.rb +1 -1
  22. data/lib/space/{models → model}/repo/git.rb +14 -16
  23. data/lib/space/{models → model}/repos.rb +18 -9
  24. data/lib/space/{models → model}/repos/collection.rb +1 -1
  25. data/lib/space/{models → model}/repos/scope.rb +1 -1
  26. data/lib/space/screen.rb +28 -11
  27. data/lib/space/screen/dashboard.rb +21 -5
  28. data/lib/space/screen/progress.rb +16 -5
  29. data/lib/space/screen/view.rb +2 -6
  30. data/lib/space/source.rb +51 -0
  31. data/lib/space/source/command.rb +70 -0
  32. data/lib/space/source/watch.rb +64 -0
  33. data/lib/space/source/watcher.rb +32 -0
  34. data/lib/space/version.rb +1 -1
  35. metadata +27 -24
  36. data/lib/space/app/command.rb +0 -45
  37. data/lib/space/app/command/builtin.rb +0 -43
  38. data/lib/space/app/command/development.rb +0 -60
  39. data/lib/space/app/logger.rb +0 -21
  40. data/lib/space/events/buffer.rb +0 -18
  41. data/lib/space/events/event.rb +0 -14
  42. data/lib/space/models.rb +0 -7
  43. data/lib/space/models/repo.rb +0 -57
  44. data/lib/space/shell.rb +0 -56
  45. data/lib/space/shell/command.rb +0 -63
  46. data/lib/space/shell/watch.rb +0 -50
  47. data/lib/space/shell/watcher.rb +0 -40
data/bin/space CHANGED
@@ -5,4 +5,10 @@ require 'bundler/setup'
5
5
  require 'space'
6
6
 
7
7
  abort 'Need to specify a project name' if ARGV.empty?
8
+
9
+ paths = Dir[File.expand_path('lib/**/*.rb')]
10
+ paths.each do |path|
11
+ require path
12
+ end
13
+
8
14
  Space::App.new(ARGV[0]).run
@@ -0,0 +1,7 @@
1
+ require 'ansi/core'
2
+
3
+ class String
4
+ def deansi
5
+ gsub(ANSI::Code::PATTERN, '')
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def demodulize
3
+ split('::').last
4
+ end unless method_defined?(:demodulize)
5
+ end
@@ -2,14 +2,14 @@ require 'yaml'
2
2
  require 'hashr'
3
3
 
4
4
  module Space
5
- # autoload :Action, 'space/action'
5
+ autoload :Action, 'space/action'
6
6
  autoload :App, 'space/app'
7
7
  autoload :Config, 'space/config'
8
8
  autoload :Events, 'space/events'
9
9
  autoload :Helpers, 'space/helpers'
10
- autoload :Models, 'space/models'
10
+ autoload :Logger, 'space/logger'
11
+ autoload :Model, 'space/model'
11
12
  autoload :Screen, 'space/screen'
12
- autoload :Shell, 'space/shell'
13
+ autoload :Source, 'space/source'
13
14
  autoload :Tmux, 'space/tmux'
14
15
  end
15
-
@@ -0,0 +1,43 @@
1
+ module Space
2
+ class Action
3
+ autoload :Handler, 'space/action/handler'
4
+ autoload :Parser, 'space/action/parser'
5
+
6
+ autoload :Execute, 'space/action/builtin'
7
+ autoload :Refresh, 'space/action/builtin'
8
+ autoload :Scope, 'space/action/builtin'
9
+ autoload :Unscope, 'space/action/builtin'
10
+
11
+ autoload :Local, 'space/action/development'
12
+ autoload :Remote, 'space/action/development'
13
+
14
+ attr_reader :project, :scope, :args
15
+
16
+ def initialize(project, scope, *args)
17
+ @project = project
18
+ @scope = scope
19
+ @args = args
20
+ log "ACTION #{self.class.name.demodulize} (#{scope.map(&:name).inspect})"
21
+ end
22
+
23
+ def run
24
+ raise 'not implemented'
25
+ end
26
+
27
+ private
28
+
29
+ def in_scope
30
+ scope.each { |repo| yield repo }
31
+ end
32
+
33
+ def system(cmd)
34
+ puts cmd
35
+ super
36
+ end
37
+
38
+ def confirm
39
+ puts "--- hit any key to continue ---\n"
40
+ STDIN.getc
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ require 'ansi/core'
2
+
3
+ module Space
4
+ class Action
5
+ class Execute < Action
6
+ def run
7
+ Events.sources.registered do
8
+ in_scope do |repo|
9
+ Dir.chdir(repo.path) do
10
+ puts "in #{repo.path}\n".ansi(:bold, :green)
11
+ system(*args)
12
+ puts
13
+ end
14
+ end
15
+ confirm
16
+ end
17
+ end
18
+ end
19
+
20
+ class Refresh < Action
21
+ def run
22
+ project.bundler.refresh
23
+ in_scope do |repo|
24
+ repo.refresh
25
+ end
26
+ end
27
+ end
28
+
29
+ class Scope < Action
30
+ def run
31
+ project.repos.scope = scope
32
+ Events.notify(:finish)
33
+ end
34
+ end
35
+
36
+ class Unscope < Action
37
+ def run
38
+ project.repos.scope = nil
39
+ Events.notify(:finish)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,56 @@
1
+ module Space
2
+ class Action
3
+ class Local < Action
4
+ def run
5
+ Events.sources.registered do
6
+ scope.each do |repo|
7
+ system "bundle config --global local.#{repo.name} #{repo.path}"
8
+ end
9
+ sleep 0.2 # not perfect, but fsevent is too slow to trigger
10
+ end
11
+ end
12
+ end
13
+
14
+ class Remote < Action
15
+ def run
16
+ Events.sources.registered do
17
+ scope.each do |repo|
18
+ system "bundle config --delete local.#{repo.name}"
19
+ end
20
+ sleep 0.2
21
+ end
22
+ end
23
+ end
24
+
25
+ # class Install < Action
26
+ # def run
27
+ # in_scope do |repo|
28
+ # repo.execute 'bundle install'
29
+ # repo.refresh
30
+ # end
31
+ # end
32
+ # end
33
+
34
+ # class Update < Action
35
+ # def run
36
+ # in_scope do |repo|
37
+ # repo.execute 'bundle update'
38
+ # repo.execute 'git commit -am "bump dependencies"'
39
+ # repo.refresh
40
+ # end
41
+ # end
42
+ # end
43
+
44
+ # class Checkout < Action
45
+ # def run
46
+ # # check if branch exists, git co (-b)
47
+ # end
48
+ # end
49
+
50
+ # class PullDeps < Action
51
+ # def run
52
+ # # pull all dependencies
53
+ # end
54
+ # end
55
+ end
56
+ end
@@ -1,5 +1,7 @@
1
+ require 'core_ext/string/demodulize'
2
+
1
3
  module Space
2
- class App
4
+ class Action
3
5
  class Handler
4
6
  ALIASES = {
5
7
  '' => 'scope',
@@ -14,27 +16,29 @@ module Space
14
16
 
15
17
  def run(line)
16
18
  scope, type = parse(line)
17
- command = command_for(scope, type)
18
- command.run
19
+ action = action_for(scope, type)
20
+ action.run
21
+ Events.flush
19
22
  end
20
23
 
21
24
  private
22
25
 
23
- def command_for(scope, type)
26
+ def action_for(scope, type)
24
27
  const = const_for(type)
25
- args = [project, scope]
26
- args << type if const == Command::Execute
28
+ repos = repos_for(scope)
29
+ args = [project, repos]
30
+ args << type if const == Action::Execute
27
31
  const.new(*args)
28
32
  end
29
33
 
30
34
  def parse(line)
31
- Parser.new(project.names).parse(line)
35
+ Parser.new(project.repos.names).parse(line)
32
36
  end
33
37
 
34
38
  def const_for(type)
35
- Command.const_get(const_name(type))
39
+ Action.const_get(const_name(type))
36
40
  rescue NameError
37
- Command::Execute
41
+ Action::Execute
38
42
  end
39
43
 
40
44
  def const_name(type)
@@ -42,6 +46,10 @@ module Space
42
46
  type = ALIASES[type] if ALIASES.key?(type)
43
47
  type.capitalize
44
48
  end
49
+
50
+ def repos_for(scope)
51
+ scope ? project.repos.select_by_names_or_numbers(scope) : project.repos.scope.self_and_deps
52
+ end
45
53
  end
46
54
  end
47
55
  end
@@ -1,5 +1,5 @@
1
1
  module Space
2
- class App
2
+ class Action
3
3
  class Parser
4
4
  attr_reader :names, :line
5
5
 
@@ -11,7 +11,7 @@ module Space
11
11
  @line = line
12
12
  scope = parse_scope
13
13
  command = parse_command
14
- [scope || names, command]
14
+ [scope, command]
15
15
  end
16
16
 
17
17
  private
@@ -19,7 +19,7 @@ module Space
19
19
  def parse_scope
20
20
  scope = []
21
21
  pattern = /^(#{names.join('|')}|\d+)\s*/
22
- line.gsub!(pattern) { |repo| scope << resolve(repo.strip); '' } while line =~ pattern
22
+ line.gsub!(pattern) { |repo| scope << repo.strip; '' } while line =~ pattern
23
23
  line.strip!
24
24
  scope unless scope.empty?
25
25
  end
@@ -28,11 +28,8 @@ module Space
28
28
  line.strip
29
29
  line unless line.empty?
30
30
  end
31
-
32
- def resolve(repo)
33
- repo =~ /^\d+$/ ? names[repo.to_i - 1] : repo
34
- end
35
31
  end
36
32
  end
37
33
  end
38
34
 
35
+
@@ -1,55 +1,40 @@
1
+ require 'space/logger'
1
2
  require 'readline'
3
+ require 'thread'
2
4
 
3
5
  module Space
4
6
  class App
5
- autoload :Command, 'space/app/command'
6
- autoload :Handler, 'space/app/handler'
7
- autoload :Logger, 'space/app/logger'
8
- autoload :Parser, 'space/app/parser'
9
-
10
- class << self
11
- def logger
12
- @logger ||= Logger.new
13
- end
14
- end
15
-
16
- include Readline
17
-
18
7
  attr_reader :name, :project, :screen
19
8
 
20
9
  def initialize(name)
21
10
  @name = name
22
- @project = Models::Project.new(name)
11
+ @project = Model::Project.new(name)
23
12
  @screen = Screen.new(project)
24
-
25
- project.subscribe(screen)
26
13
  end
27
14
 
28
15
  def run
29
- refresh
30
- screen.display(:dashboard)
16
+ screen.display
17
+ project.refresh
31
18
  cli_loop
19
+ # Thread.new(&method(:cli_loop))
20
+ # sleep
21
+ puts
32
22
  end
33
23
 
34
24
  private
35
25
 
36
- def refresh
37
- screen.display(:progress)
38
- project.refresh
39
- end
40
-
41
26
  def cli_loop
42
27
  loop do
43
- line = readline(prompt, true)
44
- break if line.nil?
45
- handle(line) unless line.empty?
28
+ print "\e[3;0H"
29
+ line = Readline.readline(prompt, true) || break
30
+ handle(line)
46
31
  end
32
+ rescue Exception => e
33
+ log e.message, e.backtrace
47
34
  end
48
35
 
49
36
  def handle(line)
50
- screen.display(:progress)
51
- Handler.new(project).run(line)
52
- screen.display(:dashboard)
37
+ Action::Handler.new(project).run(line) unless line.empty?
53
38
  end
54
39
 
55
40
  def prompt
@@ -57,4 +42,3 @@ module Space
57
42
  end
58
43
  end
59
44
  end
60
-
@@ -1,34 +1,41 @@
1
1
  module Space
2
2
  module Events
3
- autoload :Buffer, 'space/events/buffer'
4
- autoload :Event, 'space/events/event'
3
+ autoload :Subscription, 'space/events/subscription'
4
+ autoload :Sources, 'space/events/sources'
5
5
 
6
- attr_reader :buffer
6
+ class << self
7
+ def sources
8
+ @sources ||= Sources.new(self)
9
+ end
7
10
 
8
- def buffering
9
- @buffer = Buffer.new
10
- yield.tap do
11
- buffer, @buffer = @buffer, nil
12
- buffer.flush
11
+ def subscriptions
12
+ @subscriptions ||= []
13
13
  end
14
- end
15
14
 
16
- def buffering?
17
- !!@buffer
18
- end
15
+ def events
16
+ @events ||= []
17
+ end
19
18
 
20
- def observers
21
- @observers ||= []
22
- end
19
+ def subscribe(observer, *types)
20
+ subscriptions << Subscription.new(observer, types)
21
+ end
22
+
23
+ def flush
24
+ event = events.first
25
+ events.clear
26
+ notify(event, false) if event
27
+ end
23
28
 
24
- def subscribe(observer)
25
- observers << observer
29
+ def notify(event)
30
+ # log event
31
+ subscriptions.each do |subscription|
32
+ subscription.notify(event)
33
+ end
34
+ end
26
35
  end
27
36
 
28
37
  def notify(*args)
29
- event = args.first.is_a?(Event) ? args.first : Event.new(self, *args)
30
- App.logger.debug "Event on #{self.class.name.split('::').last}: #{event.source.class.name.split('::').last} #{event.event.inspect}"
31
- buffering? ? buffer.push(event) : observers.each { |observer| observer.notify(event) }
38
+ Events.notify(*args)
32
39
  end
33
40
  end
34
41
  end
@@ -0,0 +1,34 @@
1
+ module Space
2
+ module Events
3
+ class Sources
4
+ attr_reader :events, :sources
5
+
6
+ def initialize(events)
7
+ @events = events
8
+ @sources = []
9
+ end
10
+
11
+ def registered
12
+ register(Thread.current.object_id)
13
+ yield.tap do
14
+ unregister(Thread.current.object_id)
15
+ end
16
+ end
17
+
18
+ def register(source)
19
+ Thread.exclusive do
20
+ events.notify(:start) if sources.empty?
21
+ sources << source
22
+ end
23
+ end
24
+
25
+ def unregister(source)
26
+ Thread.exclusive do
27
+ sources.delete(source)
28
+ events.notify(:finish) if sources.empty?
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+