alibuild 1.17.35__tar.gz → 1.17.36__tar.gz

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 (93) hide show
  1. {alibuild-1.17.35 → alibuild-1.17.36}/PKG-INFO +2 -2
  2. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild.egg-info/PKG-INFO +2 -2
  3. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild.egg-info/requires.txt +1 -1
  4. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/_version.py +3 -3
  5. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/analytics.py +2 -2
  6. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/args.py +3 -1
  7. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/build.py +134 -76
  8. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/build_template.sh +10 -0
  9. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/clean.py +3 -3
  10. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/cmd.py +8 -14
  11. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/deps.py +4 -4
  12. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/doctor.py +4 -4
  13. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/log.py +1 -1
  14. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/scm.py +1 -1
  15. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/sl.py +1 -1
  16. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/sync.py +17 -6
  17. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/utilities.py +17 -17
  18. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/workarea.py +4 -3
  19. {alibuild-1.17.35 → alibuild-1.17.36}/pyproject.toml +1 -1
  20. alibuild-1.17.36/requirements.txt +5 -0
  21. {alibuild-1.17.35 → alibuild-1.17.36}/setup.py +1 -1
  22. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_args.py +1 -1
  23. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_build.py +9 -4
  24. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_parseRecipe.py +2 -2
  25. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_utilities.py +3 -5
  26. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_workarea.py +23 -0
  27. alibuild-1.17.35/requirements.txt +0 -6
  28. {alibuild-1.17.35 → alibuild-1.17.36}/.flake8 +0 -0
  29. {alibuild-1.17.35 → alibuild-1.17.36}/.github/workflows/documentation.yml +0 -0
  30. {alibuild-1.17.35 → alibuild-1.17.36}/.github/workflows/pr-check.yml +0 -0
  31. {alibuild-1.17.35 → alibuild-1.17.36}/.github/workflows/release.yml +0 -0
  32. {alibuild-1.17.35 → alibuild-1.17.36}/.gitignore +0 -0
  33. {alibuild-1.17.35 → alibuild-1.17.36}/.pylintrc +0 -0
  34. {alibuild-1.17.35 → alibuild-1.17.36}/ANALYTICS.md +0 -0
  35. {alibuild-1.17.35 → alibuild-1.17.36}/DESIGN.md +0 -0
  36. {alibuild-1.17.35 → alibuild-1.17.36}/LICENSE.md +0 -0
  37. {alibuild-1.17.35 → alibuild-1.17.36}/PACKAGING.md +0 -0
  38. {alibuild-1.17.35 → alibuild-1.17.36}/README.rst +0 -0
  39. {alibuild-1.17.35 → alibuild-1.17.36}/alfaBuild +0 -0
  40. {alibuild-1.17.35 → alibuild-1.17.36}/aliBuild +0 -0
  41. {alibuild-1.17.35 → alibuild-1.17.36}/aliDeps +0 -0
  42. {alibuild-1.17.35 → alibuild-1.17.36}/aliDoctor +0 -0
  43. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild.egg-info/SOURCES.txt +0 -0
  44. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild.egg-info/dependency_links.txt +0 -0
  45. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild.egg-info/top_level.txt +0 -0
  46. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/__init__.py +0 -0
  47. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/git.py +0 -0
  48. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/init.py +0 -0
  49. {alibuild-1.17.35 → alibuild-1.17.36}/alibuild_helpers/templating_plugin.py +0 -0
  50. {alibuild-1.17.35 → alibuild-1.17.36}/alienv +0 -0
  51. {alibuild-1.17.35 → alibuild-1.17.36}/codecov.yml +0 -0
  52. {alibuild-1.17.35 → alibuild-1.17.36}/debian/changelog +0 -0
  53. {alibuild-1.17.35 → alibuild-1.17.36}/debian/compat +0 -0
  54. {alibuild-1.17.35 → alibuild-1.17.36}/debian/control +0 -0
  55. {alibuild-1.17.35 → alibuild-1.17.36}/debian/copyright +0 -0
  56. {alibuild-1.17.35 → alibuild-1.17.36}/debian/files +0 -0
  57. {alibuild-1.17.35 → alibuild-1.17.36}/debian/rules +0 -0
  58. {alibuild-1.17.35 → alibuild-1.17.36}/docs/SUPPORT +0 -0
  59. {alibuild-1.17.35 → alibuild-1.17.36}/docs/docs/alice_logo.png +0 -0
  60. {alibuild-1.17.35 → alibuild-1.17.36}/docs/docs/deps.png +0 -0
  61. {alibuild-1.17.35 → alibuild-1.17.36}/docs/docs/index.md +0 -0
  62. {alibuild-1.17.35 → alibuild-1.17.36}/docs/docs/quick.md +0 -0
  63. {alibuild-1.17.35 → alibuild-1.17.36}/docs/docs/reference.md +0 -0
  64. {alibuild-1.17.35 → alibuild-1.17.36}/docs/docs/stylesheets/extra.css +0 -0
  65. {alibuild-1.17.35 → alibuild-1.17.36}/docs/docs/troubleshooting.md +0 -0
  66. {alibuild-1.17.35 → alibuild-1.17.36}/docs/docs/user.md +0 -0
  67. {alibuild-1.17.35 → alibuild-1.17.36}/docs/mkdocs.yml +0 -0
  68. {alibuild-1.17.35 → alibuild-1.17.36}/pb +0 -0
  69. {alibuild-1.17.35 → alibuild-1.17.36}/setup.cfg +0 -0
  70. {alibuild-1.17.35 → alibuild-1.17.36}/templates/alibuild_to_please.jnj +0 -0
  71. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_analytics.py +0 -0
  72. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_clean.py +0 -0
  73. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_cmd.py +0 -0
  74. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_deps.py +0 -0
  75. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_doctor.py +0 -0
  76. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_git.py +0 -0
  77. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_hashing.py +0 -0
  78. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_init.py +0 -0
  79. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_log.py +0 -0
  80. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_packagelist.py +0 -0
  81. {alibuild-1.17.35 → alibuild-1.17.36}/tests/test_sync.py +0 -0
  82. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/broken1.sh +0 -0
  83. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/broken2.sh +0 -0
  84. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/broken3.sh +0 -0
  85. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/broken4.sh +0 -0
  86. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/broken5.sh +0 -0
  87. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/broken6.sh +0 -0
  88. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/broken7.sh +0 -0
  89. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/clobber-initdotsh.sh +0 -0
  90. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/defaults-o2.sh +0 -0
  91. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/delete-etc.sh +0 -0
  92. {alibuild-1.17.35 → alibuild-1.17.36}/tests/testdist/tracking-env.sh +0 -0
  93. {alibuild-1.17.35 → alibuild-1.17.36}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alibuild
3
- Version: 1.17.35
3
+ Version: 1.17.36
4
4
  Summary: ALICE Build Tool
5
5
  Home-page: https://alisw.github.io/alibuild
6
6
  Author: Giulio Eulisse
@@ -17,7 +17,7 @@ Requires-Dist: pyyaml
17
17
  Requires-Dist: requests
18
18
  Requires-Dist: distro
19
19
  Requires-Dist: jinja2
20
- Requires-Dist: boto3<1.36.0
20
+ Requires-Dist: boto3
21
21
  Provides-Extra: test
22
22
  Requires-Dist: tox; extra == "test"
23
23
  Provides-Extra: docs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alibuild
3
- Version: 1.17.35
3
+ Version: 1.17.36
4
4
  Summary: ALICE Build Tool
5
5
  Home-page: https://alisw.github.io/alibuild
6
6
  Author: Giulio Eulisse
@@ -17,7 +17,7 @@ Requires-Dist: pyyaml
17
17
  Requires-Dist: requests
18
18
  Requires-Dist: distro
19
19
  Requires-Dist: jinja2
20
- Requires-Dist: boto3<1.36.0
20
+ Requires-Dist: boto3
21
21
  Provides-Extra: test
22
22
  Requires-Dist: tox; extra == "test"
23
23
  Provides-Extra: docs
@@ -2,7 +2,7 @@ pyyaml
2
2
  requests
3
3
  distro
4
4
  jinja2
5
- boto3<1.36.0
5
+ boto3
6
6
 
7
7
  [docs]
8
8
  mkdocs
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.17.35'
32
- __version_tuple__ = version_tuple = (1, 17, 35)
31
+ __version__ = version = '1.17.36'
32
+ __version_tuple__ = version_tuple = (1, 17, 36)
33
33
 
34
- __commit_id__ = commit_id = 'g23eed7df6'
34
+ __commit_id__ = commit_id = 'g8f166593e'
@@ -72,7 +72,7 @@ def report(eventType, **metadata):
72
72
  ostype = "Macintosh" if architecture.startswith("osx") else "Linux"
73
73
  osversion, osprocessor = architecture.split("_", 1)
74
74
  args = ["curl", "--max-time", "5",
75
- "--user-agent", "aliBuild/%s (%s; %s %s) Python/%s" % (
75
+ "--user-agent", "aliBuild/{} ({}; {} {}) Python/{}".format(
76
76
  os.environ["ALIBUILD_VERSION"],
77
77
  ostype,
78
78
  osprocessor,
@@ -89,7 +89,7 @@ def report(eventType, **metadata):
89
89
  "https://www.google-analytics.com/collect"]
90
90
  try:
91
91
  subprocess.Popen(args)
92
- except:
92
+ except Exception:
93
93
  pass
94
94
 
95
95
  def report_event(category, action, label = "", value = None):
@@ -206,6 +206,8 @@ def doParseArgs():
206
206
  help=("Assume we're not building %(metavar)s and all its (unique) dependencies. "
207
207
  "You can specify this option multiple times or separate multiple arguments "
208
208
  "with commas."))
209
+ deps_parser.add_argument("-e", dest="environment", action="append", default=[],
210
+ help="KEY=VALUE binding to add to the environment. May be specified multiple times.")
209
211
 
210
212
  deps_graph = deps_parser.add_argument_group(title="Customise graph output")
211
213
  deps_graph.add_argument("--neat", dest="neat", action="store_true",
@@ -482,7 +484,7 @@ def finaliseArgs(args, parser):
482
484
  else:
483
485
  args.develPrefix = basename(dirname(abspath(args.configDir)))
484
486
  if getattr(args, "docker", False):
485
- args.develPrefix = "%s-%s" % (args.develPrefix, args.architecture) if "develPrefix" in args else args.architecture
487
+ args.develPrefix = f"{args.develPrefix}-{args.architecture}" if "develPrefix" in args else args.architecture
486
488
 
487
489
  if args.action == "init":
488
490
  args.configDir = args.configDir % {"prefix": args.develPrefix + "/"}
@@ -1,5 +1,6 @@
1
1
  from os.path import abspath, exists, basename, dirname, join, realpath
2
2
  from os import makedirs, unlink, readlink, rmdir
3
+ from pathlib import Path
3
4
  from alibuild_helpers import __version__
4
5
  from alibuild_helpers.analytics import report_event
5
6
  from alibuild_helpers.log import debug, info, banner, warning
@@ -19,7 +20,6 @@ from alibuild_helpers.sync import remote_from_url
19
20
  from alibuild_helpers.workarea import logged_scm, updateReferenceRepoSpec, checkout_sources
20
21
  from alibuild_helpers.log import ProgressPrint, log_current_package
21
22
  from glob import glob
22
- from textwrap import dedent
23
23
  from collections import OrderedDict
24
24
  from shlex import quote
25
25
  import tempfile
@@ -31,6 +31,7 @@ import socket
31
31
  import os
32
32
  import re
33
33
  import shutil
34
+ import sys
34
35
  import time
35
36
 
36
37
 
@@ -43,7 +44,7 @@ def writeAll(fn, txt) -> None:
43
44
  def readHashFile(fn):
44
45
  try:
45
46
  return open(fn).read().strip("\n")
46
- except IOError:
47
+ except OSError:
47
48
  return "0"
48
49
 
49
50
 
@@ -55,11 +56,9 @@ def update_git_repos(args, specs, buildOrder):
55
56
  """
56
57
 
57
58
  def update_repo(package, git_prompt):
58
- specs[package]["scm"] = Git()
59
- if specs[package]["is_devel_pkg"]:
60
- specs[package]["source"] = os.path.join(os.getcwd(), specs[package]["package"])
61
- if exists(os.path.join(specs[package]["source"], ".sl")) or exists(os.path.join(specs[package]["source"], ".git/sl")):
62
- specs[package]["scm"] = Sapling()
59
+ # Note: spec["scm"] should already be initialized before this is called
60
+ # This function just updates the repository and fetches refs
61
+ assert "scm" in specs[package], f"specs[{package!r}] has no scm key"
63
62
  updateReferenceRepoSpec(args.referenceSources, package, specs[package],
64
63
  fetch=args.fetchRepos, allowGitPrompt=git_prompt)
65
64
 
@@ -195,7 +194,7 @@ def storeHashes(package, specs, considerRelocation):
195
194
  # spec["env"] is of type OrderedDict[str, str].
196
195
  # spec["*_path"] are of type OrderedDict[str, list[str]].
197
196
  assert isinstance(spec[key], OrderedDict), \
198
- "spec[%r] was of type %r" % (key, type(spec[key]))
197
+ f"spec[{key!r}] was of type {type(spec[key])!r}"
199
198
 
200
199
  # Python 3.12 changed the string representation of OrderedDicts from
201
200
  # OrderedDict([(key, value)]) to OrderedDict({key: value}), so to remain
@@ -204,7 +203,7 @@ def storeHashes(package, specs, considerRelocation):
204
203
  h_all(", ".join(
205
204
  # XXX: We still rely on repr("str") being "'str'",
206
205
  # and on repr(["a", "b"]) being "['a', 'b']".
207
- "(%r, %r)" % (key, value)
206
+ f"({key!r}, {value!r})"
208
207
  for key, value in spec[key].items()
209
208
  ))
210
209
  h_all("])")
@@ -272,7 +271,7 @@ def hash_local_changes(spec):
272
271
  h = Hasher()
273
272
  if "track_env" in spec:
274
273
  assert isinstance(spec["track_env"], OrderedDict), \
275
- "spec[%r] was of type %r" % ("track_env", type(spec["track_env"]))
274
+ "spec[{!r}] was of type {!r}".format("track_env", type(spec["track_env"]))
276
275
 
277
276
  # Python 3.12 changed the string representation of OrderedDicts from
278
277
  # OrderedDict([(key, value)]) to OrderedDict({key: value}), so to remain
@@ -281,7 +280,7 @@ def hash_local_changes(spec):
281
280
  h(", ".join(
282
281
  # XXX: We still rely on repr("str") being "'str'",
283
282
  # and on repr(["a", "b"]) being "['a', 'b']".
284
- "(%r, %r)" % (key, value) for key, value in spec["track_env"].items()))
283
+ f"({key!r}, {value!r})" for key, value in spec["track_env"].items()))
285
284
  h("])")
286
285
  def hash_output(msg, args):
287
286
  lines = msg % args
@@ -365,6 +364,7 @@ def generate_initdotsh(package, specs, architecture, post_build=False):
365
364
  commit_hash=quote(spec["commit_hash"]),
366
365
  ) for line in (
367
366
  'export {bigpackage}_ROOT="$WORK_DIR/$ALIBUILD_ARCH_PREFIX"/{package}/{version}-{revision}',
367
+ 'export RECC_PREFIX_MAP="${bigpackage}_ROOT=/recc/{bigpackage}_ROOT:$RECC_PREFIX_MAP"',
368
368
  "export {bigpackage}_VERSION={version}",
369
369
  "export {bigpackage}_REVISION={revision}",
370
370
  "export {bigpackage}_HASH={hash}",
@@ -380,12 +380,12 @@ def generate_initdotsh(package, specs, architecture, post_build=False):
380
380
  # First, output a sensible error message if types are wrong.
381
381
  for key in ("env", "append_path", "prepend_path"):
382
382
  dieOnError(not isinstance(spec.get(key, {}), dict),
383
- "Tag `%s' in %s should be a dict." % (key, package))
383
+ f"Tag `{key}' in {package} should be a dict.")
384
384
 
385
385
  # Set "env" variables.
386
386
  # We only put the values in double-quotes, so that they can refer to other
387
387
  # shell variables or do command substitution (e.g. $(brew --prefix ...)).
388
- lines.extend('export {}="{}"'.format(key, value)
388
+ lines.extend(f'export {key}="{value}"'
389
389
  for key, value in spec.get("env", {}).items()
390
390
  if key != "DYLD_LIBRARY_PATH")
391
391
 
@@ -402,7 +402,7 @@ def generate_initdotsh(package, specs, architecture, post_build=False):
402
402
  # By default we add the .../bin directory to PATH and .../lib to LD_LIBRARY_PATH.
403
403
  # Prepend to these paths, so that our packages win against system ones.
404
404
  for key, value in (("PATH", "bin"), ("LD_LIBRARY_PATH", "lib")):
405
- prepend_path.setdefault(key, []).insert(0, "${}_ROOT/{}".format(bigpackage, value))
405
+ prepend_path.setdefault(key, []).insert(0, f"${bigpackage}_ROOT/{value}")
406
406
  lines.extend('export {key}="{value}${{{key}+:${key}}}"'
407
407
  .format(key=key, value=":".join(value))
408
408
  for key, value in prepend_path.items()
@@ -482,12 +482,17 @@ def doBuild(args, parser):
482
482
 
483
483
  makedirs(join(workDir, "SPECS"), exist_ok=True)
484
484
 
485
- # If the alidist workdir contains a .sl directory, we use Sapling as SCM.
486
- # Otherwise, we default to git (without checking for the actual presence of
487
- # .git). We mustn't check for a .git directory, because some tests use a
488
- # subdirectory of the alibuild source tree as the "alidist" checkout, and
489
- # that won't have a .git directory.
490
- scm = exists("%s/.sl" % args.configDir) and Sapling() or Git()
485
+ # If the alidist workdir contains a .sl directory (or .git/sl for git repos
486
+ # with Sapling enabled), we use Sapling as SCM. Otherwise, we default to git
487
+ # (without checking for the actual presence of .git). We mustn't check for a
488
+ # .git directory, because some tests use a subdirectory of the alibuild source
489
+ # tree as the "alidist" checkout, and that won't have a .git directory.
490
+ config_path = Path(args.configDir)
491
+ has_sapling = (config_path / ".sl").exists() or (config_path / ".git" / "sl").exists()
492
+ if has_sapling and shutil.which("sl"):
493
+ scm = Sapling()
494
+ else:
495
+ scm = Git()
491
496
  try:
492
497
  checkedOutCommitName = scm.checkedOutCommitName(directory=args.configDir)
493
498
  except SCMError:
@@ -563,13 +568,13 @@ def doBuild(args, parser):
563
568
  del develCandidates, develCandidatesUpper, develPkgsUpper
564
569
 
565
570
  if buildOrder:
566
- if args.onlyDeps:
571
+ if args.onlyDeps:
567
572
  builtPackages = buildOrder[:-1]
568
573
  else:
569
574
  builtPackages = buildOrder
570
575
  if len(builtPackages) > 1:
571
576
  banner("Packages will be built in the following order:\n - %s",
572
- "\n - ".join(x+" (development package)" if x in develPkgs else "%s@%s" % (x, specs[x]["tag"])
577
+ "\n - ".join(x+" (development package)" if x in develPkgs else "{}@{}".format(x, specs[x]["tag"])
573
578
  for x in builtPackages if x != "defaults-release"))
574
579
  else:
575
580
  banner("No dependencies of package %s to build.", buildOrder[-1])
@@ -587,11 +592,18 @@ def doBuild(args, parser):
587
592
 
588
593
  for pkg, spec in specs.items():
589
594
  spec["is_devel_pkg"] = pkg in develPkgs
590
- spec["scm"] = Git()
591
595
  if spec["is_devel_pkg"]:
592
- spec["source"] = os.path.join(os.getcwd(), pkg)
593
- if "source" in spec and exists(os.path.join(spec["source"], ".sl")):
594
- spec["scm"] = Sapling()
596
+ spec["source"] = str(Path.cwd() / pkg)
597
+
598
+ # Only initialize Sapling if it's in PATH and the repo uses it
599
+ use_sapling = False
600
+ if "source" in spec:
601
+ source_path = Path(spec["source"])
602
+ has_sapling = ( (source_path / ".sl").exists() or (source_path / ".git" / "sl").exists() )
603
+ if has_sapling and shutil.which("sl"):
604
+ use_sapling = True
605
+ spec["scm"] = Sapling() if use_sapling else Git()
606
+
595
607
  reference_repo = join(os.path.abspath(args.referenceSources), pkg.lower())
596
608
  if exists(reference_repo):
597
609
  spec["reference"] = reference_repo
@@ -817,7 +829,7 @@ def doBuild(args, parser):
817
829
  develPrefix = possibleDevelPrefix
818
830
 
819
831
  if possibleDevelPrefix:
820
- spec["build_family"] = "%s-%s" % (possibleDevelPrefix, args.defaults)
832
+ spec["build_family"] = f"{possibleDevelPrefix}-{args.defaults}"
821
833
  else:
822
834
  spec["build_family"] = args.defaults
823
835
  if spec["package"] == mainPackage:
@@ -937,7 +949,7 @@ def doBuild(args, parser):
937
949
 
938
950
  # Now that we have all the information about the package we want to build, let's
939
951
  # check if it wasn't built / unpacked already.
940
- hashPath= "%s/%s/%s/%s-%s" % (workDir,
952
+ hashPath= "{}/{}/{}/{}-{}".format(workDir,
941
953
  args.architecture,
942
954
  spec["package"],
943
955
  spec["version"],
@@ -980,12 +992,12 @@ def doBuild(args, parser):
980
992
  unlink(join(buildWorkDir, "BUILD", spec["package"] + "-latest"))
981
993
  if "develPrefix" in args:
982
994
  unlink(join(buildWorkDir, "BUILD", spec["package"] + "-latest-" + args.develPrefix))
983
- except:
995
+ except Exception:
984
996
  pass
985
997
  try:
986
998
  rmdir(join(buildWorkDir, "BUILD"))
987
999
  rmdir(join(workDir, "INSTALLROOT"))
988
- except:
1000
+ except Exception:
989
1001
  pass
990
1002
  continue
991
1003
 
@@ -1008,15 +1020,10 @@ def doBuild(args, parser):
1008
1020
 
1009
1021
  # The actual build script.
1010
1022
  debug("spec = %r", spec)
1011
-
1012
- cmd_raw = ""
1013
- try:
1014
- fp = open(dirname(realpath(__file__))+'/build_template.sh', 'r')
1015
- cmd_raw = fp.read()
1016
- fp.close()
1017
- except:
1018
- from pkg_resources import resource_string
1019
- cmd_raw = resource_string("alibuild_helpers", 'build_template.sh')
1023
+
1024
+ fp = open(dirname(realpath(__file__))+'/build_template.sh')
1025
+ cmd_raw = fp.read()
1026
+ fp.close()
1020
1027
 
1021
1028
  if args.docker:
1022
1029
  cachedTarball = re.sub("^" + workDir, "/sw", spec["cachedTarball"])
@@ -1030,7 +1037,7 @@ def doBuild(args, parser):
1030
1037
  spec["version"] + "-" + spec["revision"])
1031
1038
 
1032
1039
  makedirs(scriptDir, exist_ok=True)
1033
- writeAll("%s/%s.sh" % (scriptDir, spec["package"]), spec["recipe"])
1040
+ writeAll("{}/{}.sh".format(scriptDir, spec["package"]), spec["recipe"])
1034
1041
  writeAll("%s/build.sh" % scriptDir, cmd_raw % {
1035
1042
  "provenance": create_provenance_info(spec["package"], specs, args),
1036
1043
  "initdotsh_deps": generate_initdotsh(p, specs, args.architecture, post_build=False),
@@ -1093,7 +1100,7 @@ def doBuild(args, parser):
1093
1100
  scriptDir=quote(scriptDir),
1094
1101
  extraArgs=" ".join(map(quote, args.docker_extra_args)),
1095
1102
  additionalEnv=" ".join(
1096
- "-e {}={}".format(var, quote(value)) for var, value in buildEnvironment),
1103
+ f"-e {var}={quote(value)}" for var, value in buildEnvironment),
1097
1104
  # Used e.g. by O2DPG-sim-tests to find the O2DPG repository.
1098
1105
  develVolumes=" ".join(
1099
1106
  '-v "$PWD/$(readlink {pkg} || echo {pkg})":/{pkg}:rw'.format(pkg=quote(spec["package"]))
@@ -1105,12 +1112,14 @@ def doBuild(args, parser):
1105
1112
  )
1106
1113
  else:
1107
1114
  os.environ.update(buildEnvironment)
1108
- build_command = "%s -e -x %s/build.sh 2>&1" % (BASH, quote(scriptDir))
1115
+ build_command = f"{BASH} -e -x {quote(scriptDir)}/build.sh 2>&1"
1109
1116
 
1110
1117
  debug("Build command: %s", build_command)
1118
+ progress_msg = "Unpacking %s@%s" if cachedTarball else "Compiling %s@%s"
1119
+ if not cachedTarball and not args.debug:
1120
+ progress_msg += " (use --debug for full output)"
1111
1121
  progress = ProgressPrint(
1112
- ("Unpacking %s@%s" if cachedTarball else
1113
- "Compiling %s@%s (use --debug for full output)") %
1122
+ progress_msg %
1114
1123
  (spec["package"],
1115
1124
  args.develPrefix if "develPrefix" in args and spec["is_devel_pkg"] else spec["version"])
1116
1125
  )
@@ -1127,51 +1136,100 @@ def doBuild(args, parser):
1127
1136
  if spec["is_devel_pkg"]:
1128
1137
  updatablePkgs.append(spec["package"])
1129
1138
 
1130
- buildErrMsg = dedent("""\
1131
- Error while executing {sd}/build.sh on `{h}'.
1132
- Log can be found in {w}/BUILD/{p}-latest{devSuffix}/log
1133
- Please upload it to CERNBox/Dropbox if you intend to request support.
1134
- Build directory is {w}/BUILD/{p}-latest{devSuffix}/{p}.
1135
- """).format(
1136
- h=socket.gethostname(),
1137
- sd=scriptDir,
1138
- w=buildWorkDir,
1139
- p=spec["package"],
1140
- devSuffix="-" + args.develPrefix
1141
- if "develPrefix" in args and spec["is_devel_pkg"]
1142
- else "",
1143
- )
1144
- if updatablePkgs:
1145
- buildErrMsg += dedent("""
1146
- Note that you have packages in development mode.
1147
- Devel sources are not updated automatically, you must do it by hand.\n
1148
- This problem might be due to one or more outdated devel sources.
1149
- To update all development packages required for this build it is usually sufficient to do:
1150
- """)
1151
- buildErrMsg += "".join("\n ( cd %s && git pull --rebase )" % dp for dp in updatablePkgs)
1139
+ # Determine paths
1140
+ devSuffix = "-" + args.develPrefix if "develPrefix" in args and spec["is_devel_pkg"] else ""
1141
+ log_path = f"{buildWorkDir}/BUILD/{spec['package']}-latest{devSuffix}/log"
1142
+ build_dir = f"{buildWorkDir}/BUILD/{spec['package']}-latest{devSuffix}/{spec['package']}"
1143
+
1144
+ # Use relative paths if we're inside the work directory
1145
+ try:
1146
+ from os.path import relpath
1147
+ log_path = relpath(log_path, os.getcwd())
1148
+ build_dir = relpath(build_dir, os.getcwd())
1149
+ except (ValueError, OSError):
1150
+ pass # Keep absolute paths if relpath fails
1151
+
1152
+ # Color codes for error message (if TTY)
1153
+ bold = "\033[1m" if sys.stderr.isatty() else ""
1154
+ red = "\033[31m" if sys.stderr.isatty() else ""
1155
+ reset = "\033[0m" if sys.stderr.isatty() else ""
1156
+
1157
+ # Build the error message
1158
+ devel_note = " (development package)" if spec["is_devel_pkg"] else ""
1159
+ buildErrMsg = f"{red}{bold}BUILD FAILED:{reset} {spec['package']}@{spec['version']}{devel_note}\n"
1160
+ buildErrMsg += "=" * 70 + "\n\n"
1161
+
1162
+ buildErrMsg += f"{bold}Log File:{reset}\n"
1163
+ buildErrMsg += f" {log_path}\n\n"
1164
+
1165
+ buildErrMsg += f"{bold}Build Directory:{reset}\n"
1166
+ buildErrMsg += f" {build_dir}\n"
1152
1167
 
1153
1168
  # Gather build info for the error message
1154
1169
  try:
1170
+ detected_arch = detectArch()
1171
+
1172
+ # Only show safe arguments (no tokens/secrets) in CLI-usable format
1155
1173
  safe_args = {
1156
1174
  "pkgname", "defaults", "architecture", "forceUnknownArch",
1157
1175
  "develPrefix", "jobs", "noSystem", "noDevel", "forceTracked", "plugin",
1158
1176
  "disable", "annotate", "onlyDeps", "docker"
1159
- }
1160
- args_str = " ".join(f"--{k}={v}" for k, v in vars(args).items() if v and k in safe_args)
1161
- detected_arch = detectArch()
1162
- buildErrMsg += dedent(f"""
1163
- Build info:
1164
- OS: {detected_arch}
1165
- Using aliBuild from alibuild@{__version__ or "unknown"} recipes in alidist@{os.environ["ALIBUILD_ALIDIST_HASH"][:10]}
1166
- Build arguments: {args_str}
1167
- """)
1177
+ }
1178
+
1179
+ cli_args = []
1180
+ for k, v in vars(args).items():
1181
+ if not v or k not in safe_args:
1182
+ continue
1183
+
1184
+ # Format based on type for CLI usage
1185
+ if isinstance(v, bool):
1186
+ if v: # Only show if True
1187
+ cli_args.append(f"--{k}")
1188
+ elif isinstance(v, list):
1189
+ if v: # Only show non-empty lists
1190
+ # For lists, use multiple --flag value or --flag=val1,val2
1191
+ for item in v:
1192
+ cli_args.append(f"--{k}={quote(str(item))}")
1193
+ else:
1194
+ # Quote if needed
1195
+ cli_args.append(f"--{k}={quote(str(v))}")
1196
+
1197
+ args_str = " ".join(cli_args)
1198
+
1199
+ buildErrMsg += f"\n{bold}Environment:{reset}\n"
1200
+ buildErrMsg += f" OS: {detected_arch}\n"
1201
+ buildErrMsg += f" aliBuild: {__version__ or 'unknown'} (alidist@{os.environ['ALIBUILD_ALIDIST_HASH'][:10]})\n"
1168
1202
 
1169
1203
  if detected_arch.startswith("osx"):
1170
- buildErrMsg += f'XCode version: {getstatusoutput("xcodebuild -version")[1]}'
1204
+ xcode_info = getstatusoutput("xcodebuild -version")[1]
1205
+ # Combine XCode version lines into one
1206
+ xcode_lines = xcode_info.strip().split('\n')
1207
+ if len(xcode_lines) >= 2:
1208
+ xcode_str = f"{xcode_lines[0]} ({xcode_lines[1]})"
1209
+ else:
1210
+ xcode_str = xcode_lines[0] if xcode_lines else "Unknown"
1211
+ buildErrMsg += f" XCode: {xcode_str}\n"
1212
+
1213
+ buildErrMsg += f" Arguments: {args_str}\n"
1171
1214
 
1172
1215
  except Exception as exc:
1173
1216
  warning("Failed to gather build info", exc_info=exc)
1174
1217
 
1218
+ # Add note about development packages if applicable
1219
+ if updatablePkgs:
1220
+ buildErrMsg += f"\n{bold}Development Packages:{reset}\n"
1221
+ buildErrMsg += " Development sources are not updated automatically.\n"
1222
+ buildErrMsg += " This may be due to outdated sources. To update:\n"
1223
+ buildErrMsg += "".join(f"\n ( cd {dp} && git pull --rebase )" for dp in updatablePkgs)
1224
+ buildErrMsg += "\n"
1225
+
1226
+ # Add Next Steps section
1227
+ buildErrMsg += f"\n{bold}Next Steps:{reset}\n"
1228
+ buildErrMsg += f" • View error log: cat {log_path}\n"
1229
+ if not args.debug:
1230
+ buildErrMsg += f" • Rebuild with debug: aliBuild build {spec['package']} --debug\n"
1231
+ buildErrMsg += f" • Please upload the full log to CERNBox/Dropbox if you intend to request support.\n"
1232
+
1175
1233
 
1176
1234
  dieOnError(err, buildErrMsg.strip())
1177
1235
 
@@ -71,6 +71,16 @@ export BUILDROOT="$ALIBUILD_BUILD_WORK_DIR/BUILD/$PKGHASH"
71
71
  export SOURCEDIR="$WORK_DIR/SOURCES/$PKGNAME/$PKGVERSION/$COMMIT_HASH"
72
72
  export BUILDDIR="$BUILDROOT/$PKGNAME"
73
73
 
74
+ # All caching for RECC should happen relative to $WORK_DIR
75
+ export RECC_PROJECT_ROOT=$WORK_DIR
76
+ export RECC_WORKING_DIR_PREFIX=$WORK_DIR
77
+ # Moreover we allow caching stuff across different builds of the same
78
+ # package, but not across packages.
79
+ export RECC_PREFIX_MAP=$BUILDDIR=/recc/BUILDDIR-$PKGNAME:$INSTALLROOT=/recc/INSTALLROOT-$PKGNAME:$SOURCEDIR=/recc/SOURCEDIR-$PKGNAME
80
+ #export RECC_PREFIX_MAP=$RECC_PREFIX_MAP:$(readlink $BUILDDIR)=/recc/BUILDDIR-$PKGNAME:$(readlink $INSTALLROOT)=/recc/INSTALLROOT-$PKGNAME:$(readlink $SOURCEDIR)=/recc/SOURCEDIR-$PKGNAME
81
+ # No point in mixing packages
82
+ export RECC_ACTION_SALT="$PKGNAME"
83
+
74
84
  rm -fr "$WORK_DIR/INSTALLROOT/$PKGHASH"
75
85
  # We remove the build directory only if we are not in incremental mode.
76
86
  if [[ "$INCREMENTAL_BUILD_HASH" == 0 ]] && ! rm -rf "$BUILDROOT"; then
@@ -43,13 +43,13 @@ def decideClean(workDir, architecture, aggressiveCleanup):
43
43
  # we do not need the actual tarballs after they have been built.
44
44
  toDelete = ["%s/TMP" % workDir, "%s/INSTALLROOT" % workDir]
45
45
  if aggressiveCleanup:
46
- toDelete += ["%s/TARS/%s/store" % (workDir, architecture),
46
+ toDelete += [f"{workDir}/TARS/{architecture}/store",
47
47
  "%s/SOURCES" % (workDir)]
48
48
  allBuildStuff = glob.glob("%s/BUILD/*" % workDir)
49
49
  toDelete += [x for x in allBuildStuff
50
50
  if not path.islink(x) and basename(x) not in symlinksBuild]
51
- installGlob ="%s/%s/*/" % (workDir, architecture)
52
- installedPackages = set([dirname(x) for x in glob.glob(installGlob)])
51
+ installGlob =f"{workDir}/{architecture}/*/"
52
+ installedPackages = {dirname(x) for x in glob.glob(installGlob)}
53
53
  symlinksInstall = []
54
54
  for x in installedPackages:
55
55
  symlinksInstall += [path.realpath(y) for y in glob.glob(x + "/latest*")]
@@ -6,7 +6,7 @@ from textwrap import dedent
6
6
  from subprocess import TimeoutExpired
7
7
  from shlex import quote
8
8
 
9
- from alibuild_helpers.log import debug, warning, dieOnError
9
+ from alibuild_helpers.log import debug, error, dieOnError
10
10
 
11
11
  def decode_with_fallback(data):
12
12
  """Try to decode DATA as utf-8; if that doesn't work, fall back to latin-1.
@@ -29,7 +29,7 @@ def getoutput(command, timeout=None):
29
29
  try:
30
30
  stdout, stderr = proc.communicate(timeout=timeout)
31
31
  except TimeoutExpired:
32
- warning("Process %r timed out; terminated", command)
32
+ error("Process %r timed out; terminated", command)
33
33
  proc.terminate()
34
34
  stdout, stderr = proc.communicate()
35
35
  dieOnError(proc.returncode, "Command %s failed with code %d: %s" %
@@ -43,7 +43,7 @@ def getstatusoutput(command, timeout=None, cwd=None):
43
43
  try:
44
44
  merged_output, _ = proc.communicate(timeout=timeout)
45
45
  except TimeoutExpired:
46
- warning("Process %r timed out; terminated", command)
46
+ error("Process %r timed out; terminated", command)
47
47
  proc.terminate()
48
48
  merged_output, _ = proc.communicate()
49
49
  merged_output = decode_with_fallback(merged_output)
@@ -88,14 +88,8 @@ class DockerRunner:
88
88
  def __enter__(self):
89
89
  if self._docker_image:
90
90
  # "sleep inf" pauses forever, until we kill it.
91
- envOpts = []
92
- volumes = []
93
- for env in self._extra_env.items():
94
- envOpts.append("-e")
95
- envOpts.append(f"{env[0]}={env[1]}")
96
- for v in self._extra_volumes:
97
- volumes.append("-v")
98
- volumes.append(v)
91
+ envOpts = [opt for k, v in self._extra_env.items() for opt in ("-e", f"{k}={v}")]
92
+ volumes = [opt for v in self._extra_volumes for opt in ("-v", v)]
99
93
  cmd = ["docker", "run", "--detach"] + envOpts + volumes + ["--rm", "--entrypoint="]
100
94
  cmd += self._docker_run_args
101
95
  cmd += [self._docker_image, "sleep", "inf"]
@@ -105,13 +99,13 @@ class DockerRunner:
105
99
  if self._container is None:
106
100
  command_prefix=""
107
101
  if self._extra_env:
108
- command_prefix="env " + " ".join("{}={}".format(k, quote(v)) for (k,v) in self._extra_env.items()) + " "
109
- return getstatusoutput("{}{} -c {}".format(command_prefix, BASH, quote(cmd))
102
+ command_prefix="env " + " ".join(f"{k}={quote(v)}" for (k,v) in self._extra_env.items()) + " "
103
+ return getstatusoutput(f"{command_prefix}{BASH} -c {quote(cmd)}"
110
104
  , cwd=cwd)
111
105
  envOpts = []
112
106
  for env in self._extra_env.items():
113
107
  envOpts.append("-e")
114
- envOpts.append("{}={}".format(env[0], env[1]))
108
+ envOpts.append(f"{env[0]}={env[1]}")
115
109
  exec_cmd = ["docker", "container", "exec"] + envOpts + [self._container, "bash", "-c", cmd]
116
110
  return getstatusoutput(exec_cmd, cwd=cwd)
117
111
 
@@ -83,18 +83,18 @@ def doDeps(args, parser):
83
83
  assert color, "This should not happen (happened for %s)" % k
84
84
 
85
85
  # Node definition
86
- dot += '"%s" [shape=box, style="rounded,filled", fontname="helvetica", fillcolor=%s]\n' % (k,color)
86
+ dot += f'"{k}" [shape=box, style="rounded,filled", fontname="helvetica", fillcolor={color}]\n'
87
87
 
88
88
  # Connections (different whether it's a build dependency or a runtime one)
89
89
  for dep in spec["build_requires"]:
90
- dot += '"%s" -> "%s" [color=grey70]\n' % (k, dep)
90
+ dot += f'"{k}" -> "{dep}" [color=grey70]\n'
91
91
  for dep in spec["runtime_requires"]:
92
- dot += '"%s" -> "%s" [color=dodgerblue3]\n' % (k, dep)
92
+ dot += f'"{k}" -> "{dep}" [color=dodgerblue3]\n'
93
93
 
94
94
  dot += "}\n"
95
95
 
96
96
  if args.outdot:
97
- fp = open(args.outdot, "wt")
97
+ fp = open(args.outdot, "w")
98
98
  else:
99
99
  fp = NamedTemporaryFile(delete=False, mode="wt")
100
100
  fp.write(dot)
@@ -33,7 +33,7 @@ def checkPreferSystem(spec, cmd, homebrew_replacement, getstatusoutput_docker):
33
33
  warning("Package %s cannot be picked up from the system and will be built by aliBuild.\n"
34
34
  "This is due to the fact the following script fails:\n\n%s\n\n"
35
35
  "with the following output:\n\n%s\n",
36
- spec["package"], cmd, "\n".join("%s: %s" % (spec["package"], x) for x in out.split("\n")))
36
+ spec["package"], cmd, "\n".join("{}: {}".format(spec["package"], x) for x in out.split("\n")))
37
37
  return (err, "")
38
38
 
39
39
  def checkRequirements(spec, cmd, homebrew_replacement, getstatusoutput_docker):
@@ -53,7 +53,7 @@ def checkRequirements(spec, cmd, homebrew_replacement, getstatusoutput_docker):
53
53
  "This is due to the fact that the following script fails:\n\n%s\n"
54
54
  "with the following output:\n\n%s\n%s\n",
55
55
  spec["package"], cmd,
56
- "\n".join("%s: %s" % (spec["package"], x) for x in out.split("\n")),
56
+ "\n".join("{}: {}".format(spec["package"], x) for x in out.split("\n")),
57
57
  spec.get("system_requirement_missing"))
58
58
  return (err, "")
59
59
 
@@ -125,7 +125,7 @@ def doDoctor(args, parser):
125
125
  packages = []
126
126
  exitcode = 0
127
127
  for p in args.packages:
128
- path = "%s/%s.sh" % (args.configDir, p.lower())
128
+ path = f"{args.configDir}/{p.lower()}.sh"
129
129
  if not exists(path):
130
130
  error("Cannot find recipe %s for package %s.", path, p)
131
131
  exitcode = 1
@@ -166,7 +166,7 @@ def doDoctor(args, parser):
166
166
  taps = taps,
167
167
  log = info)
168
168
 
169
- alwaysBuilt = set(x for x in specs) - fromSystem - own - failed
169
+ alwaysBuilt = {x for x in specs} - fromSystem - own - failed
170
170
  if alwaysBuilt:
171
171
  banner("The following packages will be built by aliBuild because\n"
172
172
  " usage of a system version of it is not allowed or supported, by policy:\n\n- %s",