Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: brian-c/grabass
base: 9cf5dbd02c
...
head fork: brian-c/grabass
compare: a00eda194d
  • 6 commits
  • 8 files changed
  • 0 commit comments
  • 1 contributor
View
5 Gemfile
@@ -0,0 +1,5 @@
+source 'http://rubygems.org'
+
+group :development do
+ gem 'rspec'
+end
View
18 Gemfile.lock
@@ -0,0 +1,18 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ diff-lcs (1.1.3)
+ rspec (2.8.0)
+ rspec-core (~> 2.8.0)
+ rspec-expectations (~> 2.8.0)
+ rspec-mocks (~> 2.8.0)
+ rspec-core (2.8.0)
+ rspec-expectations (2.8.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.8.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ rspec
View
26 bin/grabass
@@ -1,8 +1,6 @@
#!/usr/bin/env ruby
require 'optparse'
-require 'json'
-require 'fileutils'
require 'grabass'
ABOUT = '''
@@ -26,6 +24,10 @@ optparse = OptionParser.new do |args|
args.on '-f', '--force', 'Replace existing files' do
options[:force] = true
end
+ options[:quiet] = false
+ args.on '-q', '--quiet', 'Don\'t log anything' do
+ options[:quiet] = true
+ end
end
optparse.parse!
@@ -37,19 +39,23 @@ if ARGV.length == 0
elsif ARGV.length == 1
if File.exists? ARGV[0]
manifest = Grabass::AssetManifest.new ARGV[0]
- manifest.fetch(options)
- finished = Time.now
+ results = manifest.grab options
else
puts "Asset manifest \"#{ARGV[0]}\" not found."
+ exit
end
elsif ARGV.length == 2
- asset = Grabass::Asset.new ARGV[0], ARGV[1]
- asset.fetch(options)
- finished = Time.now
+ asset = Grabass::Asset.new ARGV[0], {'*' => ARGV[1]}
+ results = asset.fetch options
+elsif ARGV.length == 3
+ asset = Grabass::Asset.new ARGV[0], {ARGV[1] => ARGV[2]}
+ results = asset.fetch options
end
-if finished
- puts '', "Grabass took in #{'%.2f' % (finished - started)} seconds."
-end
+finished = Time.now
+time = '%.2f' % (finished - started)
+pass = results[:pass]
+total = pass + results[:fail]
+puts "Grabass took in #{time} seconds. #{pass}/#{total} successful."
puts ''
View
14 example.json
@@ -1,7 +1,13 @@
[
+ "A single JavaScript file",
{"http://code.jquery.com/jquery-1.7.1.js": "scripts/jquery.js"},
- {"http://documentcloud.github.com/underscore/underscore.js": "scripts/underscore.js"},
- {"http://requirejs.org/docs/release/${version}/comments/require.js": "scripts/require.js"},
- {"http://spinejs.com/pages/download": "scripts/spine"},
- {"http://www.fontsquirrel.com/fontfacekit/TitilliumText": "scripts/TitilliumText"}
+
+ "A zipped directory with a selection",
+ {"http://spinejs.com/pages/download": {"lib": "scripts/spine"}},
+
+ "A zipped group of loose files with multiple selections",
+ {"http://www.fontsquirrel.com/fontfacekit/TitilliumText": [
+ {"*.{svg,ttf}": "fonts/titillium/normal"},
+ {"*.{eot, woff}": "fonts/titillium/weird"}
+ ]}
]
View
2  grabass.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'grabass'
- s.version = '0.0.1'
+ s.version = '0.1.0'
s.summary = 'Grabass'
s.description = 'Grab static assets and put them somewhere'
View
229 lib/grabass.rb
@@ -1,120 +1,199 @@
-#!/usr/bin/env ruby
-
require 'json'
require 'fileutils'
-module Grabass
- def self.underline(string, char = '-')
- "#{string}\n#{char * (string.length / char.length)}"
+class Grabass
+ def self.temp_dir
+ File.join ENV['TMPDIR'], 'grabass'
end
- def self.indent(string, prefix = '', spaces = 2)
- prefix + (' ' * (spaces - prefix.length)) + string
+ def self.indent(text, prefix = '', spaces = 2)
+ prefix + (' ' * (spaces - prefix.length)) + text
end
- SCRIPT_DIR = File.dirname __FILE__
- TEMP_DIR = "#{SCRIPT_DIR}/_grabass_temp"
+ def self.underline(text, char = '-')
+ "#{text}\n#{char * 72}"
+ end
- class AssetManifest
- def initialize(filename)
- @filename = filename
+ class Asset
+ attr_accessor :source, :selections, :type
- @assets = JSON.parse File.read filename
- @assets.map! do |definition|
- source = definition.keys[0]
- destination = definition[source]
+ def initialize(source, selections = [])
+ @source = source
+ @selections = selections # [{'pattern': 'destination'}]
- Asset.new source, destination
+ if source.end_with? '.git' or Dir.exists? File.join @source, '.git'
+ @type = :git
+ elsif @source.start_with? '/', '.', '~'
+ @type = :local
+ else
+ @type = :remote
end
end
- def fetch(options)
- puts ''
- puts Grabass::underline "Fetching assets from #{@filename}", '='
+ def grab(destination_root, options = {})
+ puts Grabass::underline @source unless options[:quite]
+ fetch options # Get the files into the temp_dir
+
+ results = {:pass => 0, :fail => 0}
+
+ @selections.each do |selection|
+ pattern, destination = selection.to_a[0]
+ absolute_destination = File.absolute_path destination, destination_root
- @assets.each do |asset|
- asset.fetch options
+ # TODO: Do this check before fetching things.
+ if File.exists? absolute_destination and not options[:force]
+ puts Grabass::indent "#{destination} already exists. Use --force to replace.", '!'
+ results[:fail] += 1
+ else
+ if File.exists? absolute_destination
+ puts Grabass::indent "Replacing existing #{destination}", '!' unless options[:quiet]
+ FileUtils.remove_entry absolute_destination, true
+ end
+
+ Dir.chdir temp_dir
+ selected_files = Dir.glob(pattern)
+
+ if selected_files.length == 1
+ FileUtils.makedirs File.dirname absolute_destination
+ `mv #{selected_files[0]} #{absolute_destination}`
+ else
+ FileUtils.makedirs absolute_destination
+ FileUtils.move selected_files, absolute_destination
+ end
+
+ results[:pass] += 1
+ end
end
+
+ puts '' unless options[:quiet] # Blank line between assets
+ results
end
- end
- class Asset
- def initialize(source, destination)
- @source, @destination = source, destination
- @temp_file = TEMP_DIR + '/' + source.gsub(/\W+/, '-')
+ def fetch(options = {})
+ `rm -rf #{temp_dir}`
+
+ if @type == :local
+ elsif @type == :remote
+ download_remote options
+ if is_zipped?
+ unzip
+ end
+ elsif @type == :git
+ clone_git_repo
+ end
+
+ Dir.chdir temp_dir
+ Dir['*']
end
- def fetch(options)
- FileUtils.remove_dir TEMP_DIR if File.exists? TEMP_DIR
- FileUtils.mkpath TEMP_DIR
+ def copy_local
+ end
- puts ''
- puts Grabass::underline @source
+ def download_remote(options = {})
+ puts Grabass::indent "Downloading #{@source}" unless options[:quiet]
+ `curl --silent --location #{@source} --output #{temp_file}`
+ end
- if not options[:force] and File.exists? @destination
- puts Grabass::indent 'Destination file already exists!', '!'
- puts Grabass::indent 'Use the --force option to overwrite it.'
- else
- if download
- unzip if mime_type.include? 'zip'
- move_to_destination options[:force]
- else
- puts Grabass::indent 'Download failed!', '!'
+ def is_zipped?
+ `file --brief --mime-type #{temp_file}`.include? 'zip'
+ end
+
+ def unzip(options ={})
+ puts Grabass::indent "Unzipping..." unless options[:quiet]
+ `unzip #{temp_file} -d #{temp_dir}`
+ FileUtils.remove temp_file
+
+ # If the zip file expanded into a single directory (they usually do),
+ # bring its contents up into temp_dir
+ # since that's the root from which we'll make our selections
+
+ Dir.chdir temp_dir
+ if Dir['*'].length == 1
+ single_unzipped_thing = Dir['*'][0]
+ if File.directory? single_unzipped_thing
+ `mv #{File.join temp_dir, single_unzipped_thing, '*'} #{temp_dir}`
+ FileUtils.remove_dir single_unzipped_thing
end
+ else
+ puts Grabass::indent "Zip archive contained loose contents", '>' unless options[:quiet]
end
+ end
- FileUtils.remove_dir TEMP_DIR
+ def clone_git_repo
+ puts Grabass::indent "Temporarily cloning #{@source}" unless options[:quiet]
+ `git clone --quiet #{@source} #{temp_dir}`
end
- def download
- puts Grabass::indent "Downloading #{@source}"
- `curl --silent --location #{@source} --output "#{@temp_file}"`
- File.exists? @temp_file
+ private
+
+ def short_name
+ @source.gsub(/\W/, '')
end
- def mime_type
- `file --brief --mime-type #{@temp_file}`
+ def temp_dir
+ holding = File.join Grabass::temp_dir, short_name
+ FileUtils.makedirs holding
+ holding
end
- def unzip
- puts Grabass::indent 'Unzipping...'
+ def temp_file
+ File.join temp_dir, short_name
+ end
+ end
- # Remember what files exist now so we can see exactly what gets unzipped.
- originals = Dir.entries TEMP_DIR
+ class Comment
+ def initialize(content)
+ @content = content
+ end
- `unzip #{@temp_file} -d #{TEMP_DIR}`
+ def display(options)
+ puts Grabass::underline @content unless options[:quiet]
+ end
+ end
- FileUtils.rm "#{@temp_file}"
+ class AssetManifest
+ def initialize(filename)
+ @filename = filename
+ @root = File.absolute_path File.dirname filename
- new_files = Dir.entries(TEMP_DIR) - originals
- new_files.map! do |filename|
- "#{TEMP_DIR}/#{filename}"
- end
+ records = JSON.parse File.read @filename
+ @records = records.map do |record|
+ if record.is_a? String
+ Comment.new record
+ else
+ source, selections = record.to_a[0]
- if new_files.length == 1
- # Rename to the original temp name if the zip only unzipped one thing.
- FileUtils.move new_files[0], @temp_file
- else
- # Pack more than one thing into a single directory with the temp name.
- FileUtils.mkpath @temp_file
- FileUtils.move new_files, @temp_file
+ if selections.is_a? String
+ selections = [{'*' => selections}]
+ elsif selections.is_a? Hash
+ selections = [selections]
+ end
+
+ Asset.new source, selections
+ end
end
end
- def move_to_destination(force)
- if File.exists? @destination and force
- puts Grabass::indent "Replacing existing #{@destination}"
+ def grab(options = {})
+ results = {:pass => 0, :fail => 0}
- if Dir.exists? @destination
- FileUtils.remove_dir @destination
- else
- FileUtils.remove @destination
+ unless options[:quiet]
+ puts ''
+ puts Grabass::underline "Fetching assets from #{@filename}", '='
+ puts ''
+ end
+
+ @records.each do |record|
+ if record.is_a? Comment
+ record.display options
+ elsif record.is_a? Asset
+ asset_results = record.grab @root, options
+ results[:pass] += asset_results[:pass]
+ results[:fail] += asset_results[:fail]
end
end
- puts Grabass::indent "Moving to #{@destination}..."
- FileUtils.mkpath(File.dirname(@destination))
- FileUtils.move @temp_file, @destination
+ results
end
end
end
View
9 new-format.json
@@ -0,0 +1,9 @@
+[
+ "COMMENT",
+ {"SOURCE": "DESTINATION"},
+ {"SOURCE": {"SELECTION": "DESTINATION"}},
+ {"SOURCE": [
+ {"SELECTION1": "DESTINATION1"},
+ {"SELECTION2": "DESTINATION2"}
+ ]}
+]
View
91 spec/grabass_lib_spec.rb
@@ -0,0 +1,91 @@
+require 'grabass'
+require 'fileutils'
+
+TEMP_DESTINATION = File.join ENV['TMPDIR'], 'grabass-test-output'
+
+describe 'Grabass' do
+ SINGLE_FILE = 'http://code.jquery.com/jquery-1.7.1.js'
+
+ ZIPPED_DIR = 'https://nodeload.github.com/maccman/spine/zipball/master'
+ ZIPPED_DIR_LENGTH = 8
+
+ ZIPPED_GROUP = 'http://www.fontsquirrel.com/fontfacekit/TitilliumText'
+ ZIPPED_GROUP_LENGTH = 27
+
+ GIT_REPO = 'git://github.com/maccman/spine.git'
+ GIT_REPO_LENGTH = 8
+
+ describe 'Asset' do
+ describe 'initialize' do
+ it 'should recognize a local absolute path'
+
+ it 'should recognize a local relative path'
+
+ it 'should recognize a remote file' do
+ asset = Grabass::Asset.new 'http://example.com/foo/bar.txt'
+ asset.type.should == :remote
+ end
+
+ it 'should recognize a Git repo over Git' do
+ asset = Grabass::Asset.new 'git://github.com/foo/bar.git'
+ asset.type.should == :git
+ end
+
+ it 'should recognize a Git repo over HTTP' do
+ asset = Grabass::Asset.new 'https://github.com/foo/bar.git'
+ asset.type.should == :git
+ end
+ end
+
+ describe 'fetch' do
+ it 'should copy a local file'
+
+ it 'should download a file over HTTP' do
+ asset = Grabass::Asset.new SINGLE_FILE
+ asset.fetch.length.should == 1
+ end
+
+ it 'should unzip a zipped directory and work with its contents' do
+ asset = Grabass::Asset.new ZIPPED_DIR
+ asset.fetch.length.should == ZIPPED_DIR_LENGTH
+ end
+
+ it 'should unzip a zipped file group and work with the files' do
+ asset = Grabass::Asset.new ZIPPED_GROUP
+ asset.fetch.length.should == ZIPPED_GROUP_LENGTH
+ end
+
+ it 'should clone a Git repo temporarily' do
+ asset = Grabass::Asset.new GIT_REPO
+ asset.fetch.length.should == GIT_REPO_LENGTH
+ end
+ end
+
+ describe 'make_selection' do
+ it 'should automatically select a single file' do
+ asset = Grabass::Asset.new SINGLE_FILE
+ asset.fetch
+ asset.make_selection('*').length.should == 1
+ end
+
+ it 'should automatically select all files from a directory' do
+ asset = Grabass::Asset.new ZIPPED_DIR
+ asset.fetch
+ asset.make_selection('*').length.should == ZIPPED_DIR_LENGTH
+ end
+
+ it 'should automatically select all files from a Git repo'
+
+ it 'should select a given glob of files'
+ end
+
+ describe 'placement' do
+ it 'should directly move a single selection to its destination'
+
+ it 'should move a multi-selection to a directory'
+ end
+ end
+
+ describe 'AssetManifest' do
+ end
+end

No commit comments for this range

Something went wrong with that request. Please try again.