space 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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
+