Skip to content

Commit e744eb8

Browse files
committed
improve error handling for Flutter version retrieval and streamline version fetching logic
1 parent e9f2e4c commit e744eb8

File tree

4 files changed

+98
-111
lines changed

4 files changed

+98
-111
lines changed

.github/scripts/read_fvmrc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ def main() -> None:
1414
with open(sys.argv[1], encoding="utf-8") as f:
1515
v = json.load(f)["flutter"].strip()
1616
if not v:
17-
raise ValueError("Empty 'flutter' value in .fvmrc")
17+
raise ValueError("Empty or missing 'flutter' value")
1818
print(v)
1919
except Exception as e:
20-
print(f"Error parsing {sys.argv[1]}: {e}", file=sys.stderr)
20+
print(f"Error parsing {sys.argv[1]!r}: {e}", file=sys.stderr)
2121
sys.exit(1)
2222

2323

sdk/python/packages/flet-cli/src/flet_cli/commands/build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None:
2222
parser.add_argument(
2323
"--flutter-version",
2424
action="version",
25-
version=flet.version.get_flutter_version() or "Unknown",
25+
version=flet.version.FLUTTER_VERSION,
2626
help="Print the required Flutter SDK version and exit.",
2727
)
2828
parser.add_argument(

sdk/python/packages/flet-cli/src/flet_cli/commands/flutter_base.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,13 @@
1414
from rich.style import Style
1515
from rich.theme import Theme
1616

17-
import flet.version as flet_version
17+
import flet.version
1818
import flet_cli.utils.processes as processes
1919
from flet.utils import cleanup_path, is_windows
2020
from flet.utils.platform_utils import get_bool_env_var
2121
from flet_cli.commands.base import BaseCommand
2222
from flet_cli.utils.flutter import get_flutter_dir, install_flutter
2323

24-
25-
def get_flutter_version() -> Optional[version.Version]:
26-
flutter_version_str = flet_version.get_flutter_version()
27-
if not flutter_version_str:
28-
return None
29-
return version.Version(flutter_version_str)
30-
31-
3224
no_rich_output = get_bool_env_var("FLET_CLI_NO_RICH_OUTPUT")
3325

3426
error_style = Style(color="red", bold=True)
@@ -104,12 +96,12 @@ def handle(self, options: argparse.Namespace) -> None:
10496

10597
def initialize_command(self):
10698
assert self.options
107-
self.required_flutter_version = get_flutter_version()
108-
if not self.required_flutter_version:
99+
self.required_flutter_version = version.Version(flet.version.FLUTTER_VERSION)
100+
if self.required_flutter_version == version.Version("0"):
109101
self.cleanup(
110102
1,
111-
"Cannot determine required Flutter SDK version. "
112-
"In a development checkout ensure `.fvmrc` exists.",
103+
"Unable to determine the required Flutter SDK version. "
104+
"If in a source checkout, ensure a valid `.fvmrc` file exists.",
113105
)
114106

115107
self.emojis = {
@@ -138,9 +130,8 @@ def initialize_command(self):
138130
style=warning_style,
139131
)
140132
prompt = (
141-
"Flutter SDK "
142-
f"{self.required_flutter_version} is required. It will be installed now. "
143-
"Proceed? [y/n] "
133+
f"Flutter SDK {self.required_flutter_version} is required. "
134+
f"It will be installed now. Proceed? [y/n] "
144135
)
145136

146137
if not self._prompt_input(prompt):
@@ -240,7 +231,8 @@ def install_flutter(self):
240231

241232
if self.verbose > 0:
242233
console.log(
243-
f"Flutter {self.required_flutter_version} installed {self.emojis['checkmark']}"
234+
f"Flutter {self.required_flutter_version} "
235+
f"installed {self.emojis['checkmark']}"
244236
)
245237

246238
def install_jdk(self):
Lines changed: 86 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""Provide the current Flet version."""
22

33
import json
4-
import os
54
import subprocess as sp
65
from pathlib import Path
76
from typing import Optional
@@ -13,19 +12,31 @@
1312
"PYODIDE_VERSION",
1413
"find_repo_root",
1514
"from_git",
15+
"get_flet_version",
1616
"get_flutter_version",
1717
"version",
1818
]
1919

2020
# set by CI
2121
version = ""
22+
"""
23+
The Flet version in use.
24+
25+
This value is set explicitly in CI for released packages. When running from
26+
source and no version is provided, it is derived from the nearest Git tag
27+
when available.
28+
"""
2229

2330

2431
# set by CI
2532
FLUTTER_VERSION = ""
2633
"""
2734
The Flutter SDK version used when building the flet client or packaging
2835
apps with [`flet build`](https://docs.flet.dev/cli/flet-build/).
36+
37+
This value is set explicitly in CI for released packages. When running from
38+
source and no version is provided, it is resolved from the repository's
39+
`.fvmrc` file when available.
2940
"""
3041

3142
PYODIDE_VERSION = "0.27.7"
@@ -35,90 +46,33 @@
3546
"""
3647

3748

38-
def _find_upwards(start_dir: Path, file_name: str) -> Optional[Path]:
39-
current_dir = start_dir.resolve()
40-
while current_dir != current_dir.parent:
41-
candidate = current_dir / file_name
42-
if candidate.is_file():
43-
return candidate
44-
current_dir = current_dir.parent
45-
return None
46-
47-
48-
def _flutter_version_from_fvmrc(fvmrc_path: Path) -> Optional[str]:
49-
try:
50-
raw = fvmrc_path.read_text(encoding="utf-8").strip()
51-
except OSError:
52-
return None
53-
if not raw:
49+
def from_git() -> Optional[str]:
50+
"""Try to get the version from Git tags."""
51+
repo_root = find_repo_root(Path(__file__).resolve().parent)
52+
if not repo_root:
5453
return None
55-
try:
56-
data = json.loads(raw)
57-
except json.JSONDecodeError:
58-
return raw.strip().strip('"')
59-
if isinstance(data, dict):
60-
value = data.get("flutter")
61-
if isinstance(value, str) and value.strip():
62-
return value.strip()
63-
return None
64-
65-
66-
def get_flutter_version() -> str:
67-
"""
68-
Return the required Flutter SDK version.
69-
70-
In CI/release builds the value is stamped into `FLUTTER_VERSION`.
71-
In a local development checkout (where `FLUTTER_VERSION == ""`), it is
72-
resolved from the repository's `.fvmrc`.
73-
"""
74-
75-
if FLUTTER_VERSION:
76-
return FLUTTER_VERSION
77-
78-
start_dirs = [Path.cwd(), Path(__file__).resolve().parent]
79-
for start_dir in start_dirs:
80-
fvmrc_path = _find_upwards(start_dir, ".fvmrc")
81-
if fvmrc_path:
82-
v = _flutter_version_from_fvmrc(fvmrc_path)
83-
if v:
84-
return v
85-
return ""
8654

55+
git_cmd = "git.exe" if is_windows() else "git"
56+
if not which(git_cmd):
57+
return None
8758

88-
def from_git() -> Optional[str]:
89-
"""Try to get the version from Git tags."""
90-
working = Path().absolute()
9159
try:
92-
repo_root = find_repo_root(Path(__file__).resolve().parent)
60+
result = sp.run(
61+
[git_cmd, "describe", "--abbrev=0"],
62+
cwd=repo_root,
63+
capture_output=True,
64+
text=True,
65+
check=True,
66+
)
67+
tag = result.stdout.strip()
68+
return tag[1:] if tag.startswith("v") else tag
69+
70+
except sp.CalledProcessError as e:
71+
# Git is present but no tags / not a valid repo state
72+
print(f"Error getting Git version: {e}")
73+
except OSError as e:
74+
print(f"Error running Git: {e}")
9375

94-
if repo_root:
95-
os.chdir(repo_root)
96-
in_repo = (
97-
which("git.exe" if is_windows() else "git")
98-
and sp.run(
99-
["git", "status"],
100-
capture_output=True,
101-
text=True,
102-
).returncode
103-
== 0
104-
)
105-
106-
if in_repo:
107-
try:
108-
git_p = sp.run(
109-
["git", "describe", "--abbrev=0"],
110-
capture_output=True,
111-
text=True,
112-
check=True, # Raise an exception for non-zero exit codes
113-
)
114-
tag = git_p.stdout.strip()
115-
return tag[1:] if tag.startswith("v") else tag
116-
except sp.CalledProcessError as e:
117-
print(f"Error getting Git version: {e}")
118-
except FileNotFoundError:
119-
print("Git command not found.")
120-
finally:
121-
os.chdir(working)
12276
return None
12377

12478

@@ -132,16 +86,57 @@ def find_repo_root(start_path: Path) -> Optional[Path]:
13286
return None
13387

13488

135-
DEFAULT_FLET_VERSION = "0.1.0"
89+
def get_flet_version() -> str:
90+
"""Return the Flet version, falling back to Git or a default if needed."""
91+
92+
# If the version is already set (e.g., replaced by CI), use it
93+
if version:
94+
return version
95+
96+
# Only try to get the version from Git if the pre-set version is empty.
97+
# This is more likely to happen in a development/source environment.
98+
if not is_mobile():
99+
git_version = from_git()
100+
if git_version:
101+
return git_version # Use Git version if available
102+
103+
# If 'version' is still empty after the above (e.g., in a built package
104+
# where CI didn't replace it), fall back to the default version.
105+
# CI replacement is the standard way for packaged versions.
106+
return "0.1.0"
107+
108+
109+
def get_flutter_version() -> str:
110+
"""
111+
Return the Flutter SDK version.
112+
113+
Uses `FLUTTER_VERSION` when set (CI/release builds); otherwise resolves it
114+
from `.fvmrc` in a local development checkout.
115+
"""
116+
117+
# If the version is already set (e.g., replaced by CI), use it
118+
if FLUTTER_VERSION:
119+
return FLUTTER_VERSION
120+
121+
if not is_mobile():
122+
repo_root = find_repo_root(Path(__file__).resolve().parent)
123+
if repo_root:
124+
fvmrc_path = repo_root / ".fvmrc"
125+
try:
126+
v = json.loads(fvmrc_path.read_text(encoding="utf-8"))[
127+
"flutter"
128+
].strip()
129+
if not v:
130+
raise ValueError("Empty or missing 'flutter' value")
131+
return v
132+
except Exception as e:
133+
print(f"Error parsing {fvmrc_path!r}: {e}")
134+
135+
# If 'FLUTTER_VERSION' is still empty after the above (e.g., in a built package
136+
# where CI didn't replace it), fall back to the below default.
137+
# CI replacement is the standard way for packaged versions.
138+
return "0"
136139

137-
if not version and not is_mobile():
138-
# Only try to get the version from Git if the pre-set version is empty
139-
# This is more likely to happen in a development/source environment
140-
version = from_git() or DEFAULT_FLET_VERSION # Fallback to default if Git fails
141140

142-
# If 'version' is still empty after the above (e.g., in a built package
143-
# where CI didn't replace it), it might be appropriate to have another
144-
# default or a way to set it during the build process. However, the
145-
# CI replacement is the standard way for packaged versions.
146-
if not version:
147-
version = DEFAULT_FLET_VERSION # Final fallback
141+
version = get_flet_version()
142+
FLUTTER_VERSION = get_flutter_version()

0 commit comments

Comments
 (0)