From 1a1c1ebf00162d7549fd7ff07c7b776c5221b73b Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Mon, 15 Feb 2016 08:53:48 +0300
Subject: build-pkg: move top-level code to main() function

---
 tools/build-pkg.lua | 68 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 36 insertions(+), 32 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index d087031..4f16d0b 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -917,36 +917,40 @@ local function makeMxeSourcePackage()
     makePackage(name, files, deps, ver, d1, d2)
 end
 
-assert(not io.open('usr/.git'), 'Remove usr/')
-local MXE_DIR_EXPECTED = '/usr/lib/mxe'
-if MXE_DIR ~= MXE_DIR_EXPECTED then
-    log("Warning! Building in dir %s, not in %s",
-        MXE_DIR, MXE_DIR_EXPECTED)
-end
-gitInit()
-assert(execute(("%s check-requirements MXE_TARGETS=%q"):format(
-    tool 'make', table.concat(TARGETS, ' '))))
-if not max_items then
-    local cmd = ('%s download -j 6 -k'):format(tool 'make')
-    while not execute(cmd) do end
-end
-gitAdd()
-gitCommit('Initial commit')
-gitTag(GIT_INITIAL)
-local items, item2deps, item2ver = getItems()
-local build_list = sortForBuild(items, item2deps)
-assert(isTopoOrdered(build_list, items, item2deps))
-build_list = sliceArray(build_list, max_items)
-local unbroken, item2files = buildPackages(build_list, item2deps)
-gitCheckout(GIT_ALL, unbroken, makeItem2Index(build_list))
-makeDebs(unbroken, item2deps, item2ver, item2files)
-if not no_debs then
-    makeMxeRequirementsPackage('wheezy')
-    makeMxeRequirementsPackage('jessie')
-end
-makeMxeSourcePackage()
-if #unbroken < #build_list then
-    local code = 1
-    local close = true
-    os.exit(code, close)
+local function main()
+    assert(not io.open('usr/.git'), 'Remove usr/')
+    local MXE_DIR_EXPECTED = '/usr/lib/mxe'
+    if MXE_DIR ~= MXE_DIR_EXPECTED then
+        log("Warning! Building in dir %s, not in %s",
+            MXE_DIR, MXE_DIR_EXPECTED)
+    end
+    gitInit()
+    assert(execute(("%s check-requirements MXE_TARGETS=%q"):format(
+        tool 'make', table.concat(TARGETS, ' '))))
+    if not max_items then
+        local cmd = ('%s download -j 6 -k'):format(tool 'make')
+        while not execute(cmd) do end
+    end
+    gitAdd()
+    gitCommit('Initial commit')
+    gitTag(GIT_INITIAL)
+    local items, item2deps, item2ver = getItems()
+    local build_list = sortForBuild(items, item2deps)
+    assert(isTopoOrdered(build_list, items, item2deps))
+    build_list = sliceArray(build_list, max_items)
+    local unbroken, item2files = buildPackages(build_list, item2deps)
+    gitCheckout(GIT_ALL, unbroken, makeItem2Index(build_list))
+    makeDebs(unbroken, item2deps, item2ver, item2files)
+    if not no_debs then
+        makeMxeRequirementsPackage('wheezy')
+        makeMxeRequirementsPackage('jessie')
+    end
+    makeMxeSourcePackage()
+    if #unbroken < #build_list then
+        local code = 1
+        local close = true
+        os.exit(code, close)
+    end
 end
+
+main()
-- 
cgit v0.12


From 3f47774f1c93c8cfae905897ea3a2b2229cd81f0 Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Mon, 15 Feb 2016 09:02:13 +0300
Subject: build-pkg: add argument pass=first to build funcs

---
 tools/build-pkg.lua | 38 ++++++++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index 4f16d0b..638a2b4 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -350,10 +350,10 @@ local function isBlacklisted(file)
 end
 
 local GIT_INITIAL = 'initial'
-local GIT_ALL = 'first-all'
+local GIT_ALL_PSEUDOITEM = 'all'
 
-local function itemToBranch(item)
-    return 'first-' .. item:gsub('~', '_')
+local function itemToBranch(item, pass)
+    return pass .. '-' .. item:gsub('~', '_')
 end
 
 -- creates git repo in ./usr
@@ -383,10 +383,10 @@ local function gitCommit(message)
     assert(execute(cmd:format(message)))
 end
 
-local function gitCheckout(new_branch, deps, item2index)
+local function gitCheckout(new_branch, deps, item2index, pass_of_deps)
     local main_dep = deps[1]
     if main_dep then
-        main_dep = itemToBranch(main_dep)
+        main_dep = itemToBranch(main_dep, pass_of_deps)
     else
         main_dep = GIT_INITIAL
     end
@@ -398,7 +398,7 @@ local function gitCheckout(new_branch, deps, item2index)
         local cmd2 = '%s %s merge -q %s -m %q'
         if not execute(cmd2:format(GIT,
             GIT_USER,
-            itemToBranch(deps[i]),
+            itemToBranch(deps[i], pass_of_deps),
             message))
         then
             -- probably merge conflict
@@ -546,15 +546,17 @@ local function removeEmptyDirs(item)
 end
 
 -- builds package, returns list of new files
-local function buildItem(item, item2deps, file2item, item2index)
-    gitCheckout(itemToBranch(item), item2deps[item], item2index)
+local function buildItem(item, item2deps, file2item, item2index, pass)
+    gitCheckout(
+        itemToBranch(item, pass), item2deps[item], item2index, pass
+    )
     local target, pkg = parseItem(item)
     local cmd = '%s %s MXE_TARGETS=%s --jobs=1'
     os.execute(cmd:format(tool 'make', pkg, target))
     gitAdd()
     local new_files, changed_files = gitStatus()
     if #new_files + #changed_files > 0 then
-        gitCommit(("Build %s"):format(item))
+        gitCommit(("Build %s, pass %s"):format(item, pass))
     end
     for _, file in ipairs(new_files) do
         checkFile(file, item)
@@ -771,7 +773,7 @@ local function isEmpty(files)
 end
 
 -- build all packages, save filelist to list file
-local function buildPackages(items, item2deps)
+local function buildPackages(items, item2deps, pass)
     local broken = {}
     local unbroken = {}
     local file2item = {}
@@ -788,8 +790,9 @@ local function buildPackages(items, item2deps)
     local progress_printer = progressPrinter(items)
     for i, item in ipairs(items) do
         if not brokenDep(item) then
-            local files = buildItem(item, item2deps,
-                file2item, item2index)
+            local files = buildItem(
+                item, item2deps, file2item, item2index, pass
+            )
             findForeignInstalls(item, files)
             if isBuilt(item, files) then
                 item2files[item] = files
@@ -938,8 +941,15 @@ local function main()
     local build_list = sortForBuild(items, item2deps)
     assert(isTopoOrdered(build_list, items, item2deps))
     build_list = sliceArray(build_list, max_items)
-    local unbroken, item2files = buildPackages(build_list, item2deps)
-    gitCheckout(GIT_ALL, unbroken, makeItem2Index(build_list))
+    local unbroken, item2files = buildPackages(
+        build_list, item2deps, 'first'
+    )
+    gitCheckout(
+        itemToBranch(GIT_ALL_PSEUDOITEM, 'first'),
+        unbroken,
+        makeItem2Index(build_list),
+        'first'
+    )
     makeDebs(unbroken, item2deps, item2ver, item2files)
     if not no_debs then
         makeMxeRequirementsPackage('wheezy')
-- 
cgit v0.12


From 07a0103247814dfd39f0dc057ae3d5cd70da8769 Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Mon, 15 Feb 2016 21:50:40 +0300
Subject: build-pkg: provide a way to mute removeEmptyDirs()

---
 tools/build-pkg.lua | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index 638a2b4..38500e8 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -531,13 +531,16 @@ end
 
 local function removeEmptyDirs(item)
     -- removing an empty dir can reveal another one (parent)
+    -- don't pass item to mute the log message
     local go_on = true
     while go_on do
         go_on = false
         local f = io.popen('find usr/* -empty -type d', 'r')
         for dir in f:lines() do
-            log("Remove empty directory %s created by %s",
-                dir, item)
+            if item then
+                log("Remove empty directory %s created by %s",
+                    dir, item)
+            end
             os.remove(dir)
             go_on = true
         end
-- 
cgit v0.12


From 1856ae5f8aef881a0dde8df71e1bedef4b6e83d4 Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Mon, 15 Feb 2016 21:53:23 +0300
Subject: build-pkg, buildItem(): log pass (first, second)

---
 tools/build-pkg.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index 38500e8..e866abc 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -572,8 +572,8 @@ local function buildItem(item, item2deps, file2item, item2index, pass)
         if not isInArray(creator_item, item2deps[item]) then
             table.insert(item2deps[item], creator_item)
         end
-        log('Item %s changes %s, created by %s',
-            item, file, creator_item)
+        log('Item %s (pass %s) changes %s, created by %s',
+            item, pass, file, creator_item)
     end
     checkFileList(concatArrays(new_files, changed_files), item)
     removeEmptyDirs(item)
-- 
cgit v0.12


From d25a31bd2183f101d6836af54ed8eafbd9057700 Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Sun, 21 Feb 2016 16:41:51 +0300
Subject: build-pkg: move function isBuilt()

It will be used in buildItem()
---
 tools/build-pkg.lua | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index e866abc..7a7172f 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -548,6 +548,18 @@ local function removeEmptyDirs(item)
     end
 end
 
+local function isBuilt(item, files)
+    local target, pkg = parseItem(item)
+    local INSTALLED = 'usr/%s/installed/%s'
+    local installed = INSTALLED:format(target, pkg)
+    for _, file in ipairs(files) do
+        if file == installed then
+            return true
+        end
+    end
+    return false
+end
+
 -- builds package, returns list of new files
 local function buildItem(item, item2deps, file2item, item2index, pass)
     gitCheckout(
@@ -692,18 +704,6 @@ local function makeDeb(item, files, deps, ver)
     makePackage(deb_pkg, files, deb_deps, ver, d1, d2)
 end
 
-local function isBuilt(item, files)
-    local target, pkg = parseItem(item)
-    local INSTALLED = 'usr/%s/installed/%s'
-    local installed = INSTALLED:format(target, pkg)
-    for _, file in ipairs(files) do
-        if file == installed then
-            return true
-        end
-    end
-    return false
-end
-
 local function findForeignInstalls(item, files)
     for _, file in ipairs(files) do
         local pattern = 'usr/([^/]+)/installed/([^/]+)'
-- 
cgit v0.12


From aa4744cea4cf5b785216f985f4b42c79da417c28 Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Mon, 15 Feb 2016 21:54:38 +0300
Subject: build-pkg: add second pass

The second pass is done after the first one. During the second pass,
an item is built in tree of files from all other items. It checks that:

  * packages can be built in any order satisfying dependencies;
  * a package can be rebuilt after its dependee.

For both cases, not only build status is checked but also two sets of
files are compared. Currently content of files is not checked, only
their existance in both passes.

See #1111
---
 tools/build-pkg.lua | 87 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 78 insertions(+), 9 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index 7a7172f..a78c444 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -548,6 +548,57 @@ local function removeEmptyDirs(item)
     end
 end
 
+local function prepareTree(pass, item, item2deps, prev_files, item2index)
+    if pass == 'first' then
+        gitCheckout(
+            itemToBranch(item, pass),
+            item2deps[item],
+            item2index,
+            pass
+        )
+    elseif pass == 'second' then
+        -- Build item second time to check if it builds correctly if
+        -- its followers and unrelated packages have been built.
+        gitCheckout(
+            itemToBranch(item, 'second'),
+            {GIT_ALL_PSEUDOITEM},
+            item2index,
+            'first'
+        )
+        -- Remove files of item from previous build.
+        for _, file in ipairs(prev_files) do
+            os.remove(file)
+        end
+        removeEmptyDirs()
+        gitAdd()
+        gitCommit(("Remove %s to rebuild it"):format(item, pass))
+    else
+        error("Unknown pass: " .. pass)
+    end
+end
+
+local function comparePasses(item, new_files, prev_file2item, prev_files)
+    local files_set = {}
+    for _, file in ipairs(new_files) do
+        if not prev_file2item[file] then
+            log('Item %s installs a file on second pass only: %s',
+                item, file)
+        elseif prev_file2item[file] ~= item then
+            log('File %s was installed by %s on first pass ' ..
+                'and by %s - on the second pass',
+                file, prev_file2item[file], item)
+        end
+        files_set[file] = true
+    end
+    for _, file in ipairs(prev_files) do
+        if not files_set[file] then
+            log('Item %s installs a file on first pass only: %s',
+                item, file)
+        end
+    end
+    -- TODO compare contents of files (nm for binaries)
+end
+
 local function isBuilt(item, files)
     local target, pkg = parseItem(item)
     local INSTALLED = 'usr/%s/installed/%s'
@@ -561,10 +612,9 @@ local function isBuilt(item, files)
 end
 
 -- builds package, returns list of new files
-local function buildItem(item, item2deps, file2item, item2index, pass)
-    gitCheckout(
-        itemToBranch(item, pass), item2deps[item], item2index, pass
-    )
+-- prev_files is passed only to second pass.
+local function buildItem(item, item2deps, file2item, item2index, pass, prev_files)
+    prepareTree(pass, item, item2deps, prev_files, item2index)
     local target, pkg = parseItem(item)
     local cmd = '%s %s MXE_TARGETS=%s --jobs=1'
     os.execute(cmd:format(tool 'make', pkg, target))
@@ -573,9 +623,13 @@ local function buildItem(item, item2deps, file2item, item2index, pass)
     if #new_files + #changed_files > 0 then
         gitCommit(("Build %s, pass %s"):format(item, pass))
     end
-    for _, file in ipairs(new_files) do
-        checkFile(file, item)
-        file2item[file] = item
+    if pass == 'first' then
+        for _, file in ipairs(new_files) do
+            checkFile(file, item)
+            file2item[file] = item
+        end
+    elseif isBuilt(item, new_files) then
+        comparePasses(item, new_files, file2item, prev_files)
     end
     for _, file in ipairs(changed_files) do
         checkFile(file, item)
@@ -776,7 +830,8 @@ local function isEmpty(files)
 end
 
 -- build all packages, save filelist to list file
-local function buildPackages(items, item2deps, pass)
+-- prev_files is passed only to second pass.
+local function buildPackages(items, item2deps, pass, prev_item2files)
     local broken = {}
     local unbroken = {}
     local file2item = {}
@@ -789,12 +844,22 @@ local function buildPackages(items, item2deps, pass)
         end
         return false
     end
+    if pass == 'second' then
+        assert(prev_item2files)
+        -- fill file2item with data from prev_item2files
+        for item, files in pairs(prev_item2files) do
+            for _, file in ipairs(files) do
+                file2item[file] = item
+            end
+        end
+    end
     local item2index = makeItem2Index(items)
     local progress_printer = progressPrinter(items)
     for i, item in ipairs(items) do
         if not brokenDep(item) then
+            local prev_files = prev_item2files and prev_item2files[item]
             local files = buildItem(
-                item, item2deps, file2item, item2index, pass
+                item, item2deps, file2item, item2index, pass, prev_files
             )
             findForeignInstalls(item, files)
             if isBuilt(item, files) then
@@ -959,6 +1024,10 @@ local function main()
         makeMxeRequirementsPackage('jessie')
     end
     makeMxeSourcePackage()
+    -- second pass
+    buildPackages(
+        build_list, item2deps, 'second', item2files
+    )
     if #unbroken < #build_list then
         local code = 1
         local close = true
-- 
cgit v0.12


From f3de04c95496fbee09c3c8f9e31deb5351de1b4d Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Mon, 15 Feb 2016 22:02:19 +0300
Subject: build-pkg: provide a way to disable second pass

---
 tools/build-pkg.lua | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index a78c444..d02a29e 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -19,6 +19,9 @@ To prevent build-pkg from creating deb packages,
 set environment variable MXE_NO_DEBS to 1
 In this case fakeroot and dpkg-deb are not needed.
 
+To switch off the second pass, set MXE_NO_SECOND_PASS to 1.
+See https://github.com/mxe/mxe/issues/1111
+
 To limit number of packages being built to x,
 set environment variable MXE_MAX_ITEMS to x,
 
@@ -32,6 +35,7 @@ How to remove them: http://stackoverflow.com/a/4262545
 
 local max_items = tonumber(os.getenv('MXE_MAX_ITEMS'))
 local no_debs = os.getenv('MXE_NO_DEBS')
+local no_second_pass = os.getenv('MXE_NO_SECOND_PASS')
 
 local TODAY = os.date("%Y%m%d")
 
@@ -1024,10 +1028,11 @@ local function main()
         makeMxeRequirementsPackage('jessie')
     end
     makeMxeSourcePackage()
-    -- second pass
-    buildPackages(
-        build_list, item2deps, 'second', item2files
-    )
+    if not no_second_pass then
+        buildPackages(
+            build_list, item2deps, 'second', item2files
+        )
+    end
     if #unbroken < #build_list then
         local code = 1
         local close = true
-- 
cgit v0.12


From 732169d86a0ea74e8a4fa75bc6fae18e10a0aeb3 Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Thu, 18 Feb 2016 01:23:00 +0300
Subject: build-pkg: exit with non-zero if second pass fails

---
 tools/build-pkg.lua | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index d02a29e..81b0391 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -1013,9 +1013,13 @@ local function main()
     local build_list = sortForBuild(items, item2deps)
     assert(isTopoOrdered(build_list, items, item2deps))
     build_list = sliceArray(build_list, max_items)
+    local first_pass_failed, second_pass_failed
     local unbroken, item2files = buildPackages(
         build_list, item2deps, 'first'
     )
+    if #unbroken < #build_list then
+        first_pass_failed = true
+    end
     gitCheckout(
         itemToBranch(GIT_ALL_PSEUDOITEM, 'first'),
         unbroken,
@@ -1029,11 +1033,14 @@ local function main()
     end
     makeMxeSourcePackage()
     if not no_second_pass then
-        buildPackages(
+        local unbroken_second = buildPackages(
             build_list, item2deps, 'second', item2files
         )
+        if #unbroken_second < #build_list then
+            second_pass_failed = true
+        end
     end
-    if #unbroken < #build_list then
+    if first_pass_failed or second_pass_failed then
         local code = 1
         local close = true
         os.exit(code, close)
-- 
cgit v0.12


From ea511c193cd74b9cd6fae46c6745e38df4c4acb4 Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Sun, 28 Feb 2016 13:51:19 +0300
Subject: build-pkg: use "git add" with --all

From the warning produced by "git add ." after removing a file with "rm":

> warning: You ran 'git add' with neither '-A (--all)' or '--ignore-removal',
> whose behaviour will change in Git 2.0 with respect to paths you removed.
> Paths like 'foo.txt' that are
> removed from your working tree are ignored with this version of Git.
>
> * 'git add --ignore-removal <pathspec>', which is the current default,
>   ignores paths you removed from your working tree.
>
> * 'git add --all <pathspec>' will let you also record the removals.
>
> Run 'git status' to check the paths you removed from your working tree.

$ git status --porcelain
 D foo.txt

$ git add --all .

$ git status --porcelain
D  foo.txt

$ git --version
git version 1.9.1
---
 tools/build-pkg.lua | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index 81b0391..b3fa217 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -430,7 +430,7 @@ local function gitCheckout(new_branch, deps, item2index, pass_of_deps)
 end
 
 local function gitAdd()
-    os.execute(GIT .. 'add .')
+    os.execute(GIT .. 'add --all .')
 end
 
 -- return two lists of filepaths under ./usr/
@@ -442,6 +442,7 @@ local function gitStatus()
     local git_st = io.popen(GIT .. 'status --porcelain', 'r')
     for line in git_st:lines() do
         local status, file = line:match('(..) (.*)')
+        assert(status:sub(2, 2) == ' ')
         status = trim(status)
         if file:sub(1, 1) == '"' then
             -- filename with a space is quoted by git
-- 
cgit v0.12


From 6784792540ffd9eec647c85a984e1af126e79f4f Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Sun, 28 Feb 2016 14:59:10 +0300
Subject: build-pkg: detect broken symlink and removed file

---
 tools/build-pkg.lua | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index b3fa217..a5635ca 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -178,6 +178,10 @@ local function fileExists(name)
     end
 end
 
+local function isSymlink(name)
+    return shell(("ls -l %q"):format(name)):sub(1, 1) == "l"
+end
+
 local function writeFile(filename, data)
     local file = io.open(filename, 'w')
     file:write(data)
@@ -450,7 +454,13 @@ local function gitStatus()
         end
         file = 'usr/' .. file
         if not fileExists(file) then
-            log('Missing file: %q', file)
+            if status == 'D' then
+                log('Removed file: %q', file)
+            elseif isSymlink(file) then
+                log('Broken symlink: %q', file)
+            else
+                log('Missing file: %q', file)
+            end
         elseif not isBlacklisted(file) then
             if status == 'A' then
                 table.insert(new_files, file)
-- 
cgit v0.12


From 9da2e477d372a21e727a3c47bca8fe1a8345192d Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Sun, 28 Feb 2016 16:34:35 +0300
Subject: build-pkg: provide more info about removed files

---
 tools/build-pkg.lua | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index a5635ca..56b1aaa 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -317,6 +317,18 @@ local function sortForBuild(items, item2deps)
     return build_list
 end
 
+local function isDependency(item, dependency, item2deps)
+    for _, dep in ipairs(item2deps[item]) do
+        if dep == dependency then
+            return true
+        end
+        if isDependency(dep, dependency, item2deps) then
+            return true
+        end
+    end
+    return false
+end
+
 local function makeItem2Index(build_list)
     local item2index = {}
     for index, item in ipairs(build_list) do
@@ -440,7 +452,7 @@ end
 -- return two lists of filepaths under ./usr/
 -- 1. new files
 -- 2. changed files
-local function gitStatus()
+local function gitStatus(item, item2deps, file2item)
     local new_files = {}
     local changed_files = {}
     local git_st = io.popen(GIT .. 'status --porcelain', 'r')
@@ -455,7 +467,17 @@ local function gitStatus()
         file = 'usr/' .. file
         if not fileExists(file) then
             if status == 'D' then
-                log('Removed file: %q', file)
+                local prev_owner = assert(file2item[file])
+                if prev_owner == item then
+                    log('Item %s removed %q installed by itself',
+                        item, file)
+                elseif isDependency(prev_owner, item, item2deps) then
+                    log('Item %s removed %q installed by its follower %s',
+                        item, file, prev_owner)
+                else
+                    log('Item %s removed %q installed by %s',
+                        item, file, prev_owner)
+                end
             elseif isSymlink(file) then
                 log('Broken symlink: %q', file)
             else
@@ -634,7 +656,7 @@ local function buildItem(item, item2deps, file2item, item2index, pass, prev_file
     local cmd = '%s %s MXE_TARGETS=%s --jobs=1'
     os.execute(cmd:format(tool 'make', pkg, target))
     gitAdd()
-    local new_files, changed_files = gitStatus()
+    local new_files, changed_files = gitStatus(item, item2deps, file2item)
     if #new_files + #changed_files > 0 then
         gitCommit(("Build %s, pass %s"):format(item, pass))
     end
-- 
cgit v0.12


From c5c610b0853821a8ba824ff7a96d3bfc5d8562e7 Mon Sep 17 00:00:00 2001
From: Boris Nagaev <bnagaev@gmail.com>
Date: Wed, 20 Apr 2016 09:07:15 +0300
Subject: build-pkg, second pass: fix fail on broken package

If a package is found to be broken on the first pass, then
prev_files = nil, because this structure is filled only
for non-broken packages.

See https://github.com/mxe/mxe/pull/1243#issuecomment-211137555
---
 tools/build-pkg.lua | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/tools/build-pkg.lua b/tools/build-pkg.lua
index 56b1aaa..0af1d33 100755
--- a/tools/build-pkg.lua
+++ b/tools/build-pkg.lua
@@ -602,13 +602,15 @@ local function prepareTree(pass, item, item2deps, prev_files, item2index)
             item2index,
             'first'
         )
-        -- Remove files of item from previous build.
-        for _, file in ipairs(prev_files) do
-            os.remove(file)
-        end
         removeEmptyDirs()
-        gitAdd()
-        gitCommit(("Remove %s to rebuild it"):format(item, pass))
+        if prev_files then
+            -- Remove files of item from previous build.
+            for _, file in ipairs(prev_files) do
+                os.remove(file)
+            end
+            gitAdd()
+            gitCommit(("Remove %s to rebuild it"):format(item, pass))
+        end
     else
         error("Unknown pass: " .. pass)
     end
-- 
cgit v0.12