alibuild 1.17.19__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. alibuild-1.17.19.data/scripts/aliBuild +137 -0
  2. alibuild-1.17.19.data/scripts/aliDeps +7 -0
  3. alibuild-1.17.19.data/scripts/aliDoctor +7 -0
  4. alibuild-1.17.19.data/scripts/alienv +344 -0
  5. alibuild-1.17.19.data/scripts/pb +7 -0
  6. alibuild-1.17.19.dist-info/METADATA +78 -0
  7. alibuild-1.17.19.dist-info/RECORD +74 -0
  8. alibuild-1.17.19.dist-info/WHEEL +5 -0
  9. alibuild-1.17.19.dist-info/licenses/LICENSE.md +674 -0
  10. alibuild-1.17.19.dist-info/top_level.txt +5 -0
  11. alibuild_helpers/__init__.py +21 -0
  12. alibuild_helpers/_version.py +21 -0
  13. alibuild_helpers/analytics.py +120 -0
  14. alibuild_helpers/args.py +493 -0
  15. alibuild_helpers/build.py +1209 -0
  16. alibuild_helpers/build_template.sh +314 -0
  17. alibuild_helpers/clean.py +83 -0
  18. alibuild_helpers/cmd.py +154 -0
  19. alibuild_helpers/deps.py +116 -0
  20. alibuild_helpers/doctor.py +195 -0
  21. alibuild_helpers/git.py +104 -0
  22. alibuild_helpers/init.py +103 -0
  23. alibuild_helpers/log.py +132 -0
  24. alibuild_helpers/scm.py +31 -0
  25. alibuild_helpers/sl.py +62 -0
  26. alibuild_helpers/sync.py +693 -0
  27. alibuild_helpers/templating_plugin.py +18 -0
  28. alibuild_helpers/utilities.py +662 -0
  29. alibuild_helpers/workarea.py +179 -0
  30. debian/changelog +11 -0
  31. debian/compat +1 -0
  32. debian/control +14 -0
  33. debian/copyright +10 -0
  34. debian/files +1 -0
  35. debian/rules +7 -0
  36. docs/README.md +1 -0
  37. docs/SUPPORT +3 -0
  38. docs/docs/alice_logo.png +0 -0
  39. docs/docs/deps.png +0 -0
  40. docs/docs/index.md +75 -0
  41. docs/docs/quick.md +89 -0
  42. docs/docs/reference.md +430 -0
  43. docs/docs/stylesheets/extra.css +9 -0
  44. docs/docs/troubleshooting.md +346 -0
  45. docs/docs/user.md +413 -0
  46. docs/mkdocs.yml +37 -0
  47. templates/alibuild_to_please.jnj +63 -0
  48. tests/test_analytics.py +42 -0
  49. tests/test_args.py +119 -0
  50. tests/test_build.py +426 -0
  51. tests/test_clean.py +154 -0
  52. tests/test_cmd.py +73 -0
  53. tests/test_deps.py +79 -0
  54. tests/test_doctor.py +128 -0
  55. tests/test_git.py +48 -0
  56. tests/test_hashing.py +67 -0
  57. tests/test_init.py +103 -0
  58. tests/test_log.py +50 -0
  59. tests/test_packagelist.py +235 -0
  60. tests/test_parseRecipe.py +132 -0
  61. tests/test_sync.py +332 -0
  62. tests/test_utilities.py +383 -0
  63. tests/test_workarea.py +101 -0
  64. tests/testdist/broken1.sh +1 -0
  65. tests/testdist/broken2.sh +1 -0
  66. tests/testdist/broken3.sh +3 -0
  67. tests/testdist/broken4.sh +2 -0
  68. tests/testdist/broken5.sh +2 -0
  69. tests/testdist/broken6.sh +2 -0
  70. tests/testdist/broken7.sh +5 -0
  71. tests/testdist/clobber-initdotsh.sh +4 -0
  72. tests/testdist/defaults-o2.sh +10 -0
  73. tests/testdist/delete-etc.sh +4 -0
  74. tests/testdist/tracking-env.sh +6 -0
@@ -0,0 +1,383 @@
1
+ # vim: set fileencoding=utf-8 :
2
+
3
+ import unittest
4
+
5
+ # Assuming you are using the mock library to ... mock things
6
+ from unittest.mock import patch
7
+
8
+ from alibuild_helpers.utilities import doDetectArch, filterByArchitectureDefaults, disabledByArchitectureDefaults, getPkgDirs
9
+ from alibuild_helpers.utilities import Hasher
10
+ from alibuild_helpers.utilities import asList
11
+ from alibuild_helpers.utilities import prunePaths
12
+ from alibuild_helpers.utilities import resolve_version
13
+ from alibuild_helpers.utilities import topological_sort
14
+ from alibuild_helpers.utilities import resolveFilename, resolveDefaultsFilename
15
+ import alibuild_helpers
16
+ import os
17
+ import string
18
+
19
+ UBUNTU_1510_OS_RELEASE = """
20
+ NAME="Ubuntu"
21
+ VERSION="15.10 (Wily Werewolf)"
22
+ ID=ubuntu
23
+ ID_LIKE=debian
24
+ PRETTY_NAME="Ubuntu 15.10"
25
+ VERSION_ID="15.10"
26
+ HOME_URL="http://www.ubuntu.com/"
27
+ SUPPORT_URL="http://help.ubuntu.com/"
28
+ BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
29
+ """
30
+
31
+ LINUX_MINT_OS_RELEASE = """
32
+ NAME="Ubuntu"
33
+ VERSION="14.04.4 LTS, Trusty Tahr"
34
+ ID=ubuntu
35
+ ID_LIKE=debian
36
+ PRETTY_NAME="Ubuntu 14.04.4 LTS"
37
+ VERSION_ID="14.04"
38
+ HOME_URL="http://www.ubuntu.com/"
39
+ SUPPORT_URL="http://help.ubuntu.com/"
40
+ BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
41
+ """
42
+
43
+ UBUNTU_1404_OS_RELEASE = """
44
+ NAME="Ubuntu"
45
+ VERSION="14.04.3 LTS, Trusty Tahr"
46
+ ID=ubuntu
47
+ ID_LIKE=debian
48
+ PRETTY_NAME="Ubuntu 14.04.3 LTS"
49
+ VERSION_ID="14.04"
50
+ HOME_URL="http://www.ubuntu.com/"
51
+ SUPPORT_URL="http://help.ubuntu.com/"
52
+ BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
53
+ """
54
+
55
+ UBUNTU_1604_OS_RELEASE = """
56
+ NAME="Ubuntu"
57
+ VERSION="16.04 LTS (Xenial Xerus)"
58
+ ID=ubuntu
59
+ ID_LIKE=debian
60
+ PRETTY_NAME="Ubuntu 16.04 LTS"
61
+ VERSION_ID="16.04"
62
+ HOME_URL="http://www.ubuntu.com/"
63
+ SUPPORT_URL="http://help.ubuntu.com/"
64
+ BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
65
+ UBUNTU_CODENAME=xenial
66
+ """
67
+
68
+ UBUNTU_1804_OS_RELEASE = """
69
+ NAME="Ubuntu"
70
+ VERSION="18.04.4 LTS (Bionic Beaver)"
71
+ ID=ubuntu
72
+ ID_LIKE=debian
73
+ PRETTY_NAME="Ubuntu 18.04.4 LTS"
74
+ VERSION_ID="18.04"
75
+ HOME_URL="https://www.ubuntu.com/"
76
+ SUPPORT_URL="https://help.ubuntu.com/"
77
+ BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
78
+ PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
79
+ VERSION_CODENAME=bionic
80
+ UBUNTU_CODENAME=bionic
81
+ """
82
+
83
+ DEBIAN_7_OS_RELEASE = """
84
+ PRETTY_NAME="Debian GNU/Linux 7 (wheezy)"
85
+ NAME="Debian GNU/Linux"
86
+ VERSION_ID="7"
87
+ VERSION="7 (wheezy)"
88
+ ID=debian
89
+ ANSI_COLOR="1;31"
90
+ HOME_URL="http://www.debian.org/"
91
+ SUPPORT_URL="http://www.debian.org/support/"
92
+ BUG_REPORT_URL="http://bugs.debian.org/"
93
+ """
94
+
95
+ DEBIAN_8_OS_RELEASE = """
96
+ PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
97
+ NAME="Debian GNU/Linux"
98
+ VERSION_ID="8"
99
+ VERSION="8 (jessie)"
100
+ ID=debian
101
+ HOME_URL="http://www.debian.org/"
102
+ SUPPORT_URL="http://www.debian.org/support"
103
+ BUG_REPORT_URL="https://bugs.debian.org/"
104
+ """
105
+
106
+ SABAYON2_OS_RELEASE = """
107
+ NAME=Sabayon
108
+ ID=sabayon
109
+ PRETTY_NAME="Sabayon/Linux"
110
+ ANSI_COLOR="1;32"
111
+ HOME_URL="http://www.sabayon.org/"
112
+ SUPPORT_URL="http://forum.sabayon.org/"
113
+ BUG_REPORT_URL="https://bugs.sabayon.org/"
114
+ """
115
+
116
+ architecturePayloads = [
117
+ ['osx_x86-64', False, [], ('','',''), 'Darwin', 'x86-64'],
118
+ ['osx_arm64', False, [], ('','',''), 'Darwin', 'arm64'],
119
+ ['slc5_x86-64', False, [], ('redhat', '5.XX', 'Boron'), 'Linux', 'x86-64'],
120
+ ['slc6_x86-64', False, [], ('centos', '6.X', 'Carbon'), 'Linux', 'x86-64'],
121
+ ['slc7_x86-64', False, [], ('centos', '7.X', 'Ptor'), 'Linux', 'x86-64'],
122
+ ['ubuntu1804_x86-64', True, UBUNTU_1804_OS_RELEASE.split("\n"), ('Ubuntu', '18.04', 'bionic'), 'Linux', 'x86-64'],
123
+ ['ubuntu1604_x86-64', True, UBUNTU_1604_OS_RELEASE.split("\n"), ('Ubuntu', '16.04', 'xenial'), 'Linux', 'x86-64'],
124
+ ['ubuntu1510_x86-64', False, [], ('Ubuntu', '15.10', 'wily'), 'Linux', 'x86-64'],
125
+ ['ubuntu1510_x86-64', True, UBUNTU_1510_OS_RELEASE.split("\n"), ('Ubuntu', '15.10', 'wily'), 'Linux', 'x86-64'],
126
+ ['ubuntu1510_x86-64', True, UBUNTU_1510_OS_RELEASE.split("\n"), ('', '', ''), 'Linux', 'x86-64'], # ANACONDA case
127
+ ['ubuntu1404_x86-64', True, UBUNTU_1404_OS_RELEASE.split("\n"), ('Ubuntu', '14.04', 'trusty'), 'Linux', 'x86-64'],
128
+ ['ubuntu1404_x86-64', True, UBUNTU_1404_OS_RELEASE.split("\n"), ('', '', ''), 'Linux', 'x86-64'],
129
+ ['ubuntu1404_x86-64', True, LINUX_MINT_OS_RELEASE.split("\n"), ('LinuxMint', '17.3', 'rosa'), 'Linux', 'x86-64'], # LinuxMint
130
+ ['ubuntu1204_x86-64', True, DEBIAN_7_OS_RELEASE.split("\n"), ('Debian', '7', 'wheezy'), 'Linux', 'x86-64'],
131
+ ['ubuntu1404_x86-64', True, DEBIAN_8_OS_RELEASE.split("\n"), ('Debian', '8', 'jessie'), 'Linux', 'x86-64'],
132
+ ['sabayon2_x86-64', True, SABAYON2_OS_RELEASE.split("\n"), ('gentoo', '2.2', ''), 'Linux', 'x86_64']
133
+ ]
134
+
135
+ macOSArchitecturePayloads = [
136
+ ['osx_x86-64', False, [], ('','',''), 'Darwin', 'x86_64'],
137
+ ['osx_arm64', False, [], ('','',''), 'Darwin', 'arm64'],
138
+ ]
139
+
140
+ class TestUtilities(unittest.TestCase):
141
+ def test_osx(self) -> None:
142
+ for payload in architecturePayloads:
143
+ result, hasOsRelease, osReleaseLines, platformTuple, platformSystem, platformProcessor = payload
144
+ self.assertEqual(result, doDetectArch(hasOsRelease, osReleaseLines, platformTuple, platformSystem, platformProcessor))
145
+ # Test by mocking platform.processor
146
+ def test_osx_mock(self) -> None:
147
+ for payload in macOSArchitecturePayloads:
148
+ result, hasOsRelease, osReleaseLines, platformTuple, platformSystem, platformProcessor = payload
149
+ with patch('platform.machine', return_value=platformProcessor):
150
+ platformProcessor = None
151
+ self.assertEqual(result, doDetectArch(hasOsRelease, osReleaseLines, platformTuple, platformSystem, None))
152
+ def test_Hasher(self) -> None:
153
+ h = Hasher()
154
+ h("foo")
155
+ self.assertEqual("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33", h.hexdigest())
156
+ h("")
157
+ self.assertEqual("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33", h.hexdigest())
158
+ self.assertRaises(AttributeError, h, 1)
159
+ h("bar")
160
+ self.assertEqual("8843d7f92416211de9ebb963ff4ce28125932878", h.hexdigest())
161
+
162
+ def test_UTF8_Hasher(self) -> None:
163
+ h1 = Hasher()
164
+ h2 = Hasher()
165
+ h3 = Hasher()
166
+ h1(u'\ua000')
167
+ h2(u'\ua001')
168
+ h3(b'foo')
169
+ self.assertEqual(h1.hexdigest(), "2af8e41129115eb231a0af76ec5465d3a9184fc4")
170
+ self.assertEqual(h2.hexdigest(), "1619bcdbeff6828138ad9b6e43cc17e856457603")
171
+ self.assertEqual(h3.hexdigest(), "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
172
+ self.assertNotEqual(h1.hexdigest(), h2.hexdigest())
173
+
174
+ def test_asList(self) -> None:
175
+ self.assertEqual(asList("a"), ["a"])
176
+ self.assertEqual(asList(["a"]), ["a"])
177
+ self.assertEqual(asList(None), [None])
178
+
179
+ def test_filterByArchitecture(self) -> None:
180
+ self.assertEqual(["AliRoot"], list(filterByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot"])))
181
+ self.assertEqual([], list(filterByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:(?!osx)"])))
182
+ self.assertEqual(["GCC"], list(filterByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:(?!osx)", "GCC"])))
183
+ self.assertEqual(["AliRoot", "GCC"], list(filterByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:(?!slc6)", "GCC"])))
184
+ self.assertEqual(["GCC"], list(filterByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:slc6", "GCC:osx"])))
185
+ self.assertEqual([], list(filterByArchitectureDefaults("osx_x86-64", "ali", [])))
186
+ self.assertEqual(["GCC"], list(filterByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:slc6", "GCC:defaults=ali"])))
187
+ self.assertEqual([], list(filterByArchitectureDefaults("osx_x86-64", "o2", ["AliRoot:slc6", "GCC:defaults=ali"])))
188
+
189
+ def test_disabledByArchitecture(self) -> None:
190
+ self.assertEqual([], list(disabledByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot"])))
191
+ self.assertEqual(["AliRoot"], list(disabledByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:(?!osx)"])))
192
+ self.assertEqual(["AliRoot"], list(disabledByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:(?!osx)", "GCC"])))
193
+ self.assertEqual([], list(disabledByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:(?!slc6)", "GCC"])))
194
+ self.assertEqual(["AliRoot"], list(disabledByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:slc6", "GCC:osx"])))
195
+ self.assertEqual([], list(disabledByArchitectureDefaults("osx_x86-64", "ali", [])))
196
+ self.assertEqual(["AliRoot"], list(disabledByArchitectureDefaults("osx_x86-64", "ali", ["AliRoot:slc6", "GCC:defaults=ali"])))
197
+ self.assertEqual(["AliRoot", "GCC"], list(disabledByArchitectureDefaults("osx_x86-64", "o2", ["AliRoot:slc6", "GCC:defaults=ali"])))
198
+
199
+ def test_prunePaths(self) -> None:
200
+ fake_env = {
201
+ "PATH": "/sw/bin:/usr/local/bin",
202
+ "LD_LIBRARY_PATH": "/sw/lib",
203
+ "DYLD_LIBRARY_PATH": "/sw/lib",
204
+ "ALIBUILD_VERSION": "v1.0.0",
205
+ "ROOT_VERSION": "v1.0.0"
206
+ }
207
+ fake_env_copy = {
208
+ "PATH": "/sw/bin:/usr/local/bin",
209
+ "LD_LIBRARY_PATH": "/sw/lib",
210
+ "DYLD_LIBRARY_PATH": "/sw/lib",
211
+ "ALIBUILD_VERSION": "v1.0.0",
212
+ "ROOT_VERSION": "v1.0.0"
213
+ }
214
+ with patch.object(os, "environ", fake_env):
215
+ prunePaths("/sw")
216
+ self.assertTrue("ROOT_VERSION" not in fake_env)
217
+ self.assertTrue(fake_env["PATH"] == "/usr/local/bin")
218
+ self.assertTrue(fake_env["LD_LIBRARY_PATH"] == "")
219
+ self.assertTrue(fake_env["DYLD_LIBRARY_PATH"] == "")
220
+ self.assertTrue(fake_env["ALIBUILD_VERSION"] == "v1.0.0")
221
+
222
+ with patch.object(os, "environ", fake_env_copy):
223
+ prunePaths("/foo")
224
+ self.assertTrue("ROOT_VERSION" not in fake_env_copy)
225
+ self.assertTrue(fake_env_copy["PATH"] == "/sw/bin:/usr/local/bin")
226
+ self.assertTrue(fake_env_copy["LD_LIBRARY_PATH"] == "/sw/lib")
227
+ self.assertTrue(fake_env_copy["DYLD_LIBRARY_PATH"] == "/sw/lib")
228
+ self.assertTrue(fake_env_copy["ALIBUILD_VERSION"] == "v1.0.0")
229
+
230
+ def test_resolver(self) -> None:
231
+ spec = {"package": "test-pkg",
232
+ "version": "%(tag_basename)s",
233
+ "tag": "foo/bar",
234
+ "commit_hash": "000000000000000000000000000"
235
+ }
236
+ self.assertTrue(resolve_version(spec, "release", "stream/v1", "v1"), "bar")
237
+ spec["version"] = "%(branch_stream)s"
238
+ self.assertTrue(resolve_version(spec, "release", "stream/v1", "v1"), "v1")
239
+ spec["version"] = "%(defaults_upper)s"
240
+ self.assertTrue(resolve_version(spec, "o2", "stream/v1", "v1"), "O2")
241
+ spec["version"] = "NO%(defaults_upper)s"
242
+ self.assertTrue(resolve_version(spec, "release", "stream/v1", "v1"), "NO")
243
+
244
+ def test_get_pkg_dirs(self) -> None:
245
+ self.assertEqual(getPkgDirs("alidist"), ["alidist/"])
246
+ with patch.object(os, "environ", {"BITS_PATH": ""}):
247
+ self.assertEqual(getPkgDirs("alidist"), ["alidist/"])
248
+ with patch.object(os, "environ", {"BITS_PATH": "/foo/bar"}):
249
+ self.assertEqual(getPkgDirs("alidist"), ["/foo/bar", "alidist/"])
250
+ with patch.object(os, "environ", {"BITS_PATH": "/foo/bar:"}):
251
+ self.assertEqual(getPkgDirs("alidist"), ["/foo/bar", "alidist/"])
252
+ with patch.object(os, "environ", {"BITS_PATH": "foo/bar:"}):
253
+ self.assertEqual(getPkgDirs("alidist"), ["alidist/foo/bar", "alidist/"])
254
+ with patch.object(os, "environ", {"BITS_PATH": "foo/bar:/bar"}):
255
+ self.assertEqual(getPkgDirs("alidist"), ["alidist/foo/bar", "/bar", "alidist/"])
256
+
257
+ def test_resolveDefaults(self) -> None:
258
+ def fake_exists(n):
259
+ return {"alidist/defaults-release.sh": True,
260
+ "/foo/defaults-o2.sh": True,
261
+ "/bar/defaults-o2.sh": True,
262
+ "alidist/bar/defaults-o2.sh": True
263
+ }.get(n, False)
264
+
265
+ with patch.object(os.path, "exists", fake_exists):
266
+ self.assertEqual(resolveDefaultsFilename("release", "alidist"), "alidist/defaults-release.sh")
267
+ self.assertEqual(resolveDefaultsFilename("release", "alidost"), None)
268
+ self.assertEqual(resolveDefaultsFilename("o2", "alidist"), None)
269
+ with patch.object(os.path, "exists", fake_exists), \
270
+ patch.object(os, "environ", {"BITS_PATH": "/foo"}):
271
+ self.assertEqual(resolveDefaultsFilename("release", "alidist"), "alidist/defaults-release.sh")
272
+ self.assertEqual(resolveDefaultsFilename("release", "alidost"), None)
273
+ self.assertEqual(resolveDefaultsFilename("o2", "alidist"), "/foo/defaults-o2.sh")
274
+ with patch.object(os.path, "exists", fake_exists), \
275
+ patch.object(os, "environ", {"BITS_PATH": "/bar:/foo"}):
276
+ self.assertEqual(resolveDefaultsFilename("release", "alidist"), "alidist/defaults-release.sh")
277
+ self.assertEqual(resolveDefaultsFilename("release", "alidost"), None)
278
+ self.assertEqual(resolveDefaultsFilename("o2", "alidist"), "/bar/defaults-o2.sh")
279
+ with patch.object(os.path, "exists", fake_exists), \
280
+ patch.object(os, "environ", {"BITS_PATH": "bar:/foo"}):
281
+ self.assertEqual(resolveDefaultsFilename("release", "alidist"), "alidist/defaults-release.sh")
282
+ self.assertEqual(resolveDefaultsFilename("release", "alidost"), None)
283
+ self.assertEqual(resolveDefaultsFilename("o2", "alidist"), "alidist/bar/defaults-o2.sh")
284
+
285
+ def test_resolveFilename(self) -> None:
286
+ def fake_exists(n):
287
+ return {
288
+ "alidist/defaults-release.sh": True,
289
+ "alidist/zlib.sh": True,
290
+ "/foo/defaults-o2.sh": True,
291
+ "/bar/defaults-o2.sh": True,
292
+ "alidist/bar/defaults-o2.sh": True,
293
+ "/bar/python.sh": True
294
+ }.get(n, False)
295
+
296
+ def fake_abspath(n):
297
+ return os.path.join("/fake/", n)
298
+
299
+ with patch.object(os.path, "exists", fake_exists), \
300
+ patch.object(os.path, "abspath", fake_abspath):
301
+ self.assertEqual(resolveFilename({}, "zlib", "alidist"), ("alidist/zlib.sh", "/fake/alidist/"))
302
+
303
+ with patch.object(os.path, "exists", fake_exists), \
304
+ patch.object(os.path, "abspath", fake_abspath), \
305
+ patch.object(os, "environ", {"BITS_PATH": "/foo"}):
306
+ self.assertEqual(resolveFilename({}, "zlib", "alidist"), ("alidist/zlib.sh", "/fake/alidist/"))
307
+
308
+ with patch.object(os.path, "exists", fake_exists), \
309
+ patch.object(os.path, "abspath", fake_abspath), \
310
+ patch.object(os, "environ", {"BITS_PATH": "/bar:/foo"}):
311
+ self.assertEqual(resolveFilename({}, "zlib", "alidist"), ("alidist/zlib.sh", "/fake/alidist/"))
312
+ self.assertEqual(resolveFilename({}, "zlib", "alidost"), (None, None))
313
+ self.assertEqual(resolveFilename({}, "python", "alidist"), ("/bar/python.sh", "/bar"))
314
+
315
+
316
+ class TestTopologicalSort(unittest.TestCase):
317
+ """Check that various properties of topological sorting hold."""
318
+
319
+ def test_resolve_dependency_chain(self) -> None:
320
+ """Test that topological sorting correctly sorts packages in a dependency chain."""
321
+ # Topological sorting only takes "requires" into account, since the
322
+ # build/runtime distinction does not matter for resolving build order.
323
+ self.assertEqual(["c", "b", "a"], list(topological_sort({
324
+ "a": {"package": "a", "requires": ["b"]},
325
+ "b": {"package": "b", "requires": ["c"]},
326
+ "c": {"package": "c", "requires": []},
327
+ })))
328
+
329
+ def test_diamond_dependency(self) -> None:
330
+ """Test that a diamond dependency relationship is handled correctly."""
331
+ self.assertEqual(["base", "mid2", "mid1", "top"], list(topological_sort({
332
+ "top": {"package": "top", "requires": ["mid1", "mid2"]},
333
+ # Add a mid1 -> mid2 cross-dependency to make the order deterministic.
334
+ "mid1": {"package": "mid1", "requires": ["base", "mid2"]},
335
+ "mid2": {"package": "mid2", "requires": ["base"]},
336
+ "base": {"package": "base", "requires": []},
337
+ })))
338
+
339
+ def test_dont_drop_packages(self) -> None:
340
+ """Check that topological sorting doesn't drop any packages."""
341
+ # For half the packages, depend on the first package, to make this a
342
+ # little more than trivial.
343
+ specs = {pkg: {"package": pkg, "requires": [] if pkg < "m" else ["a"]}
344
+ for pkg in string.ascii_lowercase}
345
+ self.assertEqual(frozenset(specs.keys()),
346
+ frozenset(topological_sort(specs)))
347
+
348
+ def test_cycle(self) -> None:
349
+ """Test that dependency cycles are detected and reported."""
350
+ specs = {
351
+ "A": {"package": "A", "requires": ["B"]},
352
+ "B": {"package": "B", "requires": ["C"]},
353
+ "C": {"package": "C", "requires": ["D"]},
354
+ "D": {"package": "D", "requires": ["A"]}
355
+ }
356
+ with patch.object(alibuild_helpers.log, 'error') as mock_error:
357
+ with self.assertRaises(SystemExit) as cm:
358
+ list(topological_sort(specs))
359
+ self.assertEqual(cm.exception.code, 1)
360
+ mock_error.assert_called_once_with("%s", "Dependency cycle detected: A -> B -> C -> D -> A")
361
+
362
+ def test_empty_set(self) -> None:
363
+ """Test that an empty set of packages is handled correctly."""
364
+ self.assertEqual([], list(topological_sort({})))
365
+
366
+ def test_single_package(self) -> None:
367
+ """Test that a single package with no dependencies is handled correctly."""
368
+ self.assertEqual(["A"], list(topological_sort({
369
+ "A": {"package": "A", "requires": []}
370
+ })))
371
+
372
+ def test_independent_packages(self) -> None:
373
+ """Test that packages with no dependencies between them are handled correctly."""
374
+ result = list(topological_sort({
375
+ "A": {"package": "A", "requires": []},
376
+ "B": {"package": "B", "requires": []},
377
+ "C": {"package": "C", "requires": []}
378
+ }))
379
+ self.assertEqual(set(["A", "B", "C"]), set(result))
380
+ self.assertEqual(3, len(result))
381
+
382
+ if __name__ == '__main__':
383
+ unittest.main()
tests/test_workarea.py ADDED
@@ -0,0 +1,101 @@
1
+ from os import getcwd
2
+ import unittest
3
+ from unittest.mock import patch, MagicMock # In Python 3, mock is built-in
4
+ from collections import OrderedDict
5
+
6
+ from alibuild_helpers.workarea import updateReferenceRepoSpec
7
+ from alibuild_helpers.git import Git
8
+
9
+
10
+ MOCK_SPEC = OrderedDict((
11
+ ("package", "AliRoot"),
12
+ ("source", "https://github.com/alisw/AliRoot"),
13
+ ("scm", Git()),
14
+ ("is_devel_pkg", False),
15
+ ))
16
+
17
+
18
+ @patch("alibuild_helpers.workarea.debug", new=MagicMock())
19
+ @patch("alibuild_helpers.git.clone_speedup_options",
20
+ new=MagicMock(return_value=["--filter=blob:none"]))
21
+ class WorkareaTestCase(unittest.TestCase):
22
+
23
+ @patch("os.path.exists")
24
+ @patch("os.makedirs")
25
+ @patch("alibuild_helpers.git")
26
+ @patch("alibuild_helpers.workarea.is_writeable", new=MagicMock(return_value=False))
27
+ def test_reference_sources_reused(self, mock_git, mock_makedirs, mock_exists):
28
+ """Check mirrors are reused when pre-existing, but not writable.
29
+
30
+ In this case, make sure nothing is fetched, even when requested.
31
+ """
32
+ mock_exists.return_value = True
33
+ spec = MOCK_SPEC.copy()
34
+ updateReferenceRepoSpec(referenceSources="sw/MIRROR", p="AliRoot",
35
+ spec=spec, fetch=True)
36
+ mock_exists.assert_called_with("%s/sw/MIRROR/aliroot" % getcwd())
37
+ mock_makedirs.assert_called_with("%s/sw/MIRROR" % getcwd(), exist_ok=True)
38
+ mock_git.assert_not_called()
39
+ self.assertEqual(spec.get("reference"), "%s/sw/MIRROR/aliroot" % getcwd())
40
+
41
+ @patch("os.path.exists")
42
+ @patch("os.makedirs")
43
+ @patch("codecs.open")
44
+ @patch("alibuild_helpers.git.git")
45
+ @patch("alibuild_helpers.workarea.is_writeable", new=MagicMock(return_value=True))
46
+ def test_reference_sources_updated(self, mock_git, mock_open, mock_makedirs, mock_exists):
47
+ """Check mirrors are updated when possible and git output is logged."""
48
+ mock_exists.return_value = True
49
+ mock_git.return_value = 0, "sentinel output"
50
+ mock_open.return_value = MagicMock(
51
+ __enter__=lambda *args, **kw: MagicMock(
52
+ write=lambda output: self.assertEqual(output, "sentinel output")))
53
+ spec = MOCK_SPEC.copy()
54
+ updateReferenceRepoSpec(referenceSources="sw/MIRROR", p="AliRoot",
55
+ spec=spec, fetch=True)
56
+ mock_exists.assert_called_with("%s/sw/MIRROR/aliroot" % getcwd())
57
+ mock_exists.assert_has_calls([])
58
+ mock_makedirs.assert_called_with("%s/sw/MIRROR" % getcwd(), exist_ok=True)
59
+ mock_git.assert_called_once_with([
60
+ "fetch", "-f", "--filter=blob:none", spec["source"], "+refs/tags/*:refs/tags/*", "+refs/heads/*:refs/heads/*",
61
+ ], directory="%s/sw/MIRROR/aliroot" % getcwd(), check=False, prompt=True)
62
+ self.assertEqual(spec.get("reference"), "%s/sw/MIRROR/aliroot" % getcwd())
63
+
64
+ @patch("os.path.exists")
65
+ @patch("os.makedirs")
66
+ @patch("alibuild_helpers.git")
67
+ @patch("alibuild_helpers.workarea.is_writeable", new=MagicMock(return_value=False))
68
+ def test_reference_sources_not_writable(self, mock_git, mock_makedirs, mock_exists):
69
+ """Check nothing is fetched when mirror directory isn't writable."""
70
+ mock_exists.side_effect = lambda path: not path.endswith("/aliroot")
71
+ spec = MOCK_SPEC.copy()
72
+ updateReferenceRepoSpec(referenceSources="sw/MIRROR", p="AliRoot",
73
+ spec=spec, fetch=True)
74
+ mock_exists.assert_called_with("%s/sw/MIRROR/aliroot" % getcwd())
75
+ mock_makedirs.assert_called_with("%s/sw/MIRROR" % getcwd(), exist_ok=True)
76
+ mock_git.assert_not_called()
77
+ self.assertNotIn("reference", spec,
78
+ "should delete spec['reference'], as no mirror exists")
79
+
80
+ @patch("os.path.exists")
81
+ @patch("os.makedirs")
82
+ @patch("alibuild_helpers.git.git")
83
+ @patch("alibuild_helpers.workarea.is_writeable", new=MagicMock(return_value=True))
84
+ def test_reference_sources_created(self, mock_git, mock_makedirs, mock_exists):
85
+ """Check the mirror directory is created when possible."""
86
+ mock_git.return_value = 0, ""
87
+ mock_exists.side_effect = lambda path: not path.endswith("/aliroot")
88
+ spec = MOCK_SPEC.copy()
89
+ updateReferenceRepoSpec(referenceSources="sw/MIRROR", p="AliRoot",
90
+ spec=spec, fetch=True)
91
+ mock_exists.assert_called_with("%s/sw/MIRROR/aliroot" % getcwd())
92
+ mock_makedirs.assert_called_with("%s/sw/MIRROR" % getcwd(), exist_ok=True)
93
+ mock_git.assert_called_once_with([
94
+ "clone", "--bare", spec["source"],
95
+ "%s/sw/MIRROR/aliroot" % getcwd(), "--filter=blob:none",
96
+ ], directory=".", check=False, prompt=True)
97
+ self.assertEqual(spec.get("reference"), "%s/sw/MIRROR/aliroot" % getcwd())
98
+
99
+
100
+ if __name__ == '__main__':
101
+ unittest.main()
@@ -0,0 +1 @@
1
+ broken
@@ -0,0 +1 @@
1
+ ---
@@ -0,0 +1,3 @@
1
+ gfooo:
2
+ - :
3
+ ---
@@ -0,0 +1,2 @@
1
+ broken
2
+ ---
@@ -0,0 +1,2 @@
1
+ tag: foo
2
+ ---
@@ -0,0 +1,2 @@
1
+ tag: "foo
2
+ ---
@@ -0,0 +1,5 @@
1
+ package: broken7
2
+ version: 1
3
+ prefer_system: false
4
+ ---
5
+
@@ -0,0 +1,4 @@
1
+ package: clobber-initdotsh
2
+ version: "1"
3
+ ---
4
+ echo exit 1 > "$INSTALLROOT/etc/profile.d/init.sh"
@@ -0,0 +1,10 @@
1
+ package: defaults-o2
2
+ version: v1
3
+ env:
4
+ CXXFLAGS: "-fPIC -g -O2 -std=c++11"
5
+ CFLAGS: "-fPIC -g -O2"
6
+ CMAKE_BUILD_TYPE: "RELWITHDEBINFO"
7
+ ---
8
+ # This file is included in any build recipe and it's only used to set
9
+ # environment variables. Which file to actually include can be defined by the
10
+ # "--defaults" option of alibuild.
@@ -0,0 +1,4 @@
1
+ package: delete-etc
2
+ version: "1"
3
+ ---
4
+ rm -rf "$INSTALLROOT/etc"
@@ -0,0 +1,6 @@
1
+ package: tracking-env
2
+ version: "1.0"
3
+ track_env:
4
+ TRACKED_ENV: echo "$TRACKED_ENV"
5
+ ---
6
+ echo Building with $TRACKED_ENV