rubypath 0.3.2 → 1.0.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.
@@ -1,161 +0,0 @@
1
- class Path::Backend
2
-
3
- #
4
- class Sys
5
-
6
- def initialize(root = nil)
7
- @root = ::File.expand_path root if root
8
- @umask = File.umask
9
- end
10
-
11
- def quit
12
- File.umask @umask
13
- end
14
-
15
- def home(user)
16
- ::File.expand_path "~#{user}"
17
- end
18
-
19
- def getwd
20
- ::Dir.getwd
21
- end
22
-
23
- def user
24
- require 'etc'
25
-
26
- Etc.getlogin
27
- end
28
-
29
- def r(path)
30
- return path unless @root
31
- ::File.expand_path("#{@root}/#{::File.expand_path(path)}")
32
- end
33
-
34
- def ur(path)
35
- return path unless @root
36
-
37
- if path.slice(0, @root.length) == @root
38
- path.slice(@root.length, path.length - @root.length)
39
- else
40
- path
41
- end
42
- end
43
-
44
- def fs(path, obj, method, *args)
45
- # puts "[FS] #{obj} #{method} #{args.inspect}"
46
- obj.send method, *args
47
- rescue Errno::ENOENT
48
- raise Errno::ENOENT.new path
49
- rescue Errno::EISDIR
50
- raise Errno::EISDIR.new path
51
- rescue Errno::ENOTDIR
52
- raise Errno::ENOTDIR.new path
53
- rescue Errno::EACCES
54
- raise Errno::EACCES.new path
55
- end
56
-
57
- ## OPERATIONS
58
-
59
- def expand_path(path, base)
60
- ::File.expand_path path, base
61
- end
62
-
63
- def exists?(path)
64
- fs path, ::File, :exists?, r(path)
65
- end
66
-
67
- def mkdir(path)
68
- fs path, ::Dir, :mkdir, r(path)
69
- end
70
-
71
- def mkpath(path)
72
- fs path, ::FileUtils, :mkdir_p, r(path)
73
- end
74
-
75
- def directory?(path)
76
- fs path, ::File, :directory?, r(path)
77
- end
78
-
79
- def file?(path)
80
- fs path, ::File, :file?, r(path)
81
- end
82
-
83
- def touch(path)
84
- fs path, ::FileUtils, :touch, r(path)
85
- end
86
-
87
- def write(path, content, *args)
88
- fs path, ::IO, :write, r(path), content, *args
89
- end
90
-
91
- def read(path, *args)
92
- fs path, ::IO, :read, r(path), *args
93
- end
94
-
95
- def mtime(path)
96
- fs path, ::File, :mtime, r(path)
97
- end
98
-
99
- def mtime=(path, time)
100
- fs path, ::File, :utime, atime(path), time, r(path)
101
- end
102
-
103
- def atime(path)
104
- fs path, ::File, :atime, r(path)
105
- end
106
-
107
- def atime=(path, time)
108
- fs path, ::File, :utime, time, mtime(path), r(path)
109
- end
110
-
111
- def entries(path)
112
- fs path, ::Dir, :entries, r(path)
113
- end
114
-
115
- def glob(pattern, flags = 0, &block)
116
- if block_given?
117
- fs pattern, ::Dir, :glob, r(pattern), flags do |path|
118
- yield ur(path)
119
- end
120
- else
121
- fs(pattern, ::Dir, :glob, r(pattern), flags).map{|path| ur path }
122
- end
123
- end
124
-
125
- def get_umask
126
- File.umask
127
- end
128
-
129
- def set_umask(mask)
130
- File.umask mask
131
- end
132
-
133
- def mode(path)
134
- fs(path, ::File, :stat, r(path)).mode & 0777
135
- end
136
-
137
- def chmod(path, mode)
138
- fs path, ::File, :chmod, mode, r(path)
139
- end
140
-
141
- def unlink(path)
142
- fs path, ::File, :unlink, r(path)
143
- end
144
-
145
- def rmtree(path)
146
- fs path, ::FileUtils, :rm_r, r(path), force: true
147
- end
148
-
149
- def rmtree!(path)
150
- fs path, ::FileUtils, :rm_r, r(path)
151
- end
152
-
153
- def safe_rmtree(path)
154
- fs path, ::FileUtils, :rm_r, r(path), force: true, secure: true
155
- end
156
-
157
- def safe_rmtree!(path)
158
- fs path, ::FileUtils, :rm_r, r(path), secure: true
159
- end
160
- end
161
- end
@@ -1,19 +0,0 @@
1
- class Path
2
- # @!group Comparison
3
-
4
- # Compare path to given object. If object is a string, Path or #{Path.like?}
5
- # they will be compared using the string paths. Otherwise they are assumed
6
- # as not equal.
7
- #
8
- # @param other [Object] Object to compare path with.
9
- # @return [Boolean] True if object represents same path.
10
- #
11
- def eql?(other)
12
- if other.is_a?(Path)
13
- cleanpath.internal_path == other.cleanpath.internal_path
14
- else
15
- Path.new(other).eql?(self) if Path.like?(other)
16
- end
17
- end
18
- alias_method :==, :eql?
19
- end
@@ -1,109 +0,0 @@
1
- class Path
2
-
3
- class << self
4
- # @!group Construction
5
-
6
- # Create new {Path}.
7
- #
8
- # If single argument is a path object it will be returned and no new one
9
- # will be created. If not arguments are given {Path::EMPTY} will be
10
- # returned.
11
- #
12
- # @see #initialize
13
- #
14
- def new(*args)
15
- args.flatten!
16
- return Path::EMPTY if args.empty?
17
- return args.first if args.size == 1 && args.first.is_a?(self)
18
- super
19
- end
20
-
21
- # Check if given object is like a path.
22
- #
23
- # An object is like a path if
24
- # 1. It is a {Path} object.
25
- # 2. It is a string.
26
- # 3. It responds to {#to_path} and {#to_path} returns a string.
27
- # 4. It responds to {#path} and {#path} returns a string.
28
- #
29
- # If no rule matches it is not considered to be like a path.
30
- #
31
- # @return [Boolean] True if object is path like, false otherwise.
32
- #
33
- def like?(obj)
34
- return true if obj.is_a?(self)
35
- return true if obj.is_a?(String)
36
- return true if obj.respond_to?(:to_path) && obj.to_path.is_a?(String)
37
- return true if obj.respond_to?(:path) && obj.path.is_a?(String)
38
- false
39
- end
40
-
41
- # Convert given object to path string using {::Path.like?} rules.
42
- #
43
- # @note Should not be used directly.
44
- #
45
- # @return [String]
46
- # @raise [ArgumentError] If given object is not {::Path.like?}.
47
- # @see ::Path.like?
48
- #
49
- def like_path(obj)
50
- case obj
51
- when String
52
- return obj
53
- else
54
- [:to_path, :path, :to_str, :to_s].each do |mth|
55
- if obj.respond_to?(mth) && obj.send(mth).is_a?(String)
56
- return obj.send(mth)
57
- end
58
- end
59
- end
60
-
61
- raise ArgumentError.new \
62
- "Argument #{obj.inspect} cannot be converted to path string."
63
- end
64
-
65
- # Return system file path separator.
66
- #
67
- # @return [String] File separator.
68
- # @see ::File::SEPARATOR
69
- #
70
- def separator
71
- ::File::SEPARATOR
72
- end
73
-
74
- # Allow class object to be used as a bock.
75
- #
76
- # @example
77
- # %w(path/to/fileA path/to/fileB).map(&Path)
78
- #
79
- def to_proc
80
- proc {|*args| Path.new(*args) }
81
- end
82
- end
83
-
84
- # @!group Construction
85
-
86
- # Initialize new {Path} object.
87
- #
88
- # Given arguments will be converted to String using `#to_path`, `#path` or
89
- # `#to_s` in this order if they return a String object.
90
- #
91
- # @overload initialize([[String, #to_path, #path, #to_s], ...]
92
- #
93
- def initialize(*args)
94
- parts = args.flatten
95
- @path = if parts.size > 1
96
- ::File.join(*parts.map{|p| Path.like_path p })
97
- elsif parts.size == 1
98
- Path.like_path(parts.first).dup
99
- else
100
- ''
101
- end
102
- end
103
-
104
- # Empty path.
105
- #
106
- # @return [Path] Empty path.
107
- #
108
- EMPTY = Path.new('')
109
- end
@@ -1,160 +0,0 @@
1
- class Path
2
- class << self
3
-
4
- # Returns the current working directory.
5
- #
6
- # @return [Path] Current working directory.
7
- # @see ::Dir.getwd
8
- #
9
- def getwd
10
- new Backend.instance.getwd
11
- end
12
-
13
- def glob(pattern, flags = nil)
14
- flags = default_glob_flags(flags)
15
-
16
- if block_given?
17
- Backend.instance.glob(pattern, flags) {|path| yield Path path }
18
- else
19
- Backend.instance.glob(pattern, flags).map(&Path)
20
- end
21
- end
22
-
23
- # @!visibility private
24
- #
25
- def default_glob_flags(flags)
26
- if flags.nil? && defined?(::File::FNM_EXTGLOB)
27
- ::File::FNM_EXTGLOB
28
- else
29
- flags.to_i
30
- end
31
- end
32
- end
33
-
34
- # @!group Directory Operations
35
-
36
- # Create directory.
37
- #
38
- # Given arguments will be joined with current path before directory is
39
- # created.
40
- #
41
- # @raise [Errno::ENOENT] If parent directory could not created.
42
- # @return [Path] Path to created directory.
43
- # @see #mkpath
44
- #
45
- def mkdir(*args)
46
- with_path(*args) do |path|
47
- Backend.instance.mkdir path
48
- Path path
49
- end
50
- end
51
-
52
- # Create directory and all missing parent directories.
53
- #
54
- # Given arguments will be joined with current path before directories
55
- # are created.
56
- #
57
- # @return [Path] Path to created directory.
58
- # @see #mkdir
59
- # @see ::FileUtils.mkdir_p
60
- #
61
- def mkpath(*args)
62
- with_path(*args) do |path|
63
- Backend.instance.mkpath path
64
- Path path
65
- end
66
- end
67
- alias_method :mkdir_p, :mkpath
68
-
69
- # Return list of entries in directory. That includes special directories
70
- # (`.`, `..`).
71
- #
72
- # Given arguments will be joined before children are listed for directory.
73
- #
74
- # @return [Array<Path>] Entries in directory.
75
- #
76
- def entries(*args)
77
- invoke_backend(:entries, internal_path).map(&Path)
78
- end
79
-
80
- #
81
- def glob(pattern, flags = nil, &block)
82
- Path.glob(::File.join(escaped_glob_path, pattern), flags, &block)
83
- end
84
-
85
- # Removes file or directory. If it's a directory it will be removed
86
- # recursively.
87
- #
88
- # WARNING: This method causes local vulnerability if one of parent
89
- # directories or removing directory tree are world writable (including
90
- # `/tmp`, whose permission is 1777), and the current process has strong
91
- # privilege such as Unix super user (root), and the system has symbolic link.
92
- # For secure removing see {#safe_rmtree}.
93
- #
94
- # @return [Path] Path to removed file or directory.
95
- #
96
- def rmtree(*args)
97
- with_path(*args) do |path|
98
- invoke_backend :rmtree, internal_path
99
- Path path
100
- end
101
- end
102
- alias_method :rm_rf, :rmtree
103
-
104
- # Removes file or directory. If it's a directory it will be removed
105
- # recursively.
106
- #
107
- # This method uses #{FileUtils#remove_entry_secure} to avoid TOCTTOU
108
- # (time-of-check-to-time-of-use) local security vulnerability of {#rmtree}.
109
- # {#rmtree} causes security hole when:
110
- #
111
- # * Parent directory is world writable (including `/tmp`).
112
- # * Removing directory tree includes world writable directory.
113
- # * The system has symbolic link.
114
- #
115
- # @return [Path] Path to removed file or directory.
116
- #
117
- def safe_rmtree(*args)
118
- with_path(*args) do |path|
119
- invoke_backend :safe_rmtree, internal_path
120
- Path path
121
- end
122
- end
123
-
124
- # Removes file or directory. If it's a directory it will be removed
125
- # recursively.
126
- #
127
- # This method behaves exactly like {#rmtree} but will raise exceptions
128
- # e.g. when file does not exist.
129
- #
130
- # @return [Path] Path to removed file or directory.
131
- #
132
- def rmtree!(*args)
133
- with_path(*args) do |path|
134
- invoke_backend :rmtree!, internal_path
135
- Path path
136
- end
137
- end
138
- alias_method :rm_r, :rmtree!
139
-
140
- # Removes file or directory. If it's a directory it will be removed
141
- # recursively.
142
- #
143
- # This method behaves exactly like {#safe_rmtree} but will raise exceptions
144
- # e.g. when file does not exist.
145
- #
146
- # @return [Path] Path to removed file or directory.
147
- #
148
- def safe_rmtree!(*args)
149
- with_path(*args) do |path|
150
- invoke_backend :safe_rmtree!, internal_path
151
- Path path
152
- end
153
- end
154
-
155
- private
156
-
157
- def escaped_glob_path
158
- internal_path.gsub(/[\[\]\*\?\{\}]/, '\\\\\0')
159
- end
160
- end