diff --git a/packages/fuchsia_ctl/bin/main.dart b/packages/fuchsia_ctl/bin/main.dart index 3f5c03a38bc8..156284eb4b69 100644 --- a/packages/fuchsia_ctl/bin/main.dart +++ b/packages/fuchsia_ctl/bin/main.dart @@ -262,7 +262,12 @@ Future pushPackages( stdout.writeln('Untaring $repoArchive to ${repo.path}'); repo.createSync(recursive: true); - await tar.untar(repoArchive, repo.path); + final OperationResult result = await tar.untar(repoArchive, repo.path); + if (!result.success) { + stdout.writeln( + 'Error untarring $repoArchive \nstdout: ${result.info} \nstderr: ${result.error}'); + exit(-1); + } final String repositoryBase = path.join(repo.path, 'amber-files'); stdout.writeln('Serving $repositoryBase to $targetIp'); diff --git a/packages/fuchsia_ctl/lib/src/tar.dart b/packages/fuchsia_ctl/lib/src/tar.dart index 9ab2167f976b..0a55442a6d77 100644 --- a/packages/fuchsia_ctl/lib/src/tar.dart +++ b/packages/fuchsia_ctl/lib/src/tar.dart @@ -17,7 +17,11 @@ abstract class Tar { const Tar(); /// Untars a tar file. - Future untar(String src, String destination); + Future untar( + String src, + String destination, { + Duration timeoutMs, + }); } /// The archive package is very slow and memory intensive. Use @@ -35,16 +39,21 @@ class SystemTar implements Tar { /// program. final ProcessManager processManager; + /// The default timeout for untar operations as [Duration] in milliseconds. + static const Duration defaultTarTimeoutMs = + Duration(milliseconds: 5 * 60 * 1000); + @override Future untar( String src, - String destination, - ) async { + String destination, { + Duration timeoutMs = defaultTarTimeoutMs, + }) async { final ProcessResult result = await processManager.run([ 'tar', - '-xvf', src, // + '-xf', src, // '-C', destination, - ]); + ]).timeout(timeoutMs); return OperationResult.fromProcessResult(result); } diff --git a/packages/fuchsia_ctl/test/image_paver_test.dart b/packages/fuchsia_ctl/test/image_paver_test.dart index 38ca0e52c912..f5cc0818be06 100644 --- a/packages/fuchsia_ctl/test/image_paver_test.dart +++ b/packages/fuchsia_ctl/test/image_paver_test.dart @@ -158,7 +158,8 @@ class FakeTar implements Tar { final MemoryFileSystem fs; @override - Future untar(String src, String destination) async { + Future untar(String src, String destination, + {Duration timeoutMs}) async { if (passes) { final Directory dir = fs.directory(destination) ..createSync(recursive: true); diff --git a/packages/fuchsia_ctl/test/tar_test.dart b/packages/fuchsia_ctl/test/tar_test.dart new file mode 100644 index 000000000000..98581b44e440 --- /dev/null +++ b/packages/fuchsia_ctl/test/tar_test.dart @@ -0,0 +1,35 @@ +// Copyright 2020 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:process/process.dart'; +import 'package:test/test.dart'; +import 'package:fuchsia_ctl/src/tar.dart'; +import 'package:mockito/mockito.dart'; + +void main() { + group('Tar', () { + test('Untar file times out', () async { + final MockProcessManager processManager = MockProcessManager(); + + when(processManager.run(any)).thenAnswer((_) async { + await Future.delayed(const Duration(milliseconds: 3)); + return ProcessResult(0, 0, 'Good job', ''); + }); + + final Tar tar = SystemTar(processManager: processManager); + expect( + tar.untar( + 'source.tar', + '/destination', + timeoutMs: const Duration(milliseconds: 1), + ), + throwsA(const TypeMatcher())); + }); + }); +} + +class MockProcessManager extends Mock implements ProcessManager {}