grabass 0.1.0 → 0.2.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.
Files changed (3) hide show
  1. data/bin/grabass +31 -46
  2. data/lib/grabass.rb +150 -104
  3. metadata +2 -2
@@ -1,61 +1,46 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'optparse'
4
- require 'grabass'
3
+ require_relative '../lib/grabass'
5
4
 
6
- ABOUT = '''
7
- Grabass
8
- Grab static assets and put them somewhere.
9
- http://github.com/brian-c/grabass
10
-
11
- Use it like this:
12
- grabass assets.json
13
- # That JSON looks like this:
14
- [{"http://some.remote/file.js": "./lib/file.js"}]
15
-
16
- grabass http://some.remote/file.js ./lib/file.js
17
- grabass http://some.remote/archive.zip ./lib/archive/
18
- '''
5
+ commands = ['install', 'help']
6
+ command = ARGV.shift if commands.include? ARGV[0]
7
+ command ||= commands[0]
19
8
 
20
9
  options = {}
10
+ options[:force] = (ARGV.delete '--force') || (ARGV.delete '-f')
11
+ options[:quiet] = (ARGV.delete '--quiet') || (ARGV.delete '-q')
12
+ options[:help] = (ARGV.delete '--help') || (ARGV.delete '-h')
13
+ options[:version] = (ARGV.delete '--version') || (ARGV.delete '-v')
21
14
 
22
- optparse = OptionParser.new do |args|
23
- options[:force] = false
24
- args.on '-f', '--force', 'Replace existing files' do
25
- options[:force] = true
26
- end
27
- options[:quiet] = false
28
- args.on '-q', '--quiet', 'Don\'t log anything' do
29
- options[:quiet] = true
30
- end
31
- end
15
+ manifest = ARGV.shift if not ARGV[0].nil? and File.exists? ARGV[0]
16
+ manifest = Grabass::AssetManifest.new manifest || 'assets.json'
32
17
 
33
- optparse.parse!
18
+ destinations = ARGV
34
19
 
35
- started = Time.now
20
+ unless options[:quiet]
21
+ started = Time.now
22
+ end
36
23
 
37
- if ARGV.length == 0
38
- puts ABOUT
39
- elsif ARGV.length == 1
40
- if File.exists? ARGV[0]
41
- manifest = Grabass::AssetManifest.new ARGV[0]
42
- results = manifest.grab options
24
+ case command
25
+ when 'help'
26
+ puts 'Help!'
27
+ when 'install'
28
+ if destinations.length == 0
29
+ # Grab entire manifest
30
+ results = manifest.install options
43
31
  else
44
- puts "Asset manifest \"#{ARGV[0]}\" not found."
32
+ # Grab the given destinations
33
+ puts 'TODO: Install specific destinations from the command line'
45
34
  exit
46
35
  end
47
- elsif ARGV.length == 2
48
- asset = Grabass::Asset.new ARGV[0], {'*' => ARGV[1]}
49
- results = asset.fetch options
50
- elsif ARGV.length == 3
51
- asset = Grabass::Asset.new ARGV[0], {ARGV[1] => ARGV[2]}
52
- results = asset.fetch options
53
36
  end
54
37
 
55
- finished = Time.now
56
- time = '%.2f' % (finished - started)
57
- pass = results[:pass]
58
- total = pass + results[:fail]
38
+ unless options[:quiet] or results.nil?
39
+ time = '%.2f' % (Time.now - started)
59
40
 
60
- puts "Grabass took in #{time} seconds. #{pass}/#{total} successful."
61
- puts ''
41
+ pass = results[:pass]
42
+ total = pass + results[:fail]
43
+
44
+ puts "Grabass took in #{time} seconds. #{pass}/#{total} successful."
45
+ puts ''
46
+ end
@@ -14,130 +14,178 @@ class Grabass
14
14
  "#{text}\n#{char * 72}"
15
15
  end
16
16
 
17
- class Asset
18
- attr_accessor :source, :selections, :type
19
-
20
- def initialize(source, selections = [])
21
- @source = source
22
- @selections = selections # [{'pattern': 'destination'}]
17
+ class Source
18
+ def initialize(location)
19
+ @location = location
23
20
 
24
- if source.end_with? '.git' or Dir.exists? File.join @source, '.git'
21
+ if @location.end_with? '.git' or Dir.exists? File.join @location, '.git'
25
22
  @type = :git
26
- elsif @source.start_with? '/', '.', '~'
23
+ elsif @location.start_with? '/', '.', '~'
27
24
  @type = :local
28
25
  else
29
26
  @type = :remote
30
27
  end
31
28
  end
32
29
 
33
- def grab(destination_root, options = {})
34
- puts Grabass::underline @source unless options[:quite]
35
- fetch options # Get the files into the temp_dir
36
-
37
- results = {:pass => 0, :fail => 0}
38
-
39
- @selections.each do |selection|
40
- pattern, destination = selection.to_a[0]
41
- absolute_destination = File.absolute_path destination, destination_root
42
-
43
- # TODO: Do this check before fetching things.
44
- if File.exists? absolute_destination and not options[:force]
45
- puts Grabass::indent "#{destination} already exists. Use --force to replace.", '!'
46
- results[:fail] += 1
47
- else
48
- if File.exists? absolute_destination
49
- puts Grabass::indent "Replacing existing #{destination}", '!' unless options[:quiet]
50
- FileUtils.remove_entry absolute_destination, true
51
- end
52
-
53
- Dir.chdir temp_dir
54
- selected_files = Dir.glob(pattern)
55
-
56
- if selected_files.length == 1
57
- FileUtils.makedirs File.dirname absolute_destination
58
- `mv #{selected_files[0]} #{absolute_destination}`
59
- else
60
- FileUtils.makedirs absolute_destination
61
- FileUtils.move selected_files, absolute_destination
62
- end
63
-
64
- results[:pass] += 1
65
- end
66
- end
67
-
68
- puts '' unless options[:quiet] # Blank line between assets
69
- results
30
+ def clean_up
31
+ FileUtils.rm_rf temp_dir
70
32
  end
71
33
 
72
34
  def fetch(options = {})
73
- `rm -rf #{temp_dir}`
35
+ clean_up
36
+ FileUtils.mkdir_p temp_dir
74
37
 
75
- if @type == :local
76
- elsif @type == :remote
38
+ case @type
39
+ when :local
40
+ copy_local options
41
+ when :remote
77
42
  download_remote options
78
- if is_zipped?
79
- unzip
80
- end
81
- elsif @type == :git
82
- clone_git_repo
43
+ unzip options if is_zipped?
44
+ when :git
45
+ clone_git_repo options
83
46
  end
84
47
 
85
- Dir.chdir temp_dir
86
- Dir['*']
48
+ temp_dir
87
49
  end
88
50
 
89
- def copy_local
51
+ def copy_local(options = {})
52
+ # TODO
90
53
  end
91
54
 
92
55
  def download_remote(options = {})
93
- puts Grabass::indent "Downloading #{@source}" unless options[:quiet]
94
- `curl --silent --location #{@source} --output #{temp_file}`
56
+ puts "Downloading #{@location}" unless options[:quiet]
57
+ wd = FileUtils.pwd
58
+ FileUtils.cd temp_dir
59
+ `curl --silent --location #{@location} --remote-name --remote-header-name`
60
+ FileUtils.cd wd
95
61
  end
96
62
 
97
63
  def is_zipped?
98
- `file --brief --mime-type #{temp_file}`.include? 'zip'
64
+ `file --mime-type --brief #{Dir[File.join temp_dir, '*']}`.include? 'zip'
99
65
  end
100
66
 
101
- def unzip(options ={})
102
- puts Grabass::indent "Unzipping..." unless options[:quiet]
103
- `unzip #{temp_file} -d #{temp_dir}`
104
- FileUtils.remove temp_file
67
+ def unzip(options = {})
68
+ puts "Unzipping..." unless options[:quiet]
69
+
70
+ download = Dir[File.join temp_dir, '*'][0]
71
+ `unzip #{download} -d #{temp_dir}`
72
+ FileUtils.rm download
105
73
 
106
74
  # If the zip file expanded into a single directory (they usually do),
107
75
  # bring its contents up into temp_dir
108
76
  # since that's the root from which we'll make our selections
109
77
 
110
- Dir.chdir temp_dir
111
- if Dir['*'].length == 1
112
- single_unzipped_thing = Dir['*'][0]
78
+ temp_dir_contents = Dir[File.join temp_dir, '*']
79
+ if temp_dir_contents.length == 1
80
+ single_unzipped_thing = temp_dir_contents[0]
81
+
113
82
  if File.directory? single_unzipped_thing
114
- `mv #{File.join temp_dir, single_unzipped_thing, '*'} #{temp_dir}`
115
- FileUtils.remove_dir single_unzipped_thing
83
+ FileUtils.mv Dir[File.join single_unzipped_thing, '*'], temp_dir
84
+ FileUtils.rm_r single_unzipped_thing
116
85
  end
117
- else
118
- puts Grabass::indent "Zip archive contained loose contents", '>' unless options[:quiet]
119
86
  end
120
87
  end
121
88
 
122
- def clone_git_repo
123
- puts Grabass::indent "Temporarily cloning #{@source}" unless options[:quiet]
124
- `git clone --quiet #{@source} #{temp_dir}`
89
+ def clone_git_repo(options = {})
90
+ puts Grabass::indent "Temporarily cloning #{@location}" unless options[:quiet]
91
+ `git clone --quiet #{@location} #{temp_dir}`
125
92
  end
126
93
 
127
- private
128
-
129
94
  def short_name
130
- @source.gsub(/\W/, '')
95
+ @location.gsub(/\W/, '')
131
96
  end
132
97
 
133
98
  def temp_dir
134
- holding = File.join Grabass::temp_dir, short_name
135
- FileUtils.makedirs holding
136
- holding
99
+ File.join Grabass::temp_dir, short_name
100
+ end
101
+ end
102
+
103
+ class Selection
104
+ def initialize(glob, destination)
105
+ @glob, @destination = glob, destination
106
+ end
107
+
108
+ def make_from(source_dir, options)
109
+ selection = Dir[File.join source_dir, @glob]
110
+
111
+ if selection.length == 0
112
+ puts "No files selected with glob \"#{@glob}\"" unless options[:quiet]
113
+ return false
114
+ elsif selection.length == 1
115
+ puts "Moving \"#{File.basename selection[0]}\" to #{@destination}" unless options[:quiet]
116
+
117
+ if File.exists? @destination
118
+ if options[:force]
119
+ if File.directory?(selection[0]) == File.directory?(@destination)
120
+ puts "Removing existing \"#{@destination}\"..." unless options[:quiet]
121
+ FileUtils.rm_rf @destination
122
+ end
123
+ else
124
+ puts "#{@destination} already exists. Use --force to replace." unless options[:quiet]
125
+ return false
126
+ end
127
+ end
128
+
129
+ FileUtils.mkdir_p File.dirname @destination
130
+ FileUtils.mv selection[0], @destination
131
+ else
132
+ puts "Moving #{selection.length} \"#{@glob}\" to #{@destination}" unless options[:quiet]
133
+
134
+ failures = 0
135
+ selection.each do |file|
136
+ destination_file = File.join @destination, file.sub(source_dir, '')
137
+ if File.exists? destination_file
138
+ if options[:force]
139
+ if File.directory?(file) == File.directory?(destination_file)
140
+ puts "Removing \"#{destination_file}\"..." unless options[:quiet]
141
+ FileUtils.rm_rf destination_file
142
+ end
143
+ else
144
+ puts "#{destination_file} already exists. Use --force to replace." unless options[:quiet]
145
+ failures += 1
146
+ end
147
+ end
148
+ end
149
+
150
+ return false if failures > 0
151
+
152
+ FileUtils.mkdir_p @destination
153
+ FileUtils.mv selection, @destination
154
+ end
155
+
156
+ true
137
157
  end
158
+ end
159
+
160
+ class Asset
161
+ def initialize(source, selections)
162
+ @source = Source.new(source)
138
163
 
139
- def temp_file
140
- File.join temp_dir, short_name
164
+ @selections = []
165
+ selections.each do |selection|
166
+ selection.each do |glob, destination|
167
+ @selections << Selection.new(glob, destination)
168
+ end
169
+ end
170
+ end
171
+
172
+ def install(options = {})
173
+ results = {:pass => 0, :fail => 0}
174
+
175
+ source_dir = @source.fetch
176
+
177
+ @selections.each do |selection|
178
+ success = selection.make_from source_dir, options
179
+
180
+ if success
181
+ results[:pass] += 1
182
+ else
183
+ results[:fail] += 1
184
+ end
185
+ end
186
+
187
+ puts '' unless options[:quiet] # Blank line between assets
188
+ results
141
189
  end
142
190
  end
143
191
 
@@ -147,26 +195,28 @@ class Grabass
147
195
  end
148
196
 
149
197
  def display(options)
150
- puts Grabass::underline @content unless options[:quiet]
198
+ puts @content unless options[:quiet]
151
199
  end
152
200
  end
153
201
 
154
202
  class AssetManifest
155
203
  def initialize(filename)
156
204
  @filename = filename
157
- @root = File.absolute_path File.dirname filename
205
+ root = File.dirname File.absolute_path filename
158
206
 
159
- records = JSON.parse File.read @filename
160
- @records = records.map do |record|
161
- if record.is_a? String
162
- Comment.new record
207
+ @assets = JSON.parse(File.read @filename).map do |item|
208
+ if item.is_a? String
209
+ Comment.new item
163
210
  else
164
- source, selections = record.to_a[0]
211
+ source, selections = item.to_a[0]
165
212
 
166
- if selections.is_a? String
167
- selections = [{'*' => selections}]
168
- elsif selections.is_a? Hash
169
- selections = [selections]
213
+ selections = {'*' => selections} if selections.is_a? String
214
+ selections = [selections] if selections.is_a? Hash
215
+
216
+ selections.map! do |selection|
217
+ selection.each do |glob, destination|
218
+ selection[glob] = File.absolute_path destination, root
219
+ end
170
220
  end
171
221
 
172
222
  Asset.new source, selections
@@ -174,20 +224,16 @@ class Grabass
174
224
  end
175
225
  end
176
226
 
177
- def grab(options = {})
178
- results = {:pass => 0, :fail => 0}
227
+ def install(options = {})
228
+ puts "Installing assets from #{@filename}", '' unless options[:quiet]
179
229
 
180
- unless options[:quiet]
181
- puts ''
182
- puts Grabass::underline "Fetching assets from #{@filename}", '='
183
- puts ''
184
- end
230
+ results = {:pass => 0, :fail => 0}
185
231
 
186
- @records.each do |record|
187
- if record.is_a? Comment
188
- record.display options
189
- elsif record.is_a? Asset
190
- asset_results = record.grab @root, options
232
+ @assets.each do |asset|
233
+ if asset.is_a? Comment
234
+ asset.display options
235
+ elsif asset.is_a? Asset
236
+ asset_results = asset.install options
191
237
  results[:pass] += asset_results[:pass]
192
238
  results[:fail] += asset_results[:fail]
193
239
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grabass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-11 00:00:00.000000000 Z
12
+ date: 2012-03-26 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Grab static assets and put them somewhere
15
15
  email: brian.carstensen@gmail.com