| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| #include "File.h" |
| #include "llvm/Support/FileSystem.h" |
| #include "llvm/Support/Path.h" |
| |
| namespace clang { |
| namespace doc { |
| |
| llvm::Error copyFile(llvm::StringRef FilePath, llvm::StringRef OutDirectory) { |
| llvm::SmallString<128> PathWrite; |
| llvm::sys::path::native(OutDirectory, PathWrite); |
| llvm::sys::path::append(PathWrite, llvm::sys::path::filename(FilePath)); |
| llvm::SmallString<128> PathRead; |
| llvm::sys::path::native(FilePath, PathRead); |
| std::error_code FileErr = llvm::sys::fs::copy_file(PathRead, PathWrite); |
| if (FileErr) { |
| return llvm::createStringError(llvm::inconvertibleErrorCode(), |
| "error creating file " + |
| llvm::sys::path::filename(FilePath) + |
| ": " + FileErr.message() + "\n"); |
| } |
| return llvm::Error::success(); |
| } |
| |
| llvm::SmallString<128> computeRelativePath(llvm::StringRef Destination, |
| llvm::StringRef Origin) { |
| // If Origin is empty, the relative path to the Destination is its complete |
| // path. |
| if (Origin.empty()) |
| return Destination; |
| |
| // The relative path is an empty path if both directories are the same. |
| if (Destination == Origin) |
| return {}; |
| |
| // These iterators iterate through each of their parent directories |
| llvm::sys::path::const_iterator FileI = llvm::sys::path::begin(Destination); |
| llvm::sys::path::const_iterator FileE = llvm::sys::path::end(Destination); |
| llvm::sys::path::const_iterator DirI = llvm::sys::path::begin(Origin); |
| llvm::sys::path::const_iterator DirE = llvm::sys::path::end(Origin); |
| // Advance both iterators until the paths differ. Example: |
| // Destination = A/B/C/D |
| // Origin = A/B/E/F |
| // FileI will point to C and DirI to E. The directories behind them is the |
| // directory they share (A/B). |
| while (FileI != FileE && DirI != DirE && *FileI == *DirI) { |
| ++FileI; |
| ++DirI; |
| } |
| llvm::SmallString<128> Result; // This will hold the resulting path. |
| // Result has to go up one directory for each of the remaining directories in |
| // Origin |
| while (DirI != DirE) { |
| llvm::sys::path::append(Result, ".."); |
| ++DirI; |
| } |
| // Result has to append each of the remaining directories in Destination |
| while (FileI != FileE) { |
| llvm::sys::path::append(Result, *FileI); |
| ++FileI; |
| } |
| return Result; |
| } |
| |
| } // namespace doc |
| } // namespace clang |