MrMurano 1.0.5 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30d48034f5391a6edaca9fbe64b6615b5d3224fa
4
- data.tar.gz: f60967a24c13ba28b07e54d6c86bf5132be0017d
3
+ metadata.gz: 551631f8375cdb4352643781c4c47b7c1c4ec219
4
+ data.tar.gz: 7e341a608f0539f3b367ba5d0fd3e95dd4f15f84
5
5
  SHA512:
6
- metadata.gz: 99a4c4bac57e8b288615b37f45e13e130818d8a5fe8b1022eca162d2e00763af5e690c90d94c51ec3938745cd232a01e44bfb3312d94f971f0b4052ec05c1cbf
7
- data.tar.gz: f15d2379a7c6ac706dfc78c7b70eff1d5816345ff5dcba6a7a1b180f795a8960880822b0b62362877e9b708e647db0a86294b5f3e04c1d8eae63785836477a70
6
+ metadata.gz: d31e0375a7d1c2ba7a27acba8bc30d2c03f780bba0ededa5a0648b8e257e19899b91121c862bd2209c838b099a65c0578d55f06729cf0a776655f539f901491c
7
+ data.tar.gz: 55883ceda28d17b8bd6f72947c68cc59084e56f9d8d858b8036a4c9dda29728e3ddb7a6254778afe8a1e0c1b85f125f326f2c8895a3167191a02078ba3f3c16d
data/README.markdown CHANGED
@@ -10,6 +10,7 @@ To start from an existing project in Murano
10
10
  ```
11
11
  mkdir myproject
12
12
  cd myproject
13
+ mr config solution.id XXXXXX
13
14
  mr syncdown -same
14
15
  ```
15
16
 
@@ -23,5 +24,32 @@ Then deploy `mr syncup -same`
23
24
  ```
24
25
  > gem install MrMurano
25
26
  ```
27
+ Or
28
+ ```
29
+ > gem update MrMurano
30
+ ```
31
+
32
+ ## Features
33
+
34
+ ### Sub-directories
35
+
36
+ For the endpoints, modules, and eventhandlers directories. The can contain both
37
+ files or a sub-directory of files. This allows for keeping common things grouped
38
+ together. Or adding a git submodule in to manage reusable chunks.
39
+
40
+
41
+
42
+ ### Bundles
43
+
44
+ MrMuanro allows adding bundles of resources to your project.
45
+
46
+ A Bundle is a group of modules, endpoints, and static files.
47
+
48
+ Bundles live in the 'bundle' directory. Each bundle is a directory that matches
49
+ the layout of a project. (with directories for endpoints, modules, files, etc)
50
+
51
+ The items in bundles are layered by sorting the bundle names. Then your project's
52
+ items are layered on top. This builds the list of what is synced. It also allows
53
+ you to override things that are in a bundle from you project.
26
54
 
27
55
 
data/TODO.taskpaper CHANGED
@@ -1,12 +1,12 @@
1
1
 
2
2
  Commands:
3
- - First time run needs to be smoothed out.
4
3
  - Status will show things have changes when they don’t.
4
+ - First time run needs to be smoothed out. @done(2016-08-09)
5
5
  - Default for most commands should be -same @done(2016-08-02)
6
6
  - Add Diff Command @done(2016-07-27)
7
7
 
8
8
  Account:
9
- - Netrc library (or the netrc format) doesn't allow '#' in passwords.
9
+ - Netrc library (or the netrc format) doesn't allow '#' in passwords. @done(2016-08-10)
10
10
 
11
11
  Endpoints:
12
12
  - Add support for multiple endpoints in one file (maybe)
@@ -37,7 +37,8 @@ SolutionBase:
37
37
  - Rebuild how local names and paths are computed from remote items. @done(2016-07-27)
38
38
 
39
39
  Bundles:
40
- - Work on design
40
+ - Test syncdown behavor.
41
+ - Work on design @done(2016-08-09)
41
42
  Thinking of something like VIM bundles. A directory of directories. Each with a
42
43
  manafest file? (maybe) A Bundle is a group of modules, endpoints, static files
43
44
  and the other things.
@@ -1,12 +1,55 @@
1
- require 'netrc'
2
1
  require 'uri'
3
2
  require 'net/http'
4
3
  require 'json'
5
4
  require 'date'
6
5
  require 'pp'
7
6
  require 'terminal-table'
7
+ require 'pathname'
8
+ require 'yaml'
8
9
 
9
10
  module MrMurano
11
+ class Passwords
12
+ def initialize(path)
13
+ path = Pathname.new(path) unless path.kind_of? Pathname
14
+ @path = path
15
+ @data = nil
16
+ end
17
+ def load()
18
+ if @path.exist? then
19
+ @path.chmod(0600)
20
+ @path.open('rb') do |io|
21
+ @data = YAML.load(io)
22
+ end
23
+ end
24
+ end
25
+ def save()
26
+ @path.open('wb') do |io|
27
+ io << @data.to_yaml
28
+ end
29
+ @path.chmod(0600)
30
+ end
31
+ def set(host, user, pass)
32
+ unless @data.kind_of? Hash then
33
+ @data = {host=>{user=>pass}}
34
+ return
35
+ end
36
+ hd = @data[host]
37
+ if hd.nil? or not hd.kind_of?(Hash) then
38
+ hd = {user=>pass}
39
+ return
40
+ end
41
+ hd[user] = pass
42
+ return
43
+ end
44
+ def get(host, user)
45
+ return nil unless @data.kind_of? Hash
46
+ return nil unless @data.has_key? host
47
+ return nil unless @data[host].kind_of? Hash
48
+ return nil unless @data[host].has_key? user
49
+ return @data[host][user]
50
+ end
51
+ end
52
+
10
53
  class Account
11
54
 
12
55
 
@@ -21,21 +64,14 @@ module MrMurano
21
64
  user = ask("Account name: ")
22
65
  $cfg.set('user.name', user, :user)
23
66
  end
24
- # Maybe in the future use Keychain. For now all in Netrc.
25
- # if (/darwin/ =~ RUBY_PLATFORM) != nil then
26
- # # macOS
27
- # pws = `security 2>&1 >/dev/null find-internet-password -gs "#{host}" -a "#{user}"`
28
- # pws.strip!
29
- # pws.sub!(/^password: "(.*)"$/, '\1')
30
- # return pws
31
- # Use Netrc
32
- nrc = Netrc.read
33
- ruser, pws = nrc[host]
34
- pws = nil unless ruser == user
67
+ pff = Pathname.new(ENV['HOME']) + '.mrmurano/passwords'
68
+ pf = Passwords.new(pff)
69
+ pf.load
70
+ pws = pf.get(host, user)
35
71
  if pws.nil? then
36
72
  pws = ask("Password: ") { |q| q.echo = "*" }
37
- nrc[host] = user, pws
38
- nrc.save
73
+ pf.set(host, user, pws)
74
+ pf.save
39
75
  end
40
76
  {
41
77
  :email => $cfg['user.name'],
@@ -9,6 +9,7 @@ module MrMurano
9
9
  def initialize
10
10
  super
11
11
  @uriparts << 'endpoint'
12
+ @location = $cfg['location.endpoints']
12
13
  end
13
14
 
14
15
  ##
@@ -80,7 +81,7 @@ module MrMurano
80
81
  name << '.lua'
81
82
  end
82
83
 
83
- def toremotename(from, path)
84
+ def toRemoteItem(from, path)
84
85
  # read first line of file and get method/path from it?
85
86
  path = Pathname.new(path) unless path.kind_of? Pathname
86
87
  aheader = path.readlines().first
@@ -12,6 +12,7 @@ module MrMurano
12
12
  super
13
13
  @uriparts << 'file'
14
14
  @itemkey = :path
15
+ @location = $cfg['location.files']
15
16
  end
16
17
 
17
18
  ##
@@ -69,7 +70,8 @@ module MrMurano
69
70
  # Most of these pull into ram. So maybe just go with that. Would guess that
70
71
  # truely large static content is rare, and we can optimize/fix that later.
71
72
 
72
- form = HTTP::FormData.create(:file=>HTTP::FormData::File.new(local.to_s))
73
+ file = HTTP::FormData::File.new(local.to_s, {:mime_type=>remote[:mime_type]})
74
+ form = HTTP::FormData.create(:file=>file)
73
75
  req = Net::HTTP::Put.new(uri)
74
76
  workit(req) do |request,http|
75
77
  request.content_type = form.content_type
@@ -92,8 +94,9 @@ module MrMurano
92
94
  name
93
95
  end
94
96
 
95
- def toremotename(from, path)
96
- name = super(from, path)
97
+ def toRemoteItem(from, path)
98
+ item = super(from, path)
99
+ name = item[:name]
97
100
  name = '/' if name == $cfg['files.default_page']
98
101
  name = "/#{name}" unless name.chars.first == '/'
99
102
 
@@ -113,7 +116,7 @@ module MrMurano
113
116
  itemA[:checksum] != itemB[:checksum])
114
117
  end
115
118
 
116
- def locallist(from)
119
+ def localitems(from)
117
120
  from = Pathname.new(from) unless from.kind_of? Pathname
118
121
  unless from.exist? then
119
122
  return []
@@ -121,14 +124,9 @@ module MrMurano
121
124
  raise "Not a directory: #{from.to_s}" unless from.directory?
122
125
 
123
126
  Pathname.glob(from.to_s + '/**/*').map do |path|
124
- name = toremotename(from, path)
125
- case name
126
- when Hash
127
- name[:local_path] = path
128
- name
129
- else
130
- {:local_path => path, :name => name}
131
- end
127
+ name = toRemoteItem(from, path)
128
+ name[:local_path] = path
129
+ name
132
130
  end
133
131
  end
134
132
 
@@ -94,6 +94,7 @@ module MrMurano
94
94
  super
95
95
  @uriparts << 'library'
96
96
  @itemkey = :alias
97
+ @location = $cfg['location.modules']
97
98
  end
98
99
 
99
100
  def tolocalname(item, key)
@@ -102,7 +103,7 @@ module MrMurano
102
103
  end
103
104
 
104
105
 
105
- def toremotename(from, path)
106
+ def toRemoteItem(from, path)
106
107
  name = path.basename.to_s.sub(/\..*/, '')
107
108
  {:name => name}
108
109
  end
@@ -118,6 +119,7 @@ module MrMurano
118
119
  super
119
120
  @uriparts << 'eventhandler'
120
121
  @itemkey = :alias
122
+ @location = $cfg['location.eventhandlers']
121
123
  end
122
124
 
123
125
  def list
@@ -145,7 +147,7 @@ module MrMurano
145
147
  "#{item[:name]}.lua"
146
148
  end
147
149
 
148
- def toremotename(from, path)
150
+ def toRemoteItem(from, path)
149
151
  path = Pathname.new(path) unless path.kind_of? Pathname
150
152
  aheader = path.readlines().first
151
153
  md = /--#EVENT (\S+) (\S+)/.match(aheader)
@@ -32,7 +32,7 @@ module MrMurano
32
32
  say_error ":: #{response.body}"
33
33
  end
34
34
  end
35
- remote.reject!{|k,v| k==:synckey}
35
+ remote.reject!{|k,v| k==:synckey or k==:bundled}
36
36
  post('/', remote)
37
37
  end
38
38
 
@@ -74,7 +74,7 @@ module MrMurano
74
74
  into
75
75
  end
76
76
 
77
- def locallist(from)
77
+ def localitems(from)
78
78
  from = Pathname.new(from) unless from.kind_of? Pathname
79
79
  if not from.exist? then
80
80
  say_warning "Skipping missing #{from.to_s}"
@@ -90,7 +90,7 @@ module MrMurano
90
90
  from.open {|io| here = YAML.load(io) }
91
91
  here = [] if here == false
92
92
 
93
- here
93
+ here.map{|i| Hash.transform_keys_to_symbols(i)}
94
94
  end
95
95
  end
96
96
 
@@ -100,6 +100,7 @@ module MrMurano
100
100
  super
101
101
  @uriparts << 'role'
102
102
  @itemkey = :role_id
103
+ @location = $cfg['location.roles']
103
104
  end
104
105
  end
105
106
 
@@ -108,6 +109,7 @@ module MrMurano
108
109
  def initialize
109
110
  super
110
111
  @uriparts << 'user'
112
+ @location = $cfg['location.users']
111
113
  end
112
114
 
113
115
  def upload(local, remote)
@@ -14,6 +14,8 @@ module MrMurano
14
14
  raise "No solution!" if @sid.nil?
15
15
  @uriparts = [:solution, @sid]
16
16
  @itemkey = :id
17
+ @locationbase = $cfg['location.base']
18
+ @location = nil
17
19
  end
18
20
 
19
21
  def verbose(msg)
@@ -94,14 +96,14 @@ module MrMurano
94
96
  # …
95
97
 
96
98
  ##
97
- # Compute a remote resource name from the local path
99
+ # Compute a remote item hash from the local path
98
100
  # @param root Pathname: Root path for this resource type from config files
99
101
  # @param path Pathname: Path to local item
100
- # @return String: remote resource name
101
- def toremotename(root, path)
102
+ # @return Hash: hash of the details for the remote item for this path
103
+ def toRemoteItem(root, path)
102
104
  path = Pathname.new(path) unless path.kind_of? Pathname
103
105
  root = Pathname.new(root) unless root.kind_of? Pathname
104
- path.relative_path_from(root).to_s
106
+ {:name => path.relative_path_from(root).to_s}
105
107
  end
106
108
 
107
109
  ##
@@ -129,13 +131,51 @@ module MrMurano
129
131
  dest = into + name
130
132
  end
131
133
 
132
- def locallist(from)
133
- from = Pathname.new(from) unless from.kind_of? Pathname
134
- unless from.exist? then
135
- return []
134
+ ##
135
+ # So, for bundles this needs to look at all the places and build up the mered
136
+ # stack of local items.
137
+ #
138
+ # Which means it needs the from to be split into the base and the sub so we can
139
+ # inject bundle directories.
140
+
141
+ ##
142
+ # Get a list of local items.
143
+ #
144
+ # This collects items in the project and all bundles.
145
+ def locallist()
146
+ # so. if @locationbase/bundles exists
147
+ # gather and merge: @locationbase/bundles/*/@location
148
+ # then merge @locationbase/@location
149
+ #
150
+
151
+ bundleDir = $cfg['location.bundles'] or 'bundles'
152
+ bundleDir = 'bundles' if bundleDir.nil?
153
+ items = {}
154
+ if (@locationbase + bundleDir).directory? then
155
+ (@locationbase + bundleDir).children.sort.each do |bndl|
156
+ if (bndl + @location).exist? then
157
+ verbose("Loading from bundle #{bndl.basename}")
158
+ bitems = localitems(bndl + @location)
159
+ bitems.map!{|b| b[:bundled] = true; b} # mark items from bundles.
160
+
161
+
162
+ # use synckey for quicker merging.
163
+ bitems.each { |b| items[synckey(b)] = b }
164
+ end
165
+ end
136
166
  end
137
- raise "Not a directory: #{from.to_s}" unless from.directory?
167
+ if (@locationbase + @location).exist? then
168
+ bitems = localitems(@locationbase + @location)
169
+ # use synckey for quicker merging.
170
+ bitems.each { |b| items[synckey(b)] = b }
171
+ end
172
+
173
+ items.values
174
+ end
138
175
 
176
+ ##
177
+ # Get a list of local items rooted at #from
178
+ def localitems(from)
139
179
  from.children.map do |path|
140
180
  if path.directory? then
141
181
  # TODO: look for definition. ( ?.rockspec? ?mr.modules? ?mr.manifest? )
@@ -150,14 +190,11 @@ module MrMurano
150
190
  end.select do |path|
151
191
  path.extname == '.lua'
152
192
  end.map do |path|
153
- name = toremotename(from, path)
154
- case name
155
- when Hash
156
- name[:local_path] = path
157
- name
158
- else
159
- {:local_path => path, :name => name}
160
- end
193
+ # sometimes this is a name, sometimes it is an item.
194
+ # do I want to keep that? NO.
195
+ name = toRemoteItem(from, path)
196
+ name[:local_path] = path
197
+ name
161
198
  end
162
199
  end
163
200
 
@@ -167,6 +204,10 @@ module MrMurano
167
204
  end
168
205
 
169
206
  def download(local, item)
207
+ if item[:bundled] then
208
+ say_warning "Not downloading into bundled item #{synckey(item)}"
209
+ return
210
+ end
170
211
  local.dirname.mkpath
171
212
  id = item[@itemkey.to_sym]
172
213
  local.open('wb') do |io|
@@ -180,10 +221,10 @@ module MrMurano
180
221
  dest.unlink
181
222
  end
182
223
 
183
- def syncup(from, options=Commander::Command::Options.new)
224
+ def syncup(options=Commander::Command::Options.new)
184
225
  itemkey = @itemkey.to_sym
185
226
  options.asdown=false
186
- dt = status(from, options)
227
+ dt = status(options)
187
228
  toadd = dt[:toadd]
188
229
  todel = dt[:todel]
189
230
  tomod = dt[:tomod]
@@ -214,9 +255,12 @@ module MrMurano
214
255
  end
215
256
  end
216
257
 
217
- def syncdown(into, options=Commander::Command::Options.new)
258
+ # FIXME this still needs the path passed in.
259
+ # Need to think some more on how syncdown works with bundles.
260
+ def syncdown(options=Commander::Command::Options.new)
218
261
  options.asdown = true
219
- dt = status(into, options)
262
+ dt = status(options)
263
+ into = @locationbase + @location
220
264
  toadd = dt[:toadd]
221
265
  todel = dt[:todel]
222
266
  tomod = dt[:tomod]
@@ -275,9 +319,9 @@ module MrMurano
275
319
  df
276
320
  end
277
321
 
278
- def status(from, options=Commander::Command::Options.new)
322
+ def status(options=Commander::Command::Options.new)
279
323
  there = list()
280
- here = locallist(from)
324
+ here = locallist()
281
325
  itemkey = @itemkey.to_sym
282
326
 
283
327
  therebox = {}
@@ -57,37 +57,37 @@ command :status do |c|
57
57
 
58
58
  if options.endpoints then
59
59
  sol = MrMurano::Endpoint.new
60
- ret = sol.status($cfg['location.base'] + $cfg['location.endpoints'], options)
60
+ ret = sol.status(options)
61
61
  gmerge(ret, 'A', options)
62
62
  end
63
63
 
64
64
  if options.modules then
65
65
  sol = MrMurano::Library.new
66
- ret = sol.status( $cfg['location.base'] + $cfg['location.modules'], options)
66
+ ret = sol.status(options)
67
67
  gmerge(ret, 'M', options)
68
68
  end
69
69
 
70
70
  if options.eventhandlers then
71
71
  sol = MrMurano::EventHandler.new
72
- ret = sol.status( $cfg['location.base'] + $cfg['location.eventhandlers'], options)
72
+ ret = sol.status(options)
73
73
  gmerge(ret, 'E', options)
74
74
  end
75
75
 
76
76
  if options.roles then
77
77
  sol = MrMurano::Role.new
78
- ret = sol.status( $cfg['location.base'] + $cfg['location.roles'], options)
78
+ ret = sol.status(options)
79
79
  gmerge(ret, 'R', options)
80
80
  end
81
81
 
82
82
  if options.users then
83
83
  sol = MrMurano::User.new
84
- ret = sol.status( $cfg['location.base'] + $cfg['location.users'], options)
84
+ ret = sol.status(options)
85
85
  gmerge(ret, 'U', options)
86
86
  end
87
87
 
88
88
  if options.files then
89
89
  sol = MrMurano::File.new
90
- ret = sol.status( $cfg['location.base'] + $cfg['location.files'], options)
90
+ ret = sol.status(options)
91
91
  gmerge(ret, 'S', options)
92
92
  end
93
93
 
data/lib/MrMurano/sync.rb CHANGED
@@ -24,32 +24,32 @@ command :syncdown do |c|
24
24
 
25
25
  if options.endpoints then
26
26
  sol = MrMurano::Endpoint.new
27
- sol.syncdown($cfg['location.base'] + $cfg['location.endpoints'], options)
27
+ sol.syncdown(options)
28
28
  end
29
29
 
30
30
  if options.modules then
31
31
  sol = MrMurano::Library.new
32
- sol.syncdown( $cfg['location.base'] + $cfg['location.modules'], options)
32
+ sol.syncdown(options)
33
33
  end
34
34
 
35
35
  if options.eventhandlers then
36
36
  sol = MrMurano::EventHandler.new
37
- sol.syncdown( $cfg['location.base'] + $cfg['location.eventhandlers'], options)
37
+ sol.syncdown(options)
38
38
  end
39
39
 
40
40
  if options.roles then
41
41
  sol = MrMurano::Role.new
42
- sol.syncdown( $cfg['location.base'] + $cfg['location.roles'], options)
42
+ sol.syncdown(options)
43
43
  end
44
44
 
45
45
  if options.users then
46
46
  sol = MrMurano::User.new
47
- sol.syncdown( $cfg['location.base'] + $cfg['location.users'], options)
47
+ sol.syncdown(options)
48
48
  end
49
49
 
50
50
  if options.files then
51
51
  sol = MrMurano::File.new
52
- sol.syncdown( $cfg['location.base'] + $cfg['location.files'], options)
52
+ sol.syncdown(options)
53
53
  end
54
54
 
55
55
  end
@@ -81,32 +81,32 @@ command :syncup do |c|
81
81
 
82
82
  if options.endpoints then
83
83
  sol = MrMurano::Endpoint.new
84
- sol.syncup($cfg['location.base'] + $cfg['location.endpoints'], options)
84
+ sol.syncup(options)
85
85
  end
86
86
 
87
87
  if options.modules then
88
88
  sol = MrMurano::Library.new
89
- sol.syncup( $cfg['location.base'] + $cfg['location.modules'], options)
89
+ sol.syncup(options)
90
90
  end
91
91
 
92
92
  if options.eventhandlers then
93
93
  sol = MrMurano::EventHandler.new
94
- sol.syncup( $cfg['location.base'] + $cfg['location.eventhandlers'], options)
94
+ sol.syncup(options)
95
95
  end
96
96
 
97
97
  if options.roles then
98
98
  sol = MrMurano::Role.new
99
- sol.syncup( $cfg['location.base'] + $cfg['location.roles'], options)
99
+ sol.syncup(options)
100
100
  end
101
101
 
102
102
  if options.users then
103
103
  sol = MrMurano::User.new
104
- sol.syncup( $cfg['location.base'] + $cfg['location.users'], options)
104
+ sol.syncup(options)
105
105
  end
106
106
 
107
107
  if options.files then
108
108
  sol = MrMurano::File.new
109
- sol.syncup( $cfg['location.base'] + $cfg['location.files'], options)
109
+ sol.syncup(options)
110
110
  end
111
111
 
112
112
  end
@@ -1,4 +1,4 @@
1
1
  module MrMurano
2
- VERSION = '1.0.5'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
4
4
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: MrMurano
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Conrad Tadpol Tilstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-09 00:00:00.000000000 Z
11
+ date: 2016-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander