| 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 | |