重置仓库到最新一次commit

This commit is contained in:
2023-01-30 15:33:27 +08:00
commit 09f5375891
37 changed files with 2286 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:mason_logger/mason_logger.dart';
import 'package:yoyo_get_fast_mirror/src/commands/commands.dart';
import 'package:yoyo_get_fast_mirror/src/version.dart';
const executableName = 'yoyo-getfastmirror';
const packageName = 'yoyo_get_fast_mirror';
const description = 'A Very Good Project created by Yoyo.';
class YoyoGetFastMirrorCommandRunner extends CommandRunner<int> {
/// {@macro yoyo_get_fast_mirror_command_runner}
YoyoGetFastMirrorCommandRunner({
Logger? logger,
}) : _logger = logger ?? Logger(),
super(executableName, description) {
// Add root options and flags
argParser
..addFlag(
'version',
abbr: 'v',
negatable: false,
help: 'Print the current version.',
)
..addFlag(
'verbose',
help: 'Noisy logging, including all shell commands executed.',
);
// Add sub commands
addCommand(GetfastmirroCommand(logger: _logger));
}
@override
void printUsage() => _logger.info(usage);
final Logger _logger;
@override
Future<int> run(Iterable<String> args) async {
try {
final topLevelResults = parse(args);
if (topLevelResults['verbose'] == true) {
_logger.level = Level.verbose;
}
return await runCommand(topLevelResults) ?? ExitCode.success.code;
} on FormatException catch (e, stackTrace) {
// On format errors, show the commands error message, root usage and
// exit with an error code
_logger
..err(e.message)
..err('$stackTrace')
..info('')
..info(usage);
return ExitCode.usage.code;
} on UsageException catch (e) {
// On usage errors, show the commands usage message and
// exit with an error code
_logger
..err(e.message)
..info('')
..info(e.usage);
return ExitCode.usage.code;
}
}
@override
Future<int?> runCommand(ArgResults topLevelResults) async {
_logger
..detail('Argument information:')
..detail(' Top level options:');
for (final option in topLevelResults.options) {
if (topLevelResults.wasParsed(option)) {
_logger.detail(' - $option: ${topLevelResults[option]}');
}
}
if (topLevelResults.command != null) {
final commandResult = topLevelResults.command!;
_logger
..detail(' Command: ${commandResult.name}')
..detail(' Command options:');
for (final option in commandResult.options) {
if (commandResult.wasParsed(option)) {
_logger.detail(' - $option: ${commandResult[option]}');
}
}
}
final int? exitCode;
if (topLevelResults['version'] == true) {
_logger.info(packageVersion);
exitCode = ExitCode.success.code;
} else {
exitCode = await super.runCommand(topLevelResults);
}
return exitCode;
}
}

View File

@@ -0,0 +1 @@
export 'getfastmirror_command.dart';

View File

@@ -0,0 +1,41 @@
import 'package:args/command_runner.dart';
import 'package:mason_logger/mason_logger.dart';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/getfastmirror.dart';
class GetfastmirroCommand extends Command<int> {
GetfastmirroCommand({
required Logger logger,
}) : _logger = logger {
argParser.addFlag(
'only-test',
abbr: 'o',
help: "Only test mirrors' speed",
negatable: false,
);
}
@override
String get description =>
'Get fastest mirror and generate config file for oyo';
@override
String get name => 'getfastmirror';
final Logger _logger;
@override
Future<int> run() async {
final output = lightBlue.wrap('''
Get the fastest mirror which will be write into source file
And generate a config file for oyo
''');
_logger.info(output);
final onlyTest = argResults?['only-test'] == true;
final commandResult = await getFastMirror(onlyTest: onlyTest);
if (commandResult['success'] == false) {
_logger.err(commandResult['msg'] as String);
return ExitCode.unavailable.code;
}
return ExitCode.success.code;
}
}

View File

@@ -0,0 +1,170 @@
String aptFastConfigTemplate(String yoYoMirroList,String ubuntuMirroList) {
return '''
###################################################################
# CONFIGURATION OPTIONS
###################################################################
# Every item has a default value besides MIRRORS (which is unset).
# Use aptitude, apt-get, or apt?
# Note that apt-get is used as a fallback for outputting the
# package URI list for e.g. aptitude, which can't do this
# Optionally add the FULLPATH to apt-get or apt-rpm or aptitude
# e.g. /usr/bin/aptitude
#
# Default: apt-get
#
_APTMGR=apt
if grep -Eqi "linuxmint" /etc/os-release;then
_APTMGR=apt-get
fi
if [ -x "\$(command -v oyo)" ]; then
_APTMGR=apt-get
fi
####
#
# UOS sources auth config
#
#
if grep -Eqi "UnionTech" /etc/issue || grep -Eq "UnionTech" /etc/*-release;then
AUTH_UOS_USER="uos-https://license.chinauos.com-apt"
AUTH_UOS_PASSWD="`cat /etc/apt/auth.conf.d/uos.conf | grep home-packages.chinauos.com`"
AUTH_UOS_PASSWD=`echo \${AUTH_UOS_PASSWD#*password }`
fi
##### UOS自动读取账号密码以实现使用aptss来加速下载
# Enable DOWNLOADBEFORE to suppress apt-fast confirmation dialog and download
# packages directly.
#
# Default: dialog enabled
#
DOWNLOADBEFORE=true
# Choose mirror list to speed up downloads from same archive. To select some
# mirrors take a look at your distribution's archive mirror lists.
# Debian: http://www.debian.org/mirror/list
# Ubuntu: https://launchpad.net/ubuntu/+archivemirrors
#
# It is required to add mirrors in the sources.list to this array as well, so
# apt-fast can destinguish between different distributions.
#
# Examples:
#
# Different distributions (as in operating systems):
#
# sources.list:
# deb http://deb.debian.org/debian/ unstable main non-free contrib
# deb http://de.archive.ubuntu.com/ubuntu/ bionic main universe
#
# apt-fast.conf:
# MIRRORS=( 'http://deb.debian.org/debian','http://ftp.debian.org/debian,http://ftp2.de.debian.org/debian,http://ftp.de.debian.org/debian,ftp://ftp.uni-kl.de/debian'
# 'http://archive.ubuntu.com/ubuntu,http://de.archive.ubuntu.com/ubuntu,http://ftp.halifax.rwth-aachen.de/ubuntu,http://ftp.uni-kl.de/pub/linux/ubuntu,http://mirror.informatik.uni-mannheim.de/pub/linux/distributions/ubuntu/' )
#
#
# Single distribution:
#
# sources.list:
# deb http://fr.archive.ubuntu.com/ubuntu/ bionic main
# deb http://fr.archive.ubuntu.com/ubuntu/ artful main
#
# apt-fast.conf:
# MIRRORS=( 'http://fr.archive.ubuntu.com/ubuntu,http://bouyguestelecom.ubuntu.lafibre.info/ubuntu,http://mirror.ovh.net/ubuntu,http://ubuntu-archive.mirrors.proxad.net/ubuntu' )
#
# Default: disabled
MIRRORS=( '$ubuntuMirroList'
'$yoYoMirroList' )
# Maximum number of connections
# You can use this value in _DOWNLOADER command. Escape with \${}: \${_MAXNUM}
#
# Default: 5
#
_MAXNUM=16
# Maximum number of connections per server
# Default: 10
#
_MAXCONPERSRV=1
# Split size i.e. size of each piece
# Possible Values: 1M-1024M
#
_MINSPLITSZ=1M
# Piece selection algorithm to use
# Available values are: default, inorder, geom
# default: selects piece so that it reduces the number of establishing connection, reasonable for most cases
# inorder: selects pieces in sequential order starting from first piece
# geom: selects piece which has minimum index like inorder, but it exponentially increasingly keeps space from previously selected pieces
#
_PIECEALGO=default
# Downloadmanager listfile
# You can use this value in _DOWNLOADER command. Escape with \${}: \${DLLIST}
#
# Default: /tmp/apt-fast.list
#
DLLIST='/tmp/apt-fast.list'
# Download command to use. Temporary download list is designed for aria2. But
# you can choose another download command or download manager. It has to
# support following input file syntax (\\t is tab character):
#
# # Comment
# MIRROR1\\tMIRROR2\\tMIRROR3...
# out=FILENAME1
# MIRROR1\\tMIRROR2\\tMIRROR3...
# out=FILENAME2
# ...
#
# Examples:
# aria2c with a proxy (set username, proxy, ip and password!)
# _DOWNLOADER='aria2c --no-conf -c -j \${_MAXNUM} -x \${_MAXCONPERSRV} -s \${_SPLITCON} --min-split-size=\${_MINSPLITSZ} --stream-piece-selector=\${_PIECEALGO} --http-proxy=http://username:password@proxy_ip:proxy_port -i \${DLLIST}'
#
# Default: _DOWNLOADER='aria2c --no-conf -c -j \${_MAXNUM} -x \${_MAXCONPERSRV} -s \${_SPLITCON} --min-split-size=\${_MINSPLITSZ} --stream-piece-selector=\${_PIECEALGO} -i \${DLLIST} --connect-timeout=600 --timeout=600 -m0'
#
_DOWNLOADER='aria2c --no-conf -c -j \${_MAXNUM} -x \${_MAXCONPERSRV} --min-split-size=\${_MINSPLITSZ} --stream-piece-selector=\${_PIECEALGO} -i \${DLLIST} --connect-timeout=600 --timeout=600 -m0 --http-user \${AUTH_UOS_USER} --http-passwd \${AUTH_UOS_PASSWD}'
# Download temp folder for Downloadmanager
# example /tmp/apt-fast. Standard is /var/cache/apt-fast
#
# Default: /var/cache/apt/apt-fast
#
DLDIR='/var/cache/apt/apt-fast'
# APT archives cache directory
#
# Default /var/cache/apt/archives
# (APT configuration items Dir::Cache and Dir::Cache::archives)
#
APTCACHE='/var/cache/apt/archives'
# apt-fast colors
# Colors are disabled when not using a terminal.
#
# Default colors are:
# cGreen='\\e[0;32m'
# cRed='\\e[0;31m'
# cBlue='\\e[0;34m'
# endColor='\\e[0m'
''';
}

View File

@@ -0,0 +1,37 @@
import 'dart:io';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/apt_fast_config_template.dart';
final tmpDir = Directory.systemTemp.path;
final String filePath = '$tmpDir/oyo/apt-fast.conf';
final File file = File(filePath);
final List<String> mirroListInConfigFileYoyo = [];
final List<String> mirroListInConfigFileUbuntu = [];
void generateAptFastConfigFile(
List<Map<String, String>> sortedUrlListAndTimeYoyo,
List<Map<String, String>> sortedUrlListAndTimeUbuntu,
) {
//Yoyo
for (final element in sortedUrlListAndTimeYoyo) {
mirroListInConfigFileYoyo.add(element['url'] ?? '');
}
final mirroListInConfigFileStringYoyo = mirroListInConfigFileYoyo
.toString()
.replaceAll('[', '')
.replaceAll(']', '');
//Ubuntu
for (final element in sortedUrlListAndTimeUbuntu) {
mirroListInConfigFileUbuntu.add(element['url'] ?? '');
}
final mirroListInConfigFileStringUbuntu = mirroListInConfigFileUbuntu
.toString()
.replaceAll('[', '')
.replaceAll(']', '');
final configContent = aptFastConfigTemplate(
mirroListInConfigFileStringYoyo,
mirroListInConfigFileStringUbuntu,
);
if (!file.existsSync()) file.createSync(recursive: true);
file.writeAsStringSync(configContent);
}

View File

@@ -0,0 +1,14 @@
import 'package:http/http.dart' as http;
Uri mirrorsUri = Uri(
scheme: 'https',
host: 'packages.yzzi.icu',
path: '/sources_mirrors.list',
);
/// 获取镜像列表,返回一个 List<String>
Future<List<String>> getMirrorList() async {
final response = await http.get(mirrorsUri);
final list = response.body.replaceAll('\n', ' ').trimRight().split(' ');
return list;
}

View File

@@ -0,0 +1,69 @@
import 'package:mason_logger/mason_logger.dart';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/generate_apt_fast_config_file.dart';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/get_mirro_list.dart';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/network_test.dart';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/test_mirro_speed.dart';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/ubuntu_sources_list_template.dart';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/write_mirror_into_file.dart';
import 'package:yoyo_get_fast_mirror/src/commands/modules/getfastmirro/yoyo_sources_list_template.dart';
final Map<String, dynamic> status = {};
final Logger _logger = Logger();
const List<String> ubuntuMirrorList = [
'https://mirrors.tuna.tsinghua.edu.cn/ubuntu/',
'https://mirrors.aliyun.com/ubuntu/',
'https://repo.huaweicloud.com/ubuntu/'
];
final outputYoyo = lightGreen.wrap('Yoyo Mirrors:');
final outputUbuntu = lightGreen.wrap('Ubuntu Mirrors:');
Future<Map<String, dynamic>> getFastMirror({bool onlyTest = false}) async {
//首先测试网络链接
if (!await networkTest()) {
status['success'] = false;
status['msg'] = 'NetWork Error';
return status;
}
//获取Yoyo镜像地址
final yoYoMirrorList = await getMirrorList();
_logger.info("\n$outputYoyo\n${yoYoMirrorList.join('\n')}\n");
//测试Yoyo镜像并获取时间和排序后的Map
final sortedUrlListAndTimeYoyo = await testMirroSpeed(yoYoMirrorList);
//测试Ubuntu镜像并获取时间和排序后的Map
_logger.info("\n$outputUbuntu\n${ubuntuMirrorList.join('\n')}\n");
final sortedUrlListAndTimeUbuntu = await testMirroSpeed(ubuntuMirrorList);
//生成config
if (!onlyTest) {
try {
generateAptFastConfigFile(
sortedUrlListAndTimeYoyo, sortedUrlListAndTimeUbuntu,);
} catch (e) {
status['success'] = false;
status['msg'] = 'Generate Config File Error';
return status;
} finally {
status['success'] = true;
}
//写入镜像源文件
//Yoyo
final fastestYoyoMirror =
sortedUrlListAndTimeYoyo.first.entries.first.value;
final yoyoSourcesListFile = yoyoSourcesListTemplate(fastestYoyoMirror);
writeMirrorIntoFile(
yoyoSourcesListFile,
'/etc/apt/sources.list.d/yoyo-os.list',
);
//Ubuntu
final fastestUbuntuMirror =
sortedUrlListAndTimeUbuntu.first.entries.first.value;
final ubuntuSourcesLIstFile =
ubuntuSourcesListTemplate(fastestUbuntuMirror);
writeMirrorIntoFile(
ubuntuSourcesLIstFile,
'/etc/apt/sources.list',
);
}
//返回执行结果
return status;
}

View File

@@ -0,0 +1,13 @@
import 'package:http/http.dart' as http;
Uri mirrosUri = Uri(
scheme: 'https',
host: 'baidu.com',
path: '/',
);
/// 测试网络连接成功返回true
Future<bool> networkTest() async {
final response = await http.get(mirrosUri);
return response.statusCode == 200;
}

View File

@@ -0,0 +1,44 @@
import 'dart:collection';
import 'package:cli_spinner/cli_spinner.dart';
import 'package:dart_ping/dart_ping.dart';
import 'package:mason_logger/mason_logger.dart';
Logger _logger = Logger();
final speedResult = lightGreen.wrap('Speed Result:');
Future<List<Map<String, String>>> testMirroSpeed(
List<String> mirrorList,
) async {
final spinner =
Spinner.type('Speed Test ......', SpinnerType.boxCircle)..start();
final testResult = <Map<String, String>>[];
final logMsg = StringBuffer()..write(speedResult);
for (final element in mirrorList) {
late final PingData pingRes;
late final double time;
try {
pingRes = await Ping(Uri.parse(element).host, count: 1).stream.first;
time = pingRes.response!.time!.inMicroseconds * 0.001;
testResult.add({'url': element, 'time': time.toStringAsFixed(3)});
logMsg.write('\n${time.toStringAsFixed(3)}ms \t$element');
} catch (e) {
testResult.add({'url': element, 'time': '99999999'});
logMsg.write('\nTimeout \t$element');
}
}
spinner.updateMessage('');
spinner.stop();
_logger.info(logMsg.toString());
final resultMap = testResult.asMap();
final Map<int, Map<String, String>> sortedResult = SplayTreeMap.from(
resultMap,
(key1, key2) => double.parse(resultMap[key1]!['time'] ?? '') >
double.parse(resultMap[key2]!['time'] ?? '')
? 1
: -1,
);
final sortedUrlListAndTime =
sortedResult.entries.map((e) => e.value).toList();
return sortedUrlListAndTime;
}

View File

@@ -0,0 +1,11 @@
String ubuntuSourcesListTemplate(String ubuntuMirrorUrl) {
return '''
# Generate by yoyo-getfastmirror
# Author: Github/Riceneeder
deb $ubuntuMirrorUrl jammy main restricted universe multiverse
deb $ubuntuMirrorUrl jammy-updates main restricted universe multiverse
deb $ubuntuMirrorUrl jammy-backports main restricted universe multiverse
deb $ubuntuMirrorUrl jammy-security main restricted universe multiverse
''';
}

View File

@@ -0,0 +1,14 @@
import 'dart:io';
import 'package:mason_logger/mason_logger.dart';
final done = lightGreen.wrap('Done');
final Logger _logger = Logger();
void writeMirrorIntoFile(String mirror, String path) {
final file = File(path);
final writting = lightYellow.wrap('Writting $path');
_logger.info(writting);
if (!file.existsSync()) file.createSync(recursive: true);
file.writeAsStringSync(mirror);
_logger.info(done);
}

View File

@@ -0,0 +1,8 @@
String yoyoSourcesListTemplate(String yoyoMirrorUrl) {
return '''
# Generate by yoyo-getfastmirror
# Author: Gtibhub/Riceneeder
deb [arch=amd64] $yoyoMirrorUrl kokomi main
''';
}

View File

@@ -0,0 +1 @@
const packageVersion = '0.0.1';

View File

@@ -0,0 +1 @@
library yoyo_get_fast_mirror;