UEPyScripts 1.4.2__tar.gz → 1.4.3__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 (37) hide show
  1. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/PKG-INFO +1 -1
  2. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ugs/git_utils.py +110 -68
  3. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/.gitignore +0 -0
  4. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/LICENSE +0 -0
  5. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/README.md +0 -0
  6. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/pyproject.toml +0 -0
  7. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/__init__.py +0 -0
  8. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/context/__init__.py +0 -0
  9. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/internal/__init__.py +0 -0
  10. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/internal/config.py +0 -0
  11. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/internal/engine.py +0 -0
  12. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/internal/engine_resolver.py +0 -0
  13. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/internal/project.py +0 -0
  14. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/py.typed +0 -0
  15. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/run/__init__.py +0 -0
  16. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/run/buildgraph.py +0 -0
  17. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/run/uat.py +0 -0
  18. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/run/ubt.py +0 -0
  19. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/__init__.py +0 -0
  20. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ci/buildgraph.py +0 -0
  21. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ci/cleanup.py +0 -0
  22. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/helpers.py +0 -0
  23. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/subprocess.py +0 -0
  24. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/__init__.py +0 -0
  25. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/check_engine_installation.py +0 -0
  26. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/close_editor.py +0 -0
  27. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/compile_editor.py +0 -0
  28. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/engine_installation/engine_destination.py +0 -0
  29. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/engine_installation/engine_installer.py +0 -0
  30. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/engine_installation/engine_source.py +0 -0
  31. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/generate_solution.py +0 -0
  32. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ue/run_editor.py +0 -0
  33. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ugs/cleanup.py +0 -0
  34. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ugs/pull.py +0 -0
  35. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ugs/push.py +0 -0
  36. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/ugs/ugs_types.py +0 -0
  37. {uepyscripts-1.4.2 → uepyscripts-1.4.3}/src/uepyscripts/tools/winreg.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: UEPyScripts
3
- Version: 1.4.2
3
+ Version: 1.4.3
4
4
  Summary: Collection of Python tools and helpers designed to automate common Unreal Engine project tasks (builds, packaging, editor control, CI tasks, etc.).
5
5
  Project-URL: Changelog, https://github.com/TheEmidee/UEPyScripts/releases
6
6
  Project-URL: Homepage, https://github.com/TheEmidee/UEPyScripts
@@ -1,68 +1,110 @@
1
- import os
2
- import subprocess
3
- from pathlib import Path
4
-
5
- from uepyscripts import logger
6
-
7
- ANCESTRY_LOOKBACK = 2000
8
-
9
-
10
- def get_current_sha(cwd: Path) -> str:
11
- sha = os.environ.get("GIT_COMMIT") # Jenkins sets this automatically
12
- if sha:
13
- return sha
14
- return subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=cwd, text=True).strip()
15
-
16
-
17
- def get_current_branch(cwd: Path) -> str:
18
- branch = os.environ.get("GIT_BRANCH") # Jenkins' Git plugin sets this, sometimes as "origin/<branch>"
19
- if branch:
20
- return branch.split("/", 1)[1] if "/" in branch else branch
21
-
22
- branch = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd, text=True).strip()
23
- if branch != "HEAD":
24
- return branch
25
-
26
- # Detached HEAD (e.g. a CI checkout of an explicit ref rather than a
27
- # tracked branch, with no GIT_BRANCH env var set either) — fall back to
28
- # whichever local or remote-tracking ref currently points at this commit.
29
- refs = subprocess.check_output(
30
- ["git", "for-each-ref", "--points-at=HEAD", "--format=%(refname:short)", "refs/heads/", "refs/remotes/"],
31
- cwd=cwd,
32
- text=True,
33
- ).splitlines()
34
- for ref in refs:
35
- return ref.split("/", 1)[1] if "/" in ref else ref
36
-
37
- logger.warning("Could not resolve current branch: HEAD is detached and no ref points at it")
38
- return branch
39
-
40
-
41
- def get_local_ancestry(cwd: Path, limit: int = ANCESTRY_LOOKBACK) -> list[str]:
42
- out = subprocess.check_output(["git", "log", f"-{limit}", "--format=%H", "HEAD"], cwd=cwd, text=True)
43
- return out.splitlines()
44
-
45
-
46
- def get_remote_reachable_shas(cwd: Path, remote: str = "origin") -> set[str]:
47
- """All commit SHAs reachable from any current branch tip on `remote`, after
48
- pruning local remote-tracking refs for branches deleted on the remote."""
49
- subprocess.run(["git", "fetch", "--prune", remote], cwd=cwd, check=True, capture_output=True, text=True)
50
- out = subprocess.check_output(["git", "rev-list", f"--remotes={remote}"], cwd=cwd, text=True)
51
- return set(out.splitlines())
52
-
53
-
54
- def resolve_nearest_published_ancestor(index: list[str], ancestry: list[str]) -> tuple[str | None, bool]:
55
- """Finds the nearest ancestor SHA (including HEAD itself) present in the
56
- index. Returns None if nothing has ever been published reachable from HEAD
57
- within the walked ancestry. The bool is True when the match was found by
58
- walking the ancestry itself (an exact match), False when falling back to
59
- the most recent published version because nothing in the ancestry matched."""
60
- index_set = set(index)
61
- for sha in ancestry:
62
- if sha in index_set:
63
- return sha, True
64
-
65
- if index:
66
- return index[-1], False
67
-
68
- return None, True
1
+ import os
2
+ import subprocess
3
+ from pathlib import Path
4
+
5
+ from uepyscripts import logger
6
+
7
+ ANCESTRY_LOOKBACK = 500
8
+
9
+
10
+ def get_current_sha(cwd: Path) -> str:
11
+ sha = os.environ.get("GIT_COMMIT") # Jenkins sets this automatically
12
+ if sha:
13
+ return sha
14
+ return subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=cwd, text=True).strip()
15
+
16
+
17
+ def get_current_branch(cwd: Path) -> str:
18
+ branch = os.environ.get("GIT_BRANCH") # Jenkins' Git plugin sets this, sometimes as "origin/<branch>"
19
+ if branch:
20
+ return branch.split("/", 1)[1] if "/" in branch else branch
21
+
22
+ branch = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd, text=True).strip()
23
+ if branch != "HEAD":
24
+ return branch
25
+
26
+ # Detached HEAD (e.g. a CI checkout of an explicit ref rather than a
27
+ # tracked branch, with no GIT_BRANCH env var set either) — fall back to
28
+ # whichever local or remote-tracking ref currently points at this commit.
29
+ refs = subprocess.check_output(
30
+ ["git", "for-each-ref", "--points-at=HEAD", "--format=%(refname:short)", "refs/heads/", "refs/remotes/"],
31
+ cwd=cwd,
32
+ text=True,
33
+ ).splitlines()
34
+ for ref in refs:
35
+ return ref.split("/", 1)[1] if "/" in ref else ref
36
+
37
+ logger.warning("Could not resolve current branch: HEAD is detached and no ref points at it")
38
+ return branch
39
+
40
+
41
+ def is_shallow_repository(cwd: Path) -> bool:
42
+ out = subprocess.check_output(["git", "rev-parse", "--is-shallow-repository"], cwd=cwd, text=True).strip()
43
+ return out == "true"
44
+
45
+
46
+ def deepen_shallow_history(cwd: Path, limit: int, remote: str = "origin") -> bool:
47
+ """Pulls down the commits missing from a shallow checkout, and only the
48
+ commits: `--filter=tree:0` keeps trees and blobs on the server, so this
49
+ stays a metadata-sized fetch even on a repository the size of an engine
50
+ tree. Returns False (after logging) when the remote refuses, so callers
51
+ can carry on with whatever history is available locally."""
52
+ try:
53
+ subprocess.run(
54
+ ["git", "fetch", "--no-tags", "--filter=tree:0", f"--deepen={limit}", remote],
55
+ cwd=cwd,
56
+ check=True,
57
+ capture_output=True,
58
+ text=True,
59
+ )
60
+ return True
61
+ except subprocess.CalledProcessError as e:
62
+ reason = e.stderr.strip() or e
63
+ logger.warning(f"Could not deepen shallow history from '{remote}' ({reason}); ancestry walking is limited to the local history")
64
+ return False
65
+
66
+
67
+ def get_local_ancestry(cwd: Path, limit: int = ANCESTRY_LOOKBACK) -> list[str]:
68
+ ancestry = _log_ancestry(cwd, limit)
69
+
70
+ # CI checkouts are typically shallow clones (Jenkins' cloneOption(depth: 1)),
71
+ # where HEAD is a grafted boundary commit: `git log HEAD` stops at HEAD
72
+ # itself and every already-published parent looks unreachable, which would
73
+ # downgrade an incremental publish into a full fresh sync. Deepen first so
74
+ # the walk sees the real ancestry.
75
+ if len(ancestry) < limit and is_shallow_repository(cwd):
76
+ logger.info(f"Shallow checkout detected ({len(ancestry)} commit(s) available); deepening history to {limit} commits")
77
+ if deepen_shallow_history(cwd, limit):
78
+ ancestry = _log_ancestry(cwd, limit)
79
+
80
+ return ancestry
81
+
82
+
83
+ def _log_ancestry(cwd: Path, limit: int) -> list[str]:
84
+ out = subprocess.check_output(["git", "log", f"-{limit}", "--format=%H", "HEAD"], cwd=cwd, text=True)
85
+ return out.splitlines()
86
+
87
+
88
+ def get_remote_reachable_shas(cwd: Path, remote: str = "origin") -> set[str]:
89
+ """All commit SHAs reachable from any current branch tip on `remote`, after
90
+ pruning local remote-tracking refs for branches deleted on the remote."""
91
+ subprocess.run(["git", "fetch", "--prune", remote], cwd=cwd, check=True, capture_output=True, text=True)
92
+ out = subprocess.check_output(["git", "rev-list", f"--remotes={remote}"], cwd=cwd, text=True)
93
+ return set(out.splitlines())
94
+
95
+
96
+ def resolve_nearest_published_ancestor(index: list[str], ancestry: list[str]) -> tuple[str | None, bool]:
97
+ """Finds the nearest ancestor SHA (including HEAD itself) present in the
98
+ index. Returns None if nothing has ever been published reachable from HEAD
99
+ within the walked ancestry. The bool is True when the match was found by
100
+ walking the ancestry itself (an exact match), False when falling back to
101
+ the most recent published version because nothing in the ancestry matched."""
102
+ index_set = set(index)
103
+ for sha in ancestry:
104
+ if sha in index_set:
105
+ return sha, True
106
+
107
+ if index:
108
+ return index[-1], False
109
+
110
+ return None, True
File without changes
File without changes
File without changes
File without changes