Prevent single-child ".." folders from appearing at the top of the source tree; merge project.eachfile() into project.getsourcetree()

This commit is contained in:
Jason Perkins 2012-03-27 19:52:48 -04:00
parent 0b241993c2
commit a1a0afd327
5 changed files with 99 additions and 146 deletions

View File

@ -228,6 +228,7 @@
function tree.trimroot(tr)
local trimmed
-- start by removing single-children folders from the top of the tree
while #tr.children == 1 do
local node = tr.children[1]
@ -237,8 +238,7 @@
end
-- remove this node from the tree, and move its children up a level
trimmed = node.path
trimmed = true
local numChildren = #node.children
for i = 1, numChildren do
local child = node.children[i]
@ -247,13 +247,33 @@
end
end
-- found the top, now remove any single-children ".." folders from here
local dotdot
local count = #tr.children
repeat
dotdot = false
for i = 1, count do
local node = tr.children[i]
if node.name == ".." and #node.children == 1 then
local child = node.children[1]
child.parent = node.parent
tr.children[i] = child
trimmed = true
dotdot = true
end
end
until not dotdot
-- if nodes were removed, adjust the paths on all remaining nodes
if trimmed then
local trimlen = #trimmed + 2
tree.traverse(tr, {
onnode = function(node)
node.path = node.path:sub(trimlen)
if node.parent.path then
node.path = path.join(node.parent.path, node.name)
else
node.path = node.name
end
end
})
}, false)
end
end

View File

@ -65,54 +65,6 @@
end
--
-- Return an iterator for the list of source code files contained by a project.
--
-- @param prj
-- The project to query.
-- @return
-- A source code file iterator, which returns file configuration objects.
-- These file configurations contain:
--
-- fullpath - the relative path from the project to the file
-- vpath - the file's virtual path, if specified, or fullpath if not
--
function project.eachfile(prj)
-- make sure I have the project, and not it's root configuration
prj = prj.project or prj
-- find *all* files referenced by the project, regardless of configuration,
-- and cache the list for future calls
if not prj.files then
local files = {}
for _, block in ipairs(prj.blocks) do
for _, file in ipairs(block.files) do
if not files[file] then
local fcfg = project.getfileconfig(prj, file)
-- add it both indexed for iteration and keyed for quick tests
table.insert(files, file)
files[file] = fcfg
end
end
end
prj.files = files
end
local files = prj.files
local i = 0
return function()
i = i + 1
if i <= #files then
local filename = files[i]
return files[filename]
end
end
end
--
-- Locate a project by name; case insensitive.
--
@ -305,14 +257,28 @@
--
function project.getsourcetree(prj)
-- make sure I have the project, and not it's root configuration
prj = prj.project or prj
-- check for a previously cached tree
if prj.sourcetree then
return prj.sourcetree
end
local tr = premake.tree.new(prj.name)
for fcfg in project.eachfile(prj) do
-- find *all* files referenced by the project, regardless of configuration
local files = {}
for _, block in ipairs(prj.blocks) do
for _, file in ipairs(block.files) do
files[file] = file
end
end
-- create a tree from the file list
local tr = premake.tree.new(prj.name)
for file in pairs(files) do
local fcfg = project.getfileconfig(prj, file)
-- The tree represents the logical source code tree to be displayed
-- in the IDE, not the physical organization of the file system. So
-- virtual paths are used when adding nodes.
@ -324,10 +290,10 @@
end
end)
-- Store additional path information for file (leaf) nodes
node.abspath = fcfg.abspath
node.relpath = fcfg.relpath
node.vpath = fcfg.vpath
-- Store full file configuration in file (leaf) nodes
for key, value in pairs(fcfg) do
node[key] = value
end
end
premake.tree.trimroot(tr)

View File

@ -202,6 +202,51 @@
end
--
-- A ".." folder containing a single subfolder should never appear
-- at the top of the source tree.
--
function suite.trimroot_removesDotDot_onTopLevelSiblings()
tree.add(tr, "../../tests/test_hello.c")
tree.add(tr, "../src/test.c")
tree.trimroot(tr)
prepare()
test.capture [[
tests
test_hello.c
src
test.c
]]
end
function suite.trimroot_removesDotDot_onTopLevel()
tree.add(tr, "../tests/test_hello.c")
tree.add(tr, "src/test.c")
tree.trimroot(tr)
prepare()
test.capture [[
tests
test_hello.c
src
test.c
]]
end
function suite.trimroot_removesDotDot_onMultipleNestings()
tree.add(tr, "../../../tests/test_hello.c")
tree.add(tr, "../src/test.c")
tree.trimroot(tr)
prepare()
test.capture [[
tests
test_hello.c
src
test.c
]]
end
--
-- When nodes are trimmed, the paths on the remaining nodes should
-- be updated to reflect the new hierarchy.
@ -211,6 +256,13 @@
tree.add(tr, "A/1")
tree.add(tr, "A/2")
tree.trimroot(tr)
prepare()
test.isequal("1", tr.children[1].path)
end
function suite.trimroot_updatesPaths_onDotDotRemoved()
tree.add(tr, "../../../tests/test_hello.c")
tree.add(tr, "../src/test.c")
tree.trimroot(tr)
test.isequal("tests", tr.children[1].path)
end

View File

@ -63,7 +63,6 @@
dofile("test_project.lua")
dofile("project/test_baking.lua")
dofile("project/test_eachconfig.lua")
dofile("project/test_eachfile.lua")
dofile("project/test_filtering.lua")
dofile("project/test_getconfig.lua")
dofile("project/test_hasconfig.lua")

View File

@ -1,84 +0,0 @@
--
-- tests/project/test_eachfile.lua
-- Automated test suite for the file iteration function.
-- Copyright (c) 2011-2012 Jason Perkins and the Premake project
--
T.project_eachfile = { }
local suite = T.project_eachfile
local project = premake5.project
--
-- Setup and teardown
--
local sln, prj
function suite.setup()
sln, prj = test.createsolution()
end
local function prepare(field)
if not field then
field = "relpath"
end
for file in project.eachfile(prj) do
_p(2, file[field])
end
end
--
-- Sanity check that all files are returned, with project relative paths.
--
function suite.listsAllFiles()
files { "hello.h", "hello.c" }
prepare()
test.capture [[
hello.h
hello.c
]]
end
--
-- Ensure that the virtual path field defaults to the real file path.
--
function suite.vpathsAreNil_onNoVpaths()
files { "hello.h", "hello.c" }
prepare("vpath")
test.capture [[
hello.h
hello.c
]]
end
--
-- If a virtual path is specified, the vpath field should be set.
--
function suite.vpathSet_onVpath()
files { "hello.h", "hello.c" }
vpaths { Headers = "**.h" }
prepare("vpath")
test.capture [[
Headers/hello.h
hello.c
]]
end
--
-- A file listed in a configuration should be included in the list.
--
function suite.includesFile_setInConfiguration()
files { "hello.h" }
configuration { "Debug" }
files { "hello.c" }
prepare()
test.capture [[
hello.h
hello.c
]]
end