init (v1.24.3)
This commit is contained in:
commit
e8e56309a6
|
@ -0,0 +1,18 @@
|
||||||
|
# Don’t commit the following directories created by pub.
|
||||||
|
build/
|
||||||
|
packages
|
||||||
|
.buildlog
|
||||||
|
|
||||||
|
# Or Settings
|
||||||
|
.settings
|
||||||
|
.project
|
||||||
|
|
||||||
|
# Or the files created by dart2js.
|
||||||
|
*.dart.js
|
||||||
|
*.dart.precompiled.js
|
||||||
|
*.js_
|
||||||
|
*.js.deps
|
||||||
|
*.js.map
|
||||||
|
|
||||||
|
# Include when developing application packages.
|
||||||
|
pubspec.lock
|
|
@ -0,0 +1,3 @@
|
||||||
|
language: dart
|
||||||
|
script: ./tool/travis.sh
|
||||||
|
sudo: false
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Names should be added to this file with this pattern:
|
||||||
|
#
|
||||||
|
# For individuals:
|
||||||
|
# Name <email address>
|
||||||
|
#
|
||||||
|
# For organizations:
|
||||||
|
# Organization <fnmatch pattern>
|
||||||
|
#
|
||||||
|
Google Inc. <*@google.com>
|
||||||
|
Sean Eagan <seaneagan1@gmail.com>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
## 0.1.3
|
||||||
|
|
||||||
|
* Assume owner/group matches that of executable until it's possible to check. (#5)
|
|
@ -0,0 +1,33 @@
|
||||||
|
Want to contribute? Great! First, read this page (including the small print at
|
||||||
|
the end).
|
||||||
|
|
||||||
|
### Before you contribute
|
||||||
|
Before we can use your code, you must sign the
|
||||||
|
[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual)
|
||||||
|
(CLA), which you can do online. The CLA is necessary mainly because you own the
|
||||||
|
copyright to your changes, even after your contribution becomes part of our
|
||||||
|
codebase, so we need your permission to use and distribute your code. We also
|
||||||
|
need to be sure of various other things—for instance that you'll tell us if you
|
||||||
|
know that your code infringes on other people's patents. You don't have to sign
|
||||||
|
the CLA until after you've submitted your code for review and a member has
|
||||||
|
approved it, but you must do it before we can put your code into our codebase.
|
||||||
|
|
||||||
|
Before you start working on a larger contribution, you should get in touch with
|
||||||
|
us first through the issue tracker with your idea so that we can help out and
|
||||||
|
possibly guide you. Coordinating up front makes it much easier to avoid
|
||||||
|
frustration later on.
|
||||||
|
|
||||||
|
### Code reviews
|
||||||
|
All submissions, including submissions by project members, require review.
|
||||||
|
|
||||||
|
### File headers
|
||||||
|
All files in the project must start with the following header.
|
||||||
|
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
### The small print
|
||||||
|
Contributions made by corporations are covered by a different agreement than the
|
||||||
|
one above, the
|
||||||
|
[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate).
|
|
@ -0,0 +1,26 @@
|
||||||
|
Copyright 2015, the Dart project authors. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,41 @@
|
||||||
|
which [![pub package](http://img.shields.io/pub/v/which.svg)](https://pub.dartlang.org/packages/which) [![Build Status](https://travis-ci.org/dart-lang/which.svg?branch=master)](https://travis-ci.org/dart-lang/which) [![Coverage Status](https://coveralls.io/repos/dart-lang/which/badge.svg)](https://coveralls.io/r/dart-lang/which)
|
||||||
|
=====
|
||||||
|
|
||||||
|
Check for and locate installed executables. Just like unix [which(1)][unix_which], except:
|
||||||
|
|
||||||
|
* Doesn't shell out (fast).
|
||||||
|
* Cross-platform (works on windows).
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pub global activate den
|
||||||
|
den install which
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:which/which.dart';
|
||||||
|
|
||||||
|
main(arguments) async {
|
||||||
|
|
||||||
|
// Asynchronously
|
||||||
|
var git = await which('git', orElse: () => null);
|
||||||
|
|
||||||
|
// Or synchronously
|
||||||
|
var git = whichSync('git', orElse: () => null);
|
||||||
|
|
||||||
|
if (git == null) {
|
||||||
|
print('Please install git and try again');
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Process.run(git, ['add', '-A']);
|
||||||
|
await Process.run(git, ['commit', '-m', arguments.first]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[unix_which]: http://en.wikipedia.org/wiki/Which_%28Unix%29
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.src.candidate_paths;
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:path/path.dart';
|
||||||
|
|
||||||
|
Iterable<String> getCandidatePaths(String command, Map<String, String> environment, bool isWindows, Context context) {
|
||||||
|
if (context.isAbsolute(command)) return [command];
|
||||||
|
|
||||||
|
String getEnvVar(String envVar, String defaultValue) {
|
||||||
|
var v = environment[envVar];
|
||||||
|
return v == null ? defaultValue : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pathVarSeparator = isWindows ? ";" : ":";
|
||||||
|
|
||||||
|
List<String> splitEnvVar(String envVar, String defaultValue) =>
|
||||||
|
getEnvVar(envVar, defaultValue).split(pathVarSeparator);
|
||||||
|
|
||||||
|
var pathEnv = splitEnvVar('PATH', '');
|
||||||
|
|
||||||
|
var noExtPaths =
|
||||||
|
pathEnv.map((pathEntry) => context.join(pathEntry, command));
|
||||||
|
|
||||||
|
if (!isWindows) return noExtPaths;
|
||||||
|
|
||||||
|
pathEnv.insert(0, context.current);
|
||||||
|
var pathExt = splitEnvVar('PATHEXT', ".EXE");
|
||||||
|
if (command.contains('.')) pathExt.insert(0, '');
|
||||||
|
return noExtPaths.expand((commandPath) =>
|
||||||
|
pathExt.map((pathExtEntry) => commandPath + pathExtEntry));
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterable<String> getRealCandidatePaths(String command) =>
|
||||||
|
getCandidatePaths(command, Platform.environment, Platform.isWindows, context);
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/// See http://dartbug.com/22036
|
||||||
|
library which.src.has_permission;
|
||||||
|
|
||||||
|
class FilePermission {
|
||||||
|
|
||||||
|
final int index;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
|
const FilePermission._(this.index, this._name);
|
||||||
|
|
||||||
|
static const EXECUTE = const FilePermission._(0, 'EXECUTE');
|
||||||
|
static const WRITE = const FilePermission._(1, 'WRITE');
|
||||||
|
static const READ = const FilePermission._(2, 'READ');
|
||||||
|
static const SET_UID = const FilePermission._(3, 'SET_UID');
|
||||||
|
static const SET_GID = const FilePermission._(4, 'SET_GID');
|
||||||
|
static const STICKY = const FilePermission._(5, 'STICKY');
|
||||||
|
|
||||||
|
static const List<FilePermission> values = const [EXECUTE, WRITE, READ, SET_UID, SET_GID, STICKY];
|
||||||
|
|
||||||
|
String toString() => 'FilePermission.$_name';
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilePermissionRole {
|
||||||
|
|
||||||
|
final int index;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
|
const FilePermissionRole._(this.index, this._name);
|
||||||
|
|
||||||
|
static const WORLD = const FilePermissionRole._(0, 'WORLD');
|
||||||
|
static const GROUP = const FilePermissionRole._(1, 'GROUP');
|
||||||
|
static const OWNER = const FilePermissionRole._(2, 'OWNER');
|
||||||
|
|
||||||
|
static const List<FilePermissionRole> values = const [WORLD, GROUP, OWNER];
|
||||||
|
|
||||||
|
String toString() => 'FilePermissionRole.$_name';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasPermission(int fileStatMode, FilePermission permission, {FilePermissionRole role: FilePermissionRole.WORLD}) {
|
||||||
|
var bitIndex = _getPermissionBitIndex(permission, role);
|
||||||
|
return (fileStatMode & (1 << bitIndex)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getPermissionBitIndex(FilePermission permission, FilePermissionRole role) {
|
||||||
|
switch (permission) {
|
||||||
|
case FilePermission.SET_UID: return 11;
|
||||||
|
case FilePermission.SET_GID: return 10;
|
||||||
|
case FilePermission.STICKY: return 9;
|
||||||
|
default: return (role.index * 3) + permission.index;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.src.is_executable;
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:when/when.dart';
|
||||||
|
|
||||||
|
import 'has_permission.dart';
|
||||||
|
|
||||||
|
Future<bool> isExecutable(String path, bool isWindows, Future<FileStat> getStat(path)) =>
|
||||||
|
_isExecutable(path, isWindows, getStat);
|
||||||
|
|
||||||
|
bool isExecutableSync(String path, bool isWindows, FileStat getStat(path)) =>
|
||||||
|
_isExecutable(path, isWindows, getStat);
|
||||||
|
|
||||||
|
_isExecutable(String path, bool isWindows, getStat(path)) =>
|
||||||
|
when(() => getStat(path), onSuccess: (stat) => isExecutableStat(stat, isWindows));
|
||||||
|
|
||||||
|
/// Tests whether the file exists and is executable.
|
||||||
|
bool isExecutableStat(FileStat stat, bool isWindows) {
|
||||||
|
if (FileSystemEntityType.FILE != stat.type) return false;
|
||||||
|
|
||||||
|
// There is no concept of executable on windows.
|
||||||
|
if (isWindows) return true;
|
||||||
|
|
||||||
|
// TODO: This currently produces false positives (returns true when it
|
||||||
|
// shouldn't) when the uid/gid of current user and executable don't
|
||||||
|
// match. Fix if/when uid/gid support is added:
|
||||||
|
// http://dartbug.com/22037.
|
||||||
|
return FilePermissionRole.values.any((role) =>
|
||||||
|
hasPermission(stat.mode, FilePermission.EXECUTE, role: role));
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.src.util;
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
/// Transparently call `firstWhere` on a [Stream] or [Iterable].
|
||||||
|
// TODO: Remove once https://dartbug.com/22028 is fixed.
|
||||||
|
dynamic firstWhere(sequence, test, { orElse() }) => sequence is Iterable ?
|
||||||
|
sequence.firstWhere(test, orElse: orElse) :
|
||||||
|
_streamFirstWhere(sequence, test, orElse: orElse);
|
||||||
|
|
||||||
|
Future _streamFirstWhere(Stream stream, test(item), { orElse() }) {
|
||||||
|
var pairs = stream.asyncMap((item) => test(item).then((result) => [item, result]));
|
||||||
|
return pairs.firstWhere((pair) => pair.last, defaultValue: () => [orElse(), null]).then((pair) => pair.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The identity function simply returns its argument ([x]).
|
||||||
|
dynamic identity(x) => x;
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.src.which_impl;
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:when/when.dart';
|
||||||
|
|
||||||
|
import 'util.dart';
|
||||||
|
|
||||||
|
Future<String> which(
|
||||||
|
String command,
|
||||||
|
Iterable<String> candidatePaths,
|
||||||
|
bool isWindows,
|
||||||
|
Future<bool> isExecutable(String path, bool isWindows),
|
||||||
|
orElse()) => new Future(() => _which(
|
||||||
|
command,
|
||||||
|
candidatePaths,
|
||||||
|
isWindows,
|
||||||
|
isExecutable,
|
||||||
|
orElse,
|
||||||
|
toSequence: (items) => new Stream.fromIterable(items)));
|
||||||
|
|
||||||
|
String whichSync(
|
||||||
|
String command,
|
||||||
|
Iterable<String> candidatePaths,
|
||||||
|
bool isWindows,
|
||||||
|
bool isExecutable(String path, bool isWindows),
|
||||||
|
orElse()) => _which(
|
||||||
|
command,
|
||||||
|
candidatePaths,
|
||||||
|
isWindows,
|
||||||
|
isExecutable,
|
||||||
|
orElse);
|
||||||
|
|
||||||
|
_which(
|
||||||
|
String command,
|
||||||
|
Iterable<String> candidatePaths,
|
||||||
|
bool isWindows,
|
||||||
|
isExecutable(String path, bool isWindows),
|
||||||
|
orElse(),
|
||||||
|
{toSequence(Iterable items): identity}) => when(
|
||||||
|
() => firstWhere(
|
||||||
|
toSequence(candidatePaths),
|
||||||
|
(path) => isExecutable(path, isWindows),
|
||||||
|
orElse: orElse != null ? orElse : () => _commandNotFound(command, null)),
|
||||||
|
onError: (e) => _commandNotFound(command, e));
|
||||||
|
|
||||||
|
_commandNotFound(String command, e) {
|
||||||
|
var message = 'Command not found: $command';
|
||||||
|
if (e != null) message += '\n$e';
|
||||||
|
throw new StateError(message);
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which;
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'src/candidate_paths.dart';
|
||||||
|
import 'src/is_executable.dart';
|
||||||
|
import 'src/which_impl.dart' as impl;
|
||||||
|
|
||||||
|
/// Returns a future for the first [command] executable in the `PATH`.
|
||||||
|
///
|
||||||
|
/// If [command] is not found, [orElse] is called, which defaults to throwing.
|
||||||
|
Future<String> which(String command, { orElse() }) => new Future(() => impl.which(
|
||||||
|
command,
|
||||||
|
getRealCandidatePaths(command),
|
||||||
|
Platform.isWindows,
|
||||||
|
(path, isWindows) => isExecutable(path, isWindows, FileStat.stat),
|
||||||
|
orElse));
|
||||||
|
|
||||||
|
/// Returns the first [command] executable in the `PATH`.
|
||||||
|
///
|
||||||
|
/// If [command] is not found, [orElse] is called, which defaults to throwing.
|
||||||
|
String whichSync(String command, { orElse() }) => impl.whichSync(
|
||||||
|
command,
|
||||||
|
getRealCandidatePaths(command),
|
||||||
|
Platform.isWindows,
|
||||||
|
(path, isWindows) => isExecutableSync(path, isWindows, FileStat.statSync),
|
||||||
|
orElse);
|
|
@ -0,0 +1,15 @@
|
||||||
|
name: which
|
||||||
|
version: 0.1.3
|
||||||
|
authors:
|
||||||
|
Dart Team <misc@dartlang.org>
|
||||||
|
Sean Eagan <seaneagan1@gmail.com>
|
||||||
|
description: Like unix which(1) - check for and locate installed executables.
|
||||||
|
homepage: https://github.com/dart-lang/which
|
||||||
|
environment:
|
||||||
|
sdk: '>=1.0.0 <2.0.0'
|
||||||
|
dependencies:
|
||||||
|
path: '>=1.3.1 <2.0.0'
|
||||||
|
when: '>=0.2.0 <0.3.0'
|
||||||
|
dev_dependencies:
|
||||||
|
mockito: '>=0.8.1 <0.9.0'
|
||||||
|
unittest: '>=0.11.4 <0.12.0'
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.test.candidate_paths;
|
||||||
|
|
||||||
|
import 'package:unittest/unittest.dart';
|
||||||
|
|
||||||
|
import 'util.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
group('getCandidatePaths', () {
|
||||||
|
test('posix', () {
|
||||||
|
var candidatePaths = getPosixCandidatePaths('z', '/x/y:/a/b/c', '/foo/bar');
|
||||||
|
expect(candidatePaths, ['/x/y/z', '/a/b/c/z']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('windows', () {
|
||||||
|
var candidatePaths = getWindowsCandidatePaths('z', r'C:\x\y;C:\a\b\c', '.EXE;.BAT', r'C:\foo\bar');
|
||||||
|
expect(candidatePaths, [
|
||||||
|
r'C:\foo\bar\z.EXE',
|
||||||
|
r'C:\foo\bar\z.BAT',
|
||||||
|
r'C:\x\y\z.EXE',
|
||||||
|
r'C:\x\y\z.BAT',
|
||||||
|
r'C:\a\b\c\z.EXE',
|
||||||
|
r'C:\a\b\c\z.BAT']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.test.has_permission;
|
||||||
|
|
||||||
|
import 'package:unittest/unittest.dart';
|
||||||
|
import 'package:which/src/has_permission.dart';
|
||||||
|
|
||||||
|
import 'util.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
test('hasPermission', () {
|
||||||
|
var mode = parseBinary('010101010101');
|
||||||
|
|
||||||
|
expect(hasPermission(mode, FilePermission.SET_UID), isFalse);
|
||||||
|
expect(hasPermission(mode, FilePermission.SET_GID), isTrue);
|
||||||
|
expect(hasPermission(mode, FilePermission.STICKY), isFalse);
|
||||||
|
expect(hasPermission(mode, FilePermission.READ, role: FilePermissionRole.OWNER), isTrue);
|
||||||
|
expect(hasPermission(mode, FilePermission.WRITE, role: FilePermissionRole.OWNER), isFalse);
|
||||||
|
expect(hasPermission(mode, FilePermission.EXECUTE, role: FilePermissionRole.OWNER), isTrue);
|
||||||
|
expect(hasPermission(mode, FilePermission.READ, role: FilePermissionRole.GROUP), isFalse);
|
||||||
|
expect(hasPermission(mode, FilePermission.WRITE, role: FilePermissionRole.GROUP), isTrue);
|
||||||
|
expect(hasPermission(mode, FilePermission.EXECUTE, role: FilePermissionRole.GROUP), isFalse);
|
||||||
|
expect(hasPermission(mode, FilePermission.READ, role: FilePermissionRole.WORLD), isTrue);
|
||||||
|
expect(hasPermission(mode, FilePermission.WRITE, role: FilePermissionRole.WORLD), isFalse);
|
||||||
|
expect(hasPermission(mode, FilePermission.EXECUTE, role: FilePermissionRole.WORLD), isTrue);
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.test.is_executable;
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
import 'package:unittest/unittest.dart';
|
||||||
|
import 'package:which/src/is_executable.dart';
|
||||||
|
|
||||||
|
import 'util.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
group('isExecutableStat', () {
|
||||||
|
test('false if not a file', () {
|
||||||
|
|
||||||
|
var stat = new MockFileStat();
|
||||||
|
|
||||||
|
// A directory.
|
||||||
|
when(stat.type).thenReturn(FileSystemEntityType.DIRECTORY);
|
||||||
|
|
||||||
|
var result = isExecutableStat(stat, false);
|
||||||
|
|
||||||
|
expect(result, isFalse);
|
||||||
|
|
||||||
|
verifyNever(stat.mode);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('true for all files on windows', () {
|
||||||
|
|
||||||
|
var stat = new MockFileStat();
|
||||||
|
|
||||||
|
// A file.
|
||||||
|
when(stat.type).thenReturn(FileSystemEntityType.FILE);
|
||||||
|
|
||||||
|
var result = isExecutableStat(stat, true);
|
||||||
|
|
||||||
|
expect(result, isTrue);
|
||||||
|
|
||||||
|
verifyNever(stat.mode);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('true if has world execute permission', () {
|
||||||
|
var result = isExecutableStat(_getMockFileStat('000000000001'), false);
|
||||||
|
expect(result, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('true if has group execute permission', () {
|
||||||
|
var result = isExecutableStat(_getMockFileStat('000000001000'), false);
|
||||||
|
expect(result, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('true if has owner execute permission', () {
|
||||||
|
var result = isExecutableStat(_getMockFileStat('000001000000'), false);
|
||||||
|
expect(result, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('false if has no execute permissions', () {
|
||||||
|
var result = isExecutableStat(_getMockFileStat('111110110110'), false);
|
||||||
|
expect(result, isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MockFileStat _getMockFileStat(String mode) {
|
||||||
|
var stat = new MockFileStat();
|
||||||
|
|
||||||
|
// A file.
|
||||||
|
when(stat.type).thenReturn(FileSystemEntityType.FILE);
|
||||||
|
|
||||||
|
// Last bit is world execute.
|
||||||
|
when(stat.mode).thenReturn(int.parse(mode, radix: 2));
|
||||||
|
|
||||||
|
return stat;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.test;
|
||||||
|
|
||||||
|
import 'candidate_paths_test.dart' as candidate_paths;
|
||||||
|
import 'has_permission_test.dart' as has_permission;
|
||||||
|
import 'is_executable_test.dart' as is_exe;
|
||||||
|
import 'which_test.dart' as which;
|
||||||
|
import 'which_impl_test.dart' as which_impl;
|
||||||
|
|
||||||
|
main() {
|
||||||
|
candidate_paths.main();
|
||||||
|
has_permission.main();
|
||||||
|
is_exe.main();
|
||||||
|
which.main();
|
||||||
|
which_impl.main();
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.test.util;
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
import 'package:which/src/candidate_paths.dart';
|
||||||
|
|
||||||
|
getPosixCandidatePaths(String command, String pathVar, String current) {
|
||||||
|
var env = {
|
||||||
|
'PATH': pathVar
|
||||||
|
};
|
||||||
|
var isWindows = false;
|
||||||
|
var context = new path.Context(style: path.Style.posix, current: current);
|
||||||
|
|
||||||
|
return getCandidatePaths(command, env, isWindows, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
getWindowsCandidatePaths(String command, String pathVar, String pathExtVar, String current) {
|
||||||
|
var env = {
|
||||||
|
'PATH': pathVar,
|
||||||
|
'PATHEXT': pathExtVar
|
||||||
|
};
|
||||||
|
var isWindows = true;
|
||||||
|
var context = new path.Context(style: path.Style.windows, current: current);
|
||||||
|
|
||||||
|
return getCandidatePaths(command, env, isWindows, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockFileStat extends Mock implements FileStat {
|
||||||
|
|
||||||
|
MockFileStat();
|
||||||
|
|
||||||
|
noSuchMethod(i) => super.noSuchMethod(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseBinary(String b) => int.parse(b, radix: 2);
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.test.which_impl;
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:unittest/unittest.dart';
|
||||||
|
import 'package:which/src/which_impl.dart';
|
||||||
|
|
||||||
|
import 'util.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
group('which', () {
|
||||||
|
test('should complete to the first matching executable in candidate paths', () {
|
||||||
|
var candidatePaths = getPosixCandidatePaths('z', '/x/y:/a/b/c', '/foo/bar');
|
||||||
|
|
||||||
|
return which('z', candidatePaths, false, (path, isWindows) => new Future.value(path == '/x/y/z' || path == '/a/b/c/z'), null)
|
||||||
|
.then((path) => expect(path, '/x/y/z'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should call orElse if command not found', () {
|
||||||
|
var candidatePaths = getPosixCandidatePaths('z', '/x/y:/a/b/c', '/foo/bar');
|
||||||
|
|
||||||
|
return which('z', candidatePaths, false, (path, isWindows) => new Future.value(false), () => '/or/else')
|
||||||
|
.then((path) => expect(path, '/or/else'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should throw state error if command not found and orElse not provided', () {
|
||||||
|
var future = new Future(() =>
|
||||||
|
which('z', [], false, (path, isWindows) => new Future.value(false), null));
|
||||||
|
|
||||||
|
expect(future, throwsStateError);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('whichSync', () {
|
||||||
|
test('should return the first matching executable in candidate paths', () {
|
||||||
|
var candidatePaths = getWindowsCandidatePaths('z', r'C:\x\y;C:\a\b\c', '.EXE;.BAT', r'C:\foo\bar');
|
||||||
|
|
||||||
|
var result = whichSync('find', candidatePaths, true, (path, isWindows) => path == r'C:\x\y\z.BAT' || path == r'C:\a\b\c\z.BAT', null);
|
||||||
|
|
||||||
|
expect(result, r'C:\x\y\z.BAT');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should call orElse if command not found', () {
|
||||||
|
var candidatePaths = getWindowsCandidatePaths('z', r'C:\x\y;C:\a\b\c', '.EXE;.BAT', r'C:\foo\bar');
|
||||||
|
|
||||||
|
var result = whichSync('find', candidatePaths, true, (path, isWindows) => false, () => r'C:\or\else');
|
||||||
|
|
||||||
|
expect(result, r'C:\or\else');
|
||||||
|
});
|
||||||
|
test('should throw state error if command not found and orElse not provided', () {
|
||||||
|
expect(() => whichSync('z', [], true, (path, isWindows) => false, null), throwsStateError);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library which.test.which;
|
||||||
|
|
||||||
|
import 'package:path/path.dart';
|
||||||
|
import 'package:unittest/unittest.dart';
|
||||||
|
import 'package:which/which.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
group('which', () {
|
||||||
|
// Any dart:io supported platform (*nix, osx, windows) should have `find`.
|
||||||
|
test('should find `find`', () => which('find').then(_testResult));
|
||||||
|
});
|
||||||
|
|
||||||
|
group('whichSync', () {
|
||||||
|
// Any dart:io supported platform (*nix, osx, windows) should have `find`.
|
||||||
|
test('should find `find`', () {
|
||||||
|
_testResult(whichSync('find'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_testResult(String path) {
|
||||||
|
expect(path, isNotNull);
|
||||||
|
var base = basenameWithoutExtension(path);
|
||||||
|
expect(base, 'find');
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||||
|
# for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
# BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
# Fast fail the script on failures.
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Verify that the libraries are error free.
|
||||||
|
dartanalyzer --fatal-warnings \
|
||||||
|
lib/which.dart \
|
||||||
|
test/test.dart
|
||||||
|
|
||||||
|
# Run the tests.
|
||||||
|
dart test/test.dart
|
||||||
|
|
||||||
|
# Install dart_coveralls; gather and send coverage data.
|
||||||
|
if [ "$COVERALLS_TOKEN" ]; then
|
||||||
|
pub global activate dart_coveralls 0.1.11
|
||||||
|
pub global run dart_coveralls report \
|
||||||
|
--token $COVERALLS_TOKEN \
|
||||||
|
--retry 2 \
|
||||||
|
--exclude-test-files \
|
||||||
|
test/test.dart
|
||||||
|
fi
|
Loading…
Reference in New Issue