palimpsest 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/palimpsest.png)](http://badge.fury.io/rb/palimpsest)
|
12
13
|
[![Dependency Status](https://gemnasium.com/razor-x/palimpsest.png)](https://gemnasium.com/razor-x/palimpsest)
|
13
14
|
[![Build Status](https://travis-ci.org/razor-x/palimpsest.png?branch=master)](https://travis-ci.org/razor-x/palimpsest)
|
14
15
|
[![Coverage Status](https://coveralls.io/repos/razor-x/palimpsest/badge.png)](https://coveralls.io/r/razor-x/palimpsest)
|
15
16
|
[![Code Climate](https://codeclimate.com/github/razor-x/palimpsest.png)](https://codeclimate.com/github/razor-x/palimpsest)
|
17
|
+
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/428992451dfb452dbd522644cbb17f71 "githalytics.com")](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:
|