faster_path 0.1.12 → 0.1.13
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.
- checksums.yaml +4 -4
- data/Cargo.lock +6 -6
- data/Cargo.toml +2 -2
- data/Gemfile +0 -8
- data/README.md +6 -7
- data/Rakefile +8 -3
- data/faster_path.gemspec +1 -1
- data/lib/faster_path/optional/monkeypatches.rb +5 -0
- data/lib/faster_path/optional/refinements.rb +5 -0
- data/lib/faster_path/version.rb +1 -1
- data/lib/faster_path.rb +5 -0
- data/src/basename.rs +25 -16
- data/src/chop_basename.rs +56 -0
- data/src/dirname.rs +35 -21
- data/src/lib.rs +2 -0
- data/src/plus.rs +131 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f1b4b37c294db2912d786c35de76f60cba0b6a9
|
4
|
+
data.tar.gz: 46af8f1bb6c06baed02866d6f9777bb9dfb6f1ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6d51a6c3a7796aa41063ee31a3c0f05c88df32350f5fbc2f0913553c9fdaf6ab5600475594d3e9dc3706df49785f5bfc0e0ed0de4b29d169e166abd1acf4f45
|
7
|
+
data.tar.gz: 96b16a98d9e807e33669956d6adb879f57d5e976def60c2d11502b9107a601bf793cfe75148f56e2e6c99b3b3af7745434e5c166d40c1b902b911efd797a0b65
|
data/Cargo.lock
CHANGED
@@ -2,20 +2,20 @@
|
|
2
2
|
name = "faster_path"
|
3
3
|
version = "0.0.1"
|
4
4
|
dependencies = [
|
5
|
-
"array_tool 0.
|
6
|
-
"libc 0.2.
|
5
|
+
"array_tool 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
6
|
+
"libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
7
7
|
]
|
8
8
|
|
9
9
|
[[package]]
|
10
10
|
name = "array_tool"
|
11
|
-
version = "0.
|
11
|
+
version = "0.4.1"
|
12
12
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
13
13
|
|
14
14
|
[[package]]
|
15
15
|
name = "libc"
|
16
|
-
version = "0.2.
|
16
|
+
version = "0.2.30"
|
17
17
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
18
18
|
|
19
19
|
[metadata]
|
20
|
-
"checksum array_tool 0.
|
21
|
-
"checksum libc 0.2.
|
20
|
+
"checksum array_tool 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a07ccb27c611e5cda99e498e99ba71b3ecdb7db5df02096cef42a3df5b84542"
|
21
|
+
"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915"
|
data/Cargo.toml
CHANGED
data/Gemfile
CHANGED
@@ -5,11 +5,3 @@ source 'https://rubygems.org' do
|
|
5
5
|
gem 'coveralls', require: false
|
6
6
|
end
|
7
7
|
end
|
8
|
-
|
9
|
-
begin
|
10
|
-
# https://github.com/ruby/spec dependencies
|
11
|
-
eval_gemfile File.expand_path('spec/ruby_spec/Gemfile', File.dirname(__FILE__))
|
12
|
-
rescue
|
13
|
-
`git submodule update --init`
|
14
|
-
eval_gemfile File.expand_path('spec/ruby_spec/Gemfile', File.dirname(__FILE__))
|
15
|
-
end
|
data/README.md
CHANGED
@@ -113,7 +113,7 @@ curl -sSf https://static.rust-lang.org/rustup.sh | sh
|
|
113
113
|
Add this line to your application's Gemfile:
|
114
114
|
|
115
115
|
```ruby
|
116
|
-
gem 'faster_path', '~> 0.1.
|
116
|
+
gem 'faster_path', '~> 0.1.13'
|
117
117
|
```
|
118
118
|
|
119
119
|
And then execute:
|
@@ -143,7 +143,6 @@ Current methods implemented:
|
|
143
143
|
| `FasterPath.absolute?` | `Pathname#absolute?` | 93.9% |
|
144
144
|
| `FasterPath.chop_basename` | `Pathname#chop_basename` | 50.6% |
|
145
145
|
| `FasterPath.relative?` | `Pathname#relative?` | 93.2% |
|
146
|
-
| `FasterPath.blank?` | | |
|
147
146
|
| `FasterPath.directory?` | `Pathname#directory?` | 25.5% |
|
148
147
|
| `FasterPath.add_trailing_separator` | `Pathname#add_trailing_separator` | 46.8% |
|
149
148
|
| `FasterPath.has_trailing_separator?` | `Pathname#has_trailing_separator` | 61.2% |
|
@@ -169,9 +168,11 @@ require "faster_path/optional/monkeypatches"
|
|
169
168
|
FasterPath.sledgehammer_everything!
|
170
169
|
```
|
171
170
|
|
172
|
-
##
|
171
|
+
## Optional Rust implementations
|
173
172
|
|
174
|
-
**
|
173
|
+
**These are stable, not performant, and not included in `File` by default.**
|
174
|
+
|
175
|
+
These will **not** be included by default in monkey-patches. Be cautious when using the `FasterPath::RefineFile` refinement. To try them with monkeypatching use the environment flag of `WITH_REGRESSION`. These methods are here to be improved upon.
|
175
176
|
|
176
177
|
|FasterPath Implementation|Ruby Implementation|
|
177
178
|
|---|---|
|
@@ -180,9 +181,7 @@ FasterPath.sledgehammer_everything!
|
|
180
181
|
| `FasterPath.extname` | `File.extname` |
|
181
182
|
|
182
183
|
It's been my observation (and some others) that the Rust implementation of the C code for `File` has similar results but
|
183
|
-
performance seems to vary based on CPU cache on possibly 64bit/32bit system environmnets.
|
184
|
-
|
185
|
-
**Developers for FasterPath:** Most of these need to be rewritten, please use `WITH_REGRESSION=true TEST_MONKEYPATCHES=true` in your testing. You can see the resulting failures currently on TravisCI under "Allow Failures".
|
184
|
+
performance seems to vary based on CPU cache on possibly 64bit/32bit system environmnets. When these methods were initially written, and somewhat simplistic, they were faster than the C implementations on `File`. After the implementations have been perfected to match the behavior in Ruby they don't perform as well and are therefore not included by default when the monkey patch method `FasterPath.sledgehammer_everything!` is executed. If you don't want to pass the `WITH_REGRESSION` environment variable you can put any turthy parameter on the monkey patch method to include it.
|
186
185
|
|
187
186
|
## Getting Started with Development
|
188
187
|
|
data/Rakefile
CHANGED
@@ -57,19 +57,24 @@ task :lint do
|
|
57
57
|
puts
|
58
58
|
end
|
59
59
|
|
60
|
+
desc "Run Rust Tests"
|
61
|
+
task :cargo do
|
62
|
+
sh "cargo test -- --nocapture"
|
63
|
+
end
|
64
|
+
|
60
65
|
Rake::TestTask.new(minitest: :build_lib) do |t|
|
61
66
|
t.libs << "test"
|
62
67
|
t.libs << "lib"
|
63
68
|
t.test_files = FileList['test/**/*_test.rb']
|
64
69
|
end
|
65
70
|
|
66
|
-
task test: [:minitest, :lint] do |_t|
|
67
|
-
exec 'mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname'
|
71
|
+
task test: [:cargo, :minitest, :lint] do |_t|
|
72
|
+
exec 'spec/mspec/bin/mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname'
|
68
73
|
end
|
69
74
|
|
70
75
|
desc "Full mspec results w/o encoding"
|
71
76
|
task :mspec_full do
|
72
|
-
exec %(bash -c "TEST_MONKEYPATCHES=true WITH_REGRESSION=true mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname")
|
77
|
+
exec %(bash -c "TEST_MONKEYPATCHES=true WITH_REGRESSION=true spec/mspec/bin/mspec --format spec core/file/basename core/file/extname core/file/dirname library/pathname")
|
73
78
|
end
|
74
79
|
|
75
80
|
desc "Full mspec results w/ encoding"
|
data/faster_path.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency "color_pound_spec_reporter", "~> 0.0.9"
|
34
34
|
spec.add_development_dependency "rubocop", "~> 0.47"
|
35
35
|
unless ENV['CI']
|
36
|
-
spec.add_development_dependency "stop_watch", "~>
|
36
|
+
spec.add_development_dependency "stop_watch", "~> 1.0.0"
|
37
37
|
spec.add_development_dependency "gruff", "~> 0.7.0"
|
38
38
|
end
|
39
39
|
end
|
data/lib/faster_path/version.rb
CHANGED
data/lib/faster_path.rb
CHANGED
@@ -49,6 +49,10 @@ module FasterPath
|
|
49
49
|
Rust.basename(pth, ext)
|
50
50
|
end
|
51
51
|
|
52
|
+
def self.plus(pth, pth2)
|
53
|
+
Rust.plus(pth, pth2)
|
54
|
+
end
|
55
|
+
|
52
56
|
def self.add_trailing_separator(pth)
|
53
57
|
Rust.add_trailing_separator(pth)
|
54
58
|
end
|
@@ -93,6 +97,7 @@ module FasterPath
|
|
93
97
|
attach_function :is_blank, [ :string ], :bool
|
94
98
|
attach_function :both_are_blank, [ :string, :string ], :bool
|
95
99
|
attach_function :basename, [ :string, :string ], :string
|
100
|
+
attach_function :plus, [ :string, :string ], :string
|
96
101
|
attach_function :dirname, [ :string ], :string
|
97
102
|
attach_function :basename_for_chop, [ :string ], :string # decoupling behavior
|
98
103
|
attach_function :dirname_for_chop, [ :string ], :string # decoupling behavior
|
data/src/basename.rs
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
extern crate array_tool;
|
2
1
|
use libc::c_char;
|
3
2
|
use std::ffi::{CStr, CString};
|
4
|
-
use path_parsing::extract_last_path_segment;
|
5
|
-
use self::array_tool::string::Squeeze;
|
6
3
|
|
7
4
|
#[no_mangle]
|
8
5
|
pub extern "C" fn basename(c_pth: *const c_char, c_ext: *const c_char) -> *const c_char {
|
@@ -12,21 +9,33 @@ pub extern "C" fn basename(c_pth: *const c_char, c_ext: *const c_char) -> *const
|
|
12
9
|
let pth = unsafe { CStr::from_ptr(c_pth) }.to_str().unwrap();
|
13
10
|
let ext = unsafe { CStr::from_ptr(c_ext) }.to_str().unwrap();
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
}
|
12
|
+
let name = rust::basename(pth, ext);
|
13
|
+
|
14
|
+
CString::new(name).unwrap().into_raw()
|
15
|
+
}
|
20
16
|
|
21
|
-
|
17
|
+
pub mod rust {
|
18
|
+
extern crate array_tool;
|
19
|
+
use path_parsing::extract_last_path_segment;
|
20
|
+
use self::array_tool::string::Squeeze;
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
pub fn basename(pth: &str, ext: &str) -> String {
|
23
|
+
// Known edge case
|
24
|
+
match &pth.squeeze("/")[..] {
|
25
|
+
"/" => { return "/".to_string() }
|
26
|
+
_ => {}
|
26
27
|
}
|
27
|
-
} else if name.ends_with(ext) {
|
28
|
-
name = &name[..name.len() - ext.len()];
|
29
|
-
};
|
30
28
|
|
31
|
-
|
29
|
+
let mut name = extract_last_path_segment(pth);
|
30
|
+
|
31
|
+
if ext == ".*" {
|
32
|
+
if let Some(dot_i) = name.rfind('.') {
|
33
|
+
name = &name[0..dot_i];
|
34
|
+
}
|
35
|
+
} else if name.ends_with(ext) {
|
36
|
+
name = &name[..name.len() - ext.len()];
|
37
|
+
};
|
38
|
+
name.to_string()
|
39
|
+
}
|
32
40
|
}
|
41
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
pub mod rust {
|
2
|
+
use std::path::MAIN_SEPARATOR;
|
3
|
+
use std::str;
|
4
|
+
|
5
|
+
pub fn chop_basename(input: &str) -> Option<(String,String)> {
|
6
|
+
if input.is_empty() {
|
7
|
+
return None;
|
8
|
+
}
|
9
|
+
|
10
|
+
let mut offset = 0;
|
11
|
+
let mut trailing_slashes = input.chars().rev();
|
12
|
+
loop {
|
13
|
+
match trailing_slashes.next() {
|
14
|
+
Some(MAIN_SEPARATOR) => { offset = offset + 1 },
|
15
|
+
_ => { break },
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
let input = &input[0..input.len()-offset];
|
20
|
+
let base = input.rsplit_terminator(MAIN_SEPARATOR).nth(0).unwrap_or("");
|
21
|
+
let directory = &input[0..input.len()-base.len()];
|
22
|
+
|
23
|
+
if directory.is_empty() && (base.is_empty() || base == "/") {
|
24
|
+
return None
|
25
|
+
};
|
26
|
+
|
27
|
+
Some((directory.to_string(), base.to_string()))
|
28
|
+
}
|
29
|
+
|
30
|
+
#[test]
|
31
|
+
fn it_chops_the_basename_and_dirname() {
|
32
|
+
assert_eq!(chop_basename(&""[..]), None);
|
33
|
+
assert_eq!(chop_basename(&"/"[..]), None);
|
34
|
+
assert_eq!(
|
35
|
+
chop_basename(&"."[..]),
|
36
|
+
Some(("".to_string(), ".".to_string()))
|
37
|
+
);
|
38
|
+
assert_eq!(
|
39
|
+
chop_basename(&"asdf/asdf"[..]),
|
40
|
+
Some(("asdf/".to_string(), "asdf".to_string()))
|
41
|
+
);
|
42
|
+
assert_eq!(
|
43
|
+
chop_basename(&"asdf.txt"[..]),
|
44
|
+
Some(("".to_string(), "asdf.txt".to_string()))
|
45
|
+
);
|
46
|
+
assert_eq!(
|
47
|
+
chop_basename(&"asdf/"[..]),
|
48
|
+
Some(("".to_string(), "asdf".to_string()))
|
49
|
+
);
|
50
|
+
assert_eq!(
|
51
|
+
chop_basename(&"/asdf/"[..]),
|
52
|
+
Some(("/".to_string(), "asdf".to_string()))
|
53
|
+
);
|
54
|
+
}
|
55
|
+
|
56
|
+
}
|
data/src/dirname.rs
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
use std::path::MAIN_SEPARATOR;
|
2
1
|
use libc::c_char;
|
3
2
|
use std::ffi::{CStr, CString};
|
4
|
-
use path_parsing::{last_sep_i, last_non_sep_i, last_non_sep_i_before};
|
5
3
|
|
6
4
|
#[no_mangle]
|
7
5
|
pub extern "C" fn dirname(path: *const c_char) -> *const c_char {
|
@@ -9,24 +7,40 @@ pub extern "C" fn dirname(path: *const c_char) -> *const c_char {
|
|
9
7
|
return path
|
10
8
|
}
|
11
9
|
let r_str = unsafe { CStr::from_ptr(path) }.to_str().unwrap();
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
}
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
10
|
+
|
11
|
+
CString::new(rust::dirname(r_str)).unwrap().into_raw()
|
12
|
+
}
|
13
|
+
|
14
|
+
pub mod rust {
|
15
|
+
use std::path::MAIN_SEPARATOR;
|
16
|
+
use path_parsing::{last_sep_i, last_non_sep_i, last_non_sep_i_before};
|
17
|
+
|
18
|
+
pub fn dirname(path: &str) -> String {
|
19
|
+
let r_str = path;
|
20
|
+
if r_str.is_empty() {
|
21
|
+
return ".".to_string();
|
22
|
+
}
|
23
|
+
let non_sep_i = last_non_sep_i(r_str);
|
24
|
+
if non_sep_i == -1 {
|
25
|
+
return MAIN_SEPARATOR.to_string();
|
26
|
+
}
|
27
|
+
let sep_i = last_sep_i(r_str, non_sep_i);
|
28
|
+
if sep_i == -1 {
|
29
|
+
return ".".to_string();
|
30
|
+
}
|
31
|
+
if sep_i == 0 {
|
32
|
+
return MAIN_SEPARATOR.to_string();
|
33
|
+
}
|
34
|
+
let non_sep_i2 = last_non_sep_i_before(r_str, sep_i);
|
35
|
+
if non_sep_i2 != -1 {
|
36
|
+
return r_str[..(non_sep_i2 + 1) as usize].to_string();
|
37
|
+
} else {
|
38
|
+
return MAIN_SEPARATOR.to_string();
|
39
|
+
}
|
31
40
|
}
|
32
41
|
}
|
42
|
+
|
43
|
+
#[test]
|
44
|
+
fn returns_dot_for_empty_string(){
|
45
|
+
assert_eq!(rust::dirname(""), ".".to_string());
|
46
|
+
}
|
data/src/lib.rs
CHANGED
data/src/plus.rs
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
extern crate array_tool;
|
2
|
+
use std::path::Path;
|
3
|
+
use libc::c_char;
|
4
|
+
use std::ffi::{CStr,CString};
|
5
|
+
use std::str;
|
6
|
+
use chop_basename::rust::chop_basename;
|
7
|
+
use basename::rust::basename;
|
8
|
+
use dirname::rust::dirname;
|
9
|
+
use self::array_tool::vec::Shift;
|
10
|
+
use std::ops::Index;
|
11
|
+
|
12
|
+
#[no_mangle]
|
13
|
+
pub extern fn plus(string: *const c_char, string2: *const c_char) -> *const c_char {
|
14
|
+
let c_str = unsafe {
|
15
|
+
if string.is_null() {
|
16
|
+
return string;
|
17
|
+
}
|
18
|
+
CStr::from_ptr(string)
|
19
|
+
};
|
20
|
+
|
21
|
+
let c_str2 = unsafe {
|
22
|
+
if string2.is_null() {
|
23
|
+
return string2;
|
24
|
+
}
|
25
|
+
CStr::from_ptr(string2)
|
26
|
+
};
|
27
|
+
|
28
|
+
let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
|
29
|
+
let r_str2 = str::from_utf8(c_str2.to_bytes()).unwrap();
|
30
|
+
|
31
|
+
let result = plus_paths(r_str, r_str2);
|
32
|
+
|
33
|
+
let output = CString::new(result).unwrap();
|
34
|
+
output.into_raw()
|
35
|
+
}
|
36
|
+
|
37
|
+
fn plus_paths(path1: &str, path2: &str) -> String {
|
38
|
+
let mut prefix2 = path2.to_string();
|
39
|
+
let mut index_list2: Vec<usize> = vec![];
|
40
|
+
let mut basename_list2: Vec<String> = vec![];
|
41
|
+
|
42
|
+
loop {
|
43
|
+
match chop_basename(&prefix2[..]) {
|
44
|
+
None => { break },
|
45
|
+
Some((pfx2, basename2)) => {
|
46
|
+
prefix2 = pfx2.clone();
|
47
|
+
index_list2.unshift(pfx2.len());
|
48
|
+
basename_list2.unshift(basename2.to_owned());
|
49
|
+
},
|
50
|
+
}
|
51
|
+
}
|
52
|
+
if !prefix2.is_empty() {
|
53
|
+
return path2.to_string()
|
54
|
+
};
|
55
|
+
|
56
|
+
let mut prefix1 = path1.to_string();
|
57
|
+
|
58
|
+
loop {
|
59
|
+
while !basename_list2.is_empty() && basename_list2.first().unwrap() == "." {
|
60
|
+
index_list2.shift();
|
61
|
+
basename_list2.shift();
|
62
|
+
}
|
63
|
+
match chop_basename(&prefix1[..]) {
|
64
|
+
None => { break },
|
65
|
+
Some((pfx1, basename1)) => {
|
66
|
+
prefix1 = pfx1.clone();
|
67
|
+
if basename1 == "." { continue };
|
68
|
+
if basename1 == ".." || basename_list2.is_empty() || basename_list2.first().unwrap() != ".." {
|
69
|
+
prefix1.push_str(&basename1);
|
70
|
+
break
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
index_list2.shift();
|
75
|
+
basename_list2.shift();
|
76
|
+
}
|
77
|
+
|
78
|
+
let result: String;
|
79
|
+
|
80
|
+
let mut r1 = if let Some((_,_)) = chop_basename(&prefix1[..]) {true} else {false};
|
81
|
+
|
82
|
+
if !r1 {
|
83
|
+
r1 = basename(&prefix1[..], "").contains("/");
|
84
|
+
if r1 {
|
85
|
+
while !basename_list2.is_empty() && basename_list2.first().unwrap() == ".." {
|
86
|
+
index_list2.shift();
|
87
|
+
basename_list2.shift();
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
if !basename_list2.is_empty() {
|
92
|
+
let suffix2 = path2.index(index_list2.first().unwrap().to_owned()..);
|
93
|
+
if r1 {
|
94
|
+
result = Path::new(&prefix1).join(Path::new(&suffix2)).to_str().unwrap().to_string();
|
95
|
+
} else {
|
96
|
+
prefix1.push_str(&suffix2);
|
97
|
+
result = prefix1.to_string();
|
98
|
+
}
|
99
|
+
} else {
|
100
|
+
if r1 {
|
101
|
+
result = prefix1.to_string();
|
102
|
+
} else {
|
103
|
+
result = dirname(&prefix1[..]);
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
String::from(result)
|
108
|
+
}
|
109
|
+
|
110
|
+
#[test]
|
111
|
+
fn it_will_plus_same_as_ruby() {
|
112
|
+
assert_eq!("/" , plus_paths("/" , "/"));
|
113
|
+
assert_eq!("a/b" , plus_paths("a" , "b"));
|
114
|
+
assert_eq!("a" , plus_paths("a" , "."));
|
115
|
+
assert_eq!("b" , plus_paths("." , "b"));
|
116
|
+
assert_eq!("." , plus_paths("." , "."));
|
117
|
+
assert_eq!("/b" , plus_paths("a" , "/b"));
|
118
|
+
|
119
|
+
assert_eq!("/" , plus_paths("/" , ".."));
|
120
|
+
assert_eq!("." , plus_paths("a" , ".."));
|
121
|
+
assert_eq!("a" , plus_paths("a/b", ".."));
|
122
|
+
assert_eq!("../.." , plus_paths(".." , ".."));
|
123
|
+
assert_eq!("/c" , plus_paths("/" , "../c"));
|
124
|
+
assert_eq!("c" , plus_paths("a" , "../c"));
|
125
|
+
assert_eq!("a/c" , plus_paths("a/b", "../c"));
|
126
|
+
assert_eq!("../../c", plus_paths(".." , "../c"));
|
127
|
+
|
128
|
+
assert_eq!("a//b/d//e", plus_paths("a//b/c", "../d//e"));
|
129
|
+
|
130
|
+
assert_eq!("//foo/var/bar", plus_paths("//foo/var", "bar"));
|
131
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faster_path
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel P. Clark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -128,14 +128,14 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
131
|
+
version: 1.0.0
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
138
|
+
version: 1.0.0
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: gruff
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -177,6 +177,7 @@ files:
|
|
177
177
|
- src/basename.rs
|
178
178
|
- src/basename_for_chop.rs
|
179
179
|
- src/both_are_blank.rs
|
180
|
+
- src/chop_basename.rs
|
180
181
|
- src/dirname.rs
|
181
182
|
- src/dirname_for_chop.rs
|
182
183
|
- src/entries.rs
|
@@ -188,6 +189,7 @@ files:
|
|
188
189
|
- src/is_relative.rs
|
189
190
|
- src/lib.rs
|
190
191
|
- src/path_parsing.rs
|
192
|
+
- src/plus.rs
|
191
193
|
- src/ruby_array.rs
|
192
194
|
- src/ruby_string.rs
|
193
195
|
- src/rust_arch_bits.rs
|
@@ -211,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
211
213
|
version: '0'
|
212
214
|
requirements: []
|
213
215
|
rubyforge_project:
|
214
|
-
rubygems_version: 2.6.
|
216
|
+
rubygems_version: 2.6.13
|
215
217
|
signing_key:
|
216
218
|
specification_version: 4
|
217
219
|
summary: Reimplementation of Pathname for better performance
|