1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | #include "File.h" |
9 | #include "llvm/Support/FileSystem.h" |
10 | #include "llvm/Support/Path.h" |
11 | |
12 | namespace clang { |
13 | namespace doc { |
14 | |
15 | llvm::Error copyFile(llvm::StringRef FilePath, llvm::StringRef OutDirectory) { |
16 | llvm::SmallString<128> PathWrite; |
17 | llvm::sys::path::native(path: OutDirectory, result&: PathWrite); |
18 | llvm::sys::path::append(path&: PathWrite, a: llvm::sys::path::filename(path: FilePath)); |
19 | llvm::SmallString<128> PathRead; |
20 | llvm::sys::path::native(path: FilePath, result&: PathRead); |
21 | std::error_code FileErr = llvm::sys::fs::copy_file(From: PathRead, To: PathWrite); |
22 | if (FileErr) { |
23 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
24 | S: "error creating file " + |
25 | llvm::sys::path::filename(path: FilePath) + |
26 | ": " + FileErr.message() + "\n" ); |
27 | } |
28 | return llvm::Error::success(); |
29 | } |
30 | |
31 | llvm::SmallString<128> computeRelativePath(llvm::StringRef Destination, |
32 | llvm::StringRef Origin) { |
33 | // If Origin is empty, the relative path to the Destination is its complete |
34 | // path. |
35 | if (Origin.empty()) |
36 | return Destination; |
37 | |
38 | // The relative path is an empty path if both directories are the same. |
39 | if (Destination == Origin) |
40 | return {}; |
41 | |
42 | // These iterators iterate through each of their parent directories |
43 | llvm::sys::path::const_iterator FileI = llvm::sys::path::begin(path: Destination); |
44 | llvm::sys::path::const_iterator FileE = llvm::sys::path::end(path: Destination); |
45 | llvm::sys::path::const_iterator DirI = llvm::sys::path::begin(path: Origin); |
46 | llvm::sys::path::const_iterator DirE = llvm::sys::path::end(path: Origin); |
47 | // Advance both iterators until the paths differ. Example: |
48 | // Destination = A/B/C/D |
49 | // Origin = A/B/E/F |
50 | // FileI will point to C and DirI to E. The directories behind them is the |
51 | // directory they share (A/B). |
52 | while (FileI != FileE && DirI != DirE && *FileI == *DirI) { |
53 | ++FileI; |
54 | ++DirI; |
55 | } |
56 | llvm::SmallString<128> Result; // This will hold the resulting path. |
57 | // Result has to go up one directory for each of the remaining directories in |
58 | // Origin |
59 | while (DirI != DirE) { |
60 | llvm::sys::path::append(path&: Result, a: ".." ); |
61 | ++DirI; |
62 | } |
63 | // Result has to append each of the remaining directories in Destination |
64 | while (FileI != FileE) { |
65 | llvm::sys::path::append(path&: Result, a: *FileI); |
66 | ++FileI; |
67 | } |
68 | return Result; |
69 | } |
70 | |
71 | } // namespace doc |
72 | } // namespace clang |
73 | |