MrMurano 1.0.5 → 1.1.0

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.
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