Advertisement
MeXaN1cK

Diff

Mar 8th, 2021 (edited)
865
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.65 KB | None | 0 0
  1. local serialization = require("serialization")
  2. local unicode = require("unicode")
  3.  
  4. local max = math.max
  5.  
  6. local function saveFile(data, fl)
  7.     file = io.open(fl, "w")
  8.     file:write(data)
  9.     file:close()
  10. end
  11.  
  12. local function getFileLines(filename)
  13.     local result = {}
  14.     for line in io.lines(filename) do
  15.         table.insert(result, line)
  16.     end
  17.     return result
  18. end
  19.  
  20. function timeOffset()
  21.     local currenttime = os.time()
  22.     local datetime = os.date("!*t", currenttime)
  23.     datetime.isdst = true -- Флаг дневного времени суток
  24.     return currenttime - os.time(datetime)
  25. end
  26.  
  27. local function hunkHeader(arr)
  28.     local header = "@@ -%d,%d +%d,%d @@"
  29.     return string.format(header, arr[1], arr[2], arr[3], arr[4])
  30. end
  31.  
  32. local function longestCommonSubSequence(str1, str2)
  33.     if str1 == nil or str2 == nil then
  34.         return nil
  35.     end
  36.     local str1Len = #str1
  37.     local str2Len = #str2
  38.     local num = {}
  39.  
  40.     for i = 0, str1Len do
  41.         local subArray = {}
  42.         for j = 0, str2Len do
  43.             subArray[j] = 0
  44.         end
  45.         num[i] = subArray
  46.     end
  47.  
  48.     for i = 0, str1Len do
  49.         for j = 0, str2Len do
  50.             if str1[i] == str2[j] then
  51.                 if i == 0 or j == 0 then
  52.                     num[i][j] = 1
  53.                 else
  54.                     num[i][j] = 1 + num[i - 1][j - 1]
  55.                 end
  56.             else
  57.                 if i == 0 and j == 0 then
  58.                     num[i][j] = 0
  59.                 elseif i == 0 and j ~= 0 then
  60.                     num[i][j] = max(0, num[i][j - 1])
  61.                 elseif i ~= 0 and j == 0 then
  62.                     num[i][j] = max(0, num[i - 1][j])
  63.                 elseif i ~= 0 and j ~= 0 then
  64.                     num[i][j] = max(num[i - 1][j], num[i][j - 1])
  65.                 end
  66.             end
  67.         end
  68.     end
  69.     return num
  70. end
  71.  
  72. local function printDiff(arr, str1, str2, i, j)
  73.     local R = {}
  74.     if i > 0 and j > 0 and str1[i] == str2[j] then
  75.         R = printDiff(arr, str1, str2, i - 1, j - 1)
  76.         table.insert(R, {file = "fl", String = " " .. str1[i], line = i})
  77.         return R
  78.     elseif j > 0 and (i == 0 or arr[i][j - 1] >= arr[i - 1][j]) then
  79.         R = printDiff(arr, str1, str2, i, j - 1)
  80.         table.insert(R, {file = "fl2", String = "+" .. str2[j], line = j})
  81.         return R
  82.     elseif i > 0 and (j == 0 or arr[i][j - 1] < arr[i - 1][j]) then
  83.         R = printDiff(arr, str1, str2, i - 1, j)
  84.         table.insert(R, {file = "fl1", String = "-" .. str1[i], line = i})
  85.         return R
  86.     else
  87.         return R
  88.     end
  89. end
  90.  
  91. local function generatePatch(old_file, new_file, patch_file)
  92.     local result = {
  93.         "--- " .. old_file .. "\t" .. os.date("%Y-%m-%d %X") .. "\t" .. "+0" .. math.ceil(timeOffset() / 3600) .. "00",
  94.         "+++ " .. new_file .. "\t" .. os.date("%Y-%m-%d %X") .. "\t" .. "+0" .. math.ceil(timeOffset() / 3600) .. "00"
  95.     }
  96.  
  97.     local hunks = getHunks(getFileLines(old_file), getFileLines(new_file))
  98.  
  99.     for i = 1, #hunks do
  100.         table.insert(result, hunkHeader(hunks[i]))
  101.         table.insert(result, table.concat(hunks[i][5], "\r\n"))
  102.     end
  103.    
  104.     if patch_file:match(".diff") then
  105.         saveFile(table.concat(result, "\r\n"), patch_file)
  106.     else
  107.         saveFile(table.concat(result, "\r\n"), patch_file..".diff")
  108.     end
  109. end
  110.  
  111. function getHunks(old_file_lines, new_file_lines)
  112.     local hunkPositions = {}
  113.  
  114.     local diffRes =
  115.         printDiff(
  116.         longestCommonSubSequence(old_file_lines, new_file_lines),
  117.         old_file_lines,
  118.         new_file_lines,
  119.         #old_file_lines,
  120.         #new_file_lines
  121.     )
  122.  
  123.     local isFindStart = false
  124.     local hunkCounter = 0
  125.     local hunkStartPositionInOldFile = 0
  126.     local sequenceCounter = 0
  127.  
  128.     local addLineCounter = 0
  129.     local delLineCounter = 0
  130.     local hunkAddLineCounter = 0
  131.     local hunkDelLineCounter = 0
  132.     local hunkData = {}
  133.  
  134.     for k, v in ipairs(diffRes) do
  135.         sequenceCounter = sequenceCounter + 1
  136.         if v["file"] == "fl1" or v["file"] == "fl2" then
  137.             hunkData[#hunkData + 1] = v["String"]
  138.             if v["file"] == "fl1" then
  139.                 delLineCounter = delLineCounter + 1
  140.                 hunkDelLineCounter = hunkDelLineCounter + 1
  141.             else
  142.                 addLineCounter = addLineCounter + 1
  143.                 hunkAddLineCounter = hunkAddLineCounter + 1
  144.             end
  145.             if isFindStart == false then
  146.                 isFindStart = true
  147.                 hunkStartPositionInOldFile = sequenceCounter - (addLineCounter)
  148.             end
  149.             hunkCounter = hunkCounter + 1
  150.         elseif isFindStart then
  151.             hunkPositions[#hunkPositions + 1] = {
  152.                 hunkStartPositionInOldFile,
  153.                 hunkDelLineCounter,
  154.                 sequenceCounter - delLineCounter - 1,
  155.                 hunkAddLineCounter,
  156.                 hunkData
  157.             }
  158.             hunkCounter = 0
  159.             hunkStartPositionInOldFile = 0
  160.             isFindStart = false
  161.             hunkAddLineCounter = 0
  162.             hunkDelLineCounter = 0
  163.             hunkData = {}
  164.         end
  165.     end
  166.  
  167.     if isFindStart then
  168.         hunkPositions[#hunkPositions + 1] = {
  169.             hunkStartPositionInOldFile,
  170.             hunkDelLineCounter,
  171.             sequenceCounter - delLineCounter - 1,
  172.             hunkAddLineCounter,
  173.             hunkData
  174.         }
  175.         hunkCounter = 0
  176.         hunkStartPositionInOldFile = 0
  177.         isFindStart = false
  178.         hunkAddLineCounter = 0
  179.         hunkDelLineCounter = 0
  180.         hunkData = {}
  181.     end
  182.  
  183.     return hunkPositions
  184. end
  185.  
  186. args = require("shell").parse(...)
  187. generatePatch(args[1], args[2], args[3])
  188.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement