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
b6644733
Commit
b6644733
authored
Jul 22, 2016
by
John McCutchan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support for synchronizing assets onto a DevFS
parent
1fe118fe
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
560 additions
and
426 deletions
+560
-426
asset.dart
packages/flutter_tools/lib/src/asset.dart
+418
-0
devfs.dart
packages/flutter_tools/lib/src/devfs.dart
+82
-6
flx.dart
packages/flutter_tools/lib/src/flx.dart
+15
-372
zip.dart
packages/flutter_tools/lib/src/zip.dart
+15
-44
devfs_test.dart
packages/flutter_tools/test/devfs_test.dart
+23
-4
mocks.dart
packages/flutter_tools/test/src/mocks.dart
+7
-0
No files found.
packages/flutter_tools/lib/src/asset.dart
0 → 100644
View file @
b6644733
This diff is collapsed.
Click to expand it.
packages/flutter_tools/lib/src/devfs.dart
View file @
b6644733
...
...
@@ -9,23 +9,37 @@ import 'dart:io';
import
'package:path/path.dart'
as
path
;
import
'dart/package_map.dart'
;
import
'asset.dart'
;
import
'globals.dart'
;
import
'observatory.dart'
;
// A file that has been added to a DevFS.
class
DevFSEntry
{
DevFSEntry
(
this
.
devicePath
,
this
.
file
);
DevFSEntry
(
this
.
devicePath
,
this
.
file
)
:
bundleEntry
=
null
;
DevFSEntry
.
bundle
(
this
.
devicePath
,
AssetBundleEntry
bundleEntry
)
:
bundleEntry
=
bundleEntry
,
file
=
bundleEntry
.
file
;
final
String
devicePath
;
final
AssetBundleEntry
bundleEntry
;
final
File
file
;
FileStat
_fileStat
;
// When we updated the DevFS, did we see this entry?
bool
_wasSeen
=
false
;
DateTime
get
lastModified
=>
_fileStat
?.
modified
;
bool
get
stillExists
{
if
(
_isSourceEntry
)
return
true
;
_stat
();
return
_fileStat
.
type
!=
FileSystemEntityType
.
NOT_FOUND
;
}
bool
get
isModified
{
if
(
_isSourceEntry
)
return
true
;
if
(
_fileStat
==
null
)
{
_stat
();
return
true
;
...
...
@@ -36,8 +50,18 @@ class DevFSEntry {
}
void
_stat
()
{
if
(
_isSourceEntry
)
return
;
_fileStat
=
file
.
statSync
();
}
bool
get
_isSourceEntry
=>
file
==
null
;
Future
<
List
<
int
>>
contentsAsBytes
()
async
{
if
(
_isSourceEntry
)
return
bundleEntry
.
contentsAsBytes
();
return
file
.
readAsBytes
();
}
}
...
...
@@ -46,6 +70,7 @@ abstract class DevFSOperations {
Future
<
Uri
>
create
(
String
fsName
);
Future
<
dynamic
>
destroy
(
String
fsName
);
Future
<
dynamic
>
writeFile
(
String
fsName
,
DevFSEntry
entry
);
Future
<
dynamic
>
deleteFile
(
String
fsName
,
DevFSEntry
entry
);
Future
<
dynamic
>
writeSource
(
String
fsName
,
String
devicePath
,
String
contents
);
...
...
@@ -74,7 +99,7 @@ class ServiceProtocolDevFSOperations implements DevFSOperations {
Future
<
dynamic
>
writeFile
(
String
fsName
,
DevFSEntry
entry
)
async
{
List
<
int
>
bytes
;
try
{
bytes
=
await
entry
.
file
.
read
AsBytes
();
bytes
=
await
entry
.
contents
AsBytes
();
}
catch
(
e
)
{
return
e
;
}
...
...
@@ -91,6 +116,11 @@ class ServiceProtocolDevFSOperations implements DevFSOperations {
}
}
@override
Future
<
dynamic
>
deleteFile
(
String
fsName
,
DevFSEntry
entry
)
async
{
// TODO(johnmccutchan): Add file deletion to the devFS protocol.
}
@override
Future
<
dynamic
>
writeSource
(
String
fsName
,
String
devicePath
,
...
...
@@ -135,7 +165,11 @@ class DevFS {
return
await
_operations
.
destroy
(
fsName
);
}
Future
<
dynamic
>
update
()
async
{
Future
<
dynamic
>
update
([
AssetBundle
bundle
=
null
])
async
{
// Mark all entries as not seen.
_entries
.
forEach
((
String
path
,
DevFSEntry
entry
)
{
entry
.
_wasSeen
=
false
;
});
printTrace
(
'DevFS: Starting sync from
$rootDirectory
'
);
// Send the root and lib directories.
Directory
directory
=
rootDirectory
;
...
...
@@ -162,6 +196,27 @@ class DevFS {
}
}
}
if
(
bundle
!=
null
)
{
// Synchronize asset bundle.
for
(
AssetBundleEntry
entry
in
bundle
.
entries
)
{
// We write the assets into 'build/flx' so that they are in the
// same location in DevFS and the iOS simulator.
final
String
devicePath
=
path
.
join
(
'build/flx'
,
entry
.
archivePath
);
_syncBundleEntry
(
devicePath
,
entry
);
}
}
// Handle deletions.
final
List
<
String
>
toRemove
=
new
List
<
String
>();
_entries
.
forEach
((
String
path
,
DevFSEntry
entry
)
{
if
(!
entry
.
_wasSeen
)
{
_deleteEntry
(
path
,
entry
);
toRemove
.
add
(
path
);
}
});
for
(
int
i
=
0
;
i
<
toRemove
.
length
;
i
++)
{
_entries
.
remove
(
toRemove
[
i
]);
}
// Send the assets.
printTrace
(
'DevFS: Waiting for sync of
${_pendingWrites.length}
files '
'to finish'
);
await
Future
.
wait
(
_pendingWrites
);
...
...
@@ -175,6 +230,10 @@ class DevFS {
logger
.
flush
();
}
void
_deleteEntry
(
String
path
,
DevFSEntry
entry
)
{
_pendingWrites
.
add
(
_operations
.
deleteFile
(
fsName
,
entry
));
}
void
_syncFile
(
String
devicePath
,
File
file
)
{
DevFSEntry
entry
=
_entries
[
devicePath
];
if
(
entry
==
null
)
{
...
...
@@ -182,6 +241,7 @@ class DevFS {
entry
=
new
DevFSEntry
(
devicePath
,
file
);
_entries
[
devicePath
]
=
entry
;
}
entry
.
_wasSeen
=
true
;
bool
needsWrite
=
entry
.
isModified
;
if
(
needsWrite
)
{
Future
<
dynamic
>
pendingWrite
=
_operations
.
writeFile
(
fsName
,
entry
);
...
...
@@ -193,13 +253,29 @@ class DevFS {
}
}
bool
_shouldIgnore
(
String
path
)
{
void
_syncBundleEntry
(
String
devicePath
,
AssetBundleEntry
assetBundleEntry
)
{
DevFSEntry
entry
=
_entries
[
devicePath
];
if
(
entry
==
null
)
{
// New file.
entry
=
new
DevFSEntry
.
bundle
(
devicePath
,
assetBundleEntry
);
_entries
[
devicePath
]
=
entry
;
}
entry
.
_wasSeen
=
true
;
Future
<
dynamic
>
pendingWrite
=
_operations
.
writeFile
(
fsName
,
entry
);
if
(
pendingWrite
!=
null
)
{
_pendingWrites
.
add
(
pendingWrite
);
}
else
{
printTrace
(
'DevFS: Failed to sync "
$devicePath
"'
);
}
}
bool
_shouldIgnore
(
String
devicePath
)
{
List
<
String
>
ignoredPrefixes
=
<
String
>[
'android/'
,
'build/'
,
'ios/'
,
'packages/analyzer'
];
for
(
String
ignoredPrefix
in
ignoredPrefixes
)
{
if
(
p
ath
.
startsWith
(
ignoredPrefix
))
if
(
deviceP
ath
.
startsWith
(
ignoredPrefix
))
return
true
;
}
return
false
;
...
...
packages/flutter_tools/lib/src/flx.dart
View file @
b6644733
This diff is collapsed.
Click to expand it.
packages/flutter_tools/lib/src/zip.dart
View file @
b6644733
...
...
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:convert'
show
UTF8
;
import
'dart:io'
;
import
'package:archive/archive.dart'
;
import
'package:path/path.dart'
as
path
;
import
'asset.dart'
;
import
'base/process.dart'
;
abstract
class
ZipBuilder
{
...
...
@@ -21,30 +21,13 @@ abstract class ZipBuilder {
ZipBuilder
.
_
();
List
<
ZipEntry
>
entries
=
<
Zip
Entry
>[];
List
<
AssetBundleEntry
>
entries
=
<
AssetBundle
Entry
>[];
void
addEntry
(
Zip
Entry
entry
)
=>
entries
.
add
(
entry
);
void
addEntry
(
AssetBundle
Entry
entry
)
=>
entries
.
add
(
entry
);
void
createZip
(
File
outFile
,
Directory
zipBuildDir
);
}
class
ZipEntry
{
ZipEntry
.
fromFile
(
this
.
archivePath
,
File
file
)
{
this
.
_file
=
file
;
}
ZipEntry
.
fromString
(
this
.
archivePath
,
String
contents
)
{
this
.
_contents
=
contents
;
}
final
String
archivePath
;
File
_file
;
String
_contents
;
bool
get
isStringEntry
=>
_contents
!=
null
;
}
class
_ArchiveZipBuilder
extends
ZipBuilder
{
_ArchiveZipBuilder
()
:
super
.
_
();
...
...
@@ -52,14 +35,9 @@ class _ArchiveZipBuilder extends ZipBuilder {
void
createZip
(
File
outFile
,
Directory
zipBuildDir
)
{
Archive
archive
=
new
Archive
();
for
(
ZipEntry
entry
in
entries
)
{
if
(
entry
.
isStringEntry
)
{
List
<
int
>
data
=
UTF8
.
encode
(
entry
.
_contents
);
archive
.
addFile
(
new
ArchiveFile
.
noCompress
(
entry
.
archivePath
,
data
.
length
,
data
));
}
else
{
List
<
int
>
data
=
entry
.
_file
.
readAsBytesSync
();
archive
.
addFile
(
new
ArchiveFile
(
entry
.
archivePath
,
data
.
length
,
data
));
}
for
(
AssetBundleEntry
entry
in
entries
)
{
List
<
int
>
data
=
entry
.
contentsAsBytes
();
archive
.
addFile
(
new
ArchiveFile
.
noCompress
(
entry
.
archivePath
,
data
.
length
,
data
));
}
List
<
int
>
zipData
=
new
ZipEncoder
().
encode
(
archive
);
...
...
@@ -79,18 +57,11 @@ class _ZipToolBuilder extends ZipBuilder {
zipBuildDir
.
deleteSync
(
recursive:
true
);
zipBuildDir
.
createSync
(
recursive:
true
);
for
(
ZipEntry
entry
in
entries
)
{
if
(
entry
.
isStringEntry
)
{
List
<
int
>
data
=
UTF8
.
encode
(
entry
.
_contents
);
File
file
=
new
File
(
path
.
join
(
zipBuildDir
.
path
,
entry
.
archivePath
));
file
.
parent
.
createSync
(
recursive:
true
);
file
.
writeAsBytesSync
(
data
);
}
else
{
List
<
int
>
data
=
entry
.
_file
.
readAsBytesSync
();
File
file
=
new
File
(
path
.
join
(
zipBuildDir
.
path
,
entry
.
archivePath
));
file
.
parent
.
createSync
(
recursive:
true
);
file
.
writeAsBytesSync
(
data
);
}
for
(
AssetBundleEntry
entry
in
entries
)
{
List
<
int
>
data
=
entry
.
contentsAsBytes
();
File
file
=
new
File
(
path
.
join
(
zipBuildDir
.
path
,
entry
.
archivePath
));
file
.
parent
.
createSync
(
recursive:
true
);
file
.
writeAsBytesSync
(
data
);
}
if
(
_getCompressedNames
().
isNotEmpty
)
{
...
...
@@ -112,13 +83,13 @@ class _ZipToolBuilder extends ZipBuilder {
Iterable
<
String
>
_getCompressedNames
()
{
return
entries
.
where
((
Zip
Entry
entry
)
=>
!
entry
.
isStringEntry
)
.
map
((
Zip
Entry
entry
)
=>
entry
.
archivePath
);
.
where
((
AssetBundle
Entry
entry
)
=>
!
entry
.
isStringEntry
)
.
map
((
AssetBundle
Entry
entry
)
=>
entry
.
archivePath
);
}
Iterable
<
String
>
_getStoredNames
()
{
return
entries
.
where
((
Zip
Entry
entry
)
=>
entry
.
isStringEntry
)
.
map
((
Zip
Entry
entry
)
=>
entry
.
archivePath
);
.
where
((
AssetBundle
Entry
entry
)
=>
entry
.
isStringEntry
)
.
map
((
AssetBundle
Entry
entry
)
=>
entry
.
archivePath
);
}
}
packages/flutter_tools/test/devfs_test.dart
View file @
b6644733
...
...
@@ -4,6 +4,7 @@
import
'dart:io'
;
import
'package:flutter_tools/src/asset.dart'
;
import
'package:flutter_tools/src/devfs.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:test/test.dart'
;
...
...
@@ -18,6 +19,8 @@ void main() {
String
basePath
;
MockDevFSOperations
devFSOperations
=
new
MockDevFSOperations
();
DevFS
devFS
;
AssetBundle
assetBundle
=
new
AssetBundle
();
assetBundle
.
entries
.
add
(
new
AssetBundleEntry
.
fromString
(
'a.txt'
,
''
));
group
(
'devfs'
,
()
{
testUsingContext
(
'create local file system'
,
()
async
{
tempDir
=
Directory
.
systemTemp
.
createTempSync
();
...
...
@@ -38,8 +41,6 @@ void main() {
testUsingContext
(
'modify existing file on local file system'
,
()
async
{
File
file
=
new
File
(
path
.
join
(
basePath
,
filePath
));
file
.
writeAsBytesSync
(<
int
>[
1
,
2
,
3
,
4
,
5
,
6
]);
});
testUsingContext
(
'update dev file system'
,
()
async
{
await
devFS
.
update
();
expect
(
devFSOperations
.
contains
(
'writeFile test bar/foo.txt'
),
isTrue
);
});
...
...
@@ -47,11 +48,29 @@ void main() {
File
file
=
new
File
(
path
.
join
(
basePath
,
filePath2
));
await
file
.
parent
.
create
(
recursive:
true
);
file
.
writeAsBytesSync
(<
int
>[
1
,
2
,
3
,
4
,
5
,
6
,
7
]);
});
testUsingContext
(
'update dev file system'
,
()
async
{
await
devFS
.
update
();
expect
(
devFSOperations
.
contains
(
'writeFile test foo/bar.txt'
),
isTrue
);
});
testUsingContext
(
'delete a file from the local file system'
,
()
async
{
File
file
=
new
File
(
path
.
join
(
basePath
,
filePath
));
await
file
.
delete
();
await
devFS
.
update
();
expect
(
devFSOperations
.
contains
(
'deleteFile test bar/foo.txt'
),
isTrue
);
});
testUsingContext
(
'add file in an asset bundle'
,
()
async
{
await
devFS
.
update
(
assetBundle
);
expect
(
devFSOperations
.
contains
(
'writeFile test build/flx/a.txt'
),
isTrue
);
});
testUsingContext
(
'add a file to the asset bundle'
,
()
async
{
assetBundle
.
entries
.
add
(
new
AssetBundleEntry
.
fromString
(
'b.txt'
,
''
));
await
devFS
.
update
(
assetBundle
);
expect
(
devFSOperations
.
contains
(
'writeFile test build/flx/b.txt'
),
isTrue
);
});
testUsingContext
(
'delete a file from the asset bundle'
,
()
async
{
assetBundle
.
entries
.
clear
();
await
devFS
.
update
(
assetBundle
);
expect
(
devFSOperations
.
contains
(
'deleteFile test build/flx/b.txt'
),
isTrue
);
});
testUsingContext
(
'delete dev file system'
,
()
async
{
await
devFS
.
destroy
();
});
...
...
packages/flutter_tools/test/src/mocks.dart
View file @
b6644733
...
...
@@ -75,6 +75,8 @@ class MockDevFSOperations implements DevFSOperations {
final
List
<
String
>
messages
=
new
List
<
String
>();
bool
contains
(
String
match
)
{
print
(
'Checking for `
$match
` in:'
);
print
(
messages
);
bool
result
=
messages
.
contains
(
match
);
messages
.
clear
();
return
result
;
...
...
@@ -96,6 +98,11 @@ class MockDevFSOperations implements DevFSOperations {
messages
.
add
(
'writeFile
$fsName
${entry.devicePath}
'
);
}
@override
Future
<
dynamic
>
deleteFile
(
String
fsName
,
DevFSEntry
entry
)
async
{
messages
.
add
(
'deleteFile
$fsName
${entry.devicePath}
'
);
}
@override
Future
<
dynamic
>
writeSource
(
String
fsName
,
String
devicePath
,
...
...
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