Skip to content

Commit 2fd0bd4

Browse files
committed
(#18) IPath.Parent: document the current solution
1 parent 0d425ae commit 2fd0bd4

3 files changed

Lines changed: 27 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ All notable changes to this project will be documented in this file.
1010

1111
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1212

13+
## [Unreleased]
14+
### Changed
15+
- [#18](https://github.com/ForNeVeR/TruePath/issues/18): update to behavior of `.Parent` on relative paths.
16+
17+
Now, it works for relative paths by either removing the last part or adding `..` as necessary to lead to a parent directory.
18+
19+
Thanks to @Kataane.
20+
1321
## [1.4.0] - 2024-08-12
1422
### Changed
1523
- [#16: Support Windows disk drives in the normalization algorithm](https://github.com/ForNeVeR/TruePath/issues/16).

README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,28 @@ This is an interface that is implemented by both `LocalPath` and `AbsolutePath`.
7171
This is a marker type that doesn't offer any advanced functionality over the contained string. It is used to mark paths that include wildcards, for further integration with external libraries, such as [Microsoft.Extensions.FileSystemGlobbing][file-system-globbing.nuget].
7272

7373
### Path Features
74-
Aside from the strict types, the following features are supported for the paths:
75-
- `IPath::Value` returns the normalized path string;
76-
- `IPath::FileName` returns the last component of the path;
77-
- `IPath::Parent` returns the parent path item (`null` for the root path or top-level relative path);
78-
- `IPath<T>` supports operators to join it with `LocalPath` or a `string` (note that in both cases appending an absolute path to path of another kind will take over: the last absolute path in chain will win and destroy all the previous ones; this is the standard behavior of path-combining methods — use `AbsolutePath` in combination with `RelativePath` if you want to avoid this behavior);
79-
- `IPath::IsPrefixOf` to check path prefixes;
80-
- `IPath::StartsWith` to check if the current path starts with a specified path;
81-
- `AbsolutePath::ReadKind` helps to check if a path exists, and if it is, then what kind of path it is (file, directory, or something else);
74+
Aside from the strict types, the following features are supported for the paths.
75+
76+
- `IPath::Value` returns the normalized path string.
77+
- `IPath::FileName` returns the last component of the path.
78+
- `IPath::Parent` returns the parent path item (`null` for the root absolute path).
79+
80+
Note that it will _always_ return a meaningful parent for a relative path: parent for `.` is `..`, parent for `..` is `../..`.
81+
82+
This means that generally `.Parent` behaves the same as appending a `..` component to the end of the path would. Also, this allows for an interesting property that `a / b.Parent.Value` is always the same as `(a / b).Parent` and `a / b / ".."` — in cases when this yield no exceptions, at least.
83+
- `IPath<T>` supports operators to join it with `LocalPath` or a `string` (note that in both cases appending an absolute path to path of another kind will take over: the last absolute path in chain will win and destroy all the previous ones; this is the standard behavior of path-combining methods — use `AbsolutePath` in combination with `RelativePath` if you want to avoid this behavior).
84+
- `IPath::IsPrefixOf` to check path prefixes.
85+
- `IPath::StartsWith` to check if the current path starts with a specified path.
86+
- `AbsolutePath::ReadKind` helps to check if a path exists, and if it is, then what kind of path it is (file, directory, or something else).
8287
- `AbsolutePath::Canonicalize` to convert the path to the correct case on case-insensitive file systems, resolve symlinks.
83-
- `LocalPath::IsAbsolute` to check the path kind (since it supports both kinds);
88+
- `LocalPath::IsAbsolute` to check the path kind (since it supports both kinds).
8489
- `LocalPath::ResolveToCurrentDirectory`: effectively calculates `currentDirectory / this`. No-op for paths that are already absolute (aside from converting to the `AbsolutePath` type).
85-
- `AbsolutePath::RelativeTo`, `LocalPath::RelativeTo` to get a relative part between two paths, if possible;
90+
- `AbsolutePath::RelativeTo`, `LocalPath::RelativeTo` to get a relative part between two paths, if possible.
8691
- extension methods on `IPath`:
8792
- `GetExtensionWithDot` and `GetExtensionWithoutDot` to get the file extension with or without the leading dot (note that `GetExtensionWithDot` will behave differently for paths ending with dots and paths without dot at all);
8893
- `GetFileNameWithoutExtension` to get the file name without the extension (and without the trailing dot, if any)
8994

90-
(Note how `GetFileNameWithoutExtension()` works nicely together with `GetExtensionWithDot()` to reconstruct the resulting path from their concatenation, however weird the initial name was — no extension, trailing dot, no base name.)
95+
(note how `GetFileNameWithoutExtension()` works nicely together with `GetExtensionWithDot()` to reconstruct the resulting path from their concatenation, however weird the initial name was — no extension, trailing dot, no base name).
9196

9297
### `Temporary`
9398

TruePath/IPath.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ public interface IPath
1414
string FileName { get; }
1515

1616
/// <summary>
17-
/// The parent of this path. Will be <c>null</c> for a rooted absolute path, or relative path pointing to the
18-
/// current directory.
17+
/// The parent of this path. Will be <c>null</c> for a rooted absolute path. For a relative path, will always
18+
/// resolve to its parent directory — by either removing directories from the end of the path, or appending
19+
/// <code>..</code> to the end.
1920
/// </summary>
2021
IPath? Parent { get; }
2122
}

0 commit comments

Comments
 (0)