space 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +17 -2
- data/Guardfile +5 -0
- data/README.md +4 -0
- data/Rakefile +1 -1
- data/bin/space +2 -1
- data/lib/core_ext/{enumerable.rb → enumerable/map_slice.rb} +2 -7
- data/lib/core_ext/{string.rb → string/wrap.rb} +1 -2
- data/lib/space.rb +6 -16
- data/lib/space/app.rb +36 -48
- data/lib/space/app/command.rb +45 -0
- data/lib/space/app/command/builtin.rb +43 -0
- data/lib/space/app/command/development.rb +60 -0
- data/lib/space/app/handler.rb +47 -0
- data/lib/space/app/logger.rb +21 -0
- data/lib/space/{action → app}/parser.rb +3 -2
- data/lib/space/config.rb +14 -6
- data/lib/space/events.rb +34 -0
- data/lib/space/events/buffer.rb +18 -0
- data/lib/space/events/event.rb +14 -0
- data/lib/space/helpers.rb +30 -15
- data/lib/space/models.rb +7 -0
- data/lib/space/models/project.rb +48 -0
- data/lib/space/models/project/bundler.rb +30 -0
- data/lib/space/models/repo.rb +46 -29
- data/lib/space/models/repo/bundle.rb +39 -0
- data/lib/space/models/repo/dependency.rb +22 -0
- data/lib/space/models/repo/git.rb +52 -0
- data/lib/space/models/repos.rb +31 -26
- data/lib/space/models/repos/collection.rb +26 -0
- data/lib/space/models/repos/scope.rb +18 -0
- data/lib/space/screen.rb +19 -15
- data/lib/space/screen/dashboard.rb +28 -0
- data/lib/space/screen/progress.rb +15 -0
- data/lib/space/screen/view.rb +43 -0
- data/lib/space/shell.rb +56 -0
- data/lib/space/shell/command.rb +63 -0
- data/lib/space/shell/watch.rb +50 -0
- data/lib/space/shell/watcher.rb +40 -0
- data/lib/space/templates/{project.erb → header.erb} +0 -1
- data/lib/space/templates/{repository.erb → repo.erb} +1 -1
- data/lib/space/tmux.rb +11 -0
- data/lib/space/version.rb +1 -1
- metadata +33 -15
- data/lib/space/action.rb +0 -84
- data/lib/space/models/bundle.rb +0 -44
- data/lib/space/models/command.rb +0 -28
- data/lib/space/models/commands.rb +0 -23
- data/lib/space/models/dependency.rb +0 -18
- data/lib/space/models/git.rb +0 -23
- data/lib/space/view.rb +0 -25
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Space
|
5
|
+
class App
|
6
|
+
class Logger < ::Logger
|
7
|
+
def initialize
|
8
|
+
truncate
|
9
|
+
super('/tmp/space.log')
|
10
|
+
end
|
11
|
+
|
12
|
+
def truncate
|
13
|
+
File.open(filename, 'w+') { |f| f.write('-' * 80 + "\n") }
|
14
|
+
end
|
15
|
+
|
16
|
+
def filename
|
17
|
+
'/tmp/space.log'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Space
|
2
|
-
class
|
2
|
+
class App
|
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, command]
|
14
|
+
[scope || names, command]
|
15
15
|
end
|
16
16
|
|
17
17
|
private
|
@@ -35,3 +35,4 @@ module Space
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
data/lib/space/config.rb
CHANGED
@@ -2,15 +2,23 @@ module Space
|
|
2
2
|
class Config < Hashr
|
3
3
|
class << self
|
4
4
|
def load(name)
|
5
|
-
|
6
|
-
unless path = paths.detect { |path| File.exists?(path) }
|
7
|
-
puts("Could not find #{name}.yml at either of ~/.space/#{name}.yml and ./.#{name}.yml")
|
8
|
-
exit
|
9
|
-
end
|
10
|
-
new(YAML.load(File.read(path)))
|
5
|
+
new(YAML.load(File.read(path(name))))
|
11
6
|
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def path(name)
|
11
|
+
path = paths(name).detect { |path| File.exists?(path) }
|
12
|
+
path || raise("Could not find #{name}.yml at either of ~/.space/#{name}.yml and ./.space/#{name}.yml")
|
13
|
+
end
|
14
|
+
|
15
|
+
def paths(name)
|
16
|
+
%w(. ~).map { |path| File.expand_path("#{path}/.space/#{name}.yml") }
|
17
|
+
end
|
12
18
|
end
|
13
19
|
|
20
|
+
define :template_dir => File.expand_path('../templates', __FILE__)
|
21
|
+
|
14
22
|
def paths
|
15
23
|
@paths ||= repositories.map { |path| base_dir ? "#{base_dir}/#{path}" : path }
|
16
24
|
end
|
data/lib/space/events.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Space
|
2
|
+
module Events
|
3
|
+
autoload :Buffer, 'space/events/buffer'
|
4
|
+
autoload :Event, 'space/events/event'
|
5
|
+
|
6
|
+
attr_reader :buffer
|
7
|
+
|
8
|
+
def buffering
|
9
|
+
@buffer = Buffer.new
|
10
|
+
yield.tap do
|
11
|
+
buffer, @buffer = @buffer, nil
|
12
|
+
buffer.flush
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def buffering?
|
17
|
+
!!@buffer
|
18
|
+
end
|
19
|
+
|
20
|
+
def observers
|
21
|
+
@observers ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def subscribe(observer)
|
25
|
+
observers << observer
|
26
|
+
end
|
27
|
+
|
28
|
+
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) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Space
|
2
|
+
module Events
|
3
|
+
class Buffer < Array
|
4
|
+
def push(event)
|
5
|
+
# if any? { |e| e.source == event.source }
|
6
|
+
# App.logger.debug("REJECT event #{event.event.inspect} on #{event.source.class.name.split("\\n").last}")
|
7
|
+
# else
|
8
|
+
super
|
9
|
+
# end
|
10
|
+
end
|
11
|
+
|
12
|
+
def flush
|
13
|
+
each { |event| event.source.notify(*event) }
|
14
|
+
clear
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/space/helpers.rb
CHANGED
@@ -1,25 +1,44 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'ansi/core'
|
3
|
-
require 'core_ext/string'
|
3
|
+
require 'core_ext/string/wrap'
|
4
4
|
|
5
5
|
module Space
|
6
6
|
module Helpers
|
7
7
|
def project_title
|
8
|
-
"Project: #{
|
8
|
+
"Project: #{name}".ansi(:bold)
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def tableize(string)
|
12
|
+
string.split(' ')
|
13
|
+
project.local_repos.join(', ')
|
14
|
+
end
|
15
|
+
|
16
|
+
def repo_name
|
17
|
+
repo.name.ansi(:bold)
|
18
|
+
end
|
19
|
+
|
20
|
+
def repo_status
|
21
|
+
[git.branch, git.commit, repo_local].compact.join(', ')
|
22
|
+
end
|
23
|
+
|
24
|
+
def repo_local
|
25
|
+
'L'.ansi(:bold, :red) if repo_local?
|
26
|
+
end
|
27
|
+
|
28
|
+
def repo_local?
|
29
|
+
project.local_repos.include?(repo.name)
|
15
30
|
end
|
16
31
|
|
17
32
|
def repo_selected?
|
18
|
-
|
33
|
+
repos.scoped? && repos.scope.include?(repo)
|
19
34
|
end
|
20
35
|
|
21
36
|
def git_status
|
22
|
-
"Git: #{format_boolean(git.clean?)}"
|
37
|
+
"Git: #{format_boolean(git.clean?)}#{git_ahead if git.ahead?}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def git_ahead
|
41
|
+
" #{git.ahead} commit#{'s' if git.ahead > 1} ahead".ansi(:yellow)
|
23
42
|
end
|
24
43
|
|
25
44
|
def bundle_status
|
@@ -34,20 +53,16 @@ module Space
|
|
34
53
|
bundle.deps.map { |dep| "• #{dep.ref} #{format_boolean(dep.fresh?)} #{dep.name}" }.join("\n")
|
35
54
|
end
|
36
55
|
|
37
|
-
def bundle_local
|
38
|
-
repos = bundle.local_repos
|
39
|
-
"\nLocal: #{repos.join(', ')}\n" unless repos.empty?
|
40
|
-
end
|
41
|
-
|
42
56
|
def format_boolean(value)
|
43
57
|
value ? '✔'.ansi(:green, :bold) : '⚡'.ansi(:red, :bold)
|
44
58
|
end
|
45
59
|
|
46
|
-
def i(string)
|
60
|
+
def i(string, width = 2)
|
47
61
|
lines = string.split("\n")
|
48
62
|
lines = lines.map { |line| line.wrap(80).split("\n") }.flatten
|
49
|
-
lines = lines.map { |line|
|
63
|
+
lines = lines.map { |line| [' ' * width, line].join }
|
50
64
|
lines.join("\n")
|
51
65
|
end
|
52
66
|
end
|
53
67
|
end
|
68
|
+
|
data/lib/space/models.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Space
|
2
|
+
module Models
|
3
|
+
class Project
|
4
|
+
include Events
|
5
|
+
|
6
|
+
autoload :Bundler, 'space/models/project/bundler'
|
7
|
+
|
8
|
+
attr_reader :name, :repos, :bundler, :config
|
9
|
+
|
10
|
+
def initialize(name)
|
11
|
+
@name = name
|
12
|
+
@config = Config.load(name)
|
13
|
+
@repos = Repos.new(self, config.paths)
|
14
|
+
@bundler = Bundler.new(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
def local_repos
|
18
|
+
bundler.config.keys.map do |key|
|
19
|
+
key =~ /^local\.(.+)$/
|
20
|
+
$1 if repos.names.include?($1)
|
21
|
+
end.compact
|
22
|
+
end
|
23
|
+
|
24
|
+
def names
|
25
|
+
@names ||= Tmux.windows || repos.names
|
26
|
+
end
|
27
|
+
|
28
|
+
def number(name)
|
29
|
+
if number = names.index(name)
|
30
|
+
number + 1
|
31
|
+
else
|
32
|
+
names << name
|
33
|
+
number(name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def refresh
|
38
|
+
bundler.refresh
|
39
|
+
repos.all.each(&:refresh)
|
40
|
+
end
|
41
|
+
|
42
|
+
def subscribe(*args)
|
43
|
+
super
|
44
|
+
[bundler, repos].each { |object| object.subscribe(self) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'core_ext/enumerable/map_slice'
|
2
|
+
|
3
|
+
module Space
|
4
|
+
module Models
|
5
|
+
class Project
|
6
|
+
class Bundler
|
7
|
+
include Events, Shell
|
8
|
+
|
9
|
+
commands config: 'bundle config'
|
10
|
+
|
11
|
+
watch '~/.bundle/config'
|
12
|
+
|
13
|
+
attr_reader :project
|
14
|
+
|
15
|
+
def initialize(project)
|
16
|
+
@project = project
|
17
|
+
super()
|
18
|
+
end
|
19
|
+
|
20
|
+
def config
|
21
|
+
lines = result(:config).split("\n")[2..-1] || []
|
22
|
+
values = lines.map_slice(3) do |name, value, _|
|
23
|
+
[name, value =~ /: "(.*)"/ && $1]
|
24
|
+
end
|
25
|
+
Hash[*values.compact.flatten]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/space/models/repo.rb
CHANGED
@@ -1,40 +1,57 @@
|
|
1
1
|
module Space
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
@path = File.expand_path(path)
|
8
|
-
@git = Git.new(path)
|
9
|
-
@bundle = Bundle.new(path)
|
10
|
-
end
|
2
|
+
module Models
|
3
|
+
class Repo
|
4
|
+
autoload :Bundle, 'space/models/repo/bundle'
|
5
|
+
autoload :Dependency, 'space/models/repo/dependency'
|
6
|
+
autoload :Git, 'space/models/repo/git'
|
11
7
|
|
12
|
-
|
13
|
-
@name ||= File.basename(path)
|
14
|
-
end
|
8
|
+
include Events
|
15
9
|
|
16
|
-
|
17
|
-
git.commit
|
18
|
-
end
|
10
|
+
attr_reader :project, :path, :git, :bundle
|
19
11
|
|
20
|
-
|
21
|
-
|
22
|
-
|
12
|
+
def initialize(project, path)
|
13
|
+
@project = project
|
14
|
+
@path = File.expand_path(path)
|
15
|
+
@git = Git.new(self)
|
16
|
+
@bundle = Bundle.new(self, project.repos)
|
17
|
+
end
|
23
18
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
19
|
+
def name
|
20
|
+
@name ||= File.basename(path)
|
21
|
+
end
|
28
22
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
def number
|
24
|
+
@number ||= project.number(name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def ref
|
28
|
+
git.commit
|
33
29
|
end
|
34
|
-
end
|
35
30
|
|
36
|
-
|
37
|
-
|
31
|
+
def deps
|
32
|
+
bundle.deps
|
33
|
+
end
|
34
|
+
|
35
|
+
def refresh
|
36
|
+
git.refresh
|
37
|
+
bundle.refresh
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute(cmd)
|
41
|
+
chdir do
|
42
|
+
puts "in #{path}".ansi(:bold, :yellow)
|
43
|
+
system(cmd)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def chdir(&block)
|
48
|
+
Dir.chdir(path, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def subscribe(*args)
|
52
|
+
super
|
53
|
+
[git, bundle].each { |object| object.subscribe(self) }
|
54
|
+
end
|
38
55
|
end
|
39
56
|
end
|
40
57
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'observer'
|
2
|
+
|
3
|
+
module Space
|
4
|
+
module Models
|
5
|
+
class Repo
|
6
|
+
class Bundle
|
7
|
+
include Events, Shell
|
8
|
+
|
9
|
+
commands check: 'bundle check',
|
10
|
+
list: 'bundle list'
|
11
|
+
|
12
|
+
watch 'Gemfile',
|
13
|
+
'Gemfile.lock'
|
14
|
+
|
15
|
+
attr_reader :repo, :repos
|
16
|
+
|
17
|
+
def initialize(repo, repos)
|
18
|
+
@repo = repo
|
19
|
+
@repos = repos
|
20
|
+
super(repo.path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def clean?
|
24
|
+
info =~ /dependencies are satisfied/
|
25
|
+
end
|
26
|
+
|
27
|
+
def info
|
28
|
+
result(:check).split("\n").first
|
29
|
+
end
|
30
|
+
|
31
|
+
def deps
|
32
|
+
result(:list).scan(/\* ([\w-]+) \(.* ([\d|\w]+)\)/).map do |name, ref|
|
33
|
+
Dependency.new(repos.find_by_name(name), ref) if repos.names.include?(name)
|
34
|
+
end.compact
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Space
|
2
|
+
module Models
|
3
|
+
class Repo
|
4
|
+
class Dependency
|
5
|
+
attr_reader :repo, :ref
|
6
|
+
|
7
|
+
def initialize(repo, ref)
|
8
|
+
@repo = repo
|
9
|
+
@ref = ref
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
repo.name
|
14
|
+
end
|
15
|
+
|
16
|
+
def fresh?
|
17
|
+
repo.ref == ref
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|