faster_path 0.3.7 → 0.3.8
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/README.md +26 -24
- data/lib/faster_path.rb +2 -26
- data/lib/faster_path/optional/monkeypatches.rb +2 -2
- data/lib/faster_path/thermite_initialize.rb +2 -1
- data/lib/faster_path/version.rb +1 -1
- data/src/basename.rs +63 -20
- data/src/chop_basename.rs +12 -13
- data/src/cleanpath_aggressive.rs +21 -33
- data/src/cleanpath_conservative.rs +27 -41
- data/src/dirname.rs +59 -19
- data/src/extname.rs +19 -57
- data/src/helpers.rs +13 -8
- data/src/lib.rs +14 -9
- data/src/memrnchr.rs +70 -0
- data/src/path_parsing.rs +23 -14
- data/src/pathname.rs +79 -122
- data/src/prepend_prefix.rs +12 -11
- data/src/relative_path_from.rs +17 -15
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71e809651aa4aa3df08645c40f0d616e3f061648ddeeb0e29086e578003df395
|
4
|
+
data.tar.gz: ded1645695ee0ddfd84261e25be66ed6f96b5386f45e093ecb46c0a6301f8896
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad20f8a279a81ccff6ce068f7c778649d3f71b59576d625e82e4bd1713c78d44dd10eb859b96b925f14c44f64171449c2fd17b46710a53a8e238f75ec17b5195
|
7
|
+
data.tar.gz: 0f2135684d07b33503b4ef62b4f6a750b5648d3b450d8ad0a55f9bdd54853355b86ba9e3e2fd546eb24a9148d9eace955b3642ad9bfeba4ca55c52e8de262bce
|
data/README.md
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
[](https://travis-ci.org/danielpclark/faster_path)
|
4
4
|
[](https://ci.appveyor.com/project/danielpclark/faster-path/branch/master)
|
5
5
|
[](https://github.com/danielpclark/faster_path/tags)
|
6
|
-
[](https://github.com/danielpclark/faster_path/pulse)
|
7
7
|
[](https://github.com/danielpclark/faster_path/releases)
|
8
|
-
[](https://coveralls.io/github/danielpclark/faster_path)
|
8
|
+
[](https://coveralls.io/github/danielpclark/faster_path?branch=master)
|
9
9
|
[](http://inch-ci.org/github/danielpclark/faster_path)
|
10
10
|
[](https://www.codetriage.com/danielpclark/faster_path)
|
11
11
|
[](https://twitter.com/share?url=https%3A%2F%2Fgithub.com%2Fdanielpclark%2Ffaster_path&via=6ftdan&hashtags=Ruby&text=You%20could%20save%2015%25%20or%20more%20on%20website%20page%20load%20time%20by%20switching%20to%20the%20FasterPath%20gem.)
|
@@ -115,7 +115,7 @@ curl -sSf https://static.rust-lang.org/rustup.sh | sh
|
|
115
115
|
Add this line to your application's Gemfile:
|
116
116
|
|
117
117
|
```ruby
|
118
|
-
gem 'faster_path', '~> 0.3.
|
118
|
+
gem 'faster_path', '~> 0.3.8'
|
119
119
|
```
|
120
120
|
|
121
121
|
And then execute:
|
@@ -129,7 +129,7 @@ Or install it yourself as:
|
|
129
129
|
## Visual Benchmarks
|
130
130
|
|
131
131
|
Benchmarks in Faster Path now produce visual graph charts of performance improvements.
|
132
|
-
When you run `rake bench` the graph art will be placed in `doc/graph/`. Here's the performance
|
132
|
+
When you run `export GRAPH=1; bundle && rake bench` the graph art will be placed in `doc/graph/`. Here's the performance
|
133
133
|
improvement result for the `chop_basename` method.
|
134
134
|
|
135
135
|

|
@@ -140,21 +140,23 @@ Current methods implemented:
|
|
140
140
|
|
141
141
|
|FasterPath Rust Implementation|Ruby 2.5.0 Implementation|Time Shaved Off|
|
142
142
|
|---|---|:---:|
|
143
|
-
| `FasterPath.absolute?` | `Pathname#absolute?` |
|
144
|
-
| `FasterPath.add_trailing_separator` | `Pathname#add_trailing_separator` |
|
145
|
-
| `FasterPath.
|
146
|
-
| `FasterPath.
|
147
|
-
| `FasterPath.
|
148
|
-
| `FasterPath.
|
149
|
-
| `FasterPath.
|
150
|
-
| `FasterPath.
|
151
|
-
| `FasterPath.
|
152
|
-
| `FasterPath.
|
153
|
-
| `FasterPath.
|
154
|
-
| `FasterPath.
|
155
|
-
| `FasterPath.
|
156
|
-
| `FasterPath.
|
157
|
-
| `FasterPath.
|
143
|
+
| `FasterPath.absolute?` | `Pathname#absolute?` | 95.8% |
|
144
|
+
| `FasterPath.add_trailing_separator` | `Pathname#add_trailing_separator` | 68.7% |
|
145
|
+
| `FasterPath.basename` | `File.basename` | 49.4% |
|
146
|
+
| `FasterPath.children` | `Pathname#children` | 39.2% |
|
147
|
+
| `FasterPath.chop_basename` | `Pathname#chop_basename` | 76.6% |
|
148
|
+
| `FasterPath.cleanpath_aggressive` | `Pathname#cleanpath_aggressive` | 78.2% |
|
149
|
+
| `FasterPath.cleanpath_conservative` | `Pathname#cleanpath_conservative` | 74.1% |
|
150
|
+
| `FasterPath.del_trailing_separator` | `Pathname#del_trailing_separator` | 87.7% |
|
151
|
+
| `FasterPath.directory?` | `Pathname#directory?` | 16.8% |
|
152
|
+
| `FasterPath.dirname` | `File.dirname` | 28.9% |
|
153
|
+
| `FasterPath.entries` | `Pathname#entries` | 36.1% |
|
154
|
+
| `FasterPath.extname` | `File.extname` | 66.2% |
|
155
|
+
| `FasterPath.has_trailing_separator?` | `Pathname#has_trailing_separator` | 86.3% |
|
156
|
+
| `FasterPath.plus` | `Pathname#join` | 67.9% |
|
157
|
+
| `FasterPath.plus` | `Pathname#plus` | 86.6% |
|
158
|
+
| `FasterPath.relative?` | `Pathname#relative?` | 87.2% |
|
159
|
+
| `FasterPath.relative_path_from` | `Pathname#relative_path_from` | 74.0% |
|
158
160
|
|
159
161
|
You may choose to use the methods directly, or scope change to rewrite behavior on the
|
160
162
|
standard library with the included refinements, or even call a method to monkeypatch
|
@@ -176,17 +178,17 @@ FasterPath.sledgehammer_everything!
|
|
176
178
|
|
177
179
|
## Optional Rust implementations
|
178
180
|
|
179
|
-
**These are stable, not performant, and not included in `
|
181
|
+
**These are stable, not performant, and not included in `Pathname` by default.**
|
180
182
|
|
181
|
-
These will **not** be included by default in monkey-patches.
|
183
|
+
These will **not** be included by default in monkey-patches. To try them with monkeypatching use the environment flag of `WITH_REGRESSION`. These methods are here to be improved upon.
|
182
184
|
|
183
185
|
|FasterPath Implementation|Ruby Implementation|
|
184
186
|
|---|---|
|
185
|
-
| `FasterPath.
|
186
|
-
| `FasterPath.
|
187
|
+
| `FasterPath.entries_compat` | `Pathname.entries` |
|
188
|
+
| `FasterPath.children_compat` | `Pathname.children` |
|
187
189
|
|
188
190
|
It's been my observation (and some others) that the Rust implementation of the C code for `File` has similar results but
|
189
|
-
performance seems to vary based on CPU cache on possibly 64bit/32bit system environments.
|
191
|
+
performance seems to vary based on CPU cache on possibly 64bit/32bit system environments. These are not included by default when the monkey patch method `FasterPath.sledgehammer_everything!` is executed.
|
190
192
|
|
191
193
|
## Getting Started with Development
|
192
194
|
|
data/lib/faster_path.rb
CHANGED
@@ -21,9 +21,6 @@ module FasterPath
|
|
21
21
|
private_class_method :basename
|
22
22
|
private_class_method :children
|
23
23
|
private_class_method :children_compat
|
24
|
-
private_class_method :chop_basename
|
25
|
-
private_class_method :entries
|
26
|
-
private_class_method :entries_compat
|
27
24
|
end
|
28
25
|
|
29
26
|
def self.rust_arch_bits
|
@@ -43,32 +40,11 @@ module FasterPath
|
|
43
40
|
end
|
44
41
|
|
45
42
|
def self.children(pth, with_directory=true)
|
46
|
-
|
47
|
-
return result if result
|
48
|
-
raise Errno::NOENT, "No such file or directory @ dir_initialize - #{pth}"
|
43
|
+
Public.send(:children, pth, with_directory)
|
49
44
|
end
|
50
45
|
|
51
46
|
def self.children_compat(pth, with_directory=true)
|
52
|
-
|
53
|
-
return result if result
|
54
|
-
raise Errno::NOENT, "No such file or directory @ dir_initialize - #{pth}"
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.chop_basename(pth)
|
58
|
-
result = Public.send(:chop_basename, pth)
|
59
|
-
result unless result.empty?
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.entries(pth)
|
63
|
-
result = Public.send(:entries, pth)
|
64
|
-
return result if result
|
65
|
-
raise Errno::NOENT, "No such file or directory @ dir_initialize - #{pth}"
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.entries_compat(pth)
|
69
|
-
result = Public.send(:entries_compat, pth)
|
70
|
-
return result if result
|
71
|
-
raise Errno::NOENT, "No such file or directory @ dir_initialize - #{pth}"
|
47
|
+
Public.send(:children_compat, pth, with_directory)
|
72
48
|
end
|
73
49
|
|
74
50
|
module Rust
|
@@ -10,7 +10,7 @@ module FasterPath
|
|
10
10
|
pth = pth.to_path if pth.respond_to? :to_path
|
11
11
|
raise TypeError unless pth.is_a?(String) && ext.is_a?(String)
|
12
12
|
FasterPath.basename(pth, ext)
|
13
|
-
end
|
13
|
+
end
|
14
14
|
|
15
15
|
def self.extname(pth)
|
16
16
|
pth = pth.to_path if pth.respond_to? :to_path
|
@@ -22,7 +22,7 @@ module FasterPath
|
|
22
22
|
pth = pth.to_path if pth.respond_to? :to_path
|
23
23
|
raise TypeError unless pth.is_a? String
|
24
24
|
FasterPath.dirname(pth)
|
25
|
-
end
|
25
|
+
end
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'rake/tasklib'
|
2
3
|
require_relative './version'
|
3
4
|
|
4
5
|
module Thermite
|
@@ -8,7 +9,7 @@ module Thermite
|
|
8
9
|
end
|
9
10
|
end
|
10
11
|
|
11
|
-
class Tasks
|
12
|
+
class Tasks < Rake::TaskLib
|
12
13
|
def github_download_uri(_tag, version)
|
13
14
|
"#{github_uri}/releases/download/v#{FasterPath::VERSION}/#{config.tarball_filename(version)}"
|
14
15
|
end
|
data/lib/faster_path/version.rb
CHANGED
data/src/basename.rs
CHANGED
@@ -1,26 +1,69 @@
|
|
1
1
|
extern crate memchr;
|
2
|
-
|
3
|
-
use path_parsing::{
|
4
|
-
|
5
|
-
pub fn basename<'a>(
|
6
|
-
let
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
|
3
|
+
use path_parsing::{find_last_sep_pos, find_last_non_sep_pos, find_last_dot_pos};
|
4
|
+
|
5
|
+
pub fn basename<'a>(path: &'a str, ext: &str) -> &'a str {
|
6
|
+
let bytes: &[u8] = path.as_bytes();
|
7
|
+
let mut left: usize = 0;
|
8
|
+
let mut right: usize = bytes.len();
|
9
|
+
if let Some(last_slash_pos) = find_last_sep_pos(bytes) {
|
10
|
+
if last_slash_pos == right - 1 {
|
11
|
+
if let Some(pos) = find_last_non_sep_pos(&bytes[..last_slash_pos]) {
|
12
|
+
right = pos + 1;
|
13
|
+
} else {
|
14
|
+
return "/";
|
15
|
+
}
|
16
|
+
if let Some(pos) = find_last_sep_pos(&bytes[..right]) {
|
17
|
+
left = pos + 1;
|
18
|
+
}
|
19
|
+
} else {
|
20
|
+
left = last_slash_pos + 1;
|
21
|
+
}
|
10
22
|
}
|
11
|
-
let
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
let mut name = &pth[name_start..name_end];
|
16
|
-
if ext == ".*" {
|
17
|
-
if let Some(dot_i) = memrchr('.' as u8, name.as_bytes()) {
|
18
|
-
name = &name[..dot_i];
|
23
|
+
let ext_bytes = ext.as_bytes();
|
24
|
+
if ext_bytes == b".*" {
|
25
|
+
if let Some(dot_pos) = find_last_dot_pos(&bytes[left..right]) {
|
26
|
+
right = left + dot_pos;
|
19
27
|
}
|
20
|
-
} else if
|
21
|
-
|
22
|
-
}
|
23
|
-
|
28
|
+
} else if bytes[left..right].ends_with(ext_bytes) {
|
29
|
+
right -= ext_bytes.len();
|
30
|
+
}
|
31
|
+
&path[left..right]
|
32
|
+
}
|
33
|
+
|
34
|
+
#[test]
|
35
|
+
fn absolute() {
|
36
|
+
assert_eq!(basename("/a/b///c", ""), "c");
|
37
|
+
}
|
38
|
+
|
39
|
+
#[test]
|
40
|
+
fn trailing_slashes_absolute() {
|
41
|
+
assert_eq!(basename("/a/b///c//////", ""), "c");
|
42
|
+
}
|
43
|
+
|
44
|
+
#[test]
|
45
|
+
fn relative() {
|
46
|
+
assert_eq!(basename("b///c", ""), "c");
|
47
|
+
}
|
48
|
+
|
49
|
+
#[test]
|
50
|
+
fn trailing_slashes_relative() {
|
51
|
+
assert_eq!(basename("b/c//", ""), "c");
|
52
|
+
}
|
53
|
+
|
54
|
+
#[test]
|
55
|
+
fn root() {
|
56
|
+
assert_eq!(basename("//c", ""), "c");
|
57
|
+
}
|
58
|
+
|
59
|
+
#[test]
|
60
|
+
fn trailing_slashes_root() {
|
61
|
+
assert_eq!(basename("//c//", ""), "c");
|
62
|
+
}
|
63
|
+
|
64
|
+
#[test]
|
65
|
+
fn trailing_slashes_relative_root() {
|
66
|
+
assert_eq!(basename("c//", ""), "c");
|
24
67
|
}
|
25
68
|
|
26
69
|
#[test]
|
data/src/chop_basename.rs
CHANGED
@@ -1,21 +1,14 @@
|
|
1
|
-
use
|
1
|
+
use path_parsing::{find_last_non_sep_pos, find_last_sep_pos};
|
2
2
|
use std::str;
|
3
3
|
|
4
4
|
pub fn chop_basename<'a>(input: &'a str) -> Option<(&'a str, &'a str)> {
|
5
|
-
|
5
|
+
let bytes = input.as_bytes();
|
6
|
+
let len = find_last_non_sep_pos(&bytes)? + 1;
|
7
|
+
let base_start = find_last_sep_pos(&bytes[..len]).map_or(0, |pos| pos + 1);
|
8
|
+
if base_start == len {
|
6
9
|
return None;
|
7
10
|
}
|
8
|
-
|
9
|
-
let input = input.trim_right_matches(MAIN_SEPARATOR);
|
10
|
-
let end = input.rsplitn(2, MAIN_SEPARATOR).nth(0).unwrap().len();
|
11
|
-
let base = &input[input.len()-end..input.len()];
|
12
|
-
let directory = &input[0..input.len()-base.len()];
|
13
|
-
|
14
|
-
if directory.is_empty() && (base.is_empty() || base.chars().next().unwrap() == MAIN_SEPARATOR) {
|
15
|
-
return None
|
16
|
-
};
|
17
|
-
|
18
|
-
Some((directory, base))
|
11
|
+
Some((&input[0..base_start], &input[base_start..len]))
|
19
12
|
}
|
20
13
|
|
21
14
|
#[test]
|
@@ -27,5 +20,11 @@ fn it_chops_the_basename_and_dirname() {
|
|
27
20
|
assert_eq!(chop_basename("asdf.txt"), Some(("", "asdf.txt")) );
|
28
21
|
assert_eq!(chop_basename("asdf/"), Some(("", "asdf")) );
|
29
22
|
assert_eq!(chop_basename("/asdf/"), Some(("/", "asdf")) );
|
23
|
+
assert_eq!(chop_basename("a///b"), Some(("a///", "b")) );
|
24
|
+
assert_eq!(chop_basename("a///b//"), Some(("a///", "b")) );
|
25
|
+
assert_eq!(chop_basename("/a///b//"), Some(("/a///", "b")) );
|
26
|
+
assert_eq!(chop_basename("/a///b//"), Some(("/a///", "b")) );
|
27
|
+
|
28
|
+
assert_eq!(chop_basename("./../..///.../..//"), Some(("./../..///.../", "..")));
|
30
29
|
}
|
31
30
|
|
data/src/cleanpath_aggressive.rs
CHANGED
@@ -1,32 +1,24 @@
|
|
1
|
+
use std::borrow::Cow;
|
1
2
|
use prepend_prefix::prepend_prefix;
|
2
3
|
use basename::basename;
|
3
4
|
use chop_basename::chop_basename;
|
4
|
-
|
5
|
-
use self::array_tool::vec::Shift;
|
6
|
-
use std::path::MAIN_SEPARATOR;
|
7
|
-
|
8
|
-
pub fn cleanpath_aggressive(path: &str) -> String {
|
9
|
-
let sep = MAIN_SEPARATOR.to_string();
|
10
|
-
let mut names: Vec<String> = vec![];
|
11
|
-
let mut pre = path.to_string();
|
12
|
-
loop {
|
13
|
-
match chop_basename(&pre.clone()) {
|
14
|
-
Some((ref p, ref base)) => {
|
15
|
-
pre = p.to_string();
|
16
|
-
match base.as_ref() {
|
17
|
-
"." => {},
|
18
|
-
".." => names.unshift(base.to_string()),
|
19
|
-
_ => {
|
20
|
-
if names.first() == Some(&"..".to_string()) {
|
21
|
-
names.shift();
|
22
|
-
} else {
|
23
|
-
names.unshift(base.to_string())
|
24
|
-
}
|
25
|
-
}
|
5
|
+
use path_parsing::{SEP_STR, contains_sep};
|
26
6
|
|
7
|
+
pub fn cleanpath_aggressive(path: &str) -> Cow<str> {
|
8
|
+
let mut names: Vec<&str> = vec![];
|
9
|
+
let mut prefix = path;
|
10
|
+
while let Some((ref p, ref base)) = chop_basename(&prefix) {
|
11
|
+
prefix = p;
|
12
|
+
match base.as_ref() {
|
13
|
+
"." => {}
|
14
|
+
".." => names.push(base),
|
15
|
+
_ => {
|
16
|
+
if names.last() == Some(&"..") {
|
17
|
+
names.pop();
|
18
|
+
} else {
|
19
|
+
names.push(base);
|
27
20
|
}
|
28
|
-
}
|
29
|
-
None => break,
|
21
|
+
}
|
30
22
|
}
|
31
23
|
}
|
32
24
|
// // Windows Feature
|
@@ -35,16 +27,12 @@ pub fn cleanpath_aggressive(path: &str) -> String {
|
|
35
27
|
// pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
36
28
|
// ```
|
37
29
|
//
|
38
|
-
if basename(&
|
39
|
-
|
40
|
-
|
41
|
-
let _ = names.shift();
|
42
|
-
} else {
|
43
|
-
break
|
44
|
-
}
|
45
|
-
}
|
30
|
+
if contains_sep(basename(&prefix, "").as_bytes()) {
|
31
|
+
let len = names.iter().rposition(|&c| c != "..").map_or(0, |pos| pos + 1);
|
32
|
+
names.truncate(len);
|
46
33
|
}
|
47
|
-
|
34
|
+
names.reverse();
|
35
|
+
prepend_prefix(&prefix, &names.join(&SEP_STR))
|
48
36
|
}
|
49
37
|
|
50
38
|
#[test]
|
@@ -1,25 +1,18 @@
|
|
1
|
+
use std::borrow::Cow;
|
2
|
+
use std::path::MAIN_SEPARATOR;
|
1
3
|
use prepend_prefix::prepend_prefix;
|
2
4
|
use basename::basename;
|
3
5
|
use dirname::dirname;
|
4
6
|
use chop_basename::chop_basename;
|
5
|
-
|
6
|
-
use self::array_tool::vec::Shift;
|
7
|
-
use std::path::MAIN_SEPARATOR;
|
7
|
+
use path_parsing::{SEP_STR, contains_sep};
|
8
8
|
|
9
|
-
pub fn cleanpath_conservative(path: &str) ->
|
10
|
-
let
|
11
|
-
let mut
|
12
|
-
let
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
pre = p.to_string();
|
17
|
-
match base.as_ref() {
|
18
|
-
"." => {},
|
19
|
-
_ => names.unshift(base.to_string()),
|
20
|
-
}
|
21
|
-
},
|
22
|
-
None => break,
|
9
|
+
pub fn cleanpath_conservative(path: &str) -> Cow<str> {
|
10
|
+
let mut names: Vec<&str> = vec![];
|
11
|
+
let mut prefix = path;
|
12
|
+
while let Some((ref p, ref base)) = chop_basename(&prefix) {
|
13
|
+
prefix = p;
|
14
|
+
if base != &"." {
|
15
|
+
names.push(base);
|
23
16
|
}
|
24
17
|
}
|
25
18
|
// // Windows Feature
|
@@ -28,33 +21,26 @@ pub fn cleanpath_conservative(path: &str) -> String {
|
|
28
21
|
// pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
29
22
|
// ```
|
30
23
|
//
|
31
|
-
if basename(&
|
32
|
-
|
33
|
-
|
34
|
-
let _ = names.shift();
|
35
|
-
} else {
|
36
|
-
break
|
37
|
-
}
|
38
|
-
}
|
24
|
+
if contains_sep(basename(&prefix, "").as_bytes()) {
|
25
|
+
let len = names.iter().rposition(|&c| c != "..").map_or(0, |pos| pos + 1);
|
26
|
+
names.truncate(len);
|
39
27
|
}
|
40
28
|
|
41
|
-
|
42
|
-
|
43
|
-
|
29
|
+
let last_name = match names.first() {
|
30
|
+
Some(&name) => name,
|
31
|
+
None => return dirname(&prefix).into(),
|
32
|
+
};
|
44
33
|
|
45
|
-
if
|
46
|
-
names.
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
if !(last == Some(&".".to_string()) || last == Some(&"..".to_string())) &&
|
53
|
-
chop_basename(path).map(|(a, b)| a.len() + b.len()).unwrap() < path.len() {
|
54
|
-
format!("{}{}", last.unwrap(), MAIN_SEPARATOR)
|
34
|
+
if last_name != ".." && basename(&path, "") == "." {
|
35
|
+
names.reverse();
|
36
|
+
names.push(".");
|
37
|
+
} else if last_name != "." && last_name != ".." &&
|
38
|
+
chop_basename(path).map(|(a, b)| a.len() + b.len()).unwrap() < path.len() {
|
39
|
+
return format!("{}{}", last_name, MAIN_SEPARATOR).into();
|
55
40
|
} else {
|
56
|
-
|
41
|
+
names.reverse();
|
57
42
|
}
|
43
|
+
prepend_prefix(&prefix, &names.join(&SEP_STR))
|
58
44
|
}
|
59
45
|
|
60
46
|
#[test]
|
@@ -97,11 +83,11 @@ fn it_conservatively_cleans_the_path() {
|
|
97
83
|
// DOSISH_DRIVE_LETTER = File.dirname("A:") == "A:."
|
98
84
|
// DOSISH_UNC = File.dirname("//") == "//"
|
99
85
|
//
|
100
|
-
//
|
86
|
+
//
|
101
87
|
// if DOSISH
|
102
88
|
// assert_eq!(cleanpath_conservative, 'c:/foo/bar', 'c:\\foo\\bar')
|
103
89
|
// end
|
104
|
-
//
|
90
|
+
//
|
105
91
|
// if DOSISH_UNC
|
106
92
|
// assert_eq!(cleanpath_conservative, '//', '//')
|
107
93
|
// else
|