exec method
Run command.
The contents of katana.yaml
and the arguments of the command are passed to context
.
コマンドを実行します。
context
にkatana.yaml
の内容やコマンドの引数が渡されます。
Implementation
@override
Future<void> exec(ExecContext context) async {
final com = context.args.get(2, "");
if (com == "init") {
label("Add initial information in `katana.yaml`.");
if (!context.yaml.containsKey("app")) {
context.yaml["app"] = {};
}
final app = context.yaml.getAsMap("app");
if (!app.containsKey("keystore")) {
app["keystore"] = {};
}
final keystore = app.getAsMap("keystore");
keystore["alias"] = "";
keystore["name"] = "";
keystore["organization"] = "";
keystore["state"] = "Tokyo";
keystore["country"] = "Japan";
await context.save();
return;
}
final bin = context.yaml.getAsMap("bin");
final keytool = bin.get("keytool", "keytool");
final openssl = bin.get("openssl", "openssl");
final app = context.yaml.getAsMap("app");
if (app.isEmpty) {
error("The item [app] is missing. Please add an item.");
return;
}
final keystore = app.getAsMap("keystore");
if (keystore.isEmpty) {
error("The item [app]->[keystore] is missing. Please add an item.");
return;
}
final alias = keystore.get("alias", "");
if (alias.isEmpty) {
error(
"The item [app]->[keystore]->[alias] is missing. Please describe the alias of the keystore.",
);
return;
}
final name = keystore.get("name", "");
if (name.isEmpty) {
error(
"The item [app]->[keystore]->[name] is missing. Describe the common name of the keytool.",
);
return;
}
final organization = keystore.get("organization", "");
if (organization.isEmpty) {
error(
"The item [app]->[keystore]->[organization] is missing. Describe the organization of the keytool.",
);
return;
}
final state = keystore.get("state", "");
if (state.isEmpty) {
error(
"The item [app]->[keystore]->[state] is missing. Describe the state of the keytool.",
);
return;
}
final country = keystore.get("country", "");
if (country.isEmpty) {
error(
"The item [app]->[keystore]->[country] is missing. Describe the country of the keytool.",
);
return;
}
label("Create a password.");
final passwordFile = File("android/app/appkey_password.key");
if (!passwordFile.existsSync()) {
final password = generateCode(16);
passwordFile.writeAsStringSync(password);
}
final password = passwordFile.readAsStringSync();
label("Create a keystore.");
final appKey = File("android/app/appkey.keystore");
if (!appKey.existsSync()) {
await command(
"Create appkey.keystore",
[
keytool,
"-genkey",
"-v",
"-keystore",
"android/app/appkey.keystore",
"-keyalg",
"RSA",
"-storepass",
password,
"-alias",
alias,
"-validity",
"10950",
"-dname",
"CN=$name, O=$organization, S=$state, C=$country",
],
);
}
label("Convert the keystore to a p12 file.");
final p12 = File("android/app/appkey.p12");
if (!p12.existsSync()) {
await command(
"Create appkey.p12",
[
keytool,
"-v",
"-importkeystore",
"-srckeystore",
"android/app/appkey.keystore",
"-srcalias",
alias,
"-srcstorepass",
password,
"-srckeypass",
password,
"-destkeystore",
"android/app/appkey.p12",
"-deststoretype",
"PKCS12",
"-storepass",
password,
],
);
}
label("Store keystore information in `key.properties`.");
final properties = File("android/key.properties");
if (properties.existsSync()) {
final contents = await properties.readAsLines();
if (!contents.any((e) => e.startsWith("storePassword"))) {
contents.add("storePassword=$password");
}
if (!contents.any((e) => e.startsWith("keyPassword"))) {
contents.add("keyPassword=$password");
}
if (!contents.any((e) => e.startsWith("keyAlias"))) {
contents.add("keyAlias=$alias");
}
if (!contents.any((e) => e.startsWith("storeFile"))) {
contents.add("storeFile=appkey.keystore");
}
await properties.writeAsString(contents.join("\n"));
} else {
await properties.writeAsString(
"storePassword=$password\nkeyPassword=$password\nkeyAlias=$alias\nstoreFile=appkey.keystore",
);
}
label("Add processing to the Gradle file.");
final gradle = AppGradle();
await gradle.load();
if (!gradle.loadProperties.any((e) => e.name == "keyProperties")) {
gradle.loadProperties.add(
GradleLoadProperties(
path: "key.properties",
name: "keyProperties",
file: "keyPropertiesFile",
),
);
}
gradle.android?.buildTypes = GradleAndroidBuildTypes(
release: GradleAndroidBuildType(signingConfig: "signingConfigs.release"),
debug: GradleAndroidBuildType(signingConfig: "signingConfigs.debug"),
);
gradle.android?.signingConfigs = GradleAndroidSigningConfigs(
release: GradleAndroidSigningConfig(
keyAlias: "keyProperties['keyAlias']",
keyPassword: "keyProperties['keyPassword']",
storeFile: "file(keyProperties['storeFile'])",
storePassword: "keyProperties['storePassword']",
),
debug: GradleAndroidSigningConfig(
keyAlias: "keyProperties['keyAlias']",
keyPassword: "keyProperties['keyPassword']",
storeFile: "file(keyProperties['storeFile'])",
storePassword: "keyProperties['storePassword']",
),
);
await gradle.save();
label("Save the fingerprint information.");
final fingerPrintFile = File("android/app/appkey_fingerprint.txt");
if (!fingerPrintFile.existsSync()) {
final fingerPrint = await command(
"Create appkey_fingerprint.txt",
[
keytool,
"-list",
"-v",
"-keystore",
"android/app/appkey.keystore",
"-alias",
alias,
"-storepass",
password,
"-keypass",
password,
],
);
await fingerPrintFile.writeAsString(fingerPrint);
}
label("Save the keyhash information.");
final keyHashFile = File("android/app/appkey_keyhash.txt");
if (!keyHashFile.existsSync()) {
// ignore: avoid_print
print("\r\n#### Create appkey_keyhash.txt");
var keyHash = "";
final keytoolResult = await Process.start(keytool, [
"-exportcert",
"-v",
"-keystore",
"android/app/appkey.keystore",
"-alias",
alias,
"-storepass",
password,
]);
final openSslSha1Restul = await Process.start(openssl, [
"sha1",
"-binary",
]);
keytoolResult.stdout.pipe(openSslSha1Restul.stdin);
final openSslBase64Result = await Process.start(openssl, ["base64"]);
openSslSha1Restul.stdout.pipe(openSslBase64Result.stdin);
openSslBase64Result.stdout.transform(utf8.decoder).forEach((e) {
keyHash += e;
// ignore: avoid_print
print(e);
});
await openSslBase64Result.exitCode;
await keyHashFile.writeAsString(keyHash);
}
label("Rewrite `.gitignore`.");
final gitignore = File("android/.gitignore");
if (!gitignore.existsSync()) {
error("Cannot find `android/.gitignore`. Project is broken.");
return;
}
final gitignores = await gitignore.readAsLines();
if (context.yaml.getAsMap("git").get("ignore_secure_file", true)) {
if (!gitignores.any((e) => e.startsWith("key.properties"))) {
gitignores.add("key.properties");
}
if (!gitignores.any((e) => e.startsWith("**/*.keystore"))) {
gitignores.add("**/*.keystore");
}
if (!gitignores.any((e) => e.startsWith("**/*.jks"))) {
gitignores.add("**/*.jks");
}
if (!gitignores.any((e) => e.startsWith("**/*.p12"))) {
gitignores.add("**/*.p12");
}
if (!gitignores.any((e) => e.startsWith("*.json"))) {
gitignores.add("*.json");
}
if (!gitignores.any((e) => e.startsWith("**/appkey_fingerprint.txt"))) {
gitignores.add("**/appkey_fingerprint.txt");
}
if (!gitignores.any((e) => e.startsWith("**/appkey_password.key"))) {
gitignores.add("**/appkey_password.key");
}
} else {
gitignores.removeWhere((e) => e.startsWith("**/*.p12"));
gitignores.removeWhere((e) => e.startsWith("*.json"));
gitignores.removeWhere((e) => e.startsWith("**/appkey_fingerprint.txt"));
gitignores.removeWhere((e) => e.startsWith("**/appkey_password.key"));
gitignores.removeWhere((e) => e.startsWith("key.properties"));
gitignores.removeWhere((e) => e.startsWith("**/*.keystore"));
gitignores.removeWhere((e) => e.startsWith("**/*.jks"));
}
await gitignore.writeAsString(gitignores.join("\n"));
}