space 0.0.3 → 0.0.4
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.
- 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
|