palimpsest 0.0.1 → 0.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +123 -8
- data/lib/palimpsest/assets.rb +15 -7
- data/lib/palimpsest/component.rb +33 -0
- data/lib/palimpsest/environment.rb +152 -37
- data/lib/palimpsest/external.rb +74 -0
- data/lib/palimpsest/site.rb +23 -0
- data/lib/palimpsest/utility.rb +7 -11
- data/lib/palimpsest/version.rb +1 -1
- data/lib/palimpsest.rb +6 -1
- data/spec/component_spec.rb +28 -0
- data/spec/environment_spec.rb +126 -42
- data/spec/external_spec.rb +86 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/utility_spec.rb +12 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 786935525c8fd9d713375ffc0b13e52bae005eb7
|
4
|
+
data.tar.gz: 9b1f0e46de8b8d23fd44a55034e1ce87529c135a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a405c655b0aa0024da55885d687e89cabe671705ba2dde83c1875ee911b04c297856dc97cf05ea85f79544ae35f49c6f8a7cb354993bb356d61c61e65e757ca
|
7
|
+
data.tar.gz: c139bd33702b70b8297f6f5eab2d0a1289f74249e95fd8fd68c184f1c1e7b5b8349f614ac3b7db538d836971c41c74597ced18ac2f98cdce2911058a382b31bd
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -9,16 +9,20 @@ Palimpsest runs on top of any project and acts as a post processor for your code
|
|
9
9
|
Features a [Sprockets](https://github.com/sstephenson/sprockets) asset pipeline
|
10
10
|
and easy integration with [Kit](https://github.com/razor-x/kit).
|
11
11
|
|
12
|
+
[](http://badge.fury.io/rb/palimpsest)
|
12
13
|
[](https://gemnasium.com/razor-x/palimpsest)
|
13
14
|
[](https://travis-ci.org/razor-x/palimpsest)
|
14
15
|
[](https://coveralls.io/r/razor-x/palimpsest)
|
15
16
|
[](https://codeclimate.com/github/razor-x/palimpsest)
|
17
|
+
[](http://githalytics.com/razor-x/palimpsest)
|
16
18
|
|
17
19
|
## Installation
|
18
20
|
|
19
21
|
Add this line to your application's Gemfile:
|
20
22
|
|
21
|
-
|
23
|
+
````ruby
|
24
|
+
gem 'palimpsest'
|
25
|
+
````
|
22
26
|
|
23
27
|
And then execute:
|
24
28
|
|
@@ -32,20 +36,131 @@ Or install it yourself as:
|
|
32
36
|
$ gem install palimpsest
|
33
37
|
````
|
34
38
|
|
39
|
+
## Documentation
|
40
|
+
|
41
|
+
The primary documentation for Palimpsest is this README and the YARD source documentation.
|
42
|
+
|
43
|
+
YARD documentation for all gem versions is hosted on the [Palimpsest gem page](https://rubygems.org/gems/palimpsest).
|
44
|
+
Documentation for the latest commits is hosted on [the RubyDoc.info project page](http://rubydoc.info/github/razor-x/palimpsest/frames).
|
45
|
+
|
35
46
|
## Usage
|
36
47
|
|
37
|
-
**Palimpsest should not be considered stable until version
|
48
|
+
**Palimpsest should not be considered stable until version 1.0.0 is released.**
|
38
49
|
|
39
|
-
|
50
|
+
This README will focus on examples of how to get your project working with Palimpsest through `Palimpsest::Environment`.
|
40
51
|
|
41
|
-
|
52
|
+
Palimpsest's classes are independently useful outside of `Palimpsest::Environment`, and each is
|
53
|
+
[well documented for that purpose](http://rubydoc.info/github/razor-x/palimpsest/frames).
|
42
54
|
|
43
|
-
|
55
|
+
The first step is always
|
44
56
|
|
45
|
-
|
57
|
+
````ruby
|
58
|
+
require 'palimpsest'
|
59
|
+
````
|
60
|
+
### Additional requirements
|
46
61
|
|
47
|
-
|
48
|
-
|
62
|
+
Some optional Palimpsest features depend on gems not required by Palimpsest itself.
|
63
|
+
Include these in your project's Gemfile if you plan to use them.
|
64
|
+
|
65
|
+
For example, to use the `image_compression` option, add to your Gemfile
|
66
|
+
|
67
|
+
````ruby
|
68
|
+
gem 'sprockets-image_compressor'
|
69
|
+
````
|
70
|
+
|
71
|
+
and to your project
|
72
|
+
|
73
|
+
````ruby
|
74
|
+
require 'sprockets-image_compressor'
|
75
|
+
````
|
76
|
+
|
77
|
+
or if you set `js_compressor: uglifier` you must add to your Gemfile
|
78
|
+
|
79
|
+
````ruby
|
80
|
+
gem 'uglifier'
|
81
|
+
````
|
82
|
+
|
83
|
+
and to your project
|
84
|
+
|
85
|
+
````ruby
|
86
|
+
require 'uglifier'
|
87
|
+
````
|
88
|
+
|
89
|
+
Similarly you must include gems for any sprockets engines you want to use.
|
90
|
+
|
91
|
+
### Creating and populating an environment
|
92
|
+
|
93
|
+
Create an environment with
|
94
|
+
|
95
|
+
````ruby
|
96
|
+
environment = Palimpsest::Environment.new
|
97
|
+
````
|
98
|
+
For most operations you will need to specify a `site` which can be any object which
|
99
|
+
responds to the methods `Palimpsest::Environment` assumes exists in some of its own methods.
|
100
|
+
A model class `Palimpsest::Site` is included which implements all possible expected methods.
|
101
|
+
Finally, the examples below assume default options for each class, but these can be overridden with `#options`.
|
102
|
+
|
103
|
+
````ruby
|
104
|
+
site = Palimpsest::Site.new
|
105
|
+
site.name = 'my_app'
|
106
|
+
environment.site = site
|
107
|
+
````
|
108
|
+
|
109
|
+
To populate the environment from a git repo,
|
110
|
+
|
111
|
+
````ruby
|
112
|
+
site.repo = Grit::Repo.new '/path/to/project/repo'
|
113
|
+
environment.treeish = 'my_feature' # if you want something other then 'master'
|
114
|
+
environment.populate
|
115
|
+
````
|
116
|
+
or to populate from a directory,
|
117
|
+
|
118
|
+
````ruby
|
119
|
+
site.source = '/path/to/project/source'
|
120
|
+
environment.populate from :source
|
121
|
+
````
|
122
|
+
Either way you will get a copy of your site in a new random working directory,
|
123
|
+
|
124
|
+
````ruby
|
125
|
+
environment.directory #=> '/tmp/palimpsest_my_app_6025680'
|
126
|
+
````
|
127
|
+
|
128
|
+
### Working with the environment
|
129
|
+
|
130
|
+
If you project contains a file `palimpsest_config.yml`,
|
131
|
+
then its configuration is available with `environment.config`.
|
132
|
+
|
133
|
+
[**An example `palimpsest_config.yml`.**](http://rubydoc.info/github/razor-x/palimpsest/Palimpsest/Environment)
|
134
|
+
|
135
|
+
The configuration file tells Palimpsest how to behave when you ask it to manipulate the environment
|
136
|
+
and acts as a shortcut to working with the other Palimpsest classes directly.
|
137
|
+
|
138
|
+
If you made it this far, you can make Palimpsest do all sorts of magic to your code in the working directory.
|
139
|
+
|
140
|
+
For example, to search through you code for tags referencing assets,
|
141
|
+
process and save those assets with sprockets,
|
142
|
+
and replace the tags with references to the processed assets,
|
143
|
+
|
144
|
+
````ruby
|
145
|
+
environment.compile_assets
|
146
|
+
````
|
147
|
+
Check the [`Palimpsest::Environment` documentation](http://rubydoc.info/github/razor-x/palimpsest/Palimpsest/Environment)
|
148
|
+
for all available magic, and freely extend the class to add new magic applicable to your project.
|
149
|
+
|
150
|
+
### Finishing with the environment
|
151
|
+
|
152
|
+
You can copy the current state of the environment to another directory with `Palimpsest::Environment#copy`.
|
153
|
+
By default, this will use `site.path` for the destination, or you can specify with
|
154
|
+
|
155
|
+
````ruby
|
156
|
+
environment.copy dest: '/path/to/out/dir'
|
157
|
+
````
|
158
|
+
|
159
|
+
To delete the working directory, use
|
160
|
+
|
161
|
+
````ruby
|
162
|
+
environment.cleanup
|
163
|
+
````
|
49
164
|
|
50
165
|
## Development
|
51
166
|
|
data/lib/palimpsest/assets.rb
CHANGED
@@ -29,6 +29,9 @@ module Palimpsest
|
|
29
29
|
# keyword to use in asset tag for inline assets
|
30
30
|
inline: 'inline',
|
31
31
|
|
32
|
+
# if true, use sprockets-image_compressor with pngcrush and jpegoptim
|
33
|
+
image_compression: false,
|
34
|
+
|
32
35
|
# if true, also generate a gzipped asset
|
33
36
|
gzip: false,
|
34
37
|
|
@@ -40,7 +43,7 @@ module Palimpsest
|
|
40
43
|
src_post: '%]',
|
41
44
|
|
42
45
|
# allowed options for `Sprockets::Environment`
|
43
|
-
sprockets_options: [
|
46
|
+
sprockets_options: [:js_compressor, :css_compressor]
|
44
47
|
}
|
45
48
|
|
46
49
|
# @!attribute directory
|
@@ -78,7 +81,12 @@ module Palimpsest
|
|
78
81
|
options[:sprockets_options].each do |opt|
|
79
82
|
sprockets.send "#{opt}=".to_sym, options[opt] if options[opt]
|
80
83
|
end
|
81
|
-
|
84
|
+
|
85
|
+
if options[:image_compression]
|
86
|
+
Sprockets::ImageCompressor::Integration.setup sprockets
|
87
|
+
end
|
88
|
+
|
89
|
+
self
|
82
90
|
end
|
83
91
|
|
84
92
|
# Load paths into the sprockets environment.
|
@@ -87,7 +95,7 @@ module Palimpsest
|
|
87
95
|
paths.each do |path|
|
88
96
|
sprockets.append_path "#{directory + '/' unless directory.empty?}#{path}"
|
89
97
|
end
|
90
|
-
|
98
|
+
self
|
91
99
|
end
|
92
100
|
|
93
101
|
# @return [Sprockets::Environment] sprockets environment with {#options} and {#paths} loaded
|
@@ -165,15 +173,15 @@ module Palimpsest
|
|
165
173
|
# @param options [Hash] merged with {DEFAULT_OPTIONS}
|
166
174
|
# (see #find_tags)
|
167
175
|
def self.find_tags path, type=nil, options={}
|
168
|
-
|
176
|
+
fail ArgumentError, 'path cannot be empty' if path.empty?
|
169
177
|
|
170
178
|
options = DEFAULT_OPTIONS.merge options
|
171
179
|
pre = Regexp.escape options[:src_pre]
|
172
180
|
post= Regexp.escape options[:src_post]
|
173
181
|
|
174
|
-
cmd = [
|
175
|
-
cmd.concat
|
176
|
-
cmd <<
|
182
|
+
cmd = ['grep']
|
183
|
+
cmd.concat %w(-l -I -r -E)
|
184
|
+
cmd <<
|
177
185
|
if type.nil?
|
178
186
|
pre + '(.*?)' + post
|
179
187
|
else
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Palimpsest
|
2
|
+
|
3
|
+
# Use this class to store parts of your project in a location
|
4
|
+
# separate from the normal installed location.
|
5
|
+
#
|
6
|
+
# For example, put custom templates in `components/my_app/templates`
|
7
|
+
# which might later be installed to `apps/my_app/templates`.
|
8
|
+
#
|
9
|
+
# This is useful when `apps/my_app` is a separate project
|
10
|
+
# with its own repository loaded using {Palimpsest::External}.
|
11
|
+
class Component
|
12
|
+
|
13
|
+
# @!attribute source_path
|
14
|
+
# @return [String] source path for component
|
15
|
+
#
|
16
|
+
# @!attribute install_path
|
17
|
+
# @return [String] install path for component
|
18
|
+
attr_accessor :source_path, :install_path
|
19
|
+
|
20
|
+
def initialize source_path: '', install_path: ''
|
21
|
+
self.source_path = source_path
|
22
|
+
self.install_path = install_path
|
23
|
+
end
|
24
|
+
|
25
|
+
# Installs files in {#source_path} to {#install_path}
|
26
|
+
def install
|
27
|
+
fail RuntimeError if source_path.empty?
|
28
|
+
fail RuntimeError if install_path.empty?
|
29
|
+
FileUtils.mkdir_p install_path
|
30
|
+
FileUtils.mv Dir["#{source_path}/*"], install_path
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,9 +1,8 @@
|
|
1
|
-
require 'grit'
|
2
|
-
|
3
1
|
module Palimpsest
|
4
2
|
|
5
3
|
# An environment is populated with the contents of
|
6
4
|
# a site's repository at a specified commit.
|
5
|
+
# Alternatively, a single directory can be used to populate the environment.
|
7
6
|
# The environment's files are rooted in a temporary {#directory}.
|
8
7
|
# An environment is the primary way to interact with a site's files.
|
9
8
|
#
|
@@ -13,11 +12,33 @@ module Palimpsest
|
|
13
12
|
# Paths are all relative to the working {#directory}.
|
14
13
|
#
|
15
14
|
# ````yml
|
16
|
-
# palimpsest_config.yml
|
15
|
+
# # example of palimpsest_config.yml
|
16
|
+
#
|
17
|
+
# # component settings
|
18
|
+
# :components:
|
19
|
+
# # all component paths are relative to the base
|
20
|
+
# :base: _components
|
21
|
+
#
|
22
|
+
# # list of components
|
23
|
+
# :paths:
|
24
|
+
# #- [ components_path, install_path ]
|
25
|
+
# - [ my_app/templates, apps/my_app/templates ]
|
26
|
+
# - [ my_app/extra, apps/my_app ]
|
17
27
|
#
|
28
|
+
# # externals settings
|
29
|
+
# :externals:
|
30
|
+
# # server or local path that repos are under
|
31
|
+
# :server: "https://github.com/razor-x"
|
32
|
+
#
|
33
|
+
# # list of external repos
|
34
|
+
# :repos:
|
35
|
+
# #- [ name, install_path, branch, server (optional) ]
|
36
|
+
# - [ my_app, apps/my_app, master ]
|
37
|
+
# - [ sub_app, apps/my_app/sub_app, my_feature, "https://bitbucket.org/razorx" ]
|
18
38
|
# # asset settings
|
19
39
|
# :assets:
|
20
|
-
# # all options are passed to
|
40
|
+
# # all options are passed to Assets#options
|
41
|
+
# # options will use defaults set in Palimpsest::Asset::DEFAULT_OPTIONS if unset here
|
21
42
|
# # unless otherwise mentioned, options can be set or overridden per asset type
|
22
43
|
# :options:
|
23
44
|
# # opening and closing brackets for asset source tags
|
@@ -61,8 +82,10 @@ module Palimpsest
|
|
61
82
|
# - assets/stylesheets
|
62
83
|
# # images can be part of the asset pipeline
|
63
84
|
# :images:
|
64
|
-
# # options can be overridden per type
|
65
85
|
# :options:
|
86
|
+
# # requires the sprockets-image_compressor gem
|
87
|
+
# :image_compression: true
|
88
|
+
# # options can be overridden per type
|
66
89
|
# :output: images
|
67
90
|
# :paths:
|
68
91
|
# - assets/images
|
@@ -87,12 +110,9 @@ module Palimpsest
|
|
87
110
|
# @!attribute treeish
|
88
111
|
# @return [String] the reference used to pick the commit to build the environment with
|
89
112
|
#
|
90
|
-
# @!attribute [r] directory
|
91
|
-
# @return [String] the environment's working directory
|
92
|
-
#
|
93
113
|
# @!attribute [r] populated
|
94
114
|
# @return [Boolean] true if the site's repo has been extracted
|
95
|
-
attr_reader :site, :treeish, :
|
115
|
+
attr_reader :site, :treeish, :populated
|
96
116
|
|
97
117
|
def initialize site: nil, treeish: 'master', options: {}
|
98
118
|
@populated = false
|
@@ -109,49 +129,71 @@ module Palimpsest
|
|
109
129
|
@options = @options.merge options
|
110
130
|
end
|
111
131
|
|
132
|
+
# @see Environment#site
|
112
133
|
def site= site
|
113
|
-
|
134
|
+
fail RuntimeError, "Cannot redefine 'site' once populated" if populated
|
114
135
|
@site = site
|
115
136
|
end
|
116
137
|
|
138
|
+
# @see Environment#treeish
|
117
139
|
def treeish= treeish
|
118
|
-
|
119
|
-
|
140
|
+
fail RuntimeError, "Cannot redefine 'treeish' once populated" if populated
|
141
|
+
fail TypeError unless treeish.is_a? String
|
120
142
|
@treeish = treeish
|
121
143
|
end
|
122
144
|
|
145
|
+
# @return [String] the environment's working directory
|
123
146
|
def directory
|
124
|
-
raise RuntimeError if site.nil?
|
125
147
|
if @directory.nil?
|
126
|
-
|
148
|
+
name = site.nil? ? '' : site.name
|
149
|
+
@directory = Utility.make_random_directory options[:tmp_dir], "#{options[:dir_prefix]}#{name}_"
|
127
150
|
else
|
128
151
|
@directory
|
129
152
|
end
|
130
153
|
end
|
131
154
|
|
155
|
+
# Copy the contents of the working directory.
|
156
|
+
# @param dest [String] path to copy environment's files to
|
157
|
+
# @return [Environment] the current environment instance
|
158
|
+
def copy dest: site.path
|
159
|
+
FileUtils.cp_r Dir["#{directory}/*"], dest, preserve: true
|
160
|
+
self
|
161
|
+
end
|
162
|
+
|
132
163
|
# Removes the environment's working directory.
|
164
|
+
# @return [Environment] the current environment instance
|
133
165
|
def cleanup
|
134
166
|
FileUtils.remove_entry_secure directory if @directory
|
135
167
|
@directory = nil
|
168
|
+
@assets = []
|
169
|
+
@components = []
|
136
170
|
@populated = false
|
137
|
-
|
171
|
+
self
|
138
172
|
end
|
139
173
|
|
140
174
|
# Extracts the site's files from repository to the working directory.
|
141
|
-
|
175
|
+
# @return [Environment] the current environment instance
|
176
|
+
def populate from: :auto
|
142
177
|
cleanup if populated
|
143
|
-
|
178
|
+
fail RuntimeError, "Cannot populate without 'site'" if site.nil?
|
144
179
|
|
145
180
|
case from
|
181
|
+
when :auto
|
182
|
+
if site.respond_to?(:repo) ? site.repo : nil
|
183
|
+
populate from: :repo
|
184
|
+
else
|
185
|
+
populate from: :source
|
186
|
+
end
|
146
187
|
when :repo
|
147
|
-
|
148
|
-
|
188
|
+
fail RuntimeError, "Cannot populate without 'treeish'" if treeish.empty?
|
189
|
+
Utility.extract_repo site.repo, treeish, directory
|
190
|
+
@populated = true
|
149
191
|
when :source
|
150
|
-
FileUtils.cp_r Dir["#{site.source}/*"], directory
|
192
|
+
FileUtils.cp_r Dir["#{site.source}/*"], directory, preserve: true
|
193
|
+
@populated = true
|
151
194
|
end
|
152
195
|
|
153
|
-
|
154
|
-
return self
|
196
|
+
self
|
155
197
|
end
|
156
198
|
|
157
199
|
# @return [Hash] configuration loaded from {#options}`[:config_file]` under {#directory}
|
@@ -161,15 +203,65 @@ module Palimpsest
|
|
161
203
|
validate_config if @config
|
162
204
|
end
|
163
205
|
|
164
|
-
# @return [Array<
|
206
|
+
# @return [Array<Component>] components with paths loaded from config
|
207
|
+
def components
|
208
|
+
return @components if @components
|
209
|
+
return [] if config[:components].nil?
|
210
|
+
return [] if config[:components][:paths].nil?
|
211
|
+
|
212
|
+
@components = []
|
213
|
+
|
214
|
+
base = directory
|
215
|
+
base += config[:components][:base].nil? ? '' : '/' + config[:components][:base]
|
216
|
+
|
217
|
+
config[:components][:paths].each do |paths|
|
218
|
+
@components << Component.new(source_path: "#{base}/#{paths[0]}", install_path: "#{directory}/#{paths[1]}")
|
219
|
+
end
|
220
|
+
|
221
|
+
@components
|
222
|
+
end
|
223
|
+
|
224
|
+
# Install all components.
|
225
|
+
# @return [Environment] the current environment instance
|
226
|
+
def install_components
|
227
|
+
components.each { |c| c.install }
|
228
|
+
self
|
229
|
+
end
|
230
|
+
|
231
|
+
# @return [Array<External>] externals loaded from config
|
232
|
+
def externals
|
233
|
+
return @externals if @externals
|
234
|
+
return [] if config[:externals].nil?
|
235
|
+
return [] if config[:externals][:repos].nil?
|
236
|
+
|
237
|
+
@externals = []
|
238
|
+
|
239
|
+
config[:externals][:repos].each do |repo|
|
240
|
+
source = repo[3].nil? ? config[:externals][:server] : repo[3]
|
241
|
+
@externals << External.new(name: repo[0], source: source, branch: repo[2], install_path: "#{directory}/#{repo[1]}" )
|
242
|
+
end
|
243
|
+
|
244
|
+
@externals
|
245
|
+
end
|
246
|
+
|
247
|
+
# Install all externals.
|
248
|
+
# @return [Environment] the current environment instance
|
249
|
+
def install_externals
|
250
|
+
externals.each { |e| e.install }
|
251
|
+
self
|
252
|
+
end
|
253
|
+
|
254
|
+
# @return [Array<Assets>] assets with settings and paths loaded from config
|
165
255
|
def assets
|
256
|
+
return @assets if @assets
|
257
|
+
|
166
258
|
@assets = []
|
167
259
|
|
168
260
|
config[:assets].each do |type, opt|
|
169
|
-
next if [
|
261
|
+
next if [:sources].include? type
|
170
262
|
next if opt[:paths].nil?
|
171
263
|
|
172
|
-
assets =
|
264
|
+
assets = Assets.new directory: directory, paths: opt[:paths]
|
173
265
|
assets.options config[:assets][:options] unless config[:assets][:options].nil?
|
174
266
|
assets.options opt[:options] unless opt[:options].nil?
|
175
267
|
assets.type = type
|
@@ -187,12 +279,12 @@ module Palimpsest
|
|
187
279
|
@sources_with_assets = []
|
188
280
|
|
189
281
|
opts = {}
|
190
|
-
[
|
282
|
+
[:src_pre, :src_post].each do |opt|
|
191
283
|
opts[opt] = config[:assets][:options][opt] unless config[:assets][:options][opt].nil?
|
192
284
|
end unless config[:assets][:options].nil?
|
193
285
|
|
194
286
|
config[:assets][:sources].each do |path|
|
195
|
-
@sources_with_assets <<
|
287
|
+
@sources_with_assets << Assets.find_tags("#{directory}/#{path}", nil, opts)
|
196
288
|
end
|
197
289
|
|
198
290
|
@sources_with_assets.flatten
|
@@ -200,35 +292,57 @@ module Palimpsest
|
|
200
292
|
|
201
293
|
# Finds all assets in {#sources_with_assets} and
|
202
294
|
# generates the assets and updates the sources.
|
295
|
+
# @return [Environment] the current environment instance
|
203
296
|
def compile_assets
|
204
297
|
sources_with_assets.each do |file|
|
205
298
|
source = File.read file
|
206
299
|
assets.each { |a| a.update_source! source }
|
207
|
-
|
300
|
+
Utility.write source, file, preserve: true
|
208
301
|
end
|
209
|
-
|
302
|
+
self
|
210
303
|
end
|
211
304
|
|
212
305
|
private
|
213
306
|
|
214
307
|
# Checks the config file for invalid settings.
|
215
|
-
#
|
308
|
+
# @todo refactor this
|
216
309
|
# - Checks that paths are not absolute or use `../` or `~/`.
|
217
310
|
def validate_config
|
218
311
|
message = 'bad path in config'
|
219
312
|
|
220
|
-
def safe_path?(path) Palimpsest::Utility.safe_path?(path) end
|
221
|
-
|
222
313
|
# Checks the option in the asset key.
|
223
314
|
def validate_asset_options opts
|
224
315
|
opts.each do |k,v|
|
225
|
-
|
226
|
-
|
316
|
+
fail RuntimeError, 'bad option in config' if k == :sprockets_options
|
317
|
+
fail RuntimeError, message if k == :output && ! Utility.safe_path?(v)
|
227
318
|
end
|
228
319
|
end
|
229
320
|
|
230
|
-
@config[:
|
321
|
+
@config[:external].each do |k, v|
|
322
|
+
next if k == :server
|
231
323
|
|
324
|
+
v.each do |repo|
|
325
|
+
fail RuntimeError, message unless Utility.safe_path? repo[1]
|
326
|
+
end unless v.nil?
|
327
|
+
end unless @config[:external].nil?
|
328
|
+
|
329
|
+
@config[:components].each do |k,v|
|
330
|
+
# process @config[:components][:base] then go to the next option
|
331
|
+
if k == :base
|
332
|
+
fail RuntimeError, message unless Utility.safe_path? v
|
333
|
+
next
|
334
|
+
end unless v.nil?
|
335
|
+
|
336
|
+
# process @config[:components][:paths]
|
337
|
+
if k == :paths
|
338
|
+
v.each do |path|
|
339
|
+
fail RuntimeError, message unless Utility.safe_path? path[0]
|
340
|
+
fail RuntimeError, message unless Utility.safe_path? path[1]
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end unless @config[:components].nil?
|
344
|
+
|
345
|
+
@config[:assets].each do |k, v|
|
232
346
|
# process @config[:assets][:options] then go to the next option
|
233
347
|
if k == :options
|
234
348
|
validate_asset_options v
|
@@ -238,7 +352,7 @@ module Palimpsest
|
|
238
352
|
# process @config[:assets][:sources] then go to the next option
|
239
353
|
if k == :sources
|
240
354
|
v.each_with_index do |source, i|
|
241
|
-
|
355
|
+
fail RuntimeError, message unless Utility.safe_path? source
|
242
356
|
end
|
243
357
|
next
|
244
358
|
end
|
@@ -253,10 +367,11 @@ module Palimpsest
|
|
253
367
|
|
254
368
|
# process each asset path
|
255
369
|
asset_value.each_with_index do |path, i|
|
256
|
-
|
370
|
+
fail RuntimeError, message unless Utility.safe_path? path
|
257
371
|
end
|
258
372
|
end
|
259
373
|
end unless @config[:assets].nil?
|
374
|
+
|
260
375
|
@config
|
261
376
|
end
|
262
377
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Palimpsest
|
2
|
+
|
3
|
+
# Use this class to manage external repositories you want to include in your project.
|
4
|
+
#
|
5
|
+
# Given a name, source and branch, the contents of the repository at the HEAD of the branch
|
6
|
+
# will be available as an {Environment} object through {#environment}.
|
7
|
+
#
|
8
|
+
# Use {#cleanup} to remove all files created by the {#External} object.
|
9
|
+
class External
|
10
|
+
|
11
|
+
# @!attribute name
|
12
|
+
# @return [String] repository name
|
13
|
+
#
|
14
|
+
# @!attribute source
|
15
|
+
# @return [String] base source url or path to external git repo (without name)
|
16
|
+
#
|
17
|
+
# @!attribute branch
|
18
|
+
# @return [String] branch to use for treeish
|
19
|
+
#
|
20
|
+
# @!attribute install_path
|
21
|
+
# @return [String] where the files will be installed to
|
22
|
+
attr_accessor :name, :source, :branch, :install_path
|
23
|
+
|
24
|
+
def initialize name: '', source: '', branch: 'master', install_path: ''
|
25
|
+
self.name = name
|
26
|
+
self.source = source
|
27
|
+
self.branch = branch
|
28
|
+
self.install_path = install_path
|
29
|
+
end
|
30
|
+
|
31
|
+
def repo_path
|
32
|
+
( source.empty? || name.empty? ) ? '' : "#{source}/#{name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Environment] environment with contents of the repository at the HEAD of the branch
|
36
|
+
def environment
|
37
|
+
return @environment if @environment
|
38
|
+
|
39
|
+
site = Site.new repo: Grit::Repo.new(tmp_environment.directory)
|
40
|
+
@environment = Environment.new site: site, treeish: branch
|
41
|
+
end
|
42
|
+
|
43
|
+
# Copy the files to the {#install_path}.
|
44
|
+
# @return (see Environment#copy)
|
45
|
+
def install
|
46
|
+
environment.copy dest: install_path
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [External] the current external instance
|
50
|
+
def cleanup
|
51
|
+
environment.cleanup if @environment
|
52
|
+
@environment = nil
|
53
|
+
|
54
|
+
tmp_environment.cleanup if @tmp_environment
|
55
|
+
@tmp_environment = nil
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Environment] temporary environment to hold the cloned repository
|
60
|
+
def tmp_environment
|
61
|
+
return @tmp_environment if @tmp_environment
|
62
|
+
|
63
|
+
fail RuntimeError if repo_path.empty?
|
64
|
+
|
65
|
+
Grit::Git.git_max_size = 200 * 1048576
|
66
|
+
Grit::Git.git_timeout = 200
|
67
|
+
|
68
|
+
@tmp_environment = Environment.new
|
69
|
+
gritty = Grit::Git.new tmp_environment.directory
|
70
|
+
gritty.clone( { branch: branch }, repo_path, tmp_environment.directory )
|
71
|
+
@tmp_environment
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Palimpsest
|
2
|
+
|
3
|
+
# Model site object used by {Environment#site}.
|
4
|
+
class Site
|
5
|
+
|
6
|
+
# @!attribute name
|
7
|
+
# @return [String] name for this site
|
8
|
+
#
|
9
|
+
# @!attribute repo
|
10
|
+
# @return [Grit::Repo] grit repo for this site
|
11
|
+
#
|
12
|
+
# @!attribute source
|
13
|
+
# @return [String] path to source code for this site
|
14
|
+
attr_accessor :name, :repo, :source, :path
|
15
|
+
|
16
|
+
def initialize name: '', repo: nil, source: ''
|
17
|
+
self.name = name
|
18
|
+
self.repo = repo
|
19
|
+
self.source = source
|
20
|
+
self.path = path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/palimpsest/utility.rb
CHANGED
@@ -38,8 +38,8 @@ module Palimpsest
|
|
38
38
|
# @return [String] input path if valid
|
39
39
|
def self.validate_path path, root=''
|
40
40
|
case
|
41
|
-
when path[/(\.\.\/|~\/)/] then
|
42
|
-
when File.expand_path(path, root)[/^#{root}/].nil? then
|
41
|
+
when path[/(\.\.\/|~\/)/] then fail RuntimeError
|
42
|
+
when File.expand_path(path, root)[/^#{root}/].nil? then fail RuntimeError
|
43
43
|
else path
|
44
44
|
end
|
45
45
|
end
|
@@ -48,22 +48,18 @@ module Palimpsest
|
|
48
48
|
# @param [Grit::Repo] repo
|
49
49
|
# @param [String] treeish
|
50
50
|
# @param [String] directory
|
51
|
-
def self.extract_repo repo, treeish, directory
|
51
|
+
def self.extract_repo repo, treeish, directory
|
52
52
|
input = Archive::Tar::Minitar::Input.new StringIO.new(repo.archive_tar treeish)
|
53
|
-
input.each
|
54
|
-
if files.nil?
|
55
|
-
input.extract_entry directory, entry
|
56
|
-
else
|
57
|
-
input.extract_entry directory, entry if files.include? entry.name
|
58
|
-
end
|
59
|
-
end
|
53
|
+
input.each { |e| input.extract_entry directory, e }
|
60
54
|
end
|
61
55
|
|
62
56
|
# Write contents to file.
|
63
57
|
# @param contents [String]
|
64
58
|
# @param file [String]
|
65
|
-
def self.write contents, file
|
59
|
+
def self.write contents, file, preserve: false
|
60
|
+
original_time = File.mtime file if preserve
|
66
61
|
File.open(file, 'w') { |f| f.write contents }
|
62
|
+
File.utime original_time, original_time, file if preserve
|
67
63
|
end
|
68
64
|
end
|
69
65
|
end
|
data/lib/palimpsest/version.rb
CHANGED
data/lib/palimpsest.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
+
require 'grit'
|
2
|
+
|
1
3
|
require 'palimpsest/version'
|
4
|
+
require 'palimpsest/utility'
|
5
|
+
require 'palimpsest/site'
|
2
6
|
require 'palimpsest/assets'
|
7
|
+
require 'palimpsest/component'
|
8
|
+
require 'palimpsest/external'
|
3
9
|
require 'palimpsest/environment'
|
4
|
-
require 'palimpsest/utility'
|
5
10
|
|
6
11
|
# No web framework, no problem:
|
7
12
|
# Palimpsest gives any custom or legacy project # a modern workflow and toolset.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Palimpsest::Component do
|
4
|
+
|
5
|
+
subject(:component) { Palimpsest::Component.new }
|
6
|
+
|
7
|
+
describe "#install" do
|
8
|
+
|
9
|
+
it "fails if no source path" do
|
10
|
+
component.install_path = 'install/path'
|
11
|
+
expect { component.install }.to raise_error RuntimeError
|
12
|
+
end
|
13
|
+
|
14
|
+
it "fails if no install path" do
|
15
|
+
component.source_path = 'src/path'
|
16
|
+
expect { component.install }.to raise_error RuntimeError
|
17
|
+
end
|
18
|
+
|
19
|
+
it "moves the component to the install path" do
|
20
|
+
component.source_path = 'src/path'
|
21
|
+
component.install_path = 'install/path'
|
22
|
+
allow(Dir).to receive(:[]).with('src/path/*').and_return( %w(src/path/1 src/path/2) )
|
23
|
+
expect(FileUtils).to receive(:mkdir_p).with('install/path')
|
24
|
+
expect(FileUtils).to receive(:mv).with(%w(src/path/1 src/path/2), 'install/path')
|
25
|
+
component.install
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/environment_spec.rb
CHANGED
@@ -2,17 +2,11 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Palimpsest::Environment do
|
4
4
|
|
5
|
-
let(:site_1) {
|
6
|
-
let(:site_2) {
|
5
|
+
let(:site_1) { Palimpsest::Site.new name: 'site_1' }
|
6
|
+
let(:site_2) { Palimpsest::Site.new name: 'site_2' }
|
7
7
|
|
8
8
|
subject(:environment) { Palimpsest::Environment.new }
|
9
9
|
|
10
|
-
after :all do
|
11
|
-
Dir.glob("#{Palimpsest::Environment.new.options[:tmp_dir]}/#{Palimpsest::Environment.new.options[:dir_prefix]}*").each do |dir|
|
12
|
-
FileUtils.remove_entry_secure dir
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
10
|
describe ".new" do
|
17
11
|
|
18
12
|
it "sets default options" do
|
@@ -63,36 +57,33 @@ describe Palimpsest::Environment do
|
|
63
57
|
|
64
58
|
describe "#directory" do
|
65
59
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
before :each do
|
71
|
-
allow(Palimpsest::Utility).to receive(:make_random_directory).and_return('/tmp/rand_dir')
|
72
|
-
end
|
60
|
+
before :each do
|
61
|
+
allow(Palimpsest::Utility).to receive(:make_random_directory).and_return('/tmp/rand_dir')
|
62
|
+
end
|
73
63
|
|
74
|
-
|
64
|
+
context "when directory is unset" do
|
75
65
|
|
76
|
-
|
77
|
-
|
78
|
-
end
|
66
|
+
it "makes and returns a random directory" do
|
67
|
+
expect(environment.directory).to eq '/tmp/rand_dir'
|
79
68
|
end
|
69
|
+
end
|
80
70
|
|
81
|
-
|
71
|
+
context "when directory is set" do
|
82
72
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
73
|
+
it "returns the current directory" do
|
74
|
+
expect(Palimpsest::Utility).to receive(:make_random_directory).once
|
75
|
+
environment.directory
|
76
|
+
expect(environment.directory).to eq '/tmp/rand_dir'
|
88
77
|
end
|
89
78
|
end
|
79
|
+
end
|
90
80
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
81
|
+
describe "#copy" do
|
82
|
+
it "moves the component to the install path" do
|
83
|
+
dir = environment.directory
|
84
|
+
allow(Dir).to receive(:[]).with("#{dir}/*").and_return( %W(#{dir}/path/1 #{dir}/path/2) )
|
85
|
+
expect(FileUtils).to receive(:cp_r).with( %W(#{dir}/path/1 #{dir}/path/2), '/dest/path', preserve: true)
|
86
|
+
environment.copy dest: '/dest/path'
|
96
87
|
end
|
97
88
|
end
|
98
89
|
|
@@ -106,6 +97,10 @@ describe Palimpsest::Environment do
|
|
106
97
|
environment.cleanup
|
107
98
|
expect(environment.instance_variable_get :@directory).to eq nil
|
108
99
|
end
|
100
|
+
|
101
|
+
it "returns itself" do
|
102
|
+
expect(environment.cleanup).to be environment
|
103
|
+
end
|
109
104
|
end
|
110
105
|
|
111
106
|
describe "#populate" do
|
@@ -120,40 +115,40 @@ describe Palimpsest::Environment do
|
|
120
115
|
subject(:environment) { Palimpsest::Environment.new site: site_1, treeish: 'master' }
|
121
116
|
|
122
117
|
before :each do
|
123
|
-
|
118
|
+
site_1.repo = double Grit::Repo
|
124
119
|
allow(Palimpsest::Utility).to receive :extract_repo
|
125
120
|
end
|
126
121
|
|
127
122
|
it "extracts the repo to the directory and sets populated true" do
|
128
123
|
expect(Palimpsest::Utility).to receive(:extract_repo).with(site_1.repo, 'master', environment.directory)
|
129
|
-
environment.populate
|
124
|
+
environment.populate from: :repo
|
130
125
|
expect(environment.populated).to eq true
|
131
126
|
end
|
132
127
|
|
133
128
|
it "fails when missing treeish" do
|
134
129
|
environment.site = site_1
|
135
130
|
environment.treeish = ''
|
136
|
-
expect { environment.populate }.to raise_error RuntimeError, /populate without/
|
131
|
+
expect { environment.populate from: :repo }.to raise_error RuntimeError, /populate without/
|
137
132
|
end
|
138
133
|
|
139
134
|
it "returns itself" do
|
140
|
-
expect(environment.populate).to be environment
|
135
|
+
expect(environment.populate from: :repo).to be environment
|
141
136
|
end
|
142
137
|
|
143
138
|
it "will cleanup if populated" do
|
144
139
|
environment.populate
|
145
140
|
expect(environment).to receive :cleanup
|
146
|
-
environment.populate
|
141
|
+
environment.populate from: :repo
|
147
142
|
end
|
148
143
|
end
|
149
144
|
|
150
|
-
context "populate from
|
145
|
+
context "populate from source" do
|
151
146
|
|
152
|
-
it "copies the source files to the directory" do
|
147
|
+
it "copies the source files to the directory preserving mtime" do
|
153
148
|
environment.site = site_1
|
154
|
-
|
149
|
+
site_1.source = '/path/to/source'
|
155
150
|
allow(Dir).to receive(:[]).with('/path/to/source/*').and_return( %w(dir_1 dir_2) )
|
156
|
-
expect(FileUtils).to receive(:cp_r).with( %w(dir_1 dir_2), environment.directory )
|
151
|
+
expect(FileUtils).to receive(:cp_r).with( %w(dir_1 dir_2), environment.directory, preserve: true )
|
157
152
|
environment.populate from: :source
|
158
153
|
end
|
159
154
|
end
|
@@ -189,6 +184,16 @@ describe Palimpsest::Environment do
|
|
189
184
|
|
190
185
|
let(:config) do
|
191
186
|
YAML.load <<-EOF
|
187
|
+
:components:
|
188
|
+
:base: _components
|
189
|
+
:paths:
|
190
|
+
- [ my_app/templates, apps/my_app/templates ]
|
191
|
+
- [ my_app/extra, apps/my_app ]
|
192
|
+
:externals:
|
193
|
+
:server: "https://github.com/razor-x"
|
194
|
+
:repos:
|
195
|
+
- [ my_app, apps/my_app, master ]
|
196
|
+
- [ sub_app, apps/my_app/sub_app, my_feature, "https://bitbucket.org/razorx" ]
|
192
197
|
:assets:
|
193
198
|
:options:
|
194
199
|
:output: compiled
|
@@ -219,6 +224,85 @@ describe Palimpsest::Environment do
|
|
219
224
|
allow(environment).to receive(:config).and_return(config)
|
220
225
|
end
|
221
226
|
|
227
|
+
describe "#components" do
|
228
|
+
|
229
|
+
it "returns an array" do
|
230
|
+
expect(environment.components).to be_a Array
|
231
|
+
end
|
232
|
+
|
233
|
+
it "contains components" do
|
234
|
+
expect(environment.components[0]).to be_a Palimpsest::Component
|
235
|
+
expect(environment.components[1]).to be_a Palimpsest::Component
|
236
|
+
end
|
237
|
+
|
238
|
+
it "sets the components source and install paths" do
|
239
|
+
expect(environment.components[0].source_path).to eq "#{environment.directory}/_components/my_app/templates"
|
240
|
+
expect(environment.components[0].install_path).to eq "#{environment.directory}/apps/my_app/templates"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
describe "#install_components" do
|
245
|
+
|
246
|
+
it "installs the components" do
|
247
|
+
expect(environment.components[0]).to receive(:install)
|
248
|
+
expect(environment.components[1]).to receive(:install)
|
249
|
+
environment.install_components
|
250
|
+
end
|
251
|
+
|
252
|
+
it "returns itself" do
|
253
|
+
expect(environment.install_components).to be environment
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe "#externals" do
|
258
|
+
|
259
|
+
it "returns an array" do
|
260
|
+
expect(environment.externals).to be_a Array
|
261
|
+
end
|
262
|
+
|
263
|
+
it "contains externals" do
|
264
|
+
expect(environment.externals[0]).to be_a Palimpsest::External
|
265
|
+
expect(environment.externals[1]).to be_a Palimpsest::External
|
266
|
+
end
|
267
|
+
|
268
|
+
it "sets the externals repo path" do
|
269
|
+
expect(environment.externals[0].repo_path).to eq 'https://github.com/razor-x/my_app'
|
270
|
+
expect(environment.externals[1].repo_path).to eq 'https://bitbucket.org/razorx/sub_app'
|
271
|
+
end
|
272
|
+
|
273
|
+
it "sets the externals branch" do
|
274
|
+
expect(environment.externals[0].branch).to eq 'master'
|
275
|
+
expect(environment.externals[1].branch).to eq 'my_feature'
|
276
|
+
end
|
277
|
+
|
278
|
+
it "sets the install path" do
|
279
|
+
expect(environment.externals[0].install_path).to eq "#{environment.directory}/apps/my_app"
|
280
|
+
expect(environment.externals[1].install_path).to eq "#{environment.directory}/apps/my_app/sub_app"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
describe "#install_externals" do
|
285
|
+
|
286
|
+
let(:external_1) { double Palimpsest::External }
|
287
|
+
let(:external_2) { double Palimpsest::External }
|
288
|
+
|
289
|
+
before :each do
|
290
|
+
allow(environment).to receive(:externals).and_return( [ external_1, external_2 ] )
|
291
|
+
allow(external_1).to receive(:install)
|
292
|
+
allow(external_2).to receive(:install)
|
293
|
+
end
|
294
|
+
|
295
|
+
it "installs the externals" do
|
296
|
+
expect(external_1).to receive(:install)
|
297
|
+
expect(external_2).to receive(:install)
|
298
|
+
environment.install_externals
|
299
|
+
end
|
300
|
+
|
301
|
+
it "returns itself" do
|
302
|
+
expect(environment.install_externals).to be environment
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
222
306
|
describe "#assets" do
|
223
307
|
|
224
308
|
subject(:assets) { environment.assets }
|
@@ -292,12 +376,12 @@ describe Palimpsest::Environment do
|
|
292
376
|
expect(environment.compile_assets).to be environment
|
293
377
|
end
|
294
378
|
|
295
|
-
it "compiles the assets and writes the sources" do
|
379
|
+
it "compiles the assets and writes the sources while preserving mtime" do
|
296
380
|
allow(environment).to receive(:sources_with_assets).and_return sources
|
297
381
|
allow(File).to receive(:read).with(sources[0]).and_return('data_1')
|
298
382
|
allow(File).to receive(:read).with(sources[1]).and_return('data_2')
|
299
|
-
expect(Palimpsest::Utility).to receive(:write).with 'data_1', sources[0]
|
300
|
-
expect(Palimpsest::Utility).to receive(:write).with 'data_2', sources[1]
|
383
|
+
expect(Palimpsest::Utility).to receive(:write).with 'data_1', sources[0], preserve: true
|
384
|
+
expect(Palimpsest::Utility).to receive(:write).with 'data_2', sources[1], preserve: true
|
301
385
|
environment.compile_assets
|
302
386
|
end
|
303
387
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Palimpsest::External do
|
4
|
+
|
5
|
+
subject(:external) { Palimpsest::External.new name: 'my_app', source: 'path/to/source', branch: 'my_feature' }
|
6
|
+
|
7
|
+
let(:gritty) { double Grit::Git }
|
8
|
+
let(:repo) { double Grit::Repo }
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
allow(Grit::Git).to receive(:new).and_return(gritty)
|
12
|
+
allow(Grit::Repo).to receive(:new).and_return(repo)
|
13
|
+
allow(gritty).to receive(:clone)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#repo_path" do
|
17
|
+
|
18
|
+
it "gives the full path to the source repo" do
|
19
|
+
expect(external.repo_path).to eq 'path/to/source/my_app'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#environment" do
|
24
|
+
|
25
|
+
it "returns a new environment" do
|
26
|
+
expect(external.environment).to be_a Palimpsest::Environment
|
27
|
+
end
|
28
|
+
|
29
|
+
it "sets the treeish for the environment" do
|
30
|
+
expect(external.environment.treeish).to eq 'my_feature'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "sets the repo for the environment" do
|
34
|
+
expect(external.environment.site.repo).to equal repo
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#tmp_environment" do
|
39
|
+
|
40
|
+
it "fails if no repo path" do
|
41
|
+
external.name = ''
|
42
|
+
external.source = ''
|
43
|
+
expect { external.tmp_environment }.to raise_error RuntimeError
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns a new environment" do
|
47
|
+
expect(external.tmp_environment).to be_a Palimpsest::Environment
|
48
|
+
end
|
49
|
+
|
50
|
+
it "sets the treeish for the environment" do
|
51
|
+
expect(gritty).to receive(:clone).with( { branch: 'my_feature' }, external.repo_path, anything )
|
52
|
+
external.tmp_environment
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#cleanup" do
|
57
|
+
|
58
|
+
it "cleans environment" do
|
59
|
+
expect(external.environment).to receive(:cleanup)
|
60
|
+
external.cleanup
|
61
|
+
end
|
62
|
+
it "clears @environment" do
|
63
|
+
expect(external.instance_variable_get :@environment).to be_nil
|
64
|
+
external.cleanup
|
65
|
+
end
|
66
|
+
|
67
|
+
it "cleans tmp_environment" do
|
68
|
+
expect(external.tmp_environment).to receive(:cleanup)
|
69
|
+
external.cleanup
|
70
|
+
end
|
71
|
+
|
72
|
+
it "clears @tmp_environment" do
|
73
|
+
expect(external.instance_variable_get :@tmp_environment).to be_nil
|
74
|
+
external.cleanup
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#install" do
|
79
|
+
|
80
|
+
it "installs the external to the install path" do
|
81
|
+
external.install_path = 'path/to/install'
|
82
|
+
expect(external.environment).to receive(:copy).with(dest: 'path/to/install')
|
83
|
+
external.install
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -12,4 +12,10 @@ SimpleCov.start
|
|
12
12
|
|
13
13
|
RSpec.configure do |c|
|
14
14
|
c.expect_with(:rspec) { |e| e.syntax = :expect }
|
15
|
+
|
16
|
+
c.after :suite do
|
17
|
+
Dir.glob("#{Palimpsest::Environment.new.options[:tmp_dir]}/#{Palimpsest::Environment.new.options[:dir_prefix]}*").each do |dir|
|
18
|
+
FileUtils.remove_entry_secure dir
|
19
|
+
end
|
20
|
+
end
|
15
21
|
end
|
data/spec/utility_spec.rb
CHANGED
@@ -46,11 +46,22 @@ describe Palimpsest::Utility do
|
|
46
46
|
describe "write" do
|
47
47
|
|
48
48
|
let(:file) { double File }
|
49
|
+
let(:mtime) { Time.now }
|
49
50
|
|
50
|
-
|
51
|
+
before :each do
|
51
52
|
allow(File).to receive(:open).with('path/to/file', 'w').and_yield(file)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "writes to file" do
|
52
56
|
expect(file).to receive(:write).with('data')
|
53
57
|
Palimpsest::Utility.write 'data', 'path/to/file'
|
54
58
|
end
|
59
|
+
|
60
|
+
it "can preserve atime and mtime" do
|
61
|
+
allow(file).to receive(:write)
|
62
|
+
allow(File).to receive(:mtime).with('path/to/file').and_return(mtime)
|
63
|
+
expect(File).to receive(:utime).with(mtime, mtime, 'path/to/file')
|
64
|
+
Palimpsest::Utility.write 'data', 'path/to/file', preserve: true
|
65
|
+
end
|
55
66
|
end
|
56
67
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: palimpsest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Boyd Sosenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -255,12 +255,17 @@ files:
|
|
255
255
|
- Rakefile
|
256
256
|
- lib/palimpsest.rb
|
257
257
|
- lib/palimpsest/assets.rb
|
258
|
+
- lib/palimpsest/component.rb
|
258
259
|
- lib/palimpsest/environment.rb
|
260
|
+
- lib/palimpsest/external.rb
|
261
|
+
- lib/palimpsest/site.rb
|
259
262
|
- lib/palimpsest/utility.rb
|
260
263
|
- lib/palimpsest/version.rb
|
261
264
|
- palimpsest.gemspec
|
262
265
|
- spec/assets_spec.rb
|
266
|
+
- spec/component_spec.rb
|
263
267
|
- spec/environment_spec.rb
|
268
|
+
- spec/external_spec.rb
|
264
269
|
- spec/spec_helper.rb
|
265
270
|
- spec/utility_spec.rb
|
266
271
|
homepage: https://github.com/razor-x/palimpsest
|
@@ -291,7 +296,9 @@ summary: Built flexible, simple, and customizable. Palimpsest runs on top of any
|
|
291
296
|
and easy integration with Kit.
|
292
297
|
test_files:
|
293
298
|
- spec/assets_spec.rb
|
299
|
+
- spec/component_spec.rb
|
294
300
|
- spec/environment_spec.rb
|
301
|
+
- spec/external_spec.rb
|
295
302
|
- spec/spec_helper.rb
|
296
303
|
- spec/utility_spec.rb
|
297
304
|
has_rdoc:
|