| 169 | } |
| 170 | |
| 171 | bool copy::operator()(const QString& offset) |
| 172 | { |
| 173 | using copy_opts = fs::copy_options; |
| 174 | |
| 175 | // NOTE always deep copy on windows. the alternatives are too messy. |
| 176 | #if defined Q_OS_WIN32 |
| 177 | m_followSymlinks = true; |
| 178 | #endif |
| 179 | |
| 180 | auto src = PathCombine(m_src.absolutePath(), offset); |
| 181 | auto dst = PathCombine(m_dst.absolutePath(), offset); |
| 182 | |
| 183 | std::error_code err{}; |
| 184 | |
| 185 | fs::copy_options opt = copy_opts::none; |
| 186 | |
| 187 | // The default behavior is to follow symlinks |
| 188 | if (!m_followSymlinks) |
| 189 | opt |= copy_opts::copy_symlinks; |
| 190 | |
| 191 | const auto testAndCopy = [opt, &err](const QString& s, const QString& d) { |
| 192 | if (ensureFilePathExists(d)) { |
| 193 | fs::copy(toStdString(s), toStdString(d), opt, err); |
| 194 | } else { |
| 195 | // mkpath failed which means the destination directory doesn't exist. |
| 196 | err = std::make_error_code(std::errc::no_such_file_or_directory); |
| 197 | } |
| 198 | |
| 199 | if (err) { |
| 200 | qWarning() << "Failed to copy files:" << QString::fromStdString(err.message()); |
| 201 | qDebug() << "Source file:" << s; |
| 202 | qDebug() << "Destination file:" << d; |
| 203 | } |
| 204 | }; |
| 205 | |
| 206 | // We can't use copy_opts::recursive because we need to take into account the |
| 207 | // blacklisted paths, so we iterate over the source directory, and if there's no blacklist |
| 208 | // match, we copy the file. |
| 209 | if (QDir src_dir(src); src_dir.exists()) { |
| 210 | QDirIterator source_it(src, QDir::Filter::Files | QDir::Filter::Hidden, QDirIterator::Subdirectories); |
| 211 | |
| 212 | while (source_it.hasNext()) { |
| 213 | auto src_path = source_it.next(); |
| 214 | auto relative_path = src_dir.relativeFilePath(src_path); |
| 215 | |
| 216 | auto dst_path = PathCombine(dst, relative_path); |
| 217 | |
| 218 | if (m_blacklist && m_blacklist->matches(relative_path)) { |
| 219 | qDebug() << "Attempted to copy blacklisted file:"; |
| 220 | qDebug() << "Source file:" << src_path; |
| 221 | qDebug() << "Destination file:" << dst_path; |
| 222 | continue; |
| 223 | } |
| 224 | |
| 225 | testAndCopy(src_path, dst_path); |
| 226 | } |
| 227 | } else { // src_dir could still be a file, try to copy it directly. |
| 228 | if (m_blacklist && m_blacklist->matches(src)){ |
nothing calls this directly
no test coverage detected