summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2025-02-17 10:05:15 +0100
committerPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2025-02-20 15:33:53 +0100
commite749a97621d445de5e0dec89ab840dd61839d872 (patch)
tree87f5290818f07def99b0a76e6e088614c5664a91
parent377b216dea73254f8d8e37868484be69a746678a (diff)
downloadjustbuild-e749a97621d445de5e0dec89ab840dd61839d872.tar.gz
just-lock: Improve handling of pragmas in 'repos' import description
In particular, any transitive 'file'-type repository will inherit any given '{to_git: true}' pragma in the import description objects. Note that this technically can only happen for transitive 'file' repositories imported from a 'file' source, so in all other cases such a pragma would not have any effect. Document change and extend the import from 'file' source test to check this feature.
-rwxr-xr-xbin/just-lock.py44
-rw-r--r--doc/future-designs/just-lock.md8
-rw-r--r--share/man/just-lock-config.5.md15
-rw-r--r--test/end-to-end/just-lock/file-imports.sh6
4 files changed, 50 insertions, 23 deletions
diff --git a/bin/just-lock.py b/bin/just-lock.py
index 3f1ed1ae..1639a656 100755
--- a/bin/just-lock.py
+++ b/bin/just-lock.py
@@ -745,8 +745,29 @@ def rewrite_file_repo(repo: Json, remote_type: str, remote_stub: Dict[str, Any],
fail("Unsupported remote type!")
+def update_pragmas(repo: Json, pragma: Json) -> Json:
+ """Update the description with any input-provided "absent" and "to_git"
+ pragmas, as needed:
+ - for all repositories, merge the "absent" pragma
+ - for "file"-type repositories, merge the "to_git" pragma"""
+ existing: Json = dict(repo.get("pragma", {})) # operate on copy
+ # all repos support "absent pragma"
+ absent: bool = existing.get("absent", False) or pragma.get("absent", False)
+ if absent:
+ existing["absent"] = True
+ # support "to_git" pragma for "file"-type repos
+ if repo.get("type") == "file":
+ to_git = existing.get("to_git", False) or pragma.get("to_git", False)
+ if to_git:
+ existing["to_git"] = True
+ # all other pragmas as kept; if no pragma was set, do not set any
+ if existing:
+ repo = dict(repo, **{"pragma": existing})
+ return repo
+
+
def rewrite_repo(repo_spec: Json, *, remote_type: str,
- remote_stub: Dict[str, Any], assign: Json, absent: bool,
+ remote_stub: Dict[str, Any], assign: Json, pragma: Json,
as_layer: bool, fail_context: str) -> Json:
"""Rewrite description of imported repositories."""
new_spec: Json = {}
@@ -766,8 +787,9 @@ def rewrite_repo(repo_spec: Json, *, remote_type: str,
elif repo.get("type") in ["computed", "tree structure"]:
target: str = repo.get("repo", None)
repo = dict(repo, **{"repo": assign[target]})
- if absent and isinstance(repo, dict):
- repo["pragma"] = dict(repo.get("pragma", {}), **{"absent": True})
+ # update pragmas, as needed
+ if isinstance(repo, dict):
+ repo = update_pragmas(repo, pragma)
new_spec["repository"] = repo
# rewrite other roots and bindings, if actually needed to be imported
if not as_layer:
@@ -823,19 +845,13 @@ def handle_import(remote_type: str, remote_stub: Dict[str, Any],
% (json.dumps(import_map, indent=2), ))
pragma: Json = repo_desc.get("pragma", None)
- if pragma is not None and not isinstance(pragma, dict):
+ if pragma is None:
+ pragma = {}
+ elif not isinstance(pragma, dict):
fail(
fail_context +
"Expected \"repos\" entry subfield \"pragma\" to be a map, but found:\n%r"
% (json.dumps(pragma, indent=2), ))
- absent: bool = False if pragma is None else pragma.get("absent", False)
- if absent is None:
- absent = False
- elif not isinstance(absent, bool):
- fail(
- fail_context +
- "Expected \"repos\" entry pragma \"absent\" to be a bool, but found:\n%r"
- % (json.dumps(absent, indent=2), ))
# Handle import with renaming
foreign_repos: Json = foreign_config.get("repositories", {})
@@ -869,7 +885,7 @@ def handle_import(remote_type: str, remote_stub: Dict[str, Any],
remote_type=remote_type,
remote_stub=remote_stub,
assign=total_assign,
- absent=absent,
+ pragma=pragma,
as_layer=False,
fail_context=fail_context)
for repo in extra_imports:
@@ -877,7 +893,7 @@ def handle_import(remote_type: str, remote_stub: Dict[str, Any],
remote_type=remote_type,
remote_stub=remote_stub,
assign=total_assign,
- absent=absent,
+ pragma=pragma,
as_layer=True,
fail_context=fail_context)
diff --git a/doc/future-designs/just-lock.md b/doc/future-designs/just-lock.md
index 0ee3bf62..151625c1 100644
--- a/doc/future-designs/just-lock.md
+++ b/doc/future-designs/just-lock.md
@@ -264,7 +264,9 @@ The type of a _source_ is defined by the string value of the mandatory subfield
checkout.
The checkout is assumed to be maintained, so that `"file"`-type repositories
- marked to be imported can retain their type.
+ marked to be imported can retain their type. For such transitive dependencies,
+ one can also set the `"to_git": true` pragma with a corresponding entry in the
+ usual `"pragma"` field.
Proposed format:
``` jsonc
@@ -277,7 +279,9 @@ The type of a _source_ is defined by the string value of the mandatory subfield
, "repo": "<foreign_name>" // optional; corresponds to `foreign_repository_name` var
, "map": {"from_name": "to_name"} // optional; corresponds to `import_map` var (option --map)
, "pragma": // optional
- {"absent": true} // corresponds to `absent` var (option --absent)
+ { "absent": true // corresponds to `absent` var (option --absent)
+ , "to_git": true // any imported "file"-repositories will also be "to_git":true
+ }
}
, ...
]
diff --git a/share/man/just-lock-config.5.md b/share/man/just-lock-config.5.md
index f90378ff..5ae901fb 100644
--- a/share/man/just-lock-config.5.md
+++ b/share/man/just-lock-config.5.md
@@ -40,16 +40,19 @@ The following fields are supported:
and its value is used instead.
- *`"map"`* has as value a JSON object with string key-value pairs defining a
- mapping between repository names that would be brought in by this import
+ mapping between repository names that would be brought in by this import
(possibly transitively) and already imported repositories. This mapping can
be used to avoid additional duplications of repositories from multiple
imports. This entry is optional.
- - *`"pragma"`* has as value a JSON object. Currently, it supports the key
- *`"absent"`* with a boolean value; if this field evaluates to `true`, it
- informs that the imported repository and all transitive repositories imported
- as a consequence should have the `{"absent": true}` pragma added to their
- description in the output configuration. This entry is optional.
+ - *`"pragma"`* has as value a JSON object. This entry is optional.
+ If the object contains the `{"absent": true}` object, it informs that the
+ imported repository and all transitive repositories imported as a
+ consequence should have the `{"absent": true}` pragma added to their
+ description.
+ If the object contains the `{"to_git": true}` object, it informs that all
+ `"file"`-type repositories brought in as a consequence of this import should
+ have the `{"to_git": true}` pragma added to their description.
Source objects
--------------
diff --git a/test/end-to-end/just-lock/file-imports.sh b/test/end-to-end/just-lock/file-imports.sh
index 71dc5edc..e61ac834 100644
--- a/test/end-to-end/just-lock/file-imports.sh
+++ b/test/end-to-end/just-lock/file-imports.sh
@@ -77,7 +77,7 @@ cat > repos.in.json <<EOF
}
, "imports":
[ { "source": "file"
- , "repos": [{"alias": "foo"}]
+ , "repos": [{"alias": "foo", "pragma": {"to_git": true}}]
, "path": "${REPO_DIRS}/foo"
}
, { "source": "file"
@@ -94,6 +94,10 @@ echo
"${JUST_LOCK}" -C repos.in.json -o repos.json --local-build-root "${LBR}" 2>&1
cat repos.json
echo
+# Check pragmas for repo "foo" are correctly set
+[ $(jq -r '.repositories.foo.repository.pragma.special' repos.json) = "resolve-completely" ]
+[ $(jq -r '.repositories.foo.repository.pragma.to_git' repos.json) = true ]
+# Check the symlink gets resolved as expected
"${JUST_MR}" -L '["env", "PATH='"${PATH}"'"]' --norc --just "${JUST}" --local-build-root "${LBR}" install -o "${OUT}" 2>&1
echo
cat "${OUT}/out.txt"