Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
63d6ec56
Unverified
Commit
63d6ec56
authored
Mar 24, 2021
by
Jenn Magder
Committed by
GitHub
Mar 24, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate deferred_components_validator to null safety (#78934)
parent
ce31d4ff
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
56 additions
and
31 deletions
+56
-31
deferred_components_gen_snapshot_validator.dart
...c/android/deferred_components_gen_snapshot_validator.dart
+1
-1
deferred_components_prebuild_validator.dart
...b/src/android/deferred_components_prebuild_validator.dart
+3
-2
deferred_components_validator.dart
..._tools/lib/src/android/deferred_components_validator.dart
+13
-13
deferred_component.dart
packages/flutter_tools/lib/src/base/deferred_component.dart
+10
-14
build_system.dart
...ages/flutter_tools/lib/src/build_system/build_system.dart
+7
-0
bundle.dart
packages/flutter_tools/lib/src/bundle.dart
+1
-0
assemble.dart
packages/flutter_tools/lib/src/commands/assemble.dart
+1
-0
build_appbundle.dart
packages/flutter_tools/lib/src/commands/build_appbundle.dart
+1
-0
build_ios_framework.dart
...s/flutter_tools/lib/src/commands/build_ios_framework.dart
+1
-0
packages.dart
packages/flutter_tools/lib/src/commands/packages.dart
+2
-0
resident_runner.dart
packages/flutter_tools/lib/src/resident_runner.dart
+1
-0
flutter_command.dart
packages/flutter_tools/lib/src/runner/flutter_command.dart
+1
-0
compile.dart
packages/flutter_tools/lib/src/web/compile.dart
+1
-0
deferred_components_gen_snapshot_validator_test.dart
...roid/deferred_components_gen_snapshot_validator_test.dart
+2
-0
deferred_components_prebuild_validator_test.dart
.../android/deferred_components_prebuild_validator_test.dart
+11
-1
No files found.
packages/flutter_tools/lib/src/android/deferred_components_gen_snapshot_validator.dart
View file @
63d6ec56
...
...
@@ -33,7 +33,7 @@ class DeferredComponentsGenSnapshotValidator extends DeferredComponentsValidator
DeferredComponentsGenSnapshotValidator
(
this
.
env
,
{
bool
exitOnFail
=
true
,
String
title
,
})
:
super
(
env
.
projectDir
,
env
.
logger
,
exitOnFail:
exitOnFail
,
title:
title
);
})
:
super
(
env
.
projectDir
,
env
.
logger
,
e
nv
.
platform
,
e
xitOnFail:
exitOnFail
,
title:
title
);
/// The build environment that should be used to find the input files to run
/// checks against.
...
...
packages/flutter_tools/lib/src/android/deferred_components_prebuild_validator.dart
View file @
63d6ec56
...
...
@@ -11,6 +11,7 @@ import '../base/deferred_component.dart';
import
'../base/error_handling_io.dart'
;
import
'../base/file_system.dart'
;
import
'../base/logger.dart'
;
import
'../base/platform.dart'
;
import
'../globals.dart'
as
globals
;
import
'../project.dart'
;
import
'../template.dart'
;
...
...
@@ -31,12 +32,12 @@ class DeferredComponentsPrebuildValidator extends DeferredComponentsValidator {
/// When [exitOnFail] is set to true, the [handleResults] and [attemptToolExit]
/// methods will exit the tool when this validator detects a recommended
/// change. This defaults to true.
DeferredComponentsPrebuildValidator
(
Directory
projectDir
,
Logger
logger
,
{
DeferredComponentsPrebuildValidator
(
Directory
projectDir
,
Logger
logger
,
Platform
platform
,
{
bool
exitOnFail
=
true
,
String
title
,
Directory
templatesDir
,
})
:
_templatesDir
=
templatesDir
,
super
(
projectDir
,
logger
,
exitOnFail:
exitOnFail
,
title:
title
);
super
(
projectDir
,
logger
,
platform
,
exitOnFail:
exitOnFail
,
title:
title
);
final
Directory
_templatesDir
;
...
...
packages/flutter_tools/lib/src/android/deferred_components_validator.dart
View file @
63d6ec56
...
...
@@ -2,14 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'../base/common.dart'
;
import
'../base/deferred_component.dart'
;
import
'../base/file_system.dart'
;
import
'../base/logger.dart'
;
import
'../base/platform.dart'
;
import
'../base/terminal.dart'
;
import
'../globals.dart'
as
globals
;
/// A class to configure and run deferred component setup verification checks
/// and tasks.
...
...
@@ -21,9 +19,9 @@ import '../globals.dart' as globals;
/// The results of each check are handled internally as they are not meant to
/// be run isolated.
abstract
class
DeferredComponentsValidator
{
DeferredComponentsValidator
(
this
.
projectDir
,
this
.
logger
,
{
DeferredComponentsValidator
(
this
.
projectDir
,
this
.
logger
,
this
.
platform
,
{
this
.
exitOnFail
=
true
,
String
title
,
String
?
title
,
})
:
outputDir
=
projectDir
.
childDirectory
(
'build'
)
.
childDirectory
(
kDeferredComponentsTempDirectory
),
...
...
@@ -38,6 +36,8 @@ abstract class DeferredComponentsValidator {
/// Logger to use for [displayResults] output.
final
Logger
logger
;
final
Platform
platform
;
/// When true, failed checks and tasks will result in [attemptToolExit]
/// triggering [throwToolExit].
final
bool
exitOnFail
;
...
...
@@ -74,7 +74,7 @@ abstract class DeferredComponentsValidator {
final
List
<
String
>
diffLines
;
/// Tracks the new and missing loading units.
Map
<
String
,
dynamic
>
loadingUnitComparisonResults
;
Map
<
String
,
dynamic
>
?
loadingUnitComparisonResults
;
/// All files read by the validator.
final
List
<
File
>
inputs
;
...
...
@@ -91,7 +91,7 @@ abstract class DeferredComponentsValidator {
bool
get
changesNeeded
=>
generatedFiles
.
isNotEmpty
||
modifiedFiles
.
isNotEmpty
||
invalidFiles
.
isNotEmpty
||
(
loadingUnitComparisonResults
!=
null
&&
!(
loadingUnitComparisonResults
[
'match'
]
as
bool
));
||
(
loadingUnitComparisonResults
!=
null
&&
!(
loadingUnitComparisonResults
!
[
'match'
]
as
bool
));
/// Handles the results of all executed checks by calling [displayResults] and
/// [attemptToolExit].
...
...
@@ -163,7 +163,7 @@ abstract class DeferredComponentsValidator {
The above files have been placed into `build/
$kDeferredComponentsTempDirectory
`,
a temporary directory. The files should be reviewed and moved into the project'
s
`
android
`
directory
.
''');
if (diffLines != null && diffLines.isNotEmpty && !
globals.
platform.isWindows) {
if (diffLines != null && diffLines.isNotEmpty && !platform.isWindows) {
logger.printStatus(r'''
The
recommended
changes
can
be
quickly
applied
by
running:
...
...
@@ -175,21 +175,21 @@ The recommended changes can be quickly applied by running:
}
// Log loading unit golden changes, if any.
if (loadingUnitComparisonResults != null) {
if ((loadingUnitComparisonResults['
new
'] as List<LoadingUnit>).isNotEmpty) {
if ((loadingUnitComparisonResults
!
['
new
'] as List<LoadingUnit>).isNotEmpty) {
logger.printStatus('
New
loading
units
were
found:
', emphasis: true);
for (final LoadingUnit unit in loadingUnitComparisonResults['
new
'] as List<LoadingUnit>) {
for (final LoadingUnit unit in loadingUnitComparisonResults
!
['
new
'] as List<LoadingUnit>) {
logger.printStatus(unit.toString(), color: TerminalColor.grey, indent: 2);
}
logger.printStatus('');
}
if ((loadingUnitComparisonResults['
missing
'] as Set<LoadingUnit>).isNotEmpty) {
if ((loadingUnitComparisonResults
!
['
missing
'] as Set<LoadingUnit>).isNotEmpty) {
logger.printStatus('
Previously
existing
loading
units
no
longer
exist:
', emphasis: true);
for (final LoadingUnit unit in loadingUnitComparisonResults['
missing
'] as Set<LoadingUnit>) {
for (final LoadingUnit unit in loadingUnitComparisonResults
!
['
missing
'] as Set<LoadingUnit>) {
logger.printStatus(unit.toString(), color: TerminalColor.grey, indent: 2);
}
logger.printStatus('');
}
if (loadingUnitComparisonResults['
match
'] as bool) {
if (loadingUnitComparisonResults
!
['
match
'] as bool) {
logger.printStatus('
No
change
in
generated
loading
units
.
\
n
');
} else {
logger.printStatus('''
...
...
packages/flutter_tools/lib/src/base/deferred_component.dart
View file @
63d6ec56
...
...
@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:meta/meta.dart'
;
import
'../base/file_system.dart'
;
import
'../base/logger.dart'
;
import
'../convert.dart'
;
...
...
@@ -14,7 +10,7 @@ import '../convert.dart';
/// the app's pubspec.yaml.
class
DeferredComponent
{
DeferredComponent
({
@
required
this
.
name
,
required
this
.
name
,
this
.
libraries
=
const
<
String
>[],
this
.
assets
=
const
<
Uri
>[],
})
:
_assigned
=
false
;
...
...
@@ -49,8 +45,8 @@ class DeferredComponent {
/// unassigned and should not be used for any tasks that require loading unit information.
/// When using [loadingUnits], [assigned] should be checked first. Loading units can be
/// assigned with [assignLoadingUnits].
Set
<
LoadingUnit
>
get
loadingUnits
=>
_loadingUnits
;
Set
<
LoadingUnit
>
_loadingUnits
;
Set
<
LoadingUnit
>
?
get
loadingUnits
=>
_loadingUnits
;
Set
<
LoadingUnit
>
?
_loadingUnits
;
/// Indicates if the component has loading units assigned.
///
...
...
@@ -81,7 +77,7 @@ class DeferredComponent {
for
(
final
String
lib
in
libraries
)
{
for
(
final
LoadingUnit
loadingUnit
in
allLoadingUnits
)
{
if
(
loadingUnit
.
libraries
.
contains
(
lib
))
{
_loadingUnits
.
add
(
loadingUnit
);
_loadingUnits
!
.
add
(
loadingUnit
);
}
}
}
...
...
@@ -97,7 +93,7 @@ class DeferredComponent {
}
if
(
loadingUnits
!=
null
&&
_assigned
)
{
out
.
write
(
'
\n
LoadingUnits:'
);
for
(
final
LoadingUnit
loadingUnit
in
loadingUnits
)
{
for
(
final
LoadingUnit
loadingUnit
in
loadingUnits
!
)
{
out
.
write
(
'
\n
-
${loadingUnit.id}
'
);
}
}
...
...
@@ -117,8 +113,8 @@ class LoadingUnit {
/// Loading units must include an [id] and [libraries]. The [path] is only present when
/// parsing the loading unit from a laoding unit manifest produced by gen_snapshot.
LoadingUnit
({
@
required
this
.
id
,
@
required
this
.
libraries
,
required
this
.
id
,
required
this
.
libraries
,
this
.
path
,
});
...
...
@@ -132,7 +128,7 @@ class LoadingUnit {
///
/// This value may be null when the loading unit is parsed from a
/// `deferred_components_golden.yaml` file, which does not store the path.
final
String
path
;
final
String
?
path
;
/// Returns a human readable string representation of this LoadingUnit, ignoring
/// the [path] field. The [path] is not included as it is not relevant when the
...
...
@@ -156,7 +152,7 @@ class LoadingUnit {
///
/// This will read all existing loading units for every provided abi. If no abis are
/// provided, loading units for all abis will be parsed.
static
List
<
LoadingUnit
>
parseGeneratedLoadingUnits
(
Directory
outputDir
,
Logger
logger
,
{
List
<
String
>
abis
})
{
static
List
<
LoadingUnit
>
parseGeneratedLoadingUnits
(
Directory
outputDir
,
Logger
logger
,
{
List
<
String
>
?
abis
})
{
final
List
<
LoadingUnit
>
loadingUnits
=
<
LoadingUnit
>[];
final
List
<
FileSystemEntity
>
files
=
outputDir
.
listSync
(
recursive:
true
);
for
(
final
FileSystemEntity
fileEntity
in
files
)
{
...
...
@@ -190,7 +186,7 @@ class LoadingUnit {
}
// Read gen_snapshot manifest
final
String
fileString
=
manifestFile
.
readAsStringSync
();
Map
<
String
,
dynamic
>
manifest
;
Map
<
String
,
dynamic
>
?
manifest
;
try
{
manifest
=
jsonDecode
(
fileString
)
as
Map
<
String
,
dynamic
>;
}
on
FormatException
catch
(
e
)
{
...
...
packages/flutter_tools/lib/src/build_system/build_system.dart
View file @
63d6ec56
...
...
@@ -330,6 +330,7 @@ class Environment {
@required
Logger
logger
,
@required
Artifacts
artifacts
,
@required
ProcessManager
processManager
,
@required
Platform
platform
,
@required
String
engineVersion
,
Directory
buildDir
,
Map
<
String
,
String
>
defines
=
const
<
String
,
String
>{},
...
...
@@ -368,6 +369,7 @@ class Environment {
logger:
logger
,
artifacts:
artifacts
,
processManager:
processManager
,
platform:
platform
,
engineVersion:
engineVersion
,
inputs:
inputs
,
);
...
...
@@ -386,6 +388,7 @@ class Environment {
Map
<
String
,
String
>
defines
=
const
<
String
,
String
>{},
Map
<
String
,
String
>
inputs
=
const
<
String
,
String
>{},
String
engineVersion
,
Platform
platform
,
@required
FileSystem
fileSystem
,
@required
Logger
logger
,
@required
Artifacts
artifacts
,
...
...
@@ -403,6 +406,7 @@ class Environment {
logger:
logger
,
artifacts:
artifacts
,
processManager:
processManager
,
platform:
platform
??
FakePlatform
(),
engineVersion:
engineVersion
,
);
}
...
...
@@ -416,6 +420,7 @@ class Environment {
@required
this
.
defines
,
@required
this
.
flutterRootDir
,
@required
this
.
processManager
,
@required
this
.
platform
,
@required
this
.
logger
,
@required
this
.
fileSystem
,
@required
this
.
artifacts
,
...
...
@@ -490,6 +495,8 @@ class Environment {
final
ProcessManager
processManager
;
final
Platform
platform
;
final
Logger
logger
;
final
Artifacts
artifacts
;
...
...
packages/flutter_tools/lib/src/bundle.dart
View file @
63d6ec56
...
...
@@ -160,6 +160,7 @@ Future<void> buildWithAssemble({
fileSystem:
globals
.
fs
,
logger:
globals
.
logger
,
processManager:
globals
.
processManager
,
platform:
globals
.
platform
,
);
final
Target
target
=
buildMode
==
BuildMode
.
debug
?
const
CopyFlutterBundle
()
...
...
packages/flutter_tools/lib/src/commands/assemble.dart
View file @
63d6ec56
...
...
@@ -239,6 +239,7 @@ class AssembleCommand extends FlutterCommand {
fileSystem:
globals
.
fs
,
logger:
globals
.
logger
,
processManager:
globals
.
processManager
,
platform:
globals
.
platform
,
engineVersion:
globals
.
artifacts
.
isLocalEngine
?
null
:
globals
.
flutterVersion
.
engineRevision
...
...
packages/flutter_tools/lib/src/commands/build_appbundle.dart
View file @
63d6ec56
...
...
@@ -116,6 +116,7 @@ class BuildAppBundleCommand extends BuildSubCommand {
final
DeferredComponentsPrebuildValidator
validator
=
DeferredComponentsPrebuildValidator
(
FlutterProject
.
current
().
directory
,
globals
.
logger
,
globals
.
platform
,
title:
'Deferred components prebuild validation'
,
exitOnFail:
true
,
);
...
...
packages/flutter_tools/lib/src/commands/build_ios_framework.dart
View file @
63d6ec56
...
...
@@ -382,6 +382,7 @@ end
fileSystem: globals.fs,
logger: globals.logger,
processManager: globals.processManager,
platform: globals.platform,
engineVersion: globals.artifacts.isLocalEngine
? null
: globals.flutterVersion.engineRevision,
...
...
packages/flutter_tools/lib/src/commands/packages.dart
View file @
63d6ec56
...
...
@@ -118,6 +118,7 @@ class PackagesGetCommand extends FlutterCommand {
flutterRootDir:
globals
.
fs
.
directory
(
Cache
.
flutterRoot
),
outputDir:
globals
.
fs
.
directory
(
getBuildDirectory
()),
processManager:
globals
.
processManager
,
platform:
globals
.
platform
,
projectDir:
flutterProject
.
directory
,
);
...
...
@@ -323,6 +324,7 @@ class PackagesInteractiveGetCommand extends FlutterCommand {
flutterRootDir:
globals
.
fs
.
directory
(
Cache
.
flutterRoot
),
outputDir:
globals
.
fs
.
directory
(
getBuildDirectory
()),
processManager:
globals
.
processManager
,
platform:
globals
.
platform
,
projectDir:
flutterProject
.
directory
,
);
...
...
packages/flutter_tools/lib/src/resident_runner.dart
View file @
63d6ec56
...
...
@@ -919,6 +919,7 @@ abstract class ResidentRunner {
flutterRootDir:
globals
.
fs
.
directory
(
Cache
.
flutterRoot
),
outputDir:
globals
.
fs
.
directory
(
getBuildDirectory
()),
processManager:
globals
.
processManager
,
platform:
globals
.
platform
,
projectDir:
globals
.
fs
.
currentDirectory
,
);
_lastBuild
=
await
globals
.
buildSystem
.
buildIncremental
(
...
...
packages/flutter_tools/lib/src/runner/flutter_command.dart
View file @
63d6ec56
...
...
@@ -1158,6 +1158,7 @@ abstract class FlutterCommand extends Command<void> {
flutterRootDir:
globals
.
fs
.
directory
(
Cache
.
flutterRoot
),
outputDir:
globals
.
fs
.
directory
(
getBuildDirectory
()),
processManager:
globals
.
processManager
,
platform:
globals
.
platform
,
projectDir:
project
.
directory
,
);
...
...
packages/flutter_tools/lib/src/web/compile.dart
View file @
63d6ec56
...
...
@@ -64,6 +64,7 @@ Future<void> buildWeb(
fileSystem:
globals
.
fs
,
logger:
globals
.
logger
,
processManager:
globals
.
processManager
,
platform:
globals
.
platform
,
cacheDir:
globals
.
cache
.
getRoot
(),
engineVersion:
globals
.
artifacts
.
isLocalEngine
?
null
...
...
packages/flutter_tools/test/general.shard/android/deferred_components_gen_snapshot_validator_test.dart
View file @
63d6ec56
...
...
@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/android/deferred_components_validator.dart';
import
'package:flutter_tools/src/base/deferred_component.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'package:flutter_tools/src/build_system/build_system.dart'
;
import
'package:flutter_tools/src/build_system/targets/common.dart'
;
import
'package:flutter_tools/src/globals.dart'
as
globals
;
...
...
@@ -35,6 +36,7 @@ void main() {
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
globals
.
processManager
,
platform:
FakePlatform
(),
engineVersion:
'invalidEngineVersion'
,
);
return
result
;
...
...
packages/flutter_tools/test/general.shard/android/deferred_components_prebuild_validator_test.dart
View file @
63d6ec56
...
...
@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/android/deferred_components_validator.dart';
import
'package:flutter_tools/src/base/deferred_component.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'../../src/common.dart'
;
import
'../../src/context.dart'
;
...
...
@@ -18,6 +19,7 @@ void main() {
FileSystem
fileSystem
;
BufferLogger
logger
;
Directory
projectDir
;
Platform
platform
;
Directory
flutterRootDir
;
setUp
(()
{
...
...
@@ -25,12 +27,14 @@ void main() {
logger
=
BufferLogger
.
test
();
projectDir
=
fileSystem
.
directory
(
'/project'
);
flutterRootDir
=
fileSystem
.
directory
(
'/flutter_root'
);
platform
=
FakePlatform
();
});
testWithoutContext
(
'No checks passes'
,
()
async
{
final
DeferredComponentsPrebuildValidator
validator
=
DeferredComponentsPrebuildValidator
(
projectDir
,
logger
,
platform
,
exitOnFail:
false
,
title:
'test check'
,
);
...
...
@@ -43,6 +47,7 @@ void main() {
final
DeferredComponentsPrebuildValidator
validator
=
DeferredComponentsPrebuildValidator
(
projectDir
,
logger
,
platform
,
exitOnFail:
false
,
title:
'test check'
,
);
...
...
@@ -67,6 +72,7 @@ void main() {
final
DeferredComponentsPrebuildValidator
validator
=
DeferredComponentsPrebuildValidator
(
projectDir
,
logger
,
platform
,
exitOnFail:
false
,
title:
'test check'
,
templatesDir:
templatesDir
,
...
...
@@ -105,6 +111,7 @@ void main() {
final
DeferredComponentsPrebuildValidator
validator
=
DeferredComponentsPrebuildValidator
(
projectDir
,
logger
,
platform
,
exitOnFail:
false
,
title:
'test check'
,
templatesDir:
templatesDir
,
...
...
@@ -128,7 +135,7 @@ void main() {
expect
(
logger
.
statusText
.
contains
(
'build/
${DeferredComponentsValidator.kDeferredComponentsTempDirectory}
/component1/src/main/AndroidManifest.xml
\n
'
),
true
);
});
test
Using
Context
(
'androidComponentSetup all files exist passes'
,
()
async
{
test
Without
Context
(
'androidComponentSetup all files exist passes'
,
()
async
{
final
Directory
templatesDir
=
flutterRootDir
.
childDirectory
(
'templates'
).
childDirectory
(
'deferred_component'
);
final
File
buildGradleTemplate
=
templatesDir
.
childFile
(
'build.gradle.tmpl'
);
final
File
androidManifestTemplate
=
templatesDir
.
childDirectory
(
'src'
).
childDirectory
(
'main'
).
childFile
(
'AndroidManifest.xml.tmpl'
);
...
...
@@ -143,6 +150,7 @@ void main() {
final
DeferredComponentsPrebuildValidator
validator
=
DeferredComponentsPrebuildValidator
(
projectDir
,
logger
,
platform
,
exitOnFail:
false
,
title:
'test check'
,
templatesDir:
templatesDir
,
...
...
@@ -175,6 +183,7 @@ void main() {
final
DeferredComponentsPrebuildValidator
validator
=
DeferredComponentsPrebuildValidator
(
projectDir
,
logger
,
platform
,
exitOnFail:
false
,
title:
'test check'
,
);
...
...
@@ -242,6 +251,7 @@ void main() {
final DeferredComponentsPrebuildValidator validator = DeferredComponentsPrebuildValidator(
projectDir,
logger,
platform,
exitOnFail: false,
title: '
test
check
',
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment