* @brief Write out a patch file. * Writes patch file using already computed diffutils script. Converts path * delimiters from \ to / since we want to keep compatibility with patch-tools. * @param [in] script list of changes. * @param [in] inf file_data table containing filenames */
| 1740 | * @param [in] inf file_data table containing filenames |
| 1741 | */ |
| 1742 | void CDiffWrapper::WritePatchFile(struct change * script, file_data * inf) |
| 1743 | { |
| 1744 | file_data inf_patch[2] = { inf[0], inf[1] }; |
| 1745 | |
| 1746 | // Get paths, primarily use alternative paths, only if they are empty |
| 1747 | // use full filepaths |
| 1748 | String path1(m_alternativePaths[0]); |
| 1749 | String path2(m_alternativePaths[1]); |
| 1750 | if (path1.empty()) |
| 1751 | path1 = m_files[0]; |
| 1752 | if (path2.empty()) |
| 1753 | path2 = m_files[1]; |
| 1754 | path1 = paths::ToUnixPath(path1); |
| 1755 | path2 = paths::ToUnixPath(path2); |
| 1756 | auto strdupPath = [](const String& path, const void *buffer, size_t buffered_chars) -> char* |
| 1757 | { |
| 1758 | FileTextEncoding encoding = codepage_detect::Guess(_T(""), buffer, buffered_chars, 1); |
| 1759 | if (encoding.m_unicoding != ucr::NONE) |
| 1760 | encoding.SetUnicoding(ucr::UTF8); |
| 1761 | ucr::buffer buf(256); |
| 1762 | ucr::convert(ucr::CP_TCHAR, reinterpret_cast<const unsigned char *>(path.c_str()), static_cast<int>(path.size() * sizeof(tchar_t)), encoding.m_codepage, &buf); |
| 1763 | return strdup(reinterpret_cast<const char *>(buf.ptr)); |
| 1764 | }; |
| 1765 | inf_patch[0].name = strdupPath(path1, inf_patch[0].buffer, inf_patch[0].buffered_chars); |
| 1766 | inf_patch[1].name = strdupPath(path2, inf_patch[1].buffer, inf_patch[1].buffered_chars); |
| 1767 | |
| 1768 | // If paths in m_s1File and m_s2File point to original files, then we can use |
| 1769 | // them to fix potentially meaningless stats from potentially temporary files, |
| 1770 | // resulting from whatever transforms may have taken place. |
| 1771 | // If not, then we can't help it, and hence assert that this won't happen. |
| 1772 | if (!m_bPathsAreTemp) |
| 1773 | { |
| 1774 | mywstat(m_files[0].c_str(), &inf_patch[0].stat); |
| 1775 | mywstat(m_files[1].c_str(), &inf_patch[1].stat); |
| 1776 | } |
| 1777 | else |
| 1778 | { |
| 1779 | assert(false); |
| 1780 | } |
| 1781 | |
| 1782 | outfile = nullptr; |
| 1783 | if (!m_sPatchFile.empty()) |
| 1784 | { |
| 1785 | const tchar_t *mode = (m_bAppendFiles ? _T("a+") : _T("w+")); |
| 1786 | if (cio::tfopen_s(&outfile, m_sPatchFile, mode) != 0) |
| 1787 | outfile = nullptr; |
| 1788 | } |
| 1789 | |
| 1790 | if (outfile == nullptr) |
| 1791 | { |
| 1792 | m_status.bPatchFileFailed = true; |
| 1793 | return; |
| 1794 | } |
| 1795 | |
| 1796 | if (paths::IsNullDeviceName(ucr::toTString(inf[0].name))) |
| 1797 | { |
| 1798 | free((void *)inf_patch[0].name); |
| 1799 | inf_patch[0].name = strdup("/dev/null"); |
nothing calls this directly
no test coverage detected