compass 0.11.beta.7 → 0.11.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.
- data/VERSION.yml +2 -2
- data/frameworks/compass/stylesheets/compass/layout/_grid-background.scss +40 -22
- data/frameworks/compass/stylesheets/compass/utilities/sprites/_base.scss +6 -1
- data/frameworks/compass/templates/extension/manifest.rb +8 -2
- data/lib/compass/commands/print_version.rb +3 -0
- data/lib/compass/commands/update_project.rb +23 -9
- data/lib/compass/commands/watch_project.rb +41 -8
- data/lib/compass/compiler.rb +2 -3
- data/lib/compass/configuration.rb +34 -0
- data/lib/compass/configuration/adapters.rb +6 -2
- data/lib/compass/configuration/data.rb +1 -0
- data/lib/compass/configuration/defaults.rb +1 -1
- data/lib/compass/configuration/serialization.rb +1 -0
- data/lib/compass/exec/project_options_parser.rb +3 -3
- data/lib/compass/sass_extensions/functions/gradient_support.rb +81 -65
- data/lib/compass/sass_extensions/sprites/sprites.rb +9 -0
- data/lib/compass/version.rb +1 -1
- data/test/configuration_test.rb +67 -6
- data/test/fixtures/stylesheets/blueprint/css/screen.css +1 -1
- data/test/fixtures/stylesheets/blueprint/css/single-imports/debug.css +1 -1
- data/test/fixtures/stylesheets/compass/css/gradients.css +46 -24
- data/test/fixtures/stylesheets/compass/css/grid_background.css +8 -0
- data/test/fixtures/stylesheets/compass/sass/gradients.sass +8 -2
- data/test/fixtures/stylesheets/compass/sass/grid_background.scss +4 -0
- metadata +18 -19
- data/lib/vendor/fssm/fssm.rb +0 -33
- data/lib/vendor/fssm/fssm/backends/fsevents.rb +0 -36
- data/lib/vendor/fssm/fssm/backends/inotify.rb +0 -26
- data/lib/vendor/fssm/fssm/backends/polling.rb +0 -25
- data/lib/vendor/fssm/fssm/backends/rubycocoa/fsevents.rb +0 -131
- data/lib/vendor/fssm/fssm/monitor.rb +0 -26
- data/lib/vendor/fssm/fssm/path.rb +0 -91
- data/lib/vendor/fssm/fssm/pathname.rb +0 -502
- data/lib/vendor/fssm/fssm/state/directory.rb +0 -57
- data/lib/vendor/fssm/fssm/state/file.rb +0 -24
- data/lib/vendor/fssm/fssm/support.rb +0 -63
- data/lib/vendor/fssm/fssm/tree.rb +0 -176
data/lib/vendor/fssm/fssm.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
dir = File.dirname(__FILE__)
|
2
|
-
$LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
|
3
|
-
|
4
|
-
module FSSM
|
5
|
-
FileNotFoundError = Class.new(StandardError)
|
6
|
-
CallbackError = Class.new(StandardError)
|
7
|
-
|
8
|
-
class << self
|
9
|
-
def dbg(msg=nil)
|
10
|
-
STDERR.puts(msg)
|
11
|
-
end
|
12
|
-
|
13
|
-
def monitor(*args, &block)
|
14
|
-
monitor = FSSM::Monitor.new
|
15
|
-
FSSM::Support.use_block(args.empty? ? monitor : monitor.path(*args), block)
|
16
|
-
|
17
|
-
monitor.run
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
require 'thread'
|
23
|
-
|
24
|
-
require 'fssm/pathname'
|
25
|
-
require 'fssm/support'
|
26
|
-
require 'fssm/tree'
|
27
|
-
require 'fssm/path'
|
28
|
-
require 'fssm/state/directory'
|
29
|
-
require 'fssm/state/file'
|
30
|
-
require 'fssm/monitor'
|
31
|
-
|
32
|
-
require "fssm/backends/#{FSSM::Support.backend.downcase}"
|
33
|
-
FSSM::Backends::Default = FSSM::Backends.const_get(FSSM::Support.backend)
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'rubycocoa/fsevents')
|
2
|
-
|
3
|
-
module FSSM::Backends
|
4
|
-
class FSEvents
|
5
|
-
def initialize
|
6
|
-
@handlers = {}
|
7
|
-
@fsevents = []
|
8
|
-
end
|
9
|
-
|
10
|
-
def add_handler(handler, preload=true)
|
11
|
-
@handlers[handler.path.to_s] = handler
|
12
|
-
|
13
|
-
fsevent = Rucola::FSEvents.new(handler.path.to_s, {:latency => 0.5}) do |events|
|
14
|
-
events.each do |event|
|
15
|
-
handler.refresh(event.path)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
fsevent.create_stream
|
20
|
-
handler.refresh(nil, true) if preload
|
21
|
-
fsevent.start
|
22
|
-
@fsevents << fsevent
|
23
|
-
end
|
24
|
-
|
25
|
-
def run
|
26
|
-
begin
|
27
|
-
OSX.CFRunLoopRun
|
28
|
-
rescue Interrupt
|
29
|
-
@fsevents.each do |fsev|
|
30
|
-
fsev.stop
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module FSSM::Backends
|
2
|
-
class Inotify
|
3
|
-
def initialize
|
4
|
-
@notifier = INotify::Notifier.new
|
5
|
-
end
|
6
|
-
|
7
|
-
def add_handler(handler, preload=true)
|
8
|
-
@notifier.watch(handler.path.to_s, :recursive, :attrib, :modify, :create,
|
9
|
-
:delete, :delete_self, :moved_from, :moved_to, :move_self) do |event|
|
10
|
-
path = FSSM::Pathname.for(event.absolute_name)
|
11
|
-
path = path.dirname unless event.name == "" # Event on root directory
|
12
|
-
handler.refresh(path)
|
13
|
-
end
|
14
|
-
|
15
|
-
handler.refresh(nil, true) if preload
|
16
|
-
end
|
17
|
-
|
18
|
-
def run
|
19
|
-
begin
|
20
|
-
@notifier.run
|
21
|
-
rescue Interrupt
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module FSSM::Backends
|
2
|
-
class Polling
|
3
|
-
def initialize(options={})
|
4
|
-
@handlers = []
|
5
|
-
@latency = options[:latency] || 1.5
|
6
|
-
end
|
7
|
-
|
8
|
-
def add_handler(handler, preload=true)
|
9
|
-
handler.refresh(nil, true) if preload
|
10
|
-
@handlers << handler
|
11
|
-
end
|
12
|
-
|
13
|
-
def run
|
14
|
-
begin
|
15
|
-
loop do
|
16
|
-
start = Time.now.to_f
|
17
|
-
@handlers.each {|handler| handler.refresh}
|
18
|
-
nap_time = @latency - (Time.now.to_f - start)
|
19
|
-
sleep nap_time if nap_time > 0
|
20
|
-
end
|
21
|
-
rescue Interrupt
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,131 +0,0 @@
|
|
1
|
-
OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework'
|
2
|
-
|
3
|
-
module Rucola
|
4
|
-
class FSEvents
|
5
|
-
class FSEvent
|
6
|
-
attr_reader :fsevents_object
|
7
|
-
attr_reader :id
|
8
|
-
attr_reader :path
|
9
|
-
|
10
|
-
def initialize(fsevents_object, id, path)
|
11
|
-
@fsevents_object, @id, @path = fsevents_object, id, path
|
12
|
-
end
|
13
|
-
|
14
|
-
# Returns an array of the files/dirs in the path that the event occurred in.
|
15
|
-
# The files are sorted by the modification time, the first entry is the last modified file.
|
16
|
-
def files
|
17
|
-
Dir.glob("#{File.expand_path(path)}/*").sort_by {|f| File.mtime(f) }.reverse
|
18
|
-
end
|
19
|
-
|
20
|
-
# Returns the last modified file in the path that the event occurred in.
|
21
|
-
def last_modified_file
|
22
|
-
files.first
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class StreamError < StandardError;
|
27
|
-
end
|
28
|
-
|
29
|
-
attr_reader :paths
|
30
|
-
attr_reader :stream
|
31
|
-
|
32
|
-
attr_accessor :allocator
|
33
|
-
attr_accessor :context
|
34
|
-
attr_accessor :since
|
35
|
-
attr_accessor :latency
|
36
|
-
attr_accessor :flags
|
37
|
-
|
38
|
-
# Initializes a new FSEvents `watchdog` object and starts watching the directories you specify for events. The
|
39
|
-
# block is used as a handler for events, which are passed as the block's argument. This method is the easiest
|
40
|
-
# way to start watching some directories if you don't care about the details of setting up the event stream.
|
41
|
-
#
|
42
|
-
# Rucola::FSEvents.start_watching('/tmp') do |events|
|
43
|
-
# events.each { |event| log.debug("#{event.files.inspect} were changed.") }
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# Rucola::FSEvents.start_watching('/var/log/system.log', '/var/log/secure.log', :since => last_id, :latency => 5) do
|
47
|
-
# Growl.notify("Something was added to your log files!")
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# Note that the method also returns the FSEvents object. This enables you to control the event stream if you want to.
|
51
|
-
#
|
52
|
-
# fsevents = Rucola::FSEvents.start_watching('/Volumes') do |events|
|
53
|
-
# events.each { |event| Growl.notify("Volume changes: #{event.files.to_sentence}") }
|
54
|
-
# end
|
55
|
-
# fsevents.stop
|
56
|
-
def self.start_watching(*params, &block)
|
57
|
-
fsevents = new(*params, &block)
|
58
|
-
fsevents.create_stream
|
59
|
-
fsevents.start
|
60
|
-
fsevents
|
61
|
-
end
|
62
|
-
|
63
|
-
# Creates a new FSEvents `watchdog` object. You can specify a list of paths to watch and options to control the
|
64
|
-
# behaviour of the watchdog. The block you pass serves as a callback when an event is generated on one of the
|
65
|
-
# specified paths.
|
66
|
-
#
|
67
|
-
# fsevents = FSEvents.new('/etc/passwd') { Mailer.send_mail("Someone touched the password file!") }
|
68
|
-
# fsevents.create_stream
|
69
|
-
# fsevents.start
|
70
|
-
#
|
71
|
-
# fsevents = FSEvents.new('/home/upload', :since => UploadWatcher.last_event_id) do |events|
|
72
|
-
# events.each do |event|
|
73
|
-
# UploadWatcher.last_event_id = event.id
|
74
|
-
# event.files.each do |file|
|
75
|
-
# UploadWatcher.logfile.append("#{file} was changed")
|
76
|
-
# end
|
77
|
-
# end
|
78
|
-
# end
|
79
|
-
#
|
80
|
-
# *:since: The service will report events that have happened after the supplied event ID. Never use 0 because that
|
81
|
-
# will cause every fsevent since the "beginning of time" to be reported. Use OSX::KFSEventStreamEventIdSinceNow
|
82
|
-
# if you want to receive events that have happened after this call. (Default: OSX::KFSEventStreamEventIdSinceNow).
|
83
|
-
# You can find the ID's passed with :since in the events passed to your block.
|
84
|
-
# *:latency: Number of seconds to wait until an FSEvent is reported, this allows the service to bundle events. (Default: 0.0)
|
85
|
-
#
|
86
|
-
# Please refer to the Cocoa documentation for the rest of the options.
|
87
|
-
def initialize(*params, &block)
|
88
|
-
raise ArgumentError, 'No callback block was specified.' unless block_given?
|
89
|
-
|
90
|
-
options = params.last.kind_of?(Hash) ? params.pop : {}
|
91
|
-
@paths = params.flatten
|
92
|
-
|
93
|
-
paths.each { |path| raise ArgumentError, "The specified path (#{path}) does not exist." unless File.exist?(path) }
|
94
|
-
|
95
|
-
@allocator = options[:allocator] || OSX::KCFAllocatorDefault
|
96
|
-
@context = options[:context] || nil
|
97
|
-
@since = options[:since] || OSX::KFSEventStreamEventIdSinceNow
|
98
|
-
@latency = options[:latency] || 0.0
|
99
|
-
@flags = options[:flags] || 0
|
100
|
-
@stream = options[:stream] || nil
|
101
|
-
|
102
|
-
@user_callback = block
|
103
|
-
@callback = Proc.new do |stream, client_callback_info, number_of_events, paths_pointer, event_flags, event_ids|
|
104
|
-
paths_pointer.regard_as('*')
|
105
|
-
events = []
|
106
|
-
number_of_events.times {|i| events << Rucola::FSEvents::FSEvent.new(self, event_ids[i], paths_pointer[i]) }
|
107
|
-
@user_callback.call(events)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Create the stream.
|
112
|
-
# Raises a Rucola::FSEvents::StreamError if the stream could not be created.
|
113
|
-
def create_stream
|
114
|
-
@stream = OSX.FSEventStreamCreate(@allocator, @callback, @context, @paths, @since, @latency, @flags)
|
115
|
-
raise(StreamError, 'Unable to create FSEvents stream.') unless @stream
|
116
|
-
OSX.FSEventStreamScheduleWithRunLoop(@stream, OSX.CFRunLoopGetCurrent, OSX::KCFRunLoopDefaultMode)
|
117
|
-
end
|
118
|
-
|
119
|
-
# Start the stream.
|
120
|
-
# Raises a Rucola::FSEvents::StreamError if the stream could not be started.
|
121
|
-
def start
|
122
|
-
raise(StreamError, 'Unable to start FSEvents stream.') unless OSX.FSEventStreamStart(@stream)
|
123
|
-
end
|
124
|
-
|
125
|
-
# Stop the stream.
|
126
|
-
# You can resume it by calling `start` again.
|
127
|
-
def stop
|
128
|
-
OSX.FSEventStreamStop(@stream)
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
class FSSM::Monitor
|
2
|
-
def initialize(options={})
|
3
|
-
@options = options
|
4
|
-
@backend = FSSM::Backends::Default.new
|
5
|
-
end
|
6
|
-
|
7
|
-
def path(*args, &block)
|
8
|
-
path = FSSM::Path.new(*args)
|
9
|
-
FSSM::Support.use_block(path, block)
|
10
|
-
|
11
|
-
@backend.add_handler(FSSM::State::Directory.new(path))
|
12
|
-
path
|
13
|
-
end
|
14
|
-
|
15
|
-
def file(*args, &block)
|
16
|
-
path = FSSM::Path.new(*args)
|
17
|
-
FSSM::Support.use_block(path, block)
|
18
|
-
|
19
|
-
@backend.add_handler(FSSM::State::File.new(path))
|
20
|
-
path
|
21
|
-
end
|
22
|
-
|
23
|
-
def run
|
24
|
-
@backend.run
|
25
|
-
end
|
26
|
-
end
|
@@ -1,91 +0,0 @@
|
|
1
|
-
class FSSM::Path
|
2
|
-
def initialize(path=nil, glob=nil, &block)
|
3
|
-
set_path(path || '.')
|
4
|
-
set_glob(glob || '**/*')
|
5
|
-
init_callbacks
|
6
|
-
|
7
|
-
if block_given?
|
8
|
-
if block.arity == 1
|
9
|
-
block.call(self)
|
10
|
-
else
|
11
|
-
self.instance_eval(&block)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_s
|
17
|
-
@path.to_s
|
18
|
-
end
|
19
|
-
|
20
|
-
def to_pathname
|
21
|
-
@path
|
22
|
-
end
|
23
|
-
|
24
|
-
def glob(value=nil)
|
25
|
-
return @glob if value.nil?
|
26
|
-
set_glob(value)
|
27
|
-
end
|
28
|
-
|
29
|
-
def create(callback_or_path=nil, &block)
|
30
|
-
callback_action(:create, (block_given? ? block : callback_or_path))
|
31
|
-
end
|
32
|
-
|
33
|
-
def update(callback_or_path=nil, &block)
|
34
|
-
callback_action(:update, (block_given? ? block : callback_or_path))
|
35
|
-
end
|
36
|
-
|
37
|
-
def delete(callback_or_path=nil, &block)
|
38
|
-
callback_action(:delete, (block_given? ? block : callback_or_path))
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def init_callbacks
|
44
|
-
do_nothing = lambda {|base, relative|}
|
45
|
-
@callbacks = Hash.new(do_nothing)
|
46
|
-
end
|
47
|
-
|
48
|
-
def callback_action(type, arg=nil)
|
49
|
-
if arg.is_a?(Proc)
|
50
|
-
set_callback(type, arg)
|
51
|
-
elsif arg.nil?
|
52
|
-
get_callback(type)
|
53
|
-
else
|
54
|
-
run_callback(type, arg)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def set_callback(type, arg)
|
59
|
-
raise ArgumentError, "Proc expected" unless arg.is_a?(Proc)
|
60
|
-
@callbacks[type] = arg
|
61
|
-
end
|
62
|
-
|
63
|
-
def get_callback(type)
|
64
|
-
@callbacks[type]
|
65
|
-
end
|
66
|
-
|
67
|
-
def run_callback(type, arg)
|
68
|
-
base, relative = split_path(arg)
|
69
|
-
|
70
|
-
begin
|
71
|
-
@callbacks[type].call(base, relative)
|
72
|
-
rescue Exception => e
|
73
|
-
raise FSSM::CallbackError, "#{type} - #{base.join(relative)}: #{e.message}", e.backtrace
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def split_path(path)
|
78
|
-
path = FSSM::Pathname.for(path)
|
79
|
-
[@path, (path.relative? ? path : path.relative_path_from(@path))]
|
80
|
-
end
|
81
|
-
|
82
|
-
def set_path(path)
|
83
|
-
path = FSSM::Pathname.for(path)
|
84
|
-
raise FSSM::FileNotFoundError, "No such file or directory - #{path}" unless path.exist?
|
85
|
-
@path = path.expand_path
|
86
|
-
end
|
87
|
-
|
88
|
-
def set_glob(glob)
|
89
|
-
@glob = glob.is_a?(Array) ? glob : [glob]
|
90
|
-
end
|
91
|
-
end
|
@@ -1,502 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'find'
|
3
|
-
|
4
|
-
module FSSM
|
5
|
-
class Pathname < String
|
6
|
-
SYMLOOP_MAX = 8
|
7
|
-
|
8
|
-
ROOT = '/'.freeze
|
9
|
-
DOT = '.'.freeze
|
10
|
-
DOT_DOT = '..'.freeze
|
11
|
-
|
12
|
-
class << self
|
13
|
-
def for(path)
|
14
|
-
path.is_a?(::FSSM::Pathname) ? path : new("#{path}")
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize(path)
|
19
|
-
raise ArgumentError, "path cannot contain ASCII NULLs" if path =~ %r{\0}
|
20
|
-
super(path)
|
21
|
-
end
|
22
|
-
|
23
|
-
def <=>(other)
|
24
|
-
self.tr('/', "\0").to_s <=> other.to_str.tr('/', "\0")
|
25
|
-
rescue NoMethodError
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
|
29
|
-
def ==(other)
|
30
|
-
left = self.cleanpath.tr('/', "\0").to_s
|
31
|
-
right = self.class.for(other).cleanpath.tr('/', "\0").to_s
|
32
|
-
|
33
|
-
left == right
|
34
|
-
rescue NoMethodError
|
35
|
-
false
|
36
|
-
end
|
37
|
-
|
38
|
-
def +(path)
|
39
|
-
dup << path
|
40
|
-
end
|
41
|
-
|
42
|
-
def <<(path)
|
43
|
-
replace( join(path).cleanpath! )
|
44
|
-
end
|
45
|
-
|
46
|
-
def absolute?
|
47
|
-
self[0, 1].to_s == ROOT
|
48
|
-
end
|
49
|
-
|
50
|
-
def ascend
|
51
|
-
parts = to_a
|
52
|
-
parts.length.downto(1) do |i|
|
53
|
-
yield self.class.join(parts[0, i])
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def children
|
58
|
-
entries[2..-1]
|
59
|
-
end
|
60
|
-
|
61
|
-
def cleanpath!
|
62
|
-
parts = to_a
|
63
|
-
final = []
|
64
|
-
|
65
|
-
parts.each do |part|
|
66
|
-
case part
|
67
|
-
when DOT then
|
68
|
-
next
|
69
|
-
when DOT_DOT then
|
70
|
-
case final.last
|
71
|
-
when ROOT then
|
72
|
-
next
|
73
|
-
when DOT_DOT then
|
74
|
-
final.push(DOT_DOT)
|
75
|
-
when nil then
|
76
|
-
final.push(DOT_DOT)
|
77
|
-
else
|
78
|
-
final.pop
|
79
|
-
end
|
80
|
-
else
|
81
|
-
final.push(part)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
replace(final.empty? ? DOT : self.class.join(*final))
|
86
|
-
end
|
87
|
-
|
88
|
-
def cleanpath
|
89
|
-
dup.cleanpath!
|
90
|
-
end
|
91
|
-
|
92
|
-
def descend
|
93
|
-
parts = to_a
|
94
|
-
1.upto(parts.length) { |i| yield self.class.join(parts[0, i]) }
|
95
|
-
end
|
96
|
-
|
97
|
-
def dot?
|
98
|
-
self == DOT
|
99
|
-
end
|
100
|
-
|
101
|
-
def dot_dot?
|
102
|
-
self == DOT_DOT
|
103
|
-
end
|
104
|
-
|
105
|
-
def each_filename(&blk)
|
106
|
-
to_a.each(&blk)
|
107
|
-
end
|
108
|
-
|
109
|
-
def mountpoint?
|
110
|
-
stat1 = self.lstat
|
111
|
-
stat2 = self.parent.lstat
|
112
|
-
|
113
|
-
stat1.dev != stat2.dev || stat1.ino == stat2.ino
|
114
|
-
rescue Errno::ENOENT
|
115
|
-
false
|
116
|
-
end
|
117
|
-
|
118
|
-
def parent
|
119
|
-
self + '..'
|
120
|
-
end
|
121
|
-
|
122
|
-
def realpath
|
123
|
-
path = self
|
124
|
-
|
125
|
-
SYMLOOP_MAX.times do
|
126
|
-
link = path.readlink
|
127
|
-
link = path.dirname + link if link.relative?
|
128
|
-
path = link
|
129
|
-
end
|
130
|
-
|
131
|
-
raise Errno::ELOOP, self
|
132
|
-
rescue Errno::EINVAL
|
133
|
-
path.expand_path
|
134
|
-
end
|
135
|
-
|
136
|
-
def relative?
|
137
|
-
!absolute?
|
138
|
-
end
|
139
|
-
|
140
|
-
def relative_path_from(base)
|
141
|
-
base = self.class.for(base)
|
142
|
-
|
143
|
-
raise ArgumentError, 'no relative path between a relative and absolute' if self.absolute? != base.absolute?
|
144
|
-
|
145
|
-
return self if base.dot?
|
146
|
-
return self.class.new(DOT) if self == base
|
147
|
-
|
148
|
-
base = base.cleanpath.to_a
|
149
|
-
dest = self.cleanpath.to_a
|
150
|
-
|
151
|
-
while !dest.empty? && !base.empty? && dest[0] == base[0]
|
152
|
-
base.shift
|
153
|
-
dest.shift
|
154
|
-
end
|
155
|
-
|
156
|
-
base.shift if base[0] == DOT
|
157
|
-
dest.shift if dest[0] == DOT
|
158
|
-
|
159
|
-
raise ArgumentError, "base directory may not contain '#{DOT_DOT}'" if base.include?(DOT_DOT)
|
160
|
-
|
161
|
-
path = base.fill(DOT_DOT) + dest
|
162
|
-
path = self.class.join(*path)
|
163
|
-
path = self.class.new(DOT) if path.empty?
|
164
|
-
|
165
|
-
path
|
166
|
-
end
|
167
|
-
|
168
|
-
def root?
|
169
|
-
!!(self =~ %r{^#{ROOT}+$})
|
170
|
-
end
|
171
|
-
|
172
|
-
def to_a
|
173
|
-
array = to_s.split(File::SEPARATOR)
|
174
|
-
array.delete('')
|
175
|
-
array.insert(0, ROOT) if absolute?
|
176
|
-
array
|
177
|
-
end
|
178
|
-
|
179
|
-
alias segments to_a
|
180
|
-
|
181
|
-
def to_path
|
182
|
-
self
|
183
|
-
end
|
184
|
-
|
185
|
-
def to_s
|
186
|
-
"#{self}"
|
187
|
-
end
|
188
|
-
|
189
|
-
alias to_str to_s
|
190
|
-
|
191
|
-
def unlink
|
192
|
-
Dir.unlink(self)
|
193
|
-
true
|
194
|
-
rescue Errno::ENOTDIR
|
195
|
-
File.unlink(self)
|
196
|
-
true
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
class Pathname
|
201
|
-
def self.[](pattern)
|
202
|
-
Dir[pattern].map! {|d| FSSM::Pathname.new(d) }
|
203
|
-
end
|
204
|
-
|
205
|
-
def self.pwd
|
206
|
-
FSSM::Pathname.new(Dir.pwd)
|
207
|
-
end
|
208
|
-
|
209
|
-
def entries
|
210
|
-
Dir.entries(self).map! {|e| FSSM::Pathname.new(e) }
|
211
|
-
end
|
212
|
-
|
213
|
-
def mkdir(mode = 0777)
|
214
|
-
Dir.mkdir(self, mode)
|
215
|
-
end
|
216
|
-
|
217
|
-
def opendir(&blk)
|
218
|
-
Dir.open(self, &blk)
|
219
|
-
end
|
220
|
-
|
221
|
-
def rmdir
|
222
|
-
Dir.rmdir(self)
|
223
|
-
end
|
224
|
-
|
225
|
-
def self.glob(pattern, flags = 0)
|
226
|
-
dirs = Dir.glob(pattern, flags)
|
227
|
-
dirs.map! {|path| FSSM::Pathname.new(path) }
|
228
|
-
|
229
|
-
if block_given?
|
230
|
-
dirs.each {|dir| yield dir }
|
231
|
-
nil
|
232
|
-
else
|
233
|
-
dirs
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
def glob(pattern, flags = 0, &block)
|
238
|
-
patterns = [pattern].flatten
|
239
|
-
patterns.map! {|p| self.class.glob(self.to_s + p, flags, &block) }
|
240
|
-
patterns.flatten
|
241
|
-
end
|
242
|
-
|
243
|
-
def chdir
|
244
|
-
blk = lambda { yield self } if block_given?
|
245
|
-
Dir.chdir(self, &blk)
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
class Pathname
|
250
|
-
def blockdev?
|
251
|
-
FileTest.blockdev?(self)
|
252
|
-
end
|
253
|
-
|
254
|
-
def chardev?
|
255
|
-
FileTest.chardev?(self)
|
256
|
-
end
|
257
|
-
|
258
|
-
def directory?
|
259
|
-
FileTest.directory?(self)
|
260
|
-
end
|
261
|
-
|
262
|
-
def executable?
|
263
|
-
FileTest.executable?(self)
|
264
|
-
end
|
265
|
-
|
266
|
-
def executable_real?
|
267
|
-
FileTest.executable_real?(self)
|
268
|
-
end
|
269
|
-
|
270
|
-
def exists?
|
271
|
-
FileTest.exists?(self)
|
272
|
-
end
|
273
|
-
|
274
|
-
def file?
|
275
|
-
FileTest.file?(self)
|
276
|
-
end
|
277
|
-
|
278
|
-
def grpowned?
|
279
|
-
FileTest.grpowned?(self)
|
280
|
-
end
|
281
|
-
|
282
|
-
def owned?
|
283
|
-
FileTest.owned?(self)
|
284
|
-
end
|
285
|
-
|
286
|
-
def pipe?
|
287
|
-
FileTest.pipe?(self)
|
288
|
-
end
|
289
|
-
|
290
|
-
def readable?
|
291
|
-
FileTest.readable?(self)
|
292
|
-
end
|
293
|
-
|
294
|
-
def readable_real?
|
295
|
-
FileTest.readable_real?(self)
|
296
|
-
end
|
297
|
-
|
298
|
-
def setgid?
|
299
|
-
FileTest.setgit?(self)
|
300
|
-
end
|
301
|
-
|
302
|
-
def setuid?
|
303
|
-
FileTest.setuid?(self)
|
304
|
-
end
|
305
|
-
|
306
|
-
def socket?
|
307
|
-
FileTest.socket?(self)
|
308
|
-
end
|
309
|
-
|
310
|
-
def sticky?
|
311
|
-
FileTest.sticky?(self)
|
312
|
-
end
|
313
|
-
|
314
|
-
def symlink?
|
315
|
-
FileTest.symlink?(self)
|
316
|
-
end
|
317
|
-
|
318
|
-
def world_readable?
|
319
|
-
FileTest.world_readable?(self)
|
320
|
-
end
|
321
|
-
|
322
|
-
def world_writable?
|
323
|
-
FileTest.world_writable?(self)
|
324
|
-
end
|
325
|
-
|
326
|
-
def writable?
|
327
|
-
FileTest.writable?(self)
|
328
|
-
end
|
329
|
-
|
330
|
-
def writable_real?
|
331
|
-
FileTest.writable_real?(self)
|
332
|
-
end
|
333
|
-
|
334
|
-
def zero?
|
335
|
-
FileTest.zero?(self)
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
class Pathname
|
340
|
-
def atime
|
341
|
-
File.atime(self)
|
342
|
-
end
|
343
|
-
|
344
|
-
def ctime
|
345
|
-
File.ctime(self)
|
346
|
-
end
|
347
|
-
|
348
|
-
def ftype
|
349
|
-
File.ftype(self)
|
350
|
-
end
|
351
|
-
|
352
|
-
def lstat
|
353
|
-
File.lstat(self)
|
354
|
-
end
|
355
|
-
|
356
|
-
def mtime
|
357
|
-
File.mtime(self)
|
358
|
-
end
|
359
|
-
|
360
|
-
def stat
|
361
|
-
File.stat(self)
|
362
|
-
end
|
363
|
-
|
364
|
-
def utime(atime, mtime)
|
365
|
-
File.utime(self, atime, mtime)
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
class Pathname
|
370
|
-
def self.join(*parts)
|
371
|
-
last_part = FSSM::Pathname.new(parts.last)
|
372
|
-
return last_part if last_part.absolute?
|
373
|
-
FSSM::Pathname.new(File.join(*parts.reject {|p| p.empty? }))
|
374
|
-
end
|
375
|
-
|
376
|
-
def basename
|
377
|
-
self.class.new(File.basename(self))
|
378
|
-
end
|
379
|
-
|
380
|
-
def chmod(mode)
|
381
|
-
File.chmod(mode, self)
|
382
|
-
end
|
383
|
-
|
384
|
-
def chown(owner, group)
|
385
|
-
File.chown(owner, group, self)
|
386
|
-
end
|
387
|
-
|
388
|
-
def dirname
|
389
|
-
self.class.new(File.dirname(self))
|
390
|
-
end
|
391
|
-
|
392
|
-
def expand_path(from = nil)
|
393
|
-
self.class.new(File.expand_path(self, from))
|
394
|
-
end
|
395
|
-
|
396
|
-
def extname
|
397
|
-
File.extname(self)
|
398
|
-
end
|
399
|
-
|
400
|
-
def fnmatch?(pat, flags = 0)
|
401
|
-
File.fnmatch(pat, self, flags)
|
402
|
-
end
|
403
|
-
|
404
|
-
def join(*parts)
|
405
|
-
self.class.join(self, *parts)
|
406
|
-
end
|
407
|
-
|
408
|
-
def lchmod(mode)
|
409
|
-
File.lchmod(mode, self)
|
410
|
-
end
|
411
|
-
|
412
|
-
def lchown(owner, group)
|
413
|
-
File.lchown(owner, group, self)
|
414
|
-
end
|
415
|
-
|
416
|
-
def link(to)
|
417
|
-
File.link(self, to)
|
418
|
-
end
|
419
|
-
|
420
|
-
def open(mode = 'r', perm = nil, &blk)
|
421
|
-
File.open(self, mode, perm, &blk)
|
422
|
-
end
|
423
|
-
|
424
|
-
def readlink
|
425
|
-
self.class.new(File.readlink(self))
|
426
|
-
end
|
427
|
-
|
428
|
-
def rename(to)
|
429
|
-
File.rename(self, to)
|
430
|
-
replace(to)
|
431
|
-
end
|
432
|
-
|
433
|
-
def size
|
434
|
-
File.size(self)
|
435
|
-
end
|
436
|
-
|
437
|
-
def size?
|
438
|
-
File.size?(self)
|
439
|
-
end
|
440
|
-
|
441
|
-
def split
|
442
|
-
File.split(self).map {|part| FSSM::Pathname.new(part) }
|
443
|
-
end
|
444
|
-
|
445
|
-
def symlink(to)
|
446
|
-
File.symlink(self, to)
|
447
|
-
end
|
448
|
-
|
449
|
-
def truncate
|
450
|
-
File.truncate(self)
|
451
|
-
end
|
452
|
-
end
|
453
|
-
|
454
|
-
class Pathname
|
455
|
-
def mkpath
|
456
|
-
self.class.new(FileUtils.mkpath(self))
|
457
|
-
end
|
458
|
-
|
459
|
-
def rmtree
|
460
|
-
self.class.new(FileUtils.rmtree(self).first)
|
461
|
-
end
|
462
|
-
|
463
|
-
def touch
|
464
|
-
self.class.new(FileUtils.touch(self).first)
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
class Pathname
|
469
|
-
def each_line(sep = $/, &blk)
|
470
|
-
IO.foreach(self, sep, &blk)
|
471
|
-
end
|
472
|
-
|
473
|
-
def read(len = nil, off = 0)
|
474
|
-
IO.read(self, len, off)
|
475
|
-
end
|
476
|
-
|
477
|
-
def readlines(sep = $/)
|
478
|
-
IO.readlines(self, sep)
|
479
|
-
end
|
480
|
-
|
481
|
-
def sysopen(mode = 'r', perm = nil)
|
482
|
-
IO.sysopen(self, mode, perm)
|
483
|
-
end
|
484
|
-
end
|
485
|
-
|
486
|
-
class Pathname
|
487
|
-
def find
|
488
|
-
Find.find(self) {|path| yield FSSM::Pathname.new(path) }
|
489
|
-
end
|
490
|
-
end
|
491
|
-
|
492
|
-
class Pathname
|
493
|
-
class << self
|
494
|
-
alias getwd pwd
|
495
|
-
end
|
496
|
-
|
497
|
-
alias absolute expand_path
|
498
|
-
alias delete unlink
|
499
|
-
alias exist? exists?
|
500
|
-
alias fnmatch fnmatch?
|
501
|
-
end
|
502
|
-
end
|