faster_path 0.1.12 → 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|