Skip to content

Commit 336cf6c

Browse files
committed
node: don't read lockfile version twice
Store the lockfile path and version in their own dataclass for later use when deciding whether to patch same lockfiles.
1 parent 6ee0117 commit 336cf6c

File tree

5 files changed

+64
-36
lines changed

5 files changed

+64
-36
lines changed

node/flatpak_node_generator/package.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,14 @@ class LocalSource(PackageSource):
134134
path: str
135135

136136

137+
@dataclass(frozen=True, eq=True)
138+
class Lockfile:
139+
path: Path
140+
version: int
141+
142+
137143
class Package(NamedTuple):
138144
name: str
139145
version: str
140146
source: PackageSource
141-
lockfile: Path
147+
lockfile: Lockfile

node/flatpak_node_generator/providers/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def parse_git_source(self, version: str, from_: Optional[str] = None) -> GitSour
5050
from_=from_,
5151
)
5252

53-
def process_lockfile(self, lockfile: Path) -> Iterator[Package]:
53+
def process_lockfile(self, lockfile_path: Path) -> Iterator[Package]:
5454
raise NotImplementedError()
5555

5656

node/flatpak_node_generator/providers/npm.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from ..package import (
2727
GitSource,
2828
LocalSource,
29+
Lockfile,
2930
NamedGitSource,
3031
Package,
3132
PackageSource,
@@ -54,7 +55,7 @@ def __init__(self, options: Options):
5455
self.no_devel = options.no_devel
5556

5657
def _process_packages_v1(
57-
self, lockfile: Path, entry: Dict[str, Dict[Any, Any]]
58+
self, lockfile: Lockfile, entry: Dict[str, Dict[Any, Any]]
5859
) -> Iterator[Package]:
5960
for name, info in entry.get('dependencies', {}).items():
6061
if info.get('dev') and self.no_devel:
@@ -95,13 +96,18 @@ def _process_packages_v1(
9596
else:
9697
source = RegistrySource(integrity=integrity)
9798

98-
yield Package(name=name, version=version, source=source, lockfile=lockfile)
99+
yield Package(
100+
name=name,
101+
version=version,
102+
source=source,
103+
lockfile=lockfile,
104+
)
99105

100106
if 'dependencies' in info:
101107
yield from self._process_packages_v1(lockfile, info)
102108

103109
def _process_packages_v2(
104-
self, lockfile: Path, entry: Dict[str, Dict[Any, Any]]
110+
self, lockfile: Lockfile, entry: Dict[str, Dict[Any, Any]]
105111
) -> Iterator[Package]:
106112
for install_path, info in entry.get('packages', {}).items():
107113
if (info.get('dev') or info.get('devOptional')) and self.no_devel:
@@ -151,20 +157,20 @@ def _process_packages_v2(
151157
source=source,
152158
)
153159

154-
def process_lockfile(self, lockfile: Path) -> Iterator[Package]:
155-
with open(lockfile) as fp:
160+
def process_lockfile(self, lockfile_path: Path) -> Iterator[Package]:
161+
with open(lockfile_path) as fp:
156162
data = json.load(fp)
157163

164+
lockfile = Lockfile(lockfile_path, data['lockfileVersion'])
165+
158166
# TODO Once lockfile v2 syntax support is complete, use _process_packages_v2
159167
# for both v2 and v2 lockfiles
160-
if data['lockfileVersion'] in {1, 2}:
168+
if lockfile.version in {1, 2}:
161169
yield from self._process_packages_v1(lockfile, data)
162-
elif data['lockfileVersion'] in {3}:
170+
elif lockfile.version in {3}:
163171
yield from self._process_packages_v2(lockfile, data)
164172
else:
165-
raise NotImplementedError(
166-
f'Unknown lockfile version {data["lockfileVersion"]}'
167-
)
173+
raise NotImplementedError(f'Unknown lockfile version {lockfile.version}')
168174

169175

170176
class NpmRCFileProvider(RCFileProvider):
@@ -202,11 +208,11 @@ def __init__(
202208
str, asyncio.Future[NpmModuleProvider.RegistryPackageIndex]
203209
] = {}
204210
self.index_entries: Dict[Path, str] = {}
205-
self.all_lockfiles: Set[Path] = set()
211+
self.all_lockfiles: Set[Lockfile] = set()
206212
# Mapping of lockfiles to a dict of the Git source target paths and
207213
# NamedGitSource objects (package name + GitSource)
208214
self.git_sources: DefaultDict[
209-
Path, Dict[Path, NamedGitSource]
215+
Lockfile, Dict[Path, NamedGitSource]
210216
] = collections.defaultdict(lambda: {})
211217
# FIXME better pass the same provider object we created in main
212218
self.rcfile_provider = NpmRCFileProvider()
@@ -433,7 +439,7 @@ def get_lockfile_rc(self, lockfile: Path) -> Dict[str, str]:
433439

434440
def get_package_registry(self, package: Package) -> str:
435441
assert isinstance(package.source, RegistrySource)
436-
rc = self.get_lockfile_rc(package.lockfile)
442+
rc = self.get_lockfile_rc(package.lockfile.path)
437443
if rc and '/' in package.name:
438444
scope, _ = package.name.split('/', maxsplit=1)
439445
if f'{scope}:registry' in rc:
@@ -493,16 +499,13 @@ def _finalize(self) -> None:
493499
}
494500

495501
for lockfile, sources in self.git_sources.items():
496-
prefix = self.relative_lockfile_dir(lockfile)
502+
prefix = self.relative_lockfile_dir(lockfile.path)
497503
data: Dict[str, Dict[str, str]] = {
498504
'package.json': {},
499505
'package-lock.json': {},
500506
}
501507

502-
with open(lockfile) as fp:
503-
lockfile_v1 = json.load(fp)['lockfileVersion'] == 1
504-
505-
if lockfile_v1:
508+
if lockfile.version == 1:
506509
for path, named_git_source in sources.items():
507510
GIT_URL_PREFIX = 'git+'
508511
new_version = f'{path}#{named_git_source.git_source.commit}'
@@ -530,25 +533,27 @@ def _finalize(self) -> None:
530533
.replace('\n', '')
531534
)
532535
json_data = json.dumps(data[filename])
533-
patch_commands[lockfile].append(
536+
patch_commands[lockfile.path].append(
534537
'jq'
535538
' --arg buildroot "$FLATPAK_BUILDER_BUILDDIR"'
536539
f' --argjson data {shlex.quote(json_data)}'
537540
f' {shlex.quote(script)} {target}'
538541
f' > {target}.new'
539542
)
540-
patch_commands[lockfile].append(f'mv {target}{{.new,}}')
543+
patch_commands[lockfile.path].append(f'mv {target}{{.new,}}')
541544

542545
if len(patch_commands) > 0:
543546
patch_all_commands: List[str] = []
544547
for lockfile in self.all_lockfiles:
545548
patch_dest = (
546-
self.gen.data_root / 'patch' / self.relative_lockfile_dir(lockfile)
549+
self.gen.data_root
550+
/ 'patch'
551+
/ self.relative_lockfile_dir(lockfile.path)
547552
)
548553
# Don't use with_extension to avoid problems if the package has a . in its name.
549554
patch_dest = patch_dest.with_name(patch_dest.name + '.sh')
550555

551-
self.gen.add_script_source(patch_commands[lockfile], patch_dest)
556+
self.gen.add_script_source(patch_commands[lockfile.path], patch_dest)
552557
patch_all_commands.append(f'"$FLATPAK_BUILDER_BUILDDIR"/{patch_dest}')
553558

554559
patch_all_dest = self.gen.data_root / 'patch-all.sh'

node/flatpak_node_generator/providers/yarn.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@
99

1010
from ..integrity import Integrity
1111
from ..manifest import ManifestGenerator
12-
from ..package import GitSource, LocalSource, Package, PackageSource, ResolvedSource
12+
from ..package import (
13+
GitSource,
14+
LocalSource,
15+
Lockfile,
16+
Package,
17+
PackageSource,
18+
ResolvedSource,
19+
)
1320
from . import LockfileProvider, ModuleProvider, ProviderFactory, RCFileProvider
1421
from .npm import NpmRCFileProvider
1522
from .special import SpecialSourceProvider
@@ -78,7 +85,7 @@ def unquote(self, string: str) -> str:
7885
return string
7986

8087
def process_package(
81-
self, lockfile: Path, name_line: str, entry: Dict[str, Any]
88+
self, lockfile: Lockfile, name_line: str, entry: Dict[str, Any]
8289
) -> Package:
8390
assert name_line and entry
8491

@@ -99,12 +106,16 @@ def process_package(
99106
source = ResolvedSource(resolved=entry['resolved'], integrity=integrity)
100107

101108
return Package(
102-
name=name, version=entry['version'], source=source, lockfile=lockfile
109+
name=name,
110+
version=entry['version'],
111+
source=source,
112+
lockfile=lockfile,
103113
)
104114

105-
def process_lockfile(self, lockfile: Path) -> Iterator[Package]:
106-
for name_line, package in self.parse_lockfile(lockfile).items():
107-
yield self.process_package(lockfile, name_line, package)
115+
def process_lockfile(self, lockfile_path: Path) -> Iterator[Package]:
116+
for name_line, package in self.parse_lockfile(lockfile_path).items():
117+
# only lockfile v1 supported
118+
yield self.process_package(Lockfile(lockfile_path, 1), name_line, package)
108119

109120

110121
class YarnRCFileProvider(RCFileProvider):
@@ -161,7 +172,9 @@ async def generate_package(self, package: Package) -> None:
161172
)
162173

163174
elif isinstance(source, LocalSource):
164-
assert (package.lockfile.parent / source.path / 'package.json').is_file()
175+
assert (
176+
package.lockfile.path.parent / source.path / 'package.json'
177+
).is_file()
165178

166179
else:
167180
raise NotImplementedError(

node/tests/test_yarn.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
from pathlib import Path
22

3-
from conftest import ProviderFactorySpec
43
from flatpak_node_generator.integrity import Integrity
5-
from flatpak_node_generator.package import GitSource, Package, ResolvedSource
4+
from flatpak_node_generator.package import (
5+
GitSource,
6+
Lockfile,
7+
Package,
8+
ResolvedSource,
9+
)
610
from flatpak_node_generator.providers.yarn import YarnLockfileProvider
711

812
TEST_LOCKFILE = """
@@ -37,10 +41,10 @@
3741
def test_lockfile_parsing(tmp_path: Path) -> None:
3842
lockfile_provider = YarnLockfileProvider()
3943

40-
yarn_lock = tmp_path / 'yarn.lock'
41-
yarn_lock.write_text(TEST_LOCKFILE)
44+
yarn_lock = Lockfile(tmp_path / 'yarn.lock', 1)
45+
yarn_lock.path.write_text(TEST_LOCKFILE)
4246

43-
packages = list(lockfile_provider.process_lockfile(yarn_lock))
47+
packages = list(lockfile_provider.process_lockfile(yarn_lock.path))
4448

4549
assert packages == [
4650
Package(

0 commit comments

Comments
 (0)