73 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8#include "File.h"9#include "llvm/Support/FileSystem.h"10#include "llvm/Support/Path.h"11 12namespace clang {13namespace doc {14 15llvm::Error copyFile(llvm::StringRef FilePath, llvm::StringRef OutDirectory) {16 llvm::SmallString<128> PathWrite;17 llvm::sys::path::native(OutDirectory, PathWrite);18 llvm::sys::path::append(PathWrite, llvm::sys::path::filename(FilePath));19 llvm::SmallString<128> PathRead;20 llvm::sys::path::native(FilePath, PathRead);21 std::error_code FileErr = llvm::sys::fs::copy_file(PathRead, PathWrite);22 if (FileErr) {23 return llvm::createStringError(llvm::inconvertibleErrorCode(),24 "error creating file " +25 llvm::sys::path::filename(FilePath) +26 ": " + FileErr.message() + "\n");27 }28 return llvm::Error::success();29}30 31llvm::SmallString<128> computeRelativePath(llvm::StringRef Destination,32 llvm::StringRef Origin) {33 // If Origin is empty, the relative path to the Destination is its complete34 // 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 directories43 llvm::sys::path::const_iterator FileI = llvm::sys::path::begin(Destination);44 llvm::sys::path::const_iterator FileE = llvm::sys::path::end(Destination);45 llvm::sys::path::const_iterator DirI = llvm::sys::path::begin(Origin);46 llvm::sys::path::const_iterator DirE = llvm::sys::path::end(Origin);47 // Advance both iterators until the paths differ. Example:48 // Destination = A/B/C/D49 // Origin = A/B/E/F50 // FileI will point to C and DirI to E. The directories behind them is the51 // 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 in58 // Origin59 while (DirI != DirE) {60 llvm::sys::path::append(Result, "..");61 ++DirI;62 }63 // Result has to append each of the remaining directories in Destination64 while (FileI != FileE) {65 llvm::sys::path::append(Result, *FileI);66 ++FileI;67 }68 return Result;69}70 71} // namespace doc72} // namespace clang73