1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use core::fmt::Display;
16 use std::path::{Path, PathBuf};
17 
18 #[derive(Debug, PartialEq, Eq)]
19 pub struct RepoPath {
20     root: PathBuf,
21     path: PathBuf,
22 }
23 
24 impl Display for RepoPath {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result25     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26         write!(f, "{}", self.path.display())
27     }
28 }
29 
30 impl RepoPath {
new<P: Into<PathBuf>, Q: Into<PathBuf>>(root: P, path: Q) -> RepoPath31     pub fn new<P: Into<PathBuf>, Q: Into<PathBuf>>(root: P, path: Q) -> RepoPath {
32         let root: PathBuf = root.into();
33         let path: PathBuf = path.into();
34         assert!(root.is_absolute());
35         assert!(path.is_relative());
36         RepoPath { root, path }
37     }
root(&self) -> &Path38     pub fn root(&self) -> &Path {
39         self.root.as_path()
40     }
rel(&self) -> &Path41     pub fn rel(&self) -> &Path {
42         self.path.as_path()
43     }
abs(&self) -> PathBuf44     pub fn abs(&self) -> PathBuf {
45         self.root.join(&self.path)
46     }
join(&self, path: &impl AsRef<Path>) -> RepoPath47     pub fn join(&self, path: &impl AsRef<Path>) -> RepoPath {
48         RepoPath::new(self.root.clone(), self.path.join(path))
49     }
with_same_root<P: Into<PathBuf>>(&self, path: P) -> RepoPath50     pub fn with_same_root<P: Into<PathBuf>>(&self, path: P) -> RepoPath {
51         RepoPath::new(self.root.clone(), path)
52     }
53 }
54 
55 #[cfg(test)]
56 mod tests {
57     use super::*;
58 
59     #[test]
test_basic()60     fn test_basic() {
61         let p = RepoPath::new(&"/foo", &"bar");
62         assert_eq!(p.root(), Path::new("/foo"));
63         assert_eq!(p.rel(), Path::new("bar"));
64         assert_eq!(p.abs(), PathBuf::from("/foo/bar"));
65         assert_eq!(p.join(&"baz"), RepoPath::new("/foo", "bar/baz"));
66         assert_eq!(p.with_same_root(&"baz"), RepoPath::new("/foo", "baz"));
67     }
68 }
69