1---
2-- workspace.lua
3-- Work with the list of workspaces loaded from the script.
4-- Copyright (c) 2002-2015 Jason Perkins and the Premake project
5---
6
7	local p = premake
8	p.workspace = p.api.container("workspace", p.global)
9
10	local workspace = p.workspace
11
12
13---
14-- Switch this container's name from "solution" to "workspace"
15--
16-- We changed these names on 30 Jul 2015. While it might be nice to leave
17-- `solution()` around for Visual Studio folks and everyone still used to the
18-- old system, it would be good to eventually deprecate and remove all of
19-- the other, more internal uses of "solution" and "sln". Probably including
20-- all uses of container class aliases, since we probably aren't going to
21-- need those again (right?).
22---
23
24	p.solution = workspace
25	workspace.alias = "solution"
26
27	p.alias(_G, "workspace", "solution")
28	p.alias(_G, "externalworkspace", "externalsolution")
29
30
31
32---
33-- Create a new workspace container instance.
34---
35
36	function workspace.new(name)
37		local wks = p.container.new(workspace, name)
38		return wks
39	end
40
41
42
43--
44-- Iterate over the configurations of a workspace.
45--
46-- @return
47--    A configuration iteration function.
48--
49
50	function workspace.eachconfig(self)
51		self = p.oven.bakeWorkspace(self)
52
53		local i = 0
54		return function()
55			i = i + 1
56			if i > #self.configs then
57				return nil
58			else
59				return self.configs[i]
60			end
61		end
62	end
63
64
65--
66-- Iterate over the projects of a workspace.
67--
68-- @return
69--    An iterator function, returning project configurations.
70--
71
72	function workspace.eachproject(self)
73		local i = 0
74		return function ()
75			i = i + 1
76			if i <= #self.projects then
77				return p.workspace.getproject(self, i)
78			end
79		end
80	end
81
82
83--
84-- Locate a project by name, case insensitive.
85--
86-- @param name
87--    The name of the projec to find.
88-- @return
89--    The project object, or nil if a matching project could not be found.
90--
91
92	function workspace.findproject(self, name)
93		name = name:lower()
94		for _, prj in ipairs(self.projects) do
95			if name == prj.name:lower() then
96				return prj
97			end
98		end
99		return nil
100	end
101
102
103--
104-- Retrieve the tree of project groups.
105--
106-- @return
107--    The tree of project groups defined for the workspace.
108--
109
110	function workspace.grouptree(self)
111		-- check for a previously cached tree
112		if self.grouptree then
113			return self.grouptree
114		end
115
116		-- build the tree of groups
117
118		local tr = p.tree.new()
119		for prj in workspace.eachproject(self) do
120			local prjpath = path.join(prj.group, prj.name)
121			local node = p.tree.add(tr, prjpath)
122			node.project = prj
123		end
124
125		-- assign UUIDs to each node in the tree
126		p.tree.traverse(tr, {
127			onbranch = function(node)
128				node.uuid = os.uuid("group:" .. node.path)
129			end
130		})
131
132		self.grouptree = tr
133		return tr
134	end
135
136
137--
138-- Retrieve the project configuration at a particular index.
139--
140-- @param idx
141--    An index into the array of projects.
142-- @return
143--    The project configuration at the given index.
144--
145
146	function workspace.getproject(self, idx)
147		self = p.oven.bakeWorkspace(self)
148		return self.projects[idx]
149	end
150
151
152
153---
154-- Determines if the workspace contains a project that meets certain criteria.
155--
156-- @param func
157--    A test function. Receives a project as its only argument and returns a
158--    boolean indicating whether it meets to matching criteria.
159-- @return
160--    True if the test function returned true.
161---
162
163	function workspace.hasProject(self, func)
164		return p.container.hasChild(self, p.project, func)
165	end
166
167
168--
169-- Return the relative path from the solution to the specified file.
170--
171-- @param self
172--    The workspace object to query.
173-- @param filename
174--    The file path, or an array of file paths, to convert.
175-- @return
176--    The relative path, or array of paths, from the workspace to the file.
177--
178
179	function workspace.getrelative(self, filename)
180		if type(filename) == "table" then
181			local result = {}
182			for i, name in ipairs(filename) do
183				if name and #name > 0 then
184					table.insert(result, workspace.getrelative(self, name))
185				end
186			end
187			return result
188		else
189			if filename then
190				return path.getrelative(self.location, filename)
191			end
192		end
193	end
194